diff -u --recursive --new-file v2.3.99-pre8/linux/CREDITS linux/CREDITS
--- v2.3.99-pre8/linux/CREDITS	Wed Apr 26 16:34:06 2000
+++ linux/CREDITS	Sat May 20 11:39:56 2000
@@ -251,6 +251,14 @@
 S: 6369 BG Simpelveld
 S: The Netherlands
 
+N: Peter Berger
+E: pberger@brimson.com
+W: http://www.brimson.com
+D: Author/maintainer of Digi AccelePort USB driver
+S: 1549 Hiironen Rd.
+S: Brimson, MN  55602
+S: USA
+
 N: Hennus Bergman
 E: hennus@cybercomm.nl
 W: http://www.cybercomm.nl/~hennus/
@@ -318,6 +326,13 @@
 D: IEEE 1394 subsystem rewrite and maintainer
 D: Texas Instruments PCILynx IEEE 1394 driver
 
+N: Al Borchers
+E: alborchers@steinerpoint.com
+D: Author/maintainer of Digi AccelePort USB driver
+S: 4912 Zenith Ave. S.
+S: Minneapolis, MN  55410
+S: USA
+
 N: Marc Boucher
 E: marc@mbsi.ca
 P: CA 67 A5 1A 38 CE B6 F2  D5 83 51 03 D2 9C 30 9E  CE D2 DD 65
@@ -942,14 +957,20 @@
 
 N: Andre Hedrick
 E: andre@linux-ide.org
+E: ahedrick@atipa.com
 E: andre@suse.com
+W: http://www.linux-ide.org/
 D: Random SMP kernel hacker...
 D: Uniform Multi-Platform E-IDE driver
 D: Active-ATA-Chipset maddness..........
 D: Ultra DMA 66/33
 D: ATA-Smart Kernel Daemon
-S: 580 Second Street, Suite 2
-S: Oakland, CA
+S: Linux ATA Development (LAD)
+S: Concord, CA
+S: Atipa Linux Solutions
+S: 6000 Connecticut  Kansas City, MO  64120
+S: SuSE Linux, Inc.
+S: 580 Second Street, Suite 210  Oakland, CA  94607
 S: USA
 
 N: Jochen Hein
@@ -1607,12 +1628,30 @@
 D: XF86_8514
 D: cfdisk (curses based disk partitioning program)
 
+N: Claudio S. Matsuoka
+E: claudio@conectiva.com
+E: claudio@helllabs.org
+W: http://helllabs.org/~claudio
+D: OV511 driver hacks
+S: Conectiva S.A.
+S: R. Tocantins 89
+S: 80050-430  Curitiba PR
+S: Brazil
+
 N: Heinz Mauelshagen
 E: mge@EZ-Darmstadt.Telekom.de
 D: Logical Volume Manager
 S: Bartningstr. 12
 S: 64289 Darmstadt
 S: Germany 
+
+N: Mark W. McClelland
+E: mmcclelland@delphi.com
+E: mark@alpha.dyndns.org
+W: http://alpha.dyndns.org/ov511/
+D: OV511 driver
+S: (address available on request)
+S: USA
 
 N: Mike McLagan
 E: mike.mclagan@linux.org
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.3.99-pre8/linux/Documentation/Configure.help	Fri May 12 14:18:55 2000
+++ linux/Documentation/Configure.help	Tue May 23 08:22:22 2000
@@ -1496,7 +1496,7 @@
 
   If unsure, say Y.
 
-DANGEROUS! RAID-1/RAID-5 code
+RAID-1/RAID-5 code (DANGEROUS)
 CONFIG_RAID15_DANGEROUS
   This new RAID1/RAID5 code has been freshly merged, and has not seen
   enough testing yet. While there are no known bugs in it, it might
@@ -9779,6 +9779,12 @@
 CONFIG_USB_SERIAL_OMNINET
   Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
 
+USB Digi International AccelePort USB Serial Driver
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT
+  Say Y here if you want to use a Digi AccelePort USB 4 device,
+  a 4 port USB serial converter.  The Digi Acceleport USB 2 and
+  8 are not yet supported by this driver.
+
 USB Printer support
 CONFIG_USB_PRINTER
   Say Y here if you want to connect a USB printer to your computer's
@@ -10430,7 +10436,7 @@
 Provide NFSv3 server support
 CONFIG_NFSD_V3
   If you would like to include the NFSv3 server as well as the NFSv2
-  server, say Y here.  In unsure, say Y.
+  server, say Y here.  If unsure, say Y.
 
 OS/2 HPFS file system support
 CONFIG_HPFS_FS
@@ -12461,14 +12467,6 @@
   option doesn't work for all laptops -- it might not turn off your
   backlight at all, or it might print a lot of errors to the console,
   especially if you are using gpm.
-
-Ignore multiple suspend/standby events
-CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-  This option is necessary on the IBM Thinkpad 560, but should work on
-  all other laptops. When the APM BIOS returns multiple suspend or
-  standby events while one is already being processed they will be
-  ignored. Without this the Thinkpad 560 has troubles with the user
-  level daemon apmd, and with the PCMCIA package pcmcia-cs.
 
 Ignore multiple suspend/resume cycles
 CONFIG_APM_IGNORE_SUSPEND_BOUNCE
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.3.99-pre8/linux/Documentation/DocBook/Makefile	Wed Apr 26 16:34:06 2000
+++ linux/Documentation/DocBook/Makefile	Sun May 21 20:18:07 2000
@@ -1,4 +1,4 @@
-BOOKS	:= wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml
+BOOKS	:= wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml kernel-api.sgml parportbook.sgml kernel-hacking.sgml kernel-locking.sgml
 
 PS	:=	$(patsubst %.sgml, %.ps, $(BOOKS))
 PDF	:=	$(patsubst %.sgml, %.pdf, $(BOOKS))
@@ -18,6 +18,9 @@
 	 (echo "*** You need to install DocBook stylesheets ***"; \
 	  exit 1)
 
+%.eps: %.fig
+	-fig2dev -Leps $< $@
+
 $(TOPDIR)/scripts/docproc:
 	$(MAKE) -C $(TOPDIR)/scripts docproc
 
@@ -51,6 +54,7 @@
 		$(TOPDIR)/drivers/sound/sound_firmware.c \
 		$(TOPDIR)/drivers/net/wan/syncppp.c \
 		$(TOPDIR)/drivers/net/wan/z85230.c \
+		$(TOPDIR)/fs/devfs/base.c \
 		$(TOPDIR)/kernel/pm.c \
 		$(TOPDIR)/kernel/ksyms.c \
 		$(TOPDIR)/net/netsyms.c \
@@ -66,12 +70,15 @@
 LOG	:=	$(patsubst %.sgml, %.log, $(BOOKS))
 
 clean:
-	$(RM) core *~
-	$(RM) $(BOOKS)
-	$(RM) $(DVI) $(AUX) $(TEX) $(LOG)
+	-$(RM) core *~
+	-$(RM) $(BOOKS)
+	-$(RM) $(DVI) $(AUX) $(TEX) $(LOG)
+	-$(RM) parport-share.eps parport-multi.eps parport-structure.eps
 
 mrproper: clean
-	$(RM) $(PS) $(PDF)
+	-$(RM) $(PS) $(PDF)
+
+parportbook.ps: parport-share.eps parport-multi.eps parport-structure.eps
 
 %.ps : %.sgml db2ps
 	db2ps $<
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/kernel-api.tmpl linux/Documentation/DocBook/kernel-api.tmpl
--- v2.3.99-pre8/linux/Documentation/DocBook/kernel-api.tmpl	Tue Apr 11 15:09:11 2000
+++ linux/Documentation/DocBook/kernel-api.tmpl	Sat May 13 08:11:27 2000
@@ -101,6 +101,11 @@
      </sect1>
   </chapter>
 
+  <chapter id="devfs">
+     <title>The Device File System</title>
+!Efs/devfs/base.c
+  </chapter>
+
   <chapter id="pmfuncs">
      <title>Power Management</title>
 !Ekernel/pm.c
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl
--- v2.3.99-pre8/linux/Documentation/DocBook/kernel-hacking.tmpl	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/kernel-hacking.tmpl	Sun May 21 20:18:07 2000
@@ -0,0 +1,1316 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+
+<book id="lk-hacking-guide">
+ <bookinfo>
+  <title>Unreliable Guide To Hacking The Linux Kernel</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Paul</firstname>
+    <othername>Rusty</othername>
+    <surname>Russell</surname>
+    <affiliation>
+     <address>
+      <email>rusty@linuxcare.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2000</year>
+   <holder>Paul Russell</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+    This documentation is free software; you can redistribute
+    it and/or modify it under the terms of the GNU General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later
+    version.
+   </para>
+   
+   <para>
+    This program is distributed in the hope that it will be
+    useful, but WITHOUT ANY WARRANTY; without even the implied
+    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    See the GNU General Public License for more details.
+   </para>
+   
+   <para>
+    You should have received a copy of the GNU General Public
+    License along with this program; if not, write to the Free
+    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+    MA 02111-1307 USA
+   </para>
+   
+   <para>
+    For more details see the file COPYING in the source
+    distribution of Linux.
+   </para>
+  </legalnotice>
+
+  <releaseinfo>
+   This is the first release of this document as part of the kernel tarball.
+  </releaseinfo>
+
+ </bookinfo>
+
+ <toc></toc>
+
+ <chapter id="introduction">
+  <title>Introduction</title>
+  <para>
+   Welcome, gentle reader, to Rusty's Unreliable Guide to Linux
+   Kernel Hacking.  This document describes the common routines and
+   general requirements for kernel code: its goal is to serve as a
+   primer for Linux kernel development for experienced C
+   programmers.  I avoid implementation details: that's what the
+   code is for, and I ignore whole tracts of useful routines.
+  </para>
+  <para>
+   Before you read this, please understand that I never wanted to
+   write this document, being grossly under-qualified, but I always
+   wanted to read it, and this was the only way.  I hope it will
+   grow into a compendium of best practice, common starting points
+   and random information.
+  </para>
+ </chapter>
+
+ <chapter id="basic-players">
+  <title>The Players</title>
+
+  <para>
+   At any time each of the CPUs in a system can be:
+  </para>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+     not associated with any process, serving a hardware interrupt;
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     not associated with any process, serving a softirq, tasklet or bh;
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     running in kernel space, associated with a process;
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     running a process in user space.
+    </para>
+   </listitem>
+  </itemizedlist>
+
+  <para>
+   There is a strict ordering between these: other than the last
+   category (userspace) each can only be pre-empted by those above.
+   For example, while a softirq is running on a CPU, no other
+   softirq will pre-empt it, but a hardware interrupt can.  However,
+   any other CPUs in the system execute independently.
+  </para>
+
+  <para>
+   We'll see a number of ways that the user context can block
+   interrupts, to become truly non-preemptable.
+  </para>
+  
+  <sect1 id="basics-usercontext">
+   <title>User Context</title>
+
+   <para>
+    User context is when you are coming in from a system call or
+    other trap: you can sleep, and you own the CPU (except for
+    interrupts) until you call <function>schedule()</function>.  
+    In other words, user context (unlike userspace) is not pre-emptable.
+   </para>
+
+   <note>
+    <para>
+     You are always in user context on module load and unload,
+     and on operations on the block device layer.
+    </para>
+   </note>
+
+   <para>
+    In user context, the <varname>current</varname> pointer (indicating 
+    the task we are currently executing) is valid, and
+    <function>in_interrupt()</function>
+    (<filename>include/asm/hardirq.h</filename>) is <returnvalue>false
+    </returnvalue>.  
+   </para>
+
+   <caution>
+    <para>
+     Beware that if you have interrupts or bottom halves disabled 
+     (see below), <function>in_interrupt()</function> will return a 
+     false positive.
+    </para>
+   </caution>
+  </sect1>
+
+  <sect1 id="basics-hardirqs">
+   <title>Hardware Interrupts (Hard IRQs)</title>
+
+   <para>
+    Timer ticks, <hardware>network cards</hardware> and 
+    <hardware>keyboard</hardware> are examples of real
+    hardware which produce interrupts at any time.  The kernel runs
+    interrupt handlers, which services the hardware.  The kernel
+    guarantees that this handler is never re-entered: if another
+    interrupt arrives, it is queued (or dropped).  Because it
+    disables interrupts, this handler has to be fast: frequently it
+    simply acknowledges the interrupt, marks a `software interrupt'
+    for execution and exits.
+   </para>
+
+   <para>
+    You can tell you are in a hardware interrupt, because 
+    <function>in_irq()</function> returns <returnvalue>true</returnvalue>.  
+   </para>
+   <caution>
+    <para>
+     Beware that this will return a false positive if interrupts are disabled 
+     (see below).
+    </para>
+   </caution>
+  </sect1>
+
+  <sect1 id="basics-softirqs">
+   <title>Software Interrupt Context: Bottom Halves, Tasklets, softirqs</title>
+
+   <para>
+    Whenever a system call is about to return to userspace, or a
+    hardware interrupt handler exits, any `software interrupts'
+    which are marked pending (usually by hardware interrupts) are
+    run (<filename>kernel/softirq.c</filename>).
+   </para>
+
+   <para>
+    Much of the real interrupt handling work is done here.  Early in
+    the transition to <acronym>SMP</acronym>, there were only `bottom 
+    halves' (BHs), which didn't take advantage of multiple CPUs.  Shortly 
+    after we switched from wind-up computers made of match-sticks and snot,
+    we abandoned this limitation.
+   </para>
+
+   <para>
+    <filename class=headerfile>include/linux/interrupt.h</filename> lists the 
+    different BH's.  No matter how many CPUs you have, no two BHs will run at 
+    the same time. This made the transition to SMP simpler, but sucks hard for
+    scalable performance.  A very important bottom half is the timer
+    BH (<filename class=headerfile>include/linux/timer.h</filename>): you 
+    can register to have it call functions for you in a given length of time.
+   </para>
+
+   <para>
+    2.3.43 introduced softirqs, and re-implemented the (now
+    deprecated) BHs underneath them.  Softirqs are fully-SMP
+    versions of BHs: they can run on as many CPUs at once as
+    required.  This means they need to deal with any races in shared
+    data using their own locks.  A bitmask is used to keep track of
+    which are enabled, so the 32 available softirqs should not be
+    used up lightly.  (<emphasis>Yes</emphasis>, people will
+    notice).
+   </para>
+
+   <para>
+    tasklets (<filename class=headerfile>include/linux/interrupt.h</filename>) 
+    are like softirqs, except they are dynamically-registrable (meaning you 
+    can have as many as you want), and they also guarantee that any tasklet 
+    will only run on one CPU at any time, although different tasklets can 
+    run simultaneously (unlike different BHs).  
+   </para>
+   <caution>
+    <para>
+     The name `tasklet' is misleading: they have nothing to do with `tasks', 
+     and probably more to do with some bad vodka Alexey Kuznetsov had at the 
+     time.
+    </para>
+   </caution>
+
+   <para>
+    You can tell you are in a softirq (or bottom half, or tasklet)
+    using the <function>in_softirq()</function> macro 
+    (<filename class=headerfile>include/asm/softirq.h</filename>).  
+   </para>
+   <caution>
+    <para>
+     Beware that this will return a false positive if a bh lock (see below)
+     is held.
+    </para>
+   </caution>
+  </sect1>
+ </chapter>
+
+ <chapter id="basic-rules">
+  <title>Some Basic Rules</title>
+
+  <variablelist>
+   <varlistentry>
+    <term>No memory protection</term>
+    <listitem>
+     <para>
+      If you corrupt memory, whether in user context or
+      interrupt context, the whole machine will crash.  Are you
+      sure you can't do what you want in userspace?
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>No floating point or <acronym>MMX</acronym></term>
+    <listitem>
+     <para>
+      The <acronym>FPU</acronym> context is not saved; even in user
+      context the <acronym>FPU</acronym> state probably won't
+      correspond with the current process: you would mess with some
+      user process' <acronym>FPU</acronym> state.  If you really want
+      to do this, you would have to explicitly save/restore the full
+      <acronym>FPU</acronym> state (and avoid context switches).  It
+      is generally a bad idea; use fixed point arithmetic first.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>A rigid stack limit</term>
+    <listitem>
+     <para>
+      The kernel stack is about 6K in 2.2 (for most
+      architectures: it's about 14K on the Alpha), and shared
+      with interrupts so you can't use it all.  Avoid deep
+      recursion and huge local arrays on the stack (allocate
+      them dynamically instead).
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term>The Linux kernel is portable</term>
+    <listitem>
+     <para>
+      Let's keep it that way.  Your code should be 64-bit clean,
+      and endian-independent.  You should also minimize CPU
+      specific stuff, e.g. inline assembly should be cleanly
+      encapsulated and minimized to ease porting.  Generally it
+      should be restricted to the architecture-dependent part of
+      the kernel tree.
+     </para>
+    </listitem>
+   </varlistentry>
+  </variablelist>
+ </chapter>
+
+ <chapter id="ioctls">
+  <title>ioctls: Not writing a new system call</title>
+
+  <para>
+   A system call generally looks like this
+  </para>
+
+  <programlisting>
+asmlinkage int sys_mycall(int arg) 
+{
+        return 0; 
+}
+  </programlisting>
+
+  <para>
+   First, in most cases you don't want to create a new system call.
+   You create a character device and implement an appropriate ioctl
+   for it.  This is much more flexible than system calls, doesn't have
+   to be entered in every architecture's
+   <filename class=headerfile>include/asm/unistd.h</filename> and
+   <filename>arch/kernel/entry.S</filename> file, and is much more
+   likely to be accepted by Linus.
+  </para>
+
+  <para>
+   Inside the ioctl you're in user context to a process.  When a
+   error occurs you return a negated errno (see
+   <filename class=headerfile>include/linux/errno.h</filename>),
+   otherwise you return <returnvalue>0</returnvalue>.
+  </para>
+
+  <para>
+   After you slept you should check if a signal occurred: the
+   Unix/Linux way of handling signals is to temporarily exit the
+   system call with the <constant>-ERESTARTSYS</constant> error.  The
+   system call entry code will switch back to user context, process
+   the signal handler and then your system call will be restarted
+   (unless the user disabled that).  So you should be prepared to
+   process the restart, e.g. if you're in the middle of manipulating
+   some data structure.
+  </para>
+
+  <programlisting>
+if (signal_pending()) 
+        return -ERESTARTSYS;
+  </programlisting>
+
+  <para>
+   If you're doing longer computations: first think userspace. If you
+   <emphasis>really</emphasis> want to do it in kernel you should
+   regularly check if you need to give up the CPU (remember there is
+   cooperative multitasking per CPU).  Idiom:
+  </para>
+
+  <programlisting>
+if (current-&gt;need_resched)
+        schedule(); /* Will sleep */ 
+  </programlisting>
+
+  <para>
+   A short note on interface design: the UNIX system call motto is
+   "Provide mechanism not policy".
+  </para>
+ </chapter>
+
+ <chapter id="deadlock-recipes">
+  <title>Recipes for Deadlock</title>
+
+  <para>
+   You cannot call any routines which may sleep, unless:
+  </para>
+  <itemizedlist>
+   <listitem>
+    <para>
+     You are in user context.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     You do not own any spinlocks.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     You have interrupts enabled (actually, Andi Kleen says
+     that the scheduling code will enable them for you, but
+     that's probably not what you wanted).
+    </para>
+   </listitem>
+  </itemizedlist>
+
+  <para>
+   Note that some functions may sleep implicitly: common ones are
+   the user space access functions (*_user) and memory allocation
+   functions without GFP_ATOMIC.
+  </para>
+
+  <para>
+   You will eventually lock up your box if you break these rules.  
+  </para>
+
+  <para>
+   Really.
+  </para>
+ </chapter>
+
+ <chapter id="common-routines">
+  <title>Common Routines</title>
+
+  <sect1 id="routines-printk">
+   <title>
+    <function>printk()</function>
+    <filename class=headerfile>include/linux/kernel.h</filename>
+   </title>
+
+   <para>
+    <function>printk()</function> feeds kernel messages to the
+    console, dmesg, and the syslog daemon.  It is useful for debugging
+    and reporting errors, and can be used inside interrupt context,
+    but use with caution: a machine which has its console flooded with
+    printk messages is unusable.  It uses a format string mostly
+    compatible with ANSI C printf, and C string concatenation to give
+    it a first "priority" argument:
+   </para>
+
+   <programlisting>
+printk(KERN_INFO "i = %u\n", i);
+   </programlisting>
+
+   <para>
+    See <filename class=headerfile>include/linux/kernel.h</filename>;
+    for other KERN_ values; these are interpreted by syslog as the
+    level.  Special case: for printing an IP address use
+   </para>
+
+   <programlisting>
+__u32 ipaddress;
+printk(KERN_INFO "my ip: %d.%d.%d.%d\n", NIPQUAD(ipaddress));
+   </programlisting>
+
+   <para>
+    <function>printk()</function> internally uses a 1K buffer and does
+    not catch overruns.  Make sure that will be enough.
+   </para>
+
+   <note>
+    <para>
+     You will know when you are a real kernel hacker
+     when you start typoing printf as printk in your user programs :)
+    </para>
+   </note>
+
+   <!--- From the Lions book reader department --> 
+
+   <note>
+    <para>
+     Another sidenote: the original Unix Version 6 sources had a
+     comment on top of its printf function: "Printf should not be
+     used for chit-chat".  You should follow that advice.
+    </para>
+   </note>
+  </sect1>
+
+  <sect1 id="routines-copy">
+   <title>
+    <function>copy_[to/from]_user()</function>
+    /
+    <function>get_user()</function>
+    /
+    <function>put_user()</function>
+    <filename class=headerfile>include/asm/uaccess.h</filename>
+   </title>  
+
+   <para>
+    <emphasis>[SLEEPS]</emphasis>
+   </para>
+
+   <para>
+    <function>put_user()</function> and <function>get_user()</function>
+    are used to get and put single values (such as an int, char, or
+    long) from and to userspace.  A pointer into userspace should
+    never be simply dereferenced: data should be copied using these
+    routines.  Both return <constant>-EFAULT</constant> or 0.
+   </para>
+   <para>
+    <function>copy_to_user()</function> and
+    <function>copy_from_user()</function> are more general: they copy
+    an arbitrary amount of data to and from userspace.
+    <caution>
+     <para>
+      Unlike <function>put_user()</function> and
+      <function>get_user()</function>, they return the amount of
+      uncopied data (ie. <returnvalue>0</returnvalue> still means
+      success).
+     </para>
+    </caution>
+    [Yes, this moronic interface makes me cringe.  Please submit a
+    patch and become my hero --RR.]
+   </para>
+   <para>
+    The functions may sleep implicitly. This should never be called
+    outside user context (it makes no sense), with interrupts
+    disabled, or a spinlock held.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-kmalloc">
+   <title><function>kmalloc()</function>/<function>kfree()</function>
+    <filename class=headerfile>include/linux/slab.h</filename></title>
+
+   <para>
+    <emphasis>[MAY SLEEP: SEE BELOW]</emphasis>
+   </para>
+
+   <para>
+    These routines are used to dynamically request pointer-aligned
+    chunks of memory, like malloc and free do in userspace, but
+    <function>kmalloc()</function> takes an extra flag word.
+    Important values:
+   </para>
+
+   <variablelist>
+    <varlistentry>
+     <term>
+      <constant>
+       GFP_KERNEL
+      </constant>
+     </term>
+     <listitem>
+      <para>
+       May sleep and swap to free memory. Only allowed in user
+       context, but is the most reliable way to allocate memory.
+      </para>
+     </listitem>
+    </varlistentry>
+    
+    <varlistentry>
+     <term>
+      <constant>
+       GFP_ATOMIC
+      </constant>
+     </term>
+     <listitem>
+      <para>
+       Don't sleep. Less reliable than <constant>GFP_KERNEL</constant>,
+       but may be called from interrupt context. You should
+       <emphasis>really</emphasis> have a good out-of-memory
+       error-handling strategy.
+      </para>
+     </listitem>
+    </varlistentry>
+    
+    <varlistentry>
+     <term>
+      <constant>
+       GFP_DMA
+      </constant>
+     </term>
+     <listitem>
+      <para>
+       Allocate ISA DMA lower than 16MB. If you don't know what that
+       is you don't need it.  Very unreliable.
+      </para>
+     </listitem>
+    </varlistentry>
+   </variablelist>
+
+   <para>
+    If you see a <errorname>kmem_grow: Called nonatomically from int
+    </errorname> warning message you called a memory allocation function
+    from interrupt context without <constant>GFP_ATOMIC</constant>.
+    You should really fix that.  Run, don't walk.
+   </para>
+
+   <para>
+    If you are allocating at least <constant>PAGE_SIZE</constant>
+    (<filename class=headerfile>include/asm/page.h</filename>) bytes,
+    consider using <function>__get_free_pages()</function>
+
+    (<filename class=headerfile>include/linux/mm.h</filename>).  It
+    takes an order argument (0 for page sized, 1 for double page, 2
+    for four pages etc.) and the same memory priority flag word as
+    above.
+   </para>
+
+   <para>
+    If you are allocating more than a page worth of bytes you can use
+    <function>vmalloc()</function>.  It'll allocate virtual memory in
+    the kernel map.  This block is not contiguous in physical memory,
+    but the <acronym>MMU</acronym> makes it look like it is for you
+    (so it'll only look contiguous to the CPUs, not to external device
+    drivers).  If you really need large physically contiguous memory
+    for some weird device, you have a problem: it is poorly supported
+    in Linux because after some time memory fragmentation in a running
+    kernel makes it hard.  The best way is to allocate the block early
+    in the boot process.
+   </para>
+
+   <para>
+    Before inventing your own cache of often-used objects consider
+    using a slab cache in
+    <filename class=headerfile>include/linux/slab.h</filename>
+   </para>
+  </sect1>
+
+  <sect1 id="routines-current">
+   <title><function>current</function>
+    <filename class=headerfile>include/asm/current.h</filename></title>
+
+   <para>
+    This global variable (really a macro) contains a pointer to
+    the current task structure, so is only valid in user context.
+    For example, when a process makes a system call, this will
+    point to the task structure of the calling process.  It is
+    <emphasis>not NULL</emphasis> in interrupt context.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-local-irqs">
+   <title><function>local_irq_save()</function>/<function>local_irq_restore()</function>
+    <filename class=headerfile>include/asm/system.h</filename>
+   </title>
+
+   <para>
+    These routines disable hard interrupts on the local CPU, and
+    restore them.  They are reentrant; saving the previous state in
+    their one <varname>unsigned long flags</varname> argument.  If you
+    know that interrupts are enabled, you can simply use
+    <function>local_irq_disable()</function> and
+    <function>local_irq_enable()</function>.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-softirqs">
+   <title><function>local_bh_disable()</function>/<function>local_bh_enable()</function>
+    <filename class=headerfile>include/asm/softirq.h</filename></title>
+
+   <para>
+    These routines disable soft interrupts on the local CPU, and
+    restore them.  They are reentrant; if soft interrupts were
+    disabled before, they will still be disabled after this pair
+    of functions has been called.  They prevent softirqs, tasklets
+    and bottom halves from running on the current CPU.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-processorids">
+   <title><function>smp_processor_id</function>()/<function>cpu_[number/logical]_map()</function>
+    <filename class=headerfile>include/asm/smp.h</filename></title>
+   
+   <para>
+    <function>smp_processor_id()</function> returns the current
+    processor number, between 0 and <symbol>NR_CPUS</symbol> (the
+    maximum number of CPUs supported by Linux, currently 32).  These
+    values are not necessarily continuous: to get a number between 0
+    and <function>smp_num_cpus()</function> (the number of actual
+    processors in this machine), the
+    <function>cpu_number_map()</function> function is used to map the
+    processor id to a logical number.
+    <function>cpu_logical_map()</function> does the reverse.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-init">
+   <title><type>__init</type>/<type>__exit</type>/<type>__initdata</type>
+    <filename class=headerfile>include/linux/init.h</filename></title>
+
+   <para>
+    After boot, the kernel frees up a special section; functions
+    marked with <type>__init</type> and data structures marked with
+    <type>__initdata</type> are dropped after boot is complete (within
+    modules this directive is currently ignored).  <type>__exit</type>
+    is used to declare a function which is only required on exit: the
+    function will be dropped if this file is not compiled as a module.
+    See the header file for use.
+   </para>
+
+  </sect1>
+
+  <sect1 id="routines-init-again">
+   <title><function>__initcall()</function>/<function>module_init()</function>
+    <filename class=headerfile>include/linux/init.h</filename></title>
+   <para>
+    Many parts of the kernel are well served as a module
+    (dynamically-loadable parts of the kernel).  Using the
+    <function>module_init()</function> and
+    <function>module_exit()</function> macros it is easy to write code
+    without #ifdefs which can operate both as a module or built into
+    the kernel.
+   </para>
+
+   <para>
+    The <function>module_init()</function> macro defines which
+    function is to be called at module insertion time (if the file is
+    compiled as a module), or at boot time: if the file is not
+    compiled as a module the <function>module_init()</function> macro
+    becomes equivalent to <function>__initcall()</function>, which
+    through linker magic ensures that the function is called on boot.
+   </para>
+
+   <para>
+    The function can return a negative error number to cause
+    module loading to fail (unfortunately, this has no effect if
+    the module is compiled into the kernel).  For modules, this is
+    called in user context, with interrupts enabled, and the
+    kernel lock held, so it can sleep.
+   </para>
+  </sect1>
+  
+  <sect1 id="routines-moduleexit">
+   <title> <function>module_exit()</function>
+    <filename class=headerfile>include/linux/init.h</filename> </title>
+
+   <para>
+    This macro defines the function to be called at module removal
+    time (or never, in the case of the file compiled into the
+    kernel).  It will only be called if the module usage count has
+    reached zero.  This function can also sleep, but cannot fail:
+    everything must be cleaned up by the time it returns.
+   </para>
+  </sect1>
+
+  <sect1 id="routines-module-use-counters">
+   <title> <function>MOD_INC_USE_COUNT</function>/<function>MOD_DEC_USE_COUNT</function>
+    <filename class=headerfile>include/linux/module.h</filename></title>
+
+   <para>
+    These manipulate the module usage count, to protect against
+    removal (a module also can't be removed if another module uses
+    one of its exported symbols: see below).  Every reference to
+    the module from user context should be reflected by this
+    counter (e.g. for every data structure or socket) before the
+    function sleeps.  To quote Tim Waugh:
+   </para>
+
+   <programlisting>
+/* THIS IS BAD */
+foo_open (...)
+{
+        stuff..
+        if (fail)
+                return -EBUSY;
+        sleep.. (might get unloaded here)
+        stuff..
+        MOD_INC_USE_COUNT;
+        return 0;
+}
+
+/* THIS IS GOOD /
+foo_open (...)
+{
+        MOD_INC_USE_COUNT;
+        stuff..
+        if (fail) {
+                MOD_DEC_USE_COUNT;
+                return -EBUSY;
+        }
+        sleep.. (safe now)
+        stuff..
+        return 0;
+}
+   </programlisting>
+  </sect1>
+ </chapter>
+
+ <chapter id="queues">
+  <title>Wait Queues
+   <filename class=headerfile>include/linux/wait.h</filename>
+  </title>
+  <para>
+   <emphasis>[SLEEPS]</emphasis>
+  </para>
+
+  <para>
+   A wait queue is used to wait for someone to wake you up when a
+   certain condition is true.  They must be used carefully to ensure
+   there is no race condition.  You declare a
+   <type>wait_queue_head_t</type>, and then processes which want to
+   wait for that condition declare a <type>wait_queue_t</type>
+   referring to themselves, and place that in the queue.
+  </para>
+
+  <sect1 id="queue-declaring">
+   <title>Declaring</title>
+   
+   <para>
+    You declare a <type>wait_queue_head_t</type> using the
+    <function>DECLARE_WAIT_QUEUE_HEAD()</function> macro, or using the
+    <function>init_waitqueue_head()</function> routine in your
+    initialization code.
+   </para>
+  </sect1>
+  
+  <sect1 id="queue-waitqueue">
+   <title>Queuing</title>
+   
+   <para>
+    Placing yourself in the waitqueue is fairly complex, because you
+    must put yourself in the queue before checking the condition.
+    There is a macro to do this:
+    <function>wait_event_interruptible()</function>
+
+    <filename class=headerfile>include/linux/sched.h</filename> The
+    first argument is the wait queue head, and the second is an
+    expression which is evaluated; the macro returns
+    <returnvalue>0</returnvalue> when this expression is true, or
+    <returnvalue>-ERESTARTSYS</returnvalue> if a signal is received.
+    The <function>wait_event()</function> version ignores signals.
+   </para>
+  </sect1>
+
+  <sect1 id="queue-waking">
+   <title>Waking Up Queued Tasks</title>
+   
+   <para>
+    Call <function>wake_up()</function>
+
+    <filename class=headerfile>include/linux/sched.h</filename>;,
+    which will wake up every process in the queue.  The exception is
+    if one has <constant>TASK_EXCLUSIVE</constant> set, in which case
+    the remainder of the queue will not be woken.
+   </para>
+  </sect1>
+ </chapter>
+
+ <chapter id="atomic-ops">
+  <title>Atomic Operations</title>
+
+  <para>
+   Certain operations are guaranteed atomic on all platforms.  The
+   first class of operations work on <type>atomic_t</type>
+
+   <filename class=headerfile>include/asm/atomic.h</filename>; this
+   contains a signed integer (at least 32 bits long), and you must use
+   these functions to manipulate or read atomic_t variables.
+   <function>atomic_read()</function> and
+   <function>atomic_set()</function> get and set the counter,
+   <function>atomic_add()</function>,
+   <function>atomic_sub()</function>,
+   <function>atomic_inc()</function>,
+   <function>atomic_dec()</function>, and
+   <function>atomic_dec_and_test()</function> (returns
+   <returnvalue>true</returnvalue> if it was decremented to zero).
+  </para>
+
+  <para>
+   Yes.  It returns <returnvalue>true</returnvalue> (i.e. != 0) if the
+   atomic variable is zero.
+  </para>
+
+  <para>
+   Note that these functions are slower than normal arithmetic, and
+   so should not be used unnecessarily.  On some platforms they
+   are much slower, like 32-bit Sparc where they use a spinlock.
+  </para>
+
+  <para>
+   The second class of atomic operations is atomic bit operations,
+   defined in
+
+   <filename class=headerfile>include/asm/bitops.h</filename>.  These
+   operations generally take a pointer to the bit pattern, and a bit
+   number: 0 is the least significant bit.
+   <function>set_bit()</function>, <function>clear_bit()</function>
+   and <function>change_bit()</function> set, clear, and flip the
+   given bit.  <function>test_and_set_bit()</function>,
+   <function>test_and_clear_bit()</function> and
+   <function>test_and_change_bit()</function> do the same thing,
+   except return true if the bit was previously set; these are
+   particularly useful for very simple locking.
+  </para>
+  
+  <para>
+   It is possible to call these operations with bit indices greater
+   than 31.  The resulting behavior is strange on big-endian
+   platforms though so it is a good idea not to do this.
+  </para>
+ </chapter>
+
+ <chapter id="symbols">
+  <title>Symbols</title>
+
+  <para>
+   Within the kernel proper, the normal linking rules apply
+   (ie. unless a symbol is declared to be file scope with the
+   <type>static</type> keyword, it can be used anywhere in the
+   kernel).  However, for modules, a special exported symbol table is
+   kept which limits the entry points to the kernel proper.  Modules
+   can also export symbols.
+  </para>
+
+  <sect1 id="sym-exportsymbols">
+   <title><function>EXPORT_SYMBOL()</function>
+    <filename class=headerfile>include/linux/module.h</filename></title>
+
+   <para>
+    This is the classic method of exporting a symbol, and it works
+    for both modules and non-modules.  In the kernel all these
+    declarations are often bundled into a single file to help
+    genksyms (which searches source files for these declarations).
+    See the comment on genksyms and Makefiles below.
+   </para>
+  </sect1>
+
+  <sect1 id="sym-exportsymtab">
+   <title><function>EXPORT_SYMTAB</function></title>
+
+   <para>
+    For convenience, a module usually exports all non-file-scope
+    symbols (ie. all those not declared <type>static</type>).  If this
+    is defined before
+
+    <filename class=headerfile>include/linux/module.h</filename> is
+    included, then only symbols explicit exported with
+    <function>EXPORT_SYMBOL()</function> will be exported.
+   </para>
+  </sect1>
+ </chapter>
+
+ <chapter id="conventions">
+  <title>Routines and Conventions</title>
+
+  <sect1 id="conventions-doublelinkedlist">
+   <title>Double-linked lists
+    <filename class=headerfile>include/linux/list.h</filename></title>
+
+   <para>
+    There are three sets of linked-list routines in the kernel
+    headers, but this one seems to be winning out (and Linus has
+    used it).  If you don't have some particular pressing need for
+    a single list, it's a good choice.  In fact, I don't care
+    whether it's a good choice or not, just use it so we can get
+    rid of the others.
+   </para>
+  </sect1>
+
+  <sect1 id="convention-returns">
+   <title>Return Conventions</title>
+
+   <para>
+    For code called in user context, it's very common to defy C
+    convention, and return <returnvalue>0</returnvalue> for success,
+    and a negative error number
+    (eg. <returnvalue>-EFAULT</returnvalue>) for failure.  This can be
+    unintuitive at first, but it's fairly widespread in the networking
+    code, for example.
+   </para>
+
+   <para>
+    The filesystem code uses <function>ERR_PTR()</function>
+
+    <filename class=headerfile>include/linux/fs.h</filename>; to
+    encode a negative error number into a pointer, and
+    <function>IS_ERR()</function> and <function>PTR_ERR()</function>
+    to get it back out again: avoids a separate pointer parameter for
+    the error number.  Icky, but in a good way.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-borkedcompile">
+   <title>Breaking Compilation</title>
+
+   <para>
+    Linus and the other developers sometimes change function or
+    structure names in development kernels; this is not done just to
+    keep everyone on their toes: it reflects a fundamental change
+    (eg. can no longer be called with interrupts on, or does extra
+    checks, or doesn't do checks which were caught before).  Usually
+    this is accompanied by a fairly complete note to the linux-kernel
+    mailing list; search the archive.  Simply doing a global replace
+    on the file usually makes things <emphasis>worse</emphasis>.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-initialising">
+   <title>Initializing structure members</title>
+
+   <para>
+    The preferred method of initializing structures is to use the
+    gcc Labeled Elements extension, eg:
+   </para>
+   <programlisting>
+static struct block_device_operations opt_fops = {
+        open:                   opt_open,
+        release:                opt_release,
+        ioctl:                  opt_ioctl,
+        check_media_change:     opt_media_change,
+};
+   </programlisting>
+
+   <para>
+    This makes it easy to grep for, and makes it clear which
+    structure fields are set.  You should do this because it looks
+    cool.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-gnu-extns">
+   <title>GNU Extensions</title>
+
+   <para>
+    GNU Extensions are explicitly allowed in the Linux kernel.
+    Note that some of the more complex ones are not very well
+    supported, due to lack of general use, but the following are
+    considered standard (see the GCC info page section "C
+    Extensions" for more details - Yes, really the info page, the
+    man page is only a short summary of the stuff in info):
+   </para>
+   <itemizedlist>
+    <listitem>
+     <para>
+      Inline functions
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Statement expressions (ie. the ({ and }) constructs).
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Declaring attributes of a function / variable / type
+      (__attribute__)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Labeled elements
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      typeof
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Zero length arrays
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Macro varargs
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Arithmetic on void pointers
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Non-Constant initializers
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Assembler Instructions (not outside arch/ and include/asm/)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Function names as strings (__FUNCTION__)
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      __builtin_constant_p()
+     </para>
+    </listitem>
+   </itemizedlist>
+
+   <para>
+    Be wary when using long long in the kernel, the code gcc generates for
+    it is horrible and worse: division and multiplication does not work
+    on i386 because the GCC runtime functions for it are missing from
+    the kernel environment.
+   </para>
+
+    <!-- FIXME: add a note about ANSI aliasing cleanness -->
+  </sect1>
+
+  <sect1 id="conventions-cplusplus">
+   <title>C++</title>
+   
+   <para>
+    Using C++ in the kernel is usually a bad idea, because the
+    kernel does not provide the necessary runtime environment
+    and the include files are not tested for it.  It is still
+    possible, but not recommended.  If you really want to do
+    this, forget about exceptions at least.
+   </para>
+  </sect1>
+
+  <sect1 id="conventions-ifdef">
+   <title>&num;if</title>
+   
+   <para>
+    It is generally considered cleaner to use macros in header files
+    (or at the top of .c files) to abstract away functions rather than
+    using `#if' pre-processor statements throughout the source code.
+   </para>
+  </sect1>
+ </chapter>
+
+ <chapter id="submitting">
+  <title>Putting Your Stuff in the Kernel</title>
+
+  <para>
+   In order to get your stuff into shape for official inclusion, or
+   even to make a neat patch, there's administrative work to be
+   done:
+  </para>
+  <itemizedlist>
+   <listitem>
+    <para>
+     Figure out whose pond you've been pissing in.  Look at the top of
+     the source files, inside the <filename>MAINTAINERS</filename>
+     file, and last of all in the <filename>CREDITS</filename> file.
+     You should coordinate with this person to make sure you're not
+     duplicating effort, or trying something that's already been
+     rejected.
+    </para>
+
+    <para>
+     Make sure you put your name and EMail address at the top of
+     any files you create or mangle significantly.  This is the
+     first place people will look when they find a bug, or when
+     <emphasis>they</emphasis> want to make a change.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Usually you want a configuration option for your kernel hack.
+     Edit <filename>Config.in</filename> in the appropriate directory
+     (but under <filename>arch/</filename> it's called
+     <filename>config.in</filename>).  The Config Language used is not
+     bash, even though it looks like bash; the safe way is to use only
+     the constructs that you already see in
+     <filename>Config.in</filename> files (see
+     <filename>Documentation/kbuild/config-language.txt</filename>).
+     It's good to run "make xconfig" at least once to test (because
+     it's the only one with a static parser).
+    </para>
+
+    <para>
+     Variables which can be Y or N use <type>bool</type> followed by a
+     tagline and the config define name (which must start with
+     CONFIG_).  The <type>tristate</type> function is the same, but
+     allows the answer M (which defines
+     <symbol>CONFIG_foo_MODULE</symbol> in your source, instead of
+     <symbol>CONFIG_FOO</symbol>) if <symbol>CONFIG_MODULES</symbol>
+     is enabled.
+    </para>
+
+    <para>
+     You may well want to make your CONFIG option only visible if
+     <symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a
+     warning to users.  There many other fancy things you can do: see
+     the the various <filename>Config.in</filename> files for ideas.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Edit the <filename>Makefile</filename>: the CONFIG variables are
+     exported here so you can conditionalize compilation with `ifeq'.
+     If your file exports symbols then add the names to
+     <varname>MX_OBJS</varname> or <varname>OX_OBJS</varname> instead
+     of <varname>M_OBJS</varname> or <varname>O_OBJS</varname>, so
+     that genksyms will find them.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Document your option in Documentation/Configure.help.  Mention
+     incompatibilities and issues here.  <emphasis> Definitely
+     </emphasis> end your description with <quote> if in doubt, say N
+     </quote> (or, occasionally, `Y'); this is for people who have no
+     idea what you are talking about.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Put yourself in <filename>CREDITS</filename> if you've done
+     something noteworthy, usually beyond a single file (your name
+     should be at the top of the source files anyway).
+     <filename>MAINTAINERS</filename> means you want to be consulted
+     when changes are made to a subsystem, and hear about bugs; it
+     implies a more-than-passing commitment to some part of the code.
+    </para>
+   </listitem>
+  </itemizedlist>
+ </chapter>
+
+ <chapter id="cantrips">
+  <title>Kernel Cantrips</title>
+
+  <para>
+   Some favorites from browsing the source.  Feel free to add to this
+   list.
+  </para>
+
+  <para>
+   <filename>include/linux/brlock.h:</filename>
+  </para>
+  <programlisting>
+extern inline void br_read_lock (enum brlock_indices idx)
+{
+        /*
+         * This causes a link-time bug message if an
+         * invalid index is used:
+         */
+        if (idx >= __BR_END)
+                __br_lock_usage_bug();
+
+        read_lock(&amp;__brlock_array[smp_processor_id()][idx]);
+}
+  </programlisting>
+
+  <para>
+   <filename>include/linux/fs.h</filename>:
+  </para>
+  <programlisting>
+/*
+ * Kernel pointers have redundant information, so we can use a
+ * scheme where we can return either an error code or a dentry
+ * pointer with the same return value.
+ *
+ * This should be a per-architecture thing, to allow different
+ * error and pointer decisions.
+ */
+ #define ERR_PTR(err)    ((void *)((long)(err)))
+ #define PTR_ERR(ptr)    ((long)(ptr))
+ #define IS_ERR(ptr)     ((unsigned long)(ptr) > (unsigned long)(-1000))
+</programlisting>
+
+  <para>
+   <filename>include/asm-i386/uaccess.h:</filename>
+  </para>
+
+  <programlisting>
+#define copy_to_user(to,from,n)                         \
+        (__builtin_constant_p(n) ?                      \
+         __constant_copy_to_user((to),(from),(n)) :     \
+         __generic_copy_to_user((to),(from),(n)))
+  </programlisting>
+
+  <para>
+   <filename>arch/sparc/kernel/head.S:</filename>
+  </para>
+
+  <programlisting>
+/*
+ * Sun people can't spell worth damn. "compatability" indeed.
+ * At least we *know* we can't spell, and use a spell-checker.
+ */
+
+/* Uh, actually Linus it is I who cannot spell. Too much murky
+ * Sparc assembly will do this to ya.
+ */
+C_LABEL(cputypvar):
+        .asciz "compatability"
+
+/* Tested on SS-5, SS-10. Probably someone at Sun applied a spell-checker. */
+        .align 4
+C_LABEL(cputypvar_sun4m):
+        .asciz "compatible"
+  </programlisting>
+
+  <para>
+   <filename>arch/sparc/lib/checksum.S:</filename>
+  </para>
+
+  <programlisting>
+        /* Sun, you just can't beat me, you just can't.  Stop trying,
+         * give up.  I'm serious, I am going to kick the living shit
+         * out of you, game over, lights out.
+         */
+  </programlisting>
+ </chapter>
+
+ <chapter id="credits">
+  <title>Thanks</title>
+
+  <para>
+   Thanks to Andi Kleen for the idea, answering my questions, fixing
+   my mistakes, filling content, etc.  Philipp Rumpf for more spelling
+   and clarity fixes, and some excellent non-obvious points.  Werner
+   Almesberger for giving me a great summary of
+   <function>disable_irq()</function>, and Jes Sorensen and Andrea
+   Arcangeli added caveats. Michael Elizabeth Chastain for checking
+   and adding to the Configure section. <!-- Rusty insisted on this
+   bit; I didn't do it! --> Telsa Gwynne for teaching me DocBook. 
+  </para>
+ </chapter>
+</book>
+
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/kernel-locking.tmpl linux/Documentation/DocBook/kernel-locking.tmpl
--- v2.3.99-pre8/linux/Documentation/DocBook/kernel-locking.tmpl	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/kernel-locking.tmpl	Sun May 21 20:18:07 2000
@@ -0,0 +1,1221 @@
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
+
+<book id="LKLockingGuide">
+ <bookinfo>
+  <title>Unreliable Guide To Locking</title>
+  
+  <authorgroup>
+   <author>
+    <firstname>Paul</firstname>
+    <othername>Rusty</othername>
+    <surname>Russell</surname>
+    <affiliation>
+     <address>
+      <email>rusty@linuxcare.com</email>
+     </address>
+    </affiliation>
+   </author>
+  </authorgroup>
+
+  <copyright>
+   <year>2000</year>
+   <holder>Paul Russell</holder>
+  </copyright>
+
+  <legalnotice>
+   <para>
+     This documentation is free software; you can redistribute
+     it and/or modify it under the terms of the GNU General Public
+     License as published by the Free Software Foundation; either
+     version 2 of the License, or (at your option) any later
+     version.
+   </para>
+      
+   <para>
+     This program is distributed in the hope that it will be
+     useful, but WITHOUT ANY WARRANTY; without even the implied
+     warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+     See the GNU General Public License for more details.
+   </para>
+      
+   <para>
+     You should have received a copy of the GNU General Public
+     License along with this program; if not, write to the Free
+     Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+     MA 02111-1307 USA
+   </para>
+      
+   <para>
+     For more details see the file COPYING in the source
+     distribution of Linux.
+   </para>
+  </legalnotice>
+ </bookinfo>
+
+ <toc></toc>
+  <chapter id="intro">
+   <title>Introduction</title>
+   <para>
+     Welcome, to Rusty's Remarkably Unreliable Guide to Kernel
+     Locking issues.  This document describes the locking systems in
+     the Linux Kernel as we approach 2.4.
+   </para>
+   <para>
+     It looks like <firstterm linkend="gloss-smp"><acronym>SMP</acronym>
+     </firstterm> is here to stay; so everyone hacking on the kernel 
+     these days needs to know the fundamentals of concurrency and locking 
+     for SMP.
+   </para>
+
+   <sect1 id="races">
+    <title>The Problem With Concurrency</title>
+    <para>
+      (Skip this if you know what a Race Condition is).
+    </para>
+    <para>
+      In a normal program, you can increment a counter like so:
+    </para>
+    <programlisting>
+      very_important_count++;
+    </programlisting>
+
+    <para>
+      This is what they would expect to happen:
+    </para>
+
+    <table>
+     <title>Expected Results</title>
+
+     <tgroup cols=2 align=left>
+
+      <thead>
+       <row>
+        <entry>Instance 1</entry>
+        <entry>Instance 2</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry>read very_important_count (5)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry>add 1 (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry>write very_important_count (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>read very_important_count (6)</entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>add 1 (7)</entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>write very_important_count (7)</entry>
+       </row>
+      </tbody>
+
+     </tgroup>
+    </table>
+
+    <para>
+     This is what might happen:
+    </para>
+
+    <table>
+     <title>Possible Results</title>
+
+     <tgroup cols=2 align=left>
+      <thead>
+       <row>
+        <entry>Instance 1</entry>
+        <entry>Instance 2</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry>read very_important_count (5)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>read very_important_count (5)</entry>
+       </row>
+       <row>
+        <entry>add 1 (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>add 1 (5)</entry>
+       </row>
+       <row>
+        <entry>write very_important_count (6)</entry>
+        <entry></entry>
+       </row>
+       <row>
+        <entry></entry>
+        <entry>write very_important_count (6)</entry>
+       </row>
+      </tbody>
+     </tgroup>
+    </table>
+
+    <para>
+      This overlap, where what actually happens depends on the
+      relative timing of multiple tasks, is called a race condition.
+      The piece of code containing the concurrency issue is called a
+      critical region.  And especially since Linux starting running
+      on SMP machines, they became one of the major issues in kernel
+      design and implementation.
+    </para>
+    <para>
+      The solution is to recognize when these simultaneous accesses
+      occur, and use locks to make sure that only one instance can
+      enter the critical region at any time.  There are many
+      friendly primitives in the Linux kernel to help you do this.
+      And then there are the unfriendly primitives, but I'll pretend
+      they don't exist.
+    </para>
+   </sect1>
+  </chapter>
+
+  <chapter id="locks">
+   <title>Two Main Types of Kernel Locks: Spinlocks and Semaphores</title>
+
+   <para>
+     There are two main types of kernel locks.  The fundamental type
+     is the spinlock 
+     (<filename class=headerfile>include/asm/spinlock.h</filename>), 
+     which is a very simple single-holder lock: if you can't get the 
+     spinlock, you keep trying (spinning) until you can.  Spinlocks are 
+     very small and fast, and can be used anywhere.
+   </para>
+   <para>
+     The second type is a semaphore
+     (<filename class=headerfile>include/asm/semaphore.h</filename>): it
+     can have more than one holder at any time (the number decided at
+     initialization time), although it is most commonly used as a
+     single-holder lock (a mutex).  If you can't get a semaphore,
+     your task will put itself on the queue, and be woken up when the
+     semaphore is released.  This means the CPU will do something
+     else while you are waiting, but there are many cases when you
+     simply can't sleep, and so have to use a spinlock instead.
+   </para>
+ 
+   <sect1 id="uniprocessor">
+    <title>Locks and Uniprocessor Kernels</title>
+
+    <para>
+      For kernels compiled without <symbol>CONFIG_SMP</symbol>, spinlocks 
+      do not exist at all.  This is an excellent design decision: when
+      no-one else can run at the same time, there is no reason to
+      have a lock at all.
+    </para>
+
+    <para>
+      You should always test your locking code with <symbol>CONFIG_SMP</symbol>
+      enabled, even if you don't have an SMP test box, because it
+      will still catch some (simple) kinds of deadlock.
+    </para>
+
+    <para>
+      Semaphores still exist, because they are required for
+      synchronization between <firstterm linkend="gloss-usercontext">user 
+      contexts</firstterm>, as we will see below.
+    </para>
+   </sect1>
+
+   <sect1 id="rwlocks">
+    <title>Read/Write Lock Variants</title>
+
+    <para>
+      Both spinlocks and semaphores have read/write variants:
+      <type>rwlock_t</type> and <structname>struct rw_semaphore</structname>. 
+      These divide users into two classes: the readers and the writers.  If 
+      you are only reading the data, you can get a read lock, but to write to 
+      the data you need the write lock.  Many people can hold a read lock,
+      but a writer must be sole holder.
+    </para>
+
+    <para>
+      This means much smoother locking if your code divides up
+      neatly along reader/writer lines.  All the discussions below
+      also apply to read/write variants.
+    </para>
+   </sect1>
+
+    <sect1 id="usercontextlocking">
+     <title>Locking Only In User Context</title>
+
+     <para>
+       If you have a data structure which is only ever accessed from
+       user context, then you can use a simple semaphore
+       (<filename>linux/asm/semaphore.h</filename>) to protect it.  This 
+       is the most trivial case: you initialize the semaphore to the number 
+       of resources available (usually 1), and call
+       <function>down_interruptible()</function> to grab the semaphore, and 
+       <function>up()</function> to release it.  There is also a 
+       <function>down()</function>, which should be avoided, because it 
+       will not return if a signal is received.
+     </para>
+
+     <para>
+       Example: <filename>linux/net/core/netfilter.c</filename> allows 
+       registration of new <function>setsockopt()</function> and 
+       <function>getsockopt()</function> calls, with
+       <function>nf_register_sockopt()</function>.  Registration and 
+       de-registration are only done on module load and unload (and boot 
+       time, where there is no concurrency), and the list of registrations 
+       is only consulted for an unknown <function>setsockopt()</function>
+       or <function>getsockopt()</function> system call.  The 
+       <varname>nf_sockopt_mutex</varname> is perfect to protect this,
+       especially since the setsockopt and getsockopt calls may well
+       sleep.
+     </para>
+   </sect1>
+
+   <sect1 id="lock-user-bh">
+    <title>Locking Between User Context and BHs</title>
+
+    <para>
+      If a <firstterm linkend="gloss-bh">bottom half</firstterm> shares 
+      data with user context, you have two problems.  Firstly, the current 
+      user context can be interrupted by a bottom half, and secondly, the 
+      critical region could be entered from another CPU.  This is where
+      <function>spin_lock_bh()</function> 
+      (<filename class=headerfile>include/linux/spinlock.h</filename>) is 
+      used.  It disables bottom halves on that CPU, then grabs the lock.
+      <function>spin_unlock_bh()</function> does the reverse.
+    </para>
+
+    <para>
+      This works perfectly for <firstterm linkend="gloss-up"><acronym>UP
+      </acronym></firstterm> as well: the spin lock vanishes, and this macro 
+      simply becomes <function>local_bh_disable()</function>
+      (<filename class=headerfile>include/asm/softirq.h</filename>), which 
+      protects you from the bottom half being run.
+    </para>
+   </sect1>
+
+   <sect1 id="lock-user-tasklet">
+    <title>Locking Between User Context and Tasklets/Soft IRQs</title>
+
+    <para>
+      This is exactly the same as above, because
+      <function>local_bh_disable()</function> actually disables all 
+      softirqs and <firstterm linkend="gloss-tasklet">tasklets</firstterm>
+      on that CPU as well.  It should really be 
+      called `local_softirq_disable()', but the name has been preserved 
+      for historical reasons.  Similarly,
+      <function>spin_lock_bh()</function> would now be called 
+      spin_lock_softirq() in a perfect world.
+    </para>
+   </sect1>
+
+   <sect1 id="lock-bh">
+    <title>Locking Between Bottom Halves</title>
+
+    <para>
+      Sometimes a bottom half might want to share data with
+      another bottom half (especially remember that timers are run
+      off a bottom half).
+    </para>
+
+    <sect2 id="lock-bh-same">
+     <title>The Same BH</title>
+
+     <para>
+       Since a bottom half is never run on two CPUs at once, you
+       don't need to worry about your bottom half being run twice
+       at once, even on SMP.
+     </para>
+    </sect2>
+
+    <sect2 id="lock-bh-different">
+     <title>Different BHs</title>
+
+     <para>
+       Since only one bottom half ever runs at a time once, you
+       don't need to worry about race conditions with other bottom
+       halves.  Beware that things might change under you, however,
+       if someone changes your bottom half to a tasklet.  If you
+       want to make your code future-proof, pretend you're already
+       running from a tasklet (see below), and doing the extra
+       locking.  Of course, if it's five years before that happens,
+       you're gonna look like a damn fool.
+     </para>
+    </sect2>
+   </sect1>
+
+   <sect1 id="lock-tasklets">
+    <title>Locking Between Tasklets</title>
+
+    <para>
+      Sometimes a tasklet might want to share data with another
+      tasklet, or a bottom half.
+    </para>
+
+    <sect2 id="lock-tasklets-same">
+     <title>The Same Tasklet</title>
+     <para>
+       Since a tasklet is never run on two CPUs at once, you don't
+       need to worry about your tasklet being reentrant (running
+       twice at once), even on SMP.
+     </para>
+    </sect2>
+
+    <sect2 id="lock-tasklets-different">
+     <title>Different Tasklets</title>
+     <para>
+       If another tasklet (or bottom half, such as a timer) wants
+       to share data with your tasklet, you will both need to use
+       <function>spin_lock()</function> and
+       <function>spin_unlock()</function> calls.  
+       <function>spin_lock_bh()</function> is
+       unnecessary here, as you are already in a a tasklet, and
+       none will be run on the same CPU.
+     </para>
+    </sect2>
+   </sect1>
+
+   <sect1 id="lock-softirqs">
+    <title>Locking Between Softirqs</title>
+
+    <para>
+      Often a <firstterm linkend="gloss-softirq">softirq</firstterm> might 
+      want to share data with itself, a tasklet, or a bottom half.
+    </para>
+
+    <sect2 id="lock-softirqs-same">
+     <title>The Same Softirq</title>
+
+     <para>
+       The same softirq can run on the other CPUs: you can use a
+       per-CPU array (see <xref linkend="per-cpu">) for better
+       performance.  If you're going so far as to use a softirq,
+       you probably care about scalable performance enough
+       to justify the extra complexity.
+     </para>
+
+     <para>
+       You'll need to use <function>spin_lock()</function> and 
+       <function>spin_unlock()</function> for shared data.
+     </para>
+    </sect2>
+
+    <sect2 id="lock-softirqs-different">
+     <title>Different Softirqs</title>
+
+     <para>
+       You'll need to use <function>spin_lock()</function> and 
+       <function>spin_unlock()</function> for shared data, whether it 
+       be a timer (which can be running on a different CPU), bottom half, 
+       tasklet or the same or another softirq.
+     </para>
+    </sect2>
+   </sect1>
+  </chapter>
+
+  <chapter id="hardirq-context">
+   <title>Hard IRQ Context</title>
+
+   <para>
+     Hardware interrupts usually communicate with a bottom half,
+     tasklet or softirq.  Frequently this involved putting work in a
+     queue, which the BH/softirq will take out.
+   </para>
+
+   <sect1 id="hardirq-softirq">
+    <title>Locking Between Hard IRQ and Softirqs/Tasklets/BHs</title>
+
+    <para>
+      If a hardware irq handler shares data with a softirq, you have
+      two concerns.  Firstly, the softirq processing can be
+      interrupted by a hardware interrupt, and secondly, the
+      critical region could be entered by a hardware interrupt on
+      another CPU.  This is where <function>spin_lock_irq()</function> is 
+      used.  It is defined to disable interrupts on that cpu, then grab 
+      the lock. <function>spin_unlock_irq()</function> does the reverse.
+    </para>
+
+    <para>
+      This works perfectly for UP as well: the spin lock vanishes,
+      and this macro simply becomes <function>local_irq_disable()</function>
+      (<filename class=headerfile>include/asm/smp.h</filename>), which 
+      protects you from the softirq/tasklet/BH being run.
+    </para>
+
+    <para>
+      <function>spin_lock_irqsave()</function> 
+      (<filename>include/linux/spinlock.h</filename>) is a variant
+      which saves whether interrupts were on or off in a flags word,
+      which is passed to <function>spin_lock_irqrestore()</function>.  This 
+      means that the same code can be used inside an hard irq handler (where
+      interrupts are already off) and in softirqs (where the irq
+      disabling is required).
+    </para>
+   </sect1>
+  </chapter>
+
+  <chapter id="common-techniques">
+   <title>Common Techniques</title>
+
+   <para>
+     This section lists some common dilemmas and the standard
+     solutions used in the Linux kernel code.  If you use these,
+     people will find your code simpler to understand.
+   </para>
+
+   <para>
+     If I could give you one piece of advice: never sleep with anyone
+     crazier than yourself.  But if I had to give you advice on
+     locking: <emphasis>keep it simple</emphasis>.
+   </para>
+
+   <para>
+     Lock data, not code.
+   </para>
+
+   <para>
+     Be reluctant to introduce new locks.
+   </para>
+
+   <para>
+     Strangely enough, this is the exact reverse of my advice when
+     you <emphasis>have</emphasis> slept with someone crazier than yourself.
+   </para>
+
+   <sect1 id="techniques-no-writers">
+    <title>No Writers in Interrupt Context</title>
+
+    <para>
+      There is a fairly common case where an interrupt handler needs
+      access to a critical region, but does not need write access.
+      In this case, you do not need to use
+      <function>read_lock_irq()</function>, but only
+      <function>read_lock()</function> everywhere (since if an interrupt 
+      occurs, the irq handler will only try to grab a read lock, which 
+      won't deadlock).  You will still need to use 
+      <function>write_lock_irq()</function>.
+    </para>
+
+    <para>
+      Similar logic applies to locking between softirqs/tasklets/BHs
+      which never need a write lock, and user context: 
+      <function>read_lock()</function> and
+      <function>write_lock_bh()</function>.
+    </para>
+   </sect1>
+
+   <sect1 id="techniques-deadlocks">
+    <title>Deadlock: Simple and Advanced</title>
+
+    <para>
+      There is a coding bug where a piece of code tries to grab a
+      spinlock twice: it will spin forever, waiting for the lock to
+      be released (spinlocks and writelocks are not re-entrant in
+      Linux).  This is trivial to diagnose: not a
+      stay-up-five-nights-talk-to-fluffy-code-bunnies kind of
+      problem.
+    </para>
+
+    <para>
+      For a slightly more complex case, imagine you have a region
+      shared by a bottom half and user context.  If you use a
+      <function>spin_lock()</function> call to protect it, it is 
+      possible that the user context will be interrupted by the bottom 
+      half while it holds the lock, and the bottom half will then spin 
+      forever trying to get the same lock.
+    </para>
+
+    <para>
+      Both of these are called deadlock, and as shown above, it can
+      occur even with a single CPU (although not on UP compiles,
+      since spinlocks vanish on kernel compiles with 
+      <symbol>CONFIG_SMP</symbol>=n. You'll still get data corruption 
+      in the second example).
+    </para>
+
+    <para>
+      This complete lockup is easy to diagnose: on SMP boxes the
+      watchdog timer or compiling with <symbol>DEBUG_SPINLOCKS</symbol> set
+      (<filename>include/linux/spinlock.h</filename>) will show this up 
+      immediately when it happens.
+    </para>
+
+    <para>
+      A more complex problem is the so-called `deadly embrace',
+      involving two or more locks.  Say you have a hash table: each
+      entry in the table is a spinlock, and a chain of hashed
+      objects.  Inside a softirq handler, you sometimes want to
+      alter an object from one place in the hash to another: you
+      grab the spinlock of the old hash chain and the spinlock of
+      the new hash chain, and delete the object from the old one,
+      and insert it in the new one.
+    </para>
+
+    <para>
+      There are two problems here.  First, if your code ever
+      tries to move the object to the same chain, it will deadlock
+      with itself as it tries to lock it twice.  Secondly, if the
+      same softirq on another CPU is trying to move another object
+      in the reverse direction, the following could happen:
+    </para>
+
+    <table>
+     <title>Consequences</title>
+
+     <tgroup cols=2 align=left>
+
+      <thead>
+       <row>
+        <entry>CPU 1</entry>
+        <entry>CPU 2</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry>Grab lock A -&gt; OK</entry>
+        <entry>Grab lock B -&gt; OK</entry>
+       </row>
+       <row>
+        <entry>Grab lock B -&gt; spin</entry>
+        <entry>Grab lock A -&gt; spin</entry>
+       </row>
+      </tbody>
+     </tgroup>
+    </table>
+
+    <para>
+      The two CPUs will spin forever, waiting for the other to give up
+      their lock.  It will look, smell, and feel like a crash.
+    </para>
+
+    <sect2 id="techs-deadlock-prevent">
+     <title>Preventing Deadlock</title>
+
+     <para>
+       Textbooks will tell you that if you always lock in the same
+       order, you will never get this kind of deadlock.  Practice
+       will tell you that this approach doesn't scale: when I
+       create a new lock, I don't understand enough of the kernel
+       to figure out where in the 5000 lock hierarchy it will fit.
+     </para>
+
+     <para>
+       The best locks are encapsulated: they never get exposed in
+       headers, and are never held around calls to non-trivial
+       functions outside the same file.  You can read through this
+       code and see that it will never deadlock, because it never
+       tries to grab another lock while it has that one.  People
+       using your code don't even need to know you are using a
+       lock.
+     </para>
+
+     <para>
+       A classic problem here is when you provide callbacks or
+       hooks: if you call these with the lock held, you risk simple
+       deadlock, or a deadly embrace (who knows what the callback
+       will do?).  Remember, the other programmers are out to get
+       you, so don't do this.
+     </para>
+    </sect2>
+
+    <sect2 id="techs-deadlock-overprevent">
+     <title>Overzealous Prevention Of Deadlocks</title>
+
+     <para>
+       Deadlocks are problematic, but not as bad as data
+       corruption.  Code which grabs a read lock, searches a list,
+       fails to find what it wants, drops the read lock, grabs a
+       write lock and inserts the object has a race condition.
+     </para>
+
+     <para>
+       If you don't see why, please stay the fuck away from my code.
+     </para>
+    </sect2>
+   </sect1>
+
+   <sect1 id="per-cpu">
+    <title>Per-CPU Data</title>
+      
+    <para>
+      A great technique for avoiding locking which is used fairly
+      widely is to duplicate information for each CPU.  For example,
+      if you wanted to keep a count of a common condition, you could
+      use a spin lock and a single counter.  Nice and simple.
+    </para>
+
+    <para>
+      If that was too slow [it's probably not], you could instead
+      use a counter for each CPU [don't], then none of them need an
+      exclusive lock [you're wasting your time here].  To make sure
+      the CPUs don't have to synchronize caches all the time, align
+      the counters to cache boundaries by appending
+      `__cacheline_aligned' to the declaration
+      (<filename class=headerfile>include/linux/cache.h</filename>). 
+      [Can't you think of anything better to do?]
+    </para>
+
+    <para>
+      They will need a read lock to access their own counters,
+      however.  That way you can use a write lock to grant exclusive
+      access to all of them at once, to tally them up.
+    </para>
+   </sect1>
+
+   <sect1 id="brlock">
+    <title>Big Reader Locks</title>
+
+    <para>
+      A classic example of per-CPU information is Ingo's `big
+      reader' locks 
+      (<filename class=headerfile>linux/include/brlock.h</filename>).  These 
+      use the Per-CPU Data techniques described above to create a lock which 
+      is very fast to get a read lock, but agonizingly slow for a write
+      lock.
+    </para>
+
+    <para>
+      Fortunately, there are a limited number of these locks
+      available: you have to go through a strict interview process
+      to get one.
+    </para>
+   </sect1>
+
+   <sect1 id="lock-avoidance-rw">
+    <title>Avoiding Locks: Read And Write Ordering</title>
+
+    <para>
+      Sometimes it is possible to avoid locking.  Consider the
+      following case from the 2.2 firewall code, which inserted an
+      element into a single linked list in user context:
+    </para>
+
+    <programlisting>
+        new-&gt;next = i-&gt;next;
+        i-&gt;next = new;
+    </programlisting>
+
+    <para>
+      Here the author (Alan Cox, who knows what he's doing) assumes
+      that the pointer assignments are atomic.  This is important,
+      because networking packets would traverse this list on bottom
+      halves without a lock.  Depending on their exact timing, they
+      would either see the new element in the list with a valid 
+      <structfield>next</structfield> pointer, or it would not be in the 
+      list yet.
+    </para>
+
+    <para>
+      Of course, the writes <emphasis>must</emphasis> be in this
+      order, otherwise the new element appears in the list with an
+      invalid <structfield>next</structfield> pointer, and any other 
+      CPU iterating at the wrong time will jump through it into garbage.  
+      Because modern CPUs reorder, Alan's code actually read as follows:
+    </para>
+      
+    <programlisting>
+        new-&gt;next = i-&gt;next;
+        wmb();
+        i-&gt;next = new;
+    </programlisting>
+
+    <para>
+      The <function>wmb()</function> is a write memory barrier 
+      (<filename class=headerfile>include/asm/system.h</filename>): neither 
+      the compiler nor the CPU will allow any writes to memory after the 
+      <function>wmb()</function> to be visible to other hardware
+      before any of the writes before the <function>wmb()</function>.
+    </para>
+
+    <para>
+      As i386 does not do write reordering, this bug would never
+      show up on that platform.  On other SMP platforms, however, it
+      will.
+    </para>
+
+    <para>
+      There is also <function>rmb()</function> for read ordering: to ensure 
+      any previous variable reads occur before following reads.  The simple
+      <function>mb()</function> macro combines both 
+      <function>rmb()</function> and <function>wmb()</function>.
+    </para>
+
+    <para>
+      Dropping or gaining a spinlock, and any atomic operation are
+      all defined to act as memory barriers (ie. as per the 
+      <function>mb()</function> macro).
+    </para>
+
+    <para>
+      There is a similar, but unrelated, problem with code like the
+      following:
+    </para>
+
+    <programlisting>
+        if (!(ctrack-&gt;status &amp; IPS_CONFIRMED)) {
+                spin_lock_bh(&amp;ip_conntrack_lock);
+                if (!(ctrack-&gt;status &amp; IPS_CONFIRMED)) {
+                        clean_from_lists(h-&gt;ctrack);
+                        h-&gt;ctrack-&gt;status |= IPS_CONFIRMED;
+                }
+                spin_unlock_bh(&amp;ip_conntrack_lock);
+        }
+    </programlisting>
+
+    <para>
+      In this case, the author has tried to be tricky: knowing that
+      the CONFIRMED bit is set and never reset in the status word,
+      you can test it outside the lock, and frequently avoid
+      grabbing the lock at all.  However, the compiler could cache
+      the value in a register, rather than rereading it once the
+      lock is obtained, creating a subtle race.  The way to get
+      around this is to declare the status field `volatile', or use
+      a temporary volatile pointer to achieve the same effect in
+      this one place.
+    </para>
+   </sect1>
+
+   <sect1 id="lock-avoidance-atomic-ops">
+    <title>Avoiding Locks: Atomic Operations</title>
+
+    <para>
+      There are a number of atomic operations defined in
+      <filename class=headerfile>include/asm/atomic.h</filename>: these 
+      are guaranteed to be seen atomically from all CPUs in the system, thus 
+      avoiding races. If your shared data consists of a single counter, say, 
+      these operations might be simpler than using spinlocks (although for
+      anything non-trivial using spinlocks is clearer).
+    </para>
+
+    <para>
+      Note that the atomic operations are defined to act as both
+      read and write barriers on all platforms.
+    </para>
+   </sect1>
+
+   <sect1 id="ref-counts">
+    <title>Protecting A Collection of Objects: Reference Counts</title>
+
+    <para>
+      Locking a collection of objects is fairly easy: you get a
+      single spinlock, and you make sure you grab it before
+      searching, adding or deleting an object.
+    </para>
+
+    <para>
+      The purpose of this lock is not to protect the individual
+      objects: you might have a separate lock inside each one for
+      that.  It is to protect the <emphasis>data structure
+      containing the objects</emphasis> from race conditions.  Often
+      the same lock is used to protect the contents of all the
+      objects as well, for simplicity, but they are inherently
+      orthogonal (and many other big words designed to confuse).
+    </para>
+
+    <para>
+      Changing this to a read-write lock will often help markedly if
+      reads are far more common that writes.  If not, there is
+      another approach you can use to reduce the time the lock is
+      held: reference counts.
+    </para>
+
+    <para>
+      In this approach, an object has an owner, who sets the
+      reference count to one.  Whenever you get a pointer to the
+      object, you increment the reference count (a `get' operation).
+      Whenever you relinquish a pointer, you decrement the reference
+      count (a `put' operation).  When the owner wants to destroy
+      it, they mark it dead, and do a put.
+    </para>
+
+    <para>
+      Whoever drops the reference count to zero (usually implemented
+      with <function>atomic_dec_and_test()</function>) actually cleans 
+      up and frees the object.
+    </para>
+
+    <para>
+      This means that you are guaranteed that the object won't
+      vanish underneath you, even though you no longer have a lock
+      for the collection.
+    </para>
+
+    <para>
+      Here's some skeleton code:
+    </para>
+
+    <programlisting>
+        void create_foo(struct foo *x)
+        {
+                atomic_set(&amp;x-&gt;use, 1);
+                spin_lock_bh(&amp;list_lock);
+                ... insert in list ...
+                spin_unlock_bh(&amp;list_lock);
+        }
+
+        struct foo *get_foo(int desc)
+        {
+                struct foo *ret;
+
+                spin_lock_bh(&amp;list_lock);
+                ... find in list ...
+                if (ret) atomic_inc(&amp;ret-&gt;use);
+                spin_unlock_bh(&amp;list_lock);
+
+                return ret;
+        }
+
+        void put_foo(struct foo *x)
+        {
+                if (atomic_dec_and_test(&amp;x-&gt;use))
+                        kfree(foo);
+        }
+
+        void destroy_foo(struct foo *x)
+        {
+                spin_lock_bh(&amp;list_lock);
+                ... remove from list ...
+                spin_unlock_bh(&amp;list_lock);
+
+                put_foo(x);
+        }
+    </programlisting>
+
+    <sect2 id="helpful-macros">
+     <title>Macros To Help You</title>
+     <para>
+       There are a set of debugging macros tucked inside
+       <filename class=headerfile>include/linux/netfilter_ipv4/lockhelp.h</filename>
+       and <filename class=headerfile>listhelp.h</filename>: these are very
+       useful for ensuring that locks are held in the right places to protect
+       infrastructure.
+     </para>
+    </sect2>
+   </sect1>
+   
+   <sect1 id="sleeping-things">
+    <title>Things Which Sleep</title>
+
+    <para>
+      You can never call the following routines while holding a
+      spinlock, as they may sleep:
+    </para>
+
+    <itemizedlist>
+     <listitem>
+      <para>
+        Accesses to 
+        <firstterm linkend="gloss-userspace">userspace</firstterm>:
+      </para>
+      <itemizedlist>
+       <listitem>
+        <para>
+          <function>copy_from_user()</function>
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+          <function>copy_to_user()</function>
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+          <function>get_user()</function>
+        </para>
+       </listitem>
+       <listitem>
+        <para>
+          <function> put_user()</function>
+        </para>
+       </listitem>
+      </itemizedlist>
+     </listitem>
+
+     <listitem>
+      <para>
+        <function>kmalloc(GFP_KERNEL)</function>
+      </para>
+     </listitem>
+
+     <listitem>
+      <para>
+        <function>printk()</function>, which can be called from
+        user context, interestingly enough.
+      </para>
+     </listitem>
+    </itemizedlist>
+   </sect1>
+
+   <sect1 id="sparc">
+    <title>The Fucked Up Sparc</title>
+
+    <para>
+      Alan Cox says <quote>the irq disable/enable is in the register
+      window on a sparc</quote>.  Andi Kleen says <quote>when you do
+      restore_flags in a different function you mess up all the
+      register windows</quote>.
+    </para>
+
+    <para>
+      So never pass the flags word set by 
+      <function>spin_lock_irqsave()</function> and brethren to another 
+      function (unless it's declared <type>inline</type>.  Usually no-one 
+      does this, but now you've been warned.  Dave Miller can never do 
+      anything in a straightforward manner (I can say that, because I have
+      pictures of him and a certain PowerPC maintainer in a compromising 
+      position).
+    </para>
+   </sect1>
+
+   <sect1 id="racing-timers">
+    <title>Racing Timers: A Kernel Pastime</title>
+
+    <para>
+      Timers can produce their own special problems with races.
+      Consider a collection of objects (list, hash, etc) where each
+      object has a timer which is due to destroy it.
+    </para>
+
+    <para>
+      If you want to destroy the entire collection (say on module
+      removal), you might do the following:
+    </para>
+
+    <programlisting>
+        /* THIS CODE BAD BAD BAD BAD: IF IT WAS ANY WORSE IT WOULD USE
+           HUNGARIAN NOTATION */
+        spin_lock_bh(&amp;list_lock);
+
+        while (list) {
+                struct foo *next = list-&gt;next;
+                del_timer(&amp;list-&gt;timer);
+                kfree(list);
+                list = next;
+        }
+
+        spin_unlock_bh(&amp;list_lock);
+    </programlisting>
+
+    <para>
+      Sooner or later, this will crash on SMP, because a timer can
+      have just gone off before the <function>spin_lock_bh()</function>, 
+      and it will only get the lock after we 
+      <function>spin_unlock_bh()</function>, and then try to free
+      the element (which has already been freed!).
+    </para>
+
+    <para>
+      This can be avoided by checking the result of 
+      <function>del_timer()</function>: if it returns
+      <returnvalue>1</returnvalue>, the timer has been deleted.  
+      If <returnvalue>0</returnvalue>, it means (in this
+      case) that it is currently running, so we can do:
+    </para>
+
+    <programlisting>
+        retry:  
+                spin_lock_bh(&amp;list_lock);
+
+                while (list) {
+                        struct foo *next = list-&gt;next;
+                        if (!del_timer(&amp;list-&gt;timer)) {
+                                /* Give timer a chance to delete this */
+                                spin_unlock_bh(&amp;list_lock);
+                                goto retry;
+                        }
+                        kfree(list);
+                        list = next;
+                }
+
+                spin_unlock_bh(&amp;list_lock);
+    </programlisting>
+
+    <para>
+      Another common problem is deleting timers which restart
+      themselves (by calling <function>add_timer()</function> at the end 
+      of their timer function).  Because this is a fairly common case 
+      which is prone to races, the function <function>del_timer_sync()</function> 
+      (<filename class=headerfile>include/linux/timer.h</filename>) is
+      provided to handle this case.  It returns the number of times the timer 
+      had to be deleted before we finally stopped it from adding itself back 
+      in.
+    </para>
+   </sect1>
+  </chapter>
+
+  <chapter id="references">
+   <title>Further reading</title>
+
+   <itemizedlist>
+    <listitem>
+     <para>
+       <filename>Documentation/spinlocks.txt</filename>: 
+       Linus Torvalds' spinlocking tutorial in the kernel sources.
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+       Unix Systems for Modern Architectures: Symmetric
+       Multiprocessing and Caching for Kernel Programmers:
+     </para>
+
+     <para>
+       Curt Schimmel's very good introduction to kernel level
+       locking (not written for Linux, but nearly everything
+       applies).  The book is expensive, but really worth every
+       penny to understand SMP locking. [ISBN: 0201633388]
+     </para>
+    </listitem>
+   </itemizedlist>
+  </chapter>
+
+  <chapter id="thanks">
+    <title>Thanks</title>
+
+    <para>
+      Thanks to Telsa Gwynne for DocBooking, neatening and adding
+      style.
+    </para>
+
+    <para>
+      Thanks to Martin Pool, Philipp Rumpf, Stephen Rothwell, Paul
+      Mackerras, Ruedi Aschwanden, Alan Cox for proofreading,
+      correcting, flaming, commenting.
+    </para>
+
+    <para>
+      Thanks to the cabal for having no influence on this document.
+    </para>
+  </chapter>
+
+  <glossary id="glossary">
+   <title>Glossary</title>
+
+   <glossentry id="gloss-bh">
+    <glossterm>bh</glossterm>
+     <glossdef>
+      <para>
+        Bottom Half: for historical reasons, functions with
+        `_bh' in them often now refer to any software interrupt, e.g.
+        <function>spin_lock_bh()</function> blocks any software interrupt 
+        on the current CPU.  Bottom halves are deprecated, and will 
+        eventually be replaced by tasklets.  Only one bottom half will be 
+        running at any time.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-hwinterrupt">
+    <glossterm>Hardware Interrupt / Hardware IRQ</glossterm>
+    <glossdef>
+     <para>
+       Hardware interrupt request.  <function>in_irq()</function> returns 
+       <returnvalue>true</returnvalue> in a hardware interrupt handler (it 
+       also returns true when interrupts are blocked).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-interruptcontext">
+    <glossterm>Interrupt Context</glossterm>
+    <glossdef>
+     <para>
+       Not user context: processing a hardware irq or software irq.
+       Indicated by the <function>in_interrupt()</function> macro 
+       returning <returnvalue>true</returnvalue> (although it also
+       returns true when interrupts or BHs are blocked).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-smp">
+    <glossterm><acronym>SMP</acronym></glossterm>
+    <glossdef>
+     <para>
+       Symmetric Multi-Processor: kernels compiled for multiple-CPU
+       machines.  (CONFIG_SMP=y).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-softirq">
+    <glossterm>softirq</glossterm>
+    <glossdef>
+     <para>
+       Strictly speaking, one of up to 32 enumerated software
+       interrupts which can run on multiple CPUs at once.
+       Sometimes used to refer to tasklets and bottom halves as
+       well (ie. all software interrupts).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-swinterrupt">
+    <glossterm>Software Interrupt / Software IRQ</glossterm>
+    <glossdef>
+     <para>
+       Software interrupt handler.  <function>in_irq()</function> returns 
+       <returnvalue>false</returnvalue>; <function>in_softirq()</function>
+       returns <returnvalue>true</returnvalue>.  Tasklets, softirqs and 
+       bottom halves all fall into the category of `software interrupts'.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-tasklet">
+    <glossterm>tasklet</glossterm>
+    <glossdef>
+     <para>
+       A dynamically-registrable software interrupt,
+       which is guaranteed to only run on one CPU at a time.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-up">
+    <glossterm><acronym>UP</acronym></glossterm>
+    <glossdef>
+     <para>
+       Uni-Processor: Non-SMP.  (CONFIG_SMP=n).
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-usercontext">
+    <glossterm>User Context</glossterm>
+    <glossdef>
+     <para>
+       The kernel executing on behalf of a particular
+       process or kernel thread (given by the <function>current()</function>
+       macro.)  Not to be confused with userspace.  Can be interrupted by 
+       software  or hardware interrupts.
+     </para>
+    </glossdef>
+   </glossentry>
+
+   <glossentry id="gloss-userspace">
+    <glossterm>Userspace</glossterm>
+    <glossdef>
+     <para>
+       A process executing its own code outside the kernel.
+     </para>
+    </glossdef>
+   </glossentry>      
+
+  </glossary>
+</book>
+
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/DocBook/parportbook.tmpl linux/Documentation/DocBook/parportbook.tmpl
--- v2.3.99-pre8/linux/Documentation/DocBook/parportbook.tmpl	Tue Apr 11 15:09:11 2000
+++ linux/Documentation/DocBook/parportbook.tmpl	Tue May 23 08:44:35 2000
@@ -1,8 +1,9 @@
+<!-- -*- sgml -*- -->
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[]>
 
 <book id="ParportGuide">
  <bookinfo>
-  <title>The Parallel Port Subsystem</title>
+  <title>The Linux 2.4 Parallel Port Subsystem</title>
 
   <authorgroup>
    <author>
@@ -51,90 +52,97 @@
   </legalnotice>
  </bookinfo>
 
-<toc></toc>
+ <toc></toc>
 
-<chapter id="design">
-<title>Design goals</title>
+ <chapter id="design">
+  <title>Design goals</title>
 
-<sect1>
-<title>The problems</title>
+  <sect1>
+   <title>The problems</title>
 
-<!-- Short-comings -->
-<!-- How they are addressed -->
-
-<!-- Short-comings
-     - simplistic lp driver
-     - platform differences
-     - no support for Zip drive pass-through
-     - no support for readback? When did Carsten add it?
-     - more parallel port devices. Figures?
-     - IEEE 1284 transfer modes: no advanced modes
-  -->
+   <para>
+    The first parallel port support for Linux came with the line
+    printer driver, <literal>lp</literal>.  The printer driver is a
+    character special device, and (in Linux 2.0) had support for
+    writing, via <function>write</function>, and configuration and
+    statistics reporting via <function>ioctl</function>.
+   </para>
+
+   <para>
+    The printer driver could be used on any computer that had an IBM
+    PC-compatible parallel port.  Because some architectures have
+    parallel ports that aren't really the same as PC-style ports,
+    other variants of the printer driver were written in order to
+    support Amiga and Atari parallel ports.
+   </para>
+
+   <para>
+    When the Iomega Zip drive was released, and a driver written for
+    it, a problem became apparent.  The Zip drive is a parallel port
+    device that provides a parallel port of its own---it is designed
+    to sit between a computer and an attached printer, with the
+    printer plugged into the Zip drive, and the Zip drive plugged into
+    the computer.
+   </para>
+
+   <para>
+    The problem was that, although printers and Zip drives were both
+    supported, for any given port only one could be used at a time.
+    Only one of the two drivers could be present in the kernel at
+    once.  This was because of the fact that both drivers wanted to
+    drive the same hardware---the parallel port.  When the printer
+    driver initialised, it would call the
+    <function>check_region</function> function to make sure that the
+    IO region associated with the parallel port was free, and then it
+    would call <function>request_region</function> to allocate it.
+    The Zip drive used the same mechanism.  Whichever driver
+    initialised first would gain exclusive control of the parallel
+    port.
+   </para>
+
+   <para>
+    The only way around this problem at the time was to make sure that
+    both drivers were available as loadable kernel modules.  To use
+    the printer, load the printer driver module; then for the Zip
+    drive, unload the printer driver module and load the Zip driver
+    module.
+   </para>
+
+   <para>
+    The net effect was that printing a document that was stored on a
+    Zip drive was a bit of an ordeal, at least if the Zip drive and
+    printer shared a parallel port.  A better solution was
+    needed.
+   </para>
+
+   <para>
+    Zip drives are not the only devices that presented problems for
+    Linux.  There are other devices with pass-through ports, for
+    example parallel port CD-ROM drives.  There are also printers that
+    report their status textually rather than using simple error pins:
+    sending a command to the printer can cause it to report the number
+    of pages that it has ever printed, or how much free memory it has,
+    or whether it is running out of toner, and so on.  The printer
+    driver didn't originally offer any facility for reading back this
+    information (although Carsten Gross added nibble mode readback
+    support for kernel 2.2).
+   </para>
 
-<para>The first parallel port support for Linux came with the line
-printer driver, <filename>lp</filename>.  The printer driver is a
-character special device, and (in Linux 2.0) had support for writing,
-via <function>write</function>, and configuration and statistics
-reporting via <function>ioctl</function>.</para>
-
-<para>The printer driver could be used on any computer that had an IBM
-PC-compatible parallel port.  Because some architectures have parallel
-ports that aren't really the same as PC-style ports, other variants of
-the printer driver were written in order to support Amiga and Atari
-parallel ports.</para>
-
-<para>When the Iomega Zip drive was released, and a driver written for
-it, a problem became apparent.  The Zip drive is a parallel port
-device that provides a parallel port of its own---it is designed to
-sit between a computer and an attached printer, with the printer
-plugged into the Zip drive, and the Zip drive plugged into the
-computer.</para>
-
-<para>The problem was that, although printers and Zip drives were both
-supported, for any given port only one could be used at a time.  Only
-one of the two drivers could be present in the kernel at once.  This
-was because of the fact that both drivers wanted to drive the same
-hardware---the parallel port.  When the printer driver initialised, it
-would call the <function>check_region</function> function to make sure
-that the IO region associated with the parallel port was free, and
-then it would call <function>request_region</function> to allocate it.
-The Zip drive used the same mechanism.  Whichever driver initialised
-first would gain exclusive control of the parallel port.</para>
-
-<para>The only way around this problem at the time was to make sure
-that both drivers were available as loadable kernel modules.  To use
-the printer, load the printer driver module; then for the Zip drive,
-unload the printer driver module and load the Zip driver
-module.</para>
-
-<para>The net effect was that printing a document that was stored on a Zip
-drive was a bit of an ordeal, at least if the Zip drive and printer
-shared a parallel port.  A better solution was needed.</para>
-
-<para>Zip drives are not the only devices that presented problems for
-Linux.  There are other devices with pass-through ports, for example
-parallel port CD-ROM drives.  There are also printers that report
-their status textually rather than using simple error pins: sending a
-command to the printer can cause it to report the number of pages that
-it has ever printed, or how much free memory it has, or whether it is
-running out of toner, and so on.  The printer driver didn't originally
-offer any facility for reading back this information (although Carsten
-Gross added nibble mode readback support for kernel 2.2).</para>
-
-<!-- IEEE 1284 transfer modes: no advanced modes --> 
-
-<para>The IEEE has issued a standards document called IEEE 1284, which
-documents existing practice for parallel port communications in a
-variety of modes.  Those modes are: <quote>compatibility</quote>,
-reverse nibble, reverse byte, ECP and EPP.  Newer devices often use
-the more advanced modes of transfer (ECP and EPP).  In Linux 2.0, the
-printer driver only supported <quote>compatibility mode</quote>
-(i.e. normal printer protocol) and reverse nibble mode.</para>
+   <para>
+    The IEEE has issued a standards document called IEEE 1284, which
+    documents existing practice for parallel port communications in a
+    variety of modes.  Those modes are: <quote>compatibility</quote>,
+    reverse nibble, reverse byte, ECP and EPP.  Newer devices often
+    use the more advanced modes of transfer (ECP and EPP).  In Linux
+    2.0, the printer driver only supported <quote>compatibility
+    mode</quote> (i.e. normal printer protocol) and reverse nibble
+    mode.
+   </para>
 
-</sect1>
+  </sect1>
 
-<sect1>
-<title>The solutions</title>
+  <sect1>
+   <title>The solutions</title>
 
 <!-- How they are addressed
      - sharing model
@@ -143,104 +151,131 @@
      - whether or not 'platform independence' goal was met
   -->
 
-<para>The <filename>parport</filename> code in Linux 2.2 was designed
-to meet these problems of architectural differences in parallel ports,
-of port-sharing between devices with pass-through ports, and of lack
-of support for IEEE 1284 transfer modes.</para>
-
-<!-- platform differences -->
-
-<para>There are two layers to the
-<filename>parport</filename> subsystem, only one of which deals
-directly with the hardware.  The other layer deals with sharing and
-IEEE 1284 transfer modes.  In this way, parallel support for a
-particular architecture comes in the form of a module which registers
-itself with the generic sharing layer.</para>
-
-<!-- sharing model -->
-
-<para>The sharing model provided by the <filename>parport</filename>
-subsystem is one of exclusive access.  A device driver, such as the
-printer driver, must ask the <filename>parport</filename> layer for
-access to the port, and can only use the port once access has been
-granted.  When it has finished a <quote>transaction</quote>, it can
-tell the <filename>parport</filename> layer that it may release the
-port for other device drivers to use.</para>
-
-<!-- talk a bit about how drivers can share devices on the same port -->
-
-<para>Devices with pass-through ports all manage to share a parallel
-port with other devices in generally the same way.  The device has a
-latch for each of the pins on its pass-through port.  The normal state
-of affairs is pass-through mode, with the device copying the signal
-lines between its host port and its pass-through port.  When the
-device sees a special signal from the host port, it latches the
-pass-through port so that devices further downstream don't get
-confused by the pass-through device's conversation with the host
-parallel port: the device connected to the pass-through port (and any
-devices connected in turn to it) are effectively cut off from the
-computer.  When the pass-through device has completed its transaction
-with the computer, it enables the pass-through port again.</para>
-
-<mediaobject>
-<imageobject>
-<imagedata Align=center scalefit=1 fileref="parport-share.eps">
-</imageobject>
-</mediaobject>
-
-<para>This technique relies on certain <quote>special signals</quote>
-being invisible to devices that aren't watching for them.  This tends
-to mean only changing the data signals and leaving the control signals
-alone.  IEEE 1284.3 documents a standard protocol for daisy-chaining
-devices together with parallel ports.</para>
-
-<!-- transfer modes -->
-
-<para>Support for standard transfer modes are provided as operations
-that can be performed on a port, along with operations for setting the
-data lines, or the control lines, or reading the status lines.  These
-operations appear to the device driver as function pointers; more
-later.</para>
-
-</sect1>
-
-</chapter>
-
-<chapter id="transfermodes">
-<title>Standard transfer modes</title>
-
-<!-- Defined by IEEE, but in common use (even though there are widely -->
-<!-- varying implementations). -->
-
-<para>The <quote>standard</quote> transfer modes in use over the
-parallel port are <quote>defined</quote> by a document called IEEE
-1284.  It really just codifies existing practice and documents
-protocols (and variations on protocols) that have been in common use
-for quite some time.</para>
-
-<para>The original definitions of which pin did what were set out by
-Centronics Data Computer Corporation, but only the printer-side
-interface signals were specified.</para>
-
-<para>By the early 1980s, IBM's host-side implementation had become
-the most widely used.  New printers emerged that claimed Centronics
-compatibility, but although compatible with Centronics they differed
-from one another in a number of ways.</para>
-
-<para>As a result of this, when IEEE 1284 was published in 1994, all
-that it could really do was document the various protocols that are
-used for printers (there are about six variations on a theme).</para>
-
-<para>In addition to the protocol used to talk to
-Centronics-compatible printers, IEEE 1284 defined other protocols that
-are used for unidirectional peripheral-to-host transfers (reverse
-nibble and reverse byte) and for fast bidirectional transfers (ECP and
-EPP).</para>
+   <para>
+    The <literal>parport</literal> code in Linux 2.2 was designed to
+    meet these problems of architectural differences in parallel
+    ports, of port-sharing between devices with pass-through ports,
+    and of lack of support for IEEE 1284 transfer modes.
+   </para>
 
-</chapter>
+   <!-- platform differences -->
+
+   <para>
+    There are two layers to the <literal>parport</literal>
+    subsystem, only one of which deals directly with the hardware.
+    The other layer deals with sharing and IEEE 1284 transfer modes.
+    In this way, parallel support for a particular architecture comes
+    in the form of a module which registers itself with the generic
+    sharing layer.
+   </para>
 
-<chapter id="structure">
-<title>Structure</title>
+   <!-- sharing model -->
+
+   <para>
+    The sharing model provided by the <literal>parport</literal>
+    subsystem is one of exclusive access.  A device driver, such as
+    the printer driver, must ask the <literal>parport</literal>
+    layer for access to the port, and can only use the port once
+    access has been granted.  When it has finished a
+    <quote>transaction</quote>, it can tell the
+    <literal>parport</literal> layer that it may release the port
+    for other device drivers to use.
+   </para>
+
+   <!-- talk a bit about how drivers can share devices on the same port -->
+
+   <para>
+    Devices with pass-through ports all manage to share a parallel
+    port with other devices in generally the same way.  The device has
+    a latch for each of the pins on its pass-through port.  The normal
+    state of affairs is pass-through mode, with the device copying the
+    signal lines between its host port and its pass-through port.
+    When the device sees a special signal from the host port, it
+    latches the pass-through port so that devices further downstream
+    don't get confused by the pass-through device's conversation with
+    the host parallel port: the device connected to the pass-through
+    port (and any devices connected in turn to it) are effectively cut
+    off from the computer.  When the pass-through device has completed
+    its transaction with the computer, it enables the pass-through
+    port again.
+   </para>
+
+   <mediaobject>
+    <imageobject>
+     <imagedata fileref="parport-share.eps" format=ps>
+    </imageobject>
+    <imageobject>
+     <imagedata fileref="parport-share.jpeg" format=jpeg>
+    </imageobject>
+   </mediaobject>
+
+   <para>
+    This technique relies on certain <quote>special signals</quote>
+    being invisible to devices that aren't watching for them.  This
+    tends to mean only changing the data signals and leaving the
+    control signals alone.  IEEE 1284.3 documents a standard protocol
+    for daisy-chaining devices together with parallel ports.
+   </para>
+
+   <!-- transfer modes -->
+
+   <para>
+    Support for standard transfer modes are provided as operations
+    that can be performed on a port, along with operations for setting
+    the data lines, or the control lines, or reading the status lines.
+    These operations appear to the device driver as function pointers;
+    more later.
+   </para>
+
+  </sect1>
+
+ </chapter>
+
+ <chapter id="transfermodes">
+  <title>Standard transfer modes</title>
+
+  <!-- Defined by IEEE, but in common use (even though there are widely -->
+  <!-- varying implementations). -->
+
+  <para>
+   The <quote>standard</quote> transfer modes in use over the parallel
+   port are <quote>defined</quote> by a document called IEEE 1284.  It
+   really just codifies existing practice and documents protocols (and
+   variations on protocols) that have been in common use for quite
+   some time.
+  </para>
+
+  <para>
+   The original definitions of which pin did what were set out by
+   Centronics Data Computer Corporation, but only the printer-side
+   interface signals were specified.
+  </para>
+
+  <para>
+   By the early 1980s, IBM's host-side implementation had become the
+   most widely used.  New printers emerged that claimed Centronics
+   compatibility, but although compatible with Centronics they
+   differed from one another in a number of ways.
+  </para>
+
+  <para>
+   As a result of this, when IEEE 1284 was published in 1994, all that
+   it could really do was document the various protocols that are used
+   for printers (there are about six variations on a theme).
+  </para>
+
+  <para>
+   In addition to the protocol used to talk to Centronics-compatible
+   printers, IEEE 1284 defined other protocols that are used for
+   unidirectional peripheral-to-host transfers (reverse nibble and
+   reverse byte) and for fast bidirectional transfers (ECP and
+   EPP).
+  </para>
+
+ </chapter>
+
+ <chapter id="structure">
+  <title>Structure</title>
 
 <!-- Main structure
      - sharing core
@@ -251,240 +286,288 @@
      - IEEE 1284.3 API
   -->
 
-<!-- Diagram -->
+  <mediaobject>
+   <imageobject>
+    <imagedata format=eps fileref="parport-structure.eps">
+   </imageobject>
+   <imageobject>
+    <imagedata format=jpeg fileref="parport-structure.jpeg">
+   </imageobject>
+  </mediaobject>
+
+  <sect1>
+   <title>Sharing core</title>
+
+   <para>
+    At the core of the <literal>parport</literal> subsystem is the
+    sharing mechanism (see
+    <filename>drivers/parport/share.c</filename>).  This module,
+    <literal>parport</literal>, is responsible for keeping track of
+    which ports there are in the system, which device drivers might be
+    interested in new ports, and whether or not each port is available
+    for use (or if not, which driver is currently using it).
+   </para>
+
+  </sect1>
+
+  <sect1>
+   <title>Parports and their overrides</title>
+
+   <para>
+    The generic <literal>parport</literal> sharing code doesn't
+    directly handle the parallel port hardware.  That is done instead
+    by <quote>low-level</quote> <literal>parport</literal> drivers.
+    The function of a low-level <literal>parport</literal> driver is
+    to detect parallel ports, register them with the sharing code, and
+    provide a list of access functions for each port.
+   </para>
+
+   <para>
+    The most basic access functions that must be provided are ones for
+    examining the status lines, for setting the control lines, and for
+    setting the data lines.  There are also access functions for
+    setting the direction of the data lines; normally they are in the
+    <quote>forward</quote> direction (that is, the computer drives
+    them), but some ports allow switching to <quote>reverse</quote>
+    mode (driven by the peripheral).  There is an access function for
+    examining the data lines once in reverse mode.
+   </para>
+
+  </sect1>
+
+  <sect1>
+   <title>IEEE 1284 transfer modes</title>
+
+   <para>
+    Stacked on top of the sharing mechanism, but still in the
+    <literal>parport</literal> module, are functions for
+    transferring data.  They are provided for the device drivers to
+    use, and are very much like library routines.  Since these
+    transfer functions are provided by the generic
+    <literal>parport</literal> core they must use the <quote>lowest
+    common denominator</quote> set of access functions: they can set
+    the control lines, examine the status lines, and use the data
+    lines.  With some parallel ports the data lines can only be set
+    and not examined, and with other ports accessing the data register
+    causes control line activity; with these types of situations, the
+    IEEE 1284 transfer functions make a best effort attempt to do the
+    right thing.  In some cases, it is not physically possible to use
+    particular IEEE 1284 transfer modes.
+   </para>
+
+   <para>
+    The low-level <literal>parport</literal> drivers also provide
+    IEEE 1284 transfer functions, as names in the access function
+    list.  The low-level driver can just name the generic IEEE 1284
+    transfer functions for this.  Some parallel ports can do IEEE 1284
+    transfers in hardware; for those ports, the low-level driver can
+    provide functions to utilise that feature.
+   </para>
+
+  </sect1>
+
+  <!-- muxes? -->
+
+  <sect1>
+   <title>Pardevices and parport_drivers</title>
+
+   <para>
+    When a parallel port device driver (such as
+    <literal>lp</literal>) initialises it tells the sharing layer
+    about itself using <function>parport_register_driver</function>.
+    The information is put into a <structname>struct
+    parport_driver</structname>, which is put into a linked list.  The
+    information in a <structname>struct parport_driver</structname>
+    really just amounts to some function pointers to callbacks in the
+    parallel port device driver.
+   </para>
+
+   <para>
+    During its initialisation, a low-level port driver tells the
+    sharing layer about all the ports that it has found (using
+    <function>parport_register_port</function>), and the sharing layer
+    creates a <structname>struct parport</structname> for each of
+    them.  Each <structname>struct parport</structname> contains
+    (among other things) a pointer to a <structname>struct
+    parport_operations</structname>, which is a list of function
+    pointers for the various operations that can be performed on a
+    port.  You can think of a <structname>struct parport</structname>
+    as a parallel port <quote>object</quote>, if
+    <quote>object-orientated</quote> programming is your thing.  The
+    <structname>parport</structname> structures are chained in a
+    linked list, whose head is <varname>portlist</varname> (in
+    <filename>drivers/parport/share.c</filename>).
+   </para>
+
+   <para>
+    Once the port has been registered, the low-level port driver
+    announces it.  The <function>parport_announce_port</function>
+    function walks down the list of parallel port device drivers
+    (<structname>struct parport_driver</structname>s) calling the
+    <function>attach</function> function of each.
+   </para>
+
+   <para>
+    Similarly, a low-level port driver can undo the effect of
+    registering a port with the
+    <function>parport_unregister_port</function> function, and device
+    drivers are notified using the <function>detach</function>
+    callback.
+   </para>
+
+   <para>
+    Device drivers can undo the effect of registering themselves with
+    the <function>parport_unregister_driver</function>
+    function.
+   </para>
+
+  </sect1>
+
+  <!-- IEEE 1284.3 API -->
+
+  <sect1>
+   <title>The IEEE 1284.3 API</title>
+
+   <para>
+    The ability to daisy-chain devices is very useful, but if every
+    device does it in a different way it could lead to lots of
+    complications for device driver writers.  Fortunately, the IEEE
+    are standardising it in IEEE 1284.3, which covers daisy-chain
+    devices and port multiplexors.
+   </para>
+
+   <para>
+    At the time of writing, IEEE 1284.3 has not been published, but
+    the draft specifies the on-the-wire protocol for daisy-chaining
+    and multiplexing, and also suggests a programming interface for
+    using it.  That interface (or most of it) has been implemented in
+    the <literal>parport</literal> code in Linux.
+   </para>
+
+   <para>
+    At initialisation of the parallel port <quote>bus</quote>,
+    daisy-chained devices are assigned addresses starting from zero.
+    There can only be four devices with daisy-chain addresses, plus
+    one device on the end that doesn't know about daisy-chaining and
+    thinks it's connected directly to a computer.
+   </para>
+
+   <para>
+    Another way of connecting more parallel port devices is to use a
+    multiplexor.  The idea is to have a device that is connected
+    directly to a parallel port on a computer, but has a number of
+    parallel ports on the other side for other peripherals to connect
+    to (two or four ports are allowed).  The multiplexor switches
+    control to different ports under software control---it is, in
+    effect, a programmable printer switch.
+   </para>
+
+   <para>
+    Combining the ability of daisy-chaining five devices together with
+    the ability to multiplex one parallel port between four gives the
+    potential to have twenty peripherals connected to the same
+    parallel port!
+   </para>
+
+   <para>
+    In addition, of course, a single computer can have multiple
+    parallel ports.  So, each parallel port peripheral in the system
+    can be identified with three numbers, or co-ordinates: the
+    parallel port, the multiplexed port, and the daisy-chain
+    address.
+   </para>
+
+   <mediaobject>
+    <imageobject>
+     <imagedata format=eps fileref="parport-multi.eps">
+    </imageobject>
+    <imageobject>
+     <imagedata format=jpeg fileref="parport-multi.jpeg">
+    </imageobject>
+   </mediaobject>
+
+   <para>
+    Each device in the system is numbered at initialisation (by
+    <function>parport_daisy_init</function>).  You can convert between
+    this device number and its co-ordinates with
+    <function>parport_device_num</function> and
+    <function>parport_device_coords</function>.
+   </para>
+
+   <funcsynopsis>
+    <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+    </funcsynopsisinfo>
+    <funcprototype>
+     <funcdef>int <function>parport_device_num</function></funcdef>
+     <paramdef>int <parameter>parport</parameter></paramdef>
+     <paramdef>int <parameter>mux</parameter></paramdef>
+     <paramdef>int <parameter>daisy</parameter></paramdef>
+    </funcprototype>
+   </funcsynopsis>
+
+   <funcsynopsis>
+    <funcprototype>
+     <funcdef>int <function>parport_device_coords</function></funcdef>
+     <paramdef>int <parameter>devnum</parameter></paramdef>
+     <paramdef>int *<parameter>parport</parameter></paramdef>
+     <paramdef>int *<parameter>mux</parameter></paramdef>
+     <paramdef>int *<parameter>daisy</parameter></paramdef>
+    </funcprototype>
+   </funcsynopsis>
+
+   <para>
+    Any parallel port peripheral will be connected directly or
+    indirectly to a parallel port on the system, but it won't have a
+    daisy-chain address if it does not know about daisy-chaining, and
+    it won't be connected through a multiplexor port if there is no
+    multiplexor.  The special co-ordinate value
+    <constant>-1</constant> is used to indicate these cases.
+   </para>
+
+   <para>
+    Two functions are provided for finding devices based on their IEEE
+    1284 Device ID: <function>parport_find_device</function> and
+    <function>parport_find_class</function>.
+   </para>
 
-<mediaobject>
-<imageobject>
-<imagedata Align=Center ScaleFit=1 fileref="parport-structure.eps">
-</imageobject>
-</mediaobject>
-
-<sect1>
-<title>Sharing core</title>
-
-<!-- sharing core -->
-
-<para>At the core of the <filename>parport</filename> subsystem is the
-sharing mechanism (see <filename>drivers/parport/share.c</filename>).
-This module, <filename>parport</filename>, is responsible for
-keeping track of which ports there are in the system, which device
-drivers might be interested in new ports, and whether or not each port
-is available for use (or if not, which driver is currently using
-it).</para>
-
-</sect1>
-
-<sect1>
-<title>Parports and their overrides</title>
-<!-- parports and their overrides -->
-
-<para>The generic <filename>parport</filename> sharing code doesn't
-directly handle the parallel port hardware.  That is done instead by
-<quote>low-level</quote> <filename>parport</filename> drivers.  The
-function of a low-level <filename>parport</filename> driver is to
-detect parallel ports, register them with the sharing code, and
-provide a list of access functions for each port.</para>
-
-<para>The most basic access functions that must be provided are ones
-for examining the status lines, for setting the control lines, and for
-setting the data lines.  There are also access functions for setting
-the direction of the data lines; normally they are in the
-<quote>forward</quote> direction (that is, the computer drives them),
-but some ports allow switching to <quote>reverse</quote> mode (driven
-by the peripheral).  There is an access function for examining the
-data lines once in reverse mode.</para>
-
-</sect1>
-
-<sect1>
-<title>IEEE 1284 transfer modes</title>
-<!-- IEEE 1284 transfer modes -->
-
-<para>Stacked on top of the sharing mechanism, but still in the
-<filename>parport</filename> module, are functions for transferring
-data.  They are provided for the device drivers to use, and are very
-much like library routines.  Since these transfer functions are
-provided by the generic <filename>parport</filename> core they must
-use the <quote>lowest common denominator</quote> set of access
-functions: they can set the control lines, examine the status lines,
-and use the data lines.  With some parallel ports the data lines can
-only be set and not examined, and with other ports accessing the data
-register causes control line activity; with these types of situations,
-the IEEE 1284 transfer functions make a best effort attempt to do the
-right thing.  In some cases, it is not physically possible to use
-particular IEEE 1284 transfer modes.</para>
-
-<para>The low-level <filename>parport</filename> drivers also provide
-IEEE 1284 transfer functions, as names in the access function list.
-The low-level driver can just name the generic IEEE 1284 transfer
-functions for this.  Some parallel ports can do IEEE 1284 transfers in
-hardware; for those ports, the low-level driver can provide functions
-to utilise that feature.</para>
-
-</sect1>
-
-<!-- muxes? -->
-
-<!-- pardevices and pardrivers -->
-
-<sect1>
-<title>Pardevices and parport_drivers</title>
-
-<para>When a parallel port device driver (such as
-<filename>lp</filename>) initialises it tells the sharing layer about
-itself using <function>parport_register_driver</function>.  The
-information is put into a <structname>struct
-parport_driver</structname>, which is put into a linked list.  The
-information in a <structname>struct parport_driver</structname> really
-just amounts to some function pointers to callbacks in the parallel
-port device driver.</para>
-
-<para>During its initialisation, a low-level port driver tells the
-sharing layer about all the ports that it has found (using
-<function>parport_register_port</function>), and the sharing layer
-creates a <structname>struct parport</structname> for each of them.
-Each <structname>struct parport</structname> contains (among other
-things) a pointer to a <structname>struct
-parport_operations</structname>, which is a list of function pointers
-for the various operations that can be performed on a port.  You can
-think of a <structname>struct parport</structname> as a parallel port
-<quote>object</quote>, if <quote>object-orientated</quote> programming
-is your thing.  The <structname>parport</structname> structures are
-chained in a linked list, whose head is <varname>portlist</varname>
-(in <filename>drivers/parport/share.c</filename>).</para>
-
-<para>Once the port has been registered, the low-level port driver
-announces it.  The <function>parport_announce_port</function> function
-walks down the list of parallel port device drivers
-(<structname>struct parport_driver</structname>s) calling the
-<function>attach</function> function of each.</para>
-
-<para>Similarly, a low-level port driver can undo the effect of
-registering a port with the
-<function>parport_unregister_port</function> function, and device
-drivers are notified using the <function>detach</function>
-callback.</para>
-
-<para>Device drivers can undo the effect of registering themselves
-with the <function>parport_unregister_driver</function>
-function.</para>
-
-</sect1>
-
-<!-- IEEE 1284.3 API -->
-
-<sect1>
-<title>The IEEE 1284.3 API</title>
-
-<para>The ability to daisy-chain devices is very useful, but if every
-device does it in a different way it could lead to lots of
-complications for device driver writers.  Fortunately, the IEEE are
-standardising it in IEEE 1284.3, which covers daisy-chain devices and
-port multiplexors.</para>
-
-<para>At the time of writing, IEEE 1284.3 has not been published, but
-the draft specifies the on-the-wire protocol for daisy-chaining and
-multiplexing, and also suggests a programming interface for using it.
-That interface (or most of it) has been implemented in the
-<filename>parport</filename> code in Linux.</para>
-
-<para>At initialisation of the parallel port <quote>bus</quote>, daisy-chained
-devices are assigned addresses starting from zero.  There can only be
-four devices with daisy-chain addresses, plus one device on the end
-that doesn't know about daisy-chaining and thinks it's connected
-directly to a computer.</para>
-
-<para>Another way of connecting more parallel port devices is to use a
-multiplexor.  The idea is to have a device that is connected directly
-to a parallel port on a computer, but has a number of parallel ports
-on the other side for other peripherals to connect to (two or four
-ports are allowed).  The multiplexor switches control to different
-ports under software control---it is, in effect, a programmable
-printer switch.</para>
-
-<para>Combining the ability of daisy-chaining five devices together
-with the ability to multiplex one parallel port between four gives the
-potential to have twenty peripherals connected to the same parallel
-port!</para>
-
-<para>In addition, of course, a single computer can have multiple
-parallel ports.  So, each parallel port peripheral in the system can
-be identified with three numbers, or co-ordinates: the parallel port,
-the multiplexed port, and the daisy-chain address.</para>
-
-<mediaobject>
-<imageobject>
-<imagedata align=center scalefit=1 fileref="parport-multi.eps">
-</imageobject>
-</mediaobject>
-
-<!-- x parport_open -->
-<!-- x parport_close -->
-<!-- x parport_device_id -->
-<!-- x parport_device_num -->
-<!-- x parport_device_coords -->
-<!-- x parport_find_device -->
-<!-- x parport_find_class -->
-
-<para>Each device in the system is numbered at initialisation (by
-<function>parport_daisy_init</function>).  You can convert between
-this device number and its co-ordinates with
-<function>parport_device_num</function> and
-<function>parport_device_coords</function>.</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_device_num</function></funcdef>
-  <paramdef>int <parameter>parport</parameter></paramdef>
-  <paramdef>int <parameter>mux</parameter></paramdef>
-  <paramdef>int <parameter>daisy</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_device_coords</function></funcdef>
-  <paramdef>int <parameter>devnum</parameter></paramdef>
-  <paramdef>int *<parameter>parport</parameter></paramdef>
-  <paramdef>int *<parameter>mux</parameter></paramdef>
-  <paramdef>int *<parameter>daisy</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>Any parallel port peripheral will be connected directly or
-indirectly to a parallel port on the system, but it won't have a
-daisy-chain address if it does not know about daisy-chaining, and it
-won't be connected through a multiplexor port if there is no
-multiplexor.  The special co-ordinate value <constant>-1</constant> is
-used to indicate these cases.</para>
-
-<para>Two functions are provided for finding devices based on their
-IEEE 1284 Device ID: <function>parport_find_device</function> and
-<function>parport_find_class</function>.</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_find_device</function></funcdef>
-  <paramdef>const char *<parameter>mfg</parameter></paramdef>
-  <paramdef>const char *<parameter>mdl</parameter></paramdef>
-  <paramdef>int <parameter>from</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_find_class</function></funcdef>
-  <paramdef>parport_device_class <parameter>cls</parameter></paramdef>
-  <paramdef>int <parameter>from</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>These functions take a device number (in addition to some other
-things), and return another device number.  They walk through the list
-of detected devices until they find one that matches the requirements,
-and then return that device number (or <constant>-1</constant> if
-there are no more such devices).  They start their search at the
-device after the one in the list with the number given (at
-<parameter>from</parameter>+1, in other words).</para>
+   <funcsynopsis>
+    <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+    </funcsynopsisinfo>
+    <funcprototype>
+     <funcdef>int <function>parport_find_device</function></funcdef>
+     <paramdef>const char *<parameter>mfg</parameter></paramdef>
+     <paramdef>const char *<parameter>mdl</parameter></paramdef>
+     <paramdef>int <parameter>from</parameter></paramdef>
+    </funcprototype>
+   </funcsynopsis>
+
+   <funcsynopsis>
+    <funcprototype>
+     <funcdef>int <function>parport_find_class</function></funcdef>
+     <paramdef>parport_device_class <parameter>cls</parameter></paramdef>
+     <paramdef>int <parameter>from</parameter></paramdef>
+    </funcprototype>
+   </funcsynopsis>
 
-</sect1>
+   <para>
+    These functions take a device number (in addition to some other
+    things), and return another device number.  They walk through the
+    list of detected devices until they find one that matches the
+    requirements, and then return that device number (or
+    <constant>-1</constant> if there are no more such devices).  They
+    start their search at the device after the one in the list with
+    the number given (at <parameter>from</parameter>+1, in other
+    words).
+   </para>
 
-</chapter>
+  </sect1>
 
-<chapter id="drivers">
-<title>Device driver's view</title>
+ </chapter>
+
+ <chapter id="drivers">
+  <title>Device driver's view</title>
 
 <!-- Cover:
      - sharing interface, preemption, interrupts, wakeups...
@@ -499,1040 +582,1367 @@
 <!-- driver' should deal with that later; might be worth mentioning -->
 <!-- in the text. -->
 
-<para>This section is written from the point of view of the device
-driver programmer, who might be writing a driver for a printer or a
-scanner or else anything that plugs into the parallel port.  It
-explains how to use the <filename>parport</filename> interface to find
-parallel ports, use them, and share them with other device
-drivers.</para>
-
-<para>We'll start out with a description of the various functions that
-can be called, and then look at a reasonably simple example of their
-use: the printer driver.</para>
-
-<para>The interactions between the device driver and the
-<filename>parport</filename> layer are as follows.  First, the device
-driver registers its existence with <filename>parport</filename>, in
-order to get told about any parallel ports that have been (or will be)
-detected.  When it gets told about a parallel port, it then tells
-<filename>parport</filename> that it wants to drive a device on that
-port.  Thereafter it can claim exclusive access to the port in order
-to talk to its device.</para>
-
-<para>So, the first thing for the device driver to do is tell
-<filename>parport</filename> that it wants to know what parallel ports
-are on the system.  To do this, it uses the
-<function>parport_register_device</function> function:</para>
+  <para>
+   This section is written from the point of view of the device driver
+   programmer, who might be writing a driver for a printer or a
+   scanner or else anything that plugs into the parallel port.  It
+   explains how to use the <literal>parport</literal> interface to
+   find parallel ports, use them, and share them with other device
+   drivers.
+  </para>
+
+  <para>
+   We'll start out with a description of the various functions that
+   can be called, and then look at a reasonably simple example of
+   their use: the printer driver.
+  </para>
+
+  <para>
+   The interactions between the device driver and the
+   <literal>parport</literal> layer are as follows.  First, the
+   device driver registers its existence with
+   <literal>parport</literal>, in order to get told about any
+   parallel ports that have been (or will be) detected.  When it gets
+   told about a parallel port, it then tells
+   <literal>parport</literal> that it wants to drive a device on
+   that port.  Thereafter it can claim exclusive access to the port in
+   order to talk to its device.
+  </para>
+
+  <para>
+   So, the first thing for the device driver to do is tell
+   <literal>parport</literal> that it wants to know what parallel
+   ports are on the system.  To do this, it uses the
+   <function>parport_register_device</function> function:
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
 
-<programlisting>
-<![CDATA[
 struct parport_driver {
         const char *name;
         void (*attach) (struct parport *);
         void (*detach) (struct parport *);
         struct parport_driver *next;
 };
-]]></programlisting>
+   </funcsynopsisinfo>
 
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_register_driver</function></funcdef>
-  <paramdef>struct parport_driver *<parameter>driver</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>In other words, the device driver passes pointers to a couple of
-functions to <filename>parport</filename>, and
-<filename>parport</filename> calls <function>attach</function> for
-each port that's detected (and <function>detach</function> for each
-port that disappears -- yes, this can happen).</para>
-
-<para>The next thing that happens is that the device driver tells
-<filename>parport</filename> that it thinks there's a device on the
-port that it can drive.  This typically will happen in the driver's
-<function>attach</function> function, and is done with
-<function>parport_register_device</function>:</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>struct pardevice *<function>parport_register_device</function></funcdef>
-  <paramdef>struct parport *<parameter>port</parameter></paramdef>
-  <paramdef>const char *<parameter>name</parameter></paramdef>
-  <paramdef>int <parameter>(*pf)</parameter>
-    <funcparams>void *</funcparams></paramdef>
-  <paramdef>void <parameter>(*kf)</parameter>
-    <funcparams>void *</funcparams></paramdef>
-  <paramdef>void <parameter>(*irq_func)</parameter>
-    <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>
-  <paramdef>int <parameter>flags</parameter></paramdef>
-  <paramdef>void *<parameter>handle</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>The <parameter>port</parameter> comes from the parameter supplied
-to the <function>attach</function> function when it is called, or
-alternatively can be found from the list of detected parallel ports
-directly with the (now deprecated)
-<function>parport_enumerate</function> function.</para>
-
-<para>The next three parameters, <parameter>pf</parameter>,
-<parameter>kf</parameter>, and <parameter>irq_func</parameter>, are
-more function pointers.  These callback functions get called under
-various circumstances, and are always given the
-<parameter>handle</parameter> as one of their parameters.</para>
-
-<para>The preemption callback, <parameter>pf</parameter>, is called
-when the driver has claimed access to the port but another device
-driver wants access.  If the driver is willing to let the port go, it
-should return zero and the port will be released on its behalf.  There
-is no need to call <function>parport_release</function>.  If
-<parameter>pf</parameter> gets called at a bad time for letting the
-port go, it should return non-zero and no action will be taken.  It is
-good manners for the driver to try to release the port at the earliest
-opportunity after its preemption callback is called.</para>
-
-<para>The <quote>kick</quote> callback, <parameter>kf</parameter>, is
-called when the port can be claimed for exclusive access; that is,
-<function>parport_claim</function> is guaranteed to succeed inside the
-<quote>kick</quote> callback.  If the driver wants to claim the port
-it should do so; otherwise, it need not take any action.</para>
-
-<para>The <parameter>irq_func</parameter> callback is called,
-predictably, when a parallel port interrupt is generated.  But it is
-not the only code that hooks on the interrupt.  The sequence is this:
-the lowlevel driver is the one that has done
-<function>request_irq</function>; it then does whatever
-hardware-specific things it needs to do to the parallel port hardware
-(for PC-style ports, there is nothing special to do); it then tells
-the IEEE 1284 code about the interrupt, which may involve reacting to
-an IEEE 1284 event, depending on the current IEEE 1284 phase; and
-finally the <parameter>irq_func</parameter> function is called.</para>
-
-<para>None of the callback functions are allowed to block.</para>
-
-<para>The <parameter>flags</parameter> are for telling
-<filename>parport</filename> any requirements or hints that are
-useful.  The only useful value here (other than
-<constant>0</constant>, which is the usual value) is
-<constant>PARPORT_DEV_EXCL</constant>.  The point of that flag is to
-request exclusive access at all times---once a driver has successfully
-called <function>parport_register_device</function> with that flag, no
-other device drivers will be able to register devices on that port
-(until the successful driver deregisters its device, of
-course).</para>
-
-<para>The <constant>PARPORT_DEV_EXCL</constant> flag is for preventing
-port sharing, and so should only be used when sharing the port with
-other device drivers is impossible and would lead to incorrect
-behaviour.  Use it sparingly!</para>
-
-<para>Devices can also be registered by device drivers based on their
-device numbers (the same device numbers as in the previous
-section).</para>
-
-<para>The <function>parport_open</function> function is similar to
-<function>parport_register_device</function>, and
-<function>parport_close</function> is the equivalent of
-<function>parport_unregister_device</function>.  The difference is
-that <function>parport_open</function> takes a device number rather
-than a pointer to a <structname>struct parport</structname>.</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>struct pardevice *<function>parport_open</function></funcdef>
-  <paramdef>int <parameter>devnum</parameter></paramdef>
-  <paramdef>int <parameter>(*pf)</parameter>
-    <funcparams>void *</funcparams></paramdef>
-  <paramdef>int <parameter>(*kf)</parameter>
-    <funcparams>void *</funcparams></paramdef>
-  <paramdef>int <parameter>(*irqf)</parameter>
-    <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>
-  <paramdef>int <parameter>flags</parameter></paramdef>
-  <paramdef>void *<parameter>handle</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>void <function>parport_close</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>struct pardevice *<function>parport_register_device</function></funcdef>
-  <paramdef>struct parport *<parameter>port</parameter></paramdef>
-  <paramdef>const char *<parameter>name</parameter></paramdef>
-  <paramdef>int <parameter>(*pf)</parameter>
-    <funcparams>void *</funcparams></paramdef>
-  <paramdef>int <parameter>(*kf)</parameter>
-    <funcparams>void *</funcparams></paramdef>
-  <paramdef>int <parameter>(*irqf)</parameter>
-    <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>
-  <paramdef>int <parameter>flags</parameter></paramdef>
-  <paramdef>void *<parameter>handle</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>void <function>parport_unregister_device</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>The intended use of these functions is during driver
-initialisation while the driver looks for devices that it supports, as
-demonstrated by the following code fragment:</para>
+   <funcprototype>
+    <funcdef>int <function>parport_register_driver</function></funcdef>
+    <paramdef>struct parport_driver *<parameter>driver</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   In other words, the device driver passes pointers to a couple of
+   functions to <literal>parport</literal>, and
+   <literal>parport</literal> calls <function>attach</function> for
+   each port that's detected (and <function>detach</function> for each
+   port that disappears---yes, this can happen).
+  </para>
+
+  <para>
+   The next thing that happens is that the device driver tells
+   <literal>parport</literal> that it thinks there's a device on the
+   port that it can drive.  This typically will happen in the driver's
+   <function>attach</function> function, and is done with
+   <function>parport_register_device</function>:
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+   </funcsynopsisinfo>
+   <funcprototype>
+    <funcdef>struct pardevice *<function>parport_register_device</function></funcdef>
+    <paramdef>struct parport *<parameter>port</parameter></paramdef>
+    <paramdef>const char *<parameter>name</parameter></paramdef>
+    <paramdef>int <parameter>(*pf)</parameter>
+     <funcparams>void *</funcparams></paramdef>
+    <paramdef>void <parameter>(*kf)</parameter>
+     <funcparams>void *</funcparams></paramdef>
+    <paramdef>void <parameter>(*irq_func)</parameter>
+     <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>
+    <paramdef>int <parameter>flags</parameter></paramdef>
+    <paramdef>void *<parameter>handle</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   The <parameter>port</parameter> comes from the parameter supplied
+   to the <function>attach</function> function when it is called, or
+   alternatively can be found from the list of detected parallel ports
+   directly with the (now deprecated)
+   <function>parport_enumerate</function> function.
+  </para>
+
+  <para>
+   The next three parameters, <parameter>pf</parameter>,
+   <parameter>kf</parameter>, and <parameter>irq_func</parameter>, are
+   more function pointers.  These callback functions get called under
+   various circumstances, and are always given the
+   <parameter>handle</parameter> as one of their parameters.
+  </para>
+
+  <para>
+   The preemption callback, <parameter>pf</parameter>, is called when
+   the driver has claimed access to the port but another device driver
+   wants access.  If the driver is willing to let the port go, it
+   should return zero and the port will be released on its behalf.
+   There is no need to call <function>parport_release</function>.  If
+   <parameter>pf</parameter> gets called at a bad time for letting the
+   port go, it should return non-zero and no action will be taken.  It
+   is good manners for the driver to try to release the port at the
+   earliest opportunity after its preemption callback is
+   called.
+  </para>
+
+  <para>
+   The <quote>kick</quote> callback, <parameter>kf</parameter>, is
+   called when the port can be claimed for exclusive access; that is,
+   <function>parport_claim</function> is guaranteed to succeed inside
+   the <quote>kick</quote> callback.  If the driver wants to claim the
+   port it should do so; otherwise, it need not take any
+   action.
+  </para>
+
+  <para>
+   The <parameter>irq_func</parameter> callback is called,
+   predictably, when a parallel port interrupt is generated.  But it
+   is not the only code that hooks on the interrupt.  The sequence is
+   this: the lowlevel driver is the one that has done
+   <function>request_irq</function>; it then does whatever
+   hardware-specific things it needs to do to the parallel port
+   hardware (for PC-style ports, there is nothing special to do); it
+   then tells the IEEE 1284 code about the interrupt, which may
+   involve reacting to an IEEE 1284 event, depending on the current
+   IEEE 1284 phase; and finally the <parameter>irq_func</parameter>
+   function is called.
+  </para>
+
+  <para>
+   None of the callback functions are allowed to block.
+  </para>
+
+  <para>
+   The <parameter>flags</parameter> are for telling
+   <literal>parport</literal> any requirements or hints that are
+   useful.  The only useful value here (other than
+   <constant>0</constant>, which is the usual value) is
+   <constant>PARPORT_DEV_EXCL</constant>.  The point of that flag is
+   to request exclusive access at all times---once a driver has
+   successfully called <function>parport_register_device</function>
+   with that flag, no other device drivers will be able to register
+   devices on that port (until the successful driver deregisters its
+   device, of course).
+  </para>
+
+  <para>
+   The <constant>PARPORT_DEV_EXCL</constant> flag is for preventing
+   port sharing, and so should only be used when sharing the port with
+   other device drivers is impossible and would lead to incorrect
+   behaviour.  Use it sparingly!
+  </para>
+
+  <para>
+   Devices can also be registered by device drivers based on their
+   device numbers (the same device numbers as in the previous
+   section).
+  </para>
+
+  <para>
+   The <function>parport_open</function> function is similar to
+   <function>parport_register_device</function>, and
+   <function>parport_close</function> is the equivalent of
+   <function>parport_unregister_device</function>.  The difference is
+   that <function>parport_open</function> takes a device number rather
+   than a pointer to a <structname>struct parport</structname>.
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+   </funcsynopsisinfo>
+   <funcprototype>
+    <funcdef>struct pardevice *<function>parport_open</function></funcdef>
+    <paramdef>int <parameter>devnum</parameter></paramdef>
+    <paramdef>int <parameter>(*pf)</parameter>
+     <funcparams>void *</funcparams></paramdef>
+    <paramdef>int <parameter>(*kf)</parameter>
+     <funcparams>void *</funcparams></paramdef>
+    <paramdef>int <parameter>(*irqf)</parameter>
+     <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>
+    <paramdef>int <parameter>flags</parameter></paramdef>
+    <paramdef>void *<parameter>handle</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <funcsynopsis>
+   <funcprototype>
+    <funcdef>void <function>parport_close</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <funcsynopsis>
+   <funcprototype>
+    <funcdef>struct pardevice *<function>parport_register_device</function></funcdef>
+    <paramdef>struct parport *<parameter>port</parameter></paramdef>
+    <paramdef>const char *<parameter>name</parameter></paramdef>
+    <paramdef>int <parameter>(*pf)</parameter>
+     <funcparams>void *</funcparams></paramdef>
+    <paramdef>int <parameter>(*kf)</parameter>
+     <funcparams>void *</funcparams></paramdef>
+    <paramdef>int <parameter>(*irqf)</parameter>
+     <funcparams>int, void *, struct pt_regs *</funcparams></paramdef>
+    <paramdef>int <parameter>flags</parameter></paramdef>
+    <paramdef>void *<parameter>handle</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <funcsynopsis>
+   <funcprototype>
+    <funcdef>void <function>parport_unregister_device</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   The intended use of these functions is during driver initialisation
+   while the driver looks for devices that it supports, as
+   demonstrated by the following code fragment:
+  </para>
 
-<programlisting>
-<![CDATA[
+  <programlisting>
+   <![CDATA[
 int devnum = -1;
 while ((devnum = parport_find_class (PARPORT_CLASS_DIGCAM,
                                      devnum)) != -1) {
     struct pardevice *dev = parport_open (devnum, ...);
     ...
 }
-]]></programlisting>
+   ]]></programlisting>
 
-<para>Once your device driver has registered its device and been
-handed a pointer to a <structname>struct pardevice</structname>, the
-next thing you are likely to want to do is communicate with the device
-you think is there.  To do that you'll need to claim access to the
-port.</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_claim</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_claim_or_block</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>void <function>parport_release</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>To claim access to the port, use
-<function>parport_claim</function> or
-<function>parport_claim_or_block</function>.  The first of these will
-not block, and so can be used from interrupt context.  If
-<function>parport_claim</function> succeeds it will return zero and
-the port is available to use.  It may fail (returning non-zero) if the
-port is in use by another driver and that driver is not willing to
-relinquish control of the port.</para>
-
-<para>The other function, <function>parport_claim_or_block</function>,
-will block if necessary to wait for the port to be free.  If it slept,
-it returns <constant>1</constant>; if it succeeded without needing to
-sleep it returns <constant>0</constant>.  If it fails it will return a
-negative error code.</para>
-
-<para>When you have finished communicating with the device, you can
-give up access to the port so that other drivers can communicate with
-their devices.  The <function>parport_release</function> function
-cannot fail, but it should not be called without the port claimed.
-Similarly, you should not try to claim the port if you already have it
-claimed.</para>
-
-<para>You may find that although there are convenient points for your
-driver to relinquish the parallel port and allow other drivers to talk
-to their devices, it would be preferable to keep hold of the port.
-The printer driver only needs the port when there is data to print,
-for example, but a network driver (such as PLIP) could be sent a
-remote packet at any time.  With PLIP, it is no huge catastrophe if a
-network packet is dropped, since it will likely be sent again, so it
-is possible for that kind of driver to share the port with other
-(pass-through) devices.</para>
-
-<para>The <function>parport_yield</function> and
-<function>parport_yield_blocking</function> functions are for marking
-points in the driver at which other drivers may claim the port and use
-their devices.  Yielding the port is similar to releasing it and
-reclaiming it, but it more efficient because nothing is done if there
-are no other devices needing the port.  In fact, nothing is done even
-if there are other devices waiting but the current device is still
-within its <quote>timeslice</quote>.  The default timeslice is half a
-second, but it can be adjusted via a <filename>/proc</filename>
-entry.</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_yield</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_yield_blocking</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>The first of these, <function>parport_yield</function>, will not
-block but as a result may fail.  The return value for
-<function>parport_yield</function> is the same as for
-<function>parport_claim</function>.  The blocking version,
-<function>parport_yield_blocking</function>, has the same return code
-as <function>parport_claim_or_block</function>.</para>
-
-<para>Once the port has been claimed, the device driver can use the
-functions in the <structname>struct parport_operations</structname>
-pointer in the <structname>struct parport</structname> it has a
-pointer to.  For example:</para>
+  <para>
+   Once your device driver has registered its device and been handed a
+   pointer to a <structname>struct pardevice</structname>, the next
+   thing you are likely to want to do is communicate with the device
+   you think is there.  To do that you'll need to claim access to the
+   port.
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+   </funcsynopsisinfo>
+   <funcprototype>
+    <funcdef>int <function>parport_claim</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <funcsynopsis>
+   <funcprototype>
+    <funcdef>int <function>parport_claim_or_block</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <funcsynopsis>
+   <funcprototype>
+    <funcdef>void <function>parport_release</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   To claim access to the port, use <function>parport_claim</function>
+   or <function>parport_claim_or_block</function>.  The first of these
+   will not block, and so can be used from interrupt context.  If
+   <function>parport_claim</function> succeeds it will return zero and
+   the port is available to use.  It may fail (returning non-zero) if
+   the port is in use by another driver and that driver is not willing
+   to relinquish control of the port.
+  </para>
+
+  <para>
+   The other function, <function>parport_claim_or_block</function>,
+   will block if necessary to wait for the port to be free.  If it
+   slept, it returns <constant>1</constant>; if it succeeded without
+   needing to sleep it returns <constant>0</constant>.  If it fails it
+   will return a negative error code.
+  </para>
+
+  <para>
+   When you have finished communicating with the device, you can give
+   up access to the port so that other drivers can communicate with
+   their devices.  The <function>parport_release</function> function
+   cannot fail, but it should not be called without the port claimed.
+   Similarly, you should not try to claim the port if you already have
+   it claimed.
+  </para>
+
+  <para>
+   You may find that although there are convenient points for your
+   driver to relinquish the parallel port and allow other drivers to
+   talk to their devices, it would be preferable to keep hold of the
+   port.  The printer driver only needs the port when there is data to
+   print, for example, but a network driver (such as PLIP) could be
+   sent a remote packet at any time.  With PLIP, it is no huge
+   catastrophe if a network packet is dropped, since it will likely be
+   sent again, so it is possible for that kind of driver to share the
+   port with other (pass-through) devices.
+  </para>
+
+  <para>
+   The <function>parport_yield</function> and
+   <function>parport_yield_blocking</function> functions are for
+   marking points in the driver at which other drivers may claim the
+   port and use their devices.  Yielding the port is similar to
+   releasing it and reclaiming it, but is more efficient because
+   nothing is done if there are no other devices needing the port.  In
+   fact, nothing is done even if there are other devices waiting but
+   the current device is still within its <quote>timeslice</quote>.
+   The default timeslice is half a second, but it can be adjusted via
+   a <filename>/proc</filename> entry.
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+   </funcsynopsisinfo>
+   <funcprototype>
+    <funcdef>int <function>parport_yield</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <funcsynopsis>
+   <funcprototype>
+    <funcdef>int <function>parport_yield_blocking</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   The first of these, <function>parport_yield</function>, will not
+   block but as a result may fail.  The return value for
+   <function>parport_yield</function> is the same as for
+   <function>parport_claim</function>.  The blocking version,
+   <function>parport_yield_blocking</function>, has the same return
+   code as <function>parport_claim_or_block</function>.
+  </para>
+
+  <para>
+   Once the port has been claimed, the device driver can use the
+   functions in the <structname>struct parport_operations</structname>
+   pointer in the <structname>struct parport</structname> it has a
+   pointer to.  For example:
+  </para>
 
-<programlisting>
-<![CDATA[
+  <programlisting>
+   <![CDATA[
 port->ops->write_data (port, d);
-]]></programlisting>
+   ]]></programlisting>
 
-<para>Some of these operations have <quote>shortcuts</quote>.  For
-instance, <function>parport_write_data</function> is equivalent to the
-above, but may be a little bit faster (it's a macro that in some cases
-can avoid needing to indirect through <varname>port</varname> and
-<varname>ops</varname>).</para>
-
-</chapter>
-
-<chapter id="portdrivers">
-<title>Port drivers</title>
-
-<!-- What port drivers are for (i.e. implementing parport objects). -->
-
-<para>To recap, then:</para>
-
-<itemizedlist spacing=compact>
-
-<listitem>
-<para>
-The device driver registers itself with <filename>parport</filename>.
-</para>
-</listitem>
-
-<listitem>
-<para>
-A low-level driver finds a parallel port and registers it with
-<filename>parport</filename> (these first two things can happen in
-either order).  This registration creates a <structname>struct
-parport</structname> which is linked onto a list of known ports.
-</para>
-</listitem>
-
-<listitem>
-<para>
-<filename>parport</filename> calls the <function>attach</function>
-function of each registered device driver, passing it the pointer to
-the new <structname>struct parport</structname>.
-</para>
-</listitem>
-
-<listitem>
-<para>
-The device driver gets a handle from <filename>parport</filename>, for
-use with
-<function>parport_claim</function>/<function>release</function>.  This
-handle takes the form of a pointer to a <structname>struct
-pardevice</structname>, representing a particular device on the
-parallel port, and is acquired using
-<function>parport_register_device</function>.
-</para>
-</listitem>
-
-<listitem>
-<para>
-The device driver claims the port using
-<function>parport_claim</function> (or
-<function>function_claim_or_block</function>).
-</para>
-</listitem>
-
-<listitem>
-<para>
-Then it goes ahead and uses the port.  When finished it releases the
-port.
-</para>
-</listitem>
-
-</itemizedlist>
-
-<para>The purpose of the low-level drivers, then, is to detect
-parallel ports and provide methods of accessing them
-(i.e. implementing the operations in <structname>struct
-parport_operations</structname>).</para>
-
-<!-- Interaction with sharing engine; port state -->
-<!-- What did I mean by that? -->
-
-<!-- Talk about parport_pc implementation, and contrast with e.g. amiga -->
-
-<para>A more complete description of which operation is supposed to do
-what is available in
-<filename>Documentation/parport-lowlevel.txt</filename>.</para>
-
-</chapter>
-
-<chapter id="lp">
-<title>The printer driver</title>
-
-<!-- Talk the reader through the printer driver. -->
-<!-- Could even talk about parallel port console here. -->
-
-<para>The printer driver, <filename>lp</filename> is a character
-special device driver and a <filename>parport</filename> client.  As a
-character special device driver it registers a <structname>struct
-file_operations</structname> using
-<function>register_chrdev</function>, with pointers filled in for
-<structfield>write</structfield>, <structfield>ioctl</structfield>,
-<structfield>open</structfield> and
-<structfield>release</structfield>.  As a client of
-<filename>parport</filename>, it registers a <structname>struct
-parport_driver</structname> using
-<function>parport_register_driver</function>, so that
-<filename>parport</filename> knows to call
-<function>lp_attach</function> when a new parallel port is discovered
-(and <function>lp_detach</function> when it goes away).</para>
-
-<para>The parallel port console functionality is also implemented in
-<filename>lp.c</filename>, but that won't be covered here (it's quite
-simple though).</para>
-
-<para>The initialisation of the driver is quite easy to understand
-(see <function>lp_init</function>).  The <varname>lp_table</varname>
-is an array of structures that contain information about a specific
-device (the <structname>struct pardevice</structname> associated with
-it, for example).  That array is initialised to sensible values first
-of all.</para>
-
-<para>Next, the printer driver calls
-<function>register_chrdev</function> passing it a pointer to
-<varname>lp_fops</varname>, which contains function pointers for the
-printer driver's implementation of <function>open</function>,
-<function>write</function>, and so on.  This part is the same as for
-any character special device driver.</para>
-
-<para>After successfully registering itself as a character special
-device driver, the printer driver registers itself as a
-<filename>parport</filename> client using
-<function>parport_register_driver</function>.  It passes a pointer to
-this structure:</para>
+  <para>
+   Some of these operations have <quote>shortcuts</quote>.  For
+   instance, <function>parport_write_data</function> is equivalent to
+   the above, but may be a little bit faster (it's a macro that in
+   some cases can avoid needing to indirect through
+   <varname>port</varname> and <varname>ops</varname>).
+  </para>
+
+ </chapter>
+
+ <chapter id="portdrivers">
+  <title>Port drivers</title>
+
+  <!-- What port drivers are for (i.e. implementing parport objects). -->
+
+  <para>
+   To recap, then:</para>
+
+  <itemizedlist spacing=compact>
+
+   <listitem>
+    <para>
+     The device driver registers itself with <literal>parport</literal>.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     A low-level driver finds a parallel port and registers it with
+     <literal>parport</literal> (these first two things can happen
+     in either order).  This registration creates a <structname>struct
+     parport</structname> which is linked onto a list of known ports.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     <literal>parport</literal> calls the
+     <function>attach</function> function of each registered device
+     driver, passing it the pointer to the new <structname>struct
+     parport</structname>.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     The device driver gets a handle from
+     <literal>parport</literal>, for use with
+     <function>parport_claim</function>/<function>release</function>.
+     This handle takes the form of a pointer to a <structname>struct
+     pardevice</structname>, representing a particular device on the
+     parallel port, and is acquired using
+     <function>parport_register_device</function>.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     The device driver claims the port using
+     <function>parport_claim</function> (or
+     <function>function_claim_or_block</function>).
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Then it goes ahead and uses the port.  When finished it releases
+     the port.
+    </para>
+   </listitem>
+
+  </itemizedlist>
+
+  <para>
+   The purpose of the low-level drivers, then, is to detect parallel
+   ports and provide methods of accessing them (i.e. implementing the
+   operations in <structname>struct
+   parport_operations</structname>).
+  </para>
+
+  <!-- Should DocBookise this -->
+  <para>
+   A more complete description of which operation is supposed to do
+   what is available in
+   <filename>Documentation/parport-lowlevel.txt</filename>.
+  </para>
+
+ </chapter>
+
+ <chapter id="lp">
+  <title>The printer driver</title>
+
+  <!-- Talk the reader through the printer driver. -->
+  <!-- Could even talk about parallel port console here. -->
+
+  <para>
+   The printer driver, <literal>lp</literal> is a character special
+   device driver and a <literal>parport</literal> client.  As a
+   character special device driver it registers a <structname>struct
+   file_operations</structname> using
+   <function>register_chrdev</function>, with pointers filled in for
+   <structfield>write</structfield>, <structfield>ioctl</structfield>,
+   <structfield>open</structfield> and
+   <structfield>release</structfield>.  As a client of
+   <literal>parport</literal>, it registers a <structname>struct
+   parport_driver</structname> using
+   <function>parport_register_driver</function>, so that
+   <literal>parport</literal> knows to call
+   <function>lp_attach</function> when a new parallel port is
+   discovered (and <function>lp_detach</function> when it goes
+   away).
+  </para>
+
+  <para>
+   The parallel port console functionality is also implemented in
+   <filename>drivers/char/lp.c</filename>, but that won't be covered
+   here (it's quite simple though).
+  </para>
+
+  <para>
+   The initialisation of the driver is quite easy to understand (see
+   <function>lp_init</function>).  The <varname>lp_table</varname> is
+   an array of structures that contain information about a specific
+   device (the <structname>struct pardevice</structname> associated
+   with it, for example).  That array is initialised to sensible
+   values first of all.
+  </para>
+
+  <para>
+   Next, the printer driver calls <function>register_chrdev</function>
+   passing it a pointer to <varname>lp_fops</varname>, which contains
+   function pointers for the printer driver's implementation of
+   <function>open</function>, <function>write</function>, and so on.
+   This part is the same as for any character special device
+   driver.
+  </para>
+
+  <para>
+   After successfully registering itself as a character special device
+   driver, the printer driver registers itself as a
+   <literal>parport</literal> client using
+   <function>parport_register_driver</function>.  It passes a pointer
+   to this structure:
+  </para>
 
-<programlisting>
-<![CDATA[
+  <programlisting>
+   <![CDATA[
 static struct parport_driver lp_driver = {
         "lp",
         lp_attach,
         lp_detach,
         NULL
 };
-]]></programlisting>
+   ]]></programlisting>
 
-<para>The <function>lp_detach</function> function is not very
-interesting (it does nothing); the interesting bit is
-<function>lp_attach</function>.  What goes on here depends on whether
-the user supplied any parameters.  The possibilities are: no
-parameters supplied, in which case the printer driver uses every port
-that is detected; the user supplied the parameter <quote>auto</quote>,
-in which case only ports on which the device ID string indicates a
-printer is present are used; or the user supplied a list of parallel
-port numbers to try, in which case only those are used.</para>
-
-<para>For each port that the printer driver wants to use (see
-<function>lp_register</function>), it calls
-<function>parport_register_device</function> and stores the resulting
-<structname>struct pardevice</structname> pointer in the
-<varname>lp_table</varname>.  If the user told it to do so, it then
-resets the printer.</para>
-
-<para>The other interesting piece of the printer driver, from the
-point of view of <filename>parport</filename>, is
-<function>lp_write</function>.  In this function, the user space
-process has data that it wants printed, and the printer driver hands
-it off to the <filename>parport</filename> code to deal with.</para>
-
-<para>The <filename>parport</filename> functions it uses that we have
-not seen yet are <function>parport_negotiate</function>,
-<function>parport_set_timeout</function>, and
-<function>parport_write</function>.  These functions are part of the
-IEEE 1284 implementation.</para>
-
-<para>The way the IEEE 1284 protocol works is that the host tells the
-peripheral what transfer mode it would like to use, and the peripheral
-either accepts that mode or rejects it; if the mode is rejected, the
-host can try again with a different mode.  This is the negotation
-phase.  Once the peripheral has accepted a particular transfer mode,
-data transfer can begin that mode.</para>
-
-<para>The particular transfer mode that the printer driver wants to
-use is named in IEEE 1284 as <quote>compatibility</quote> mode, and
-the function to request a particular mode is called
-<function>parport_negotiate</function>.</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>int <function>parport_negotiate</function></funcdef>
-  <paramdef>struct parport *<parameter>port</parameter></paramdef>
-  <paramdef>int <parameter>mode</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>The <parameter>modes</parameter> parameter is a symbolic
-constant representing an IEEE 1284 mode; in this instance, it is
-<constant>IEEE1284_MODE_COMPAT</constant>. (Compatibility mode is
-slightly different to the other modes---rather than being specifically
-requested, it is the default until another mode is selected.)</para>
-
-<para>Back to <function>lp_write</function> then.  First, access to
-the parallel port is secured with
-<function>parport_claim_or_block</function>.  At this point the driver
-might sleep, waiting for another driver (perhaps a Zip drive driver,
-for instance) to let the port go.  Next, it goes to compatibility mode
-using <function>parport_negotiate</function>.</para>
-
-<para>The main work is done in the write-loop.  In particular, the
-line that hands the data over to <filename>parport</filename>
-reads:</para>
+  <para>
+   The <function>lp_detach</function> function is not very interesting
+   (it does nothing); the interesting bit is
+   <function>lp_attach</function>.  What goes on here depends on
+   whether the user supplied any parameters.  The possibilities are:
+   no parameters supplied, in which case the printer driver uses every
+   port that is detected; the user supplied the parameter
+   <quote>auto</quote>, in which case only ports on which the device
+   ID string indicates a printer is present are used; or the user
+   supplied a list of parallel port numbers to try, in which case only
+   those are used.
+  </para>
+
+  <para>
+   For each port that the printer driver wants to use (see
+   <function>lp_register</function>), it calls
+   <function>parport_register_device</function> and stores the
+   resulting <structname>struct pardevice</structname> pointer in the
+   <varname>lp_table</varname>.  If the user told it to do so, it then
+   resets the printer.
+  </para>
+
+  <para>
+   The other interesting piece of the printer driver, from the point
+   of view of <literal>parport</literal>, is
+   <function>lp_write</function>.  In this function, the user space
+   process has data that it wants printed, and the printer driver
+   hands it off to the <literal>parport</literal> code to deal with.
+  </para>
+
+  <para>
+   The <literal>parport</literal> functions it uses that we have not
+   seen yet are <function>parport_negotiate</function>,
+   <function>parport_set_timeout</function>, and
+   <function>parport_write</function>.  These functions are part of
+   the IEEE 1284 implementation.
+  </para>
+
+  <para>
+   The way the IEEE 1284 protocol works is that the host tells the
+   peripheral what transfer mode it would like to use, and the
+   peripheral either accepts that mode or rejects it; if the mode is
+   rejected, the host can try again with a different mode.  This is
+   the negotation phase.  Once the peripheral has accepted a
+   particular transfer mode, data transfer can begin that mode.
+  </para>
+
+  <para>
+   The particular transfer mode that the printer driver wants to use
+   is named in IEEE 1284 as <quote>compatibility</quote> mode, and the
+   function to request a particular mode is called
+   <function>parport_negotiate</function>.
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+   </funcsynopsisinfo>
+   <funcprototype>
+    <funcdef>int <function>parport_negotiate</function></funcdef>
+    <paramdef>struct parport *<parameter>port</parameter></paramdef>
+    <paramdef>int <parameter>mode</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   The <parameter>modes</parameter> parameter is a symbolic constant
+   representing an IEEE 1284 mode; in this instance, it is
+   <constant>IEEE1284_MODE_COMPAT</constant>. (Compatibility mode is
+   slightly different to the other modes---rather than being
+   specifically requested, it is the default until another mode is
+   selected.)
+  </para>
+
+  <para>
+   Back to <function>lp_write</function> then.  First, access to the
+   parallel port is secured with
+   <function>parport_claim_or_block</function>.  At this point the
+   driver might sleep, waiting for another driver (perhaps a Zip drive
+   driver, for instance) to let the port go.  Next, it goes to
+   compatibility mode using <function>parport_negotiate</function>.
+  </para>
+
+  <para>
+   The main work is done in the write-loop.  In particular, the line
+   that hands the data over to <literal>parport</literal> reads:
+  </para>
 
 <programlisting>
 <![CDATA[
         written = parport_write (port, kbuf, copy_size);
 ]]></programlisting>
 
-<para>The <function>parport_write</function> function writes data to
-the peripheral using the currently selected transfer mode
-(compatibility mode, in this case).  It returns the number of bytes
-successfully written:</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>ssize_t <function>parport_write</function></funcdef>
-  <paramdef>struct parport *<parameter>port</parameter></paramdef>
-  <paramdef>const void *<parameter>buf</parameter></paramdef>
-  <paramdef>size_t <parameter>len</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<funcsynopsis><funcprototype>
-  <funcdef>ssize_t <function>parport_read</function></funcdef>
-  <paramdef>struct parport *<parameter>port</parameter></paramdef>
-  <paramdef>void *<parameter>buf</parameter></paramdef>
-  <paramdef>size_t <parameter>len</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>(<function>parport_read</function> does what it sounds like, but
-only works for modes in which reverse transfer is possible.  Of
-course, <function>parport_write</function> only works in modes in
-which forward transfer is possible, too.)</para>
-
-<para>The <parameter>buf</parameter> pointer should be to kernel space
-memory, and obviously the <parameter>len</parameter> parameter
-specifies the amount of data to transfer.</para>
-
-<para>In fact what <function>parport_write</function> does is call the
-appropriate block transfer function from the <structname>struct
-parport_operations</structname>:</para>
+  <para>
+   The <function>parport_write</function> function writes data to the
+   peripheral using the currently selected transfer mode
+   (compatibility mode, in this case).  It returns the number of bytes
+   successfully written:
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+   </funcsynopsisinfo>
+   <funcprototype>
+    <funcdef>ssize_t <function>parport_write</function></funcdef>
+    <paramdef>struct parport *<parameter>port</parameter></paramdef>
+    <paramdef>const void *<parameter>buf</parameter></paramdef>
+    <paramdef>size_t <parameter>len</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <funcsynopsis>
+   <funcprototype>
+    <funcdef>ssize_t <function>parport_read</function></funcdef>
+    <paramdef>struct parport *<parameter>port</parameter></paramdef>
+    <paramdef>void *<parameter>buf</parameter></paramdef>
+    <paramdef>size_t <parameter>len</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   (<function>parport_read</function> does what it sounds like, but
+   only works for modes in which reverse transfer is possible.  Of
+   course, <function>parport_write</function> only works in modes in
+   which forward transfer is possible, too.)
+  </para>
+
+  <para>
+   The <parameter>buf</parameter> pointer should be to kernel space
+   memory, and obviously the <parameter>len</parameter> parameter
+   specifies the amount of data to transfer.
+  </para>
+
+  <para>
+   In fact what <function>parport_write</function> does is call the
+   appropriate block transfer function from the <structname>struct
+   parport_operations</structname>:
+  </para>
 
-<programlisting>
-<![CDATA[
+  <programlisting>
+   <![CDATA[
 struct parport_operations {
         [...]
 
         /* Block read/write */
-        size_t (*epp_write_data) (struct parport *port, const void *buf,
+        size_t (*epp_write_data) (struct parport *port,
+                                  const void *buf,
                                   size_t len, int flags);
-        size_t (*epp_read_data) (struct parport *port, void *buf, size_t len,
+        size_t (*epp_read_data) (struct parport *port,
+                                 void *buf, size_t len,
                                  int flags);
-        size_t (*epp_write_addr) (struct parport *port, const void *buf,
+        size_t (*epp_write_addr) (struct parport *port,
+                                  const void *buf,
                                   size_t len, int flags);
-        size_t (*epp_read_addr) (struct parport *port, void *buf, size_t len,
+        size_t (*epp_read_addr) (struct parport *port,
+                                 void *buf, size_t len,
                                  int flags);
 
-        size_t (*ecp_write_data) (struct parport *port, const void *buf,
+        size_t (*ecp_write_data) (struct parport *port,
+                                  const void *buf,
                                   size_t len, int flags);
-        size_t (*ecp_read_data) (struct parport *port, void *buf, size_t len,
+        size_t (*ecp_read_data) (struct parport *port,
+                                 void *buf, size_t len,
                                  int flags);
-        size_t (*ecp_write_addr) (struct parport *port, const void *buf,
+        size_t (*ecp_write_addr) (struct parport *port,
+                                  const void *buf,
                                   size_t len, int flags);
 
-        size_t (*compat_write_data) (struct parport *port, const void *buf,
+        size_t (*compat_write_data) (struct parport *port,
+                                     const void *buf,
                                      size_t len, int flags);
-        size_t (*nibble_read_data) (struct parport *port, void *buf,
-                                    size_t len, int flags);
-        size_t (*byte_read_data) (struct parport *port, void *buf,
-                                  size_t len, int flags);
+        size_t (*nibble_read_data) (struct parport *port,
+                                    void *buf, size_t len,
+                                    int flags);
+        size_t (*byte_read_data) (struct parport *port,
+                                  void *buf, size_t len,
+                                  int flags);
 };
-]]></programlisting>
+   ]]></programlisting>
 
-<para>The transfer code in <filename>parport</filename> will tolerate
-a data transfer stall only for so long, and this timeout can be
-specified with <function>parport_set_timeout</function>, which returns
-the previous timeout:</para>
-
-<funcsynopsis><funcprototype>
-  <funcdef>long <function>parport_set_timeout</function></funcdef>
-  <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
-  <paramdef>long <parameter>inactivity</parameter></paramdef>
-</funcprototype></funcsynopsis>
-
-<para>This timeout is specific to the device, and is restored on
-<function>parport_claim</function>.</para>
-
-</chapter>
-
-<chapter id="ppdev">
-<title>User-level device drivers</title>
-
-<!-- ppdev -->
-<sect1>
-<title>Introduction to ppdev</title>
-
-<para>The printer is accessible through <filename>/dev/lp0</filename>;
-in the same way, the parallel port itself is accessible through
-<filename>/dev/parport0</filename>.  The difference is in the level of
-control that you have over the wires in the parallel port
-cable.</para>
-
-<para>With the printer driver, a user-space program (such as the
-printer spooler) can send bytes in <quote>printer protocol</quote>.
-Briefly, this means that for each byte, the eight data lines are set
-up, then a <quote>strobe</quote> line tells the printer to look at the
-data lines, and the printer sets an <quote>acknowledgement</quote>
-line to say that it got the byte.  The printer driver also allows the
-user-space program to read bytes in <quote>nibble mode</quote>, which
-is a way of transferring data from the peripheral to the computer half
-a byte at a time (and so it's quite slow).</para>
-
-<para>In contrast, the <filename>ppdev</filename> driver (accessed via
-<filename>/dev/parport0</filename>) allows you to:</para>
-
-<itemizedlist spacing=compact>
-
-<listitem>
-<para>
-examine status lines,
-</para>
-</listitem>
-
-<listitem>
-<para>
-set control lines,
-</para>
-</listitem>
-
-<listitem>
-<para>
-set/examine data lines (and control the direction of the data lines),
-</para>
-</listitem>
-
-<listitem>
-<para>
-wait for an interrupt (triggered by one of the status lines),
-</para>
-</listitem>
-
-<listitem>
-<para>
-find out how many new interrupts have occurred,
-</para>
-</listitem>
-
-<listitem>
-<para>
-set up a response to an interrupt,
-</para>
-</listitem>
-
-<listitem>
-<para>
-use IEEE 1284 negotiation (for telling peripheral which transfer mode,
-to use)
-</para>
-</listitem>
-
-<listitem>
-<para>
-transfer data using a specified IEEE 1284 mode.
-</para>
-</listitem>
-
-</itemizedlist>
-
-</sect1>
-
-<sect1>
-<title>User-level or kernel-level driver?</title>
-
-<para>The decision of whether to choose to write a kernel-level device
-driver or a user-level device driver depends on several factors.  One
-of the main ones from a practical point of view is speed: kernel-level
-device drivers get to run faster because they are not preemptable,
-unlike user-level applications.</para>
-
-<para>Another factor is ease of development.  It is in general easier
-to write a user-level driver because (a) one wrong move does not
-result in a crashed machine, (b) you have access to user libraries
-(such as the C library), and (c) debugging is easier.</para>
-
-</sect1>
-
-<sect1>
-<title>Programming interface</title>
-
-<para>The <filename>ppdev</filename> interface is largely the same as
-that of other character special devices, in that it supports
-<function>open</function>, <function>close</function>,
-<function>read</function>, <function>write</function>, and
-<function>ioctl</function>.</para>
-
-<sect2>
-<title>Starting and stopping: <function>open</function> and
-<function>close</function></title>
-
-<para>The device node <filename>/dev/parport0</filename> represents
-any device that is connected to <filename>parport0</filename>, the
-first parallel port in the system.  Each time the device node is
-opened, it represents (to the process doing the opening) a different
-device.  It can be opened more than once, but only one instance can
-actually be in control of the parallel port at any time.  A process
-that has opened <filename>/dev/parport0</filename> shares the parallel
-port in the same way as any other device driver.  A user-land driver
-may be sharing the parallel port with in-kernel device drivers as well
-as other user-land drivers.</para>
-</sect2>
-
-<sect2>
-<title>Control: <function>ioctl</function></title>
-
-<para>Most of the control is done, naturally enough, via the
-<function>ioctl</function> call.  Using <function>ioctl</function>,
-the user-land driver can control both the <filename>ppdev</filename>
-driver in the kernel and the physical parallel port itself.  The
-<function>ioctl</function> call takes as parameters a file descriptor
-(the one returned from opening the device node), a command, and
-optionally (a pointer to) some data.</para>
-
-<variablelist>
-<varlistentry><term><constant>PPCLAIM</constant></term>
-<listitem>
-
-<para>Claims access to the port.  As a user-land device driver writer,
-you will need to do this before you are able to actually change the
-state of the parallel port in any way.  Note that some operations only
-affect the <filename>ppdev</filename> driver and not the port, such as
-<constant>PPSETMODE</constant>; they can be performed while access to
-the port is not claimed.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPEXCL</constant></term>
-<listitem>
-
-<para>Instructs the kernel driver to forbid any sharing of the port
-with other drivers, i.e. it requests exclusivity.  The
-<constant>PPEXCL</constant> command is only valid when the port is not
-already claimed for use, and it may mean that the next
-<constant>PPCLAIM</constant> <function>ioctl</function> will fail:
-some other driver may already have registered itself on that
-port.</para>
-
-<para>Most device drivers don't need exclusive access to the port.
-It's only provided in case it is really needed, for example for
-devices where access to the port is required for extensive periods of
-time (many seconds).</para>
-
-<para>Note that the <constant>PPEXCL</constant>
-<function>ioctl</function> doesn't actually claim the port there and
-then---action is deferred until the <constant>PPCLAIM</constant>
-<function>ioctl</function> is performed.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPRELEASE</constant></term>
-<listitem>
-
-<para>Releases the port.  Releasing the port undoes the effect of
-claiming the port.  It allows other device drivers to talk to their
-devices (assuming that there are any).</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPYIELD</constant></term>
-<listitem>
-
-<para>Yields the port to another driver.  This
-<function>ioctl</function> is a kind of short-hand for releasing the
-port and immediately reclaiming it.  It gives other drivers a chance
-to talk to their devices, but afterwards claims the port back.  An
-example of using this would be in a user-land printer driver: once a
-few characters have been written we could give the port to another
-device driver for a while, but if we still have characters to send to
-the printer we would want the port back as soon as possible.</para>
-
-<para>It is important not to claim the parallel port for too long, as
-other device drivers will have no time to service their devices.  If
-your device does not allow for parallel port sharing at all, it is
-better to claim the parallel port exclusively (see
-<constant>PPEXCL</constant>).</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPNEGOT</constant></term>
-<listitem>
-
-<para>Performs IEEE 1284 negotiation into a particular mode.  Briefly,
-negotiation is the method by which the host and the peripheral decide
-on a protocol to use when transferring data.</para>
-
-<para>An IEEE 1284 compliant device will start out in compatibility
-mode, and then the host can negotiate to another mode (such as
-ECP).</para>
-
-<para>The <function>ioctl</function> parameter should be a pointer to
-an <type>int</type>; values for this are in
-<filename>parport.h</filename> and include:</para>
-
-<itemizedlist spacing=compact>
-<listitem><para><constant>IEEE1284_MODE_COMPAT</constant></para></listitem>
-<listitem><para><constant>IEEE1284_MODE_NIBBLE</constant></para></listitem>
-<listitem><para><constant>IEEE1284_MODE_BYTE</constant></para></listitem>
-<listitem><para><constant>IEEE1284_MODE_EPP</constant></para></listitem>
-<listitem><para><constant>IEEE1284_MODE_ECP</constant></para></listitem>
-</itemizedlist>
-
-<para>The <constant>PPNEGOT</constant> <function>ioctl</function>
-actually does two things: it performs the on-the-wire negotiation, and
-it sets the behaviour of subsequent
-<function>read</function>/<function>write</function> calls so that
-they use that mode (but see <constant>PPSETMODE</constant>).</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPSETMODE</constant></term>
-<listitem>
-
-<para>Sets which IEEE 1284 protocol to use for the
-<function>read</function> and <function>write</function> calls.</para>
-
-<para>The <function>ioctl</function> parameter should be a pointer to
-an <type>int</type>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPGETTIME</constant></term>
-<listitem>
-
-<para>Retrieves the time-out value.  The <function>read</function> and
-<function>write</function> calls will time out if the peripheral
-doesn't respond quickly enough.  The <constant>PPGETTIME</constant>
-<function>ioctl</function> retrieves the length of time that the
-peripheral is allowed to have before giving up.</para>
-
-<para>The <function>ioctl</function> parameter should be a pointer to
-a <structname>struct timeval</structname>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPSETTIME</constant></term>
-<listitem>
-
-<para>Sets the time-out.  The <function>ioctl</function> parameter
-should be a pointer to a <structname>struct
-timeval</structname>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPWCONTROL</constant></term>
-<listitem>
-
-<para>Sets the control lines.  The <function>ioctl</function>
-parameter is a pointer to an <type>unsigned char</type>, the bitwise
-OR of the control line values in
-<filename>parport.h</filename>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPRCONTROL</constant></term>
-<listitem>
-
-<para>Returns the last value written to the control register, in the
-form of an <type>unsigned char</type>: each bit corresponds to a
-control line (although some are unused).  The
-<function>ioctl</function> parameter should be a pointer to an
-<type>unsigned char</type>.</para>
-
-<para>This doesn't actually touch the hardware; the last value written
-is remembered in software.  This is because some parallel port
-hardware does not offer read access to the control register.</para>
-
-<para>The control lines bits are defined in
-<filename>parport.h</filename>:</para>
-
-<itemizedlist spacing=compact>
-<listitem><para><constant>PARPORT_CONTROL_STROBE</constant></para></listitem>
-<listitem><para><constant>PARPORT_CONTROL_AUTOFD</constant></para></listitem>
-<listitem><para><constant>PARPORT_CONTROL_SELECT</constant></para></listitem>
-<listitem><para><constant>PARPORT_CONTROL_INIT</constant></para></listitem>
-</itemizedlist>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPFCONTROL</constant></term>
-<listitem>
-
-<para>Frobs the control lines.  Since a common operation is to change
-one of the control signals while leaving the others alone, it would be
-quite inefficient for the user-land driver to have to use
-<constant>PPRCONTROL</constant>, make the change, and then use
-<constant>PPWCONTROL</constant>.  Of course, each driver could
-remember what state the control lines are supposed to be in (they are
-never changed by anything else), but in order to provide
-<constant>PPRCONTROL</constant>, <filename>ppdev</filename> must
-remember the state of the control lines anyway.</para>
-
-<para>The <constant>PPFCONTROL</constant> <function>ioctl</function>
-is for <quote>frobbing</quote> control lines, and is like
-<constant>PPWCONTROL</constant> but acts on a restricted set of
-control lines.  The <function>ioctl</function> parameter is a pointer
-to a <structname>struct ppdev_frob_struct</structname>:</para>
+  <para>
+   The transfer code in <literal>parport</literal> will tolerate a
+   data transfer stall only for so long, and this timeout can be
+   specified with <function>parport_set_timeout</function>, which
+   returns the previous timeout:
+  </para>
+
+  <funcsynopsis>
+   <funcsynopsisinfo>
+#include &lt;parport.h&gt;
+   </funcsynopsisinfo>
+   <funcprototype>
+    <funcdef>long <function>parport_set_timeout</function></funcdef>
+    <paramdef>struct pardevice *<parameter>dev</parameter></paramdef>
+    <paramdef>long <parameter>inactivity</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   This timeout is specific to the device, and is restored on
+   <function>parport_claim</function>.
+  </para>
+
+  <para>
+   The next function to look at is the one that allows processes to
+   read from <filename>/dev/lp0</filename>:
+   <function>lp_read</function>.  It's short, like
+   <function>lp_write</function>.
+  </para>
+
+  <para>
+   The semantics of reading from a line printer device are as follows:
+  </para>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+     Switch to reverse nibble mode.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Try to read data from the peripheral using reverse nibble mode,
+     until either the user-provided buffer is full or the peripheral
+     indicates that there is no more data.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     If there was data, stop, and return it.
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     Otherwise, we tried to read data and there was none.  If the user
+     opened the device node with the <constant>O_NONBLOCK</constant>
+     flag, return.  Otherwise wait until an interrupt occurs on the
+     port (or a timeout elapses).
+    </para>
+   </listitem>
+  </itemizedlist>
+
+ </chapter>
+
+ <chapter id="ppdev">
+  <title>User-level device drivers</title>
+
+  <!-- ppdev -->
+  <sect1>
+   <title>Introduction to ppdev</title>
 
-<programlisting>
-<![CDATA[
-struct ppdev_frob_struct {
-        unsigned char mask;
-        unsigned char val;
-};
-]]>
-</programlisting>
-
-<para>The <structfield>mask</structfield> and
-<structfield>val</structfield> fields are bitwise ORs of control line
-names (such as in <constant>PPWCONTROL</constant>).  The operation
-performed by <constant>PPFCONTROL</constant> is:</para>
-
-<programlisting>
-<![CDATA[new_ctr = (old_ctr & ~mask) | val;]]>
-</programlisting>
-
-<para>In other words, the signals named in
-<structfield>mask</structfield> are set to the values in
-<structfield>val</structfield>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPRSTATUS</constant></term>
-<listitem>
-
-<para>Returns an <type>unsigned char</type> containing bits set for
-each status line that is set (for instance,
-<constant>PARPORT_STATUS_BUSY</constant>).  The
-<function>ioctl</function> parameter should be a pointer to an
-<type>unsigned char</type>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPDATADIR</constant></term>
-<listitem>
-
-<para>Controls the data line drivers.  Normally the computer's
-parallel port will drive the data lines, but for byte-wide transfers
-from the peripheral to the host it is useful to turn off those drivers
-and let the peripheral drive the signals. (If the drivers on the
-computer's parallel port are left on when this happens, the port might
-be damaged.)</para>
-
-<para>This is only needed in conjunction with
-<constant>PPWDATA</constant> or <constant>PPRDATA</constant>.</para>
-
-<para>The <function>ioctl</function> parameter is a pointer to an
-<type>int</type>.  If the <type>int</type> is zero, the drivers are
-turned on (forward direction); if non-zero, the drivers are turned off
-(reverse direction).</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPWDATA</constant></term>
-<listitem>
-
-<para>Sets the data lines (if in forward mode).  The
-<function>ioctl</function> parameter is a pointer to an <type>unsigned
-char</type>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPRDATA</constant></term>
-<listitem>
-
-<para>Reads the data lines (if in reverse mode).  The
-<function>ioctl</function> parameter is a pointer to an <type>unsigned
-char</type>.</para>
-
-</listitem></varlistentry>
-
-<varlistentry><term><constant>PPCLRIRQ</constant></term>
-<listitem>
+   <para>
+    The printer is accessible through <filename>/dev/lp0</filename>;
+    in the same way, the parallel port itself is accessible through
+    <filename>/dev/parport0</filename>.  The difference is in the
+    level of control that you have over the wires in the parallel port
+    cable.
+   </para>
 
-<para>Clears the interrupt count.  The <filename>ppdev</filename>
-driver keeps a count of interrupts as they are triggered.
-<constant>PPCLRIRQ</constant> stores this count in an
-<type>int</type>, a pointer to which is passed in as the
-<function>ioctl</function> parameter.</para>
+   <para>
+    With the printer driver, a user-space program (such as the printer
+    spooler) can send bytes in <quote>printer protocol</quote>.
+    Briefly, this means that for each byte, the eight data lines are
+    set up, then a <quote>strobe</quote> line tells the printer to
+    look at the data lines, and the printer sets an
+    <quote>acknowledgement</quote> line to say that it got the byte.
+    The printer driver also allows the user-space program to read
+    bytes in <quote>nibble mode</quote>, which is a way of
+    transferring data from the peripheral to the computer half a byte
+    at a time (and so it's quite slow).
+   </para>
 
-<para>In addition, the interrupt count is reset to zero.</para>
+   <para>
+    In contrast, the <literal>ppdev</literal> driver (accessed via
+    <filename>/dev/parport0</filename>) allows you to:
+   </para>
 
-</listitem></varlistentry>
+   <itemizedlist spacing=compact>
 
-<varlistentry><term><constant>PPWCTLONIRQ</constant></term>
-<listitem>
+    <listitem>
+     <para>
+      examine status lines,
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      set control lines,
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      set/examine data lines (and control the direction of the data
+      lines),
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      wait for an interrupt (triggered by one of the status lines),
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      find out how many new interrupts have occurred,
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      set up a response to an interrupt,
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      use IEEE 1284 negotiation (for telling peripheral which transfer
+      mode, to use)
+     </para>
+    </listitem>
+
+    <listitem>
+     <para>
+      transfer data using a specified IEEE 1284 mode.
+     </para>
+    </listitem>
 
-<para>Set a trigger response.  Afterwards when an interrupt is
-triggered, the interrupt handler will set the control lines as
-requested.  The <function>ioctl</function> parameter is a pointer to
-an <type>unsigned char</type>, which is interpreted in the same way as
-for <constant>PPWCONTROL</constant>.</para>
+   </itemizedlist>
 
-<para>The reason for this <function>ioctl</function> is simply speed.
-Without this <function>ioctl</function>, responding to an interrupt
-would start in the interrupt handler, switch context to the user-land
-driver via <function>poll</function> or <function>select</function>,
-and then switch context back to the kernel in order to handle
-<constant>PPWCONTROL</constant>.  Doing the whole lot in the interrupt
-handler is a lot faster.</para>
+  </sect1>
 
-</listitem></varlistentry>
+  <sect1>
+   <title>User-level or kernel-level driver?</title>
 
-<!-- PPSETPHASE? -->
+   <para>
+    The decision of whether to choose to write a kernel-level device
+    driver or a user-level device driver depends on several factors.
+    One of the main ones from a practical point of view is speed:
+    kernel-level device drivers get to run faster because they are not
+    preemptable, unlike user-level applications.
+   </para>
 
-</variablelist>
+   <para>
+    Another factor is ease of development.  It is in general easier to
+    write a user-level driver because (a) one wrong move does not
+    result in a crashed machine, (b) you have access to user libraries
+    (such as the C library), and (c) debugging is easier.
+   </para>
 
-</sect2>
+  </sect1>
 
-<sect2>
-<title>Transferring data: <function>read</function> and
-<function>write</function></title>
+  <sect1>
+   <title>Programming interface</title>
 
-<para>Transferring data using <function>read</function> and
-<function>write</function> is straightforward.  The data is
-transferring using the current IEEE 1284 mode (see the
-<constant>PPSETMODE</constant> <function>ioctl</function>).  For modes
-which can only transfer data in one direction, only the appropriate
-function will work, of course.</para>
-</sect2>
+   <para>
+    The <literal>ppdev</literal> interface is largely the same as that
+    of other character special devices, in that it supports
+    <function>open</function>, <function>close</function>,
+    <function>read</function>, <function>write</function>, and
+    <function>ioctl</function>.  The constants for the
+    <function>ioctl</function> commands are in
+    <filename>include/linux/ppdev.h</filename>.
+   </para>
 
-<sect2>
-<title>Waiting for events: <function>poll</function> and
-<function>select</function></title>
+   <sect2>
+    <title>
+     Starting and stopping: <function>open</function> and
+     <function>close</function>
+    </title>
+
+    <para>
+     The device node <filename>/dev/parport0</filename> represents any
+     device that is connected to <filename>parport0</filename>, the
+     first parallel port in the system.  Each time the device node is
+     opened, it represents (to the process doing the opening) a
+     different device.  It can be opened more than once, but only one
+     instance can actually be in control of the parallel port at any
+     time.  A process that has opened
+     <filename>/dev/parport0</filename> shares the parallel port in
+     the same way as any other device driver.  A user-land driver may
+     be sharing the parallel port with in-kernel device drivers as
+     well as other user-land drivers.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Control: <function>ioctl</function></title>
+
+    <para>
+     Most of the control is done, naturally enough, via the
+     <function>ioctl</function> call.  Using
+     <function>ioctl</function>, the user-land driver can control both
+     the <literal>ppdev</literal> driver in the kernel and the
+     physical parallel port itself.  The <function>ioctl</function>
+     call takes as parameters a file descriptor (the one returned from
+     opening the device node), a command, and optionally (a pointer
+     to) some data.
+    </para>
+
+    <variablelist>
+     <varlistentry><term><constant>PPCLAIM</constant></term>
+      <listitem>
+
+       <para>
+	Claims access to the port.  As a user-land device driver
+	writer, you will need to do this before you are able to
+	actually change the state of the parallel port in any way.
+	Note that some operations only affect the
+	<literal>ppdev</literal> driver and not the port, such as
+	<constant>PPSETMODE</constant>; they can be performed while
+	access to the port is not claimed.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPEXCL</constant></term>
+      <listitem>
+
+       <para>
+	Instructs the kernel driver to forbid any sharing of the port
+	with other drivers, i.e. it requests exclusivity.  The
+	<constant>PPEXCL</constant> command is only valid when the
+	port is not already claimed for use, and it may mean that the
+	next <constant>PPCLAIM</constant> <function>ioctl</function>
+	will fail: some other driver may already have registered
+	itself on that port.
+       </para>
+
+       <para>
+	Most device drivers don't need exclusive access to the port.
+	It's only provided in case it is really needed, for example
+	for devices where access to the port is required for extensive
+	periods of time (many seconds).
+       </para>
+
+       <para>
+	Note that the <constant>PPEXCL</constant>
+	<function>ioctl</function> doesn't actually claim the port
+	there and then---action is deferred until the
+	<constant>PPCLAIM</constant> <function>ioctl</function> is
+	performed.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPRELEASE</constant></term>
+      <listitem>
+
+       <para>
+	Releases the port.  Releasing the port undoes the effect of
+	claiming the port.  It allows other device drivers to talk to
+	their devices (assuming that there are any).
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPYIELD</constant></term>
+      <listitem>
+
+       <para>
+	Yields the port to another driver.  This
+	<function>ioctl</function> is a kind of short-hand for
+	releasing the port and immediately reclaiming it.  It gives
+	other drivers a chance to talk to their devices, but
+	afterwards claims the port back.  An example of using this
+	would be in a user-land printer driver: once a few characters
+	have been written we could give the port to another device
+	driver for a while, but if we still have characters to send to
+	the printer we would want the port back as soon as possible.
+       </para>
+
+       <para>
+	It is important not to claim the parallel port for too long,
+	as other device drivers will have no time to service their
+	devices.  If your device does not allow for parallel port
+	sharing at all, it is better to claim the parallel port
+	exclusively (see <constant>PPEXCL</constant>).
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPNEGOT</constant></term>
+      <listitem>
+
+       <para>
+	Performs IEEE 1284 negotiation into a particular mode.
+	Briefly, negotiation is the method by which the host and the
+	peripheral decide on a protocol to use when transferring data.
+       </para>
+
+       <para>
+	An IEEE 1284 compliant device will start out in compatibility
+	mode, and then the host can negotiate to another mode (such as
+	ECP).
+       </para>
+
+       <para>
+	The <function>ioctl</function> parameter should be a pointer
+	to an <type>int</type>; values for this are in
+	<filename>incluce/linux/parport.h</filename> and include:
+       </para>
+
+       <itemizedlist spacing=compact>
+	<listitem><para>
+	  <constant>IEEE1284_MODE_COMPAT</constant></para></listitem>
+	<listitem><para>
+	  <constant>IEEE1284_MODE_NIBBLE</constant></para></listitem>
+	<listitem><para>
+	  <constant>IEEE1284_MODE_BYTE</constant></para></listitem>
+	<listitem><para>
+	  <constant>IEEE1284_MODE_EPP</constant></para></listitem>
+	<listitem><para>
+	  <constant>IEEE1284_MODE_ECP</constant></para></listitem>
+       </itemizedlist>
+
+       <para>
+	The <constant>PPNEGOT</constant> <function>ioctl</function>
+	actually does two things: it performs the on-the-wire
+	negotiation, and it sets the behaviour of subsequent
+	<function>read</function>/<function>write</function> calls so
+	that they use that mode (but see
+	<constant>PPSETMODE</constant>).
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPSETMODE</constant></term>
+      <listitem>
+
+       <para>
+	Sets which IEEE 1284 protocol to use for the
+	<function>read</function> and <function>write</function>
+	calls.
+       </para>
+
+       <para>
+	The <function>ioctl</function> parameter should be a pointer
+	to an <type>int</type>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPGETTIME</constant></term>
+      <listitem>
+
+       <para>
+	Retrieves the time-out value.  The <function>read</function>
+	and <function>write</function> calls will time out if the
+	peripheral doesn't respond quickly enough.  The
+	<constant>PPGETTIME</constant> <function>ioctl</function>
+	retrieves the length of time that the peripheral is allowed to
+	have before giving up.
+       </para>
+
+       <para>
+	The <function>ioctl</function> parameter should be a pointer
+	to a <structname>struct timeval</structname>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPSETTIME</constant></term>
+      <listitem>
+
+       <para>
+	Sets the time-out.  The <function>ioctl</function> parameter
+	should be a pointer to a <structname>struct
+	timeval</structname>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPWCONTROL</constant></term>
+      <listitem>
+
+       <para>
+	Sets the control lines.  The <function>ioctl</function>
+	parameter is a pointer to an <type>unsigned char</type>, the
+	bitwise OR of the control line values in
+	<filename>include/linux/parport.h</filename>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPRCONTROL</constant></term>
+      <listitem>
+
+       <para>
+	Returns the last value written to the control register, in the
+	form of an <type>unsigned char</type>: each bit corresponds to
+	a control line (although some are unused).  The
+	<function>ioctl</function> parameter should be a pointer to an
+	<type>unsigned char</type>.
+       </para>
+
+       <para>
+	This doesn't actually touch the hardware; the last value
+	written is remembered in software.  This is because some
+	parallel port hardware does not offer read access to the
+	control register.
+       </para>
+
+       <para>
+	The control lines bits are defined in
+	<filename>include/linux/parport.h</filename>:
+       </para>
+
+       <itemizedlist spacing=compact>
+	<listitem><para>
+	  <constant>PARPORT_CONTROL_STROBE</constant></para></listitem>
+	  <listitem><para>
+	  <constant>PARPORT_CONTROL_AUTOFD</constant></para></listitem>
+	  <listitem><para>
+	  <constant>PARPORT_CONTROL_SELECT</constant></para></listitem>
+	  <listitem><para>
+	  <constant>PARPORT_CONTROL_INIT</constant></para></listitem>
+       </itemizedlist>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPFCONTROL</constant></term>
+      <listitem>
+
+       <para>
+	Frobs the control lines.  Since a common operation is to
+	change one of the control signals while leaving the others
+	alone, it would be quite inefficient for the user-land driver
+	to have to use <constant>PPRCONTROL</constant>, make the
+	change, and then use <constant>PPWCONTROL</constant>.  Of
+	course, each driver could remember what state the control
+	lines are supposed to be in (they are never changed by
+	anything else), but in order to provide
+	<constant>PPRCONTROL</constant>, <literal>ppdev</literal>
+	must remember the state of the control lines anyway.
+       </para>
+
+       <para>
+	The <constant>PPFCONTROL</constant> <function>ioctl</function>
+	is for <quote>frobbing</quote> control lines, and is like
+	<constant>PPWCONTROL</constant> but acts on a restricted set
+	of control lines.  The <function>ioctl</function> parameter is
+	a pointer to a <structname>struct
+	ppdev_frob_struct</structname>:
+       </para>
 
-<para>The <filename>ppdev</filename> driver provides user-land device
-drivers with the ability to wait for interrupts, and this is done
-using <function>poll</function> (and <function>select</function>,
-which is implemented in terms of <function>poll</function>).</para>
+       <programlisting>
+	<![CDATA[
+struct ppdev_frob_struct {
+        unsigned char mask;
+        unsigned char val;
+};
+	]]>
+       </programlisting>
 
-<para>When a user-land device driver wants to wait for an interrupt,
-it sleeps with <function>poll</function>.  When the interrupt arrives,
-<filename>ppdev</filename> wakes it up (with a <quote>read</quote>
-event, although strictly speaking there is nothing to actually
-<function>read</function>).</para>
+       <para>
+	The <structfield>mask</structfield> and
+	<structfield>val</structfield> fields are bitwise ORs of
+	control line names (such as in
+	<constant>PPWCONTROL</constant>).  The operation performed by
+	<constant>PPFCONTROL</constant> is:
+       </para>
+
+       <programlisting>
+	<![CDATA[
+	new_ctr = (old_ctr & ~mask) | val;]]>
+       </programlisting>
+
+       <para>
+	In other words, the signals named in
+	<structfield>mask</structfield> are set to the values in
+	<structfield>val</structfield>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPRSTATUS</constant></term>
+      <listitem>
+
+       <para>
+	Returns an <type>unsigned char</type> containing bits set for
+	each status line that is set (for instance,
+	<constant>PARPORT_STATUS_BUSY</constant>).  The
+	<function>ioctl</function> parameter should be a pointer to an
+	<type>unsigned char</type>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPDATADIR</constant></term>
+      <listitem>
+
+       <para>
+	Controls the data line drivers.  Normally the computer's
+	parallel port will drive the data lines, but for byte-wide
+	transfers from the peripheral to the host it is useful to turn
+	off those drivers and let the peripheral drive the
+	signals. (If the drivers on the computer's parallel port are
+	left on when this happens, the port might be damaged.)
+       </para>
+
+       <para>
+	This is only needed in conjunction with
+	<constant>PPWDATA</constant> or
+	<constant>PPRDATA</constant>.
+       </para>
+
+       <para>
+	The <function>ioctl</function> parameter is a pointer to an
+	<type>int</type>.  If the <type>int</type> is zero, the
+	drivers are turned on (forward direction); if non-zero, the
+	drivers are turned off (reverse direction).
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPWDATA</constant></term>
+      <listitem>
+
+       <para>
+	Sets the data lines (if in forward mode).  The
+	<function>ioctl</function> parameter is a pointer to an
+	<type>unsigned char</type>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPRDATA</constant></term>
+      <listitem>
+
+       <para>
+	Reads the data lines (if in reverse mode).  The
+	<function>ioctl</function> parameter is a pointer to an
+	<type>unsigned char</type>.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPCLRIRQ</constant></term>
+      <listitem>
+
+       <para>
+	Clears the interrupt count.  The <literal>ppdev</literal>
+	driver keeps a count of interrupts as they are triggered.
+	<constant>PPCLRIRQ</constant> stores this count in an
+	<type>int</type>, a pointer to which is passed in as the
+	<function>ioctl</function> parameter.
+       </para>
+
+       <para>
+	In addition, the interrupt count is reset to zero.
+       </para>
+
+      </listitem></varlistentry>
+
+     <varlistentry><term><constant>PPWCTLONIRQ</constant></term>
+      <listitem>
+
+       <para>
+	Set a trigger response.  Afterwards when an interrupt is
+	triggered, the interrupt handler will set the control lines as
+	requested.  The <function>ioctl</function> parameter is a
+	pointer to an <type>unsigned char</type>, which is interpreted
+	in the same way as for <constant>PPWCONTROL</constant>.
+       </para>
+
+       <para>
+	The reason for this <function>ioctl</function> is simply
+	speed.  Without this <function>ioctl</function>, responding to
+	an interrupt would start in the interrupt handler, switch
+	context to the user-land driver via <function>poll</function>
+	or <function>select</function>, and then switch context back
+	to the kernel in order to handle
+	<constant>PPWCONTROL</constant>.  Doing the whole lot in the
+	interrupt handler is a lot faster.
+       </para>
+
+      </listitem></varlistentry>
+
+     <!-- PPSETPHASE? -->
+
+    </variablelist>
+
+   </sect2>
+
+   <sect2>
+    <title>Transferring data: <function>read</function> and
+     <function>write</function></title>
+
+    <para>
+     Transferring data using <function>read</function> and
+     <function>write</function> is straightforward.  The data is
+     transferring using the current IEEE 1284 mode (see the
+     <constant>PPSETMODE</constant> <function>ioctl</function>).  For
+     modes which can only transfer data in one direction, only the
+     appropriate function will work, of course.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Waiting for events: <function>poll</function> and
+     <function>select</function></title>
+
+    <para>
+     The <literal>ppdev</literal> driver provides user-land device
+     drivers with the ability to wait for interrupts, and this is done
+     using <function>poll</function> (and <function>select</function>,
+     which is implemented in terms of <function>poll</function>).
+    </para>
+
+    <para>
+     When a user-land device driver wants to wait for an interrupt, it
+     sleeps with <function>poll</function>.  When the interrupt
+     arrives, <literal>ppdev</literal> wakes it up (with a
+     <quote>read</quote> event, although strictly speaking there is
+     nothing to actually <function>read</function>).
+    </para>
 
-</sect2>
+   </sect2>
 
-</sect1>
+  </sect1>
 
-<sect1>
-<title>Examples</title>
+  <sect1>
+   <title>Examples</title>
 
-<para>Presented here are two demonstrations of how to write a simple
-printer driver for <filename>ppdev</filename>.  Firstly we will use
-the <function>write</function> function, and after that we will drive
-the control and data lines directly.</para>
+   <para>
+    Presented here are two demonstrations of how to write a simple
+    printer driver for <literal>ppdev</literal>.  Firstly we will
+    use the <function>write</function> function, and after that we
+    will drive the control and data lines directly.
+   </para>
 
-<para>The first thing to do is to actually open the device.</para>
+   <para>
+    The first thing to do is to actually open the device.
+   </para>
 
-<programlisting><![CDATA[
+   <programlisting><![CDATA[
 int drive_printer (const char *name)
 {
     int fd;
@@ -1543,32 +1953,39 @@
         perror ("open");
         return 1;
     }
-]]></programlisting>
+    ]]></programlisting>
 
-<para>Here <varname>name</varname> should be something along the lines
-of <filename>"/dev/parport0"</filename>. (If you don't have any
-<filename>/dev/parport</filename> files, you can make them with
-<command>mknod</command>; they are character special device nodes with
-major 99.)</para>
+   <para>
+    Here <varname>name</varname> should be something along the lines
+    of <filename>"/dev/parport0"</filename>. (If you don't have any
+    <filename>/dev/parport</filename> files, you can make them with
+    <command>mknod</command>; they are character special device nodes
+    with major 99.)
+   </para>
 
-<para>In order to do anything with the port we need to claim access to
-it.</para>
+   <para>
+    In order to do anything with the port we need to claim access to
+    it.
+   </para>
 
-<programlisting><![CDATA[
+   <programlisting><![CDATA[
     if (ioctl (fd, PPCLAIM)) {
         perror ("PPCLAIM");
         close (fd);
         return 1;
     }
-]]></programlisting>
+    ]]></programlisting>
 
-<para>Our printer driver will copy its input (from
-<varname>stdin</varname>) to the printer, and it can do that it one of
-two ways.  The first way is to hand it all off to the kernel driver,
-with the knowledge that the protocol that the printer speaks is IEEE
-1284's <quote>compatibility</quote> mode.</para>
+   <para>
+    Our printer driver will copy its input (from
+    <varname>stdin</varname>) to the printer, and it can do that it
+    one of two ways.  The first way is to hand it all off to the
+    kernel driver, with the knowledge that the protocol that the
+    printer speaks is IEEE 1284's <quote>compatibility</quote>
+    mode.
+   </para>
 
-<programlisting><![CDATA[
+   <programlisting><![CDATA[
     /* Switch to compatibility mode.  (In fact we don't need
      * to do this, since we start off in compatibility mode
      * anyway, but this demonstrates PPNEGOT.)
@@ -1608,38 +2025,46 @@
             got -= written;
         }
     }
-]]></programlisting>
+    ]]></programlisting>
 
-<para>The <function>write_printer</function> function is not pictured
-above.  This is because the main loop that is shown can be used for
-both methods of driving the printer.  Here is one implementation of
-<function>write_printer</function>:</para>
+   <para>
+    The <function>write_printer</function> function is not pictured
+    above.  This is because the main loop that is shown can be used
+    for both methods of driving the printer.  Here is one
+    implementation of <function>write_printer</function>:
+   </para>
 
-<programlisting><![CDATA[
+   <programlisting><![CDATA[
 ssize_t write_printer (int fd, const void *ptr, size_t count)
 {
     return write (fd, ptr, count);
 }
-]]></programlisting>
+    ]]></programlisting>
+
+   <para>
+    We hand the data to the kernel-level driver (using
+    <function>write</function>) and it handles the printer
+    protocol.
+   </para>
+
+   <para>
+    Now let's do it the hard way!  In this particular example there is
+    no practical reason to do anything other than just call
+    <function>write</function>, because we know that the printer talks
+    an IEEE 1284 protocol.  On the other hand, this particular example
+    does not even need a user-land driver since there is already a
+    kernel-level one; for the purpose of this discussion, try to
+    imagine that the printer speaks a protocol that is not already
+    implemented under Linux.
+   </para>
 
-<para>We hand the data to the kernel-level driver (using
-<function>write</function>) and it handles the printer
-protocol.</para>
-
-<para>Now let's do it the hard way!  In this particular example there
-is no practical reason to do anything other than just call
-<function>write</function>, because we know that the printer talks an
-IEEE 1284 protocol.  On the other hand, this particular example does
-not even need a user-land driver since there is already a kernel-level
-one; for the purpose of this discussion, try to imagine that the
-printer speaks a protocol that is not already implemented under
-Linux.</para>
-
-<para>So, here is the alternative implementation of
-<function>write_printer</function> (for brevity, error checking has
-been omitted):</para>
+   <para>
+    So, here is the alternative implementation of
+    <function>write_printer</function> (for brevity, error checking
+    has been omitted):
+   </para>
 
-<programlisting><![CDATA[
+   <programlisting><![CDATA[
 ssize_t write_printer (int fd, const void *ptr, size_t count)
 {
     ssize_t wrote = 0;
@@ -1690,13 +2115,15 @@
 
     return wrote;
 }
-]]></programlisting>
+    ]]></programlisting>
 
-<para>To show a bit more of the <filename>ppdev</filename> interface,
-here is a small piece of code that is intended to mimic the printer's
-side of printer protocol.</para>
+   <para>
+    To show a bit more of the <literal>ppdev</literal> interface,
+    here is a small piece of code that is intended to mimic the
+    printer's side of printer protocol.
+   </para>
 
-<programlisting><![CDATA[
+   <programlisting><![CDATA[
   for (;;)
     {
       int irqc;
@@ -1739,9 +2166,158 @@
 
       putchar (ch);
     }
-]]></programlisting>
+    ]]></programlisting>
+
+   <para>
+    And here is an example (with no error checking at all) to show how
+    to read data from the port, using ECP mode, with optional
+    negotiation to ECP mode first.
+   </para>
+
+   <programlisting><![CDATA[
+    {
+      int fd, mode;
+      fd = open ("/dev/parport0", O_RDONLY | O_NOCTTY);
+      ioctl (fd, PPCLAIM);
+      mode = IEEE1284_MODE_ECP;
+      if (negotiate_first) {
+        ioctl (fd, PPNEGOT, &mode);
+        /* no need for PPSETMODE */
+      } else {
+        ioctl (fd, PPSETMODE, &mode);
+      }
+
+      /* Now do whatever we want with fd */
+      close (0);
+      dup2 (fd, 0);
+      if (!fork()) {
+        /* child */
+        execlp ("cat", "cat", NULL);
+        exit (1);
+      } else {
+        /* parent */
+        wait (NULL);
+      }
+
+      /* Okay, finished */
+      ioctl (fd, PPRELEASE);
+      close (fd);
+    }
+    ]]></programlisting>
+
+  </sect1>
+
+ </chapter>
 
-</sect1>
+ <appendix>
+  <title>
+   API reference
+  </title>
+
+!Fdrivers/parport/daisy.c parport_device_num
+!Fdrivers/parport/daisy.c parport_device_coords
+!Fdrivers/parport/daisy.c parport_find_device
+!Fdrivers/parport/daisy.c parport_find_class
+!Fdrivers/parport/share.c parport_register_driver
+!Fdrivers/parport/share.c parport_unregister_driver
+!Fdrivers/parport/share.c parport_register_device
+!Fdrivers/parport/share.c parport_unregister_device
+!Fdrivers/parport/daisy.c parport_open
+!Fdrivers/parport/daisy.c parport_close
+!Fdrivers/parport/share.c parport_claim
+!Fdrivers/parport/share.c parport_claim_or_block
+!Fdrivers/parport/share.c parport_release
+!Finclude/linux/parport.h parport_yield
+!Finclude/linux/parport.h parport_yield_blocking
+!Fdrivers/parport/ieee1284.c parport_negotiate
+!Fdrivers/parport/ieee1284.c parport_write
+!Fdrivers/parport/ieee1284.c parport_read
+!Fdrivers/parport/ieee1284.c parport_set_timeout
+
+ </appendix>
+
+ <appendix>
+  <title>
+   The Linux 2.2 Parallel Port Subsystem
+  </title>
+
+  <para>
+   Although the interface described in this document is largely new
+   with the 2.4 kernel, the sharing mechanism is available in the 2.2
+   kernel as well.  The functions available in 2.2 are:
+  </para>
+
+  <itemizedlist>
+   <listitem>
+    <para>
+     <function>parport_register_device</function>
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     <function>parport_unregister_device</function>
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     <function>parport_claim</function>
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     <function>parport_claim_or_block</function>
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     <function>parport_release</function>
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     <function>parport_yield</function>
+    </para>
+   </listitem>
+
+   <listitem>
+    <para>
+     <function>parport_yield_blocking</function>
+    </para>
+   </listitem>
+  </itemizedlist>
+
+  <para>
+   In addition, negotiation to reverse nibble mode is supported:
+  </para>
+
+  <funcsynopsis>
+   <funcprototype>
+     <funcdef>int <function>parport_ieee1284_nibble_mode_ok</function></funcdef>
+    <paramdef>struct parport *<parameter>port</parameter></paramdef>
+    <paramdef>unsigned char <parameter>mode</parameter></paramdef>
+   </funcprototype>
+  </funcsynopsis>
+
+  <para>
+   The only valid values for <parameter>mode</parameter> are 0 (for
+   reverse nibble mode) and 4 (for Device ID in reverse nibble mode).
+  </para>
+
+  <para>
+   This function is obsoleted by
+   <function>parport_negotiate</function> in Linux 2.4, and has been
+   removed.
+  </para>
+ </appendix>
+</book>
+
+<!-- Local Variables: -->
+<!-- sgml-indent-step: 1 -->
+<!-- sgml-indent-data: 1 -->
+<!-- End: -->
 
-</chapter>
-</book>
\ No newline at end of file
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/filesystems/cramfs.txt linux/Documentation/filesystems/cramfs.txt
--- v2.3.99-pre8/linux/Documentation/filesystems/cramfs.txt	Fri Jan 21 18:19:15 2000
+++ linux/Documentation/filesystems/cramfs.txt	Sat May 20 11:30:31 2000
@@ -27,8 +27,8 @@
 mkcramfs simply truncates to 8 bits, which is a potential security
 issue.
 
-Hard links are not supported, but symlinks are.  (See also the TODO
-comment in mkcramfs.c at the nlink test.)
+Hard links are supported, but hard linked files
+will still have a link count of 1 in the cramfs image.
 
 Cramfs directories have no `.' or `..' entries.  Directories (like
 every other file on cramfs) always have a link count of 1.  (There's
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/kbuild/config-language.txt linux/Documentation/kbuild/config-language.txt
--- v2.3.99-pre8/linux/Documentation/kbuild/config-language.txt	Thu May 11 15:30:05 2000
+++ linux/Documentation/kbuild/config-language.txt	Sun May 21 20:18:08 2000
@@ -193,7 +193,7 @@
 
 Configure:  implemented
 Menuconfig: implemented
-Xconfig:    does not display, but writes to output files
+Xconfig:    implemented
 mconfig:    implemented
 
 Example:
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/kernel-doc-nano-HOWTO.txt linux/Documentation/kernel-doc-nano-HOWTO.txt
--- v2.3.99-pre8/linux/Documentation/kernel-doc-nano-HOWTO.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/kernel-doc-nano-HOWTO.txt	Sun May 21 20:18:07 2000
@@ -0,0 +1,128 @@
+kernel-doc nano-HOWTO
+=====================
+
+Many places in the source tree have extractable documentation in the
+form of block comments above functions.  The components of this system
+are:
+
+- scripts/kernel-doc
+
+  This is a perl script that hunts for the block comments and can mark
+  them up directly into DocBook, man, text, and HTML. (No, not
+  texinfo.)
+
+- Documentation/DocBook/*.tmpl
+
+  These are SGML template files, which are normal SGML files with
+  special place-holders for where the extracted documentation should
+  go.
+
+- scripts/docproc.c
+
+  This is a program for converting SGML template files into SGML
+  files.  It invokes kernel-doc, giving it the list of functions that
+  are to be documented.
+
+- scripts/gen-all-syms
+
+  This is a script that lists the EXPORT_SYMBOL symbols in a list of C
+  files.
+
+- scripts/docgen
+
+  This script invokes docproc, telling it which functions are to be
+  documented (this list comes from gen-all-syms).
+
+- Makefile
+
+  The targets 'sgmldocs', 'psdocs', and 'pdfdocs' are used to build
+  DocBook files, PostScript files, and PDF files in
+  Documentation/DocBook.
+
+- Documentation/DocBook/Makefile
+
+  This is where C files are associated with SGML templates.
+
+
+How to extract the documentation
+--------------------------------
+
+If you just want to read the ready-made books on the various
+subsystems (see Documentation/DocBook/*.tmpl), just type 'make
+psdocs', or 'make pdfdocs', depending on your preference.  If you
+would rather read a different format, you can type 'make sgmldocs' and
+then use DocBook tools to convert Documentation/DocBook/*.sgml to a
+format of your choice (for example, 'db2html ...').
+
+If you want to see man pages instead, you can do this:
+
+$ cd linux
+$ scripts/kernel-doc -man $(find -name '*.c') | split-man.pl /tmp/man
+
+Here is split-man.pl:
+
+-->
+#!/usr/bin/perl
+
+if ($#ARGV < 0) {
+   die "where do I put the results?\n";
+}
+
+mkdir $ARGV[0],0777 or die "Can't create $ARGV[0]: $!\n";
+$state = 0;
+while (<STDIN>) {
+    if (/^\.TH \"[^\"]*\" 4 \"([^\"]*)\"/) {
+	if ($state == 1) { close OUT }
+	$state = 1;
+	$fn = "$ARGV[0]/$1.4";
+	print STDERR "Creating $fn\n";
+	open OUT, ">$fn" or die "can't open $fn: $!\n";
+	print OUT $_;
+    } elsif ($state != 0) {
+	print OUT $_;
+    }
+}
+
+close OUT;
+<--
+
+If you just want to view the documentation for one function in one
+file, you can do this:
+
+$ scripts/kernel-doc -man -function fn file | nroff -man | less
+
+or this:
+
+$ scripts/kernel-doc -text -function fn file
+
+
+How to add extractable documentation to your source files
+---------------------------------------------------------
+
+The format of the block comment is like this:
+
+/**
+ * function_name(:)? (- short description)?
+(* @parameterx: (description of parameter x)?)*
+(* a blank line)?
+ * (Description:)? (Description of function)?
+ * (section header: (section description)? )*
+(*)?*/
+
+The short function description cannot be multiline, but the other
+descriptions can be.
+
+All descriptive text is further processed, scanning for the following special
+patterns, which are highlighted appropriately.
+
+'funcname()' - function
+'$ENVVAR' - environment variable
+'&struct_name' - name of a structure (up to two words including 'struct')
+'@parameter' - name of a parameter
+'%CONST' - name of a constant.
+
+Take a look around the source tree for examples.
+
+Tim.
+*/ <twaugh@redhat.com>
+
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- v2.3.99-pre8/linux/Documentation/networking/8139too.txt	Thu May 11 15:30:05 2000
+++ linux/Documentation/networking/8139too.txt	Sat May 20 11:38:02 2000
@@ -132,6 +132,20 @@
 
 
 
+Submitting Bug Reports
+----------------------
+Obtain and compile the modified rtl8139-diag source code from the 
+8139too driver Web site.  This diagnostics programs, originally
+from Donald Becker, has been modified to display all registers
+on your RTL8139 chip, not just the first 0x80.
+
+If possible, send the output of a working and broken driver with
+	rtl8139-diag -mmmaaavvveefN > my-output-file.txt
+
+Send "lspci -vvv" or "cat /proc/pci" output for PCI information.
+
+
+
 Known Bugs / Errata / To-Do
 ---------------------------
 The following issues are known, and are actively being pursued.  Patches
@@ -149,7 +163,7 @@
 
 4) Sparc64 platform not tested at all.
 
-5) Identify and fix "rx wedge" when ping flooded.
+5) Identify and fix "rx wedge" when ping flooded. (WIP)
 
 7) N-Way auto-negotiation is known to fail in some cases.  This problem
 also occurs in the rtl8139 driver in kernels 2.2.x/2.3.x.  Solution:
@@ -158,17 +172,30 @@
 it automatically.  (patches welcome)
 
 8) Much improved command line / module parameter setup.  (patches and
-suggestions welcome)
+suggestions welcome)  (WIP)
 
 9) Better documentation.  (patches welcome)
 
-10) User-mode (or maybe optional /proc) diagnostics program.
+10) (rtl8139-diag modified from Becker version, DONE)
+User-mode (or maybe optional /proc) diagnostics program.
+
+11) RTL8139C support untested.
 
 
 
 
 Change History
 --------------
+Version 0.9.5 - May 17, 2000
+
+* Improved chip version recognition
+* Continue banging away at receiver hang problem
+* Use spin_lock_irq in another spot
+* Don't print anything on pci_enable_device, it does so for us
+* Disable buggy NWay code
+* Define TxConfig bitmasks
+
+
 Version 0.9.4.1 - April 27, 2000 - third public beta release
 
 * Replace several "magic numbers" with symbolic constants
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/pci.txt linux/Documentation/pci.txt
--- v2.3.99-pre8/linux/Documentation/pci.txt	Thu May 11 15:30:05 2000
+++ linux/Documentation/pci.txt	Mon May 15 12:13:10 2000
@@ -89,6 +89,16 @@
 			function otherwise.
 	__devexit	The same for __exit.
 
+Tips:
+	The module_init()/module_exit() functions (and all initialization
+        functions called only from these) should be marked __init/exit.
+	The struct pci_driver shouldn't be marked with any of these tags.
+	The ID table array should be marked __devinitdata.
+	The probe() and remove() functions (and all initialization
+	functions called only from these) should be marked __devinit/exit.
+	If you are sure the driver is not a hotplug driver then use only 
+	__init/exit __initdata/exitdata.
+
 
 2. How to find PCI devices manually (the old style)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/s390/DASD linux/Documentation/s390/DASD
--- v2.3.99-pre8/linux/Documentation/s390/DASD	Fri May 12 14:18:55 2000
+++ linux/Documentation/s390/DASD	Sat May 20 11:30:31 2000
@@ -22,7 +22,7 @@
 support of the FBA and CKD architectures. For the FBA architecture
 only some smart data structures are missing to make the support
 complete. 
-We performed our testing on 3380 and 3390 type disksof different
+We performed our testing on 3380 and 3390 type disks of different
 sizes, under VM and on the bare hardware (LPAR), using internal disks
 of the multiprise as well as a RAMAC virtual array. Disks exported by
 an Enterprise Storage Server (Seascape) should work fine as well.
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/usb/ov511.txt linux/Documentation/usb/ov511.txt
--- v2.3.99-pre8/linux/Documentation/usb/ov511.txt	Thu May 11 15:30:05 2000
+++ linux/Documentation/usb/ov511.txt	Sat May 20 10:37:04 2000
@@ -6,11 +6,8 @@
 Homepage: http://alpha.dyndns.org/ov511
 
 NEW IN THIS VERSION:
- o Improvements to sensor detection code
- o Added "i2c_detect_tries" and "aperture" parameters
- o proc filesystem status support
- o read() fixed partially
- o code cleanups and minor fixes
+ o 352x288 mode
+ o force_rgb parameter for apps that expect RGB instead of BGR
 
 INTRODUCTION:
 
@@ -139,7 +136,7 @@
         or so lines higher than the red component. This is only apparent in 
         images with white objects on black backgrounds at 640x480. Setting this
         to 1 will realign the color planes correctly. NOTE: This is still
-        experimental and very buggy.
+        experimental and very buggy. You will likely need a fast (500 Mhz) CPU.
 
   NAME: snapshot
   TYPE: integer (boolean)
@@ -148,8 +145,41 @@
         button is pressed. Note that this does not yet work with most apps,
         including xawtv and vidcat. NOTE: See the section "TODO" for more info.
 
+  NAME: sensor
+  TYPE: integer ([0, 1, 3])
+  DEFAULT: [varies]
+  DESC: If you know that your camera sensor is not detected correctly, set this
+        parameter. This is a global option for all attached OV511 cameras. You
+        will probably never need to set this, but if you do, valid values are:
+        	0 for OV7620
+        	1 for OV7620AE
+        	3 for OV7610
+
+  NAME: i2c_detect_tries
+  TYPE: integer (don't set it insanely high!)
+  DEFAULT: 5
+  DESC: This is the number of times the driver will try to sync and detect the
+        internal i2c bus (which connects the OV511 and sensor). If you are
+        getting intermittant detection failures ("Failed to read sensor ID...")
+        you should increase this by a modest amount. If setting it to 20 or so
+        doesn't fix things, look elsewhere for the cause of the problem.
+
+  NAME: aperture
+  TYPE: integer (0 - 15)
+  DEFAULT: [varies by sensor]
+  DESC: For legal values, see the OV7610/7620 specs under register Common F.
+        This setting affects the upper nybble of that reg (bits 4-7). This is
+        for if you want to play with the camera's pixel saturation.
+
+  NAME: force_rgb
+  TYPE: integer (boolean)
+  DEFAULT: 0
+  DESC: Force image to be read in RGB instead of BGR. This option allow
+        programs that expect RGB data (e.g. gqcam) to work with this driver. If
+        your colors look VERY wrong, you may want to change this.
+
 WORKING FEATURES:
- o Color streaming/capture at 640x480 and 320x240
+ o Color streaming/capture at 640x480, 352x288, and 320x240
  o YUV420 color
  o Monochrome
  o Setting/getting of saturation, contrast and brightness (no hue yet; only
@@ -158,7 +188,7 @@
 
 EXPERIMENTAL FEATURES:
  o fix_rgb_offset: Sometimes works, but other times causes errors with xawtv and
-   corrupted frames.
+   corrupted frames. If you have a very fast CPU, you can try it.
  o Snapshot mode (only works with some read() based apps; see below for more)
  o read() support
 
@@ -197,6 +227,6 @@
 
 The code is based in no small part on the CPiA driver by Johannes Erdfelt,
 Randy Dunlap, and others. Big thanks to them for their pioneering work on that
-and the USB stack. Thanks to Bret Wallach for getting camera reg IO , ISOC, and
-image capture working. Thanks to Orion Sky Lawlor and Kevin Moore for their
-work as well.
+and the USB stack. Thanks to Bret Wallach for getting camera reg IO, ISOC, and
+image capture working. Thanks to Orion Sky Lawlor, Kevin Moore, and Claudio
+Matsuoka for their work as well.
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- v2.3.99-pre8/linux/Documentation/usb/usb-serial.txt	Thu May 11 15:30:05 2000
+++ linux/Documentation/usb/usb-serial.txt	Sat May 20 11:39:56 2000
@@ -59,6 +59,13 @@
   properly enumerated, assigned a port, and then communication _should_ be
   possible. The driver cleans up properly when the device is removed, or
   the connection is canceled on the Visor.
+
+  NOTE:
+    This means that in order to talk to the Visor, the sync button must be
+    pressed BEFORE trying to get any program to communicate to the Visor.
+    This goes against the current documentation for pilot-xfer and other
+    packages, but is the only way that it will work due to the hardware
+    in the Visor.
   
   When the device is connected, try talking to it on the second port
   (this is usually /dev/ttyUSB1 if you do not have any other usb-serial
@@ -105,6 +112,24 @@
 
   This is an ISDN TA. Please report both successes and troubles to the
   author at omninet@kroah.com
+
+
+Digi AccelePort Driver
+
+  This driver supports the Digi AccelePort USB 4 device, a 4 port
+  USB serial converter.  The driver does NOT yet support the Digi
+  AccelePort USB 2 or 8.
+
+  The driver supports open, close, read, write, termios settings (baud
+  rate, word size, parity, stop bits, hardware/software flow control,
+  CREAD), DTR/RTS, and TIOCMGET/SET/BIS/BIC ioctls.  It has not been
+  thoroughly tested, but it seems to be working reasonable well.  There
+  is more work to do, including flow control, ioctls, and support for
+  the Digi AccelePort USB 2 and 8.
+
+  Please contact Peter Berger (pberger@brimson.com) or Al Borchers
+  (alborchers@steinerpoint.com) for questions or problems with this
+  driver.
 
 
 Generic Serial driver
diff -u --recursive --new-file v2.3.99-pre8/linux/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST
--- v2.3.99-pre8/linux/Documentation/video4linux/bttv/CARDLIST	Tue Apr 11 15:09:11 2000
+++ linux/Documentation/video4linux/bttv/CARDLIST	Mon May 15 12:06:25 2000
@@ -38,6 +38,10 @@
   card=36 - Typhoon TView TV/FM Tuner
   card=37 - PixelView PlayTV pro
   card=38 - TView99 CPH063
+  card=39 - Pinnacle PCTV Rave
+  card=40 - STB2
+  card=41 - AVerMedia TVPhone 98
+  card=42 - ProVideo PV951
 
 tuner.o
   type=0 - Temic PAL
diff -u --recursive --new-file v2.3.99-pre8/linux/MAINTAINERS linux/MAINTAINERS
--- v2.3.99-pre8/linux/MAINTAINERS	Thu May 11 15:30:05 2000
+++ linux/MAINTAINERS	Sat May 20 11:39:56 2000
@@ -482,6 +482,7 @@
 IDE DRIVER [GENERAL]
 P:	Andre Hedrick
 M:	andre@linux-ide.org
+M:	ahedrick@atipa.com
 M:	andre@suse.com
 L:	linux-kernel@vger.rutgers.edu
 W:	http://www.kernel.org/pub/linux/kernel/people/hedrick/
@@ -1139,6 +1140,13 @@
 L:	linux-usb@suse.com
 S:	Maintained
 
+USB OV511 DRIVER
+P:     Mark McClelland
+M:     mmcclelland@delphi.com
+L:     linux-usb@suse.com
+W:     http://alpha.dyndns.org/ov511/
+S:     Maintained
+
 USB PEGASUS DRIVER
 P:	Petko Manolov
 M:	petkan@spct.net
@@ -1148,6 +1156,13 @@
 USB PRINTER DRIVER
 P:	Vojtech Pavlik
 M:	vojtech@suse.cz
+L:	linux-usb@suse.com
+S:	Supported
+
+USB SERIAL DIGI ACCELEPORT DRIVER
+P:	Peter Berger and Al Borchers
+M:	pberger@brimson.com
+M:	alborchers@steinerpoint.com
 L:	linux-usb@suse.com
 S:	Supported
 
diff -u --recursive --new-file v2.3.99-pre8/linux/Makefile linux/Makefile
--- v2.3.99-pre8/linux/Makefile	Fri May 12 14:18:55 2000
+++ linux/Makefile	Mon May 15 15:30:20 2000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 3
 SUBLEVEL = 99
-EXTRAVERSION = -pre8
+EXTRAVERSION = -pre9
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -81,10 +81,6 @@
 #
 
 CPPFLAGS := -D__KERNEL__ -I$(HPATH)
-
-ifdef CONFIG_SMP
-CPPFLAGS += -D__SMP__
-endif
 
 CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.3.99-pre8/linux/arch/alpha/kernel/osf_sys.c	Thu May 11 15:30:05 2000
+++ linux/arch/alpha/kernel/osf_sys.c	Sat May 20 10:47:29 2000
@@ -42,7 +42,6 @@
 #include <asm/hwrpb.h>
 #include <asm/processor.h>
 
-extern long do_sys_mount(char *, char *, char *, int, void *);
 extern int do_pipe(int *);
 
 extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
@@ -377,7 +376,7 @@
 	retval = PTR_ERR(devname);
 	if (IS_ERR(devname))
 		goto out;
-	retval = do_sys_mount(devname, dirname, "ext2", flags, NULL);
+	retval = do_mount(devname, dirname, "ext2", flags, NULL);
 	putname(devname);
 out:
 	return retval;
@@ -396,7 +395,7 @@
 	retval = PTR_ERR(devname);
 	if (IS_ERR(devname))
 		goto out;
-	retval = do_sys_mount(devname, dirname, "iso9660", flags, NULL);
+	retval = do_mount(devname, dirname, "iso9660", flags, NULL);
 	putname(devname);
 out:
 	return retval;
@@ -409,7 +408,7 @@
 	if (copy_from_user(&tmp, args, sizeof(tmp)))
 		return -EFAULT;
 
-	return do_sys_mount("", dirname, "proc", flags, NULL);
+	return do_mount("", dirname, "proc", flags, NULL);
 }
 
 asmlinkage int osf_mount(unsigned long typenr, char *path, int flag, void *data)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.3.99-pre8/linux/arch/arm/Makefile	Fri May 12 14:18:55 2000
+++ linux/arch/arm/Makefile	Mon May 15 12:00:34 2000
@@ -182,7 +182,7 @@
 SUBDIRS		+= drivers/acorn
 DRIVERS		+= drivers/acorn/block/acorn-block.a
 DRIVERS		+= drivers/acorn/char/acorn-char.o
-DRIVERS		+= drivers/acorn/net/acorn-net.a
+DRIVERS		+= drivers/acorn/net/acorn-net.o
 DRIVERS		+= drivers/acorn/scsi/acorn-scsi.a
 endif
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/def-configs/ebsa110 linux/arch/arm/def-configs/ebsa110
--- v2.3.99-pre8/linux/arch/arm/def-configs/ebsa110	Thu May 11 15:30:05 2000
+++ linux/arch/arm/def-configs/ebsa110	Mon May 15 12:00:33 2000
@@ -10,7 +10,7 @@
 CONFIG_EXPERIMENTAL=y
 
 #
-# System and processor type
+# System and Processor Type
 #
 # CONFIG_ARCH_ARC is not set
 # CONFIG_ARCH_A5K is not set
@@ -25,6 +25,8 @@
 # CONFIG_PCI is not set
 # CONFIG_ISA is not set
 # CONFIG_ISA_DMA is not set
+# CONFIG_SBUS is not set
+# CONFIG_PCMCIA is not set
 
 #
 # Loadable module support
@@ -69,7 +71,6 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
 # CONFIG_I2O_BLOCK is not set
 # CONFIG_I2O_LAN is not set
 # CONFIG_I2O_SCSI is not set
@@ -87,13 +88,19 @@
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 
 #
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
 CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_RAID15_DANGEROUS is not set
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -124,7 +131,7 @@
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
+# CONFIG_MOUSE is not set
 # CONFIG_PSMOUSE is not set
 # CONFIG_82C710_MOUSE is not set
 # CONFIG_PC110_PAD is not set
@@ -141,6 +148,7 @@
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 # CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
 CONFIG_SOFT_WATCHDOG=y
 # CONFIG_PCWATCHDOG is not set
 # CONFIG_ACQUIRE_WDT is not set
@@ -173,6 +181,7 @@
 CONFIG_RTNETLINK=y
 # CONFIG_NETLINK_DEV is not set
 CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -222,6 +231,7 @@
 CONFIG_IP_NF_TARGET_REJECT=y
 # CONFIG_IP_NF_TARGET_MIRROR is not set
 CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=y
 CONFIG_IP_NF_TARGET_REDIRECT=y
 CONFIG_IP_NF_MANGLE=y
@@ -302,10 +312,12 @@
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
 CONFIG_PPP_ASYNC=y
 # CONFIG_PPP_SYNC_TTY is not set
 CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
 
 #
@@ -342,9 +354,10 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -354,10 +367,12 @@
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
-CONFIG_MINIX_FS=y
+# CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
@@ -365,23 +380,39 @@
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_EXT2_FS is not set
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/def-configs/footbridge linux/arch/arm/def-configs/footbridge
--- v2.3.99-pre8/linux/arch/arm/def-configs/footbridge	Thu May 11 15:30:05 2000
+++ linux/arch/arm/def-configs/footbridge	Mon May 15 12:00:33 2000
@@ -10,7 +10,7 @@
 CONFIG_EXPERIMENTAL=y
 
 #
-# System and processor type
+# System and Processor Type
 #
 # CONFIG_ARCH_ARC is not set
 # CONFIG_ARCH_A5K is not set
@@ -19,6 +19,10 @@
 CONFIG_FOOTBRIDGE=y
 CONFIG_HOST_FOOTBRIDGE=y
 # CONFIG_ADDIN_FOOTBRIDGE is not set
+
+#
+# Footbridge Implementations
+#
 CONFIG_ARCH_EBSA285=y
 # CONFIG_ARCH_CATS is not set
 CONFIG_ARCH_NETWINDER=y
@@ -30,7 +34,10 @@
 CONFIG_CPU_SA110=y
 CONFIG_PCI=y
 CONFIG_PCI_NAMES=y
+CONFIG_ISA=y
 CONFIG_ISA_DMA=y
+# CONFIG_SBUS is not set
+# CONFIG_PCMCIA is not set
 CONFIG_ALIGNMENT_TRAP=y
 
 #
@@ -137,7 +144,11 @@
 #
 CONFIG_BLK_DEV_LOOP=m
 CONFIG_BLK_DEV_NBD=m
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_RAID15_DANGEROUS is not set
 CONFIG_BLK_DEV_RAM=y
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -202,6 +213,7 @@
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
 # CONFIG_WDT is not set
+# CONFIG_WDTPCI is not set
 CONFIG_SOFT_WATCHDOG=y
 # CONFIG_PCWATCHDOG is not set
 # CONFIG_ACQUIRE_WDT is not set
@@ -242,6 +254,7 @@
 # CONFIG_VIDEO_PMS is not set
 # CONFIG_VIDEO_BWQCAM is not set
 # CONFIG_VIDEO_CQCAM is not set
+# CONFIG_VIDEO_CPIA is not set
 # CONFIG_VIDEO_SAA5249 is not set
 # CONFIG_TUNER_3036 is not set
 # CONFIG_VIDEO_STRADIS is not set
@@ -262,56 +275,6 @@
 # CONFIG_AGP is not set
 
 #
-# USB support
-#
-CONFIG_USB=m
-
-#
-# USB Controllers
-#
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
-CONFIG_USB_OHCI=m
-
-#
-# Miscellaneous USB options
-#
-# CONFIG_USB_DEVICEFS is not set
-
-#
-# USB Devices
-#
-CONFIG_USB_PRINTER=m
-CONFIG_USB_SCANNER=m
-CONFIG_USB_AUDIO=m
-# CONFIG_USB_ACM is not set
-# CONFIG_USB_SERIAL is not set
-# CONFIG_USB_CPIA is not set
-# CONFIG_USB_IBMCAM is not set
-# CONFIG_USB_OV511 is not set
-# CONFIG_USB_DC2XX is not set
-# CONFIG_USB_STORAGE is not set
-# CONFIG_USB_USS720 is not set
-# CONFIG_USB_DABUSB is not set
-# CONFIG_USB_PLUSB is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RIO500 is not set
-# CONFIG_USB_DSBR is not set
-
-#
-# USB HID
-#
-# CONFIG_USB_HID is not set
-CONFIG_USB_KBD=m
-CONFIG_USB_MOUSE=m
-# CONFIG_USB_WACOM is not set
-# CONFIG_USB_WMFORCE is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-
-#
 # Console drivers
 #
 CONFIG_VGA_CONSOLE=y
@@ -522,10 +485,12 @@
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
 CONFIG_PPP_ASYNC=m
 # CONFIG_PPP_SYNC_TTY is not set
 CONFIG_PPP_DEFLATE=m
 CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
 CONFIG_SLIP=m
 CONFIG_SLIP_COMPRESSED=y
 CONFIG_SLIP_SMART=y
@@ -588,9 +553,10 @@
 CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
-# CONFIG_BLK_DEV_AEC6210 is not set
-# CONFIG_AEC6210_TUNING is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD7409 is not set
 # CONFIG_AMD7409_OVERRIDE is not set
 # CONFIG_BLK_DEV_CMD64X is not set
@@ -610,6 +576,7 @@
 # CONFIG_BLK_DEV_SIS5513 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_VIA82CXXX_TUNING is not set
 CONFIG_BLK_DEV_SL82C105=y
 # CONFIG_IDE_CHIPSETS is not set
 CONFIG_IDEDMA_AUTO=y
@@ -625,6 +592,7 @@
 #
 CONFIG_SOUND=m
 # CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
@@ -633,6 +601,7 @@
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 CONFIG_SOUND_OSS=m
 # CONFIG_SOUND_TRACEINIT is not set
 # CONFIG_SOUND_DMAP is not set
@@ -643,6 +612,7 @@
 # CONFIG_SOUND_CS4232 is not set
 # CONFIG_SOUND_SSCAPE is not set
 # CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
 # CONFIG_SOUND_MSS is not set
@@ -657,7 +627,6 @@
 # CONFIG_SOUND_AWE32_SYNTH is not set
 # CONFIG_SOUND_WAVEFRONT is not set
 # CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_OPL3SA1 is not set
 # CONFIG_SOUND_OPL3SA2 is not set
@@ -670,8 +639,8 @@
 # File systems
 #
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=y
-# CONFIG_AUTOFS4_FS is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=y
 CONFIG_ADFS_FS=m
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -683,10 +652,12 @@
 CONFIG_VFAT_FS=m
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
@@ -694,17 +665,22 @@
 # CONFIG_DEVFS_DEBUG is not set
 CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
 # CONFIG_NFSD_V3 is not set
@@ -712,6 +688,16 @@
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
@@ -767,6 +753,57 @@
 # CONFIG_NLS_KOI8_R is not set
 
 #
+# USB support
+#
+CONFIG_USB=m
+CONFIG_USB_DEBUG=y
+
+#
+# Miscellaneous USB options
+#
+# CONFIG_USB_DEVICEFS is not set
+
+#
+# USB Controllers
+#
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_OHCI=m
+
+#
+# USB Devices
+#
+CONFIG_USB_PRINTER=m
+CONFIG_USB_SCANNER=m
+CONFIG_USB_AUDIO=m
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_USS720 is not set
+# CONFIG_USB_DABUSB is not set
+# CONFIG_USB_PLUSB is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_DSBR is not set
+
+#
+# USB HID
+#
+# CONFIG_USB_HID is not set
+CONFIG_USB_KBD=m
+CONFIG_USB_MOUSE=m
+# CONFIG_USB_WACOM is not set
+# CONFIG_USB_WMFORCE is not set
+# CONFIG_INPUT_KEYBDEV is not set
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+
+#
 # Kernel hacking
 #
 CONFIG_FRAME_POINTER=y
@@ -774,4 +811,5 @@
 CONFIG_DEBUG_USER=y
 # CONFIG_DEBUG_INFO is not set
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_LL is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_DC21285_PORT is not set
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/def-configs/rpc linux/arch/arm/def-configs/rpc
--- v2.3.99-pre8/linux/arch/arm/def-configs/rpc	Thu Feb 10 17:11:02 2000
+++ linux/arch/arm/def-configs/rpc	Mon May 15 12:00:33 2000
@@ -2,6 +2,7 @@
 # Automatically generated make config: don't edit
 #
 CONFIG_ARM=y
+CONFIG_UID16=y
 
 #
 # Code maturity level options
@@ -9,7 +10,7 @@
 CONFIG_EXPERIMENTAL=y
 
 #
-# System and processor type
+# System and Processor Type
 #
 # CONFIG_ARCH_ARC is not set
 # CONFIG_ARCH_A5K is not set
@@ -23,7 +24,11 @@
 CONFIG_CPU_ARM6=y
 CONFIG_CPU_ARM7=y
 CONFIG_CPU_SA110=y
+# CONFIG_PCI is not set
+# CONFIG_ISA is not set
 # CONFIG_ISA_DMA is not set
+# CONFIG_SBUS is not set
+# CONFIG_PCMCIA is not set
 # CONFIG_ALIGNMENT_TRAP is not set
 
 #
@@ -47,10 +52,14 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_ARTHUR is not set
+
+#
+# Parallel port support
+#
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 # CONFIG_PARPORT_PC_FIFO is not set
-# CONFIG_PARPORT_PC_PCMCIA is not set
+CONFIG_PARPORT_PC_SUPERIO=y
 # CONFIG_PARPORT_ARC is not set
 # CONFIG_PARPORT_AMIGA is not set
 # CONFIG_PARPORT_MFC3 is not set
@@ -63,7 +72,6 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
 # CONFIG_I2O_BLOCK is not set
 # CONFIG_I2O_LAN is not set
 # CONFIG_I2O_SCSI is not set
@@ -79,44 +87,23 @@
 # Block devices
 #
 CONFIG_BLK_DEV_FD=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_IDE is not set
-CONFIG_BLK_DEV_IDEDISK=y
-CONFIG_IDEDISK_MULTI_MODE=y
-CONFIG_BLK_DEV_IDECD=y
-# CONFIG_BLK_DEV_IDETAPE is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-
-#
-# IDE chipset support/bugfixes
-#
-# CONFIG_BLK_DEV_CMD640 is not set
-CONFIG_BLK_DEV_IDE_ICSIDE=y
-CONFIG_BLK_DEV_IDEDMA_ICS=y
-CONFIG_IDEDMA_ICS_AUTO=y
-CONFIG_BLK_DEV_IDE_RAPIDE=y
-CONFIG_BLK_DEV_IDEDMA=y
-CONFIG_IDEDMA_AUTO=y
-# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 
 #
 # Additional Block Devices
 #
 CONFIG_BLK_DEV_LOOP=m
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_RAID15_DANGEROUS is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_BLK_DEV_XD is not set
-CONFIG_PARIDE_PARPORT=y
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
 
 #
 # Acorn-specific block devices
@@ -139,6 +126,17 @@
 # CONFIG_PPDEV is not set
 
 #
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_PHILIPSPAR is not set
+# CONFIG_I2C_ELV is not set
+# CONFIG_I2C_VELLEMAN is not set
+# CONFIG_I2C_ALGOPCF is not set
+CONFIG_I2C_CHARDEV=y
+
+#
 # Mice
 #
 CONFIG_BUSMOUSE=y
@@ -177,20 +175,10 @@
 # CONFIG_FTAPE is not set
 # CONFIG_DRM is not set
 # CONFIG_DRM_TDFX is not set
-
-#
-# PCMCIA character device support
-#
-# CONFIG_PCMCIA_SERIAL_CS is not set
 # CONFIG_AGP is not set
 CONFIG_RPCMOUSE=y
 
 #
-# Support for USB
-#
-# CONFIG_USB is not set
-
-#
 # Console drivers
 #
 CONFIG_FB=y
@@ -201,10 +189,6 @@
 CONFIG_FB=y
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FB_ACORN=y
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_3DFX is not set
 # CONFIG_FB_VIRTUAL is not set
 CONFIG_FBCON_ADVANCED=y
 CONFIG_FBCON_MFB=y
@@ -222,6 +206,7 @@
 # CONFIG_FBCON_MAC is not set
 # CONFIG_FBCON_VGA_PLANES is not set
 # CONFIG_FBCON_VGA is not set
+# CONFIG_FBCON_HGA is not set
 # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
 CONFIG_FBCON_FONTS=y
 # CONFIG_FONT_8x8 is not set
@@ -298,6 +283,7 @@
 #
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -312,12 +298,10 @@
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
-# CONFIG_RTL8139 is not set
-# CONFIG_DM9102 is not set
 # CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -330,10 +314,12 @@
 # CONFIG_HIPPI is not set
 # CONFIG_PLIP is not set
 CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
 # CONFIG_PPP_ASYNC is not set
 # CONFIG_PPP_SYNC_TTY is not set
 # CONFIG_PPP_DEFLATE is not set
 # CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
 
 #
@@ -342,7 +328,7 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring driver support
+# Token Ring devices
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -355,9 +341,42 @@
 # CONFIG_WAN is not set
 
 #
-# PCMCIA network device support
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
 #
-# CONFIG_NET_PCMCIA is not set
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+CONFIG_BLK_DEV_IDE_ICSIDE=y
+CONFIG_BLK_DEV_IDEDMA_ICS=y
+CONFIG_IDEDMA_ICS_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
+CONFIG_BLK_DEV_IDE_RAPIDE=y
+# CONFIG_IDE_CHIPSETS is not set
+CONFIG_IDEDMA_AUTO=y
+# CONFIG_BLK_DEV_IDE_MODES is not set
 
 #
 # SCSI support
@@ -368,9 +387,11 @@
 # SCSI support type (disk, tape, CD-ROM)
 #
 CONFIG_BLK_DEV_SD=y
-# CONFIG_CHR_DEV_ST is not set
+CONFIG_SD_EXTRA_DEVS=8
+CONFIG_CHR_DEV_ST=m
 CONFIG_BLK_DEV_SR=y
 CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
 
 #
@@ -390,12 +411,12 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
@@ -403,6 +424,8 @@
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
 CONFIG_SCSI_PPA=m
 CONFIG_SCSI_IMM=m
 # CONFIG_SCSI_IZIP_EPP16 is not set
@@ -410,15 +433,14 @@
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
 # CONFIG_SCSI_DEBUG is not set
 CONFIG_SCSI_ACORNSCSI_3=m
 CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE=y
@@ -439,6 +461,7 @@
 #
 CONFIG_SOUND=m
 # CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
@@ -447,12 +470,18 @@
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
 # CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
 CONFIG_SOUND_OSS=m
+# CONFIG_SOUND_TRACEINIT is not set
+# CONFIG_SOUND_DMAP is not set
 # CONFIG_SOUND_AD1816 is not set
 # CONFIG_SOUND_SGALAXY is not set
+# CONFIG_SOUND_ADLIB is not set
+# CONFIG_SOUND_ACI_MIXER is not set
 # CONFIG_SOUND_CS4232 is not set
 # CONFIG_SOUND_SSCAPE is not set
 # CONFIG_SOUND_GUS is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
 # CONFIG_SOUND_MSS is not set
@@ -460,30 +489,29 @@
 # CONFIG_SOUND_NM256 is not set
 # CONFIG_SOUND_MAD16 is not set
 # CONFIG_SOUND_PAS is not set
+# CONFIG_PAS_JOYSTICK is not set
 # CONFIG_SOUND_PSS is not set
-# CONFIG_SOUND_SOFTOSS is not set
+CONFIG_SOUND_SOFTOSS=m
 # CONFIG_SOUND_SB is not set
+# CONFIG_SOUND_AWE32_SYNTH is not set
 # CONFIG_SOUND_WAVEFRONT is not set
 # CONFIG_SOUND_MAUI is not set
-# CONFIG_SOUND_VIA82CXXX is not set
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_OPL3SA1 is not set
 # CONFIG_SOUND_OPL3SA2 is not set
 # CONFIG_SOUND_UART6850 is not set
+# CONFIG_SOUND_AEDSP16 is not set
 CONFIG_SOUND_VIDC=m
 # CONFIG_SOUND_WAVEARTIST is not set
 
 #
-# Additional low level sound drivers
-#
-# CONFIG_LOWLEVEL_SOUND is not set
-
-#
-# Filesystems
+# File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
 CONFIG_ADFS_FS=y
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -492,35 +520,66 @@
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
 #
 CONFIG_PARTITION_ADVANCED=y
+CONFIG_ACORN_PARTITION=y
+CONFIG_ACORN_PARTITION_ICS=y
+CONFIG_ACORN_PARTITION_ADFS=y
+CONFIG_ACORN_PARTITION_POWERTEC=y
+CONFIG_ACORN_PARTITION_RISCIX=y
 CONFIG_OSF_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+# CONFIG_ATARI_PARTITION is not set
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 CONFIG_BSD_DISKLABEL=y
@@ -528,13 +587,6 @@
 # CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
 CONFIG_SUN_PARTITION=y
-CONFIG_AMIGA_PARTITION=y
-# CONFIG_ATARI_PARTITION is not set
-CONFIG_ACORN_PARTITION=y
-CONFIG_ACORN_PARTITION_ADFS=y
-CONFIG_ACORN_PARTITION_ICS=y
-CONFIG_ACORN_PARTITION_POWERTEC=y
-CONFIG_ACORN_PARTITION_RISCIX=y
 CONFIG_NLS=y
 
 #
@@ -568,6 +620,11 @@
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 CONFIG_NLS_KOI8_R=m
+
+#
+# USB support
+#
+# CONFIG_USB is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- v2.3.99-pre8/linux/arch/arm/kernel/Makefile	Fri May 12 14:18:55 2000
+++ linux/arch/arm/kernel/Makefile	Mon May 15 12:00:33 2000
@@ -34,7 +34,7 @@
 
 export-objs		:= armksyms.o dma.o ecard.o hw-footbridge.o leds-$(MACHINE).o
 
-obj-$(CONFIG_ARCH_ACORN) += dma.o ecard.o iic.o fiq.o time-acorn.o
+obj-$(CONFIG_ARCH_ACORN) += dma.o ecard.o fiq.o time-acorn.o
 obj-$(CONFIG_DEBUG_LL)	+= debug-$(PROCESSOR).o
 obj-$(CONFIG_MODULES)	+= armksyms.o
 obj-$(CONFIG_LEDS)	+= leds-$(MACHINE).o
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/kernel/iic.c linux/arch/arm/kernel/iic.c
--- v2.3.99-pre8/linux/arch/arm/kernel/iic.c	Thu Jun 17 01:11:35 1999
+++ linux/arch/arm/kernel/iic.c	Wed Dec 31 16:00:00 1969
@@ -1,248 +0,0 @@
-/*
- * linux/arch/arm/kernel/iic.c
- *
- * Copyright (C) 1995, 1996 Russell King
- *
- * IIC is used to get the current time from the CMOS rtc.
- */
-
-#include <linux/delay.h>
-#include <linux/errno.h>
-
-#include <asm/system.h>
-#include <asm/hardware.h>
-#include <asm/io.h>
-#include <asm/ioc.h>
-
-#define FORCE_ONES	0xdc
-
-/*
- * if delay loop has been calibrated then us that,
- * else use IOC timer 1.
- */
-static void iic_delay(void)
-{
-	extern unsigned long loops_per_sec;
-	if (loops_per_sec != (1 << 12)) {
-		udelay(100); /* was 10 */
-		return;
-	} else {
-		unsigned long flags;
-		save_flags_cli(flags);
-
-		outb(254,  IOC_T1LTCHL);
-		outb(255,  IOC_T1LTCHH);
-		outb(0,    IOC_T1GO);
-		outb(1<<6, IOC_IRQCLRA);			/* clear T1 irq */
-		outb(10,   IOC_T1LTCHL); /* was 4 */
-		outb(0,    IOC_T1LTCHH);
-		outb(0,    IOC_T1GO);
-		while ((inb(IOC_IRQSTATA) & (1<<6)) == 0);
-		restore_flags(flags);
-	}
-}
-
-#define IIC_INIT()		dat = (inb(IOC_CONTROL) | FORCE_ONES) & ~3
-#define IIC_SET_DAT		outb(dat|=1, IOC_CONTROL);
-#define IIC_CLR_DAT		outb(dat&=~1, IOC_CONTROL);
-#define IIC_SET_CLK		outb(dat|=2, IOC_CONTROL);
-#define IIC_CLR_CLK		outb(dat&=~2, IOC_CONTROL);
-#define IIC_DELAY		iic_delay();
-#define IIC_READ_DATA()		(inb(IOC_CONTROL) & 1)
-
-static inline void iic_set_lines(int clk, int dat)
-{
-	int old;
-
-	old = inb(IOC_CONTROL) | FORCE_ONES;
-
-	old &= ~3;
-
-	if (clk)
-		old |= 2;
-	if (dat)
-		old |= 1;
-
-	outb(old, IOC_CONTROL);
-
-	iic_delay();
-}
-
-static inline unsigned int iic_read_data(void)
-{
-	return inb(IOC_CONTROL) & 1;
-}
-
-/*
- * C: ==~~_
- * D: =~~__
- */
-static inline void iic_start(void)
-{
-	unsigned int dat;
-
-	IIC_INIT();
-
-	IIC_SET_DAT
-	IIC_DELAY
-	IIC_SET_CLK
-	IIC_DELAY
-
-	IIC_CLR_DAT
-	IIC_DELAY
-	IIC_CLR_CLK
-	IIC_DELAY
-}
-
-/*
- * C: __~~
- * D: =__~
- */
-static inline void iic_stop(void)
-{
-	unsigned int dat;
-
-	IIC_INIT();
-
-	IIC_CLR_DAT
-	IIC_DELAY
-	IIC_SET_CLK
-	IIC_DELAY
-	IIC_SET_DAT
-	IIC_DELAY
-}
-
-/*
- * C: __~_
- * D: =___
- */
-static inline void iic_acknowledge(void)
-{
-	unsigned int dat;
-
-	IIC_INIT();
-
-	IIC_CLR_DAT
-	IIC_DELAY
-	IIC_SET_CLK
-	IIC_DELAY
-	IIC_CLR_CLK
-	IIC_DELAY
-}
-
-/*
- * C: __~_
- * D: =~H~
- */
-static inline int iic_is_acknowledged(void)
-{
-	unsigned int dat, ack_bit;
-
-	IIC_INIT();
-
-	IIC_SET_DAT
-	IIC_DELAY
-	IIC_SET_CLK
-	IIC_DELAY
-
-	ack_bit = IIC_READ_DATA();
-
-	IIC_CLR_CLK
-	IIC_DELAY
-
-	return ack_bit == 0;
-}
-
-/*
- * C: _~__~__~__~__~__~__~__~_
- * D: =DDXDDXDDXDDXDDXDDXDDXDD
- */
-static void iic_sendbyte(unsigned int b)
-{
-	unsigned int dat, i;
-
-	IIC_INIT();
-
-	for (i = 0; i < 8; i++) {
-		if (b & 128)
-			IIC_SET_DAT
-		else
-			IIC_CLR_DAT
-		IIC_DELAY
-
-		IIC_SET_CLK
-		IIC_DELAY
-		IIC_CLR_CLK
-		IIC_DELAY
-
-		b <<= 1;
-	}
-}
-
-/*
- * C: __~_~_~_~_~_~_~_~_
- * D: =~HHHHHHHHHHHHHHHH
- */
-static unsigned char iic_recvbyte(void)
-{
-	unsigned int dat, i, in;
-
-	IIC_INIT();
-
-	IIC_SET_DAT
-	IIC_DELAY
-
-	in = 0;
-	for (i = 0; i < 8; i++) {
-		IIC_SET_CLK
-		IIC_DELAY
-
-		in = (in << 1) | IIC_READ_DATA();
-
-		IIC_CLR_CLK
-		IIC_DELAY
-	}
-
-	return in;
-}
-
-int iic_control (unsigned char addr, unsigned char loc, unsigned char *buf, int len)
-{
-	int i, err = -EIO;
-
-	iic_start();
-	iic_sendbyte(addr & 0xfe);
-	if (!iic_is_acknowledged())
-		goto error;
-
-	iic_sendbyte(loc);
-	if (!iic_is_acknowledged())
-		goto error;
-
-	if (addr & 1) {
-		iic_stop();
-		iic_start();
-		iic_sendbyte(addr|1);
-		if (!iic_is_acknowledged())
-			goto error;
-
-		for (i = 0; i < len - 1; i++) {
-			buf[i] = iic_recvbyte();
-			iic_acknowledge();
-		}
-		buf[i] = iic_recvbyte();
-	} else {
-		for (i = 0; i < len; i++) {
-			iic_sendbyte(buf[i]);
-
-			if (!iic_is_acknowledged())
-				goto error;
-		}
-	}
-
-	err = 0;
-error:
-	iic_stop();
-
-	return err;
-}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.3.99-pre8/linux/arch/arm/kernel/traps.c	Thu Feb 10 17:11:03 2000
+++ linux/arch/arm/kernel/traps.c	Mon May 15 16:41:29 2000
@@ -399,13 +399,13 @@
 	printk(KERN_CRIT"kernel BUG at %s:%d!\n", file, line);
 	if (data)
 		printk(KERN_CRIT"extra data = %p\n", data);
-	*(int *)0 = 0;
+	BUG();
 }
 
 void __readwrite_bug(const char *fn)
 {
 	printk("%s called, but not implemented", fn);
-	*(int *)0 = 0;
+	BUG();
 }
 
 void __pte_error(const char *file, int line, unsigned long val)
@@ -436,7 +436,7 @@
 	printk(KERN_CRIT "abort() called from %p!  (Please "
 	       "report to rmk@arm.linux.org.uk)\n", lr);
 
-	*(int *)0 = 0;
+	BUG();
 
 	/* if that doesn't kill us, halt */
 	panic("Oops failed to kill thread");
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.3.99-pre8/linux/arch/arm/lib/Makefile	Tue Apr 11 15:09:12 2000
+++ linux/arch/arm/lib/Makefile	Mon May 15 12:00:33 2000
@@ -20,6 +20,7 @@
 L_OBJS_clps7500		:= io-acorn.o
 L_OBJS_ebsa110		:= io-ebsa110.o
 L_OBJS_footbridge	:= io-footbridge.o
+L_OBJS_l7200     	:= io-acorn.o
 L_OBJS_nexuspci		:= io-footbridge.o
 L_OBJS_sa1100		:= io-footbridge.o
 L_OBJS_shark		:= io-shark.o
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.3.99-pre8/linux/arch/i386/config.in	Thu May 11 15:30:05 2000
+++ linux/arch/i386/config.in	Tue May 23 08:22:22 2000
@@ -180,7 +180,6 @@
    bool '    Enable PM at boot time' CONFIG_APM_DO_ENABLE
    bool '    Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
    bool '    Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
-   bool '    Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
    bool '    Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
    bool '    RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
    bool '    Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.3.99-pre8/linux/arch/i386/defconfig	Fri May 12 14:18:55 2000
+++ linux/arch/i386/defconfig	Mon May 15 13:11:34 2000
@@ -111,7 +111,6 @@
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
-# CONFIG_RAID15_DANGEROUS is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_BLK_DEV_INITRD is not set
 
@@ -169,6 +168,13 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
 # CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/acpi.c linux/arch/i386/kernel/acpi.c
--- v2.3.99-pre8/linux/arch/i386/kernel/acpi.c	Thu May 11 15:30:06 2000
+++ linux/arch/i386/kernel/acpi.c	Mon May 15 12:14:19 2000
@@ -829,7 +829,7 @@
 	{0x8086, 0x7113, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_INTEL_PIIX4},
 	{0x1106, 0x3040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_586},
 	{0x1106, 0x3057, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_VIA_686A},
-	{0,}, /* terminate list */
+	{0,} /* terminate list */
 };
 
 static int __init acpi_probe(struct pci_dev *dev,
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- v2.3.99-pre8/linux/arch/i386/kernel/apic.c	Thu May 11 15:30:06 2000
+++ linux/arch/i386/kernel/apic.c	Sat May 13 07:37:34 2000
@@ -30,11 +30,6 @@
 int prof_old_multiplier[NR_CPUS] = { 1, };
 int prof_counter[NR_CPUS] = { 1, };
 
-/*
- * IA s/w dev Vol 3, Section 7.4
- */
-#define APIC_DEFAULT_PHYS_BASE 0xfee00000
-
 int get_maxlvt(void)
 {
 	unsigned int v, ver, maxlvt;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.3.99-pre8/linux/arch/i386/kernel/apm.c	Fri Mar 10 16:40:39 2000
+++ linux/arch/i386/kernel/apm.c	Tue May 23 08:22:22 2000
@@ -132,6 +132,9 @@
  *   1.13: Changes for new pm_ interfaces (Andy Henroid
  *         <andy_henroid@yahoo.com>).
  *         Modularize the code.
+ *         Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
+ *         is now the way life works).
+ *         Fix thinko in suspend() (wrong return).
  *
  * APM 1.1 Reference:
  *
@@ -308,9 +311,7 @@
 #endif
 static int			suspends_pending = 0;
 static int			standbys_pending = 0;
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 static int			waiting_for_resume = 0;
-#endif
 
 #ifdef CONFIG_APM_RTC_IS_GMT
 #	define	clock_cmos_diff	0
@@ -866,22 +867,22 @@
 static int suspend(void)
 {
 	int		err;
-	int		ret;
 	struct apm_user	*as;
 
 	get_time_diff();
 	err = apm_set_power_state(APM_STATE_SUSPEND);
 	reinit_timer();
 	set_time();
-	ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
-	if (!ret)
+	if (err == APM_NO_ERROR)
+		err = APM_SUCCESS;
+	if (err != APM_SUCCESS)
 		apm_error("suspend", err);
 	for (as = user_list; as != NULL; as = as->next) {
 		as->suspend_wait = 0;
-		as->suspend_result = (ret ? 0 : -EIO);
+		as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
 	}
 	wake_up_interruptible(&apm_suspend_waitqueue);
-	return ret;
+	return err;
 }
 
 static void standby(void)
@@ -962,14 +963,7 @@
 		switch (event) {
 		case APM_SYS_STANDBY:
 		case APM_USER_STANDBY:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-			if (waiting_for_resume)
-				break;
-#endif
 			if (send_event(event, NULL)) {
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
-				waiting_for_resume = 1;
-#endif
 				if (standbys_pending <= 0)
 					standby();
 			}
@@ -986,14 +980,18 @@
 			if (ignore_bounce)
 				break;
 #endif
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
+			/*
+			 * If we are already processing a SUSPEND,
+			 * then further SUSPEND events from the BIOS
+			 * will be ignored.  We also return here to
+			 * cope with the fact that the Thinkpads keep
+			 * sending a SUSPEND event until something else
+			 * happens!
+			 */
 			if (waiting_for_resume)
-				break;
-#endif
+				return;
 			if (send_event(event, NULL)) {
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 				waiting_for_resume = 1;
-#endif
 				if (suspends_pending <= 0)
 					(void) suspend();
 			}
@@ -1002,9 +1000,7 @@
 		case APM_NORMAL_RESUME:
 		case APM_CRITICAL_RESUME:
 		case APM_STANDBY_RESUME:
-#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
 			waiting_for_resume = 0;
-#endif
 #ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
 			last_resume = jiffies;
 			ignore_bounce = 1;
@@ -1036,8 +1032,10 @@
 	int		err;
 
 	if ((standbys_pending > 0) || (suspends_pending > 0)) {
-		if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) {
+		if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
 			pending_count = 4;
+			if (debug)
+				printk(KERN_DEBUG "apm: setting state busy\n");
 			err = apm_set_power_state(APM_STATE_BUSY);
 			if (err)
 				apm_error("busy", err);
@@ -1097,7 +1095,7 @@
 static int check_apm_user(struct apm_user *as, const char *func)
 {
 	if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
-		printk(KERN_ERR "apm: %s passed bad filp", func);
+		printk(KERN_ERR "apm: %s passed bad filp\n", func);
 		return 1;
 	}
 	return 0;
@@ -1200,7 +1198,7 @@
 		} else if (!send_event(APM_USER_SUSPEND, as))
 			return -EAGAIN;
 		if (suspends_pending <= 0) {
-			if (!suspend())
+			if (suspend() != APM_SUCCESS)
 				return -EIO;
 		} else {
 			as->suspend_wait = 1;
@@ -1251,7 +1249,7 @@
 		     as1 = as1->next)
 			;
 		if (as1 == NULL)
-			printk(KERN_ERR "apm: filp not in user list");
+			printk(KERN_ERR "apm: filp not in user list\n");
 		else
 			as1->next = as->next;
 	}
@@ -1268,7 +1266,7 @@
 
 	as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
 	if (as == NULL) {
-		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
+		printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
 		       sizeof(*as));
 		MOD_DEC_USE_COUNT;
 		return -ENOMEM;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c
--- v2.3.99-pre8/linux/arch/i386/kernel/i8259.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/i386/kernel/i8259.c	Sat May 13 07:37:34 2000
@@ -456,7 +456,7 @@
 	 * IRQ0 must be given a fixed assignment and initialized,
 	 * because it's used before the IO-APIC is set up.
 	 */
-	set_intr_gate(IRQ0_TRAP_VECTOR, interrupt[0]);
+	set_intr_gate(FIRST_DEVICE_VECTOR, interrupt[0]);
 
 	/*
 	 * The reschedule interrupt is a CPU-to-CPU reschedule-helper
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.3.99-pre8/linux/arch/i386/kernel/io_apic.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/i386/kernel/io_apic.c	Sat May 13 07:37:34 2000
@@ -48,6 +48,11 @@
 /* MP IRQ source entries */
 int mp_irq_entries = 0;
 
+#if CONFIG_SMP
+# define TARGET_CPUS cpu_online_map
+#else
+# define TARGET_CPUS 0x01
+#endif
 /*
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
@@ -89,7 +94,7 @@
 	entry->pin = pin;
 }
 
-#define __DO_ACTION(name,R,ACTION, FINAL)				\
+#define __DO_ACTION(R, ACTION, FINAL)					\
 									\
 {									\
 	int pin;							\
@@ -112,8 +117,8 @@
 
 #define DO_ACTION(name,R,ACTION, FINAL)					\
 									\
-static void name##_IO_APIC_irq(unsigned int irq)			\
-__DO_ACTION(name,R,ACTION, FINAL)
+	static void name##_IO_APIC_irq (unsigned int irq)		\
+	__DO_ACTION(R, ACTION, FINAL)
 
 DO_ACTION( __mask,    0, |= 0x00010000, io_apic_sync(entry->apic))/* mask = 1 */
 DO_ACTION( __unmask,  0, &= 0xfffeffff, )				/* mask = 0 */
@@ -542,25 +547,26 @@
 	return 0;
 }
 
-int irq_vector[NR_IRQS] = { IRQ0_TRAP_VECTOR , 0 };
+int irq_vector[NR_IRQS] = { FIRST_DEVICE_VECTOR , 0 };
 
 static int __init assign_irq_vector(int irq)
 {
-	static int current_vector = IRQ0_TRAP_VECTOR, offset = 0;
+	static int current_vector = FIRST_DEVICE_VECTOR, offset = 0;
 	if (IO_APIC_VECTOR(irq) > 0)
 		return IO_APIC_VECTOR(irq);
-	if (current_vector == 0xFF)
-		panic("ran out of interrupt sources!");
 next:
 	current_vector += 8;
 	if (current_vector == SYSCALL_VECTOR)
 		goto next;
 
-	if (current_vector > 0xFF) {
+	if (current_vector > FIRST_SYSTEM_VECTOR) {
 		offset++;
-		current_vector = IRQ0_TRAP_VECTOR + offset;
+		current_vector = FIRST_DEVICE_VECTOR + offset;
 	}
 
+	if (current_vector == FIRST_SYSTEM_VECTOR)
+		panic("ran out of interrupt sources!");
+
 	IO_APIC_VECTOR(irq) = current_vector;
 	return current_vector;
 }
@@ -587,7 +593,7 @@
 		entry.delivery_mode = dest_LowestPrio;
 		entry.dest_mode = 1;			/* logical delivery */
 		entry.mask = 0;				/* enable IRQ */
-		entry.dest.logical.logical_dest = APIC_ALL_CPUS;
+		entry.dest.logical.logical_dest = TARGET_CPUS;
 
 		idx = find_irq_entry(apic,pin,mp_INT);
 		if (idx == -1) {
@@ -605,7 +611,7 @@
 		if (irq_trigger(idx)) {
 			entry.trigger = 1;
 			entry.mask = 1;
-			entry.dest.logical.logical_dest = APIC_ALL_CPUS;
+			entry.dest.logical.logical_dest = TARGET_CPUS;
 		}
 
 		irq = pin_2_irq(idx, apic, pin);
@@ -660,7 +666,7 @@
 	 */
 	entry.dest_mode = 1;				/* logical delivery */
 	entry.mask = 0;					/* unmask IRQ now */
-	entry.dest.logical.logical_dest = APIC_ALL_CPUS;
+	entry.dest.logical.logical_dest = TARGET_CPUS;
 	entry.delivery_mode = dest_LowestPrio;
 	entry.polarity = 0;
 	entry.trigger = 0;
@@ -1167,7 +1173,7 @@
 	mask = mask << 24;
 
 	spin_lock_irqsave(&ioapic_lock, flags);
-	__DO_ACTION( target,  1, = mask, )
+	__DO_ACTION(1, = mask, )
 	spin_unlock_irqrestore(&ioapic_lock, flags);
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.3.99-pre8/linux/arch/i386/kernel/irq.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/i386/kernel/irq.c	Sat May 13 07:37:34 2000
@@ -1117,7 +1117,8 @@
 	struct proc_dir_entry *entry;
 	char name [MAX_NAMELEN];
 
-	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type))
+	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type) ||
+			irq_dir[irq])
 		return;
 
 	memset(name, 0, MAX_NAMELEN);
@@ -1158,10 +1159,7 @@
 	/*
 	 * Create entries for all existing IRQs.
 	 */
-	for (i = 0; i < NR_IRQS; i++) {
-		if (irq_desc[i].handler == &no_irq_type)
-			continue;
+	for (i = 0; i < NR_IRQS; i++)
 		register_irq_proc(i);
-	}
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/ldt.c linux/arch/i386/kernel/ldt.c
--- v2.3.99-pre8/linux/arch/i386/kernel/ldt.c	Tue Aug  3 12:10:35 1999
+++ linux/arch/i386/kernel/ldt.c	Sat May 20 10:39:58 2000
@@ -93,6 +93,7 @@
 		mm->segments = vmalloc(LDT_ENTRIES*LDT_ENTRY_SIZE);
 		if (!mm->segments)
 			goto out_unlock;
+		memset(mm->segments, 0, LDT_ENTRIES*LDT_ENTRY_SIZE);
 		
 		if (atomic_read(&mm->mm_users) > 1)
 			printk(KERN_WARNING "LDT allocated for cloned task!\n");
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c
--- v2.3.99-pre8/linux/arch/i386/kernel/mpparse.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/i386/kernel/mpparse.c	Sat May 13 07:37:34 2000
@@ -50,11 +50,6 @@
 unsigned long phys_cpu_present_map = 0;
 
 /*
- * IA s/w dev Vol 3, Section 7.4
- */
-#define APIC_DEFAULT_PHYS_BASE 0xfee00000
-
-/*
  * Intel MP BIOS table parsing routines:
  */
 
@@ -65,10 +60,12 @@
 
 static int __init mpf_checksum(unsigned char *mp, int len)
 {
-	int sum=0;
-	while(len--)
-		sum+=*mp++;
-	return sum&0xFF;
+	int sum = 0;
+
+	while (len--)
+		sum += *mp++;
+
+	return sum & 0xFF;
 }
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/pci-i386.c linux/arch/i386/kernel/pci-i386.c
--- v2.3.99-pre8/linux/arch/i386/kernel/pci-i386.c	Thu May 11 15:30:06 2000
+++ linux/arch/i386/kernel/pci-i386.c	Mon May 15 13:40:09 2000
@@ -121,6 +121,19 @@
 	}
 }
 
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might have be mirrored at 0x0100-0x03ff..
+ */
 void
 pcibios_align_resource(void *data, struct resource *res, unsigned long size)
 {
@@ -129,17 +142,16 @@
 	if (res->flags & IORESOURCE_IO) {
 		unsigned long start = res->start;
 
-		/* We need to avoid collisions with `mirrored' VGA ports
-		   and other strange ISA hardware, so we always want the
-		   addresses kilobyte aligned.  */
 		if (size > 0x100) {
 			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
 			       " (%ld bytes)\n", dev->slot_name,
 			       dev->resource - res, size);
 		}
 
-		start = (start + 1024 - 1) & ~(1024 - 1);
-		res->start = start;
+		if (start & 0x300) {
+			start = (start + 0x3ff) & ~0x3ff;
+			res->start = start;
+		}
 	}
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c
--- v2.3.99-pre8/linux/arch/i386/kernel/pci-irq.c	Thu May 11 15:30:06 2000
+++ linux/arch/i386/kernel/pci-irq.c	Sat May 13 07:34:49 2000
@@ -222,6 +222,7 @@
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371FB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82440MX_1, pirq_piix_get, pirq_piix_set },
 	{ "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_0, pirq_via_get, pirq_via_set },
 	{ "VIA", PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596, pirq_via_get, pirq_via_set },
@@ -345,7 +346,7 @@
 
 	if (!irq) {
 		DBG(" ... failed\n");
-		if (newirq && mask == (1 << newirq)) {
+		if (assign && newirq && mask == (1 << newirq)) {
 			msg = "Guessed";
 			irq = newirq;
 		} else
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.3.99-pre8/linux/arch/i386/kernel/pci-pc.c	Thu May 11 15:30:06 2000
+++ linux/arch/i386/kernel/pci-pc.c	Sat May 20 11:32:08 2000
@@ -844,15 +844,15 @@
 	pcibios_last_bus = -1;
 }
 
-static void __init pci_fixup_rcc(struct pci_dev *d)
+static void __init pci_fixup_serverworks(struct pci_dev *d)
 {
 	/*
-	 * RCC host bridges -- Find and scan all secondary buses.
+	 * ServerWorks host bridges -- Find and scan all secondary buses.
 	 * Register 0x44 contains first, 0x45 last bus number routed there.
 	 */
 	u8 busno;
 	pci_read_config_byte(d, 0x44, &busno);
-	printk("PCI: RCC host bridge: secondary bus %02x\n", busno);
+	printk("PCI: ServerWorks host bridge: secondary bus %02x\n", busno);
 	pci_scan_bus(busno, pci_root_ops, NULL);
 	pcibios_last_bus = -1;
 }
@@ -928,8 +928,9 @@
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454GX,	pci_fixup_i450gx },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_RCC,	PCI_DEVICE_ID_RCC_HE,		pci_fixup_rcc },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_RCC,	PCI_DEVICE_ID_RCC_LE,		pci_fixup_rcc },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS,	PCI_DEVICE_ID_SERVERWORKS_HE,		pci_fixup_serverworks },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS,	PCI_DEVICE_ID_SERVERWORKS_LE,		pci_fixup_serverworks },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SERVERWORKS,	PCI_DEVICE_ID_SERVERWORKS_CMIC_HE,	pci_fixup_serverworks },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_COMPAQ,	PCI_DEVICE_ID_COMPAQ_6010,	pci_fixup_compaq },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_UMC,	PCI_DEVICE_ID_UMC_UM8886BF,	pci_fixup_umc_ide },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5513,		pci_fixup_ide_trash },
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.3.99-pre8/linux/arch/i386/kernel/setup.c	Thu May 11 15:30:06 2000
+++ linux/arch/i386/kernel/setup.c	Sat May 20 09:22:58 2000
@@ -406,6 +406,32 @@
 	e820.nr_map++;
 } /* add_memory_region */
 
+#define E820_DEBUG	1
+
+static void __init print_e820_map(void)
+{
+	int i;
+
+	for (i = 0; i < e820.nr_map; i++) {
+		printk(" e820: %016Lx @ %016Lx ",
+			e820.map[i].size, e820.map[i].addr);
+		switch (e820.map[i].type) {
+		case E820_RAM:	printk("(usable)\n");
+				break;
+		case E820_RESERVED:
+				printk("(reserved)\n");
+				break;
+		case E820_ACPI:
+				printk("(ACPI data)\n");
+				break;
+		case E820_NVS:
+				printk("(ACPI NVS)\n");
+				break;
+		default:	printk("type %lu\n", e820.map[i].type);
+				break;
+		}
+	}
+}
 
 /*
  * Do NOT EVER look at the BIOS memory size location.
@@ -415,11 +441,6 @@
 
 void __init setup_memory_region(void)
 {
-#define E820_DEBUG	1
-#ifdef E820_DEBUG
-	int i;
-#endif
-
 	/*
 	 * If we're lucky and live on a modern system, the setup code
 	 * will have given us a memory map that we can use to properly
@@ -439,27 +460,6 @@
 		if (e820.nr_map > E820MAX)
 			e820.nr_map = E820MAX;
 		memcpy(e820.map, E820_MAP, e820.nr_map * sizeof e820.map[0]);
-#ifdef E820_DEBUG
-		for (i=0; i < e820.nr_map; i++) {
-			printk("e820: %08x @ %08x ", (int)e820.map[i].size,
-						(int)e820.map[i].addr);
-			switch (e820.map[i].type) {
-			case E820_RAM:	printk("(usable)\n");
-					break;
-			case E820_RESERVED:
-					printk("(reserved)\n");
-					break;
-			case E820_ACPI:
-					printk("(ACPI data)\n");
-					break;
-			case E820_NVS:
-					printk("(ACPI NVS)\n");
-					break;
-			default:	printk("type %lu\n", e820.map[i].type);
-					break;
-			}
-		}
-#endif
 	}
 	else {
 		/* otherwise fake a memory map; one section from 0k->640k,
@@ -472,6 +472,8 @@
 		add_memory_region(0, LOWMEMSIZE(), E820_RAM);
 		add_memory_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
   	}
+	printk("BIOS-provided physical RAM map:\n");
+	print_e820_map();
 } /* setup_memory_region */
 
 
@@ -538,6 +540,10 @@
 	}
 	*to = '\0';
 	*cmdline_p = command_line;
+	if (usermem) {
+		printk("user-defined physical RAM map:\n");
+		print_e820_map();
+	}
 }
 
 void __init setup_arch(char **cmdline_p)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.3.99-pre8/linux/arch/i386/kernel/traps.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/i386/kernel/traps.c	Sat May 13 07:37:34 2000
@@ -790,7 +790,7 @@
 	 * On normal SMP PC this is used only with SMP, but we have to
 	 * use it and set it up here to start the Cobalt clock
 	 */
-	set_fixmap(FIX_APIC_BASE, APIC_PHYS_BASE);
+	set_fixmap(FIX_APIC_BASE, APIC_DEFAULT_PHYS_BASE);
 	printk("Local APIC ID %lx\n", apic_read(APIC_ID));
 	printk("Local APIC Version %lx\n", apic_read(APIC_LVR));
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- v2.3.99-pre8/linux/arch/i386/mm/init.c	Tue Mar  7 14:32:25 2000
+++ linux/arch/i386/mm/init.c	Sat May 13 07:40:53 2000
@@ -242,8 +242,18 @@
 	pte_t *pte;
 
 	pgd = swapper_pg_dir + __pgd_offset(vaddr);
+	if (pgd_none(*pgd)) {
+		printk("PAE BUG #00!\n");
+		return;
+	}
 	pmd = pmd_offset(pgd, vaddr);
+	if (pmd_none(*pmd)) {
+		printk("PAE BUG #01!\n");
+		return;
+	}
 	pte = pte_offset(pmd, vaddr);
+	if (pte_val(*pte))
+		pte_ERROR(*pte);
 	pgprot_val(prot) = pgprot_val(PAGE_KERNEL) | pgprot_val(flags);
 	set_pte(pte, mk_pte_phys(phys, prot));
 
@@ -271,53 +281,65 @@
 	pmd_t *pmd;
 	pte_t *pte;
 	int i, j;
+	unsigned long vaddr;
 
-	i = __pgd_offset(start);
-	j = __pmd_offset(start);
+	vaddr = start;
+	i = __pgd_offset(vaddr);
+	j = __pmd_offset(vaddr);
 	pgd = pgd_base + i;
 
-	for ( ; (i < PTRS_PER_PGD) && (start != end); pgd++, i++) {
+	for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
 #if CONFIG_X86_PAE
 		if (pgd_none(*pgd)) {
 			pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 			set_pgd(pgd, __pgd(__pa(pmd) + 0x1));
-			if (pmd != pmd_offset(pgd, start))
-				BUG();
+			if (pmd != pmd_offset(pgd, 0))
+				printk("PAE BUG #02!\n");
 		}
-		pmd = pmd_offset(pgd, start);
+		pmd = pmd_offset(pgd, vaddr);
 #else
 		pmd = (pmd_t *)pgd;
 #endif
-		for (; (j < PTRS_PER_PMD) && start; pmd++, j++) {
+		for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
 			if (pmd_none(*pmd)) {
 				pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
 				set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
 				if (pte != pte_offset(pmd, 0))
 					BUG();
 			}
-			start += PMD_SIZE;
+			vaddr += PMD_SIZE;
 		}
 		j = 0;
 	}
 }
 
-static void __init pagetable_init(void)
+static void __init pagetable_init (void)
 {
+	unsigned long vaddr, end;
 	pgd_t *pgd, *pgd_base;
+	int i, j, k;
 	pmd_t *pmd;
 	pte_t *pte;
-	int i, j, k;
-	unsigned long vaddr, end;
 
-	end = (unsigned long)__va(max_low_pfn*PAGE_SIZE) - 1;
+	/*
+	 * This can be zero as well - no problem, in that case we exit
+	 * the loops anyway due to the PTRS_PER_* conditions.
+	 */
+	end = (unsigned long)__va(max_low_pfn*PAGE_SIZE);
 
-	i = __pgd_offset(PAGE_OFFSET);
 	pgd_base = swapper_pg_dir;
+#if CONFIG_X86_PAE
+	for (i = 0; i < PTRS_PER_PGD; i++) {
+		pgd = pgd_base + i;
+		__pgd_clear(pgd);
+	}
+#endif
+	i = __pgd_offset(PAGE_OFFSET);
 	pgd = pgd_base + i;
 
 	for (; i < PTRS_PER_PGD; pgd++, i++) {
 		vaddr = i*PGDIR_SIZE;
-		if (vaddr >= end)
+		if (end && (vaddr >= end))
 			break;
 #if CONFIG_X86_PAE
 		pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
@@ -329,7 +351,7 @@
 			BUG();
 		for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
 			vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
-			if (vaddr >= end)
+			if (end && (vaddr >= end))
 				break;
 			if (cpu_has_pse) {
 				unsigned long __pe;
@@ -354,7 +376,7 @@
 
 			for (k = 0; k < PTRS_PER_PTE; pte++, k++) {
 				vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
-				if (vaddr >= end)
+				if (end && (vaddr >= end))
 					break;
 				*pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL);
 			}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c
--- v2.3.99-pre8/linux/arch/ia64/ia32/sys_ia32.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/ia64/ia32/sys_ia32.c	Sat May 20 10:47:29 2000
@@ -2735,8 +2735,6 @@
 
 extern asmlinkage long sys_mount(char * dev_name, char * dir_name, char * type,
 				unsigned long new_flags, void *data);
-extern long do_sys_mount(char * dev_name, char * dir_name, char * type,
-				unsigned long new_flags, void *data);
 
 #define SMBFS_NAME	"smbfs"
 #define NCPFS_NAME	"ncpfs"
@@ -2784,7 +2782,7 @@
 			do_smb_super_data_conv((void *)data_page);
 		else
 			panic("The problem is here...");
-		err = do_sys_mount((char *)dev_page, (char *)dir_page,
+		err = do_mount((char *)dev_page, (char *)dir_page,
 				(char *)type_page, new_flags,
 				(void *)data_page);
 		if(data_page)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/Makefile linux/arch/mips/Makefile
--- v2.3.99-pre8/linux/arch/mips/Makefile	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/Makefile	Sat May 13 08:29:14 2000
@@ -125,6 +125,7 @@
 ifdef CONFIG_BAGET_MIPS
 SUBDIRS       += arch/mips/baget arch/mips/baget/prom
 LIBS          += arch/mips/baget/baget.a arch/mips/baget/prom/bagetlib.a
+LOADADDR      += 0x80001000
 endif
 
 #
@@ -189,6 +190,7 @@
 	@$(MAKEBOOT) clean
 	$(MAKE) -C arch/$(ARCH)/kernel clean
 	$(MAKE) -C arch/$(ARCH)/tools clean
+	$(MAKE) -C arch/mips/baget clean
 
 archmrproper:
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/Makefile linux/arch/mips/arc/Makefile
--- v2.3.99-pre8/linux/arch/mips/arc/Makefile	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 2000/01/13 00:11:11 ralf Exp $
+# $Id: Makefile,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
 #
 # Makefile for the SGI arcs prom monitor library routines
 # under Linux.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c
--- v2.3.99-pre8/linux/arch/mips/arc/cmdline.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/cmdline.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: cmdline.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
+ * $Id: cmdline.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/env.c linux/arch/mips/arc/env.c
--- v2.3.99-pre8/linux/arch/mips/arc/env.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/env.c	Sat May 13 08:29:14 2000
@@ -11,12 +11,14 @@
 
 #include <asm/sgialib.h>
 
-char * __init prom_getenv(char *name)
+PCHAR __init
+ArcGetEnvironmentVariable(CHAR *name)
 {
 	return romvec->get_evar(name);
 }
 
-long __init prom_setenv(char *name, char *value)
+LONG __init
+ArcSetEnvironmentVariable(PCHAR name, PCHAR value)
 {
 	return romvec->set_evar(name, value);
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/file.c linux/arch/mips/arc/file.c
--- v2.3.99-pre8/linux/arch/mips/arc/file.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/file.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: file.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
+ * $Id: file.c,v 1.1 1998/10/18 13:32:08 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <asm/sgialib.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c
--- v2.3.99-pre8/linux/arch/mips/arc/identify.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/identify.c	Sat May 13 08:29:14 2000
@@ -7,7 +7,7 @@
  * 
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: identify.c,v 1.3 1999/10/21 00:23:04 ralf Exp $
+ * $Id: identify.c,v 1.2 1999/02/25 21:04:13 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/init.c linux/arch/mips/arc/init.c
--- v2.3.99-pre8/linux/arch/mips/arc/init.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips/arc/init.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.4 1999/10/09 00:00:57 ralf Exp $
+/* $Id: init.c,v 1.5 2000/03/07 15:45:27 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.
@@ -23,7 +23,7 @@
 
 extern void prom_testtree(void);
 
-int __init prom_init(int argc, char **argv, char **envp)
+int __init prom_init(int argc, char **argv, char **envp, int *prom_vec)
 {
 	struct linux_promblock *pb;
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c
--- v2.3.99-pre8/linux/arch/mips/arc/memory.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips/arc/memory.c	Sat May 13 08:29:14 2000
@@ -21,8 +21,6 @@
 
 #undef DEBUG
 
-extern char _end;
-
 struct linux_mdesc * __init
 ArcGetMemoryDescriptor(struct linux_mdesc *Current)
 {
@@ -146,7 +144,7 @@
 void __init prom_meminit(void)
 {
 	struct prom_pmemblock *largest;
-	unsigned long bootmap_size;
+	unsigned long bootmap_size, kbegin, kend;
 	struct linux_mdesc *p;
 	int totram;
 	int i = 0;
@@ -195,6 +193,7 @@
 	pblocks[i].size = 0;
 
 	max_low_pfn = find_max_low_pfn();
+
 	largest = find_largest_memblock();
 	bootmap_size = init_bootmem(largest->base >> PAGE_SHIFT, max_low_pfn);
 
@@ -208,6 +207,8 @@
 		prom_printf("CRITIAL: overwriting PROM data.\n");
 		BUG();
 	}
+
+	/* Reserve the memory bootmap itself */
 	reserve_bootmem(largest->base, bootmap_size);
 
 	printk("PROMLIB: Total free ram %dK / %dMB.\n",
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c
--- v2.3.99-pre8/linux/arch/mips/arc/misc.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/misc.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
+/* $Id: misc.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
  *
  * misc.c: Miscellaneous ARCS PROM routines.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/salone.c linux/arch/mips/arc/salone.c
--- v2.3.99-pre8/linux/arch/mips/arc/salone.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/salone.c	Sat May 13 08:29:14 2000
@@ -4,7 +4,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: salone.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
+ * $Id: salone.c,v 1.1 1998/10/18 13:32:09 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <asm/sgialib.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/time.c linux/arch/mips/arc/time.c
--- v2.3.99-pre8/linux/arch/mips/arc/time.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/time.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: time.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
+ * $Id: time.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <asm/sgialib.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/arc/tree.c linux/arch/mips/arc/tree.c
--- v2.3.99-pre8/linux/arch/mips/arc/tree.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/arc/tree.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: tree.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
+ * $Id: tree.c,v 1.1 1998/10/18 13:32:10 tsbogend Exp $
  */
 #include <linux/init.h>
 #include <asm/sgialib.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/Makefile linux/arch/mips/baget/Makefile
--- v2.3.99-pre8/linux/arch/mips/baget/Makefile	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/Makefile	Sat May 13 08:29:14 2000
@@ -11,11 +11,8 @@
 
 all: baget.a 
 
-image:	../../../vmlinux
-	cp -f $< $@
-
 O_TARGET := baget.a
-O_OBJS   := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o
+O_OBJS   := baget.o print.o setup.o time.o irq.o bagetIRQ.o reset.o wbflush.o
 
 ifeq ($(CONFIG_SERIAL),y)
 	OX_OBJS += vacserial.o
@@ -38,8 +35,8 @@
 
 ##################### Baget Loader stuff ########################
 
-dummy.c:
-	touch $@
+image: ../../../vmlinux
+	cp -f $< $@
 
 image.bin: image
 	$(OBJCOPY) -O binary $< $@
@@ -47,6 +44,9 @@
 ramdisk.bin:
 	echo "Dummy ramdisk used. Provide your own if needed !" > $@
 
+dummy.c:
+	touch $@
+
 dummy.o: dummy.c image.bin ramdisk.bin
 	$(CC) $(CFLAGS) -c -o $@ $<
 	$(OBJCOPY) --add-section=.vmlinux=image.bin \
@@ -54,10 +54,11 @@
 
 balo.h: image
 	$(NM) $< | awk ' \
-            BEGIN               { printf "/* DO NOT EDIT THIS FILE */\n" }    \
-	    /kernel_entry/      { printf "#define START 0x%s\n", $$1 }        \
-            /balo_ramdisk_base/ { printf "#define RAMDISK_BASE 0x%s\n", $$1 } \
-	    /balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \
+	BEGIN               { printf "/* DO NOT EDIT THIS FILE */\n" }    \
+	/_ftext/            { printf "#define LOADADDR 0x%s\n", $$1     } \
+	/kernel_entry/      { printf "#define START 0x%s\n", $$1 }        \
+	/balo_ramdisk_base/ { printf "#define RAMDISK_BASE 0x%s\n", $$1 } \
+	/balo_ramdisk_size/ { printf "#define RAMDISK_SIZE 0x%s\n", $$1 } \
                        ' > $@
 balo.o:   balo.c balo.h
 	$(CC) $(CFLAGS) -c $< 
@@ -69,7 +70,6 @@
 	$(LD) $(LDFLAGS) -T ld.script.balo -o $@ $^ 
 
 clean:
-	rm -f balo.o balo.h dummy.o dummy.c hello.o image.bin image balo_supp.o
-	rm -f $(O_OBJS) $(O_TARGET)
+	rm -f balo balo.h dummy.c image image.bin
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/baget.c linux/arch/mips/baget/baget.c
--- v2.3.99-pre8/linux/arch/mips/baget/baget.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/baget.c	Sat May 13 08:29:14 2000
@@ -13,15 +13,9 @@
 #include <asm/bootinfo.h>
 #include <asm/mipsregs.h>
 #include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 
 #include <asm/baget/baget.h>
-
-/* 
- * Following values are set by BALO into RAM disk buffer parameters
- */
-unsigned long balo_ramdisk_base = 0xBA;  /* Signature for BALO ! */
-unsigned long balo_ramdisk_size = 0;
-
 
 /*
  *  Following code is based on routines from 'mm/vmalloc.c'
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/bagetIRQ.S linux/arch/mips/baget/bagetIRQ.S
--- v2.3.99-pre8/linux/arch/mips/baget/bagetIRQ.S	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/bagetIRQ.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: bagetIRQ.S,v 1.2 1999/08/18 23:37:42 ralf Exp $
+/* $Id: bagetIRQ.S,v 1.1 1999/01/17 03:49:37 ralf Exp $
  * bagetIRQ.S: Interrupt exception dispatch code for Baget/MIPS
  *
  * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/balo.c linux/arch/mips/baget/balo.c
--- v2.3.99-pre8/linux/arch/mips/baget/balo.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/balo.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: balo.c,v 1.1 1999/01/17 03:49:37 ralf Exp $
+/* $Id$
  *
  * balo.c: BAget LOader
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c
--- v2.3.99-pre8/linux/arch/mips/baget/irq.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/irq.c	Sat May 13 08:29:14 2000
@@ -29,8 +29,7 @@
 
 #include <asm/baget/baget.h>
 
-unsigned int local_bh_count[NR_CPUS];
-unsigned int local_irq_count[NR_CPUS];
+irq_cpustat_t irq_stat [NR_CPUS];
 unsigned long spurious_count = 0;
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/print.c linux/arch/mips/baget/print.c
--- v2.3.99-pre8/linux/arch/mips/baget/print.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/print.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: print.c,v 1.2 1999/10/09 00:00:57 ralf Exp $
+/* $Id: print.c,v 1.1 1999/01/17 03:49:38 ralf Exp $
  *
  * print.c: Simple print fascility
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/prom/Makefile linux/arch/mips/baget/prom/Makefile
--- v2.3.99-pre8/linux/arch/mips/baget/prom/Makefile	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/prom/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 1999/01/17 03:49:40 ralf Exp $
+# $Id$
 # Makefile for the Baget/MIPS prom emulator library routines.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/time.c linux/arch/mips/baget/time.c
--- v2.3.99-pre8/linux/arch/mips/baget/time.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/baget/time.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.4 1999/10/09 00:00:57 ralf Exp $
+/* $Id: time.c,v 1.3 1999/08/17 22:18:37 ralf Exp $
  * time.c: Baget/MIPS specific time handling details
  *
  * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/baget/vacserial.c linux/arch/mips/baget/vacserial.c
--- v2.3.99-pre8/linux/arch/mips/baget/vacserial.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/mips/baget/vacserial.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: vacserial.c,v 1.4 1999/10/09 00:00:57 ralf Exp $
+/* $Id: vacserial.c,v 1.3 1999/08/17 22:18:37 ralf Exp $
  * vacserial.c: VAC UART serial driver
  *              This code stealed and adopted from linux/drivers/char/serial.c
  *              See that for author info
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/boot/Makefile linux/arch/mips/boot/Makefile
--- v2.3.99-pre8/linux/arch/mips/boot/Makefile	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/boot/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.10 1999/10/17 19:55:22 harald Exp $
+# $Id: Makefile,v 1.9 1999/04/07 18:45:23 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.3.99-pre8/linux/arch/mips/config.in	Tue Apr 11 15:09:13 2000
+++ linux/arch/mips/config.in	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.42 2000/02/24 00:12:40 ralf Exp $
+# $Id: config.in,v 1.46 2000/03/26 22:59:01 ralf Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -26,168 +26,169 @@
 #
 # Select some configuration options automatically for certain systems.
 #
+unset CONFIG_ARC32
+unset CONFIG_PCI
+unset CONFIG_ISA
 unset CONFIG_MIPS_JAZZ
 unset CONFIG_VIDEO_G364
 
 define_bool CONFIG_SBUS n
 
-if [ "$CONFIG_ALGOR_P4032" = "y" -o "$CONFIG_SNI_RM200_PCI" = "y" -o \
-     "$CONFIG_DDB5074" = "y" ]; then
+if [ "$CONFIG_ALGOR_P4032" = "y" ]; then
    define_bool CONFIG_PCI y
-else
-   define_bool CONFIG_PCI n
 fi
-if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o "$CONFIG_OLIVETTI_M700" = "y" -o \
-     "$CONFIG_SNI_RM200_PCI" = "y" -o "$CONFIG_ACER_PICA_61" = "y" ]; then
-   define_bool CONFIG_ISA y
-else
-   define_bool CONFIG_ISA n
-fi
-
 if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
+   define_bool CONFIG_ARC32 y
    define_bool CONFIG_HAVE_IO_PORTS y
-   define_bool CONFIG_MIPS_JAZZ y
    define_bool CONFIG_FB y
    define_bool CONFIG_FB_G364 y	
+   define_bool CONFIG_MIPS_JAZZ y
 fi
 if [ "$CONFIG_ACER_PICA_61" = "y" ]; then
+   define_bool CONFIG_ARC32 y
    define_bool CONFIG_HAVE_IO_PORTS y
    define_bool CONFIG_MIPS_JAZZ y
 fi
+if [ "$CONFIG_SGI_IP22" = "y" ]; then
+   define_bool CONFIG_ARC32 y
+fi
 if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then
+   define_bool CONFIG_ARC32 y
    define_bool CONFIG_HAVE_IO_PORTS y
 fi
 if [ "$CONFIG_DDB5074" = "y" ]; then
    define_bool CONFIG_HAVE_IO_PORTS y
+   define_bool CONFIG_ISA y
+   define_bool CONFIG_PCI y
+fi
+
+if [ "$CONFIG_ISA" != "y" ]; then
+   define_bool CONFIG_ISA n
+fi
+
+if [ "$CONFIG_PCI" != "y" ]; then
+   define_bool CONFIG_PCI n
 fi
 endmenu
 
 mainmenu_option next_comment
-comment 'CPU selection'
-
-if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then
-    choice 'CPU core' \
-	"R3000 CONFIG_CPU_R3000	\
-	 R4300 CONFIG_CPU_R4300	\
-	 R4x00 CONFIG_CPU_R4X00	\
-	 R5000 CONFIG_CPU_R5000	\
-	 R56x0 CONFIG_CPU_NEVADA \
-	 R10000 CONFIG_CPU_R10000" R4x00
+	comment 'CPU selection'
 
-    bool '  ll/sc Instructions available' CONFIG_CPU_HAS_LLSC
-    bool '  Writeback Buffer available' CONFIG_CPU_HAS_WB
-else
-    choice 'CPU type' \
-	"R3000 CONFIG_CPU_R3000	\
-	 R6000 CONFIG_CPU_R6000	\
-	 R4300 CONFIG_CPU_R4300	\
-	 R4x00 CONFIG_CPU_R4X00	\
-	 R5000 CONFIG_CPU_R5000	\
-	 R56x0 CONFIG_CPU_NEVADA \
-	 R8000 CONFIG_CPU_R8000	\
-	 R10000 CONFIG_CPU_R10000 \
-         Advanced CONFIG_CPU_ADVANCED" R4x00
-
-    if [ "$CONFIG_CPU_R3000" = "y" ]; then
-        if [ "$CONFIG_DECSTATION" = "y" ]; then
-            define_bool CONFIG_CPU_HAS_LLSC n
-            define_bool CONFIG_CPU_HAS_WB y
-        else
-            define_bool CONFIG_CPU_HAS_LLSC n
-            define_bool CONFIG_CPU_HAS_WB n
-        fi
-    else
-        define_bool CONFIG_CPU_HAS_LLSC y
-        define_bool CONFIG_CPU_HAS_WB n
-    fi
-fi
+	choice 'CPU type' \
+		"R3000 CONFIG_CPU_R3000	\
+		 R6000 CONFIG_CPU_R6000	\
+		 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
+
+	bool 'Advanced CPU Config' CONFIG_CPU_ADVANCED
+
+	if [ "$CONFIG_CPU_ADVANCED" = "y" ]; then
+		bool '  ll/sc Instructions available' CONFIG_CPU_HAS_LLSC
+		bool '  Writeback Buffer available' CONFIG_CPU_HAS_WB
+	else
+		if [ "$CONFIG_CPU_R3000" = "y" ]; then
+			if [ "$CONFIG_DECSTATION" = "y" ]; then
+				define_bool CONFIG_CPU_HAS_LLSC n
+				define_bool CONFIG_CPU_HAS_WB y
+			else
+				define_bool CONFIG_CPU_HAS_LLSC n
+				define_bool CONFIG_CPU_HAS_WB n
+			fi
+		else
+			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
-   define_bool CONFIG_CPU_LITTLE_ENDIAN y
-else
-   bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
-fi
-
-if [ "$CONFIG_PROC_FS" = "y" ]; then
-   define_bool CONFIG_KCORE_ELF y
-fi
-define_bool CONFIG_ELF_KERNEL y
+	if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then
+	   define_bool CONFIG_CPU_LITTLE_ENDIAN y
+	else
+	   bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
+	fi
+
+	if [ "$CONFIG_PROC_FS" = "y" ]; then
+	   define_bool CONFIG_KCORE_ELF y
+	fi
+	define_bool CONFIG_ELF_KERNEL y
+
+	if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then
+	   bool 'Include IRIX binary compatibility' CONFIG_BINFMT_IRIX 
+	   bool 'Include forward keyboard' CONFIG_FORWARD_KEYBOARD 
+	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
+	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
+
+	bool 'Enable loadable module support' CONFIG_MODULES
+	if [ "$CONFIG_MODULES" = "y" ]; then
+	   bool '  Set version information on all symbols for modules' CONFIG_MODVERSIONS
+	   bool '  Kernel module loader' CONFIG_KMOD
+	fi
+
+	if [ "$CONFIG_DECSTATION" = "y" ]; then
+            bool 'TURBOchannel support' CONFIG_TC
+	fi
+endmenu
 
-if [ "$CONFIG_CPU_LITTLE_ENDIAN" = "n" ]; then
-   define_bool CONFIG_BINFMT_IRIX y
-   define_bool CONFIG_FORWARD_KEYBOARD y
+if [ "$CONFIG_ISA" = "y" ]; then
+   source drivers/pnp/Config.in
 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
 
-source drivers/pci/Config.in
-
-bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
-if [ "$CONFIG_HOTPLUG" = "y" ]; then
+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
-
-if [ "$CONFIG_SGI_IP22" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then
-   source drivers/parport/Config.in
-fi
-endmenu
-
-mainmenu_option next_comment
-comment 'Loadable module support'
-bool 'Enable loadable module support' CONFIG_MODULES
-if [ "$CONFIG_MODULES" = "y" ]; then
-   bool '  Set version information on all symbols for modules' CONFIG_MODVERSIONS
-   bool '  Kernel module loader' CONFIG_KMOD
-fi
-
-source drivers/pci/Config.in
-
-endmenu
-
-if [ "$CONFIG_DECSTATION" = "y" ]; then
-   mainmenu_option next_comment
-   comment 'TURBOchannel support'
-   bool 'TURBOchannel support' CONFIG_TC
-#   if [ "$CONFIG_TC" = "y" ]; then
-#      tristate '  MAGMA Parallel port support' CONFIG_PARPORT
-#   fi
-   endmenu
-fi
-
-source drivers/pnp/Config.in
-
 source drivers/block/Config.in
 
 if [ "$CONFIG_NET" = "y" ]; then
    source net/Config.in
 fi
 
-mainmenu_option next_comment
-comment 'ATA/IDE/MFM/RLL support'
-
-tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+if [ "$CONFIG_DECSTATION" != "n" -a \
+     "$CONFIG_SGI_IP22" != "n" ]; then
+    source drivers/telephony/Config.in
+fi
 
-if [ "$CONFIG_IDE" != "n" ]; then
-  source drivers/ide/Config.in
-else
-  define_bool CONFIG_BLK_DEV_IDE_MODES n
-  define_bool CONFIG_BLK_DEV_HD n
+if [ "$CONFIG_SGI_IP22" != "n" -a \
+     "$CONFIG_DECSTATION" != "n" ]; then
+
+    mainmenu_option next_comment
+    comment 'ATA/IDE/MFM/RLL support'
+    
+    tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+    
+    if [ "$CONFIG_IDE" != "n" ]; then
+      source drivers/ide/Config.in
+    else
+      define_bool CONFIG_BLK_DEV_IDE_MODES n
+      define_bool CONFIG_BLK_DEV_HD n
+    fi
+    endmenu
 fi
-endmenu
 
 mainmenu_option next_comment
 comment 'SCSI support'
@@ -195,77 +196,57 @@
 tristate 'SCSI support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
-   if [ "$CONFIG_SGI" = "y" -o "$CONFIG_DECSTATION" = "y" ]; then
-      comment '  SCSI support type (disk, tape, CDrom)'
-
-      dep_tristate '  SCSI disk support' CONFIG_BLK_DEV_SD $CONFIG_SCSI
-      dep_tristate '  SCSI tape support' CONFIG_CHR_DEV_ST $CONFIG_SCSI
-      dep_tristate '  SCSI CDROM support' CONFIG_BLK_DEV_SR $CONFIG_SCSI
-      dep_tristate '  SCSI generic support' CONFIG_CHR_DEV_SG $CONFIG_SCSI
-
-      comment 'Some SCSI devices (e.g. CD jukebox) support multiple LUNs'
-
-      bool '  Probe all LUNs on each SCSI device' CONFIG_SCSI_MULTI_LUN
-
-      bool '  Verbose SCSI error reporting' CONFIG_SCSI_CONSTANTS
-
-      #mainmenu_option next_comment
-      comment 'SCSI low-level drivers'
-      if [ "$CONFIG_SGI" = "y" ]; then
-	 dep_tristate 'SGI wd93 Scsi Driver' CONFIG_SCSI_SGIWD93 $CONFIG_SCSI
-      else
-	 if [ "$CONFIG_TC" = "y" ]; then
-	    dep_tristate 'DEC NCR53C94 Scsi Driver' CONFIG_SCSI_DECNCR $CONFIG_SCSI
-	 fi
-	 dep_tristate 'DEC SII Scsi Driver' CONFIG_SCSI_DECSII $CONFIG_SCSI
-      fi
-   else
-      source drivers/scsi/Config.in
-   fi
+   source drivers/scsi/Config.in
 fi
 endmenu
 
+if [ "$CONFIG_DECSTATION" != "n" -a \
+     "$CONFIG_SGI_IP22" != "n" ]; then
+    source drivers/i2o/Config.in
+fi
+
 if [ "$CONFIG_NET" = "y" ]; then
    mainmenu_option next_comment
    comment 'Network device support'
 
    bool 'Network device support' CONFIG_NETDEVICES
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-      if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "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
+	 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
+	    bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
+	    bool ' Keepalive and linefill' CONFIG_SLIP_SMART
 	 fi
-	 tristate '  PPP (point-to-point) support' CONFIG_PPP
+	 tristate 'PPP (point-to-point) support' CONFIG_PPP
 	 if [ ! "$CONFIG_PPP" = "n" ]; then
-	    comment '    CCP compressors for PPP are only built as modules.'
+	    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
-         if [ "$CONFIG_SGI" = "y" ]; then
-            bool '  SGI Seeq ethernet controller support' CONFIG_SGISEEQ
-         fi
-      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
-	 tristate '  Baget Backplane Shared Memory support' CONFIG_BAGETBSM
       fi
    fi
    endmenu
 fi
 
-if [ "$CONFIG_SGI" != "y" -a "$CONFIG_DECSTATION" != "y" -a "$CONFIG_BAGET_MIPS" != "y" ]; then
-   mainmenu_option next_comment
-   # comment 'AX.25 network device drivers'
-
-   source drivers/net/hamradio/Config.in
-   endmenu
-
+if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then
    mainmenu_option next_comment
    comment 'ISDN subsystem'
 
@@ -287,20 +268,20 @@
    endmenu
 fi
 
-if [ "$CONFIG_DECSTATION" != "y" ]; then
+if [ "$CONFIG_DECSTATION" != "n" -a \
+     "$CONFIG_SGI_IP22" != "n" ]; then
    source drivers/char/Config.in
-else
+fi
+
+if [ "$CONFIG_DECSTATION" = "y" ]; then
    mainmenu_option next_comment
-   comment 'DECstation Character devices'
+   comment 'DECStation Character devices'
 
    bool 'Virtual terminal' CONFIG_VT
    if [ "$CONFIG_VT" = "y" ]; then
       bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
    fi
    tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL
-   if [ "$CONFIG_SGI_IP22" = "y" ]; then
-      bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE
-   fi
    if [ "$CONFIG_SERIAL" = "y" ]; then
       bool 'DZ11 Serial Support' CONFIG_DZ
       if [ "$CONFIG_TC" = "y" ]; then
@@ -314,32 +295,42 @@
    fi
    bool 'Keyboard Support' CONFIG_KEYBOARD
    bool 'Mouse Support' CONFIG_MOUSE
-#    bool 'Enhanced Real Time Clock Support' CONFIG_RTC
+   bool 'Enhanced Real Time Clock Support' CONFIG_RTC
    endmenu
 fi
 
-
-#source drivers/misc/Config.in
-
-source fs/Config.in
-
-if [ "$CONFIG_VT" = "y" ]; then
+if [ "$CONFIG_SGI_IP22" = "y" ]; then
    mainmenu_option next_comment
-   comment 'Console drivers'
-   if [ "$CONFIG_SGI_IP22" = "y" ]; then
+   comment 'SGI Character devices'
+   bool 'Virtual terminal' CONFIG_VT
+   if [ "$CONFIG_VT" = "y" ]; then
+      bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE
       tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE
       if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then
 	 define_bool CONFIG_DUMMY_CONSOLE y
       else
          define_bool CONFIG_FONT_8x16 y
       fi
-   else
+      bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE
+   fi
+   bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
+   if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+      int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
+   fi
+   endmenu
+fi
+
+source fs/Config.in
+
+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
-	 source drivers/video/Config.in
-   fi
+      bool 'Support for frame buffer devices' CONFIG_FB
+      source drivers/video/Config.in
    endmenu
 fi
 
@@ -363,7 +354,6 @@
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
-#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
 bool 'Are you using a crosscompiler' CONFIG_CROSSCOMPILE
 if [ "$CONFIG_MODULES" = "y" ]; then
    bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/Makefile linux/arch/mips/ddb5074/Makefile
--- v2.3.99-pre8/linux/arch/mips/ddb5074/Makefile	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/ddb5074/Makefile	Sat May 13 08:29:14 2000
@@ -8,7 +8,7 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 #
-# $Id: Makefile,v 1.1 2000/01/26 00:07:44 ralf Exp $
+# $Id$
 #
 
 .S.s:
@@ -17,6 +17,6 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 O_TARGET = ddb5074.a
-O_OBJS  = setup.o irq.o time.o prom.o pci.o int-handler.o nile4.o
+O_OBJS  = setup.o irq.o time.o prom.o pci.o pci-dma.o int-handler.o nile4.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/int-handler.S linux/arch/mips/ddb5074/int-handler.S
--- v2.3.99-pre8/linux/arch/mips/ddb5074/int-handler.S	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/ddb5074/int-handler.S	Sat May 13 08:29:14 2000
@@ -6,9 +6,9 @@
  *  Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
- *  $Id: int-handler.S,v 1.2 2000/01/27 02:06:56 ralf Exp $
+ *  $Id: int-handler.S,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
 
 #include <asm/asm.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/irq.c linux/arch/mips/ddb5074/irq.c
--- v2.3.99-pre8/linux/arch/mips/ddb5074/irq.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips/ddb5074/irq.c	Sat May 13 08:29:14 2000
@@ -2,7 +2,7 @@
  *  arch/mips/ddb5074/irq.c -- NEC DDB Vrc-5074 interrupt routines
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
  *  $Id: irq.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
@@ -30,7 +30,7 @@
 extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
 
 
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+void no_action(int cpl, void *dev_id, struct pt_regs *regs)
 {
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/nile4.c linux/arch/mips/ddb5074/nile4.c
--- v2.3.99-pre8/linux/arch/mips/ddb5074/nile4.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/ddb5074/nile4.c	Sat May 13 08:29:14 2000
@@ -2,9 +2,9 @@
  *  arch/mips/ddb5074/nile4.c -- NEC Vrc-5074 Nile 4 support routines
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
- *  $Id: nile4.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
+ *  $Id$
  */
 
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/pci-dma.c linux/arch/mips/ddb5074/pci-dma.c
--- v2.3.99-pre8/linux/arch/mips/ddb5074/pci-dma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ddb5074/pci-dma.c	Sat May 13 08:29:14 2000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2000   Ani Joshi <ajoshi@unixbox.com>
+ *
+ *
+ * Dynamic DMA mapping support.
+ *
+ * swiped from i386, and cloned for MIPS by Geert.
+ *
+ */
+
+#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_handle = virt_to_bus(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)vaddr, get_order(size));
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/pci.c linux/arch/mips/ddb5074/pci.c
--- v2.3.99-pre8/linux/arch/mips/ddb5074/pci.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips/ddb5074/pci.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
  *                     Albert Dorofeev <albert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
  *  $Id: pci.c,v 1.4 2000/02/18 00:02:17 ralf Exp $
  */
@@ -168,163 +168,136 @@
     nile4_pci_write_config_dword
 };
 
+struct {
+    struct resource ram;
+    struct resource flash;
+    struct resource isa_io;
+    struct resource pci_io;
+    struct resource isa_mem;
+    struct resource pci_mem;
+    struct resource nile4;
+    struct resource boot;
+} ddb5074_resources = {
+    { "RAM", 0x00000000, 0x03ffffff,
+      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+    { "Flash ROM", 0x04000000, 0x043fffff },
+    { "Nile4 ISA I/O", 0x06000000, 0x060fffff },
+    { "Nile4 PCI I/O", 0x06100000, 0x07ffffff },
+    { "Nile4 ISA mem", 0x08000000, 0x08ffffff, IORESOURCE_MEM },
+    { "Nile4 PCI mem", 0x09000000, 0x0fffffff, IORESOURCE_MEM },
+    { "Nile4 ctrl", 0x1fa00000, 0x1fbfffff,
+      IORESOURCE_MEM | PCI_BASE_ADDRESS_MEM_TYPE_64 },
+    { "Boot ROM", 0x1fc00000, 0x1fffffff }
+};
 
-static void __init pcibios_claim_resources(struct list_head *bus_list)
+static void __init ddb5074_pci_fixup(void)
 {
-    struct list_head *ln, *dn;
-    struct pci_bus *bus;
     struct pci_dev *dev;
-    int idx;
 
-    for (ln = bus_list->next; ln != bus_list; ln = ln->next) {
-	bus = pci_bus_b(ln);
-	for (dn = bus->devices.next; dn != &bus->devices; dn = dn->next) {
-	    dev = pci_dev_b(dn);
-	    for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
-		struct resource *r = &dev->resource[idx];
-		struct resource *pr;
-		if (!r->start)
-		    continue;
-		pr = pci_find_parent_resource(dev, r);
-		if (!pr || request_resource(pr, r) < 0) {
-		    printk(KERN_ERR "PCI: Address space collision on region %d of device %s\n", idx, dev->name);
-		    /* We probably should disable the region, shouldn't we? */
-		}
-	    }
+    pci_for_each_dev(dev) {
+	if (dev->vendor == PCI_VENDOR_ID_NEC &&
+	    dev->device == PCI_DEVICE_ID_NEC_NILE4) {
+	    /*
+	     *  The first 64-bit PCI base register should point to the Nile4
+	     *  control registers. Unfortunately this isn't the case, so we fix
+	     *  it ourselves. This allows the serial driver to find the UART.
+	     */
+	    dev->resource[0] = ddb5074_resources.nile4;
+	    request_resource(&iomem_resource, &dev->resource[0]);
+	    /*
+	     *  The second 64-bit PCI base register points to the first memory
+	     *  bank. Unfortunately the address is wrong, so we fix it (again).
+	     */
+	    dev->resource[2] = ddb5074_resources.ram;
+	    request_resource(&iomem_resource, &dev->resource[2]);
+	} else if (dev->vendor == PCI_VENDOR_ID_AL &&
+		   dev->device == PCI_DEVICE_ID_AL_M7101) {
+	    /*
+	     *  It's nice to have the LEDs on the GPIO pins available for
+	     *  debugging
+	     */
+	    extern struct pci_dev *pci_pmu;
+	    u8 t8;
+
+	    pci_pmu = dev;		/* for LEDs D2 and D3 */
+	    /* Program the lines for LEDs D2 and D3 to output */
+	    nile4_pci_read_config_byte(dev, 0x7d, &t8);
+	    t8 |= 0xc0;
+	    nile4_pci_write_config_byte(dev, 0x7d, t8);
+	    /* Turn LEDs D2 and D3 off */
+	    nile4_pci_read_config_byte(dev, 0x7e, &t8);
+	    t8 |= 0xc0;
+	    nile4_pci_write_config_byte(dev, 0x7e, t8);
 	}
-	pcibios_claim_resources(&bus->children);
     }
 }
 
-
-void pcibios_init(void)
+static void __init pcibios_fixup_irqs(void)
 {
-    printk("PCI: Probing PCI hardware\n");
-    ioport_resource.end = 0x1ffffff;
-    pci_scan_bus(0, &nile4_pci_ops, NULL);
-    pcibios_claim_resources(&pci_root_buses);
-}
-
-void pcibios_fixup_bus(struct pci_bus *bus)
-{
-    struct list_head *dn;
     struct pci_dev *dev;
-    extern struct pci_dev *pci_pmu;	/* for LEDs D2 and D3 */
-    int slot_num, func_num;
-    u8 t8;
-
-    /*
-     *  FIXME: PMON doesn't autoconfigure the PCI devices
-     *         For now we just hardcode them for our configuration
-     */
-    printk("PCI: Configuring PCI devices (hardcoded)\n");
-    for (dn = bus->devices.next; dn != &bus->devices; dn = dn->next) {
-	dev = pci_dev_b(dn);
+    int slot_num;
 
+    pci_for_each_dev(dev) {
 	slot_num = PCI_SLOT(dev->devfn);
-	func_num = PCI_FUNC(dev->devfn);
-	printk("  Device %2d: ", slot_num);
 	switch (slot_num) {
 	    case 0:
-		printk("[onboard] Acer Labs M1533 Aladdin IV\n");
 		dev->irq = nile4_to_irq(NILE4_INT_INTE);
 		break;
 	    case 1:
-		printk("[onboard] DEC DC21140\n");
 		dev->irq = nile4_to_irq(NILE4_INT_INTA);
-		dev->resource[0].start = 0x100000;
-		dev->resource[0].end = dev->resource[0].start+0x7f;
-		nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-					     dev->resource[0].start);
-		dev->resource[1].start = 0x1000000;
-		dev->resource[1].end = dev->resource[1].start+0x7f;
-		nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-					     dev->resource[1].start);
 		break;
-	    case 2:
-		printk("[slot 1]  Realtek 8029\n");
+	    case 2:	/* slot 1 */
 		dev->irq = nile4_to_irq(NILE4_INT_INTA);
-		dev->resource[0].start = 0x800000;
-		dev->resource[0].end = dev->resource[0].start+0x1f;
-		nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-					     dev->resource[0].start);
 		break;
-	    case 3:
-		printk("[slot 2]  DEC DC21140 (#2)\n");
+	    case 3:	/* slot 2 */
 		dev->irq = nile4_to_irq(NILE4_INT_INTB);
-		dev->resource[0].start = 0x1000000;
-		dev->resource[0].end = dev->resource[0].start+0x7f;
-		nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-					     dev->resource[0].start);
-		dev->resource[1].start = 0x4000000;
-		dev->resource[1].end = dev->resource[1].start+0x7f;
-		nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-					     dev->resource[1].start);
 		break;
-	    case 4:
-		printk("[slot 3]  Promise Technology IDE UltraDMA/33");
-		printk(" or 3Com 3c905 :-)\n");
+	    case 4:	/* slot 3 */
 		dev->irq = nile4_to_irq(NILE4_INT_INTC);
-		dev->resource[0].start = 0x1800000;
-		dev->resource[0].end = dev->resource[0].start+0x7fffff;
-		nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-					     dev->resource[0].start);
 		break;
 	    case 5:
-		printk("[onboard] NEC Vrc-5074 Nile 4 Host Bridge\n");
 		/*
 		 * Fixup so the serial driver can use the UART
 		 */
 		dev->irq = nile4_to_irq(NILE4_INT_UART);
-		dev->resource[0].start = PHYSADDR(NILE4_BASE);
-		dev->resource[0].end = dev->resource[0].start+NILE4_SIZE-1;
-		dev->resource[0].flags = IORESOURCE_MEM |
-					 PCI_BASE_ADDRESS_MEM_TYPE_64;
-		
-		break;
-	    case 10:
-		printk("[onboard] Acer Labs M7101 PMU\n");
-		pci_pmu = dev;
-		/* Program the lines for LEDs D2 and D3 to output */
-		nile4_pci_read_config_byte(dev, 0x7d, &t8);
-		t8 |= 0xc0;
-		nile4_pci_write_config_byte(dev, 0x7d, t8);
-		/* Turn LEDs D2 and D3 off */
-		nile4_pci_read_config_byte(dev, 0x7e, &t8);
-		t8 |= 0xc0;
-		nile4_pci_write_config_byte(dev, 0x7e, t8);
 		break;
 	    case 13:
-		printk("[onboard] Acer Labs M5237 USB\n");
 		dev->irq = nile4_to_irq(NILE4_INT_INTE);
-		dev->resource[0].start = 0x1001000;
-		dev->resource[0].end = dev->resource[0].start+0xfff;
-		nile4_pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
-					     dev->resource[0].start);
 		break;
 	    default:
-		printk("\n");
 		break;
 	}
     }
 }
 
-char *pcibios_setup (char *str)
+void __init pcibios_init(void)
 {
-    return str;
+    printk("PCI: Probing PCI hardware\n");
+    ioport_resource.end = 0x1ffffff;		/*  32 MB */
+    iomem_resource.end = 0x1fffffff;		/* 512 MB */
+    /* `ram' and `nile4' are requested through the Nile4 pci_dev */
+    request_resource(&iomem_resource, &ddb5074_resources.flash);
+    request_resource(&iomem_resource, &ddb5074_resources.isa_io);
+    request_resource(&iomem_resource, &ddb5074_resources.pci_io);
+    request_resource(&iomem_resource, &ddb5074_resources.isa_mem);
+    request_resource(&iomem_resource, &ddb5074_resources.pci_mem);
+    request_resource(&iomem_resource, &ddb5074_resources.boot);
+
+    pci_scan_bus(0, &nile4_pci_ops, NULL);
+    ddb5074_pci_fixup();
+    pci_assign_unassigned_resources();
+    pci_set_bus_ranges();
+    pcibios_fixup_irqs();
 }
 
-void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-				    struct resource *res, int resource)
+void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-    unsigned long where, size;
-    u32 reg;
+    bus->resource[1] = &ddb5074_resources.pci_mem;
+}
 
-    where = PCI_BASE_ADDRESS_0 + (resource * 4);
-    size = res->end - res->start;
-    pci_read_config_dword(dev, where, &reg);
-    reg = (reg & size) | (((u32)(res->start - root->start)) & ~size);
-    pci_write_config_dword(dev, where, reg);
+char *pcibios_setup (char *str)
+{
+    return str;
 }
 
 void __init pcibios_update_irq(struct pci_dev *dev, int irq)
@@ -341,15 +314,85 @@
     ranges->mem_end -= bus->resource[1]->start;
 }
 
-int __init pcibios_enable_device(struct pci_dev *dev)
+int pcibios_enable_resources(struct pci_dev *dev)
 {
-    printk("pcibios_enable_device for %04x:%04x\n", dev->vendor, dev->device);
-    panic("pcibios_enable_device: not yet implemented\n");
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: Enabling device %s (%04x -> %04x)\n", dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+    return pcibios_enable_resources(dev);
+}
+
+void pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			     struct resource *res, int resource)
+{
+	u32 new, check;
+	int reg;
+
+	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
+	
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
+	}
+}
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size)
+{
+	struct pci_dev *dev = data;
+
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		/* We need to avoid collisions with `mirrored' VGA ports
+		   and other strange ISA hardware, so we always want the
+		   addresses kilobyte aligned.  */
+		if (size > 0x100) {
+			printk(KERN_ERR "PCI: I/O Region %s/%d too large"
+			       " (%ld bytes)\n", dev->slot_name,
+			       dev->resource - res, size);
+		}
+
+		start = (start + 1024 - 1) & ~(1024 - 1);
+		res->start = start;
+	}
 }
 
-void __init pcibios_align_resource(void *data, struct resource *res,
-				   unsigned long size)
-{}
 
 struct pci_fixup pcibios_fixups[] = {};
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/prom.c linux/arch/mips/ddb5074/prom.c
--- v2.3.99-pre8/linux/arch/mips/ddb5074/prom.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/ddb5074/prom.c	Sat May 13 08:29:14 2000
@@ -2,9 +2,9 @@
  *  arch/mips/ddb5074/prom.c -- NEC DDB Vrc-5074 PROM routines
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
- *  $Id: prom.c,v 1.2 2000/02/14 17:07:36 ralf Exp $
+ *  $Id: prom.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
 
 #include <linux/init.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/setup.c linux/arch/mips/ddb5074/setup.c
--- v2.3.99-pre8/linux/arch/mips/ddb5074/setup.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/ddb5074/setup.c	Sat May 13 08:29:14 2000
@@ -2,9 +2,9 @@
  *  arch/mips/ddb5074/setup.c -- NEC DDB Vrc-5074 setup routines
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
- *  $Id: setup.c,v 1.2 2000/02/14 17:07:36 ralf Exp $
+ *  $Id: setup.c,v 1.1 2000/01/26 00:07:44 ralf Exp $
  */
 
 #include <linux/config.h>
@@ -40,12 +40,12 @@
 
 extern struct rtc_ops ddb_rtc_ops;
 
+static void (*back_to_prom)(void) = (void (*)(void))0xbfc00000;
+
 static void ddb_machine_restart(char *command)
 {
     u32 t;
 
-    // FIXME: This doesn't seem to work...
-    printk("Restarting DDB Vrc-5074...");
     /* PCI cold reset */
     t = nile4_in32(NILE4_PCICTRL+4);
     t |= 0x40000000;
@@ -54,8 +54,8 @@
     t = nile4_in32(NILE4_CPUSTAT);
     t |= 1;
     nile4_out32(NILE4_CPUSTAT, t);
-    printk("Restart failed!\n");
-    do {} while (1);
+    /* Call the PROM */
+    back_to_prom();
 }
 
 static void ddb_machine_halt(void)
@@ -91,6 +91,8 @@
 
 void __init ddb_setup(void)
 {
+    extern int panic_timeout;
+
     irq_setup = ddb_irq_setup;
     mips_io_port_base = NILE4_PCI_IO_BASE;
     isa_slot_offset = NILE4_PCI_MEM_BASE;
@@ -106,6 +108,9 @@
     _machine_power_off = ddb_machine_power_off;
 
     rtc_ops = &ddb_rtc_ops;
+
+    /* Reboot on panic */
+    panic_timeout = 180;
 }
 
 int __init page_is_ram(unsigned long pagenr)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/ddb5074/time.c linux/arch/mips/ddb5074/time.c
--- v2.3.99-pre8/linux/arch/mips/ddb5074/time.c	Sat Feb 26 22:31:39 2000
+++ linux/arch/mips/ddb5074/time.c	Sat May 13 08:29:14 2000
@@ -1,8 +1,8 @@
 /*
- *  arch.mips/ddb5074/time.c -- Timer routines
+ *  arch/mips/ddb5074/time.c -- Timer routines
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
  *  $Id*
  */
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c
--- v2.3.99-pre8/linux/arch/mips/dec/irq.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/dec/irq.c	Sat May 13 08:29:14 2000
@@ -31,6 +31,8 @@
 extern volatile unsigned int *imr;	/* address of the interrupt mask register       */
 extern decint_t dec_interrupt[NR_INTS];
 
+irq_cpustat_t irq_stat [NR_CPUS];
+
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 unsigned long spurious_count = 0;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/prom/Makefile linux/arch/mips/dec/prom/Makefile
--- v2.3.99-pre8/linux/arch/mips/dec/prom/Makefile	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/dec/prom/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 2000/02/05 06:47:08 ralf Exp $
+# $Id: Makefile,v 1.1 1999/01/17 03:49:44 ralf Exp $
 # Makefile for the DECstation prom monitor library routines
 # under Linux.
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/prom/init.c linux/arch/mips/dec/prom/init.c
--- v2.3.99-pre8/linux/arch/mips/dec/prom/init.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/dec/prom/init.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1998 Harald Koerfgen
  *
- * $Id: init.c,v 1.4 1999/10/09 00:00:58 ralf Exp $
+ * $Id: init.c,v 1.3 1999/08/09 19:43:13 harald Exp $
  */
 #include <linux/init.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/prom/memory.c linux/arch/mips/dec/prom/memory.c
--- v2.3.99-pre8/linux/arch/mips/dec/prom/memory.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/dec/prom/memory.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
  *
- * $Id: memory.c,v 1.4 2000/02/13 20:52:05 harald Exp $
+ * $Id: memory.c,v 1.3 1999/10/09 00:00:58 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/reset.c linux/arch/mips/dec/reset.c
--- v2.3.99-pre8/linux/arch/mips/dec/reset.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/reset.c	Sat May 13 08:29:14 2000
@@ -1,5 +1,5 @@
 /*
- *  $Id: reset.c,v 1.4 1999/04/11 17:06:16 harald Exp $
+ *  $Id: $
  *
  *  Reset a DECstation machine.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/rtc-dec.c linux/arch/mips/dec/rtc-dec.c
--- v2.3.99-pre8/linux/arch/mips/dec/rtc-dec.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/dec/rtc-dec.c	Sat May 13 08:29:14 2000
@@ -1,5 +1,5 @@
 
-/* $Id: rtc-dec.c,v 1.1 1999/01/17 03:49:42 ralf Exp $
+/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/dec/serial.c linux/arch/mips/dec/serial.c
--- v2.3.99-pre8/linux/arch/mips/dec/serial.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/mips/dec/serial.c	Sat May 13 08:29:14 2000
@@ -31,11 +31,11 @@
 #ifdef CONFIG_SERIAL_CONSOLE
 
 #ifdef CONFIG_ZS
-extern long zs_serial_console_init(long, long);
+extern void zs_serial_console_init(void);
 #endif
 
 #ifdef CONFIG_DZ
-extern long dz_serial_console_init(long, long);
+extern void dz_serial_console_init(void);
 #endif
 
 #endif
@@ -66,6 +66,8 @@
 #endif
 }
 
+__initcall(rs_init);
+
 #endif
 
 #ifdef CONFIG_SERIAL_CONSOLE
@@ -73,26 +75,24 @@
 /* serial_console_init handles the special case of starting
  *   up the console on the serial port
  */
-long __init serial_console_init(long kmem_start, long kmem_end)
+void __init serial_console_init(void)
 {
 #if defined(CONFIG_ZS) && defined(CONFIG_DZ)
     if (IOASIC)
-	kmem_start = zs_serial_console_init(kmem_start, kmem_end);
+	zs_serial_console_init();
     else
-	kmem_start = dz_serial_console_init(kmem_start, kmem_end);
+	dz_serial_console_init();
 #else
 
 #ifdef CONFIG_ZS
-    kmem_start = zs_serial_console_init(kmem_start, kmem_end);
+    zs_serial_console_init();
 #endif
 
 #ifdef CONFIG_DZ
-    kmem_start = dz_serial_console_init(kmem_start, kmem_end);
+    dz_serial_console_init();
 #endif
 
 #endif
-
-    return kmem_start;
 }
 
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/defconfig linux/arch/mips/defconfig
--- v2.3.99-pre8/linux/arch/mips/defconfig	Thu May 11 15:30:06 2000
+++ linux/arch/mips/defconfig	Sat May 13 08:29:14 2000
@@ -20,8 +20,9 @@
 CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
 # CONFIG_SBUS is not set
-# CONFIG_PCI is not set
+CONFIG_ARC32=y
 # CONFIG_ISA is not set
+# CONFIG_PCI is not set
 
 #
 # CPU selection
@@ -50,24 +51,18 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_NET=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 
 #
-# Loadable module support
+# Parallel port support
 #
+# CONFIG_PARPORT is not set
 CONFIG_MODULES=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA is not set
 
 #
 # Block devices
@@ -75,14 +70,21 @@
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 
 #
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_RAID15_DANGEROUS is not set
 # CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
 
 #
 # Networking options
@@ -134,13 +136,6 @@
 # CONFIG_NET_SCHED is not set
 
 #
-# ATA/IDE/MFM/RLL support
-#
-# CONFIG_IDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
 # SCSI support
 #
 CONFIG_SCSI=y
@@ -174,12 +169,12 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
@@ -187,155 +182,39 @@
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
 # Network device support
 #
 CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_NET_SB1000 is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-# CONFIG_NET_ETHERNET is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_YELLOWFIN is not set
-# CONFIG_ACENIC is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_PPP is not set
+CONFIG_SGISEEQ=y
 
 #
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# AX.25 network device drivers
-#
-# CONFIG_MKISS is not set
-# CONFIG_6PACK is not set
-# CONFIG_BPQETHER is not set
-# CONFIG_DMASCC is not set
-# CONFIG_SCC is not set
-# CONFIG_BAYCOM_SER_FDX is not set
-# CONFIG_BAYCOM_SER_HDX is not set
-# CONFIG_BAYCOM_PAR is not set
-# CONFIG_BAYCOM_EPP is not set
-# CONFIG_SOUNDMODEM is not set
-# CONFIG_YAM is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
-# Character devices
+# SGI Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SGI_NEWPORT_CONSOLE=y
+CONFIG_FONT_8x16=y
+# CONFIG_SGI_PROM_CONSOLE is not set
 # CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
 
 #
 # File systems
@@ -344,6 +223,7 @@
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -353,10 +233,12 @@
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
@@ -364,17 +246,22 @@
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -382,6 +269,16 @@
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
@@ -392,16 +289,25 @@
 # CONFIG_AMIGA_PARTITION is not set
 # CONFIG_ATARI_PARTITION is not set
 # CONFIG_MAC_PARTITION is not set
-# CONFIG_MSDOS_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
 # Console drivers
 #
-CONFIG_SGI_NEWPORT_CONSOLE=y
-CONFIG_FONT_8x16=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
 
 #
 # Sound
@@ -412,8 +318,14 @@
 # SGI devices
 #
 CONFIG_SGI_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
 CONFIG_SGI_DS1286=y
 # CONFIG_SGI_NEWPORT_GFX is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/defconfig-decstation linux/arch/mips/defconfig-decstation
--- v2.3.99-pre8/linux/arch/mips/defconfig-decstation	Fri Mar 10 16:40:40 2000
+++ linux/arch/mips/defconfig-decstation	Sat May 13 08:29:14 2000
@@ -1,5 +1,5 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 
 #
@@ -19,6 +19,9 @@
 # CONFIG_OLIVETTI_M700 is not set
 # CONFIG_SGI_IP22 is not set
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SBUS is not set
+# CONFIG_ISA is not set
+# CONFIG_PCI is not set
 
 #
 # CPU selection
@@ -45,47 +48,41 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_NET=y
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 
 #
-# Loadable module support
+# Parallel port support
 #
+# CONFIG_PARPORT is not set
 CONFIG_MODULES=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
-
-#
-# TURBOchannel support
-#
 CONFIG_TC=y
+# CONFIG_PCMCIA is not set
 
 #
-# Plug and Play configuration
+# Block devices
 #
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 
 #
-# Block devices
+# Additional Block Devices
 #
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-# CONFIG_BLK_DEV_HD_ONLY is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_RAID15_DANGEROUS is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_INITRD is not set
 
 #
 # Networking options
@@ -107,10 +104,18 @@
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_ALIAS is not set
 # CONFIG_SYN_COOKIES is not set
+
+#
+# (it is safe to leave these untouched)
+#
 # CONFIG_SKB_LARGE is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
@@ -129,33 +134,65 @@
 # CONFIG_NET_SCHED is not set
 
 #
-# Telephony Support
+# SCSI support
 #
-# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
+CONFIG_SCSI=y
 
 #
-# SCSI support
+# SCSI support type (disk, tape, CD-ROM)
 #
-CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_CHR_DEV_ST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_DECNCR=y
-# CONFIG_SCSI_DECSII is not set
+# CONFIG_SCSI_LOGGING is not set
 
 #
-# I2O device support
+# SCSI low-level drivers
 #
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
+CONFIG_SCSI_DECNCR=y
+# CONFIG_SCSI_DECSII is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Network device support
@@ -167,7 +204,7 @@
 CONFIG_DECLANCE=y
 
 #
-# DECstation Character devices
+# DECStation Character devices
 #
 # CONFIG_VT is not set
 CONFIG_SERIAL=y
@@ -177,29 +214,26 @@
 # CONFIG_UNIX98_PTYS is not set
 # CONFIG_KEYBOARD is not set
 # CONFIG_MOUSE is not set
+# CONFIG_RTC is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Filesystems
+# File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_BFS_FS_WRITE is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
@@ -207,6 +241,9 @@
 # CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_QNX4FS_RW is not set
@@ -224,6 +261,7 @@
 #
 # CONFIG_CODA_FS is not set
 # CONFIG_NFS_FS is not set
+# CONFIG_NFS_V3 is not set
 # CONFIG_ROOT_NFS is not set
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
@@ -231,6 +269,16 @@
 # CONFIG_LOCKD is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
@@ -249,6 +297,11 @@
 CONFIG_ULTRIX_PARTITION=y
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/defconfig-ip22 linux/arch/mips/defconfig-ip22
--- v2.3.99-pre8/linux/arch/mips/defconfig-ip22	Thu May 11 15:30:06 2000
+++ linux/arch/mips/defconfig-ip22	Sat May 13 08:29:14 2000
@@ -19,6 +19,10 @@
 # CONFIG_OLIVETTI_M700 is not set
 CONFIG_SGI_IP22=y
 # CONFIG_SNI_RM200_PCI is not set
+# CONFIG_SBUS is not set
+CONFIG_ARC32=y
+# CONFIG_ISA is not set
+# CONFIG_PCI is not set
 
 #
 # CPU selection
@@ -47,50 +51,40 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_NET=y
-
-#
-# PCMCIA/CardBus support
-#
-# CONFIG_PCMCIA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 
 #
-# Loadable module support
+# Parallel port support
 #
+# CONFIG_PARPORT is not set
 CONFIG_MODULES=y
 # CONFIG_MODVERSIONS is not set
 CONFIG_KMOD=y
-
-#
-# Plug and Play configuration
-#
-# CONFIG_PNP is not set
-# CONFIG_ISAPNP is not set
+# CONFIG_PCMCIA is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 
 #
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_RAID15_DANGEROUS is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_INITRD is not set
 
 #
 # Networking options
@@ -142,12 +136,6 @@
 # CONFIG_NET_SCHED is not set
 
 #
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-# CONFIG_PHONE_IXJ is not set
-
-#
 # SCSI support
 #
 CONFIG_SCSI=y
@@ -158,7 +146,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
-CONFIG_ST_EXTRA_DEVS=2
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
@@ -182,12 +169,12 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
@@ -195,32 +182,20 @@
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_PPA is not set
-# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_NCR53C7xx is not set
 # CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
 # CONFIG_SCSI_PSI240I is not set
 # CONFIG_SCSI_QLOGIC_FAS is not set
-# CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
-# CONFIG_I2O_BLOCK is not set
-# CONFIG_I2O_LAN is not set
-# CONFIG_I2O_SCSI is not set
-# CONFIG_I2O_PROC is not set
 
 #
 # Network device support
@@ -232,64 +207,14 @@
 CONFIG_SGISEEQ=y
 
 #
-# Character devices
+# SGI Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_SGI_NEWPORT_CONSOLE=y
+CONFIG_FONT_8x16=y
+# CONFIG_SGI_PROM_CONSOLE is not set
 # CONFIG_UNIX98_PTYS is not set
-# CONFIG_PRINTER is not set
-# CONFIG_PPDEV is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-CONFIG_MOUSE=y
-CONFIG_PSMOUSE=y
-# CONFIG_82C710_MOUSE is not set
-# CONFIG_PC110_PAD is not set
-
-#
-# Joysticks
-#
-# CONFIG_JOYSTICK is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_NVRAM is not set
-# CONFIG_RTC is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
-# CONFIG_DRM_TDFX is not set
-# CONFIG_AGP is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
 
 #
 # File systems
@@ -298,6 +223,7 @@
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -307,10 +233,12 @@
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
@@ -318,17 +246,22 @@
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -336,19 +269,45 @@
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
 CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
 # Console drivers
 #
-CONFIG_SGI_NEWPORT_CONSOLE=y
-CONFIG_FONT_8x16=y
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
 
 #
 # Sound
@@ -359,8 +318,14 @@
 # SGI devices
 #
 CONFIG_SGI_SERIAL=y
+# CONFIG_SERIAL_CONSOLE is not set
 CONFIG_SGI_DS1286=y
 # CONFIG_SGI_NEWPORT_GFX is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/Makefile linux/arch/mips/jazz/Makefile
--- v2.3.99-pre8/linux/arch/mips/jazz/Makefile	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/jazz/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.6 1999/02/25 21:57:01 tsbogend Exp $
+# $Id: Makefile,v 1.5 1999/01/03 17:50:47 ralf Exp $
 #
 # Makefile for the Jazz family specific parts of the kernel
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/floppy-jazz.c linux/arch/mips/jazz/floppy-jazz.c
--- v2.3.99-pre8/linux/arch/mips/jazz/floppy-jazz.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/jazz/floppy-jazz.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy-jazz.c,v 1.3 2000/02/24 00:12:40 ralf Exp $
+/* $Id: floppy-jazz.c,v 1.2 1998/10/18 13:18:25 tsbogend 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/int-handler.S linux/arch/mips/jazz/int-handler.S
--- v2.3.99-pre8/linux/arch/mips/jazz/int-handler.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/jazz/int-handler.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: int-handler.S,v 1.15 1999/08/18 23:37:43 ralf Exp $
+/* $Id: int-handler.S,v 1.14 1999/05/01 22:40:34 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/kbd-jazz.c linux/arch/mips/jazz/kbd-jazz.c
--- v2.3.99-pre8/linux/arch/mips/jazz/kbd-jazz.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/jazz/kbd-jazz.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: kbd-jazz.c,v 1.1 1999/01/03 17:50:48 ralf Exp $
+/* $Id: kbd-jazz.c,v 1.1 1998/10/28 12:38:10 ralf Exp $
  *
  * Low-level hardware access stuff for Jazz family machines.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/reset.c linux/arch/mips/jazz/reset.c
--- v2.3.99-pre8/linux/arch/mips/jazz/reset.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/jazz/reset.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  *  Reset a Jazz machine.
  *
- *  $Id: reset.c,v 1.3 1998/03/04 08:29:10 ralf Exp $
+ *  $Id:$
  */
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/rtc-jazz.c linux/arch/mips/jazz/rtc-jazz.c
--- v2.3.99-pre8/linux/arch/mips/jazz/rtc-jazz.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/jazz/rtc-jazz.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: rtc-jazz.c,v 1.2 1998/08/26 21:46:38 tsbogend Exp $
+/* $Id: rtc-jazz.c,v 1.2 1998/06/25 20:19:14 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/jazz/setup.c linux/arch/mips/jazz/setup.c
--- v2.3.99-pre8/linux/arch/mips/jazz/setup.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/jazz/setup.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.25 2000/01/27 01:05:23 ralf Exp $
+/* $Id: setup.c,v 1.24 1999/10/09 00:00:58 ralf Exp $
  *
  * Setup pointers to hardware-dependent routines.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile
--- v2.3.99-pre8/linux/arch/mips/kernel/Makefile	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.15 2000/01/26 00:07:44 ralf Exp $
+# $Id: Makefile,v 1.14 1999/10/09 00:00:58 ralf Exp $
 #
 # Makefile for the Linux/MIPS kernel.
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S
--- v2.3.99-pre8/linux/arch/mips/kernel/entry.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/entry.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.20 2000/02/23 00:41:00 ralf Exp $
+/* $Id: entry.S,v 1.19 1999/12/08 22:05:10 harald Exp $
  *
  * Low level exception handling
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/fpe.c linux/arch/mips/kernel/fpe.c
--- v2.3.99-pre8/linux/arch/mips/kernel/fpe.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/fpe.c	Sat May 13 08:29:14 2000
@@ -6,7 +6,7 @@
  *
  * Copyright (C) 1997 Ralf Baechle
  *
- * $Id: fpe.c,v 1.4 1999/05/01 22:40:35 ralf Exp $
+ * $Id: fpe.c,v 1.3 1998/04/05 11:23:50 ralf Exp $
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/gdb-low.S linux/arch/mips/kernel/gdb-low.S
--- v2.3.99-pre8/linux/arch/mips/kernel/gdb-low.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/gdb-low.S	Sat May 13 08:29:14 2000
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 1995 Andreas Busse
  *
- * $Id: gdb-low.S,v 1.5 1999/08/18 23:37:43 ralf Exp $
+ * $Id: gdb-low.S,v 1.4 1997/12/01 17:57:26 ralf Exp $
  */
 
 #include <linux/sys.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c
--- v2.3.99-pre8/linux/arch/mips/kernel/gdb-stub.c	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/gdb-stub.c	Sat May 13 08:29:14 2000
@@ -12,7 +12,7 @@
  *
  *  Copyright (C) 1995 Andreas Busse
  *
- * $Id: gdb-stub.c,v 1.7 1999/06/12 18:39:28 ulfc Exp $
+ * $Id: gdb-stub.c,v 1.6 1999/05/01 22:40:35 ralf Exp $
  */
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S
--- v2.3.99-pre8/linux/arch/mips/kernel/head.S	Thu May 11 15:30:06 2000
+++ linux/arch/mips/kernel/head.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.17 1999/12/04 03:58:59 ralf Exp $
+/* $Id: head.S,v 1.18 2000/03/03 22:17:07 kevink Exp $
  *
  * arch/mips/kernel/head.S
  *
@@ -29,7 +29,6 @@
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 #include <asm/bootinfo.h>
-#include <asm/cpu.h>
 
 	.text
 	/*
@@ -101,7 +100,7 @@
 	eret
 	END(except_vec0_r4600)
 
-	/* TLB refill, EXL == 0, R4xx0, non-R4600 version */
+	/* TLB refill, EXL == 0, R52x0 "Nevada" version */
 	.set	noreorder
 	.set	noat
 	LEAF(except_vec0_nevada)
@@ -122,9 +121,10 @@
 	mtc0	k0, CP0_ENTRYLO0		# load it
 	srl	k1, k1, 6			# convert to entrylo1
 	mtc0	k1, CP0_ENTRYLO1		# load it
-	tlbwr					# write random tlb entry
-	nop
+	nop					# QED specified nops
 	nop
+	tlbwr					# write random tlb entry
+	nop					# traditional nop
 	eret					# return from trap
 	END(except_vec0_nevada)
 
@@ -393,12 +393,6 @@
 	EXPORT(stext)
 	EXPORT(_stext)
 
-	/* Determine which MIPS variant we are running on. */
-	b	cpu_probe
-	 nop
-
-probe_done:
-
 	/*
 	 * Stack for kernel and init, current variable
 	 */
@@ -420,166 +414,9 @@
 	bne	t0, t1, 1b
 	 sw	zero, (t0)
 
-	jal	prom_init /* prom_init(argc, argv, envp); */
-	 nop
-#ifdef CONFIG_SGI_IP22
-	jal	sgi_sysinit
-	 nop
-#endif
-
-#ifdef CONFIG_COBALT_MICRO_SERVER
-	jal	SetUpBootInfo
-	 nop
-#endif
-
-	/*
-	 * Determine the mmu/cache attached to this machine,
-	 * then flush the tlb and caches.  On the r4xx0
-	 * variants this also sets CP0_WIRED to zero.
-	 */
-	jal	loadmmu
+	jal	init_arch
 	 nop
-
-	/* Disable coprocessors */
-	mfc0	t0, CP0_STATUS
-	li	t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX)
-	and	t0, t1
-	or	t0, ST0_CU0
-	mtc0	t0, CP0_STATUS
-
-1:	jal	start_kernel
-	 nop
-	/*
-	 * Main should never return here, but
-	 * just in case, we know what happens.
-	 */
-	b	1b
-	 nop					# delay slot
 	END(kernel_entry)
-
-	/* CPU type probing code, called at Kernel entry. */
-	LEAF(cpu_probe)
-	mfc0	t0, CP0_PRID
-	la	t3, mips_cputype
-	andi	t1, t0, 0xff00
-	li	t2, PRID_IMP_R2000
-	bne	t1, t2, 1f
-	 andi	t0, 0x00ff
-
-	li	t2, CPU_R2000
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R3000
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, PRID_REV_R3000A
-	bne	t0, t2, 9f
-	 nop
-
-	li	t2, CPU_R3000A
-	b	probe_done
-	sw	t2, (t3)
-9:
-	li	t2, CPU_R3000
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R6000
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R6000
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R4000
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, PRID_REV_R4400
-	bne	t0, t2, 9f
-	 nop
-
-	li	t2, CPU_R4400SC
-	b	probe_done
-	 sw	t2, (t3)
-9:
-	li	t2, CPU_R4000SC
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R6000A
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R6000A
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R10000
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R10000
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R8000
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R8000
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R4600
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R4600
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R4700
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R4700
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R4650
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R4650
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_R5000
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_R5000
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, PRID_IMP_NEVADA
-	bne	t1, t2, 1f
-	 nop
-
-	li	t2, CPU_NEVADA
-	b	probe_done
-	 sw	t2, (t3)
-1:
-	li	t2, CPU_UNKNOWN
-	sw	t2, (t3)
-
-	b	probe_done
-	 nop
-	END(cpu_probe)
 
 /*
  * This buffer is reserved for the use of the cache error handler.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irix5sys.h linux/arch/mips/kernel/irix5sys.h
--- v2.3.99-pre8/linux/arch/mips/kernel/irix5sys.h	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/irix5sys.h	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: irix5sys.h,v 1.2 1998/08/25 09:14:39 ralf Exp $
+/* $Id: irix5sys.h,v 1.2 1998/08/17 10:16:25 ralf Exp $
  *
  * irix5sys.h: 32-bit IRIX5 ABI system call table.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
--- v2.3.99-pre8/linux/arch/mips/kernel/irixelf.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/mips/kernel/irixelf.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: irixelf.c,v 1.24 2000/02/04 07:40:23 ralf Exp $
+/* $Id: irixelf.c,v 1.28 2000/03/23 02:25:42 ralf Exp $
  *
  * irixelf.c: Code to load IRIX ELF executables which conform to
  *            the MIPS ABI.
@@ -29,6 +29,7 @@
 #include <linux/shm.h>
 #include <linux/personality.h>
 #include <linux/elfcore.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -253,10 +254,10 @@
 #endif
 
 	/* First of all, some simple consistency checks */
-	if((interp_elf_ex->e_type != ET_EXEC &&
-	    interp_elf_ex->e_type != ET_DYN) ||
-	    !elf_check_arch(interp_elf_ex->e_machine) ||
-	    !interpreter->f_op->mmap) {
+	if ((interp_elf_ex->e_type != ET_EXEC &&
+	     interp_elf_ex->e_type != ET_DYN) ||
+	     !elf_check_arch(interp_elf_ex->e_machine) ||
+	     !interpreter->f_op->mmap) {
 		printk("IRIX interp has bad e_type %d\n", interp_elf_ex->e_type);
 		return 0xffffffff;
 	}
@@ -424,42 +425,41 @@
 					    struct elf_phdr *epp,
 					    struct linux_binprm *bprm, int pnum)
 {
-	mm_segment_t old_fs;
 	int i;
 	int retval = -EINVAL;
 	struct file *file = NULL;
 
 	*name = NULL;
 	for(i = 0; i < pnum; i++, epp++) {
-		if(epp->p_type != PT_INTERP)
+		if (epp->p_type != PT_INTERP)
 			continue;
 
 		/* It is illegal to have two interpreters for one executable. */
-		if(*name != NULL)
+		if (*name != NULL)
 			goto out;
 
 		*name = (char *) kmalloc((epp->p_filesz +
 					  strlen(IRIX_INTERP_PREFIX)),
 					 GFP_KERNEL);
-		if(!*name)
+		if (!*name)
 			return -ENOMEM;
 
 		strcpy(*name, IRIX_INTERP_PREFIX);
 		retval = kernel_read(bprm->file, epp->p_offset, (*name + 16),
-				   epp->p_filesz);
-		if(retval < 0)
+		                     epp->p_filesz);
+		if (retval < 0)
 			goto out;
 
 		file = open_exec(*name);
-		if(IS_ERR(file)) {
+		if (IS_ERR(file)) {
 			retval = PTR_ERR(file);
 			goto out;
 		}
 		retval = kernel_read(file, 0, bprm->buf, 128);
-		if(retval < 0)
+		if (retval < 0)
 			goto dput_and_out;
 
-		*interp_elf_ex = *((struct elfhdr *) bprm->buf);
+		*interp_elf_ex = *(struct elfhdr *) bprm->buf;
 	}
 	*interpreter = file;
 	return 0;
@@ -548,7 +548,7 @@
 
 		fput(interp);
 
-		if(*eentry == 0xffffffff)
+		if (*eentry == 0xffffffff)
 			return -1;
 	}
 	return 0;
@@ -655,10 +655,10 @@
 	                                   &interpreter,
 					   &interp_elf_ex, elf_phdata, bprm,
 					   elf_ex.e_phnum);
-	if(retval)
+	if (retval)
 		goto out_free_file;
 
-	if(elf_interpreter) {
+	if (elf_interpreter) {
 		retval = verify_irix_interpreter(&interp_elf_ex);
 		if(retval)
 			goto out_free_interp;
@@ -841,8 +841,8 @@
 	up(&current->mm->mmap_sem);
 
 	k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
-	if(k > elf_bss) elf_bss = k;
-	
+	if (k > elf_bss) elf_bss = k;
+
 	if (error != (elf_phdata->p_vaddr & 0xfffff000)) {
 		kfree(elf_phdata);
 		return error;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixinv.c linux/arch/mips/kernel/irixinv.c
--- v2.3.99-pre8/linux/arch/mips/kernel/irixinv.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/irixinv.c	Sat May 13 08:29:14 2000
@@ -5,7 +5,7 @@
  *
  * Miguel de Icaza, 1997.
  *
- * $Id: irixinv.c,v 1.4 1999/10/09 00:00:58 ralf Exp $
+ * $Id: irixinv.c,v 1.3 1998/04/05 11:23:51 ralf Exp $
  */
 #include <linux/mm.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixioctl.c linux/arch/mips/kernel/irixioctl.c
--- v2.3.99-pre8/linux/arch/mips/kernel/irixioctl.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/irixioctl.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: irixioctl.c,v 1.7 1999/09/28 22:25:46 ralf Exp $
+/* $Id: irixioctl.c,v 1.6 1999/02/06 05:12:56 adevries Exp $
  * irixioctl.c: A fucking mess...
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c
--- v2.3.99-pre8/linux/arch/mips/kernel/irixsig.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/irixsig.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: irixsig.c,v 1.14 2000/01/17 03:58:59 ralf Exp $
+ * $Id: irixsig.c,v 1.13 1999/10/09 00:00:58 ralf Exp $
  */
 
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v2.3.99-pre8/linux/arch/mips/kernel/irq.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/irq.c	Sat May 13 08:29:14 2000
@@ -32,6 +32,24 @@
 #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.
+ */
+
+irq_cpustat_t irq_stat [NR_CPUS];
+
+/*
  * 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.)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c
--- v2.3.99-pre8/linux/arch/mips/kernel/mips_ksyms.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/mips_ksyms.c	Sat May 13 08:29:14 2000
@@ -23,6 +23,7 @@
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
+#include <asm/semaphore.h>
 #include <asm/sgi/sgihpc.h>
 #include <asm/softirq.h>
 #include <asm/uaccess.h>
@@ -56,8 +57,6 @@
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 EXPORT_SYMBOL(_clear_page);
-EXPORT_SYMBOL(local_bh_count);
-EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_thread);
@@ -87,6 +86,13 @@
 EXPORT_SYMBOL(_dma_cache_inv);
 
 EXPORT_SYMBOL(invalid_pte_table);
+
+/*
+ * Semaphore stuff
+ */
+EXPORT_SYMBOL(__down_read);
+EXPORT_SYMBOL(__down_write);
+EXPORT_SYMBOL(__rwsem_wake);
 
 /*
  * Base address of ports for Intel style I/O.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c
--- v2.3.99-pre8/linux/arch/mips/kernel/proc.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/proc.c	Sat May 13 08:29:14 2000
@@ -34,6 +34,7 @@
 	const char *mach_sgi_names[] = GROUP_SGI_NAMES;
 	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_group_to_name[] = { mach_unknown_names,
 	                                      mach_jazz_names,
 	                                      mach_dec_names,
@@ -42,7 +43,8 @@
 	                                      mach_acn_names,
 	                                      mach_sgi_names,
 					      mach_cobalt_names,
-					      mach_nec_ddb_names };
+					      mach_nec_ddb_names,
+					      mach_baget_names };
 	unsigned int version = read_32bit_cp0_register(CP0_PRID);
 	int len;
 
@@ -68,7 +70,7 @@
 	len += sprintf(buffer + len, "unaligned accesses\t: %lu\n",
 		       unaligned_instructions);
 	len += sprintf(buffer + len, "wait instruction\t: %s\n",
-	               wait_available ? "yes" : "no");
+	               cpu_wait ? "yes" : "no");
 	len += sprintf(buffer + len, "microsecond timers\t: %s\n",
 	               cyclecounter_available ? "yes" : "no");
 	len += sprintf(buffer + len, "extra interrupt vector\t: %s\n",
@@ -82,4 +84,9 @@
 	len += sprintf(buffer + len, fmt, 'I', vcei_count);
 
 	return len;
+}
+
+void init_irq_proc(void)
+{
+	/* Nothing, for now.  */
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v2.3.99-pre8/linux/arch/mips/kernel/process.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/process.c	Sat May 13 08:29:14 2000
@@ -40,10 +40,8 @@
 
 	while (1) {
 		while (!current->need_resched)
-			if (wait_available)
-				__asm__(".set\tmips3\n\t"
-					"wait\n\t"
-					".set\tmips0");
+			if (cpu_wait)
+				(*cpu_wait)();
 		schedule();
 		check_pgt_cache();
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v2.3.99-pre8/linux/arch/mips/kernel/ptrace.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/ptrace.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: ptrace.c,v 1.18 1999/10/09 00:00:58 ralf Exp $
+/* $Id: ptrace.c,v 1.17 1999/09/28 22:25:47 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
@@ -28,7 +28,6 @@
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
-	unsigned int flags;
 	int res;
 	extern void save_fp(void*);
 
@@ -49,19 +48,22 @@
 		res = 0;
 		goto out;
 	}
-	if (pid == 1) {		/* you may not mess with init */
-		res = -EPERM;
+	res = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
 		goto out;
-	}
-	if (!(child = find_task_by_pid(pid))) {
-		res = -ESRCH;
+
+	res = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
 		goto out;
-	}
+
 	if (request == PTRACE_ATTACH) {
-		if (child == current) {
-			res = -EPERM;
-			goto out;
-		}
+		if (child == current)
+			goto out_tsk;
 		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
@@ -71,42 +73,34 @@
 	 	    (current->gid != child->gid) ||
 		    (!cap_issubset(child->cap_permitted,
 		                  current->cap_permitted)) ||
-                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE)){
-			res = -EPERM;
-			goto out;
-		}
+                    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+			goto out_tsk;
 		/* the same process cannot be attached many times */
 		if (child->flags & PF_PTRACED)
-			goto out;
+			goto out_tsk;
 		child->flags |= PF_PTRACED;
 
-		write_lock_irqsave(&tasklist_lock, flags);
+		write_lock_irq(&tasklist_lock);
 		if (child->p_pptr != current) {
 			REMOVE_LINKS(child);
 			child->p_pptr = current;
 			SET_LINKS(child);
 		}
-		write_unlock_irqrestore(&tasklist_lock, flags);
+		write_unlock_irq(&tasklist_lock);
 
 		send_sig(SIGSTOP, child, 1);
 		res = 0;
-		goto out;
-	}
-	if (!(child->flags & PF_PTRACED)) {
-		res = -ESRCH;
-		goto out;
+		goto out_tsk;
 	}
+	res = -ESRCH;
+	if (!(child->flags & PF_PTRACED))
+		goto out_tsk;
 	if (child->state != TASK_STOPPED) {
-		if (request != PTRACE_KILL) {
-			res = -ESRCH;
-			goto out;
-		}
-	}
-	if (child->p_pptr != current) {
-		res = -ESRCH;
-		goto out;
+		if (request != PTRACE_KILL)
+			goto out_tsk;
 	}
-
+	if (child->p_pptr != current)
+		goto out_tsk;
 	switch (request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
@@ -116,11 +110,11 @@
 		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
 		res = -EIO;
 		if (copied != sizeof(tmp))
-			goto out;
+			break;
 		res = put_user(tmp,(unsigned long *) data);
 
 		goto out;
-	}
+		}
 
 	/* Read the word at location addr in the USER area.  */
 	case PTRACE_PEEKUSR: {
@@ -189,7 +183,7 @@
 		res = 0;
 		if (access_process_vm(child, addr, &data, sizeof(data), 1)
 		    == sizeof(data))
-			goto out;
+			break;
 		res = -EIO;
 		goto out;
 
@@ -240,23 +234,22 @@
 			res = -EIO;
 			break;
 		}
-		goto out;
+		break;
 		}
 
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT: { /* restart after signal. */
-		if ((unsigned long) data > _NSIG) {
-			res = -EIO;
-			goto out;
-		}
+		res = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
 		if (request == PTRACE_SYSCALL)
 			child->flags |= PF_TRACESYS;
 		else
 			child->flags &= ~PF_TRACESYS;
 		child->exit_code = data;
 		wake_up_process(child);
-		res = data;
-		goto out;
+		res = 0;
+		break;
 		}
 
 	/*
@@ -264,34 +257,35 @@
 	 * perhaps it should be put in the status that it wants to 
 	 * exit.
 	 */
-	case PTRACE_KILL: {
-		if (child->state != TASK_ZOMBIE) {
-			child->exit_code = SIGKILL;
-			wake_up_process(child);
-		}
+	case PTRACE_KILL:
 		res = 0;
-		goto out;
-		}
+		if (child->state != TASK_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		wake_up_process(child);
+		break;
 
-	case PTRACE_DETACH: { /* detach a process that was attached. */
-		if ((unsigned long) data > _NSIG) {
-			res = -EIO;
-			goto out;
-		}
+	case PTRACE_DETACH: /* detach a process that was attached. */
+		res = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
 		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
 		child->exit_code = data;
+		write_lock_irq(&tasklist_lock);
 		REMOVE_LINKS(child);
 		child->p_pptr = child->p_opptr;
 		SET_LINKS(child);
+		write_unlock_irq(&tasklist_lock);
 		wake_up_process(child);
 		res = 0;
-		goto out;
-		}
+		break;
 
 	default:
 		res = -EIO;
 		goto out;
 	}
+out_tsk:
+	free_task_struct(child);
 out:
 	unlock_kernel();
 	return res;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S
--- v2.3.99-pre8/linux/arch/mips/kernel/r2300_fpu.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/r2300_fpu.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: r2300_fpu.S,v 1.7 1999/09/28 22:25:47 ralf Exp $
+/* $Id: r2300_fpu.S,v 1.6 1999/08/09 19:43:14 harald Exp $
  *
  * r2300_fpu.S: Save/restore floating point context for signal handlers.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S
--- v2.3.99-pre8/linux/arch/mips/kernel/r2300_switch.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/r2300_switch.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: r2300_switch.S,v 1.9 1999/10/12 17:33:49 harald Exp $
+/* $Id: r2300_switch.S,v 1.8 1999/08/18 23:37:44 ralf Exp $
  *
  * r2300_switch.S: R2300 specific task switching code.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S
--- v2.3.99-pre8/linux/arch/mips/kernel/r4k_fpu.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/r4k_fpu.S	Sat May 13 08:29:14 2000
@@ -32,7 +32,6 @@
 	cfc1	t1,fcr31
 
 	/* Store the 16 even double precision registers */
-1:
 	EX(sdc1	$f0,(SC_FPREGS+0)(a0))
 	EX(sdc1	$f2,(SC_FPREGS+16)(a0))
 	EX(sdc1	$f4,(SC_FPREGS+32)(a0))
@@ -75,7 +74,7 @@
 	 * Restore the 16 even double precision registers
 	 * when cp1 was enabled in the cp0 status register.
 	 */
-1:	EX(ldc1	$f0,(SC_FPREGS+0)(a0))
+	EX(ldc1	$f0,(SC_FPREGS+0)(a0))
 	EX(ldc1	$f2,(SC_FPREGS+16)(a0))
 	EX(ldc1	$f4,(SC_FPREGS+32)(a0))
 	EX(ldc1	$f6,(SC_FPREGS+48)(a0))
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S
--- v2.3.99-pre8/linux/arch/mips/kernel/r4k_misc.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/r4k_misc.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: r4k_misc.S,v 1.9 1999/12/04 03:59:00 ralf Exp $
+/* $Id: r4k_misc.S,v 1.8 1999/10/09 00:00:58 ralf Exp $
  *
  * r4k_misc.S: Misc. exception handling code for r4k.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S
--- v2.3.99-pre8/linux/arch/mips/kernel/r4k_switch.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/r4k_switch.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: r4k_switch.S,v 1.10 1999/10/09 00:00:58 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/r6000_fpu.S linux/arch/mips/kernel/r6000_fpu.S
--- v2.3.99-pre8/linux/arch/mips/kernel/r6000_fpu.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/r6000_fpu.S	Sat May 13 08:29:14 2000
@@ -10,7 +10,7 @@
  * Multi-arch abstraction and asm macros for easier reading:
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r6000_fpu.S,v 1.6 1999/08/09 19:43:15 harald Exp $
+ * $Id: r6000_fpu.S,v 1.5 1999/05/01 22:40:37 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/fpregdef.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S
--- v2.3.99-pre8/linux/arch/mips/kernel/scall_o32.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/scall_o32.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: scall_o32.S,v 1.11 2000/02/23 01:33:55 ralf Exp $
+/* $Id: scall_o32.S,v 1.10 2000/02/23 00:41: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v2.3.99-pre8/linux/arch/mips/kernel/setup.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/setup.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.22 2000/01/27 01:05:23 ralf Exp $
+/* $Id: setup.c,v 1.28 2000/03/13 22:21:44 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
@@ -39,6 +39,7 @@
 #include <asm/io.h>
 #include <asm/stackframe.h>
 #include <asm/system.h>
+#include <asm/cpu.h>
 #ifdef CONFIG_SGI_IP22
 #include <asm/sgialib.h>
 #endif
@@ -46,11 +47,13 @@
 struct mips_cpuinfo boot_cpu_data = { NULL, NULL, 0 };
 
 /*
- * Not all of the MIPS CPUs have the "wait" instruction available.  This
- * is set to true if it is available.  The wait instruction stops the
- * pipeline and reduces the power consumption of the CPU very much.
+ * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
+ * the implementation of the "wait" feature differs between CPU families. This
+ * points to the function that implements CPU specific wait. 
+ * The wait instruction stops the pipeline and reduces the power consumption of
+ * the CPU very much.
  */
-char wait_available;
+void (*cpu_wait)(void) = NULL;
 
 /*
  * Do we have a cyclecounter available?
@@ -119,6 +122,125 @@
  */
 unsigned long isa_slot_offset;
 
+extern void sgi_sysinit(void);
+extern void SetUpBootInfo(void);
+extern void loadmmu(void);
+extern asmlinkage void start_kernel(void);
+extern int prom_init(int, char **, char **, int *);
+
+/*
+ * Probe whether cpu has config register by trying to play with
+ * alternate cache bit and see whether it matters.
+ * It's used by cpu_probe to distinguish between R3000A and R3081.
+ */
+static inline int cpu_has_confreg(void)
+{
+#ifdef CONFIG_CPU_R3000
+	extern unsigned long r3k_cache_size(unsigned long);
+	unsigned long size1, size2; 
+	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);
+
+	size1 = r3k_cache_size(ST0_DE);
+	write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC);
+	size2 = r3k_cache_size(ST0_DE);
+	write_32bit_cp0_register(CP0_CONF, cfg);
+	return size1 != size2;
+#else
+	return 0;
+#endif
+}
+
+static inline void cpu_probe(void)
+{
+	unsigned int prid = read_32bit_cp0_register(CP0_PRID);
+	switch(prid & 0xff00) {
+	case PRID_IMP_R2000:
+		mips_cputype = CPU_R2000;
+		break;
+	case PRID_IMP_R3000:
+		if((prid & 0xff) == PRID_REV_R3000A)
+			if(cpu_has_confreg())
+				mips_cputype = CPU_R3081E;
+			else
+				mips_cputype = CPU_R3000A;
+		else
+			 mips_cputype = CPU_R3000;
+		break;
+	case PRID_IMP_R4000:
+		if((prid & 0xff) == PRID_REV_R4400)
+			mips_cputype = CPU_R4400SC;
+		else
+			mips_cputype = CPU_R4000SC;
+		break;
+	case PRID_IMP_R4600:
+		mips_cputype = CPU_R4600;
+		break;
+	case PRID_IMP_R4650:
+		mips_cputype = CPU_R4650;
+		break;
+	case PRID_IMP_R4700:
+		mips_cputype = CPU_R4700;
+		break;
+	case PRID_IMP_R5000:
+		mips_cputype = CPU_R5000;
+		break;
+	case PRID_IMP_NEVADA:
+		mips_cputype = CPU_NEVADA;
+		break;
+	case PRID_IMP_R6000:
+		mips_cputype = CPU_R6000;
+		break;
+	case PRID_IMP_R6000A:
+		mips_cputype = CPU_R6000A;
+		break;
+	case PRID_IMP_R8000:
+		mips_cputype = CPU_R8000;
+		break;
+	case PRID_IMP_R10000:
+		mips_cputype = CPU_R10000;
+		break;
+	default:
+		mips_cputype = CPU_UNKNOWN;
+	}
+}
+
+asmlinkage void __init init_arch(int argc, char **argv, char **envp, int *prom_vec)
+{
+	unsigned int s;
+
+	/* Determine which MIPS variant we are running on. */
+	cpu_probe();
+
+	prom_init(argc, argv, envp, prom_vec);
+
+#ifdef CONFIG_SGI_IP22
+	sgi_sysinit();
+#endif
+#ifdef CONFIG_COBALT_MICRO_SERVER
+	SetUpBootInfo();
+#endif
+
+	/*
+	 * Determine the mmu/cache attached to this machine,
+	 * then flush the tlb and caches.  On the r4xx0
+	 * variants this also sets CP0_WIRED to zero.
+	 */
+	loadmmu();
+
+	/* Disable coprocessors */
+	s = read_32bit_cp0_register(CP0_STATUS);
+	s &= ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_KX|ST0_SX);
+	s |= ST0_CU0;
+	write_32bit_cp0_register(CP0_STATUS, s);
+
+	/*
+	 * Main should never return here, but
+	 * just in case, we know what happens.
+	 */
+	for(;;)
+		start_kernel();
+}
+
 static void __init default_irq_setup(void)
 {
 	panic("Unknown machtype in init_IRQ");
@@ -156,7 +278,7 @@
 	switch(mips_machgroup)
 	{
 #ifdef CONFIG_BAGET_MIPS
-	case MACH_GROUP_UNKNOWN: 
+	case MACH_GROUP_BAGET: 
 		baget_setup();
 		break;
 #endif
@@ -220,4 +342,19 @@
 			*memory_start_p = initrd_end;
 	}
 #endif
+
+	paging_init();
+}
+
+void r3081_wait(void) 
+{
+	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);
+	write_32bit_cp0_register(CP0_CONF, cfg|CONF_HALT);
+}
+
+void r4k_wait(void)
+{
+	__asm__(".set\tmips3\n\t"
+		"wait\n\t"
+		".set\tmips0");
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/signal.c linux/arch/mips/kernel/signal.c
--- v2.3.99-pre8/linux/arch/mips/kernel/signal.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/signal.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.25 2000/02/05 06:47:08 ralf Exp $
+/* $Id: signal.c,v 1.24 2000/02/04 07:40:23 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/softfp.S linux/arch/mips/kernel/softfp.S
--- v2.3.99-pre8/linux/arch/mips/kernel/softfp.S	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/kernel/softfp.S	Sat May 13 08:29:14 2000
@@ -147,7 +147,7 @@
 insn:	LOCK_KERNEL;							\
 	la	a1, 8f;							\
 	TEXT(#insn);							\
-	la	a1, nosim;						\
+	la	a0, nosim;						\
 	UNLOCK_KERNEL;							\
 	j	done
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- v2.3.99-pre8/linux/arch/mips/kernel/syscall.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/syscall.c	Sat May 13 08:29:14 2000
@@ -129,7 +129,6 @@
 	int error;
 	char * filename;
 
-	lock_kernel();
 	filename = getname((char *) (long)regs.regs[4]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
@@ -139,7 +138,6 @@
 	putname(filename);
 
 out:
-	unlock_kernel();
 	return error;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h
--- v2.3.99-pre8/linux/arch/mips/kernel/syscalls.h	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/syscalls.h	Sat May 13 08:29:14 2000
@@ -44,7 +44,7 @@
 SYS(sys_ptrace, 4)
 SYS(sys_alarm, 1)
 SYS(sys_fstat, 2)
-SYS(sys_ni_syscall, 0)
+SYS(sys_pause, 0)
 SYS(sys_utime, 2)				/* 4030 */
 SYS(sys_ni_syscall, 0)
 SYS(sys_ni_syscall, 0)
@@ -232,3 +232,5 @@
 SYS(sys_lstat64, 3)
 SYS(sys_fstat64, 3)				/* 4215 */
 SYS(sys_pivot_root, 2)
+SYS(sys_mincore, 3)
+SYS(sys_madvise, 3)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.3.99-pre8/linux/arch/mips/kernel/sysirix.c	Thu May 11 15:30:06 2000
+++ linux/arch/mips/kernel/sysirix.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: sysirix.c,v 1.24 2000/02/05 06:47:08 ralf Exp $
+/* $Id: sysirix.c,v 1.26 2000/03/12 23:15:33 ralf Exp $
  *
  * sysirix.c: IRIX system call emulation.
  *
@@ -853,7 +853,6 @@
 	int error, base = 0;
 	char *filename;
 
-	lock_kernel();
 	if(regs->regs[2] == 1000)
 		base = 1;
 	filename = getname((char *) (long)regs->regs[base + 4]);
@@ -865,7 +864,6 @@
 	putname(filename);
 
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -1491,10 +1489,10 @@
 	printk("[%s:%ld] Wheee.. irix_statvfs(%s,%p)\n",
 	       current->comm, current->pid, fname, buf);
 	error = verify_area(VERIFY_WRITE, buf, sizeof(struct irix_statvfs));
-	if(error)
+	if (error)
 		goto out;
 	error = user_path_walk(fname, &nd);
-	if (err)
+	if (error)
 		goto out;
 	error = vfs_statfs(nd.dentry->d_inode->i_sb, &kbuf);
 	if (error)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c
--- v2.3.99-pre8/linux/arch/mips/kernel/sysmips.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/sysmips.c	Sat May 13 08:29:14 2000
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
  *
- * $Id: sysmips.c,v 1.9 2000/02/18 00:24:30 ralf Exp $
+ * $Id: sysmips.c,v 1.8 2000/02/05 06:47:08 ralf Exp $
  */
 #include <linux/errno.h>
 #include <linux/linkage.h>
@@ -123,4 +123,11 @@
 sys_cachectl(char *addr, int nbytes, int op)
 {
 	return -ENOSYS;
+}
+
+asmlinkage int sys_pause(void)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	return -ERESTARTNOHAND;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- v2.3.99-pre8/linux/arch/mips/kernel/traps.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/traps.c	Sat May 13 08:29:14 2000
@@ -1,12 +1,13 @@
-/* $Id: traps.c,v 1.27 2000/01/16 01:29:05 ralf Exp $
+/* $Id: traps.c,v 1.28 2000/03/13 10:33:02 raiko 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 1994, 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1994 - 1999 by Ralf Baechle
  * Modified for R3000 by Paul M. Antoine, 1995, 1996
  * Complete output from die() by Ulf Carlsson, 1998
+ * Copyright (C) 1999 Silicon Graphics, Inc.
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -226,8 +227,50 @@
 		__die(str, regs, where, line);
 }
 
+extern const struct exception_table_entry __start___dbe_table[];
+extern const struct exception_table_entry __stop___dbe_table[];
+
+static void __declare_dbe_table(void)
+{
+	__asm__ __volatile__(
+	".section\t__dbe_table,\"a\"\n\t"
+	".previous"
+	);
+}
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+		 const struct exception_table_entry *last,
+		 unsigned long value)
+{
+	const struct exception_table_entry *mid;
+	long diff;
+
+	while (first < last) {
+		mid = (last - first) / 2 + first;
+		diff = mid->insn - value;
+		if (diff < 0)
+			first = mid + 1;
+		else
+			last = mid;
+	}
+	return (first == last && first->insn == value) ? first->nextinsn : 0;
+}
+
+#define search_dbe_table(addr)	\
+	search_one_table(__start___dbe_table, __stop___dbe_table - 1, (addr))
+
 static void default_be_board_handler(struct pt_regs *regs)
 {
+	unsigned long new_epc;
+	unsigned long fixup = search_dbe_table(regs->cp0_epc);
+
+	if (fixup) {
+		new_epc = fixup_exception(dpf_reg, fixup, regs->cp0_epc);
+		regs->cp0_epc = new_epc;
+		return;
+	}
+
 	/*
 	 * Assume it would be too dangerous to continue ...
 	 */
@@ -281,7 +324,7 @@
 {
 	unsigned long pc;
 	unsigned int insn;
-	extern void simfp(void*);
+	extern void simfp(unsigned int);
 
 #ifdef CONFIG_MIPS_FPE_MODULE
 	if (fpe_handler != NULL) {
@@ -688,8 +731,7 @@
 		else
 			memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
 
-		/* Cache error vector  */
-		memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
+		/* Cache error vector already set above.  */
 
 		if (vce_available) {
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
@@ -698,7 +740,6 @@
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
 			       0x80);
 		}
-
 		break;
 
 	case CPU_R6000:
@@ -718,14 +759,14 @@
 	case CPU_R2000:
 	case CPU_R3000:
 	case CPU_R3000A:
-		memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
-		memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
-		break;
 	case CPU_R3041:
 	case CPU_R3051:
 	case CPU_R3052:
 	case CPU_R3081:
 	case CPU_R3081E:
+		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]);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c
--- v2.3.99-pre8/linux/arch/mips/kernel/unaligned.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/kernel/unaligned.c	Sat May 13 08:29:14 2000
@@ -7,8 +7,7 @@
  * for more details.
  *
  * Copyright (C) 1996, 1998 by Ralf Baechle
- *
- * $Id: unaligned.c,v 1.7 1999/12/04 03:59:00 ralf Exp $
+ * Copyright (C) 1999 Silicon Graphics, Inc.
  *
  * This file contains exception handler for address error exception with the
  * special capability to execute faulting instructions in software.  The
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- v2.3.99-pre8/linux/arch/mips/lib/Makefile	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.12 1999/12/04 03:59:00 ralf Exp $
+# $Id: Makefile,v 1.11 1999/10/17 19:55:22 harald Exp $
 #
 # Makefile for MIPS-specific library files..
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/csum_partial.S linux/arch/mips/lib/csum_partial.S
--- v2.3.99-pre8/linux/arch/mips/lib/csum_partial.S	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/lib/csum_partial.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: csum_partial.S,v 1.2 1998/05/07 23:44:01 ralf Exp $
+/* $Id: csum_partial.S,v 1.1 1998/05/04 09:12: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/csum_partial_copy.c linux/arch/mips/lib/csum_partial_copy.c
--- v2.3.99-pre8/linux/arch/mips/lib/csum_partial_copy.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/csum_partial_copy.c	Sat May 13 08:29:14 2000
@@ -14,7 +14,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * $Id: csum_partial_copy.c,v 1.3 2000/02/05 06:47:08 ralf Exp $
+ * $Id: csum_partial_copy.c,v 1.2 1998/09/19 19:16:17 ralf Exp $
  */
 #include <net/checksum.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/floppy-no.c linux/arch/mips/lib/floppy-no.c
--- v2.3.99-pre8/linux/arch/mips/lib/floppy-no.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/floppy-no.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy-no.c,v 1.1 1998/06/30 00:21:54 ralf Exp $
+/* $Id: floppy-no.c,v 1.1 1998/05/07 18:38:32 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/floppy-std.c linux/arch/mips/lib/floppy-std.c
--- v2.3.99-pre8/linux/arch/mips/lib/floppy-std.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/floppy-std.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy-std.c,v 1.3 2000/02/24 00:12:40 ralf Exp $
+/* $Id: floppy-std.c,v 1.2 1999/01/04 16:03:51 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/ide-no.c linux/arch/mips/lib/ide-no.c
--- v2.3.99-pre8/linux/arch/mips/lib/ide-no.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/lib/ide-no.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: ide-no.c,v 1.3 1999/06/17 13:25:49 ralf Exp $
+/* $Id: ide-no.c,v 1.2 1998/06/30 00:21:54 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/ide-std.c linux/arch/mips/lib/ide-std.c
--- v2.3.99-pre8/linux/arch/mips/lib/ide-std.c	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/lib/ide-std.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: ide-std.c,v 1.4 1999/06/17 13:25:49 ralf Exp $
+/* $Id: ide-std.c,v 1.4 1999/06/11 14:29: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/kbd-no.c linux/arch/mips/lib/kbd-no.c
--- v2.3.99-pre8/linux/arch/mips/lib/kbd-no.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/kbd-no.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: kbd-no.c,v 1.1 1999/01/04 16:03:51 ralf Exp $
+/* $Id: kbd-no.c,v 1.1 1998/10/28 12:38:14 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/kbd-std.c linux/arch/mips/lib/kbd-std.c
--- v2.3.99-pre8/linux/arch/mips/lib/kbd-std.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/kbd-std.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: kbd-std.c,v 1.2 1999/06/17 13:25:50 ralf Exp $
+/* $Id: kbd-std.c,v 1.2 1999/06/11 14:29: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/memcpy.S linux/arch/mips/lib/memcpy.S
--- v2.3.99-pre8/linux/arch/mips/lib/memcpy.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/memcpy.S	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * $Id: memcpy.S,v 1.4 2000/01/27 01:05:23 ralf Exp $
+ * $Id: memcpy.S,v 1.3 1998/07/10 01:14:49 ralf Exp $
  *
  * Unified implementation of memcpy, memmove and the __copy_user backend.
  * For __rmemcpy and memmove an exception is always a kernel bug, therefore
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S
--- v2.3.99-pre8/linux/arch/mips/lib/memset.S	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/lib/memset.S	Sat May 13 08:29:14 2000
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1998 by Ralf Baechle
  *
- * $Id: memset.S,v 1.1 1998/05/04 09:12:54 ralf Exp $
+ * $Id: memset.S,v 1.2 1998/04/25 17:01:45 ralf Exp $
  */
 #include <asm/asm.h>
 #include <asm/offset.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/r3k_dump_tlb.c linux/arch/mips/lib/r3k_dump_tlb.c
--- v2.3.99-pre8/linux/arch/mips/lib/r3k_dump_tlb.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/r3k_dump_tlb.c	Sat May 13 08:29:14 2000
@@ -29,7 +29,7 @@
 
 	for(i=first;i<=last;i++)
 	{
-		write_32bit_cp0_register(CP0_INDEX, i);
+		write_32bit_cp0_register(CP0_INDEX, i<<8);
 		__asm__ __volatile__(
 			".set\tnoreorder\n\t"
 			"tlbr\n\t"
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/rtc-no.c linux/arch/mips/lib/rtc-no.c
--- v2.3.99-pre8/linux/arch/mips/lib/rtc-no.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/rtc-no.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: rtc-no.c,v 1.1 1998/06/30 00:21:55 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/rtc-std.c linux/arch/mips/lib/rtc-std.c
--- v2.3.99-pre8/linux/arch/mips/lib/rtc-std.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/rtc-std.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: rtc-std.c,v 1.1 1998/06/30 00:21:55 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/strlen_user.S linux/arch/mips/lib/strlen_user.S
--- v2.3.99-pre8/linux/arch/mips/lib/strlen_user.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/strlen_user.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: strlen_user.S,v 1.4 1999/12/04 03:59:00 ralf Exp $
+/* $Id: strlen_user.S,v 1.3 1999/08/21 22:19:11 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/strncpy_user.S linux/arch/mips/lib/strncpy_user.S
--- v2.3.99-pre8/linux/arch/mips/lib/strncpy_user.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/strncpy_user.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: strncpy_user.S,v 1.4 1999/12/04 03:59:00 ralf Exp $
+/* $Id: strncpy_user.S,v 1.3 1999/08/21 22:19:11 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/strnlen_user.S linux/arch/mips/lib/strnlen_user.S
--- v2.3.99-pre8/linux/arch/mips/lib/strnlen_user.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/strnlen_user.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: strnlen_user.S,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: strnlen_user.S,v 1.2 1999/11/19 20:35: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/lib/watch.S linux/arch/mips/lib/watch.S
--- v2.3.99-pre8/linux/arch/mips/lib/watch.S	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/lib/watch.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: watch.S,v 1.3 1999/08/21 22:19:11 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/andes.c linux/arch/mips/mm/andes.c
--- v2.3.99-pre8/linux/arch/mips/mm/andes.c	Sat Feb 26 22:31:40 2000
+++ linux/arch/mips/mm/andes.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: andes.c,v 1.11 2000/02/24 00:12:40 ralf Exp $
+/* $Id: andes.c,v 1.10 2000/02/13 20:52:05 harald Exp $
  *
  * andes.c: MMU and cache operations for the R10000 (ANDES).
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/fault.c linux/arch/mips/mm/fault.c
--- v2.3.99-pre8/linux/arch/mips/mm/fault.c	Wed Apr 26 16:34:06 2000
+++ linux/arch/mips/mm/fault.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.16 2000/02/18 00:24:30 ralf Exp $
+/* $Id: fault.c,v 1.15 2000/02/04 07:40:23 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
@@ -90,12 +90,17 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	{
-		int fault = handle_mm_fault(mm, vma, address, write);
-		if (fault < 0)
-			goto out_of_memory;
-		if (!fault)
-			goto do_sigbus;
+	switch (handle_mm_fault(mm, vma, address, write)) {
+	case 1:
+		tsk->min_flt++;
+		break;
+	case 2:
+		tsk->maj_flt++;
+		break;
+	case 0:
+		goto do_sigbus;
+	default:
+		goto out_of_memory;
 	}
 
 	up(&mm->mmap_sem);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/init.c linux/arch/mips/mm/init.c
--- v2.3.99-pre8/linux/arch/mips/mm/init.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/mm/init.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.27 2000/02/23 01:33:56 ralf Exp $
+/* $Id: init.c,v 1.26 2000/02/23 00:41: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/loadmmu.c linux/arch/mips/mm/loadmmu.c
--- v2.3.99-pre8/linux/arch/mips/mm/loadmmu.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips/mm/loadmmu.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: loadmmu.c,v 1.15 2000/02/24 00:12:40 ralf Exp $
+ * $Id: loadmmu.c,v 1.17 2000/03/13 10:33:05 raiko Exp $
  */
 #include <linux/config.h>
 #include <linux/init.h>
@@ -15,7 +15,6 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/bootinfo.h>
-#include <asm/sgialib.h>
 
 /* memory functions */
 void (*_clear_page)(void * page);
@@ -59,6 +58,7 @@
 	case CPU_R2000:
 	case CPU_R3000:
 	case CPU_R3000A:
+	case CPU_R3081E:
 		printk("Loading R[23]00 MMU routines.\n");
 		ld_mmu_r2300();
 		break;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/r2300.c linux/arch/mips/mm/r2300.c
--- v2.3.99-pre8/linux/arch/mips/mm/r2300.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/mm/r2300.c	Sat May 13 08:29:14 2000
@@ -7,7 +7,7 @@
  * Copyright (C) 1998, 2000 Harald Koerfgen
  * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
  *
- * $Id: r2300.c,v 1.15 2000/02/24 00:12:40 ralf Exp $
+ * $Id: r2300.c,v 1.16 2000/03/13 10:33:05 raiko Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -18,7 +18,6 @@
 #include <asm/pgtable.h>
 #include <asm/mmu_context.h>
 #include <asm/system.h>
-#include <asm/sgialib.h>
 #include <asm/isadep.h>
 #include <asm/io.h>
 #include <asm/wbflush.h>
@@ -116,7 +115,7 @@
 		 "I" (PAGE_SIZE));
 }
 
-static unsigned long __init size_cache(unsigned long ca_flags)
+unsigned long __init r3k_cache_size(unsigned long ca_flags)
 {
 	unsigned long flags, status, dummy, size;
 	volatile unsigned long *p;
@@ -152,14 +151,14 @@
 
 static void __init probe_dcache(void)
 {
-	dcache_size = size_cache(ST0_DE);
+	dcache_size = r3k_cache_size(ST0_DE);
 	printk("Primary data cache %dkb, linesize 4 bytes\n",
 		dcache_size >> 10);
 }
 
 static void __init probe_icache(void)
 {
-	icache_size = size_cache(ST0_DE|ST0_CE);
+	icache_size = r3k_cache_size(ST0_DE|ST0_CE);
 	printk("Primary instruction cache %dkb, linesize 8 bytes\n",
 		icache_size >> 10);
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/mm/r4xx0.c linux/arch/mips/mm/r4xx0.c
--- v2.3.99-pre8/linux/arch/mips/mm/r4xx0.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/mm/r4xx0.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: r4xx0.c,v 1.30 2000/02/24 01:12:37 ralf Exp $
+/* $Id: r4xx0.c,v 1.29 2000/02/24 00:12:40 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/Makefile linux/arch/mips/sgi/kernel/Makefile
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.8 2000/02/05 06:47:08 ralf Exp $
+# $Id: Makefile,v 1.7 1999/05/07 18:00:16 ulfc Exp $
 # Makefile for the SGI specific kernel interface routines
 # under Linux.
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indyIRQ.S linux/arch/mips/sgi/kernel/indyIRQ.S
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indyIRQ.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/indyIRQ.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: indyIRQ.S,v 1.4 1999/08/18 23:37:45 ralf Exp $
+/* $Id: indyIRQ.S,v 1.3 1998/03/22 23:27:17 ralf Exp $
  * indyIRQ.S: Interrupt exception dispatch code for FullHouse and
  *            Guiness.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_hpc.c linux/arch/mips/sgi/kernel/indy_hpc.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_hpc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/indy_hpc.c	Sat May 13 08:29:14 2000
@@ -6,6 +6,7 @@
  * Copyright (C) 1998 Ralf Baechle
  */
 #include <linux/init.h>
+#include <linux/types.h>
 
 #include <asm/addrspace.h>
 #include <asm/sgi/sgihpc.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_int.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips/sgi/kernel/indy_int.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: indy_int.c,v 1.17 2000/02/04 07:40:23 ralf Exp $
+/* $Id: indy_int.c,v 1.18 2000/03/02 02:36:50 ralf Exp $
  *
  * indy_int.c: Routines for generic manipulation of the INT[23] ASIC
  *             found on INDY workstations..
@@ -38,6 +38,24 @@
 #include <asm/sgi/sgint23.h>
 #include <asm/sgialib.h>
 #include <asm/gdb-stub.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.
+ */
+
+irq_cpustat_t irq_stat [NR_CPUS];
 
 /* #define DEBUG_SGINT */
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_mc.c linux/arch/mips/sgi/kernel/indy_mc.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_mc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/indy_mc.c	Sat May 13 08:29:14 2000
@@ -4,7 +4,7 @@
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - Indigo2 changes
  *
- * $Id: indy_mc.c,v 1.8 1999/12/06 23:13:20 ralf Exp $
+ * $Id: indy_mc.c,v 1.7 1999/12/04 03:59:00 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_rtc.c linux/arch/mips/sgi/kernel/indy_rtc.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_rtc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/indy_rtc.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: indy_rtc.c,v 1.2 1999/10/21 00:23:05 ralf Exp $
+/* $Id: indy_rtc.c,v 1.1 1998/06/30 00:21:58 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_sc.c linux/arch/mips/sgi/kernel/indy_sc.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_sc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/indy_sc.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: indy_sc.c,v 1.13 1999/12/04 03:59:00 ralf Exp $
+/* $Id: indy_sc.c,v 1.14 2000/03/25 22:35:07 ralf Exp $
  *
  * indy_sc.c: Indy cache managment functions.
  *
@@ -28,16 +28,17 @@
 #define SC_SIZE 0x00080000
 #define SC_LINE 32
 #define CI_MASK (SC_SIZE - SC_LINE)
-#define SC_ROUND(n) ((n) + SC_LINE - 1)
 #define SC_INDEX(n) ((n) & CI_MASK)
 
 static inline void indy_sc_wipe(unsigned long first, unsigned long last)
 {
+	unsigned long tmp;
+
 	__asm__ __volatile__("
 		.set	noreorder
 		.set	mips3
 		.set	noat
-		mfc0	$2, $12
+		mfc0	%2, $12
 		li	$1, 0x80	# Go 64 bit
 		mtc0	$1, $12
 
@@ -50,12 +51,12 @@
 		bne	%0, %1, 1b
 		daddu	%0, 32
 
-		mtc0	$2, $12		# Back to 32 bit
+		mtc0	%2, $12		# Back to 32 bit
 		nop; nop; nop; nop;
 		.set mips0
 		.set reorder"
-		: /* no output */
-		: "r" (first), "r" (last)
+		: "=r" (first), "=r" (last), "=&r" (tmp)
+		: "0" (first), "1" (last)
 		: "$1");
 }
 
@@ -67,12 +68,13 @@
 #ifdef DEBUG_CACHE
 	printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
 #endif
+
+	if (!size)
+		return;
+
 	/* Which lines to flush?  */
 	first_line = SC_INDEX(addr);
-	if (size <= SC_LINE)
-		last_line = SC_INDEX(addr);
-	else
-		last_line = SC_INDEX(addr + size - 1);
+	last_line = SC_INDEX(addr + size - 1);
 
 	__save_and_cli(flags);
 	if (first_line <= last_line) {
@@ -80,9 +82,6 @@
 		goto out;
 	}
 
-	/* Cache index wrap around.  Due to the way the buddy system works
-	   this case should not happen.  We're prepared to handle it,
-	   though. */
 	indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
 	indy_sc_wipe(0, last_line);
 out:
@@ -98,8 +97,9 @@
 	printk("Enabling R4600 SCACHE\n");
 #endif
 	__asm__ __volatile__("
-		.set noreorder
-		.set mips3
+		.set	push
+		.set	noreorder
+		.set	mips3
 		mfc0	%2, $12
 		nop; nop; nop; nop;
 		li	%1, 0x80
@@ -115,8 +115,7 @@
 		nop; nop; nop; nop;
 		mtc0	%2, $12
 		nop; nop; nop; nop;
-		.set mips0
-		.set reorder"
+		.set	pop"
 		: "=r" (tmp1), "=r" (tmp2), "=r" (addr));
 }
 
@@ -128,8 +127,9 @@
 	printk("Disabling R4600 SCACHE\n");
 #endif
 	__asm__ __volatile__("
-		.set noreorder
-		.set mips3
+		.set	push
+		.set	noreorder
+		.set	mips3
 		li	%0, 0x1
 		dsll	%0, 31
 		lui	%1, 0x9000
@@ -145,9 +145,8 @@
 		nop; nop; nop; nop;
 		mtc0	%2, $12
 		nop; nop; nop; nop;
-		.set mips2
-		.set reorder
-        " : "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
+		.set	pop"
+		: "=r" (tmp1), "=r" (tmp2), "=r" (tmp3));
 }
 
 static inline int __init indy_sc_probe(void)
@@ -221,7 +220,6 @@
 
 void __init indy_sc_init(void)
 {
-return;
 	if (indy_sc_probe()) {
 		indy_sc_enable();
 		bcops = &indy_sc_ops;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_timer.c linux/arch/mips/sgi/kernel/indy_timer.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/indy_timer.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/indy_timer.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: indy_timer.c,v 1.18 2000/02/04 07:40:23 ralf Exp $
+/* $Id: indy_timer.c,v 1.17 2000/01/21 22:34:03 ralf Exp $
  *
  * indy_timer.c: Setting up the clock on the INDY 8254 controller.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/promcon.c linux/arch/mips/sgi/kernel/promcon.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/promcon.c	Tue Aug 31 17:29:12 1999
+++ linux/arch/mips/sgi/kernel/promcon.c	Sat May 13 08:29:14 2000
@@ -66,8 +66,7 @@
  *    Register console.
  */
 
-long __init sgi_prom_console_init(long kmem_start, long kmem_end)
+void __init sgi_prom_console_init(void )
 {
     register_console(&sercons);
-    return kmem_start;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/reset.c linux/arch/mips/sgi/kernel/reset.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/reset.c	Thu May 11 15:30:06 2000
+++ linux/arch/mips/sgi/kernel/reset.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: reset.c,v 1.8 1999/10/21 00:23:05 ralf Exp $
+/* $Id: reset.c,v 1.7 1999/08/11 20:26:51 andrewb Exp $
  *
  * Reset a SGI.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/setup.c linux/arch/mips/sgi/kernel/setup.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/setup.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/setup.c	Sat May 13 08:29:14 2000
@@ -30,9 +30,10 @@
 #ifdef CONFIG_REMOTE_DEBUG
 extern void rs_kgdb_hook(int);
 extern void breakpoint(void);
+static int remote_debug = 0;
 #endif
 
-#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_PROM_CONSOLE)
+#if defined(CONFIG_SERIAL_CONSOLE) || defined(CONFIG_SGI_PROM_CONSOLE)
 extern void console_setup(char *);
 #endif
 
@@ -40,8 +41,6 @@
 void indy_reboot_setup(void);
 void sgi_volume_set(unsigned char);
 
-static int remote_debug = 0;
-
 #define sgi_kh ((struct hpc_keyb *) (KSEG1 + 0x1fbd9800 + 64))
 
 #define KBD_STAT_IBF		0x02	/* Keyboard input buffer full */
@@ -166,7 +165,7 @@
 	 * graphics console, it is set to "d" for the first serial
 	 * line and "d2" for the second serial line.
 	 */
-	ctype = prom_getenv("console");
+	ctype = ArcGetEnvironmentVariable("console");
 	if(*ctype == 'd') {
 		if(*(ctype+1)=='2')
 			console_setup ("ttyS1");
@@ -197,10 +196,10 @@
 #endif
 
 #ifdef CONFIG_SGI_PROM_CONSOLE
-	console_setup("ttyS0", NULL);
+	console_setup("ttyS0");
 #endif
-	  
-	sgi_volume_set(simple_strtoul(prom_getenv("volume"), NULL, 10));
+ 
+	sgi_volume_set(simple_strtoul(ArcGetEnvironmentVariable("volume"), NULL, 10));
 
 #ifdef CONFIG_VT
 #ifdef CONFIG_SGI_NEWPORT_CONSOLE
@@ -231,3 +230,4 @@
 	init_vino();
 #endif
 }
+__initcall(rs_init);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/system.c linux/arch/mips/sgi/kernel/system.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/system.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/system.c	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: system.c,v 1.9 1999/10/21 00:23:05 ralf Exp $
+ * $Id: system.c,v 1.8 1999/10/09 00:00:59 ralf Exp $
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sgi/kernel/time.c linux/arch/mips/sgi/kernel/time.c
--- v2.3.99-pre8/linux/arch/mips/sgi/kernel/time.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sgi/kernel/time.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.3 1999/10/09 00:00:59 ralf Exp $
+/* $Id: time.c,v 1.2 1998/04/05 11:24:00 ralf Exp $
  * time.c: Generic SGI time_init() code, this will dispatch to the
  *         appropriate per-architecture time/counter init code.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/Makefile linux/arch/mips/sni/Makefile
--- v2.3.99-pre8/linux/arch/mips/sni/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sni/Makefile	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.4 2000/02/18 00:24:30 ralf Exp $
+# $Id: Makefile,v 1.3 1999/01/04 16:03:57 ralf Exp $
 #
 # Makefile for the SNI specific part of the kernel
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/dma.c linux/arch/mips/sni/dma.c
--- v2.3.99-pre8/linux/arch/mips/sni/dma.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sni/dma.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: dma.c,v 1.2 2000/02/24 00:12:41 ralf Exp $
+/* $Id: dma.c,v 1.1 2000/02/18 00:24:30 ralf Exp $
  *
  * Dynamic DMA mapping support.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/int-handler.S linux/arch/mips/sni/int-handler.S
--- v2.3.99-pre8/linux/arch/mips/sni/int-handler.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sni/int-handler.S	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: int-handler.S,v 1.5 1999/08/18 23:37:46 ralf Exp $
+/* $Id: int-handler.S,v 1.4 1999/01/04 16:03:58 ralf Exp $
  *
  * SNI RM200 PCI specific interrupt handler code.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/io.c linux/arch/mips/sni/io.c
--- v2.3.99-pre8/linux/arch/mips/sni/io.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sni/io.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: io.c,v 1.5 1999/10/09 00:00:59 ralf Exp $
+/* $Id: io.c,v 1.4 1999/08/18 23:37:46 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/pci.c linux/arch/mips/sni/pci.c
--- v2.3.99-pre8/linux/arch/mips/sni/pci.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sni/pci.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.10 2000/02/05 06:47:09 ralf Exp $
+/* $Id: pci.c,v 1.9 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/pcimt_scache.c linux/arch/mips/sni/pcimt_scache.c
--- v2.3.99-pre8/linux/arch/mips/sni/pcimt_scache.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sni/pcimt_scache.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: pcimt_scache.c,v 1.5 1999/10/09 00:00:59 ralf Exp $
+/* $Id: pcimt_scache.c,v 1.4 1999/01/04 16:03:59 ralf Exp $
  *
  * arch/mips/sni/pcimt_scache.c
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/sni/setup.c linux/arch/mips/sni/setup.c
--- v2.3.99-pre8/linux/arch/mips/sni/setup.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/sni/setup.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.14 2000/01/27 01:05:23 ralf Exp $
+/* $Id: setup.c,v 1.13 1999/12/04 03:59:00 ralf Exp $
  *
  * Setup pointers to hardware-dependent routines.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/tools/Makefile linux/arch/mips/tools/Makefile
--- v2.3.99-pre8/linux/arch/mips/tools/Makefile	Fri Jun 25 17:40:13 1999
+++ linux/arch/mips/tools/Makefile	Sat May 13 08:29:14 2000
@@ -3,7 +3,7 @@
 # Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
 # Copyright (C) 1997 Ralf Baechle (ralf@gnu.ai.mit.edu)
 #
-# $Id: Makefile,v 1.2 1997/12/01 17:57:41 ralf Exp $
+# $Id: Makefile,v 1.2 1997/09/23 06:23:49 ralf Exp $
 #
 TARGET	:= $(TOPDIR)/include/asm-$(ARCH)/offset.h
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c
--- v2.3.99-pre8/linux/arch/mips/tools/offset.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips/tools/offset.c	Sat May 13 08:29:14 2000
@@ -1,4 +1,4 @@
-/* $Id: offset.c,v 1.12 1999/10/09 00:00:59 ralf Exp $
+/* $Id: offset.c,v 1.11 1999/09/28 22:25:50 ralf Exp $
  *
  * offset.c: Calculate pt_regs and task_struct offsets.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/Makefile linux/arch/mips64/Makefile
--- v2.3.99-pre8/linux/arch/mips64/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.6 2000/01/29 01:41:59 ralf Exp $
+# $Id: Makefile,v 1.5 2000/01/21 22:34:03 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/Makefile linux/arch/mips64/arc/Makefile
--- v2.3.99-pre8/linux/arch/mips64/arc/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.3 2000/01/17 23:32:46 ralf Exp $
+# $Id: Makefile,v 1.1 1999/08/20 21:13:32 ralf Exp $
 #
 # Makefile for the ARC prom monitor library routines under Linux.
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/cmdline.c linux/arch/mips64/arc/cmdline.c
--- v2.3.99-pre8/linux/arch/mips64/arc/cmdline.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/cmdline.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: cmdline.c,v 1.2 1999/11/19 23:29:05 ralf Exp $
+/* $Id: cmdline.c,v 1.2 1999/10/19 20:51: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/console.c linux/arch/mips64/arc/console.c
--- v2.3.99-pre8/linux/arch/mips64/arc/console.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/console.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: console.c,v 1.3 1999/11/19 23:29:05 ralf Exp $
+/* $Id: console.c,v 1.3 1999/10/19 20:51: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/env.c linux/arch/mips64/arc/env.c
--- v2.3.99-pre8/linux/arch/mips64/arc/env.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/env.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: env.c,v 1.4 1999/11/19 23:29:05 ralf Exp $
+/* $Id: env.c,v 1.4 1999/10/19 20:51: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/file.c linux/arch/mips64/arc/file.c
--- v2.3.99-pre8/linux/arch/mips64/arc/file.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/file.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: file.c,v 1.3 1999/11/19 23:29:05 ralf Exp $
+/* $Id: file.c,v 1.3 1999/10/19 20:51: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/identify.c linux/arch/mips64/arc/identify.c
--- v2.3.99-pre8/linux/arch/mips64/arc/identify.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/identify.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: identify.c,v 1.5 2000/01/17 23:32:46 ralf Exp $
+/* $Id: identify.c,v 1.5 1999/11/19 20:35: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/misc.c linux/arch/mips64/arc/misc.c
--- v2.3.99-pre8/linux/arch/mips64/arc/misc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/misc.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.4 2000/01/17 23:32:46 ralf Exp $
+/* $Id: misc.c,v 1.2 1999/08/21 21:42:59 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/printf.c linux/arch/mips64/arc/printf.c
--- v2.3.99-pre8/linux/arch/mips64/arc/printf.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/printf.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: printf.c,v 1.2 1999/11/19 23:29:05 ralf Exp $
+/* $Id: printf.c,v 1.1 1999/08/20 21:13: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/salone.c linux/arch/mips64/arc/salone.c
--- v2.3.99-pre8/linux/arch/mips64/arc/salone.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/salone.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: salone.c,v 1.3 1999/11/19 23:29:05 ralf Exp $
+/* $Id: salone.c,v 1.2 1999/08/21 21:42:59 ralf Exp $
  *
  * Routines to load into memory and execute stand-along program images using
  * ARCS PROM firmware.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/time.c linux/arch/mips64/arc/time.c
--- v2.3.99-pre8/linux/arch/mips64/arc/time.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/time.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.3 1999/11/19 23:29:05 ralf Exp $
+/* $Id: time.c,v 1.2 1999/08/21 21:42:59 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/arc/tree.c linux/arch/mips64/arc/tree.c
--- v2.3.99-pre8/linux/arch/mips64/arc/tree.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/arc/tree.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: tree.c,v 1.4 1999/11/19 23:29:05 ralf Exp $
+/* $Id: tree.c,v 1.3 1999/09/27 16:01: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/boot/Makefile linux/arch/mips64/boot/Makefile
--- v2.3.99-pre8/linux/arch/mips64/boot/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/boot/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 1999/12/04 03:59:00 ralf Exp $
+# $Id: Makefile,v 1.1 1999/08/18 21:46: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/config.in linux/arch/mips64/config.in
--- v2.3.99-pre8/linux/arch/mips64/config.in	Tue Apr 11 15:09:13 2000
+++ linux/arch/mips64/config.in	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.14 2000/02/18 11:06:20 ulfc Exp $
+# $Id: config.in,v 1.19 2000/03/27 01:44:45 ralf Exp $
 #
 # For a description of the syntax of this configuration file,
 # see the Configure script.
@@ -17,26 +17,23 @@
 if [ "$CONFIG_SGI_IP27" = "y" ]; then
    bool '  IP27 N-Mode' CONFIG_SGI_SN0_N_MODE
    bool '  Discontiguous Memory Support' CONFIG_DISCONTIGMEM
+   bool '  Multi-Processing support (Experimental)' CONFIG_SMP
    #bool '  IP27 XXL' CONFIG_SGI_SN0_XXL
 fi
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool 'Symmetric Multi-Processing support' CONFIG_SMP
-fi
 endmenu
 
 #
 # Select some configuration options automatically based on user selections
 #
-unset CONFIG_BOOT_ELF32
-unset CONFIG_BOOT_ELF64
 unset CONFIG_ARC32
 unset CONFIG_ARC64
+unset CONFIG_BINFMT_ELF32
 unset CONFIG_BOARD_SCACHE
+unset CONFIG_BOOT_ELF32
+unset CONFIG_BOOT_ELF64
 unset CONFIG_COHERENT_IO
-unset CONFIG_BINFMT_ELF32
-
-define_bool CONFIG_ISA n
-define_bool CONFIG_SBUS n
+unset CONFIG_ISA
+unset CONFIG_PCI
 
 if [ "$CONFIG_SGI_IP22" = "y" ]; then
    define_bool CONFIG_BOOT_ELF32 y
@@ -51,10 +48,18 @@
    define_bool CONFIG_COHERENT_IO y
    define_bool CONFIG_PCI y
    define_bool CONFIG_QL_ISP_A64 y
-else
+fi
+
+if [ "$CONFIG_ISA" != "y" ]; then
+   define_bool CONFIG_ISA n
+fi
+
+if [ "$CONFIG_PCI" != "y" ]; then
    define_bool CONFIG_PCI n
 fi
 
+define_bool CONFIG_SBUS n
+
 mainmenu_option next_comment
 comment 'CPU selection'
 
@@ -210,6 +215,8 @@
       tristate 'SGI Newport Console support' CONFIG_SGI_NEWPORT_CONSOLE
       if [ "$CONFIG_SGI_NEWPORT_CONSOLE" != "y" ]; then
 	 define_bool CONFIG_DUMMY_CONSOLE y
+      else
+	 define_bool CONFIG_FONT_8x16 y
       fi
    fi
   endmenu
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/defconfig linux/arch/mips64/defconfig
--- v2.3.99-pre8/linux/arch/mips64/defconfig	Thu May 11 15:30:06 2000
+++ linux/arch/mips64/defconfig	Mon May 15 10:57:20 2000
@@ -14,13 +14,14 @@
 CONFIG_SGI_IP27=y
 # CONFIG_SGI_SN0_N_MODE is not set
 # CONFIG_DISCONTIGMEM is not set
-# CONFIG_ISA is not set
-# CONFIG_SBUS is not set
+# CONFIG_SMP is not set
 CONFIG_BOOT_ELF64=y
 CONFIG_ARC64=y
 CONFIG_COHERENT_IO=y
 CONFIG_PCI=y
 CONFIG_QL_ISP_A64=y
+# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
 
 #
 # CPU selection
@@ -43,7 +44,7 @@
 # CONFIG_PCMCIA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
 CONFIG_BINFMT_ELF=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_BINFMT_ELF32=y
@@ -52,7 +53,9 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
 CONFIG_PCI_NAMES=y
 
 #
@@ -69,8 +72,12 @@
 #
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
 # CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
 
 #
 # Networking options
@@ -149,12 +156,12 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
@@ -180,11 +187,9 @@
 CONFIG_SCSI_QLOGIC_ISP=y
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
 
 #
 # I2O device support
@@ -322,17 +327,13 @@
 # CONFIG_DRM_TDFX is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-
-#
 # File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -342,10 +343,12 @@
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
@@ -353,23 +356,39 @@
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
@@ -382,6 +401,7 @@
 # CONFIG_MAC_PARTITION is not set
 # CONFIG_MSDOS_PARTITION is not set
 CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 CONFIG_KCORE_ELF=y
@@ -392,8 +412,14 @@
 # CONFIG_SOUND is not set
 
 #
+# USB support
+#
+# CONFIG_USB is not set
+
+#
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
+# CONFIG_MIPS_FPE_MODULE is not set
 # CONFIG_REMOTE_DEBUG is not set
-CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MAGIC_SYSRQ is not set
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22
--- v2.3.99-pre8/linux/arch/mips64/defconfig-ip22	Thu May 11 15:30:06 2000
+++ linux/arch/mips64/defconfig-ip22	Mon May 15 10:57:20 2000
@@ -16,6 +16,9 @@
 CONFIG_ARC32=y
 CONFIG_BOARD_SCACHE=y
 CONFIG_ARC_MEMORY=y
+# CONFIG_ISA is not set
+# CONFIG_PCI is not set
+# CONFIG_SBUS is not set
 
 #
 # CPU selection
@@ -32,14 +35,11 @@
 #
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_NET=y
-
-#
-# PCMCIA/CardBus support
-#
+# CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
 CONFIG_BINFMT_ELF=y
 # CONFIG_MIPS32_COMPAT is not set
 # CONFIG_BINFMT_MISC is not set
@@ -53,24 +53,22 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 
 #
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_INITRD is not set
 
 #
 # Networking options
@@ -102,6 +100,7 @@
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
 
 #
 # Telephony Support
@@ -110,6 +109,13 @@
 # CONFIG_PHONE_IXJ is not set
 
 #
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
 # SCSI support
 #
 # CONFIG_SCSI is not set
@@ -118,7 +124,6 @@
 # I2O device support
 #
 # CONFIG_I2O is not set
-# CONFIG_I2O_PCI is not set
 # CONFIG_I2O_BLOCK is not set
 # CONFIG_I2O_LAN is not set
 # CONFIG_I2O_SCSI is not set
@@ -134,6 +139,7 @@
 #
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -158,7 +164,7 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring driver support
+# Token Ring devices
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -241,17 +247,13 @@
 # CONFIG_DRM_TDFX is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-
-#
 # File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -261,10 +263,12 @@
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
@@ -272,23 +276,39 @@
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
@@ -301,6 +321,7 @@
 # Console drivers
 #
 CONFIG_SGI_NEWPORT_CONSOLE=y
+CONFIG_FONT_8x16=y
 CONFIG_KCORE_ELF=y
 
 #
@@ -313,6 +334,11 @@
 #
 # CONFIG_SGI_SERIAL is not set
 CONFIG_SGI_DS1286=y
+
+#
+# USB support
+#
+# CONFIG_USB is not set
 
 #
 # Kernel hacking
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27
--- v2.3.99-pre8/linux/arch/mips64/defconfig-ip27	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/defconfig-ip27	Mon May 15 10:57:20 2000
@@ -14,11 +14,14 @@
 CONFIG_SGI_IP27=y
 # CONFIG_SGI_SN0_N_MODE is not set
 # CONFIG_DISCONTIGMEM is not set
+# CONFIG_SMP is not set
 CONFIG_BOOT_ELF64=y
 CONFIG_ARC64=y
 CONFIG_COHERENT_IO=y
 CONFIG_PCI=y
 CONFIG_QL_ISP_A64=y
+# CONFIG_ISA is not set
+# CONFIG_SBUS is not set
 
 #
 # CPU selection
@@ -37,14 +40,11 @@
 # CONFIG_CPU_LITTLE_ENDIAN is not set
 CONFIG_NET=y
 CONFIG_PCI_NAMES=y
-
-#
-# PCMCIA/CardBus support
-#
+# CONFIG_HOTPLUG is not set
 # CONFIG_PCMCIA is not set
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
+CONFIG_SYSCTL=y
 CONFIG_BINFMT_ELF=y
 CONFIG_MIPS32_COMPAT=y
 CONFIG_BINFMT_ELF32=y
@@ -53,33 +53,31 @@
 #
 # Loadable module support
 #
-# CONFIG_MODULES is not set
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
 CONFIG_PCI_NAMES=y
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_IDE is not set
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-# CONFIG_BLK_DEV_HD_ONLY is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
 
 #
 # Additional Block Devices
 #
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
 # CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_DEV_IDE_MODES is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_INITRD is not set
 
 #
 # Networking options
@@ -111,6 +109,7 @@
 #
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
 
 #
 # Telephony Support
@@ -119,6 +118,13 @@
 # CONFIG_PHONE_IXJ is not set
 
 #
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
 # SCSI support
 #
 CONFIG_SCSI=y
@@ -129,7 +135,6 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 # CONFIG_CHR_DEV_ST is not set
-CONFIG_ST_EXTRA_DEVS=2
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 
@@ -144,18 +149,19 @@
 #
 # SCSI low-level drivers
 #
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
 # CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
@@ -181,11 +187,9 @@
 CONFIG_SCSI_QLOGIC_ISP=y
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
-# CONFIG_SCSI_SEAGATE is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_T128 is not set
 # CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
 
 #
 # I2O device support
@@ -207,6 +211,7 @@
 #
 # CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -221,7 +226,7 @@
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_DEPCA is not set
 # CONFIG_NET_ISA is not set
-# CONFIG_NET_EISA is not set
+# CONFIG_NET_PCI is not set
 # CONFIG_NET_POCKET is not set
 
 #
@@ -240,7 +245,7 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# Token Ring driver support
+# Token Ring devices
 #
 # CONFIG_TR is not set
 # CONFIG_NET_FC is not set
@@ -322,17 +327,13 @@
 # CONFIG_DRM_TDFX is not set
 
 #
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# Filesystems
+# File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -342,6 +343,7 @@
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
@@ -349,6 +351,9 @@
 # CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_QNX4FS_RW is not set
@@ -366,6 +371,7 @@
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 CONFIG_ROOT_NFS=y
 # CONFIG_NFSD is not set
 # CONFIG_NFSD_V3 is not set
@@ -373,12 +379,30 @@
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
 CONFIG_SGI_PARTITION=y
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 CONFIG_KCORE_ELF=y
 
@@ -388,8 +412,14 @@
 # CONFIG_SOUND is not set
 
 #
+# USB support
+#
+# CONFIG_USB is not set
+
+#
 # Kernel hacking
 #
 CONFIG_CROSSCOMPILE=y
+# CONFIG_MIPS_FPE_MODULE is not set
 # CONFIG_REMOTE_DEBUG is not set
-CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MAGIC_SYSRQ is not set
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/Makefile linux/arch/mips64/kernel/Makefile
--- v2.3.99-pre8/linux/arch/mips64/kernel/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/Makefile	Sat May 13 08:30:17 2000
@@ -18,11 +18,15 @@
 OX_OBJS := mips64_ksyms.o
 
 ifdef CONFIG_MIPS32_COMPAT
-O_OBJS += linux32.o scall_o32.o signal32.o
+O_OBJS += linux32.o scall_o32.o signal32.o ioctl32.o
 endif
 
 ifdef CONFIG_BINFMT_ELF32
 O_OBJS += binfmt_elf32.o
+endif
+
+ifdef CONFIG_SMP
+O_OBJS += smp.o
 endif
 
 clean:
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/binfmt_elf32.c linux/arch/mips64/kernel/binfmt_elf32.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/binfmt_elf32.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/binfmt_elf32.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: binfmt_elf32.c,v 1.2 2000/01/17 23:32:46 ralf Exp $
+/* $Id: binfmt_elf32.c,v 1.1 1999/11/24 06:56:13 ralf Exp $
  *
  * Support for 32-bit Linux/MIPS ELF binaries.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/branch.c linux/arch/mips64/kernel/branch.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/branch.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/branch.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: branch.c,v 1.1 1999/12/04 03:59:00 ralf Exp $
+/* $Id: branch.c,v 1.1 1999/10/09 20:55:05 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/entry.S linux/arch/mips64/kernel/entry.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/entry.S	Thu May 11 15:30:06 2000
+++ linux/arch/mips64/kernel/entry.S	Sat May 13 08:30:17 2000
@@ -10,6 +10,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics
  */
 #include <linux/config.h>
+
 #include <asm/asm.h>
 #include <asm/regdef.h>
 #include <asm/mipsregs.h>
@@ -34,10 +35,11 @@
 
 FEXPORT(ret_from_sys_call)
 FEXPORT(ret_from_irq)
-#ifdef CONFIG_SMP
-#error Barffff...
-#else
 		la	t1, softirq_state
+#ifdef CONFIG_SMP
+		lwu	t0, TASK_PROCESSOR($28)
+		dsll	t0, t0, 5
+		daddu	t1, t0
 #endif
 		lw	t0, 0 (t1)
 		lw	t1, 4 (t1)		# unused delay slot
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/head.S linux/arch/mips64/kernel/head.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/head.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/head.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.4 2000/01/25 01:35:05 ralf Exp $
+/* $Id: head.S,v 1.6 2000/03/27 21:05:04 ulfc 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
@@ -20,6 +20,15 @@
 #include <asm/mipsregs.h>
 #include <asm/stackframe.h>
 
+#define ARC64_TWIDDLE_PC \
+#ifdef CONFIG_ARC64 \
+	/* We get launched at a XKPHYS address but the kernel is linked to \
+	   run at a KSEG0 address, so jump there.  */ \
+	la	t0, 1f \
+	jr	t0 \
+1: \
+#endif
+
 	.text
 
 EXPORT(stext)					# used for profiling
@@ -29,13 +38,7 @@
 
 NESTED(kernel_entry, 16, sp)			# kernel entry point
 
-#ifdef CONFIG_ARC64
-	/* We get launched at a XKPHYS address but the kernel is linked to
-	   run at a KSEG0 address, so jump there.  */
-	la	t0, 1f
-	jr	t0
-1:
-#endif
+	ARC64_TWIDDLE_PC
 
 	ori	sp, 0xf				# align stack on 16 byte.
 	xori	sp, 0xf
@@ -47,24 +50,44 @@
 	CLI					# disable interrupts
 
 	mfc0	t0, CP0_STATUS
-	li	t1, ~(ST0_CU1|ST0_CU2|ST0_CU3)
+	/*
+	 * On IP27, I am seeing the TS bit set when the
+	 * kernel is loaded. Maybe because the kernel is
+	 * in ckseg0 and not xkphys? Clear it anyway ...
+	 */
+	li	t1, ~(ST0_TS|ST0_CU1|ST0_CU2|ST0_CU3)
 	and	t0, t1
-	or	t0, (ST0_CU0|ST0_KX|ST0_SX)
-	mtc0	t0, CP0_STATUS
+	or	t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR) # Bogosity: cu0 indicates kernel
+	mtc0	t0, CP0_STATUS			   # thread in copy_thread.
 
 	la	$28, init_task_union		# init current pointer
 	daddiu	t0, $28, KERNEL_STACK_SIZE-32
 	sd	t0, kernelsp
 	dsubu	sp, t0, 4*SZREG			# init stack pointer
-
+	move	t0, $28
+#ifdef CONFIG_SMP
+	mtc0	t0, CP0_WATCHLO
+	dsrl32	t0, t0, 0
+	mtc0	t0, CP0_WATCHHI
+#endif
 	jal	start_kernel
 1:	b	1b				# just in case ...
 	END(kernel_entry)
 
+NESTED(bootstrap, 16, sp)
+	ARC64_TWIDDLE_PC
+	CLI
+	mfc0	t0, CP0_STATUS
+	li	t1, ~(ST0_CU1|ST0_CU2|ST0_CU3)
+	and	t0, t1
+	or	t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR) # Bogosity: cu0 indicates kernel
+	mtc0	t0, CP0_STATUS			   # thread in copy_thread.
+	jal	cboot
+	END(bootstrap)
+
 	__FINIT
 
 	.comm	kernelsp, 8, 8			# current stackpointer
-	.comm	current_pgd, 8, 8		# current page tables
 
 #define PAGE_SIZE	0x1000
 
@@ -81,5 +104,5 @@
 	page	swapper_pg_dir, 1
 	page	invalid_pte_table, 1
 	page	invalid_pmd_table, 1
+	page	empty_bad_page_table, 1
 	page	empty_bad_page
-	page	empty_bad_page_table
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/ioctl32.c linux/arch/mips64/kernel/ioctl32.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/ioctl32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/kernel/ioctl32.c	Sat May 13 08:30:17 2000
@@ -0,0 +1,529 @@
+/* $Id: ioctl32.c,v 1.1 2000/04/05 00:43:25 ulfc Exp $
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ *
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ *
+ * Mostly from the sparc64 ioctl32 implementation.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/vt.h>
+#include <linux/kd.h>
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+
+#define A(__x) ((unsigned long)(__x))
+
+long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+struct timeval32 {
+	int tv_sec;
+	int tv_usec;
+};
+
+#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
+#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
+#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
+#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
+
+static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct timeval32 *up = (struct timeval32 *)arg;
+	struct timeval ktv;
+	mm_segment_t old_fs = get_fs();
+	int err;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
+	set_fs(old_fs);
+	if(!err) {
+		err = put_user(ktv.tv_sec, &up->tv_sec);
+		err |= __put_user(ktv.tv_usec, &up->tv_usec);
+	}
+	return err;
+}
+
+struct ifmap32 {
+	unsigned int mem_start;
+	unsigned int mem_end;
+	unsigned short base_addr;
+	unsigned char irq;
+	unsigned char dma;
+	unsigned char port;
+};
+
+struct ifreq32 {
+#define IFHWADDRLEN     6
+#define IFNAMSIZ        16
+        union {
+                char    ifrn_name[IFNAMSIZ];	/* if name, e.g. "en0" */
+        } ifr_ifrn;
+        union {
+                struct  sockaddr ifru_addr;
+                struct  sockaddr ifru_dstaddr;
+                struct  sockaddr ifru_broadaddr;
+                struct  sockaddr ifru_netmask;
+                struct  sockaddr ifru_hwaddr;
+                short   ifru_flags;
+                int     ifru_ivalue;
+                int     ifru_mtu;
+                struct  ifmap32 ifru_map;
+                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
+		char	ifru_newname[IFNAMSIZ];
+                __kernel_caddr_t32 ifru_data;
+        } ifr_ifru;
+};
+
+struct ifconf32 {
+        int     ifc_len;                        /* size of buffer       */
+        __kernel_caddr_t32  ifcbuf;
+};
+
+static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ireq32 *uir32 = (struct ireq32 *)arg;
+	struct net_device *dev;
+	struct ifreq32 ifr32;
+
+	if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32)))
+		return -EFAULT;
+
+	read_lock(&dev_base_lock);
+	dev = __dev_get_by_index(ifr32.ifr_ifindex);
+	if (!dev) {
+		read_unlock(&dev_base_lock);
+		return -ENODEV;
+	}
+
+	strcpy(ifr32.ifr_name, dev->name);
+	read_unlock(&dev_base_lock);
+
+	if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32)))
+	    return -EFAULT;
+
+	return 0;
+}
+
+static inline int dev_ifconf(unsigned int fd, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct ioconf32 *uifc32 = (struct ioconf32 *)arg;
+	struct ifconf32 ifc32;
+	struct ifconf ifc;
+	struct ifreq32 *ifr32;
+	struct ifreq *ifr;
+	mm_segment_t old_fs;
+	int len;
+	int err;
+
+	if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
+		return -EFAULT;
+
+	if(ifc32.ifcbuf == 0) {
+		ifc32.ifc_len = 0;
+		ifc.ifc_len = 0;
+		ifc.ifc_buf = NULL;
+	} else {
+		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) *
+			sizeof (struct ifreq);
+		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
+		if (!ifc.ifc_buf)
+			return -ENOMEM;
+	}
+	ifr = ifc.ifc_req;
+	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
+	len = ifc32.ifc_len / sizeof (struct ifreq32);
+	while (len--) {
+		if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);	
+	set_fs (old_fs);
+	if (err)
+		goto out;
+
+	ifr = ifc.ifc_req;
+	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
+	len = ifc.ifc_len / sizeof (struct ifreq);
+	ifc32.ifc_len = len * sizeof (struct ifreq32);
+
+	while (len--) {
+		if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+
+	if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
+		err = -EFAULT;
+		goto out;
+	}
+out:
+	if(ifc.ifc_buf != NULL)
+		kfree (ifc.ifc_buf);
+	return err;
+}
+
+static inline int dev_ifsioc(unsigned int fd, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct ifreq32 *uifr = (struct ifreq32 *)arg;
+	struct ifreq ifr;
+	mm_segment_t old_fs;
+	int err;
+	
+	switch (cmd) {
+	case SIOCSIFMAP:
+		err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name));
+		err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
+		err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
+		err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
+		err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
+		err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
+		err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
+		if (err)
+			return -EFAULT;
+		break;
+	default:
+		if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32)))
+			return -EFAULT;
+		break;
+	}
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+	if (!err) {
+		switch (cmd) {
+		case SIOCGIFFLAGS:
+		case SIOCGIFMETRIC:
+		case SIOCGIFMTU:
+		case SIOCGIFMEM:
+		case SIOCGIFHWADDR:
+		case SIOCGIFINDEX:
+		case SIOCGIFADDR:
+		case SIOCGIFBRDADDR:
+		case SIOCGIFDSTADDR:
+		case SIOCGIFNETMASK:
+		case SIOCGIFTXQLEN:
+			if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32)))
+				return -EFAULT;
+			break;
+		case SIOCGIFMAP:
+			err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name));
+			err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
+			err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
+			err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
+			err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
+			err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
+			err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
+			if (err)
+				err = -EFAULT;
+			break;
+		}
+	}
+	return err;
+}
+
+struct rtentry32
+{
+	unsigned int	rt_pad1;
+	struct sockaddr	rt_dst;		/* target address		*/
+	struct sockaddr	rt_gateway;	/* gateway addr (RTF_GATEWAY)	*/
+	struct sockaddr	rt_genmask;	/* target network mask (IP)	*/
+	unsigned short	rt_flags;
+	short		rt_pad2;
+	unsigned int	rt_pad3;
+	unsigned int	rt_pad4;
+	short		rt_metric;	/* +1 for binary compatibility!	*/
+	unsigned int	rt_dev;		/* forcing the device at add	*/
+	unsigned int	rt_mtu;		/* per route MTU/Window 	*/
+#ifndef __KERNEL__
+#define rt_mss	rt_mtu			/* Compatibility :-(            */
+#endif
+	unsigned int	rt_window;	/* Window clamping 		*/
+	unsigned short	rt_irtt;	/* Initial RTT			*/
+};
+
+static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct rtentry32 *ur = (struct rtentry32 *)arg;
+	struct rtentry r;
+	char devname[16];
+	u32 rtdev;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr));
+	ret |= __get_user (r.rt_flags, &(ur->rt_flags));
+	ret |= __get_user (r.rt_metric, &(ur->rt_metric));
+	ret |= __get_user (r.rt_mtu, &(ur->rt_mtu));
+	ret |= __get_user (r.rt_window, &(ur->rt_window));
+	ret |= __get_user (r.rt_irtt, &(ur->rt_irtt));
+	ret |= __get_user (rtdev, &(ur->rt_dev));
+	if (rtdev) {
+		ret |= copy_from_user (devname, (char *)A(rtdev), 15);
+		r.rt_dev = devname; devname[15] = 0;
+	} else
+		r.rt_dev = 0;
+	if (ret)
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, cmd, (long)&r);
+	set_fs (old_fs);
+	return ret;
+}
+
+static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
+	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
+	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
+	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
+	}
+	return sys_ioctl(fd, cmd, arg);
+}
+
+static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+	
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user((unsigned int) val, (u32 *)arg))
+		return -EFAULT;
+	return err;
+}
+
+struct ioctl32_handler {
+	unsigned int cmd;
+	int (*function)(unsigned int, unsigned int, unsigned long);
+};
+
+struct ioctl32_list {
+	struct ioctl32_handler handler;
+	struct ioctl32_list *next;
+};
+
+#define IOCTL32_DEFAULT(cmd)		{ { cmd, (void *) sys_ioctl }, 0 }
+#define IOCTL32_HANDLER(cmd, handler)	{ { cmd, (void *) handler }, 0 }
+
+static struct ioctl32_list ioctl32_handler_table[] = {
+	IOCTL32_DEFAULT(TCGETA),
+	IOCTL32_DEFAULT(TCSETA),
+	IOCTL32_DEFAULT(TCSETAW),
+	IOCTL32_DEFAULT(TCSETAF),
+	IOCTL32_DEFAULT(TCSBRK),
+	IOCTL32_DEFAULT(TCXONC),
+	IOCTL32_DEFAULT(TCFLSH),
+	IOCTL32_DEFAULT(TCGETS),
+	IOCTL32_DEFAULT(TCSETS),
+	IOCTL32_DEFAULT(TCSETSW),
+	IOCTL32_DEFAULT(TCSETSF),
+	IOCTL32_DEFAULT(TIOCLINUX),
+
+	IOCTL32_DEFAULT(TIOCGETD),
+	IOCTL32_DEFAULT(TIOCSETD),
+	IOCTL32_DEFAULT(TIOCEXCL),
+	IOCTL32_DEFAULT(TIOCNXCL),
+	IOCTL32_DEFAULT(TIOCCONS),
+	IOCTL32_DEFAULT(TIOCGSOFTCAR),
+	IOCTL32_DEFAULT(TIOCSSOFTCAR),
+	IOCTL32_DEFAULT(TIOCSWINSZ),
+	IOCTL32_DEFAULT(TIOCGWINSZ),
+	IOCTL32_DEFAULT(TIOCMGET),
+	IOCTL32_DEFAULT(TIOCMBIC),
+	IOCTL32_DEFAULT(TIOCMBIS),
+	IOCTL32_DEFAULT(TIOCMSET),
+	IOCTL32_DEFAULT(TIOCPKT),
+	IOCTL32_DEFAULT(TIOCNOTTY),
+	IOCTL32_DEFAULT(TIOCSTI),
+	IOCTL32_DEFAULT(TIOCOUTQ),
+	IOCTL32_DEFAULT(TIOCSPGRP),
+	IOCTL32_DEFAULT(TIOCGPGRP),
+	IOCTL32_DEFAULT(TIOCSCTTY),
+	IOCTL32_DEFAULT(TIOCGPTN),
+	IOCTL32_DEFAULT(TIOCSPTLCK),
+	IOCTL32_DEFAULT(TIOCGSERIAL),
+	IOCTL32_DEFAULT(TIOCSSERIAL),
+	IOCTL32_DEFAULT(TIOCSERGETLSR),
+
+	IOCTL32_DEFAULT(FIOCLEX),
+	IOCTL32_DEFAULT(FIONCLEX),
+	IOCTL32_DEFAULT(FIOASYNC),
+	IOCTL32_DEFAULT(FIONBIO),
+	IOCTL32_DEFAULT(FIONREAD),
+
+	IOCTL32_DEFAULT(PIO_FONT),
+	IOCTL32_DEFAULT(GIO_FONT),
+	IOCTL32_DEFAULT(KDSIGACCEPT),
+	IOCTL32_DEFAULT(KDGETKEYCODE),
+	IOCTL32_DEFAULT(KDSETKEYCODE),
+	IOCTL32_DEFAULT(KIOCSOUND),
+	IOCTL32_DEFAULT(KDMKTONE),
+	IOCTL32_DEFAULT(KDGKBTYPE),
+	IOCTL32_DEFAULT(KDSETMODE),
+	IOCTL32_DEFAULT(KDGETMODE),
+	IOCTL32_DEFAULT(KDSKBMODE),
+	IOCTL32_DEFAULT(KDGKBMODE),
+	IOCTL32_DEFAULT(KDSKBMETA),
+	IOCTL32_DEFAULT(KDGKBMETA),
+	IOCTL32_DEFAULT(KDGKBENT),
+	IOCTL32_DEFAULT(KDSKBENT),
+	IOCTL32_DEFAULT(KDGKBSENT),
+	IOCTL32_DEFAULT(KDSKBSENT),
+	IOCTL32_DEFAULT(KDGKBDIACR),
+	IOCTL32_DEFAULT(KDSKBDIACR),
+	IOCTL32_DEFAULT(KDGKBLED),
+	IOCTL32_DEFAULT(KDSKBLED),
+	IOCTL32_DEFAULT(KDGETLED),
+	IOCTL32_DEFAULT(KDSETLED),
+	IOCTL32_DEFAULT(GIO_SCRNMAP),
+	IOCTL32_DEFAULT(PIO_SCRNMAP),
+	IOCTL32_DEFAULT(GIO_UNISCRNMAP),
+	IOCTL32_DEFAULT(PIO_UNISCRNMAP),
+	IOCTL32_DEFAULT(PIO_FONTRESET),
+	IOCTL32_DEFAULT(PIO_UNIMAPCLR),
+
+	IOCTL32_DEFAULT(VT_SETMODE),
+	IOCTL32_DEFAULT(VT_GETMODE),
+	IOCTL32_DEFAULT(VT_GETSTATE),
+	IOCTL32_DEFAULT(VT_OPENQRY),
+	IOCTL32_DEFAULT(VT_ACTIVATE),
+	IOCTL32_DEFAULT(VT_WAITACTIVE),
+	IOCTL32_DEFAULT(VT_RELDISP),
+	IOCTL32_DEFAULT(VT_DISALLOCATE),
+	IOCTL32_DEFAULT(VT_RESIZE),
+	IOCTL32_DEFAULT(VT_RESIZEX),
+	IOCTL32_DEFAULT(VT_LOCKSWITCH),
+	IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
+
+	IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
+	IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
+	IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
+	IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
+
+	IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
+	IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
+	IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
+	IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
+
+	IOCTL32_HANDLER(BLKGETSIZE, w_long)
+
+};
+
+#define NR_IOCTL32_HANDLERS	(sizeof(ioctl32_handler_table) /	\
+				 sizeof(ioctl32_handler_table[0]))
+
+static struct ioctl32_list *ioctl32_hash_table[1024];
+
+static inline int ioctl32_hash(unsigned int cmd)
+{
+	return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
+}
+
+int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned int arg)
+{
+	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+	struct file *filp;
+	struct ioctl32_list *l;
+	int error;
+
+	l = ioctl32_hash_table[ioctl32_hash(cmd)];
+
+	error = -EBADF;
+
+	filp = fget(fd);
+	if (!filp)
+		return error;
+
+	if (!filp->f_op || !filp->f_op->ioctl) {
+		error = sys_ioctl (fd, cmd, arg);
+		goto out;
+	}
+
+	while (l && l->handler.cmd != cmd)
+		l = l->next;
+
+	if (l) {
+		handler = (void *)l->handler.function;
+		error = handler(fd, cmd, arg, filp);
+	} else {
+		error = -EINVAL;
+		printk("unknown ioctl: %08x\n", cmd);
+	}
+out:
+	fput(filp);
+	return error;
+}
+
+static void ioctl32_insert(struct ioctl32_list *entry)
+{
+	int hash = ioctl32_hash(entry->handler.cmd);
+	if (!ioctl32_hash_table[hash])
+		ioctl32_hash_table[hash] = entry;
+	else {
+		struct ioctl32_list *l;
+		l = ioctl32_hash_table[hash];
+		while (l->next)
+			l = l->next;
+		l->next = entry;
+		entry->next = 0;
+	}
+}
+
+static int __init init_ioctl32(void)
+{
+	int i;
+	for (i = 0; i < NR_IOCTL32_HANDLERS; i++)
+		ioctl32_insert(&ioctl32_handler_table[i]);
+	return 0;
+}
+
+__initcall(init_ioctl32);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/linux32.c linux/arch/mips64/kernel/linux32.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/linux32.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/linux32.c	Sat May 13 08:30:17 2000
@@ -1,10 +1,1309 @@
-int sys32_newstat(void) {return 0;}
-int sys32_newlstat(void) {return 0;}
-int sys32_newfstat(void) {return 0;}
-int sys_mmap2(void) {return 0;}
-int sys_truncate64(void) {return 0;}
-int sys_ftruncate64(void) {return 0;}
-int sys_stat64(void) {return 0;}
-int sys_lstat64(void) {return 0;}
-int sys_fstat64(void) {return 0;}
+/* $Id: linux32.c,v 1.14 2000/03/23 00:30:53 ulfc Exp $
+ * 
+ * Conversion between 32-bit and 64-bit native system calls.
+ *
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com)
+ * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)
+ */
 
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/smp_lock.h>
+#include <linux/highuid.h>
+#include <linux/dirent.h>
+#include <linux/resource.h>
+#include <linux/highmem.h>
+#include <linux/time.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+
+#include <asm/uaccess.h>
+#include <asm/mman.h>
+
+
+#define A(__x) ((unsigned long)(__x))
+
+#if 1
+static inline int
+putstat(struct stat32 *ubuf, struct stat *kbuf)
+{
+	int err;
+	
+	err = put_user (kbuf->st_dev, &ubuf->st_dev);
+	err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
+	err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
+	err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
+	err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
+	err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
+	err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
+	err |= __put_user (kbuf->st_size, &ubuf->st_size);
+	err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
+	err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
+	err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
+	err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
+	err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+	return err;
+}
+
+extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+
+asmlinkage int
+sys32_newstat(char * filename, struct stat32 *statbuf)
+{
+	int ret;
+	struct stat s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newstat(filename, &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
+
+asmlinkage int
+sys32_newlstat(char * filename, struct stat32 *statbuf)
+{
+	int ret;
+	struct stat s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newlstat(filename, &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+asmlinkage int
+sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
+{
+	int ret;
+	struct stat s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_newfstat(fd, &s);
+	set_fs (old_fs);
+	if (putstat (statbuf, &s))
+		return -EFAULT;
+	return ret;
+}
+#else
+/*
+ * Revalidate the inode. This is required for proper NFS attribute caching.
+ */
+static __inline__ int
+do_revalidate(struct dentry *dentry)
+{
+	struct inode * inode = dentry->d_inode;
+	if (inode->i_op && inode->i_op->revalidate)
+		return inode->i_op->revalidate(dentry);
+	return 0;
+}
+
+static int cp_new_stat32(struct inode * inode, struct stat32 * statbuf)
+{
+	struct stat32 tmp;
+	unsigned int blocks, indirect;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
+	tmp.st_ino = inode->i_ino;
+	tmp.st_mode = inode->i_mode;
+	tmp.st_nlink = inode->i_nlink;
+	SET_STAT_UID(tmp, inode->i_uid);
+	SET_STAT_GID(tmp, inode->i_gid);
+	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+	tmp.st_size = inode->i_size;
+	tmp.st_atime = inode->i_atime;
+	tmp.st_mtime = inode->i_mtime;
+	tmp.st_ctime = inode->i_ctime;
+/*
+ * st_blocks and st_blksize are approximated with a simple algorithm if
+ * they aren't supported directly by the filesystem. The minix and msdos
+ * filesystems don't keep track of blocks, so they would either have to
+ * be counted explicitly (by delving into the file itself), or by using
+ * this simple algorithm to get a reasonable (although not 100% accurate)
+ * value.
+ */
+
+/*
+ * Use minix fs values for the number of direct and indirect blocks.  The
+ * count is now exact for the minix fs except that it counts zero blocks.
+ * Everything is in units of BLOCK_SIZE until the assignment to
+ * tmp.st_blksize.
+ */
+#define D_B   7
+#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
+
+	if (!inode->i_blksize) {
+		blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+		if (blocks > D_B) {
+			indirect = (blocks - D_B + I_B - 1) / I_B;
+			blocks += indirect;
+			if (indirect > 1) {
+				indirect = (indirect - 1 + I_B - 1) / I_B;
+				blocks += indirect;
+				if (indirect > 1)
+					blocks++;
+			}
+		}
+		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
+		tmp.st_blksize = BLOCK_SIZE;
+	} else {
+		tmp.st_blocks = inode->i_blocks;
+		tmp.st_blksize = inode->i_blksize;
+	}
+	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
+{
+	struct dentry * dentry;
+	int error;
+
+	lock_kernel();
+	dentry = namei(filename);
+
+	error = PTR_ERR(dentry);
+	if (!IS_ERR(dentry)) {
+		error = do_revalidate(dentry);
+		if (!error)
+			error = cp_new_stat32(dentry->d_inode, statbuf);
+
+		dput(dentry);
+	}
+	unlock_kernel();
+	return error;
+}
+asmlinkage int sys32_newlstat(char *filename, struct stat32 * statbuf)
+{
+	struct dentry * dentry;
+	int error;
+
+	lock_kernel();
+	dentry = lnamei(filename);
+
+	error = PTR_ERR(dentry);
+	if (!IS_ERR(dentry)) {
+		error = do_revalidate(dentry);
+		if (!error)
+			error = cp_new_stat32(dentry->d_inode, statbuf);
+
+		dput(dentry);
+	}
+	unlock_kernel();
+	return error;
+}
+
+asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 * statbuf)
+{
+	struct file * f;
+	int err = -EBADF;
+
+	lock_kernel();
+	f = fget(fd);
+	if (f) {
+		struct dentry * dentry = f->f_dentry;
+
+		err = do_revalidate(dentry);
+		if (!err)
+			err = cp_new_stat32(dentry->d_inode, statbuf);
+		fput(f);
+	}
+	unlock_kernel();
+	return err;
+}
+#endif
+asmlinkage int sys_mmap2(void) {return 0;}
+
+asmlinkage long sys_truncate(const char * path, unsigned long length);
+
+asmlinkage int sys_truncate64(const char *path, unsigned int high,
+			      unsigned int low)
+{
+	if ((int)high < 0)
+		return -EINVAL;
+	return sys_truncate(path, (high << 32) | low);
+}
+
+asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
+
+asmlinkage int sys_ftruncate64(unsigned int fd, unsigned int high,
+			       unsigned int low)
+{
+	if ((int)high < 0)
+		return -EINVAL;
+	return sys_ftruncate(fd, (high << 32) | low);
+}
+
+asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+
+asmlinkage int sys_stat64(char * filename, struct stat *statbuf)
+{
+	return sys_newstat(filename, statbuf);
+}
+
+asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
+
+asmlinkage int sys_lstat64(char * filename, struct stat *statbuf)
+{
+	return sys_newlstat(filename, statbuf);
+}
+
+asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+asmlinkage int sys_fstat64(unsigned int fd, struct stat *statbuf)
+{
+	return sys_newfstat(fd, statbuf);
+}
+
+#if 0
+/*
+ * count32() counts the number of arguments/envelopes
+ */
+static int count32(u32 * argv, int max)
+{
+	int i = 0;
+
+	if (argv != NULL) {
+		for (;;) {
+			u32 p;
+			/* egcs is stupid */
+			if (!access_ok(VERIFY_READ, argv, sizeof (u32)))
+				return -EFAULT;
+			__get_user(p,argv);
+			if (!p)
+				break;
+			argv++;
+			if(++i > max)
+				return -E2BIG;
+		}
+	}
+	return i;
+}
+
+
+/*
+ * 'copy_strings32()' copies argument/envelope strings from user
+ * memory to free pages in kernel mem. These are in a format ready
+ * to be put directly into the top of new user memory.
+ */
+int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm) 
+{
+	while (argc-- > 0) {
+		u32 str;
+		int len;
+		unsigned long pos;
+
+		if (get_user(str, argv+argc) || !str || !(len = strnlen_user((char *)A(str), bprm->p))) 
+			return -EFAULT;
+		if (bprm->p < len) 
+			return -E2BIG; 
+
+		bprm->p -= len;
+		/* XXX: add architecture specific overflow check here. */ 
+
+		pos = bprm->p;
+		while (len > 0) {
+			char *kaddr;
+			int i, new, err;
+			struct page *page;
+			int offset, bytes_to_copy;
+
+			offset = pos % PAGE_SIZE;
+			i = pos/PAGE_SIZE;
+			page = bprm->page[i];
+			new = 0;
+			if (!page) {
+				page = alloc_page(GFP_HIGHUSER);
+				bprm->page[i] = page;
+				if (!page)
+					return -ENOMEM;
+				new = 1;
+			}
+			kaddr = (char *)kmap(page);
+
+			if (new && offset)
+				memset(kaddr, 0, offset);
+			bytes_to_copy = PAGE_SIZE - offset;
+			if (bytes_to_copy > len) {
+				bytes_to_copy = len;
+				if (new)
+					memset(kaddr+offset+len, 0, PAGE_SIZE-offset-len);
+			}
+			err = copy_from_user(kaddr + offset, (char *)A(str), bytes_to_copy);
+			flush_page_to_ram(page);
+			kunmap(page);
+
+			if (err)
+				return -EFAULT; 
+
+			pos += bytes_to_copy;
+			str += bytes_to_copy;
+			len -= bytes_to_copy;
+		}
+	}
+	return 0;
+}
+
+
+/*
+ * sys_execve32() executes a new program.
+ */
+int do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
+{
+	struct linux_binprm bprm;
+	struct dentry * dentry;
+	int retval;
+	int i;
+
+	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); 
+
+	dentry = open_namei(filename, 0, 0);
+	retval = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		return retval;
+
+	bprm.dentry = dentry;
+	bprm.filename = filename;
+	bprm.sh_bang = 0;
+	bprm.loader = 0;
+	bprm.exec = 0;
+	if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
+		dput(dentry);
+		return bprm.argc;
+	}
+
+	if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
+		dput(dentry);
+		return bprm.envc;
+	}
+
+	retval = prepare_binprm(&bprm);
+	if (retval < 0) 
+		goto out; 
+
+	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+	if (retval < 0) 
+		goto out; 
+
+	bprm.exec = bprm.p;
+	retval = copy_strings32(bprm.envc, envp, &bprm);
+	if (retval < 0) 
+		goto out; 
+
+	retval = copy_strings32(bprm.argc, argv, &bprm);
+	if (retval < 0) 
+		goto out; 
+
+	retval = search_binary_handler(&bprm,regs);
+	if (retval >= 0)
+		/* execve success */
+		return retval;
+
+out:
+	/* Something went wrong, return the inode and free the argument pages*/
+	if (bprm.dentry)
+		dput(bprm.dentry);
+
+	/* Assumes that free_page() can take a NULL argument. */ 
+	/* I hope this is ok for all architectures */ 
+	for (i = 0 ; i < MAX_ARG_PAGES ; i++)
+		if (bprm.page[i])
+			__free_page(bprm.page[i]);
+
+	return retval;
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys32_execve(abi64_no_regargs, struct pt_regs regs)
+{
+	int error;
+	char * filename;
+
+	filename = getname((char *) (long)regs.regs[4]);
+	printk("Executing: %s\n", filename);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve32(filename, (u32 *) (long)regs.regs[5],
+	                  (u32 *) (long)regs.regs[6], &regs);
+	putname(filename);
+
+out:
+	return error;
+}
+#else
+static int
+nargs(unsigned int arg, char **ap)
+{
+	char *ptr;
+	int n;
+
+	n = 0;
+	do {
+		/* egcs is stupid */
+		if (!access_ok(VERIFY_READ, arg, sizeof (unsigned int)))
+			return -EFAULT;
+		__get_user((long)ptr,(int *)A(arg));
+		if (ap)
+			*ap++ = ptr;
+		arg += sizeof(unsigned int);
+		n++;
+	} while (ptr);
+	return(n - 1);
+}
+
+asmlinkage int 
+sys32_execve(abi64_no_regargs, struct pt_regs regs)
+{
+	extern asmlinkage int sys_execve(abi64_no_regargs, struct pt_regs regs);
+	extern asmlinkage long sys_munmap(unsigned long addr, size_t len);
+	unsigned int argv = (unsigned int)regs.regs[5];
+	unsigned int envp = (unsigned int)regs.regs[6];
+	char **av, **ae;
+	int na, ne, r, len;
+	char * filename;
+
+	na = nargs(argv, NULL);
+	ne = nargs(envp, NULL);
+	len = (na + ne + 2) * sizeof(*av);
+	/*
+	 *  kmalloc won't work because the `sys_exec' code will attempt
+	 *  to do a `get_user' on the arg list and `get_user' will fail
+	 *  on a kernel address (simplifies `get_user').  Instead we
+	 *  do an mmap to get a user address.  Note that since a successful
+	 *  `execve' frees all current memory we only have to do an
+	 *  `munmap' if the `execve' failes.
+	 */
+	down(&current->mm->mmap_sem);
+	lock_kernel();
+
+	av = (char **) do_mmap_pgoff(0, 0, len, PROT_READ | PROT_WRITE,
+				     MAP_PRIVATE | MAP_ANONYMOUS, 0);
+
+	unlock_kernel();
+	up(&current->mm->mmap_sem);
+
+	if (IS_ERR(av))
+		return((long) av);
+	ae = av + na + 1;
+	av[na] = (char *)0;
+	ae[ne] = (char *)0;
+	(void)nargs(argv, av);
+	(void)nargs(envp, ae);
+	filename = getname((char *) (long)regs.regs[4]);
+	r = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return(r);
+
+	r = do_execve(filename, av, ae, &regs);
+	putname(filename);
+	if (IS_ERR(r))
+		sys_munmap((unsigned long)av, len);
+	return(r);
+}
+#endif
+
+struct dirent32 {
+	unsigned int	d_ino;
+	unsigned int	d_off;
+	unsigned short	d_reclen;
+	char		d_name[NAME_MAX + 1];
+};
+
+static void
+xlate_dirent(void *dirent64, void *dirent32, long n)
+{
+	long off;
+	struct dirent *dirp;
+	struct dirent32 *dirp32;
+
+	off = 0;
+	while (off < n) {
+		dirp = (struct dirent *)(dirent64 + off);
+		dirp32 = (struct dirent32 *)(dirent32 + off);
+		off += dirp->d_reclen;
+		dirp32->d_ino = dirp->d_ino;
+		dirp32->d_off = (unsigned int)dirp->d_off;
+		dirp32->d_reclen = dirp->d_reclen;
+		strncpy(dirp32->d_name, dirp->d_name, dirp->d_reclen - ((3 * 4) + 2));
+	}
+	return;
+}
+
+asmlinkage long sys_getdents(unsigned int fd, void * dirent, unsigned int count);
+
+asmlinkage long
+sys32_getdents(unsigned int fd, void * dirent32, unsigned int count)
+{
+	long n;
+	void *dirent64;
+
+	dirent64 = (void *)((unsigned long)(dirent32 + (sizeof(long) - 1)) & ~(sizeof(long) - 1));
+	if ((n = sys_getdents(fd, dirent64, count - (dirent64 - dirent32))) < 0)
+		return(n);
+	xlate_dirent(dirent64, dirent32, n);
+	return(n);
+}
+
+asmlinkage int old_readdir(unsigned int fd, void * dirent, unsigned int count);
+
+asmlinkage int
+sys32_readdir(unsigned int fd, void * dirent32, unsigned int count)
+{
+	int n;
+	struct dirent dirent64;
+
+	if ((n = old_readdir(fd, &dirent64, count)) < 0)
+		return(n);
+	xlate_dirent(&dirent64, dirent32, dirent64.d_reclen);
+	return(n);
+}
+
+struct timeval32
+{
+    int tv_sec, tv_usec;
+};
+
+struct itimerval32
+{
+    struct timeval32 it_interval;
+    struct timeval32 it_value;
+};
+
+struct rusage32 {
+        struct timeval32 ru_utime;
+        struct timeval32 ru_stime;
+        int    ru_maxrss;
+        int    ru_ixrss;
+        int    ru_idrss;
+        int    ru_isrss;
+        int    ru_minflt;
+        int    ru_majflt;
+        int    ru_nswap;
+        int    ru_inblock;
+        int    ru_oublock;
+        int    ru_msgsnd; 
+        int    ru_msgrcv; 
+        int    ru_nsignals;
+        int    ru_nvcsw;
+        int    ru_nivcsw;
+};
+
+static int
+put_rusage (struct rusage32 *ru, struct rusage *r)
+{
+	int err;
+	
+	err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
+	err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
+	err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
+	err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
+	err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
+	err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
+	err |= __put_user (r->ru_idrss, &ru->ru_idrss);
+	err |= __put_user (r->ru_isrss, &ru->ru_isrss);
+	err |= __put_user (r->ru_minflt, &ru->ru_minflt);
+	err |= __put_user (r->ru_majflt, &ru->ru_majflt);
+	err |= __put_user (r->ru_nswap, &ru->ru_nswap);
+	err |= __put_user (r->ru_inblock, &ru->ru_inblock);
+	err |= __put_user (r->ru_oublock, &ru->ru_oublock);
+	err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
+	err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
+	err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
+	err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
+	err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
+	return err;
+}
+
+extern asmlinkage int sys_wait4(pid_t pid, unsigned int * stat_addr,
+				int options, struct rusage * ru);
+
+asmlinkage int
+sys32_wait4(__kernel_pid_t32 pid, unsigned int * stat_addr, int options,
+	    struct rusage32 * ru)
+{
+	if (!ru)
+		return sys_wait4(pid, stat_addr, options, NULL);
+	else {
+		struct rusage r;
+		int ret;
+		unsigned int status;
+		mm_segment_t old_fs = get_fs();
+	
+		set_fs(KERNEL_DS);	
+		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
+		set_fs(old_fs);
+		if (put_rusage (ru, &r)) return -EFAULT;
+		if (stat_addr && put_user (status, stat_addr))
+			return -EFAULT;
+		return ret;
+	}
+}
+
+asmlinkage int
+sys32_waitpid(__kernel_pid_t32 pid, unsigned int *stat_addr, int options)
+{
+	return sys32_wait4(pid, stat_addr, options, NULL);
+}
+
+#define RLIM_INFINITY32	0x7fffffff
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+
+struct rlimit32 {
+	int	rlim_cur;
+	int	rlim_max;
+};
+
+extern asmlinkage int sys_old_getrlimit(unsigned int resource, struct rlimit *rlim);
+
+asmlinkage int
+sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit r;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_old_getrlimit(resource, &r);
+	set_fs (old_fs);
+	if (!ret) {
+		ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
+		ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
+	}
+	return ret;
+}
+
+extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
+
+asmlinkage int
+sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit r;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+
+	if (resource >= RLIM_NLIMITS) return -EINVAL;	
+	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+	    __get_user (r.rlim_max, &rlim->rlim_max))
+		return -EFAULT;
+	if (r.rlim_cur == RLIM_INFINITY32)
+		r.rlim_cur = RLIM_INFINITY;
+	if (r.rlim_max == RLIM_INFINITY32)
+		r.rlim_max = RLIM_INFINITY;
+	set_fs (KERNEL_DS);
+	ret = sys_setrlimit(resource, &r);
+	set_fs (old_fs);
+	return ret;
+}
+
+struct statfs32 {
+	int	f_type;
+	int	f_bsize;
+	int	f_frsize;
+	int	f_blocks;
+	int	f_bfree;
+	int	f_files;
+	int	f_ffree;
+	int	f_bavail;
+	__kernel_fsid_t32	f_fsid;
+	int	f_namelen;
+	int	f_spare[6];
+};
+
+static inline int
+put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
+{
+	int err;
+	
+	err = put_user (kbuf->f_type, &ubuf->f_type);
+	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
+	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
+	err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
+	err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
+	err |= __put_user (kbuf->f_files, &ubuf->f_files);
+	err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
+	err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
+	err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
+	err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
+	return err;
+}
+
+extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
+
+asmlinkage int
+sys32_statfs(const char * path, struct statfs32 *buf)
+{
+	int ret;
+	struct statfs s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_statfs((const char *)path, &s);
+	set_fs (old_fs);
+	if (put_statfs(buf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
+
+asmlinkage int
+sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
+{
+	int ret;
+	struct statfs s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_fstatfs(fd, &s);
+	set_fs (old_fs);
+	if (put_statfs(buf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int
+sys_getrusage(int who, struct rusage *ru);
+
+asmlinkage int
+sys32_getrusage(int who, struct rusage32 *ru)
+{
+	struct rusage r;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_getrusage(who, &r);
+	set_fs (old_fs);
+	if (put_rusage (ru, &r)) return -EFAULT;
+	return ret;
+}
+
+static inline long
+get_tv32(struct timeval *o, struct timeval32 *i)
+{
+	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
+		(__get_user(o->tv_sec, &i->tv_sec) |
+		 __get_user(o->tv_usec, &i->tv_usec)));
+	return ENOSYS;
+}
+
+static inline long
+get_it32(struct itimerval *o, struct itimerval32 *i)
+{
+	return (!access_ok(VERIFY_READ, i, sizeof(*i)) ||
+		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
+		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
+		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
+		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
+	return ENOSYS;
+}
+
+static inline long
+put_tv32(struct timeval32 *o, struct timeval *i)
+{
+	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
+		(__put_user(i->tv_sec, &o->tv_sec) |
+		 __put_user(i->tv_usec, &o->tv_usec)));
+}
+
+static inline long
+put_it32(struct itimerval32 *o, struct itimerval *i)
+{
+	return (!access_ok(VERIFY_WRITE, i, sizeof(*i)) ||
+		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
+		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
+		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
+		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
+	return ENOSYS;
+}
+
+extern int do_getitimer(int which, struct itimerval *value);
+
+asmlinkage int
+sys32_getitimer(int which, struct itimerval32 *it)
+{
+	struct itimerval kit;
+	int error;
+
+	error = do_getitimer(which, &kit);
+	if (!error && put_it32(it, &kit))
+		error = -EFAULT;
+
+	return error;
+}
+
+extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+
+
+asmlinkage int
+sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
+{
+	struct itimerval kin, kout;
+	int error;
+
+	if (in) {
+		if (get_it32(&kin, in))
+			return -EFAULT;
+	} else
+		memset(&kin, 0, sizeof(kin));
+
+	error = do_setitimer(which, &kin, out ? &kout : NULL);
+	if (error || !out)
+		return error;
+	if (put_it32(out, &kout))
+		return -EFAULT;
+
+	return 0;
+
+}
+asmlinkage unsigned long 
+sys32_alarm(unsigned int seconds)
+{
+	struct itimerval it_new, it_old;
+	unsigned int oldalarm;
+
+	it_new.it_interval.tv_sec = it_new.it_interval.tv_usec = 0;
+	it_new.it_value.tv_sec = seconds;
+	it_new.it_value.tv_usec = 0;
+	do_setitimer(ITIMER_REAL, &it_new, &it_old);
+	oldalarm = it_old.it_value.tv_sec;
+	/* ehhh.. We can't return 0 if we have an alarm pending.. */
+	/* And we'd better return too much than too little anyway */
+	if (it_old.it_value.tv_usec)
+		oldalarm++;
+	return oldalarm;
+}
+
+/* Translations due to time_t size differences.  Which affects all
+   sorts of things, like timeval and itimerval.  */
+
+
+extern struct timezone sys_tz;
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+
+asmlinkage int
+sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	if (tv) {
+		struct timeval ktv;
+		do_gettimeofday(&ktv);
+		if (put_tv32(tv, &ktv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+asmlinkage int
+sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	struct timeval ktv;
+	struct timezone ktz;
+
+ 	if (tv) {
+		if (get_tv32(&ktv, tv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_from_user(&ktz, tz, sizeof(ktz)))
+			return -EFAULT;
+	}
+
+	return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
+}
+
+extern asmlinkage long sys_llseek(unsigned int fd, unsigned long offset_high,
+			          unsigned long offset_low, loff_t * result,
+			          unsigned int origin);
+
+extern asmlinkage int sys32_llseek(unsigned int fd, unsigned int offset_high,
+			           unsigned int offset_low, loff_t * result,
+			           unsigned int origin)
+{
+	return sys_llseek(fd, offset_high, offset_low, result, origin);
+}
+
+struct iovec32 { unsigned int iov_base; int iov_len; };
+
+typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
+
+static long
+do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
+		  u32 count)
+{
+	unsigned long tot_len;
+	struct iovec iovstack[UIO_FASTIOV];
+	struct iovec *iov=iovstack, *ivp;
+	struct inode *inode;
+	long retval, i;
+	IO_fn_t fn;
+
+	/* First get the "struct iovec" from user memory and
+	 * verify all the pointers
+	 */
+	if (!count)
+		return 0;
+	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+		return -EFAULT;
+	if (count > UIO_MAXIOV)
+		return -EINVAL;
+	if (count > UIO_FASTIOV) {
+		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
+		if (!iov)
+			return -ENOMEM;
+	}
+
+	tot_len = 0;
+	i = count;
+	ivp = iov;
+	while(i > 0) {
+		u32 len;
+		u32 buf;
+
+		__get_user(len, &vector->iov_len);
+		__get_user(buf, &vector->iov_base);
+		tot_len += len;
+		ivp->iov_base = (void *)A(buf);
+		ivp->iov_len = (__kernel_size_t) len;
+		vector++;
+		ivp++;
+		i--;
+	}
+
+	inode = file->f_dentry->d_inode;
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	retval = locks_verify_area((type == VERIFY_WRITE
+				    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
+				   inode, file, file->f_pos, tot_len);
+	if (retval) {
+		if (iov != iovstack)
+			kfree(iov);
+		return retval;
+	}
+
+	/* Then do the actual IO.  Note that sockets need to be handled
+	 * specially as they have atomicity guarantees and can handle
+	 * iovec's natively
+	 */
+	if (inode->i_sock) {
+		int err;
+		err = sock_readv_writev(type, inode, file, iov, count, tot_len);
+		if (iov != iovstack)
+			kfree(iov);
+		return err;
+	}
+
+	if (!file->f_op) {
+		if (iov != iovstack)
+			kfree(iov);
+		return -EINVAL;
+	}
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	fn = file->f_op->read;
+	if (type == VERIFY_READ)
+		fn = (IO_fn_t) file->f_op->write;		
+	ivp = iov;
+	while (count > 0) {
+		void * base;
+		int len, nr;
+
+		base = ivp->iov_base;
+		len = ivp->iov_len;
+		ivp++;
+		count--;
+		nr = fn(file, base, len, &file->f_pos);
+		if (nr < 0) {
+			if (retval)
+				break;
+			retval = nr;
+			break;
+		}
+		retval += nr;
+		if (nr != len)
+			break;
+	}
+	if (iov != iovstack)
+		kfree(iov);
+	return retval;
+}
+
+asmlinkage long
+sys32_readv(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	long ret = -EBADF;
+
+	lock_kernel();
+	file = fget(fd);
+	if(!file)
+		goto bad_file;
+
+	if(!(file->f_mode & 1))
+		goto out;
+
+	ret = do_readv_writev32(VERIFY_WRITE, file,
+				vector, count);
+out:
+	fput(file);
+bad_file:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage long
+sys32_writev(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	int ret = -EBADF;
+
+	lock_kernel();
+	file = fget(fd);
+	if(!file)
+		goto bad_file;
+
+	if(!(file->f_mode & 2))
+		goto out;
+
+	ret = do_readv_writev32(VERIFY_READ, file,
+				vector, count);
+out:
+	fput(file);
+bad_file:
+	unlock_kernel();
+	return ret;
+}
+
+/*
+ * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+ */
+
+static inline int
+get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
+{
+#ifdef __MIPSEB__
+	if (ufdset) {
+		unsigned long odd;
+
+		if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
+			return -EFAULT;
+
+		odd = n & 1UL;
+		n &= ~1UL;
+		while (n) {
+			unsigned long h, l;
+			__get_user(l, ufdset);
+			__get_user(h, ufdset+1);
+			ufdset += 2;
+			*fdset++ = h << 32 | l;
+			n -= 2;
+		}
+		if (odd)
+			__get_user(*fdset, ufdset);
+	} else {
+		/* Tricky, must clear full unsigned long in the
+		 * kernel fdset at the end, this makes sure that
+		 * actually happens.
+		 */
+		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
+	}
+	return 0;
+#else
+	<<Bomb - little endian support must define this>>
+#endif
+}
+
+static inline void
+set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+	unsigned long odd;
+
+	if (!ufdset)
+		return;
+
+	odd = n & 1UL;
+	n &= ~1UL;
+	while (n) {
+		unsigned long h, l;
+		l = *fdset++;
+		h = l >> 32;
+		__put_user(l, ufdset);
+		__put_user(h, ufdset+1);
+		ufdset += 2;
+		n -= 2;
+	}
+	if (odd)
+		__put_user(*fdset, ufdset);
+}
+
+/*
+ * We can actually return ERESTARTSYS instead of EINTR, but I'd
+ * like to be certain this leads to no problems. So I return
+ * EINTR just for safety.
+ *
+ * Update: ERESTARTSYS breaks at least the xview clock binary, so
+ * I'm trying ERESTARTNOHAND which restart only when you want to.
+ */
+#define MAX_SELECT_SECONDS \
+	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+
+asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct timeval32 *tvp)
+{
+	fd_set_bits fds;
+	char *bits;
+	unsigned long nn;
+	long timeout;
+	int ret, size;
+
+	timeout = MAX_SCHEDULE_TIMEOUT;
+	if (tvp) {
+		time_t sec, usec;
+
+		if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
+		    || (ret = __get_user(sec, &tvp->tv_sec))
+		    || (ret = __get_user(usec, &tvp->tv_usec)))
+			goto out_nofds;
+
+		ret = -EINVAL;
+		if(sec < 0 || usec < 0)
+			goto out_nofds;
+
+		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
+			timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
+			timeout += sec * (unsigned long) HZ;
+		}
+	}
+
+	ret = -EINVAL;
+	if (n < 0)
+		goto out_nofds;
+	if (n > current->files->max_fdset)
+		n = current->files->max_fdset;
+
+	/*
+	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
+	 * since we used fdset we need to allocate memory in units of
+	 * long-words. 
+	 */
+	ret = -ENOMEM;
+	size = FDS_BYTES(n);
+	bits = kmalloc(6 * size, GFP_KERNEL);
+	if (!bits)
+		goto out_nofds;
+	fds.in      = (unsigned long *)  bits;
+	fds.out     = (unsigned long *) (bits +   size);
+	fds.ex      = (unsigned long *) (bits + 2*size);
+	fds.res_in  = (unsigned long *) (bits + 3*size);
+	fds.res_out = (unsigned long *) (bits + 4*size);
+	fds.res_ex  = (unsigned long *) (bits + 5*size);
+
+	nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
+	if ((ret = get_fd_set32(nn, fds.in, inp)) ||
+	    (ret = get_fd_set32(nn, fds.out, outp)) ||
+	    (ret = get_fd_set32(nn, fds.ex, exp)))
+		goto out;
+	zero_fd_set(n, fds.res_in);
+	zero_fd_set(n, fds.res_out);
+	zero_fd_set(n, fds.res_ex);
+
+	ret = do_select(n, &fds, &timeout);
+
+	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
+		time_t sec = 0, usec = 0;
+		if (timeout) {
+			sec = timeout / HZ;
+			usec = timeout % HZ;
+			usec *= (1000000/HZ);
+		}
+		put_user(sec, &tvp->tv_sec);
+		put_user(usec, &tvp->tv_usec);
+	}
+
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		ret = -ERESTARTNOHAND;
+		if (signal_pending(current))
+			goto out;
+		ret = 0;
+	}
+
+	set_fd_set32(nn, inp, fds.res_in);
+	set_fd_set32(nn, outp, fds.res_out);
+	set_fd_set32(nn, exp, fds.res_ex);
+
+out:
+	kfree(bits);
+out_nofds:
+	return ret;
+}
+
+
+
+struct timespec32 {
+	int 	tv_sec;
+	int	tv_nsec;
+};
+
+extern asmlinkage int sys_sched_rr_get_interval(pid_t pid,
+						struct timespec *interval);
+
+asmlinkage int
+sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_sched_rr_get_interval(pid, &t);
+	set_fs (old_fs);
+	if (put_user (t.tv_sec, &interval->tv_sec) ||
+	    __put_user (t.tv_nsec, &interval->tv_nsec))
+		return -EFAULT;
+	return ret;
+}
+
+
+extern asmlinkage int sys_nanosleep(struct timespec *rqtp,
+				    struct timespec *rmtp); 
+
+asmlinkage int
+sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+
+	if (get_user (t.tv_sec, &rqtp->tv_sec) ||
+	    __get_user (t.tv_nsec, &rqtp->tv_nsec))
+		return -EFAULT;
+	
+	set_fs (KERNEL_DS);
+	ret = sys_nanosleep(&t, rmtp ? &t : NULL);
+	set_fs (old_fs);
+	if (rmtp && ret == -EINTR) {
+		if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
+	    	    __put_user (t.tv_nsec, &rmtp->tv_nsec))
+			return -EFAULT;
+	}
+	return ret;
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/mips64_ksyms.c linux/arch/mips64/kernel/mips64_ksyms.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/mips64_ksyms.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/mips64_ksyms.c	Sat May 13 08:30:17 2000
@@ -24,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
+#include <asm/semaphore.h>
 #include <asm/softirq.h>
 #include <asm/uaccess.h>
 
@@ -56,8 +57,6 @@
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
 EXPORT_SYMBOL(_clear_page);
-EXPORT_SYMBOL(local_bh_count);
-EXPORT_SYMBOL(local_irq_count);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(kernel_thread);
@@ -83,10 +82,19 @@
  */
 EXPORT_SYMBOL(_flush_page_to_ram);
 EXPORT_SYMBOL(_flush_cache_all);
+#ifndef CONFIG_COHERENT_IO
 EXPORT_SYMBOL(_dma_cache_wback_inv);
 EXPORT_SYMBOL(_dma_cache_inv);
+#endif
 
 EXPORT_SYMBOL(invalid_pte_table);
+
+/*
+ * Semaphore stuff
+ */
+EXPORT_SYMBOL(__down_read);
+EXPORT_SYMBOL(__down_write);
+EXPORT_SYMBOL(__rwsem_wake);
 
 /*
  * Base address of ports for Intel style I/O.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/proc.c linux/arch/mips64/kernel/proc.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/proc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/proc.c	Sat May 13 08:30:17 2000
@@ -11,6 +11,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/smp.h>
 #include <asm/bootinfo.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
@@ -45,6 +46,7 @@
 	len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n",
 		       (loops_per_sec + 2500) / 500000,
 	               ((loops_per_sec + 2500) / 5000) % 100);
+	len += sprintf(buffer + len, "Number of cpus\t\t: %d\n", smp_num_cpus);
 #if defined (__MIPSEB__)
 	len += sprintf(buffer + len, "byteorder\t\t: big endian\n");
 #endif
@@ -68,4 +70,9 @@
 	len += sprintf(buffer + len, fmt, 'I', vcei_count);
 
 	return len;
+}
+
+void init_irq_proc(void)
+{
+	/* Nothing, for now.  */
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/process.c linux/arch/mips64/kernel/process.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/process.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/process.c	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.5 2000/01/29 01:41:59 ralf Exp $
+/* $Id: process.c,v 1.4 2000/01/16 01:34:01 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
@@ -33,6 +33,7 @@
 asmlinkage int cpu_idle(void)
 {
 	/* endless idle loop with no priority at all */
+	init_idle();
 	current->priority = 0;
 	current->counter = -100;
 	while (1) {
@@ -51,20 +52,20 @@
 void exit_thread(void)
 {
 	/* Forget lazy fpu state */
-	if (last_task_used_math == current) {
+	if (IS_FPU_OWNER()) {
 		set_cp0_status(ST0_CU1, ST0_CU1);
 		__asm__ __volatile__("cfc1\t$0,$31");
-		last_task_used_math = NULL;
+		CLEAR_FPU_OWNER();
 	}
 }
 
 void flush_thread(void)
 {
 	/* Forget lazy fpu state */
-	if (last_task_used_math == current) {
+	if (IS_FPU_OWNER()) {
 		set_cp0_status(ST0_CU1, ST0_CU1);
 		__asm__ __volatile__("cfc1\t$0,$31");
-		last_task_used_math = NULL;
+		CLEAR_FPU_OWNER();
 	}
 }
 
@@ -76,8 +77,7 @@
 
 	childksp = (unsigned long)p + KERNEL_STACK_SIZE - 32;
 
-	if (last_task_used_math == current) {
-		set_cp0_status(ST0_CU1, ST0_CU1);
+	if (IS_FPU_OWNER()) {
 		save_fp(p);
 	}
 	/* set up new TSS. */
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/ptrace.c linux/arch/mips64/kernel/ptrace.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/ptrace.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/ptrace.c	Sat May 13 08:30:17 2000
@@ -8,13 +8,561 @@
  * Copyright (C) Linus Torvalds
  * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
  * Copyright (C) 1996 David S. Miller
+ * Copyright (C) 2000 Ulf Carlsson
  *
  * At this time Linux/MIPS64 only supports syscall tracing, even for 32-bit
  * binaries.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/user.h>
 
+#include <asm/mipsregs.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+/* Tracing a 32-bit process with a 64-bit strace and vice verca will not
+   work.  I don't know how to fix this.  */
+
+asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
+{
+	struct task_struct *child;
+	int ret;
+
+	lock_kernel();
+#if 0
+	printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+	       (int) request, (int) pid, (unsigned long) addr,
+	       (unsigned long) data);
+#endif
+	ret = -EPERM;
+	if (request == PTRACE_TRACEME) {
+		/* are we already being traced? */
+		if (current->flags & PF_PTRACED)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->flags |= PF_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out_tsk;
+
+	if (request == PTRACE_ATTACH) {
+		if (child == current)
+			goto out_tsk;
+		if ((!child->dumpable ||
+		    (current->uid != child->euid) ||
+		    (current->uid != child->suid) ||
+		    (current->uid != child->uid) ||
+	 	    (current->gid != child->egid) ||
+	 	    (current->gid != child->sgid) ||
+	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+			goto out_tsk;
+		/* the same process cannot be attached many times */
+		if (child->flags & PF_PTRACED)
+			goto out_tsk;
+		child->flags |= PF_PTRACED;
+
+		write_lock_irq(&tasklist_lock);
+		if (child->p_pptr != current) {
+			REMOVE_LINKS(child);
+			child->p_pptr = current;
+			SET_LINKS(child);
+		}
+		write_unlock_irq(&tasklist_lock);
+
+		send_sig(SIGSTOP, child, 1);
+		ret = 0;
+		goto out_tsk;
+	}
+	ret = -ESRCH;
+	if (!(child->flags & PF_PTRACED))
+		goto out_tsk;
+	if (child->state != TASK_STOPPED) {
+		if (request != PTRACE_KILL)
+			goto out_tsk;
+	}
+	if (child->p_pptr != current)
+		goto out_tsk;
+
+	switch (request) {
+	/* when I and D space are separate, these will need to be fixed. */
+	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+	case PTRACE_PEEKDATA: {
+		unsigned int tmp;
+		int copied;
+
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		ret = -EIO;
+		if (copied != sizeof(tmp))
+			break;
+		ret = put_user(tmp, (unsigned int *) data);
+		break;
+	}
+
+	/* read the word at location addr in the USER area. */
+	case PTRACE_PEEKUSR: {
+		struct pt_regs *regs;
+		unsigned int tmp;
+
+		regs = (struct pt_regs *) ((unsigned long) child +
+			KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
+		ret = 0;
+
+		switch (addr) {
+		case 0 ... 31:
+			tmp = regs->regs[addr];
+			break;
+		case FPR_BASE ... FPR_BASE + 31:
+			if (child->used_math) {
+#ifndef CONFIG_SMP
+				if (last_task_used_math == child) {
+					set_cp0_status(ST0_CU1, ST0_CU1);
+					save_fp(child);
+					set_cp0_status(ST0_CU1, 0);
+					last_task_used_math = NULL;
+				}
+#endif
+				tmp = child->thread.fpu.hard.fp_regs[addr - 32];
+			} else {
+				tmp = -EIO;
+			}
+			break;
+		case PC:
+			tmp = regs->cp0_epc;
+			break;
+		case CAUSE:
+			tmp = regs->cp0_cause;
+			break;
+		case BADVADDR:
+			tmp = regs->cp0_badvaddr;
+			break;
+		case MMHI:
+			tmp = regs->hi;
+			break;
+		case MMLO:
+			tmp = regs->lo;
+			break;
+		case FPC_CSR:
+			tmp = child->thread.fpu.hard.control;
+			break;
+		case FPC_EIR: { /* implementation / version register */
+			unsigned int flags;
+			__save_flags(flags);
+			set_cp0_status(ST0_CU1, ST0_CU1);
+			__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+			__restore_flags(flags);
+			break;
+		}
+		default:
+			tmp = 0;
+			ret = -EIO;
+			goto out_tsk;
+		}
+		ret = put_user(tmp, (unsigned *) data);
+		break;
+		}
+	/* when I and D space are separate, this will have to be fixed. */
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		ret = 0;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+			break;
+		ret = -EIO;
+		break;
+
+	case PTRACE_POKEUSR: {
+		struct pt_regs *regs;
+		ret = 0;
+		regs = (struct pt_regs *) ((unsigned long) child +
+			KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
+
+		switch (addr) {
+		case 0 ... 31:
+			regs->regs[addr] = data;
+			break;
+		case FPR_BASE ... FPR_BASE + 31: {
+			unsigned long *fregs;
+			if (child->used_math) {
+#ifndef CONFIG_SMP
+				if (last_task_used_math == child) {
+					set_cp0_status(ST0_CU1, ST0_CU1);
+					save_fp(child);
+					set_cp0_status(ST0_CU1, 0);
+					last_task_used_math = NULL;
+					regs->cp0_status &= ~ST0_CU1;
+				}
+#endif
+			} else {
+				/* FP not yet used  */
+				memset(&child->thread.fpu.hard, ~0,
+				       sizeof(child->thread.fpu.hard));
+				child->thread.fpu.hard.control = 0;
+			}
+			fregs = child->thread.fpu.hard.fp_regs;
+			fregs[addr - FPR_BASE] = data;
+			break;
+		}
+		case PC:
+			regs->cp0_epc = data;
+			break;
+		case MMHI:
+			regs->hi = data;
+			break;
+		case MMLO:
+			regs->lo = data;
+			break;
+		case FPC_CSR:
+			child->thread.fpu.hard.control = data;
+			break;
+		default:
+			/* The rest are not allowed. */
+			ret = -EIO;
+			break;
+		}
+		goto out;
+		}
+	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+	case PTRACE_CONT: { /* restart after signal. */
+		ret = -EIO;
+		if ((unsigned int) data > _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			child->flags |= PF_TRACESYS;
+		else
+			child->flags &= ~PF_TRACESYS;
+		child->exit_code = data;
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+/*
+ * make the child exit.  Best I can do is send it a sigkill. 
+ * perhaps it should be put in the status that it wants to 
+ * exit.
+ */
+	case PTRACE_KILL: {
+		if (child->state == TASK_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		wake_up_process(child);
+		break;
+	}
+
+	case PTRACE_DETACH: { /* detach a process that was attached. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+		child->exit_code = data;
+		write_lock_irq(&tasklist_lock);
+		REMOVE_LINKS(child);
+		child->p_pptr = child->p_opptr;
+		SET_LINKS(child);
+		write_unlock_irq(&tasklist_lock);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+	default:
+		ret = -EIO;
+		break;
+	}
+
+out_tsk:
+	free_task_struct(child);
+out:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+	struct task_struct *child;
+	int ret;
+
+	lock_kernel();
+#if 0
+	printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n",
+	       (int) request, (int) pid, (unsigned long) addr,
+	       (unsigned long) data);
+#endif
+	ret = -EPERM;
+	if (request == PTRACE_TRACEME) {
+		/* are we already being traced? */
+		if (current->flags & PF_PTRACED)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->flags |= PF_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
+
+	if (request == PTRACE_ATTACH) {
+		if (child == current)
+			goto out_tsk;
+		if ((!child->dumpable ||
+		    (current->uid != child->euid) ||
+		    (current->uid != child->suid) ||
+		    (current->uid != child->uid) ||
+	 	    (current->gid != child->egid) ||
+	 	    (current->gid != child->sgid) ||
+	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+			goto out_tsk;
+		/* the same process cannot be attached many times */
+		if (child->flags & PF_PTRACED)
+			goto out_tsk;
+		child->flags |= PF_PTRACED;
+
+		write_lock_irq(&tasklist_lock);
+		if (child->p_pptr != current) {
+			REMOVE_LINKS(child);
+			child->p_pptr = current;
+			SET_LINKS(child);
+		}
+		write_unlock_irq(&tasklist_lock);
+
+		send_sig(SIGSTOP, child, 1);
+		ret = 0;
+		goto out_tsk;
+	}
+	ret = -ESRCH;
+	if (!(child->flags & PF_PTRACED))
+		goto out_tsk;
+	if (child->state != TASK_STOPPED) {
+		if (request != PTRACE_KILL)
+			goto out_tsk;
+	}
+	if (child->p_pptr != current)
+		goto out_tsk;
+
+	switch (request) {
+	/* when I and D space are separate, these will need to be fixed. */
+	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+	case PTRACE_PEEKDATA: {
+		unsigned long tmp;
+		int copied;
+
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		ret = -EIO;
+		if (copied != sizeof(tmp))
+			break;
+		ret = put_user(tmp,(unsigned long *) data);
+		break;
+	}
+
+	/* read the word at location addr in the USER area. */
+	case PTRACE_PEEKUSR: {
+		struct pt_regs *regs;
+		unsigned long tmp;
+
+		regs = (struct pt_regs *) ((unsigned long) child +
+			KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
+		ret = 0;
+
+		switch (addr) {
+		case 0 ... 31:
+			tmp = regs->regs[addr];
+			break;
+		case FPR_BASE ... FPR_BASE + 31:
+			if (child->used_math) {
+#ifndef CONFIG_SMP
+				if (last_task_used_math == child) {
+					set_cp0_status(ST0_CU1, ST0_CU1);
+					save_fp(child);
+					set_cp0_status(ST0_CU1, 0);
+					last_task_used_math = NULL;
+				}
+#endif
+				tmp = child->thread.fpu.hard.fp_regs[addr - 32];
+			} else {
+				tmp = -EIO;
+			}
+			break;
+		case PC:
+			tmp = regs->cp0_epc;
+			break;
+		case CAUSE:
+			tmp = regs->cp0_cause;
+			break;
+		case BADVADDR:
+			tmp = regs->cp0_badvaddr;
+			break;
+		case MMHI:
+			tmp = regs->hi;
+			break;
+		case MMLO:
+			tmp = regs->lo;
+			break;
+		case FPC_CSR:
+			tmp = child->thread.fpu.hard.control;
+			break;
+		case FPC_EIR: { /* implementation / version register */
+			unsigned int flags;
+			__save_flags(flags);
+			set_cp0_status(ST0_CU1, ST0_CU1);
+			__asm__ __volatile__("cfc1\t%0,$0": "=r" (tmp));
+			__restore_flags(flags);
+			break;
+		}
+		default:
+			tmp = 0;
+			ret = -EIO;
+			goto out_tsk;
+		}
+		ret = put_user(tmp, (unsigned long *) data);
+		break;
+		}
+	/* when I and D space are separate, this will have to be fixed. */
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		ret = 0;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+			break;
+		ret = -EIO;
+		break;
+
+	case PTRACE_POKEUSR: {
+		struct pt_regs *regs;
+		ret = 0;
+		regs = (struct pt_regs *) ((unsigned long) child +
+			KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
+
+		switch (addr) {
+		case 0 ... 31:
+			regs->regs[addr] = data;
+			break;
+		case FPR_BASE ... FPR_BASE + 31: {
+			unsigned long *fregs;
+			if (child->used_math) {
+#ifndef CONFIG_SMP
+				if (last_task_used_math == child) {
+					set_cp0_status(ST0_CU1, ST0_CU1);
+					save_fp(child);
+					set_cp0_status(ST0_CU1, 0);
+					last_task_used_math = NULL;
+					regs->cp0_status &= ~ST0_CU1;
+				}
+#endif
+			} else {
+				/* FP not yet used  */
+				memset(&child->thread.fpu.hard, ~0,
+				       sizeof(child->thread.fpu.hard));
+				child->thread.fpu.hard.control = 0;
+			}
+			fregs = child->thread.fpu.hard.fp_regs;
+			fregs[addr - FPR_BASE] = data;
+			break;
+		}
+		case PC:
+			regs->cp0_epc = data;
+			break;
+		case MMHI:
+			regs->hi = data;
+			break;
+		case MMLO:
+			regs->lo = data;
+			break;
+		case FPC_CSR:
+			child->thread.fpu.hard.control = data;
+			break;
+		default:
+			/* The rest are not allowed. */
+			ret = -EIO;
+			break;
+		}
+		goto out;
+		}
+	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+	case PTRACE_CONT: { /* restart after signal. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			child->flags |= PF_TRACESYS;
+		else
+			child->flags &= ~PF_TRACESYS;
+		child->exit_code = data;
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+/*
+ * make the child exit.  Best I can do is send it a sigkill. 
+ * perhaps it should be put in the status that it wants to 
+ * exit.
+ */
+	case PTRACE_KILL: {
+		if (child->state == TASK_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		wake_up_process(child);
+		break;
+	}
+
+	case PTRACE_DETACH: { /* detach a process that was attached. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+		child->exit_code = data;
+		write_lock_irq(&tasklist_lock);
+		REMOVE_LINKS(child);
+		child->p_pptr = child->p_opptr;
+		SET_LINKS(child);
+		write_unlock_irq(&tasklist_lock);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
+
+	default:
+		ret = -EIO;
+		break;
+	}
+
+out_tsk:
+	free_task_struct(child);
+out:
+	unlock_kernel();
+	return ret;
+}
 
 asmlinkage void syscall_trace(void)
 {
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_cache.S linux/arch/mips64/kernel/r4k_cache.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_cache.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/r4k_cache.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: r4k_cache.S,v 1.1 1999/12/04 03:59:00 ralf Exp $
+/* $Id: r4k_cache.S,v 1.1 1999/10/10 18:49: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_fpu.S linux/arch/mips64/kernel/r4k_fpu.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_fpu.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/r4k_fpu.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: r4k_fpu.S,v 1.1 1999/09/28 22:25:52 ralf Exp $
+/* $Id: r4k_fpu.S,v 1.1 1999/09/27 16:01: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_genex.S linux/arch/mips64/kernel/r4k_genex.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_genex.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/r4k_genex.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: r4k_genex.S,v 1.3 2000/01/20 23:32:21 ralf Exp $
+/* $Id: r4k_genex.S,v 1.3 1999/11/23 17:12:49 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
@@ -69,6 +69,14 @@
 	NESTED(handle_\exception, PT_SIZE, sp)
 	.set	noat
 	SAVE_ALL
+#if DEBUG_MIPS64
+jal dodebug2
+ld $4, PT_R4(sp)
+ld $5, PT_R5(sp)
+ld $6, PT_R6(sp)
+ld $7, PT_R7(sp)
+ld $2, PT_R2(sp)
+#endif
 	__BUILD_clear_\clear
 	.set	at
 	__BUILD_\verbose \exception
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_switch.S linux/arch/mips64/kernel/r4k_switch.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_switch.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/r4k_switch.S	Sat May 13 08:30:17 2000
@@ -9,6 +9,7 @@
  * Copyright (C) 1994, 1995, 1996, by Andreas Busse
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
 #include <asm/cachectl.h>
@@ -43,8 +44,14 @@
 	 */
 	move	$28, a1
 	cpu_restore_nonscratch $28
+#ifndef CONFIG_SMP
 	daddiu	t0, $28, KERNEL_STACK_SIZE-32
 	sd	t0, kernelsp
+#else
+	mtc0	a1, CP0_WATCHLO
+	dsrl32	a1, a1, 0
+	mtc0	a1, CP0_WATCHHI
+#endif
 	mfc0	t1, CP0_STATUS		/* Do we really need this? */
 	li	a3, 0xff00
 	and	t1, a3
@@ -73,7 +80,7 @@
 	beqz	a0, 2f				# Save floating point state
 	 nor	t3, zero, t3
 
-	lw	t1, ST_OFF(a0)			# last thread looses fpu
+	ld	t1, ST_OFF(a0)			# last thread looses fpu
 	and	t1, t3
 	sd	t1, ST_OFF(a0)
 	sll	t2, t1, 5
@@ -84,6 +91,8 @@
 	fpu_save_16even a0 t1			# clobbers t1
 2:
 
+	beqz	a1, 3f
+
 	sll	t0, t0, 5			# load new fp state
 	bgez	t0, 1f
 	 ldc1	$f0, (THREAD_FPU + 0x00)($28)
@@ -91,6 +100,7 @@
 1:
 	.set	reorder
 	fpu_restore_16even $28, t0		# clobbers t0
+3:
 	jr	ra
 	END(lazy_fpu_switch)
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_debug.c linux/arch/mips64/kernel/r4k_tlb_debug.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_debug.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/r4k_tlb_debug.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: r4k_tlb_debug.c,v 1.3 2000/01/29 01:41:59 ralf Exp $
+/* $Id: r4k_tlb_debug.c,v 1.2 2000/01/17 23:32:46 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_glue.S linux/arch/mips64/kernel/r4k_tlb_glue.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/r4k_tlb_glue.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/r4k_tlb_glue.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: r4k_tlb_glue.S,v 1.2 2000/01/17 23:32:46 ralf Exp $
+/* $Id: r4k_tlb_glue.S,v 1.5 1999/11/23 17:12:49 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
@@ -23,10 +23,26 @@
 	END(__tlb_refill_debug_tramp)
 	__FINIT
 
-	.macro	tlb_handler name
+	.macro	__BUILD_cli
+	CLI
+	.endm
+
+	.macro	__BUILD_sti
+	STI
+	.endm
+
+	.macro	tlb_handler name interruptible
 	NESTED(__\name, PT_SIZE, sp)
 	SAVE_ALL
-	CLI
+#if DEBUG_MIPS64
+jal dodebug2
+ld $4, PT_R4(sp)
+ld $5, PT_R5(sp)
+ld $6, PT_R6(sp)
+ld $7, PT_R7(sp)
+ld $2, PT_R2(sp)
+#endif
+	__BUILD_\interruptible
 	dmfc0	t0, CP0_BADVADDR
 	sd	t0, PT_BVADDR(sp)
 	move	a0, sp
@@ -35,8 +51,8 @@
 	END(__\name)
 	.endm
 
-	tlb_handler	tlb_refill_debug
-	tlb_handler	xtlb_refill_debug
-	tlb_handler	xtlb_mod_debug
-	tlb_handler	xtlb_tlbl_debug
-	tlb_handler	xtlb_tlbs_debug
+	tlb_handler	tlb_refill_debug cli
+	tlb_handler	xtlb_refill_debug cli
+	tlb_handler	xtlb_mod_debug sti
+	tlb_handler	xtlb_tlbl_debug sti
+	tlb_handler	xtlb_tlbs_debug sti
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/scall_64.S linux/arch/mips64/kernel/scall_64.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/scall_64.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/scall_64.S	Sat May 13 08:30:17 2000
@@ -22,9 +22,6 @@
 /* This duplicates the definition from <asm/signal.h> */
 #define SIGILL		4		/* Illegal instruction (ANSI).  */
 
-/* Highest syscall handled here.  */
-#define MAX_SYSCALL_NO	__NR_Linux + __NR_Linux_syscalls
-
 #ifndef CONFIG_MIPS32_COMPAT
 #define handle_sys64 handle_sys
 #endif
@@ -35,18 +32,19 @@
 #ifndef CONFIG_MIPS32_COMPAT
 	.set	noat
 	SAVE_SOME
+	STI
 	.set	at
 #endif
 	ld	t1, PT_EPC(sp)		# skip syscall on return
 
-	sltiu	t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
+	subu	t0, v0, __NR_Linux	# check syscall number
+	sltiu	t0, t0,	__NR_Linux_syscalls + 1
 	daddiu	t1, 4			# skip to next instruction
 	beqz	t0, illegal_syscall
 	sd	t1, PT_EPC(sp)
 
-	dsll	t0, v0, 3
+	dsll	t0, v0, 3		# offset into table
 	ld	t2, (sys_call_table - (__NR_Linux * 8))(t0) # syscall routine
-	beqz	t2, illegal_syscall;
 
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
 
@@ -163,7 +161,7 @@
 	PTR	sys_ni_syscall		/* ptrace */
 	PTR	sys_alarm
 	PTR	sys_fstat
-	PTR	sys_ni_syscall
+	PTR	sys_pause
 	PTR	sys_utime				/* 4030 */
 	PTR	sys_ni_syscall
 	PTR	sys_ni_syscall
@@ -345,3 +343,5 @@
 	PTR	sys_ni_syscall
 	PTR	sys_ni_syscall
 	PTR	sys_pivot_root				/* 4210 */
+	PTR	sys_mincore
+	PTR	sys_madvise
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/scall_o32.S linux/arch/mips64/kernel/scall_o32.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/scall_o32.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/scall_o32.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: scall_o32.S,v 1.8 2000/02/23 00:41:00 ralf Exp $
+/* $Id: scall_o32.S,v 1.18 2000/03/27 21:04:13 ulfc 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
@@ -35,23 +35,26 @@
 	SAVE_SOME
 	STI
 	.set	at
- SAVE_ALL
- ld	a1, PT_R2(sp)
- PRINT("Got syscall %d\n")
- RESTORE_ALL
-
+#if DEBUG_MIPS64
+ jal dodebug
+ ld $4, PT_R4(sp)
+ ld $5, PT_R5(sp)
+ ld $6, PT_R6(sp)
+ ld $7, PT_R7(sp)
+ ld $2, PT_R2(sp)
+#endif
 	ld	t1, PT_EPC(sp)		# skip syscall on return
 
-	sltiu	t0, v0, MAX_SYSCALL_NO + 1 # check syscall number
+	subu	t0, v0, __NR_Linux32	# check syscall number
+	sltiu	t0, t0, __NR_Linux32_syscalls + 1
 	daddiu	t1, 4			# skip to next instruction
 	beqz	t0, not_o32_scall
 	sd	t1, PT_EPC(sp)
 
 	/* XXX Put both in one cacheline, should save a bit. */
-	dsll	t0, v0, 3
+	dsll	t0, v0, 3		# offset into table
 	ld	t2, (sys_call_table - (__NR_Linux32 * 8))(t0) # syscall routine
 	lbu	t3, (sys_narg_table - __NR_Linux32)(v0)	# number of arguments
-	beqz	t2, illegal_syscall;
 
 	subu	t0, t3, 5		# 5 or more arguments?
 	sd	a3, PT_R26(sp)		# save a3 for syscall restarting
@@ -72,7 +75,7 @@
 	negu	v0			# error
 	sd	v0, PT_R0(sp)		# set flag for syscall restarting
 1:	sd	v0, PT_R2(sp)		# result
-
+	
 FEXPORT(o32_ret_from_sys_call)
 	lw	t0, softirq_state
 	lw	t1, softirq_state+4	# unused delay slot
@@ -110,6 +113,11 @@
 
 trace_a_syscall:
 	SAVE_STATIC
+	sd	a4, PT_R8(sp)
+	sd	a5, PT_R9(sp)
+	sd	a6, PT_R10(sp)
+	sd	a7, PT_R11(sp)
+
 	sd	t2,PT_R1(sp)
 	jal	syscall_trace
 	ld	t2,PT_R1(sp)
@@ -118,6 +126,9 @@
 	ld	a1, PT_R5(sp)
 	ld	a2, PT_R6(sp)
 	ld	a3, PT_R7(sp)
+	ld	a4, PT_R8(sp)
+	ld	a5, PT_R9(sp)
+
 	jalr	t2
 
 	li	t0, -EMAXERRNO - 1	# error?
@@ -130,7 +141,7 @@
 1:	sd	v0, PT_R2(sp)		# result
 
 	jal	syscall_trace
-	j	ret_from_sys_call
+	j	o32_ret_from_sys_call
 
 /* ------------------------------------------------------------------------ */
 
@@ -197,12 +208,12 @@
 	sys	sys_read	3
 	sys	sys_write	3
 	sys	sys_open	3			/* 4005 */
-	sys	sys_close	3
+	sys	sys_close	1
 	sys	sys_waitpid	3
 	sys	sys_creat	2
 	sys	sys_link	2
 	sys	sys_unlink	1			/* 4010 */
-	sys	sys_execve	0
+	sys	sys32_execve	0
 	sys	sys_chdir	1
 	sys	sys_time	1
 	sys	sys_mknod	3
@@ -217,10 +228,10 @@
 	sys	sys_setuid	1
 	sys	sys_getuid	0
 	sys	sys_stime	1			/* 4025 */
-	sys	sys_ni_syscall	0	/* ptrace */
-	sys	sys_alarm	1
+	sys	sys32_ptrace	4
+	sys	sys32_alarm	1
 	sys	sys_fstat	2
-	sys	sys_ni_syscall	0
+	sys	sys_pause	0
 	sys	sys_utime	2			/* 4030 */
 	sys	sys_ni_syscall	0
 	sys	sys_ni_syscall	0
@@ -245,7 +256,7 @@
 	sys	sys_acct	0
 	sys	sys_umount	2
 	sys	sys_ni_syscall	0
-	sys	sys_ioctl	3
+	sys	sys32_ioctl	3
 	sys	sys_fcntl	3			/* 4055 */
 	sys	sys_ni_syscall	2
 	sys	sys_setpgid	2
@@ -266,11 +277,11 @@
 	sys	sys32_sigsuspend	0
 	sys	sys32_sigpending	1
 	sys	sys_sethostname	2
-	sys	sys_setrlimit	2			/* 4075 */
-	sys	sys_old_getrlimit	2
-	sys	sys_getrusage	2
-	sys	sys_gettimeofday 2
-	sys	sys_settimeofday 2
+	sys	sys32_setrlimit	2			/* 4075 */
+	sys	sys32_getrlimit	2
+	sys	sys32_getrusage	2
+	sys	sys32_gettimeofday 2
+	sys	sys32_settimeofday 2
 	sys	sys_getgroups	2			/* 4080 */
 	sys	sys_setgroups	2
 	sys	sys_ni_syscall	0 /* old_select */
@@ -280,7 +291,7 @@
 	sys	sys_uselib	1
 	sys	sys_swapon	2
 	sys	sys_reboot	3
-	sys	old_readdir	3
+	sys	sys32_readdir	3
 	sys	sys_mmap	6			/* 4090 */
 	sys	sys_munmap	2
 	sys	sys_truncate	2
@@ -290,13 +301,13 @@
 	sys	sys_getpriority	2
 	sys	sys_setpriority	3
 	sys	sys_ni_syscall	0
-	sys	sys_statfs	2
-	sys	sys_fstatfs	2			/* 4100 */
+	sys	sys32_statfs	2
+	sys	sys32_fstatfs	2			/* 4100 */
 	sys	sys_ni_syscall	0	/* sys_ioperm */
 	sys	sys_socketcall	2
 	sys	sys_syslog	3
-	sys	sys_setitimer	3
-	sys	sys_getitimer	2			/* 4105 */
+	sys	sys32_setitimer	3
+	sys	sys32_getitimer	2			/* 4105 */
 	sys	sys32_newstat	2
 	sys	sys32_newlstat	2
 	sys	sys32_newfstat	2
@@ -305,7 +316,7 @@
 	sys	sys_vhangup	0
 	sys	sys_ni_syscall	0	/* was sys_idle	 */
 	sys	sys_ni_syscall	0	/* sys_vm86 */
-	sys	sys_wait4	4
+	sys	sys32_wait4	4
 	sys	sys_swapoff	1			/* 4115 */
 	sys	sys_sysinfo	1
 	sys	sys_ipc		6
@@ -317,7 +328,7 @@
 	sys	sys_ni_syscall	0	/* sys_modify_ldt */
 	sys	sys_adjtimex	1
 	sys	sys_mprotect	3			/* 4125 */
-	sys	sys_sigprocmask	3
+	sys	sys32_sigprocmask	3
 	sys	sys_create_module 2
 	sys	sys_init_module	5
 	sys	sys_delete_module 1
@@ -331,13 +342,13 @@
 	sys	sys_ni_syscall	0 /* for afs_syscall */
 	sys	sys_setfsuid	1
 	sys	sys_setfsgid	1
-	sys	sys_llseek	5			/* 4140 */
-	sys	sys_getdents	3
-	sys	sys_select	5
+	sys	sys32_llseek	5			/* 4140 */
+	sys	sys32_getdents	3
+	sys	sys32_select	5
 	sys	sys_flock	2
 	sys	sys_msync	3
-	sys	sys_readv	3			/* 4145 */
-	sys	sys_writev	3
+	sys	sys32_readv	3			/* 4145 */
+	sys	sys32_writev	3
 	sys	sys_cacheflush	3
 	sys	sys_cachectl	3
 	sys	sys_sysmips	4
@@ -356,8 +367,8 @@
 	sys	sys_sched_yield	0
 	sys	sys_sched_get_priority_max 1
 	sys	sys_sched_get_priority_min 1
-	sys	sys_sched_rr_get_interval 2		/* 4165 */
-	sys	sys_nanosleep	2
+	sys	sys32_sched_rr_get_interval 2		/* 4165 */
+	sys	sys32_nanosleep	2
 	sys	sys_mremap	4
 	sys	sys_accept	3
 	sys	sys_bind	3
@@ -408,6 +419,8 @@
 	sys	sys_lstat64	3
 	sys	sys_fstat64	3			/* 4210 */
 	sys	sys_pivot_root	2
+	sys	sys_mincore	3
+	sys	sys_madvise	3
 	.endm
 
 	.macro	sys function, nargs
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/setup.c linux/arch/mips64/kernel/setup.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/setup.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/setup.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.7 2000/02/04 07:40:24 ralf Exp $
+/* $Id: setup.c,v 1.9 2000/03/14 01:39:27 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
@@ -37,10 +37,13 @@
 #include <asm/system.h>
 
 #ifdef CONFIG_SGI_IP27
+/* XXX Origin garbage has no business in this file  */
 #include <asm/sn/sn0/addrs.h>
 #endif
 
-struct mips_cpuinfo boot_cpu_data;
+#ifndef CONFIG_SMP
+struct cpuinfo_mips cpu_data[1];
+#endif
 
 #ifdef CONFIG_VT
 struct screen_info screen_info;
@@ -102,7 +105,10 @@
  * mips_io_port_base is the begin of the address space to which x86 style
  * I/O ports are mapped.
  */
+#ifdef CONFIG_SGI_IP27
+/* XXX Origin garbage has no business in this file  */
 unsigned long mips_io_port_base = IO_BASE;
+#endif
 
 extern void ip22_setup(void);
 extern void ip27_setup(void);
@@ -183,4 +189,6 @@
 			*memory_start_p = initrd_end;
 	}
 #endif
+
+	paging_init();
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/signal.c linux/arch/mips64/kernel/signal.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/signal.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/signal.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.5 2000/02/04 07:40:24 ralf Exp $
+/* $Id: signal.c,v 1.4 2000/01/17 23:32:46 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
@@ -26,6 +26,7 @@
 #include <asm/stackframe.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
+#include <asm/system.h>
 
 #define DEBUG_SIG 0
 
@@ -37,6 +38,35 @@
 extern asmlinkage int save_fp_context(struct sigcontext *sc);
 extern asmlinkage int restore_fp_context(struct sigcontext *sc);
 
+static inline int store_fp_context(struct sigcontext *sc)
+{
+	unsigned int fcr0;
+	int err = 0;
+
+	err |= __copy_to_user(&sc->sc_fpregs[0], 
+		&current->thread.fpu.hard.fp_regs[0], NUM_FPU_REGS * 
+						sizeof(unsigned long));
+	err |= __copy_to_user(&sc->sc_fpc_csr, &current->thread.fpu.hard.control,
+						sizeof(unsigned int));
+	__asm__ __volatile__("cfc1 %0, $0\n\t" : "=r" (fcr0));
+	err |= __copy_to_user(&sc->sc_fpc_eir, &fcr0, sizeof(unsigned int));
+
+	return err;
+}
+
+static inline int refill_fp_context(struct sigcontext *sc)
+{
+	int err = 0;
+
+	if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
+		return -EFAULT;
+	err |= __copy_from_user(&current->thread.fpu.hard.fp_regs[0], 
+			&sc->sc_fpregs[0], NUM_FPU_REGS * sizeof(unsigned long));
+	err |= __copy_from_user(&current->thread.fpu.hard.control, &sc->sc_fpc_csr,
+							sizeof(unsigned int));
+	return err;
+}
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -180,8 +210,12 @@
 
 	err |= __get_user(owned_fp, &sc->sc_ownedfp);
 	if (owned_fp) {
-		err |= restore_fp_context(sc);
-		last_task_used_math = current;
+		if (IS_FPU_OWNER()) {
+			CLEAR_FPU_OWNER();
+			regs->cp0_status &= ~ST0_CU1;
+		}
+		current->used_math = 1;
+		err |= refill_fp_context(sc);
 	}
 
 	return err;
@@ -281,11 +315,9 @@
 static int inline
 setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
-	int owned_fp;
 	int err = 0;
 
 	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
-	err |= __put_user(regs->cp0_status, &sc->sc_status);
 
 #define save_gp_reg(i) {						\
 	err |= __put_user(regs->regs[i], &sc->sc_regs[i]);		\
@@ -306,16 +338,19 @@
 	err |= __put_user(regs->cp0_cause, &sc->sc_cause);
 	err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
 
-	owned_fp = (current == last_task_used_math);
-	err |= __put_user(owned_fp, &sc->sc_ownedfp);
-
 	if (current->used_math) {	/* fp is active.  */
-		set_cp0_status(ST0_CU1, ST0_CU1);
-		err |= save_fp_context(sc);
-		last_task_used_math = NULL;
-		regs->cp0_status &= ~ST0_CU1;
+		if (IS_FPU_OWNER()) {
+			lazy_fpu_switch(current, 0);
+			CLEAR_FPU_OWNER();
+			regs->cp0_status &= ~ST0_CU1;
+		}
+		err |= __put_user(1, &sc->sc_ownedfp);
+		err |= store_fp_context(sc);
 		current->used_math = 0;
+	} else {
+		err |= __put_user(0, &sc->sc_ownedfp);
 	}
+	err |= __put_user(regs->cp0_status, &sc->sc_status);
 
 	return err;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/signal32.c linux/arch/mips64/kernel/signal32.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/signal32.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips64/kernel/signal32.c	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: signal32.c,v 1.2 2000/02/18 00:03:48 ralf Exp $
+/* $Id: signal32.c,v 1.4 2000/03/15 22:46:55 kanoj 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
@@ -25,6 +25,7 @@
 #include <asm/stackframe.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
+#include <asm/system.h>
 
 #define DEBUG_SIG 0
 
@@ -38,12 +39,11 @@
 
 /* 32-bit compatibility types */
 
-#define _NSIG32		128
 #define _NSIG32_BPW	32
-#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+#define _NSIG32_WORDS	(_NSIG / _NSIG32_BPW)
 
 typedef struct {
-	unsigned int sig[_NSIG_WORDS];
+	unsigned int sig[_NSIG32_WORDS];
 } sigset32_t;
 
 typedef unsigned int __sighandler32_t;
@@ -65,6 +65,35 @@
 } stack32_t;
 
 
+static inline int store_fp_context(struct sigcontext *sc)
+{
+	unsigned int fcr0;
+	int err = 0;
+
+	err |= __copy_to_user(&sc->sc_fpregs[0], 
+		&current->thread.fpu.hard.fp_regs[0], NUM_FPU_REGS * 
+						sizeof(unsigned long));
+	err |= __copy_to_user(&sc->sc_fpc_csr, &current->thread.fpu.hard.control,
+						sizeof(unsigned int));
+	__asm__ __volatile__("cfc1 %0, $0\n\t" : "=r" (fcr0));
+	err |= __copy_to_user(&sc->sc_fpc_eir, &fcr0, sizeof(unsigned int));
+
+	return err;
+}
+
+static inline int refill_fp_context(struct sigcontext *sc)
+{
+	int err = 0;
+
+	if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
+		return -EFAULT;
+	err |= __copy_from_user(&current->thread.fpu.hard.fp_regs[0], 
+			&sc->sc_fpregs[0], NUM_FPU_REGS * sizeof(unsigned long));
+	err |= __copy_from_user(&current->thread.fpu.hard.control, &sc->sc_fpc_csr,
+							sizeof(unsigned int));
+	return err;
+}
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -211,8 +240,12 @@
 
 	err |= __get_user(owned_fp, &sc->sc_ownedfp);
 	if (owned_fp) {
-		err |= restore_fp_context(sc);
-		last_task_used_math = current;
+		if (IS_FPU_OWNER()) {
+			CLEAR_FPU_OWNER();
+			regs->cp0_status &= ~ST0_CU1;
+		}
+		current->used_math = 1;
+		err |= refill_fp_context(sc);
 	}
 
 	return err;
@@ -237,7 +270,10 @@
 {
 	struct sigframe *frame;
 	sigset_t blocked;
+
+#if DEBUG_MIPS64
 printk("%s called.\n", __FUNCTION__);
+#endif
 
 	frame = (struct sigframe *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
@@ -314,11 +350,9 @@
 static int inline
 setup_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
-	int owned_fp;
 	int err = 0;
 
 	err |= __put_user(regs->cp0_epc, &sc->sc_pc);
-	err |= __put_user(regs->cp0_status, &sc->sc_status);
 
 #define save_gp_reg(i) {						\
 	err |= __put_user(regs->regs[i], &sc->sc_regs[i]);		\
@@ -339,16 +373,19 @@
 	err |= __put_user(regs->cp0_cause, &sc->sc_cause);
 	err |= __put_user(regs->cp0_badvaddr, &sc->sc_badvaddr);
 
-	owned_fp = (current == last_task_used_math);
-	err |= __put_user(owned_fp, &sc->sc_ownedfp);
-
 	if (current->used_math) {	/* fp is active.  */
-		set_cp0_status(ST0_CU1, ST0_CU1);
-		err |= save_fp_context(sc);
-		last_task_used_math = NULL;
-		regs->cp0_status &= ~ST0_CU1;
+		if (IS_FPU_OWNER()) {
+			lazy_fpu_switch(current, 0);
+			CLEAR_FPU_OWNER();
+			regs->cp0_status &= ~ST0_CU1;
+		}
+		err |= __put_user(1, &sc->sc_ownedfp);
+		err |= store_fp_context(sc);
 		current->used_math = 0;
+	} else {
+		err |= __put_user(0, &sc->sc_ownedfp);
 	}
+	err |= __put_user(regs->cp0_status, &sc->sc_status);
 
 	return err;
 }
@@ -390,10 +427,10 @@
 		/*
 		 * Set up the return code ...
 		 *
-		 *         li      v0, __NR_sigreturn
+		 *         li      v0, __NR_Linux32_sigreturn
 		 *         syscall
 		 */
-		err |= __put_user(0x24020000 + __NR_sigreturn,
+		err |= __put_user(0x24020000 + __NR_Linux32_sigreturn,
 		                  frame->sf_code + 0);
 		err |= __put_user(0x0000000c                 ,
 		                  frame->sf_code + 1);
@@ -453,10 +490,10 @@
 		/*
 		 * Set up the return code ...
 		 *
-		 *         li      v0, __NR_sigreturn
+		 *         li      v0, __NR_Linux32_sigreturn
 		 *         syscall
 		 */
-		err |= __put_user(0x24020000 + __NR_sigreturn,
+		err |= __put_user(0x24020000 + __NR_Linux32_sigreturn,
 		                  frame->rs_code + 0);
 		err |= __put_user(0x0000000c                 ,
 		                  frame->rs_code + 1);
@@ -555,7 +592,10 @@
 {
 	struct k_sigaction *ka;
 	siginfo_t info;
+
+#if DEBUG_MIPS64
 printk("%s: delivering signal.\n", current->comm);
+#endif
 
 	if (!oldset)
 		oldset = &current->blocked;
@@ -656,7 +696,9 @@
 		if (regs->regs[0])
 			syscall_restart(regs, ka);
 		/* Whee!  Actually deliver the signal.  */
+#if DEBUG_MIPS64
 printk("%s: delivering signal.\n", __FUNCTION__);
+#endif
 		handle_signal(signr, ka, &info, oldset, regs);
 		return 1;
 	}
@@ -674,6 +716,25 @@
 			regs->cp0_epc -= 8;
 		}
 	}
+	return 0;
+}
+
+extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set,
+						old_sigset_t *oset);
+
+asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, 
+							old_sigset_t32 *oset)
+{
+	old_sigset_t s;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+
+	if (set && get_user (s, set)) return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
+	set_fs (old_fs);
+	if (ret) return ret;
+	if (oset && put_user (s, oset)) return -EFAULT;
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/smp.c linux/arch/mips64/kernel/smp.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/smp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/kernel/smp.c	Sat May 13 08:30:17 2000
@@ -0,0 +1,258 @@
+#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 <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+#include <asm/mmu_context.h>
+
+#ifdef CONFIG_SGI_IP27
+
+#include <asm/sn/arch.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/agent.h>
+#include <asm/sn/sn0/ip27.h>
+
+#define DORESCHED	0xab
+#define DOCALL		0xbc
+
+#define IRQ_TO_SWLEVEL(i)	i + 7	/* Delete this from here */
+
+static void sendintr(int destid, unsigned char status)
+{
+	int irq;
+
+#if (CPUS_PER_NODE == 2)
+	switch (status) {
+		case DORESCHED:	irq = CPU_RESCHED_A_IRQ; break;
+		case DOCALL:	irq = CPU_CALL_A_IRQ; break;
+		default:	panic("sendintr");
+	}
+	irq += cputoslice(destid);
+
+	/*
+	 * Convert the compact hub number to the NASID to get the correct
+	 * part of the address space.  Then set the interrupt bit associated
+	 * with the CPU we want to send the interrupt to.
+	 */
+	REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cputocnode(destid)),
+			IRQ_TO_SWLEVEL(irq));
+#else
+	<< Bomb!  Must redefine this for more than 2 CPUS. >>
+#endif
+}
+
+#endif /* CONFIG_SGI_IP27 */
+
+/* The 'big kernel lock' */
+spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+int smp_threads_ready = 0;	/* Not used */
+atomic_t smp_commenced = ATOMIC_INIT(0);
+struct cpuinfo_mips cpu_data[NR_CPUS];
+int smp_num_cpus;		/* Number that came online.  */
+int __cpu_number_map[NR_CPUS];
+int __cpu_logical_map[NR_CPUS];
+cycles_t cacheflush_time;
+
+static void smp_tune_scheduling (void)
+{
+}
+
+void __init smp_boot_cpus(void)
+{
+	extern void allowboot(void);
+	extern int maxcpus;
+
+	init_new_context(current, &init_mm);
+	global_irq_holder = 0;
+	current->processor = 0;
+	init_idle();
+	smp_tune_scheduling();
+	smp_num_cpus = maxcpus;
+	allowboot();
+}
+
+void __init smp_commence(void)
+{
+	wmb();
+	atomic_set(&smp_commenced,1);
+}
+
+static void stop_this_cpu(void *dummy)
+{
+	/*
+	 * Remove this CPU
+	 */
+	for (;;);
+}
+
+void smp_send_stop(void)
+{
+	smp_call_function(stop_this_cpu, NULL, 1, 0);
+	smp_num_cpus = 1;
+}
+
+/*
+ * this function sends a 'reschedule' IPI to another CPU.
+ * it goes straight through and wastes no time serializing
+ * anything. Worst case is that we lose a reschedule ...
+ */
+void smp_send_reschedule(int cpu)
+{
+	sendintr(cpu, DORESCHED);
+}
+
+/* Not really SMP stuff ... */
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return 0;
+}
+
+/*
+ * Run a function on all other CPUs.
+ *  <func>      The function to run. This must be fast and non-blocking.
+ *  <info>      An arbitrary pointer to pass to the function.
+ *  <retry>     If true, keep retrying until ready.
+ *  <wait>      If true, wait until function has completed on other CPUs.
+ *  [RETURNS]   0 on success, else a negative status code.
+ *
+ * Does not return until remote CPUs are nearly ready to execute <func>
+ * or are or have executed.
+ */
+static volatile struct call_data_struct {
+	void (*func) (void *info);
+	void *info;
+	atomic_t started;
+	atomic_t finished;
+	int wait;
+} *call_data = NULL;
+
+int smp_call_function (void (*func) (void *info), void *info, int retry, 
+								int wait)
+{
+	struct call_data_struct data;
+	int i, cpus = smp_num_cpus-1;
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+
+	if (cpus == 0)
+		return 0;
+
+	data.func = func;
+	data.info = info;
+	atomic_set(&data.started, 0);
+	data.wait = wait;
+	if (wait)
+		atomic_set(&data.finished, 0);
+
+	spin_lock_bh(&lock);
+	call_data = &data;
+	/* Send a message to all other CPUs and wait for them to respond */
+	for (i = 0; i < smp_num_cpus; i++)
+		if (smp_processor_id() != i)
+			sendintr(i, DOCALL);
+
+	/* Wait for response */
+	/* FIXME: lock-up detection, backtrace on lock-up */
+	while (atomic_read(&data.started) != cpus)
+		barrier();
+
+	if (wait)
+		while (atomic_read(&data.finished) != cpus)
+			barrier();
+	spin_unlock_bh(&lock);
+	return 0;
+}
+
+void smp_call_function_interrupt(void)
+{
+	void (*func) (void *info) = call_data->func;
+	void *info = call_data->info;
+	int wait = call_data->wait;
+
+	/*
+	 * Notify initiating CPU that I've grabbed the data and am
+	 * about to execute the function.
+	 */
+	atomic_inc(&call_data->started);
+
+	/*
+	 * At this point the info structure may be out of scope unless wait==1.
+	 */
+	(*func)(info);
+	if (wait)
+		atomic_inc(&call_data->finished);
+}
+	
+
+static void flush_tlb_all_ipi(void *info)
+{
+	_flush_tlb_all();
+}
+
+void flush_tlb_all(void)
+{
+	smp_call_function(flush_tlb_all_ipi, 0, 1, 1);
+	_flush_tlb_all();
+}
+
+static void flush_tlb_mm_ipi(void *mm)
+{
+	_flush_tlb_mm((struct mm_struct *)mm);
+}
+
+void flush_tlb_mm(struct mm_struct *mm)
+{
+	smp_call_function(flush_tlb_mm_ipi, (void *)mm, 1, 1);
+	_flush_tlb_mm(mm);
+}
+
+struct flush_tlb_data {
+	struct mm_struct *mm;
+	struct vm_area_struct *vma;
+	unsigned long addr1;
+	unsigned long addr2;
+};
+
+static void flush_tlb_range_ipi(void *info)
+{
+	struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
+
+	_flush_tlb_range(fd->mm, fd->addr1, fd->addr2);
+}
+
+void flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+	struct flush_tlb_data fd;
+
+	fd.mm = mm;
+	fd.addr1 = start;
+	fd.addr2 = end;
+	smp_call_function(flush_tlb_range_ipi, (void *)&fd, 1, 1);
+	_flush_tlb_range(mm, start, end);
+}
+
+static void flush_tlb_page_ipi(void *info)
+{
+	struct flush_tlb_data *fd = (struct flush_tlb_data *)info;
+
+	_flush_tlb_page(fd->vma, fd->addr1);
+}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
+{
+	struct flush_tlb_data fd;
+
+	fd.vma = vma;
+	fd.addr1 = page;
+	smp_call_function(flush_tlb_page_ipi, (void *)&fd, 1, 1);
+	_flush_tlb_page(vma, page);
+}
+
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/softfp.S linux/arch/mips64/kernel/softfp.S
--- v2.3.99-pre8/linux/arch/mips64/kernel/softfp.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/softfp.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: softfp.S,v 1.1 1999/12/04 03:59:00 ralf Exp $
+/* $Id: softfp.S,v 1.2 2000/03/21 23:50:42 ulfc 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
@@ -148,7 +148,8 @@
 insn:	LOCK_KERNEL;							\
 	la	a1, 8f;							\
 	TEXT(#insn);							\
-	la	a1, nosim;						\
+	la	a0, nosim;						\
+	jal	printk;							\
 	UNLOCK_KERNEL;							\
 	j	done
 
@@ -165,9 +166,9 @@
 	.cpload	$25
 	.set	reorder
 
-	subu	sp, 16
+	dsubu	sp, 16
 	.cprestore 20
-	sw	ra, 16(sp)
+	sd	ra, 0(sp)
 
 	/* For now we assume that we get the opcode to simulate passed in as
 	   an argument.  */
@@ -178,9 +179,9 @@
 	 */
 	la	ta1, lowtab
 	andi	ta2, ta0, 0x3f
-	sll	ta2, ta2, 2
-	addu	ta1, ta2
-	lw	ta1, (ta1)
+	sll	ta2, ta2, 3
+	daddu	ta1, ta2
+	ld	ta1, (ta1)
 	jr	ta1
 	END(simfp)
 
@@ -189,17 +190,17 @@
  * can keep the jump table significantly shorter.
  */
 #define FMT_switch(insn,opc,temp0,temp1)				\
-insn:	srl	temp0, opc, 19;						\
+insn:	srl	temp0, opc, 18;						\
 	andi	temp0, 0x1c;						\
 	la	temp1, insn ## .tab;					\
-	addu	temp0, temp1;						\
-	lw	temp0, (temp0);						\
+	daddu	temp0, temp1;						\
+	ld	temp0, (temp0);						\
 	jr	temp0;							\
 									\
 	.data;								\
 insn ## .tab:								\
-	.word	insn ## .s, insn ## .d, unimp, unimp;			\
-	.word	insn ## .w, insn ## .l, unimp, unimp;			\
+	.dword	insn ## .s, insn ## .d, unimp, unimp;			\
+	.dword	insn ## .w, insn ## .l, unimp, unimp;			\
 	.previous
 
 	BITCH(add)
@@ -293,8 +294,8 @@
 	   full fp simulation.  */
 
 	/* Done, return.  */
-	lw	ra, 16(sp)
-	addu	sp, 16
+	ld	ra, 0(sp)
+	daddu	sp, 16
 	jr	ra
 
 /* Convert a double fp to a fixed point integer.  */
@@ -378,8 +379,8 @@
 	jal	s_put_fpreg
 
 	/* Done, return.  */
-	lw	ra, 16(sp)
-	addu	sp, 16
+	ld	ra, 0(sp)
+	daddu	sp, 16
 	jr	ra
 
 cvt.w.w = unimp				# undefined result
@@ -410,11 +411,9 @@
 /* Get the single precission register which's number is in ta1.  */
 s_get_fpreg:
 	.set	noat
-	sll	AT, ta1, 2
 	sll	ta1, 3
-	addu	ta1, AT
 	la	AT, 1f
-	addu	AT, ta1
+	daddu	AT, ta1
 	jr	AT
 	.set	at
 
@@ -489,11 +488,9 @@
  */
 s_put_fpreg:
 	.set	noat
-	sll	AT, ta1, 2
 	sll	ta1, 3
-	addu	ta1, AT
 	la	AT, 1f
-	addu	AT, ta1
+	daddu	AT, ta1
 	jr	AT
 	.set	at
 	
@@ -565,9 +562,11 @@
 /* Get the double precission register which's number is in ta1 into ta1/ta2.  */
 d_get_fpreg:
 	.set	noat
-	sll	ta1, 3
+	sll	AT, ta1, 1
+	sll	ta1, 2
+	daddu	ta1, AT
 	la	AT, 1f
-	addu	AT, ta1
+	daddu	AT, ta1
 	jr	AT
 	.set	at
 
@@ -624,16 +623,16 @@
  * Send an invalid operation exception.
  */
 invalid:
-	lw	ra, 16(sp)
-	addu	sp, 16
+	ld	ra, 0(sp)
+	daddu	sp, 16
 	jr	ra
 
 /*
  * Done, just skip over the current instruction
  */
 done:
-	lw	ra, 16(sp)
-	addu	sp, 16
+	ld	ra, 0(sp)
+	daddu	sp, 16
 	jr	ra
 
 unimp:
@@ -641,7 +640,7 @@
 	   on new, yet unsupported CPU types or when the faulting instruction
 	   is being executed for cache but has been overwritten in memory.  */
 	LOCK_KERNEL
-	move	a0, ta0
+	move	a1, ta0
 	PRINT(KERN_DEBUG "FP support: unknown fp op %08lx, ")
 	PRINT("please mail to ralf@gnu.org.\n")
 	UNLOCK_KERNEL
@@ -650,19 +649,19 @@
 	move	a1, $28
 	jal	force_sig
 
-	lw	ra, 16(sp)
-	addu	sp, 16
+	ld	ra, 0(sp)
+	daddu	sp, 16
 	jr	ra
 
 /*
  * Jump table for the lowest 6 bits of a cp1 instruction.
  */
 	.data
-lowtab:	.word	add,   sub,   mul,   div,   sqrt,  abs,   mov,   neg
-	.word	round.l,trunc.l,ceil.l,floor.l,round.w,trunc.w,ceil.w,floor.w
-	.word	unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
-	.word	unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
-	.word	cvt.s, cvt.d, unimp, unimp, cvt.w, cvt.l, unimp, unimp
-	.word	unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
-	.word	c.f,   c.un,  c.eq,  c.ueq, c.olt, c.ult, c.ole, c.ule
-	.word	c.sf,  c.ngle,c.seq, c.ngl, c.lt,  c.nge, c.le, c.ngt
+lowtab:	.dword	add,   sub,   mul,   div,   sqrt,  abs,   mov,   neg
+	.dword	round.l,trunc.l,ceil.l,floor.l,round.w,trunc.w,ceil.w,floor.w
+	.dword	unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
+	.dword	unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
+	.dword	cvt.s, cvt.d, unimp, unimp, cvt.w, cvt.l, unimp, unimp
+	.dword	unimp, unimp, unimp, unimp, unimp, unimp, unimp, unimp
+	.dword	c.f,   c.un,  c.eq,  c.ueq, c.olt, c.ult, c.ole, c.ule
+	.dword	c.sf,  c.ngle,c.seq, c.ngl, c.lt,  c.nge, c.le, c.ngt
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/syscall.c linux/arch/mips64/kernel/syscall.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/syscall.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips64/kernel/syscall.c	Sat May 13 08:30:17 2000
@@ -108,7 +108,6 @@
 	int error;
 	char * filename;
 
-	lock_kernel();
 	filename = getname((char *) (long)regs.regs[4]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
@@ -118,7 +117,6 @@
 	putname(filename);
 
 out:
-	unlock_kernel();
 	return error;
 }
 
@@ -322,4 +320,11 @@
 asmlinkage void bad_stack(void)
 {
 	do_exit(SIGSEGV);
+}
+
+asmlinkage int sys_pause(void)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	return -ERESTARTNOHAND;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/traps.c linux/arch/mips64/kernel/traps.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/traps.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/traps.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.5 2000/02/24 00:12:41 ralf Exp $
+/* $Id: traps.c,v 1.4 2000/01/20 23:50:27 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
@@ -328,8 +328,9 @@
 void do_ri(struct pt_regs *regs)
 {
 	lock_kernel();
-	printk("[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
-	       current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+	printk("Cpu%d[%s:%ld] Illegal instruction at %08lx ra=%08lx\n",
+	        smp_processor_id(), current->comm, current->pid, regs->cp0_epc, 
+		regs->regs[31]);
 	unlock_kernel();
 	if (compute_return_epc(regs))
 		return;
@@ -345,16 +346,27 @@
 		goto bad_cid;
 
 	regs->cp0_status |= ST0_CU1;
+#ifndef CONFIG_SMP
 	if (last_task_used_math == current)
 		return;
 
 	if (current->used_math) {		/* Using the FPU again.  */
-		lazy_fpu_switch(last_task_used_math);
+		lazy_fpu_switch(last_task_used_math, current);
 	} else {				/* First time FPU user.  */
+		lazy_fpu_switch(last_task_used_math, 0);
 		init_fpu();
 		current->used_math = 1;
 	}
 	last_task_used_math = current;
+#else
+	if (current->used_math) {
+		lazy_fpu_switch(0, current);
+	} else {
+		init_fpu();
+		current->used_math = 1;
+	}
+	current->flags |= PF_USEDFPU;
+#endif
 	return;
 
 bad_cid:
@@ -446,7 +458,6 @@
 		mips4_available = 1;
 		set_cp0_status(ST0_XX, ST0_XX);
 	}
-	mips4_available = 0;
 }
 
 static inline void go_64(void)
@@ -561,5 +572,4 @@
 
 	atomic_inc(&init_mm.mm_count);	/* XXX UP?  */
 	current->active_mm = &init_mm;
-	current_pgd = init_mm.pgd;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/kernel/unaligned.c linux/arch/mips64/kernel/unaligned.c
--- v2.3.99-pre8/linux/arch/mips64/kernel/unaligned.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/kernel/unaligned.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.2 2000/01/17 23:32:46 ralf Exp $
+/* $Id: unaligned.c,v 1.2 1999/11/23 17:12:50 ralf Exp $
  *
  * Handle unaligned accesses by emulation.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/Makefile linux/arch/mips64/lib/Makefile
--- v2.3.99-pre8/linux/arch/mips64/lib/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 1999/12/04 03:59:00 ralf Exp $
+# $Id: Makefile,v 1.2 1999/11/19 20:35:22 ralf Exp $
 #
 # Makefile for MIPS-specific library files..
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/csum_partial.S linux/arch/mips64/lib/csum_partial.S
--- v2.3.99-pre8/linux/arch/mips64/lib/csum_partial.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/csum_partial.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: csum_partial.S,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: csum_partial.S,v 1.1 1999/08/21 21:43: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/csum_partial_copy.c linux/arch/mips64/lib/csum_partial_copy.c
--- v2.3.99-pre8/linux/arch/mips64/lib/csum_partial_copy.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/csum_partial_copy.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: csum_partial_copy.c,v 1.3 2000/02/05 06:47:09 ralf Exp $
+/* $Id: csum_partial_copy.c,v 1.2 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/floppy-no.c linux/arch/mips64/lib/floppy-no.c
--- v2.3.99-pre8/linux/arch/mips64/lib/floppy-no.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/floppy-no.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: floppy-no.c,v 1.1 1999/08/21 21:43: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/floppy-std.c linux/arch/mips64/lib/floppy-std.c
--- v2.3.99-pre8/linux/arch/mips64/lib/floppy-std.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/floppy-std.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: floppy-std.c,v 1.1 1999/08/21 21:43: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/ide-no.c linux/arch/mips64/lib/ide-no.c
--- v2.3.99-pre8/linux/arch/mips64/lib/ide-no.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/ide-no.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ide-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: ide-no.c,v 1.1 1999/08/21 21:43: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/ide-std.c linux/arch/mips64/lib/ide-std.c
--- v2.3.99-pre8/linux/arch/mips64/lib/ide-std.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/ide-std.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ide-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: ide-std.c,v 1.1 1999/08/21 21:43: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/kbd-no.c linux/arch/mips64/lib/kbd-no.c
--- v2.3.99-pre8/linux/arch/mips64/lib/kbd-no.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/kbd-no.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: kbd-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: kbd-no.c,v 1.1 1999/08/21 21:43: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/kbd-std.c linux/arch/mips64/lib/kbd-std.c
--- v2.3.99-pre8/linux/arch/mips64/lib/kbd-std.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/kbd-std.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: kbd-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: kbd-std.c,v 1.1 1999/08/21 21:43:01 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/memcpy.S linux/arch/mips64/lib/memcpy.S
--- v2.3.99-pre8/linux/arch/mips64/lib/memcpy.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/memcpy.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: memcpy.S,v 1.4 2000/01/27 01:05:24 ralf Exp $
+/* $Id: memcpy.S,v 1.2 1999/10/19 20:51:51 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/memset.S linux/arch/mips64/lib/memset.S
--- v2.3.99-pre8/linux/arch/mips64/lib/memset.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/memset.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: memset.S,v 1.3 2000/01/16 01:37:19 ralf Exp $
+/* $Id: memset.S,v 1.3 2000/01/15 23:48: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/rtc-no.c linux/arch/mips64/lib/rtc-no.c
--- v2.3.99-pre8/linux/arch/mips64/lib/rtc-no.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/rtc-no.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: rtc-no.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: rtc-no.c,v 1.1 1999/08/21 21:43:01 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/rtc-std.c linux/arch/mips64/lib/rtc-std.c
--- v2.3.99-pre8/linux/arch/mips64/lib/rtc-std.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/rtc-std.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: rtc-std.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: rtc-std.c,v 1.1 1999/08/21 21:43:01 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/strlen_user.S linux/arch/mips64/lib/strlen_user.S
--- v2.3.99-pre8/linux/arch/mips64/lib/strlen_user.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/strlen_user.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: strlen_user.S,v 1.3 2000/01/17 23:32:46 ralf Exp $
+/* $Id: strlen_user.S,v 1.2 1999/11/19 20:35:22 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/strncpy_user.S linux/arch/mips64/lib/strncpy_user.S
--- v2.3.99-pre8/linux/arch/mips64/lib/strncpy_user.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/strncpy_user.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: strncpy_user.S,v 1.3 2000/01/17 23:32:46 ralf Exp $
+/* $Id: strncpy_user.S,v 1.2 1999/11/19 20:35:23 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/strnlen_user.S linux/arch/mips64/lib/strnlen_user.S
--- v2.3.99-pre8/linux/arch/mips64/lib/strnlen_user.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/strnlen_user.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: strnlen_user.S,v 1.1 1999/12/04 03:59:00 ralf Exp $
+/* $Id: strnlen_user.S,v 1.1 1999/11/19 20:35:23 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/lib/watch.S linux/arch/mips64/lib/watch.S
--- v2.3.99-pre8/linux/arch/mips64/lib/watch.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/lib/watch.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: watch.S,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: watch.S,v 1.1 1999/08/21 21:43:01 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/Makefile linux/arch/mips64/mm/Makefile
--- v2.3.99-pre8/linux/arch/mips64/mm/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/mm/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.5 2000/02/24 00:12:41 ralf Exp $
+# $Id: Makefile,v 1.4 2000/01/17 23:32:46 ralf Exp $
 #
 # Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/andes.c linux/arch/mips64/mm/andes.c
--- v2.3.99-pre8/linux/arch/mips64/mm/andes.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/mm/andes.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: andes.c,v 1.6 2000/02/24 00:12:41 ralf Exp $
+/* $Id: andes.c,v 1.7 2000/03/13 22:43:25 kanoj 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
@@ -91,7 +91,7 @@
 static void
 andes_flush_cache_mm(struct mm_struct *mm)
 {
-	if (mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -103,7 +103,7 @@
 andes_flush_cache_range(struct mm_struct *mm, unsigned long start,
                         unsigned long end)
 {
-	if (mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 
 #ifdef DEBUG_CACHE
@@ -129,7 +129,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if (mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -244,17 +244,17 @@
 
 static void andes_flush_tlb_mm(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 
 #ifdef DEBUG_TLB
 		printk("[tlbmm<%d>]", mm->context);
 #endif
-		save_and_cli(flags);
-		get_new_mmu_context(mm, asid_cache);
+		__save_and_cli(flags);
+		get_new_cpu_mmu_context(mm, smp_processor_id());
 		if(mm == current->mm)
-			set_entryhi(mm->context & 0xff);
-		restore_flags(flags);
+			set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff);
+		__restore_flags(flags);
 	}
 }
 
@@ -262,7 +262,7 @@
 andes_flush_tlb_range(struct mm_struct *mm, unsigned long start,
                       unsigned long end)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 		int size;
 
@@ -270,12 +270,12 @@
 		printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff),
 		       start, end);
 #endif
-		save_and_cli(flags);
+		__save_and_cli(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		size = (size + 1) >> 1;
 		if(size <= NTLB_ENTRIES_HALF) {
 			int oldpid = (get_entryhi() & 0xff);
-			int newpid = (mm->context & 0xff);
+			int newpid = (CPU_CONTEXT(smp_processor_id(), mm) & 0xff);
 
 			start &= (PAGE_MASK << 1);
 			end += ((PAGE_SIZE << 1) - 1);
@@ -300,9 +300,10 @@
 			}
 			set_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, asid_cache);
+			get_new_cpu_mmu_context(mm, smp_processor_id());
 			if(mm == current->mm)
-				set_entryhi(mm->context & 0xff);
+				set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 
+									0xff);
 		}
 		__restore_flags(flags);
 	}
@@ -311,16 +312,16 @@
 static void
 andes_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
-	if(vma->vm_mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) != 0) {
 		unsigned long flags;
 		int oldpid, newpid, idx;
 
 #ifdef DEBUG_TLB
 		printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
 #endif
-		newpid = (vma->vm_mm->context & 0xff);
+		newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff);
 		page &= (PAGE_MASK << 1);
-		save_and_cli(flags);
+		__save_and_cli(flags);
 		oldpid = (get_entryhi() & 0xff);
 		set_entryhi(page | newpid);
 		BARRIER;
@@ -338,7 +339,7 @@
 	finish:
 		BARRIER;
 		set_entryhi(oldpid);
-		restore_flags(flags);
+		__restore_flags(flags);
 	}
 }
 
@@ -354,17 +355,16 @@
 	pte_t *ptep;
 	int idx, pid;
 
+	__save_and_cli(flags);
 	pid = get_entryhi() & 0xff;
 
-#ifdef DEBUG_TLB
-	if((pid != (vma->vm_mm->context & 0xff)) ||
-           (vma->vm_mm->context == 0)) {
-		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
-		       (int) (vma->vm_mm->context & 0xff), pid);
+	if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) ||
+	   (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) == 0)) {
+		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d 
+			tlbpid=%d\n", (int) (CPU_CONTEXT(smp_processor_id(), 
+			vma->vm_mm) & 0xff), pid);
 	}
-#endif
 
-	__save_and_cli(flags);
 	address &= (PAGE_MASK << 1);
 	set_entryhi(address | (pid));
 	pgdp = pgd_offset(vma->vm_mm, address);
@@ -398,6 +398,7 @@
 
 static void andes_show_regs(struct pt_regs *regs)
 {
+	printk("Cpu %d\n", smp_processor_id());
 	/* Saved main processor registers. */
 	printk("$0      : %016lx %016lx %016lx %016lx\n",
 	       0UL, regs->regs[1], regs->regs[2], regs->regs[3]);
@@ -469,7 +470,7 @@
 	write_32bit_cp0_register(CP0_PAGEMASK, PM_4K);
 
         /* From this point on the ARC firmware is dead.  */
-	flush_tlb_all();
+	_flush_tlb_all();
 
         /* Did I tell you that ARC SUCKS?  */
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/extable.c linux/arch/mips64/mm/extable.c
--- v2.3.99-pre8/linux/arch/mips64/mm/extable.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/mm/extable.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: extable.c,v 1.2 1999/12/04 03:59:00 ralf Exp $
+/* $Id: extable.c,v 1.2 1999/11/23 17:12:50 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/fault.c linux/arch/mips64/mm/fault.c
--- v2.3.99-pre8/linux/arch/mips64/mm/fault.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/mips64/mm/fault.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: fault.c,v 1.6 2000/02/18 00:24:31 ralf Exp $
+/* $Id: fault.c,v 1.7 2000/03/13 22:43:25 kanoj 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
@@ -27,18 +27,36 @@
 #include <asm/softirq.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/ptrace.h>
 
 #define development_version (LINUX_VERSION_CODE & 0x100)
 
 extern void die(char *, struct pt_regs *, unsigned long write);
 
-unsigned long asid_cache;
-
 /*
  * Macro for exception fixup code to access integer registers.
  */
 #define dpf_reg(r) (regs->regs[r])
 
+asmlinkage void
+dodebug(abi64_no_regargs, struct pt_regs regs)
+{
+	printk("Got syscall %d, cpu %d proc %s:%d epc 0x%lx\n", regs.regs[2], smp_processor_id(), current->comm, current->pid, regs.cp0_epc);
+}
+
+asmlinkage void
+dodebug2(abi64_no_regargs, struct pt_regs regs)
+{
+	unsigned long retaddr;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		"add %0,$0,$31\n\t"
+		".set reorder"
+		: "=r" (retaddr));
+	printk("Got exception 0x%lx at 0x%lx\n", retaddr, regs.cp0_epc);
+}
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -59,9 +77,9 @@
 	 */
 	if (in_interrupt() || mm == &init_mm)
 		goto no_context;
-#if 0
-	printk("[%s:%d:%08lx:%ld:%08lx]\n", current->comm, current->pid,
-	       address, write, regs->cp0_epc);
+#if DEBUG_MIPS64
+	printk("Cpu%d[%s:%d:%08lx:%ld:%08lx]\n", smp_processor_id(), current->comm,
+		current->pid, address, write, regs->cp0_epc);
 #endif
 	down(&mm->mmap_sem);
 	vma = find_vma(mm, address);
@@ -93,12 +111,17 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	{
-		int fault = handle_mm_fault(mm, vma, address, write);
-		if (fault < 0)
-			goto out_of_memory;
-		if (!fault)
-			goto do_sigbus;
+	switch (handle_mm_fault(mm, vma, address, write)) {
+	case 1:
+		tsk->min_flt++;
+		break;
+	case 2:
+		tsk->maj_flt++;
+		break;
+	case 0:
+		goto do_sigbus;
+	default:
+		goto out_of_memory;
 	}
 
 	up(&mm->mmap_sem);
@@ -150,10 +173,9 @@
 	 * Oops. The kernel tried to access some bad page. We'll have to
 	 * terminate things with extreme prejudice.
 	 */
-	printk(KERN_ALERT "Unable to handle kernel paging request at virtual "
+	printk(KERN_ALERT "Cpu %d Unable to handle kernel paging request at "
 	       "address %08lx, epc == %08lx, ra == %08lx\n",
-	       address, regs->cp0_epc, regs->regs[31]);
-while(1);
+	       smp_processor_id(), address, regs->cp0_epc, regs->regs[31]);
 	die("Oops", regs, write);
 	do_exit(SIGKILL);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/init.c linux/arch/mips64/mm/init.c
--- v2.3.99-pre8/linux/arch/mips64/mm/init.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/mm/init.c	Sat May 13 08:30:17 2000
@@ -87,6 +87,8 @@
 	if (ret) {
 		init = pgd_offset(&init_mm, 0);
 		pgd_init((unsigned long)ret);
+		memcpy(ret + USER_PTRS_PER_PGD, init + USER_PTRS_PER_PGD,
+			(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
 	}
 	return ret;
 }
@@ -250,7 +252,7 @@
 
 	bp = pte_val(BAD_PAGE);
  	p = (unsigned long *) page;
-	end = p + PTRS_PER_PTE;
+	end = p + (2 * PTRS_PER_PTE);
 
 	while (p < end) {
 		p[0] = p[1] = p[2] = p[3] =
@@ -278,7 +280,7 @@
 	unsigned long page;
 
 	page = (unsigned long) invalid_pmd_table;
-	pte_init(page);
+	pmd_init(page);
 
 	return (pmd_t *) page;
 }
@@ -345,8 +347,8 @@
 
 	/* Initialize the entire pgd.  */
 	pgd_init((unsigned long)swapper_pg_dir);
-	pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2);
 	pmd_init((unsigned long)invalid_pmd_table);
+	memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE);
 
 	max_dma =  virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 	low = max_low_pfn;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/loadmmu.c linux/arch/mips64/mm/loadmmu.c
--- v2.3.99-pre8/linux/arch/mips64/mm/loadmmu.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/mm/loadmmu.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.6 2000/02/24 00:12:41 ralf Exp $
+/* $Id: loadmmu.c,v 1.5 2000/01/27 01:05:24 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/r4xx0.c linux/arch/mips64/mm/r4xx0.c
--- v2.3.99-pre8/linux/arch/mips64/mm/r4xx0.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/mm/r4xx0.c	Sat May 13 08:30:17 2000
@@ -784,7 +784,7 @@
 	struct vm_area_struct *vma;
 	unsigned long flags;
 
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 	start &= PAGE_MASK;
@@ -793,7 +793,8 @@
 #endif
 	vma = find_vma(mm, start);
 	if(vma) {
-		if(mm->context != current->mm->context) {
+		if (CPU_CONTEXT(smp_processor_id(), mm) !=
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 			r4k_flush_cache_all_s16d16i16();
 		} else {
 			pgd_t *pgd;
@@ -822,7 +823,7 @@
 	struct vm_area_struct *vma;
 	unsigned long flags;
 
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 	start &= PAGE_MASK;
@@ -831,7 +832,8 @@
 #endif
 	vma = find_vma(mm, start);
 	if(vma) {
-		if(mm->context != current->mm->context) {
+		if (CPU_CONTEXT(smp_processor_id(), mm) !=
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 			r4k_flush_cache_all_s32d16i16();
 		} else {
 			pgd_t *pgd;
@@ -860,7 +862,7 @@
 	struct vm_area_struct *vma;
 	unsigned long flags;
 
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 	start &= PAGE_MASK;
@@ -869,7 +871,8 @@
 #endif
 	vma = find_vma(mm, start);
 	if(vma) {
-		if(mm->context != current->mm->context) {
+		if (CPU_CONTEXT(smp_processor_id(), mm) !=
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 			r4k_flush_cache_all_s64d16i16();
 		} else {
 			pgd_t *pgd;
@@ -898,7 +901,7 @@
 	struct vm_area_struct *vma;
 	unsigned long flags;
 
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 	start &= PAGE_MASK;
@@ -907,7 +910,8 @@
 #endif
 	vma = find_vma(mm, start);
 	if(vma) {
-		if(mm->context != current->mm->context) {
+		if (CPU_CONTEXT(smp_processor_id(), mm) !=
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 			r4k_flush_cache_all_s128d16i16();
 		} else {
 			pgd_t *pgd;
@@ -936,7 +940,7 @@
 	struct vm_area_struct *vma;
 	unsigned long flags;
 
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 	start &= PAGE_MASK;
@@ -945,7 +949,8 @@
 #endif
 	vma = find_vma(mm, start);
 	if(vma) {
-		if(mm->context != current->mm->context) {
+		if (CPU_CONTEXT(smp_processor_id(), mm) !=
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 			r4k_flush_cache_all_s32d32i32();
 		} else {
 			pgd_t *pgd;
@@ -974,7 +979,7 @@
 	struct vm_area_struct *vma;
 	unsigned long flags;
 
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 	start &= PAGE_MASK;
@@ -983,7 +988,8 @@
 #endif
 	vma = find_vma(mm, start);
 	if(vma) {
-		if(mm->context != current->mm->context) {
+		if (CPU_CONTEXT(smp_processor_id(), mm) !=
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 			r4k_flush_cache_all_s64d32i32();
 		} else {
 			pgd_t *pgd;
@@ -1012,7 +1018,7 @@
 	struct vm_area_struct *vma;
 	unsigned long flags;
 
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		return;
 
 	start &= PAGE_MASK;
@@ -1021,7 +1027,8 @@
 #endif
 	vma = find_vma(mm, start);
 	if(vma) {
-		if(mm->context != current->mm->context) {
+		if (CPU_CONTEXT(smp_processor_id(), mm) !=
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 			r4k_flush_cache_all_s128d32i32();
 		} else {
 			pgd_t *pgd;
@@ -1047,7 +1054,7 @@
 r4k_flush_cache_range_d16i16(struct mm_struct *mm, unsigned long start,
                              unsigned long end)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 
 #ifdef DEBUG_CACHE
@@ -1063,7 +1070,7 @@
 r4k_flush_cache_range_d32i32(struct mm_struct *mm, unsigned long start,
                              unsigned long end)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 
 #ifdef DEBUG_CACHE
@@ -1082,7 +1089,7 @@
  */
 static void r4k_flush_cache_mm_s16d16i16(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1092,7 +1099,7 @@
 
 static void r4k_flush_cache_mm_s32d16i16(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1102,7 +1109,7 @@
 
 static void r4k_flush_cache_mm_s64d16i16(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1112,7 +1119,7 @@
 
 static void r4k_flush_cache_mm_s128d16i16(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1122,7 +1129,7 @@
 
 static void r4k_flush_cache_mm_s32d32i32(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1132,7 +1139,7 @@
 
 static void r4k_flush_cache_mm_s64d32i32(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1142,7 +1149,7 @@
 
 static void r4k_flush_cache_mm_s128d32i32(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1152,7 +1159,7 @@
 
 static void r4k_flush_cache_mm_d16i16(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1162,7 +1169,7 @@
 
 static void r4k_flush_cache_mm_d32i32(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 #ifdef DEBUG_CACHE
 		printk("cmm[%d]", (int)mm->context);
 #endif
@@ -1184,7 +1191,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1209,7 +1216,8 @@
 	 * for every cache flush operation.  So we do indexed flushes
 	 * in that case, which doesn't overly flush the cache too much.
 	 */
-	if(mm->context != current->mm->context) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 		/* Do indexed flush, too much work to get the (possible)
 		 * tlb refills to work correctly.
 		 */
@@ -1238,7 +1246,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1262,7 +1270,8 @@
 	 * for every cache flush operation.  So we do indexed flushes
 	 * in that case, which doesn't overly flush the cache too much.
 	 */
-	if(mm->context != current->mm->context) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 		/* Do indexed flush, too much work to get the (possible)
 		 * tlb refills to work correctly.
 		 */
@@ -1291,7 +1300,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1316,7 +1325,8 @@
 	 * for every cache flush operation.  So we do indexed flushes
 	 * in that case, which doesn't overly flush the cache too much.
 	 */
-	if(mm->context != current->mm->context) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 		/* Do indexed flush, too much work to get the (possible)
 		 * tlb refills to work correctly.
 		 */
@@ -1345,7 +1355,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1370,7 +1380,8 @@
 	 * for every cache flush operation.  So we do indexed flushes
 	 * in that case, which doesn't overly flush the cache too much.
 	 */
-	if(mm->context != current->mm->context) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 		/*
 		 * Do indexed flush, too much work to get the (possible)
 		 * tlb refills to work correctly.
@@ -1400,7 +1411,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1426,7 +1437,8 @@
 	 * for every cache flush operation.  So we do indexed flushes
 	 * in that case, which doesn't overly flush the cache too much.
 	 */
-	if(mm->context != current->mm->context) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 		/*
 		 * Do indexed flush, too much work to get the (possible)
 		 * tlb refills to work correctly.
@@ -1456,7 +1468,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1482,7 +1494,8 @@
 	 * for every cache flush operation.  So we do indexed flushes
 	 * in that case, which doesn't overly flush the cache too much.
 	 */
-	if(mm->context != current->mm->context) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 		/*
 		 * Do indexed flush, too much work to get the (possible)
 		 * tlb refills to work correctly.
@@ -1512,7 +1525,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1537,7 +1550,8 @@
 	 * for every cache flush operation.  So we do indexed flushes
 	 * in that case, which doesn't overly flush the cache too much.
 	 */
-	if(mm->context != current->mm->context) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 
+				CPU_CONTEXT(smp_processor_id(), current->mm)) {
 		/* Do indexed flush, too much work to get the (possible)
 		 * tlb refills to work correctly.
 		 */
@@ -1566,7 +1580,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1622,7 +1636,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -1681,7 +1695,7 @@
 	 * If ownes no valid ASID yet, cannot possibly have gotten
 	 * this page into the cache.
 	 */
-	if(mm->context == 0)
+	if (CPU_CONTEXT(smp_processor_id(), mm) == 0)
 		return;
 
 #ifdef DEBUG_CACHE
@@ -2010,7 +2024,7 @@
 	printk("[tlball]");
 #endif
 
-	save_and_cli(flags);
+	__save_and_cli(flags);
 	/* Save old context and create impossible VPN2 value */
 	old_ctx = (get_entryhi() & 0xff);
 	set_entryhi(KSEG0);
@@ -2030,29 +2044,29 @@
 	}
 	BARRIER;
 	set_entryhi(old_ctx);
-	restore_flags(flags);
+	__restore_flags(flags);
 }
 
 static void r4k_flush_tlb_mm(struct mm_struct *mm)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 
 #ifdef DEBUG_TLB
 		printk("[tlbmm<%d>]", mm->context);
 #endif
-		save_and_cli(flags);
-		get_new_mmu_context(mm, asid_cache);
+		__save_and_cli(flags);
+		get_new_cpu_mmu_context(mm, smp_processor_id());
 		if(mm == current->mm)
-			set_entryhi(mm->context & 0xff);
-		restore_flags(flags);
+			set_entryhi(CPU_CONTEXT(smp_processor_id(), mm) & 0xff);
+		__restore_flags(flags);
 	}
 }
 
 static void r4k_flush_tlb_range(struct mm_struct *mm, unsigned long start,
 				unsigned long end)
 {
-	if(mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), mm) != 0) {
 		unsigned long flags;
 		int size;
 
@@ -2060,12 +2074,12 @@
 		printk("[tlbrange<%02x,%08lx,%08lx>]", (mm->context & 0xff),
 		       start, end);
 #endif
-		save_and_cli(flags);
+		__save_and_cli(flags);
 		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
 		size = (size + 1) >> 1;
 		if(size <= NTLB_ENTRIES_HALF) {
 			int oldpid = (get_entryhi() & 0xff);
-			int newpid = (mm->context & 0xff);
+			int newpid = (CPU_CONTEXT(smp_processor_id(), mm) & 0xff);
 
 			start &= (PAGE_MASK << 1);
 			end += ((PAGE_SIZE << 1) - 1);
@@ -2090,9 +2104,10 @@
 			}
 			set_entryhi(oldpid);
 		} else {
-			get_new_mmu_context(mm, asid_cache);
+			get_new_cpu_mmu_context(mm, smp_processor_id());
 			if(mm == current->mm)
-				set_entryhi(mm->context & 0xff);
+				set_entryhi(CPU_CONTEXT(smp_processor_id(), 
+								mm) & 0xff);
 		}
 		__restore_flags(flags);
 	}
@@ -2100,16 +2115,16 @@
 
 static void r4k_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
-	if(vma->vm_mm->context != 0) {
+	if (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) != 0) {
 		unsigned long flags;
 		int oldpid, newpid, idx;
 
 #ifdef DEBUG_TLB
 		printk("[tlbpage<%d,%08lx>]", vma->vm_mm->context, page);
 #endif
-		newpid = (vma->vm_mm->context & 0xff);
+		newpid = (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff);
 		page &= (PAGE_MASK << 1);
-		save_and_cli(flags);
+		__save_and_cli(flags);
 		oldpid = (get_entryhi() & 0xff);
 		set_entryhi(page | newpid);
 		BARRIER;
@@ -2127,7 +2142,7 @@
 	finish:
 		BARRIER;
 		set_entryhi(oldpid);
-		restore_flags(flags);
+		__restore_flags(flags);
 	}
 }
 
@@ -2150,16 +2165,18 @@
 	pte_t *ptep;
 	int idx, pid;
 
+	__save_and_cli(flags);
 	pid = (get_entryhi() & 0xff);
 
 #ifdef DEBUG_TLB
-	if((pid != (vma->vm_mm->context & 0xff)) || (vma->vm_mm->context == 0)) {
-		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d tlbpid=%d\n",
-		       (int) (vma->vm_mm->context & 0xff), pid);
+	if((pid != (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) & 0xff)) ||
+	   (CPU_CONTEXT(smp_processor_id(), vma->vm_mm) == 0)) {
+		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%d
+			tlbpid=%d\n", (int) (CPU_CONTEXT(smp_processor_id(),
+			vma->vm_mm) & 0xff), pid);
 	}
 #endif
 
-	__save_and_cli(flags);
 	address &= (PAGE_MASK << 1);
 	set_entryhi(address | (pid));
 	pgdp = pgd_offset(vma->vm_mm, address);
@@ -2538,5 +2555,5 @@
 	 *     be set for 4kb pages.
 	 */
 	write_32bit_cp0_register(CP0_PAGEMASK, PM_4K);
-	flush_tlb_all();
+	_flush_tlb_all();
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/mm/umap.c linux/arch/mips64/mm/umap.c
--- v2.3.99-pre8/linux/arch/mips64/mm/umap.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/mm/umap.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: umap.c,v 1.5 2000/02/04 07:40:24 ralf Exp $
+/* $Id: umap.c,v 1.4 2000/01/29 01:41:59 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/Makefile linux/arch/mips64/sgi-ip22/Makefile
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.4 2000/01/21 22:34:03 ralf Exp $
+# $Id: Makefile,v 1.1 1999/08/20 21:13:33 ralf Exp $
 #
 # Makefile for the SGI specific kernel interface routines
 # under Linux.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-berr.c linux/arch/mips64/sgi-ip22/ip22-berr.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-berr.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-berr.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-berr.c,v 1.2 2000/02/24 00:12:41 ralf Exp $
+/* $Id: ip22-berr.c,v 1.1 2000/01/21 22:34:03 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-hpc.c linux/arch/mips64/sgi-ip22/ip22-hpc.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-hpc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-hpc.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-hpc.c,v 1.2 1999/12/04 03:59:01 ralf Exp $
+/* $Id: ip22-hpc.c,v 1.2 1999/10/19 20:51:52 ralf Exp $
  *
  * ip22-hpc.c: Routines for generic manipulation of the HPC controllers.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-int.c linux/arch/mips64/sgi-ip22/ip22-int.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-int.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-int.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-int.c,v 1.4 2000/02/04 07:40:24 ralf Exp $
+/* $Id: ip22-int.c,v 1.5 2000/03/02 02:36:50 ralf Exp $
  *
  * indy_int.c: Routines for generic manipulation of the INT[23] ASIC
  *             found on INDY workstations..
@@ -37,6 +37,24 @@
 #include <asm/sgi/sgint23.h>
 #include <asm/sgialib.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.
+ */
+
+irq_cpustat_t irq_stat [NR_CPUS];
+
 struct sgi_int2_regs *sgi_i2regs;
 struct sgi_int3_regs *sgi_i3regs;
 struct sgi_ioc_ints *ioc_icontrol;
@@ -272,7 +290,7 @@
 	int do_random, cpu;
 
 	cpu = smp_processor_id();
-	irq_enter(cpu);
+	irq_enter(cpu, irq);
 	kstat.irqs[0][irq]++;
 
 	printk("Got irq %d, press a key.", irq);
@@ -308,7 +326,7 @@
 			add_interrupt_randomness(irq);
 		__cli();
 	}
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
 
 	/* unmasking and bottom half handling is done magically for us. */
 }
@@ -433,10 +451,10 @@
 		action = local_irq_action[irq];
 	}
 
-	irq_enter(cpu);
+	irq_enter(cpu, irq);
 	kstat.irqs[0][irq + 16]++;
 	action->handler(irq, action->dev_id, regs);
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
 }
 
 void indy_local1_irqdispatch(struct pt_regs *regs)
@@ -457,10 +475,10 @@
 		irq = lc1msk_to_irqnr[mask];
 		action = local_irq_action[irq];
 	}
-	irq_enter(cpu);
+	irq_enter(cpu, irq);
 	kstat.irqs[0][irq + 24]++;
 	action->handler(irq, action->dev_id, regs);
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
 }
 
 void indy_buserror_irq(struct pt_regs *regs)
@@ -468,13 +486,13 @@
 	int cpu = smp_processor_id();
 	int irq = 6;
 
-	irq_enter(cpu);
+	irq_enter(cpu, irq);
 	kstat.irqs[0][irq]++;
 	printk("Got a bus error IRQ, shouldn't happen yet\n");
 	show_regs(regs);
 	printk("Spinning...\n");
 	while(1);
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
 }
 
 /* Misc. crap just to keep the kernel linking... */
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-irq.S linux/arch/mips64/sgi-ip22/ip22-irq.S
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-irq.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-irq.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-irq.S,v 1.2 1999/12/04 03:59:01 ralf Exp $
+/* $Id: ip22-irq.S,v 1.1 1999/08/20 21:13: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-mc.c linux/arch/mips64/sgi-ip22/ip22-mc.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-mc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-mc.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-mc.c,v 1.2 1999/12/04 03:59:01 ralf Exp $
+/* $Id: ip22-mc.c,v 1.2 1999/10/19 20:51: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-reset.c linux/arch/mips64/sgi-ip22/ip22-reset.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-reset.c	Thu May 11 15:30:06 2000
+++ linux/arch/mips64/sgi-ip22/ip22-reset.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-reset.c,v 1.3 1999/12/04 03:59:01 ralf Exp $
+/* $Id: ip22-reset.c,v 1.3 1999/10/08 21:07:51 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-rtc.c linux/arch/mips64/sgi-ip22/ip22-rtc.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-rtc.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-rtc.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-rtc.c,v 1.2 1999/12/04 03:59:01 ralf Exp $
+/* $Id: ip22-rtc.c,v 1.1 1999/08/20 21:13:34 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-sc.c linux/arch/mips64/sgi-ip22/ip22-sc.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-sc.c	Mon Mar 27 08:08:22 2000
+++ linux/arch/mips64/sgi-ip22/ip22-sc.c	Sat May 13 08:30:17 2000
@@ -27,7 +27,6 @@
 #define SC_SIZE 0x00080000
 #define SC_LINE 32
 #define CI_MASK (SC_SIZE - SC_LINE)
-#define SC_ROUND(n) ((n) + SC_LINE - 1)
 #define SC_INDEX(n) ((n) & CI_MASK)
 
 static inline void indy_sc_wipe(unsigned long first, unsigned long last)
@@ -53,9 +52,13 @@
 #ifdef DEBUG_CACHE
 	printk("indy_sc_wback_invalidate[%08lx,%08lx]", addr, size);
 #endif
+
+	if (!size)
+		return;
+
 	/* Which lines to flush?  */
 	first_line = SC_INDEX(addr);
-	last_line = SC_INDEX(SC_ROUND(addr + size));
+	last_line = SC_INDEX(addr + size - 1);
 
 	__save_and_cli(flags);
 	if (first_line <= last_line) {
@@ -63,11 +66,8 @@
 		goto out;
 	}
 
-	/* Cache index wrap around.  Due to the way the buddy system works
-	   this case should not happen.  We're prepared to handle it,
-	   though. */
-	indy_sc_wipe(last_line, SC_SIZE);
-	indy_sc_wipe(0, first_line);
+	indy_sc_wipe(first_line, SC_SIZE - SC_LINE);
+	indy_sc_wipe(0, last_line);
 out:
 	__restore_flags(flags);
 }
@@ -159,7 +159,6 @@
 
 void __init indy_sc_init(void)
 {
-return;  /* Not for now, debugging ... */
 	if (indy_sc_probe()) {
 		indy_sc_enable();
 		bcops = &indy_sc_ops;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-setup.c linux/arch/mips64/sgi-ip22/ip22-setup.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-setup.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-setup.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip22-setup.c,v 1.5 2000/01/27 01:05:24 ralf Exp $
+/* $Id: ip22-setup.c,v 1.4 1999/10/08 21:07:51 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-timer.c linux/arch/mips64/sgi-ip22/ip22-timer.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/ip22-timer.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/ip22-timer.c	Sat May 13 08:30:17 2000
@@ -267,12 +267,12 @@
 	int cpu = smp_processor_id();
 	int irq = 4;
 
-	irq_enter(cpu);
+	irq_enter(cpu, irq);
 	kstat.irqs[0][irq]++;
 	printk("indy_8254timer_irq: Whoops, should not have gotten this IRQ\n");
 	prom_getchar();
 	ArcEnterInteractiveMode();
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
 }
 
 void do_gettimeofday(struct timeval *tv)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/system.c linux/arch/mips64/sgi-ip22/system.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/system.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/system.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: system.c,v 1.3 1999/12/04 03:59:01 ralf Exp $
+/* $Id: system.c,v 1.3 1999/10/19 20:51: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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip22/time.c linux/arch/mips64/sgi-ip22/time.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip22/time.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip22/time.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.2 1999/12/04 03:59:01 ralf Exp $
+/* $Id: time.c,v 1.1 1999/08/20 21:13:34 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/Makefile linux/arch/mips64/sgi-ip27/Makefile
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.4 2000/02/18 00:24:31 ralf Exp $
+# $Id: Makefile,v 1.3 2000/02/04 08:41:40 kanoj Exp $
 #
 # Makefile for the IP27 specific kernel interface routines under Linux.
 #
@@ -11,6 +11,6 @@
 L_TARGET = ip27.a
 L_OBJS  = ip27-berr.o ip27-irq.o ip27-irq-glue.o ip27-klconfig.o \
 	  ip27-memory.o ip27-pci.o ip27-pci-dma.o ip27-reset.o ip27-setup.o \
-	  ip27-timer.o ip27-init.o
+	  ip27-timer.o ip27-init.o ip27-nmi.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/TODO linux/arch/mips64/sgi-ip27/TODO
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/TODO	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/TODO	Sat May 13 08:30:17 2000
@@ -4,8 +4,20 @@
 3. Need to figure out why address swaizzling is needed in inw/outw for 
 Qlogic scsi controllers.
 4. Need to integrate ip27-klconfig.c:find_lboard and 
-ip27-init.c:find_lbaord_real.
+ip27-init.c:find_lbaord_real. DONE
 5. Is it okay to set calias space on all nodes as 0, instead of 8k as
 in irix?
 6. Investigate why things do not work without the setup_test() call
 being invoked on all nodes in ip27-memory.c.
+7. Too many CLIs in the locore handlers :
+For the low level handlers set up by set_except_vector(), 
+__tlb_refill_debug_tramp, __xtlb_refill_debug_tramp and cacheerror,
+investigate whether the code should do CLI, STI or KMODE. 
+8. Too many do_page_faults invoked - investigate.
+9. start_thread must turn off UX64 ... and define tlb_refill_debug.
+10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
+does not agree with pgd_bad/pmd_bad.
+11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node.
+This might need to change later. Only the timer intr is set up to be
+received on both Cpu A and B. (ip27_do_irq()/bridge_startup())
+13. Cache flushing (specially the SMP version) has to be investigated.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-berr.c linux/arch/mips64/sgi-ip27/ip27-berr.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-berr.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/ip27-berr.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27-berr.c,v 1.1 2000/01/20 23:50:27 ralf Exp $
+/* $Id: ip27-berr.c,v 1.1 2000/01/20 22:50:29 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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-init.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips64/sgi-ip27/ip27-init.c	Mon May 15 12:10:26 2000
@@ -1,5 +1,11 @@
+#include <linux/config.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
 #include <linux/mmzone.h>	/* for numnodes */
+#include <linux/mm.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
 #include <asm/sn/types.h>
 #include <asm/sn/sn0/addrs.h>
 #include <asm/sn/sn0/hubni.h>
@@ -8,16 +14,33 @@
 #include <asm/ioc3.h>
 #include <asm/mipsregs.h>
 #include <asm/sn/gda.h>
+#include <asm/sn/intr.h>
+#include <asm/current.h>
+#include <asm/smp.h>
+#include <asm/processor.h>
+#include <asm/mmu_context.h>
+#include <asm/sn/launch.h>
+#include <asm/sn/sn_private.h>
+#include <asm/sn/sn0/ip27.h>
 
-typedef unsigned long cpumask_t;	/* into asm/sn/types.h */
-typedef unsigned long cpuid_t;
+#define CPU_NONE		(cpuid_t)-1
 
 #define	CPUMASK_CLRALL(p)	(p) = 0
 #define CPUMASK_SETB(p, bit)	(p) |= 1 << (bit)
+#define CPUMASK_CLRB(p, bit)	(p) &= ~(1ULL << (bit))
+#define CPUMASK_TSTB(p, bit)	((p) & (1ULL << (bit)))
+
+#define CNODEMASK_CLRALL(p)	(p) = 0
+#define CNODEMASK_TSTB(p, bit)	((p) & (1ULL << (bit)))
+#define CNODEMASK_SETB(p, bit)	((p) |= 1ULL << (bit))
 
 cpumask_t	boot_cpumask;
+static volatile cpumask_t boot_barrier;
 hubreg_t	region_mask = 0;
 static int	fine_mode = 0;
+int		maxcpus;
+static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED;
+static cnodemask_t hub_init_mask;
 
 cnodeid_t	nasid_to_compact_node[MAX_NASIDS];
 nasid_t		compact_to_nasid_node[MAX_COMPACT_NODES];
@@ -47,51 +70,6 @@
 		>> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE);
 }
 
-lboard_t * find_lboard_real(lboard_t *start, unsigned char brd_type)
-{
-	/* Search all boards stored on this node. */
-	while (start) {
-		if (start->brd_type == brd_type)
-			return start;
-		start = KLCF_NEXT(start);
-	}
-	/* Didn't find it. */
-	return (lboard_t *)NULL;
-}
-
-klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
-{
-	int index, j;
-
-	if (kli == (klinfo_t *)NULL) {
-		index = 0;
-	} else {
-		for (j = 0; j < KLCF_NUM_COMPS(brd); j++)
-			if (kli == KLCF_COMP(brd, j))
-				break;
-		index = j;
-		if (index == KLCF_NUM_COMPS(brd)) {
-			printk("find_component: Bad pointer: 0x%p\n", kli);
-			return (klinfo_t *)NULL;
-		}
-		index++;		/* next component */
-	}
-
-	for (; index < KLCF_NUM_COMPS(brd); index++) {
-		kli = KLCF_COMP(brd, index);
-		if (KLCF_COMP_TYPE(kli) == struct_type)
-			return kli;
-	}
-
-	/* Didn't find it. */
-	return (klinfo_t *)NULL;
-}
-
-klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type)
-{
-	return find_component(brd, (klinfo_t *)NULL, struct_type);
-}
-
 nasid_t get_actual_nasid(lboard_t *brd)
 {
 	klhub_t *hub;
@@ -117,7 +95,7 @@
 	int cpus_found = 0;
 	cpuid_t cpuid;
 
-	brd = find_lboard_real((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
 
 	do {
 		acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
@@ -138,7 +116,7 @@
 		}
 		brd = KLCF_NEXT(brd);
 		if (brd)
-			brd = find_lboard_real(brd,KLTYPE_IP27);
+			brd = find_lboard(brd,KLTYPE_IP27);
 		else
 			break;
 	} while (brd);
@@ -182,9 +160,38 @@
 	return(highest + 1);
 }
 
+void alloc_cpupda(int i)
+{
+	cnodeid_t	node;
+	nasid_t		nasid;
+
+	node = get_cpu_cnode(i);
+	nasid = COMPACT_TO_NASID_NODEID(node);
+
+	cputonasid(i) = nasid;
+	cputocnode(i) = node;
+	cputoslice(i) = get_cpu_slice(i);
+}
+
+int cpu_enabled(cpuid_t cpu)
+{
+	if (cpu == CPU_NONE)
+		return 0;
+	return (CPUMASK_TSTB(boot_cpumask, cpu) != 0);
+}
+
+void initpdas(void)
+{
+	cpuid_t i;
+
+	for (i = 0; i < maxcpus; i++)
+		if (cpu_enabled(i))
+			alloc_cpupda(i);
+}
+
 void mlreset (void)
 {
-	int i, maxcpus;
+	int i;
 
 	fine_mode = is_fine_dirmode();
 
@@ -194,8 +201,11 @@
 	 */
 	CPUMASK_CLRALL(boot_cpumask);
 	maxcpus = cpu_node_probe(&boot_cpumask, &numnodes);
+	printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes);
+	initpdas();
 
 	gen_region_mask(&region_mask, numnodes);
+	CNODEMASK_CLRALL(hub_init_mask);
 
 	/*
 	 * Set all nodes' calias sizes to 8k
@@ -225,3 +235,257 @@
 	}
 }
 
+
+void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level,
+							char *name)
+{
+	volatile hubreg_t bits;
+	int i;
+
+	/* Check pending interrupts */
+	if ((bits = HUB_L(pend)) != 0)
+		for (i = 0; i < N_INTPEND_BITS; i++)
+			if (bits & (1 << i))
+				LOCAL_HUB_CLR_INTR(base_level + i);
+}
+	
+void intr_clear_all(nasid_t nasid)
+{
+	REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
+	REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
+	REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
+	REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
+	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
+		INT_PEND0_BASELVL, "INT_PEND0");
+	intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
+		INT_PEND1_BASELVL, "INT_PEND1");
+}
+
+void sn_mp_setup(void)
+{
+	cnodeid_t	cnode;
+#if 0
+	cpuid_t		cpu;
+#endif
+
+	for (cnode = 0; cnode < numnodes; cnode++) {
+#if 0
+		init_platform_nodepda();
+#endif
+		intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
+	}
+#if 0
+	for (cpu = 0; cpu < maxcpus; cpu++) {
+		init_platform_pda();
+	}
+#endif
+}
+
+void per_hub_init(cnodeid_t cnode)
+{
+	cnodemask_t	done;
+
+	spin_lock(&hub_mask_lock);
+	/* Test our bit. */
+	if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) {
+		/* Turn our bit on in the mask. */
+		CNODEMASK_SETB(hub_init_mask, cnode);
+	}
+	spin_unlock(&hub_mask_lock);
+
+	/*
+	 * Do the actual initialization if it hasn't been done yet.
+	 * We don't need to hold a lock for this work.
+	 */
+	if (!done) {
+		hub_rtc_init(cnode);
+	}
+}
+
+/*
+ * This is similar to hard_smp_processor_id().
+ */
+cpuid_t getcpuid(void)
+{
+	klcpu_t *klcpu;
+
+	klcpu = nasid_slice_to_cpuinfo(get_nasid(),LOCAL_HUB_L(PI_CPU_NUM));
+	return klcpu->cpu_info.virtid;
+}
+
+void per_cpu_init(void)
+{
+	extern void install_cpu_nmi_handler(int slice);
+	extern void load_mmu(void);
+	static int is_slave = 0;
+	cpuid_t cpu = getcpuid();
+	cnodeid_t cnode = get_compact_nodeid();
+
+	current_cpu_data.asid_cache = ASID_FIRST_VERSION;
+#if 0
+	intr_init();
+#endif
+	set_cp0_status(ST0_IM, 0);
+	per_hub_init(cnode);
+	cpu_time_init();
+	if (smp_processor_id())	/* master can't do this early, no kmalloc */
+		install_cpuintr(cpu);
+	/* Install our NMI handler if symmon hasn't installed one. */
+	install_cpu_nmi_handler(cputoslice(smp_processor_id()));
+#if 0
+	install_tlbintr(cpu);
+#endif
+	set_cp0_status(SRB_DEV0 | SRB_DEV1, SRB_DEV0 | SRB_DEV1);
+	if (is_slave) {
+		set_cp0_status(ST0_BEV, 0);
+		if (mips4_available)
+			set_cp0_status(ST0_XX, ST0_XX);
+		set_cp0_status(ST0_KX|ST0_SX|ST0_UX, ST0_KX|ST0_SX|ST0_UX);
+		sti();
+		load_mmu();
+	}
+	if (is_slave == 0)
+		is_slave = 1;
+}
+
+cnodeid_t get_compact_nodeid(void)
+{
+	nasid_t nasid;
+
+	nasid = get_nasid();
+	/*
+	 * Map the physical node id to a virtual node id (virtual node ids
+	 * are contiguous).
+	 */
+	return NASID_TO_COMPACT_NODEID(nasid);
+}
+
+#ifdef CONFIG_SMP
+
+void __init smp_callin(void)
+{
+#if 0
+	calibrate_delay();
+	smp_store_cpu_info(cpuid);
+#endif
+}
+
+int __init start_secondary(void)
+{
+	extern int cpu_idle(void);
+	extern atomic_t smp_commenced;
+
+	smp_callin();
+	while (!atomic_read(&smp_commenced));
+	return cpu_idle();
+}
+
+static atomic_t numstarted = ATOMIC_INIT(0);
+void cboot(void)
+{
+	atomic_inc(&numstarted);
+	CPUMASK_CLRB(boot_barrier, getcpuid());	/* needs atomicity */
+	per_cpu_init();
+#if 0
+	ecc_init();
+	bte_lateinit();
+	init_mfhi_war();
+#endif
+	_flush_tlb_all();
+	flush_cache_all();
+	start_secondary();
+}
+
+void allowboot(void)
+{
+	int		num_cpus = 0;
+	cpuid_t		cpu;
+	cnodeid_t	cnode;
+	extern void	bootstrap(void);
+
+	sn_mp_setup();
+	/* Master has already done per_cpu_init() */
+	install_cpuintr(getcpuid());
+#if 0
+	bte_lateinit();
+	ecc_init();
+#endif
+
+	boot_barrier = boot_cpumask;
+	/* Launch slaves. */
+	for (cpu = 0; cpu < maxcpus; cpu++) {
+		if (cpu == smp_processor_id()) {
+			num_cpus++;
+			/* We're already started, clear our bit */
+			CPUMASK_CLRB(boot_barrier, cpu);
+			continue;
+		}
+
+		/* Skip holes in CPU space */
+		if (CPUMASK_TSTB(boot_cpumask, cpu)) {
+			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", num_cpus);
+			init_tasks[num_cpus] = p;
+			p->processor = num_cpus;
+			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;
+			
+			/*
+		 	 * Launch a slave into bootstrap().
+		 	 * It doesn't take an argument, and we
+			 * set sp to the kernel stack of the newly 
+			 * created idle process, gp to the proc struct
+			 * (so that current-> works).
+		 	 */
+			LAUNCH_SLAVE(cputonasid(cpu), cputoslice(cpu), 
+				(launch_proc_t)bootstrap, 0, 
+				(void *)((unsigned long)p+KERNEL_STACK_SIZE - 32),
+				(void *)p);
+
+			/*
+			 * Now optimistically set the mapping arrays. We
+			 * need to wait here, verify the cpu booted up, then
+			 * fire up the next cpu.
+			 */
+			__cpu_number_map[cpu] = num_cpus;
+			__cpu_logical_map[num_cpus] = cpu;
+			num_cpus++;
+			/* smp_num_cpus++; Do after smp_send_reschedule works */
+		}
+	}
+
+	/* while(atomic_read(&numstarted) != (maxcpus - num_cpus)) */
+	if (maxcpus > 1) while(atomic_read(&numstarted) == 0);
+	printk("Holding %d cpus slave\n", atomic_read(&numstarted));
+
+#ifdef LATER
+	Wait logic goes here.
+#endif
+	for (cnode = 0; cnode < numnodes; cnode++) {
+#if 0
+		if (cnodetocpu(cnode) == -1) {
+			printk("Initializing headless hub,cnode %d", cnode);
+			per_hub_init(cnode);
+		}
+#endif
+	}
+#if 0
+	cpu_io_setup();
+	init_mfhi_war();
+#endif
+}
+
+#else /* CONFIG_SMP */
+void cboot(void) {}
+#endif /* CONFIG_SMP */
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq-glue.S linux/arch/mips64/sgi-ip27/ip27-irq-glue.S
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq-glue.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/ip27-irq-glue.S	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27-irq-glue.S,v 1.1 2000/01/17 23:32:47 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-irq.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips64/sgi-ip27/ip27-irq.c	Mon May 15 12:10:26 2000
@@ -1,14 +1,14 @@
-/* $Id: ip27-irq.c,v 1.6 2000/02/10 05:58:56 dagum Exp $
+/* $Id: ip27-irq.c,v 1.9 2000/03/14 01:39:27 ralf Exp $
  *
  * ip27-irq.c: Highlevel interrupt handling for IP27 architecture.
  *
  * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/init.h>
 
 #include <linux/errno.h>
-#include <linux/kernel_stat.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/types.h>
@@ -17,8 +17,9 @@
 #include <linux/timex.h>
 #include <linux/malloc.h>
 #include <linux/random.h>
-#include <linux/smp.h>
 #include <linux/smp_lock.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
 
 #include <asm/bitops.h>
 #include <asm/bootinfo.h>
@@ -33,14 +34,58 @@
 #include <asm/sn/sn0/hub.h>
 #include <asm/sn/sn0/ip27.h>
 #include <asm/sn/arch.h>
+#include <asm/sn/intr.h>
+#include <asm/sn/intr_public.h>
+
+#undef DEBUG_IRQ
+#ifdef DEBUG_IRQ
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+
+/*
+ * 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.
+ */
+
+irq_cpustat_t irq_stat [NR_CPUS];
 
 extern asmlinkage void ip27_irq(void);
 int (*irq_cannonicalize)(int irq);
+int intr_connect_level(cpuid_t cpu, int bit);
+int intr_disconnect_level(cpuid_t cpu, int bit);
 
 unsigned int local_bh_count[NR_CPUS];
 unsigned int local_irq_count[NR_CPUS];
 unsigned long spurious_count = 0;
 
+/*
+ * we need to map irq's up to at least bit 7 of the INT_MASK0_A register
+ * since bits 0-6 are pre-allocated for other purposes.
+ */
+#define IRQ_TO_SWLEVEL(i)	i + 7
+#define SWLEVEL_TO_IRQ(s)	s - 7
+/*
+ * use these macros to get the encoded nasid, widget id, and real irq
+ * from the irq value
+ */
+#define NASID_FROM_IRQ(i)       ((i >> 16)&(0xff))
+#define WID_FROM_IRQ(i)          ((i >> 8)&(0xff))
+#define IRQ_FROM_IRQ(i)               ((i)&(0xff))
+
 void disable_irq(unsigned int irq_nr)
 {
 	panic("disable_irq() called ...");
@@ -87,7 +132,7 @@
 	int do_random, cpu;
 
 	cpu = smp_processor_id();
-	irq_enter(cpu);
+	irq_enter(cpu, irq);
 	kstat.irqs[cpu][irq]++;
 
 	action = *(irq + irq_action);
@@ -105,7 +150,7 @@
 			add_interrupt_randomness(irq);
 		__cli();
 	}
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
 
 	/* unmasking and bottom half handling is done magically for us. */
 }
@@ -130,20 +175,26 @@
 /* For now ...  */
 void ip27_do_irq(struct pt_regs *regs)
 {
-	int irq;
+	int irq, swlevel;
 	hubreg_t pend0, mask0;
+	int pi_int_mask0 = ((cputoslice(smp_processor_id()) == 0) ?
+					PI_INT_MASK0_A : PI_INT_MASK0_B);
 
 	/* copied from Irix intpend0() */
 	while (((pend0 = LOCAL_HUB_L(PI_INT_PEND0)) & 
-				(mask0 = LOCAL_HUB_L(PI_INT_MASK0_A))) != 0) {
+				(mask0 = LOCAL_HUB_L(pi_int_mask0))) != 0) {
+		pend0 &= mask0;
 		do {
-			irq = ms1bit(pend0);
-			LOCAL_HUB_S(PI_INT_MASK0_A, mask0 & ~(1 << irq));
-			LOCAL_HUB_S(PI_INT_PEND_MOD, irq);
-			LOCAL_HUB_L(PI_INT_MASK0_A);		/* Flush */
+			swlevel = ms1bit(pend0);
+			LOCAL_HUB_S(pi_int_mask0, mask0 & ~(1 << swlevel));
+			LOCAL_HUB_CLR_INTR(swlevel);
+			/* "map" swlevel to irq */
+			irq = SWLEVEL_TO_IRQ(swlevel);
 			do_IRQ(irq, regs);
-			LOCAL_HUB_S(PI_INT_MASK0_A, mask0);
-			pend0 ^= 1ULL << irq;
+			/* reset INT_MASK0 register */
+			LOCAL_HUB_S(pi_int_mask0, mask0);
+			/* clear bit in pend0 */
+			pend0 ^= 1ULL << swlevel;
 		} while (pend0);
 	}
 }
@@ -152,96 +203,141 @@
 /* Startup one of the (PCI ...) IRQs routes over a bridge.  */
 static unsigned int bridge_startup(unsigned int irq)
 {
-	bridge_t *bridge = (bridge_t *) 0x9200000008000000;
-	bridgereg_t br;
-	int pin;
+        bridge_t *bridge;
+        int pin, swlevel;
+        int real_irq = IRQ_FROM_IRQ(irq);
+
+	DBG("bridge_startup(): irq= 0x%x  real_irq= %d\n", irq, real_irq);
+        bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq));
+
+        /* FIIIIIXME ...  Temporary kludge.  This knows how interrupts are
+           setup in _my_ Origin.  */
+
+        if (irq != real_irq)            /* pci device interrupt */
+                switch (real_irq) {
+                        case IRQ_FROM_IRQ(IOC3_ETH_INT):        pin = 2; break;
+			default:		  pin = real_irq; break;
+                }
+        else
+                switch (real_irq) {
+                        case CPU_RESCHED_A_IRQ:
+                        case CPU_RESCHED_B_IRQ:
+                        case CPU_CALL_A_IRQ:
+                        case CPU_CALL_B_IRQ:
+                                                return 0;
+                        default:                panic("bridge_startup: whoops? %d\n", irq);
+                }
+
+        /*
+         * "map" irq to a swlevel greater than 6 since the first 6 bits
+         * of INT_PEND0 are taken
+         */
+        swlevel = IRQ_TO_SWLEVEL(real_irq);
+        intr_connect_level(smp_processor_id(), swlevel);
+
+        bridge->b_int_addr[pin].addr = 0x20000 | swlevel;
+        bridge->b_int_enable |= (1 << pin);
+	/* set more stuff in int_enable reg */
+	bridge->b_int_enable |= 0x7ffffe00;
 
-	/* FIIIIIXME ...  Temporary kludge.  This knows how interrupts are
-	   setup in _my_ Origin.  */
-	switch (irq) {
-	case IOC3_SERIAL_INT:	pin = 3; break;
-	case IOC3_ETH_INT:	pin = 2; break;
-	case SCSI1_INT:		pin = 1; break;
-	case SCSI0_INT:		pin = 0; break;
-	default:		panic("bridge_startup: whoops?");
-	}
-
-	br = LOCAL_HUB_L(PI_INT_MASK0_A);
-	LOCAL_HUB_S(PI_INT_MASK0_A, br | (1 << irq));
-	LOCAL_HUB_L(PI_INT_MASK0_A);			/* Flush */
-
-	bridge->b_int_addr[pin].addr = 0x20000 | irq;
-	bridge->b_int_enable |= (1 << pin);
-	if (irq < 2) {
-		bridgereg_t device;
+        if (real_irq < 2 || real_irq==4 || real_irq==5) {
+                bridgereg_t device;
 #if 0
-		/*
-	 	 * Allocate enough RRBs on the bridge for the DMAs.
-	 	 * Right now allocating 2 RRBs on the normal channel
-	 	 * and 2 on the virtual channel for slot 0 on the bus.
-		 * And same for slot 1, to get ioc3 eth working.
-	 	 */
-		Not touching b_even_resp	  /* boot doesn't go far */
-		bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */
-		bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */
-		bridge->b_even_resp = 0xcc88;	  /* breaks eth0 */
+                /*
+                 * Allocate enough RRBs on the bridge for the DMAs.
+                 * Right now allocating 2 RRBs on the normal channel
+                 * and 2 on the virtual channel for slot 0 on the bus.
+                 * And same for slot 1, to get ioc3 eth working.
+                 */
+                Not touching b_even_resp          /* boot doesn't go far */
+                bridge->b_even_resp = 0xdd99cc88; /* boot doesn't go far */
+                bridge->b_even_resp = 0xcccc8888; /* breaks eth0 */
+                bridge->b_even_resp = 0xcc88;     /* breaks eth0 */
 #endif
-		/* Turn on bridge swapping */
-		device = bridge->b_device[irq].reg;
-		device |= BRIDGE_DEV_SWAP_DIR;
-		bridge->b_device[irq].reg = device;
-	}
-	bridge->b_widget.w_tflush;			/* Flush */
+                /* Turn on bridge swapping */
+                device = bridge->b_device[real_irq].reg;
+                device |= BRIDGE_DEV_SWAP_DIR;
+                bridge->b_device[real_irq].reg = device;
+                /*
+                 * Associate interrupt pin with device
+                 * XXX This only works if b_int_device is initialized to 0!
+                 */
+                device = bridge->b_int_device;
+                device |= (pin << (real_irq*3));
+                bridge->b_int_device = device;
+        }
+        bridge->b_widget.w_tflush;                      /* Flush */
 
-	return 0;	/* Never anything pending.  */
+        return 0;       /* Never anything pending.  */
 }
 
-/* Startup one of the (PCI ...) IRQs routes over a bridge.  */
+/* Shutdown one of the (PCI ...) IRQs routes over a bridge.  */
 static unsigned int bridge_shutdown(unsigned int irq)
 {
-	bridge_t *bridge = (bridge_t *) 0x9200000008000000;
-	bridgereg_t br;
-	int pin;
+        bridge_t *bridge;
+        int pin, swlevel;
+        int real_irq = IRQ_FROM_IRQ(irq);
+        struct irqaction **p;
+
+        bridge = (bridge_t *) NODE_SWIN_BASE(NASID_FROM_IRQ(irq), WID_FROM_IRQ(irq));
+	DBG("bridge_shutdown: irq 0x%x\n", irq);
+        /* FIIIIIXME ...  Temporary kludge.  This knows how interrupts are
+           setup in _my_ Origin.  */
+
+        if (irq != real_irq)            /* pci device interrupt */
+                switch (real_irq) {
+                        case IRQ_FROM_IRQ(IOC3_ETH_INT):        pin = 2; break;
+			default:		  pin = real_irq; break;
+                }
+        else
+                switch (real_irq) {
+                        case CPU_RESCHED_A_IRQ:
+                        case CPU_RESCHED_B_IRQ:
+                        case CPU_CALL_A_IRQ:
+                        case CPU_CALL_B_IRQ:
+                                                return 0;
+                        default:                panic("bridge_startup: whoops?");
+                }
+
+        /*
+         * map irq to a swlevel greater than 6 since the first 6 bits
+         * of INT_PEND0 are taken
+         */
+        swlevel = IRQ_TO_SWLEVEL(real_irq);
+        intr_disconnect_level(smp_processor_id(), swlevel);
 
-	/* FIIIIIXME ...  Temporary kludge.  This knows how interrupts are
-	   setup in _my_ Origin.  */
-	switch (irq) {
-	case IOC3_SERIAL_INT:	pin = 3; break;
-	case IOC3_ETH_INT:	pin = 2; break;
-	case SCSI1_INT:		pin = 1; break;
-	case SCSI0_INT:		pin = 0; break;
-	default:		panic("bridge_startup: whoops?");
-	}
-
-	br = LOCAL_HUB_L(PI_INT_MASK0_A);
-	LOCAL_HUB_S(PI_INT_MASK0_A, br & ~(1 << irq));
-	LOCAL_HUB_L(PI_INT_MASK0_A);			/* Flush */
+        bridge->b_int_enable &= ~(1 << pin);
+        bridge->b_widget.w_tflush;                      /* Flush */
 
-	bridge->b_int_enable &= ~(1 << pin);
-	bridge->b_widget.w_tflush;			/* Flush */
-
-	return 0;	/* Never anything pending.  */
+        return 0;       /* Never anything pending.  */
 }
 
 static void bridge_init(void)
 {
-	bridge_t *bridge = (bridge_t *) 0x9200000008000000;
-
-	/* Hmm...  IRIX sets additional bits in the address which are
-	   documented as reserved in the bridge docs ...  */
-	bridge->b_int_mode = 0x0;			/* Don't clear ints */
+	bridge_t *bridge;
+	nasid_t   nasid;
+        char    wid;
+        int     bus;
+
+        nasid = get_nasid();
+
+        for (bus=0; bus<num_bridges; bus++) {
+          bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus],bus_to_wid[bus]);          
+          /* Hmm...  IRIX sets additional bits in the address which are
+             documented as reserved in the bridge docs ...  */
+          bridge->b_int_mode = 0x0;                     /* Don't clear ints */
 #if 0
-	bridge->b_wid_int_upper = 0x000a8000;           /* Ints to node 0 */
-	bridge->b_wid_int_lower = 0x01000090;
-	bridge->b_dir_map = 0xa00000;			/* DMA */
+          bridge->b_wid_int_upper = 0x000a8000;           /* Ints to node 0 */
+          bridge->b_wid_int_lower = 0x01000090;
+          bridge->b_dir_map = 0xa00000;                 /* DMA */
 #endif /* shouldn't lower= 0x01800090 ??? */
-        bridge->b_wid_int_upper = 0x00098000;           /* Ints to node 0 */
-        bridge->b_wid_int_lower = 0x01800090;
-        bridge->b_dir_map = 0x900000;                   /* DMA */
-
-	bridge->b_int_enable = 0;
-	bridge->b_widget.w_tflush;			/* Flush */
-	set_cp0_status(SRB_DEV0 | SRB_DEV1, SRB_DEV0 | SRB_DEV1);
+          bridge->b_wid_int_upper = 0x000a8000;           /* Ints to widget A */
+          bridge->b_wid_int_lower = 0x01800090;
+          bridge->b_dir_map = 0xa00000;                   /* DMA */
+
+          bridge->b_int_enable = 0;
+          bridge->b_widget.w_tflush;                    /* Flush */
+        }
 }
 
 void irq_debug(void)
@@ -254,17 +350,18 @@
 	printk("PI_INT_MASK0_A = 0x%x\n", LOCAL_HUB_L(PI_INT_MASK0_A));
 }
 
-int setup_irq(int irq, struct irqaction *new)
+int setup_irq(unsigned int irq, struct irqaction *new)
 {
 	int shared = 0;
 	struct irqaction *old, **p;
 	unsigned long flags;
 
+	DBG("setup_irq: 0x%x\n", irq);
 	if (new->flags & SA_SAMPLE_RANDOM)
 		rand_initialize_irq(irq);
 
 	save_and_cli(flags);
-	p = irq_action + irq;
+	p = irq_action + IRQ_FROM_IRQ(irq);
 	if ((old = *p) != NULL) {
 		/* Can't share interrupts unless both agree to */
 		if (!(old->flags & new->flags & SA_SHIRQ)) {
@@ -297,7 +394,8 @@
 	int retval;
 	struct irqaction *action;
 
-	if (irq > 9)
+	DBG("request_irq(): irq= 0x%x\n", irq);
+	if (IRQ_FROM_IRQ(irq) > 9)
 		return -EINVAL;
 	if (!handler)
 		return -EINVAL;
@@ -313,7 +411,9 @@
 	action->next = NULL;
 	action->dev_id = dev_id;
 
+	DBG("request_irq(): %s  devid= 0x%x\n", devname, dev_id);
 	retval = setup_irq(irq, action);
+	DBG("request_irq(): retval= %d\n", retval);
 	if (retval)
 		kfree(action);
 	return retval;
@@ -324,11 +424,11 @@
 	struct irqaction * action, **p;
 	unsigned long flags;
 
-	if (irq > 9) {
+	if (IRQ_FROM_IRQ(irq) > 9) {
 		printk("Trying to free IRQ%d\n", irq);
 		return;
 	}
-	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+	for (p = IRQ_FROM_IRQ(irq) + irq_action; (action = *p) != NULL; p = &action->next) {
 		if (action->dev_id != dev_id)
 			continue;
 
@@ -347,6 +447,7 @@
 /* Useless ISA nonsense.  */
 unsigned long probe_irq_on (void)
 {
+	panic("probe_irq_on called!\n");
 	return 0;
 }
 
@@ -366,4 +467,313 @@
 
 	bridge_init();
 	set_except_vector(0, ip27_irq);
+}
+
+
+#ifdef CONFIG_SMP
+
+/*
+ * This following are the global intr on off routines, copied almost
+ * entirely from i386 code.
+ */
+
+int global_irq_holder = NO_PROC_ID;
+spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
+
+extern void show_stack(unsigned long* esp);
+
+static void show(char * str)
+{
+	int i;
+	int cpu = smp_processor_id();
+
+	printk("\n%s, CPU %d:\n", str, cpu);
+	printk("irq:  %d [",irqs_running());
+	for(i=0;i < smp_num_cpus;i++)
+		printk(" %d",local_irq_count(i));
+	printk(" ]\nbh:   %d [",spin_is_locked(&global_bh_lock) ? 1 : 0);
+	for(i=0;i < smp_num_cpus;i++)
+		printk(" %d",local_bh_count(i));
+
+	printk(" ]\nStack dumps:");
+	for(i = 0; i < smp_num_cpus; i++) {
+		unsigned long esp;
+		if (i == cpu)
+			continue;
+		printk("\nCPU %d:",i);
+		printk("Code not developed yet\n");
+		/* show_stack(0); */
+	}
+	printk("\nCPU %d:",cpu);
+	printk("Code not developed yet\n");
+	/* show_stack(NULL); */
+	printk("\n");
+}
+
+#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) {
+				show("wait_on_irq");
+				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;
+		}
+	}
+}
+
+void synchronize_irq(void)
+{
+	if (irqs_running()) {
+		/* Stupid approach */
+		cli();
+		sti();
+	}
+}
+
+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;
+}
+
+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);
+	}
+}
+
+#endif /* CONFIG_SMP */
+
+/*
+ * Get values that vary depending on which CPU and bit we're operating on.
+ */
+static hub_intmasks_t *intr_get_ptrs(cpuid_t cpu, int bit, int *new_bit,
+				hubreg_t **intpend_masks, int *ip)
+{
+	hub_intmasks_t *hub_intmasks;
+
+	hub_intmasks = &cpu_data[cpu].p_intmasks;
+	if (bit < N_INTPEND_BITS) {
+		*intpend_masks = hub_intmasks->intpend0_masks;
+		*ip = 0;
+		*new_bit = bit;
+	} else {
+		*intpend_masks = hub_intmasks->intpend1_masks;
+		*ip = 1;
+		*new_bit = bit - N_INTPEND_BITS;
+	}
+	return hub_intmasks;
+}
+
+int intr_connect_level(cpuid_t cpu, int bit)
+{
+	int ip;
+	int slice = cputoslice(cpu);
+	volatile hubreg_t *mask_reg;
+	hubreg_t *intpend_masks;
+	nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu));
+
+	(void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip);
+
+	/* Make sure it's not already pending when we connect it. */
+	REMOTE_HUB_CLR_INTR(nasid, bit + ip * N_INTPEND_BITS);
+
+	intpend_masks[0] |= (1ULL << (u64)bit);
+
+	if (ip == 0) {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + 
+				PI_INT_MASK_OFFSET * slice);
+	} else {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + 
+				PI_INT_MASK_OFFSET * slice);
+	}
+	HUB_S(mask_reg, intpend_masks[0]);
+	return(0);
+}
+
+int intr_disconnect_level(cpuid_t cpu, int bit)
+{
+	int ip;
+	int slice = cputoslice(cpu);
+	volatile hubreg_t *mask_reg;
+	hubreg_t *intpend_masks;
+	nasid_t nasid = COMPACT_TO_NASID_NODEID(cputocnode(cpu));
+
+	(void)intr_get_ptrs(cpu, bit, &bit, &intpend_masks, &ip);
+	intpend_masks[0] &= ~(1ULL << (u64)bit);
+	if (ip == 0) {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK0_A + 
+				PI_INT_MASK_OFFSET * slice);
+	} else {
+		mask_reg = REMOTE_HUB_ADDR(nasid, PI_INT_MASK1_A + 
+				PI_INT_MASK_OFFSET * slice);
+	}
+	HUB_S(mask_reg, intpend_masks[0]);
+	return(0);
+}
+
+
+void handle_resched_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* Nothing, the return from intr will work for us */
+}
+
+void install_cpuintr(cpuid_t cpu)
+{
+	int irq;
+	extern void smp_call_function_interrupt(void);
+	static int done = 0;
+
+	/*
+	 * This is a hack till we have a pernode irqlist. Currently,
+	 * just have the master cpu set up the handlers for the per
+	 * cpu irqs.
+	 */
+
+#ifdef CONFIG_SMP
+#if (CPUS_PER_NODE == 2)
+	irq = CPU_RESCHED_A_IRQ + cputoslice(cpu);
+	intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq));
+	if (done == 0)
+	if (request_irq(irq, handle_resched_intr, 0, "resched", 0))
+		panic("intercpu intr unconnectible\n");
+	irq = CPU_CALL_A_IRQ + cputoslice(cpu);
+	intr_connect_level(cpu, IRQ_TO_SWLEVEL(irq));
+	if (done == 0)
+	if (request_irq(irq, smp_call_function_interrupt, 0,
+						"callfunc", 0))
+		panic("intercpu intr unconnectible\n");
+	/* HACK STARTS */
+	if (done)
+		return;
+	irq = CPU_RESCHED_A_IRQ + cputoslice(cpu) + 1;
+	if (request_irq(irq, handle_resched_intr, 0, "resched", 0))
+		panic("intercpu intr unconnectible\n");
+	irq = CPU_CALL_A_IRQ + cputoslice(cpu) + 1;
+	if (request_irq(irq, smp_call_function_interrupt, 0,
+						"callfunc", 0))
+		panic("intercpu intr unconnectible\n");
+	done = 1;
+	/* HACK ENDS */
+#else /* CPUS_PER_NODE */
+	<< Bomb!  Must redefine this for more than 2 CPUS. >>
+#endif /* CPUS_PER_NODE */
+#endif /* CONFIG_SMP */
+}
+
+void install_tlbintr(cpuid_t cpu)
+{
+	int intr_bit = N_INTPEND_BITS + TLB_INTR_A + cputoslice(cpu);
+
+	intr_connect_level(cpu, intr_bit);
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-klconfig.c linux/arch/mips64/sgi-ip27/ip27-klconfig.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-klconfig.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/ip27-klconfig.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27-klconfig.c,v 1.1 2000/01/17 23:32:47 ralf Exp $
+/* $Id$
  *
  * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org)
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
@@ -13,21 +13,111 @@
 #include <linux/mm.h>		
 
 #include <asm/sn/klconfig.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
 
-lboard_t *find_lboard(unsigned int type)
+klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char struct_type)
 {
-	lboard_t *b;
+	int index, j;
 
-	for (
-b = KL_CONFIG_INFO(get_nasid());
-b;
-b = KLCF_NEXT(b)) {
-		if (KLCF_REMOTE(b))
-			continue;		/* Skip remote boards. */
+	if (kli == (klinfo_t *)NULL) {
+		index = 0;
+	} else {
+		for (j = 0; j < KLCF_NUM_COMPS(brd); j++)
+			if (kli == KLCF_COMP(brd, j))
+				break;
+		index = j;
+		if (index == KLCF_NUM_COMPS(brd)) {
+			printk("find_component: Bad pointer: 0x%p\n", kli);
+			return (klinfo_t *)NULL;
+		}
+		index++;		/* next component */
+	}
+
+	for (; index < KLCF_NUM_COMPS(brd); index++) {
+		kli = KLCF_COMP(brd, index);
+		if (KLCF_COMP_TYPE(kli) == struct_type)
+			return kli;
+	}
+
+	/* Didn't find it. */
+	return (klinfo_t *)NULL;
+}
+
+klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type)
+{
+	return find_component(brd, (klinfo_t *)NULL, struct_type);
+}
+
+lboard_t * find_lboard(lboard_t *start, unsigned char brd_type)
+{
+	/* Search all boards stored on this node. */
+	while (start) {
+		if (start->brd_type == brd_type)
+			return start;
+		start = KLCF_NEXT(start);
+	}
+	/* Didn't find it. */
+	return (lboard_t *)NULL;
+}
+
+cnodeid_t get_cpu_cnode(int cpu)
+{
+	return CPUID_TO_COMPACT_NODEID(cpu);
+}
+
+klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice)
+{
+	lboard_t *brd;
+	klcpu_t *acpu;
+
+	if (!(brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27)))
+		return (klcpu_t *)NULL;
+
+	if (!(acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU)))
+		return (klcpu_t *)NULL;
+
+	do {
+		if ((acpu->cpu_info.physid) == slice)
+			return acpu;
+	} while ((acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu, 
+								KLSTRUCT_CPU)));
+	return (klcpu_t *)NULL;
+}
+
+klcpu_t * sn_get_cpuinfo(cpuid_t cpu)
+{
+	nasid_t nasid;
+	int slice;
+	klcpu_t *acpu;
+	gda_t *gdap = GDA;
+	cnodeid_t cnode;
 
-		if (b->brd_type == type)
-			return (lboard_t *) b;
+	if (!(cpu < MAXCPUS)) {
+		printk("sn_get_cpuinfo: illegal cpuid 0x%lx\n", cpu);
+		return NULL;
 	}
 
+	cnode = get_cpu_cnode(cpu);
+	if (cnode == INVALID_CNODEID)
+		return NULL;
+
+	if ((nasid = gdap->g_nasidtable[cnode]) == INVALID_NASID)
+		return NULL;
+
+	for (slice = 0; slice < CPUS_PER_NODE; slice++) {
+		acpu = nasid_slice_to_cpuinfo(nasid, slice);
+		if (acpu && acpu->cpu_info.virtid == cpu)
+			return acpu;
+	}
 	return NULL;
+}
+
+int get_cpu_slice(cpuid_t cpu)
+{
+	klcpu_t *acpu;
+
+	if ((acpu = sn_get_cpuinfo(cpu)) == NULL)
+		return -1;
+	return acpu->cpu_info.physid;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-memory.c linux/arch/mips64/sgi-ip27/ip27-memory.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-memory.c	Tue Apr 11 15:09:13 2000
+++ linux/arch/mips64/sgi-ip27/ip27-memory.c	Mon May 15 16:41:29 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27-memory.c,v 1.9 2000/02/10 09:07:31 kanoj Exp $
+/* $Id: ip27-memory.c,v 1.2 2000/01/27 01:05:24 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
@@ -46,7 +46,7 @@
 int numa_debug(void)
 {
 	printk("NUMA debug\n");
-	*(int *)0 = 0;
+	BUG();
 	return(0);
 }
 
@@ -57,17 +57,12 @@
  */
 pfn_t node_getfirstfree(cnodeid_t cnode)
 {
-#ifdef LATER
 	nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
 
 	if (cnode == 0)
-		return KDM_TO_PHYS((unsigned long)(&_end));
-	return KDM_TO_PHYS(SYMMON_STK_ADDR(nasid, 0));
-#endif
-	if (cnode == 0)
 		return (KDM_TO_PHYS(PAGE_ALIGN((unsigned long)(&_end)) - 
 					(CKSEG0 - K0BASE)) >> PAGE_SHIFT);
-	return slot_getbasepfn(cnode, 0);
+	return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT);
 }
 
 /*
@@ -124,7 +119,7 @@
 
 	nasid = COMPACT_TO_NASID_NODEID(node);
 	/* Find the node board */
-	brd = find_lboard_real((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
+	brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
 	if (!brd)
 		return 0;
 
@@ -269,28 +264,24 @@
 void __init paging_init(void)
 {
 	cnodeid_t node;
-	unsigned int zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
 
 	/* Initialize the entire pgd.  */
 	pgd_init((unsigned long)swapper_pg_dir);
-	pgd_init((unsigned long)swapper_pg_dir + PAGE_SIZE / 2);
 	pmd_init((unsigned long)invalid_pmd_table);
+	memset((void *)invalid_pte_table, 0, sizeof(pte_t) * 2 * PTRS_PER_PTE);
 
 	for (node = 0; node < numnodes; node++) {
 		pfn_t start_pfn = slot_getbasepfn(node, 0);
 		pfn_t end_pfn = node_getmaxclick(node);
 
 		zones_size[ZONE_DMA] = end_pfn + 1 - start_pfn;
-		PLAT_NODE_DATA(node)->physstart = (start_pfn << PAGE_SHIFT);
-		PLAT_NODE_DATA(node)->size = (zones_size[ZONE_DMA] << PAGE_SHIFT);
 		free_area_init_node(node, NODE_DATA(node), zones_size, 
 						start_pfn << PAGE_SHIFT, 0);
-		PLAT_NODE_DATA(node)->start_mapnr = 
-					(NODE_DATA(node)->node_mem_map - mem_map);
-		if ((PLAT_NODE_DATA(node)->start_mapnr + 
-					PLAT_NODE_DATA(node)->size) > pagenr)
-			pagenr = PLAT_NODE_DATA(node)->start_mapnr +
-					PLAT_NODE_DATA(node)->size;
+		if ((PLAT_NODE_DATA_STARTNR(node) + 
+					PLAT_NODE_DATA_SIZE(node)) > pagenr)
+			pagenr = PLAT_NODE_DATA_STARTNR(node) +
+					PLAT_NODE_DATA_SIZE(node);
 	}
 }
 
@@ -314,6 +305,11 @@
 	for (nid = 0; nid < numnodes; nid++) {
 
 		/*
+		 * Hack till free_area_init_core() zeroes free_pages
+		 */
+		for (tmp = 0; tmp < MAX_NR_ZONES; tmp++)
+			PLAT_NODE_DATA(nid)->gendata.node_zones[tmp].free_pages=0;
+		/*
 	 	 * This will free up the bootmem, ie, slot 0 memory.
 	 	 */
 		totalram_pages += free_all_bootmem_node(nid);
@@ -322,7 +318,7 @@
 		 * We need to manually do the other slots.
 		 */
 		pg = NODE_DATA(nid)->node_mem_map + slot_getsize(nid, 0);
-		pgnr = PLAT_NODE_DATA(nid)->start_mapnr + slot_getsize(nid, 0);
+		pgnr = PLAT_NODE_DATA_STARTNR(nid) + slot_getsize(nid, 0);
 		numslots = node_getlastslot(nid);
 		for (slot = 1; slot <= numslots; slot++) {
 			pslot = NODE_DATA(nid)->node_mem_map + 
@@ -357,9 +353,9 @@
 
 	reservedpages = ram = 0;
 	for (nid = 0; nid < numnodes; nid++) {
-		for (tmp = PLAT_NODE_DATA(nid)->start_mapnr; tmp < 
-			((PLAT_NODE_DATA(nid)->start_mapnr) + 
-			(PLAT_NODE_DATA(nid)->size >> PAGE_SHIFT)); tmp++) {
+		for (tmp = PLAT_NODE_DATA_STARTNR(nid); tmp < 
+			(PLAT_NODE_DATA_STARTNR(nid) +
+			PLAT_NODE_DATA_SIZE(nid)); tmp++) {
 			/* Ignore holes */
 			if (PageSkip(mem_map+tmp))
 				continue;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-nmi.c linux/arch/mips64/sgi-ip27/ip27-nmi.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-nmi.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/sgi-ip27/ip27-nmi.c	Sat May 13 08:30:17 2000
@@ -0,0 +1,165 @@
+#include <linux/kernel.h>
+#include <linux/mmzone.h>
+#include <linux/spinlock.h>
+#include <linux/smp.h>
+#include <asm/atomic.h>
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/nmi.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/sn0/hub.h>
+
+#if 0
+#define NODE_NUM_CPUS(n)	CNODE_NUM_CPUS(n)
+#else
+#define NODE_NUM_CPUS(n)	CPUS_PER_NODE
+#endif
+
+#define CNODEID_NONE (cnodeid_t)-1
+#define enter_panic_mode()	spin_lock(&nmi_lock)
+
+typedef unsigned long machreg_t;
+
+spinlock_t nmi_lock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * Lets see what else we need to do here. Set up sp, gp?
+ */
+void nmi_dump(void)
+{
+	void cont_nmi_dump(void);
+
+	cont_nmi_dump();
+}
+
+void install_cpu_nmi_handler(int slice)
+{
+	nmi_t *nmi_addr;
+
+	nmi_addr = (nmi_t *)NMI_ADDR(get_nasid(), slice);
+	if (nmi_addr->call_addr)
+		return;
+	nmi_addr->magic = NMI_MAGIC;
+	nmi_addr->call_addr = (void *)nmi_dump;
+	nmi_addr->call_addr_c =
+		(void *)(~((unsigned long)(nmi_addr->call_addr)));
+	nmi_addr->call_parm = 0;
+}
+
+/*
+ * Copy the cpu registers which have been saved in the IP27prom format
+ * into the eframe format for the node under consideration.
+ */
+
+void
+nmi_cpu_eframe_save(nasid_t nasid,
+		    int	    slice)
+{
+	int 		i, numberof_nmi_cpu_regs;
+	machreg_t	*prom_format;
+	
+	/* Get the total number of registers being saved by the prom */
+	numberof_nmi_cpu_regs = sizeof(struct reg_struct) / sizeof(machreg_t);
+	
+	/* Get the pointer to the current cpu's register set. */
+	prom_format = 
+	    (machreg_t *)(TO_UNCAC(TO_NODE(nasid, IP27_NMI_KREGS_OFFSET)) +
+			  slice * IP27_NMI_KREGS_CPU_SIZE);
+
+	printk("NMI nasid %d: slice %d\n", nasid, slice);
+	for (i = 0; i < numberof_nmi_cpu_regs; i++)
+		printk("0x%lx  ", prom_format[i]);
+	printk("\n\n");
+}	
+
+/*
+ * Copy the cpu registers which have been saved in the IP27prom format
+ * into the eframe format for the node under consideration.
+ */
+void
+nmi_node_eframe_save(cnodeid_t  cnode)
+{
+	int		cpu;
+	nasid_t		nasid;
+
+	/* Make sure that we have a valid node */
+	if (cnode == CNODEID_NONE)
+		return;
+
+	nasid = COMPACT_TO_NASID_NODEID(cnode);
+	if (nasid == INVALID_NASID)
+		return;
+
+	/* Save the registers into eframe for each cpu */
+	for(cpu = 0; cpu < NODE_NUM_CPUS(cnode); cpu++) 
+		nmi_cpu_eframe_save(nasid, cpu);
+}
+
+/*
+ * Save the nmi cpu registers for all cpus in the system.
+ */
+void
+nmi_eframes_save(void)
+{
+	cnodeid_t	cnode;
+
+	for(cnode = 0 ; cnode < numnodes; cnode++) 
+		nmi_node_eframe_save(cnode);
+}
+
+void
+cont_nmi_dump(void)
+{
+#ifndef REAL_NMI_SIGNAL
+	static atomic_t nmied_cpus = ATOMIC_INIT(0);
+
+	atomic_inc(&nmied_cpus);
+#endif
+	/* 
+	 * Use enter_panic_mode to allow only 1 cpu to proceed
+	 */
+	enter_panic_mode();
+
+#ifdef REAL_NMI_SIGNAL
+	/*
+	 * Wait up to 15 seconds for the other cpus to respond to the NMI.
+	 * If a cpu has not responded after 10 sec, send it 1 additional NMI.
+	 * This is for 2 reasons:
+	 *	- sometimes a MMSC fail to NMI all cpus.
+	 *	- on 512p SN0 system, the MMSC will only send NMIs to
+	 *	  half the cpus. Unfortunately, we dont know which cpus may be
+	 *	  NMIed - it depends on how the site chooses to configure.
+	 * 
+	 * Note: it has been measure that it takes the MMSC up to 2.3 secs to
+	 * send NMIs to all cpus on a 256p system.
+	 */
+	for (i=0; i < 1500; i++) {
+		for (node=0; node < numnodes; node++)
+			if (NODEPDA(node)->dump_count == 0)
+				break;
+		if (node == numnodes)
+			break;
+		if (i == 1000) {
+			for (node=0; node < numnodes; node++)
+				if (NODEPDA(node)->dump_count == 0) {
+					cpu = CNODE_TO_CPU_BASE(node);
+					for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) {
+						CPUMASK_SETB(nmied_cpus, cpu);
+						SEND_NMI((cputonasid(cpu)), (cputoslice(cpu)));
+					}
+				}
+					
+		}
+		udelay(10000);
+	}
+#else
+	while (atomic_read(&nmied_cpus) != smp_num_cpus);
+#endif
+
+	/*
+	 * Save the nmi cpu registers for all cpu in the eframe format.
+	 */
+	nmi_eframes_save();
+	LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
+}
+
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c linux/arch/mips64/sgi-ip27/ip27-pci-dma.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci-dma.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/ip27-pci-dma.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27-pci-dma.c,v 1.1 2000/02/18 00:24:31 ralf Exp $
+/* $Id: ip27-pci-dma.c,v 1.1 2000/02/16 21:22:00 ralf Exp $
  *
  * Dynamic DMA mapping support.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci.c linux/arch/mips64/sgi-ip27/ip27-pci.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-pci.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/ip27-pci.c	Sat May 13 08:30:17 2000
@@ -13,6 +13,8 @@
 #include <asm/sn/arch.h>
 #include <asm/pci/bridge.h>
 #include <asm/paccess.h>
+#include <asm/sn/sn0/ip27.h>
+#include <asm/sn/sn0/hub.h>
 
 /*
  * The Bridge ASIC supports both type 0 and type 1 access.  Type 1 is
@@ -22,14 +24,18 @@
  */
 #define CF0_READ_PCI_CFG(dev,where,value,bm,mask)			\
 do {									\
-	bridge_t *bridge = (bridge_t *) 0x9200000008000000;		\
+	bridge_t *bridge;                                               \
 	int slot = PCI_SLOT(dev->devfn);				\
 	int fn = PCI_FUNC(dev->devfn);					\
 	volatile u32 *addr;						\
 	u32 cf, __bit;							\
+	unsigned int bus_id = (unsigned) dev->bus->number;              \
 									\
-	if (dev->bus->number)						\
-		return PCIBIOS_DEVICE_NOT_FOUND;			\
+	bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],        \
+                                             bus_to_wid[bus_id]);       \
+                                                                        \
+	/*if (dev->bus->number)			 */			\
+	/*	return PCIBIOS_DEVICE_NOT_FOUND; */			\
 									\
 	__bit = (((where) & (bm)) << 3);				\
 	addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2];	\
@@ -59,14 +65,18 @@
 
 #define CF0_WRITE_PCI_CFG(dev,where,value,bm,mask)			\
 do {									\
-	bridge_t *bridge = (bridge_t *) 0x9200000008000000;		\
+	bridge_t *bridge;                                               \
 	int slot = PCI_SLOT(dev->devfn);				\
 	int fn = PCI_FUNC(dev->devfn);					\
 	volatile u32 *addr;						\
 	u32 cf, __bit;							\
+	unsigned int bus_id = (unsigned) dev->bus->number;              \
 									\
-	if (dev->bus->number)						\
-		return PCIBIOS_DEVICE_NOT_FOUND;			\
+	bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],        \
+                                             bus_to_wid[bus_id]);       \
+                                                                        \
+	/* if (dev->bus->number)		 */			\
+	/* 	return PCIBIOS_DEVICE_NOT_FOUND; */			\
 									\
 	if (dev->vendor == PCI_VENDOR_ID_SGI				\
 	    && dev->device == PCI_DEVICE_ID_SGI_IOC3)			\
@@ -114,11 +124,14 @@
 {
 	struct pci_ops *ops = &bridge_pci_ops;
 	nasid_t nid = get_nasid();
+	int	i;
 
 	ioport_resource.end = ~0UL;
 
-	printk("PCI: Probing PCI hardware on host bus 0, node %d.\n", nid);
-	pci_scan_bus(0, ops, NULL);
+	for (i=0; i<num_bridges; i++) {
+		printk("PCI: Probing PCI hardware on host bus %2d, node %d.\n", i, nid);
+		pci_scan_bus(i, ops, NULL);
+	}
 }
 
 static inline u8
@@ -145,7 +158,11 @@
 static int __init
 pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	return (slot + (((pin-1) & 1) << 2)) & 7;
+	int rv;
+	rv = (slot + (((pin-1) & 1) << 2)) & 7;
+	rv |= (bus_to_wid[dev->bus->number] << 8);
+	rv |= (bus_to_nid[dev->bus->number] << 16);
+	return rv;
 }
 
 void __init
@@ -171,33 +188,7 @@
 void __init
 pcibios_fixup_bus(struct pci_bus *b)
 {
-	unsigned short command;
-	struct list_head *ln;
-	struct pci_dev *dev;
-
 	pci_fixup_irqs(pci_swizzle, pci_map_irq);
-
-	/*
-	 * Older qlogicisp driver expects to have the IO space enable 
-	 * bit set. Make that happen for qlogic in slots 0 and 1. Things
-	 * stop working if we program the controllers as not having
-	 * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags.
-	 */
-	for (ln=b->devices.next; ln != &b->devices; ln=ln->next) {
-		dev = pci_dev_b(ln);
-		if (PCI_FUNC(dev->devfn) == 0) {
-			if ((PCI_SLOT(dev->devfn) == 0) || 
-						(PCI_SLOT(dev->devfn) == 1)) {
-				if (pci_read_config_word(dev, PCI_COMMAND, 
-								&command) == 0) {
-					command |= PCI_COMMAND_IO;
-					pci_write_config_word(dev, PCI_COMMAND, 
-									command);
-					dev->resource[1].flags |= 1;
-				}
-			}
-		}
-	}
 }
 
 void __init
@@ -239,7 +230,7 @@
 	   with tons of bogus information in the pci_dev.  On Origins the
 	   INTA, INTB and INTC pins are all wired together as if it'd only
 	   use INTA.  */
-	printk("PCI: Fixing base addresses for device %s\n", d->slot_name);
+	printk("PCI: Fixing base addresses for IOC3 device %s\n", d->slot_name);
 
 	for (i = 1; i <= PCI_ROM_RESOURCE; i++) {
 		d->resource[i].start = 0UL;
@@ -251,8 +242,115 @@
 	d->irq = 1;
 }
 
+static void __init
+pci_fixup_isp1020(struct pci_dev *d)
+{
+	unsigned short command;
+
+	printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", d->slot_name);
+
+	/* Configure device to allow bus mastering, i/o and memory mapping. 
+	 * Older qlogicisp driver expects to have the IO space enable 
+	 * bit set. Things stop working if we program the controllers as not having
+	 * PCI_COMMAND_MEMORY, so we have to fudge the mem_flags.
+	 */
+
+	/* only turn on scsi's on main bus */
+	if (d->bus->number == 0) {
+		pci_set_master(d);
+		pci_read_config_word(d, PCI_COMMAND, &command);
+		command |= PCI_COMMAND_MEMORY;
+		command |= PCI_COMMAND_IO;
+		pci_write_config_word(d, PCI_COMMAND, command);
+		d->resource[1].flags |= 1;
+	}
+}
+static void __init
+pci_fixup_isp2x00(struct pci_dev *d)
+{
+	unsigned int bus_id = (unsigned) d->bus->number;
+	bridge_t *bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[bus_id],
+				     bus_to_wid[bus_id]);
+	bridgereg_t 	devreg;
+	int		i;
+	int		slot = PCI_SLOT(d->devfn);
+	unsigned int	start;
+	unsigned short command;
+
+	printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", d->slot_name);
+
+	/* set the resource struct for this device */
+	start = (u32) bridge;	/* yes, we want to lose the upper 32 bits here */
+	start |= BRIDGE_DEVIO(slot);
+
+	d->resource[0].start = start;
+	d->resource[0].end = d->resource[0].start + 0xff;
+	d->resource[0].flags = IORESOURCE_IO;
+
+	d->resource[1].start = start;
+	d->resource[1].end = d->resource[0].start + 0xfff;
+	d->resource[1].flags = IORESOURCE_MEM;
+
+	/*
+	 * set the bridge device(x) reg for this device
+	 */
+	devreg = bridge->b_device[slot].reg;
+	/* point device(x) to it appropriate small window */
+	devreg &= ~BRIDGE_DEV_OFF_MASK;
+	devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK;
+
+	/* turn on byte swapping in direct map mode (how we currently run dma's) */
+	devreg |= BRIDGE_DEV_SWAP_DIR;		/* turn on byte swapping */
+
+	bridge->b_device[slot].reg = devreg;
+
+	/* set card's base addr reg */
+	//pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001);
+	//pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000);
+	//pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, 0x8b20000);
+
+	/* I got these from booting irix on system...*/
+	pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x200001);
+	//pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, 0xf800000);
+	pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS,   0x10200000);
+
+	pci_conf0_write_config_dword(d, PCI_BASE_ADDRESS_1, start);
+	//pci_conf0_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000));
+
+
+	/* set cache line size */
+	pci_conf0_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080);
+
+	/* set pci bus timeout */
+	bridge->b_bus_timeout |= BRIDGE_BUS_PCI_RETRY_HLD(0x3);
+	bridge->b_wid_tflush;
+	printk("PCI: bridge bus timeout= 0x%x \n", bridge->b_bus_timeout);
+
+	/* set host error field */
+	bridge->b_int_host_err = 0x44;
+	bridge->b_wid_tflush;
+		
+	bridge->b_wid_tflush;   	/* wait until Bridge PIO complete */
+	for (i=0; i<8; i++)
+		printk("PCI: device(%d)= 0x%x\n",i,bridge->b_device[i].reg);
+
+	/* configure device to allow bus mastering, i/o and memory mapping */
+	pci_set_master(d);
+	pci_read_config_word(d, PCI_COMMAND, &command);
+	command |= PCI_COMMAND_MEMORY;
+	command |= PCI_COMMAND_IO;
+	pci_write_config_word(d, PCI_COMMAND, command);
+	/*d->resource[1].flags |= 1;*/
+}
+
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3,
 	  pci_fixup_ioc3 },
+	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020,
+	  pci_fixup_isp1020 },
+	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100,
+	  pci_fixup_isp2x00 },
+	{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200,
+	  pci_fixup_isp2x00 },
 	{ 0 }
 };
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-reset.c linux/arch/mips64/sgi-ip27/ip27-reset.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-reset.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/sgi-ip27/ip27-reset.c	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27-reset.c,v 1.1 2000/01/17 23:32:47 ralf Exp $
+/* $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
@@ -9,15 +9,22 @@
  * Copyright (C) 1997, 1998, 1999 by Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
+#include <linux/smp.h>
+#include <linux/mmzone.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/system.h>
 #include <asm/sgialib.h>
 #include <asm/sgi/sgihpc.h>
 #include <asm/sgi/sgint23.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/gda.h>
+#include <asm/sn/sn0/hub.h>
 
 void machine_restart(char *command) __attribute__((noreturn));
 void machine_halt(void) __attribute__((noreturn));
@@ -26,7 +33,19 @@
 /* XXX How to pass the reboot command to the firmware??? */
 void machine_restart(char *command)
 {
-	ArcReboot();
+	int i;
+
+	printk("Reboot started from CPU %d\n", smp_processor_id());
+#ifdef CONFIG_SMP
+	smp_send_stop();
+#endif
+#if 0
+	for (i = 0; i < numnodes; i++)
+		REMOTE_HUB_S(COMPACT_TO_NASID_NODEID(i), PROMOP_REG, 
+							PROMOP_RESTART);
+#else
+	LOCAL_HUB_S(NI_PORT_RESET, NPR_PORTRESET | NPR_LOCALRESET);
+#endif
 }
 
 void machine_halt(void)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-setup.c linux/arch/mips64/sgi-ip27/ip27-setup.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-setup.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips64/sgi-ip27/ip27-setup.c	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27-setup.c,v 1.6 2000/02/05 02:12:32 kanoj Exp $
+/* $Id: ip27-setup.c,v 1.7 2000/03/07 15:45:29 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
@@ -19,12 +19,25 @@
 #include <asm/sn/klconfig.h>
 #include <asm/ioc3.h>
 #include <asm/mipsregs.h>
+#include <asm/sn/arch.h>
+#include <asm/sn/sn_private.h>
+#include <asm/pci/bridge.h>
+#include <asm/paccess.h>
+#include <asm/sn/sn0/ip27.h>
 
 /* Check against user dumbness.  */
 #ifdef CONFIG_VT
 #error CONFIG_VT not allowed for IP27.
 #endif
 
+#undef DEBUG_SETUP
+#ifdef DEBUG_SETUP
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+
 /*
  * get_nasid() returns the physical node id number of the caller.
  */
@@ -84,12 +97,130 @@
 #endif
 }
 
+#define XBOW_WIDGET_PART_NUM    0x0
+#define XXBOW_WIDGET_PART_NUM   0xd000          /* Xbridge */
+#define BASE_XBOW_PORT  	8     /* Lowest external port */
+
+static void __init pcibr_setup(void)
+{
+	int 			i;
+	bridge_t 		*bridge; 
+	volatile u64 		hubreg;
+	nasid_t	 		nasid;
+	xwidget_part_num_t	partnum;
+	widgetreg_t 		widget_id;
+
+	num_bridges = 0;
+	/*
+	 * find what's on our local node
+	 */
+	nasid = 0;
+	hubreg = LOCAL_HUB_L(IIO_LLP_CSR);
+	if (hubreg & IIO_LLP_CSR_IS_UP) {
+		/* link is up */
+		widget_id = *(volatile widgetreg_t *)
+                        (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID);
+		partnum = XWIDGET_PART_NUM(widget_id);
+		printk("pcibr_setup(): found partnum= 0x%x ", partnum);
+		if (partnum == BRIDGE_WIDGET_PART_NUM) {
+			/*
+			 * found direct connected bridge so must be Origin200
+			 */
+			printk("...is bridge\n");
+			num_bridges = 1;
+        		bus_to_wid[0] = 0x8;
+			bus_to_nid[0] = 0;
+		}
+		if (partnum == XBOW_WIDGET_PART_NUM) {
+			lboard_t *brd;
+			klxbow_t *xbow_p;
+			/*
+			 * found xbow, so may have multiple bridges
+			 * need to probe xbow
+			 */
+			printk("...is xbow\n");
+
+			if ((brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid),
+                                   KLTYPE_MIDPLANE8)) == NULL)
+				printk("argh\n");
+			else
+				printk("brd= 0x%x\n", brd);
+			if ((xbow_p = (klxbow_t *)
+			     find_component(brd, NULL, KLSTRUCT_XBOW)) == NULL)
+				printk("argh\n");
+			else {
+			   for (i=HUB_WIDGET_ID_MIN; i<=HUB_WIDGET_ID_MAX; i++) {
+				if (!XBOW_PORT_IS_ENABLED(xbow_p, i))
+					continue;
+				if (XBOW_PORT_TYPE_IO(xbow_p, i)) {
+				   widget_id = *(volatile widgetreg_t *)
+                        		   (RAW_NODE_SWIN_BASE(nasid, i) + WIDGET_ID);
+				   partnum = XWIDGET_PART_NUM(widget_id);
+				   if (partnum == BRIDGE_WIDGET_PART_NUM) {
+					printk("widget 0x%x is a bridge\n", i);
+					bus_to_wid[num_bridges] = i;
+					bus_to_nid[num_bridges] = nasid;
+					num_bridges++;
+				   }
+				}
+			   }
+			}
+		}
+		if (partnum == XXBOW_WIDGET_PART_NUM) {
+			/*
+			 * found xbridge, assume ibrick for now 
+			 */
+			printk("...is xbridge\n");
+        		bus_to_wid[0] = 0xb;
+        		bus_to_wid[1] = 0xe;
+        		bus_to_wid[2] = 0xf;
+
+        		bus_to_nid[0] = 0;
+        		bus_to_nid[1] = 0;
+        		bus_to_nid[2] = 0;
+
+			num_bridges = 3;
+		}
+	}
+	/*
+         * set bridge registers
+         */
+	for (i=0; i<num_bridges; i++) {
+		DBG("pcibr_setup: bus= %d  bus_to_wid[%2d]= %d  bus_to_nid[%2d]= %d\n",
+                        i, i, bus_to_wid[i], i, bus_to_nid[i]);
+
+		/*
+		 * point to this bridge
+		 */
+		bridge = (bridge_t *) NODE_SWIN_BASE(bus_to_nid[i],bus_to_wid[i]);
+		/*
+	 	 * Clear all pending interrupts.
+	 	 */
+		bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR);
+		/*
+	 	 * Until otherwise set up, assume all interrupts are from slot 0
+	 	 */
+		bridge->b_int_device = (u32) 0x0;
+		/*
+	 	 * swap pio's to pci mem and io space (big windows)
+	 	 */
+		bridge->b_wid_control |= BRIDGE_CTRL_IO_SWAP;
+		bridge->b_wid_control |= BRIDGE_CTRL_MEM_SWAP;
+
+		bridge->b_wid_tflush;     /* wait until Bridge PIO complete */
+	}
+}
+
 void __init ip27_setup(void)
 {
 	nasid_t nid;
 	hubreg_t p, e;
 
-	set_cp0_status(ST0_IM, 0);
+	/*
+	 * hub_rtc init and cpu clock intr enabled for later calibrate_delay.
+	 */
+	DBG("ip27_setup(): Entered.\n");
+	per_cpu_init();
 	nid = get_nasid();
 	printk("IP27: Running on node %d.\n", nid);
 
@@ -108,4 +239,9 @@
 	verify_mode();
 	ioc3_sio_init();
 	ioc3_eth_init();
+
+	DBG("ip27_setup(): calling pcibr_setup\n");
+	/* set some bridge registers */
+	pcibr_setup();
+	DBG("ip27_setup(): Exit.\n");
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-timer.c linux/arch/mips64/sgi-ip27/ip27-timer.c
--- v2.3.99-pre8/linux/arch/mips64/sgi-ip27/ip27-timer.c	Thu Mar  2 14:36:22 2000
+++ linux/arch/mips64/sgi-ip27/ip27-timer.c	Mon May 15 12:10:26 2000
@@ -3,6 +3,7 @@
  * Copytight (C) 1999 Ralf Baechle (ralf@gnu.org)
  * Copytight (C) 1999 Silicon Graphics, Inc.
  */
+#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -19,6 +20,7 @@
 #include <asm/sn/klconfig.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/addrs.h>
+#include <asm/sn/sn_private.h>
 #include <asm/sn/sn0/ip27.h>
 #include <asm/sn/sn0/hub.h>
 
@@ -44,7 +46,6 @@
 {               
         int retval = 0;
         int real_seconds, real_minutes, cmos_minutes;
-        unsigned char save_control, save_freq_select;
 	struct m48t35_rtc *rtc;
 	nasid_t nid;
 
@@ -89,20 +90,50 @@
 
 void rt_timer_interrupt(struct pt_regs *regs)
 {
+	int cpu = smp_processor_id();
+	int cpuA = ((cputoslice(smp_processor_id())) == 0);
+	int user = user_mode(regs);
 	int irq = 7;				/* XXX Assign number */
 
 	write_lock(&xtime_lock);
 
 again:
-	LOCAL_HUB_S(PI_RT_PEND_A, 0);		/* Ack  */
+	LOCAL_HUB_S(cpuA ? PI_RT_PEND_A : PI_RT_PEND_B, 0);	/* Ack  */
 	ct_cur += CYCLES_PER_JIFFY;
-	LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
+	LOCAL_HUB_S(cpuA ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, ct_cur);
 
 	if (LOCAL_HUB_L(PI_RT_COUNT) >= ct_cur)
 		goto again;
 
-	kstat.irqs[0][irq]++;
+	kstat.irqs[cpu][irq]++;		/* kstat+do_timer only for bootcpu? */
 	do_timer(regs);
+
+#ifdef CONFIG_SMP
+	if (current->pid) {
+		unsigned int *inc, *inc2;
+
+		update_one_process(current, 1, user, !user, cpu);
+		if (--current->counter <= 0) {
+			current->counter = 0;
+			current->need_resched = 1;
+		}
+
+		if (user) {
+			if (current->priority < DEF_PRIORITY) {
+				inc = &kstat.cpu_nice;
+				inc2 = &kstat.per_cpu_nice[cpu];
+			} else {
+				inc = &kstat.cpu_user;
+				inc2 = &kstat.per_cpu_user[cpu];
+			}
+		} else {
+			inc = &kstat.cpu_system;
+			inc2 = &kstat.per_cpu_system[cpu];
+		}
+		atomic_inc((atomic_t *)inc);
+		atomic_inc((atomic_t *)inc2);
+	}
+#endif /* CONFIG_SMP */
 	
         /*
          * If we have an externally synchronized Linux clock, then update
@@ -194,7 +225,8 @@
 	nasid_t nid;
 
 	nid = get_nasid();
-	rtc = KL_CONFIG_CH_CONS_INFO(nid)->memory_base + IOC3_BYTEBUS_DEV0;
+	rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + 
+							IOC3_BYTEBUS_DEV0);
 
         rtc->control |= M48T35_RTC_READ;
 	sec = rtc->sec;
@@ -221,15 +253,18 @@
 
 void __init time_init(void)
 {
+	xtime.tv_sec = get_m48t35_time();
+	xtime.tv_usec = 0;
+}
+
+void __init cpu_time_init(void)
+{
 	lboard_t *board;
 	klcpu_t *cpu;
 	int cpuid;
 	
-	xtime.tv_sec = get_m48t35_time();
-	xtime.tv_usec = 0;
-
 	/* Don't use ARCS.  ARCS is fragile.  Klconfig is simple and sane.  */
-	board = find_lboard(KLTYPE_IP27);
+	board = find_lboard(KL_CONFIG_INFO(get_nasid()), KLTYPE_IP27);
 	if (!board)
 		panic("Can't find board info for myself.");
 
@@ -238,15 +273,29 @@
 	if (!cpu)
 		panic("No information about myself?");
 
-	printk("CPU clock is %dMHz.\n", cpu->cpu_speed);
-
-	/* Don't worry about second CPU, it's disabled.  */
-	LOCAL_HUB_S(PI_RT_EN_A, 1);
-	LOCAL_HUB_S(PI_PROF_EN_A, 0);
-	ct_cur = CYCLES_PER_JIFFY;
-	LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
-	LOCAL_HUB_S(PI_RT_COUNT, 0);
-	LOCAL_HUB_S(PI_RT_PEND_A, 0);
+	printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed);
 
 	set_cp0_status(SRB_TIMOCLK, SRB_TIMOCLK);
+}
+
+void __init hub_rtc_init(cnodeid_t cnode)
+{
+	/*
+	 * We only need to initialize the current node.
+	 * If this is not the current node then it is a cpuless
+	 * node and timeouts will not happen there.
+	 */
+	if (get_compact_nodeid() == cnode) {
+		LOCAL_HUB_S(PI_RT_EN_A, 1);
+		LOCAL_HUB_S(PI_RT_EN_B, 1);
+		LOCAL_HUB_S(PI_PROF_EN_A, 0);
+		LOCAL_HUB_S(PI_PROF_EN_B, 0);
+		ct_cur = CYCLES_PER_JIFFY;
+		LOCAL_HUB_S(PI_RT_COMPARE_A, ct_cur);
+		LOCAL_HUB_S(PI_RT_COUNT, 0);
+		LOCAL_HUB_S(PI_RT_PEND_A, 0);
+		LOCAL_HUB_S(PI_RT_COMPARE_B, ct_cur);
+		LOCAL_HUB_S(PI_RT_COUNT, 0);
+		LOCAL_HUB_S(PI_RT_PEND_B, 0);
+	}
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/tools/Makefile linux/arch/mips64/tools/Makefile
--- v2.3.99-pre8/linux/arch/mips64/tools/Makefile	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/tools/Makefile	Sat May 13 08:30:17 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.2 1999/12/04 03:59:01 ralf Exp $
+# $Id: Makefile,v 1.1 1999/08/18 21:46:53 ralf Exp $
 #
 # Makefile for MIPS kernel build tools.
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/mips64/tools/offset.c linux/arch/mips64/tools/offset.c
--- v2.3.99-pre8/linux/arch/mips64/tools/offset.c	Sat Feb 26 22:31:41 2000
+++ linux/arch/mips64/tools/offset.c	Sat May 13 08:30:17 2000
@@ -82,6 +82,7 @@
 	offset("#define TASK_COUNTER       ", struct task_struct, counter);
 	offset("#define TASK_PRIORITY      ", struct task_struct, priority);
 	offset("#define TASK_MM            ", struct task_struct, mm);
+	offset("#define TASK_PROCESSOR     ", struct task_struct, processor);
 	size("#define TASK_STRUCT_SIZE   ", struct task_struct);
 	linefeed;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/8260_io/enet.c linux/arch/ppc/8260_io/enet.c
--- v2.3.99-pre8/linux/arch/ppc/8260_io/enet.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/8260_io/enet.c	Mon May 15 14:53:30 2000
@@ -689,8 +689,8 @@
 	cep->dirty_tx = cep->cur_tx = cep->tx_bd_base;
 	cep->cur_rx = cep->rx_bd_base;
 
-	ep->sen_genscc.scc_rfcr = SCC_EB;
-	ep->sen_genscc.scc_tfcr = SCC_EB;
+	ep->sen_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	ep->sen_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
 
 	/* Set maximum bytes per receive buffer.
 	 * This appears to be an Ethernet frame size, not the buffer
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/8260_io/uart.c linux/arch/ppc/8260_io/uart.c
--- v2.3.99-pre8/linux/arch/ppc/8260_io/uart.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/8260_io/uart.c	Mon May 15 14:53:30 2000
@@ -2536,8 +2536,8 @@
 				/* Set up the uart parameters in the
 				 * parameter ram.
 				 */
-				up->smc_rfcr = SMC_EB;
-				up->smc_tfcr = SMC_EB;
+				up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+				up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
 
 				/* Set this to 1 for now, so we get single
 				 * character interrupts.  Using idle charater
@@ -2579,8 +2579,8 @@
 				/* Set up the uart parameters in the
 				 * parameter ram.
 				 */
-				sup->scc_genscc.scc_rfcr = SMC_EB;
-				sup->scc_genscc.scc_tfcr = SMC_EB;
+				sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+				sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
 
 				/* Set this to 1 for now, so we get single
 				 * character interrupts.  Using idle charater
@@ -2741,8 +2741,8 @@
 	*/
 	up->smc_rbase = dp_addr;	/* Base of receive buffer desc. */
 	up->smc_tbase = dp_addr+sizeof(cbd_t);	/* Base of xmt buffer desc. */
-	up->smc_rfcr = SMC_EB;
-	up->smc_tfcr = SMC_EB;
+	up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
+	up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
 
 	/* Set this to 1 for now, so we get single character interrupts.
 	*/
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig
--- v2.3.99-pre8/linux/arch/ppc/configs/common_defconfig	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/configs/common_defconfig	Mon May 15 14:53:30 2000
@@ -15,10 +15,11 @@
 CONFIG_6xx=y
 # CONFIG_4xx is not set
 # CONFIG_PPC64 is not set
-# CONFIG_82xx is not set
+# CONFIG_8260 is not set
 # CONFIG_8xx is not set
 CONFIG_ALL_PPC=y
 # CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
 # CONFIG_APUS is not set
 # CONFIG_SMP is not set
 CONFIG_ALTIVEC=y
@@ -159,10 +160,10 @@
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
@@ -377,6 +378,11 @@
 # CONFIG_HAMRADIO is not set
 
 #
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
@@ -607,6 +613,7 @@
 CONFIG_DMASOUND_AWACS=y
 CONFIG_DMASOUND=y
 # CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
@@ -688,3 +695,4 @@
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_KGDB is not set
 CONFIG_XMON=y
+
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/defconfig linux/arch/ppc/defconfig
--- v2.3.99-pre8/linux/arch/ppc/defconfig	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/defconfig	Mon May 15 14:53:30 2000
@@ -15,10 +15,11 @@
 CONFIG_6xx=y
 # CONFIG_4xx is not set
 # CONFIG_PPC64 is not set
-# CONFIG_82xx is not set
+# CONFIG_8260 is not set
 # CONFIG_8xx is not set
 CONFIG_ALL_PPC=y
 # CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
 # CONFIG_APUS is not set
 # CONFIG_SMP is not set
 CONFIG_ALTIVEC=y
@@ -159,10 +160,10 @@
 # CONFIG_BLK_DEV_RZ1000 is not set
 CONFIG_BLK_DEV_IDEPCI=y
 # CONFIG_IDEPCI_SHARE_IRQ is not set
-# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+CONFIG_BLK_DEV_IDEDMA=y
 CONFIG_IDEDMA_PCI_EXPERIMENTAL=y
 # CONFIG_IDEDMA_PCI_WIP is not set
 # CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
@@ -377,6 +378,11 @@
 # CONFIG_HAMRADIO is not set
 
 #
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
 # ISDN subsystem
 #
 # CONFIG_ISDN is not set
@@ -608,6 +614,7 @@
 CONFIG_DMASOUND_AWACS=y
 CONFIG_DMASOUND=y
 # CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
 # CONFIG_SOUND_ES1370 is not set
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/chrp_pci.c	Thu Feb 10 17:11:04 2000
+++ linux/arch/ppc/kernel/chrp_pci.c	Mon May 15 14:53:30 2000
@@ -17,6 +17,7 @@
 #include <asm/prom.h>
 #include <asm/gg2.h>
 #include <asm/machdep.h>
+#include <asm/init.h>
 
 #include "pci.h"
 
@@ -31,7 +32,7 @@
  * limit the bus number to 3 bits
  */
 
-int gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+int __chrp gg2_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
 				 unsigned char offset, unsigned char *val)
 {
 	if (bus > 7) {
@@ -42,7 +43,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+int __chrp gg2_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
 				 unsigned char offset, unsigned short *val)
 {
 	if (bus > 7) {
@@ -54,7 +55,7 @@
 }
 
 
-int gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+int __chrp gg2_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
 				  unsigned char offset, unsigned int *val)
 {
 	if (bus > 7) {
@@ -65,7 +66,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+int __chrp gg2_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
 				  unsigned char offset, unsigned char val)
 {
 	if (bus > 7)
@@ -74,7 +75,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+int __chrp gg2_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
 				  unsigned char offset, unsigned short val)
 {
 	if (bus > 7)
@@ -83,7 +84,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+int __chrp gg2_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
 				   unsigned char offset, unsigned int val)
 {
 	if (bus > 7)
@@ -98,7 +99,7 @@
 				 | (((o) & ~3) << 24))
 unsigned int python_busnr = 0;
 
-int python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+int __chrp python_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
 				    unsigned char offset, unsigned char *val)
 {
 	if (bus > python_busnr) {
@@ -110,7 +111,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+int __chrp python_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
 				    unsigned char offset, unsigned short *val)
 {
 	if (bus > python_busnr) {
@@ -123,7 +124,7 @@
 }
 
 
-int python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+int __chrp python_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
 				     unsigned char offset, unsigned int *val)
 {
 	if (bus > python_busnr) {
@@ -135,7 +136,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+int __chrp python_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
 				     unsigned char offset, unsigned char val)
 {
 	if (bus > python_busnr)
@@ -145,7 +146,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+int __chrp python_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
 				     unsigned char offset, unsigned short val)
 {
 	if (bus > python_busnr)
@@ -156,7 +157,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+int __chrp python_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
 				      unsigned char offset, unsigned int val)
 {
 	if (bus > python_busnr)
@@ -167,7 +168,7 @@
 }
 
 
-int rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
+int __chrp rtas_pcibios_read_config_byte(unsigned char bus, unsigned char dev_fn,
 				    unsigned char offset, unsigned char *val)
 {
 	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
@@ -176,7 +177,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
+int __chrp rtas_pcibios_read_config_word(unsigned char bus, unsigned char dev_fn,
 				    unsigned char offset, unsigned short *val)
 {
 	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
@@ -186,7 +187,7 @@
 }
 
 
-int rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
+int __chrp rtas_pcibios_read_config_dword(unsigned char bus, unsigned char dev_fn,
 				     unsigned char offset, unsigned int *val)
 {
 	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
@@ -195,7 +196,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
+int __chrp rtas_pcibios_write_config_byte(unsigned char bus, unsigned char dev_fn,
 				     unsigned char offset, unsigned char val)
 {
 	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
@@ -204,7 +205,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
+int __chrp rtas_pcibios_write_config_word(unsigned char bus, unsigned char dev_fn,
 				     unsigned char offset, unsigned short val)
 {
 	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
@@ -213,7 +214,7 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-int rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
+int __chrp rtas_pcibios_write_config_dword(unsigned char bus, unsigned char dev_fn,
 				      unsigned char offset, unsigned int val)
 {
 	unsigned long addr = (offset&0xff) | ((dev_fn&0xff)<<8) | ((bus & 0xff)<<16);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/chrp_setup.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon May 15 14:53:30 2000
@@ -49,6 +49,7 @@
 #include <asm/irq.h>
 #include <asm/hydra.h>
 #include <asm/keyboard.h>
+#include <asm/init.h>
 
 #include "time.h"
 #include "local_irq.h"
@@ -112,7 +113,7 @@
 	"Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
 };
 
-int
+int __chrp
 chrp_get_cpuinfo(char *buffer)
 {
 	int i, len, sdramen;
@@ -306,7 +307,7 @@
 	}
 }
 
-void
+void __chrp
 chrp_event_scan(void)
 {
 	unsigned char log[1024];
@@ -317,7 +318,7 @@
 	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
 }
 	
-void
+void __chrp
 chrp_restart(char *cmd)
 {
 	printk("RTAS system-reboot returned %d\n",
@@ -325,7 +326,7 @@
 	for (;;);
 }
 
-void
+void __chrp
 chrp_power_off(void)
 {
 	/* allow power on only with power button press */
@@ -334,13 +335,13 @@
 	for (;;);
 }
 
-void
+void __chrp
 chrp_halt(void)
 {
 	chrp_power_off();
 }
 
-u_int
+u_int __chrp
 chrp_irq_cannonicalize(u_int irq)
 {
 	if (irq == 2)
@@ -353,7 +354,7 @@
 	}
 }
 
-int chrp_get_irq( struct pt_regs *regs )
+int __chrp chrp_get_irq( struct pt_regs *regs )
 {
         int irq;
 
@@ -383,7 +384,7 @@
 	return irq;
 }
 
-void chrp_post_irq(struct pt_regs* regs, int irq)
+void __chrp chrp_post_irq(struct pt_regs* regs, int irq)
 {
 	/*
 	 * If it's an i8259 irq then we've already done the
@@ -445,7 +446,7 @@
 ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
 ide_ioreg_t chrp_idedma_regbase;
 
-void
+void __chrp
 chrp_ide_probe(void)
 {
         struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
@@ -460,19 +461,19 @@
         }
 }
 
-void
+void __chrp
 chrp_ide_insw(ide_ioreg_t port, void *buf, int ns)
 {
 	ide_insw(port+_IO_BASE, buf, ns);
 }
 
-void
+void __chrp
 chrp_ide_outsw(ide_ioreg_t port, void *buf, int ns)
 {
 	ide_outsw(port+_IO_BASE, buf, ns);
 }
 
-int
+int __chrp
 chrp_ide_default_irq(ide_ioreg_t base)
 {
         if (chrp_ide_ports_known == 0)
@@ -480,7 +481,7 @@
 	return chrp_ide_irq;
 }
 
-ide_ioreg_t
+ide_ioreg_t __chrp
 chrp_ide_default_io_base(int index)
 {
         if (chrp_ide_ports_known == 0)
@@ -488,13 +489,13 @@
 	return chrp_ide_regbase[index];
 }
 
-int
+int __chrp
 chrp_ide_check_region(ide_ioreg_t from, unsigned int extent)
 {
         return check_region(from, extent);
 }
 
-void
+void __chrp
 chrp_ide_request_region(ide_ioreg_t from,
 			unsigned int extent,
 			const char *name)
@@ -502,20 +503,20 @@
         request_region(from, extent, name);
 }
 
-void
+void __chrp
 chrp_ide_release_region(ide_ioreg_t from,
 			unsigned int extent)
 {
         release_region(from, extent);
 }
 
-void
+void __chrp
 chrp_ide_fix_driveid(struct hd_driveid *id)
 {
         ppc_generic_ide_fix_driveid(id);
 }
 
-void
+void __chrp
 chrp_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
 {
 	ide_ioreg_t reg = data_port;
@@ -629,7 +630,7 @@
 	if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
 }
 
-void
+void __chrp
 chrp_progress(char *s, unsigned short hex)
 {
 	extern unsigned int rtas_data;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/chrp_time.c	Fri Mar 10 16:40:40 2000
+++ linux/arch/ppc/kernel/chrp_time.c	Mon May 15 14:53:30 2000
@@ -25,6 +25,7 @@
 #include <asm/processor.h>
 #include <asm/nvram.h>
 #include <asm/prom.h>
+#include <asm/init.h>
 #include "time.h"
 
 static int nvram_as1 = NVRAM_AS1;
@@ -45,7 +46,7 @@
 	nvram_data = base + 1;
 }
 
-int chrp_cmos_clock_read(int addr)
+int __chrp chrp_cmos_clock_read(int addr)
 {
 	if (nvram_as1 != 0)
 		outb(addr>>8, nvram_as1);
@@ -53,7 +54,7 @@
 	return (inb(nvram_data));
 }
 
-void chrp_cmos_clock_write(unsigned long val, int addr)
+void __chrp chrp_cmos_clock_write(unsigned long val, int addr)
 {
 	if (nvram_as1 != 0)
 		outb(addr>>8, nvram_as1);
@@ -65,7 +66,7 @@
 /*
  * Set the hardware clock. -- Cort
  */
-int chrp_set_rtc_time(unsigned long nowtime)
+int __chrp chrp_set_rtc_time(unsigned long nowtime)
 {
 	unsigned char save_control, save_freq_select;
 	struct rtc_time tm;
@@ -111,7 +112,7 @@
 	return 0;
 }
 
-unsigned long chrp_get_rtc_time(void)
+unsigned long __chrp chrp_get_rtc_time(void)
 {
 	unsigned int year, mon, day, hour, min, sec;
 	int i;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.3.99-pre8/linux/arch/ppc/kernel/entry.S	Sat Feb 26 22:31:41 2000
+++ linux/arch/ppc/kernel/entry.S	Mon May 15 14:53:30 2000
@@ -291,25 +291,9 @@
 	 * -- Cort
 	 */
 	cmpi	0,r3,0
-	bne	ret_from_except
-	/*
-	 * If we're returning from user mode we do things differently
-	 * -- Cort
-	 */
-	lwz	r3,_MSR(r1)
-	andi.	r3,r3,MSR_PR
-	beq+	10f
-	b	8f
-
+	beq	restore
 	.globl	ret_from_except
 ret_from_except:
-0:	/* disable interrupts */
-	lis	r30,int_control@h
-	ori	r30,r30,int_control@l
-	lwz	r30,0(r30)
-	mtlr	r30
-	blrl
-	
 	lwz	r5,_MSR(r1)
 	andi.	r5,r5,MSR_EE
 	beq	2f
@@ -341,65 +325,58 @@
 	bl	do_softirq
 	.globl	do_bottom_half_ret
 do_bottom_half_ret:
-2:	/* disable interrupts */	
-	lis	r30,int_control@h
-	ori	r30,r30,int_control@l
-	lwz	r30,0(r30)
-	mtlr	r30
-	blrl
-	lwz	r3,_MSR(r1)	/* Returning to user mode? */
+2:	lwz	r3,_MSR(r1)	/* Returning to user mode? */
 	andi.	r3,r3,MSR_PR
-	beq+	10f		/* if so, check need_resched and signals */
+	beq+	restore		/* if so, check need_resched and signals */
+	.globl ret_to_user_hook	
+ret_to_user_hook:
+	nop
 	lwz	r3,NEED_RESCHED(r2)
 	cmpi	0,r3,0		/* check need_resched flag */
 	beq+	7f
 	bl	schedule
-	b	0b
 7:	lwz	r5,SIGPENDING(r2) /* Check for pending unblocked signals */
 	cmpwi	0,r5,0
-	beq+	8f
+	beq+	restore
 	li	r3,0
 	addi	r4,r1,STACK_FRAME_OVERHEAD
 	bl	do_signal
 	.globl	do_signal_ret
 do_signal_ret:
-	b	0b
-8:	/* 
-	 * We need to hard disable here even if RTL is active since
-	 * being interrupted after here trashes the SPRG2
-	 *  -- Cort
-	 */ 
-	mfmsr	r0		/* Get current interrupt state */
-	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
-	mtmsr	r0		/* Update machine state */
-	
-	addi	r4,r1,INT_FRAME_SIZE	/* size of frame */
-	stw	r4,THREAD+KSP(r2)	/* save kernel stack pointer */
-	tophys(r3,r1)
-	mtspr	SPRG2,r3	/* phys exception stack pointer */
-	b	11f
-10:	/* make sure we hard disable here, even if rtl is active -- Cort */
-	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 */
-11: 
-	lwz	r2,_CTR(r1)
+restore:	
+	lwz	r3,_CTR(r1)
 	lwz	r0,_LINK(r1)
-	mtctr	r2
+	mtctr	r3
 	mtlr	r0
-	lwz	r2,_XER(r1)
-	lwz	r0,_CCR(r1)
-	mtspr	XER,r2
-	mtcrf	0xFF,r0
+	lwz	r3,_XER(r1)
+	mtspr	XER,r3
 	REST_10GPRS(3, r1)
 	REST_10GPRS(13, r1)
 	REST_8GPRS(23, r1)
 	REST_GPR(31, r1)
-	lwz	r2,_NIP(r1)	/* Restore environment */
+	
+	/* make sure we hard disable here, even if rtl is active, to protect
+	 * SRR[01] and SPRG2 -- Cort 
+	 */
+	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 */
+	
+	/* if returning to user mode, set new sprg2 and save kernel SP */
 	lwz	r0,_MSR(r1)
-	mtspr	SRR0,r2
 	mtspr	SRR1,r0
+	andi.	r0,r0,MSR_PR
+	beq+	1f
+	addi	r0,r1,INT_FRAME_SIZE	/* size of frame */
+	stw	r0,THREAD+KSP(r2)	/* save kernel stack pointer */
+	tophys(r2,r1)
+	mtspr	SPRG2,r2	/* phys exception stack pointer */
+1:	
+	lwz	r2,_CCR(r1)
+	mtcrf	0xFF,r2
+	lwz	r2,_NIP(r1)
+	mtspr	SRR0,r2
 	lwz	r0,GPR0(r1)
 	lwz	r2,GPR2(r1)
 	lwz	r1,GPR1(r1)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.3.99-pre8/linux/arch/ppc/kernel/head.S	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/kernel/head.S	Mon May 15 14:53:30 2000
@@ -1459,7 +1459,8 @@
 /*
  * Set up the segment registers for a new context.
  */
-_GLOBAL(set_context)
+	.globl set_context
+set_context:	
 	rlwinm	r3,r3,4,8,27	/* VSID = context << 4 */
 	addis	r3,r3,0x6000	/* Set Ks, Ku bits */
 	li	r0,12		/* TASK_SIZE / SEGMENT_SIZE */
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/ppc_ksyms.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon May 15 14:53:30 2000
@@ -58,6 +58,7 @@
 long long __ashldi3(long long, int);
 long long __lshrdi3(long long, int);
 int abs(int);
+extern unsigned long ret_to_user_hook;
 
 EXPORT_SYMBOL(clear_page);
 EXPORT_SYMBOL(do_signal);
@@ -284,3 +285,5 @@
 EXPORT_SYMBOL(debugger_iabr_match);
 EXPORT_SYMBOL(debugger_dabr_match);
 EXPORT_SYMBOL(debugger_fault_handler);
+
+EXPORT_SYMBOL(ret_to_user_hook);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/ptrace.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/ppc/kernel/ptrace.c	Mon May 15 14:53:30 2000
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/ppc/kernel/ptrace.c
  *
- *  PowerPC version 
+ *  PowerPC version
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *
  *  Derived from "arch/m68k/kernel/ptrace.c"
@@ -9,14 +9,14 @@
  *  Taken from linux/kernel/ptrace.c and modified for M680x0.
  *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
  *
- * Modified by Cort Dougan (cort@cs.nmt.edu) 
+ * Modified by Cort Dougan (cort@hq.fsmlabs.com)
+ * and Paul Mackerras (paulus@linuxcare.com.au).
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file README.legal in the main directory of
  * this archive for more details.
  */
 
-#include <stddef.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
@@ -26,7 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 
-#include <asm/segment.h>
+#include <asm/uaccess.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
@@ -44,7 +44,7 @@
 /*
  * Get contents of register REGNO in task TASK.
  */
-static inline long get_reg(struct task_struct *task, int regno)
+static inline unsigned long get_reg(struct task_struct *task, int regno)
 {
 	if (regno < sizeof(struct pt_regs) / sizeof(unsigned long))
 		return ((unsigned long *)task->thread.regs)[regno];
@@ -64,7 +64,7 @@
 		((unsigned long *)task->thread.regs)[regno] = data;
 		return 0;
 	}
-	return -1;
+	return -EIO;
 }
 
 static inline void
@@ -81,216 +81,10 @@
 	regs->msr &= ~MSR_SE;
 }
 
-#if 0
-/*
- * This routine gets a long from any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- */
-static unsigned long get_long(struct task_struct * tsk, 
-	struct vm_area_struct * vma, unsigned long addr)
-{
-	pgd_t * pgdir;
-	pmd_t * pgmiddle;
-	pte_t * pgtable;
-	unsigned long page;
-
-repeat:
-	pgdir = pgd_offset(vma->vm_mm, addr);
-	if (pgd_none(*pgdir)) {
-		handle_mm_fault(tsk->mm, vma, addr, 0);
-		goto repeat;
-	}
-	if (pgd_bad(*pgdir)) {
-		printk("ptrace[1]: bad page directory %lx\n", pgd_val(*pgdir));
-		pgd_clear(pgdir);
-		return 0;
-	}
-	pgmiddle = pmd_offset(pgdir,addr);
-	if (pmd_none(*pgmiddle)) {
-		handle_mm_fault(tsk->mm, vma, addr, 0);
-		goto repeat;
-	}
-	if (pmd_bad(*pgmiddle)) {
-		printk("ptrace[3]: bad pmd %lx\n", pmd_val(*pgmiddle));
-		pmd_clear(pgmiddle);
-		return 0;
-	}
-	pgtable = pte_offset(pgmiddle, addr);
-	if (!pte_present(*pgtable)) {
-		handle_mm_fault(tsk->mm, vma, addr, 0);
-		goto repeat;
-	}
-	page = pte_page(*pgtable);
-/* this is a hack for non-kernel-mapped video buffers and similar */
-	if (MAP_NR(page) >= max_mapnr)
-		return 0;
-	page += addr & ~PAGE_MASK;
-	return *(unsigned long *) page;
-}
-
-/*
- * This routine puts a long into any process space by following the page
- * tables. NOTE! You should check that the long isn't on a page boundary,
- * and that it is in the task area before calling this: this routine does
- * no checking.
- *
- * Now keeps R/W state of page so that a text page stays readonly
- * even if a debugger scribbles breakpoints into it.  -M.U-
- */
-static void put_long(struct task_struct * tsk, struct vm_area_struct * vma,
-		     unsigned long addr, unsigned long data)
-{
-	pgd_t *pgdir;
-	pmd_t *pgmiddle;
-	pte_t *pgtable;
-	unsigned long page;
-		
-repeat:
-	pgdir = pgd_offset(vma->vm_mm, addr);
-	if (!pgd_present(*pgdir)) {
-		handle_mm_fault(tsk->mm, vma, addr, 1);
-		goto repeat;
-	}
-	if (pgd_bad(*pgdir)) {
-		printk("ptrace[2]: bad page directory %lx\n", pgd_val(*pgdir));
-		pgd_clear(pgdir);
-		return;
-	}
-	pgmiddle = pmd_offset(pgdir,addr);
-	if (pmd_none(*pgmiddle)) {
-		handle_mm_fault(tsk->mm, vma, addr, 1);
-		goto repeat;
-	}
-	if (pmd_bad(*pgmiddle)) {
-		printk("ptrace[4]: bad pmd %lx\n", pmd_val(*pgmiddle));
-		pmd_clear(pgmiddle);
-		return;
-	}
-	pgtable = pte_offset(pgmiddle, addr);
-	if (!pte_present(*pgtable)) {
-		handle_mm_fault(tsk->mm, vma, addr, 1);
-		goto repeat;
-	}
-	page = pte_page(*pgtable);
-	if (!pte_write(*pgtable)) {
-		handle_mm_fault(tsk->mm, vma, addr, 1);
-		goto repeat;
-	}
-/* this is a hack for non-kernel-mapped video buffers and similar */
-	if (MAP_NR(page) < max_mapnr) {
-		unsigned long phys_addr = page + (addr & ~PAGE_MASK);
-		*(unsigned long *) phys_addr = data;
-		flush_icache_range(phys_addr, phys_addr+4);
-	}
-/* we're bypassing pagetables, so we have to set the dirty bit ourselves */
-/* this should also re-instate whatever read-only mode there was before */
-	set_pte(pgtable, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
-	flush_tlb_all();
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls get_long() to read a long.
- */
-static int read_long(struct task_struct * tsk, unsigned long addr,
-	unsigned long * result)
-{
-	struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr);
-
-	if (!vma)
-		return -EIO;
-	if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-		unsigned long low,high;
-		struct vm_area_struct * vma_low = vma;
-
-		if (addr + sizeof(long) >= vma->vm_end) {
-			vma_low = vma->vm_next;
-			if (!vma_low || vma_low->vm_start != vma->vm_end)
-				return -EIO;
-		}
-		high = get_long(tsk, vma,addr & ~(sizeof(long)-1));
-		low = get_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1));
-		switch (addr & (sizeof(long)-1)) {
-			case 3:
-				low >>= 8;
-				low |= high << 24;
-				break;
-			case 2:
-				low >>= 16;
-				low |= high << 16;
-				break;
-			case 1:
-				low >>= 24;
-				low |= high << 8;
-				break;
-		}
-		*result = low;
-	} else
-		*result = get_long(tsk, vma,addr);
-	return 0;
-}
-
-/*
- * This routine checks the page boundaries, and that the offset is
- * within the task area. It then calls put_long() to write a long.
- */
-static int write_long(struct task_struct * tsk, unsigned long addr,
-	unsigned long data)
-{
-	struct vm_area_struct * vma = find_extend_vma(tsk->mm, addr);
-
-	if (!vma)
-		return -EIO;
-	if ((addr & ~PAGE_MASK) > PAGE_SIZE-sizeof(long)) {
-		unsigned long low,high;
-		struct vm_area_struct * vma_low = vma;
-
-		if (addr + sizeof(long) >= vma->vm_end) {
-			vma_low = vma->vm_next;
-			if (!vma_low || vma_low->vm_start != vma->vm_end)
-				return -EIO;
-		}
-		high = get_long(tsk, vma,addr & ~(sizeof(long)-1));
-		low = get_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1));
-		switch (addr & (sizeof(long)-1)) {
-			case 0: /* shouldn't happen, but safety first */
-				high = data;
-				break;
-			case 3:
-				low &= 0x000000ff;
-				low |= data << 8;
-				high &= ~0xff;
-				high |= data >> 24;
-				break;
-			case 2:
-				low &= 0x0000ffff;
-				low |= data << 16;
-				high &= ~0xffff;
-				high |= data >> 16;
-				break;
-			case 1:
-				low &= 0x00ffffff;
-				low |= data << 24;
-				high &= ~0xffffff;
-				high |= data >> 8;
-				break;
-		}
-		put_long(tsk, vma,addr & ~(sizeof(long)-1),high);
-		put_long(tsk, vma_low,(addr+sizeof(long)) & ~(sizeof(long)-1),low);
-	} else
-		put_long(tsk, vma,addr,data);
-	return 0;
-}
-#endif
-
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret = -EPERM;
-	unsigned long flags;
 
 	lock_kernel();
 	if (request == PTRACE_TRACEME) {
@@ -302,209 +96,209 @@
 		ret = 0;
 		goto out;
 	}
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
 	ret = -ESRCH;
 	read_lock(&tasklist_lock);
 	child = find_task_by_pid(pid);
-	read_unlock(&tasklist_lock);	/* FIXME!!! */
-	if ( !child )
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
 		goto out;
+
 	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out_tsk;
+
 	if (request == PTRACE_ATTACH) {
 		if (child == current)
-			goto out;
+			goto out_tsk;
 		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
-		    (current->uid != child->uid) ||
 		    (current->uid != child->suid) ||
+		    (current->uid != child->uid) ||
 	 	    (current->gid != child->egid) ||
-	 	    (current->gid != child->gid) ||
 		    (current->gid != child->sgid) ||
-		    (!cap_issubset(child->cap_permitted, current->cap_permitted)))
+		    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+		    (current->gid != child->gid))
 		    && !capable(CAP_SYS_PTRACE))
-			goto out;
+			goto out_tsk;
 		/* the same process cannot be attached many times */
 		if (child->flags & PF_PTRACED)
-			goto out;
+			goto out_tsk;
 		child->flags |= PF_PTRACED;
-		
-		write_lock_irqsave(&tasklist_lock, flags);
+
+		write_lock_irq(&tasklist_lock);
 		if (child->p_pptr != current) {
 			REMOVE_LINKS(child);
 			child->p_pptr = current;
 			SET_LINKS(child);
 		}
-		write_unlock_irqrestore(&tasklist_lock, flags);
+		write_unlock_irq(&tasklist_lock);
 
 		send_sig(SIGSTOP, child, 1);
 		ret = 0;
-		goto out;
+		goto out_tsk;
 	}
 	ret = -ESRCH;
 	if (!(child->flags & PF_PTRACED))
-		goto out;
+		goto out_tsk;
 	if (child->state != TASK_STOPPED) {
 		if (request != PTRACE_KILL)
-			goto out;
+			goto out_tsk;
 	}
 	if (child->p_pptr != current)
-		goto out;
+		goto out_tsk;
 
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
-		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-		case PTRACE_PEEKDATA: {
-			unsigned long tmp;
-			int copied;
-
-			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-			ret = -EIO;
-			if (copied != sizeof(tmp))
-				goto out;
-			ret = put_user(tmp,(unsigned long *) data);
-			goto out;
-		}
-	/* read the word at location addr in the USER area. */
-		case PTRACE_PEEKUSR: {
-			unsigned long tmp;
-			
-			if ((addr & 3) || addr < 0 || addr > (PT_FPSCR << 2)) {
-				ret = -EIO;
-				goto out;
-			}
-			
-			ret = verify_area(VERIFY_WRITE, (void *) data,
-					  sizeof(long));
-			if (ret)
-				goto out;
-			tmp = 0;  /* Default return condition */
-			addr = addr >> 2; /* temporary hack. */
-			if (addr < PT_FPR0) {
-				tmp = get_reg(child, addr);
-			}
-			else if (addr >= PT_FPR0 && addr <= PT_FPSCR) {
-				if (child->thread.regs->msr & MSR_FP)
-					giveup_fpu(child);
-				tmp = ((long *)child->thread.fpr)[addr - PT_FPR0];
-			}
-			else
-				ret = -EIO;
-			if (!ret)
-				put_user(tmp,(unsigned long *) data);
-			goto out;
-		}
-
-      /* If I and D space are separate, this will have to be fixed. */
-		case PTRACE_POKETEXT: /* write the word at location addr. */
-		case PTRACE_POKEDATA:
-			ret = 0;
-			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-				goto out;
-			ret = -EIO;
-			goto out;
-		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-			ret = -EIO;
-			if ((addr & 3) || addr < 0 || addr >= ((PT_FPR0 + 64) << 2))
-				goto out;
-
-			addr = addr >> 2; /* temporary hack. */
-			    
-			if (addr == PT_ORIG_R3)
-				goto out;
-			if (addr < PT_FPR0) {
-				if (put_reg(child, addr, data))
-					goto out;
-				ret = 0;
-				goto out;
-			}
-			if (addr >= PT_FPR0 && addr < PT_FPR0 + 64) {
-				if (child->thread.regs->msr & MSR_FP)
-					giveup_fpu(child);
-				((long *)child->thread.fpr)[addr - PT_FPR0] = data;
-				ret = 0;
-				goto out;
-			}
-			goto out;
+	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+	case PTRACE_PEEKDATA: {
+		unsigned long tmp;
+		int copied;
+
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		ret = -EIO;
+		if (copied != sizeof(tmp))
+			break;
+		ret = put_user(tmp,(unsigned long *) data);
+		break;
+	}
 
-		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
-		case PTRACE_CONT: { /* restart after signal. */
-			ret = -EIO;
-			if ((unsigned long) data >= _NSIG)
-				goto out;
-			if (request == PTRACE_SYSCALL)
-				child->flags |= PF_TRACESYS;
-			else
-				child->flags &= ~PF_TRACESYS;
-			child->exit_code = data;
-			wake_up_process(child);
-			/* make sure the single step bit is not set. */
-			clear_single_step(child);
+	/* read the word at location addr in the USER area. */
+	/* XXX this will need fixing for 64-bit */
+	case PTRACE_PEEKUSR: {
+		unsigned long index, tmp;
+
+		ret = -EIO;
+		/* convert to index and check */
+		index = (unsigned long) addr >> 2;
+		if ((addr & 3) || index > PT_FPSCR)
+			break;
+
+		if (addr < PT_FPR0) {
+			tmp = get_reg(child, (int) index);
+		} else {
+			if (child->thread.regs->msr & MSR_FP)
+				giveup_fpu(child);
+			tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
+		}
+		ret = put_user(tmp,(unsigned long *) data);
+		break;
+	}
+
+	/* If I and D space are separate, this will have to be fixed. */
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		ret = 0;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+			break;
+		ret = -EIO;
+		break;
+
+	/* write the word at location addr in the USER area */
+	/* XXX this will need fixing for 64-bit */
+	case PTRACE_POKEUSR: {
+		unsigned long index;
+
+		ret = -EIO;
+		/* convert to index and check */
+		index = (unsigned long) addr >> 2;
+		if ((addr & 3) || index > PT_FPSCR)
+			break;
+
+		if (addr == PT_ORIG_R3)
+			break;
+		if (addr < PT_FPR0) {
+			ret = put_reg(child, addr, data);
+		} else {
+			if (child->thread.regs->msr & MSR_FP)
+				giveup_fpu(child);
+			((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
 			ret = 0;
-			goto out;
 		}
+		break;
+	}
+
+	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+	case PTRACE_CONT: { /* restart after signal. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			child->flags |= PF_TRACESYS;
+		else
+			child->flags &= ~PF_TRACESYS;
+		child->exit_code = data;
+		/* make sure the single step bit is not set. */
+		clear_single_step(child);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
 
 /*
  * make the child exit.  Best I can do is send it a sigkill. 
  * perhaps it should be put in the status that it wants to 
  * exit.
  */
-		case PTRACE_KILL: {
-			ret = 0;
-			if (child->state == TASK_ZOMBIE) /* already dead */
-				goto out;
-			wake_up_process(child);
-			child->exit_code = SIGKILL;
-			/* make sure the single step bit is not set. */
-			clear_single_step(child);
-			goto out;
-		}
-
-		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
-			ret = -EIO;
-			if ((unsigned long) data >= _NSIG)
-				goto out;
-			child->flags &= ~PF_TRACESYS;
-			set_single_step(child);
-			child->exit_code = data;
-			/* give it a chance to run. */
-			wake_up_process(child);
-			ret = 0;
-			goto out;
-		}
+	case PTRACE_KILL: {
+		ret = 0;
+		if (child->state == TASK_ZOMBIE)	/* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		/* make sure the single step bit is not set. */
+		clear_single_step(child);
+		wake_up_process(child);
+		break;
+	}
+
+	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		child->flags &= ~PF_TRACESYS;
+		set_single_step(child);
+		child->exit_code = data;
+		/* give it a chance to run. */
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
 
-		case PTRACE_DETACH: { /* detach a process that was attached. */
-			ret = -EIO;
-			if ((unsigned long) data >= _NSIG)
-				goto out;
-			child->flags &= ~(PF_PTRACED|PF_TRACESYS);
-			wake_up_process(child);
-			child->exit_code = data;
-			write_lock_irqsave(&tasklist_lock, flags);
-			REMOVE_LINKS(child);
-			child->p_pptr = child->p_opptr;
-			SET_LINKS(child);
-			write_unlock_irqrestore(&tasklist_lock, flags);
-			/* make sure the single step bit is not set. */
-			clear_single_step(child);
-			ret = 0;
-			goto out;
-		}
+	case PTRACE_DETACH: { /* detach a process that was attached. */
+		ret = -EIO;
+		if ((unsigned long) data > _NSIG)
+			break;
+		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+		child->exit_code = data;
+		write_lock_irq(&tasklist_lock);
+		REMOVE_LINKS(child);
+		child->p_pptr = child->p_opptr;
+		SET_LINKS(child);
+		write_unlock_irq(&tasklist_lock);
+		/* make sure the single step bit is not set. */
+		clear_single_step(child);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	}
 
-		default:
-			ret = -EIO;
-			goto out;
+	default:
+		ret = -EIO;
+		break;
 	}
+out_tsk:
+	free_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
 }
 
-asmlinkage void syscall_trace(void)
+void syscall_trace(void)
 {
 	if ((current->flags & (PF_PTRACED|PF_TRACESYS))
 			!= (PF_PTRACED|PF_TRACESYS))
-		goto out;
+		return;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
 	notify_parent(current, SIGCHLD);
@@ -518,5 +312,4 @@
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
-out:
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/setup.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/kernel/setup.c	Mon May 15 11:03:48 2000
@@ -776,8 +776,11 @@
 	id->word127        = __le16_to_cpu(id->word127);
 	id->dlf            = __le16_to_cpu(id->dlf);
 	id->csfo           = __le16_to_cpu(id->csfo);
-	for (i = 0; i < 30; i++)
-		id->words130_159[i] = __le16_to_cpu(id->words130_159[i]);
+	for (i = 0; i < 26; i++)
+		id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);
+	id->word156        = __le16_to_cpu(id->word156);
+	for (i = 0; i < 4; i++)
+		id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);
 	for (i = 0; i < 96; i++)
 		id->words160_255[i] = __le16_to_cpu(id->words160_255[i]);
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/time.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/ppc/kernel/time.c	Mon May 15 14:53:30 2000
@@ -41,10 +41,7 @@
 #include <asm/processor.h>
 #include <asm/nvram.h>
 #include <asm/cache.h>
-/* Fixme - Why is this here? - Corey */
-#ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
-#endif
 #include <asm/machdep.h>
 
 #include "time.h"
@@ -62,6 +59,7 @@
 unsigned decrementer_count;	/* count value for 1e6/HZ microseconds */
 unsigned count_period_num;	/* 1 decrementer count equals */
 unsigned count_period_den;	/* count_period_num / count_period_den us */
+unsigned long last_tb;
 
 /*
  * timer_interrupt - gets called when the decrementer overflows,
@@ -103,6 +101,8 @@
 	 */
 	while ((d = get_dec()) == dval)
 		;
+	asm volatile("mftb 	%0" : "=r" (last_tb) );
+	
 	/*
 	 * Don't play catchup between the call to time_init()
 	 * and sti() in init/main.c.
@@ -149,20 +149,21 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	unsigned long flags;
+	unsigned long flags, diff;
 
 	save_flags(flags);
 	cli();
 	*tv = xtime;
 	/* XXX we don't seem to have the decrementers synced properly yet */
 #ifndef CONFIG_SMP
-	tv->tv_usec += (decrementer_count - get_dec())
-	    * count_period_num / count_period_den;
-	if (tv->tv_usec >= 1000000) {
-		tv->tv_usec -= 1000000;
-		tv->tv_sec++;
-	}
+	asm volatile("mftb %0" : "=r" (diff) );
+	diff -= last_tb;
+	
+	tv->tv_usec += diff * count_period_num / count_period_den;
+	tv->tv_sec += tv->tv_usec / 1000000;
+	tv->tv_usec = tv->tv_usec % 1000000;
 #endif
+
 	restore_flags(flags);
 }
 
@@ -334,6 +335,3 @@
 	 */
 	GregorianDay(tm);
 }
-
-
-
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.3.99-pre8/linux/arch/ppc/kernel/traps.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/kernel/traps.c	Mon May 15 14:53:30 2000
@@ -91,7 +91,7 @@
 	{
 #if defined(CONFIG_8xx) && defined(CONFIG_PCI)
 		/* the qspan pci read routines can cause machine checks -- Cort */
-		bad_page_fault(regs,regs->dar);
+		bad_page_fault(regs, regs->dar);
 		return;
 #endif
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
@@ -214,8 +214,6 @@
 {
 	int fixed;
 
-	if (regs->msr & MSR_FP)
-		giveup_fpu(current);
 	fixed = fix_alignment(regs);
 	if (fixed == 1) {
 		regs->nip += 4;	/* skip over emulated instruction */
@@ -223,7 +221,10 @@
 	}
 	if (fixed == -EFAULT) {
 		/* fixed == -EFAULT means the operand address was bad */
-		bad_page_fault(regs, regs->dar);
+		if (user_mode(regs))
+			force_sig(SIGSEGV, current);
+		else
+			bad_page_fault(regs, regs->dar);
 		return;
 	}
 	_exception(SIGBUS, regs);	
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/Makefile linux/arch/ppc/mbxboot/Makefile
--- v2.3.99-pre8/linux/arch/ppc/mbxboot/Makefile	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/mbxboot/Makefile	Mon May 15 14:53:30 2000
@@ -28,14 +28,14 @@
 TFTPIMAGE=/tftpboot/zImage.embedded
 
 ifdef CONFIG_8xx
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00180000
-OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o
+ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00180000
+OBJECTS := head.o misc.o ../coffboot/zlib.o m8xx_tty.o gzimage.o rdimage.o
 CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8xx
 endif
 
 ifdef CONFIG_8260
-ZLINKFLAGS = -T ../vmlinux.lds -Ttext 0x00400000
-OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o
+ZLINKFLAGS = -T vmlinux.lds -Ttext 0x00400000
+OBJECTS := head_8260.o misc.o ../coffboot/zlib.o m8260_tty.o embed_config.o gzimage.o rdimage.o
 CFLAGS = $(CPPFLAGS) -O2 -DSTDC_HEADERS -fno-builtin -DCONFIG_8260
 endif
 
@@ -61,21 +61,32 @@
 all:	zImage
 
 zvmlinux.initrd: zvmlinux
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp1 $(OBJECTS)
+#
+# Build the boot loader images 
+#
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
-		--add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.initrd.tmp1 zvmlinux.initrd1
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 initrd` \
-		-DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 initrd` \
-		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd1 image` \
-		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd1 image` \
-		-c -o misc.o misc.c
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+		--add-section=.gzimage=../coffboot/vmlinux.gz \
+		--set-section-flags=.gzimage=alloc,load,readonly,data \
+		gzimage.o
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .rdimage rdimage.o
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
-		--add-section=initrd=ramdisk.image.gz \
-		--add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.initrd.tmp $@
+		--add-section=.rdimage=ramdisk.image.gz \
+		--set-section-flags=.rdimage=alloc,load,readonly,data \
+		rdimage.o
+	$(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+#
+# Compute the sizes/offsets for the final image, and rebuild with these values.
+#
+	$(CC) $(CFLAGS) \
+		-DINITRD_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .rdimage` \
+		-DINITRD_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .rdimage` \
+		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux.initrd .gzimage` \
+		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux.initrd .gzimage` \
+		-c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@
+	$(OBJDUMP) -h $@
 
 zImage: zvmlinux
 	ln -sf zvmlinux zImage
@@ -85,23 +96,27 @@
 
 zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
 #
-# build the boot loader image and then compute the offset into it
-# for the kernel image
+# Build the boot loader images 
+#
+#
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .gzimage gzimage.o
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
+		--add-section=.gzimage=../coffboot/vmlinux.gz \
+		--set-section-flags=.gzimage=alloc,load,readonly,data \
+		gzimage.o
+	$(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+#
+# Compute the sizes/offsets for the final image, and rebuild with these values.
 #
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.tmp $@
-#
-# then with the offset rebuild the bootloader so we know where the kernel is
-#
-	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
-		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux image` \
-		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux image` \
+	$(CC) $(CFLAGS) \
+		-DINITRD_OFFSET=0 \
+		-DINITRD_SIZE=0 \
+		-DZIMAGE_OFFSET=`sh offset $(OBJDUMP) zvmlinux .gzimage` \
+		-DZIMAGE_SIZE=`sh size $(OBJDUMP) zvmlinux .gzimage` \
 		-c -o misc.o misc.c
-	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
-	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
-		zvmlinux.tmp $@
-	rm zvmlinux.tmp
+	$(LD) $(ZLINKFLAGS) -o $@ $(OBJECTS)
+	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment $@
+	$(OBJDUMP) -h $@
 
 znetboot : zImage
 	cp zImage $(TFTPIMAGE)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/embed_config.c linux/arch/ppc/mbxboot/embed_config.c
--- v2.3.99-pre8/linux/arch/ppc/mbxboot/embed_config.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/mbxboot/embed_config.c	Sun May 21 20:55:06 2000
@@ -236,12 +236,12 @@
 	 * here for those people that may load the kernel with
 	 * a JTAG/COP tool and not the rom monitor.
 	 */
-	bd->bi_baudrate = 115200;
-	bd->bi_intfreq = 200;
-	bd->bi_busfreq = 66;
-	bd->bi_cpmfreq = 66;
-	bd->bi_brgfreq = 33;
-	bd->bi_memsize = 16 * 1024 * 1024;
+	bd->bi_baudrate = 19200;
+	bd->bi_intfreq  = 165;
+	bd->bi_busfreq  = 33;
+	bd->bi_cpmfreq  = 132;
+	bd->bi_brgfreq  = bd->bi_cpmfreq / 2; /* BRGCLK = (CPM*2/4) */
+	bd->bi_memsize  = 16 * 1024 * 1024;
 #endif
 
 	cp = (u_char *)def_enet_addr;
@@ -250,3 +250,4 @@
 	}
 }
 #endif /* EST8260 */
+
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/gzimage.c linux/arch/ppc/mbxboot/gzimage.c
--- v2.3.99-pre8/linux/arch/ppc/mbxboot/gzimage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/gzimage.c	Mon May 15 14:53:30 2000
@@ -0,0 +1,8 @@
+/*
+ * gzimage.c
+ *
+ * Dummy file to allow a compressed zImage to be added
+ * into a linker section, accessed by the boot coode
+ */
+
+char dummy_for_gzimage;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/head_8260.S linux/arch/ppc/mbxboot/head_8260.S
--- v2.3.99-pre8/linux/arch/ppc/mbxboot/head_8260.S	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/mbxboot/head_8260.S	Mon May 15 14:53:30 2000
@@ -9,10 +9,17 @@
  * $Id: head.S,v 1.33 1999/09/08 01:06:58 cort Exp $
  *	
  * Boot loader philosophy:
+ *
  *      ROM loads us to some arbitrary location
- *      Move the boot code to the link address (8M)
+ *      ROM loads these registers:
+ *	
+ *          R3 = Pointer to the board configuration data
+ *          R5 = Pointer to Open Firmware data 	
+ *		 	
+ *      ROM jumps to start/start_
+ *      Move the boot code to the link address (4 MB)
  *      Call decompress_kernel()
- *         Relocate the initrd, zimage and residual data to 8M
+ *         Relocate the initrd, zimage and residual data to 4 MB
  *         Decompress the kernel to 0
  *      Jump to the kernel entry
  *            -- Cort
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/misc.c linux/arch/ppc/mbxboot/misc.c
--- v2.3.99-pre8/linux/arch/ppc/mbxboot/misc.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/mbxboot/misc.c	Mon May 15 14:53:30 2000
@@ -25,6 +25,15 @@
 #endif
 
 /*
+ * The following references are needed to cause the linker to pull in the
+ * gzimage.o and rdimage.o files.  These object files are special,
+ * since they get placed into the .gzimage and .rdimage ELF sections 
+ * of the zvmlinux and zvmlinux.initrd files.
+ */
+extern char dummy_for_gzimage;
+extern char dummy_for_rdimage;
+
+/*
  * Please send me load/board info and such data for hardware not
  * listed here so I can keep track since things are getting tricky
  * with the different load addrs with different firmware.  This will
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/rdimage.c linux/arch/ppc/mbxboot/rdimage.c
--- v2.3.99-pre8/linux/arch/ppc/mbxboot/rdimage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/rdimage.c	Mon May 15 14:53:30 2000
@@ -0,0 +1,8 @@
+/*
+ * rdimage.c
+ *
+ * Dummy file to allow a compressed initrd to be added
+ * into a linker section, accessed by the boot coode
+ */
+
+char dummy_for_rdimage;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mbxboot/vmlinux.lds linux/arch/ppc/mbxboot/vmlinux.lds
--- v2.3.99-pre8/linux/arch/ppc/mbxboot/vmlinux.lds	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mbxboot/vmlinux.lds	Mon May 15 14:53:30 2000
@@ -0,0 +1,152 @@
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+   __DYNAMIC = 0;    */
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = + SIZEOF_HEADERS;
+  .interp : { *(.interp) }
+  .hash          : { *(.hash)		}
+  .dynsym        : { *(.dynsym)		}
+  .dynstr        : { *(.dynstr)		}
+  .rel.text      : { *(.rel.text)		}
+  .rela.text     : { *(.rela.text) 	}
+  .rel.data      : { *(.rel.data)		}
+  .rela.data     : { *(.rela.data) 	}
+  .rel.rodata    : { *(.rel.rodata) 	}
+  .rela.rodata   : { *(.rela.rodata) 	}
+  .rel.got       : { *(.rel.got)		}
+  .rela.got      : { *(.rela.got)		}
+  .rel.ctors     : { *(.rel.ctors)	}
+  .rela.ctors    : { *(.rela.ctors)	}
+  .rel.dtors     : { *(.rel.dtors)	}
+  .rela.dtors    : { *(.rela.dtors)	}
+  .rel.bss       : { *(.rel.bss)		}
+  .rela.bss      : { *(.rela.bss)		}
+  .rel.plt       : { *(.rel.plt)		}
+  .rela.plt      : { *(.rela.plt)		}
+/*  .init          : { *(.init)	} =0*/
+  .plt : { *(.plt) }
+  .text      :
+  {
+    *(.text)
+    *(.fixup)
+    *(.got1)
+  }
+  _etext = .;
+  PROVIDE (etext = .);
+  .rodata    :
+  {
+    *(.rodata)
+    *(.rodata1)
+  }
+  .fini      : { *(.fini)    } =0
+  .ctors     : { *(.ctors)   }
+  .dtors     : { *(.dtors)   }
+  /* Read-write section, merged into data segment: */
+  . = (. + 0x0FFF) & 0xFFFFF000;
+  .data    :
+  {
+    *(.data)
+    *(.data1)
+    *(.sdata)
+    *(.sdata2)
+    *(.got.plt) *(.got)
+    *(.dynamic)
+    CONSTRUCTORS
+  }
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  .fixup   : { *(.fixup) }
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { 
+    *(.data.init);
+    __vtop_table_begin = .;
+    *(.vtop_fixup);
+    __vtop_table_end = .;
+    __ptov_table_begin = .;
+    *(.ptov_fixup);
+    __ptov_table_end = .;
+  }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
+
+  . = ALIGN(4096);
+  __pmac_begin = .;
+  .text.pmac : { *(.text.pmac) }
+  .data.pmac : { *(.data.pmac) }
+  . = ALIGN(4096);
+  __pmac_end = .;
+
+  . = ALIGN(4096);
+  __prep_begin = .;
+  .text.prep : { *(.text.prep) }
+  .data.prep : { *(.data.prep) }
+  . = ALIGN(4096);
+  __prep_end = .;
+
+  . = ALIGN(4096);
+  __apus_begin = .;
+  .text.apus : { *(.text.apus) }
+  .data.apus : { *(.data.apus) }
+  . = ALIGN(4096);
+  __apus_end = .;
+
+  . = ALIGN(4096);
+  __apus_begin = .;
+  .text.apus : { *(.text.apus) }
+  .data.apus : { *(.data.apus) }
+  . = ALIGN(4096);
+  __apus_end = .;
+
+  . = ALIGN(4096);
+  __openfirmware_begin = .;
+  .text.openfirmware : { *(.text.openfirmware) }
+  .data.openfirmware : { *(.data.openfirmware) }
+  . = ALIGN(4096);
+  __openfirmware_end = .;
+
+  __bss_start = .;
+  .bss       :
+  {
+   *(.sbss) *(.scommon)
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+  }
+  _end = . ;
+  PROVIDE (end = .);
+
+  /*
+   * For loader only: Put the zImage after everything else
+   */
+  _gzstart = . ;
+  .gzimage : { *(.gzimage) }
+  _gzend   = . ;
+  
+  /*
+   * For loader only: Put the initrd after zImage
+   */
+  _rdstart = . ;
+  .rdimage : { *(.rdimage) }
+  _rdend   = . ;
+  
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.3.99-pre8/linux/arch/ppc/mm/fault.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/mm/fault.c	Mon May 15 14:53:30 2000
@@ -62,10 +62,21 @@
 {
 	struct vm_area_struct * vma;
 	struct mm_struct *mm = current->mm;
+	siginfo_t info;
+	int code = SEGV_MAPERR;
 #if defined(CONFIG_4xx)
 	int is_write = error_code & ESR_DST;
 #else
 	int is_write = error_code & 0x02000000;
+
+	/*
+	 * Fortunately the bit assignments in SRR1 for an instruction
+	 * fault and DSISR for a data fault are mostly the same for the
+	 * bits we are interested in.  But there are some bits which
+	 * indicate errors in DSISR but can validly be set in SRR1.
+	 */
+	if (regs->trap == 0x400)
+		error_code &= 0x48200000;
 #endif /* CONFIG_4xx */
 
 #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
@@ -82,16 +93,7 @@
 #endif /* !CONFIG_4xx */
 #endif /* CONFIG_XMON || CONFIG_KGDB */
 
-	if (in_interrupt()) {
-		static int complained;
-		if (complained < 20) {
-			++complained;
-			printk("page fault in interrupt handler, addr=%lx\n",
-			       address);
-			show_regs(regs);
-		}
-	}
-	if (current == NULL || mm == NULL) {
+	if (in_interrupt() || mm == NULL) {
 		bad_page_fault(regs, address);
 		return;
 	}
@@ -107,10 +109,12 @@
 		goto bad_area;
 
 good_area:
+	code = SEGV_ACCERR;
 #if defined(CONFIG_6xx)
 	if (error_code & 0x95700000)
 		/* an error such as lwarx to I/O controller space,
 		   address matching DABR, eciwx, etc. */
+		goto bad_area;
 #endif /* CONFIG_6xx */
 #if defined(CONFIG_8xx)
         /* The MPC8xx seems to always set 0x80000000, which is
@@ -119,9 +123,8 @@
          */
 	if (error_code & 0x10000000)
                 /* Guarded storage error. */
-#endif /* CONFIG_8xx */
 		goto bad_area;
-	
+#endif /* CONFIG_8xx */
 	
 	/* a write */
 	if (is_write) {
@@ -135,8 +138,25 @@
 		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
 	}
-	if (!handle_mm_fault(mm, vma, address, is_write))
-		goto bad_area;
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+        switch (handle_mm_fault(mm, vma, address, is_write)) {
+        case 1:
+                current->min_flt++;
+                break;
+        case 2:
+                current->maj_flt++;
+                break;
+        case 0:
+                goto do_sigbus;
+        default:
+                goto out_of_memory;
+	}
+
 	up(&mm->mmap_sem);
 	/*
 	 * keep track of tlb+htab misses that are good addrs but
@@ -147,22 +167,55 @@
 	return;
 
 bad_area:
-
 	up(&mm->mmap_sem);
 	pte_errors++;	
+
+	/* User mode accesses cause a SIGSEGV */
+	if (user_mode(regs)) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = code;
+		info.si_addr = (void *) address;
+		force_sig_info(SIGSEGV, &info, current);
+		return;
+	}
+
+	bad_page_fault(regs, address);
+	return;
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+out_of_memory:
+	up(&mm->mmap_sem);
+	printk("VM: killing process %s\n", current->comm);
+	if (user_mode(regs))
+		do_exit(SIGKILL);
 	bad_page_fault(regs, address);
+	return;
+
+do_sigbus:
+	up(&mm->mmap_sem);
+	info.si_signo = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *)address;
+	force_sig_info (SIGBUS, &info, current);
+	if (!user_mode(regs))
+		bad_page_fault(regs, address);
 }
 
+/*
+ * bad_page_fault is called when we have a bad access from the kernel.
+ * It is called from do_page_fault above and from some of the procedures
+ * in traps.c.
+ */
 void
 bad_page_fault(struct pt_regs *regs, unsigned long address)
 {
 	unsigned long fixup;
 
-	if (user_mode(regs)) {
-		force_sig(SIGSEGV, current);
-		return;
-	}
-	
 	/* Are we prepared to handle this fault?  */
 	if ((fixup = search_exception_table(regs->nip)) != 0) {
 		regs->nip = fixup;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.3.99-pre8/linux/arch/ppc/mm/init.c	Thu May 11 15:30:06 2000
+++ linux/arch/ppc/mm/init.c	Mon May 15 14:53:30 2000
@@ -83,6 +83,7 @@
 extern char etext[], _stext[];
 extern char __init_begin, __init_end;
 extern char __prep_begin, __prep_end;
+extern char __chrp_begin, __chrp_end;
 extern char __pmac_begin, __pmac_end;
 extern char __apus_begin, __apus_end;
 extern char __openfirmware_begin, __openfirmware_end;
@@ -777,7 +778,7 @@
 	unsigned long a;
 	unsigned long num_freed_pages = 0, num_prep_pages = 0,
 		num_pmac_pages = 0, num_openfirmware_pages = 0,
-		num_apus_pages = 0;
+		num_apus_pages = 0, num_chrp_pages = 0;
 #define FREESEC(START,END,CNT) do { \
 	a = (unsigned long)(&START); \
 	for (; a < (unsigned long)(&END); a += PAGE_SIZE) { \
@@ -794,6 +795,7 @@
 	case _MACH_Pmac:
 		FREESEC(__apus_begin,__apus_end,num_apus_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
 		break;
 	case _MACH_chrp:
 		FREESEC(__apus_begin,__apus_end,num_apus_pages);
@@ -803,20 +805,24 @@
 	case _MACH_prep:
 		FREESEC(__apus_begin,__apus_end,num_apus_pages);
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
+		FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
 		break;
 	case _MACH_mbx:
 		FREESEC(__apus_begin,__apus_end,num_apus_pages);
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
 		break;
 	case _MACH_apus:
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
 		break;
 	case _MACH_gemini:
 		FREESEC(__apus_begin,__apus_end,num_apus_pages);
 		FREESEC(__pmac_begin,__pmac_end,num_pmac_pages);
 		FREESEC(__prep_begin,__prep_end,num_prep_pages);
+		FREESEC(__chrp_begin,__chrp_end,num_chrp_pages);
 		break;
 	}
 
@@ -829,6 +835,8 @@
 
 	if ( num_prep_pages )
 		printk(" %ldk prep", PGTOKB(num_prep_pages));
+	if ( num_chrp_pages )
+		printk(" %ldk chrp", PGTOKB(num_chrp_pages));
 	if ( num_pmac_pages )
 		printk(" %ldk pmac", PGTOKB(num_pmac_pages));
 	if ( num_openfirmware_pages )
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/treeboot/mkevimg linux/arch/ppc/treeboot/mkevimg
--- v2.3.99-pre8/linux/arch/ppc/treeboot/mkevimg	Tue Dec  7 09:32:42 1999
+++ linux/arch/ppc/treeboot/mkevimg	Mon May 15 14:53:30 2000
@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 
 #
 #    Copyright (c) 1998-1999 TiVo, Inc.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/treeboot/mkirimg linux/arch/ppc/treeboot/mkirimg
--- v2.3.99-pre8/linux/arch/ppc/treeboot/mkirimg	Tue Dec  7 09:32:42 1999
+++ linux/arch/ppc/treeboot/mkirimg	Mon May 15 14:53:30 2000
@@ -1,4 +1,4 @@
-#!/usr/local/bin/perl
+#!/usr/bin/perl
 #
 #    Copyright (c) 1998-1999 TiVo, Inc.
 #      Original ELF parsing code.
@@ -332,7 +332,7 @@
   syswrite(OUTPUT, $ibuf, $initialOffset);
 
   if ($imageFound) {
-    $testN = pack ("I2", $bss_addr + $bss_size, $image_size);
+    $testN = pack ("N2", $bss_addr + $bss_size, $image_size);
     syswrite(OUTPUT, $testN, length($testN));
     printf("Updated symbol \"imageSect_start\" to 0x%08x\n",
 	   $bss_addr + $bss_size);
@@ -342,7 +342,7 @@
   }
 
   if ($initrdFound) {
-    $testN = pack ("I2", $bss_addr + $bss_size + $image_size, $initrd_size);
+    $testN = pack ("N2", $bss_addr + $bss_size + $image_size, $initrd_size);
     syswrite(OUTPUT, $testN, length($testN));
     printf("Updated symbol \"initrdSect_start\" to 0x%08x\n",
 	   $bss_addr + $bss_size + $image_size);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds
--- v2.3.99-pre8/linux/arch/ppc/vmlinux.lds	Sat Oct  9 11:47:50 1999
+++ linux/arch/ppc/vmlinux.lds	Mon May 15 14:53:30 2000
@@ -104,6 +104,13 @@
   __prep_end = .;
 
   . = ALIGN(4096);
+  __chrp_begin = .;
+  .text.chrp : { *(.text.chrp) }
+  .data.chrp : { *(.data.chrp) }
+  . = ALIGN(4096);
+  __chrp_end = .;
+
+  . = ALIGN(4096);
   __apus_begin = .;
   .text.apus : { *(.text.apus) }
   .data.apus : { *(.data.apus) }
@@ -135,4 +142,3 @@
   _end = . ;
   PROVIDE (end = .);
 }
-
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/config.in linux/arch/sh/config.in
--- v2.3.99-pre8/linux/arch/sh/config.in	Tue Apr 11 15:09:14 2000
+++ linux/arch/sh/config.in	Sat May 20 12:05:29 2000
@@ -15,6 +15,10 @@
 
 mainmenu_option next_comment
 comment 'Processor type and features'
+choice 'SuperH system type'					\
+	"Generic		CONFIG_SH_GENERIC		\
+	 SolutionEngine		CONFIG_SH_SOLUTION_ENGINE" Generic
+
 choice 'Processor type' \
    "SH7708 CONFIG_CPU_SUBTYPE_SH7708 \
     SH7709 CONFIG_CPU_SUBTYPE_SH7709 \
@@ -32,7 +36,12 @@
    define_bool CONFIG_CPU_SH4 y
 fi
 bool 'Little Endian' CONFIG_LITTLE_ENDIAN
-hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
+if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
+  define_hex CONFIG_MEMORY_START 0c000000
+else
+  hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
+  hex 'I/O port offset address' CONFIG_IOPORT_START ba000000
+fi
 endmenu
 
 mainmenu_option next_comment
@@ -52,7 +61,9 @@
 
 bool 'Networking support' CONFIG_NET
 
-bool 'Directy Connected Compact Flash support' CONFIG_CF_ENABLER
+if [ "$CONFIG_SH_SOLUTION_ENGINE" != "y" ]; then
+   bool 'Directly Connected Compact Flash support' CONFIG_CF_ENABLER
+fi
 
 bool 'PCI support' CONFIG_PCI
 if [ "$CONFIG_PCI" = "y" ]; then
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/defconfig linux/arch/sh/defconfig
--- v2.3.99-pre8/linux/arch/sh/defconfig	Thu May 11 15:30:06 2000
+++ linux/arch/sh/defconfig	Sat May 20 12:05:29 2000
@@ -12,6 +12,8 @@
 #
 # Processor type and features
 #
+CONFIG_SH_GENERIC=y
+# CONFIG_SH_SOLUTION_ENGINE is not set
 CONFIG_CPU_SUBTYPE_SH7708=y
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
@@ -19,6 +21,7 @@
 # CONFIG_CPU_SH4 is not set
 CONFIG_LITTLE_ENDIAN=y
 CONFIG_MEMORY_START=0c000000
+CONFIG_IOPORT_START=ba000000
 
 #
 # Loadable module support
@@ -62,9 +65,10 @@
 #
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_LVM is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
-# CONFIG_MD_STRIPED is not set
+# CONFIG_MD_RAID0 is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_INITRD=y
 
@@ -85,6 +89,13 @@
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
 # CONFIG_BLK_DEV_IDECS is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
@@ -137,6 +148,7 @@
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile
--- v2.3.99-pre8/linux/arch/sh/kernel/Makefile	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/kernel/Makefile	Sat May 20 12:05:29 2000
@@ -10,7 +10,7 @@
 	$(CC) $(AFLAGS) -traditional -c $< -o $*.o
 
 O_TARGET := kernel.o
-O_OBJS   := process.o signal.o entry.o traps.o irq.o irq_onchip.o \
+O_OBJS   := process.o signal.o entry.o traps.o irq.o irq_ipr.o \
             ptrace.o setup.o time.o sys_sh.o semaphore.o pci-sh.o \
 	    irq_imask.o
 OX_OBJS  := sh_ksyms.o
@@ -18,6 +18,14 @@
 
 ifdef CONFIG_CF_ENABLER
 O_OBJS += cf-enabler.o
+endif
+
+ifdef CONFIG_SH_GENERIC
+O_OBJS += io_generic.o
+endif
+
+ifdef CONFIG_SH_SOLUTION_ENGINE
+O_OBJS += setup_se.o io_se.o
 endif
 
 ifdef CONFIG_CPU_SH4
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S
--- v2.3.99-pre8/linux/arch/sh/kernel/entry.S	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/kernel/entry.S	Sat May 20 12:05:29 2000
@@ -282,7 +282,7 @@
 	 mov	$r0, $r9
 #endif
 	! New Syscall ABI
-	sub	$r9, $r8
+	add	#-0x40, $r8
 	shlr2	$r8
 	shll8	$r8
 	shll8	$r8
@@ -492,7 +492,16 @@
 	mov.l	2f, $k1
 	and	$k1, $k2	! Mask orignal SR value
 	or	$k0, $k2	! Inherit current FD-bit
-	or	$g_imask, $k2	! Inherit the IMASK-bits
+	!
+	mov	$k3, $k0	! Calculate IMASK-bits
+	shlr2	$k0
+	and	#0x3c, $k0
+	cmp/eq	#0x3c, $k0
+	bf/s	7f
+	 mov	$g_imask, $k0
+	shll2	$k0
+	!
+7:	or	$k0, $k2	! Set the IMASK-bits
 	ldc	$k2, $ssr
 	!
 #if defined(__SH4__)
@@ -507,7 +516,7 @@
 	! There's the case we don't get FPU now
 	stc	$sr, $k2
 	tst	$k1, $k2
-	bt	7f
+	bt	8f
 	! We need to grab FPU here
 	xor	$k1, $k2
 	ldc	$k2, $sr		! Grab FPU
@@ -519,7 +528,7 @@
 	!
 	! Restoring FPU...
 	!
-7:	mov.l	3f, $k1
+8:	mov.l	3f, $k1
 	lds	$k1, $fpscr
 	fmov.s	@$r15+, $fr0
 	fmov.s	@$r15+, $fr1
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/io_generic.c linux/arch/sh/kernel/io_generic.c
--- v2.3.99-pre8/linux/arch/sh/kernel/io_generic.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/io_generic.c	Sat May 20 12:05:29 2000
@@ -0,0 +1,99 @@
+/* $Id: io_generic.c,v 1.3 2000/05/07 23:31:58 gniibe Exp $
+ *
+ * linux/arch/sh/kernel/io_generic.c
+ *
+ * Copyright (C) 2000  Niibe Yutaka
+ *
+ * Generic I/O routine.
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+
+#define PORT2ADDR(x) (CONFIG_IOPORT_START+(x))
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+unsigned long inb(unsigned int port)
+{
+	return *(volatile unsigned char*)PORT2ADDR(port);
+}
+
+unsigned long inb_p(unsigned int port)
+{
+	unsigned long v = *(volatile unsigned char*)PORT2ADDR(port);
+
+	delay();
+	return v;
+}
+
+unsigned long inw(unsigned int port)
+{
+	return *(volatile unsigned short*)PORT2ADDR(port);
+}
+
+unsigned long inl(unsigned int port)
+{
+	return *(volatile unsigned long*)PORT2ADDR(port);
+}
+
+void insb(unsigned int port, void *buffer, unsigned long count)
+{
+	unsigned char *buf=buffer;
+	while(count--) *buf++=inb(port);
+}
+
+void insw(unsigned int port, void *buffer, unsigned long count)
+{
+	unsigned short *buf=buffer;
+	while(count--) *buf++=inw(port);
+}
+
+void insl(unsigned int port, void *buffer, unsigned long count)
+{
+	unsigned long *buf=buffer;
+	while(count--) *buf++=inl(port);
+}
+
+void outb(unsigned long b, unsigned int port)
+{
+	*(volatile unsigned char*)PORT2ADDR(port) = b;
+}
+
+void outb_p(unsigned long b, unsigned int port)
+{
+	*(volatile unsigned char*)PORT2ADDR(port) = b;
+	delay();
+}
+
+void outw(unsigned long b, unsigned int port)
+{
+	*(volatile unsigned short*)PORT2ADDR(port) = b;
+}
+
+void outl(unsigned long b, unsigned int port)
+{
+        *(volatile unsigned long*)PORT2ADDR(port) = b;
+}
+
+void outsb(unsigned int port, const void *buffer, unsigned long count)
+{
+	const unsigned char *buf=buffer;
+	while(count--) outb(*buf++, port);
+}
+
+void outsw(unsigned int port, const void *buffer, unsigned long count)
+{
+	const unsigned short *buf=buffer;
+	while(count--) outw(*buf++, port);
+}
+
+void outsl(unsigned int port, const void *buffer, unsigned long count)
+{
+	const unsigned long *buf=buffer;
+	while(count--) outl(*buf++, port);
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/io_se.c linux/arch/sh/kernel/io_se.c
--- v2.3.99-pre8/linux/arch/sh/kernel/io_se.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/io_se.c	Sun May 21 20:55:06 2000
@@ -0,0 +1,221 @@
+/* $Id: io_se.c,v 1.4 2000/05/07 23:31:58 gniibe Exp $
+ *
+ * linux/arch/sh/kernel/io_se.c
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * I/O routine for Hitachi SolutionEngine.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+#include <asm/hitachi_se.h>
+
+/* SH pcmcia io window base, start and end.  */
+int sh_pcic_io_wbase = 0xb8400000;
+int sh_pcic_io_start;
+int sh_pcic_io_stop;
+int sh_pcic_io_type;
+int sh_pcic_io_dummy;
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+/* MS7750 requires special versions of in*, out* routines, since
+   PC-like io ports are located at upper half byte of 16-bit word which
+   can be accessed only with 16-bit wide.  */
+
+static inline volatile __u16 *
+port2adr(unsigned int port)
+{
+	if (port >= 0x2000)
+		return (volatile __u16 *) (PA_MRSHPC + (port - 0x2000));
+	else if (port >= 0x1000)
+		return (volatile __u16 *) (PA_83902 + (port << 1));
+	else if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		return (volatile __u16 *) (sh_pcic_io_wbase + (port &~ 1));
+	else
+		return (volatile __u16 *) (PA_SUPERIO + (port << 1));
+}
+
+static inline int
+shifted_port(unsigned int port)
+{
+	/* For IDE registers, value is not shifted */
+	if ((0x1f0 <= port && port < 0x1f8) || port == 0x3f6)
+		return 0;
+	else
+		return 1;
+}
+
+#define maybebadio(name,port) \
+  printk("bad PC-like io %s for port 0x%x at 0x%08x\n", \
+	 #name, (port), (__u32) __builtin_return_address(0))
+
+unsigned long inb(unsigned int port)
+{
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		return *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
+	else if (shifted_port(port))
+		return (*port2adr(port) >> 8); 
+	else
+		return (*port2adr(port))&0xff; 
+}
+
+unsigned long inb_p(unsigned int port)
+{
+	unsigned long v;
+
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		v = *(__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
+	else if (shifted_port(port))
+		v = (*port2adr(port) >> 8); 
+	else
+		v = (*port2adr(port))&0xff; 
+	delay();
+	return v;
+}
+
+unsigned long inw(unsigned int port)
+{
+	if (port >= 0x2000 ||
+	    (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+		return *port2adr(port);
+	else
+		maybebadio(inw, port);
+	return 0;
+}
+
+unsigned long inl(unsigned int port)
+{
+	maybebadio(inl, port);
+	return 0;
+}
+
+void outb(unsigned long value, unsigned int port)
+{
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		*(__u8 *)(sh_pcic_io_wbase + port) = value; 
+	else if (shifted_port(port))
+		*(port2adr(port)) = value << 8;
+	else
+		*(port2adr(port)) = value;
+}
+
+void outb_p(unsigned long value, unsigned int port)
+{
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop)
+		*(__u8 *)(sh_pcic_io_wbase + port) = value; 
+	else if (shifted_port(port))
+		*(port2adr(port)) = value << 8;
+	else
+		*(port2adr(port)) = value;
+	delay();
+}
+
+void outw(unsigned long value, unsigned int port)
+{
+	if (port >= 0x2000 ||
+	    (sh_pcic_io_start <= port && port <= sh_pcic_io_stop))
+		*port2adr(port) = value;
+	else
+		maybebadio(outw, port);
+}
+
+void outl(unsigned long value, unsigned int port)
+{
+	maybebadio(outl, port);
+}
+
+void insb(unsigned int port, void *addr, unsigned long count)
+{
+	volatile __u16 *p = port2adr(port);
+
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+		volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + 0x40000 + port); 
+		while (count--)
+			*((__u8 *) addr)++ = *bp;
+	} else if (shifted_port(port)) {
+		while (count--)
+			*((__u8 *) addr)++ = *p >> 8;
+	} else {
+		while (count--)
+			*((__u8 *) addr)++ = *p;
+	}
+}
+
+void insw(unsigned int port, void *addr, unsigned long count)
+{
+	volatile __u16 *p = port2adr(port);
+	while (count--)
+		*((__u16 *) addr)++ = *p;
+}
+
+void insl(unsigned int port, void *addr, unsigned long count)
+{
+	maybebadio(insl, port);
+}
+
+void outsb(unsigned int port, const void *addr, unsigned long count)
+{
+	volatile __u16 *p = port2adr(port);
+
+	if (sh_pcic_io_start <= port && port <= sh_pcic_io_stop) {
+		volatile __u8 *bp = (__u8 *) (sh_pcic_io_wbase + port); 
+		while (count--)
+			*bp = *((__u8 *) addr)++;
+	} else if (shifted_port(port)) {
+		while (count--)
+			*p = *((__u8 *) addr)++ << 8;
+	} else {
+		while (count--)
+			*p = *((__u8 *) addr)++;
+	}
+}
+
+void outsw(unsigned int port, const void *addr, unsigned long count)
+{
+	volatile __u16 *p = port2adr(port);
+	while (count--)
+		*p = *((__u16 *) addr)++;
+}
+
+void outsl(unsigned int port, const void *addr, unsigned long count)
+{
+	maybebadio(outsw, port);
+}
+
+/* Map ISA bus address to the real address. Only for PCMCIA.  */
+
+/* ISA page descriptor.  */
+static __u32 sh_isa_memmap[256];
+
+int
+sh_isa_mmap(__u32 start, __u32 length, __u32 offset)
+{
+	int idx;
+
+	if (start >= 0x100000 || (start & 0xfff) || (length != 0x1000))
+		return -1;
+
+	idx = start >> 12;
+	sh_isa_memmap[idx] = 0xb8000000 + (offset &~ 0xfff);
+#if 0
+	printk("sh_isa_mmap: start %x len %x offset %x (idx %x paddr %x)\n",
+	       start, length, offset, idx, sh_isa_memmap[idx]);
+#endif
+	return 0;
+}
+
+unsigned long
+sh_isa_slot(unsigned long offset)
+{
+	int idx;
+
+	idx = (offset >> 12) & 0xff;
+	offset &= 0xfff;
+	return sh_isa_memmap[idx] + offset;
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c
--- v2.3.99-pre8/linux/arch/sh/kernel/irq.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/kernel/irq.c	Sun May 21 20:55:06 2000
@@ -13,6 +13,7 @@
  * Naturally it's not a 1:1 relation, but there are similarities.
  */
 
+#include <linux/config.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/kernel_stat.h>
@@ -300,7 +301,7 @@
 		desc->handler->end(irq);
 	spin_unlock(&irq_controller_lock);
 
-#if 1
+#if 0
 	__sti();
 #endif
 	if (softirq_state[cpu].active&softirq_state[cpu].mask)
@@ -513,3 +514,10 @@
 	spin_unlock_irqrestore(&irq_controller_lock,flags);
 	return 0;
 }
+
+#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
+
+void init_irq_proc(void)
+{
+}
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/irq_ipr.c linux/arch/sh/kernel/irq_ipr.c
--- v2.3.99-pre8/linux/arch/sh/kernel/irq_ipr.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/irq_ipr.c	Sat May 20 12:05:29 2000
@@ -0,0 +1,171 @@
+/* $Id: irq_ipr.c,v 1.6 2000/05/14 08:41:25 gniibe Exp $
+ *
+ * linux/arch/sh/kernel/irq_ipr.c
+ *
+ * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Interrupt handling for IPR-based IRQ.
+ *
+ * Supported system:
+ *	On-chip supporting modules (TMU, RTC, etc.).
+ *	On-chip supporting modules for SH7709/SH7709A/SH7729.
+ *	Hitachi SolutionEngine external I/O:
+ *		MS7709SE01, MS7709ASE01, and MS7750SE01
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+struct ipr_data {
+	unsigned int addr;	/* Address of Interrupt Priority Register */
+	int shift;		/* Shifts of the 16-bit data */
+	int priority;		/* The priority */
+};
+static struct ipr_data ipr_data[NR_IRQS];
+
+void set_ipr_data(unsigned int irq, unsigned int addr, int pos, int priority)
+{
+	ipr_data[irq].addr = addr;
+	ipr_data[irq].shift = pos*4; /* POSition (0-3) x 4 means shift */
+	ipr_data[irq].priority = priority;
+}
+
+static void enable_ipr_irq(unsigned int irq);
+void disable_ipr_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_ipr_irq disable_ipr_irq
+
+static void mask_and_ack_ipr(unsigned int);
+static void end_ipr_irq(unsigned int irq);
+
+static unsigned int startup_ipr_irq(unsigned int irq)
+{ 
+	enable_ipr_irq(irq);
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type ipr_irq_type = {
+	"IPR-based-IRQ",
+	startup_ipr_irq,
+	shutdown_ipr_irq,
+	enable_ipr_irq,
+	disable_ipr_irq,
+	mask_and_ack_ipr,
+	end_ipr_irq
+};
+
+void disable_ipr_irq(unsigned int irq)
+{
+	unsigned long val, flags;
+	unsigned int addr = ipr_data[irq].addr;
+	unsigned short mask = 0xffff ^ (0x0f << ipr_data[irq].shift);
+
+	/* Set the priority in IPR to 0 */
+	save_and_cli(flags);
+	val = ctrl_inw(addr);
+	val &= mask;
+	ctrl_outw(val, addr);
+	restore_flags(flags);
+}
+
+static void enable_ipr_irq(unsigned int irq)
+{
+	unsigned long val, flags;
+	unsigned int addr = ipr_data[irq].addr;
+	int priority = ipr_data[irq].priority;
+	unsigned short value = (priority << ipr_data[irq].shift);
+
+	/* Set priority in IPR back to original value */
+	save_and_cli(flags);
+	val = ctrl_inw(addr);
+	val |= value;
+	ctrl_outw(val, addr);
+	restore_flags(flags);
+}
+
+void make_ipr_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &ipr_irq_type;
+	disable_ipr_irq(irq);
+}
+
+static void mask_and_ack_ipr(unsigned int irq)
+{
+	disable_ipr_irq(irq);
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7709
+	/* This is needed when we use edge triggered setting */
+	/* XXX: Is it really needed? */
+	if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
+		/* Clear external interrupt request */
+		int a = ctrl_inb(INTC_IRR0);
+		a &= ~(1 << (irq - IRQ0_IRQ));
+		ctrl_outb(a, INTC_IRR0);
+	}
+#endif
+}
+
+static void end_ipr_irq(unsigned int irq)
+{
+	enable_ipr_irq(irq);
+}
+
+void __init init_IRQ(void)
+{
+	int i;
+
+	for (i = TIMER_IRQ; i < NR_IRQS; i++) {
+		irq_desc[i].handler = &ipr_irq_type;
+	}
+
+	set_ipr_data(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
+	set_ipr_data(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
+
+#ifdef CONFIG_CPU_SUBTYPE_SH7709
+	/*
+	 * Initialize the Interrupt Controller (INTC)
+	 * registers to their power on values
+	 */ 
+#if 0
+	/*
+	 * XXX: I think that this is the job of boot loader. -- gniibe
+	 *
+	 * When Takeshi released new boot loader following setting
+	 * will be removed shortly.
+	 */
+	ctrl_outb(0, INTC_IRR0);
+	ctrl_outb(0, INTC_IRR1);
+	ctrl_outb(0, INTC_IRR2);
+
+	ctrl_outw(0, INTC_ICR0);
+	ctrl_outw(0, INTC_ICR1);/* Really? 0x4000?*/
+	ctrl_outw(0, INTC_ICR2);
+	ctrl_outw(0, INTC_INTER);
+	ctrl_outw(0, INTC_IPRA);
+	ctrl_outw(0, INTC_IPRB);
+	ctrl_outw(0, INTC_IPRC);
+	ctrl_outw(0, INTC_IPRD);
+	ctrl_outw(0, INTC_IPRE);
+#endif
+
+	/*
+	 * Enable external irq (INTC IRQ mode).
+	 * You should set corresponding bits of PFC to "00"
+	 * to enable these interrupts.
+	 */
+	set_ipr_data(IRQ0_IRQ, IRQ0_IRP_ADDR, IRQ0_IRP_POS, IRQ0_PRIORITY);
+	set_ipr_data(IRQ1_IRQ, IRQ1_IRP_ADDR, IRQ1_IRP_POS, IRQ1_PRIORITY);
+	set_ipr_data(IRQ2_IRQ, IRQ2_IRP_ADDR, IRQ2_IRP_POS, IRQ2_PRIORITY);
+	set_ipr_data(IRQ3_IRQ, IRQ3_IRP_ADDR, IRQ3_IRP_POS, IRQ3_PRIORITY);
+	set_ipr_data(IRQ4_IRQ, IRQ4_IRP_ADDR, IRQ4_IRP_POS, IRQ4_PRIORITY);
+	set_ipr_data(IRQ5_IRQ, IRQ5_IRP_ADDR, IRQ5_IRP_POS, IRQ5_PRIORITY);
+#endif /* CONFIG_CPU_SUBTYPE_SH7709 */
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/irq_onchip.c linux/arch/sh/kernel/irq_onchip.c
--- v2.3.99-pre8/linux/arch/sh/kernel/irq_onchip.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/kernel/irq_onchip.c	Wed Dec 31 16:00:00 1969
@@ -1,298 +0,0 @@
-/* $Id: irq_onchip.c,v 1.7 2000-01-09 15:55:55+09 gniibe Exp $
- *
- * linux/arch/sh/kernel/irq_onchip.c
- *
- * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
- *
- * Interrupt handling for on-chip supporting modules (TMU, RTC, etc.).
- *
- */
-
-#include <linux/config.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/malloc.h>
-#include <linux/random.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/bitops.h>
-#include <asm/smp.h>
-#include <asm/pgtable.h>
-#include <asm/delay.h>
-
-#include <linux/irq.h>
-
-struct ipr_data {
-	int offset;
-	int priority;
-};
-static struct ipr_data ipr_data[NR_IRQS-TIMER_IRQ];
-
-void set_ipr_data(unsigned int irq, int offset, int priority)
-{
-	ipr_data[irq-TIMER_IRQ].offset = offset;
-	ipr_data[irq-TIMER_IRQ].priority = priority;
-}
-
-static void enable_onChip_irq(unsigned int irq);
-void disable_onChip_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_onChip_irq	disable_onChip_irq
-
-static void mask_and_ack_onChip(unsigned int);
-static void end_onChip_irq(unsigned int irq);
-
-static unsigned int startup_onChip_irq(unsigned int irq)
-{ 
-	enable_onChip_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type onChip_irq_type = {
-	"On-Chip-IPR",
-	startup_onChip_irq,
-	shutdown_onChip_irq,
-	enable_onChip_irq,
-	disable_onChip_irq,
-	mask_and_ack_onChip,
-	end_onChip_irq
-};
-
-/*
- * These have to be protected by the irq controller spinlock
- * before being called.
- *
- *
- * IPRA  15-12  11-8  7-4  3-0
- * IPRB  15-12  11-8  7-4  3-0
- * IPRC  15-12  11-8  7-4  3-0
- *
- */
-#if defined(__sh3__)
-#define INTC_IPR	0xfffffee2UL	/* Word access */
-#define INTC_SIZE	0x2
-#elif defined(__SH4__)
-#define INTC_IPR	0xffd00004UL	/* Word access */
-#define INTC_SIZE	0x4
-#endif
-
-void disable_onChip_irq(unsigned int irq)
-{
-	unsigned long val, flags;
-	/* Set priority in IPR to 0 */
-	int offset = ipr_data[irq-TIMER_IRQ].offset;
-	unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE);
-	unsigned short mask = 0xffff ^ (0xf << (offset%16));
-
-	save_and_cli(flags);
-	val = ctrl_inw(intc_ipr_address);
-	val &= mask;
-	ctrl_outw(val, intc_ipr_address);
-	restore_flags(flags);
-}
-
-static void enable_onChip_irq(unsigned int irq)
-{
-	unsigned long val, flags;
-	/* Set priority in IPR back to original value */
-	int offset = ipr_data[irq-TIMER_IRQ].offset;
-	int priority = ipr_data[irq-TIMER_IRQ].priority;
-	unsigned long intc_ipr_address = INTC_IPR + (offset/16*INTC_SIZE);
-	unsigned short value = (priority << (offset%16));
-
-	save_and_cli(flags);
-	val = ctrl_inw(intc_ipr_address);
-	val |= value;
-	ctrl_outw(val, intc_ipr_address);
-	restore_flags(flags);
-}
-
-void make_onChip_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	irq_desc[irq].handler = &onChip_irq_type;
-	enable_irq(irq);
-}
-
-static void mask_and_ack_onChip(unsigned int irq)
-{
-	disable_onChip_irq(irq);
-}
-
-static void end_onChip_irq(unsigned int irq)
-{
-	enable_onChip_irq(irq);
-}
-
-
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
-/*
- * SH7707/SH7709/SH7709A/SH7729 Extended on-chip I/O
- */
-
-#define INTC_IRR0	0xa4000004UL
-#define INTC_IRR1	0xa4000006UL
-#define INTC_IRR2	0xa4000008UL
-
-#define INTC_ICR0  	0xfffffee0
-#define INTC_ICR1  	0xa4000010
-#define INTC_ICR2  	0xa4000012
-#define INTC_INTER 	0xa4000014
-#define INTC_IPRA  	0xfffffee2
-#define INTC_IPRB  	0xfffffee4
-#define INTC_IPRC  	0xa4000016
-#define INTC_IPRD  	0xa4000018
-#define INTC_IPRE  	0xa400001a
-
-#define IRQ0_IRQ	32
-#define IRQ1_IRQ	33
-#define IRQ2_IRQ	34
-#define IRQ3_IRQ	35
-#define IRQ4_IRQ	36
-#define IRQ5_IRQ	37
-
-#define IRQ0_IRP_OFFSET	32
-#define IRQ1_IRP_OFFSET	36
-#define IRQ2_IRP_OFFSET	40
-#define IRQ3_IRP_OFFSET	44
-#define IRQ4_IRP_OFFSET	48
-#define IRQ5_IRP_OFFSET	52
-
-#define IRQ0_PRIORITY	1
-#define IRQ1_PRIORITY	1
-#define IRQ2_PRIORITY	1
-#define IRQ3_PRIORITY	1
-#define IRQ4_PRIORITY	1
-#define IRQ5_PRIORITY	1
-
-static void enable_onChip2_irq(unsigned int irq);
-void disable_onChip2_irq(unsigned int irq);
-
-/* shutdown is same as "disable" */
-#define shutdown_onChip2_irq	disable_onChip2_irq
-
-static void mask_and_ack_onChip2(unsigned int);
-static void end_onChip2_irq(unsigned int irq);
-
-static unsigned int startup_onChip2_irq(unsigned int irq)
-{ 
-	enable_onChip2_irq(irq);
-	return 0; /* never anything pending */
-}
-
-static struct hw_interrupt_type onChip2_irq_type = {
-	"Extended-IPR",
-	startup_onChip2_irq,
-	shutdown_onChip2_irq,
-	enable_onChip2_irq,
-	disable_onChip2_irq,
-	mask_and_ack_onChip2,
-	end_onChip2_irq
-};
-
-void disable_onChip2_irq(unsigned int irq)
-{
-	unsigned long val, flags;
-	/* Set priority in IPR to 0 */
-	int offset = ipr_data[irq-TIMER_IRQ].offset - 32;
-	unsigned long intc_ipr_address = INTC_IPRC + (offset/16*INTC_SIZE);
-	unsigned short mask = 0xffff ^ (0xf << (offset%16));
-
-	save_and_cli(flags);
-	val = ctrl_inw(intc_ipr_address);
-	val &= mask;
-	ctrl_outw(val, intc_ipr_address);
-	restore_flags(flags);
-}
-
-static void enable_onChip2_irq(unsigned int irq)
-{
-	unsigned long val, flags;
-	/* Set priority in IPR back to original value */
-	int offset = ipr_data[irq-TIMER_IRQ].offset - 32;
-	int priority = ipr_data[irq-TIMER_IRQ].priority;
-	unsigned long intc_ipr_address = INTC_IPRC + (offset/16*INTC_SIZE);
-	unsigned short value = (priority << (offset%16));
-
-	save_and_cli(flags);
-	val = ctrl_inw(intc_ipr_address);
-	val |= value;
-	ctrl_outw(val, intc_ipr_address);
-	restore_flags(flags);
-}
-
-static void mask_and_ack_onChip2(unsigned int irq)
-{
-	disable_onChip2_irq(irq);
-	if (IRQ0_IRQ <= irq && irq <= IRQ5_IRQ) {
-		/* Clear external interrupt request */
-		int a = ctrl_inb(INTC_IRR0);
-		a &= ~(1 << (irq - IRQ0_IRQ));
-		ctrl_outb(a, INTC_IRR0);
-	}
-}
-
-static void end_onChip2_irq(unsigned int irq)
-{
-	enable_onChip2_irq(irq);
-}
-#endif /* CONFIG_CPU_SUBTYPE_SH7709 */
-
-void __init init_IRQ(void)
-{
-	int i;
-
-	for (i = TIMER_IRQ; i < NR_IRQS; i++) {
-		irq_desc[i].handler = &onChip_irq_type;
-	}
-
-#ifdef CONFIG_CPU_SUBTYPE_SH7709
-
-	/*
-	 * Initialize the Interrupt Controller (INTC)
-	 * registers to their power on values
-	 */ 
-
-	ctrl_outb(0, INTC_IRR0);
-	ctrl_outb(0, INTC_IRR1);
-	ctrl_outb(0, INTC_IRR2);
-
-	ctrl_outw(0, INTC_ICR0);
-	ctrl_outw(0, INTC_ICR1);
-	ctrl_outw(0, INTC_ICR2);
-	ctrl_outw(0, INTC_INTER);
-	ctrl_outw(0, INTC_IPRA);
-	ctrl_outw(0, INTC_IPRB);
-	ctrl_outw(0, INTC_IPRC);
-	ctrl_outw(0, INTC_IPRD);
-	ctrl_outw(0, INTC_IPRE);
-
-	for (i = IRQ0_IRQ; i < NR_IRQS; i++) {
-		irq_desc[i].handler = &onChip2_irq_type;
-	}
-
-	/*
-	 * Enable external irq(INTC IRQ mode).
-	 * You should set corresponding bits of PFC to "00"
-	 * to enable these interrupts.
-	 */
-	set_ipr_data(IRQ0_IRQ, IRQ0_IRP_OFFSET, IRQ0_PRIORITY);
-	set_ipr_data(IRQ1_IRQ, IRQ1_IRP_OFFSET, IRQ1_PRIORITY);
-	set_ipr_data(IRQ2_IRQ, IRQ2_IRP_OFFSET, IRQ2_PRIORITY);
-	set_ipr_data(IRQ3_IRQ, IRQ3_IRP_OFFSET, IRQ3_PRIORITY);
-	set_ipr_data(IRQ4_IRQ, IRQ4_IRP_OFFSET, IRQ4_PRIORITY);
-	set_ipr_data(IRQ5_IRQ, IRQ5_IRP_OFFSET, IRQ5_PRIORITY);
-#endif /* CONFIG_CPU_SUBTYPE_SH7709 */
-}
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/ptrace.c linux/arch/sh/kernel/ptrace.c
--- v2.3.99-pre8/linux/arch/sh/kernel/ptrace.c	Tue Apr 11 15:09:14 2000
+++ linux/arch/sh/kernel/ptrace.c	Sat May 20 12:05:29 2000
@@ -1,4 +1,4 @@
-/* $Id: ptrace.c,v 1.4 2000/03/22 13:59:01 gniibe Exp $
+/* $Id: ptrace.c,v 1.5 2000/05/09 01:42:21 gniibe Exp $
  *
  * linux/arch/sh/kernel/ptrace.c
  *
@@ -137,7 +137,6 @@
 {
 	struct task_struct *child, *tsk = current;
 	struct user * dummy = NULL;
-	unsigned long flags;
 	int ret;
 
 	lock_kernel();
@@ -154,15 +153,19 @@
 	ret = -ESRCH;
 	read_lock(&tasklist_lock);
 	child = find_task_by_pid(pid);
-	read_unlock(&tasklist_lock);	/* FIXME!!! */
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
-		goto out;
+		goto out_tsk;
+
 	if (request == PTRACE_ATTACH) {
 		if (child == tsk)
-			goto out;
+			goto out_tsk;
 		if ((!child->dumpable ||
 		    (tsk->uid != child->euid) ||
 		    (tsk->uid != child->suid) ||
@@ -171,34 +174,33 @@
 	 	    (tsk->gid != child->sgid) ||
 	 	    (!cap_issubset(child->cap_permitted, tsk->cap_permitted)) ||
 	 	    (tsk->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
-			goto out;
+			goto out_tsk;
 		/* the same process cannot be attached many times */
 		if (child->flags & PF_PTRACED)
-			goto out;
+			goto out_tsk;
 		child->flags |= PF_PTRACED;
 
-		write_lock_irqsave(&tasklist_lock, flags);
+		write_lock_irq(&tasklist_lock);
 		if (child->p_pptr != tsk) {
 			REMOVE_LINKS(child);
 			child->p_pptr = tsk;
 			SET_LINKS(child);
 		}
-		write_unlock_irqrestore(&tasklist_lock, flags);
+		write_unlock_irq(&tasklist_lock);
 
 		send_sig(SIGSTOP, child, 1);
 		ret = 0;
-		goto out;
+		goto out_tsk;
 	}
 	ret = -ESRCH;
 	if (!(child->flags & PF_PTRACED))
-		goto out;
+		goto out_tsk;
 	if (child->state != TASK_STOPPED) {
 		if (request != PTRACE_KILL)
-			goto out;
+			goto out_tsk;
 	}
 	if (child->p_pptr != tsk)
-		goto out;
-
+		goto out_tsk;
 	switch (request) {
 	/* when I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
@@ -357,11 +359,11 @@
 			break;
 		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
 		child->exit_code = data;
-		write_lock_irqsave(&tasklist_lock, flags);
+		write_lock_irq(&tasklist_lock);
 		REMOVE_LINKS(child);
 		child->p_pptr = child->p_opptr;
 		SET_LINKS(child);
-		write_unlock_irqrestore(&tasklist_lock, flags);
+		write_unlock_irq(&tasklist_lock);
 		wake_up_process(child);
 		ret = 0;
 		break;
@@ -371,6 +373,8 @@
 		ret = -EIO;
 		break;
 	}
+out_tsk:
+	free_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/setup_se.c linux/arch/sh/kernel/setup_se.c
--- v2.3.99-pre8/linux/arch/sh/kernel/setup_se.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/setup_se.c	Sat May 20 12:05:29 2000
@@ -0,0 +1,123 @@
+/* $Id: setup_se.c,v 1.6 2000/05/14 08:41:25 gniibe Exp $
+ *
+ * linux/arch/sh/kernel/setup_se.c
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <asm/io.h>
+#include <asm/hitachi_se.h>
+#include <asm/smc37c93x.h>
+
+/*
+ * Configure the Super I/O chip
+ */
+static void __init smsc_config(int index, int data)
+{
+	outb_p(index, INDEX_PORT);
+	outb_p(data, DATA_PORT);
+}
+
+static void __init init_smsc(void)
+{
+	outb_p(CONFIG_ENTER, CONFIG_PORT);
+	outb_p(CONFIG_ENTER, CONFIG_PORT);
+
+	/* FDC */
+	smsc_config(CURRENT_LDN_INDEX, LDN_FDC);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IRQ_SELECT_INDEX, 6); /* IRQ6 */
+
+	/* IDE1 */
+	smsc_config(CURRENT_LDN_INDEX, LDN_IDE1);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IRQ_SELECT_INDEX, 14); /* IRQ14 */
+
+	/* AUXIO (GPIO): to use IDE1 */
+	smsc_config(CURRENT_LDN_INDEX, LDN_AUXIO);
+	smsc_config(GPIO46_INDEX, 0x00); /* nIOROP */
+	smsc_config(GPIO47_INDEX, 0x00); /* nIOWOP */
+
+	/* COM1 */
+	smsc_config(CURRENT_LDN_INDEX, LDN_COM1);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IO_BASE_HI_INDEX, 0x03);
+	smsc_config(IO_BASE_LO_INDEX, 0xf8);
+	smsc_config(IRQ_SELECT_INDEX, 3); /* IRQ3 */
+
+	/* RTC */
+	smsc_config(CURRENT_LDN_INDEX, LDN_RTC);
+	smsc_config(ACTIVATE_INDEX, 0x01);
+	smsc_config(IRQ_SELECT_INDEX, 8); /* IRQ8 */
+
+	/* XXX: COM2, PARPORT, KBD, and MOUSE will come here... */
+	outb_p(CONFIG_EXIT, CONFIG_PORT);
+}
+
+/*
+ * Initialize IRQ setting
+ */
+static void __init init_se_IRQ(void)
+{
+	int i;
+
+	/*
+	 * Super I/O (Just mimic PC):
+	 *  1: keyboard
+	 *  3: serial 0
+	 *  4: serial 1
+	 *  5: printer
+	 *  6: floppy
+	 *  8: rtc
+	 * 12: mouse
+	 * 14: ide0
+	 */
+	set_ipr_data(14, BCR_ILCRA, 2, 0x0f-14);
+	set_ipr_data(12, BCR_ILCRA, 1, 0x0f-12); 
+	set_ipr_data( 8, BCR_ILCRB, 1, 0x0f- 8); 
+	set_ipr_data( 6, BCR_ILCRC, 3, 0x0f- 6);
+	set_ipr_data( 5, BCR_ILCRC, 2, 0x0f- 5);
+	set_ipr_data( 4, BCR_ILCRC, 1, 0x0f- 4);
+	set_ipr_data( 3, BCR_ILCRC, 0, 0x0f- 3);
+	set_ipr_data( 1, BCR_ILCRD, 3, 0x0f- 1);
+
+	set_ipr_data(10, BCR_ILCRD, 1, 0x0f-10); /* LAN */
+
+	set_ipr_data( 0, BCR_ILCRE, 3, 0x0f- 0); /* PCIRQ3 */
+	set_ipr_data(11, BCR_ILCRE, 2, 0x0f-11); /* PCIRQ2 */
+	set_ipr_data( 9, BCR_ILCRE, 1, 0x0f- 9); /* PCIRQ1 */
+	set_ipr_data( 7, BCR_ILCRE, 0, 0x0f- 7); /* PCIRQ0 */
+
+	/* #2, #13 are allocated for SLOT IRQ #1 and #2 (for now) */
+	/* NOTE: #2 and #13 are not used on PC */
+	set_ipr_data(13, BCR_ILCRG, 1, 0x0f-13); /* SLOTIRQ2 */
+	set_ipr_data( 2, BCR_ILCRG, 0, 0x0f- 2); /* SLOTIRQ1 */
+
+	for (i = 0; i < 15; i++) {
+		make_ipr_irq(i);
+	}
+}
+
+/*
+ * Initialize the board
+ */
+int __init setup_se(void)
+{
+	init_se_IRQ();
+	init_smsc();
+	/* XXX: RTC setting comes here */
+
+	printk(KERN_INFO "Hitach SolutionEngine Setup...done\n");
+	return 0;
+}
+
+module_init(setup_se);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/signal.c linux/arch/sh/kernel/signal.c
--- v2.3.99-pre8/linux/arch/sh/kernel/signal.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/kernel/signal.c	Sat May 20 12:05:29 2000
@@ -165,11 +165,11 @@
 	unsigned long flags;
 
 	if (!tsk->used_math) {
-		sc->sc_ownedfp = 0;
+		__copy_to_user(&sc->sc_ownedfp, 0, sizeof(int));
 		return 0;
 	}
 
-	sc->sc_ownedfp = 1;
+	__copy_to_user(&sc->sc_ownedfp, 1, sizeof(int));
 
 	/* This will cause a "finit" to be triggered by the next
 	   attempted FPU operation by the 'current' process.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c
--- v2.3.99-pre8/linux/arch/sh/kernel/time.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/kernel/time.c	Sat May 20 12:05:29 2000
@@ -47,9 +47,6 @@
 #define RCR2_RESET	0x02	/* Reset bit               */
 #define RCR2_START	0x01	/* Start bit               */
 
-#define RTC_IRQ		22
-#define RTC_IPR_OFFSET	0
-
 #if defined(__sh3__)
 #define TMU_TOCR	0xfffffe90	/* Byte access */
 #define TMU_TSTR	0xfffffe92	/* Byte access */
@@ -204,13 +201,6 @@
 static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	do_timer(regs);
-#ifdef TAKESHI
-	{
-		unsigned long what_is_this=0xa4000124;
-
-		ctrl_outb(ctrl_inb(what_is_this)+1,what_is_this);
-	}
-#endif
 #if 0
 	if (!user_mode(regs))
 		sh_do_profile(regs->pc);
@@ -393,23 +383,23 @@
 
 void __init time_init(void)
 {
-	unsigned int cpu_clock, master_clock, module_clock;
-	unsigned short ifc, pfc;
+	unsigned int cpu_clock, master_clock, bus_clock, module_clock;
+	unsigned short frqcr, ifc, pfc;
 	unsigned long interval;
 #if defined(__sh3__)
 	static int ifc_table[] = { 1, 2, 4, 1, 3, 1, 1, 1 };
 	static int pfc_table[] = { 1, 2, 4, 1, 3, 6, 1, 1 };
+	static int stc_table[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
 #elif defined(__SH4__)
 	static int ifc_table[] = { 1, 2, 3, 4, 6, 8, 1, 1 };
+#define bfc_table ifc_table	/* Same */
 	static int pfc_table[] = { 2, 3, 4, 6, 8, 2, 2, 2 };
 #endif
 
 	xtime.tv_sec = get_rtc_time();
 	xtime.tv_usec = 0;
 
-	set_ipr_data(TIMER_IRQ, TIMER_IPR_OFFSET, TIMER_PRIORITY);
 	setup_irq(TIMER_IRQ, &irq0);
-	set_ipr_data(RTC_IRQ, RTC_IPR_OFFSET, TIMER_PRIORITY);
 	setup_irq(RTC_IRQ, &irq1);
 
 	/* Check how fast it is.. */
@@ -420,23 +410,37 @@
 	       (cpu_clock / 1000000), (cpu_clock % 1000000)/10000);
 #if defined(__sh3__)
 	{
-		unsigned short tmp;
-		tmp  = (ctrl_inw(FRQCR) & 0x000c) >> 2;
-		tmp |= (ctrl_inw(FRQCR) & 0x4000) >> 12;
-		ifc  = ifc_table[tmp & 0x0007];
-		tmp  = ctrl_inw(FRQCR) & 0x0003;
-		tmp |= (ctrl_inw(FRQCR) & 0x2000) >> 11;
-		pfc = pfc_table[ctrl_inw(FRQCR) & 0x0007];
+		unsigned short tmp, stc;
+		frqcr = ctrl_inw(FRQCR);
+		tmp  = (frqcr & 0x8000) >> 13;
+		tmp |= (frqcr & 0x0030) >>  4;
+		stc = stc_table[tmp];
+		tmp  = (frqcr & 0x4000) >> 12;
+		tmp |= (frqcr & 0x000c) >> 2;
+		ifc  = ifc_table[tmp];
+		tmp  = (frqcr & 0x2000) >> 11;
+		tmp |= frqcr & 0x0003;
+		pfc = pfc_table[tmp];
+		master_clock = cpu_clock;
+		bus_clock = master_clock/pfc;
 	}
 #elif defined(__SH4__)
-	ifc  = ifc_table[(ctrl_inw(FRQCR)>> 6) & 0x0007];
-	pfc = pfc_table[ctrl_inw(FRQCR) & 0x0007];
+	{
+		unsigned short bfc;
+		frqcr = ctrl_inw(FRQCR);
+		ifc  = ifc_table[(frqcr>> 6) & 0x0007];
+		bfc  = bfc_table[(frqcr>> 3) & 0x0007];
+		pfc = pfc_table[frqcr & 0x0007];
+		master_clock = cpu_clock * ifc;
+		bus_clock = master_clock/bfc;
+	}
 #endif
-	master_clock = cpu_clock * ifc;
+	printk("Bus clock: %d.%02dMHz\n",
+	       (bus_clock/1000000), (bus_clock % 1000000)/10000);
 	module_clock = master_clock/pfc;
 	printk("Module clock: %d.%02dMHz\n",
 	       (module_clock/1000000), (module_clock % 1000000)/10000);
-	interval = (module_clock/400);
+	interval = (module_clock/(HZ*4));
 
 	printk("Interval = %ld\n", interval);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/lib/checksum.S linux/arch/sh/lib/checksum.S
--- v2.3.99-pre8/linux/arch/sh/lib/checksum.S	Sun Nov  7 16:37:34 1999
+++ linux/arch/sh/lib/checksum.S	Sat May 20 12:05:29 2000
@@ -1,4 +1,4 @@
-/* $Id: checksum.S,v 1.2 1999/10/29 13:06:55 gniibe Exp $
+/* $Id: checksum.S,v 1.4 2000/05/14 08:41:26 gniibe Exp $
  *
  * INET		An implementation of the TCP/IP protocol suite for the LINUX
  *		operating system.  INET is implemented using the  BSD Socket
@@ -49,95 +49,99 @@
 	   * Fortunately, it is easy to convert 2-byte alignment to 4-byte
 	   * alignment for the unrolled loop.
 	   */
-	mov	r5,r1
-	mov	r4,r0
-	tst	#2,r0		! Check alignment.
+	mov	$r5, $r1
+	mov	$r4, $r0
+	tst	#2, $r0		! Check alignment.
 	bt	2f		! Jump if alignment is ok.
 	!
-	add	#-2,r5		! Alignment uses up two bytes.
-	cmp/pz	r5		!
+	add	#-2, $r5	! Alignment uses up two bytes.
+	cmp/pz	$r5		!
 	bt/s	1f		! Jump if we had at least two bytes.
 	 clrt
 	bra	6f
-	 add	#2,r5		! r5 was < 2.  Deal with it.
+	 add	#2, $r5		! $r5 was < 2.  Deal with it.
 1:
-	mov.w	@r4+,r0
-	extu.w	r0,r0
-	addc	r0,r6
+	mov.w	@$r4+, $r0
+	extu.w	$r0, $r0
+	addc	$r0, $r6
 	bf	2f
-	add	#1,r6
+	add	#1, $r6
 2:
-	mov	#-5,r0
-	shld	r0,r5
-	tst	r5,r5
+	mov	#-5, $r0
+	shld	$r0, $r5
+	tst	$r5, $r5
 	bt/s	4f		! if it's =0, go to 4f
 	 clrt
+	.align	2
 3:
-	mov.l	@r4+,r0
-	addc	r0,r6
-	mov.l	@r4+,r0
-	addc	r0,r6
-	mov.l	@r4+,r0
-	addc	r0,r6
-	mov.l	@r4+,r0
-	addc	r0,r6
-	mov.l	@r4+,r0
-	addc	r0,r6
-	mov.l	@r4+,r0
-	addc	r0,r6
-	mov.l	@r4+,r0
-	addc	r0,r6
-	mov.l	@r4+,r0
-	addc	r0,r6
-	movt	r0
-	dt	r5
+	mov.l	@$r4+, $r0
+	mov.l	@$r4+, $r2
+	mov.l	@$r4+, $r3
+	addc	$r0, $r6
+	mov.l	@$r4+, $r0
+	addc	$r2, $r6
+	mov.l	@$r4+, $r2
+	addc	$r3, $r6
+	mov.l	@$r4+, $r3
+	addc	$r0, $r6
+	mov.l	@$r4+, $r0
+	addc	$r2, $r6
+	mov.l	@$r4+, $r2
+	addc	$r3, $r6
+	addc	$r0, $r6
+	addc	$r2, $r6
+	movt	$r0	
+	dt	$r5
 	bf/s	3b
-	 cmp/eq	#1,r0
-	mov	#0,r0
-	addc	r0,r6
+	 cmp/eq	#1, $r0
+	! here, we know $r5==0
+	addc	$r5, $r6		! add carry to $r6
 4:
-	mov	r1,r5
-	mov	#0x1c,r0
-	and	r0,r5
-	tst	r5,r5
+	mov	$r1, $r0
+	and	#0x1c, $r0
+	tst	$r0, $r0
 	bt/s	6f
-	 clrt
-	shlr2	r5
+	 mov	$r0, $r5
+	shlr2	$r5
+	mov	#0, $r2
 5:
-	mov.l	@r4+,r0
-	addc	r0,r6
-	movt	r0
-	dt	r5
+	addc	$r2, $r6
+	mov.l	@$r4+, $r2
+	movt	$r0
+	dt	$r5
 	bf/s	5b
-	 cmp/eq	#1,r0
-	mov	#0,r0
-	addc	r0,r6
+	 cmp/eq	#1, $r0
+	addc	$r2, $r6
+	addc	$r5, $r6	! $r5==0 here, so it means add carry-bit
 6:
-	mov	r1,r5
-	mov	#3,r0
-	and	r0,r5
-	tst	r5,r5
+	mov	$r1, $r5
+	mov	#3, $r0
+	and	$r0, $r5
+	tst	$r5, $r5
 	bt	9f		! if it's =0 go to 9f
-	mov	#2,r1
-	cmp/hs  r1,r5
+	mov	#2, $r1
+	cmp/hs  $r1, $r5
 	bf	7f
-	mov.w	@r4+,r0
-	extu.w	r0,r0
-	cmp/eq	r1,r5
+	mov.w	@r4+, $r0
+	extu.w	$r0, $r0
+	cmp/eq	$r1, $r5
 	bt/s	8f
 	 clrt
-	shll16	r0
-	addc	r0,r6
+	shll16	$r0
+	addc	$r0, $r6
 7:
-	mov.b	@r4+,r0
-	extu.b	r0,r0
+	mov.b	@$r4+, $r0
+	extu.b	$r0, $r0
+#ifndef	__LITTLE_ENDIAN__
+	shll8	$r0
+#endif
 8:
-	addc	r0,r6
-	mov	#0,r0
-	addc	r0,r6 
+	addc	$r0, $r6
+	mov	#0, $r0
+	addc	$r0, $r6 
 9:
 	rts
-	 mov	r6,r0
+	 mov	$r6, $r0
 
 /*
 unsigned int csum_partial_copy_generic (const char *src, char *dst, int len, 
@@ -167,6 +171,16 @@
 	.long 9999b, 6002f	;	\
 	.previous
 
+!
+! r4:	const char *SRC
+! r5:	char *DST
+! r6:	int LEN
+! r7:	int SUM
+!
+! on stack:
+! int *SRC_ERR_PTR
+! int *DST_ERR_PTR
+!
 ENTRY(csum_partial_copy_generic)
 	mov.l	r5,@-r15
 	mov.l	r6,@-r15
@@ -179,7 +193,7 @@
 	bt/s	1f
 	 clrt
 	bra	4f
-	 add	#2,r6			! ecx was < 2.  Deal with it.
+	 add	#2,r6			! $r6 was < 2.  Deal with it.
 SRC(1:	mov.w	@r4+,r0	)
 DST(	mov.w	r0,@r5	)
 	add	#2,r5
@@ -273,6 +287,9 @@
 SRC(5:	mov.b	@r4+,r0	)
 DST(	mov.b	r0,@r5	)
 	extu.b	r0,r0
+#ifndef	__LITTLE_ENDIAN__
+	shll8	r0
+#endif
 6:	addc	r0,r7
 	mov	#0,r0
 	addc	r0,r7
@@ -299,7 +316,7 @@
 	mov.l	8000f,r0
 	jmp	@r0
 	 nop
-	.balign 4
+	.align	2
 8000:	.long	5000b
 
 6002:
@@ -309,7 +326,7 @@
 	mov.l	8001f,r0
 	jmp	@r0
 	 nop
-	.balign 4
+	.align	2
 8001:	.long	5000b
 
 .previous
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c
--- v2.3.99-pre8/linux/arch/sh/mm/cache.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/mm/cache.c	Sat May 20 12:05:29 2000
@@ -49,7 +49,7 @@
 #elif defined(__SH4__)
 #define CCR		 0xff00001c	/* Address of Cache Control Register */
 #define CCR_CACHE_VAL	 0x00000105	/* 8k+16k-byte cache,P1-wb,enable */
-#define CCR_CACHE_INIT	 0x0000090d	/* 8k+16k-byte cache,CF,P1-wb,enable */
+#define CCR_CACHE_INIT	 0x0000090d	/* ICI,ICE(8k), OCI,P1-wb,OCE(16k) */
 #define CCR_CACHE_ENABLE 0x00000101
 
 #define CACHE_IC_ADDRESS_ARRAY 0xf0000000
@@ -60,143 +60,41 @@
 #define CACHE_OC_WAY_SHIFT       13
 #define CACHE_IC_WAY_SHIFT       13
 #define CACHE_OC_ENTRY_SHIFT      5
+#define CACHE_IC_ENTRY_SHIFT      5
 #define CACHE_OC_ENTRY_MASK  0x3fe0
+#define CACHE_OC_ENTRY_PHYS_MASK  0x0fe0
 #define CACHE_IC_ENTRY_MASK  0x1fe0
+#define CACHE_IC_NUM_ENTRIES	256
 #define CACHE_OC_NUM_ENTRIES	512
 #define CACHE_OC_NUM_WAYS	  1
 #define CACHE_IC_NUM_WAYS	  1
 #endif
 
-/* Write back caches to memory (if needed) and invalidates the caches */
-void cache_flush_area(unsigned long start, unsigned long end)
-{
-	unsigned long flags;
-	unsigned long addr, data, v, p;
-
-	start &= ~(L1_CACHE_BYTES-1);
-	save_and_cli(flags);
-	jump_to_P2();
-
-	for (v = start; v < end; v+=L1_CACHE_BYTES) {
-		p = __pa(v);
-		addr = CACHE_IC_ADDRESS_ARRAY |
-			(v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */;
-		data = (v&0xfffffc00); /* U=0, V=0 */
-		ctrl_outl(data,addr);
-#if CACHE_IC_ADDRESS_ARRAY != CACHE_OC_ADDRESS_ARRAY
-		asm volatile("ocbp	%0"
-			     : /* no output */
-			     : "m" (__m(v)));
-#endif
-	}
-	back_to_P1();
-	restore_flags(flags);
-}
-
-/* Purge (just invalidate, no write back) the caches */
-/* This is expected to work well.. but..
-
-   On SH7708S, the write-back cache is written back on "purge".
-   (it's not expected, though).
-
-   It seems that we have no way to just purge (with no write back action)
-   the cache line. */
-void cache_purge_area(unsigned long start, unsigned long end)
-{
-	unsigned long flags;
-	unsigned long addr, data, v, p, j;
-
-	start &= ~(L1_CACHE_BYTES-1);
-	save_and_cli(flags);
-	jump_to_P2();
-
-	for (v = start; v < end; v+=L1_CACHE_BYTES) {
-		p = __pa(v);
-		for (j=0; j<CACHE_IC_NUM_WAYS; j++) {
-			addr = CACHE_IC_ADDRESS_ARRAY|(j<<CACHE_IC_WAY_SHIFT)|
-				(v&CACHE_IC_ENTRY_MASK);
-			data = ctrl_inl(addr);
-			if ((data & 0xfffffc00) == (p&0xfffffc00)
-			    && (data & CACHE_VALID)) {
-				data &= ~CACHE_VALID;
-				ctrl_outl(data,addr);
-				break;
-			}
-		}
-#if CACHE_IC_ADDRESS_ARRAY != CACHE_OC_ADDRESS_ARRAY
-		asm volatile("ocbi	%0"
-			     : /* no output */
-			     : "m" (__m(v)));
-#endif
-	}
-	back_to_P1();
-	restore_flags(flags);
-}
-
-/* write back the dirty cache, but not invalidate the cache */
-void cache_wback_area(unsigned long start, unsigned long end)
-{
-	unsigned long flags;
-	unsigned long v;
-
-	start &= ~(L1_CACHE_BYTES-1);
-	save_and_cli(flags);
-	jump_to_P2();
-
-	for (v = start; v < end; v+=L1_CACHE_BYTES) {
-#if CACHE_IC_ADDRESS_ARRAY == CACHE_OC_ADDRESS_ARRAY
-		unsigned long addr, data, j;
-		unsigned long p = __pa(v);
-
-		for (j=0; j<CACHE_OC_NUM_WAYS; j++) {
-			addr = CACHE_OC_ADDRESS_ARRAY|(j<<CACHE_OC_WAY_SHIFT)|
-				(v&CACHE_OC_ENTRY_MASK);
-			data = ctrl_inl(addr);
-			if ((data & 0xfffffc00) == (p&0xfffffc00)
-			    && (data & CACHE_VALID)
-			    && (data & CACHE_UPDATED)) {
-				data &= ~CACHE_UPDATED;
-				ctrl_outl(data,addr);
-				break;
-			}
-		}
-#else
-		asm volatile("ocbwb	%0"
-			     : /* no output */
-			     : "m" (__m(v)));
-#endif
-	}
-	back_to_P1();
-	restore_flags(flags);
-}
 
 /*
- * Write back the cache.
+ * Write back all the cache.
  *
- * For SH-4, flush (write back) Operand Cache, as Instruction Cache
- * doesn't have "updated" data.
+ * For SH-4, we only need to flush (write back) Operand Cache,
+ * as Instruction Cache doesn't have "updated" data.
  *
- * Assumes that called in interrupt disabled.
+ * Assumes that this is called in interrupt disabled context, and P2.
+ * Shuld be INLINE function.
  */
-static void cache_wback_all(void)
+static inline void cache_wback_all(void)
 {
 	unsigned long addr, data, i, j;
 
-	jump_to_P2();
-
 	for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
 		for (j=0; j<CACHE_OC_NUM_WAYS; j++) {
 			addr = CACHE_OC_ADDRESS_ARRAY|(j<<CACHE_OC_WAY_SHIFT)|
 				(i<<CACHE_OC_ENTRY_SHIFT);
 			data = ctrl_inl(addr);
-			if (data & CACHE_VALID) {
-				data &= ~(CACHE_VALID|CACHE_UPDATED);
-				ctrl_outl(data,addr);
+			if (data & CACHE_UPDATED) {
+				data &= ~CACHE_UPDATED;
+				ctrl_outl(data, addr);
 			}
 		}
 	}
-
-	back_to_P1();
 }
 
 static void
@@ -206,7 +104,8 @@
 	unsigned long addr0, addr1, data0, data1, data2, data3;
 
 	jump_to_P2();
-	/* Check if the entry shadows or not.
+	/*
+	 * Check if the entry shadows or not.
 	 * When shadowed, it's 128-entry system.
 	 * Otherwise, it's 256-entry system.
 	 */
@@ -221,8 +120,8 @@
 	data3 = ctrl_inl(addr0);
 
 	/* Invaliate them, in case the cache has been enabled already. */
-	ctrl_outl(data0&~0x00000001,addr0);
-	ctrl_outl(data2&~0x00000001,addr1);
+	ctrl_outl(data0&~0x00000001, addr0);
+	ctrl_outl(data2&~0x00000001, addr1);
 	back_to_P1();
 
 	if (data0 == data1 && data2 == data3) {	/* Shadow */
@@ -250,76 +149,141 @@
 	ccr = ctrl_inl(CCR);
 	if (ccr == CCR_CACHE_VAL)
 		return;
+	jump_to_P2();
 	if (ccr & CCR_CACHE_ENABLE)
-		/* Should check RA here. If RA was 1,
-		   we only need to flush the half of the caches. */
+		/*
+		 * XXX: Should check RA here. 
+		 * If RA was 1, we only need to flush the half of the caches.
+		 */
 		cache_wback_all();
 
-	jump_to_P2();
 	ctrl_outl(CCR_CACHE_INIT, CCR);
 	back_to_P1();
 }
 
 #if defined(__SH4__)
-void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
+/*
+ * SH-4 has virtually indexed and physically tagged cache.
+ */
+
+/*
+ * Write back the dirty D-caches, but not invalidate them.
+ *
+ * START, END: Virtual Address
+ */
+static void dcache_wback_range(unsigned long start, unsigned long end)
 {
-	unsigned long flags;
-	unsigned long addr, data, v;
+	unsigned long v;
 
-	save_and_cli(flags);
-	jump_to_P2();
+	start &= ~(L1_CACHE_BYTES-1);
+	for (v = start; v < end; v+=L1_CACHE_BYTES) {
+		asm volatile("ocbwb	%0"
+			     : /* no output */
+			     : "m" (__m(v)));
+	}
+}
 
-	v = page_address(pg);
+/*
+ * Invalidate I-caches.
+ *
+ * START, END: Virtual Address
+ *
+ */
+static void icache_purge_range(unsigned long start, unsigned long end)
+{
+	unsigned long addr, data, v;
 
-	/* Write back O Cache */
-	asm volatile("ocbwb	%0"
-		     : /* no output */
-		     : "m" (__m(v)));
-	/* Invalidate I Cache */
-	addr = CACHE_IC_ADDRESS_ARRAY |
-		(v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */;
-	data = (v&0xfffffc00); /* Valid=0 */
-	ctrl_outl(data,addr);
+	start &= ~(L1_CACHE_BYTES-1);
 
+	jump_to_P2();
+	/*
+	 * To handle the cache-line, we calculate the entry with virtual
+	 * address: entry = vaddr & CACHE_IC_ENTRY_MASK.
+	 *
+	 * With A-bit "on", data written to is translated by MMU and
+	 * compared the tag of cache and if it's not matched, nothing
+	 * will be occurred.  (We can avoid flushing other caches.)
+	 * 
+	 */
+	for (v = start; v < end; v+=L1_CACHE_BYTES) {
+		addr = CACHE_IC_ADDRESS_ARRAY |	(v&CACHE_IC_ENTRY_MASK)
+			| 0x8 /* A-bit */;
+		data = (v&0xfffffc00); /* Valid=0 */
+		ctrl_outl(data, addr);
+	}
 	back_to_P1();
-	restore_flags(flags);
 }
 
+/*
+ * Write back the range of D-cache, and purge the I-cache.
+ *
+ * Called from sh/kernel/signal.c, after accessing the memory
+ * through U0 area.  START and END is the address of U0.
+ */
 void flush_icache_range(unsigned long start, unsigned long end)
 {
-	unsigned long flags;
-	unsigned long addr, data, v;
+	dcache_wback_range(start, end);
+	icache_purge_range(start, end);
+}
 
-	start &= ~(L1_CACHE_BYTES-1);
-	save_and_cli(flags);
-	jump_to_P2();
+/*
+ * Invalidate the I-cache of the page (don't need to write back D-cache).
+ *
+ * Called from kernel/ptrace.c, mm/memory.c after flush_page_to_ram is called.
+ */
+void flush_icache_page(struct vm_area_struct *vma, struct page *pg)
+{
+	unsigned long phys, addr, data, i;
 
-	for (v = start; v < end; v+=L1_CACHE_BYTES) {
-		/* Write back O Cache */
-		asm volatile("ocbwb	%0"
-			     : /* no output */
-			     : "m" (__m(v)));
-		/* Invalidate I Cache */
-		addr = CACHE_IC_ADDRESS_ARRAY |
-			(v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */;
-		data = (v&0xfffffc00); /* Valid=0 */
-		ctrl_outl(data,addr);
+	/*
+	 * Alas, we don't know where the virtual address is,
+	 * So, we can't use icache_purge_range().
+	 */
+
+	/* Physical address of this page */
+	phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START;
+
+	jump_to_P2();
+	/* Loop all the I-cache */
+	for (i=0; i<CACHE_IC_NUM_ENTRIES; i++) {
+		addr = CACHE_IC_ADDRESS_ARRAY| (i<<CACHE_IC_ENTRY_SHIFT);
+		data = ctrl_inl(addr);
+		if ((data & CACHE_VALID) && (data&PAGE_MASK) == phys) {
+			data &= ~CACHE_VALID;
+			ctrl_outl(data, addr);
+		}
 	}
 	back_to_P1();
-	restore_flags(flags);
 }
 
 void flush_cache_all(void)
 {
+	unsigned long addr, data, i;
 	unsigned long flags;
 
 	save_and_cli(flags);
-	/* Write back Operand Cache */
-	cache_wback_all();
-
-	/* Then, invalidate Instruction Cache and Operand Cache */
 	jump_to_P2();
-	ctrl_outl(CCR_CACHE_INIT, CCR);
+
+	/* Loop all the D-cache */
+	for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
+		addr = CACHE_OC_ADDRESS_ARRAY|(i<<CACHE_OC_ENTRY_SHIFT);
+		data = ctrl_inl(addr);
+		if (data & CACHE_VALID) {
+			data &= ~(CACHE_UPDATED|CACHE_VALID);
+			ctrl_outl(data, addr);
+		}
+	}
+
+	/* Loop all the I-cache */
+	for (i=0; i<CACHE_IC_NUM_ENTRIES; i++) {
+		addr = CACHE_IC_ADDRESS_ARRAY| (i<<CACHE_IC_ENTRY_SHIFT);
+		data = ctrl_inl(addr);
+		if (data & CACHE_VALID) {
+			data &= ~CACHE_VALID;
+			ctrl_outl(data, addr);
+		}
+	}
+
 	back_to_P1();
 	restore_flags(flags);
 }
@@ -334,24 +298,42 @@
 void flush_cache_range(struct mm_struct *mm, unsigned long start,
 		       unsigned long end)
 {
-	unsigned long flags;
+	/*
+	 * Calling
+	 *	dcache_flush_range(start, end);
+	 * is not good for the purpose of this function.  That is,
+	 * flushing cache lines indexed by the virtual address is not
+	 * sufficient.
+	 *
+	 * Instead, we need to flush the relevant cache lines which
+	 * hold the data of the corresponding physical memory, as we
+	 * have "alias" issues.
+	 *
+	 * This is needed because, kernel accesses the memory through
+	 * P1-area (and/or U0-area) and user-space accesses through U0-area.
+	 * And P1-area and U0-area may use different cache lines for
+	 * same physical memory.
+	 *
+	 * If we would call dcache_flush_range(), the line of P1-area
+	 * could remain in the cache, unflushed.
+	 */
 	unsigned long addr, data, v;
 
 	start &= ~(L1_CACHE_BYTES-1);
-	save_and_cli(flags);
 	jump_to_P2();
 
 	for (v = start; v < end; v+=L1_CACHE_BYTES) {
-		addr = CACHE_IC_ADDRESS_ARRAY |
-			(v&CACHE_IC_ENTRY_MASK) | 0x8 /* A-bit */;
-		data = (v&0xfffffc00); /* Update=0, Valid=0 */
-		ctrl_outl(data,addr);
 		addr = CACHE_OC_ADDRESS_ARRAY |
-			(v&CACHE_OC_ENTRY_MASK) | 0x8 /* A-bit */;
-		ctrl_outl(data,addr);
+			(v&CACHE_OC_ENTRY_PHYS_MASK) | 0x8 /* A-bit */;
+		data = (v&0xfffffc00); /* Update=0, Valid=0 */
+
+		/* Try all the cases for aliases */
+		ctrl_outl(data, addr);
+		ctrl_outl(data, addr | 0x1000);
+		ctrl_outl(data, addr | 0x2000);
+		ctrl_outl(data, addr | 0x3000);
 	}
 	back_to_P1();
-	restore_flags(flags);
 }
 
 void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
@@ -359,9 +341,30 @@
 	flush_cache_range(vma->vm_mm, addr, addr+PAGE_SIZE);
 }
 
-void __flush_page_to_ram(unsigned long page)
-{				/* Page is in physical address */
-	/* XXX: for the time being... */
-	flush_cache_all();
+/*
+ * After accessing the memory from kernel space (P1-area), we need to 
+ * write back the cache line, to avoid "alias" issues.
+ *
+ * We search the D-cache to see if we have the entries corresponding to
+ * the page, and if found, write back them.
+ */
+void flush_page_to_ram(struct page *pg)
+{
+	unsigned long phys, addr, data, i;
+
+	/* Physical address of this page */
+	phys = (pg - mem_map)*PAGE_SIZE + __MEMORY_START;
+
+	jump_to_P2();
+	/* Loop all the D-cache */
+	for (i=0; i<CACHE_OC_NUM_ENTRIES; i++) {
+		addr = CACHE_OC_ADDRESS_ARRAY| (i<<CACHE_OC_ENTRY_SHIFT);
+		data = ctrl_inl(addr);
+		if ((data & CACHE_UPDATED) && (data&PAGE_MASK) == phys) {
+			data &= ~CACHE_UPDATED;
+			ctrl_outl(data, addr);
+		}
+	}
+	back_to_P1();
 }
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sh/mm/fault.c linux/arch/sh/mm/fault.c
--- v2.3.99-pre8/linux/arch/sh/mm/fault.c	Wed Apr 26 16:34:07 2000
+++ linux/arch/sh/mm/fault.c	Sat May 20 12:05:29 2000
@@ -28,6 +28,7 @@
 #include <asm/mmu_context.h>
 
 extern void die(const char *,struct pt_regs *,long);
+static void __flush_tlb_page(struct mm_struct *mm, unsigned long page);
 
 /*
  * Ugly, ugly, but the goto's result in better assembly..
@@ -167,12 +168,17 @@
 	 * make sure we exit gracefully rather than endlessly redo
 	 * the fault.
 	 */
-	{
-		int fault = handle_mm_fault(mm, vma, address, writeaccess);
-		if (fault < 0)
-			goto out_of_memory;
-		if (!fault)
-			goto do_sigbus;
+	switch (handle_mm_fault(mm, vma, address, writeaccess)) {
+	case 1:
+		tsk->min_flt++;
+		break;
+	case 2:
+		tsk->maj_flt++;
+		break;
+	case 0:
+		goto do_sigbus;
+	default:
+		goto out_of_memory;
 	}
 
 	up(&mm->mmap_sem);
@@ -209,18 +215,20 @@
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
 	else
 		printk(KERN_ALERT "Unable to handle kernel paging request");
-	printk(" at virtual address %08lx\n",address);
+	printk(" at virtual address %08lx\n", address);
 	printk(KERN_ALERT "pc = %08lx\n", regs->pc);
-	asm volatile("mov.l	%1,%0"
+	asm volatile("mov.l	%1, %0"
 		     : "=r" (page)
 		     : "m" (__m(MMU_TTB)));
-	page = ((unsigned long *) page)[address >> 22];
-	printk(KERN_ALERT "*pde = %08lx\n", page);
-	if (page & _PAGE_PRESENT) {
-		page &= PAGE_MASK;
-		address &= 0x003ff000;
-		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
-		printk(KERN_ALERT "*pte = %08lx\n", page);
+	if (page) {
+		page = ((unsigned long *) page)[address >> 22];
+		printk(KERN_ALERT "*pde = %08lx\n", page);
+		if (page & _PAGE_PRESENT) {
+			page &= PAGE_MASK;
+			address &= 0x003ff000;
+			page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+			printk(KERN_ALERT "*pte = %08lx\n", page);
+		}
 	}
 	die("Oops", regs, writeaccess);
 	do_exit(SIGKILL);
@@ -261,18 +269,24 @@
 	unsigned long pteaddr;
 
 	save_and_cli(flags);
+#if defined(__SH4__)
 	/*
-	 *  We don't need to set PTEH register.
-	 *  It's automatically set by the hardware.
+	 * ITLB is not affected by "ldtlb" instruction.
+	 * So, we need to flush the entry by ourselves.
 	 */
+	__flush_tlb_page(vma->vm_mm, address&PAGE_MASK);
+#endif
+
+	/* Set PTEH register */
+	pteaddr = (address & MMU_VPN_MASK) |
+		(vma->vm_mm->context & MMU_CONTEXT_ASID_MASK);
+	ctrl_outl(pteaddr, MMU_PTEH);
+
+	/* Set PTEL register */
 	pteval = pte_val(pte);
 	pteval &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
 	pteval |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */
-	/* Set PTEL register */
 	ctrl_outl(pteval, MMU_PTEL);
-	/* Set PTEH register */
-	pteaddr = (address & MMU_VPN_MASK) | (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK);
-	ctrl_outl(pteaddr, MMU_PTEH);
 
 	/* Load the TLB */
 	asm volatile("ldtlb": /* no output */ : /* no input */ : "memory");
@@ -306,20 +320,6 @@
 	addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
 	data = page | asid; /* VALID bit is off */
 	ctrl_outl(data, addr);
-#if 0 	/* Not need when using ASSOC. ??? */
-	{
-		int i;
-		for (i=0; i<4; i++) {
-			addr = MMU_ITLB_ADDRESS_ARRAY | (i<<8);
-			data = ctrl_inl(addr);
-			data &= ~0x300;
-			if (data == (page | asid)) {
-				ctrl_outl(data, addr);
-				break;
-			}
-		}
-	}
-#endif
 	back_to_P1();
 #endif
 	if (saved_asid != MMU_NO_ASID)
@@ -383,9 +383,16 @@
 {
 	unsigned long flags, status;
 
+	/*
+	 * Flush all the TLB.
+	 *
+	 * Write to the MMU control register's bit:
+	 * 	TF-bit for SH-3, TI-bit for SH-4.
+	 *      It's same position, bit #2.
+	 */
 	save_and_cli(flags);
 	status = ctrl_inl(MMUCR);
-	status |= 0x04;		/* Set TF-bit to flush */
-	ctrl_outl(status,MMUCR);
+	status |= 0x04;		
+	ctrl_outl(status, MMUCR);
 	restore_flags(flags);
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.3.99-pre8/linux/arch/sparc/config.in	Tue Apr 11 15:09:14 2000
+++ linux/arch/sparc/config.in	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.92 2000/03/29 11:56:48 davem Exp $
+# $Id: config.in,v 1.93 2000/05/22 08:12:19 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -186,6 +186,11 @@
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
       tristate '  Dummy net driver support' CONFIG_DUMMY
       tristate '  Bonding driver support' CONFIG_BONDING
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        if [ "$CONFIG_NETLINK" = "y" ]; then
+          tristate '  Ethertap network tap (EXPERIMENTAL)' CONFIG_ETHERTAP
+        fi
+      fi
       tristate '  PPP (point-to-point) support' CONFIG_PPP
       if [ ! "$CONFIG_PPP" = "n" ]; then
         dep_tristate '  PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v2.3.99-pre8/linux/arch/sparc/kernel/Makefile	Fri May 12 14:18:55 2000
+++ linux/arch/sparc/kernel/Makefile	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.53 2000/03/31 04:06:19 davem Exp $
+# $Id: Makefile,v 1.54 2000/05/12 23:51:24 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -59,13 +59,11 @@
 	@echo "#ifndef CONFIG_SMP" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
 	@echo "#include <linux/config.h>" > tmp.c
-	@echo "#undef __SMP__" >> tmp.c
 	@echo "#undef CONFIG_SMP" >> tmp.c
 	@echo "#include <linux/sched.h>" >> tmp.c
 	$(CPP) $(CPPFLAGS) tmp.c -o tmp.i
 	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
 	@echo "#include <linux/config.h>" >> check_asm.c
-	@echo "#undef __SMP__" >> check_asm.c
 	@echo "#undef CONFIG_SMP" >> check_asm.c
 	@echo "#include <linux/sched.h>" >> check_asm.c
 	@echo 'struct task_struct _task;' >> check_asm.c
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/entry.S linux/arch/sparc/kernel/entry.S
--- v2.3.99-pre8/linux/arch/sparc/kernel/entry.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/entry.S	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.163 1999/11/19 04:11:24 davem Exp $
+/* $Id: entry.S,v 1.164 2000/05/09 17:40:13 davem Exp $
  * arch/sparc/kernel/entry.S:  Sparc trap low-level entry points.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/head.S linux/arch/sparc/kernel/head.S
--- v2.3.99-pre8/linux/arch/sparc/kernel/head.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/head.S	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.102 2000/01/29 01:08:54 anton Exp $
+/* $Id: head.S,v 1.103 2000/05/09 17:40:13 davem Exp $
  * head.S: The initial boot code for the Sparc port of Linux.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/irq.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/irq.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.102 2000/02/25 05:44:35 davem Exp $
+/*  $Id: irq.c,v 1.103 2000/05/09 17:40:13 davem Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/process.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/process.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.146 2000/03/01 02:53:27 davem Exp $
+/*  $Id: process.c,v 1.147 2000/05/09 17:40:13 davem Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/setup.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/setup.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.117 2000/03/27 12:14:54 davem Exp $
+/*  $Id: setup.c,v 1.118 2000/05/09 17:40:13 davem Exp $
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/signal.c linux/arch/sparc/kernel/signal.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/signal.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/signal.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/*  $Id: signal.c,v 1.102 2000/04/08 02:11:36 davem Exp $
+/*  $Id: signal.c,v 1.103 2000/05/09 17:40:13 davem Exp $
  *  linux/arch/sparc/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/sparc_ksyms.c linux/arch/sparc/kernel/sparc_ksyms.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/sparc_ksyms.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/sparc_ksyms.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.96 2000/03/16 09:12:49 jj Exp $
+/* $Id: sparc_ksyms.c,v 1.97 2000/05/09 17:40:13 davem Exp $
  * arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/sun4d_irq.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/sun4d_irq.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/*  $Id: sun4d_irq.c,v 1.24 1999/12/27 06:08:34 anton Exp $
+/*  $Id: sun4d_irq.c,v 1.25 2000/05/09 17:40:13 davem Exp $
  *  arch/sparc/kernel/sun4d_irq.c:
  *			SS1000/SC2000 interrupt handling.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/sys_sunos.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/sys_sunos.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.122 2000/04/27 02:49:03 davem Exp $
+/* $Id: sys_sunos.c,v 1.123 2000/05/22 07:29:39 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -634,7 +634,6 @@
 
 extern dev_t get_unnamed_dev(void);
 extern void put_unnamed_dev(dev_t);
-extern asmlinkage long do_sys_mount(char *, char *, char *, int, void *);
 extern asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
 extern asmlinkage int sys_socket(int family, int type, int protocol);
 extern asmlinkage int sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
@@ -754,7 +753,7 @@
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
 }
 
 asmlinkage int
@@ -814,7 +813,7 @@
 	ret = PTR_ERR(dev_fname);
 	if (IS_ERR(dev_fname))
 		goto out2;
-	ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
+	ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
 	if (dev_fname)
 		putname(dev_fname);
 out2:
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/time.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/time.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.54 2000/04/13 08:14:30 anton Exp $
+/* $Id: time.c,v 1.55 2000/05/09 17:40:13 davem Exp $
  * linux/arch/sparc/kernel/time.c
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
--- v2.3.99-pre8/linux/arch/sparc/kernel/traps.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/kernel/traps.c	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.61 2000/01/21 11:38:41 jj Exp $
+/* $Id: traps.c,v 1.62 2000/05/09 17:40:13 davem Exp $
  * arch/sparc/kernel/traps.c
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/lib/rwsem.S linux/arch/sparc/lib/rwsem.S
--- v2.3.99-pre8/linux/arch/sparc/lib/rwsem.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/lib/rwsem.S	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* $Id: rwsem.S,v 1.4 2000/02/13 07:59:39 anton Exp $
+/* $Id: rwsem.S,v 1.5 2000/05/09 17:40:13 davem Exp $
  * Assembly part of rw semaphores.
  *
  * Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/btfixup.c linux/arch/sparc/mm/btfixup.c
--- v2.3.99-pre8/linux/arch/sparc/mm/btfixup.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/btfixup.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: btfixup.c,v 1.9 1999/12/27 06:30:02 anton Exp $
+/* $Id: btfixup.c,v 1.10 2000/05/09 17:40:13 davem Exp $
  * btfixup.c: Boot time code fixup and relocator, so that
  * we can get rid of most indirect calls to achieve single
  * image sun4c and srmmu kernel.
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/hypersparc.S linux/arch/sparc/mm/hypersparc.S
--- v2.3.99-pre8/linux/arch/sparc/mm/hypersparc.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/hypersparc.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: hypersparc.S,v 1.14 1999/08/14 03:51:47 anton Exp $
+/* $Id: hypersparc.S,v 1.15 2000/05/09 17:40:13 davem Exp $
  * hypersparc.S: High speed Hypersparc mmu/cache operations.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- v2.3.99-pre8/linux/arch/sparc/mm/init.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/init.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.84 2000/03/15 23:26:26 anton Exp $
+/*  $Id: init.c,v 1.85 2000/05/09 17:40:13 davem Exp $
  *  linux/arch/sparc/mm/init.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.3.99-pre8/linux/arch/sparc/mm/srmmu.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/srmmu.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.208 2000/02/14 04:52:33 jj Exp $
+/* $Id: srmmu.c,v 1.209 2000/05/09 17:40:13 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.3.99-pre8/linux/arch/sparc/mm/sun4c.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/sun4c.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: sun4c.c,v 1.191 2000/04/08 02:11:41 davem Exp $
+/* $Id: sun4c.c,v 1.192 2000/05/09 17:40:13 davem Exp $
  * sun4c.c: Doing in software what should be done in hardware.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/swift.S linux/arch/sparc/mm/swift.S
--- v2.3.99-pre8/linux/arch/sparc/mm/swift.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/swift.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: swift.S,v 1.4 2000/02/12 03:08:47 zaitcev Exp $
+/* $Id: swift.S,v 1.5 2000/05/09 17:40:13 davem Exp $
  * swift.S: MicroSparc-II mmu/cache operations.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/tsunami.S linux/arch/sparc/mm/tsunami.S
--- v2.3.99-pre8/linux/arch/sparc/mm/tsunami.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/tsunami.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: tsunami.S,v 1.3 1999/10/09 05:32:19 zaitcev Exp $
+/* $Id: tsunami.S,v 1.4 2000/05/09 17:40:13 davem Exp $
  * tsunami.S: High speed MicroSparc-I mmu/cache operations.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc/mm/viking.S linux/arch/sparc/mm/viking.S
--- v2.3.99-pre8/linux/arch/sparc/mm/viking.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc/mm/viking.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: viking.S,v 1.15 2000/01/15 00:51:36 anton Exp $
+/* $Id: viking.S,v 1.16 2000/05/09 17:40:13 davem Exp $
  * viking.S: High speed Viking cache/mmu operations
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.3.99-pre8/linux/arch/sparc64/config.in	Fri May 12 14:18:55 2000
+++ linux/arch/sparc64/config.in	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.109 2000/05/02 06:35:59 davem Exp $
+# $Id: config.in,v 1.112 2000/05/22 08:12:19 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -204,6 +204,11 @@
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
       tristate '  Dummy net driver support' CONFIG_DUMMY
       tristate '  Bonding driver support' CONFIG_BONDING
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+        if [ "$CONFIG_NETLINK" = "y" ]; then
+          tristate '  Ethertap network tap (EXPERIMENTAL)' CONFIG_ETHERTAP
+        fi
+      fi
       tristate '  PPP (point-to-point) support' CONFIG_PPP
       if [ ! "$CONFIG_PPP" = "n" ]; then
          dep_tristate '  PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.3.99-pre8/linux/arch/sparc64/kernel/Makefile	Fri May 12 14:18:55 2000
+++ linux/arch/sparc64/kernel/Makefile	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.53 2000/03/31 04:06:22 davem Exp $
+# $Id: Makefile,v 1.54 2000/05/12 23:51:24 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S
--- v2.3.99-pre8/linux/arch/sparc64/kernel/head.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/head.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.64 2000/03/06 22:33:42 davem Exp $
+/* $Id: head.S,v 1.65 2000/05/09 17:40:13 davem Exp $
  * head.S: Initial boot code for the Sparc64 port of Linux.
  *
  * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/ioctl32.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/ioctl32.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.89 2000/05/06 10:38:42 davem Exp $
+/* $Id: ioctl32.c,v 1.90 2000/05/22 07:29:39 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -2400,39 +2400,6 @@
 	return err;
 }
 
-typedef struct blkelv_ioctl32_arg_s {
-	u32 queue_ID;
-	int read_latency;
-	int write_latency;
-	int max_bomb_segments;
-} blkelv_ioctl32_arg_t;
-
-static int do_blkelv_ioctl(unsigned int fd, unsigned int cmd, blkelv_ioctl32_arg_t *arg)
-{
-	blkelv_ioctl_arg_t b;
-	int err;
-	mm_segment_t old_fs = get_fs();
-
-	if (cmd == BLKELVSET) {	
-		err = get_user((long)b.queue_ID, &arg->queue_ID);
-		err |= __get_user(b.read_latency, &arg->read_latency);
-		err |= __get_user(b.write_latency, &arg->write_latency);
-		err |= __get_user(b.max_bomb_segments, &arg->max_bomb_segments);
-		if (err) return err;
-	}
-	set_fs (KERNEL_DS);
-	err = sys_ioctl(fd, cmd, (unsigned long)&b);
-	set_fs (old_fs);
-	if (cmd == BLKELVGET && !err) {
-		err = put_user((long)b.queue_ID, &arg->queue_ID);
-		err |= __put_user(b.read_latency, &arg->read_latency);
-		err |= __put_user(b.write_latency, &arg->write_latency);
-		err |= __put_user(b.max_bomb_segments, &arg->max_bomb_segments);
-		if (err) return err;
-	}
-	return err;
-}
-
 static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
@@ -2994,6 +2961,9 @@
 COMPATIBLE_IOCTL(LV_SET_STATUS)
 COMPATIBLE_IOCTL(LV_SET_ALLOCATION)
 #endif /* LVM */
+/* elevator */
+COMPATIBLE_IOCTL(BLKELVGET)
+COMPATIBLE_IOCTL(BLKELVSET)
 /* And these ioctls need translation */
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
@@ -3040,8 +3010,6 @@
 HANDLE_IOCTL(BLKFRAGET, w_long)
 HANDLE_IOCTL(BLKSECTGET, w_long)
 HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
-HANDLE_IOCTL(BLKELVGET, do_blkelv_ioctl)
-HANDLE_IOCTL(BLKELVSET, do_blkelv_ioctl)
 HANDLE_IOCTL(FBIOPUTCMAP32, fbiogetputcmap)
 HANDLE_IOCTL(FBIOGETCMAP32, fbiogetputcmap)
 HANDLE_IOCTL(FBIOSCURSOR32, fbiogscursor)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/irq.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/irq.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.86 2000/04/15 06:02:50 davem Exp $
+/* $Id: irq.c,v 1.87 2000/05/09 17:40:13 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/process.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/process.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.106 2000/04/15 06:02:50 davem Exp $
+/*  $Id: process.c,v 1.107 2000/05/09 17:40:14 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/setup.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/setup.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.53 2000/03/15 14:42:52 jj Exp $
+/*  $Id: setup.c,v 1.54 2000/05/09 17:40:14 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/sparc64_ksyms.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.83 2000/04/19 08:38:25 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.84 2000/05/09 17:40:14 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sparc32.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.146 2000/05/09 04:48:34 davem Exp $
+/* $Id: sys_sparc32.c,v 1.147 2000/05/22 07:29:40 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -1742,9 +1742,6 @@
 	return 0;
 }
 
-extern long do_sys_mount(char * dev_page, char * dir_page, char * type_page,
-			 unsigned long new_flags, char * data_page);
-
 #define SMBFS_NAME	"smbfs"
 #define NCPFS_NAME	"ncpfs"
 
@@ -1784,7 +1781,7 @@
 		goto dev_out;
 
 	if (!is_smb && !is_ncp) {
-		err = do_sys_mount((char*)dev_page, (char*)dir_page,
+		err = do_mount((char*)dev_page, (char*)dir_page,
 				(char*)type_page, new_flags, (char*)data_page);
 	} else {
 		if (is_ncp)
@@ -1792,7 +1789,7 @@
 		else
 			do_smb_super_data_conv((void *)data_page);
 
-		err = do_sys_mount((char*)dev_page, (char*)dir_page,
+		err = do_mount((char*)dev_page, (char*)dir_page,
 				(char*)type_page, new_flags, (char*)data_page);
 	}
 	free_page(dir_page);
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/sys_sunos32.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.46 2000/04/27 02:49:03 davem Exp $
+/* $Id: sys_sunos32.c,v 1.47 2000/05/22 07:29:40 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -598,7 +598,6 @@
 	char       *netname;   /* server's netname */
 };
 
-extern long do_sys_mount(const char *, const char *, char *, int, void *);
 extern dev_t get_unnamed_dev(void);
 extern void put_unnamed_dev(dev_t);
 extern asmlinkage int sys_mount(char *, char *, char *, unsigned long, void *);
@@ -727,7 +726,7 @@
 	linux_nfs_mount.hostname [255] = 0;
 	putname (the_name);
 	
-	return do_sys_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
+	return do_mount ("", dir_name, "nfs", linux_flags, &linux_nfs_mount);
 }
 
 /* XXXXXXXXXXXXXXXXXXXX */
@@ -787,7 +786,7 @@
 	ret = PTR_ERR(dev_fname);
 	if (IS_ERR(dev_fname))
 		goto out2;
-	ret = do_sys_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
+	ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL);
 	if (dev_fname)
 		putname(dev_fname);
 out2:
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/systbls.S linux/arch/sparc64/kernel/systbls.S
--- v2.3.99-pre8/linux/arch/sparc64/kernel/systbls.S	Wed Apr 26 16:34:07 2000
+++ linux/arch/sparc64/kernel/systbls.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.72 2000/04/13 07:30:34 jj Exp $
+/* $Id: systbls.S,v 1.73 2000/05/10 14:23:39 jj Exp $
  * systbls.S: System call entry point tables for OS compatibility.
  *            The native Linux system call table lives here also.
  *
@@ -83,7 +83,7 @@
 /*10*/  .word sys_unlink, sunos_execv, sys_chdir, sys_chown, sys_mknod
 /*15*/	.word sys_chmod, sys_lchown, sparc_brk, sys_perfctr, sys_lseek
 /*20*/	.word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
-/*25*/	.word sys_time, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
+/*25*/	.word sys_nis_syscall, sys_ptrace, sys_alarm, sys_sigaltstack, sys_nis_syscall
 /*30*/	.word sys_utime, sys_nis_syscall, sys_nis_syscall, sys_access, sys_nice
 	.word sys_nis_syscall, sys_sync, sys_kill, sys_newstat, sys_sendfile
 /*40*/	.word sys_newlstat, sys_dup, sys_pipe, sys_times, sys_nis_syscall
@@ -124,7 +124,7 @@
 	.word sys_ipc, sys_nis_syscall, sys_clone, sys_nis_syscall, sys_adjtimex
 /*220*/	.word sys_nis_syscall, sys_create_module, sys_delete_module, sys_get_kernel_syms, sys_getpgid
 	.word sys_bdflush, sys_sysfs, sys_nis_syscall, sys_setfsuid, sys_setfsgid
-/*230*/	.word sys_select, sys_time, sys_nis_syscall, sys_stime, sys_nis_syscall
+/*230*/	.word sys_select, sys_nis_syscall, sys_nis_syscall, sys_stime, sys_nis_syscall
 	.word sys_nis_syscall, sys_llseek, sys_mlock, sys_munlock, sys_mlockall
 /*240*/	.word sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
 	.word sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/time.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/time.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.25 2000/04/13 05:29:44 davem Exp $
+/* $Id: time.c,v 1.26 2000/05/09 17:40:14 davem Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.3.99-pre8/linux/arch/sparc64/kernel/traps.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/traps.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.65 2000/01/21 11:39:01 jj Exp $
+/* $Id: traps.c,v 1.66 2000/05/09 17:40:14 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/kernel/ttable.S linux/arch/sparc64/kernel/ttable.S
--- v2.3.99-pre8/linux/arch/sparc64/kernel/ttable.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/kernel/ttable.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: ttable.S,v 1.30 1999/12/01 23:52:03 davem Exp $
+/* $Id: ttable.S,v 1.31 2000/05/09 17:40:14 davem Exp $
  * ttable.S: Sparc V9 Trap Table(s) with SpitFire extensions.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/lib/debuglocks.c linux/arch/sparc64/lib/debuglocks.c
--- v2.3.99-pre8/linux/arch/sparc64/lib/debuglocks.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/lib/debuglocks.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: debuglocks.c,v 1.4 2000/01/31 04:59:10 davem Exp $
+/* $Id: debuglocks.c,v 1.5 2000/05/09 17:40:14 davem Exp $
  * debuglocks.c: Debugging versions of SMP locking primitives.
  *
  * Copyright (C) 1998 David S. Miller (davem@redhat.com)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.3.99-pre8/linux/arch/sparc64/mm/init.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/mm/init.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.151 2000/04/26 17:09:32 davem Exp $
+/*  $Id: init.c,v 1.152 2000/05/09 17:40:14 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- v2.3.99-pre8/linux/arch/sparc64/mm/ultra.S	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/mm/ultra.S	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.42 2000/05/05 18:47:41 davem Exp $
+/* $Id: ultra.S,v 1.43 2000/05/09 17:40:14 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997, 2000 David S. Miller (davem@redhat.com)
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/prom/misc.c linux/arch/sparc64/prom/misc.c
--- v2.3.99-pre8/linux/arch/sparc64/prom/misc.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/prom/misc.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.17 2000/04/15 06:02:50 davem Exp $
+/* $Id: misc.c,v 1.18 2000/05/09 17:40:14 davem Exp $
  * misc.c:  Miscellaneous prom functions that don't belong
  *          anywhere else.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/arch/sparc64/solaris/misc.c linux/arch/sparc64/solaris/misc.c
--- v2.3.99-pre8/linux/arch/sparc64/solaris/misc.c	Thu May 11 15:30:06 2000
+++ linux/arch/sparc64/solaris/misc.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.26 2000/04/14 09:59:02 davem Exp $
+/* $Id: misc.c,v 1.27 2000/05/09 17:40:14 davem Exp $
  * misc.c: Miscelaneous syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/Makefile linux/drivers/acorn/net/Makefile
--- v2.3.99-pre8/linux/drivers/acorn/net/Makefile	Thu Mar  2 14:36:22 2000
+++ linux/drivers/acorn/net/Makefile	Mon May 15 12:00:34 2000
@@ -3,7 +3,7 @@
 # Makefile for the Acorn ethercard network device drivers
 #
 
-L_TARGET := acorn-net.a
+O_TARGET := acorn-net.o
 MOD_LIST_NAME := ACORN_NET_MODULES
 
 obj-y	:=
@@ -11,11 +11,11 @@
 obj-n	:=
 obj-	:=
 
-obj-$(CONFIG_ARM_ETHER1)	+= ether1.o
-obj-$(CONFIG_ARM_ETHER3)	+= ether3.o
 obj-$(CONFIG_ARM_ETHERH)	+= etherh.o
+obj-$(CONFIG_ARM_ETHER3)	+= ether3.o
+obj-$(CONFIG_ARM_ETHER1)	+= ether1.o
 
-L_OBJS	:= $(obj-y)
+O_OBJS	:= $(obj-y)
 M_OBJS	:= $(obj-m)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c
--- v2.3.99-pre8/linux/drivers/acorn/net/ether1.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/acorn/net/ether1.c	Mon May 15 12:00:34 2000
@@ -29,6 +29,7 @@
  *				TDR time-distance.
  * 1.05	RMK	31/12/1997	Removed calls to dev_tint for 2.1
  * 1.06	RMK	10/02/2000	Updated for 2.3.43
+ * 1.07	RMK	13/05/2000	Updated for 2.3.99-pre8
  */
 
 #include <linux/module.h>
@@ -74,7 +75,7 @@
 static void ether1_timeout(struct net_device *dev);
 
 /* ------------------------------------------------------------------------- */
-static char *version = "ether1 ethernet driver (c) 2000 Russell King v1.06\n";
+static char *version = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
 
 #define BUS_16 16
 #define BUS_8  8
@@ -620,95 +621,6 @@
 	return failures ? 1 : 0;
 }
 
-static int __init
-ether1_probe1(struct net_device *dev)
-{
-	static unsigned int version_printed = 0;
-	struct ether1_priv *priv;
-	int i;
-
-	if (!dev->priv)
-		dev->priv = kmalloc (sizeof (struct ether1_priv), GFP_KERNEL);
-
-	if (!dev->priv)
-	    	return 1;
-
-	priv = (struct ether1_priv *)dev->priv;
-	memset (priv, 0, sizeof (struct ether1_priv));
-
-	if ((priv->bus_type = ether1_reset (dev)) == 0) {
-		kfree (dev->priv);
-		return 1;
-	}
-
-	if (net_debug && version_printed++ == 0)
-		printk (KERN_INFO "%s", version);
-
-	request_region (dev->base_addr, 16, "ether1");
-	request_region (dev->base_addr + 0x800, 4096, "ether1(ram)");
-
-	printk (KERN_INFO "%s: ether1 at %lx, IRQ%d, ether address ",
-		dev->name, dev->base_addr, dev->irq);
-
-	for (i = 0; i < 6; i++)
-		printk (i==0?" %02x":i==5?":%02x\n":":%02x", dev->dev_addr[i]);
-
-	if (ether1_init_2 (dev)) {
-		kfree (dev->priv);
-		return 1;
-	}
-
-	dev->open		= ether1_open;
-	dev->stop		= ether1_close;
-	dev->hard_start_xmit    = ether1_sendpacket;
-	dev->get_stats		= ether1_getstats;
-	dev->set_multicast_list = ether1_setmulticastlist;
-	dev->tx_timeout		= ether1_timeout;
-	dev->watchdog_timeo	= 5 * HZ / 100;
-
-	/* Fill in the fields of the device structure with ethernet values */
-	ether_setup (dev);
-
-	return 0;
-}	
-    
-/* ------------------------------------------------------------------------- */
-
-static void __init
-ether1_addr(struct net_device *dev)
-{
-	int i;
-    
-	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = inb (IDPROM_ADDRESS + i);
-}
-
-int __init
-ether1_probe(struct net_device *dev)
-{
-#ifndef MODULE
-	struct expansion_card *ec;
-
-	if (!dev)
-		return ENODEV;
-
-	ecard_startfind ();
-	if ((ec = ecard_find (0, ether1_cids)) == NULL)
-		return ENODEV;
-
-	dev->base_addr = ecard_address (ec, ECARD_IOC, ECARD_FAST);
-	dev->irq       = ec->irq;
-
-	ecard_claim (ec);
-
-#endif
-	ether1_addr (dev);
-
-	if (ether1_probe1 (dev) == 0)
-		return 0;
-	return ENODEV;
-}
-
 /* ------------------------------------------------------------------------- */
 
 static int
@@ -1087,66 +999,118 @@
 
 /* ------------------------------------------------------------------------- */
 
-#ifdef MODULE
+static void __init ether1_banner(void)
+{
+	static unsigned int version_printed = 0;
 
-static struct ether_dev {
-	struct expansion_card	*ec;
-	char			name[9];
-	struct net_device	dev;
-} ether_devs[MAX_ECARDS];
+	if (net_debug && version_printed++ == 0)
+		printk (KERN_INFO "%s", version);
+}
 
-int
-init_module (void)
+static struct net_device * __init ether1_init_one(struct expansion_card *ec)
 {
-	struct expansion_card *ec;
-	int i, ret = -ENODEV;
+	struct net_device *dev;
+	struct ether1_priv *priv;
+	int i;
 
-	memset(ether_devs, 0, sizeof(ether_devs));
+	ether1_banner();
 
-	ecard_startfind ();
-	ec = ecard_find(0, ether1_cids);
-	i = 0;
-
-	while (ec && i < MAX_ECARDS) {
-		ecard_claim(ec);
-
-		ether_devs[i].ec	    = ec;
-		ether_devs[i].dev.irq	    = ec->irq;
-		ether_devs[i].dev.base_addr = ecard_address(ec, ECARD_IOC, ECARD_FAST);
-		ether_devs[i].dev.init	    = ether1_probe;
-		ether_devs[i].dev.name	    = ether_devs[i].name;
-
-		ret = register_netdev(&ether_devs[i].dev);
-
-		if (ret) {
-			ecard_release(ec);
-			ether_devs[i].ec = NULL;
-			break;
-		}
+	ecard_claim(ec);
+	
+	dev = init_etherdev(NULL, sizeof(struct ether1_priv));
+	if (!dev)
+		goto out;
 
-		i += 1;
-		ec = ecard_find(0, ether1_cids);
+	dev->base_addr	= ecard_address(ec, ECARD_IOC, ECARD_FAST);
+	dev->irq	= ec->irq;
+
+	/*
+	 * these will not fail - the nature of the bus ensures this
+	 */
+	request_region(dev->base_addr, 16, dev->name);
+	request_region(dev->base_addr + 0x800, 4096, dev->name);
+
+	priv = (struct ether1_priv *)dev->priv;
+	if ((priv->bus_type = ether1_reset(dev)) == 0)
+		goto free_dev;
+
+	printk(KERN_INFO "%s: ether1 at %lx, IRQ%d, ether address ",
+		dev->name, dev->base_addr, dev->irq);
+    
+	for (i = 0; i < 6; i++) {
+		dev->dev_addr[i] = inb(IDPROM_ADDRESS + i);
+		printk (i==0?" %02x":i==5?":%02x\n":":%02x", dev->dev_addr[i]);
 	}
 
-	return i != 0 ? 0 : ret;
+	if (ether1_init_2(dev))
+		goto free_dev;
+
+	dev->open		= ether1_open;
+	dev->stop		= ether1_close;
+	dev->hard_start_xmit    = ether1_sendpacket;
+	dev->get_stats		= ether1_getstats;
+	dev->set_multicast_list = ether1_setmulticastlist;
+	dev->tx_timeout		= ether1_timeout;
+	dev->watchdog_timeo	= 5 * HZ / 100;
+	return 0;
+
+free_dev:
+	release_region(dev->base_addr, 16);
+	release_region(dev->base_addr + 0x800, 4096);
+	unregister_netdev(dev);
+	kfree(dev);
+out:
+	ecard_release(ec);
+	return dev;
 }
 
-void
-cleanup_module (void)
+static struct expansion_card	*e_card[MAX_ECARDS];
+static struct net_device	*e_dev[MAX_ECARDS];
+
+static int __init ether1_init(void)
 {
-	int i;
+	int i, ret = -ENODEV;
+
+	ecard_startfind();
 
 	for (i = 0; i < MAX_ECARDS; i++) {
-		if (ether_devs[i].ec) {
-			unregister_netdev(&ether_devs[i].dev);
+		struct expansion_card *ec;
+		struct net_device *dev;
+
+		ec = ecard_find(0, ether1_cids);
+		if (!ec)
+			break;
 
-			release_region(ether_devs[i].dev.base_addr, 16);
-			release_region(ether_devs[i].dev.base_addr + 0x800, 4096);
+		dev = ether1_init_one(ec);
+		if (!dev)
+			break;
 
-			ecard_release(ether_devs[i].ec);
+		e_card[i] = ec;
+		e_dev[i]  = dev;
+		ret = 0;
+	}
+
+	return ret;
+}
 
-			ether_devs[i].ec = NULL;
+static void __exit ether1_exit(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_ECARDS; i++) {
+		if (e_dev[i]) {
+			unregister_netdev(e_dev[i]);
+			release_region(e_dev[i]->base_addr, 16);
+			release_region(e_dev[i]->base_addr + 0x800, 4096);
+			kfree(e_dev[i]);
+			e_dev[i] = NULL;
+		}
+		if (e_card[i]) {
+			ecard_release(e_card[i]);
+			e_card[i] = NULL;
 		}
 	}
 }
-#endif /* MODULE */
+
+module_init(ether1_init);
+module_exit(ether1_exit);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c
--- v2.3.99-pre8/linux/drivers/acorn/net/ether3.c	Sun Feb 20 21:12:38 2000
+++ linux/drivers/acorn/net/ether3.c	Mon May 15 12:00:34 2000
@@ -37,9 +37,10 @@
  * 1.15	RMK	30/04/1999	More fixes to the transmit routine for buggy
  *				hardware.
  * 1.16	RMK	10/02/2000	Updated for 2.3.43
+ * 1.17	RMK	13/05/2000	Updated for 2.3.99-pre8
  */
 
-static char *version = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.16\n";
+static char *version = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -78,7 +79,6 @@
 static void	ether3_setmulticastlist(struct net_device *dev);
 static int	ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt);
 static void	ether3_tx(struct net_device *dev, struct dev_priv *priv);
-static int	ether3_probe1 (struct net_device *dev);
 static int	ether3_open (struct net_device *dev);
 static int	ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
 static void	ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs);
@@ -407,132 +407,6 @@
 }
 
 /*
- * This is the real probe routine.
- */
-static int __init
-ether3_probe1(struct net_device *dev)
-{
-	static unsigned version_printed = 0;
-	struct dev_priv *priv;
-	unsigned int i, bus_type, error = ENODEV;
-	const char *name = "ether3";
-
-	if (net_debug && version_printed++ == 0)
-		printk(version);
-
-	if (!dev->priv) {
-		dev->priv = kmalloc(sizeof (struct dev_priv), GFP_KERNEL);
-		if (!dev->priv) {
-			printk(KERN_ERR "ether3_probe1: no memory\n");
-			return -ENOMEM;
-		}
-	}
-
-	priv = (struct dev_priv *) dev->priv;
-	memset(priv, 0, sizeof(struct dev_priv));
-
-	request_region(dev->base_addr, 128, name);
-
-	/* Reset card...
-	 */
-	ether3_outb(0x80, REG_CONFIG2 + 1);
-	bus_type = BUS_UNKNOWN;
-	udelay(4);
-
-	/* Test using Receive Pointer (16-bit register) to find out
-	 * how the ether3 is connected to the bus...
-	 */
-	if (ether3_probe_bus_8(dev, 0x100) &&
-	    ether3_probe_bus_8(dev, 0x201))
-		bus_type = BUS_8;
-
-	if (bus_type == BUS_UNKNOWN &&
-	    ether3_probe_bus_16(dev, 0x101) &&
-	    ether3_probe_bus_16(dev, 0x201))
-		bus_type = BUS_16;
-
-	switch (bus_type) {
-	case BUS_UNKNOWN:
-		printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
-		goto failed;
-
-	case BUS_8:
-		printk(KERN_ERR "%s: %s found, but is an unsupported "
-			"8-bit card\n", dev->name, name);
-		goto failed;
-
-	default:
-		break;
-	}
-
-	printk("%s: %s at %lx, IRQ%d, ether address ",
-		dev->name, name, dev->base_addr, dev->irq);
-	for (i = 0; i < 6; i++)
-		printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]);
-
-	if (ether3_init_2(dev))
-		goto failed;
-
-	dev->open		= ether3_open;
-	dev->stop		= ether3_close;
-	dev->hard_start_xmit	= ether3_sendpacket;
-	dev->get_stats		= ether3_getstats;
-	dev->set_multicast_list	= ether3_setmulticastlist;
-	dev->tx_timeout		= ether3_timeout;
-	dev->watchdog_timeo	= 5 * HZ / 100;
-
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(dev);
-
-	return 0;
-
-failed:
-	kfree(dev->priv);
-	dev->priv = NULL;
-	release_region(dev->base_addr, 128);
-	return error;
-}
-
-static void __init
-ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
-{
-	ecard_claim(ec);
-
-	dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
-	dev->irq = ec->irq;
-
-	if (ec->cid.manufacturer == MANU_ANT &&
-	    ec->cid.product == PROD_ANT_ETHERB) {
-		dev->base_addr += 0x200;
-	}
-
-	ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
-	ec->irqmask = 0xf0;
-
-	ether3_addr(dev->dev_addr, ec);
-}
-
-#ifndef MODULE
-int __init
-ether3_probe(struct net_device *dev)
-{
-	struct expansion_card *ec;
-
-	if (!dev)
-		return ENODEV;
-
-	ecard_startfind();
-
-	if ((ec = ecard_find(0, ether3_cids)) == NULL)
-		return ENODEV;
-
-	ether3_get_dev(dev, ec);
-
-	return ether3_probe1(dev);
-}
-#endif
-
-/*
  * Open/initialize the board.  This is called (in the current kernel)
  * sometime after booting when the 'ifconfig' program is run.
  *
@@ -903,63 +777,163 @@
 	}
 }
 
-#ifdef MODULE
+static void __init ether3_banner(void)
+{
+	static unsigned version_printed = 0;
 
-static struct ether_dev {
-	struct expansion_card	*ec;
-	char			name[9];
-	struct net_device	dev;
-} ether_devs[MAX_ECARDS];
+	if (net_debug && version_printed++ == 0)
+		printk(version);
+}
 
-int
-init_module(void)
+static const char * __init
+ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
 {
-	struct expansion_card *ec;
-	int i, ret = -ENODEV;
+	const char *name = "ether3";
+	dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
+	dev->irq = ec->irq;
+
+	if (ec->cid.manufacturer == MANU_ANT &&
+	    ec->cid.product == PROD_ANT_ETHERB) {
+		dev->base_addr += 0x200;
+		name = "etherb";
+	}
 
-	memset(ether_devs, 0, sizeof(ether_devs));
+	ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
+	ec->irqmask = 0xf0;
 
-	ecard_startfind ();
-	ec = ecard_find(0, ether3_cids);
-	i = 0;
+	ether3_addr(dev->dev_addr, ec);
 
-	while (ec && i < MAX_ECARDS) {
-		ecard_claim(ec);
+	return name;
+}
 
-		ether_devs[i].ec	    = ec;
-		ether_devs[i].dev.init	    = ether3_probe1;
-		ether_devs[i].dev.name	    = ether_devs[i].name;
-		ether3_get_dev(&ether_devs[i].dev, ec);
+static struct net_device * __init ether3_init_one(struct expansion_card *ec)
+{
+	struct net_device *dev;
+	struct dev_priv *priv;
+	const char *name;
+	int i, bus_type;
 
-		ret = register_netdev(&ether_devs[i].dev);
+	ether3_banner();
 
-		if (ret) {
-			ecard_release(ec);
-			ether_devs[i].ec = NULL;
-		} else
-			i += 1;
+	ecard_claim(ec);
 
-		ec = ecard_find(0, ether3_cids);
+	dev = init_etherdev(NULL, sizeof(struct dev_priv));
+	if (!dev)
+		goto out;
+
+	name = ether3_get_dev(dev, ec);
+
+	/*
+	 * this will not fail - the nature of the bus ensures this
+	 */
+	request_region(dev->base_addr, 128, dev->name);
+
+	priv = (struct dev_priv *) dev->priv;
+
+	/* Reset card...
+	 */
+	ether3_outb(0x80, REG_CONFIG2 + 1);
+	bus_type = BUS_UNKNOWN;
+	udelay(4);
+
+	/* Test using Receive Pointer (16-bit register) to find out
+	 * how the ether3 is connected to the bus...
+	 */
+	if (ether3_probe_bus_8(dev, 0x100) &&
+	    ether3_probe_bus_8(dev, 0x201))
+		bus_type = BUS_8;
+
+	if (bus_type == BUS_UNKNOWN &&
+	    ether3_probe_bus_16(dev, 0x101) &&
+	    ether3_probe_bus_16(dev, 0x201))
+		bus_type = BUS_16;
+
+	switch (bus_type) {
+	case BUS_UNKNOWN:
+		printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
+		goto failed;
+
+	case BUS_8:
+		printk(KERN_ERR "%s: %s found, but is an unsupported "
+			"8-bit card\n", dev->name, name);
+		goto failed;
+
+	default:
+		break;
 	}
 
-	return i != 0 ? 0 : ret;
+	printk("%s: %s at %lx, IRQ%d, ether address ",
+		dev->name, name, dev->base_addr, dev->irq);
+	for (i = 0; i < 6; i++)
+		printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]);
+
+	if (ether3_init_2(dev))
+		goto failed;
+
+	dev->open		= ether3_open;
+	dev->stop		= ether3_close;
+	dev->hard_start_xmit	= ether3_sendpacket;
+	dev->get_stats		= ether3_getstats;
+	dev->set_multicast_list	= ether3_setmulticastlist;
+	dev->tx_timeout		= ether3_timeout;
+	dev->watchdog_timeo	= 5 * HZ / 100;
+	return 0;
+
+failed:
+	release_region(dev->base_addr, 128);
+	unregister_netdev(dev);
+	kfree(dev);
+out:
+	ecard_release(ec);
+	return NULL;
 }
 
-void
-cleanup_module(void)
+static struct expansion_card	*e_card[MAX_ECARDS];
+static struct net_device	*e_dev[MAX_ECARDS];
+
+static int ether3_init(void)
 {
-	int i;
+	int i, ret = -ENODEV;
+
+	ecard_startfind();
 
 	for (i = 0; i < MAX_ECARDS; i++) {
-		if (ether_devs[i].ec) {
-			unregister_netdev(&ether_devs[i].dev);
+		struct net_device *dev;
+		struct expansion_card *ec;
 
-			release_region(ether_devs[i].dev.base_addr, 128);
+		ec = ecard_find(0, ether3_cids);
+		if (!ec)
+			break;
 
-			ecard_release(ether_devs[i].ec);
+		dev = ether3_init_one(ec);
+		if (!dev)
+			break;
+
+		e_card[i] = ec;
+		e_dev[i]  = dev;
+		ret = 0;
+	}
+
+	return ret;
+}
 
-			ether_devs[i].ec = NULL;
+static void ether3_exit(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_ECARDS; i++) {
+		if (e_dev[i]) {
+			unregister_netdev(e_dev[i]);
+			release_region(e_dev[i]->base_addr, 128);
+			kfree(e_dev[i]);
+			e_dev[i] = NULL;
+		}
+		if (e_card[i]) {
+			ecard_release(e_card[i]);
+			e_card[i] = NULL;
 		}
 	}
 }
-#endif /* MODULE */
+
+module_init(ether3_init);
+module_exit(ether3_exit);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c
--- v2.3.99-pre8/linux/drivers/acorn/net/etherh.c	Sun Feb 20 21:12:38 2000
+++ linux/drivers/acorn/net/etherh.c	Mon May 15 12:00:34 2000
@@ -14,6 +14,7 @@
  *  23-11-1997	RMK	1.04	Added media autodetection
  *  16-04-1998	RMK	1.05	Improved media autodetection
  *  10-02-2000	RMK	1.06	Updated for 2.3.43
+ *  13-05-2000	RMK	1.07	Updated for 2.3.99-pre8
  *
  * Insmod Module Parameters
  * ------------------------
@@ -62,7 +63,8 @@
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("i3 EtherH driver");
 
-static char *version = "etherh [500/600/600A] ethernet driver (c) 2000 R.M.King v1.06\n";
+static char *version __initdata =
+	"etherh [500/600/600A] ethernet driver (c) 2000 R.M.King v1.07\n";
 
 #define ETHERH500_DATAPORT	0x200	/* MEMC */
 #define ETHERH500_NS8390	0x000	/* MEMC */
@@ -81,34 +83,10 @@
 
 /* --------------------------------------------------------------------------- */
 
-/*
- * Read the ethernet address string from the on board rom.
- * This is an ascii string...
- */
-static int __init
-etherh_addr(char *addr, struct expansion_card *ec)
-{
-	struct in_chunk_dir cd;
-	char *s;
-	
-	if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) {
-		int i;
-		for (i = 0; i < 6; i++) {
-			addr[i] = simple_strtoul(s + 1, &s, 0x10);
-			if (*s != (i == 5? ')' : ':'))
-				break;
-		}
-		if (i == 6)
-			return 0;
-	}
-	return ENODEV;
-}
-
 static void
 etherh_setif(struct net_device *dev)
 {
-	unsigned long addr;
-	unsigned long flags;
+	unsigned long addr, flags;
 
 	save_flags_cli(flags);
 
@@ -118,19 +96,27 @@
 	case PROD_I3_ETHERLAN600A:
 		addr = dev->base_addr + EN0_RCNTHI;
 
-		if (ei_status.interface_num)	/* 10b2 */
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
 			outb((inb(addr) & 0xf8) | 1, addr);
-		else				/* 10bT */
+			break;
+		case IF_PORT_10BASET:
 			outb((inb(addr) & 0xf8), addr);
+			break;
+		}
 		break;
 
 	case PROD_I3_ETHERLAN500:
 		addr = dev->rmem_start;
 
-		if (ei_status.interface_num)	/* 10b2 */
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
 			outb(inb(addr) & ~ETHERH_CP_IF, addr);
-		else				/* 10bT */
+			break;
+		case IF_PORT_10BASET:
 			outb(inb(addr) | ETHERH_CP_IF, addr);
+			break;
+		}
 		break;
 
 	default:
@@ -143,22 +129,30 @@
 static int
 etherh_getifstat(struct net_device *dev)
 {
-	int stat;
+	int stat = 0;
 
 	switch (dev->mem_end) {
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600A:
-		if (ei_status.interface_num)	/* 10b2 */
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
 			stat = 1;
-		else				/* 10bT */
+			break;
+		case IF_PORT_10BASET:
 			stat = inb(dev->base_addr+EN0_RCNTHI) & 4;
+			break;
+		}
 		break;
 
 	case PROD_I3_ETHERLAN500:
-		if (ei_status.interface_num)	/* 10b2 */
+		switch (dev->if_port) {
+		case IF_PORT_10BASE2:
 			stat = 1;
-		else				/* 10bT */
+			break;
+		case IF_PORT_10BASET:
 			stat = inb(dev->rmem_start) & ETHERH_CP_HEARTBEAT;
+			break;
+		}
 		break;
 
 	default:
@@ -170,14 +164,54 @@
 }
 
 /*
- * Reset the 8390 (hard reset)
+ * Configure the interface.  Note that we ignore the other
+ * parts of ifmap, since its mostly meaningless for this driver.
+ */
+static int etherh_set_config(struct net_device *dev, struct ifmap *map)
+{
+	switch (map->port) {
+	case IF_PORT_10BASE2:
+	case IF_PORT_10BASET:
+		/*
+		 * If the user explicitly sets the interface
+		 * media type, turn off automedia detection.
+		 */
+		dev->flags &= ~IFF_AUTOMEDIA;
+		dev->if_port = map->port;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	etherh_setif(dev);
+
+	return 0;
+}
+
+/*
+ * Reset the 8390 (hard reset).  Note that we can't actually do this.
  */
 static void
 etherh_reset(struct net_device *dev)
 {
 	outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, dev->base_addr);
 
-	etherh_setif(dev);
+	/*
+	 * See if we need to change the interface type.
+	 * Note that we use 'interface_num' as a flag
+	 * to indicate that we need to change the media.
+	 */
+	if (dev->flags & IFF_AUTOMEDIA && ei_status.interface_num) {
+		ei_status.interface_num = 0;
+
+		if (dev->if_port == IF_PORT_10BASET)
+			dev->if_port = IF_PORT_10BASE2;
+		else
+			dev->if_port = IF_PORT_10BASET;
+
+		etherh_setif(dev);
+	}
 }
 
 /*
@@ -332,8 +366,31 @@
 		return -EAGAIN;
 	}
 
+	/*
+	 * Make sure that we aren't going to change the
+	 * media type on the next reset - we are about to
+	 * do automedia manually now.
+	 */
+	ei_status.interface_num = 0;
+
+	/*
+	 * If we are doing automedia detection, do it now.
+	 * This is more reliable than the 8390's detection.
+	 */
+	if (dev->flags & IFF_AUTOMEDIA) {
+		dev->if_port = IF_PORT_10BASET;
+		etherh_setif(dev);
+		mdelay(1);
+		if (!etherh_getifstat(dev)) {
+			dev->if_port = IF_PORT_10BASE2;
+			etherh_setif(dev);
+		}
+	} else
+		etherh_setif(dev);
+
 	etherh_reset(dev);
 	ei_open(dev);
+
 	return 0;
 }
 
@@ -350,281 +407,266 @@
 	return 0;
 }
 
+static void etherh_irq_enable(ecard_t *ec, int irqnr)
+{
+	unsigned int ctrl_addr = (unsigned int)ec->irq_data;
+	outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr);
+}
+
+static void etherh_irq_disable(ecard_t *ec, int irqnr)
+{
+	unsigned int ctrl_addr = (unsigned int)ec->irq_data;
+	outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr);
+}
+
+static expansioncard_ops_t etherh_ops = {
+	etherh_irq_enable,
+	etherh_irq_disable,
+	NULL,
+	NULL,
+	NULL,
+	NULL
+};
+
 /*
- * This is the real probe routine.
+ * Initialisation
  */
-static int __init
-etherh_probe1(struct net_device *dev)
+
+static void __init etherh_banner(void)
 {
 	static int version_printed;
-	unsigned int addr, i, reg0, tmp;
-	const char *dev_type;
-	const char *if_type;
-	const char *name = "etherh";
-
-	addr = dev->base_addr;
 
 	if (net_debug && version_printed++ == 0)
 		printk(version);
+}
 
-	switch (dev->mem_end) {
-	case PROD_I3_ETHERLAN500:
-		dev_type = "500";
-		break;
-	case PROD_I3_ETHERLAN600:
-		dev_type = "600";
-		break;
-	case PROD_I3_ETHERLAN600A:
-		dev_type = "600A";
-		break;
-	default:
-		dev_type = "";
-	}
+static int __init etherh_check_presence(struct net_device *dev)
+{
+	unsigned int addr = dev->base_addr, reg0, tmp;
 
-	reg0 = inb (addr);
+	reg0 = inb(addr);
 	if (reg0 == 0xff) {
 		if (net_debug & DEBUG_INIT)
-			printk("%s: %s error: NS8390 command register wrong\n",
-				dev->name, name);
+			printk("%s: etherh error: NS8390 command register wrong\n",
+				dev->name);
 		return -ENODEV;
 	}
 
- 	outb (E8390_NODMA | E8390_PAGE1 | E8390_STOP, addr + E8390_CMD);
-	tmp = inb (addr + 13);
-	outb (0xff, addr + 13);
-	outb (E8390_NODMA | E8390_PAGE0, addr + E8390_CMD);
-	inb (addr + EN0_COUNTER0);
-	if (inb (addr + EN0_COUNTER0) != 0) {
+ 	outb(E8390_NODMA | E8390_PAGE1 | E8390_STOP, addr + E8390_CMD);
+	tmp = inb(addr + 13);
+	outb(0xff, addr + 13);
+	outb(E8390_NODMA | E8390_PAGE0, addr + E8390_CMD);
+	inb(addr + EN0_COUNTER0);
+	if (inb(addr + EN0_COUNTER0) != 0) {
 		if (net_debug & DEBUG_INIT)
-			printk("%s: %s error: NS8390 not found\n",
-				dev->name, name);
-		outb (reg0, addr);
-		outb (tmp, addr + 13);
+			printk("%s: etherh error: NS8390 not found\n",
+				dev->name);
+		outb(reg0, addr);
+		outb(tmp, addr + 13);
 		return -ENODEV;
 	}
 
-	if (ethdev_init(dev))
-		return -ENOMEM;
-
-	request_region(addr, 16, name);
-
-	printk("%s: %s %s at %lx, IRQ%d, ether address ",
-		dev->name, name, dev_type, dev->base_addr, dev->irq);
-
-	for (i = 0; i < 6; i++)
-		printk (i == 5 ? "%2.2x " : "%2.2x:", dev->dev_addr[i]);
-
-	ei_status.name		= name;
-	ei_status.word16	= 1;
-	ei_status.tx_start_page	= ETHERH_TX_START_PAGE;
-	ei_status.rx_start_page	= ei_status.tx_start_page + TX_PAGES;
-	ei_status.stop_page	= ETHERH_STOP_PAGE;
-	ei_status.reset_8390	= etherh_reset;
-	ei_status.block_input	= etherh_block_input;
-	ei_status.block_output	= etherh_block_output;
-	ei_status.get_8390_hdr	= etherh_get_header;
-	dev->open		= etherh_open;
-	dev->stop		= etherh_close;
-
-	/* select 10bT */
-	ei_status.interface_num = 0;
-	if_type = "10BaseT";
-	etherh_setif(dev);
-	mdelay(1);
-	if (!etherh_getifstat(dev)) {
-		if_type = "10Base2";
-		ei_status.interface_num = 1;
-		etherh_setif(dev);
-	}
-	if (!etherh_getifstat(dev))
-		if_type = "UNKNOWN";
-
-	printk("%s\n", if_type);
-
-	etherh_reset(dev);
-	NS8390_init (dev, 0);
 	return 0;
 }
 
-static void etherh_irq_enable(ecard_t *ec, int irqnr)
+/*
+ * Read the ethernet address string from the on board rom.
+ * This is an ascii string...
+ */
+static int __init etherh_addr(char *addr, struct expansion_card *ec)
 {
-	unsigned int ctrl_addr = (unsigned int)ec->irq_data;
-	outb(inb(ctrl_addr) | ETHERH_CP_IE, ctrl_addr);
+	struct in_chunk_dir cd;
+	char *s;
+	
+	if (ecard_readchunk(&cd, ec, 0xf5, 0) && (s = strchr(cd.d.string, '('))) {
+		int i;
+		for (i = 0; i < 6; i++) {
+			addr[i] = simple_strtoul(s + 1, &s, 0x10);
+			if (*s != (i == 5? ')' : ':'))
+				break;
+		}
+		if (i == 6)
+			return 0;
+	}
+	return ENODEV;
 }
 
-static void etherh_irq_disable(ecard_t *ec, int irqnr)
+static struct net_device * __init etherh_init_one(struct expansion_card *ec)
 {
-	unsigned int ctrl_addr = (unsigned int)ec->irq_data;
-	outb(inb(ctrl_addr) & ~ETHERH_CP_IE, ctrl_addr);
-}
+	struct net_device *dev;
+	const char *dev_type;
+	int i;
 
-static expansioncard_ops_t etherh_ops = {
-	etherh_irq_enable,
-	etherh_irq_disable,
-	NULL,
-	NULL,
-	NULL,
-	NULL
-};
+	etherh_banner();
 
-static void __init
-etherh_initdev(ecard_t *ec, struct net_device *dev)
-{
-	ecard_claim (ec);
+	ecard_claim(ec);
 	
-	dev->irq = ec->irq;
-	dev->mem_end = ec->cid.product;
+	dev = init_etherdev(NULL, 0);
+	if (!dev)
+		goto out;
+
+	etherh_addr(dev->dev_addr, ec);
+
+	dev->open	= etherh_open;
+	dev->stop	= etherh_close;
+	dev->set_config	= etherh_set_config;
+	dev->irq	= ec->irq;
+	dev->base_addr	= ecard_address(ec, ECARD_MEMC, 0);
+	dev->mem_end	= ec->cid.product;
+	ec->ops		= &etherh_ops;
 
 	switch (ec->cid.product) {
 	case PROD_I3_ETHERLAN500:
-		dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH500_NS8390;
-		dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
+		dev->base_addr += ETHERH500_NS8390;
+		dev->mem_start  = dev->base_addr + ETHERH500_DATAPORT;
 		dev->rmem_start = (unsigned long)
-		ec->irq_data   = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST)
+		ec->irq_data    = (void *)ecard_address (ec, ECARD_IOC, ECARD_FAST)
 				  + ETHERH500_CTRLPORT;
 		break;
 
 	case PROD_I3_ETHERLAN600:
 	case PROD_I3_ETHERLAN600A:
-		dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH600_NS8390;
+		dev->base_addr += ETHERH600_NS8390;
 		dev->mem_start = dev->base_addr + ETHERH600_DATAPORT;
-		ec->irq_data = (void *)(dev->base_addr + ETHERH600_CTRLPORT);
+		ec->irq_data   = (void *)(dev->base_addr + ETHERH600_CTRLPORT);
 		break;
 
 	default:
-		printk ("%s: etherh error: unknown card type\n", dev->name);
+		printk("%s: etherh error: unknown card type %x\n",
+		       dev->name, ec->cid.product);
+		goto out;
 	}
-	ec->ops = &etherh_ops;
 
-	etherh_addr(dev->dev_addr, ec);
-}
+	if (!request_region(dev->base_addr, 16, dev->name))
+		goto region_not_free;
 
-#ifndef MODULE
-int __init
-etherh_probe(struct net_device *dev)
-{
-	if (!dev)
-		return ENODEV;
+	if (etherh_check_presence(dev) || ethdev_init(dev))
+		goto release;
 
-	if (!dev->base_addr || dev->base_addr == 0xffe0) {
-		struct expansion_card *ec;
+	switch (ec->cid.product) {
+	case PROD_I3_ETHERLAN500:
+		dev_type = "500";
+		break;
 
-		ecard_startfind();
+	case PROD_I3_ETHERLAN600:
+		dev_type = "600";
+		break;
 
-		if ((ec = ecard_find (0, etherh_cids)) == NULL)
-			return ENODEV;
+	case PROD_I3_ETHERLAN600A:
+		dev_type = "600A";
+		break;
 
-		etherh_initdev(ec, dev);
+	default:
+		dev_type = "unknown";
+		break;
 	}
-	return etherh_probe1(dev);
-}
-#endif
 
-#ifdef MODULE
-#define MAX_ETHERH_CARDS 2
+	printk("%s: etherh %s at %lx, IRQ%d, ether address ",
+		dev->name, dev_type, dev->base_addr, dev->irq);
 
-static int io[MAX_ETHERH_CARDS];
-static int irq[MAX_ETHERH_CARDS];
-static char ethernames[MAX_ETHERH_CARDS][9];
-static struct net_device *my_ethers[MAX_ETHERH_CARDS];
-static struct expansion_card *ec[MAX_ETHERH_CARDS];
+	for (i = 0; i < 6; i++)
+		printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]);
 
-static int
-init_all_cards(void)
-{
-	struct net_device *dev = NULL;
-	int i, found = 0;
+	/*
+	 * Unfortunately, ethdev_init eventually calls
+	 * ether_setup, which re-writes dev->flags.
+	 */
+	switch (ec->cid.product) {
+	case PROD_I3_ETHERLAN500:
+		dev->if_port   = IF_PORT_UNKNOWN;
+		break;
 
-	for (i = 0; i < MAX_ETHERH_CARDS; i++) {
-		my_ethers[i] = NULL;
-		ec[i] = NULL;
-		strcpy (ethernames[i], "        ");
+	case PROD_I3_ETHERLAN600:
+	case PROD_I3_ETHERLAN600A:
+		dev->flags    |= IFF_PORTSEL | IFF_AUTOMEDIA;
+		dev->if_port   = IF_PORT_10BASET;
+		break;
 	}
 
-	ecard_startfind();
-
-	for (i = 0; i < MAX_ETHERH_CARDS; i++) {
-		if (!dev)
-			dev = (struct net_device *)kmalloc (sizeof (struct net_device), GFP_KERNEL);
-		if (dev)
-			memset (dev, 0, sizeof (struct net_device));
-
-		if (!io[i]) {
-			if ((ec[i] = ecard_find (0, etherh_cids)) == NULL)
-				continue;
-
-			if (!dev)
-				return -ENOMEM;
-
-			etherh_initdev (ec[i], dev);
-		} else {
-			ec[i] = NULL;
-			if (!dev)
-				return -ENOMEM;
-			dev->base_addr = io[i];
-			dev->irq = irq[i];
-		}
+	ei_status.name		= dev->name;
+	ei_status.word16	= 1;
+	ei_status.tx_start_page	= ETHERH_TX_START_PAGE;
+	ei_status.rx_start_page	= ei_status.tx_start_page + TX_PAGES;
+	ei_status.stop_page	= ETHERH_STOP_PAGE;
 
-		dev->init = etherh_probe1;
-		dev->name = ethernames[i];
+	ei_status.reset_8390	= etherh_reset;
+	ei_status.block_input	= etherh_block_input;
+	ei_status.block_output	= etherh_block_output;
+	ei_status.get_8390_hdr	= etherh_get_header;
+	ei_status.interface_num = 0;
 
-		my_ethers[i] = dev;
+	etherh_reset(dev);
+	NS8390_init(dev, 0);
+	return dev;
 
-		if (register_netdev(dev) != 0) {
-			printk(KERN_ERR "No etherh card found at %08lX\n",
-				dev->base_addr);
-			if (ec[i]) {
-				ecard_release(ec[i]);
-				ec[i] = NULL;
-			}
-			continue;
-		}
-		found ++;
-		dev = NULL;
-	}
+release:
+	release_region(dev->base_addr, 16);
+region_not_free:
+	unregister_netdev(dev);
+	kfree(dev);
+out:
+	ecard_release(ec);
+	return NULL;
+}
 
-	if (dev)
-		kfree (dev);
+#define MAX_ETHERH_CARDS 2
 
-	return found ? 0 : -ENODEV;
-}
+static struct net_device *e_dev[MAX_ETHERH_CARDS];
+static struct expansion_card *e_card[MAX_ETHERH_CARDS];
 
-int
-init_module(void)
+static int __init etherh_init(void)
 {
-	int ret;
+	int i, ret = -ENODEV;
 
-	if (load_8390_module(__FILE__))
+	if (load_8390_module("etherh.c"))
 		return -ENOSYS;
 
 	lock_8390_module();
 
-	ret = init_all_cards();
+	ecard_startfind();
 
-	if (ret) {
-		unlock_8390_module();
+	for (i = 0; i < MAX_ECARDS; i++) {
+		struct expansion_card *ec;
+		struct net_device *dev;
+
+		ec = ecard_find(0, etherh_cids);
+		if (!ec)
+			break;
+
+		dev = etherh_init_one(ec);
+		if (!dev)
+			break;
+
+		e_card[i] = ec;
+		e_dev[i]  = dev;
+		ret = 0;
 	}
 
+	if (ret)
+		unlock_8390_module();
+
 	return ret;
 }
 
-void
-cleanup_module(void)
+static void __exit etherh_exit(void)
 {
 	int i;
+
 	for (i = 0; i < MAX_ETHERH_CARDS; i++) {
-		if (my_ethers[i]) {
-			unregister_netdev(my_ethers[i]);
-			release_region (my_ethers[i]->base_addr, 16);
-			kfree (my_ethers[i]);
-			my_ethers[i] = NULL;
+		if (e_dev[i]) {
+			unregister_netdev(e_dev[i]);
+			release_region(e_dev[i]->base_addr, 16);
+			kfree(e_dev[i]);
+			e_dev[i] = NULL;
 		}
-		if (ec[i]) {
-			ec[i]->ops = NULL;
-			ecard_release(ec[i]);
-			ec[i] = NULL;
+		if (e_card[i]) {
+			e_card[i]->ops = NULL;
+			ecard_release(e_card[i]);
+			e_card[i] = NULL;
 		}
 	}
 	unlock_8390_module();
 }
-#endif /* MODULE */
+
+module_init(etherh_init);
+module_exit(etherh_exit);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/atm/eni.c linux/drivers/atm/eni.c
--- v2.3.99-pre8/linux/drivers/atm/eni.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/atm/eni.c	Sat May 13 08:19:21 2000
@@ -2283,7 +2283,7 @@
 	  0, 0, 0 /* FPGA */ },
 	{ PCI_VENDOR_ID_EF, PCI_DEVICE_ID_EF_ATM_ASIC, PCI_ANY_ID, PCI_ANY_ID,
 	  0, 0, 1 /* ASIC */ },
-	{ 0 }
+	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci,eni_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.3.99-pre8/linux/drivers/block/Config.in	Fri May 12 14:18:55 2000
+++ linux/drivers/block/Config.in	Mon May 15 10:57:20 2000
@@ -49,10 +49,12 @@
 bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD
 dep_tristate '  Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD
 dep_tristate '  RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD
-bool         '   DANGEROUS! RAID1/RAID5 code' CONFIG_RAID15_DANGEROUS
-if [ "$CONFIG_RAID15_DANGEROUS" = "y" ]; then
- dep_tristate '    RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD
- dep_tristate '    RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  bool '    RAID-1/RAID-5 code (DANGEROUS)' CONFIG_RAID15_DANGEROUS
+  if [ "$CONFIG_RAID15_DANGEROUS" = "y" ]; then
+    dep_tristate '      RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD
+    dep_tristate '      RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD
+  fi
 fi
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 dep_bool '  Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.3.99-pre8/linux/drivers/block/DAC960.c	Thu May 11 15:30:06 2000
+++ linux/drivers/block/DAC960.c	Sat May 13 07:35:38 2000
@@ -19,8 +19,9 @@
 */
 
 
-#define DAC960_DriverVersion			"2.3.4"
-#define DAC960_DriverDate			"23 September 1999"
+#define DAC960_DriverVersion                  "2.3.5"
+#define DAC960_DriverDate                     "23 January 2000"
+
 
 
 #include <linux/version.h>
@@ -110,7 +111,7 @@
   DAC960_Announce("***** DAC960 RAID Driver Version "
 		  DAC960_DriverVersion " of "
 		  DAC960_DriverDate " *****\n", Controller);
-  DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff "
+  DAC960_Announce("Copyright 1998-2000 by Leonard N. Zubkoff "
 		  "<lnz@dandelion.com>\n", Controller);
 }
 
@@ -184,6 +185,23 @@
 
 
 /*
+  DAC960_WaitForCommand waits for a wake_up on Controller's Command Wait Queue.
+*/
+
+static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
+{
+  DECLARE_WAITQUEUE(WaitQueueEntry, current);
+  add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
+  current->state = TASK_UNINTERRUPTIBLE;
+  spin_unlock(&io_request_lock);
+  schedule();
+  current->state = TASK_RUNNING;
+  remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
+  spin_lock_irq(&io_request_lock);
+}
+
+
+/*
   DAC960_QueueCommand queues Command.
 */
 
@@ -307,6 +325,62 @@
 
 
 /*
+  DAC960_ReportErrorStatus reports Controller BIOS Messages passed through
+  the Error Status Register when the driver performs the BIOS handshaking.
+  It returns true for fatal errors and false otherwise.
+*/
+
+static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
+					unsigned char ErrorStatus,
+					unsigned char Parameter0,
+					unsigned char Parameter1)
+{
+  switch (ErrorStatus)
+    {
+    case 0x00:
+      DAC960_Notice("Physical Drive %d:%d Not Responding\n",
+		    Controller, Parameter1, Parameter0);
+      break;
+    case 0x08:
+      if (Controller->DriveSpinUpMessageDisplayed) break;
+      DAC960_Notice("Spinning Up Drives\n", Controller);
+      Controller->DriveSpinUpMessageDisplayed = true;
+      break;
+    case 0x30:
+      DAC960_Notice("Configuration Checksum Error\n", Controller);
+      break;
+    case 0x60:
+      DAC960_Notice("Mirror Race Recovery Failed\n", Controller);
+      break;
+    case 0x70:
+      DAC960_Notice("Mirror Race Recovery In Progress\n", Controller);
+      break;
+    case 0x90:
+      DAC960_Notice("Physical Drive %d:%d COD Mismatch\n",
+		    Controller, Parameter1, Parameter0);
+      break;
+    case 0xA0:
+      DAC960_Notice("Logical Drive Installation Aborted\n", Controller);
+      break;
+    case 0xB0:
+      DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller);
+      break;
+    case 0xD0:
+      DAC960_Notice("New Controller Configuration Found\n", Controller);
+      break;
+    case 0xF0:
+      DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller);
+      return true;
+    default:
+      DAC960_Error("Unknown Initialization Error %02X for Controller at\n",
+		   Controller, ErrorStatus);
+      return true;
+    }
+  return false;
+}
+
+
+/*
   DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface.
 */
 
@@ -372,7 +446,7 @@
       case DAC960_V5_Controller:
 	while (--TimeoutCounter >= 0)
 	  {
-	    if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress))
+	    if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress))
 	      break;
 	    udelay(10);
 	  }
@@ -469,6 +543,9 @@
       unsigned long BaseAddress1 = pci_resource_start (PCI_Device, 1);
       unsigned short SubsystemVendorID, SubsystemDeviceID;
       int CommandIdentifier;
+      unsigned char ErrorStatus, Parameter0, Parameter1;
+      void *BaseAddress;
+
 
       if (pci_enable_device(PCI_Device))
 	  goto Ignore;
@@ -517,24 +594,6 @@
       Controller->Function = Function;
       sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
       /*
-	Acquire shared access to the IRQ Channel.
-      */
-      if (IRQ_Channel == 0)
-	{
-	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      strcpy(Controller->FullModelName, "DAC960");
-      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
-		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
-	{
-	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      Controller->IRQ_Channel = IRQ_Channel;
-      /*
 	Map the Controller Register Window.
       */
       if (MemoryWindowSize < PAGE_SIZE)
@@ -549,34 +608,87 @@
 		       "Controller at\n", Controller);
 	  goto Failure;
 	}
+      BaseAddress = Controller->BaseAddress;
       switch (ControllerType)
 	{
 	case DAC960_V5_Controller:
-	  DAC960_V5_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_V5_DisableInterrupts(BaseAddress);
+	  DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V5_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
 	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
 	    {
 	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_V5_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V5_EnableInterrupts(BaseAddress);
 	  break;
 	case DAC960_V4_Controller:
-	  DAC960_V4_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_V4_DisableInterrupts(BaseAddress);
+	  DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V4_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
 	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
 	    {
 	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_V4_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V4_EnableInterrupts(BaseAddress);
 	  break;
 	case DAC960_V3_Controller:
 	  request_region(Controller->IO_Address, 0x80,
 			 Controller->FullModelName);
-	  DAC960_V3_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V3_DisableInterrupts(BaseAddress);
+	  DAC960_V3_AcknowledgeStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V3_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
+	  DAC960_V3_EnableInterrupts(BaseAddress);
 	  break;
 	}
+      /*
+	Acquire shared access to the IRQ Channel.
+      */
+      if (IRQ_Channel == 0)
+	{
+	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      strcpy(Controller->FullModelName, "DAC960");
+      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
+		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
+	{
+	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      Controller->IRQ_Channel = IRQ_Channel;
       DAC960_ActiveControllerCount++;
       for (CommandIdentifier = 0;
 	   CommandIdentifier < DAC960_MaxChannels;
@@ -597,11 +709,11 @@
 			"0x%X PCI Address 0x%X\n", Controller,
 			Bus, Device, Function, IO_Address, PCI_Address);
       if (Controller == NULL) break;
-      if (Controller->IRQ_Channel > 0)
-	free_irq(IRQ_Channel, Controller);
       if (Controller->MemoryMappedAddress != NULL)
 	iounmap(Controller->MemoryMappedAddress);
       DAC960_Controllers[Controller->ControllerNumber] = NULL;
+      if (Controller->IRQ_Channel > 0)
+	free_irq(IRQ_Channel, Controller);
     Ignore:
       kfree(Controller);
     }
@@ -1346,9 +1458,7 @@
       Command = DAC960_AllocateCommand(Controller);
       if (Command != NULL) break;
       if (!WaitForCommand) return false;
-      spin_unlock(&io_request_lock);
-      sleep_on(&Controller->CommandWaitQueue);
-      spin_lock_irq(&io_request_lock);
+      DAC960_WaitForCommand(Controller);
     }
   DAC960_ClearCommand(Command);
   if (Request->cmd == READ)
@@ -1900,6 +2010,20 @@
 	      }
 	  else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
 	    Controller->NeedConsistencyCheckProgress = true;
+	  if (CommandType != DAC960_MonitoringCommand &&
+	      Controller->RebuildFlagPending)
+	    {
+	      DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *)
+		Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress);
+	      Enquiry->RebuildFlag = Controller->PendingRebuildFlag;
+	      Controller->RebuildFlagPending = false;
+	    }
+	  else if (CommandType == DAC960_MonitoringCommand &&
+		   NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress)
+	    {
+	      Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag;
+	      Controller->RebuildFlagPending = true;
+	    }
 	}
       else if (CommandOpcode == DAC960_PerformEventLogOperation)
 	{
@@ -2083,6 +2207,9 @@
 	    Controller->RebuildProgress.LogicalDriveSize;
 	  unsigned int BlocksCompleted =
 	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+	  if (CommandStatus == DAC960_NoRebuildOrCheckInProgress &&
+	      Controller->LastRebuildStatus == DAC960_NormalCompletion)
+	    CommandStatus = DAC960_RebuildSuccessful;
 	  switch (CommandStatus)
 	    {
 	    case DAC960_NormalCompletion:
@@ -2110,13 +2237,28 @@
 			      "Failure of Drive Being Rebuilt\n", Controller);
 	      break;
 	    case DAC960_NoRebuildOrCheckInProgress:
-	      if (Controller->LastRebuildStatus != DAC960_NormalCompletion)
-		break;
+	      break;
 	    case DAC960_RebuildSuccessful:
 	      DAC960_Progress("Rebuild Completed Successfully\n", Controller);
 	      break;
+	    case DAC960_RebuildSuccessfullyTerminated:
+	      DAC960_Progress("Rebuild Successfully Terminated\n", Controller);
+	      break;
 	    }
 	  Controller->LastRebuildStatus = CommandStatus;
+	  if (CommandType != DAC960_MonitoringCommand &&
+	      Controller->RebuildStatusPending)
+	    {
+	      Command->CommandStatus = Controller->PendingRebuildStatus;
+	      Controller->RebuildStatusPending = false;
+	    }
+	  else if (CommandType == DAC960_MonitoringCommand &&
+		   CommandStatus != DAC960_NormalCompletion &&
+		   CommandStatus != DAC960_NoRebuildOrCheckInProgress)
+	    {
+	      Controller->PendingRebuildStatus = CommandStatus;
+	      Controller->RebuildStatusPending = true;
+	    }
 	}
       else if (CommandOpcode == DAC960_RebuildStat)
 	{
@@ -2331,7 +2473,7 @@
   if (CommandType == DAC960_QueuedCommand)
     {
       DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand;
-      KernelCommand->CommandStatus = CommandStatus;
+      KernelCommand->CommandStatus = Command->CommandStatus;
       Command->KernelCommand = NULL;
       if (CommandOpcode == DAC960_DCDB)
 	Controller->DirectCommandActive[KernelCommand->DCDB->Channel]
@@ -2352,9 +2494,12 @@
       return;
     }
   /*
-    Deallocate the Command, and wake up any processes waiting on a free Command.
+    Deallocate the Command.
   */
   DAC960_DeallocateCommand(Command);
+  /*
+    Wake up any processes waiting on a free Command.
+  */
   wake_up(&Controller->CommandWaitQueue);
 }
 
@@ -2761,19 +2906,14 @@
 	  }
 	if (CommandOpcode == DAC960_DCDB)
 	  {
-	    while (true)
-	      {
-		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-		if (!Controller->DirectCommandActive[DCDB.Channel]
-						    [DCDB.TargetID])
-		  Command = DAC960_AllocateCommand(Controller);
-		if (Command != NULL)
-		  Controller->DirectCommandActive[DCDB.Channel]
-						 [DCDB.TargetID] = true;
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		if (Command != NULL) break;
-		sleep_on(&Controller->CommandWaitQueue);
-	      }
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    while (Controller->DirectCommandActive[DCDB.Channel]
+						  [DCDB.TargetID] ||
+		   (Command = DAC960_AllocateCommand(Controller)) == NULL)
+	      DAC960_WaitForCommand(Controller);
+	    Controller->DirectCommandActive[DCDB.Channel]
+					   [DCDB.TargetID] = true;
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	    DAC960_ClearCommand(Command);
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
@@ -2783,14 +2923,10 @@
 	  }
 	else
 	  {
-	    while (true)
-	      {
-		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-		Command = DAC960_AllocateCommand(Controller);
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		if (Command != NULL) break;
-		sleep_on(&Controller->CommandWaitQueue);
-	      }
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+	      DAC960_WaitForCommand(Controller);
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	    DAC960_ClearCommand(Command);
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
@@ -3194,14 +3330,10 @@
   DAC960_CommandMailbox_T *CommandMailbox;
   ProcessorFlags_T ProcessorFlags;
   unsigned char Channel, TargetID, LogicalDriveNumber;
-  while (true)
-    {
-      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-      Command = DAC960_AllocateCommand(Controller);
-      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-      if (Command != NULL) break;
-      sleep_on(&Controller->CommandWaitQueue);
-    }
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+    DAC960_WaitForCommand(Controller);
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
   Controller->UserStatusLength = 0;
   DAC960_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/DAC960.h linux/drivers/block/DAC960.h
--- v2.3.99-pre8/linux/drivers/block/DAC960.h	Tue Dec 14 01:27:23 1999
+++ linux/drivers/block/DAC960.h	Sat May 20 10:55:25 2000
@@ -55,17 +55,17 @@
 
 
 /*
-  Define a 32 bit I/O Address data type.
+  Define a 32/64 bit I/O Address data type.
 */
 
-typedef unsigned int DAC960_IO_Address_T;
+typedef unsigned long DAC960_IO_Address_T;
 
 
 /*
-  Define a 32 bit PCI Bus Address data type.
+  Define a 32/64 bit PCI Bus Address data type.
 */
 
-typedef unsigned int DAC960_PCI_Address_T;
+typedef unsigned long DAC960_PCI_Address_T;
 
 
 /*
@@ -196,6 +196,7 @@
 #define DAC960_RebuildFailed_BadBlocksOnOther	0x0003	/* Consistency */
 #define DAC960_RebuildFailed_NewDriveFailed	0x0004	/* Consistency */
 #define DAC960_RebuildSuccessful		0x0100	/* Consistency */
+#define DAC960_RebuildSuccessfullyTerminated	0x0107	/* Consistency */
 #define DAC960_AddCapacityInProgress		0x0004	/* Consistency */
 #define DAC960_AddCapacityFailedOrSuspended	0x00F4	/* Consistency */
 #define DAC960_Config2ChecksumError		0x0002	/* Configuration */
@@ -513,7 +514,7 @@
   unsigned char SynchronousMultiplier;			/* Byte 4 */
   unsigned char SynchronousOffset:5;			/* Byte 5 Bits 0-4 */
   unsigned char :3;					/* Byte 5 Bits 5-7 */
-  unsigned long DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
+  unsigned int DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
 }
 DAC960_DeviceState_T;
 
@@ -1110,7 +1111,6 @@
 
 typedef struct buffer_head BufferHeader_T;
 typedef struct file File_T;
-typedef struct file_operations FileOperations_T;
 typedef struct gendisk GenericDiskInfo_T;
 typedef struct hd_geometry DiskGeometry_T;
 typedef struct hd_struct DiskPartition_T;
@@ -1212,6 +1212,7 @@
   unsigned char LogicalDriveCount;
   unsigned char GeometryTranslationHeads;
   unsigned char GeometryTranslationSectors;
+  unsigned char PendingRebuildFlag;
   unsigned short ControllerQueueDepth;
   unsigned short DriverQueueDepth;
   unsigned short MaxBlocksPerCommand;
@@ -1247,6 +1248,9 @@
   boolean NeedRebuildProgress;
   boolean NeedConsistencyCheckProgress;
   boolean EphemeralProgressMessage;
+  boolean RebuildFlagPending;
+  boolean RebuildStatusPending;
+  boolean DriveSpinUpMessageDisplayed;
   Timer_T MonitoringTimer;
   GenericDiskInfo_T GenericDiskInfo;
   DAC960_Command_T *FreeCommands;
@@ -1265,6 +1269,7 @@
   DAC960_EventLogEntry_T EventLogEntry;
   DAC960_RebuildProgress_T RebuildProgress;
   DAC960_CommandStatus_T LastRebuildStatus;
+  DAC960_CommandStatus_T PendingRebuildStatus;
   DAC960_LogicalDriveInformation_T
     LogicalDriveInformation[2][DAC960_MaxLogicalDrives];
   DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives];
@@ -1389,7 +1394,8 @@
   DAC960_V5_MailboxRegister11Offset =		0x5B,
   DAC960_V5_MailboxRegister12Offset =		0x5C,
   DAC960_V5_StatusCommandIdentifierRegOffset =	0x5D,
-  DAC960_V5_StatusRegisterOffset =		0x5E
+  DAC960_V5_StatusRegisterOffset =		0x5E,
+  DAC960_V5_ErrorStatusRegisterOffset =		0x63
 }
 DAC960_V5_RegisterOffsets_T;
 
@@ -1411,7 +1417,8 @@
   } Write;
   struct {
     boolean HardwareMailboxEmpty:1;			/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
+    boolean InitializationNotInProgress:1;		/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
 DAC960_V5_InboundDoorBellRegister_T;
@@ -1455,6 +1462,22 @@
 
 
 /*
+  Define the structure of the DAC960 V5 Error Status Register.
+*/
+
+typedef union DAC960_V5_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V5_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V5 Controller Interface Registers.
 */
@@ -1510,12 +1533,21 @@
 }
 
 static inline
-boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress)
+boolean DAC960_V5_HardwareMailboxFullP(void *ControllerBaseAddress)
 {
   DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
     readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-  return InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+  return !InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+}
+
+static inline
+boolean DAC960_V5_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+  return !InboundDoorBellRegister.Read.InitializationNotInProgress;
 }
 
 static inline
@@ -1571,7 +1603,7 @@
 void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress)
 {
   DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.All = 0xFF;
   InterruptMaskRegister.Bits.DisableInterrupts = false;
   writeb(InterruptMaskRegister.All,
 	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
@@ -1581,7 +1613,7 @@
 void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress)
 {
   DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.All = 0xFF;
   InterruptMaskRegister.Bits.DisableInterrupts = true;
   writeb(InterruptMaskRegister.All,
 	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
@@ -1603,7 +1635,9 @@
   NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
   NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
   NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  wmb();
   NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+  mb();
 }
 
 static inline
@@ -1633,6 +1667,26 @@
   return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset);
 }
 
+static inline boolean
+DAC960_V5_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V5_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V5_CommandIdentifierRegisterOffset);
+  writeb(0xFF, ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset);
+  return true;
+}
+
 static inline
 void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
 {
@@ -1691,7 +1745,8 @@
   DAC960_V4_MailboxRegister11Offset =		0x100B,
   DAC960_V4_MailboxRegister12Offset =		0x100C,
   DAC960_V4_StatusCommandIdentifierRegOffset =	0x1018,
-  DAC960_V4_StatusRegisterOffset =		0x101A
+  DAC960_V4_StatusRegisterOffset =		0x101A,
+  DAC960_V4_ErrorStatusRegisterOffset =		0x103F
 }
 DAC960_V4_RegisterOffsets_T;
 
@@ -1713,7 +1768,8 @@
   } Write;
   struct {
     boolean HardwareMailboxFull:1;			/* Bit 0 */
-    unsigned int :31;					/* Bits 1-31 */
+    boolean InitializationInProgress:1;			/* Bit 1 */
+    unsigned int :30;					/* Bits 2-31 */
   } Read;
 }
 DAC960_V4_InboundDoorBellRegister_T;
@@ -1758,6 +1814,22 @@
 
 
 /*
+  Define the structure of the DAC960 V4 Error Status Register.
+*/
+
+typedef union DAC960_V4_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V4_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V4 Controller Interface Registers.
 */
@@ -1822,6 +1894,15 @@
 }
 
 static inline
+boolean DAC960_V4_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.InitializationInProgress;
+}
+
+static inline
 void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 {
   DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
@@ -1910,7 +1991,9 @@
   NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
   NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
   NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  wmb();
   NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+  mb();
 }
 
 static inline
@@ -1940,11 +2023,31 @@
   return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset);
 }
 
+static inline boolean
+DAC960_V4_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V4_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V4_CommandIdentifierRegisterOffset);
+  writeb(0, ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset);
+  return true;
+}
+
 static inline
 void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0xAABBFFFF,
+  writel(0x743C485E,
 	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
   writel((unsigned long) Controller->FirstCommandMailbox,
 	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
@@ -1962,7 +2065,7 @@
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
   if (readl(ControllerBaseAddress
-	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF)
+	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0x743C485E)
     return;
   *MemoryMailboxAddress =
     (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
@@ -1996,6 +2099,7 @@
   DAC960_V3_MailboxRegister12Offset =		0x0C,
   DAC960_V3_StatusCommandIdentifierRegOffset =	0x0D,
   DAC960_V3_StatusRegisterOffset =		0x0E,
+  DAC960_V3_ErrorStatusRegisterOffset =		0x3F,
   DAC960_V3_InboundDoorBellRegisterOffset =	0x40,
   DAC960_V3_OutboundDoorBellRegisterOffset =	0x41,
   DAC960_V3_InterruptEnableRegisterOffset =	0x43
@@ -2019,7 +2123,8 @@
   } Write;
   struct {
     boolean MailboxFull:1;				/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
+    boolean InitializationInProgress:1;			/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
 DAC960_V3_InboundDoorBellRegister_T;
@@ -2060,6 +2165,22 @@
 
 
 /*
+  Define the structure of the DAC960 V3 Error Status Register.
+*/
+
+typedef union DAC960_V3_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V3_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V3 Controller Interface Registers.
 */
@@ -2114,6 +2235,15 @@
 }
 
 static inline
+boolean DAC960_V3_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.InitializationInProgress;
+}
+
+static inline
 void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress)
 {
   DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
@@ -2186,6 +2316,26 @@
 DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset);
+}
+
+static inline boolean
+DAC960_V3_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V3_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V3_CommandIdentifierRegisterOffset);
+  writeb(0, ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset);
+  return true;
 }
 
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/elevator.c linux/drivers/block/elevator.c
--- v2.3.99-pre8/linux/drivers/block/elevator.c	Tue Mar 14 19:10:39 2000
+++ linux/drivers/block/elevator.c	Sat May 20 11:36:59 2000
@@ -105,7 +105,7 @@
 	int ret;
 	blkelv_ioctl_arg_t output;
 
-	output.queue_ID			= elevator;
+	output.queue_ID			= elevator->queue_ID;
 	output.read_latency		= elevator->read_latency;
 	output.write_latency		= elevator->write_latency;
 	output.max_bomb_segments	= elevator->max_bomb_segments;
@@ -146,5 +146,8 @@
 
 void elevator_init(elevator_t * elevator)
 {
+	static unsigned int queue_ID;
+
 	*elevator = ELEVATOR_DEFAULTS;
+	elevator->queue_ID = queue_ID++;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.3.99-pre8/linux/drivers/block/floppy.c	Thu May 11 15:30:06 2000
+++ linux/drivers/block/floppy.c	Mon May 22 09:50:55 2000
@@ -1,5 +1,5 @@
 /*
- *  linux/kernel/floppy.c
+ *  linux/drivers/block/floppy.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 1993, 1994  Alain Knaff
@@ -96,6 +96,12 @@
  * 1995/10/18 -- Ralf Baechle -- Portability cleanup; move machine dependent
  * features to asm/floppy.h.
  */
+
+/*
+ * 1998/05/07 -- Russell King -- More portability cleanups; moved definition of
+ * interrupt and dma channel to asm/floppy.h. Cleaned up some formatting &
+ * use of '0' for NULL.
+ */
  
 /*
  * 1998/06/07 -- Alan Cox -- Merged the 2.0.34 fixes for resource allocation
@@ -123,19 +129,6 @@
 /* do print messages for unexpected interrupts */
 static int print_unex=1;
 #include <linux/module.h>
-
-/* the following is the mask of allowed drives. By default units 2 and
- * 3 of both floppy controllers are disabled, because switching on the
- * motor of these drives causes system hangs on some PCI computers. drive
- * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
- * a drive is allowed. */
- 
-static int FLOPPY_IRQ=6;
-static int FLOPPY_DMA=2;
-static int allowed_drive_mask = 0x33;
-static int irqdma_allocated = 0;
- 
-
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
@@ -177,6 +170,8 @@
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
+static int FLOPPY_IRQ=6;
+static int FLOPPY_DMA=2;
 static int can_use_virtual_dma=2;
 /* =======
  * can use virtual DMA:
@@ -186,7 +181,7 @@
  * but fall back on virtual DMA when not enough memory available
  */
 
-static int use_virtual_dma=0;
+static int use_virtual_dma;
 /* =======
  * use virtual DMA
  * 0 using hard DMA
@@ -205,8 +200,22 @@
 static devfs_handle_t devfs_handle = NULL;
 
 #define K_64	0x10000		/* 64KB */
+
+/* the following is the mask of allowed drives. By default units 2 and
+ * 3 of both floppy controllers are disabled, because switching on the
+ * motor of these drives causes system hangs on some PCI computers. drive
+ * 0 is the low bit (0x1), and drive 7 is the high bit (0x80). Bits are on if
+ * a drive is allowed.
+ *
+ * NOTE: This must come before we include the arch floppy header because
+ *       some ports reference this variable from there. -DaveM
+ */
+
+static int allowed_drive_mask = 0x33;
+
 #include <asm/floppy.h>
 
+static int irqdma_allocated = 0;
 
 #define MAJOR_NR FLOPPY_MAJOR
 
@@ -231,9 +240,9 @@
 static inline void fallback_on_nodma_alloc(char **addr, size_t l)
 {
 #ifdef FLOPPY_CAN_FALLBACK_ON_NODMA
-	if(*addr)
+	if (*addr)
 		return; /* we have the memory */
-	if(can_use_virtual_dma != 2)
+	if (can_use_virtual_dma != 2)
 		return; /* no fallback allowed */
 	printk("DMA memory shortage. Temporarily falling back on virtual DMA\n");
 	*addr = (char *) nodma_mem_alloc(l);
@@ -393,6 +402,16 @@
  * 'options'.  Other parameters should be self-explanatory (see also
  * setfdprm(8)).
  */
+/*
+	    Size
+	     |  Sectors per track
+	     |  | Head
+	     |  | |  Tracks
+	     |  | |  | Stretch
+	     |  | |  | |  Gap 1 size
+	     |  | |  | |    |  Data rate, | 0x40 for perp
+	     |  | |  | |    |    |  Spec1 (stepping rate, head unload
+	     |  | |  | |    |    |    |    /fmt gap (gap2) */
 static struct floppy_struct floppy_type[32] = {
 	{    0, 0,0, 0,0,0x00,0x00,0x00,0x00,NULL    },	/*  0 no testing    */
 	{  720, 9,2,40,0,0x2A,0x02,0xDF,0x50,"d360"  }, /*  1 360KB PC      */
@@ -403,7 +422,7 @@
 	{ 1440, 9,2,80,0,0x23,0x01,0xDF,0x50,"h720"  },	/*  6 720KB AT      */
 	{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,"H1440" },	/*  7 1.44MB 3.5"   */
 	{ 5760,36,2,80,0,0x1B,0x43,0xAF,0x54,"E2880" },	/*  8 2.88MB 3.5"   */
-	{ 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120"},	/*  9 3.12MB 3.5"   */
+	{ 6240,39,2,80,0,0x1B,0x43,0xAF,0x28,"E3120" },	/*  9 3.12MB 3.5"   */
 
 	{ 2880,18,2,80,0,0x25,0x00,0xDF,0x02,"h1440" }, /* 10 1.44MB 5.25"  */
 	{ 3360,21,2,80,0,0x1C,0x00,0xCF,0x0C,"H1680" }, /* 11 1.68MB 3.5"   */
@@ -491,8 +510,8 @@
  * not contain a 64k byte boundary crossing, or data will be
  * corrupted/lost.
  */
-static char *floppy_track_buffer=0;
-static int max_buffer_sectors=0;
+static char *floppy_track_buffer;
+static int max_buffer_sectors;
 
 static int *errors;
 typedef void (*done_f)(int);
@@ -503,7 +522,7 @@
 	void (*error)(void); /* this is called to tally an error */
 	done_f done; /* this is called to say if the operation has 
 		      * succeeded/failed */
-} *cont=NULL;
+} *cont;
 
 static void floppy_ready(void);
 static void floppy_start(void);
@@ -551,14 +570,13 @@
 static unsigned char current_drive = 0;
 static long current_count_sectors = 0;
 static unsigned char sector_t; /* sector in track */
-static unsigned char in_sector_offset; /* offset within physical sector,
-										* expressed in units of 512 bytes */
+static unsigned char in_sector_offset;	/* offset within physical sector,
+					 * expressed in units of 512 bytes */
 
 #ifndef fd_eject
 #define fd_eject(x) -EINVAL
 #endif
 
-
 #ifdef DEBUGT
 static long unsigned debugtimer;
 #endif
@@ -602,10 +620,10 @@
 #define OLOGSIZE 20
 
 static void (*lasthandler)(void) = NULL;
-static unsigned long interruptjiffies=0;
-static unsigned long resultjiffies=0;
-static int resultsize=0;
-static unsigned long lastredo=0;
+static unsigned long interruptjiffies;
+static unsigned long resultjiffies;
+static int resultsize;
+static unsigned long lastredo;
 
 static struct output_log {
 	unsigned char data;
@@ -613,7 +631,7 @@
 	unsigned long jiffies;
 } output_log[OLOGSIZE];
 
-static int output_log_pos=0;
+static int output_log_pos;
 #endif
 
 #define CURRENTD -1
@@ -640,7 +658,7 @@
 
 static int maximum(int a, int b)
 {
-	if(a > b)
+	if (a > b)
 		return a;
 	else
 		return b;
@@ -649,7 +667,7 @@
 
 static int minimum(int a, int b)
 {
-	if(a < b)
+	if (a < b)
 		return a;
 	else
 		return b;
@@ -697,11 +715,11 @@
 	if (jiffies - UDRS->select_date < UDP->select_delay)
 		DPRINT("WARNING disk change called early\n");
 	if (!(FDCS->dor & (0x10 << UNIT(drive))) ||
-	   (FDCS->dor & 3) != UNIT(drive) ||
-	   fdc != FDC(drive)){
+	    (FDCS->dor & 3) != UNIT(drive) ||
+	    fdc != FDC(drive)){
 		DPRINT("probing disk change on unselected drive\n");
 		DPRINT("drive=%d fdc=%d dor=%x\n",drive, FDC(drive),
-			FDCS->dor);
+			(unsigned int)FDCS->dor);
 	}
 #endif
 
@@ -791,7 +809,7 @@
 {
 	if (DP->select_delay)
 		return;
-	fd_outb(FDCS->dor & ~(0x10<<UNIT(current_drive)),FD_DOR);
+	fd_outb(FDCS->dor & ~(0x10<<UNIT(current_drive)), FD_DOR);
 	fd_outb(FDCS->dor, FD_DOR);
 	DRS->select_date = jiffies;
 }
@@ -1034,7 +1052,7 @@
 }
 
 static spinlock_t floppy_hlt_lock = SPIN_LOCK_UNLOCKED;
-static int hlt_disabled=0;
+static int hlt_disabled;
 static void floppy_disable_hlt(void)
 {
 	unsigned long flags;
@@ -1090,7 +1108,7 @@
 	f=claim_dma_lock();
 	fd_disable_dma();
 #ifdef fd_dma_setup
-	if(fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, 
+	if (fd_dma_setup(raw_cmd->kernel_data, raw_cmd->length, 
 			(raw_cmd->flags & FD_RAW_READ)?
 			DMA_MODE_READ : DMA_MODE_WRITE,
 			FDCS->address) < 0) {
@@ -1120,7 +1138,7 @@
 static int wait_til_ready(void)
 {
 	int counter, status;
-	if(FDCS->reset)
+	if (FDCS->reset)
 		return -1;
 	for (counter = 0; counter < 10000; counter++) {
 		status = fd_inb(FD_STATUS);		
@@ -1184,7 +1202,7 @@
 		else
 			break;
 	}
-	if(!initialising) {
+	if (!initialising) {
 		DPRINT("get result error. Fdc=%d Last status=%x Read bytes=%d\n",
 		       fdc, status, i);
 		show_floppy();
@@ -1198,7 +1216,7 @@
 static int need_more_output(void)
 {
 	int status;
-	if( (status = wait_til_ready()) < 0)
+	if ((status = wait_til_ready()) < 0)
 		return -1;
 	if ((status & (STATUS_READY|STATUS_DIR|STATUS_DMA)) == STATUS_READY)
 		return MORE_OUTPUT;
@@ -1249,7 +1267,7 @@
 {
 	/* Turn on FIFO */
 	output_byte(FD_CONFIGURE);
-	if(need_more_output() != MORE_OUTPUT)
+	if (need_more_output() != MORE_OUTPUT)
 		return 0;
 	output_byte(0);
 	output_byte(0x10 | (no_fifo & 0x20) | (fifo_depth & 0xf));
@@ -1304,7 +1322,7 @@
 				/* chose the default rate table, not the one
 				 * where 1 = 2 Mbps */
 				output_byte(FD_DRIVESPEC);
-				if(need_more_output() == MORE_OUTPUT) {
+				if (need_more_output() == MORE_OUTPUT) {
 					output_byte(UNIT(current_drive));
 					output_byte(0xc0);
 				}
@@ -1745,14 +1763,14 @@
 	do_print = !handler && print_unex && !initialising;
 
 	inr = result();
-	if(do_print)
+	if (do_print)
 		print_result("unexpected interrupt", inr);
 	if (inr == 0){
 		int max_sensei = 4;
 		do {
 			output_byte(FD_SENSEI);
 			inr = result();
-			if(do_print)
+			if (do_print)
 				print_result("sensei", inr);
 			max_sensei--;
 		} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2 && max_sensei);
@@ -2325,31 +2343,31 @@
 	nr_sectors = 0;
 	CODE2SIZE;
 
-	if(ST1 & ST1_EOC)
+	if (ST1 & ST1_EOC)
 		eoc = 1;
 	else
 		eoc = 0;
 
-	if(COMMAND & 0x80)
+	if (COMMAND & 0x80)
 		heads = 2;
 	else
 		heads = 1;
 
-	nr_sectors = (((R_TRACK-TRACK) * heads + 
+	nr_sectors = (((R_TRACK-TRACK) * heads +
 				   R_HEAD-HEAD) * SECT_PER_TRACK +
-				  R_SECTOR-SECTOR + eoc) << SIZECODE >> 2;
+				   R_SECTOR-SECTOR + eoc) << SIZECODE >> 2;
 
 #ifdef FLOPPY_SANITY_CHECK
 	if (nr_sectors / ssize > 
-		(in_sector_offset + current_count_sectors + ssize - 1)/ssize) {
+		(in_sector_offset + current_count_sectors + ssize - 1) / ssize) {
 		DPRINT("long rw: %x instead of %lx\n",
 			nr_sectors, current_count_sectors);
 		printk("rs=%d s=%d\n", R_SECTOR, SECTOR);
 		printk("rh=%d h=%d\n", R_HEAD, HEAD);
 		printk("rt=%d t=%d\n", R_TRACK, TRACK);
 		printk("heads=%d eoc=%d\n", heads, eoc);
-		printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK, 
-			   sector_t, ssize);
+		printk("spt=%d st=%d ss=%d\n", SECT_PER_TRACK,
+		       sector_t, ssize);
 		printk("in_sector_offset=%d\n", in_sector_offset);
 	}
 #endif
@@ -2547,22 +2565,24 @@
  * does not work with MT, hence we can only transfer one head at
  * a time
  */
-static void virtualdmabug_workaround(void) {
+static void virtualdmabug_workaround(void)
+{
 	int hard_sectors, end_sector;
+
 	if(CT(COMMAND) == FD_WRITE) {
 		COMMAND &= ~0x80; /* switch off multiple track mode */
-	   
+
 		hard_sectors = raw_cmd->length >> (7 + SIZECODE);
 		end_sector = SECTOR + hard_sectors - 1;
 #ifdef FLOPPY_SANITY_CHECK
 		if(end_sector > SECT_PER_TRACK) {
-			printk("too many sectors %d > %d\n", 
-				   end_sector, SECT_PER_TRACK);
+			printk("too many sectors %d > %d\n",
+			       end_sector, SECT_PER_TRACK);
 			return;
 		}
 #endif
 		SECT_PER_TRACK = end_sector; /* make sure SECT_PER_TRACK points
-									  * to end of transfer */
+					      * to end of transfer */
 	}
 }
 
@@ -2603,7 +2623,7 @@
 	TRACK = CURRENT->sector / max_sector;
 	sector_t = CURRENT->sector % max_sector;
 	if (_floppy->track && TRACK >= _floppy->track) {
-		if(CURRENT->current_nr_sectors & 1) {
+		if (CURRENT->current_nr_sectors & 1) {
 			current_count_sectors = 1;
 			return 1;
 		} else
@@ -2935,7 +2955,7 @@
 
 static void do_fd_request(request_queue_t * q)
 {
-	if(usage_count == 0) {
+	if (usage_count == 0) {
 		printk("warning: usage count=0, CURRENT=%p exiting\n", CURRENT);
 		printk("sect=%ld cmd=%d\n", CURRENT->sector, CURRENT->cmd);
 		return;
@@ -3057,7 +3077,7 @@
 		raw_cmd->flags |= FD_RAW_HARDFAILURE;
 	} else {
 		raw_cmd->reply_count = inr;
-		if(raw_cmd->reply_count > MAX_REPLIES)
+		if (raw_cmd->reply_count > MAX_REPLIES)
 			raw_cmd->reply_count=0;
 		for (i=0; i< raw_cmd->reply_count; i++)
 			raw_cmd->reply[i] = reply_buffer[i];
@@ -3382,7 +3402,7 @@
 		process_fd_request();		
 		*g = current_type[drive];
 	}
-	if(!*g)
+	if (!*g)
 		return -ENODEV;
 	return 0;
 }
@@ -3420,8 +3440,8 @@
 	/* convert compatibility eject ioctls into floppy eject ioctl.
 	 * We do this in order to provide a means to eject floppy disks before
 	 * installing the new fdutils package */
-	if(cmd == CDROMEJECT || /* CD-ROM eject */
-	   cmd == 0x6470 /* SunOS floppy eject */) {
+	if (cmd == CDROMEJECT || /* CD-ROM eject */
+	    cmd == 0x6470 /* SunOS floppy eject */) {
 		DPRINT("obsolete eject ioctl\n");
 		DPRINT("please use floppycontrol --eject\n");
 		cmd = FDEJECT;
@@ -3467,7 +3487,7 @@
 
 	switch (cmd) {
 		case FDEJECT:
-			if(UDRS->fd_ref != 1)
+			if (UDRS->fd_ref != 1)
 				/* somebody else has this drive open */
 				return -EBUSY;
 			LOCK_FDC(drive,1);
@@ -3508,9 +3528,9 @@
 			CALL(poll_drive(1, FD_RAW_NEED_DISK));
 			ret = UDRS->flags;
 			process_fd_request();
-			if(ret & FD_VERIFY)
+			if (ret & FD_VERIFY)
 				return -ENODEV;
-			if(!(ret & FD_DISK_WRITABLE))
+			if (!(ret & FD_DISK_WRITABLE))
 				return -EROFS;
 			return 0;
 		case FDFMTTRK:
@@ -3705,7 +3725,7 @@
 			INFBOUND(try, 16);
 			tmp= (char *)fd_dma_mem_alloc(1024*try);
 		}
-		if(!tmp &&  !floppy_track_buffer) {
+		if (!tmp && !floppy_track_buffer) {
 			fallback_on_nodma_alloc(&tmp, 2048 * try);
 		}
 		if (!tmp && !floppy_track_buffer) {
@@ -3713,7 +3733,7 @@
 			RETERR(ENXIO);
 		}
 		if (floppy_track_buffer) {
-			if(tmp)
+			if (tmp)
 				fd_dma_mem_free((unsigned long)tmp,try*1024);
 		} else {
 			buffer_min = buffer_max = -1;
@@ -3787,9 +3807,9 @@
 	int cf;
 
 	if (UTESTF(FD_DISK_CHANGED) ||
-	   UTESTF(FD_VERIFY) ||
-	   test_bit(drive, &fake_change) ||
-	   NO_GEOM){
+	    UTESTF(FD_VERIFY) ||
+	    test_bit(drive, &fake_change) ||
+	    NO_GEOM){
 		lock_fdc(drive,0);
 		cf = UTESTF(FD_DISK_CHANGED) || UTESTF(FD_VERIFY);
 		if (!(cf || test_bit(drive, &fake_change) || NO_GEOM)){
@@ -3892,13 +3912,13 @@
 		return FDC_UNKNOWN;
 	}
 
-	if(!fdc_configure()) {
+	if (!fdc_configure()) {
 		printk(KERN_INFO "FDC %d is an 82072\n",fdc);
 		return FDC_82072;      	/* 82072 doesn't know CONFIGURE */
 	}
 
 	output_byte(FD_PERPENDICULAR);
-	if(need_more_output() == MORE_OUTPUT) {
+	if (need_more_output() == MORE_OUTPUT) {
 		output_byte(0);
 	} else {
 		printk(KERN_INFO "FDC %d is an 82072A\n", fdc);
@@ -4037,7 +4057,8 @@
 
 	{ "unexpected_interrupts", 0, &print_unex, 1, 0 },
 	{ "no_unexpected_interrupts", 0, &print_unex, 0, 0 },
-	{ "L40SX", 0, &print_unex, 0, 0 } };
+	{ "L40SX", 0, &print_unex, 0, 0 }
+};
 
 static int __init floppy_setup(char *str)
 {
@@ -4053,11 +4074,11 @@
 					param = ints[1];
 				else
 					param = config_params[i].def_param;
-				if(config_params[i].fn)
+				if (config_params[i].fn)
 					config_params[i].
 						fn(ints,param,
 						   config_params[i].param2);
-				if(config_params[i].var) {
+				if (config_params[i].var) {
 					DPRINT("%s=%d\n", str, param);
 					*config_params[i].var = param;
 				}
@@ -4086,7 +4107,7 @@
 	int i,unit,drive;
 
 
-	raw_cmd = 0;
+	raw_cmd = NULL;
 
 	devfs_handle = devfs_mk_dir (NULL, "floppy", 0, NULL);
 	if (devfs_register_blkdev(MAJOR_NR,"fd",&floppy_fops)) {
@@ -4174,7 +4195,7 @@
 			FDCS->address = -1;
 			continue;
 		}
-		if(can_use_virtual_dma == 2 && FDCS->version < FDC_82072A)
+		if (can_use_virtual_dma == 2 && FDCS->version < FDC_82072A)
 			can_use_virtual_dma = 0;
 
 		have_no_fdc = 0;
@@ -4192,13 +4213,13 @@
 	if (have_no_fdc) 
 	{
 		DPRINT("no floppy controllers found\n");
- 		floppy_tq.routine = (void *)(void *) empty;
+		floppy_tq.routine = (void *)(void *) empty;
 		mark_bh(IMMEDIATE_BH);
 		schedule();
- 		if (usage_count)
- 			floppy_release_irq_and_dma();
+		if (usage_count)
+			floppy_release_irq_and_dma();
 		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-		devfs_unregister_blkdev(MAJOR_NR,"fd");		
+		devfs_unregister_blkdev(MAJOR_NR,"fd");
 	}
 	
 	for (drive = 0; drive < N_DRIVE; drive++) {
@@ -4324,7 +4345,7 @@
 	if (floppy_track_buffer && max_buffer_sectors) {
 		tmpsize = max_buffer_sectors*1024;
 		tmpaddr = (unsigned long)floppy_track_buffer;
-		floppy_track_buffer = 0;
+		floppy_track_buffer = NULL;
 		max_buffer_sectors = 0;
 		buffer_min = buffer_max = -1;
 		fd_dma_mem_free(tmpaddr, tmpsize);
@@ -4357,7 +4378,7 @@
 
 #ifdef MODULE
 
-char *floppy=NULL;
+char *floppy;
 
 static void __init parse_floppy_cfg_string(char *cfg)
 {
@@ -4365,11 +4386,11 @@
 
 	while(*cfg) {
 		for(ptr = cfg;*cfg && *cfg != ' ' && *cfg != '\t'; cfg++);
-		if(*cfg) {
+		if (*cfg) {
 			*cfg = '\0';
 			cfg++;
 		}
-		if(*ptr)
+		if (*ptr)
 			floppy_setup(ptr);
 	}
 }
@@ -4378,7 +4399,7 @@
 {
 	printk(KERN_INFO "inserting floppy driver for " UTS_RELEASE "\n");
 		
-	if(floppy)
+	if (floppy)
 		parse_floppy_cfg_string(floppy);
 	return floppy_init();
 }
@@ -4411,7 +4432,7 @@
 void floppy_eject(void)
 {
 	int dummy;
-	if(have_no_fdc)
+	if (have_no_fdc)
 		return;
 	if(floppy_grab_irq_and_dma()==0)
 	{
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.3.99-pre8/linux/drivers/block/loop.c	Thu May 11 15:30:06 2000
+++ linux/drivers/block/loop.c	Mon May 15 14:54:32 2000
@@ -289,7 +289,8 @@
 		if (lo->lo_flags & LO_FLAGS_READ_ONLY)
 			goto error_out;
 	} else if (current_request->cmd != READ) {
-		printk(KERN_ERR "unknown loop device command (%d)?!?", current_request->cmd);
+		printk(KERN_ERR "unknown loop device command (%d)?!?",
+		       current_request->cmd);
 		goto error_out;
 	}
 
@@ -423,8 +424,28 @@
 		/* Backed by a block device - don't need to hold onto
 		   a file structure */
 		lo->lo_backing_file = NULL;
+
+		if (error)
+			goto out_putf;
 	} else if (S_ISREG(inode->i_mode)) {
 		struct address_space_operations *aops;
+
+		aops = inode->i_mapping->a_ops;
+		/*
+		 * If we can't read - sorry. If we only can't write - well,
+		 * it's going to be read-only.
+		 */
+		error = -EINVAL;
+		if (!aops->readpage)
+			goto out_putf;
+
+		if (!aops->prepare_write || !aops->commit_write)
+			lo->lo_flags |= LO_FLAGS_READ_ONLY;
+
+		error = get_write_access(inode);
+		if (error)
+			goto out_putf;
+
 		/* Backed by a regular file - we need to hold onto a file
 		   structure for this file.  Friggin' NFS can't live without
 		   it on write and for reading we use do_generic_file_read(),
@@ -437,35 +458,23 @@
 
 		error = -ENFILE;
 		lo->lo_backing_file = get_empty_filp();
-		if (lo->lo_backing_file) {
-			lo->lo_backing_file->f_mode = file->f_mode;
-			lo->lo_backing_file->f_pos = file->f_pos;
-			lo->lo_backing_file->f_flags = file->f_flags;
-			lo->lo_backing_file->f_owner = file->f_owner;
-			lo->lo_backing_file->f_dentry = file->f_dentry;
-			lo->lo_backing_file->f_vfsmnt = file->f_vfsmnt;
-			lo->lo_backing_file->f_op = file->f_op;
-			lo->lo_backing_file->private_data = file->private_data;
-			file_moveto(lo->lo_backing_file, file);
-
-			error = get_write_access(inode);
-			if (error) {
-				put_filp(lo->lo_backing_file);
-				lo->lo_backing_file = NULL;
-			}
-		}
-		aops = inode->i_mapping->a_ops;
-		/*
-		 * If we can't read - sorry. If we only can't write - well,
-		 * it's going to be read-only.
-		 */
-		if (!aops->readpage)
-			error = -EINVAL;
-		else if (!aops->prepare_write || !aops->commit_write)
-			lo->lo_flags |= LO_FLAGS_READ_ONLY;
+		if (lo->lo_backing_file == NULL) {
+			put_write_access(inode);
+			goto out_putf;
+		}
+
+		lo->lo_backing_file->f_mode = file->f_mode;
+		lo->lo_backing_file->f_pos = file->f_pos;
+		lo->lo_backing_file->f_flags = file->f_flags;
+		lo->lo_backing_file->f_owner = file->f_owner;
+		lo->lo_backing_file->f_dentry = file->f_dentry;
+		lo->lo_backing_file->f_vfsmnt = mntget(file->f_vfsmnt);
+		lo->lo_backing_file->f_op = file->f_op;
+		lo->lo_backing_file->private_data = file->private_data;
+		file_moveto(lo->lo_backing_file, file);
+
+		error = 0;
 	}
-	if (error)
-		goto out_putf;
 
 	if (IS_RDONLY (inode) || is_read_only(lo->lo_device))
 		lo->lo_flags |= LO_FLAGS_READ_ONLY;
@@ -477,9 +486,9 @@
 	lo->ioctl = NULL;
 	figure_loop_size(lo);
 
-out_putf:
+ out_putf:
 	fput(file);
-out:
+ out:
 	if (error)
 		MOD_DEC_USE_COUNT;
 	return error;
@@ -530,6 +539,7 @@
 	lo->lo_dentry = NULL;
 
 	if (lo->lo_backing_file != NULL) {
+		put_write_access(lo->lo_backing_file->f_dentry->d_inode);
 		fput(lo->lo_backing_file);
 		lo->lo_backing_file = NULL;
 	} else {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/block/xor.c linux/drivers/block/xor.c
--- v2.3.99-pre8/linux/drivers/block/xor.c	Fri May 12 14:18:55 2000
+++ linux/drivers/block/xor.c	Mon May 15 12:10:26 2000
@@ -15,6 +15,7 @@
  * (for example /usr/src/linux/COPYING); if not, write to the Free
  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#include <linux/config.h>
 #define BH_TRACE 0
 #include <linux/module.h>
 #include <linux/raid/md.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.3.99-pre8/linux/drivers/char/Config.in	Thu May 11 15:30:06 2000
+++ linux/drivers/char/Config.in	Mon May 22 09:50:53 2000
@@ -50,6 +50,10 @@
       bool '  Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
    fi 
    tristate '  Specialix SX (and SI) card support' CONFIG_SX
+   tristate '  Specialix RIO system support' CONFIG_RIO
+   if [ "$CONFIG_RIO" != "n" ]; then
+     bool '    Support really old RIO/PCI cards' CONFIG_RIO_OLDPCI
+   fi
    bool '  Stallion multiport serial support' CONFIG_STALDRV
    if [ "$CONFIG_STALDRV" = "y" ]; then
      tristate '    Stallion EasyIO or EC8/32 support' CONFIG_STALLION
@@ -201,7 +205,7 @@
    fi
    comment 'Video Adapters'
    if [ "$CONFIG_I2C_ALGOBIT" = "y" -o "$CONFIG_I2C_ALGOBIT" = "m" ]; then
-      dep_tristate '  BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT
+      dep_tristate '  BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV $CONFIG_PCI $CONFIG_I2C_ALGOBIT $CONFIG_SOUND
    fi
    dep_tristate '  Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
    if [ "$CONFIG_ALL_PPC" = "y" ]; then
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.3.99-pre8/linux/drivers/char/Makefile	Thu May 11 15:30:06 2000
+++ linux/drivers/char/Makefile	Sat May 20 12:07:56 2000
@@ -136,41 +136,38 @@
 obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
 obj-$(CONFIG_SX) += sx.o
 
+# If either SX or RIO is in the kernel, generic_serial goes in the
+# kernel, and the module is no longer required. The "in kernel" case
+# is last to be able to override the module case....  This is an
+# example of the new "makefile automatically figures out the
+# dependencies"....  -- REW
 
-# If either is in the kernel, generic_serial goes in the kernel, and
-# the module is no longer required. The "in kernel" case is last to be
-# able to override the module case....  This is an example of the new
-# "makefile automatically figures out the dependencies"....  -- REW
+GS=n
+ifeq ($(CONFIG_RIO),m)
+  M_OBJS += generic_serial.o
+  MOD_SUB_DIRS += rio
+  GS = m
+endif
 
-GS = n
 ifeq ($(CONFIG_SX),m)
   GS = m
+  M_OBJS += sx.o
 endif
-ifeq ($(CONFIG_RIO),m)
-  GS = m 
-endif
-ifeq ($(CONFIG_SX),y)
-  GS = y 
-endif
-ifeq ($(CONFIG_RIO),y)
-  GS = y 
-endif
-obj-$(GS) += generic_serial.o
-
-
-
 
 ifeq ($(CONFIG_RIO),y)
-obj-y += rio/rio.o  generic_serial.o
-SUB_DIRS += rio
-MOD_SUB_DIRS += rio
-else
-  ifeq ($(CONFIG_RIO),m)
-  obj-m += generic_serial.o
+  L_OBJS += rio/rio.o  generic_serial.o
+  SUB_DIRS += rio
   MOD_SUB_DIRS += rio
-  endif
+  GS = y
 endif
 
+ifeq ($(CONFIG_SX),y)
+  L_OBJS += sx.o
+  GS = y
+endif
+
+obj-$(GS) += generic_serial.o
+
 obj-$(CONFIG_ATIXL_BUSMOUSE) += atixlmouse.o
 obj-$(CONFIG_LOGIBUSMOUSE) += logibusmouse.o
 obj-$(CONFIG_PRINTER) += lp.o
@@ -205,7 +202,7 @@
 obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
 obj-$(CONFIG_AMIGAMOUSE) += amigamouse.o
 obj-$(CONFIG_ATARIMOUSE) += atarimouse.o
-obj-$(CONFIG_ADBMOUSE) += adbmouse.o busmouse.o
+obj-$(CONFIG_ADBMOUSE) += adbmouse.o
 obj-$(CONFIG_PC110_PAD) += pc110pad.o
 obj-$(CONFIG_WDT) += wdt.o
 obj-$(CONFIG_WDTPCI) += wdt_pci.o
@@ -232,7 +229,8 @@
   endif
 endif
 
-obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o tda8425.o tda985x.o tea6300.o
+obj-$(CONFIG_VIDEO_BT848) += bttv.o msp3400.o \
+	tda7432.o tda8425.o tda985x.o tda9875.o tea6300.o tea6420.o
 ifeq ($(CONFIG_VIDEO_BT848),y)
 L_TUNERS=y
 else
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.3.99-pre8/linux/drivers/char/bttv.c	Thu May 11 15:30:06 2000
+++ linux/drivers/char/bttv.c	Mon May 22 09:50:53 2000
@@ -43,19 +43,13 @@
 #include <linux/interrupt.h>
 #include <linux/kmod.h>
 #include <linux/vmalloc.h>
-
-#ifdef LOCK_I2C_BUS
-# error INSTALL ERROR
-# error gcc uses the old, obsolete i2c.h include file.  Please install the \
-	new i2c stack.  Please install it by patching the kernel, otherwise \
-	gcc will not find the new header files.
-#endif
+#include <linux/init.h>
 
 #include "bttv.h"
 #include "tuner.h"
 
-#define DEBUG(x) 		/* Debug driver */
-#define IDEBUG(x)		/* Debug interrupt handler */
+#define DEBUG(x)	/* Debug driver */
+#define IDEBUG(x)	/* Debug interrupt handler */
 #define MIN(a,b) (((a)>(b))?(b):(a))
 #define MAX(a,b) (((a)>(b))?(a):(b))
 
@@ -100,7 +94,7 @@
 static unsigned long remap[BTTV_MAX];
 static unsigned int radio[BTTV_MAX];
 static unsigned int card[BTTV_MAX] = { 0, 0, 0, 0 };
-static unsigned int pll[BTTV_MAX] = { 0, 0, 0, 0};
+static unsigned int pll[BTTV_MAX] = { -1, -1, -1, -1};
 static unsigned int fieldnr = 0;
 static unsigned int verbose = 1;
 static unsigned int debug = 0;
@@ -473,7 +467,7 @@
         NULL
 };
 
-static int init_bttv_i2c(struct bttv *btv)
+static int __init init_bttv_i2c(struct bttv *btv)
 {
 	/* i2c bit_adapter */
 	memcpy(&btv->i2c_adap, &i2c_adap_template, sizeof(struct i2c_adapter));
@@ -495,7 +489,7 @@
 }
 
 /* read I2C */
-static int I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) 
+static int __init I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) 
 {
         unsigned char buffer = 0;
 
@@ -520,7 +514,7 @@
 }
 
 /* write I2C */
-static int I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
+static int __init I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
                     unsigned char b2, int both)
 {
         unsigned char buffer[2];
@@ -537,7 +531,7 @@
 }
 
 /* read EEPROM */
-static void readee(struct bttv *btv, unsigned char *eedata, int addr)
+static void __init readee(struct bttv *btv, unsigned char *eedata, int addr)
 {
 	int i;
         
@@ -564,7 +558,7 @@
         int  id;
         char *name;
 } 
-hauppauge_tuner[] = 
+hauppauge_tuner[] __initdata = 
 {
         { TUNER_ABSENT,        "" },
         { TUNER_ABSENT,        "External" },
@@ -612,8 +606,7 @@
         { TUNER_ABSENT,        "Temic 4046FM5" },
 };
 
-static void
-hauppauge_eeprom(struct bttv *btv)
+static void __init hauppauge_eeprom(struct bttv *btv)
 {
         if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) 
         {
@@ -622,10 +615,11 @@
 			printk("bttv%d: Hauppauge eeprom: tuner=%s (%d)\n",btv->nr,
 			       hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type);
         }
+
+	return;
 }
 
-static void
-hauppauge_boot_msp34xx(struct bttv *btv)
+static void __init hauppauge_boot_msp34xx(struct bttv *btv)
 {
 	int i;
 
@@ -661,7 +655,7 @@
 /*  This is basically the same procedure as 
  *  used by Alessandro Rubini in his pxc200 
  *  driver, but using BTTV functions */
-static void init_PXC200(struct bttv *btv)
+static void __init init_PXC200(struct bttv *btv)
 {
 	static const int vals[] = { 0x08, 0x09, 0x0a, 0x0b, 0x0d, 0x0d,
 				    0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
@@ -711,21 +705,25 @@
 	unsigned id;
 	int cardnr;
 	char *name;
-} cards[] = {
+} cards[] __initdata = {
 	{ 0x00011002, BTTV_HAUPPAUGE878,  "ATI TV Wonder" },
-	{ 0x00031461, BTTV_AVERMEDIA98,   "AVerMedia TVPhone98" },
+	{ 0x00011461, BTTV_AVPHONE98,     "AVerMedia TVPhone98" },
+	{ 0x00031461, BTTV_AVPHONE98,     "AVerMedia TVPhone98" },
+	{ 0x00041461, BTTV_AVPHONE98,     "AVerMedia TVPhone98" },
 	{ 0x10b42636, BTTV_HAUPPAUGE878,  "STB ???" },
 	{ 0x1118153b, BTTV_TERRATVALUE,   "Terratec TV Value" },
+	{ 0x1200bd11, BTTV_PINNACLERAVE,  "Pinnacle PCTV Rave" },
 	{ 0x13eb0070, BTTV_HAUPPAUGE878,  "Hauppauge WinTV" },
 	{ 0x14610002, BTTV_AVERMEDIA98,   "Avermedia TVCapture 98" },
 	{ 0x18501851, BTTV_CHRONOS_VS2,   "Chronos Video Shuttle II" },
 	{ 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" },
+	{ 0x263610b4, BTTV_STB2,          "STB TV PCI FM, P/N 6000704" },
 	{ 0x3000144f, BTTV_MAGICTVIEW063, "TView 99 (CPH063)" },
 	{ 0x300014ff, BTTV_MAGICTVIEW061, "TView 99 (CPH061)" },
 	{ 0x3002144f, BTTV_MAGICTVIEW061, "Askey Magic TView" },
 	{ 0x300214ff, BTTV_PHOEBE_TVMAS,  "Phoebe TV Master" },
+	{ 0x402010fc, 0 /* no tvcards entry yet */, "I-O Data Co. GV-BCV3/PCI" },
 	{ 0x6606217d, BTTV_WINFAST2000,   "Leadtek WinFast TV 2000" },
-	{ 0x1200bd11, BTTV_PINNACLERAVE,  "Pinnacle PCTV Rave" },
 	{ 0, -1, NULL }
 };
 
@@ -747,6 +745,13 @@
 	int tda9840:1;
 	int tda985x:1;
 	int tea63xx:1;
+	int tea64xx:1;
+	int tda7432:1;
+	int tda9875:1;
+
+	/* other settings */
+	int pll;
+	int tuner_type;
 };
 
 static struct tvcard tvcards[] = 
@@ -754,149 +759,161 @@
 	/* 0x00 */
         { " *** UNKNOWN *** ",
           3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "MIRO PCTV",
           4, 1, 0, 2,15, { 2, 3, 1, 1}, { 2, 0, 0, 0,10},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "Hauppauge old",
           4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
-	  1,1,0,1,0 },
+	  1,1,0,1,0,0,0,1,  PLL_NONE, -1 },
         { "STB",
           3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0,
-	  0,1,1,1,1 },
+	  0,1,1,1,1,0,0,1,  PLL_NONE, -1 },
 
         { "Intel",
-          3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
-	  1,1,1,1,0 },
+          3, 1, 0, -1, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 	{ "Diamond DTV2000",
           3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 0, 1, 0, 1, 3},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 	{ "AVerMedia TVPhone",
           3, 1, 0, 3,15, { 2, 3, 1, 1}, {12, 4,11,11, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "MATRIX-Vision MV-Delta",
           5, 1, -1, 3, 0, { 2, 3, 1, 0, 0},{0 }, 0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 
 	/* 0x08 */
         { "Fly Video II",
           3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},
 	  { 0, 0xc00, 0x800, 0x400, 0xc00, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "TurboTV",
           3, 1, 0, 2, 3, { 2, 3, 1, 1}, { 1, 1, 2, 3, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "Hauppauge new (bt878)",
 	  4, 1, 0, 2, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0,
-	  1,1,0,1,0 },
+	  1,1,0,1,0,0,0,1,  PLL_28,   -1 },
         { "MIRO PCTV pro",
           3, 1, 0, 2, 65551, { 2, 3, 1, 1}, {1,65537, 0, 0,10},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 
 	{ "ADS Technologies Channel Surfer TV",
 	  3, 1, 2, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "AVerMedia TVCapture 98",
 	  3, 4, 0, 2, 15, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_28,   -1 },
         { "Aimslab VHX",
           3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 0, 1, 2, 3, 4},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "Zoltrix TV-Max",
           3, 1, 0, 2,15, { 2, 3, 1, 1}, {0 , 0, 1 , 0, 10},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 
 	/* 0x10 */
         { "Pixelview PlayTV (bt878)",
-          3, 1, 0, 2, 0x01e000, { 2, 0, 1, 1},
+          3, 1, 0, 2, 0x01fe00, { 2, 0, 1, 1},
 	  { 0x01c000, 0, 0x018000, 0x014000, 0x002000, 0 },0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_28,   -1 },
         { "Leadtek WinView 601",
           3, 1, 0, 2, 0x8300f8, { 2, 3, 1, 1,0},
 	  { 0x4fa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007,0xcfa007},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "AVEC Intercapture",
 	  3, 2, 0, 2, 0, {2, 3, 1, 1}, {1, 0, 0, 0, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 	{ "LifeView FlyKit w/o Tuner",
 	  3, 1, -1, -1, 0x8dff00, { 2, 3, 1, 1}, { 0 },0,
-	  0,0,0,0,0 },
+	  0,0,0,0,0,0,0,1,  PLL_NONE, -1 },
 
         { "CEI Raffles Card",
 	  3, 3, 0, 2, 0, {2, 3, 1, 1}, {0, 0, 0, 0 ,0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 	{ "Lucky Star Image World ConferenceTV",
-	  3, 1, 0, 2, 16777215, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0,
-	  1,1,1,1,0 },
+	  3, 1, 0, 2, 0x00fffe07, { 2, 3, 1, 1}, { 131072, 1, 1638400, 3, 4},0,
+	  1,1,1,1,0,0,0,1,  PLL_28,   TUNER_PHILIPS_PAL_I },
 	{ "Phoebe Tv Master + FM",
 	  3, 1, 0, 2, 0xc00, { 2, 3, 1, 1},{0, 1, 0x800, 0x400, 0xc00, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "Modular Technology MM205 PCTV, bt878",
 	  2, 1, 0, -1, 7, { 2, 3 }, { 0, 0, 0, 0, 0 },0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 
 	/* 0x18 */
         { "Askey/Typhoon/Anubis Magic TView CPH051/061 (bt878)",
 	  3, 1, 0, 2, 0xe00, { 2, 3, 1, 1}, {0x400, 0x400, 0x400, 0x400, 0},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_28,   -1 },
         { "Terratec/Vobis TV-Boostar",
           3, 1, 0, 2, 16777215 , { 2, 3, 1, 1}, { 131072, 1, 1638400, 3,4},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "Newer Hauppauge WinCam (bt878)",
  	  4, 1, 0, 3, 7, { 2, 0, 1, 1}, { 0, 1, 2, 3, 4},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "MAXI TV Video PCI2",
           3, 1, 0, 2, 0xffff, { 2, 3, 1, 1}, { 0, 1, 2, 3, 0xc00},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, TUNER_PHILIPS_SECAM },
 
         { "Terratec TerraTV+",
           3, 1, 0, 2, 0x70000, { 2, 3, 1, 1}, 
           { 0x20000, 0x30000, 0x00000, 0x10000, 0x40000},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "Imagenation PXC200",
           5, 1, -1, 4, 0, { 2, 3, 1, 0, 0}, { 0 }, 0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "FlyVideo 98",
           3, 1, 0, 2, 0x8dff00, {2, 3, 1, 1}, 
           { 0, 0x8dff00, 0x8df700, 0x8de700, 0x8dff00, 0 },0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
         { "iProTV",
 	  3, 1, 0, 2, 1, { 2, 3, 1, 1}, { 1, 0, 0, 0, 0 },0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 
 	/* 0x20 */
 	{ "Intel Create and Share PCI",
 	  4, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 4, 4, 4, 4},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 	{ "Terratec TerraTValue",
-          3, 1, 0, 2, 0xf00, { 2, 3, 1, 1}, { 0x500, 0, 0x300, 0x900, 0x900},0,
-	  1,1,1,1,0 },
+	  3, 1, 0, 2, 0xffff00, { 2, 3, 1, 1},
+	  { 0x500, 0, 0x300, 0x900, 0x900},0,
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
 	{ "Leadtek WinFast 2000",
 	  3, 1, 0, 2, 0xfff000, { 2, 3, 1, 1,0},
 	  { 0x621000,0x620100,0x621100,0x620000,0xE210000,0x620000},0,
-	  1,1,1,1,1 },
+	  1,1,1,1,1,0,0,1,  PLL_28,   -1 },
 	{ "Chronos Video Shuttle II",
 	  3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0, 0x1000, 0x1000, 0x0800},0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_28,   -1 },
 
 	{ "Typhoon TView TV/FM Tuner",
 	  3, 3, 0, 2, 0x1800, { 2, 3, 1, 1}, { 0, 0x800, 0, 0, 0x1800, 0 },0,
-	  1,1,1,1,0 },
+	  1,1,1,1,0,0,0,1,  PLL_28,   -1 },
 	{ "PixelView PlayTV pro",
           3, 1, 0, 2, 0xff, { 2, 3, 1, 1 },
-          { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0 },
+          { 0x21, 0x20, 0x24, 0x2c, 0x29, 0x29 }, 0,
+	  0,0,0,0,0,0,0,1,  PLL_28,   -1 },
 	{ "TView99 CPH063",
-	  3, 1, 0, 2, 0x551e00, { 2, 0, 1, 1},
-	  { 0x551400, 0x551200, 0, 0, 0x551200 }, 0,1,1,1,1,0 },
+	  3, 1, 0, 2, 0x551e00, { 2, 3, 1, 1},
+	  { 0x551400, 0x551200, 0, 0, 0, 0x551200 }, 0,
+	  1,1,1,1,0,0,0,1,  PLL_28,   -1 },
 	{ "Pinnacle PCTV Rave",
 	  3, 1, 0, 2, 0x03000F, { 2, 3, 1, 1}, { 2, 0, 0, 0, 1},0,
-	  1,1,1,1,0 },
-	
+	  1,1,1,1,0,0,0,1,  PLL_NONE, -1 },
+
+        /* 0x28 */
+        { "STB2",
+          3, 1, 0, 2, 7, { 2, 3, 1, 1}, { 4, 0, 2, 3, 1},0,
+	  0,1,1,1,0,1,1,1,  PLL_NONE, -1 },
+        { "AVerMedia TVPhone 98",
+	  3, 4, 0, 2, 4, { 2, 3, 1, 1}, { 13, 14, 11, 7, 0, 0},0,
+	  1,1,1,1,0,0,0,1,  PLL_28,   5 },
+        { "ProVideo PV951", /* pic16c54 */
+          3, 1, 0, 2, 0, { 2, 3, 1, 1}, { 0, 0, 0, 0, 0},0,
+	  0,0,0,0,0,0,0,0,  PLL_28,   1 },
 };
 #define TVCARDS (sizeof(tvcards)/sizeof(struct tvcard))
 
-static void
-dump_eeprom(struct bttv *btv,int addr)
+static void __init dump_eeprom(struct bttv *btv,int addr)
 {
 	int i;
 
@@ -913,8 +930,7 @@
 	}
 }
 
-static int
-idcard_eeprom(struct bttv *btv)
+static int __init idcard_eeprom(struct bttv *btv)
 {
 	unsigned id;
 	int i,n;
@@ -1477,6 +1493,10 @@
         unsigned char lmask, rmask, *p;
         int W, l, r;
 	int i;
+
+	if (debug)
+		printk("bttv clip: %dx%d+%d+%d\n",w,h,x,y);
+
 	/* bitmap is fixed width, 128 bytes (1024 pixels represented) */
         if (x<0)
         {
@@ -1497,10 +1517,10 @@
                 w=1024-x;
 
         l=x>>3;
-        r=(x+w)>>3;
+        r=(x+w-1)>>3;
         W=r-l-1;
         lmask=lmaskt[x&7];
-        rmask=rmaskt[(x+w)&7];
+        rmask=rmaskt[(x+w-1)&7];
         p=clipmap+128*y+l;
         
         if (W>0) 
@@ -1716,8 +1736,7 @@
 	struct tvnorm *tvn;
 	unsigned long flags;
  	
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&btv->s_lock, flags);
 
 	tvn=&tvnorms[btv->win.norm];
 	
@@ -1771,7 +1790,7 @@
 	btwrite(format, BT848_COLOR_FMT);
 	btwrite(bswap | BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&btv->s_lock, flags);
 }
 
 
@@ -1835,6 +1854,7 @@
 {
 	unsigned int *ro, *re;
 	unsigned int *vbuf;
+	unsigned long flags;
 	
 	if(btv->fbuffer==NULL)
 	{
@@ -1870,7 +1890,7 @@
 	if (debug)
 		printk("bttv%d: cap vgrab: queue %d (%d:%dx%d)\n",
 		       btv->nr,mp->frame,mp->format,mp->width,mp->height);
-        cli();
+       	spin_lock_irqsave(&btv->s_lock, flags); 
         btv->gbuf[mp->frame].stat    = GBUFFER_GRABBING;
 	btv->gbuf[mp->frame].fmt     = palette2fmt[mp->format];
 	btv->gbuf[mp->frame].width   = mp->width;
@@ -1885,12 +1905,13 @@
 #endif
 
 	if (btv->gq_in == btv->gq_out) {
+		btv->gq_start = 1;
 		btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);
         }
 	btv->gqueue[btv->gq_in++] = mp->frame;
 	btv->gq_in = btv->gq_in % MAX_GBUFFERS;
 
-        sti();
+	spin_unlock_irqrestore(&btv->s_lock, flags);
 	btor(3, BT848_CAP_CTL);
 	btor(3, BT848_GPIO_DMA_CTL);
 	return 0;
@@ -1911,23 +1932,25 @@
 	todo=count;
 	while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) 
 	{
+		unsigned long flags;
+
 		if(copy_to_user((void *) buf, (void *) btv->vbibuf+btv->vbip, q))
 			return -EFAULT;
 		todo-=q;
 		buf+=q;
 
-		cli();
+		spin_lock_irqsave(&btv->s_lock, flags);
 		if (todo && q==VBIBUF_SIZE-btv->vbip) 
 		{
 			if(nonblock)
 			{
-				sti();
+				spin_unlock_irqrestore(&btv->s_lock, flags);	
 				if(count==todo)
 					return -EWOULDBLOCK;
 				return count-todo;
 			}
+			spin_unlock_irqrestore(&btv->s_lock, flags);	
 			interruptible_sleep_on(&btv->vbiq);
-			sti();
 			if(signal_pending(current))
 			{
 				if(todo==count)
@@ -1935,7 +1958,8 @@
 				else
 					return count-todo;
 			}
-		}
+		} else
+			spin_unlock_irqrestore(&btv->s_lock, flags);	
 	}
 	if (todo) 
 	{
@@ -1958,7 +1982,7 @@
 {
 	if (verbose)
 		printk("bttv%d: resetting chip\n",btv->nr);
-	btwrite(0xfffffUL, BT848_INT_STAT);
+	btwrite(~0x0UL, BT848_INT_STAT);
 	btand(~15, BT848_GPIO_DMA_CTL);
 	btwrite(0, BT848_SRESET);
 	btwrite(virt_to_bus(btv->risc_jmp+2),
@@ -1984,6 +2008,8 @@
         int i,ret;
 
 	ret = -EBUSY;
+
+	MOD_INC_USE_COUNT;
 	down(&btv->lock);
 	if (btv->user)
 		goto out_unlock;
@@ -2005,11 +2031,11 @@
 	set_pll(btv);
         btv->user++;
 	up(&btv->lock);
-        MOD_INC_USE_COUNT;
         return 0;
 
  out_unlock:
 	up(&btv->lock);
+	MOD_DEC_USE_COUNT;
 	return ret;
 }
 
@@ -2033,14 +2059,15 @@
 
 	btread(BT848_I2C); 	/* This fixes the PCI posting delay */
 	
-	/*
-	 *	This is sucky but right now I can't find a good way to
-	 *	be sure its safe to free the buffer. We wait 5-6 fields
-	 *	which is more than sufficient to be sure.
-	 */
-
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout(HZ/10);	/* Wait 1/10th of a second */
+	if (-1 != btv->gq_grab) {
+		/*
+		 *	This is sucky but right now I can't find a good way to
+		 *	be sure its safe to free the buffer. We wait 5-6 fields
+		 *	which is more than sufficient to be sure.
+		 */
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(HZ/10);	/* Wait 1/10th of a second */
+	}
 	
 	/*
 	 *	We have allowed it to drain.
@@ -2726,6 +2753,8 @@
 	todo=count;
 	while (todo && todo>(q=VBIBUF_SIZE-btv->vbip)) 
 	{
+		unsigned long flags;
+
 		if (btv->needs_restart) {
 			down(&btv->lock);
 			bt848_restart(btv);
@@ -2736,18 +2765,18 @@
 		todo-=q;
 		buf+=q;
 
-		cli();
+		spin_lock_irqsave(&btv->s_lock, flags);	
 		if (todo && q==VBIBUF_SIZE-btv->vbip) 
 		{
 			if(nonblock)
 			{
-				sti();
+				spin_unlock_irqrestore(&btv->s_lock, flags);	
 				if(count==todo)
 					return -EWOULDBLOCK;
 				return count-todo;
 			}
+			spin_unlock_irqrestore(&btv->s_lock, flags);	
 			interruptible_sleep_on(&btv->vbiq);
-			sti();
 			if(signal_pending(current))
 			{
 				if(todo==count)
@@ -2755,7 +2784,8 @@
 				else
 					return count-todo;
 			}
-		}
+		} else
+			spin_unlock_irqrestore(&btv->s_lock, flags);	
 	}
 	if (todo) 
 	{
@@ -2784,6 +2814,8 @@
 {
 	struct bttv *btv=(struct bttv *)(dev-2);
 
+	MOD_INC_USE_COUNT;
+
         down(&btv->lock);
 	if (btv->needs_restart)
 		bt848_restart(btv);
@@ -2792,7 +2824,6 @@
 	bt848_set_risc_jmps(btv,-1);
 	up(&btv->lock);
 
-	MOD_INC_USE_COUNT;
 	return 0;   
 }
 
@@ -2864,6 +2895,7 @@
 	struct bttv *btv = (struct bttv *)(dev-1);
 	unsigned long v;
 
+	MOD_INC_USE_COUNT;
         down(&btv->lock);
 	if (btv->user)
 		goto busy_unlock;
@@ -2876,11 +2908,11 @@
 	bt848_muxsel(btv,0);
 	up(&btv->lock);
 
-	MOD_INC_USE_COUNT;
 	return 0;   
 
  busy_unlock:
 	up(&btv->lock);
+	MOD_DEC_USE_COUNT;
 	return -EBUSY;
 }
 
@@ -2986,7 +3018,7 @@
 #define  TRITON_PEER_CONCURRENCY  (1<<3)
   
 
-static void handle_chipset(void)
+static void __init handle_chipset(void)
 {
 	struct pci_dev *dev = NULL;
   
@@ -3018,7 +3050,7 @@
 
 
 /* can tda9855.c handle this too maybe? */
-static void init_tda9840(struct bttv *btv)
+static void __init init_tda9840(struct bttv *btv)
 {
         /* Horrible Hack */
         I2CWrite(btv, I2C_TDA9840, TDA9840_SW, 0x2a, 1);  /* sound mode switching */
@@ -3034,17 +3066,16 @@
 
 /* Figure out card and tuner type */
 
-static void idcard(int i)
+static void __init idcard(struct bttv *btv)
 {
-        struct bttv *btv = &bttvs[i];
 	int type,eeprom = 0;
 
 	btwrite(0, BT848_GPIO_OUT_EN);
-	DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", i, btread(BT848_GPIO_DATA)));
+	DEBUG(printk(KERN_DEBUG "bttv%d: GPIO: 0x%08x\n", btv->nr, btread(BT848_GPIO_DATA)));
 
 	/* Default the card to the user-selected one. */
-	if (card[i] >= 0 && card[i] < TVCARDS)
-		btv->type=card[i];
+	if (card[btv->nr] >= 0 && card[btv->nr] < TVCARDS)
+		btv->type=card[btv->nr];
 
 	/* If we were asked to auto-detect, then do so! */
 	if (btv->type == BTTV_UNKNOWN) {
@@ -3063,7 +3094,7 @@
 			        btv->type=BTTV_HAUPPAUGE;
 			}
 
-		/* STB cards have a eeprom @ 0xae */
+		/* STB cards have a eeprom @ 0xae (old bt848) */
 		} else if (I2CRead(btv, I2C_STBEE, "eeprom")>=0) {
 			btv->type=BTTV_STB;
 		}
@@ -3078,20 +3109,20 @@
 	}
 
 	/* print which board we have found */
-	printk(KERN_INFO "bttv%d: model: ",btv->nr);
-
 	sprintf(btv->video_dev.name,"BT%d%s(%.22s)",
 		btv->id,
 		(btv->id==848 && btv->revision==0x12) ? "A" : "",
 		tvcards[btv->type].name);
-	printk("%s\n",btv->video_dev.name);
+	printk(KERN_INFO "bttv%d: model: %s\n",btv->nr,btv->video_dev.name);
 
+	
         /* board specific initialisations */
         if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) {
                 /* auto detect tuner for MIRO cards */
                 btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
         }
         if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) {
+		/* pick up some config infos from the eeprom */
 		if (0xa0 != eeprom) {
 			eeprom = 0xa0;
 			readee(btv,eeprom_data,0xa0);
@@ -3099,32 +3130,42 @@
                 hauppauge_eeprom(btv);
                 hauppauge_boot_msp34xx(btv);
         }
-	if (btv->type == BTTV_MAXI) {
-		/* PHILIPS FI1216MK2 tuner (PAL/SECAM) */
-		btv->tuner_type=TUNER_PHILIPS_SECAM;
-	}
- 
  	if (btv->type == BTTV_PXC200)
 		init_PXC200(btv);
- 	
-        if (btv->type == BTTV_CONFERENCETV)
-                btv->tuner_type = 1;
-	
-        if (btv->type == BTTV_HAUPPAUGE878	||
-	    btv->type == BTTV_CONFERENCETV	||
-	    btv->type == BTTV_PIXVIEWPLAYTV	||
-	    btv->type == BTTV_AVERMEDIA98	||
-	    btv->type == BTTV_MAGICTVIEW061	||
-	    btv->type == BTTV_MAGICTVIEW063	||
-	    btv->type == BTTV_CHRONOS_VS2	||
-	    btv->type == BTTV_TYPHOON_TVIEW	||
-	    btv->type == BTTV_PXELVWPLTVPRO     ||
-	    btv->type == BTTV_WINFAST2000) {
-                btv->pll.pll_ifreq=28636363;
-                btv->pll.pll_crystal=BT848_IFORM_XT0;
-        }
 
-	if (btv->tuner_type != -1) 
+
+	/* pll configuration */
+        if (!(btv->id==848 && btv->revision==0x11)) {
+		/* defaults from card list */
+		if (PLL_28 == tvcards[btv->type].pll) {
+			btv->pll.pll_ifreq=28636363;
+			btv->pll.pll_crystal=BT848_IFORM_XT0;
+		}
+		/* insmod options can override */
+                switch (pll[btv->nr]) {
+                case 0: /* none */
+			btv->pll.pll_crystal = 0;
+			btv->pll.pll_ifreq   = 0;
+			btv->pll.pll_ofreq   = 0;
+                        break;
+                case 1: /* 28 MHz */
+                        btv->pll.pll_ifreq   = 28636363;
+			btv->pll.pll_ofreq   = 0;
+                        btv->pll.pll_crystal=BT848_IFORM_XT0;
+                        break;
+                case 2: /* 35 MHz */
+                        btv->pll.pll_ifreq   = 35468950;
+			btv->pll.pll_ofreq   = 0;
+                        btv->pll.pll_crystal=BT848_IFORM_XT1;
+                        break;
+                }
+        }
+	
+	
+	/* tuner configuration */
+ 	if (-1 != tvcards[btv->type].tuner_type)
+                btv->tuner_type = tvcards[btv->type].tuner_type;
+	if (btv->tuner_type != -1)
 		call_i2c_clients(btv,TUNER_SET_TYPE,&btv->tuner_type);
 
 	/* try to detect audio/fader chips */
@@ -3154,12 +3195,28 @@
 			request_module("tda985x");
 	}
 
-	if (tvcards[btv->type].tea63xx /* &&
-	    I2CRead(btv, I2C_TEA6300, "TEA63xx") >= 0 */) {
+	if (tvcards[btv->type].tda9875 &&
+	    I2CRead(btv, I2C_TDA9875, "TDA9875") >=0) {
+		if (autoload)
+			request_module("tda9875");
+	}
+
+	if (tvcards[btv->type].tda7432 &&
+	    I2CRead(btv, I2C_TDA7432, "TDA7432") >=0) {
+		if (autoload)
+			request_module("tda7432");
+	}
+
+	if (tvcards[btv->type].tea63xx) {
 		if (autoload)
 			request_module("tea6300");
 	}
 
+	if (tvcards[btv->type].tea64xx) {
+		if (autoload)
+			request_module("tea6420");
+	}
+
 	if (tvcards[btv->type].tuner != -1) {
 		if (autoload)
 			request_module("tuner");
@@ -3171,6 +3228,10 @@
 
 static void bt848_set_risc_jmps(struct bttv *btv, int flags)
 {
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&btv->s_lock, irq_flags);
+
 	if (-1 == flags) {
 		/* defaults */
 		flags = 0;
@@ -3242,7 +3303,11 @@
 		btv->risc_jmp[11]=cpu_to_le32(virt_to_bus(btv->risc_jmp+12));
 	}
 
-	btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
+	if (btv->gq_start) {
+		btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP|(0x8<<16)|BT848_RISC_IRQ);
+	} else {
+		btv->risc_jmp[12]=cpu_to_le32(BT848_RISC_JUMP);
+	}
 	btv->risc_jmp[13]=cpu_to_le32(virt_to_bus(btv->risc_jmp));
 
 	/* enable cpaturing and DMA */
@@ -3253,18 +3318,17 @@
 		bt848_dma(btv, 3);
 	else
 		bt848_dma(btv, 0);
+
+	spin_unlock_irqrestore(&btv->s_lock, irq_flags);
 }
 
-static int
-init_video_dev(struct bttv *btv)
+static int __init init_video_dev(struct bttv *btv)
 {
-        int num = btv - bttvs;
-
 	memcpy(&btv->video_dev,&bttv_template, sizeof(bttv_template));
 	memcpy(&btv->vbi_dev,&vbi_template, sizeof(vbi_template));
 	memcpy(&btv->radio_dev,&radio_template,sizeof(radio_template));
         
-	idcard(num);
+	idcard(btv);
         
 	if(video_register_device(&btv->video_dev,VFL_TYPE_GRABBER)<0)
 		return -1;
@@ -3273,7 +3337,7 @@
 	        video_unregister_device(&btv->video_dev);
 		return -1;
 	}
-	if (radio[num])
+	if (radio[btv->nr])
 	{
 		if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) 
                 {
@@ -3285,9 +3349,8 @@
         return 1;
 }
 
-static int init_bt848(int i)
+static int __init init_bt848(struct bttv *btv)
 {
-        struct bttv *btv = &bttvs[i];
 	int j;
 
 	btv->user=0; 
@@ -3297,14 +3360,14 @@
 	 * might help to make a new card work */
 	if (verbose >= 2)
 		printk("bttv%d: gpio: out_enable=0x%x, data=0x%x, in=0x%x\n",
-		       i,
+		       btv->nr,
 		       btread(BT848_GPIO_OUT_EN),
 		       btread(BT848_GPIO_DATA),
 		       btread(BT848_GPIO_REG_INP));
 
 	/* reset the bt848 */
 	btwrite(0, BT848_SRESET);
-	DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n",i,(unsigned long) btv->bt848_mem));
+	DEBUG(printk(KERN_DEBUG "bttv%d: bt848_mem: 0x%lx\n", btv->nr, (unsigned long) btv->bt848_mem));
 
 	/* not registered yet */
 	btv->video_dev.minor = -1;
@@ -3412,7 +3475,7 @@
 	btwrite(0x00, BT848_O_SCLOOP);
 
 	/* clear interrupt status */
-	btwrite(0xfffffUL, BT848_INT_STAT);
+	btwrite(~0x0UL, BT848_INT_STAT);
         
 	/* set interrupt mask */
 	btwrite(btv->triton1|
@@ -3452,7 +3515,6 @@
 		astat=stat&btread(BT848_INT_MASK);
 		if (!astat)
 			return;
-		btwrite(astat,BT848_INT_STAT);
 		IDEBUG(printk ("bttv%d: astat=%08x\n", btv->nr, astat));
 		IDEBUG(printk ("bttv%d:  stat=%08x\n", btv->nr, stat));
 
@@ -3561,6 +3623,7 @@
 			}
 			if (stat&(8<<28)) 
 			{
+				btv->gq_start = 0;
 				btv->gq_grab = btv->gqueue[btv->gq_out++];
 				btv->gq_out  = btv->gq_out % MAX_GBUFFERS;
 				if (debug)
@@ -3613,7 +3676,9 @@
 		{
 			IDEBUG(printk ("bttv%d: IRQ_I2CDONE\n", btv->nr));
 		}
-    
+   
+		btwrite(astat,BT848_INT_STAT);
+ 
 		count++;
 		if (count > 10)
 			printk (KERN_WARNING "bttv%d: irq loop %d\n",
@@ -3633,7 +3698,76 @@
  *	Scan for a Bt848 card, request the irq and map the io memory 
  */
 
-int configure_bt848(struct pci_dev *dev, int bttv_num)
+static void __init bttv_remove(struct pci_dev *pci_dev)
+{
+        u8 command;
+        int j;
+        struct bttv *btv = pci_dev->driver_data;
+
+        /* unregister i2c_bus */
+        i2c_bit_del_bus(&btv->i2c_adap);
+
+        /* turn off all capturing, DMA and IRQs */
+        btand(~15, BT848_GPIO_DMA_CTL);
+
+        /* first disable interrupts before unmapping the memory! */
+        btwrite(0, BT848_INT_MASK);
+        btwrite(~0x0UL,BT848_INT_STAT);
+        btwrite(0x0, BT848_GPIO_OUT_EN);
+
+        /* disable PCI bus-mastering */
+        pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
+        /* Should this be &=~ ?? */
+        command&=~PCI_COMMAND_MASTER;
+        pci_write_config_byte(btv->dev, PCI_COMMAND, command);
+
+        /* unmap and free memory */
+        for (j = 0; j < gbuffers; j++)
+                if (btv->gbuf[j].risc)
+                        kfree(btv->gbuf[j].risc);
+        if (btv->gbuf)
+                kfree((void *) btv->gbuf);
+
+        if (btv->risc_scr_odd)
+                kfree((void *) btv->risc_scr_odd);
+
+        if (btv->risc_scr_even)
+                kfree((void *) btv->risc_scr_even);
+
+        DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp));
+        if (btv->risc_jmp)
+                kfree((void *) btv->risc_jmp);
+
+        DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf));
+        if (btv->vbibuf)
+                vfree((void *) btv->vbibuf);
+
+        free_irq(btv->irq,btv);
+        DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem));
+        if (btv->bt848_mem)
+                iounmap(btv->bt848_mem);
+
+        if(btv->video_dev.minor!=-1)
+                video_unregister_device(&btv->video_dev);
+        if(btv->vbi_dev.minor!=-1)
+                video_unregister_device(&btv->vbi_dev);
+        if (radio[btv->nr] && btv->radio_dev.minor != -1)
+                video_unregister_device(&btv->radio_dev);
+
+        release_mem_region(btv->bt848_adr,
+                           pci_resource_len(btv->dev,0));
+        /* wake up any waiting processes
+           because shutdown flag is set, no new processes (in this queue)
+           are expected
+        */
+        btv->shutdown=1;
+        wake_up(&btv->gpioq);
+
+        return;
+}
+
+
+static int __init bttv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id)
 {
 	int result;
 	unsigned char command;
@@ -3642,6 +3776,8 @@
         unsigned int cmd;
 #endif
 
+	printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num);
+
         btv=&bttvs[bttv_num];
         btv->dev=dev;
         btv->nr = bttv_num;
@@ -3657,15 +3793,15 @@
         btv->vbip=VBIBUF_SIZE;
 
 	init_waitqueue_head(&btv->gpioq);
+	btv->s_lock = SPIN_LOCK_UNLOCKED;
 	btv->shutdown=0;
 
         btv->id=dev->device;
         btv->irq=dev->irq;
-        btv->bt848_adr=pci_resource_start(dev, 0);
-
+	btv->bt848_adr=pci_resource_start(dev, 0);
 	if (pci_enable_device(dev))
 		return -EIO;
-	if (!request_mem_region(pci_resource_start(dev,0),
+	if (!request_mem_region(btv->bt848_adr,
 				pci_resource_len(dev,0),
 				"bttv")) {
 		return -EBUSY;
@@ -3689,29 +3825,7 @@
         cmd = (cmd | PCI_COMMAND_MEMORY ); 
         pci_write_config_dword(dev, PCI_COMMAND, cmd);
 #endif
-        
-        btv->pll.pll_crystal = 0;
-        btv->pll.pll_ifreq   = 0;
-        btv->pll.pll_ofreq   = 0;
-        btv->pll.pll_current = 0;
-        if (!(btv->id==848 && btv->revision==0x11)) {
-                switch (pll[btv->nr]) {
-                case 0:
-                        /* off */
-                        break;
-                case 1:
-                        /* 28 MHz crystal installed */
-                        btv->pll.pll_ifreq=28636363;
-                        btv->pll.pll_crystal=BT848_IFORM_XT0;
-                        break;
-                case 2:
-                        /* 35 MHz crystal installed */
-                        btv->pll.pll_ifreq=35468950;
-                        btv->pll.pll_crystal=BT848_IFORM_XT1;
-                        break;
-                }
-        }
-       
+
 #ifdef __sparc__
 	btv->bt848_mem=(unsigned char *)btv->bt848_adr;
 #else
@@ -3751,119 +3865,53 @@
                 if (!(command&BT878_EN_TBFX)) 
                 {
                         printk("bttv: 430FX compatibility could not be enabled\n");
+			free_irq(btv->irq,btv);
 			result = -1;
 			goto fail;
                 }
         }
+
+	dev->driver_data = btv;
+
+	if(init_bt848(btv) < 0) {
+		bttv_remove(dev);
+		return -EIO;
+	}
+
+	bttv_num++;
+
         return 0;
 	
  fail:
-	release_mem_region(pci_resource_start(btv->dev,0),
+	release_mem_region(btv->bt848_adr,
 			   pci_resource_len(btv->dev,0));
 	return result;
 }
 
-static int find_bt848(void)
-{
-        struct pci_dev *dev;
-        int result=0;
-
-        bttv_num=0;
-
-	pci_for_each_dev(dev) {
-                if (dev->vendor == PCI_VENDOR_ID_BROOKTREE)
-                        if ((dev->device == PCI_DEVICE_ID_BT848)||
-                            (dev->device == PCI_DEVICE_ID_BT849)||
-                            (dev->device == PCI_DEVICE_ID_BT878)||
-                            (dev->device == PCI_DEVICE_ID_BT879))
-                                result=configure_bt848(dev,bttv_num++);
-                if (result)
-                        return result;
-        }
-	if(bttv_num)
-		printk(KERN_INFO "bttv: %d Bt8xx card(s) found.\n", bttv_num);
-	return bttv_num;
-}
-
-static void release_bttv(void)
-{
-	u8 command;
-	int i,j;
-	struct bttv *btv;
-
-	for (i=0;i<bttv_num; i++) 
-	{
-		btv=&bttvs[i];
-
-    		/* unregister i2c_bus */
-                i2c_bit_del_bus(&btv->i2c_adap);
-
-		/* turn off all capturing, DMA and IRQs */
-		btand(~15, BT848_GPIO_DMA_CTL);
-
-		/* first disable interrupts before unmapping the memory! */
-		btwrite(0, BT848_INT_MASK);
-		btwrite(0xffffffffUL,BT848_INT_STAT);
-		btwrite(0x0, BT848_GPIO_OUT_EN);
-
-		/* disable PCI bus-mastering */
-		pci_read_config_byte(btv->dev, PCI_COMMAND, &command);
-		/* Should this be &=~ ?? */
-		command&=~PCI_COMMAND_MASTER;
-		pci_write_config_byte(btv->dev, PCI_COMMAND, command);
-    
-		/* unmap and free memory */
-		for (j = 0; j < gbuffers; j++)
-			if (btv->gbuf[j].risc)
-				kfree(btv->gbuf[j].risc);
-		if (btv->gbuf)
-		        kfree((void *) btv->gbuf);
+static struct pci_device_id bttv_pci_tbl[] __initdata = {
+        {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879,
+         PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+        {0,}
+};
 
-		if (btv->risc_scr_odd)
-			kfree((void *) btv->risc_scr_odd);
-			
-		if (btv->risc_scr_even)
-			kfree((void *) btv->risc_scr_even);
+MODULE_DEVICE_TABLE(pci, bttv_pci_tbl);
 
-		DEBUG(printk(KERN_DEBUG "free: risc_jmp: 0x%p.\n", btv->risc_jmp));
-		if (btv->risc_jmp)
-			kfree((void *) btv->risc_jmp);
-
-		DEBUG(printk(KERN_DEBUG "bt848_vbibuf: 0x%p.\n", btv->vbibuf));
-		if (btv->vbibuf)
-			vfree((void *) btv->vbibuf);
-
-
-		free_irq(btv->irq,btv);
-		DEBUG(printk(KERN_DEBUG "bt848_mem: 0x%p.\n", btv->bt848_mem));
-		if (btv->bt848_mem)
-			iounmap(btv->bt848_mem);
-
-		if(btv->video_dev.minor!=-1)
-			video_unregister_device(&btv->video_dev);
-		if(btv->vbi_dev.minor!=-1)
-			video_unregister_device(&btv->vbi_dev);
-		if (radio[btv->nr] && btv->radio_dev.minor != -1)
-			video_unregister_device(&btv->radio_dev);
-
-		release_mem_region(pci_resource_start(btv->dev,0),
-				   pci_resource_len(btv->dev,0));
-       		/* wake up any waiting processes
-		   because shutdown flag is set, no new processes (in this queue) 
-		   are expected
-		*/
-		btv->shutdown=1;
-		wake_up(&btv->gpioq);
-	}
-}
+static struct pci_driver bttv_pci_driver = {
+        name:"bttv",
+        id_table:bttv_pci_tbl,
+        probe:bttv_probe,
+        remove:bttv_remove,
+};
 
-#ifdef MODULE
-int init_module(void)
-#else
-int init_bttv_cards(struct video_init *unused)
-#endif
+static int __init bttv_init_module(void)
 {
-	int i;
+	bttv_num = 0;
 
 	printk(KERN_INFO "bttv: driver version %d.%d.%d loaded\n",
 	       (BTTV_VERSION_CODE >> 16) & 0xff,
@@ -3878,31 +3926,18 @@
 		       gbuffers,gbufsize/1024,gbuffers*gbufsize/1024);
 
 	handle_chipset();
-	if (find_bt848()<=0)
-		return -EIO;
-
-	/* initialize Bt848s */
-	for (i=0; i<bttv_num; i++) 
-	{
-		if (init_bt848(i)<0) 
-		{
-			release_bttv();
-			return -EIO;
-		} 
-	}
 
-	return 0;
+	return pci_module_init(&bttv_pci_driver);
 }
 
-
-#ifdef MODULE
-
-void cleanup_module(void)
+static void __exit bttv_cleanup_module(void)
 {
-        release_bttv();
+	pci_unregister_driver(&bttv_pci_driver);
+        return;
 }
 
-#endif
+module_init(bttv_init_module);
+module_exit(bttv_cleanup_module);
 
 /*
  * Local variables:
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/bttv.h linux/drivers/char/bttv.h
--- v2.3.99-pre8/linux/drivers/char/bttv.h	Wed Apr 26 16:34:07 2000
+++ linux/drivers/char/bttv.h	Mon May 22 09:50:53 2000
@@ -1,4 +1,4 @@
-/* 
+/*
     bttv - Bt848 frame grabber driver
 
     Copyright (C) 1996,97 Ralph Metzler (rjkm@thp.uni-koeln.de)
@@ -21,7 +21,7 @@
 #ifndef _BTTV_H_
 #define _BTTV_H_
 
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,25) 
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,28) 
 
 #include <linux/types.h>
 #include <linux/wait.h>
@@ -143,6 +143,8 @@
 
         int tuner_type;
         int channel;
+
+	spinlock_t s_lock;
         
         unsigned int nr;
 	unsigned short id;
@@ -183,7 +185,7 @@
 
 	struct bttv_gbuf *gbuf;
 	int gqueue[MAX_GBUFFERS];
-	int gq_in,gq_out,gq_grab;
+	int gq_in,gq_out,gq_grab,gq_start;
         char *fbuffer;
 
 	struct bttv_pll_info pll;
@@ -272,7 +274,13 @@
 #define BTTV_PXELVWPLTVPRO 0x25
 #define BTTV_MAGICTVIEW063 0x26
 #define BTTV_PINNACLERAVE  0x27
-
+#define BTTV_STB2          0x28
+#define BTTV_AVPHONE98     0x29
+#define BTTV_PV951         0x2a
+
+#define PLL_NONE 0
+#define PLL_28   1
+#define PLL_35   2
 
 #define AUDIO_TUNER        0x00
 #define AUDIO_RADIO        0x01
@@ -289,9 +297,11 @@
 #define TEA6300            0x04
 
 #define I2C_TSA5522        0xc2
+#define I2C_TDA7432        0x8a
+#define I2C_TDA8425        0x82
 #define I2C_TDA9840        0x84
 #define I2C_TDA9850        0xb6
-#define I2C_TDA8425        0x82
+#define I2C_TDA9875        0xb0
 #define I2C_HAUPEE         0xa0
 #define I2C_STBEE          0xae
 #define I2C_VHX            0xc0
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.3.99-pre8/linux/drivers/char/epca.c	Fri Mar 10 16:40:42 2000
+++ linux/drivers/char/epca.c	Mon May 15 12:13:10 2000
@@ -4080,9 +4080,10 @@
 	{ PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem },
 	{ PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx },
 	{ PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj },
-	{ 0, }, /* terminate list */
+	{ 0, }
 };
 
+MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
 
 int __init init_PCI (void)
 { /* Begin init_PCI */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/generic_serial.c linux/drivers/char/generic_serial.c
--- v2.3.99-pre8/linux/drivers/char/generic_serial.c	Tue Mar 14 19:10:39 2000
+++ linux/drivers/char/generic_serial.c	Sat May 20 10:50:59 2000
@@ -52,6 +52,10 @@
 
 #define RS_EVENT_WRITE_WAKEUP	1
 
+#ifdef MODULE
+MODULE_PARM(gs_debug, "i");
+#endif
+
 #ifdef DEBUG
 static void my_hd (unsigned char *addr, int len)
 {
@@ -209,12 +213,9 @@
 	if (!port || !port->xmit_buf || !tmp_buf)
 		return -EIO;
 
-	/* printk ("from_user = %d.\n", from_user); */
 	save_flags(flags);
 	if (from_user) {
-		/* printk ("Going into the semaphore\n"); */
 		down(&tmp_buf_sem);
-		/* printk ("got out of the semaphore\n"); */
 		while (1) {
 			c = count;
 
@@ -363,19 +364,14 @@
 	func_exit();
 		return -EINVAL;  /* This is an error which we don't know how to handle. */
 	}
-	gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 1\n");
 
 	rcib = gs_real_chars_in_buffer(port->tty);
 
-	gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 2\n");
-
 	if(rcib <= 0) {
 		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
 		func_exit();
 		return rv;
 	}
-	gs_dprintk (GS_DEBUG_FLUSH, "checkpoint 3\n");
-
 	/* stop trying: now + twice the time it would normally take +  seconds */
 	end_jiffies  = jiffies; 
 	if (timeout !=  MAX_SCHEDULE_TIMEOUT)
@@ -520,11 +516,10 @@
 	func_enter ();
 
 	tty = port->tty;
-	if (!tty) return;
+	if (!tty) 
+		return;
 
 	gs_shutdown_port (port);
-
-	/* gs_flush_buffer (tty); */
 	port->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE |GS_ACTIVE);
 	port->tty = NULL;
 	port->count = 0;
@@ -576,7 +571,6 @@
 		else
 			return -ERESTARTSYS;
 	}
-
 	gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); 
 
 	/*
@@ -599,7 +593,6 @@
 	}
 
 	gs_dprintk (GS_DEBUG_BTR, "after subtype\n");
-
 	/*
 	 * If non-blocking mode is set, or the port is not enabled,
 	 * then make the check up front and then exit.
@@ -613,7 +606,6 @@
 	}
 
 	gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); 
- 
 	if (port->flags & ASYNC_CALLOUT_ACTIVE) {
 		if (port->normal_termios.c_cflag & CLOCAL) 
 			do_clocal = 1;
@@ -622,8 +614,7 @@
 			do_clocal = 1;
 	}
 
-	gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n"); 
-
+	gs_dprintk (GS_DEBUG_BTR, "after clocal check.\n");
 	/*
 	 * Block waiting for the carrier detect and the line to become
 	 * free (i.e., not in use by the callout).  While we are in
@@ -632,10 +623,10 @@
 	 * exit, either normal or abnormal.
 	 */
 	retval = 0;
+	
 	add_wait_queue(&port->open_wait, &wait);
-
+	
 	gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 
-
 	cli();
 	if (!tty_hung_up_p(filp))
 		port->count--;
@@ -667,7 +658,7 @@
 	}
 	gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
 		    port->blocked_open);
-	current->state = TASK_RUNNING;
+	set_current_state (TASK_RUNNING);
 	remove_wait_queue(&port->open_wait, &wait);
 	if (!tty_hung_up_p(filp))
 		port->count++;
@@ -687,10 +678,8 @@
 	struct gs_port *port;
 
 	func_enter ();
-	port = (struct gs_port *) tty->driver_data;
 
-	gs_dprintk (GS_DEBUG_CLOSE, "tty=%p, port=%p port->tty=%p\n",
-	            tty, port, port->tty);
+	port = (struct gs_port *) tty->driver_data;
 
 	if(! port) {
 		func_exit();
@@ -703,9 +692,7 @@
 		port->tty = tty;
 	}
 
-
 	save_flags(flags); cli();
-
 	if (tty_hung_up_p(filp)) {
 		restore_flags(flags);
 		port->rd->hungup (port);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.3.99-pre8/linux/drivers/char/lp.c	Sat Feb 26 22:31:44 2000
+++ linux/drivers/char/lp.c	Mon May 22 09:50:55 2000
@@ -146,13 +146,6 @@
 
 static unsigned int lp_count = 0;
 
-/* Test if printer is ready */
-#define	LP_READY(status)	((status) & LP_PBUSY)
-/* Test if the printer is not acking the strobe */
-#define	LP_NO_ACKING(status)	((status) & LP_PACK)
-/* Test if the printer has error conditions */
-#define LP_NO_ERROR(status)	((status) & LP_PERRORP)
-
 #undef LP_DEBUG
 
 /* --- low-level port access ----------------------------------- */
@@ -265,6 +258,7 @@
 	parport_set_timeout (lp_table[minor].dev,
 			     lp_table[minor].timeout);
 
+	if ((retv = lp_check_status (minor)) == 0)
 	do {
 		/* Write the data. */
 		written = parport_write (port, kbuf, copy_size);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.3.99-pre8/linux/drivers/char/mem.c	Tue Apr 11 15:09:16 2000
+++ linux/drivers/char/mem.c	Mon May 15 11:19:26 2000
@@ -231,9 +231,10 @@
 {
 	unsigned long p = *ppos;
 	ssize_t read = 0;
-	ssize_t virtr;
+	ssize_t virtr = 0;
+	char * kbuf; /* k-addr because vread() takes vmlist_lock rwlock */
 		
-	if (p < (unsigned long) high_memory) { 
+	if (p < (unsigned long) high_memory) {
 		read = count;
 		if (count > (unsigned long) high_memory - p)
 			read = (unsigned long) high_memory - p;
@@ -258,11 +259,27 @@
 		count -= read;
 	}
 
-	virtr = vread(buf, (char *)p, count);
-	if (virtr < 0)
-		return virtr;
-	*ppos += p + virtr;
-	return virtr + read;
+	kbuf = (char *)__get_free_page(GFP_KERNEL);
+	if (!kbuf)
+		return -ENOMEM;
+	while (count > 0) {
+		int len = count;
+
+		if (len > PAGE_SIZE)
+			len = PAGE_SIZE;
+		len = vread(kbuf, (char *)p, len);
+		if (len && copy_to_user(buf, kbuf, len)) {
+			free_page((unsigned long)kbuf);
+			return -EFAULT;
+		}
+		count -= len;
+		buf += len;
+		virtr += len;
+		p += len;
+	}
+	free_page((unsigned long)kbuf);
+ 	*ppos = p;
+ 	return virtr + read;
 }
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/msp3400.c linux/drivers/char/msp3400.c
--- v2.3.99-pre8/linux/drivers/char/msp3400.c	Thu May 11 15:30:06 2000
+++ linux/drivers/char/msp3400.c	Mon May 15 12:06:25 2000
@@ -871,7 +871,7 @@
 		/* unmute */
 		msp3400c_setvolume(client, msp->left, msp->right);
 
-		if (msp->watch_stereo) 
+		if (msp->watch_stereo)
 			mod_timer(&msp->wake_stereo, jiffies+5*HZ);
 
 		if (debug)
@@ -1086,7 +1086,7 @@
 		msp3400c_settreble(client, msp->treble);
 		msp3400c_setvolume(client, msp->left, msp->right);
 
-		if (msp->watch_stereo) 
+		if (msp->watch_stereo)
 			mod_timer(&msp->wake_stereo, jiffies+HZ);
 
 		msp->active = 0;
@@ -1236,7 +1236,7 @@
 msp3400c_mixer_open(struct inode *inode, struct file *file)
 {
         int minor = MINOR(inode->i_rdev);
-	struct i2c_client *client = NULL;
+	struct i2c_client *client;
 	struct msp3400c *msp;
 	int i;
 
@@ -1246,12 +1246,12 @@
 		if (msp->mixer_num == minor) {
 			client = msps[i];
 			file->private_data = client;
-			goto match;
+			break;
 		}
 	}
-	return -ENODEV;
+	if (MSP3400_MAX == i)
+		return -ENODEV;
 
-match:
 	/* lock bttv in memory while the mixer is in use  */
 	if (client->adapter->inc_use)
 		client->adapter->inc_use(client->adapter);
@@ -1265,8 +1265,8 @@
 {
 	struct i2c_client *client = file->private_data;
 
-	if (client->adapter->inc_use) 
-		client->adapter->inc_use(client->adapter);
+	if (client->adapter->dec_use) 
+		client->adapter->dec_use(client->adapter);
         MOD_DEC_USE_COUNT;
         return 0;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/func.h linux/drivers/char/rio/func.h
--- v2.3.99-pre8/linux/drivers/char/rio/func.h	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/func.h	Sat May 20 10:51:00 2000
@@ -168,4 +168,6 @@
 extern int rio_ismodem (kdev_t device);
 extern void rio_udelay (int usecs);
 
+extern void rio_start_card_running (struct Host * HostP);
+
 #endif	/* __func_h_def */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/host.h linux/drivers/char/rio/host.h
--- v2.3.99-pre8/linux/drivers/char/rio/host.h	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/host.h	Sat May 20 10:51:00 2000
@@ -56,16 +56,16 @@
     uchar             	    Mode;      /* Control stuff */
     uchar                   Slot;      /* Slot */
     volatile caddr_t        Caddr;     /* KV address of DPRAM */
-    volatile struct DpRam   *CardP;    /* KV address of DPRAM, with overlay */
+    volatile struct DpRam  *CardP;     /* KV address of DPRAM, with overlay */
     paddr_t          	    PaddrP;    /* Phys. address of DPRAM */
     char                    Name[MAX_NAME_LEN];  /* The name of the host */
     uint            	    UniqueNum; /* host unique number */
-    spinlock_t		    HostLock;  /* Lock structure for MPX */
-    /*struct pci_devinfo	    PciDevInfo; *//* PCI Bus/Device/Function stuff */
+    spinlock_t	            HostLock;  /* Lock structure for MPX */
+    /*struct pci_devinfo    PciDevInfo; *//* PCI Bus/Device/Function stuff */
     /*struct lockb	    HostLock;  *//* Lock structure for MPX */
     uint                    WorkToBeDone; /* set to true each interrupt */
     uint                    InIntr;    /* Being serviced? */
-    uint                    IntSrvDone;	/* host's interrupt has been serviced */
+    uint                    IntSrvDone;/* host's interrupt has been serviced */
     int			    (*Copy)( caddr_t, caddr_t, int ); /* copy func */
     struct timer_list timer;
     /*
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/linux_compat.h linux/drivers/char/rio/linux_compat.h
--- v2.3.99-pre8/linux/drivers/char/rio/linux_compat.h	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/linux_compat.h	Sat May 20 10:51:00 2000
@@ -47,7 +47,6 @@
 
 #define SEM_SIGIGNORE 0x1234
 
-
 #ifdef DEBUG_SEM
 #define swait(a,b)      printk ("waiting:    " __FILE__ " line %d\n", __LINE__)
 #define ssignal(sem)    printk ("signalling: " __FILE__ " line %d\n", __LINE__)
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rio_linux.c linux/drivers/char/rio/rio_linux.c
--- v2.3.99-pre8/linux/drivers/char/rio/rio_linux.c	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/rio_linux.c	Sat May 20 10:55:25 2000
@@ -109,108 +109,6 @@
 more than 512 ports.... */
 
 
-/* ************************************************************** */
-/* * This section can be removed when 2.0 becomes outdated....  * */
-/* ************************************************************** */
-
-#if LINUX_VERSION_CODE < 0x020100    /* Less than 2.1.0 */
-#define TWO_ZERO
-#else
-#if LINUX_VERSION_CODE < 0x020209   /* less than 2.2.x */
-#warning "Please use a recent 2.2.x kernel. "
-#endif
-#endif
-
-
-#ifdef TWO_ZERO
-
-/* Here is the section that makes the 2.2 compatible driver source 
-   work for 2.0 too! We mostly try to adopt the "new thingies" from 2.2, 
-   and provide for compatibility stuff here if possible. */
-
-#include <linux/bios32.h>
-
-#define Get_user(a,b)                a = get_user(b)
-#define Put_user(a,b)                0,put_user(a,b)
-#define copy_to_user(a,b,c)          memcpy_tofs(a,b,c)
-
-static inline int copy_from_user(void *to,const void *from, int c) 
-{
-  memcpy_fromfs(to, from, c);
-  return 0;
-}
-
-#define pci_present                  pcibios_present
-#define pci_read_config_word         pcibios_read_config_word
-#define pci_read_config_dword        pcibios_read_config_dword
-
-static inline unsigned char get_irq (unsigned char bus, unsigned char fn)
-{
-  unsigned char t; 
-  pcibios_read_config_byte (bus, fn, PCI_INTERRUPT_LINE, &t);
-  return t;
-}
-
-static inline void *ioremap(unsigned long base, long length)
-{
-  if (base < 0x100000) return (void *)base;
-  return vremap (base, length);
-}
-
-#define my_iounmap(x, b)             (((long)x<0x100000)?0:vfree ((void*)x))
-
-#define capable(x)                   suser()
-
-#define queue_task                   queue_task_irq_off
-#define tty_flip_buffer_push(tty)    queue_task(&tty->flip.tqueue, &tq_timer)
-#define signal_pending(current)      (current->signal & ~current->blocked)
-#define schedule_timeout(to)         do {current->timeout = jiffies + (to);schedule ();} while (0)
-#define time_after(t1,t2)            (((long)t1-t2) > 0)
-
-
-#define test_and_set_bit(nr, addr)   set_bit(nr, addr)
-#define test_and_clear_bit(nr, addr) clear_bit(nr, addr)
-
-/* Not yet implemented on 2.0 */
-#define ASYNC_SPD_SHI  -1
-#define ASYNC_SPD_WARP -1
-
-
-/* Ugly hack: the driver_name doesn't exist in 2.0.x . So we define it
-   to the "name" field that does exist. As long as the assignments are
-   done in the right order, there is nothing to worry about. */
-#define driver_name           name 
-
-/* Should be in a header somewhere. They are in tty.h on 2.2 */
-#define TTY_HW_COOK_OUT       14 /* Flag to tell ntty what we can handle */
-#define TTY_HW_COOK_IN        15 /* in hardware - output and input       */
-
-/* The return type of a "close" routine. */
-#define INT                   void
-#define NO_ERROR              /* Nothing */
-
-#else
-
-/* The 2.2.x compatibility section. */
-#include <asm/uaccess.h>
-
-#define Get_user(a,b)         get_user(a,b)
-#define Put_user(a,b)         put_user(a,b)
-#define get_irq(pdev)         pdev->irq
-
-#define INT                   int
-#define NO_ERROR              0              
-
-#define my_iounmap(x,b)       (iounmap((char *)(b)))
-
-#endif
-
-/* ************************************************************** */
-/* *                End of compatibility section..              * */
-/* ************************************************************** */
-
-
-
 /* Why the hell am I defining these here? */
 #define RIO_TYPE_NORMAL 1
 #define RIO_TYPE_CALLOUT 2
@@ -373,55 +271,15 @@
   NULL
 };
 
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-#define DEBUG
-
-#ifdef DEBUG
-#define rio_dprintk(f, str...) if (rio_debug & f) printk (str)
-#else
-#define rio_dprintk(f, str...) /* nothing */
-#endif
-
-
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
-#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  " __FUNCTION__ "\n")
-
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
-                                  "(port %d)\n", port->line)
-
-
-
-
 /* 
  *  Firmware loader driver specific routines
  *
  */
 
 static struct file_operations rio_fw_fops = {
-	NULL,	/*	lseek	*/
-	NULL,	/*	read	*/
-	NULL,	/*	write	*/
-	NULL,	/*	readdir	*/
-	NULL,	/*	select	*/
-	rio_fw_ioctl,
-	NULL,	/*	mmap	*/
-	rio_fw_open,
-#ifndef TWO_ZERO
-	NULL,	/*	flush	*/
-#endif
-	rio_fw_release,
-	NULL,	/*	fsync	*/
-	NULL,	/*	fasync	*/
-	NULL,	/*	check_media_change	*/
-	NULL,	/*	revalidate	*/
+	ioctl:		rio_fw_ioctl,
+	open:		rio_fw_open,
+	release:	rio_fw_release,
 };
 
 struct miscdevice rio_fw_device = {
@@ -446,11 +304,11 @@
     KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
  
   if (!port) {
-    printk(badinfo, kdevname(device), routine);
+    printk (badinfo, kdevname(device), routine);
     return 1;
   }
   if (port->magic != RIO_MAGIC) {
-    printk(badmagic, kdevname(device), routine);
+    printk (badmagic, kdevname(device), routine);
     return 1;
   }
 
@@ -468,15 +326,15 @@
   unsigned char *addr = ad;
   
   for (i=0;i<len;i+=16) {
-    printk ("%08x ", (int) addr+i);
+    rio_dprintk (RIO_DEBUG_PARAM, "%08x ", (int) addr+i);
     for (j=0;j<16;j++) {
-      printk ("%02x %s", addr[j+i], (j==7)?" ":"");
+      rio_dprintk (RIO_DEBUG_PARAM, "%02x %s", addr[j+i], (j==7)?" ":"");
     }
     for (j=0;j<16;j++) {
       ch = addr[j+i];
-      printk ("%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
+      rio_dprintk (RIO_DEBUG_PARAM, "%c", (ch < 0x20)?'.':((ch > 0x7f)?'.':ch));
     }
-    printk ("\n");
+    rio_dprintk (RIO_DEBUG_PARAM, "\n");
   }
 }
 #else
@@ -568,21 +426,26 @@
 
 void rio_reset_interrupt (struct Host *HostP)
 {
+  func_enter();
+
   switch( HostP->Type ) {
   case RIO_AT:
   case RIO_MCA:
   case RIO_PCI:
     WBYTE(HostP->ResetInt , 0xff);
   }
+
+  func_exit();
 }
 
 
 static void rio_interrupt (int irq, void *ptr, struct pt_regs *regs)
 {
   struct Host *HostP;
+  func_enter ();
 
-  HostP = &p->RIOHosts[(long)ptr];
-  /*   func_enter ();  */
+  HostP = (struct Host*)ptr; /* &p->RIOHosts[(long)ptr]; */
+  
   rio_dprintk (RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", 
                irq, HostP->Ivec); 
 
@@ -627,7 +490,7 @@
     }
   }
 #endif
-
+  rio_dprintk (RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n"); 
   if (HostP->Ivec == irq) {
     /* Tell the card we've noticed the interrupt. */
     rio_reset_interrupt (HostP);
@@ -649,7 +512,7 @@
   clear_bit (RIO_BOARD_INTR_LOCK, &HostP->locks);
   rio_dprintk (RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", 
                irq, HostP->Ivec); 
-  /*  func_exit ();  */
+  func_exit ();
 }
 
 
@@ -657,7 +520,7 @@
 {
   func_enter ();
 
-  rio_interrupt (0, (void *)data, NULL);
+  rio_interrupt (0, &p->RIOHosts[data], NULL);
   p->RIOHosts[data].timer.expires = jiffies + rio_poll;
   add_timer (&p->RIOHosts[data].timer);
 
@@ -756,11 +619,11 @@
 #if 0
   port->gs.flags &= ~ GS_ACTIVE;
   if (!port->gs.tty) {
-    printk ("No tty.\n");
+    rio_dprintk (RIO_DBUG_TTY, "No tty.\n");
     return;
   }
   if (!port->gs.tty->termios) {
-    printk ("No termios.\n");
+    rio_dprintk (RIO_DEBUG_TTY, "No termios.\n");
     return;
   }
   if (port->gs.tty->termios->c_cflag & HUPCL) {
@@ -1000,6 +863,8 @@
 
   if (rio_debug & RIO_DEBUG_PROBE)
     my_hd ((char *)&vpdp, 0x20);
+  
+  func_exit();
 
   return &vpdp;
 }
@@ -1099,7 +964,7 @@
   /* However, the RIO driver allows users to configure their first
      RTA as the ports numbered 504-511. We therefore need to allocate 
      the whole range. :-(   -- REW */
-
+  
 #define RI_SZ   sizeof(struct rio_info)
 #define HOST_SZ sizeof(struct Host)
 #define PORT_SZ sizeof(struct Port *)
@@ -1138,11 +1003,20 @@
     port->gs.close_delay = HZ/2;
     port->gs.closing_wait = 30 * HZ;
     port->gs.rd = &rio_real_driver;
+
+    /*
+     * Initializing wait queue
+     */
+    init_waitqueue_head(&port->gs.open_wait);
+    init_waitqueue_head(&port->gs.close_wait); 
+
   }
 #else
   /* We could postpone initializing them to when they are configured. */
 #endif
 
+
+  
   if (rio_debug & RIO_DEBUG_INIT) {
     my_hd (&rio_real_driver, sizeof (rio_real_driver));
   }
@@ -1166,7 +1040,6 @@
 }
 
 
-#ifdef MODULE
 static void rio_release_drivers(void)
 {
   func_enter();
@@ -1176,7 +1049,6 @@
   tty_unregister_driver (&rio_driver);
   func_exit();
 }
-#endif
 
 #ifdef TWO_ZERO
 #define PDEV unsigned char pci_bus, unsigned pci_fun
@@ -1213,7 +1085,7 @@
   unsigned int t;
 
 #define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x00260000
+#define CNTRL_REG_GOODVALUE     0x18260000
 
   pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
   hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
@@ -1294,7 +1166,6 @@
       pci_read_config_dword (pdev, 0x2c, &tint);
       tshort = (tint >> 16) & 0xffff;
       rio_dprintk (RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
-      /* rio_dprintk (RIO_DEBUG_PROBE, "pdev = %d/%d  (%x)\n", pdev, tint); */ 
       if (tshort != 0x0100) {
         rio_dprintk (RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", 
                     tshort);
@@ -1307,49 +1178,51 @@
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
       hp->Ivec = get_irq (pdev);
-      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      if (((1 << hp->Ivec) & rio_irqmask) == 0)
+              hp->Ivec = 0;
       hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy; 
-      hp->Mode  = RIO_PCI_DEFAULT_MODE;
- 
+      hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
+      rio_reset_interrupt (hp);
+      rio_start_card_running (hp);
+
       rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
                    (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
                    p->RIOHosts[p->RIONumHosts].Caddr);
       if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
                         p->RIOHosts[p->RIONumHosts].Caddr, 
                         RIO_PCI, 0 ) == RIO_SUCCESS) {
-        WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
-        p->RIOHosts[p->RIONumHosts].UniqueNum  =
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
-          ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
-        rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
-                   p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-#if 1
-        fix_rio_pci (pdev);
-#endif
-        p->RIOLastPCISearch = RIO_SUCCESS;
-        p->RIONumHosts++;
-        found++;
+              rio_dprintk (RIO_DEBUG_INIT, "Done RIOBoardTest\n");
+              WBYTE(p->RIOHosts[p->RIONumHosts].ResetInt, 0xff);
+              p->RIOHosts[p->RIONumHosts].UniqueNum  =
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[0]) &0xFF)<< 0)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[1]) &0xFF)<< 8)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[2]) &0xFF)<<16)|
+                      ((RBYTE(p->RIOHosts[p->RIONumHosts].Unique[3]) &0xFF)<<24);
+              rio_dprintk (RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n",
+                           p->RIOHosts[p->RIONumHosts].UniqueNum);
+              
+              fix_rio_pci (pdev);
+              p->RIOLastPCISearch = RIO_SUCCESS;
+              p->RIONumHosts++;
+              found++;
       } else {
-        my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
-                    p->RIOHosts[p->RIONumHosts].Caddr);
+              my_iounmap (p->RIOHosts[p->RIONumHosts].PaddrP, 
+                          p->RIOHosts[p->RIONumHosts].Caddr);
       }
-
+      
 #ifdef TWO_ZERO
     }  /* We have two variants with the opening brace, so to prevent */
 #else
     }  /* Emacs from getting confused we have two closing braces too. */
 #endif
     
-
     /* Then look for the older PCI card.... : */
 #ifndef TWO_ZERO
 
+
   /* These older PCI cards have problems (only byte-mode access is
      supported), which makes them a bit awkward to support. 
      They also have problems sharing interrupts. Be careful. 
@@ -1374,15 +1247,21 @@
       hp = &p->RIOHosts[p->RIONumHosts];
       hp->PaddrP =  tint & PCI_BASE_ADDRESS_MEM_MASK;
       hp->Ivec = get_irq (pdev);
-      if (((1 << hp->Ivec) & rio_irqmask) == 0) hp->Ivec = 0;
+      if (((1 << hp->Ivec) & rio_irqmask) == 0) 
+      	hp->Ivec = 0;
       hp->Ivec |= 0x8000; /* Mark as non-sharable */
       hp->CardP	= (struct DpRam *)
       hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
       hp->Type  = RIO_PCI;
       hp->Copy  = rio_pcicopy;
-      hp->Mode  = RIO_PCI_DEFAULT_MODE;
- 
-      rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
+      hp->Mode  = RIO_PCI_BOOT_FROM_RAM;
+
+      rio_dprintk (RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
+      rio_dprintk (RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
+
+      rio_reset_interrupt (hp);
+      rio_start_card_running (hp);
+       rio_dprintk (RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n",
                    (void *)p->RIOHosts[p->RIONumHosts].PaddrP,
                    p->RIOHosts[p->RIONumHosts].Caddr);
       if (RIOBoardTest( p->RIOHosts[p->RIONumHosts].PaddrP,
@@ -1425,11 +1304,15 @@
     hp->CardP = (struct DpRam *)
     hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
     hp->Type = RIO_AT;
-    hp->Copy = rio_pcicopy;
+    hp->Copy = rio_pcicopy; /* AT card PCI???? - PVDL
+                             * -- YES! this is now a normal copy. Only the 
+                             * old PCI card uses the special PCI copy. 
+                             * Moreover, the ISA card will work with the 
+                             * special PCI copy anyway. -- REW */
     hp->Mode = 0;
 
     vpdp = get_VPD_PROM (hp);
-
+    rio_dprintk (RIO_DEBUG_PROBE, "Got VPD ROM\n");
     okboard = 0;
     if ((strncmp (vpdp->identifier, RIO_ISA_IDENT, 16) == 0) ||
         (strncmp (vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) ||
@@ -1460,11 +1343,21 @@
     if (hp->Ivec) {
       int mode = SA_SHIRQ;
       if (hp->Ivec & 0x8000) {mode = 0; hp->Ivec &= 0x7fff;}
-      if (request_irq (hp->Ivec, rio_interrupt, mode, "rio", (void *)i)) {
-        printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
-        hp->Ivec = 0;
+      rio_dprintk (RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp,hp->Ivec, hp->Mode);
+      retval = request_irq (hp->Ivec, rio_interrupt, mode, "rio", hp);
+      rio_dprintk (RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
+      if (retval) {
+              printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
+              hp->Ivec = 0;
       }
       rio_dprintk (RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
+      if (hp->Ivec != 0){
+              rio_dprintk (RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n"); 
+              hp->Mode |= RIO_PCI_INT_ENABLE;
+      } else
+              hp->Mode &= !RIO_PCI_INT_ENABLE;
+      rio_dprintk (RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
+      rio_start_card_running (hp);
     }
     /* Init the timer "always" to make sure that it can safely be 
        deleted when we unload... */
@@ -1481,7 +1374,7 @@
   }
 
   if (found) {
-    printk (KERN_INFO "rio: total of %d boards detected.\n", found);
+    rio_dprintk (RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
 
     if (misc_register(&rio_fw_device) < 0) {
       printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
@@ -1506,7 +1399,7 @@
   for (i=0,hp=p->RIOHosts;i<p->RIONumHosts;i++, hp++) {
     RIOHostReset (hp->Type, hp->CardP, hp->Slot);
     if (hp->Ivec) {
-      free_irq (hp->Ivec, (void *)i);
+      free_irq (hp->Ivec, hp);
       rio_dprintk (RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
     }
     /* It is safe/allowed to del_timer a non-active timer */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rio_linux.h linux/drivers/char/rio/rio_linux.h
--- v2.3.99-pre8/linux/drivers/char/rio/rio_linux.h	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/rio_linux.h	Sun May 21 20:55:06 2000
@@ -23,13 +23,13 @@
  *  Version 1.0 -- July, 1999. 
  * 
  */
+#include <linux/config.h>
 
 #define RIO_NBOARDS        4
 #define RIO_PORTSPERBOARD 128
 #define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
 
 #ifdef __KERNEL__
-#include <linux/config.h>
 
 #define RIO_MAGIC 0x12345678
 
@@ -158,5 +158,30 @@
 #else
 #define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
 #define rio_memcpy_fromio                      memcpy_fromio
+#endif
+
+#define DEBUG
+
+
+/* 
+   This driver can spew a whole lot of debugging output at you. If you
+   need maximum performance, you should disable the DEBUG define. To
+   aid in debugging in the field, I'm leaving the compile-time debug
+   features enabled, and disable them "runtime". That allows me to
+   instruct people with problems to enable debugging without requiring
+   them to recompile... 
+*/
+
+#ifdef DEBUG
+#define rio_dprintk(f, str...) if (rio_debug & f) printk (str)
+#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ "\n")
+#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  " __FUNCTION__ "\n")
+#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter " __FUNCTION__ \
+                                   "(port %d)\n", port->line)
+#else
+#define rio_dprintk(f, str...) /* nothing */
+#define func_enter()
+#define func_exit()
+#define func_enter2()
 #endif
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rioboot.c linux/drivers/char/rio/rioboot.c
--- v2.3.99-pre8/linux/drivers/char/rio/rioboot.c	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/rioboot.c	Sun May 21 20:55:06 2000
@@ -81,7 +81,6 @@
 #include "cmdblk.h"
 #include "route.h"
 
-
 static uchar
 RIOAtVec2Ctrl[] =
 {
@@ -113,6 +112,8 @@
 {
 	int offset;
 
+	func_enter ();
+
 	/* Linux doesn't allow you to disable interrupts during a
 	   "copyin". (Crash when a pagefault occurs). */
 	/* disable(oldspl); */
@@ -126,6 +127,7 @@
 		rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code Too Large!\n"));
 		p->RIOError.Error = HOST_FILE_TOO_LARGE;
 		/* restore(oldspl); */
+		func_exit ();
 		return ENOMEM;
 	}
 
@@ -133,6 +135,7 @@
 		rio_dprint(RIO_DEBUG_BOOT, ("RTA Boot Code : BUSY BUSY BUSY!\n"));
 		p->RIOError.Error = BOOT_IN_PROGRESS;
 		/* restore(oldspl); */
+		func_exit ();
 		return EBUSY;
 	}
 
@@ -160,6 +163,7 @@
 		rio_dprint(RIO_DEBUG_BOOT, ("Bad data copy from user space\n"));
 		p->RIOError.Error = COPYIN_FAILED;
 		/* restore(oldspl); */
+		func_exit ();
 		return EFAULT;
 	}
 
@@ -171,9 +175,61 @@
 	p->RIOBootCount   = rbp->Count;
 
 	/* restore(oldspl); */
+	func_exit();
 	return 0;
 }
 
+void rio_start_card_running (struct Host * HostP)
+{
+	func_enter ();
+
+	switch ( HostP->Type ) {
+	case RIO_AT:
+		rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n"));
+		WBYTE(HostP->Control, 
+		      BOOT_FROM_RAM | EXTERNAL_BUS_ON
+		      | HostP->Mode
+		      | RIOAtVec2Ctrl[HostP->Ivec & 0xF] );
+		break;
+		
+#ifdef FUTURE_RELEASE
+	case RIO_MCA:
+				/*
+				** MCA handles IRQ vectors differently, so we don't write 
+				** them to this register.
+				*/
+		rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n"));
+		WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode);
+		break;
+
+	case RIO_EISA:
+				/*
+				** EISA is totally different and expects OUTBZs to turn it on.
+				*/
+		rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n");
+		OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM );
+		break;
+#endif
+
+	case RIO_PCI:
+				/*
+				** PCI is much the same as MCA. Everything is once again memory
+				** mapped, so we are writing to memory registers instead of io
+				** ports.
+				*/
+		rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n"));
+		WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
+		break;
+	default:
+		rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type));
+		break;
+	}
+/* 
+	printk (KERN_INFO "Done with starting the card\n");
+	func_exit ();
+*/
+	return;
+}
 
 /*
 ** Load in the host boot code - load it directly onto all halted hosts
@@ -206,6 +262,10 @@
 	for ( host=0; host<p->RIONumHosts; host++ ) {
 		rio_dprint(RIO_DEBUG_BOOT, ("Attempt to boot host %d\n",host));
 		HostP = &p->RIOHosts[host];
+		
+		rio_dprint(RIO_DEBUG_BOOT,  ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
+		    HostP->Type, HostP->Mode, HostP->Ivec ) );
+
 
 		if ( (HostP->Flags & RUN_STATE) != RC_WAITING ) {
 			rio_dprint(RIO_DEBUG_BOOT, ("%s %d already running\n","Host",host));
@@ -233,6 +293,7 @@
 		if ( p->RIOConf.HostLoadBase < rbp->Count ) {
 			rio_dprint(RIO_DEBUG_BOOT, ("Bin too large\n"));
 			p->RIOError.Error = HOST_FILE_TOO_LARGE;
+			func_exit ();
 			return EFBIG;
 		}
 		/*
@@ -259,6 +320,7 @@
 			if ( !DownCode ) {
 				rio_dprint(RIO_DEBUG_BOOT, ("No system memory available\n"));
 				p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
+				func_exit ();
 				return ENOMEM;
 			}
 			bzero(DownCode, rbp->Count);
@@ -266,6 +328,7 @@
 			if ( copyin((int)rbp->DataP,DownCode,rbp->Count)==COPYFAIL ) {
 				rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
 				p->RIOError.Error = COPYIN_FAILED;
+				func_exit ();
 				return EFAULT;
 			}
 
@@ -276,6 +339,7 @@
 		else if ( copyin((int)rbp->DataP,StartP,rbp->Count)==COPYFAIL ) {
 			rio_dprint(RIO_DEBUG_BOOT, ("Bad copyin of host data\n"));
 			p->RIOError.Error = COPYIN_FAILED;
+			func_exit ();
 			return EFAULT;
 		}
 
@@ -405,47 +469,8 @@
 		rio_dprint(RIO_DEBUG_BOOT,  ("Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n",
 		    HostP->Type, HostP->Mode, HostP->Ivec ) );
 
-		switch ( HostP->Type ) {
-			case RIO_AT:
-				rio_dprint(RIO_DEBUG_BOOT, ("Start ISA card running\n"));
-				WBYTE(HostP->Control, 
-					BOOT_FROM_RAM | EXTERNAL_BUS_ON
-					| HostP->Mode
-					| RIOAtVec2Ctrl[HostP->Ivec & 0xF] );
-				break;
-
-#ifdef FUTURE_RELEASE
-			case RIO_MCA:
-				/*
-				** MCA handles IRQ vectors differently, so we don't write 
-				** them to this register.
-				*/
-				rio_dprint(RIO_DEBUG_BOOT, ("Start MCA card running\n"));
-				WBYTE(HostP->Control, McaTpBootFromRam | McaTpBusEnable | HostP->Mode);
-				break;
-
-			case RIO_EISA:
-				/*
-				** EISA is totally different and expects OUTBZs to turn it on.
-				*/
-				rio_dprint(RIO_DEBUG_BOOT, NULL,DBG_DAEMON,"Start EISA card running\n");
-				OUTBZ( HostP->Slot, EISA_CONTROL_PORT, HostP->Mode | RIOEisaVec2Ctrl[HostP->Ivec] | EISA_TP_RUN | EISA_TP_BUS_ENABLE | EISA_TP_BOOT_FROM_RAM );
-				break;
-#endif
+		rio_start_card_running(HostP);
 
-			case RIO_PCI:
-				/*
-				** PCI is much the same as MCA. Everything is once again memory
-				** mapped, so we are writing to memory registers instead of io
-				** ports.
-				*/
-				rio_dprint(RIO_DEBUG_BOOT, ("Start PCI card running\n"));
-				WBYTE(HostP->Control, PCITpBootFromRam | PCITpBusEnable | HostP->Mode);
-				break;
-			default:
-				rio_dprint(RIO_DEBUG_BOOT, ("Unknown host type %d\n",HostP->Type));
-				break;
-		}
 		rio_dprint(RIO_DEBUG_BOOT, ("Set control port\n"));
 
 		/*
@@ -453,9 +478,10 @@
 		** pointer:
 		*/
 		for ( wait_count=0; (wait_count<p->RIOConf.StartupTime)&&
-				(RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) {
+			(RWORD(HostP->__ParmMapR)==OldParmMap); wait_count++ ) {
 			rio_dprint(RIO_DEBUG_BOOT, ("Checkout %d, 0x%x\n",wait_count,RWORD(HostP->__ParmMapR)));
 			delay(HostP, HUNDRED_MS);
+
 		}
 
 		/*
@@ -613,6 +639,7 @@
 	p->RIOSystemUp++;
 	
 	rio_dprint(RIO_DEBUG_BOOT, ("Done everything %x\n", HostP->Ivec));
+	func_exit ();
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/riocmd.c linux/drivers/char/rio/riocmd.c
--- v2.3.99-pre8/linux/drivers/char/rio/riocmd.c	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/riocmd.c	Sun May 21 20:55:06 2000
@@ -43,7 +43,6 @@
 #include <asm/string.h>
 #include <asm/semaphore.h>
 
-
 #include <linux/termios.h>
 #include <linux/serial.h>
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rioctrl.c linux/drivers/char/rio/rioctrl.c
--- v2.3.99-pre8/linux/drivers/char/rio/rioctrl.c	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/rioctrl.c	Sun May 21 20:55:06 2000
@@ -201,6 +201,8 @@
 	int		retval = 0;
 	unsigned long flags;
 	
+	func_enter ();
+	
 	/* Confuse teh compiler to think that we've initialized these */
 	Host=0;
 	PortP = NULL;
@@ -1776,6 +1778,8 @@
 	}
 	rio_dprint(RIO_DEBUG_CTRL, ("INVALID DAEMON IOCTL 0x%x\n",cmd));
 	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
+
+	func_exit ();
 	return EINVAL;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/rioinit.c linux/drivers/char/rio/rioinit.c
--- v2.3.99-pre8/linux/drivers/char/rio/rioinit.c	Thu May 11 15:30:06 2000
+++ linux/drivers/char/rio/rioinit.c	Sat May 20 10:51:00 2000
@@ -1414,7 +1414,7 @@
 	    (int)p->RIOHosts, sizeof(struct Host) ) );
 
 	for( host=0; host<RIO_HOSTS; host++ ) {
-		p->RIOHosts[host].HostLock = SPIN_LOCK_UNLOCKED; /* Let the first guy takes it */
+		spin_lock_init (&p->RIOHosts[host].HostLock);
 		p->RIOHosts[host].timeout_id = 0; /* Let the first guy takes it */
 	}
 	/*
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/riotty.c linux/drivers/char/rio/riotty.c
--- v2.3.99-pre8/linux/drivers/char/rio/riotty.c	Thu May 11 15:30:07 2000
+++ linux/drivers/char/rio/riotty.c	Sun May 21 20:55:06 2000
@@ -89,7 +89,6 @@
 #include "list.h"
 #include "sam.h"
 
-
 #if 0
 static void ttyseth_pv(struct Port *, struct ttystatics *, 
 				struct termios *sg, int);
@@ -154,13 +153,21 @@
 	unsigned long flags;
 	int retval = 0;
 
+	func_enter ();
+
+	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
+	   is going to oops.
+	*/
+	tty->driver_data = NULL;
+        
 	SysPort = rio_minor (tty->device);
 	Modem   = rio_ismodem (tty->device);
 
 	if ( p->RIOFailed ) {
 		rio_dprint(RIO_DEBUG_TTY, ("System initialisation failed\n"));
 		pseterr(ENXIO);
-		return 0;
+		func_exit ();
+		return -ENXIO;
 	}
 
 	rio_dprint(RIO_DEBUG_TTY, ("port open SysPort %d (%s) (mapped:%d)\n",
@@ -176,22 +183,24 @@
 	if (SysPort >= RIO_PORTS) {	/* out of range ? */
 		rio_dprint(RIO_DEBUG_TTY, ("Illegal port number %d\n",SysPort));
 		pseterr(ENXIO);
-		return 0;
+		func_exit();
+		return -ENXIO;
 	}
 
 	/*
 	** Grab pointer to the port stucture
 	*/
 	PortP = p->RIOPortp[SysPort];	/* Get control struc */
-
+	rio_dprintk (RIO_DEBUG_TTY, "PortP: %p\n", PortP);
 	if ( !PortP->Mapped ) {	/* we aren't mapped yet! */
 		/*
 		** The system doesn't know which RTA this port
 		** corresponds to.
 		*/
 		rio_dprint(RIO_DEBUG_TTY, ("port not mapped into system\n"));
+		func_exit ();
 		pseterr(ENXIO);
-		return 0;
+		return -ENXIO;
 	}
 
 	tty->driver_data = PortP;
@@ -209,7 +218,8 @@
 	if ( (PortP->HostP->Flags & RUN_STATE) != RC_RUNNING ) {
 		rio_dprint(RIO_DEBUG_TTY, ("Host not running\n"));
 		pseterr(ENXIO);
-		return 0;
+		func_exit ();
+		return -ENXIO;
 	}
 
 	/*
@@ -224,12 +234,14 @@
 			do {
 				if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
 					rio_dprint(RIO_DEBUG_TTY, ("RTA EINTR in delay \n"));
+					func_exit ();
 					return -EINTR;
 				}
 				if (repeat_this -- <= 0) {
 					rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
 					RIOPreemptiveCmd(p, PortP, FCLOSE ); 
 					pseterr(EINTR);
+					func_exit ();
 					return -EIO;
 				}
 			} while(!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED));
@@ -237,6 +249,7 @@
 		} else {
 			rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
 			pseterr(ENXIO);
+			func_exit ();
 			return 0;
 		}
 	}
@@ -249,6 +262,7 @@
 	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
 	  if (!PortP->WaitUntilBooted) {
 	    rio_dprint(RIO_DEBUG_TTY, ("RTA never booted\n"));
+	    func_exit ();
 	    return -ENXIO;
 	  }
 
@@ -258,10 +272,12 @@
 	  */
 	  if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
 	    rio_dprint(RIO_DEBUG_TTY, ("RTA_wait_for_boot: EINTR in delay \n"));
+	    func_exit ();
 	    return -EINTR;
 	  }
 	  if (repeat_this -- <= 0) {
 	    rio_dprint(RIO_DEBUG_TTY, ("Waiting for RTA to boot timeout\n"));
+	    func_exit ();
 	    return -EIO;
 	  }
 	}
@@ -276,8 +292,10 @@
 	}
 #if 0
 	retval = gs_init_port(&PortP->gs);
-	if (retval)
-	  return retval;
+	if (retval){
+		func_exit ();
+		return retval;
+	}
 #endif
 
 	/*
@@ -306,6 +324,7 @@
 		rio_dprint(RIO_DEBUG_TTY, ("Port unmapped while closing!\n"));
 		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 		retval = -ENXIO;
+		func_exit ();
 		return retval;
 	}
 
@@ -375,6 +394,7 @@
 			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
 				rio_dprint(RIO_DEBUG_TTY, ("Waiting for open to finish broken by signal\n"));
 				RIOPreemptiveCmd(p, PortP, FCLOSE );
+				func_exit ();
 				return -EINTR;
 			}
 			rio_spin_lock_irqsave(&PortP->portSem, flags);
@@ -425,6 +445,7 @@
 					tp->tm.c_state &= ~WOPEN;
 					PortP->State &= ~RIO_WOPEN;
 					rio_spin_unlock_irqrestore(&PortP->portSem, flags);
+					func_exit ();
 					return -EINTR;
 				}
 			}
@@ -462,6 +483,7 @@
 
 	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
 	rio_dprint(RIO_DEBUG_TTY, ("Returning from open\n"));
+	func_exit ();
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rio/unixrup.h linux/drivers/char/rio/unixrup.h
--- v2.3.99-pre8/linux/drivers/char/rio/unixrup.h	Thu May 11 15:30:07 2000
+++ linux/drivers/char/rio/unixrup.h	Sat May 20 10:51:00 2000
@@ -49,7 +49,7 @@
     uint             Id;		/* Id number */
     uint             BaseSysPort;	/* SysPort of first tty on this RTA */
     uint             ModTypes;		/* Modules on this RTA */
-    spinlock_t       RupLock;		/* Lock structure for MPX */
+    spinlock_t	     RupLock;		/* Lock structure for MPX */
 /*    struct lockb     RupLock;	*/	/* Lock structure for MPX */
 };
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/rtc.c linux/drivers/char/rtc.c
--- v2.3.99-pre8/linux/drivers/char/rtc.c	Thu May 11 15:30:07 2000
+++ linux/drivers/char/rtc.c	Sat May 20 09:27:06 2000
@@ -760,7 +760,7 @@
 
 static void rtc_dropped_irq(unsigned long data)
 {
-	printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", rtc_freq);
+	unsigned long freq;
 
 	spin_lock_irq (&rtc_lock);
 
@@ -771,7 +771,12 @@
 	rtc_irq_data += ((rtc_freq/HZ)<<8);
 	rtc_irq_data &= ~0xff;
 	rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);	/* restart */
+
+	freq = rtc_freq;
+
 	spin_unlock_irq(&rtc_lock);
+
+	printk(KERN_INFO "rtc: lost some interrupts at %ldHz.\n", freq);
 
 	/* Now we have new data */
 	wake_up_interruptible(&rtc_wait);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/sh-sci.c linux/drivers/char/sh-sci.c
--- v2.3.99-pre8/linux/drivers/char/sh-sci.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/char/sh-sci.c	Sat May 20 12:05:30 2000
@@ -189,10 +189,35 @@
 	ctrl_out(smr_val, SCSMR);
 
 #if defined(CONFIG_SH_SCIF_SERIAL)
+#if defined(__sh3__)
+	{ /* For SH7709, SH7709A, SH7729 */
+		unsigned short data;
+
+		/* We need to set SCPCR to enable RTS/CTS */
+		data = ctrl_inw(SCPCR);
+		/* Clear out SCP7MD1,0, SCP6MD1,0, SCP4MD1,0*/
+		ctrl_outw(data&0x0fcf, SCPCR); 
+	}
+#endif
 	if (C_CRTSCTS(port->gs.tty))
 		fcr_val |= 0x08;
-	else
+	else {
+#if defined(__sh3__)
+		unsigned short data;
+
+		/* We need to set SCPCR to enable RTS/CTS */
+		data = ctrl_inw(SCPCR);
+		/* Clear out SCP7MD1,0, SCP4MD1,0,
+		   Set SCP6MD1,0 = {01} (output)  */
+		ctrl_outw((data&0x0fcf)|0x1000, SCPCR);
+
+		data = ctrl_inb(SCPDR);
+		/* Set /RTS2 (bit6) = 0 */
+		ctrl_outb(data&0xbf, SCPDR);
+#elif defined(__SH4__)
 		ctrl_outw(0x0080, SCSPTR); /* Set RTS = 1 */
+#endif
+	}
 	ctrl_out(fcr_val, SCFCR);
 #endif
 
@@ -721,7 +746,7 @@
 	int i;
 
 	for (i=SCI_ERI_IRQ; i<SCI_IRQ_END; i++)
-		set_ipr_data(i, SCI_IPR_OFFSET, SCI_PRIORITY);
+		set_ipr_data(i, SCI_IPR_ADDR, SCI_IPR_POS, SCI_PRIORITY);
 
 	port = &sci_ports[0];
 
@@ -789,6 +814,7 @@
 	while (!(status & SCI_TD_E));
 
 	ctrl_outb(c, SC_TDR);
+	ctrl_in(SC_SR);		/* Dummy read */
 	ctrl_out(SCI_TD_E_CLEAR, SC_SR);
 
 	restore_flags(flags);
@@ -817,6 +843,7 @@
 		}
 	} while (!(status & SCI_RD_F));
 	c = ctrl_inb(SC_RDR);
+	ctrl_in(SC_SR);		/* Dummy read */
 	ctrl_out(SCI_RDRF_CLEAR, SC_SR);
 	restore_flags(flags);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/sh-sci.h linux/drivers/char/sh-sci.h
--- v2.3.99-pre8/linux/drivers/char/sh-sci.h	Tue Apr 11 15:09:17 2000
+++ linux/drivers/char/sh-sci.h	Sat May 20 12:05:30 2000
@@ -56,7 +56,8 @@
 #define SCI_TEI_IRQ	26
 #define SCI_IRQ_END	27
 
-#define SCI_IPR_OFFSET	(16+4)
+#define SCI_IPR_ADDR	INTC_IPRB
+#define SCI_IPR_POS	1
 #endif
 
 #if defined(CONFIG_SH_SCIF_SERIAL)
@@ -69,12 +70,16 @@
 #define SC_RDR 0xA400015A
 #define SCFCR  (volatile unsigned char *)0xA400015C
 #define SCFDR  0xA400015E
-#undef  SCSPTR /* Is there any register for RTS?? */
+
+#undef  SCSPTR /* SH7709 doesn't have SCSPTR */
+#define SCPCR  0xA4000116 /* Instead, it has SCPCR and SCPDR */
+#define SCPDR  0xA4000136
 #undef  SCLSR
 
 #define SCSCR_INIT	0x30	/* TIE=0,RIE=0,TE=1,RE=1 */
 				/* 0x33 when external clock is used */
-#define SCI_IPR_OFFSET	(64+4)
+#define SCI_IPR_ADDR	INTC_IPRE
+#define SCI_IPR_POS	1
 
 #elif defined(__SH4__)
 #define SCSMR  (volatile unsigned short *)0xFFE80000
@@ -89,7 +94,8 @@
 #define SCLSR  0xFFE80024
 
 #define SCSCR_INIT	0x0038	/* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */
-#define SCI_IPR_OFFSET	(32+4)
+#define SCI_IPR_ADDR	INTC_IPRC
+#define SCI_IPR_POS	1
 
 #endif
 
@@ -187,8 +193,17 @@
  * -- Greg Banks 27Feb2000
  */
 
+/*
+ * XXX: Well, this is not relevant...
+ * Should we have config option for peripheral clock?
+ * Or we get the value from time.c.
+ */
 #if defined(__sh3__)
-#define PCLK           14745600
+#if defined(CONFIG_CPU_SUBTYPE_SH7709)
+#define PCLK           33333333
+#else
+#define PCLK           14745600	/* Isn't it 15MHz? */
+#endif
 #elif defined(__SH4__)
 #define PCLK           33333333
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/sx.c linux/drivers/char/sx.c
--- v2.3.99-pre8/linux/drivers/char/sx.c	Thu May 11 15:30:07 2000
+++ linux/drivers/char/sx.c	Sat May 20 10:51:00 2000
@@ -1079,7 +1079,7 @@
 	struct tty_struct *tty;
 	int copied=0;
 
-	/* func_enter2 (); */
+	func_enter2 ();
 	tty = port->gs.tty;
 	while (1) {
 		rx_op = sx_read_channel_byte (port, hi_rxopos);
@@ -1134,7 +1134,7 @@
 		/*    tty_schedule_flip (tty); */
 	}
 
-	/* func_exit (); */
+	func_exit ();
 }
 
 /* Inlined: it is called only once. Remove the inline if you add another 
@@ -2343,6 +2343,12 @@
 #ifdef NEW_WRITE_LOCKING
 			port->gs.port_write_sem = MUTEX;
 #endif
+			/*
+			 * Initializing wait queue
+			 */
+			init_waitqueue_head(&port->gs.open_wait);
+			init_waitqueue_head(&port->gs.close_wait); 		
+			
 			port++;
 		}
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda7432.c linux/drivers/char/tda7432.c
--- v2.3.99-pre8/linux/drivers/char/tda7432.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/tda7432.c	Mon May 15 12:06:25 2000
@@ -0,0 +1,505 @@
+/*
+ * For the STS-Thompson TDA7432 audio processor chip
+ * 
+ * Handles audio functions: volume, balance, tone, loudness
+ * This driver will not complain if used with any 
+ * other i2c device with the same address.
+ *
+ * Copyright (c) 2000 Eric Sandeen <eric_sandeen@bigfoot.com>
+ * This code is placed under the terms of the GNU General Public License
+ * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
+ * Which was based on tda8425.c by Greg Alexander (c) 1998
+ *
+ * OPTIONS:
+ * debug    - set to 1 if you'd like to see debug messages
+ *            set to 2 if you'd like to be inundated with debug messages
+ *
+ * loudness - set between 0 and 15 for varying degrees of loudness effect
+ *
+ * TODO:
+ *  Implement tone controls
+ *
+ *  Revision: 0.3 - Fixed silly reversed volume controls.  :)
+ *  Revision: 0.2 - Cleaned up #defines
+ *			fixed volume control
+ *                  Added I2C_DRIVERID_TDA7432
+ *			added loudness insmod control
+ *  Revision: 0.1 - initial version
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "bttv.h"
+#include "audiochip.h"
+
+/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */
+#ifndef I2C_DRIVERID_TDA7432
+  #define I2C_DRIVERID_TDA7432	27
+#endif
+
+
+MODULE_AUTHOR("Eric Sandeen <eric_sandeen@bigfoot.com>");
+MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip");
+
+MODULE_PARM(debug,"i");
+MODULE_PARM(loudness,"i");
+static int loudness = 0; /* disable loudness by default */
+static int debug = 0;	 /* insmod parameter */
+
+
+/* Address to scan (I2C address of this chip) */
+static unsigned short normal_i2c[] = {
+	I2C_TDA7432 >> 1,
+	I2C_CLIENT_END};
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
+static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short force[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static struct i2c_client_address_data addr_data = {
+	normal_i2c, normal_i2c_range, 
+	probe, probe_range, 
+	ignore, ignore_range, 
+	force
+};
+
+/* Structure of address and subaddresses for the tda7432 */
+
+struct tda7432 {
+	int addr;
+	int input;
+	int volume;
+	int tone;
+	int lf, lr, rf, rr;
+	int loud;
+};
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+#define dprintk  if (debug) printk
+#define d2printk if (debug > 1) printk
+
+/* The TDA7432 is made by STS-Thompson
+ * http://www.st.com
+ * http://us.st.com/stonline/books/pdf/docs/4056.pdf
+ *
+ * TDA7432: I2C-bus controlled basic audio processor
+ *
+ * The TDA7432 controls basic audio functions like volume, balance,
+ * and tone control (including loudness).  It also has four channel
+ * output (for front and rear).  Since most vidcap cards probably
+ * don't have 4 channel output, this driver will set front & rear
+ * together (no independent control).
+ */ 
+
+		/* Subaddresses for TDA7432 */
+
+#define TDA7432_IN	0x00 /* Input select                 */
+#define TDA7432_VL	0x01 /* Volume                       */
+#define TDA7432_TN	0x02 /* Bass, Treble (Tone)          */
+#define TDA7432_LF	0x03 /* Attenuation LF (Left Front)  */
+#define TDA7432_LR	0x04 /* Attenuation LR (Left Rear)   */
+#define TDA7432_RF	0x05 /* Attenuation RF (Right Front) */
+#define TDA7432_RR	0x06 /* Attenuation RR (Right Rear)  */
+#define TDA7432_LD	0x07 /* Loudness                     */
+
+
+		/* Masks for bits in TDA7432 subaddresses */
+
+/* Many of these not used - just for documentation */
+
+/* Subaddress 0x00 - Input selection and bass control */
+
+/* Bits 0,1,2 control input:
+ * 0x00 - Stereo input
+ * 0x02 - Mono input
+ * 0x03 - Mute
+ * Mono probably isn't used - I'm guessing only the stereo
+ * input is connected on most cards, so we'll set it to stereo.
+ * 
+ * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut
+ * Bit 4 controls bass range: 0/1 is extended/standard bass range
+ * 
+ * Highest 3 bits not used
+ */
+ 
+#define TDA7432_STEREO_IN	0
+#define TDA7432_MONO_IN		2	/* Probably won't be used */
+#define TDA7432_MUTE		3	/* Probably won't be used */
+#define TDA7432_BASS_SYM	1 << 3
+#define TDA7432_BASS_NORM	1 << 4
+
+/* Subaddress 0x01 - Volume */
+
+/* Lower 7 bits control volume from -79dB to +32dB in 1dB steps
+ * Recommended maximum is +20 dB
+ *
+ * +32dB: 0x00
+ * +20dB: 0x0c
+ *   0dB: 0x20
+ * -79dB: 0x6f
+ *
+ * MSB (bit 7) controls loudness: 1/0 is loudness on/off
+ */
+
+#define	TDA7432_VOL_0DB		0x20
+#define TDA7432_LD_ON		1 << 7
+
+
+/* Subaddress 0x02 - Tone control */ 
+
+/* Bits 0,1,2 control absolute treble gain from 0dB to 14dB
+ * 0x0 is 14dB, 0x7 is 0dB
+ *
+ * Bit 3 controls treble attenuation/gain (sign)
+ * 1 = gain (+)
+ * 0 = attenuation (-)
+ *
+ * Bits 4,5,6 control absolute bass gain from 0dB to 14dB
+ * (This is only true for normal base range, set in 0x00)
+ * 0x0 << 4 is 14dB, 0x7 is 0dB
+ * 
+ * Bit 7 controls bass attenuation/gain (sign)
+ * 1 << 7 = gain (+)
+ * 0 << 7 = attenuation (-) 
+ *
+ * Example:
+ * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble
+ */
+
+#define TDA7432_TREBLE_0DB		0xf 
+#define TDA7432_TREBLE			7
+#define TDA7432_TREBLE_GAIN		1 << 3
+#define TDA7432_BASS_0DB		0xf << 4
+#define TDA7432_BASS			7 << 4
+#define TDA7432_BASS_GAIN		1 << 7
+
+ 
+/* Subaddress 0x03 - Left  Front attenuation */
+/* Subaddress 0x04 - Left  Rear  attenuation */
+/* Subaddress 0x05 - Right Front attenuation */
+/* Subaddress 0x06 - Right Rear  attenuation */
+
+/* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB
+ * in 1.5dB steps.
+ *
+ * 0x00 is     0dB
+ * 0x1f is -37.5dB
+ *
+ * Bit 5 mutes that channel when set (1 = mute, 0 = unmute)
+ * We'll use the mute on the input, though (above) 
+ * Bits 6,7 unused
+ */
+
+#define TDA7432_ATTEN_0DB	0x00
+
+
+/* Subaddress 0x07 - Loudness Control */
+
+/* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps
+ * when bit 4 is NOT set
+ *
+ * 0x0 is   0dB
+ * 0xf is -15dB
+ *
+ * If bit 4 is set, then there is a flat attenuation according to
+ * the lower 4 bits, as above.
+ *
+ * Bits 5,6,7 unused
+ */
+ 
+ 
+
+/* Begin code */
+
+static int tda7432_write(struct i2c_client *client, int subaddr, int val)
+{
+	unsigned char buffer[2];
+	d2printk("tda7432: In tda7432_write\n");
+	dprintk("tda7432: Writing %d 0x%x\n", subaddr, val);
+	buffer[0] = subaddr;
+	buffer[1] = val;
+	if (2 != i2c_master_send(client,buffer,2)) {
+		printk(KERN_WARNING "tda7432: I/O error, trying (write %d 0x%x)\n",
+		       subaddr, val);
+		return -1;
+	}
+	return 0;
+}
+
+/* I don't think we ever actually _read_ the chip... */
+#if 0
+static int tda7432_read(struct i2c_client *client)
+{
+	unsigned char buffer;
+	d2printk("tda7432: In tda7432_read\n");
+	if (1 != i2c_master_recv(client,&buffer,1)) {
+		printk(KERN_WARNING "tda7432: I/O error, trying (read)\n");
+		return -1;
+	}
+	dprintk("tda7432: Read 0x%02x\n", buffer); 
+	return buffer;
+}
+#endif
+
+static int tda7432_set(struct i2c_client *client)
+{
+	struct tda7432 *t = client->data;
+	unsigned char buf[16];
+	d2printk("tda7432: In tda7432_set\n");
+	
+	dprintk(KERN_INFO 
+		"tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
+		t->input,t->volume,t->tone,t->lf,t->lr,t->rf,t->rr,t->loud);
+	buf[0]  = TDA7432_IN;
+	buf[1]  = t->input;
+	buf[2]  = t->volume;
+	buf[3]  = t->tone;
+	buf[4]  = t->lf;
+	buf[5]  = t->lr;
+	buf[6]  = t->rf;
+	buf[7]  = t->rr;
+	buf[8]  = t->loud;
+	if (9 != i2c_master_send(client,buf,9)) {
+		printk(KERN_WARNING "tda7432: I/O error, trying tda7432_set\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void do_tda7432_init(struct i2c_client *client)
+{
+	struct tda7432 *t = client->data;
+	d2printk("tda7432: In tda7432_init\n");
+
+	t->input  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
+		    TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
+		    TDA7432_BASS_NORM;   /* Normal bass range     */ 
+	t->volume = TDA7432_VOL_0DB;	 /* 0dB Volume            */
+	if (loudness)			 /* Turn loudness on?     */
+		t->volume |= TDA7432_LD_ON;	
+	t->tone   = TDA7432_TREBLE_0DB | /* 0dB Treble            */
+		    TDA7432_BASS_0DB; 	 /* 0dB Bass              */
+	t->lf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->lr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->rf     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->rr     = TDA7432_ATTEN_0DB;	 /* 0dB attenuation       */
+	t->loud   = loudness;		 /* insmod parameter      */
+
+	tda7432_set(client);
+}
+
+/* *********************** *
+ * i2c interface functions *
+ * *********************** */
+
+static int tda7432_attach(struct i2c_adapter *adap, int addr,
+			  unsigned short flags, int kind)
+{
+	struct tda7432 *t;
+	struct i2c_client *client;
+	d2printk("tda7432: In tda7432_attach\n");
+	client = kmalloc(sizeof *client,GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;		
+        memcpy(client,&client_template,sizeof(struct i2c_client));
+        client->adapter = adap;
+        client->addr = addr;
+	
+	client->data = t = kmalloc(sizeof *t,GFP_KERNEL);
+	if (!t)
+		return -ENOMEM;
+	memset(t,0,sizeof *t);
+	do_tda7432_init(client);
+	MOD_INC_USE_COUNT;
+	strcpy(client->name,"TDA7432");
+	printk(KERN_INFO "tda7432: init\n");
+
+	i2c_attach_client(client);
+	return 0;
+}
+
+static int tda7432_probe(struct i2c_adapter *adap)
+{
+	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+		return i2c_probe(adap, &addr_data, tda7432_attach);
+	return 0;
+}
+
+static int tda7432_detach(struct i2c_client *client)
+{
+	struct tda7432 *t  = client->data;
+
+	do_tda7432_init(client);
+	i2c_detach_client(client);
+	
+	kfree(t);
+	kfree(client);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int tda7432_command(struct i2c_client *client,
+			   unsigned int cmd, void *arg)
+{
+	struct tda7432 *t = client->data;
+	d2printk("tda7432: In tda7432_command\n");
+#if 0
+	__u16 *sarg = arg;
+#endif
+
+	switch (cmd) {
+	/* --- v4l ioctls --- */
+	/* take care: bttv does userspace copying, we'll get a
+	   kernel pointer here... */
+	
+	/* Query card - scale from TDA7432 settings to V4L settings */
+	case VIDIOCGAUDIO:
+	{
+		struct video_audio *va = arg;
+		dprintk("tda7432: VIDIOCGAUDIO\n");
+
+		va->flags |= VIDEO_AUDIO_VOLUME |
+			VIDEO_AUDIO_BASS |
+			VIDEO_AUDIO_TREBLE;
+
+		/* Master volume control
+		 * V4L volume is min 0, max 65535
+		 * TDA7432 Volume: 
+		 * Min (-79dB) is 0x6f
+		 * Max (+20dB) is 0x07
+		 * (Mask out bit 7 of vol - it's for the loudness setting)
+		 */
+
+		va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630;
+		
+		/* Balance depends on L,R attenuation
+		 * V4L balance is 0 to 65535, middle is 32768
+		 * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f
+		 * to scale up to V4L numbers, mult by 1057
+		 * attenuation exists for lf, lr, rf, rr
+		 * we use only lf and rf (front channels)
+		 */
+		 
+		if ( (t->lf) < (t->rf) )
+			/* right is attenuated, balance shifted left */
+			va->balance = (32768 - 1057*(t->rf));
+		else
+			/* left is attenuated, balance shifted right */
+			va->balance = (32768 + 1057*(t->lf));
+
+		/* Bass/treble */
+		va->bass = 32768;   /* brain hurts... set to middle for now */
+		va->treble = 32768; /* brain hurts... set to middle for now */
+		
+		break; /* VIDIOCGAUDIO case */
+	}
+
+	/* Set card - scale from V4L settings to TDA7432 settings */
+	case VIDIOCSAUDIO:
+	{
+		struct video_audio *va = arg;
+		dprintk("tda7432: VIDEOCSAUDIO\n");
+
+		t->volume = 0x6f - ( (va->volume)/630 );
+		
+		if (loudness)		/* Turn on the loudness bit */
+			t->volume |= TDA7432_LD_ON;
+		
+		if (va->balance < 32768) {
+			/* shifted to left, attenuate right */
+			t->rr = (32768 - va->balance)/1057;
+			t->rf = t->rr;
+		}
+		else {
+			/* shifted to right, attenuate left */
+			t->lf = (va->balance - 32768)/1057;
+			t->lr = t->lf;
+		}
+		
+		/* t->tone = 0xff; */ /* Brain hurts - no tone control for now... */
+
+		tda7432_write(client,TDA7432_VL, t->volume);
+		/* tda7432_write(client,TDA7432_TN, t->tone); */
+		tda7432_write(client,TDA7432_LF, t->lf);
+		tda7432_write(client,TDA7432_LR, t->lr);
+		tda7432_write(client,TDA7432_RF, t->rf);
+		tda7432_write(client,TDA7432_RR, t->rr);
+
+		break;
+
+	} /* end of VIDEOCSAUDIO case */
+
+	default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */
+
+		/* nothing */
+		d2printk("tda7432: Default\n");
+
+	} /* end of (cmd) switch */
+
+	return 0;
+}
+
+
+static struct i2c_driver driver = {
+        "i2c tda7432 driver",
+	I2C_DRIVERID_TDA7432,
+        I2C_DF_NOTIFY,
+	tda7432_probe,
+        tda7432_detach,
+        tda7432_command,
+};
+
+static struct i2c_client client_template =
+{
+        "(unset)",		/* name */
+        -1,
+        0,
+        0,
+        NULL,
+        &driver
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+int tda7432_init(void)
+#endif
+{
+
+	if ( (loudness < 0) || (loudness > 15) )
+	{
+		printk(KERN_ERR "tda7432: loudness parameter must be between 0 and 15\n");
+		return -EINVAL;
+	}
+
+
+	i2c_add_driver(&driver);
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	i2c_del_driver(&driver);
+}
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda8425.c linux/drivers/char/tda8425.c
--- v2.3.99-pre8/linux/drivers/char/tda8425.c	Tue Jan 11 22:31:40 2000
+++ linux/drivers/char/tda8425.c	Mon May 15 12:06:25 2000
@@ -31,7 +31,6 @@
 #include "audiochip.h"
 
 /* Addresses to scan */
-#define I2C_TDA8425        0x82
 static unsigned short normal_i2c[] = {
     I2C_TDA8425 >> 1,
     I2C_CLIENT_END};
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda985x.c linux/drivers/char/tda985x.c
--- v2.3.99-pre8/linux/drivers/char/tda985x.c	Tue Mar  7 14:32:25 2000
+++ linux/drivers/char/tda985x.c	Mon May 15 12:06:25 2000
@@ -13,6 +13,7 @@
  *
  * OPTIONS:
  * debug   - set to 1 if you'd like to see debug messages
+ *         - set to 2 if you'd like to be flooded with debug messages
  * chip    - set to 9850 or 9855 to select your chip (default 9855)
  *
  * TODO:
@@ -20,7 +21,8 @@
  *                            and unmote to fix. - Is this still here?
  *   Fine tune sound
  *   Get rest of capabilities into video_audio struct...
- * 
+ *
+ *  Revision  0.5 - cleaned up debugging messages, added debug level=2 
  *  Revision: 0.4 - check for correct chip= insmod value
  *                  also cleaned up comments a bit
  *  Revision: 0.3 - took out extraneous tda985x_write in tda985x_command
@@ -55,9 +57,10 @@
 #define I2C_TDA985x_H        0xb6
 static unsigned short normal_i2c[] = {I2C_CLIENT_END};
 static unsigned short normal_i2c_range[] = {
-    I2C_TDA985x_L >> 1,
-    I2C_TDA985x_H >> 1,
-    I2C_CLIENT_END};
+	I2C_TDA985x_L >> 1,
+	I2C_TDA985x_H >> 1,
+	I2C_CLIENT_END
+};
 static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
 static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
 static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
@@ -84,6 +87,7 @@
 static struct i2c_client client_template;
 
 #define dprintk  if (debug) printk
+#define d2printk if (debug == 2) printk
 
 /* The TDA9850 and TDA9855 are both made by Philips Semiconductor
  * http://www.semiconductors.philips.com
@@ -154,9 +158,9 @@
 #define TDA9855_AVL	1<<6 /* AVL, Automatic Volume Level */
 #define TDA9855_LOUD	1<<5 /* Loudness, 1==off */
 #define TDA9855_SUR	1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */
-				/* Bits 0 to 3 select various combinations
-                                 * of line in and line out, only the 
-                                 * interesting ones are defined */
+			     /* Bits 0 to 3 select various combinations
+                              * of line in and line out, only the 
+                              * interesting ones are defined */
 #define TDA9855_EXT	1<<2 /* Selects inputs LIR and LIL.  Pins 41 & 12 */
 #define TDA9855_INT	0    /* Selects inputs LOR and LOL.  (internal) */
 
@@ -213,8 +217,8 @@
 static int tda985x_write(struct i2c_client *client, int subaddr, int val)
 {
 	unsigned char buffer[2];
-	dprintk("In tda985x_write\n");
-	dprintk("Writing %d 0x%x\n", subaddr, val);
+	d2printk("tda985x: In tda985x_write\n");
+	dprintk("tda985x: Writing %d 0x%x\n", subaddr, val);
 	buffer[0] = subaddr;
 	buffer[1] = val;
 	if (2 != i2c_master_send(client,buffer,2)) {
@@ -228,12 +232,12 @@
 static int tda985x_read(struct i2c_client *client)
 {
 	unsigned char buffer;
-	dprintk("In tda985x_read\n");
+	d2printk("tda985x: In tda985x_read\n");
 	if (1 != i2c_master_recv(client,&buffer,1)) {
 		printk(KERN_WARNING "tda985x: I/O error, trying (read)\n");
 		return -1;
 	}
-	dprintk("Read 0x%02x\n", buffer); 
+	dprintk("tda985x: Read 0x%02x\n", buffer); 
 	return buffer;
 }
 
@@ -241,12 +245,12 @@
 {
 	struct tda985x *t = client->data;
 	unsigned char buf[16];
-	dprintk("In tda985x_set\n");
+	d2printk("tda985x: In tda985x_set\n");
 	
 	if (chip == 9855)
 	{
 		dprintk(KERN_INFO 
-			"tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
+			"tda985x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
 			t->rvol,t->lvol,t->bass,t->treble,t->sub,
 			t->c5,t->c6,t->c7,t->a1,t->a2,t->a3);
 		buf[0]  = TDA9855_VR;
@@ -262,7 +266,7 @@
 		buf[10] = t->a2;
 		buf[11] = t->a3;
 		if (12 != i2c_master_send(client,buf,12)) {
-			printk(KERN_WARNING "tda9855: I/O error, trying tda985x_set\n");
+			printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n");
 			return -1;
 		}
 	}
@@ -270,7 +274,7 @@
 	else if (chip == 9850)
 	{
         	dprintk(KERN_INFO 
-			"tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
+			"tda986x: tda985x_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
 	               	 t->c4,t->c5,t->c6,t->c7,t->a1,t->a2,t->a3);
 		buf[0]  = TDA9850_C4;
 		buf[1]  = t->c4;
@@ -281,7 +285,7 @@
 		buf[6]  = t->a2;
 		buf[7]  = t->a3;
 		if (8 != i2c_master_send(client,buf,8)) {
-			printk(KERN_WARNING "tda9850: I/O error, trying tda985x_set\n");
+			printk(KERN_WARNING "tda985x: I/O error, trying tda985x_set\n");
 			return -1;
 	        }
 	}
@@ -292,11 +296,11 @@
 static void do_tda985x_init(struct i2c_client *client)
 {
 	struct tda985x *t = client->data;
-	dprintk("In tda985x_init\n");
+	d2printk("tda985x: In tda985x_init\n");
 
 	if (chip == 9855)
 	{
-		printk("Using tda9855 options\n");
+		printk("tda985x: Using tda9855 options\n");
 		t->rvol = 0x6f;		/* 0dB */
 		t->lvol = 0x6f;		/* 0dB */
 		t->bass = 0x0e;		/* 0dB */
@@ -313,7 +317,7 @@
 
 	else if (chip == 9850)
 	{
-		printk("Using tda9850 options\n");
+		printk("tda985x: Using tda9850 options\n");
 		t->c4 = 0x08;		/* Set stereo noise thresh to nominal */
 		t->c5 = 0x08;		/* Set SAP noise threshold to nominal */
 		t->c6 = TDA985x_STEREO;	/* Select Stereo mode for decoder */
@@ -337,7 +341,7 @@
 {
 	struct tda985x *t;
 	struct i2c_client *client;
-	dprintk("In tda985x_attach\n");
+	d2printk("tda985x: In tda985x_attach\n");
 	client = kmalloc(sizeof *client,GFP_KERNEL);
 	if (!client)
 		return -ENOMEM;		
@@ -382,7 +386,7 @@
 			   unsigned int cmd, void *arg)
 {
 	struct tda985x *t = client->data;
-	dprintk("In tda985x_command...\n");
+	d2printk("tda985x: In tda985x_command\n");
 #if 0
 	__u16 *sarg = arg;
 #endif
@@ -394,7 +398,7 @@
 	case VIDIOCGAUDIO:
 	{
 		struct video_audio *va = arg;
-		dprintk("VIDIOCGAUDIO\n");
+		dprintk("tda985x: VIDIOCGAUDIO\n");
 		if (chip == 9855)
 		{
 			int left,right;
@@ -430,7 +434,7 @@
 	case VIDIOCSAUDIO:
 	{
 		struct video_audio *va = arg;
-		dprintk("VIDEOCSAUDIO...\n");
+		dprintk("tda985x: VIDEOCSAUDIO\n");
 		if (chip == 9855)
 		{
 			int left,right;
@@ -453,17 +457,17 @@
 
 		switch (va->mode) {
 			case VIDEO_SOUND_MONO:
-				dprintk("VIDEO_SOUND_MONO\n");
+				dprintk("tda985x: VIDEO_SOUND_MONO\n");
 				t->c6= TDA985x_MONO | (t->c6 & 0x3f);
 				tda985x_write(client,TDA985x_C6,t->c6);
 				break;
 			case VIDEO_SOUND_STEREO:
-				dprintk("VIDEO_SOUND_STEREO\n");
+				dprintk("tda985x: VIDEO_SOUND_STEREO\n");
 				t->c6= TDA985x_STEREO | (t->c6 & 0x3f);
 				tda985x_write(client,TDA985x_C6,t->c6); 
 				break;
 			case VIDEO_SOUND_LANG1:
-				dprintk("VIDEO_SOUND_LANG1\n");
+				dprintk("tda985x: VIDEO_SOUND_LANG1\n");
 				t->c6= TDA985x_SAP | (t->c6 & 0x3f);
 				tda985x_write(client,TDA985x_C6,t->c6);
 				break;
@@ -476,7 +480,7 @@
 	default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */
 
 		/* nothing */
-		dprintk("Default\n");
+		d2printk("tda985x: Default\n");
 
 	} /* end of (cmd) switch */
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tda9875.c linux/drivers/char/tda9875.c
--- v2.3.99-pre8/linux/drivers/char/tda9875.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/tda9875.c	Mon May 15 12:06:25 2000
@@ -0,0 +1,371 @@
+/*
+ * For the TDA9875 chip
+ * (The TDA9875 is used on the Diamond DTV2000 french version 
+ * Other cards probably use these chips as well.)
+ * This driver will not complain if used with any 
+ * other i2c device with the same address.
+ *
+ * Copyright (c) 2000 Guillamue Delvit based on Gerd Knorr source and
+ * Eric Sandeen 
+ * This code is placed under the terms of the GNU General Public License
+ * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
+ * Which was based on tda8425.c by Greg Alexander (c) 1998
+ *
+ * OPTIONS:
+ * debug   - set to 1 if you'd like to see debug messages
+ * 
+ *  Revision: 0.1 - original version
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "bttv.h"
+#include "audiochip.h"
+
+/* This driver ID is brand new, so define it if it's not in i2c-id.h yet */
+#ifndef I2C_DRIVERID_TDA9875
+  #define I2C_DRIVERID_TDA9875  28
+#endif
+
+
+MODULE_PARM(debug,"i");
+
+static int debug = 0;	/* insmod parameter */
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] =  {
+    I2C_TDA9875 >> 1,
+    I2C_CLIENT_END};
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
+static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short force[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static struct i2c_client_address_data addr_data = {
+	normal_i2c, normal_i2c_range, 
+	probe, probe_range, 
+	ignore, ignore_range, 
+	force
+};
+
+/* This is a superset of the TDA9875 */
+struct tda9875 {
+	int mode;
+	int rvol, lvol;
+	int bass, treble;
+};
+
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+#define dprintk  if (debug) printk
+
+/* The TDA9875 is made by Philips Semiconductor
+ * http://www.semiconductors.philips.com
+ * TDA9875: I2C-bus controlled DSP audio processor, FM demodulator
+ *
+ */ 
+
+		/* subaddresses for TDA9875 */
+#define TDA9875_MUT         0x12  /*General mute  (value --> 0b11001100*/
+#define TDA9875_CFG         0x01  /* Config register (value --> 0b00000000 */
+#define TDA9875_DACOS       0x13  /*DAC i/o select (ADC) 0b0000100*/
+#define TDA9875_LOSR        0x16  /*Line output select regirter 0b0100 0001*/
+
+#define TDA9875_CH1V        0x0c  /*Chanel 1 volume (mute)*/
+#define TDA9875_CH2V        0x0d  /*Chanel 2 volume (mute)*/
+#define TDA9875_SC1         0x14  /*SCART 1 in (mono)*/
+#define TDA9875_SC2         0x15  /*SCART 2 in (mono)*/
+
+#define TDA9875_ADCIS       0x17  /*ADC input select (mono) 0b0110 000*/
+#define TDA9875_AER         0x19  /*Audio effect (AVL+Pseudo) 0b0000 0110*/
+#define TDA9875_MCS         0x18  /*Main channel select (DAC) 0b0000100*/
+#define TDA9875_MVL         0x1a  /* Main volume gauche */
+#define TDA9875_MVR         0x1b  /* Main volume droite */
+#define TDA9875_MBA         0x1d  /* Main Basse */
+#define TDA9875_MTR         0x1e  /* Main treble */
+#define TDA9875_ACS         0x1f  /* Auxilary channel select (FM) 0b0000000*/
+#define TDA9875_AVL         0x20  /* Auxilary volume gauche */
+#define TDA9875_AVR         0x21  /* Auxilary volume droite */
+#define TDA9875_ABA         0x22  /* Auxilary Basse */
+#define TDA9875_ATR         0x23  /* Auxilary treble */
+
+#define TDA9875_MSR         0x02  /* Monitor select register */
+#define TDA9875_C1MSB       0x03  /* Carrier 1 (FM) frequency register MSB */
+#define TDA9875_C1MIB       0x04  /* Carrier 1 (FM) frequency register (16-8]b */
+#define TDA9875_C1LSB       0x05  /* Carrier 1 (FM) frequency register LSB */
+#define TDA9875_C2MSB       0x06  /* Carrier 2 (nicam) frequency register MSB */
+#define TDA9875_C2MIB       0x07  /* Carrier 2 (nicam) frequency register (16-8]b */
+#define TDA9875_C2LSB       0x08  /* Carrier 2 (nicam) frequency register LSB */
+#define TDA9875_DCR         0x09  /* Demodulateur configuration regirter*/
+#define TDA9875_DEEM        0x0a  /* FM de-emphasis regirter*/
+#define TDA9875_FMAT        0x0b  /* FM Matrix regirter*/
+
+/* values */
+#define TDA9875_MUTE_ON	    0xff /* general mute */
+#define TDA9875_MUTE_OFF    0xcc /* general no mute */
+
+
+
+/* Begin code */
+
+static int tda9875_write(struct i2c_client *client, int subaddr, int val)
+{
+	unsigned char buffer[2];
+	dprintk("In tda9875_write\n");
+	dprintk("Writing %d 0x%x\n", subaddr, val);
+	buffer[0] = subaddr;
+	buffer[1] = val;
+	if (2 != i2c_master_send(client,buffer,2)) {
+		printk(KERN_WARNING "tda9875: I/O error, trying (write %d 0x%x)\n",
+		       subaddr, val);
+		return -1;
+	}
+	return 0;
+}
+
+#if 0
+static int tda9875_read(struct i2c_client *client)
+{
+	unsigned char buffer;
+	dprintk("In tda9875_read\n");
+	if (1 != i2c_master_recv(client,&buffer,1)) {
+		printk(KERN_WARNING "tda9875: I/O error, trying (read)\n");
+		return -1;
+	}
+	dprintk("Read 0x%02x\n", buffer); 
+	return buffer;
+}
+#endif
+
+static void tda9875_set(struct i2c_client *client)
+{
+	struct tda9875 *tda = client->data;
+	
+	dprintk(KERN_DEBUG "tda9875_set(%04x,%04x,%04x,%04x)\n",tda->lvol,tda->rvol,tda->bass,tda->treble);
+	tda9875_write(client, TDA9875_MVL, tda->lvol / 600 - 84);
+	tda9875_write(client, TDA9875_MVR, tda->rvol / 600 -84);
+	tda9875_write(client, TDA9875_MBA, tda->bass / 2340 -12);
+	tda9875_write(client, TDA9875_MTR, tda->treble / 2621 -12);
+}
+
+static void do_tda9875_init(struct i2c_client *client)
+{
+	struct tda9875 *t = client->data;
+	dprintk("In tda9875_init\n"); 
+	tda9875_write(client, TDA9875_CFG, 0xd0 ); /*reg de config 0 (reset)*/
+    	tda9875_write(client, TDA9875_MSR, 0x03 );    /* Monitor 0b00000XXX*/
+	tda9875_write(client, TDA9875_C1MSB, 0x00 );  /*Car1(FM) MSB XMHz*/
+	tda9875_write(client, TDA9875_C1MIB, 0x00 );  /*Car1(FM) MIB XMHz*/
+	tda9875_write(client, TDA9875_C1LSB, 0x00 );  /*Car1(FM) LSB XMHz*/
+	tda9875_write(client, TDA9875_C2MSB, 0x00 );  /*Car2(NICAM) MSB XMHz*/
+	tda9875_write(client, TDA9875_C2MIB, 0x00 );  /*Car2(NICAM) MIB XMHz*/
+	tda9875_write(client, TDA9875_C2LSB, 0x00 );  /*Car2(NICAM) LSB XMHz*/
+	tda9875_write(client, TDA9875_DCR, 0x00 );    /*Demod config 0x00*/
+	tda9875_write(client, TDA9875_DEEM, 0x44 );   /*DE-Emph 0b0100 0100*/
+	tda9875_write(client, TDA9875_FMAT, 0x00 );   /*FM Matrix reg 0x00*/
+	tda9875_write(client, TDA9875_SC1, 0x00 );    /* SCART 1 (SC1)*/
+	tda9875_write(client, TDA9875_SC2, 0x01 );    /* SCART 2 (sc2)*/
+        
+	tda9875_write(client, TDA9875_CH1V, 0x10 );  /* Chanel volume 1 mute*/
+	tda9875_write(client, TDA9875_CH2V, 0x10 );  /* Chanel volume 2 mute */
+	tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/
+	tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/
+	tda9875_write(client, TDA9875_LOSR, 0x00 );  /* line out (in:mono)*/
+ 	tda9875_write(client, TDA9875_AER, 0x00 );   /*06 Effect (AVL+PSEUDO) */
+	tda9875_write(client, TDA9875_MCS, 0x44 );   /* Main ch select (DAC) */
+	tda9875_write(client, TDA9875_MVL, 0x03 );   /* Vol Main left 10dB */
+	tda9875_write(client, TDA9875_MVR, 0x03 );   /* Vol Main right 10dB*/
+	tda9875_write(client, TDA9875_MBA, 0x00 );   /* Main Bass Main 0dB*/
+	tda9875_write(client, TDA9875_MTR, 0x00 );   /* Main Treble Main 0dB*/
+	tda9875_write(client, TDA9875_ACS, 0x44 );   /* Aux chan select (dac)*/	
+	tda9875_write(client, TDA9875_AVL, 0x00 );   /* Vol Aux left 0dB*/
+	tda9875_write(client, TDA9875_AVR, 0x00 );   /* Vol Aux right 0dB*/
+	tda9875_write(client, TDA9875_ABA, 0x00 );   /* Aux Bass Main 0dB*/
+	tda9875_write(client, TDA9875_ATR, 0x00 );   /* Aux Aigus Main 0dB*/
+	
+	tda9875_write(client, TDA9875_MUT, 0xcc );   /* General mute  */
+        
+	t->mode=AUDIO_MUTE;
+	t->lvol=t->rvol =51000;  	/* 0dB */
+	t->bass=30420; 		/* 0dB */
+	t->treble=34073;  		/* 0dB */
+	tda9875_set(client);
+
+}
+
+
+/* *********************** *
+ * i2c interface functions *
+ * *********************** */
+
+static int tda9875_attach(struct i2c_adapter *adap, int addr,
+			  unsigned short flags, int kind)
+{
+	struct tda9875 *t;
+	struct i2c_client *client;
+	dprintk("In tda9875_attach\n");
+	client = kmalloc(sizeof *client,GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;		
+        memcpy(client,&client_template,sizeof(struct i2c_client));
+        client->adapter = adap;
+        client->addr = addr;
+	
+	client->data = t = kmalloc(sizeof *t,GFP_KERNEL);
+	if (!t)
+		return -ENOMEM;
+	memset(t,0,sizeof *t);
+	do_tda9875_init(client);
+	MOD_INC_USE_COUNT;
+	strcpy(client->name,"TDA9875");
+	printk(KERN_INFO "tda9875: init\n");
+
+	i2c_attach_client(client);
+	return 0;
+}
+
+static int tda9875_probe(struct i2c_adapter *adap)
+{
+	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+		return i2c_probe(adap, &addr_data, tda9875_attach);
+	return 0;
+}
+
+static int tda9875_detach(struct i2c_client *client)
+{
+	struct tda9875 *t  = client->data;
+
+	do_tda9875_init(client);
+	i2c_detach_client(client);
+	
+	kfree(t);
+	kfree(client);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int tda9875_command(struct i2c_client *client,
+				unsigned int cmd, void *arg)
+{
+	struct tda9875 *t = client->data;
+
+	dprintk("In tda9875_command...\n"); 
+
+	switch (cmd) {	
+        /* --- v4l ioctls --- */
+	/* take care: bttv does userspace copying, we'll get a
+	   kernel pointer here... */
+	case VIDIOCGAUDIO:
+	{
+		struct video_audio *va = arg;
+		int left,right;
+
+		dprintk("VIDIOCGAUDIO\n");
+
+		va->flags |= VIDEO_AUDIO_VOLUME |
+			VIDEO_AUDIO_BASS |
+			VIDEO_AUDIO_TREBLE;
+
+		/* min is -84 max is 24 */
+		left = (t->lvol+85)*600;
+		right = (t->rvol+85)*600;
+		va->volume=MAX(left,right);
+		va->balance=(32768*MIN(left,right))/
+			(va->volume ? va->volume : 1);
+		va->balance=(left<right)?
+			(65535-va->balance) : va->balance;
+		va->bass = (t->bass+13)*2340;     /* min -12 max +15 */
+		va->treble = (t->treble+13)*2621;/* min -12 max +12 */
+
+		va->mode |= VIDEO_SOUND_MONO;
+
+
+		break; /* VIDIOCGAUDIO case */
+	}
+
+	case VIDIOCSAUDIO:
+	{
+		struct video_audio *va = arg;
+		int left,right;
+
+		dprintk("VIDEOCSAUDIO...\n"); 
+		left = (MIN(65536 - va->balance,32768) *
+			va->volume) / 32768;
+		right = (MIN(va->balance,32768) *
+			 va->volume) / 32768;
+		t->lvol = left/600-84;
+		t->rvol = right/600-84;
+		t->bass = va->bass/2340-12;
+		t->treble = va->treble/2621-12;
+		tda9875_set(client);
+
+		break;
+
+	} /* end of VIDEOCSAUDIO case */
+
+	default: /* Not VIDEOCGAUDIO or VIDEOCSAUDIO */
+
+		/* nothing */
+		dprintk("Default\n");
+
+	} /* end of (cmd) switch */
+
+	return 0;
+}
+
+
+static struct i2c_driver driver = {
+        "i2c tda9875 driver",
+        I2C_DRIVERID_TDA9875, /* Get new one for TDA9875 */
+        I2C_DF_NOTIFY,
+	tda9875_probe,
+        tda9875_detach,
+        tda9875_command,
+};
+
+static struct i2c_client client_template =
+{
+        "(unset)",		/* name */
+        -1,
+        0,
+        0,
+        NULL,
+        &driver
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+int tda9875_init(void)
+#endif
+{
+	i2c_add_driver(&driver);
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	i2c_del_driver(&driver);
+}
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
+
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tea6420.c linux/drivers/char/tea6420.c
--- v2.3.99-pre8/linux/drivers/char/tea6420.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/tea6420.c	Mon May 15 12:06:25 2000
@@ -0,0 +1,268 @@
+/*
+ * for the TEA6420 chip (only found on 3DFX (STB) TV/FM cards to the best
+ * of my knowledge)
+ * Copyright (C) 2000 Dave Stuart <justdave@ynn.com>
+ * This code is placed under the terms of the GNU General Public License
+ * Code liberally copied from tea6300 by . . .
+ *
+ * Copyright (c) 1998 Greg Alexander <galexand@acm.org>
+ * This code is placed under the terms of the GNU General Public License
+ * Code liberally copied from msp3400.c, which is by Gerd Knorr
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/videodev.h>
+#include <linux/i2c.h>
+#include <linux/i2c-algo-bit.h>
+
+#include "bttv.h"
+#include "audiochip.h"
+
+
+/* Addresses to scan */
+#define I2C_TEA6420	0x98
+static unsigned short normal_i2c[] = {
+    I2C_TEA6420 >> 1,
+    I2C_CLIENT_END};
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
+static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short force[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
+static struct i2c_client_address_data addr_data = {
+	normal_i2c, normal_i2c_range, 
+	probe, probe_range, 
+	ignore, ignore_range, 
+	force
+};
+
+
+MODULE_PARM(debug,"i");
+static int debug = 0; /* insmod parameter */
+
+#define dprintk  if (debug) printk
+
+
+struct tea6420 {
+	int mode;		/* set to AUDIO_{OFF,TUNER,RADIO,EXTERN} */
+	int stereo;
+};
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+#define TEA6420_S_SA       0x00  /* stereo A input */
+#define TEA6420_S_SB       0x01  /* stereo B */
+#define TEA6420_S_SC       0x02  /* stereo C */
+#define TEA6420_S_SD       0x03  /* stereo D */
+#define TEA6420_S_SE       0x04  /* stereo E */
+#define TEA6420_S_GMU      0x05  /* general mute */
+
+
+/* ******************************** *
+ * functions for talking to TEA6420 *
+ * ******************************** */
+
+static int tea6420_write(struct i2c_client *client, int val)
+{
+	unsigned char buffer[2];
+	int result;
+
+/*	buffer[0] = addr; */
+	buffer[0] = val;
+	result = i2c_master_send(client,buffer,1);
+	if (1 != result) {
+		printk(KERN_WARNING "tea6420: I/O error, trying (write
+0x%x) result = %d\n", val, result);
+		return -1;
+	}
+	return 0;
+}
+
+
+static void do_tea6420_init(struct i2c_client *client)
+{
+	struct tea6420 *tea = client->data;
+	
+	tea->mode=AUDIO_OFF;
+	tea->stereo=1;
+	tea6420_write(client, TEA6420_S_GMU); /* mute */
+}
+
+static void tea6420_audio(struct i2c_client *client, int mode)
+{
+	struct tea6420 *tea = client->data;
+	
+	/* valid for AUDIO_TUNER, RADIO, EXTERN, OFF */
+	dprintk(KERN_DEBUG "tea6420_audio:%d (T,R,E,I,O)\n",mode);
+	tea->mode=mode;
+	if (mode==AUDIO_OFF) {	/* just mute it */
+		tea6420_write(client, TEA6420_S_GMU);
+		return;
+	}
+	switch(mode) {
+		case AUDIO_TUNER:
+			tea6420_write(client, TEA6420_S_SA);
+			break;
+		case AUDIO_RADIO:
+			tea6420_write(client, TEA6420_S_SB);
+			break;
+		case AUDIO_EXTERN:
+			tea6420_write(client, TEA6420_S_SC);
+			break;
+	}
+}
+
+
+/* *********************** *
+ * i2c interface functions *
+ * *********************** */
+
+static int tea6420_attach(struct i2c_adapter *adap, int addr,
+			  unsigned short flags, int kind)
+{
+	struct tea6420 *tea;
+	struct i2c_client *client;
+
+	client = kmalloc(sizeof *client,GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;		
+        memcpy(client,&client_template,sizeof(struct i2c_client));
+        client->adapter = adap;
+        client->addr = addr;
+
+	client->data = tea = kmalloc(sizeof *tea,GFP_KERNEL);
+	if (!tea)
+		return -ENOMEM;
+	memset(tea,0,sizeof *tea);
+	do_tea6420_init(client);
+
+	MOD_INC_USE_COUNT;
+	strcpy(client->name,"TEA6420");
+	printk(KERN_INFO "tea6420: initialized\n");
+
+	i2c_attach_client(client);
+	return 0;
+}
+
+static int tea6420_probe(struct i2c_adapter *adap)
+{	
+	if (adap->id == (I2C_ALGO_BIT | I2C_HW_B_BT848))
+		return i2c_probe(adap, &addr_data, tea6420_attach);
+	return 0;
+}
+
+static int tea6420_detach(struct i2c_client *client)
+{
+	struct tea6420 *tea  = client->data;
+    
+	do_tea6420_init(client);
+	i2c_detach_client(client);
+
+	kfree(tea);
+	kfree(client);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static int
+tea6420_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+        __u16 *sarg = arg;
+
+	switch (cmd) {
+	case AUDC_SET_RADIO:
+		tea6420_audio(client,AUDIO_RADIO);
+		break;
+	case AUDC_SET_INPUT:
+		tea6420_audio(client,*sarg);
+		break;
+
+	/* --- v4l ioctls --- */
+	/* take care: bttv does userspace copying, we'll get a
+	   kernel pointer here... */
+	case VIDIOCGAUDIO:
+	{
+		struct video_audio *va = arg;
+
+		va->flags |= VIDEO_AUDIO_VOLUME |
+			VIDEO_AUDIO_BASS |
+			VIDEO_AUDIO_TREBLE;
+/*		va->volume=MAX(tea->left,tea->right);
+		va->balance=(32768*MIN(tea->left,tea->right))/
+			(va->volume ? va->volume : 1);
+		va->balance=(tea->left<tea->right)?
+			(65535-va->balance) : va->balance;
+		va->bass = tea->bass;
+		va->treble = tea->treble;
+*/		break;
+	}
+	case VIDIOCSAUDIO:
+	{
+
+/*		tea->left = (MIN(65536 - va->balance,32768) *
+			     va->volume) / 32768;
+		tea->right = (MIN(va->balance,32768) *
+			      va->volume) / 32768;
+		tea->bass = va->bass;
+		tea->treble = va->treble;
+		tea6420_set(client);
+*/		break;
+	}
+
+default:
+		/* nothing */
+	}
+	return 0;
+}
+
+static struct i2c_driver driver = {
+        "i2c tea6420 driver",
+        I2C_DRIVERID_TEA6420,
+        I2C_DF_NOTIFY,
+	tea6420_probe,
+        tea6420_detach,
+        tea6420_command,
+};
+
+static struct i2c_client client_template =
+{
+        "(unset)",		/* name */
+        -1,
+        0,
+        0,
+        NULL,
+        &driver
+};
+
+#ifdef MODULE
+int init_module(void)
+#else
+int tea6420_init(void)
+#endif
+{
+	i2c_add_driver(&driver);
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+	i2c_del_driver(&driver);
+}
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.3.99-pre8/linux/drivers/char/tty_io.c	Thu May 11 15:30:07 2000
+++ linux/drivers/char/tty_io.c	Sat May 20 12:07:56 2000
@@ -146,8 +146,8 @@
 extern int serial167_init(void);
 extern long serial167_console_init(void);
 #endif
-#ifdef CONFIG_8xx
-extern console_8xx_init(void);
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+extern void console_8xx_init(void);
 extern int rs_8xx_init(void);
 #endif /* CONFIG_8xx */
 #ifdef CONFIG_HWC
@@ -2194,7 +2194,7 @@
 	con_init();
 #endif
 #ifdef CONFIG_SERIAL_CONSOLE
-#ifdef CONFIG_8xx
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
 	console_8xx_init();
 #elif defined(CONFIG_SERIAL) 	
 	serial_console_init();
@@ -2340,7 +2340,7 @@
 #ifdef CONFIG_RIO
 	rio_init();
 #endif
-#ifdef CONFIG_8xx
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
         rs_8xx_init();
 #endif /* CONFIG_8xx */
 	pty_init();
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.3.99-pre8/linux/drivers/char/videodev.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/char/videodev.c	Mon May 22 09:50:53 2000
@@ -41,7 +41,6 @@
 static struct video_device *video_device[VIDEO_NUM_DEVICES];
 
 #ifdef CONFIG_VIDEO_BT848
-extern int init_bttv_cards(struct video_init *);
 extern int i2c_tuner_init(struct video_init *);
 #endif
 #ifdef CONFIG_VIDEO_BWQCAM
@@ -59,9 +58,8 @@
 
 static struct video_init video_init_list[]={
 #ifdef CONFIG_VIDEO_BT848
-	{"i2c-tuner", i2c_tuner_init},
-	{"bttv", init_bttv_cards},
-#endif	
+        {"i2c-tuner", i2c_tuner_init},
+#endif 
 #ifdef CONFIG_VIDEO_BWQCAM
 	{"bw-qcam", init_bw_qcams},
 #endif	
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/Config.in linux/drivers/ide/Config.in
--- v2.3.99-pre8/linux/drivers/ide/Config.in	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/Config.in	Sat May 20 11:15:44 2000
@@ -12,6 +12,15 @@
 
    dep_tristate '  Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
    dep_mbool '    Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK
+
+   define_bool CONFIG_BLK_DEV_IDEDISK_VENDOR n
+   dep_mbool '    Fujitsu Vendor Specific' CONFIG_BLK_DEV_IDEDISK_FUJITSU $CONFIG_BLK_DEV_IDEDISK_VENDOR
+   dep_mbool '    IBM Vendor Specific' CONFIG_BLK_DEV_IDEDISK_IBM $CONFIG_BLK_DEV_IDEDISK_VENDOR
+   dep_mbool '    Maxtor Vendor Specific' CONFIG_BLK_DEV_IDEDISK_MAXTOR $CONFIG_BLK_DEV_IDEDISK_VENDOR
+   dep_mbool '    Quantum Vendor Specific' CONFIG_BLK_DEV_IDEDISK_QUANTUM $CONFIG_BLK_DEV_IDEDISK_VENDOR
+   dep_mbool '    Seagate Vendor Specific' CONFIG_BLK_DEV_IDEDISK_SEAGATE $CONFIG_BLK_DEV_IDEDISK_VENDOR
+   dep_mbool '    Western Digital Vendor Specific' CONFIG_BLK_DEV_IDEDISK_WD $CONFIG_BLK_DEV_IDEDISK_VENDOR
+
    dep_tristate '  PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA
    dep_tristate '  Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
    dep_tristate '  Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/aec62xx.c linux/drivers/ide/aec62xx.c
--- v2.3.99-pre8/linux/drivers/ide/aec62xx.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/aec62xx.c	Mon May 15 11:03:48 2000
@@ -176,6 +176,7 @@
 };
 
 struct chipset_bus_clock_list_entry aec62xx_base [] = {
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	{	XFER_UDMA_4,	0x41,	0x04,	0x31,	0x05	},
 	{	XFER_UDMA_3,	0x41,	0x03,	0x31,	0x04	},
 	{	XFER_UDMA_2,	0x41,	0x02,	0x31,	0x03	},
@@ -185,7 +186,7 @@
 	{	XFER_MW_DMA_2,	0x41,	0x00,	0x31,	0x00	},
 	{	XFER_MW_DMA_1,	0x42,	0x00,	0x31,	0x00	},
 	{	XFER_MW_DMA_0,	0x7a,	0x00,	0x0a,	0x00	},
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 	{	XFER_PIO_4,	0x41,	0x00,	0x31,	0x00	},
 	{	XFER_PIO_3,	0x43,	0x00,	0x33,	0x00	},
 	{	XFER_PIO_2,	0x78,	0x00,	0x08,	0x00	},
@@ -202,18 +203,22 @@
 
 static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
 {
+	int bus_speed = system_bus_clock();
+
 	for ( ; chipset_table->xfer_speed ; chipset_table++)
 		if (chipset_table->xfer_speed == speed) {
-			return ((byte) ((1) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
+			return ((byte) ((bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
 		}
 	return 0x00;
 }
 
 static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
 {
+	int bus_speed = system_bus_clock();
+
 	for ( ; chipset_table->xfer_speed ; chipset_table++)
 		if (chipset_table->xfer_speed == speed) {
-			return ((byte) ((1) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34));
+			return ((byte) ((bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34));
 		}
 	return 0x00;
 }
@@ -222,8 +227,6 @@
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
-	byte unit		= (drive->select.b.unit & 0x01);
-	int drive_number	= ((hwif->channel ? 2 : 0) + unit);
 	int err			= 0;
 	unsigned short d_conf	= 0x0000;
 	byte ultra		= 0x00;
@@ -236,18 +239,18 @@
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only */
 
-	pci_read_config_word(dev, 0x40|(2*drive_number), &d_conf);
+	pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
 	tmp0 = pci_bus_clock_list(speed, aec62xx_base);
 	SPLIT_BYTE(tmp0,tmp1,tmp2);
 	MAKE_WORD(d_conf,tmp1,tmp2);
-	pci_write_config_word(dev, 0x40|(2*drive_number), d_conf);
+	pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
 
 	tmp1 = 0x00;
 	tmp2 = 0x00;
 	pci_read_config_byte(dev, 0x54, &ultra);
-	tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number))));
+	tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
 	ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
-	tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number))));
+	tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
 	pci_write_config_byte(dev, 0x54, tmp2);
 
 	__restore_flags(flags);	/* local CPU only */
@@ -261,7 +264,6 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
-	int drive_number	= ((hwif->channel ? 2 : 0) + unit);
 	byte ultra_pci		= hwif->channel ? 0x45 : 0x44;
 	int err			= 0;
 	byte drive_conf		= 0x00;
@@ -269,15 +271,14 @@
 	byte ultra		= 0x00;
 	byte tmp1		= 0x00;
 	byte tmp2		= 0x00;
-
 	unsigned long flags;
 
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only */
 
-	pci_read_config_byte(dev, 0x40|drive_number, &drive_conf);
+	pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
 	drive_conf = pci_bus_clock_list(speed, aec62xx_base);
-	pci_write_config_byte(dev, 0x40|drive_number, drive_conf);
+	pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
 
 	pci_read_config_byte(dev, ultra_pci, &ultra);
 	tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
@@ -286,10 +287,24 @@
 	pci_write_config_byte(dev, ultra_pci, tmp2);
 	__restore_flags(flags);	/* local CPU only */
 
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
 	err = ide_config_drive_speed(drive, speed);
+	drive->current_speed = speed;
 	return(err);
 }
 
+
+static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+		return ((int) aec6210_tune_chipset(drive, speed));
+	} else {
+		return ((int) aec6260_tune_chipset(drive, speed));
+	}
+}
+
 #ifdef CONFIG_BLK_DEV_IDEDMA
 static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra)
 {
@@ -524,7 +539,7 @@
 {
 #ifdef CONFIG_AEC62XX_TUNING
 	hwif->tuneproc = &aec62xx_tune_drive;
-
+	hwif->speedproc = &aec62xx_tune_chipset;
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base)
 		hwif->dmaproc = &aec62xx_dmaproc;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/alim15x3.c linux/drivers/ide/alim15x3.c
--- v2.3.99-pre8/linux/drivers/ide/alim15x3.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/alim15x3.c	Mon May 15 11:03:48 2000
@@ -333,6 +333,7 @@
 
 	err = ide_config_drive_speed(drive, speed);
 
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (speed >= XFER_SW_DMA_0) {
 		unsigned long dma_base = hwif->dma_base;
 
@@ -353,6 +354,9 @@
 			pci_write_config_byte(dev, 0x4b, tmpbyte);
 		}
 	}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+	drive->current_speed = speed;
 
 	return (err);
 }
@@ -399,6 +403,9 @@
 
 	(void) ali15x3_tune_chipset(drive, speed);
 
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
 	rval = (int)(	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
 			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
 			((id->dma_mword >> 8) & 7) ? ide_dma_on :
@@ -629,7 +636,7 @@
 	 * has 80-pin (from host view)
 	 */
 	pci_read_config_byte(dev, 0x4a, &tmpbyte);
-	ata66 = (!(tmpbyte & ata66mask)) ? 0 : 1;
+	ata66 = (!(tmpbyte & ata66mask)) ? 1 : 0;
 	__restore_flags(flags);
 
 	return(ata66);
@@ -673,6 +680,7 @@
 	hwif->tuneproc = &ali15x3_tune_drive;
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
+	hwif->speedproc = &ali15x3_tune_chipset;
 #ifndef CONFIG_BLK_DEV_IDEDMA
 	hwif->autodma = 0;
 	return;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/amd7409.c linux/drivers/ide/amd7409.c
--- v2.3.99-pre8/linux/drivers/ide/amd7409.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/amd7409.c	Mon May 15 11:03:48 2000
@@ -81,21 +81,22 @@
 	struct pci_dev *dev	= hwif->pci_dev;
 	int err			= 0;
 	byte unit		= (drive->select.b.unit & 0x01);
-	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + unit);
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	unsigned long dma_base	= hwif->dma_base;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 	byte drive_pci		= 0x00;
 	byte drive_pci2		= 0x00;
 	byte ultra_timing	= 0x00;
 	byte dma_pio_timing	= 0x00;
 	byte pio_timing		= 0x00;
 
-        switch (drive_number) {
+        switch (drive->dn) {
 		case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break;
 		case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break;
 		case 2: drive_pci = 0x51; drive_pci2 = 0x49; break;
 		case 3: drive_pci = 0x50; drive_pci2 = 0x48; break;
 		default:
-                        return ((int) ide_dma_off_quietly);
+                        return -1;
         }
 
 	pci_read_config_byte(dev, drive_pci, &ultra_timing);
@@ -109,7 +110,7 @@
 
 	ultra_timing &= ~0xC7;
 	dma_pio_timing &= ~0xFF;
-	pio_timing &= ~(0x03 << drive_number);
+	pio_timing &= ~(0x03 << drive->dn);
 
 #ifdef DEBUG
 	printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
@@ -117,67 +118,74 @@
 #endif
 
 	switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
 		case XFER_UDMA_4:
 			ultra_timing |= 0x45;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_3:
 			ultra_timing |= 0x44;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_2:
 			ultra_timing |= 0x40;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_1:
 			ultra_timing |= 0x41;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_UDMA_0:
 			ultra_timing |= 0x42;
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_MW_DMA_2:
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_MW_DMA_1:
 			dma_pio_timing |= 0x21;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_MW_DMA_0:
 			dma_pio_timing |= 0x77;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 		case XFER_PIO_4:
 			dma_pio_timing |= 0x20;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_3:
 			dma_pio_timing |= 0x22;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_2:
 			dma_pio_timing |= 0x42;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_1:
 			dma_pio_timing |= 0x65;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
 		case XFER_PIO_0:
 		default:
 			dma_pio_timing |= 0xA8;
-			pio_timing |= (0x03 << drive_number);
+			pio_timing |= (0x03 << drive->dn);
 			break;
         }
 
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	pci_write_config_byte(dev, drive_pci, ultra_timing);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 	pci_write_config_byte(dev, drive_pci2, dma_pio_timing);
 	pci_write_config_byte(dev, 0x4c, pio_timing);
 
@@ -186,12 +194,16 @@
 		ultra_timing, dma_pio_timing, pio_timing);
 #endif
 
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	if (speed > XFER_PIO_4) {
 		outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
 	} else {
 		outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
 	}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
 	err = ide_config_drive_speed(drive, speed);
+	drive->current_speed = speed;
 	return (err);
 }
 
@@ -231,6 +243,7 @@
 			break;
 	}
 	(void) amd7409_tune_chipset(drive, speed);
+	drive->current_speed = speed;
 }
 
 static void amd7409_tune_drive (ide_drive_t *drive, byte pio)
@@ -403,13 +416,14 @@
 void __init ide_init_amd7409 (ide_hwif_t *hwif)
 {
 	hwif->tuneproc = &amd7409_tune_drive;
+	hwif->speedproc = &amd7409_tune_chipset;
 
 #ifndef CONFIG_BLK_DEV_IDEDMA
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
 	hwif->autodma = 0;
 	return;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+#else
 
 	if (hwif->dma_base) {
 		hwif->dmaproc = &amd7409_dmaproc;
@@ -419,6 +433,7 @@
 		hwif->drives[0].autotune = 1;
 		hwif->drives[1].autotune = 1;
 	}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 }
 
 void ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase)
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/cmd64x.c linux/drivers/ide/cmd64x.c
--- v2.3.99-pre8/linux/drivers/ide/cmd64x.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/cmd64x.c	Mon May 15 11:03:48 2000
@@ -344,9 +344,9 @@
 		(void) ide_config_drive_speed(drive, speed);
 }
 
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int tune_chipset_for_dma (ide_drive_t *drive, byte speed)
+static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed)
 {
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
 	byte unit		= (drive->select.b.unit & 0x01);
@@ -357,6 +357,8 @@
 	u8 regU			= 0;
 	u8 regD			= 0;
 
+	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))	return 1;
+
 	(void) pci_read_config_byte(dev, pciD, &regD);
 	(void) pci_read_config_byte(dev, pciU, &regU);
 	regD &= ~(unit ? 0x40 : 0x20);
@@ -378,17 +380,37 @@
 		case XFER_SW_DMA_2:	regD |= (unit ? 0x40 : 0x10); break;
 		case XFER_SW_DMA_1:	regD |= (unit ? 0x80 : 0x20); break;
 		case XFER_SW_DMA_0:	regD |= (unit ? 0xC0 : 0x30); break;
+#else
+	int err			= 0;
+
+	switch(speed) {
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+		case XFER_PIO_4:	cmd64x_tuneproc(drive, 4); break;
+		case XFER_PIO_3:	cmd64x_tuneproc(drive, 3); break;
+		case XFER_PIO_2:	cmd64x_tuneproc(drive, 2); break;
+		case XFER_PIO_1:	cmd64x_tuneproc(drive, 1); break;
+		case XFER_PIO_0:	cmd64x_tuneproc(drive, 0); break;
+
 		default:
 			return 1;
 	}
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	(void) pci_write_config_byte(dev, pciU, regU);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
 	err = ide_config_drive_speed(drive, speed);
+
+	drive->current_speed = speed;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	regD |= (unit ? 0x40 : 0x20);
 	(void) pci_write_config_byte(dev, pciD, regD);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	return err;
 }
 
+#ifdef CONFIG_BLK_DEV_IDEDMA
 static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
 {
 	struct hd_driveid *id	= drive->id;
@@ -450,12 +472,15 @@
 		set_pio = 1;
 	}
 
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
 	config_chipset_for_pio(drive, set_pio);
 
 	if (set_pio)
 		return ((int) ide_dma_off_quietly);
 
-	if (tune_chipset_for_dma(drive, speed))
+	if (cmd64x_tune_chipset(drive, speed))
 		return ((int) ide_dma_off);
 
 	rval = (int)(	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
@@ -680,8 +705,9 @@
 	class_rev &= 0xff;
 
 	hwif->tuneproc = &cmd64x_tuneproc;
+	hwif->speedproc = &cmd64x_tune_chipset;
 	hwif->drives[0].autotune = 1;
-	hwif->drives[0].autotune = 1;
+	hwif->drives[1].autotune = 1;
 
 	if (!hwif->dma_base)
 		return;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/hd.c linux/drivers/ide/hd.c
--- v2.3.99-pre8/linux/drivers/ide/hd.c	Mon Mar 27 08:08:24 2000
+++ linux/drivers/ide/hd.c	Sat May 20 23:31:02 2000
@@ -881,3 +881,12 @@
 	return 0;
 }
 
+static int parse_hd_setup (char *line) {
+	int ints[6];
+
+	(void) get_options(line, ARRAY_SIZE(ints), ints);
+	hd_setup(NULL, ints);
+
+	return 0;
+}
+__setup("hd=", parse_hd_setup);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/hpt34x.c linux/drivers/ide/hpt34x.c
--- v2.3.99-pre8/linux/drivers/ide/hpt34x.c	Mon Mar 27 08:08:24 2000
+++ linux/drivers/ide/hpt34x.c	Mon May 15 11:03:48 2000
@@ -96,14 +96,13 @@
 
 static void hpt34x_clear_chipset (ide_drive_t *drive)
 {
-	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
 	unsigned int reg1	= 0, tmp1 = 0;
 	unsigned int reg2	= 0, tmp2 = 0;
 
 	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
 	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
-	tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
-	tmp2 = (reg2 & ~(0x11 << drive_number));
+	tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
+	tmp2 = (reg2 & ~(0x11 << drive->dn));
 	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
 	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
 }
@@ -112,7 +111,6 @@
 {
 	int			err;
 	byte			hi_speed, lo_speed;
-	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
 	unsigned int reg1	= 0, tmp1 = 0;
 	unsigned int reg2	= 0, tmp2 = 0;
 
@@ -127,20 +125,24 @@
 
 	pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
 	pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
-	tmp1 = ((lo_speed << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
-	tmp2 = ((hi_speed << drive_number) | reg2);
+	tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
+	tmp2 = ((hi_speed << drive->dn) | reg2);
 	err = ide_config_drive_speed(drive, speed);
 	pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
 	pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
 
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
 #if HPT343_DEBUG_DRIVE_INFO
 	printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \
 		" (0x%02x 0x%02x) 0x%04x\n",
 		drive->name, ide_xfer_verbose(speed),
-		drive_number, reg1, tmp1, reg2, tmp2,
+		drive->dn, reg1, tmp1, reg2, tmp2,
 		hi_speed, lo_speed, err);
 #endif /* HPT343_DEBUG_DRIVE_INFO */
 
+	drive->current_speed = speed;
 	return(err);
 }
 
@@ -410,6 +412,7 @@
 void __init ide_init_hpt34x (ide_hwif_t *hwif)
 {
 	hwif->tuneproc = &hpt34x_tune_drive;
+	hwif->speedproc = &hpt34x_tune_chipset;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/hpt366.c linux/drivers/ide/hpt366.c
--- v2.3.99-pre8/linux/drivers/ide/hpt366.c	Mon Mar 27 08:08:24 2000
+++ linux/drivers/ide/hpt366.c	Mon May 15 11:03:48 2000
@@ -173,6 +173,14 @@
 byte hpt363_shared_irq = 0;
 byte hpt363_shared_pin = 0;
 
+static unsigned int pci_rev_check_hpt366 (struct pci_dev *dev)
+{
+	unsigned int class_rev;
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+	return ((int) (class_rev == 0x03) ? 1 : 0);
+}
+
 static int check_in_drive_lists (ide_drive_t *drive, const char **list)
 {
 	struct hd_driveid *id = drive->id;
@@ -212,9 +220,6 @@
 static int hpt366_tune_chipset (ide_drive_t *drive, byte speed)
 {
 	int			err;
-#if HPT366_DEBUG_DRIVE_INFO
-	int drive_number	= ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-#endif /* HPT366_DEBUG_DRIVE_INFO */
 	byte regtime		= (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
 	unsigned int reg1	= 0;
 	unsigned int reg2	= 0;
@@ -251,11 +256,15 @@
 	pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
 	err = ide_config_drive_speed(drive, speed);
 
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
 #if HPT366_DEBUG_DRIVE_INFO
 	printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n",
 		drive->name, speed, ide_xfer_verbose(speed),
-		drive_number, reg1, reg2, err);
+		drive->dn, reg1, reg2, err);
 #endif /* HPT366_DEBUG_DRIVE_INFO */
+	drive->current_speed = speed;
 	return(err);
 }
 
@@ -469,10 +478,12 @@
 		case ide_dma_check:
 			return config_drive_xfer_rate(drive);
 		case ide_dma_lostirq:
+#if 0
 			pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
 			pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03);
 			pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
 			/* ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); */
+#endif
 		case ide_dma_timeout:
 		default:
 			break;
@@ -508,6 +519,8 @@
 	if (!hpt366_proc) {
 		hpt366_proc = 1;
 		bmide_dev = dev;
+		if (pci_rev_check_hpt366(dev))
+			bmide2_dev = dev;
 		hpt366_display_info = &hpt366_get_info;
 	}
 	if ((hpt366_proc) && ((dev->devfn - bmide_dev->devfn) == 1)) {
@@ -533,7 +546,11 @@
 
 void __init ide_init_hpt366 (ide_hwif_t *hwif)
 {
+	if (pci_rev_check_hpt366(hwif->pci_dev)) return;
+
 	hwif->tuneproc = &hpt366_tune_drive;
+	hwif->speedproc = &hpt366_tune_chipset;
+
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->dmaproc = &hpt366_dmaproc;
@@ -555,6 +572,11 @@
 	byte masterdma = 0, slavedma = 0;
 	byte dma_new = 0, dma_old = inb(dmabase+2);
 	unsigned long flags;
+
+	if (pci_rev_check_hpt366(hwif->pci_dev)) {
+		ide_setup_dma(hwif, dmabase, 8);
+		return;
+	}
 
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/icside.c linux/drivers/ide/icside.c
--- v2.3.99-pre8/linux/drivers/ide/icside.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/icside.c	Mon May 15 12:03:25 2000
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/hdreg.h>
 #include <linux/ide.h>
+#include <linux/pci.h>
 #include <linux/init.h>
 
 #include <asm/dma.h>
@@ -219,55 +220,73 @@
  * here, but we rely on the main IDE driver spotting that both
  * interfaces use the same IRQ, which should guarantee this.
  */
-#define TABLE_SIZE 2048
+#define NR_ENTRIES 256
+#define TABLE_SIZE (NR_ENTRIES * 8)
 
-static int
-icside_build_dmatable(ide_drive_t *drive, int reading)
+static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
 {
-	struct request *rq = HWGROUP(drive)->rq;
-	struct buffer_head *bh = rq->bh;
-	unsigned long addr, size;
-	unsigned char *virt_addr;
-	unsigned int count = 0;
-	dmasg_t *sg = (dmasg_t *)HWIF(drive)->dmatable_cpu;
+	struct buffer_head *bh;
+	struct scatterlist *sg = hwif->sg_table;
+	int nents = 0;
 
+	if (rq->cmd == READ)
+		hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+	else
+		hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+	bh = rq->bh;
 	do {
-		if (bh == NULL) {
-			/* paging requests have (rq->bh == NULL) */
-			virt_addr = rq->buffer;
-			addr = virt_to_bus (virt_addr);
-			size = rq->nr_sectors << 9;
-		} else {
-			/* group sequential buffers into one large buffer */
-			virt_addr = bh->b_data;
-			addr = virt_to_bus (virt_addr);
-			size = bh->b_size;
-			while ((bh = bh->b_reqnext) != NULL) {
-				if ((addr + size) != virt_to_bus (bh->b_data))
-					break;
-				size += bh->b_size;
-			}
-		}
+		unsigned char *virt_addr = bh->b_data;
+		unsigned int size = bh->b_size;
 
-		if (addr & 3) {
-			printk("%s: misaligned DMA buffer\n", drive->name);
-			return 0;
+		while ((bh = bh->b_reqnext) != NULL) {
+			if ((virt_addr + size) != (unsigned char *)bh->b_data)
+				break;
+			size += bh->b_size;
 		}
+		memset(&sg[nents], 0, sizeof(*sg));
+		sg[nents].address = virt_addr;
+		sg[nents].length = size;
+		nents++;
+	} while (bh != NULL);
 
-		if (size) {
-			if (reading)
-				dma_cache_inv((unsigned int)virt_addr, size);
-			else
-				dma_cache_wback((unsigned int)virt_addr, size);
-		}
+	return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
+}
+
+static int
+icside_build_dmatable(ide_drive_t *drive, int reading)
+{
+	dmasg_t *ide_sg = (dmasg_t *)HWIF(drive)->dmatable_cpu;
+	unsigned int count = 0;
+	int i;
+	struct scatterlist *sg;
+
+	HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
 
-		sg[count].address = addr;
-		sg[count].length = size;
-		if (++count >= (TABLE_SIZE / sizeof(dmasg_t))) {
-			printk("%s: DMA table too small\n", drive->name);
+	sg = HWIF(drive)->sg_table;
+	while (i && sg_dma_len(sg)) {
+		u32 cur_addr;
+		u32 cur_len;
+
+		cur_addr = sg_dma_address(sg);
+		cur_len  = sg_dma_len(sg);
+
+		if (count >= (TABLE_SIZE / sizeof(dmasg_t))) {
+			printk("%s: DMA table too small\n",
+				drive->name);
+			pci_unmap_sg(NULL,
+				     HWIF(drive)->sg_table,
+				     HWIF(drive)->sg_nents,
+				     HWIF(drive)->sg_dma_direction);
 			return 0;
+		} else {
+			ide_sg[count].address = cur_addr;
+			ide_sg[count].length  = cur_len;
 		}
-	} while (bh != NULL);
+
+		count++;
+		sg++;
+		i--;
+	}
 
 	if (!count)
 		printk("%s: empty DMA table?\n", drive->name);
@@ -275,6 +294,15 @@
 	return count;
 }
 
+/* Teardown mappings after DMA has completed.  */
+static void icside_destroy_dmatable(ide_drive_t *drive)
+{
+	struct scatterlist *sg = HWIF(drive)->sg_table;
+	int nents = HWIF(drive)->sg_nents;
+
+	pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
+}
+
 static int
 icside_config_if(ide_drive_t *drive, int xfer_mode)
 {
@@ -303,6 +331,9 @@
 		break;
 	}
 
+	if (!drive->init_speed)
+		drive->init_speed = (byte) xfer_mode;
+
 	if (drive->drive_data &&
 	    ide_config_drive_speed(drive, (byte) xfer_mode) == 0)
 		func = ide_dma_on;
@@ -312,10 +343,18 @@
 	printk("%s: %s selected (peak %dMB/s)\n", drive->name,
 		ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
 
+	drive->current_speed = (byte) xfer_mode;
+
 	return func;
 }
 
 static int
+icside_set_speed(ide_drive_t *drive, byte speed)
+{
+	return ((int) icside_config_if(drive, (int) speed));
+}
+
+static int
 icside_dma_check(ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
@@ -415,6 +454,7 @@
 	case ide_dma_end:
 		drive->waiting_for_dma = 0;
 		disable_dma(hwif->hw.dma);
+		icside_destroy_dmatable(drive);
 		return get_dma_residue(hwif->hw.dma) != 0;
 
 	case ide_dma_test_irq:
@@ -425,8 +465,7 @@
 	}
 }
 
-static unsigned long
-icside_alloc_dmatable(void)
+static void *icside_alloc_dmatable(void)
 {
 	static unsigned long dmatable;
 	static unsigned int leftover;
@@ -448,28 +487,39 @@
 		leftover -= TABLE_SIZE;
 	}
 
-	return table;
+	return (void *)table;
 }
 
 static int
 icside_setup_dma(ide_hwif_t *hwif, int autodma)
 {
-	unsigned long table = icside_alloc_dmatable();
-
 	printk("    %s: SG-DMA", hwif->name);
 
-	if (!table)
-		printk(" -- ERROR, unable to allocate DMA table\n");
-	else {
-		hwif->dmatable_cpu = (void *)table;
-		hwif->dmaproc = icside_dmaproc;
-		hwif->autodma = autodma;
-
-		printk(" capable%s\n", autodma ?
-			", auto-enable" : "");
+	hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,
+				 GFP_KERNEL);
+	if (!hwif->sg_table)
+		goto failed;
+
+	hwif->dmatable_cpu = icside_alloc_dmatable();
+
+	if (!hwif->dmatable_cpu) {
+		kfree(hwif->sg_table);
+		hwif->sg_table = NULL;
+		goto failed;
 	}
 
-	return hwif->dmatable_cpu != NULL;
+	hwif->dmaproc = &icside_dmaproc;
+	hwif->autodma = autodma;
+	hwif->speedproc = &icside_set_speed;
+
+	printk(" capable%s\n", autodma ?
+		", auto-enable" : "");
+
+	return 1;
+
+failed:
+	printk(" -- ERROR, unable to allocate DMA table\n");
+	return 0;
 }
 #endif
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- v2.3.99-pre8/linux/drivers/ide/ide-disk.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/ide-disk.c	Mon May 15 11:03:48 2000
@@ -33,8 +33,6 @@
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
 
-#define _IDE_DISK_C		/* Tell linux/hdsmart.h it's really us */
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -688,13 +686,12 @@
 
 static int set_nowerr(ide_drive_t *drive, int arg)
 {
-	unsigned long flags;
-
-	if (ide_spin_wait_hwgroup(drive, &flags))
+	if (ide_spin_wait_hwgroup(drive))
 		return -EBUSY;
+
 	drive->nowerr = arg;
 	drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irq(&io_request_lock);
 	return 0;
 }
 
@@ -713,7 +710,7 @@
 	ide_add_setting(drive,	"breada_readahead",	SETTING_RW,					BLKRAGET,		BLKRASET,		TYPE_INT,	0,	255,				1,	2,	&read_ahead[major],		NULL);
 	ide_add_setting(drive,	"file_readahead",	SETTING_RW,					BLKFRAGET,		BLKFRASET,		TYPE_INTA,	0,	INT_MAX,			1,	1024,	&max_readahead[major][minor],	NULL);
 	ide_add_setting(drive,	"max_kb_per_request",	SETTING_RW,					BLKSECTGET,		BLKSECTSET,		TYPE_INTA,	1,	255,				1,	2,	&max_sectors[major][minor],	NULL);
-
+	ide_add_setting(drive,	"lun",			SETTING_RW,					-1,			-1,			TYPE_INT,	0,	7,				1,	1,	&drive->lun,			NULL);
 }
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-features.c linux/drivers/ide/ide-features.c
--- v2.3.99-pre8/linux/drivers/ide/ide-features.c	Mon Mar 27 08:08:24 2000
+++ linux/drivers/ide/ide-features.c	Mon May 15 11:03:48 2000
@@ -27,6 +27,7 @@
 #include <linux/malloc.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/hdreg.h>
 #include <linux/ide.h>
 
 #include <asm/byteorder.h>
@@ -109,6 +110,46 @@
 }
 
 /*
+ *
+ */
+byte ide_auto_reduce_xfer (ide_drive_t *drive)
+{
+	switch(drive->current_speed) {
+		case XFER_UDMA_7:	return XFER_UDMA_6;
+		case XFER_UDMA_6:	return XFER_UDMA_5;
+		case XFER_UDMA_5:	return XFER_UDMA_4;
+		case XFER_UDMA_4:	return XFER_UDMA_3;
+		case XFER_UDMA_3:	return XFER_UDMA_2;
+		case XFER_UDMA_2:	return XFER_UDMA_1;
+		case XFER_UDMA_1:	return XFER_UDMA_0;
+		case XFER_UDMA_0:
+			if (drive->id->dma_mword & 0x0004) return XFER_MW_DMA_2;
+			else if (drive->id->dma_mword & 0x0002) return XFER_MW_DMA_1;
+			else if (drive->id->dma_mword & 0x0001) return XFER_MW_DMA_0;
+			else return XFER_PIO_4;
+		case XFER_MW_DMA_2:	return XFER_MW_DMA_1;
+		case XFER_MW_DMA_1:	return XFER_MW_DMA_0;
+		case XFER_MW_DMA_0:
+			if (drive->id->dma_1word & 0x0004) return XFER_SW_DMA_2;
+			else if (drive->id->dma_1word & 0x0002) return XFER_SW_DMA_1;
+			else if (drive->id->dma_1word & 0x0001) return XFER_SW_DMA_0;
+			else return XFER_PIO_4;
+		case XFER_SW_DMA_2:	return XFER_SW_DMA_1;
+		case XFER_SW_DMA_1:	return XFER_SW_DMA_0;
+		case XFER_SW_DMA_0:
+			{
+				return XFER_PIO_4;
+			}
+		case XFER_PIO_4:	return XFER_PIO_3;
+		case XFER_PIO_3:	return XFER_PIO_2;
+		case XFER_PIO_2:	return XFER_PIO_1;
+		case XFER_PIO_1:	return XFER_PIO_0;
+		case XFER_PIO_0:
+		default:		return XFER_PIO_SLOW;
+	}
+}
+
+/*
  * Update the 
  */
 int ide_driveid_update (ide_drive_t *drive)
@@ -136,8 +177,10 @@
 		ide_delay_50ms();	/* give drive a breather */
 	} while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
 	ide_delay_50ms();	/* wait for IRQ and DRQ_STAT */
-	if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
+	if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
+		printk("%s: CHECK for good STATUS\n", drive->name);
 		return 0;
+	}
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only; some systems need this */
 	id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
@@ -146,17 +189,14 @@
 	ide__sti();		/* local CPU only */
 	__restore_flags(flags);	/* local CPU only */
 	ide_fix_driveid(id);
-	if (id && id->cyls) {
+	if (id) {
 		drive->id->dma_ultra = id->dma_ultra;
 		drive->id->dma_mword = id->dma_mword;
 		drive->id->dma_1word = id->dma_1word;
 		/* anything more ? */
-#ifdef DEBUG
-		printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
-			drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
-#endif
 		kfree(id);
 	}
+
 	return 1;
 }
 
@@ -167,7 +207,7 @@
  * in combination with the device (usually a disk) properly detect
  * and acknowledge each end of the ribbon.
  */
-int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature)
+int ide_ata66_check (ide_drive_t *drive, byte cmd, byte nsect, byte feature)
 {
 	if ((cmd == WIN_SETFEATURES) &&
 	    (nsect > XFER_UDMA_2) &&
@@ -189,15 +229,16 @@
  * 1 : Safe to update drive->id DMA registers.
  * 0 : OOPs not allowed.
  */
-int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature)
+int set_transfer (ide_drive_t *drive, byte cmd, byte nsect, byte feature)
 {
-	struct hd_driveid *id = drive->id;
-
 	if ((cmd == WIN_SETFEATURES) &&
 	    (nsect >= XFER_SW_DMA_0) &&
 	    (feature == SETFEATURES_XFER) &&
-	    (id->dma_ultra || id->dma_mword || id->dma_1word))
+	    (drive->id->dma_ultra ||
+	     drive->id->dma_mword ||
+	     drive->id->dma_1word))
 		return 1;
+
 	return 0;
 }
 
@@ -219,6 +260,8 @@
 	byte unit = (drive->select.b.unit & 0x01);
 	byte stat;
 
+	outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2);
+
 	/*
 	 * Don't use ide_wait_cmd here - it will
 	 * attempt to set_geometry and recalibrate,
@@ -307,6 +350,7 @@
 	return error;
 }
 
+EXPORT_SYMBOL(ide_auto_reduce_xfer);
 EXPORT_SYMBOL(ide_driveid_update);
 EXPORT_SYMBOL(ide_ata66_check);
 EXPORT_SYMBOL(set_transfer);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c
--- v2.3.99-pre8/linux/drivers/ide/ide-pci.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/ide-pci.c	Mon May 15 11:03:48 2000
@@ -30,6 +30,7 @@
 #define DEVID_PIIX3	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371SB_1})
 #define DEVID_PIIX4	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82371AB})
 #define DEVID_PIIX4E	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AB_1})
+#define DEVID_PIIX4E2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82443MX_1})
 #define DEVID_PIIX4U	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82801AA_1})
 #define DEVID_PIIX4U2	((ide_pci_devid_t){PCI_VENDOR_ID_INTEL,   PCI_DEVICE_ID_INTEL_82372FB_1})
 #define DEVID_VIA_IDE	((ide_pci_devid_t){PCI_VENDOR_ID_VIA,     PCI_DEVICE_ID_VIA_82C561})
@@ -303,6 +304,7 @@
 	{DEVID_PIIX3,	"PIIX3",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
 	{DEVID_PIIX4,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}}, 	ON_BOARD,	0 },
 	{DEVID_PIIX4E,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
+	{DEVID_PIIX4E2,	"PIIX4",	PCI_PIIX,	NULL,		INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4U,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_PIIX4U2,	"PIIX4",	PCI_PIIX,	ATA66_PIIX,	INIT_PIIX,	NULL,		{{0x41,0x80,0x80}, {0x43,0x80,0x80}},	ON_BOARD,	0 },
 	{DEVID_VIA_IDE,	"VIA_IDE",	NULL,		NULL,		NULL,		NULL,		{{0x00,0x00,0x00}, {0x00,0x00,0x00}},	ON_BOARD,	0 },
@@ -476,6 +478,7 @@
 	unsigned short pcicmd = 0, tried_config = 0;
 	byte tmp = 0;
 	ide_hwif_t *hwif, *mate = NULL;
+	unsigned int class_rev;
 
 #ifdef CONFIG_IDEDMA_AUTO
 	autodma = 1;
@@ -504,6 +507,11 @@
 	}
 	if (tried_config)
 		printk("%s: device enabled (Linux)\n", d->name);
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+	printk("%s: chipset revision %d\n", d->name, class_rev);
+
 	/*
 	 * Can we trust the reported IRQ?
 	 */
@@ -545,7 +553,7 @@
 		ide_pci_enablebit_t *e = &(d->enablebits[port]);
 		if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
 			continue;	/* port not enabled */
-		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port))
+		if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev != 0x03))
 			return;
 		if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
 			ctl  = dev->resource[(2*port)+1].start;
@@ -656,9 +664,19 @@
 	struct pci_dev *dev2 = NULL, *findev;
 	ide_pci_device_t *d2;
 	unsigned char pin1 = 0, pin2 = 0;
+	unsigned int class_rev;
 
 	if (PCI_FUNC(dev->devfn) & 1)
 		return;
+
+	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+	class_rev &= 0xff;
+
+	switch(class_rev) {
+		case 3:		return;
+		default:	break;
+	}
+
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
 	pci_for_each_dev(findev) {
 		if ((findev->vendor == dev->vendor) &&
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-pmac.c linux/drivers/ide/ide-pmac.c
--- v2.3.99-pre8/linux/drivers/ide/ide-pmac.c	Mon Mar 27 08:08:24 2000
+++ linux/drivers/ide/ide-pmac.c	Mon May 15 11:03:48 2000
@@ -7,6 +7,8 @@
  *
  *  Copyright (C) 1998 Paul Mackerras.
  *
+ *  Bits from Benjamin Herrenschmidt
+ *
  *  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
@@ -16,12 +18,6 @@
  *
  *  Copyright (c) 1995-1998  Mark Lord
  *
- * BenH: I began adding more complete timing setup code, mostly because DMA
- *       won't work on new machines unless timings are setup correctly. This
- *       code was mainly stolen from Cmd646 driver and should be completed to
- *       include real timing calc. instead of hard coded values. The format of
- *       the timing register can be found in Darwin's source code, except for
- *       Keylargo ATA-4 controller.
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -44,14 +40,18 @@
 #endif
 #include "ide_modes.h"
 
+extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
+
 #undef IDE_PMAC_DEBUG
 
-#define IDE_SYSCLK_NS	30
+#define IDE_SYSCLK_NS		30
+#define IDE_SYSCLK_ULTRA_PS	0x1d4c /* (15 * 1000 / 2)*/
 
 struct pmac_ide_hwif {
 	ide_ioreg_t			regbase;
 	int				irq;
 	int				kind;
+	int				aapl_bus_id;
 	struct device_node*		node;
 	u32				timings[2];
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
@@ -90,17 +90,27 @@
 static pmac_ide_timing udma_timings[] =
 {
     {   0,    114 },	/* Mode 0 */
-    {   0,     73 },	/*      1 */
-    {   0,     54 },	/*      2 */
-    {   0,     39 },	/*      3 */
-    {   0,     25 }	/*      4 */
+    {   0,     75 },	/*      1 */
+    {   0,     55 },	/*      2 */
+    {   100,   45 },	/*      3 */
+    {   100,   25 }	/*      4 */
 };
 
-#define MAX_DCMDS	256	/* allow up to 256 DBDMA commands per xfer */
+/* allow up to 256 DBDMA commands per xfer */
+#define MAX_DCMDS		256
+
+/* Wait 1.5s for disk to answer on IDE bus after
+ * enable operation.
+ * NOTE: There is at least one case I know of a disk that needs about 10sec
+ *       before anwering on the bus. I beleive we could add a kernel command
+ *       line arg to override this delay for such cases.
+ */
+#define IDE_WAKEUP_DELAY_MS	1500
 
 static void pmac_ide_setup_dma(struct device_node *np, int ix);
 static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
 static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr);
+static int pmac_ide_tune_chipset(ide_drive_t *drive, byte speed);
 static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio);
 static void pmac_ide_selectproc(ide_drive_t *drive);
 
@@ -156,14 +166,6 @@
 		return;
 	}
 
-	/* we check only for -EINVAL meaning that we have found a matching
-	   bay but with the wrong device type */ 
-	i = check_media_bay_by_base(data_port, MB_CD);
-	if (i == -EINVAL) {
-		hw->io_ports[IDE_DATA_OFFSET] = 0;
-		return;
-	}
-
 	for (i = 0; i < 8; ++i)
 		hw->io_ports[i] = data_port + i * 0x10;
 	hw->io_ports[8] = data_port + 0x160;
@@ -178,6 +180,7 @@
 #ifdef CONFIG_PMAC_IDEDMA_AUTO
 		ide_hwifs[ix].autodma = 1;
 #endif
+//		ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
 	}
 }
 
@@ -214,7 +217,9 @@
 
 /* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
 #define SYSCLK_TICKS(t)		(((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
+#define SYSCLK_TICKS_UDMA(t)	(((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
 
+/* Calculate PIO timings */
 static void
 pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
 {
@@ -227,26 +232,31 @@
 	if (i < 0)
 		return;
 		
-	/* The "ata-4" IDE controller of UMA machines is a bit different.
-	 * We don't do anything for PIO modes until we know how to do the
-	 * calculation.
-	 */
-	if (pmac_ide[i].kind == controller_kl_ata4)
-		return;
-		
 	pio = ide_get_best_pio_mode(drive, pio, 4, &d);
 	accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time);
-	if (accessTicks < 4)
-		accessTicks = 4;
-	recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4;
-	if (recTicks < 1)
-		recTicks = 1;
 	if (drive->select.all & 0x10)
 		timings = &pmac_ide[i].timings[1];
 	else
 		timings = &pmac_ide[i].timings[0];
 	
-	*timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);	
+	if (pmac_ide[i].kind == controller_kl_ata4) {
+		/* The "ata-4" IDE controller of Core99 machines */
+		accessTicks = SYSCLK_TICKS_UDMA(ide_pio_timings[pio].active_time * 1000);
+		recTicks = SYSCLK_TICKS_UDMA(d.cycle_time * 1000) - accessTicks;
+
+		*timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5);
+	} else {
+		/* The old "ata-3" IDE controller */
+		accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time);
+		if (accessTicks < 4)
+			accessTicks = 4;
+		recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4;
+		if (recTicks < 1)
+			recTicks = 1;
+	
+		*timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);
+	}
+
 #ifdef IDE_PMAC_DEBUG
 	printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
 		pio,  *timings);
@@ -294,7 +304,7 @@
 	struct device_node *atas;
 	struct device_node *p, **pp, *removables, **rp;
 	unsigned long base;
-	int irq;
+	int irq, big_delay;
 	ide_hwif_t *hwif;
 
 	if (_machine != _MACH_Pmac)
@@ -322,9 +332,11 @@
 	}
 	*rp = NULL;
 	*pp = removables;
+	big_delay = 0;
 
 	for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
 		struct device_node *tp;
+		int *bidp;
 
 		/*
 		 * If this node is not under a mac-io or dbdma node,
@@ -378,6 +390,9 @@
 		else
 			pmac_ide[i].kind = controller_ohare;
 
+		bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
+		pmac_ide[i].aapl_bus_id =  bidp ? *bidp : 0;
+
 		if (np->parent && np->parent->name
 		    && strcasecmp(np->parent->name, "media-bay") == 0) {
 			media_bay_set_ide_infos(np->parent,base,irq,i);
@@ -388,42 +403,41 @@
 			 */
 			 feature_set(np, FEATURE_IDE0_enable);
 		} else {
-			/* This is necessary to enable IDE when net-booting */
-			int *bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
-			int bid = bidp ? *bidp : 0;
-			printk("pmac_ide: enabling IDE bus ID %d\n", bid);
-			switch(bid) {
+ 			/* This is necessary to enable IDE when net-booting */
+			printk("pmac_ide: enabling IDE bus ID %d\n",
+				pmac_ide[i].aapl_bus_id);
+			switch(pmac_ide[i].aapl_bus_id) {
 			    case 0:
 				feature_set(np, FEATURE_IDE0_reset);
-				feature_set(np, FEATURE_IOBUS_enable);
 				mdelay(10);
  				feature_set(np, FEATURE_IDE0_enable);
 				mdelay(10);
 				feature_clear(np, FEATURE_IDE0_reset);
 				break;
 			    case 1:
-				feature_set(np, FEATURE_Mediabay_IDE_reset);
+				feature_set(np, FEATURE_IDE1_reset);
 				mdelay(10);
- 				feature_set(np, FEATURE_Mediabay_IDE_enable);
+ 				feature_set(np, FEATURE_IDE1_enable);
 				mdelay(10);
-				feature_clear(np, FEATURE_Mediabay_IDE_reset);
+				feature_clear(np, FEATURE_IDE1_reset);
 				break;
 			    case 2:
-			    	/* This one exists only for KL, I don't know about any
-			    	   enable bit */
+			    	/* This one exists only for KL, I don't know
+				   about any enable bit */
 				feature_set(np, FEATURE_IDE2_reset);
 				mdelay(10);
 				feature_clear(np, FEATURE_IDE2_reset);
 				break;
 			}
-			mdelay(1000);
+			big_delay = 1;
 		}
 
 		hwif = &ide_hwifs[i];
 		pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq);
 		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 		hwif->chipset = ide_pmac;
-		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+		hwif->noprobe = (!hwif->io_ports[IDE_DATA_OFFSET]) ||
+			(check_media_bay_by_base(base, MB_CD) == -EINVAL);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 		if (np->n_addrs >= 2) {
@@ -435,6 +449,8 @@
 		++i;
 	}
 	pmac_ide_count = i;
+	if (big_delay)
+		mdelay(IDE_WAKEUP_DELAY_MS);
 
 #ifdef CONFIG_PMAC_PBOOK
 	pmu_register_sleep_notifier(&idepmac_sleep_notifier);
@@ -642,6 +658,7 @@
 	return result;
 }
 
+/* Calculate MultiWord DMA timings */
 static int
 pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
 {
@@ -652,18 +669,15 @@
 	int accessTicks, recTicks;
 	struct hd_driveid *id = drive->id;
 	
-	/* For now, we don't know these values */
-	if (pmac_ide[idx].kind == controller_kl_ata4 && feature != IDE_DMA2_ENABLE)
-		return 0;
-	if (pmac_ide[idx].kind != controller_kl_ata4 && feature == IDE_DMA0_ENABLE)
-		return 0;
-				
 	/* Set feature on drive */
     	printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
 	if (pmac_ide_do_setfeature(drive, feature)) {
 	    	printk("%s: Failed !\n", drive->name);
 	    	return 0;
 	}
+
+	if (!drive->init_speed)
+		drive->init_speed = feature;
 	
 	/* which drive is it ? */
 	if (drive->select.all & 0x10)
@@ -681,7 +695,10 @@
 
 	/* For ata-4 controller, we don't know the calculation */
 	if (pmac_ide[idx].kind == controller_kl_ata4) {
-		*timings = 0x00019465;	/* MDMA2 */
+		accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+		recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
+		*timings = ((*timings) & 0xffe003ff) |
+			(accessTicks | (recTicks << 5)) << 10;
 	} else {
 		int halfTick = 0;
 		int origAccessTime = accessTime;
@@ -696,7 +713,9 @@
 			recTicks = 1;
 		cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
 
-		if ((accessTicks > 1) &&
+		/* KeyLargo ata-3 don't support the half-tick stuff */
+		if ((pmac_ide[idx].kind != controller_kl_ata3) &&
+			(accessTicks > 1) &&
 			((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
 			((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
             			halfTick    = 1;
@@ -708,21 +727,21 @@
 #ifdef IDE_PMAC_DEBUG
 	printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
 		feature & 0xf, *timings);
-#endif	
+#endif
+	drive->current_speed = feature;	
 	return 1;
 }
 
+/* Calculate Ultra DMA timings */
 static int
 pmac_ide_udma_enable(ide_drive_t *drive, int idx)
 {
 	byte bits = drive->id->dma_ultra & 0x1f;
 	byte feature = udma_bits_to_command(bits);
-	u32 timings;
+	int cycleTime, accessTime;
+	int rdyToPauseTicks, cycleTicks;
+	u32 *timings;
 	
-	/* We support only those values */
-	if (feature != IDE_UDMA4_ENABLE && feature != IDE_UDMA2_ENABLE)
-		return 0;
-		
 	/* Set feature on drive */
     	printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
 	if (pmac_ide_do_setfeature(drive, feature)) {
@@ -730,23 +749,25 @@
 		return 0;
 	}
 
-	/* Put this channel into UDMA mode.
-	 * This value is set by MacOS on the iBook for U/DMA2
-	 */
-	switch(feature) {	
-		case IDE_UDMA4_ENABLE:
-			timings = 0x0cd00065;
-			break;
-		case IDE_UDMA2_ENABLE:
-			timings = 0x11100065;
-			break;
-	}
-	
+	if (!drive->init_speed)
+		drive->init_speed = feature;
+
+	/* which drive is it ? */
 	if (drive->select.all & 0x10)
-		pmac_ide[idx].timings[1] = timings;
+		timings = &pmac_ide[idx].timings[1];
 	else
-		pmac_ide[idx].timings[0] = timings;
-	
+		timings = &pmac_ide[idx].timings[0];
+
+	cycleTime = udma_timings[feature & 0xf].cycleTime;
+	accessTime = udma_timings[feature & 0xf].accessTime;
+
+	rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+	cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
+
+	*timings = ((*timings) & 0xe00fffff) |
+			((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+
+	drive->current_speed = feature;	
 	return 1;
 }
 
@@ -792,6 +813,12 @@
 	return 0;
 }
 
+static int
+pmac_ide_tune_chipset(ide_drive_t *drive, byte speed)
+{
+	return 0;
+}
+
 int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
 	ide_hwif_t *hwif = HWIF(drive);
@@ -813,6 +840,7 @@
 		pmac_ide_dma_onoff(drive, (func == ide_dma_on));
 		break;
 	case ide_dma_check:
+		printk("IDE-DMA check !\n");
 		if (hwif->autodma)
 			pmac_ide_dma_onoff(drive, 1);
 		break;
@@ -837,8 +865,21 @@
 		return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
 	case ide_dma_test_irq:
 		return (in_le32(&dma->status) & (RUN|ACTIVE)) == RUN;
+
+		/* Let's implement tose just in case someone wants them */
+	case ide_dma_bad_drive:
+	case ide_dma_good_drive:
+		return check_drive_lists(drive, (func == ide_dma_good_drive));
+	case ide_dma_verbose:
+		return report_drive_dmaing(drive);
+	case ide_dma_retune:
+	case ide_dma_lostirq:
+	case ide_dma_timeout:
+		printk("ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func),  func);
+		return 1;
 	default:
-		printk(KERN_ERR "pmac_ide_dmaproc: bad func %d\n", func);
+		printk("ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
+		return 1;
 	}
 	return 0;
 }
@@ -869,8 +910,20 @@
 		}
 	}
 	feature_set(np, FEATURE_IDE0_reset);
-	feature_clear(np, FEATURE_IOBUS_enable);
 	feature_clear(np, FEATURE_IDE0_enable);
+	switch(pmac_ide[i].aapl_bus_id) {
+	    case 0:
+		feature_set(np, FEATURE_IDE0_reset);
+		feature_clear(np, FEATURE_IDE0_enable);
+		break;
+	    case 1:
+		feature_set(np, FEATURE_IDE1_reset);
+		feature_clear(np, FEATURE_IDE1_enable);
+		break;
+	    case 2:
+		feature_set(np, FEATURE_IDE2_reset);
+		break;
+	}
 	pmac_ide[i].timings[0] = 0;
 	pmac_ide[i].timings[1] = 0;
 }
@@ -881,12 +934,30 @@
 	int j;
 
 	/* Revive IDE disk and controller */
-	feature_set(np, FEATURE_IOBUS_enable);
-	mdelay(10);
-	feature_set(np, FEATURE_IDE0_enable);
-	mdelay(10);
-	feature_clear(np, FEATURE_IDE0_reset);
-	mdelay(100);
+	switch(pmac_ide[i].aapl_bus_id) {
+	    case 0:
+		feature_set(np, FEATURE_IDE0_reset);
+		mdelay(10);
+ 		feature_set(np, FEATURE_IDE0_enable);
+		mdelay(10);
+		feature_clear(np, FEATURE_IDE0_reset);
+		break;
+	    case 1:
+		feature_set(np, FEATURE_IDE1_reset);
+		mdelay(10);
+ 		feature_set(np, FEATURE_IDE1_enable);
+		mdelay(10);
+		feature_clear(np, FEATURE_IDE1_reset);
+		break;
+	    case 2:
+	    	/* This one exists only for KL, I don't know
+		   about any enable bit */
+		feature_set(np, FEATURE_IDE2_reset);
+		mdelay(10);
+		feature_clear(np, FEATURE_IDE2_reset);
+		break;
+	}
+	mdelay(IDE_WAKEUP_DELAY_MS);
 
 	/* Reset timings */
 	pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
@@ -940,7 +1011,7 @@
 			/* Disable irq during sleep */
 			disable_irq(pmac_ide[i].irq);
 			ret = check_media_bay_by_base(base, MB_CD);
-			if (ret == -ENODEV)
+			if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
 				/* not media bay - put the disk to sleep */
 				idepmac_sleep_disk(i, base);
 		}
@@ -953,7 +1024,7 @@
 			hwif = &ide_hwifs[i];
 		        /* We don't handle media bay devices this way */
 			ret = check_media_bay_by_base(base, MB_CD);
-			if (ret == -ENODEV)
+			if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
 				idepmac_wake_disk(i, base);
 			else if (ret == 0)
 				idepmac_wake_bay(i, base);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c
--- v2.3.99-pre8/linux/drivers/ide/ide-probe.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/ide-probe.c	Mon May 15 11:03:48 2000
@@ -56,6 +56,11 @@
 	ide_input_data(drive, id, SECTOR_WORDS);		/* read 512 bytes of id info */
 	ide__sti();	/* local CPU only */
 	ide_fix_driveid(id);
+
+	if (id->word156 == 0x4d42) {
+		printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156);
+	}
+
 	if (!drive->forced_lun)
 		drive->last_lun = id->last_lun & 0x7;
 #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
@@ -764,9 +769,10 @@
 			char name[64];
 
 			ide_add_generic_settings(hwif->drives + unit);
+			hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
 			sprintf (name, "host%d/bus%d/target%d/lun%d",
 				 (hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index,
-				 hwif->channel, unit, 0);
+				 hwif->channel, unit, hwif->drives[unit].lun);
 			hwif->drives[unit].de =
 				devfs_mk_dir (ide_devfs_handle, name, 0, NULL);
 		}
@@ -775,9 +781,9 @@
 
 static int hwif_init (ide_hwif_t *hwif)
 {
-	ide_drive_t *drive;
-	void (*rfn)(request_queue_t *);
-	
+	request_queue_t *q;
+	unsigned int unit;
+
 	if (!hwif->present)
 		return 0;
 	if (!hwif->irq) {
@@ -795,39 +801,7 @@
 #endif /* CONFIG_BLK_DEV_HD */
 	
 	hwif->present = 0; /* we set it back to 1 if all is ok below */
-	switch (hwif->major) {
-	case IDE0_MAJOR: rfn = &do_ide0_request; break;
-#if MAX_HWIFS > 1
-	case IDE1_MAJOR: rfn = &do_ide1_request; break;
-#endif
-#if MAX_HWIFS > 2
-	case IDE2_MAJOR: rfn = &do_ide2_request; break;
-#endif
-#if MAX_HWIFS > 3
-	case IDE3_MAJOR: rfn = &do_ide3_request; break;
-#endif
-#if MAX_HWIFS > 4
-	case IDE4_MAJOR: rfn = &do_ide4_request; break;
-#endif
-#if MAX_HWIFS > 5
-	case IDE5_MAJOR: rfn = &do_ide5_request; break;
-#endif
-#if MAX_HWIFS > 6
-	case IDE6_MAJOR: rfn = &do_ide6_request; break;
-#endif
-#if MAX_HWIFS > 7
-	case IDE7_MAJOR: rfn = &do_ide7_request; break;
-#endif
-#if MAX_HWIFS > 8
-	case IDE8_MAJOR: rfn = &do_ide8_request; break;
-#endif
-#if MAX_HWIFS > 9
-	case IDE9_MAJOR: rfn = &do_ide9_request; break;
-#endif
-	default:
-		printk("%s: request_fn NOT DEFINED\n", hwif->name);
-		return (hwif->present = 0);
-	}
+
 	if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) {
 		printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
 		return (hwif->present = 0);
@@ -860,19 +834,11 @@
 	read_ahead[hwif->major] = 8;	/* (4kB) */
 	hwif->present = 1;	/* success */
 
-	/*
-	 * FIXME(eric) - This needs to be tested.  I *think* that this
-	 * is correct.   Also, I believe that there is no longer any
-	 * reason to have multiple functions (do_ide[0-7]_request)
-	 * functions - the queuedata field could be used to indicate
-	 * the correct hardware group - either this, or we could add
-	 * a new field to request_queue_t to hold this information.
-	 */
-	drive = &hwif->drives[0];
-	blk_init_queue(&drive->queue, rfn);
-
-	drive = &hwif->drives[1];
-	blk_init_queue(&drive->queue, rfn);
+	for (unit = 0; unit < MAX_DRIVES; ++unit) {
+		q = &hwif->drives[unit].queue;
+		q->queuedata = hwif->hwgroup;
+		blk_init_queue(q, do_ide_request);
+	}
 
 #if (DEBUG_SPINLOCK > 0)
 {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/ide.c linux/drivers/ide/ide.c
--- v2.3.99-pre8/linux/drivers/ide/ide.c	Thu May 11 15:30:07 2000
+++ linux/drivers/ide/ide.c	Mon May 15 11:03:48 2000
@@ -321,6 +321,7 @@
 		 || !strncmp(id->model, "Hitachi CV", 10)	/* Hitachi */
 		 || !strncmp(id->model, "SunDisk SDCFB", 13)	/* SunDisk */
 		 || !strncmp(id->model, "HAGIWARA HPC", 12)	/* Hagiwara */
+		 || !strncmp(id->model, "LEXAR ATA_FLASH", 15)	/* Lexar */
 		 || !strncmp(id->model, "ATA_FLASH", 9))	/* Simple Tech */
 		{
 			return 1;	/* yes, it is a flash memory card */
@@ -767,6 +768,18 @@
 			args[1] = err;
 			args[2] = IN_BYTE(IDE_NSECTOR_REG);
 		}
+	} else if (rq->cmd == IDE_DRIVE_TASK) {
+		byte *args = (byte *) rq->buffer;
+		rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+		if (args) {
+			args[0] = stat;
+			args[1] = err;
+			args[2] = IN_BYTE(IDE_NSECTOR_REG);
+			args[3] = IN_BYTE(IDE_SECTOR_REG);
+			args[4] = IN_BYTE(IDE_LCYL_REG);
+			args[5] = IN_BYTE(IDE_HCYL_REG);
+			args[6] = IN_BYTE(IDE_SELECT_REG);
+		}
 	}
 	spin_lock_irqsave(&io_request_lock, flags);
 	blkdev_dequeue_request(rq);
@@ -876,7 +889,7 @@
 	if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
 		return ide_stopped;
 	/* retry only "normal" I/O: */
-	if (rq->cmd == IDE_DRIVE_CMD) {
+	if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) {
 		rq->errors = 1;
 		ide_end_drive_cmd(drive, stat, err);
 		return ide_stopped;
@@ -1036,7 +1049,20 @@
 static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
 {
 	byte *args = rq->buffer;
-	if (args) {
+	if (args && rq->cmd == IDE_DRIVE_TASK) {
+
+#ifdef DEBUG
+		printk("%s: DRIVE_TASK_CMD data=x%02x cmd=0x%02x fr=0x%02x ns=0x%02x sc=0x%02x lcyl=0x%02x hcyl=0x%02x sel=0x%02x\n",
+			drive->name, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+#endif
+		OUT_BYTE(args[1], IDE_FEATURE_REG);
+		OUT_BYTE(args[3], IDE_SECTOR_REG);
+		OUT_BYTE(args[4], IDE_LCYL_REG);
+		OUT_BYTE(args[5], IDE_HCYL_REG);
+		OUT_BYTE(args[6], IDE_SELECT_REG);
+		ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
+		return ide_started;
+	} else if (args) {
 #ifdef DEBUG
 		printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x xx=0x%02x\n",
 		 drive->name, args[0], args[1], args[2], args[3]);
@@ -1116,7 +1142,7 @@
 		return startstop;
 	}
 	if (!drive->special.all) {
-		if (rq->cmd == IDE_DRIVE_CMD) {
+		if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) {
 			return execute_drive_cmd(drive, rq);
 		}
 		if (drive->driver != NULL) {
@@ -1225,7 +1251,7 @@
  * the driver.  This makes the driver much more friendlier to shared IRQs
  * than previous designs, while remaining 100% (?) SMP safe and capable.
  */
-static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
 {
 	ide_drive_t	*drive;
 	ide_hwif_t	*hwif;
@@ -1313,73 +1339,13 @@
 	return &hwif->drives[DEVICE_NR(dev) & 1].queue;
 }
 
-void do_ide0_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[0].hwgroup, 0);
-}
-
-#if MAX_HWIFS > 1
-void do_ide1_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[1].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 1 */
-
-#if MAX_HWIFS > 2
-void do_ide2_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[2].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 2 */
-
-#if MAX_HWIFS > 3
-void do_ide3_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[3].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 3 */
-
-#if MAX_HWIFS > 4
-void do_ide4_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[4].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 4 */
-
-#if MAX_HWIFS > 5
-void do_ide5_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[5].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 5 */
-
-#if MAX_HWIFS > 6
-void do_ide6_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[6].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 6 */
-
-#if MAX_HWIFS > 7
-void do_ide7_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[7].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 7 */
-
-#if MAX_HWIFS > 8
-void do_ide8_request (request_queue_t *q)
-{
-	ide_do_request (ide_hwifs[8].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 8 */
-
-#if MAX_HWIFS > 9
-void do_ide9_request (request_queue_t *q)
+/*
+ * Passes the stuff to ide_do_request
+ */
+void do_ide_request(request_queue_t *q)
 {
-	ide_do_request (ide_hwifs[9].hwgroup, 0);
+	ide_do_request(q->queuedata, 0);
 }
-#endif /* MAX_HWIFS > 9 */
 
 /*
  * ide_timer_expiry() is our timeout function for all drive operations.
@@ -1656,16 +1622,8 @@
  */
 void ide_init_drive_cmd (struct request *rq)
 {
-	rq->buffer = NULL;
+	memset(rq, 0, sizeof(*rq));
 	rq->cmd = IDE_DRIVE_CMD;
-	rq->sector = 0;
-	rq->nr_sectors = 0;
-	rq->nr_segments = 0;
-	rq->current_nr_sectors = 0;
-	rq->sem = NULL;
-	rq->bh = NULL;
-	rq->bhtail = NULL;
-	rq->q = NULL;
 }
 
 /*
@@ -2049,8 +2007,10 @@
 		hwgroup->hwif = HWIF(hwgroup->drive);
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
-	if (hwif->dma_base)
+	if (hwif->dma_base) {
 		(void) ide_release_dma(hwif);
+		hwif->dma_base = 0;
+	}
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
 	/*
@@ -2083,6 +2043,7 @@
 	init_hwif_data (index);	/* restore hwif data to pristine status */
 	hwif->hwgroup		= old_hwif.hwgroup;
 	hwif->tuneproc		= old_hwif.tuneproc;
+	hwif->speedproc		= old_hwif.speedproc;
 	hwif->selectproc	= old_hwif.selectproc;
 	hwif->resetproc		= old_hwif.resetproc;
 	hwif->dmaproc		= old_hwif.dmaproc;
@@ -2103,7 +2064,7 @@
 	hwif->pci_devid		= old_hwif.pci_devid;
 #endif /* CONFIG_BLK_DEV_IDEPCI */
 	hwif->straight8		= old_hwif.straight8;
-
+	hwif->hwif_data		= old_hwif.hwif_data;
 abort:
 	restore_flags(flags);	/* all CPUs */
 }
@@ -2304,24 +2265,24 @@
 	return val;
 }
 
-int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags)
+int ide_spin_wait_hwgroup (ide_drive_t *drive)
 {
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	unsigned long timeout = jiffies + (3 * HZ);
 
-	spin_lock_irqsave(&io_request_lock, *flags);
+	spin_lock_irq(&io_request_lock);
 	while (hwgroup->busy) {
-		unsigned long lflags;
-		spin_unlock_irqrestore(&io_request_lock, *flags);
-		__save_flags(lflags);	/* local CPU only */
+		unsigned long flags;
+		spin_unlock_irq(&io_request_lock);
+		__save_flags(flags);	/* local CPU only */
 		__sti();		/* local CPU only; needed for jiffies */
 		if (0 < (signed long)(jiffies - timeout)) {
-			__restore_flags(lflags);	/* local CPU only */
+			__restore_flags(flags);
 			printk("%s: channel busy\n", drive->name);
 			return -EBUSY;
 		}
-		__restore_flags(lflags);	/* local CPU only */
-		spin_lock_irqsave(&io_request_lock, *flags);
+		__restore_flags(flags);	/* local CPU only */
+		spin_lock_irq(&io_request_lock);
 	}
 	return 0;
 }
@@ -2333,7 +2294,6 @@
  */
 int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
 {
-	unsigned long flags;
 	int i;
 	u32 *p;
 
@@ -2345,7 +2305,7 @@
 		return -EINVAL;
 	if (setting->set)
 		return setting->set(drive, val);
-	if (ide_spin_wait_hwgroup(drive, &flags))
+	if (ide_spin_wait_hwgroup(drive))
 		return -EBUSY;
 	switch (setting->data_type) {
 		case TYPE_BYTE:
@@ -2363,7 +2323,7 @@
 				*p = val;
 			break;
 	}
-	spin_unlock_irqrestore(&io_request_lock, flags);
+	spin_unlock_irq(&io_request_lock);
 	return 0;
 }
 
@@ -2416,6 +2376,9 @@
 	ide_add_setting(drive,	"unmaskirq",		drive->no_unmask ? SETTING_READ : SETTING_RW,	HDIO_GET_UNMASKINTR,	HDIO_SET_UNMASKINTR,	TYPE_BYTE,	0,	1,				1,		1,		&drive->unmask,			NULL);
 	ide_add_setting(drive,	"using_dma",		SETTING_RW,					HDIO_GET_DMA,		HDIO_SET_DMA,		TYPE_BYTE,	0,	1,				1,		1,		&drive->using_dma,		set_using_dma);
 	ide_add_setting(drive,	"ide_scsi",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	1,				1,		1,		&drive->scsi,			NULL);
+	ide_add_setting(drive,	"init_speed",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	69,				1,		1,		&drive->init_speed,		NULL);
+	ide_add_setting(drive,	"current_speed",	SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	69,				1,		1,		&drive->current_speed,		NULL);
+	ide_add_setting(drive,	"number",		SETTING_RW,					-1,			-1,			TYPE_BYTE,	0,	3,				1,		1,		&drive->dn,			NULL);
 }
 
 int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf)
@@ -2435,6 +2398,16 @@
 	return ide_do_drive_cmd(drive, &rq, ide_wait);
 }
 
+int ide_wait_cmd_task (ide_drive_t *drive, byte *buf)
+{
+	struct request rq;
+
+	ide_init_drive_cmd(&rq);
+	rq.cmd = IDE_DRIVE_TASK;
+	rq.buffer = buf;
+	return ide_do_drive_cmd(drive, &rq, ide_wait);
+}
+
 /*
  * Delay for *at least* 50ms.  As we don't know how much time is left
  * until the next tick occurs, we wait an extra tick to be safe.
@@ -2551,6 +2524,7 @@
 		case HDIO_DRIVE_CMD:
 		{
 			byte args[4], *argbuf = args;
+			byte xfer_rate = 0;
 			int argsize = 4;
 			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
 			if (NULL == (void *) arg)
@@ -2564,18 +2538,22 @@
 					return -ENOMEM;
 				memcpy(argbuf, args, 4);
 			}
-			if (ide_ata66_check(drive, args[0], args[1], args[2]))
-				goto abort;
+
+			if (set_transfer(drive, args[0], args[1], args[2])) {
+				xfer_rate = args[1];
+				if (ide_ata66_check(drive, args[0], args[1], args[2]))
+					goto abort;
+			}
 
 			err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
 
-			if (!err && set_transfer(drive, args[0], args[1], args[2])) {
-#if 0
+			if (!err && xfer_rate) {
 				/* active-retuning-calls future */
-				if (HWIF(drive)->tune2proc)
-					HWIF(drive)->tune2proc(drive, args[1]);
-#endif
+				if ((HWIF(drive)->speedproc) != NULL)
+					HWIF(drive)->speedproc(drive, xfer_rate);
 				ide_driveid_update(drive);
+			} else {
+				printk("%s: \n", drive->name);
 			}
 		abort:
 			if (copy_to_user((void *)arg, argbuf, argsize))
@@ -2584,6 +2562,18 @@
 				kfree(argbuf);
 			return err;
 		}
+		case HDIO_DRIVE_TASK:
+		{
+			byte args[7], *argbuf = args;
+			int argsize = 7;
+			if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+			if (copy_from_user(args, (void *)arg, 7))
+				return -EFAULT;
+			err = ide_wait_cmd_task(drive, argbuf);
+			if (copy_to_user((void *)arg, argbuf, argsize))
+				err = -EFAULT;
+			return err;
+		}
 
 		case HDIO_SCAN_HWIF:
 		{
@@ -3512,37 +3502,9 @@
 EXPORT_SYMBOL(ide_intr);
 EXPORT_SYMBOL(ide_fops);
 EXPORT_SYMBOL(ide_get_queue);
-EXPORT_SYMBOL(do_ide0_request);
 EXPORT_SYMBOL(ide_add_generic_settings);
 EXPORT_SYMBOL(ide_devfs_handle);
-#if MAX_HWIFS > 1
-EXPORT_SYMBOL(do_ide1_request);
-#endif /* MAX_HWIFS > 1 */
-#if MAX_HWIFS > 2
-EXPORT_SYMBOL(do_ide2_request);
-#endif /* MAX_HWIFS > 2 */
-#if MAX_HWIFS > 3
-EXPORT_SYMBOL(do_ide3_request);
-#endif /* MAX_HWIFS > 3 */
-#if MAX_HWIFS > 4
-EXPORT_SYMBOL(do_ide4_request);
-#endif /* MAX_HWIFS > 4 */
-#if MAX_HWIFS > 5
-EXPORT_SYMBOL(do_ide5_request);
-#endif /* MAX_HWIFS > 5 */
-#if MAX_HWIFS > 6
-EXPORT_SYMBOL(do_ide6_request);
-#endif /* MAX_HWIFS > 6 */
-#if MAX_HWIFS > 7
-EXPORT_SYMBOL(do_ide7_request);
-#endif /* MAX_HWIFS > 7 */
-#if MAX_HWIFS > 8
-EXPORT_SYMBOL(do_ide8_request);
-#endif /* MAX_HWIFS > 8 */
-#if MAX_HWIFS > 9
-EXPORT_SYMBOL(do_ide9_request);
-#endif /* MAX_HWIFS > 9 */
-
+EXPORT_SYMBOL(do_ide_request);
 /*
  * Driver module
  */
@@ -3567,6 +3529,7 @@
 EXPORT_SYMBOL(ide_revalidate_disk);
 EXPORT_SYMBOL(ide_cmd);
 EXPORT_SYMBOL(ide_wait_cmd);
+EXPORT_SYMBOL(ide_wait_cmd_task);
 EXPORT_SYMBOL(ide_delay_50ms);
 EXPORT_SYMBOL(ide_stall_queue);
 #ifdef CONFIG_PROC_FS
@@ -3652,8 +3615,13 @@
 {
 	int index;
 
-	for (index = 0; index < MAX_HWIFS; ++index)
+	for (index = 0; index < MAX_HWIFS; ++index) {
 		ide_unregister(index);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+		if (ide_hwifs[index].dma_base)
+			(void) ide_release_dma(&ide_hwifs[index]);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+	}
 
 #ifdef CONFIG_PROC_FS
 	proc_ide_destroy();
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- v2.3.99-pre8/linux/drivers/ide/pdc202xx.c	Mon Mar 27 08:08:24 2000
+++ linux/drivers/ide/pdc202xx.c	Mon May 15 11:03:48 2000
@@ -262,59 +262,99 @@
 
 #endif /* PDC202XX_DECODE_REGISTER_INFO */
 
-/*   0    1    2    3    4    5    6   7   8
- * 960, 480, 390, 300, 240, 180, 120, 90, 60
- *           180, 150, 120,  90,  60
- * DMA_Speed
- * 180, 120,  90,  90,  90,  60,  30
- *  11,   5,   4,   3,   2,   1,   0
- */
-static int config_chipset_for_pio (ide_drive_t *drive, byte pio)
+static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
-	byte			drive_pci, speed;
-	byte			AP, BP, TA, TB;
 
-	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-	int err;
+	unsigned int		drive_conf;
+	int			err;
+	byte			drive_pci, AP, BP, CP, DP;
+	byte			TA = 0, TB = 0, TC = 0;
 
-	switch (drive_number) {
+	switch (drive->dn) {
 		case 0: drive_pci = 0x60; break;
 		case 1: drive_pci = 0x64; break;
 		case 2: drive_pci = 0x68; break;
 		case 3: drive_pci = 0x6c; break;
-		default: return 1;
+		default: return -1;
 	}
 
+	if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0))	return -1;
+
+	pci_read_config_dword(dev, drive_pci, &drive_conf);
 	pci_read_config_byte(dev, (drive_pci), &AP);
 	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
+	if (speed >= XFER_SW_DMA_0) {
+		if ((BP & 0xF0) && (CP & 0x0F)) {
+			/* clear DMA modes of upper 842 bits of B Register */
+			/* clear PIO forced mode upper 1 bit of B Register */
+			pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0);
+			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+
+			/* clear DMA modes of lower 8421 bits of C Register */
+			pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F);
+			pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+		}
+	} else {
+#else
+	{
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+		if ((AP & 0x0F) || (BP & 0x07)) {
+			/* clear PIO modes of lower 8421 bits of A Register */
+			pci_write_config_byte(dev, (drive_pci), AP & ~0x0F);
+			pci_read_config_byte(dev, (drive_pci), &AP);
+
+			/* clear PIO modes of lower 421 bits of B Register */
+			pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07);
+			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
 
+			pci_read_config_byte(dev, (drive_pci), &AP);
+			pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+		}
+	}
 
-	if ((AP & 0x0F) || (BP & 0x07)) {
-		/* clear PIO modes of lower 8421 bits of A Register */
-		pci_write_config_byte(dev, (drive_pci), AP & ~0x0F);
-		pci_read_config_byte(dev, (drive_pci), &AP);
-
-		/* clear PIO modes of lower 421 bits of B Register */
-		pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07);
-		pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci), &AP);
+	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
 
-		pci_read_config_byte(dev, (drive_pci), &AP);
-		pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+	switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+		case XFER_UDMA_4:	TB = 0x20; TC = 0x01; break;	/* speed 8 == UDMA mode 4 */
+		case XFER_UDMA_3:	TB = 0x40; TC = 0x02; break;	/* speed 7 == UDMA mode 3 */
+		case XFER_UDMA_2:	TB = 0x20; TC = 0x01; break;	/* speed 6 == UDMA mode 2 */
+		case XFER_UDMA_1:	TB = 0x40; TC = 0x02; break;	/* speed 5 == UDMA mode 1 */
+		case XFER_UDMA_0:	TB = 0x60; TC = 0x03; break;	/* speed 4 == UDMA mode 0 */
+		case XFER_MW_DMA_2:	TB = 0x60; TC = 0x03; break;	/* speed 4 == MDMA mode 2 */
+		case XFER_MW_DMA_1:	TB = 0x60; TC = 0x04; break;	/* speed 3 == MDMA mode 1 */
+		case XFER_MW_DMA_0:	TB = 0x60; TC = 0x05; break;	/* speed 2 == MDMA mode 0 */
+		case XFER_SW_DMA_2:	TB = 0x60; TC = 0x05; break;	/* speed 0 == SDMA mode 2 */
+		case XFER_SW_DMA_1:	TB = 0x80; TC = 0x06; break;	/* speed 1 == SDMA mode 1 */
+		case XFER_SW_DMA_0:	TB = 0xC0; TC = 0x0B; break;	/* speed 0 == SDMA mode 0 */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+		case XFER_PIO_4:	TA = 0x01; TB = 0x04; break;
+		case XFER_PIO_3:	TA = 0x02; TB = 0x06; break;
+		case XFER_PIO_2:	TA = 0x03; TB = 0x08; break;
+		case XFER_PIO_1:	TA = 0x05; TB = 0x0C; break;
+		case XFER_PIO_0:
+		default:		TA = 0x09; TB = 0x13; break;
 	}
 
-	pio = (pio == 5) ? 4 : pio;
-	switch (ide_get_best_pio_mode(drive, 255, pio, NULL)) {
-		case 4:speed = XFER_PIO_4; TA=0x01; TB=0x04; break;
-		case 3:speed = XFER_PIO_3; TA=0x02; TB=0x06; break;
-		case 2:speed = XFER_PIO_2; TA=0x03; TB=0x08; break;
-		case 1:speed = XFER_PIO_1; TA=0x05; TB=0x0C; break;
-		case 0:
-		default:speed = XFER_PIO_0; TA=0x09; TB=0x13; break;
+#ifdef CONFIG_BLK_DEV_IDEDMA
+        if (speed >= XFER_SW_DMA_0) {
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
+		pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
+	} else {
+#else
+	{
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+		pci_write_config_byte(dev, (drive_pci), AP|TA);
+		pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
 	}
-	pci_write_config_byte(dev, (drive_pci), AP|TA);
-	pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
 
 #if PDC202XX_DECODE_REGISTER_INFO
 	pci_read_config_byte(dev, (drive_pci), &AP);
@@ -333,13 +373,30 @@
 #if PDC202XX_DEBUG_DRIVE_INFO
 	printk("%s: %s drive%d 0x%08x ",
 		drive->name, ide_xfer_verbose(speed),
-		drive_number, drive_conf);
+		drive->dn, drive_conf);
 		pci_read_config_dword(dev, drive_pci, &drive_conf);
 	printk("0x%08x\n", drive_conf);
 #endif /* PDC202XX_DEBUG_DRIVE_INFO */
 	return err;
 }
 
+/*   0    1    2    3    4    5    6   7   8
+ * 960, 480, 390, 300, 240, 180, 120, 90, 60
+ *           180, 150, 120,  90,  60
+ * DMA_Speed
+ * 180, 120,  90,  90,  90,  60,  30
+ *  11,   5,   4,   3,   2,   1,   0
+ */
+static int config_chipset_for_pio (ide_drive_t *drive, byte pio)
+{
+	byte speed = 0x00;
+
+	pio = (pio == 5) ? 4 : pio;
+	speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
+        
+	return ((int) pdc202xx_tune_chipset(drive, speed));
+}
+
 static void pdc202xx_tune_drive (ide_drive_t *drive, byte pio)
 {
 	(void) config_chipset_for_pio(drive, pio);
@@ -352,15 +409,15 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
 	unsigned long high_16	= dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
+	unsigned long dma_base  = hwif->dma_base;
+	byte unit		= (drive->select.b.unit & 0x01);
 
-	int			err;
 	unsigned int		drive_conf;
 	byte			drive_pci;
 	byte			test1, test2, speed = -1;
-	byte			AP, BP, CP, DP, TB, TC;
+	byte			AP;
 	unsigned short		EP;
 	byte CLKSPD		= IN_BYTE(high_16 + 0x11);
-	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
 	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
 	byte udma_33		= ultra ? (inb(high_16 + 0x001f) & 1) : 0;
 
@@ -397,9 +454,9 @@
 			 * check to make sure drive on same channel
 			 * is u66 capable
 			 */
-			if (hwif->drives[!(drive_number%2)].id) {
-				if ((hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0010) ||
-				    (hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0008)) {
+			if (hwif->drives[!(drive->dn%2)].id) {
+				if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) ||
+				    (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0008)) {
 					OUT_BYTE(CLKSPD | mask, (high_16 + 0x11));
 				} else {
 					OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11));
@@ -410,7 +467,7 @@
 		}
 	}
 
-	switch(drive_number) {
+	switch(drive->dn) {
 		case 0:	drive_pci = 0x60;
 			pci_read_config_dword(dev, drive_pci, &drive_conf);
 			if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
@@ -451,101 +508,34 @@
 
 chipset_is_set:
 
-	if (drive->media != ide_disk)
-		return ide_dma_off_quietly;
+	if (drive->media != ide_disk)	return ide_dma_off_quietly;
 
 	pci_read_config_byte(dev, (drive_pci), &AP);
-	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
-	pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
-
-	if (id->capability & 4) {		/* IORDY_EN */
+	if (id->capability & 4)	/* IORDY_EN */
 		pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN);
-		pci_read_config_byte(dev, (drive_pci), &AP);
-	}
-
-	if (drive->media == ide_disk) {		/* PREFETCH_EN */
-		pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
-		pci_read_config_byte(dev, (drive_pci), &AP);
-	}
-
-	if ((BP & 0xF0) && (CP & 0x0F)) {
-		/* clear DMA modes of upper 842 bits of B Register */
-		/* clear PIO forced mode upper 1 bit of B Register */
-		pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0xF0);
-		pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-
-		/* clear DMA modes of lower 8421 bits of C Register */
-		pci_write_config_byte(dev, (drive_pci)|0x02, CP & ~0x0F);
-		pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
-	}
-
 	pci_read_config_byte(dev, (drive_pci), &AP);
-	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+	if (drive->media == ide_disk)	/* PREFETCH_EN */
+		pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
 
-	if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) {
-		/* speed 8 == UDMA mode 4 == speed 6 plus cable */
-		speed = XFER_UDMA_4; TB = 0x20; TC = 0x01;
-	} else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) {
-		/* speed 7 == UDMA mode 3 == speed 5 plus cable */
-		speed = XFER_UDMA_3; TB = 0x40; TC = 0x02;
-	} else if ((id->dma_ultra & 0x0004) && (udma_33)) {
-		/* speed 6 == UDMA mode 2 */
-		speed = XFER_UDMA_2; TB = 0x20; TC = 0x01;
-	} else if ((id->dma_ultra & 0x0002) && (udma_33)) {
-		/* speed 5 == UDMA mode 1 */
-		speed = XFER_UDMA_1; TB = 0x40; TC = 0x02;
-	} else if ((id->dma_ultra & 0x0001) && (udma_33)) {
-		/* speed 4 == UDMA mode 0 */
-		speed = XFER_UDMA_0; TB = 0x60; TC = 0x03;
-	} else if (id->dma_mword & 0x0004) {
-		/* speed 4 == DMA mode 2 multi-word */
-		speed = XFER_MW_DMA_2; TB = 0x60; TC = 0x03;
-	} else if (id->dma_mword & 0x0002) {
-		/* speed 3 == DMA mode 1 multi-word */
-		speed = XFER_MW_DMA_1; TB = 0x60; TC = 0x04;
-	} else if (id->dma_mword & 0x0001) {
-		/* speed 2 == DMA mode 0 multi-word */
-		speed = XFER_MW_DMA_0; TB = 0x60; TC = 0x05;
-	} else if (id->dma_1word & 0x0004) {
-		/* speed 2 == DMA mode 2 single-word */
-		speed = XFER_SW_DMA_2; TB = 0x60; TC = 0x05;
-	} else if (id->dma_1word & 0x0002) {
-		/* speed 1 == DMA mode 1 single-word */
-		speed = XFER_SW_DMA_1; TB = 0x80; TC = 0x06;
-	} else if (id->dma_1word & 0x0001) {
-		/* speed 0 == DMA mode 0 single-word */
-		speed = XFER_SW_DMA_0; TB = 0xC0; TC = 0x0B;
-	} else {
+	if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33))		speed = XFER_UDMA_4;
+	else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33))	speed = XFER_UDMA_3;
+	else if ((id->dma_ultra & 0x0004) && (udma_33)) 		speed = XFER_UDMA_2;
+	else if ((id->dma_ultra & 0x0002) && (udma_33))			speed = XFER_UDMA_1;
+	else if ((id->dma_ultra & 0x0001) && (udma_33))			speed = XFER_UDMA_0;
+	else if (id->dma_mword & 0x0004)				speed = XFER_MW_DMA_2;
+	else if (id->dma_mword & 0x0002)				speed = XFER_MW_DMA_1;
+	else if (id->dma_mword & 0x0001)				speed = XFER_MW_DMA_0;
+	else if (id->dma_1word & 0x0004)				speed = XFER_SW_DMA_2;
+	else if (id->dma_1word & 0x0002)				speed = XFER_SW_DMA_1;
+	else if (id->dma_1word & 0x0001)				speed = XFER_SW_DMA_0;
+	else {
 		/* restore original pci-config space */
 		pci_write_config_dword(dev, drive_pci, drive_conf);
 		return ide_dma_off_quietly;
 	}
 
-	pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
-	pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
-
-#if PDC202XX_DECODE_REGISTER_INFO
-	pci_read_config_byte(dev, (drive_pci), &AP);
-	pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
-	pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
-
-	decode_registers(REG_A, AP);
-	decode_registers(REG_B, BP);
-	decode_registers(REG_C, CP);
-	decode_registers(REG_D, DP);
-#endif /* PDC202XX_DECODE_REGISTER_INFO */
-
-	err = ide_config_drive_speed(drive, speed);
-
-#if PDC202XX_DEBUG_DRIVE_INFO
-	printk("%s: %s drive%d 0x%08x ",
-		drive->name, ide_xfer_verbose(speed),
-		drive_number, drive_conf);
-	pci_read_config_dword(dev, drive_pci, &drive_conf);
-	printk("0x%08x\n", drive_conf);
-#endif /* PDC202XX_DEBUG_DRIVE_INFO */
+	outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+	(void) pdc202xx_tune_chipset(drive, speed);
 
 	return ((int)	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
 			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
@@ -716,6 +706,7 @@
 void __init ide_init_pdc202xx (ide_hwif_t *hwif)
 {
 	hwif->tuneproc = &pdc202xx_tune_drive;
+	hwif->speedproc = &pdc202xx_tune_chipset;
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/piix.c linux/drivers/ide/piix.c
--- v2.3.99-pre8/linux/drivers/ide/piix.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/piix.c	Mon May 15 11:03:48 2000
@@ -112,6 +112,7 @@
 			p += sprintf(p, "\n                                Intel PIIX4 Ultra 66 Chipset.\n");
 			break;
 		case PCI_DEVICE_ID_INTEL_82801AB_1:
+		case PCI_DEVICE_ID_INTEL_82443MX_1:
 		case PCI_DEVICE_ID_INTEL_82371AB:
 			p += sprintf(p, "\n                                Intel PIIX4 Ultra 33 Chipset.\n");
 			break;
@@ -258,28 +259,18 @@
 }
 
 #if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
-static int piix_config_drive_for_dma (ide_drive_t *drive)
+static int piix_tune_chipset (ide_drive_t *drive, byte speed)
 {
-	struct hd_driveid *id	= drive->id;
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
-
-	int			sitre;
-	short			reg4042, reg44, reg48, reg4a, reg54;
-	byte			speed;
-
 	byte maslave		= hwif->channel ? 0x42 : 0x40;
-	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
-	int ultra66		= ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) ||
-				   (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0;
-	int ultra		= ((ultra66) ||
-				   (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
-				   (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0;
-	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-	int a_speed		= 2 << (drive_number * 4);
-	int u_flag		= 1 << drive_number;
-	int v_flag		= 0x10 << drive_number;
+	int a_speed		= 2 << (drive->dn * 4);
+	int u_flag		= 1 << drive->dn;
+	int v_flag		= 0x10 << drive->dn;
 	int u_speed		= 0;
+	int err			= 0;
+	int			sitre;
+	short			reg4042, reg44, reg48, reg4a, reg54;
 
 	pci_read_config_word(dev, maslave, &reg4042);
 	sitre = (reg4042 & 0x4000) ? 1 : 0;
@@ -288,29 +279,16 @@
 	pci_read_config_word(dev, 0x4a, &reg4a);
 	pci_read_config_word(dev, 0x54, &reg54);
 
-	if ((id->dma_ultra & 0x0010) && (ultra)) {
-		u_speed = 2 << (drive_number * 4);
-		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
-	} else if ((id->dma_ultra & 0x0008) && (ultra)) {
-		u_speed = 1 << (drive_number * 4);
-		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
-	} else if ((id->dma_ultra & 0x0004) && (ultra)) {
-		u_speed = 2 << (drive_number * 4);
-		speed = XFER_UDMA_2;
-	} else if ((id->dma_ultra & 0x0002) && (ultra)) {
-		u_speed = 1 << (drive_number * 4);
-		speed = XFER_UDMA_1;
-	} else if ((id->dma_ultra & 0x0001) && (ultra)) {
-		u_speed = 0 << (drive_number * 4);
-		speed = XFER_UDMA_0;
-	} else if (id->dma_mword & 0x0004) {
-		speed = XFER_MW_DMA_2;
-	} else if (id->dma_mword & 0x0002) {
-		speed = XFER_MW_DMA_1;
-	} else if (id->dma_1word & 0x0004) {
-		speed = XFER_SW_DMA_2;
-        } else {
-		speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+	switch(speed) {
+		case XFER_UDMA_4:
+		case XFER_UDMA_2:	u_speed = 2 << (drive->dn * 4); break;
+		case XFER_UDMA_3:
+		case XFER_UDMA_1:	u_speed = 1 << (drive->dn * 4); break;
+		case XFER_UDMA_0:	u_speed = 0 << (drive->dn * 4); break;
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:
+		case XFER_SW_DMA_2:	break;
+		default:		return -1;
 	}
 
 	if (speed >= XFER_UDMA_0) {
@@ -328,7 +306,6 @@
 			pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
 		}
 	}
-
 	if (speed < XFER_UDMA_0) {
 		if (reg48 & u_flag)
 			pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
@@ -340,11 +317,52 @@
 
 	piix_tune_drive(drive, piix_dma_2_pio(speed));
 
-	(void) ide_config_drive_speed(drive, speed);
-
 #if PIIX_DEBUG_DRIVE_INFO
-	printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number);
+	printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
 #endif /* PIIX_DEBUG_DRIVE_INFO */
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+	err = ide_config_drive_speed(drive, speed);
+	drive->current_speed = speed;
+	return err;
+}
+
+static int piix_config_drive_for_dma (ide_drive_t *drive)
+{
+	struct hd_driveid *id	= drive->id;
+	ide_hwif_t *hwif	= HWIF(drive);
+	struct pci_dev *dev	= hwif->pci_dev;
+	byte			speed;
+
+	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+	int ultra66		= ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) ||
+				   (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0;
+	int ultra		= ((ultra66) ||
+				   (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
+				   (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) ||
+				   (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0;
+
+	if ((id->dma_ultra & 0x0010) && (ultra)) {
+		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0008) && (ultra)) {
+		speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0004) && (ultra)) {
+		speed = XFER_UDMA_2;
+	} else if ((id->dma_ultra & 0x0002) && (ultra)) {
+		speed = XFER_UDMA_1;
+	} else if ((id->dma_ultra & 0x0001) && (ultra)) {
+		speed = XFER_UDMA_0;
+	} else if (id->dma_mword & 0x0004) {
+		speed = XFER_MW_DMA_2;
+	} else if (id->dma_mword & 0x0002) {
+		speed = XFER_MW_DMA_1;
+	} else if (id->dma_1word & 0x0004) {
+		speed = XFER_SW_DMA_2;
+        } else {
+		speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+	}
+
+	(void) piix_tune_chipset(drive, speed);
 
 	return ((int)	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
 			((id->dma_ultra >> 8) & 7) ? ide_dma_on :
@@ -413,6 +431,7 @@
 #ifdef CONFIG_PIIX_TUNING
 	hwif->autodma = 1;
 	hwif->dmaproc = &piix_dmaproc;
+	hwif->speedproc = &piix_tune_chipset;
 #endif /* CONFIG_PIIX_TUNING */
 #endif /* !CONFIG_BLK_DEV_IDEDMA */
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/qd6580.c linux/drivers/ide/qd6580.c
--- v2.3.99-pre8/linux/drivers/ide/qd6580.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/qd6580.c	Mon May 15 11:03:48 2000
@@ -1,12 +1,21 @@
 /*
- *  linux/drivers/ide/qd6580.c		Version 0.02	Feb 09, 1996
+ *  linux/drivers/ide/qd6580.c      Version 0.03    May 13, 2000
  *
- *  Copyright (C) 1996  Linus Torvalds & author (see below)
+ *  Copyright (C) 1996-2000  Linus Torvalds & author (see below)
  */
 
 /*
- * QDI QD6580 EIDE controller fast support by Colten Edwards.
- * No net access, but (maybe) can be reached at pje120@cs.usask.ca
+ *  Version 0.03	Cleaned auto-tune, added probe
+ * 
+ * QDI QD6580 EIDE controller fast support
+ * 
+ * To activate controller support use kernel parameter "ide0=qd6580"
+ * To enable tuning use kernel parameter "ide0=autotune"
+ */
+
+/* 
+ * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
+ * Samuel Thibault <samuel.thibault@fnac.net>
  */
 
 #undef REALLY_SLOW_IO           /* most systems can safely undef this */
@@ -27,42 +36,237 @@
 #include "ide_modes.h"
 
 /*
- * Register 0xb3 looks like:
- *	0x4f is fast		mode3 ?
- *	0x3f is medium		mode2 ?
- *	0x2f is slower		mode1 ?
- *	0x1f is slower yet	mode0 ?
- *	0x0f ???		???
+ * I/O ports are 0xb0 0xb1 0xb2 and 0xb3
+ *            or 0x30 0x31 0x32 and 0x33
+ *	-- this is a dual IDE interface with I/O chips
+ *
+ * More research on qd6580 being done by willmore@cig.mot.com (David)
+ */
+
+/* 
+ * 0xb0: Timer1
  *
- * Don't know whether this sets BOTH drives, or just the first drive.
- * Don't know if there is a separate setting for the second drive.
+ *  
+ * 0xb1: Status
  *
- * Feel free to patch this if you have one of these beasts
- * and can work out the answers!
+ * && 0xf0 is either 0b1010000 or 0b01010000, or else it isn't a qd6580
+ * bit 3 & 2: unknown (useless ?) I have 0 & 1, respectively
+ * bit 1: 1 if qd6580 baseport is 0xb0
+ *        0 if qd6580 baseport is 0x30
+ * bit 0: 1 if ide baseport is 0x1f0
+ *        0 if ide baseport is 0x170
+ *   (? Strange: the Dos driver uses it, and then forces baseport to 0x1f0 ?)
+ * 
+ *        
+ * 0xb2: Timer2
  *
- * I/O ports are 0xb0 0xb2 and 0xb3
+ * 
+ * 0xb3: Control
  *
- * More research on qd6580 being done by willmore@cig.mot.com (David)
- *	-- this is apparently a *dual* IDE interface
+ * bits 0-3 are always set 1
+ * bit 6 : if 1, must be set 1
+ * bit 1 : if 1, bit 7 must be set 1
+ * bit 0 : if 1, drives are independant, we can have two different timers for
+ *               the two drives.
+ *         if 0, we have to take the slowest drive into account,
+ *               but we may tune the second hwif ?
  */
 
-static void tune_qd6580 (ide_drive_t *drive, byte pio)
+typedef struct ide_hd_timings_s {
+	int active_time;		/* Active pulse (ns) minimum */
+	int recovery_time;		/* Recovery pulse (ns) minimum */
+} ide_hd_timings_t;
+
+static int basePort;		/* base port address (0x30 or 0xb0) */
+static byte status;			/* status register of qd6580 */
+static byte control;		/* control register of qd6580 */
+
+/* truncates a in [b,c] */
+#define IDE_IN(a,b,c)   ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) )
+
+static int bus_clock;		/* Vesa local bus clock (ns) */
+static int tuned=0;			/* to remember whether we've already been tuned */
+
+/*
+ * tune_drive
+ *
+ * Finds timings for the specified drive, returns it in struc t
+ */
+
+static void tune_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t)
+{
+	ide_pio_data_t d;
+
+	t->active_time   = 0xaf;
+	t->recovery_time = 0x19f; /* worst cases values from the dos driver */
+
+	if (drive->present == 0) {	/* not present : free to give any timing */
+		t->active_time = 0x0;
+		t->recovery_time = 0x0;
+		return;
+	}
+	
+	pio = ide_get_best_pio_mode(drive, pio, 4, &d);
+
+	if (pio) {
+	
+		switch (pio) {
+			case 0: break;
+			case 3: t->active_time = 0x56;
+						t->recovery_time = d.cycle_time-0x66;
+					break;
+			case 4: t->active_time = 0x46;
+						t->recovery_time = d.cycle_time-0x3d;
+					break;
+			default: if (d.cycle_time >= 0xb4) {
+						t->active_time = 0x6e;
+						t->recovery_time = d.cycle_time - 0x78;
+					} else {
+						t->active_time = ide_pio_timings[pio].active_time;
+						t->recovery_time = d.cycle_time 
+								-t->active_time
+								-ide_pio_timings[pio].setup_time;
+					}
+		}		
+	}	
+	printk("%s: PIO mode%d, tim1=%dns tim2=%dns\n", drive->name, pio, t->active_time, t->recovery_time);
+}
+
+/* 
+ * tune_ide
+ *
+ * Tunes the whole ide, ie tunes each drives, and takes the worst timings
+ * to tune qd6580
+ */
+
+static void tune_ide ( ide_hwif_t *hwif, byte pio )
 {
 	unsigned long flags;
+	ide_hd_timings_t t[2]={{0,0},{0,0}};
+	
+	byte active_cycle;
+	byte recovery_cycle;
+	byte parameter;
+	int bus_speed = ide_system_bus_speed ();
+	
+	bus_clock = 1000 / bus_speed;
+	
+	save_flags(flags);		/* all CPUs */
+	cli();					/* all CPUs */
+	outb( (bus_clock<30) ? 0x0 : 0x0a, basePort + 0x02);
+	outb( 0x40 | ((control & 0x02) ? 0x9f:0x1f), basePort+0x03);
+	restore_flags(flags);	
 
-	pio = ide_get_best_pio_mode(drive, pio, 3, NULL);
+	tune_drive (&hwif->drives[0], pio, &t[0]);
+	tune_drive (&hwif->drives[1], pio, &t[1]);
 
-	save_flags(flags);	/* all CPUs */
-	cli();			/* all CPUs */
-	outb_p(0x8d,0xb0);
-	outb_p(0x0 ,0xb2);
-	outb_p(((pio+1)<<4)|0x0f,0xb3);
+	t[0].active_time   = IDE_MAX(t[0].active_time,  t[1].active_time);
+	t[0].recovery_time = IDE_MAX(t[0].recovery_time,t[1].recovery_time);
+	
+	active_cycle   = 17-IDE_IN(t[0].active_time   / bus_clock + 1, 2, 17);
+	recovery_cycle = 15-IDE_IN(t[0].recovery_time / bus_clock + 1, 2, 15);
+	
+	parameter=active_cycle | (recovery_cycle<<4);
+		
+	printk("%s: tim1=%dns tim2=%dns => %#x\n", hwif->name, t[0].active_time, t[0].recovery_time, parameter);
+	
+	save_flags(flags);		/* all CPUs */
+	cli();					/* all CPUs */
+	outb_p(parameter,0xb0);
 	inb(0x3f6);
 	restore_flags(flags);	/* all CPUs */
+	
+}
+
+/*
+ * tune_qd6580
+ *
+ * tunes the hwif if not tuned
+ */
+
+static void tune_qd6580 (ide_drive_t *drive, byte pio)
+{
+	if (! tuned) {
+		tune_ide(HWIF(drive), pio);
+		tuned = 1;
+	}
+}
+
+/*
+ * testreg
+ *
+ * tests if the given port is a register
+ */
+
+static int __init testreg(int port)
+{
+	byte savereg;
+	byte readreg;
+	unsigned long flags;
+	
+	save_flags(flags);		/* all CPUs */
+	cli();					/* all CPUs */
+	savereg = inb(port);
+	outb_p(0x15,port);		/* safe value */
+	readreg = inb_p(port);
+	outb(savereg,port);
+	restore_flags(flags);	/* all CPUs */
+
+	if (savereg == 0x15) {
+		printk("Outch ! the probe for qd6580 isn't reliable !\n");
+		printk("Please contact samuel.thibault@fnac.net to tell about your hardware\n");
+		printk("Assuming qd6580 is present");
+	}
+
+	return (readreg == 0x15);
 }
 
+/* 
+ * trybase:
+ *
+ * tries to find a qd6580 at the given base and save it if found
+ */
+
+static int __init trybase (int base)
+{
+	unsigned long flags;
+
+	save_flags(flags);		/* all CPUs */
+	cli();					/* all CPUs */
+	status = inb(base+0x01);
+	control = inb(base+0x03);
+	restore_flags(flags);	/* all CPUs */
+
+	if (((status & 0xf0) != 0x50) && ((status & 0xf0) != 0xa0)) return(0);
+	if (! ( ((status & 0x02) == 0x0) == (base == 0x30) ) ) return (0);
+
+	/* Seems to be OK, let's use it */
+	
+	basePort = base;
+	return(testreg(base));
+}
+
+/* 
+ * probe:
+ *
+ * probes qd6580 at 0xb0 (the default) or 0x30
+ */
+
+static int __init probe (void)
+{
+	return (trybase(0xb0) ? 1 : trybase(0x30));
+}
+
+
 void __init init_qd6580 (void)
 {
+	if (! probe()) {
+		printk("qd6580: not found\n");
+		return;
+	}
+	
+	printk("qd6580: base=%#x, status=%#x, control=%#x\n", basePort, status, control);
+	
 	ide_hwifs[0].chipset = ide_qd6580;
 	ide_hwifs[1].chipset = ide_qd6580;
 	ide_hwifs[0].tuneproc = &tune_qd6580;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c
--- v2.3.99-pre8/linux/drivers/ide/sis5513.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/sis5513.c	Mon May 15 11:03:48 2000
@@ -227,9 +227,8 @@
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
 
-	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
 	byte reg4bh		= 0;
-	byte rw_prefetch	= (0x11 << drive_number);
+	byte rw_prefetch	= (0x11 << drive->dn);
 
 	pci_read_config_byte(dev, 0x4b, &reg4bh);
 	if (drive->media != ide_disk)
@@ -248,12 +247,8 @@
 
 	unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
 	unsigned short xfer_pio = drive->id->eide_pio_modes;
-	int drive_number	= ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
 
-#if 0
 	config_drive_art_rwp(drive);
-#endif
-
 	pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
 
 	if (xfer_pio> 4)
@@ -281,7 +276,7 @@
  * Cycle time    20T (600ns) 13T (390ns) 8T (240ns) 6T (180ns) 4T (120ns)
  */
 
-	switch(drive_number) {
+	switch(drive->dn) {
 		case 0:		drive_pci = 0x40; break;
 		case 1:		drive_pci = 0x42; break;
 		case 2:		drive_pci = 0x44; break;
@@ -329,7 +324,7 @@
 	return err;
 }
 
-#undef SIS5513_TUNEPROC
+#define SIS5513_TUNEPROC
 
 #ifdef SIS5513_TUNEPROC
 static void sis5513_tune_drive (ide_drive_t *drive, byte pio)
@@ -354,7 +349,6 @@
 	unsigned long dma_base	= hwif->dma_base;
 	byte unit		= (drive->select.b.unit & 0x01);
 	byte speed		= 0x00, unmask = 0xE0, four_two = 0x00;
-	int drive_number	= ((hwif->channel ? 2 : 0) + unit);
 	byte udma_66		= ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
 
 	if (host_dev) {
@@ -370,7 +364,7 @@
 		}
 	}
 
-	switch(drive_number) {
+	switch(drive->dn) {
 		case 0:		drive_pci = 0x40;break;
 		case 1:		drive_pci = 0x42;break;
 		case 2:		drive_pci = 0x44;break;
@@ -438,7 +432,7 @@
 	err = ide_config_drive_speed(drive, speed);
 
 #if SIS5513_DEBUG_DRIVE_INFO
-	printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number);
+	printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
 #endif /* SIS5513_DEBUG_DRIVE_INFO */
 
 	return ((int)	((id->dma_ultra >> 11) & 3) ? ide_dma_on :
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c
--- v2.3.99-pre8/linux/drivers/ide/via82cxxx.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/ide/via82cxxx.c	Mon May 15 11:03:48 2000
@@ -115,6 +115,7 @@
 
 struct chipset_bus_clock_list_entry via82cxxx_type_one [] = {
 		/* speed */	/* 25 */	/* 33 */	/* 37.5 */	/* 41.5 */	
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	{	XFER_UDMA_4,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00	},
 	{	XFER_UDMA_3,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00	},
 	{	XFER_UDMA_2,	0x60,	0x20,	0x60,	0x20,	0x60,	0x21,	0x00,	0x00	},
@@ -124,7 +125,7 @@
 	{	XFER_MW_DMA_2,	0x03,	0x20,	0x03,	0x20,	0x03,	0x21,	0x00,	0x00	},
 	{	XFER_MW_DMA_1,	0x03,	0x31,	0x03,	0x31,	0x03,	0x32,	0x00,	0x00	},
 	{	XFER_MW_DMA_0,	0x03,	0x31,	0x03,	0x31,	0x03,	0x32,	0x00,	0x00	},
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 	{	XFER_PIO_4,	0x03,	0x20,	0x03,	0x20,	0x03,	0x21,	0x00,	0x00	},
 	{	XFER_PIO_3,	0x03,	0x31,	0x03,	0x31,	0x03,	0x32,	0x00,	0x00	},
 	{	XFER_PIO_2,	0x03,	0x65,	0x03,	0x65,	0x03,	0x76,	0x00,	0x00	},
@@ -135,6 +136,7 @@
 
 struct chipset_bus_clock_list_entry via82cxxx_type_two [] = {
 		/* speed */	/* 25 */	/* 33 */	/* 37.5 */	/* 41.5 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	{	XFER_UDMA_4,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00	},
 	{	XFER_UDMA_3,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00	},
 	{	XFER_UDMA_2,	0xE0,	0x20,	0xE0,	0x20,	0xE1,	0x31,	0xE1,	0x32	},
@@ -144,7 +146,7 @@
 	{	XFER_MW_DMA_2,	0x03,	0x20,	0x03,	0x20,	0x03,	0x31,	0x03,	0x32	},
 	{	XFER_MW_DMA_1,	0x03,	0x31,	0x03,	0x31,	0x03,	0x42,	0x03,	0x53	},
 	{	XFER_MW_DMA_0,	0x03,	0x31,	0x03,	0x31,	0x03,	0x42,	0x03,	0x53	},
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 	{	XFER_PIO_4,	0x03,	0x20,	0x03,	0x20,	0x03,	0x31,	0x03,	0x32	},
 	{	XFER_PIO_3,	0x03,	0x31,	0x03,	0x31,	0x03,	0x42,	0x03,	0x53	},
 	{	XFER_PIO_2,	0x03,	0x65,	0x03,	0x65,	0x03,	0x87,	0x03,	0xA8	},
@@ -155,6 +157,7 @@
 
 struct chipset_bus_clock_list_entry via82cxxx_type_three [] = {
 		/* speed */	/* 25 */	/* 33 */	/* 37.5 */	/* 41.5 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	{	XFER_UDMA_4,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00	},
 	{	XFER_UDMA_3,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00	},
 	{	XFER_UDMA_2,	0xE0,	0x20,	0xE0,	0x20,	0xE1,	0x31,	0xE1,	0x32	},
@@ -164,7 +167,7 @@
 	{	XFER_MW_DMA_2,	0x03,	0x20,	0x03,	0x20,	0x03,	0x31,	0x03,	0x32	},
 	{	XFER_MW_DMA_1,	0x03,	0x31,	0x03,	0x31,	0x03,	0x42,	0x03,	0x53	},
 	{	XFER_MW_DMA_0,	0x03,	0x31,	0x03,	0x31,	0x03,	0x42,	0x03,	0x53	},
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 	{	XFER_PIO_4,	0x03,	0x20,	0x03,	0x20,	0x03,	0x31,	0x03,	0x32	},
 	{	XFER_PIO_3,	0x03,	0x31,	0x03,	0x31,	0x03,	0x42,	0x03,	0x53	},
 	{	XFER_PIO_2,	0x03,	0x65,	0x03,	0x65,	0x03,	0x87,	0x03,	0xA8	},
@@ -175,6 +178,7 @@
 
 struct chipset_bus_clock_list_entry via82cxxx_type_four [] = {
 		/* speed */	/* 25 */	/* 33 */	/* 37.5 */	/* 41.5 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
 	{	XFER_UDMA_4,	0x00,	0x00,	0xE0,	0x20,	0xE1,	0x31,	0x00,	0x00	},
 	{	XFER_UDMA_3,	0x00,	0x00,	0xE1,	0x20,	0xE2,	0x31,	0x00,	0x00	},
 	{	XFER_UDMA_2,	0x00,	0x00,	0xE2,	0x20,	0xE4,	0x31,	0x00,	0x00	},
@@ -184,7 +188,7 @@
 	{	XFER_MW_DMA_2,	0x00,	0x00,	0x03,	0x20,	0x03,	0x31,	0x00,	0x00	},
 	{	XFER_MW_DMA_1,	0x00,	0x00,	0x03,	0x31,	0x03,	0x42,	0x00,	0x00	},
 	{	XFER_MW_DMA_0,	0x00,	0x00,	0x03,	0x31,	0x03,	0x42,	0x00,	0x00	},
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
 	{	XFER_PIO_4,	0x00,	0x00,	0x03,	0x20,	0x03,	0x31,	0x00,	0x00	},
 	{	XFER_PIO_3,	0x00,	0x00,	0x03,	0x31,	0x03,	0x42,	0x00,	0x00	},
 	{	XFER_PIO_2,	0x00,	0x00,	0x03,	0x65,	0x03,	0x87,	0x00,	0x00	},
@@ -651,8 +655,7 @@
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
-	byte unit		= (drive->select.b.unit & 0x01);
-	int drive_number	= ((hwif->channel ? 2 : 0) + unit);
+	struct chipset_bus_clock_list_entry * temp_table = NULL;
 
 	byte ata2_pci		= 0x00;
 	byte ata3_pci		= 0x00;
@@ -662,7 +665,10 @@
 
 	int bus_speed		= system_bus_clock();
 
-	switch(drive_number) {
+	if (via82cxxx_table == NULL)
+		return -1;
+
+	switch(drive->dn) {
 		case 0: ata2_pci = 0x4b; ata3_pci = 0x53; break;
 		case 1: ata2_pci = 0x4a; ata3_pci = 0x52; break;
 		case 2: ata2_pci = 0x49; ata3_pci = 0x51; break;
@@ -671,16 +677,26 @@
 			return -1;
 	}
 
+	if ((via82cxxx_table == via82cxxx_type_four) && (speed <= XFER_UDMA_2)) {
+		temp_table = via82cxxx_type_three;
+	} else {
+		temp_table = via82cxxx_table;
+	}
+
 	pci_read_config_byte(dev, ata2_pci, &timing);
-	timing = pci_bus_clock_list(speed, bus_speed, via82cxxx_table);
+	timing = pci_bus_clock_list(speed, bus_speed, temp_table);
 	pci_write_config_byte(dev, ata2_pci, timing);
 
 	pci_read_config_byte(dev, ata3_pci, &ultra);
-	ultra = pci_bus_clock_list_ultra(speed, bus_speed, via82cxxx_table);
+	ultra = pci_bus_clock_list_ultra(speed, bus_speed, temp_table);
 	pci_write_config_byte(dev, ata3_pci, ultra);
 
+	if (!drive->init_speed)
+		drive->init_speed = speed;
+
 	err = ide_config_drive_speed(drive, speed);
 
+	drive->current_speed = speed;
 	return(err);
 }
 
@@ -845,6 +861,7 @@
 	struct pci_dev *isa;
 	int i, j, ata33, ata66;
 
+	int bus_speed = system_bus_clock();
 	byte revision = 0;
 
 	for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) {
@@ -873,18 +890,26 @@
 			ata33 = 1;
 			ata66 = 0;
 
+			via82cxxx_table = ApolloISAChipInfo[j].chipset_table;
+
 			if (ApolloISAChipInfo[j].flags & VIA_FLAG_CHECK_REV) {
 				pci_read_config_byte(isa_dev, 0x0d, &revision);
 				ata33 = (revision >= 0x20) ? 1 : 0;
 			} else if (ApolloISAChipInfo[j].flags & VIA_FLAG_ATA_66) {
+				byte ata66_0 = 0, ata66_1 = 0;
 				ata33 = 0;
 				ata66 = 1;
+				pci_read_config_byte(dev, 0x50, &ata66_1);
+				pci_read_config_byte(dev, 0x52, &ata66_0);
+				if ((ata66_0 & 0x04) || (ata66_1 & 0x04)) {
+					via82cxxx_table = (bus_speed == 33 || bus_speed == 37) ?
+						via82cxxx_type_four :
+						via82cxxx_type_three;
+				}
 			}
 
 			if (ata33 | ata66)
 				printk(" Chipset Core ATA-%s", ata66 ? "66" : "33");
-
-			via82cxxx_table = ApolloISAChipInfo[j].chipset_table;
 		}
 		printk("\n");
 	}
@@ -915,6 +940,7 @@
 
 #ifdef CONFIG_VIA82CXXX_TUNING
 	hwif->tuneproc = &via82cxxx_tune_drive;
+	hwif->speedproc = &via82cxxx_tune_chipset;
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
 	hwif->autodma = 0;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c
--- v2.3.99-pre8/linux/drivers/isdn/avmb1/kcapi.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/isdn/avmb1/kcapi.c	Sun May 21 20:18:08 2000
@@ -320,7 +320,7 @@
 		*eof = 1;
 	if (off >= len+begin)
 		return 0;
-	*start = page + (begin-off);
+	*start = page + (off-begin);
 	return ((count < begin+len-off) ? count : begin+len-off);
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile
--- v2.3.99-pre8/linux/drivers/macintosh/Makefile	Sun Feb 13 19:29:03 2000
+++ linux/drivers/macintosh/Makefile	Sat May 20 12:07:56 2000
@@ -12,20 +12,20 @@
 SUB_DIRS     := 
 MOD_SUB_DIRS := $(SUB_DIRS)
 
-L_TARGET := macintosh.a
-L_OBJS   :=
+O_TARGET := macintosh.o
+O_OBJS   :=
 M_OBJS   :=
 
 ifeq ($(CONFIG_PMAC_PBOOK),y)
-  L_OBJS += mediabay.o
+  O_OBJS += mediabay.o
 else
   ifeq ($(CONFIG_MAC_FLOPPY),y)
-    L_OBJS += mediabay.o
+    O_OBJS += mediabay.o
   endif
 endif
 
 ifeq ($(CONFIG_MAC_SERIAL),y)
-  L_OBJS += macserial.o
+  O_OBJS += macserial.o
 else
   ifeq ($(CONFIG_MAC_SERIAL),m)
     M_OBJS += macserial.o
@@ -33,7 +33,7 @@
 endif
 
 ifeq ($(CONFIG_NVRAM),y)
-  L_OBJS += nvram.o
+  O_OBJS += nvram.o
 else
   ifeq ($(CONFIG_NVRAM),m)
     M_OBJS += nvram.o
@@ -41,39 +41,39 @@
 endif
 
 ifdef CONFIG_ADB
-  LX_OBJS  := adb.o
+  OX_OBJS  := adb.o
 endif
 
 ifdef CONFIG_ADB_KEYBOARD
-  L_OBJS += mac_keyb.o
+  O_OBJS += mac_keyb.o
 endif
 
 ifdef CONFIG_ADB_MACII
-  L_OBJS += via-macii.o
+  O_OBJS += via-macii.o
 endif
 
 ifdef CONFIG_ADB_MACIISI
-  L_OBJS += via-maciisi.o
+  O_OBJS += via-maciisi.o
 endif
 
 ifdef CONFIG_ADB_CUDA
-  L_OBJS += via-cuda.o
+  O_OBJS += via-cuda.o
 endif
 
 ifdef CONFIG_ADB_IOP
-  L_OBJS += adb-iop.o
+  O_OBJS += adb-iop.o
 endif
 
 ifdef CONFIG_ADB_PMU
-  L_OBJS += via-pmu.o
+  O_OBJS += via-pmu.o
 endif
 
 ifdef CONFIG_ADB_PMU68K
-  L_OBJS += via-pmu68k.o
+  O_OBJS += via-pmu68k.o
 endif
 
 ifdef CONFIG_ADB_MACIO
-  L_OBJS += macio-adb.o
+  O_OBJS += macio-adb.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.3.99-pre8/linux/drivers/macintosh/adb.c	Wed Feb 16 17:03:52 2000
+++ linux/drivers/macintosh/adb.c	Sat May 20 12:07:56 2000
@@ -72,6 +72,7 @@
 struct adb_driver *adb_controller;
 struct notifier_block *adb_client_list = NULL;
 static int adb_got_sleep = 0;
+static int adb_inited = 0;
 
 #ifdef CONFIG_PMAC_PBOOK
 static int adb_notify_sleep(struct pmu_sleep_notifier *self, int when);
@@ -213,6 +214,11 @@
 		return 0;
 #endif
 
+	/* xmon may do early-init */
+	if (adb_inited)
+		return 0;
+	adb_inited = 1;
+		
 	adb_controller = NULL;
 
 	i = 0;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/mac_keyb.c linux/drivers/macintosh/mac_keyb.c
--- v2.3.99-pre8/linux/drivers/macintosh/mac_keyb.c	Sun Feb 13 19:29:03 2000
+++ linux/drivers/macintosh/mac_keyb.c	Sat May 20 12:07:56 2000
@@ -16,7 +16,7 @@
  *
  * - Standard 1 button mouse
  * - All standard Apple Extended protocol (handler ID 4)
- * - mouseman and trackman mice & trackballs 
+ * - mouseman and trackman mice & trackballs
  * - PowerBook Trackpad (default setup: enable tapping)
  * - MicroSpeed mouse & trackball (needs testing)
  * - CH Products Trackball Pro (needs testing)
@@ -344,7 +344,7 @@
 #ifdef CONFIG_ADBMOUSE
 	/*
 	 * XXX: Add mouse button 2+3 fake codes here if mouse open.
-	 *	Keep track of 'button' states here as we only send 
+	 *	Keep track of 'button' states here as we only send
 	 *	single up/down events!
 	 *	Really messy; might need to check if keyboard is in
 	 *	VC_RAW mode.
@@ -591,11 +591,12 @@
 static void
 buttons_input(unsigned char *data, int nb, struct pt_regs *regs, int autopoll)
 {
+#ifdef CONFIG_ADB_PMU
 	/*
 	 * XXX: Where is the contrast control for the passive?
 	 *  -- Cort
 	 */
-	 
+
 	/* Ignore data from register other than 0 */
 #if 0
 	if ((adb_hardware != ADB_VIAPMU) || (data[0] & 0x3) || (nb < 2))
@@ -603,7 +604,7 @@
 	if ((data[0] & 0x3) || (nb < 2))
 #endif
 		return;
-		
+
 	switch (data[1]&0xf )
 	{
 		/* mute */
@@ -627,28 +628,25 @@
 		/* brightness decrease */
 		case 0xa:
 			/* down event */
-#ifdef CONFIG_PPC
 			if ( data[1] == (data[1]&0xf) ) {
 				if (backlight_level > 2)
 					pmu_set_brightness(backlight_level-2);
 				else
 					pmu_set_brightness(0);
 			}
-#endif
 			break;
 		/* brightness increase */
 		case 0x9:
 			/* down event */
-#ifdef CONFIG_PPC
 			if ( data[1] == (data[1]&0xf) ) {
 				if (backlight_level < 0x1e)
 					pmu_set_brightness(backlight_level+2);
-				else 
+				else
 					pmu_set_brightness(0x1f);
 			}
-#endif
 			break;
 	}
+#endif /* CONFIG_ADB_PMU */
 }
 
 /* Map led flags as defined in kbd_kern.h to bits for Apple keyboard. */
@@ -736,7 +734,7 @@
 	led_request.complete = 1;
 
 	mackeyb_probe();
-	
+
 	notifier_chain_register(&adb_client_list, &mackeyb_adb_notifier);
 }
 
@@ -744,11 +742,11 @@
 adb_message_handler(struct notifier_block *this, unsigned long code, void *x)
 {
 	unsigned long flags;
-	
+
 	switch (code) {
 	case ADB_MSG_PRE_RESET:
 	case ADB_MSG_POWERDOWN:
-	    	/* Stop the repeat timer. Autopoll is already off at this point */
+		/* Stop the repeat timer. Autopoll is already off at this point */
 		save_flags(flags);
 		cli();
 		del_timer(&repeat_timer);
@@ -758,7 +756,7 @@
 		while(!led_request.complete)
 			adb_poll();
 		break;
-			
+
 	case ADB_MSG_POST_RESET:
 		mackeyb_probe();
 		break;
@@ -841,7 +839,7 @@
 		    || (adb_mouse_kinds[id] == ADBMOUSE_MICROSPEED)) {
 			init_microspeed(id);
 		} else if (adb_mouse_kinds[id] == ADBMOUSE_MS_A3) {
-			init_ms_a3(id);	
+			init_ms_a3(id);
 		}  else if (adb_mouse_kinds[id] ==  ADBMOUSE_EXTENDED) {
 			/*
 			 * Register 1 is usually used for device
@@ -854,7 +852,7 @@
 
 			if ((req.reply_len) &&
 			    (req.reply[1] == 0x9a) && ((req.reply[2] == 0x21)
-			    	|| (req.reply[2] == 0x20)))
+				|| (req.reply[2] == 0x20)))
 				init_trackball(id);
 			else if ((req.reply_len >= 4) &&
 			    (req.reply[1] == 0x74) && (req.reply[2] == 0x70) &&
@@ -877,10 +875,10 @@
         }
 }
 
-static void 
+static void
 init_trackpad(int id)
 {
-	struct adb_request req;	
+	struct adb_request req;
 	unsigned char r1_buffer[8];
 
 	printk(" (trackpad)");
@@ -907,15 +905,15 @@
 
             adb_request(&req, NULL, ADBREQ_SYNC, 9,
 	        ADB_WRITEREG(id,2),
-	    	    0x99,
-	    	    0x94,
-	    	    0x19,
-	    	    0xff,
-	    	    0xb2,
-	    	    0x8a,
-	    	    0x1b,
-	    	    0x50);
-	    
+		    0x99,
+		    0x94,
+		    0x19,
+		    0xff,
+		    0xb2,
+		    0x8a,
+		    0x1b,
+		    0x50);
+
 	    adb_request(&req, NULL, ADBREQ_SYNC, 9,
 	        ADB_WRITEREG(id,1),
 	            r1_buffer[0],
@@ -929,13 +927,13 @@
         }
 }
 
-static void 
+static void
 init_trackball(int id)
 {
 	struct adb_request req;
-	
+
 	printk(" (trackman/mouseman)");
-	
+
 	adb_mouse_kinds[id] = ADBMOUSE_TRACKBALL;
 
 	adb_request(&req, NULL, ADBREQ_SYNC, 3,
@@ -971,7 +969,7 @@
         printk(" (TurboMouse 5)");
 
 	adb_mouse_kinds[id] = ADBMOUSE_TURBOMOUSE5;
-	
+
 	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
 
 	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(3));
@@ -1012,7 +1010,7 @@
 
 	/* This will initialize mice using the Microspeed, MacPoint and
 	   other compatible firmware. Bit 12 enables extended protocol.
-	   
+
 	   Register 1 Listen (4 Bytes)
             0 -  3     Button is mouse (set also for double clicking!!!)
             4 -  7     Button is locking (affects change speed also)
@@ -1027,7 +1025,7 @@
             0 -  7     Product code
             8 - 23     undefined, reserved
            24 - 31     Version number
-        
+
        Speed 0 is max. 1 to 255 set speed in increments of 1/256 of max.
  */
 	adb_request(&req, NULL, ADBREQ_SYNC, 5,
@@ -1051,7 +1049,7 @@
 	ADB_WRITEREG(id, 0x2),
 	    0x00,
 	    0x07);
- 
+
  	adb_request(&req, NULL, ADBREQ_SYNC, 1, ADB_FLUSH(id));
  }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.3.99-pre8/linux/drivers/macintosh/macserial.c	Sun Feb 13 19:29:03 2000
+++ linux/drivers/macintosh/macserial.c	Sat May 20 12:07:56 2000
@@ -131,17 +131,17 @@
 #define _INLINE_ inline
 
 #ifdef SERIAL_DEBUG_OPEN
-#define OPNDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#define OPNDBG(fmt, arg...)	printk(KERN_DEBUG fmt , ## arg)
 #else
 #define OPNDBG(fmt, arg...)	do { } while (0)
 #endif
 #ifdef SERIAL_DEBUG_POWER
-#define PWRDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#define PWRDBG(fmt, arg...)	printk(KERN_DEBUG fmt , ## arg)
 #else
 #define PWRDBG(fmt, arg...)	do { } while (0)
 #endif
 #ifdef SERIAL_DEBUG_BAUDS
-#define BAUDBG(fmt, arg...)	printk(KERN_INFO fmt , ## arg)
+#define BAUDBG(fmt, arg...)	printk(fmt , ## arg)
 #else
 #define BAUDBG(fmt, arg...)	do { } while (0)
 #endif
@@ -414,7 +414,7 @@
 			continue;
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 			tty_flip_buffer_push(tty);
-			
+
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
 			static int flip_buf_ovf;
 			if (++flip_buf_ovf <= 1)
@@ -505,7 +505,7 @@
 			if (info->tx_stopped) {
 #ifdef SERIAL_DEBUG_FLOW
 				printk("CTS up\n");
-#endif			
+#endif
 				info->tx_stopped = 0;
 				if (!info->tx_active)
 					transmit_chars(info);
@@ -513,7 +513,7 @@
 		} else {
 #ifdef SERIAL_DEBUG_FLOW
 			printk("CTS down\n");
-#endif			
+#endif
 			info->tx_stopped = 1;
 		}
 	}
@@ -536,7 +536,7 @@
 	    == virt_to_bus(info->rx_cmds[info->rx_cbuf] + 1))
 		where -= in_le16(&info->rx->res_count);
 	where--;
-	
+
 	stat = read_zsreg(info->zs_channel, R1);
 
 	flag = stat_to_flag(stat);
@@ -582,7 +582,7 @@
 #ifdef SERIAL_DEBUG_INTR
 		printk("rs_interrupt: irq %d, zs_intreg 0x%x\n",
 		       irq, (int)zs_intreg);
-#endif	
+#endif
 
 		if ((zs_intreg & CHAN_IRQMASK) == 0)
 			break;
@@ -659,7 +659,7 @@
 
 	if (serial_paranoia_check(info, tty->device, "rs_stop"))
 		return;
-	
+
 #if 0
 	save_flags(flags); cli();
 	if (info->curregs[5] & TxENAB) {
@@ -675,7 +675,7 @@
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
-	
+
 #ifdef SERIAL_DEBUG_STOP
 	printk("rs_start %ld....\n", 
 	       tty->ldisc.chars_in_buffer(tty));
@@ -683,7 +683,7 @@
 
 	if (serial_paranoia_check(info, tty->device, "rs_start"))
 		return;
-	
+
 	save_flags(flags); cli();
 #if 0
 	if (info->xmit_cnt && info->xmit_buf && !(info->curregs[5] & TxENAB)) {
@@ -717,7 +717,7 @@
 {
 	struct mac_serial	*info = (struct mac_serial *) private_;
 	struct tty_struct	*tty;
-	
+
 	tty = info->tty;
 	if (!tty)
 		return;
@@ -750,7 +750,7 @@
 	OPNDBG("starting up ttyS%d (irq %d)...\n", info->line, info->irq);
 
 	delay = set_scc_power(info, 1);
-	
+
 	setup_scc(info);
 
 	OPNDBG("enabling IRQ on ttyS%d (irq %d)...\n", info->line, info->irq);
@@ -758,7 +758,6 @@
 	info->flags |= ZILOG_INITIALIZED;
 	enable_irq(info->irq);
 	if (info->dma_initted) {
-//		enable_irq(info->tx_dma_irq);
 		enable_irq(info->rx_dma_irq);
 	}
 
@@ -881,8 +880,6 @@
 	volatile struct dbdma_cmd *cd;
 	unsigned char *p;
 
-//printk(KERN_DEBUG "SCC: dma_init\n");
-
 	info->rx_nbuf = 8;
 
 	/* various mem set up */
@@ -958,10 +955,10 @@
 static int setup_scc(struct mac_serial * info)
 {
 	unsigned long flags;
-	
+
 	OPNDBG("setting up ttys%d SCC...\n", info->line);
 
-	save_flags(flags); cli(); /* Disable interrupts */	
+	save_flags(flags); cli(); /* Disable interrupts */
 
 	/*
 	 * Reset the chip.
@@ -992,7 +989,8 @@
 	/*
 	 * Turn on RTS and DTR.
 	 */
-	zs_rtsdtr(info, 1);
+	if (!info->is_irda)
+		zs_rtsdtr(info, 1);
 
 	/*
 	 * Finally, enable sequencing and interrupts
@@ -1058,7 +1056,7 @@
 {
 	OPNDBG("Shutting down serial port %d (irq %d)....\n", info->line,
 	       info->irq);
-	
+
 	if (!(info->flags & ZILOG_INITIALIZED)) {
 		OPNDBG("(already shutdown)\n");
 		return;
@@ -1124,7 +1122,7 @@
 	/* The timings looks strange but that's the ones MacOS seems
 	   to use for the internal modem. I think we can use a lot faster
 	   ones, at least whe not using the modem, this should be tested.
-	 */				
+	 */
 	if (state) {
 		PWRDBG("ttyS%02d: powering up hardware\n", info->line);
 		if (feature_test(info->dev_node, FEATURE_Serial_enable) == 0) {
@@ -1150,7 +1148,7 @@
 			delay = 2500;	/* wait for 2.5s before using */
 		}
 #ifdef CONFIG_PMAC_PBOOK
-		if (info->is_pwbk_ir)
+		if (info->is_irda)
 			pmu_enable_irled(1);
 #endif /* CONFIG_PMAC_PBOOK */
 	} else {
@@ -1161,14 +1159,14 @@
 			mdelay(10);
 		}
 #ifdef CONFIG_PMAC_PBOOK
-		if (info->is_pwbk_ir)
+		if (info->is_irda)
 			pmu_enable_irled(0);
 #endif /* CONFIG_PMAC_PBOOK */
-			
-		if (info->zs_chan_a == info->zs_channel) {
+
+		if (info->zs_chan_a == info->zs_channel && !info->is_irda) {
 			PWRDBG("ttyS%02d: shutting down SCC channel A\n", info->line);
 			feature_clear(info->dev_node, FEATURE_Serial_IO_A);
-		} else {
+		} else if (!info->is_irda) {
 			PWRDBG("ttyS%02d: shutting down SCC channel B\n", info->line);
 			feature_clear(info->dev_node, FEATURE_Serial_IO_B);
 		}
@@ -1188,6 +1186,113 @@
 	return delay;
 }
 
+static void irda_rts_pulses(struct mac_serial *info, int w)
+{
+	unsigned long flags;
+
+	udelay(w);
+	save_flags(flags); cli();
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);
+	udelay(2);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+	udelay(8);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB);
+	udelay(4);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+	restore_flags(flags);
+}
+
+/*
+ * Set the irda codec on the imac to the specified baud rate.
+ */
+static void irda_setup(struct mac_serial *info)
+{
+	int code, speed, t;
+	unsigned long flags;
+
+	speed = info->tty->termios->c_cflag & CBAUD;
+	if (speed < B2400 || speed > B115200)
+		return;
+	code = 0x4d + B115200 - speed;
+
+	/* disable serial interrupts and receive DMA */
+	write_zsreg(info->zs_channel, 1, info->curregs[1] & ~0x9f);
+
+	/* wait for transmitter to drain */
+	t = 10000;
+	while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP) == 0
+	       || (read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
+		if (--t <= 0) {
+			printk(KERN_ERR "transmitter didn't drain\n");
+			return;
+		}
+		udelay(10);
+	}
+	udelay(100);
+
+	/* set to 8 bits, no parity, 19200 baud, RTS on, DTR off */
+	write_zsreg(info->zs_channel, 4, X16CLK | SB1);
+	write_zsreg(info->zs_channel, 11, TCBR | RCBR);
+	t = BPS_TO_BRG(19200, ZS_CLOCK/16);
+	write_zsreg(info->zs_channel, 12, t);
+	write_zsreg(info->zs_channel, 13, t >> 8);
+	write_zsreg(info->zs_channel, 14, BRENABL);
+	write_zsreg(info->zs_channel, 3, Rx8 | RxENABLE);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+
+	/* set TxD low for ~104us and pulse RTS */
+	udelay(1000);
+	save_flags(flags); cli();
+	write_zsdata(info->zs_channel, 0xfe);
+	irda_rts_pulses(info, 150);
+	restore_flags(flags);
+	irda_rts_pulses(info, 180);
+	irda_rts_pulses(info, 50);
+	udelay(100);
+
+	/* assert DTR, wait 30ms, talk to the chip */
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR);
+	udelay(30000);
+	while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV)
+		read_zsdata(info->zs_channel);
+
+	write_zsdata(info->zs_channel, 1);
+	t = 1000;
+	while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {
+		if (--t <= 0) {
+			printk(KERN_ERR "irda_setup timed out on 1st byte\n");
+			goto out;
+		}
+		udelay(10);
+	}
+	t = read_zsdata(info->zs_channel);
+	if (t != 4)
+		printk(KERN_ERR "irda_setup 1st byte = %x\n", t);
+
+	write_zsdata(info->zs_channel, code);
+	t = 1000;
+	while ((read_zsreg(info->zs_channel, 0) & Rx_CH_AV) == 0) {
+		if (--t <= 0) {
+			printk(KERN_ERR "irda_setup timed out on 2nd byte\n");
+			goto out;
+		}
+		udelay(10);
+	}
+	t = read_zsdata(info->zs_channel);
+	if (t != code)
+		printk(KERN_ERR "irda_setup 2nd byte = %x (%x)\n", t, code);
+
+	/* Drop DTR again and do some more RTS pulses */
+ out:
+	udelay(100);
+	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS);
+	irda_rts_pulses(info, 80);
+
+	/* We should be right to go now.  We assume that load_zsregs
+	   will get called soon to load up the correct baud rate etc. */
+	info->curregs[5] = (info->curregs[5] | RTS) & ~DTR;
+	info->pendregs[5] = info->curregs[5];
+}
 
 /*
  * This routine is called to set the UART divisor registers to match
@@ -1195,7 +1300,6 @@
  */
 static void change_speed(struct mac_serial *info, struct termios *old_termios)
 {
-	unsigned short port;
 	unsigned cflag;
 	int	bits;
 	int	brg, baud;
@@ -1203,8 +1307,6 @@
 
 	if (!info->tty || !info->tty->termios)
 		return;
-	if (!(port = info->port))
-		return;
 
 	cflag = info->tty->termios->c_cflag;
 	baud = tty_get_baud_rate(info->tty);
@@ -1227,7 +1329,7 @@
 	info->zs_baud = baud;
 	info->clk_divisor = 16;
 
-	BAUDBG("set speed to %d bds, ", baud);
+	BAUDBG(KERN_DEBUG "set speed to %d bds, ", baud);
 
 	switch (baud) {
 	case ZS_CLOCK/16:	/* 230400 */
@@ -1325,6 +1427,10 @@
 	BAUDBG("timeout=%d/%ds, base:%d\n", (int)info->timeout, (int)HZ,
 	       (int)info->baud_base);
 
+	/* set the irda codec to the right rate */
+	if (info->is_irda)
+		irda_setup(info);
+
 	/* Load up the new values */
 	load_zsregs(info->zs_channel, info->curregs);
 
@@ -1391,7 +1497,7 @@
 	} else {
 		while (1) {
 			save_flags(flags);
-			cli();		
+			cli();
 			c = MIN(count,
 				MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				    SERIAL_XMIT_SIZE - info->xmit_head));
@@ -1419,7 +1525,7 @@
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	int	ret;
-				
+
 	if (serial_paranoia_check(info, tty->device, "rs_write_room"))
 		return 0;
 	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
@@ -1431,7 +1537,7 @@
 static int rs_chars_in_buffer(struct tty_struct *tty)
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
-				
+
 	if (serial_paranoia_check(info, tty->device, "rs_chars_in_buffer"))
 		return 0;
 	return info->xmit_cnt;
@@ -1441,7 +1547,7 @@
 {
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
-				
+
 	if (serial_paranoia_check(info, tty->device, "rs_flush_buffer"))
 		return;
 	save_flags(flags); cli();
@@ -1466,13 +1572,12 @@
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
-	
 	printk("throttle %ld....\n",tty->ldisc.chars_in_buffer(tty));
 #endif
 
 	if (serial_paranoia_check(info, tty->device, "rs_throttle"))
 		return;
-	
+
 	if (I_IXOFF(tty)) {
 		save_flags(flags); cli();
 		info->x_char = STOP_CHAR(tty);
@@ -1502,13 +1607,12 @@
 	struct mac_serial *info = (struct mac_serial *)tty->driver_data;
 	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
-	
 	printk("unthrottle %s: %d....\n",tty->ldisc.chars_in_buffer(tty));
 #endif
 
 	if (serial_paranoia_check(info, tty->device, "rs_unthrottle"))
 		return;
-	
+
 	if (I_IXOFF(tty)) {
 		save_flags(flags); cli();
 		if (info->x_char)
@@ -1685,8 +1789,6 @@
 
 	if (serial_paranoia_check(info, tty->device, "rs_break"))
 		return;
-	if (!info->port)
-		return;
 
 	save_flags(flags); cli();
 	if (break_state == -1)
@@ -1714,7 +1816,7 @@
 		if (tty->flags & (1 << TTY_IO_ERROR))
 		    return -EIO;
 	}
-	
+
 	switch (cmd) {
 		case TIOCMGET:
 			return get_modem_info(info, (unsigned int *) arg);
@@ -1736,7 +1838,7 @@
 					 info, sizeof(struct mac_serial)))
 				return -EFAULT;
 			return 0;
-			
+
 		default:
 			return -ENOIOCTLCMD;
 		}
@@ -1775,15 +1877,15 @@
 
 	if (!info || serial_paranoia_check(info, tty->device, "rs_close"))
 		return;
-	
+
 	save_flags(flags); cli();
-	
+
 	if (tty_hung_up_p(filp)) {
 		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 		return;
 	}
-	
+
 	OPNDBG("rs_close ttys%d, count = %d\n", info->line, info->count);
 	if ((tty->count == 1) && (info->count != 1)) {
 		/*
@@ -1984,7 +2086,7 @@
 		info->flags |= ZILOG_CALLOUT_ACTIVE;
 		return 0;
 	}
-	
+
 	/*
 	 * If non-blocking mode is set, or the port is not enabled,
 	 * then make the check up front and then exit.
@@ -2004,7 +2106,7 @@
 		if (tty->termios->c_cflag & CLOCAL)
 			do_clocal = 1;
 	}
-	
+
 	/*
 	 * Block waiting for the carrier detect and the line to become
 	 * free (i.e., not in use by the callout).  While we are in
@@ -2024,7 +2126,8 @@
 	while (1) {
 		cli();
 		if (!(info->flags & ZILOG_CALLOUT_ACTIVE) &&
-		    (tty->termios->c_cflag & CBAUD))
+		    (tty->termios->c_cflag & CBAUD) &&
+		    !info->is_irda)
 			zs_rtsdtr(info, 1);
 		sti();
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -2034,7 +2137,7 @@
 			if (info->flags & ZILOG_HUP_NOTIFY)
 				retval = -EAGAIN;
 			else
-				retval = -ERESTARTSYS;	
+				retval = -ERESTARTSYS;
 #else
 			retval = -EAGAIN;
 #endif
@@ -2063,7 +2166,7 @@
 		return retval;
 	info->flags |= ZILOG_NORMAL_ACTIVE;
 	return 0;
-}	
+}
 
 /*
  * This routine is called whenever a serial port is opened.  It
@@ -2208,11 +2311,11 @@
 	/* XXX tested only with wallstreet PowerBook,
 	   should do no harm anyway */
 	conn = get_property(ch, "AAPL,connector", &len);
-	zss->is_pwbk_ir = conn && (strcmp(conn, "infrared") == 0);
+	zss->is_irda = conn && (strcmp(conn, "infrared") == 0);
 	/* 1999 Powerbook G3 has slot-names property instead */
 	slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len);
 	if (slots && slots->count > 0 && strcmp(slots->name, "IrDA") == 0)
-		zss->is_pwbk_ir = 1;
+		zss->is_irda = 1;
 
 	if (zss->has_dma) {
 		zss->dma_priv = NULL;
@@ -2345,7 +2448,11 @@
 
 	memset(&serial_driver, 0, sizeof(struct tty_driver));
 	serial_driver.magic = TTY_DRIVER_MAGIC;
+#ifdef CONFIG_DEVFS_FS
+	serial_driver.name = "tts/%d";
+#else
 	serial_driver.name = "ttyS";
+#endif /* CONFIG_DEVFS_FS */
 	serial_driver.major = TTY_MAJOR;
 	serial_driver.minor_start = 64;
 	serial_driver.num = zs_channels_found;
@@ -2383,7 +2490,11 @@
 	 * major number and the subtype code.
 	 */
 	callout_driver = serial_driver;
+#ifdef CONFIG_DEVFS_FS
+	callout_driver.name = "cua/%d";
+#else
 	callout_driver.name = "cua";
+#endif /* CONFIG_DEVFS_FS */
 	callout_driver.major = TTYAUX_MAJOR;
 	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
 
@@ -2402,7 +2513,7 @@
 		zs_soft[channel].clk_divisor = 16;
 /* -- we are not sure the SCC is powered ON at this point
  		zs_soft[channel].zs_baud = get_zsbaud(&zs_soft[channel]);
-*/		
+*/
 		zs_soft[channel].zs_baud = 38400;
 
 		/* If console serial line, then enable interrupts. */
@@ -2453,16 +2564,16 @@
 			printk(", port = %s", connector);
 		if (info->is_cobalt_modem)
 			printk(" (cobalt modem)");
-		if (info->is_pwbk_ir)
-			printk(" (powerbook IR)");
+		if (info->is_irda)
+			printk(" (IrDA)");
 		printk("\n");
 
 #ifndef CONFIG_XMON
 #ifdef CONFIG_KGDB
 		if (!info->kgdb_channel)
 #endif /* CONFIG_KGDB */
-		/* By default, disable the port */
-		set_scc_power(info, 0);
+			/* By default, disable the port */
+			set_scc_power(info, 0);
 #endif /* CONFIG_XMON */
  	}
 	tmp_buf = 0;
@@ -2561,7 +2672,7 @@
 			while ((read_zsreg(info->zs_channel, 0) & Tx_BUF_EMP)
                                 == 0)
 				eieio();
-			
+
 			write_zsdata(info->zs_channel, 13);
 		}
 	}
@@ -2869,7 +2980,7 @@
 		probe_sccs();
 
 	set_scc_power(&zs_soft[tty_num], 1);
-	
+
 	zs_kgdbchan = zs_soft[tty_num].zs_channel;
 	zs_soft[tty_num].change_needed = 0;
 	zs_soft[tty_num].clk_divisor = 16;
@@ -2891,12 +3002,12 @@
 serial_notify_sleep(struct pmu_sleep_notifier *self, int when)
 {
 	int i;
-	
+
 	switch (when) {
 	case PBOOK_SLEEP_REQUEST:
 	case PBOOK_SLEEP_REJECT:
 		break;
-		
+
 	case PBOOK_SLEEP_NOW:
 		for (i=0; i<zs_channels_found; i++) {
 			struct mac_serial *info = &zs_soft[i];
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/macserial.h linux/drivers/macintosh/macserial.h
--- v2.3.99-pre8/linux/drivers/macintosh/macserial.h	Fri Oct 22 13:21:49 1999
+++ linux/drivers/macintosh/macserial.h	Sat May 20 12:07:56 2000
@@ -111,7 +111,7 @@
 	char kgdb_channel;  /* Kgdb is running on this channel */
 	char is_cons;       /* Is this our console. */
 	char is_cobalt_modem;	/* is a gatwick-based cobalt modem */
-	char is_pwbk_ir;	/* is connected to an IR led on powerbooks */
+	char is_irda;		/* is connected to an IrDA codec */
 	unsigned char tx_active; /* character is being xmitted */
 	unsigned char tx_stopped; /* output is suspended */
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c
--- v2.3.99-pre8/linux/drivers/macintosh/mediabay.c	Thu May 11 15:30:07 2000
+++ linux/drivers/macintosh/mediabay.c	Sat May 20 12:07:56 2000
@@ -3,6 +3,8 @@
  *
  * Copyright (C) 1998 Paul Mackerras.
  *
+ * Various evolutions by Benjamin Herrenschmidt & Henry Worth
+ *
  *  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
@@ -56,12 +58,15 @@
 
 struct media_bay_info {
 	volatile struct media_bay_hw*	addr;
+	volatile u8*			extint_gpio;
 	int				content_id;
 	int				state;
 	int				last_value;
 	int				value_count;
 	int				timer;
 	struct device_node*		dev_node;
+	int				pismo;	/* New PowerBook3,1 */
+	int				gpio_cache;
 #ifdef CONFIG_BLK_DEV_IDE
 	unsigned long			cd_base;
 	int 				cd_index;
@@ -75,7 +80,25 @@
 static volatile struct media_bay_info media_bays[MAX_BAYS];
 int media_bay_count = 0;
 
-#define MB_CONTENTS(i)	((in_8(&media_bays[i].addr->contents) >> 4) & 7)
+inline int mb_content(volatile struct media_bay_info *bay)
+{
+        if (bay->pismo) {
+                unsigned char new_gpio = in_8(bay->extint_gpio + 0xe) & 2;
+                if (new_gpio) {
+                	bay->gpio_cache = new_gpio;
+                        return MB_NO;
+                } else if (bay->gpio_cache != new_gpio) {
+                        /* make sure content bits are set */
+                        feature_set(bay->dev_node, FEATURE_Mediabay_content);
+                        udelay(5);
+                        bay->gpio_cache = new_gpio;
+                }
+                return (in_le32((unsigned*)bay->addr) >> 4) & 0xf;
+        } else {
+                int cont = (in_8(&bay->addr->contents) >> 4) & 7;
+                return (cont == 7) ? MB_NO : cont;
+        }
+}
 
 #ifdef CONFIG_BLK_DEV_IDE
 /* check the busy bit in the media-bay ide interface
@@ -184,12 +207,22 @@
 		media_bays[n].addr = (volatile struct media_bay_hw *)
 			ioremap(np->addrs[0].address, sizeof(struct media_bay_hw));
 
+		media_bays[n].pismo = device_is_compatible(np, "keylargo-media-bay");
+		if (media_bays[n].pismo) {
+			if (!np->parent || strcmp(np->parent->name, "mac-io")) {
+				printk(KERN_ERR "Pismo media-bay has no mac-io parent !\n");
+				continue;
+			}
+			media_bays[n].extint_gpio = ioremap(np->parent->addrs[0].address
+				+ 0x58, 0x10);
+		}
+
 #ifdef MB_USE_INTERRUPTS
 		if (np->n_intrs == 0) {
 			printk(KERN_ERR "media bay %d has no irq\n",n);
 			continue;
 		}
-		
+
 		if (request_irq(np->intrs[0].line, media_bay_intr, 0, "Media bay", (void *)n)) {
 			printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n",
 				np->intrs[0].line, n);
@@ -203,10 +236,11 @@
 		/* Force an immediate detect */
 		set_mb_power(n,0);
 		mdelay(MB_POWER_DELAY);
-		out_8(&media_bays[n].addr->contents, 0x70);
+		if(!media_bays[n].pismo)
+			out_8(&media_bays[n].addr->contents, 0x70);
 		mdelay(MB_STABLE_DELAY);
 		media_bays[n].content_id = MB_NO;
-		media_bays[n].last_value = MB_CONTENTS(n);
+		media_bays[n].last_value = mb_content(&media_bays[n]);
 		media_bays[n].value_count = MS_TO_HZ(MB_STABLE_DELAY);
 		media_bays[n].state = mb_empty;
 		do {
@@ -214,11 +248,11 @@
 			media_bay_step(n);
 		} while((media_bays[n].state != mb_empty) &&
 			(media_bays[n].state != mb_up));
-		
+
 		n++;
 		np=np->next;
 	}
-	
+
 	if (media_bay_count)
 	{
 		printk(KERN_INFO "Registered %d media-bay(s)\n", media_bay_count);
@@ -227,7 +261,8 @@
 		pmu_register_sleep_notifier(&mb_sleep_notifier);
 #endif /* CONFIG_PMAC_PBOOK */
 
-		kernel_thread(media_bay_task, NULL, 0);
+		kernel_thread(media_bay_task, NULL,
+			      CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
 	}
 }
 
@@ -252,7 +287,11 @@
 		MBDBG("mediabay%d: powering up\n", which);
 	} else {
 		feature_clear(mb->dev_node, FEATURE_Mediabay_floppy_enable);
-		feature_clear(mb->dev_node, FEATURE_IDE1_enable);
+		if (mb->pismo)
+			feature_clear(mb->dev_node, FEATURE_IDE0_enable);
+		else
+			feature_clear(mb->dev_node, FEATURE_IDE1_enable);
+		feature_clear(mb->dev_node, FEATURE_Mediabay_IDE_switch);
 		feature_clear(mb->dev_node, FEATURE_Mediabay_PCI_enable);
 		feature_clear(mb->dev_node, FEATURE_SWIM3_enable);
 		feature_clear(mb->dev_node, FEATURE_Mediabay_power);
@@ -271,9 +310,17 @@
 	
 	switch (id) {
 	case MB_CD:
-		feature_set(bay->dev_node, FEATURE_IDE1_enable);
-		udelay(10);
-		feature_set(bay->dev_node, FEATURE_IDE1_reset);
+		if (bay->pismo) {
+			feature_set(bay->dev_node, FEATURE_Mediabay_IDE_switch);
+			udelay(10);
+			feature_set(bay->dev_node, FEATURE_IDE0_enable);
+			udelay(10);
+			feature_set(bay->dev_node, FEATURE_IDE0_reset);
+		} else {
+			feature_set(bay->dev_node, FEATURE_IDE1_enable);
+			udelay(10);
+			feature_set(bay->dev_node, FEATURE_IDE1_reset);
+		}
 		printk(KERN_INFO "media bay %d contains a CD-ROM drive\n", which);
 		break;
 	case MB_FD:
@@ -345,8 +392,8 @@
 
 			if ((MB_CD != media_bays[i].content_id) || media_bays[i].state != mb_up)
 				return 0;
-				
-			printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i);			
+
+			printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i);
 			do {
 				if (MB_IDE_READY(i)) {
 					media_bays[i].cd_index	= index;
@@ -354,7 +401,7 @@
 				}
 				mdelay(1);
 			} while(--timeout);
-			printk(KERN_DEBUG "Timeout waiting IDE in bay %d\n", i);			
+			printk(KERN_DEBUG "Timeount waiting IDE in bay %d\n", i);
 			return -ENODEV;
 		} 
 #endif
@@ -397,7 +444,10 @@
 	    	}
 #ifdef CONFIG_BLK_DEV_IDE
 		MBDBG("mediabay%d: waiting IDE reset (kind:%d)\n", i, bay->content_id);
-	    	feature_clear(bay->dev_node, FEATURE_IDE1_reset);
+		if (bay->pismo)
+	    		feature_clear(bay->dev_node, FEATURE_IDE0_reset);
+		else
+	    		feature_clear(bay->dev_node, FEATURE_IDE1_reset);
 	    	bay->timer = MS_TO_HZ(MB_IDE_WAIT);
 	    	bay->state = mb_ide_resetting;
 #else
@@ -476,23 +526,21 @@
 int __pmac
 media_bay_task(void *x)
 {
-	int	i = 0;
-	
+	int	i;
+
 	strcpy(current->comm, "media-bay");
 #ifdef MB_IGNORE_SIGNALS
 	sigfillset(&current->blocked);
 #endif
 
 	for (;;) {
-	    media_bay_step(i);
+		for (i = 0; i < media_bay_count; ++i)
+			media_bay_step(i);
 
-	    if (++i >= media_bay_count) {
-		i = 0;
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(1);
 		if (signal_pending(current))
 			return 0;
-	    }
 	}
 }
 
@@ -500,7 +548,7 @@
 poll_media_bay(int which)
 {
 	volatile struct media_bay_info* bay = &media_bays[which];
-	int id = MB_CONTENTS(which);
+	int id = mb_content(bay);
 
 	if (id == bay->last_value) {
 	    if (id != bay->content_id
@@ -548,27 +596,26 @@
 			bay = &media_bays[i];
 			set_mb_power(i, 0);
 			mdelay(10);
-			out_8(&bay->addr->contents, 0x70);
 		}
 		break;
 	case PBOOK_WAKE:
 		for (i=0; i<media_bay_count; i++) {
 			bay = &media_bays[i];
 			/* We re-enable the bay using it's previous content
-			   only if it did not change. Note those bozo timings, they seem
-			   to help the 3400 get it right
+			   only if it did not change. Note those bozo timings,
+			   they seem to help the 3400 get it right.
 			 */
 			mdelay(MB_STABLE_DELAY);
-			out_8(&bay->addr->contents, 0x70);
+			if (!bay->pismo)
+				out_8(&bay->addr->contents, 0x70);
 			mdelay(MB_STABLE_DELAY);
-			if (MB_CONTENTS(i) != bay->content_id)
+			if (mb_content(bay) != bay->content_id)
 				continue;
 			set_mb_power(i, 1);
-			mdelay(MB_POWER_DELAY);
-			media_bays[i].last_value = bay->content_id;
-			media_bays[i].value_count = MS_TO_HZ(MB_STABLE_DELAY);
-			media_bays[i].timer = 0;
-			media_bays[i].cd_retry = 0;
+			bay->last_value = bay->content_id;
+			bay->value_count = MS_TO_HZ(MB_STABLE_DELAY);
+			bay->timer = MS_TO_HZ(MB_POWER_DELAY);
+			bay->cd_retry = 0;
 			do {
 				mdelay(1000/HZ);
 				media_bay_step(i);
@@ -580,3 +627,4 @@
 	return PBOOK_SLEEP_OK;
 }
 #endif /* CONFIG_PMAC_PBOOK */
+
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/nvram.c linux/drivers/macintosh/nvram.c
--- v2.3.99-pre8/linux/drivers/macintosh/nvram.c	Thu Feb 10 17:11:09 2000
+++ linux/drivers/macintosh/nvram.c	Sat May 20 12:07:56 2000
@@ -96,21 +96,18 @@
 	&nvram_fops
 };
 
-int nvram_init(void)
+int __init nvram_init(void)
 {
 	printk(KERN_INFO "Macintosh non-volatile memory driver v%s\n",
 		NVRAM_VERSION);
 	misc_register(&nvram_dev);
 	return 0;
 }
-#ifdef MODULE
-int init_module (void)
-{
-        return( nvram_init() );
-}
 
-void cleanup_module (void)
+void __exit nvram_cleanup(void)
 {
         misc_deregister( &nvram_dev );
 }
-#endif
+
+module_init(nvram_init);
+module_exit(nvram_cleanup);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.3.99-pre8/linux/drivers/macintosh/via-pmu.c	Thu Feb 10 17:11:09 2000
+++ linux/drivers/macintosh/via-pmu.c	Sat May 20 12:07:56 2000
@@ -41,6 +41,7 @@
 #include <asm/feature.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#include <asm/heathrow.h>
 
 /* Misc minor number allocated for /dev/pmu */
 #define PMU_MINOR	154
@@ -201,7 +202,7 @@
 	"PowerBook 2400/3400/3500(G3)",
 	"PowerBook G3 Series",
 	"1999 PowerBook G3",
-	"Core99 (iBook/iMac/G4)"
+	"Core99"
 };
 
 int __openfirmware
@@ -326,7 +327,7 @@
 	out_8(&via[IER], IER_SET | SR_INT | CB1_INT);
 
 	pmu_fully_inited = 1;
-	
+
 	/* Enable backlight */
 	pmu_enable_backlight(1);
 }
@@ -508,7 +509,7 @@
 
 	if (save_autopoll != 0)
 		pmu_adb_autopoll(save_autopoll);
-		
+
 	return 0;
 }
 
@@ -845,9 +846,9 @@
 		} else {
 #ifdef CONFIG_XMON
 			if (len == 4 && data[1] == 0x2c) {
-				extern int xmon_wants_key, xmon_pmu_keycode;
+				extern int xmon_wants_key, xmon_adb_keycode;
 				if (xmon_wants_key) {
-					xmon_pmu_keycode = data[2];
+					xmon_adb_keycode = data[2];
 					return;
 				}
 			}
@@ -886,7 +887,7 @@
 
 	if ((vias == NULL) || !pmu_has_backlight)
 		return;
-		
+
 	/* first call: get current backlight value */
 	if (on && backlight_level < 0) {
 		switch (pmu_kind) {
@@ -983,12 +984,12 @@
 	struct adb_request req;
 
 	cli();
-	
+
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
 					PMU_INT_TICK );
 	while(!req.complete)
 		pmu_poll();
-	
+
 	pmu_request(&req, NULL, 1, PMU_RESET);
 	while(!req.complete || (pmu_state != idle))
 		pmu_poll();
@@ -1002,7 +1003,7 @@
 	struct adb_request req;
 
 	cli();
-	
+
 	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
 					PMU_INT_TICK );
 	while(!req.complete)
@@ -1065,6 +1066,8 @@
 		current = list_entry(list, struct pmu_sleep_notifier, list);
 		ret = current->notifier_call(current, when);
 		if (ret != PBOOK_SLEEP_OK) {
+			printk(KERN_DEBUG "sleep %d rejected by %p (%p)\n",
+			       when, current, current->notifier_call);
 			for (; list != &sleep_notifiers; list = list->next) {
 				current = list_entry(list, struct pmu_sleep_notifier, list);
 				current->notifier_call(current, fallback);
@@ -1179,7 +1182,7 @@
 		while (!req.complete) pmu_poll();
 		udelay(50000);
 	}
-	udelay(50000);
+	udelay(150000);
 }
 #endif
 
@@ -1240,20 +1243,14 @@
 
 	/* Make sure the decrementer won't interrupt us */
 	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-#if 0
-	/* Save the state of PCI config space for some slots */
-	pbook_pci_save();
-#endif
+
 	/* For 750, save backside cache setting and disable it */
 	save_l2cr = _get_L2CR();	/* (returns 0 if not 750) */
 	if (save_l2cr)
 		_set_L2CR(0);
 
-	if (macio_base != 0) {
+	if (macio_base != 0)
 		save_fcr = in_le32(FEATURE_CTRL(macio_base));
-		/* Check if this is still valid on older powerbooks */
-		out_le32(FEATURE_CTRL(macio_base), save_fcr & ~(0x00000140UL));
-	}
 
 	if (current->thread.regs && (current->thread.regs->msr & MSR_FP) != 0)
 		giveup_fpu(current);
@@ -1267,12 +1264,15 @@
 	/* Ask the PMU to put us to sleep */
 	pmu_request(&sleep_req, NULL, 5, PMU_SLEEP, 'M', 'A', 'T', 'T');
 	while (!sleep_req.complete)
-		mb();
+		pmu_poll();
 
 	cli();
 	while (pmu_state != idle)
 		pmu_poll();
 
+	/* clear IOBUS enable */
+	out_le32(FEATURE_CTRL(macio_base), save_fcr & ~HRW_IOBUS_ENABLE);
+
 	/* Call low-level ASM sleep handler */
 	low_sleep_handler();
 
@@ -1281,17 +1281,15 @@
 	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
 	grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
 
+	/* reenable IOBUS */
+	out_le32(FEATURE_CTRL(macio_base), save_fcr | HRW_IOBUS_ENABLE);
+
 	/* Make sure the PMU is idle */
 	while (pmu_state != idle)
 		pmu_poll();
 
 	sti();
-#if 0
-	/* According to someone from Apple, this should not be needed,
-	   at least not for all devices. Let's keep it for now until we
-	   have something that works. */
-	pbook_pci_restore();
-#endif
+
 	set_context(current->mm->context);
 
 	/* Restore L2 cache */
@@ -1302,6 +1300,7 @@
 	sleep_restore_intrs();
 
 	/* Notify drivers */
+	mdelay(10);
 	broadcast_wake();
 
 	return 0;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.3.99-pre8/linux/drivers/net/3c59x.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/3c59x.c	Sat May 13 08:19:21 2000
@@ -423,7 +423,7 @@
 	{ 0x10B7, 0x6560, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFE656 },
 	{ 0x10B7, 0x6562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3CCFEM656 },
 	{ 0x10B7, 0x4500, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_3C450 },
-	{0,},						/* 0 terminated list. */
+	{0,}						/* 0 terminated list. */
 };
 MODULE_DEVICE_TABLE(pci, vortex_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/8139too.c linux/drivers/net/8139too.c
--- v2.3.99-pre8/linux/drivers/net/8139too.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/8139too.c	Sat May 20 11:38:03 2000
@@ -24,6 +24,15 @@
 		Daniel Kobras - identified specific locations of
 			posted MMIO write bugginess
 
+		Gerard Sharp - bug fix
+
+	Submitting bug reports:
+
+		"rtl8139-diag -mmmaaavvveefN" output
+		enable RTL8139_DEBUG below, and look at 'dmesg' or kernel log
+
+		See 8139too.txt for more details.
+
 -----------------------------------------------------------------------------
 
 				Theory of Operation
@@ -88,7 +97,7 @@
 #include <asm/io.h>
 
 
-#define RTL8139_VERSION "0.9.4.1"
+#define RTL8139_VERSION "0.9.5"
 #define RTL8139_MODULE_NAME "8139too"
 #define RTL8139_DRIVER_NAME   RTL8139_MODULE_NAME " Fast Ethernet driver " RTL8139_VERSION
 #define PFX RTL8139_MODULE_NAME ": "
@@ -201,7 +210,7 @@
 /*	{0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/
 	{0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 },
 	{0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
-	{0,},
+	{0,}
 };
 MODULE_DEVICE_TABLE (pci, rtl8139_pci_tbl);
 
@@ -304,6 +313,17 @@
 	AcceptAllPhys = 0x01,
 };
 
+/* Bits in TxConfig. */
+enum tx_config_bits {
+	TxIFG1 = (1 << 25),	/* Interframe Gap Time */
+	TxIFG0 = (1 << 24),	/* Enabling these bits violates IEEE 802.3 */
+	TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
+	TxCRC = (1 << 16),	/* DISABLE appending CRC to end of Tx packets */
+	TxClearAbt = (1 << 0),	/* Clear abort (WO) */
+
+	TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
+};
+
 /* Bits in Config1 */
 enum Config1Bits {
 	Cfg1_PM_Enable = 0x01,
@@ -369,28 +389,53 @@
 	dma_addr_t mapping;
 };
 
+
 typedef enum {
 	CH_8139 = 0,
 	CH_8139A,
+	CH_8139A_G,
 	CH_8139B,
+	CH_8130,
+	CH_8139C,
 } chip_t;
 
+
 /* directly indexed by chip_t, above */
 const static struct {
 	const char *name;
+	u32 version; /* from RTL8139C docs */
 	u32 RxConfigMask; /* should clear the bits supported by this chip */
 } rtl_chip_info[] = {
 	{ "RTL-8139",
+	  0x60000000,
 	  0xf0fe0040, /* XXX copied from RTL8139A, verify */
 	},
 	
 	{ "RTL-8139A",
+	  0x70000000,
 	  0xf0fe0040,
 	},
 	
-	{ "RTL-8139B(L)",
+	{ "RTL-8139A rev. G",
+	  0x70800000,
+	  0xf0fe0040,
+	},
+	
+	{ "RTL-8139B",
+	  0x78000000,
 	  0xf0fc0040
 	},
+
+	{ "RTL-8130",
+	  0x7C000000,
+	  0xf0fe0040, /* XXX copied from RTL8139A, verify */
+	},
+
+	{ "RTL-8139C",
+	  0x74000000,
+	  0xf0fc0040, /* XXX copied from RTL8139B, verify */
+	},
+
 };
 
 
@@ -574,12 +619,8 @@
 	
 	/* enable device (incl. PCI PM wakeup), and bus-mastering */
 	rc = pci_enable_device (pdev);
-	if (rc) {
-		printk (KERN_ERR PFX "cannot enable PCI device (bus %d, "
-			"devfn %d), aborting\n",
-			pdev->bus->number, pdev->devfn);
+	if (rc)
 		goto err_out_free_mmio;
-	}
 
 	pci_set_master (pdev);
 
@@ -631,15 +672,20 @@
 	}
 	
 	/* identify chip attached to board */
-	tmp = RTL_R32 (TxConfig);
-	if (((tmp >> 28) & 7) == 7) {
-		if (pio_len == RTL8139B_IO_SIZE)
-			tp->chipset = CH_8139B;
-		else
-			tp->chipset = CH_8139A;
-	} else {
-		tp->chipset = CH_8139;
-	}
+	tmp = RTL_R32 (TxConfig) & TxVersionMask;
+	for (i = arraysize (rtl_chip_info) - 1; i >= 0; i--)
+		if (tmp == rtl_chip_info[i].version) {
+			tp->chipset = i;
+			goto match;
+		}
+
+	/* if unknown chip, assume array element #0, original RTL-8139 in this case */
+	printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n",
+		pdev->slot_name);
+	printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%x\n", pdev->slot_name, RTL_R32 (TxConfig));
+	tp->chipset = 0;
+
+match:
 	DPRINTK ("chipset id (%d/%d/%d) == %d, '%s'\n",
 		CH_8139,
 		CH_8139A,
@@ -738,7 +784,7 @@
 
 	tp->phys[0] = 32;
 
-	printk (KERN_INFO "%s: '%s' board found at 0x%lx, IRQ %d\n",
+	printk (KERN_INFO "%s: %s board found at 0x%lx, IRQ %d\n",
 		dev->name, board_info[ent->driver_data].name,
 		dev->base_addr, dev->irq);
 
@@ -1122,6 +1168,7 @@
 	/* Check this value: the documentation for IFG contradicts ifself. */
 	RTL_W32 (TxConfig, (TX_DMA_BURST << 8));
 
+#if 0
 	/* if link status not ok... */
 	if ((RTL_R16 (BasicModeStatus) & (1<<2)) == 0) {
 		printk (KERN_INFO "%s: no link, starting NWay\n", dev->name);
@@ -1144,10 +1191,13 @@
 		/* XXX writing Config1 here is flat out wrong */
 		/* RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20); */
 	}
+#endif
 
-	tmp = RTL_R8 (Config1) & Config1Clear;
-	tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
-	RTL_W8_F (Config1, tmp);
+	if (tp->chipset > CH_8139) {
+		tmp = RTL_R8 (Config1) & Config1Clear;
+		tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
+		RTL_W8_F (Config1, tmp);
+	}
 
 	if (tp->chipset == CH_8139B) {
 		tmp = RTL_R8 (Config4) & ~(1<<2);
@@ -1596,13 +1646,19 @@
 			/* A.C.: Reset the multicast list. */
 			rtl8139_set_rx_mode (dev);
 
+			/* XXX potentially temporary hack to
+			 * restart hung receiver */
 			while (--tmp_work > 0) {
-				tmp8 = RTL_R8 (ChipCmd) & ChipCmdClear;
+				tmp8 = RTL_R8 (ChipCmd);
 				if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
 					break;
-				RTL_W8_F (ChipCmd, tmp8 | CmdRxEnb | CmdTxEnb);
+				RTL_W8_F (ChipCmd, (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb);
 			}
 
+			/* G.S.: Re-enable receiver */
+			/* XXX temporary hack to work around receiver hang */
+			rtl8139_set_rx_mode (dev);
+
 			if (tmp_work <= 0)			
 				printk (KERN_WARNING PFX "tx/rx enable wait too long\n");
 		} else {
@@ -1973,7 +2029,6 @@
 	u32 mc_filter[2];	/* Multicast hash filter */
 	int i, rx_mode;
 	u32 tmp;
-	unsigned long flags=0;
 
 	DPRINTK ("ENTER\n");
 
@@ -2006,7 +2061,7 @@
 	
 	/* if called from irq handler, lock already acquired */
 	if (!in_irq ())
-		spin_lock_irqsave (&tp->lock, flags);
+		spin_lock_irq (&tp->lock);
 
 	/* We can safely update without stopping the chip. */
 	tmp = rtl8139_rx_config | rx_mode |
@@ -2016,7 +2071,7 @@
 	RTL_W32_F (MAR0 + 4, mc_filter[1]);
 
 	if (!in_irq ())
-		spin_unlock_irqrestore (&tp->lock, flags);
+		spin_unlock_irq (&tp->lock);
 
 	DPRINTK ("EXIT\n");
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.3.99-pre8/linux/drivers/net/Config.in	Fri May 12 14:18:55 2000
+++ linux/drivers/net/Config.in	Sat May 20 12:05:30 2000
@@ -51,6 +51,9 @@
    if [ "$CONFIG_SGI_IP27" = "y" ]; then
       bool ' SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
    fi
+   if [ "$CONFIG_SUPERH" = "y" -a "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
+      tristate '  National DP83902AV  support' CONFIG_STNIC
+   fi
    bool '  3COM cards' CONFIG_NET_VENDOR_3COM
    if [ "$CONFIG_NET_VENDOR_3COM" = "y" ]; then
       tristate '    3c501 "EtherLink" support' CONFIG_EL1
@@ -218,7 +221,7 @@
    dep_tristate '  PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
    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
+   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
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.3.99-pre8/linux/drivers/net/Makefile	Fri May 12 14:18:55 2000
+++ linux/drivers/net/Makefile	Sat May 20 12:05:30 2000
@@ -146,6 +146,8 @@
 obj-$(CONFIG_YELLOWFIN) += yellowfin.o
 obj-$(CONFIG_ACENIC) += acenic.o
 
+obj-$(CONFIG_STNIC) += stnic.o 8390.o
+
 ifeq ($(CONFIG_SK98LIN),y)
 SUB_DIRS += sk98lin
 obj-y += sk98lin/sk98lin.o
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.3.99-pre8/linux/drivers/net/Space.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/net/Space.c	Mon May 15 12:00:34 2000
@@ -95,10 +95,6 @@
 extern int pamsnet_probe(struct net_device *);
 extern int cs89x0_probe(struct net_device *dev);
 extern int ethertap_probe(struct net_device *dev);
-extern int ether1_probe (struct net_device *dev);
-extern int ether3_probe (struct net_device *dev);
-extern int etherh_probe (struct net_device *dev);
-extern int am79c961_probe(struct net_device *dev);
 extern int hplance_probe(struct net_device *dev);
 extern int bagetlance_probe(struct net_device *);
 extern int dec_lance_probe(struct net_device *);
@@ -401,22 +397,6 @@
 	{NULL, 0},
 };
 
-struct devprobe arm_probes[] __initdata = {
-#ifdef CONFIG_ARM_ETHERH
-	{etherh_probe , 0},
-#endif
-#ifdef CONFIG_ARM_ETHER3
-	{ether3_probe , 0},
-#endif
-#ifdef CONFIG_ARM_ETHER1
-	{ether1_probe , 0},
-#endif
-#ifdef CONFIG_ARM_AM79C961A
-	{am79c961_probe, 0},
-#endif
-	{NULL, 0},
-};
-
 /*
  * Unified ethernet device probe, segmented per architecture and
  * per bus interface. This drives the legacy devices only for now.
@@ -437,8 +417,6 @@
 	 * The arch specific probes are 1st so that any on-board ethernet
 	 * will be probed before other ISA/EISA/MCA/PCI bus cards.
 	 */
-	if (probe_list(dev, arm_probes) == 0)
-		return 0;
 	if (probe_list(dev, m68k_probes) == 0)
 		return 0;
 	if (probe_list(dev, mips_probes) == 0)
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.3.99-pre8/linux/drivers/net/acenic.c	Fri May 12 14:18:55 2000
+++ linux/drivers/net/acenic.c	Mon May 15 12:10:26 2000
@@ -2966,6 +2966,6 @@
 
 /*
  * Local variables:
- * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o acenic.o acenic.c"
+ * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h   -c -o acenic.o acenic.c"
  * End:
  */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c
--- v2.3.99-pre8/linux/drivers/net/am79c961a.c	Wed Apr 26 16:34:07 2000
+++ linux/drivers/net/am79c961a.c	Mon May 15 12:00:34 2000
@@ -3,7 +3,10 @@
  *
  * Derived from various things including skeleton.c
  *
- * R.M.King 1995.
+ * Russell King 1995-2000.
+ *
+ * This is a special driver for the am79c961A Lance chip used in the
+ * Intel (formally Digital Equipment Corp) EBSA110 platform.
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -21,9 +24,11 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/system.h>
 #include <asm/bitops.h>
+#include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/ecard.h>
@@ -33,26 +38,13 @@
 
 #include "am79c961a.h"
 
-static int am79c961_probe1 (struct net_device *dev);
-static int am79c961_open (struct net_device *dev);
-static int am79c961_sendpacket (struct sk_buff *skb, struct net_device *dev);
 static void am79c961_interrupt (int irq, void *dev_id, struct pt_regs *regs);
 static void am79c961_rx (struct net_device *dev, struct dev_priv *priv);
 static void am79c961_tx (struct net_device *dev, struct dev_priv *priv);
-static int am79c961_close (struct net_device *dev);
-static struct enet_statistics *am79c961_getstats (struct net_device *dev);
-static void am79c961_setmulticastlist (struct net_device *dev);
-static void am79c961_timeout(struct net_device *dev);
 
 static unsigned int net_debug = NET_DEBUG;
 
-static void
-am79c961_setmulticastlist (struct net_device *dev);
-
-static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.01\n";
-
-#define FUNC_PROLOGUE \
-	struct dev_priv *priv = (struct dev_priv *)dev->priv
+static char *version = "am79c961 ethernet driver (c) 1995 R.M.King v0.02\n";
 
 /* --------------------------------------------------------------------------- */
 
@@ -270,109 +262,6 @@
 	write_rreg (dev->base_addr, CSR0, CSR0_IENA|CSR0_STRT);
 }
 
-static int
-am79c961_init(struct net_device *dev)
-{
-	unsigned long flags;
-
-	am79c961_ramtest(dev, 0x66);
-	am79c961_ramtest(dev, 0x99);
-
-	save_flags_cli (flags);
-
-	write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */
-	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
-	write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
-
-	restore_flags (flags);
-
-	return 0;
-}
-
-/*
- * This is the real probe routine.
- */
-static int
-am79c961_probe1(struct net_device *dev)
-{
-	static unsigned version_printed = 0;
-	struct dev_priv *priv;
-	int i;
-
-	if (!dev->priv) {
-		dev->priv = kmalloc (sizeof (struct dev_priv), GFP_KERNEL);
-		if (!dev->priv)
-			return -ENOMEM;
-	}
-
-	priv = (struct dev_priv *) dev->priv;
-	memset (priv, 0, sizeof(struct dev_priv));
-
-	/*
-	 * The PNP initialisation should have been done by the ether bootp loader.
-	 */
-	inb((dev->base_addr + NET_RESET) >> 1);	/* reset the device */
-
-	udelay (5);
-
-	if (inb (dev->base_addr >> 1) != 0x08 ||
-	    inb ((dev->base_addr >> 1) + 1) != 00 ||
-	    inb ((dev->base_addr >> 1) + 2) != 0x2b) {
-		kfree (dev->priv);
-		dev->priv = NULL;
-		return -ENODEV;
-	}
-
-	/*
-	 * Ok, we've found a valid hw ID
-	 */
-
-	if (net_debug  &&  version_printed++ == 0)
-		printk (KERN_INFO "%s", version);
-
-	printk(KERN_INFO "%s: am79c961 found [%04lx, %d] ", dev->name, dev->base_addr, dev->irq);
-	request_region (dev->base_addr, 0x18, "am79c961");
-
-	/* Retrive and print the ethernet address. */
-	for (i = 0; i < 6; i++) {
-		dev->dev_addr[i] = inb ((dev->base_addr >> 1) + i) & 0xff;
-		printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
-	}
-
-	if (am79c961_init(dev)) {
-		kfree (dev->priv);
-		dev->priv = NULL;
-		return -ENODEV;
-	}
-
-	dev->open = am79c961_open;
-	dev->stop = am79c961_close;
-	dev->hard_start_xmit = am79c961_sendpacket;
-	dev->get_stats = am79c961_getstats;
-	dev->set_multicast_list = am79c961_setmulticastlist;
-	dev->tx_timeout = am79c961_timeout;
-
-	/* Fill in the fields of the device structure with ethernet values. */
-	ether_setup(dev);
-
-	return 0;
-}
-
-int
-am79c961_probe(struct net_device *dev)
-{
-	static int initialised = 0;
-
-	if (initialised)
-		return -ENODEV;
-	initialised = 1;
-
-	dev->base_addr = 0x220;
-	dev->irq = 3;
-
-	return am79c961_probe1(dev);
-}
-
 /*
  * Open/initialize the board.  This is called (in the current kernel)
  * sometime after booting when the 'ifconfig' program is run.
@@ -408,9 +297,17 @@
 static int
 am79c961_close(struct net_device *dev)
 {
+	unsigned long flags;
+
 	netif_stop_queue(dev);
 
-	am79c961_init(dev);
+	save_flags_cli (flags);
+
+	write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */
+	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
+	write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
+
+	restore_flags (flags);
 
 	free_irq (dev->irq, dev);
 
@@ -709,3 +606,103 @@
 
 	netif_wake_queue(dev);
 }
+
+static int
+am79c961_hw_init(struct net_device *dev)
+{
+	unsigned long flags;
+
+	am79c961_ramtest(dev, 0x66);
+	am79c961_ramtest(dev, 0x99);
+
+	save_flags_cli (flags);
+
+	write_ireg (dev->base_addr, 2, 0x4000); /* autoselect media */
+	write_rreg (dev->base_addr, CSR0, CSR0_STOP);
+	write_rreg (dev->base_addr, CSR3, CSR3_MASKALL);
+
+	restore_flags (flags);
+
+	return 0;
+}
+
+static void __init am79c961_banner(void)
+{
+	static unsigned version_printed = 0;
+
+	if (net_debug && version_printed++ == 0)
+		printk(KERN_INFO "%s", version);
+}
+
+static int __init am79c961_init(void)
+{
+	struct net_device *dev;
+	struct dev_priv *priv;
+	int i, ret;
+
+	dev = init_etherdev(NULL, sizeof(struct dev_priv));
+	ret = -ENOMEM;
+	if (!dev)
+		goto out;
+
+	priv = (struct dev_priv *) dev->priv;
+
+	/*
+	 * Fixed address and IRQ lines here.
+	 * The PNP initialisation should have been
+	 * done by the ether bootp loader.
+	 */
+	dev->base_addr = 0x220;
+	dev->irq = IRQ_EBSA110_ETHERNET;
+
+	/*
+	 * Reset the device.
+	 */
+	inb((dev->base_addr + NET_RESET) >> 1);
+	udelay(5);
+
+	/*
+	 * Check the manufacturer part of the
+	 * ether address.
+	 */
+    	ret = -ENODEV;
+	if (inb(dev->base_addr >> 1) != 0x08 ||
+	    inb((dev->base_addr >> 1) + 1) != 00 ||
+	    inb((dev->base_addr >> 1) + 2) != 0x2b)
+	    	goto nodev;
+
+	if (!request_region(dev->base_addr, 0x18, dev->name))
+		goto nodev;
+
+	am79c961_banner();
+	printk(KERN_INFO "%s: am79c961 found at %08lx, IRQ%d, ether address ",
+		dev->name, dev->base_addr, dev->irq);
+
+	/* Retrive and print the ethernet address. */
+	for (i = 0; i < 6; i++) {
+		dev->dev_addr[i] = inb((dev->base_addr >> 1) + i) & 0xff;
+		printk (i == 5 ? "%02x\n" : "%02x:", dev->dev_addr[i]);
+	}
+
+	if (am79c961_hw_init(dev))
+		goto release;
+
+	dev->open		= am79c961_open;
+	dev->stop		= am79c961_close;
+	dev->hard_start_xmit	= am79c961_sendpacket;
+	dev->get_stats		= am79c961_getstats;
+	dev->set_multicast_list	= am79c961_setmulticastlist;
+	dev->tx_timeout		= am79c961_timeout;
+
+	return 0;
+
+release:
+	release_region(dev->base_addr, 0x18);
+nodev:
+	unregister_netdev(dev);
+	kfree(dev);
+out:
+	return ret;
+}
+
+module_init(am79c961_init);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/arc-rimi.c linux/drivers/net/arcnet/arc-rimi.c
--- v2.3.99-pre8/linux/drivers/net/arcnet/arc-rimi.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/arcnet/arc-rimi.c	Sat May 13 07:50:25 2000
@@ -345,9 +345,8 @@
 	s = get_options(s, 8, ints);
 	if (!ints[0])
 		return 1;
-	dev = alloc_bootmem(sizeof(struct net_device) + 10);
-	memset(dev, 0, sizeof(struct net_device) + 10);
-	dev->name = (char *) (dev + 1);
+	dev = alloc_bootmem(sizeof(struct net_device));
+	memset(dev, 0, sizeof(struct net_device));
 	dev->init = arcrimi_probe;
 
 	switch (ints[0]) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com20020-isa.c linux/drivers/net/arcnet/com20020-isa.c
--- v2.3.99-pre8/linux/drivers/net/arcnet/com20020-isa.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/arcnet/com20020-isa.c	Sat May 13 07:50:25 2000
@@ -194,10 +194,9 @@
 	s = get_options(s, 8, ints);
 	if (!ints[0])
 		return 1;
-	dev = alloc_bootmem(sizeof(struct net_device) + sizeof(struct arcnet_local) + 10);
-	memset(dev, 0, sizeof(struct net_device) + sizeof(struct arcnet_local) + 10);
+	dev = alloc_bootmem(sizeof(struct net_device) + sizeof(struct arcnet_local));
+	memset(dev, 0, sizeof(struct net_device) + sizeof(struct arcnet_local));
 	lp = dev->priv = (struct arcnet_local *) (dev + 1);
-	dev->name = (char *) (lp + 1);
 	dev->init = com20020isa_probe;
 
 	switch (ints[0]) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com20020-pci.c linux/drivers/net/arcnet/com20020-pci.c
--- v2.3.99-pre8/linux/drivers/net/arcnet/com20020-pci.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/arcnet/com20020-pci.c	Sat May 13 08:19:21 2000
@@ -139,7 +139,9 @@
 	{0,}
 };
 
-static struct pci_driver com20020pci_driver __devinitdata = {
+MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
+
+static struct pci_driver com20020pci_driver = {
 	name:		"com20020",
 	id_table:	com20020pci_id_table,
 	probe:		com20020pci_probe,
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com90io.c linux/drivers/net/arcnet/com90io.c
--- v2.3.99-pre8/linux/drivers/net/arcnet/com90io.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/arcnet/com90io.c	Sat May 13 07:50:25 2000
@@ -428,9 +428,8 @@
 	s = get_options(s, 4, ints);
 	if (!ints[0])
 		return 0;
-	dev = alloc_bootmem(sizeof(struct net_device) + 10);
-	memset(dev, 0, sizeof(struct net_device) + 10);
-	dev->name = (char *) (dev + 1);
+	dev = alloc_bootmem(sizeof(struct net_device));
+	memset(dev, 0, sizeof(struct net_device));
 	dev->init = com90io_probe;
 
 	switch (ints[0]) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/arcnet/com90xx.c linux/drivers/net/arcnet/com90xx.c
--- v2.3.99-pre8/linux/drivers/net/arcnet/com90xx.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/arcnet/com90xx.c	Sat May 13 07:50:25 2000
@@ -677,9 +677,8 @@
 		printk("com90xx: Disabled.\n");
 		return 1;
 	}
-	dev = alloc_bootmem(sizeof(struct net_device) + 10);
-	memset(dev, 0, sizeof(struct net_device) + 10);
-	dev->name = (char *) (dev + 1);
+	dev = alloc_bootmem(sizeof(struct net_device));
+	memset(dev, 0, sizeof(struct net_device));
 	dev->init = com90xx_probe;
 
 	switch (ints[0]) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c
--- v2.3.99-pre8/linux/drivers/net/bagetlance.c	Sat Feb 26 22:31:46 2000
+++ linux/drivers/net/bagetlance.c	Sat May 13 08:29:40 2000
@@ -1,4 +1,4 @@
-/* $Id: bagetlance.c,v 1.2 1999/10/09 00:01:21 ralf Exp $
+/* $Id$
  * vmelance.c: Ethernet driver for VME Lance cards on Baget/MIPS
  *      This code stealed and adopted from linux/drivers/net/atarilance.c
  *      See that for author info
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/declance.c linux/drivers/net/declance.c
--- v2.3.99-pre8/linux/drivers/net/declance.c	Sat Feb 26 22:31:46 2000
+++ linux/drivers/net/declance.c	Sat May 13 08:29:40 2000
@@ -256,6 +256,8 @@
 	volatile struct lance_init_block *init_block;
 	volatile unsigned long *dma_ptr_reg;
 
+	spinlock_t	lock;
+
 	int rx_new, tx_new;
 	int rx_old, tx_old;
 
@@ -265,6 +267,7 @@
 
 	struct net_device *dev;	/* Backpointer        */
 	struct lance_private *next_module;
+	struct timer_list       multicast_timer;
 
 	/* Pointers to the ring buffers as seen from the CPU */
 	char *rx_buf_ptr_cpu[RX_RING_SIZE];
@@ -443,7 +446,6 @@
 }
 
 /* Setup the Lance Rx and Tx rings */
-/* Sets dev->tbusy */
 static void lance_init_ring(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
@@ -454,12 +456,10 @@
 	ib = (struct lance_init_block *) (dev->mem_start);
 
 	/* Lock out other processes while setting up hardware */
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 	lp->rx_new = lp->tx_new = 0;
 	lp->rx_old = lp->tx_old = 0;
 
-	ib->mode = 0;
-
 	/* Copy the ethernet address to the lance init block.
 	 * XXX bit 0 of the physical address registers has to be zero
 	 */
@@ -485,11 +485,6 @@
 	if (ZERO)
 		printk("TX ptr: %8.8x(%8.8x)\n", leptr, libdesc_offset(btx_ring, 0));
 
-	/* Clear the multicast filter */
-	ib->filter[0] = 0;
-	ib->filter[2] = 0;
-	ib->filter[4] = 0;
-	ib->filter[6] = 0;
 	if (ZERO)
 		printk("TX rings:\n");
 
@@ -630,7 +625,7 @@
 	return 0;
 }
 
-static int lance_tx(struct net_device *dev)
+static void lance_tx(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_init_block *ib;
@@ -641,6 +636,8 @@
 	ib = (struct lance_init_block *) (dev->mem_start);
 	j = lp->tx_old;
 
+	spin_lock(&lp->lock);
+
 	for (i = j; i != lp->tx_new; i = j) {
 		td = &ib->btx_ring[i];
 		/* If we hit a packet not owned by us, stop */
@@ -665,7 +662,7 @@
 				lance_init_ring(dev);
 				load_csrs(lp);
 				init_restart_lance(lp);
-				return 0;
+				goto out;
 			}
 			/* Buffer errors and underflows turn off the
 			 * transmitter, restart the adapter.
@@ -681,7 +678,7 @@
 				lance_init_ring(dev);
 				load_csrs(lp);
 				init_restart_lance(lp);
-				return 0;
+				goto out;
 			}
 		} else if ((td->tmd1_bits & LE_T1_POK) == LE_T1_POK) {
 			/*
@@ -702,7 +699,12 @@
 		j = (j + 1) & TX_RING_MOD_MASK;
 	}
 	lp->tx_old = j;
-	return 0;
+out:
+	if (netif_queue_stopped(dev) &&
+	    TX_BUFFS_AVAIL > 0)
+		netif_wake_queue(dev);
+
+	spin_unlock(&lp->lock);
 }
 
 static void lance_interrupt(const int irq, void *dev_id, struct pt_regs *regs)
@@ -712,11 +714,6 @@
 	volatile struct lance_regs *ll = lp->ll;
 	int csr0;
 
-	if (dev->interrupt)
-		printk("%s: again\n", dev->name);
-
-	dev->interrupt = 1;
-
 	writereg(&ll->rap, LE_CSR0);
 	csr0 = ll->rdp;
 
@@ -734,10 +731,6 @@
 	if (csr0 & LE_C0_TINT)
 		lance_tx(dev);
 
-	if ((TX_BUFFS_AVAIL >= 0) && dev->tbusy) {
-		dev->tbusy = 0;
-		mark_bh(NET_BH);
-	}
 	if (csr0 & LE_C0_BABL)
 		lp->stats.tx_errors++;
 
@@ -763,17 +756,17 @@
 		lance_init_ring(dev);
 		load_csrs(lp);
 		init_restart_lance(lp);
-		dev->tbusy = 0;
+		netif_wake_queue(dev);
 	}
 	writereg(&ll->rdp, LE_C0_INEA);
 	writereg(&ll->rdp, LE_C0_INEA);
-	dev->interrupt = 0;
 }
 
 struct net_device *last_dev = 0;
 
 static int lance_open(struct net_device *dev)
 {
+	volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
 	int status = 0;
@@ -789,12 +782,20 @@
 	writereg(&ll->rap, LE_CSR0);
 	writereg(&ll->rdp, LE_C0_STOP);
 
+	/* Set mode and clear multicast filter only at device open,
+	 * so that lance_init_ring() called at any error will not
+	 * forget multicast filters.
+	 *
+	 * BTW it is common bug in all lance drivers! --ANK
+	 */
+	ib->mode = 0;
+	ib->filter [0] = 0;
+	ib->filter [2] = 0;
+
 	lance_init_ring(dev);
 	load_csrs(lp);
 
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
+	netif_start_queue(dev);
 
 	status = init_restart_lance(lp);
 
@@ -811,8 +812,8 @@
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
 
-	dev->start = 0;
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
+	del_timer_sync(&lp->multicast_timer);
 
 	/* Stop the card */
 	writereg(&ll->rap, LE_CSR0);
@@ -838,51 +839,30 @@
 	lance_init_ring(dev);
 	load_csrs(lp);
 	dev->trans_start = jiffies;
-	dev->interrupt = 0;
-	dev->start = 1;
-	dev->tbusy = 0;
 	status = init_restart_lance(lp);
-#ifdef DEBUG_DRIVER
-	printk("Lance restart=%d\n", status);
-#endif
 	return status;
 }
 
-static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static void lance_tx_timeout(struct net_device *dev)
 {
 	struct lance_private *lp = (struct lance_private *) dev->priv;
 	volatile struct lance_regs *ll = lp->ll;
-	volatile struct lance_init_block *ib;
-	unsigned long flags;
-	int entry, skblen, len;
-	int status = 0;
-	static int outs;
-	ib = (struct lance_init_block *) (dev->mem_start);
-
-	/* Transmitter timeout, serious problems */
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
 
-		if (tickssofar < 100) {
-			status = -1;
-		} else {
-			printk("%s: transmit timed out, status %04x, reset\n",
+	printk(KERN_ERR "%s: transmit timed out, status %04x, reset\n",
 			       dev->name, ll->rdp);
 			lance_reset(dev);
-		}
-		return status;
-	}
-	/* Block a timer-based transmit from overlapping. */
-	if (test_and_set_bit(0, (void *) &dev->tbusy) != 0) {
-		printk("Transmitter access conflict.\n");
-		return -1;
-	}
+	netif_wake_queue(dev);
+}
+
+static int lance_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct lance_private *lp = (struct lance_private *) dev->priv;
+	volatile struct lance_regs *ll = lp->ll;
+	volatile struct lance_init_block *ib = (struct lance_init_block *) (dev->mem_start);
+	int entry, skblen, len;
+
 	skblen = skb->len;
-	save_and_cli(flags);
-	if (!TX_BUFFS_AVAIL) {
-		restore_flags(flags);
-		return -1;
-	}
+
 	len = (skblen <= ETH_ZLEN) ? ETH_ZLEN : skblen;
 
 	lp->stats.tx_bytes += len;
@@ -904,17 +884,18 @@
 	ib->btx_ring[entry].tmd1_bits = (LE_T1_POK | LE_T1_OWN);
 	lp->tx_new = (lp->tx_new + 1) & TX_RING_MOD_MASK;
 
-	outs++;
+	if (TX_BUFFS_AVAIL <= 0)
+		netif_stop_queue(dev);
+
 	/* Kick the lance: transmit now */
 	writereg(&ll->rdp, LE_C0_INEA | LE_C0_TDMD);
+
+	spin_unlock_irq(&lp->lock);
+
 	dev->trans_start = jiffies;
 	dev_kfree_skb(skb);
 
-	if (TX_BUFFS_AVAIL)
-		dev->tbusy = 0;
-
-	restore_flags(flags);
-	return status;
+ 	return 0;
 }
 
 static struct net_device_stats *lance_get_stats(struct net_device *dev)
@@ -983,11 +964,16 @@
 
 	ib = (struct lance_init_block *) (dev->mem_start);
 
-	while (dev->tbusy)
-		schedule();
-	set_bit(0, (void *) &dev->tbusy);
-	while (lp->tx_old != lp->tx_new)
-		schedule();
+	if (!netif_running(dev))
+		return;
+
+	if (lp->tx_old != lp->tx_new) {
+		mod_timer(&lp->multicast_timer, jiffies + 4);
+		netif_wake_queue(dev);
+		return;
+	}
+
+	netif_stop_queue(dev);
 
 	writereg(&ll->rap, LE_CSR0);
 	writereg(&ll->rdp, LE_C0_STOP);
@@ -1002,7 +988,14 @@
 	}
 	load_csrs(lp);
 	init_restart_lance(lp);
-	dev->tbusy = 0;
+	netif_wake_queue(dev);
+}
+
+static void lance_set_multicast_retry(unsigned long _opaque)
+{
+	struct net_device *dev = (struct net_device *) _opaque;
+
+	lance_set_multicast(dev);
 }
 
 static int __init dec_lance_init(struct net_device *dev, const int type)
@@ -1167,14 +1160,14 @@
 
 	printk(" irq = %d\n", dev->irq);
 
-	/* Fill the dev fields */
-
-	dev->open = lance_open;
-	dev->stop = lance_close;
-	dev->hard_start_xmit = lance_start_xmit;
-	dev->get_stats = lance_get_stats;
-	dev->set_multicast_list = lance_set_multicast;
-	dev->dma = 0;
+	lp->dev = dev;
+	dev->open = &lance_open;
+	dev->stop = &lance_close;
+	dev->hard_start_xmit = &lance_start_xmit;
+	dev->tx_timeout = &lance_tx_timeout;
+	dev->watchdog_timeo = 5*HZ;
+	dev->get_stats = &lance_get_stats;
+	dev->set_multicast_list = &lance_set_multicast;
 
 	/* lp->ll is the location of the registers for lance card */
 	lp->ll = ll;
@@ -1185,25 +1178,39 @@
 	 * specification.
 	 */
 	lp->busmaster_regval = 0;
-	lp->dev = dev;
+
+	dev->dma = 0;
 
 	ether_setup(dev);
-/*
-   #ifdef MODULE
+
+	/* We cannot sleep if the chip is busy during a
+	 * multicast list update event, because such events
+	 * can occur from interrupts (ex. IPv6).  So we
+	 * use a timer to try again later when necessary. -DaveM
+	 */
+	init_timer(&lp->multicast_timer);
+	lp->multicast_timer.data = (unsigned long) dev;
+	lp->multicast_timer.function = &lance_set_multicast_retry;
+
+#ifdef MODULE
    dev->ifindex = dev_new_index();
    lp->next_module = root_lance_dev;
    root_lance_dev = lp;
-   #endif
- */
+#endif
 	return 0;
 }
 
 
 /* Find all the lance cards on the system and initialize them */
-int __init dec_lance_probe(struct net_device *dev)
+static int __init dec_lance_probe(void)
 {
+	struct net_device *dev = NULL;
 	static int called = 0;
 
+#ifdef MODULE
+	root_lance_dev = NULL;
+#endif
+
 #ifdef CONFIG_TC
 	int slot = -1;
 
@@ -1238,19 +1245,9 @@
 	return dec_lance_init(dev, type);
 }
 
-/*
-   #ifdef MODULE
-
-   int
-   init_module(void)
-   {
-   root_lance_dev = NULL;
-   return dec_lance_probe(NULL);
-   }
-
-   void
-   cleanup_module(void)
-   {
+static void __exit dec_lance_cleanup(void)
+{
+#ifdef MODULE
    struct lance_private *lp;
 
    while (root_lance_dev) {
@@ -1260,6 +1257,8 @@
    kfree(root_lance_dev->dev);
    root_lance_dev = lp;
    }
-   }
+#endif /* MODULE */
+}
 
-   #endif -* MODULE */
+module_init(dec_lance_probe);
+module_exit(dec_lance_cleanup);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.3.99-pre8/linux/drivers/net/eepro100.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/eepro100.c	Sat May 13 08:19:21 2000
@@ -2206,7 +2206,7 @@
 		PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER,
 		PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0,},
+	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl);
 	
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.3.99-pre8/linux/drivers/net/epic100.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/epic100.c	Sat May 13 08:19:21 2000
@@ -189,7 +189,7 @@
 	{ 0x10B8, 0x0005, 0x1092, 0x0AB4, 0, 0, SMSC_83C170_0 },
 	{ 0x10B8, 0x0005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C170 },
 	{ 0x10B8, 0x0006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMSC_83C175 },
-	{ 0,},
+	{ 0,}
 };
 MODULE_DEVICE_TABLE (pci, epic_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.3.99-pre8/linux/drivers/net/hp100.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/hp100.c	Sun May 21 20:18:08 2000
@@ -3123,11 +3123,11 @@
 MODULE_PARM(hp100_port, "1-5i");
 #endif
 
-#ifndef LINUX_2_1
-static char devname[5][IFNAMSIZ] = { "", "", "", "", "" };
-static char *hp100_name[5] = { devname[0], devname[1],
-                               devname[2], devname[3],
-                               devname[4] };
+/* Allocate 5 string of length IFNAMSIZ, one string for each device */
+char hp100_name[5][IFNAMSIZ] = { "", "", "", "", "" };
+#ifdef LINUX_2_1
+/* Allow insmod to write those 5 strings individually */
+MODULE_PARM(hp100_name, "1-5c" __MODULE_STRING(IFNAMSIZ));
 #endif
 
 /* List of devices */
@@ -3159,9 +3159,11 @@
       /* Create device and set basics args */
       hp100_devlist[i] = kmalloc(sizeof(struct net_device), GFP_KERNEL);
       memset(hp100_devlist[i], 0x00, sizeof(struct net_device));
-#ifndef LINUX_2_1
+#if LINUX_VERSION_CODE >= 0x020362	/* 2.3.99-pre7 */
+      memcpy(hp100_devlist[i]->name, hp100_name[i], IFNAMSIZ);	/* Copy name */
+#else
       hp100_devlist[i]->name = hp100_name[i];
-#endif
+#endif /* LINUX_VERSION_CODE >= 0x020362 */
       hp100_devlist[i]->base_addr = hp100_port[i];
       hp100_devlist[i]->init = &hp100_probe;
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
--- v2.3.99-pre8/linux/drivers/net/ioc3-eth.c	Thu Mar  2 14:36:22 2000
+++ linux/drivers/net/ioc3-eth.c	Sat May 13 08:29:40 2000
@@ -97,6 +97,7 @@
 	int rx_pi;			/* RX producer index */
 	int tx_ci;			/* TX consumer index */
 	int tx_pi;			/* TX producer index */
+	spinlock_t ioc3_lock;
 };
 
 /* We use this to acquire receive skb's that we can DMA directly into. */
@@ -390,6 +391,7 @@
 	struct sk_buff *skb;
 	u32 etcir;
 
+	spin_lock(&ip->ioc3_lock);
 	etcir = ioc3->etcir;
 	tx_entry = (etcir >> 7) & 127;
 	o_entry = ip->tx_ci;
@@ -401,7 +403,7 @@
 		skb = ip->tx_skbs[o_entry];
 		ip->stats.tx_packets++;
 		ip->stats.tx_bytes += skb->len;
-		dev_kfree_skb(skb);
+		dev_kfree_skb_irq(skb);
 		ip->tx_skbs[o_entry] = NULL;
 
 		o_entry = (o_entry + 1) & 127;		/* Next */
@@ -410,6 +412,7 @@
 		tx_entry = (etcir >> 7) & 127;
 	}
 	ip->tx_ci = o_entry;
+	spin_unlock(&ip->ioc3_lock);
 }
 
 /*
@@ -602,20 +605,30 @@
 
 static void ioc3_probe1(struct net_device *dev, struct ioc3 *ioc3)
 {
-	struct ioc3_private *p;
+	struct ioc3_private *ip;
 
 	dev = init_etherdev(dev, 0);
-	p = (struct ioc3_private *) kmalloc(sizeof(*p), GFP_KERNEL);
-	memset(p, 0, sizeof(*p));
-	dev->priv = p;
+
+	/*
+	 * This probably needs to be register_netdevice, or call
+	 * init_etherdev so that it calls register_netdevice. Quick
+	 * hack for now.
+	 */
+	netif_device_attach(dev);
+
+	ip = (struct ioc3_private *) kmalloc(sizeof(*ip), GFP_KERNEL);
+	memset(ip, 0, sizeof(*ip));
+	dev->priv = ip;
 	dev->irq = IOC3_ETH_INT;
 
-	p->regs = ioc3;
+	ip->regs = ioc3;
 
-	ioc3_eth_init(dev, p, ioc3);
-	ioc3_ssram_disc(p);
+	ioc3_eth_init(dev, ip, ioc3);
+	ioc3_ssram_disc(ip);
         ioc3_get_eaddr(dev, ioc3);
-	ioc3_init_rings(dev, p, ioc3);
+	ioc3_init_rings(dev, ip, ioc3);
+
+	spin_lock_init(&ip->ioc3_lock);
 
 	/* Misc registers  */
 	ioc3->erbar = 0;
@@ -702,6 +715,7 @@
 		return 1;
 	}
 
+	spin_lock_irq(&ip->ioc3_lock);
 	data = (unsigned long) skb->data;
 	len = skb->len;
 
@@ -718,7 +732,7 @@
 		}
 		desc->cmd    = len | ETXD_INTWHENDONE | ETXD_D0V;
 		desc->bufcnt = len;
-	} if ((data ^ (data + len)) & 0x4000) {
+	} else if ((data ^ (data + len)) & 0x4000) {
 		unsigned long b2, s1, s2;
 
 		b2 = (data | 0x3fffUL) + 1UL;
@@ -747,6 +761,7 @@
 
 	if (TX_BUFFS_AVAIL(ip))
 		netif_wake_queue(dev);
+	spin_unlock_irq(&ip->ioc3_lock);
 
 	return 0;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ncr885e.c linux/drivers/net/ncr885e.c
--- v2.3.99-pre8/linux/drivers/net/ncr885e.c	Tue Mar  7 14:32:26 2000
+++ linux/drivers/net/ncr885e.c	Sat May 20 12:07:56 2000
@@ -424,7 +424,7 @@
 	/* look for any channel status (?) */
 	if ( xfer ) {
 
-		dev_kfree_skb( sp->tx_skbufs[i] );
+		dev_kfree_skb_irq( sp->tx_skbufs[i] );
 
 		if ( txbits & TX_STATUS_TXOK ) {
 			sp->stats.tx_packets++;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.3.99-pre8/linux/drivers/net/ne2k-pci.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/ne2k-pci.c	Sat May 13 08:19:21 2000
@@ -115,7 +115,7 @@
 	{ 0x1050, 0x5a5a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Winbond_W89C940F },
 	{ 0x12c3, 0x0058, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80232 },
 	{ 0x12c3, 0x5598, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Holtek_HT80229 },
-	{ 0, },
+	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, ne2k_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.3.99-pre8/linux/drivers/net/pcnet32.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/pcnet32.c	Sat May 13 08:19:21 2000
@@ -334,8 +334,10 @@
     { 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, 0, 0, 0, 0, 0, 0 },
+    { 0, }
 };
+
+MODULE_DEVICE_TABLE (pci, pcnet32_pci_tbl);
 
 static u16 pcnet32_wio_read_csr (unsigned long addr, int index)
 {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/ppp_synctty.c linux/drivers/net/ppp_synctty.c
--- v2.3.99-pre8/linux/drivers/net/ppp_synctty.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/net/ppp_synctty.c	Sat May 20 11:34:54 2000
@@ -269,12 +269,22 @@
 
 	err = -EFAULT;
 	switch (cmd) {
-	case PPPIOCGUNIT:
+	case PPPIOCGCHAN:
 		err = -ENXIO;
 		if (ap == 0)
 			break;
 		err = -EFAULT;
 		if (put_user(ppp_channel_index(&ap->chan), (int *) arg))
+			break;
+		err = 0;
+		break;
+
+	case PPPIOCGUNIT:
+		err = -ENXIO;
+		if (ap == 0)
+			break;
+		err = -EFAULT;
+		if (put_user(ppp_unit_number(&ap->chan), (int *) arg))
 			break;
 		err = 0;
 		break;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c
--- v2.3.99-pre8/linux/drivers/net/pppoe.c	Fri May 12 14:18:55 2000
+++ linux/drivers/net/pppoe.c	Mon May 22 09:50:55 2000
@@ -33,6 +33,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
+#include <linux/if_ether.h>
 #include <linux/if_pppox.h>
 #include <net/sock.h>
 #include <linux/ppp_channel.h>
@@ -46,10 +47,12 @@
 
 
 static int __attribute__((unused)) pppoe_debug = 7;
-#define PPPOE_HASH_SIZE 16
+#define PPPOE_HASH_BITS 4
+#define PPPOE_HASH_SIZE (1<<PPPOE_HASH_BITS)
 
 int pppoe_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
 int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb);
+int __pppoe_xmit(struct sock *sk, struct sk_buff *skb);
 
 struct proto_ops pppoe_ops;
 
@@ -81,23 +84,18 @@
 
 static int hash_item(unsigned long sid, unsigned char *addr)
 {
-	int i = 0;
-	union {
-		char c[sizeof(unsigned long)];
-		unsigned long i;
-	} hash;
-
-	hash.i = sid;
-
-	for (i = 0; i < ETH_ALEN; ++i)
-		hash.c[0] = hash.c[0] ^ addr[i];
-
-	for (i = 1; i < sizeof(int); ++i)
-		hash.c[0] = hash.c[0] ^ hash.c[i];
+	char hash=0;
+	int i,j;
+	for (i = 0; i < ETH_ALEN ; ++i){
+		for (j = 0; j < 8/PPPOE_HASH_BITS ; ++j){
+			hash ^= addr[i] >> ( j * PPPOE_HASH_BITS );
+		}
+	}
 
-	i = (int) (hash.c[0] & (PPPOE_HASH_SIZE - 1));
+	for (i = 0; i < (sizeof(unsigned long)*8) / PPPOE_HASH_BITS ; ++i)
+		hash ^= sid >> (i*PPPOE_HASH_BITS);
 
-	return i;
+	return hash & ( PPPOE_HASH_SIZE - 1 );
 }	
 
 static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE] = { 0, };
@@ -105,7 +103,7 @@
 /**********************************************************************
  *
  *  Set/get/delete/rehash items  (internal versions)
- *  
+ *
  **********************************************************************/
 static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr)
 {
@@ -162,7 +160,7 @@
 	return ret;
 }
 
-static struct pppox_opt *__find_on_dev(struct net_device *dev, 
+static struct pppox_opt *__find_on_dev(struct net_device *dev,
 				       struct pppox_opt *start)
 {
 	struct pppox_opt *po;
@@ -195,9 +193,9 @@
 /**********************************************************************
  *
  *  Set/get/delete/rehash items
- *  
+ *
  **********************************************************************/
-static inline struct pppox_opt *get_item(unsigned long sid, 
+static inline struct pppox_opt *get_item(unsigned long sid,
 					 unsigned char *addr)
 {
 	struct pppox_opt *po;
@@ -239,7 +237,7 @@
 	return ret;
 }
 
-static struct pppox_opt *find_on_dev(struct net_device *dev, 
+static struct pppox_opt *find_on_dev(struct net_device *dev,
 				     struct pppox_opt *start)
 {
 	struct pppox_opt *po;
@@ -255,7 +253,7 @@
  *  Certain device events require that sockets be unconnected
  *
  **************************************************************************/
-static int pppoe_device_event(struct notifier_block *this, 
+static int pppoe_device_event(struct notifier_block *this,
 			      unsigned long event, void *ptr)
 {
 	int error = NOTIFY_DONE;
@@ -277,7 +275,7 @@
 
 			if (po->sk->state & PPPOX_CONNECTED)
 				pppox_unbind_sock(po->sk);
-			
+
 			if (po->sk->state & PPPOX_CONNECTED) {
 				lock_sock(po->sk);
 				po->sk->shutdown = RCV_SHUTDOWN&SEND_SHUTDOWN;
@@ -313,7 +311,7 @@
  * Receive a PPPoE Session frame.
  *
  ***********************************************************************/
-static int pppoe_rcv(struct sk_buff *skb, 
+static int pppoe_rcv(struct sk_buff *skb,
 		      struct net_device *dev,
 		      struct packet_type *pt)
 
@@ -336,6 +334,19 @@
 		skb_pull(skb, sizeof(struct pppoe_hdr));
 
 		ppp_input(&po->chan, skb);
+	} else if( sk->state & PPPOX_RELAY ){
+		struct pppox_opt *relay_po;
+
+		relay_po = get_item_by_addr( &po->pppoe_relay );
+
+		if( relay_po == NULL  ||
+		    !( relay_po->sk->state & PPPOX_CONNECTED ) )
+			goto abort;
+
+		skb_pull(skb, sizeof(struct pppoe_hdr));
+		if( !__pppoe_xmit( relay_po->sk , skb) )
+			goto abort;
+
 	} else {
 		sock_queue_rcv_skb(sk, skb);
 	}
@@ -353,7 +364,7 @@
  * -- This is solely for detection of PADT frames
  *
  ***********************************************************************/
-static int pppoe_disc_rcv(struct sk_buff *skb, 
+static int pppoe_disc_rcv(struct sk_buff *skb,
 			  struct net_device *dev,
 			  struct packet_type *pt)
 
@@ -539,7 +550,7 @@
 
 	dev = dev_get_by_name(sp->sa_addr.pppoe.dev);
 		
-	error = -ENODEV; 
+	error = -ENODEV;
 	if (!dev)
 		goto end;
 
@@ -768,13 +779,11 @@
 
 /************************************************************************
  *
- * xmit function called by generic PPP driver
- * sends PPP frame over PPPoE socket
+ * xmit function for internal use.
  *
  ***********************************************************************/
-int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
 {
-	struct sock *sk = (struct sock *) chan->private;
 	struct net_device *dev = sk->protinfo.pppox->pppoe_dev;
 	struct pppoe_hdr hdr;
 	struct pppoe_hdr *ph;
@@ -832,6 +841,20 @@
  abort:
 	return 0;
 }
+
+
+/************************************************************************
+ *
+ * xmit function called by generic PPP driver
+ * sends PPP frame over PPPoE socket
+ *
+ ***********************************************************************/
+int pppoe_xmit(struct ppp_channel *chan, struct sk_buff *skb)
+{
+	struct sock *sk = (struct sock *) chan->private;
+	return __pppoe_xmit(sk, skb);
+}
+
 
 struct ppp_channel_ops pppoe_chan_ops = { pppoe_xmit , NULL };
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/setup.c linux/drivers/net/setup.c
--- v2.3.99-pre8/linux/drivers/net/setup.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/net/setup.c	Tue May 23 08:21:51 2000
@@ -12,7 +12,6 @@
 extern int slip_init_ctrl_dev(void);
 extern int strip_init_ctrl_dev(void);
 extern int x25_asy_init_ctrl_dev(void);
-extern int slhc_install(void);
   
 extern int dmascc_init(void);
 extern int yam_init(void);
@@ -22,7 +21,7 @@
 extern int awc4500_pnp_probe(void);
 extern int awc4500_365_probe(void);
 extern int arcnet_init(void); 
-extern int cpm_enet_init(void); 
+extern int scc_enet_init(void); 
 extern int dlci_setup(void); 
 extern int lapbeth_init(void);
 extern int sdla_setup(void); 
@@ -34,7 +33,7 @@
 extern int madgemc_probe(void);
 extern int tms_pci_probe(void);
 
-/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is tring of 9 zeros. */
+/* Pad device name to IFNAMSIZ=16. F.e. __PAD6 is string of 9 zeros. */
 #define __PAD6 "\0\0\0\0\0\0\0\0\0"
 #define __PAD5 __PAD6 "\0"
 #define __PAD4 __PAD5 "\0"
@@ -73,27 +72,17 @@
 #if defined(CONFIG_ARCNET)
 	{arcnet_init, 0},
 #endif
-#if defined(CONFIG_8xx)
-        {cpm_enet_init, 0},
+#if defined(CONFIG_SCC_ENET)
+        {scc_enet_init, 0},
 #endif
 #if defined(CONFIG_COMX)
 	{comx_init, 0},
-#endif	/*
-	 *	SLHC if present needs attaching so other people see it
-	 *	even if not opened.
-	 */
+#endif
+	 
 #if defined(CONFIG_LANMEDIA)
 	{lmc_setup, 0},
 #endif
 	 
-#ifdef CONFIG_INET	 
-#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
-	 || defined(CONFIG_PPP) \
-    || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
-	{slhc_install, 0},
-#endif	
-#endif
-
 /*
 *
 *	Wireless non-HAM
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c
--- v2.3.99-pre8/linux/drivers/net/sgiseeq.c	Sat Feb 26 22:31:47 2000
+++ linux/drivers/net/sgiseeq.c	Sat May 13 08:29:40 2000
@@ -1,4 +1,4 @@
-/* $Id: sgiseeq.c,v 1.9 1998/10/14 23:40:46 ralf Exp $
+/* $Id: sgiseeq.c,v 1.17 2000/03/27 23:02:57 ralf Exp $
  *
  * sgiseeq.c: Seeq8003 ethernet driver for SGI machines.
  *
@@ -694,15 +694,14 @@
 	char *ep;
 
 	if (initialized)	/* Already initialized? */
-		return 0;
+		return 1;
 	initialized++;
 
-	/* First get the ethernet address of the onboard
-	 * interface from ARCS.
+	/* First get the ethernet address of the onboard interface from ARCS.
 	 * This is fragile; PROM doesn't like running from cache.
-	 * On MIPS64 it crashes for some other, yet unknown reason.
+	 * On MIPS64 it crashes for some other, yet unknown reason ...
 	 */
-	ep = romvec->get_evar("eaddr");
+	ep = ArcGetEnvironmentVariable("eaddr");
 	str2eaddr(onboard_eth_addr, ep);
 	return sgiseeq_init(dev,
 			    (struct sgiseeq_regs *) (KSEG1ADDR(0x1fbd4000)),
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/sgiseeq.h linux/drivers/net/sgiseeq.h
--- v2.3.99-pre8/linux/drivers/net/sgiseeq.h	Sat Feb 26 22:31:47 2000
+++ linux/drivers/net/sgiseeq.h	Sat May 13 08:29:40 2000
@@ -1,4 +1,4 @@
-/* $Id: sgiseeq.h,v 1.5 1999/12/04 03:59:03 ralf Exp $
+/* $Id: sgiseeq.h,v 1.4 1999/10/09 00:01:24 ralf Exp $
  * sgiseeq.h: Defines for the Seeq8003 ethernet controller.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/sis900.c linux/drivers/net/sis900.c
--- v2.3.99-pre8/linux/drivers/net/sis900.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/sis900.c	Mon May 15 12:13:10 2000
@@ -79,7 +79,8 @@
 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_900,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_900},
 	{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7016,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018},
+	{0,}
 };
 MODULE_DEVICE_TABLE (pci, sis900_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.3.99-pre8/linux/drivers/net/slhc.c	Tue Nov 23 22:42:21 1999
+++ linux/drivers/net/slhc.c	Tue May 23 08:21:51 2000
@@ -77,7 +77,6 @@
 #include <linux/timer.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <linux/init.h>
 #include <net/checksum.h>
 #include <net/slhc_vj.h>
 #include <asm/unaligned.h>
@@ -749,12 +748,6 @@
 void cleanup_module(void)
 {
 	return;
-}
-
-#else /* MODULE */
-int __init slhc_install(void)
-{
-	return 0;
 }
 
 #endif /* MODULE */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/starfire.c linux/drivers/net/starfire.c
--- v2.3.99-pre8/linux/drivers/net/starfire.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/starfire.c	Sat May 13 08:19:21 2000
@@ -211,7 +211,7 @@
 
 static struct pci_device_id starfire_pci_tbl[] __devinitdata = {
 	{ 0x9004, 0x6915, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_6915 },
-	{ 0, },
+	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/stnic.c linux/drivers/net/stnic.c
--- v2.3.99-pre8/linux/drivers/net/stnic.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/stnic.c	Sat May 20 12:05:30 2000
@@ -0,0 +1,302 @@
+/* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
+ *
+ * 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) 1999 kaz Kojima
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/hitachi_se.h>
+
+#include "8390.h"
+
+#define byte	unsigned char
+#define half	unsigned short
+#define word	unsigned int
+#define vbyte	volatile unsigned char
+#define vhalf	volatile unsigned short
+#define vword	volatile unsigned int
+
+#define STNIC_RUN	0x01	/* 1 == Run, 0 == reset. */
+
+#define START_PG	0	/* First page of TX buffer */
+#define STOP_PG		128	/* Last page +1 of RX ring */
+
+/* Alias */
+#define STNIC_CR	E8390_CMD
+#define PG0_RSAR0	EN0_RSARLO
+#define PG0_RSAR1	EN0_RSARHI
+#define PG0_RBCR0	EN0_RCNTLO
+#define PG0_RBCR1	EN0_RCNTHI
+
+#define CR_RRD		E8390_RREAD
+#define CR_RWR		E8390_RWRITE
+#define CR_PG0		E8390_PAGE0
+#define CR_STA		E8390_START
+#define CR_RDMA		E8390_NODMA
+
+/* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS.  */
+static byte stnic_eadr[6] =
+{0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};
+
+static struct net_device *stnic_dev;
+
+static int stnic_open (struct net_device *dev);
+static int stnic_close (struct net_device *dev);
+static void stnic_reset (struct net_device *dev);
+static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
+			   int ring_page);
+static void stnic_block_input (struct net_device *dev, int count,
+			       struct sk_buff *skb , int ring_offset);
+static void stnic_block_output (struct net_device *dev, int count,
+				const unsigned char *buf, int start_page);
+
+static void stnic_init (struct net_device *dev);
+
+/* SH7750 specific read/write io. */
+static inline void
+STNIC_DELAY (void)
+{
+  vword trash;
+  trash = *(vword *) 0xa0000000;
+  trash = *(vword *) 0xa0000000;
+}
+
+static inline byte
+STNIC_READ (int reg)
+{
+  byte val;
+
+  val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;
+  STNIC_DELAY ();
+  return val;
+}
+
+static inline void
+STNIC_WRITE (int reg, byte val)
+{
+  *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);
+  STNIC_DELAY ();
+}
+
+int __init stnic_probe(void)
+{
+  struct net_device tmp, *dev = NULL;
+  int i;
+
+  tmp.base_addr = 0x1000;
+  dev = &tmp;
+
+  if (load_8390_module ("stnic.c"))
+    return -ENOSYS;
+
+  /* New style probing API */
+  dev = init_etherdev (0, 0);
+  stnic_dev = dev;
+
+  /* Allocate dev->priv and fill in 8390 specific dev fields. */
+  if (ethdev_init (dev))
+    {
+      printk ("Unable to get memory for dev->priv.\n");
+      return -ENOMEM;
+    }
+
+  for (i = 0; i < ETHER_ADDR_LEN; i++)
+    dev->dev_addr[i] = stnic_eadr[i];
+
+  /* Set the base address to point to the NIC, not the "real" base! */
+  dev->base_addr = 0x1000;
+  dev->irq = IRQ_STNIC;
+  dev->open = &stnic_open;
+  dev->stop = &stnic_close;
+
+  /* Snarf the interrupt now.  There's no point in waiting since we cannot
+     share and the board will usually be enabled. */
+  if (request_irq (dev->irq, ei_interrupt, 0, "DP83902A", dev))
+    {
+      printk (" unable to get IRQ %d.\n", dev->irq);
+      kfree(dev->priv);
+      dev->priv = NULL;
+      return EAGAIN;
+    }
+
+  ei_status.name = "eth0";
+  ei_status.word16 = 1;
+  ei_status.tx_start_page = START_PG;
+  ei_status.rx_start_page = START_PG + TX_PAGES;
+  ei_status.stop_page = STOP_PG;
+
+  ei_status.reset_8390 = &stnic_reset;
+  ei_status.get_8390_hdr = &stnic_get_hdr;
+  ei_status.block_input = &stnic_block_input;
+  ei_status.block_output = &stnic_block_output;
+  stnic_init (dev);
+
+  printk (KERN_INFO "NS ST-NIC 83902A\n");
+
+  return 0;
+}
+
+static int
+stnic_open (struct net_device *dev)
+{
+#if 0
+  printk ("stnic open\n");
+#endif
+  ei_open (dev);
+  MOD_INC_USE_COUNT;
+  return 0;
+}
+
+static int
+stnic_close (struct net_device *dev)
+{
+  ei_close (dev);
+  MOD_DEC_USE_COUNT;
+  return 0;
+}
+
+static void
+stnic_reset (struct net_device *dev)
+{
+  *(vhalf *) PA_83902_RST = 0;
+  udelay (5);
+  if (ei_debug > 1)
+    printk("8390 reset done (%ld).", jiffies);
+  *(vhalf *) PA_83902_RST = ~0;
+  udelay (5);
+}
+
+static void
+stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
+	       int ring_page)
+{
+  half buf[2];
+
+  STNIC_WRITE (PG0_RSAR0, 0);
+  STNIC_WRITE (PG0_RSAR1, ring_page);
+  STNIC_WRITE (PG0_RBCR0, 4);
+  STNIC_WRITE (PG0_RBCR1, 0);
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+
+  buf[0] = *(vhalf *) PA_83902_IF;
+  STNIC_DELAY ();
+  buf[1] = *(vhalf *) PA_83902_IF;
+  STNIC_DELAY ();
+  hdr->next = buf[0] >> 8;
+  hdr->status = buf[0] & 0xff;
+#ifdef __LITTLE_ENDIAN__
+  hdr->count = buf[1];
+#else
+  hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
+#endif
+
+  if (ei_debug > 1)
+    printk ("ring %x status %02x next %02x count %04x.\n",
+	    ring_page, hdr->status, hdr->next, hdr->count);
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+/* Block input and output, similar to the Crynwr packet driver. If you are
+   porting to a new ethercard look at the packet driver source for hints.
+   The HP LAN doesn't use shared memory -- we put the packet
+   out through the "remote DMA" dataport. */
+
+static void
+stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,
+		   int offset)
+{
+  char *buf = skb->data;
+  half val;
+
+  STNIC_WRITE (PG0_RSAR0, offset & 0xff);
+  STNIC_WRITE (PG0_RSAR1, offset >> 8);
+  STNIC_WRITE (PG0_RBCR0, length & 0xff);
+  STNIC_WRITE (PG0_RBCR1, length >> 8);
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+
+  if (length & 1)
+    length++;
+
+  while (length > 0)
+    {
+      val = *(vhalf *) PA_83902_IF;
+#ifdef __LITTLE_ENDIAN__
+      *buf++ = val & 0xff;
+      *buf++ = val >> 8;
+#else
+      *buf++ = val >> 8;
+      *buf++ = val & 0xff;
+#endif
+      STNIC_DELAY ();
+      length -= sizeof (half);
+    }
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+static void
+stnic_block_output (struct net_device *dev, int length,
+		    const unsigned char *buf, int output_page)
+{
+
+  STNIC_WRITE (PG0_RBCR0, 1);
+  STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
+
+  STNIC_WRITE (PG0_RSAR0, 0);
+  STNIC_WRITE (PG0_RSAR1, output_page);
+  STNIC_WRITE (PG0_RBCR0, length & 0xff);
+  STNIC_WRITE (PG0_RBCR1, length >> 8);
+  STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);
+
+  if (length & 1)
+    length++;
+
+  while (length > 0)
+    {
+#ifdef __LITTLE_ENDIAN__
+      *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];
+#else
+      *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];
+#endif
+      STNIC_DELAY ();
+      buf += sizeof (half);
+      length -= sizeof (half);
+    }
+
+  STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
+}
+
+/* This function resets the STNIC if something screws up.  */
+static void
+stnic_init (struct net_device *dev)
+{
+  stnic_reset (dev);
+  NS8390_init (dev, 0);
+  return;
+}
+
+/* Hardware interrupt handler.  */
+extern void ei_interrupt (int irq, void *dev_id, struct pt_regs *regs);
+
+void
+do_stnic_intr (int irq, void *dev_id, struct pt_regs *regs)
+{
+  ei_interrupt (0, stnic_dev, regs);
+}
+
+module_init(stnic_probe);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- v2.3.99-pre8/linux/drivers/net/tulip/tulip_core.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/tulip/tulip_core.c	Sat May 13 08:19:21 2000
@@ -168,7 +168,7 @@
 	{ 0x1282, 0x9100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
 	{ 0x1282, 0x9102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DC21140 },
 	{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
-	{0},
+	{0, }
 };
 MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- v2.3.99-pre8/linux/drivers/net/via-rhine.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/via-rhine.c	Sat May 13 08:19:21 2000
@@ -291,7 +291,7 @@
 {
 	{0x1106, 0x6100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT86C100A},
 	{0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VT3043},
-	{0,},			/* terminate list */
+	{0,}			/* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, via_rhine_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-hw-comx.c linux/drivers/net/wan/comx-hw-comx.c
--- v2.3.99-pre8/linux/drivers/net/wan/comx-hw-comx.c	Tue Mar 14 19:10:39 2000
+++ linux/drivers/net/wan/comx-hw-comx.c	Sun May 21 20:34:37 2000
@@ -1031,11 +1031,6 @@
 	char *page;
 
 
-	if (file->f_dentry->d_inode->i_ino != entry->low_ino) {
-		printk(KERN_ERR "comx_write_proc: file <-> data internal error\n");
-		return -EIO;
-	}
-
 	if(ch->init_status & HW_OPEN) {
 		return -EAGAIN;	
 	}
@@ -1234,7 +1229,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &comxhw_read_proc;
 	new_file->write_proc = &comxhw_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 6;
 	new_file->nlink = 1;
 
@@ -1245,7 +1239,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &comxhw_read_proc;
 	new_file->write_proc = &comxhw_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 5;
 	new_file->nlink = 1;
 
@@ -1256,7 +1249,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &comxhw_read_proc;
 	new_file->write_proc = &comxhw_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 2;		// Ezt tudjuk
 	new_file->nlink = 1;
 
@@ -1268,7 +1260,6 @@
 		new_file->data = (void *)new_file;
 		new_file->read_proc = &comxhw_read_proc;
 		new_file->write_proc = &comxhw_write_proc;
-		new_file->proc_iops = &comx_normal_inode_ops;
 		new_file->size = 9;
 		new_file->nlink = 1;
 	}
@@ -1280,7 +1271,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &comxhw_read_proc;
 	new_file->write_proc = &comxhw_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 8;
 	new_file->nlink = 1;
 
@@ -1291,7 +1281,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &comxhw_read_proc;
 	new_file->write_proc = NULL;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 	if ((new_file = create_proc_entry(FILENAME_FIRMWARE, S_IFREG | 0644, 
@@ -1301,7 +1290,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &comxhw_read_proc;
 	new_file->write_proc = &comxhw_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 	if (ch->hardware == &comx_hw) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-hw-locomx.c linux/drivers/net/wan/comx-hw-locomx.c
--- v2.3.99-pre8/linux/drivers/net/wan/comx-hw-locomx.c	Tue Mar 14 19:10:39 2000
+++ linux/drivers/net/wan/comx-hw-locomx.c	Sun May 21 20:34:37 2000
@@ -330,11 +330,6 @@
 	int val;
 	char *page;
 
-	if (file->f_dentry->d_inode->i_ino != entry->low_ino) {
-		printk(KERN_ERR "hw_write_proc: file <-> data internal error\n");
-		return -EIO;
-	}
-
 	if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
 		return -ENOMEM;
 	}
@@ -395,7 +390,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &locomx_read_proc;
 	new_file->write_proc = &locomx_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 	if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644, 
@@ -405,7 +399,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &locomx_read_proc;
 	new_file->write_proc = &locomx_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 /* 	No clock yet */
@@ -417,7 +410,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &locomx_read_proc;
 	new_file->write_proc = &locomx_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 */
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-hw-mixcom.c linux/drivers/net/wan/comx-hw-mixcom.c
--- v2.3.99-pre8/linux/drivers/net/wan/comx-hw-mixcom.c	Tue Mar 14 19:10:39 2000
+++ linux/drivers/net/wan/comx-hw-mixcom.c	Sun May 21 20:34:37 2000
@@ -742,11 +742,6 @@
 	char *page;
 	int value;
 
-	if (file->f_dentry->d_inode->i_ino != entry->low_ino) {
-		printk(KERN_ERR "mixcom_write_proc: file <-> data internal error\n");
-		return -EIO;
-	}
-
 	if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
 		return -ENOMEM;
 	}
@@ -829,7 +824,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &mixcom_read_proc;
 	new_file->write_proc = &mixcom_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 	if ((new_file = create_proc_entry(FILENAME_IRQ, S_IFREG | 0644, 
@@ -839,7 +833,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &mixcom_read_proc;
 	new_file->write_proc = &mixcom_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 #if 0
@@ -850,7 +843,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &mixcom_read_proc;
 	new_file->write_proc = &mixcom_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 #endif
 
@@ -861,7 +853,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &mixcom_read_proc;
 	new_file->write_proc = &mixcom_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 	if ((new_file = create_proc_entry(FILENAME_TWIN, S_IFREG | 0444, 
@@ -871,7 +862,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &mixcom_read_proc;
 	new_file->write_proc = &mixcom_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->nlink = 1;
 
 	setup_twin(dev);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-proto-fr.c linux/drivers/net/wan/comx-proto-fr.c
--- v2.3.99-pre8/linux/drivers/net/wan/comx-proto-fr.c	Tue Mar 14 19:10:39 2000
+++ linux/drivers/net/wan/comx-proto-fr.c	Sun May 21 20:34:37 2000
@@ -641,11 +641,6 @@
 		fr = ch->LINE_privdata;
 	}
 
-	if (file->f_dentry->d_inode->i_ino != entry->low_ino) {
-		printk(KERN_ERR "comxfr_write_proc: file <-> data internal error\n");
-		return -EIO;
-	}
-
 	if (!(page = (char *)__get_free_page(GFP_KERNEL))) {
 		return -ENOMEM;
 	}
@@ -803,7 +798,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &fr_read_proc;
 	new_file->write_proc = &fr_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 5;
 	new_file->nlink = 1;
 
@@ -814,7 +808,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &fr_read_proc;
 	new_file->write_proc = &fr_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 4;
 	new_file->nlink = 1;
 
@@ -860,7 +853,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &fr_read_proc;
 	new_file->write_proc = &fr_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 5;
 	new_file->nlink = 1;
 
@@ -871,7 +863,6 @@
 	new_file->data = (void *)new_file;
 	new_file->read_proc = &fr_read_proc;
 	new_file->write_proc = &fr_write_proc;
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->size = 10;
 	new_file->nlink = 1;
 	MOD_INC_USE_COUNT;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx-proto-lapb.c linux/drivers/net/wan/comx-proto-lapb.c
--- v2.3.99-pre8/linux/drivers/net/wan/comx-proto-lapb.c	Tue Mar 14 19:10:39 2000
+++ linux/drivers/net/wan/comx-proto-lapb.c	Sun May 21 20:34:37 2000
@@ -221,11 +221,6 @@
 	unsigned long parm;
 	char *page;
 
-	if (file->f_dentry->d_inode->i_ino != entry->low_ino) {
-		printk(KERN_ERR "comxlapb_write_proc: file <-> data internal error\n");
-		return -EIO;
-	}
-
 	if (lapb_getparms(dev->priv, &parms)) {
 		return -ENODEV;
 	}
@@ -499,7 +494,6 @@
 		new_file->data = (void *)new_file;
 		new_file->read_proc = &comxlapb_read_proc;
 		new_file->write_proc = &comxlapb_write_proc;
-		new_file->proc_iops = &comx_normal_inode_ops;
 		new_file->size = size;
 		new_file->nlink = 1;
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/comx.c linux/drivers/net/wan/comx.c
--- v2.3.99-pre8/linux/drivers/net/wan/comx.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/wan/comx.c	Sun May 21 20:34:37 2000
@@ -81,21 +81,18 @@
 static struct comx_hardware *comx_channels = NULL;
 static struct comx_protocol *comx_lines = NULL;
 
-struct inode_operations comx_normal_inode_ops; 
-static struct inode_operations comx_root_inode_ops; // for mkdir
-static struct inode_operations comx_debug_inode_ops; // mas a file_ops
-static struct file_operations comx_normal_file_ops;  // with open/relase
-static struct file_operations comx_debug_file_ops;  // with lseek+read
+static struct inode_operations comx_root_inode_ops = {
+	lookup:	comx_lookup,
+	mkdir: comx_mkdir,
+	rmdir: comx_rmdir,
+};
 
-static void comx_delete_dentry(struct dentry *dentry);
+static int comx_delete_dentry(struct dentry *dentry);
 static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode,
 	int size, struct proc_dir_entry *dir);
 
 static struct dentry_operations comx_dentry_operations = {
-	NULL,			/* revalidate */
-	NULL,			/* d_hash */
-	NULL, 			/* d_compare */
-	&comx_delete_dentry	/* d_delete */
+	d_delete:	comx_delete_dentry,
 };
 
 
@@ -601,11 +598,6 @@
 	char str[30];
 	int ret=0;
 
-	if (file->f_dentry->d_inode->i_ino != entry->low_ino) {
-		printk(KERN_ERR "comx_write_proc: file <-> data internal error\n");
-		return -EIO;
-	}
-
 	if (count > PAGE_SIZE) {
 		printk(KERN_ERR "count is %lu > %d!!!\n", count, (int)PAGE_SIZE);
 		return -ENOSPC;
@@ -761,84 +753,12 @@
 	return count;
 }
 
-static loff_t comx_debug_lseek(struct file *file, loff_t offset, int orig)
-{
-	switch(orig) {
-		case 0:	
-			file->f_pos = max(0, min(offset, 
-				file->f_dentry->d_inode->i_size));
-			return(file->f_pos);
-		case 1: 
-			file->f_pos = max(0, min(offset + file->f_pos, 
-				file->f_dentry->d_inode->i_size));
-			return(file->f_pos);
-		case 2: 
-			file->f_pos = max(0, 
-				min(offset + file->f_dentry->d_inode->i_size, 
-				file->f_dentry->d_inode->i_size));
-			return(file->f_pos);
-	}
-	return(file->f_pos);
-}
-
-static int comx_file_open(struct inode *inode, struct file *file)
-{
-
-	if((file->f_mode & FMODE_WRITE) && !(inode->i_mode & 0200)) {
-		return -EACCES;
-	}
-
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static int comx_file_release(struct inode *inode, struct file *file)
-{
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-static ssize_t comx_debug_read(struct file *file, char *buffer, size_t count,
-	loff_t *ppos)
-{
-	struct proc_dir_entry *de = file->f_dentry->d_inode->u.generic_ip;
-	struct net_device *dev = de->parent->data;
-	struct comx_channel *ch = dev->priv;
-	loff_t copied = 0;
-	unsigned long flags;
-
-	save_flags(flags); cli(); // We may run into trouble when debug_area is filled
-				  // from irq inside read. no problem if the buffer is
-				  // large enough
-
-	while (count > 0 && ch->debug_start != ch->debug_end) {
-		int len;
-
-		len = min( (ch->debug_end - ch->debug_start + ch->debug_size)
-			%ch->debug_size, min (ch->debug_size - 
-			ch->debug_start, count));
-
-		if (len) copy_to_user(buffer + copied, 
-			ch->debug_area + ch->debug_start, len);
-		ch->debug_start = (ch->debug_start + len) % ch->debug_size;
-
-		de->size -= len;
-		count -= len;
-		copied += len;
-	}
-
-	restore_flags(flags);
-	return copied;
-}
-
 static int comx_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	struct proc_dir_entry *new_dir, *debug_file;
 	struct net_device *dev;
 	struct comx_channel *ch;
 
-	if (dir->i_ino != comx_root_dir->low_ino) return -ENOTDIR;
-
 	if ((new_dir = create_proc_entry(dentry->d_name.name, mode | S_IFDIR, 
 		comx_root_dir)) == NULL) {
 		return -EIO;
@@ -867,7 +787,6 @@
 	    S_IFREG | 0644, new_dir)) == NULL) {
 		return -ENOMEM;
 	}
-	debug_file->proc_iops = &comx_debug_inode_ops;
 	debug_file->data = (void *)debug_file; 
 	debug_file->read_proc = NULL; // see below
 	debug_file->write_proc = &comx_write_proc;
@@ -912,9 +831,6 @@
 	struct comx_channel *ch = dev->priv;
 	int ret;
 
-	/* Egyelore miert ne ? */
-	if (dir->i_ino != comx_root_dir->low_ino) return -ENOTDIR;
-
 	if (dev->flags & IFF_UP) {
 		printk(KERN_ERR "%s: down interface before removing it\n", dev->name);
 		return -EBUSY;
@@ -962,10 +878,6 @@
 	struct proc_dir_entry *de;
 	struct inode *inode = NULL;
 
-	if (!dir || !S_ISDIR(dir->i_mode)) {
-		return ERR_PTR(-ENOTDIR);
-	}
-
 	if ((de = (struct proc_dir_entry *) dir->u.generic_ip) != NULL) {
 		for (de = de->subdir ; de ; de = de->next) {
 			if ((de && de->low_ino) && 
@@ -998,9 +910,9 @@
 	return __res;
 }
 
-static void comx_delete_dentry(struct dentry *dentry)
+static int comx_delete_dentry(struct dentry *dentry)
 {
-	d_drop(dentry);
+	return 1;
 }
 
 static struct proc_dir_entry *create_comx_proc_entry(char *name, int mode,
@@ -1009,7 +921,6 @@
 	struct proc_dir_entry *new_file;
 
 	if ((new_file = create_proc_entry(name, S_IFREG | mode, dir)) != NULL) {
-		new_file->proc_iops = &comx_normal_inode_ops;
 		new_file->data = (void *)new_file;
 		new_file->read_proc = &comx_read_proc;
 		new_file->write_proc = &comx_write_proc;
@@ -1115,23 +1026,6 @@
 {
 	struct proc_dir_entry *new_file;
 
-	comx_root_inode_ops.lookup = &comx_lookup;
-	comx_root_inode_ops.mkdir = &comx_mkdir;
-	comx_root_inode_ops.rmdir = &comx_rmdir;
-
-	comx_normal_inode_ops.lookup = &comx_lookup;
-
-	memcpy(&comx_debug_inode_ops, &comx_normal_inode_ops, 
-		sizeof(struct inode_operations));
-
-	comx_normal_file_ops.open = &comx_file_open;
-	comx_normal_file_ops.release = &comx_file_release;
-
-	memcpy(&comx_debug_file_ops, &comx_normal_file_ops, 
-		sizeof(struct file_operations));
-	comx_debug_file_ops.llseek = &comx_debug_lseek;
-	comx_debug_file_ops.read = &comx_debug_read;
-
 	comx_root_dir = create_proc_entry("comx", 
 		S_IFDIR | S_IWUSR | S_IRUGO | S_IXUGO, &proc_root);
 	if (!comx_root_dir)
@@ -1143,7 +1037,6 @@
 		return -ENOMEM;
 	}
 	
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->data = new_file;
 	new_file->read_proc = &comx_root_read_proc;
 	new_file->write_proc = NULL;
@@ -1154,7 +1047,6 @@
 		return -ENOMEM;
 	}
 	
-	new_file->proc_iops = &comx_normal_inode_ops;
 	new_file->data = new_file;
 	new_file->read_proc = &comx_root_read_proc;
 	new_file->write_proc = NULL;
@@ -1211,5 +1103,4 @@
 EXPORT_SYMBOL(comx_status);
 EXPORT_SYMBOL(comx_rx);
 EXPORT_SYMBOL(comx_strcasecmp);
-EXPORT_SYMBOL(comx_normal_inode_ops);
 EXPORT_SYMBOL(comx_root_dir);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wan/lmc/lmc_main.c linux/drivers/net/wan/lmc/lmc_main.c
--- v2.3.99-pre8/linux/drivers/net/wan/lmc/lmc_main.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/wan/lmc/lmc_main.c	Sat May 13 08:19:21 2000
@@ -112,7 +112,7 @@
 #ifdef MODULE
 static struct pci_device_id lmc_pci_tbl[] __devinitdata = {
     { 0x1011, 0x009, 0x1379, PCI_ANY_ID, 0, 0, 0},
-    { 0 },
+    { 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, lmc_pci_tbl);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v2.3.99-pre8/linux/drivers/net/wavelan.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/wavelan.c	Sun May 21 20:18:08 2000
@@ -4211,6 +4211,7 @@
 				break;
 			}
 			memset(dev, 0x00, sizeof(struct net_device));
+			memcpy(dev->name, name[i], IFNAMSIZ);	/* Copy name */
 			dev->base_addr = io[i];
 			dev->irq = irq[i];
 			dev->init = &wavelan_config;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h
--- v2.3.99-pre8/linux/drivers/net/wavelan.p.h	Thu May 11 15:30:07 2000
+++ linux/drivers/net/wavelan.p.h	Sun May 21 20:18:08 2000
@@ -695,8 +695,10 @@
 /* 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] = { "", "", "", "" };
 MODULE_PARM(io, "1-4i");
 MODULE_PARM(irq, "1-4i");
+MODULE_PARM(name, "1-4c" __MODULE_STRING(IFNAMSIZ));
 #endif	/* MODULE */
 
 #endif	/* WAVELAN_P_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- v2.3.99-pre8/linux/drivers/net/yellowfin.c	Thu May 11 15:30:07 2000
+++ linux/drivers/net/yellowfin.c	Sat May 13 08:19:21 2000
@@ -237,7 +237,7 @@
 static struct pci_device_id yellowfin_pci_tbl[] __devinitdata = {
 	{ 0x1000, 0x0702, PCI_ANY_ID, PCI_ANY_ID, 0, 0, YELLOWFIN_GNIC },
 	{ 0x1000, 0x0701, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SYM83C885 },
-	{ 0, },
+	{ 0, }
 };
 MODULE_DEVICE_TABLE (pci, yellowfin_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- v2.3.99-pre8/linux/drivers/parport/ChangeLog	Wed Apr 26 16:34:08 2000
+++ linux/drivers/parport/ChangeLog	Tue May 23 08:24:46 2000
@@ -1,3 +1,43 @@
+2000-05-16  Tim Waugh  <twaugh@redhat.com>
+
+	* share.c (parport_claim): Fix SMP race.
+
+2000-05-15  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
+
+	* parport_pc.c (parport_pc_compat_write_block_pio): Check for
+	timeouts.
+	(parport_pc_ecp_write_block_pio): Likewise.
+	(parport_pc_ecp_read_block_pio): Likewise.
+
+2000-05-02  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
+
+	* parport_pc.c: PCI SYBA patch and verbose PCI detection.
+
+2000-05-02  Gunther Mayer  <gunther.mayer@braunschweig.okersurf.de>
+
+	* parport_pc.c (decode_smsc): Fix SMSC 665/666 identification.
+
+2000-04-28  Tim Waugh  <twaugh@redhat.com>
+
+	* ieee1284.c: Short function descriptions can't be multiline.
+
+	* daisy.c: Short function descriptions can't be multiline.
+
+2000-04-19  Tim Waugh  <twaugh@redhat.com>
+
+	* parport_pc.c (parport_pc_fifo_write_block_dma): Make maxlen
+	calculation a bit clearer.
+
+	* ieee1284.c (parport_negotiate): Turn on data line drivers.
+
+	* ieee1284_ops.c (parport_ieee1284_read_byte): Turn off data line
+	drivers.
+	(parport_ieee1284_write_compat): Turn on data line drivers.
+
+	* daisy.c (assign_addrs): Turn on data line drivers.
+	(cpp_mux): Likewise.
+	(cpp_daisy): Likewise.
+
 2000-04-04  Tim Waugh  <twaugh@redhat.com>
 
 	* parport_pc.c: Add support for another PCI card.
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/daisy.c linux/drivers/parport/daisy.c
--- v2.3.99-pre8/linux/drivers/parport/daisy.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/parport/daisy.c	Mon May 15 11:16:30 2000
@@ -252,8 +252,7 @@
 }
 
 /**
- *	parport_device_num - convert device coordinates into a
- *			     canonical device number
+ *	parport_device_num - convert device coordinates
  *	@parport: parallel port number
  *	@mux: multiplexor port number (-1 for no multiplexor)
  *	@daisy: daisy chain address (-1 for no daisy chain address)
@@ -279,8 +278,7 @@
 }
 
 /**
- *	parport_device_coords - convert a canonical device number into
- *				device coordinates
+ *	parport_device_coords - convert canonical device number
  *	@devnum: device number
  *	@parport: pointer to storage for parallel port number
  *	@mux: pointer to storage for multiplexor port number
@@ -325,6 +323,7 @@
 {
 	unsigned char s;
 
+	parport_data_forward (port);
 	parport_write_data (port, 0xaa); udelay (2);
 	parport_write_data (port, 0x55); udelay (2);
 	parport_write_data (port, 0x00); udelay (2);
@@ -373,6 +372,7 @@
 	unsigned char s;
 	int rc;
 
+	parport_data_forward (port);
 	parport_write_data (port, 0xaa); udelay (2);
 	parport_write_data (port, 0x55); udelay (2);
 	parport_write_data (port, 0xf0); udelay (2);
@@ -430,6 +430,7 @@
 	int thisdev = numdevs;
 	char *deviceid;
 
+	parport_data_forward (port);
 	parport_write_data (port, 0xaa); udelay (2);
 	parport_write_data (port, 0x55); udelay (2);
 	parport_write_data (port, 0x00); udelay (2);
@@ -502,8 +503,7 @@
    'from' itself is skipped. */
 
 /**
- *	parport_find_device - find a device with a specified
- *			      manufacturer and model string
+ *	parport_find_device - find a specific device
  *	@mfg: required manufacturer string
  *	@mdl: required model string
  *	@from: previous device number found in search, or %NULL for
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/ieee1284.c linux/drivers/parport/ieee1284.c
--- v2.3.99-pre8/linux/drivers/parport/ieee1284.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/parport/ieee1284.c	Mon May 15 11:16:30 2000
@@ -380,6 +380,7 @@
 	udelay(1);
 
 	/* Event 0: Set data */
+	parport_data_forward (port);
 	parport_write_data (port, m);
 	udelay (400); /* Shouldn't need to wait this long. */
 
@@ -734,7 +735,6 @@
 
 /**
  *	parport_set_timeout - set the inactivity timeout for a device
- *	                      on a port
  *	@dev: device on a port
  *	@inactivity: inactivity timeout (in jiffies)
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/ieee1284_ops.c linux/drivers/parport/ieee1284_ops.c
--- v2.3.99-pre8/linux/drivers/parport/ieee1284_ops.c	Thu Feb 10 17:11:12 2000
+++ linux/drivers/parport/ieee1284_ops.c	Mon May 15 11:16:30 2000
@@ -57,6 +57,7 @@
 
 	port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA;
 	parport_write_control (port, ctl);
+	parport_data_forward (port);
 	while (count < len) {
 		long expire = jiffies + dev->timeout;
 		long wait = (HZ + 99) / 100;
@@ -267,6 +268,9 @@
 			port->physport->ieee1284.phase = IEEE1284_PH_REV_IDLE;
 			break;
 		}
+
+		/* Event 14: Place data bus in high impedance state. */
+		parport_data_reverse (port);
 
 		/* Event 7: Set nAutoFd low. */
 		parport_frob_control (port,
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.3.99-pre8/linux/drivers/parport/parport_pc.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/parport/parport_pc.c	Mon May 15 11:18:19 2000
@@ -704,6 +704,7 @@
 					  int flags)
 {
 	size_t written;
+	int r;
 
 	/* Special case: a timeout of zero means we cannot call schedule(). */
 	if (!port->physport->cad->timeout)
@@ -745,9 +746,14 @@
 		frob_econtrol (port, 0xe0, ECR_PS2 << 5);
 	}
 
-	parport_wait_peripheral (port,
-				 PARPORT_STATUS_BUSY,
-				 PARPORT_STATUS_BUSY);
+	r = parport_wait_peripheral (port,
+				     PARPORT_STATUS_BUSY,
+				     PARPORT_STATUS_BUSY);
+	if (r)
+		printk (KERN_DEBUG
+			"%s: BUSY timeout (%d) in compat_write_block_pio\n", 
+			port->name, r);
+
 	port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
 
 	return written;
@@ -760,6 +766,7 @@
 				       int flags)
 {
 	size_t written;
+	int r;
 
 	/* Special case: a timeout of zero means we cannot call schedule(). */
 	if (!port->physport->cad->timeout)
@@ -772,9 +779,12 @@
 		parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
 
 		/* Event 40: PError goes high. */
-		parport_wait_peripheral (port,
-					 PARPORT_STATUS_PAPEROUT,
-					 PARPORT_STATUS_PAPEROUT);
+		r = parport_wait_peripheral (port,
+					     PARPORT_STATUS_PAPEROUT,
+					     PARPORT_STATUS_PAPEROUT);
+		if (r)
+			printk (KERN_DEBUG "%s: PError timeout (%d) "
+				"in ecp_write_block_pio\n", port->name, r);
 	}
 
 	/* Set up ECP parallel port mode.*/
@@ -818,18 +828,30 @@
 		parport_pc_data_reverse (port); /* Must be in PS2 mode */
 		udelay (5);
 		parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
-		parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
+		r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
+		if (r)
+			printk (KERN_DEBUG "%s: PE,1 timeout (%d) "
+				"in ecp_write_block_pio\n", port->name, r);
+
 		parport_frob_control (port,
 				      PARPORT_CONTROL_INIT,
 				      PARPORT_CONTROL_INIT);
-		parport_wait_peripheral (port,
-					 PARPORT_STATUS_PAPEROUT,
-					 PARPORT_STATUS_PAPEROUT);
+		r = parport_wait_peripheral (port,
+					     PARPORT_STATUS_PAPEROUT,
+					     PARPORT_STATUS_PAPEROUT);
+                if (r)
+                        printk (KERN_DEBUG "%s: PE,2 timeout (%d) "
+				"in ecp_write_block_pio\n", port->name, r);
 	}
 
-	parport_wait_peripheral (port,
-				 PARPORT_STATUS_BUSY, 
-				 PARPORT_STATUS_BUSY);
+	r = parport_wait_peripheral (port,
+				     PARPORT_STATUS_BUSY, 
+				     PARPORT_STATUS_BUSY);
+	if(r)
+		printk (KERN_DEBUG
+			"%s: BUSY timeout (%d) in ecp_write_block_pio\n",
+			port->name, r);
+
 	port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
 
 	return written;
@@ -840,6 +862,7 @@
 {
 	size_t left = length;
 	size_t fifofull;
+	int r;
 	const int fifo = FIFO(port);
 	const struct parport_pc_private *priv = port->physport->private_data;
 	const int fifo_depth = priv->fifo_depth;
@@ -882,7 +905,10 @@
 				      0);
 
 		/* Event 40: PError goes low */
-		parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
+		r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0);
+                if (r)
+                        printk (KERN_DEBUG "%s: PE timeout Event 40 (%d) "
+				"in ecp_read_block_pio\n", port->name, r);
 	}
 
 	/* Set up ECP FIFO mode.*/
@@ -961,9 +987,14 @@
 
 	/* Go to forward idle mode to shut the peripheral up. */
 	parport_frob_control (port, PARPORT_CONTROL_INIT, 0);
-	parport_wait_peripheral (port,
-				 PARPORT_STATUS_PAPEROUT,
-				 PARPORT_STATUS_PAPEROUT);
+	r = parport_wait_peripheral (port,
+				     PARPORT_STATUS_PAPEROUT,
+				     PARPORT_STATUS_PAPEROUT);
+	if (r)
+		printk (KERN_DEBUG
+			"%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n",
+			port->name, r);
+
 	port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
 
 	/* Finish up. */
@@ -1218,7 +1249,7 @@
 
         if (devid == devrev)
 		/* simple heuristics, we happened to read some
-                   non-winbond register */
+                   non-smsc register */
 		return;
 
 	func=NULL;
@@ -1228,8 +1259,8 @@
 
 	if	(id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;}
 	else if	(id==0x6582) type="37c665IR";
-	else if	((id==0x6502) && (key==0x44)) type="37c665GT";
-	else if	((id==0x6502) && (key==0x55)) type="37c666GT";
+	else if	(devid==0x65) type="37c665GT";
+	else if	(devid==0x66) type="37c666GT";
 
 	if(type==NULL)
                 printk("SMSC unknown chip type\n");
@@ -2263,6 +2294,7 @@
 	plx_9050,
 	afavlab_tk9902,
 	timedia_1889,
+	syba_2p_epp,
 };
 
 
@@ -2270,9 +2302,11 @@
  * (but offset by last_sio) */
 static struct parport_pc_pci {
 	int numports;
-	struct {
+	struct { /* BAR (base address registers) numbers in the config
+                    space header */
 		int lo;
-		int hi; /* -ve if not there */
+		int hi; /* -1 if not there, >6 for offset-method (max
+                           BAR is 6) */
 	} addr[4];
 } cards[] __devinitdata = {
 	/* siig_1s1p_10x_550 */		{ 1, { { 3, 4 }, } },
@@ -2301,6 +2335,9 @@
 	/* plx_9050 */			{ 2, { { 4, -1 }, { 5, -1 }, } },
 	/* afavlab_tk9902 */		{ 1, { { 0, 1 }, } },
 	/* timedia_1889 */		{ 1, { { 2, -1 }, } },
+					/* SYBA uses fixed offsets in
+                                           a 1K io window */
+	/* syba_2p_epp */		{ 2, { { 0, 0x078 }, { 0, 0x178 }, } },
 };
 
 static struct pci_device_id parport_pc_pci_tbl[] __devinitdata = {
@@ -2360,7 +2397,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, afavlab_tk9902 },
 	{ PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, timedia_1889 },
-	{ 0, }, /* terminate list */
+	{ 0x1592, 0x0782, PCI_ANY_ID, PCI_ANY_ID, 0, 0, syba_2p_epp },
+	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
 
@@ -2384,9 +2422,16 @@
 		unsigned long io_lo, io_hi;
 		io_lo = pci_resource_start (dev, lo);
 		io_hi = 0;
-		if (hi >= 0)
+		if ((hi >= 0) && (hi <= 6))
 			io_hi = pci_resource_start (dev, hi);
+		else if (hi > 6)
+			io_lo += hi; /* Reinterpret the meaning of
+                                        "hi" as an offset (see SYBA
+                                        def.) */
 		/* TODO: test if sharing interrupts works */
+		printk (KERN_DEBUG "PCI parallel port detected: %04x:%04x, "
+			"I/O at %#lx(%#lx)\n", parport_pc_pci_tbl[i].vendor,
+			parport_pc_pci_tbl[i].device, io_lo, io_hi);
 		if (parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
 					   PARPORT_DMA_NONE, dev))
 			count++;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/parport/share.c linux/drivers/parport/share.c
--- v2.3.99-pre8/linux/drivers/parport/share.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/parport/share.c	Mon May 22 09:50:55 2000
@@ -602,6 +602,7 @@
 void parport_unregister_device(struct pardevice *dev)
 {
 	struct parport *port;
+	unsigned long flags;
 
 #ifdef PARPORT_PARANOID
 	if (dev == NULL) {
@@ -614,11 +615,14 @@
 
 	port = dev->port->physport;
 
+	read_lock_irqsave (&port->cad_lock, flags);
 	if (port->cad == dev) {
+		read_unlock_irqrestore (&port->cad_lock, flags);
 		printk(KERN_DEBUG "%s: %s forgot to release port\n",
 		       port->name, dev->name);
 		parport_release (dev);
 	}
+	read_unlock_irqrestore (&port->cad_lock, flags);
 
 	spin_lock(&port->pardevice_lock);
 	if (dev->next)
@@ -663,14 +667,17 @@
 	struct parport *port = dev->port->physport;
 	unsigned long flags;
 
+	read_lock_irqsave (&port->cad_lock, flags);
 	if (port->cad == dev) {
+		read_unlock_irqrestore (&port->cad_lock, flags);
 		printk(KERN_INFO "%s: %s already owner\n",
 		       dev->port->name,dev->name);
 		return 0;
 	}
+	read_unlock_irqrestore (&port->cad_lock, flags);
 
-try_again:
 	/* Preempt any current device */
+	write_lock_irqsave (&port->cad_lock, flags);
 	if ((oldcad = port->cad) != NULL) {
 		if (oldcad->preempt) {
 			if (oldcad->preempt(oldcad->private))
@@ -680,7 +687,9 @@
 			goto blocked;
 
 		if (port->cad != oldcad) {
-			printk(KERN_WARNING 
+			/* I think we'll actually deadlock rather than
+                           get here, but just in case.. */
+			printk(KERN_WARNING
 			       "%s: %s released port when preempted!\n",
 			       port->name, oldcad->name);
 			if (port->cad)
@@ -707,9 +716,7 @@
 	}
 
 	/* Now we do the change of devices */
-	write_lock_irqsave(&port->cad_lock, flags);
 	port->cad = dev;
-	write_unlock_irqrestore(&port->cad_lock, flags);
 
 #ifdef CONFIG_PARPORT_1284
 	/* If it's a mux port, select it. */
@@ -729,6 +736,7 @@
 
 	/* Restore control registers */
 	port->ops->restore_state(port, dev->state);
+	write_unlock_irqrestore(&port->cad_lock, flags);
 	dev->time = jiffies;
 	return 0;
 
@@ -736,13 +744,10 @@
 	/* If this is the first time we tried to claim the port, register an
 	   interest.  This is only allowed for devices sleeping in
 	   parport_claim_or_block(), or those with a wakeup function.  */
+
+	/* The cad_lock is still held for writing here */
 	if (dev->waiting & 2 || dev->wakeup) {
-		spin_lock_irqsave (&port->waitlist_lock, flags);
-		if (port->cad == NULL) {
-			/* The port got released in the meantime. */
-			spin_unlock_irqrestore (&port->waitlist_lock, flags);
-			goto try_again;
-		}
+		spin_lock (&port->waitlist_lock);
 		if (test_and_set_bit(0, &dev->waiting) == 0) {
 			/* First add ourselves to the end of the wait list. */
 			dev->waitnext = NULL;
@@ -753,8 +758,9 @@
 			} else
 				port->waithead = port->waittail = dev;
 		}
-		spin_unlock_irqrestore (&port->waitlist_lock, flags);
+		spin_unlock (&port->waitlist_lock);
 	}
+	write_unlock_irqrestore (&port->cad_lock, flags);
 	return -EAGAIN;
 }
 
@@ -826,7 +832,9 @@
 	unsigned long flags;
 
 	/* Make sure that dev is the current device */
+	write_lock_irqsave(&port->cad_lock, flags);
 	if (port->cad != dev) {
+		write_unlock_irqrestore (&port->cad_lock, flags);
 		printk(KERN_WARNING "%s: %s tried to release parport "
 		       "when not owner\n", port->name, dev->name);
 		return;
@@ -846,7 +854,6 @@
 	}
 #endif
 
-	write_lock_irqsave(&port->cad_lock, flags);
 	port->cad = NULL;
 	write_unlock_irqrestore(&port->cad_lock, flags);
 
@@ -863,7 +870,7 @@
 			return;
 		} else if (pd->wakeup) {
 			pd->wakeup(pd->private);
-			if (dev->port->cad)
+			if (dev->port->cad) /* racy but no matter */
 				return;
 		} else {
 			printk(KERN_ERR "%s: don't know how to wake %s\n", port->name, pd->name);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/pci/pci.ids linux/drivers/pci/pci.ids
--- v2.3.99-pre8/linux/drivers/pci/pci.ids	Thu May 11 15:30:07 2000
+++ linux/drivers/pci/pci.ids	Sat May 20 11:32:08 2000
@@ -2268,10 +2268,13 @@
 1164  Advanced Peripherals Technologies
 1165  Imagraph Corporation
 	0001  Motion TPEG Recorder/Player with audio
-1166  Relience Computer
+1166  ServerWorks
 	0007  CNB20-LE CPU to PCI Bridge
 	0008  CNB20HE
-	0009  CNB20HE
+	0009  CNB20LE
+	0010  CIOB30
+	0011  CMIC_HE
+	0201  CSB5
 1167  Mutoh Industries Inc
 1168  Thine Electronics Inc
 1169  Centre for Development of Advanced Computing
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
--- v2.3.99-pre8/linux/drivers/pcmcia/yenta.c	Thu May 11 15:30:07 2000
+++ linux/drivers/pcmcia/yenta.c	Sat May 20 11:28:14 2000
@@ -564,7 +564,7 @@
  */
 static void yenta_power_sense(pci_socket_t *socket)
 {
-	u32 status = config_readl(socket, CB_SOCKET_STATE);
+	u32 status = cb_readl(socket, CB_SOCKET_STATE);
 
 	/*
 	 * Nothing inserted, nothing to sense..
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/s390/block/dasd_proc.c linux/drivers/s390/block/dasd_proc.c
--- v2.3.99-pre8/linux/drivers/s390/block/dasd_proc.c	Fri May 12 14:18:55 2000
+++ linux/drivers/s390/block/dasd_proc.c	Sun May 21 20:34:37 2000
@@ -19,64 +19,16 @@
 extern int dasd_proc_read_debug ( char *, char **, off_t, int);
 #endif /* DASD_PROFILE */
 
-struct proc_dir_entry dasd_proc_root_entry = {
-	0,
-	4,"dasd",
-	S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP,
-	1,0,0,
-	0,
-	NULL,
-};
-
-struct proc_dir_entry dasd_proc_devices_entry = {
-	0,
-	7,"devices",
-	S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP,
-	1,0,0,
-	0,
-	NULL,
-	&dasd_proc_read_devices,
-};
-
-#ifdef DASD_PROFILE
-struct proc_dir_entry dasd_proc_stats_entry = {
-	0,
-	10,"statistics",
-	S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP,
-	1,0,0,
-	0,
-	NULL,
-	&dasd_proc_read_statistics,
-};
-
-struct proc_dir_entry dasd_proc_debug_entry = {
-	0,
-	5,"debug",
-	S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP,
-	1,0,0,
-	0,
-	NULL,
-	&dasd_proc_read_debug,
-};
-#endif /* DASD_PROFILE */
-
-struct proc_dir_entry dasd_proc_device_template = {
-	0,
-	6,"dd????",
-	S_IFBLK | S_IRUGO | S_IWUSR | S_IWGRP,
-	1,0,0,
-	0,
-	NULL,
-};
+static struct proc_dir_entry *dasd_proc_root_entry;
 
 void
 dasd_proc_init ( void )
 {
-	proc_register( & proc_root, & dasd_proc_root_entry);
-	proc_register( & dasd_proc_root_entry, & dasd_proc_devices_entry);
+	dasd_proc_root_entry = proc_mkdir("dasd", NULL);
+	create_proc_info_entry("devices",0,&dasd_proc_root_entry,dasd_proc_read_devices);
 #ifdef DASD_PROFILE
- 	proc_register( & dasd_proc_root_entry, & dasd_proc_stats_entry); 
- 	proc_register( & dasd_proc_root_entry, & dasd_proc_debug_entry); 
+	create_proc_info_entry("statistics",0,&dasd_proc_root_entry,dasd_proc_read_statistics);
+	create_proc_info_entry("debug",0,&dasd_proc_root_entry,dasd_proc_read_debug);
 #endif /* DASD_PROFILE */
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/BusLogic.c linux/drivers/scsi/BusLogic.c
--- v2.3.99-pre8/linux/drivers/scsi/BusLogic.c	Wed Dec 29 13:13:18 1999
+++ linux/drivers/scsi/BusLogic.c	Sun May 21 11:38:47 2000
@@ -4354,7 +4354,8 @@
 		   HostAdapter, Length, BusLogic_MessageBufferSize);
   if ((Length -= Offset) <= 0) return 0;
   if (Length >= BytesAvailable) Length = BytesAvailable;
-  *StartPointer = &HostAdapter->MessageBuffer[Offset];
+  memcpy(ProcBuffer, HostAdapter->MessageBuffer + Offset, Length);
+  *StartPointer = ProcBuffer;
   return Length;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.3.99-pre8/linux/drivers/scsi/aha152x.c	Thu May 11 15:30:07 2000
+++ linux/drivers/scsi/aha152x.c	Sun May 21 20:18:08 2000
@@ -13,9 +13,13 @@
  * General Public License for more details.
  *
  *
- * $Id: aha152x.c,v 2.0 1999/12/25 15:07:32 fischer Exp fischer $
+ * $Id: aha152x.c,v 2.1 2000/05/17 16:23:17 fischer Exp fischer $
  *
  * $Log: aha152x.c,v $
+ * Revision 2.1  2000/05/17 16:23:17  fischer
+ * - signature update
+ * - fix for data out w/o scatter gather
+ *
  * Revision 2.0  1999/12/25 15:07:32  fischer
  * - interrupt routine completly reworked
  * - basic support for new eh code
@@ -202,7 +206,7 @@
 
 #include <linux/module.h>
 
-#ifdef PCMCIA
+#if defined(PCMCIA)
 #undef MODULE
 #endif
 
@@ -275,7 +279,6 @@
 #define DPRINTK(when,msgs...)
 #define	DO_LOCK(flags)		spin_lock_irqsave(&QLOCK,flags)
 #define	DO_UNLOCK(flags)	spin_unlock_irqrestore(&QLOCK,flags)
-#define DEBUG_DEFAULT	0
 #endif
 
 #define LEAD		"(scsi%d:%d:%d) "
@@ -290,6 +293,7 @@
 			(cmd) ? ((cmd)->lun & 0x07) : -1
 
 #define DELAY_DEFAULT 100
+#define DEBUG_DEFAULT 0
 
 /* possible irq range */
 #if defined(PCMCIA)
@@ -1714,7 +1718,9 @@
  */
 int aha152x_host_reset(Scsi_Cmnd * SCpnt)
 {
+#if defined(AHA152X_DEBUG)
 	struct Scsi_Host *shpnt = SCpnt->host;
+#endif
 
 	DPRINTK(debug_eh, DEBUG_LEAD "aha152x_host_reset(%p)\n", CMDINFO(SCpnt), SCpnt);
 
@@ -2731,14 +2737,19 @@
 
 		CURRENT_SC->resid += data_count;
 
-		data_count -= CURRENT_SC->SCp.ptr - CURRENT_SC->SCp.buffer->address;
-		while(data_count>0) {
-			CURRENT_SC->SCp.buffer--;
-			CURRENT_SC->SCp.buffers_residual++;
-			data_count -= CURRENT_SC->SCp.buffer->length;
+		if(CURRENT_SC->use_sg) {
+			data_count -= CURRENT_SC->SCp.ptr - CURRENT_SC->SCp.buffer->address;
+			while(data_count>0) {
+				CURRENT_SC->SCp.buffer--;
+				CURRENT_SC->SCp.buffers_residual++;
+				data_count -= CURRENT_SC->SCp.buffer->length;
+			}
+			CURRENT_SC->SCp.ptr           = CURRENT_SC->SCp.buffer->address - data_count;
+			CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + data_count;
+		} else {
+			CURRENT_SC->SCp.ptr           -= data_count;
+			CURRENT_SC->SCp.this_residual += data_count;
 		}
-		CURRENT_SC->SCp.ptr           = CURRENT_SC->SCp.buffer->address - data_count;
-		CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length + data_count;
 	}
 
 	DPRINTK(debug_datao, DEBUG_LEAD "datao_end: request_bufflen=%d; resid=%d; stcnt=%d\n",
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.3.99-pre8/linux/drivers/scsi/megaraid.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/scsi/megaraid.c	Sun May 21 20:18:08 2000
@@ -1481,7 +1481,7 @@
     if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
       u16 magic;
       pci_read_config_word(pdev, PCI_CONF_AMISIG, &magic);
-      if (magic != AMI_SIGNATURE)
+      if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471))
 	continue;		/* not an AMI board */
     }
     printk (KERN_INFO "megaraid: found 0x%4.04x:0x%4.04x: in %s\n",
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.3.99-pre8/linux/drivers/scsi/megaraid.h	Fri Jan 28 15:09:08 2000
+++ linux/drivers/scsi/megaraid.h	Tue May 23 14:20:38 2000
@@ -109,6 +109,7 @@
 #define PCI_CONF_IRQ_OFFSET        0x3c
 #define PCI_CONF_AMISIG            0xa0
 #define AMI_SIGNATURE              0x3344
+#define AMI_SIGNATURE_471          0xCCCC
 
 #if LINUX_VERSION_CODE < 0x20100
 #define MEGARAID \
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/ac97_codec.c linux/drivers/sound/ac97_codec.c
--- v2.3.99-pre8/linux/drivers/sound/ac97_codec.c	Thu May 11 15:30:07 2000
+++ linux/drivers/sound/ac97_codec.c	Sun May 21 20:18:08 2000
@@ -71,6 +71,7 @@
 	{0x83847605, "SigmaTel STAC9704"      , NULL},
 	{0x83847608, "SigmaTel STAC9708"      , NULL},
 	{0x83847609, "SigmaTel STAC9721/23"   , sigmatel_init},
+	{0x54524106, "TriTech TR28026"        , NULL},
 	{0x54524108, "TriTech TR28028"        , NULL},
 	{0x574D4C00, "Wolfson WM9704"         , NULL},
 	{0x00000000, NULL, NULL}
@@ -330,6 +331,10 @@
 
 	/* else, write the first set in the mask as the
 	   output */	
+	/* clear out current set value first (AC97 supports only 1 input!) */
+	val = (1 << ac97_rm2oss[codec->codec_read(codec, AC97_RECORD_SELECT)&0x07]);
+	if (mask != val) mask &= ~val;
+	
 	val = ffs(mask); 
 	val = ac97_oss_rm[val-1];
 	val |= val << 8;  /* set both channels */
@@ -418,6 +423,7 @@
 		switch (_IOC_NR(cmd)) {
 		case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
 			if (!codec->recmask_io) return -EINVAL;
+			if(!val) return 0;
 			if (!(val &= codec->record_sources)) return -EINVAL;
 
 			codec->recmask_io(codec, 0, val);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.3.99-pre8/linux/drivers/sound/cmpci.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/sound/cmpci.c	Sun May 21 20:18:08 2000
@@ -586,7 +586,7 @@
 
 /* --------------------------------------------------------------------- */
 
-#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)
+#define DMABUF_DEFAULTORDER (16-PAGE_SHIFT)
 #define DMABUF_MINORDER 1
 
 static void dealloc_dmabuf(struct dmabuf *db)
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/dmasound/dmasound_awacs.c linux/drivers/sound/dmasound/dmasound_awacs.c
--- v2.3.99-pre8/linux/drivers/sound/dmasound/dmasound_awacs.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/sound/dmasound/dmasound_awacs.c	Sat May 20 12:08:24 2000
@@ -18,12 +18,15 @@
 #include <linux/nvram.h>
 #include <linux/vt_kern.h>
 #include <linux/cuda.h>
+#include <linux/pmu.h>
 
 #include <asm/uaccess.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/dbdma.h>
+#include <asm/feature.h>
+#include <asm/irq.h>
 
 #include "awacs_defs.h"
 #include "dmasound.h"
@@ -1577,257 +1580,279 @@
  * /dev/mixer abstraction
  */
 
-static int PMacMixerIoctl(u_int cmd, u_long arg)
+static int awacs_mixer_ioctl(u_int cmd, u_long arg)
 {
 	int data;
-	/* Different IOCTLS for burgundy*/
-	if (awacs_revision < AWACS_BURGUNDY) {
-		switch (cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-			data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
-				| SOUND_MASK_LINE | SOUND_MASK_MIC
-				| SOUND_MASK_CD | SOUND_MASK_RECLEV
-				| SOUND_MASK_ALTPCM
-				| SOUND_MASK_MONITOR;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_RECMASK:
-			data = SOUND_MASK_LINE | SOUND_MASK_MIC
-				| SOUND_MASK_CD;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_RECSRC:
-			data = 0;
-			if (awacs_reg[0] & MASK_MUX_AUDIN)
-				data |= SOUND_MASK_LINE;
-			if (awacs_reg[0] & MASK_MUX_MIC)
-				data |= SOUND_MASK_MIC;
-			if (awacs_reg[0] & MASK_MUX_CD)
-				data |= SOUND_MASK_CD;
-			if (awacs_reg[1] & MASK_LOOPTHRU)
-				data |= SOUND_MASK_MONITOR;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_RECSRC:
-			IOCTL_IN(arg, data);
-			data &= (SOUND_MASK_LINE
-				 | SOUND_MASK_MIC | SOUND_MASK_CD
-				 | SOUND_MASK_MONITOR);
-			awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
-					  | MASK_MUX_AUDIN);
-			awacs_reg[1] &= ~MASK_LOOPTHRU;
-			if (data & SOUND_MASK_LINE)
-				awacs_reg[0] |= MASK_MUX_AUDIN;
-			if (data & SOUND_MASK_MIC)
-				awacs_reg[0] |= MASK_MUX_MIC;
-			if (data & SOUND_MASK_CD)
-				awacs_reg[0] |= MASK_MUX_CD;
-			if (data & SOUND_MASK_MONITOR)
-				awacs_reg[1] |= MASK_LOOPTHRU;
-			awacs_write(awacs_reg[0] | MASK_ADDR0);
-			awacs_write(awacs_reg[1] | MASK_ADDR1);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_STEREODEVS:
-			data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
-				| SOUND_MASK_RECLEV;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_CAPS:
-			return IOCTL_OUT(arg, 0);
-		case SOUND_MIXER_READ_VOLUME:
-			data = (awacs_reg[1] & MASK_AMUTE)? 0:
-				awacs_get_volume(awacs_reg[2], 6);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_VOLUME:
-			IOCTL_IN(arg, data);
-			return IOCTL_OUT(arg, dmasound_set_volume(data));
-		case SOUND_MIXER_READ_SPEAKER:
-			if (awacs_revision == 3
-			    && sys_ctrler == SYS_CTRLER_CUDA)
-				data = awacs_spkr_vol;
-			else
-				data = (awacs_reg[1] & MASK_CMUTE)? 0:
-					awacs_get_volume(awacs_reg[4], 6);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_SPEAKER:
-			IOCTL_IN(arg, data);
-			if (awacs_revision == 3
-			    && sys_ctrler == SYS_CTRLER_CUDA)
-				awacs_enable_amp(data);
-			else
-				data = awacs_volume_setter(data, 4, MASK_CMUTE, 6);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_ALTPCM:	/* really bell volume */
-			IOCTL_IN(arg, data);
-			beep_volume = data & 0xff;
-			/* fall through */
-		case SOUND_MIXER_READ_ALTPCM:
-			return IOCTL_OUT(arg, beep_volume);
-		case SOUND_MIXER_WRITE_LINE:
-			IOCTL_IN(arg, data);
-			awacs_reg[0] &= ~MASK_MUX_AUDIN;
-			if ((data & 0xff) >= 50)
-				awacs_reg[0] |= MASK_MUX_AUDIN;
-			awacs_write(MASK_ADDR0 | awacs_reg[0]);
-			/* fall through */
-		case SOUND_MIXER_READ_LINE:
-			data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_MIC:
-			IOCTL_IN(arg, data);
-			data &= 0xff;
-			awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE);
-			if (data >= 25) {
-				awacs_reg[0] |= MASK_MUX_MIC;
-				if (data >= 75)
-					awacs_reg[0] |= MASK_GAINLINE;
-			}
-			awacs_write(MASK_ADDR0 | awacs_reg[0]);
-			/* fall through */
-		case SOUND_MIXER_READ_MIC:
-			data = (awacs_reg[0] & MASK_MUX_MIC)?
-				(awacs_reg[0] & MASK_GAINLINE? 100: 50): 0;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_CD:
-			IOCTL_IN(arg, data);
-			awacs_reg[0] &= ~MASK_MUX_CD;
-			if ((data & 0xff) >= 50)
-				awacs_reg[0] |= MASK_MUX_CD;
-			awacs_write(MASK_ADDR0 | awacs_reg[0]);
-			/* fall through */
-		case SOUND_MIXER_READ_CD:
-			data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_RECLEV:
-			IOCTL_IN(arg, data);
-			data = awacs_volume_setter(data, 0, 0, 4);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_RECLEV:
-			data = awacs_get_volume(awacs_reg[0], 4);
-			return IOCTL_OUT(arg, data);
-		}
-	} else {
-		/* We are, we are, we are... Burgundy or better */
-		switch(cmd) {
-		case SOUND_MIXER_READ_DEVMASK:
-			data = SOUND_MASK_VOLUME | SOUND_MASK_CD |
-				SOUND_MASK_LINE | SOUND_MASK_MIC |
-				SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_RECMASK:
-			data = SOUND_MASK_LINE | SOUND_MASK_MIC
-				| SOUND_MASK_CD;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_RECSRC:
-			data = 0;
-			if (awacs_reg[0] & MASK_MUX_AUDIN)
-				data |= SOUND_MASK_LINE;
-			if (awacs_reg[0] & MASK_MUX_MIC)
-				data |= SOUND_MASK_MIC;
-			if (awacs_reg[0] & MASK_MUX_CD)
-				data |= SOUND_MASK_CD;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_RECSRC:
-			IOCTL_IN(arg, data);
-			data &= (SOUND_MASK_LINE
-				 | SOUND_MASK_MIC | SOUND_MASK_CD);
-			awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
-					  | MASK_MUX_AUDIN);
-			if (data & SOUND_MASK_LINE)
-				awacs_reg[0] |= MASK_MUX_AUDIN;
-			if (data & SOUND_MASK_MIC)
-				awacs_reg[0] |= MASK_MUX_MIC;
-			if (data & SOUND_MASK_CD)
-				awacs_reg[0] |= MASK_MUX_CD;
-			awacs_write(awacs_reg[0] | MASK_ADDR0);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_STEREODEVS:
-			data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
-				| SOUND_MASK_RECLEV | SOUND_MASK_CD
-				| SOUND_MASK_LINE;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_CAPS:
-			return IOCTL_OUT(arg, 0);
-		case SOUND_MIXER_WRITE_VOLUME:
-			IOCTL_IN(arg, data);
-			awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data);
-			/* Fall through */
-		case SOUND_MIXER_READ_VOLUME:
-			return IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME));
-		case SOUND_MIXER_WRITE_SPEAKER:
-			IOCTL_IN(arg, data);
-
-			if (!(data & 0xff)) {
-			  /* Mute the left speaker */
-			  awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
-					     awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2);
-			} else {
-			  /* Unmute the left speaker */
-			  awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
-					     awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2);
-			}
-			if (!(data & 0xff00)) {
-			  /* Mute the right speaker */
-			  awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
-					     awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4);
-			} else {
-			  /* Unmute the right speaker */
-			  awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
-					     awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4);
-			}
-
-			data = (((data&0xff)*16)/100 > 0xf ? 0xf :
-				(((data&0xff)*16)/100)) +
-				 ((((data>>8)*16)/100 > 0xf ? 0xf :
-				((((data>>8)*16)/100)))<<4);
-
-			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data);
-			/* Fall through */
-		case SOUND_MIXER_READ_SPEAKER:
-			data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER);
-			data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8);
-			return IOCTL_OUT(arg, ~data);
-		case SOUND_MIXER_WRITE_ALTPCM:	/* really bell volume */
-			IOCTL_IN(arg, data);
-			beep_volume = data & 0xff;
-			/* fall through */
-		case SOUND_MIXER_READ_ALTPCM:
-			return IOCTL_OUT(arg, beep_volume);
-		case SOUND_MIXER_WRITE_LINE:
-			IOCTL_IN(arg, data);
-			awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data);
-
-			/* fall through */
-		case SOUND_MIXER_READ_LINE:
-			data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_MIC:
-			IOCTL_IN(arg, data);
-			/* Mic is mono device */
-			data = (data << 8) + (data << 24);
-			awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data);
-			/* fall through */
-		case SOUND_MIXER_READ_MIC:
-			data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC);
-			data <<= 24;
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_CD:
-			IOCTL_IN(arg, data);
-			awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data);
-			/* fall through */
-		case SOUND_MIXER_READ_CD:
-			data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_WRITE_RECLEV:
-			IOCTL_IN(arg, data);
-			data = awacs_volume_setter(data, 0, 0, 4);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_READ_RECLEV:
-			data = awacs_get_volume(awacs_reg[0], 4);
-			return IOCTL_OUT(arg, data);
-		case SOUND_MIXER_OUTMASK:
-			break;
-		case SOUND_MIXER_OUTSRC:
-			break;
-		}
+
+	switch (cmd) {
+	case SOUND_MIXER_READ_DEVMASK:
+		data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+			| SOUND_MASK_LINE | SOUND_MASK_MIC
+			| SOUND_MASK_CD | SOUND_MASK_RECLEV
+			| SOUND_MASK_ALTPCM
+			| SOUND_MASK_MONITOR;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_RECMASK:
+		data = SOUND_MASK_LINE | SOUND_MASK_MIC
+			| SOUND_MASK_CD;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_RECSRC:
+		data = 0;
+		if (awacs_reg[0] & MASK_MUX_AUDIN)
+			data |= SOUND_MASK_LINE;
+		if (awacs_reg[0] & MASK_MUX_MIC)
+			data |= SOUND_MASK_MIC;
+		if (awacs_reg[0] & MASK_MUX_CD)
+			data |= SOUND_MASK_CD;
+		if (awacs_reg[1] & MASK_LOOPTHRU)
+			data |= SOUND_MASK_MONITOR;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_RECSRC:
+		IOCTL_IN(arg, data);
+		data &= (SOUND_MASK_LINE
+			 | SOUND_MASK_MIC | SOUND_MASK_CD
+			 | SOUND_MASK_MONITOR);
+		awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
+				  | MASK_MUX_AUDIN);
+		awacs_reg[1] &= ~MASK_LOOPTHRU;
+		if (data & SOUND_MASK_LINE)
+			awacs_reg[0] |= MASK_MUX_AUDIN;
+		if (data & SOUND_MASK_MIC)
+			awacs_reg[0] |= MASK_MUX_MIC;
+		if (data & SOUND_MASK_CD)
+			awacs_reg[0] |= MASK_MUX_CD;
+		if (data & SOUND_MASK_MONITOR)
+			awacs_reg[1] |= MASK_LOOPTHRU;
+		awacs_write(awacs_reg[0] | MASK_ADDR0);
+		awacs_write(awacs_reg[1] | MASK_ADDR1);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_STEREODEVS:
+		data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+			| SOUND_MASK_RECLEV;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_CAPS:
+		return IOCTL_OUT(arg, 0);
+	case SOUND_MIXER_READ_VOLUME:
+		data = (awacs_reg[1] & MASK_AMUTE)? 0:
+			awacs_get_volume(awacs_reg[2], 6);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_VOLUME:
+		IOCTL_IN(arg, data);
+		return IOCTL_OUT(arg, PMacSetVolume(data));
+	case SOUND_MIXER_READ_SPEAKER:
+		if (awacs_revision == 3
+		    && sys_ctrler == SYS_CTRLER_CUDA)
+			data = awacs_spkr_vol;
+		else
+			data = (awacs_reg[1] & MASK_CMUTE)? 0:
+				awacs_get_volume(awacs_reg[4], 6);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_SPEAKER:
+		IOCTL_IN(arg, data);
+		if (awacs_revision == 3
+		    && sys_ctrler == SYS_CTRLER_CUDA)
+			awacs_enable_amp(data);
+		else
+			data = awacs_volume_setter(data, 4, MASK_CMUTE, 6);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_ALTPCM:	/* really bell volume */
+		IOCTL_IN(arg, data);
+		beep_volume = data & 0xff;
+				/* fall through */
+	case SOUND_MIXER_READ_ALTPCM:
+		return IOCTL_OUT(arg, beep_volume);
+	case SOUND_MIXER_WRITE_LINE:
+		IOCTL_IN(arg, data);
+		awacs_reg[0] &= ~MASK_MUX_AUDIN;
+		if ((data & 0xff) >= 50)
+			awacs_reg[0] |= MASK_MUX_AUDIN;
+		awacs_write(MASK_ADDR0 | awacs_reg[0]);
+				/* fall through */
+	case SOUND_MIXER_READ_LINE:
+		data = (awacs_reg[0] & MASK_MUX_AUDIN)? 100: 0;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_MIC:
+		IOCTL_IN(arg, data);
+		data &= 0xff;
+		awacs_reg[0] &= ~(MASK_MUX_MIC | MASK_GAINLINE);
+		if (data >= 25) {
+			awacs_reg[0] |= MASK_MUX_MIC;
+			if (data >= 75)
+				awacs_reg[0] |= MASK_GAINLINE;
+		}
+		awacs_write(MASK_ADDR0 | awacs_reg[0]);
+				/* fall through */
+	case SOUND_MIXER_READ_MIC:
+		data = (awacs_reg[0] & MASK_MUX_MIC)?
+			(awacs_reg[0] & MASK_GAINLINE? 100: 50): 0;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_CD:
+		IOCTL_IN(arg, data);
+		awacs_reg[0] &= ~MASK_MUX_CD;
+		if ((data & 0xff) >= 50)
+			awacs_reg[0] |= MASK_MUX_CD;
+		awacs_write(MASK_ADDR0 | awacs_reg[0]);
+				/* fall through */
+	case SOUND_MIXER_READ_CD:
+		data = (awacs_reg[0] & MASK_MUX_CD)? 100: 0;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_RECLEV:
+		IOCTL_IN(arg, data);
+		data = awacs_volume_setter(data, 0, 0, 4);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_RECLEV:
+		data = awacs_get_volume(awacs_reg[0], 4);
+		return IOCTL_OUT(arg, data);
+	case MIXER_WRITE(SOUND_MASK_MONITOR):
+		IOCTL_IN(arg, data);
+		awacs_reg[1] &= ~MASK_LOOPTHRU;
+		if ((data & 0xff) >= 50)
+			awacs_reg[1] |= MASK_LOOPTHRU;
+		awacs_write(MASK_ADDR1 | awacs_reg[1]);
+		/* fall through */
+	case MIXER_READ(SOUND_MASK_MONITOR):
+		data = (awacs_reg[1] & MASK_LOOPTHRU)? 100: 0;
+		return IOCTL_OUT(arg, data);
 	}
 	return -EINVAL;
+}
+
+static int burgundy_mixer_ioctl(u_int cmd, u_long arg)
+{
+	int data;
+
+	/* We are, we are, we are... Burgundy or better */
+	switch(cmd) {
+	case SOUND_MIXER_READ_DEVMASK:
+		data = SOUND_MASK_VOLUME | SOUND_MASK_CD |
+			SOUND_MASK_LINE | SOUND_MASK_MIC |
+			SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_RECMASK:
+		data = SOUND_MASK_LINE | SOUND_MASK_MIC
+			| SOUND_MASK_CD;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_RECSRC:
+		data = 0;
+		if (awacs_reg[0] & MASK_MUX_AUDIN)
+			data |= SOUND_MASK_LINE;
+		if (awacs_reg[0] & MASK_MUX_MIC)
+			data |= SOUND_MASK_MIC;
+		if (awacs_reg[0] & MASK_MUX_CD)
+			data |= SOUND_MASK_CD;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_RECSRC:
+		IOCTL_IN(arg, data);
+		data &= (SOUND_MASK_LINE
+			 | SOUND_MASK_MIC | SOUND_MASK_CD);
+		awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
+				  | MASK_MUX_AUDIN);
+		if (data & SOUND_MASK_LINE)
+			awacs_reg[0] |= MASK_MUX_AUDIN;
+		if (data & SOUND_MASK_MIC)
+			awacs_reg[0] |= MASK_MUX_MIC;
+		if (data & SOUND_MASK_CD)
+			awacs_reg[0] |= MASK_MUX_CD;
+		awacs_write(awacs_reg[0] | MASK_ADDR0);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_STEREODEVS:
+		data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
+			| SOUND_MASK_RECLEV | SOUND_MASK_CD
+			| SOUND_MASK_LINE;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_CAPS:
+		return IOCTL_OUT(arg, 0);
+	case SOUND_MIXER_WRITE_VOLUME:
+		IOCTL_IN(arg, data);
+		awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data);
+				/* Fall through */
+	case SOUND_MIXER_READ_VOLUME:
+		return IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME));
+	case SOUND_MIXER_WRITE_SPEAKER:
+		IOCTL_IN(arg, data);
+
+		if (!(data & 0xff)) {
+			/* Mute the left speaker */
+			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2);
+		} else {
+			/* Unmute the left speaker */
+			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2);
+		}
+		if (!(data & 0xff00)) {
+			/* Mute the right speaker */
+			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4);
+		} else {
+			/* Unmute the right speaker */
+			awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
+					   awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4);
+		}
+
+		data = (((data&0xff)*16)/100 > 0xf ? 0xf :
+			(((data&0xff)*16)/100)) + 
+			((((data>>8)*16)/100 > 0xf ? 0xf :
+			  ((((data>>8)*16)/100)))<<4);
+
+		awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data);
+				/* Fall through */
+	case SOUND_MIXER_READ_SPEAKER:
+		data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER);
+		data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8);
+		return IOCTL_OUT(arg, ~data);
+	case SOUND_MIXER_WRITE_ALTPCM:	/* really bell volume */
+		IOCTL_IN(arg, data);
+		beep_volume = data & 0xff;
+				/* fall through */
+	case SOUND_MIXER_READ_ALTPCM:
+		return IOCTL_OUT(arg, beep_volume);
+	case SOUND_MIXER_WRITE_LINE:
+		IOCTL_IN(arg, data);
+		awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data);
+
+				/* fall through */
+	case SOUND_MIXER_READ_LINE:
+		data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE);				
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_MIC:
+		IOCTL_IN(arg, data);
+				/* Mic is mono device */
+		data = (data << 8) + (data << 24);
+		awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data);
+				/* fall through */
+	case SOUND_MIXER_READ_MIC:
+		data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC);				
+		data <<= 24;
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_CD:
+		IOCTL_IN(arg, data);
+		awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data);
+				/* fall through */
+	case SOUND_MIXER_READ_CD:
+		data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_WRITE_RECLEV:
+		IOCTL_IN(arg, data);
+		data = awacs_volume_setter(data, 0, 0, 4);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_READ_RECLEV:
+		data = awacs_get_volume(awacs_reg[0], 4);
+		return IOCTL_OUT(arg, data);
+	case SOUND_MIXER_OUTMASK:
+		break;
+	case SOUND_MIXER_OUTSRC:
+		break;
+	}
+	return -EINVAL;
+}
+
+static int PMacMixerIoctl(u_int cmd, u_long arg)
+{
+	/* Different IOCTLS for burgundy*/
+	if (awacs_revision >= AWACS_BURGUNDY)
+		return burgundy_mixer_ioctl(cmd, arg);
+	return awacs_mixer_ioctl(cmd, arg);
 }
 
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c
--- v2.3.99-pre8/linux/drivers/sound/emu10k1/main.c	Thu May 11 15:30:08 2000
+++ linux/drivers/sound/emu10k1/main.c	Sat May 13 08:19:21 2000
@@ -80,7 +80,7 @@
 	"EMU10K1",
 };
 
-static struct pci_device_id emu10k1_pci_tbl[] = {
+static struct pci_device_id emu10k1_pci_tbl[] __devinitdata = {
 	{PCI_VENDOR_ID_CREATIVE, PCI_DEVICE_ID_CREATIVE_EMU10K1,
 	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, EMU10K1},
 	{0,}
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.3.99-pre8/linux/drivers/sound/es1370.c	Thu May 11 15:30:08 2000
+++ linux/drivers/sound/es1370.c	Sat May 13 08:19:21 2000
@@ -2599,7 +2599,7 @@
 
 static struct pci_device_id id_table[] __devinitdata = {
 	{ PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
-	{ 0, 0, 0, 0, 0, 0 }
+	{ 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, id_table);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.3.99-pre8/linux/drivers/sound/es1371.c	Thu May 11 15:30:08 2000
+++ linux/drivers/sound/es1371.c	Sat May 13 08:19:21 2000
@@ -2804,7 +2804,7 @@
 	{ PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
 	{ PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_CT5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
 	{ PCI_VENDOR_ID_ECTIVA, PCI_DEVICE_ID_ECTIVA_EV1938, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
-	{ 0, 0, 0, 0, 0, 0 }
+	{ 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, id_table);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.3.99-pre8/linux/drivers/sound/esssolo1.c	Thu May 11 15:30:08 2000
+++ linux/drivers/sound/esssolo1.c	Sat May 13 08:19:21 2000
@@ -2335,7 +2335,7 @@
 
 static struct pci_device_id id_table[] __devinitdata = {
 	{ PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_SOLO1, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
-	{ 0, 0, 0, 0, 0, 0 }
+	{ 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, id_table);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.3.99-pre8/linux/drivers/sound/sb_card.c	Thu May 11 15:30:08 2000
+++ linux/drivers/sound/sb_card.c	Sat May 13 08:14:03 2000
@@ -249,6 +249,11 @@
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
 		0,0,0,0,
 		0,1,1,-1},
+	{"Sound Blaster 16",
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
+		0,0,0,0,
+		0,1,1,-1},
 	{"Sound Blaster 16", 
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
@@ -364,6 +369,11 @@
 		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045),
 		0,0,0,0,
 		0,1,1,-1},
+	{"ESS 1688",
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968),
+		0,0,0,0,
+		0,1,2,-1},
 	{"ESS 1868",
 		ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
 		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868),
@@ -442,11 +452,6 @@
 		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001),
 		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001),
 		1,0,0,0},
-	{"Creative SB16 PnP", 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a), 
-		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031),
-		0,0,0,0,
-		0,1,1,-1},
 	{0}
 };
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.3.99-pre8/linux/drivers/sound/sonicvibes.c	Thu May 11 15:30:08 2000
+++ linux/drivers/sound/sonicvibes.c	Sat May 13 08:19:21 2000
@@ -2634,7 +2634,7 @@
 
 static struct pci_device_id id_table[] __devinitdata = {
        { PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SONICVIBES, PCI_ANY_ID, PCI_ANY_ID, 0, 0 },
-       { 0, 0, 0, 0, 0, 0 }
+       { 0, }
 };
 
 MODULE_DEVICE_TABLE(pci, id_table);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/trident.c linux/drivers/sound/trident.c
--- v2.3.99-pre8/linux/drivers/sound/trident.c	Thu May 11 15:30:08 2000
+++ linux/drivers/sound/trident.c	Sun May 21 20:18:08 2000
@@ -29,6 +29,10 @@
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  *  History
+ *  v0.14.3 May 20 2000 Aaron Holtzman
+ *  Fix kfree'd memory access in release
+ *  Fix race in open while looking for a free virtual channel slot
+ *  remove open_wait wq (which appears to be unused)
  *  v0.14.2 Mar 29 2000 Ching Ling Lee
  *	Add clear to silence advance in trident_update_ptr 
  *	fix invalid data of the end of the sound
@@ -166,10 +170,6 @@
 	unsigned int magic;
 	struct trident_card *card;	/* Card info */
 
-	/* single open lock mechanism, only used for recording */
-	struct semaphore open_sem;
-	wait_queue_head_t open_wait;
-
 	/* file mode */
 	mode_t open_mode;
 
@@ -261,6 +261,9 @@
 	/* We keep trident cards in a linked list */
 	struct trident_card *next;
 
+	/* single open lock mechanism, only used for recording */
+	struct semaphore open_sem;
+
 	/* The trident has a certain amount of cross channel interaction
 	   so we use a single per card lock */
 	spinlock_t lock;
@@ -1904,6 +1907,7 @@
 
 	/* find an avaiable virtual channel (instance of /dev/dsp) */
 	while (card != NULL) {
+		down(&card->open_sem);
 		for (i = 0; i < NR_HW_CH; i++) {
 			if (card->states[i] == NULL) {
 				state = card->states[i] = (struct trident_state *)
@@ -1915,6 +1919,7 @@
 				goto found_virt;
 			}
 		}
+		up(&card->open_sem);
 		card = card->next;
 	}
 	/* no more virtual channel avaiable */
@@ -1939,10 +1944,8 @@
 	state->card = card;
 	state->magic = TRIDENT_STATE_MAGIC;
 	init_waitqueue_head(&dmabuf->wait);
-	init_MUTEX(&state->open_sem);
 	file->private_data = state;
 
-	down(&state->open_sem);
 
 	/* set default sample format. According to OSS Programmer's Guide  /dev/dsp
 	   should be default to unsigned 8-bits, mono, with sample rate 8kHz and
@@ -1985,7 +1988,7 @@
 	}
 
 	state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-	up(&state->open_sem);
+	up(&card->open_sem);
 
 #ifdef DEBUG
 	printk(KERN_ERR "trident: open virtual channel %d, hard channel %d\n", 
@@ -1999,6 +2002,7 @@
 static int trident_release(struct inode *inode, struct file *file)
 {
 	struct trident_state *state = (struct trident_state *)file->private_data;
+	struct trident_card *card = state->card;
 	struct dmabuf *dmabuf = &state->dmabuf;
 
 	VALIDATE_STATE(state);
@@ -2009,25 +2013,25 @@
 	}
 
 	/* stop DMA state machine and free DMA buffers/channels */
-	down(&state->open_sem);
+	down(&card->open_sem);
 
 	if (file->f_mode & FMODE_WRITE) {
 		stop_dac(state);
 		dealloc_dmabuf(state);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 	}
+
 	if (file->f_mode & FMODE_READ) {
 		stop_adc(state);
 		dealloc_dmabuf(state);
 		state->card->free_pcm_channel(state->card, dmabuf->channel->num);
 	}
 
-	kfree(state->card->states[state->virt]);
-	state->card->states[state->virt] = NULL;
-	state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+	card->states[state->virt] = NULL;
+	kfree(state);
 
 	/* we're covered by the open_sem */
-	up(&state->open_sem);
+	up(&card->open_sem);
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -2408,6 +2412,7 @@
 	card->banks[BANK_A].bitmap = 0UL;
 	card->banks[BANK_B].addresses = &bank_b_addrs;
 	card->banks[BANK_B].bitmap = 0UL;
+	init_MUTEX(&card->open_sem);
 	spin_lock_init(&card->lock);
 	devs = card;
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- v2.3.99-pre8/linux/drivers/sound/via82cxxx_audio.c	Fri May 12 14:18:55 2000
+++ linux/drivers/sound/via82cxxx_audio.c	Mon May 15 12:13:10 2000
@@ -305,7 +305,7 @@
 
 static struct pci_device_id via_pci_tbl[] __initdata = {
 	{ PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ 0, },
+	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci,via_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/tc.c linux/drivers/tc/tc.c
--- v2.3.99-pre8/linux/drivers/tc/tc.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/tc/tc.c	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: $
+/* $Id: tc.c,v 1.3 1999/10/09 00:01:32 ralf Exp $
  * tc-init: We assume the TURBOchannel to be up and running so
  * just probe for Modules and fill in the global data structure
  * tc_bus.
@@ -13,6 +13,7 @@
 
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/ioport.h>
 #include <asm/addrspace.h>
 #include <asm/errno.h>
 #include <asm/dec/machtype.h>
@@ -231,6 +232,6 @@
 					tc_bus[i].name, tc_bus[i].firmware);
 			}
 #endif
+		ioport_resource.end = KSEG2 - 1;
 	}
-
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/tcsyms.c linux/drivers/tc/tcsyms.c
--- v2.3.99-pre8/linux/drivers/tc/tcsyms.c	Wed Jun 30 11:24:55 1999
+++ linux/drivers/tc/tcsyms.c	Sat May 13 08:31:25 2000
@@ -1,13 +1,14 @@
 /*
- *	Turbo Channel Services -- Exported Symbols
+ *	TURBOchannel Services -- Exported Symbols
  *
  */
 
 #include <linux/module.h>
 #include <asm/dec/tc.h>
 
-EXPORT_SYMBOL(get_tc_irq_nr);
-EXPORT_SYMBOL(claim_tc_card);
 EXPORT_SYMBOL(search_tc_card);
-EXPORT_SYMBOL(get_tc_speed);
+EXPORT_SYMBOL(claim_tc_card);
+EXPORT_SYMBOL(release_tc_card);
 EXPORT_SYMBOL(get_tc_base_addr);
+EXPORT_SYMBOL(get_tc_irq_nr);
+EXPORT_SYMBOL(get_tc_speed);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/zs.c linux/drivers/tc/zs.c
--- v2.3.99-pre8/linux/drivers/tc/zs.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/tc/zs.c	Sat May 13 08:31:25 2000
@@ -42,6 +42,7 @@
 #include <asm/segment.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
+#include <asm/wbflush.h>
 #include <asm/dec/interrupts.h>
 #include <asm/dec/machtype.h>
 #include <asm/dec/tc.h>
@@ -155,7 +156,7 @@
  * memory if large numbers of serial ports are open.
  */
 static unsigned char tmp_buf[4096]; /* This is cheating */
-static struct semaphore tmp_buf_sem = MUTEX;
+static DECLARE_MUTEX(tmp_buf_sem);
 
 static inline int serial_paranoia_check(struct dec_serial *info,
 					dev_t device, const char *routine)
@@ -195,7 +196,7 @@
 
 	if (reg != 0) {
 		*channel->control = reg & 0xf;
-		RECOVERY_DELAY;
+		wbflush(); RECOVERY_DELAY;
 	}
 	retval = *channel->control;
 	RECOVERY_DELAY;
@@ -207,10 +208,10 @@
 {
 	if (reg != 0) {
 		*channel->control = reg & 0xf;
-		RECOVERY_DELAY;
+		wbflush(); RECOVERY_DELAY;
 	}
 	*channel->control = value;
-	RECOVERY_DELAY;
+	wbflush(); RECOVERY_DELAY;
 	return;
 }
 
@@ -227,7 +228,7 @@
 				unsigned char value)
 {
 	*channel->data = value;
-	RECOVERY_DELAY;
+	wbflush(); RECOVERY_DELAY;
 	return;
 }
 
@@ -1313,7 +1314,7 @@
 		char_time = 1;
 	if (timeout)
 		char_time = MIN(char_time, timeout);
-	while ((read_zsreg(info->zs_channel, 1) & ALL_SNT) == 0) {
+	while ((read_zsreg(info->zs_channel, 1) & Tx_BUF_EMP) == 0) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(char_time);
 		if (signal_pending(current))
@@ -1351,7 +1352,7 @@
 static int block_til_ready(struct tty_struct *tty, struct file * filp,
 			   struct dec_serial *info)
 {
-	struct wait_queue wait = { current, NULL };
+	DECLARE_WAITQUEUE(wait, current);
 	int		retval;
 	int		do_clocal = 0;
 
@@ -1773,8 +1774,8 @@
 		info->tqueue.data = info;
 		info->callout_termios =callout_driver.init_termios;
 		info->normal_termios = serial_driver.init_termios;
-		info->open_wait = 0;
-		info->close_wait = 0;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
 		printk("tty%02d at 0x%08x (irq = %d)", info->line, 
 		       info->port, info->irq);
 		printk(" is a Z85C30 SCC\n");
@@ -1828,7 +1829,7 @@
 	while (!(*(info->zs_channel->control) & Tx_BUF_EMP) && --loops)
 		RECOVERY_DELAY;
 	*(info->zs_channel->data) = ch;
-	RECOVERY_DELAY;
+	wbflush(); RECOVERY_DELAY;
 
 	restore_flags(flags);
 }
@@ -2021,10 +2022,9 @@
 /*
  *	Register console.
  */
-long __init zs_serial_console_init(long kmem_start, long kmem_end)
+void __init zs_serial_console_init(void)
 {
 	register_console(&sercons);
-	return kmem_start;
 }
 #endif /* ifdef CONFIG_SERIAL_CONSOLE */
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/tc/zs.h linux/drivers/tc/zs.h
--- v2.3.99-pre8/linux/drivers/tc/zs.h	Fri Jun 25 17:38:40 1999
+++ linux/drivers/tc/zs.h	Sat May 13 08:31:25 2000
@@ -142,8 +142,8 @@
 	struct tq_struct	tqueue_hangup;
 	struct termios		normal_termios;
 	struct termios		callout_termios;
-	struct wait_queue	*open_wait;
-	struct wait_queue	*close_wait;
+	wait_queue_head_t	open_wait;
+	wait_queue_head_t	close_wait;
 };
 
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/Config.in linux/drivers/usb/Config.in
--- v2.3.99-pre8/linux/drivers/usb/Config.in	Fri May 12 14:18:55 2000
+++ linux/drivers/usb/Config.in	Sat May 20 09:21:51 2000
@@ -43,7 +43,7 @@
    dep_tristate '  USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB
    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
 	   dep_tristate '  USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB
-      dep_tristate '  USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB
+      dep_tristate '  USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB $CONFIG_SCSI
       if [ "$CONFIG_USB_STORAGE" != "n" ]; then
          bool '    USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG
       fi
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.3.99-pre8/linux/drivers/usb/audio.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/audio.c	Mon May 15 11:38:19 2000
@@ -3,7 +3,7 @@
 /*
  *	audio.c  --  USB Audio Class driver
  *
- *	Copyright (C) 1999
+ *	Copyright (C) 1999, 2000
  *	    Alan Cox (alan@lxorguk.ukuu.org.uk)
  *	    Thomas Sailer (sailer@ife.ee.ethz.ch)
  *
@@ -59,6 +59,21 @@
  * 1999-12-20:  Fix bad bug in conversion to per interface probing.
  *		disconnect was called multiple times for the audio device,
  *		leading to a premature freeing of the audio structures
+ * 2000-05-13:  I don't remember who changed the find_format routine,
+ *              but the change was completely broken for the Dallas
+ *              chip. Anyway taking sampling rate into account in find_format
+ *              is bad and should not be done unless there are devices with
+ *              completely broken audio descriptors. Unless someone shows
+ *              me such a descriptor, I will not allow find_format to
+ *              take the sampling rate into account.
+ *              Also, the former find_format made:
+ *              - mpg123 play mono instead of stereo
+ *              - sox completely fail for wav's with sample rates < 44.1kHz
+ *                  for the Dallas chip.
+ *              Also fix a rather long standing problem with applications that
+ *              use "small" writes producing no sound at all.
+ * 2000-05-15:  My fears came true, the Philips camera indeed has pretty stupid
+ *              audio descriptors.
  *
  */
 
@@ -441,9 +456,9 @@
 	db->bufsize = nr << PAGE_SHIFT;
 	db->ready = 1;
 	printk(KERN_DEBUG "dmabuf_init: bytepersec %d bufs %d ossfragshift %d ossmaxfrags %d "
-	       "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d\n",
+	       "fragshift %d fragsize %d numfrag %d dmasize %d bufsize %d fmt 0x%x\n",
 	       bytepersec, bufs, db->ossfragshift, db->ossmaxfrags, db->fragshift, db->fragsize,
-	       db->numfrag, db->dmasize, db->bufsize);
+	       db->numfrag, db->dmasize, db->bufsize, db->format);
 	return 0;
 }
 
@@ -973,6 +988,8 @@
 		}
 		spin_lock_irqsave(&as->lock, flags);
 	}
+	if (u->dma.count <= 0 && !u->dma.mapped)
+		return 0;
 	u->flags |= FLG_RUNNING;
 	if (!(u->flags & FLG_URB0RUNNING)) {
 		urb = &u->durb[0].urb;
@@ -1332,6 +1349,8 @@
 		}
 		spin_lock_irqsave(&as->lock, flags);
 	}
+	if (u->dma.count <= 0 && !u->dma.mapped)
+		return 0;
        	u->flags |= FLG_RUNNING;
 	if (!(u->flags & FLG_URB0RUNNING)) {
 		urb = &u->durb[0].urb;
@@ -1395,30 +1414,39 @@
 
 /* --------------------------------------------------------------------- */
 
-static unsigned int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int rate)
+static unsigned int format_goodness(struct audioformat *afp, unsigned int fmt, unsigned int srate)
 {
-	unsigned int i;
+	unsigned int g = 0;
+
+	if (srate < afp->sratelo)
+		g += afp->sratelo - srate;
+	if (srate > afp->sratehi)
+		g += srate - afp->sratehi;
+	if (AFMT_ISSTEREO(afp->format) && !AFMT_ISSTEREO(fmt))
+		g += 0x100000;
+	if (!AFMT_ISSTEREO(afp->format) && AFMT_ISSTEREO(fmt))
+		g += 0x400000;
+	if (AFMT_IS16BIT(afp->format) && !AFMT_IS16BIT(fmt))
+		g += 0x100000;
+	if (!AFMT_IS16BIT(afp->format) && AFMT_IS16BIT(fmt))
+		g += 0x400000;
+	return g;
+}
+
+static int find_format(struct audioformat *afp, unsigned int nr, unsigned int fmt, unsigned int srate)
+{
+	unsigned int i, g, gb = ~0;
+	int j = -1; /* default to failure */
 
-	/* first find an exact match, taking both format and sample rate into account,
-	   but ignore stereo bit */
+	/* find "best" format (according to format_goodness) */
 	for (i = 0; i < nr; i++) {
-		if (afp[i].format == (fmt & ~AFMT_STEREO) && rate >= afp[i].sratelo && rate <= afp[i].sratehi)
-			return i;
+		g = format_goodness(&afp[i], fmt, srate);
+		if (g >= gb) 
+			continue;
+		j = i;
+		gb = g;
 	}
-		
-	/* second find a match with the same stereo/mono and 8bit/16bit property */
-	for (i = 0; i < nr; i++)
-		if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) &&
-		    !AFMT_IS16BIT(afp[i].format) == !AFMT_IS16BIT(fmt) && 
-		    rate >= afp[i].sratelo && rate <= afp[i].sratehi)
-			return i;
-	/* third find a match with the same number of channels */
-	for (i = 0; i < nr; i++)
-		if (!AFMT_ISSTEREO(afp[i].format) == !AFMT_ISSTEREO(fmt) && 
-		    rate >= afp[i].sratelo && rate <= afp[i].sratehi)
-			return i;
-	/* return failure */
-	return -1;
+       	return j;
 }
 
 static int set_format_in(struct usb_audiodev *as)
@@ -1430,9 +1458,9 @@
 	struct usbin *u = &as->usbin;
 	struct dmabuf *d = &u->dma;
 	struct audioformat *fmt;
-	unsigned int fmtnr, ep;
+	unsigned int ep;
 	unsigned char data[3];
-	int ret;
+	int fmtnr, ret;
 
 	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
 		return 0;
@@ -1465,7 +1493,9 @@
 		d->srate = fmt->sratelo;
 	if (d->srate > fmt->sratehi)
 		d->srate = fmt->sratehi;
-printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
+#if 1
+	printk(KERN_DEBUG "usb_audio: set_format_in: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
+#endif
 	if (usb_set_interface(dev, alts->bInterfaceNumber, fmt->altsetting) < 0) {
 		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
 		       dev->devnum, u->interface, fmt->altsetting);
@@ -1517,9 +1547,9 @@
 	struct usbout *u = &as->usbout;
 	struct dmabuf *d = &u->dma;
 	struct audioformat *fmt;
-	unsigned int fmtnr, ep;
+	unsigned int ep;
 	unsigned char data[3];
-	int ret;
+	int fmtnr, ret;
 
 	if (u->interface < 0 || u->interface >= config->bNumInterfaces)
 		return 0;
@@ -1559,7 +1589,9 @@
 		d->srate = fmt->sratelo;
 	if (d->srate > fmt->sratehi)
 		d->srate = fmt->sratehi;
-printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
+#if 1
+	printk(KERN_DEBUG "usb_audio: set_format_out: usb_set_interface %u %u\n", alts->bInterfaceNumber, fmt->altsetting);
+#endif
 	if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) {
 		printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n",
 		       dev->devnum, u->interface, fmt->altsetting);
@@ -1927,6 +1959,7 @@
 	
 	if (as->usbout.dma.mapped || !as->usbout.dma.ready)
 		return 0;
+	usbout_start(as);
 	add_wait_queue(&as->usbout.dma.wait, &wait);
 	for (;;) {
 		__set_current_state(TASK_INTERRUPTIBLE);
@@ -2033,6 +2066,7 @@
 	ssize_t ret = 0;
 	unsigned long flags;
 	unsigned int ptr;
+	unsigned int start_thr;
 	int cnt, err;
 
 	if (ppos != &file->f_pos)
@@ -2043,10 +2077,11 @@
 		return ret;
 	if (!access_ok(VERIFY_READ, buffer, count))
 		return -EFAULT;
+	start_thr = (as->usbout.dma.srate << AFMT_BYTESSHIFT(as->usbout.dma.format)) / (1000 / (3 * DESCFRAMES));
 	add_wait_queue(&as->usbout.dma.wait, &wait);
 	while (count > 0) {
 #if 0
-		printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%x\n",
+		printk(KERN_DEBUG "usb_audio_write: count %u dma: count %u rdptr %u wrptr %u dmasize %u fragsize %u flags 0x%02x taskst 0x%lx\n",
 		       count, as->usbout.dma.count, as->usbout.dma.rdptr, as->usbout.dma.wrptr, as->usbout.dma.dmasize, as->usbout.dma.fragsize,
 		       as->usbout.flags, current->state);
 #endif
@@ -2097,7 +2132,7 @@
 		count -= cnt;
 		buffer += cnt;
 		ret += cnt;
-		if (usbout_start(as)) {
+		if (as->usbout.dma.count >= start_thr && usbout_start(as)) {
 			if (!ret)
 				ret = -ENODEV;
 			break;
@@ -2525,17 +2560,6 @@
 
 /* --------------------------------------------------------------------- */
 
-/*
- *	TO DO in order to get to the point of building an OSS interface
- *	structure, let alone playing music..
- *
- *	Use kmalloc/kfree for the descriptors we build
- *	Write the descriptor->OSS convertor code
- *	Figure how we deal with mixers
- *	Check alternate configurations. For now assume we will find one
- *	zero bandwidth (idle) config and one or more live one pers interface.
- */
-
 static void * usb_audio_probe(struct usb_device *dev, unsigned int ifnum);
 static void usb_audio_disconnect(struct usb_device *dev, void *ptr);
 
@@ -2543,25 +2567,11 @@
 	"audio",
 	usb_audio_probe,
 	usb_audio_disconnect,
-	/*{ NULL, NULL }, */ LIST_HEAD_INIT(usb_audio_driver.driver_list), 
+	LIST_HEAD_INIT(usb_audio_driver.driver_list), 
 	NULL,
 	0
 };
 
-
-#if 0
-static int usb_audio_irq(int state, void *buffer, int len, void *dev_id)
-{
-#if 0
-	struct usb_audio_device *aud = (struct usb_audio_device *)dev_id;
-
-	printk(KERN_DEBUG "irq on %p\n", aud);
-#endif
-
-	return 1;
-}
-#endif
-
 static void *find_descriptor(void *descstart, unsigned int desclen, void *after, 
 			     u8 dtype, int iface, int altsetting)
 {
@@ -3559,11 +3569,6 @@
 			unregister_sound_mixer(ms->dev_mixer);
 		ms->dev_mixer = -1;
 	}
-#if 0
-	if(aud->irq_handle)
-		usb_release_irq(dev, aud->irq_handle, aud->irqpipe);
-	aud->irq_handle = NULL;
-#endif
 	release(s);
 	wake_up(&open_wait);
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.3.99-pre8/linux/drivers/usb/hub.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/hub.c	Sat May 20 11:23:54 2000
@@ -338,7 +338,7 @@
 	portstatus = le16_to_cpu(portsts.wPortStatus);
 	portchange = le16_to_cpu(portsts.wPortChange);
 	dbg("portstatus %x, change %x, %s", portstatus, portchange,
-		portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
+		portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "1.5 Mb/s" : "12 Mb/s");
 
 	/* Clear the connection change status */
 	usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_C_CONNECTION);
@@ -369,7 +369,7 @@
 		portstatus = le16_to_cpu(portsts.wPortStatus);
 		portchange = le16_to_cpu(portsts.wPortChange);
 		dbg("portstatus %x, change %x, %s", portstatus ,portchange,
-			portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
+			portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "1.5 Mb/s" : "12 Mb/s");
 
 		if ((portchange & USB_PORT_STAT_C_CONNECTION) ||
 		    !(portstatus & USB_PORT_STAT_CONNECTION))
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/input.c linux/drivers/usb/input.c
--- v2.3.99-pre8/linux/drivers/usb/input.c	Tue Apr 11 15:09:20 2000
+++ linux/drivers/usb/input.c	Mon May 15 11:38:12 2000
@@ -244,6 +244,7 @@
 {
 	struct input_handle *handle = dev->handle;
 	struct input_dev **devptr = &input_dev;
+	struct input_handle *dnext;
 
 /*
  * Kill any pending repeat timers.
@@ -256,9 +257,10 @@
  */
 
 	while (handle) {
+		dnext = handle->dnext;
 		input_unlink_handle(handle);
 		handle->handler->disconnect(handle);
-		handle = handle->dnext;
+		handle = dnext;
 	}
 
 /*
@@ -309,15 +311,17 @@
 {
 	struct input_handler **handlerptr = &input_handler;
 	struct input_handle *handle = handler->handle;
+	struct input_handle *hnext;
 
 /*
  * Tell the handler to disconnect from all devices it keeps open.
  */
 
 	while (handle) {
+		hnext = handle->hnext;
 		input_unlink_handle(handle);
 		handler->disconnect(handle);
-		handle = handle->hnext;
+		handle = hnext;
 	}
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/ov511.c linux/drivers/usb/ov511.c
--- v2.3.99-pre8/linux/drivers/usb/ov511.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/ov511.c	Sat May 20 10:37:04 2000
@@ -6,7 +6,7 @@
  * Color fixes by by Orion Sky Lawlor, olawlor@acm.org, 2/26/2000
  * Snapshot code by Kevin Moore
  * OV7620 fixes by Charl P. Botha <cpbotha@ieee.org>
- * Changes by Claudio Matsuoka, claudio@conectiva.com, 3/26/2000
+ * Changes by Claudio Matsuoka <claudio@conectiva.com>
  * 
  * Based on the Linux CPiA driver written by Peter Pregler,
  * Scott J. Bertin and Johannes Erdfelt.
@@ -30,7 +30,7 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-static const char version[] = "1.13";
+static const char version[] = "1.14";
 
 #define __NO_VERSION__
 
@@ -64,6 +64,9 @@
 #define DEFAULT_WIDTH 640
 #define DEFAULT_HEIGHT 480
 
+#define GET_SEGSIZE(p) ((p) == VIDEO_PALETTE_RGB24 ? 384 : 256)
+#define GET_DEPTH(p) ((p) == VIDEO_PALETTE_RGB24 ? 24 : 8)
+
 /* PARAMETER VARIABLES: */
 static int autoadjust = 1;    /* CCD dynamically changes exposure, etc... */
 
@@ -90,9 +93,13 @@
 static int i2c_detect_tries = 5;
 
 /* For legal values, see the OV7610/7620 specs under register Common F,
-   upper nybble  (set to 0-F) */
+ * upper nybble  (set to 0-F) */
 static int aperture = -1;
 
+/* Force image to be read in RGB instead of BGR. This option allow
+ * programs that expect RGB data (e.g. gqcam) to work with this driver. */
+static int force_rgb = 0;
+
 MODULE_PARM(autoadjust, "i");
 MODULE_PARM(debug, "i");
 MODULE_PARM(fix_rgb_offset, "i");
@@ -100,8 +107,9 @@
 MODULE_PARM(sensor, "i");
 MODULE_PARM(i2c_detect_tries, "i");
 MODULE_PARM(aperture, "i");
+MODULE_PARM(force_rgb, "i");
 
-MODULE_AUTHOR("Mark McClelland (and others)");
+MODULE_AUTHOR("Mark McClelland <mmcclelland@delphi.com> & Bret Wallach & Orion Sky Lawlor <olawlor@acm.org> & Kevin Moore & Charl P. Botha <cpbotha@ieee.org> & Claudio Matsuoka <claudio@conectiva.com>");
 MODULE_DESCRIPTION("OV511 USB Camera Driver");
 
 char kernel_version[] = UTS_RELEASE;
@@ -126,6 +134,26 @@
 	{  -1, NULL }
 };
 
+static struct palette_list plist[] = {
+	{ VIDEO_PALETTE_GREY,	"GREY" },
+	{ VIDEO_PALETTE_HI240,  "HI240" },
+	{ VIDEO_PALETTE_RGB565, "RGB565" },
+	{ VIDEO_PALETTE_RGB24,	"RGB24" },
+	{ VIDEO_PALETTE_RGB32,	"RGB32" },
+	{ VIDEO_PALETTE_RGB555, "RGB555" },
+	{ VIDEO_PALETTE_YUV422, "YUV422" },
+	{ VIDEO_PALETTE_YUYV,   "YUYV" },
+	{ VIDEO_PALETTE_UYVY,   "UYVY" },
+	{ VIDEO_PALETTE_YUV420, "YUV420" },
+	{ VIDEO_PALETTE_YUV411, "YUV411" },
+	{ VIDEO_PALETTE_RAW,    "RAW" },
+	{ VIDEO_PALETTE_YUV422P,"YUV422P" },
+	{ VIDEO_PALETTE_YUV411P,"YUV411P" },
+	{ VIDEO_PALETTE_YUV420P,"YUV420P" },
+	{ VIDEO_PALETTE_YUV410P,"YUV410P" },
+	{ -1, NULL }
+};
+
 /**********************************************************************
  *
  * Memory management
@@ -236,7 +264,8 @@
  **********************************************************************/
 
 #ifdef CONFIG_PROC_FS
-static struct proc_dir_entry *ov511_proc_root = NULL;
+static struct proc_dir_entry *ov511_proc_entry = NULL;
+static struct proc_dir_entry *video_proc_entry = NULL;
 
 #define YES_NO(x) ((x) ? "yes" : "no")
 
@@ -244,7 +273,7 @@
                           int count, int *eof, void *data)
 {
 	char *out = page;
-	int i, len;
+	int i, j, len;
 	struct usb_ov511 *ov511 = data;
 
 	/* IMPORTANT: This output MUST be kept under PAGE_SIZE
@@ -259,6 +288,10 @@
 	out += sprintf (out, "subcapture      : %s\n", YES_NO (ov511->sub_flag));
 	out += sprintf (out, "sub_size        : %d %d %d %d\n",
 		ov511->subx, ov511->suby, ov511->subw, ov511->subh);
+	out += sprintf (out, "data_format     : %s\n", force_rgb ? "RGB" : "BGR");
+	out += sprintf (out, "brightness      : %d\n", ov511->brightness >> 8);
+	out += sprintf (out, "colour          : %d\n", ov511->colour >> 8);
+	out += sprintf (out, "contrast        : %d\n", ov511->contrast >> 8);
 	out += sprintf (out, "num_frames      : %d\n", OV511_NUMFRAMES);
 	for (i = 0; i < OV511_NUMFRAMES; i++) {
 		out += sprintf (out, "frame           : %d\n", i);
@@ -266,27 +299,40 @@
 			ov511->frame[i].depth);
 		out += sprintf (out, "  size          : %d %d\n",
 			ov511->frame[i].width, ov511->frame[i].height);
+#if 0
 		out += sprintf (out, "  hdr_size      : %d %d\n",
 			ov511->frame[i].hdrwidth, ov511->frame[i].hdrheight);
-		out += sprintf (out, "  format        : %d\n",
-			ov511->frame[i].format);
+#endif
+		out += sprintf (out, "  format        : ");
+		for (j = 0; plist[j].num >= 0; j++) {
+			if (plist[j].num == ov511->frame[i].format) {
+				out += sprintf (out, "%s\n", plist[j].name);
+				break;
+			}
+		}
+		if (plist[j].num < 0)
+			out += sprintf (out, "unknown\n");
 		out += sprintf (out, "  segsize       : %d\n",
 			ov511->frame[i].segsize);
+		out += sprintf (out, "  data_buffer   : 0x%p\n",
+			ov511->frame[i].data);
 #if 0
-		out += sprintf (out, "  curline       : %d\n",
-			ov511->frame[i].curline);
-		out += sprintf (out, "  segment       : %d\n",
-			ov511->frame[i].segment);
-		out += sprintf (out, "  scanlength    : %ld\n",
-			ov511->frame[i].scanlength);
 		out += sprintf (out, "  bytesread     : %ld\n",
 			ov511->frame[i].bytes_read);
 #endif
 	}
 	out += sprintf (out, "snap_enabled    : %s\n", YES_NO (ov511->snap_enabled));
-	out += sprintf (out, "bridge          : %d\n", ov511->bridge);
-	out += sprintf (out, "sensor          : %d\n", ov511->sensor);
+	out += sprintf (out, "bridge          : %s\n",
+		ov511->bridge == BRG_OV511 ? "OV511" :
+		ov511->bridge == BRG_OV511PLUS ? "OV511+" :
+		"unknown");
+	out += sprintf (out, "sensor          : %s\n",
+		ov511->sensor == SEN_OV7610 ? "OV7610" :
+		ov511->sensor == SEN_OV7620 ? "OV7620" :
+		ov511->sensor == SEN_OV7620AE ? "OV7620AE" :
+		"unknown");
 	out += sprintf (out, "packet_size     : %d\n", ov511->packet_size);
+	out += sprintf (out, "framebuffer     : 0x%p\n", ov511->fbuf);
 	
 	len = out - page;
 	len -= off;
@@ -303,130 +349,7 @@
 static int ov511_write_proc(struct file *file, const char *buffer,
                            unsigned long count, void *data)
 {
-	int retval = -EINVAL;
-
-#if 0
-	/* struct cam_data *cam = data; */
-	struct usb_ov511 new_params;
-	int size = count;
-	int find_colon;
-	unsigned long val;
-	u32 command_flags = 0;
-	u8 new_mains;
-	
-	if (down_interruptible(&cam->param_lock))
-		return -ERESTARTSYS;
-	
-	/*
-	 * Skip over leading whitespace
-	 */
-	while (count && isspace(*buffer)) {
-		--count;
-		++buffer;
-	}
-	
-	
-#define MATCH(x) \
-	({ \
-		int _len = strlen(x), _ret, _colon_found; \
-		_ret = (_len <= count && strncmp(buffer, x, _len) == 0); \
-		if (_ret) { \
-			buffer += _len; \
-			count -= _len; \
-			if (find_colon) { \
-				_colon_found = 0; \
-				while (count && (*buffer == ' ' || *buffer == '\t' || \
-				       (!_colon_found && *buffer == ':'))) { \
-					if (*buffer == ':')  \
-						_colon_found = 1; \
-					--count; \
-					++buffer; \
-				} \
-				if (!count || !_colon_found) \
-					retval = -EINVAL; \
-				find_colon = 0; \
-			} \
-		} \
-		_ret; \
-	})
-
-#define VALUE \
-	({ \
-		char *_p; \
-		unsigned long int _ret; \
-		_ret = simple_strtoul(buffer, &_p, 0); \
-		if (_p == buffer) \
-			retval = -EINVAL; \
-		else { \
-			count -= _p - buffer; \
-			buffer = _p; \
-		} \
-		_ret; \
-	})
-
-
-	retval = 0;
-	while (count && !retval) {
-		find_colon = 1;
-
-		if (MATCH("")) {
-			if (!retval)
-				val = VALUE;
-
-			if (!retval) {
-				if (val <= 0xff)
-					/* ... = val */ ;
-				else
-					retval = -EINVAL;
-			}
-		} else {
-			DBG("No match found\n");
-			retval = -EINVAL;
-		}
-
-		if (!retval) {
-			while (count && isspace(*buffer) && *buffer != '\n') {
-				--count;
-				++buffer;
-			}
-			if (count) {
-				if (*buffer != '\n' && *buffer != ';')
-					retval = -EINVAL;
-				else {
-					--count;
-					++buffer;
-				}
-			}
-		}
-	}
-
-#undef MATCH	
-#undef FIRMWARE_VERSION
-#undef VALUE
-#undef FIND_VALUE
-#undef FIND_END
-	if (!retval) {
-		if (command_flags & COMMAND_SETCOLOURPARAMS) {
-			/* Adjust cam->vp to reflect these changes */
-			cam->vp.brightness =
-				new_params.colourParams.brightness*65535/100;
-			cam->vp.contrast =
-				new_params.colourParams.contrast*65535/100;
-			cam->vp.colour =
-				new_params.colourParams.saturation*65535/100;
-		}
-		
-		memcpy(&cam->params, &new_params, sizeof(struct cam_params));
-		cam->mainsFreq = new_mains;
-		cam->cmd_queue |= command_flags;
-		retval = size;
-	} else
-		PDEBUG(3, "error: %d\n", retval);
-	
-	up(&cam->param_lock);
-#endif
-	
-	return retval;
+	return -EINVAL;
 }
 
 static void create_proc_ov511_cam (struct usb_ov511 *ov511)
@@ -434,14 +357,15 @@
 	char name[7];
 	struct proc_dir_entry *ent;
 	
-	PDEBUG (4, "***************");
-	if (!ov511_proc_root || !ov511)
+	PDEBUG (4, "creating /proc/video/ov511/videoX entry");
+	if (!ov511_proc_entry || !ov511)
 		return;
 
 	sprintf(name, "video%d", ov511->vdev.minor);
-	PDEBUG (4, "==== name: %s", name);
+	PDEBUG (4, "creating %s", name);
 	
-	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_root);
+	ent = create_proc_entry(name, S_IFREG|S_IRUGO|S_IWUSR, ov511_proc_entry);
+
 	if (!ent)
 		return;
 
@@ -460,26 +384,44 @@
 		return;
 	
 	sprintf(name, "video%d", ov511->vdev.minor);
-	PDEBUG (4, "==== name: %s", name);
-#if 0
-	remove_proc_entry(name, ov511_proc_root);
+	PDEBUG (4, "destroying %s", name);
+	remove_proc_entry(name, ov511_proc_entry);
 	ov511->proc_entry = NULL;
-#endif
 }
 
 static void proc_ov511_create(void)
 {
-	ov511_proc_root = create_proc_entry("ov511", S_IFDIR, 0);
+	struct proc_dir_entry *p = NULL;
+
+	/* No current standard here. Alan prefers /proc/video/ as it keeps
+	 * /proc "less cluttered than /proc/randomcardifoundintheshed/"
+	 * -claudio
+	 */
+	PDEBUG (3, "creating /proc/video");
+	video_proc_entry = proc_mkdir("video", p);
+	if (!video_proc_entry) {
+		if (!p) {
+			err("Unable to initialise /proc/video\n");
+			return;
+		} else {	/* FIXME - this doesn't work */
+			PDEBUG (3, "/proc/video already exists");
+			video_proc_entry = p;
+		}
+	}
 
-	if (ov511_proc_root)
-		ov511_proc_root->owner = THIS_MODULE;
+	ov511_proc_entry = create_proc_entry("ov511", S_IFDIR, video_proc_entry);
+
+	if (ov511_proc_entry)
+		ov511_proc_entry->owner = THIS_MODULE;
 	else
-		printk("Unable to initialise /proc/ov511\n");	/***********/
+		err("Unable to initialise /proc/video/ov511\n");
 }
 
 static void proc_ov511_destroy(void)
 {
-	remove_proc_entry("ov511", 0);
+	PDEBUG (3, "removing /proc/video/ov511");
+	remove_proc_entry("ov511", video_proc_entry);
+	remove_proc_entry("video", NULL);
 }
 #endif /* CONFIG_PROC_FS */
 
@@ -510,7 +452,6 @@
 	return rc;
 }
 
-
 /* returns: negative is error, pos or zero is data */
 static int ov511_reg_read(struct usb_device *dev, unsigned char reg)
 {
@@ -533,7 +474,6 @@
 	}
 }
 
-
 static int ov511_i2c_write(struct usb_device *dev,
 			   unsigned char reg,
 			   unsigned char value)
@@ -580,7 +520,6 @@
 	return rc;
 }
 
-
 /* returns: negative is error, pos or zero is data */
 static int ov511_i2c_read(struct usb_device *dev, unsigned char reg)
 {
@@ -653,7 +592,6 @@
 	return rc;
 }
 
-
 static int ov511_write_regvals(struct usb_device *dev,
 			       struct ov511_regvals * pRegvals)
 {
@@ -682,9 +620,8 @@
 	return rc;
 }
 
-
-#if 0
-static void ov511_dump_i2c_range( struct usb_device *dev, int reg1, int regn)
+#ifdef OV511_DEBUG 
+static void ov511_dump_i2c_range(struct usb_device *dev, int reg1, int regn)
 {
 	int i;
 	int rc;
@@ -694,15 +631,13 @@
 	}
 }
 
-
-static void ov511_dump_i2c_regs( struct usb_device *dev)
+static void ov511_dump_i2c_regs(struct usb_device *dev)
 {
 	PDEBUG(3, "I2C REGS");
 	ov511_dump_i2c_range(dev, 0x00, 0x38);
 }
 
-
-static void ov511_dump_reg_range( struct usb_device *dev, int reg1, int regn)
+static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn)
 {
 	int i;
 	int rc;
@@ -712,8 +647,8 @@
 	}
 }
 
-
-static void ov511_dump_regs( struct usb_device *dev)
+#if 0
+static void ov511_dump_regs(struct usb_device *dev)
 {
 	PDEBUG(1, "CAMERA INTERFACE REGS");
 	ov511_dump_reg_range(dev, 0x10, 0x1f);
@@ -736,7 +671,7 @@
 
 }
 #endif
-
+#endif
 
 static int ov511_reset(struct usb_device *dev, unsigned char reset_type)
 {
@@ -752,24 +687,21 @@
 	return rc;
 }
 
-
 /* Temporarily stops OV511 from functioning. Must do this before changing
  * registers while the camera is streaming */
 static inline int ov511_stop(struct usb_device *dev)
 {
-	PDEBUG(4, "ov511_stop()");
+	PDEBUG(4, "stopping");
 	return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));
 }
 
-
 /* Restarts OV511 after ov511_stop() is called */
 static inline int ov511_restart(struct usb_device *dev)
 {
-	PDEBUG(4, "ov511_restart()");
+	PDEBUG(4, "restarting");
 	return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));
 }
 
-
 static int ov511_set_packet_size(struct usb_ov511 *ov511, int size)
 {
 	int alt, mult;
@@ -844,9 +776,16 @@
 	if (ov511_stop(dev) < 0)
 		return -EIO;
 
+	ov511->contrast = p->contrast;
+	ov511->brightness = p->brightness;
+	ov511->colour = p->colour;
+	ov511->hue = p->hue;
+	ov511->whiteness = p->whiteness;
+
 	if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)
 		return -EIO;
 #if 0
+	/* disable auto adjust mode */
 	if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)
 		return -EIO;
 #endif
@@ -880,7 +819,6 @@
 	return 0;
 }
 
-
 static inline int
 ov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p)
 {
@@ -903,12 +841,10 @@
 
 	p->hue = 0x8000;
 	p->whiteness = 105 << 8;
-#if 0
-	p->depth = 3;  /* Don't know if this is right */
-#else
-	p->depth = 24;
-#endif
-	p->palette = VIDEO_PALETTE_RGB24;
+
+	/* Can we get these from frame[0]? -claudio? */
+	p->depth = ov511->frame[0].depth;
+	p->palette = ov511->frame[0].format;
 
 	if (ov511_restart(dev) < 0)
 		return -EIO;
@@ -916,6 +852,22 @@
 	return 0;
 }
 
+/* FIXME: add 176x144, 160x140 */
+static struct mode_list mlist[] = {
+	{ 640, 480, VIDEO_PALETTE_GREY, 0x4f, 0x3d, 0x00, 0x00,
+	  0x4f, 0x3d, 0x00, 0x00, 0x04, 0x03, 0x24, 0x04, 0x9e },
+	{ 640, 480, VIDEO_PALETTE_RGB24,0x4f, 0x3d, 0x00, 0x00,
+	  0x4f, 0x3d, 0x00, 0x00, 0x06, 0x03, 0x24, 0x04, 0x9e },
+	{ 320, 240, VIDEO_PALETTE_GREY, 0x27, 0x1f, 0x00, 0x00,
+	  0x27, 0x1f, 0x00, 0x00, 0x01, 0x03, 0x04, 0x24, 0x1e },
+	{ 320, 240, VIDEO_PALETTE_RGB24,0x27, 0x1f, 0x00, 0x00,
+	  0x27, 0x1f, 0x00, 0x00, 0x01, 0x03, 0x04, 0x24, 0x1e },
+	{ 352, 288, VIDEO_PALETTE_GREY, 0x2b, 0x25, 0x00, 0x00,
+	  0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
+	{ 352, 288, VIDEO_PALETTE_RGB24,0x2b, 0x25, 0x00, 0x00,
+	  0x2b, 0x25, 0x00, 0x00, 0x01, 0x03, 0x04, 0x04, 0x1e },
+	{ 0, 0 }
+};
 
 static int
 ov511_mode_init_regs(struct usb_ov511 *ov511,
@@ -925,6 +877,7 @@
 	struct usb_device *dev = ov511->dev;
 	int hwsbase = 0;
 	int hwebase = 0;
+	int i;
 
 	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",
 	       width, height, mode, sub_flag);
@@ -975,6 +928,9 @@
 		break;
 	}
 
+#if 0
+	/* FIXME: subwindow support is currently broken! 
+	 */
 	if (width == 640 && height == 480) {
 		if (sub_flag) {
 			/* horizontal window start */
@@ -1018,41 +974,51 @@
 			}
 		}
 
-		ov511_reg_write(dev, 0x14, 0x00);
-		ov511_reg_write(dev, 0x15, 0x00);
+		ov511_reg_write(dev, 0x14, 0x00);	/* Pixel divisor */
+		ov511_reg_write(dev, 0x15, 0x00);	/* Line divisor */
 
 		/* FIXME?? Shouldn't below be true only for YUV420? */
-		ov511_reg_write(dev, 0x18, 0x03);
+		ov511_reg_write(dev, 0x18, 0x03);	/* YUV420/422, YFIR */
 
-		ov511_i2c_write(dev, 0x12, 0x24);
-		ov511_i2c_write(dev, 0x14, 0x04);
+		ov511_i2c_write(dev, 0x12, 0x24);	/* Common A */
+		ov511_i2c_write(dev, 0x14, 0x04);	/* Common C */
 
 		/* 7620 doesn't have register 0x35, so play it safe */
 		if (ov511->sensor != SEN_OV7620)
 			ov511_i2c_write(dev, 0x35, 0x9e);
-	} else if (width == 320 && height == 240) {
-		ov511_reg_write(dev, 0x12, 0x27);
-		ov511_reg_write(dev, 0x13, 0x1f);
-		ov511_reg_write(dev, 0x14, 0x00);
-		ov511_reg_write(dev, 0x15, 0x00);
-		ov511_reg_write(dev, 0x18, 0x03);
+#endif
+
+	for (i = 0; mlist[i].width; i++) {
+		if (width != mlist[i].width ||
+		    height != mlist[i].height ||
+		    mode != mlist[i].mode)
+			continue;
+
+		ov511_reg_write(dev, 0x12, mlist[i].pxcnt);
+		ov511_reg_write(dev, 0x13, mlist[i].lncnt);
+		ov511_reg_write(dev, 0x14, mlist[i].pxdv);
+		ov511_reg_write(dev, 0x15, mlist[i].lndv);
+		ov511_reg_write(dev, 0x18, mlist[i].m420);
 
 		/* Snapshot additions */
-		ov511_reg_write(dev, 0x1a, 0x27);
-		ov511_reg_write(dev, 0x1b, 0x1f);
-                ov511_reg_write(dev, 0x1c, 0x00);
-                ov511_reg_write(dev, 0x1d, 0x00);
+		ov511_reg_write(dev, 0x1a, mlist[i].s_pxcnt);
+		ov511_reg_write(dev, 0x1b, mlist[i].s_lncnt);
+                ov511_reg_write(dev, 0x1c, mlist[i].s_pxdv);
+                ov511_reg_write(dev, 0x1d, mlist[i].s_lndv);
 
-		if (mode == VIDEO_PALETTE_GREY) {
-		  ov511_i2c_write(dev, 0x11, 1); /* check */
-		} else {
-		  ov511_i2c_write(dev, 0x11, 1); /* check */
-		}
+		ov511_i2c_write(dev, 0x11, mlist[i].clock); /* check */
 
-		ov511_i2c_write(dev, 0x12, 0x04);
-		ov511_i2c_write(dev, 0x14, 0x24);
-		ov511_i2c_write(dev, 0x35, 0x1e);
-	} else {
+		ov511_i2c_write(dev, 0x12, mlist[i].common_A);
+		ov511_i2c_write(dev, 0x14, mlist[i].common_C);
+
+		/* 7620 doesn't have register 0x35, so play it safe */
+		if (ov511->sensor != SEN_OV7620)
+			ov511_i2c_write(dev, 0x35, mlist[i].common_L);
+
+		break;
+	}
+
+	if (mlist[i].width == 0) {
 		err("Unknown mode (%d, %d): %d", width, height, mode);
 		rc = -EINVAL;
 	}
@@ -1060,10 +1026,14 @@
 	if (ov511_restart(ov511->dev) < 0)
 		return -EIO;
 
+#ifdef OV511_DEBUG
+	if (debug >= 5)
+		ov511_dump_i2c_regs(dev);
+#endif
+
 	return rc;
 }
 
-
 /**********************************************************************
  *
  * Color correction functions
@@ -1093,32 +1063,38 @@
 ov511_move_420_block(int yTL, int yTR, int yBL, int yBR, int u, int v, 
 	int rowPixels, unsigned char * rgb)
 {
-	const double brightness = 1.0; // 0->black; 1->full scale
-	const double saturation = 1.0; // 0->greyscale; 1->full color
+	const double brightness = 1.0; /* 0->black; 1->full scale */
+	const double saturation = 1.0; /* 0->greyscale; 1->full color */
 	const double fixScale = brightness * 256 * 256;
 	const int rvScale = (int)(1.402 * saturation * fixScale);
 	const int guScale = (int)(-0.344136 * saturation * fixScale);
 	const int gvScale = (int)(-0.714136 * saturation * fixScale);
 	const int buScale = (int)(1.772 * saturation * fixScale);
 	const int yScale = (int)(fixScale);	
+	int r, g, b;
+
+	g = guScale * u + gvScale * v;
+	if (force_rgb) {
+		r = buScale * u;
+		b = rvScale * v;
+	} else {
+		r = rvScale * v;
+		b = buScale * u;
+	}
 
-	int r = rvScale * v;
-	int g = guScale * u + gvScale * v;
-	int b = buScale * u;
 	yTL *= yScale; yTR *= yScale;
 	yBL *= yScale; yBR *= yScale;
 
-	//Write out top two pixels
+	/* Write out top two pixels */
 	rgb[0] = LIMIT(b+yTL); rgb[1] = LIMIT(g+yTL); rgb[2] = LIMIT(r+yTL);
 	rgb[3] = LIMIT(b+yTR); rgb[4] = LIMIT(g+yTR); rgb[5] = LIMIT(r+yTR);
 
-	//Skip down to next line to write out bottom two pixels
+	/* Skip down to next line to write out bottom two pixels */
 	rgb += 3 * rowPixels;
 	rgb[0] = LIMIT(b+yBL); rgb[1] = LIMIT(g+yBL); rgb[2] = LIMIT(r+yBL);
 	rgb[3] = LIMIT(b+yBR); rgb[4] = LIMIT(g+yBR); rgb[5] = LIMIT(r+yBR);
 }
 
-
 /*
  * For a 640x480 YUV4:2:0 images, data shows up in 1200 384 byte segments.
  * The first 64 bytes of each segment are U, the next 64 are V.  The U and
@@ -1155,13 +1131,13 @@
 #undef OV511_DUMPPIX
 
 static void
-ov511_parse_data_rgb24(unsigned char * pIn0, unsigned char * pOut0,
+ov511_parse_data_rgb24(unsigned char *pIn0, unsigned char *pOut0,
 		       int iOutY, int iOutUV, int iHalf, int iWidth)    			    
 {
 #ifndef OV511_DUMPPIX
 	int k, l, m;
-	unsigned char * pIn;
-	unsigned char * pOut, * pOut1;
+	unsigned char *pIn;
+	unsigned char *pOut, *pOut1;
 
 	/* Just copy the Y's if in the first stripe */
 	if (!iHalf) {
@@ -1232,7 +1208,6 @@
 			pOut += 8 * 3;
 		}
 	}
-
 #else
 	/* Just dump pix data straight out for debug */
 	int i, j;
@@ -1249,7 +1224,6 @@
 #endif
 }
 
-
 /*
  * For 640x480 RAW BW images, data shows up in 1200 256 byte segments.
  * The segments represent 4 squares of 8x8 pixels as follows:
@@ -1257,11 +1231,11 @@
  *      0  1 ...  7    64  65 ...  71   ...  192 193 ... 199
  *      8  9 ... 15    72  73 ...  79        200 201 ... 207
  *           ...              ...                    ...
- *     56 57 ... 63   120 121     127        248 249 ... 255
+ *     56 57 ... 63   120 121 ... 127        248 249 ... 255
  *
  */ 
 static void
-ov511_parse_data_grey(unsigned char * pIn0, unsigned char * pOut0,
+ov511_parse_data_grey(unsigned char *pIn0, unsigned char *pOut0,
 		      int iOutY, int iWidth)		    
 {
 	int k, l, m;
@@ -1276,13 +1250,12 @@
 			for (m = 0; m < 8; m++) {
 				*pOut1++ = *pIn++;
 			}
-			pOut1 += iWidth - 8;
+			pOut1 += iWidth - WDIV;
 		}
 		pOut += 8;
 	}
 }
 
-
 /*
  * fixFrameRGBoffset--
  * My camera seems to return the red channel about 1 pixel
@@ -1317,7 +1290,6 @@
 	}
 }
 
-
 /**********************************************************************
  *
  * OV511 data transfer, IRQ handler
@@ -1488,7 +1460,6 @@
 	return totlen;
 }
 
-
 static void ov511_isoc_irq(struct urb *urb)
 {
 	int len;
@@ -1520,7 +1491,6 @@
 	return;
 }
 
-
 static int ov511_init_isoc(struct usb_ov511 *ov511)
 {
 	urb_t *urb;
@@ -1595,7 +1565,6 @@
 	return 0;
 }
 
-
 static void ov511_stop_isoc(struct usb_ov511 *ov511)
 {
 	if (!ov511->streaming || !ov511->dev)
@@ -1622,7 +1591,6 @@
 	}
 }
 
-
 static int ov511_new_frame(struct usb_ov511 *ov511, int framenum)
 {
 	struct ov511_frame *frame;
@@ -1658,25 +1626,17 @@
 	/* Make sure it's not too big */
 	if (width > DEFAULT_WIDTH)
 		width = DEFAULT_WIDTH;
-#if 0
-	width = (width / 8) * 8;	/* Multiple of 8 */
-#endif
-	width &= ~7L;
+
+	width &= ~7L;			/* Multiple of 8 */
 
 	if (height > DEFAULT_HEIGHT)
 		height = DEFAULT_HEIGHT;
-#if 0
-	height = (height / 4) * 4;	/* Multiple of 4 */
-#endif
-	width &= ~3L;
 
-//	/* We want a fresh frame every 30 we get */
-//	ov511->compress = (ov511->compress + 1) % 30;
+	width &= ~3L;			/* Multiple of 4 */
 
 	return 0;
 }
 
-
 /****************************************************************************
  *
  * V4L API
@@ -1687,43 +1647,45 @@
 {
 	int err = -EBUSY;
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+	int i;
 
-	PDEBUG(4, "ov511_open");
+	PDEBUG(4, "opening");
 
 	down(&ov511->lock);
-	if (ov511->user)
-		goto out_unlock;
 
-	ov511->frame[0].grabstate = FRAME_UNUSED;
-	ov511->frame[1].grabstate = FRAME_UNUSED;
+	if (ov511->user) {
+		up(&ov511->lock);
+		return -EBUSY;
+	}
 
 	err = -ENOMEM;
 
 	/* Allocate memory for the frame buffers */
-	ov511->fbuf = rvmalloc(2 * MAX_DATA_SIZE);
+	ov511->fbuf = rvmalloc(OV511_NUMFRAMES * MAX_DATA_SIZE);
 	if (!ov511->fbuf)
-		goto open_err_ret;
+		return err;
 
-	ov511->frame[0].data = ov511->fbuf;
-	ov511->frame[1].data = ov511->fbuf + MAX_DATA_SIZE;
 	ov511->sub_flag = 0;
 
-	PDEBUG(4, "frame [0] @ %p", ov511->frame[0].data);
-	PDEBUG(4, "frame [1] @ %p", ov511->frame[1].data);
-
-	ov511->sbuf[0].data = kmalloc(FRAMES_PER_DESC * MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
-	if (!ov511->sbuf[0].data)
-		goto open_err_on0;
-	ov511->sbuf[1].data = kmalloc(FRAMES_PER_DESC * MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
-	if (!ov511->sbuf[1].data)
-		goto open_err_on1;
-		
-	PDEBUG(4, "sbuf[0] @ %p", ov511->sbuf[0].data);
-	PDEBUG(4, "sbuf[1] @ %p", ov511->sbuf[1].data);
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		ov511->frame[i].grabstate = FRAME_UNUSED;
+		ov511->frame[i].data = ov511->fbuf + i * MAX_DATA_SIZE;
+		PDEBUG(4, "frame [%d] @ %p", i, ov511->frame[0].data);
+
+		ov511->sbuf[i].data = kmalloc(FRAMES_PER_DESC *
+			MAX_FRAME_SIZE_PER_DESC, GFP_KERNEL);
+		if (!ov511->sbuf[i].data) {
+open_free_ret:
+			while (--i) kfree(ov511->sbuf[i].data);
+			rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE);
+			return err;
+		}	
+		PDEBUG(4, "sbuf[%d] @ %p", i, ov511->sbuf[i].data);
+	}
 
 	err = ov511_init_isoc(ov511);
 	if (err)
-		goto open_err_on2;
+		goto open_free_ret;
 
 	ov511->user++;
 	up(&ov511->lock);
@@ -1731,24 +1693,12 @@
 	MOD_INC_USE_COUNT;
 
 	return 0;
-
-open_err_on2:
-	kfree (ov511->sbuf[1].data);
-open_err_on1:
-	kfree (ov511->sbuf[0].data);
-open_err_on0:
-	rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE);
-open_err_ret:
-	return err;
-out_unlock:
-	up(&ov511->lock);
-	return err;
 }
 
-
 static void ov511_close(struct video_device *dev)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
+	int i;
 
 	PDEBUG(4, "ov511_close");
 	
@@ -1759,10 +1709,9 @@
 
 	ov511_stop_isoc(ov511);
 
-	rvfree(ov511->fbuf, 2 * MAX_DATA_SIZE);
-
-	kfree(ov511->sbuf[1].data);
-	kfree(ov511->sbuf[0].data);
+	rvfree(ov511->fbuf, OV511_NUMFRAMES * MAX_DATA_SIZE);
+	for (i = 0; i < OV511_NUMFRAMES; i++)
+		kfree(ov511->sbuf[i].data);
 
 	up(&ov511->lock);
 
@@ -1772,7 +1721,6 @@
 	}
 }
 
-
 static int ov511_init_done(struct video_device *dev)
 {
 #ifdef CONFIG_PROC_FS
@@ -1782,13 +1730,11 @@
 	return 0;
 }
 
-
 static long ov511_write(struct video_device *dev, const char *buf, unsigned long count, int noblock)
 {
 	return -EINVAL;
 }
 
-
 static int ov511_ioctl(struct video_device *vdev, unsigned int cmd, void *arg)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)vdev;
@@ -2097,7 +2043,6 @@
 	return 0;
 }
 
-
 static long ov511_read(struct video_device *dev, char *buf, unsigned long count, int noblock)
 {
 	struct usb_ov511 *ov511 = (struct usb_ov511 *)dev;
@@ -2138,10 +2083,6 @@
 
 	frame = &ov511->frame[frmx];
 
-	/* FIXME */
-	frame->segsize = frame->format == VIDEO_PALETTE_RGB24 ? 384 : 256;
-	frame->depth = frame->format == VIDEO_PALETTE_RGB24 ? 24 : 8;
-
 restart:
 	if (!ov511->dev)
 		return -EIO;
@@ -2165,11 +2106,8 @@
 
 
 	/* Repeat until we get a snapshot frame */
-	if (!ov511->snap_enabled) {
-		PDEBUG (4, "snap disabled");
-	} else {
+	if (ov511->snap_enabled)
 		PDEBUG (4, "Waiting snapshot frame");
-	}
 	if (ov511->snap_enabled && !frame->snapshot) {
 		frame->bytes_read = 0;
 		if (ov511_new_frame(ov511, frmx))
@@ -2178,13 +2116,11 @@
 	}
 
 	/* Clear the snapshot */
-	if (ov511->snap_enabled)
-		PDEBUG (4, "Clear snapshot");
 	if (ov511->snap_enabled && frame->snapshot) {
 		frame->snapshot = 0;
-		ov511_reg_write(ov511->dev, 0x52, 0x01);
-		ov511_reg_write(ov511->dev, 0x52, 0x03);
-		ov511_reg_write(ov511->dev, 0x52, 0x01);
+		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
+		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x03);
+		ov511_reg_write(ov511->dev, OV511_REG_SYSTEM_SNAPSHOT, 0x01);
 	}
 
 	PDEBUG(4, "frmx=%d, bytes_read=%ld, scanlength=%ld", frmx,
@@ -2212,7 +2148,7 @@
 
 		/* Mark it as available to be used again. */
 		ov511->frame[frmx].grabstate = FRAME_UNUSED;
-		if (ov511_new_frame(ov511, frmx ? 0 : 1))
+		if (ov511_new_frame(ov511, !frmx))
 			err("ov511_new_frame returned error");
 	}
 
@@ -2221,7 +2157,6 @@
 	return count;
 }
 
-
 static int ov511_mmap(struct video_device *dev, const char *adr,
 	unsigned long size)
 {
@@ -2229,7 +2164,7 @@
 	unsigned long start = (unsigned long)adr;
 	unsigned long page, pos;
 
-	if (!ov511->dev)
+	if (ov511->dev == NULL)
 		return -EIO;
 
 	PDEBUG(4, "mmap: %ld (%lX) bytes", size, size);
@@ -2238,8 +2173,7 @@
 		return -EINVAL;
 
 	pos = (unsigned long)ov511->fbuf;
-	while (size > 0)
-	{
+	while (size > 0) {
 		page = kvirt_to_pa(pos);
 		if (remap_page_range(start, page, PAGE_SIZE, PAGE_SHARED))
 			return -EAGAIN;
@@ -2254,7 +2188,6 @@
 	return 0;
 }
 
-
 static struct video_device ov511_template = {
 	name:		"OV511 USB Camera",
 	type:		VID_TYPE_CAPTURE,
@@ -2268,7 +2201,6 @@
 	initialize:	ov511_init_done,
 };
 
-
 /****************************************************************************
  *
  * OV511/OV7610 configuration
@@ -2281,68 +2213,70 @@
 	int i, success;
 	int rc;
 
-	static struct ov511_regvals aRegvalsNorm7610[] =
-	{{OV511_I2C_BUS, 0x10, 0xff},
-	 {OV511_I2C_BUS, 0x16, 0x06},
-	 {OV511_I2C_BUS, 0x28, 0x24},
-	 {OV511_I2C_BUS, 0x2b, 0xac},
-	 {OV511_I2C_BUS, 0x05, 0x00},
-	 {OV511_I2C_BUS, 0x06, 0x00},
-	 {OV511_I2C_BUS, 0x12, 0x00},
-	 {OV511_I2C_BUS, 0x38, 0x81},
-	 {OV511_I2C_BUS, 0x28, 0x24}, /* 0c */
-	 {OV511_I2C_BUS, 0x05, 0x00},
-	 {OV511_I2C_BUS, 0x0f, 0x05},
-	 {OV511_I2C_BUS, 0x15, 0x01},
-	 {OV511_I2C_BUS, 0x20, 0x1c},
-	 {OV511_I2C_BUS, 0x23, 0x2a},
-	 {OV511_I2C_BUS, 0x24, 0x10},
-	 {OV511_I2C_BUS, 0x25, 0x8a},
-	 {OV511_I2C_BUS, 0x27, 0xc2},
-	 {OV511_I2C_BUS, 0x29, 0x03}, /* 91 */
-	 {OV511_I2C_BUS, 0x2a, 0x04},
-	 {OV511_I2C_BUS, 0x2c, 0xfe},
-	 {OV511_I2C_BUS, 0x30, 0x71},
-	 {OV511_I2C_BUS, 0x31, 0x60},
-	 {OV511_I2C_BUS, 0x32, 0x26},
-	 {OV511_I2C_BUS, 0x33, 0x20},
-	 {OV511_I2C_BUS, 0x34, 0x48},
-	 {OV511_I2C_BUS, 0x12, 0x24},
-	 {OV511_I2C_BUS, 0x11, 0x01},
-	 {OV511_I2C_BUS, 0x0c, 0x24},
-	 {OV511_I2C_BUS, 0x0d, 0x24},
-	 {OV511_DONE_BUS, 0x0, 0x00},
+	static struct ov511_regvals aRegvalsNorm7610[] = {
+		{ OV511_I2C_BUS, 0x10, 0xff },
+		{ OV511_I2C_BUS, 0x16, 0x06 },
+		{ OV511_I2C_BUS, 0x28, 0x24 },
+		{ OV511_I2C_BUS, 0x2b, 0xac },
+		{ OV511_I2C_BUS, 0x05, 0x00 },
+		{ OV511_I2C_BUS, 0x06, 0x00 },
+		{ OV511_I2C_BUS, 0x12, 0x00 },
+		{ OV511_I2C_BUS, 0x38, 0x81 },
+		{ OV511_I2C_BUS, 0x28, 0x24 }, /* 0c */
+		{ OV511_I2C_BUS, 0x05, 0x00 },
+		{ OV511_I2C_BUS, 0x0f, 0x05 },
+		{ OV511_I2C_BUS, 0x15, 0x01 },
+		{ OV511_I2C_BUS, 0x20, 0x1c },
+		{ OV511_I2C_BUS, 0x23, 0x2a },
+		{ OV511_I2C_BUS, 0x24, 0x10 },
+		{ OV511_I2C_BUS, 0x25, 0x8a },
+		{ OV511_I2C_BUS, 0x27, 0xc2 },
+		{ OV511_I2C_BUS, 0x29, 0x03 }, /* 91 */
+		{ OV511_I2C_BUS, 0x2a, 0x04 },
+		{ OV511_I2C_BUS, 0x2c, 0xfe },
+		{ OV511_I2C_BUS, 0x30, 0x71 },
+		{ OV511_I2C_BUS, 0x31, 0x60 },
+		{ OV511_I2C_BUS, 0x32, 0x26 },
+		{ OV511_I2C_BUS, 0x33, 0x20 },
+		{ OV511_I2C_BUS, 0x34, 0x48 },
+		{ OV511_I2C_BUS, 0x12, 0x24 },
+		{ OV511_I2C_BUS, 0x11, 0x01 },
+		{ OV511_I2C_BUS, 0x0c, 0x24 },
+		{ OV511_I2C_BUS, 0x0d, 0x24 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
 	};
 
-	static struct ov511_regvals aRegvalsNorm7620[] =
-	{{OV511_I2C_BUS, 0x10, 0xff},
-	 {OV511_I2C_BUS, 0x16, 0x06},
-	 {OV511_I2C_BUS, 0x28, 0x24},
-	 {OV511_I2C_BUS, 0x2b, 0xac},
-	 {OV511_I2C_BUS, 0x12, 0x00},
-	 {OV511_I2C_BUS, 0x28, 0x24},
-	 {OV511_I2C_BUS, 0x05, 0x00},
-	 {OV511_I2C_BUS, 0x0f, 0x05},
-	 {OV511_I2C_BUS, 0x15, 0x01},
-	 {OV511_I2C_BUS, 0x23, 0x00},
-	 {OV511_I2C_BUS, 0x24, 0x10},
-	 {OV511_I2C_BUS, 0x25, 0x8a},
-	 {OV511_I2C_BUS, 0x27, 0xe2},
-	 {OV511_I2C_BUS, 0x29, 0x03},
-	 {OV511_I2C_BUS, 0x2a, 0x00},
-	 {OV511_I2C_BUS, 0x2c, 0xfe},
-	 {OV511_I2C_BUS, 0x30, 0x71},
-	 {OV511_I2C_BUS, 0x31, 0x60},
-	 {OV511_I2C_BUS, 0x32, 0x26},
-	 {OV511_I2C_BUS, 0x33, 0x20},
-	 {OV511_I2C_BUS, 0x34, 0x48},
-	 {OV511_I2C_BUS, 0x12, 0x24},
-	 {OV511_I2C_BUS, 0x11, 0x01},
-	 {OV511_I2C_BUS, 0x0c, 0x24},
-	 {OV511_I2C_BUS, 0x0d, 0x24},
-	 {OV511_DONE_BUS, 0x0, 0x00},
+	static struct ov511_regvals aRegvalsNorm7620[] = {
+		{ OV511_I2C_BUS, 0x10, 0xff },
+		{ OV511_I2C_BUS, 0x16, 0x06 },
+		{ OV511_I2C_BUS, 0x28, 0x24 },
+		{ OV511_I2C_BUS, 0x2b, 0xac },
+		{ OV511_I2C_BUS, 0x12, 0x00 },
+		{ OV511_I2C_BUS, 0x28, 0x24 },
+		{ OV511_I2C_BUS, 0x05, 0x00 },
+		{ OV511_I2C_BUS, 0x0f, 0x05 },
+		{ OV511_I2C_BUS, 0x15, 0x01 },
+		{ OV511_I2C_BUS, 0x23, 0x00 },
+		{ OV511_I2C_BUS, 0x24, 0x10 },
+		{ OV511_I2C_BUS, 0x25, 0x8a },
+		{ OV511_I2C_BUS, 0x27, 0xe2 },
+		{ OV511_I2C_BUS, 0x29, 0x03 },
+		{ OV511_I2C_BUS, 0x2a, 0x00 },
+		{ OV511_I2C_BUS, 0x2c, 0xfe },
+		{ OV511_I2C_BUS, 0x30, 0x71 },
+		{ OV511_I2C_BUS, 0x31, 0x60 },
+		{ OV511_I2C_BUS, 0x32, 0x26 },
+		{ OV511_I2C_BUS, 0x33, 0x20 },
+		{ OV511_I2C_BUS, 0x34, 0x48 },
+		{ OV511_I2C_BUS, 0x12, 0x24 },
+		{ OV511_I2C_BUS, 0x11, 0x01 },
+		{ OV511_I2C_BUS, 0x0c, 0x24 },
+		{ OV511_I2C_BUS, 0x0d, 0x24 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
 	};
 
+	PDEBUG (4, "starting configuration");
+
 	if(ov511_reg_write(dev, OV511_REG_I2C_SLAVE_ID_WRITE,
 	                        OV7610_I2C_WRITE_ID) < 0)
 		return -1;
@@ -2385,13 +2319,13 @@
 			err("Error detecting sensor type");
 			return -1;
 		} else if((rc & 3) == 3) {
-			printk("ov511: Sensor is an OV7610\n");
+			info("Sensor is an OV7610");
 			ov511->sensor = SEN_OV7610;
 		} else if((rc & 3) == 1) {
-			printk("ov511: Sensor is an OV7620AE\n");
+			info("Sensor is an OV7620AE");
 			ov511->sensor = SEN_OV7620AE;
 		} else if((rc & 3) == 0) {
-			printk("ov511: Sensor is an OV7620\n");
+			info("Sensor is an OV7620");
 			ov511->sensor = SEN_OV7620;
 		} else {
 			err("Unknown image sensor version: %d", rc & 3);
@@ -2399,13 +2333,15 @@
 		}
 	} else {	/* sensor != 0; user overrode detection */
 		ov511->sensor = sensor;
-		printk("ov511: Sensor set to type %d\n", ov511->sensor);
+		info("Sensor set to type %d", ov511->sensor);
 	}
 
 	if (ov511->sensor == SEN_OV7620) {
+		PDEBUG(4, "Writing 7620 registers");
 		if (ov511_write_regvals(dev, aRegvalsNorm7620))
 			return -1;
 	} else {
+		PDEBUG(4, "Writing 7610 registers");
 		if (ov511_write_regvals(dev, aRegvalsNorm7610))
 			return -1;
 	}
@@ -2438,34 +2374,35 @@
 static int ov511_configure(struct usb_ov511 *ov511)
 {
 	struct usb_device *dev = ov511->dev;
+	int i;
 
-	static struct ov511_regvals aRegvalsInit[] =
-	{{OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x7f},
-	 {OV511_REG_BUS,  OV511_REG_SYSTEM_INIT, 0x01},
-	 {OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x7f},
-	 {OV511_REG_BUS,  OV511_REG_SYSTEM_INIT, 0x01},
-	 {OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x3f},
-	 {OV511_REG_BUS,  OV511_REG_SYSTEM_INIT, 0x01},
-	 {OV511_REG_BUS,  OV511_REG_SYSTEM_RESET, 0x3d},
-	 {OV511_DONE_BUS, 0x0, 0x00},
+	static struct ov511_regvals aRegvalsInit[] = {
+		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
+	 	{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
+	 	{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x7f },
+		{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
+		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3f },
+		{ OV511_REG_BUS, OV511_REG_SYSTEM_INIT, 0x01 },
+		{ OV511_REG_BUS, OV511_REG_SYSTEM_RESET, 0x3d },
+		{ OV511_DONE_BUS, 0x0, 0x00},
 	};
 
-	static struct ov511_regvals aRegvalsNorm511[] =
-	{{OV511_REG_BUS, 0x20, 0x01},
-	 {OV511_REG_BUS, 0x52, 0x02},
-	 {OV511_REG_BUS, 0x52, 0x00},
-	 {OV511_REG_BUS, 0x31, 0x1f}, /* 0f */
-	 {OV511_REG_BUS, 0x70, 0x3f},
-	 {OV511_REG_BUS, 0x71, 0x3f},
-	 {OV511_REG_BUS, 0x72, 0x01},
-	 {OV511_REG_BUS, 0x73, 0x01},
-	 {OV511_REG_BUS, 0x74, 0x01},
-	 {OV511_REG_BUS, 0x75, 0x01},
-	 {OV511_REG_BUS, 0x76, 0x01},
-	 {OV511_REG_BUS, 0x77, 0x01},
-	 {OV511_REG_BUS, 0x78, 0x06},
-	 {OV511_REG_BUS, 0x79, 0x03},
-	 {OV511_DONE_BUS, 0x0, 0x00},
+	static struct ov511_regvals aRegvalsNorm511[] = {
+		{ OV511_REG_BUS, OV511_REG_DRAM_ENABLE_FLOW_CONTROL, 0x01 },
+		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x02 },
+		{ OV511_REG_BUS, OV511_REG_SYSTEM_SNAPSHOT, 0x00 },
+		{ OV511_REG_BUS, OV511_REG_FIFO_BITMASK, 0x1f }, /* 0f */
+		{ OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_Y, 0x3f },
+		{ OV511_REG_BUS, OV511_OMNICE_PREDICTION_HORIZ_UV, 0x3f },
+		{ OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_Y, 0x01 },
+		{ OV511_REG_BUS, OV511_OMNICE_PREDICTION_VERT_UV, 0x01 },
+		{ OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_Y, 0x01 },
+		{ OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_HORIZ_UV, 0x01 },
+		{ OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_Y, 0x01 },
+		{ OV511_REG_BUS, OV511_OMNICE_QUANTIZATION_VERT_UV, 0x01 },
+		{ OV511_REG_BUS, OV511_OMNICE_ENABLE, 0x06 },
+		{ OV511_REG_BUS, OV511_OMNICE_LUT_ENABLE, 0x03 },
+		{ OV511_DONE_BUS, 0x0, 0x00 },
 	};
 
 	memcpy(&ov511->vdev, &ov511_template, sizeof(ov511_template));
@@ -2488,16 +2425,15 @@
 
 	/* Set default sizes in case IOCTL (VIDIOCMCAPTURE) is not used
 	 * (using read() instead). */
-	ov511->frame[0].width = DEFAULT_WIDTH;
-	ov511->frame[0].height = DEFAULT_HEIGHT;
-	ov511->frame[0].depth = 24;		/**************/
-	ov511->frame[0].bytes_read = 0;
-	ov511->frame[0].segment = 0;
-	ov511->frame[1].width = DEFAULT_WIDTH;
-	ov511->frame[1].height = DEFAULT_HEIGHT;
-	ov511->frame[1].depth = 24;
-	ov511->frame[1].bytes_read = 0;
-	ov511->frame[1].segment = 0;
+	for (i = 0; i < OV511_NUMFRAMES; i++) {
+		ov511->frame[i].width = DEFAULT_WIDTH;
+		ov511->frame[i].height = DEFAULT_HEIGHT;
+		ov511->frame[i].depth = 24;
+		ov511->frame[i].bytes_read = 0;
+		ov511->frame[i].segment = 0;
+		ov511->frame[i].format = VIDEO_PALETTE_RGB24;
+		ov511->frame[i].segsize = GET_SEGSIZE(ov511->frame[i].format);
+	}
 
 	/* Initialize to DEFAULT_WIDTH, DEFAULT_HEIGHT, YUV4:2:0 */
 
@@ -2588,7 +2524,7 @@
 	PDEBUG (4, "CustomID = %d", ov511->customid);
 	for (i = 0; clist[i].id >= 0; i++) {
 		if (ov511->customid == clist[i].id) {
-			printk ("Camera: %s\n", clist[i].description);
+			info("camera: %s", clist[i].description);
 			ov511->desc = i;
 			break;
 		}
@@ -2606,6 +2542,11 @@
 		err("support for your camera.");
 	}
 
+	/* Workaround for some applications that want data in RGB
+	 * instead of BGR */
+	if (force_rgb)
+		info("data format set to RGB");
+
 	if (!ov511_configure(ov511)) {
 		ov511->user = 0;
 		init_MUTEX(&ov511->lock);	/* to 1 == available */
@@ -2670,7 +2611,6 @@
 	}
 
 #ifdef CONFIG_PROC_FS
-        PDEBUG(3, "destroying /proc/ov511/video%d", ov511->vdev.minor);
         destroy_proc_ov511_cam(ov511);
 #endif
 
@@ -2712,13 +2652,12 @@
 
 static void __exit usb_ov511_exit(void)
 {
+	usb_deregister(&ov511_driver);
+	info("ov511 driver deregistered");
+
 #ifdef CONFIG_PROC_FS
-	PDEBUG(3, "destroying /proc/ov511");
         proc_ov511_destroy();
 #endif 
-
-	usb_deregister(&ov511_driver);
-	info("ov511 driver deregistered");
 }
 
 module_init(usb_ov511_init);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/ov511.h linux/drivers/usb/ov511.h
--- v2.3.99-pre8/linux/drivers/usb/ov511.h	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/ov511.h	Sat May 20 10:37:04 2000
@@ -1,3 +1,4 @@
+
 #ifndef __LINUX_OV511_H
 #define __LINUX_OV511_H
 
@@ -9,7 +10,7 @@
 
 #ifdef OV511_DEBUG
 #  define PDEBUG(level, fmt, args...) \
-if (debug >= level) printk("ov511: [" __PRETTY_FUNCTION__ ":%d] " fmt "\n", __LINE__ , ## args)
+if (debug >= level) info("[" __PRETTY_FUNCTION__ ":%d] " fmt, __LINE__ , ## args)
 #else
 #  define PDEBUG(level, fmt, args...) do {} while(0)
 #endif
@@ -119,48 +120,55 @@
 #define OV511PLUS_ALT_SIZE_961	7
 
 /* OV7610 registers */
-#define OV7610_REG_GAIN          0x00
-#define OV7610_REG_BLUE          0x01
-#define OV7610_REG_RED           0x02
-#define OV7610_REG_SAT           0x03
-#define OV7610_REG_CNT           0x05
-#define OV7610_REG_BRT           0x06
-#define OV7610_REG_BLUE_BIAS     0x0C
-#define OV7610_REG_RED_BIAS      0x0D
-#define OV7610_REG_GAMMA_COEFF   0x0E
-#define OV7610_REG_WB_RANGE      0x0F
-#define OV7610_REG_EXP           0x10
-#define OV7610_REG_CLOCK         0x11
-#define OV7610_REG_COM_A         0x12
-#define OV7610_REG_COM_B         0x13
-#define OV7610_REG_COM_C         0x14
-#define OV7610_REG_COM_D         0x15
-#define OV7610_REG_FIELD_DIVIDE  0x16
-#define OV7610_REG_HWIN_START    0x17
-#define OV7610_REG_HWIN_END      0x18
-#define OV7610_REG_VWIN_START    0x19
-#define OV7610_REG_VWIN_END      0x1A
-#define OV7610_REG_PIXEL_SHIFT   0x1B
-#define OV7610_REG_ID_HIGH       0x1C
-#define OV7610_REG_ID_LOW        0x1D
-#define OV7610_REG_COM_E         0x20
-#define OV7610_REG_YOFFSET       0x21
-#define OV7610_REG_UOFFSET       0x22
-#define OV7610_REG_ECW           0x24
-#define OV7610_REG_ECB           0x25
-#define OV7610_REG_COM_F         0x26
-#define OV7610_REG_COM_G         0x27
-#define OV7610_REG_COM_H         0x28
-#define OV7610_REG_COM_I         0x29
-#define OV7610_REG_FRAMERATE_H   0x2A
-#define OV7610_REG_FRAMERATE_L   0x2B
-#define OV7610_REG_ALC           0x2C
-#define OV7610_REG_COM_J         0x2D
-#define OV7610_REG_VOFFSET       0x2E
-#define OV7610_REG_YGAMMA        0x33
-#define OV7610_REG_BIAS_ADJUST   0x34
-#define OV7610_REG_COM_L         0x35
-#define OV7610_REG_COM_K         0x38
+#define OV7610_REG_GAIN          0x00	/* gain setting (5:0) */
+#define OV7610_REG_BLUE          0x01	/* blue channel balance */
+#define OV7610_REG_RED           0x02	/* red channel balance */
+#define OV7610_REG_SAT           0x03	/* saturation */
+					/* 04 reserved */
+#define OV7610_REG_CNT           0x05	/* Y contrast */
+#define OV7610_REG_BRT           0x06	/* Y brightness */
+					/* 08-0b reserved */
+#define OV7610_REG_BLUE_BIAS     0x0C	/* blue channel bias (5:0) */
+#define OV7610_REG_RED_BIAS      0x0D	/* read channel bias (5:0) */
+#define OV7610_REG_GAMMA_COEFF   0x0E	/* gamma settings */
+#define OV7610_REG_WB_RANGE      0x0F	/* AEC/ALC/S-AWB settings */
+#define OV7610_REG_EXP           0x10	/* manual exposure setting */
+#define OV7610_REG_CLOCK         0x11	/* polarity/clock prescaler */
+#define OV7610_REG_COM_A         0x12	/* misc common regs */
+#define OV7610_REG_COM_B         0x13	/* misc common regs */
+#define OV7610_REG_COM_C         0x14	/* misc common regs */
+#define OV7610_REG_COM_D         0x15	/* misc common regs */
+#define OV7610_REG_FIELD_DIVIDE  0x16	/* field interval/mode settings */
+#define OV7610_REG_HWIN_START    0x17	/* horizontal window start */
+#define OV7610_REG_HWIN_END      0x18	/* horizontal window end */
+#define OV7610_REG_VWIN_START    0x19	/* vertical window start */
+#define OV7610_REG_VWIN_END      0x1A	/* vertical window end */
+#define OV7610_REG_PIXEL_SHIFT   0x1B	/* pixel shift */
+#define OV7610_REG_ID_HIGH       0x1C	/* manufacturer ID MSB */
+#define OV7610_REG_ID_LOW        0x1D	/* manufacturer ID LSB */
+					/* 0e-0f reserved */
+#define OV7610_REG_COM_E         0x20	/* misc common regs */
+#define OV7610_REG_YOFFSET       0x21	/* Y channel offset */
+#define OV7610_REG_UOFFSET       0x22	/* U channel offset */
+					/* 23 reserved */
+#define OV7610_REG_ECW           0x24	/* Exposure white level for AEC */
+#define OV7610_REG_ECB           0x25	/* Exposure black level for AEC */
+#define OV7610_REG_COM_F         0x26	/* misc settings */
+#define OV7610_REG_COM_G         0x27	/* misc settings */
+#define OV7610_REG_COM_H         0x28	/* misc settings */
+#define OV7610_REG_COM_I         0x29	/* misc settings */
+#define OV7610_REG_FRAMERATE_H   0x2A	/* frame rate MSB + misc */
+#define OV7610_REG_FRAMERATE_L   0x2B	/* frame rate LSB */
+#define OV7610_REG_ALC           0x2C	/* Auto Level Control settings */
+#define OV7610_REG_COM_J         0x2D	/* misc settings */
+#define OV7610_REG_VOFFSET       0x2E	/* V channel offset adjustment */
+#define OV7610_REG_ARRAY_BIAS	 0x2F	/* Array bias -- don't change */
+					/* 30-32 reserved */
+#define OV7610_REG_YGAMMA        0x33	/* misc gamma settings (7:6) */
+#define OV7610_REG_BIAS_ADJUST   0x34	/* misc bias settings */
+#define OV7610_REG_COM_L         0x35	/* misc settings */
+					/* 36-37 reserved */
+#define OV7610_REG_COM_K         0x38	/* misc registers */
 
 
 #define STREAM_BUF_SIZE	(PAGE_SIZE * 4)
@@ -171,8 +179,7 @@
 #define FRAME_SIZE_PER_DESC	993	/* FIXME - Deprecated */
 #define MAX_FRAME_SIZE_PER_DESC	993	/* For statically allocated stuff */
 
-// FIXME - should this be 0x81 (endpoint address) or 0x01 (endpoint number)?
-#define OV511_ENDPOINT_ADDRESS 0x81	/* Address of isoc endpoint */
+#define OV511_ENDPOINT_ADDRESS 1	/* Isoc endpoint number */
 
 // CAMERA SPECIFIC
 // FIXME - these can vary between specific models
@@ -223,9 +230,9 @@
 
 struct ov511_regvals {
 	enum {
-	  OV511_DONE_BUS,
-	  OV511_REG_BUS,
-	  OV511_I2C_BUS,
+		OV511_DONE_BUS,
+		OV511_REG_BUS,
+		OV511_I2C_BUS,
 	} bus;
 	unsigned char reg;
 	unsigned char val;
@@ -269,15 +276,16 @@
 	/* Device structure */
 	struct usb_device *dev;
 
-#if 0
-	unsigned char customid; /* Type of camera */
-#else
 	int customid;
 	int desc;
-#endif
-
 	unsigned char iface;
 
+	int brightness;
+	int colour;
+	int contrast;
+	int hue;
+	int whiteness;
+
 	struct semaphore lock;
 	int user;		/* user count for exclusive use */
 
@@ -318,10 +326,33 @@
 	struct proc_dir_entry *proc_entry;	/* /proc/ov511/videoX */
 };
 
-
 struct cam_list {
 	int id;
 	char *description;
+};
+
+struct palette_list {
+	int num;
+	char *name;
+};
+
+struct mode_list {
+	int width;
+	int height;
+	int mode;
+	u8 pxcnt;
+	u8 lncnt;
+	u8 pxdv;
+	u8 lndv;
+	u8 s_pxcnt;
+	u8 s_lncnt;
+	u8 s_pxdv;
+	u8 s_lndv;
+	u8 clock;
+	u8 m420;
+	u8 common_A;
+	u8 common_C;
+	u8 common_L;
 };
 
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c
--- v2.3.99-pre8/linux/drivers/usb/pegasus.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/pegasus.c	Tue May 23 08:22:22 2000
@@ -16,7 +16,7 @@
 #include <linux/usb.h>
 
 
-static const char *version = __FILE__ ": v0.3.9 2000/04/11 Written by Petko Manolov (petkan@spct.net)\n";
+static const char *version = __FILE__ ": v0.3.12 2000/05/22 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n";
 
 
 #define	PEGASUS_MTU		1500
@@ -24,12 +24,15 @@
 #define	SROM_WRITE		0x01
 #define	SROM_READ		0x02
 #define	PEGASUS_TX_TIMEOUT	(HZ*5)
+#define	PEGASUS_RESET		1
 #define	ALIGN(x)		x __attribute__((aligned(L1_CACHE_BYTES)))
 
+
 struct pegasus {
 	struct usb_device	*usb;
 	struct net_device	*net;
 	struct net_device_stats	stats;
+	int			flags;
 	spinlock_t		pegasus_lock;
 	struct urb		rx_urb, tx_urb, intr_urb;
 	unsigned char		ALIGN(rx_buff[PEGASUS_MAX_MTU]); 
@@ -44,9 +47,11 @@
 	void	*private;
 };
 
+
 static int loopback = 0;
 static int multicast_filter_limit = 32;
 
+
 MODULE_AUTHOR("Petko Manolov <petkan@spct.net>");
 MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver");
 MODULE_PARM(loopback, "i");
@@ -98,6 +103,7 @@
 	return 1;
 }
 
+
 static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regdata)
 {
 	int i;
@@ -115,6 +121,7 @@
 	return 1;
 }
 
+
 static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata, __u8 direction)
 {
 	int i;
@@ -134,6 +141,7 @@
 	return 1;
 }
 
+
 static int pegasus_get_node_id(struct usb_device *dev, __u8 *id)
 {
 	int i;
@@ -143,6 +151,7 @@
 	return 0;
 }
 
+
 static int pegasus_reset_mac(struct usb_device *dev)
 {
 	__u8 data = 0x8;
@@ -165,6 +174,7 @@
 	return 1;
 }
 
+
 static int pegasus_start_net(struct net_device *dev, struct usb_device *usb)
 {
 	__u16 partmedia, temp;
@@ -195,13 +205,14 @@
 
 	data[0] = 0xc9;
 	data[1] = (partmedia & 0x100) ? 0x30 : ((partmedia & 0x80) ? 0x10 : 0);
-	data[2] = (loopback & 1) ? 0x08 : 0x00;
+	data[2] = (loopback & 1) ? 0x09 : 0x01;
 
 	pegasus_set_registers(usb, 0, 3, data);
 
 	return 0;
 }
 
+
 static void pegasus_read_bulk(struct urb *urb)
 {
 	struct pegasus *pegasus = urb->context;
@@ -253,15 +264,16 @@
 		warn("(prb)failed rx_urb %d", res);
 }
 
+
 static void pegasus_irq(urb_t *urb)
 {
-	if(urb->status) {
-		__u8	*d = urb->transfer_buffer;
-		printk("txst0 %x, txst1 %x, rxst %x, rxlst0 %x, rxlst1 %x, wakest %x",
-			d[0], d[1], d[2], d[3], d[4], d[5]);
-	}
+	__u8	*d = urb->transfer_buffer;
+	
+	if ( d[0] )
+		dbg("txst0=0x%2x", d[0]);
 }
 
+
 static void pegasus_write_bulk(struct urb *urb)
 {
 	struct pegasus *pegasus = urb->context;
@@ -280,12 +292,15 @@
 	struct pegasus *pegasus = net->priv;
 
 	warn("%s: Tx timed out. Reseting...", net->name);
+	usb_unlink_urb(&pegasus->tx_urb);
 	pegasus->stats.tx_errors++;
 	net->trans_start = jiffies;
+	pegasus->flags |= PEGASUS_RESET;
 
 	netif_wake_queue(net);
 }
 
+
 static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
 	struct pegasus	*pegasus = net->priv;
@@ -317,11 +332,13 @@
 	return 0;
 }
 
+
 static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
 {
 	return &((struct pegasus *)dev->priv)->stats;
 }
 
+
 static int pegasus_open(struct net_device *net)
 {
 	struct pegasus *pegasus = (struct pegasus *)net->priv;
@@ -334,8 +351,10 @@
 
 	if ((res = usb_submit_urb(&pegasus->rx_urb)))
 		warn("(open)failed rx_urb %d", res);
-
-/*	usb_submit_urb(&pegasus->intr_urb);*/
+		
+	if ((res = usb_submit_urb(&pegasus->intr_urb)))
+		warn("(open)failed intr_urb %d", res);
+		
 	netif_start_queue(net);
 
 	MOD_INC_USE_COUNT;
@@ -343,6 +362,7 @@
 	return 0;
 }
 
+
 static int pegasus_close(struct net_device *net)
 {
 	struct pegasus	*pegasus = net->priv;
@@ -351,13 +371,14 @@
 
 	usb_unlink_urb(&pegasus->rx_urb);
 	usb_unlink_urb(&pegasus->tx_urb);
-/*	usb_unlink_urb(&pegasus->intr_urb); */
+	usb_unlink_urb(&pegasus->intr_urb);
 
 	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
 
+
 static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
 {
 	__u16 *data = (__u16 *)&rq->ifr_data;
@@ -379,6 +400,7 @@
 	}
 }
 
+
 static void pegasus_set_rx_mode(struct net_device *net)
 {
 	struct pegasus *pegasus = net->priv;
@@ -400,6 +422,7 @@
 	netif_wake_queue(net);
 }
 
+
 static int check_device_ids( __u16 vendor, __u16 product )
 {
 	int i=0;
@@ -413,6 +436,7 @@
 	return	-1;
 }
 
+
 static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum)
 {
 	struct net_device *net;
@@ -463,7 +487,7 @@
 			pegasus->tx_buff, PEGASUS_MAX_MTU, pegasus_write_bulk,
 			pegasus);
 	FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3),
-			pegasus->intr_buff, 8, pegasus_irq, pegasus, 250);
+			pegasus->intr_buff, 8, pegasus_irq, pegasus, 500);
 
 
 	printk(KERN_INFO "%s: %s\n", net->name, usb_dev_id[dev_indx].name);
@@ -471,6 +495,7 @@
 	return pegasus;
 }
 
+
 static void pegasus_disconnect(struct usb_device *dev, void *ptr)
 {
 	struct pegasus *pegasus = ptr;
@@ -487,10 +512,11 @@
 
 	usb_unlink_urb(&pegasus->rx_urb);
 	usb_unlink_urb(&pegasus->tx_urb);
-/*	usb_unlink_urb(&pegasus->intr_urb);*/
+	usb_unlink_urb(&pegasus->intr_urb);
 
 	kfree(pegasus);
 }
+
 
 static struct usb_driver pegasus_driver = {
 	name:		"pegasus",
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.3.99-pre8/linux/drivers/usb/printer.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/usb/printer.c	Mon May 15 11:38:12 2000
@@ -1,5 +1,5 @@
 /*
- * printer.c  Version 0.3
+ * printer.c  Version 0.4
  *
  * Copyright (c) 1999 Michael Gee 	<michael@linuxspecific.com>
  * Copyright (c) 1999 Pavel Machek      <pavel@suse.cz>
@@ -13,6 +13,7 @@
  *	v0.1 - thorough cleaning, URBification, almost a rewrite
  *	v0.2 - some more cleanups
  *	v0.3 - cleaner again, waitqueue fixes
+ *	v0.4 - fixes in unidirectional mode
  */
 
 /*
@@ -102,7 +103,7 @@
 		return;
 
 	if (urb->status)
-		warn("nonzero read bulk status received: %d", urb->status);
+		warn("nonzero read/write bulk status received: %d", urb->status);
 
 	wake_up_interruptible(&usblp->wait);
 }
@@ -172,9 +173,12 @@
 
 	usblp->writeurb.transfer_buffer_length = 0;
 	usblp->writeurb.status = 0;
-	usblp->readcount = 0;
 
-	usb_submit_urb(&usblp->readurb);
+	if (usblp->bidir) {
+		usblp->readcount = 0;
+		usb_submit_urb(&usblp->readurb);
+	}
+
 	return 0;
 }
 
@@ -185,7 +189,8 @@
 	usblp->used = 0;
 			
 	if (usblp->dev) {
-        	usb_unlink_urb(&usblp->readurb);
+		if (usblp->bidir)
+        		usb_unlink_urb(&usblp->readurb);
         	usb_unlink_urb(&usblp->writeurb);
 		MOD_DEC_USE_COUNT;
 		return 0;
@@ -203,8 +208,8 @@
 {
 	struct usblp *usblp = file->private_data;
 	poll_wait(file, &usblp->wait, wait);
-	return (usblp->readurb.status  == -EINPROGRESS ? 0 : POLLIN  | POLLRDNORM)
-	     | (usblp->writeurb.status == -EINPROGRESS ? 0 : POLLOUT | POLLWRNORM);
+	return ((usblp->bidir || usblp->readurb.status  == -EINPROGRESS) ? 0 : POLLIN  | POLLRDNORM)
+	     		      | (usblp->writeurb.status == -EINPROGRESS  ? 0 : POLLOUT | POLLWRNORM);
 }
 
 static ssize_t usblp_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
@@ -315,7 +320,6 @@
 	int minor, i, alts = -1, bidir = 0;
 	char *buf;
 
-
 	for (i = 0; i < dev->actconfig->interface[ifnum].num_altsetting; i++) {
 
 		interface = &dev->actconfig->interface[ifnum].altsetting[i];
@@ -342,22 +346,21 @@
 		err("can't set desired altsetting %d on interface %d", alts, ifnum);
 
 	epwrite = interface->endpoint + 0;
-	epread = NULL;
-
-	if (bidir) {
-		epread  = interface->endpoint + 1;
-		if ((epread->bEndpointAddress & 0x80) != 0x80) {
-			epwrite = interface->endpoint + 1;
-			epread  = interface->endpoint + 0;
+	epread = bidir ? interface->endpoint + 1 : NULL;
 
-			if ((epread->bEndpointAddress & 0x80) != 0x80)
-				return NULL;
-		}
+	if ((epwrite->bEndpointAddress & 0x80) == 0x80) {
+		if (interface->bNumEndpoints == 1)
+			return NULL;
+		epwrite = interface->endpoint + 1;
+		epread = bidir ? interface->endpoint + 0 : NULL;
 	}
 
 	if ((epwrite->bEndpointAddress & 0x80) == 0x80)
 		return NULL;
 
+	if (bidir && (epread->bEndpointAddress & 0x80) != 0x80)
+		return NULL;
+
 	for (minor = 0; minor < USBLP_MINORS && usblp_table[minor]; minor++);
 	if (usblp_table[minor]) {
 		err("no more free usblp devices");
@@ -386,10 +389,9 @@
 	FILL_BULK_URB(&usblp->writeurb, dev, usb_sndbulkpipe(dev, epwrite->bEndpointAddress),
 		buf, 0, usblp_bulk, usblp);
 
-	if (bidir) {
+	if (bidir)
 		FILL_BULK_URB(&usblp->readurb, dev, usb_rcvbulkpipe(dev, epread->bEndpointAddress),
 			buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp);
-	}
 
 	info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
 		minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
@@ -408,8 +410,9 @@
 
 	usblp->dev = NULL;
 
-	usb_unlink_urb(&usblp->readurb);
 	usb_unlink_urb(&usblp->writeurb);
+	if (usblp->bidir)
+		usb_unlink_urb(&usblp->readurb);
 
 	kfree(usblp->writeurb.transfer_buffer);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/Makefile linux/drivers/usb/serial/Makefile
--- v2.3.99-pre8/linux/drivers/usb/serial/Makefile	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/Makefile	Tue May 23 08:21:51 2000
@@ -4,8 +4,26 @@
 
 O_TARGET	:= usb-serial.o
 M_OBJS		:= usb-serial.o
-O_OBJS		:= usbserial.o visor.o whiteheat.o ftdi_sio.o keyspan_pda.o omninet.o digi_acceleport.o
+O_OBJS		:= usbserial.o
 MOD_LIST_NAME	:= USB_SERIAL_MODULES
 
+ifeq ($(CONFIG_USB_SERIAL_VISOR),y)
+	O_OBJS += visor.o
+endif
+ifeq ($(CONFIG_USB_SERIAL_WHITEHEAT),y)
+	O_OBJS += whiteheat.o
+endif
+ifeq ($(CONFIG_USB_SERIAL_FTDI_SIO),y)
+	O_OBJS += ftdi_sio.o
+endif
+ifeq ($(CONFIG_USB_SERIAL_KEYSPAN_PDA),y)
+	O_OBJS += keyspan_pda.o
+endif
+ifeq ($(CONFIG_USB_SERIAL_OMNINET),y)
+	O_OBJS += omninet.o
+endif
+ifeq ($(CONFIG_USB_SERIAL_DIGI_ACCELEPORT),y)
+	O_OBJS += digi_acceleport.o
+endif
+ 
 include $(TOPDIR)/Rules.make
-
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c
--- v2.3.99-pre8/linux/drivers/usb/serial/digi_acceleport.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/digi_acceleport.c	Tue May 23 08:21:51 2000
@@ -14,16 +14,39 @@
 *  Peter Berger (pberger@brimson.com)
 *  Al Borchers (borchers@steinerpoint.com)
 *
+*  (5/16/2000) pberger and borchers
+*    -- added timeouts to sleeps
+*    -- handle transition to/from B0 in digi_set_termios
+*
+*  (5/13/2000) pberger and borchers
+*    -- all commands now sent on out of band port, using digi_write_oob
+*    -- get modem control signals whenever they change, support TIOCMGET/
+*       SET/BIS/BIC ioctls
+*    -- digi_set_termios now supports parity, word size, stop bits, and
+*       receive enable
+*    -- cleaned up open and close, use digi_set_termios and digi_write_oob
+*       to set port parameters
+*    -- added digi_startup_device to start read chains on all ports
+*    -- write buffer is only used when count==1, to be sure put_char can
+*       write a char (unless the buffer is full)
+*
+*  (5/10/2000) pberger and borchers
+*    -- Added MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT calls
+*    -- Fixed problem where the first incoming character is lost on
+*       port opens after the first close on that port.  Now we keep
+*       the read_urb chain open until shutdown.
+*    -- Added more port conditioning calls in digi_open and digi_close.
+*    -- Convert port->active to a use count so that we can deal with multiple
+*       opens and closes properly.
+*    -- Fixed some problems with the locking code.
+*
 *  (5/3/2000) pberger and borchers
-*  First alpha version of the driver--many known limitations and bugs.
+*    -- First alpha version of the driver--many known limitations and bugs.
 *
-*  $Id: digi_acceleport.c,v 1.28 2000/05/04 01:47:08 root Exp root $
+*  $Id: digi_acceleport.c,v 1.43 2000/05/17 03:21:38 root Exp root $
 */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_SERIAL_DIGI_ACCELEPORT
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -37,45 +60,57 @@
 #include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
+#include <linux/usb.h>
+#include "usb-serial.h"
 
 #ifdef CONFIG_USB_SERIAL_DEBUG
 	#define DEBUG
 #else
 	#undef DEBUG
 #endif
-#include <linux/usb.h>
-#include "usb-serial.h"
 
 
 /* Defines */
 
 /* port buffer length -- must be <= transfer buffer length - 2 */
 /* so we can be sure to send the full buffer in one urb */
-#define DIGI_PORT_BUF_LEN			16
+#define DIGI_PORT_BUF_LEN		16
+
+/* retry timeout while waiting for urb->status to go to 0 */
+#define DIGI_RETRY_TIMEOUT		(HZ/10)
 
 /* AccelePort USB Defines */
 
 /* ids */
-#define DIGI_VENDOR_ID				0x05c5
-#define DIGI_ID					0x0004
+#define DIGI_VENDOR_ID			0x05c5
+#define DIGI_ID				0x0004
 
-/* commands */
-#define DIGI_CMD_SET_BAUD_RATE			0
-#define DIGI_CMD_SET_WORD_SIZE			1
-#define DIGI_CMD_SET_PARITY			2
-#define DIGI_CMD_SET_STOP_BITS			3
-#define DIGI_CMD_SET_INPUT_FLOW_CONTROL		4
-#define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL	5
-#define DIGI_CMD_SET_DTR_SIGNAL			6
-#define DIGI_CMD_SET_RTS_SIGNAL			7
-#define DIGI_CMD_RECEIVE_ENABLE			10
-#define DIGI_CMD_BREAK_CONTROL			11
-#define DIGI_CMD_LOCAL_LOOPBACK			12
-#define DIGI_CMD_TRANSMIT_IDLE			13
-#define DIGI_CMD_WRITE_UART_REGISTER		15
-#define DIGI_CMD_AND_UART_REGISTER		16
-#define DIGI_CMD_OR_UART_REGISTER		17
-#define DIGI_CMD_SEND_DATA			18
+/* commands
+ * "INB": can be used on the in-band endpoint
+ * "OOB": can be used on the out-of-band endpoint
+ */
+#define DIGI_CMD_SET_BAUD_RATE			0	/* INB, OOB */
+#define DIGI_CMD_SET_WORD_SIZE			1	/* INB, OOB */
+#define DIGI_CMD_SET_PARITY			2	/* INB, OOB */
+#define DIGI_CMD_SET_STOP_BITS			3	/* INB, OOB */
+#define DIGI_CMD_SET_INPUT_FLOW_CONTROL		4	/* INB, OOB */
+#define DIGI_CMD_SET_OUTPUT_FLOW_CONTROL	5	/* INB, OOB */
+#define DIGI_CMD_SET_DTR_SIGNAL			6	/* INB, OOB */
+#define DIGI_CMD_SET_RTS_SIGNAL			7	/* INB, OOB */
+#define DIGI_CMD_READ_INPUT_SIGNALS		8	/*      OOB */
+#define DIGI_CMD_IFLUSH_FIFO			9	/*      OOB */
+#define DIGI_CMD_RECEIVE_ENABLE			10	/* INB, OOB */
+#define DIGI_CMD_BREAK_CONTROL			11	/* INB, OOB */
+#define DIGI_CMD_LOCAL_LOOPBACK			12	/* INB, OOB */
+#define DIGI_CMD_TRANSMIT_IDLE			13	/* INB, OOB */
+#define DIGI_CMD_READ_UART_REGISTER		14	/*      OOB */
+#define DIGI_CMD_WRITE_UART_REGISTER		15	/* INB, OOB */
+#define DIGI_CMD_AND_UART_REGISTER		16	/* INB, OOB */
+#define DIGI_CMD_OR_UART_REGISTER		17	/* INB, OOB */
+#define DIGI_CMD_SEND_DATA			18	/* INB      */
+#define DIGI_CMD_RECEIVE_DATA			19	/* INB      */
+#define DIGI_CMD_RECEIVE_DISABLE		20	/* INB      */
+#define DIGI_CMD_GET_PORT_TYPE			21	/*      OOB */
 
 /* baud rates */
 #define DIGI_BAUD_50				0
@@ -102,10 +137,71 @@
 #define DIGI_BAUD_230400			21
 #define DIGI_BAUD_460800			22
 
-/* flow control arguments */
-#define DIGI_ENABLE_IXON_IXOFF_FLOW_CONTROL	1
-#define DIGI_ENABLE_RTS_CTS_FLOW_CONTROL	2
-#define DIGI_ENABLE_DTR_DSR_FLOW_CONTROL	4
+/* arguments */
+#define DIGI_WORD_SIZE_5			0
+#define DIGI_WORD_SIZE_6			1
+#define DIGI_WORD_SIZE_7			2
+#define DIGI_WORD_SIZE_8			3
+
+#define DIGI_PARITY_NONE			0
+#define DIGI_PARITY_ODD				1
+#define DIGI_PARITY_EVEN			2
+#define DIGI_PARITY_MARK			3
+#define DIGI_PARITY_SPACE			4
+
+#define DIGI_STOP_BITS_1			0
+#define DIGI_STOP_BITS_2			1
+
+#define DIGI_INPUT_FLOW_CONTROL_XON_XOFF	1
+#define DIGI_INPUT_FLOW_CONTROL_RTS		2
+#define DIGI_INPUT_FLOW_CONTROL_DTR		4
+
+#define DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF	1
+#define DIGI_OUTPUT_FLOW_CONTROL_CTS		2
+#define DIGI_OUTPUT_FLOW_CONTROL_DSR		4
+
+#define DIGI_DTR_INACTIVE			0
+#define DIGI_DTR_ACTIVE				1
+#define DIGI_DTR_INPUT_FLOW_CONTROL		2
+
+#define DIGI_RTS_INACTIVE			0
+#define DIGI_RTS_ACTIVE				1
+#define DIGI_RTS_INPUT_FLOW_CONTROL		2
+#define DIGI_RTS_TOGGLE				3
+
+#define DIGI_FLUSH_TX				1
+#define DIGI_FLUSH_RX				2
+#define DIGI_RESUME_TX				4 /* clears xoff condition */
+
+#define DIGI_DISABLE				0
+#define DIGI_ENABLE				1
+
+#define DIGI_DEASSERT				0
+#define DIGI_ASSERT				1
+
+/* in band status codes */
+#define DIGI_OVERRUN_ERROR			4
+#define DIGI_PARITY_ERROR			8
+#define DIGI_FRAMING_ERROR			16
+#define DIGI_BREAK_ERROR			32
+
+/* out of band status */
+#define DIGI_NO_ERROR				0
+#define DIGI_BAD_FIRST_PARAMETER		1
+#define DIGI_BAD_SECOND_PARAMETER		2
+#define DIGI_INVALID_LINE			3
+#define DIGI_INVALID_OPCODE			4
+
+/* input signals */
+#define DIGI_READ_INPUT_SIGNALS_SLOT		1
+#define DIGI_READ_INPUT_SIGNALS_ERR		2
+#define DIGI_READ_INPUT_SIGNALS_BUSY		4
+#define DIGI_READ_INPUT_SIGNALS_PE		8
+#define DIGI_READ_INPUT_SIGNALS_CTS		16
+#define DIGI_READ_INPUT_SIGNALS_DSR		32
+#define DIGI_READ_INPUT_SIGNALS_RI		64
+#define DIGI_READ_INPUT_SIGNALS_DCD		128
+
 
 /* macros */
 #define MAX(a,b)	(((a)>(b))?(a):(b))
@@ -117,32 +213,21 @@
 typedef struct digi_private {
 	spinlock_t dp_port_lock;
 	int dp_buf_len;
-	char dp_buf[32];
+	unsigned char dp_buf[DIGI_PORT_BUF_LEN];
+	unsigned int dp_modem_signals;
 } digi_private_t;
 
-struct s_digiusb {
-	u8 opcode;
-	u8 length;
-	u8 val;
-	u8 pad;
-};
-
 
 /* Local Function Declarations */
 
-static void digi_send_cmd( char *mes, struct usb_serial_port *port, int opcode,
-	int length, int val );
-static void digi_send_oob( char *mes, int opcode, int linenum, int data1, int data2 );
+static int digi_write_oob( unsigned char *buf, int count );
+static int digi_set_modem_signals( struct usb_serial_port *port,
+	unsigned int modem_signals );
 static void digi_rx_throttle (struct usb_serial_port *port);
 static void digi_rx_unthrottle (struct usb_serial_port *port);
-static int digi_setbaud( struct usb_serial_port *port, int baud );
 static void digi_set_termios( struct usb_serial_port *port, 
 	struct termios *old_termios );
 static void digi_break_ctl( struct usb_serial_port *port, int break_state );
-static int digi_get_modem_info( struct usb_serial *serial,
-	unsigned char *value );
-static int digi_set_modem_info( struct usb_serial *serial,
-	unsigned char value );
 static int digi_ioctl( struct usb_serial_port *port, struct file *file,
 	unsigned int cmd, unsigned long arg );
 static int digi_write( struct usb_serial_port *port, int from_user,
@@ -152,138 +237,186 @@
 static int digi_chars_in_buffer( struct usb_serial_port *port );
 static int digi_open( struct usb_serial_port *port, struct file *filp );
 static void digi_close( struct usb_serial_port *port, struct file *filp );
-static int digi_startup (struct usb_serial *serial);
+static int digi_startup_device( struct usb_serial *serial );
+static int digi_startup( struct usb_serial *serial );
 static void digi_shutdown( struct usb_serial *serial );
 static void digi_read_bulk_callback( struct urb *urb );
+static void digi_read_oob( struct urb *urb );
 
 
 /* Statics */
 
 /* device info needed for the Digi serial converter */
-static __u16	digi_vendor_id		= DIGI_VENDOR_ID;
-static __u16	digi_product_id		= DIGI_ID;
+static __u16 digi_vendor_id = DIGI_VENDOR_ID;
+static __u16 digi_product_id = DIGI_ID;
 
 /* out of band port */
-static int oob_port_num;					/* index of out-of-band port */
-static struct usb_serial_port *oob_port;	/* out-of-band control port */
-static int oob_read_started = 0;
+static int oob_port_num;			/* index of out-of-band port */
+static struct usb_serial_port *oob_port;	/* out-of-band port */
+static int device_startup = 0;
 
-/* config lock -- used to protect digi statics and globals, like oob vars */
-spinlock_t config_lock;
+/* startup lock -- used to by digi_startup_device */
+spinlock_t startup_lock;
 
 
 /* Globals */
 
 struct usb_serial_device_type digi_acceleport_device = {
-	name:			"Digi USB",
-	idVendor:		&digi_vendor_id,
-	idProduct:		&digi_product_id,
-	needs_interrupt_in:	DONT_CARE,
-	needs_bulk_in:		MUST_HAVE,
-	needs_bulk_out:		MUST_HAVE,
-	num_interrupt_in:	0,
-	num_bulk_in:		5,
-	num_bulk_out:		5,
-	num_ports:		4,
-	open:			digi_open,
-	close:			digi_close,
-	write:			digi_write,
-	write_room:		digi_write_room,
-	write_bulk_callback:	digi_write_bulk_callback,
-	read_bulk_callback:	digi_read_bulk_callback,
-	chars_in_buffer:	digi_chars_in_buffer,
-	throttle:		digi_rx_throttle,
-	unthrottle:		digi_rx_unthrottle,
-	ioctl:			digi_ioctl,
-	set_termios:		digi_set_termios,
-	break_ctl:		digi_break_ctl,
-	startup:		digi_startup,
-	shutdown:		digi_shutdown,
+	name:				"Digi USB",
+	idVendor:			&digi_vendor_id,
+	idProduct:			&digi_product_id,
+	needs_interrupt_in:		DONT_CARE,
+	needs_bulk_in:			MUST_HAVE,
+	needs_bulk_out:			MUST_HAVE,
+	num_interrupt_in:		0,
+	num_bulk_in:			5,
+	num_bulk_out:			5,
+	num_ports:			4,
+	open:				digi_open,
+	close:				digi_close,
+	write:				digi_write,
+	write_room:			digi_write_room,
+	write_bulk_callback: 		digi_write_bulk_callback,
+	read_bulk_callback:		digi_read_bulk_callback,
+	chars_in_buffer:		digi_chars_in_buffer,
+	throttle:			digi_rx_throttle,
+	unthrottle:			digi_rx_unthrottle,
+	ioctl:				digi_ioctl,
+	set_termios:			digi_set_termios,
+	break_ctl:			digi_break_ctl,
+	startup:			digi_startup,
+	shutdown:			digi_shutdown,
 };
 
 
 /* Functions */
 
-/* Send message on the out-of-Band endpoint */
-static void digi_send_oob( char *mes, int opcode, int linenum, int data1, int data2 )
+/*
+*  Digi Write OOB
+*
+*  Write commands on the out of band port.  Commands are 4
+*  bytes each, multiple commands can be sent at once, and
+*  no command will be split across USB packets.  Returns 0
+*  if successful, -EINTR if interrupted while sleeping, or
+*  a negative error returned by usb_submit_urb.
+*/
+
+static int digi_write_oob( unsigned char *buf, int count )
 {
-	int ret;
-	struct s_digiusb digiusb;
-	digi_private_t *priv = (digi_private_t *)(oob_port->private);
 
+	int ret = 0;
+	int len;
+	digi_private_t *oob_priv = (digi_private_t *)(oob_port->private);
 
-dbg( "digi_send_oob: TOP: from '%s', opcode: %d, linenum:%d, data1: %d, data2: %d", mes, opcode, linenum, data1, data2 );
 
-	digiusb.opcode = (u8)opcode;
-	digiusb.length = (u8)linenum;
-	digiusb.val = (u8)data1;
-	digiusb.pad = (u8)data2;
+dbg( "digi_write_oob: TOP: port=%d, count=%d", oob_port->number, count );
 
-	spin_lock( &priv->dp_port_lock );
+	spin_lock( &oob_priv->dp_port_lock );
 
-	while (oob_port->write_urb->status == -EINPROGRESS) {
-dbg( "digi_send_oob: opcode:%d already writing...", opcode );
-		spin_unlock( &priv->dp_port_lock );
-		interruptible_sleep_on(&oob_port->write_wait);
-		if (signal_pending(current)) {
-			return;
+	while( count > 0 ) {
+
+		while( oob_port->write_urb->status == -EINPROGRESS ) {
+			spin_unlock( &oob_priv->dp_port_lock );
+			interruptible_sleep_on_timeout( &oob_port->write_wait,
+				DIGI_RETRY_TIMEOUT );
+			if( signal_pending(current) ) {
+				return( -EINTR );
+			}
+			spin_lock( &oob_priv->dp_port_lock );
+		}
+
+		/* len must be a multiple of 4, so commands are not split */
+		len = MIN( count, oob_port->bulk_out_size );
+		if( len > 4 )
+			len &= ~3;
+
+		memcpy( oob_port->write_urb->transfer_buffer, buf, len );
+		oob_port->write_urb->transfer_buffer_length = len;
+
+		if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) {
+			count -= len;
+			buf += len;
+		} else {
+			dbg( "digi_write_oob: usb_submit_urb failed, ret=%d",
+				ret );
+			break;
 		}
-		spin_lock( &priv->dp_port_lock );
-	}
 
-	memcpy( oob_port->write_urb->transfer_buffer, &digiusb, sizeof(digiusb) );
-	oob_port->write_urb->transfer_buffer_length = sizeof(digiusb);
-	if( (ret=usb_submit_urb(oob_port->write_urb)) != 0 ) {
-		dbg(
-		"digi_send_oob: usb_submit_urb(write bulk) failed, opcode=%d, ret=%d",
-		opcode, ret );
 	}
 
-	spin_unlock( &priv->dp_port_lock );
+	spin_unlock( &oob_priv->dp_port_lock );
 
-dbg( "digi_send_oob: opcode %d done", opcode );
+	return( ret );
 
 }
 
 
-static void digi_send_cmd( char *mes, struct usb_serial_port *port, int opcode,
-	int length, int val )
+/*
+*  Digi Set Modem Signals
+*
+*  Sets or clears DTR and RTS on the port, according to the
+*  modem_signals argument.  Use TIOCM_DTR and TIOCM_RTS flags
+*  for the modem_signals argument.  Returns 0 if successful,
+*  -EINTR if interrupted while sleeping, or a non-zero error
+*  returned by usb_submit_urb.
+*/
+
+static int digi_set_modem_signals( struct usb_serial_port *port,
+	unsigned int modem_signals )
 {
 
 	int ret;
-	struct s_digiusb digiusb;
-	digi_private_t *priv = (digi_private_t *)(port->private);
-
+	unsigned char *data = oob_port->write_urb->transfer_buffer;
+	digi_private_t *port_priv = (digi_private_t *)(port->private);
+	digi_private_t *oob_priv = (digi_private_t *)(oob_port->private);
 
-dbg( "digi_send_cmd: TOP: from '%s', opcode: %d, val: %d", mes, opcode, val );
 
-	digiusb.opcode = (u8)opcode;
-	digiusb.length = (u8)length;
-	digiusb.val = (u8)val;
-	digiusb.pad = 0;
+dbg( "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x",
+port->number, modem_signals );
 
-	spin_lock( &priv->dp_port_lock );
+	spin_lock( &oob_priv->dp_port_lock );
+	spin_lock( &port_priv->dp_port_lock );
 
-	while( port->write_urb->status == -EINPROGRESS ) {
-dbg( "digi_send_cmd: opcode=%d already writing...", opcode );
-		spin_unlock( &priv->dp_port_lock );
-		interruptible_sleep_on( &port->write_wait );
+	while( oob_port->write_urb->status == -EINPROGRESS ) {
+		spin_unlock( &port_priv->dp_port_lock );
+		spin_unlock( &oob_priv->dp_port_lock );
+		interruptible_sleep_on_timeout( &oob_port->write_wait,
+			DIGI_RETRY_TIMEOUT );
 		if( signal_pending(current) ) {
-			return;
+			return( -EINTR );
 		}
-		spin_lock( &priv->dp_port_lock );
+		spin_lock( &oob_priv->dp_port_lock );
+		spin_lock( &port_priv->dp_port_lock );
 	}
 
-	memcpy( port->write_urb->transfer_buffer, &digiusb, sizeof(digiusb) );
-	port->write_urb->transfer_buffer_length = sizeof(digiusb);
-	if( (ret=usb_submit_urb(port->write_urb)) != 0 )
-		dbg(
-		"digi_send_cmd: usb_submit_urb(write bulk) failed, opcode=%d, ret=%d",
-		opcode, ret );
+	/* command is 4 bytes: command, line, argument, pad */
+	data[0] = DIGI_CMD_SET_DTR_SIGNAL;
+	data[1] = port->number;
+	data[2] = (modem_signals&TIOCM_DTR) ?
+		DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
+	data[3] = 0;
+
+	data[4] = DIGI_CMD_SET_RTS_SIGNAL;
+	data[5] = port->number;
+	data[6] = (modem_signals&TIOCM_RTS) ?
+		DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
+	data[7] = 0;
+
+	oob_port->write_urb->transfer_buffer_length = 8;
+
+	if( (ret=usb_submit_urb(oob_port->write_urb)) == 0 ) {
+		port_priv->dp_modem_signals =
+			(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
+			| (modem_signals&(TIOCM_DTR|TIOCM_RTS));
+	} else {
+		dbg( "digi_set_modem_signals: usb_submit_urb failed, ret=%d",
+			ret );
+	}
 
-dbg( "digi_send_cmd: opcode %d done", opcode );
+	spin_unlock( &port_priv->dp_port_lock );
+	spin_unlock( &oob_priv->dp_port_lock );
 
-	spin_unlock( &priv->dp_port_lock );
+	return( ret );
 
 }
 
@@ -312,52 +445,7 @@
 
 	/* just restart the receive interrupt URB */
 	//if (usb_submit_urb(port->interrupt_in_urb))
-	//	dbg( "digi_rx_unthrottle: usb_submit_urb(read urb) failed" );
-
-}
-
-
-static int digi_setbaud( struct usb_serial_port *port, int baud )
-{
-
-	int bindex;
-
-
-dbg( "digi_setbaud: TOP: port=%d", port->number );
-
-	switch( baud ) {
-		case 50: bindex = DIGI_BAUD_50; break;
-		case 75: bindex = DIGI_BAUD_75; break;
-		case 110: bindex = DIGI_BAUD_110; break;
-		case 150: bindex = DIGI_BAUD_150; break;
-		case 200: bindex = DIGI_BAUD_200; break;
-		case 300: bindex = DIGI_BAUD_300; break;
-		case 600: bindex = DIGI_BAUD_600; break;
-		case 1200: bindex = DIGI_BAUD_1200; break;
-		case 1800: bindex = DIGI_BAUD_1800; break;
-		case 2400: bindex = DIGI_BAUD_2400; break;
-		case 4800: bindex = DIGI_BAUD_4800; break;
-		case 7200: bindex = DIGI_BAUD_7200; break;
-		case 9600: bindex = DIGI_BAUD_9600; break;
-		case 14400: bindex = DIGI_BAUD_14400; break;
-		case 19200: bindex = DIGI_BAUD_19200; break;
-		case 28800: bindex = DIGI_BAUD_28800; break;
-		case 38400: bindex = DIGI_BAUD_38400; break;
-		case 57600: bindex = DIGI_BAUD_57600; break;
-		case 76800: bindex = DIGI_BAUD_76800; break;
-		case 115200: bindex = DIGI_BAUD_115200; break;
-		case 153600: bindex = DIGI_BAUD_153600; break;
-		case 230400: bindex = DIGI_BAUD_230400; break;
-		case 460800: bindex = DIGI_BAUD_460800; break;
-		default:
-			dbg( "digi_setbaud: can't handle requested baud rate %d", baud );
-			return( -EINVAL );
-			break;
-	}
-
-	digi_send_cmd( "digi_setbaud:", port, DIGI_CMD_SET_BAUD_RATE, 2, bindex );
-
-	return( 0 );	/* FIX -- send_cmd should return a value??, return it */
+	//	dbg( "digi_rx_unthrottle: usb_submit_urb failed" );
 
 }
 
@@ -367,167 +455,243 @@
 {
 
 	unsigned int iflag = port->tty->termios->c_iflag;
-	unsigned int old_iflag = old_termios->c_iflag;
 	unsigned int cflag = port->tty->termios->c_cflag;
+	unsigned int old_iflag = old_termios->c_iflag;
 	unsigned int old_cflag = old_termios->c_cflag;
-	int arg;
+	unsigned char buf[32];
+	int arg,ret;
+	int i = 0;
 
 
 dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", port->number, iflag, old_iflag, cflag, old_cflag );
 
 	/* set baud rate */
-	/* if( (cflag&CBAUD) != (old_cflag&CBAUD) ) */ {
+	if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
+
+		arg = -1;
+
+		/* reassert DTR and (maybe) RTS on transition from B0 */
+		if( (old_cflag&CBAUD) == B0 ) {
+			/* don't set RTS if using hardware flow control */
+			/* and throttling input -- not implemented yet */
+			digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS );
+		}
+
 		switch( (cflag&CBAUD) ) {
-			case B50: digi_setbaud(port, 50); break;
-			case B75: digi_setbaud(port, 75); break;
-			case B110: digi_setbaud(port, 110); break;
-			case B150: digi_setbaud(port, 150); break;
-			case B200: digi_setbaud(port, 200); break;
-			case B300: digi_setbaud(port, 300); break;
-			case B600: digi_setbaud(port, 600); break;
-			case B1200: digi_setbaud(port, 1200); break;
-			case B1800: digi_setbaud(port, 1800); break;
-			case B2400: digi_setbaud(port, 2400); break;
-			case B4800: digi_setbaud(port, 4800); break;
-			case B9600: digi_setbaud(port, 9600); break;
-			case B19200: digi_setbaud(port, 19200); break;
-			case B38400: digi_setbaud(port, 38400); break;
-			case B57600: digi_setbaud(port, 57600); break;
-			case B115200: digi_setbaud(port, 115200); break;
-			default:
-				dbg( "digi_set_termios: can't handle baud rate 0x%x",
-					(cflag&CBAUD) );
-				break;
+			/* drop DTR and RTS on transition to B0 */
+		case B0: digi_set_modem_signals( port, 0 ); break;
+		case B50: arg = DIGI_BAUD_50; break;
+		case B75: arg = DIGI_BAUD_75; break;
+		case B110: arg = DIGI_BAUD_110; break;
+		case B150: arg = DIGI_BAUD_150; break;
+		case B200: arg = DIGI_BAUD_200; break;
+		case B300: arg = DIGI_BAUD_300; break;
+		case B600: arg = DIGI_BAUD_600; break;
+		case B1200: arg = DIGI_BAUD_1200; break;
+		case B1800: arg = DIGI_BAUD_1800; break;
+		case B2400: arg = DIGI_BAUD_2400; break;
+		case B4800: arg = DIGI_BAUD_4800; break;
+		case B9600: arg = DIGI_BAUD_9600; break;
+		case B19200: arg = DIGI_BAUD_19200; break;
+		case B38400: arg = DIGI_BAUD_38400; break;
+		case B57600: arg = DIGI_BAUD_57600; break;
+		case B115200: arg = DIGI_BAUD_115200; break;
+		case B230400: arg = DIGI_BAUD_230400; break;
+		case B460800: arg = DIGI_BAUD_460800; break;
+		default:
+			dbg( "digi_set_termios: can't handle baud rate 0x%x",
+				(cflag&CBAUD) );
+			break;
 		}
+
+		if( arg != -1 ) {
+			buf[i++] = DIGI_CMD_SET_BAUD_RATE;
+			buf[i++] = port->number;
+			buf[i++] = arg;
+			buf[i++] = 0;
+		}
+
+	}
+
+	/* set parity */
+	if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) {
+
+		if( (cflag&PARENB) ) {
+			if( (cflag&PARODD) )
+				arg = DIGI_PARITY_ODD;
+			else
+				arg = DIGI_PARITY_EVEN;
+		} else {
+			arg = DIGI_PARITY_NONE;
+		}
+
+		buf[i++] = DIGI_CMD_SET_PARITY;
+		buf[i++] = port->number;
+		buf[i++] = arg;
+		buf[i++] = 0;
+
+	}
+
+	/* set word size */
+	if( (cflag&CSIZE) != (old_cflag&CSIZE) ) {
+
+		arg = -1;
+
+		switch( (cflag&CSIZE) ) {
+		case CS5: arg = DIGI_WORD_SIZE_5; break;
+		case CS6: arg = DIGI_WORD_SIZE_6; break;
+		case CS7: arg = DIGI_WORD_SIZE_7; break;
+		case CS8: arg = DIGI_WORD_SIZE_8; break;
+		default:
+			dbg( "digi_set_termios: can't handle word size %d",
+				(cflag&CSIZE) );
+			break;
+		}
+
+		if( arg != -1 ) {
+			buf[i++] = DIGI_CMD_SET_WORD_SIZE;
+			buf[i++] = port->number;
+			buf[i++] = arg;
+			buf[i++] = 0;
+		}
+
+	}
+
+	/* set stop bits */
+	if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) {
+
+		if( (cflag&CSTOPB) )
+			arg = DIGI_STOP_BITS_2;
+		else
+			arg = DIGI_STOP_BITS_1;
+
+		buf[i++] = DIGI_CMD_SET_STOP_BITS;
+		buf[i++] = port->number;
+		buf[i++] = arg;
+		buf[i++] = 0;
+
 	}
 
 	/* set input flow control */
-	/* if( (iflag&IXOFF) != (old_iflag&IXOFF)
-	|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) */ {
+	if( (iflag&IXOFF) != (old_iflag&IXOFF)
+	|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) {
 
 		arg = 0;
 
 		if( (iflag&IXOFF) )
-			arg |= DIGI_ENABLE_IXON_IXOFF_FLOW_CONTROL;
+			arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
+		else
+			arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
+
 		if( (cflag&CRTSCTS) )
-			arg |= DIGI_ENABLE_RTS_CTS_FLOW_CONTROL;
+			arg |= DIGI_INPUT_FLOW_CONTROL_RTS;
+		else
+			arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS;
 
-		digi_send_cmd( "digi_termios: set input flow control:", port,
-			DIGI_CMD_SET_INPUT_FLOW_CONTROL, 2, arg );
+		buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+		buf[i++] = port->number;
+		buf[i++] = arg;
+		buf[i++] = 0;
 
 	}
 
 	/* set output flow control */
-	/* if( (iflag&IXON) != (old_iflag&IXON)
-	|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) */ {
+	/*if( (iflag&IXON) != (old_iflag&IXON)
+	|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) )*/ {
 
 		arg = 0;
 
 		if( (iflag&IXON) )
-			arg |= DIGI_ENABLE_IXON_IXOFF_FLOW_CONTROL;
+			arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
+		else
+			arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
+
 		if( (cflag&CRTSCTS) )
-			arg |= DIGI_ENABLE_RTS_CTS_FLOW_CONTROL;
+			arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS;
+		else
+			arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS;
 
-		digi_send_cmd( "digi_set_termios: set output flow control:", port,
-			DIGI_CMD_SET_OUTPUT_FLOW_CONTROL, 2, arg );
+		buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+		buf[i++] = port->number;
+		buf[i++] = arg;
+		buf[i++] = 0;
 
 	}
 
-}
+	/* set receive enable/disable */
+	if( (cflag&CREAD) != (old_cflag&CREAD) ) {
 
+		if( (cflag&CREAD) )
+			arg = DIGI_ENABLE;
+		else
+			arg = DIGI_DISABLE;
 
-static void digi_break_ctl( struct usb_serial_port *port, int break_state )
-{
-dbg( "digi_break_ctl: TOP: port=%d", port->number );
-}
+		buf[i++] = DIGI_CMD_RECEIVE_ENABLE;
+		buf[i++] = port->number;
+		buf[i++] = arg;
+		buf[i++] = 0;
 
+	}
 
-/* modem control pins: DTR and RTS are outputs and can be controlled;
-   DCD, RI, DSR, CTS are inputs and can be read */
+	if( (ret=digi_write_oob( buf, i )) != 0 )
+		dbg( "digi_set_termios: write oob failed, ret=%d", ret );
 
-static int digi_get_modem_info( struct usb_serial *serial,
-	unsigned char *value )
-{
-dbg( "digi_get_modem_info: TOP" );
-	return( 0 );
 }
 
 
-static int digi_set_modem_info( struct usb_serial *serial,
-	unsigned char value )
+static void digi_break_ctl( struct usb_serial_port *port, int break_state )
 {
-dbg( "digi_set_modem_info: TOP" );
-	return( 0 );
+dbg( "digi_break_ctl: TOP: port=%d", port->number );
 }
 
 
 static int digi_ioctl( struct usb_serial_port *port, struct file *file,
 	unsigned int cmd, unsigned long arg )
 {
-	struct usb_serial *serial = port->serial;
-	int rc;
-	unsigned int value;
-	unsigned char status, mask;
+
+	digi_private_t *priv = (digi_private_t *)(port->private);
+	unsigned int val;
+
 
 dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", port->number, cmd );
-return( -ENOIOCTLCMD );
 
 	switch (cmd) {
-	case TIOCMGET: /* get modem pins state */
-		rc = digi_get_modem_info(serial, &status);
-		if (rc < 0)
-			return rc;
-		value =
-			((status & (1<<7)) ? TIOCM_DTR : 0) |
-			((status & (1<<6)) ? TIOCM_CAR : 0) |
-			((status & (1<<5)) ? TIOCM_RNG : 0) |
-			((status & (1<<4)) ? TIOCM_DSR : 0) |
-			((status & (1<<3)) ? TIOCM_CTS : 0) |
-			((status & (1<<2)) ? TIOCM_RTS : 0);
-		if (copy_to_user((unsigned int *)arg, &value, sizeof(int)))
-			return -EFAULT;
-		return 0;
-	case TIOCMSET: /* set a state as returned by MGET */
-		if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
-			return -EFAULT;
-		status =
-			((value & TIOCM_DTR) ? (1<<7) : 0) |
-			((value & TIOCM_CAR) ? (1<<6) : 0) |
-			((value & TIOCM_RNG) ? (1<<5) : 0) |
-			((value & TIOCM_DSR) ? (1<<4) : 0) |
-			((value & TIOCM_CTS) ? (1<<3) : 0) |
-			((value & TIOCM_RTS) ? (1<<2) : 0);
-		rc = digi_set_modem_info(serial, status);
-		if (rc < 0)
-			return rc;
-		return 0;
-	case TIOCMBIS: /* set bits in bitmask <arg> */
-	case TIOCMBIC: /* clear bits from bitmask <arg> */
-		if (copy_from_user(&value, (unsigned int *)arg, sizeof(int)))
-			return -EFAULT;
-		rc = digi_get_modem_info(serial, &status);
-		if (rc < 0)
-			return rc;
-		mask =
-			((value & TIOCM_RTS) ? (1<<2) : 0) |
-			((value & TIOCM_DTR) ? (1<<7) : 0);
-		if (cmd == TIOCMBIS)
-			status |= mask;
-		else
-			status &= ~mask;
-		rc = digi_set_modem_info(serial, status);
-		if (rc < 0)
-			return rc;
-		return 0;
+
+	case TIOCMGET:
+		spin_lock( &priv->dp_port_lock );
+		val = priv->dp_modem_signals;
+		spin_unlock( &priv->dp_port_lock );
+		if( copy_to_user((unsigned int *)arg, &val, sizeof(int)) )
+			return( -EFAULT );
+		return( 0 );
+
+	case TIOCMSET:
+	case TIOCMBIS:
+	case TIOCMBIC:
+		if( copy_from_user(&val, (unsigned int *)arg, sizeof(int)) )
+			return( -EFAULT );
+		spin_lock( &priv->dp_port_lock );
+		if( cmd == TIOCMBIS )
+			val = priv->dp_modem_signals | val;
+		else if( cmd == TIOCMBIC )
+			val = priv->dp_modem_signals & ~val;
+		spin_unlock( &priv->dp_port_lock );
+		return( digi_set_modem_signals( port, val ) );
+
 	case TIOCMIWAIT:
 		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
 		/* TODO */
+		return( 0 );
+
 	case TIOCGICOUNT:
 		/* return count of modemline transitions */
-		return 0; /* TODO */
+		/* TODO */
+		return 0;
+
 	}
-	
-	return -ENOIOCTLCMD;
+
+	return( -ENOIOCTLCMD );
+
 }
 
 
@@ -535,7 +699,7 @@
 	const unsigned char *buf, int count )
 {
 
-	int i,ret,data_len,new_len;
+	int ret,data_len,new_len;
 	digi_private_t *priv = (digi_private_t *)(port->private);
 
 
@@ -550,16 +714,18 @@
 	/* wait for urb status clear to submit another urb */
 	if( port->write_urb->status == -EINPROGRESS ) {
 
-dbg( "digi_write: -EINPROGRESS set" );
-
-		/* buffer the data if possible */
-		new_len = MIN( count, DIGI_PORT_BUF_LEN-priv->dp_buf_len );
-		memcpy( priv->dp_buf+priv->dp_buf_len, buf, new_len );
-		priv->dp_buf_len += new_len;
+		/* buffer data if count is 1 (probably put_char) if possible */
+		if( count == 1 ) {
+			new_len = MIN( count,
+				DIGI_PORT_BUF_LEN-priv->dp_buf_len );
+			memcpy( priv->dp_buf+priv->dp_buf_len, buf, new_len );
+			priv->dp_buf_len += new_len;
+		} else {
+			new_len = 0;
+		}
 
-		/* unlock and return number of bytes buffered */
 		spin_unlock( &priv->dp_port_lock );
-dbg( "digi_write: buffering, return %d", new_len );
+
 		return( new_len );
 
 	}
@@ -569,19 +735,16 @@
 	new_len = MIN( count, port->bulk_out_size-2-priv->dp_buf_len );
 	data_len = new_len + priv->dp_buf_len;
 
-dbg( "digi_write: counts: new data %d, buf data %d, total data %d (max %d)", new_len, priv->dp_buf_len, data_len, port->bulk_out_size-2 );
-
-	/* nothing to send */
 	if( data_len == 0 ) {
 		spin_unlock( &priv->dp_port_lock );
 		return( 0 );
 	}
 
-	/* set command and length bytes */
-	*((u8 *)(port->write_urb->transfer_buffer)) = (u8)DIGI_CMD_SEND_DATA;
-	*((u8 *)(port->write_urb->transfer_buffer)+1) = (u8)data_len;
+	*((unsigned char *)(port->write_urb->transfer_buffer))
+		= (unsigned char)DIGI_CMD_SEND_DATA;
+	*((unsigned char *)(port->write_urb->transfer_buffer)+1)
+		= (unsigned char)data_len;
 
-	/* set total transfer buffer length */
 	port->write_urb->transfer_buffer_length = data_len+2;
 
 	/* copy in buffered data first */
@@ -590,33 +753,34 @@
 
 	/* copy in new data */
 	if( from_user ) {
-		copy_from_user( port->write_urb->transfer_buffer+2+priv->dp_buf_len,
+		copy_from_user(
+			port->write_urb->transfer_buffer+2+priv->dp_buf_len,
 			buf, new_len );
-	}
-	else {
+	} else {
 		memcpy( port->write_urb->transfer_buffer+2+priv->dp_buf_len,
 			buf, new_len );
 	}  
 
-#ifdef DEBUG
-	printk( KERN_DEBUG __FILE__ ": digi_write: length=%d, data=",
-		port->write_urb->transfer_buffer_length );
+#ifdef DEBUG_DATA
+{
+	int i;
+
+	printk( KERN_DEBUG __FILE__ ": digi_write: port=%d, length=%d, data=",
+		port->number, port->write_urb->transfer_buffer_length );
 	for( i=0; i<port->write_urb->transfer_buffer_length; ++i ) {
 		printk( "%.2x ",
-			((unsigned char *)port->write_urb->transfer_buffer)[i] );
+		((unsigned char *)port->write_urb->transfer_buffer)[i] );
 	}
 	printk( "\n" );
+}
 #endif
 
-	/* submit urb */
 	if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
-		/* submit successful, return length of new data written */
 		ret = new_len;
-		/* clear buffer */
 		priv->dp_buf_len = 0;
-	}
-	else {
-		dbg( "digi_write: usb_submit_urb(write bulk) failed, ret=%d", ret );
+	} else {
+		dbg( "digi_write: usb_submit_urb failed, ret=%d",
+			ret );
 		/* no bytes written - should we return the error code or 0? */
 		ret = 0;
 	}
@@ -658,28 +822,34 @@
 	spin_lock( &priv->dp_port_lock );
 	if( port->write_urb->status != -EINPROGRESS && priv->dp_buf_len > 0 ) {
 
-		/* set command and length bytes */
-		*((u8 *)(port->write_urb->transfer_buffer))
-			= (u8)DIGI_CMD_SEND_DATA;
-		*((u8 *)(port->write_urb->transfer_buffer)+1)
-			= (u8)priv->dp_buf_len;
+		*((unsigned char *)(port->write_urb->transfer_buffer))
+			= (unsigned char)DIGI_CMD_SEND_DATA;
+		*((unsigned char *)(port->write_urb->transfer_buffer)+1)
+			= (unsigned char)priv->dp_buf_len;
 
-		/* set total transfer buffer length */
 		port->write_urb->transfer_buffer_length = priv->dp_buf_len+2;
 
-		/* copy in buffered data */
 		memcpy( port->write_urb->transfer_buffer+2, priv->dp_buf,
 			priv->dp_buf_len );
 
-		/* submit urb */
-dbg( "digi_write_bulk_callback: submit urb to write buffer, data len=%d",
-priv->dp_buf_len );
+#ifdef DEBUG_DATA
+{
+	int i;
+
+	printk( KERN_DEBUG __FILE__ ": digi_write_bulk_callback: port=%d, length=%d, data=",
+		port->number, port->write_urb->transfer_buffer_length );
+	for( i=0; i<port->write_urb->transfer_buffer_length; ++i ) {
+		printk( "%.2x ",
+		((unsigned char *)port->write_urb->transfer_buffer)[i] );
+	}
+	printk( "\n" );
+}
+#endif
+
 		if( (ret=usb_submit_urb(port->write_urb)) == 0 ) {
-			/* successful, clear buffer */
 			priv->dp_buf_len = 0;
-		}
-		else {
-			dbg( "digi_write_bulk_callback: usb_submit_urb(write bulk) failed, ret=%d", ret );
+		} else {
+			dbg( "digi_write_bulk_callback: usb_submit_urb failed, ret=%d", ret );
 		}
 
 	}
@@ -690,7 +860,8 @@
 
 	/* wake up line discipline */
 	tty = port->tty;
-	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup )
+	if( (tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
+	&& tty->ldisc.write_wakeup )
 		(tty->ldisc.write_wakeup)(tty);
 
 	/* wake up other tty processes */
@@ -717,7 +888,7 @@
 
 	spin_unlock( &priv->dp_port_lock );
 
-dbg( "digi_write_room: return room=%d", room );
+dbg( "digi_write_room: port=%d, room=%d", port->number, room );
 	return( room );
 
 }
@@ -732,11 +903,10 @@
 dbg( "digi_chars_in_buffer: TOP: port=%d", port->number );
 
 	if( port->write_urb->status == -EINPROGRESS ) {
-dbg( "digi_chars_in_buffer: return=%d", port->bulk_out_size );
-		return( port->bulk_out_size );
-	}
-	else {
-dbg( "digi_chars_in_buffer: return=%d", priv->dp_buf_len );
+dbg( "digi_chars_in_buffer: port=%d, chars=%d", port->number, port->bulk_out_size - 2 );
+		return( port->bulk_out_size - 2 );
+	} else {
+dbg( "digi_chars_in_buffer: port=%d, chars=%d", port->number, priv->dp_buf_len );
 		return( priv->dp_buf_len );
 	}
 
@@ -746,61 +916,53 @@
 static int digi_open( struct usb_serial_port *port, struct file *filp )
 {
 
+	int i = 0;
 	int ret;
+	unsigned char buf[32];
 	digi_private_t *priv = (digi_private_t *)(port->private);
+	struct termios not_termios;
+
 
+dbg( "digi_open: TOP: port %d, active:%d", port->number, port->active );
 
-dbg( "digi_open: TOP: port %d", port->number );
+	/* be sure the device is started up */
+	if( digi_startup_device( port->serial ) != 0 )
+		return( -ENXIO );
+
+	MOD_INC_USE_COUNT;
 
 	/* if port is already open, just return */
-	/* be sure exactly one open succeeds */
+	/* be sure exactly one open proceeds */
 	spin_lock( &priv->dp_port_lock );
-	if( port->active ) {
+	if( port->active++ ) {
+		spin_unlock( &priv->dp_port_lock );
 		return( 0 );
 	}
-	port->active = 1;
 	spin_unlock( &priv->dp_port_lock );
  
-	/* start reading from the out-of-band port for the device */
-	/* be sure this happens exactly once */
-	spin_lock( &config_lock );
-	if( !oob_read_started ) {
-		if( (ret=usb_submit_urb(oob_port->read_urb)) != 0 ) {
-			dbg( "digi_open: usb_submit_urb(read bulk) for oob failed, ret=%d",
-				ret );
-			spin_unlock( &config_lock );
-			return( -ENXIO );
-		}
-		else {
-dbg( "digi_open: usb_submit_urb(read bulk) for oob succeeded" );
-			oob_read_started = 1;
-		}
-	}
-	spin_unlock( &config_lock );
-
-	/* initialize port */
-dbg( "digi_open: init..." );
-	/* set 9600, 8N1, DTR, RTS, RX enable, no input or output flow control */
-	digi_setbaud( port, 9600 );
-	digi_send_cmd( "digi_open: wordsize", port, DIGI_CMD_SET_WORD_SIZE, 2, 3 );
-	digi_send_cmd( "digi_open: parity", port, DIGI_CMD_SET_PARITY, 2, 0 );
-	digi_send_cmd( "digi_open: stopbits", port, DIGI_CMD_SET_STOP_BITS, 2, 0 );
-	digi_send_cmd( "digi_open: DTR on", port, DIGI_CMD_SET_DTR_SIGNAL, 2, 1 );
-	digi_send_cmd( "digi_open: RTS on", port, DIGI_CMD_SET_RTS_SIGNAL, 2, 1 );
-	digi_send_cmd( "digi_open: RX enable on", port, DIGI_CMD_RECEIVE_ENABLE, 2,
-		1 );
-	digi_send_cmd( "digi_open: input flow control off", port,
-		DIGI_CMD_SET_INPUT_FLOW_CONTROL, 2, 0 );
-	digi_send_cmd( "digi_open: output flow control off", port,
-		DIGI_CMD_SET_OUTPUT_FLOW_CONTROL, 2, 0 );
-
-	/* start reading from the device */
-	if( (ret=usb_submit_urb(port->read_urb)) != 0 ) {
-		dbg( "digi_open: usb_submit_urb(read bulk) failed, ret=%d", ret );
-		return( -ENXIO );
-	}
+	/* read modem signals automatically whenever they change */
+	buf[i++] = DIGI_CMD_READ_INPUT_SIGNALS;
+	buf[i++] = port->number;
+	buf[i++] = DIGI_ENABLE;
+	buf[i++] = 0;
+
+	/* flush fifos */
+	buf[i++] = DIGI_CMD_IFLUSH_FIFO;
+	buf[i++] = port->number;
+	buf[i++] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+	buf[i++] = 0;
+
+	if( (ret=digi_write_oob( buf, i )) != 0 )
+		dbg( "digi_open: write oob failed, ret=%d", ret );
+
+	/* set termios settings */
+	not_termios.c_cflag = ~port->tty->termios->c_cflag;
+	not_termios.c_iflag = ~port->tty->termios->c_iflag;
+	digi_set_termios( port, &not_termios );
+
+	/* set DTR and RTS */
+	digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS );
 
-dbg( "digi_open: done" );
 	return( 0 );
 
 }
@@ -809,39 +971,119 @@
 static void digi_close( struct usb_serial_port *port, struct file *filp )
 {
 
-dbg( "digi_close: TOP: port %d", port->number );
+	int i = 0;
+	int ret;
+	unsigned char buf[32];
+	digi_private_t *priv = (digi_private_t *)(port->private);
+
+
+dbg( "digi_close: TOP: port %d, active:%d", port->number, port->active );
+
+
+	/* do cleanup only after final close on this port */
+	spin_lock( &priv->dp_port_lock );
+	if( --port->active ) {
+		spin_unlock( &priv->dp_port_lock );
+		MOD_DEC_USE_COUNT;
+		return;
+	}
+	spin_unlock( &priv->dp_port_lock );
 	
-	/* Need to change the control lines here */
-	/* TODO */
-dbg( "digi_close: wanna clear DTR and RTS..." );
-
-//digi_send_cmd( "digi_close DTR off", port, 6, 2, 0);	// clear DTR
-//digi_send_cmd( "digi_close RTS off", port, 7, 2, 0);	// clear RTS
-//digi_send_cmd( "digi_close RX disable", port, 10, 2, 0);	// Rx Disable
-
-digi_send_oob( "digi_close RTS off", DIGI_CMD_SET_RTS_SIGNAL,
-	port->number, 0, 0 );	// clear RTS
-digi_send_oob( "digi_close DTR off", DIGI_CMD_SET_DTR_SIGNAL,
-	port->number, 0, 0 );	// clear DTR
+	/* drop DTR and RTS */
+	digi_set_modem_signals( port, 0 );
 
+	/* disable input flow control */
+	buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
+	buf[i++] = port->number;
+	buf[i++] = DIGI_DISABLE;
+	buf[i++] = 0;
+
+	/* disable output flow control */
+	buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
+	buf[i++] = port->number;
+	buf[i++] = DIGI_DISABLE;
+	buf[i++] = 0;
+
+	/* disable reading modem signals automatically */
+	buf[i++] = DIGI_CMD_READ_INPUT_SIGNALS;
+	buf[i++] = port->number;
+	buf[i++] = DIGI_DISABLE;
+	buf[i++] = 0;
+
+	/* flush fifos */
+	buf[i++] = DIGI_CMD_IFLUSH_FIFO;
+	buf[i++] = port->number;
+	buf[i++] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
+	buf[i++] = 0;
+
+	/* disable receive */
+	buf[i++] = DIGI_CMD_RECEIVE_ENABLE;
+	buf[i++] = port->number;
+	buf[i++] = DIGI_DISABLE;
+	buf[i++] = 0;
+
+	if( (ret=digi_write_oob( buf, i )) != 0 )
+		dbg( "digi_close: write oob failed, ret=%d", ret );
+
+	/* wait for final commands on oob port to complete */
 	while( oob_port->write_urb->status == -EINPROGRESS ) {
-dbg ("digi_close: waiting for final writes to complete on oob port %d...", oob_port->number );
-		interruptible_sleep_on( &oob_port->write_wait );
+		interruptible_sleep_on_timeout( &oob_port->write_wait,
+			DIGI_RETRY_TIMEOUT );
 		if( signal_pending(current) ) {
 			break;
 		}
 	}
 	
-	/* shutdown our bulk reads and writes */
+	/* shutdown any outstanding bulk writes */
 	usb_unlink_urb (port->write_urb);
-	usb_unlink_urb (port->read_urb);
 
-	port->active = 0;
+	MOD_DEC_USE_COUNT;
 
 }
 
 
-static int digi_startup (struct usb_serial *serial)
+/*
+*  Digi Startup Device
+*
+*  Starts reads on all ports.  Must be called AFTER startup, with
+*  urbs initialized.  Returns 0 if successful, non-zero error otherwise.
+*/
+
+static int digi_startup_device( struct usb_serial *serial )
+{
+
+	int i,ret = 0;
+
+
+	spin_lock( &startup_lock );
+
+	/* be sure this happens exactly once */
+	if( device_startup ) {
+		spin_unlock( &startup_lock );
+		return( 0 );
+	}
+
+	/* start reading from each bulk in endpoint for the device */
+	for( i=0; i<digi_acceleport_device.num_ports+1; i++ ) {
+
+		if( (ret=usb_submit_urb(serial->port[i].read_urb)) != 0 ) {
+			dbg( "digi_startup_device: usb_submit_urb failed, port=%d, ret=%d",
+				i, ret );
+			break;
+		}
+
+	}
+
+	device_startup = 1;
+
+	spin_unlock( &startup_lock );
+
+	return( ret );
+
+}
+
+
+static int digi_startup( struct usb_serial *serial )
 {
 
 	int i;
@@ -850,22 +1092,24 @@
 
 dbg( "digi_startup: TOP" );
 
-	/* initialize config lock */
-	spin_lock_init( &config_lock );
+	spin_lock_init( &startup_lock );
 
 	/* allocate the private data structures for all ports */
 	/* number of regular ports + 1 for the out-of-band port */
 	for( i=0; i<digi_acceleport_device.num_ports+1; i++ ) {
 
+		serial->port[i].active = 0;
+
 		/* allocate private structure */
 		priv = serial->port[i].private =
-			(digi_private_t *)kmalloc( sizeof(struct digi_private),
+			(digi_private_t *)kmalloc( sizeof(digi_private_t),
 			GFP_KERNEL );
 		if( priv == (digi_private_t *)0 )
-			return( 1 );				/* error */
+			return( 1 );			/* error */
 
 		/* initialize private structure */
 		priv->dp_buf_len = 0;
+		priv->dp_modem_signals = 0;
 		spin_lock_init( &priv->dp_port_lock );
 
 		/* initialize write wait queue for this port */
@@ -876,7 +1120,7 @@
 	/* initialize out of band port info */
 	oob_port_num = digi_acceleport_device.num_ports;
 	oob_port = &serial->port[oob_port_num];
-	oob_read_started = 0;
+	device_startup = 0;
 
 	return( 0 );
 
@@ -891,10 +1135,13 @@
 
 dbg( "digi_shutdown: TOP" );
 
-	/* stop writing and reading from the out-of-band port */
-	usb_unlink_urb( oob_port->write_urb );
-	usb_unlink_urb( oob_port->read_urb );
-	oob_read_started = 0;
+	/* stop reads and writes on all ports */
+	for( i=0; i<digi_acceleport_device.num_ports+1; i++ ) {
+		usb_unlink_urb (serial->port[i].read_urb);
+		usb_unlink_urb (serial->port[i].write_urb);
+	}
+
+	device_startup = 0;
 
 	/* free the private data structures for all ports */
 	/* number of regular ports + 1 for the out-of-band port */
@@ -910,7 +1157,10 @@
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
 	struct usb_serial *serial = port->serial;
 	struct tty_struct *tty = port->tty;
-	unsigned char *data = urb->transfer_buffer;
+	int opcode = ((unsigned char *)urb->transfer_buffer)[0];
+	int len = ((unsigned char *)urb->transfer_buffer)[1];
+	int status = ((unsigned char *)urb->transfer_buffer)[2];
+	unsigned char *data = ((unsigned char *)urb->transfer_buffer)+3;
 	int ret,i;
 
 
@@ -918,58 +1168,108 @@
 
 	/* handle oob callback */
 	if( port->number == oob_port_num ) {
-dbg( "digi_read_bulk_callback: oob_port callback, opcode=%d, line=%d, status=%d, ret=%d", data[0], data[1], data[2], data[3] );
-		if( urb->status ) {
-			dbg( "digi_read_bulk_callback: nonzero read bulk status on oob: %d",
-				urb->status );
-		}
-		if( (ret=usb_submit_urb(urb)) != 0 ) {
-			dbg( "digi_read_bulk_callback: failed resubmitting oob urb, ret=%d",
-				ret );
-		}
+		digi_read_oob( urb );
 		return;
 	}
 
 	/* sanity checks */
 	if( port_paranoia_check( port, "digi_read_bulk_callback" )
 	|| serial_paranoia_check( serial, "digi_read_bulk_callback" ) ) {
-		return;
+		goto resubmit;
 	}
 
-	/* check status */
 	if( urb->status ) {
 		dbg( "digi_read_bulk_callback: nonzero read bulk status: %d",
 			urb->status );
-		return;
+		goto resubmit;
 	}
 
-#ifdef DEBUG
-	if (urb->actual_length) {
-		printk( KERN_DEBUG __FILE__ ": digi_read_bulk_callback: length=%d, data=",
-			urb->actual_length );
-		for( i=0; i<urb->actual_length; ++i ) {
-			printk( "%.2x ", data[i] );
-		}
-		printk( "\n" );
+#ifdef DEBUG_DATA
+if( urb->actual_length ) {
+	printk( KERN_DEBUG __FILE__ ": digi_read_bulk_callback: port=%d, length=%d, data=",
+		port->number, urb->actual_length );
+	for( i=0; i<urb->actual_length; ++i ) {
+		printk( "%.2x ", ((unsigned char *)urb->transfer_buffer)[i] );
 	}
+	printk( "\n" );
+}
 #endif
 
-	/* Digi read packets are:												 */
-	/* 0         1      2         3       4    ...     3+length-1 == 2+length*/
-	/* opcode, length, status, data[0], data[1]...data[length-2]			 */
-	if( urb->actual_length > 3 ) {
-		for( i=3; i<2+data[1]; ++i ) {
+	if( urb->actual_length != len + 2 )
+     		err( KERN_INFO "digi_read_bulk_callback: INCOMPLETE PACKET, port=%d, opcode=%d, len=%d, actual_length=%d, status=%d", port->number, opcode, len, urb->actual_length, status );
+
+	/* receive data */
+	if( opcode == DIGI_CMD_RECEIVE_DATA && urb->actual_length > 3 ) {
+		len = MIN( len, urb->actual_length-3 );
+		for( i=0; i<len; ++i ) {
 			 tty_insert_flip_char(tty, data[i], 0);
 	  	}
 	  	tty_flip_buffer_push(tty);
 	}
 
-	/* Continue trying to read */
+	/* continue read */
+resubmit:
 	if( (ret=usb_submit_urb(urb)) != 0 )
-		dbg( "digi_read_bulk_callback: failed resubmitting read urb, ret=%d",
+		dbg( "digi_read_bulk_callback: failed resubmitting urb, ret=%d",
 			ret );
 
 }
 
-#endif	/* CONFIG_USB_SERIAL_DIGI_ACCELEPORT */
+
+static void digi_read_oob( struct urb *urb )
+{
+
+	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
+	struct usb_serial *serial = port->serial;
+	digi_private_t *priv;
+	int oob_opcode = ((unsigned char *)urb->transfer_buffer)[0];
+	int oob_line = ((unsigned char *)urb->transfer_buffer)[1];
+	int oob_status = ((unsigned char *)urb->transfer_buffer)[2];
+	int oob_ret = ((unsigned char *)urb->transfer_buffer)[3];
+	int ret;
+
+
+dbg( "digi_read_oob: opcode=%d, line=%d, status=%d, ret=%d", oob_opcode, oob_line, oob_status, oob_ret );
+
+	if( urb->status ) {
+		dbg( "digi_read_oob: nonzero read bulk status on oob: %d",
+			urb->status );
+		goto resubmit;
+	}
+
+	if( oob_opcode == DIGI_CMD_READ_INPUT_SIGNALS && oob_status == 0 ) {
+
+		priv = serial->port[oob_line].private;
+
+		spin_lock( &priv->dp_port_lock );
+
+		/* convert from digi flags to termiox flags */
+		if( oob_ret & DIGI_READ_INPUT_SIGNALS_CTS )
+			priv->dp_modem_signals |= TIOCM_CTS;
+		else
+			priv->dp_modem_signals &= ~TIOCM_CTS;
+		if( oob_ret & DIGI_READ_INPUT_SIGNALS_DSR )
+			priv->dp_modem_signals |= TIOCM_DSR;
+		else
+			priv->dp_modem_signals &= ~TIOCM_DSR;
+		if( oob_ret & DIGI_READ_INPUT_SIGNALS_RI )
+			priv->dp_modem_signals |= TIOCM_RI;
+		else
+			priv->dp_modem_signals &= ~TIOCM_RI;
+		if( oob_ret & DIGI_READ_INPUT_SIGNALS_DCD )
+			priv->dp_modem_signals |= TIOCM_CD;
+		else
+			priv->dp_modem_signals &= ~TIOCM_CD;
+
+		spin_unlock( &priv->dp_port_lock );
+
+	}
+
+resubmit:
+	if( (ret=usb_submit_urb(urb)) != 0 ) {
+		dbg( "digi_read_oob: failed resubmitting oob urb, ret=%d",
+		ret );
+	}
+
+}
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c
--- v2.3.99-pre8/linux/drivers/usb/serial/ftdi_sio.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/ftdi_sio.c	Tue May 23 08:21:51 2000
@@ -32,9 +32,6 @@
 
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_SERIAL_FTDI_SIO
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -722,7 +719,4 @@
 	dbg("ftdi_sio_ioctl returning 0");
 	return 0;
 } /* ftdi_sio_ioctl */
-
-#endif 	/* CONFIG_USB_SERIAL_FTDI_SIO */
-
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c
--- v2.3.99-pre8/linux/drivers/usb/serial/keyspan_pda.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/keyspan_pda.c	Tue May 23 08:21:51 2000
@@ -18,9 +18,6 @@
 
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -700,4 +697,3 @@
 	shutdown:		keyspan_pda_shutdown,
 };
 
-#endif	/* CONFIG_USB_SERIAL_KEYSPAN_PDA */
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c
--- v2.3.99-pre8/linux/drivers/usb/serial/omninet.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/omninet.c	Tue May 23 08:21:51 2000
@@ -13,9 +13,6 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_SERIAL_OMNINET
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -335,7 +332,4 @@
 
 	return;
 }
-
-#endif	/* CONFIG_USB_SERIAL_OMNINET */
-
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- v2.3.99-pre8/linux/drivers/usb/serial/usbserial.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/usbserial.c	Tue May 23 08:21:51 2000
@@ -14,6 +14,10 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (05/22/2000) gkh
+ *	Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be 
+ *	removed from the individual device source files.
+ *
  * (05/03/2000) gkh
  *	Added the Digi Acceleport driver from Al Borchers and Peter Berger.
  * 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
--- v2.3.99-pre8/linux/drivers/usb/serial/visor.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/visor.c	Tue May 23 08:21:51 2000
@@ -20,9 +20,6 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_SERIAL_VISOR
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -206,8 +203,4 @@
 	/* continue on with initialization */
 	return (0);
 }
-
-
-#endif	/* CONFIG_USB_SERIAL_VISOR*/
-
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c
--- v2.3.99-pre8/linux/drivers/usb/serial/whiteheat.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/serial/whiteheat.c	Tue May 23 08:21:51 2000
@@ -21,9 +21,6 @@
  */
 
 #include <linux/config.h>
-
-#ifdef CONFIG_USB_SERIAL_WHITEHEAT
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
@@ -406,7 +403,4 @@
 
 	return;
 }
-
-#endif	/* CONFIG_USB_SERIAL_WHITEHEAT */
-
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.3.99-pre8/linux/drivers/usb/uhci.c	Fri May 12 14:18:55 2000
+++ linux/drivers/usb/uhci.c	Sat May 20 11:39:27 2000
@@ -821,6 +821,7 @@
 	/* Control status phase */
 	status = uhci_status_bits(td->status);
 
+#ifdef I_HAVE_BUGGY_APC_BACKUPS
 	/* APC BackUPS Pro kludge */
 	/* It tries to send all of the descriptor instead of the amount */
 	/*  we requested */
@@ -828,6 +829,7 @@
 	    status & TD_CTRL_ACTIVE &&
 	    status & TD_CTRL_NAK)
 		return 0;
+#endif
 
 	if (status & TD_CTRL_ACTIVE)
 		return -EINPROGRESS;
@@ -2325,30 +2327,29 @@
 {
 	int i;
 
+	/* disable legacy emulation */
+	pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
+	if (pci_enable_device(dev) < 0)
+		return -1;
+
+	if (!dev->irq) {
+		err("found UHCI device with no IRQ assigned. check BIOS settings!");
+		return -1;
+	}
+
 	/* Search for the IO base address.. */
 	for (i = 0; i < 6; i++) {
-		unsigned int io_addr = dev->resource[i].start;
-		unsigned int io_size =
-			dev->resource[i].end - dev->resource[i].start + 1;
+		unsigned int io_addr = pci_resource_start(dev, i);
+		unsigned int io_size = pci_resource_len(dev, i);
 
 		/* IO address? */
-		if (!(dev->resource[i].flags & IORESOURCE_IO))
+		if (!(pci_resource_flags(dev, i) & IORESOURCE_IO))
 			continue;
 
 		/* Is it already in use? */
 		if (check_region(io_addr, io_size))
 			break;
-
-		if (!dev->irq) {
-			err("found UHCI device with no IRQ assigned. check BIOS settings!");
-			continue;
-		}
-
-		/* disable legacy emulation */
-		pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
-
-		if (pci_enable_device(dev) < 0)
-			continue;
 
 		return setup_uhci(dev, dev->irq, io_addr, io_size);
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- v2.3.99-pre8/linux/drivers/usb/usb-ohci.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/usb-ohci.c	Tue May 23 08:22:07 2000
@@ -92,7 +92,6 @@
 	kfree (urb->hcpriv);
 	urb->hcpriv = NULL;
 
-	wake_up (&op_wakeup);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -493,16 +492,16 @@
 		urb->start_frame = ((ed->state == ED_OPER)? (ed->last_iso + 1): 
 								(le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff;
 	}	
+	urb->status = USB_ST_URB_PENDING;
+	urb->actual_length = 0;
 	
 	if (ed->state != ED_OPER)  /* link the ed into a chain if is not already */
 		ep_link (ohci, ed);
 	
+	urb->status = USB_ST_URB_PENDING; 
 	td_submit_urb (urb); /* fill the TDs and link it to the ed */
 
 	spin_unlock_irqrestore (&usb_ed_lock, flags);
-	
-	urb->status = USB_ST_URB_PENDING; 
-	// queue_urb(s, &urb->urb_list);
 
 	return 0;	
 }
@@ -529,6 +528,8 @@
 	urb_print (urb, "UNLINK", 1);
 #endif		  
 
+	usb_dec_dev_use (urb->dev);	
+	
 	if (usb_pipedevice (urb->pipe) == ohci->rh.devnum) 
 		return rh_unlink_urb (urb); /* a request to the virtual root hub */
 	
@@ -546,19 +547,23 @@
 			ep_rm_ed (urb->dev, urb_priv->ed);
 			urb_priv->ed->state |= ED_URB_DEL;
 			spin_unlock_irqrestore (&usb_ed_lock, flags);
-
-			add_wait_queue (&op_wakeup, &wait);
-			current->state = TASK_UNINTERRUPTIBLE;
-			if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */
-				err("unlink URB timeout!");
-			remove_wait_queue (&op_wakeup, &wait); 
-		} else 
+			if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
+				add_wait_queue (&op_wakeup, &wait);
+				current->state = TASK_UNINTERRUPTIBLE;
+				if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */
+					err("unlink URB timeout!");
+				remove_wait_queue (&op_wakeup, &wait); 
+				urb->status = -ENOENT;
+			} else
+				urb->status = -EINPROGRESS;
+		} else {
 			urb_rm_priv (urb);
-
-		urb->status = -ENOENT;	// mark urb as killed		
-		if (urb->complete)
-			urb->complete ((struct urb *) urb);
-		usb_dec_dev_use (urb->dev);		
+			if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) {
+				urb->complete (urb); 
+				urb->status = 0;	
+			} else 
+				urb->status = -ENOENT;
+		}	
 	}	
 	return 0;
 }
@@ -967,7 +972,7 @@
 
 /* prepare a TD */
 
-static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int type, int index)
+static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int index)
 {
 	volatile td_t  * td, * td_pt;
 	urb_priv_t * urb_priv = urb->hcpriv;
@@ -984,7 +989,6 @@
 	td->index = index;
 	td->urb = urb; 
 	td->hwINFO = cpu_to_le32 (info);
-	td->type = type;
 	if ((td->ed->type & 3) == PIPE_ISOCHRONOUS) {
 		td->hwCBP = cpu_to_le32 (((!data || !len)? 
 								0 : virt_to_bus (data)) & 0xFFFFF000);
@@ -1031,12 +1035,12 @@
 			info = usb_pipeout (urb->pipe)? 
 				TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
 			while(data_len > 4096) {		
-				td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt);
+				td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt);
 				data += 4096; data_len -= 4096; cnt++;
 			}
 			info = usb_pipeout (urb->pipe)?
 				TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
-			td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt);
+			td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt);
 			cnt++;
 			writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
 			break;
@@ -1044,20 +1048,20 @@
 		case PIPE_INTERRUPT:
 			info = usb_pipeout (urb->pipe)? 
 				TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle;
-			td_fill (info, data, data_len, urb, ST_ADDR | ADD_LEN, cnt++);
+			td_fill (info, data, data_len, urb, cnt++);
 			break;
 
 		case PIPE_CONTROL:
 			info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
-			td_fill (info, ctrl, 8, urb, ST_ADDR, cnt++); 
+			td_fill (info, ctrl, 8, urb, cnt++); 
 			if (data_len > 0) {  
 				info = usb_pipeout (urb->pipe)? 
 					TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
-				td_fill (info, data, data_len, urb, ADD_LEN, cnt++);  
+				td_fill (info, data, data_len, urb, cnt++);  
 			} 
 			info = usb_pipeout (urb->pipe)? 
  				TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
-			td_fill (info, NULL, 0, urb, 0, cnt++);
+			td_fill (info, NULL, 0, urb, cnt++);
 			writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
 			break;
 
@@ -1065,7 +1069,7 @@
 			for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
 				td_fill (TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff), 
  					(__u8 *) data + urb->iso_frame_desc[cnt].offset, 
-					urb->iso_frame_desc[cnt].length, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt); 
+					urb->iso_frame_desc[cnt].length, urb, cnt); 
 			}
 			break;
 	} 
@@ -1076,7 +1080,55 @@
 /*-------------------------------------------------------------------------*
  * Done List handling functions
  *-------------------------------------------------------------------------*/
- 
+
+
+/* calculate the transfer length and update the urb */
+
+static void dl_transfer_length(td_t * td)
+{
+	__u32 tdINFO, tdBE, tdCBP;
+ 	__u16 tdPSW;
+ 	urb_t * urb = td->urb;
+ 	urb_priv_t * urb_priv = urb->hcpriv;
+	int dlen = 0;
+	int cc = 0;
+	
+	tdINFO = le32_to_cpup (&td->hwINFO);
+  	tdBE   = le32_to_cpup (&td->hwBE);
+  	tdCBP  = le32_to_cpup (&td->hwCBP);
+
+
+  	if (tdINFO & TD_ISO) {
+ 		tdPSW = le16_to_cpu (td->hwPSW[0]);
+ 		cc = (tdPSW >> 12) & 0xF;
+		if (cc < 0xE)  {
+			if (usb_pipeout(urb->pipe)) {
+				dlen = urb->iso_frame_desc[td->index].length;
+			} else {
+				dlen = tdPSW & 0x3ff;
+			}
+			urb->actual_length += dlen;
+			urb->iso_frame_desc[td->index].actual_length = dlen;
+			if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN))
+				cc = TD_CC_NOERROR;
+					 
+			urb->iso_frame_desc[td->index].status = cc_to_error[cc];
+		}
+	} else { /* BULK, INT, CONTROL DATA */
+		if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL && 
+				((td->index == 0) || (td->index == urb_priv->length - 1)))) {
+ 			if (tdBE != 0) {
+ 				if (td->hwCBP == 0)
+					urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1;
+  				else
+					urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer;
+			}
+  		}
+  	}
+}
+
+/*-------------------------------------------------------------------------*/
+
 /* replies to the request have to be on a FIFO basis so
  * we reverse the reversed done-list */
  
@@ -1130,6 +1182,7 @@
 	unsigned long flags;
 	ed_t * ed;
 	__u32 edINFO;
+	__u32 tdINFO;
 	td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP;
 	__u32 * td_p;
 	int ctrl = 0, bulk = 0;
@@ -1141,16 +1194,25 @@
 		tdHeadP = bus_to_virt (le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
 		edINFO = le32_to_cpup (&ed->hwINFO);
 		td_p = &ed->hwHeadP;
-			
+
 		for (td = tdHeadP; td != tdTailP; td = td_next) { 
 			urb_t * urb = td->urb;
 			urb_priv_t * urb_priv = td->urb->hcpriv;
 			
 			td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
 			if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
+				tdINFO = le32_to_cpup (&td->hwINFO);
+				if (TD_CC_GET (tdINFO) < 0xE) dl_transfer_length (td);
 				*td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
 				if(++ (urb_priv->td_cnt) == urb_priv->length) 
 					urb_rm_priv (urb);
+					if (urb->transfer_flags & USB_ASYNC_UNLINK) {
+						usb_dec_dev_use (urb->dev);
+						urb->status = -ECONNRESET;
+						urb->complete (urb); 
+					} else {	
+						wake_up (&op_wakeup);
+					}
 			} else {
 				td_p = &td->hwNextTD;
 			}
@@ -1167,7 +1229,7 @@
    	 	}
    	 	else {
    	 		ed->state &= ~ED_URB_DEL;
-   	 		ed->hwINFO  &=  ~cpu_to_le32 (OHCI_ED_SKIP);
+   	 		ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP);
    	 	}
    	 	
    	 	if ((ed->type & 3) == CTRL) ctrl |= 1;
@@ -1185,6 +1247,8 @@
    	spin_unlock_irqrestore (&usb_ed_lock, flags);
 }
 
+
+  		
 /*-------------------------------------------------------------------------*/
 
 /* td done list */
@@ -1193,12 +1257,11 @@
 {
   	td_t * td_list_next = NULL;
 	ed_t * ed;
-	int dlen = 0;
 	int cc = 0;
 	urb_t * urb;
 	urb_priv_t * urb_priv;
- 	__u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP;
- 	__u16 tdPSW;
+ 	__u32 tdINFO, edHeadP, edTailP;
+ 	
  	unsigned long flags;
  	
   	while (td_list) {
@@ -1207,40 +1270,11 @@
   		urb = td_list->urb;
   		urb_priv = urb->hcpriv;
   		tdINFO = le32_to_cpup (&td_list->hwINFO);
-  		tdBE   = le32_to_cpup (&td_list->hwBE);
-  		tdCBP  = le32_to_cpup (&td_list->hwCBP);
   		
    		ed = td_list->ed;
    		
-  		if (td_list->type & ST_ADDR) 
-  			urb->actual_length = 0;
-  			
- 		if (td_list->type & ADD_LEN) { /* accumulate length of multi td transfers */
- 			if (tdINFO & TD_ISO) {
- 				tdPSW = le16_to_cpu (td_list->hwPSW[0]);
- 				cc = (tdPSW >> 12) & 0xF;
-				if (cc < 0xE)  {
-					if (usb_pipeout(urb->pipe)) {
-						dlen = urb->iso_frame_desc[td_list->index].length;
-					} else {
-						dlen = tdPSW & 0x3ff;
-					}
-					urb->actual_length += dlen;
-					urb->iso_frame_desc[td_list->index].actual_length = dlen;
-					if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN))
-						cc = TD_CC_NOERROR;
-					 
-					urb->iso_frame_desc[td_list->index].status = cc_to_error[cc];
-				}
- 			} else {
- 				if (tdBE != 0) {
- 					if (td_list->hwCBP == 0)
-						urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1;
-  					else
-						urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer;
-  			    }
-  			}
-  		}
+   		dl_transfer_length(td_list);
+ 			
   		/* error code of transfer */
   		cc = TD_CC_GET (tdINFO);
   		if( cc == TD_CC_STALL) usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
@@ -1936,11 +1970,11 @@
 {
 	unsigned long mem_base;
 
-	mem_base = dev->resource[0].start;
 	if (pci_enable_device(dev) < 0)
 		return -ENODEV;
 	
 	pci_set_master (dev);
+	mem_base = dev->resource[0].start;
 	mem_base = (unsigned long) ioremap_nocache (mem_base, 4096);
 
 	if (!mem_base) {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-ohci.h linux/drivers/usb/usb-ohci.h
--- v2.3.99-pre8/linux/drivers/usb/usb-ohci.h	Mon Mar 27 08:08:28 2000
+++ linux/drivers/usb/usb-ohci.h	Tue May 23 08:22:22 2000
@@ -432,7 +432,7 @@
 static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load);
 static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed);
 /* td */
-static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int type, int index);
+static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int index);
 static void td_submit_urb(urb_t * urb);
 /* root hub */
 static int rh_submit_urb(urb_t * urb);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-storage.c linux/drivers/usb/usb-storage.c
--- v2.3.99-pre8/linux/drivers/usb/usb-storage.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/usb-storage.c	Sat May 20 10:18:21 2000
@@ -1,7 +1,10 @@
 /* Driver for USB Mass Storage compliant devices
  *
- * (c) 1999 Michael Gee (michael@linuxspecific.com)
- * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
+ * Initial work by:
+ *   (c) 1999 Michael Gee (michael@linuxspecific.com)
+ *
+ * Current development and maintainance by:
+ *   (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
  *
  * This driver is based on the 'USB Mass Storage Class' document. This
  * describes in detail the protocol used to communicate with such
@@ -16,6 +19,9 @@
  *
  * Also, for certain devices, the interrupt endpoint is used to convey
  * status of a command.
+ *
+ * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
+ * information about this driver.
  */
 
 #include <linux/module.h>
@@ -111,10 +117,15 @@
 	struct semaphore	ip_waitq;	 /* for CBI interrupts	 */
 	int			ip_wanted;	 /* is an IRQ expected?	 */
 
+	/* interrupt communications data */
 	struct semaphore	irq_urb_sem;	 /* to protect irq_urb	 */
 	struct urb		*irq_urb;	 /* for USB int requests */
 	unsigned char		irqbuf[2];	 /* buffer for USB IRQ	 */
 
+	/* control and bulk communications data */
+	struct semaphore	current_urb_sem; /* to protect irq_urb	 */
+	struct urb		*current_urb;	 /* non-int USB requests */
+
 	/* mutual exclusion structures */
 	struct semaphore	notify;		 /* thread begin/end	    */
 	struct semaphore	sleeper;	 /* to sleep the thread on  */
@@ -147,6 +158,155 @@
  * Data transfer routines
  ***********************************************************************/
 
+/* This is the completion handler which will wake us up when an URB
+ * completes.
+ */
+static void usb_stor_blocking_completion(urb_t *urb)
+{
+	api_wrapper_data *awd = (api_wrapper_data *)urb->context;
+
+	if (waitqueue_active(awd->wakeup))
+		wake_up(awd->wakeup);
+}
+
+/* This is our function to emulate usb_control_msg() but give us enough
+ * access to make aborts/resets work
+ */
+int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
+			 u8 request, u8 requesttype, u16 value, u16 index, 
+			 void *data, u16 size)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	DECLARE_WAIT_QUEUE_HEAD(wqh);
+	api_wrapper_data awd;
+	int status;
+	devrequest *dr;
+
+	/* allocate the device request structure */
+	dr = kmalloc(sizeof(devrequest), GFP_KERNEL);
+	if (!dr)
+		return -ENOMEM;
+
+	/* fill in the structure */
+	dr->requesttype = requesttype;
+	dr->request = request;
+	dr->value = cpu_to_le16(value);
+	dr->index = cpu_to_le16(index);
+	dr->length = cpu_to_le16(size);
+
+	/* set up data structures for the wakeup system */
+	awd.wakeup = &wqh;
+	awd.handler = 0;
+	init_waitqueue_head(&wqh); 	
+	add_wait_queue(&wqh, &wait);
+
+	/* lock the URB */
+	down(&(us->current_urb_sem));
+
+	/* fill the URB */
+	FILL_CONTROL_URB(us->current_urb, us->pusb_dev, pipe, 
+			 (unsigned char*) dr, data, size, 
+			 usb_stor_blocking_completion, &awd);
+
+	/* submit the URB */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	status = usb_submit_urb(us->current_urb);
+	if (status) {
+		/* something went wrong */
+		up(&(us->current_urb_sem));
+		remove_wait_queue(&wqh, &wait);
+		kfree(dr);
+		return status;
+	}
+
+	/* wait for the completion of the URB */
+	up(&(us->current_urb_sem));
+	if (us->current_urb->status == -EINPROGRESS)
+		schedule_timeout(10*HZ);
+	down(&(us->current_urb_sem));
+
+	/* we either timed out or got woken up -- clean up either way */
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&wqh, &wait);
+
+	/* did we time out? */
+	if (us->current_urb->status == -EINPROGRESS) {
+		US_DEBUGP("usb_stor_control_msg() timeout\n");
+		usb_unlink_urb(us->current_urb);
+		status = -ETIMEDOUT;
+	} else
+		status = us->current_urb->status;
+
+	/* return the actual length of the data transferred if no error*/
+	if (status >= 0)
+		status = us->current_urb->actual_length;
+
+	/* release the lock and return status */
+	up(&(us->current_urb_sem));
+	kfree(dr);
+  	return status;
+}
+
+/* This is our function to emulate usb_bulk_msg() but give us enough
+ * access to make aborts/resets work
+ */
+int usb_stor_bulk_msg(struct us_data *us, void *data, int pipe,
+		      unsigned int len, unsigned int *act_len)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	DECLARE_WAIT_QUEUE_HEAD(wqh);
+	api_wrapper_data awd;
+	int status;
+
+	/* set up data structures for the wakeup system */
+	awd.wakeup = &wqh;
+	awd.handler = 0;
+	init_waitqueue_head(&wqh); 	
+	add_wait_queue(&wqh, &wait);
+
+	/* lock the URB */
+	down(&(us->current_urb_sem));
+
+	/* fill the URB */
+	FILL_BULK_URB(us->current_urb, us->pusb_dev, pipe, data, len,
+		      usb_stor_blocking_completion, &awd);
+
+	/* submit the URB */
+	set_current_state(TASK_UNINTERRUPTIBLE);
+	status = usb_submit_urb(us->current_urb);
+	if (status) {
+		/* something went wrong */
+		up(&(us->current_urb_sem));
+		remove_wait_queue(&wqh, &wait);
+		return status;
+	}
+
+	/* wait for the completion of the URB */
+	up(&(us->current_urb_sem));
+	if (us->current_urb->status == -EINPROGRESS)
+		schedule_timeout(10*HZ);
+	down(&(us->current_urb_sem));
+
+	/* we either timed out or got woken up -- clean up either way */
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&wqh, &wait);
+
+	/* did we time out? */
+	if (us->current_urb->status == -EINPROGRESS) {
+		US_DEBUGP("usb_stor_bulk_msg() timeout\n");
+		usb_unlink_urb(us->current_urb);
+		status = -ETIMEDOUT;
+	} else
+		status = us->current_urb->status;
+
+	/* return the actual length of the data transferred */
+	*act_len = us->current_urb->actual_length;
+
+	/* release the lock and return status */
+	up(&(us->current_urb_sem));
+	return status;
+}
+
 /*
  * Transfer one SCSI scatter-gather buffer via bulk transfer
  *
@@ -158,26 +318,33 @@
  * timeout limit.  Thus we don't have to worry about it for individual
  * packets.
  */
-static int us_transfer_partial(struct us_data *us, int pipe, 
-			       char *buf, int length)
+static int us_transfer_partial(struct us_data *us, char *buf, int length)
 {
 	int result;
 	int partial;
+	int pipe;
+
+	/* calculate the appropriate pipe information */
+	if (US_DIRECTION(us->srb->cmnd[0]))
+		pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
+	else
+		pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
 
 	/* transfer the data */
-	US_DEBUGP("Bulk xfer 0x%x(%d)\n", (unsigned int)buf, length);
-	result = usb_bulk_msg(us->pusb_dev, pipe, buf, length, &partial, 5*HZ);
-	US_DEBUGP("bulk_msg returned %d xferred %d/%d\n",
+	US_DEBUGP("us_transfer_partial(): xfer %d bytes\n", length);
+	result = usb_stor_bulk_msg(us, buf, pipe, length, &partial);
+	US_DEBUGP("usb_stor_bulk_msg() returned %d xferred %d/%d\n",
 		  result, partial, length);
-	
+
 	/* if we stall, we need to clear it before we go on */
 	if (result == -EPIPE) {
 		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
 		usb_clear_halt(us->pusb_dev, pipe);
 	}
-
+	
 	/* did we send all the data? */
 	if (partial == length) {
+		US_DEBUGP("us_transfer_partial(): transfer complete\n");
 		return US_BULK_TRANSFER_GOOD;
 	}
 
@@ -186,7 +353,17 @@
 		/* NAK - that means we've retried a few times allready */
 		if (result == -ETIMEDOUT) {
 			US_DEBUGP("us_transfer_partial(): device NAKed\n");
+			return US_BULK_TRANSFER_FAILED;
 		}
+
+		/* -ENOENT -- we canceled this transfer */
+		if (result == -ENOENT) {
+			US_DEBUGP("us_transfer_partial(): transfer aborted\n");
+			return US_BULK_TRANSFER_ABORTED;
+		}
+
+		/* the catch-all case */
+		US_DEBUGP("us_transfer_partial(): unknown error\n");
 		return US_BULK_TRANSFER_FAILED;
 	}
 
@@ -203,21 +380,12 @@
  * function simply determines if we're going to use scatter-gather or not,
  * and acts appropriately.  For now, it also re-interprets the error codes.
  */
-static void us_transfer(Scsi_Cmnd *srb, int dir_in)
+static void us_transfer(Scsi_Cmnd *srb, struct us_data* us, int dir_in)
 {
-	struct us_data *us;
 	int i;
 	int result = -1;
-	unsigned int pipe;
 	struct scatterlist *sg;
 
-	/* calculate the appropriate pipe information */
-	us = (struct us_data*) srb->host_scribble;
-	if (dir_in)
-		pipe = usb_rcvbulkpipe(us->pusb_dev, us->ep_in);
-	else
-		pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
-
 	/* are we scatter-gathering? */
 	if (srb->use_sg) {
 
@@ -226,7 +394,7 @@
 		 */
 		sg = (struct scatterlist *) srb->request_buffer;
 		for (i = 0; i < srb->use_sg; i++) {
-			result = us_transfer_partial(us, pipe, sg[i].address, 
+			result = us_transfer_partial(us, sg[i].address, 
 						     sg[i].length);
 			if (result)
 				break;
@@ -234,7 +402,7 @@
 	}
 	else
 		/* no scatter-gather, just make the request */
-		result = us_transfer_partial(us, pipe, srb->request_buffer, 
+		result = us_transfer_partial(us, srb->request_buffer, 
 					     srb->request_bufflen);
 
 	/* return the result in the data structure itself */
@@ -433,6 +601,8 @@
 /*
  * Control/Bulk/Interrupt transport
  */
+
+/* The interrupt handler for CBI devices */
 static void CBI_irq(struct urb *urb)
 {
 	struct us_data *us = (struct us_data *)urb->context;
@@ -465,13 +635,13 @@
 
 	/* COMMAND STAGE */
 	/* let's send the command via the control pipe */
-	result = usb_control_msg(us->pusb_dev, 
-				 usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, 
-				 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
-				 us->ifnum, srb->cmnd, srb->cmd_len, HZ*5);
+	result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
+				      US_CBI_ADSC, 
+				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
+				      us->ifnum, srb->cmnd, srb->cmd_len);
 
 	/* check the return code for the command */
-	US_DEBUGP("Call to usb_control_msg() returned %d\n", result);
+	US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
 	if (result < 0) {
 		/* STALL must be cleared when they are detected */
 		if (result == -EPIPE) {
@@ -493,7 +663,7 @@
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (us_transfer_length(srb, us)) {
-		us_transfer(srb, US_DIRECTION(srb->cmnd[0]));
+		us_transfer(srb, us, US_DIRECTION(srb->cmnd[0]));
 		US_DEBUGP("CBI data stage result is 0x%x\n", srb->result);
 	}
 
@@ -561,15 +731,14 @@
 
 	/* COMMAND STAGE */
 	/* let's send the command via the control pipe */
-	result = usb_control_msg(us->pusb_dev, 
-				 usb_sndctrlpipe(us->pusb_dev,0), US_CBI_ADSC, 
-				 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
-				 us->ifnum, srb->cmnd, srb->cmd_len, HZ*5);
+	result = usb_stor_control_msg(us, usb_sndctrlpipe(us->pusb_dev,0),
+				      US_CBI_ADSC, 
+				      USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, 
+				      us->ifnum, srb->cmnd, srb->cmd_len);
 
 	/* check the return code for the command */
+	US_DEBUGP("Call to usb_stor_control_msg() returned %d\n", result);
 	if (result < 0) {
-		US_DEBUGP("Call to usb_control_msg() returned %d\n", result);
-
 		/* a stall is a fatal condition from the device */
 		if (result == -EPIPE) {
 			US_DEBUGP("-- Stall on control pipe. Clearing\n");
@@ -587,7 +756,7 @@
 	/* DATA STAGE */
 	/* transfer the data payload for this command, if one exists*/
 	if (us_transfer_length(srb, us)) {
-		us_transfer(srb, US_DIRECTION(srb->cmnd[0]));
+		us_transfer(srb, us, US_DIRECTION(srb->cmnd[0]));
 		US_DEBUGP("CB data stage result is 0x%x\n", srb->result);
 	}
 	
@@ -602,6 +771,39 @@
 /*
  * Bulk only transport
  */
+
+/* Determine what the maximum LUN supported is */
+static int Bulk_max_lun(struct us_data *us)
+{
+	unsigned char data;
+	int result;
+	int pipe;
+
+	/* issue the command */
+	pipe = usb_rcvctrlpipe(us->pusb_dev, 0);
+	result = usb_control_msg(us->pusb_dev, pipe,
+				 US_BULK_GET_MAX_LUN, 
+				 USB_DIR_IN | USB_TYPE_CLASS | 
+				 USB_RECIP_INTERFACE,
+				 0, us->ifnum, &data, sizeof(data), HZ);
+
+	US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
+		  result, data);
+
+	/* if we have a successful request, return the result */
+	if (!result)
+		return data;
+
+	/* if we get a STALL, clear the stall */
+	if (result == -EPIPE) {
+		US_DEBUGP("clearing endpoint halt for pipe 0x%x\n", pipe);
+		usb_clear_halt(us->pusb_dev, pipe);
+	}
+
+	/* return the default -- no LUNs */
+	return 0;
+}
+
 static int Bulk_transport(Scsi_Cmnd *srb, struct us_data *us)
 {
 	struct bulk_cb_wrap bcb;
@@ -629,8 +831,8 @@
 	US_DEBUGP("Bulk command S 0x%x T 0x%x LUN %d L %d F %d CL %d\n",
 		  le32_to_cpu(bcb.Signature), bcb.Tag, bcb.Lun, 
 		  bcb.DataTransferLength, bcb.Flags, bcb.Length);
-	result = usb_bulk_msg(us->pusb_dev, pipe, &bcb,
-			      US_BULK_CB_WRAP_LEN, &partial, HZ*5);
+	result = usb_stor_bulk_msg(us, &bcb, pipe, US_BULK_CB_WRAP_LEN, 
+				   &partial);
 	US_DEBUGP("Bulk command transfer result=%d\n", result);
 	
 	/* if we stall, we need to clear it before we go on */
@@ -643,7 +845,7 @@
 	if (result == 0) {
 		/* send/receive data payload, if there is any */
 		if (bcb.DataTransferLength) {
-			us_transfer(srb, bcb.Flags);
+			us_transfer(srb, us, bcb.Flags);
 			US_DEBUGP("Bulk data transfer result 0x%x\n", 
 				  srb->result);
 		}
@@ -658,8 +860,8 @@
 	
 	/* get CSW for device status */
 	US_DEBUGP("Attempting to get CSW...\n");
-	result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
-			      US_BULK_CS_WRAP_LEN, &partial, HZ*2);
+	result = usb_stor_bulk_msg(us, &bcs, pipe, US_BULK_CS_WRAP_LEN, 
+				   &partial);
 	
 	/* did the attempt to read the CSW fail? */
 	if (result == -EPIPE) {
@@ -668,8 +870,8 @@
 	       
 		/* get the status again */
 		US_DEBUGP("Attempting to get CSW (2nd try)...\n");
-		result = usb_bulk_msg(us->pusb_dev, pipe, &bcs,
-				      US_BULK_CS_WRAP_LEN, &partial, HZ*2);
+		result = usb_stor_bulk_msg(us, &bcs, pipe,
+					   US_BULK_CS_WRAP_LEN, &partial);
 		
 		/* if it fails again, we need a reset and return an error*/
 		if (result == -EPIPE) {
@@ -1025,9 +1227,9 @@
 
 	result = usb_control_msg(us->pusb_dev, 
 				 usb_sndctrlpipe(us->pusb_dev,0), 
-				 US_BULK_RESET, 
+				 US_BULK_RESET_REQUEST, 
 				 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-				 US_BULK_RESET_HARD, us->ifnum, NULL, 0, HZ*5);
+				 0, us->ifnum, NULL, 0, HZ*5);
 
 	if (result < 0)
 		US_DEBUGP("Bulk hard reset failed %d\n", result);
@@ -1049,7 +1251,7 @@
 
 static const char* us_info(struct Scsi_Host *host)
 {
-	return "SCSI emulation for USB Mass Storage devices\n";
+	return "SCSI emulation for USB Mass Storage devices";
 }
 
 /* detect a virtual adapter (always works) */
@@ -1109,6 +1311,7 @@
 	
 	/* free the data structure we were using */
 	US_DEBUGP("-- freeing private host data structure\n");
+	kfree(us->current_urb);
 	kfree(us);
 	(struct us_data*)psh->hostdata[0] = NULL;
 
@@ -1289,22 +1492,11 @@
 };
 
 static unsigned char sense_notready[] = {
-	0x70,			    /* current error */
-	0x00,
-	0x02,			    /* not ready */
-	0x00,
-	0x00,
-	0x0a,			    /* additional length */
-	0x00,
-	0x00,
-	0x00,
-	0x00,
-	0x04,			    /* not ready */
-	0x03,			    /* manual intervention */
-	0x00,
-	0x00,
-	0x00,
-	0x00
+	[0]	= 0x70,			    /* current error */
+	[2]	= 0x02,			    /* not ready */
+	[5]	= 0x0a,			    /* additional length */
+	[10]	= 0x04,			    /* not ready */
+	[11]	= 0x03			    /* manual intervention */
 };
 
 static int usb_stor_control_thread(void * __us)
@@ -1429,25 +1621,31 @@
 	return 0;
 }	
 
+/* This is the list of devices we recognize, along with their flag data */
 static struct us_unusual_dev us_unusual_dev_list[] = {
+	{ 0x03f0, 0x0107, 0x0200,
+	  "HP USB CD-Writer Plus", US_SC_8070, US_PR_CB, 0}, 
+	{ 0x04e6, 0x0001, 0x0200,
+	  "Matshita LS-120", US_SC_8020, US_PR_CB, US_FL_SINGLE_LUN},
+	{ 0x04e6, 0x0002, 0x0100,
+	  "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
+	{ 0x04e6, 0x0006, 0x0100,
+	  "Shuttle eUSB MMC Adapter", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, 
 	{ 0x057b, 0x0000, 0x0114,
-	  "Y-E Data Flashbuster-U", US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN },
+	  "Y-E Data Flashbuster-U", US_SC_UFI, US_PR_CB, US_FL_SINGLE_LUN},
 	{ 0x059b, 0x0030, 0x0100,
-	  "Iomega Zip 250", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN },
+	  "Iomega Zip 250", US_SC_SCSI, US_PR_BULK, US_FL_SINGLE_LUN},
+	{ 0x0693, 0x0002, 0x0100,
+	  "Hagiwara FlashGate SmartMedia", US_SC_SCSI, US_PR_BULK,
+	  US_FL_ALT_LENGTH},
 	{ 0x0781, 0x0001, 0x0200,
-	  "Sandisk ImageMate (w/eject button)", US_SC_SCSI, US_PR_CB, 
-	  US_FL_SINGLE_LUN | US_FL_START_STOP },
+	  "Sandisk ImageMate (SDDR-01)", US_SC_SCSI, US_PR_CB, 
+	  US_FL_SINGLE_LUN | US_FL_START_STOP},
 	{ 0x0781, 0x0002, 0x0009,
-	  "** SECRET DEVICE **", US_SC_SCSI, US_PR_BULK, 
-	  US_FL_SINGLE_LUN | US_FL_IGNORE_SER },
+	  "Sandisk Imagemate (SDDR-31)", US_SC_SCSI, US_PR_BULK, 
+	  US_FL_SINGLE_LUN | US_FL_IGNORE_SER},
 	{ 0x07af, 0x0005, 0x0100,
 	  "Microtech USB-SCSI-HD50", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
-	{ 0x04e6, 0x0002, 0x0100,
-	  "Shuttle eUSCSI Bridge", US_SC_SCSI, US_PR_BULK, US_FL_ALT_LENGTH}, 
-	{ 0x04e6, 0x0006, 0x0100,
-	  "Shuttle eUSB MMC Adapter", US_SC_SCSI, US_PR_CB, US_FL_SINGLE_LUN}, 
-	{ 0x03f0, 0x0107, 0x0200,
-	  "HP USB CD-Writer Plus", US_SC_8070, US_PR_CB, 0}, 
 	{ 0x0000, 0x0000, 0x0,
 	  "", 0, 0, 0}
 };
@@ -1713,12 +1911,20 @@
 		}
 		memset(ss, 0, sizeof(struct us_data));
 
+		/* allocate the URB we're going to use */
+		ss->current_urb = usb_alloc_urb(0);
+		if (!ss->current_urb) {
+			kfree(ss);
+			return NULL;
+		}
+
 		/* Initialize the mutexes only when the struct is new */
 		init_MUTEX_LOCKED(&(ss->sleeper));
 		init_MUTEX_LOCKED(&(ss->notify));
 		init_MUTEX_LOCKED(&(ss->ip_waitq));
 		init_MUTEX(&(ss->queue_exclusion));
 		init_MUTEX(&(ss->irq_urb_sem));
+		init_MUTEX(&(ss->current_urb_sem));
 		init_MUTEX(&(ss->dev_semaphore));
 
 		/* copy over the subclass and protocol data */
@@ -1774,11 +1980,14 @@
 			ss->transport_name = "Bulk";
 			ss->transport = Bulk_transport;
 			ss->transport_reset = Bulk_reset;
+			/* FIXME: for testing purposes only */
+			Bulk_max_lun(ss);
 			break;
 			
 		default:
 			ss->transport_name = "Unknown";
 			up(&us_list_semaphore);
+			kfree(ss->current_urb);
 			kfree(ss);
 			return NULL;
 			break;
@@ -1802,6 +2011,7 @@
 			US_DEBUGP("contact mdharm-usb@one-eyed-alien.net\n");
 			US_DEBUGP("if you see this message.\n");
 			up(&us_list_semaphore);
+			kfree(ss->current_urb);
 			kfree(ss);
 			return NULL;
 			break;
@@ -1824,6 +2034,7 @@
 		default:
 			ss->protocol_name = "Unknown";
 			up(&us_list_semaphore);
+			kfree(ss->current_urb);
 			kfree(ss);
 			return NULL;
 			break;
@@ -1859,6 +2070,7 @@
 		if (ss->pid < 0) {
 			printk(KERN_WARNING USB_STORAGE 
 			       "Unable to start control thread\n");
+			kfree(ss->current_urb);
 			kfree(ss);
 			return NULL;
 		}
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-storage.h linux/drivers/usb/usb-storage.h
--- v2.3.99-pre8/linux/drivers/usb/usb-storage.h	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/usb-storage.h	Sat May 20 10:18:21 2000
@@ -77,16 +77,17 @@
 #define US_BULK_STAT_FAIL	1
 #define US_BULK_STAT_PHASE	2
 
-#define US_BULK_RESET		0xff
-#define US_BULK_RESET_SOFT	1
-#define US_BULK_RESET_HARD	0
+/* bulk-only class specific requests */
+#define US_BULK_RESET_REQUEST	0xff
+#define US_BULK_GET_MAX_LUN	0xfe
 
 /*
  * us_bulk_transfer() return codes
  */
-#define US_BULK_TRANSFER_GOOD	0
-#define US_BULK_TRANSFER_SHORT	1
-#define US_BULK_TRANSFER_FAILED 2
+#define US_BULK_TRANSFER_GOOD		0  /* good transfer                 */
+#define US_BULK_TRANSFER_SHORT		1  /* transfered less than expected */
+#define US_BULK_TRANSFER_FAILED		2  /* transfer died in the middle   */
+#define US_BULK_TRANSFER_ABORTED	3  /* transfer canceled             */
 
 /*
  * Transport return codes
@@ -95,6 +96,7 @@
 #define USB_STOR_TRANSPORT_GOOD	   0   /* Transport good, command good	   */
 #define USB_STOR_TRANSPORT_FAILED  1   /* Transport good, command failed   */
 #define USB_STOR_TRANSPORT_ERROR   2   /* Transport bad (i.e. device dead) */
+#define USB_STOR_TRANSPORT_ABORTED 3   /* Transport aborted                */
 
 /*
  * CBI accept device specific command
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- v2.3.99-pre8/linux/drivers/usb/usb-uhci.c	Thu May 11 15:30:08 2000
+++ linux/drivers/usb/usb-uhci.c	Mon May 15 12:05:15 2000
@@ -12,7 +12,7 @@
  * (C) Copyright 1999 Johannes Erdfelt
  * (C) Copyright 1999 Randy Dunlap
  *
- * $Id: usb-uhci.c,v 1.228 2000/04/02 19:55:51 acher Exp $
+ * $Id: usb-uhci.c,v 1.231 2000/05/13 15:34:17 acher Exp $
  */
 
 #include <linux/config.h>
@@ -48,7 +48,7 @@
 /* This enables an extra UHCI slab for memory debugging */
 #define DEBUG_SLAB
 
-#define VERSTR "$Revision: 1.228 $ time " __TIME__ " " __DATE__
+#define VERSTR "$Revision: 1.231 $ time " __TIME__ " " __DATE__
 
 #include <linux/usb.h>
 #include "usb-uhci.h"
@@ -109,10 +109,10 @@
 
 	while (q != &s->free_desc) {
 		qh = list_entry (q, uhci_desc_t, horizontal);
+		q=qh->horizontal.prev;
+
 		if ((qh->last_used!=now) || force)
 			delete_qh(s,qh);
-
-		q=qh->horizontal.prev;
 	}
 }
 /*-------------------------------------------------------------------*/
@@ -1142,6 +1142,12 @@
 
 			if (!(urb->transfer_flags & USB_TIMEOUT_KILLED))
 				urb->status = -ENOENT;  // now the urb is really dead
+			switch (usb_pipetype (pipe)) {
+			case PIPE_ISOCHRONOUS:
+			case PIPE_INTERRUPT:
+				uhci_clean_iso_step2(s, urb_priv);
+				break;
+			}
 	
 			usb_dec_dev_use (dev);
 #ifdef DEBUG_SLAB
@@ -1149,12 +1155,7 @@
 #else
 			kfree (urb_priv);
 #endif
-			switch (usb_pipetype (pipe)) {
-			case PIPE_ISOCHRONOUS:
-			case PIPE_INTERRUPT:
-				uhci_clean_iso_step2(s, urb_priv);
-				break;
-			}
+
 			list_del (&urb->urb_list);
 		}
 	}
@@ -1168,7 +1169,9 @@
 	
 	async_dbg("unlink_urb_async called %p",urb);
 
-	if (urb->status == -EINPROGRESS) {
+	if ((urb->status == -EINPROGRESS) ||
+	    ((usb_pipetype (urb->pipe) ==  PIPE_INTERRUPT) && ((urb_priv_t*)urb->hcpriv)->flags))
+	{
 		((urb_priv_t*)urb->hcpriv)->started = ~0;
 
 		dequeue_urb (s, urb);
@@ -1560,7 +1563,7 @@
 
 	urb->hcpriv = urb_priv;
 	INIT_LIST_HEAD (&urb_priv->desc_list);
-	urb_priv->short_control_packet = 0;
+	urb_priv->flags = 0;
 	dbg("submit_urb: scheduling %p", urb);
 	urb_priv->next_queued_urb = NULL;
 	urb_priv->prev_queued_urb = NULL;
@@ -2151,7 +2154,7 @@
 	   status stage is completed
 	 */
 
-	if (urb_priv->short_control_packet && 
+	if (urb_priv->flags && 
 		((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE)))) 
 		goto transfer_finished;
 
@@ -2199,7 +2202,7 @@
 					dbg("short packet during control transfer, retrigger status stage @ %p",last_desc);
 					//uhci_show_td (desc);
 					//uhci_show_td (last_desc);
-					urb_priv->short_control_packet=1;
+					urb_priv->flags = 1; // mark as short control packet
 					return 0;
 				}
 			}
@@ -2280,35 +2283,43 @@
 		if (urb->complete) {
 			//dbg("process_interrupt: calling completion, status %i",status);
 			urb->status = status;
-			
+			((urb_priv_t*)urb->hcpriv)->flags=1; // if unlink_urb is called during completion
+
 			spin_unlock(&s->urb_list_lock);
 			
 			urb->complete ((struct urb *) urb);
 			
 			spin_lock(&s->urb_list_lock);
-			
-			urb->status = -EINPROGRESS;
+
+			((urb_priv_t*)urb->hcpriv)->flags=0;		       			
 		}
+		
+		if ((urb->status != -ECONNABORTED) && (urb->status != ECONNRESET) &&
+			    (urb->status != -ENOENT)) {
 
-		// Recycle INT-TD if interval!=0, else mark TD as one-shot
-		if (urb->interval) {
+			urb->status = -EINPROGRESS;
 
-			desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE);
-			if (status==0) {
-				((urb_priv_t*)urb->hcpriv)->started=jiffies;
-				desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-				      usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
-				usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
-			} else {
-				desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-				      usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+			// Recycle INT-TD if interval!=0, else mark TD as one-shot
+			if (urb->interval) {
+				
+				desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE);
+				if (status==0) {
+					((urb_priv_t*)urb->hcpriv)->started=jiffies;
+					desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+					usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
+				} else {
+					desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+				}
+				desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+				mb();
+			}
+			else {
+				uhci_unlink_urb_async(s, urb);
+				desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
 			}
-			desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
-				(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
-			mb();
-		}
-		else {
-			desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
 		}
 	}
 
@@ -2334,7 +2345,7 @@
 	dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s),
 	    urb->number_of_packets,mode,desc->hw.td.status);
 
-	for (i = 0; p != &urb_priv->desc_list; p = p->next, i++) {
+	for (i = 0; p != &urb_priv->desc_list;  i++) {
 		desc = list_entry (p, uhci_desc_t, desc_list);
 		
 		//uhci_show_td(desc);
@@ -2378,8 +2389,9 @@
 		dbg("process_iso: %i: len:%d %08x status:%x",
 		     i, urb->iso_frame_desc[i].actual_length, desc->hw.td.status,urb->iso_frame_desc[i].status);
 
-		delete_desc (desc);
 		list_del (p);
+		p = p->next;
+		delete_desc (desc);
 	}
 	
 	dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length);
@@ -2823,7 +2835,6 @@
 		pci_read_config_byte (dev, PCI_CLASS_PROG, &type);
 		if (type != 0)
 			continue;
-
 
 		if (pci_enable_device (dev) < 0)
 			continue;
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h
--- v2.3.99-pre8/linux/drivers/usb/usb-uhci.h	Tue Apr 11 15:09:20 2000
+++ linux/drivers/usb/usb-uhci.h	Mon May 15 12:05:15 2000
@@ -2,7 +2,7 @@
 #define __LINUX_UHCI_H
 
 /*
-   $Id: usb-uhci.h,v 1.54 2000/04/02 19:55:53 acher Exp $
+   $Id: usb-uhci.h,v 1.55 2000/05/13 12:50:30 acher Exp $
  */
 #define MODNAME "usb-uhci"
 #define UHCI_LATENCY_TIMER 0
@@ -160,7 +160,7 @@
 	uhci_desc_t *bottom_qh;
 	uhci_desc_t *next_qh;       	// next helper QH
 	char use_loop;
-	char short_control_packet;
+	char flags;
 } urb_priv_t, *purb_priv_t;
 
 struct virt_root_hub {
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c
--- v2.3.99-pre8/linux/drivers/usb/wacom.c	Mon Mar 27 08:08:28 2000
+++ linux/drivers/usb/wacom.c	Sat May 20 11:24:15 2000
@@ -104,8 +104,8 @@
 	int distance_max;
 	void (*irq)(struct urb *urb);
 	unsigned long evbit;
-	unsigned long relbit;
 	unsigned long absbit;
+	unsigned long relbit;
 	unsigned long btnbit;
 	unsigned long digibit;
 };
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.3.99-pre8/linux/drivers/video/cyber2000fb.c	Fri May 12 14:18:55 2000
+++ linux/drivers/video/cyber2000fb.c	Mon May 15 12:00:33 2000
@@ -1636,3 +1636,5 @@
 module_init(cyber2000fb_init);
 #endif
 module_exit(cyberpro_exit);
+
+MODULE_DEVICE_TABLE(pci, cyberpro_pci_table);
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/video/cyber2000fb.h linux/drivers/video/cyber2000fb.h
--- v2.3.99-pre8/linux/drivers/video/cyber2000fb.h	Fri May 12 14:18:55 2000
+++ linux/drivers/video/cyber2000fb.h	Mon May 15 12:10:26 2000
@@ -3,6 +3,7 @@
  *
  * Integraphics Cyber2000 frame buffer device
  */
+#include <linux/config.h>
 
 #define cyber2000_outb(dat,reg)	writeb(dat, CyberRegs + reg)
 #define cyber2000_outw(dat,reg)	writew(dat, CyberRegs + reg)
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/video/newport_con.c linux/drivers/video/newport_con.c
--- v2.3.99-pre8/linux/drivers/video/newport_con.c	Tue Aug 31 17:29:14 1999
+++ linux/drivers/video/newport_con.c	Sat May 13 08:33:26 2000
@@ -1,9 +1,9 @@
-/* $Id: newport_con.c,v 1.13 1999/04/11 10:37:08 ulfc Exp $
+/* $Id: newport_con.c,v 1.14 1999/06/24 01:10:24 ulfc Exp $
  *
  * newport_con.c: Abscon for newport hardware
  * 
  * (C) 1998 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- * (C) 1999 Ulf Carlsson (ulfc@bun.falkenberg.se)
+ * (C) 1999 Ulf Carlsson (ulfc@thepuffingruop.com)
  * 
  * This driver is based on sgicons.c and cons_newport.
  * 
@@ -26,14 +26,19 @@
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/newport.h>
+#include <video/newport.h>
 #define INCLUDE_LINUX_LOGO_DATA
 #include <asm/linux_logo.h>
 
+#include <video/font.h>
+
 #define LOGO_W		80
 #define LOGO_H		80
 
-extern unsigned char vga_font[];
+extern struct fbcon_font_desc font_vga_8x16;
+
+#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
+
 extern struct newport_regs *npregs;
 
 static int logo_active;
@@ -148,9 +153,9 @@
     for(i = 0; i < 128; i++) {
 	newport_bfwait();
 	if (i == 92 || i == 94)
-	    npregs->set.dcbdata0.hwords.s1 = 0xff00;
+	    npregs->set.dcbdata0.byshort.s1 = 0xff00;
 	else
-	    npregs->set.dcbdata0.hwords.s1 = 0x0000;
+	    npregs->set.dcbdata0.byshort.s1 = 0x0000;
     }
 
     newport_init_cmap();
@@ -158,10 +163,10 @@
     /* turn off popup plane */
     npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL |
                            XM9_CRS_CONFIG | NPORT_DMODE_W1);
-    npregs->set.dcbdata0.bytes.b3 &= ~XM9_PUPMODE;
+    npregs->set.dcbdata0.bybytes.b3 &= ~XM9_PUPMODE;
     npregs->set.dcbmode = (DCB_XMAP1 | R_DCB_XMAP9_PROTOCOL |
                            XM9_CRS_CONFIG | NPORT_DMODE_W1);
-    npregs->set.dcbdata0.bytes.b3 &= ~XM9_PUPMODE;
+    npregs->set.dcbdata0.bybytes.b3 &= ~XM9_PUPMODE;
     
     topscan = 0;
     npregs->cset.topscan = 0x3ff;
@@ -187,7 +192,7 @@
 			   NPORT_DMODE_W2 | VC2_PROTOCOL);
     for(i = 0; i < 128; i++) {
 	newport_bfwait();
-	linetable[i] = npregs->set.dcbdata0.hwords.s1;
+	linetable[i] = npregs->set.dcbdata0.byshort.s1;
     }
 
     newport_xsize = newport_ysize = 0;
@@ -198,12 +203,12 @@
 			       NPORT_DMODE_W2 | VC2_PROTOCOL);
 	do {
 	    newport_bfwait();
-	    treg = npregs->set.dcbdata0.hwords.s1;
+	    treg = npregs->set.dcbdata0.byshort.s1;
 	    if ((treg & 1) == 0)
 		cols += (treg >> 7) & 0xfe;
 	    if ((treg & 0x80) == 0) {
 		newport_bfwait();
-		treg = npregs->set.dcbdata0.hwords.s1;
+		treg = npregs->set.dcbdata0.byshort.s1;
 	    } 
 	} while ((treg & 0x8000) == 0);
 	if (cols) {
@@ -226,18 +231,18 @@
     unsigned int bt445_rev;
     unsigned int bitplanes;
 
-    rex3_rev = npregs->cset.stat & NPORT_STAT_VERS;
+    rex3_rev = npregs->cset.status & NPORT_STAT_VERS;
 
     npregs->set.dcbmode = (DCB_CMAP0 | NCMAP_PROTOCOL |
                            NCMAP_REGADDR_RREG | NPORT_DMODE_W1);
-    tmp = npregs->set.dcbdata0.bytes.b3;
+    tmp = npregs->set.dcbdata0.bybytes.b3;
     cmap_rev = tmp & 7;
     board_rev = (tmp >> 4) & 7;
     bitplanes = ((board_rev > 1) && (tmp & 0x80)) ? 8 : 24; 
 
     npregs->set.dcbmode = (DCB_CMAP1 | NCMAP_PROTOCOL |
                            NCMAP_REGADDR_RREG | NPORT_DMODE_W1);
-    tmp = npregs->set.dcbdata0.bytes.b3;
+    tmp = npregs->set.dcbdata0.bybytes.b3;
     if ((tmp & 7) < cmap_rev)
 	cmap_rev = (tmp & 7);
 
@@ -245,14 +250,14 @@
 
     npregs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL |
                            XM9_CRS_REVISION | NPORT_DMODE_W1);
-    xmap9_rev = npregs->set.dcbdata0.bytes.b3 & 7;
+    xmap9_rev = npregs->set.dcbdata0.bybytes.b3 & 7;
 
     npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL |
                            BT445_CSR_ADDR_REG | NPORT_DMODE_W1);
-    npregs->set.dcbdata0.bytes.b3 = BT445_REVISION_REG;
+    npregs->set.dcbdata0.bybytes.b3 = BT445_REVISION_REG;
     npregs->set.dcbmode = (DCB_BT445 | BT445_PROTOCOL |
                            BT445_CSR_REVISION | NPORT_DMODE_W1);
-    bt445_rev = (npregs->set.dcbdata0.bytes.b3 >> 4) - 0x0a;
+    bt445_rev = (npregs->set.dcbdata0.bybytes.b3 >> 4) - 0x0a;
 
 #define L(a)     (char)('A'+(a))
     printk ("NG1: Revision %d, %d bitplanes, REX3 revision %c, VC2 revision %c, xmap9 revision %c, cmap revision %c, bt445 revision %c\n",
@@ -281,7 +286,7 @@
 	return NULL;
     }
 
-    p->set.xstarti = TESTVAL; if(p->set._xstart.i != XSTI_TO_FXSTART(TESTVAL)) {
+    p->set.xstarti = TESTVAL; if(p->set._xstart.word != XSTI_TO_FXSTART(TESTVAL)) {
 	return NULL;
     }
 
@@ -325,7 +330,7 @@
 {
     unsigned char *p;
     
-    p = &vga_font[(charattr & 0xff) << 4];
+    p = &FONT_DATA[(charattr & 0xff) << 4];
     charattr = (charattr >> 8) & 0xff;
     xpos <<= 3;
     ypos <<= 4;
@@ -374,7 +379,7 @@
 			     NPORT_DMODE0_L32);
     
     for (i = 0; i < count; i++, xpos += 8) {
-	p = &vga_font[(s[i] & 0xff) << 4];
+	p = &FONT_DATA[(s[i] & 0xff) << 4];
 
 	newport_wait();
 
diff -u --recursive --new-file v2.3.99-pre8/linux/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- v2.3.99-pre8/linux/drivers/video/riva/fbdev.c	Wed Apr 26 16:34:08 2000
+++ linux/drivers/video/riva/fbdev.c	Mon May 22 09:50:55 2000
@@ -69,7 +69,7 @@
 	if(!(expr)) { \
         printk( "Assertion failed! %s,%s,%s,line=%d\n",\
         #expr,__FILE__,__FUNCTION__,__LINE__); \
-	*(int*)0 = 0; \
+	BUG(); \
         }
 #else
 #define assert(expr)
@@ -127,7 +127,7 @@
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
-	{ 0, }, /* terminate list */
+	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/Makefile linux/fs/Makefile
--- v2.3.99-pre8/linux/fs/Makefile	Tue Apr 11 15:09:21 2000
+++ linux/fs/Makefile	Mon May 15 13:54:04 2000
@@ -21,7 +21,7 @@
 		nfsd nls devpts devfs adfs partitions qnx4 udf bfs cramfs \
 		openpromfs autofs4 ramfs
 
-SUB_DIRS := partitions
+SUB_DIRS :=
 
 ifeq ($(CONFIG_QUOTA),y)
 O_OBJS += dquot.o
@@ -29,6 +29,14 @@
 O_OBJS += noquot.o
 endif
 
+ifdef CONFIG_PROC_FS
+SUB_DIRS += proc
+endif
+
+SUB_DIRS += partitions
+
+# Do not add any filesystems before this line
+
 ifeq ($(CONFIG_EXT2_FS),y)
 SUB_DIRS += ext2
 else
@@ -91,10 +99,6 @@
   ifeq ($(CONFIG_VFAT_FS),m)
   MOD_SUB_DIRS += vfat
   endif
-endif
-
-ifdef CONFIG_PROC_FS
-SUB_DIRS += proc
 endif
 
 ifeq ($(CONFIG_BFS_FS),y)
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.3.99-pre8/linux/fs/affs/namei.c	Fri Mar 10 16:40:46 2000
+++ linux/fs/affs/namei.c	Sat May 20 10:55:25 2000
@@ -249,7 +249,6 @@
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->i_version = ++event;
 	mark_inode_dirty(inode);
-	d_delete(dentry);
 	mark_inode_dirty(dir);
 	retval = 0;
 
@@ -380,7 +379,6 @@
 	dir->i_version = ++event;
 	mark_inode_dirty(dir);
 	mark_inode_dirty(inode);
-	d_delete(dentry);
 
 rmdir_done:
 	affs_brelse(bh);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/autofs/dir.c linux/fs/autofs/dir.c
--- v2.3.99-pre8/linux/fs/autofs/dir.c	Sat Feb 26 22:31:51 2000
+++ linux/fs/autofs/dir.c	Sat May 20 10:55:26 2000
@@ -12,29 +12,10 @@
 
 #include "autofs_i.h"
 
-static int autofs_dir_readdir(struct file *filp,
-			       void *dirent, filldir_t filldir)
-{
-	struct inode *inode=filp->f_dentry->d_inode;
-
-	switch((unsigned long) filp->f_pos)
-	{
-	case 0:
-		if (filldir(dirent, ".", 1, 0, inode->i_ino) < 0)
-			return 0;
-		filp->f_pos++;
-		/* fall through */
-	case 1:
-		if (filldir(dirent, "..", 2, 1, AUTOFS_ROOT_INO) < 0)
-			return 0;
-		filp->f_pos++;
-		/* fall through */
-	}
-	return 1;
-}
-
 /*
- * No entries except for "." and "..", both of which are handled by the VFS layer
+ * No entries except for "." and "..", both of which are handled by the VFS
+ * layer. So all children are negative and dcache-based versions of operations
+ * are OK.
  */
 static struct dentry *autofs_dir_lookup(struct inode *dir,struct dentry *dentry)
 {
@@ -44,7 +25,7 @@
 
 struct file_operations autofs_dir_operations = {
 	read:		generic_read_dir,
-	readdir:	autofs_dir_readdir,
+	readdir:	dcache_readdir,
 };
 
 struct inode_operations autofs_dir_inode_operations = {
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/autofs/dirhash.c linux/fs/autofs/dirhash.c
--- v2.3.99-pre8/linux/fs/autofs/dirhash.c	Thu May 11 15:30:08 2000
+++ linux/fs/autofs/dirhash.c	Sat May 20 10:55:26 2000
@@ -133,8 +133,8 @@
 	autofs_say(ent->name,ent->len);
 
 	autofs_init_usage(dh,ent);
-	if ( ent->dentry )
-		ent->dentry->d_count++;
+	if (ent->dentry)
+		dget(ent->dentry);
 
 	dhnp = &dh->h[(unsigned) ent->hash % AUTOFS_HASH_SIZE];
 	ent->next = *dhnp;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/autofs4/root.c linux/fs/autofs4/root.c
--- v2.3.99-pre8/linux/fs/autofs4/root.c	Thu May 11 15:30:08 2000
+++ linux/fs/autofs4/root.c	Sat May 20 10:55:26 2000
@@ -16,7 +16,6 @@
 #include <linux/param.h>
 #include "autofs_i.h"
 
-static int autofs4_dir_readdir(struct file *,void *,filldir_t);
 static struct dentry *autofs4_dir_lookup(struct inode *,struct dentry *);
 static int autofs4_dir_symlink(struct inode *,struct dentry *,const char *);
 static int autofs4_dir_unlink(struct inode *,struct dentry *);
@@ -27,13 +26,13 @@
 
 struct file_operations autofs4_root_operations = {
 	read:		generic_read_dir,
-	readdir:	autofs4_dir_readdir,
+	readdir:	dcache_readdir,
 	ioctl:		autofs4_root_ioctl,
 };
 
 struct file_operations autofs4_dir_operations = {
 	read:		generic_read_dir,
-	readdir:	autofs4_dir_readdir,
+	readdir:	dcache_readdir,
 };
 
 struct inode_operations autofs4_root_inode_operations = {
@@ -51,67 +50,6 @@
 	mkdir:		autofs4_dir_mkdir,
 	rmdir:		autofs4_dir_rmdir,
 };
-
-static inline struct dentry *nth_child(struct dentry *dir, int nr)
-{
-	struct list_head *tmp = dir->d_subdirs.next;
-
-	while(tmp != &dir->d_subdirs) {
-		if (nr-- == 0)
-			return list_entry(tmp, struct dentry, d_child);
-		tmp = tmp->next;
-	}
-	return NULL;
-}
-
-static int autofs4_dir_readdir(struct file *filp, void *dirent,
-			      filldir_t filldir)
-{
-	struct autofs_sb_info *sbi;
-	struct autofs_info *ino;
-	struct dentry *dentry = filp->f_dentry;
-	struct dentry *dent_ptr;
-	struct inode *dir = dentry->d_inode;
-	struct list_head *cursor;
-	off_t nr;
-
-	sbi = autofs4_sbi(dir->i_sb);
-	ino = autofs4_dentry_ino(dentry);
-	nr = filp->f_pos;
-
-	switch(nr)
-	{
-	case 0:
-		if (filldir(dirent, ".", 1, nr, dir->i_ino) < 0)
-			return 0;
-		filp->f_pos = ++nr;
-		/* fall through */
-	case 1:
-		if (filldir(dirent, "..", 2, nr, dentry->d_parent->d_inode->i_ino) < 0)
-			return 0;
-		filp->f_pos = ++nr;
-		/* fall through */
-	default:
-		dent_ptr = nth_child(dentry, nr-2);
-		if (dent_ptr == NULL)
-			break;
-
-		cursor = &dent_ptr->d_child;
-
-		while(cursor != &dentry->d_subdirs) {
-			dent_ptr = list_entry(cursor, struct dentry, d_child);
-			if (dent_ptr->d_inode &&
-			    filldir(dirent, dent_ptr->d_name.name, dent_ptr->d_name.len, nr,
-				    dent_ptr->d_inode->i_ino) < 0)
-				return 0;
-			filp->f_pos = ++nr;
-			cursor = cursor->next;
-		}
-		break;
-	}
-
-	return 0;
-}
 
 /* Update usage from here to top of tree, so that scan of
    top-level directories will give a useful result */
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/bfs/dir.c linux/fs/bfs/dir.c
--- v2.3.99-pre8/linux/fs/bfs/dir.c	Fri Mar 10 16:40:46 2000
+++ linux/fs/bfs/dir.c	Sat May 20 10:55:26 2000
@@ -32,11 +32,6 @@
 	unsigned int offset;
 	int block;
 
-	if (!dir || !dir->i_sb || !S_ISDIR(dir->i_mode)) {
-		printf("Bad inode or not a directory %s:%08lx\n", bdevname(dev), dir->i_ino);
-		return -EBADF;
-	}
-
 	if (f->f_pos & (BFS_DIRENT_SIZE-1)) {
 		printf("Bad f_pos=%08lx for %s:%08lx\n", (unsigned long)f->f_pos, 
 			bdevname(dev), dir->i_ino);
@@ -188,7 +183,6 @@
 	inode->i_nlink--;
 	inode->i_ctime = dir->i_ctime;
 	mark_inode_dirty(inode);
-	d_delete(dentry);
 	error = 0;
 
 out_brelse:
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.3.99-pre8/linux/fs/binfmt_aout.c	Thu May 11 15:30:08 2000
+++ linux/fs/binfmt_aout.c	Mon May 15 12:00:34 2000
@@ -86,6 +86,8 @@
 	struct user dump;
 #if defined(__alpha__)
 #       define START_DATA(u)	(u.start_data)
+#elif defined(__arm__)
+#	define START_DATA(u)	((u.u_tsize << PAGE_SHIFT) + u.start_code)
 #elif defined(__sparc__)
 #       define START_DATA(u)    (u.u_tsize)
 #elif defined(__i386__) || defined(__mc68000__)
@@ -217,7 +219,7 @@
 	envp = (char **) sp;
 	sp -= argc+1;
 	argv = (char **) sp;
-#if defined(__i386__) || defined(__mc68000__)
+#if defined(__i386__) || defined(__mc68000__) || defined(__arm__)
 	put_user((unsigned long) envp,--sp);
 	put_user((unsigned long) argv,--sp);
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/buffer.c linux/fs/buffer.c
--- v2.3.99-pre8/linux/fs/buffer.c	Fri May 12 14:18:55 2000
+++ linux/fs/buffer.c	Sat May 20 10:00:57 2000
@@ -1324,7 +1324,7 @@
 	 * instead.
 	 */
 	if (!offset) {
-		if (!try_to_free_buffers(page)) {
+		if (!try_to_free_buffers(page, 0)) {
 			atomic_inc(&buffermem_pages);
 			return 0;
 		}
@@ -2121,15 +2121,17 @@
  * This all is required so that we can free up memory
  * later.
  */
-static void sync_page_buffers(struct buffer_head *bh)
+static void sync_page_buffers(struct buffer_head *bh, int wait)
 {
-	struct buffer_head * tmp;
+	struct buffer_head * tmp = bh;
 
-	tmp = bh;
 	do {
 		struct buffer_head *p = tmp;
 		tmp = tmp->b_this_page;
-		if (buffer_dirty(p) && !buffer_locked(p))
+		if (buffer_locked(p)) {
+			if (wait)
+				__wait_on_buffer(p);
+		} else if (buffer_dirty(p))
 			ll_rw_block(WRITE, 1, &p);
 	} while (tmp != bh);
 }
@@ -2151,7 +2153,7 @@
  *       obtain a reference to a buffer head within a page.  So we must
  *	 lock out all of these paths to cleanly toss the page.
  */
-int try_to_free_buffers(struct page * page)
+int try_to_free_buffers(struct page * page, int wait)
 {
 	struct buffer_head * tmp, * bh = page->buffers;
 	int index = BUFSIZE_INDEX(bh->b_size);
@@ -2201,7 +2203,7 @@
 	spin_unlock(&free_list[index].lock);
 	write_unlock(&hash_table_lock);
 	spin_unlock(&lru_list_lock);	
-	sync_page_buffers(bh);
+	sync_page_buffers(bh, wait);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/coda/cache.c linux/fs/coda/cache.c
--- v2.3.99-pre8/linux/fs/coda/cache.c	Thu Aug 26 13:05:40 1999
+++ linux/fs/coda/cache.c	Sun May 21 20:34:37 2000
@@ -259,8 +259,6 @@
 
 void coda_purge_dentries(struct inode *inode)
 {
-	struct list_head *tmp, *head = &inode->i_dentry;
-
 	if (!inode)
 		return ;
 
@@ -268,23 +266,7 @@
 	iget(inode->i_sb, inode->i_ino);
 	/* catch the dentries later if some are still busy */
 	coda_flag_inode(inode, C_PURGE);
-
-restart:
-	tmp = head;
-	while ((tmp = tmp->next) != head) {
-		struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
-		if (!dentry->d_count) {
-			CDEBUG(D_DOWNCALL, 
-			       "coda_free_dentries: freeing %s/%s, i_count=%d\n",
-			       dentry->d_parent->d_name.name, dentry->d_name.name, 
-			       inode->i_count);
-			dget(dentry);
-			d_drop(dentry);
-			dput(dentry);
-			goto restart;
-		}
-			
-	}
+	d_prune_aliases(inode);
 	iput(inode);
 }
 
@@ -311,28 +293,18 @@
 
 void coda_flag_inode_children(struct inode *inode, int flag)
 {
-	struct list_head *alias;
 	struct dentry *alias_de;
 
 	ENTRY;
-	if ( !inode ) 
+	if ( !inode || !S_ISDIR(inode->i_mode)) 
 		return; 
 
-	if (list_empty(&inode->i_dentry))
-	        return; 
-
-	/* I believe that shrink_dcache_parent will not
-	   remove dentries from the alias list. If it 
-	   does we are toast. 
-	*/
-	alias = inode->i_dentry.next; 
-	while ( alias != &inode->i_dentry ) {
-		alias_de = list_entry(alias, struct dentry, d_alias);
-		coda_flag_children(alias_de, flag);
-		alias = alias->next;
-		shrink_dcache_parent(alias_de);
-	}
-
+	alias_de = d_find_alias(inode);
+	if (!alias_de)
+		return;
+	coda_flag_children(alias_de, flag);
+	shrink_dcache_parent(alias_de);
+	dput(alias_de);
 }
 
 /* this will not zap the inode away */
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.3.99-pre8/linux/fs/coda/dir.c	Mon Mar 27 08:08:29 2000
+++ linux/fs/coda/dir.c	Sat May 20 10:55:26 2000
@@ -45,7 +45,7 @@
 
 /* dentry ops */
 static int coda_dentry_revalidate(struct dentry *de, int);
-static void coda_dentry_delete(struct dentry *);
+static int coda_dentry_delete(struct dentry *);
 
 /* support routines */
 static int coda_venus_readdir(struct file *filp, void *dirent, 
@@ -434,7 +434,6 @@
         /* cache management: mtime has changed, ask Venus */
 	dircnp->c_flags |= C_VATTR;
 	de->d_inode->i_nlink--;
-	d_delete(de);
 
         return 0;
 }
@@ -801,20 +800,21 @@
  * This is the callback from dput() when d_count is going to 0.
  * We use this to unhash dentries with bad inodes.
  */
-static void coda_dentry_delete(struct dentry * dentry)
+static int coda_dentry_delete(struct dentry * dentry)
 {
 	int flags;
 
 	if (!dentry->d_inode) 
-		return ;
+		return 0;
 
 	flags =  (ITOC(dentry->d_inode)->c_flags) & C_PURGE;
 	if (is_bad_inode(dentry->d_inode) || flags) {
 		CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n", 
 		       dentry->d_parent->d_name.name, dentry->d_name.name,
 		       dentry->d_inode->i_ino);
-		d_drop(dentry);
+		return 1;
 	}
+	return 0;
 }
 
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.3.99-pre8/linux/fs/coda/psdev.c	Thu May 11 15:30:08 2000
+++ linux/fs/coda/psdev.c	Sat May 20 09:27:06 2000
@@ -296,6 +296,8 @@
 	       vcp->vc_inuse, vcp->vc_pid, current->pid);
 
 	if ( vcp->vc_pid != current->pid ) {
+		/* FIXME: this is broken. If venus does fork(), accounting goes wrong */
+		printk( "Closed by someone else than caller?\n" );
 		return 0;
 	}
         
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/cramfs/inode.c linux/fs/cramfs/inode.c
--- v2.3.99-pre8/linux/fs/cramfs/inode.c	Thu May 11 15:30:08 2000
+++ linux/fs/cramfs/inode.c	Tue May 23 14:52:18 2000
@@ -84,15 +84,17 @@
 #define NEXT_BUFFER(_ix) ((_ix) ^ 1)
 
 /*
- * BLKS_PER_BUF_SHIFT must be at least 1 to allow for "compressed"
- * data that takes up more space than the original.  1 is guaranteed
- * to suffice, though.  Larger values provide more read-ahead and
- * proportionally less wastage at the end of the buffer.
+ * BLKS_PER_BUF_SHIFT should be at least 2 to allow for "compressed"
+ * data that takes up more space than the original and with unlucky
+ * alignment.
  */
-#define BLKS_PER_BUF_SHIFT (2)
-#define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT)
-static unsigned char read_buffers[READ_BUFFERS][BLKS_PER_BUF][PAGE_CACHE_SIZE];
+#define BLKS_PER_BUF_SHIFT	(2)
+#define BLKS_PER_BUF		(1 << BLKS_PER_BUF_SHIFT)
+#define BUFFER_SIZE		(BLKS_PER_BUF*PAGE_CACHE_SIZE)
+
+static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE];
 static unsigned buffer_blocknr[READ_BUFFERS];
+static struct super_block * buffer_dev[READ_BUFFERS];
 static int next_buffer = 0;
 
 /*
@@ -102,19 +104,27 @@
 static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
 {
 	struct buffer_head * bh_array[BLKS_PER_BUF];
-	unsigned i, blocknr, last_blocknr, buffer;
+	unsigned i, blocknr, buffer;
+	char *data;
 
 	if (!len)
 		return NULL;
 	blocknr = offset >> PAGE_CACHE_SHIFT;
-	last_blocknr = (offset + len - 1) >> PAGE_CACHE_SHIFT;
-	if (last_blocknr - blocknr >= BLKS_PER_BUF)
-		goto eek; resume:
 	offset &= PAGE_CACHE_SIZE - 1;
+
+	/* Check if an existing buffer already has the data.. */
 	for (i = 0; i < READ_BUFFERS; i++) {
-		if ((blocknr >= buffer_blocknr[i]) &&
-		    (last_blocknr - buffer_blocknr[i] < BLKS_PER_BUF))
-			return &read_buffers[i][blocknr - buffer_blocknr[i]][offset];
+		unsigned int blk_offset;
+
+		if (buffer_dev[i] != sb)
+			continue;
+		if (blocknr < buffer_blocknr[i])
+			continue;
+		blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT;
+		blk_offset += offset;
+		if (blk_offset + len > BUFFER_SIZE)
+			continue;
+		return read_buffers[i] + blk_offset;
 	}
 
 	/* Ok, read in BLKS_PER_BUF pages completely first. */
@@ -125,24 +135,19 @@
 	buffer = next_buffer;
 	next_buffer = NEXT_BUFFER(buffer);
 	buffer_blocknr[buffer] = blocknr;
+	buffer_dev[buffer] = sb;
+
+	data = read_buffers[buffer];
 	for (i = 0; i < BLKS_PER_BUF; i++) {
 		struct buffer_head * bh = bh_array[i];
 		if (bh) {
-			memcpy(read_buffers[buffer][i], bh->b_data, PAGE_CACHE_SIZE);
+			memcpy(data, bh->b_data, PAGE_CACHE_SIZE);
 			bforget(bh);
 		} else
-			memset(read_buffers[buffer][i], 0, PAGE_CACHE_SIZE);
+			memset(data, 0, PAGE_CACHE_SIZE);
+		data += PAGE_CACHE_SIZE;
 	}
-	return read_buffers[buffer][0] + offset;
-
- eek:
-	printk(KERN_ERR
-	       "cramfs (device %s): requested chunk (%u:+%u) bigger than buffer\n",
-	       bdevname(sb->s_dev), offset, len);
-	/* TODO: return EIO to process or kill the current process
-           instead of resuming. */
-	*((int *)0) = 0; /* XXX: doesn't work on all archs */
-	goto resume;
+	return read_buffers[buffer] + offset;
 }
 			
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/dcache.c linux/fs/dcache.c
--- v2.3.99-pre8/linux/fs/dcache.c	Thu May 11 15:30:08 2000
+++ linux/fs/dcache.c	Sun May 21 20:34:37 2000
@@ -131,7 +131,8 @@
 	 * Each fs will have to watch for this.
 	 */
 	if (dentry->d_op && dentry->d_op->d_delete) {
-		dentry->d_op->d_delete(dentry);
+		if (dentry->d_op->d_delete(dentry))
+			d_drop(dentry);
 
 		count = dentry->d_count - 1;
 		if (count != 0)
@@ -220,6 +221,53 @@
 	return 0;
 }
 
+/**
+ * d_find_alias - grab a hashed alias of inode
+ * @inode: inode in question
+ *
+ * If inode has a hashed alias - acquire the reference to alias and
+ * return it. Otherwise return NULL. Notice that if inode is a directory
+ * there can be only one alias and it can be unhashed only if it has
+ * no children.
+ */
+
+struct dentry * d_find_alias(struct inode *inode)
+{
+	struct list_head *head, *next, *tmp;
+	struct dentry *alias;
+
+	head = &inode->i_dentry;
+	next = inode->i_dentry.next;
+	while (next != head) {
+		tmp = next;
+		next = tmp->next;
+		alias = list_entry(tmp, struct dentry, d_alias);
+		if (!d_unhashed(alias))
+			return dget(alias);
+	}
+	return NULL;
+}
+
+/*
+ *	Try to kill dentries associated with this inode.
+ * WARNING: you must own a reference to inode.
+ */
+void d_prune_aliases(struct inode *inode)
+{
+	struct list_head *tmp, *head = &inode->i_dentry;
+restart:
+	tmp = head;
+	while ((tmp = tmp->next) != head) {
+		struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
+		if (!dentry->d_count) {
+			dget(dentry);
+			d_drop(dentry);
+			dput(dentry);
+			goto restart;
+		}
+	}
+}
+
 /*
  * Throw away a dentry - free the inode, dput the parent.
  * This requires that the LRU list has already been
@@ -384,37 +432,6 @@
 	return 0; /* No mount points found in tree */
 }
 
-int d_active_refs(struct dentry *root)
-{
-	struct dentry *this_parent = root;
-	struct list_head *next;
-	int count = root->d_count;
-
-repeat:
-	next = this_parent->d_subdirs.next;
-resume:
-	while (next != &this_parent->d_subdirs) {
-		struct list_head *tmp = next;
-		struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
-		next = tmp->next;
-		/* Decrement count for unused children */
-		count += (dentry->d_count - 1);
-		if (!list_empty(&dentry->d_subdirs)) {
-			this_parent = dentry;
-			goto repeat;
-		}
-	}
-	/*
-	 * All done at this level ... ascend and resume the search.
-	 */
-	if (this_parent != root) {
-		next = this_parent->d_child.next; 
-		this_parent = this_parent->d_parent;
-		goto resume;
-	}
-	return count;
-}
-
 /*
  * Search the dentry child list for the specified parent,
  * and move any unused dentries to the end of the unused
@@ -788,7 +805,7 @@
  * Note that we have to be a lot more careful about getting the hash
  * switched - we have to switch the hash value properly even if it
  * then no longer matches the actual (corrupted) string of the target.
- * The has value has to match the hash queue that the dentry is on..
+ * The hash value has to match the hash queue that the dentry is on..
  */
 static inline void switch_names(struct dentry * dentry, struct dentry * target)
 {
@@ -948,7 +965,12 @@
 asmlinkage long sys_getcwd(char *buf, unsigned long size)
 {
 	int error;
-	struct dentry *pwd = current->fs->pwd; 
+	struct vfsmount *pwdmnt;
+	struct dentry *pwd;
+
+	lock_kernel();
+	pwdmnt = mntget(current->fs->pwdmnt);
+	pwd = dget(current->fs->pwd);
 
 	error = -ENOENT;
 	/* Has the current directory has been unlinked? */
@@ -959,9 +981,7 @@
 			unsigned long len;
 			char * cwd;
 
-			lock_kernel();
 			cwd = d_path(pwd, current->fs->pwdmnt, page, PAGE_SIZE);
-			unlock_kernel();
 
 			error = -ERANGE;
 			len = PAGE_SIZE + page - cwd;
@@ -973,6 +993,9 @@
 			free_page((unsigned long) page);
 		}
 	}
+	dput(pwd);
+	mntput(pwdmnt);
+	unlock_kernel();
 	return error;
 }
 
@@ -1008,6 +1031,34 @@
 		break;
 	}
 	return result;
+}
+
+void d_genocide(struct dentry *root)
+{
+	struct dentry *this_parent = root;
+	struct list_head *next;
+
+repeat:
+	next = this_parent->d_subdirs.next;
+resume:
+	while (next != &this_parent->d_subdirs) {
+		struct list_head *tmp = next;
+		struct dentry *dentry = list_entry(tmp, struct dentry, d_child);
+		next = tmp->next;
+		if (d_unhashed(dentry)||!dentry->d_inode)
+			continue;
+		if (!list_empty(&dentry->d_subdirs)) {
+			this_parent = dentry;
+			goto repeat;
+		}
+		dentry->d_count--;
+	}
+	if (this_parent != root) {
+		next = this_parent->d_child.next; 
+		this_parent->d_count--;
+		this_parent = this_parent->d_parent;
+		goto resume;
+	}
 }
 
 /**
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/devfs/base.c linux/fs/devfs/base.c
--- v2.3.99-pre8/linux/fs/devfs/base.c	Thu May 11 15:30:08 2000
+++ linux/fs/devfs/base.c	Sat May 20 10:55:26 2000
@@ -555,7 +555,7 @@
 
 #define OOPS(format, args...) {printk (format, ## args); \
                                printk ("Forcing Oops\n"); \
-                               *(int *) 0 = 0;}
+                               BUG();}
 
 struct directory_type
 {
@@ -729,17 +729,21 @@
 
 /*  Support functions follow  */
 
+
+/**
+ *	search_for_entry_in_dir - Search for a devfs entry inside another devfs entry.
+ *	@parent:  The parent devfs entry.
+ *	@name:  The name of the entry.
+ *	@namelen:  The number of characters in @name.
+ *	@traverse_symlink:  If %TRUE then the entry is traversed if it is a symlink.
+ *
+ *	Returns a pointer to the entry on success, else %NULL.
+ */
+
 static struct devfs_entry *search_for_entry_in_dir (struct devfs_entry *parent,
 						    const char *name,
 						    unsigned int namelen,
 						    int traverse_symlink)
-/*  [SUMMARY] Search for a devfs entry inside another devfs entry.
-    <parent> The parent devfs entry.
-    <name> The name of the entry.
-    <namelen> The number of characters in <<name>>.
-    <traverse_symlink> If TRUE then the entry is traversed if it is a symlink.
-    [RETURNS] A pointer to the entry on success, else NULL.
-*/
 {
     struct devfs_entry *curr;
 
@@ -783,10 +787,14 @@
     return new;
 }   /*  End Function create_entry  */
 
+
+/**
+ *	get_root_entry - Get the root devfs entry.
+ *
+ *	Returns the root devfs entry on success, else %NULL.
+ */
+
 static struct devfs_entry *get_root_entry (void)
-/*  [SUMMARY] Get the root devfs entry.
-    [RETURNS] The root devfs entry on success, else NULL.
-*/
 {
     struct devfs_entry *new;
 
@@ -809,23 +817,27 @@
     return root_entry;
 }   /*  End Function get_root_entry  */
 
+
+/**
+ *	search_for_entry - Search for an entry in the devfs tree.
+ *	@dir: The parent directory to search from. If this is %NULL the root is used
+ *	@name: The name of the entry.
+ *	@namelen: The number of characters in @name.
+ *	@mkdir: If %TRUE intermediate directories are created as needed.
+ *	@mkfile: If %TRUE the file entry is created if it doesn't exist.
+ *	@is_new: If the returned entry was newly made, %TRUE is written here. If
+ * 		this is %NULL nothing is written here.
+ *	@traverse_symlink: If %TRUE then symbolic links are traversed.
+ *
+ *	If the entry is created, then it will be in the unregistered state.
+ *	Returns a pointer to the entry on success, else %NULL.
+ */
+
 static struct devfs_entry *search_for_entry (struct devfs_entry *dir,
 					     const char *name,
 					     unsigned int namelen, int mkdir,
 					     int mkfile, int *is_new,
 					     int traverse_symlink)
-/*  [SUMMARY] Search for an entry in the devfs tree.
-    <dir> The parent directory to search from. If this is NULL the root is used
-    <name> The name of the entry.
-    <namelen> The number of characters in <<name>>.
-    <mkdir> If TRUE intermediate directories are created as needed.
-    <mkfile> If TRUE the file entry is created if it doesn't exist.
-    <is_new> If the returned entry was newly made, TRUE is written here. If
-    this is NULL nothing is written here.
-    <traverse_symlink> If TRUE then symbolic links are traversed.
-    [NOTE] If the entry is created, then it will be in the unregistered state.
-    [RETURNS] A pointer to the entry on success, else NULL.
-*/
 {
     int len;
     const char *subname, *stop, *ptr;
@@ -887,16 +899,20 @@
     return NULL;
 }   /*  End Function search_for_entry  */
 
+
+/**
+ *	find_by_dev - Find a devfs entry in a directory.
+ *	@major: The major number to search for.
+ *	@minor: The minor number to search for.
+ *	@type: The type of special file to search for. This may be either
+ *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK.
+ *
+ *	Returns the devfs_entry pointer on success, else %NULL.
+ */
+
 static struct devfs_entry *find_by_dev (struct devfs_entry *dir,
 					unsigned int major, unsigned int minor,
 					char type)
-/*  [SUMMARY] Find a devfs entry in a directory.
-    <major> The major number to search for.
-    <minor> The minor number to search for.
-    <type> The type of special file to search for. This may be either
-    DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK.
-    [RETURNS] The devfs_entry pointer on success, else NULL.
-*/
 {
     struct devfs_entry *entry, *de;
 
@@ -926,26 +942,31 @@
     return NULL;
 }   /*  End Function find_by_dev  */
 
+
+/**
+ *	find_entry - Find a devfs entry.
+ *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
+ *		name is relative to the root of the devfs.
+ *	@name: The name of the entry. This is ignored if @handle is not %NULL.
+ *	@namelen: The number of characters in @name, not including a %NULL
+ *		terminator. If this is 0, then @name must be %NULL-terminated and the
+ *		length is computed internally.
+ *	@major: The major number. This is used if @handle and @name are %NULL.
+ *	@minor: The minor number. This is used if @handle and @name are %NULL.
+ *		NOTE: If @major and @minor are both 0, searching by major and minor
+ *		numbers is disabled.
+ *	@type: The type of special file to search for. This may be either
+ *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK.
+ *	@traverse_symlink: If %TRUE then symbolic links are traversed.
+ *
+ *	FIXME: What the hell is @handle? - ch
+ *	Returns the devfs_entry pointer on success, else %NULL.
+ */
+
 static struct devfs_entry *find_entry (devfs_handle_t dir,
 				       const char *name, unsigned int namelen,
 				       unsigned int major, unsigned int minor,
 				       char type, int traverse_symlink)
-/*  [SUMMARY] Find a devfs entry.
-    <dir> The handle to the parent devfs directory entry. If this is NULL the
-    name is relative to the root of the devfs.
-    <name> The name of the entry. This is ignored if <<handle>> is not NULL.
-    <namelen> The number of characters in <<name>>, not including a NULL
-    terminator. If this is 0, then <<name>> must be NULL-terminated and the
-    length is computed internally.
-    <major> The major number. This is used if <<handle>> and <<name>> are NULL.
-    <minor> The minor number. This is used if <<handle>> and <<name>> are NULL.
-    [NOTE] If <<major>> and <<minor>> are both 0, searching by major and minor
-    numbers is disabled.
-    <type> The type of special file to search for. This may be either
-    DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK.
-    <traverse_symlink> If TRUE then symbolic links are traversed.
-    [RETURNS] The devfs_entry pointer on success, else NULL.
-*/
 {
     struct devfs_entry *entry;
 
@@ -991,11 +1012,13 @@
     return fs_info->table[inode->i_ino - FIRST_INODE];
 }   /*  End Function get_devfs_inode_from_vfs_inode  */
 
+
+/**
+ *	free_dentries - Free the dentries for a device entry and invalidate inodes.
+ *	@de: The entry.
+ */
+
 static void free_dentries (struct devfs_entry *de)
-/*  [SUMMARY] Free the dentries for a device entry and invalidate inodes.
-    <de> The entry.
-    [RETURNS] Nothing.
-*/
 {
     struct devfs_inode *di;
     struct dentry *dentry;
@@ -1015,11 +1038,15 @@
     }
 }   /*  End Function free_dentries  */
 
+
+/**
+ *	is_devfsd_or_child - Test if the current process is devfsd or one of its children.
+ *	fs_info: The filesystem information.
+ *
+ *	Returns %TRUE if devfsd or child, else %FALSE.
+ */
+
 static int is_devfsd_or_child (struct fs_info *fs_info)
-/*  [SUMMARY] Test if the current process is devfsd or one of its children.
-    <fs_info> The filesystem information.
-    [RETURNS] TRUE if devfsd or child, else FALSE.
-*/
 {
     struct task_struct *p;
 
@@ -1030,20 +1057,28 @@
     return (FALSE);
 }   /*  End Function is_devfsd_or_child  */
 
+
+/**
+ *	devfsd_queue_empty - Test if devfsd has work pending in its event queue.
+ *	@fs_info: The filesystem information.
+ *
+ *	Returns %TRUE if the queue is empty, else %FALSE.
+ */
+
 static inline int devfsd_queue_empty (struct fs_info *fs_info)
-/*  [SUMMARY] Test if devfsd has work pending in its event queue.
-    <fs_info> The filesystem information.
-    [RETURNS] TRUE if the queue is empty, else FALSE.
-*/
 {
     return (fs_info->devfsd_buf_out == fs_info->devfsd_buf_in) ? TRUE : FALSE;
 }   /*  End Function devfsd_queue_empty  */
 
+
+/**
+ *	wait_for_devfsd_finished - Wait for devfsd to finish processing its event queue.
+ *	@fs_info: The filesystem information.
+ *
+ *	Returns %TRUE if no more waiting will be required, else %FALSE.
+ */
+
 static int wait_for_devfsd_finished (struct fs_info *fs_info)
-/*  [SUMMARY] Wait for devfsd to finish processing its event queue.
-    <fs_info> The filesystem information.
-    [RETURNS] TRUE if no more waiting will be required, else FALSE.
-*/
 {
     DECLARE_WAITQUEUE (wait, current);
 
@@ -1059,17 +1094,21 @@
     return (TRUE);
 }   /*  End Function wait_for_devfsd_finished  */
 
+
+/**
+ *	devfsd_notify_one - Notify a single devfsd daemon of a change.
+ *	@data: Data to be passed.
+ *	@type: The type of change.
+ *	@mode: The mode of the entry.
+ *	@uid: The user ID.
+ *	@gid: The group ID.
+ *	@fs_info: The filesystem info.
+ *
+ *	Returns %TRUE if an event was queued and devfsd woken up, else %FALSE.
+ */
+
 static int devfsd_notify_one (void *data, unsigned int type, umode_t mode,
 			      uid_t uid, gid_t gid, struct fs_info *fs_info)
-/*  [SUMMARY] Notify a single devfsd daemon of a change.
-    <data> Data to be passed.
-    <type> The type of change.
-    <mode> The mode of the entry.
-    <uid> The user ID.
-    <gid> The group ID.
-    <fs_info> The filesystem info.
-    [RETURNS] TRUE if an event was queued and devfsd woken up, else FALSE.
-*/
 {
     unsigned int next_pos;
     unsigned long flags;
@@ -1103,14 +1142,16 @@
     return (TRUE);
 }   /*  End Function devfsd_notify_one  */
 
+
+/**
+ *	devfsd_notify - Notify all devfsd daemons of a change.
+ *	@de: The devfs entry that has changed.
+ *	@type: The type of change event.
+ *	@wait: If TRUE, the functions waits for all daemons to finish processing
+ *		the event.
+ */
+
 static void devfsd_notify (struct devfs_entry *de, unsigned int type, int wait)
-/*  [SUMMARY] Notify all devfsd daemons of a change.
-    <de> The devfs entry that has changed.
-    <type> The type of change event.
-    <wait> If TRUE, the functions waits for all daemons to finish processing
-    the event.
-    [RETURNS] Nothing.
-*/
 {
     struct fs_info *fs_info;
 
@@ -1122,35 +1163,38 @@
     }
 }   /*  End Function devfsd_notify  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_register - Register a device entry.
+ *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
+ *		new name is relative to the root of the devfs.
+ *	@name: The name of the entry.
+ *	@namelen: The number of characters in @name, not including a %NULL
+ *		terminator. If this is 0, then @name must be %NULL-terminated and the
+ *		length is computed internally.
+ *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*).
+ *	@major: The major number. Not needed for regular files.
+ *	@minor: The minor number. Not needed for regular files.
+ *	@mode: The default file mode.
+ *	@uid: The default UID of the file.
+ *	@guid: The default GID of the file.
+ *	@ops: The &file_operations or &block_device_operations structure.
+ *		This must not be externally deallocated.
+ *	@info: An arbitrary pointer which will be written to the @private_data
+ *		field of the &file structure passed to the device driver. You can set
+ *		this to whatever you like, and change it once the file is opened (the next
+ *		file opened will not see this change).
+ *
+ *	Returns a handle which may later be used in a call to devfs_unregister().
+ *	On failure %NULL is returned.
+ */
+
 devfs_handle_t devfs_register (devfs_handle_t dir,
 			       const char *name, unsigned int namelen,
 			       unsigned int flags,
 			       unsigned int major, unsigned int minor,
 			       umode_t mode, uid_t uid, gid_t gid,
 			       void *ops, void *info)
-/*  [SUMMARY] Register a device entry.
-    <dir> The handle to the parent devfs directory entry. If this is NULL the
-    new name is relative to the root of the devfs.
-    <name> The name of the entry.
-    <namelen> The number of characters in <<name>>, not including a NULL
-    terminator. If this is 0, then <<name>> must be NULL-terminated and the
-    length is computed internally.
-    <flags> A set of bitwise-ORed flags (DEVFS_FL_*).
-    <major> The major number. Not needed for regular files.
-    <minor> The minor number. Not needed for regular files.
-    <mode> The default file mode.
-    <uid> The default UID of the file.
-    <guid> The default GID of the file.
-    <ops> The <<file_operations>> or <<block_device_operations>> structure.
-    This must not be externally deallocated.
-    <info> An arbitrary pointer which will be written to the <<private_data>>
-    field of the <<file>> structure passed to the device driver. You can set
-    this to whatever you like, and change it once the file is opened (the next
-    file opened will not see this change).
-    [RETURNS] A handle which may later be used in a call to
-    [<devfs_unregister>]. On failure NULL is returned.
-*/
 {
     int is_new;
     struct devfs_entry *de;
@@ -1276,11 +1320,13 @@
     return de;
 }   /*  End Function devfs_register  */
 
+
+/**
+ *	unregister - Unregister a device entry.
+ *	@de: The entry to unregister.
+ */
+
 static void unregister (struct devfs_entry *de)
-/*  [SUMMARY] Unregister a device entry.
-    <de> The entry to unregister.
-    [RETURNS] Nothing.
-*/
 {
     struct devfs_entry *child;
 
@@ -1332,13 +1378,14 @@
     }
 }   /*  End Function unregister  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_unregister - Unregister a device entry.
+ *	de: A handle previously created by devfs_register() or returned from
+ *		devfs_find_handle(). If this is %NULL the routine does nothing.
+ */
+
 void devfs_unregister (devfs_handle_t de)
-/*  [SUMMARY] Unregister a device entry.
-    <de> A handle previously created by [<devfs_register>] or returned from
-    [<devfs_find_handle>]. If this is NULL the routine does nothing.
-    [RETURNS] Nothing.
-*/
 {
     if (de == NULL) return;
 #ifdef CONFIG_DEVFS_DEBUG
@@ -1349,28 +1396,31 @@
     unregister (de);
 }   /*  End Function devfs_unregister  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_mk_symlink Create a symbolic link in the devfs namespace.
+ *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
+ *		new name is relative to the root of the devfs.
+ *	@name: The name of the entry.
+ *	@namelen: The number of characters in @name, not including a %NULL
+ *		terminator. If this is 0, then @name must be %NULL-terminated and the
+ *		length is computed internally.
+ *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*).
+ *	@link: The destination name.
+ *	@linklength: The number of characters in @link, not including a %NULL
+ *		terminator. If this is 0, then @link must be %NULL-terminated and the
+ *		length is computed internally.
+ *	@handle: The handle to the symlink entry is written here. This may be %NULL.
+ *	@info: An arbitrary pointer which will be associated with the entry.
+ *
+ *	Returns 0 on success, else a negative error code is returned.
+ */
+
 int devfs_mk_symlink (devfs_handle_t dir,
 		      const char *name, unsigned int namelen,
 		      unsigned int flags,
 		      const char *link, unsigned int linklength,
 		      devfs_handle_t *handle, void *info)
-/*  [SUMMARY] Create a symbolic link in the devfs namespace.
-    <dir> The handle to the parent devfs directory entry. If this is NULL the
-    new name is relative to the root of the devfs.
-    <name> The name of the entry.
-    <namelen> The number of characters in <<name>>, not including a NULL
-    terminator. If this is 0, then <<name>> must be NULL-terminated and the
-    length is computed internally.
-    <flags> A set of bitwise-ORed flags (DEVFS_FL_*).
-    <link> The destination name.
-    <linklength> The number of characters in <<link>>, not including a NULL
-    terminator. If this is 0, then <<link>> must be NULL-terminated and the
-    length is computed internally.
-    <handle> The handle to the symlink entry is written here. This may be NULL.
-    <info> An arbitrary pointer which will be associated with the entry.
-    [RETURNS] 0 on success, else a negative error code is returned.
-*/
 {
     int is_new;
     char *newname;
@@ -1439,23 +1489,26 @@
     return 0;
 }   /*  End Function devfs_mk_symlink  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_mk_dir - Create a directory in the devfs namespace.
+ *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
+ *		new name is relative to the root of the devfs.
+ *	@name: The name of the entry.
+ *	@namelen: The number of characters in @name, not including a %NULL
+ *		terminator. If this is 0, then @name must be %NULL-terminated and the
+ *		length is computed internally.
+ *	@info: An arbitrary pointer which will be associated with the entry.
+ *
+ *	Use of this function is optional. The devfs_register() function
+ *	will automatically create intermediate directories as needed. This function
+ *	is provided for efficiency reasons, as it provides a handle to a directory.
+ *	Returns a handle which may later be used in a call to devfs_unregister().
+ *	On failure %NULL is returned.
+ */
+
 devfs_handle_t devfs_mk_dir (devfs_handle_t dir, const char *name,
 			     unsigned int namelen, void *info)
-/*  [SUMMARY] Create a directory in the devfs namespace.
-    <dir> The handle to the parent devfs directory entry. If this is NULL the
-    new name is relative to the root of the devfs.
-    <name> The name of the entry.
-    <namelen> The number of characters in <<name>>, not including a NULL
-    terminator. If this is 0, then <<name>> must be NULL-terminated and the
-    length is computed internally.
-    <info> An arbitrary pointer which will be associated with the entry.
-    [NOTE] Use of this function is optional. The [<devfs_register>] function
-    will automatically create intermediate directories as needed. This function
-    is provided for efficiency reasons, as it provides a handle to a directory.
-    [RETURNS] A handle which may later be used in a call to
-    [<devfs_unregister>]. On failure NULL is returned.
-*/
 {
     int is_new;
     struct devfs_entry *de;
@@ -1499,29 +1552,31 @@
     return de;
 }   /*  End Function devfs_mk_dir  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_find_handle - Find the handle of a devfs entry.
+ *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
+ *		name is relative to the root of the devfs.
+ *	@name: The name of the entry.
+ *	@namelen: The number of characters in @name, not including a %NULL
+ *		terminator. If this is 0, then @name must be %NULL-terminated and the
+ *		length is computed internally.
+ *	@major: The major number. This is used if @name is %NULL.
+ *	@minor: The minor number. This is used if @name is %NULL.
+ *	@type: The type of special file to search for. This may be either
+ *		%DEVFS_SPECIAL_CHR or %DEVFS_SPECIAL_BLK.
+ *	@traverse_symlinks: If %TRUE then symlink entries in the devfs namespace are
+ *		traversed. Symlinks pointing out of the devfs namespace will cause a
+ *		failure. Symlink traversal consumes stack space.
+ *
+ *	Returns a handle which may later be used in a call to devfs_unregister(),
+ *	devfs_get_flags(), or devfs_set_flags(). On failure %NULL is returned.
+ */
+
 devfs_handle_t devfs_find_handle (devfs_handle_t dir,
 				  const char *name, unsigned int namelen,
 				  unsigned int major, unsigned int minor,
 				  char type, int traverse_symlinks)
-/*  [SUMMARY] Find the handle of a devfs entry.
-    <dir> The handle to the parent devfs directory entry. If this is NULL the
-    name is relative to the root of the devfs.
-    <name> The name of the entry.
-    <namelen> The number of characters in <<name>>, not including a NULL
-    terminator. If this is 0, then <<name>> must be NULL-terminated and the
-    length is computed internally.
-    <major> The major number. This is used if <<name>> is NULL.
-    <minor> The minor number. This is used if <<name>> is NULL.
-    <type> The type of special file to search for. This may be either
-    DEVFS_SPECIAL_CHR or DEVFS_SPECIAL_BLK.
-    <traverse_symlinks> If TRUE then symlink entries in the devfs namespace are
-    traversed. Symlinks pointing out of the devfs namespace will cause a
-    failure. Symlink traversal consumes stack space.
-    [RETURNS] A handle which may later be used in a call to
-    [<devfs_unregister>], [<devfs_get_flags>], or [<devfs_set_flags>].
-    On failure NULL is returned.
-*/
 {
     devfs_handle_t de;
 
@@ -1533,13 +1588,16 @@
     return de;
 }   /*  End Function devfs_find_handle  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_flags - Get the flags for a devfs entry.
+ *	@de: The handle to the device entry.
+ *	@flags: The flags are written here.
+ *
+ *	Returns 0 on success, else a negative error code.
+ */
+
 int devfs_get_flags (devfs_handle_t de, unsigned int *flags)
-/*  [SUMMARY] Get the flags for a devfs entry.
-    <de> The handle to the device entry.
-    <flags> The flags are written here.
-    [RETURNS] 0 on success, else a negative error code.
-*/
 {
     unsigned int fl = 0;
 
@@ -1557,13 +1615,16 @@
     return 0;
 }   /*  End Function devfs_get_flags  */
 
-/*PUBLIC_FUNCTION*/
+
+/*
+ *	devfs_set_flags - Set the flags for a devfs entry.
+ *	@de: The handle to the device entry.
+ *	@flags: The flags to set. Unset flags are cleared.
+ *
+ *	Returns 0 on success, else a negative error code.
+ */
+
 int devfs_set_flags (devfs_handle_t de, unsigned int flags)
-/*  [SUMMARY] Set the flags for a devfs entry.
-    <de> The handle to the device entry.
-    <flags> The flags to set. Unset flags are cleared.
-    [RETURNS] 0 on success, else a negative error code.
-*/
 {
     if (de == NULL) return -EINVAL;
     if (!de->registered) return -ENODEV;
@@ -1592,15 +1653,18 @@
     return 0;
 }   /*  End Function devfs_set_flags  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_maj_min - Get the major and minor numbers for a devfs entry.
+ *	@de: The handle to the device entry.
+ *	@major: The major number is written here. This may be %NULL.
+ *	@minor: The minor number is written here. This may be %NULL.
+ *
+ *	Returns 0 on success, else a negative error code.
+ */
+
 int devfs_get_maj_min (devfs_handle_t de, unsigned int *major,
 		       unsigned int *minor)
-/*  [SUMMARY] Get the major and minor numbers for a devfs entry.
-    <de> The handle to the device entry.
-    <major> The major number is written here. This may be NULL.
-    <minor> The minor number is written here. This may be NULL.
-    [RETURNS] 0 on success, else a negative error code.
-*/
 {
     if (de == NULL) return -EINVAL;
     if (!de->registered) return -ENODEV;
@@ -1611,12 +1675,15 @@
     return 0;
 }   /*  End Function devfs_get_maj_min  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_handle_from_inode - Get the devfs handle for a VFS inode.
+ *	@inode: The VFS inode.
+ *
+ *	Returns the devfs handle on success, else %NULL.
+ */
+
 devfs_handle_t devfs_get_handle_from_inode (struct inode *inode)
-/*  [SUMMARY] Get the devfs handle for a VFS inode.
-    <inode> The VFS inode.
-    [RETURNS] The devfs handle on success, else NULL.
-*/
 {
     struct devfs_inode *di;
 
@@ -1627,16 +1694,19 @@
     return di->de;
 }   /*  End Function devfs_get_handle_from_inode  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_generate_path - Generate a pathname for an entry, relative to the devfs root.
+ *	@de: The devfs entry.
+ *	@path: The buffer to write the pathname to. The pathname and '\0'
+ *		terminator will be written at the end of the buffer.
+ *	@buflen: The length of the buffer.
+ *
+ *	Returns the offset in the buffer where the pathname starts on success,
+ *	else a negative error code.
+ */
+
 int devfs_generate_path (devfs_handle_t de, char *path, int buflen)
-/*  [SUMMARY] Generate a pathname for an entry, relative to the devfs root.
-    <de> The devfs entry.
-    <path> The buffer to write the pathname to. The pathname and '\0'
-    terminator will be written at the end of the buffer.
-    <buflen> The length of the buffer.
-    [RETURNS] The offset in the buffer where the pathname starts on success,
-    else a negative error code.
-*/
 {
     int pos;
 
@@ -1656,12 +1726,15 @@
     return pos;
 }   /*  End Function devfs_generate_path  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_ops - Get the device operations for a devfs entry.
+ *	@de: The handle to the device entry.
+ *
+ *	Returns a pointer to the device operations on success, else NULL.
+ */
+
 void *devfs_get_ops (devfs_handle_t de)
-/*  [SUMMARY] Get the device operations for a devfs entry.
-    <de> The handle to the device entry.
-    [RETURNS] A pointer to the device operations on success, else NULL.
-*/
 {
     if (de == NULL) return NULL;
     if (!de->registered) return NULL;
@@ -1670,13 +1743,16 @@
     return NULL;
 }   /*  End Function devfs_get_ops  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_set_file_size - Set the file size for a devfs regular file.
+ *	de: The handle to the device entry.
+ *	size: The new file size.
+ *
+ *	Returns 0 on success, else a negative error code.
+ */
+
 int devfs_set_file_size (devfs_handle_t de, unsigned long size)
-/*  [SUMMARY] Set the file size for a devfs regular file.
-    <de> The handle to the device entry.
-    <size> The new file size.
-    [RETURNS] 0 on success, else a negative error code.
-*/
 {
     struct devfs_inode *di;
 
@@ -1694,24 +1770,28 @@
     return 0;
 }   /*  End Function devfs_set_file_size  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_info - Get the info pointer written to private_data of @de upon open.
+ *	@de: The handle to the device entry.
+ *
+ *	Returns the info pointer.
+ */
 void *devfs_get_info (devfs_handle_t de)
-/*  [SUMMARY] Get the info pointer written to <<private_data>> upon open.
-    <de> The handle to the device entry.
-    [RETURNS] The info pointer.
-*/
 {
     if (de == NULL) return NULL;
     if (!de->registered) return NULL;
     return de->info;
 }   /*  End Function devfs_get_info  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_set_info - Set the info pointer written to private_data upon open.
+ *	@de: The handle to the device entry.
+ *
+ *	Returns 0 on success, else a negative error code.
+ */
 int devfs_set_info (devfs_handle_t de, void *info)
-/*  [SUMMARY] Set the info pointer written to <<private_data>> upon open.
-    <de> The handle to the device entry.
-    [RETURNS] 0 on success, else a negative error code.
-*/
 {
     if (de == NULL) return -EINVAL;
     if (!de->registered) return -EINVAL;
@@ -1719,24 +1799,29 @@
     return 0;
 }   /*  End Function devfs_set_info  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_parent - Get the parent device entry.
+ *	@de: The handle to the device entry.
+ *
+ *	Returns the parent device entry if it exists, else %NULL.
+ */
 devfs_handle_t devfs_get_parent (devfs_handle_t de)
-/*  [SUMMARY] Get the parent device entry.
-    <de> The handle to the device entry.
-    [RETURNS] The parent device entry if it exists, else NULL.
-*/
 {
     if (de == NULL) return NULL;
     if (!de->registered) return NULL;
     return de->parent;
 }   /*  End Function devfs_get_parent  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_first_child - Get the first leaf node in a directory.
+ *	@de: The handle to the device entry.
+ *
+ *	Returns the leaf node device entry if it exists, else %NULL.
+ */
+
 devfs_handle_t devfs_get_first_child (devfs_handle_t de)
-/*  [SUMMARY] Get the first leaf node in a directory.
-    <de> The handle to the device entry.
-    [RETURNS] The leaf node device entry if it exists, else NULL.
-*/
 {
     if (de == NULL) return NULL;
     if (!de->registered) return NULL;
@@ -1744,27 +1829,31 @@
     return de->u.dir.first;
 }   /*  End Function devfs_get_first_child  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_next_sibling - Get the next sibling leaf node. for a device entry.
+ *	@de: The handle to the device entry.
+ *
+ *	Returns the leaf node device entry if it exists, else %NULL.
+ */
+
 devfs_handle_t devfs_get_next_sibling (devfs_handle_t de)
-/*  [SUMMARY] Get the next sibling leaf node. for a device entry.
-    <de> The handle to the device entry.
-    [RETURNS] The leaf node device entry if it exists, else NULL.
-*/
 {
     if (de == NULL) return NULL;
     if (!de->registered) return NULL;
     return de->next;
 }   /*  End Function devfs_get_next_sibling  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_auto_unregister - Configure a devfs entry to be automatically unregistered.
+ *	@master: The master devfs entry. Only one slave may be registered.
+ *	@slave: The devfs entry which will be automatically unregistered when the
+ *		master entry is unregistered. It is illegal to call devfs_unregister()
+ *		on this entry.
+ */
+
 void devfs_auto_unregister (devfs_handle_t master, devfs_handle_t slave)
-/*  [SUMMARY] Configure a devfs entry to be automatically unregistered.
-    <master> The master devfs entry. Only one slave may be registered.
-    <slave> The devfs entry which will be automatically unregistered when the
-    master entry is unregistered. It is illegal to call [<devfs_unregister>] on
-    this entry.
-    [RETURNS] Nothing.
-*/
 {
     if (master == NULL) return;
     if (master->slave != NULL)
@@ -1779,25 +1868,30 @@
     master->slave = slave;
 }   /*  End Function devfs_auto_unregister  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_unregister_slave - Get the slave entry which will be automatically unregistered.
+ *	@master: The master devfs entry.
+ *
+ *	Returns the slave which will be unregistered when @master is unregistered.
+ */
+
 devfs_handle_t devfs_get_unregister_slave (devfs_handle_t master)
-/*  [SUMMARY] Get the slave entry which will be automatically unregistered.
-    <master> The master devfs entry.
-    [RETURNS] The slave which will be unregistered when <<master>> is
-    unregistered.
-*/
 {
     if (master == NULL) return NULL;
     return master->slave;
 }   /*  End Function devfs_get_unregister_slave  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_get_name - Get the name for a device entry in its parent directory.
+ *	@de: The handle to the device entry.
+ *	@namelen: The length of the name is written here. This may be %NULL.
+ *
+ *	Returns the name on success, else %NULL.
+ */
+
 const char *devfs_get_name (devfs_handle_t de, unsigned int *namelen)
-/*  [SUMMARY] Get the name for a device entry in its parent directory.
-    <de> The handle to the device entry.
-    <namelen> The length of the name is written here. This may be NULL.
-    [RETURNS] The name on success, else NULL.
-*/
 {
     if (de == NULL) return NULL;
     if (!de->registered) return NULL;
@@ -1805,61 +1899,73 @@
     return de->name;
 }   /*  End Function devfs_get_name  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_register_chrdev - Optionally register a conventional character driver.
+ *	@major: The major number for the driver.
+ *	@name: The name of the driver (as seen in /proc/devices).
+ *	@fops: The &file_operations structure pointer.
+ *
+ *	This function will register a character driver provided the "devfs=only"
+ *	option was not provided at boot time.
+ *	Returns 0 on success, else a negative error code on failure.
+ */
+
 int devfs_register_chrdev (unsigned int major, const char *name,
 			   struct file_operations *fops)
-/*  [SUMMARY] Optionally register a conventional character driver.
-    [PURPOSE] This function will register a character driver provided the
-    "devfs=only" option was not provided at boot time.
-    <major> The major number for the driver.
-    <name> The name of the driver (as seen in /proc/devices).
-    <fops> The file_operations structure pointer.
-    [RETURNS] 0 on success, else a negative error code on failure.
-*/
 {
     if (boot_options & OPTION_ONLY) return 0;
     return register_chrdev (major, name, fops);
 }   /*  End Function devfs_register_chrdev  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_register_blkdev - Optionally register a conventional block driver.
+ *	@major: The major number for the driver.
+ *	@name: The name of the driver (as seen in /proc/devices).
+ *	@bdops: The &block_device_operations structure pointer.
+ *
+ *	This function will register a block driver provided the "devfs=only"
+ *	option was not provided at boot time.
+ *	Returns 0 on success, else a negative error code on failure.
+ */
+
 int devfs_register_blkdev (unsigned int major, const char *name,
 			   struct block_device_operations *bdops)
-/*  [SUMMARY] Optionally register a conventional block driver.
-    [PURPOSE] This function will register a block driver provided the
-    "devfs=only" option was not provided at boot time.
-    <major> The major number for the driver.
-    <name> The name of the driver (as seen in /proc/devices).
-    <bdops> The block_device_operations structure pointer.
-    [RETURNS] 0 on success, else a negative error code on failure.
-*/
 {
     if (boot_options & OPTION_ONLY) return 0;
     return register_blkdev (major, name, bdops);
 }   /*  End Function devfs_register_blkdev  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_unregister_chrdev - Optionally unregister a conventional character driver.
+ *	major: The major number for the driver.
+ *	name: The name of the driver (as seen in /proc/devices).
+ *
+ *	This function will unregister a character driver provided the "devfs=only"
+ *	option was not provided at boot time.
+ *	Returns 0 on success, else a negative error code on failure.
+ */
+
 int devfs_unregister_chrdev (unsigned int major, const char *name)
-/*  [SUMMARY] Optionally unregister a conventional character driver.
-    [PURPOSE] This function will unregister a character driver provided the
-    "devfs=only" option was not provided at boot time.
-    <major> The major number for the driver.
-    <name> The name of the driver (as seen in /proc/devices).
-    [RETURNS] 0 on success, else a negative error code on failure.
-*/
 {
     if (boot_options & OPTION_ONLY) return 0;
     return unregister_chrdev (major, name);
 }   /*  End Function devfs_unregister_chrdev  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_unregister_blkdev - Optionally unregister a conventional block driver.
+ *	@major: The major number for the driver.
+ *	@name: The name of the driver (as seen in /proc/devices).
+ *
+ *	This function will unregister a block driver provided the "devfs=only"
+ *	option was not provided at boot time.
+ *	Returns 0 on success, else a negative error code on failure.
+ */
+
 int devfs_unregister_blkdev (unsigned int major, const char *name)
-/*  [SUMMARY] Optionally unregister a conventional block driver.
-    [PURPOSE] This function will unregister a block driver provided the
-    "devfs=only" option was not provided at boot time.
-    <major> The major number for the driver.
-    <name> The name of the driver (as seen in /proc/devices).
-    [RETURNS] 0 on success, else a negative error code on failure.
-*/
 {
     if (boot_options & OPTION_ONLY) return 0;
     return unregister_blkdev (major, name);
@@ -1867,13 +1973,13 @@
 
 #ifndef MODULE
 
-/*UNPUBLISHED_FUNCTION*/
+/**
+ *	devfs_setup - Process kernel boot options.
+ *	@str: The boot options after the "devfs=".
+ *	@unused: Unused.
+ */
+
 SETUP_STATIC int __init devfs_setup (char *str)
-/*  [SUMMARY] Process kernel boot options.
-    <str> The boot options after the "devfs=".
-    <unused> Unused.
-    [RETURNS] Nothing.
-*/
 {
     while ( (*str != '\0') && !isspace (*str) )
     {
@@ -2027,13 +2133,17 @@
     }
 }   /*  End Function update_devfs_inode_from_entry  */
 
+
+/**
+ *	create_devfs_inode - Create a devfs inode entry.
+ *	@de: The devfs entry to associate the new inode with.
+ *	@fs_info: The FS info.
+ *
+ *	Returns a pointer to the devfs inode on success, else %NULL.
+ */
+
 static struct devfs_inode *create_devfs_inode (struct devfs_entry *de,
 					       struct fs_info *fs_info)
-/*  [SUMMARY] Create a devfs inode entry.
-    <de> The devfs entry to associate the new inode with.
-    <fs_info> The FS info.
-    [RETURNS] A pointer to the devfs inode on success, else NULL.
-*/
 {
     struct devfs_inode *di, **table;
 
@@ -2077,18 +2187,22 @@
     return di;
 }   /*  End Function create_devfs_inode  */
 
+
+/**
+ *	try_modload - Notify devfsd of an inode lookup.
+ *	@parent: The parent devfs entry.
+ *	@fs_info: The filesystem info.
+ *	@name: The device name.
+ *	@namelen: The number of characters in @name.
+ *	@buf: A working area that will be used. This must not go out of scope until
+ *		devfsd is idle again.
+ *
+ *	Returns 0 on success, else a negative error code.
+ */
+
 static int try_modload (struct devfs_entry *parent, struct fs_info *fs_info,
 			const char *name, unsigned namelen,
 			char buf[STRING_LENGTH])
-/*  [SUMMARY] Notify devfsd of an inode lookup.
-    <parent> The parent devfs entry.
-    <fs_info> The filesystem info.
-    <name> The device name.
-    <namelen> The number of characters in <<name>>.
-    <buf> A working area that will be used. This must not go out of scope until
-    devfsd is idle again.
-    [RETURNS] 0 on success, else a negative error code.
-*/
 {
     int pos;
 
@@ -2136,11 +2250,15 @@
     kfree (fs_info);
 }   /*  End Function delete_fs  */
 
+
+/**
+ *	check_disc_changed - Check if a removable disc was changed.
+ *	@de: The device.
+ *
+ *	Returns 1 if the media was changed, else 0.
+ */
+
 static int check_disc_changed (struct devfs_entry *de)
-/*  [SUMMARY] Check if a removable disc was changed.
-    <de> The device.
-    [RETURNS] 1 if the media was changed, else 0.
-*/
 {
     int tmp;
     kdev_t dev = MKDEV (de->u.fcb.u.device.major, de->u.fcb.u.device.minor);
@@ -2166,11 +2284,13 @@
     return 1;
 }   /*  End Function check_disc_changed  */
 
+
+/**
+ *	scan_dir_for_removable - Scan a directory for removable media devices and check media.
+ *	@dir: The directory.
+ */
+
 static void scan_dir_for_removable (struct devfs_entry *dir)
-/*  [SUMMARY] Scan a directory for removable media devices and check media.
-    <dir> The directory.
-    [RETURNS] Nothing.
-*/
 {
     struct devfs_entry *de;
 
@@ -2184,14 +2304,17 @@
     }
 }   /*  End Function scan_dir_for_removable  */
 
+/**
+ *	get_removable_partition - Get removable media partition.
+ *	@dir: The parent directory.
+ *	@name: The name of the entry.
+ *	@namelen: The number of characters in <<name>>.
+ *
+ *	Returns 1 if the media was changed, else 0.
+ */
+
 static int get_removable_partition (struct devfs_entry *dir, const char *name,
 				    unsigned int namelen)
-/*  [SUMMARY] Get removable media partition.
-    <dir> The parent directory.
-    <name> The name of the entry.
-    <namelen> The number of characters in <<name>>.
-    [RETURNS] 1 if the media was changed, else 0.
-*/
 {
     struct devfs_entry *de;
 
@@ -2365,15 +2488,19 @@
     statfs:        devfs_statfs,
 };
 
+
+/**
+ *	get_vfs_inode - Get a VFS inode.
+ *	@sb: The super block.
+ *	@di: The devfs inode.
+ *	@dentry The dentry to register with the devfs inode.
+ *
+ *	Returns the inode on success, else %NULL.
+ */
+
 static struct inode *get_vfs_inode (struct super_block *sb,
 				    struct devfs_inode *di,
 				    struct dentry *dentry)
-/*  [SUMMARY] Get a VFS inode.
-    <sb> The super block.
-    <di> The devfs inode.
-    <dentry> The dentry to register with the devfs inode.
-    [RETURNS] The inode on success, else NULL.
-*/
 {
     struct inode *inode;
 
@@ -2551,9 +2678,13 @@
 
 /*  Dentry operations for device entries follow  */
 
+
+/**
+ *	devfs_d_release - Callback for when a dentry is freed.
+ *	@dentry: The dentry.
+ */
+
 static void devfs_d_release (struct dentry *dentry)
-/*  [SUMMARY] Callback for when a dentry is freed.
-*/
 {
 #ifdef CONFIG_DEVFS_DEBUG
     struct inode *inode = dentry->d_inode;
@@ -2564,9 +2695,13 @@
 #endif
 }   /*  End Function devfs_d_release  */
 
+/**
+ *	devfs_d_iput - Callback for when a dentry loses its inode.
+ *	@dentry: The dentry.
+ *	@inode:	The inode.
+ */
+
 static void devfs_d_iput (struct dentry *dentry, struct inode *inode)
-/*  [SUMMARY] Callback for when a dentry loses its inode.
-*/
 {
     struct devfs_inode *di;
 
@@ -2587,7 +2722,7 @@
     iput (inode);
 }   /*  End Function devfs_d_iput  */
 
-static void devfs_d_delete (struct dentry *dentry);
+static int devfs_d_delete (struct dentry *dentry);
 
 static struct dentry_operations devfs_dops =
 {
@@ -2606,9 +2741,12 @@
     d_revalidate: devfs_d_revalidate_wait,
 };
 
-static void devfs_d_delete (struct dentry *dentry)
-/*  [SUMMARY] Callback for when all files for a dentry are closed.
-*/
+/**
+ *	devfs_d_delete - Callback for when all files for a dentry are closed.
+ *	@detry: The dentry.
+ */
+
+static int devfs_d_delete (struct dentry *dentry)
 {
     struct inode *inode = dentry->d_inode;
     struct devfs_inode *di;
@@ -2623,8 +2761,7 @@
 	    printk ("%s: d_delete(): dropping negative dentry: %p\n",
 		    DEVFS_NAME, dentry);
 #endif
-	d_drop (dentry);
-	return;
+	return 1;
     }
     fs_info = inode->i_sb->u.generic_sbp;
     di = get_devfs_inode_from_vfs_inode (inode);
@@ -2633,16 +2770,16 @@
 	printk ("%s: d_delete(): dentry: %p  inode: %p  devfs_inode: %p\n",
 		DEVFS_NAME, dentry, inode, di);
 #endif
-    if (di == NULL) return;
-    if (di->de == NULL) return;
+    if (di == NULL) return 0;
+    if (di->de == NULL) return 0;
     if ( !S_ISCHR (di->mode) && !S_ISBLK (di->mode) && !S_ISREG (di->mode) )
-	return;
-    if (!di->de->u.fcb.open) return;
+	return 0;
+    if (!di->de->u.fcb.open) return 0;
     di->de->u.fcb.open = FALSE;
     if (di->de->u.fcb.aopen_notify)
 	devfsd_notify_one (di->de, DEVFSD_NOTIFY_CLOSE, inode->i_mode,
 			   current->euid, current->egid, fs_info);
-    if (!di->de->u.fcb.auto_owner) return;
+    if (!di->de->u.fcb.auto_owner) return 0;
     /*  Change the ownership/protection back  */
     di->mode = (di->mode & ~S_IALLUGO) | S_IRUGO | S_IWUGO;
     di->uid = di->de->u.fcb.default_uid;
@@ -2650,6 +2787,7 @@
     inode->i_mode = di->mode;
     inode->i_uid = di->uid;
     inode->i_gid = di->gid;
+    return 0;
 }   /*  End Function devfs_d_delete  */
 
 static int devfs_d_revalidate_wait (struct dentry *dentry, int flags)
@@ -3431,11 +3569,9 @@
 void __init mount_devfs_fs (void)
 {
     int err;
-    extern long do_sys_mount (char *dev_name, char *dir_name,
-			      char *type, int flags, void *data);
 
     if ( (boot_options & OPTION_NOMOUNT) ) return;
-    err = do_sys_mount ("none", "/dev", "devfs", 0, "");
+    err = do_mount ("none", "/dev", "devfs", 0, "");
     if (err == 0) printk ("Mounted devfs on /dev\n");
     else printk ("Warning: unable to mount devfs, err: %d\n", err);
 }   /*  End Function mount_devfs_fs  */
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/devfs/util.c linux/fs/devfs/util.c
--- v2.3.99-pre8/linux/fs/devfs/util.c	Wed Feb 16 17:03:52 2000
+++ linux/fs/devfs/util.c	Sat May 13 08:11:27 2000
@@ -38,13 +38,14 @@
 
 /*  Private functions follow  */
 
+/**
+ *	_devfs_convert_name - Convert from an old style location-based name to new style.
+ *	@new: The new name will be written here.
+ *	@old: The old name.
+ *	@disc: If true, disc partitioning information should be processed.
+ */
+
 static void __init _devfs_convert_name (char *new, const char *old, int disc)
-/*  [SUMMARY] Convert from an old style location-based name to new style.
-    <new> The new name will be written here.
-    <old> The old name.
-    <disc> If true, disc partitioning information should be processed.
-    [RETURNS] Nothing.
-*/
 {
     int host, bus, target, lun;
     char *ptr;
@@ -73,12 +74,12 @@
 
 /*  Public functions follow  */
 
-/*PUBLIC_FUNCTION*/
+/**
+ *	devfs_make_root - Create the root FS device entry if required.
+ *	@name: The name of the root FS device, as passed by "root=".
+ */
+
 void __init devfs_make_root (const char *name)
-/*  [SUMMARY] Create the root FS device entry if required.
-    <name> The name of the root FS device, as passed by "root=".
-    [RETURNS] Nothing.
-*/
 {
     char dest[64];
 
@@ -97,12 +98,13 @@
     devfs_mk_symlink (NULL, name, 0, DEVFS_FL_DEFAULT, dest, 0, NULL,NULL);
 }   /*  End Function devfs_make_root  */
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_register_tape - Register a tape device in the "/dev/tapes" hierarchy.
+ *	@de: Any tape device entry in the device directory.
+ */
+
 void devfs_register_tape (devfs_handle_t de)
-/*  [SUMMARY] Register a tape device in the "/dev/tapes" hierarchy.
-    <de> Any tape device entry in the device directory.
-    [RETURNS] Nothing.
-*/
 {
     int pos;
     devfs_handle_t parent, slave;
@@ -122,30 +124,31 @@
 }   /*  End Function devfs_register_tape  */
 EXPORT_SYMBOL(devfs_register_tape);
 
-/*PUBLIC_FUNCTION*/
+
+/**
+ *	devfs_register_series - Register a sequence of device entries.
+ *	@dir: The handle to the parent devfs directory entry. If this is %NULL the
+ *		new names are relative to the root of the devfs.
+ *	@format: The printf-style format string. A single "\%u" is allowed.
+ *	@flags: A set of bitwise-ORed flags (DEVFS_FL_*).
+ *	@major: The major number. Not needed for regular files.
+ *	@minor_start: The starting minor number. Not needed for regular files.
+ *	@mode: The default file mode.
+ *	@uid: The default UID of the file.
+ *	@guid: The default GID of the file.
+ *	@ops: The &file_operations or &block_device_operations structure.
+ *		This must not be externally deallocated.
+ *	@info: An arbitrary pointer which will be written to the private_data
+ *		field of the &file structure passed to the device driver. You can set
+ *		this to whatever you like, and change it once the file is opened (the next
+ *		file opened will not see this change).
+ */
+
 void devfs_register_series (devfs_handle_t dir, const char *format,
 			    unsigned int num_entries, unsigned int flags,
 			    unsigned int major, unsigned int minor_start,
 			    umode_t mode, uid_t uid, gid_t gid,
 			    void *ops, void *info)
-/*  [SUMMARY] Register a sequence of device entries.
-    <dir> The handle to the parent devfs directory entry. If this is NULL the
-    new names are relative to the root of the devfs.
-    <format> The printf-style format string. A single "%u" is allowed.
-    <flags> A set of bitwise-ORed flags (DEVFS_FL_*).
-    <major> The major number. Not needed for regular files.
-    <minor_start> The starting minor number. Not needed for regular files.
-    <mode> The default file mode.
-    <uid> The default UID of the file.
-    <guid> The default GID of the file.
-    <ops> The <<file_operations>> or <<block_device_operations>> structure.
-    This must not be externally deallocated.
-    <info> An arbitrary pointer which will be written to the <<private_data>>
-    field of the <<file>> structure passed to the device driver. You can set
-    this to whatever you like, and change it once the file is opened (the next
-    file opened will not see this change).
-    [RETURNS] Nothing.
-*/
 {
     unsigned int count;
     char devname[128];
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/exec.c linux/fs/exec.c
--- v2.3.99-pre8/linux/fs/exec.c	Thu May 11 15:30:08 2000
+++ linux/fs/exec.c	Sun May 21 11:38:47 2000
@@ -45,8 +45,8 @@
 #include <linux/kmod.h>
 #endif
 
-static struct linux_binfmt *formats = (struct linux_binfmt *) NULL;
-static spinlock_t binfmt_lock = SPIN_LOCK_UNLOCKED;
+static struct linux_binfmt *formats;
+static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED;
 
 int register_binfmt(struct linux_binfmt * fmt)
 {
@@ -56,17 +56,17 @@
 		return -EINVAL;
 	if (fmt->next)
 		return -EBUSY;
-	spin_lock(&binfmt_lock);
+	write_lock(&binfmt_lock);
 	while (*tmp) {
 		if (fmt == *tmp) {
-			spin_unlock(&binfmt_lock);
+			write_unlock(&binfmt_lock);
 			return -EBUSY;
 		}
 		tmp = &(*tmp)->next;
 	}
 	fmt->next = formats;
 	formats = fmt;
-	spin_unlock(&binfmt_lock);
+	write_unlock(&binfmt_lock);
 	return 0;	
 }
 
@@ -74,16 +74,16 @@
 {
 	struct linux_binfmt ** tmp = &formats;
 
-	spin_lock(&binfmt_lock);
+	write_lock(&binfmt_lock);
 	while (*tmp) {
 		if (fmt == *tmp) {
 			*tmp = fmt->next;
-			spin_unlock(&binfmt_lock);
+			write_unlock(&binfmt_lock);
 			return 0;
 		}
 		tmp = &(*tmp)->next;
 	}
-	spin_unlock(&binfmt_lock);
+	write_unlock(&binfmt_lock);
 	return -EINVAL;
 }
 
@@ -103,35 +103,34 @@
 {
 	int fd, retval;
 	struct file * file;
-	struct linux_binfmt * fmt;
 
-	lock_kernel();
 	fd = sys_open(library, 0, 0);
-	retval = fd;
 	if (fd < 0)
-		goto out;
+		return fd;
 	file = fget(fd);
 	retval = -ENOEXEC;
-	if (file && file->f_op && file->f_op->read) {
-		spin_lock(&binfmt_lock);
-		for (fmt = formats ; fmt ; fmt = fmt->next) {
-			if (!fmt->load_shlib)
-				continue;
-			if (!try_inc_mod_count(fmt->module))
-				continue;
-			spin_unlock(&binfmt_lock);
-			retval = fmt->load_shlib(file);
-			spin_lock(&binfmt_lock);
-			put_binfmt(fmt);
-			if (retval != -ENOEXEC)
-				break;
+	if (file) {
+		if(file->f_op && file->f_op->read) {
+			struct linux_binfmt * fmt;
+
+			read_lock(&binfmt_lock);
+			for (fmt = formats ; fmt ; fmt = fmt->next) {
+				if (!fmt->load_shlib)
+					continue;
+				if (!try_inc_mod_count(fmt->module))
+					continue;
+				read_unlock(&binfmt_lock);
+				retval = fmt->load_shlib(file);
+				read_lock(&binfmt_lock);
+				put_binfmt(fmt);
+				if (retval != -ENOEXEC)
+					break;
+			}
+			read_unlock(&binfmt_lock);
 		}
-		spin_unlock(&binfmt_lock);
+		fput(file);
 	}
-	fput(file);
 	sys_close(fd);
-out:
-	unlock_kernel();
   	return retval;
 }
 
@@ -288,6 +287,7 @@
 	if (!mpnt) 
 		return -ENOMEM; 
 	
+	down(&current->mm->mmap_sem);
 	{
 		mpnt->vm_mm = current->mm;
 		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
@@ -311,6 +311,7 @@
 		}
 		stack_base += PAGE_SIZE;
 	}
+	up(&current->mm->mmap_sem);
 	
 	return 0;
 }
@@ -745,14 +746,14 @@
 	}
 #endif
 	for (try=0; try<2; try++) {
-		spin_lock(&binfmt_lock);
+		read_lock(&binfmt_lock);
 		for (fmt = formats ; fmt ; fmt = fmt->next) {
 			int (*fn)(struct linux_binprm *, struct pt_regs *) = fmt->load_binary;
 			if (!fn)
 				continue;
 			if (!try_inc_mod_count(fmt->module))
 				continue;
-			spin_unlock(&binfmt_lock);
+			read_unlock(&binfmt_lock);
 			retval = fn(bprm, regs);
 			if (retval >= 0) {
 				put_binfmt(fmt);
@@ -762,16 +763,16 @@
 				current->did_exec = 1;
 				return retval;
 			}
-			spin_lock(&binfmt_lock);
+			read_lock(&binfmt_lock);
 			put_binfmt(fmt);
 			if (retval != -ENOEXEC)
 				break;
 			if (!bprm->file) {
-				spin_unlock(&binfmt_lock);
+				read_unlock(&binfmt_lock);
 				return retval;
 			}
 		}
-		spin_unlock(&binfmt_lock);
+		read_unlock(&binfmt_lock);
 		if (retval != -ENOEXEC) {
 			break;
 #ifdef CONFIG_KMOD
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/ext2/balloc.c linux/fs/ext2/balloc.c
--- v2.3.99-pre8/linux/fs/ext2/balloc.c	Mon Mar 27 08:08:29 2000
+++ linux/fs/ext2/balloc.c	Sat May 20 11:24:56 2000
@@ -209,7 +209,7 @@
 	 */
 	if (sb->u.ext2_sb.s_loaded_block_bitmaps > 0 &&
 	    sb->u.ext2_sb.s_block_bitmap_number[0] == block_group &&
-	    sb->u.ext2_sb.s_block_bitmap[block_group]) {
+	    sb->u.ext2_sb.s_block_bitmap[0]) {
 		return 0;
 	}
 	/*
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.3.99-pre8/linux/fs/ext2/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/ext2/namei.c	Sat May 20 10:55:26 2000
@@ -577,7 +577,6 @@
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->u.ext2_i.i_flags &= ~EXT2_BTREE_FL;
 	mark_inode_dirty(dir);
-	d_delete(dentry);
 
 end_rmdir:
 	brelse (bh);
@@ -619,7 +618,6 @@
 	mark_inode_dirty(inode);
 	inode->i_ctime = dir->i_ctime;
 	retval = 0;
-	d_delete(dentry);	/* This also frees the inode */
 
 end_unlink:
 	brelse (bh);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/balloc.c linux/fs/hfs/balloc.c
--- v2.3.99-pre8/linux/fs/hfs/balloc.c	Sun Jan  4 10:40:17 1998
+++ linux/fs/hfs/balloc.c	Mon May 15 10:47:12 2000
@@ -86,6 +86,8 @@
 	retval.bn->magic = HFS_BNODE_MAGIC;
 	retval.bn->tree = tree;
 	retval.bn->node = node;
+	hfs_init_waitqueue(&retval.bn->wqueue);
+	hfs_init_waitqueue(&retval.bn->rqueue);
 	hfs_bnode_lock(&retval, HFS_LOCK_WRITE);
 
 	retval.bn->buf = get_new_node(tree, node);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/catalog.c linux/fs/hfs/catalog.c
--- v2.3.99-pre8/linux/fs/hfs/catalog.c	Fri Jun  4 13:30:25 1999
+++ linux/fs/hfs/catalog.c	Mon May 15 12:00:34 2000
@@ -60,7 +60,7 @@
 	hfs_byte_t	RExtRec[12];	/* first extent record
 					   for the resource fork */
 	hfs_lword_t	Resrv;		/* reserved by Apple */
-} FIL_REC;
+} __attribute__((packed)) FIL_REC;
 
 /* the catalog record for a directory */
 typedef struct {
@@ -74,14 +74,14 @@
 	hfs_dinfo_t	UsrInfo;	/* data used by the Finder */
 	hfs_dxinfo_t	FndrInfo;	/* more data used by Finder */
 	hfs_byte_t	Resrv[16];	/* reserved by Apple */
-} DIR_REC;
+} __attribute__((packed)) DIR_REC;
 
 /* the catalog record for a thread */
 typedef struct {
 	hfs_byte_t		Reserv[8];	/* reserved by Apple */
 	hfs_lword_t		ParID;		/* CNID of parent directory */
 	struct hfs_name		CName;		/* The name of this entry */
-} THD_REC;
+}  __attribute__((packed)) THD_REC;
 
 /* A catalog tree record */
 struct hfs_cat_rec {
@@ -92,7 +92,7 @@
 		DIR_REC dir;
 		THD_REC thd;
 	} u;
-};
+} __attribute__((packed));
 
 /*================ File-local variables ================*/
  
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/dir.c linux/fs/hfs/dir.c
--- v2.3.99-pre8/linux/fs/hfs/dir.c	Tue Apr 11 15:09:21 2000
+++ linux/fs/hfs/dir.c	Sat May 20 10:55:27 2000
@@ -274,7 +274,6 @@
 		inode->i_nlink--; 
 		inode->i_ctime = CURRENT_TIME;
 		mark_inode_dirty(inode);
-		d_delete(dentry);
 		update_dirs_minus(entry, 0);
 	}
 
@@ -328,7 +327,6 @@
 	inode->i_nlink = 0;
 	inode->i_ctime = CURRENT_TIME;
 	mark_inode_dirty(inode);
-	d_delete(dentry);
 	update_dirs_minus(entry, 1);
 	 
 hfs_rmdir_put:
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- v2.3.99-pre8/linux/fs/hfs/file_hdr.c	Sat Feb 26 22:31:52 2000
+++ linux/fs/hfs/file_hdr.c	Mon May 15 12:00:34 2000
@@ -158,7 +158,7 @@
         hfs_byte_t	filler[16];
         hfs_word_t	entries;
         hfs_byte_t	descrs[12*HFS_HDR_MAX];
-};
+}  __attribute__((packed));
 
 /*================ File-local functions ================*/
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/hfs.h linux/fs/hfs/hfs.h
--- v2.3.99-pre8/linux/fs/hfs/hfs.h	Thu Feb 10 17:11:17 2000
+++ linux/fs/hfs/hfs.h	Mon May 15 12:00:34 2000
@@ -130,7 +130,7 @@
 struct hfs_name {
 	hfs_byte_t	Len;
 	hfs_byte_t	Name[31];
-};
+} __attribute__((packed));
 
 typedef struct {
 	hfs_word_t	v;
@@ -150,21 +150,21 @@
 	hfs_word_t	 fdFlags;
 	hfs_point_t	 fdLocation;
 	hfs_word_t	 fdFldr;
-} hfs_finfo_t;
+} __attribute__((packed)) hfs_finfo_t;
 
 typedef struct {
 	hfs_word_t	fdIconID;
 	hfs_byte_t	fdUnused[8];
 	hfs_word_t	fdComment;
 	hfs_lword_t	fdPutAway;
-} hfs_fxinfo_t;
+} __attribute__((packed)) hfs_fxinfo_t;
 
 typedef struct {
 	hfs_rect_t	frRect;
 	hfs_word_t	frFlags;
 	hfs_point_t	frLocation;
 	hfs_word_t	frView;
-} hfs_dinfo_t;
+} __attribute__((packed)) hfs_dinfo_t;
 
 typedef struct {
 	hfs_point_t	frScroll;
@@ -172,7 +172,7 @@
 	hfs_word_t	frUnused;
 	hfs_word_t	frComment;
 	hfs_lword_t	frPutAway;
-} hfs_dxinfo_t;
+} __attribute__((packed)) hfs_dxinfo_t;
 
 union hfs_finder_info {
 	struct {
@@ -189,7 +189,7 @@
 struct hfs_bkey {
 	hfs_byte_t	KeyLen;		/* number of bytes in the key */
 	hfs_byte_t	value[1];	/* (KeyLen) bytes of key */
-};
+} __attribute__((packed));
 
 /* Cast to a pointer to a generic bkey */
 #define	HFS_BKEY(X)	(((void)((X)->KeyLen)), ((struct hfs_bkey *)(X)))
@@ -200,7 +200,7 @@
 	hfs_byte_t	Resrv1;	/* padding */
 	hfs_lword_t	ParID;	/* CNID of the parent dir */
 	struct hfs_name	CName;	/* The filename of the entry */
-};
+} __attribute__((packed));
 
 /* The key used in the extents b-tree: */
 struct hfs_ext_key {
@@ -208,7 +208,7 @@
 	hfs_byte_t	FkType;	/* HFS_FK_{DATA,RSRC} */
 	hfs_lword_t	FNum;	/* The File ID of the file */
 	hfs_word_t	FABN;	/* allocation blocks number*/
-};
+} __attribute__((packed));
 
 /*======== Data structures kept in memory ========*/
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/hfs_btree.h linux/fs/hfs/hfs_btree.h
--- v2.3.99-pre8/linux/fs/hfs/hfs_btree.h	Fri Jan 21 18:19:17 2000
+++ linux/fs/hfs/hfs_btree.h	Mon May 15 12:00:34 2000
@@ -90,7 +90,7 @@
         hfs_byte_t  bthResv2;   /* reserved */
         hfs_lword_t bthAtrb;    /* (F) attributes */
         hfs_lword_t bthResv3[16]; /* Reserved */
-};
+} __attribute__((packed));
 
 /*
  * struct NodeDescriptor
@@ -112,7 +112,7 @@
 	hfs_byte_t  ndNHeight;	/* (F) The level of this node (leaves=1) */
 	hfs_word_t  ndNRecs;	/* (V) The number of records in this node */
 	hfs_word_t  ndResv2;	/* Reserved */
-};
+} __attribute__((packed));
 
 /*
  * typedef hfs_cmpfn
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/mdb.c linux/fs/hfs/mdb.c
--- v2.3.99-pre8/linux/fs/hfs/mdb.c	Fri Jun  4 13:30:25 1999
+++ linux/fs/hfs/mdb.c	Mon May 15 12:00:34 2000
@@ -71,7 +71,7 @@
 	hfs_byte_t	drXTExtRec[12];	/* extents B-tree's first 3 extents */
 	hfs_lword_t	drCTFlSize;	/* bytes in the catalog B-tree */
 	hfs_byte_t	drCTExtRec[12];	/* catalog B-tree's first 3 extents */
-};
+} __attribute__((packed));
 
 /*================ Global functions ================*/
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hfs/part_tbl.c linux/fs/hfs/part_tbl.c
--- v2.3.99-pre8/linux/fs/hfs/part_tbl.c	Sun Jan  4 10:40:17 1998
+++ linux/fs/hfs/part_tbl.c	Mon May 15 12:00:34 2000
@@ -77,7 +77,7 @@
 		hfs_lword_t	pdSize;
 		hfs_lword_t	pdFSID;
 	}	pdEntry[42];
-};
+} __attribute__((packed));
 
 /*================ File-local functions ================*/
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/hpfs/namei.c linux/fs/hpfs/namei.c
--- v2.3.99-pre8/linux/fs/hpfs/namei.c	Thu May 11 15:30:08 2000
+++ linux/fs/hpfs/namei.c	Sat May 20 10:55:27 2000
@@ -326,7 +326,6 @@
 	if (r != 2) {
 		inode->i_nlink--;
 		hpfs_unlock_2inodes(dir, inode);
-		d_delete(dentry);
 	} else {	/* no space for deleting, try to truncate file */
 		struct iattr newattrs;
 		int err;
@@ -388,7 +387,6 @@
 		dir->i_nlink--;
 		inode->i_nlink = 0;
 		hpfs_unlock_2inodes(dir, inode);
-		d_delete(dentry);
 	} else hpfs_unlock_2inodes(dir, inode);
 	return r == 2 ? -ENOSPC : r == 1 ? -EFSERROR : 0;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/inode.c linux/fs/inode.c
--- v2.3.99-pre8/linux/fs/inode.c	Thu May 11 15:30:08 2000
+++ linux/fs/inode.c	Mon May 15 14:54:33 2000
@@ -377,7 +377,7 @@
  *
  *	Discard all of the inodes for a given superblock. If the discard
  *	fails because there are busy inodes then a non zero value is returned.
- *	If the discard is successful all the inodes are dicarded.
+ *	If the discard is successful all the inodes have been discarded.
  */
  
 int invalidate_inodes(struct super_block * sb)
@@ -470,7 +470,7 @@
 /*
  * Called with the inode lock held.
  * NOTE: we are not increasing the inode-refcount, you must call __iget()
- * by hand after calling find_inode now! This simplify iunique and won't
+ * by hand after calling find_inode now! This simplifies iunique and won't
  * add any additional branch in the common code.
  */
 static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/lockd/clntproc.c linux/fs/lockd/clntproc.c
--- v2.3.99-pre8/linux/fs/lockd/clntproc.c	Tue Apr 11 15:09:22 2000
+++ linux/fs/lockd/clntproc.c	Sat May 13 09:43:55 2000
@@ -233,11 +233,21 @@
 	struct rpc_clnt	*clnt;
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_res	*resp = &req->a_res;
+	struct file	*filp = argp->lock.fl.fl_file;
+	struct rpc_message msg;
 	int		status;
 
 	dprintk("lockd: call procedure %s on %s\n",
 			nlm_procname(proc), host->h_name);
 
+	msg.rpc_proc = proc;
+	msg.rpc_argp = argp;
+	msg.rpc_resp = resp;
+	if (filp)
+		msg.rpc_cred = nfs_file_cred(filp);
+	else
+		msg.rpc_cred = NULL;
+
 	do {
 		if (host->h_reclaiming && !argp->reclaim) {
 			interruptible_sleep_on(&host->h_gracewait);
@@ -249,7 +259,7 @@
 			return -ENOLCK;
 
 		/* Perform the RPC call. If an error occurs, try again */
-		if ((status = rpc_call(clnt, proc, argp, resp, 0)) < 0) {
+		if ((status = rpc_call_sync(clnt, &msg, 0)) < 0) {
 			dprintk("lockd: rpc_call returned error %d\n", -status);
 			switch (status) {
 			case -EPROTONOSUPPORT:
@@ -330,11 +340,31 @@
 nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
 {
 	struct nlm_host	*host = req->a_host;
-	int status;
+	struct rpc_clnt	*clnt;
+	struct nlm_args	*argp = &req->a_args;
+	struct nlm_res	*resp = &req->a_res;
+	struct file	*file = argp->lock.fl.fl_file;
+	struct rpc_message msg;
+	int		status;
 
+	dprintk("lockd: call procedure %s on %s (async)\n",
+			nlm_procname(proc), host->h_name);
+
+	/* If we have no RPC client yet, create one. */
+	if ((clnt = nlm_bind_host(host)) == NULL)
+		return -ENOLCK;
+
+        /* bootstrap and kick off the async RPC call */
+	msg.rpc_proc = proc;
+	msg.rpc_argp = argp;
+	msg.rpc_resp =resp;
+	if (file)
+		msg.rpc_cred = nfs_file_cred(file);
+	else
+		msg.rpc_cred = NULL;
 	/* Increment host refcount */
 	nlm_get_host(host);
-	status = nlmsvc_async_call(req, proc, callback);
+        status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
 	if (status < 0)
 		nlm_release_host(host);
 	return status;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/lockd/svclock.c linux/fs/lockd/svclock.c
--- v2.3.99-pre8/linux/fs/lockd/svclock.c	Tue Apr 11 15:09:22 2000
+++ linux/fs/lockd/svclock.c	Sat May 13 09:43:55 2000
@@ -533,8 +533,10 @@
 	nlmsvc_insert_block(block, jiffies + 30 * HZ);
 
 	/* Call the client */
-	nlmclnt_async_call(&block->b_call, NLMPROC_GRANTED_MSG,
-						nlmsvc_grant_callback);
+	nlm_get_host(block->b_call.a_host);
+	if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG,
+						nlmsvc_grant_callback) < 0)
+		nlm_release_host(block->b_call.a_host);
 	up(&file->f_sema);
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.3.99-pre8/linux/fs/minix/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/minix/namei.c	Sat May 20 10:55:27 2000
@@ -409,7 +409,6 @@
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->i_nlink--;
 	mark_inode_dirty(dir);
-	d_delete(dentry);
 	retval = 0;
 end_rmdir:
 	brelse(bh);
@@ -444,7 +443,6 @@
 	inode->i_nlink--;
 	inode->i_ctime = dir->i_ctime;
 	mark_inode_dirty(inode);
-	d_delete(dentry);	/* This also frees the inode */
 	retval = 0;
 end_unlink:
 	brelse(bh);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.3.99-pre8/linux/fs/msdos/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/msdos/namei.c	Sat May 20 10:55:27 2000
@@ -337,7 +337,6 @@
 	dir->i_nlink--;
 	mark_inode_dirty(inode);
 	mark_inode_dirty(dir);
-	d_delete(dentry);
 	res = 0;
 
 rmdir_done:
@@ -432,7 +431,6 @@
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(inode);
 	mark_inode_dirty(dir);
-	d_delete(dentry);	/* This also frees the inode */
 	res = 0;
 unlink_done:
 	return res;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/namei.c linux/fs/namei.c
--- v2.3.99-pre8/linux/fs/namei.c	Thu May 11 15:30:08 2000
+++ linux/fs/namei.c	Sat May 20 10:55:27 2000
@@ -902,20 +902,18 @@
 		if (nd->last.name[nd->last.len])
 			goto exit;
 
-		dir = dget(nd->dentry);
+		dir = nd->dentry;
 		down(&dir->d_inode->i_sem);
 
 		dentry = lookup_hash(&nd->last, nd->dentry);
 		error = PTR_ERR(dentry);
 		if (IS_ERR(dentry)) {
 			up(&dir->d_inode->i_sem);
-			dput(dir);
 			goto exit;
 		}
 
 		if (dentry->d_inode) {
 			up(&dir->d_inode->i_sem);
-			dput(dir);
 			error = -EEXIST;
 			if (flag & O_EXCL)
 				goto exit_dput;
@@ -940,12 +938,12 @@
 				goto exit;
 		} else {
 			error = vfs_create(dir->d_inode, dentry, mode);
+			up(&dir->d_inode->i_sem);
 			/* Don't check for write permission, don't truncate */
 			acc_mode = 0;
 			flag &= ~O_TRUNC;
 			dput(nd->dentry);
 			nd->dentry = dentry;
-			unlock_dir(dir);
 			if (error)
 				goto exit;
 		}
@@ -1219,6 +1217,8 @@
 	if (!error)
 		dentry->d_inode->i_flags |= S_DEAD;
 	double_up(&dir->i_zombie, &dentry->d_inode->i_zombie);
+	if (!error)
+		d_delete(dentry);
 	dput(dentry);
 
 	return error;
@@ -1276,6 +1276,8 @@
 		if (dir->i_op && dir->i_op->unlink) {
 			DQUOT_INIT(dir);
 			error = dir->i_op->unlink(dir, dentry);
+			if (!error)
+				d_delete(dentry);
 		}
 	}
 	up(&dir->i_zombie);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.3.99-pre8/linux/fs/ncpfs/dir.c	Fri Mar 10 16:40:47 2000
+++ linux/fs/ncpfs/dir.c	Sat May 20 10:55:27 2000
@@ -71,7 +71,7 @@
 static int ncp_lookup_validate(struct dentry *, int);
 static int ncp_hash_dentry(struct dentry *, struct qstr *);
 static int ncp_compare_dentry (struct dentry *, struct qstr *, struct qstr *);
-static void ncp_delete_dentry(struct dentry *);
+static int ncp_delete_dentry(struct dentry *);
 
 struct dentry_operations ncp_dentry_operations =
 {
@@ -119,32 +119,22 @@
 
 /*
  * This is the callback from dput() when d_count is going to 0.
- * We use this to unhash dentries with bad inodes and close files.
+ * We use this to unhash dentries with bad inodes.
+ * Closing files can be safely postponed until iput() - it's done there anyway.
  */
-static void
+static int
 ncp_delete_dentry(struct dentry * dentry)
 {
 	struct inode *inode = dentry->d_inode;
 
-	if (inode)
-	{
+	if (inode) {
 		if (is_bad_inode(inode))
-		{
-			d_drop(dentry);
-		}
-		/*
-		 * Lock the superblock, then recheck the dentry count.
-		 * (Somebody might have used it again ...)
-		 */
-		if (dentry->d_count == 1 && NCP_FINFO(inode)->opened) {
-			PPRINTK("ncp_delete_dentry: closing file %s/%s\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name);
-			ncp_make_closed(inode);
-		}
+			return 1;
 	} else
 	{
 	/* N.B. Unhash negative dentries? */
 	}
+	return 0;
 }
 
 static inline int
@@ -1000,7 +990,6 @@
 		case 0x00:
 			DPRINTK("ncp: removed %s/%s\n",
 				dentry->d_parent->d_name.name, dentry->d_name.name);
-			d_delete(dentry);
 			break;
 		case 0x85:
 		case 0x8A:
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.3.99-pre8/linux/fs/nfs/dir.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/nfs/dir.c	Sun May 21 20:53:32 2000
@@ -35,8 +35,6 @@
 #define NFS_PARANOIA 1
 /* #define NFS_DEBUG_VERBOSE 1 */
 
-static int nfs_safe_remove(struct dentry *);
-
 static int nfs_readdir(struct file *, void *, filldir_t);
 static struct dentry *nfs_lookup(struct inode *, struct dentry *);
 static int nfs_create(struct inode *, struct dentry *, int);
@@ -71,6 +69,70 @@
 };
 
 typedef u32 * (*decode_dirent_t)(u32 *, struct nfs_entry *, int);
+typedef struct {
+	struct file	*file;
+	struct page	*page;
+	unsigned long	page_index;
+	unsigned	page_offset;
+	u64		target;
+	struct nfs_entry *entry;
+	decode_dirent_t	decode;
+	int		plus;
+	int		error;
+} nfs_readdir_descriptor_t;
+
+/* Now we cache directories properly, by stuffing the dirent
+ * data directly in the page cache.
+ *
+ * Inode invalidation due to refresh etc. takes care of
+ * _everything_, no sloppy entry flushing logic, no extraneous
+ * copying, network direct to page cache, the way it was meant
+ * to be.
+ *
+ * NOTE: Dirent information verification is done always by the
+ *	 page-in of the RPC reply, nowhere else, this simplies
+ *	 things substantially.
+ */
+static
+int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page *page)
+{
+	struct file	*file = desc->file;
+	struct inode	*inode = file->f_dentry->d_inode;
+	void		*buffer = (void *)kmap(page);
+	int		plus = NFS_USE_READDIRPLUS(inode);
+	int		error;
+
+	dfprintk(VFS, "NFS: nfs_readdir_filler() reading cookie %Lu into page %lu.\n", (long long)desc->entry->cookie, page->index);
+
+ again:
+	error = NFS_PROTO(inode)->readdir(file, desc->entry->cookie, buffer,
+					  NFS_SERVER(inode)->dtsize, plus);
+	/* We requested READDIRPLUS, but the server doesn't grok it */
+	if (desc->plus && error == -ENOTSUPP) {
+		NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
+		plus = 0;
+		goto again;
+	}
+	if (error < 0)
+		goto error;
+	SetPageUptodate(page);
+	kunmap(page);
+	/* Ensure consistent page alignment of the data.
+	 * Note: assumes we have exclusive access to this mapping either
+	 *	 throught inode->i_sem or some other mechanism.
+	 */
+	if (page->index == 0)
+		invalidate_inode_pages(inode);
+	UnlockPage(page);
+	return 0;
+ error:
+	SetPageError(page);
+	kunmap(page);
+	UnlockPage(page);
+	invalidate_inode_pages(inode);
+	desc->error = error;
+	return -EIO;
+}
 
 /*
  * Given a pointer to a buffer that has already been filled by a call
@@ -81,309 +143,217 @@
  * read.
  */
 static inline
-long find_dirent(struct page *page, loff_t offset,
-		 struct nfs_entry *entry,
-		 decode_dirent_t decode, int plus, int use_cookie)
-{
-	u8		*p = (u8 *)kmap(page),
-			*start = p;
-	unsigned long	base = page_offset(page),
-			pg_offset = 0;
-	int		loop_count = 0;
+int find_dirent(nfs_readdir_descriptor_t *desc, struct page *page)
+{
+	struct nfs_entry *entry = desc->entry;
+	char		*start = (char *)kmap(page),
+			*p = start;
+	int		loop_count = 0,
+			status = 0;
 
-	if (!p)
-		return -EIO;
 	for(;;) {
-		p = (u8*)decode((__u32*)p, entry, plus);
-		if (IS_ERR(p))
+		p = (char *)desc->decode((u32*)p, entry, desc->plus);
+		if (IS_ERR(p)) {
+			status = PTR_ERR(p);
 			break;
-		pg_offset = p - start;
-		entry->prev = entry->offset;
-		entry->offset = base + pg_offset;
-		if ((use_cookie ? entry->cookie : entry->offset) > offset)
+		}
+		desc->page_offset = p - start;
+		dfprintk(VFS, "NFS: found cookie %Lu\n", (long long)entry->cookie);
+		if (entry->prev_cookie == desc->target)
 			break;
 		if (loop_count++ > 200) {
 			loop_count = 0;
 			schedule();
 		}
 	}
-
 	kunmap(page);
-	return (IS_ERR(p)) ?  PTR_ERR(p) : (long)pg_offset;
+	dfprintk(VFS, "NFS: find_dirent() returns %d\n", status);
+	return status;
 }
 
 /*
  * Find the given page, and call find_dirent() in order to try to
  * return the next entry.
- *
- * Returns -EIO if the page is not available, or up to date.
  */
 static inline
-long find_dirent_page(struct inode *inode, loff_t offset,
-		      struct nfs_entry *entry)
+int find_dirent_page(nfs_readdir_descriptor_t *desc)
 {
-	decode_dirent_t	decode = NFS_PROTO(inode)->decode_dirent;
+	struct inode	*inode = desc->file->f_dentry->d_inode;
 	struct page	*page;
-	unsigned long	index = entry->offset >> PAGE_CACHE_SHIFT;
-	long		status = -EIO;
-	int		plus = NFS_USE_READDIRPLUS(inode),
-			use_cookie = NFS_MONOTONE_COOKIES(inode);
-
-	dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", entry->offset & PAGE_CACHE_MASK);
-
-	if (entry->page)
-		page_cache_release(entry->page);
-
-	page = find_get_page(&inode->i_data, index);
-
-	if (page && Page_Uptodate(page))
-		status = find_dirent(page, offset, entry, decode, plus, use_cookie);
-
-	/* NB: on successful return we will be holding the page */
-	if (status < 0) {
-		entry->page = NULL;
-		if (page)
-			page_cache_release(page);
-	} else
-		entry->page = page;
+	unsigned long	index = desc->page_index;
+	int		status;
+
+	dfprintk(VFS, "NFS: find_dirent_page() searching directory page %ld\n", desc->page_index);
 
-	dfprintk(VFS, "NFS: find_dirent_page() returns %ld\n", status);
+	if (desc->page) {
+		page_cache_release(desc->page);
+		desc->page = NULL;
+	}
+
+	page = read_cache_page(&inode->i_data, index,
+			       (filler_t *)nfs_readdir_filler, desc);
+	if (IS_ERR(page)) {
+		status = PTR_ERR(page);
+		goto out;
+	}
+	if (!Page_Uptodate(page))
+		goto read_error;
+
+	/* NOTE: Someone else may have changed the READDIRPLUS flag */
+	desc->plus = NFS_USE_READDIRPLUS(inode);
+	status = find_dirent(desc, page);
+	if (status >= 0)
+		desc->page = page;
+	else
+		page_cache_release(page);
+ out:
+	dfprintk(VFS, "NFS: find_dirent_page() returns %d\n", status);
 	return status;
+ read_error:
+	page_cache_release(page);
+	return -EIO;
 }
 
-
 /*
  * Recurse through the page cache pages, and return a
  * filled nfs_entry structure of the next directory entry if possible.
  *
- * The target for the search is position 'offset'.
- * The latter may either be an offset into the page cache, or (better)
- * a cookie depending on whether we're interested in strictly following
- * the RFC wrt. not assuming monotonicity of cookies or not.
- *
- * For most systems, the latter is more reliable since it naturally
- * copes with holes in the directory.
+ * The target for the search is 'desc->target'.
  */
 static inline
-long search_cached_dirent_pages(struct inode *inode, loff_t offset,
-				struct nfs_entry *entry)
+int readdir_search_pagecache(nfs_readdir_descriptor_t *desc)
 {
-	long		res = 0;
+	int		res = 0;
 	int		loop_count = 0;
 
-	dfprintk(VFS, "NFS: search_cached_dirent_pages() searching for cookie %Ld\n", (long long)offset);
+	dfprintk(VFS, "NFS: readdir_search_pagecache() searching for cookie %Lu\n", (long long)desc->target);
 	for (;;) {
-		res = find_dirent_page(inode, offset, entry);
-		if (res == -EAGAIN) {
-			/* Align to beginning of next page */
-			entry->offset &= PAGE_CACHE_MASK;
-			entry->offset += PAGE_CACHE_SIZE;
-		}
+		res = find_dirent_page(desc);
 		if (res != -EAGAIN)
 			break;
+		/* Align to beginning of next page */
+		desc->page_offset = 0;
+		desc->page_index ++;
 		if (loop_count++ > 200) {
 			loop_count = 0;
 			schedule();
 		}
 	}
-	if (res < 0 && entry->page) {
-		page_cache_release(entry->page);
-		entry->page = NULL;
-	}
-	dfprintk(VFS, "NFS: search_cached_dirent_pages() returned %ld\n", res);
-	return res;
-}
-
-
-/* Now we cache directories properly, by stuffing the dirent
- * data directly in the page cache.
- *
- * Inode invalidation due to refresh etc. takes care of
- * _everything_, no sloppy entry flushing logic, no extraneous
- * copying, network direct to page cache, the way it was meant
- * to be.
- *
- * NOTE: Dirent information verification is done always by the
- *	 page-in of the RPC reply, nowhere else, this simplies
- *	 things substantially.
- */
-static inline
-long try_to_get_dirent_page(struct file *file, struct inode *inode,
-			    struct nfs_entry *entry)
-{
-	struct dentry	*dir = file->f_dentry;
-	struct page	*page;
-	__u32		*p;
-	unsigned long	index = entry->offset >> PAGE_CACHE_SHIFT;
-	long		res = 0;
-	unsigned int	dtsize = NFS_SERVER(inode)->dtsize;
-	int		plus = NFS_USE_READDIRPLUS(inode);
-
-	dfprintk(VFS, "NFS: try_to_get_dirent_page() reading directory page @ index %ld\n", index);
-
-	page = grab_cache_page(&inode->i_data, index);
-
-	if (!page) {
-		res = -ENOMEM;
-		goto out;
-	}
-
-	if (Page_Uptodate(page)) {
-		dfprintk(VFS, "NFS: try_to_get_dirent_page(): page already up to date.\n");
-		goto unlock_out;
-	}
-
-	p = (__u32 *)kmap(page);
-
-	if (dtsize > PAGE_CACHE_SIZE)
-		dtsize = PAGE_CACHE_SIZE;
-	res = NFS_PROTO(inode)->readdir(dir, entry->cookie, p, dtsize, plus);
-
-	kunmap(page);
-
-	if (res < 0)
-		goto error;
-	if (PageError(page))
-		ClearPageError(page);
-	SetPageUptodate(page);
-
- unlock_out:
-	UnlockPage(page);
-	page_cache_release(page);
- out:
-	dfprintk(VFS, "NFS: try_to_get_dirent_page() returns %ld\n", res);
+	dfprintk(VFS, "NFS: readdir_search_pagecache() returned %d\n", res);
 	return res;
- error:
-	SetPageError(page);
-	goto unlock_out;
 }
 
-/* Recover from a revalidation flush.  The case here is that
- * the inode for the directory got invalidated somehow, and
- * all of our cached information is lost.  In order to get
- * a correct cookie for the current readdir request from the
- * user, we must (re-)fetch all the older readdir page cache
- * entries.
- *
- * Returns < 0 if some error occurs.
+/*
+ * Once we've found the start of the dirent within a page: fill 'er up...
  */
-static inline
-long refetch_to_readdir(struct file *file, struct inode *inode,
-			loff_t off, struct nfs_entry *entry)
-{
-	struct nfs_entry	my_dirent,
-				*dirent = &my_dirent;
-	long			res;
-	int			plus = NFS_USE_READDIRPLUS(inode),
-				use_cookie = NFS_MONOTONE_COOKIES(inode),
-				loop_count = 0;
-
-	dfprintk(VFS, "NFS: refetch_to_readdir() searching for cookie %Ld\n", (long long)off);
-	*dirent = *entry;
-	entry->page = NULL;
-
-	for (res = 0;res >= 0;) {
-		if (loop_count++ > 200) {
-			loop_count = 0;
-			schedule();
-		}
+static 
+int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent,
+		   filldir_t filldir)
+{
+	struct file	*file = desc->file;
+	struct nfs_entry *entry = desc->entry;
+	char		*start = (char *)kmap(desc->page),
+			*p = start + desc->page_offset;
+	unsigned long	fileid;
+	int		loop_count = 0,
+			res = 0;
 
-		/* Search for last cookie in page cache */
-		res = search_cached_dirent_pages(inode, off, dirent);
+	dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ cookie %Lu\n", (long long)desc->target);
 
-		if (res >= 0) {
-			/* Cookie was found */
-			if ((use_cookie?dirent->cookie:dirent->offset) > off) {
-				*entry = *dirent;
-				dirent->page = NULL;
-				break;
+	for(;;) {
+		/* Note: entry->prev_cookie contains the cookie for
+		 *	 retrieving the current dirent on the server */
+		fileid = nfs_fileid_to_ino_t(entry->ino);
+		res = filldir(dirent, entry->name, entry->len, 
+			      entry->prev_cookie, fileid);
+		if (res < 0)
+			break;
+		file->f_pos = desc->target = entry->cookie;
+		p = (char *)desc->decode((u32 *)p, entry, desc->plus);
+		if (IS_ERR(p)) {
+			if (PTR_ERR(p) == -EAGAIN) {
+				desc->page_offset = 0;
+				desc->page_index ++;
 			}
-			continue;
-		}
-
-		if (dirent->page)
-			page_cache_release(dirent->page);
-		dirent->page = NULL;
-
-		if (res != -EIO) {
-			*entry = *dirent;
 			break;
 		}
-
-		/* Read in a new page */
-		res = try_to_get_dirent_page(file, inode, dirent);
-		if (res == -EBADCOOKIE) {
-			memset(dirent, 0, sizeof(*dirent));
-			nfs_zap_caches(inode);
-			res = 0;
-		}
-		/* We requested READDIRPLUS, but the server doesn't grok it */
-		if (plus && res == -ENOTSUPP) {
-			NFS_FLAGS(inode) &= ~NFS_INO_ADVISE_RDPLUS;
-			memset(dirent, 0, sizeof(*dirent));
-			nfs_zap_caches(inode);
-			plus = 0;
-			res = 0;
+		desc->page_offset = p - start;
+		if (loop_count++ > 200) {
+			loop_count = 0;
+			schedule();
 		}
 	}
-	if (dirent->page)
-		page_cache_release(dirent->page);
+	kunmap(desc->page);
+	page_cache_release(desc->page);
+	desc->page = NULL;
 
-	dfprintk(VFS, "NFS: refetch_to_readdir() returns %ld\n", res);
+	dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", (long long)desc->target, res);
 	return res;
 }
 
 /*
- * Once we've found the start of the dirent within a page: fill 'er up...
+ * If we cannot find a cookie in our cache, we suspect that this is
+ * because it points to a deleted file, so we ask the server to return
+ * whatever it thinks is the next entry. We then feed this to filldir.
+ * If all goes well, we should then be able to find our way round the
+ * cache on the next call to readdir_search_pagecache();
+ *
+ * NOTE: we cannot add the anonymous page to the pagecache because
+ *	 the data it contains might not be page aligned. Besides,
+ *	 we should already have a complete representation of the
+ *	 directory in the page cache by the time we get here.
  */
-static
-int nfs_do_filldir(struct file *file, struct inode *inode,
-		   struct nfs_entry *entry, void *dirent, filldir_t filldir)
+static inline
+int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent,
+		     filldir_t filldir)
 {
-	decode_dirent_t	decode = NFS_PROTO(inode)->decode_dirent;
-	struct page	*page = entry->page;
-	__u8		*p,
-			*start;
-	unsigned long	base = page_offset(page),
-			offset = entry->offset,
-			pg_offset,
-			fileid;
-	int		plus = NFS_USE_READDIRPLUS(inode),
-			use_cookie = NFS_MONOTONE_COOKIES(inode),
-			loop_count = 0,
-			res = 0;
-
-	dfprintk(VFS, "NFS: nfs_do_filldir() filling starting @ offset %ld\n", entry->offset);
-	pg_offset = offset & ~PAGE_CACHE_MASK;
-	start = (u8*)kmap(page);
-	p = start + pg_offset;
+	struct file	*file = desc->file;
+	struct inode	*inode = file->f_dentry->d_inode;
+	struct page	*page = NULL;
+	u32		*p;
+	int		status = -EIO;
+
+	dfprintk(VFS, "NFS: uncached_readdir() searching for cookie %Lu\n", (long long)desc->target);
+	if (desc->page) {
+		page_cache_release(desc->page);
+		desc->page = NULL;
+	}
 
-	for(;;) {
-		/* Note: entry->prev contains the offset of the start of the
-		 *       current dirent */
-		fileid = nfs_fileid_to_ino_t(entry->ino);
-		if (use_cookie)
-			res = filldir(dirent, entry->name, entry->len, entry->prev_cookie, fileid);
+	page = page_cache_alloc();
+	if (!page) {
+		status = -ENOMEM;
+		goto out;
+	}
+	p = (u32 *)kmap(page);
+	status = NFS_PROTO(inode)->readdir(file, desc->target, p,
+					   NFS_SERVER(inode)->dtsize, 0);
+	if (status >= 0) {
+		p = desc->decode(p, desc->entry, 0);
+		if (IS_ERR(p))
+			status = PTR_ERR(p);
 		else
-			res = filldir(dirent, entry->name, entry->len, entry->prev, fileid);
-		if (res < 0)
-			break;
-		file->f_pos = (use_cookie) ? entry->cookie : entry->offset;
-		p = (u8*)decode((__u32*)p, entry, plus);
-		if (!p || IS_ERR(p))
-			break;
-		pg_offset = p - start;
-		entry->prev = entry->offset;
-		entry->offset = base + pg_offset;
-		if (loop_count++ > 200) {
-			loop_count = 0;
-			schedule();
-		}
+			desc->entry->prev_cookie = desc->target;
 	}
 	kunmap(page);
+	if (status < 0)
+		goto out_release;
 
-	dfprintk(VFS, "NFS: nfs_do_filldir() filling ended @ offset %ld; returning = %d\n", entry->offset, res);
-	return res;
+	desc->page_index = 0;
+	desc->page_offset = 0;
+	desc->page = page;
+	status = nfs_do_filldir(desc, dirent, filldir);
+
+	/* Reset read descriptor so it searches the page cache from
+	 * the start upon the next call to readdir_search_pagecache() */
+	desc->page_index = 0;
+	desc->page_offset = 0;
+	memset(desc->entry, 0, sizeof(*desc->entry));
+ out:
+	dfprintk(VFS, "NFS: uncached_readdir() returns %d\n", status);
+	return status;
+ out_release:
+	page_cache_release(page);
+	goto out;
 }
 
 /* The file offset position is now represented as a true offset into the
@@ -393,10 +363,9 @@
 {
 	struct dentry	*dentry = filp->f_dentry;
 	struct inode	*inode = dentry->d_inode;
-	struct page	*page;
-	struct nfs_entry my_entry,
-			*entry = &my_entry;
-	loff_t		offset;
+	nfs_readdir_descriptor_t my_desc,
+			*desc = &my_desc;
+	struct nfs_entry my_entry;
 	long		res;
 
 	res = nfs_revalidate(dentry);
@@ -409,36 +378,41 @@
 	 * read from the last dirent to revalidate f_pos
 	 * itself.
 	 */
-	memset(entry, 0, sizeof(*entry));
+	memset(desc, 0, sizeof(*desc));
+	memset(&my_entry, 0, sizeof(my_entry));
 
-	offset = filp->f_pos;
+	desc->file = filp;
+	desc->target = filp->f_pos;
+	desc->entry = &my_entry;
+	desc->decode = NFS_PROTO(inode)->decode_dirent;
 
-	while(!entry->eof) {
-		res = search_cached_dirent_pages(inode, offset, entry);
-
-		if (res < 0) {
-			if (entry->eof)
-				break;
-			res = refetch_to_readdir(filp, inode, offset, entry);
-			if (res < 0)
+	while(!desc->entry->eof) {
+		res = readdir_search_pagecache(desc);
+		if (res == -EBADCOOKIE) {
+			/* This means either end of directory */
+			if (desc->entry->cookie == desc->target) {
+				res = 0;
 				break;
+			}
+			/* Or that the server has 'lost' a cookie */
+			res = uncached_readdir(desc, dirent, filldir);
+			if (res >= 0)
+				continue;
 		}
+		if (res < 0)
+			break;
 
-		page = entry->page;
-		if (!page)
-			printk(KERN_ERR "NFS: Missing page...\n");
-		res = nfs_do_filldir(filp, inode, entry, dirent, filldir);
-		page_cache_release(page);
-		entry->page = NULL;
+		res = nfs_do_filldir(desc, dirent, filldir);
 		if (res < 0) {
 			res = 0;
 			break;
 		}
-		offset = filp->f_pos;
 	}
-	if (entry->page)
-		page_cache_release(entry->page);
-	if (res < 0 && res != -EBADCOOKIE)
+	if (desc->page)
+		page_cache_release(desc->page);
+	if (desc->error < 0)
+		return desc->error;
+	if (res < 0)
 		return res;
 	return 0;
 }
@@ -583,26 +557,18 @@
 
 /*
  * This is called from dput() when d_count is going to 0.
- * We use it to clean up silly-renamed files.
  */
-static void nfs_dentry_delete(struct dentry *dentry)
+static int nfs_dentry_delete(struct dentry *dentry)
 {
 	dfprintk(VFS, "NFS: dentry_delete(%s/%s, %x)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		dentry->d_flags);
 
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
-		int error;
-		
-		dentry->d_flags &= ~DCACHE_NFSFS_RENAMED;
-		/* Unhash it first */
-		d_drop(dentry);
-		error = nfs_safe_remove(dentry);
-		if (error)
-			printk("NFS: can't silly-delete %s/%s, error=%d\n",
-				dentry->d_parent->d_name.name,
-				dentry->d_name.name, error);
+		/* Unhash it, so that ->d_iput() would be called */
+		return 1;
 	}
+	return 0;
 
 }
 
@@ -627,36 +593,30 @@
 		nfs_fh_free(dentry->d_fsdata);
 }
 
-struct dentry_operations nfs_dentry_operations = {
-	d_revalidate:	nfs_lookup_revalidate,
-	d_delete:	nfs_dentry_delete,
-	d_release:	nfs_dentry_release,
-};
-
-#if 0 /* dead code */
-#ifdef NFS_PARANOIA
 /*
- * Display all dentries holding the specified inode.
+ * Called when the dentry loses inode.
+ * We use it to clean up silly-renamed files.
  */
-static void show_dentry(struct list_head * dlist)
+static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode)
 {
-	struct list_head *tmp = dlist;
-
-	while ((tmp = tmp->next) != dlist) {
-		struct dentry * dentry = list_entry(tmp, struct dentry, d_alias);
-		const char * unhashed = "";
-
-		if (d_unhashed(dentry))
-			unhashed = "(unhashed)";
-
-		printk("show_dentry: %s/%s, d_count=%d%s\n",
-			dentry->d_parent->d_name.name,
-			dentry->d_name.name, dentry->d_count,
-			unhashed);
+	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
+		struct dentry *dir = dentry->d_parent;
+		struct inode *dir_i = dir->d_inode;
+		int error;
+		
+		nfs_zap_caches(dir_i);
+		NFS_CACHEINV(inode);
+		error = NFS_PROTO(dir_i)->remove(dir, &dentry->d_name);
 	}
+	iput(inode);
 }
-#endif /* NFS_PARANOIA */
-#endif /* 0 */
+
+struct dentry_operations nfs_dentry_operations = {
+	d_revalidate:	nfs_lookup_revalidate,
+	d_delete:	nfs_dentry_delete,
+	d_release:	nfs_dentry_release,
+	d_iput:		nfs_dentry_iput,
+};
 
 static struct dentry *nfs_lookup(struct inode *dir_i, struct dentry * dentry)
 {
@@ -715,7 +675,6 @@
 		nfs_renew_times(dentry);
 		error = 0;
 	}
-	NFS_CACHEINV(dentry->d_parent->d_inode);
 	return error;
 }
 
@@ -809,7 +768,6 @@
 	d_drop(dentry);
 #endif
 	nfs_zap_caches(dir_i);
-	dir_i->i_nlink++;
 	error = NFS_PROTO(dir_i)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
 					&fattr);
 	if (!error && fhandle.size != 0)
@@ -830,13 +788,6 @@
 	nfs_zap_caches(dir_i);
 	error = NFS_PROTO(dir_i)->rmdir(dir, &dentry->d_name);
 
-	/* Update i_nlink and invalidate dentry. */
-	if (!error) {
-		d_drop(dentry);
-		if (dir_i->i_nlink)
-			dir_i->i_nlink--;
-	}
-
 	return error;
 }
 
@@ -919,7 +870,7 @@
  * Remove a file after making sure there are no pending writes,
  * and after checking that the file has only one user. 
  *
- * We update inode->i_nlink and free the inode prior to the operation
+ * We invalidate the attribute cache and free the inode prior to the operation
  * to avoid possible races if the server reuses the inode.
  */
 static int nfs_safe_remove(struct dentry *dentry)
@@ -927,28 +878,12 @@
 	struct dentry *dir = dentry->d_parent;
 	struct inode *dir_i = dir->d_inode;
 	struct inode *inode = dentry->d_inode;
-	int error, rehash = 0;
+	int error = -EBUSY, rehash = 0;
 		
 	dfprintk(VFS, "NFS: safe_remove(%s/%s, %ld)\n",
 		dentry->d_parent->d_name.name, dentry->d_name.name,
 		inode->i_ino);
 
-	/* N.B. not needed now that d_delete is done in advance? */
-	error = -EBUSY;
-	if (!inode) {
-#ifdef NFS_PARANOIA
-printk("nfs_safe_remove: %s/%s already negative??\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-#endif
-	}
-
-	if (dentry->d_count > 1) {
-#ifdef NFS_PARANOIA
-printk("nfs_safe_remove: %s/%s busy, d_count=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
-#endif
-		goto out;
-	}
 	/*
 	 * Unhash the dentry while we remove the file ...
 	 */
@@ -956,24 +891,26 @@
 		d_drop(dentry);
 		rehash = 1;
 	}
+	if (dentry->d_count > 1) {
+#ifdef NFS_PARANOIA
+		printk("nfs_safe_remove: %s/%s busy, d_count=%d\n",
+			dentry->d_parent->d_name.name, dentry->d_name.name,
+			dentry->d_count);
+#endif
+		goto out;
+	}
 	nfs_zap_caches(dir_i);
+	NFS_CACHEINV(inode);
 	error = NFS_PROTO(dir_i)->remove(dir, &dentry->d_name);
 	if (error < 0)
 		goto out;
 	/*
-	 * Update i_nlink and free the inode
-	 */
-	if (inode) {
-		if (inode->i_nlink)
-			inode->i_nlink --;
-		d_delete(dentry);
-	}
-	/*
-	 * Rehash the negative dentry if the operation succeeded.
+	 * Free the inode
 	 */
-	if (rehash)
-		d_add(dentry, NULL);
+	d_delete(dentry);
 out:
+	if (rehash)
+		d_rehash(dentry);
 	return error;
 }
 
@@ -1067,14 +1004,8 @@
 	 */
 	d_drop(dentry);
 	nfs_zap_caches(dir_i);
+	NFS_CACHEINV(inode);
 	error = NFS_PROTO(dir_i)->link(old_dentry, dir, &dentry->d_name);
-	if (!error) {
- 		/*
-		 * Update the link count immediately, as some apps
-		 * (e.g. pine) test this after making a link.
-		 */
-		inode->i_nlink++;
-	}
 	return error;
 }
 
@@ -1107,8 +1038,17 @@
 {
 	struct inode *old_inode = old_dentry->d_inode;
 	struct inode *new_inode = new_dentry->d_inode;
-	struct dentry *dentry = NULL;
-	int error, rehash = 0;
+	struct dentry *dentry = NULL, *rehash = NULL;
+	int error = -EBUSY;
+
+	/*
+	 * To prevent any new references to the target during the rename,
+	 * we unhash the dentry and free the inode in advance.
+	 */
+	if (!d_unhashed(new_dentry)) {
+		d_drop(new_dentry);
+		rehash = new_dentry;
+	}
 
 	dfprintk(VFS, "NFS: rename(%s/%s -> %s/%s, ct=%d)\n",
 		 old_dentry->d_parent->d_name.name, old_dentry->d_name.name,
@@ -1125,7 +1065,6 @@
 	 */
 	if (!new_inode)
 		goto go_ahead;
-	error = -EBUSY;
 	if (S_ISDIR(new_inode->i_mode))
 		goto out;
 	else if (new_dentry->d_count > 1) {
@@ -1139,10 +1078,10 @@
 		/* silly-rename the existing target ... */
 		err = nfs_sillyrename(new_dir, new_dentry);
 		if (!err) {
-			new_dentry = dentry;
+			new_dentry = rehash = dentry;
 			new_inode = NULL;
-			/* hash the replacement target */
-			d_add(new_dentry, NULL);
+			/* instantiate the replacement target */
+			d_instantiate(new_dentry, NULL);
 		}
 
 		/* dentry still busy? */
@@ -1166,14 +1105,6 @@
 		shrink_dcache_parent(old_dentry);
 	}
 
-	/*
-	 * To prevent any new references to the target during the rename,
-	 * we unhash the dentry and free the inode in advance.
-	 */
-	if (!d_unhashed(new_dentry)) {
-		d_drop(new_dentry);
-		rehash = 1;
-	}
 	if (new_inode)
 		d_delete(new_dentry);
 
@@ -1183,15 +1114,12 @@
 					   &old_dentry->d_name,
 					   new_dentry->d_parent,
 					   &new_dentry->d_name);
-	NFS_CACHEINV(old_dir);
-	NFS_CACHEINV(new_dir);
-	/* Update the dcache if needed */
+out:
 	if (rehash)
-		d_add(new_dentry, NULL);
+		d_rehash(rehash);
 	if (!error && !S_ISDIR(old_inode->i_mode))
 		d_move(old_dentry, new_dentry);
 
-out:
 	/* new dentry created? */
 	if (dentry)
 		dput(dentry);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.3.99-pre8/linux/fs/nfs/inode.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/nfs/inode.c	Sun May 21 20:53:32 2000
@@ -555,22 +555,18 @@
 	struct list_head *tmp, *head = &inode->i_dentry;
 	int unhashed;
 
-restart:
+	if (S_ISDIR(inode->i_mode)) {
+		struct dentry *dentry = d_find_alias(inode);
+		if (dentry) {
+			shrink_dcache_parent(dentry);
+			dput(dentry);
+		}
+	}
+	d_prune_aliases(inode);
 	tmp = head;
 	unhashed = 0;
 	while ((tmp = tmp->next) != head) {
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
-		dprintk("nfs_free_dentries: found %s/%s, d_count=%d, hashed=%d\n",
-			dentry->d_parent->d_name.name, dentry->d_name.name,
-			dentry->d_count, !d_unhashed(dentry));
-		if (!list_empty(&dentry->d_subdirs))
-			shrink_dcache_parent(dentry);
-		if (!dentry->d_count) {
-			dget(dentry);
-			d_drop(dentry);
-			dput(dentry);
-			goto restart;
-		}
 		if (d_unhashed(dentry))
 			unhashed++;
 	}
@@ -895,11 +891,20 @@
  */
 int nfs_open(struct inode *inode, struct file *filp)
 {
+	struct rpc_auth *auth = NFS_CLIENT(inode)->cl_auth;
+	struct rpc_cred *cred = rpcauth_lookupcred(auth, 0);
+
+	filp->private_data = cred;
 	return 0;
 }
 
 int nfs_release(struct inode *inode, struct file *filp)
 {
+	struct rpc_auth *auth = NFS_CLIENT(inode)->cl_auth;
+	struct rpc_cred *cred = nfs_file_cred(filp);
+
+	if (cred)
+		rpcauth_releasecred(auth, cred);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
--- v2.3.99-pre8/linux/fs/nfs/nfs2xdr.c	Tue Apr 11 15:09:22 2000
+++ linux/fs/nfs/nfs2xdr.c	Mon May 15 12:11:10 2000
@@ -485,13 +485,6 @@
 			break;
 		}
 	}
-	p++; /* EOF flag */
-
-	if (p > end) {
-		printk(KERN_NOTICE
-			"NFS: short packet in readdir reply!\n");
-		return -errno_NFSERR_IO;
-	}
 	return nr;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfs/nfs3proc.c linux/fs/nfs/nfs3proc.c
--- v2.3.99-pre8/linux/fs/nfs/nfs3proc.c	Tue Apr 11 15:09:22 2000
+++ linux/fs/nfs/nfs3proc.c	Sat May 20 10:27:56 2000
@@ -138,14 +138,16 @@
 }
 
 static int
-nfs3_proc_read(struct dentry *dentry, struct nfs_fattr *fattr, int flags,
+nfs3_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
 	       loff_t offset, unsigned int count, void *buffer, int *eofp)
 {
+	struct dentry		*dentry = file->f_dentry;
+	struct rpc_cred		*cred = nfs_file_cred(file);
 	struct nfs_readargs	arg = { NFS_FH(dentry), offset, count, 1,
 					{{buffer, count}, {0,0}, {0,0}, {0,0},
 					 {0,0}, {0,0}, {0,0}, {0,0}} };
 	struct nfs_readres	res = { fattr, count, 0 };
-	struct rpc_message	msg = { NFS3PROC_READ, &arg, &res, NULL };
+	struct rpc_message	msg = { NFS3PROC_READ, &arg, &res, cred };
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
@@ -157,16 +159,18 @@
 }
 
 static int
-nfs3_proc_write(struct dentry *dentry, struct nfs_fattr *fattr, int flags,
+nfs3_proc_write(struct file *file, struct nfs_fattr *fattr, int flags,
 		loff_t offset, unsigned int count,
 		void *buffer, struct nfs_writeverf *verf)
 {
+	struct dentry		*dentry = file->f_dentry;
+	struct rpc_cred		*cred = nfs_file_cred(file);
 	struct nfs_writeargs	arg = { NFS_FH(dentry), offset, count,
 					NFS_FILE_SYNC, 1,
 					{{buffer, count}, {0,0}, {0,0}, {0,0},
 					 {0,0}, {0,0}, {0,0}, {0,0}} };
 	struct nfs_writeres	res = { fattr, verf, 0 };
-	struct rpc_message	msg = { NFS3PROC_WRITE, &arg, &res, NULL };
+	struct rpc_message	msg = { NFS3PROC_WRITE, &arg, &res, cred };
 	int			status, rpcflags = 0;
 
 	dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
@@ -369,13 +373,15 @@
  * readdirplus.
  */
 static int
-nfs3_proc_readdir(struct dentry *dir, u64 cookie, void *entry,
+nfs3_proc_readdir(struct file *file, u64 cookie, void *entry,
 		  unsigned int size, int plus)
 {
+	struct dentry		*dir = file->f_dentry;
+	struct rpc_cred		*cred = nfs_file_cred(file);
 	struct nfs_fattr	dir_attr;
 	struct nfs3_readdirargs	arg = { NFS_FH(dir), cookie, {0, 0}, 0, 0, 0 };
 	struct nfs3_readdirres	res = { &dir_attr, 0, 0, 0, 0 };
-	struct rpc_message	msg = { NFS3PROC_READDIR, &arg, &res, NULL };
+	struct rpc_message	msg = { NFS3PROC_READDIR, &arg, &res, cred };
 	u32			*verf = NFS_COOKIEVERF(dir->d_inode);
 	int			status;
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfs/proc.c linux/fs/nfs/proc.c
--- v2.3.99-pre8/linux/fs/nfs/proc.c	Tue Apr 11 15:09:22 2000
+++ linux/fs/nfs/proc.c	Sat May 20 10:27:56 2000
@@ -122,14 +122,16 @@
 }
 
 static int
-nfs_proc_read(struct dentry *dentry, struct nfs_fattr *fattr, int flags,
+nfs_proc_read(struct file *file, struct nfs_fattr *fattr, int flags,
 	      loff_t offset, unsigned int count, void *buffer, int *eofp)
 {
+	struct dentry		*dentry = file->f_dentry;
+	struct rpc_cred		*cred = nfs_file_cred(file);
 	struct nfs_readargs	arg = { NFS_FH(dentry), offset, count, 1,
 				       {{ buffer, count }, {0,0}, {0,0}, {0,0},
 					{0,0}, {0,0}, {0,0}, {0,0}} };
 	struct nfs_readres	res = { fattr, count, 0};
-	struct rpc_message	msg = { NFSPROC_READ, &arg, &res, NULL };
+	struct rpc_message	msg = { NFSPROC_READ, &arg, &res, cred };
 	int			status;
 
 	dprintk("NFS call  read %d @ %Ld\n", count, (long long)offset);
@@ -142,16 +144,18 @@
 }
 
 static int
-nfs_proc_write(struct dentry *dentry, struct nfs_fattr *fattr, int how,
+nfs_proc_write(struct file *file, struct nfs_fattr *fattr, int how,
 	       loff_t offset, unsigned int count,
 	       void *buffer, struct nfs_writeverf *verf)
 {
+	struct dentry		*dentry = file->f_dentry;
+	struct rpc_cred		*cred = nfs_file_cred(file);
 	struct nfs_writeargs	arg = {NFS_FH(dentry), offset, count,
 					NFS_FILE_SYNC, 1,
 					{{buffer, count}, {0,0}, {0,0}, {0,0},
 					 {0,0}, {0,0}, {0,0}, {0,0}}};
 	struct nfs_writeres     res = {fattr, verf, count};
-	struct rpc_message	msg = { NFSPROC_WRITE, &arg, &res, NULL };
+	struct rpc_message	msg = { NFSPROC_WRITE, &arg, &res, cred };
 	int			status, flags = 0;
 
 	dprintk("NFS call  write %d @ %Ld\n", count, (long long)offset);
@@ -311,12 +315,14 @@
  * from nfs_readdir by calling the decode_entry function directly.
  */
 static int
-nfs_proc_readdir(struct dentry *dir, __u64 cookie, void *entry, 
+nfs_proc_readdir(struct file *file, __u64 cookie, void *entry, 
 		 unsigned int size, int plus)
 {
+	struct dentry		*dir = file->f_dentry;
+	struct rpc_cred		*cred = nfs_file_cred(file);
 	struct nfs_readdirargs	arg;
 	struct nfs_readdirres	res;
-	struct rpc_message	msg = { NFSPROC_READDIR, &arg, &res, NULL };
+	struct rpc_message	msg = { NFSPROC_READDIR, &arg, &res, cred };
 	struct nfs_server       *server = NFS_DSERVER(dir);
 	int			status;
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfs/read.c linux/fs/nfs/read.c
--- v2.3.99-pre8/linux/fs/nfs/read.c	Thu May 11 15:30:08 2000
+++ linux/fs/nfs/read.c	Sat May 13 09:43:55 2000
@@ -83,8 +83,9 @@
  * Read a page synchronously.
  */
 static int
-nfs_readpage_sync(struct dentry *dentry, struct page *page)
+nfs_readpage_sync(struct file *file, struct page *page)
 {
+	struct dentry	*dentry = file->f_dentry;
 	struct inode	*inode = dentry->d_inode;
 	struct nfs_fattr fattr;
 	loff_t		offset = page_offset(page);
@@ -112,7 +113,7 @@
 			(long long)offset, rsize, buffer);
 
 		lock_kernel();
-		result = NFS_PROTO(inode)->read(dentry, &fattr, flags, offset,
+		result = NFS_PROTO(inode)->read(file, &fattr, flags, offset,
 						rsize, buffer, &eof);
 		unlock_kernel();
 		nfs_refresh_inode(inode, &fattr);
@@ -195,9 +196,9 @@
 }
 
 static int
-nfs_readpage_async(struct dentry *dentry, struct page *page)
+nfs_readpage_async(struct file *file, struct page *page)
 {
-	struct inode	*inode = dentry->d_inode;
+	struct inode	*inode = file->f_dentry->d_inode;
 	struct nfs_page	*req, *new = NULL;
 	int		result;
 
@@ -227,7 +228,7 @@
 		}
 
 		result = -ENOMEM;
-		new = nfs_create_request(dentry, page, 0, PAGE_CACHE_SIZE);
+		new = nfs_create_request(file, page, 0, PAGE_CACHE_SIZE);
 		if (!new)
 			break;
 	}
@@ -462,20 +463,16 @@
 /*
  * Read a page over NFS.
  * We read the page synchronously in the following cases:
- *  -	The file is a swap file. Swap-ins are always sync operations,
- *	so there's no need bothering to make async reads 100% fail-safe.
  *  -	The NFS rsize is smaller than PAGE_CACHE_SIZE. We could kludge our way
  *	around this by creating several consecutive read requests, but
  *	that's hardly worth it.
  *  -	The error flag is set for this page. This happens only when a
  *	previous async read operation failed.
- *  -	The server is congested.
  */
 int
 nfs_readpage(struct file *file, struct page *page)
 {
-	struct dentry *dentry = file->f_dentry;
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	int		error;
 
 	dprintk("NFS: nfs_readpage (%p %ld@%lu)\n",
@@ -493,11 +490,11 @@
 
 	error = -1;
 	if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE)
-		error = nfs_readpage_async(dentry, page);
+		error = nfs_readpage_async(file, page);
 	if (error >= 0)
 		goto out;
 
-	error = nfs_readpage_sync(dentry, page);
+	error = nfs_readpage_sync(file, page);
 	if (error < 0 && IS_SWAPFILE(inode))
 		printk("Aiee.. nfs swap-in of page failed!\n");
 out:
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.3.99-pre8/linux/fs/nfs/write.c	Fri May 12 14:18:56 2000
+++ linux/fs/nfs/write.c	Sat May 13 09:43:55 2000
@@ -89,8 +89,7 @@
 /*
  * Local function declarations
  */
-static struct nfs_page * nfs_update_request(struct file*, struct dentry *,
-					    struct page *page,
+static struct nfs_page * nfs_update_request(struct file*, struct page *page,
 					    unsigned int, unsigned int);
 static void	nfs_strategy(struct inode *inode);
 static void	nfs_writeback_done(struct rpc_task *);
@@ -168,9 +167,10 @@
  * Offset is the data offset within the page.
  */
 static int
-nfs_writepage_sync(struct dentry *dentry, struct page *page,
+nfs_writepage_sync(struct file *file, struct page *page,
 		   unsigned int offset, unsigned int count)
 {
+	struct dentry	*dentry = file->f_dentry;
 	struct inode	*inode = dentry->d_inode;
 	loff_t		base;
 	unsigned int	wsize = NFS_SERVER(inode)->wsize;
@@ -193,7 +193,7 @@
 		if (count < wsize && !IS_SWAPFILE(inode))
 			wsize = count;
 
-		result = NFS_PROTO(inode)->write(dentry, &fattr, flags,
+		result = NFS_PROTO(inode)->write(file, &fattr, flags,
 						 base, wsize, buffer, &verf);
 		nfs_write_attributes(inode, &fattr);
 
@@ -229,18 +229,18 @@
 }
 
 static int
-nfs_writepage_async(struct file *file, struct dentry *dentry, struct page *page,
+nfs_writepage_async(struct file *file, struct page *page,
 		    unsigned int offset, unsigned int count)
 {
 	struct nfs_page	*req;
 	int		status;
 
-	req = nfs_update_request(file, dentry, page, offset, count);
+	req = nfs_update_request(file, page, offset, count);
 	status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
 	if (status < 0)
 		goto out;
 	nfs_release_request(req);
-	nfs_strategy(dentry->d_inode);
+	nfs_strategy(file->f_dentry->d_inode);
  out:
 	return status;
 }
@@ -251,8 +251,7 @@
 int
 nfs_writepage(struct file *file, struct page *page)
 {
-	struct dentry *dentry = file->f_dentry;
-	struct inode *inode = dentry->d_inode;
+	struct inode *inode = file->f_dentry->d_inode;
 	unsigned long end_index = inode->i_size >> PAGE_CACHE_SHIFT;
 	unsigned offset = PAGE_CACHE_SIZE;
 	int err;
@@ -267,11 +266,11 @@
 		return -EIO;
 do_it:
 	if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
-		err = nfs_writepage_async(file, dentry, page, 0, offset);
+		err = nfs_writepage_async(file, page, 0, offset);
 		if (err >= 0)
 			goto out_ok;
 	}
-	err = nfs_writepage_sync(dentry, page, 0, offset); 
+	err = nfs_writepage_sync(file, page, 0, offset); 
 	if ( err == offset)
 		goto out_ok;
 	return err; 
@@ -476,10 +475,12 @@
  * Page must be locked by the caller. This makes sure we never create
  * two different requests for the same page, and avoids possible deadlock
  * when we reach the hard limit on the number of dirty pages.
+ * It should be safe to sleep here.
  */
-struct nfs_page *nfs_create_request(struct dentry *dentry, struct page *page,
+struct nfs_page *nfs_create_request(struct file *file, struct page *page,
 				    unsigned int offset, unsigned int count)
 {
+	struct dentry		*dentry = file->f_dentry;
 	struct inode		*inode = dentry->d_inode;
 	struct nfs_reqlist	*cache = NFS_REQUESTLIST(inode);
 	struct nfs_page		*req = NULL;
@@ -531,8 +532,10 @@
 	page_cache_get(page);
 	req->wb_offset  = offset;
 	req->wb_bytes   = count;
-	req->wb_dentry  = dget(dentry);
-	req->wb_cred	= rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+	req->wb_file    = file;
+	get_file(file);
+	req->wb_dentry  = dentry;
+	req->wb_cred	= nfs_file_cred(file);
 	req->wb_count   = 1;
 
 	/* register request's existence */
@@ -573,12 +576,7 @@
 	if (NFS_WBACK_BUSY(req))
 		printk(KERN_ERR "NFS: Request released while still locked!\n");
 
-	rpcauth_releasecred(NFS_CLIENT(inode)->cl_auth, req->wb_cred);
-	lock_kernel();
-	if (req->wb_file)
-		fput(req->wb_file);
-	dput(req->wb_dentry);
-	unlock_kernel();
+	fput(req->wb_file);
 	page_cache_release(page);
 	nfs_page_free(req);
 	/* wake up anyone waiting to allocate a request */
@@ -789,10 +787,6 @@
 		if (prev) {
 			if (req->wb_file != prev->wb_file)
 				break;
-			if (req->wb_dentry != prev->wb_dentry)
-				break;
-			if (req->wb_cred != prev->wb_cred)
-				break;
 			if (page_index(req->wb_page) != page_index(prev->wb_page)+1)
 				break;
 
@@ -818,10 +812,10 @@
  * Note: Should always be called with the Page Lock held!
  */
 static struct nfs_page *
-nfs_update_request(struct file* file, struct dentry *dentry, struct page *page,
+nfs_update_request(struct file* file, struct page *page,
 		   unsigned int offset, unsigned int bytes)
 {
-	struct inode		*inode = dentry->d_inode;
+	struct inode		*inode = file->f_dentry->d_inode;
 	struct nfs_page		*req, *new = NULL;
 	unsigned long		rqend, end;
 
@@ -856,21 +850,14 @@
 		}
 		spin_unlock(&nfs_wreq_lock);
 
-
-		/* Create the request. It's safe to sleep in this call because
-		 * we only get here if the page is locked.
-		 *
+		/*
 		 * If we're over the soft limit, flush out old requests
 		 */
-		if (file && nfs_nr_requests >= MAX_REQUEST_SOFT)
+		if (inode->u.nfs_i.npages >= MAX_REQUEST_SOFT)
 			nfs_wb_file(inode, file);
-		new = nfs_create_request(dentry, page, offset, bytes);
+		new = nfs_create_request(file, page, offset, bytes);
 		if (!new)
 			return ERR_PTR(-ENOMEM);
-		if (file) {
-			new->wb_file = file;
-			get_file(file);
-		}
 		/* If the region is locked, adjust the timeout */
 		if (region_locked(inode, new))
 			new->wb_timeout = jiffies + NFS_WRITEBACK_LOCKDELAY;
@@ -1006,7 +993,7 @@
 	 * page synchronously.
 	 */
 	if (NFS_SERVER(inode)->wsize < PAGE_SIZE)
-		return nfs_writepage_sync(dentry, page, offset, count);
+		return nfs_writepage_sync(file, page, offset, count);
 
 	/*
 	 * Try to find an NFS request corresponding to this page
@@ -1015,7 +1002,7 @@
 	 * it out now.
 	 */
 	do {
-		req = nfs_update_request(file, dentry, page, offset, count);
+		req = nfs_update_request(file, page, offset, count);
 		status = (IS_ERR(req)) ? PTR_ERR(req) : 0;
 		if (status != -EBUSY)
 			break;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfsd/nfscache.c linux/fs/nfsd/nfscache.c
--- v2.3.99-pre8/linux/fs/nfsd/nfscache.c	Thu May 11 15:30:08 2000
+++ linux/fs/nfsd/nfscache.c	Mon May 22 09:50:55 2000
@@ -49,16 +49,21 @@
 	struct svc_cacherep	*rp;
 	struct nfscache_head	*rh;
 	size_t			i;
+	unsigned long		order;
 
 	if (cache_initialized)
 		return;
 
 	i = CACHESIZE * sizeof (struct svc_cacherep);
-	nfscache = kmalloc (i, GFP_KERNEL);
+	for (order = 0; (PAGE_SIZE << order) < i; order++)
+		;
+	nfscache = (struct svc_cacherep *)
+		__get_free_pages(GFP_KERNEL, order);
 	if (!nfscache) {
 		printk (KERN_ERR "nfsd: cannot allocate %d bytes for reply cache\n", i);
 		return;
 	}
+	memset(nfscache, 0, i);
 
 	i = HASHSIZE * sizeof (struct nfscache_head);
 	hash_list = kmalloc (i, GFP_KERNEL);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- v2.3.99-pre8/linux/fs/nfsd/nfsfh.c	Sun Mar 19 18:35:31 2000
+++ linux/fs/nfsd/nfsfh.c	Sat May 20 12:19:41 2000
@@ -812,17 +812,11 @@
 {
 	struct dentry * dentry = fhp->fh_dentry;
 	if (fhp->fh_dverified) {
+		fhp->fh_dentry = NULL;
 		fh_unlock(fhp);
 		fhp->fh_dverified = 0;
-		if (!dentry->d_count)
-			goto out_bad;
 		dput(dentry);
 		nfsd_nr_put++;
 	}
-	return;
-
-out_bad:
-	printk(KERN_ERR "fh_put: %s/%s has d_count 0!\n",
-		dentry->d_parent->d_name.name, dentry->d_name.name);
 	return;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/openpromfs/inode.c linux/fs/openpromfs/inode.c
--- v2.3.99-pre8/linux/fs/openpromfs/inode.c	Mon Mar 27 08:08:30 2000
+++ linux/fs/openpromfs/inode.c	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: inode.c,v 1.10 2000/03/24 01:32:51 davem Exp $
+/* $Id: inode.c,v 1.11 2000/05/22 07:29:42 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
@@ -870,7 +870,6 @@
 			buffer [10 + len] = 0;
 			prom_feval (buffer);
 		}
-	d_delete(dentry);
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.3.99-pre8/linux/fs/partitions/check.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/partitions/check.c	Mon May 15 12:08:51 2000
@@ -134,6 +134,9 @@
 		case IDE0_MAJOR:
 			maj = "hd";
 			break;
+		case MD_MAJOR:
+			unit -= 'a'-'0';
+			break;
 	}
 	if (hd->major >= SCSI_DISK1_MAJOR && hd->major <= SCSI_DISK7_MAJOR) {
 		unit = unit + (hd->major - SCSI_DISK1_MAJOR + 1) * 16;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/pipe.c linux/fs/pipe.c
--- v2.3.99-pre8/linux/fs/pipe.c	Thu May 11 15:30:08 2000
+++ linux/fs/pipe.c	Sun May 21 20:18:08 2000
@@ -465,7 +465,7 @@
 	return NULL;
 }
 
-static struct vfsmount *pipe_mnt = NULL;
+static struct vfsmount *pipe_mnt;
 
 static struct inode * get_pipe_inode(void)
 {
@@ -609,6 +609,7 @@
 	root->i_atime = root->i_mtime = root->i_ctime = CURRENT_TIME;
 	sb->s_blocksize = 1024;
 	sb->s_blocksize_bits = 10;
+	sb->s_magic = PIPEFS_MAGIC;
 	sb->s_op	= &pipefs_ops;
 	sb->s_root = d_alloc(NULL, &(const struct qstr) { "pipe:", 5, 0 });
 	if (!sb->s_root) {
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/proc/base.c linux/fs/proc/base.c
--- v2.3.99-pre8/linux/fs/proc/base.c	Thu May 11 15:30:08 2000
+++ linux/fs/proc/base.c	Sun May 21 20:34:37 2000
@@ -22,6 +22,7 @@
 #include <linux/stat.h>
 #include <linux/init.h>
 #include <linux/file.h>
+#include <linux/string.h>
 
 /*
  * For hysterical raisins we keep the same inumbers as in the old procfs.
@@ -651,6 +652,11 @@
 	return 0;
 }
 
+/*
+ *	Exceptional case: normally we are not allowed to unhash a busy
+ * directory. In this case, however, we can do it - no aliasing problems
+ * due to the way we treat inodes.
+ */
 static int pid_base_revalidate(struct dentry * dentry, int flags)
 {
 	if (dentry->d_inode->u.proc_i.task->p_pptr)
@@ -659,9 +665,9 @@
 	return 0;
 }
 
-static void pid_delete_dentry(struct dentry * dentry)
+static int pid_delete_dentry(struct dentry * dentry)
 {
-	d_drop(dentry);
+	return 1;
 }
 
 static struct dentry_operations pid_fd_dentry_operations =
@@ -861,6 +867,28 @@
 	lookup:		proc_base_lookup,
 };
 
+/*
+ * /proc/self:
+ */
+static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
+{
+	char tmp[30];
+	sprintf(tmp, "%d", current->pid);
+	return vfs_readlink(dentry,buffer,buflen,tmp);
+}
+
+static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+{
+	char tmp[30];
+	sprintf(tmp, "%d", current->pid);
+	return vfs_follow_link(nd,tmp);
+}	
+
+static struct inode_operations proc_self_inode_operations = {
+	readlink:	proc_self_readlink,
+	follow_link:	proc_self_follow_link,
+};
+
 struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
 {
 	unsigned int pid, c;
@@ -872,6 +900,23 @@
 	pid = 0;
 	name = dentry->d_name.name;
 	len = dentry->d_name.len;
+	if (len == 4 && !memcmp(name, "self", 4)) {
+		inode = get_empty_inode();
+		if (!inode)
+			return ERR_PTR(-ENOMEM);
+		inode->i_sb = dir->i_sb;
+		inode->i_dev = dir->i_sb->s_dev;
+		inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
+		inode->i_ino = fake_ino(0, PROC_PID_INO);
+		inode->u.proc_i.file = NULL;
+		inode->u.proc_i.task = NULL;
+		inode->i_mode = S_IFLNK|S_IRWXUGO;
+		inode->i_uid = inode->i_gid = 0;
+		inode->i_size = 64;
+		inode->i_op = &proc_self_inode_operations;
+		d_add(dentry, inode);
+		return NULL;
+	}
 	while (len-- > 0) {
 		c = *name - '0';
 		name++;
@@ -916,7 +961,8 @@
 {
 	if (inode->u.proc_i.file)
 		fput(inode->u.proc_i.file);
-	free_task_struct(inode->u.proc_i.task);
+	if (inode->u.proc_i.task)
+		free_task_struct(inode->u.proc_i.task);
 }
 
 #define PROC_NUMBUF 10
@@ -932,7 +978,7 @@
 	struct task_struct *p;
 	int nr_pids = 0;
 
-	index -= FIRST_PROCESS_ENTRY;
+	index--;
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		int pid = p->pid;
@@ -953,9 +999,17 @@
 {
 	unsigned int pid_array[PROC_MAXPIDS];
 	char buf[PROC_NUMBUF];
-	unsigned int nr = filp->f_pos;
+	unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
 	unsigned int nr_pids, i;
 
+	if (!nr) {
+		ino_t ino = fake_ino(0,PROC_PID_INO);
+		if (filldir(dirent, "self", 4, filp->f_pos, ino) < 0)
+			return 0;
+		filp->f_pos++;
+		nr++;
+	}
+
 	nr_pids = get_pid_list(nr, pid_array);
 
 	for (i = 0; i < nr_pids; i++) {
@@ -963,11 +1017,7 @@
 		ino_t ino = fake_ino(pid,PROC_PID_INO);
 		unsigned long j = PROC_NUMBUF;
 
-		do {
-			j--;
-			buf[j] = '0' + (pid % 10);
-			pid /= 10;
-		} while (pid);
+		do buf[--j] = '0' + (pid % 10); while (pid/=10);
 
 		if (filldir(dirent, buf+j, PROC_NUMBUF-j, filp->f_pos, ino) < 0)
 			break;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/proc/generic.c linux/fs/proc/generic.c
--- v2.3.99-pre8/linux/fs/proc/generic.c	Thu May 11 15:30:08 2000
+++ linux/fs/proc/generic.c	Sun May 21 20:34:37 2000
@@ -140,9 +140,13 @@
 {
     switch (orig) {
     case 0:
+	if (offset < 0)
+	    return -EINVAL;    
 	file->f_pos = offset;
 	return(file->f_pos);
     case 1:
+	if (offset + file->f_pos < 0)
+	    return -EINVAL;    
 	file->f_pos += offset;
 	return(file->f_pos);
     case 2:
@@ -218,10 +222,9 @@
  * smarter: we could keep a "volatile" flag in the 
  * inode to indicate which ones to keep.
  */
-static void
-proc_delete_dentry(struct dentry * dentry)
+static int proc_delete_dentry(struct dentry * dentry)
 {
-	d_drop(dentry);
+	return 1;
 }
 
 static struct dentry_operations proc_dentry_operations =
@@ -340,7 +343,7 @@
 	lookup:		proc_lookup,
 };
 
-int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
+static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp)
 {
 	int	i;
 	
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/proc/kcore.c linux/fs/proc/kcore.c
--- v2.3.99-pre8/linux/fs/proc/kcore.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/proc/kcore.c	Mon May 15 11:19:26 2000
@@ -315,13 +315,12 @@
 	size_t elf_buflen;
 	int num_vma;
 
-	/* XXX we need to somehow lock vmlist between here
-	 * and after elf_kcore_store_hdr() returns.
-	 * For now assume that num_vma does not change (TA)
-	 */
+	read_lock(&vmlist_lock);
 	proc_root_kcore->size = size = get_kcore_size(&num_vma, &elf_buflen);
-	if (buflen == 0 || *fpos >= size)
+	if (buflen == 0 || *fpos >= size) {
+		read_unlock(&vmlist_lock);
 		return 0;
+	}
 
 	/* trim buflen to not go beyond EOF */
 	if (buflen > size - *fpos)
@@ -335,10 +334,13 @@
 		if (buflen < tsz)
 			tsz = buflen;
 		elf_buf = kmalloc(elf_buflen, GFP_ATOMIC);
-		if (!elf_buf)
+		if (!elf_buf) {
+			read_unlock(&vmlist_lock);
 			return -ENOMEM;
+		}
 		memset(elf_buf, 0, elf_buflen);
 		elf_kcore_store_hdr(elf_buf, num_vma, elf_buflen);
+		read_unlock(&vmlist_lock);
 		if (copy_to_user(buffer, elf_buf + *fpos, tsz)) {
 			kfree(elf_buf);
 			return -EFAULT;
@@ -352,7 +354,8 @@
 		/* leave now if filled buffer already */
 		if (buflen == 0)
 			return acc;
-	}
+	} else
+		read_unlock(&vmlist_lock);
 
 	/* where page 0 not mapped, write zeros into buffer */
 #if defined (__i386__) || defined (__mc68000__)
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/proc/proc_devtree.c linux/fs/proc/proc_devtree.c
--- v2.3.99-pre8/linux/fs/proc/proc_devtree.c	Tue Jan 11 22:31:43 2000
+++ linux/fs/proc/proc_devtree.c	Sun May 21 20:34:37 2000
@@ -112,7 +112,6 @@
 		al = proc_symlink(at, de, ent->name);
 		if (al == 0)
 			break;
-		proc_register(de, al);
 		*lastp = al;
 		lastp = &al->next;
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.3.99-pre8/linux/fs/proc/root.c	Thu May 11 15:30:08 2000
+++ linux/fs/proc/root.c	Sun May 21 20:34:37 2000
@@ -22,38 +22,9 @@
 struct proc_dir_entry *proc_sys_root;
 #endif
 
-/*
- * /proc/self:
- */
-static int proc_self_readlink(struct dentry *dentry, char *buffer, int buflen)
-{
-	char tmp[30];
-	sprintf(tmp, "%d", current->pid);
-	return vfs_readlink(dentry,buffer,buflen,tmp);
-}
-
-static int proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	char tmp[30];
-	sprintf(tmp, "%d", current->pid);
-	return vfs_follow_link(nd,tmp);
-}	
-
-static struct inode_operations proc_self_inode_operations = {
-	readlink:	proc_self_readlink,
-	follow_link:	proc_self_follow_link
-};
-
-static struct proc_dir_entry proc_root_self = {
-	0, 4, "self",
-	S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, 1, 0, 0,
-	64, &proc_self_inode_operations,
-};
-
 void __init proc_root_init(void)
 {
 	proc_misc_init();
-	proc_register(&proc_root, &proc_root_self);
 	proc_net = proc_mkdir("net", 0);
 #ifdef CONFIG_SYSVIPC
 	proc_mkdir("sysvipc", 0);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c
--- v2.3.99-pre8/linux/fs/qnx4/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/qnx4/namei.c	Sat May 20 10:55:28 2000
@@ -184,7 +184,6 @@
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	dir->i_nlink--;
 	mark_inode_dirty(dir);
-	d_delete(dentry);
 	retval = 0;
 
       end_rmdir:
@@ -228,7 +227,6 @@
 	inode->i_nlink--;
 	inode->i_ctime = dir->i_ctime;
 	mark_inode_dirty(inode);
-	d_delete(dentry);
 	retval = 0;
 
       end_unlink:
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/ramfs/inode.c linux/fs/ramfs/inode.c
--- v2.3.99-pre8/linux/fs/ramfs/inode.c	Thu May 11 15:30:08 2000
+++ linux/fs/ramfs/inode.c	Sat May 20 10:55:28 2000
@@ -227,7 +227,6 @@
 
 		inode->i_nlink--;
 		dput(dentry);			/* Undo the count from "create" - this does all the work */
-		d_delete(dentry);
 		retval = 0;
 	}
 	return retval;
@@ -269,57 +268,6 @@
 	return error;
 }
 
-/*
- * This really should be the same as the proc filldir,
- * once proc does the "one dentry tree" thing..
- */
-static int ramfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
-{
-	int i;
-	struct dentry *dentry = filp->f_dentry;
-
-	i = filp->f_pos;
-	switch (i) {
-		case 0:
-			if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino) < 0)
-				break;
-			i++;
-			filp->f_pos++;
-			/* fallthrough */
-		case 1:
-			if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino) < 0)
-				break;
-			i++;
-			filp->f_pos++;
-			/* fallthrough */
-		default: {
-			struct list_head *list = dentry->d_subdirs.next;
-
-			int j = i-2;
-			for (;;) {
-				if (list == &dentry->d_subdirs)
-					return 0;
-				if (!j)
-					break;
-				j--;
-				list = list->next;
-			}
-
-			do {
-				struct dentry *de = list_entry(list, struct dentry, d_child);
-
-				if (ramfs_positive(de)) {
-					if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino) < 0)
-						break;
-				}
-				filp->f_pos++;
-				list = list->next;
-			} while (list != &dentry->d_subdirs);
-		}
-	}
-	return 0;
-}
-
 static struct address_space_operations ramfs_aops = {
 	readpage:	ramfs_readpage,
 	writepage:	ramfs_writepage,
@@ -335,7 +283,7 @@
 
 static struct file_operations ramfs_dir_operations = {
 	read:		generic_read_dir,
-	readdir:	ramfs_readdir,
+	readdir:	dcache_readdir,
 };
 
 static struct inode_operations ramfs_dir_inode_operations = {
@@ -350,9 +298,15 @@
 	rename:		ramfs_rename,
 };
 
+static void ramfs_put_super(struct super_block *sb)
+{
+	d_genocide(sb->s_root);
+	shrink_dcache_parent(sb->s_root);
+}
 
 static struct super_operations ramfs_ops = {
-	statfs:	 ramfs_statfs,
+	put_super:	ramfs_put_super,
+	statfs:		ramfs_statfs,
 };
 
 static struct super_block *ramfs_read_super(struct super_block * sb, void * data, int silent)
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/readdir.c linux/fs/readdir.c
--- v2.3.99-pre8/linux/fs/readdir.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/readdir.c	Sat May 20 10:55:28 2000
@@ -32,6 +32,53 @@
 	return res;
 }
 
+int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+	int i;
+	struct dentry *dentry = filp->f_dentry;
+
+	i = filp->f_pos;
+	switch (i) {
+		case 0:
+			if (filldir(dirent, ".", 1, i, dentry->d_inode->i_ino) < 0)
+				break;
+			i++;
+			filp->f_pos++;
+			/* fallthrough */
+		case 1:
+			if (filldir(dirent, "..", 2, i, dentry->d_parent->d_inode->i_ino) < 0)
+				break;
+			i++;
+			filp->f_pos++;
+			/* fallthrough */
+		default: {
+			struct list_head *list = dentry->d_subdirs.next;
+
+			int j = i-2;
+			for (;;) {
+				if (list == &dentry->d_subdirs)
+					return 0;
+				if (!j)
+					break;
+				j--;
+				list = list->next;
+			}
+
+			do {
+				struct dentry *de = list_entry(list, struct dentry, d_child);
+
+				if (!d_unhashed(de) && de->d_inode) {
+					if (filldir(dirent, de->d_name.name, de->d_name.len, filp->f_pos, de->d_inode->i_ino) < 0)
+						break;
+				}
+				filp->f_pos++;
+				list = list->next;
+			} while (list != &dentry->d_subdirs);
+		}
+	}
+	return 0;
+}
+
 /*
  * Traditional linux readdir() handling..
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.3.99-pre8/linux/fs/smbfs/dir.c	Fri Mar 10 16:40:48 2000
+++ linux/fs/smbfs/dir.c	Sat May 20 10:55:28 2000
@@ -168,7 +168,7 @@
 static int smb_lookup_validate(struct dentry *, int);
 static int smb_hash_dentry(struct dentry *, struct qstr *);
 static int smb_compare_dentry(struct dentry *, struct qstr *, struct qstr *);
-static void smb_delete_dentry(struct dentry *);
+static int smb_delete_dentry(struct dentry *);
 
 static struct dentry_operations smbfs_dentry_operations =
 {
@@ -259,9 +259,9 @@
 
 /*
  * This is the callback from dput() when d_count is going to 0.
- * We use this to unhash dentries with bad inodes and close files.
+ * We use this to unhash dentries with bad inodes.
  */
-static void
+static int
 smb_delete_dentry(struct dentry * dentry)
 {
 	if (dentry->d_inode)
@@ -272,13 +272,13 @@
 printk("smb_delete_dentry: bad inode, unhashing %s/%s\n", 
 dentry->d_parent->d_name.name, dentry->d_name.name);
 #endif
-			d_drop(dentry);
+			return 1;
 		}
-		smb_close_dentry(dentry);
 	} else
 	{
 	/* N.B. Unhash negative dentries? */
 	}
+	return 0;
 }
 
 /*
@@ -466,10 +466,7 @@
 	smb_invalid_dir_cache(dir);
 	error = smb_proc_unlink(dentry);
 	if (!error)
-	{
 		smb_renew_times(dentry);
-		d_delete(dentry);
-	}
 	return error;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.3.99-pre8/linux/fs/smbfs/file.c	Thu May 11 15:30:08 2000
+++ linux/fs/smbfs/file.c	Sat May 20 10:55:28 2000
@@ -26,12 +26,6 @@
 /* #define SMBFS_DEBUG_VERBOSE 1 */
 /* #define pr_debug printk */
 
-static inline int
-min(int a, int b)
-{
-	return a < b ? a : b;
-}
-
 static int
 smb_fsync(struct file *file, struct dentry * dentry)
 {
@@ -340,28 +334,15 @@
 static int
 smb_file_open(struct inode *inode, struct file * file)
 {
-#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_file_open: opening %s/%s, d_count=%d\n",
-file->f_dentry->d_parent->d_name.name, file->f_dentry->d_name.name,
-file->f_dentry->d_count);
-#endif
+	inode->u.smbfs_i.openers++;
 	return 0;
 }
 
 static int
 smb_file_release(struct inode *inode, struct file * file)
 {
-	struct dentry * dentry = file->f_dentry;
-
-#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_file_release: closing %s/%s, d_count=%d\n",
-dentry->d_parent->d_name.name, dentry->d_name.name, dentry->d_count);
-#endif
-	
-	if (dentry->d_count == 1)
-	{
+	if (!--inode->u.smbfs_i.openers)
 		smb_close(inode);
-	}
 	return 0;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- v2.3.99-pre8/linux/fs/smbfs/proc.c	Wed Jun 16 19:26:27 1999
+++ linux/fs/smbfs/proc.c	Sat May 20 10:55:29 2000
@@ -818,11 +818,6 @@
 		goto out;
 	}
 
-	/*
-	 * Note: If the caller holds an active dentry and the file is
-	 * currently open, we can be sure that the file isn't about
-	 * to be closed. (See smb_close_dentry() below.)
-	 */
 	if (!smb_is_open(inode))
 	{
 		struct smb_sb_info *server = SMB_SERVER(inode);
@@ -941,46 +936,6 @@
 		smb_unlock_server(server);
 	}
 	return result;
-}
-
-/*
- * This routine is called from dput() when d_count is going to 0.
- * We use this to close the file so that cached dentries don't
- * keep too many files open.
- *
- * There are some tricky race conditions here: the dentry may go
- * back into use while we're closing the file, and we don't want
- * the new user to be confused as to the open status.
- */
-void
-smb_close_dentry(struct dentry * dentry)
-{
-	struct inode *ino = dentry->d_inode;
-
-	if (ino)
-	{
-		if (smb_is_open(ino))
-		{
-			struct smb_sb_info *server = SMB_SERVER(ino);
-			smb_lock_server(server);
-			/*
-			 * Check whether the dentry is back in use.
-			 */
-			if (dentry->d_count <= 1)
-			{
-#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_close_dentry: closing %s/%s, count=%d\n",
-       DENTRY_PATH(dentry), dentry->d_count);
-#endif
-				smb_proc_close_inode(server, ino);
-			}
-			smb_unlock_server(server);
-		}
-#ifdef SMBFS_DEBUG_VERBOSE
-printk("smb_close_dentry: closed %s/%s, count=%d\n",
-       DENTRY_PATH(dentry), dentry->d_count);
-#endif
-	}
 }
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/super.c linux/fs/super.c
--- v2.3.99-pre8/linux/fs/super.c	Fri May 12 14:18:56 2000
+++ linux/fs/super.c	Sun May 21 20:34:37 2000
@@ -76,7 +76,7 @@
  *	Once the reference is obtained we can drop the spinlock.
  */
 
-static struct file_system_type *file_systems = NULL;
+static struct file_system_type *file_systems;
 static rwlock_t file_systems_lock = RW_LOCK_UNLOCKED;
 
 /* WARNING: This can be used only if we _already_ own a reference */
@@ -315,6 +315,7 @@
 		strcpy(name, dir_name);
 		mnt->mnt_dirname = name;
 	}
+	mnt->mnt_owner = current->uid;
 
 	if (parent)
 		list_add(&mnt->mnt_child, &parent->mnt_mounts);
@@ -1020,10 +1021,6 @@
 	struct nameidata nd;
 	char *kname;
 	int retval;
-	struct super_block *sb;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
 
 	lock_kernel();
 	kname = getname(name);
@@ -1036,10 +1033,14 @@
 	putname(kname);
 	if (retval)
 		goto out;
-	sb = nd.dentry->d_inode->i_sb;
 	retval = -EINVAL;
 	if (nd.dentry!=nd.mnt->mnt_root)
 		goto dput_and_out;
+
+	retval = -EPERM;
+	if (!capable(CAP_SYS_ADMIN) && current->uid!=nd.mnt->mnt_owner)
+		goto dput_and_out;
+
 	dput(nd.dentry);
 	/* puts nd.mnt */
 	down(&mount_sem);
@@ -1062,6 +1063,21 @@
 	return sys_umount(name,0);
 }
 
+static int mount_is_safe(struct nameidata *nd)
+{
+	if (capable(CAP_SYS_ADMIN))
+		return 0;
+	if (S_ISLNK(nd->dentry->d_inode->i_mode))
+		return -EPERM;
+	if (nd->dentry->d_inode->i_mode & S_ISVTX) {
+		if (current->uid != nd->dentry->d_inode->i_uid)
+			return -EPERM;
+	}
+	if (permission(nd->dentry->d_inode, MAY_WRITE))
+		return -EPERM;
+	return 0;
+}
+
 /*
  * do loopback mount.
  */
@@ -1071,18 +1087,22 @@
 	int err = 0;
 	if (!old_name || !*old_name)
 		return -EINVAL;
-	if (path_init(old_name, LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &old_nd))
+	if (path_init(old_name, LOOKUP_POSITIVE, &old_nd))
 		err = path_walk(old_name, &old_nd);
 	if (err)
 		goto out;
-	if (path_init(new_name, LOOKUP_POSITIVE|LOOKUP_DIRECTORY, &new_nd))
+	if (path_init(new_name, LOOKUP_POSITIVE, &new_nd))
 		err = path_walk(new_name, &new_nd);
 	if (err)
 		goto out1;
-	err = -EPERM;
-	if (!capable(CAP_SYS_ADMIN) &&
-	     current->uid != new_nd.dentry->d_inode->i_uid)
+	err = mount_is_safe(&new_nd);
+	if (err)
+		goto out2;
+	err = -EINVAL;
+	if (S_ISDIR(new_nd.dentry->d_inode->i_mode) !=
+	      S_ISDIR(old_nd.dentry->d_inode->i_mode))
 		goto out2;
+		
 	down(&mount_sem);
 	err = -ENOENT;
 	if (d_unhashed(old_nd.dentry) && !IS_ROOT(old_nd.dentry))
@@ -1143,31 +1163,29 @@
 	return retval;
 }
 
-static int copy_mount_options (const void * data, unsigned long *where)
+static int copy_mount_options (const void *data, unsigned long *where)
 {
 	int i;
 	unsigned long page;
-	struct vm_area_struct * vma;
 
 	*where = 0;
 	if (!data)
 		return 0;
 
-	vma = find_vma(current->mm, (unsigned long) data);
-	if (!vma || (unsigned long) data < vma->vm_start)
-		return -EFAULT;
-	if (!(vma->vm_flags & VM_READ))
-		return -EFAULT;
-	i = vma->vm_end - (unsigned long) data;
-	if (PAGE_SIZE <= (unsigned long) i)
-		i = PAGE_SIZE-1;
-	if (!(page = __get_free_page(GFP_KERNEL))) {
+	if (!(page = __get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
-	}
-	if (copy_from_user((void *) page,data,i)) {
+
+	/* We only care that *some* data at the address the user
+	 * gave us is valid.  Just in case, we'll zero
+	 * the remainder of the page.
+	 */
+	i = copy_from_user((void *)page, data, PAGE_SIZE);
+	if (i == PAGE_SIZE) {
 		free_page(page); 
 		return -EFAULT;
 	}
+	if (i)
+		memset((char *)page + PAGE_SIZE - i, 0, i);
 	*where = page;
 	return 0;
 }
@@ -1186,7 +1204,7 @@
  * aren't used, as the syscall assumes we are talking to an older
  * version that didn't understand them.
  */
-long do_sys_mount(char * dev_name, char * dir_name, char *type_page,
+long do_mount(char * dev_name, char * dir_name, char *type_page,
 		  unsigned long new_flags, void *data_page)
 {
 	struct file_system_type * fstype;
@@ -1279,26 +1297,24 @@
 			  unsigned long new_flags, void * data)
 {
 	int retval;
-	unsigned long data_page = 0;
-	unsigned long type_page = 0;
-	unsigned long dev_page = 0;
+	unsigned long data_page;
+	unsigned long type_page;
+	unsigned long dev_page;
 	char *dir_page;
 
-	lock_kernel();
 	retval = copy_mount_options (type, &type_page);
 	if (retval < 0)
-		goto out;
+		return retval;
 
 	/* copy_mount_options allows a NULL user pointer,
 	 * and just returns zero in that case.  But if we
 	 * allow the type to be NULL we will crash.
 	 * Previously we did not check this case.
 	 */
-	if (type_page == 0) {
-		retval = -EINVAL;
-		goto out;
-	}
+	if (type_page == 0)
+		return -EINVAL;
 
+	lock_kernel();
 	dir_page = getname(dir_name);
 	retval = PTR_ERR(dir_page);
 	if (IS_ERR(dir_page))
@@ -1309,7 +1325,7 @@
 		goto out2;
 	retval = copy_mount_options (data, &data_page);
 	if (retval >= 0) {
-		retval = do_sys_mount((char*)dev_page,dir_page,(char*)type_page,
+		retval = do_mount((char*)dev_page,dir_page,(char*)type_page,
 				      new_flags, (void*)data_page);
 		free_page(data_page);
 	}
@@ -1318,7 +1334,6 @@
 	putname(dir_page);
 out1:
 	free_page(type_page);
-out:
 	unlock_kernel();
 	return retval;
 }
@@ -1493,10 +1508,6 @@
 {
 	struct task_struct *p;
 
-	/* We can't afford dput() blocking under the tasklist_lock */
-	mntget(old_rootmnt);
-	dget(old_root);
-
 	read_lock(&tasklist_lock);
 	for_each_task(p) {
 		if (!p->fs) continue;
@@ -1506,9 +1517,6 @@
 			set_fs_pwd(p->fs, new_rootmnt, new_root);
 	}
 	read_unlock(&tasklist_lock);
-
-	dput(old_root);
-	mntput(old_rootmnt);
 }
 
 /*
@@ -1525,8 +1533,8 @@
 
 asmlinkage long sys_pivot_root(const char *new_root, const char *put_old)
 {
-	struct dentry *root = current->fs->root;
-	struct vfsmount *root_mnt = current->fs->rootmnt;
+	struct dentry *root;
+	struct vfsmount *root_mnt;
 	struct vfsmount *tmp;
 	struct nameidata new_nd, old_nd;
 	char *name;
@@ -1559,6 +1567,8 @@
 	if (error)
 		goto out1;
 
+	root_mnt = mntget(current->fs->rootmnt);
+	root = dget(current->fs->root);
 	down(&mount_sem);
 	error = -ENOENT;
 	if (d_unhashed(new_nd.dentry) && !IS_ROOT(new_nd.dentry))
@@ -1597,6 +1607,8 @@
 	error = 0;
 out2:
 	up(&mount_sem);
+	dput(root);
+	mntput(root_mnt);
 	path_release(&old_nd);
 out1:
 	path_release(&new_nd);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.3.99-pre8/linux/fs/sysv/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/sysv/namei.c	Sat May 20 10:55:29 2000
@@ -398,7 +398,6 @@
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(inode);
 	mark_inode_dirty(dir);
-	d_delete(dentry);
 	retval = 0;
 end_rmdir:
 	brelse(bh);
@@ -429,7 +428,6 @@
 	inode->i_nlink--;
 	inode->i_ctime = dir->i_ctime;
 	mark_inode_dirty(inode);
-	d_delete(dentry);
 	retval = 0;
 end_unlink:
 	brelse(bh);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/udf/namei.c linux/fs/udf/namei.c
--- v2.3.99-pre8/linux/fs/udf/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/udf/namei.c	Sun May 21 20:34:37 2000
@@ -346,7 +346,7 @@
 
 	sb = dir->i_sb;
 
-	if (dentry->d_name.len)
+	if (dentry)
 	{
 		if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
 		{
@@ -447,20 +447,17 @@
 				}
 			}
 	
-			if (!lfi)
+			if (!lfi || !dentry)
 				continue;
 	
-			if ((flen = udf_get_filename(nameptr, fname, lfi)))
-			{
-				if (udf_match(flen, fname, &(dentry->d_name)))
-				{
-					if (fibh->sbh != fibh->ebh)
-						udf_release_data(fibh->ebh);
-					udf_release_data(fibh->sbh);
-					udf_release_data(bh);
-					*err = -EEXIST;
-					return NULL;
-				}
+			if ((flen = udf_get_filename(nameptr, fname, lfi)) &&
+			    udf_match(flen, fname, &(dentry->d_name))) {
+				if (fibh->sbh != fibh->ebh)
+					udf_release_data(fibh->ebh);
+				udf_release_data(fibh->sbh);
+				udf_release_data(bh);
+				*err = -EEXIST;
+				return NULL;
 			}
 		}
 	}
@@ -691,7 +688,6 @@
 	struct udf_fileident_bh fibh;
 	int err;
 	struct FileIdentDesc cfi, *fi;
-	struct dentry parent;
 
 	err = -EMLINK;
 	if (dir->i_nlink >= (256<<sizeof(dir->i_nlink))-1)
@@ -704,10 +700,8 @@
 
 	inode->i_op = &udf_dir_inode_operations;
 	inode->i_fop = &udf_dir_operations;
-	parent.d_name.len = 0;
-	parent.d_name.name = NULL;
 	inode->i_size = 0;
-	if (!(fi = udf_add_entry(inode, &parent, &fibh, &cfi, &err)))
+	if (!(fi = udf_add_entry(inode, NULL, &fibh, &cfi, &err)))
 	{
 		inode->i_nlink--;
 		mark_inode_dirty(inode);
@@ -852,7 +846,6 @@
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	UDF_I_UCTIME(inode) = UDF_I_UCTIME(dir) = UDF_I_UMTIME(dir) = CURRENT_UTIME;
 	mark_inode_dirty(dir);
-	d_delete(dentry);
 
 end_rmdir:
 	if (fibh.sbh != fibh.ebh)
@@ -902,7 +895,6 @@
 	mark_inode_dirty(inode);
 	inode->i_ctime = dir->i_ctime;
 	retval = 0;
-	d_delete(dentry);	/* This also frees the inode */
 
 end_unlink:
 	if (fibh.sbh != fibh.ebh)
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.3.99-pre8/linux/fs/ufs/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/ufs/namei.c	Sat May 20 10:55:29 2000
@@ -673,7 +673,6 @@
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
 	mark_inode_dirty(dir);
-	d_delete(dentry);
 
 end_rmdir:
 	brelse (bh);
@@ -730,7 +729,6 @@
 	mark_inode_dirty(inode);
 	inode->i_ctime = dir->i_ctime;
 	retval = 0;
-	d_delete(dentry);	/* This also frees the inode */
 
 end_unlink:
 	brelse (bh);
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/umsdos/Makefile linux/fs/umsdos/Makefile
--- v2.3.99-pre8/linux/fs/umsdos/Makefile	Thu Feb 10 17:11:19 2000
+++ linux/fs/umsdos/Makefile	Sat May 20 10:55:29 2000
@@ -8,7 +8,7 @@
 # Note 2:  the CFLAGS definitions are now in the main makefile.
 O_TARGET := umsdos.o
 
-O_OBJS   := dir.o  inode.o ioctl.o mangle.o namei.o rdir.o emd.o check.o
+O_OBJS   := dir.o  inode.o ioctl.o mangle.o namei.o rdir.o emd.o
 
 M_OBJS   := $(O_TARGET)
 
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/umsdos/check.c linux/fs/umsdos/check.c
--- v2.3.99-pre8/linux/fs/umsdos/check.c	Sat Feb 26 22:31:54 2000
+++ linux/fs/umsdos/check.c	Wed Dec 31 16:00:00 1969
@@ -1,229 +0,0 @@
-/*
- * linux/fs/umsdos/check.c
- *
- * Sanity-checking code
- */
-
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/ptrace.h>
-#include <linux/mman.h>
-#include <linux/mm.h>
-#include <linux/umsdos_fs.h>
-
-#include <asm/system.h>
-
-#ifdef CHECK_PAGE_TABLES
-static int check_one_table (struct pde *page_dir)
-{
-	if (pgd_none (*page_dir))
-		return 0;
-	if (pgd_bad (*page_dir))
-		return 1;
-	return 0;
-}
-
-/*
- * This function checks all page tables of "current"
- */
-void check_page_tables (void)
-{
-	struct pgd *pg_dir;
-	static int err = 0;
-
-	int stack_level = (long) (&pg_dir) - current->kernel_stack_page;
-
-	if (stack_level < 1500)
-		printk ("** %d ** ", stack_level);
-	pg_dir = PAGE_DIR_OFFSET (current, 0);
-	if (err == 0) {
-		int i;
-
-		for (i = 0; i < PTRS_PER_PAGE; i++, page_dir++) {
-			int notok = check_one_table (page_dir);
-
-			if (notok) {
-				err++;
-				printk ("|%d:%08lx| ", i, page_dir->pgd);
-			}
-		}
-		if (err)
-			printk ("\nError MM %d\n", err);
-	}
-}
-#endif
-
-
-#if UMS_DEBUG
-/*
- * check for wait queue in 2.3.x
- */
-inline void uq_log (char *txt, struct inode *inode)
-{
-	printk (KERN_ERR "%s: (%lu) magic=%lu creator=%lu lock=%u\n", txt, inode->i_ino, inode->u.umsdos_i.dir_info.p.__magic, inode->u.umsdos_i.dir_info.p.__creator, inode->u.umsdos_i.dir_info.p.lock.lock);
-}
-
-/*
- * check a superblock
- */
-
-void check_sb (struct super_block *sb, const char c)
-{
-	if (sb) {
-		printk (" (has %c_sb=%d, %d)", 
-			c, MAJOR (sb->s_dev), MINOR (sb->s_dev));
-	} else {
-		printk (" (%c_sb is NULL)", c);
-	}
-} 
-
-/*
- * check an inode
- */
-
-void check_inode (struct inode *inode)
-{
-	if (inode) {
-		printk (KERN_DEBUG "*   inode is %lu (i_count=%d)",
-			 inode->i_ino, inode->i_count);
-		check_sb (inode->i_sb, 'i');
-		
-		if (inode->i_dentry.next) {	/* FIXME: does this work ? */
-			printk (" (has i_dentry)");
-		} else {
-			printk (" (NO i_dentry)");
-		}
-		
-		printk (" (i_patched=%d)", inode->u.umsdos_i.i_patched);
-
-	} else {
-		printk (KERN_DEBUG "*   inode is NULL\n");
-	}
-}
-
-/*
- * checks all inode->i_dentry
- *
- */
-void checkd_inode (struct inode *inode)
-{
-	struct dentry *ret;
-	struct list_head *cur;
-	int count = 0;
-	if (!inode) {
-		printk (KERN_ERR "checkd_inode: inode is NULL!\n");
-		return;
-	}
-
-	printk (KERN_DEBUG "checkd_inode:  inode %lu\n", inode->i_ino);
-	cur = inode->i_dentry.next;
-	while (count++ < 10) {
-		PRINTK (("1..."));
-		if (!cur) {
-			printk (KERN_ERR "checkd_inode: *** NULL reached. exit.\n");
-			return;
-		}
-		PRINTK (("2..."));
-		ret = list_entry (cur, struct dentry, d_alias);
-		PRINTK (("3..."));
-		if (cur == cur->next) {
-			printk (KERN_DEBUG "checkd_inode: *** cur=cur->next: normal exit.\n");
-			return;
-		}
-		PRINTK (("4..."));
-		if (!ret) {
-			printk (KERN_ERR "checkd_inode: *** ret dentry is NULL. exit.\n");
-			return;
-		}
-		PRINTK (("5... (ret=%p)...", ret));
-		PRINTK (("5.1.. (ret->d_dname=%p)...", &(ret->d_name)));
-		PRINTK (("5.1.1. (ret->d_dname.len=%d)...", (int) ret->d_name.len));
-		PRINTK (("5.1.2. (ret->d_dname.name=%c)...", ret->d_name.name));
-		printk (KERN_DEBUG "checkd_inode:   i_dentry is %.*s\n", (int) ret->d_name.len, ret->d_name.name);
-		PRINTK (("6..."));
-		cur = cur->next;
-		PRINTK (("7..."));
-#if 1
-		printk (KERN_DEBUG "checkd_inode: *** finished after count 1 (operator forced)\n");
-		return;
-#endif		
-	}
-	printk (KERN_ERR "checkd_inode: *** OVER LIMIT (loop?) !\n");
-	return;
-}
-
-/*
- * internal part of check_dentry. does the real job.
- *
- */
-
-void check_dent_int (struct dentry *dentry, int parent)
-{
-	if (parent) {
-		printk (KERN_DEBUG "*  parent(%d) dentry: %.*s\n", 
-			parent, (int) dentry->d_name.len, dentry->d_name.name);
-	} else {
-		printk (KERN_DEBUG "*  checking dentry: %.*s\n",
-			 (int) dentry->d_name.len, dentry->d_name.name);
-	}
-	check_inode (dentry->d_inode);
-	printk (KERN_DEBUG "*   d_count=%d", dentry->d_count);
-	check_sb (dentry->d_sb, 'd');
-	if (dentry->d_op == NULL) {
-		printk (" (d_op is NULL)\n");
-	} else {
-		printk (" (d_op is UNKNOWN: %p)\n", dentry->d_op);
-	}
-}
-
-/*
- * checks dentry with full traceback to root and prints info. Limited to 10 recursive depths to avoid infinite loops.
- *
- */
-
-void check_dentry_path (struct dentry *dentry, const char *desc)
-{
-	int count=0;
-	printk (KERN_DEBUG "*** check_dentry_path: %.60s\n", desc);
-
-	if (!dentry) {
-		printk (KERN_DEBUG "*** checking dentry... it is NULL !\n");
-		return;
-	}
-	if (IS_ERR(dentry)) {
-		printk (KERN_DEBUG "*** checking dentry... it is ERR(%ld) !\n",
-			 PTR_ERR(dentry));
-		return;
-	}
-	
-	while (dentry && count < 10) {
-		check_dent_int (dentry, count++);
-		if (IS_ROOT(dentry)) {
-			printk (KERN_DEBUG "*** end checking dentry (root reached ok)\n");
-			break;
-		}
-		dentry = dentry->d_parent;
-	}
-
-	if (count >= 10) {	/* if infinite loop detected */
-		printk (KERN_ERR 
-			"*** WARNING ! INFINITE LOOP ! check_dentry_path aborted !\n");
-	}
-	
-	if (!dentry) {
-		printk (KERN_ERR 
-			"*** WARNING ! NULL dentry ! check_dentry_path aborted !\n");
-	}
-}
-#else
-inline void uq_log (char *txt, struct inode *inode) {};
-void check_sb (struct super_block *sb, const char c) {};
-void check_inode (struct inode *inode) {};
-void checkd_inode (struct inode *inode) {};
-void check_dentry_path (struct dentry *dentry, const char *desc) {};
-#endif	/* UMS_DEBUG */
-
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v2.3.99-pre8/linux/fs/umsdos/dir.c	Tue Apr 11 15:09:23 2000
+++ linux/fs/umsdos/dir.c	Sat May 20 10:55:29 2000
@@ -36,12 +36,14 @@
 }
 
 /* for now, drop everything to force lookups ... */
-static void umsdos_dentry_dput(struct dentry *dentry)
+/* ITYM s/everything/& positive/... */
+static int umsdos_dentry_dput(struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
 	if (inode) {
-		d_drop(dentry);
+		return 1;
 	}
+	return 0;
 }
 
 struct dentry_operations umsdos_dentry_operations =
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/umsdos/inode.c linux/fs/umsdos/inode.c
--- v2.3.99-pre8/linux/fs/umsdos/inode.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/umsdos/inode.c	Sat May 20 10:55:29 2000
@@ -367,14 +367,6 @@
 		sb->s_root = new_root;
 		printk(KERN_INFO "UMSDOS: changed to alternate root\n");
 	}
-
-	/* if d_count is not 1, mount will fail with -EBUSY! */
-	if (sb->s_root->d_count > 1) {
-		shrink_dcache_sb(sb);
-		if (sb->s_root->d_count > 1) {
-			printk(KERN_ERR "UMSDOS: root count %d > 1 !", sb->s_root->d_count);
-		}
-	}
 	return sb;
 
 out_fail:
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/umsdos/ioctl.c linux/fs/umsdos/ioctl.c
--- v2.3.99-pre8/linux/fs/umsdos/ioctl.c	Tue Dec 14 01:27:24 1999
+++ linux/fs/umsdos/ioctl.c	Sat May 20 10:55:29 2000
@@ -331,6 +331,8 @@
 			ret = -EISDIR;
 			if (!S_ISDIR(temp->d_inode->i_mode))
 				ret = msdos_unlink (dir, temp);
+			if (!ret)
+				d_delete(temp);
 		}
 		dput (temp);
 		goto out;
@@ -355,6 +357,8 @@
 			ret = -ENOTDIR;
 			if (S_ISDIR(temp->d_inode->i_mode))
 				ret = msdos_rmdir (dir, temp);
+			if (!ret)
+				d_delete(temp);
 		}
 		dput (temp);
 		goto out;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c
--- v2.3.99-pre8/linux/fs/umsdos/namei.c	Fri Mar 10 16:40:49 2000
+++ linux/fs/umsdos/namei.c	Sat May 20 10:55:29 2000
@@ -524,6 +524,7 @@
 out_unlink:
 	printk(KERN_WARNING "umsdos_symlink: write failed, unlinking\n");
 	UMSDOS_unlink (dir, dentry);
+	d_drop(dentry);
 	goto out;
 }
 
@@ -898,9 +899,11 @@
 printk("umsdos_rmdir: EMD %s/%s unlink failed, err=%d\n",
 demd->d_parent->d_name.name, demd->d_name.name, err);
 #endif
-			dput(demd);
-			if (!err)
+			if (!err) {
+				d_delete(demd);
 				ret = 0;
+			}
+			dput(demd);
 		}
 	} else if (empty == 2)
 		ret = 0;
@@ -921,6 +924,7 @@
 	if (ret && ret != -ENOENT)
 		goto out_dput;
 
+	d_delete(temp);
 	/* OK so far ... remove the name from the EMD */
 	ret = umsdos_delentry (dentry->d_parent, &info, 1);
 #ifdef UMSDOS_PARANOIA
@@ -1009,6 +1013,8 @@
 	}
 
 	ret = msdos_unlink(dir, temp);
+	if (!ret)
+		d_delete(temp);
 #ifdef UMSDOS_PARANOIA
 if (ret)
 printk("umsdos_unlink: %s/%s unlink failed, ret=%d\n",
@@ -1018,8 +1024,6 @@
 	/* dput() temp if we didn't do it above */
 out_dput:
 	dput(temp);
-	if (!ret)
-		d_delete (dentry);
 
 out_unlock:
 	umsdos_unlockcreate (dir);
@@ -1065,7 +1069,8 @@
 			printk(KERN_WARNING
 				"umsdos_unlink: link removal failed, ret=%d\n",
 				 ret);
-		}
+		} else
+			d_delete(link);
 	} else {
 		struct iattr newattrs;
 		inode->i_nlink--;
@@ -1100,11 +1105,13 @@
 		 * If the target already exists, delete it first.
 		 */
 	if (new_dentry->d_inode) {
-		new_dentry->d_count++;
+		dget(new_dentry);
 		if (S_ISDIR(old_dentry->d_inode->i_mode))
 			ret = UMSDOS_rmdir (new_dir, new_dentry);
 		else
 			ret = UMSDOS_unlink (new_dir, new_dentry);
+		if (!ret)
+			d_drop(new_dentry);
 		dput(new_dentry);
 		if (ret)
 			return ret;
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v2.3.99-pre8/linux/fs/umsdos/rdir.c	Fri Mar 10 16:40:49 2000
+++ linux/fs/umsdos/rdir.c	Sat May 20 10:55:29 2000
@@ -174,6 +174,8 @@
 			ret = 0;
 			if (demd->d_inode)
 				ret = msdos_unlink (dentry->d_inode, demd);
+			if (!ret)
+				d_delete(demd);
 			dput(demd);
 		}
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.3.99-pre8/linux/fs/vfat/namei.c	Wed Apr 26 16:34:09 2000
+++ linux/fs/vfat/namei.c	Sat May 20 10:55:29 2000
@@ -961,24 +961,6 @@
 	return res ? res : -ENOENT;
 }
 
-/* Find a hashed dentry for inode; NULL if there are none */
-static struct dentry *find_alias(struct inode *inode)
-{
-	struct list_head *head, *next, *tmp;
-	struct dentry *alias;
-
-	head = &inode->i_dentry;
-	next = inode->i_dentry.next;
-	while (next != head) {
-		tmp = next;
-		next = tmp->next;
-		alias = list_entry(tmp, struct dentry, d_alias);
-		if (!d_unhashed(alias))
-			return dget(alias);
-	}
-	return NULL;
-}
-
 struct dentry *vfat_lookup(struct inode *dir,struct dentry *dentry)
 {
 	int res;
@@ -1005,7 +987,7 @@
 	fat_brelse(dir->i_sb, bh);
 	if (res)
 		return ERR_PTR(res);
-	alias = find_alias(inode);
+	alias = d_find_alias(inode);
 	if (alias) {
 		if (d_invalidate(alias)==0)
 			dput(alias);
@@ -1116,7 +1098,6 @@
 	mark_inode_dirty(dentry->d_inode);
 	/* releases bh */
 	vfat_remove_entry(dir,&sinfo,bh,de);
-	d_delete(dentry);
 
 	return res;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-alpha/ide.h linux/include/asm-alpha/ide.h
--- v2.3.99-pre8/linux/include/asm-alpha/ide.h	Fri Aug  6 11:16:54 1999
+++ linux/include/asm-alpha/ide.h	Sat May 20 09:40:21 2000
@@ -74,7 +74,8 @@
 	int index;
 
 	for (index = 0; index < MAX_HWIFS; index++) {
-		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		memset(&hw, 0, sizeof(hw_regs_t));
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-ebsa285/irq.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-arm/arch-ebsa285/irq.h	Mon May 15 12:00:33 2000
@@ -44,19 +44,8 @@
 static inline int fixup_irq(unsigned int irq)
 {
 #ifdef CONFIG_HOST_FOOTBRIDGE
-	if (irq == isa_irq) {
+	if (irq == isa_irq)
 		irq = *(unsigned char *)PCIIACK_BASE;
-
-		/*
-		 * The NetWinder appears to randomly give wrong interrupt
-		 * numbers from time to time.  When it does, map them to
-		 * the unused IRQ 13
-		 */
-		if (irq >= NR_IRQS) {
-			printk(KERN_ERR "Strange interrupt %d?\n", irq);
-			irq = _ISA_IRQ(13);
-		}
-	}
 #endif
 
 	return irq;
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/dma.h linux/include/asm-arm/arch-l7200/dma.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/dma.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,23 @@
+#ifndef __ASM_ARCH_DMA_H
+#define __ASM_ARCH_DMA_H
+
+/*
+ * This is the maximum DMA address that can be DMAd to.
+ * There should not be more than (0xd0000000 - 0xc0000000)
+ * bytes of RAM.
+ */
+#define MAX_DMA_ADDRESS		0xd0000000
+#define MAX_DMA_CHANNELS	8
+
+#define DMA_0			0
+#define DMA_1			1
+#define DMA_2			2
+#define DMA_3			3
+#define DMA_S0			4
+#define DMA_S1			5
+#define DMA_VIRTUAL_FLOPPY	6
+#define DMA_VIRTUAL_SOUND	7
+
+#define DMA_FLOPPY		DMA_VIRTUAL_FLOPPY
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/hardware.h linux/include/asm-arm/arch-l7200/hardware.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/hardware.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/hardware.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,49 @@
+/*
+ * linux/include/asm-arm/arch-l7200/hardware.h
+ *
+ * Copyright (C) 2000 Rob Scott (rscott@mtrob.fdns.net)
+ *                    Steve Hill (sjhill@cotw.com)
+ *
+ * This file contains the hardware definitions for the 
+ * LinkUp Systems L7200 SOC development board.
+ *
+ * Changelog:
+ *   02-01-2000	 RS	Created L7200 version, derived from rpc code
+ *   03-21-2000	SJH	Cleaned up file
+ *   04-21-2000	 RS 	Changed mapping of I/O in virtual space
+ *   04-25-2000	SJH	Removed unused symbols and such
+ *   05-05-2000	SJH	Complete rewrite
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+/* Hardware addresses of major areas.
+ *  *_START is the physical address
+ *  *_SIZE  is the size of the region
+ *  *_BASE  is the virtual address
+ */
+#define RAM_START		0xf0000000
+#define RAM_SIZE		0x02000000
+#define RAM_BASE		0xc0000000
+
+#define IO_START		0x80000000      /* I/O */
+#define IO_SIZE			0x01000000
+#define IO_BASE			0xd0000000
+
+#define IO_START_2		0x90000000      /* I/O */
+#define IO_SIZE_2		0x01000000
+#define IO_BASE_2		0xd1000000
+
+#define ISA_START		0x20000000	/* ISA */
+#define ISA_SIZE		0x20000000
+#define ISA_BASE		0xe0000000
+
+#define FLUSH_BASE_PHYS		0x40000000	/* ROM */
+#define FLUSH_BASE		0xdf000000
+
+#define PARAMS_BASE		(PAGE_OFFSET + 0x0100)
+#define Z_PARAMS_BASE		(RAM_START + PARAMS_OFFSET)
+
+#define PCIO_BASE		IO_BASE
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/ide.h linux/include/asm-arm/arch-l7200/ide.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/ide.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,27 @@
+/*
+ * linux/include/asm-arm/arch-l7200/ide.h
+ *
+ * Copyright (c) 2000 Steve Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *  29-03-2000	SJH	Created file placeholder
+ */
+#include <asm/irq.h>
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+{
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void
+ide_init_default_hwifs(void)
+{
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/io.h linux/include/asm-arm/arch-l7200/io.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/io.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,210 @@
+/*
+ * linux/include/asm-arm/arch-l7200/io.h
+ *
+ * Copyright (C) 2000 Steven Hill (sjhill@cotw.com)
+ *
+ * Modifications:
+ *  21-03-2000	SJH	Created from linux/include/asm-arm/arch-nexuspci/io.h
+ */
+#ifndef __ASM_ARM_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H
+
+#include <asm/arch/hardware.h>
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+/*
+ * We use two different types of addressing - PC style addresses, and ARM
+ * addresses.  PC style accesses the PC hardware with the normal PC IO
+ * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
+ * and are translated to the start of IO.  Note that all addresses are
+ * shifted left!
+ */
+#define __PORT_PCIO(x)	(!((x) & 0x80000000))
+
+/*
+ * Dynamic IO functions.
+ */
+
+extern __inline__ void __outb (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"strb	%1, [%0, %2, lsl #2]	@ outb"
+	: "=&r" (temp)
+	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+extern __inline__ void __outw (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"str	%1, [%0, %2, lsl #2]	@ outw"
+	: "=&r" (temp)
+	: "r" (value|value<<16), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+extern __inline__ void __outl (unsigned int value, unsigned int port)
+{
+	unsigned long temp;
+	__asm__ __volatile__(
+	"tst	%2, #0x80000000\n\t"
+	"mov	%0, %4\n\t"
+	"addeq	%0, %0, %3\n\t"
+	"str	%1, [%0, %2, lsl #2]	@ outl"
+	: "=&r" (temp)
+	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)
+	: "cc");
+}
+
+#define DECLARE_DYN_IN(sz,fnsuffix,instr)					\
+extern __inline__ unsigned sz __in##fnsuffix (unsigned int port)		\
+{										\
+	unsigned long temp, value;						\
+	__asm__ __volatile__(							\
+	"tst	%2, #0x80000000\n\t"						\
+	"mov	%0, %4\n\t"							\
+	"addeq	%0, %0, %3\n\t"							\
+	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
+	: "=&r" (temp), "=r" (value)						\
+	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
+	: "cc");								\
+	return (unsigned sz)value;						\
+}
+
+extern __inline__ unsigned int __ioaddr (unsigned int port)			\
+{										\
+	if (__PORT_PCIO(port))							\
+		return (unsigned int)(PCIO_BASE + (port << 2));			\
+	else									\
+		return (unsigned int)(IO_BASE + (port << 2));			\
+}
+
+#define DECLARE_IO(sz,fnsuffix,instr)	\
+	DECLARE_DYN_IN(sz,fnsuffix,instr)
+
+DECLARE_IO(char,b,"b")
+DECLARE_IO(short,w,"")
+DECLARE_IO(int,l,"")
+
+#undef DECLARE_IO
+#undef DECLARE_DYN_IN
+
+/*
+ * Constant address IO functions
+ *
+ * These have to be macros for the 'J' constraint to work -
+ * +/-4096 immediate operand.
+ */
+#define __outbc(value,port)							\
+({										\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"strb	%0, [%1, %2]	@ outbc"				\
+		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"strb	%0, [%1, %2]	@ outbc"				\
+		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
+})
+
+#define __inbc(port)								\
+({										\
+	unsigned char result;							\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"ldrb	%0, [%1, %2]	@ inbc"					\
+		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"ldrb	%0, [%1, %2]	@ inbc"					\
+		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
+	result;									\
+})
+
+#define __outwc(value,port)							\
+({										\
+	unsigned long v = value;						\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]	@ outwc"				\
+		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
+	else									\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]	@ outwc"				\
+		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
+})
+
+#define __inwc(port)								\
+({										\
+	unsigned short result;							\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]	@ inwc"					\
+		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]	@ inwc"					\
+		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
+	result & 0xffff;							\
+})
+
+#define __outlc(value,port)							\
+({										\
+	unsigned long v = value;						\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]	@ outlc"				\
+		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"str	%0, [%1, %2]	@ outlc"				\
+		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
+})
+
+#define __inlc(port)								\
+({										\
+	unsigned long result;							\
+	if (__PORT_PCIO((port)))						\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]	@ inlc"					\
+		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
+	else									\
+		__asm__ __volatile__(						\
+		"ldr	%0, [%1, %2]	@ inlc"					\
+		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
+	result;									\
+})
+
+#define __ioaddrc(port)								\
+	(__PORT_PCIO((port)) ? PCIO_BASE + ((port) << 2) : IO_BASE + ((port) << 2))
+
+#define inb(p)	 	(__builtin_constant_p((p)) ? __inbc(p)    : __inb(p))
+#define inw(p)	 	(__builtin_constant_p((p)) ? __inwc(p)    : __inw(p))
+#define inl(p)	 	(__builtin_constant_p((p)) ? __inlc(p)    : __inl(p))
+#define outb(v,p)	(__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
+#define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
+#define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
+#define __ioaddr(p)	(__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
+
+/*
+ * Translated address IO functions
+ *
+ * IO address has already been translated to a virtual address
+ */
+#define outb_t(v,p)	(*(volatile unsigned char *)(p) = (v))
+#define inb_t(p)	(*(volatile unsigned char *)(p))
+#define outw_t(v,p)	(*(volatile unsigned int *)(p) = (v))
+#define inw_t(p)	(*(volatile unsigned int *)(p))
+#define outl_t(v,p)	(*(volatile unsigned long *)(p) = (v))
+#define inl_t(p)	(*(volatile unsigned long *)(p))
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/irq.h linux/include/asm-arm/arch-l7200/irq.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/irq.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,66 @@
+/*
+ * include/asm-arm/arch-l7200/irq.h
+ *
+ * Copyright (C) 2000 Rob Scott (rscott@mtrob.fdns.ne
+ *                    Steve Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *   01-02-2000	RS	Created l7200 version, derived from ebsa110 code
+ *   04-15-2000 RS      Made dependent on hardware.h
+ *   05-05-2000 SJH     Complete rewrite
+ */
+
+/*
+ * IRQ base register
+ */
+#define	IRQ_BASE	(IO_BASE_2 + 0x1000)
+
+/* 
+ * Normal IRQ registers
+ */
+#define IRQ_STATUS	(*(volatile unsigned long *) (IRQ_BASE + 0x000))
+#define IRQ_RAWSTATUS	(*(volatile unsigned long *) (IRQ_BASE + 0x004))
+#define IRQ_ENABLE	(*(volatile unsigned long *) (IRQ_BASE + 0x008))
+#define IRQ_ENABLECLEAR	(*(volatile unsigned long *) (IRQ_BASE + 0x00c))
+#define IRQ_SOFT	(*(volatile unsigned long *) (IRQ_BASE + 0x010))
+#define IRQ_SOURCESEL	(*(volatile unsigned long *) (IRQ_BASE + 0x018))
+
+/* 
+ * Fast IRQ registers
+ */
+#define FIQ_STATUS	(*(volatile unsigned long *) (IRQ_BASE + 0x100))
+#define FIQ_RAWSTATUS	(*(volatile unsigned long *) (IRQ_BASE + 0x104))
+#define FIQ_ENABLE	(*(volatile unsigned long *) (IRQ_BASE + 0x108))
+#define FIQ_ENABLECLEAR	(*(volatile unsigned long *) (IRQ_BASE + 0x10c))
+#define FIQ_SOFT	(*(volatile unsigned long *) (IRQ_BASE + 0x110))
+#define FIQ_SOURCESEL	(*(volatile unsigned long *) (IRQ_BASE + 0x118))
+
+#define fixup_irq(x) (x)
+
+static void l7200_mask_irq(unsigned int irq)
+{
+	IRQ_ENABLECLEAR = 1 << irq;
+}
+
+static void l7200_unmask_irq(unsigned int irq)
+{
+	IRQ_ENABLE = 1 << irq;
+}
+ 
+static __inline__ void irq_init_irq(void)
+{
+	int irq;
+
+	IRQ_ENABLECLEAR = 0xffffffff;	/* clear all interrupt enables */
+	FIQ_ENABLECLEAR = 0xffffffff;	/* clear all fast interrupt enables */
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		irq_desc[irq].valid	= 1;
+		irq_desc[irq].probe_ok	= 1;
+		irq_desc[irq].mask_ack	= l7200_mask_irq;
+		irq_desc[irq].mask	= l7200_mask_irq;
+		irq_desc[irq].unmask	= l7200_unmask_irq;
+	}
+
+	init_FIQ();
+}
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/irqs.h linux/include/asm-arm/arch-l7200/irqs.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/irqs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/irqs.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,45 @@
+/*
+ * include/asm-arm/arch-l7200/irqs.h
+ *
+ * Copyright (C) 2000 Rob Scott (rscott@mtrob.fdns.net)
+ *                    Steve Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *   01-02-2000 RS	Create l7200 version
+ *   03-28-2000 SJH	Removed unused interrupt
+ */
+
+#define NR_IRQS          32
+
+#define IRQ_STWDOG        0   /* Watchdog timer */
+#define IRQ_PROG          1   /* Programmable interrupt */
+#define IRQ_DEBUG_RX      2   /* Comm Rx debug */
+#define IRQ_DEBUG_TX      3   /* Comm Tx debug */
+#define IRQ_GCTC1         4   /* Timer 1 */
+#define IRQ_GCTC2         5   /* Timer 2 */
+#define IRQ_DMA           6   /* DMA controller */
+#define IRQ_CLCD          7   /* Color LCD controller */
+#define IRQ_SM_RX         8   /* Smart card */
+#define IRQ_SM_TX         9   /* Smart cart */
+#define IRQ_SM_RST       10   /* Smart card */
+#define IRQ_SIB          11   /* Serial Interface Bus */
+#define IRQ_MMC          12   /* MultiMediaCard */
+#define IRQ_SSP1         13   /* Synchronous Serial Port 1 */
+#define IRQ_SSP2         14   /* Synchronous Serial Port 1 */
+#define IRQ_SPI          15   /* SPI slave */
+#define IRQ_UART_1       16   /* UART 1 */
+#define IRQ_UART_2       17   /* UART 2 */
+#define IRQ_IRDA         18   /* IRDA */
+#define IRQ_RTC_TICK     19   /* Real Time Clock tick */
+#define IRQ_RTC_ALARM    20   /* Real Time Clock alarm */
+#define IRQ_GPIO         21   /* General Purpose IO */
+#define IRQ_GPIO_DMA     22   /* General Purpose IO, DMA */
+#define IRQ_M2M          23   /* Memory to memory DMA  */
+#define IRQ_RESERVED     24   /* RESERVED, don't use */
+#define IRQ_INTF         25   /* External active low interrupt */
+#define IRQ_INT0         26   /* External active low interrupt */
+#define IRQ_INT1         27   /* External active low interrupt */
+#define IRQ_INT2         28   /* External active low interrupt */
+#define IRQ_INT3         29   /* External active low interrupt */
+#define IRQ_BAT_LO       30   /* Low batery or external power */
+#define IRQ_MEDIA_CHG    31   /* Media change interrupt */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/memory.h linux/include/asm-arm/arch-l7200/memory.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/memory.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/memory.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,44 @@
+/*
+ * linux/include/asm-arm/arch-l7200/memory.h
+ *
+ * Copyright (c) 2000 Steven Hill (sjhill@cotw.com)
+ * Copyright (c) 2000 Rob Scott (rscott@mtrob.fdns.net)
+ *
+ * Changelog:
+ *  03-13-2000	SJH	Created
+ *  04-13-2000  RS      Changed bus macros for new addr
+ *  05-03-2000  SJH     Removed bus macros and fixed virt_to_phys macro
+ */
+#ifndef __ASM_ARCH_MMU_H
+#define __ASM_ARCH_MMU_H
+
+/*
+ * Task size: 3GB
+ */
+#define TASK_SIZE       (0xc0000000UL)
+#define TASK_SIZE_26    (0x04000000UL)
+
+/*
+ * Page offset: 3GB
+ */
+#define PAGE_OFFSET     (0xc0000000UL)
+
+/*
+ * Physical DRAM offset on the L7200 SDB.
+ */
+#define PHYS_OFFSET     (0xf0000000UL)
+
+/*
+ * The DRAM is contiguous.
+ */
+#define __virt_to_phys__is_a_macro
+#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt__is_a_macro
+#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
+
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x) __virt_to_phys(x)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x) __phys_to_virt(x)
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/param.h linux/include/asm-arm/arch-l7200/param.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/param.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/param.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-arm/arch-l7200/param.h
+ *
+ * Copyright (C) 2000 Rob Scott (rscott@mtrob.fdns.net)
+ *                    Steve Hill (sjhill@cotw.com)
+ *
+ * This file contains the hardware definitions for the
+ * LinkUp Systems L7200 SOC development board.
+ *
+ * Changelog:
+ *   04-21-2000 RS      Created L7200 version
+ *   04-25-2000 SJH     Cleaned up file
+ *   05-03-2000 SJH     Change comments and rate
+ */
+#ifndef __ASM_ARCH_PARAM_H
+#define __ASM_ARCH_PARAM_H
+
+/*
+ * See 'time.h' for how the RTC HZ rate is set
+ */
+#define HZ 128
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/processor.h linux/include/asm-arm/arch-l7200/processor.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/processor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/processor.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,27 @@
+/*
+ * linux/include/asm-arm/arch-l7200/processor.h
+ *
+ * Copyright (c) 2000 Steven Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *  03-21-2000	SJH	Created
+ *  05-03-2000	SJH	Comment cleaning
+ */
+
+#ifndef __ASM_ARCH_PROCESSOR_H
+#define __ASM_ARCH_PROCESSOR_H
+
+/*
+ * Bus types
+ */
+#define EISA_bus 0
+#define EISA_bus__is_a_macro /* for versions in ksyms.c */
+#define MCA_bus 0
+#define MCA_bus__is_a_macro /* for versions in ksyms.c */
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/serial_l7200.h linux/include/asm-arm/arch-l7200/serial_l7200.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/serial_l7200.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/serial_l7200.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,101 @@
+/*
+ * linux/include/asm-arm/arch-l7200/serial_l7200.h
+ *
+ * Copyright (c) 2000 Steven Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *  05-09-2000	SJH	Created
+ */
+#ifndef __ASM_ARCH_SERIAL_L7200_H
+#define __ASM_ARCH_SERIAL_L7200_H
+
+#include <asm/arch/memory.h>
+
+/*
+ * This assumes you have a 3.6864 MHz clock for your UART.
+ */
+#define BASE_BAUD 3686400
+
+/*
+ * UART base register addresses
+ */
+#define UART1_BASE	(IO_BASE + 0x00044000)
+#define UART2_BASE	(IO_BASE + 0x00045000)
+
+/*
+ * UART register offsets
+ */
+#define UARTDR			0x00	/* Tx/Rx data */
+#define RXSTAT			0x04	/* Rx status */
+#define H_UBRLCR		0x08	/* mode register high */
+#define M_UBRLCR		0x0C	/* mode reg mid (MSB of buad)*/
+#define L_UBRLCR		0x10	/* mode reg low (LSB of baud)*/
+#define UARTCON			0x14	/* control register */
+#define UARTFLG			0x18	/* flag register */
+#define UARTINTSTAT		0x1C	/* FIFO IRQ status register */
+#define UARTINTMASK		0x20	/* FIFO IRQ mask register */
+
+/*
+ * UART baud rate register values
+ */
+#define BR_110			0x827
+#define BR_1200			0x06e
+#define BR_2400			0x05f
+#define BR_4800			0x02f
+#define BR_9600			0x017
+#define BR_14400		0x00f
+#define BR_19200		0x00b
+#define BR_38400		0x005
+#define BR_57600		0x003
+#define BR_76800 		0x002
+#define BR_115200		0x001
+
+/*
+ * Receiver status register (RXSTAT) mask values
+ */
+#define RXSTAT_NO_ERR		0x00	/* No error */
+#define RXSTAT_FRM_ERR		0x01	/* Framing error */
+#define RXSTAT_PAR_ERR		0x02	/* Parity error */
+#define RXSTAT_OVR_ERR		0x04	/* Overrun error */
+
+/*
+ * High byte of UART bit rate and line control register (H_UBRLCR) values
+ */
+#define UBRLCR_BRK		0x01	/* generate break on tx */
+#define UBRLCR_PEN		0x02	/* enable parity */
+#define UBRLCR_PDIS		0x00	/* disable parity */
+#define UBRLCR_EVEN		0x04	/* 1= even parity,0 = odd parity */
+#define UBRLCR_STP2		0x08	/* transmit 2 stop bits */
+#define UBRLCR_FIFO		0x10	/* enable FIFO */
+#define UBRLCR_LEN5		0x60	/* word length5 */
+#define UBRLCR_LEN6		0x40	/* word length6 */
+#define UBRLCR_LEN7		0x20	/* word length7 */
+#define UBRLCR_LEN8		0x00	/* word length8 */
+
+/*
+ * UART control register (UARTCON) values
+ */
+#define UARTCON_UARTEN		0x01	/* Enable UART */
+#define UARTCON_DMAONERR	0x08	/* Mask RxDmaRq when errors occur */
+
+/*
+ * UART flag register (UARTFLG) mask values
+ */
+#define UARTFLG_UTXFF		0x20	/* Transmit FIFO full */
+#define UARTFLG_URXFE		0x10	/* Receiver FIFO empty */
+#define UARTFLG_UBUSY		0x08	/* Transmitter busy */
+#define UARTFLG_DCD		0x04	/* Data carrier detect */
+#define UARTFLG_DSR		0x02	/* Data set ready */
+#define UARTFLG_CTS		0x01	/* Clear to send */
+
+/*
+ * UART interrupt status/clear registers (UARTINTSTAT/CLR) values
+ */
+#define UART_TXINT		0x01	/* TX interrupt */
+#define UART_RXINT		0x02	/* RX interrupt */
+#define UART_RXERRINT		0x04	/* RX error interrupt */
+#define UART_MSINT		0x08	/* Modem Status interrupt */
+#define UART_UDINT		0x10	/* UART Disabled interrupt */
+#define UART_ALLIRQS		0x1f	/* All interrupts */
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/system.h linux/include/asm-arm/arch-l7200/system.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/system.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/system.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,30 @@
+/*
+ * linux/include/asm-arm/arch-l7200/system.h
+ *
+ * Copyright (c) 2000 Steven Hill (sjhill@cotw.com)
+ *
+ * Changelog
+ *  03-21-2000  SJH	Created
+ *  04-26-2000  SJH	Fixed functions
+ *  05-03-2000  SJH	Removed usage of obsolete 'iomd.h'
+ */
+#ifndef __ASM_ARCH_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H
+
+extern __inline__ void arch_idle(void)
+{
+        while (!current->need_resched && !hlt_counter)
+		{ };
+/*                outb(0, IOMD_SUSMODE);*/
+}
+
+#define arch_power_off()	do { } while (0)
+
+extern inline void arch_reset(char mode)
+{
+	if (mode == 's') {
+		cpu_reset(0);
+	}
+}
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/time.h linux/include/asm-arm/arch-l7200/time.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/time.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/time.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,68 @@
+/*
+ * linux/include/asm-arm/arch-l7200/time.h
+ *
+ * Copyright (C) 2000 Rob Scott (rscott@mtrob.fdns.net)
+ *                    Steve Hill (sjhill@cotw.com)
+ *
+ * Changelog:
+ *   01-02-2000	RS	Created l7200 version, derived from rpc code
+ *   05-03-2000	SJH	Complete rewrite
+ */
+#ifndef _ASM_ARCH_TIME_H
+#define _ASM_ARCH_TIME_H
+
+#include <asm/arch/irqs.h>
+
+/*
+ * RTC base register address
+ */
+#define RTC_BASE	(IO_BASE_2 + 0x2000)
+
+/*
+ * RTC registers
+ */
+#define RTC_RTCDR	(*(volatile unsigned char *) (RTC_BASE + 0x000))
+#define RTC_RTCMR	(*(volatile unsigned char *) (RTC_BASE + 0x004))
+#define RTC_RTCS	(*(volatile unsigned char *) (RTC_BASE + 0x008))
+#define RTC_RTCC	(*(volatile unsigned char *) (RTC_BASE + 0x008))
+#define RTC_RTCDV	(*(volatile unsigned char *) (RTC_BASE + 0x00c))
+#define RTC_RTCCR	(*(volatile unsigned char *) (RTC_BASE + 0x010))
+
+/*
+ * RTCCR register values
+ */
+#define RTC_RATE_32	0x00      /* 32 Hz tick */
+#define RTC_RATE_64	0x10      /* 64 Hz tick */
+#define RTC_RATE_128	0x20      /* 128 Hz tick */
+#define RTC_RATE_256	0x30      /* 256 Hz tick */
+#define RTC_EN_ALARM	0x01      /* Enable alarm */
+#define RTC_EN_TIC	0x04      /* Enable counter */
+#define RTC_EN_STWDOG	0x08      /* Enable watchdog */
+
+/*
+ * Handler for timer interrupt
+ */
+static void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	do_timer(regs);
+	do_profile(regs);
+	RTC_RTCC = 0;				/* Clear interrupt */
+}
+
+/*
+ * Set up timer interrupt, and return the current time in seconds.
+ */
+extern __inline__ void setup_timer(void)
+{
+	xtime.tv_sec = RTC_RTCDR;
+
+	RTC_RTCC = 0;				/* Clear interrupt */
+
+	timer_irq.handler = timer_interrupt;
+
+	setup_arm_irq(IRQ_RTC_TICK, &timer_irq);
+
+	RTC_RTCCR = RTC_RATE_128 | RTC_EN_TIC;	/* Set rate and enable timer */
+}
+
+#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/timex.h linux/include/asm-arm/arch-l7200/timex.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/timex.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,20 @@
+/*
+ * linux/include/asm-arm/arch-l7200/timex.h
+ *
+ * Copyright (C) 2000 Rob Scott (rscott@mtrob.fdns.net)
+ *                    Steve Hill (sjhill@cotw.com)
+ *
+ * 04-21-2000  RS Created file
+ * 05-03-2000 SJH Tick rate was wrong
+ *
+ */
+
+/*
+ * On the ARM720T, clock ticks are set to 128 Hz.
+ *
+ * NOTE: The actual RTC value is set in 'time.h' which
+ *       must be changed when choosing a different tick
+ *       rate. The value of HZ in 'param.h' must also
+ *       be changed to match below.
+ */
+#define CLOCK_TICK_RATE		128
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/uncompress.h linux/include/asm-arm/arch-l7200/uncompress.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/uncompress.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/uncompress.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,19 @@
+/*
+ * linux/include/asm-arm/arch-l7200/uncompress.h
+ *
+ * Copyright (C) 2000 Steve Hill (sjhill@cotw.com)
+ */
+
+static __inline__ void putc(char c)
+{
+}
+
+static void puts(const char *s)
+{
+}
+
+static __inline__ void arch_decomp_setup(void)
+{
+}
+
+#define arch_decomp_wdog()
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/arch-l7200/vmalloc.h linux/include/asm-arm/arch-l7200/vmalloc.h
--- v2.3.99-pre8/linux/include/asm-arm/arch-l7200/vmalloc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-l7200/vmalloc.h	Mon May 15 12:00:33 2000
@@ -0,0 +1,16 @@
+/*
+ * linux/include/asm-arm/arch-l7200/vmalloc.h
+ */
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET	  (8*1024*1024)
+#define VMALLOC_START	  (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/hardirq.h linux/include/asm-arm/hardirq.h
--- v2.3.99-pre8/linux/include/asm-arm/hardirq.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-arm/hardirq.h	Mon May 15 12:00:33 2000
@@ -5,23 +5,27 @@
 #include <linux/threads.h>
 
 extern unsigned int local_irq_count[NR_CPUS];
+extern unsigned int local_bh_count[NR_CPUS];
+
+#define local_irq_count(cpu)	(local_irq_count[(cpu)])
+#define local_bh_count(cpu)	(local_bh_count[(cpu)])
 
 /*
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
  */
 #define in_interrupt() ({ const int __cpu = smp_processor_id(); \
-	(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
+	(local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
 
-#define in_irq() (local_irq_count[smp_processor_id()] != 0)
+#define in_irq() (local_irq_count(smp_processor_id()) != 0)
 
 #ifndef CONFIG_SMP
 
-#define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
+#define hardirq_trylock(cpu)	(local_irq_count(cpu) == 0)
 #define hardirq_endlock(cpu)	do { } while (0)
 
-#define hardirq_enter(cpu)	(local_irq_count[cpu]++)
-#define hardirq_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()	do { } while (0)
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/proc-armo/semaphore.h linux/include/asm-arm/proc-armo/semaphore.h
--- v2.3.99-pre8/linux/include/asm-arm/proc-armo/semaphore.h	Sun Feb 13 19:29:04 2000
+++ linux/include/asm-arm/proc-armo/semaphore.h	Wed Dec 31 16:00:00 1969
@@ -1,75 +0,0 @@
-/*
- * linux/include/asm-arm/proc-armo/locks.h
- *
- * Copyright (C) 2000 Russell King
- *
- * Interrupt safe locking assembler.
- */
-#ifndef __ASM_PROC_LOCKS_H
-#define __ASM_PROC_LOCKS_H
-
-#define __down_op(ptr,fail)			\
-	({					\
-	__asm__ __volatile__ (			\
-	"@ atomic down operation\n"		\
-"	mov	r0, pc\n"			\
-"	orr	lr, r0, #0x08000000\n"		\
-"	teqp	lr, #0\n"			\
-"	ldr	lr, [%0]\n"			\
-"	and	r0, r0, #0x0c000003\n"		\
-"	subs	lr, lr, #1\n"			\
-"	str	lr, [%0]\n"			\
-"	orrmi	r0, r0, #0x80000000	@ set N\n" \
-"	teqp	r0, #0\n"			\
-"	movmi	r0, %0\n"			\
-	blmi	" SYMBOL_NAME_STR(fail)		\
-	:					\
-	: "r" (ptr)				\
-	: "r0", "lr", "cc");			\
-	})
-
-#define __down_op_ret(ptr,fail)			\
-	({					\
-		unsigned int result;		\
-	__asm__ __volatile__ (			\
-"	@ down_op_ret\n"			\
-"	mov	r0, pc\n"			\
-"	orr	lr, r0, #0x08000000\n"		\
-"	teqp	lr, #0\n"			\
-"	ldr	lr, [%1]\m"			\
-"	and	r0, r0, #0x0c000003\n"		\
-"	subs	lr, lr, #1\n"			\
-"	str	lr, [%1]\n"			\
-"	orrmi	r0, r0, #0x80000000	@ set N\n" \
-"	teqp	r0, #0\n"			\
-"	movmi	r0, %1\n"			\
-"	movpl	r0, #0\n"			\
-"	blmi	" SYMBOL_NAME_STR(fail) "\n"	\
-"	mov	%0, r0"				\
-	: "=&r" (result)			\
-	: "r" (ptr)				\
-	: "r0", "lr", "cc");			\
-	result;					\
-	})
-
-#define __up_op(ptr,wake)			\
-	({					\
-	__asm__ __volatile__ (			\
-	"@ up_op\n"				\
-	mov	r0, pc\n"			\
-	orr	lr, r0, #0x08000000\n"		\
-	teqp	lr, #0\n"			\
-	ldr	lr, [%0]\n"			\
-	and	r0, r0, #0x0c000003\n"		\
-	adds	lr, lr, #1\n"			\
-	str	lr, [%0]\n"			\
-	orrle	r0, r0, #0x80000000	@ set N\n" \
-	teqp	r0, #0\n"			\
-	movmi	r0, %0\n"			\
-	blmi	" SYMBOL_NAME_STR(wake)		\
-	:					\
-	: "r" (ptr)				\
-	: "r0", "lr", "cc");			\
-	})
-
-#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/proc-armv/locks.h linux/include/asm-arm/proc-armv/locks.h
--- v2.3.99-pre8/linux/include/asm-arm/proc-armv/locks.h	Sun Feb 13 19:29:04 2000
+++ linux/include/asm-arm/proc-armv/locks.h	Mon May 15 12:00:34 2000
@@ -12,18 +12,18 @@
 	({					\
 	__asm__ __volatile__(			\
 	"@ down_op\n"				\
-"	mrs	r0, cpsr\n"			\
-"	orr	lr, r0, #128\n"			\
+"	mrs	ip, cpsr\n"			\
+"	orr	lr, ip, #128\n"			\
 "	msr	cpsr_c, lr\n"			\
 "	ldr	lr, [%0]\n"			\
 "	subs	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
-"	msr	cpsr_c, r0\n"			\
-"	movmi	r0, %0\n"			\
+"	msr	cpsr_c, ip\n"			\
+"	movmi	ip, %0\n"			\
 "	blmi	" SYMBOL_NAME_STR(fail)		\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "r0", "lr", "cc");			\
+	: "ip", "lr", "cc");			\
 	})
 
 #define __down_op_ret(ptr,fail)			\
@@ -31,20 +31,20 @@
 		unsigned int ret;		\
 	__asm__ __volatile__(			\
 	"@ down_op_ret\n"			\
-"	mrs	r0, cpsr\n"			\
-"	orr	lr, r0, #128\n"			\
+"	mrs	ip, cpsr\n"			\
+"	orr	lr, ip, #128\n"			\
 "	msr	cpsr_c, lr\n"			\
 "	ldr	lr, [%1]\n"			\
 "	subs	lr, lr, %2\n"			\
 "	str	lr, [%1]\n"			\
-"	msr	cpsr_c, r0\n"			\
-"	movmi	r0, %1\n"			\
-"	movpl	r0, #0\n"			\
+"	msr	cpsr_c, ip\n"			\
+"	movmi	ip, %1\n"			\
+"	movpl	ip, #0\n"			\
 "	blmi	" SYMBOL_NAME_STR(fail) "\n"	\
-"	mov	%0, r0"				\
+"	mov	%0, ip"				\
 	: "=&r" (ret)				\
 	: "r" (ptr), "I" (1)			\
-	: "r0", "lr", "cc");			\
+	: "ip", "lr", "cc");			\
 	ret;					\
 	})
 
@@ -52,18 +52,18 @@
 	({					\
 	__asm__ __volatile__(			\
 	"@ up_op\n"				\
-"	mrs	r0, cpsr\n"			\
-"	orr	lr, r0, #128\n"			\
+"	mrs	ip, cpsr\n"			\
+"	orr	lr, ip, #128\n"			\
 "	msr	cpsr_c, lr\n"			\
 "	ldr	lr, [%0]\n"			\
 "	adds	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
-"	msr	cpsr_c, r0\n"			\
-"	movle	r0, %0\n"			\
+"	msr	cpsr_c, ip\n"			\
+"	movle	ip, %0\n"			\
 "	blle	" SYMBOL_NAME_STR(wake)		\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "r0", "lr", "cc");			\
+	: "ip", "lr", "cc");			\
 	})
 
 /*
@@ -78,36 +78,36 @@
 	({					\
 	__asm__ __volatile__(			\
 	"@ down_op_write\n"			\
-"	mrs	r0, cpsr\n"			\
-"	orr	lr, r0, #128\n"			\
+"	mrs	ip, cpsr\n"			\
+"	orr	lr, ip, #128\n"			\
 "	msr	cpsr_c, lr\n"			\
 "	ldr	lr, [%0]\n"			\
 "	subs	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
-"	msr	cpsr_c, r0\n"			\
-"	movne	r0, %0\n"			\
+"	msr	cpsr_c, ip\n"			\
+"	movne	ip, %0\n"			\
 "	blne	" SYMBOL_NAME_STR(fail)		\
 	:					\
 	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
-	: "r0", "lr", "cc");			\
+	: "ip", "lr", "cc");			\
 	})
 
 #define __up_op_write(ptr,wake)			\
 	({					\
 	__asm__ __volatile__(			\
 	"@ up_op_read\n"			\
-"	mrs	r0, cpsr\n"			\
-"	orr	lr, r0, #128\n"			\
+"	mrs	ip, cpsr\n"			\
+"	orr	lr, ip, #128\n"			\
 "	msr	cpsr_c, lr\n"			\
 "	ldr	lr, [%0]\n"			\
 "	adds	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
-"	msr	cpsr_c, r0\n"			\
-"	movcs	r0, %0\n"			\
+"	msr	cpsr_c, ip\n"			\
+"	movcs	ip, %0\n"			\
 "	blcs	" SYMBOL_NAME_STR(wake)		\
 	:					\
 	: "r" (ptr), "I" (RW_LOCK_BIAS)		\
-	: "r0", "lr", "cc");			\
+	: "ip", "lr", "cc");			\
 	})
 
 #define __down_op_read(ptr,fail)		\
@@ -117,18 +117,18 @@
 	({					\
 	__asm__ __volatile__(			\
 	"@ up_op_read\n"			\
-"	mrs	r0, cpsr\n"			\
-"	orr	lr, r0, #128\n"			\
+"	mrs	ip, cpsr\n"			\
+"	orr	lr, ip, #128\n"			\
 "	msr	cpsr_c, lr\n"			\
 "	ldr	lr, [%0]\n"			\
 "	adds	lr, lr, %1\n"			\
 "	str	lr, [%0]\n"			\
-"	msr	cpsr_c, r0\n"			\
-"	moveq	r0, %0\n"			\
+"	msr	cpsr_c, ip\n"			\
+"	moveq	ip, %0\n"			\
 "	bleq	" SYMBOL_NAME_STR(wake)		\
 	:					\
 	: "r" (ptr), "I" (1)			\
-	: "r0", "lr", "cc");			\
+	: "ip", "lr", "cc");			\
 	})
 
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/softirq.h linux/include/asm-arm/softirq.h
--- v2.3.99-pre8/linux/include/asm-arm/softirq.h	Sun Feb 13 19:29:04 2000
+++ linux/include/asm-arm/softirq.h	Mon May 15 12:00:34 2000
@@ -4,14 +4,12 @@
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
 
-extern unsigned int local_bh_count[NR_CPUS];
-
-#define cpu_bh_disable(cpu)	do { local_bh_count[(cpu)]++; barrier(); } while (0)
-#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count[(cpu)]--; } while (0)
+#define cpu_bh_disable(cpu)	do { local_bh_count(cpu)++; barrier(); } while (0)
+#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count(cpu)--; } while (0)
 
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 #define local_bh_enable()	cpu_bh_enable(smp_processor_id())
 
-#define in_softirq()		(local_bh_count[smp_processor_id()] != 0)
+#define in_softirq()		(local_bh_count(smp_processor_id()) != 0)
 
 #endif	/* __ASM_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/string.h linux/include/asm-arm/string.h
--- v2.3.99-pre8/linux/include/asm-arm/string.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-arm/string.h	Mon May 15 12:00:34 2000
@@ -13,12 +13,17 @@
 extern char * strchr(const char * s, int c);
 
 #define __HAVE_ARCH_MEMCPY
+extern void * memcpy(void *, const void *, __kernel_size_t);
+
 #define __HAVE_ARCH_MEMMOVE
+extern void * memmove(void *, const void *, __kernel_size_t);
+
 #define __HAVE_ARCH_MEMCHR
-extern void * memchr(const void *cs, int c, size_t count);
+extern void * memchr(const void *, int, __kernel_size_t);
 
 #define __HAVE_ARCH_MEMZERO
 #define __HAVE_ARCH_MEMSET
+extern void * memset(void *, int, __kernel_size_t);
 
 extern void __memzero(void *ptr, __kernel_size_t n);
 
@@ -36,4 +41,3 @@
 #define memzero(p,n) ({ if ((n) != 0) __memzero((p),(n)); (p); })
 
 #endif
- 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-arm/unistd.h linux/include/asm-arm/unistd.h
--- v2.3.99-pre8/linux/include/asm-arm/unistd.h	Fri Jan 21 18:19:17 2000
+++ linux/include/asm-arm/unistd.h	Mon May 15 12:00:34 2000
@@ -65,7 +65,7 @@
 #define __NR_mpx			(__NR_SYSCALL_BASE+ 56)
 #define __NR_setpgid			(__NR_SYSCALL_BASE+ 57)
 #define __NR_ulimit			(__NR_SYSCALL_BASE+ 58)
-#define __NR_oldolduname		(__NR_SYSCALL_BASE+ 59)
+
 #define __NR_umask			(__NR_SYSCALL_BASE+ 60)
 #define __NR_chroot			(__NR_SYSCALL_BASE+ 61)
 #define __NR_ustat			(__NR_SYSCALL_BASE+ 62)
@@ -115,7 +115,7 @@
 #define __NR_stat			(__NR_SYSCALL_BASE+106)
 #define __NR_lstat			(__NR_SYSCALL_BASE+107)
 #define __NR_fstat			(__NR_SYSCALL_BASE+108)
-#define __NR_olduname			(__NR_SYSCALL_BASE+109)
+
 #define __NR_iopl			(__NR_SYSCALL_BASE+110)
 #define __NR_vhangup			(__NR_SYSCALL_BASE+111)
 #define __NR_idle			(__NR_SYSCALL_BASE+112)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-i386/apicdef.h linux/include/asm-i386/apicdef.h
--- v2.3.99-pre8/linux/include/asm-i386/apicdef.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-i386/apicdef.h	Sat May 13 07:37:34 2000
@@ -7,7 +7,8 @@
  * Alan Cox <Alan.Cox@linux.org>, 1995.
  * Ingo Molnar <mingo@redhat.com>, 1999, 2000
  */
-#define		APIC_PHYS_BASE	0xfee00000 /* IA s/w dev Vol 3, Section 7.4 */
+
+#define		APIC_DEFAULT_PHYS_BASE	0xfee00000
  
 #define		APIC_ID		0x20
 #define			GET_APIC_ID(x)		(((x)>>24)&0x0F)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-i386/hw_irq.h linux/include/asm-i386/hw_irq.h
--- v2.3.99-pre8/linux/include/asm-i386/hw_irq.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-i386/hw_irq.h	Tue May 23 14:18:47 2000
@@ -28,36 +28,34 @@
  */
 
 /*
- * Special IRQ vectors used by the SMP architecture, 0x30-0x4f
+ * Special IRQ vectors used by the SMP architecture, 0xf0-0xff
  *
  *  some of the following vectors are 'rare', they are merged
  *  into a single vector (CALL_FUNCTION_VECTOR) to save vector space.
  *  TLB, reschedule and local APIC vectors are performance-critical.
+ *
+ *  Vectors 0xf0-0xfa are free (reserved for future Linux use).
  */
-#define INVALIDATE_TLB_VECTOR	0x30
-#define LOCAL_TIMER_VECTOR	0x31
-#define RESCHEDULE_VECTOR	0x40
-
-/* 'rare' vectors: */
-#define CALL_FUNCTION_VECTOR	0x41
+#define SPURIOUS_APIC_VECTOR	0xff
+#define ERROR_APIC_VECTOR	0xfe
+#define INVALIDATE_TLB_VECTOR	0xfd
+#define RESCHEDULE_VECTOR	0xfc
+#define CALL_FUNCTION_VECTOR	0xfb
 
 /*
- * These IRQs should never really happen on perfect hardware running
- * a perfect kernel, but we nevertheless print a message to catch the
- * rest ;) Subtle, the APIC architecture mandates the spurious vector
- * to have bits 0-3 set to 1. Note that these vectors do not occur
- * normally, so we violate the 'only 2 vectors per priority level'
- * rule here.
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
  */
-#define SPURIOUS_APIC_VECTOR	0x3f
-#define ERROR_APIC_VECTOR	0x43
+#define LOCAL_TIMER_VECTOR	0xef
 
 /*
- * First APIC vector available to drivers: (vectors 0x51-0xfe)
- * we start at 0x51 to spread out vectors between priority levels
- * evenly. (note that 0x80 is the syscall vector)
+ * First APIC vector available to drivers: (vectors 0x30-0xee)
+ * we start at 0x31 to spread out vectors evenly between priority
+ * levels. (0x80 is the syscall vector)
  */
-#define IRQ0_TRAP_VECTOR	0x51
+#define FIRST_DEVICE_VECTOR	0x31
+#define FIRST_SYSTEM_VECTOR	0xef
 
 extern int irq_vector[NR_IRQS];
 #define IO_APIC_VECTOR(irq)	irq_vector[irq]
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-i386/ide.h linux/include/asm-i386/ide.h
--- v2.3.99-pre8/linux/include/asm-i386/ide.h	Fri Mar 10 16:40:49 2000
+++ linux/include/asm-i386/ide.h	Tue May 23 14:19:01 2000
@@ -78,6 +78,7 @@
 	int index;
 
 	for(index = 0; index < MAX_HWIFS; index++) {
+		memset(&hw, 0, sizeof(hw_regs_t));
 		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- v2.3.99-pre8/linux/include/asm-i386/uaccess.h	Mon Mar 27 08:08:31 2000
+++ linux/include/asm-i386/uaccess.h	Tue May 23 14:18:49 2000
@@ -135,16 +135,8 @@
 		:"0" (ptr),"d" (x)					\
 		:"cx")
 
-#define put_user(x,ptr)									\
-({	int __ret_pu;									\
-	switch(sizeof (*(ptr))) {							\
-	case 1:  __put_user_x(1,__ret_pu,(__typeof__(*(ptr)))(x),ptr); break;		\
-	case 2:  __put_user_x(2,__ret_pu,(__typeof__(*(ptr)))(x),ptr); break;		\
-	case 4:  __put_user_x(4,__ret_pu,(__typeof__(*(ptr)))(x),ptr); break;		\
-	default: __put_user_x(X,__ret_pu,x,ptr); break;					\
-	}										\
-	__ret_pu;									\
-})
+#define put_user(x,ptr)							\
+  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
 
 #define __get_user(x,ptr) \
   __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
@@ -157,6 +149,16 @@
 	__put_user_size((x),(ptr),(size),__pu_err);	\
 	__pu_err;					\
 })
+
+
+#define __put_user_check(x,ptr,size)			\
+({							\
+	long __pu_err = -EFAULT;					\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);		\
+	if (access_ok(VERIFY_WRITE,__pu_addr,size))	\
+		__put_user_size((x),__pu_addr,(size),__pu_err);	\
+	__pu_err;					\
+})							
 
 #define __put_user_size(x,ptr,size,retval)				\
 do {									\
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-ia64/ide.h linux/include/asm-ia64/ide.h
--- v2.3.99-pre8/linux/include/asm-ia64/ide.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-ia64/ide.h	Sat May 20 09:40:22 2000
@@ -84,6 +84,7 @@
 	int index;
 
 	for(index = 0; index < MAX_HWIFS; index++) {
+		memset(&hw, 0, sizeof(hw_regs_t));
 		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/arc/types.h linux/include/asm-mips/arc/types.h
--- v2.3.99-pre8/linux/include/asm-mips/arc/types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/arc/types.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,72 @@
+/*
+ * 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 1999 Ralf Baechle (ralf@gnu.org)
+ * Copyright 1999 Silicon Graphics, Inc.
+ */
+#ifndef _ASM_ARC_TYPES_H
+#define _ASM_ARC_TYPES_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_ARC32
+
+typedef char		CHAR;
+typedef short		SHORT;
+typedef long		LARGE_INTEGER __attribute__ ((__mode__ (__DI__)));
+typedef	long		LONG __attribute__ ((__mode__ (__SI__)));
+typedef unsigned char	UCHAR;
+typedef unsigned short	USHORT;
+typedef unsigned long	ULONG __attribute__ ((__mode__ (__SI__)));
+typedef void		VOID;
+
+/* The pointer types.  Note that we're using a 64-bit compiler but all
+   pointer in the ARC structures are only 32-bit, so we need some disgusting
+   workarounds.  Keep your vomit bag handy.  */
+typedef LONG		_PCHAR;
+typedef LONG		_PSHORT;
+typedef LONG		_PLARGE_INTEGER;
+typedef	LONG		_PLONG;
+typedef LONG		_PUCHAR;
+typedef LONG		_PUSHORT;
+typedef LONG		_PULONG;
+typedef LONG		_PVOID;
+
+#endif /* CONFIG_ARC32 */
+
+#ifdef CONFIG_ARC64
+
+typedef char		CHAR;
+typedef short		SHORT;
+typedef long		LARGE_INTEGER __attribute__ ((__mode__ (__DI__)));
+typedef	long		LONG __attribute__ ((__mode__ (__DI__)));
+typedef unsigned char	UCHAR;
+typedef unsigned short	USHORT;
+typedef unsigned long	ULONG __attribute__ ((__mode__ (__DI__)));
+typedef void		VOID;
+
+/* The pointer types.  We're 64-bit and the firmware is also 64-bit, so
+   live is sane ...  */
+typedef CHAR		*_PCHAR;
+typedef SHORT		*_PSHORT;
+typedef LARGE_INTEGER	*_PLARGE_INTEGER;
+typedef	LONG		*_PLONG;
+typedef UCHAR		*_PUCHAR;
+typedef USHORT		*_PUSHORT;
+typedef ULONG		*_PULONG;
+typedef VOID		*_PVOID;
+
+#endif /* CONFIG_ARC64  */
+
+typedef CHAR		*PCHAR;
+typedef SHORT		*PSHORT;
+typedef LARGE_INTEGER	*PLARGE_INTEGER;
+typedef	LONG		*PLONG;
+typedef UCHAR		*PUCHAR;
+typedef USHORT		*PUSHORT;
+typedef ULONG		*PULONG;
+typedef VOID		*PVOID;
+
+#endif /* _ASM_ARC_TYPES_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/asmmacro.h linux/include/asm-mips/asmmacro.h
--- v2.3.99-pre8/linux/include/asm-mips/asmmacro.h	Sat Feb 26 22:31:55 2000
+++ linux/include/asm-mips/asmmacro.h	Sat May 13 08:31:25 2000
@@ -4,7 +4,7 @@
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1998 Ralf Baechle
  *
- * $Id: asmmacro.h,v 1.4 1999/08/18 23:37:49 ralf Exp $
+ * $Id: asmmacro.h,v 1.3 1998/03/27 04:47:58 ralf Exp $
  */
 #ifndef __MIPS_ASMMACRO_H
 #define __MIPS_ASMMACRO_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/atomic.h linux/include/asm-mips/atomic.h
--- v2.3.99-pre8/linux/include/asm-mips/atomic.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips/atomic.h	Sat May 13 08:31:25 2000
@@ -11,10 +11,10 @@
  *
  * Copyright (C) 1996, 1997 by Ralf Baechle
  *
- * $Id: atomic.h,v 1.7 1999/08/13 17:07:27 harald Exp $
+ * $Id: atomic.h,v 1.6 1999/07/26 19:42:42 harald Exp $
  */
-#ifndef __ASM_MIPS_ATOMIC_H
-#define __ASM_MIPS_ATOMIC_H
+#ifndef __ASM_ATOMIC_H
+#define __ASM_ATOMIC_H
 
 #include <linux/config.h>
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/baget/baget.h linux/include/asm-mips/baget/baget.h
--- v2.3.99-pre8/linux/include/asm-mips/baget/baget.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/baget/baget.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: baget.h,v 1.2 1999/04/11 17:03:40 harald Exp $
+/* $Id$
  * baget.h: Definitions specific to Baget/MIPS machines.
  *
  * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/baget/vac.h linux/include/asm-mips/baget/vac.h
--- v2.3.99-pre8/linux/include/asm-mips/baget/vac.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/baget/vac.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: vac.h,v 1.2 1999/04/11 17:03:40 harald Exp $
+/* $Id$
  *
  * vac.h: Various VIC controller defines.  The VIC is a VME controller
  *        used in Baget/MIPS series.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/baget/vic.h linux/include/asm-mips/baget/vic.h
--- v2.3.99-pre8/linux/include/asm-mips/baget/vic.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/baget/vic.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: vic.h,v 1.1 1999/01/27 23:59:07 ralf Exp $
+/* $Id$
  *
  * vic.h: Various VIC controller defines.  The VIC is an interrupt controller
  *        used in Baget/MIPS series.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/bcache.h linux/include/asm-mips/bcache.h
--- v2.3.99-pre8/linux/include/asm-mips/bcache.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/bcache.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: bcache.h,v 1.2 1999/08/20 21:59:07 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/bitops.h linux/include/asm-mips/bitops.h
--- v2.3.99-pre8/linux/include/asm-mips/bitops.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips/bitops.h	Sat May 13 08:31:25 2000
@@ -54,9 +54,9 @@
 extern __inline__ int find_next_zero_bit (void * addr, int size, int offset);
 extern __inline__ unsigned long ffz(unsigned long word);
 
-#include <asm/mipsregs.h>
-
 #if defined(CONFIG_CPU_HAS_LLSC)
+
+#include <asm/mipsregs.h>
 
 /*
  * These functions for MIPS ISA > 1 are interrupt and SMP proof and
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/bootinfo.h linux/include/asm-mips/bootinfo.h
--- v2.3.99-pre8/linux/include/asm-mips/bootinfo.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips/bootinfo.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: bootinfo.h,v 1.10 2000/01/26 00:07:45 ralf Exp $
+/* $Id: bootinfo.h,v 1.11 2000/03/06 11:14:32 raiko Exp $
  *
  * bootinfo.h -- Definition of the Linux/MIPS boot information structure
  *
@@ -24,9 +24,10 @@
 #define MACH_GROUP_SGI          6 /* Silicon Graphics workstations and servers */
 #define MACH_GROUP_COBALT       7 /* Cobalt servers		 	      */
 #define MACH_GROUP_NEC_DDB	8 /* NEC DDB */
+#define MACH_GROUP_BAGET	9 /* Baget */
 
 #define GROUP_NAMES { "unknown", "Jazz", "Digital", "ARC", \
-                      "SNI", "ACN", "SGI", "Cobalt", "NEC DDB" }
+                      "SNI", "ACN", "SGI", "Cobalt", "NEC DDB", "Baget" }
 
 /*
  * Valid machtype values for group unknown (low order halfword of mips_machtype)
@@ -105,6 +106,14 @@
 #define MACH_NEC_DDB5074	 0	/* NEC DDB Vrc-5074 */
 
 #define GROUP_NEC_DDB_NAMES { "Vrc-5074" }
+
+/*
+ * Valid machtype for group BAGET
+ */
+#define MACH_BAGET201		0	/* BT23-201 */
+#define MACH_BAGET202		1	/* BT23-202 */
+
+#define GROUP_BAGET_NAMES { "BT23-201", "BT23-202" }
 
 /*
  * Valid cputype values
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/branch.h linux/include/asm-mips/branch.h
--- v2.3.99-pre8/linux/include/asm-mips/branch.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/branch.h	Sat May 13 08:31:25 2000
@@ -7,7 +7,7 @@
  *
  * Copyright (C) 1996, 1997, 1998 by Ralf Baechle
  *
- * $Id: branch.h,v 1.2 1998/05/04 09:13:00 ralf Exp $
+ * $Id: branch.h,v 1.2 1998/04/28 19:37:46 ralf Exp $
  */
 #include <asm/ptrace.h>
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/bugs.h linux/include/asm-mips/bugs.h
--- v2.3.99-pre8/linux/include/asm-mips/bugs.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/bugs.h	Sat May 13 08:31:25 2000
@@ -17,6 +17,11 @@
 {
 	printk("Checking for 'wait' instruction... ");
 	switch(mips_cputype) {
+	case CPU_R3081:
+	case CPU_R3081E:
+		cpu_wait = r3081_wait;
+		printk(" available.\n");
+		break;
 	case CPU_R4200: 
 	case CPU_R4300: 
 	case CPU_R4600: 
@@ -25,7 +30,7 @@
 	case CPU_R4700: 
 	case CPU_R5000: 
 	case CPU_NEVADA:
-		wait_available = 1;
+		cpu_wait = r4k_wait;
 		printk(" available.\n");
 		break;
 	default:
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/byteorder.h linux/include/asm-mips/byteorder.h
--- v2.3.99-pre8/linux/include/asm-mips/byteorder.h	Fri Jun 25 17:37:52 1999
+++ linux/include/asm-mips/byteorder.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: byteorder.h,v 1.7 1999/01/04 16:09:20 ralf Exp $
+/* $Id: byteorder.h,v 1.8 1998/11/02 09:29:32 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/cache.h linux/include/asm-mips/cache.h
--- v2.3.99-pre8/linux/include/asm-mips/cache.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/cache.h	Sat May 13 08:31:25 2000
@@ -13,9 +13,11 @@
 #include <linux/config.h>
 
 #if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_R6000)
-#define L1_CACHE_BYTES	16
+#define L1_CACHE_BYTES		16
 #else
-#define L1_CACHE_BYTES  32	/* A guess */
+#define L1_CACHE_BYTES 		32	/* A guess */
 #endif
+
+#define SMP_CACHE_BYTES		L1_CACHE_BYTES
 
 #endif /* _ASM_CACHE_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/checksum.h linux/include/asm-mips/checksum.h
--- v2.3.99-pre8/linux/include/asm-mips/checksum.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/checksum.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.9 2000/02/18 22:06:19 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/cpu.h linux/include/asm-mips/cpu.h
--- v2.3.99-pre8/linux/include/asm-mips/cpu.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/cpu.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: cpu.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
+/* $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.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/current.h linux/include/asm-mips/current.h
--- v2.3.99-pre8/linux/include/asm-mips/current.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/current.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: current.h,v 1.6 1999/09/28 22:27:17 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ddb5074.h linux/include/asm-mips/ddb5074.h
--- v2.3.99-pre8/linux/include/asm-mips/ddb5074.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/ddb5074.h	Sat May 13 08:31:25 2000
@@ -2,7 +2,7 @@
  *  include/asm-mips/ddb5074.h -- NEC DDB Vrc-5074 definitions
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  */
 
 extern void ddb5074_led_hex(int hex);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/delay.h linux/include/asm-mips/delay.h
--- v2.3.99-pre8/linux/include/asm-mips/delay.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips/delay.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: delay.h,v 1.3 1999/08/18 23:37:49 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/div64.h linux/include/asm-mips/div64.h
--- v2.3.99-pre8/linux/include/asm-mips/div64.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/div64.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: div64.h,v 1.1 2000/01/29 01:42:28 ralf Exp $
+/* $Id: div64.h,v 1.1 2000/01/28 23:18:43 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/dma.h linux/include/asm-mips/dma.h
--- v2.3.99-pre8/linux/include/asm-mips/dma.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/dma.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.7 2000/01/29 01:42:28 ralf Exp $
+/* $Id: dma.h,v 1.6 1999/12/30 14:22:47 raiko Exp $
  * linux/include/asm/dma.h: Defines for using and allocating dma channels.
  * Written by Hennus Bergman, 1992.
  * High DMA channel support & info by Hannu Savolainen
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ds1286.h linux/include/asm-mips/ds1286.h
--- v2.3.99-pre8/linux/include/asm-mips/ds1286.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/ds1286.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ds1286.h,v 1.2 1999/08/19 22:56:33 ralf Exp $
+/* $Id: ds1286.h,v 1.1 1998/07/10 01:14: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/elf.h linux/include/asm-mips/elf.h
--- v2.3.99-pre8/linux/include/asm-mips/elf.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-mips/elf.h	Sat May 13 08:31:25 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: elf.h,v 1.7 1999/08/20 21:59:08 ralf Exp $
+ * $Id: elf.h,v 1.6 1999/02/15 02:22:10 ralf Exp $
  */
 #ifndef __ASM_MIPS_ELF_H
 #define __ASM_MIPS_ELF_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/fcntl.h linux/include/asm-mips/fcntl.h
--- v2.3.99-pre8/linux/include/asm-mips/fcntl.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/fcntl.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.5 1999/01/04 16:09:21 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/floppy.h linux/include/asm-mips/floppy.h
--- v2.3.99-pre8/linux/include/asm-mips/floppy.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/floppy.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.7 1999/08/18 23:37:49 ralf Exp $
+/* $Id: floppy.h,v 1.6 1999/01/04 16:09:21 ralf Exp $
  *
  * Architecture specific parts of the Floppy driver
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/fp.h linux/include/asm-mips/fp.h
--- v2.3.99-pre8/linux/include/asm-mips/fp.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/fp.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: fp.h,v 1.2 1999/07/26 19:42:43 harald Exp $
+/* $Id: fp.h,v 1.1 1998/07/16 19:10:04 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/gdb-stub.h linux/include/asm-mips/gdb-stub.h
--- v2.3.99-pre8/linux/include/asm-mips/gdb-stub.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/gdb-stub.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: gdb-stub.h,v 1.3 1998/08/25 09:21:55 ralf Exp $
+/* $Id: gdb-stub.h,v 1.3 1998/07/20 17:52: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/gfx.h linux/include/asm-mips/gfx.h
--- v2.3.99-pre8/linux/include/asm-mips/gfx.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/gfx.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: gfx.h,v 1.5 1999/08/19 22:56:33 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/hardirq.h linux/include/asm-mips/hardirq.h
--- v2.3.99-pre8/linux/include/asm-mips/hardirq.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips/hardirq.h	Mon May 15 12:10:26 2000
@@ -1,35 +1,48 @@
-/* $Id: hardirq.h,v 1.7 2000/02/23 00:41:38 ralf Exp $
+/* $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.
  *
- * Copyright (C) 1997, 1998, 1999 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1997, 1998, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_HARDIRQ_H
 #define _ASM_HARDIRQ_H
 
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <linux/irq.h>
 
-extern unsigned int local_irq_count[NR_CPUS];
+typedef struct {
+	unsigned int __local_irq_count;
+	unsigned int __local_bh_count;
+} ____cacheline_aligned irq_cpustat_t;
+
+extern irq_cpustat_t irq_stat [NR_CPUS];
+
+/*
+ * Simple wrappers reducing source bloat
+ */
+#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count)
+#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count)
+#define nmi_counter(cpu) (irq_stat[(cpu)].__nmi_counter)
 
 /*
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
  */
 #define in_interrupt() ({ int __cpu = smp_processor_id(); \
-	(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
-#define in_irq() (local_irq_count[smp_processor_id()] != 0)
+	(local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
+#define in_irq() (local_irq_count(smp_processor_id()) != 0)
 
 #ifndef CONFIG_SMP
 
-#define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
+#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)		(local_irq_count(cpu)++)
+#define irq_exit(cpu)		(local_irq_count(cpu)--)
 
 #define synchronize_irq()	barrier();
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/hdreg.h linux/include/asm-mips/hdreg.h
--- v2.3.99-pre8/linux/include/asm-mips/hdreg.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/hdreg.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: hdreg.h,v 1.1 1999/06/17 14:09:00 ralf Exp $
+/* $Id: hdreg.h,v 1.4 1998/05/08 21:05:26 davem Exp $
  *
  *  linux/include/asm-mips/hdreg.h
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/highmem.h linux/include/asm-mips/highmem.h
--- v2.3.99-pre8/linux/include/asm-mips/highmem.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/highmem.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: highmem.h,v 1.2 2000/01/29 01:42:28 ralf Exp $
+/* $Id: highmem.h,v 1.1 2000/01/27 01:05: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/hw_irq.h linux/include/asm-mips/hw_irq.h
--- v2.3.99-pre8/linux/include/asm-mips/hw_irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/hw_irq.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,5 @@
+/* This exists merely to satisfy <linux/irq.h>.  There is
+   nothing that would go here of general interest.
+
+   Everything of consequence is in arch/alpha/kernel/irq_impl.h,
+   to be used only in arch/alpha/kernel/.  */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ide.h linux/include/asm-mips/ide.h
--- v2.3.99-pre8/linux/include/asm-mips/ide.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/ide.h	Sat May 13 08:31:25 2000
@@ -17,7 +17,11 @@
 #include <linux/config.h>
 
 #ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
+#define MAX_HWIFS	10
+# else
 #define MAX_HWIFS	6
+# endif
 #endif
 
 #define ide__sti()	__sti()
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/inventory.h linux/include/asm-mips/inventory.h
--- v2.3.99-pre8/linux/include/asm-mips/inventory.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/inventory.h	Sat May 13 08:31:25 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: inventory.h,v 1.2 1997/12/06 23:55:49 ralf Exp $
+ * $Id:$
  */
 #ifndef __ASM_MIPS_INVENTORY_H
 #define __ASM_MIPS_INVENTORY_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ioctls.h linux/include/asm-mips/ioctls.h
--- v2.3.99-pre8/linux/include/asm-mips/ioctls.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/ioctls.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ioctls.h,v 1.8 1998/08/25 09:21:56 ralf Exp $
+/* $Id: ioctls.h,v 1.5 1998/08/19 21:58:11 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/irq.h linux/include/asm-mips/irq.h
--- v2.3.99-pre8/linux/include/asm-mips/irq.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/irq.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.7 2000/02/23 00:41:38 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/isadep.h linux/include/asm-mips/isadep.h
--- v2.3.99-pre8/linux/include/asm-mips/isadep.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/isadep.h	Sat May 13 08:31:25 2000
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1998 Harald Koerfgen
  *
- * $Id: isadep.h,v 1.2 1999/08/13 17:07:27 harald Exp $
+ * $Id: isadep.h,v 1.1 1999/07/26 19:46:00 harald Exp $
  */
 #include <linux/config.h>
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/jazz.h linux/include/asm-mips/jazz.h
--- v2.3.99-pre8/linux/include/asm-mips/jazz.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/jazz.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: jazz.h,v 1.10 1998/10/18 13:16:02 tsbogend Exp $
+/* $Id: jazz.h,v 1.9 1998/09/19 19:19: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/jazzdma.h linux/include/asm-mips/jazzdma.h
--- v2.3.99-pre8/linux/include/asm-mips/jazzdma.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/jazzdma.h	Sat May 13 08:31:25 2000
@@ -1,7 +1,7 @@
 /*
  * Helpfile for jazzdma.c -- Mips Jazz R4030 DMA controller support
  *
- * $Id: jazzdma.h,v 1.6 1998/03/04 09:51:22 ralf Exp $
+ * $Id:$
  */
 #ifndef __ASM_MIPS_JAZZDMA_H
 #define __ASM_MIPS_JAZZDMA_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/linux_logo.h linux/include/asm-mips/linux_logo.h
--- v2.3.99-pre8/linux/include/asm-mips/linux_logo.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/linux_logo.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: linux_logo.h,v 1.4 1999/01/04 16:09:23 ralf Exp $
+/* $Id: linux_logo.h,v 1.3 1998/09/19 19:19:38 ralf Exp $
  *
  * include/asm-mips/linux_logo.h: This is a linux logo
  *                                to be displayed on boot.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/mc146818rtc.h linux/include/asm-mips/mc146818rtc.h
--- v2.3.99-pre8/linux/include/asm-mips/mc146818rtc.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/mc146818rtc.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: mc146818rtc.h,v 1.3 1999/08/19 22:56:33 ralf Exp $
+/* $Id: mc146818rtc.h,v 1.2 1998/06/30 00:23:10 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/mipsregs.h linux/include/asm-mips/mipsregs.h
--- v2.3.99-pre8/linux/include/asm-mips/mipsregs.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/mipsregs.h	Sat May 13 08:31:25 2000
@@ -30,6 +30,7 @@
 #define CP0_RANDOM $1
 #define CP0_ENTRYLO0 $2
 #define CP0_ENTRYLO1 $3
+#define CP0_CONF $3
 #define CP0_CONTEXT $4
 #define CP0_PAGEMASK $5
 #define CP0_WIRED $6
@@ -333,6 +334,8 @@
 #define CONF_DB				(1 <<  4)
 #define CONF_IB				(1 <<  5)
 #define CONF_SC				(1 << 17)
+#define CONF_AC                         (1 << 23)
+#define CONF_HALT                       (1 << 25)
 
 /*
  * R10000 performance counter definitions.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/mman.h linux/include/asm-mips/mman.h
--- v2.3.99-pre8/linux/include/asm-mips/mman.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/mman.h	Sat May 13 08:31:25 2000
@@ -56,6 +56,12 @@
 #define MCL_CURRENT	1		/* lock all current mappings */
 #define MCL_FUTURE	2		/* lock all future mappings */
 
+#define MADV_NORMAL	0x0		/* default page-in behavior */
+#define MADV_RANDOM	0x1		/* page-in minimum required */
+#define MADV_SEQUENTIAL	0x2		/* read-ahead aggressively */
+#define MADV_WILLNEED	0x3		/* pre-fault pages */
+#define MADV_DONTNEED	0x4		/* discard these pages */
+
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
 #define MAP_FILE       0
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/mmu_context.h linux/include/asm-mips/mmu_context.h
--- v2.3.99-pre8/linux/include/asm-mips/mmu_context.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/mmu_context.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: mmu_context.h,v 1.8 2000/02/23 00:41:38 ralf Exp $
+/* $Id: mmu_context.h,v 1.7 2000/02/04 07:40:53 ralf Exp $
  *
  * Switch a MMU context.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/namei.h linux/include/asm-mips/namei.h
--- v2.3.99-pre8/linux/include/asm-mips/namei.h	Tue Apr 11 15:09:23 2000
+++ linux/include/asm-mips/namei.h	Sat May 13 08:31:25 2000
@@ -3,7 +3,7 @@
  *
  * Included from linux/fs/namei.c
  *
- * $Id: namei.h,v 1.7 1999/06/17 13:30:37 ralf Exp $
+ * $Id: namei.h,v 1.6 1999/01/04 16:09:23 ralf Exp $
  */
 #ifndef __ASM_MIPS_NAMEI_H
 #define __ASM_MIPS_NAMEI_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ng1.h linux/include/asm-mips/ng1.h
--- v2.3.99-pre8/linux/include/asm-mips/ng1.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/ng1.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ng1.h,v 1.4 1999/08/19 22:56:33 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ng1hw.h linux/include/asm-mips/ng1hw.h
--- v2.3.99-pre8/linux/include/asm-mips/ng1hw.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/ng1hw.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ng1hw.h,v 1.5 1999/11/07 10:18:31 ulfc Exp $
+/* $Id: ng1hw.h,v 1.4 1999/08/04 06:01:51 ulfc Exp $
  * 
  * ng1hw.h: Tweaks the newport.h structures and definations to be compatible
  * 	    with IRIX.  Quite ugly, but it works.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/nile4.h linux/include/asm-mips/nile4.h
--- v2.3.99-pre8/linux/include/asm-mips/nile4.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/nile4.h	Sat May 13 08:31:25 2000
@@ -2,7 +2,7 @@
  *  asm-mips/nile4.h -- NEC Vrc-5074 Nile 4 definitions
  *
  *  Copyright (C) 2000 Geert Uytterhoeven <geert@sonycom.com>
- *                     Sony Suprastructure Center Europe (SUPC-E), Brussels
+ *                     Sony Software Development Center Europe (SDCE), Brussels
  *
  *  This file is based on the following documentation:
  *
@@ -10,8 +10,6 @@
  *
  *  $Id: nile4.h,v 1.1 2000/01/26 00:07:45 ralf Exp $
  */
-
-#include <asm/addrspace.h>
 
 
 #define NILE4_BASE		0xbfa00000
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/offset.h linux/include/asm-mips/offset.h
--- v2.3.99-pre8/linux/include/asm-mips/offset.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/offset.h	Sat May 13 08:31:25 2000
@@ -52,7 +52,7 @@
 #define TASK_COUNTER       32
 #define TASK_PRIORITY      36
 #define TASK_MM            44
-#define TASK_STRUCT_SIZE   904
+#define TASK_STRUCT_SIZE   880
 
 /* MIPS specific thread_struct offsets. */
 #define THREAD_REG16   584
@@ -80,7 +80,7 @@
 /* Linux mm_struct offsets. */
 #define MM_USERS      16
 #define MM_PGD        12
-#define MM_CONTEXT    64
+#define MM_CONTEXT    68
 
 /* Linux sigcontext offsets. */
 #define SC_REGS       16
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/paccess.h linux/include/asm-mips/paccess.h
--- v2.3.99-pre8/linux/include/asm-mips/paccess.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips/paccess.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,98 @@
+/* $Id: paccess.h,v 1.1 2000/04/07 12:55:57 raiko 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, 1999, 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ *
+ * Protected memory access.  Used for everything that might take revenge
+ * by sending a DBE error like accessing possibly non-existant memory or
+ * devices.
+ */
+#ifndef _ASM_PACCESS_H
+#define _ASM_PACCESS_H
+
+#include <linux/errno.h>
+
+#define put_dbe(x,ptr) __put_dbe((x),(ptr),sizeof(*(ptr)))
+#define get_dbe(x,ptr) __get_dbe((x),(ptr),sizeof(*(ptr)))
+
+struct __large_pstruct { unsigned long buf[100]; };
+#define __mp(x) (*(struct __large_pstruct *)(x))
+
+#define __get_dbe(x,ptr,size) ({ \
+int __gu_err; \
+__typeof(*(ptr)) __gu_val; \
+unsigned long __gu_addr; \
+__asm__("":"=r" (__gu_val)); \
+__gu_addr = (unsigned long) (ptr); \
+__asm__("":"=r" (__gu_err)); \
+switch (size) { \
+case 1: __get_dbe_asm("lb"); break; \
+case 2: __get_dbe_asm("lh"); break; \
+case 4: __get_dbe_asm("lw"); break; \
+case 8:  __get_dbe_asm("ld"); break; \
+default: __get_dbe_unknown(); break; \
+} x = (__typeof__(*(ptr))) __gu_val; __gu_err; })
+
+#define __get_dbe_asm(insn) \
+({ \
+__asm__ __volatile__( \
+	".set\tpush\n\t" \
+	".set\tnoreorder\n\t" \
+	insn "\t%1,%2\n\t" \
+	"1:\tmove\t%0,$0\n" \
+	".set\tpop\n\t" \
+	"2:\n\t" \
+	".section\t.fixup,\"ax\"\n" \
+	"3:\tli\t%0,%3\n\t" \
+	"move\t%1,$0\n\t" \
+	"j\t2b\n\t" \
+	".previous\n\t" \
+	".section\t__dbe_table,\"a\"\n\t" \
+	".word\t1b-4,3b\n\t" \
+	".previous" \
+	:"=r" (__gu_err), "=r" (__gu_val) \
+	:"o" (__mp(__gu_addr)), "i" (-EFAULT)); })
+
+extern void __get_dbe_unknown(void);
+
+#define __put_dbe(x,ptr,size) ({ \
+int __pu_err; \
+__typeof__(*(ptr)) __pu_val; \
+unsigned long __pu_addr; \
+__pu_val = (x); \
+__pu_addr = (unsigned long) (ptr); \
+__asm__("":"=r" (__pu_err)); \
+switch (size) { \
+case 1: __put_dbe_asm("sb"); break; \
+case 2: __put_dbe_asm("sh"); break; \
+case 4: __put_dbe_asm("sw"); break; \
+case 8: __put_dbe_asm("sd"); break; \
+default: __put_dbe_unknown(); break; \
+} __pu_err; })
+
+#define __put_dbe_asm(insn) \
+({ \
+__asm__ __volatile__( \
+	".set\tpush\n\t" \
+	".set\tnoreorder\n\t" \
+	insn "\t%1,%2\n\t" \
+	"1:\tmove\t%0,$0\n" \
+	".set\tpop\n\t" \
+	"2:\n\t" \
+	".section\t.fixup,\"ax\"\n" \
+	"3:\tli\t%0,%3\n\t" \
+	"j\t2b\n\t" \
+	".previous\n\t" \
+	".section\t__dbe_table,\"a\"\n\t" \
+	".word\t1b-4,3b\n\t" \
+	".previous" \
+	:"=r" (__pu_err) \
+	:"r" (__pu_val), "o" (__mp(__pu_addr)), "i" (-EFAULT)); })
+
+extern void __put_dbe_unknown(void);
+
+#endif /* _ASM_PACCESS_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/parport.h linux/include/asm-mips/parport.h
--- v2.3.99-pre8/linux/include/asm-mips/parport.h	Tue Mar 14 19:10:40 2000
+++ linux/include/asm-mips/parport.h	Sat May 13 08:31:25 2000
@@ -1,13 +1,11 @@
-/* $Id: parport.h,v 1.2 2000/02/18 00:24:48 ralf Exp $
- *
- * parport.h: ia32-specific parport initialisation
+/* $Id$
  *
  * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
  *
  * This file should only be included by drivers/parport/parport_pc.c.
  */
 #ifndef _ASM_PARPORT_H
-#define _ASM_PARPORT_H 1
+#define _ASM_PARPORT_H
 
 static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
 static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
@@ -15,4 +13,4 @@
 	return parport_pc_find_isa_ports (autoirq, autodma);
 }
 
-#endif /* !(_ASM_PARPORT_H) */
+#endif /* _ASM_PARPORT_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- v2.3.99-pre8/linux/include/asm-mips/pci.h	Sun Mar 19 18:35:31 2000
+++ linux/include/asm-mips/pci.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: pci.h,v 1.9 2000/02/24 00:13:19 ralf Exp $
+/* $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
@@ -34,6 +34,13 @@
 #include <asm/scatterlist.h>
 #include <linux/string.h>
 #include <asm/io.h>
+
+#ifdef CONFIG_DDB5074
+#undef PCIBIOS_MIN_IO
+#undef PCIBIOS_MIN_MEM
+#define PCIBIOS_MIN_IO		0x0100000
+#define PCIBIOS_MIN_MEM		0x1000000
+#endif
 
 struct pci_dev;
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/pgalloc.h linux/include/asm-mips/pgalloc.h
--- v2.3.99-pre8/linux/include/asm-mips/pgalloc.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips/pgalloc.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: pgalloc.h,v 1.4 2000/02/24 00:13:19 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/pgtable.h linux/include/asm-mips/pgtable.h
--- v2.3.99-pre8/linux/include/asm-mips/pgtable.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips/pgtable.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.30 2000/02/24 00:13:19 ralf Exp $
+/* $Id: pgtable.h,v 1.31 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
@@ -439,6 +439,7 @@
 extern int do_check_pgt_cache(int, int);
 
 extern pgd_t swapper_pg_dir[1024];
+extern void paging_init(void);
 
 extern void update_mmu_cache(struct vm_area_struct *vma,
 				unsigned long address, pte_t pte);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/posix_types.h linux/include/asm-mips/posix_types.h
--- v2.3.99-pre8/linux/include/asm-mips/posix_types.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/posix_types.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: posix_types.h,v 1.7 2000/02/16 01:07:48 ralf Exp $
+/* $Id: posix_types.h,v 1.6 2000/02/04 23:32:54 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/prctl.h linux/include/asm-mips/prctl.h
--- v2.3.99-pre8/linux/include/asm-mips/prctl.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/prctl.h	Sat May 13 08:31:25 2000
@@ -3,7 +3,7 @@
  *
  * The IRIX kernel maps a page at PRDA_ADDRESS with the
  * contents of prda and fills it the bits on prda_sys.
- * $Id: prctl.h,v 1.1 1997/09/21 22:27:19 miguel Exp $
+ * $Id$
  */
 
 #ifndef __PRCTL_H__
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/processor.h linux/include/asm-mips/processor.h
--- v2.3.99-pre8/linux/include/asm-mips/processor.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips/processor.h	Mon May 15 12:10:26 2000
@@ -12,10 +12,10 @@
 #ifndef _ASM_PROCESSOR_H
 #define _ASM_PROCESSOR_H
 
-#include <asm/isadep.h>
-
 #include <linux/config.h>
 
+#include <asm/isadep.h>
+
 /*
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
@@ -39,7 +39,9 @@
  * System setup and hardware flags..
  * XXX: Should go into mips_cpuinfo.
  */
-extern char wait_available;		/* only available on R4[26]00 */
+extern void (*cpu_wait)(void);	/* only available on R4[26]00 and R3081 */
+extern void r3081_wait(void);
+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 */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ptrace.h linux/include/asm-mips/ptrace.h
--- v2.3.99-pre8/linux/include/asm-mips/ptrace.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/ptrace.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ptrace.h,v 1.8 1999/10/12 17:33:50 harald Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/r4kcache.h linux/include/asm-mips/r4kcache.h
--- v2.3.99-pre8/linux/include/asm-mips/r4kcache.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/r4kcache.h	Sat May 13 08:31:25 2000
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  *
- * $Id: r4kcache.h,v 1.5 1998/03/04 05:36:23 ralf Exp $
+ * $Id: r4kcache.h,v 1.7 1997/12/18 13:00:45 ralf Exp $
  *
  * FIXME: Handle split L2 caches.
  */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/resource.h linux/include/asm-mips/resource.h
--- v2.3.99-pre8/linux/include/asm-mips/resource.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/resource.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: resource.h,v 1.5 2000/02/04 07:40:53 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/semaphore-helper.h linux/include/asm-mips/semaphore-helper.h
--- v2.3.99-pre8/linux/include/asm-mips/semaphore-helper.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/semaphore-helper.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: semaphore-helper.h,v 1.7 1999/10/21 00:23:05 ralf Exp $
+/* $Id: semaphore-helper.h,v 1.6 1999/10/20 21:10:58 ralf Exp $
  *
  * SMP- and interrupt-safe semaphores helper functions.
  *
@@ -92,7 +92,6 @@
 	"sc\t%0, %2\n\t"
 	"beqz\t%0, 1b\n\t"
 	"2:"
-	".text"
 	: "=r"(ret), "=r"(tmp), "=m"(__atomic_fool_gcc(&sem->waking))
 	: "0"(0));
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/semaphore.h linux/include/asm-mips/semaphore.h
--- v2.3.99-pre8/linux/include/asm-mips/semaphore.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/semaphore.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: semaphore.h,v 1.13 2000/02/18 00:24:48 ralf Exp $
+/* $Id: semaphore.h,v 1.12 1999/12/08 22:05:10 harald Exp $
  *
  * SMP- and interrupt-safe semaphores..
  *
@@ -31,7 +31,7 @@
 #if WAITQUEUE_DEBUG
 	long __magic;
 #endif
-};
+} __attribute__((aligned(8)));
 
 #if WAITQUEUE_DEBUG
 # define __SEM_DEBUG_INIT(name) \
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/serial.h linux/include/asm-mips/serial.h
--- v2.3.99-pre8/linux/include/asm-mips/serial.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/serial.h	Sat May 13 08:31:25 2000
@@ -1,5 +1,9 @@
 /* $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.
+ *
  * Copyright (C) 1999 by Ralf Baechle
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sgi/sgi.h linux/include/asm-mips/sgi/sgi.h
--- v2.3.99-pre8/linux/include/asm-mips/sgi/sgi.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sgi/sgi.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgi.h,v 1.1 1999/10/21 00:23:05 ralf Exp $
+/* $Id: sgi.h,v 1.1.1.1 1997/06/01 03:17:12 ralf Exp $
  * sgi.h: Definitions specific to SGI machines.
  *
  * Copyright (C) 1996 David S. Miller (dm@sgi.com)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sgi/sgihpc.h linux/include/asm-mips/sgi/sgihpc.h
--- v2.3.99-pre8/linux/include/asm-mips/sgi/sgihpc.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sgi/sgihpc.h	Sat May 13 08:31:25 2000
@@ -18,8 +18,8 @@
 
 /* An HPC dma descriptor. */
 struct hpc_dma_desc {
-	unsigned long pbuf;      /* physical address of data buffer */
-	unsigned long cntinfo;   /* counter and info bits */
+	unsigned int pbuf;      /* physical address of data buffer */
+	unsigned int cntinfo;   /* counter and info bits */
 #define HPCDMA_EOX    0x80000000 /* last desc in chain for tx */
 #define HPCDMA_EOR    0x80000000 /* last desc in chain for rx */
 #define HPCDMA_EOXP   0x40000000 /* end of packet for tx */
@@ -31,10 +31,10 @@
 #define HPCDMA_OWN    0x00004000 /* Denotes ring buffer ownership on rx */
 #define HPCDMA_BCNT   0x00003fff /* size in bytes of this dma buffer */
 
-	unsigned long pnext;     /* paddr of next hpc_dma_desc if any */
+	unsigned int pnext;     /* paddr of next hpc_dma_desc if any */
 };
 
-typedef volatile unsigned long hpcreg;
+typedef volatile unsigned int hpcreg;
 
 /* HPC1 stuff. */
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sgi/sgimc.h linux/include/asm-mips/sgi/sgimc.h
--- v2.3.99-pre8/linux/include/asm-mips/sgi/sgimc.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sgi/sgimc.h	Sat May 13 08:31:25 2000
@@ -1,16 +1,22 @@
-/* $Id: sgimc.h,v 1.2 1999/12/06 23:13:21 ralf Exp $
+/* $Id: sgimc.h,v 1.1.1.1 1997/06/01 03:17: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.
+ *
  * sgimc.h: Definitions for memory controller hardware found on
  *          SGI IP20, IP22, IP26, and IP28 machines.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
+ * Copyright (C) 1999 Ralf Baechle
+ * Copyright (C) 1999 Silicon Graphics, Inc.
  */
-
-#ifndef _MIPS_SGIMC_H
-#define _MIPS_SGIMC_H
+#ifndef _ASM_SGI_SGIMC_H
+#define _ASM_SGI_SGIMC_H
 
 struct sgimc_misc_ctrl {
-	unsigned long _unused1;
-	volatile unsigned long cpuctrl0;     /* CPU control register 0, readwrite */
+	u32 _unused1;
+	volatile u32 cpuctrl0;     /* CPU control register 0, readwrite */
 #define SGIMC_CCTRL0_REFS         0x0000000f /* REFS mask */
 #define SGIMC_CCTRL0_EREFRESH     0x00000010 /* Memory refresh enable */
 #define SGIMC_CCTRL0_EPERRGIO     0x00000020 /* GIO parity error enable */
@@ -31,8 +37,8 @@
 #define SGIMC_CCTRL0_R4KNOCHKPARR 0x04000000 /* Don't chk parity on mem data reads */
 #define SGIMC_CCTRL0_GIOBTOB      0x08000000 /* Allow GIO back to back writes */
 
-	unsigned long _unused2;
-	volatile unsigned long cpuctrl1;     /* CPU control register 1, readwrite */
+	u32 _unused2;
+	volatile u32 cpuctrl1;     /* CPU control register 1, readwrite */
 #define SGIMC_CCTRL1_EGIOTIMEO    0x00000010 /* GIO bus timeout enable */
 #define SGIMC_CCTRL1_FIXEDEHPC    0x00001000 /* Fixed HPC endianness */
 #define SGIMC_CCTRL1_LITTLEHPC    0x00002000 /* Little endian HPC */
@@ -41,18 +47,18 @@
 #define SGIMC_CCTRL1_FIXEDEEXP1   0x00010000 /* Fixed EXP1 endianness */
 #define SGIMC_CCTRL1_LITTLEEXP1   0x00020000 /* Little endian EXP1 */
 
-	unsigned long _unused3;
-	volatile unsigned long watchdogt;    /* Watchdog reg rdonly, write clears */
+	u32 _unused3;
+	volatile u32 watchdogt;    /* Watchdog reg rdonly, write clears */
 
-	unsigned long _unused4;
-	volatile unsigned long systemid;     /* MC system ID register, readonly */
+	u32 _unused4;
+	volatile u32 systemid;     /* MC system ID register, readonly */
 #define SGIMC_SYSID_MASKREV       0x0000000f /* Revision of MC controller */
 #define SGIMC_SYSID_EPRESENT      0x00000010 /* Indicates presence of EISA bus */
 
-	unsigned long _unused5[3];
-	volatile unsigned long divider;      /* Divider reg for RPSS */
+	u32 _unused5[3];
+	volatile u32 divider;      /* Divider reg for RPSS */
 
-	unsigned long _unused6;
+	u32 _unused6;
 	volatile unsigned char eeprom;       /* EEPROM byte reg for r4k */
 #define SGIMC_EEPROM_PRE          0x00000001 /* eeprom chip PRE pin assertion */
 #define SGIMC_EEPROM_CSEL         0x00000002 /* Active high, eeprom chip select */
@@ -61,16 +67,16 @@
 #define SGIMC_EEPROM_SDATAI       0x00000010 /* Serial EEPROM data-in */
 
 	unsigned char _unused7[3];
-	unsigned long _unused8[3];
+	u32 _unused8[3];
 	volatile unsigned short rcntpre;     /* Preload refresh counter */
 
 	unsigned short _unused9;
-	unsigned long _unused9a;
+	u32 _unused9a;
 	volatile unsigned short rcounter;    /* Readonly refresh counter */
 
 	unsigned short _unused10;
-	unsigned long _unused11[13];
-	volatile unsigned long gioparm;      /* Parameter word for GIO64 */
+	u32 _unused11[13];
+	volatile u32 gioparm;      /* Parameter word for GIO64 */
 #define SGIMC_GIOPARM_HPC64       0x00000001 /* HPC talks to GIO using 64-bits */
 #define SGIMC_GIOPARM_GFX64       0x00000002 /* GFX talks to GIO using 64-bits */
 #define SGIMC_GIOPARM_EXP064      0x00000004 /* EXP(slot0) talks using 64-bits */
@@ -88,18 +94,18 @@
 #define SGIMC_GIOPARM_PLINEEXP0   0x00004000 /* EXP(slot0) has pipeline attr */
 #define SGIMC_GIOPARM_PLINEEXP1   0x00008000 /* EXP(slot1) has pipeline attr */
 
-	unsigned long _unused13;
+	u32 _unused13;
 	volatile unsigned short cputp;       /* CPU bus arb time period */
 
 	unsigned short _unused14;
-	unsigned long _unused15[3];
+	u32 _unused15[3];
 	volatile unsigned short lbursttp;    /* Time period for long bursts */
 
 	unsigned short _unused16;
-	unsigned long _unused17[9];
-	volatile unsigned long mconfig0;     /* Memory config register zero */
-	unsigned long _unused18;
-	volatile unsigned long mconfig1;     /* Memory config register one */
+	u32 _unused17[9];
+	volatile u32 mconfig0;     /* Memory config register zero */
+	u32 _unused18;
+	volatile u32 mconfig1;     /* Memory config register one */
 
         /* These defines apply to both mconfig registers above. */
 #define SGIMC_MCONFIG_FOURMB     0x00000000  /* Physical ram = 4megs */
@@ -110,99 +116,99 @@
 #define SGIMC_MCONFIG_OTEIGHTMB  0x00001f00  /* Physical ram = 128megs */
 #define SGIMC_MCONFIG_RMASK      0x00001f00  /* Ram config bitmask */
 
-	unsigned long _unused19;
-	volatile unsigned long cmacc;        /* Mem access config for CPU */
-	unsigned long _unused20;
-	volatile unsigned long gmacc;        /* Mem access config for GIO */
+	u32 _unused19;
+	volatile u32 cmacc;        /* Mem access config for CPU */
+	u32 _unused20;
+	volatile u32 gmacc;        /* Mem access config for GIO */
 
 	/* This define applies to both cmacc and gmacc registers above. */
 #define SGIMC_MACC_ALIASBIG       0x20000000 /* 512MB home for alias */
 
 	/* Error address/status regs from GIO and CPU perspectives. */
-	unsigned long _unused21;
-	volatile unsigned long cerr;         /* Error address reg for CPU */
-	unsigned long _unused22;
-	volatile unsigned long cstat;        /* Status reg for CPU */
-	unsigned long _unused23;
-	volatile unsigned long gerr;         /* Error address reg for GIO */
-	unsigned long _unused24;
-	volatile unsigned long gstat;        /* Status reg for GIO */
+	u32 _unused21;
+	volatile u32 cerr;         /* Error address reg for CPU */
+	u32 _unused22;
+	volatile u32 cstat;        /* Status reg for CPU */
+	u32 _unused23;
+	volatile u32 gerr;         /* Error address reg for GIO */
+	u32 _unused24;
+	volatile u32 gstat;        /* Status reg for GIO */
 
 	/* Special hard bus locking registers. */
-	unsigned long _unused25;
+	u32 _unused25;
 	volatile unsigned char syssembit;    /* Uni-bit system semaphore */
 	unsigned char _unused26[3];
-	unsigned long _unused27;
+	u32 _unused27;
 	volatile unsigned char mlock;        /* Global GIO memory access lock */
 	unsigned char _unused28[3];
-	unsigned long _unused29;
+	u32 _unused29;
 	volatile unsigned char elock;        /* Locks EISA from GIO accesses */
 
 	/* GIO dma control registers. */
 	unsigned char _unused30[3];
-	unsigned long _unused31[14];
-	volatile unsigned long gio_dma_trans;/* DMA mask to translation GIO addrs */
-	unsigned long _unused32;
-	volatile unsigned long gio_dma_sbits;/* DMA GIO addr substitution bits */
-	unsigned long _unused33;
-	volatile unsigned long dma_intr_cause; /* DMA IRQ cause indicator bits */
-	unsigned long _unused34;
-	volatile unsigned long dma_ctrl;     /* Main DMA control reg */
+	u32 _unused31[14];
+	volatile u32 gio_dma_trans;/* DMA mask to translation GIO addrs */
+	u32 _unused32;
+	volatile u32 gio_dma_sbits;/* DMA GIO addr substitution bits */
+	u32 _unused33;
+	volatile u32 dma_intr_cause; /* DMA IRQ cause indicator bits */
+	u32 _unused34;
+	volatile u32 dma_ctrl;     /* Main DMA control reg */
 
 	/* DMA TLB entry 0 */
-	unsigned long _unused35;
-	volatile unsigned long dtlb_hi0;
-	unsigned long _unused36;
-	volatile unsigned long dtlb_lo0;
+	u32 _unused35;
+	volatile u32 dtlb_hi0;
+	u32 _unused36;
+	volatile u32 dtlb_lo0;
 
 	/* DMA TLB entry 1 */
-	unsigned long _unused37;
-	volatile unsigned long dtlb_hi1;
-	unsigned long _unused38;
-	volatile unsigned long dtlb_lo1;
+	u32 _unused37;
+	volatile u32 dtlb_hi1;
+	u32 _unused38;
+	volatile u32 dtlb_lo1;
 
 	/* DMA TLB entry 2 */
-	unsigned long _unused39;
-	volatile unsigned long dtlb_hi2;
-	unsigned long _unused40;
-	volatile unsigned long dtlb_lo2;
+	u32 _unused39;
+	volatile u32 dtlb_hi2;
+	u32 _unused40;
+	volatile u32 dtlb_lo2;
 
 	/* DMA TLB entry 3 */
-	unsigned long _unused41;
-	volatile unsigned long dtlb_hi3;
-	unsigned long _unused42;
-	volatile unsigned long dtlb_lo3;
+	u32 _unused41;
+	volatile u32 dtlb_hi3;
+	u32 _unused42;
+	volatile u32 dtlb_lo3;
 };
 
 /* MC misc control registers live at physical 0x1fa00000. */
 extern struct sgimc_misc_ctrl *mcmisc_regs;
-extern u32 *rpsscounter;          	/* Chirps at 100ns */
+extern u32 *rpsscounter;          /* Chirps at 100ns */
 
 struct sgimc_dma_ctrl {
-	unsigned long _unused1;
-	volatile unsigned long maddronly;   /* Address DMA goes at */
-	unsigned long _unused2;
-	volatile unsigned long maddrpdeflts; /* Same as above, plus set defaults */
-	unsigned long _unused3;
-	volatile unsigned long dmasz;       /* DMA count */
-	unsigned long _unused4;
-	volatile unsigned long ssize;       /* DMA stride size */
-	unsigned long _unused5;
-	volatile unsigned long gmaddronly;  /* Set GIO DMA but do not start trans */
-	unsigned long _unused6;
-	volatile unsigned long dmaddnpgo;   /* Set GIO DMA addr + start transfer */
-	unsigned long _unused7;
-	volatile unsigned long dmamode;     /* DMA mode config bit settings */
-	unsigned long _unused8;
-	volatile unsigned long dmacount;    /* Zoom and byte count for DMA */
-	unsigned long _unused9;
-	volatile unsigned long dmastart;    /* Pedal to the metal. */
-	unsigned long _unused10;
-	volatile unsigned long dmarunning;  /* DMA op is in progress */
-	unsigned long _unused11;
+	u32 _unused1;
+	volatile u32 maddronly;   /* Address DMA goes at */
+	u32 _unused2;
+	volatile u32 maddrpdeflts; /* Same as above, plus set defaults */
+	u32 _unused3;
+	volatile u32 dmasz;       /* DMA count */
+	u32 _unused4;
+	volatile u32 ssize;       /* DMA stride size */
+	u32 _unused5;
+	volatile u32 gmaddronly;  /* Set GIO DMA but do not start trans */
+	u32 _unused6;
+	volatile u32 dmaddnpgo;   /* Set GIO DMA addr + start transfer */
+	u32 _unused7;
+	volatile u32 dmamode;     /* DMA mode config bit settings */
+	u32 _unused8;
+	volatile u32 dmacount;    /* Zoom and byte count for DMA */
+	u32 _unused9;
+	volatile u32 dmastart;    /* Pedal to the metal. */
+	u32 _unused10;
+	volatile u32 dmarunning;  /* DMA op is in progress */
+	u32 _unused11;
 
 	/* Set dma addr, defaults, and kick it */
-	volatile unsigned long maddr_defl_go; /* go go go! -lm */
+	volatile u32 maddr_defl_go; /* go go go! -lm */
 };
 
 /* MC controller dma regs live at physical 0x1fa02000. */
@@ -213,11 +219,11 @@
 #define SGIMC_SEG1_BADDR     0x20000000
 
 /* Maximum size of the above banks are per machine. */
-extern unsigned long sgimc_seg0_size, sgimc_seg1_size;
+extern u32 sgimc_seg0_size, sgimc_seg1_size;
 #define SGIMC_SEG0_SIZE_ALL         0x10000000 /* 256MB */
 #define SGIMC_SEG1_SIZE_IP20_IP22   0x08000000 /* 128MB */
 #define SGIMC_SEG1_SIZE_IP26_IP28   0x20000000 /* 512MB */
 
 extern void sgimc_init(void);
 
-#endif /* !(_MIPS_SGIMC_H) */
+#endif /* _ASM_SGI_SGIMC_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sgi/sgint23.h linux/include/asm-mips/sgi/sgint23.h
--- v2.3.99-pre8/linux/include/asm-mips/sgi/sgint23.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sgi/sgint23.h	Sat May 13 08:31:25 2000
@@ -1,12 +1,16 @@
-/* $Id: sgint23.h,v 1.1 1999/10/21 00:23:05 ralf Exp $
+/* $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.
  *
  * sgint23.h: Defines for the SGI INT2 and INT3 chipsets.
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  * Copyright (C) 1999 Andrew R. Baker (andrewb@uab.edu) - INT2 corrections
  */
-#ifndef _ASM_SGINT23_H
-#define _ASM_SGINT23_H
+#ifndef _ASM_SGI_SGINT23_H
+#define _ASM_SGI_SGINT23_H
 
 /* These are the virtual IRQ numbers, we divide all IRQ's into
  * 'spaces', the 'space' determines where and how to enable/disable
@@ -163,7 +167,7 @@
 struct sgi_int2_regs {
 	struct sgi_ioc_ints ints;
 
-	volatile unsigned long ledbits;   /* LED control bits */
+	volatile u32 ledbits; 		  /* LED control bits */
 #define INT2_LED_TXCLK         0x01       /* GPI to TXCLK enable */
 #define INT2_LED_SERSLCT0      0x02       /* serial port0: 0=apple 1=pc */
 #define INT2_LED_SERSLCT1      0x04       /* serial port1: 0=apple 1=pc */
@@ -182,8 +186,8 @@
 /* I am guesing there are only two unused registers here 
  * but I could be wrong...			- andrewb
  */
-/*	unsigned long _unused[3]; */
-	unsigned long _unused[2];
+/*	u32 _unused[3]; */
+	u32 _unused[2];
 	struct sgi_ioc_timers timers;
 };
 
@@ -192,13 +196,13 @@
 
 #ifdef __MIPSEB__
 	unsigned char _unused0[3];
-	volatile unsigned char tclear;    /* Timer clear strobe address */
+	volatile unsigned char tclear;		/* Timer clear strobe address */
 #else
-	volatile unsigned char tclear;    /* Timer clear strobe address */
+	volatile unsigned char tclear;		/* Timer clear strobe address */
 	unsigned char _unused0[3];
 #endif
-	volatile unsigned long estatus;   /* Error status reg */
-	unsigned long _unused1[2];
+	volatile u32 estatus;			/* Error status reg */
+	u32 _unused1[2];
 	struct sgi_ioc_timers timers;
 };
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sgialib.h linux/include/asm-mips/sgialib.h
--- v2.3.99-pre8/linux/include/asm-mips/sgialib.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sgialib.h	Sat May 13 08:31:25 2000
@@ -1,11 +1,11 @@
-/* $Id: sgialib.h,v 1.4 1999/02/25 20:55:07 tsbogend Exp $
+/* $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 _MIPS_SGIALIB_H
-#define _MIPS_SGIALIB_H
+#ifndef _ASM_SGIALIB_H
+#define _ASM_SGIALIB_H
 
 #include <asm/sgiarcs.h>
 
@@ -17,10 +17,11 @@
 extern int prom_flags;
 #define PROM_FLAG_ARCS  1
 
-/* Init the PROM library and it's internal data structures.  Called
+/*
+ * 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);
+extern int prom_init(int argc, char **argv, char **envp, int *prom_vec);
 
 /* Simple char-by-char console I/O. */
 extern void prom_putchar(char c);
@@ -81,8 +82,8 @@
 extern void prom_identify_arch(void);
 
 /* Environemt variable routines. */
-extern char *prom_getenv(char *name);
-extern long prom_setenv(char *name, char *value);
+extern PCHAR ArcGetEnvironmentVariable(CHAR *name);
+extern LONG SetEnvironmentVariable(PCHAR name, PCHAR value);
 
 /* ARCS command line acquisition and parsing. */
 extern char *prom_getcmdline(void);
@@ -119,4 +120,4 @@
 extern struct linux_sysid *prom_getsysid(void);
 extern void prom_cacheflush(void);
 
-#endif /* !(_MIPS_SGIALIB_H) */
+#endif /* _ASM_SGIALIB_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sgiarcs.h linux/include/asm-mips/sgiarcs.h
--- v2.3.99-pre8/linux/include/asm-mips/sgiarcs.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sgiarcs.h	Sat May 13 08:31:25 2000
@@ -4,9 +4,10 @@
  *
  * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com)
  */
+#ifndef _ASM_SGIARCS_H
+#define _ASM_SGIARCS_H
 
-#ifndef _MIPS_SGIARCS_H
-#define _MIPS_SGIARCS_H
+#include <asm/arc/types.h>
 
 /* Various ARCS error codes. */
 #define PROM_ESUCCESS                   0x00
@@ -232,8 +233,8 @@
 	long (*mount)(char *file, enum linux_mountops op);
 
 	/* Dealing with firmware environment variables. */
-	char *(*get_evar)(char *name);
-	long (*set_evar)(char *name, char *value);
+	PCHAR (*get_evar)(CHAR *name);
+	LONG (*set_evar)(PCHAR name, PCHAR value);
 
 	long (*get_finfo)(unsigned long fd, struct linux_finfo *buf);
 	long (*set_finfo)(unsigned long fd, unsigned long flags,
@@ -366,4 +367,4 @@
 	int             smax;              /* Max # of symbols. */
 };
 
-#endif /* !(_MIPS_SGIARCS_H) */
+#endif /* _ASM_SGIARCS_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/shmparam.h linux/include/asm-mips/shmparam.h
--- v2.3.99-pre8/linux/include/asm-mips/shmparam.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/shmparam.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: shmparam.h,v 1.3 2000/01/29 01:42:28 ralf Exp $
+/* $Id: shmparam.h,v 1.3 2000/01/28 19:46:32 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sigcontext.h linux/include/asm-mips/sigcontext.h
--- v2.3.99-pre8/linux/include/asm-mips/sigcontext.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sigcontext.h	Sat May 13 08:31:25 2000
@@ -1,16 +1,13 @@
-/*
- * include/asm-mips/sigcontext.h
+/* $Id: sigcontext.h,v 1.5 1997/12/16 05:36:43 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 by Ralf Baechle
- *
- * $Id: sigcontext.h,v 1.5 1997/12/16 05:36:43 ralf Exp $
+ * Copyright (C) 1996, 1997, 2000 by Ralf Baechle
  */
-#ifndef __ASM_MIPS_SIGCONTEXT_H
-#define __ASM_MIPS_SIGCONTEXT_H
+#ifndef _ASM_SIGCONTEXT_H
+#define _ASM_SIGCONTEXT_H
 
 /*
  * Keep this struct definition in sync with the sigcontext fragment
@@ -35,4 +32,4 @@
 	unsigned long      sc_sigset[4];	/* kernel's sigset_t */
 };
 
-#endif /* __ASM_MIPS_SIGCONTEXT_H */
+#endif /* _ASM_SIGCONTEXT_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/siginfo.h linux/include/asm-mips/siginfo.h
--- v2.3.99-pre8/linux/include/asm-mips/siginfo.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/siginfo.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.6 2000/02/18 00:24:48 ralf Exp $
+/* $Id: siginfo.h,v 1.5 1999/08/18 23:37:49 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/signal.h linux/include/asm-mips/signal.h
--- v2.3.99-pre8/linux/include/asm-mips/signal.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/signal.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: signal.h,v 1.7 1999/09/28 22:27:17 ralf Exp $
+/* $Id: signal.h,v 1.6 1999/08/18 23:37:49 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/sni.h linux/include/asm-mips/sni.h
--- v2.3.99-pre8/linux/include/asm-mips/sni.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/sni.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sni.h,v 1.3 1999/01/04 16:09:26 ralf Exp $
+/* $Id: sni.h,v 1.2 1998/09/19 19:19:39 ralf Exp $
  *
  * SNI specific definitions
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h
--- v2.3.99-pre8/linux/include/asm-mips/socket.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips/socket.h	Sat May 13 08:31:25 2000
@@ -1,8 +1,8 @@
 /*
- * $Id: socket.h,v 1.5 1998/03/17 22:16:17 ralf Exp $
+ * $Id: socket.h,v 1.6 2000/02/25 21:52:09 ralf Exp $
  */
-#ifndef __ASM_MIPS_SOCKET_H
-#define __ASM_MIPS_SOCKET_H
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
 
 #include <asm/sockios.h>
 
@@ -56,6 +56,8 @@
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
+#ifdef __KERNEL__
+
 #define SO_PEERNAME             28
 
 /* Types of sockets.  */
@@ -71,4 +73,6 @@
 				   the dev level.  For writing rarp and
 				   other similar things on the user level.  */
 
-#endif /* __ASM_MIPS_SOCKET_H */
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/softirq.h linux/include/asm-mips/softirq.h
--- v2.3.99-pre8/linux/include/asm-mips/softirq.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/softirq.h	Sat May 13 08:31:25 2000
@@ -13,14 +13,12 @@
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
 
-extern unsigned int local_bh_count[NR_CPUS];
-
-#define cpu_bh_disable(cpu)	do { local_bh_count[(cpu)]++; barrier(); } while (0)
-#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count[(cpu)]--; } while (0)
+#define cpu_bh_disable(cpu)	do { local_bh_count(cpu)++; barrier(); } while (0)
+#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count(cpu)--; } while (0)
 
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 #define local_bh_enable()	cpu_bh_enable(smp_processor_id())
 
-#define in_softirq() (local_bh_count[smp_processor_id()] != 0)
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
 
 #endif /* _ASM_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/spinlock.h linux/include/asm-mips/spinlock.h
--- v2.3.99-pre8/linux/include/asm-mips/spinlock.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/spinlock.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: spinlock.h,v 1.9 2000/01/25 00:41:46 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/stackframe.h linux/include/asm-mips/stackframe.h
--- v2.3.99-pre8/linux/include/asm-mips/stackframe.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/stackframe.h	Sat May 13 08:31:25 2000
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 1994, 1995, 1996 by Ralf Baechle and Paul M. Antoine.
  *
- * $Id: stackframe.h,v 1.11 1999/12/04 03:59:12 ralf Exp $
+ * $Id: stackframe.h,v 1.10 1999/08/13 17:07:27 harald Exp $
  */
 #ifndef __ASM_MIPS_STACKFRAME_H
 #define __ASM_MIPS_STACKFRAME_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/string.h linux/include/asm-mips/string.h
--- v2.3.99-pre8/linux/include/asm-mips/string.h	Sat Feb 26 22:31:56 2000
+++ linux/include/asm-mips/string.h	Sat May 13 08:31:25 2000
@@ -100,20 +100,18 @@
 	".set\tnoreorder\n\t"
 	".set\tnoat\n"
 	"1:\tlbu\t%3,(%0)\n\t"
-#if defined(CONFIG_CPU_R3000)
-	"lbu\t$1,(%1)\n\t"
-	"nop\n\t"
-	"beqz\t%2,2f\n\t"
-#else
 	"beqz\t%2,2f\n\t"
 	"lbu\t$1,(%1)\n\t"
-#endif
 	"subu\t%2,1\n\t"
 	"bne\t$1,%3,3f\n\t"
 	"addiu\t%0,1\n\t"
 	"bnez\t%3,1b\n\t"
 	"addiu\t%1,1\n"
-	"2:\tmove\t%3,$1\n"
+	"2:\n\t"
+#if defined(CONFIG_CPU_R3000)
+	"nop\n\t"
+#endif	
+	"move\t%3,$1\n"
 	"3:\tsubu\t%3,$1\n\t"
 	".set\tat\n\t"
 	".set\treorder"
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/system.h linux/include/asm-mips/system.h
--- v2.3.99-pre8/linux/include/asm-mips/system.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/system.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.21 1999/12/30 14:21:21 raiko Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.3.99-pre8/linux/include/asm-mips/termios.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/termios.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.9 2000/02/18 00:24:48 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/timex.h linux/include/asm-mips/timex.h
--- v2.3.99-pre8/linux/include/asm-mips/timex.h	Fri Jun 25 17:37:53 1999
+++ linux/include/asm-mips/timex.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: timex.h,v 1.2 1999/02/15 02:22:14 ralf Exp $
+/* $Id: timex.h,v 1.1 1998/08/25 09:22:03 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
@@ -17,6 +17,7 @@
 	(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
 		<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
 
+#ifdef __KERNEL__
 /*
  * Standard way to access the cycle counter.
  * Currently only used on SMP for scheduling.
@@ -35,5 +36,6 @@
 {
 	return read_32bit_cp0_register(CP0_COUNT);
 }
+#endif /* __KERNEL__ */
 
 #endif /*  __ASM_MIPS_TIMEX_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/types.h linux/include/asm-mips/types.h
--- v2.3.99-pre8/linux/include/asm-mips/types.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/types.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: types.h,v 1.4 2000/02/18 00:24:48 ralf Exp $
+/* $Id: types.h,v 1.3 1999/08/18 23:37:50 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/uaccess.h linux/include/asm-mips/uaccess.h
--- v2.3.99-pre8/linux/include/asm-mips/uaccess.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/uaccess.h	Sat May 13 08:31:25 2000
@@ -407,7 +407,7 @@
 #define clear_user(addr,n) ({ \
 void * __cl_addr = (addr); \
 unsigned long __cl_size = (n); \
-if (__cl_size && __access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
+if (__cl_size && access_ok(VERIFY_WRITE, ((unsigned long)(__cl_addr)), __cl_size)) \
 __cl_size = __clear_user(__cl_addr, __cl_size); \
 __cl_size; })
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/ucontext.h linux/include/asm-mips/ucontext.h
--- v2.3.99-pre8/linux/include/asm-mips/ucontext.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/ucontext.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ucontext.h,v 1.2 1999/09/28 22:27:17 ralf Exp $
+/* $Id: ucontext.h,v 1.2 1999/09/27 16:01:40 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/unaligned.h linux/include/asm-mips/unaligned.h
--- v2.3.99-pre8/linux/include/asm-mips/unaligned.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/unaligned.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: unaligned.h,v 1.3 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/unistd.h linux/include/asm-mips/unistd.h
--- v2.3.99-pre8/linux/include/asm-mips/unistd.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/unistd.h	Sat May 13 08:31:25 2000
@@ -1015,7 +1015,7 @@
 #define __NR_ptrace			(__NR_Linux +  26)
 #define __NR_alarm			(__NR_Linux +  27)
 #define __NR_oldfstat			(__NR_Linux +  28)
-#define __NR_unused29			(__NR_Linux +  29)
+#define __NR_pause			(__NR_Linux +  29)
 #define __NR_utime			(__NR_Linux +  30)
 #define __NR_stty			(__NR_Linux +  31)
 #define __NR_gtty			(__NR_Linux +  32)
@@ -1203,11 +1203,13 @@
 #define __NR_lstat64			(__NR_Linux + 214)
 #define __NR_fstat64			(__NR_Linux + 215)
 #define __NR_pivot_root			(__NR_Linux + 216)
+#define __NR_mincore			(__NR_Linux + 217)
+#define __NR_madvise			(__NR_Linux + 218)
 
 /*
  * Offset of the last Linux flavoured syscall
  */
-#define __NR_Linux_syscalls		216
+#define __NR_Linux_syscalls		218
 
 #ifndef _LANGUAGE_ASSEMBLY
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/watch.h linux/include/asm-mips/watch.h
--- v2.3.99-pre8/linux/include/asm-mips/watch.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/watch.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: watch.h,v 1.3 1998/08/25 09:22:05 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips/wbflush.h linux/include/asm-mips/wbflush.h
--- v2.3.99-pre8/linux/include/asm-mips/wbflush.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips/wbflush.h	Sat May 13 08:31:25 2000
@@ -7,7 +7,7 @@
  *
  * Copyright (c) 1998 Harald Koerfgen
  *
- * $Id: wbflush.h,v 1.3 1999/10/07 07:27:43 raiko Exp $
+ * $Id: wbflush.h,v 1.2 1999/08/13 17:07:28 harald Exp $
  */
 #ifndef __ASM_MIPS_WBFLUSH_H
 #define __ASM_MIPS_WBFLUSH_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/a.out.h linux/include/asm-mips64/a.out.h
--- v2.3.99-pre8/linux/include/asm-mips64/a.out.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/a.out.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: a.out.h,v 1.2 2000/01/16 01:40:43 ralf Exp $
+/* $Id: a.out.h,v 1.1 1999/08/18 23:37:50 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/addrspace.h linux/include/asm-mips64/addrspace.h
--- v2.3.99-pre8/linux/include/asm-mips64/addrspace.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/addrspace.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: addrspace.h,v 1.6 2000/02/10 20:20:15 kanoj Exp $
+/* $Id: addrspace.h,v 1.5 2000/02/01 00:32:01 kanoj 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
@@ -103,5 +103,10 @@
 #define K1BASE		0x9000000000000000
 #endif
 #define K2BASE		0xc000000000000000
+
+#if !defined (CONFIG_CPU_R8000)
+#define COMPAT_K1BASE32		0xffffffffa0000000
+#define PHYS_TO_COMPATK1(x)	((x) | COMPAT_K1BASE32) /* 32-bit compat k1 */
+#endif
 
 #endif /* _ASM_ADDRSPACE_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/arc/hinv.h linux/include/asm-mips64/arc/hinv.h
--- v2.3.99-pre8/linux/include/asm-mips64/arc/hinv.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/arc/hinv.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: hinv.h,v 1.1 2000/01/17 23:32:47 ralf Exp $
+/* $Id$
  *
  * ARCS hardware/memory inventory/configuration and system ID definitions.
  */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/asm.h linux/include/asm-mips64/asm.h
--- v2.3.99-pre8/linux/include/asm-mips64/asm.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/asm.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: asm.h,v 1.3 2000/01/17 23:32:47 ralf Exp $
+/* $Id: asm.h,v 1.2 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/asmmacro.h linux/include/asm-mips64/asmmacro.h
--- v2.3.99-pre8/linux/include/asm-mips64/asmmacro.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/asmmacro.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: asmmacro.h,v 1.1 1999/12/04 03:59:12 ralf Exp $
+/* $Id: asmmacro.h,v 1.2 1999/10/19 20:51:53 ralf Exp $
  *
  * asmmacro.h: Assembler macros to make things easier to read.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/atomic.h linux/include/asm-mips64/atomic.h
--- v2.3.99-pre8/linux/include/asm-mips64/atomic.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips64/atomic.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: atomic.h,v 1.1 1999/08/18 23:37:50 ralf Exp $
+/* $Id$
  *
  * Atomic operations that C can't guarantee us.  Useful for
  * resource counting etc..
@@ -16,6 +16,7 @@
 #define _ASM_ATOMIC_H
 
 #include <linux/config.h>
+
 #include <asm/sgidefs.h>
 
 #ifdef CONFIG_SMP
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/bcache.h linux/include/asm-mips64/bcache.h
--- v2.3.99-pre8/linux/include/asm-mips64/bcache.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/bcache.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: bcache.h,v 1.3 2000/01/21 22:34:07 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/bitops.h linux/include/asm-mips64/bitops.h
--- v2.3.99-pre8/linux/include/asm-mips64/bitops.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/bitops.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.4 1999/12/04 03:59:12 ralf Exp $
+/* $Id: bitops.h,v 1.3 1999/08/20 21:59:08 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
@@ -376,12 +376,12 @@
 #define ext2_find_first_zero_bit(addr, size) \
         ext2_find_next_zero_bit((addr), (size), 0)
 
-extern inline unsigned long
+extern inline unsigned int
 ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
 {
-	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
-	unsigned long result = offset & ~31UL;
-	unsigned long tmp;
+	unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
+	unsigned int result = offset & ~31UL;
+	unsigned int tmp;
 
 	if (offset >= size)
 		return size;
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/bootinfo.h linux/include/asm-mips64/bootinfo.h
--- v2.3.99-pre8/linux/include/asm-mips64/bootinfo.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/bootinfo.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: bootinfo.h,v 1.2 2000/01/17 23:32:47 ralf Exp $
+/* $Id: bootinfo.h,v 1.1 1999/08/18 23:37:50 ralf Exp $
  *
  * bootinfo.h -- Definition of the Linux/MIPS boot information structure
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/branch.h linux/include/asm-mips64/branch.h
--- v2.3.99-pre8/linux/include/asm-mips64/branch.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/branch.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: branch.h,v 1.1 1999/08/21 22:19:17 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/bugs.h linux/include/asm-mips64/bugs.h
--- v2.3.99-pre8/linux/include/asm-mips64/bugs.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/bugs.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: bugs.h,v 1.1 1999/08/18 23:37:50 ralf Exp $
+/* $Id$
  *
  *  Copyright (C) 1995 Waldorf Electronics
  *  Copyright (C) 1997, 1999 Ralf Baechle
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/byteorder.h linux/include/asm-mips64/byteorder.h
--- v2.3.99-pre8/linux/include/asm-mips64/byteorder.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/byteorder.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: byteorder.h,v 1.1 1999/08/18 23:37:50 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/cache.h linux/include/asm-mips64/cache.h
--- v2.3.99-pre8/linux/include/asm-mips64/cache.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/cache.h	Sat May 13 08:31:25 2000
@@ -11,6 +11,7 @@
 #define _ASM_CACHE_H
 
 /* bytes per L1 cache line */
-#define L1_CACHE_BYTES	32	/* A guess */
+#define L1_CACHE_BYTES		32	/* A guess */
+#define SMP_CACHE_BYTES		L1_CACHE_BYTES
 
 #endif /* _ASM_CACHE_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/checksum.h linux/include/asm-mips64/checksum.h
--- v2.3.99-pre8/linux/include/asm-mips64/checksum.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/checksum.h	Sat May 13 08:31:25 2000
@@ -10,8 +10,6 @@
 #ifndef _ASM_CHECKSUM_H
 #define _ASM_CHECKSUM_H
 
-#include <asm/checksum.h>
-
 /*
  * computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/cpu.h linux/include/asm-mips64/cpu.h
--- v2.3.99-pre8/linux/include/asm-mips64/cpu.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/cpu.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: cpu.h,v 1.1 1999/12/04 03:59:12 ralf Exp $
+/* $Id: cpu.h,v 1.1 1999/10/19 20:51: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/current.h linux/include/asm-mips64/current.h
--- v2.3.99-pre8/linux/include/asm-mips64/current.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/current.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: current.h,v 1.4 2000/01/17 23:32:47 ralf Exp $
+/* $Id: current.h,v 1.3 1999/12/04 03:59: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
@@ -15,21 +15,4 @@
 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	noreorder;			\
-	ld	reg, %lo(kernelsp)(reg);	\
-	.set	pop;				\
-	ori	reg, 0x3fff;			\
-	xori	reg, 0x3fff
-
-#endif
-
 #endif /* _ASM_CURRENT_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/delay.h linux/include/asm-mips64/delay.h
--- v2.3.99-pre8/linux/include/asm-mips64/delay.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips64/delay.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: delay.h,v 1.1 1999/08/18 23:37:50 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/div64.h linux/include/asm-mips64/div64.h
--- v2.3.99-pre8/linux/include/asm-mips64/div64.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/div64.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: div64.h,v 1.1 2000/01/29 01:42:28 ralf Exp $
+/* $Id: div64.h,v 1.1 2000/01/28 23:18: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/dma.h linux/include/asm-mips64/dma.h
--- v2.3.99-pre8/linux/include/asm-mips64/dma.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips64/dma.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.4 2000/01/29 01:42:28 ralf Exp $
+/* $Id: dma.h,v 1.5 2000/03/07 15:45:42 ralf Exp $
  *
  * linux/include/asm/dma.h: Defines for using and allocating dma channels.
  * Written by Hennus Bergman, 1992.
@@ -13,6 +13,7 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
+#include <linux/config.h>
 #include <asm/io.h>			/* need byte IO */
 #include <linux/spinlock.h>		/* And spinlocks */
 #include <linux/delay.h>
@@ -294,5 +295,13 @@
 /* These are in kernel/dma.c: */
 extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
+
+/* From PCI */
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy	(0)
+#endif
 
 #endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ds1286.h linux/include/asm-mips64/ds1286.h
--- v2.3.99-pre8/linux/include/asm-mips64/ds1286.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ds1286.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ds1286.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/elf.h linux/include/asm-mips64/elf.h
--- v2.3.99-pre8/linux/include/asm-mips64/elf.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-mips64/elf.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: elf.h,v 1.4 2000/02/24 00:13:20 ralf Exp $
+/* $Id: elf.h,v 1.3 2000/01/17 23:32:47 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/errno.h linux/include/asm-mips64/errno.h
--- v2.3.99-pre8/linux/include/asm-mips64/errno.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/errno.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: errno.h,v 1.2 1999/09/28 22:27:19 ralf Exp $
+/* $Id: errno.h,v 1.1 1999/08/18 23:37:51 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/fcntl.h linux/include/asm-mips64/fcntl.h
--- v2.3.99-pre8/linux/include/asm-mips64/fcntl.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/fcntl.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: fcntl.h,v 1.1 1999/08/18 23:37:51 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/floppy.h linux/include/asm-mips64/floppy.h
--- v2.3.99-pre8/linux/include/asm-mips64/floppy.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/floppy.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.2 1999/08/21 22:19:17 ralf Exp $
+/* $Id$
  *
  * Architecture specific parts of the Floppy driver
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/gfx.h linux/include/asm-mips64/gfx.h
--- v2.3.99-pre8/linux/include/asm-mips64/gfx.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/gfx.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: gfx.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/hardirq.h linux/include/asm-mips64/hardirq.h
--- v2.3.99-pre8/linux/include/asm-mips64/hardirq.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips64/hardirq.h	Sat May 13 08:31:25 2000
@@ -1,41 +1,101 @@
-/* $Id: hardirq.h,v 1.4 2000/02/23 00:41:38 ralf Exp $
+/* $Id: hardirq.h,v 1.6 2000/03/07 15:45:42 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 by Ralf Baechle
- * Copyright (C) 1999 Silicon Graphics, Inc.
+ * Copyright (C) 1997 - 2000 by Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  */
 #ifndef _ASM_HARDIRQ_H
 #define _ASM_HARDIRQ_H
 
 #include <linux/config.h>
 #include <linux/threads.h>
+#include <linux/irq.h>
 
-extern unsigned int local_irq_count[NR_CPUS];
+typedef struct {
+	unsigned long __local_irq_count;
+	unsigned long __local_bh_count;
+	unsigned long __pad[14];
+} ____cacheline_aligned irq_cpustat_t;
+
+extern irq_cpustat_t irq_stat [NR_CPUS];
+
+/*
+ * Simple wrappers reducing source bloat
+ */
+#define local_irq_count(cpu) (irq_stat[(cpu)].__local_irq_count)
+#define local_bh_count(cpu) (irq_stat[(cpu)].__local_bh_count)
 
 /*
  * Are we in an interrupt context? Either doing bottom half
  * or hardware interrupt processing?
  */
 #define in_interrupt() ({ int __cpu = smp_processor_id(); \
-	(local_irq_count[__cpu] + local_bh_count[__cpu] != 0); })
-#define in_irq() (local_irq_count[smp_processor_id()] != 0)
+	(local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
+#define in_irq() (local_irq_count(smp_processor_id()) != 0)
 
 #ifndef CONFIG_SMP
 
-#define hardirq_trylock(cpu)	(local_irq_count[cpu] == 0)
+#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 -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/hdreg.h linux/include/asm-mips64/hdreg.h
--- v2.3.99-pre8/linux/include/asm-mips64/hdreg.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/hdreg.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: hdreg.h,v 1.1 1999/08/21 22:19:17 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/highmem.h linux/include/asm-mips64/highmem.h
--- v2.3.99-pre8/linux/include/asm-mips64/highmem.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/highmem.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: highmem.h,v 1.2 2000/01/29 01:42:28 ralf Exp $
+/* $Id: highmem.h,v 1.1 2000/01/27 01:05: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/hw_irq.h linux/include/asm-mips64/hw_irq.h
--- v2.3.99-pre8/linux/include/asm-mips64/hw_irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/hw_irq.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,5 @@
+/* This exists merely to satisfy <linux/irq.h>.  There is
+   nothing that would go here of general interest.
+
+   Everything of consequence is in arch/alpha/kernel/irq_impl.h,
+   to be used only in arch/alpha/kernel/.  */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ide.h linux/include/asm-mips64/ide.h
--- v2.3.99-pre8/linux/include/asm-mips64/ide.h	Fri Mar 10 16:40:49 2000
+++ linux/include/asm-mips64/ide.h	Sat May 13 08:31:25 2000
@@ -17,7 +17,11 @@
 #include <linux/config.h>
 
 #ifndef MAX_HWIFS
+# ifdef CONFIG_BLK_DEV_IDEPCI
+#define MAX_HWIFS	10
+# else
 #define MAX_HWIFS	6
+# endif
 #endif
 
 #define ide__sti()	__sti()
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/init.h linux/include/asm-mips64/init.h
--- v2.3.99-pre8/linux/include/asm-mips64/init.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/init.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: init.h,v 1.1 1999/08/18 23:37:51 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/inst.h linux/include/asm-mips64/inst.h
--- v2.3.99-pre8/linux/include/asm-mips64/inst.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/inst.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: inst.h,v 1.1 1999/12/04 03:59:12 ralf Exp $
+/* $Id: inst.h,v 1.1 1999/10/09 20:55:09 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/io.h linux/include/asm-mips64/io.h
--- v2.3.99-pre8/linux/include/asm-mips64/io.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/io.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.10 2000/02/24 00:13:20 ralf Exp $
+/* $Id: io.h,v 1.9 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
@@ -111,7 +111,7 @@
 	return (void *)(address + PAGE_OFFSET);
 }
 
-#define	BRIDGE_DIRECT_MAPPED_BASE	0xa200000000000000ull
+#define	BRIDGE_DIRECT_MAPPED_BASE	0xa180000000000000ull
 
 /*
  * IO bus memory addresses are also 1:1 with the physical address
@@ -264,44 +264,44 @@
  *  - you don't have to worry about side effects within the __builtin..
  */
 #define outb(val,port) \
-((__builtin_constant_p((port)) && (port) < 32768) ? \
-	__outbc((val),(port)) : \
-	__outb((val),(port)))
+((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
+	__outbc((val),(port)^(3)) : \
+	__outb((val),(port)^(3)))
 
 #define inb(port) \
-((__builtin_constant_p((port)) && (port) < 32768) ? \
-	__inbc(port) : \
-	__inb(port))
+((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
+	__inbc((port)^(3)) : \
+	__inb((port)^(3)))
 
 #define outb_p(val,port) \
-((__builtin_constant_p((port)) && (port) < 32768) ? \
-	__outbc_p((val),(port)) : \
-	__outb_p((val),(port)))
+((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
+	__outbc_p((val),(port)^(3)) : \
+	__outb_p((val),(port)^(3)))
 
 #define inb_p(port) \
-((__builtin_constant_p((port)) && (port) < 32768) ? \
-	__inbc_p(port) : \
-	__inb_p(port))
+((__builtin_constant_p((port)^(3)) && ((port)^(3)) < 32768) ? \
+	__inbc_p((port)^(3)) : \
+	__inb_p((port)^(3)))
 
 #define outw(val,port) \
-((__builtin_constant_p((port^2)) && (port^2) < 32768) ? \
-	__outwc((val),(port^2)) : \
-	__outw((val),(port^2)))
+((__builtin_constant_p(((port)^(2))) && ((port)^(2)) < 32768) ? \
+	__outwc((val),((port)^(2))) : \
+	__outw((val),((port)^(2))))
 
 #define inw(port) \
-((__builtin_constant_p((port^2)) && (port^2) < 32768) ? \
-	__inwc(port^2) : \
-	__inw(port^2))
+((__builtin_constant_p(((port)^(2))) && ((port)^(2)) < 32768) ? \
+	__inwc((port)^(2)) : \
+	__inw((port)^(2)))
 
 #define outw_p(val,port) \
-((__builtin_constant_p((port)) && (port) < 32768) ? \
-	__outwc_p((val),(port)) : \
-	__outw_p((val),(port)))
+((__builtin_constant_p((port)^(2)) && ((port)^(2)) < 32768) ? \
+	__outwc_p((val),(port)^(2)) : \
+	__outw_p((val),(port)^(2)))
 
 #define inw_p(port) \
-((__builtin_constant_p((port)) && (port) < 32768) ? \
-	__inwc_p(port) : \
-	__inw_p(port))
+((__builtin_constant_p((port)^(2)) && ((port)^(2)) < 32768) ? \
+	__inwc_p((port)^(2)) : \
+	__inw_p((port)^(2)))
 
 #define outl(val,port) \
 ((__builtin_constant_p((port)) && (port) < 32768) ? \
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ioc3.h linux/include/asm-mips64/ioc3.h
--- v2.3.99-pre8/linux/include/asm-mips64/ioc3.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ioc3.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ioc3.h,v 1.2 2000/02/18 09:54:39 ulfc Exp $
+/* $Id: ioc3.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
  *
  * Copyright (C) 1999 Ralf Baechle
  * This file is part of the Linux driver for the SGI IOC3.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ioctl.h linux/include/asm-mips64/ioctl.h
--- v2.3.99-pre8/linux/include/asm-mips64/ioctl.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ioctl.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ioctl.h,v 1.1 1999/08/18 23:37:51 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ioctls.h linux/include/asm-mips64/ioctls.h
--- v2.3.99-pre8/linux/include/asm-mips64/ioctls.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ioctls.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ioctls.h,v 1.1 1999/08/18 23:37:51 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/irq.h linux/include/asm-mips64/irq.h
--- v2.3.99-pre8/linux/include/asm-mips64/irq.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/irq.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/linux_logo.h linux/include/asm-mips64/linux_logo.h
--- v2.3.99-pre8/linux/include/asm-mips64/linux_logo.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/linux_logo.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: linux_logo.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $Id$
  *
  * include/asm-mips/linux_logo.h: This is a linux logo
  *                                to be displayed on boot.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/mc146818rtc.h linux/include/asm-mips64/mc146818rtc.h
--- v2.3.99-pre8/linux/include/asm-mips64/mc146818rtc.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/mc146818rtc.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: mc146818rtc.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/mipsregs.h linux/include/asm-mips64/mipsregs.h
--- v2.3.99-pre8/linux/include/asm-mips64/mipsregs.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/mipsregs.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: mipsregs.h,v 1.2 2000/01/17 23:32:47 ralf Exp $
+/* $Id: mipsregs.h,v 1.1 1999/08/18 23:37:51 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
@@ -238,6 +238,7 @@
 #define ST0_CE			0x00020000
 #define ST0_CH			0x00040000
 #define ST0_SR			0x00100000
+#define ST0_TS			0x00200000
 #define ST0_BEV			0x00400000
 #define ST0_RE			0x02000000
 #define ST0_FR			0x04000000
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/mman.h linux/include/asm-mips64/mman.h
--- v2.3.99-pre8/linux/include/asm-mips64/mman.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/mman.h	Sat May 13 08:31:25 2000
@@ -55,6 +55,12 @@
 #define MCL_CURRENT	1		/* lock all current mappings */
 #define MCL_FUTURE	2		/* lock all future mappings */
 
+#define MADV_NORMAL	0x0		/* default page-in behavior */
+#define MADV_RANDOM	0x1		/* page-in minimum required */
+#define MADV_SEQUENTIAL	0x2		/* read-ahead aggressively */
+#define MADV_WILLNEED	0x3		/* pre-fault pages */
+#define MADV_DONTNEED	0x4		/* discard these pages */
+
 /* compatibility flags */
 #define MAP_ANON       MAP_ANONYMOUS
 #define MAP_FILE       0
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/mmu_context.h linux/include/asm-mips64/mmu_context.h
--- v2.3.99-pre8/linux/include/asm-mips64/mmu_context.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips64/mmu_context.h	Sat May 13 08:31:25 2000
@@ -12,11 +12,17 @@
 #ifndef _ASM_MMU_CONTEXT_H
 #define _ASM_MMU_CONTEXT_H
 
+#include <linux/config.h>
+#include <linux/slab.h>
 #include <asm/pgalloc.h>
+#include <asm/processor.h>
 
-/* Fuck.  The f-word is here so you can grep for it :-)  */
-extern unsigned long asid_cache;
-extern pgd_t *current_pgd;
+#ifndef CONFIG_SMP
+#define CPU_CONTEXT(cpu, mm)	(mm)->context
+#else
+#define CPU_CONTEXT(cpu, mm)	(*((unsigned long *)((mm)->context) + cpu))
+#endif
+#define ASID_CACHE(cpu)		cpu_data[cpu].asid_cache
 
 #define ASID_INC	0x1
 #define ASID_MASK	0xff
@@ -33,14 +39,16 @@
 #define ASID_FIRST_VERSION ((unsigned long)(~ASID_VERSION_MASK) + 1)
 
 extern inline void
-get_new_mmu_context(struct mm_struct *mm, unsigned long asid)
+get_new_cpu_mmu_context(struct mm_struct *mm, unsigned long cpu)
 {
+	unsigned long asid = ASID_CACHE(cpu);
+
 	if (! ((asid += ASID_INC) & ASID_MASK) ) {
-		flush_tlb_all(); /* start new asid cycle */
+		_flush_tlb_all(); /* start new asid cycle */
 		if (!asid)      /* fix version if needed */
 			asid = ASID_FIRST_VERSION;
 	}
-	mm->context = asid_cache = asid;
+	CPU_CONTEXT(cpu, mm) = ASID_CACHE(cpu) = asid;
 }
 
 /*
@@ -50,20 +58,34 @@
 extern inline void
 init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
+#ifndef CONFIG_SMP
 	mm->context = 0;
+#else
+	/* Make sure not to do anything during a clone-vm operation */
+	if ((current == tsk) || (current->mm != mm)) {
+		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)
+			memset((void *)mm->context, 0, smp_num_cpus * 
+							sizeof(unsigned long));
+		else
+			printk("Warning: init_new_context failed\n");
+	}
+#endif
 }
 
 extern inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                              struct task_struct *tsk, unsigned cpu)
 {
-	unsigned long asid = asid_cache;
-
 	/* Check if our ASID is of an older version and thus invalid */
-	if ((next->context ^ asid) & ASID_VERSION_MASK)
-		get_new_mmu_context(next, asid);
+	if ((CPU_CONTEXT(cpu, next) ^ ASID_CACHE(cpu)) & ASID_VERSION_MASK)
+		get_new_cpu_mmu_context(next, cpu);
 
-	current_pgd = next->pgd;
-	set_entryhi(next->context);
+	set_entryhi(CPU_CONTEXT(cpu, next));
 }
 
 /*
@@ -72,7 +94,10 @@
  */
 extern inline void destroy_context(struct mm_struct *mm)
 {
-	/* Nothing to do.  */
+#ifdef CONFIG_SMP
+	if (mm->context)
+		kfree((void *)mm->context);
+#endif
 }
 
 /*
@@ -83,10 +108,9 @@
 activate_mm(struct mm_struct *prev, struct mm_struct *next)
 {
 	/* Unconditionally get a new ASID.  */
-	get_new_mmu_context(next, asid_cache);
+	get_new_cpu_mmu_context(next, smp_processor_id());
 
-	current_pgd = next->pgd;
-	set_entryhi(next->context);
+	set_entryhi(CPU_CONTEXT(smp_processor_id(), next));
 }
 
 #endif /* _ASM_MMU_CONTEXT_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/mmzone.h linux/include/asm-mips64/mmzone.h
--- v2.3.99-pre8/linux/include/asm-mips64/mmzone.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips64/mmzone.h	Sat May 13 08:31:25 2000
@@ -11,9 +11,6 @@
 
 typedef struct plat_pglist_data {
 	pg_data_t	gendata;
-	unsigned long	physstart;
-	unsigned long	size;
-	unsigned long	start_mapnr;
 } plat_pg_data_t;
 
 /*
@@ -25,10 +22,10 @@
 
 #define PHYSADDR_TO_NID(pa)		NASID_TO_COMPACT_NODEID(NASID_GET(pa))
 #define PLAT_NODE_DATA(n)		(plat_node_data[n])
-#define PLAT_NODE_DATA_STARTNR(n)	(PLAT_NODE_DATA(n)->start_mapnr)
+#define PLAT_NODE_DATA_STARTNR(n)    (PLAT_NODE_DATA(n)->gendata.node_start_mapnr)
+#define PLAT_NODE_DATA_SIZE(n)	     (PLAT_NODE_DATA(n)->gendata.node_size)
 #define PLAT_NODE_DATA_LOCALNR(p, n) \
-			(((p) - PLAT_NODE_DATA(n)->physstart) >> PAGE_SHIFT)
-#define PAGE_TO_PLAT_NODE(p)		(plat_pg_data_t *)((p)->zone->zone_pgdat)
+		(((p) - PLAT_NODE_DATA(n)->gendata.node_start_paddr) >> PAGE_SHIFT)
 
 #ifdef CONFIG_DISCONTIGMEM
 
@@ -38,8 +35,6 @@
 
 /*
  * Given a kernel address, find the home node of the underlying memory.
- * For production kern_addr_valid, change to return "numnodes" instead
- * of panicing.
  */
 #define KVADDR_TO_NID(kaddr) \
 	((NASID_TO_COMPACT_NODEID(NASID_GET(__pa(kaddr))) != -1) ? \
@@ -58,13 +53,6 @@
 #define NODE_MEM_MAP(nid)	(NODE_DATA(nid)->node_mem_map)
 
 /*
- * Given a mem_map_t, LOCAL_MAP_BASE finds the owning node for the
- * physical page and returns the kaddr for the mem_map of that node.
- */
-#define LOCAL_MAP_BASE(page) \
-			NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(page)))
-
-/*
  * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
  * and returns the the mem_map of that node.
  */
@@ -77,6 +65,18 @@
  * node's mem_map.
  */
 #define LOCAL_BASE_ADDR(kaddr)	((unsigned long)(kaddr) & ~(NODE_MAX_MEM_SIZE-1))
+
+#define LOCAL_MAP_NR(kvaddr) \
+	(((unsigned long)(kvaddr)-LOCAL_BASE_ADDR((kvaddr))) >> PAGE_SHIFT)
+
+#define MAP_NR(kaddr)	(((unsigned long)(kaddr) > (unsigned long)high_memory)\
+		? (max_mapnr + 1) : (LOCAL_MAP_NR((kaddr)) + \
+		(((unsigned long)ADDR_TO_MAPBASE((kaddr)) - PAGE_OFFSET) / \
+		sizeof(mem_map_t))))
+
+#define kern_addr_valid(addr)	((KVADDR_TO_NID((unsigned long)addr) > \
+	-1) ? 0 : (test_bit(LOCAL_MAP_NR((addr)), \
+	NODE_DATA(KVADDR_TO_NID((unsigned long)addr))->valid_addr_bitmap)))
 
 #endif /* CONFIG_DISCONTIGMEM */
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/namei.h linux/include/asm-mips64/namei.h
--- v2.3.99-pre8/linux/include/asm-mips64/namei.h	Tue Apr 11 15:09:23 2000
+++ linux/include/asm-mips64/namei.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: namei.h,v 1.1 1999/08/20 21:59:08 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ng1.h linux/include/asm-mips64/ng1.h
--- v2.3.99-pre8/linux/include/asm-mips64/ng1.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ng1.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ng1.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/offset.h linux/include/asm-mips64/offset.h
--- v2.3.99-pre8/linux/include/asm-mips64/offset.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/offset.h	Sat May 13 08:31:25 2000
@@ -52,7 +52,8 @@
 #define TASK_COUNTER       56
 #define TASK_PRIORITY      64
 #define TASK_MM            80
-#define TASK_STRUCT_SIZE   1480
+#define TASK_PROCESSOR     100
+#define TASK_STRUCT_SIZE   1432
 
 /* MIPS specific thread_struct offsets. */
 #define THREAD_REG16   896
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/paccess.h linux/include/asm-mips64/paccess.h
--- v2.3.99-pre8/linux/include/asm-mips64/paccess.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/paccess.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: paccess.h,v 1.3 2000/02/04 07:40:53 ralf Exp $
+/* $Id: paccess.h,v 1.2 2000/01/21 22:34:07 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/param.h linux/include/asm-mips64/param.h
--- v2.3.99-pre8/linux/include/asm-mips64/param.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/param.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: param.h,v 1.2 2000/01/19 02:08:47 ralf Exp $
+/* $Id: param.h,v 1.1 1999/08/18 23:37:51 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/parport.h linux/include/asm-mips64/parport.h
--- v2.3.99-pre8/linux/include/asm-mips64/parport.h	Tue Mar 14 19:10:40 2000
+++ linux/include/asm-mips64/parport.h	Sat May 13 08:31:25 2000
@@ -1,13 +1,11 @@
-/* $Id: parport.h,v 1.2 2000/02/18 00:24:48 ralf Exp $
- *
- * parport.h: ia32-specific parport initialisation
+/* $Id$
  *
  * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
  *
  * This file should only be included by drivers/parport/parport_pc.c.
  */
 #ifndef _ASM_PARPORT_H
-#define _ASM_PARPORT_H 1
+#define _ASM_PARPORT_H
 
 static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
 static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
@@ -15,4 +13,4 @@
 	return parport_pc_find_isa_ports (autoirq, autodma);
 }
 
-#endif /* !(_ASM_PARPORT_H) */
+#endif /* _ASM_PARPORT_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/pci/bridge.h linux/include/asm-mips64/pci/bridge.h
--- v2.3.99-pre8/linux/include/asm-mips64/pci/bridge.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/pci/bridge.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: bridge.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
@@ -827,5 +827,12 @@
 				(attr)
 
 #define BRIDGE_INTERNAL_ATES	128
+
+/* ========================================================================
+ *    Linux pci bus mappings to sn physical id's
+ */
+unsigned char bus_to_wid[256];	/* widget id for linux pci bus */
+unsigned char bus_to_nid[256];	/* nasid for linux pci bus */
+unsigned char num_bridges;	/* number of bridges in the system */
 
 #endif /* _ASM_PCI_BRIDGE_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/pgalloc.h linux/include/asm-mips64/pgalloc.h
--- v2.3.99-pre8/linux/include/asm-mips64/pgalloc.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips64/pgalloc.h	Mon May 15 12:10:26 2000
@@ -18,6 +18,7 @@
  *  - flush_tlb_mm(mm) flushes the specified mm context TLB entries
  *  - flush_tlb_page(mm, vmaddr) flushes a single page
  *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
  */
 extern void (*_flush_tlb_all)(void);
 extern void (*_flush_tlb_mm)(struct mm_struct *mm);
@@ -25,11 +26,22 @@
 			       unsigned long end);
 extern void (*_flush_tlb_page)(struct vm_area_struct *vma, unsigned long page);
 
+#ifndef CONFIG_SMP
+
 #define flush_tlb_all()			_flush_tlb_all()
 #define flush_tlb_mm(mm)		_flush_tlb_mm(mm)
 #define flush_tlb_range(mm,vmaddr,end)	_flush_tlb_range(mm, vmaddr, end)
 #define flush_tlb_page(vma,page)	_flush_tlb_page(vma, page)
 
+#else /* CONFIG_SMP */
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *);
+extern void flush_tlb_range(struct mm_struct *, unsigned long, unsigned long);
+extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
+
+#endif /* CONFIG_SMP */
+
 extern inline void flush_tlb_pgtables(struct mm_struct *mm,
                                       unsigned long start, unsigned long end)
 {
@@ -111,8 +123,8 @@
 {
 	unsigned long *ret;
 
-	if ((ret = (unsigned long *)pte_quicklist) != NULL) {
-		pte_quicklist = (unsigned long *)(*ret);
+	if ((ret = (unsigned long *)pmd_quicklist) != NULL) {
+		pmd_quicklist = (unsigned long *)(*ret);
 		ret[0] = ret[1];
 		pgtable_cache_size--;
 		return (pmd_t *)ret;
@@ -123,8 +135,8 @@
 
 extern inline void free_pmd_fast(pmd_t *pmd)
 {
-	*(unsigned long *)pmd = (unsigned long) pte_quicklist;
-	pte_quicklist = (unsigned long *) pmd;
+	*(unsigned long *)pmd = (unsigned long) pmd_quicklist;
+	pmd_quicklist = (unsigned long *) pmd;
 	pgtable_cache_size++;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/pgtable.h linux/include/asm-mips64/pgtable.h
--- v2.3.99-pre8/linux/include/asm-mips64/pgtable.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/pgtable.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.12 2000/02/24 00:13:20 ralf Exp $
+/* $Id: pgtable.h,v 1.14 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
@@ -72,6 +72,7 @@
 #define PTRS_PER_PMD	1024
 #define PTRS_PER_PTE	512
 #define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
+#define FIRST_USER_PGD_NR	0
 
 #define VMALLOC_START     XKSEG
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
@@ -123,15 +124,15 @@
 
 #define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_MODIFIED | _CACHE_MASK)
 
-#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT)
+#define PAGE_NONE	__pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_COW)
 #define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			_CACHE_CACHABLE_COW)
 #define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_READ | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			_CACHE_CACHABLE_COW)
 #define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_READ | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			_CACHE_CACHABLE_COW)
 #define PAGE_KERNEL	__pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
-			_CACHE_CACHABLE_NONCOHERENT)
+			_CACHE_CACHABLE_COW)
 #define PAGE_USERIO     __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
 			_CACHE_UNCACHED)
 #define PAGE_KERNEL_UNCACHED __pgprot(_PAGE_PRESENT | __READABLE | __WRITEABLE | \
@@ -204,7 +205,7 @@
 #define PAGE_PTR(address) \
 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
 
-extern pte_t invalid_pte_table[PAGE_SIZE/sizeof(pte_t)];
+extern pte_t invalid_pte_table[2*PAGE_SIZE/sizeof(pte_t)];
 extern pmd_t invalid_pmd_table[2*PAGE_SIZE/sizeof(pmd_t)];
 
 /*
@@ -411,8 +412,8 @@
 #define PAGE_TO_PA(page)	((page - mem_map) << PAGE_SHIFT)
 #else
 #define PAGE_TO_PA(page) \
-		((((page)-(page)->zone->zone_pgdat->node_mem_map) << PAGE_SHIFT) \
-		+ ((PAGE_TO_PLAT_NODE(page))->physstart))
+		((((page)-(page)->zone->zone_mem_map) << PAGE_SHIFT) \
+		+ ((page)->zone->zone_start_paddr))
 #endif
 #define mk_pte(page, pgprot)						\
 ({									\
@@ -469,6 +470,7 @@
 extern void pmd_init(unsigned long page);
 
 extern pgd_t swapper_pg_dir[1024];
+extern void paging_init(void);
 
 extern void (*update_mmu_cache)(struct vm_area_struct *vma,
 				unsigned long address, pte_t pte);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/poll.h linux/include/asm-mips64/poll.h
--- v2.3.99-pre8/linux/include/asm-mips64/poll.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/poll.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: poll.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/posix_types.h linux/include/asm-mips64/posix_types.h
--- v2.3.99-pre8/linux/include/asm-mips64/posix_types.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/posix_types.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: posix_types.h,v 1.4 2000/02/16 01:07:49 ralf Exp $
+/* $Id: posix_types.h,v 1.5 2000/02/29 20:49:16 ulfc 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
@@ -48,6 +48,26 @@
 typedef struct {
         int    val[2];
 } __kernel_fsid_t;
+
+/* Now 32bit compatibility types */
+typedef unsigned int	__kernel_dev_t32;
+typedef unsigned int	__kernel_ino_t32;
+typedef unsigned int	__kernel_mode_t32;
+typedef unsigned int	__kernel_nlink_t32;
+typedef int		__kernel_off_t32;
+typedef int		__kernel_pid_t32;
+typedef int		__kernel_ipc_pid_t32;
+typedef int		__kernel_uid_t32;
+typedef int		__kernel_gid_t32;
+typedef unsigned int	__kernel_size_t32;
+typedef int		__kernel_ssize_t32;
+typedef int		__kernel_ptrdiff_t32;
+typedef int		__kernel_time_t32;
+typedef int		__kernel_suseconds_t32;
+typedef int		__kernel_clock_t32;
+typedef int		__kernel_daddr_t32;
+typedef char *		__kernel_caddr_t32;
+typedef __kernel_fsid_t	__kernel_fsid_t32;
 
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/processor.h linux/include/asm-mips64/processor.h
--- v2.3.99-pre8/linux/include/asm-mips64/processor.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-mips64/processor.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.10 2000/02/24 00:13:20 ralf Exp $
+/* $Id: processor.h,v 1.11 2000/03/14 01:39:27 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
@@ -12,26 +12,41 @@
 #ifndef _ASM_PROCESSOR_H
 #define _ASM_PROCESSOR_H
 
+#include <linux/config.h>
+
 /*
  * Default implementation of macro that returns current
  * instruction pointer ("program counter").
  */
 #define current_text_addr() ({ __label__ _l; _l: &&_l;})
 
-#include <linux/config.h>
 #if !defined (_LANGUAGE_ASSEMBLY)
 #include <asm/cachectl.h>
 #include <asm/mipsregs.h>
 #include <asm/reg.h>
 #include <asm/system.h>
 
-struct mips_cpuinfo {
+#if (defined(CONFIG_SGI_IP27))
+#include <asm/sn/types.h>
+#include <asm/sn/intr_public.h>
+#endif
+
+struct cpuinfo_mips {
 	unsigned long udelay_val;
 	unsigned long *pgd_quick;
 	unsigned long *pmd_quick;
 	unsigned long *pte_quick;
 	unsigned long pgtable_cache_sz;
-};
+	unsigned long last_asn;
+	unsigned int irq_count, bh_count;
+	unsigned long asid_cache;
+#if defined(CONFIG_SGI_IP27)
+	cnodeid_t	p_nodeid;	/* my node ID in compact-id-space */
+	nasid_t		p_nasid;	/* my node ID in numa-as-id-space */
+	unsigned char	p_slice;	/* Physical position on node board */
+	hub_intmasks_t	p_intmasks;	/* SN0 per-CPU interrupt masks */
+#endif
+} __attribute__((aligned(128)));
 
 /*
  * System setup and hardware flags..
@@ -43,15 +58,13 @@
 extern char vce_available;		/* Supports VCED / VCEI exceptions */
 extern char mips4_available;		/* CPU has MIPS IV ISA or better */
 
-extern struct mips_cpuinfo boot_cpu_data;
 extern unsigned int vced_count, vcei_count;
+extern struct cpuinfo_mips cpu_data[];
 
 #ifdef CONFIG_SMP
-extern struct mips_cpuinfo cpu_data[];
 #define current_cpu_data cpu_data[smp_processor_id()]
 #else
-#define cpu_data &boot_cpu_data
-#define current_cpu_data boot_cpu_data
+#define current_cpu_data cpu_data[0]
 #endif
 
 /*
@@ -74,6 +87,14 @@
 /* Lazy FPU handling on uni-processor */
 extern struct task_struct *last_task_used_math;
 
+#ifndef CONFIG_SMP
+#define IS_FPU_OWNER()		(last_task_used_math == current)
+#define CLEAR_FPU_OWNER()	last_task_used_math = NULL;
+#else
+#define IS_FPU_OWNER()		(current->flags & PF_USEDFPU)
+#define CLEAR_FPU_OWNER()	current->flags &= ~PF_USEDFPU;
+#endif
+
 /*
  * User space process size: 1TB. This is hardcoded into a few places,
  * so don't change it unless you know what you are doing.  TASK_SIZE
@@ -215,13 +236,19 @@
 /*
  * Do necessary setup to start up a newly executed thread.
  */
-#define start_thread(regs, new_pc, new_sp) do {				\
+#define start_thread(regs, pc, sp) 					\
+do {									\
+	unsigned long __status;						\
+									\
 	/* New thread looses kernel privileges. */			\
-	regs->cp0_status = (regs->cp0_status & ~(ST0_CU0|ST0_KSU)) | KSU_USER;\
-	regs->cp0_epc = new_pc;						\
-	regs->regs[29] = new_sp;					\
+	__status = regs->cp0_status & ~(ST0_CU0|ST0_FR|ST0_KSU);	\
+	__status |= KSU_USER;						\
+	__status |= (current->thread.mflags & MF_32BIT) ? 0 : ST0_FR;	\
+	regs->cp0_status = __status;					\
+	regs->cp0_epc = pc;						\
+	regs->regs[29] = sp;						\
 	current->thread.current_ds = USER_DS;				\
-} while (0)
+} while(0)
 
 unsigned long get_wchan(struct task_struct *p);
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ptrace.h linux/include/asm-mips64/ptrace.h
--- v2.3.99-pre8/linux/include/asm-mips64/ptrace.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ptrace.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ptrace.h,v 1.4 2000/02/24 00:13:20 ralf Exp $
+/* $Id: ptrace.h,v 1.3 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/r10kcache.h linux/include/asm-mips64/r10kcache.h
--- v2.3.99-pre8/linux/include/asm-mips64/r10kcache.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/r10kcache.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: r10kcache.h,v 1.2 2000/01/17 23:32:47 ralf Exp $
+/* $Id: r10kcache.h,v 1.1 2000/01/16 01:27:14 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/r10kcacheops.h linux/include/asm-mips64/r10kcacheops.h
--- v2.3.99-pre8/linux/include/asm-mips64/r10kcacheops.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/r10kcacheops.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: r10kcacheops.h,v 1.1 2000/01/16 01:27:14 ralf Exp $
+/* $Id: r10kcacheops.h,v 1.1 2000/01/12 23:18:32 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/r4kcache.h linux/include/asm-mips64/r4kcache.h
--- v2.3.99-pre8/linux/include/asm-mips64/r4kcache.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/r4kcache.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: r4kcache.h,v 1.2 2000/01/17 23:32:47 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/r4kcacheops.h linux/include/asm-mips64/r4kcacheops.h
--- v2.3.99-pre8/linux/include/asm-mips64/r4kcacheops.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/r4kcacheops.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: r4kcacheops.h,v 1.1 2000/01/17 23:32:47 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/regdef.h linux/include/asm-mips64/regdef.h
--- v2.3.99-pre8/linux/include/asm-mips64/regdef.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/regdef.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: regdef.h,v 1.1 1999/08/20 21:59:08 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/resource.h linux/include/asm-mips64/resource.h
--- v2.3.99-pre8/linux/include/asm-mips64/resource.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/resource.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: resource.h,v 1.4 2000/02/04 07:40:53 ralf Exp $
+/* $Id: resource.h,v 1.3 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/semaphore-helper.h linux/include/asm-mips64/semaphore-helper.h
--- v2.3.99-pre8/linux/include/asm-mips64/semaphore-helper.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/semaphore-helper.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: semaphore-helper.h,v 1.3 1999/12/04 03:59:12 ralf Exp $
+/* $Id: semaphore-helper.h,v 1.2 1999/10/20 18:10:32 ralf Exp $
  *
  * SMP- and interrupt-safe semaphores helper functions.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/semaphore.h linux/include/asm-mips64/semaphore.h
--- v2.3.99-pre8/linux/include/asm-mips64/semaphore.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/semaphore.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: semaphore.h,v 1.6 2000/02/24 03:09:52 ulfc Exp $
+/* $Id: semaphore.h,v 1.5 2000/02/18 00:24:49 ralf Exp $
  *
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/serial.h linux/include/asm-mips64/serial.h
--- v2.3.99-pre8/linux/include/asm-mips64/serial.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/serial.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: serial.h,v 1.3 2000/02/04 07:40:53 ralf Exp $
+/* $Id: serial.h,v 1.2 2000/01/17 23:32:47 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgi/io.h linux/include/asm-mips64/sgi/io.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgi/io.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgi/io.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.1 2000/02/04 07:40:53 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgi/sgi.h linux/include/asm-mips64/sgi/sgi.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgi/sgi.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgi/sgi.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgi.h,v 1.2 1999/12/04 03:59:13 ralf Exp $
+/* $Id: sgi.h,v 1.1 1999/08/20 21:13: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgi/sgihpc.h linux/include/asm-mips64/sgi/sgihpc.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgi/sgihpc.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgi/sgihpc.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgihpc.h,v 1.2 1999/12/04 03:59:13 ralf Exp $
+/* $Id: sgihpc.h,v 1.2 1999/10/19 20:51:54 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgi/sgimc.h linux/include/asm-mips64/sgi/sgimc.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgi/sgimc.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgi/sgimc.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgimc.h,v 1.2 1999/12/04 03:59:13 ralf Exp $
+/* $Id: sgimc.h,v 1.2 1999/10/19 20:51:54 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgi/sgint23.h linux/include/asm-mips64/sgi/sgint23.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgi/sgint23.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgi/sgint23.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgint23.h,v 1.2 1999/12/04 03:59:13 ralf Exp $
+/* $Id: sgint23.h,v 1.3 1999/10/20 18:10:32 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgialib.h linux/include/asm-mips64/sgialib.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgialib.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgialib.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgialib.h,v 1.4 2000/01/17 23:32:47 ralf Exp $
+/* $Id: sgialib.h,v 1.3 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgiarcs.h linux/include/asm-mips64/sgiarcs.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgiarcs.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgiarcs.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgiarcs.h,v 1.5 2000/01/17 23:32:47 ralf Exp $
+/* $Id: sgiarcs.h,v 1.4 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sgidefs.h linux/include/asm-mips64/sgidefs.h
--- v2.3.99-pre8/linux/include/asm-mips64/sgidefs.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sgidefs.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sgidefs.h,v 1.2 1999/08/20 21:59:08 ralf Exp $
+/* $Id: sgidefs.h,v 1.1 1999/08/18 23:37: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/shmiq.h linux/include/asm-mips64/shmiq.h
--- v2.3.99-pre8/linux/include/asm-mips64/shmiq.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/shmiq.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: shmiq.h,v 1.1 1999/08/19 22:56:34 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/shmparam.h linux/include/asm-mips64/shmparam.h
--- v2.3.99-pre8/linux/include/asm-mips64/shmparam.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/shmparam.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: shmparam.h,v 1.2 2000/01/29 01:42:28 ralf Exp $
+/* $Id: shmparam.h,v 1.1 1999/08/19 22:56:35 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sigcontext.h linux/include/asm-mips64/sigcontext.h
--- v2.3.99-pre8/linux/include/asm-mips64/sigcontext.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sigcontext.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sigcontext.h,v 1.2 1999/09/28 22:27:19 ralf Exp $
+/* $Id: sigcontext.h,v 1.2 1999/09/27 16:01:40 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/siginfo.h linux/include/asm-mips64/siginfo.h
--- v2.3.99-pre8/linux/include/asm-mips64/siginfo.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/siginfo.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.3 2000/02/18 00:24:49 ralf Exp $
+/* $Id: siginfo.h,v 1.2 2000/01/27 01:05: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/signal.h linux/include/asm-mips64/signal.h
--- v2.3.99-pre8/linux/include/asm-mips64/signal.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/signal.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: signal.h,v 1.2 1999/09/28 22:27:19 ralf Exp $
+/* $Id: signal.h,v 1.2 1999/09/27 16:01:40 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
@@ -21,6 +21,7 @@
 } sigset_t;
 
 typedef unsigned long old_sigset_t;		/* at least 32 bits */
+typedef unsigned int old_sigset_t32;
 
 #define SIGHUP		 1	/* Hangup (POSIX).  */
 #define SIGINT		 2	/* Interrupt (ANSI).  */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/smp.h linux/include/asm-mips64/smp.h
--- v2.3.99-pre8/linux/include/asm-mips64/smp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/smp.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,49 @@
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+#if 0
+struct cpuinfo_mips {				/* XXX  */
+	unsigned long loops_per_sec;
+	unsigned long last_asn;
+	unsigned long *pgd_cache;
+	unsigned long *pte_cache;
+	unsigned long pgtable_cache_sz;
+	unsigned long ipi_count;
+	unsigned long irq_attempt[NR_IRQS];
+	unsigned long smp_local_irq_count;
+	unsigned long prof_multiplier;
+	unsigned long prof_counter;
+	int irq_count, bh_count;
+} __attribute__((aligned(64)));
+
+extern struct cpuinfo_mips cpu_data[NR_CPUS];
+#endif
+
+#define smp_processor_id()	(current->processor)
+
+#define PROC_CHANGE_PENALTY	20
+
+/* Map from cpu id to sequential logical cpu number.  This will only
+   not be idempotent when cpus failed to come on-line.  */
+extern int __cpu_number_map[NR_CPUS];
+#define cpu_number_map(cpu)  __cpu_number_map[cpu]
+
+/* The reverse map from sequential logical cpu number to cpu id.  */
+extern int __cpu_logical_map[NR_CPUS];
+#define cpu_logical_map(cpu)  __cpu_logical_map[cpu]
+
+/* Good enough for toy^Wupto 64 CPU Origins.  */
+extern unsigned long cpu_present_mask;
+
+#endif
+
+#define NO_PROC_ID	(-1)
+
+#endif __ASM_SMP_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/smplock.h linux/include/asm-mips64/smplock.h
--- v2.3.99-pre8/linux/include/asm-mips64/smplock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/smplock.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,56 @@
+/*
+ * <asm/smplock.h>
+ *
+ * Default SMP lock implementation
+ */
+#ifndef _ASM_SMPLOCK_H
+#define _ASM_SMPLOCK_H
+
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+extern spinlock_t kernel_flag;
+
+#define kernel_locked()			spin_is_locked(&kernel_flag)
+
+/*
+ * Release global kernel lock and global interrupt lock
+ */
+static __inline__ void release_kernel_lock(struct task_struct *task, int cpu)
+{
+	if (task->lock_depth >= 0)
+		spin_unlock(&kernel_flag);
+	release_irqlock(cpu);
+	__sti();
+}
+
+/*
+ * Re-acquire the kernel lock
+ */
+static __inline__ void reacquire_kernel_lock(struct task_struct *task)
+{
+	if (task->lock_depth >= 0)
+		spin_lock(&kernel_flag);
+}
+
+/*
+ * Getting the big kernel lock.
+ *
+ * This cannot happen asynchronously,
+ * so we only need to worry about other
+ * CPU's.
+ */
+static __inline__ void lock_kernel(void)
+{
+	if (!++current->lock_depth)
+		spin_lock(&kernel_flag);
+}
+
+static __inline__ void unlock_kernel(void)
+{
+	if (--current->lock_depth < 0)
+		spin_unlock(&kernel_flag);
+}
+
+#endif /* _ASM_SMPLOCK_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/addrs.h linux/include/asm-mips64/sn/addrs.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/addrs.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/addrs.h	Mon May 15 12:10:26 2000
@@ -1,17 +1,16 @@
-/* $Id: addrs.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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.
  *
- * Derived from IRIX <sys/SN/addrs.h>.
- *
  * Copyright (C) 1992 - 1997, 1999 Silicon Graphics, Inc.
  * Copyright (C) 1999 by Ralf Baechle
  */
 #ifndef _ASM_SN_ADDRS_H
 #define _ASM_SN_ADDRS_H
 
+#include <linux/config.h>
 #if _LANGUAGE_C
 #include <linux/types.h>
 #endif /* _LANGUAGE_C */
@@ -20,10 +19,23 @@
 #include <asm/reg.h>
 #include <asm/sn/kldir.h>
 
+#if defined(CONFIG_SGI_IP27)
+#include <asm/sn/sn0/addrs.h>
+#elif defined(CONFIG_SGI_IP35)
+#include <asm/sn/sn1/addrs.h>
+#endif
+
+
 #if _LANGUAGE_C
 
+#if defined(CONFIG_SGI_IO)	/* FIXME */
+#define PS_UINT_CAST		(__psunsigned_t)
+#define UINT64_CAST		(__uint64_t)
+#else	/* CONFIG_SGI_IO */
 #define PS_UINT_CAST		(unsigned long)
 #define UINT64_CAST		(unsigned long)
+#endif	/* CONFIG_SGI_IO */
+
 #define HUBREG_CAST		(volatile hubreg_t *)
 
 #elif _LANGUAGE_ASSEMBLY
@@ -36,7 +48,9 @@
 
 
 #define NASID_GET_META(_n)	((_n) >> NASID_LOCAL_BITS)
+#ifdef CONFIG_SGI_IP27
 #define NASID_GET_LOCAL(_n)	((_n) & 0xf)
+#endif
 #define NASID_MAKE(_m, _l)	(((_m) << NASID_LOCAL_BITS) | (_l))
 
 #define NODE_ADDRSPACE_MASK	(NODE_ADDRSPACE_SIZE - 1)
@@ -128,6 +142,7 @@
  * The bottom of ualias space is flipped depending on whether you're
  * processor 0 or 1 within a node.
  */
+#ifdef CONFIG_SGI_IP27
 #define UALIAS_FLIP_BASE	UALIAS_BASE
 #define UALIAS_FLIP_SIZE	0x20000
 #define UALIAS_FLIP_BIT		0x10000
@@ -137,6 +152,9 @@
 #define LBOOT_BASE		(HSPEC_BASE + 0x10000000)
 #define LBOOT_SIZE		0x10000000
 #define LBOOT_LIMIT		(LBOOT_BASE + LBOOT_SIZE)
+#define LBOOT_STRIDE		0		/* IP27 has only one CPU PROM */
+
+#endif
 
 #define	HUB_REGISTER_WIDGET	1
 #define IALIAS_BASE		NODE_SWIN_BASE(0, HUB_REGISTER_WIDGET)
@@ -147,10 +165,14 @@
 /*
  * Macro for referring to Hub's RBOOT space
  */
+
+#ifdef CONFIG_SGI_IP27
 #define RBOOT_SIZE		0x10000000	/* 256 Megabytes */
 #define NODE_RBOOT_BASE(_n)	(NODE_HSPEC_BASE(_n) + 0x30000000)
 #define NODE_RBOOT_LIMIT(_n)	(NODE_RBOOT_BASE(_n) + RBOOT_SIZE)
 
+#endif
+
 /*
  * Macros for referring the Hub's back door space
  *
@@ -162,14 +184,18 @@
  *   BDDIR_ENTRY_HI returns the address of the high double-word of the entry.
  *   BDPRT_ENTRY    returns the address of the double-word protection entry
  *                  corresponding to the page containing the physical address.
+ *   BDPRT_ENTRY_S  Stores the value into the protection entry.
+ *   BDPRT_ENTRY_L  Load the value from the protection entry.
  *   BDECC_ENTRY    returns the address of the ECC byte corresponding to a
  *                  double-word at a specified physical address.
+ *   BDECC_ENTRY_H  returns the address of the two ECC bytes corresponding to a
+ *                  quad-word at a specified physical address.
  */
 #define NODE_BDOOR_BASE(_n)	(NODE_HSPEC_BASE(_n) + (NODE_ADDRSPACE_SIZE/2))
 
 #define NODE_BDECC_BASE(_n)	(NODE_BDOOR_BASE(_n))
 #define NODE_BDDIR_BASE(_n)	(NODE_BDOOR_BASE(_n) + (NODE_ADDRSPACE_SIZE/4))
-
+#ifdef CONFIG_SGI_IP27
 #define BDDIR_ENTRY_LO(_pa)	((HSPEC_BASE +				      \
 				  NODE_ADDRSPACE_SIZE * 3 / 4 +		      \
 				  0x200)				    | \
@@ -189,6 +215,9 @@
 				 UINT64_CAST (_pa)	 & NASID_MASK	    | \
 				 UINT64_CAST (_pa) >> 2 & BDDIR_UPPER_MASK  | \
 				 (_rgn) << 3)
+#define BDPRT_ENTRY_ADDR(_pa,_rgn) (BDPRT_ENTRY((_pa),(_rgn)))
+#define BDPRT_ENTRY_S(_pa,_rgn,_val) (*(__psunsigned_t *)BDPRT_ENTRY((_pa),(_rgn))=(_val))
+#define BDPRT_ENTRY_L(_pa,_rgn)	(*(__psunsigned_t *)BDPRT_ENTRY((_pa),(_rgn)))
 
 #define BDECC_ENTRY(_pa)	((HSPEC_BASE +				      \
 				  NODE_ADDRSPACE_SIZE / 2)		    | \
@@ -213,6 +242,7 @@
 #define BDECC_TO_MEM(_ba)	(UINT64_CAST  (_ba) & NASID_MASK	    | \
 				 (UINT64_CAST (_ba) & BDECC_UPPER_MASK)<<2  | \
 				 (UINT64_CAST (_ba) & 3) << 3)
+#endif /* CONFIG_SGI_IP27 */
 
 
 /*
@@ -230,7 +260,6 @@
 #define LOCAL_HUB(_x)		(HUBREG_CAST (IALIAS_BASE + (_x)))
 #define REMOTE_HUB(_n, _x)	(HUBREG_CAST (NODE_SWIN_BASE(_n, 1) +	\
 					      0x800000 + (_x)))
-
 #endif /* _STANDALONE */
 
 /*
@@ -244,6 +273,10 @@
 #define LOCAL_HUB_ADDR(_x)	(HUBREG_CAST (IALIAS_BASE + (_x)))
 #define REMOTE_HUB_ADDR(_n, _x)	(HUBREG_CAST (NODE_SWIN_BASE(_n, 1) +	\
 					      0x800000 + (_x)))
+#ifdef CONFIG_SGI_IP27
+#define REMOTE_HUB_PI_ADDR(_n, _sn, _x)	(HUBREG_CAST (NODE_SWIN_BASE(_n, 1) +	\
+					      0x800000 + (_x)))
+#endif /* CONFIG_SGI_IP27 */
 
 #if _LANGUAGE_C
 
@@ -254,6 +287,8 @@
 #define LOCAL_HUB_S(_r, _d)		HUB_S(LOCAL_HUB_ADDR(_r), (_d))
 #define REMOTE_HUB_L(_n, _r)		HUB_L(REMOTE_HUB_ADDR((_n), (_r)))
 #define REMOTE_HUB_S(_n, _r, _d)	HUB_S(REMOTE_HUB_ADDR((_n), (_r)), (_d))
+#define REMOTE_HUB_PI_L(_n, _sn, _r)	HUB_L(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r)))
+#define REMOTE_HUB_PI_S(_n, _sn, _r, _d) HUB_S(REMOTE_HUB_PI_ADDR((_n), (_sn), (_r)), (_d))
 
 #endif /* _LANGUAGE_C */
 
@@ -383,11 +418,7 @@
 /* loading symmon 4k below UNIX. the arcs loader needs the topaddr for a
  * relocatable program
  */
-#ifdef SN0XXL
-#define UNIX_DEBUG_LOADADDR     0x360000
-#else
 #define	UNIX_DEBUG_LOADADDR	0x300000
-#endif
 #define	SYMMON_LOADADDR(nasid)						\
 	TO_NODE(nasid, PHYS_TO_K0(UNIX_DEBUG_LOADADDR - 0x1000))
 
@@ -420,9 +451,9 @@
 #define	KERN_XP_ADDR(nasid)	KLD_KERN_XP(nasid)->pointer
 #define	KERN_XP_SIZE(nasid)	KLD_KERN_XP(nasid)->size
 
+#define GPDA_ADDR(nasid)	TO_NODE_CAC(nasid, GPDA_OFFSET)
+
 #endif /* _LANGUAGE_C */
 
-/* Fixme for SN1 */
-#include <asm/sn/sn0/addrs.h>
 
 #endif /* _ASM_SN_ADDRS_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/agent.h linux/include/asm-mips64/sn/agent.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/agent.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/agent.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: agent.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
@@ -12,19 +12,26 @@
 #ifndef _ASM_SGI_SN_AGENT_H
 #define _ASM_SGI_SN_AGENT_H
 
+#include <linux/config.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
-//#include <sys/SN/io.h>
+//#include <asm/sn/io.h>
 
+#if defined(CONFIG_SGI_IP27)
 #include <asm/sn/sn0/hub.h>
+#elif defined(CONFIG_SGI_IP35)
+#include <asm/sn/sn1/hub.h>
+#endif	/* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
 
 /*
  * NIC register macros
  */
 
+#if defined(CONFIG_SGI_IP27)
 #define HUB_NIC_ADDR(_cpuid) 						   \
 	REMOTE_HUB_ADDR(COMPACT_TO_NASID_NODEID(cputocnode(_cpuid)),       \
 		MD_MLAN_CTL)
+#endif
 
 #define SET_HUB_NIC(_my_cpuid, _val) 				  	   \
 	(HUB_S(HUB_NIC_ADDR(_my_cpuid), (_val)))
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/arch.h linux/include/asm-mips64/sn/arch.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/arch.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/arch.h	Sat May 13 08:31:25 2000
@@ -1,10 +1,10 @@
-/* $Id: arch.h,v 1.2 2000/02/10 07:28:35 kanoj Exp $
+/* $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.
  *
- * SGI IP27 specific setup.
+ * SGI specific setup.
  *
  * Copyright (C) 1995 - 1997, 1999 Silcon Graphics, Inc.
  * Copyright (C) 1999 Ralf Baechle (ralf@gnu.org)
@@ -13,29 +13,38 @@
 #define _ASM_SN_ARCH_H
 
 #include <linux/types.h>
+#include <linux/config.h>
 
+#if !defined(CONFIG_SGI_IO)
 #include <asm/sn/types.h>
 #include <asm/sn/sn0/arch.h>
+#endif
+
 
 #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
+#if !defined(CONFIG_SGI_IO)
 typedef u64	hubreg_t;
 typedef u64	nic_t;
 #endif
+#endif
 
+#ifdef CONFIG_SGI_IP27
 #define CPUS_PER_NODE		2	/* CPUs on a single hub */
 #define CPUS_PER_NODE_SHFT	1	/* Bits to shift in the node number */
+#define CPUS_PER_SUBNODE	2	/* CPUs on a single hub PI */
+#endif
 #define CNODE_NUM_CPUS(_cnode)		(NODEPDA(_cnode)->node_num_cpus)
+
 #define CNODE_TO_CPU_BASE(_cnode)	(NODEPDA(_cnode)->node_first_cpu)
 #define cputocnode(cpu)				\
-               (ASSERT(pdaindr[(cpu)].pda), (pdaindr[(cpu)].pda->p_nodeid))
+               (cpu_data[(cpu)].p_nodeid)
 #define cputonasid(cpu)				\
-               (ASSERT(pdaindr[(cpu)].pda), (pdaindr[(cpu)].pda->p_nasid))
+               (cpu_data[(cpu)].p_nasid)
 #define cputoslice(cpu)				\
-               (ASSERT(pdaindr[(cpu)].pda), (pdaindr[(cpu)].pda->p_slice))
+               (cpu_data[(cpu)].p_slice)
 #define makespnum(_nasid, _slice)					\
 		(((_nasid) << CPUS_PER_NODE_SHFT) | (_slice))
 
-
 #if defined(_LANGUAGE_C) || defined(_LANGUAGE_C_PLUS_PLUS)
 
 #define INVALID_NASID		(nasid_t)-1
@@ -45,6 +54,9 @@
 #define	INVALID_PARTID		(partid_t)-1
 
 extern nasid_t get_nasid(void);
+extern cnodeid_t get_cpu_cnode(int);
+extern int get_cpu_slice(cpuid_t);
+
 /*
  * NO ONE should access these arrays directly.  The only reason we refer to
  * them here is to avoid the procedure call that would be required in the
@@ -64,6 +76,12 @@
     ((nnode) >> \
      (is_fine_dirmode() ? NASID_TO_FINEREG_SHFT : NASID_TO_COARSEREG_SHFT))
 
+#if !defined(_STANDALONE)
+extern cnodeid_t nasid_to_compact_node[MAX_NASIDS];
+extern nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
+extern cnodeid_t cpuid_to_compact_node[MAXCPUS];
+#endif
+
 #if !defined(DEBUG) && (!defined(SABLE) || defined(_STANDALONE))
 
 #define NASID_TO_COMPACT_NODEID(nnode)	(nasid_to_compact_node[nnode])
@@ -90,13 +108,8 @@
 #define SLOT_BITMASK    	(MAX_MEM_SLOTS - 1)
 #define SLOT_SIZE		(1LL<<SLOT_SHIFT)
 
-#if SABLE
-#define node_getnumslots(node)	(1)
-#define	NODE_MAX_MEM_SIZE	SLOT_SIZE * 1
-#else
 #define node_getnumslots(node)	(MAX_MEM_SLOTS)
 #define NODE_MAX_MEM_SIZE	SLOT_SIZE * MAX_MEM_SLOTS
-#endif /* SABLE */
 
 /*
  * New stuff in here from Irix sys/pfdat.h.
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/gda.h linux/include/asm-mips64/sn/gda.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/gda.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/gda.h	Sat May 13 08:31:25 2000
@@ -1,23 +1,19 @@
-/**************************************************************************
- *                                                                        *
- *               Copyright (C) 1992-1997, Silicon Graphics, Inc.          *
- *                                                                        *
- *  These coded instructions, statements, and computer programs  contain  *
- *  unpublished  proprietary  information of Silicon Graphics, Inc., and  *
- *  are protected by Federal copyright law.  They  may  not be disclosed  *
- *  to  third  parties  or copied or duplicated in any form, in whole or  *
- *  in part, without the prior written consent of Silicon Graphics, Inc.  *
- *                                                                        *
- **************************************************************************/
-
-/*
+/* $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.
+ *
+ * Derived from IRIX <sys/SN/gda.h>.
+ *
+ * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
+ *
  * gda.h -- Contains the data structure for the global data area,
  * 	The GDA contains information communicated between the
  *	PROM, SYMMON, and the kernel. 
  */
-
-#ifndef __SYS_SN_GDA_H__
-#define __SYS_SN_GDA_H__
+#ifndef _ASM_SN_GDA_H
+#define _ASM_SN_GDA_H
 
 #include <asm/sn/addrs.h>
 
@@ -109,4 +105,4 @@
 #define PROMOP_BIST1		0x0800		/* keep track of which BIST ran */
 #define PROMOP_BIST2		0x1000		/* keep track of which BIST ran */
 
-#endif /* __SYS_SN_GDA_H__ */
+#endif /* _ASM_SN_GDA_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/intr.h linux/include/asm-mips64/sn/intr.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/intr.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/sn/intr.h	Mon May 15 12:55:26 2000
@@ -0,0 +1,122 @@
+/*
+ * 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) 1992 - 1997 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_SN_INTR_H
+#define __ASM_SN_INTR_H
+
+/* Number of interrupt levels associated with each interrupt register. */
+#define N_INTPEND_BITS		64
+
+#define INT_PEND0_BASELVL	0
+#define INT_PEND1_BASELVL	64
+
+#define	N_INTPENDJUNK_BITS	8
+#define	INTPENDJUNK_CLRBIT	0x80
+
+#include <asm/sn/intr_public.h>
+
+#if _LANGUAGE_C
+
+/*
+ * Macros to manipulate the interrupt register on the calling hub chip.
+ */
+
+#define LOCAL_HUB_SEND_INTR(_level)	LOCAL_HUB_S(PI_INT_PEND_MOD, \
+						    (0x100|(_level)))
+#define REMOTE_HUB_SEND_INTR(_hub, _level) \
+		REMOTE_HUB_S((_hub), PI_INT_PEND_MOD, (0x100|(_level)))
+
+/*
+ * When clearing the interrupt, make sure this clear does make it 
+ * to the hub. Otherwise we could end up losing interrupts.
+ * We do an uncached load of the int_pend0 register to ensure this.
+ */
+
+#define LOCAL_HUB_CLR_INTR(_level)	  \
+                LOCAL_HUB_S(PI_INT_PEND_MOD, (_level)),	\
+                LOCAL_HUB_L(PI_INT_PEND0)
+#define REMOTE_HUB_CLR_INTR(_hub, _level) \
+		REMOTE_HUB_S((_hub), PI_INT_PEND_MOD, (_level)),	\
+                REMOTE_HUB_L((_hub), PI_INT_PEND0)
+
+#else /* LANGUAGE_ASSEMBLY */
+
+#endif /* LANGUAGE_C */
+
+/*
+ * Hard-coded interrupt levels:
+ */
+
+/*
+ *	L0 = SW1
+ *	L1 = SW2
+ *	L2 = INT_PEND0
+ *	L3 = INT_PEND1
+ *	L4 = RTC
+ *	L5 = Profiling Timer
+ *	L6 = Hub Errors
+ *	L7 = Count/Compare (T5 counters)
+ */
+
+
+/* INT_PEND0 hard-coded bits. */
+#ifdef SABLE
+#define SDISK_INTR	63
+#endif
+#ifdef DEBUG_INTR_TSTAMP
+/* hard coded interrupt level for interrupt latency test interrupt */
+#define	CPU_INTRLAT_B	62
+#define	CPU_INTRLAT_A	61
+#endif
+
+/* Hardcoded bits required by software. */
+#define MSC_MESG_INTR	13
+#define CPU_ACTION_B	11
+#define CPU_ACTION_A	10
+
+/* These are determined by hardware: */
+#define CC_PEND_B	6
+#define CC_PEND_A	5
+#define UART_INTR	4
+#define PG_MIG_INTR	3
+#define GFX_INTR_B	2
+#define GFX_INTR_A	1
+#define RESERVED_INTR	0
+
+/* INT_PEND1 hard-coded bits: */
+#define MSC_PANIC_INTR	63
+#define NI_ERROR_INTR	62
+#define MD_COR_ERR_INTR	61
+#define COR_ERR_INTR_B	60
+#define COR_ERR_INTR_A	59
+#define CLK_ERR_INTR	58
+#define IO_ERROR_INTR	57	/* set up by prom */
+
+#define	DEBUG_INTR_B	55	/* used by symmon to stop all cpus */
+#define	DEBUG_INTR_A	54
+
+#define BRIDGE_ERROR_INTR 53	/* Setup by PROM to catch Bridge Errors */
+
+#define IP27_INTR_0	52	/* Reserved for PROM use */
+#define IP27_INTR_1	51	/*   (do not use in Kernel) */
+#define IP27_INTR_2	50
+#define IP27_INTR_3	49
+#define IP27_INTR_4	48
+#define IP27_INTR_5	47
+#define IP27_INTR_6	46
+#define IP27_INTR_7	45
+
+#define	TLB_INTR_B	44	/* used for tlb flush random */
+#define	TLB_INTR_A	43
+
+#define LLP_PFAIL_INTR_B 42	/* see ml/SN/SN0/sysctlr.c */
+#define LLP_PFAIL_INTR_A 41
+
+#define NI_BRDCAST_ERR_B 40
+#define NI_BRDCAST_ERR_A 39
+
+#endif /* __ASM_SN_INTR_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/intr_public.h linux/include/asm-mips64/sn/intr_public.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/intr_public.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/sn/intr_public.h	Mon May 15 12:55:26 2000
@@ -0,0 +1,53 @@
+/* 
+ * 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) 1992 - 1997 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_SN_INTR_PUBLIC_H
+#define __ASM_SN_INTR_PUBLIC_H
+
+
+/* REMEMBER: If you change these, the whole world needs to be recompiled.
+ * It would also require changing the hubspl.s code and SN0/intr.c
+ * Currently, the spl code has no support for multiple INTPEND1 masks.
+ */
+
+#define	N_INTPEND0_MASKS	1
+#define	N_INTPEND1_MASKS	1
+
+#define INTPEND0_MAXMASK	(N_INTPEND0_MASKS - 1)
+#define INTPEND1_MAXMASK	(N_INTPEND1_MASKS - 1)
+
+#if _LANGUAGE_C
+#include <asm/sn/arch.h>
+
+struct intr_vecblk_s;	/* defined in asm/sn/intr.h */
+
+/*
+ * The following are necessary to create the illusion of a CEL
+ * on the SN0 hub.  We'll add more priority levels soon, but for
+ * now, any interrupt in a particular band effectively does an spl.
+ * These must be in the PDA since they're different for each processor.
+ * Users of this structure must hold the vector_lock in the appropriate vector
+ * block before modifying the mask arrays.  There's only one vector block
+ * for each Hub so a lock in the PDA wouldn't be adequate.
+ */
+typedef struct hub_intmasks_s {
+	/*
+	 * The masks are stored with the lowest-priority (most inclusive)
+	 * in the lowest-numbered masks (i.e., 0, 1, 2...).
+	 */
+	/* INT_PEND0: */
+	hubreg_t		intpend0_masks[N_INTPEND0_MASKS]; 
+	/* INT_PEND1: */
+	hubreg_t		intpend1_masks[N_INTPEND1_MASKS];
+	/* INT_PEND0: */
+	struct intr_vecblk_s	*dispatch0;	
+	/* INT_PEND1: */
+	struct intr_vecblk_s	*dispatch1;
+} hub_intmasks_t;
+
+#endif /* _LANGUAGE_C */
+#endif /* __ASM_SN_INTR_PUBLIC_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/io.h linux/include/asm-mips64/sn/io.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/io.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/io.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,5 @@
-/* $Id: io.h,v 1.1 2000/02/04 07:40:53 ralf Exp $
+
+/* $Id: io.h,v 1.2 2000/02/02 16:35:57 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
@@ -10,6 +11,8 @@
 #ifndef _ASM_SN_IO_H
 #define _ASM_SN_IO_H
 
+#include <linux/config.h>
+#if !defined(CONFIG_SGI_IO)
 #include <asm/sn/sn0/addrs.h>
 
 #define IO_SPACE_BASE IO_BASE
@@ -18,5 +21,55 @@
 #define IO_SPACE_LIMIT 0xffffffff
 
 /* No isa_* versions, the Origin doesn't have ISA / EISA bridges.  */
+
+#else	/* CONFIG_SGI_IO */
+
+#define IIO_ITTE_BASE	0x400160	/* base of translation table entries */
+#define IIO_ITTE(bigwin)	(IIO_ITTE_BASE + 8*(bigwin))
+
+#define IIO_ITTE_OFFSET_BITS	5	/* size of offset field */
+#define IIO_ITTE_OFFSET_MASK	((1<<IIO_ITTE_OFFSET_BITS)-1)
+#define IIO_ITTE_OFFSET_SHIFT	0
+
+#define IIO_ITTE_WIDGET_BITS	4	/* size of widget field */
+#define IIO_ITTE_WIDGET_MASK	((1<<IIO_ITTE_WIDGET_BITS)-1)
+#define IIO_ITTE_WIDGET_SHIFT	8
+
+#define IIO_ITTE_IOSP		1	/* I/O Space bit */
+#define IIO_ITTE_IOSP_MASK	1
+#define IIO_ITTE_IOSP_SHIFT	12
+#define HUB_PIO_MAP_TO_MEM	0
+#define HUB_PIO_MAP_TO_IO	1
+
+#define IIO_ITTE_INVALID_WIDGET	3	/* an invalid widget  */
+
+#define IIO_ITTE_PUT(nasid, bigwin, io_or_mem, widget, addr) \
+	REMOTE_HUB_S((nasid), IIO_ITTE(bigwin), \
+		(((((addr) >> BWIN_SIZE_BITS) & \
+		   IIO_ITTE_OFFSET_MASK) << IIO_ITTE_OFFSET_SHIFT) | \
+		(io_or_mem << IIO_ITTE_IOSP_SHIFT) | \
+		(((widget) & IIO_ITTE_WIDGET_MASK) << IIO_ITTE_WIDGET_SHIFT)))
+
+#define IIO_ITTE_DISABLE(nasid, bigwin) \
+	IIO_ITTE_PUT((nasid), HUB_PIO_MAP_TO_MEM, \
+		     (bigwin), IIO_ITTE_INVALID_WIDGET, 0)
+
+#define IIO_ITTE_GET(nasid, bigwin) REMOTE_HUB_ADDR((nasid), IIO_ITTE(bigwin))
+
+/*
+ * Macro which takes the widget number, and returns the 
+ * IO PRB address of that widget.
+ * value _x is expected to be a widget number in the range 
+ * 0, 8 - 0xF
+ */
+#define	IIO_IOPRB(_x)	(IIO_IOPRB_0 + ( ( (_x) < HUB_WIDGET_ID_MIN ? \
+			(_x) : \
+			(_x) - (HUB_WIDGET_ID_MIN-1)) << 3) )
+
+#if defined (CONFIG_SGI_IP27)
+#include <asm/sn/sn0/hubio.h>
+#endif
+
+#endif	/* CONFIG_SGI_IO */
 
 #endif /* _ASM_SN_IO_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/klconfig.h linux/include/asm-mips64/sn/klconfig.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/klconfig.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/klconfig.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: klconfig.h,v 1.2 2000/01/16 01:39:08 ralf Exp $
+/* $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
@@ -32,19 +32,35 @@
  *      that offsets of existing fields do not change.
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <asm/sn/types.h>
+#if defined(CONFIG_SGI_IP27) || defined(CONFIG_SGI_IP35)
+#include <asm/sn/agent.h>
+#include <asm/arc/types.h>
+#include <asm/arc/hinv.h>
+#endif /* !CONFIG_SGI_IP27 || !CONFIG_SGI_IP35 */
+#if defined(CONFIG_SGI_IP27)
 #include <asm/sn/sn0/addrs.h>
 //#include <sys/SN/router.h>
 // XXX Stolen from <sys/SN/router.h>:
-#define MAX_ROUTER_PORTS (6)	/* Max. number of ports on a router */
-#include <asm/sn/agent.h>
+#define MAX_ROUTER_PORTS (6)    /* Max. number of ports on a router */
+#include <asm/sn/sn0/sn0_fru.h>
 //#include <sys/graph.h>
-#include <asm/arc/types.h>
-#include <asm/arc/hinv.h>
 //#include <sys/xtalk/xbow.h>
-#include <asm/sn/sn0/sn0_fru.h>
-
+#elif defined(CONFIG_SGI_IP35)
+#include <asm/sn/sn1/addrs.h>
+#include <sys/sn/router.h>
+#include <sys/graph.h>
+#include <asm/xtalk/xbow.h>
+#endif  /* !CONFIG_SGI_IP27 && !CONFIG_SGI_IP35 */
+#if (defined(CONFIG_SGI_IP27) && defined(CONFIG_SGI_IO)) || \
+     defined(CONFIG_SGI_IP35)
+// The hack file has to be before vector and after sn0_fru....
+#include <asm/hack.h>
+#include <asm/sn/vector.h>
+#include <asm/xtalk/xtalk.h>
+#endif  /* !(CONFIG_SGI_IP27 && CONFIG_SGI_IO) || !CONFIG_SGI_IP35 */
 
 #define KLCFGINFO_MAGIC	0xbeedbabe
 
@@ -118,9 +134,15 @@
 
 
 typedef struct console_s {
+#if defined(CONFIG_SGI_IO)	/* FIXME */
+	__psunsigned_t 	uart_base;
+	__psunsigned_t 	config_base;
+	__psunsigned_t 	memory_base;
+#else
 	unsigned long 	uart_base;
 	unsigned long 	config_base;
 	unsigned long 	memory_base;
+#endif
 	short		baud;
 	short		flag;
 	int		type;
@@ -175,13 +197,23 @@
 
 /* --- New Macros for the changed kl_config_hdr_t structure --- */
 
+#if defined(CONFIG_SGI_IO)
+#define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
+			((__psunsigned_t)_k + (_k->ch_malloc_hdr_off)))
+#else
 #define PTR_CH_MALLOC_HDR(_k)   ((klc_malloc_hdr_t *)\
-			((unsigned long)_k + (_k->ch_malloc_hdr_off)))
+			(unsigned long)_k + (_k->ch_malloc_hdr_off)))
+#endif
 
 #define KL_CONFIG_CH_MALLOC_HDR(_n)   PTR_CH_MALLOC_HDR(KL_CONFIG_HDR(_n))
 
+#if defined(CONFIG_SGI_IO)
+#define PTR_CH_CONS_INFO(_k)	((console_t *)\
+			((__psunsigned_t)_k + (_k->ch_cons_off)))
+#else
 #define PTR_CH_CONS_INFO(_k)	((console_t *)\
 			((unsigned long)_k + (_k->ch_cons_off)))
+#endif
 
 #define KL_CONFIG_CH_CONS_INFO(_n)   PTR_CH_CONS_INFO(KL_CONFIG_HDR(_n))
 
@@ -313,7 +345,7 @@
 #define KL_CPU_NONE		(-1)	/* no cpu present in slot */
 
 /*
- * SN0 BOARD classes
+ * IP27 BOARD classes
  */
 
 #define KLCLASS_MASK	0xf0   
@@ -331,15 +363,15 @@
 					 * hw ifc to xtalk and are not gfx
 					 * class for sw purposes */
 
-#define KLCLASS_MAX	6		/* Bump this if a new CLASS is added */
-#define KLTYPE_MAX	8		/* Bump this if a new CLASS is added */
+#define KLCLASS_MAX	7		/* Bump this if a new CLASS is added */
+#define KLTYPE_MAX	10		/* Bump this if a new CLASS is added */
 
 #define KLCLASS_UNKNOWN	0xf0
 
 #define KLCLASS(_x) ((_x) & KLCLASS_MASK)
 
 /*
- * SN0 board types
+ * IP27 board types
  */
 
 #define KLTYPE_MASK	0x0f
@@ -369,8 +401,8 @@
 #define KLTYPE_GSN_B   	(KLCLASS_IO  | 0xD) /* Auxiliary GSN board */
 
 #define KLTYPE_GFX	(KLCLASS_GFX | 0x0) /* unknown graphics type */
-#define KLTYPE_GFX_KONA (KLCLASS_GFX | 0x1) /* KONA graphics on SN0 */
-#define KLTYPE_GFX_MGRA (KLCLASS_GFX | 0x3) /* MGRAS graphics on SN0 */
+#define KLTYPE_GFX_KONA (KLCLASS_GFX | 0x1) /* KONA graphics on IP27 */
+#define KLTYPE_GFX_MGRA (KLCLASS_GFX | 0x3) /* MGRAS graphics on IP27 */
 
 #define KLTYPE_WEIRDROUTER (KLCLASS_ROUTER | 0x0)
 #define KLTYPE_ROUTER     (KLCLASS_ROUTER | 0x1)
@@ -381,6 +413,14 @@
 #define KLTYPE_WEIRDMIDPLANE (KLCLASS_MIDPLANE | 0x0)
 #define KLTYPE_MIDPLANE8  (KLCLASS_MIDPLANE | 0x1) /* 8 slot backplane */
 #define KLTYPE_MIDPLANE    KLTYPE_MIDPLANE8
+#define KLTYPE_PBRICK_XBOW	(KLCLASS_MIDPLANE | 0x2)
+
+#define KLTYPE_IOBRICK		(KLCLASS_IOBRICK | 0x0)
+#define KLTYPE_IBRICK		(KLCLASS_IOBRICK | 0x1)
+#define KLTYPE_PBRICK		(KLCLASS_IOBRICK | 0x2)
+#define KLTYPE_XBRICK		(KLCLASS_IOBRICK | 0x3)
+
+#define KLTYPE_PBRICK_BRIDGE	KLTYPE_PBRICK
 
 /* The value of type should be more than 8 so that hinv prints
  * out the board name from the NIC string. For values less than
@@ -898,6 +938,43 @@
 
 /* external declarations of Linux kernel functions. */
 
-extern lboard_t *find_lboard(unsigned int type);
+extern lboard_t *find_lboard(lboard_t *start, unsigned char type);
+extern klinfo_t *find_component(lboard_t *brd, klinfo_t *kli, unsigned char type);
+extern klinfo_t *find_first_component(lboard_t *brd, unsigned char type);
+extern klcpu_t *nasid_slice_to_cpuinfo(nasid_t, int);
+
+
+#if defined(CONFIG_SGI_IO)
+extern xwidgetnum_t nodevertex_widgetnum_get(vertex_hdl_t node_vtx);
+extern vertex_hdl_t nodevertex_xbow_peer_get(vertex_hdl_t node_vtx);
+extern lboard_t *find_gfxpipe(int pipenum);
+extern void setup_gfxpipe_link(vertex_hdl_t vhdl,int pipenum);
+extern lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_class);
+extern lboard_t *find_lboard_module_class(lboard_t *start, moduleid_t mod,
+                                               unsigned char brd_class);
+extern lboard_t *find_nic_lboard(lboard_t *, nic_t);
+extern lboard_t *find_nic_type_lboard(nasid_t, unsigned char, nic_t);
+extern lboard_t *find_lboard_modslot(lboard_t *start, moduleid_t mod, slotid_t slot);
+extern lboard_t *find_lboard_module(lboard_t *start, moduleid_t mod);
+extern lboard_t *get_board_name(nasid_t nasid, moduleid_t mod, slotid_t slot, char *name);
+extern int	config_find_nic_router(nasid_t, nic_t, lboard_t **, klrou_t**);
+extern int	config_find_nic_hub(nasid_t, nic_t, lboard_t **, klhub_t**);
+extern int	config_find_xbow(nasid_t, lboard_t **, klxbow_t**);
+extern klcpu_t *get_cpuinfo(cpuid_t cpu);
+extern int 	update_klcfg_cpuinfo(nasid_t, int);
+extern void 	board_to_path(lboard_t *brd, char *path);
+extern moduleid_t get_module_id(nasid_t nasid);
+extern void 	nic_name_convert(char *old_name, char *new_name);
+extern int 	module_brds(nasid_t nasid, lboard_t **module_brds, int n);
+extern lboard_t *brd_from_key(ulong_t key);
+extern void 	device_component_canonical_name_get(lboard_t *,klinfo_t *,
+						    char *);
+extern int	board_serial_number_get(lboard_t *,char *);
+extern int	is_master_baseio(nasid_t,moduleid_t,slotid_t);
+extern nasid_t	get_actual_nasid(lboard_t *brd) ;
+extern net_vec_t klcfg_discover_route(lboard_t *, lboard_t *, int);
+#else	/* CONFIG_SGI_IO */
+extern klcpu_t *sn_get_cpuinfo(cpuid_t cpu);
+#endif	/* CONFIG_SGI_IO */
 
 #endif /* _ASM_SN_KLCONFIG_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/kldir.h linux/include/asm-mips64/sn/kldir.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/kldir.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/kldir.h	Mon May 15 12:10:26 2000
@@ -1,4 +1,4 @@
-/* $Id: kldir.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
@@ -12,9 +12,14 @@
 #ifndef _ASM_SN_KLDIR_H
 #define _ASM_SN_KLDIR_H
 
+#include <linux/config.h>
+#if defined(CONFIG_SGI_IO)
+#include <asm/hack.h>
+#endif
+
 /*
  * The kldir memory area resides at a fixed place in each node's memory and
- * provides pointers to most other SN0 memory areas.  This allows us to
+ * provides pointers to most other IP27 memory areas.  This allows us to
  * resize and/or relocate memory areas at a later time without breaking all
  * firmware and kernels that use them.  Indices in the array are
  * permanently dedicated to areas listed below.  Some memory areas (marked
@@ -131,6 +136,8 @@
 #define KLDIR_OFF_STRIDE		0x28
 #endif /* LANGUAGE_ASSEMBLY */
 
+#if !defined(CONFIG_SGI_IO)
+
 /*
  * This is defined here because IP27_SYMMON_STK_SIZE must be at least what
  * we define here.  Since it's set up in the prom.  We can't redefine it later
@@ -200,11 +207,17 @@
 #define KLDIR_ENT_SIZE			0x40
 #define KLDIR_MAX_ENTRIES		(0x400 / 0x40)
 
+#endif	/* !CONFIG_SGI_IO */
+
 #ifdef _LANGUAGE_C
 typedef struct kldir_ent_s {
 	u64		magic;		/* Indicates validity of entry      */
 	off_t		offset;		/* Offset from start of node space  */
+#if defined(CONFIG_SGI_IO)	/* FIXME */
+	__psunsigned_t	pointer;	/* Pointer to area in some cases    */
+#else
 	unsigned long	pointer;	/* Pointer to area in some cases    */
+#endif
 	size_t		size;		/* Size in bytes 		    */
 	u64		count;		/* Repeat count if array, 1 if not  */
 	size_t		stride;		/* Stride if array, 0 if not        */
@@ -213,5 +226,23 @@
 	   entry to store partition info. Refer to klpart.h for this. */
 } kldir_ent_t;
 #endif /* _LANGUAGE_C */
+
+#if defined(CONFIG_SGI_IO)
+
+#define KLDIR_ENT_SIZE			0x40
+#define KLDIR_MAX_ENTRIES		(0x400 / 0x40)
+
+/*
+ * The actual offsets of each memory area are machine-dependent
+ */
+#ifdef CONFIG_SGI_IP27
+// Not yet #include <asm/sn/sn0/kldir.h>
+#elif defined(CONFIG_SGI_IP35)
+#include <asm/sn/sn1/kldir.h>
+#else
+#error "kldir.h is currently defined for IP27 and IP35 platforms only"
+#endif
+
+#endif	/* CONFIG_SGI_IO */
 
 #endif /* _ASM_SN_KLDIR_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/launch.h linux/include/asm-mips64/sn/launch.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/launch.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/sn/launch.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,123 @@
+/* $Id: launch.h,v 1.3 2000/04/21 04:09:13 pfg 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) 1992 - 1997, 2000 Silicon Graphics, Inc.
+ * Copyright (C) 2000 by Colin Ngam
+ */
+#ifndef _ASM_SN_LAUNCH_H
+#define _ASM_SN_LAUNCH_H
+
+#include <linux/config.h>
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+
+/*
+ * The launch data structure resides at a fixed place in each node's memory
+ * and is used to communicate between the master processor and the slave
+ * processors.
+ *
+ * The master stores launch parameters in the launch structure
+ * corresponding to a target processor that is in a slave loop, then sends
+ * an interrupt to the slave processor.  The slave calls the desired
+ * function, then returns to the slave loop.  The master may poll or wait
+ * for the slaves to finish.
+ *
+ * There is an array of launch structures, one per CPU on the node.  One
+ * interrupt level is used per local CPU.
+ */
+
+#define LAUNCH_MAGIC		0xaddbead2addbead3
+#ifdef CONFIG_SGI_IP27
+#define LAUNCH_SIZEOF		0x100
+#define LAUNCH_PADSZ		0xa0
+#endif
+
+#define LAUNCH_OFF_MAGIC	0x00	/* Struct offsets for assembly      */
+#define LAUNCH_OFF_BUSY		0x08
+#define LAUNCH_OFF_CALL		0x10
+#define LAUNCH_OFF_CALLC	0x18
+#define LAUNCH_OFF_CALLPARM	0x20
+#define LAUNCH_OFF_STACK	0x28
+#define LAUNCH_OFF_GP		0x30
+#define LAUNCH_OFF_BEVUTLB	0x38
+#define LAUNCH_OFF_BEVNORMAL	0x40
+#define LAUNCH_OFF_BEVECC	0x48
+
+#define LAUNCH_STATE_DONE	0	/* Return value of LAUNCH_POLL      */
+#define LAUNCH_STATE_SENT	1
+#define LAUNCH_STATE_RECD	2
+
+/*
+ * The launch routine is called only if the complement address is correct.
+ *
+ * Before control is transferred to a routine, the compliment address
+ * is zeroed (invalidated) to prevent an accidental call from a spurious
+ * interrupt.
+ *
+ * The slave_launch routine turns on the BUSY flag, and the slave loop
+ * clears the BUSY flag after control is returned to it.
+ */
+
+#ifdef _LANGUAGE_C
+
+typedef int launch_state_t;
+typedef void (*launch_proc_t)(u64 call_parm);
+
+typedef struct launch_s {
+	volatile u64		magic;	/* Magic number                     */
+	volatile u64		busy;	/* Slave currently active           */
+	volatile launch_proc_t	call_addr;	/* Func. for slave to call  */
+	volatile u64		call_addr_c;	/* 1's complement of call_addr*/
+	volatile u64		call_parm;	/* Single parm passed to call*/
+	volatile void *stack_addr;	/* Stack pointer for slave function */
+	volatile void *gp_addr;		/* Global pointer for slave func.   */
+	volatile char 		*bevutlb;/* Address of bev utlb ex handler   */
+	volatile char 		*bevnormal;/*Address of bev normal ex handler */
+	volatile char 		*bevecc;/* Address of bev cache err handler */
+	volatile char		pad[160];	/* Pad to LAUNCH_SIZEOF	    */
+} launch_t;
+
+/*
+ * PROM entry points for launch routines are determined by IPxxprom/start.s
+ */
+
+#define LAUNCH_SLAVE	(*(void (*)(int nasid, int cpu, \
+				    launch_proc_t call_addr, \
+				    u64 call_parm, \
+				    void *stack_addr, \
+				    void *gp_addr)) \
+			 IP27PROM_LAUNCHSLAVE)
+
+#define LAUNCH_WAIT	(*(void (*)(int nasid, int cpu, int timeout_msec)) \
+			 IP27PROM_WAITSLAVE)
+
+#define LAUNCH_POLL	(*(launch_state_t (*)(int nasid, int cpu)) \
+			 IP27PROM_POLLSLAVE)
+
+#define LAUNCH_LOOP	(*(void (*)(void)) \
+			 IP27PROM_SLAVELOOP)
+
+#define LAUNCH_FLASH	(*(void (*)(void)) \
+			 IP27PROM_FLASHLEDS)
+
+#ifdef _STANDALONE
+
+launch_t       *launch_get(int nasid, int cpu);
+launch_t       *launch_get_current(void);
+void		launch_loop(void);
+void		launch_slave(int nasid, int cpu,
+			     launch_proc_t call_addr,
+			     __int64_t call_parm,
+			     void *stack_addr,
+			     void *gp_addr);
+int		launch_wait(int nasid, int cpu, int timeout_msec);
+launch_state_t	launch_poll(int nasid, int cpu);
+
+#endif /* _STANDALONE */
+
+#endif /* _LANGUAGE_C */
+
+#endif /* _ASM_SN_LAUNCH_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/nmi.h linux/include/asm-mips64/sn/nmi.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/nmi.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/sn/nmi.h	Mon May 15 12:55:26 2000
@@ -0,0 +1,125 @@
+/* 
+ * 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) 1992 - 1997 Silicon Graphics, Inc.
+ */
+#ifndef __ASM_SN_NMI_H
+#define __ASM_SN_NMI_H
+
+#ident "$Revision: 1.1 $"
+
+#include <asm/sn/addrs.h>
+
+/*
+ * The launch data structure resides at a fixed place in each node's memory
+ * and is used to communicate between the master processor and the slave
+ * processors.
+ *
+ * The master stores launch parameters in the launch structure
+ * corresponding to a target processor that is in a slave loop, then sends
+ * an interrupt to the slave processor.  The slave calls the desired
+ * function, followed by an optional rendezvous function, then returns to
+ * the slave loop.  The master does not wait for the slaves before
+ * returning.
+ *
+ * There is an array of launch structures, one per CPU on the node.  One
+ * interrupt level is used per CPU.
+ */
+
+#define NMI_MAGIC		0x48414d4d455201
+#define NMI_SIZEOF		0x40
+
+#define NMI_OFF_MAGIC		0x00	/* Struct offsets for assembly      */
+#define NMI_OFF_FLAGS		0x08
+#define NMI_OFF_CALL		0x10
+#define NMI_OFF_CALLC		0x18
+#define NMI_OFF_CALLPARM	0x20
+#define NMI_OFF_GMASTER		0x28
+
+/*
+ * The NMI routine is called only if the complement address is
+ * correct.
+ *
+ * Before control is transferred to a routine, the compliment address
+ * is zeroed (invalidated) to prevent an accidental call from a spurious
+ * interrupt.
+ *
+ */
+
+#ifdef _LANGUAGE_C
+
+typedef struct nmi_s {
+	volatile unsigned long	 magic;		/* Magic number */
+	volatile unsigned long	 flags;		/* Combination of flags above */
+	volatile void *call_addr;	/* Routine for slave to call        */
+	volatile void *call_addr_c;	/* 1's complement of address        */
+	volatile void *call_parm;	/* Single parm passed to call	    */
+	volatile unsigned long	 gmaster;	/* Flag true only on global master*/
+} nmi_t;
+
+#endif /* _LANGUAGE_C */
+
+/* Following definitions are needed both in the prom & the kernel
+ * to identify the format of the nmi cpu register save area in the
+ * low memory on each node.
+ */
+#ifdef _LANGUAGE_C
+
+struct reg_struct {
+	unsigned long	gpr[32];
+	unsigned long	sr;
+	unsigned long	cause;
+	unsigned long	epc;
+	unsigned long	badva;
+	unsigned long	error_epc;
+	unsigned long	cache_err;
+	unsigned long	nmi_sr;
+};
+
+#endif /* _LANGUAGE_C */
+
+/* These are the assembly language offsets into the reg_struct structure */
+
+#define R0_OFF		0x0
+#define R1_OFF		0x8
+#define R2_OFF		0x10
+#define R3_OFF		0x18
+#define R4_OFF		0x20
+#define R5_OFF		0x28
+#define R6_OFF		0x30
+#define R7_OFF		0x38
+#define R8_OFF		0x40
+#define R9_OFF		0x48
+#define R10_OFF		0x50
+#define R11_OFF		0x58
+#define R12_OFF		0x60
+#define R13_OFF		0x68
+#define R14_OFF		0x70
+#define R15_OFF		0x78
+#define R16_OFF		0x80
+#define R17_OFF		0x88
+#define R18_OFF		0x90
+#define R19_OFF		0x98
+#define R20_OFF		0xa0
+#define R21_OFF		0xa8
+#define R22_OFF		0xb0
+#define R23_OFF		0xb8
+#define R24_OFF		0xc0
+#define R25_OFF		0xc8
+#define R26_OFF		0xd0
+#define R27_OFF		0xd8
+#define R28_OFF		0xe0
+#define R29_OFF		0xe8
+#define R30_OFF		0xf0
+#define R31_OFF		0xf8
+#define SR_OFF		0x100
+#define CAUSE_OFF	0x108
+#define EPC_OFF		0x110
+#define BADVA_OFF	0x118
+#define ERROR_EPC_OFF	0x120
+#define CACHE_ERR_OFF	0x128
+#define NMISR_OFF	0x130
+
+#endif /* __ASM_SN_NMI_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/addrs.h linux/include/asm-mips64/sn/sn0/addrs.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/addrs.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/addrs.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: addrs.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/arch.h linux/include/asm-mips64/sn/sn0/arch.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/arch.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/arch.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: arch.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hub.h linux/include/asm-mips64/sn/sn0/hub.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hub.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/hub.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: hub.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hubio.h linux/include/asm-mips64/sn/sn0/hubio.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hubio.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/hubio.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: hubio.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hubni.h linux/include/asm-mips64/sn/sn0/hubni.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hubni.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/hubni.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: hubni.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hubpi.h linux/include/asm-mips64/sn/sn0/hubpi.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/hubpi.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/hubpi.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: hubpi.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/ip27.h linux/include/asm-mips64/sn/sn0/ip27.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/ip27.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/ip27.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ip27.h,v 1.2 2000/01/26 06:11:50 kanoj Exp $
+/* $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
@@ -85,9 +85,19 @@
 
 /* Sanity hazzard ...  Below all the Origin hacks are following.  */
 
-#define IOC3_SERIAL_INT		8
-#define IOC3_ETH_INT		9
-#define SCSI1_INT		1
 #define SCSI0_INT		0
+#define SCSI1_INT		1
+#define CPU_RESCHED_A_IRQ	3
+#define CPU_RESCHED_B_IRQ	4
+#define QLOGICFC_SLOT5          5
+#define CPU_CALL_A_IRQ		6
+#define CPU_CALL_B_IRQ		7
+#define IOC3_SERIAL_INT		8
+/*#define IOC3_ETH_INT		9*/
+#define IOC3_ETH_INT		0x0809	/* nasid 0, wid 0x8 */
 
+#define SN00_BRIDGE		0x9200000008000000
+#define SN00I_BRIDGE0		0x920000000b000000
+#define SN00I_BRIDGE1		0x920000000e000000
+#define SN00I_BRIDGE2		0x920000000f000000
 #endif /* _ASM_SN_SN0_IP27_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/sn0_fru.h linux/include/asm-mips64/sn/sn0/sn0_fru.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn0/sn0_fru.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/sn0/sn0_fru.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sn0_fru.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/sn_private.h linux/include/asm-mips64/sn/sn_private.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/sn_private.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-mips64/sn/sn_private.h	Sat May 13 08:31:25 2000
@@ -0,0 +1,6 @@
+extern cnodeid_t get_compact_nodeid(void);
+extern void hub_rtc_init(cnodeid_t);
+extern void cpu_time_init(void);
+extern void per_cpu_init(void);
+extern void install_cpuintr(cpuid_t cpu);
+extern void install_tlbintr(cpuid_t cpu);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sn/types.h linux/include/asm-mips64/sn/types.h
--- v2.3.99-pre8/linux/include/asm-mips64/sn/types.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sn/types.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: types.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
@@ -12,6 +12,9 @@
 
 #include <linux/types.h>
 
+typedef unsigned long 	cpuid_t;
+typedef unsigned long 	cpumask_t;
+typedef unsigned long	cnodemask_t;
 typedef signed short	nasid_t;	/* node id in numa-as-id space */
 typedef signed short	cnodeid_t;	/* node id in compact-id space */
 typedef signed char	partid_t;	/* partition ID type */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/socket.h linux/include/asm-mips64/socket.h
--- v2.3.99-pre8/linux/include/asm-mips64/socket.h	Thu Mar  2 14:36:23 2000
+++ linux/include/asm-mips64/socket.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: socket.h,v 1.1 1999/08/18 23:37:52 ralf Exp $
+/* $Id: socket.h,v 1.2 2000/02/25 21:52:09 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
@@ -61,6 +61,8 @@
 #define SO_ATTACH_FILTER        26
 #define SO_DETACH_FILTER        27
 
+#ifdef __KERNEL__
+
 #define SO_PEERNAME             28
 
 /* Types of sockets.  */
@@ -75,5 +77,6 @@
 #define SOCK_PACKET 10		/* Linux specific way of getting packets at
 				   the dev level.  For writing rarp and
 				   other similar things on the user level.  */
+#endif /* __KERNEL__ */
 
 #endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sockios.h linux/include/asm-mips64/sockios.h
--- v2.3.99-pre8/linux/include/asm-mips64/sockios.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sockios.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sockios.h,v 1.1 1999/08/18 23:37:52 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/softirq.h linux/include/asm-mips64/softirq.h
--- v2.3.99-pre8/linux/include/asm-mips64/softirq.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/softirq.h	Sat May 13 08:31:25 2000
@@ -13,14 +13,12 @@
 #include <asm/atomic.h>
 #include <asm/hardirq.h>
 
-extern unsigned int local_bh_count[NR_CPUS];
-
-#define cpu_bh_disable(cpu)	do { local_bh_count[(cpu)]++; barrier(); } while (0)
-#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count[(cpu)]--; } while (0)
+#define cpu_bh_disable(cpu)	do { local_bh_count(cpu)++; barrier(); } while (0)
+#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count(cpu)--; } while (0)
 
 #define local_bh_disable()	cpu_bh_disable(smp_processor_id())
 #define local_bh_enable()	cpu_bh_enable(smp_processor_id())
 
-#define in_softirq() (local_bh_count[smp_processor_id()] != 0)
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
 
 #endif /* _ASM_SOFTIRQ_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/spinlock.h linux/include/asm-mips64/spinlock.h
--- v2.3.99-pre8/linux/include/asm-mips64/spinlock.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/spinlock.h	Sat May 13 08:31:25 2000
@@ -22,6 +22,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.
@@ -62,7 +65,24 @@
 	: "memory");
 }
 
-#define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
+static inline unsigned int spin_trylock(spinlock_t *lock)
+{
+	unsigned int temp, res;
+
+	__asm__ __volatile__(
+	".set\tnoreorder\t\t\t# spin_trylock\n\t"
+	"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" (*lock), "=&r" (res)
+	:"r" (1), "m" (*lock)
+	: "memory");
+
+	return res == 0;
+}
 
 /*
  * Read-write spinlocks, allowing multiple readers but only one writer.
@@ -110,6 +130,7 @@
 	"sub\t%1, 1\n\t"
 	"sc\t%1, %0\n\t"
 	"beqz\t%1, 1b\n\t"
+	"sync\n\t"
 	".set\treorder"	
 	: "=o" (__dummy_lock(rw)), "=&r" (tmp)
 	: "o" (__dummy_lock(rw))
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/stackframe.h linux/include/asm-mips64/stackframe.h
--- v2.3.99-pre8/linux/include/asm-mips64/stackframe.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/stackframe.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: stackframe.h,v 1.4 2000/02/24 03:24:38 ulfc Exp $
+/* $Id: stackframe.h,v 1.3 1999/12/04 03:59: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
@@ -11,8 +11,12 @@
 #ifndef _ASM_STACKFRAME_H
 #define _ASM_STACKFRAME_H
 
+#include <linux/config.h>
+
 #include <asm/asm.h>
 #include <asm/offset.h>
+#include <asm/processor.h>
+#include <asm/addrspace.h>
 
 #ifdef _LANGUAGE_C
 
@@ -82,8 +86,20 @@
 		 move	k1, sp
 		.set	reorder
 		/* Called from user mode, new stack. */
+#ifndef CONFIG_SMP
 		lui	k1, %hi(kernelsp)
 		ld	k1, %lo(kernelsp)(k1)
+#else
+		mfc0	k0, CP0_WATCHLO
+		mfc0	k1, CP0_WATCHHI
+		dsll32	k0, k0, 0	/* Get rid of sign extension */
+		dsrl32	k0, k0, 0	/* Get rid of sign extension */
+		dsll32	k1, k1, 0
+		or	k1, k1, k0
+		li	k0, K0BASE
+		or	k1, k1, k0
+		daddiu	k1, k1, KERNEL_STACK_SIZE-32
+#endif
 8:		move	k0, sp
 		dsubu	sp, k1, PT_SIZE
 		sd	k0, PT_R29(sp)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/stat.h linux/include/asm-mips64/stat.h
--- v2.3.99-pre8/linux/include/asm-mips64/stat.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/stat.h	Sat May 13 08:31:25 2000
@@ -28,6 +28,32 @@
 	unsigned int	st_gen;
 };
 
+struct stat32 {
+	__kernel_dev_t32    st_dev;
+	int		    st_pad1[3];
+	__kernel_ino_t32    st_ino;
+	__kernel_mode_t32   st_mode;
+	__kernel_nlink_t32  st_nlink;
+	__kernel_uid_t32    st_uid;
+	__kernel_gid_t32    st_gid;
+	__kernel_dev_t32    st_rdev;
+	int		    st_pad2[2];
+	__kernel_off_t32    st_size;
+	int		    st_pad3;
+	__kernel_time_t32   st_atime;
+	int		    reserved0;
+	__kernel_time_t32   st_mtime;
+	int		    reserved1;
+	__kernel_time_t32   st_ctime;
+	int		    reserved2;
+	int		    st_blksize;
+	int		    st_blocks;
+	char		    st_fstype[16];	/* Filesystem type name */
+	int		    st_pad4[8];
+	unsigned int	    st_flags;
+	unsigned int	    st_gen;
+};
+
 struct stat {
 	dev_t		st_dev;
 	long		st_pad1[3];		/* Reserved for network id */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/statfs.h linux/include/asm-mips64/statfs.h
--- v2.3.99-pre8/linux/include/asm-mips64/statfs.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/statfs.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: statfs.h,v 1.1 1999/08/18 23:37:52 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/string.h linux/include/asm-mips64/string.h
--- v2.3.99-pre8/linux/include/asm-mips64/string.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/string.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: string.h,v 1.4 2000/01/16 01:37:19 ralf Exp $
+/* $Id: string.h,v 1.3 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/sysmips.h linux/include/asm-mips64/sysmips.h
--- v2.3.99-pre8/linux/include/asm-mips64/sysmips.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/sysmips.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: sysmips.h,v 1.1 1999/12/04 03:59:12 ralf Exp $
+/* $Id: sysmips.h,v 1.1 1999/10/08 21:07:57 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/system.h linux/include/asm-mips64/system.h
--- v2.3.99-pre8/linux/include/asm-mips64/system.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/system.h	Sat May 13 08:31:25 2000
@@ -11,6 +11,8 @@
 #ifndef _ASM_SYSTEM_H
 #define _ASM_SYSTEM_H
 
+#include <linux/config.h>
+
 #include <asm/sgidefs.h>
 #include <linux/kernel.h>
 
@@ -105,14 +107,27 @@
 		: "$8", "$9", "memory");
 }
 
-/*
- * Non-SMP versions ...
- */
-#define sti() __sti()
+#ifdef CONFIG_SMP
+
+extern void __global_cli(void);
+extern void __global_sti(void);
+extern unsigned long __global_save_flags(void);
+extern void __global_restore_flags(unsigned long);
+#define cli() __global_cli()
+#define sti() __global_sti()
+#define save_flags(x) ((x)=__global_save_flags())
+#define restore_flags(x) __global_restore_flags(x)
+#define save_and_cli(x) do { save_flags(flags); cli(); } while(0)
+
+#else
+
 #define cli() __cli()
+#define sti() __sti()
 #define save_flags(x) __save_flags(x)
-#define save_and_cli(x) __save_and_cli(x)
 #define restore_flags(x) __restore_flags(x)
+#define save_and_cli(x) __save_and_cli(x)
+
+#endif /* CONFIG_SMP */
 
 /* For spinlocks etc */
 #define local_irq_save(x)	__save_and_cli(x);
@@ -154,8 +169,25 @@
 #endif /* !defined (_LANGUAGE_ASSEMBLY) */
 
 #define prepare_to_switch()	do { } while(0)
+
+extern asmlinkage void lazy_fpu_switch(void *, void *);
+extern asmlinkage void init_fpu(void);
+extern asmlinkage void save_fp(void *);
+
+#ifdef CONFIG_SMP
+#define SWITCH_DO_LAZY_FPU \
+	if (prev->flags & PF_USEDFPU) { \
+		lazy_fpu_switch(prev, 0); \
+		set_cp0_status(ST0_CU1, ~ST0_CU1); \
+		prev->flags &= ~PF_USEDFPU; \
+	}
+#else /* CONFIG_SMP */
+#define SWITCH_DO_LAZY_FPU	do { } while(0)
+#endif /* CONFIG_SMP */
+
 #define switch_to(prev,next,last) \
 do { \
+	SWITCH_DO_LAZY_FPU; \
 	(last) = resume(prev, next); \
 } while(0)
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/termbits.h linux/include/asm-mips64/termbits.h
--- v2.3.99-pre8/linux/include/asm-mips64/termbits.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/termbits.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: termbits.h,v 1.1 1999/08/18 23:37:52 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/termios.h linux/include/asm-mips64/termios.h
--- v2.3.99-pre8/linux/include/asm-mips64/termios.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/termios.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.3 2000/02/18 00:24:49 ralf Exp $
+/* $Id: termios.h,v 1.2 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/timex.h linux/include/asm-mips64/timex.h
--- v2.3.99-pre8/linux/include/asm-mips64/timex.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/timex.h	Sat May 13 08:31:25 2000
@@ -33,7 +33,15 @@
 
 static inline cycles_t get_cycles (void)
 {
-	return read_32bit_cp0_register(CP0_COUNT);
+	cycles_t val;
+
+	__asm__ __volatile__(
+		".set noreorder\n\t"
+		"mfc0 %0, $9\n\t"
+		".set reorder"
+		: "=r" (val));
+
+	return val;
 }
 
 #endif /*  _ASM_TIMEX_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/types.h linux/include/asm-mips64/types.h
--- v2.3.99-pre8/linux/include/asm-mips64/types.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/types.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: types.h,v 1.3 2000/02/18 00:24:49 ralf Exp $
+/* $Id: types.h,v 1.2 1999/12/04 03:59: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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/uaccess.h linux/include/asm-mips64/uaccess.h
--- v2.3.99-pre8/linux/include/asm-mips64/uaccess.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/uaccess.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: uaccess.h,v 1.5 2000/02/21 18:05:07 ralf Exp $
+/* $Id: uaccess.h,v 1.4 2000/02/19 00:33:10 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/ucontext.h linux/include/asm-mips64/ucontext.h
--- v2.3.99-pre8/linux/include/asm-mips64/ucontext.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/ucontext.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: ucontext.h,v 1.1 1999/09/28 22:27:20 ralf Exp $
+/* $Id: ucontext.h,v 1.1 1999/09/27 16:01:40 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/unaligned.h linux/include/asm-mips64/unaligned.h
--- v2.3.99-pre8/linux/include/asm-mips64/unaligned.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/unaligned.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: unaligned.h,v 1.1 1999/08/19 22:56:35 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/unistd.h linux/include/asm-mips64/unistd.h
--- v2.3.99-pre8/linux/include/asm-mips64/unistd.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/unistd.h	Sat May 13 08:31:25 2000
@@ -1014,7 +1014,7 @@
 #define __NR_Linux32_ptrace		(__NR_Linux32 +  26)
 #define __NR_Linux32_alarm		(__NR_Linux32 +  27)
 #define __NR_Linux32_oldfstat		(__NR_Linux32 +  28)
-#define __NR_Linux32_unused29		(__NR_Linux32 +  29)
+#define __NR_Linux32_pause		(__NR_Linux32 +  29)
 #define __NR_Linux32_utime		(__NR_Linux32 +  30)
 #define __NR_Linux32_stty		(__NR_Linux32 +  31)
 #define __NR_Linux32_gtty		(__NR_Linux32 +  32)
@@ -1202,11 +1202,13 @@
 #define __NR_Linux32_lstat64		(__NR_Linux32 + 214)
 #define __NR_Linux32_fstat64		(__NR_Linux32 + 215)
 #define __NR_Linux32_root_pivot		(__NR_Linux32 + 216)
+#define __NR_Linux32_mincore		(__NR_Linux32 + 217)
+#define __NR_Linux32_madvise		(__NR_Linux32 + 218)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux32_syscalls		216
+#define __NR_Linux32_syscalls		218
 
 /*
  * Linux 64-bit syscalls are in the range from 5000 to 5999.
@@ -1241,7 +1243,7 @@
 #define __NR_ptrace			(__NR_Linux +  26)
 #define __NR_alarm			(__NR_Linux +  27)
 #define __NR_oldfstat			(__NR_Linux +  28)
-#define __NR_unused29			(__NR_Linux +  29)
+#define __NR_pause			(__NR_Linux +  29)
 #define __NR_utime			(__NR_Linux +  30)
 #define __NR_stty			(__NR_Linux +  31)
 #define __NR_gtty			(__NR_Linux +  32)
@@ -1423,11 +1425,13 @@
 #define __NR_getpmsg			(__NR_Linux + 208)
 #define __NR_putpmsg			(__NR_Linux + 209)
 #define __NR_root_pivot			(__NR_Linux + 210)
+#define __NR_mincore			(__NR_Linux + 211)
+#define __NR_madvise			(__NR_Linux + 212)
 
 /*
  * Offset of the last Linux flavoured syscall
  */
-#define __NR_Linux_syscalls		210
+#define __NR_Linux_syscalls		212
 
 #ifndef _LANGUAGE_ASSEMBLY
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/user.h linux/include/asm-mips64/user.h
--- v2.3.99-pre8/linux/include/asm-mips64/user.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/user.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: user.h,v 1.1 1999/08/20 21:59:09 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/usioctl.h linux/include/asm-mips64/usioctl.h
--- v2.3.99-pre8/linux/include/asm-mips64/usioctl.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/usioctl.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: usioctl.h,v 1.1 1999/08/19 22:56:35 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/watch.h linux/include/asm-mips64/watch.h
--- v2.3.99-pre8/linux/include/asm-mips64/watch.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/watch.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: watch.h,v 1.1 1999/09/28 22:27:20 ralf Exp $
+/* $Id: watch.h,v 1.1 1999/09/27 16:01:41 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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/xtalk/xtalk.h linux/include/asm-mips64/xtalk/xtalk.h
--- v2.3.99-pre8/linux/include/asm-mips64/xtalk/xtalk.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/xtalk/xtalk.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: xtalk.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-mips64/xtalk/xwidget.h linux/include/asm-mips64/xtalk/xwidget.h
--- v2.3.99-pre8/linux/include/asm-mips64/xtalk/xwidget.h	Sat Feb 26 22:31:57 2000
+++ linux/include/asm-mips64/xtalk/xwidget.h	Sat May 13 08:31:25 2000
@@ -1,4 +1,4 @@
-/* $Id: xwidget.h,v 1.1 2000/01/13 00:17:02 ralf Exp $
+/* $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
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
--- v2.3.99-pre8/linux/include/asm-ppc/bitops.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-ppc/bitops.h	Sun May 21 20:55:06 2000
@@ -7,7 +7,6 @@
 #define _PPC_BITOPS_H
 
 #include <linux/config.h>
-#include <asm/system.h>
 #include <asm/byteorder.h>
 
 extern void set_bit(int nr, volatile void *addr);
@@ -278,3 +277,4 @@
 #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
 
 #endif /* _PPC_BITOPS_H */
+
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-ppc/cpm_8260.h linux/include/asm-ppc/cpm_8260.h
--- v2.3.99-pre8/linux/include/asm-ppc/cpm_8260.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-ppc/cpm_8260.h	Mon May 15 14:53:31 2000
@@ -124,6 +124,14 @@
 #define BD_SC_OV	((ushort)0x0002)	/* Overrun */
 #define BD_SC_CD	((ushort)0x0001)	/* ?? */
 
+/* Function code bits, usually generic to devices.
+*/
+#define CPMFCR_GBL	((u_char)0x20)	/* Set memory snooping */
+#define CPMFCR_EB	((u_char)0x10)	/* Set big endian byte order */
+#define CPMFCR_TC2	((u_char)0x04)	/* Transfer code 2 value */
+#define CPMFCR_DTB	((u_char)0x02)	/* Use local bus for data when set */
+#define CPMFCR_BDB	((u_char)0x01)	/* Use local bus for BD when set */
+
 /* Parameter RAM offsets from the base.
 */
 #define PROFF_SCC1		((uint)0x8000)
@@ -184,13 +192,6 @@
 	uint	smc_stmp;	/* SDMA Temp */
 } smc_uart_t;
 
-/* Function code bits.
-*/
-#define SMC_GBL	((u_char)0x20)	/* Set memory snooping */
-#define SMC_EB	((u_char)0x10)	/* Set big endian byte order */
-#define SMC_TC2	((u_char)0x04)	/* Transfer code 2 value */
-#define SMC_DTB	((u_char)0x02)	/* Use local bus when set */
-
 /* SMC uart mode register (Internal memory map).
 */
 #define	SMCMR_REN	((ushort)0x0001)
@@ -336,10 +337,6 @@
 	uint	scc_rcrc;	/* Internal */
 	uint	scc_tcrc;	/* Internal */
 } sccp_t;
-
-/* Function code bits.
-*/
-#define SCC_EB	((u_char)0x10)	/* Set big endian byte order */
 
 /* CPM Ethernet through SCC1.
  */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-ppc/init.h linux/include/asm-ppc/init.h
--- v2.3.99-pre8/linux/include/asm-ppc/init.h	Sat Oct  9 11:47:50 1999
+++ linux/include/asm-ppc/init.h	Mon May 15 14:53:31 2000
@@ -16,6 +16,12 @@
 	__argprep __prep; \
 	__argprep
 
+#define __chrp __attribute__ ((__section__ (".text.chrp")))
+#define __chrpdata __attribute__ ((__section__ (".data.chrp")))
+#define __chrpfunc(__argchrp) \
+	__argchrp __chrp; \
+	__argchrp
+
 #define __apus __attribute__ ((__section__ (".text.apus")))
 #define __apusdata __attribute__ ((__section__ (".data.apus")))
 #define __apusfunc(__argapus) \
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-ppc/page.h linux/include/asm-ppc/page.h
--- v2.3.99-pre8/linux/include/asm-ppc/page.h	Sun Mar 19 18:35:31 2000
+++ linux/include/asm-ppc/page.h	Mon May 15 14:53:31 2000
@@ -1,4 +1,7 @@
 #include <linux/config.h>
+#ifndef __ASSEMBLY__
+#include <asm/system.h> /* for xmon definition */
+#endif /* ndef __ASSEMBLY__ */
 
 #ifndef _PPC_PAGE_H
 #define _PPC_PAGE_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-ppc/siginfo.h linux/include/asm-ppc/siginfo.h
--- v2.3.99-pre8/linux/include/asm-ppc/siginfo.h	Fri Jan 28 15:09:09 2000
+++ linux/include/asm-ppc/siginfo.h	Sat May 20 12:06:03 2000
@@ -122,7 +122,7 @@
  * SIGSEGV si_codes
  */
 #define SEGV_MAPERR	1	/* address not mapped to object */
-#define SRGV_ACCERR	2	/* invalid permissions for mapped object */
+#define SEGV_ACCERR	2	/* invalid permissions for mapped object */
 #define NSIGSEGV	2
 
 /*
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-ppc/string.h linux/include/asm-ppc/string.h
--- v2.3.99-pre8/linux/include/asm-ppc/string.h	Thu Apr 29 12:39:07 1999
+++ linux/include/asm-ppc/string.h	Mon May 15 14:53:31 2000
@@ -15,5 +15,15 @@
 
 extern int strcasecmp(const char *, const char *);
 extern int strncasecmp(const char *, const char *, int);
+extern char * strcpy(char *,const char *);
+extern char * strncpy(char *,const char *, __kernel_size_t);
+extern __kernel_size_t strlen(const char *);
+extern int strcmp(const char *,const char *);
+extern char * strcat(char *, const char *);
+extern void * memset(void *,int,__kernel_size_t);
+extern void * memcpy(void *,const void *,__kernel_size_t);
+extern void * memmove(void *,const void *,__kernel_size_t);
+extern int memcmp(const void *,const void *,__kernel_size_t);
+extern void * memchr(const void *,int,__kernel_size_t);
 
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/cache.h linux/include/asm-sh/cache.h
--- v2.3.99-pre8/linux/include/asm-sh/cache.h	Tue Mar  7 14:32:26 2000
+++ linux/include/asm-sh/cache.h	Sat May 20 12:05:30 2000
@@ -14,8 +14,4 @@
 #define        L1_CACHE_BYTES  32
 #endif
 
-extern void cache_flush_area(unsigned long start, unsigned long end);
-extern void cache_purge_area(unsigned long start, unsigned long end);
-extern void cache_wback_area(unsigned long start, unsigned long end);
-
 #endif /* __ASM_SH_CACHE_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/checksum.h linux/include/asm-sh/checksum.h
--- v2.3.99-pre8/linux/include/asm-sh/checksum.h	Tue Apr 11 15:09:23 2000
+++ linux/include/asm-sh/checksum.h	Sat May 20 12:05:30 2000
@@ -72,16 +72,16 @@
 static __inline__ unsigned int csum_fold(unsigned int sum)
 {
 	unsigned int __dummy;
-	__asm__("clrt\n\t"
-		"mov	%0, %1\n\t"
-		"shll16	%0\n\t"
-		"addc	%0, %1\n\t"
-		"movt	%0\n\t"
-		"shlr16	%1\n\t"
-		"add	%1, %0"
+	__asm__("swap.w %0, %1\n\t"
+		"extu.w	%0, %0\n\t"
+		"extu.w	%1, %1\n\t"
+		"add	%1, %0\n\t"
+		"swap.w	%0, %1\n\t"
+		"add	%1, %0\n\t"
+		"not	%0, %0\n\t"
 		: "=r" (sum), "=&r" (__dummy)
 		: "0" (sum));
-	return ~sum;
+	return sum;
 }
 
 /*
@@ -93,31 +93,26 @@
  */
 static __inline__ unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl)
 {
-	unsigned int sum, __dummy;
+	unsigned int sum, __dummy0, __dummy1;
 
 	__asm__ __volatile__(
 		"mov.l	@%1+, %0\n\t"
-		"add	#-4, %2\n\t"
-		"clrt\n\t"
-		"mov.l	@%1+, %3\n\t"
-		"addc	%3, %0\n\t"
-		"mov.l	@%1+, %3\n\t"
-		"addc	%3, %0\n\t"
 		"mov.l	@%1+, %3\n\t"
-		"addc	%3, %0\n"
+		"add	#-2, %2\n\t"
+		"clrt\n\t"
 		"1:\t"
-		"mov.l	@%1+, %3\n\t"
 		"addc	%3, %0\n\t"
-		"movt	%3\n\t"
+		"movt	%4\n\t"
+		"mov.l	@%1+, %3\n\t"
 		"dt	%2\n\t"
 		"bf/s	1b\n\t"
-		" cmp/eq #1, %3\n\t"
-		"mov	#0, %3\n\t"
+		" cmp/eq #1, %4\n\t"
 		"addc	%3, %0\n\t"
+		"addc	%2, %0"	    /* Here %2 is 0, add carry-bit */
 	/* Since the input registers which are loaded with iph and ihl
 	   are modified, we must also specify them as outputs, or gcc
 	   will assume they contain their original values. */
-	: "=r" (sum), "=r" (iph), "=r" (ihl), "=&z" (__dummy)
+	: "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (__dummy0), "=&z" (__dummy1)
 	: "1" (iph), "2" (ihl));
 
 	return	csum_fold(sum);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/hitachi_se.h linux/include/asm-sh/hitachi_se.h
--- v2.3.99-pre8/linux/include/asm-sh/hitachi_se.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/hitachi_se.h	Sat May 20 12:05:30 2000
@@ -0,0 +1,53 @@
+#ifndef __ASM_SH_HITACHI_SE_H
+#define __ASM_SH_HITACHI_SE_H
+
+/*
+ * linux/include/asm-sh/hitachi_se.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * Hitachi SolutionEngine support
+ */
+
+/* Box specific addresses.  */
+
+#define PA_ROM		0x00000000	/* EPROM */
+#define PA_ROM_SIZE	0x00400000	/* EPROM size 4M byte */
+#define PA_FROM		0x01000000	/* EPROM */
+#define PA_FROM_SIZE	0x00400000	/* EPROM size 4M byte */
+#define PA_EXT1		0x04000000
+#define PA_EXT1_SIZE	0x04000000
+#define PA_EXT2		0x08000000
+#define PA_EXT2_SIZE	0x04000000
+#define PA_SDRAM	0x0c000000
+#define PA_SDRAM_SIZE	0x04000000
+
+#define PA_EXT4		0x12000000
+#define PA_EXT4_SIZE	0x02000000
+#define PA_EXT5		0x14000000
+#define PA_EXT5_SIZE	0x04000000
+#define PA_PCIC		0x18000000	/* MR-SHPC-01 PCMCIA */
+
+#define PA_83902	0xb0000000	/* DP83902A */
+#define PA_83902_IF	0xb0040000	/* DP83902A remote io port */
+#define PA_83902_RST	0xb0080000	/* DP83902A reset port */
+
+#define PA_SUPERIO	0xb0400000	/* SMC37C935A super io chip */
+#define PA_DIPSW0	0xb0800000	/* Dip switch 5,6 */
+#define PA_DIPSW1	0xb0800002	/* Dip switch 7,8 */
+#define PA_LED		0xb0c00000	/* LED */
+#define PA_BCR		0xb1400000	/* FPGA */
+
+#define PA_MRSHPC	0xb83fffe0	/* MR-SHPC-01 PCMCIA controler */
+
+#define BCR_ILCRA	(PA_BCR + 0)
+#define BCR_ILCRB	(PA_BCR + 2)
+#define BCR_ILCRC	(PA_BCR + 4)
+#define BCR_ILCRD	(PA_BCR + 6)
+#define BCR_ILCRE	(PA_BCR + 8)
+#define BCR_ILCRF	(PA_BCR + 10)
+#define BCR_ILCRG	(PA_BCR + 12)
+
+#define IRQ_STNIC	10
+
+#endif  /* __ASM_SH_HITACHI_SE_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/ide.h linux/include/asm-sh/ide.h
--- v2.3.99-pre8/linux/include/asm-sh/ide.h	Tue Mar  7 14:32:26 2000
+++ linux/include/asm-sh/ide.h	Sat May 20 12:05:30 2000
@@ -17,7 +17,7 @@
 #include <linux/config.h>
 
 #ifndef MAX_HWIFS
-#define MAX_HWIFS	1	/* XXX: For my board -- gniibe */
+#define MAX_HWIFS	1
 #endif
 
 #define ide__sti()	__sti()
@@ -25,8 +25,8 @@
 static __inline__ int ide_default_irq(ide_ioreg_t base)
 {
 	switch (base) {
-		case 0xba0001f0: return 14;
-		case 0xba000170: return 14;
+		case 0x01f0: return 14;
+		case 0x0170: return 15;
 		default:
 			return 0;
 	}
@@ -36,9 +36,9 @@
 {
 	switch (index) {
 		case 0:	
-			return 0xba0001f0;
+			return 0x01f0;
 		case 1:	
-			return 0xba000170;
+			return 0x0170;
 		default:
 			return 0;
 	}
@@ -69,6 +69,7 @@
 	int index;
 
 	for(index = 0; index < MAX_HWIFS; index++) {
+		memset(&hw, 0, sizeof(hw_regs_t));
 		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/io.h linux/include/asm-sh/io.h
--- v2.3.99-pre8/linux/include/asm-sh/io.h	Tue Mar  7 14:32:26 2000
+++ linux/include/asm-sh/io.h	Sat May 20 12:05:30 2000
@@ -14,9 +14,6 @@
 
 #include <asm/cache.h>
 
-#define inb_p	inb
-#define outb_p	outb
-
 #define inw_p	inw
 #define outw_p	outw
 
@@ -53,103 +50,62 @@
         *(volatile unsigned long*)addr = b;
 }
 
-extern __inline__ unsigned long inb_local(unsigned long addr)
-{
-	return readb(addr);
-}
-
-extern __inline__ void outb_local(unsigned char b, unsigned long addr)
-{
-	return writeb(b,addr);
-}
-
-extern __inline__ unsigned long inb(unsigned long addr)
-{
-	return readb(addr);
-}
-
-extern __inline__ unsigned long inw(unsigned long addr)
-{
-	return readw(addr);
-}
-
-extern __inline__ unsigned long inl(unsigned long addr)
-{
-	return readl(addr);
-}
-
-extern __inline__ void insb(unsigned long addr, void *buffer, int count)
-{
-	unsigned char *buf=buffer;
-	while(count--) *buf++=inb(addr);
-}
-
-extern __inline__ void insw(unsigned long addr, void *buffer, int count)
-{
-	unsigned short *buf=buffer;
-	while(count--) *buf++=inw(addr);
-}
-
-extern __inline__ void insl(unsigned long addr, void *buffer, int count)
-{
-	unsigned long *buf=buffer;
-	while(count--) *buf++=inl(addr);
-}
-
-extern __inline__ void outb(unsigned char b, unsigned long addr)
-{
-       return writeb(b,addr);
-}
-
-extern __inline__ void outw(unsigned short b, unsigned long addr)
-{
-       return writew(b,addr);
-}
-
-extern __inline__ void outl(unsigned int b, unsigned long addr)
-{
-       return writel(b,addr);
-}
-
-extern __inline__ void outsb(unsigned long addr, const void *buffer, int count)
-{
-	const unsigned char *buf=buffer;
-	while(count--) outb(*buf++, addr);
-}
-
-extern __inline__ void outsw(unsigned long addr, const void *buffer, int count)
-{
-	const unsigned short *buf=buffer;
-	while(count--) outw(*buf++, addr);
-}
-
-extern __inline__ void outsl(unsigned long addr, const void *buffer, int count)
-{
-	const unsigned long *buf=buffer;
-	while(count--) outl(*buf++, addr);
-}
+extern unsigned long inb(unsigned int port);
+extern unsigned long inb_p(unsigned int port);
+extern unsigned long inw(unsigned int port);
+extern unsigned long inl(unsigned int port);
+extern void insb(unsigned int port, void *addr, unsigned long count);
+extern void insw(unsigned int port, void *addr, unsigned long count);
+extern void insl(unsigned int port, void *addr, unsigned long count);
+
+extern void outb(unsigned long value, unsigned int port);
+extern void outb_p(unsigned long value, unsigned int port);
+extern void outw(unsigned long value, unsigned int port);
+extern void outl(unsigned long value, unsigned int port);
+extern void outsb(unsigned int port, const void *addr, unsigned long count);
+extern void outsw(unsigned int port, const void *addr, unsigned long count);
+extern void outsl(unsigned int port, const void *addr, unsigned long count);
+
+/*
+ * If the platform has PC-like I/O, this function gives us the address
+ * from the offset.
+ */
+extern unsigned long sh_isa_slot(unsigned long offset);
+
+#define isa_readb(a) readb(sh_isa_slot(a))
+#define isa_readw(a) readw(sh_isa_slot(a))
+#define isa_readl(a) readl(sh_isa_slot(a))
+#define isa_writeb(b,a) writeb(b,sh_isa_slot(a))
+#define isa_writew(w,a) writew(w,sh_isa_slot(a))
+#define isa_writel(l,a) writel(l,sh_isa_slot(a))
+#define isa_memset_io(a,b,c) \
+  memset((void *)(sh_isa_slot((unsigned long)a)),(b),(c))
+#define isa_memcpy_fromio(a,b,c) \
+  memcpy((a),(void *)(sh_isa_slot((unsigned long)(b))),(c))
+#define isa_memcpy_toio(a,b,c) \
+  memcpy((void *)(sh_isa_slot((unsigned long)(a))),(b),(c))
 
 #define ctrl_in(addr)		*(addr)
 #define ctrl_out(data,addr)	*(addr) = (data)
 
 extern __inline__ unsigned long ctrl_inb(unsigned long addr)
 {
-       return *(volatile unsigned char*)addr;
+	return *(volatile unsigned char*)addr;
 }
 
 extern __inline__ unsigned long ctrl_inw(unsigned long addr)
 {
-       return *(volatile unsigned short*)addr;
+	return *(volatile unsigned short*)addr;
 }
 
 extern __inline__ unsigned long ctrl_inl(unsigned long addr)
 {
-       return *(volatile unsigned long*)addr;
+	return *(volatile unsigned long*)addr;
 }
 
 extern __inline__ void ctrl_outb(unsigned char b, unsigned long addr)
 {
-       *(volatile unsigned char*)addr = b;
+	*(volatile unsigned char*)addr = b;
 }
 
 extern __inline__ void ctrl_outw(unsigned short b, unsigned long addr)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/irq.h linux/include/asm-sh/irq.h
--- v2.3.99-pre8/linux/include/asm-sh/irq.h	Tue Mar  7 14:32:26 2000
+++ linux/include/asm-sh/irq.h	Sat May 20 12:05:30 2000
@@ -5,15 +5,31 @@
  *
  * linux/include/asm-sh/irq.h
  *
- * Copyright (C) 1999  Niibe Yutaka
+ * Copyright (C) 1999  Niibe Yutaka & Takeshi Yaegashi
+ * Copyright (C) 2000  Kazumoto Kojima
  *
  */
 
 #include <linux/config.h>
 
-#define TIMER_IRQ		16	/* Hard-wired */
-#define TIMER_IPR_OFFSET	12
-#define TIMER_PRIORITY		 2
+#if defined(__sh3__)
+#define INTC_IPRA  	0xfffffee2UL
+#define INTC_IPRB  	0xfffffee4UL
+#elif defined(__SH4__)
+#define INTC_IPRA	0xffd00004UL
+#define INTC_IPRB	0xffd00008UL
+#define INTC_IPRC	0xffd0000cUL
+#endif
+
+#define TIMER_IRQ	16
+#define TIMER_IPR_ADDR	INTC_IPRA
+#define TIMER_IPR_POS	 3
+#define TIMER_PRIORITY	 2
+
+#define RTC_IRQ		22
+#define RTC_IPR_ADDR	INTC_IPRA
+#define RTC_IPR_POS	 0
+#define RTC_PRIORITY	TIMER_PRIORITY
 
 #if defined(__SH4__)
 /*
@@ -37,8 +53,52 @@
 /*
  * Function for "on chip support modules".
  */
-extern void set_ipr_data(unsigned int irq, int offset, int priority);
-extern void make_onChip_irq(unsigned int irq);
+extern void set_ipr_data(unsigned int irq, unsigned int addr,
+			 int pos,  int priority);
+extern void make_ipr_irq(unsigned int irq);
 extern void make_imask_irq(unsigned int irq);
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7709)
+#define INTC_IRR0	0xa4000004UL
+#define INTC_IRR1	0xa4000006UL
+#define INTC_IRR2	0xa4000008UL
+
+#define INTC_ICR0  	0xfffffee0UL
+#define INTC_ICR1  	0xa4000010UL
+#define INTC_ICR2  	0xa4000012UL
+#define INTC_INTER 	0xa4000014UL
+
+#define INTC_IPRC  	0xa4000016UL
+#define INTC_IPRD  	0xa4000018UL
+#define INTC_IPRE  	0xa400001aUL
+
+#define IRQ0_IRQ	32
+#define IRQ1_IRQ	33
+#define IRQ2_IRQ	34
+#define IRQ3_IRQ	35
+#define IRQ4_IRQ	36
+#define IRQ5_IRQ	37
+
+#define IRQ0_IRP_ADDR	INTC_IPRC
+#define IRQ1_IRP_ADDR	INTC_IPRC
+#define IRQ2_IRP_ADDR	INTC_IPRC
+#define IRQ3_IRP_ADDR	INTC_IPRC
+#define IRQ4_IRP_ADDR	INTC_IPRD
+#define IRQ5_IRP_ADDR	INTC_IPRD
+
+#define IRQ0_IRP_POS	0
+#define IRQ1_IRP_POS	1
+#define IRQ2_IRP_POS	2
+#define IRQ3_IRP_POS	3
+#define IRQ4_IRP_POS	0
+#define IRQ5_IRP_POS	1
+
+#define IRQ0_PRIORITY	1
+#define IRQ1_PRIORITY	1
+#define IRQ2_PRIORITY	1
+#define IRQ3_PRIORITY	1
+#define IRQ4_PRIORITY	1
+#define IRQ5_PRIORITY	1
+#endif
 
 #endif /* __ASM_SH_IRQ_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/pgtable.h linux/include/asm-sh/pgtable.h
--- v2.3.99-pre8/linux/include/asm-sh/pgtable.h	Tue Mar  7 14:32:26 2000
+++ linux/include/asm-sh/pgtable.h	Sat May 20 12:05:30 2000
@@ -22,7 +22,10 @@
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
  *  - 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) flushes(invalidates) a range for icache
+ *  - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
  *
  *  Caches are indexed (effectively) by physical address on SH-3, so
  *  we don't need them.
@@ -43,8 +46,7 @@
 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 addr);
-extern void __flush_page_to_ram(unsigned long page_va);
-#define flush_page_to_ram(page)	__flush_page_to_ram(page_address(page))
+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 *pg);
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/smc37c93x.h linux/include/asm-sh/smc37c93x.h
--- v2.3.99-pre8/linux/include/asm-sh/smc37c93x.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sh/smc37c93x.h	Sat May 20 12:05:30 2000
@@ -0,0 +1,190 @@
+#ifndef __ASM_SH_SMC37C93X_H
+#define __ASM_SH_SMC37C93X_H
+
+/*
+ * linux/include/asm-sh/smc37c93x.h
+ *
+ * Copyright (C) 2000  Kazumoto Kojima
+ *
+ * SMSC 37C93x Super IO Chip support
+ */
+
+/* Default base I/O address */
+#define FDC_PRIMARY_BASE	0x3f0
+#define IDE1_PRIMARY_BASE	0x1f0
+#define IDE1_SECONDARY_BASE	0x170
+#define PARPORT_PRIMARY_BASE	0x378
+#define COM1_PRIMARY_BASE	0x2f8
+#define COM2_PRIMARY_BASE	0x3f8
+#define RTC_PRIMARY_BASE	0x070
+#define KBC_PRIMARY_BASE	0x060
+#define AUXIO_PRIMARY_BASE	0x000	/* XXX */
+
+/* Logical device number */
+#define LDN_FDC			0
+#define LDN_IDE1		1
+#define LDN_IDE2		2
+#define LDN_PARPORT		3
+#define LDN_COM1		4
+#define LDN_COM2		5
+#define LDN_RTC			6
+#define LDN_KBC			7
+#define LDN_AUXIO		8
+
+/* Configuration port and key */
+#define CONFIG_PORT		0x3f0
+#define INDEX_PORT		CONFIG_PORT
+#define DATA_PORT		0x3f1
+#define CONFIG_ENTER		0x55
+#define CONFIG_EXIT		0xaa
+
+/* Configuration index */
+#define CURRENT_LDN_INDEX	0x07
+#define POWER_CONTROL_INDEX	0x22
+#define ACTIVATE_INDEX		0x30
+#define IO_BASE_HI_INDEX	0x60
+#define IO_BASE_LO_INDEX	0x61
+#define IRQ_SELECT_INDEX	0x70
+#define DMA_SELECT_INDEX	0x74
+
+#define GPIO46_INDEX		0xc6
+#define GPIO47_INDEX		0xc7
+
+/* UART stuff. Only for debugging.  */
+/* UART Register */
+
+#define UART_RBR	0x0	/* Receiver Buffer Register (Read Only) */
+#define UART_THR	0x0	/* Transmitter Holding Register (Write Only) */
+#define UART_IER	0x2	/* Interrupt Enable Register */
+#define UART_IIR	0x4	/* Interrupt Ident Register (Read Only) */
+#define UART_FCR	0x4	/* FIFO Control Register (Write Only) */
+#define UART_LCR	0x6	/* Line Control Register */
+#define UART_MCR	0x8	/* MODEM Control Register */
+#define UART_LSR	0xa	/* Line Status Register */
+#define UART_MSR	0xc	/* MODEM Status Register */
+#define UART_SCR	0xe	/* Scratch Register */
+#define UART_DLL	0x0	/* Divisor Latch (LS) */
+#define UART_DLM	0x2	/* Divisor Latch (MS) */
+
+#ifndef __ASSEMBLY__
+typedef struct uart_reg {
+	volatile __u16 rbr;
+	volatile __u16 ier;
+	volatile __u16 iir;
+	volatile __u16 lcr;
+	volatile __u16 mcr;
+	volatile __u16 lsr;
+	volatile __u16 msr;
+	volatile __u16 scr;
+} uart_reg;
+#endif /* ! __ASSEMBLY__ */
+
+/* Alias for Write Only Register */
+
+#define thr	rbr
+#define tcr	iir
+
+/* Alias for Divisor Latch Register */
+
+#define dll	rbr
+#define dlm	ier
+#define fcr	iir
+
+/* Interrupt Enable Register */
+
+#define IER_ERDAI	0x0100	/* Enable Received Data Available Interrupt */
+#define IER_ETHREI	0x0200	/* Enable Transmitter Holding Register Empty Interrupt */
+#define IER_ELSI	0x0400	/* Enable Receiver Line Status Interrupt */
+#define IER_EMSI	0x0800	/* Enable MODEM Status Interrupt */
+
+/* Interrupt Ident Register */
+
+#define IIR_IP		0x0100	/* "0" if Interrupt Pending */
+#define IIR_IIB0	0x0200	/* Interrupt ID Bit 0 */
+#define IIR_IIB1	0x0400	/* Interrupt ID Bit 1 */
+#define IIR_IIB2	0x0800	/* Interrupt ID Bit 2 */
+#define IIR_FIFO	0xc000	/* FIFOs enabled */
+
+/* FIFO Control Register */
+
+#define FCR_FEN		0x0100	/* FIFO enable */
+#define FCR_RFRES	0x0200	/* Receiver FIFO reset */
+#define FCR_TFRES	0x0400	/* Transmitter FIFO reset */
+#define FCR_DMA		0x0800	/* DMA mode select */
+#define FCR_RTL		0x4000	/* Receiver triger (LSB) */
+#define FCR_RTM		0x8000	/* Receiver triger (MSB) */
+
+/* Line Control Register */
+
+#define LCR_WLS0	0x0100	/* Word Length Select Bit 0 */
+#define LCR_WLS1	0x0200	/* Word Length Select Bit 1 */
+#define LCR_STB		0x0400	/* Number of Stop Bits */
+#define LCR_PEN		0x0800	/* Parity Enable */
+#define LCR_EPS		0x1000	/* Even Parity Select */
+#define LCR_SP		0x2000	/* Stick Parity */
+#define LCR_SB		0x4000	/* Set Break */
+#define LCR_DLAB	0x8000	/* Divisor Latch Access Bit */
+
+/* MODEM Control Register */
+
+#define MCR_DTR		0x0100	/* Data Terminal Ready */
+#define MCR_RTS		0x0200	/* Request to Send */
+#define MCR_OUT1	0x0400	/* Out 1 */
+#define MCR_IRQEN	0x0800	/* IRQ Enable */
+#define MCR_LOOP	0x1000	/* Loop */
+
+/* Line Status Register */
+
+#define LSR_DR		0x0100	/* Data Ready */
+#define LSR_OE		0x0200	/* Overrun Error */
+#define LSR_PE		0x0400	/* Parity Error */
+#define LSR_FE		0x0800	/* Framing Error */
+#define LSR_BI		0x1000	/* Break Interrupt */
+#define LSR_THRE	0x2000	/* Transmitter Holding Register Empty */
+#define LSR_TEMT	0x4000	/* Transmitter Empty */
+#define LSR_FIFOE	0x8000	/* Receiver FIFO error */
+
+/* MODEM Status Register */
+
+#define MSR_DCTS	0x0100	/* Delta Clear to Send */
+#define MSR_DDSR	0x0200	/* Delta Data Set Ready */
+#define MSR_TERI	0x0400	/* Trailing Edge Ring Indicator */
+#define MSR_DDCD	0x0800	/* Delta Data Carrier Detect */
+#define MSR_CTS		0x1000	/* Clear to Send */
+#define MSR_DSR		0x2000	/* Data Set Ready */
+#define MSR_RI		0x4000	/* Ring Indicator */
+#define MSR_DCD		0x8000	/* Data Carrier Detect */
+
+/* Baud Rate Divisor */
+
+#define UART_CLK	(1843200)	/* 1.8432 MHz */
+#define UART_BAUD(x)	(UART_CLK / (16 * (x)))
+
+/* RTC register definition */
+#define RTC_SECONDS             0
+#define RTC_SECONDS_ALARM       1
+#define RTC_MINUTES             2
+#define RTC_MINUTES_ALARM       3
+#define RTC_HOURS               4
+#define RTC_HOURS_ALARM         5
+#define RTC_DAY_OF_WEEK         6
+#define RTC_DAY_OF_MONTH        7
+#define RTC_MONTH               8
+#define RTC_YEAR                9
+#define RTC_FREQ_SELECT		10
+# define RTC_UIP 0x80
+# define RTC_DIV_CTL 0x70
+/* This RTC can work under 32.768KHz clock only.  */
+# define RTC_OSC_ENABLE 0x20
+# define RTC_OSC_DISABLE 0x00
+#define RTC_CONTROL     	11
+# define RTC_SET 0x80
+# define RTC_PIE 0x40
+# define RTC_AIE 0x20
+# define RTC_UIE 0x10
+# define RTC_SQWE 0x08
+# define RTC_DM_BINARY 0x04
+# define RTC_24H 0x02
+# define RTC_DST_EN 0x01
+
+#endif  /* __ASM_SH_SMC37C93X_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/system.h linux/include/asm-sh/system.h
--- v2.3.99-pre8/linux/include/asm-sh/system.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-sh/system.h	Sat May 20 12:05:30 2000
@@ -165,18 +165,18 @@
 /*
  * Back to P1 area.
  */
-#define back_to_P1()				\
-do {						\
-	unsigned long __dummy;			\
-	__asm__ __volatile__(			\
-		"nop;nop;nop;nop;nop;nop\n\t"	\
-		"mov.l	1f, %0\n\t"		\
-		"jmp	@%0\n\t"		\
-		" nop\n\t"			\
-		".balign 4\n"			\
-		"1:	.long 2f\n"		\
-		"2:"				\
-		: "=&r" (__dummy));		\
+#define back_to_P1()					\
+do {							\
+	unsigned long __dummy;				\
+	__asm__ __volatile__(				\
+		"nop;nop;nop;nop;nop;nop;nop\n\t"	\
+		"mov.l	1f, %0\n\t"			\
+		"jmp	@%0\n\t"			\
+		" nop\n\t"				\
+		".balign 4\n"				\
+		"1:	.long 2f\n"			\
+		"2:"					\
+		: "=&r" (__dummy));			\
 } while (0)
 
 /* For spinlocks etc */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sh/unistd.h linux/include/asm-sh/unistd.h
--- v2.3.99-pre8/linux/include/asm-sh/unistd.h	Wed Apr 26 16:34:09 2000
+++ linux/include/asm-sh/unistd.h	Sat May 20 12:05:30 2000
@@ -314,16 +314,16 @@
 #define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
 type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) \
 { \
-register long __sc0 __asm__ ("$r3") = __NR_##name; \
+register long __sc3 __asm__ ("$r3") = __NR_##name; \
 register long __sc4 __asm__ ("$r4") = (long) arg1; \
 register long __sc5 __asm__ ("$r5") = (long) arg2; \
 register long __sc6 __asm__ ("$r6") = (long) arg3; \
 register long __sc7 __asm__ ("$r7") = (long) arg4; \
-register long __sc2 __asm__ ("$r0") = (long) arg5; \
+register long __sc0 __asm__ ("$r0") = (long) arg5; \
 __asm__ __volatile__ ("trapa	#0x15" \
 	: "=z" (__sc0) \
 	: "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6), "r" (__sc7),  \
-	  "r" (__sc7), "r" (__sc2) \
+	  "r" (__sc3) \
 	: "memory" ); \
 __syscall_return(type,__sc0); \
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc/bitops.h linux/include/asm-sparc/bitops.h
--- v2.3.99-pre8/linux/include/asm-sparc/bitops.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc/bitops.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: bitops.h,v 1.55 2000/02/09 03:28:32 davem Exp $
+/* $Id: bitops.h,v 1.56 2000/05/09 17:40:15 davem Exp $
  * bitops.h: Bit string operations on the Sparc.
  *
  * Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc/ide.h linux/include/asm-sparc/ide.h
--- v2.3.99-pre8/linux/include/asm-sparc/ide.h	Tue Mar 14 19:10:40 2000
+++ linux/include/asm-sparc/ide.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.4 2000/03/12 03:56:12 davem Exp $
+/* $Id: ide.h,v 1.5 2000/05/22 07:29:43 davem Exp $
  * ide.h: SPARC PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
@@ -65,7 +65,8 @@
 	int index;
 
 	for (index = 0; index < MAX_HWIFS; index++) {
-		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		memset(&hw, 0, sizeof(hw_regs_t));
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc/irq.h linux/include/asm-sparc/irq.h
--- v2.3.99-pre8/linux/include/asm-sparc/irq.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc/irq.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.28 2000/01/22 06:06:58 zaitcev Exp $
+/* $Id: irq.h,v 1.29 2000/05/09 17:40:15 davem Exp $
  * irq.h: IRQ registers on the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc/pgalloc.h linux/include/asm-sparc/pgalloc.h
--- v2.3.99-pre8/linux/include/asm-sparc/pgalloc.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc/pgalloc.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: pgalloc.h,v 1.3 2000/02/03 10:13:31 jj Exp $ */
+/* $Id: pgalloc.h,v 1.4 2000/05/09 17:40:15 davem Exp $ */
 #ifndef _SPARC_PGALLOC_H
 #define _SPARC_PGALLOC_H
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc/system.h linux/include/asm-sparc/system.h
--- v2.3.99-pre8/linux/include/asm-sparc/system.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc/system.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.81 2000/02/28 04:00:44 anton Exp $ */
+/* $Id: system.h,v 1.82 2000/05/09 17:40:15 davem Exp $ */
 #include <linux/config.h>
 
 #ifndef __SPARC_SYSTEM_H
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc/winmacro.h linux/include/asm-sparc/winmacro.h
--- v2.3.99-pre8/linux/include/asm-sparc/winmacro.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc/winmacro.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: winmacro.h,v 1.21 1999/08/14 03:52:13 anton Exp $
+/* $Id: winmacro.h,v 1.22 2000/05/09 17:40:15 davem Exp $
  * winmacro.h: Window loading-unloading macros.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/delay.h linux/include/asm-sparc64/delay.h
--- v2.3.99-pre8/linux/include/asm-sparc64/delay.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc64/delay.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: delay.h,v 1.8 2000/04/13 04:45:59 davem Exp $
+/* $Id: delay.h,v 1.9 2000/05/09 17:40:15 davem Exp $
  * delay.h: Linux delay routines on the V9.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu).
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
--- v2.3.99-pre8/linux/include/asm-sparc64/ide.h	Wed Dec 29 13:13:21 1999
+++ linux/include/asm-sparc64/ide.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: ide.h,v 1.17 1999/12/15 22:18:49 davem Exp $
+/* $Id: ide.h,v 1.18 2000/05/22 07:29:43 davem Exp $
  * ide.h: Ultra/PCI specific IDE glue.
  *
  * Copyright (C) 1997  David S. Miller (davem@caip.rutgers.edu)
@@ -59,7 +59,8 @@
 	int index;
 
 	for (index = 0; index < MAX_HWIFS; index++) {
-		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, 0);
+		memset(&hw, 0, sizeof(hw_regs_t));
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
 		hw.irq = ide_default_irq(ide_default_io_base(index));
 		ide_register_hw(&hw, NULL);
 	}
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/irq.h linux/include/asm-sparc64/irq.h
--- v2.3.99-pre8/linux/include/asm-sparc64/irq.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc64/irq.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: irq.h,v 1.17 1999/09/21 14:39:41 davem Exp $
+/* $Id: irq.h,v 1.18 2000/05/09 17:40:15 davem Exp $
  * irq.h: IRQ registers on the 64-bit Sparc.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/oplib.h linux/include/asm-sparc64/oplib.h
--- v2.3.99-pre8/linux/include/asm-sparc64/oplib.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc64/oplib.h	Mon May 22 09:50:54 2000
@@ -1,4 +1,4 @@
-/* $Id: oplib.h,v 1.12 1999/11/19 05:53:12 davem Exp $
+/* $Id: oplib.h,v 1.13 2000/05/09 17:40:15 davem Exp $
  * oplib.h:  Describes the interface and available routines in the
  *           Linux Prom library.
  *
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h
--- v2.3.99-pre8/linux/include/asm-sparc64/processor.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc64/processor.h	Mon May 22 09:50:55 2000
@@ -1,4 +1,4 @@
-/* $Id: processor.h,v 1.63 2000/03/27 10:38:57 davem Exp $
+/* $Id: processor.h,v 1.64 2000/05/09 17:40:15 davem Exp $
  * include/asm-sparc64/processor.h
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h
--- v2.3.99-pre8/linux/include/asm-sparc64/system.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc64/system.h	Mon May 22 09:50:55 2000
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.58 2000/05/05 18:47:41 davem Exp $ */
+/* $Id: system.h,v 1.59 2000/05/09 17:40:15 davem Exp $ */
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/timer.h linux/include/asm-sparc64/timer.h
--- v2.3.99-pre8/linux/include/asm-sparc64/timer.h	Thu May 11 15:30:08 2000
+++ linux/include/asm-sparc64/timer.h	Mon May 22 09:50:55 2000
@@ -1,4 +1,4 @@
-/* $Id: timer.h,v 1.2 1998/03/15 17:23:52 ecd Exp $
+/* $Id: timer.h,v 1.3 2000/05/09 17:40:15 davem Exp $
  * timer.h: System timer definitions for sun5.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/asm-sparc64/unistd.h linux/include/asm-sparc64/unistd.h
--- v2.3.99-pre8/linux/include/asm-sparc64/unistd.h	Tue Feb  1 01:35:44 2000
+++ linux/include/asm-sparc64/unistd.h	Mon May 22 09:50:55 2000
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.42 2000/01/29 17:57:26 jj Exp $ */
+/* $Id: unistd.h,v 1.44 2000/05/16 16:42:33 jj Exp $ */
 #ifndef _SPARC64_UNISTD_H
 #define _SPARC64_UNISTD_H
 
@@ -246,7 +246,9 @@
 #define __NR_setfsuid           228 /* Linux Specific                              */
 #define __NR_setfsgid           229 /* Linux Specific                              */
 #define __NR__newselect         230 /* Linux Specific                              */
-#define __NR_time               231 /* Linux Specific                              */
+#ifdef __KERNEL__
+#define __NR_time		231 /* Linux sparc32                               */
+#endif
 /* #define __NR_oldstat         232    Linux Specific                              */
 #define __NR_stime              233 /* Linux Specific                              */
 /* #define __NR_oldfstat        234    Linux Specific                              */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/coda.h linux/include/linux/coda.h
--- v2.3.99-pre8/linux/include/linux/coda.h	Thu Feb 10 17:11:21 2000
+++ linux/include/linux/coda.h	Sun May 21 20:55:06 2000
@@ -61,8 +61,9 @@
 
 
 
-/* Catch new _KERNEL defn for NetBSD */
-#ifdef __NetBSD__
+/* Catch new _KERNEL defn for NetBSD and DJGPP/__CYGWIN32__ */
+#if defined(__NetBSD__) || \
+  ((defined(DJGPP) || defined(__CYGWIN32__)) && !defined(KERNEL))
 #include <sys/types.h>
 #endif 
 
@@ -91,7 +92,6 @@
         long       ts_nsec;
 };
 #else  /* DJGPP but not KERNEL */
-#include <sys/types.h>
 #include <sys/time.h>
 typedef unsigned long long u_quad_t;
 #endif /* !KERNEL */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/dcache.h linux/include/linux/dcache.h
--- v2.3.99-pre8/linux/include/linux/dcache.h	Thu May 11 15:30:08 2000
+++ linux/include/linux/dcache.h	Tue May 23 14:18:47 2000
@@ -80,7 +80,7 @@
 	int (*d_revalidate)(struct dentry *, int);
 	int (*d_hash) (struct dentry *, struct qstr *);
 	int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
-	void (*d_delete)(struct dentry *);
+	int (*d_delete)(struct dentry *);
 	void (*d_release)(struct dentry *);
 	void (*d_iput)(struct dentry *, struct inode *);
 };
@@ -160,8 +160,11 @@
 /* only used at mount-time */
 extern struct dentry * d_alloc_root(struct inode *);
 
-/* test whether root is busy without destroying dcache */
-extern int d_active_refs(struct dentry *);
+/* <clickety>-<click> the ramfs-type tree */
+extern void d_genocide(struct dentry *);
+
+extern struct dentry *d_find_alias(struct inode *);
+extern void d_prune_aliases(struct inode *);
 
 /* test whether we have any submounts in a subdir tree */
 extern int have_submounts(struct dentry *);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/elevator.h linux/include/linux/elevator.h
--- v2.3.99-pre8/linux/include/linux/elevator.h	Tue Mar 14 19:10:40 2000
+++ linux/include/linux/elevator.h	Sat May 20 11:36:59 2000
@@ -22,6 +22,8 @@
 	int read_pendings;
 
 	elevator_fn * elevator_fn;
+
+	unsigned int queue_ID;
 };
 
 #define ELEVATOR_DEFAULTS				\
@@ -40,14 +42,14 @@
 
 
 typedef struct blkelv_ioctl_arg_s {
-	void * queue_ID;
+	int queue_ID;
 	int read_latency;
 	int write_latency;
 	int max_bomb_segments;
 } blkelv_ioctl_arg_t;
 
-#define BLKELVGET   _IO(0x12,106)
-#define BLKELVSET   _IO(0x12,107)
+#define BLKELVGET   _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t))
+#define BLKELVSET   _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))
 
 extern int blkelvget_ioctl(elevator_t *, blkelv_ioctl_arg_t *);
 extern int blkelvset_ioctl(elevator_t *, const blkelv_ioctl_arg_t *);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.3.99-pre8/linux/include/linux/fb.h	Fri May 12 14:18:56 2000
+++ linux/include/linux/fb.h	Sat May 20 11:32:08 2000
@@ -25,6 +25,8 @@
 #define FBIOPUT_CON2FBMAP	0x4610
 #define FBIOBLANK		0x4611		/* arg: 0 or vesa level + 1 */
 #define FBIOGET_VBLANK		_IOR('F', 0x12, struct fb_vblank)
+#define FBIO_ALLOC              0x4613
+#define FBIO_FREE               0x4614
 
 #define FB_TYPE_PACKED_PIXELS		0	/* Packed Pixels	*/
 #define FB_TYPE_PLANES			1	/* Non interleaved planes */
@@ -85,6 +87,7 @@
 #define FB_ACCEL_IGS_CYBER2000	33	/* CyberPro 2000		*/
 #define FB_ACCEL_IGS_CYBER2010	34	/* CyberPro 2010		*/
 #define FB_ACCEL_IGS_CYBER5000	35	/* CyberPro 5000		*/
+#define FB_ACCEL_SIS_GLAMOUR    36	/* SiS 300/630/540              */
 
 struct fb_fix_screeninfo {
 	char id[16];			/* identification string eg "TT Builtin" */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.3.99-pre8/linux/include/linux/fs.h	Thu May 11 15:30:08 2000
+++ linux/include/linux/fs.h	Tue May 23 14:18:48 2000
@@ -165,8 +165,8 @@
 #define BLKSSZGET  _IO(0x12,104)/* get block device sector size */
 #if 0
 #define BLKPG      _IO(0x12,105)/* See blkpg.h */
-#define BLKELVGET   _IO(0x12,106)/* elevator get */
-#define BLKELVSET   _IO(0x12,107)/* elevator set */
+#define BLKELVGET  _IOR(0x12,106,sizeof(blkelv_ioctl_arg_t))/* elevator get */
+#define BLKELVSET  _IOW(0x12,107,sizeof(blkelv_ioctl_arg_t))/* elevator set */
 /* This was here just to show that the number is taken -
    probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */
 #endif
@@ -794,6 +794,8 @@
 extern struct vfsmount *kern_mount(struct file_system_type *);
 extern void kern_umount(struct vfsmount *);
 extern int may_umount(struct vfsmount *);
+extern long do_mount(char *, char *, char *, unsigned long, void *);
+
 
 extern int vfs_statfs(struct super_block *, struct statfs *);
 
@@ -900,7 +902,7 @@
 
 extern int fs_may_remount_ro(struct super_block *);
 
-extern int try_to_free_buffers(struct page *);
+extern int try_to_free_buffers(struct page *, int);
 extern void refile_buffer(struct buffer_head * buf);
 
 #define BUF_CLEAN	0
@@ -1116,6 +1118,7 @@
 extern struct inode_operations page_symlink_inode_operations;
 
 extern int vfs_readdir(struct file *, filldir_t, void *);
+extern int dcache_readdir(struct file *, void *, filldir_t);
 
 extern struct super_block *get_super(kdev_t);
 struct super_block *get_empty_super(void);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/hdreg.h linux/include/linux/hdreg.h
--- v2.3.99-pre8/linux/include/linux/hdreg.h	Wed Apr 26 16:34:09 2000
+++ linux/include/linux/hdreg.h	Tue May 23 14:18:47 2000
@@ -181,6 +181,8 @@
 #define HDIO_GET_DMA		0x030b	/* get use-dma flag */
 #define HDIO_GET_NICE		0x030c	/* get nice flags */
 #define HDIO_GET_IDENTITY	0x030d	/* get IDE identification info */
+#define HDIO_DRIVE_CMD_AEB	0x031e
+#define HDIO_DRIVE_TASK		0x031e
 #define HDIO_DRIVE_CMD		0x031f	/* execute a special drive command */
 
 /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */
@@ -207,7 +209,6 @@
 #define HDIO_GETGEO_BIG		0x0330	/* */
 #define HDIO_GETGEO_BIG_RAW	0x0331	/* */
 
-
 #define __NEW_HD_DRIVE_ID
 /* structure returned by HDIO_GET_IDENTITY, as per ANSI ATA2 rev.2f spec */
 struct hd_driveid {
@@ -272,7 +273,7 @@
 	unsigned short	CurAPMvalues;	/* current APM values */
 	unsigned short	word92;		/* reserved (word 92) */
 	unsigned short	hw_config;	/* hardware config */
-	unsigned short  words94_125[31];/* reserved words 94-125 */
+	unsigned short  words94_125[32];/* reserved words 94-125 */
 	unsigned short	last_lun;	/* reserved (word 126) */
 	unsigned short	word127;	/* reserved (word 127) */
 	unsigned short	dlf;		/* device lock function
@@ -293,8 +294,10 @@
 					 * 1	read-look-ahead
 					 * 0	write cache
 					 */
-	unsigned short	words130_159[30];/* reserved vendor words 130-159 */
-	unsigned short	words160_255[96];/* reserved words 160-255 */
+	unsigned short	words130_155[26];/* reserved vendor words 130-155 */
+	unsigned short	word156;
+	unsigned short	words157_159[3];/* reserved vendor words 157-159 */
+	unsigned short	words160_255[95];/* reserved words 160-255 */
 };
 
 /*
@@ -313,10 +316,6 @@
  * These routines are used for kernel command line parameters from main.c:
  */
 #include <linux/config.h>
-
-#ifdef CONFIG_BLK_DEV_HD
-void hd_setup(char *, int *);
-#endif	/* CONFIG_BLK_DEV_HD */
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 int ide_register(int io_port, int ctl_port, int irq);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/hdsmart.h linux/include/linux/hdsmart.h
--- v2.3.99-pre8/linux/include/linux/hdsmart.h	Wed Apr 26 16:34:09 2000
+++ linux/include/linux/hdsmart.h	Mon May 15 11:03:48 2000
@@ -17,123 +17,108 @@
 #ifndef _LINUX_HDSMART_H
 #define _LINUX_HDSMART_H
 
+#define OFFLINE_FULL_SCAN		0
+#define SHORT_SELF_TEST			1
+#define EXTEND_SELF_TEST		2
+#define SHORT_CAPTIVE_SELF_TEST		129
+#define EXTEND_CAPTIVE_SELF_TEST	130
+
 /* smart_attribute is the vendor specific in SFF-8035 spec */
-struct ata_smart_attribute {
-	unsigned char				id;
-	unsigned short				status_flag;
-	unsigned char				normalized;
-	unsigned char				worse_normal;
-	unsigned char				raw[6];
-	unsigned char				reserv;
-} __attribute__ ((packed));
+typedef struct ata_smart_attribute_s {
+	unsigned char			id;
+	unsigned short			status_flag;
+	unsigned char			normalized;
+	unsigned char			worse_normal;
+	unsigned char			raw[6];
+	unsigned char			reserv;
+} __attribute__ ((packed)) ata_smart_attribute_t;
 
 /* smart_values is format of the read drive Atrribute command */
-struct ata_smart_values {
-	unsigned short				revnumber;
-	struct ata_smart_attribute		vendor_attributes [30];
-        unsigned char				offline_data_collection_status;
-        unsigned char				self_test_exec_status;
-	unsigned short				total_time_to_complete_off_line;
-	unsigned char				vendor_specific_366;
-	unsigned char				offline_data_collection_capability;
-	unsigned short				smart_capability;
-	unsigned char				errorlog_capability;
-	unsigned char				vendor_specific_371;
-	unsigned char				short_test_completion_time;
-	unsigned char				extend_test_completion_time;
-	unsigned char				reserved_374_385 [12];
-	unsigned char				vendor_specific_386_509 [125];
-	unsigned char				chksum;
-} __attribute__ ((packed));
+typedef struct ata_smart_values_s {
+	unsigned short			revnumber;
+	ata_smart_attribute_t		vendor_attributes [30];
+        unsigned char			offline_data_collection_status;
+        unsigned char			self_test_exec_status;
+	unsigned short			total_time_to_complete_off_line;
+	unsigned char			vendor_specific_366;
+	unsigned char			offline_data_collection_capability;
+	unsigned short			smart_capability;
+	unsigned char			errorlog_capability;
+	unsigned char			vendor_specific_371;
+	unsigned char			short_test_completion_time;
+	unsigned char			extend_test_completion_time;
+	unsigned char			reserved_374_385 [12];
+	unsigned char			vendor_specific_386_509 [125];
+	unsigned char			chksum;
+} __attribute__ ((packed)) ata_smart_values_t;
 
 /* Smart Threshold data structures */
 /* Vendor attribute of SMART Threshold */
-struct ata_smart_threshold_entry {
-	unsigned char				id;
-	unsigned char				normalized_threshold;
-	unsigned char				reserved[10];
-} __attribute__ ((packed));
+typedef struct ata_smart_threshold_entry_s {
+	unsigned char			id;
+	unsigned char			normalized_threshold;
+	unsigned char			reserved[10];
+} __attribute__ ((packed)) ata_smart_threshold_entry_t;
 
 /* Format of Read SMART THreshold Command */
-struct ata_smart_thresholds {
-	unsigned short				revnumber;
-	struct ata_smart_threshold_entry	thres_entries[30];
-	unsigned char				reserved[149];
-	unsigned char				chksum;
-} __attribute__ ((packed));
-
-struct ata_smart_errorlog_command_struct {
-	unsigned char				devicecontrolreg;
-	unsigned char				featuresreg;
-	unsigned char				sector_count;
-	unsigned char				sector_number;
-	unsigned char				cylinder_low;
-	unsigned char				cylinder_high;
-	unsigned char				drive_head;
-	unsigned char				commandreg;
-	unsigned int				timestamp;
-} __attribute__ ((packed));
-
-struct ata_smart_errorlog_error_struct {
-	unsigned char				error_condition;
-	unsigned char				extended_error[14];
-	unsigned char				state;
-	unsigned short				timestamp;
-} __attribute__ ((packed));
-
-struct ata_smart_errorlog_struct {
-	struct ata_smart_errorlog_command_struct	commands[6];
-	struct ata_smart_errorlog_error_struct		error_struct;
-}  __attribute__ ((packed));
-
-struct ata_smart_errorlog {
-	unsigned char				revnumber;
-	unsigned char				error_log_pointer;
-	struct ata_smart_errorlog_struct	errorlog_struct[5];
-	unsigned short				ata_error_count;
-	unsigned short				non_fatal_count;
-	unsigned short				drive_timeout_count;
-	unsigned char				reserved[53];
-} __attribute__ ((packed));
-
-struct ata_smart_selftestlog_struct {
-	unsigned char				selftestnumber;
-	unsigned char				selfteststatus;
-	unsigned short				timestamp;
-	unsigned char				selftestfailurecheckpoint;
-	unsigned int				lbafirstfailure;
-	unsigned char				vendorspecific[15];
-} __attribute__ ((packed));
-
-struct ata_smart_selftestlog {
-	unsigned short				revnumber;
-	struct ata_smart_selftestlog_struct	selftest_struct[21];
-	unsigned char				vendorspecific[2];
-	unsigned char				mostrecenttest;
-	unsigned char				resevered[2];
-	unsigned char				chksum;
-} __attribute__ ((packed));
-
-#if !defined(__KERNEL__) || defined(_IDE_DISK_C)
-/* smartctl version number */
-#define VERSION_MAJOR           		1
-#define VERSION_MINOR           		2
-
-/* Number of ata device to scan */
-int numdevices;
-
-/* how often SMART is checks in seconds */
-int checktime = 1800;
-
-typedef struct atadevices_s {
-	int					fd;
-	char					devicename[14];
-	int					selftest;
-	struct hd_driveid			drive;
-	struct ata_smart_values			smartval;
-	struct ata_smart_thresholds		smartthres;
-} atadevices_t;
-
-#endif /* !defined(__KERNEL__) || defined(_IDE_DISK_C) */
+typedef struct ata_smart_thresholds_s {
+	unsigned short			revnumber;
+	ata_smart_threshold_entry_t	thres_entries[30];
+	unsigned char			reserved[149];
+	unsigned char			chksum;
+} __attribute__ ((packed)) ata_smart_thresholds_t;
+
+typedef struct ata_smart_errorlog_command_struct_s {
+	unsigned char			devicecontrolreg;
+	unsigned char			featuresreg;
+	unsigned char			sector_count;
+	unsigned char			sector_number;
+	unsigned char			cylinder_low;
+	unsigned char			cylinder_high;
+	unsigned char			drive_head;
+	unsigned char			commandreg;
+	unsigned int			timestamp;
+} __attribute__ ((packed)) ata_smart_errorlog_command_struct_t;
+
+typedef struct ata_smart_errorlog_error_struct_s {
+	unsigned char			error_condition;
+	unsigned char			extended_error[14];
+	unsigned char			state;
+	unsigned short			timestamp;
+} __attribute__ ((packed)) ata_smart_errorlog_error_struct_t;
+
+typedef struct ata_smart_errorlog_struct_s {
+	ata_smart_errorlog_command_struct_t	commands[6];
+	ata_smart_errorlog_error_struct_t	error_struct;
+} __attribute__ ((packed)) ata_smart_errorlog_struct_t;
+
+typedef struct ata_smart_errorlog_s {
+	unsigned char			revnumber;
+	unsigned char			error_log_pointer;
+	ata_smart_errorlog_struct_t	errorlog_struct[5];
+	unsigned short			ata_error_count;
+	unsigned short			non_fatal_count;
+	unsigned short			drive_timeout_count;
+	unsigned char			reserved[53];
+	unsigned char			chksum;
+} __attribute__ ((packed)) ata_smart_errorlog_t;
+
+typedef struct ata_smart_selftestlog_struct_s {
+	unsigned char			selftestnumber;
+	unsigned char			selfteststatus;
+	unsigned short			timestamp;
+	unsigned char			selftestfailurecheckpoint;
+	unsigned int			lbafirstfailure;
+	unsigned char			vendorspecific[15];
+} __attribute__ ((packed)) ata_smart_selftestlog_struct_t;
+
+typedef struct ata_smart_selftestlog_s {
+	unsigned short			revnumber;
+	ata_smart_selftestlog_struct_t	selftest_struct[21];
+	unsigned char			vendorspecific[2];
+	unsigned char			mostrecenttest;
+	unsigned char			resevered[2];
+	unsigned char			chksum;
+} __attribute__ ((packed)) ata_smart_selftestlog_t;
 
 #endif	/* _LINUX_HDSMART_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/ide.h linux/include/linux/ide.h
--- v2.3.99-pre8/linux/include/linux/ide.h	Wed Apr 26 16:34:09 2000
+++ linux/include/linux/ide.h	Tue May 23 14:20:23 2000
@@ -64,6 +64,12 @@
 #define IDE_DRIVE_CMD		99	/* (magic) undef to reduce kernel size*/
 
 /*
+ * IDE_DRIVE_TASK is used to implement many features needed for raw tasks
+ */
+#define IDE_DRIVE_TASK		98
+#define IDE_DRIVE_CMD_AEB	98
+
+/*
  *  "No user-serviceable parts" beyond this point  :)
  *****************************************************************************/
 
@@ -302,6 +308,10 @@
 	char		driver_req[10];	/* requests specific driver */
 	int		last_lun;	/* last logical unit */
 	int		forced_lun;	/* if hdxlun was given at boot */
+	int		lun;		/* logical unit */
+	byte		init_speed;	/* transfer rate set at boot */
+	byte		current_speed;	/* current transfer rate set */
+	byte		dn;		/* now wide spread use */
 } ide_drive_t;
 
 /*
@@ -336,7 +346,8 @@
  * support all possible PIO settings.  They may silently ignore
  * or round values as they see fit.
  */
-typedef void (ide_tuneproc_t)(ide_drive_t *, byte);
+typedef void (ide_tuneproc_t) (ide_drive_t *, byte);
+typedef int (ide_speedproc_t) (ide_drive_t *, byte);
 
 /*
  * This is used to provide support for strange interfaces
@@ -374,6 +385,7 @@
 	ide_drive_t	drives[MAX_DRIVES];	/* drive info */
 	struct gendisk	*gd;		/* gendisk structure */
 	ide_tuneproc_t	*tuneproc;	/* routine to tune PIO mode for drives */
+	ide_speedproc_t	*speedproc;	/* routine to retune DMA modes for drives */
 	ide_selectproc_t *selectproc;	/* tweaks hardware to select drive */
 	ide_resetproc_t	*resetproc;	/* routine to reset controller after a disk reset */
 	ide_dmaproc_t	*dmaproc;	/* dma read/write/abort routine */
@@ -409,6 +421,7 @@
 	unsigned long	last_time;	/* time when previous rq was done */
 #endif
 	byte		straight8;	/* Alan's straight 8 check */
+	void		*hwif_data;	/* extra hwif data */
 } ide_hwif_t;
 
 /*
@@ -728,14 +741,16 @@
  * Issue ATA command and wait for completion.
  */
 int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf);
+int ide_wait_cmd_task (ide_drive_t *drive, byte *buf);
 
 void ide_delay_50ms (void);
 int system_bus_clock(void);
 
+byte ide_auto_reduce_xfer (ide_drive_t *drive);
 int ide_driveid_update (ide_drive_t *drive);
-int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature);
+int ide_ata66_check (ide_drive_t *drive, byte cmd, byte nsect, byte feature);
 int ide_config_drive_speed (ide_drive_t *drive, byte speed);
-int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature);
+int set_transfer (ide_drive_t *drive, byte cmd, byte nsect, byte feature);
 
 /*
  * ide_system_bus_speed() returns what we think is the system VESA/PCI
@@ -769,37 +784,10 @@
  */
 int drive_is_flashcard (ide_drive_t *drive);
 
-int  ide_spin_wait_hwgroup(ide_drive_t *drive, unsigned long *flags);
+int ide_spin_wait_hwgroup (ide_drive_t *drive);
 void ide_timer_expiry (unsigned long data);
 void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
-void do_ide0_request (request_queue_t * q);
-#if MAX_HWIFS > 1
-void do_ide1_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 2
-void do_ide2_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 3
-void do_ide3_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 4
-void do_ide4_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 5
-void do_ide5_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 6
-void do_ide6_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 7
-void do_ide7_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 8
-void do_ide8_request (request_queue_t * q);
-#endif
-#if MAX_HWIFS > 9
-void do_ide9_request (request_queue_t * q);
-#endif
+void do_ide_request (request_queue_t * q);
 void ide_init_subdrivers (void);
 
 #ifndef _IDE_C
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/if_pppox.h linux/include/linux/if_pppox.h
--- v2.3.99-pre8/linux/include/linux/if_pppox.h	Thu May 11 15:30:08 2000
+++ linux/include/linux/if_pppox.h	Tue May 23 14:18:50 2000
@@ -16,12 +16,13 @@
 #ifndef __LINUX_IF_PPPOX_H
 #define __LINUX_IF_PPPOX_H
 
-#include <linux/if_ether.h>
-#include <linux/if.h>
 
 #include <asm/types.h>
 #include <asm/byteorder.h>
+
 #ifdef  __KERNEL__
+#include <linux/if_ether.h>
+#include <linux/if.h>
 #include <linux/netdevice.h>
 #include <linux/sched.h>
 #include <asm/semaphore.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/lvm.h linux/include/linux/lvm.h
--- v2.3.99-pre8/linux/include/linux/lvm.h	Sun Feb 20 21:12:40 2000
+++ linux/include/linux/lvm.h	Tue May 23 14:19:01 2000
@@ -83,11 +83,13 @@
 #include <linux/version.h>
 
 #ifndef __KERNEL__
+#define ____NOT_KERNEL____
 #define __KERNEL__
+#endif
 #include <linux/kdev_t.h>
+#ifdef ____NOT_KERNEL____
+#undef ____NOT_KERNEL____
 #undef __KERNEL__
-#else
-#include <linux/kdev_t.h>
 #endif
 
 #include <linux/major.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/mount.h linux/include/linux/mount.h
--- v2.3.99-pre8/linux/include/linux/mount.h	Thu May 11 15:30:08 2000
+++ linux/include/linux/mount.h	Sun May 21 20:34:37 2000
@@ -28,6 +28,7 @@
   char *mnt_devname;			/* Name of device e.g. /dev/dsk/hda1 */
   char *mnt_dirname;			/* Name of directory mounted on */
 	struct list_head mnt_list;
+	uid_t mnt_owner;
 };
 
 static inline struct vfsmount *mntget(struct vfsmount *mnt)
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/netfilter_ipv6/ip6_tables.h linux/include/linux/netfilter_ipv6/ip6_tables.h
--- v2.3.99-pre8/linux/include/linux/netfilter_ipv6/ip6_tables.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/netfilter_ipv6/ip6_tables.h	Mon May 22 09:50:55 2000
@@ -0,0 +1,452 @@
+/*
+ * 25-Jul-1998 Major changes to allow for ip chain table
+ *
+ * 3-Jan-2000 Named tables to allow packet selection for different uses.
+ */
+
+/*
+ * 	Format of an IP6 firewall descriptor
+ *
+ * 	src, dst, src_mask, dst_mask are always stored in network byte order.
+ * 	flags are stored in host byte order (of course).
+ * 	Port numbers are stored in HOST byte order.
+ */
+
+#ifndef _IP6_TABLES_H
+#define _IP6_TABLES_H
+
+#ifdef __KERNEL__
+#include <linux/if.h>
+#include <linux/types.h>
+#include <linux/in6.h>
+#include <linux/ipv6.h>
+#include <linux/skbuff.h>
+#endif
+#include <linux/netfilter_ipv6.h>
+
+#define IP6T_FUNCTION_MAXNAMELEN 30
+#define IP6T_TABLE_MAXNAMELEN 32
+
+/* Yes, Virginia, you have to zero the padding. */
+struct ip6t_ip6 {
+	/* Source and destination IP6 addr */
+	struct in6_addr src, dst;		
+	/* Mask for src and dest IP6 addr */
+	struct in6_addr smsk, dmsk;
+	char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
+	unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
+
+	/* ARGH, HopByHop uses 0, so can't do 0 = ANY,
+	   instead IP6T_F_NOPROTO must be set */
+	u_int16_t proto;
+	/* TOS to match iff flags & IP6T_F_TOS */
+	u_int8_t tos;
+
+	/* Flags word */
+	u_int8_t flags;
+	/* Inverse flags */
+	u_int8_t invflags;
+};
+
+/* FIXME: If alignment in kernel different from userspace? --RR */
+struct ip6t_entry_match
+{
+	union {
+		struct {
+			u_int16_t match_size;
+
+			/* Used by userspace */
+			char name[IP6T_FUNCTION_MAXNAMELEN];
+		} user;
+		struct {
+			u_int16_t match_size;
+
+			/* Used inside the kernel */
+			struct ip6t_match *match;
+		} kernel;
+
+		/* Total length */
+		u_int16_t match_size;
+	} u;
+
+	unsigned char data[0];
+};
+
+struct ip6t_entry_target
+{
+	union {
+		struct {
+			u_int16_t target_size;
+
+			/* Used by userspace */
+			char name[IP6T_FUNCTION_MAXNAMELEN];
+		} user;
+		struct {
+			u_int16_t target_size;
+
+			/* Used inside the kernel */
+			struct ip6t_target *target;
+		} kernel;
+
+		/* Total length */
+		u_int16_t target_size;
+	} u;
+
+	unsigned char data[0];
+};
+
+struct ip6t_standard_target
+{
+	struct ip6t_entry_target target;
+	int verdict;
+};
+
+struct ip6t_counters
+{
+	u_int64_t pcnt, bcnt;			/* Packet and byte counters */
+};
+
+/* Values for "flag" field in struct ip6t_ip6 (general ip6 structure). */
+#define IP6T_F_PROTO		0x01	/* Set if rule cares about upper 
+					   protocols */
+#define IP6T_F_TOS		0x02	/* Match the TOS. */
+#define IP6T_F_MASK		0x03	/* All possible flag bits mask. */
+
+/* Values for "inv" field in struct ip6t_ip6. */
+#define IP6T_INV_VIA_IN		0x01	/* Invert the sense of IN IFACE. */
+#define IP6T_INV_VIA_OUT		0x02	/* Invert the sense of OUT IFACE */
+#define IP6T_INV_TOS		0x04	/* Invert the sense of TOS. */
+#define IP6T_INV_SRCIP		0x08	/* Invert the sense of SRC IP. */
+#define IP6T_INV_DSTIP		0x10	/* Invert the sense of DST OP. */
+#define IP6T_INV_FRAG		0x20	/* Invert the sense of FRAG. */
+#define IP6T_INV_PROTO		0x40	/* Invert the sense of PROTO. */
+#define IP6T_INV_MASK		0x7F	/* All possible flag bits mask. */
+
+/* This structure defines each of the firewall rules.  Consists of 3
+   parts which are 1) general IP header stuff 2) match specific
+   stuff 3) the target to perform if the rule matches */
+struct ip6t_entry
+{
+	struct ip6t_ip6 ipv6;
+
+	/* Mark with fields that we care about. */
+	unsigned int nfcache;
+
+	/* Size of ipt_entry + matches */
+	u_int16_t target_offset;
+	/* Size of ipt_entry + matches + target */
+	u_int16_t next_offset;
+
+	/* Back pointer */
+	unsigned int comefrom;
+
+	/* Packet and byte counters. */
+	struct ip6t_counters counters;
+
+	/* The matches (if any), then the target. */
+	unsigned char elems[0];
+};
+
+/*
+ * New IP firewall options for [gs]etsockopt at the RAW IP level.
+ * Unlike BSD Linux inherits IP options so you don't have to use
+ * a raw socket for this. Instead we check rights in the calls. */
+#define IP6T_BASE_CTL			64	/* base for firewall socket options */
+
+#define IP6T_SO_SET_REPLACE		(IP6T_BASE_CTL)
+#define IP6T_SO_SET_ADD_COUNTERS	(IP6T_BASE_CTL + 1)
+#define IP6T_SO_SET_MAX			IP6T_SO_SET_ADD_COUNTERS
+
+#define IP6T_SO_GET_INFO		(IP6T_BASE_CTL)
+#define IP6T_SO_GET_ENTRIES		(IP6T_BASE_CTL + 1)
+#define IP6T_SO_GET_MAX			IP6T_SO_GET_ENTRIES
+
+/* CONTINUE verdict for targets */
+#define IP6T_CONTINUE 0xFFFFFFFF
+
+/* For standard target */
+#define IP6T_RETURN (-NF_MAX_VERDICT - 1)
+
+/* TCP matching stuff */
+struct ip6t_tcp
+{
+	u_int16_t spts[2];			/* Source port range. */
+	u_int16_t dpts[2];			/* Destination port range. */
+	u_int8_t option;			/* TCP Option iff non-zero*/
+	u_int8_t flg_mask;			/* TCP flags mask byte */
+	u_int8_t flg_cmp;			/* TCP flags compare byte */
+	u_int8_t invflags;			/* Inverse flags */
+};
+
+/* Values for "inv" field in struct ipt_tcp. */
+#define IP6T_TCP_INV_SRCPT	0x01	/* Invert the sense of source ports. */
+#define IP6T_TCP_INV_DSTPT	0x02	/* Invert the sense of dest ports. */
+#define IP6T_TCP_INV_FLAGS	0x04	/* Invert the sense of TCP flags. */
+#define IP6T_TCP_INV_OPTION	0x08	/* Invert the sense of option test. */
+#define IP6T_TCP_INV_MASK	0x0F	/* All possible flags. */
+
+/* UDP matching stuff */
+struct ip6t_udp
+{
+	u_int16_t spts[2];			/* Source port range. */
+	u_int16_t dpts[2];			/* Destination port range. */
+	u_int8_t invflags;			/* Inverse flags */
+};
+
+/* Values for "invflags" field in struct ipt_udp. */
+#define IP6T_UDP_INV_SRCPT	0x01	/* Invert the sense of source ports. */
+#define IP6T_UDP_INV_DSTPT	0x02	/* Invert the sense of dest ports. */
+#define IP6T_UDP_INV_MASK	0x03	/* All possible flags. */
+
+/* ICMP matching stuff */
+struct ip6t_icmp
+{
+	u_int8_t type;				/* type to match */
+	u_int8_t code[2];			/* range of code */
+	u_int8_t invflags;			/* Inverse flags */
+};
+
+/* Values for "inv" field for struct ipt_icmp. */
+#define IP6T_ICMP_INV	0x01	/* Invert the sense of type/code test */
+
+/* The argument to IP6T_SO_GET_INFO */
+struct ip6t_getinfo
+{
+	/* Which table: caller fills this in. */
+	char name[IP6T_TABLE_MAXNAMELEN];
+
+	/* Kernel fills these in. */
+	/* Which hook entry points are valid: bitmask */
+	unsigned int valid_hooks;
+
+	/* Hook entry points: one per netfilter hook. */
+	unsigned int hook_entry[NF_IP6_NUMHOOKS];
+
+	/* Underflow points. */
+	unsigned int underflow[NF_IP6_NUMHOOKS];
+
+	/* Number of entries */
+	unsigned int num_entries;
+
+	/* Size of entries. */
+	unsigned int size;
+};
+
+/* The argument to IP6T_SO_SET_REPLACE. */
+struct ip6t_replace
+{
+	/* Which table. */
+	char name[IP6T_TABLE_MAXNAMELEN];
+
+	/* Which hook entry points are valid: bitmask.  You can't
+           change this. */
+	unsigned int valid_hooks;
+
+	/* Number of entries */
+	unsigned int num_entries;
+
+	/* Total size of new entries */
+	unsigned int size;
+
+	/* Hook entry points. */
+	unsigned int hook_entry[NF_IP6_NUMHOOKS];
+
+	/* Underflow points. */
+	unsigned int underflow[NF_IP6_NUMHOOKS];
+
+	/* Information about old entries: */
+	/* Number of counters (must be equal to current number of entries). */
+	unsigned int num_counters;
+	/* The old entries' counters. */
+	struct ip6t_counters *counters;
+
+	/* The entries (hang off end: not really an array). */
+	struct ip6t_entry entries[0];
+};
+
+/* The argument to IP6T_SO_ADD_COUNTERS. */
+struct ip6t_counters_info
+{
+	/* Which table. */
+	char name[IP6T_TABLE_MAXNAMELEN];
+
+	unsigned int num_counters;
+
+	/* The counters (actually `number' of these). */
+	struct ip6t_counters counters[0];
+};
+
+/* The argument to IP6T_SO_GET_ENTRIES. */
+struct ip6t_get_entries
+{
+	/* Which table: user fills this in. */
+	char name[IP6T_TABLE_MAXNAMELEN];
+
+	/* User fills this in: total entry size. */
+	unsigned int size;
+
+	/* The entries. */
+	unsigned char entries[0];
+};
+
+/* Standard return verdict, or do jump. */
+#define IP6T_STANDARD_TARGET ""
+/* Error verdict. */
+#define IP6T_ERROR_TARGET "ERROR"
+
+/* Helper functions */
+extern __inline__ struct ip6t_entry_target *
+ip6t_get_target(struct ip6t_entry *e)
+{
+	return (void *)e + e->target_offset;
+}
+
+/* fn returns 0 to continue iteration */
+#define IP6T_MATCH_ITERATE(e, fn, args...)	\
+({						\
+	unsigned int __i;			\
+	int __ret = 0;				\
+	struct ip6t_entry_match *__m;		\
+						\
+	for (__i = sizeof(struct ip6t_entry);	\
+	     __i < (e)->target_offset;		\
+	     __i += __m->u.match_size) {	\
+		__m = (void *)(e) + __i;	\
+						\
+		__ret = fn(__m , ## args);	\
+		if (__ret != 0)			\
+			break;			\
+	}					\
+	__ret;					\
+})
+
+/* fn returns 0 to continue iteration */
+#define IP6T_ENTRY_ITERATE(entries, size, fn, args...)		\
+({								\
+	unsigned int __i;					\
+	int __ret = 0;						\
+	struct ip6t_entry *__e;					\
+								\
+	for (__i = 0; __i < (size); __i += __e->next_offset) {	\
+		__e = (void *)(entries) + __i;			\
+								\
+		__ret = fn(__e , ## args);			\
+		if (__ret != 0)					\
+			break;					\
+	}							\
+	__ret;							\
+})
+
+/*
+ *	Main firewall chains definitions and global var's definitions.
+ */
+
+#ifdef __KERNEL__
+
+#include <linux/init.h>
+extern void ip6t_init(void) __init;
+
+struct ip6t_match
+{
+	struct list_head list;
+
+	const char name[IP6T_FUNCTION_MAXNAMELEN];
+
+	/* Return true or false: return FALSE and set *hotdrop = 1 to
+           force immediate packet drop. */
+	int (*match)(const struct sk_buff *skb,
+		     const struct net_device *in,
+		     const struct net_device *out,
+		     const void *matchinfo,
+		     int offset,
+		     const void *hdr,
+		     u_int16_t datalen,
+		     int *hotdrop);
+
+	/* Called when user tries to insert an entry of this type. */
+	/* Should return true or false. */
+	int (*checkentry)(const char *tablename,
+			  const struct ip6t_ip6 *ip,
+			  void *matchinfo,
+			  unsigned int matchinfosize,
+			  unsigned int hook_mask);
+
+	/* Called when entry of this type deleted. */
+	void (*destroy)(void *matchinfo, unsigned int matchinfosize);
+
+	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
+	struct module *me;
+};
+
+/* Registration hooks for targets. */
+struct ip6t_target
+{
+	struct list_head list;
+
+	const char name[IP6T_FUNCTION_MAXNAMELEN];
+
+	/* Returns verdict. */
+	unsigned int (*target)(struct sk_buff **pskb,
+			       unsigned int hooknum,
+			       const struct net_device *in,
+			       const struct net_device *out,
+			       const void *targinfo,
+			       void *userdata);
+
+	/* Called when user tries to insert an entry of this type:
+           hook_mask is a bitmask of hooks from which it can be
+           called. */
+	/* Should return true or false. */
+	int (*checkentry)(const char *tablename,
+			  const struct ip6t_entry *e,
+			  void *targinfo,
+			  unsigned int targinfosize,
+			  unsigned int hook_mask);
+
+	/* Called when entry of this type deleted. */
+	void (*destroy)(void *targinfo, unsigned int targinfosize);
+
+	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
+	struct module *me;
+};
+
+extern int ip6t_register_target(struct ip6t_target *target);
+extern void ip6t_unregister_target(struct ip6t_target *target);
+
+extern int ip6t_register_match(struct ip6t_match *match);
+extern void ip6t_unregister_match(struct ip6t_match *match);
+
+/* Furniture shopping... */
+struct ip6t_table
+{
+	struct list_head list;
+
+	/* A unique name... */
+	char name[IP6T_TABLE_MAXNAMELEN];
+
+	/* Seed table: copied in register_table */
+	struct ip6t_replace *table;
+
+	/* What hooks you will enter on */
+	unsigned int valid_hooks;
+
+	/* Lock for the curtain */
+	rwlock_t lock;
+
+	/* Man behind the curtain... */
+	struct ip6t_table_info *private;
+};
+
+extern int ip6t_register_table(struct ip6t_table *table);
+extern void ip6t_unregister_table(struct ip6t_table *table);
+extern unsigned int ip6t_do_table(struct sk_buff **pskb,
+				  unsigned int hook,
+				  const struct net_device *in,
+				  const struct net_device *out,
+				  struct ip6t_table *table,
+				  void *userdata);
+
+#define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
+
+#endif /*__KERNEL__*/
+#endif /* _IP6_TABLES_H */
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/netfilter_ipv6.h linux/include/linux/netfilter_ipv6.h
--- v2.3.99-pre8/linux/include/linux/netfilter_ipv6.h	Thu Mar  2 14:36:23 2000
+++ linux/include/linux/netfilter_ipv6.h	Mon May 22 09:50:55 2000
@@ -54,4 +54,14 @@
 #define NF_IP6_NUMHOOKS		5
 
 
+enum nf_ip_hook_priorities {
+	NF_IP6_PRI_FIRST = INT_MIN,
+	NF_IP6_PRI_CONNTRACK = -200,
+	NF_IP6_PRI_MANGLE = -150,
+	NF_IP6_PRI_NAT_DST = -100,
+	NF_IP6_PRI_FILTER = 0,
+	NF_IP6_PRI_NAT_SRC = 100,
+	NF_IP6_PRI_LAST = INT_MAX,
+};
+
 #endif /*__LINUX_IP6_NETFILTER_H*/
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.3.99-pre8/linux/include/linux/nfs_fs.h	Thu May 11 15:30:08 2000
+++ linux/include/linux/nfs_fs.h	Tue May 23 14:19:47 2000
@@ -15,6 +15,7 @@
 #include <linux/pagemap.h>
 
 #include <linux/sunrpc/debug.h>
+#include <linux/sunrpc/auth.h>
 
 #include <linux/nfs.h>
 #include <linux/nfs2.h>
@@ -98,7 +99,6 @@
 
 /* Inode Flags */
 #define NFS_USE_READDIRPLUS(inode)	((NFS_FLAGS(inode) & NFS_INO_ADVISE_RDPLUS) ? 1 : 0)
-#define NFS_MONOTONE_COOKIES(inode)	((NFS_SERVER(inode)->flags & NFS_NONMONOTONE_COOKIES) ? 0 : 1)
 
 /*
  * These are the default flags for swap requests
@@ -154,6 +154,17 @@
 extern struct inode_operations nfs_file_inode_operations;
 extern struct file_operations nfs_file_operations;
 extern struct address_space_operations nfs_file_aops;
+
+static __inline__ struct rpc_cred *
+nfs_file_cred(struct file *file)
+{
+	struct rpc_cred *cred = (struct rpc_cred *)(file->private_data);
+#ifdef RPC_DEBUG
+	if (cred && cred->cr_magic != RPCAUTH_CRED_MAGIC)
+		BUG();
+#endif
+	return cred;
+}
 
 /*
  * linux/fs/nfs/dir.c
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/nfs_mount.h linux/include/linux/nfs_mount.h
--- v2.3.99-pre8/linux/include/linux/nfs_mount.h	Tue Apr 11 15:09:25 2000
+++ linux/include/linux/nfs_mount.h	Tue May 23 14:19:27 2000
@@ -54,11 +54,4 @@
 #define NFS_MOUNT_NONLM		0x0200	/* 3 */
 #define NFS_MOUNT_FLAGMASK	0xFFFF
 
-/*
- * Private flags - not to be set by mount program
- */
-#ifdef __KERNEL__
-#define NFS_NONMONOTONE_COOKIES	0x00010000
-#endif /* __KERNEL__ */
- 
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/nfs_page.h linux/include/linux/nfs_page.h
--- v2.3.99-pre8/linux/include/linux/nfs_page.h	Wed Apr 26 16:34:09 2000
+++ linux/include/linux/nfs_page.h	Tue May 23 14:19:27 2000
@@ -40,7 +40,7 @@
 
 #define NFS_WBACK_BUSY(req)	((req)->wb_flags & PG_BUSY)
 
-extern	struct nfs_page *nfs_create_request(struct dentry *dentry,
+extern	struct nfs_page *nfs_create_request(struct file *file,
 					    struct page *page,
 					    unsigned int offset,
 					    unsigned int count);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/nfs_xdr.h linux/include/linux/nfs_xdr.h
--- v2.3.99-pre8/linux/include/linux/nfs_xdr.h	Tue Apr 11 15:09:25 2000
+++ linux/include/linux/nfs_xdr.h	Sat May 20 10:27:57 2000
@@ -106,7 +106,6 @@
  * Argument struct for decode_entry function
  */
 struct nfs_entry {
-	struct page *		page;
 	__u64			ino;
 	__u64			cookie,
 				prev_cookie;
@@ -115,8 +114,6 @@
 	int			eof;
 	struct nfs_fh		fh;
 	struct nfs_fattr	fattr;
-	unsigned long		offset,
-				prev;
 };
 
 /*
@@ -326,10 +323,10 @@
 			    struct nfs_fh *, struct nfs_fattr *);
 	int	(*access)  (struct dentry *, int , int);
 	int	(*readlink)(struct dentry *, void *, unsigned int);
-	int	(*read)    (struct dentry *, struct nfs_fattr *,
+	int	(*read)    (struct file *, struct nfs_fattr *,
 			    int, loff_t, unsigned int,
 			    void *buffer, int *eofp);
-	int	(*write)   (struct dentry *, struct nfs_fattr *,
+	int	(*write)   (struct file *, struct nfs_fattr *,
 			    int, loff_t, unsigned int,
 			    void *buffer, struct nfs_writeverf *verfp);
 	int	(*commit)  (struct dentry *, struct nfs_fattr *,
@@ -346,7 +343,7 @@
 	int	(*mkdir)   (struct dentry *, struct qstr *, struct iattr *,
 			    struct nfs_fh *, struct nfs_fattr *);
 	int	(*rmdir)   (struct dentry *, struct qstr *);
-	int	(*readdir) (struct dentry *, u64 cookie, void *, unsigned int,
+	int	(*readdir) (struct file *, u64 cookie, void *, unsigned int,
 			    int);
 	int	(*mknod)   (struct dentry *, struct qstr *, struct iattr *,
 			    dev_t, struct nfs_fh *, struct nfs_fattr *);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.3.99-pre8/linux/include/linux/pci_ids.h	Thu May 11 15:30:08 2000
+++ linux/include/linux/pci_ids.h	Sat May 20 11:32:08 2000
@@ -789,9 +789,12 @@
 #define PCI_DEVICE_ID_RENDITION_VERITE	0x0001
 #define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
 
-#define PCI_VENDOR_ID_RCC		0x1166
-#define PCI_DEVICE_ID_RCC_HE		0x0008
-#define PCI_DEVICE_ID_RCC_LE		0x0009
+#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_VENDOR_ID_TOSHIBA		0x1179
 #define PCI_DEVICE_ID_TOSHIBA_601	0x0601
@@ -1175,7 +1178,15 @@
 #define PCI_DEVICE_ID_INTEL_82443BX_0	0x7190
 #define PCI_DEVICE_ID_INTEL_82443BX_1	0x7191
 #define PCI_DEVICE_ID_INTEL_82443BX_2	0x7192
+#define PCI_DEVICE_ID_INTEL_82440MX_1	0x7194
+#define PCI_DEVICE_ID_INTEL_82443MX_0	0x7198
+#define PCI_DEVICE_ID_INTEL_82443MX_1	0x7199
+#define PCI_DEVICE_ID_INTEL_82443MX_2	0x719a
+#define PCI_DEVICE_ID_INTEL_82443MX_3	0x719b
+#define PCI_DEVICE_ID_INTEL_82372FB_0	0x7600
 #define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
+#define PCI_DEVICE_ID_INTEL_82372FB_2	0x7602
+#define PCI_DEVICE_ID_INTEL_82372FB_3	0x7603
 #define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
 #define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
 #define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
@@ -1253,4 +1264,7 @@
 #define PCI_DEVICE_ID_ARK_STINGARK	0xa099
 #define PCI_DEVICE_ID_ARK_2000MT	0xa0a1
 
-
+#define PCI_VENDOR_ID_SIS               0x1039
+#define PCI_DEVICE_ID_SIS_300           0x0300
+#define PCI_DEVICE_ID_SIS_540           0x5300
+#define PCI_DEVICE_ID_SIS_630           0x6300
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.3.99-pre8/linux/include/linux/proc_fs.h	Thu May 11 15:30:08 2000
+++ linux/include/linux/proc_fs.h	Tue May 23 14:18:49 2000
@@ -90,8 +90,6 @@
 void proc_pid_delete_inode(struct inode *inode);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 
-extern int proc_register(struct proc_dir_entry *, struct proc_dir_entry *);
-
 extern struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,
 						struct proc_dir_entry *parent);
 extern void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
@@ -167,7 +165,6 @@
 
 #else
 
-extern inline int proc_register(struct proc_dir_entry *a, struct proc_dir_entry *b) { return 0; }
 extern inline struct proc_dir_entry *proc_net_create(const char *name, mode_t mode, 
 	get_info_t *get_info) {return NULL;}
 extern inline void proc_net_remove(const char *name) {}
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v2.3.99-pre8/linux/include/linux/smb_fs.h	Tue Mar 14 19:10:40 2000
+++ linux/include/linux/smb_fs.h	Sat May 20 10:55:30 2000
@@ -130,7 +130,6 @@
 int smb_newconn(struct smb_sb_info *, struct smb_conn_opt *);
 int smb_errno(struct smb_sb_info *);
 int smb_close(struct inode *);
-void smb_close_dentry(struct dentry *);
 int smb_close_fileid(struct dentry *, __u16);
 int smb_open(struct dentry *, int);
 int smb_proc_read(struct dentry *, off_t, int, char *);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h
--- v2.3.99-pre8/linux/include/linux/smb_fs_i.h	Sun Dec 27 22:18:28 1998
+++ linux/include/linux/smb_fs_i.h	Tue May 23 14:18:47 2000
@@ -29,6 +29,7 @@
 	__u16 cache_valid;	/* dircache valid? */
 	unsigned long oldmtime;	/* last time refreshed */
 	unsigned long closed;	/* timestamp when closed */
+	unsigned openers;	/* number of fileid users */
 };
 
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/sunrpc/auth.h linux/include/linux/sunrpc/auth.h
--- v2.3.99-pre8/linux/include/linux/sunrpc/auth.h	Mon Mar 27 08:08:32 2000
+++ linux/include/linux/sunrpc/auth.h	Tue May 23 14:19:47 2000
@@ -25,6 +25,9 @@
 	unsigned long		cr_expire;	/* when to gc */
 	unsigned short		cr_count;	/* ref count */
 	unsigned short		cr_flags;	/* various flags */
+#ifdef RPC_DEBUG
+	unsigned long		cr_magic;	/* 0x0f4aa4f0 */
+#endif
 
 	uid_t			cr_uid;
 
@@ -33,6 +36,8 @@
 #define RPCAUTH_CRED_LOCKED	0x0001
 #define RPCAUTH_CRED_UPTODATE	0x0002
 #define RPCAUTH_CRED_DEAD	0x0004
+
+#define RPCAUTH_CRED_MAGIC	0x0f4aa4f0
 
 /*
  * Client authentication handle
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/umsdos_fs.p linux/include/linux/umsdos_fs.p
--- v2.3.99-pre8/linux/include/linux/umsdos_fs.p	Fri Apr 23 21:20:38 1999
+++ linux/include/linux/umsdos_fs.p	Sat May 20 10:55:30 2000
@@ -108,11 +108,3 @@
 /* rdir.c 22/03/95 03.31.42 */
 struct dentry *umsdos_rlookup_x (struct inode *dir, struct dentry *dentry, int nopseudo);
 struct dentry *UMSDOS_rlookup (struct inode *dir, struct dentry *dentry);
-
-/* symlink.c 23/01/95 03.38.30 */
-
-/* check.c */
-void checkd_inode (struct inode *inode);
-void check_inode (struct inode *inode);
-void check_dentry (struct dentry *dentry);
-void check_dentry_path (struct dentry *dentry, const char *desc);
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/usbdevice_fs.h linux/include/linux/usbdevice_fs.h
--- v2.3.99-pre8/linux/include/linux/usbdevice_fs.h	Tue Apr 11 15:09:25 2000
+++ linux/include/linux/usbdevice_fs.h	Sat May 20 09:21:42 2000
@@ -31,6 +31,8 @@
 #ifndef _LINUX_USBDEVICE_FS_H
 #define _LINUX_USBDEVICE_FS_H
 
+#include <linux/types.h>
+
 /* --------------------------------------------------------------------- */
 
 #define USBDEVICE_SUPER_MAGIC 0x9fa2
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/vmalloc.h linux/include/linux/vmalloc.h
--- v2.3.99-pre8/linux/include/linux/vmalloc.h	Tue Nov 23 22:42:21 1999
+++ linux/include/linux/vmalloc.h	Tue May 23 14:18:49 2000
@@ -3,6 +3,7 @@
 
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/spinlock.h>
 
 #include <asm/pgtable.h>
 
@@ -17,12 +18,48 @@
 	struct vm_struct * next;
 };
 
-struct vm_struct * get_vm_area(unsigned long size, unsigned long flags);
-void vfree(void * addr);
-void * vmalloc(unsigned long size);
-long vread(char *buf, char *addr, unsigned long count);
-void vmfree_area_pages(unsigned long address, unsigned long size);
-int vmalloc_area_pages(unsigned long address, unsigned long size);
+extern struct vm_struct * get_vm_area (unsigned long size, unsigned long flags);
+extern void vfree(void * addr);
+extern void * __vmalloc (unsigned long size, int gfp_mask);
+extern long vread(char *buf, char *addr, unsigned long count);
+extern void vmfree_area_pages(unsigned long address, unsigned long size);
+extern int vmalloc_area_pages(unsigned long address, unsigned long size , int gfp_mask);
+
+extern struct vm_struct * vmlist;
+
+
+/*
+ *	Allocate any pages
+ */
+ 
+static inline void * vmalloc (unsigned long size)
+{
+	return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM);
+}
+
+/*
+ *	Allocate ISA addressable pages for broke crap
+ */
+
+static inline void * vmalloc_dma (unsigned long size)
+{
+	return __vmalloc(size, GFP_KERNEL|GFP_DMA);
+}
+
+/*
+ *	vmalloc 32bit PA addressable pages - eg for PCI 32bit devices
+ */
+ 
+static inline void * vmalloc_32(unsigned long size)
+{
+	return __vmalloc(size, GFP_KERNEL);
+}
+
+/*
+ * vmlist_lock is a read-write spinlock that protects vmlist
+ * Used in mm/vmalloc.c (get_vm_area() and vfree()) and fs/proc/kcore.c.
+ */
+extern rwlock_t vmlist_lock;
 
 extern struct vm_struct * vmlist;
 #endif
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/wait.h linux/include/linux/wait.h
--- v2.3.99-pre8/linux/include/linux/wait.h	Sat Feb 26 22:32:07 2000
+++ linux/include/linux/wait.h	Tue May 23 14:18:47 2000
@@ -27,7 +27,7 @@
 extern int printk(const char *fmt, ...);
 #define WQ_BUG() do { \
 	printk("wq bug, forcing oops.\n"); \
-	*(int*)0 = 0; \
+	BUG(); \
 } while (0)
 
 #define CHECK_MAGIC(x) if (x != (long)&(x)) \
diff -u --recursive --new-file v2.3.99-pre8/linux/include/linux/wrapper.h linux/include/linux/wrapper.h
--- v2.3.99-pre8/linux/include/linux/wrapper.h	Mon Nov  1 13:56:27 1999
+++ linux/include/linux/wrapper.h	Sat May 20 10:55:30 2000
@@ -5,7 +5,6 @@
 #define inode_handle struct inode
 #define select_table_handle select_table
 #define vm_area_handle struct vm_area_struct
-#define file_operation_handle file_operations
 
 #define connect_wrapper(x) 0
 #define current_got_fatal_signal() (signal_pending(current))
diff -u --recursive --new-file v2.3.99-pre8/linux/include/net/slhc.h linux/include/net/slhc.h
--- v2.3.99-pre8/linux/include/net/slhc.h	Tue Feb  6 22:55:43 1996
+++ linux/include/net/slhc.h	Wed Dec 31 16:00:00 1969
@@ -1,6 +0,0 @@
-#ifndef __NET_SLHC_H
-#define __NET_SLHC_H
-
-extern void slhc_install(void);
-
-#endif
diff -u --recursive --new-file v2.3.99-pre8/linux/init/main.c linux/init/main.c
--- v2.3.99-pre8/linux/init/main.c	Fri May 12 14:18:56 2000
+++ linux/init/main.c	Mon May 22 23:24:17 2000
@@ -405,9 +405,18 @@
 	return 1;
 }
 
+static int __init quiet_kernel(char *str)
+{
+	if (*str)
+		return 0;
+	console_loglevel = 4;
+	return 1;
+}
+
 __setup("ro", readonly);
 __setup("rw", readwrite);
 __setup("debug", debug_kernel);
+__setup("quiet", quiet_kernel);
 
 /*
  * This is a simple kernel command line parsing function: it parses
@@ -726,8 +735,7 @@
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	root_mountflags = real_root_mountflags;
-	if (mount_initrd && ROOT_DEV != real_root_dev
-	    && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
+	if (mount_initrd && MAJOR(ROOT_DEV) == RAMDISK_MAJOR && MINOR(ROOT_DEV) == 0) {
 		int error;
 		int i, pid;
 
diff -u --recursive --new-file v2.3.99-pre8/linux/ipc/shm.c linux/ipc/shm.c
--- v2.3.99-pre8/linux/ipc/shm.c	Fri May 12 14:18:56 2000
+++ linux/ipc/shm.c	Sat May 20 10:55:30 2000
@@ -541,8 +541,6 @@
 	if (dent->d_name.len == SHM_FMT_LEN &&
 	    memcmp (SHM_FMT, dent->d_name.name, SHM_FMT_LEN - 8) == 0)
 		d_drop (dent);
-	else
-		d_delete (dent);
 	return 0;
 }
 
@@ -1251,6 +1249,8 @@
 		struct inode *inode = dir->d_inode;
 		down(&inode->i_zombie);
 		error = shm_unlink(inode, dentry);
+		if (!error)
+			d_delete(dentry);
 		up(&inode->i_zombie);
 		dput(dentry);
 	}
@@ -1468,7 +1468,7 @@
 }
 
 /*
- * Goes through counter = (shm_rss >> prio) present shm pages.
+ * Goes through counter = (shm_rss / (prio + 1)) present shm pages.
  */
 static unsigned long swap_id; /* currently being swapped */
 static unsigned long swap_idx; /* next to swap */
@@ -1483,7 +1483,7 @@
 	struct page * page_map;
 
 	zshm_swap(prio, gfp_mask);
-	counter = shm_rss >> prio;
+	counter = shm_rss / (prio + 1);
 	if (!counter)
 		return 0;
 	if (shm_swap_preop(&swap_entry))
@@ -1809,7 +1809,7 @@
 	int counter;
 	struct page * page_map;
 
-	counter = zshm_rss >> prio;
+	counter = zshm_rss / (prio + 1);
 	if (!counter)
 		return;
 next:
diff -u --recursive --new-file v2.3.99-pre8/linux/ipc/util.c linux/ipc/util.c
--- v2.3.99-pre8/linux/ipc/util.c	Thu May 11 15:30:08 2000
+++ linux/ipc/util.c	Mon May 15 11:19:26 2000
@@ -159,25 +159,19 @@
 void* ipc_alloc(int size)
 {
 	void* out;
-	if(size > PAGE_SIZE) {
-		lock_kernel();
+	if(size > PAGE_SIZE)
 		out = vmalloc(size);
-		unlock_kernel();
-	} else {
+	else
 		out = kmalloc(size, GFP_KERNEL);
-	}
 	return out;
 }
 
 void ipc_free(void* ptr, int size)
 {
-	if(size > PAGE_SIZE) {
-		lock_kernel();
+	if(size > PAGE_SIZE)
 		vfree(ptr);
-		unlock_kernel();
-	} else {
+	else
 		kfree(ptr);
-	}
 }
 
 /* 
diff -u --recursive --new-file v2.3.99-pre8/linux/kernel/exec_domain.c linux/kernel/exec_domain.c
--- v2.3.99-pre8/linux/kernel/exec_domain.c	Thu May 11 15:30:08 2000
+++ linux/kernel/exec_domain.c	Mon May 15 11:38:19 2000
@@ -23,7 +23,7 @@
 };
 
 static struct exec_domain *exec_domains = &default_exec_domain;
-static spinlock_t exec_domains_lock = SPIN_LOCK_UNLOCKED;
+static rwlock_t exec_domains_lock = RW_LOCK_UNLOCKED;
 
 static asmlinkage void no_lcall7(int segment, struct pt_regs * regs)
 {
@@ -48,15 +48,15 @@
 	unsigned long pers = personality & PER_MASK;
 	struct exec_domain *it;
 
-	spin_lock(&exec_domains_lock);
+	read_lock(&exec_domains_lock);
 	for (it=exec_domains; it; it=it->next)
 		if (pers >= it->pers_low && pers <= it->pers_high) {
 			if (!try_inc_mod_count(it->module))
 				continue;
-			spin_unlock(&exec_domains_lock);
+			read_unlock(&exec_domains_lock);
 			return it;
 		}
-	spin_unlock(&exec_domains_lock);
+	read_unlock(&exec_domains_lock);
 
 	/* Should never get this far. */
 	printk(KERN_ERR "No execution domain for personality 0x%02lx\n", pers);
@@ -71,15 +71,15 @@
 		return -EINVAL;
 	if (it->next)
 		return -EBUSY;
-	spin_lock(&exec_domains_lock);
+	write_lock(&exec_domains_lock);
 	for (tmp=exec_domains; tmp; tmp=tmp->next)
 		if (tmp == it) {
-			spin_unlock(&exec_domains_lock);
+			write_unlock(&exec_domains_lock);
 			return -EBUSY;
 		}
 	it->next = exec_domains;
 	exec_domains = it;
-	spin_unlock(&exec_domains_lock);
+	write_unlock(&exec_domains_lock);
 	return 0;
 }
 
@@ -88,17 +88,17 @@
 	struct exec_domain ** tmp;
 
 	tmp = &exec_domains;
-	spin_lock(&exec_domains_lock);
+	write_lock(&exec_domains_lock);
 	while (*tmp) {
 		if (it == *tmp) {
 			*tmp = it->next;
 			it->next = NULL;
-			spin_unlock(&exec_domains_lock);
+			write_unlock(&exec_domains_lock);
 			return 0;
 		}
 		tmp = &(*tmp)->next;
 	}
-	spin_unlock(&exec_domains_lock);
+	write_unlock(&exec_domains_lock);
 	return -EINVAL;
 }
 
@@ -148,11 +148,11 @@
 	int len = 0;
 	struct exec_domain * e;
 
-	spin_lock(&exec_domains_lock);
+	read_lock(&exec_domains_lock);
 	for (e=exec_domains; e && len < PAGE_SIZE - 80; e=e->next)
 		len += sprintf(page+len, "%d-%d\t%-16s\t[%s]\n",
 			e->pers_low, e->pers_high, e->name,
 			e->module ? e->module->name : "kernel");
-	spin_unlock(&exec_domains_lock);
+	read_unlock(&exec_domains_lock);
 	return len;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/kernel/fork.c linux/kernel/fork.c
--- v2.3.99-pre8/linux/kernel/fork.c	Fri May 12 14:18:56 2000
+++ linux/kernel/fork.c	Sat May 13 08:32:55 2000
@@ -674,7 +674,7 @@
 
 	if ((clone_flags & CLONE_VFORK) || !(clone_flags & CLONE_PARENT)) {
 		p->p_opptr = current;
-		if (!(current->flags & PF_PTRACED))
+		if (!(p->flags & PF_PTRACED))
 			p->p_pptr = current;
 	}
 	p->p_cptr = NULL;
diff -u --recursive --new-file v2.3.99-pre8/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.3.99-pre8/linux/kernel/ksyms.c	Thu May 11 15:30:08 2000
+++ linux/kernel/ksyms.c	Tue May 23 08:22:22 2000
@@ -118,6 +118,7 @@
 EXPORT_SYMBOL(kfree_s);
 EXPORT_SYMBOL(vmalloc);
 EXPORT_SYMBOL(vfree);
+EXPORT_SYMBOL(__vmalloc);
 EXPORT_SYMBOL(mem_map);
 EXPORT_SYMBOL(remap_page_range);
 EXPORT_SYMBOL(max_mapnr);
@@ -218,6 +219,9 @@
 EXPORT_SYMBOL(locks_mandatory_area);
 EXPORT_SYMBOL(dput);
 EXPORT_SYMBOL(have_submounts);
+EXPORT_SYMBOL(d_genocide);
+EXPORT_SYMBOL(d_find_alias);
+EXPORT_SYMBOL(d_prune_aliases);
 EXPORT_SYMBOL(prune_dcache);
 EXPORT_SYMBOL(shrink_dcache_sb);
 EXPORT_SYMBOL(shrink_dcache_parent);
@@ -248,6 +252,7 @@
 EXPORT_SYMBOL(block_fsync);
 EXPORT_SYMBOL(block_symlink);
 EXPORT_SYMBOL(vfs_readdir);
+EXPORT_SYMBOL(dcache_readdir);
 
 /* for stackable file systems (lofs, wrapfs, cryptfs, etc.) */
 EXPORT_SYMBOL(default_llseek);
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/filemap.c linux/mm/filemap.c
--- v2.3.99-pre8/linux/mm/filemap.c	Fri May 12 14:18:56 2000
+++ linux/mm/filemap.c	Mon May 22 09:50:55 2000
@@ -244,14 +244,19 @@
 	spin_unlock(&pagecache_lock);
 }
 
+/*
+ * nr_dirty represents the number of dirty pages that we will write async
+ * before doing sync writes.  We can only do sync writes if we can
+ * wait for IO (__GFP_IO set).
+ */
 int shrink_mmap(int priority, int gfp_mask)
 {
-	int ret = 0, count;
-	LIST_HEAD(old);
-	struct list_head * page_lru, * dispose;
+	int ret = 0, count, nr_dirty;
+	struct list_head * page_lru;
 	struct page * page = NULL;
 	
 	count = nr_lru_pages / (priority + 1);
+	nr_dirty = priority;
 
 	/* we need pagemap_lru_lock for list_del() ... subtle code below */
 	spin_lock(&pagemap_lru_lock);
@@ -259,25 +264,10 @@
 		page = list_entry(page_lru, struct page, lru);
 		list_del(page_lru);
 
-		dispose = &lru_cache;
 		if (PageTestandClearReferenced(page))
 			goto dispose_continue;
 
 		count--;
-
-		/*
-		 * I'm ambivalent on this one.. Should we try to
-		 * maintain LRU on the LRU list, and put pages that
-		 * are old at the end of the queue, even if that
-		 * means that we'll re-scan then again soon and
-		 * often waste CPU time? Or should be just let any
-		 * pages we do not want to touch now for one reason
-		 * or another percolate to be "young"?
-		 *
-		dispose = &old;
-		 *
-		 */
-
 		/*
 		 * Avoid unscalable SMP locking for pages we can
 		 * immediate tell are untouchable..
@@ -303,7 +293,8 @@
 		 * of zone - it's old.
 		 */
 		if (page->buffers) {
-			if (!try_to_free_buffers(page))
+			int wait = ((gfp_mask & __GFP_IO) && (nr_dirty-- < 0));
+			if (!try_to_free_buffers(page, wait))
 				goto unlock_continue;
 			/* page was locked, inode can't go away under us */
 			if (!page->mapping) {
@@ -362,7 +353,7 @@
 		UnlockPage(page);
 		page_cache_release(page);
 dispose_continue:
-		list_add(page_lru, dispose);
+		list_add(page_lru, &lru_cache);
 	}
 	goto out;
 
@@ -377,8 +368,6 @@
 	nr_lru_pages--;
 
 out:
-	list_splice(&old, lru_cache.prev);
-
 	spin_unlock(&pagemap_lru_lock);
 
 	return ret;
@@ -2319,7 +2308,8 @@
 	return error;
 }
 
-struct page *read_cache_page(struct address_space *mapping,
+static inline
+struct page *__read_cache_page(struct address_space *mapping,
 				unsigned long index,
 				int (*filler)(void *,struct page*),
 				void *data)
@@ -2347,6 +2337,35 @@
 	}
 	if (cached_page)
 		page_cache_free(cached_page);
+	return page;
+}
+
+/*
+ * Read into the page cache. If a page already exists,
+ * and Page_Uptodate() is not set, try to fill the page.
+ */
+struct page *read_cache_page(struct address_space *mapping,
+				unsigned long index,
+				int (*filler)(void *,struct page*),
+				void *data)
+{
+	struct page *page = __read_cache_page(mapping, index, filler, data);
+	int err;
+
+	if (IS_ERR(page) || Page_Uptodate(page))
+		goto out;
+
+	lock_page(page);
+	if (Page_Uptodate(page)) {
+		UnlockPage(page);
+		goto out;
+	}
+	err = filler(data, page);
+	if (err < 0) {
+		page_cache_release(page);
+		page = ERR_PTR(err);
+	}
+ out:
 	return page;
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/highmem.c linux/mm/highmem.c
--- v2.3.99-pre8/linux/mm/highmem.c	Fri May 12 14:18:56 2000
+++ linux/mm/highmem.c	Mon May 15 10:47:34 2000
@@ -60,7 +60,7 @@
 	 * ok, we can just forget about our highmem page since 
 	 * we stored its data into the new regular_page.
 	 */
-	__free_page(page);
+	page_cache_release(page);
 	new_page = mem_map + MAP_NR(regular_page);
 	LockPage(new_page);
 	return new_page;
@@ -78,7 +78,7 @@
 	if (!highpage)
 		return page;
 	if (!PageHighMem(highpage)) {
-		__free_page(highpage);
+		page_cache_release(highpage);
 		return page;
 	}
 
@@ -94,7 +94,7 @@
 	 * We can just forget the old page since 
 	 * we stored its data into the new highmem-page.
 	 */
-	__free_page(page);
+	page_cache_release(page);
 
 	return highpage;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/memory.c linux/mm/memory.c
--- v2.3.99-pre8/linux/mm/memory.c	Fri May 12 14:18:56 2000
+++ linux/mm/memory.c	Mon May 15 12:00:33 2000
@@ -156,7 +156,7 @@
 	unsigned long address = vma->vm_start;
 	unsigned long end = vma->vm_end;
 	unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
-	
+
 	src_pgd = pgd_offset(src, address)-1;
 	dst_pgd = pgd_offset(dst, address)-1;
 	
@@ -878,7 +878,7 @@
 		new_page = old_page;
 	}
 	spin_unlock(&mm->page_table_lock);
-	__free_page(new_page);
+	page_cache_release(new_page);
 	return 1;	/* Minor fault */
 
 bad_wp_page:
@@ -1022,7 +1022,7 @@
 		/* Ok, do the async read-ahead now */
 		new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset), 0);
 		if (new_page != NULL)
-			__free_page(new_page);
+			page_cache_release(new_page);
 		swap_free(SWP_ENTRY(SWP_TYPE(entry), offset));
 	}
 	return;
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/slab.c linux/mm/slab.c
--- v2.3.99-pre8/linux/mm/slab.c	Fri May 12 14:18:56 2000
+++ linux/mm/slab.c	Mon May 15 16:41:33 2000
@@ -1734,7 +1734,7 @@
 
 #if 1
 /* FORCE A KERNEL DUMP WHEN THIS HAPPENS. SPEAK IN ALL CAPS. GET THE CALL CHAIN. */
-*(int *) 0 = 0;
+BUG();
 #endif
 
 null_ptr:
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.3.99-pre8/linux/mm/swap_state.c	Fri May 12 14:18:56 2000
+++ linux/mm/swap_state.c	Mon May 15 12:00:33 2000
@@ -136,7 +136,7 @@
 		}
 		UnlockPage(page);
 	}
-        page_cache_release(page);
+	page_cache_release(page);
 }
 
 
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.3.99-pre8/linux/mm/swapfile.c	Fri May 12 14:18:56 2000
+++ linux/mm/swapfile.c	Mon May 15 10:47:34 2000
@@ -377,7 +377,7 @@
                    page we've been using. */
 		if (PageSwapCache(page))
 			delete_from_swap_cache(page);
-		__free_page(page);
+		page_cache_release(page);
 		/*
 		 * Check for and clear any overflowed swap map counts.
 		 */
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.3.99-pre8/linux/mm/vmalloc.c	Mon Mar 27 08:08:33 2000
+++ linux/mm/vmalloc.c	Sun May 21 20:18:08 2000
@@ -3,14 +3,17 @@
  *
  *  Copyright (C) 1993  Linus Torvalds
  *  Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ *  SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian <tigran@veritas.com>, May 2000
  */
 
 #include <linux/malloc.h>
 #include <linux/vmalloc.h>
+#include <linux/spinlock.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 
+rwlock_t vmlist_lock = RW_LOCK_UNLOCKED;
 struct vm_struct * vmlist = NULL;
 
 static inline void free_area_pte(pmd_t * pmd, unsigned long address, unsigned long size)
@@ -87,7 +90,8 @@
 	flush_tlb_all();
 }
 
-static inline int alloc_area_pte(pte_t * pte, unsigned long address, unsigned long size)
+static inline int alloc_area_pte (pte_t * pte, unsigned long address,
+			unsigned long size, int gfp_mask)
 {
 	unsigned long end;
 
@@ -99,7 +103,7 @@
 		struct page * page;
 		if (!pte_none(*pte))
 			printk(KERN_ERR "alloc_area_pte: page already exists\n");
-		page = alloc_page(GFP_KERNEL|__GFP_HIGHMEM);
+		page = alloc_page(gfp_mask);
 		if (!page)
 			return -ENOMEM;
 		set_pte(pte, mk_pte(page, PAGE_KERNEL));
@@ -109,7 +113,7 @@
 	return 0;
 }
 
-static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size)
+static inline int alloc_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, int gfp_mask)
 {
 	unsigned long end;
 
@@ -121,7 +125,7 @@
 		pte_t * pte = pte_alloc_kernel(pmd, address);
 		if (!pte)
 			return -ENOMEM;
-		if (alloc_area_pte(pte, address, end - address))
+		if (alloc_area_pte(pte, address, end - address, gfp_mask))
 			return -ENOMEM;
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
@@ -129,7 +133,8 @@
 	return 0;
 }
 
-int vmalloc_area_pages(unsigned long address, unsigned long size)
+inline int vmalloc_area_pages (unsigned long address,
+					unsigned long size, int gfp_mask)
 {
 	pgd_t * dir;
 	unsigned long end = address + size;
@@ -143,7 +148,7 @@
 		pmd = pmd_alloc_kernel(dir, address);
 		if (!pmd)
 			return -ENOMEM;
-		if (alloc_area_pmd(pmd, address, end - address))
+		if (alloc_area_pmd(pmd, address, end - address, gfp_mask))
 			return -ENOMEM;
 		if (pgd_val(olddir) != pgd_val(*dir))
 			set_pgdir(address, *dir);
@@ -163,11 +168,13 @@
 	if (!area)
 		return NULL;
 	addr = VMALLOC_START;
+	write_lock(&vmlist_lock);
 	for (p = &vmlist; (tmp = *p) ; p = &tmp->next) {
 		if (size + addr < (unsigned long) tmp->addr)
 			break;
 		addr = tmp->size + (unsigned long) tmp->addr;
 		if (addr > VMALLOC_END-size) {
+			write_unlock(&vmlist_lock);
 			kfree(area);
 			return NULL;
 		}
@@ -177,6 +184,7 @@
 	area->size = size + PAGE_SIZE;
 	area->next = *p;
 	*p = area;
+	write_unlock(&vmlist_lock);
 	return area;
 }
 
@@ -190,18 +198,21 @@
 		printk(KERN_ERR "Trying to vfree() bad address (%p)\n", addr);
 		return;
 	}
+	write_lock(&vmlist_lock);
 	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
 		if (tmp->addr == addr) {
 			*p = tmp->next;
 			vmfree_area_pages(VMALLOC_VMADDR(tmp->addr), tmp->size);
 			kfree(tmp);
+			write_unlock(&vmlist_lock);
 			return;
 		}
 	}
+	write_unlock(&vmlist_lock);
 	printk(KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr);
 }
 
-void * vmalloc(unsigned long size)
+void * __vmalloc (unsigned long size, int gfp_mask)
 {
 	void * addr;
 	struct vm_struct *area;
@@ -217,7 +228,7 @@
 		return NULL;
 	}
 	addr = area->addr;
-	if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size)) {
+	if (vmalloc_area_pages(VMALLOC_VMADDR(addr), size, gfp_mask)) {
 		vfree(addr);
 		BUG();
 		return NULL;
@@ -235,6 +246,7 @@
 	if ((unsigned long) addr + count < count)
 		count = -(unsigned long) addr;
 
+	read_lock(&vmlist_lock);
 	for (tmp = vmlist; tmp; tmp = tmp->next) {
 		vaddr = (char *) tmp->addr;
 		if (addr >= vaddr + tmp->size - PAGE_SIZE)
@@ -242,7 +254,7 @@
 		while (addr < vaddr) {
 			if (count == 0)
 				goto finished;
-			put_user('\0', buf);
+			*buf = '\0';
 			buf++;
 			addr++;
 			count--;
@@ -251,12 +263,13 @@
 		do {
 			if (count == 0)
 				goto finished;
-			put_user(*addr, buf);
+			*buf = *addr;
 			buf++;
 			addr++;
 			count--;
 		} while (--n > 0);
 	}
 finished:
+	read_unlock(&vmlist_lock);
 	return buf - buf_start;
 }
diff -u --recursive --new-file v2.3.99-pre8/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.3.99-pre8/linux/mm/vmscan.c	Fri May 12 14:18:56 2000
+++ linux/mm/vmscan.c	Mon May 22 21:10:31 2000
@@ -48,6 +48,9 @@
 	if ((page-mem_map >= max_mapnr) || PageReserved(page))
 		goto out_failed;
 
+	if (mm->swap_cnt)
+		mm->swap_cnt--;
+
 	/* Don't look at this pte if it's been accessed recently. */
 	if (pte_young(pte)) {
 		/*
@@ -76,10 +79,9 @@
 		set_pte(page_table, swp_entry_to_pte(entry));
 drop_pte:
 		UnlockPage(page);
-		mm->swap_cnt--;
 		vma->vm_mm->rss--;
 		flush_tlb_page(vma, address);
-		__free_page(page);
+		page_cache_release(page);
 		goto out_failed;
 	}
 
@@ -142,7 +144,6 @@
 		struct file *file = vma->vm_file;
 		if (file) get_file(file);
 		pte_clear(page_table);
-		mm->swap_cnt--;
 		vma->vm_mm->rss--;
 		flush_tlb_page(vma, address);
 		vmlist_access_unlock(vma->vm_mm);
@@ -151,7 +152,7 @@
 		if (file) fput(file);
 		if (!error)
 			goto out_free_success;
-		__free_page(page);
+		page_cache_release(page);
 		return error;
 	}
 
@@ -174,7 +175,6 @@
 	add_to_swap_cache(page, entry);
 
 	/* Put the swap entry into the pte after the page is in swapcache */
-	mm->swap_cnt--;
 	vma->vm_mm->rss--;
 	set_pte(page_table, swp_entry_to_pte(entry));
 	flush_tlb_page(vma, address);
@@ -184,7 +184,7 @@
 	rw_swap_page(WRITE, page, 0);
 
 out_free_success:
-	__free_page(page);
+	page_cache_release(page);
 	return 1;
 out_swap_free:
 	swap_free(entry);
@@ -363,7 +363,7 @@
 	 * Think of swap_cnt as a "shadow rss" - it tells us which process
 	 * we want to page out (always try largest first).
 	 */
-	counter = (nr_threads << 1) >> (priority >> 1);
+	counter = (nr_threads << 2) >> (priority >> 2);
 	if (counter < 1)
 		counter = 1;
 
@@ -430,16 +430,17 @@
  * latency.
  */
 #define FREE_COUNT	8
-#define SWAP_COUNT	8
+#define SWAP_COUNT	16
 static int do_try_to_free_pages(unsigned int gfp_mask)
 {
 	int priority;
 	int count = FREE_COUNT;
+	int swap_count;
 
 	/* Always trim SLAB caches when memory gets low. */
 	kmem_cache_reap(gfp_mask);
 
-	priority = 6;
+	priority = 64;
 	do {
 		while (shrink_mmap(priority, gfp_mask)) {
 			if (!--count)
@@ -471,12 +472,11 @@
 		 * put in the swap cache), so we must not count this
 		 * as a "count" success.
 		 */
-		{
-			int swap_count = SWAP_COUNT;
-			while (swap_out(priority, gfp_mask))
-				if (--swap_count < 0)
-					break;
-		}
+		swap_count = SWAP_COUNT;
+		while (swap_out(priority, gfp_mask))
+			if (--swap_count < 0)
+				break;
+
 	} while (--priority >= 0);
 
 	/* Always end on a shrink_mmap.. */
@@ -484,8 +484,8 @@
 		if (!--count)
 			goto done;
 	}
-
-	return 0;
+	/* We return 1 if we are freed some page */
+	return (count != FREE_COUNT);
 
 done:
 	return 1;
@@ -538,16 +538,18 @@
 			int i;
 			for(i = 0; i < MAX_NR_ZONES; i++) {
 				zone_t *zone = pgdat->node_zones+ i;
+				if (tsk->need_resched)
+					schedule();
 				if (!zone->size || !zone->zone_wake_kswapd)
 					continue;
-				something_to_do = 1;
+				if (zone->free_pages < zone->pages_low)
+					something_to_do = 1;
 				do_try_to_free_pages(GFP_KSWAPD);
 			}
-			run_task_queue(&tq_disk);
 			pgdat = pgdat->node_next;
 		} while (pgdat);
 
-		if (tsk->need_resched || !something_to_do) {
+		if (!something_to_do) {
 			tsk->state = TASK_INTERRUPTIBLE;
 			interruptible_sleep_on(&kswapd_wait);
 		}
diff -u --recursive --new-file v2.3.99-pre8/linux/net/Makefile linux/net/Makefile
--- v2.3.99-pre8/linux/net/Makefile	Tue Apr 11 15:09:26 2000
+++ linux/net/Makefile	Mon May 22 09:50:55 2000
@@ -10,7 +10,7 @@
 MOD_SUB_DIRS := ipv4
 ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \
 		netrom rose lapb x25 wanrouter netlink sched packet sunrpc \
-		econet irda decnet atm khttpd ipv4/netfilter
+		econet irda decnet atm khttpd ipv4/netfilter ipv6/netfilter
 SUB_DIRS     := core ethernet sched
 MOD_LIST_NAME := NET_MISC_MODULES
 
@@ -36,9 +36,16 @@
 
 ifeq ($(CONFIG_IPV6),y)
 SUB_DIRS += ipv6
+ifeq ($(CONFIG_NETFILTER),y)
+SUB_DIRS += ipv6/netfilter
+MOD_SUB_DIRS += ipv6/netfilter
+endif
 else
   ifeq ($(CONFIG_IPV6),m)
   MOD_SUB_DIRS += ipv6
+  ifeq ($(CONFIG_NETFILTER),y)
+  MOD_SUB_DIRS += ipv6/netfilter
+  endif
   endif
 endif
 
diff -u --recursive --new-file v2.3.99-pre8/linux/net/core/dev.c linux/net/core/dev.c
--- v2.3.99-pre8/linux/net/core/dev.c	Thu May 11 15:30:08 2000
+++ linux/net/core/dev.c	Tue May 23 08:21:51 2000
@@ -79,7 +79,6 @@
 #include <linux/brlock.h>
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
-#include <net/slhc.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
 #include <linux/if_bridge.h>
diff -u --recursive --new-file v2.3.99-pre8/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.3.99-pre8/linux/net/core/skbuff.c	Wed Apr 26 16:34:09 2000
+++ linux/net/core/skbuff.c	Mon May 22 09:50:55 2000
@@ -4,7 +4,7 @@
  *	Authors:	Alan Cox <iiitac@pyr.swan.ac.uk>
  *			Florian La Roche <rzsfl@rz.uni-sb.de>
  *
- *	Version:	$Id: skbuff.c,v 1.72 2000/04/13 00:55:54 davem Exp $
+ *	Version:	$Id: skbuff.c,v 1.73 2000/05/22 07:29:44 davem Exp $
  *
  *	Fixes:	
  *		Alan Cox	:	Fixed the worst of the load balancer bugs.
@@ -90,7 +90,7 @@
 {
 	printk("skput:over: %p:%d put:%d dev:%s", 
 		here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
-	*(int*)0 = 0;
+	BUG();
 }
 
 /**
@@ -107,7 +107,7 @@
 {
         printk("skput:under: %p:%d put:%d dev:%s",
                 here, skb->len, sz, skb->dev ? skb->dev->name : "<NULL>");
-	*(int*)0 = 0;
+	BUG();
 }
 
 static __inline__ struct sk_buff *skb_head_from_pool(void)
@@ -172,7 +172,7 @@
 		if (++count < 5) {
 			printk(KERN_ERR "alloc_skb called nonatomically "
 			       "from interrupt %p\n", NET_CALLER(size));
- 			*(int*)0 = 0;
+ 			BUG();
 		}
 		gfp_mask &= ~__GFP_WAIT;
 	}
@@ -273,7 +273,7 @@
 	if (skb->list) {
 	 	printk(KERN_WARNING "Warning: kfree_skb passed an skb still "
 		       "on a list (from %p).\n", NET_CALLER(skb));
-		*(int*)0 = 0;
+		BUG();
 	}
 
 	dst_release(skb->dst);
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
--- v2.3.99-pre8/linux/net/ipv4/ip_gre.c	Thu May 11 15:30:08 2000
+++ linux/net/ipv4/ip_gre.c	Mon May 22 09:50:55 2000
@@ -268,10 +268,10 @@
 	dev->priv = (void*)(dev+1);
 	nt = (struct ip_tunnel*)dev->priv;
 	nt->dev = dev;
-	strcpy(dev->name, nt->parms.name);
 	dev->init = ipgre_tunnel_init;
 	dev->new_style = 1;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
 		for (i=1; i<100; i++) {
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- v2.3.99-pre8/linux/net/ipv4/ipip.c	Thu May 11 15:30:08 2000
+++ linux/net/ipv4/ipip.c	Mon May 22 09:50:55 2000
@@ -1,7 +1,7 @@
 /*
  *	Linux NET3:	IP/IP protocol decoder. 
  *
- *	Version: $Id: ipip.c,v 1.33 2000/05/05 02:17:17 davem Exp $
+ *	Version: $Id: ipip.c,v 1.34 2000/05/22 08:12:19 davem Exp $
  *
  *	Authors:
  *		Sam Lantinga (slouken@cs.ucdavis.edu)  02/01/95
@@ -237,10 +237,10 @@
 	dev->priv = (void*)(dev+1);
 	nt = (struct ip_tunnel*)dev->priv;
 	nt->dev = dev;
-	strcpy(dev->name, nt->parms.name);
 	dev->init = ipip_tunnel_init;
 	dev->new_style = 1;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
 		for (i=1; i<100; i++) {
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/Config.in linux/net/ipv6/Config.in
--- v2.3.99-pre8/linux/net/ipv6/Config.in	Mon Dec 20 18:48:22 1999
+++ linux/net/ipv6/Config.in	Mon May 22 09:50:55 2000
@@ -12,3 +12,7 @@
 fi
 #bool '    IPv6: flow policy support' CONFIG_RT6_POLICY
 #bool '    IPv6: firewall support' CONFIG_IPV6_FIREWALL
+
+if [ "$CONFIG_NETFILTER" != "n" ]; then
+   source net/ipv6/netfilter/Config.in
+fi
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/netfilter/Config.in linux/net/ipv6/netfilter/Config.in
--- v2.3.99-pre8/linux/net/ipv6/netfilter/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv6/netfilter/Config.in	Mon May 22 09:50:55 2000
@@ -0,0 +1,49 @@
+#
+# IP netfilter configuration
+#
+mainmenu_option next_comment
+comment '  IPv6: Netfilter Configuration'
+
+#tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
+#if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
+#  dep_tristate '  FTP protocol support' CONFIG_IP6_NF_FTP $CONFIG_IP6_NF_CONNTRACK
+#fi
+
+#if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_NETLINK" = "y" ]; then
+#  tristate 'Userspace queueing via NETLINK (EXPERIMENTAL)' CONFIG_IP6_NF_QUEUE
+#fi
+tristate 'IP6 tables support (required for filtering/masq/NAT)' CONFIG_IP6_NF_IPTABLES
+if [ "$CONFIG_IP6_NF_IPTABLES" != "n" ]; then
+# The simple matches.
+  dep_tristate '  limit match support' CONFIG_IP6_NF_MATCH_LIMIT $CONFIG_IP6_NF_IPTABLES
+#  dep_tristate '  MAC address match support' CONFIG_IP6_NF_MATCH_MAC $CONFIG_IP6_NF_IPTABLES
+  dep_tristate '  netfilter MARK match support' CONFIG_IP6_NF_MATCH_MARK $CONFIG_IP6_NF_IPTABLES
+#  dep_tristate '  Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
+#  dep_tristate '  TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES
+#  if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
+#    dep_tristate '  Connection state match support' CONFIG_IP6_NF_MATCH_STATE $CONFIG_IP6_NF_CONNTRACK $CONFIG_IP6_NF_IPTABLES 
+#  fi
+#  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+#    dep_tristate '  Unclean match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_UNCLEAN $CONFIG_IP6_NF_IPTABLES
+#    dep_tristate '  Owner match support (EXPERIMENTAL)' CONFIG_IP6_NF_MATCH_OWNER $CONFIG_IP6_NF_IPTABLES
+#  fi
+
+# The targets
+  dep_tristate '  Packet filtering' CONFIG_IP6_NF_FILTER $CONFIG_IP6_NF_IPTABLES 
+
+  if [ "$CONFIG_IP6_NF_FILTER" != "n" ]; then
+#    dep_tristate '    REJECT target support' CONFIG_IP6_NF_TARGET_REJECT $CONFIG_IP6_NF_FILTER
+#    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+#      dep_tristate '    MIRROR target support (EXPERIMENTAL)' CONFIG_IP6_NF_TARGET_MIRROR $CONFIG_IP6_NF_FILTER
+#    fi
+  fi
+
+  dep_tristate '  Packet mangling' CONFIG_IP6_NF_MANGLE $CONFIG_IP6_NF_IPTABLES 
+  if [ "$CONFIG_IP6_NF_MANGLE" != "n" ]; then
+#    dep_tristate '    TOS target support' CONFIG_IP6_NF_TARGET_TOS $CONFIG_IP_NF_MANGLE
+    dep_tristate '    MARK target support' CONFIG_IP6_NF_TARGET_MARK $CONFIG_IP6_NF_MANGLE
+  fi
+  #dep_tristate '  LOG target support' CONFIG_IP6_NF_TARGET_LOG $CONFIG_IP6_NF_IPTABLES
+fi
+
+endmenu
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/netfilter/Makefile linux/net/ipv6/netfilter/Makefile
--- v2.3.99-pre8/linux/net/ipv6/netfilter/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv6/netfilter/Makefile	Mon May 22 09:50:55 2000
@@ -0,0 +1,180 @@
+#
+# Makefile for the netfilter modules on top of IPv6.
+#
+# 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).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := netfilter.o
+MOD_LIST_NAME := IPV6_MODULES
+M_OBJS :=
+
+IP6_NF_CONNTRACK_OBJ:=ip6_conntrack_core.o ip6_conntrack_proto_generic.o ip6_conntrack_proto_tcp.o ip6_conntrack_proto_udp.o ip6_conntrack_proto_icmp.o
+
+# Link order matters here.
+ifeq ($(CONFIG_IP6_NF_CONNTRACK),y)
+O_OBJS += ip6_conntrack_standalone.o $(IP6_NF_CONNTRACK_OBJ)
+else
+  ifeq ($(CONFIG_IP6_NF_CONNTRACK),m)
+  MI_OBJS += $(IP6_NF_CONNTRACK_OBJ)
+  MIX_OBJS += ip6_conntrack_standalone.o
+  M_OBJS += ip6_conntrack.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_FTP),y)
+O_OBJS += ip6_conntrack_ftp.o
+else
+  ifeq ($(CONFIG_IP6_NF_FTP),m)
+  MX_OBJS += ip6_conntrack_ftp.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_IPTABLES),y)
+O_OBJS += ip6_tables.o
+else
+  ifeq ($(CONFIG_IP6_NF_IPTABLES),m)
+  MX_OBJS += ip6_tables.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_LIMIT),y)
+O_OBJS += ip6t_limit.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_LIMIT),m)
+  M_OBJS += ip6t_limit.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_MARK),y)
+O_OBJS += ip6t_mark.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_MARK),m)
+  M_OBJS += ip6t_mark.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_MAC),y)
+O_OBJS += ip6t_mac.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_MAC),m)
+  M_OBJS += ip6t_mac.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_MULTIPORT),y)
+O_OBJS += ip6t_multiport.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_MULTIPORT),m)
+  M_OBJS += ip6t_multiport.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_OWNER),y)
+O_OBJS += ip6t_owner.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_OWNER),m)
+  M_OBJS += ip6t_owner.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_TOS),y)
+O_OBJS += ip6t_tos.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_TOS),m)
+  M_OBJS += ip6t_tos.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_STATE),y)
+O_OBJS += ip6t_state.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_STATE),m)
+  M_OBJS += ip6t_state.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_MATCH_UNCLEAN),y)
+O_OBJS += ip6t_unclean.o
+else
+  ifeq ($(CONFIG_IP6_NF_MATCH_UNCLEAN),m)
+  M_OBJS += ip6t_unclean.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_FILTER),y)
+O_OBJS += ip6table_filter.o
+else
+  ifeq ($(CONFIG_IP6_NF_FILTER),m)
+  M_OBJS += ip6table_filter.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_TARGET_REJECT),y)
+O_OBJS += ip6t_REJECT.o
+else
+  ifeq ($(CONFIG_IP6_NF_TARGET_REJECT),m)
+  M_OBJS += ip6t_REJECT.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_TARGET_MIRROR),y)
+O_OBJS += ip6t_MIRROR.o
+else
+  ifeq ($(CONFIG_IP6_NF_TARGET_MIRROR),m)
+  M_OBJS += ip6t_MIRROR.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_TARGET_TOS),y)
+O_OBJS += ip6t_TOS.o
+else
+  ifeq ($(CONFIG_IP6_NF_TARGET_TOS),m)
+  M_OBJS += ip6t_TOS.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_TARGET_MARK),y)
+O_OBJS += ip6t_MARK.o
+else
+  ifeq ($(CONFIG_IP6_NF_TARGET_MARK),m)
+  M_OBJS += ip6t_MARK.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_TARGET_REDIRECT),y)
+O_OBJS += ip6t_REDIRECT.o
+else
+  ifeq ($(CONFIG_IP6_NF_TARGET_REDIRECT),m)
+  M_OBJS += ip6t_REDIRECT.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_TARGET_LOG),y)
+O_OBJS += ip6t_LOG.o
+else
+  ifeq ($(CONFIG_IP6_NF_TARGET_LOG),m)
+  M_OBJS += ip6t_LOG.o
+  endif
+endif
+
+ifeq ($(CONFIG_IP6_NF_QUEUE),y)
+O_OBJS += ip6_queue.o
+else
+  ifeq ($(CONFIG_IP6_NF_QUEUE),m)
+  M_OBJS += ip6_queue.o
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
+
+ip6_conntrack.o: ip6_conntrack_standalone.o $(IP6_NF_CONNTRACK_OBJ)
+	$(LD) -r -o $@ $(IP6_NF_CONNTRACK_OBJ) ip6_conntrack_standalone.o 
+
+ip6fwadm.o: ipfwadm_core.o $(IP6_NF_COMPAT_LAYER)
+	$(LD) -r -o $@ ip6fwadm_core.o $(IP6_NF_COMPAT_LAYER)
+
+ip6chains.o: ip6chains_core.o $(IP6_NF_COMPAT_LAYER) 
+	$(LD) -r -o $@ ip6chains_core.o $(IP6_NF_COMPAT_LAYER)
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/netfilter/ip6_tables.c linux/net/ipv6/netfilter/ip6_tables.c
--- v2.3.99-pre8/linux/net/ipv6/netfilter/ip6_tables.c	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv6/netfilter/ip6_tables.c	Mon May 22 09:50:55 2000
@@ -0,0 +1,1795 @@
+/*
+ * Packet matching code.
+ *
+ * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
+ */
+#include <linux/config.h>
+#include <linux/skbuff.h>
+#include <linux/kmod.h>
+#include <linux/vmalloc.h>
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
+#include <linux/icmp.h>
+#include <net/ip.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <linux/proc_fs.h>
+
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+#define IPV6_HDR_LEN	(sizeof(struct ipv6hdr))
+
+/*#define DEBUG_IP_FIREWALL*/
+/*#define DEBUG_ALLOW_ALL*/ /* Useful for remote debugging */
+/*#define DEBUG_IP_FIREWALL_USER*/
+
+#ifdef DEBUG_IP_FIREWALL
+#define dprintf(format, args...)  printk(format , ## args)
+#else
+#define dprintf(format, args...)
+#endif
+
+#ifdef DEBUG_IP_FIREWALL_USER
+#define duprintf(format, args...) printk(format , ## args)
+#else
+#define duprintf(format, args...)
+#endif
+
+#ifdef CONFIG_NETFILTER_DEBUG
+#define IP_NF_ASSERT(x)						\
+do {								\
+	if (!(x))						\
+		printk("IP_NF_ASSERT: %s:%s:%u\n",		\
+		       __FUNCTION__, __FILE__, __LINE__);	\
+} while(0)
+#else
+#define IP_NF_ASSERT(x)
+#endif
+#define SMP_ALIGN(x) (((x) + SMP_CACHE_BYTES-1) & ~(SMP_CACHE_BYTES-1))
+
+/* Mutex protects lists (only traversed in user context). */
+static DECLARE_MUTEX(ip6t_mutex);
+
+/* Must have mutex */
+#define ASSERT_READ_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
+#define ASSERT_WRITE_LOCK(x) IP_NF_ASSERT(down_trylock(&ip6t_mutex) != 0)
+#include <linux/netfilter_ipv4/lockhelp.h>
+#include <linux/netfilter_ipv4/listhelp.h>
+
+#if 0
+/* All the better to debug you with... */
+#define static
+#define inline
+#endif
+
+/* Locking is simple: we assume at worst case there will be one packet
+   in user context and one from bottom halves (or soft irq if Alexey's
+   softnet patch was applied).
+
+   We keep a set of rules for each CPU, so we can avoid write-locking
+   them; doing a readlock_bh() stops packets coming through if we're
+   in user context.
+
+   To be cache friendly on SMP, we arrange them like so:
+   [ n-entries ]
+   ... cache-align padding ...
+   [ n-entries ]
+
+   Hence the start of any table is given by get_table() below.  */
+
+/* The table itself */
+struct ip6t_table_info
+{
+	/* Size per table */
+	unsigned int size;
+	/* Number of entries: FIXME. --RR */
+	unsigned int number;
+
+	/* Entry points and underflows */
+	unsigned int hook_entry[NF_IP6_NUMHOOKS];
+	unsigned int underflow[NF_IP6_NUMHOOKS];
+
+	char padding[SMP_ALIGN((NF_IP6_NUMHOOKS*2+2)*sizeof(unsigned int))];
+
+	/* ip6t_entry tables: one per CPU */
+	char entries[0];
+};
+
+static LIST_HEAD(ip6t_target);
+static LIST_HEAD(ip6t_match);
+static LIST_HEAD(ip6t_tables);
+#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
+
+#ifdef CONFIG_SMP
+#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*cpu_number_map(p))
+#else
+#define TABLE_OFFSET(t,p) 0
+#endif
+
+#if 0
+#define down(x) do { printk("DOWN:%u:" #x "\n", __LINE__); down(x); } while(0)
+#define down_interruptible(x) ({ int __r; printk("DOWNi:%u:" #x "\n", __LINE__); __r = down_interruptible(x); if (__r != 0) printk("ABORT-DOWNi:%u\n", __LINE__); __r; })
+#define up(x) do { printk("UP:%u:" #x "\n", __LINE__); up(x); } while(0)
+#endif
+
+static int ip6_masked_addrcmp(struct in6_addr addr1, struct in6_addr mask,
+			      struct in6_addr addr2)
+{
+	int i;
+	for( i = 0; i < 16; i++){
+		if((addr1.s6_addr[i] & mask.s6_addr[i]) != 
+		   (addr2.s6_addr[i] & mask.s6_addr[i]))
+			return 1;
+	}
+	return 0;
+}
+
+/* takes in current header and pointer to the header */
+/* if another header exists, sets hdrptr to the next header
+   and returns the new header value, else returns 0 */
+static u_int8_t ip6_nexthdr(u_int8_t currenthdr, u_int8_t *hdrptr)
+{
+	int i;
+	u_int8_t hdrlen, nexthdr = 0;
+	switch(currenthdr){
+		case IPPROTO_AH:
+		/* whoever decided to do the length of AUTH for ipv6
+		in 32bit units unlike other headers should be beaten...
+		repeatedly...with a large stick...no, an even LARGER
+		stick...no, you're still not thinking big enough */
+			nexthdr = *hdrptr;
+			hdrlen = hdrptr[i] * 4 + 8;
+			hdrptr = hdrptr + hdrlen;
+			break;
+		/*stupid rfc2402 */
+		case IPPROTO_DSTOPTS:
+		case IPPROTO_ROUTING:
+		case IPPROTO_HOPOPTS:
+			nexthdr = *hdrptr;
+			hdrlen = hdrptr[1] * 8 + 8;
+			hdrptr = hdrptr + hdrlen;
+			break;
+		case IPPROTO_FRAGMENT:
+			nexthdr = *hdrptr;
+			hdrptr = hdrptr + 8;
+			break;
+	}	
+	return nexthdr;
+
+}
+
+/* Returns whether matches rule or not. */
+static inline int
+ip6_packet_match(const struct ipv6hdr *ipv6,
+		 const char *indev,
+		 const char *outdev,
+		 const struct ip6t_ip6 *ip6info,
+		 int isfrag)
+{
+	size_t i;
+	unsigned long ret;
+
+#define FWINV(bool,invflg) ((bool) ^ !!(ip6info->invflags & invflg))
+
+	if (FWINV(ip6_masked_addrcmp(ipv6->saddr,ip6info->smsk,ip6info->src),
+		  IP6T_INV_SRCIP)
+	    || FWINV(ip6_masked_addrcmp(ipv6->daddr,ip6info->dmsk,ip6info->dst),
+		     IP6T_INV_DSTIP)) {
+		dprintf("Source or dest mismatch.\n");
+/*
+		dprintf("SRC: %u. Mask: %u. Target: %u.%s\n", ip->saddr,
+			ipinfo->smsk.s_addr, ipinfo->src.s_addr,
+			ipinfo->invflags & IP6T_INV_SRCIP ? " (INV)" : "");
+		dprintf("DST: %u. Mask: %u. Target: %u.%s\n", ip->daddr,
+			ipinfo->dmsk.s_addr, ipinfo->dst.s_addr,
+			ipinfo->invflags & IP6T_INV_DSTIP ? " (INV)" : "");*/
+		return 0;
+	}
+
+	/* Look for ifname matches; this should unroll nicely. */
+	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
+		ret |= (((const unsigned long *)indev)[i]
+			^ ((const unsigned long *)ip6info->iniface)[i])
+			& ((const unsigned long *)ip6info->iniface_mask)[i];
+	}
+
+	if (FWINV(ret != 0, IP6T_INV_VIA_IN)) {
+		dprintf("VIA in mismatch (%s vs %s).%s\n",
+			indev, ip6info->iniface,
+			ip6info->invflags&IP6T_INV_VIA_IN ?" (INV)":"");
+		return 0;
+	}
+
+	for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
+		ret |= (((const unsigned long *)outdev)[i]
+			^ ((const unsigned long *)ip6info->outiface)[i])
+			& ((const unsigned long *)ip6info->outiface_mask)[i];
+	}
+
+	if (FWINV(ret != 0, IP6T_INV_VIA_OUT)) {
+		dprintf("VIA out mismatch (%s vs %s).%s\n",
+			outdev, ip6info->outiface,
+			ip6info->invflags&IP6T_INV_VIA_OUT ?" (INV)":"");
+		return 0;
+	}
+
+/* ... might want to do something with class and flowlabel here ... */
+
+	/* look for the desired protocol header */
+	if((ip6info->flags & IP6T_F_PROTO)) {
+		u_int8_t currenthdr = ipv6->nexthdr;
+		u_int8_t *hdrptr;
+		hdrptr = (u_int8_t *)(ipv6 + 1);
+		do {
+			if (ip6info->proto == currenthdr) {
+				if(ip6info->invflags & IP6T_INV_PROTO)
+					return 0;
+				return 1;
+			}
+			currenthdr = ip6_nexthdr(currenthdr, hdrptr);
+		} while(currenthdr);
+		if (!(ip6info->invflags & IP6T_INV_PROTO))
+			return 0;
+	}
+	return 1;
+}
+
+/* should be ip6 safe */
+static inline int 
+ip6_checkentry(const struct ip6t_ip6 *ipv6)
+{
+	if (ipv6->flags & ~IP6T_F_MASK) {
+		duprintf("Unknown flag bits set: %08X\n",
+			 ipv6->flags & ~IP6T_F_MASK);
+		return 0;
+	}
+	if (ipv6->invflags & ~IP6T_INV_MASK) {
+		duprintf("Unknown invflag bits set: %08X\n",
+			 ipv6->invflags & ~IP6T_INV_MASK);
+		return 0;
+	}
+	return 1;
+}
+
+static unsigned int
+ip6t_error(struct sk_buff **pskb,
+	  unsigned int hooknum,
+	  const struct net_device *in,
+	  const struct net_device *out,
+	  const void *targinfo,
+	  void *userinfo)
+{
+	if (net_ratelimit())
+		printk("ip6_tables: error: `%s'\n", (char *)targinfo);
+
+	return NF_DROP;
+}
+
+static inline
+int do_match(struct ip6t_entry_match *m,
+	     const struct sk_buff *skb,
+	     const struct net_device *in,
+	     const struct net_device *out,
+	     int offset,
+	     const void *hdr,
+	     u_int16_t datalen,
+	     int *hotdrop)
+{
+	/* Stop iteration if it doesn't match */
+	if (!m->u.kernel.match->match(skb, in, out, m->data,
+				      offset, hdr, datalen, hotdrop))
+		return 1;
+	else
+		return 0;
+}
+
+static inline struct ip6t_entry *
+get_entry(void *base, unsigned int offset)
+{
+	return (struct ip6t_entry *)(base + offset);
+}
+
+/* Returns one of the generic firewall policies, like NF_ACCEPT. */
+unsigned int
+ip6t_do_table(struct sk_buff **pskb,
+	      unsigned int hook,
+	      const struct net_device *in,
+	      const struct net_device *out,
+	      struct ip6t_table *table,
+	      void *userdata)
+{
+	static const char nulldevname[IFNAMSIZ] = { 0 };
+	u_int16_t offset = 0;
+	struct ipv6hdr *ipv6;
+	void *protohdr;
+	u_int16_t datalen;
+	int hotdrop = 0;
+	/* Initializing verdict to NF_DROP keeps gcc happy. */
+	unsigned int verdict = NF_DROP;
+	const char *indev, *outdev;
+	void *table_base;
+	struct ip6t_entry *e, *back;
+
+	/* Initialization */
+	ipv6 = (*pskb)->nh.ipv6h;
+	protohdr = (u_int32_t *)ipv6 + IPV6_HDR_LEN;
+	datalen = (*pskb)->len - IPV6_HDR_LEN;
+	indev = in ? in->name : nulldevname;
+	outdev = out ? out->name : nulldevname;
+
+	/* We handle fragments by dealing with the first fragment as
+	 * if it was a normal packet.  All other fragments are treated
+	 * normally, except that they will NEVER match rules that ask
+	 * things we don't know, ie. tcp syn flag or ports).  If the
+	 * rule is also a fragment-specific rule, non-fragments won't
+	 * match it. */
+
+	read_lock_bh(&table->lock);
+	IP_NF_ASSERT(table->valid_hooks & (1 << hook));
+	table_base = (void *)table->private->entries
+		+ TABLE_OFFSET(table->private, smp_processor_id());
+	e = get_entry(table_base, table->private->hook_entry[hook]);
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	/* Check noone else using our table */
+	if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac
+	    && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) {
+		printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n",
+		       smp_processor_id(),
+		       table->name,
+		       &((struct ip6t_entry *)table_base)->comefrom,
+		       ((struct ip6t_entry *)table_base)->comefrom);
+	}
+	((struct ip6t_entry *)table_base)->comefrom = 0x57acc001;
+#endif
+
+	/* For return from builtin chain */
+	back = get_entry(table_base, table->private->underflow[hook]);
+
+	do {
+		IP_NF_ASSERT(e);
+		IP_NF_ASSERT(back);
+		(*pskb)->nfcache |= e->nfcache;
+		if (ip6_packet_match(ipv6, indev, outdev, &e->ipv6, offset)) {
+			struct ip6t_entry_target *t;
+
+			if (IP6T_MATCH_ITERATE(e, do_match,
+					       *pskb, in, out,
+					       offset, protohdr,
+					       datalen, &hotdrop) != 0)
+				goto no_match;
+
+			ADD_COUNTER(e->counters, ntohs(ipv6->payload_len) + IPV6_HDR_LEN, 1);
+
+			t = ip6t_get_target(e);
+			IP_NF_ASSERT(t->u.kernel.target);
+			/* Standard target? */
+			if (!t->u.kernel.target->target) {
+				int v;
+
+				v = ((struct ip6t_standard_target *)t)->verdict;
+				if (v < 0) {
+					/* Pop from stack? */
+					if (v != IP6T_RETURN) {
+						verdict = (unsigned)(-v) - 1;
+						break;
+					}
+					e = back;
+					back = get_entry(table_base,
+							 back->comefrom);
+					continue;
+				}
+				if (table_base + v
+				    != (void *)e + e->next_offset) {
+					/* Save old back ptr in next entry */
+					struct ip6t_entry *next
+						= (void *)e + e->next_offset;
+					next->comefrom
+						= (void *)back - table_base;
+					/* set back pointer to next entry */
+					back = next;
+				}
+
+				e = get_entry(table_base, v);
+			} else {
+				/* Targets which reenter must return
+                                   abs. verdicts */
+#ifdef CONFIG_NETFILTER_DEBUG
+				((struct ip6t_entry *)table_base)->comefrom
+					= 0xeeeeeeec;
+#endif
+				verdict = t->u.kernel.target->target(pskb,
+								     hook,
+								     in, out,
+								     t->data,
+								     userdata);
+
+#ifdef CONFIG_NETFILTER_DEBUG
+				if (((struct ip6t_entry *)table_base)->comefrom
+				    != 0xeeeeeeec
+				    && verdict == IP6T_CONTINUE) {
+					printk("Target %s reentered!\n",
+					       t->u.kernel.target->name);
+					verdict = NF_DROP;
+				}
+				((struct ip6t_entry *)table_base)->comefrom
+					= 0x57acc001;
+#endif
+				/* Target might have changed stuff. */
+				ipv6 = (*pskb)->nh.ipv6h;
+				protohdr = (u_int32_t *)ipv6 + IPV6_HDR_LEN;
+				datalen = (*pskb)->len - IPV6_HDR_LEN;
+
+				if (verdict == IP6T_CONTINUE)
+					e = (void *)e + e->next_offset;
+				else
+					/* Verdict */
+					break;
+			}
+		} else {
+
+		no_match:
+			e = (void *)e + e->next_offset;
+		}
+	} while (!hotdrop);
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	((struct ip6t_entry *)table_base)->comefrom = 0xdead57ac;
+#endif
+	read_unlock_bh(&table->lock);
+
+#ifdef DEBUG_ALLOW_ALL
+	return NF_ACCEPT;
+#else
+	if (hotdrop)
+		return NF_DROP;
+	else return verdict;
+#endif
+}
+
+/* If it succeeds, returns element and locks mutex */
+static inline void *
+find_inlist_lock_noload(struct list_head *head,
+			const char *name,
+			int *error,
+			struct semaphore *mutex)
+{
+	void *ret;
+
+#if 1
+	duprintf("find_inlist: searching for `%s' in %s.\n",
+		 name, head == &ip6t_target ? "ip6t_target"
+		 : head == &ip6t_match ? "ip6t_match"
+		 : head == &ip6t_tables ? "ip6t_tables" : "UNKNOWN");
+#endif
+
+	*error = down_interruptible(mutex);
+	if (*error != 0)
+		return NULL;
+
+	ret = list_named_find(head, name);
+	if (!ret) {
+		*error = -ENOENT;
+		up(mutex);
+	}
+	return ret;
+}
+
+#ifndef CONFIG_KMOD
+#define find_inlist_lock(h,n,p,e,m) find_inlist_lock_noload((h),(n),(e),(m))
+#else
+static void *
+find_inlist_lock(struct list_head *head,
+		 const char *name,
+		 const char *prefix,
+		 int *error,
+		 struct semaphore *mutex)
+{
+	void *ret;
+
+	ret = find_inlist_lock_noload(head, name, error, mutex);
+	if (!ret) {
+		char modulename[IP6T_FUNCTION_MAXNAMELEN + strlen(prefix) + 1];
+		strcpy(modulename, prefix);
+		strcat(modulename, name);
+		duprintf("find_inlist: loading `%s'.\n", modulename);
+		request_module(modulename);
+		ret = find_inlist_lock_noload(head, name, error, mutex);
+	}
+
+	return ret;
+}
+#endif
+
+static inline struct ip6t_table *
+find_table_lock(const char *name, int *error, struct semaphore *mutex)
+{
+	return find_inlist_lock(&ip6t_tables, name, "ip6table_", error, mutex);
+}
+
+static inline struct ip6t_match *
+find_match_lock(const char *name, int *error, struct semaphore *mutex)
+{
+	return find_inlist_lock(&ip6t_match, name, "ip6t_", error, mutex);
+}
+
+static inline struct ip6t_target *
+find_target_lock(const char *name, int *error, struct semaphore *mutex)
+{
+	return find_inlist_lock(&ip6t_target, name, "ip6t_", error, mutex);
+}
+
+/* All zeroes == unconditional rule. */
+static inline int
+unconditional(const struct ip6t_ip6 *ipv6)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(*ipv6); i++)
+		if (((char *)ipv6)[i])
+			break;
+
+	return (i == sizeof(*ipv6));
+}
+
+/* Figures out from what hook each rule can be called: returns 0 if
+   there are loops.  Puts hook bitmask in comefrom. */
+static int
+mark_source_chains(struct ip6t_table_info *newinfo, unsigned int valid_hooks)
+{
+	unsigned int hook;
+
+	/* No recursion; use packet counter to save back ptrs (reset
+	   to 0 as we leave), and comefrom to save source hook bitmask */
+	for (hook = 0; hook < NF_IP6_NUMHOOKS; hook++) {
+		unsigned int pos = newinfo->hook_entry[hook];
+		struct ip6t_entry *e
+			= (struct ip6t_entry *)(newinfo->entries + pos);
+
+		if (!(valid_hooks & (1 << hook)))
+			continue;
+
+		/* Set initial back pointer. */
+		e->counters.pcnt = pos;
+
+		for (;;) {
+			struct ip6t_standard_target *t
+				= (void *)ip6t_get_target(e);
+
+			if (e->comefrom & (1 << NF_IP6_NUMHOOKS)) {
+				printk("iptables: loop hook %u pos %u %08X.\n",
+				       hook, pos, e->comefrom);
+				return 0;
+			}
+			e->comefrom
+				|= ((1 << hook) | (1 << NF_IP6_NUMHOOKS));
+
+			/* Unconditional return/END. */
+			if (e->target_offset == sizeof(struct ip6t_entry)
+			    && (strcmp(t->target.u.user.name,
+				       IP6T_STANDARD_TARGET) == 0)
+			    && t->verdict < 0
+			    && unconditional(&e->ipv6)) {
+				unsigned int oldpos, size;
+
+				/* Return: backtrack through the last
+				   big jump. */
+				do {
+					e->comefrom ^= (1<<NF_IP6_NUMHOOKS);
+#ifdef DEBUG_IP_FIREWALL_USER
+					if (e->comefrom
+					    & (1 << NF_IP6_NUMHOOKS)) {
+						duprintf("Back unset "
+							 "on hook %u "
+							 "rule %u\n",
+							 hook, pos);
+					}
+#endif
+					oldpos = pos;
+					pos = e->counters.pcnt;
+					e->counters.pcnt = 0;
+
+					/* We're at the start. */
+					if (pos == oldpos)
+						goto next;
+
+					e = (struct ip6t_entry *)
+						(newinfo->entries + pos);
+				} while (oldpos == pos + e->next_offset);
+
+				/* Move along one */
+				size = e->next_offset;
+				e = (struct ip6t_entry *)
+					(newinfo->entries + pos + size);
+				e->counters.pcnt = pos;
+				pos += size;
+			} else {
+				int newpos = t->verdict;
+
+				if (strcmp(t->target.u.user.name,
+					   IP6T_STANDARD_TARGET) == 0
+				    && newpos >= 0) {
+					/* This a jump; chase it. */
+					duprintf("Jump rule %u -> %u\n",
+						 pos, newpos);
+				} else {
+					/* ... this is a fallthru */
+					newpos = pos + e->next_offset;
+				}
+				e = (struct ip6t_entry *)
+					(newinfo->entries + newpos);
+				e->counters.pcnt = pos;
+				pos = newpos;
+			}
+		}
+		next:
+		duprintf("Finished chain %u\n", hook);
+	}
+	return 1;
+}
+
+static inline int
+cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
+{
+	if (i && (*i)-- == 0)
+		return 1;
+
+	if (m->u.kernel.match->destroy)
+		m->u.kernel.match->destroy(m->data,
+					   m->u.match_size - sizeof(*m));
+
+	if (m->u.kernel.match->me)
+		__MOD_DEC_USE_COUNT(m->u.kernel.match->me);
+
+	return 0;
+}
+
+static inline int
+standard_check(const struct ip6t_entry_target *t,
+	       unsigned int max_offset)
+{
+	struct ip6t_standard_target *targ = (void *)t;
+
+	/* Check standard info. */
+	if (t->u.target_size
+	    != IP6T_ALIGN(sizeof(struct ip6t_standard_target))) {
+		duprintf("standard_check: target size %u != %u\n",
+			 t->u.target_size,
+			 IP6T_ALIGN(sizeof(struct ip6t_standard_target)));
+		return 0;
+	}
+
+	if (targ->verdict >= 0
+	    && targ->verdict > max_offset - sizeof(struct ip6t_entry)) {
+		duprintf("ip6t_standard_check: bad verdict (%i)\n",
+			 targ->verdict);
+		return 0;
+	}
+
+	if (targ->verdict < -NF_MAX_VERDICT - 1) {
+		duprintf("ip6t_standard_check: bad negative verdict (%i)\n",
+			 targ->verdict);
+		return 0;
+	}
+	return 1;
+}
+
+static inline int
+check_match(struct ip6t_entry_match *m,
+	    const char *name,
+	    const struct ip6t_ip6 *ipv6,
+	    unsigned int hookmask,
+	    unsigned int *i)
+{
+	int ret;
+	struct ip6t_match *match;
+
+	match = find_match_lock(m->u.user.name, &ret, &ip6t_mutex);
+	if (!match) {
+	  //		duprintf("check_match: `%s' not found\n", m->u.name);
+		return ret;
+	}
+	if (match->me)
+		__MOD_INC_USE_COUNT(match->me);
+	m->u.kernel.match = match;
+	up(&ip6t_mutex);
+
+	if (m->u.kernel.match->checkentry
+	    && !m->u.kernel.match->checkentry(name, ipv6, m->data,
+					      m->u.match_size - sizeof(*m),
+					      hookmask)) {
+		if (m->u.kernel.match->me)
+			__MOD_DEC_USE_COUNT(m->u.kernel.match->me);
+		duprintf("ip_tables: check failed for `%s'.\n",
+			 m->u.kernel.match->name);
+		return -EINVAL;
+	}
+
+	(*i)++;
+	return 0;
+}
+
+static struct ip6t_target ip6t_standard_target;
+
+static inline int
+check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
+	    unsigned int *i)
+{
+	struct ip6t_entry_target *t;
+	struct ip6t_target *target;
+	int ret;
+	unsigned int j;
+
+	if (!ip6_checkentry(&e->ipv6)) {
+		duprintf("ip_tables: ip check failed %p %s.\n", e, name);
+		return -EINVAL;
+	}
+
+	j = 0;
+	ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
+	if (ret != 0)
+		goto cleanup_matches;
+
+	t = ip6t_get_target(e);
+	target = find_target_lock(t->u.user.name, &ret, &ip6t_mutex);
+	if (!target) {
+	  //		duprintf("check_entry: `%s' not found\n", t->u.name);
+		return ret;
+	}
+	if (target->me)
+		__MOD_INC_USE_COUNT(target->me);
+	t->u.kernel.target = target;
+	up(&ip6t_mutex);
+
+	if (t->u.kernel.target == &ip6t_standard_target) {
+		if (!standard_check(t, size)) {
+			ret = -EINVAL;
+			goto cleanup_matches;
+		}
+	} else if (t->u.kernel.target->checkentry
+		   && !t->u.kernel.target->checkentry(name, e, t->data,
+						      t->u.target_size
+						      - sizeof(*t),
+						      e->comefrom)) {
+		if (t->u.kernel.target->me)
+			__MOD_DEC_USE_COUNT(t->u.kernel.target->me);
+		duprintf("ip_tables: check failed for `%s'.\n",
+			 t->u.kernel.target->name);
+		ret = -EINVAL;
+		goto cleanup_matches;
+	}
+
+	(*i)++;
+	return 0;
+
+ cleanup_matches:
+	IP6T_MATCH_ITERATE(e, cleanup_match, &j);
+	return ret;
+}
+
+static inline int
+check_entry_size_and_hooks(struct ip6t_entry *e,
+			   struct ip6t_table_info *newinfo,
+			   unsigned char *base,
+			   unsigned char *limit,
+			   const unsigned int *hook_entries,
+			   const unsigned int *underflows,
+			   unsigned int *i)
+{
+	unsigned int h;
+
+	if ((unsigned long)e % __alignof__(struct ip6t_entry) != 0
+	    || (unsigned char *)e + sizeof(struct ip6t_entry) >= limit) {
+		duprintf("Bad offset %p\n", e);
+		return -EINVAL;
+	}
+
+	if (e->next_offset
+	    < sizeof(struct ip6t_entry) + sizeof(struct ip6t_entry_target)) {
+		duprintf("checking: element %p size %u\n",
+			 e, e->next_offset);
+		return -EINVAL;
+	}
+
+	/* Check hooks & underflows */
+	for (h = 0; h < NF_IP6_NUMHOOKS; h++) {
+		if ((unsigned char *)e - base == hook_entries[h])
+			newinfo->hook_entry[h] = hook_entries[h];
+		if ((unsigned char *)e - base == underflows[h])
+			newinfo->underflow[h] = underflows[h];
+	}
+
+	/* FIXME: underflows must be unconditional, standard verdicts
+           < 0 (not IP6T_RETURN). --RR */
+
+	/* Clear counters and comefrom */
+	e->counters = ((struct ip6t_counters) { 0, 0 });
+	e->comefrom = 0;
+
+	(*i)++;
+	return 0;
+}
+
+static inline int
+cleanup_entry(struct ip6t_entry *e, unsigned int *i)
+{
+	struct ip6t_entry_target *t;
+
+	if (i && (*i)-- == 0)
+		return 1;
+
+	/* Cleanup all matches */
+	IP6T_MATCH_ITERATE(e, cleanup_match, NULL);
+	t = ip6t_get_target(e);
+	if (t->u.kernel.target->destroy)
+		t->u.kernel.target->destroy(t->data,
+					    t->u.target_size - sizeof(*t));
+	if (t->u.kernel.target->me)
+		__MOD_DEC_USE_COUNT(t->u.kernel.target->me);
+
+	return 0;
+}
+
+/* Checks and translates the user-supplied table segment (held in
+   newinfo) */
+static int
+translate_table(const char *name,
+		unsigned int valid_hooks,
+		struct ip6t_table_info *newinfo,
+		unsigned int size,
+		unsigned int number,
+		const unsigned int *hook_entries,
+		const unsigned int *underflows)
+{
+	unsigned int i;
+	int ret;
+
+	newinfo->size = size;
+	newinfo->number = number;
+
+	/* Init all hooks to impossible value. */
+	for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
+		newinfo->hook_entry[i] = 0xFFFFFFFF;
+		newinfo->underflow[i] = 0xFFFFFFFF;
+	}
+
+	duprintf("translate_table: size %u\n", newinfo->size);
+	i = 0;
+	/* Walk through entries, checking offsets. */
+	ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+				check_entry_size_and_hooks,
+				newinfo,
+				newinfo->entries,
+				newinfo->entries + size,
+				hook_entries, underflows, &i);
+	if (ret != 0)
+		return ret;
+
+	if (i != number) {
+		duprintf("translate_table: %u not %u entries\n",
+			 i, number);
+		return -EINVAL;
+	}
+
+	/* Check hooks all assigned */
+	for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
+		/* Only hooks which are valid */
+		if (!(valid_hooks & (1 << i)))
+			continue;
+		if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
+			duprintf("Invalid hook entry %u %u\n",
+				 i, hook_entries[i]);
+			return -EINVAL;
+		}
+		if (newinfo->underflow[i] == 0xFFFFFFFF) {
+			duprintf("Invalid underflow %u %u\n",
+				 i, underflows[i]);
+			return -EINVAL;
+		}
+	}
+
+	if (!mark_source_chains(newinfo, valid_hooks))
+		return -ELOOP;
+
+	/* Finally, each sanity check must pass */
+	i = 0;
+	ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+				check_entry, name, size, &i);
+
+	if (ret != 0) {
+		IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
+				  cleanup_entry, &i);
+		return ret;
+	}
+
+	/* And one copy for every other CPU */
+	for (i = 1; i < smp_num_cpus; i++) {
+		memcpy(newinfo->entries + SMP_ALIGN(newinfo->size*i),
+		       newinfo->entries,
+		       SMP_ALIGN(newinfo->size));
+	}
+
+	return ret;
+}
+
+static struct ip6t_table_info *
+replace_table(struct ip6t_table *table,
+	      unsigned int num_counters,
+	      struct ip6t_table_info *newinfo,
+	      int *error)
+{
+	struct ip6t_table_info *oldinfo;
+
+#ifdef CONFIG_NETFILTER_DEBUG
+	{
+		struct ip6t_entry *table_base;
+		unsigned int i;
+
+		for (i = 0; i < smp_num_cpus; i++) {
+			table_base =
+				(void *)newinfo->entries
+				+ TABLE_OFFSET(newinfo, i);
+
+			table_base->comefrom = 0xdead57ac;
+		}
+	}
+#endif
+
+	/* Do the substitution. */
+	write_lock_bh(&table->lock);
+	/* Check inside lock: is the old number correct? */
+	if (num_counters != table->private->number) {
+		duprintf("num_counters != table->private->number (%u/%u)\n",
+			 num_counters, table->private->number);
+		write_unlock_bh(&table->lock);
+		*error = -EAGAIN;
+		return NULL;
+	}
+	oldinfo = table->private;
+	table->private = newinfo;
+	write_unlock_bh(&table->lock);
+
+	return oldinfo;
+}
+
+/* Gets counters. */
+static inline int
+add_entry_to_counter(const struct ip6t_entry *e,
+		     struct ip6t_counters total[],
+		     unsigned int *i)
+{
+	ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);
+
+	(*i)++;
+	return 0;
+}
+
+static void
+get_counters(const struct ip6t_table_info *t,
+	     struct ip6t_counters counters[])
+{
+	unsigned int cpu;
+	unsigned int i;
+
+	for (cpu = 0; cpu < smp_num_cpus; cpu++) {
+		i = 0;
+		IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
+				  t->size,
+				  add_entry_to_counter,
+				  counters,
+				  &i);
+	}
+}
+
+static int
+copy_entries_to_user(unsigned int total_size,
+		     struct ip6t_table *table,
+		     void *userptr)
+{
+	unsigned int off, num, countersize;
+	struct ip6t_entry *e;
+	struct ip6t_counters *counters;
+	int ret = 0;
+
+	/* We need atomic snapshot of counters: rest doesn't change
+	   (other than comefrom, which userspace doesn't care
+	   about). */
+	countersize = sizeof(struct ip6t_counters) * table->private->number;
+	counters = vmalloc(countersize);
+
+	if (counters == NULL)
+		return -ENOMEM;
+
+	/* First, sum counters... */
+	memset(counters, 0, countersize);
+	write_lock_bh(&table->lock);
+	get_counters(table->private, counters);
+	write_unlock_bh(&table->lock);
+
+	/* ... then copy entire thing from CPU 0... */
+	if (copy_to_user(userptr, table->private->entries, total_size) != 0) {
+		ret = -EFAULT;
+		goto free_counters;
+	}
+
+	/* FIXME: use iterator macros --RR */
+	/* ... then go back and fix counters and names */
+	for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
+		unsigned int i;
+		struct ip6t_entry_match *m;
+		struct ip6t_entry_target *t;
+
+		e = (struct ip6t_entry *)(table->private->entries + off);
+		if (copy_to_user(userptr + off
+				 + offsetof(struct ip6t_entry, counters),
+				 &counters[num],
+				 sizeof(counters[num])) != 0) {
+			ret = -EFAULT;
+			goto free_counters;
+		}
+
+		for (i = sizeof(struct ip6t_entry);
+		     i < e->target_offset;
+		     i += m->u.match_size) {
+			m = (void *)e + i;
+
+			if (copy_to_user(userptr + off + i
+					 + offsetof(struct ip6t_entry_match,
+						    u.user.name),
+					 m->u.kernel.match->name,
+					 strlen(m->u.kernel.match->name)+1)
+			    != 0) {
+				ret = -EFAULT;
+				goto free_counters;
+			}
+		}
+
+		t = ip6t_get_target(e);
+		if (copy_to_user(userptr + off + e->target_offset
+				 + offsetof(struct ip6t_entry_target,
+					    u.user.name),
+				 t->u.kernel.target->name,
+				 strlen(t->u.kernel.target->name)+1) != 0) {
+			ret = -EFAULT;
+			goto free_counters;
+		}
+	}
+
+ free_counters:
+	vfree(counters);
+	return ret;
+}
+
+static int
+get_entries(const struct ip6t_get_entries *entries,
+	    struct ip6t_get_entries *uptr)
+{
+	int ret;
+	struct ip6t_table *t;
+
+	t = find_table_lock(entries->name, &ret, &ip6t_mutex);
+	if (t) {
+		duprintf("t->private->number = %u\n",
+			 t->private->number);
+		if (entries->size == t->private->size)
+			ret = copy_entries_to_user(t->private->size,
+						   t, uptr->entries);
+		else {
+			duprintf("get_entries: I've got %u not %u!\n",
+				 t->private->size,
+				 entries->size);
+			ret = -EINVAL;
+		}
+		up(&ip6t_mutex);
+	} else
+		duprintf("get_entries: Can't find %s!\n",
+			 entries->name);
+
+	return ret;
+}
+
+static int
+do_replace(void *user, unsigned int len)
+{
+	int ret;
+	struct ip6t_replace tmp;
+	struct ip6t_table *t;
+	struct ip6t_table_info *newinfo, *oldinfo;
+	struct ip6t_counters *counters;
+
+	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+		return -EFAULT;
+
+	newinfo = vmalloc(sizeof(struct ip6t_table_info)
+			  + SMP_ALIGN(tmp.size) * smp_num_cpus);
+	if (!newinfo)
+		return -ENOMEM;
+
+	if (copy_from_user(newinfo->entries, user + sizeof(tmp),
+			   tmp.size) != 0) {
+		ret = -EFAULT;
+		goto free_newinfo;
+	}
+
+	counters = vmalloc(tmp.num_counters * sizeof(struct ip6t_counters));
+	if (!counters) {
+		ret = -ENOMEM;
+		goto free_newinfo;
+	}
+	memset(counters, 0, tmp.num_counters * sizeof(struct ip6t_counters));
+
+	ret = translate_table(tmp.name, tmp.valid_hooks,
+			      newinfo, tmp.size, tmp.num_entries,
+			      tmp.hook_entry, tmp.underflow);
+	if (ret != 0)
+		goto free_newinfo_counters;
+
+	duprintf("ip_tables: Translated table\n");
+
+	t = find_table_lock(tmp.name, &ret, &ip6t_mutex);
+	if (!t)
+		goto free_newinfo_counters_untrans;
+
+	/* You lied! */
+	if (tmp.valid_hooks != t->valid_hooks) {
+		duprintf("Valid hook crap: %08X vs %08X\n",
+			 tmp.valid_hooks, t->valid_hooks);
+		ret = -EINVAL;
+		goto free_newinfo_counters_untrans_unlock;
+	}
+
+	oldinfo = replace_table(t, tmp.num_counters, newinfo, &ret);
+	if (!oldinfo)
+		goto free_newinfo_counters_untrans_unlock;
+
+	/* Get the old counters. */
+	get_counters(oldinfo, counters);
+	/* Decrease module usage counts and free resource */
+	IP6T_ENTRY_ITERATE(oldinfo->entries, oldinfo->size, cleanup_entry,NULL);
+	vfree(oldinfo);
+	/* Silent error: too late now. */
+	copy_to_user(tmp.counters, counters,
+		     sizeof(struct ip6t_counters) * tmp.num_counters);
+	vfree(counters);
+	up(&ip6t_mutex);
+	return 0;
+
+ free_newinfo_counters_untrans_unlock:
+	up(&ip6t_mutex);
+ free_newinfo_counters_untrans:
+	IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size, cleanup_entry,NULL);
+ free_newinfo_counters:
+	vfree(counters);
+ free_newinfo:
+	vfree(newinfo);
+	return ret;
+}
+
+/* We're lazy, and add to the first CPU; overflow works its fey magic
+ * and everything is OK. */
+static inline int
+add_counter_to_entry(struct ip6t_entry *e,
+		     const struct ip6t_counters addme[],
+		     unsigned int *i)
+{
+#if 0
+	duprintf("add_counter: Entry %u %lu/%lu + %lu/%lu\n",
+		 *i,
+		 (long unsigned int)e->counters.pcnt,
+		 (long unsigned int)e->counters.bcnt,
+		 (long unsigned int)addme[*i].pcnt,
+		 (long unsigned int)addme[*i].bcnt);
+#endif
+
+	ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);
+
+	(*i)++;
+	return 0;
+}
+
+static int
+do_add_counters(void *user, unsigned int len)
+{
+	unsigned int i;
+	struct ip6t_counters_info tmp, *paddc;
+	struct ip6t_table *t;
+	int ret;
+
+	if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)
+		return -EFAULT;
+
+	if (len != sizeof(tmp) + tmp.num_counters*sizeof(struct ip6t_counters))
+		return -EINVAL;
+
+	paddc = vmalloc(len);
+	if (!paddc)
+		return -ENOMEM;
+
+	if (copy_from_user(paddc, user, len) != 0) {
+		ret = -EFAULT;
+		goto free;
+	}
+
+	t = find_table_lock(tmp.name, &ret, &ip6t_mutex);
+	if (!t)
+		goto free;
+
+	write_lock_bh(&t->lock);
+	if (t->private->number != paddc->num_counters) {
+		ret = -EINVAL;
+		goto unlock_up_free;
+	}
+
+	i = 0;
+	IP6T_ENTRY_ITERATE(t->private->entries,
+			  t->private->size,
+			  add_counter_to_entry,
+			  paddc->counters,
+			  &i);
+ unlock_up_free:
+	write_unlock_bh(&t->lock);
+	up(&ip6t_mutex);
+ free:
+	vfree(paddc);
+
+	return ret;
+}
+
+static int
+do_ip6t_set_ctl(struct sock *sk,	int cmd, void *user, unsigned int len)
+{
+	int ret;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	switch (cmd) {
+	case IP6T_SO_SET_REPLACE:
+		ret = do_replace(user, len);
+		break;
+
+	case IP6T_SO_SET_ADD_COUNTERS:
+		ret = do_add_counters(user, len);
+		break;
+
+	default:
+		duprintf("do_ip6t_set_ctl:  unknown request %i\n", cmd);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+static int
+do_ip6t_get_ctl(struct sock *sk, int cmd, void *user, int *len)
+{
+	int ret;
+
+	if (!capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	switch (cmd) {
+	case IP6T_SO_GET_INFO: {
+		char name[IP6T_TABLE_MAXNAMELEN];
+		struct ip6t_table *t;
+
+		if (*len != sizeof(struct ip6t_getinfo)) {
+			duprintf("length %u != %u\n", *len,
+				 sizeof(struct ip6t_getinfo));
+			ret = -EINVAL;
+			break;
+		}
+
+		if (copy_from_user(name, user, sizeof(name)) != 0) {
+			ret = -EFAULT;
+			break;
+		}
+		t = find_table_lock(name, &ret, &ip6t_mutex);
+		if (t) {
+			struct ip6t_getinfo info;
+
+			info.valid_hooks = t->valid_hooks;
+			memcpy(info.hook_entry, t->private->hook_entry,
+			       sizeof(info.hook_entry));
+			memcpy(info.underflow, t->private->underflow,
+			       sizeof(info.underflow));
+			info.num_entries = t->private->number;
+			info.size = t->private->size;
+			strcpy(info.name, name);
+
+			if (copy_to_user(user, &info, *len) != 0)
+				ret = -EFAULT;
+			else
+				ret = 0;
+
+			up(&ip6t_mutex);
+		}
+	}
+	break;
+
+	case IP6T_SO_GET_ENTRIES: {
+		struct ip6t_get_entries get;
+
+		if (*len < sizeof(get)) {
+			duprintf("get_entries: %u < %u\n", *len, sizeof(get));
+			ret = -EINVAL;
+		} else if (copy_from_user(&get, user, sizeof(get)) != 0) {
+			ret = -EFAULT;
+		} else if (*len != sizeof(struct ip6t_get_entries) + get.size) {
+			duprintf("get_entries: %u != %u\n", *len,
+				 sizeof(struct ip6t_get_entries) + get.size);
+			ret = -EINVAL;
+		} else
+			ret = get_entries(&get, user);
+		break;
+	}
+
+	default:
+		duprintf("do_ip6t_get_ctl: unknown request %i\n", cmd);
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+/* Registration hooks for targets. */
+int
+ip6t_register_target(struct ip6t_target *target)
+{
+	int ret;
+
+	MOD_INC_USE_COUNT;
+	ret = down_interruptible(&ip6t_mutex);
+	if (ret != 0)
+		return ret;
+
+	if (!list_named_insert(&ip6t_target, target)) {
+		duprintf("ip6t_register_target: `%s' already in list!\n",
+			 target->name);
+		ret = -EINVAL;
+		MOD_DEC_USE_COUNT;
+	}
+	up(&ip6t_mutex);
+	return ret;
+}
+
+void
+ip6t_unregister_target(struct ip6t_target *target)
+{
+	down(&ip6t_mutex);
+	LIST_DELETE(&ip6t_target, target);
+	up(&ip6t_mutex);
+	MOD_DEC_USE_COUNT;
+}
+
+int
+ip6t_register_match(struct ip6t_match *match)
+{
+	int ret;
+
+	MOD_INC_USE_COUNT;
+	ret = down_interruptible(&ip6t_mutex);
+	if (ret != 0) {
+		MOD_DEC_USE_COUNT;
+		return ret;
+	}
+	if (list_named_insert(&ip6t_match, match)) {
+		ret = 0;
+	} else {
+		duprintf("ip6t_register_match: `%s' already in list!\n",
+			 match->name);
+		MOD_DEC_USE_COUNT;
+		ret = -EINVAL;
+	}
+	up(&ip6t_mutex);
+
+	return ret;
+}
+
+void
+ip6t_unregister_match(struct ip6t_match *match)
+{
+	down(&ip6t_mutex);
+	LIST_DELETE(&ip6t_match, match);
+	up(&ip6t_mutex);
+	MOD_DEC_USE_COUNT;
+}
+
+int ip6t_register_table(struct ip6t_table *table)
+{
+	int ret;
+	struct ip6t_table_info *newinfo;
+	static struct ip6t_table_info bootstrap
+		= { 0, 0, { 0 }, { 0 }, { }, { } };
+
+	MOD_INC_USE_COUNT;
+	newinfo = vmalloc(sizeof(struct ip6t_table_info)
+			  + SMP_ALIGN(table->table->size) * smp_num_cpus);
+	if (!newinfo) {
+		ret = -ENOMEM;
+		MOD_DEC_USE_COUNT;
+		return ret;
+	}
+	memcpy(newinfo->entries, table->table->entries, table->table->size);
+
+	ret = translate_table(table->name, table->valid_hooks,
+			      newinfo, table->table->size,
+			      table->table->num_entries,
+			      table->table->hook_entry,
+			      table->table->underflow);
+	if (ret != 0) {
+		vfree(newinfo);
+		MOD_DEC_USE_COUNT;
+		return ret;
+	}
+
+	ret = down_interruptible(&ip6t_mutex);
+	if (ret != 0) {
+		vfree(newinfo);
+		MOD_DEC_USE_COUNT;
+		return ret;
+	}
+
+	/* Don't autoload: we'd eat our tail... */
+	if (list_named_find(&ip6t_tables, table->name)) {
+		ret = -EEXIST;
+		goto free_unlock;
+	}
+
+	/* Simplifies replace_table code. */
+	table->private = &bootstrap;
+	if (!replace_table(table, 0, newinfo, &ret))
+		goto free_unlock;
+
+	duprintf("table->private->number = %u\n",
+		 table->private->number);
+
+	table->lock = RW_LOCK_UNLOCKED;
+	list_prepend(&ip6t_tables, table);
+
+ unlock:
+	up(&ip6t_mutex);
+	return ret;
+
+ free_unlock:
+	vfree(newinfo);
+	MOD_DEC_USE_COUNT;
+	goto unlock;
+}
+
+void ip6t_unregister_table(struct ip6t_table *table)
+{
+	down(&ip6t_mutex);
+	LIST_DELETE(&ip6t_tables, table);
+	up(&ip6t_mutex);
+
+	/* Decrease module usage counts and free resources */
+	IP6T_ENTRY_ITERATE(table->private->entries, table->private->size,
+			  cleanup_entry, NULL);
+	vfree(table->private);
+	MOD_DEC_USE_COUNT;
+}
+
+/* Returns 1 if the port is matched by the range, 0 otherwise */
+static inline int
+port_match(u_int16_t min, u_int16_t max, u_int16_t port, int invert)
+{
+	int ret;
+
+	ret = (port >= min && port <= max) ^ invert;
+	return ret;
+}
+
+static int
+tcp_find_option(u_int8_t option,
+		const struct tcphdr *tcp,
+		u_int16_t datalen,
+		int invert,
+		int *hotdrop)
+{
+	unsigned int i = sizeof(struct tcphdr);
+	const u_int8_t *opt = (u_int8_t *)tcp;
+
+	duprintf("tcp_match: finding option\n");
+	/* If we don't have the whole header, drop packet. */
+	if (tcp->doff * 4 > datalen) {
+		*hotdrop = 1;
+		return 0;
+	}
+
+	while (i < tcp->doff * 4) {
+		if (opt[i] == option) return !invert;
+		if (opt[i] < 2) i++;
+		else i += opt[i+1]?:1;
+	}
+
+	return invert;
+}
+
+static int
+tcp_match(const struct sk_buff *skb,
+	  const struct net_device *in,
+	  const struct net_device *out,
+	  const void *matchinfo,
+	  int offset,
+	  const void *hdr,
+	  u_int16_t datalen,
+	  int *hotdrop)
+{
+	const struct tcphdr *tcp = hdr;
+	const struct ip6t_tcp *tcpinfo = matchinfo;
+
+	/* To quote Alan:
+
+	   Don't allow a fragment of TCP 8 bytes in. Nobody normal
+	   causes this. Its a cracker trying to break in by doing a
+	   flag overwrite to pass the direction checks.
+	*/
+
+	if (offset == 1) {
+		duprintf("Dropping evil TCP offset=1 frag.\n");
+		*hotdrop = 1;
+		return 0;
+	} else if (offset == 0 && datalen < sizeof(struct tcphdr)) {
+		/* We've been asked to examine this packet, and we
+		   can't.  Hence, no choice but to drop. */
+		duprintf("Dropping evil TCP offset=0 tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	/* FIXME: Try tcp doff >> packet len against various stacks --RR */
+
+#define FWINVTCP(bool,invflg) ((bool) ^ !!(tcpinfo->invflags & invflg))
+
+	/* Must not be a fragment. */
+	return !offset
+		&& port_match(tcpinfo->spts[0], tcpinfo->spts[1],
+			      ntohs(tcp->source),
+			      !!(tcpinfo->invflags & IP6T_TCP_INV_SRCPT))
+		&& port_match(tcpinfo->dpts[0], tcpinfo->dpts[1],
+			      ntohs(tcp->dest),
+			      !!(tcpinfo->invflags & IP6T_TCP_INV_DSTPT))
+		&& FWINVTCP((((unsigned char *)tcp)[13]
+			     & tcpinfo->flg_mask)
+			    == tcpinfo->flg_cmp,
+			    IP6T_TCP_INV_FLAGS)
+		&& (!tcpinfo->option
+		    || tcp_find_option(tcpinfo->option, tcp, datalen,
+				       tcpinfo->invflags
+				       & IP6T_TCP_INV_OPTION,
+				       hotdrop));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+tcp_checkentry(const char *tablename,
+	       const struct ip6t_ip6 *ipv6,
+	       void *matchinfo,
+	       unsigned int matchsize,
+	       unsigned int hook_mask)
+{
+	const struct ip6t_tcp *tcpinfo = matchinfo;
+
+	/* Must specify proto == TCP, and no unknown invflags */
+	return ipv6->proto == IPPROTO_TCP
+		&& !(ipv6->invflags & IP6T_INV_PROTO)
+		&& matchsize == IP6T_ALIGN(sizeof(struct ip6t_tcp))
+		&& !(tcpinfo->invflags & ~IP6T_TCP_INV_MASK);
+}
+
+static int
+udp_match(const struct sk_buff *skb,
+	  const struct net_device *in,
+	  const struct net_device *out,
+	  const void *matchinfo,
+	  int offset,
+	  const void *hdr,
+	  u_int16_t datalen,
+	  int *hotdrop)
+{
+	const struct udphdr *udp = hdr;
+	const struct ip6t_udp *udpinfo = matchinfo;
+
+	if (offset == 0 && datalen < sizeof(struct udphdr)) {
+		/* We've been asked to examine this packet, and we
+		   can't.  Hence, no choice but to drop. */
+		duprintf("Dropping evil UDP tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	/* Must not be a fragment. */
+	return !offset
+		&& port_match(udpinfo->spts[0], udpinfo->spts[1],
+			      ntohs(udp->source),
+			      !!(udpinfo->invflags & IP6T_UDP_INV_SRCPT))
+		&& port_match(udpinfo->dpts[0], udpinfo->dpts[1],
+			      ntohs(udp->dest),
+			      !!(udpinfo->invflags & IP6T_UDP_INV_DSTPT));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+udp_checkentry(const char *tablename,
+	       const struct ip6t_ip6 *ipv6,
+	       void *matchinfo,
+	       unsigned int matchinfosize,
+	       unsigned int hook_mask)
+{
+	const struct ip6t_udp *udpinfo = matchinfo;
+
+	/* Must specify proto == UDP, and no unknown invflags */
+	if (ipv6->proto != IPPROTO_UDP || (ipv6->invflags & IP6T_INV_PROTO)) {
+		duprintf("ip6t_udp: Protocol %u != %u\n", ipv6->proto,
+			 IPPROTO_UDP);
+		return 0;
+	}
+	if (matchinfosize != IP6T_ALIGN(sizeof(struct ip6t_udp))) {
+		duprintf("ip6t_udp: matchsize %u != %u\n",
+			 matchinfosize, IP6T_ALIGN(sizeof(struct ip6t_udp)));
+		return 0;
+	}
+	if (udpinfo->invflags & ~IP6T_UDP_INV_MASK) {
+		duprintf("ip6t_udp: unknown flags %X\n",
+			 udpinfo->invflags);
+		return 0;
+	}
+
+	return 1;
+}
+
+/* Returns 1 if the type and code is matched by the range, 0 otherwise */
+static inline int
+icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
+		     u_int8_t type, u_int8_t code,
+		     int invert)
+{
+	return (type == test_type && code >= min_code && code <= max_code)
+		^ invert;
+}
+
+static int
+icmp_match(const struct sk_buff *skb,
+	   const struct net_device *in,
+	   const struct net_device *out,
+	   const void *matchinfo,
+	   int offset,
+	   const void *hdr,
+	   u_int16_t datalen,
+	   int *hotdrop)
+{
+	const struct icmphdr *icmp = hdr;
+	const struct ip6t_icmp *icmpinfo = matchinfo;
+
+	if (offset == 0 && datalen < 2) {
+		/* We've been asked to examine this packet, and we
+		   can't.  Hence, no choice but to drop. */
+		duprintf("Dropping evil ICMP tinygram.\n");
+		*hotdrop = 1;
+		return 0;
+	}
+
+	/* Must not be a fragment. */
+	return !offset
+		&& icmp_type_code_match(icmpinfo->type,
+					icmpinfo->code[0],
+					icmpinfo->code[1],
+					icmp->type, icmp->code,
+					!!(icmpinfo->invflags&IP6T_ICMP_INV));
+}
+
+/* Called when user tries to insert an entry of this type. */
+static int
+icmp_checkentry(const char *tablename,
+	   const struct ip6t_ip6 *ipv6,
+	   void *matchinfo,
+	   unsigned int matchsize,
+	   unsigned int hook_mask)
+{
+	const struct ip6t_icmp *icmpinfo = matchinfo;
+
+	/* Must specify proto == ICMP, and no unknown invflags */
+	return ipv6->proto == IPPROTO_ICMP
+		&& !(ipv6->invflags & IP6T_INV_PROTO)
+		&& matchsize == IP6T_ALIGN(sizeof(struct ip6t_icmp))
+		&& !(icmpinfo->invflags & ~IP6T_ICMP_INV);
+}
+
+/* The built-in targets: standard (NULL) and error. */
+static struct ip6t_target ip6t_standard_target
+= { { NULL, NULL }, IP6T_STANDARD_TARGET, NULL, NULL, NULL };
+static struct ip6t_target ip6t_error_target
+= { { NULL, NULL }, IP6T_ERROR_TARGET, ip6t_error, NULL, NULL };
+
+static struct nf_sockopt_ops ip6t_sockopts
+= { { NULL, NULL }, PF_INET6, IP6T_BASE_CTL, IP6T_SO_SET_MAX+1, do_ip6t_set_ctl,
+    IP6T_BASE_CTL, IP6T_SO_GET_MAX+1, do_ip6t_get_ctl, 0, NULL  };
+
+static struct ip6t_match tcp_matchstruct
+= { { NULL, NULL }, "tcp", &tcp_match, &tcp_checkentry, NULL };
+static struct ip6t_match udp_matchstruct
+= { { NULL, NULL }, "udp", &udp_match, &udp_checkentry, NULL };
+static struct ip6t_match icmp_matchstruct
+= { { NULL, NULL }, "icmp", &icmp_match, &icmp_checkentry, NULL };
+
+#ifdef CONFIG_PROC_FS
+static inline int print_name(const struct ip6t_table *t,
+			     off_t start_offset, char *buffer, int length,
+			     off_t *pos, unsigned int *count)
+{
+	if ((*count)++ >= start_offset) {
+		unsigned int namelen;
+
+		namelen = sprintf(buffer + *pos, "%s\n", t->name);
+		if (*pos + namelen > length) {
+			/* Stop iterating */
+			return 1;
+		}
+		*pos += namelen;
+	}
+	return 0;
+}
+
+static int ip6t_get_tables(char *buffer, char **start, off_t offset, int length)
+{
+	off_t pos = 0;
+	unsigned int count = 0;
+
+	if (down_interruptible(&ip6t_mutex) != 0)
+		return 0;
+
+	LIST_FIND(&ip6t_tables, print_name, struct ip6t_table *,
+		  offset, buffer, length, &pos, &count);
+
+	up(&ip6t_mutex);
+
+	/* `start' hack - see fs/proc/generic.c line ~105 */
+	*start=(char *)((unsigned long)count-offset);
+	return pos;
+}
+#endif /*CONFIG_PROC_FS*/
+
+static int __init init(void)
+{
+	int ret;
+
+	/* Noone else will be downing sem now, so we won't sleep */
+	down(&ip6t_mutex);
+	list_append(&ip6t_target, &ip6t_standard_target);
+	list_append(&ip6t_target, &ip6t_error_target);
+	list_append(&ip6t_match, &tcp_matchstruct);
+	list_append(&ip6t_match, &udp_matchstruct);
+	list_append(&ip6t_match, &icmp_matchstruct);
+	up(&ip6t_mutex);
+
+	/* Register setsockopt */
+	ret = nf_register_sockopt(&ip6t_sockopts);
+	if (ret < 0) {
+		duprintf("Unable to register sockopts.\n");
+		return ret;
+	}
+
+#ifdef CONFIG_PROC_FS
+	if (!proc_net_create("ip6_tables_names", 0, ip6t_get_tables)) {
+		nf_unregister_sockopt(&ip6t_sockopts);
+		return -ENOMEM;
+	}
+#endif
+
+	printk("ip6_tables: (c)2000 Netfilter core team\n");
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	nf_unregister_sockopt(&ip6t_sockopts);
+#ifdef CONFIG_PROC_FS
+	proc_net_remove("ip6_tables_names");
+#endif
+}
+
+module_init(init);
+module_exit(fini);
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/netfilter/ip6t_MARK.c linux/net/ipv6/netfilter/ip6t_MARK.c
--- v2.3.99-pre8/linux/net/ipv6/netfilter/ip6t_MARK.c	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv6/netfilter/ip6t_MARK.c	Mon May 22 09:50:55 2000
@@ -0,0 +1,66 @@
+/* This is a module which is used for setting the NFMARK field of an skb. */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/checksum.h>
+
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_MARK.h>
+
+static unsigned int
+target(struct sk_buff **pskb,
+       unsigned int hooknum,
+       const struct net_device *in,
+       const struct net_device *out,
+       const void *targinfo,
+       void *userinfo)
+{
+	const struct ipt_mark_target_info *markinfo = targinfo;
+
+	if((*pskb)->nfmark != markinfo->mark) {
+		(*pskb)->nfmark = markinfo->mark;
+		(*pskb)->nfcache |= NFC_ALTERED;
+	}
+	return IPT_CONTINUE;
+}
+
+static int
+checkentry(const char *tablename,
+	   const struct ipt_entry *e,
+           void *targinfo,
+           unsigned int targinfosize,
+           unsigned int hook_mask)
+{
+	if (targinfosize != IPT_ALIGN(sizeof(struct ipt_mark_target_info))) {
+		printk(KERN_WARNING "MARK: targinfosize %u != %Zu\n",
+		       targinfosize,
+		       IPT_ALIGN(sizeof(struct ipt_mark_target_info)));
+		return 0;
+	}
+
+	if (strcmp(tablename, "mangle") != 0) {
+		printk(KERN_WARNING "MARK: can only be called from \"mangle\" table, not \"%s\"\n", tablename);
+		return 0;
+	}
+
+	return 1;
+}
+
+static struct ipt_target ipt_mark_reg
+= { { NULL, NULL }, "MARK", target, checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+	if (ipt_register_target(&ipt_mark_reg))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	ipt_unregister_target(&ipt_mark_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/netfilter/ip6t_limit.c linux/net/ipv6/netfilter/ip6t_limit.c
--- v2.3.99-pre8/linux/net/ipv6/netfilter/ip6t_limit.c	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv6/netfilter/ip6t_limit.c	Mon May 22 09:50:55 2000
@@ -0,0 +1,135 @@
+/* Kernel module to control the rate
+ *
+ * Jérôme de Vivie   <devivie@info.enserb.u-bordeaux.fr>
+ * Hervé Eychenne   <eychenne@info.enserb.u-bordeaux.fr>
+ *
+ * 2 September 1999: Changed from the target RATE to the match
+ *                   `limit', removed logging.  Did I mention that
+ *                   Alexey is a fucking genius?
+ *                   Rusty Russell (rusty@rustcorp.com.au).  */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_ipv4/ipt_limit.h>
+
+/* The algorithm used is the Simple Token Bucket Filter (TBF)
+ * see net/sched/sch_tbf.c in the linux source tree
+ */
+
+static spinlock_t limit_lock = SPIN_LOCK_UNLOCKED;
+
+/* Rusty: This is my (non-mathematically-inclined) understanding of
+   this algorithm.  The `average rate' in jiffies becomes your initial
+   amount of credit `credit' and the most credit you can ever have
+   `credit_cap'.  The `peak rate' becomes the cost of passing the
+   test, `cost'.
+
+   `prev' tracks the last packet hit: you gain one credit per jiffy.
+   If you get credit balance more than this, the extra credit is
+   discarded.  Every time the match passes, you lose `cost' credits;
+   if you don't have that many, the test fails.
+
+   See Alexey's formal explanation in net/sched/sch_tbf.c.
+
+   To avoid underflow, we multiply by 128 (ie. you get 128 credits per
+   jiffy).  Hence a cost of 2^32-1, means one pass per 32768 seconds
+   at 1024HZ (or one every 9 hours).  A cost of 1 means 12800 passes
+   per second at 100HZ.  */
+
+#define CREDITS_PER_JIFFY 128
+
+static int
+ipt_limit_match(const struct sk_buff *skb,
+		const struct net_device *in,
+		const struct net_device *out,
+		const void *matchinfo,
+		int offset,
+		const void *hdr,
+		u_int16_t datalen,
+		int *hotdrop)
+{
+	struct ipt_rateinfo *r = ((struct ipt_rateinfo *)matchinfo)->master;
+	unsigned long now = jiffies;
+
+	spin_lock_bh(&limit_lock);
+	r->credit += (now - xchg(&r->prev, now)) * CREDITS_PER_JIFFY;
+	if (r->credit > r->credit_cap)
+		r->credit = r->credit_cap;
+
+	if (r->credit >= r->cost) {
+		/* We're not limited. */
+		r->credit -= r->cost;
+		spin_unlock_bh(&limit_lock);
+		return 1;
+	}
+
+       	spin_unlock_bh(&limit_lock);
+	return 0;
+}
+
+/* Precision saver. */
+static u_int32_t
+user2credits(u_int32_t user)
+{
+	/* If multiplying would overflow... */
+	if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY))
+		/* Divide first. */
+		return (user / IPT_LIMIT_SCALE) * HZ * CREDITS_PER_JIFFY;
+
+	return (user * HZ * CREDITS_PER_JIFFY) / IPT_LIMIT_SCALE;
+}
+
+static int
+ipt_limit_checkentry(const char *tablename,
+		     const struct ip6t_ip6 *ip,
+		     void *matchinfo,
+		     unsigned int matchsize,
+		     unsigned int hook_mask)
+{
+	struct ipt_rateinfo *r = matchinfo;
+
+	if (matchsize != IP6T_ALIGN(sizeof(struct ipt_rateinfo)))
+		return 0;
+
+	/* Check for overflow. */
+	if (r->burst == 0
+	    || user2credits(r->avg * r->burst) < user2credits(r->avg)) {
+		printk("Call rusty: overflow in ipt_limit: %u/%u\n",
+		       r->avg, r->burst);
+		return 0;
+	}
+
+	/* User avg in seconds * IPT_LIMIT_SCALE: convert to jiffies *
+	   128. */
+	r->prev = jiffies;
+	r->credit = user2credits(r->avg * r->burst);	 /* Credits full. */
+	r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */
+	r->cost = user2credits(r->avg);
+
+	/* For SMP, we only want to use one set of counters. */
+	r->master = r;
+
+	return 1;
+}
+
+static struct ip6t_match ipt_limit_reg
+= { { NULL, NULL }, "limit", ipt_limit_match, ipt_limit_checkentry, NULL,
+    THIS_MODULE };
+
+static int __init init(void)
+{
+	if (ip6t_register_match(&ipt_limit_reg))
+		return -EINVAL;
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	ip6t_unregister_match(&ipt_limit_reg);
+}
+
+module_init(init);
+module_exit(fini);
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/netfilter/ip6t_mark.c linux/net/ipv6/netfilter/ip6t_mark.c
--- v2.3.99-pre8/linux/net/ipv6/netfilter/ip6t_mark.c	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv6/netfilter/ip6t_mark.c	Mon May 22 09:50:55 2000
@@ -0,0 +1,50 @@
+/* Kernel module to match NFMARK values. */
+#include <linux/module.h>
+#include <linux/skbuff.h>
+
+#include <linux/netfilter_ipv4/ipt_mark.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+static int
+match(const struct sk_buff *skb,
+      const struct net_device *in,
+      const struct net_device *out,
+      const void *matchinfo,
+      int offset,
+      const void *hdr,
+      u_int16_t datalen,
+      int *hotdrop)
+{
+	const struct ipt_mark_info *info = matchinfo;
+
+	return ((skb->nfmark & info->mask) == info->mark) ^ info->invert;
+}
+
+static int
+checkentry(const char *tablename,
+           const struct ip6t_ip6 *ip,
+           void *matchinfo,
+           unsigned int matchsize,
+           unsigned int hook_mask)
+{
+	if (matchsize != IP6T_ALIGN(sizeof(struct ipt_mark_info)))
+		return 0;
+
+	return 1;
+}
+
+static struct ip6t_match mark_match
+= { { NULL, NULL }, "mark", &match, &checkentry, NULL, THIS_MODULE };
+
+static int __init init(void)
+{
+	return ip6t_register_match(&mark_match);
+}
+
+static void __exit fini(void)
+{
+	ip6t_unregister_match(&mark_match);
+}
+
+module_init(init);
+module_exit(fini);
diff -u --recursive --new-file v2.3.99-pre8/linux/net/ipv6/netfilter/ip6table_filter.c linux/net/ipv6/netfilter/ip6table_filter.c
--- v2.3.99-pre8/linux/net/ipv6/netfilter/ip6table_filter.c	Wed Dec 31 16:00:00 1969
+++ linux/net/ipv6/netfilter/ip6table_filter.c	Mon May 22 09:50:55 2000
@@ -0,0 +1,183 @@
+/*
+ * This is the 1999 rewrite of IP Firewalling, aiming for kernel 2.3.x.
+ *
+ * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
+ */
+#include <linux/module.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+
+#define FILTER_VALID_HOOKS ((1 << NF_IP6_LOCAL_IN) | (1 << NF_IP6_FORWARD) | (1 << NF_IP6_LOCAL_OUT))
+
+/* Standard entry. */
+struct ip6t_standard
+{
+	struct ip6t_entry entry;
+	struct ip6t_standard_target target;
+};
+
+struct ip6t_error_target
+{
+	struct ip6t_entry_target target;
+	char errorname[IP6T_FUNCTION_MAXNAMELEN];
+};
+
+struct ip6t_error
+{
+	struct ip6t_entry entry;
+	struct ip6t_error_target target;
+};
+
+static struct
+{
+	struct ip6t_replace repl;
+	struct ip6t_standard entries[3];
+	struct ip6t_error term;
+} initial_table __initdata
+= { { "filter", FILTER_VALID_HOOKS, 4,
+      sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
+      { [NF_IP6_LOCAL_IN] 0,
+	[NF_IP6_FORWARD] sizeof(struct ip6t_standard),
+	[NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) * 2 },
+      { [NF_IP6_LOCAL_IN] 0,
+	[NF_IP6_FORWARD] sizeof(struct ip6t_standard),
+	[NF_IP6_LOCAL_OUT] sizeof(struct ip6t_standard) * 2 },
+      0, NULL, { } },
+    {
+	    /* LOCAL_IN */
+	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+		0,
+		sizeof(struct ip6t_entry),
+		sizeof(struct ip6t_standard),
+		0, { 0, 0 }, { } },
+	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+		-NF_ACCEPT - 1 } },
+	    /* FORWARD */
+	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+		0,
+		sizeof(struct ip6t_entry),
+		sizeof(struct ip6t_standard),
+		0, { 0, 0 }, { } },
+	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+		-NF_ACCEPT - 1 } },
+	    /* LOCAL_OUT */
+	    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+		0,
+		sizeof(struct ip6t_entry),
+		sizeof(struct ip6t_standard),
+		0, { 0, 0 }, { } },
+	      { { { { IP6T_ALIGN(sizeof(struct ip6t_standard_target)), "" } }, { } },
+		-NF_ACCEPT - 1 } }
+    },
+    /* ERROR */
+    { { { { 0 }, { 0 }, { 0 }, { 0 }, "", "", { 0 }, { 0 }, 0, 0, 0 },
+	0,
+	sizeof(struct ip6t_entry),
+	sizeof(struct ip6t_error),
+	0, { 0, 0 }, { } },
+      { { { { IP6T_ALIGN(sizeof(struct ip6t_error_target)), IP6T_ERROR_TARGET } },
+	  { } },
+	"ERROR"
+      }
+    }
+};
+
+static struct ip6t_table packet_filter
+= { { NULL, NULL }, "filter", &initial_table.repl,
+    FILTER_VALID_HOOKS, RW_LOCK_UNLOCKED, NULL };
+
+/* The work comes in here from netfilter.c. */
+static unsigned int
+ip6t_hook(unsigned int hook,
+	 struct sk_buff **pskb,
+	 const struct net_device *in,
+	 const struct net_device *out,
+	 int (*okfn)(struct sk_buff *))
+{
+	return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL);
+}
+
+static unsigned int
+ip6t_local_out_hook(unsigned int hook,
+		   struct sk_buff **pskb,
+		   const struct net_device *in,
+		   const struct net_device *out,
+		   int (*okfn)(struct sk_buff *))
+{
+#if 0
+	/* root is playing with raw sockets. */
+	if ((*pskb)->len < sizeof(struct iphdr)
+	    || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
+		if (net_ratelimit())
+			printk("ip6t_hook: happy cracking.\n");
+		return NF_ACCEPT;
+	}
+#endif
+
+	return ip6t_do_table(pskb, hook, in, out, &packet_filter, NULL);
+}
+
+static struct nf_hook_ops ip6t_ops[]
+= { { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_LOCAL_IN, NF_IP6_PRI_FILTER },
+    { { NULL, NULL }, ip6t_hook, PF_INET6, NF_IP6_FORWARD, NF_IP6_PRI_FILTER },
+    { { NULL, NULL }, ip6t_local_out_hook, PF_INET6, NF_IP6_LOCAL_OUT,
+		NF_IP6_PRI_FILTER }
+};
+
+/* Default to forward because I got too much mail already. */
+static int forward = NF_ACCEPT;
+MODULE_PARM(forward, "i");
+
+static int __init init(void)
+{
+	int ret;
+
+	if (forward < 0 || forward > NF_MAX_VERDICT) {
+		printk("iptables forward must be 0 or 1\n");
+		return -EINVAL;
+	}
+
+	/* Entry 1 is the FORWARD hook */
+	initial_table.entries[1].target.verdict = -forward - 1;
+
+	/* Register table */
+	ret = ip6t_register_table(&packet_filter);
+	if (ret < 0)
+		return ret;
+
+	/* Register hooks */
+	ret = nf_register_hook(&ip6t_ops[0]);
+	if (ret < 0)
+		goto cleanup_table;
+
+	ret = nf_register_hook(&ip6t_ops[1]);
+	if (ret < 0)
+		goto cleanup_hook0;
+
+	ret = nf_register_hook(&ip6t_ops[2]);
+	if (ret < 0)
+		goto cleanup_hook1;
+
+	return ret;
+
+ cleanup_hook1:
+	nf_unregister_hook(&ip6t_ops[1]);
+ cleanup_hook0:
+	nf_unregister_hook(&ip6t_ops[0]);
+ cleanup_table:
+	ip6t_unregister_table(&packet_filter);
+
+	return ret;
+}
+
+static void __exit fini(void)
+{
+	unsigned int i;
+
+	for (i = 0; i < sizeof(ip6t_ops)/sizeof(struct nf_hook_ops); i++)
+		nf_unregister_hook(&ip6t_ops[i]);
+
+	ip6t_unregister_table(&packet_filter);
+}
+
+module_init(init);
+module_exit(fini);
diff -u --recursive --new-file v2.3.99-pre8/linux/net/sunrpc/auth.c linux/net/sunrpc/auth.c
--- v2.3.99-pre8/linux/net/sunrpc/auth.c	Mon Mar 27 08:08:34 2000
+++ linux/net/sunrpc/auth.c	Sat May 13 09:43:55 2000
@@ -84,6 +84,11 @@
 static inline void
 rpcauth_crdestroy(struct rpc_auth *auth, struct rpc_cred *cred)
 {
+#ifdef RPC_DEBUG
+	if (cred->cr_magic != RPCAUTH_CRED_MAGIC)
+		BUG();
+	cred->cr_magic = 0;
+#endif
 	if (auth->au_ops->crdestroy)
 		auth->au_ops->crdestroy(cred);
 	else
@@ -190,8 +195,13 @@
 	}
 	spin_unlock(&rpc_credcache_lock);
 
-	if (!cred)
+	if (!cred) {
 		cred = auth->au_ops->crcreate(taskflags);
+#ifdef RPC_DEBUG
+		if (cred)
+			cred->cr_magic = RPCAUTH_CRED_MAGIC;
+#endif
+	}
 
 	if (cred)
 		rpcauth_insert_credcache(auth, cred);
diff -u --recursive --new-file v2.3.99-pre8/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.3.99-pre8/linux/net/unix/af_unix.c	Fri May 12 14:18:56 2000
+++ linux/net/unix/af_unix.c	Mon May 22 09:50:55 2000
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.95 2000/05/09 04:48:37 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.96 2000/05/12 23:51:26 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
diff -u --recursive --new-file v2.3.99-pre8/linux/scripts/cramfs/mkcramfs.c linux/scripts/cramfs/mkcramfs.c
--- v2.3.99-pre8/linux/scripts/cramfs/mkcramfs.c	Fri May 12 14:18:56 2000
+++ linux/scripts/cramfs/mkcramfs.c	Sat May 20 11:30:31 2000
@@ -45,7 +45,7 @@
 /* The kernel assumes PAGE_CACHE_SIZE as block size. */
 static unsigned int blksize = PAGE_CACHE_SIZE;
 
-static int warn_dev, warn_gid, warn_link, warn_namelen, warn_size, warn_uid;
+static int warn_dev, warn_gid, warn_namelen, warn_size, warn_uid;
 
 #ifndef MIN
 # define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
@@ -224,21 +224,6 @@
 					perror("mmap");
 					exit(5);
 				}
-				if (st.st_nlink > 1) {
-					/* TODO: Although cramfs doesn't
-					   support hard links, we could still
-					   share data offset values between
-					   different inodes (safe because
-					   read-only).  This would give at
-					   least the space saving of hard
-					   links.  Just keep a hash mapping
-					   <st_ino, st_dev> onto struct
-					   entry*.  Alternatively, steal some
-					   code from Roger Wolff's `same'
-					   program, which creates a hash of
-					   file data contents. */
-					warn_link = 1;
-				}
 			}
 			close(fd);
 		} else if (S_ISLNK(st.st_mode)) {
@@ -618,11 +603,6 @@
 	if (warn_namelen) /* (can't happen when reading from ext2fs) */
 		fprintf(stderr, /* bytes, not chars: think UTF8. */
 			"warning: filenames truncated to 255 bytes.\n");
-	if (warn_link)
-		fprintf(stderr,
-			"warning: cramfs cannot represent hard links.  You may want to change hard links in\n"
-			" %s with symlinks to other files in %s.\n",
-			dirname, dirname);
 	if (warn_size)
 		fprintf(stderr,
 			"warning: file sizes truncated to %luMB (minus 1 byte).\n",
diff -u --recursive --new-file v2.3.99-pre8/linux/scripts/header.tk linux/scripts/header.tk
--- v2.3.99-pre8/linux/scripts/header.tk	Sun Feb 20 21:12:40 2000
+++ linux/scripts/header.tk	Sun May 21 20:18:08 2000
@@ -312,7 +312,7 @@
 	$w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
 				-activeback [cget $w.x$line.l -bg]
 	button $w.x$line.help -text "Help" -relief raised \
-		-command "dohelp .dohelp $helpidx"
+		-command "dohelp .dohelp $helpidx .menu$mnum"
 	pack $w.x$line.help -side right -fill y
 	pack $w.x$line.l -side right -fill both -expand on
 }
@@ -325,9 +325,9 @@
 		-relief groove -width 2 -command "update_active"
 	radiobutton $w.x$line.n -text "n"  -variable $variable -value 0 \
 		-relief groove -width 2 -command "update_active"
-		
+
 	option_name $w $mnum $line $text $variable
-		
+
 	pack $w.x$line.n $w.x$line.m $w.x$line.y -side right -fill y
 }
 
@@ -339,9 +339,9 @@
 		-relief groove -width 2 -command "update_active"
 	radiobutton $w.x$line.n -text "n"  -variable $variable -value 0 \
 		-relief groove -width 2 -command "update_active"
-		
+
 	option_name $w $mnum $line $text $variable
-		
+
 	global CONFIG_MODULES
 	if {($CONFIG_MODULES == 0)} then {
 		$w.x$line.m configure -state disabled
@@ -400,6 +400,17 @@
 	pack $w.x$line -anchor w -fill both -expand on
 }
 
+proc menusplit {w m n} {
+	if { $n > 2 } then {
+		set menuoptsize [expr [$m yposition 2] - [$m yposition 1]]   
+		set maxsize [winfo screenheight $w]
+		set splitpoint [expr $maxsize * 4 / 5 / $menuoptsize - 1]
+		for {set i [expr $splitpoint + 1]} {$i <= $n} {incr i $splitpoint} {
+			$m entryconfigure $i -columnbreak 1
+		}
+	}
+}
+
 proc submenu { w mnum line text subnum } {
 	frame $w.x$line
 	button $w.x$line.l -text "" -width 15 -relief groove
@@ -412,11 +423,20 @@
 	pack $w.x$line -anchor w -fill both -expand on
 }
 
-proc comment {w line text } {
-#nothing done for comments now.
+proc comment {w mnum line text } {
+	frame $w.x$line
+	button $w.x$line.l -text "" -width 15 -relief groove
+	$w.x$line.l configure -activefore [cget $w.x$line.l -fg] \
+		-activeback [cget $w.x$line.l -bg] -state disabled
+	button $w.x$line.m -text "$text" -relief groove -anchor w
+	$w.x$line.m configure -activefore [cget $w.x$line.m -fg] \
+		-activeback [cget $w.x$line.m -bg]
+	pack $w.x$line.l -side left -fill both
+	pack $w.x$line.m -anchor w -side right -fill both -expand on
+	pack $w.x$line -anchor w -fill both -expand on
 }
 
-proc dohelp {w var }  {
+proc dohelp {w var parent}  {
 	catch {destroy $w}
 	toplevel $w -class Dialog
 
@@ -442,45 +462,73 @@
 			" Documentation/Configure.help]
 		set found [expr [string length "$message"] > 0]
 	}
-	
+
 	frame $w.f1
+	pack $w.f1 -fill both -expand on
+
+	# Do the OK button
+	#
+	set oldFocus [focus]
+	frame $w.f2
+	button $w.f2.ok -text "OK" \
+		-width 10 -command "destroy $w; catch {focus $oldFocus}"
+	pack $w.f2.ok -side bottom -pady 6 -anchor n
+	pack $w.f2 -side bottom -padx 10 -anchor s
+
+	scrollbar $w.f1.vscroll -command "$w.f1.canvas yview"
+	pack $w.f1.vscroll -side right -fill y
+
+	canvas $w.f1.canvas -relief flat -borderwidth 0 \
+		-yscrollcommand "$w.f1.vscroll set"
+	frame $w.f1.f
+	pack $w.f1.canvas -side right -fill y -expand on
 
 	if { $found == 0 } then {
 		if { $filefound == 0 } then {
-		message $w.f1.m -width 750 -aspect 300 -relief flat -text \
+		message $w.f1.f.m -width 750 -aspect 300 -relief flat -text \
 			"No help available - unable to open file Documentation/Configure.help.  This file should have come with your kernel."
 		} else {
-		message $w.f1.m -width 400 -aspect 300 -relief flat -text \
+		message $w.f1.f.m -width 400 -aspect 300 -relief flat -text \
 			"No help available for $var"
 		}
 		label $w.f1.bm -bitmap error
 		wm title $w "RTFM"
 	} else {
-		text $w.f1.m -width 73 -relief flat -wrap word
-		$w.f1.m insert 0.0 $message
-		$w.f1.m conf -state disabled  -height [$w.f1.m index end]
+		text $w.f1.f.m -width 73 -relief flat -wrap word
+		$w.f1.f.m insert 0.0 $message
+		$w.f1.f.m conf -state disabled -height [$w.f1.f.m index end]
 
 		label $w.f1.bm -bitmap info
 		wm title $w "Configuration help" 
 	}
-	pack $w.f1.bm $w.f1.m -side left -padx 10
-	pack $w.f1 -side top
-	set oldFocus [focus]
-	
-	# Do the OK button
-	#
-	frame $w.f2
-	button $w.f2.ok -text "OK" \
-		-width 10 -command "destroy $w; catch {focus $oldFocus}"
-	pack $w.f2.ok -side bottom -pady 6 -anchor n
-	pack $w.f2 -side bottom -padx 10 -anchor s
+	pack $w.f1.f.m -side left
+	pack $w.f1.bm $w.f1.f -side left -padx 10
 
-	# Finish off the window
-	#
 	focus $w
-	global winx; global winy
-	set winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]
+	set winx [expr [winfo x $parent]+20]
+	set winy [expr [winfo y $parent]+20]
 	wm geometry $w +$winx+$winy
+	set sizok [expr [winfo reqheight $w.f2.ok] + 12]
+	set maxy [expr [winfo screenheight .] * 3 / 4]
+	set canvtotal [winfo reqheight $w.f1.f.m]
+	if [expr $sizok + $canvtotal < $maxy] {
+		set sizy $canvtotal
+	} else {
+		set sizy [expr $maxy - $sizok]
+	}
+	$w.f1.canvas configure -height $sizy -width [winfo reqwidth $w.f1.f.m] \
+		-scrollregion "0 0 [winfo reqwidth $w.f1.f.m] \
+			[winfo reqheight $w.f1.f.m]"
+	$w.f1.canvas create window 0 0 -anchor nw -window $w.f1.f
+	update idletasks
+
+	set maxy [winfo screenheight .]
+	if [expr $sizok + $canvtotal < $maxy] {
+		set sizy [expr $sizok + $canvtotal]
+	} else {
+		set sizy $maxy
+	}
+	wm maxsize $w [winfo width $w] $sizy
 }
 
 proc wrapup {w }  {
diff -u --recursive --new-file v2.3.99-pre8/linux/scripts/mkdep.c linux/scripts/mkdep.c
--- v2.3.99-pre8/linux/scripts/mkdep.c	Mon Mar 27 08:08:34 2000
+++ linux/scripts/mkdep.c	Mon May 15 15:31:17 2000
@@ -300,7 +300,6 @@
  *    m|#\s*include\s*<(.*?>"|
  *    m|#\s*(?define|undef)\s*CONFIG_(\w*)|
  *    m|(?!\w)CONFIG_|
- *    m|__SMP__|
  *
  * About 98% of the CPU time is spent here, and most of that is in
  * the 'start' paragraph.  Because the current characters are
@@ -325,7 +324,6 @@
 	CASE('"',  dquote);
 	CASE('#',  pound);
 	CASE('C',  cee);
-	CASE('_',  underscore);
 	goto start;
 
 /* / */
@@ -464,18 +462,6 @@
 		goto cee_CONFIG_word;
 	use_config(map_dot, next - map_dot - 1);
 	goto __start;
-
-/* __SMP__ */
-underscore:
-	GETNEXT NOTCASE('_', __start);
-	GETNEXT NOTCASE('S', __start);
-	GETNEXT NOTCASE('M', __start);
-	GETNEXT NOTCASE('P', __start);
-	GETNEXT NOTCASE('_', __start);
-	GETNEXT NOTCASE('_', __start);
-	use_config("SMP", 3);
-	goto __start;
-
     }
 }
 
diff -u --recursive --new-file v2.3.99-pre8/linux/scripts/tail.tk linux/scripts/tail.tk
--- v2.3.99-pre8/linux/scripts/tail.tk	Mon Oct  4 15:49:30 1999
+++ linux/scripts/tail.tk	Sun May 21 20:18:08 2000
@@ -55,6 +55,16 @@
 pack .f0.left .f0.middle .f0.right -side left -padx 5 -pady 0 -fill y
 pack .f0 -padx 5 -pady 5
 
+update idletasks
+set winy [expr 10 + [winfo reqheight .f0]]
+set scry [lindex [wm maxsize .] 1]
+set winx [expr 10 + [winfo reqwidth .f0]]
+set scrx [lindex [wm maxsize .] 0]
+if {$winx < $scrx} then {set maxx -1} else {set maxx $winx}
+if {$winy < $scry} then {set maxy -1} else {set maxy $winy}
+.f0 configure -width $winx -height $winy 
+wm maxsize . $maxx $maxy
+
 #
 # If we cannot write our config files, disable the write button.
 #
diff -u --recursive --new-file v2.3.99-pre8/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v2.3.99-pre8/linux/scripts/tkgen.c	Sun Feb 20 21:12:40 2000
+++ linux/scripts/tkgen.c	Sun May 21 20:18:08 2000
@@ -265,6 +265,8 @@
 	||   cfg->token == token_define_int || cfg->token == token_define_string
 	||   cfg->token == token_define_tristate || cfg->token == token_unset )
 	    return;
+	if ( cfg->token == token_comment && line_num == -1 )
+	    return;
     }
     else
     {
@@ -464,6 +466,7 @@
 		menu_num, line_num );
 	    break;
 
+	case token_comment:
 	case token_mainmenu_option:
 	    if ( line_num >= 0 )
 	    {
@@ -1135,6 +1138,7 @@
 	case token_bool:
 	case token_choice_header:
 	case token_choice_item:
+	case token_comment:
 	case token_dep_bool:
 	case token_dep_tristate:
 	case token_dep_mbool:
@@ -1189,6 +1193,8 @@
     {
 	int menu_line = 0;
 	int nr_submenu = imenu;
+	int menu_name_omitted = 0;
+	int opt_count = 0;
 
 	clear_globalflags();
 	start_proc( menu_first[imenu]->label, imenu, 
@@ -1210,6 +1216,21 @@
 		cfg = menu_last[nr_submenu];
 		break;
 
+	    case token_comment:
+		if ( !cfg->menu_line && !menu_name_omitted )
+		{
+		    cfg->menu_line = -1;
+		    menu_name_omitted = 1;
+		}
+		else
+		{
+		    menu_name_omitted = 1;
+		    cfg->menu_line = menu_line++;
+		    printf( "\tcomment $w.config.f %d %d \"%s\"\n",
+			cfg->menu_number, cfg->menu_line, cfg->label );
+		}
+		break;
+
 	    case token_bool:
 		cfg->menu_line = menu_line++;
 		printf( "\tbool $w.config.f %d %d \"%s\" %s\n",
@@ -1227,8 +1248,10 @@
 		printf( "\tminimenu $w.config.f %d %d \"%s\" tmpvar_%d %s\n",
 		    cfg->menu_number, cfg->menu_line, cfg->label,
 		    -(cfg->nameindex), vartable[cfg->next->nameindex].name );
-		printf( "\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line );
+		printf( "\tmenu $w.config.f.x%d.x.menu -title \"%s\"\n",
+		    cfg->menu_line, cfg->label );
 		cfg1 = cfg;
+		opt_count = 0;
 		break;
 
 	    case token_choice_item:
@@ -1236,6 +1259,12 @@
 		printf( "\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable tmpvar_%d -value \"%s\" -command \"update_active\"\n",
 		    cfg1->menu_line, cfg->label, -(cfg1->nameindex),
 		    cfg->label );
+		opt_count++;
+		if ( cfg->next && cfg->next->token != token_choice_item ) {
+		    /* last option in the menu */
+		    printf( "\tmenusplit $w $w.config.f.x%d.x.menu %d\n",
+			cfg1->menu_line, opt_count );
+		}
 		break;
 
 	    case token_dep_bool:
diff -u --recursive --new-file v2.3.99-pre8/linux/scripts/tkparse.c linux/scripts/tkparse.c
--- v2.3.99-pre8/linux/scripts/tkparse.c	Sun Feb 20 21:12:40 2000
+++ linux/scripts/tkparse.c	Sun May 21 20:18:08 2000
@@ -130,7 +130,7 @@
 static const char * get_qstring( const char * pnt, char ** label )
 {
     char quote_char;
-    char newlabel [1024];
+    char newlabel [2048];
     char * pnt1;
 
     /* advance to the open quote */
@@ -705,7 +705,7 @@
  */
 static void do_source( const char * filename )
 {
-    char buffer [1024];
+    char buffer [2048];
     FILE * infile;
     const char * old_file;
     int old_lineno;
