## Automatically generated incremental diff
## From:   linux-2.4.18-pre3
## To:     linux-2.4.18-pre4
## Robot:  $Id: make-incremental-diff,v 1.9 2001/12/10 00:06:56 hpa Exp $

diff -urN linux-2.4.18-pre3/CREDITS linux/CREDITS
--- linux-2.4.18-pre3/CREDITS	Tue Jan 15 15:10:08 2002
+++ linux/CREDITS	Tue Jan 15 15:10:12 2002
@@ -1282,6 +1282,13 @@
 D: Cobalt Networks (x86) support
 D: This-and-That
 
+N: Tim Hockin
+E: thockin@hockin.org
+W: http://www.hockin.org/~thockin
+D: Natsemi ethernet
+D: Cobalt Networks (x86) support
+D: This-and-That
+
 N: Dirk Hohndel
 E: hohndel@suse.de
 D: The XFree86[tm] Project
diff -urN linux-2.4.18-pre3/Documentation/DMA-mapping.txt linux/Documentation/DMA-mapping.txt
--- linux-2.4.18-pre3/Documentation/DMA-mapping.txt	Tue Jan 15 15:10:09 2002
+++ linux/Documentation/DMA-mapping.txt	Tue Jan 15 15:10:12 2002
@@ -60,6 +60,9 @@
 might be mapped somewhere entirely different than the rest of physical
 memory.
 
+Also, this means that you cannot take the return of a kmap()
+call and DMA to/from that.  This is similar to vmalloc().
+
 What about block I/O and networking buffers?  The block I/O and
 networking subsystems make sure that the buffers they use are valid
 for you to DMA from/to.
diff -urN linux-2.4.18-pre3/Documentation/i386/boot.txt linux/Documentation/i386/boot.txt
--- linux-2.4.18-pre3/Documentation/i386/boot.txt	Tue Jan 15 15:10:09 2002
+++ linux/Documentation/i386/boot.txt	Tue Jan 15 15:10:12 2002
@@ -2,7 +2,7 @@
 		     ----------------------------
 
 		    H. Peter Anvin <hpa@zytor.com>
-			Last update 2001-12-11
+			Last update 2002-01-01
 
 On the i386 platform, the Linux kernel uses a rather complicated boot
 convention.  This has evolved partially due to historical aspects, as
@@ -25,14 +25,14 @@
 Protocol 2.01:	(Kernel 1.3.76) Added a heap overrun warning.
 
 Protocol 2.02:	(Kernel 2.4.0-test3-pre3) New command line protocol.
-		Lower the conventional memory ceiling.  No overwrite
+		Lower the conventional memory ceiling.	No overwrite
 		of the traditional setup area, thus making booting
 		safe for systems which use the EBDA from SMM or 32-bit
 		BIOS entry points.  zImage deprecated but still
 		supported.
 
-Protocol 2.03:	(???) Explicitly makes the highest possible initrd address
-		available to the bootloader.
+Protocol 2.03:	(Kernel 2.4.18-pre1) Explicitly makes the highest possible
+		initrd address available to the bootloader.
 
 
 **** MEMORY LAYOUT
@@ -65,16 +65,16 @@
 When using bzImage, the protected-mode kernel was relocated to
 0x100000 ("high memory"), and the kernel real-mode block (boot sector,
 setup, and stack/heap) was made relocatable to any address between
-0x10000 and end of low memory.  Unfortunately, in protocols 2.00 and
+0x10000 and end of low memory.	Unfortunately, in protocols 2.00 and
 2.01 the command line is still required to live in the 0x9XXXX memory
 range, and that memory range is still overwritten by the early kernel.
-The 2.02 protocol fixes that.
+The 2.02 protocol resolves that problem.
 
 It is desirable to keep the "memory ceiling" -- the highest point in
 low memory touched by the boot loader -- as low as possible, since
 some newer BIOSes have begun to allocate some rather large amounts of
 memory, called the Extended BIOS Data Area, near the top of low
-memory.  The boot loader should use the "INT 12h" BIOS call to verify
+memory.	 The boot loader should use the "INT 12h" BIOS call to verify
 how much low memory is available.
 
 Unfortunately, if INT 12h reports that the amount of memory is too
@@ -115,7 +115,8 @@
 0202/4	2.00+	header		Magic signature "HdrS"
 0206/2	2.00+	version		Boot protocol version supported
 0208/4	2.00+	realmode_swtch	Boot loader hook (see below)
-020C/4	2.00+	start_sys	Points to kernel version string
+020C/2	2.00+	start_sys	The load-low segment (0x1000) (obsolete)
+020E/2	2.00+	kernel_version	Pointer to kernel version string
 0210/1	2.00+	type_of_loader	Boot loader identifier
 0211/1	2.00+	loadflags	Boot protocol option flags
 0212/2	2.00+	setup_move_size	Move to high memory size (used with hooks)
@@ -144,6 +145,15 @@
 setting fields in the header, you must make sure only to set fields
 supported by the protocol version in use.
 
+The "kernel_version" field, if set to a nonzero value, contains a
+pointer to a null-terminated human-readable kernel version number
+string, less 0x200.  This can be used to display the kernel version to
+the user.  This value should be less than (0x200*setup_sects).  For
+example, if this value is set to 0x1c00, the kernel version number
+string can be found at offset 0x1e00 in the kernel file.  This is a
+valid value if and only if the "setup_sects" field contains the value
+14 or higher.
+
 Most boot loaders will simply load the kernel at its target address
 directly.  Such boot loaders do not need to worry about filling in
 most of the fields in the header.  The following fields should be
@@ -164,6 +174,9 @@
 	3  SYSLINUX
 	4  EtherBoot
 
+	Please contact <hpa@zytor.com> if you need a bootloader ID
+	value assigned.
+
   loadflags, heap_end_ptr:
 	If the protocol version is 2.01 or higher, enter the
 	offset limit of the setup heap into heap_end_ptr and set the
@@ -184,9 +197,9 @@
 
 	The initrd should typically be located as high in memory as
 	possible, as it may otherwise get overwritten by the early
-	kernel initialization sequence.  However, it must never be
+	kernel initialization sequence.	 However, it must never be
 	located above the address specified in the initrd_addr_max
-	field.  The initrd should be at least 4K page aligned.
+	field.	The initrd should be at least 4K page aligned.
 
   cmd_line_ptr:
 	If the protocol version is 2.02 or higher, this is a 32-bit
diff -urN linux-2.4.18-pre3/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- linux-2.4.18-pre3/Documentation/networking/ip-sysctl.txt	Wed May 16 10:21:45 2001
+++ linux/Documentation/networking/ip-sysctl.txt	Tue Jan 15 15:10:12 2002
@@ -309,13 +309,20 @@
 	ICMP ECHO requests sent to it or just those to broadcast/multicast
 	addresses, respectively.
 
-icmp_destunreach_rate - INTEGER
-icmp_paramprob_rate - INTEGER
-icmp_timeexceed_rate - INTEGER
-icmp_echoreply_rate - INTEGER (not enabled per default)
-	Limit the maximal rates for sending ICMP packets to specific targets.
+icmp_ratelimit - INTEGER
+	Limit the maximal rates for sending ICMP packets whose type matches
+	icmp_ratemask (see below) to specific targets.
 	0 to disable any limiting, otherwise the maximal rate in jiffies(1)
-	See the source for more information.
+	Default: 1
+
+icmp_ratemask - INTEGER
+	Mask made of ICMP types for which rates are being limited.
+	Default: 6168
+	Note: 6168 = 0x1818 = 1<<ICMP_DEST_UNREACH + 1<<ICMP_SOURCE_QUENCH +
+	      1<<ICMP_TIME_EXCEEDED + 1<<ICMP_PARAMETERPROB, which means
+	      dest unreachable (3), source quench (4), time exceeded (11)
+	      and parameter problem (12) ICMP packets are rate limited
+	      (check values in icmp.h)
 
 icmp_ignore_bogus_error_responses - BOOLEAN
 	Some routers violate RFC 1122 by sending bogus responses to broadcast
@@ -511,4 +518,4 @@
 Pekka Savola
 pekkas@netcore.fi
 
-$Id: ip-sysctl.txt,v 1.19 2001/05/16 17:11:04 davem Exp $
+$Id: ip-sysctl.txt,v 1.19.2.1 2001/12/13 08:59:27 davem Exp $
diff -urN linux-2.4.18-pre3/Documentation/sound/AudioExcelDSP16 linux/Documentation/sound/AudioExcelDSP16
--- linux-2.4.18-pre3/Documentation/sound/AudioExcelDSP16	Sat Nov  6 10:38:40 1999
+++ linux/Documentation/sound/AudioExcelDSP16	Tue Jan 15 15:10:12 2002
@@ -2,7 +2,7 @@
 ------
 
 Informations about Audio Excel DSP 16 driver can be found in the source
-file lowlevel/aedsp16.c
+file aedsp16.c
 Please, read the head of the source before using it. It contain useful
 informations.
 
diff -urN linux-2.4.18-pre3/Makefile linux/Makefile
--- linux-2.4.18-pre3/Makefile	Tue Jan 15 15:10:09 2002
+++ linux/Makefile	Tue Jan 15 15:10:12 2002
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 18
-EXTRAVERSION = -pre3
+EXTRAVERSION = -pre4
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.18-pre3/arch/alpha/kernel/proto.h linux/arch/alpha/kernel/proto.h
--- linux-2.4.18-pre3/arch/alpha/kernel/proto.h	Wed Nov 14 08:18:06 2001
+++ linux/arch/alpha/kernel/proto.h	Tue Jan 15 15:10:12 2002
@@ -106,7 +106,7 @@
 extern void SMC93x_Init(void);
 
 /* smc37c669.c */
-extern void SMC669_Init(int);
+extern int SMC669_Init(int);
 
 /* es1888.c */
 extern void es1888_init(void);
diff -urN linux-2.4.18-pre3/arch/alpha/kernel/smc37c669.c linux/arch/alpha/kernel/smc37c669.c
--- linux-2.4.18-pre3/arch/alpha/kernel/smc37c669.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/alpha/kernel/smc37c669.c	Tue Jan 15 15:10:12 2002
@@ -2528,7 +2528,7 @@
  *
  * RETURNS:
  *
- *      Nothing
+ *      1 if the chip found, 0 otherwise
  *
  * ARGUMENTS:
  *
@@ -2539,7 +2539,7 @@
  *      None
  *
  */
-void __init SMC669_Init ( int index )
+int __init SMC669_Init ( int index )
 {
     SMC37c669_CONFIG_REGS *SMC_base;
     unsigned long flags;
@@ -2602,11 +2602,13 @@
 	__restore_flags(flags);
         printk( "SMC37c669 Super I/O Controller found @ 0x%lx\n",
 		(unsigned long) SMC_base );
+	return 1;
     }
     else {
 	__restore_flags(flags);
 #if SMC_DEBUG
         printk( "No SMC37c669 Super I/O Controller found\n" );
 #endif
+	return 0;
     }
 }
diff -urN linux-2.4.18-pre3/arch/alpha/kernel/sys_miata.c linux/arch/alpha/kernel/sys_miata.c
--- linux-2.4.18-pre3/arch/alpha/kernel/sys_miata.c	Fri Nov  9 13:58:02 2001
+++ linux/arch/alpha/kernel/sys_miata.c	Tue Jan 15 15:10:12 2002
@@ -230,7 +230,15 @@
 miata_init_pci(void)
 {
 	cia_init_pci();
-	SMC669_Init(0); /* it might be a GL (fails harmlessly if not) */
+	/* The PYXIS has data corruption problem with scatter/gather
+	   burst DMA reads crossing 8K boundary. It had been fixed
+	   with off-chip logic on all PYXIS systems except first
+	   MIATAs, so disable SG DMA on such machines. */
+	if (!SMC669_Init(0)) {	/* MIATA GL has SMC37c669 Super I/O */
+		alpha_mv.mv_pci_tbi = NULL; 
+		printk(KERN_INFO "pci: pyxis 8K boundary dma bug - "
+				 "sg dma disabled\n");
+	}
 	es1888_init();
 }
 
diff -urN linux-2.4.18-pre3/arch/sparc/kernel/check_asm.sh linux/arch/sparc/kernel/check_asm.sh
--- linux-2.4.18-pre3/arch/sparc/kernel/check_asm.sh	Tue Oct 30 15:08:11 2001
+++ linux/arch/sparc/kernel/check_asm.sh	Tue Jan 15 15:10:13 2002
@@ -1,12 +1,12 @@
 #!/bin/sh
 case $1 in
   -printf)
-    sed -n -e '/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
+    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
 /g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0	0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0	0x%08x\\n", check_asm_data[i++]);/' >> $4
     echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4
   ;;
   -data)
-    sed -n -e '/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
+    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
 /g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/	((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)),	sizeof(((struct '$2'_struct *)0)->\0),/' >> $4
     echo "	sizeof(struct $2_struct)," >> $4
   ;;
diff -urN linux-2.4.18-pre3/arch/sparc/kernel/devices.c linux/arch/sparc/kernel/devices.c
--- linux-2.4.18-pre3/arch/sparc/kernel/devices.c	Tue Aug 31 11:23:29 1999
+++ linux/arch/sparc/kernel/devices.c	Tue Jan 15 15:10:13 2002
@@ -4,9 +4,10 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/threads.h>
-#include <linux/config.h>
+#include <linux/string.h>
 #include <linux/init.h>
 
 #include <asm/page.h>
diff -urN linux-2.4.18-pre3/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
--- linux-2.4.18-pre3/arch/sparc/kernel/ebus.c	Tue Nov 13 09:16:05 2001
+++ linux/arch/sparc/kernel/ebus.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.18 2001/11/08 04:41:33 davem Exp $
+/* $Id: ebus.c,v 1.18.2.2 2002/01/05 01:12:31 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
diff -urN linux-2.4.18-pre3/arch/sparc/kernel/init_task.c linux/arch/sparc/kernel/init_task.c
--- linux-2.4.18-pre3/arch/sparc/kernel/init_task.c	Mon Sep 17 15:29:09 2001
+++ linux/arch/sparc/kernel/init_task.c	Tue Jan 15 15:10:13 2002
@@ -14,6 +14,6 @@
  * If this is not aligned on a 8k boundry, then you should change code
  * in etrap.S which assumes it.
  */
-union task_union init_task_union
-	__attribute__((__section__(".text"))) =
+__asm__(".section \".text\",#alloc\n");
+union task_union init_task_union =
 		{ INIT_TASK(init_task_union.task) };
diff -urN linux-2.4.18-pre3/arch/sparc/kernel/unaligned.c linux/arch/sparc/kernel/unaligned.c
--- linux-2.4.18-pre3/arch/sparc/kernel/unaligned.c	Wed May  3 01:47:57 2000
+++ linux/arch/sparc/kernel/unaligned.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: unaligned.c,v 1.22 2000/04/29 08:05:21 anton Exp $
+/* $Id: unaligned.c,v 1.22.2.1 2001/12/21 00:52:47 davem Exp $
  * unaligned.c: Unaligned load/store trap handling with special
  *              cases for the kernel to do them more quickly.
  *
@@ -224,7 +224,7 @@
 	"or	%%l1, %%g7, %%g7\n\t"						\
 	"st	%%g7, [%0 + 4]\n"						\
 "0:\n\n\t"									\
-	".section __ex_table\n\t"						\
+	".section __ex_table,#alloc\n\t"					\
 	".word	4b, " #errh "\n\t"						\
 	".word	5b, " #errh "\n\t"						\
 	".word	6b, " #errh "\n\t"						\
@@ -277,7 +277,7 @@
 "16:\t"	"stb	%%l2, [%0]\n"							\
 "17:\t"	"stb	%%l1, [%0 + 1]\n"						\
 "0:\n\n\t"									\
-	".section __ex_table\n\t"						\
+	".section __ex_table,#alloc\n\t"					\
 	".word	4b, " #errh "\n\t"						\
 	".word	5b, " #errh "\n\t"						\
 	".word	6b, " #errh "\n\t"						\
diff -urN linux-2.4.18-pre3/arch/sparc/prom/ranges.c linux/arch/sparc/prom/ranges.c
--- linux-2.4.18-pre3/arch/sparc/prom/ranges.c	Mon Dec 20 22:05:52 1999
+++ linux/arch/sparc/prom/ranges.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: ranges.c,v 1.14 1999/10/06 19:28:54 zaitcev Exp $
+/* $Id: ranges.c,v 1.14.2.1 2001/12/19 00:16:21 davem Exp $
  * ranges.c: Handle ranges in newer proms for obio/sbus.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -16,26 +16,25 @@
 int num_obio_ranges;
 
 /* Adjust register values based upon the ranges parameters. */
-void
+static void
 prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
 		 struct linux_prom_ranges *rangep, int nranges)
 {
 	int regc, rngc;
 
-	for(regc=0; regc < nregs; regc++) {
-		for(rngc=0; rngc < nranges; rngc++)
-			if(regp[regc].which_io == rangep[rngc].ot_child_space &&
-			   regp[regc].phys_addr >= rangep[rngc].ot_child_base &&
-			   regp[regc].phys_addr + regp[regc].reg_size <= rangep[rngc].ot_child_base + rangep[rngc].or_size)
+	for (regc = 0; regc < nregs; regc++) {
+		for (rngc = 0; rngc < nranges; rngc++)
+			if (regp[regc].which_io == rangep[rngc].ot_child_space)
 				break; /* Fount it */
-		if(rngc==nranges) /* oops */
+		if (rngc == nranges) /* oops */
 			prom_printf("adjust_regs: Could not find range with matching bus type...\n");
 		regp[regc].which_io = rangep[rngc].ot_parent_space;
+		regp[regc].phys_addr -= rangep[rngc].ot_child_base;
 		regp[regc].phys_addr += rangep[rngc].ot_parent_base;
 	}
 }
 
-void
+static void
 prom_adjust_ranges(struct linux_prom_ranges *ranges1, int nranges1,
 		   struct linux_prom_ranges *ranges2, int nranges2)
 {
diff -urN linux-2.4.18-pre3/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.4.18-pre3/arch/sparc64/defconfig	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/defconfig	Tue Jan 15 15:10:13 2002
@@ -785,6 +785,8 @@
 CONFIG_USB_OV511=m
 CONFIG_USB_PWC=m
 CONFIG_USB_SE401=m
+CONFIG_USB_STV680=m
+CONFIG_USB_VICAM=m
 CONFIG_USB_DSBR=m
 CONFIG_USB_DABUSB=m
 
@@ -813,6 +815,7 @@
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
 CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
 # CONFIG_USB_SERIAL_IR is not set
 CONFIG_USB_SERIAL_EDGEPORT=m
 CONFIG_USB_SERIAL_KEYSPAN_PDA=m
@@ -826,6 +829,7 @@
 # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
 CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_KLSI=m
 CONFIG_USB_SERIAL_PL2303=m
 CONFIG_USB_SERIAL_CYBERJACK=m
 CONFIG_USB_SERIAL_XIRCOM=m
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/central.c linux/arch/sparc64/kernel/central.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/central.c	Tue Oct  3 09:24:41 2000
+++ linux/arch/sparc64/kernel/central.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: central.c,v 1.14 2000/09/21 06:25:14 anton Exp $
+/* $Id: central.c,v 1.14.2.1 2001/12/19 00:16:21 davem Exp $
  * central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
  *
  * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
@@ -67,6 +67,7 @@
 		if (rngc == nranges) /* oops */
 			prom_printf("adjust_regs: Could not find range with matching bus type...\n");
 		regp[regc].which_io = rangep[rngc].ot_parent_space;
+		regp[regc].phys_addr -= rangep[rngc].ot_child_base;
 		regp[regc].phys_addr += rangep[rngc].ot_parent_base;
 	}
 }
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/check_asm.sh linux/arch/sparc64/kernel/check_asm.sh
--- linux-2.4.18-pre3/arch/sparc64/kernel/check_asm.sh	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/kernel/check_asm.sh	Tue Jan 15 15:10:13 2002
@@ -1,12 +1,12 @@
 #!/bin/sh
 case $1 in
   -printf)
-    sed -n -e '/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
+    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
 /g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/printf ("#define AOFF_'$2'_\0	0x%08x\\n", check_asm_data[i++]); printf("#define ASIZ_'$2'_\0	0x%08x\\n", check_asm_data[i++]);/' >> $4
     echo "printf (\"#define ASIZ_$2\\t0x%08x\\n\", check_asm_data[i++]);" >> $4
   ;;
   -data)
-    sed -n -e '/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
+    sed -n -e '/^#/d;/struct[ 	]*'$2'_struct[ 	]*{/,/};/p' < $3 | sed '/struct[ 	]*'$2'_struct[ 	]*{/d;/:[0-9]*[ 	]*;/d;/^[ 	]*$/d;/};/d;s/^[ 	]*//;s/volatile[ 	]*//;s/\(unsigned\|signed\|struct\)[ 	]*//;s/\(\[\|__attribute__\).*;[ 	]*$//;s/(\*//;s/)(.*)//;s/;[ 	]*$//;s/^[^ 	]*[ 	]*//;s/,/\
 /g' | sed 's/^[ 	*]*//;s/[ 	]*$//;s/^.*$/	((char *)\&((struct '$2'_struct *)0)->\0) - ((char *)((struct '$2'_struct *)0)),	sizeof(((struct '$2'_struct *)0)->\0),/' >> $4
     echo "	sizeof(struct $2_struct)," >> $4
   ;;
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/ioctl32.c	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/kernel/ioctl32.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.133 2001/11/14 06:14:29 davem Exp $
+/* $Id: ioctl32.c,v 1.133.2.1 2002/01/04 21:06:49 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -472,6 +472,7 @@
 		return -ENODEV;
 
 	strcpy(ifr32.ifr_name, dev->name);
+	dev_put(dev);
 
 	err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
 	return (err ? -EFAULT : 0);
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/iommu_common.c linux/arch/sparc64/kernel/iommu_common.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/iommu_common.c	Fri Oct 12 15:35:53 2001
+++ linux/arch/sparc64/kernel/iommu_common.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: iommu_common.c,v 1.6 2001/10/09 02:24:33 davem Exp $
+/* $Id: iommu_common.c,v 1.6.2.1 2001/12/11 22:47:27 davem Exp $
  * iommu_common.c: UltraSparc SBUS/PCI common iommu code.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -66,7 +66,9 @@
 
 	daddr = dma_sg->dma_address;
 	sglen = sg->length;
-	sgaddr = (unsigned long) sg->address;
+	sgaddr = (unsigned long) (sg->address ?
+				  sg->address :
+				  page_address(sg->page) + sg->offset);
 	while (dlen > 0) {
 		unsigned long paddr;
 
@@ -116,7 +118,9 @@
 		sg++;
 		if (--nents <= 0)
 			break;
-		sgaddr = (unsigned long) sg->address;
+		sgaddr = (unsigned long) (sg->address ?
+					  sg->address :
+					  page_address(sg->page) + sg->offset);
 		sglen = sg->length;
 	}
 	if (dlen < 0) {
@@ -197,14 +201,21 @@
 	unsigned long prev;
 	u32 dent_addr, dent_len;
 
-	prev  = (unsigned long) sg->address;
+	prev  = (unsigned long) (sg->address ?
+				 sg->address :
+				 page_address(sg->page) + sg->offset);
 	prev += (unsigned long) (dent_len = sg->length);
-	dent_addr = (u32) ((unsigned long)sg->address & (IO_PAGE_SIZE - 1UL));
+	dent_addr = (u32) ((unsigned long)(sg->address ?
+					   sg->address :
+					   page_address(sg->page) + sg->offset)
+			   & (IO_PAGE_SIZE - 1UL));
 	while (--nents) {
 		unsigned long addr;
 
 		sg++;
-		addr = (unsigned long) sg->address;
+		addr = (unsigned long) (sg->address ?
+					sg->address :
+					page_address(sg->page) + sg->offset);
 		if (! VCONTIG(prev, addr)) {
 			dma_sg->dma_address = dent_addr;
 			dma_sg->dma_length = dent_len;
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/iommu_common.h linux/arch/sparc64/kernel/iommu_common.h
--- linux-2.4.18-pre3/arch/sparc64/kernel/iommu_common.h	Fri Oct 12 15:35:53 2001
+++ linux/arch/sparc64/kernel/iommu_common.h	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: iommu_common.h,v 1.4 2001/10/09 02:24:33 davem Exp $
+/* $Id: iommu_common.h,v 1.4.2.1 2001/12/11 22:47:27 davem Exp $
  * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -6,8 +6,9 @@
 
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
 
-#include <asm/page.h>
 #include <asm/iommu.h>
 #include <asm/scatterlist.h>
 
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/pci_psycho.c	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/kernel/pci_psycho.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.30 2001/11/14 13:17:56 davem Exp $
+/* $Id: pci_psycho.c,v 1.30.2.1 2002/01/05 07:32:29 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -13,6 +13,7 @@
 #include <linux/slab.h>
 
 #include <asm/pbm.h>
+#include <asm/fhc.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
 #include <asm/starfire.h>
@@ -1480,8 +1481,7 @@
 {
 	unsigned int busrange[2];
 	struct pci_pbm_info *pbm;
-	char namebuf[64];
-	int err, len;
+	int err;
 
 	if (is_pbm_a) {
 		pbm = &p->pbm_A;
@@ -1490,13 +1490,9 @@
 		pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_A;
 	} else {
 		pbm = &p->pbm_B;
-		pbm->pci_first_slot = 1;
-		len = prom_getproperty(prom_root_node, "name",
-				       namebuf, sizeof(namebuf));
-		if (len > 0) {
-			if (!strcmp(namebuf, "SUNW,Ultra-1-Engine"))
-				pbm->pci_first_slot = 2;
-		}
+		pbm->pci_first_slot = 2;
+		if (central_bus != NULL)
+			pbm->pci_first_slot = 1;
 		pbm->io_space.start = p->controller_regs + PSYCHO_IOSPACE_B;
 		pbm->mem_space.start = p->controller_regs + PSYCHO_MEMSPACE_B;
 	}
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/power.c	Tue Jun 12 11:08:46 2001
+++ linux/arch/sparc64/kernel/power.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: power.c,v 1.9 2001/06/08 02:28:22 davem Exp $
+/* $Id: power.c,v 1.9.2.1 2001/12/11 01:57:49 davem Exp $
  * power.c: Power management driver.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -61,7 +61,7 @@
 	sprintf(current->comm, "powerd");
 
 again:
-	while(button_pressed == 0) {
+	while (button_pressed == 0) {
 		spin_lock_irq(&current->sigmask_lock);
 		flush_signals(current);
 		spin_unlock_irq(&current->sigmask_lock);
@@ -98,16 +98,19 @@
 found:
 	power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
 	printk("power: Control reg at %016lx ... ", power_reg);
-	if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
-		printk("Failed to start power daemon.\n");
-		return;
-	}
-	printk("powerd running.\n");
-	if (edev->irqs[0] != 0) {
+	if (edev->irqs[0] != PCI_IRQ_NONE) {
+		if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
+			printk("Failed to start power daemon.\n");
+			return;
+		}
+		printk("powerd running.\n");
+
 		if (request_irq(edev->irqs[0],
 				power_handler, SA_SHIRQ, "power",
 				(void *) power_reg) < 0)
 			printk("power: Error, cannot register IRQ handler.\n");
+	} else {
+		printk("not using powerd.\n");
 	}
 }
 #endif /* CONFIG_PCI */
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/process.c	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/kernel/process.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.125 2001/11/17 00:10:48 davem Exp $
+/*  $Id: process.c,v 1.125.2.1 2001/12/18 19:40:17 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -471,6 +471,7 @@
 		csp += STACK_BIAS;
 		psp += STACK_BIAS;
 		__get_user(fp, &(((struct reg_window *)psp)->ins[6]));
+		fp += STACK_BIAS;
 	} else
 		__get_user(fp, &(((struct reg_window32 *)psp)->ins[6]));
 
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S
--- linux-2.4.18-pre3/arch/sparc64/kernel/rtrap.S	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/kernel/rtrap.S	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.57 2001/12/06 00:16:11 davem Exp $
+/* $Id: rtrap.S,v 1.57.2.1 2001/12/24 04:32:33 davem Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -40,8 +40,7 @@
 __handle_user_windows:
 		call			fault_in_user_windows
 		 wrpr			%g0, RTRAP_PSTATE, %pstate
-		ba,pt			%xcc, __handle_user_windows_continue
-		 wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
+		wrpr			%g0, RTRAP_PSTATE_IRQOFF, %pstate
 		/* Redo sched+sig checks */
 		ldx			[%g6 + AOFF_task_need_resched], %l0
 		brz,pt			%l0, 1f
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/smp.c linux/arch/sparc64/kernel/smp.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/smp.c	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/kernel/smp.c	Tue Jan 15 15:10:13 2002
@@ -218,7 +218,7 @@
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
 
-	while (!smp_processors_ready)
+	while (!smp_threads_ready)
 		membar("#LoadLoad");
 }
 
@@ -676,6 +676,39 @@
 			atomic_inc(&dcpage_flushes_xcall);
 #endif
 		}
+	}
+}
+
+void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
+{
+	if (smp_processors_ready) {
+		unsigned long mask = cpu_present_map & ~(1UL << smp_processor_id());
+		u64 data0;
+
+#ifdef CONFIG_DEBUG_DCFLUSH
+		atomic_inc(&dcpage_flushes);
+#endif
+		if (mask == 0UL)
+			goto flush_self;
+		if (tlb_type == spitfire) {
+			data0 = ((u64)&xcall_flush_dcache_page_spitfire);
+			if (page->mapping != NULL)
+				data0 |= ((u64)1 << 32);
+			spitfire_xcall_deliver(data0,
+					       __pa(page->virtual),
+					       (u64) page->virtual,
+					       mask);
+		} else {
+			data0 = ((u64)&xcall_flush_dcache_page_cheetah);
+			cheetah_xcall_deliver(data0,
+					      __pa(page->virtual),
+					      0, mask);
+		}
+#ifdef CONFIG_DEBUG_DCFLUSH
+		atomic_inc(&dcpage_flushes_xcall);
+#endif
+	flush_self:
+		__local_flush_dcache_page(page);
 	}
 }
 
diff -urN linux-2.4.18-pre3/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- linux-2.4.18-pre3/arch/sparc64/kernel/sys_sparc.c	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/kernel/sys_sparc.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.55 2001/11/29 22:52:03 davem Exp $
+/* $Id: sys_sparc.c,v 1.55.2.1 2001/12/21 04:58:23 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -40,12 +40,15 @@
 	return PAGE_SIZE;
 }
 
-#define COLOUR_ALIGN(addr)	(((addr)+SHMLBA-1)&~(SHMLBA-1))
+#define COLOUR_ALIGN(addr,pgoff)		\
+	((((addr)+SHMLBA-1)&~(SHMLBA-1)) +	\
+	 (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
 
 unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags)
 {
 	struct vm_area_struct * vmm;
 	unsigned long task_size = TASK_SIZE;
+	int do_color_align;
 
 	if (flags & MAP_FIXED) {
 		/* We do not accept a shared mapping if it would violate
@@ -63,11 +66,14 @@
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
 
-	if (flags & MAP_SHARED)
-		addr = COLOUR_ALIGN(addr);
+	do_color_align = 0;
+	if (filp || (flags & MAP_SHARED))
+		do_color_align = 1;
+
+	if (do_color_align)
+		addr = COLOUR_ALIGN(addr, pgoff);
 	else
 		addr = PAGE_ALIGN(addr);
-
 	task_size -= len;
 
 	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
@@ -81,8 +87,8 @@
 		if (!vmm || addr + len <= vmm->vm_start)
 			return addr;
 		addr = vmm->vm_end;
-		if (flags & MAP_SHARED)
-			addr = COLOUR_ALIGN(addr);
+		if (do_color_align)
+			addr = COLOUR_ALIGN(addr, pgoff);
 	}
 }
 
diff -urN linux-2.4.18-pre3/arch/sparc64/solaris/timod.c linux/arch/sparc64/solaris/timod.c
--- linux-2.4.18-pre3/arch/sparc64/solaris/timod.c	Fri Dec 21 09:41:53 2001
+++ linux/arch/sparc64/solaris/timod.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: timod.c,v 1.16 2001/09/18 22:29:06 davem Exp $
+/* $Id: timod.c,v 1.16.2.1 2001/12/18 22:15:25 davem Exp $
  * timod.c: timod emulation.
  *
  * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)
diff -urN linux-2.4.18-pre3/drivers/atm/iphase.c linux/drivers/atm/iphase.c
--- linux-2.4.18-pre3/drivers/atm/iphase.c	Mon Sep 17 22:52:34 2001
+++ linux/drivers/atm/iphase.c	Tue Jan 15 15:10:13 2002
@@ -1777,8 +1777,9 @@
         memset((caddr_t)ia_vcc, 0, sizeof(*ia_vcc));
         if (vcc->qos.txtp.max_sdu > 
                          (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){
-           printk("IA:  SDU size over the configured SDU size %d\n",
-                                                          iadev->tx_buf_sz);
+           printk("IA:  SDU size over (%d) the configured SDU size %d\n",
+		  vcc->qos.txtp.max_sdu,iadev->tx_buf_sz);
+	   INPH_IA_VCC(vcc) = NULL;  
            kfree(ia_vcc);
            return -EINVAL; 
         }
diff -urN linux-2.4.18-pre3/drivers/block/floppy.c linux/drivers/block/floppy.c
--- linux-2.4.18-pre3/drivers/block/floppy.c	Fri Dec 21 09:41:53 2001
+++ linux/drivers/block/floppy.c	Tue Jan 15 15:10:13 2002
@@ -3917,7 +3917,7 @@
     {NULL, t360, t1200, t3in+5+8, t3in+5, t3in, t3in};
 
     base_minor = (drive < 4) ? drive : (124 + drive);
-    if (UDP->cmos <= NUMBER(default_drive_params)) {
+    if (UDP->cmos < NUMBER(default_drive_params)) {
 	i = 0;
 	do {
 	    char name[16];
diff -urN linux-2.4.18-pre3/drivers/block/rd.c linux/drivers/block/rd.c
--- linux-2.4.18-pre3/drivers/block/rd.c	Fri Dec 21 09:41:53 2001
+++ linux/drivers/block/rd.c	Tue Jan 15 15:10:13 2002
@@ -191,26 +191,44 @@
  *               2000 Transmeta Corp.
  * aops copied from ramfs.
  */
-static int ramdisk_readpage(struct file *file, struct page * page)
+static void ramdisk_updatepage(struct page * page, int need_kmap)
 {
 	if (!Page_Uptodate(page)) {
-		memset(kmap(page), 0, PAGE_CACHE_SIZE);
-		kunmap(page);
+		struct buffer_head *bh = page->buffers;
+		void * address;
+
+		if (need_kmap)
+			kmap(page);
+		address = page_address(page);
+		if (bh) {
+			struct buffer_head *tmp = bh;
+			do {
+				if (!buffer_uptodate(tmp)) {
+					memset(address, 0, tmp->b_size);
+					mark_buffer_uptodate(tmp, 1);
+				}
+				address += tmp->b_size;
+				tmp = tmp->b_this_page;
+			} while (tmp != bh);
+		} else
+			memset(address, 0, PAGE_CACHE_SIZE);
+		if (need_kmap)
+			kunmap(page);
 		flush_dcache_page(page);
 		SetPageUptodate(page);
 	}
+}
+
+static int ramdisk_readpage(struct file *file, struct page * page)
+{
+	ramdisk_updatepage(page, 1);
 	UnlockPage(page);
 	return 0;
 }
 
 static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
 {
-	if (!Page_Uptodate(page)) {
-		void *addr = page_address(page);
-		memset(addr, 0, PAGE_CACHE_SIZE);
-		flush_dcache_page(page);
-		SetPageUptodate(page);
-	}
+	ramdisk_updatepage(page, 0);
 	SetPageDirty(page);
 	return 0;
 }
@@ -233,44 +251,40 @@
 	unsigned long index;
 	int offset, size, err;
 
-	err = -EIO;
 	err = 0;
 	mapping = rd_bdev[minor]->bd_inode->i_mapping;
 
+	/* writing a buffer cache not uptodate must not clear it */
+	if (sbh->b_page->mapping == mapping) {
+		if (rw == WRITE) {
+			mark_buffer_uptodate(sbh, 1);
+			SetPageDirty(sbh->b_page);
+		}
+		goto out;
+	}
+
 	index = sbh->b_rsector >> (PAGE_CACHE_SHIFT - 9);
 	offset = (sbh->b_rsector << 9) & ~PAGE_CACHE_MASK;
 	size = sbh->b_size;
 
 	do {
 		int count;
-		struct page ** hash;
 		struct page * page;
 		char * src, * dst;
-		int unlock = 0;
 
 		count = PAGE_CACHE_SIZE - offset;
 		if (count > size)
 			count = size;
 		size -= count;
 
-		hash = page_hash(mapping, index);
-		page = __find_get_page(mapping, index, hash);
+		page = grab_cache_page(mapping, index);
 		if (!page) {
-			page = grab_cache_page(mapping, index);
 			err = -ENOMEM;
-			if (!page)
-				goto out;
-			err = 0;
-
-			if (!Page_Uptodate(page)) {
-				memset(kmap(page), 0, PAGE_CACHE_SIZE);
-				kunmap(page);
-				SetPageUptodate(page);
-			}
-
-			unlock = 1;
+			goto out;
 		}
 
+		ramdisk_updatepage(page, 1);
+
 		index++;
 
 		if (rw == READ) {
@@ -294,8 +308,7 @@
 		} else {
 			SetPageDirty(page);
 		}
-		if (unlock)
-			UnlockPage(page);
+		UnlockPage(page);
 		__free_page(page);
 	} while (size);
 
diff -urN linux-2.4.18-pre3/drivers/char/drm/Config.in linux/drivers/char/drm/Config.in
--- linux-2.4.18-pre3/drivers/char/drm/Config.in	Tue Jan 15 15:10:09 2002
+++ linux/drivers/char/drm/Config.in	Tue Jan 15 15:10:13 2002
@@ -6,7 +6,7 @@
 #
 
 tristate '  3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX
-tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA
+#tristate '  3dlabs GMX 2000' CONFIG_DRM_GAMMA
 tristate '  ATI Rage 128' CONFIG_DRM_R128
 dep_tristate '  ATI Radeon' CONFIG_DRM_RADEON $CONFIG_AGP
 dep_tristate '  Intel I810' CONFIG_DRM_I810 $CONFIG_AGP
diff -urN linux-2.4.18-pre3/drivers/char/drm-4.0/ffb_context.c linux/drivers/char/drm-4.0/ffb_context.c
--- linux-2.4.18-pre3/drivers/char/drm-4.0/ffb_context.c	Tue Jan 15 15:10:09 2002
+++ linux/drivers/char/drm-4.0/ffb_context.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: ffb_context.c,v 1.1 2002/01/09 21:56:59 marcelo Exp $
+/* $Id: ffb_context.c,v 1.4 2000/08/29 07:01:55 davem Exp $
  * ffb_context.c: Creator/Creator3D DRI/DRM context switching.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
diff -urN linux-2.4.18-pre3/drivers/char/drm-4.0/ffb_drv.c linux/drivers/char/drm-4.0/ffb_drv.c
--- linux-2.4.18-pre3/drivers/char/drm-4.0/ffb_drv.c	Tue Jan 15 15:10:09 2002
+++ linux/drivers/char/drm-4.0/ffb_drv.c	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: ffb_drv.c,v 1.1 2002/01/09 21:56:59 marcelo Exp $
+/* $Id: ffb_drv.c,v 1.14 2001/05/24 12:01:47 davem Exp $
  * ffb_drv.c: Creator/Creator3D direct rendering driver.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
diff -urN linux-2.4.18-pre3/drivers/char/drm-4.0/ffb_drv.h linux/drivers/char/drm-4.0/ffb_drv.h
--- linux-2.4.18-pre3/drivers/char/drm-4.0/ffb_drv.h	Tue Jan 15 15:10:09 2002
+++ linux/drivers/char/drm-4.0/ffb_drv.h	Tue Jan 15 15:10:13 2002
@@ -1,4 +1,4 @@
-/* $Id: ffb_drv.h,v 1.1 2002/01/09 21:56:59 marcelo Exp $
+/* $Id: ffb_drv.h,v 1.1 2000/06/01 04:24:39 davem Exp $
  * ffb_drv.h: Creator/Creator3D direct rendering driver.
  *
  * Copyright (C) 2000 David S. Miller (davem@redhat.com)
diff -urN linux-2.4.18-pre3/drivers/char/mxser.c linux/drivers/char/mxser.c
--- linux-2.4.18-pre3/drivers/char/mxser.c	Thu Oct 25 13:53:47 2001
+++ linux/drivers/char/mxser.c	Tue Jan 15 15:10:13 2002
@@ -614,38 +614,35 @@
 		n = (sizeof(mxser_pcibrds) / sizeof(mxser_pcibrds[0])) - 1;
 		index = 0;
 		for (b = 0; b < n; b++) {
-			pdev = pci_find_device(mxser_pcibrds[b].vendor,
-					       mxser_pcibrds[b].device, pdev);
-			if (!pdev || pci_enable_device(pdev))
-				continue;
-			hwconf.pdev = pdev;
-			printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
-				mxser_brdname[mxser_pcibrds[b].driver_data],
-				pdev->bus->number, PCI_SLOT(pdev->devfn));
-			if (m >= MXSER_BOARDS) {
-				printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
-			} else {
-				retval = mxser_get_PCI_conf(pdev,
-				   mxser_pcibrds[b].driver_data, &hwconf);
-				if (retval < 0) {
-					if (retval == MXSER_ERR_IRQ)
-						printk("Invalid interrupt number,board not configured\n");
-					else if (retval == MXSER_ERR_IRQ_CONFLIT)
-						printk("Invalid interrupt number,board not configured\n");
-					else if (retval == MXSER_ERR_VECTOR)
-						printk("Invalid interrupt vector,board not configured\n");
-					else if (retval == MXSER_ERR_IOADDR)
-						printk("Invalid I/O address,board not configured\n");
+			while (pdev = pci_find_device(mxser_pcibrds[b].vendor, mxser_pcibrds[b].device, pdev)) 
+			{
+				if (pci_enable_device(pdev))
 					continue;
-
+				hwconf.pdev = pdev;
+				printk("Found MOXA %s board(BusNo=%d,DevNo=%d)\n",
+					mxser_brdname[mxser_pcibrds[b].driver_data],
+				pdev->bus->number, PCI_SLOT(pdev->devfn));
+				if (m >= MXSER_BOARDS) {
+					printk("Too many Smartio family boards found (maximum %d),board not configured\n", MXSER_BOARDS);
+				} else {
+					retval = mxser_get_PCI_conf(pdev, mxser_pcibrds[b].driver_data, &hwconf);
+					if (retval < 0) {
+						if (retval == MXSER_ERR_IRQ)
+							printk("Invalid interrupt number,board not configured\n");
+						else if (retval == MXSER_ERR_IRQ_CONFLIT)
+							printk("Invalid interrupt number,board not configured\n");	
+						else if (retval == MXSER_ERR_VECTOR)
+							printk("Invalid interrupt vector,board not configured\n");
+						else if (retval == MXSER_ERR_IOADDR)
+							printk("Invalid I/O address,board not configured\n");
+						continue;
+					}
+					if (mxser_initbrd(m, &hwconf) < 0)
+						continue;
+					mxser_getcfg(m, &hwconf);
+					m++;
 				}
-				if (mxser_initbrd(m, &hwconf) < 0)
-					continue;
-				mxser_getcfg(m, &hwconf);
-				m++;
-
 			}
-
 		}
 	}
 #endif
diff -urN linux-2.4.18-pre3/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- linux-2.4.18-pre3/drivers/char/tty_io.c	Tue Jan 15 15:10:09 2002
+++ linux/drivers/char/tty_io.c	Tue Jan 15 15:10:13 2002
@@ -697,8 +697,13 @@
 {
 	ssize_t ret = 0, written = 0;
 	
-	if (down_interruptible(&tty->atomic_write)) {
-		return -ERESTARTSYS;
+	if (file->f_flags & O_NONBLOCK) {
+		if (down_trylock(&tty->atomic_write))
+			return -EAGAIN;
+	}
+	else {
+		if (down_interruptible(&tty->atomic_write))
+			return -ERESTARTSYS;
 	}
 	if ( test_bit(TTY_NO_WRITE_SPLIT, &tty->flags) ) {
 		lock_kernel();
diff -urN linux-2.4.18-pre3/drivers/i2c/i2c-proc.c linux/drivers/i2c/i2c-proc.c
--- linux-2.4.18-pre3/drivers/i2c/i2c-proc.c	Thu Oct 11 08:05:47 2001
+++ linux/drivers/i2c/i2c-proc.c	Tue Jan 15 15:10:15 2002
@@ -119,6 +119,10 @@
 		sprintf(name_buffer, "%s-i2c-%d-%02x", prefix, id, addr);
 	}
 	*name = kmalloc(strlen(name_buffer) + 1, GFP_KERNEL);
+	if (!*name) {
+		printk (KERN_WARNING "i2c_create_name: not enough memory\n");
+		return -ENOMEM;
+	}
 	strcpy(*name, name_buffer);
 	return 0;
 }
diff -urN linux-2.4.18-pre3/drivers/md/md.c linux/drivers/md/md.c
--- linux-2.4.18-pre3/drivers/md/md.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/md/md.c	Tue Jan 15 15:10:15 2002
@@ -1000,6 +1000,11 @@
 	struct md_list_head *tmp;
 	mdk_rdev_t *rdev;
 
+	if (!mddev->sb_dirty) {
+		printk("hm, md_update_sb() called without ->sb_dirty == 1, from %p.\n", __builtin_return_address(0));
+		return 0;
+	}
+	mddev->sb_dirty = 0;
 repeat:
 	mddev->sb->utime = CURRENT_TIME;
 	if ((++mddev->sb->events_lo)==0)
@@ -1724,6 +1729,7 @@
 	}
 
 	mddev->sb->state &= ~(1 << MD_SB_CLEAN);
+	mddev->sb_dirty = 1;
 	md_update_sb(mddev);
 
 	/*
@@ -1841,6 +1847,7 @@
 				printk(KERN_INFO "md: marking sb clean...\n");
 				mddev->sb->state |= 1 << MD_SB_CLEAN;
 			}
+			mddev->sb_dirty = 1;
 			md_update_sb(mddev);
 		}
 		if (ro)
@@ -2464,7 +2471,6 @@
 	mddev->sb->working_disks++;
 
 	mddev->sb_dirty = 1;
-
 	md_update_sb(mddev);
 
 	/*
@@ -3515,6 +3521,8 @@
 			continue;
 		if (sb->active_disks == sb->raid_disks)
 			continue;
+		if (mddev->sb_dirty)
+			md_update_sb(mddev);
 		if (!sb->spare_disks) {
 			printk(KERN_ERR "md%d: no spare disk to reconstruct array! "
 			       "-- continuing in degraded mode\n", mdidx(mddev));
diff -urN linux-2.4.18-pre3/drivers/md/multipath.c linux/drivers/md/multipath.c
--- linux-2.4.18-pre3/drivers/md/multipath.c	Mon Nov 12 09:51:56 2001
+++ linux/drivers/md/multipath.c	Tue Jan 15 15:10:15 2002
@@ -701,11 +701,8 @@
 		md_spin_unlock_irqrestore(&retry_list_lock, flags);
 
 		mddev = mp_bh->mddev;
-		if (mddev->sb_dirty) {
-			printk(KERN_INFO "dirty sb detected, updating.\n");
-			mddev->sb_dirty = 0;
+		if (mddev->sb_dirty)
 			md_update_sb(mddev);
-		}
 		bh = &mp_bh->bh_req;
 		dev = bh->b_dev;
 		
diff -urN linux-2.4.18-pre3/drivers/md/raid1.c linux/drivers/md/raid1.c
--- linux-2.4.18-pre3/drivers/md/raid1.c	Wed Oct 17 14:21:00 2001
+++ linux/drivers/md/raid1.c	Tue Jan 15 15:10:15 2002
@@ -1136,11 +1136,8 @@
 		md_spin_unlock_irqrestore(&retry_list_lock, flags);
 
 		mddev = r1_bh->mddev;
-		if (mddev->sb_dirty) {
-			printk(KERN_INFO "raid1: dirty sb detected, updating.\n");
-			mddev->sb_dirty = 0;
+		if (mddev->sb_dirty)
 			md_update_sb(mddev);
-		}
 		bh = &r1_bh->bh_req;
 		switch(r1_bh->cmd) {
 		case SPECIAL:
diff -urN linux-2.4.18-pre3/drivers/md/raid5.c linux/drivers/md/raid5.c
--- linux-2.4.18-pre3/drivers/md/raid5.c	Wed Oct 17 14:21:00 2001
+++ linux/drivers/md/raid5.c	Tue Jan 15 15:10:15 2002
@@ -1293,10 +1293,8 @@
 
 	handled = 0;
 
-	if (mddev->sb_dirty) {
-		mddev->sb_dirty = 0;
+	if (mddev->sb_dirty)
 		md_update_sb(mddev);
-	}
 	md_spin_lock_irq(&conf->device_lock);
 	while (1) {
 		struct list_head *first;
diff -urN linux-2.4.18-pre3/drivers/media/radio/radio-gemtek-pci.c linux/drivers/media/radio/radio-gemtek-pci.c
--- linux-2.4.18-pre3/drivers/media/radio/radio-gemtek-pci.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/media/radio/radio-gemtek-pci.c	Tue Jan 15 15:10:15 2002
@@ -221,6 +221,7 @@
 		case VIDIOCGTUNER:
 		{
 			struct video_tuner t;
+			int signal;
 
 			if ( copy_from_user( &t, arg, sizeof( struct video_tuner ) ) )
 				return -EFAULT;
@@ -228,11 +229,12 @@
 			if ( t.tuner ) 
 				return -EINVAL;
 
+			signal = gemtek_pci_getsignal( card );
 			t.rangelow = GEMTEK_PCI_RANGE_LOW;
 			t.rangehigh = GEMTEK_PCI_RANGE_HIGH;
-			t.flags = VIDEO_TUNER_LOW;
+			t.flags = VIDEO_TUNER_LOW | (7 << signal) ;
 			t.mode = VIDEO_MODE_AUTO;
-			t.signal = 0xFFFF * gemtek_pci_getsignal( card );
+			t.signal = 0xFFFF * signal;
 			strcpy( t.name, "FM" );
 
 			if ( copy_to_user( arg, &t, sizeof( struct video_tuner ) ) )
@@ -282,6 +284,7 @@
 			a.flags |= VIDEO_AUDIO_MUTABLE;
 			a.volume = 1;
 			a.step = 65535;
+                        a.mode = (1 << gemtek_pci_getsignal( card ));
 			strcpy( a.name, "Radio" );
 
 			if ( copy_to_user( arg, &a, sizeof( struct video_audio ) ) )
diff -urN linux-2.4.18-pre3/drivers/media/radio/radio-sf16fmi.c linux/drivers/media/radio/radio-sf16fmi.c
--- linux-2.4.18-pre3/drivers/media/radio/radio-sf16fmi.c	Sun Sep 30 12:26:06 2001
+++ linux/drivers/media/radio/radio-sf16fmi.c	Tue Jan 15 15:10:16 2002
@@ -299,6 +299,7 @@
 	while (id_table[i].card_vendor != 0 && dev == NULL) {
 		dev = isapnp_find_dev(NULL, id_table[i].vendor,
 				      id_table[i].function, NULL);
+		i++;
 	}
 
 	if (!dev)
diff -urN linux-2.4.18-pre3/drivers/net/3c509.c linux/drivers/net/3c509.c
--- linux-2.4.18-pre3/drivers/net/3c509.c	Tue Jan 15 15:10:09 2002
+++ linux/drivers/net/3c509.c	Tue Jan 15 15:10:16 2002
@@ -43,7 +43,7 @@
 		v1.18 12Mar2001 Andrew Morton <andrewm@uow.edu.au>
 			- Avoid bogus detect of 3c590's (Andrzej Krzysztofowicz)
 			- Reviewed against 1.18 from scyld.com
-		v1.18 17Nov2001 Jeff Garzik <jgarzik@mandrakesoft.com>
+		v1.18a 17Nov2001 Jeff Garzik <jgarzik@mandrakesoft.com>
 			- ethtool support
 */
 
diff -urN linux-2.4.18-pre3/drivers/net/8139cp.c linux/drivers/net/8139cp.c
--- linux-2.4.18-pre3/drivers/net/8139cp.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/8139cp.c	Tue Jan 15 15:10:16 2002
@@ -20,7 +20,6 @@
 	TODO, in rough priority order:
 	* dev->tx_timeout
 	* LinkChg interrupt
-	* ETHTOOL_[GS]SET
 	* Support forcing media type with a module parameter,
 	  like dl2k.c/sundance.c
 	* Implement PCI suspend/resume
@@ -33,18 +32,19 @@
 	* Rx checksumming
 	* Tx checksumming
 	* ETHTOOL_GREGS, ETHTOOL_[GS]WOL,
-	  ETHTOOL_[GS]MSGLVL, ETHTOOL_NWAY_RST
 	* Jumbo frames / dev->change_mtu
 	* Investigate using skb->priority with h/w VLAN priority
 	* Investigate using High Priority Tx Queue with skb->priority
 	* Adjust Rx FIFO threshold and Max Rx DMA burst on Rx FIFO error
 	* Adjust Tx FIFO threshold and Max Tx DMA burst on Tx FIFO error
+        * Implement Tx software interrupt mitigation via
+	          Tx descriptor bit
 
  */
 
 #define DRV_NAME		"8139cp"
-#define DRV_VERSION		"0.0.5"
-#define DRV_RELDATE		"Oct 19, 2001"
+#define DRV_VERSION		"0.0.6"
+#define DRV_RELDATE		"Nov 19, 2001"
 
 
 #include <linux/module.h>
@@ -55,6 +55,7 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 
@@ -76,17 +77,6 @@
 MODULE_PARM (multicast_filter_limit, "i");
 MODULE_PARM_DESC (multicast_filter_limit, "8139cp maximum number of filtered multicast addresses");
 
-/* Set the copy breakpoint for the copy-only-tiny-buffer Rx structure. */
-#if defined(__alpha__) || defined(__arm__) || defined(__hppa__) \
-        || defined(__sparc_) || defined(__ia64__) \
-        || defined(__sh__) || defined(__mips__)
-static int rx_copybreak = 1518;
-#else
-static int rx_copybreak = 100;
-#endif
-MODULE_PARM (rx_copybreak, "i");
-MODULE_PARM_DESC (rx_copybreak, "8139cp Breakpoint at which Rx packets are copied");
-
 #define PFX			DRV_NAME ": "
 
 #define CP_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
@@ -104,10 +94,10 @@
 	(((CP)->tx_tail <= (CP)->tx_head) ?			\
 	  (CP)->tx_tail + (CP_TX_RING_SIZE - 1) - (CP)->tx_head :	\
 	  (CP)->tx_tail - (CP)->tx_head - 1)
-#define CP_CHIP_VERSION		0x76
 
 #define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer.*/
 #define RX_OFFSET		2
+#define CP_INTERNAL_PHY		32
 
 /* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
 #define RX_FIFO_THRESH		5	/* Rx buffer level before first PCI xfer.  */
@@ -136,6 +126,11 @@
 	Config3		= 0x59, /* Config3 */
 	Config4		= 0x5A, /* Config4 */
 	MultiIntr	= 0x5C, /* Multiple interrupt select */
+	BasicModeCtrl	= 0x62,	/* MII BMCR */
+	BasicModeStatus	= 0x64, /* MII BMSR */
+	NWayAdvert	= 0x66, /* MII ADVERTISE */
+	NWayLPAR	= 0x68, /* MII LPA */
+	NWayExpansion	= 0x6A, /* MII Expansion */
 	Config5		= 0xD8,	/* Config5 */
 	TxPoll		= 0xD9,	/* Tell chip to check Tx descriptors for work */
 	CpCmd		= 0xE0, /* C+ Command register (C+ mode only) */
@@ -289,6 +284,8 @@
 
 	struct sk_buff		*frag_skb;
 	unsigned		dropping_frag : 1;
+
+	struct mii_if_info	mii_if;
 };
 
 #define cpr8(reg)	readb(cp->regs + (reg))
@@ -333,8 +330,8 @@
 	netif_rx (skb);
 }
 
-static inline void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
-				   u32 status, u32 len)
+static void cp_rx_err_acct (struct cp_private *cp, unsigned rx_tail,
+			    u32 status, u32 len)
 {
 	if (netif_msg_rx_err (cp))
 		printk (KERN_DEBUG
@@ -428,8 +425,8 @@
 	while (rx_work--) {
 		u32 status, len;
 		dma_addr_t mapping;
-		struct sk_buff *skb, *copy_skb;
-		unsigned copying_skb, buflen;
+		struct sk_buff *skb, *new_skb;
+		unsigned buflen;
 
 		skb = cp->rx_skb[rx_tail].skb;
 		if (!skb)
@@ -452,43 +449,30 @@
 			goto rx_next;
 		}
 
-		copying_skb = (len <= rx_copybreak);
-
 		if (netif_msg_rx_status(cp))
-			printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d copying? %d\n",
-			       cp->dev->name, rx_tail, status, len,
-			       copying_skb);
-
-		buflen = copying_skb ? len : cp->rx_buf_sz;
-		copy_skb = dev_alloc_skb (buflen + RX_OFFSET);
-		if (!copy_skb) {
+			printk(KERN_DEBUG "%s: rx slot %d status 0x%x len %d\n",
+			       cp->dev->name, rx_tail, status, len);
+
+		buflen = cp->rx_buf_sz + RX_OFFSET;
+		new_skb = dev_alloc_skb (buflen);
+		if (!new_skb) {
 			cp->net_stats.rx_dropped++;
 			goto rx_next;
 		}
 
-		skb_reserve(copy_skb, RX_OFFSET);
-		copy_skb->dev = cp->dev;
-
-		if (!copying_skb) {
-			pci_unmap_single(cp->pdev, mapping,
-					 buflen, PCI_DMA_FROMDEVICE);
-			skb->ip_summed = CHECKSUM_NONE;
-			skb_trim(skb, len);
-
-			mapping =
-			cp->rx_skb[rx_tail].mapping =
-				pci_map_single(cp->pdev, copy_skb->data,
-					       buflen, PCI_DMA_FROMDEVICE);
-			cp->rx_skb[rx_tail].skb = copy_skb;
-			skb_put(copy_skb, buflen);
-		} else {
-			skb_put(copy_skb, len);
-			pci_dma_sync_single(cp->pdev, mapping, len, PCI_DMA_FROMDEVICE);
-			memcpy(copy_skb->data, skb->data, len);
+		skb_reserve(new_skb, RX_OFFSET);
+		new_skb->dev = cp->dev;
 
-			/* We'll reuse the original ring buffer. */
-			skb = copy_skb;
-		}
+		pci_unmap_single(cp->pdev, mapping,
+				 buflen, PCI_DMA_FROMDEVICE);
+		skb->ip_summed = CHECKSUM_NONE;
+		skb_put(skb, len);
+
+		mapping =
+		cp->rx_skb[rx_tail].mapping =
+			pci_map_single(cp->pdev, new_skb->tail,
+				       buflen, PCI_DMA_FROMDEVICE);
+		cp->rx_skb[rx_tail].skb = new_skb;
 
 		cp_rx_skb(cp, skb);
 
@@ -899,10 +883,9 @@
 
 		skb->dev = cp->dev;
 		skb_reserve(skb, RX_OFFSET);
-		skb_put(skb, cp->rx_buf_sz);
 
 		cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
-			skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
+			skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
 		cp->rx_skb[i].skb = skb;
 		cp->rx_skb[i].frag = 0;
 
@@ -1025,6 +1008,39 @@
 	return 0;
 }
 
+static char mii_2_8139_map[8] = {
+	BasicModeCtrl,
+	BasicModeStatus,
+	0,
+	0,
+	NWayAdvert,
+	NWayLPAR,
+	NWayExpansion,
+	0
+};
+
+static int mdio_read(struct net_device *dev, int phy_id, int location)
+{
+	struct cp_private *cp = dev->priv;
+
+	return location < 8 && mii_2_8139_map[location] ?
+	       readw(cp->regs + mii_2_8139_map[location]) : 0;
+}
+
+
+static void mdio_write(struct net_device *dev, int phy_id, int location,
+		       int value)
+{
+	struct cp_private *cp = dev->priv;
+
+	if (location == 0) {
+		cpw8(Cfg9346, Cfg9346_Unlock);
+		cpw16(BasicModeCtrl, value);
+		cpw8(Cfg9346, Cfg9346_Lock);
+	} else if (location < 8 && mii_2_8139_map[location])
+		cpw16(mii_2_8139_map[location], value);
+}
+
 static int cp_ethtool_ioctl (struct cp_private *cp, void *useraddr)
 {
 	u32 ethcmd;
@@ -1032,21 +1048,71 @@
 	/* dev_ioctl() in ../../net/core/dev.c has already checked
 	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
 
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+	if (get_user(ethcmd, (u32 *)useraddr))
 		return -EFAULT;
 
 	switch (ethcmd) {
 
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, cp->pdev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, cp->pdev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&cp->lock);
+		mii_ethtool_gset(&cp->mii_if, &ecmd);
+		spin_unlock_irq(&cp->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&cp->lock);
+		r = mii_ethtool_sset(&cp->mii_if, &ecmd);
+		spin_unlock_irq(&cp->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&cp->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&cp->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = cp->msg_enable;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		cp->msg_enable = edata.data;
+		return 0;
+	}
 
 	default:
 		break;
@@ -1061,6 +1127,9 @@
 	struct cp_private *cp = dev->priv;
 	int rc = 0;
 
+	if (!netif_running(dev))
+		return -EINVAL;
+
 	switch (cmd) {
 	case SIOCETHTOOL:
 		return cp_ethtool_ioctl(cp, (void *) rq->ifr_data);
@@ -1173,6 +1242,10 @@
 	cp->dev = dev;
 	cp->msg_enable = (debug < 0 ? CP_DEF_MSG_ENABLE : debug);
 	spin_lock_init (&cp->lock);
+	cp->mii_if.dev = dev;
+	cp->mii_if.mdio_read = mdio_read;
+	cp->mii_if.mdio_write = mdio_write;
+	cp->mii_if.phy_id = CP_INTERNAL_PHY;
 
 	rc = pci_enable_device(pdev);
 	if (rc)
diff -urN linux-2.4.18-pre3/drivers/net/8139too.c linux/drivers/net/8139too.c
--- linux-2.4.18-pre3/drivers/net/8139too.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/8139too.c	Tue Jan 15 15:10:16 2002
@@ -92,7 +92,7 @@
 */
 
 #define DRV_NAME	"8139too"
-#define DRV_VERSION	"0.9.22"
+#define DRV_VERSION	"0.9.23"
 
 
 #include <linux/config.h>
@@ -159,6 +159,9 @@
    The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
 static int multicast_filter_limit = 32;
 
+/* bitmapped message enable number */
+static int debug = -1;
+
 /* Size of the in-memory receive ring. */
 #define RX_BUF_LEN_IDX	2	/* 0==8K, 1==16K, 2==32K, 3==64K */
 #define RX_BUF_LEN	(8192 << RX_BUF_LEN_IDX)
@@ -525,6 +528,7 @@
 	unsigned long early_rx;
 	unsigned long tx_buf_mapped;
 	unsigned long tx_timeouts;
+	unsigned long rx_lost_in_ring;
 };
 
 struct rtl8139_private {
@@ -543,12 +547,8 @@
 	dma_addr_t tx_bufs_dma;
 	signed char phys[4];		/* MII device addresses. */
 	char twistie, twist_row, twist_col;	/* Twister tune state. */
-	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
 	unsigned int default_port:4;	/* Last dev->if_port value. */
-	unsigned int media2:4;	/* Secondary monitored media port. */
 	unsigned int medialock:1;	/* Don't sense media type. */
-	unsigned int mediasense:1;	/* Media sensing in progress. */
 	spinlock_t lock;
 	chip_t chipset;
 	pid_t thr_pid;
@@ -557,6 +557,7 @@
 	u32 rx_config;
 	struct rtl_extra_stats xstats;
 	int time_to_die;
+	struct mii_if_info mii;
 };
 
 MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
@@ -567,6 +568,8 @@
 MODULE_PARM (max_interrupt_work, "i");
 MODULE_PARM (media, "1-" __MODULE_STRING(MAX_UNITS) "i");
 MODULE_PARM (full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM (debug, "i");
+MODULE_PARM_DESC (debug, "8139too bitmapped message enable number");
 MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered multicast addresses");
 MODULE_PARM_DESC (max_interrupt_work, "8139too maximum events handled per interrupt");
 MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
@@ -948,6 +951,9 @@
 	spin_lock_init (&tp->lock);
 	init_waitqueue_head (&tp->thr_wait);
 	init_completion (&tp->thr_exited);
+	tp->mii.dev = dev;
+	tp->mii.mdio_read = mdio_read;
+	tp->mii.mdio_write = mdio_write;
 
 	/* dev is fully set up and ready to use now */
 	DPRINTK("about to register device named %s (%p)...\n", dev->name, dev);
@@ -999,18 +1005,18 @@
 	/* The lower four bits are the media type. */
 	option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
 	if (option > 0) {
-		tp->full_duplex = (option & 0x210) ? 1 : 0;
+		tp->mii.full_duplex = (option & 0x210) ? 1 : 0;
 		tp->default_port = option & 0xFF;
 		if (tp->default_port)
 			tp->medialock = 1;
 	}
 	if (board_idx < MAX_UNITS  &&  full_duplex[board_idx] > 0)
-		tp->full_duplex = full_duplex[board_idx];
-	if (tp->full_duplex) {
+		tp->mii.full_duplex = full_duplex[board_idx];
+	if (tp->mii.full_duplex) {
 		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
 		/* Changing the MII-advertised media because might prevent
 		   re-connection. */
-		tp->duplex_lock = 1;
+		tp->mii.duplex_lock = 1;
 	}
 	if (tp->default_port) {
 		printk(KERN_INFO "  Forcing %dMbps %s-duplex operation.\n",
@@ -1267,7 +1273,7 @@
 
 	}
 
-	tp->full_duplex = tp->duplex_lock;
+	tp->mii.full_duplex = tp->mii.duplex_lock;
 	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
 	tp->twistie = 1;
 	tp->time_to_die = 0;
@@ -1279,7 +1285,7 @@
 			" GP Pins %2.2x %s-duplex.\n",
 			dev->name, pci_resource_start (tp->pci_dev, 1),
 			dev->irq, RTL_R8 (MediaStatus),
-			tp->full_duplex ? "full" : "half");
+			tp->mii.full_duplex ? "full" : "half");
 
 	tp->thr_pid = kernel_thread (rtl8139_thread, dev, CLONE_FS | CLONE_FILES);
 	if (tp->thr_pid < 0)
@@ -1295,18 +1301,18 @@
 	struct rtl8139_private *tp = dev->priv;
 
 	if (tp->phys[0] >= 0) {
-		u16 mii_reg5 = mdio_read(dev, tp->phys[0], 5);
-		if (mii_reg5 == 0xffff)
+		u16 mii_lpa = mdio_read(dev, tp->phys[0], MII_LPA);
+		if (mii_lpa == 0xffff)
 			;					/* Not there */
-		else if ((mii_reg5 & 0x0100) == 0x0100
-				 || (mii_reg5 & 0x00C0) == 0x0040)
-			tp->full_duplex = 1;
+		else if ((mii_lpa & LPA_100FULL) == LPA_100FULL
+				 || (mii_lpa & 0x00C0) == LPA_10FULL)
+			tp->mii.full_duplex = 1;
 
 		printk (KERN_INFO"%s: Setting %s%s-duplex based on"
 				" auto-negotiated partner ability %4.4x.\n",
-		        dev->name, mii_reg5 == 0 ? "" :
-				(mii_reg5 & 0x0180) ? "100mbps " : "10mbps ",
-			tp->full_duplex ? "full" : "half", mii_reg5);
+		        dev->name, mii_lpa == 0 ? "" :
+				(mii_lpa & 0x0180) ? "100mbps " : "10mbps ",
+			tp->mii.full_duplex ? "full" : "half", mii_lpa);
 	}
 }
 
@@ -1494,30 +1500,30 @@
 				 struct rtl8139_private *tp,
 				 void *ioaddr)
 {
-	int mii_reg5;
+	int mii_lpa;
 
-	mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
 
-	if (!tp->duplex_lock && mii_reg5 != 0xffff) {
-		int duplex = (mii_reg5 & 0x0100)
-		    || (mii_reg5 & 0x01C0) == 0x0040;
-		if (tp->full_duplex != duplex) {
-			tp->full_duplex = duplex;
+	if (!tp->mii.duplex_lock && mii_lpa != 0xffff) {
+		int duplex = (mii_lpa & LPA_100FULL)
+		    || (mii_lpa & 0x01C0) == 0x0040;
+		if (tp->mii.full_duplex != duplex) {
+			tp->mii.full_duplex = duplex;
 
-			if (mii_reg5) {
+			if (mii_lpa) {
 				printk (KERN_INFO
 					"%s: Setting %s-duplex based on MII #%d link"
 					" partner ability of %4.4x.\n",
 					dev->name,
-					tp->full_duplex ? "full" : "half",
-					tp->phys[0], mii_reg5);
+					tp->mii.full_duplex ? "full" : "half",
+					tp->phys[0], mii_lpa);
 			} else {
 				printk(KERN_INFO"%s: media is unconnected, link down, or incompatible connection\n",
 				       dev->name);
 			}
 #if 0
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
 			RTL_W8 (Cfg9346, Cfg9346_Lock);
 #endif
 		}
@@ -1751,23 +1757,36 @@
 			    struct rtl8139_private *tp, void *ioaddr)
 {
 	u8 tmp8;
+#ifndef CONFIG_8139_NEW_RX_RESET
 	int tmp_work;
+#endif
 
 	DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
 	         dev->name, rx_status);
-	if (rx_status & RxTooLong) {
-		DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
-			 dev->name, rx_status);
-		/* A.C.: The chip hangs here. */
-	}
 	tp->stats.rx_errors++;
-	if (rx_status & (RxBadSymbol | RxBadAlign))
-		tp->stats.rx_frame_errors++;
-	if (rx_status & (RxRunt | RxTooLong))
-		tp->stats.rx_length_errors++;
-	if (rx_status & RxCRCErr)
-		tp->stats.rx_crc_errors++;
+	if (!(rx_status & RxStatusOK)) {
+		if (rx_status & RxTooLong) {
+			DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
+			 	dev->name, rx_status);
+			/* A.C.: The chip hangs here. */
+		}
+		if (rx_status & (RxBadSymbol | RxBadAlign))
+			tp->stats.rx_frame_errors++;
+		if (rx_status & (RxRunt | RxTooLong))
+			tp->stats.rx_length_errors++;
+		if (rx_status & RxCRCErr)
+			tp->stats.rx_crc_errors++;
+	} else {
+		tp->xstats.rx_lost_in_ring++;
+	}
 
+#ifdef CONFIG_8139_NEW_RX_RESET
+	tmp8 = RTL_R8 (ChipCmd);
+	RTL_W8 (ChipCmd, tmp8 & ~CmdRxEnb);
+	RTL_W8 (ChipCmd, tmp8);
+	RTL_W32 (RxConfig, tp->rx_config);
+	tp->cur_rx = 0;
+#else
 	/* Reset the receiver, based on RealTek recommendation. (Bug?) */
 
 	/* disable receive */
@@ -1812,6 +1831,7 @@
 
 	/* A.C.: Reset the multicast list. */
 	__set_rx_mode (dev);
+#endif
 }
 
 static void rtl8139_rx_interrupt (struct net_device *dev,
@@ -1946,13 +1966,13 @@
 	    (tp->drv_flags & HAS_LNK_CHNG)) {
 		/* Really link-change on new chips. */
 		int lpar = RTL_R16 (NWayLPAR);
-		int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040
-				|| tp->duplex_lock;
-		if (tp->full_duplex != duplex) {
-			tp->full_duplex = duplex;
+		int duplex = (lpar & LPA_100FULL) || (lpar & 0x01C0) == 0x0040
+				|| tp->mii.duplex_lock;
+		if (tp->mii.full_duplex != duplex) {
+			tp->mii.full_duplex = duplex;
 #if 0
 			RTL_W8 (Cfg9346, Cfg9346_Unlock);
-			RTL_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			RTL_W8 (Config1, tp->mii.full_duplex ? 0x60 : 0x20);
 			RTL_W8 (Cfg9346, Cfg9346_Lock);
 #endif
 		}
@@ -2111,48 +2131,6 @@
 }
 
 
-/* Get the ethtool settings.  Assumes that eset points to kernel
-   memory, *eset has been initialized as {ETHTOOL_GSET}, and other
-   threads or interrupts aren't messing with the 8139.  */
-static void netdev_get_eset (struct net_device *dev, struct ethtool_cmd *eset)
-{
-	struct rtl8139_private *np = dev->priv;
-	void *ioaddr = np->mmio_addr;
-	u16 advert;
-
-	eset->supported = SUPPORTED_10baseT_Half
-		      	| SUPPORTED_10baseT_Full
-		      	| SUPPORTED_100baseT_Half
-		      	| SUPPORTED_100baseT_Full
-		      	| SUPPORTED_Autoneg
-		      	| SUPPORTED_TP;
-
-	eset->advertising = ADVERTISED_TP | ADVERTISED_Autoneg;
-	advert = mdio_read (dev, np->phys[0], 4);
-	if (advert & 0x0020)
-		eset->advertising |= ADVERTISED_10baseT_Half;
-	if (advert & 0x0040)
-		eset->advertising |= ADVERTISED_10baseT_Full;
-	if (advert & 0x0080)
-		eset->advertising |= ADVERTISED_100baseT_Half;
-	if (advert & 0x0100)
-		eset->advertising |= ADVERTISED_100baseT_Full;
-
-	eset->speed = (RTL_R8 (MediaStatus) & 0x08) ? 10 : 100;
-	/* (KON)FIXME: np->full_duplex is set or reset by the thread,
-	   which means this always shows half duplex if the interface
-	   isn't up yet, even if it has already autonegotiated.  */
-	eset->duplex = np->full_duplex ? DUPLEX_FULL : DUPLEX_HALF;
-	eset->port = PORT_TP;
-	/* (KON)FIXME: Is np->phys[0] correct?  starfire.c uses that.  */
-	eset->phy_address = np->phys[0];
-	eset->transceiver = XCVR_INTERNAL;
-	eset->autoneg = (mdio_read (dev, np->phys[0], 0) & 0x1000) != 0;
-	eset->maxtxpkt = 1;
-	eset->maxrxpkt = 1;
-}
-
-
 /* Get the ethtool Wake-on-LAN settings.  Assumes that wol points to
    kernel memory, *wol has been initialized as {ETHTOOL_GWOL}, and
    other threads or interrupts aren't messing with the 8139.  */
@@ -2227,7 +2205,6 @@
 	return 0;
 }
 
-
 static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
 {
 	struct rtl8139_private *np = dev->priv;
@@ -2236,33 +2213,71 @@
 	/* dev_ioctl() in ../../net/core/dev.c has already checked
 	   capable(CAP_NET_ADMIN), so don't bother with that here.  */
 
-	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+	if (get_user(ethcmd, (u32 *)useraddr))
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GSET:
-		{
-			struct ethtool_cmd eset = { ETHTOOL_GSET };
-			spin_lock_irq (&np->lock);
-			netdev_get_eset (dev, &eset);
-			spin_unlock_irq (&np->lock);
-			if (copy_to_user (useraddr, &eset, sizeof (eset)))
-				return -EFAULT;
-			return 0;
-		}
 
-	/* TODO: ETHTOOL_SSET */
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
 
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, np->pci_dev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 
 	case ETHTOOL_GWOL:
 		{
@@ -2302,6 +2317,9 @@
 	int rc = 0;
 	int phy = tp->phys[0] & 0x3f;
 
+	if (!netif_running(dev))
+		return -EINVAL;
+
 	if (cmd != SIOCETHTOOL) {
 		/* With SIOCETHTOOL, this would corrupt the pointer.  */
 		data->phy_id &= 0x1f;
@@ -2336,9 +2354,9 @@
 				/* Check for autonegotiation on or reset. */
 				tp->medialock = (value & 0x9000) ? 0 : 1;
 				if (tp->medialock)
-					tp->full_duplex = (value & 0x0100) ? 1 : 0;
+					tp->mii.full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
-			case 4: /* tp->advertising = value; */ break;
+			case 4: tp->mii.advertising = value; break;
 			}
 		}
 		mdio_write(dev, data->phy_id, data->reg_num, data->val_in);
diff -urN linux-2.4.18-pre3/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.4.18-pre3/drivers/net/Config.in	Tue Jan 15 15:10:09 2002
+++ linux/drivers/net/Config.in	Tue Jan 15 15:10:16 2002
@@ -183,6 +183,7 @@
       dep_mbool '      Use PIO instead of MMIO' CONFIG_8139TOO_PIO $CONFIG_8139TOO
       dep_mbool '      Support for automatic channel equalization (EXPERIMENTAL)' CONFIG_8139TOO_TUNE_TWISTER $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
       dep_mbool '      Support for older RTL-8129/8130 boards' CONFIG_8139TOO_8129 $CONFIG_8139TOO
+      dep_mbool '      Experiment for better RX reset (EXPERIMENTAL)' CONFIG_8139_NEW_RX_RESET $CONFIG_8139TOO $CONFIG_EXPERIMENTAL
       dep_tristate '    SiS 900/7016 PCI Fast Ethernet Adapter support' CONFIG_SIS900 $CONFIG_PCI
       dep_tristate '    SMC EtherPower II' CONFIG_EPIC100 $CONFIG_PCI
       dep_tristate '    Sundance Alta support' CONFIG_SUNDANCE $CONFIG_PCI
diff -urN linux-2.4.18-pre3/drivers/net/Makefile linux/drivers/net/Makefile
--- linux-2.4.18-pre3/drivers/net/Makefile	Fri Oct 19 08:32:28 2001
+++ linux/drivers/net/Makefile	Tue Jan 15 15:10:16 2002
@@ -17,7 +17,7 @@
 
 export-objs     :=	8390.o arlan.o aironet4500_core.o aironet4500_card.o \
 			ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \
-			net_init.o
+			net_init.o mii.o
 list-multi	:=	rcpci.o
 rcpci-objs	:=	rcpci45.o rclanmtl.o
 
@@ -63,13 +63,13 @@
 
 obj-$(CONFIG_DGRS) += dgrs.o
 obj-$(CONFIG_RCPCI) += rcpci.o
-obj-$(CONFIG_VORTEX) += 3c59x.o
+obj-$(CONFIG_VORTEX) += 3c59x.o mii.o
 obj-$(CONFIG_NE2K_PCI) += ne2k-pci.o 8390.o
-obj-$(CONFIG_PCNET32) += pcnet32.o
-obj-$(CONFIG_EEPRO100) += eepro100.o
+obj-$(CONFIG_PCNET32) += pcnet32.o mii.o
+obj-$(CONFIG_EEPRO100) += eepro100.o mii.o
 obj-$(CONFIG_TLAN) += tlan.o
-obj-$(CONFIG_EPIC100) += epic100.o
-obj-$(CONFIG_SIS900) += sis900.o
+obj-$(CONFIG_EPIC100) += epic100.o mii.o
+obj-$(CONFIG_SIS900) += sis900.o mii.o
 obj-$(CONFIG_DM9102) += dmfe.o
 obj-$(CONFIG_YELLOWFIN) += yellowfin.o
 obj-$(CONFIG_ACENIC) += acenic.o
@@ -77,7 +77,7 @@
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_NS83820) += ns83820.o
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
-obj-$(CONFIG_FEALNX) += fealnx.o
+obj-$(CONFIG_FEALNX) += fealnx.o mii.o
 
 ifeq ($(CONFIG_SK98LIN),y)
 obj-y += sk98lin/sk98lin.o
@@ -87,7 +87,7 @@
   obj-y += skfp/skfp.o
 endif
 
-obj-$(CONFIG_VIA_RHINE) += via-rhine.o
+obj-$(CONFIG_VIA_RHINE) += via-rhine.o mii.o
 obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
 
 #
@@ -100,7 +100,7 @@
 obj-$(CONFIG_AIRONET4500_PROC)	+= aironet4500_proc.o
 obj-$(CONFIG_AIRONET4500_CS)	+= aironet4500_proc.o
 
-obj-$(CONFIG_WINBOND_840) += winbond-840.o
+obj-$(CONFIG_WINBOND_840) += winbond-840.o mii.o
 obj-$(CONFIG_SUNDANCE) += sundance.o
 obj-$(CONFIG_HAMACHI) += hamachi.o
 obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
@@ -164,8 +164,8 @@
 obj-$(CONFIG_3C515) += 3c515.o
 obj-$(CONFIG_EEXPRESS) += eexpress.o
 obj-$(CONFIG_EEXPRESS_PRO) += eepro.o
-obj-$(CONFIG_8139CP) += 8139cp.o
-obj-$(CONFIG_8139TOO) += 8139too.o
+obj-$(CONFIG_8139CP) += 8139cp.o mii.o
+obj-$(CONFIG_8139TOO) += 8139too.o mii.o
 obj-$(CONFIG_WAVELAN) += wavelan.o
 obj-$(CONFIG_ARLAN) += arlan.o arlan-proc.o
 obj-$(CONFIG_ZNET) += znet.o
diff -urN linux-2.4.18-pre3/drivers/net/bonding.c linux/drivers/net/bonding.c
--- linux-2.4.18-pre3/drivers/net/bonding.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/bonding.c	Tue Jan 15 15:10:16 2002
@@ -153,6 +153,14 @@
  *
  * 2001/10/23 - Takao Indoh <indou dot takao at jp dot fujitsu dot com>
  *     - Various memory leak fixes
+ *
+ * 2001/11/5 - Mark Huth <mark dot huth at mvista dot com>
+ *     - Don't take rtnl lock in bond_mii_monitor as it deadlocks under 
+ *       certain hotswap conditions.  
+ *       Note:  this same change may be required in bond_arp_monitor ???
+ *     - Remove possibility of calling bond_sethwaddr with NULL slave_dev ptr 
+ *     - Handle hot swap ethernet interface deregistration events to remove
+ *       kernel oops following hot swap of enslaved interface
  */
 
 #include <linux/config.h>
@@ -256,6 +264,7 @@
 static void bond_set_slave_active_flags(slave_t *slave);
 static int bond_enslave(struct net_device *master, struct net_device *slave);
 static int bond_release(struct net_device *master, struct net_device *slave);
+static int bond_release_all(struct net_device *master);
 static int bond_sethwaddr(struct net_device *master, struct net_device *slave);
 
 /*
@@ -371,10 +380,13 @@
 static u16 bond_check_mii_link(bonding_t *bond)
 {
 	int has_active_interface = 0;
+	unsigned long flags;
 
+	read_lock_irqsave(&bond->lock, flags);
 	read_lock(&bond->ptrlock);
 	has_active_interface = (bond->current_slave != NULL);
 	read_unlock(&bond->ptrlock);
+	read_unlock_irqrestore(&bond->lock, flags);
 
 	return (has_active_interface ? MII_LINK_READY : 0);
 }
@@ -406,7 +418,6 @@
 static int bond_close(struct net_device *master)
 {
 	bonding_t *bond = (struct bonding *) master->priv;
-	slave_t *slave;
 	unsigned long flags;
 
 	write_lock_irqsave(&bond->lock, flags);
@@ -417,13 +428,11 @@
 	if (arp_interval> 0) {  /* arp interval, in milliseconds. */
 		del_timer(&bond->arp_timer);
 	}
-	/* We need to unlock this because bond_release will re-lock it */
-	write_unlock_irqrestore(&bond->lock, flags);
 
 	/* Release the bonded slaves */
-	while ((slave = bond->prev) != (slave_t *)bond) {
-		bond_release(master, slave->dev);
-	}
+	bond_release_all(master);
+
+	write_unlock_irqrestore(&bond->lock, flags);
 
 	MOD_DEC_USE_COUNT;
 	return 0;
@@ -865,6 +874,49 @@
 	return -EINVAL;
 }
 
+/* 
+ * This function releases all slaves.
+ * Warning: must put write-locks around the call to this function.
+ */
+static int bond_release_all(struct net_device *master)
+{
+	bonding_t *bond;
+	slave_t *our_slave;
+	struct net_device *slave_dev;
+
+	if (master == NULL)  {
+		return -ENODEV;
+	}
+
+	if (master->flags & IFF_SLAVE) {
+		return -EINVAL;
+	}
+
+	bond = (struct bonding *) master->priv;
+	bond->current_slave = NULL;
+
+	while ((our_slave = bond->prev) != (slave_t *)bond) {
+		slave_dev = our_slave->dev;
+		bond->prev = our_slave->prev;
+
+		kfree(our_slave);
+
+		netdev_set_master(slave_dev, NULL);
+
+		/* only restore its RUNNING flag if monitoring set it down */
+		if (slave_dev->flags & IFF_UP)
+			slave_dev->flags |= IFF_RUNNING;
+
+		if (slave_dev->flags & IFF_NOARP)
+			dev_close(slave_dev);
+	}
+	bond->next = (slave_t *)bond;
+	bond->slave_cnt = 0;
+	printk (KERN_INFO "%s: releases all slaves\n", master->name);
+
+	return 0;
+}
+
 /* this function is called regularly to monitor each slave's link. */
 static void bond_mii_monitor(struct net_device *master)
 {
@@ -875,14 +927,6 @@
 
 	read_lock_irqsave(&bond->lock, flags);
 
-	if (rtnl_shlock_nowait()) {
-		goto monitor_out;
-	}
-
-	if (rtnl_exlock_nowait()) {
-		rtnl_shunlock();
-		goto monitor_out;
-	}
 	/* we will try to read the link status of each of our slaves, and
 	 * set their IFF_RUNNING flag appropriately. For each slave not
 	 * supporting MII status, we won't do anything so that a user-space
@@ -1056,9 +1100,10 @@
 		} /* end of switch */
 	} /* end of while */
 
-	/* if there's no active interface and we discovered that one
-	   of the slaves could be activated earlier, so we do it.
-	*/
+	/* 
+	 * if there's no active interface and we discovered that one
+	 * of the slaves could be activated earlier, so we do it.
+	 */
 	read_lock(&bond->ptrlock);
 	oldcurrent = bond->current_slave;
 	read_unlock(&bond->ptrlock);
@@ -1096,9 +1141,6 @@
 		}
 	}
 
-	rtnl_exunlock();
-	rtnl_shunlock();
-monitor_out:
 	read_unlock_irqrestore(&bond->lock, flags);
 	/* re-arm the timer */
 	mod_timer(&bond->mii_timer, jiffies + (miimon * HZ / 1000));
@@ -1127,17 +1169,17 @@
 
 	if (!IS_UP(master)) {
 		mod_timer(&bond->arp_timer, next_timer);
-		goto monitor_out;
+		goto arp_monitor_out;
 	}
 
 
 	if (rtnl_shlock_nowait()) {
-		goto monitor_out;
+		goto arp_monitor_out;
 	}
 
 	if (rtnl_exlock_nowait()) {
 		rtnl_shunlock();
-		goto monitor_out;
+		goto arp_monitor_out;
 	}
 
 	/* see if any of the previous devices are up now (i.e. they have seen a 
@@ -1242,7 +1284,9 @@
 	 * an arp on all of the interfaces 
 	 */
 
+	read_lock(&bond->ptrlock);
 	if (bond->current_slave == NULL) { 
+		read_unlock(&bond->ptrlock);
 		slave = (slave_t *)bond;
 		while ((slave = slave->prev) != (slave_t *)bond)   {
 			arp_send(ARPOP_REQUEST, ETH_P_ARP, arp_target, 
@@ -1250,11 +1294,14 @@
 				 slave->dev->dev_addr, arp_target_hw_addr); 
 		}
 	}
+	else {
+		read_unlock(&bond->ptrlock);
+	}
 
 	rtnl_exunlock();
 	rtnl_shunlock();
 
-monitor_out:
+arp_monitor_out:
 	read_unlock_irqrestore(&bond->lock, flags);
 
 	/* re-arm the timer */
@@ -1366,16 +1413,17 @@
 {
 	bonding_t *bond = (struct bonding *) master->priv;
 	slave_t *slave;
+	unsigned long flags;
 
 	info->bond_mode = mode;
 	info->num_slaves = 0;
 	info->miimon = miimon;
 
-	read_lock(&bond->ptrlock);
+	read_lock_irqsave(&bond->lock, flags);
 	for (slave = bond->prev; slave!=(slave_t *)bond; slave = slave->prev) {
 		info->num_slaves++;
 	}
-	read_unlock(&bond->ptrlock);
+	read_unlock_irqrestore(&bond->lock, flags);
 
 	return 0;
 }
@@ -1386,27 +1434,28 @@
 	bonding_t *bond = (struct bonding *) master->priv;
 	slave_t *slave;
 	int cur_ndx = 0;
+	unsigned long flags;
 
 	if (info->slave_id < 0) {
 		return -ENODEV;
 	}
 
-	read_lock(&bond->ptrlock);
+	read_lock_irqsave(&bond->lock, flags);
 	for (slave = bond->prev; 
 		 slave != (slave_t *)bond && cur_ndx < info->slave_id; 
 		 slave = slave->prev) {
 		cur_ndx++;
 	}
+	read_unlock_irqrestore(&bond->lock, flags);
+
 	if (cur_ndx == info->slave_id) {
 		strcpy(info->slave_name, slave->dev->name);
 		info->link = slave->link;
 		info->state = slave->state;
 		info->link_failure_count = slave->link_failure_count;
 	} else {
-		read_unlock(&bond->ptrlock);
 		return -ENODEV;
 	}
-	read_unlock(&bond->ptrlock);
 
 	return 0;
 }
@@ -1479,40 +1528,40 @@
 	}
 
 	slave_dev = dev_get_by_name(ifr->ifr_slave);
+
 #ifdef BONDING_DEBUG
 	printk(KERN_INFO "slave_dev=%x: \n", (unsigned int)slave_dev);
 	printk(KERN_INFO "slave_dev->name=%s: \n", slave_dev->name);
 #endif
-	switch (cmd) {
-	case BOND_ENSLAVE_OLD:
-	case SIOCBONDENSLAVE:		
-		ret = bond_enslave(master_dev, slave_dev);
-		break;
-	case BOND_RELEASE_OLD:			
-	case SIOCBONDRELEASE:	
-		ret = bond_release(master_dev, slave_dev); 
-		break;
-	case BOND_SETHWADDR_OLD:
-	case SIOCBONDSETHWADDR:	
-		ret = bond_sethwaddr(master_dev, slave_dev);
-		break;
-	case BOND_CHANGE_ACTIVE_OLD:
-	case SIOCBONDCHANGEACTIVE:
-		if (mode == BOND_MODE_ACTIVEBACKUP) {
-			ret = bond_change_active(master_dev, slave_dev);
-		}
-		else {
-			ret = -EINVAL;
-		}
-		break;
-	default:
-		ret = -EOPNOTSUPP;
-	}
 
-	if (slave_dev) {
-		/*
-		 * Clear the module reference that was added by dev_get_by_name
-		 */
+	if (slave_dev == NULL) {
+		ret = -ENODEV;
+	} else {
+		switch (cmd) {
+		case BOND_ENSLAVE_OLD:
+		case SIOCBONDENSLAVE:		
+			ret = bond_enslave(master_dev, slave_dev);
+			break;
+		case BOND_RELEASE_OLD:			
+		case SIOCBONDRELEASE:	
+			ret = bond_release(master_dev, slave_dev); 
+			break;
+		case BOND_SETHWADDR_OLD:
+		case SIOCBONDSETHWADDR:	
+			ret = bond_sethwaddr(master_dev, slave_dev);
+			break;
+		case BOND_CHANGE_ACTIVE_OLD:
+		case SIOCBONDCHANGEACTIVE:
+			if (mode == BOND_MODE_ACTIVEBACKUP) {
+				ret = bond_change_active(master_dev, slave_dev);
+			}
+			else {
+				ret = -EINVAL;
+			}
+			break;
+		default:
+			ret = -EOPNOTSUPP;
+		}
 		dev_put(slave_dev);
 	}
 	return ret;
@@ -1592,13 +1641,11 @@
 	}
 
 	read_lock_irqsave(&bond->lock, flags);
-	read_lock(&bond->ptrlock);
 	slave = bond->prev;
 
 	/* we're at the root, get the first slave */
 	if ((slave == NULL) || (slave->dev == NULL)) { 
 		/* no suitable interface, frame not sent */
-		read_unlock(&bond->ptrlock);
 		dev_kfree_skb(skb);
 		read_unlock_irqrestore(&bond->lock, flags);
 		return 0;
@@ -1606,8 +1653,6 @@
 
 	slave_no = (data->h_dest[5]^slave->dev->dev_addr[5]) % bond->slave_cnt;
 
-	read_unlock(&bond->ptrlock);
-
 	while ( (slave_no > 0) && (slave != (slave_t *)bond) ) {
 		slave = slave->prev;
 		slave_no--;
@@ -1748,6 +1793,7 @@
 	off_t begin = 0;
 	u16 link;
 	slave_t *slave = NULL;
+	unsigned long flags;
 
 	while (bond != NULL) {
 		/*
@@ -1756,17 +1802,19 @@
 		 */
 		link = bond_check_mii_link(bond);
 
-		read_lock(&bond->ptrlock);
-
 		len += sprintf(buf + len, "Bonding Mode: ");
 		len += sprintf(buf + len, "%s\n", mode ? "active-backup" : "load balancing");
 
 		if (mode == BOND_MODE_ACTIVEBACKUP) {
+			read_lock_irqsave(&bond->lock, flags);
+			read_lock(&bond->ptrlock);
 			if (bond->current_slave != NULL) {
 				len += sprintf(buf + len, 
 					"Currently Active Slave: %s\n", 
 					bond->current_slave->dev->name);
 			}
+			read_unlock(&bond->ptrlock);
+			read_unlock_irqrestore(&bond->lock, flags);
 		}
 
 		len += sprintf(buf + len, "MII Status: ");
@@ -1777,6 +1825,7 @@
 		len += sprintf(buf + len, "Up Delay (ms): %d\n", updelay);
 		len += sprintf(buf + len, "Down Delay (ms): %d\n", downdelay);
 
+		read_lock_irqsave(&bond->lock, flags);
 		for (slave = bond->prev; slave != (slave_t *)bond; 
 		     slave = slave->prev) {
 			len += sprintf(buf + len, "\nSlave Interface: %s\n", slave->dev->name);
@@ -1789,6 +1838,7 @@
 			len += sprintf(buf + len, "Link Failure Count: %d\n", 
 				slave->link_failure_count);
 		}
+		read_unlock_irqrestore(&bond->lock, flags);
 
 		/*
 		 * Figure out the calcs for the /proc/net interface
@@ -1802,7 +1852,6 @@
 			len = 0;
 		}
 
-		read_unlock(&bond->ptrlock);
 
 		bond = bond->next_bond;
 	}
@@ -1843,7 +1892,14 @@
 			default:
 				return NOTIFY_DONE;
 			}
-		} 
+		} else if (this_bond->device == event_dev->master) {
+			switch (event) {
+			case NETDEV_UNREGISTER:
+				bond_release(this_bond->device, event_dev);
+				break;
+			}
+			return NOTIFY_DONE;
+		}
 		this_bond = this_bond->next_bond;
 	}
 	return NOTIFY_DONE;
diff -urN linux-2.4.18-pre3/drivers/net/epic100.c linux/drivers/net/epic100.c
--- linux-2.4.18-pre3/drivers/net/epic100.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/epic100.c	Tue Jan 15 15:10:16 2002
@@ -53,11 +53,15 @@
 	LK1.1.10:
 	* revert MII transceiver init change (jgarzik)
 
+	LK1.1.11:
+	* implement ETHTOOL_[GS]SET, _NWAY_RST, _[GS]MSGLVL, _GLINK (jgarzik)
+	* replace some MII-related magic numbers with constants
+
 */
 
 #define DRV_NAME	"epic100"
-#define DRV_VERSION	"1.11+LK1.1.10"
-#define DRV_RELDATE	"July 6, 2001"
+#define DRV_VERSION	"1.11+LK1.1.11"
+#define DRV_RELDATE	"Nov 17, 2001"
 
 
 /* The user-configurable values.
@@ -317,12 +321,9 @@
 	/* Ring pointers. */
 	spinlock_t lock;				/* Group with Tx control cache line. */
 	unsigned int cur_tx, dirty_tx;
-	struct descriptor  *last_tx_desc;
 
 	unsigned int cur_rx, dirty_rx;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
-	struct descriptor  *last_rx_desc;
-	long last_rx_time;					/* Last Rx, in jiffies. */
 
 	struct pci_dev *pci_dev;			/* PCI bus location. */
 	int chip_id, chip_flags;
@@ -334,13 +335,9 @@
 	signed char phys[4];				/* MII device addresses. */
 	u16 advertising;					/* NWay media advertisement */
 	int mii_phy_cnt;
+	struct mii_if_info mii;
 	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int full_duplex:1;			/* Current duplex setting. */
-	unsigned int duplex_lock:1;			/* Duplex forced by the user. */
 	unsigned int default_port:4;		/* Last dev->if_port value. */
-	unsigned int media2:4;				/* Secondary monitored media port. */
-	unsigned int medialock:1;			/* Don't sense media type. */
-	unsigned int mediasense:1;			/* Media sensing in progress. */
 };
 
 static int epic_open(struct net_device *dev);
@@ -419,6 +416,9 @@
 
 	pci_set_drvdata(pdev, dev);
 	ep = dev->priv;
+	ep->mii.dev = dev;
+	ep->mii.mdio_read = mdio_read;
+	ep->mii.mdio_write = mdio_write;
 
 	ring_space = pci_alloc_consistent(pdev, TX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space)
@@ -480,7 +480,7 @@
 	{
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < sizeof(ep->phys); phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
+			int mii_status = mdio_read(dev, phy, MII_BMSR);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				ep->phys[phy_idx++] = phy;
 				printk(KERN_INFO DRV_NAME "(%s): MII transceiver #%d control "
@@ -491,16 +491,17 @@
 		ep->mii_phy_cnt = phy_idx;
 		if (phy_idx != 0) {
 			phy = ep->phys[0];
-			ep->advertising = mdio_read(dev, phy, 4);
+			ep->mii.advertising = mdio_read(dev, phy, MII_ADVERTISE);
 			printk(KERN_INFO DRV_NAME "(%s): Autonegotiation advertising %4.4x link "
 				   "partner %4.4x.\n",
-				   pdev->slot_name, ep->advertising, mdio_read(dev, phy, 5));
+				   pdev->slot_name, ep->mii.advertising, mdio_read(dev, phy, 5));
 		} else if ( ! (ep->chip_flags & NO_MII)) {
 			printk(KERN_WARNING DRV_NAME "(%s): ***WARNING***: No MII transceiver found!\n",
 			       pdev->slot_name);
 			/* Use the known PHY address of the EPII. */
 			ep->phys[0] = 3;
 		}
+		ep->mii.phy_id = ep->phys[0];
 	}
 
 	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
@@ -510,13 +511,11 @@
 
 	/* The lower four bits are the media type. */
 	if (duplex) {
-		ep->duplex_lock = ep->full_duplex = 1;
+		ep->mii.duplex_lock = ep->mii.full_duplex = 1;
 		printk(KERN_INFO DRV_NAME "(%s):  Forced full duplex operation requested.\n",
 		       pdev->slot_name);
 	}
 	dev->if_port = ep->default_port = option;
-	if (ep->default_port)
-		ep->medialock = 1;
 
 	/* The Epic-specific entries in the device structure. */
 	dev->open = &epic_open;
@@ -699,29 +698,29 @@
 
 	if (media2miictl[dev->if_port & 15]) {
 		if (ep->mii_phy_cnt)
-			mdio_write(dev, ep->phys[0], 0, media2miictl[dev->if_port&15]);
+			mdio_write(dev, ep->phys[0], MII_BMCR, media2miictl[dev->if_port&15]);
 		if (dev->if_port == 1) {
 			if (debug > 1)
 				printk(KERN_INFO "%s: Using the 10base2 transceiver, MII "
 					   "status %4.4x.\n",
-					   dev->name, mdio_read(dev, ep->phys[0], 1));
+					   dev->name, mdio_read(dev, ep->phys[0], MII_BMSR));
 		}
 	} else {
-		int mii_reg5 = mdio_read(dev, ep->phys[0], 5);
-		if (mii_reg5 != 0xffff) {
-			if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
-				ep->full_duplex = 1;
-			else if (! (mii_reg5 & 0x4000))
-				mdio_write(dev, ep->phys[0], 0, 0x1200);
+		int mii_lpa = mdio_read(dev, ep->phys[0], MII_LPA);
+		if (mii_lpa != 0xffff) {
+			if ((mii_lpa & LPA_100FULL) || (mii_lpa & 0x01C0) == LPA_10FULL)
+				ep->mii.full_duplex = 1;
+			else if (! (mii_lpa & LPA_LPACK))
+				mdio_write(dev, ep->phys[0], MII_BMCR, BMCR_ANENABLE|BMCR_ANRESTART);
 			if (debug > 1)
 				printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
 					   " register read of %4.4x.\n", dev->name,
-					   ep->full_duplex ? "full" : "half",
-					   ep->phys[0], mii_reg5);
+					   ep->mii.full_duplex ? "full" : "half",
+					   ep->phys[0], mii_lpa);
 		}
 	}
 
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(ep->rx_ring_dma, ioaddr + PRxCDAR);
 	outl(ep->tx_ring_dma, ioaddr + PTxCDAR);
 
@@ -741,7 +740,7 @@
 		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
 			   "%s-duplex.\n",
 			   dev->name, ioaddr, dev->irq, (int)inl(ioaddr + GENCTL),
-			   ep->full_duplex ? "full" : "half");
+			   ep->mii.full_duplex ? "full" : "half");
 
 	/* Set the timer to switch to check for link beat and perhaps switch
 	   to an alternate media type. */
@@ -810,7 +809,7 @@
 
 	ep->tx_threshold = TX_FIFO_THRESH;
 	outl(ep->tx_threshold, ioaddr + TxThresh);
-	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	outl(ep->rx_ring_dma + (ep->cur_rx%RX_RING_SIZE)*
 		sizeof(struct epic_rx_desc), ioaddr + PRxCDAR);
 	outl(ep->tx_ring_dma + (ep->dirty_tx%TX_RING_SIZE)*
@@ -836,20 +835,20 @@
 {
 	struct epic_private *ep = dev->priv;
 	long ioaddr = dev->base_addr;
-	int mii_reg5 = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], 5) : 0;
-	int negotiated = mii_reg5 & ep->advertising;
+	int mii_lpa = ep->mii_phy_cnt ? mdio_read(dev, ep->phys[0], MII_LPA) : 0;
+	int negotiated = mii_lpa & ep->mii.advertising;
 	int duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
 
-	if (ep->duplex_lock)
+	if (ep->mii.duplex_lock)
 		return;
-	if (mii_reg5 == 0xffff)		/* Bogus read */
+	if (mii_lpa == 0xffff)		/* Bogus read */
 		return;
-	if (ep->full_duplex != duplex) {
-		ep->full_duplex = duplex;
+	if (ep->mii.full_duplex != duplex) {
+		ep->mii.full_duplex = duplex;
 		printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
 			   " partner capability of %4.4x.\n", dev->name,
-			   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
-		outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+			   ep->mii.full_duplex ? "full" : "half", ep->phys[0], mii_lpa);
+		outl(ep->mii.full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
 	}
 }
 
@@ -913,7 +912,6 @@
 	ep->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 	ep->dirty_tx = ep->cur_tx = 0;
 	ep->cur_rx = ep->dirty_rx = 0;
-	ep->last_rx_time = jiffies;
 	ep->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
 
 	/* Initialize all Rx descriptors. */
@@ -1371,17 +1369,66 @@
 		return -EFAULT;
 
 	switch (ethcmd) {
-	case ETHTOOL_GDRVINFO:
-		{
-			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
-			strcpy (info.driver, DRV_NAME);
-			strcpy (info.version, DRV_VERSION);
-			strcpy (info.bus_info, np->pci_dev->slot_name);
-			if (copy_to_user (useraddr, &info, sizeof (info)))
-				return -EFAULT;
-			return 0;
-		}
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
 
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
 	default:
 		break;
 	}
@@ -1432,11 +1479,11 @@
 			switch (data->reg_num) {
 			case 0:
 				/* Check for autonegotiation on or reset. */
-				ep->duplex_lock = (value & 0x9000) ? 0 : 1;
-				if (ep->duplex_lock)
-					ep->full_duplex = (value & 0x0100) ? 1 : 0;
+				ep->mii.duplex_lock = (value & 0x9000) ? 0 : 1;
+				if (ep->mii.duplex_lock)
+					ep->mii.full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
-			case 4: ep->advertising = value; break;
+			case 4: ep->mii.advertising = value; break;
 			}
 			/* Perhaps check_duplex(dev), depending on chip semantics. */
 		}
diff -urN linux-2.4.18-pre3/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- linux-2.4.18-pre3/drivers/net/fealnx.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/fealnx.c	Tue Jan 15 15:10:16 2002
@@ -15,8 +15,19 @@
 
 	Support information and updates available at
 	http://www.scyld.com/network/pci-skeleton.html
+
+	Linux kernel updates:
+
+	Version 2.51, Nov 17, 2001 (jgarzik):
+	- Add ethtool support
+	- Replace some MII-related magic numbers with constants
+
 */
 
+#define DRV_NAME	"fealnx"
+#define DRV_VERSION	"2.51"
+#define DRV_RELDATE	"Nov-17-2001"
+
 static int debug;		/* 1-> print debug message */
 static int max_interrupt_work = 20;
 
@@ -72,13 +83,15 @@
 #include <linux/skbuff.h>
 #include <linux/init.h>
 #include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <asm/processor.h>	/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "fealnx.c:v2.50 1/17/2001\n";
+KERN_INFO DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE "\n";
 
 
 /* This driver was written to use PCI memory space, however some x86 systems
@@ -379,6 +392,8 @@
 	dma_addr_t rx_ring_dma;
 	dma_addr_t tx_ring_dma;
 
+	spinlock_t lock;
+
 	struct net_device_stats stats;
 
 	/* Media monitoring timer. */
@@ -403,19 +418,17 @@
 	unsigned int linkok;
 	unsigned int line_speed;
 	unsigned int duplexmode;
-	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
-	unsigned int medialock:1;	/* Do not sense media. */
 	unsigned int default_port:4;	/* Last dev->if_port value. */
 	unsigned int PHYType;
 
 	/* MII transceiver section. */
 	int mii_cnt;		/* MII device addresses. */
 	unsigned char phys[2];	/* MII device addresses. */
+	struct mii_if_info mii;
 };
 
 
-static unsigned int mdio_read(struct net_device *dev, int phy_id, int location);
+static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int netdev_open(struct net_device *dev);
 static void getlinktype(struct net_device *dev);
@@ -539,9 +552,13 @@
 
 	/* Make certain the descriptor lists are aligned. */
 	np = dev->priv;
+	spin_lock_init(&np->lock);
 	np->pci_dev = pdev;
 	np->flags = skel_netdrv_tbl[chip_id].flags;
 	pci_set_drvdata(pdev, dev);
+	np->mii.dev = dev;
+	np->mii.mdio_read = mdio_read;
+	np->mii.mdio_write = mdio_write;
 
 	ring_space = pci_alloc_consistent(pdev, RX_TOTAL_SIZE, &ring_dma);
 	if (!ring_space) {
@@ -606,6 +623,7 @@
 		else
 			np->PHYType = OtherPHY;
 	}
+	np->mii.phy_id = np->phys[0];
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -613,17 +631,14 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii.full_duplex = 1;
 		np->default_port = option & 15;
-
-		if (np->default_port)
-			np->medialock = 1;
 	}
 
 	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
-		np->full_duplex = full_duplex[card_idx];
+		np->mii.full_duplex = full_duplex[card_idx];
 
-	if (np->full_duplex) {
+	if (np->mii.full_duplex) {
 		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
 /* 89/6/13 add, (begin) */
 //      if (np->PHYType==MarvellPHY)
@@ -636,10 +651,10 @@
 		}
 /* 89/6/13 add, (end) */
 		if (np->flags == HAS_MII_XCVR)
-			mdio_write(dev, np->phys[0], 4, 0x141);
+			mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		else
-			writel(0x141, dev->base_addr + ANARANLPAR);
-		np->duplex_lock = 1;
+			writel(ADVERTISE_FULL, dev->base_addr + ANARANLPAR);
+		np->mii.duplex_lock = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -787,7 +802,7 @@
 }
 
 
-static unsigned int mdio_read(struct net_device *dev, int phyad, int regad)
+static int mdio_read(struct net_device *dev, int phyad, int regad)
 {
 	long miiport = dev->base_addr + MANAGEMENT;
 	ulong miir;
@@ -821,7 +836,7 @@
 	miir &= ~MASK_MIIR_MII_MDC;
 	writel(miir, miiport);
 
-	return data;
+	return data & 0xffff;
 }
 
 
@@ -941,7 +956,7 @@
 // 89/9/1 modify,
 //   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */
 	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */
-	np->full_duplex = np->duplex_lock;
+	np->mii.full_duplex = np->mii.duplex_lock;
 	getlinkstatus(dev);
 	if (np->linkok)
 		getlinktype(dev);
@@ -990,7 +1005,7 @@
 		}
 	} else {
 		for (i = 0; i < DelayTime; ++i) {
-			if (mdio_read(dev, np->phys[0], 1) & 0x4) {
+			if (mdio_read(dev, np->phys[0], MII_BMSR) & BMSR_LSTATUS) {
 				np->linkok = 1;
 				return;
 			}
@@ -1475,7 +1490,7 @@
 						np->stats.tx_window_errors++;
 					if (tx_status & UDF)
 						np->stats.tx_fifo_errors++;
-					if ((tx_status & HF) && np->full_duplex == 0)
+					if ((tx_status & HF) && np->mii.full_duplex == 0)
 						np->stats.tx_heartbeat_errors++;
 
 #ifdef ETHER_STATS
@@ -1771,12 +1786,91 @@
 	writel(np->crvalue, ioaddr + TCRRCR);
 }
 
+static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	struct netdev_private *np = dev->priv;
+	u32 ethcmd;
+
+	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pci_dev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
 
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
 
 	switch (cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
@@ -1789,7 +1883,7 @@
 
 	case SIOCSMIIREG:		/* Write MII PHY register. */
 	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
-		if (!suser())
+		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 		mdio_write(dev, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
 		return 0;
diff -urN linux-2.4.18-pre3/drivers/net/hamradio/6pack.c linux/drivers/net/hamradio/6pack.c
--- linux-2.4.18-pre3/drivers/net/hamradio/6pack.c	Thu Sep 13 16:04:43 2001
+++ linux/drivers/net/hamradio/6pack.c	Tue Jan 15 15:10:16 2002
@@ -700,7 +700,6 @@
 /* Initialize 6pack control device -- register 6pack line discipline */
 
 static char msg_banner[]  __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n";
-static char msg_invparm[] __initdata = KERN_ERR  "6pack: sixpack_maxdev parameter too large.\n";
 static char msg_nomem[]   __initdata = KERN_ERR  "6pack: can't allocate sixpack_ctrls[] array! No 6pack available.\n";
 static char msg_regfail[] __initdata = KERN_ERR  "6pack: can't register line discipline (err = %d)\n";
 
diff -urN linux-2.4.18-pre3/drivers/net/mii.c linux/drivers/net/mii.c
--- linux-2.4.18-pre3/drivers/net/mii.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/mii.c	Tue Jan 15 15:10:16 2002
@@ -0,0 +1,174 @@
+/*
+
+	mii.c: MII interface library
+
+	Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
+	Copyright 2001 Jeff Garzik
+
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
+{
+	struct net_device *dev = mii->dev;
+	u32 advert, bmcr, lpa, nego;
+
+	ecmd->supported =
+	    (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+	     SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+	     SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
+
+	/* only supports twisted-pair */
+	ecmd->port = PORT_MII;
+
+	/* only supports internal transceiver */
+	ecmd->transceiver = XCVR_INTERNAL;
+
+	/* this isn't fully supported at higher layers */
+	ecmd->phy_address = mii->phy_id;
+
+	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
+	advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+	if (advert & ADVERTISE_10HALF)
+		ecmd->advertising |= ADVERTISED_10baseT_Half;
+	if (advert & ADVERTISE_10FULL)
+		ecmd->advertising |= ADVERTISED_10baseT_Full;
+	if (advert & ADVERTISE_100HALF)
+		ecmd->advertising |= ADVERTISED_100baseT_Half;
+	if (advert & ADVERTISE_100FULL)
+		ecmd->advertising |= ADVERTISED_100baseT_Full;
+
+	bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+	lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
+	if (bmcr & BMCR_ANENABLE) {
+		ecmd->advertising |= ADVERTISED_Autoneg;
+		ecmd->autoneg = AUTONEG_ENABLE;
+		
+		nego = mii_nway_result(advert & lpa);
+		if (nego == LPA_100FULL || nego == LPA_100HALF)
+			ecmd->speed = SPEED_100;
+		else
+			ecmd->speed = SPEED_10;
+		if (nego == LPA_100FULL || nego == LPA_10FULL) {
+			ecmd->duplex = DUPLEX_FULL;
+			mii->full_duplex = 1;
+		} else {
+			ecmd->duplex = DUPLEX_HALF;
+			mii->full_duplex = 0;
+		}
+	} else {
+		ecmd->autoneg = AUTONEG_DISABLE;
+
+		ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
+	}
+
+	/* ignore maxtxpkt, maxrxpkt for now */
+
+	return 0;
+}
+
+int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
+{
+	struct net_device *dev = mii->dev;
+
+	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
+		return -EINVAL;
+	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
+		return -EINVAL;
+	if (ecmd->port != PORT_MII)
+		return -EINVAL;
+	if (ecmd->transceiver != XCVR_INTERNAL)
+		return -EINVAL;
+	if (ecmd->phy_address != mii->phy_id)
+		return -EINVAL;
+	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
+		return -EINVAL;
+				  
+	/* ignore supported, maxtxpkt, maxrxpkt */
+	
+	if (ecmd->autoneg == AUTONEG_ENABLE) {
+		u32 bmcr, advert, tmp;
+
+		if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
+					  ADVERTISED_10baseT_Full |
+					  ADVERTISED_100baseT_Half |
+					  ADVERTISED_100baseT_Full)) == 0)
+			return -EINVAL;
+
+		/* advertise only what has been requested */
+		advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+		tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+		if (ADVERTISED_10baseT_Half)
+			tmp |= ADVERTISE_10HALF;
+		if (ADVERTISED_10baseT_Full)
+			tmp |= ADVERTISE_10FULL;
+		if (ADVERTISED_100baseT_Half)
+			tmp |= ADVERTISE_100HALF;
+		if (ADVERTISED_100baseT_Full)
+			tmp |= ADVERTISE_100FULL;
+		if (advert != tmp) {
+			mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
+			mii->advertising = tmp;
+		}
+		
+		/* turn on autonegotiation, and force a renegotiate */
+		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+		bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
+		mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+
+		mii->duplex_lock = 0;
+	} else {
+		u32 bmcr, tmp;
+
+		/* turn off auto negotiation, set speed and duplexity */
+		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
+		tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
+		if (ecmd->speed == SPEED_100)
+			bmcr |= BMCR_SPEED100;
+		if (ecmd->duplex == DUPLEX_FULL) {
+			bmcr |= BMCR_FULLDPLX;
+			mii->full_duplex = 1;
+		} else
+			mii->full_duplex = 0;
+		if (bmcr != tmp)
+			mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
+
+		mii->duplex_lock = 1;
+	}
+	return 0;
+}
+
+int mii_link_ok (struct mii_if_info *mii)
+{
+	if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
+		return 1;
+	return 0;
+}
+
+int mii_nway_restart (struct mii_if_info *mii)
+{
+	int bmcr;
+	int r = -EINVAL;
+
+	/* if autoneg is off, it's an error */
+	bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
+
+	if (bmcr & BMCR_ANENABLE) {
+		bmcr |= BMCR_ANRESTART;
+		mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
+		r = 0;
+	}
+
+	return r;
+}
+
+EXPORT_SYMBOL(mii_link_ok);
+EXPORT_SYMBOL(mii_nway_restart);
+EXPORT_SYMBOL(mii_ethtool_gset);
+EXPORT_SYMBOL(mii_ethtool_sset);
diff -urN linux-2.4.18-pre3/drivers/net/myri_code.h linux/drivers/net/myri_code.h
--- linux-2.4.18-pre3/drivers/net/myri_code.h	Wed Apr 23 19:01:20 1997
+++ linux/drivers/net/myri_code.h	Tue Jan 15 15:10:16 2002
@@ -6284,4 +6284,4 @@
 #define MYRI_NetReceiveBadCrcs       0xB8D4
 #define MYRI_NetReceiveBytes         0xB8DC
 
-#endif SYMBOL_DEFINES_COMPILED
+#endif /* SYMBOL_DEFINES_COMPILED */
diff -urN linux-2.4.18-pre3/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- linux-2.4.18-pre3/drivers/net/pcnet32.c	Tue Jan 15 15:10:09 2002
+++ linux/drivers/net/pcnet32.c	Tue Jan 15 15:10:16 2002
@@ -21,7 +21,12 @@
  *
  *************************************************************************/
 
-static const char *version = "pcnet32.c:v1.25kf 26.9.1999 tsbogend@alpha.franken.de\n";
+#define DRV_NAME	"pcnet32"
+#define DRV_VERSION	"1.25kf"
+#define DRV_RELDATE	"17.11.2001"
+
+static const char *version =
+DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " tsbogend@alpha.franken.de\n";
 
 #include <linux/module.h>
 
@@ -36,9 +41,12 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -284,11 +292,11 @@
     int	 shared_irq:1,			/* shared irq possible */
 	ltint:1,
 #ifdef DO_DXSUFLO
-	      dxsuflo:1,						    /* disable transmit stop on uflo */
+      dxsuflo:1,			    /* disable transmit stop on uflo */
 #endif
-	full_duplex:1,				/* full duplex possible */
 	mii:1;					/* mii port available */
     struct net_device *next;
+    struct mii_if_info mii_if;
 };
 
 static int  pcnet32_probe_vlbus(int cards_found);
@@ -303,9 +311,9 @@
 static int  pcnet32_close(struct net_device *);
 static struct net_device_stats *pcnet32_get_stats(struct net_device *);
 static void pcnet32_set_multicast_list(struct net_device *);
-#ifdef HAVE_PRIVATE_IOCTL
-static int  pcnet32_mii_ioctl(struct net_device *, struct ifreq *, int);
-#endif
+static int  pcnet32_ioctl(struct net_device *, struct ifreq *, int);
+static int mdio_read(struct net_device *dev, int phy_id, int reg_num);
+static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val);
 
 enum pci_flags_bit {
     PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
@@ -710,7 +718,7 @@
     dev->priv = lp;
     lp->name = chipname;
     lp->shared_irq = shared;
-    lp->full_duplex = fdx;
+    lp->mii_if.full_duplex = fdx;
 #ifdef DO_DXSUFLO
     lp->dxsuflo = dxsuflo;
 #endif
@@ -720,6 +728,9 @@
 	lp->options = PORT_ASEL;
     else
 	lp->options = options_mapping[options[card_idx]];
+    lp->mii_if.dev = dev;
+    lp->mii_if.mdio_read = mdio_read;
+    lp->mii_if.mdio_write = mdio_write;
     
     if (fdx && !(lp->options & PORT_ASEL) && full_duplex[card_idx])
 	lp->options |= PORT_FD;
@@ -789,9 +800,7 @@
     dev->stop = &pcnet32_close;
     dev->get_stats = &pcnet32_get_stats;
     dev->set_multicast_list = &pcnet32_set_multicast_list;
-#ifdef HAVE_PRIVATE_IOCTL
-    dev->do_ioctl = &pcnet32_mii_ioctl;
-#endif
+    dev->do_ioctl = &pcnet32_ioctl;
     dev->tx_timeout = pcnet32_tx_timeout;
     dev->watchdog_timeo = (HZ >> 1);
 
@@ -842,7 +851,7 @@
     lp->a.write_bcr (ioaddr, 2, val);
     
     /* handle full duplex setting */
-    if (lp->full_duplex) {
+    if (lp->mii_if.full_duplex) {
 	val = lp->a.read_bcr (ioaddr, 9) & ~3;
 	if (lp->options & PORT_FD) {
 	    val |= 1;
@@ -1496,29 +1505,157 @@
     pcnet32_restart(dev, 0x0042); /*  Resume normal operation */
 }
 
-#ifdef HAVE_PRIVATE_IOCTL
-static int pcnet32_mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int mdio_read(struct net_device *dev, int phy_id, int reg_num)
+{
+	struct pcnet32_private *lp = dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+	u16 val_out;
+	int phyaddr;
+
+	if (!lp->mii)
+		return 0;
+		
+	phyaddr = lp->a.read_bcr(ioaddr, 33);
+
+	lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+	val_out = lp->a.read_bcr(ioaddr, 34);
+	lp->a.write_bcr(ioaddr, 33, phyaddr);
+	
+	return val_out;
+}
+
+static void mdio_write(struct net_device *dev, int phy_id, int reg_num, int val)
+{
+	struct pcnet32_private *lp = dev->priv;
+	unsigned long ioaddr = dev->base_addr;
+	int phyaddr;
+
+	if (!lp->mii)
+		return;
+		
+	phyaddr = lp->a.read_bcr(ioaddr, 33);
+
+	lp->a.write_bcr(ioaddr, 33, ((phy_id & 0x1f) << 5) | (reg_num & 0x1f));
+	lp->a.write_bcr(ioaddr, 34, val);
+	lp->a.write_bcr(ioaddr, 33, phyaddr);
+}
+
+static int pcnet32_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	struct pcnet32_private *lp = dev->priv;
+	u32 ethcmd;
+	int phyaddr = 0;
+	int phy_id = 0;
+	unsigned long ioaddr = dev->base_addr;
+
+	if (lp->mii) {
+		phyaddr = lp->a.read_bcr (ioaddr, 33);
+		phy_id = (phyaddr >> 5) & 0x1f;
+		lp->mii_if.phy_id = phy_id;
+	}
+
+	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		if (lp->pci_dev)
+			strcpy (info.bus_info, lp->pci_dev->slot_name);
+		else
+			sprintf(info.bus_info, "VLB 0x%lx", dev->base_addr);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&lp->lock);
+		mii_ethtool_gset(&lp->mii_if, &ecmd);
+		spin_unlock_irq(&lp->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&lp->lock);
+		r = mii_ethtool_sset(&lp->mii_if, &ecmd);
+		spin_unlock_irq(&lp->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&lp->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&lp->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = pcnet32_debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		pcnet32_debug = edata.data;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int pcnet32_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
     unsigned long ioaddr = dev->base_addr;
     struct pcnet32_private *lp = dev->priv;	 
-    u16 *data = (u16 *)&rq->ifr_data;
+    struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
     int phyaddr = lp->a.read_bcr (ioaddr, 33);
 
+    if (cmd == SIOCETHTOOL)
+	return pcnet32_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
     if (lp->mii) {
 	switch(cmd) {
-	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
-	    data[0] = (phyaddr >> 5) & 0x1f;
+	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
+	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
+	    data->phy_id = (phyaddr >> 5) & 0x1f;
 	    /* Fall Through */
-	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
-	    lp->a.write_bcr (ioaddr, 33, ((data[0] & 0x1f) << 5) | (data[1] & 0x1f));
-	    data[3] = lp->a.read_bcr (ioaddr, 34);
+	case SIOCGMIIREG:		/* Read MII PHY register. */
+	case SIOCDEVPRIVATE+1:		/* for binary compat, remove in 2.5 */
+	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
+	    data->val_out = lp->a.read_bcr (ioaddr, 34);
 	    lp->a.write_bcr (ioaddr, 33, phyaddr);
 	    return 0;
-	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+	case SIOCSMIIREG:		/* Write MII PHY register. */
+	case SIOCDEVPRIVATE+2:		/* for binary compat, remove in 2.5 */
 	    if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
-	    lp->a.write_bcr (ioaddr, 33, ((data[0] & 0x1f) << 5) | (data[1] & 0x1f));
-	    lp->a.write_bcr (ioaddr, 34, data[2]);
+	    lp->a.write_bcr (ioaddr, 33, ((data->phy_id & 0x1f) << 5) | (data->reg_num & 0x1f));
+	    lp->a.write_bcr (ioaddr, 34, data->val_in);
 	    lp->a.write_bcr (ioaddr, 33, phyaddr);
 	    return 0;
 	default:
@@ -1527,13 +1664,12 @@
     }
     return -EOPNOTSUPP;
 }
-#endif	/* HAVE_PRIVATE_IOCTL */
 					    
 static struct pci_driver pcnet32_driver = {
-    name:  "pcnet32",
-    probe: pcnet32_probe_pci,
-    remove: NULL,
-    id_table: pcnet32_pci_tbl,
+	name:		DRV_NAME,
+	probe:		pcnet32_probe_pci,
+	remove:		NULL,
+	id_table:	pcnet32_pci_tbl,
 };
 
 MODULE_PARM(debug, "i");
diff -urN linux-2.4.18-pre3/drivers/net/rclanmtl.c linux/drivers/net/rclanmtl.c
--- linux-2.4.18-pre3/drivers/net/rclanmtl.c	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/rclanmtl.c	Tue Jan 15 15:10:16 2002
@@ -299,21 +299,21 @@
 {
 	int result;
 	PPAB pPab;
-	U32 pciBaseAddr = dev->base_addr;
 	PDPA pDpa = dev->priv;
+	U32 pciBaseAddr = dev->base_addr;
 	PU8 p_msgbuf = pDpa->PLanApiPA;
 	PU8 p_phymsgbuf = (PU8) virt_to_bus ((void *) p_msgbuf);
 
 	dprintk
-	    ("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:0x%08ulx phymsgbuf:0x%08ulx\n"
-	     "TransmitCallbackFunction:0x%08ulx  ReceiveCallbackFunction:0x%08ulx\n",
+	    ("InitI2O: Adapter:0x%x ATU:0x%x msgbuf:0x%x phymsgbuf:0x%x\n"
+	     "TransmitCallbackFunction:0x%x  ReceiveCallbackFunction:0x%x\n",
 	     pDpa->id, pciBaseAddr, (u32) p_msgbuf, (u32) p_phymsgbuf,
 	     (u32) TransmitCallbackFunction, (u32) ReceiveCallbackFunction);
 
 	/* Check if this interface already initialized - if so, shut it down */
 	if (pDpa->pPab != NULL) {
-		printk (KERN_WARNING
-			"(rcpci45 driver:) pDpa->pPab [%d] != NULL\n",
+		dprintk (KERN_WARNING
+			"pDpa->pPab [%d] != NULL\n",
 			pDpa->id);
 /*          RCResetLANCard(pDpa->id, 0, (PU32)NULL, (PFNCALLBACK)NULL); */
 		pDpa->pPab = NULL;
@@ -324,8 +324,8 @@
 
 	pPab = kmalloc (sizeof (*pPab), GFP_KERNEL);
 	if (!pPab) {
-		printk (KERN_ERR
-			"(rcpci45 driver:) RCInitI2OMsgLayer: Could not allocate memory for PAB struct!\n");
+		dprintk (KERN_ERR 
+				"RCInitI2OMsgLayer: Could not allocate memory for PAB struct!\n");
 		result = RC_RTN_MALLOC_ERROR;
 		goto err_out;
 	}
@@ -354,8 +354,7 @@
 		goto err_out_dealloc;
 
 	if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL) {
-		printk (KERN_INFO
-			"(rcpci45 driver:) pPab->IOPState == op: resetting adapter\n");
+		dprintk (KERN_INFO "pPab->IOPState == op: resetting adapter\n");
 		RCResetLANCard (dev, 0, (PU32) NULL, (PFNCALLBACK) NULL);
 	}
 
@@ -445,7 +444,7 @@
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
-	/* calc virual address of msg - virual already mapped to physical */
+	/* calc virtual address of msg - virtual already mapped to physical */
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
 	size = FillI2OMsgSGLFromTCB (pMsg + 4, pTransCtrlBlock);
@@ -502,7 +501,7 @@
 		dprintk ("RCPostRecvBuffers(): Inbound Free Q empty!\n");
 		return RC_RTN_FREE_Q_EMPTY;
 	}
-	/* calc virual address of msg - virual already mapped to physical */
+	/* calc virtual address of msg - virtual already mapped to physical */
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
 	size = FillI2OMsgSGLFromTCB (pMsg + 4, pTransCtrlBlock);
@@ -570,13 +569,13 @@
 						     dev);
 		} else if (I2O_LAN_RECEIVE_POST == p8Msg[7]) {	/* Receive Packet Reply Msg */
 			dprintk
-			    ("I2O_RECV_REPLY pPab:0x%08ulx p8Msg:0x%08ulx p32:0x%08ulx\n",
+			    ("I2O_RECV_REPLY pPab:0x%x p8Msg:0x%x p32:0x%x\n",
 			     (u32) pPab, (u32) p8Msg, (u32) p32);
-			dprintk ("msg: 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+			dprintk ("msg: 0x%x:0x%x:0x%x:0x%x\n",
 				 p32[0], p32[1], p32[2], p32[3]);
-			dprintk ("     0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+			dprintk ("     0x%x:0x%x:0x%x:0x%x\n",
 				 p32[4], p32[5], p32[6], p32[7]);
-			dprintk ("     0x%08ulx:0X%08ulx:0x%08ulx:0x%08ulx\n",
+			dprintk ("     0x%x:0X%x:0x%x:0x%x\n",
 				 p32[8], p32[9], p32[10], p32[11]);
 			/*  status, count, buckets remaining, packetParmBlock, adapter */
 			(*pPab->pRecvCallbackFunc) (p8Msg[19], p8Msg[12],
@@ -623,8 +622,8 @@
 								      dev);
 				break;
 			default:
-				printk (KERN_WARNING
-					"(rcpci45 driver:) Unknown private I2O msg received: 0x%x\n",
+				dprintk (KERN_WARNING
+					"Unknown private I2O msg received: 0x%x\n",
 					p32[5]);
 				break;
 			}
@@ -658,14 +657,13 @@
 		     PFNWAITCALLBACK WaitCallback)
 {
 	U32 msgOffset;
-	volatile U32 timeout;
 	volatile PU32 pMsg;
 	volatile PU32 p32, pReturnAddr;
 	P_NICSTAT pStats;
 	int i;
 	PPAB pPab = ((PDPA) dev->priv)->pPab;
 
-/*dprintk("Get82558Stats() StatsReturnAddr:0x%08ulx\n", StatsReturnAddr); */
+/*dprintk("Get82558Stats() StatsReturnAddr:0x%x\n", StatsReturnAddr); */
 
 	if (pPab == NULL)
 		return RC_RTN_ADPTR_NOT_REGISTERED;
@@ -677,10 +675,10 @@
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
-	/* calc virual address of msg - virual already mapped to physical */
+	/* calc virtual address of msg - virtual already mapped to physical */
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
-/*dprintk("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintk("Get82558Stats - pMsg = 0x%x, InQ msgOffset = 0x%x\n", pMsg, msgOffset);*/
 /*dprintk("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
 
 	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -690,30 +688,22 @@
 	pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS;
 	pMsg[5] = pPab->outMsgBlockPhyAddr;
 
-	p32 = (PU32) pPab->outMsgBlockPhyAddr;
+//	p32 = (PU32) pPab->outMsgBlockPhyAddr;
+	p32 = (PU32)pPab->pLinOutMsgBlock;
 	pStats = (P_NICSTAT) pPab->pLinOutMsgBlock;
 	pStats->dump_status = 0xFFFFFFFF;
 
 	/* post to Inbound Post Q */
 	pPab->p_atu->InQueue = msgOffset;
 
-	timeout = 100000;
-	while (1) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);
-
-		if (pStats->dump_status != 0xFFFFFFFF)
-			break;
-
-		if (!timeout--) {
-			dprintk
-			    ("RCGet82558Stats() Timeout waiting for NIC statistics\n");
+	i = 0;
+	while (pStats->dump_status == 0xFFFFFFFF) {
+		if (i++ > 0xff) {
+			dprintk ("Timeout waiting for NIC statistics\n");
 			return RC_RTN_MSG_REPLY_TIMEOUT;
 		}
+		udelay(50);
 	}
-
 	pReturnAddr = (PU32) StatsReturnAddr;
 
 	/* copy Nic stats to user's structure */
@@ -732,13 +722,13 @@
 RCGetLinkStatus (struct net_device * dev, PU32 ReturnAddr,
 		 PFNWAITCALLBACK WaitCallback)
 {
+	int i;
 	U32 msgOffset;
-	volatile U32 timeout;
 	volatile PU32 pMsg;
 	volatile PU32 p32;
 	PPAB pPab = ((PDPA) dev->priv)->pPab;
 
-	dprintk ("Get82558LinkStatus() ReturnPhysAddr:0x%08ulx\n",
+	dprintk ("Get82558LinkStatus() ReturnPhysAddr:0x%x\n",
 		 (u32) ReturnAddr);
 
 	if (pPab == NULL)
@@ -751,9 +741,9 @@
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
-	/* calc virual address of msg - virual already mapped to physical */
+	/* calc virtual address of msg - virtual already mapped to physical */
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
-/*dprintk("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintk("Get82558LinkStatus - pMsg = 0x%x, InQ msgOffset = 0x%x\n", pMsg, msgOffset);*/
 /*dprintk("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
 
 	pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -769,20 +759,13 @@
 	/* post to Inbound Post Q */
 	pPab->p_atu->InQueue = msgOffset;
 
-	timeout = 100000;
-	while (1) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);
-
-		if (*p32 != 0xFFFFFFFF)
-			break;
-
-		if (!timeout--) {
+	i = 0;
+	while (*p32 == 0xFFFFFFFF) {
+		if (i++ > 0xff) {
 			dprintk ("Timeout waiting for link status\n");
 			return RC_RTN_MSG_REPLY_TIMEOUT;
 		}
+		udelay(50);
 	}
 
 	*ReturnAddr = *p32;	/* 1 = up 0 = down */
@@ -802,8 +785,7 @@
 RC_RETURN
 RCGetMAC (struct net_device * dev, PFNWAITCALLBACK WaitCallback)
 {
-	unsigned timeout;
-	U32 off;
+	U32 off, i;
 	PU8 mac = dev->dev_addr;
 	PU32 p;
 	U32 temp[2];
@@ -839,17 +821,13 @@
 		 (uint) p_atu, (uint) off, (uint) p);
 
 	/* wait for the rcpci45 board to update the info */
-	timeout = 1000000;
+	i = 0;
 	while (0 == p_atu->EtherMacLow) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);
-
-		if (!timeout--) {
-			printk ("rc_getmac: Timeout\n");
+		if (i++ > 0xff) {
+			dprintk ("rc_getmac: Timeout\n");
 			return RC_RTN_MSG_REPLY_TIMEOUT;
-		}
+		}	
+		udelay(50);
 	}
 
 	/* read the mac address  */
@@ -1001,16 +979,16 @@
 RCGetPromiscuousMode (struct net_device * dev, PU32 pMode,
 		      PFNWAITCALLBACK WaitCallback)
 {
-	U32 msgOffset, timeout;
 	PU32 pMsg;
 	volatile PU32 p32;
+	U32 msgOffset, i;
 	PPAB pPab = ((PDPA) dev->priv)->pPab;
 
 	msgOffset = pPab->p_atu->InQueue;
 
 	if (msgOffset == 0xFFFFFFFF) {
-		printk (KERN_WARNING
-			"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
+		dprintk (KERN_WARNING
+			"RCGetLinkSpeed(): Inbound Free Q empty!\n");
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
@@ -1034,23 +1012,15 @@
 
 	pPab->p_atu->InQueue = msgOffset;
 
-	/* wait for response */
-	timeout = 1000000;
-	while (1) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0] != 0xff)
-			break;
+	i = 0;
 
-		if (!timeout--) {
-			dprintk
-			    ("Timeout waiting for promiscuous mode from adapter\n");
-			dprintk ("0x%8x\n", p32[0]);
+	/* wait for response */
+	while (p32[0] == 0xff) {
+		if (i++ > 0xff) {
+			dprintk ("Timeout waiting for promiscuous mode\n");
 			return RC_RTN_NO_LINK_SPEED;
 		}
+		udelay(50);
 	}
 
 	/* get mode */
@@ -1115,7 +1085,7 @@
 RCGetBroadcastMode (struct net_device * dev, PU32 pMode,
 		    PFNWAITCALLBACK WaitCallback)
 {
-	U32 msgOffset, timeout;
+	U32 msgOffset;
 	PU32 pMsg;
 	volatile PU32 p32;
 	PPAB pPab = ((PDPA) dev->priv)->pPab;
@@ -1123,8 +1093,8 @@
 	msgOffset = pPab->p_atu->InQueue;
 
 	if (msgOffset == 0xFFFFFFFF) {
-		printk (KERN_WARNING
-			"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
+		dprintk (KERN_WARNING
+			"RCGetLinkSpeed(): Inbound Free Q empty!\n");
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
@@ -1149,23 +1119,10 @@
 	pPab->p_atu->InQueue = msgOffset;
 
 	/* wait for response */
-	timeout = 1000000;
-	while (1) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0] != 0xff)
-			break;
-
-		if (!timeout--) {
-			printk (KERN_WARNING
-				"(rcpci45 driver:) Timeout waiting for promiscuous mode from adapter\n");
-			printk (KERN_WARNING "(rcpci45 driver:) 0x%8x\n",
-				p32[0]);
-			return RC_RTN_NO_LINK_SPEED;
-		}
+	if (p32[0] == 0xff) {
+		dprintk (KERN_WARNING
+			"Timeout waiting for promiscuous mode\n");
+		return RC_RTN_NO_LINK_SPEED;
 	}
 
 	/* get mode */
@@ -1192,7 +1149,7 @@
 RCGetLinkSpeed (struct net_device * dev, PU32 pLinkSpeedCode,
 		PFNWAITCALLBACK WaitCallback)
 {
-	U32 msgOffset, timeout;
+	U32 msgOffset, i;
 	PU32 pMsg;
 	volatile PU32 p32;
 	U8 IOPLinkSpeed;
@@ -1201,8 +1158,8 @@
 	msgOffset = pPab->p_atu->InQueue;
 
 	if (msgOffset == 0xFFFFFFFF) {
-		printk (KERN_WARNING
-			"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
+		dprintk (KERN_WARNING
+			"RCGetLinkSpeed(): Inbound Free Q empty!\n");
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
@@ -1227,26 +1184,16 @@
 	pPab->p_atu->InQueue = msgOffset;
 
 	/* wait for response */
-	timeout = 1000000;
-	while (1) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0] != 0xff)
-			break;
-
-		if (!timeout--) {
-			dprintk ("Timeout waiting for link speed from IOP\n");
-			dprintk ("0x%8x\n", p32[0]);
+	i = 0;
+	while (p32[0] == 0xff) {
+		if (i++ > 0xff) {
+			dprintk ("Timeout waiting for link speed\n");
 			return RC_RTN_NO_LINK_SPEED;
 		}
+		udelay(50);
 	}
-
 	/* get Link speed */
 	IOPLinkSpeed = (U8) ((volatile PU8) p32)[0] & 0x0f;
-
 	*pLinkSpeedCode = IOPLinkSpeed;
 
 	return RC_RTN_NO_ERROR;
@@ -1304,7 +1251,7 @@
 RCGetFirmwareVer (struct net_device * dev, PU8 pFirmString,
 		  PFNWAITCALLBACK WaitCallback)
 {
-	U32 msgOffset, timeout;
+	U32 msgOffset, i;
 	PU32 pMsg;
 	volatile PU32 p32;
 	PPAB pPab = ((PDPA) dev->priv)->pPab;
@@ -1336,22 +1283,14 @@
 	pPab->p_atu->InQueue = msgOffset;
 
 	/* wait for response */
-	timeout = 1000000;
-	while (1) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0] != 0xff)
-			break;
-
-		if (!timeout--) {
-			dprintk ("Timeout waiting for link speed from IOP\n");
+	i = 0;
+	while (p32[0] == 0xff) {
+		if (i++ > 0xff) {
+			dprintk ("Timeout waiting for link speed\n");
 			return RC_RTN_NO_FIRM_VER;
 		}
+		udelay(50);
 	}
-
 	strcpy (pFirmString, (PU8) p32);
 	return RC_RTN_NO_ERROR;
 }
@@ -1403,9 +1342,9 @@
 		   or until timer goes off */
 		while (pPab->pCallbackFunc == (PFNCALLBACK) NULL) {
 			RCProcI2OMsgQ (dev);
-			udelay (1000);	/* please don't hog the bus!!! */
+			mdelay (1);
 			timeout++;
-			if (timeout > 10000) {
+			if (timeout > 200) {
 				break;
 			}
 		}
@@ -1427,7 +1366,7 @@
 RC_RETURN
 RCResetIOP (struct net_device * dev)
 {
-	U32 msgOffset, timeout;
+	U32 msgOffset, i;
 	PU32 pMsg;
 	PPAB pPab = ((PDPA) dev->priv)->pPab;
 	volatile PU32 p32;
@@ -1452,7 +1391,7 @@
 	pMsg[7] = 0;
 	pMsg[8] = 1;		/*  return 1 byte */
 
-	/* virual pointer to return buffer - clear first two dwords */
+	/* virtual pointer to return buffer - clear first two dwords */
 	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
 	p32[0] = 0;
 	p32[1] = 0;
@@ -1462,17 +1401,13 @@
 	pPab->p_atu->InQueue = msgOffset;
 
 	/* wait for response */
-	timeout = 1000000;
-	while (1) {
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0] || p32[1])
-			break;
-
-		if (!timeout--) {
+	i = 0;
+	while (!p32[0] && !p32[1]) {
+		if (i++ > 0xff) {
 			dprintk ("RCResetIOP timeout\n");
 			return RC_RTN_MSG_REPLY_TIMEOUT;
 		}
+		udelay(100);
 	}
 	return RC_RTN_NO_ERROR;
 }
@@ -1525,11 +1460,11 @@
 		   or until timer goes off */
 		while (pPab->pCallbackFunc == (PFNCALLBACK) NULL) {
 			RCProcI2OMsgQ (dev);
-			udelay (1000);	/* please don't hog the bus!!! */
+			mdelay (1);
 			timeout++;
-			if (timeout > 10000) {
-				printk (KERN_WARNING
-					"(rcpci45 driver:) RCShutdownLANCard(): timeout\n");
+			if (timeout > 200) {
+				dprintk (KERN_WARNING
+					"RCShutdownLANCard(): timeout\n");
 				break;
 			}
 		}
@@ -1594,14 +1529,13 @@
 RCGetRavlinIPandMask (struct net_device * dev, PU32 pIpAddr, PU32 pNetMask,
 		      PFNWAITCALLBACK WaitCallback)
 {
-	unsigned timeout;
-	U32 off;
+	U32 off, i;
 	PU32 pMsg, p32;
 	PPAB pPab = ((PDPA) dev->priv)->pPab;
 	PATU p_atu;
 
 	dprintk
-	    ("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n",
+	    ("RCGetRavlinIPandMask: pIpAddr is 0x%x, *IpAddr is 0x%x\n",
 	     (u32) pIpAddr, *pIpAddr);
 
 	if (pPab == NULL)
@@ -1619,7 +1553,7 @@
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + off);
 
 	dprintk
-	    ("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n",
+	    ("RCGetRavlinIPandMask: p_atu 0x%x, off 0x%x, p32 0x%x\n",
 	     (u32) p_atu, off, (u32) p32);
 	/* setup private message */
 	pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1631,25 +1565,21 @@
 
 	p_atu->InQueue = off;	/* send it to the I2O device */
 	dprintk
-	    ("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n",
+	    ("RCGetRavlinIPandMask: p_atu 0x%x, off 0x%x, p32 0x%x\n",
 	     (u32) p_atu, off, (u32) p32);
 
 	/* wait for the rcpci45 board to update the info */
-	timeout = 100000;
+	i = 0;
 	while (0xffffffff == *p32) {
-		if (WaitCallback)
-			(*WaitCallback) ();
-
-		udelay (10);
-
-		if (!timeout--) {
+		if (i++ > 0xff) {
 			dprintk ("RCGetRavlinIPandMask: Timeout\n");
 			return RC_RTN_MSG_REPLY_TIMEOUT;
 		}
+		udelay(50);
 	}
 
 	dprintk
-	    ("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%08ulx, p32[1] (IPmask) 0x%08ulx\n",
+	    ("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%x, p32[1] (IPmask) 0x%x\n",
 	     p32[0], p32[1]);
 
 	/* send IP and mask to user's space  */
@@ -1657,7 +1587,7 @@
 	*pNetMask = p32[1];
 
 	dprintk
-	    ("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n",
+	    ("RCGetRavlinIPandMask: pIpAddr is 0x%x, *IpAddr is 0x%x\n",
 	     (u32) pIpAddr, *pIpAddr);
 
 	return RC_RTN_NO_ERROR;
@@ -1682,7 +1612,7 @@
 static int
 SendI2OOutboundQInitMsg (PPAB pPab)
 {
-	U32 msgOffset, timeout, phyOutQFrames, i;
+	U32 msgOffset, phyOutQFrames, i;
 	volatile PU32 pMsg;
 	volatile PU32 p32;
 
@@ -1693,11 +1623,11 @@
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
-	/* calc virual address of msg - virual already mapped to physical */
+	/* calc virtual address of msg - virtual already mapped to physical */
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
 	dprintk
-	    ("SendI2OOutboundQInitMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n",
+	    ("SendI2OOutboundQInitMsg - pMsg = 0x%x, InQ msgOffset = 0x%x\n",
 	     (u32) pMsg, msgOffset);
 
 	pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
@@ -1711,7 +1641,7 @@
 	/* phys address to return status - area right after PAB */
 	pMsg[7] = pPab->outMsgBlockPhyAddr;
 
-	/* virual pointer to return buffer - clear first two dwords */
+	/* virtual pointer to return buffer - clear first two dwords */
 	p32 = (PU32) pPab->pLinOutMsgBlock;
 	p32[0] = 0;
 
@@ -1719,34 +1649,19 @@
 	pPab->p_atu->InQueue = msgOffset;
 
 	/* wait for response */
-	timeout = 100000;
-	while (1) {
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0])
-			break;
-
-		if (!timeout--) {
-			dprintk
-			    ("Timeout wait for InitOutQ InPrgress status from IOP\n");
+	i = 0;
+	while (!p32[0]) {
+		if (i++ > 0xff) {
+			printk("rc: InitOutQ timeout\n");
 			return RC_RTN_NO_I2O_STATUS;
 		}
+		udelay(50);
 	}
-
-	timeout = 100000;
-	while (1) {
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE)
-			break;
-
-		if (!timeout--) {
-			dprintk
-			    ("Timeout wait for InitOutQ Complete status from IOP\n");
-			return RC_RTN_NO_I2O_STATUS;
-		}
+	if (p32[0] != I2O_EXEC_OUTBOUND_INIT_COMPLETE) {
+		printk("rc: exec outbound init failed (%x)\n",
+				p32[0]);
+		return RC_RTN_NO_I2O_STATUS;
 	}
-
 	/* load PCI outbound free Q with MF physical addresses */
 	phyOutQFrames = pPab->outMsgBlockPhyAddr;
 
@@ -1768,7 +1683,7 @@
 static int
 GetI2OStatus (PPAB pPab)
 {
-	U32 msgOffset, timeout;
+	U32 msgOffset, i;
 	PU32 pMsg;
 	volatile PU32 p32;
 
@@ -1779,7 +1694,7 @@
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
-	/* calc virual address of msg - virual already mapped to physical */
+	/* calc virtual address of msg - virtual already mapped to physical */
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
 	pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1793,51 +1708,41 @@
 	pMsg[7] = 0;
 	pMsg[8] = 88;		/*  return 88 bytes */
 
-	/* virual pointer to return buffer - clear first two dwords */
+	/* virtual pointer to return buffer - clear first two dwords */
 	p32 = (volatile PU32) pPab->pLinOutMsgBlock;
 	p32[0] = 0;
 	p32[1] = 0;
 
 	dprintk
-	    ("GetI2OStatus - pMsg:0x%08ulx, msgOffset:0x%08ulx, [1]:0x%08ulx, [6]:0x%08ulx\n",
+	    ("GetI2OStatus - pMsg:0x%x, msgOffset:0x%x, [1]:0x%x, [6]:0x%x\n",
 	     (u32) pMsg, msgOffset, pMsg[1], pMsg[6]);
 
 	/* post to Inbound Post Q */
 	pPab->p_atu->InQueue = msgOffset;
 
-	dprintk ("Return status to p32 = 0x%08ulx\n", (u32) p32);
+	dprintk ("Return status to p32 = 0x%x\n", (u32) p32);
 
 	/* wait for response */
-	timeout = 1000000;
-	while (1) {
-		udelay (10);	/* please don't hog the bus!!! */
-
-		if (p32[0] && p32[1])
-			break;
-
-		if (!timeout--) {
+	i = 0;
+	while (!p32[0] || !p32[1]) {
+		if (i++ > 0xff) {
 			dprintk ("Timeout waiting for status from IOP\n");
-			dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
-				 p32[0], p32[1], p32[2], p32[3]);
-			dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
-				 p32[4], p32[5], p32[6], p32[7]);
-			dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
-				 p32[8], p32[9], p32[10], p32[11]);
 			return RC_RTN_NO_I2O_STATUS;
 		}
+		udelay(50);
 	}
 
-	dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1],
+	dprintk ("0x%x:0x%x:0x%x:0x%x\n", p32[0], p32[1],
 		 p32[2], p32[3]);
-	dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5],
+	dprintk ("0x%x:0x%x:0x%x:0x%x\n", p32[4], p32[5],
 		 p32[6], p32[7]);
-	dprintk ("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9],
+	dprintk ("0x%x:0x%x:0x%x:0x%x\n", p32[8], p32[9],
 		 p32[10], p32[11]);
 	/* get IOP state */
 	pPab->IOPState = ((volatile PU8) p32)[10];
 	pPab->InboundMFrameSize = ((volatile PU16) p32)[6];
 
-	dprintk ("IOP state 0x%02x InFrameSize = 0x%04x\n",
+	dprintk ("IOP state 0x%x InFrameSize = 0x%x\n",
 		 pPab->IOPState, pPab->InboundMFrameSize);
 	return RC_RTN_NO_ERROR;
 }
@@ -1862,11 +1767,11 @@
 		return RC_RTN_FREE_Q_EMPTY;
 	}
 
-	/* calc virual address of msg - virual already mapped to physical */
+	/* calc virtual address of msg - virtual already mapped to physical */
 	pMsg = (PU32) (pPab->pPci45LinBaseAddr + msgOffset);
 
 	dprintk
-	    ("SendEnableSysMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n",
+	    ("SendEnableSysMsg - pMsg = 0x%x, InQ msgOffset = 0x%x\n",
 	     (u32) pMsg, msgOffset);
 
 	pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
@@ -1885,7 +1790,7 @@
 ** =========================================================================
 ** FillI2OMsgFromTCB()
 **
-** inputs   pMsgU32 - virual pointer (mapped to physical) of message frame
+** inputs   pMsgU32 - virtual pointer (mapped to physical) of message frame
 **          pXmitCntrlBlock - pointer to caller buffer control block.
 **
 ** fills in LAN SGL after Transaction Control Word or Bucket Count.
@@ -1908,9 +1813,9 @@
 	nmbrDwords = 0;
 
 	dprintk ("FillI2OMsgSGLFromTCBX\n");
-	dprintk ("TCB  0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+	dprintk ("TCB  0x%x:0x%x:0x%x:0x%x:0x%x\n",
 		 pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
-	dprintk ("pTCB 0x%08ulx, pMsg 0x%08ulx\n", (u32) pTCB, (u32) pMsg);
+	dprintk ("pTCB 0x%x, pMsg 0x%x\n", (u32) pTCB, (u32) pMsg);
 
 	nmbrBuffers = *pTCB++;
 
@@ -1987,11 +1892,11 @@
 	p32 = (PU32) p8Msg;
 
 	dprintk
-	    ("VXD: ProcessOutboundI2OMsg - pPab 0x%08ulx, phyAdr 0x%08ulx, linAdr 0x%08ulx\n",
+	    ("VXD: ProcessOutboundI2OMsg - pPab 0x%x, phyAdr 0x%x, linAdr 0x%x\n",
 	     (u32) pPab, phyAddrMsg, (u32) p8Msg);
-	dprintk ("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1],
+	dprintk ("msg :0x%x:0x%x:0x%x:0x%x\n", p32[0], p32[1],
 		 p32[2], p32[3]);
-	dprintk ("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5],
+	dprintk ("msg :0x%x:0x%x:0x%x:0x%x\n", p32[4], p32[5],
 		 p32[6], p32[7]);
 
 	if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS) {
diff -urN linux-2.4.18-pre3/drivers/net/rclanmtl.h linux/drivers/net/rclanmtl.h
--- linux-2.4.18-pre3/drivers/net/rclanmtl.h	Mon Jul  2 14:03:04 2001
+++ linux/drivers/net/rclanmtl.h	Tue Jan 15 15:10:16 2002
@@ -54,10 +54,10 @@
 #include <asm/io.h>
 
 /* Debug stuff. Define for debug output */
-#define RCDEBUG
+#undef RCDEBUG
 
 #ifdef RCDEBUG
-#define dprintk(args...) printk(KERN_DEBUG "(rcpci45 driver:) " args)
+#define dprintk(args...) printk("rc: " args)
 #else
 #define dprintk(args...) { }
 #endif
diff -urN linux-2.4.18-pre3/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- linux-2.4.18-pre3/drivers/net/rcpci45.c	Sun Sep 30 12:26:07 2001
+++ linux/drivers/net/rcpci45.c	Tue Jan 15 15:10:16 2002
@@ -29,6 +29,9 @@
 **  along with this program; if not, write to the Free Software
 **  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
+**  Pete Popov, Oct 2001: Fixed a few bugs to make the driver functional
+**  again. Note that this card is not supported or manufactured by 
+**  RedCreek anymore.
 **   
 **  Rasmus Andersen, December 2000: Converted to new PCI API and general
 **  cleanup.
@@ -62,7 +65,7 @@
 #include <asm/uaccess.h>
 
 static char version[] __initdata =
-    "RedCreek Communications PCI linux driver version 2.03\n";
+    "RedCreek Communications PCI linux driver version 2.20\n";
 
 #define RC_LINUX_MODULE
 #include "rclanmtl.h"
@@ -87,6 +90,14 @@
 /* RedCreek's OSM default LAN receive Initiator */
 #define DEFAULT_RECV_INIT_CONTEXT  0xA17
 
+/* minimum msg buffer size needed by the card 
+ * Note that the size of this buffer is hard code in the
+ * ipsec card's firmware. Thus, the size MUST be a minimum
+ * of 16K. Otherwise the card will end up using memory
+ * that does not belong to it.
+ */
+#define MSG_BUF_SIZE  16384
+
 static U32 DriverControlWord;
 
 static void rc_timer (unsigned long);
@@ -120,39 +131,25 @@
 	PDPA pDpa = dev->priv;
 
 	if (!dev) {
-		printk (KERN_ERR
-			"(rcpci45 driver:) remove non-existent device\n");
+		printk (KERN_ERR "%s: remove non-existent device\n",
+				dev->name);
 		return;
 	}
 
-	dprintk ("remove_one: IOP reset: 0x%x\n", RCResetIOP (dev));
-
-	/* RAA Inspired by starfire.c and yellowfin.c we keep these
-	 * here. */
+	RCResetIOP (dev);
 	unregister_netdev (dev);
 	free_irq (dev->irq, dev);
 	iounmap ((void *) dev->base_addr);
 	pci_release_regions (pdev);
-	kfree (pDpa->PLanApiPA);
-	kfree (pDpa->pPab);
-	kfree (pDpa);
+	if (pDpa->msgbuf)
+		kfree (pDpa->msgbuf);
+	if (pDpa->pPab)
+		kfree (pDpa->pPab);
 	kfree (dev);
 	pci_set_drvdata (pdev, NULL);
 }
 
 static int
-RCinit (struct net_device *dev)
-{
-	dev->open = &RCopen;
-	dev->hard_start_xmit = &RC_xmit_packet;
-	dev->stop = &RCclose;
-	dev->get_stats = &RCget_stats;
-	dev->do_ioctl = &RCioctl;
-	dev->set_config = &RCconfig;
-	return 0;
-}
-
-static int
 rcpci45_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	unsigned long *vaddr;
@@ -166,17 +163,17 @@
 
 	/* 
 	 * Allocate and fill new device structure. 
-	 * We need enough for struct net_device plus DPA plus the LAN API private
-	 * area, which requires a minimum of 16KB.  The top of the allocated
-	 * area will be assigned to struct net_device; the next chunk will be
-	 * assigned to DPA; and finally, the rest will be assigned to the
-	 * the LAN API layer.
+	 * We need enough for struct net_device plus DPA plus the LAN 
+	 * API private area, which requires a minimum of 16KB.  The top 
+	 * of the allocated area will be assigned to struct net_device; 
+	 * the next chunk will be assigned to DPA; and finally, the rest 
+	 * will be assigned to the the LAN API layer.
 	 */
 
 	dev = init_etherdev (NULL, sizeof (*pDpa));
 	if (!dev) {
 		printk (KERN_ERR
-			"(rcpci45 driver:) unable to allocate in init_etherdev\n");
+			"(rcpci45 driver:) init_etherdev alloc failed\n");
 		error = -ENOMEM;
 		goto err_out;
 	}
@@ -184,13 +181,14 @@
 	error = pci_enable_device (pdev);
 	if (error) {
 		printk (KERN_ERR
-			"(rcpci45 driver:) %d: unable to enable pci device, aborting\n",
+			"(rcpci45 driver:) %d: pci enable device error\n",
 			card_idx);
 		goto err_out;
 	}
 	error = -ENOMEM;
 	pci_start = pci_resource_start (pdev, 0);
 	pci_len = pci_resource_len (pdev, 0);
+	printk("pci_start %x pci_len %x\n", pci_start, pci_len);
 
 	pci_set_drvdata (pdev, dev);
 
@@ -200,29 +198,30 @@
 
 	if (!pci_start || !(pci_resource_flags (pdev, 0) & IORESOURCE_MEM)) {
 		printk (KERN_ERR
-			"(rcpci45 driver:) No PCI memory resources! Aborting.\n");
+			"(rcpci45 driver:) No PCI mem resources! Aborting\n");
 		error = -EBUSY;
 		goto err_out_free_dev;
 	}
 
 	/*
-	 * Save the starting address of the LAN API private area.  We'll
-	 * pass that to RCInitI2OMsgLayer().
+	 * pDpa->msgbuf is where the card will dma the I2O 
+	 * messages. Thus, we need contiguous physical pages of
+	 * memory.
 	 */
-	/* RAA FIXME: This size should be a #define somewhere after I
-	 * clear up some questions: What flags are neeeded in the alloc below
-	 * and what needs to be done before the memarea is long word aligned?
-	 * (Look in old code for an approach.) (Also note that the 16K below
-	 * is substantially less than the 32K allocated before (even though
-	 * some of the spacce was used for data structures.) */
-	pDpa->msgbuf = kmalloc (16384, GFP_KERNEL);
+	pDpa->msgbuf = kmalloc (MSG_BUF_SIZE, GFP_DMA|GFP_ATOMIC|GFP_KERNEL);
 	if (!pDpa->msgbuf) {
-		printk (KERN_ERR "(rcpci45 driver:) Could not allocate %d byte memory for the private msgbuf!\n", 16384);	/* RAA FIXME not hardcoded! */
+		printk (KERN_ERR "(rcpci45 driver:) \
+			Could not allocate %d byte memory for the \
+				private msgbuf!\n", MSG_BUF_SIZE);
 		goto err_out_free_dev;
 	}
-	pDpa->PLanApiPA = (void *) (((long) pDpa->msgbuf + 0xff) & ~0xff);
 
-	dprintk ("pDpa->PLanApiPA = 0x%x\n", (uint) pDpa->PLanApiPA);
+	/*
+	 * Save the starting address of the LAN API private area.  We'll
+	 * pass that to RCInitI2OMsgLayer().
+	 *
+	 */
+	pDpa->PLanApiPA = (void *) (((long) pDpa->msgbuf + 0xff) & ~0xff);
 
 	/* The adapter is accessible through memory-access read/write, not
 	 * I/O read/write.  Thus, we need to map it to some virtual address
@@ -235,17 +234,20 @@
 	vaddr = (ulong *) ioremap (pci_start, pci_len);
 	if (!vaddr) {
 		printk (KERN_ERR
-			"(rcpci45 driver:) Unable to remap address range from %lu to %lu\n",
+			"(rcpci45 driver:) \
+			Unable to remap address range from %lu to %lu\n",
 			pci_start, pci_start + pci_len);
 		goto err_out_free_region;
 	}
 
-	dprintk ("rcpci45_init_one: 0x%x, priv = 0x%x, vaddr = 0x%x\n",
-		 (uint) dev, (uint) dev->priv, (uint) vaddr);
 	dev->base_addr = (unsigned long) vaddr;
 	dev->irq = pdev->irq;
-
-	dev->init = &RCinit;
+	dev->open = &RCopen;
+	dev->hard_start_xmit = &RC_xmit_packet;
+	dev->stop = &RCclose;
+	dev->get_stats = &RCget_stats;
+	dev->do_ioctl = &RCioctl;
+	dev->set_config = &RCconfig;
 
 	return 0;		/* success */
 
@@ -258,7 +260,7 @@
 	kfree (dev);
 err_out:
 	card_idx--;
-	return error;
+	return -ENODEV;
 }
 
 static struct pci_driver rcpci45_driver = {
@@ -272,9 +274,8 @@
 rcpci_init_module (void)
 {
 	int rc = pci_module_init (&rcpci45_driver);
-
 	if (!rc)
-		printk (KERN_INFO "%s", version);
+		printk (KERN_ERR "%s", version);
 	return rc;
 }
 
@@ -287,56 +288,56 @@
 	int requested = 0;
 	int error;
 
-	dprintk ("(rcpci45 driver:) RCopen\n");
+	MOD_INC_USE_COUNT;
+	if (pDpa->nexus) {
+		/* This is not the first time RCopen is called.  Thus,
+		 * the interface was previously opened and later closed
+		 * by RCclose().  RCclose() does a Shutdown; to wake up
+		 * the adapter, a reset is mandatory before we can post
+		 * receive buffers.  However, if the adapter initiated 
+		 * a reboot while the interface was closed -- and interrupts
+		 * were turned off -- we need will need to reinitialize
+		 * the adapter, rather than simply waking it up.  
+		 */
+		printk (KERN_INFO "Waking up adapter...\n");
+		RCResetLANCard (dev, 0, 0, 0);
+	} else {
+		pDpa->nexus = 1;
+		/* 
+		 * RCInitI2OMsgLayer is done only once, unless the
+		 * adapter was sent a warm reboot
+		 */
+		error = RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback,
+					   (PFNRXCALLBACK) RCrecv_callback,
+					   (PFNCALLBACK) RCreboot_callback);
+		if (error) {
+			printk (KERN_ERR "%s: Unable to init msg layer (%x)\n",
+					dev->name, error);
+			goto err_out;
+		}
+		if ((error = RCGetMAC (dev, NULL))) {
+			printk (KERN_ERR "%s: Unable to get adapter MAC\n",
+					dev->name);
+			goto err_out;
+		}
+	}
 
 	/* Request a shared interrupt line. */
 	error = request_irq (dev->irq, RCinterrupt, SA_SHIRQ, dev->name, dev);
 	if (error) {
-		printk (KERN_ERR "(rcpci45 driver:) %s: unable to get IRQ %d\n",
-			dev->name, dev->irq);
+		printk (KERN_ERR "%s: unable to get IRQ %d\n", 
+				dev->name, dev->irq);
 		goto err_out;
 	}
 
-	error = RCInitI2OMsgLayer (dev, (PFNTXCALLBACK) RCxmit_callback,
-				   (PFNRXCALLBACK) RCrecv_callback,
-				   (PFNCALLBACK) RCreboot_callback);
-	if (error) {
-		printk (KERN_ERR
-			"(rcpci45 driver:) Unable to initialize msg layer\n");
-		goto err_out_free_irq;
-	}
-	if ((error = RCGetMAC (dev, NULL))) {
-		printk (KERN_ERR
-			"(rcpci45 driver:) Unable to get adapter MAC\n");
-		goto err_out_free_irq;
-	}
-
 	DriverControlWord |= WARM_REBOOT_CAPABLE;
 	RCReportDriverCapability (dev, DriverControlWord);
 
 	printk (KERN_INFO "%s: RedCreek Communications IPSEC VPN adapter\n",
 		dev->name);
 
-	/* RAA: Old RCopen starts here */
 	RCEnableI2OInterrupts (dev);
 
-	/* RAA Hmm, how does the comment below jibe with the newly imported
-	 * code above? A FIXME!!*/
-	if (pDpa->nexus) {
-		/* This is not the first time RCopen is called.  Thus,
-		 * the interface was previously opened and later closed
-		 * by RCclose().  RCclose() does a Shutdown; to wake up
-		 * the adapter, a reset is mandatory before we can post
-		 * receive buffers.  However, if the adapter initiated 
-		 * a reboot while the interface was closed -- and interrupts
-		 * were turned off -- we need will need to reinitialize
-		 * the adapter, rather than simply waking it up.  
-		 */
-		dprintk (KERN_INFO "Waking up adapter...\n");
-		RCResetLANCard (dev, 0, 0, 0);
-	} else
-		pDpa->nexus = 1;
-
 	while (post_buffers) {
 		if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
 			requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
@@ -346,29 +347,30 @@
 
 		if (count < requested) {
 			/*
-			 * Check to see if we were able to post any buffers at all.
+			 * Check to see if we were able to post 
+			 * any buffers at all.
 			 */
 			if (post_buffers == MAX_NMBR_RCV_BUFFERS) {
-				printk (KERN_ERR
-					"(rcpci45 driver:) Error RCopen: not able to allocate any buffers\r\n");
-				return (-ENOMEM);
+				printk (KERN_ERR "%s: \
+					unable to allocate any buffers\n", 
+						dev->name);
+				goto err_out_free_irq;
 			}
-			printk (KERN_WARNING
-				"(rcpci45 driver:) Warning RCopen: not able to allocate all requested buffers\r\n");
+			printk (KERN_WARNING "%s: \
+			unable to allocate all requested buffers\n", dev->name);
 			break;	/* we'll try to post more buffers later */
 		} else
 			post_buffers -= count;
 	}
 	pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;
 	pDpa->shutdown = 0;	/* just in case */
-	dprintk ("RCopen: posted %d buffers\n", (uint) pDpa->numOutRcvBuffers);
-	MOD_INC_USE_COUNT;
 	netif_start_queue (dev);
 	return 0;
 
 err_out_free_irq:
 	free_irq (dev->irq, dev);
 err_out:
+	MOD_DEC_USE_COUNT;
 	return error;
 }
 
@@ -384,15 +386,16 @@
 	netif_stop_queue (dev);
 
 	if (pDpa->shutdown || pDpa->reboot) {
-		dprintk ("RC_xmit_packet: tbusy!\n");
+		printk ("RC_xmit_packet: tbusy!\n");
 		return 1;
 	}
 
 	/*
-	 * The user is free to reuse the TCB after RCI2OSendPacket() returns, since
-	 * the function copies the necessary info into its own private space.  Thus,
-	 * our TCB can be a local structure.  The skb, on the other hand, will be
-	 * freed up in our interrupt handler.
+	 * The user is free to reuse the TCB after RCI2OSendPacket() 
+	 * returns, since the function copies the necessary info into its 
+	 * own private space.  Thus, our TCB can be a local structure.  
+	 * The skb, on the other hand, will be freed up in our interrupt 
+	 * handler.
 	 */
 
 	ptcb->bcount = 1;
@@ -406,11 +409,9 @@
 	ptcb->b.size = skb->len;
 	ptcb->b.addr = virt_to_bus ((void *) skb->data);
 
-	dprintk ("RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n",
-		 (uint) skb, (uint) pDpa, (uint) pDpa->id, (uint) ptcb);
 	if ((status = RCI2OSendPacket (dev, (U32) NULL, (PRCTCB) ptcb))
 	    != RC_RTN_NO_ERROR) {
-		dprintk ("RC send error 0x%x\n", (uint) status);
+		printk ("%s: send error 0x%x\n", dev->name, (uint) status);
 		return 1;
 	} else {
 		dev->trans_start = jiffies;
@@ -440,23 +441,20 @@
 	PDPA pDpa = dev->priv;
 
 	if (!pDpa) {
-		printk (KERN_ERR
-			"(rcpci45 driver:) Fatal error: xmit callback, !pDpa\n");
+		printk (KERN_ERR "%s: Fatal Error in xmit callback, !pDpa\n",
+				dev->name);
 		return;
 	}
 
-/*      dprintk("xmit_callback: Status = 0x%x\n", (uint)Status); */
 	if (Status != I2O_REPLY_STATUS_SUCCESS)
-		dprintk ("xmit_callback: Status = 0x%x\n", (uint) Status);
+		printk (KERN_INFO "%s: xmit_callback: Status = 0x%x\n", 
+				dev->name, (uint) Status);
 	if (pDpa->shutdown || pDpa->reboot)
-		dprintk ("xmit callback: shutdown||reboot\n");
-
-	dprintk ("xmit_callback: PcktCount = %d, BC = 0x%x\n",
-		 (uint) PcktCount, (uint) BufferContext);
+		printk (KERN_INFO "%s: xmit callback: shutdown||reboot\n",
+				dev->name);
 
 	while (PcktCount--) {
 		skb = (struct sk_buff *) (BufferContext[0]);
-		dprintk ("skb = 0x%x\n", (uint) skb);
 		BufferContext++;
 		dev_kfree_skb_irq (skb);
 	}
@@ -468,19 +466,18 @@
 {
 	PDPA pDpa = dev->priv;
 
-	dprintk ("RCreset_callback Status 0x%x\n", (uint) Status);
+	printk ("RCreset_callback Status 0x%x\n", (uint) Status);
 	/*
 	 * Check to see why we were called.
 	 */
 	if (pDpa->shutdown) {
-		printk (KERN_INFO
-			"(rcpci45 driver:) Shutting down interface\n");
+		printk (KERN_INFO "%s: shutting down interface\n",
+				dev->name);
 		pDpa->shutdown = 0;
 		pDpa->reboot = 0;
-		MOD_DEC_USE_COUNT;
 	} else if (pDpa->reboot) {
-		printk (KERN_INFO
-			"(rcpci45 driver:) reboot, shutdown adapter\n");
+		printk (KERN_INFO "%s: reboot, shutdown adapter\n",
+				dev->name);
 		/*
 		 * We don't set any of the flags in RCShutdownLANCard()
 		 * and we don't pass a callback routine to it.
@@ -489,7 +486,7 @@
 		 */
 		RCDisableI2OInterrupts (dev);
 		RCShutdownLANCard (dev, 0, 0, 0);
-		printk (KERN_INFO "(rcpci45 driver:) scheduling timer...\n");
+		printk (KERN_INFO "%s: scheduling timer...\n", dev->name);
 		init_timer (&pDpa->timer);
 		pDpa->timer.expires = RUN_AT ((40 * HZ) / 10);	/* 4 sec. */
 		pDpa->timer.data = (unsigned long) dev;
@@ -503,12 +500,12 @@
 {
 	PDPA pDpa = dev->priv;
 
-	dprintk ("RCreboot: rcv buffers outstanding = %d\n",
-		 (uint) pDpa->numOutRcvBuffers);
+	printk (KERN_INFO "%s: reboot: rcv buffers outstanding = %d\n",
+		 dev->name, (uint) pDpa->numOutRcvBuffers);
 
 	if (pDpa->shutdown) {
-		printk (KERN_INFO
-			"(rcpci45 driver:) skipping reboot sequence -- shutdown already initiated\n");
+		printk (KERN_INFO "%s: skip reboot, shutdown initiated\n",
+				dev->name);
 		return;
 	}
 	pDpa->reboot = 1;
@@ -560,12 +557,9 @@
 
 	ptcb->bcount = 1;
 
-	dprintk ("RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
-		 (uint) PktCount, (uint) BucketsRemain, (uint) PacketDescBlock);
-
 	if ((pDpa->shutdown || pDpa->reboot) && !Status)
-		dprintk ("shutdown||reboot && !Status: PktCount = %d\n",
-			 PktCount);
+		printk (KERN_INFO "%s: shutdown||reboot && !Status (%d)\n",
+				dev->name, PktCount);
 
 	if ((Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown) {
 		/*
@@ -574,76 +568,38 @@
 		 */
 
 		if (!pDpa->shutdown && !pDpa->reboot)
-			printk (KERN_INFO
-				"(rcpci45 driver:) RCrecv error: status = 0x%x\n",
-				(uint) Status);
+			printk (KERN_INFO "%s: recv error status = 0x%x\n",
+					dev->name, (uint) Status);
 		else
-			dprintk ("Returning %d buffers, status = 0x%x\n",
-				 PktCount, (uint) Status);
+			printk (KERN_DEBUG "%s: Returning %d buffs stat 0x%x\n",
+					dev->name, PktCount, (uint) Status);
 		/*
-		 * TO DO: check the nature of the failure and put the adapter in
-		 * failed mode if it's a hard failure.  Send a reset to the adapter
-		 * and free all outstanding memory.
+		 * TO DO: check the nature of the failure and put the 
+		 * adapter in failed mode if it's a hard failure.  
+		 * Send a reset to the adapter and free all outstanding memory.
 		 */
-		if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
-			dprintk ("RCrecv status ABORT NO DATA TRANSFER\n");
-
-		/* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */
 		if (PacketDescBlock) {
 			while (PktCount--) {
 				skb = (struct sk_buff *) PacketDescBlock[0];
-				dprintk ("free skb 0x%p\n", skb);
 				dev_kfree_skb (skb);
 				pDpa->numOutRcvBuffers--;
-				PacketDescBlock += BD_SIZE;	/* point to next context field */
+				/* point to next context field */
+				PacketDescBlock += BD_SIZE;
 			}
 		}
 		return;
 	} else {
 		while (PktCount--) {
 			skb = (struct sk_buff *) PacketDescBlock[0];
-			if (pDpa->shutdown)
-				dprintk ("shutdown: skb=0x%x\n", (uint) skb);
-
-			dprintk ("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
-				 (uint) skb, (uint) skb->data[0],
-				 (uint) skb->data[1], (uint) skb->data[2],
-				 (uint) skb->data[3], (uint) skb->data[4],
-				 (uint) skb->data[5]);
-
-#ifdef PROMISCUOUS_BY_DEFAULT	/* early 2.x firmware */
-			if ((memcmp (dev->dev_addr, skb->data, 6)) &&
-			    (!broadcast_packet (skb->data))) {
-				/*
-				 * Re-post the buffer to the adapter.  Since the adapter usually
-				 * return 1 to 2 receive buffers at a time, it's not too inefficient
-				 * post one buffer at a time but ... may be that should be 
-				 * optimized at some point.
-				 */
-				ptcb->b.context = (U32) skb;
-				ptcb->b.scount = 1;
-				ptcb->b.size = MAX_ETHER_SIZE;
-				ptcb->b.addr = virt_to_bus ((void *) skb->data);
-
-				if (RCPostRecvBuffers (dev, (PRCTCB) ptcb) !=
-				    RC_RTN_NO_ERROR) {
-					printk (KERN_WARNING
-						"(rcpci45 driver:) RCrecv_callback: post buffer failed!\n");
-					dev_kfree_skb (skb);
-				} else
-					pDpa->numOutRcvBuffers++;
-			} else
-#endif				/* PROMISCUOUS_BY_DEFAULT */
-			{
-				len = PacketDescBlock[2];
-				skb->dev = dev;
-				skb_put (skb, len);	/* adjust length and tail */
-				skb->protocol = eth_type_trans (skb, dev);
-				netif_rx (skb);	/* send the packet to the kernel */
-				dev->last_rx = jiffies;
-			}
-			pDpa->numOutRcvBuffers--;
-			PacketDescBlock += BD_SIZE;	/* point to next context field */
+			len = PacketDescBlock[2];
+			skb->dev = dev;
+			skb_put (skb, len);	/* adjust length and tail */
+			skb->protocol = eth_type_trans (skb, dev);
+			netif_rx (skb);	/* send the packet to the kernel */
+			dev->last_rx = jiffies;
+			pDpa->numOutRcvBuffers--;	
+			/* point to next context field */
+			PacketDescBlock += BD_SIZE;
 		}
 	}
 
@@ -680,11 +636,8 @@
 	pDpa = dev->priv;
 
 	if (pDpa->shutdown)
-		dprintk ("shutdown: service irq\n");
-
-	dprintk ("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n",
-		 (uint) pDpa, (uint) dev, (uint) pDpa->id);
-	dprintk ("dev = 0x%x\n", (uint) dev);
+		printk (KERN_DEBUG "%s: shutdown, service irq\n",
+				dev->name);
 
 	RCProcI2OMsgQ (dev);
 }
@@ -715,62 +668,60 @@
 			RCReportDriverCapability (dev, DriverControlWord);
 			RCEnableI2OInterrupts (dev);
 
-			if (dev->flags & IFF_UP) {
-				while (post_buffers) {
-					if (post_buffers >
-					    MAX_NMBR_POST_BUFFERS_PER_MSG)
-						requested =
-						    MAX_NMBR_POST_BUFFERS_PER_MSG;
-					else
-						requested = post_buffers;
-					count =
-					    RC_allocate_and_post_buffers (dev,
-									  requested);
-					post_buffers -= count;
-					if (count < requested)
-						break;
-				}
-				pDpa->numOutRcvBuffers =
-				    MAX_NMBR_RCV_BUFFERS - post_buffers;
-				dprintk ("rc: posted %d buffers \r\n",
-					 (uint) pDpa->numOutRcvBuffers);
+
+			if (!(dev->flags & IFF_UP)) {
+				retry = 0;
+				return;
+			}
+			while (post_buffers) {
+				if (post_buffers > 
+						MAX_NMBR_POST_BUFFERS_PER_MSG)
+					requested = 
+						MAX_NMBR_POST_BUFFERS_PER_MSG;
+				else
+					requested = post_buffers;
+				count =
+				    RC_allocate_and_post_buffers (dev,
+								  requested);
+				post_buffers -= count;
+				if (count < requested)
+					break;
 			}
-			dprintk ("Initialization done.\n");
+			pDpa->numOutRcvBuffers =
+			    MAX_NMBR_RCV_BUFFERS - post_buffers;
+			printk ("Initialization done.\n");
 			netif_wake_queue (dev);
 			retry = 0;
 			return;
 		case RC_RTN_FREE_Q_EMPTY:
 			retry++;
-			printk (KERN_WARNING
-				"(rcpci45 driver:) inbound free q empty\n");
+			printk (KERN_WARNING "%s inbound free q empty\n",
+					dev->name);
 			break;
 		default:
 			retry++;
-			printk (KERN_WARNING
-				"(rcpci45 driver:) bad status after reboot: %d\n",
-				init_status);
+			printk (KERN_WARNING "%s bad stat after reboot: %d\n",
+					dev->name, init_status);
 			break;
 		}
 
 		if (retry > REBOOT_REINIT_RETRY_LIMIT) {
-			printk (KERN_WARNING
-				"(rcpci45 driver:) unable to reinitialize adapter after reboot\n");
-			printk (KERN_WARNING
-				"(rcpci45 driver:) decrementing driver and closing interface\n");
+			printk (KERN_WARNING "%s unable to reinitialize adapter after reboot\n", dev->name);
+			printk (KERN_WARNING "%s decrementing driver and closing interface\n", dev->name);
 			RCDisableI2OInterrupts (dev);
 			dev->flags &= ~IFF_UP;
 			MOD_DEC_USE_COUNT;
 		} else {
-			printk (KERN_INFO
-				"(rcpci45 driver:) rescheduling timer...\n");
+			printk (KERN_INFO "%s: rescheduling timer...\n",
+					dev->name);
 			init_timer (&pDpa->timer);
-			pDpa->timer.expires = RUN_AT ((40 * HZ) / 10);	/* 3 sec. */
+			pDpa->timer.expires = RUN_AT ((40 * HZ) / 10);
 			pDpa->timer.data = (unsigned long) dev;
-			pDpa->timer.function = &rc_timer;	/* timer handler */
+			pDpa->timer.function = &rc_timer;
 			add_timer (&pDpa->timer);
 		}
 	} else
-		printk (KERN_WARNING "(rcpci45 driver:) timer??\n");
+		printk (KERN_WARNING "%s: unexpected timer irq\n", dev->name);
 }
 
 static int
@@ -778,19 +729,16 @@
 {
 	PDPA pDpa = dev->priv;
 
+	printk("RCclose\n");
 	netif_stop_queue (dev);
 
-	dprintk ("RCclose\r\n");
-
 	if (pDpa->reboot) {
-		printk (KERN_INFO
-			"(rcpci45 driver:) skipping reset -- adapter already in reboot mode\n");
+		printk (KERN_INFO "%s skipping reset -- adapter already in reboot mode\n", dev->name);
 		dev->flags &= ~IFF_UP;
 		pDpa->shutdown = 1;
+		MOD_DEC_USE_COUNT;
 		return 0;
 	}
-	dprintk ("receive buffers outstanding: %d\n",
-		 (uint) pDpa->numOutRcvBuffers);
 
 	pDpa->shutdown = 1;
 
@@ -806,6 +754,7 @@
 			   (PFNCALLBACK) RCreset_callback);
 
 	dev->flags &= ~IFF_UP;
+	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -817,56 +766,42 @@
 	PDPA pDpa = dev->priv;
 
 	if (!pDpa) {
-		dprintk ("RCget_stats: !pDpa\n");
 		return 0;
 	} else if (!(dev->flags & IFF_UP)) {
-		dprintk ("RCget_stats: device down\n");
 		return 0;
 	}
 
 	memset (&RCstats, 0, sizeof (RCLINKSTATS));
 	if ((RCGetLinkStatistics (dev, &RCstats, (void *) 0)) ==
 	    RC_RTN_NO_ERROR) {
-		dprintk ("TX_good 0x%x\n", (uint) RCstats.TX_good);
-		dprintk ("TX_maxcol 0x%x\n", (uint) RCstats.TX_maxcol);
-		dprintk ("TX_latecol 0x%x\n", (uint) RCstats.TX_latecol);
-		dprintk ("TX_urun 0x%x\n", (uint) RCstats.TX_urun);
-		dprintk ("TX_crs 0x%x\n", (uint) RCstats.TX_crs);
-		dprintk ("TX_def 0x%x\n", (uint) RCstats.TX_def);
-		dprintk ("TX_singlecol 0x%x\n", (uint) RCstats.TX_singlecol);
-		dprintk ("TX_multcol 0x%x\n", (uint) RCstats.TX_multcol);
-		dprintk ("TX_totcol 0x%x\n", (uint) RCstats.TX_totcol);
-
-		dprintk ("Rcv_good 0x%x\n", (uint) RCstats.Rcv_good);
-		dprintk ("Rcv_CRCerr 0x%x\n", (uint) RCstats.Rcv_CRCerr);
-		dprintk ("Rcv_alignerr 0x%x\n", (uint) RCstats.Rcv_alignerr);
-		dprintk ("Rcv_reserr 0x%x\n", (uint) RCstats.Rcv_reserr);
-		dprintk ("Rcv_orun 0x%x\n", (uint) RCstats.Rcv_orun);
-		dprintk ("Rcv_cdt 0x%x\n", (uint) RCstats.Rcv_cdt);
-		dprintk ("Rcv_runt 0x%x\n", (uint) RCstats.Rcv_runt);
-
-		pDpa->stats.rx_packets = RCstats.Rcv_good;	/* total packets received    */
-		pDpa->stats.tx_packets = RCstats.TX_good;	/* total packets transmitted    */
 
-		pDpa->stats.rx_errors = RCstats.Rcv_CRCerr + RCstats.Rcv_alignerr + RCstats.Rcv_reserr + RCstats.Rcv_orun + RCstats.Rcv_cdt + RCstats.Rcv_runt;	/* bad packets received        */
+		/* total packets received    */
+		pDpa->stats.rx_packets = RCstats.Rcv_good
+		/* total packets transmitted    */;
+		pDpa->stats.tx_packets = RCstats.TX_good;
+
+		pDpa->stats.rx_errors = RCstats.Rcv_CRCerr + 
+			RCstats.Rcv_alignerr + RCstats.Rcv_reserr + 
+			RCstats.Rcv_orun + RCstats.Rcv_cdt + RCstats.Rcv_runt;
 
-		pDpa->stats.tx_errors = RCstats.TX_urun + RCstats.TX_crs + RCstats.TX_def + RCstats.TX_totcol;	/* packet transmit problems    */
+		pDpa->stats.tx_errors = RCstats.TX_urun + RCstats.TX_crs + 
+			RCstats.TX_def + RCstats.TX_totcol;
 
 		/*
 		 * This needs improvement.
 		 */
-		pDpa->stats.rx_dropped = 0;	/* no space in linux buffers    */
-		pDpa->stats.tx_dropped = 0;	/* no space available in linux    */
-		pDpa->stats.multicast = 0;	/* multicast packets received    */
+		pDpa->stats.rx_dropped = 0; /* no space in linux buffers   */
+		pDpa->stats.tx_dropped = 0; /* no space available in linux */
+		pDpa->stats.multicast = 0;  /* multicast packets received  */
 		pDpa->stats.collisions = RCstats.TX_totcol;
 
 		/* detailed rx_errors: */
 		pDpa->stats.rx_length_errors = 0;
-		pDpa->stats.rx_over_errors = RCstats.Rcv_orun;	/* receiver ring buff overflow    */
-		pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr;	/* recved pkt with crc error    */
-		pDpa->stats.rx_frame_errors = 0;	/* recv'd frame alignment error */
-		pDpa->stats.rx_fifo_errors = 0;	/* recv'r fifo overrun        */
-		pDpa->stats.rx_missed_errors = 0;	/* receiver missed packet    */
+		pDpa->stats.rx_over_errors = RCstats.Rcv_orun;
+		pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr;
+		pDpa->stats.rx_frame_errors = 0;
+		pDpa->stats.rx_fifo_errors = 0;	
+		pDpa->stats.rx_missed_errors = 0;
 
 		/* detailed tx_errors */
 		pDpa->stats.tx_aborted_errors = 0;
@@ -886,8 +821,6 @@
 	RCuser_struct RCuser;
 	PDPA pDpa = dev->priv;
 
-	dprintk ("RCioctl: cmd = 0x%x\n", cmd);
-
 	if (!capable (CAP_NET_ADMIN))
 		return -EPERM;
 
@@ -911,16 +844,12 @@
 
 			switch (RCuser.cmd) {
 			case RCUC_GETFWVER:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETFWVER\n");
 				RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
 				RCGetFirmwareVer (dev,
 						  (PU8) & RCUD_GETFWVER->
 						  FirmString, NULL);
 				break;
 			case RCUC_GETINFO:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETINFO\n");
 				RCUD_GETINFO = &RCuser.RCUS_GETINFO;
 				RCUD_GETINFO->mem_start = dev->base_addr;
 				RCUD_GETINFO->mem_end =
@@ -929,8 +858,6 @@
 				RCUD_GETINFO->irq = dev->irq;
 				break;
 			case RCUC_GETIPANDMASK:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETIPANDMASK\n");
 				RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
 				RCGetRavlinIPandMask (dev,
 						      (PU32) &
@@ -940,8 +867,6 @@
 						      NetMask, NULL);
 				break;
 			case RCUC_GETLINKSTATISTICS:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETLINKSTATISTICS\n");
 				RCUD_GETLINKSTATISTICS =
 				    &RCuser.RCUS_GETLINKSTATISTICS;
 				RCGetLinkStatistics (dev,
@@ -950,75 +875,39 @@
 						     StatsReturn, NULL);
 				break;
 			case RCUC_GETLINKSTATUS:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETLINKSTATUS\n");
 				RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
 				RCGetLinkStatus (dev,
 						 (PU32) & RCUD_GETLINKSTATUS->
 						 ReturnStatus, NULL);
 				break;
 			case RCUC_GETMAC:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETMAC\n");
 				RCUD_GETMAC = &RCuser.RCUS_GETMAC;
 				RCGetMAC (dev, NULL);
+				memcpy(RCUD_GETMAC, dev->dev_addr, 8);
 				break;
 			case RCUC_GETPROM:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETPROM\n");
 				RCUD_GETPROM = &RCuser.RCUS_GETPROM;
 				RCGetPromiscuousMode (dev,
 						      (PU32) & RCUD_GETPROM->
 						      PromMode, NULL);
 				break;
 			case RCUC_GETBROADCAST:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETBROADCAST\n");
 				RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;
 				RCGetBroadcastMode (dev,
 						    (PU32) & RCUD_GETBROADCAST->
 						    BroadcastMode, NULL);
 				break;
 			case RCUC_GETSPEED:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC GETSPEED\n");
 				if (!(dev->flags & IFF_UP)) {
-					printk (KERN_ERR
-						"(rcpci45 driver:) RCioctl, GETSPEED error: interface down\n");
 					return -ENODATA;
 				}
 				RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
 				RCGetLinkSpeed (dev,
 						(PU32) & RCUD_GETSPEED->
 						LinkSpeedCode, NULL);
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC speed = 0x%u\n",
-					RCUD_GETSPEED->LinkSpeedCode);
 				break;
 			case RCUC_SETIPANDMASK:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC SETIPANDMASK\n");
 				RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC New IP Addr = %d.%d.%d.%d, ",
-					(U8) ((RCUD_SETIPANDMASK->
-					       IpAddr) & 0xff),
-					(U8) ((RCUD_SETIPANDMASK->
-					       IpAddr >> 8) & 0xff),
-					(U8) ((RCUD_SETIPANDMASK->
-					       IpAddr >> 16) & 0xff),
-					(U8) ((RCUD_SETIPANDMASK->
-					       IpAddr >> 24) & 0xff));
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC New Mask = %d.%d.%d.%d\n",
-					(U8) ((RCUD_SETIPANDMASK->
-					       NetMask) & 0xff),
-					(U8) ((RCUD_SETIPANDMASK->
-					       NetMask >> 8) & 0xff),
-					(U8) ((RCUD_SETIPANDMASK->
-					       NetMask >> 16) & 0xff),
-					(U8) ((RCUD_SETIPANDMASK->
-					       NetMask >> 24) & 0xff));
 				RCSetRavlinIPandMask (dev,
 						      (U32) RCUD_SETIPANDMASK->
 						      IpAddr,
@@ -1026,61 +915,33 @@
 						      NetMask);
 				break;
 			case RCUC_SETMAC:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC SETMAC\n");
-				RCUD_SETMAC = &RCuser.RCUS_SETMAC;
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-					(U8) (RCUD_SETMAC->mac[0]),
-					(U8) (RCUD_SETMAC->mac[1]),
-					(U8) (RCUD_SETMAC->mac[2]),
-					(U8) (RCUD_SETMAC->mac[3]),
-					(U8) (RCUD_SETMAC->mac[4]),
-					(U8) (RCUD_SETMAC->mac[5]));
 				RCSetMAC (dev, (PU8) & RCUD_SETMAC->mac);
 				break;
 			case RCUC_SETSPEED:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC SETSPEED\n");
 				RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;
 				RCSetLinkSpeed (dev,
 						(U16) RCUD_SETSPEED->
 						LinkSpeedCode);
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC New speed = 0x%x\n",
-					RCUD_SETSPEED->LinkSpeedCode);
 				break;
 			case RCUC_SETPROM:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC SETPROM\n");
 				RCUD_SETPROM = &RCuser.RCUS_SETPROM;
 				RCSetPromiscuousMode (dev,
 						      (U16) RCUD_SETPROM->
 						      PromMode);
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC New prom mode = 0x%x\n",
-					RCUD_SETPROM->PromMode);
 				break;
 			case RCUC_SETBROADCAST:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC SETBROADCAST\n");
 				RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;
 				RCSetBroadcastMode (dev,
 						    (U16) RCUD_SETBROADCAST->
 						    BroadcastMode);
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC New broadcast mode = 0x%x\n",
-					RCUD_SETBROADCAST->BroadcastMode);
 				break;
 			default:
-				printk (KERN_INFO
-					"(rcpci45 driver:) RC command default\n");
 				RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
 				RCUD_DEFAULT->rc = 0x11223344;
 				break;
 			}
-			if (copy_to_user
-			    (rq->ifr_data, &RCuser, sizeof (RCuser)))
+			if (copy_to_user (rq->ifr_data, &RCuser, 
+						sizeof (RCuser)))
 				return -EFAULT;
 			break;
 		}		/* RCU_COMMAND */
@@ -1098,15 +959,14 @@
 	/*
 	 * To be completed ...
 	 */
-	dprintk ("RCconfig\n");
 	return 0;
 	if (dev->flags & IFF_UP)	/* can't act on a running interface */
 		return -EBUSY;
 
 	/* Don't allow changing the I/O address */
 	if (map->base_addr != dev->base_addr) {
-		printk (KERN_WARNING
-			"(rcpci45 driver:)  Change I/O address not implemented\n");
+		printk (KERN_WARNING "%s Change I/O address not implemented\n",
+				dev->name);
 		return -EOPNOTSUPP;
 	}
 	return 0;
@@ -1135,44 +995,36 @@
 	if (!numBuffers)
 		return 0;
 	else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG) {
-		dprintk ("Too many buffers requested!\n");
-		dprintk ("attempting to allocate only 32 buffers\n");
+		printk (KERN_ERR "%s: Too many buffers requested!\n",
+				dev->name);
 		numBuffers = 32;
 	}
 
 	p = (PU32) kmalloc (sizeof (U32) + numBuffers * sizeof (singleB),
-			    GFP_KERNEL);
-
-	dprintk ("TCB = 0x%x\n", (uint) p);
+			    GFP_DMA|GFP_ATOMIC|GFP_KERNEL);
 
 	if (!p) {
-		printk (KERN_WARNING
-			"(rcpci45 driver:) RCopen: unable to allocate TCB\n");
+		printk (KERN_WARNING "%s unable to allocate TCB\n",
+				dev->name);
 		return 0;
 	}
 
 	p[0] = 0;		/* Buffer Count */
-	pB = (psingleB) ((U32) p + sizeof (U32));	/* point to the first buffer */
-
-	dprintk ("p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint) p[0], (uint) p,
-		 (uint) pB);
-	dprintk ("pB = 0x%x\n", (uint) pB);
+	pB = (psingleB) ((U32) p + sizeof (U32));/* point to the first buffer */
 
 	for (i = 0; i < numBuffers; i++) {
 		skb = dev_alloc_skb (MAX_ETHER_SIZE + 2);
 		if (!skb) {
-			dprintk
-			    ("Doh! RCopen: unable to allocate enough skbs!\n");
-			if (*p != 0) {	/* did we allocate any buffers at all? */
-				dprintk ("will post only %d buffers \n",
-					 (uint) (*p));
+			printk (KERN_WARNING 
+					"%s: unable to allocate enough skbs!\n",
+					dev->name);
+			if (*p != 0) {	/* did we allocate any buffers */
 				break;
 			} else {
 				kfree (p);	/* Free the TCB */
 				return 0;
 			}
 		}
-		dprintk ("post 0x%x\n", (uint) skb);
 		skb_reserve (skb, 2);	/* Align IP on 16 byte boundaries */
 		pB->context = (U32) skb;
 		pB->scount = 1;	/* segment count */
@@ -1183,18 +1035,16 @@
 	}
 
 	if ((status = RCPostRecvBuffers (dev, (PRCTCB) p)) != RC_RTN_NO_ERROR) {
-		printk (KERN_WARNING
-			"(rcpci45 driver:) Post buffer failed with error code 0x%x!\n",
-			status);
-		pB = (psingleB) ((U32) p + sizeof (U32));	/* point to the first buffer */
+		printk (KERN_WARNING "%s: Post buffer failed, error 0x%x\n",
+				dev->name, status);
+		/* point to the first buffer */
+		pB = (psingleB) ((U32) p + sizeof (U32));
 		while (p[0]) {
 			skb = (struct sk_buff *) pB->context;
-			dprintk ("freeing 0x%x\n", (uint) skb);
 			dev_kfree_skb (skb);
 			p[0]--;
 			pB++;
 		}
-		dprintk ("freed all buffers, p[0] = %d\n", (uint) p[0]);
 	}
 	res = p[0];
 	kfree (p);
diff -urN linux-2.4.18-pre3/drivers/net/sis900.c linux/drivers/net/sis900.c
--- linux-2.4.18-pre3/drivers/net/sis900.c	Tue Jan 15 15:10:09 2002
+++ linux/drivers/net/sis900.c	Tue Jan 15 15:10:16 2002
@@ -1783,6 +1783,40 @@
 }
 
 /**
+ *	netdev_ethtool_ioctl: - For the basic support of ethtool
+ *	@net_dev: the net device to command for
+ *	@useraddr: start address of interface request
+ *
+ *	Process ethtool command such as "ehtool -i" to show information
+ */
+
+static int netdev_ethtool_ioctl (struct net_device *net_dev, void *useraddr)
+{
+ 	struct sis900_private *sis_priv = net_dev->priv;
+ 	u32 ethcmd;
+
+	if (copy_from_user (&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+	
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO:
+		{
+			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+			strcpy (info.driver, SIS900_MODULE_NAME);
+			strcpy (info.version, SIS900_DRV_VERSION);
+			strcpy (info.bus_info, sis_priv->pci_dev->slot_name);
+			if (copy_to_user (useraddr, &info, sizeof (info)))
+				return -EFAULT;
+			return 0;
+		}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+/**
  *	mii_ioctl: - process MII i/o control command 
  *	@net_dev: the net device to command for
  *	@rq: parameter for command
@@ -1797,6 +1831,9 @@
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 
 	switch(cmd) {
+	case SIOCETHTOOL:
+		return netdev_ethtool_ioctl(net_dev, (void *) rq->ifr_data);
+
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 	case SIOCDEVPRIVATE:		/* for binary compat, remove in 2.5 */
 		data->phy_id = sis_priv->mii->phy_addr;
diff -urN linux-2.4.18-pre3/drivers/net/sungem.c linux/drivers/net/sungem.c
--- linux-2.4.18-pre3/drivers/net/sungem.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/sungem.c	Tue Jan 15 15:10:16 2002
@@ -1,4 +1,4 @@
-/* $Id: sungem.c,v 1.43 2001/12/05 08:40:54 davem Exp $
+/* $Id: sungem.c,v 1.44 2001/12/08 04:06:27 davem Exp $
  * sungem.c: Sun GEM ethernet driver.
  *
  * Copyright (C) 2000, 2001 David S. Miller (davem@redhat.com)
diff -urN linux-2.4.18-pre3/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- linux-2.4.18-pre3/drivers/net/sunqe.c	Sun Oct 21 10:36:54 2001
+++ linux/drivers/net/sunqe.c	Tue Jan 15 15:10:16 2002
@@ -1,4 +1,4 @@
-/* $Id: sunqe.c,v 1.52 2001/10/18 08:18:08 davem Exp $
+/* $Id: sunqe.c,v 1.52.2.1 2001/12/21 00:52:47 davem Exp $
  * sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
  *          Once again I am out to prove that every ethernet
  *          controller out there can be most efficiently programmed
@@ -494,6 +494,7 @@
 				spin_unlock(&qep->lock);
 			}
 	next:
+			;
 		}
 		qec_status >>= 4;
 		channel++;
diff -urN linux-2.4.18-pre3/drivers/net/tulip/ChangeLog linux/drivers/net/tulip/ChangeLog
--- linux-2.4.18-pre3/drivers/net/tulip/ChangeLog	Mon Nov 19 15:19:42 2001
+++ linux/drivers/net/tulip/ChangeLog	Tue Jan 15 15:10:16 2002
@@ -1,3 +1,17 @@
+2001-12-19  John Zielinski
+
+	* tulip_core.c (tulip_up, tulip_init_one):
+	More places to revert PHY autoconfiguration bit removal.
+
+2001-12-18  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip.h: revert PHY autoconfiguration bit removal
+
+2001-12-16  Andrew Lambeth  <wal@vmware.com>
+
+	* tulip_core.c (tulip_start_xmit): Use the more-portable
+	spin_lock_irqsave.
+
 2001-11-13  David S. Miller  <davem@redhat.com>
 
 	* tulip_core.c (tulip_mwi_config): Kill unused label early_out.
diff -urN linux-2.4.18-pre3/drivers/net/tulip/tulip.h linux/drivers/net/tulip/tulip.h
--- linux-2.4.18-pre3/drivers/net/tulip/tulip.h	Fri Nov  9 13:45:35 2001
+++ linux/drivers/net/tulip/tulip.h	Tue Jan 15 15:10:16 2002
@@ -197,8 +197,8 @@
 	csr13_cac = (1<<2), /* CSR13/14/15 autoconfiguration */
 	csr13_srl = (1<<0), /* When reset, resets all SIA functions, machines */
 
-	csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_srl),
-	csr13_mask_10bt = (csr13_eng | csr13_srl),
+	csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_srl | csr13_cac),
+	csr13_mask_10bt = (csr13_eng | csr13_srl | csr13_cac),
 };
 
 enum t21143_csr6_bits {
diff -urN linux-2.4.18-pre3/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- linux-2.4.18-pre3/drivers/net/tulip/tulip_core.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/tulip/tulip_core.c	Tue Jan 15 15:10:16 2002
@@ -399,7 +399,7 @@
 		if (tp->sym_advertise & 0x0040)
 			tp->csr6 |= FullDuplex;
 		outl(tp->csr6, ioaddr + CSR6);
-		outl(0x0000EF01, ioaddr + CSR13);
+		outl(0x0000EF05, ioaddr + CSR13);
 
 	} else if (tp->chip_id == DC21142) {
 		if (tp->mii_cnt) {
@@ -701,8 +701,9 @@
 	int entry;
 	u32 flag;
 	dma_addr_t mapping;
+	unsigned long eflags;
 
-	spin_lock_irq(&tp->lock);
+	spin_lock_irqsave(&tp->lock, eflags);
 
 	/* Calculate the next Tx descriptor entry. */
 	entry = tp->cur_tx % TX_RING_SIZE;
@@ -737,7 +738,7 @@
 	/* Trigger an immediate transmit demand. */
 	outl(0, dev->base_addr + CSR1);
 
-	spin_unlock_irq(&tp->lock);
+	spin_unlock_irqrestore(&tp->lock, eflags);
 
 	dev->trans_start = jiffies;
 
@@ -1745,7 +1746,7 @@
 		outl(0xFFFFFFFF, ioaddr + CSR14);
 		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
 		outl(inl(ioaddr + CSR6) | csr6_fd, ioaddr + CSR6);
-		outl(0x0000EF01, ioaddr + CSR13);
+		outl(0x0000EF05, ioaddr + CSR13);
 		break;
 	case DC21040:
 		outl(0x00000000, ioaddr + CSR13);
diff -urN linux-2.4.18-pre3/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- linux-2.4.18-pre3/drivers/net/via-rhine.c	Fri Dec 21 09:41:54 2001
+++ linux/drivers/net/via-rhine.c	Tue Jan 15 15:10:16 2002
@@ -76,8 +76,17 @@
 
 	LK1.1.12:
 	- Martin Eriksson: Allow Memory-Mapped IO to be enabled.
+
+	LK1.1.13 (jgarzik):
+	- Add ethtool support
+	- Replace some MII-related magic numbers with constants
+	
 */
 
+#define DRV_NAME	"via-rhine"
+#define DRV_VERSION	"1.1.13"
+#define DRV_RELDATE	"Nov-17-2001"
+
 
 /* A few user-configurable values.
    These may be modified when a driver module is loaded. */
@@ -151,17 +160,19 @@
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/mii.h>
+#include <linux/ethtool.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/uaccess.h>
 
 /* These identify the driver base version and may not be removed. */
 static char version[] __devinitdata =
-KERN_INFO "via-rhine.c:v1.10-LK1.1.12  03/11/2001  Written by Donald Becker\n"
+KERN_INFO DRV_NAME ".c:v1.10-LK" DRV_VERSION "  " DRV_RELDATE "  Written by Donald Becker\n"
 KERN_INFO "  http://www.scyld.com/network/via-rhine.html\n";
 
-static char shortname[] = "via-rhine";
+static char shortname[] = DRV_NAME;
 
 
 /* This driver was written to use PCI memory space, however most versions
@@ -470,6 +481,7 @@
 	unsigned char phys[MAX_MII_CNT];			/* MII device addresses. */
 	unsigned int mii_cnt;			/* number of MIIs found, but only the first one is used */
 	u16 mii_status;						/* last read MII status */
+	struct mii_if_info mii_if;
 };
 
 static int  mdio_read(struct net_device *dev, int phy_id, int location);
@@ -485,7 +497,7 @@
 static void via_rhine_error(struct net_device *dev, int intr_status);
 static void via_rhine_set_rx_mode(struct net_device *dev);
 static struct net_device_stats *via_rhine_get_stats(struct net_device *dev);
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  via_rhine_close(struct net_device *dev);
 static inline void clear_tally_counters(long ioaddr);
 
@@ -683,6 +695,9 @@
 	np->chip_id = chip_id;
 	np->drv_flags = via_rhine_chip_info[chip_id].drv_flags;
 	np->pdev = pdev;
+	np->mii_if.dev = dev;
+	np->mii_if.mdio_read = mdio_read;
+	np->mii_if.mdio_write = mdio_write;
 
 	if (dev->mem_start)
 		option = dev->mem_start;
@@ -690,16 +705,16 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		np->default_port = option & 15;
 	}
 	if (card_idx < MAX_UNITS  &&  full_duplex[card_idx] > 0)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 
-	if (np->full_duplex) {
+	if (np->mii_if.full_duplex) {
 		printk(KERN_INFO "%s: Set to forced full duplex, autonegotiation"
 			   " disabled.\n", dev->name);
-		np->duplex_lock = 1;
+		np->mii_if.duplex_lock = 1;
 	}
 
 	/* The chip-specific entries in the device structure. */
@@ -708,7 +723,7 @@
 	dev->stop = via_rhine_close;
 	dev->get_stats = via_rhine_get_stats;
 	dev->set_multicast_list = via_rhine_set_rx_mode;
-	dev->do_ioctl = mii_ioctl;
+	dev->do_ioctl = via_rhine_ioctl;
 	dev->tx_timeout = via_rhine_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	if (np->drv_flags & ReqTxAlign)
@@ -735,10 +750,10 @@
 			int mii_status = mdio_read(dev, phy, 1);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				np->phys[phy_idx++] = phy;
-				np->advertising = mdio_read(dev, phy, 4);
+				np->mii_if.advertising = mdio_read(dev, phy, 4);
 				printk(KERN_INFO "%s: MII PHY found at address %d, status "
 					   "0x%4.4x advertising %4.4x Link %4.4x.\n",
-					   dev->name, phy, mii_status, np->advertising,
+					   dev->name, phy, mii_status, np->mii_if.advertising,
 					   mdio_read(dev, phy, 5));
 
 				/* set IFF_RUNNING */
@@ -749,12 +764,13 @@
 			}
 		}
 		np->mii_cnt = phy_idx;
+		np->mii_if.phy_id = np->phys[0];
 	}
 
 	/* Allow forcing the media type. */
 	if (option > 0) {
 		if (option & 0x220)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		np->default_port = option & 0x3ff;
 		if (np->default_port & 0x330) {
 			/* FIXME: shouldn't someone check this variable? */
@@ -968,7 +984,7 @@
 		   ioaddr + IntrEnable);
 
 	np->chip_cmd = CmdStart|CmdTxOn|CmdRxOn|CmdNoTxPoll;
-	if (np->duplex_lock)
+	if (np->mii_if.duplex_lock)
 		np->chip_cmd |= CmdFDuplex;
 	writew(np->chip_cmd, ioaddr + ChipCmd);
 
@@ -1010,12 +1026,12 @@
 		switch (regnum) {
 		case 0:							/* Is user forcing speed/duplex? */
 			if (value & 0x9000)			/* Autonegotiation. */
-				np->duplex_lock = 0;
+				np->mii_if.duplex_lock = 0;
 			else
-				np->full_duplex = (value & 0x0100) ? 1 : 0;
+				np->mii_if.full_duplex = (value & 0x0100) ? 1 : 0;
 			break;
 		case 4:
-			np->advertising = value;
+			np->mii_if.advertising = value;
 			break;
 		}
 	}
@@ -1059,7 +1075,7 @@
 		printk(KERN_DEBUG "%s: Done via_rhine_open(), status %4.4x "
 			   "MII status: %4.4x.\n",
 			   dev->name, readw(ioaddr + ChipCmd),
-			   mdio_read(dev, np->phys[0], 1));
+			   mdio_read(dev, np->phys[0], MII_BMSR));
 
 	netif_start_queue(dev);
 
@@ -1077,19 +1093,19 @@
 {
 	struct netdev_private *np = dev->priv;
 	long ioaddr = dev->base_addr;
-	int mii_reg5 = mdio_read(dev, np->phys[0], 5);
-	int negotiated = mii_reg5 & np->advertising;
+	int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
+	int negotiated = mii_lpa & np->mii_if.advertising;
 	int duplex;
 
-	if (np->duplex_lock  ||  mii_reg5 == 0xffff)
+	if (np->mii_if.duplex_lock  ||  mii_lpa == 0xffff)
 		return;
 	duplex = (negotiated & 0x0100) || (negotiated & 0x01C0) == 0x0040;
-	if (np->full_duplex != duplex) {
-		np->full_duplex = duplex;
+	if (np->mii_if.full_duplex != duplex) {
+		np->mii_if.full_duplex = duplex;
 		if (debug)
 			printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
 				   " partner capability of %4.4x.\n", dev->name,
-				   duplex ? "full" : "half", np->phys[0], mii_reg5);
+				   duplex ? "full" : "half", np->phys[0], mii_lpa);
 		if (duplex)
 			np->chip_cmd |= CmdFDuplex;
 		else
@@ -1117,7 +1133,7 @@
 	via_rhine_check_duplex(dev);
 
 	/* make IFF_RUNNING follow the MII status bit "Link established" */
-	mii_status = mdio_read(dev, np->phys[0], 1);
+	mii_status = mdio_read(dev, np->phys[0], MII_BMSR);
 	if ( (mii_status & MIILink) != (np->mii_status & MIILink) ) {
 		if (mii_status & MIILink)
 			netif_carrier_on(dev);
@@ -1141,7 +1157,7 @@
 	printk (KERN_WARNING "%s: Transmit timed out, status %4.4x, PHY status "
 		"%4.4x, resetting...\n",
 		dev->name, readw (ioaddr + IntrStatus),
-		mdio_read (dev, np->phys[0], 1));
+		mdio_read (dev, np->phys[0], MII_BMSR));
 
 	dev->if_port = 0;
 
@@ -1456,14 +1472,14 @@
 		if (readb(ioaddr + MIIStatus) & 0x02) {
 			/* Link failed, restart autonegotiation. */
 			if (np->drv_flags & HasDavicomPhy)
-				mdio_write(dev, np->phys[0], 0, 0x3300);
+				mdio_write(dev, np->phys[0], MII_BMCR, 0x3300);
 		} else
 			via_rhine_check_duplex(dev);
 		if (debug)
 			printk(KERN_ERR "%s: MII status changed: Autonegotiation "
 				   "advertising %4.4x  partner %4.4x.\n", dev->name,
-			   mdio_read(dev, np->phys[0], 4),
-			   mdio_read(dev, np->phys[0], 5));
+			   mdio_read(dev, np->phys[0], MII_ADVERTISE),
+			   mdio_read(dev, np->phys[0], MII_LPA));
 	}
 	if (intr_status & IntrStatsMax) {
 		np->stats.rx_crc_errors	+= readw(ioaddr + RxCRCErrs);
@@ -1573,12 +1589,98 @@
 	writeb(np->rx_thresh | rx_mode, ioaddr + RxConfig);
 }
 
-static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int via_rhine_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+	struct netdev_private *np = dev->priv;
+	u32 ethcmd;
+
+	if (get_user(ethcmd, (u32 *)useraddr))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO: {
+		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+		strcpy (info.driver, DRV_NAME);
+		strcpy (info.version, DRV_VERSION);
+		strcpy (info.bus_info, np->pdev->slot_name);
+		if (copy_to_user (useraddr, &info, sizeof (info)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		return mii_nway_restart(&np->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		if (!(np->drv_flags & CanHaveMII))
+			break;
+		edata.data = mii_link_ok(&np->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+static int via_rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	struct netdev_private *np = dev->priv;
 	struct mii_ioctl_data *data = (struct mii_ioctl_data *)&rq->ifr_data;
 	unsigned long flags;
 	int retval;
+
+	if (cmd == SIOCETHTOOL)
+		return via_rhine_ethtool_ioctl(dev, (void *) rq->ifr_data);
 
 	spin_lock_irqsave(&np->lock, flags);
 	retval = 0;
diff -urN linux-2.4.18-pre3/drivers/net/wan/sdla_ppp.c linux/drivers/net/wan/sdla_ppp.c
--- linux-2.4.18-pre3/drivers/net/wan/sdla_ppp.c	Thu Sep 13 16:04:43 2001
+++ linux/drivers/net/wan/sdla_ppp.c	Tue Jan 15 15:10:16 2002
@@ -2473,7 +2473,7 @@
 #endif
 
 		default:
-			printk(KERN_INFO "%s: ERROR: Unsuported PPP Mode Selected\n",
+			printk(KERN_INFO "%s: ERROR: Unsupported PPP Mode Selected\n",
 					card->devname);
 			printk(KERN_INFO "%s:        PPP IP Modes: STATIC, PEER or HOST\n",
 					card->devname);	
diff -urN linux-2.4.18-pre3/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c
--- linux-2.4.18-pre3/drivers/net/winbond-840.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/net/winbond-840.c	Tue Jan 15 15:10:16 2002
@@ -36,6 +36,8 @@
 		power management.
 		support for big endian descriptors
 			Copyright (C) 2001 Manfred Spraul
+  	* ethtool support (jgarzik)
+	* Replace some MII-related magic numbers with constants (jgarzik)
   
 	TODO:
 	* enable pci_power_off
@@ -43,8 +45,8 @@
 */
   
 #define DRV_NAME	"winbond-840"
-#define DRV_VERSION	"1.01-c"
-#define DRV_RELDATE	"6/30/2000"
+#define DRV_VERSION	"1.01-d"
+#define DRV_RELDATE	"Nov-17-2001"
 
 
 /* Automatically extracted configuration info:
@@ -363,14 +365,11 @@
 	unsigned int cur_tx, dirty_tx;
 	unsigned int tx_q_bytes;
 	unsigned int tx_full;				/* The Tx queue is full. */
-	/* These values are keep track of the transceiver/media in use. */
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
-	unsigned int duplex_lock:1;
 	/* MII transceiver section. */
 	int mii_cnt;						/* MII device addresses. */
-	u16 advertising;					/* NWay media advertisement */
 	unsigned char phys[MII_CNT];		/* MII device addresses, but only the first is used */
 	u32 mii;
+	struct mii_if_info mii_if;
 };
 
 static int  eeprom_read(long ioaddr, int location);
@@ -453,6 +452,9 @@
 	np->chip_id = chip_idx;
 	np->drv_flags = pci_id_tbl[chip_idx].drv_flags;
 	spin_lock_init(&np->lock);
+	np->mii_if.dev = dev;
+	np->mii_if.mdio_read = mdio_read;
+	np->mii_if.mdio_write = mdio_write;
 	
 	pci_set_drvdata(pdev, dev);
 
@@ -462,16 +464,16 @@
 	/* The lower four bits are the media type. */
 	if (option > 0) {
 		if (option & 0x200)
-			np->full_duplex = 1;
+			np->mii_if.full_duplex = 1;
 		if (option & 15)
 			printk(KERN_INFO "%s: ignoring user supplied media type %d",
 				dev->name, option & 15);
 	}
 	if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 
-	if (np->full_duplex)
-		np->duplex_lock = 1;
+	if (np->mii_if.full_duplex)
+		np->mii_if.duplex_lock = 1;
 
 	/* The chip-specific entries in the device structure. */
 	dev->open = &netdev_open;
@@ -496,18 +498,19 @@
 	if (np->drv_flags & CanHaveMII) {
 		int phy, phy_idx = 0;
 		for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
-			int mii_status = mdio_read(dev, phy, 1);
+			int mii_status = mdio_read(dev, phy, MII_BMSR);
 			if (mii_status != 0xffff  &&  mii_status != 0x0000) {
 				np->phys[phy_idx++] = phy;
-				np->advertising = mdio_read(dev, phy, 4);
-				np->mii = (mdio_read(dev, phy, 2) << 16)+
-						mdio_read(dev, phy, 3);
+				np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
+				np->mii = (mdio_read(dev, phy, MII_PHYSID1) << 16)+
+						mdio_read(dev, phy, MII_PHYSID2);
 				printk(KERN_INFO "%s: MII PHY %8.8xh found at address %d, status "
 					   "0x%4.4x advertising %4.4x.\n",
-					   dev->name, np->mii, phy, mii_status, np->advertising);
+					   dev->name, np->mii, phy, mii_status, np->mii_if.advertising);
 			}
 		}
 		np->mii_cnt = phy_idx;
+		np->mii_if.phy_id = np->phys[0];
 		if (phy_idx == 0) {
 				printk(KERN_WARNING "%s: MII PHY not found -- this device may "
 					   "not operate correctly.\n", dev->name);
@@ -654,7 +657,7 @@
 	int i;
 
 	if (location == 4  &&  phy_id == np->phys[0])
-		np->advertising = value;
+		np->mii_if.advertising = value;
 
 	if (mii_preamble_required)
 		mdio_sync(mdio_addr);
@@ -728,12 +731,12 @@
 	int duplex, fasteth, result, mii_reg;
 
 	/* BSMR */
-	mii_reg = mdio_read(dev, np->phys[0], 1);
+	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
 
 	if (mii_reg == 0xffff)
 		return np->csr6;
 	/* reread: the link status bit is sticky */
-	mii_reg = mdio_read(dev, np->phys[0], 1);
+	mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
 	if (!(mii_reg & 0x4)) {
 		if (netif_carrier_ok(dev)) {
 			if (debug)
@@ -759,18 +762,18 @@
 		 * Instead bit 9 and 13 of the BMCR are updated to the result
 		 * of the negotiation..
 		 */
-		mii_reg = mdio_read(dev, np->phys[0], 0);
-		duplex = mii_reg & 0x100;
-		fasteth = mii_reg & 0x2000;
+		mii_reg = mdio_read(dev, np->phys[0], MII_BMCR);
+		duplex = mii_reg & BMCR_FULLDPLX;
+		fasteth = mii_reg & BMCR_SPEED100;
 	} else {
 		int negotiated;
-		mii_reg	= mdio_read(dev, np->phys[0], 5);
-		negotiated = mii_reg & np->advertising;
+		mii_reg	= mdio_read(dev, np->phys[0], MII_LPA);
+		negotiated = mii_reg & np->mii_if.advertising;
 
-		duplex = (negotiated & 0x0100) || ((negotiated & 0x02C0) == 0x0040);
+		duplex = (negotiated & LPA_100FULL) || ((negotiated & 0x02C0) == LPA_10FULL);
 		fasteth = negotiated & 0x380;
 	}
-	duplex |= np->duplex_lock;
+	duplex |= np->mii_if.duplex_lock;
 	/* remove fastether and fullduplex */
 	result = np->csr6 & ~0x20000200;
 	if (duplex)
@@ -822,7 +825,7 @@
 	/* and restart them with the new configuration */
 	writel(np->csr6, ioaddr + NetworkConfig);
 	if (new & 0x200)
-		np->full_duplex = 1;
+		np->mii_if.full_duplex = 1;
 }
 
 static void netdev_timer(unsigned long data)
@@ -1131,7 +1134,7 @@
 			if (tx_status & 0x0C80) np->stats.tx_carrier_errors++;
 			if (tx_status & 0x0200) np->stats.tx_window_errors++;
 			if (tx_status & 0x0002) np->stats.tx_fifo_errors++;
-			if ((tx_status & 0x0080) && np->full_duplex == 0)
+			if ((tx_status & 0x0080) && np->mii_if.full_duplex == 0)
 				np->stats.tx_heartbeat_errors++;
 #ifdef ETHER_STATS
 			if (tx_status & 0x0100) np->stats.collisions16++;
@@ -1484,6 +1487,56 @@
 		return 0;
 	}
 
+	/* get settings */
+	case ETHTOOL_GSET: {
+		struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+		spin_lock_irq(&np->lock);
+		mii_ethtool_gset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set settings */
+	case ETHTOOL_SSET: {
+		int r;
+		struct ethtool_cmd ecmd;
+		if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+			return -EFAULT;
+		spin_lock_irq(&np->lock);
+		r = mii_ethtool_sset(&np->mii_if, &ecmd);
+		spin_unlock_irq(&np->lock);
+		return r;
+	}
+	/* restart autonegotiation */
+	case ETHTOOL_NWAY_RST: {
+		return mii_nway_restart(&np->mii_if);
+	}
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = {ETHTOOL_GLINK};
+		edata.data = mii_link_ok(&np->mii_if);
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	/* get message-level */
+	case ETHTOOL_GMSGLVL: {
+		struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+		edata.data = debug;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+	/* set message-level */
+	case ETHTOOL_SMSGLVL: {
+		struct ethtool_value edata;
+		if (copy_from_user(&edata, useraddr, sizeof(edata)))
+			return -EFAULT;
+		debug = edata.data;
+		return 0;
+	}
         }
 	
 	return -EOPNOTSUPP;
diff -urN linux-2.4.18-pre3/drivers/net/wireless/airo_cs.c linux/drivers/net/wireless/airo_cs.c
--- linux-2.4.18-pre3/drivers/net/wireless/airo_cs.c	Thu Sep 13 16:04:43 2001
+++ linux/drivers/net/wireless/airo_cs.c	Tue Jan 15 15:10:16 2002
@@ -244,6 +244,11 @@
 	
 	/* Allocate space for private device-specific data */
 	local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
+	if (!local) {
+		printk(KERN_ERR "airo_cs: no memory for new device\n");
+		kfree (link);
+		return NULL;
+	}
 	memset(local, 0, sizeof(local_info_t));
 	link->priv = local;
 	
diff -urN linux-2.4.18-pre3/drivers/net/wireless/hermes_rid.h linux/drivers/net/wireless/hermes_rid.h
--- linux-2.4.18-pre3/drivers/net/wireless/hermes_rid.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/hermes_rid.h	Tue Jan 15 15:10:16 2002
@@ -0,0 +1,153 @@
+#ifndef _HERMES_RID_H
+#define _HERMES_RID_H
+
+/*
+ * Configuration RIDs
+ */
+#define HERMES_RID_CNFPORTTYPE			0xFC00	/* used */
+#define HERMES_RID_CNFOWNMACADDR		0xFC01	/* used */
+#define HERMES_RID_CNFDESIREDSSID		0xFC02	/* used */
+#define HERMES_RID_CNFOWNCHANNEL		0xFC03	/* used */
+#define HERMES_RID_CNFOWNSSID			0xFC04	/* used */
+#define HERMES_RID_CNFOWNATIMWINDOW		0xFC05
+#define HERMES_RID_CNFSYSTEMSCALE		0xFC06	/* used */
+#define HERMES_RID_CNFMAXDATALEN		0xFC07
+#define HERMES_RID_CNFWDSADDRESS		0xFC08
+#define HERMES_RID_CNFPMENABLED			0xFC09	/* used */
+#define HERMES_RID_CNFPMEPS			0xFC0A
+#define HERMES_RID_CNFMULTICASTRECEIVE		0xFC0B	/* used */
+#define HERMES_RID_CNFMAXSLEEPDURATION		0xFC0C	/* used */
+#define HERMES_RID_CNFPMHOLDOVERDURATION	0xFC0D	/* used */
+#define HERMES_RID_CNFOWNNAME			0xFC0E	/* used */
+#define HERMES_RID_CNFOWNDTIMPERIOD		0xFC10
+#define HERMES_RID_CNFWDSADDRESS1		0xFC11
+#define HERMES_RID_CNFWDSADDRESS2		0xFC12
+#define HERMES_RID_CNFWDSADDRESS3		0xFC13
+#define HERMES_RID_CNFWDSADDRESS4		0xFC14
+#define HERMES_RID_CNFWDSADDRESS5		0xFC15
+#define HERMES_RID_CNFWDSADDRESS6		0xFC16
+#define HERMES_RID_CNFMULTICASTPMBUFFERING	0xFC17
+#define HERMES_RID_CNFWEPENABLED_AGERE		0xFC20	/* used */
+#define HERMES_RID_CNFMANDATORYBSSID_SYMBOL	0xFC21
+#define HERMES_RID_CNFWEPDEFAULTKEYID		0xFC23	/* used */
+#define HERMES_RID_CNFDEFAULTKEY0		0xFC24	/* used */
+#define HERMES_RID_CNFDEFAULTKEY1		0xFC25	/* used */
+#define HERMES_RID_CNFMWOROBUST_AGERE		0xFC25	/* used */
+#define HERMES_RID_CNFDEFAULTKEY2		0xFC26	/* used */
+#define HERMES_RID_CNFDEFAULTKEY3		0xFC27	/* used */
+#define HERMES_RID_CNFWEPFLAGS_INTERSIL		0xFC28	/* used */
+#define HERMES_RID_CNFWEPKEYMAPPINGTABLE	0xFC29
+#define HERMES_RID_CNFAUTHENTICATION		0xFC2A	/* used */
+#define HERMES_RID_CNFMAXASSOCSTA		0xFC2B
+#define	HERMES_RID_CNFKEYLENGTH_SYMBOL		0xFC2B
+#define HERMES_RID_CNFTXCONTROL			0xFC2C
+#define HERMES_RID_CNFROAMINGMODE		0xFC2D
+#define HERMES_RID_CNFHOSTAUTHENTICATION	0xFC2E
+#define HERMES_RID_CNFRCVCRCERROR		0xFC30
+#define HERMES_RID_CNFMMLIFE			0xFC31
+#define HERMES_RID_CNFALTRETRYCOUNT		0xFC32
+#define HERMES_RID_CNFBEACONINT			0xFC33
+#define HERMES_RID_CNFAPPCFINFO			0xFC34
+#define HERMES_RID_CNFSTAPCFINFO		0xFC35
+#define HERMES_RID_CNFPRIORITYQUSAGE		0xFC37
+#define HERMES_RID_CNFTIMCTRL			0xFC40
+#define HERMES_RID_CNFTHIRTY2TALLY		0xFC42
+#define HERMES_RID_CNFENHSECURITY		0xFC43
+#define HERMES_RID_CNFGROUPADDRESSES		0xFC80	/* used */
+#define HERMES_RID_CNFCREATEIBSS		0xFC81	/* used */
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD	0xFC82	/* used */
+#define HERMES_RID_CNFRTSTHRESHOLD		0xFC83	/* used */
+#define HERMES_RID_CNFTXRATECONTROL		0xFC84	/* used */
+#define HERMES_RID_CNFPROMISCUOUSMODE		0xFC85	/* used */
+#define HERMES_RID_CNFBASICRATES_SYMBOL		0xFC8A
+#define HERMES_RID_CNFPREAMBLE_SYMBOL		0xFC8C	/* used */
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0	0xFC90
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1	0xFC91
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2	0xFC92
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD3	0xFC93
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD4	0xFC94
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD5	0xFC95
+#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD6	0xFC96
+#define HERMES_RID_CNFRTSTHRESHOLD0		0xFC97
+#define HERMES_RID_CNFRTSTHRESHOLD1		0xFC98
+#define HERMES_RID_CNFRTSTHRESHOLD2		0xFC99
+#define HERMES_RID_CNFRTSTHRESHOLD3		0xFC9A
+#define HERMES_RID_CNFRTSTHRESHOLD4		0xFC9B
+#define HERMES_RID_CNFRTSTHRESHOLD5		0xFC9C
+#define HERMES_RID_CNFRTSTHRESHOLD6		0xFC9D
+#define HERMES_RID_CNFSHORTPREAMBLE		0xFCB0
+#define HERMES_RID_CNFWEPKEYS_AGERE		0xFCB0	/* used */
+#define HERMES_RID_CNFEXCLUDELONGPREAMBLE	0xFCB1
+#define HERMES_RID_CNFTXKEY_AGERE		0xFCB1	/* used */
+#define HERMES_RID_CNFAUTHENTICATIONRSPTO	0xFCB2
+#define HERMES_RID_CNFBASICRATES		0xFCB3
+#define HERMES_RID_CNFSUPPORTEDRATES		0xFCB4
+#define HERMES_RID_CNFTICKTIME			0xFCE0	/* used */
+#define HERMES_RID_CNFSCANREQUEST		0xFCE1
+#define HERMES_RID_CNFJOINREQUEST		0xFCE2
+#define HERMES_RID_CNFAUTHENTICATESTATION	0xFCE3
+#define HERMES_RID_CNFCHANNELINFOREQUEST	0xFCE4
+
+/*
+ * Information RIDs
+ */
+#define HERMES_RID_MAXLOADTIME			0xFD00
+#define HERMES_RID_DOWNLOADBUFFER		0xFD01
+#define HERMES_RID_PRIID			0xFD02
+#define HERMES_RID_PRISUPRANGE			0xFD03
+#define HERMES_RID_CFIACTRANGES			0xFD04
+#define HERMES_RID_NICSERNUM			0xFD0A
+#define HERMES_RID_NICID			0xFD0B
+#define HERMES_RID_MFISUPRANGE			0xFD0C
+#define HERMES_RID_CFISUPRANGE			0xFD0D
+#define HERMES_RID_CHANNELLIST			0xFD10	/* used */
+#define HERMES_RID_REGULATORYDOMAINS		0xFD11
+#define HERMES_RID_TEMPTYPE			0xFD12
+#define HERMES_RID_CIS				0xFD13
+#define HERMES_RID_STAID			0xFD20	/* used */
+#define HERMES_RID_STASUPRANGE			0xFD21
+#define HERMES_RID_MFIACTRANGES			0xFD22
+#define HERMES_RID_CFIACTRANGES2		0xFD23
+#define HERMES_RID_SECONDARYVERSION_SYMBOL	0xFD24	/* used */
+#define HERMES_RID_PORTSTATUS			0xFD40
+#define HERMES_RID_CURRENTSSID			0xFD41	/* used */
+#define HERMES_RID_CURRENTBSSID			0xFD42	/* used */
+#define HERMES_RID_COMMSQUALITY			0xFD43	/* used */
+#define HERMES_RID_CURRENTTXRATE		0xFD44	/* used */
+#define HERMES_RID_CURRENTBEACONINTERVAL	0xFD45
+#define HERMES_RID_CURRENTSCALETHRESHOLDS	0xFD46
+#define HERMES_RID_PROTOCOLRSPTIME		0xFD47
+#define HERMES_RID_SHORTRETRYLIMIT		0xFD48	/* used */
+#define HERMES_RID_LONGRETRYLIMIT		0xFD49	/* used */
+#define HERMES_RID_MAXTRANSMITLIFETIME		0xFD4A	/* used */
+#define HERMES_RID_MAXRECEIVELIFETIME		0xFD4B
+#define HERMES_RID_CFPOLLABLE			0xFD4C
+#define HERMES_RID_AUTHENTICATIONALGORITHMS	0xFD4D
+#define HERMES_RID_PRIVACYOPTIONIMPLEMENTED	0xFD4F
+#define HERMES_RID_CURRENTTXRATE1		0xFD80
+#define HERMES_RID_CURRENTTXRATE2		0xFD81
+#define HERMES_RID_CURRENTTXRATE3		0xFD82
+#define HERMES_RID_CURRENTTXRATE4		0xFD83
+#define HERMES_RID_CURRENTTXRATE5		0xFD84
+#define HERMES_RID_CURRENTTXRATE6		0xFD85
+#define HERMES_RID_OWNMACADDR			0xFD86
+#define HERMES_RID_SCANRESULTSTABLE		0xFD88
+#define HERMES_RID_PHYTYPE			0xFDC0
+#define HERMES_RID_CURRENTCHANNEL		0xFDC1	/* used */
+#define HERMES_RID_CURRENTPOWERSTATE		0xFDC2
+#define HERMES_RID_CCAMODE			0xFDC3
+#define HERMES_RID_SUPPORTEDDATARATES		0xFDC6	/* used */
+#define HERMES_RID_BUILDSEQ			0xFFFE
+#define HERMES_RID_FWID				0xFFFF
+
+/* "ID" structure - used for ESSID and station nickname */
+struct hermes_idstring {
+	u16 len;
+	u16 val[16];
+} __attribute__ ((packed));
+
+typedef struct hermes_multicast {
+	u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
+} __attribute__ ((packed)) hermes_multicast_t;
+
+#endif
diff -urN linux-2.4.18-pre3/drivers/net/wireless/ieee802_11.h linux/drivers/net/wireless/ieee802_11.h
--- linux-2.4.18-pre3/drivers/net/wireless/ieee802_11.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/wireless/ieee802_11.h	Tue Jan 15 15:10:16 2002
@@ -0,0 +1,67 @@
+#ifndef _IEEE802_11_H
+#define _IEEE802_11_H
+
+struct ieee802_11_hdr {
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+	u16 data_len;
+} __attribute__ ((packed));
+
+/* Frame control field constants */
+#define IEEE802_11_FCTL_VERS		0x0002
+#define IEEE802_11_FCTL_FTYPE		0x000c
+#define IEEE802_11_FCTL_STYPE		0x00f0
+#define IEEE802_11_FCTL_TODS		0x0100
+#define IEEE802_11_FCTL_FROMDS		0x0200
+#define IEEE802_11_FCTL_MOREFRAGS	0x0400
+#define IEEE802_11_FCTL_RETRY		0x0800
+#define IEEE802_11_FCTL_PM		0x1000
+#define IEEE802_11_FCTL_MOREDATA	0x2000
+#define IEEE802_11_FCTL_WEP		0x4000
+#define IEEE802_11_FCTL_ORDER		0x8000
+
+#define IEEE802_11_FTYPE_MGMT		0x0000
+#define IEEE802_11_FTYPE_CTL		0x0004
+#define IEEE802_11_FTYPE_DATA		0x0008
+
+/* management */
+#define IEEE802_11_STYPE_ASSOC_REQ	0x0000
+#define IEEE802_11_STYPE_ASSOC_RESP 	0x0010
+#define IEEE802_11_STYPE_REASSOC_REQ	0x0020
+#define IEEE802_11_STYPE_REASSOC_RESP	0x0030
+#define IEEE802_11_STYPE_PROBE_REQ	0x0040
+#define IEEE802_11_STYPE_PROBE_RESP	0x0050
+#define IEEE802_11_STYPE_BEACON		0x0080
+#define IEEE802_11_STYPE_ATIM		0x0090
+#define IEEE802_11_STYPE_DISASSOC	0x00A0
+#define IEEE802_11_STYPE_AUTH		0x00B0
+#define IEEE802_11_STYPE_DEAUTH		0x00C0
+
+/* control */
+#define IEEE802_11_STYPE_PSPOLL		0x00A0
+#define IEEE802_11_STYPE_RTS		0x00B0
+#define IEEE802_11_STYPE_CTS		0x00C0
+#define IEEE802_11_STYPE_ACK		0x00D0
+#define IEEE802_11_STYPE_CFEND		0x00E0
+#define IEEE802_11_STYPE_CFENDACK	0x00F0
+
+/* data */
+#define IEEE802_11_STYPE_DATA		0x0000
+#define IEEE802_11_STYPE_DATA_CFACK	0x0010
+#define IEEE802_11_STYPE_DATA_CFPOLL	0x0020
+#define IEEE802_11_STYPE_DATA_CFACKPOLL	0x0030
+#define IEEE802_11_STYPE_NULLFUNC	0x0040
+#define IEEE802_11_STYPE_CFACK		0x0050
+#define IEEE802_11_STYPE_CFPOLL		0x0060
+#define IEEE802_11_STYPE_CFACKPOLL	0x0070
+
+#define IEEE802_11_SCTL_FRAG		0x000F
+#define IEEE802_11_SCTL_SEQ		0xFFF0
+
+#endif /* _IEEE802_11_H */
+
diff -urN linux-2.4.18-pre3/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- linux-2.4.18-pre3/drivers/parport/ChangeLog	Tue Jan 15 15:10:09 2002
+++ linux/drivers/parport/ChangeLog	Tue Jan 15 15:10:16 2002
@@ -1,3 +1,8 @@
+2002-01-13  Niels Kristian Bech Jensen  <nkbj@image.dk>
+
+	* parport_pc.c: Change some occurrences of frob_set_mode to
+	ECR_WRITE.  This fixes PLIP.
+
 2002-01-04  Tim Waugh  <twaugh@redhat.com>
 
 	* share.c (parport_claim_or_block): Sleep interruptibly to prevent
diff -urN linux-2.4.18-pre3/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- linux-2.4.18-pre3/drivers/parport/parport_pc.c	Tue Jan 15 15:10:10 2002
+++ linux/drivers/parport/parport_pc.c	Tue Jan 15 15:10:16 2002
@@ -128,7 +128,6 @@
 static int change_mode(struct parport *p, int m)
 {
 	const struct parport_pc_private *priv = p->physport->private_data;
-	int ecr = ECONTROL(p);
 	unsigned char oecr;
 	int mode;
 
@@ -140,7 +139,7 @@
 	}
 
 	/* Bits <7:5> contain the mode. */
-	oecr = inb (ecr);
+	oecr = inb (ECONTROL (p));
 	mode = (oecr >> 5) & 0x7;
 	if (mode == m) return 0;
 
@@ -631,7 +630,7 @@
 			/* FIFO is full. Wait for interrupt. */
 
 			/* Clear serviceIntr */
-			outb (ecrval & ~(1<<2), ECONTROL (port));
+			ECR_WRITE (port, ecrval & ~(1<<2));
 		false_alarm:
 			ret = parport_wait_event (port, HZ);
 			if (ret < 0) break;
@@ -859,7 +858,7 @@
 		printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
 		/* Prevent further data transfer. */
-		frob_econtrol (port, 0xe0, ECR_TST << 5);
+		frob_set_mode (port, ECR_TST);
 
 		/* Adjust for the contents of the FIFO. */
 		for (written -= priv->fifo_depth; ; written++) {
@@ -956,7 +955,7 @@
 		printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name);
 
 		/* Prevent further data transfer. */
-		frob_econtrol (port, 0xe0, ECR_TST << 5);
+		frob_set_mode (port, ECR_TST);
 
 		/* Adjust for the contents of the FIFO. */
 		for (written -= priv->fifo_depth; ; written++) {
@@ -1135,7 +1134,7 @@
 			}
 
 			/* Clear serviceIntr */
-			outb (ecrval & ~(1<<2), ECONTROL (port));
+			ECR_WRITE (port, ecrval & ~(1<<2));
 		false_alarm:
 dump_parport_state ("waiting", port);
 			ret = parport_wait_event (port, HZ);
@@ -1738,7 +1737,7 @@
 	if ((inb (ECONTROL (pb)) & 0x3 ) != 0x1)
 		goto no_reg;
 
-	outb (0x34, ECONTROL (pb));
+	ECR_WRITE (pb, 0x34);
 	if (inb (ECONTROL (pb)) != 0x35)
 		goto no_reg;
 
@@ -1816,8 +1815,8 @@
 		return 0;
 
 	/* Find out FIFO depth */
-	frob_set_mode (pb, ECR_SPP); /* Reset FIFO */
-	frob_set_mode (pb, ECR_TST); /* TEST FIFO */
+	ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */
+	ECR_WRITE (pb, ECR_TST << 5); /* TEST FIFO */
 	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++)
 		outb (0xaa, FIFO (pb));
 
@@ -1826,7 +1825,7 @@
 	 * it doesn't support ECP or FIFO MODE
 	 */
 	if (i == 1024) {
-		frob_set_mode (pb, ECR_SPP);
+		ECR_WRITE (pb, ECR_SPP << 5);
 		return 0;
 	}
 
@@ -1877,8 +1876,8 @@
 
 	priv->readIntrThreshold = i;
 
-	frob_set_mode (pb, ECR_SPP); /* Reset FIFO */
-	outb (0xf4, ECONTROL (pb)); /* Configuration mode */
+	ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */
+	ECR_WRITE (pb, 0xf4); /* Configuration mode */
 	config = inb (CONFIGA (pb));
 	pword = (config >> 4) & 0x7;
 	switch (pword) {
@@ -1939,7 +1938,7 @@
 		return 0;
 
 	oecr = inb (ECONTROL (pb));
-	frob_set_mode (pb, ECR_PS2);
+	ECR_WRITE (pb, ECR_PS2 << 5);
 	result = parport_PS2_supported(pb);
 	ECR_WRITE (pb, oecr);
 	return result;
@@ -1972,8 +1971,8 @@
 	/* Check for Intel bug. */
 	if (priv->ecr) {
 		unsigned char i;
-		for (i = 0; i < 4; i++) {
-			frob_set_mode (pb, i);
+		for (i = 0x00; i < 0x80; i += 0x20) {
+			ECR_WRITE (pb, i);
 			if (clear_epp_timeout (pb)) {
 				/* Phony EPP in ECP. */
 				return 0;
@@ -2004,7 +2003,7 @@
 
 	oecr = inb (ECONTROL (pb));
 	/* Search for SMC style EPP+ECP mode */
-	frob_set_mode (pb, ECR_EPP);
+	ECR_WRITE (pb, 0x80);
 	outb (0x04, CONTROL (pb));
 	result = parport_EPP_supported(pb);
 
@@ -2045,7 +2044,7 @@
 		PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5
 	};
 
-	frob_set_mode (pb, ECR_CNF); /* Configuration MODE */
+	ECR_WRITE (pb, ECR_CNF << 5); /* Configuration MODE */
 
 	intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07;
 	irq = lookup[intrLine];
@@ -2062,16 +2061,16 @@
 	sti();
 	irqs = probe_irq_on();
 		
-	frob_set_mode (pb, ECR_SPP); /* Reset FIFO */
-	frob_econtrol (pb, ECR_MODE_MASK | 0x04, (ECR_TST << 5) | 0x04);
-	frob_set_mode (pb, ECR_TST);
+	ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */
+	ECR_WRITE (pb, (ECR_TST << 5) | 0x04);
+	ECR_WRITE (pb, ECR_TST << 5);
 
 	/* If Full FIFO sure that writeIntrThreshold is generated */
 	for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) 
 		outb (0xaa, FIFO (pb));
 		
 	pb->irq = probe_irq_off(irqs);
-	frob_set_mode (pb, ECR_SPP);
+	ECR_WRITE (pb, ECR_SPP << 5);
 
 	if (pb->irq <= 0)
 		pb->irq = PARPORT_IRQ_NONE;
diff -urN linux-2.4.18-pre3/drivers/sbus/char/sunserial.c linux/drivers/sbus/char/sunserial.c
--- linux-2.4.18-pre3/drivers/sbus/char/sunserial.c	Thu Apr 19 08:38:49 2001
+++ linux/drivers/sbus/char/sunserial.c	Tue Jan 15 15:10:16 2002
@@ -1,4 +1,4 @@
-/* $Id: sunserial.c,v 1.79 2001/04/18 21:06:17 davem Exp $
+/* $Id: sunserial.c,v 1.79.2.2 2002/01/05 01:12:31 davem Exp $
  * serial.c: Serial port driver infrastructure for the Sparc.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
diff -urN linux-2.4.18-pre3/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- linux-2.4.18-pre3/drivers/sbus/char/zs.c	Tue Oct 30 15:08:11 2001
+++ linux/drivers/sbus/char/zs.c	Tue Jan 15 15:10:16 2002
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.68 2001/10/25 18:48:03 davem Exp $
+/* $Id: zs.c,v 1.68.2.1 2002/01/04 21:12:09 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -486,10 +486,19 @@
 static void receive_chars(struct sun_serial *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
-	unsigned char ch, stat;
-	int do_queue_task = 1;
+	int do_queue_task = 0;
+
+	while (1) {
+		unsigned char ch, r1;
+
+		r1 = read_zsreg(info->zs_channel, R1);
+		if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR)) {
+			sbus_writeb(ERR_RES, &info->zs_channel->control);
+			ZSDELAY();
+			ZS_WSYNC(info->zs_channel);
+			ZSLOG(REGCTRL, ERR_RES, 1);
+		}
 
-	do {
 		ch = sbus_readb(&info->zs_channel->data);
 		ZSLOG(REGDATA, ch, 0);
 		ch &= info->parity_mask;
@@ -498,17 +507,17 @@
 		/* If this is the console keyboard, we need to handle
 		 * L1-A's here.
 		 */
-		if(info->cons_keyb) {
-			if(ch == SUNKBD_RESET) {
+		if (info->cons_keyb) {
+			if (ch == SUNKBD_RESET) {
 				l1a_state.kbd_id = 1;
 				l1a_state.l1_down = 0;
-			} else if(l1a_state.kbd_id) {
+			} else if (l1a_state.kbd_id) {
 				l1a_state.kbd_id = 0;
-			} else if(ch == SUNKBD_L1) {
+			} else if (ch == SUNKBD_L1) {
 				l1a_state.l1_down = 1;
-			} else if(ch == (SUNKBD_L1|SUNKBD_UP)) {
+			} else if (ch == (SUNKBD_L1|SUNKBD_UP)) {
 				l1a_state.l1_down = 0;
-			} else if(ch == SUNKBD_A && l1a_state.l1_down) {
+			} else if (ch == SUNKBD_A && l1a_state.l1_down) {
 				/* whee... */
 				batten_down_hatches();
 				/* Continue execution... */
@@ -517,16 +526,14 @@
 				return;
 			}
 			sunkbd_inchar(ch, regs);
-			do_queue_task = 0;
 			goto next_char;
 		}
-		if(info->cons_mouse) {
+		if (info->cons_mouse) {
 			sun_mouse_inbyte(ch, 0);
-			do_queue_task = 0;
 			goto next_char;
 		}
-		if(info->is_cons) {
-			if(ch == 0) {
+		if (info->is_cons) {
+			if (ch == 0) {
 				/* whee, break received */
 				batten_down_hatches();
 				/* Continue execution... */
@@ -540,32 +547,42 @@
 		 * documentation for remote target debugging and
 		 * arch/sparc/kernel/sparc-stub.c to see how all this works.
 		 */
-		if((info->kgdb_channel) && (ch =='\003')) {
+		if (info->kgdb_channel && (ch =='\003')) {
 			breakpoint();
 			return;
 		}
 #endif
-		if(!tty)
+		if (!tty)
 			return;
 
+		do_queue_task++;
+
 		if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 			break;
 
 		tty->flip.count++;
-		*tty->flip.flag_buf_ptr++ = 0;
+		if (r1 & PAR_ERR)
+			*tty->flip.flag_buf_ptr++ = TTY_PARITY;
+		else if (r1 & Rx_OVR)
+			*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
+		else if (r1 & CRC_ERR)
+			*tty->flip.flag_buf_ptr++ = TTY_FRAME;
+		else
+			*tty->flip.flag_buf_ptr++ = 0;
 		*tty->flip.char_buf_ptr++ = ch;
 
 	next_char:
-		/* Check if we have another character... */
-		stat = sbus_readb(&info->zs_channel->control);
-		ZSDELAY();
-		ZSLOG(REGCTRL, stat, 0);
-		if (!(stat & Rx_CH_AV))
-			break;
+		{
+			unsigned char stat;
 
-		/* ... and see if it is clean. */
-		stat = read_zsreg(info->zs_channel, R1);
-	} while (!(stat & (PAR_ERR | Rx_OVR | CRC_ERR)));
+			/* Check if we have another character... */
+			stat = sbus_readb(&info->zs_channel->control);
+			ZSDELAY();
+			ZSLOG(REGCTRL, stat, 0);
+			if (!(stat & Rx_CH_AV))
+				break;
+		}
+	}
 
 	if (do_queue_task != 0)
 		queue_task(&tty->flip.tqueue, &tq_timer);
@@ -582,7 +599,7 @@
 		return;
 	}
 
-	if((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) {
+	if ((info->xmit_cnt <= 0) || (tty != 0 && tty->stopped)) {
 		/* That's peculiar... */
 		sbus_writeb(RES_Tx_P, &info->zs_channel->control);
 		ZSDELAY();
@@ -599,7 +616,7 @@
 	if (info->xmit_cnt < WAKEUP_CHARS)
 		zs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
 
-	if(info->xmit_cnt <= 0) {
+	if (info->xmit_cnt <= 0) {
 		sbus_writeb(RES_Tx_P, &info->zs_channel->control);
 		ZSDELAY();
 		ZS_WSYNC(info->zs_channel);
@@ -621,14 +638,14 @@
 	ZS_WSYNC(info->zs_channel);
 	ZSLOG(REGCTRL, RES_EXT_INT, 1);
 #if 0
-	if(status & DCD) {
-		if((info->tty->termios->c_cflag & CRTSCTS) &&
-		   ((info->curregs[3] & AUTO_ENAB)==0)) {
+	if (status & DCD) {
+		if ((info->tty->termios->c_cflag & CRTSCTS) &&
+		    ((info->curregs[3] & AUTO_ENAB)==0)) {
 			info->curregs[3] |= AUTO_ENAB;
 			write_zsreg(info->zs_channel, 3, info->curregs[3]);
 		}
 	} else {
-		if((info->curregs[3] & AUTO_ENAB)) {
+		if ((info->curregs[3] & AUTO_ENAB)) {
 			info->curregs[3] &= ~AUTO_ENAB;
 			write_zsreg(info->zs_channel, 3, info->curregs[3]);
 		}
@@ -638,7 +655,7 @@
 	 * 'break asserted' status change interrupt, call
 	 * the boot prom.
 	 */
-	if(status & BRK_ABRT) {
+	if (status & BRK_ABRT) {
 		if (info->break_abort)
 			batten_down_hatches();
 		if (info->cons_mouse)
@@ -651,110 +668,49 @@
 	return;
 }
 
-static void special_receive(struct sun_serial *info)
-{
-	struct tty_struct *tty = info->tty;
-	unsigned char ch, stat;
-
-	stat = read_zsreg(info->zs_channel, R1);
-	if (stat & (PAR_ERR | Rx_OVR | CRC_ERR)) {
-		ch = sbus_readb(&info->zs_channel->data);
-		ZSDELAY();
-		ZSLOG(REGDATA, ch, 0);
-	}
-
-	if (!tty)
-		goto clear;
-
-	if (tty->flip.count >= TTY_FLIPBUF_SIZE)
-		goto done;
-
-	tty->flip.count++;
-	if(stat & PAR_ERR)
-		*tty->flip.flag_buf_ptr++ = TTY_PARITY;
-	else if(stat & Rx_OVR)
-		*tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-	else if(stat & CRC_ERR)
-		*tty->flip.flag_buf_ptr++ = TTY_FRAME;
-
-done:
-	queue_task(&tty->flip.tqueue, &tq_timer);
-clear:
-	sbus_writeb(ERR_RES, &info->zs_channel->control);
-	ZSDELAY();
-	ZS_WSYNC(info->zs_channel);
-	ZSLOG(REGCTRL, ERR_RES, 1);
-}
-
-
 /*
  * This is the serial driver's generic interrupt routine
  */
 void zs_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct sun_serial *info;
-	unsigned char zs_intreg;
 	int i;
 
 	info = (struct sun_serial *)dev_id;
 	ZSLOG(REGIRQ, 0, 0);
 	for (i = 0; i < NUM_SERIAL; i++) {
-		zs_intreg = read_zsreg(info->zs_next->zs_channel, 2);
-		zs_intreg &= STATUS_MASK;
-
-		/* NOTE: The read register 2, which holds the irq status,
-		 *       does so for both channels on each chip.  Although
-		 *       the status value itself must be read from the B
-		 *       channel and is only valid when read from channel B.
-		 *       When read from channel A, read register 2 contains
-		 *       the value written to write register 2.
-		 */
+		unsigned char r3 = read_zsreg(info->zs_channel, 3);
 
 		/* Channel A -- /dev/ttya or /dev/kbd, could be the console */
-		if (zs_intreg == CHA_Rx_AVAIL) {
-			receive_chars(info, regs);
-			return;
-		}
-		if(zs_intreg == CHA_Tx_EMPTY) {
-			transmit_chars(info);
-			return;
-		}
-		if (zs_intreg == CHA_EXT_STAT) {
-			status_handle(info);
-			return;
-		}
-		if (zs_intreg == CHA_SPECIAL) {
-			special_receive(info);
-			return;
+		if (r3 & (CHAEXT | CHATxIP | CHARxIP)) {
+			sbus_writeb(RES_H_IUS, &info->zs_channel->control);
+			ZSDELAY();
+			ZS_WSYNC(info->zs_channel);
+			ZSLOG(REGCTRL, RES_H_IUS, 1);
+			if (r3 & CHARxIP)
+				receive_chars(info, regs);
+			if (r3 & CHAEXT)
+				status_handle(info);
+			if (r3 & CHATxIP)
+				transmit_chars(info);
 		}
 
 		/* Channel B -- /dev/ttyb or /dev/mouse, could be the console */
-		if(zs_intreg == CHB_Rx_AVAIL) {
-			receive_chars(info->zs_next, regs);
-			return;
-		}
-		if(zs_intreg == CHB_Tx_EMPTY) {
-			transmit_chars(info->zs_next);
-			return;
+		info = info->zs_next;
+		if (r3 & (CHBEXT | CHBTxIP | CHBRxIP)) {
+			sbus_writeb(RES_H_IUS, &info->zs_channel->control);
+			ZSDELAY();
+			ZS_WSYNC(info->zs_channel);
+			ZSLOG(REGCTRL, RES_H_IUS, 1);
+			if (r3 & CHBRxIP)
+				receive_chars(info, regs);
+			if (r3 & CHBEXT)
+				status_handle(info);
+			if (r3 & CHBTxIP)
+				transmit_chars(info);
 		}
-		if (zs_intreg == CHB_EXT_STAT) {
-			status_handle(info->zs_next);
-			return;
-		}
-
-		/* NOTE: The default value for the IRQ status in read register
-		 *       2 in channel B is CHB_SPECIAL, so we need to look at
-		 *       read register 3 in channel A to check if this is a
-		 *       real interrupt, or just the default value.
-		 *       Yes... broken hardware...
-		 */
 
-		zs_intreg = read_zsreg(info->zs_channel, 3);
-		if (zs_intreg & CHBRxIP) {
-			special_receive(info->zs_next);
-			return;
-		}
-		info = info->zs_next->zs_next;
+		info = info->zs_next;
 	}
 }
 
@@ -1933,7 +1889,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.68 $";
+	char *revision = "$Revision: 1.68.2.1 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2469,8 +2425,7 @@
 	/* Grab IRQ line before poking the chips so we do
 	 * not lose any interrupts.
 	 */
-	if (request_irq(zilog_irq, zs_interrupt,
-			(SA_INTERRUPT | SA_STATIC_ALLOC),
+	if (request_irq(zilog_irq, zs_interrupt, SA_SHIRQ,
 			"Zilog8530", zs_chain)) {
 		prom_printf("Unable to attach zs intr\n");
 		prom_halt();
diff -urN linux-2.4.18-pre3/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- linux-2.4.18-pre3/drivers/sbus/sbus.c	Sun Mar 25 18:14:21 2001
+++ linux/drivers/sbus/sbus.c	Tue Jan 15 15:10:16 2002
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.95 2001/03/15 02:11:10 davem Exp $
+/* $Id: sbus.c,v 1.95.2.3 2002/01/05 01:12:31 davem Exp $
  * sbus.c:  SBus support routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -231,6 +231,7 @@
 				return;
 			}
 			regs[regnum].which_io = ranges[rngnum].ot_parent_space;
+			regs[regnum].phys_addr -= ranges[rngnum].ot_child_base;
 			regs[regnum].phys_addr += ranges[rngnum].ot_parent_base;
 		}
 	}
diff -urN linux-2.4.18-pre3/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- linux-2.4.18-pre3/drivers/scsi/fdomain.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/scsi/fdomain.c	Tue Jan 15 15:10:16 2002
@@ -729,13 +729,13 @@
       switch (Quantum) {
       case 2:			/* ISA_200S */
       case 3:			/* ISA_250MG */
-	 base = readb(bios_base + 0x1fa2) + (readb(bios_base + 0x1fa3) << 8);
+	 base = isa_readb(bios_base + 0x1fa2) + (isa_readb(bios_base + 0x1fa3) << 8);
 	 break;
       case 4:			/* ISA_200S (another one) */
-	 base = readb(bios_base + 0x1fa3) + (readb(bios_base + 0x1fa4) << 8);
+	 base = isa_readb(bios_base + 0x1fa3) + (isa_readb(bios_base + 0x1fa4) << 8);
 	 break;
       default:
-	 base = readb(bios_base + 0x1fcc) + (readb(bios_base + 0x1fcd) << 8);
+	 base = isa_readb(bios_base + 0x1fcc) + (isa_readb(bios_base + 0x1fcd) << 8);
 	 break;
       }
    
@@ -1955,7 +1955,7 @@
 	 offset = bios_base + 0x1f31 + drive * 25;
 	 break;
       }
-      memcpy_fromio( &i, offset, sizeof( struct drive_info ) );
+      isa_memcpy_fromio( &i, offset, sizeof( struct drive_info ) );
       info_array[0] = i.heads;
       info_array[1] = i.sectors;
       info_array[2] = i.cylinders;
diff -urN linux-2.4.18-pre3/drivers/scsi/i60uscsi.c linux/drivers/scsi/i60uscsi.c
--- linux-2.4.18-pre3/drivers/scsi/i60uscsi.c	Fri Nov  9 14:05:06 2001
+++ linux/drivers/scsi/i60uscsi.c	Tue Jan 15 15:10:16 2002
@@ -640,7 +640,6 @@
 	ULONG idx;
 	UCHAR index;
 	UCHAR i;
-	ULONG flags;
 
 	Ch = hcsp->HCS_Index;
 	for (i = 0; i < 8; i++) {
diff -urN linux-2.4.18-pre3/drivers/sound/aedsp16.c linux/drivers/sound/aedsp16.c
--- linux-2.4.18-pre3/drivers/sound/aedsp16.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/aedsp16.c	Tue Jan 15 15:10:16 2002
@@ -1,5 +1,5 @@
 /*
-   drivers/sound/lowlevel/aedsp16.c
+   drivers/sound/aedsp16.c
 
    Audio Excel DSP 16 software configuration routines
    Copyright (C) 1995,1996,1997,1998  Riccardo Facchetti (fizban@tin.it)
diff -urN linux-2.4.18-pre3/drivers/sound/btaudio.c linux/drivers/sound/btaudio.c
--- linux-2.4.18-pre3/drivers/sound/btaudio.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/sound/btaudio.c	Tue Jan 15 15:10:16 2002
@@ -885,6 +885,12 @@
 	}
 
 	bta = kmalloc(sizeof(*bta),GFP_ATOMIC);
+	if (!bta) {
+		printk(KERN_WARNING 
+		       "btaudio: not enough memory\n");
+		rc = -ENOMEM;
+		goto fail1;
+	}
 	memset(bta,0,sizeof(*bta));
 
 	bta->pci  = pci_dev;
diff -urN linux-2.4.18-pre3/drivers/sound/cs4281/cs4281_wrapper-24.c linux/drivers/sound/cs4281/cs4281_wrapper-24.c
--- linux-2.4.18-pre3/drivers/sound/cs4281/cs4281_wrapper-24.c	Wed Apr 18 11:49:11 2001
+++ linux/drivers/sound/cs4281/cs4281_wrapper-24.c	Wed Dec 31 16:00:00 1969
@@ -1,42 +0,0 @@
-/*******************************************************************************
-*
-*      "cs4281_wrapper.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
-*
-*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
-*            -- tom woller (twoller@crystal.cirrus.com) or
-*               (audio@crystal.cirrus.com).
-*
-*      This program is free software; you can redistribute it and/or modify
-*      it under the terms of the GNU General Public License as published by
-*      the Free Software Foundation; either version 2 of the License, or
-*      (at your option) any later version.
-*
-*      This program is distributed in the hope that it will be useful,
-*      but WITHOUT ANY WARRANTY; without even the implied warranty of
-*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-*      GNU General Public License for more details.
-*
-*      You should have received a copy of the GNU General Public License
-*      along with this program; if not, write to the Free Software
-*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*
-* 12/20/00 trw - new file. 
-*
-*******************************************************************************/
-
-#include <linux/spinlock.h>
-
-void cs4281_null(struct pci_dev *pcidev) { return; }
-#define cs4x_mem_map_reserve(page) mem_map_reserve(page)
-#define cs4x_mem_map_unreserve(page) mem_map_unreserve(page)
-
-#define free_dmabuf(state, dmabuf) \
-	pci_free_consistent(state->pcidev, \
-			    PAGE_SIZE << (dmabuf)->buforder, \
-			    (dmabuf)->rawbuf, (dmabuf)->dmaaddr);
-#define free_dmabuf2(state, dmabuf) \
-	pci_free_consistent((state)->pcidev, \
-				    PAGE_SIZE << (state)->buforder_tmpbuff, \
-				    (state)->tmpbuff, (state)->dmaaddr_tmpbuff);
-#define cs4x_pgoff(vma) ((vma)->vm_pgoff)
-
diff -urN linux-2.4.18-pre3/drivers/sound/cs4281/cs4281m.c linux/drivers/sound/cs4281/cs4281m.c
--- linux-2.4.18-pre3/drivers/sound/cs4281/cs4281m.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/cs4281/cs4281m.c	Tue Jan 15 15:10:16 2002
@@ -1,12 +1,12 @@
 /*******************************************************************************
 *
-*      "cs4281.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+*      "cs4281m.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
 *
 *      Copyright (C) 2000,2001  Cirrus Logic Corp.  
 *            -- adapted from drivers by Thomas Sailer, 
 *            -- but don't bug him; Problems should go to:
 *            -- tom woller (twoller@crystal.cirrus.com) or
-*               (audio@crystal.cirrus.com).
+*               (pcaudio@crystal.cirrus.com).
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
@@ -51,6 +51,18 @@
 * 12/21/00 trw - added fractional "defaultorder" inputs. if >100 then use 
 *		 defaultorder-100 as power of 2 for the buffer size. example:
 *		 106 = 2^(106-100) = 2^6 = 64 bytes for the buffer size.
+* 04/02/01 trw - reworked the includes, so kgdb wouldn't get confused.
+* 04/17/01 trw - added ifdef CONFIG_PM for 2.4.x non-pm kernels. static pmprint.
+* 04/19/01 trw - reworked all of the wrapper macros to keep native 2.4.x code
+*		 predominate in the driver.
+* 07/01/01 trw - added ability to modify the record source mask to alleviate
+*		 problems with toshiba systems.  also, check for toshiba 
+*		 system to set default up properly.
+* 11/12/01 trw - removed cs4281_update_ptr() in the polling interface code.
+*		 returning with only a few bytes available in the write buffer
+*		 seems to cause some problems with some apps (xmms OSS plugin).
+*		 Also, fixed bug in cs4281_update_ptr() code to wakeup when
+*	 	 1/2 buffer is empty, not when completely full.
 *
 *******************************************************************************/
 
@@ -77,13 +89,17 @@
 #include <linux/wrapper.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
-//#include "cs_dm.h"
 #include "cs4281_hwdefs.h"
-#include "cs4281pm.h"
 
-struct cs4281_state;
 EXPORT_NO_SYMBOLS;
 
+struct cs4281_state;
+int cs4281_suspend(struct cs4281_state *s);
+int cs4281_resume(struct cs4281_state *s);
+
+#include "cs4281_wrapper.h"
+#include "cs4281pm-24.h"
+
 static void stop_dac(struct cs4281_state *s);
 static void stop_adc(struct cs4281_state *s);
 static void start_dac(struct cs4281_state *s);
@@ -99,18 +115,40 @@
 #define PCI_DEVICE_ID_CRYSTAL_CS4281  0x6005
 #endif
 
+#ifndef SS_ID_TOSHIBA_1640CDT
+#define SS_ID_TOSHIBA_1640CDT	0xff00
+#endif
+
+#ifndef PCI_VENDOR_ID_TOSHIBA
+#define PCI_VENDOR_ID_TOSHIBA 	0x1179
+#endif
+
 #define CS4281_MAGIC  ((PCI_DEVICE_ID_CRYSTAL_CS4281<<16) | PCI_VENDOR_ID_CIRRUS)
 #define	CS4281_CFLR_DEFAULT	0x00000001  /* CFLR must be in AC97 link mode */
+#define CS4281_BA0_CPWR_DEFAULT 0x4281
 
-// buffer order determines the size of the dma buffer for the driver.
-// under Linux, a smaller buffer allows more responsiveness from many of the 
-// applications (e.g. games).  A larger buffer allows some of the apps (esound) 
-// to not underrun the dma buffer as easily.  As default, use 32k (order=3)
-// rather than 64k as some of the games work more responsively.
-// log base 2( buff sz = 32k).
+/* buffer order determines the size of the dma buffer for the driver.
+* under Linux, a smaller buffer allows more responsiveness from many of the 
+* applications (e.g. games).  A larger buffer allows some of the apps (esound) 
+* to not underrun the dma buffer as easily.  As default, use 32k (order=3)
+* rather than 64k as some of the games work more responsively.
+* (2^N) * PAGE_SIZE = allocated buffer size
+*
+* also added fractional "defaultorder" inputs. if >100 then use 
+* defaultorder-100 as power of 2 for the buffer size. example:
+* 106 = 2^(106-100) = 2^6 = 64 bytes for the buffer size.
+* games are even MORE responsive now, but prone to underruns.
+*/
 static unsigned long defaultorder = 3;
 MODULE_PARM(defaultorder, "i");
 
+/*
+* use this module parm to invalidate recording sources 
+* as on some machines (Toshiba Satellites... again) setting to LINE
+* causes an error and some of the mixers (gmix) to not load.
+*/
+static unsigned long recsrc_invalid = 0;
+MODULE_PARM(recsrc_invalid, "i");
 //
 // Turn on/off debugging compilation by commenting out "#define CSDEBUG"
 //
@@ -172,7 +210,7 @@
 #define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
 
 #define CS4281_MAJOR_VERSION 	1
-#define CS4281_MINOR_VERSION 	13
+#define CS4281_MINOR_VERSION 	30
 #ifdef __ia64__
 #define CS4281_ARCH	     	64	//architecture key
 #else
@@ -182,7 +220,6 @@
 #define CS_TYPE_ADC 0
 #define CS_TYPE_DAC 1
 
-
 static const char invalid_magic[] =
     KERN_CRIT "cs4281: invalid magic value\n";
 
@@ -194,16 +231,12 @@
         }                                         \
 })
 
-//LIST_HEAD(cs4281_devs);
 struct list_head cs4281_devs = { &cs4281_devs, &cs4281_devs };
 
-struct cs4281_state; 
-
-#include "cs4281_wrapper-24.c"
-
 struct cs4281_state {
 	// magic 
 	unsigned int magic;
+	u16 ss_id, ss_vendor;  /* subsystem and vendor IDs from pci space */
 
 	// we keep the cards in a linked list 
 	struct cs4281_state *next;
@@ -221,6 +254,7 @@
 	unsigned int pBA0phys, pBA1phys;
 	char *pBA0, *pBA1;
 	unsigned int irq;
+	unsigned recsrc;
 
 	// mixer registers 
 	struct {
@@ -291,12 +325,12 @@
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
 
+#ifndef NOT_CS4281_PM
 	struct cs4281_pm pm;
 	struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES];
+#endif
 };
 
-#include "cs4281pm-24.c"
-
 #if CSDEBUG
 
 // DEBUG ROUTINES
@@ -527,7 +561,13 @@
 static void delayus(struct cs4281_state *s, u32 delay)
 {
 	u32 j;
-	if ((delay > 9999) && (s->pm.flags & CS4281_PM_IDLE)) {
+	if ((delay > 9999) 
+#ifndef NOT_CS4281_PM
+	&& (s->pm.flags & CS4281_PM_IDLE))
+#else
+	)
+#endif
+	{
 		j = (delay * HZ) / 1000000;	/* calculate delay in jiffies  */
 		if (j < 1)
 			j = 1;	/* minimum one jiffy. */
@@ -578,7 +618,7 @@
 	       card->pBA0 + BA0_ACCTL);
 
 	// Wait for the read to occur.
-	for (count = 0; count < 10; count++) {
+	for (count = 0; count < 100; count++) {
 		// First, we want to wait for a short time.
 		udelay(25);
 
@@ -593,7 +633,7 @@
 		return 1;
 
 	// Wait for the valid status bit to go active.
-	for (count = 0; count < 10; count++) {
+	for (count = 0; count < 100; count++) {
 		// Read the AC97 status register.
 		// ACSTS = Status Register = 464h
 		status = readl(card->pBA0 + BA0_ACSTS);
@@ -703,12 +743,26 @@
 		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO 
 			"cs4281: cs4281_hw_init() CFLR invalid - resetting from 0x%x to 0x%x\n",
 				temp2,CS4281_CFLR_DEFAULT));
+		temp2 = readl(card->pBA0 + BA0_CWPR);
+		if(temp2 != CS4281_BA0_CPWR_DEFAULT)
+		{
+			writel(CS4281_BA0_CPWR_DEFAULT, card->pBA0 + BA0_CWPR);
+			temp2 = readl(card->pBA0 + BA0_CWPR);
+			if(temp2 != CS4281_BA0_CPWR_DEFAULT)
+			{
+			  CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO 
+				"cs4281: cs4281_hw_init() Invalid hardware - unable to configure CPWR (0x%x)\n",
+					temp2));
+			  return 1;
+			}
+		}
 		writel(CS4281_CFLR_DEFAULT, card->pBA0 + BA0_CFLR);
 		temp2 = readl(card->pBA0 + BA0_CFLR);
 		if(temp2 != CS4281_CFLR_DEFAULT)
 		{
 			CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO 
-				"cs4281: cs4281_hw_init() Invalid hardware - unable to configure CFLR\n"));
+				"cs4281: cs4281_hw_init() Invalid hardware - unable to configure CFLR (0x%x)\n",
+					temp2));
 			return 1;
 		}
 	}
@@ -1021,15 +1075,6 @@
 	int Count,i;
 
 	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_suspend()+\n"));
-/*
-* change the state, save the current hwptr, then stop the dac/adc
-*/
-	s->pm.flags &= ~CS4281_PM_IDLE;
-	s->pm.flags |= CS4281_PM_SUSPENDING;
-	s->pm.u32hwptr_playback = readl(s->pBA0 + BA0_DCA0);
-	s->pm.u32hwptr_capture = readl(s->pBA0 + BA0_DCA1);
-	stop_dac(s);
-	stop_adc(s);
 
 	for(Count = 0x2, i=0; (Count <= CS4281_AC97_HIGHESTREGTORESTORE)
 			&& (i < CS4281_AC97_NUMBER_RESTORE_REGS); 
@@ -1269,6 +1314,14 @@
 	pm->u32DacSR = readl(s->pBA0 + BA0_DACSR);
 	pm->u32AdcSR = readl(s->pBA0 + BA0_ADCSR);
 
+/*
+* save the current hwptr, then stop the dac/adc
+*/
+	pm->u32hwptr_playback = readl(s->pBA0 + BA0_DCA0);
+	pm->u32hwptr_capture = readl(s->pBA0 + BA0_DCA1);
+	stop_dac(s);
+	stop_adc(s);
+
 	//
 	// Loop through all of the PipeLines 
 	//
@@ -1582,9 +1635,9 @@
 #ifndef NOT_CS4281_PM
 	&& (s->pm.flags & CS4281_PM_IDLE))
 #else
-)
+	)
 #endif
- {
+	{
 		s->ena |= FMODE_WRITE;
 		temp1 = readl(s->pBA0 + BA0_DCR0) & ~DCRn_MSK;	// Clear DMA0 channel mask.
 		writel(temp1, s->pBA0 + BA0_DCR0);	// Start DMA'ing.
@@ -1640,7 +1693,7 @@
 #ifndef NOT_CS4281_PM
 	&& (s->pm.flags & CS4281_PM_IDLE))
 #else
-) 
+	) 
 #endif
 	{
 		if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) {
@@ -1689,7 +1742,7 @@
 
 // --------------------------------------------------------------------- 
 
-#define DMABUF_MINORDER 1	// ==> min buffer size = 8K.
+#define DMABUF_MINORDER 0	// ==> min buffer size = 8K.
 
 
 extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db)
@@ -1698,21 +1751,21 @@
 
 	if (db->rawbuf) {
 		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend =
-		    virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) -
-				 1);
+		mapend = virt_to_page(db->rawbuf + 
+			(PAGE_SIZE << db->buforder) - 1);
 		for (map = virt_to_page(db->rawbuf); map <= mapend; map++)
 			cs4x_mem_map_unreserve(map);
-		free_dmabuf(s, db);
+		pci_free_consistent(s->pcidev, PAGE_SIZE << db->buforder, 
+			    db->rawbuf, db->dmaaddr);
 	}
 	if (s->tmpbuff && (db->type == CS_TYPE_ADC)) {
 		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend =
-		    virt_to_page(s->tmpbuff +
-				 (PAGE_SIZE << s->buforder_tmpbuff) - 1);
+		mapend = virt_to_page(s->tmpbuff +
+			 (PAGE_SIZE << s->buforder_tmpbuff) - 1);
 		for (map = virt_to_page(s->tmpbuff); map <= mapend; map++)
 			cs4x_mem_map_unreserve(map);
-		free_dmabuf2(s, db);
+		pci_free_consistent(s->pcidev, PAGE_SIZE << s->buforder_tmpbuff,
+				    s->tmpbuff, s->dmaaddr_tmpbuff);
 	}
 	s->tmpbuff = NULL;
 	db->rawbuf = NULL;
@@ -1735,7 +1788,7 @@
 * check for order within limits, but do not overwrite value, check
 * later for a fractional defaultorder (i.e. 100+).
 */
-	if((defaultorder > 0) && (defaultorder < 12))
+	if((defaultorder >= 0) && (defaultorder < 12))
 		df = defaultorder;
 	else
 		df = 1;	
@@ -1744,7 +1797,7 @@
 		db->ready = db->mapped = 0;
 		for (order = df; order >= DMABUF_MINORDER; order--)
 			if ( (db->rawbuf = (void *) pci_alloc_consistent(
-				s->pcidev, PAGE_SIZE << order, &db-> dmaaddr)))
+				s->pcidev, PAGE_SIZE << order, &db->dmaaddr)))
 				    break;
 		if (!db->rawbuf) {
 			CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
@@ -1969,10 +2022,8 @@
 		if (s->dma_adc.count > s->dma_adc.dmasize)
 			s->dma_adc.count = s->dma_adc.dmasize;
 		if (s->dma_adc.mapped) {
-			if (s->dma_adc.count >=
-			    (signed) s->dma_adc.fragsize) wake_up(&s->
-								  dma_adc.
-								  wait);
+			if (s->dma_adc.count >= (signed) s->dma_adc.fragsize) 
+				wake_up(&s->dma_adc.wait);
 		} else {
 			if (s->dma_adc.count > 0)
 				wake_up(&s->dma_adc.wait);
@@ -2143,6 +2194,7 @@
 static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd,
 		       unsigned long arg)
 {
+	int return_mask=0;
 	// Index to mixer_src[] is value of AC97 Input Mux Select Reg.
 	// Value of array member is recording source Device ID Mask.
 	static const unsigned int mixer_src[8] = {
@@ -2307,9 +2359,14 @@
 					SOUND_MASK_SPEAKER, (int *) arg);
 
 		case SOUND_MIXER_RECMASK:	// Arg contains a bit for each supported recording source 
-			return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC |
+			return_mask = (((SOUND_MASK_LINE | SOUND_MASK_MIC |
 					SOUND_MASK_CD | SOUND_MASK_VOLUME |
-					SOUND_MASK_LINE1, (int *) arg);
+					SOUND_MASK_LINE1) ) & ~recsrc_invalid);
+
+			CS_DBGOUT(CS_PARMS, 6, printk(KERN_INFO
+				"cs4281: mixer_ioctl(): return_mask=0x%x recsrc_invalid=0x%x\n",
+					(unsigned)return_mask,(unsigned)recsrc_invalid));
+			return put_user(return_mask, (int *) arg);
 
 		case SOUND_MIXER_STEREODEVS:	// Mixer channels supporting stereo 
 			return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH |
@@ -2346,6 +2403,13 @@
 		i = hweight32(val);	// i = # bits on in val.
 		if (i != 1)	// One & only 1 bit must be on.
 			return 0;
+		if(val & recsrc_invalid)
+		{
+			CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
+				"cs4281: mixer_ioctl(): REC SOURCE select error - record source invalid on this system (0x%x)\n",
+					val));
+			return -EINVAL;
+		}
 		for (i = 0; i < sizeof(mixer_src) / sizeof(int); i++) {
 			if (val == mixer_src[i]) {
 				temp1 = (i << 8) | i;
@@ -2567,6 +2631,14 @@
 
 // --------------------------------------------------------------------- 
 
+static loff_t cs4281_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+
+// --------------------------------------------------------------------- 
+
 static int cs4281_open_mixdev(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
@@ -2622,7 +2694,7 @@
 //   Mixer file operations struct.
 // ******************************************************************************************
 static /*const */ struct file_operations cs4281_mixer_fops = {
-	llseek:no_llseek,
+	llseek:cs4281_llseek,
 	ioctl:cs4281_ioctl_mixdev,
 	open:cs4281_open_mixdev,
 	release:cs4281_release_mixdev,
@@ -2684,9 +2756,18 @@
 	int count;
 	unsigned tmo;
 
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: drain_dac()+\n"));
 	if (s->dma_dac.mapped)
+	{
+		CS_DBGOUT(CS_FUNCTION, 2,
+			  printk(KERN_INFO "cs4281: drain_dac()- (mmap) 0\n"));
+		return 0;
+	}
+	if (s->ena & FMODE_WRITE)
+		add_wait_queue(&s->dma_dac.wait, &wait);
+	else
 		return 0;
-	add_wait_queue(&s->dma_dac.wait, &wait);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		spin_lock_irqsave(&s->lock, flags);
@@ -2699,6 +2780,8 @@
 		if (nonblock) {
 			remove_wait_queue(&s->dma_dac.wait, &wait);
 			current->state = TASK_RUNNING;
+			CS_DBGOUT(CS_FUNCTION, 2,
+				  printk(KERN_INFO "cs4281: drain_dac()- -EBUSY\n"));
 			return -EBUSY;
 		}
 		tmo =
@@ -2714,7 +2797,13 @@
 	remove_wait_queue(&s->dma_dac.wait, &wait);
 	current->state = TASK_RUNNING;
 	if (signal_pending(current))
+	{
+		CS_DBGOUT(CS_FUNCTION, 2,
+			  printk(KERN_INFO "cs4281: drain_dac()- -ERESTARTSYS\n"));
 		return -ERESTARTSYS;
+	}
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: drain_dac()- 0\n"));
 	return 0;
 }
 
@@ -3051,6 +3140,9 @@
 	return ret;
 }
 
+/*
+* cs4281_poll(struct file *file, struct poll_table_struct *wait)
+*/
 
 static unsigned int cs4281_poll(struct file *file,
 				struct poll_table_struct *wait)
@@ -3061,7 +3153,7 @@
 	unsigned int mask = 0;
 
 	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
-		  printk(KERN_INFO "cs4281: cs4281_poll()+\n"));
+		  printk(KERN_INFO "cs4281: cs4281_poll()+ wait=0x%x\n", (unsigned)wait));
 	VALIDATE_STATE(s);
 	if (file->f_mode & FMODE_WRITE) {
 		CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
@@ -3070,17 +3162,17 @@
 		if(!s->dma_dac.ready && prog_dmabuf_dac(s))
 			return 0;
 		poll_wait(file, &s->dma_dac.wait, wait);
-	}
-	if (file->f_mode & FMODE_READ) {
+
+	} else if (file->f_mode & FMODE_READ) {
 		CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
 			  printk(KERN_INFO
 				 "cs4281: cs4281_poll() wait on FMODE_READ\n"));
-		if(!s->dma_dac.ready && prog_dmabuf_adc(s))
+		if(!s->dma_adc.ready && prog_dmabuf_adc(s))
 			return 0;
 		poll_wait(file, &s->dma_adc.wait, wait);
+
 	}
 	spin_lock_irqsave(&s->lock, flags);
-	cs4281_update_ptr(s,CS_FALSE);
 	if (file->f_mode & FMODE_WRITE) {
 		if (s->dma_dac.mapped) {
 			if (s->dma_dac.count >=
@@ -3139,7 +3231,7 @@
 //
 	db = &s->dma_dac;
 
-	if (cs4x_pgoff(vma) != 0)
+	if ((vma->vm_pgoff) != 0)
 		return -EINVAL;
 	size = vma->vm_end - vma->vm_start;
 	if (size > (PAGE_SIZE << db->buforder))
@@ -3408,7 +3500,7 @@
 		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)))
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s,CS_FALSE);
+		cs4281_update_ptr(s,CS_TRUE);
 		abinfo.fragsize = s->dma_dac.fragsize;
 		if (s->dma_dac.mapped)
 			abinfo.bytes = s->dma_dac.dmasize;
@@ -3431,7 +3523,7 @@
 		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
 			return val;
 		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s,CS_FALSE);
+		cs4281_update_ptr(s,CS_TRUE);
 		if (s->conversion) {
 			abinfo.fragsize = s->dma_adc.fragsize / 2;
 			abinfo.bytes = s->dma_adc.count / 2;
@@ -3459,7 +3551,7 @@
 		if(!s->dma_dac.ready && prog_dmabuf_dac(s))
 			return 0;
 		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s,CS_FALSE);
+		cs4281_update_ptr(s,CS_TRUE);
 		val = s->dma_dac.count;
 		spin_unlock_irqrestore(&s->lock, flags);
 		return put_user(val, (int *) arg);
@@ -3470,7 +3562,7 @@
 		if(!s->dma_adc.ready && prog_dmabuf_adc(s))
 			return 0;
 		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s,CS_FALSE);
+		cs4281_update_ptr(s,CS_TRUE);
 		cinfo.bytes = s->dma_adc.total_bytes;
 		if (s->dma_adc.mapped) {
 			cinfo.blocks =
@@ -3503,7 +3595,7 @@
 		if(!s->dma_dac.ready && prog_dmabuf_dac(s))
 			return 0;
 		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s,CS_FALSE);
+		cs4281_update_ptr(s,CS_TRUE);
 		cinfo.bytes = s->dma_dac.total_bytes;
 		if (s->dma_dac.mapped) {
 			cinfo.blocks =
@@ -3538,6 +3630,10 @@
 	case SNDCTL_DSP_SETFRAGMENT:
 		if (get_user(val, (int *) arg))
 			return -EFAULT;
+
+		CS_DBGOUT(CS_PARMS, 4, printk(KERN_INFO
+			"cs4281: cs4281_ioctl(): Attempt to set fragsize=%d fragnum=%d\n",
+				1 << (val & 0xffff), (val >> 16) & 0xffff  ));
 		return 0;	// Say OK, but do nothing.
 
 	case SNDCTL_DSP_SUBDIVIDE:
@@ -3739,7 +3835,7 @@
 //   Wave (audio) file operations struct.
 // ******************************************************************************************
 static /*const */ struct file_operations cs4281_audio_fops = {
-	llseek:no_llseek,
+	llseek:cs4281_llseek,
 	read:cs4281_read,
 	write:cs4281_write,
 	poll:cs4281_poll,
@@ -4088,7 +4184,7 @@
 //   Midi file operations struct.
 // ******************************************************************************************
 static /*const */ struct file_operations cs4281_midi_fops = {
-	llseek:no_llseek,
+	llseek:cs4281_llseek,
 	read:cs4281_midi_read,
 	write:cs4281_midi_write,
 	poll:cs4281_midi_poll,
@@ -4263,6 +4359,35 @@
 }
 #endif
 
+/*
+* ss_vendor and ss_id must be setup prior to calling this routine.
+* setup the invalid recording source bitmask,
+* and also return a valid default initialization value as
+* the return value;
+*/
+static int cs4281_setup_record_src(struct cs4281_state *s)
+{
+	if(s->ss_vendor == PCI_VENDOR_ID_TOSHIBA)
+	{
+		if(s->ss_id == SS_ID_TOSHIBA_1640CDT)
+		{
+			CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO
+			  "cs4281: cs4281_setup_record_src(): setting LINE invalid\n"));
+			recsrc_invalid |= SOUND_MASK_LINE;
+		}
+	}
+/*
+* only return a valid recsrc value here, default to something useful.
+*/
+	if(!(recsrc_invalid & SOUND_MASK_MIC))
+		return(SOUND_MASK_MIC);
+	else if(!(recsrc_invalid & SOUND_MASK_LINE))
+		return(SOUND_MASK_LINE);
+	else if(!(recsrc_invalid & SOUND_MASK_LINE1))
+		return(SOUND_MASK_LINE1);
+	return 0;
+}
+
 static int __devinit cs4281_probe(struct pci_dev *pcidev,
 				  const struct pci_device_id *pciid)
 {
@@ -4285,22 +4410,22 @@
 	}
 	if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM) ||
 	    !(pci_resource_flags(pcidev, 1) & IORESOURCE_MEM)) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			 "cs4281: probe()- Memory region not assigned\n"));
+ 		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+ 			 "cs4281: probe()- Memory region not assigned\n"));
 		return -ENODEV;
-	}
-	if (pcidev->irq == 0) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-			 "cs4281: probe() IRQ not assigned\n"));
+ 	}
+ 	if (pcidev->irq == 0) {
+ 		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+ 			 "cs4281: probe() IRQ not assigned\n"));
 		return -ENODEV;
-	}
+ 	}
 	dma_mask = 0xffffffff;	/* this enables playback and recording */
 	i = pci_set_dma_mask(pcidev, dma_mask);
 	if (i) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-		      "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n"));
+ 		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+ 		      "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n"));
 		return i;
-	}
+ 	}
 	if (!(s = kmalloc(sizeof(struct cs4281_state), GFP_KERNEL))) {
 		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
 		      "cs4281: probe() no memory for state struct.\n"));
@@ -4404,10 +4529,18 @@
 #endif
 
 	pci_set_master(pcidev);	// enable bus mastering 
+	pci_read_config_word(pcidev, PCI_SUBSYSTEM_VENDOR_ID, &s->ss_vendor);
+	pci_read_config_word(pcidev, PCI_SUBSYSTEM_ID, &s->ss_id);
+	printk(KERN_INFO "cs4281: Subsystem vendor/id (%04X:%04X) IRQ %d\n",
+		s->ss_vendor, s->ss_id, s->irq);
+	
+	if(!recsrc_invalid)
+		val = cs4281_setup_record_src(s);
+	else
+		val = SOUND_MASK_MIC;
 
 	fs = get_fs();
 	set_fs(KERNEL_DS);
-	val = SOUND_MASK_LINE;
 	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
 	for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) {
 		val = initvol[i].vol;
@@ -4455,7 +4588,7 @@
 	unregister_sound_midi(s->dev_midi);
 	iounmap(s->pBA1);
 	iounmap(s->pBA0);
-	pci_set_drvdata(pci_dev,NULL);
+	pci_set_drvdata(pci_dev, s);
 	list_del(&s->list);
 	kfree(s);
 	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
@@ -4494,6 +4627,12 @@
 	       CS4281_ARCH);
 	rtn = pci_module_init(&cs4281_pci_driver);
 
+	if(rtn == -ENODEV)
+	{
+		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk( 
+			"cs4281: Unable to locate any cs4281 device with valid IDs 0x%x-0x%x\n",
+				PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281));
+	}
 	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
 		  printk(KERN_INFO "cs4281: cs4281_init_module()- (%d)\n",rtn));
 	return rtn;
@@ -4510,7 +4649,7 @@
 }
 // --------------------------------------------------------------------- 
 
-MODULE_AUTHOR("gw boynton, audio@crystal.cirrus.com");
+MODULE_AUTHOR("gw boynton, pcaudio@crystal.cirrus.com");
 MODULE_DESCRIPTION("Cirrus Logic CS4281 Driver");
 MODULE_LICENSE("GPL");
 
@@ -4525,3 +4664,4 @@
 	return cs4281_init_module();
 }
 #endif
+#include "cs4281pm-24.c"
diff -urN linux-2.4.18-pre3/drivers/sound/cs4281/cs4281pm-24.c linux/drivers/sound/cs4281/cs4281pm-24.c
--- linux-2.4.18-pre3/drivers/sound/cs4281/cs4281pm-24.c	Sun Feb  4 10:05:29 2001
+++ linux/drivers/sound/cs4281/cs4281pm-24.c	Tue Jan 15 15:10:16 2002
@@ -4,7 +4,7 @@
 *
 *      Copyright (C) 2000,2001  Cirrus Logic Corp.  
 *            -- tom woller (twoller@crystal.cirrus.com) or
-*               (audio@crystal.cirrus.com).
+*               (pcaudio@crystal.cirrus.com).
 *
 *      This program is free software; you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
@@ -25,28 +25,44 @@
 *******************************************************************************/
 
 #ifndef NOT_CS4281_PM
-#include <linux/pm.h>
 
-#define cs_pm_register(a, b, c) pm_register((a), (b), (c));
-#define cs_pm_unregister_all(a) pm_unregister_all((a));
+#if CS4281_PCI_PM_SUPPORT_ENABLE
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,12)
+static int cs4281_suspend_tbl(struct pci_dev *pcidev, u32 unused)
+{
+	struct cs4281_state *s = pci_get_drvdata(pcidev);
+	cs4281_suspend(s);
+	return 0;
+}
 
-int cs4281_suspend(struct cs4281_state *s);
-int cs4281_resume(struct cs4281_state *s);
-/* 
-* for now (12/22/00) only enable the pm_register PM support.
-* allow these table entries to be null.
-#define CS4281_SUSPEND_TBL cs4281_suspend_tbl
-#define CS4281_RESUME_TBL cs4281_resume_tbl
-*/
-#define CS4281_SUSPEND_TBL cs4281_null
-#define CS4281_RESUME_TBL cs4281_null
+static int cs4281_resume_tbl(struct pci_dev *pcidev)
+{
+	struct cs4281_state *s = pci_get_drvdata(pcidev);
+	cs4281_resume(s);
+	return 0;
+}
+#else
+void cs4281_suspend_tbl(struct pci_dev *pcidev)
+{
+	struct cs4281_state *s = pci_get_drvdata(pcidev);
+	cs4281_suspend(s);
+	return;
+}
 
+void cs4281_resume_tbl(struct pci_dev *pcidev)
+{
+	struct cs4281_state *s = pci_get_drvdata(pcidev);
+	cs4281_resume(s);
+	return;
+}
+#endif
+#else
 int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
 {
 	struct cs4281_state *state;
 
-	CS_DBGOUT(CS_PM, 2, printk(KERN_INFO 
-		"cs4281: cs4281_pm_callback dev=0x%x rqst=0x%x state=%d\n",
+	CS_DBGOUT(CS_PM, 2, printk(
+		"cs4281: cs4281_pm_callback()+ dev=0x%x rqst=0x%x state=%d\n",
 			(unsigned)dev,(unsigned)rqst,(unsigned)data));
 	state = (struct cs4281_state *) dev->data;
 	if (state) {
@@ -73,12 +89,13 @@
 				break;
 		}
 	}
+	CS_DBGOUT(CS_PM, 2, printk("cs4281: cs4281_pm_callback()- 0\n"));
 
 	return 0;
 }
+#endif //#if CS4281_PCI_PM_SUPPORT_ENABLE
 
-#else /* CS4281_PM */
-#define CS4281_SUSPEND_TBL cs4281_null
-#define CS4281_RESUME_TBL cs4281_null
-#endif /* CS4281_PM */
-
+#else /* NOT_CS4281_PM */
+#define CS4281_SUSPEND_TBL cs4281_null_suspend
+#define CS4281_RESUME_TBL cs4281_null_resume
+#endif /* NOT_CS4281_PM */
diff -urN linux-2.4.18-pre3/drivers/sound/cs4281/cs4281pm-24.h linux/drivers/sound/cs4281/cs4281pm-24.h
--- linux-2.4.18-pre3/drivers/sound/cs4281/cs4281pm-24.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/cs4281pm-24.h	Tue Jan 15 15:10:16 2002
@@ -0,0 +1,67 @@
+/*******************************************************************************
+*
+*      "cs4281pm-24.h" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+*
+*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
+*            -- tom woller (twoller@crystal.cirrus.com) or
+*               (audio@crystal.cirrus.com).
+*
+*      This program is free software; you can redistribute it and/or modify
+*      it under the terms of the GNU General Public License as published by
+*      the Free Software Foundation; either version 2 of the License, or
+*      (at your option) any later version.
+*
+*      This program is distributed in the hope that it will be useful,
+*      but WITHOUT ANY WARRANTY; without even the implied warranty of
+*      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+*      GNU General Public License for more details.
+*
+*      You should have received a copy of the GNU General Public License
+*      along with this program; if not, write to the Free Software
+*      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*
+* 2001.04.05 trw - new file. 
+*
+*******************************************************************************/
+#ifndef NOT_CS4281_PM
+#include <linux/pm.h>
+#include <linux/config.h>
+#include "cs4281pm.h"
+
+//#define CS4281_PCI_PM_SUPPORT_ENABLE 1
+#if CS4281_PCI_PM_SUPPORT_ENABLE
+#define cs_pm_register(a, b, c) 0;
+#define cs_pm_unregister_all(a)
+/* 
+* for now (12/22/00) only enable the pm_register PM support.
+* allow these table entries to be null.
+*/
+#define CS4281_SUSPEND_TBL cs4281_suspend_tbl
+#define CS4281_RESUME_TBL cs4281_resume_tbl
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,12)
+static int cs4281_suspend_tbl(struct pci_dev *pcidev, u32 unused);
+static int cs4281_resume_tbl(struct pci_dev *pcidev);
+#else 
+void cs4281_suspend_tbl(struct pci_dev *pcidev);
+void cs4281_resume_tbl(struct pci_dev *pcidev);
+#endif //LINUX_VERSION
+#else //CS4281_PCI_PM_SUPPORT_ENABLE
+#ifdef CONFIG_PM
+int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data);
+#define cs_pm_register(a, b, c) pm_register((a), (b), (c));
+#define cs_pm_unregister_all(a) pm_unregister_all((a));
+#define CS4281_SUSPEND_TBL cs4281_null_suspend
+#define CS4281_RESUME_TBL cs4281_null_resume
+#else
+#define cs_pm_register(a, b, c) 0;
+#define cs_pm_unregister_all(a)
+#define CS4281_SUSPEND_TBL cs4281_null_suspend
+#define CS4281_RESUME_TBL cs4281_null_resume
+#endif //CONFIG_PM
+#endif //CS4281_PCI_PM_SUPPORT_ENABLE
+#else
+#define cs_pm_register(a, b, c) 0;
+#define cs_pm_unregister_all(a)
+#define CS4281_SUSPEND_TBL cs4281_null_suspend
+#define CS4281_RESUME_TBL cs4281_null_resume
+#endif //NOT_CS4281_PM
diff -urN linux-2.4.18-pre3/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c
--- linux-2.4.18-pre3/drivers/sound/cs46xx.c	Fri Dec 21 09:41:55 2001
+++ linux/drivers/sound/cs46xx.c	Tue Jan 15 15:10:16 2002
@@ -1910,11 +1910,8 @@
                                 break;
                         if (signal_pending(current))
                                 break;
-                        if (file->f_flags & O_NONBLOCK) {
-                                remove_wait_queue(&card->midi.owait, &wait);
-                                current->state = TASK_RUNNING;
-                                return -EBUSY;
-                        }                      
+                        if (file->f_flags & O_NONBLOCK)
+                        	break;
                         tmo = (count * HZ) / 3100;
                         if (!schedule_timeout(tmo ? : 1) && tmo)
                                 printk(KERN_DEBUG "cs46xx: midi timed out??\n");
@@ -5249,6 +5246,8 @@
 	{0x1681, 0x0052, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
 	{0x1681, 0x0053, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
 	{0x1681, 0x0054, "Hercules Game Theatre XP", amp_hercules, NULL, NULL},
+	{0x1681, 0xa010, "Hercules Fortissimo II", amp_none, NULL, NULL},
+	
 	/* Not sure if the 570 needs the clkrun hack */
 	{PCI_VENDOR_ID_IBM, 0x0132, "Thinkpad 570", amp_none, NULL, clkrun_hack},
 	{PCI_VENDOR_ID_IBM, 0x0153, "Thinkpad 600X/A20/T20", amp_none, NULL, clkrun_hack},
diff -urN linux-2.4.18-pre3/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- linux-2.4.18-pre3/drivers/sound/es1370.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/es1370.c	Tue Jan 15 15:10:17 2002
@@ -2484,12 +2484,8 @@
 				break;
 			if (signal_pending(current))
 				break;
-			if (file->f_flags & O_NONBLOCK) {
-				remove_wait_queue(&s->midi.owait, &wait);
-				set_current_state(TASK_RUNNING);
-				unlock_kernel();
-				return -EBUSY;
-			}
+			if (file->f_flags & O_NONBLOCK) 
+				break;
 			tmo = (count * HZ) / 3100;
 			if (!schedule_timeout(tmo ? : 1) && tmo)
 				DBG(printk(KERN_DEBUG "es1370: midi timed out??\n");)
diff -urN linux-2.4.18-pre3/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- linux-2.4.18-pre3/drivers/sound/es1371.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/es1371.c	Tue Jan 15 15:10:17 2002
@@ -2660,10 +2660,7 @@
 			if (signal_pending(current))
 				break;
 			if (file->f_flags & O_NONBLOCK) {
-				remove_wait_queue(&s->midi.owait, &wait);
-				set_current_state(TASK_RUNNING);
-				unlock_kernel();
-				return -EBUSY;
+				break;
 			}
 			tmo = (count * HZ) / 3100;
 			if (!schedule_timeout(tmo ? : 1) && tmo)
diff -urN linux-2.4.18-pre3/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- linux-2.4.18-pre3/drivers/sound/esssolo1.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/esssolo1.c	Tue Jan 15 15:10:17 2002
@@ -1967,12 +1967,8 @@
 				break;
 			if (signal_pending(current))
 				break;
-			if (file->f_flags & O_NONBLOCK) {
-				remove_wait_queue(&s->midi.owait, &wait);
-				set_current_state(TASK_RUNNING);
-				unlock_kernel();
-				return -EBUSY;
-			}
+			if (file->f_flags & O_NONBLOCK)
+				break;
 			tmo = (count * HZ) / 3100;
 			if (!schedule_timeout(tmo ? : 1) && tmo)
 				printk(KERN_DEBUG "solo1: midi timed out??\n");
diff -urN linux-2.4.18-pre3/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c
--- linux-2.4.18-pre3/drivers/sound/sb_audio.c	Fri Feb 16 16:02:37 2001
+++ linux/drivers/sound/sb_audio.c	Tue Jan 15 15:10:17 2002
@@ -602,8 +602,8 @@
 
 	if (speed > 0)
 	{
-		if (speed < 5000)	/* which of these */
-			speed = 4000;	/* is correct ??? */
+		if (speed < 5000)
+			speed = 5000;
 
 		if (speed > max_speed)
 			speed = max_speed;
diff -urN linux-2.4.18-pre3/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- linux-2.4.18-pre3/drivers/sound/sonicvibes.c	Sun Sep 30 12:26:08 2001
+++ linux/drivers/sound/sonicvibes.c	Tue Jan 15 15:10:17 2002
@@ -2226,12 +2226,8 @@
 				break;
 			if (signal_pending(current))
 				break;
-			if (file->f_flags & O_NONBLOCK) {
-				remove_wait_queue(&s->midi.owait, &wait);
-				set_current_state(TASK_RUNNING);
-				unlock_kernel();
-				return -EBUSY;
-			}
+			if (file->f_flags & O_NONBLOCK)
+				break;
 			tmo = (count * HZ) / 3100;
 			if (!schedule_timeout(tmo ? : 1) && tmo)
 				printk(KERN_DEBUG "sv: midi timed out??\n");
diff -urN linux-2.4.18-pre3/drivers/sound/trident.c linux/drivers/sound/trident.c
--- linux-2.4.18-pre3/drivers/sound/trident.c	Tue Nov 13 09:19:41 2001
+++ linux/drivers/sound/trident.c	Tue Jan 15 15:10:17 2002
@@ -187,6 +187,7 @@
 #define TRIDENT_STATE_MAGIC	0x63657373 /* "cess" */
 
 #define TRIDENT_DMA_MASK	0x3fffffff /* DMA buffer mask for pci_alloc_consist */
+#define ALI_DMA_MASK		0xffffffff /* ALI Tridents lack the 30-bit limitation */
 
 #define NR_HW_CH		32
 
@@ -3948,13 +3949,20 @@
 	u16 temp;
 	struct pci_dev *pci_dev_m1533 = NULL;
 	int rc = -ENODEV;
+	u64 dma_mask;
 
 	if (pci_enable_device(pci_dev))
 		goto out;
 
-	if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) {
+	if (pci_dev->device == PCI_DEVICE_ID_ALI_5451)
+		dma_mask = ALI_DMA_MASK;
+	else
+		dma_mask = TRIDENT_DMA_MASK;
+	if (pci_set_dma_mask(pci_dev, dma_mask)) {
 		printk(KERN_ERR "trident: architecture does not support"
-		       " 30bit PCI busmaster DMA\n");
+		       " %s PCI busmaster DMA\n",
+		       pci_dev->device == PCI_DEVICE_ID_ALI_5451 ?
+		       "32-bit" : "30-bit");
 		goto out;
 	}
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
diff -urN linux-2.4.18-pre3/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- linux-2.4.18-pre3/drivers/video/clgenfb.c	Mon Nov 19 15:19:42 2001
+++ linux/drivers/video/clgenfb.c	Tue Jan 15 15:10:17 2002
@@ -413,6 +413,7 @@
 static struct clgenfb_info boards[MAX_NUM_BOARDS];	/* the boards */
 
 static unsigned clgen_def_mode = 1;
+static int noaccel = 0;
 
 static int release_io_ports = 0;
 
@@ -1405,7 +1406,9 @@
 			break;
 
 		case BT_PICASSO4:
+#ifdef CONFIG_ZORRO
 			vga_wseq (fb_info->regs, CL_SEQRF, 0xb8);	/* ### INCOMPLETE!! */
+#endif
 /*          vga_wseq (fb_info->regs, CL_SEQR1F, 0x1c); */
 			break;
 
@@ -2748,6 +2751,23 @@
 
 	DPRINTK ("clgen: (RAM start set to: 0x%p)\n", fb_info->fbmem);
 
+	if (noaccel)
+	{
+		printk("clgen: disabling text acceleration support\n");
+#ifdef FBCON_HAS_CFB8
+		fbcon_clgen_8.bmove = fbcon_cfb8_bmove;
+		fbcon_clgen_8.clear = fbcon_cfb8_clear;
+#endif
+#ifdef FBCON_HAS_CFB16
+		fbcon_clgen_16.bmove = fbcon_cfb16_bmove;
+		fbcon_clgen_16.clear = fbcon_cfb16_clear;
+#endif
+#ifdef FBCON_HAS_CFB32
+		fbcon_clgen_32.bmove = fbcon_cfb32_bmove;
+		fbcon_clgen_32.clear = fbcon_cfb32_clear;
+#endif
+	}
+
 	init_vgachip (fb_info);
 
 	/* set up a few more things, register framebuffer driver etc */
@@ -2851,6 +2871,8 @@
 			if (strcmp (this_opt, s) == 0)
 				clgen_def_mode = i;
 		}
+		if (!strcmp(this_opt, "noaccel"))
+			noaccel = 1;
 	}
 	return 0;
 }
diff -urN linux-2.4.18-pre3/fs/block_dev.c linux/fs/block_dev.c
--- linux-2.4.18-pre3/fs/block_dev.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/block_dev.c	Tue Jan 15 15:10:18 2002
@@ -171,11 +171,15 @@
 
 static int __block_fsync(struct inode * inode)
 {
-	int ret;
+	int ret, err;
 
-	filemap_fdatasync(inode->i_mapping);
-	ret = sync_buffers(inode->i_rdev, 1);
-	filemap_fdatawait(inode->i_mapping);
+	ret = filemap_fdatasync(inode->i_mapping);
+	err = sync_buffers(inode->i_rdev, 1);
+	if (err && !ret)
+		ret = err;
+	err = filemap_fdatawait(inode->i_mapping);
+	if (err && !ret)
+		ret = err;
 
 	return ret;
 }
diff -urN linux-2.4.18-pre3/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.18-pre3/fs/buffer.c	Fri Dec 21 09:41:55 2001
+++ linux/fs/buffer.c	Tue Jan 15 15:10:18 2002
@@ -401,9 +401,9 @@
 	struct file * file;
 	struct dentry * dentry;
 	struct inode * inode;
-	int err;
+	int ret, err;
 
-	err = -EBADF;
+	ret = -EBADF;
 	file = fget(fd);
 	if (!file)
 		goto out;
@@ -411,21 +411,27 @@
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 
-	err = -EINVAL;
-	if (!file->f_op || !file->f_op->fsync)
+	ret = -EINVAL;
+	if (!file->f_op || !file->f_op->fsync) {
+		/* Why?  We can still call filemap_fdatasync */
 		goto out_putf;
+	}
 
 	/* We need to protect against concurrent writers.. */
 	down(&inode->i_sem);
-	filemap_fdatasync(inode->i_mapping);
+	ret = filemap_fdatasync(inode->i_mapping);
 	err = file->f_op->fsync(file, dentry, 0);
-	filemap_fdatawait(inode->i_mapping);
+	if (err && !ret)
+		ret = err;
+	err = filemap_fdatawait(inode->i_mapping);
+	if (err && !ret)
+		ret = err;
 	up(&inode->i_sem);
 
 out_putf:
 	fput(file);
 out:
-	return err;
+	return ret;
 }
 
 asmlinkage long sys_fdatasync(unsigned int fd)
@@ -433,9 +439,9 @@
 	struct file * file;
 	struct dentry * dentry;
 	struct inode * inode;
-	int err;
+	int ret, err;
 
-	err = -EBADF;
+	ret = -EBADF;
 	file = fget(fd);
 	if (!file)
 		goto out;
@@ -443,20 +449,24 @@
 	dentry = file->f_dentry;
 	inode = dentry->d_inode;
 
-	err = -EINVAL;
+	ret = -EINVAL;
 	if (!file->f_op || !file->f_op->fsync)
 		goto out_putf;
 
 	down(&inode->i_sem);
-	filemap_fdatasync(inode->i_mapping);
+	ret = filemap_fdatasync(inode->i_mapping);
 	err = file->f_op->fsync(file, dentry, 1);
-	filemap_fdatawait(inode->i_mapping);
+	if (err && !ret)
+		ret = err;
+	err = filemap_fdatawait(inode->i_mapping);
+	if (err && !ret)
+		ret = err;
 	up(&inode->i_sem);
 
 out_putf:
 	fput(file);
 out:
-	return err;
+	return ret;
 }
 
 /* After several hours of tedious analysis, the following hash
@@ -1512,6 +1522,7 @@
 	int err, i;
 	unsigned long block;
 	struct buffer_head *bh, *head;
+	int need_unlock;
 
 	if (!PageLocked(page))
 		BUG();
@@ -1567,8 +1578,34 @@
 	return 0;
 
 out:
+	/*
+	 * ENOSPC, or some other error.  We may already have added some
+	 * blocks to the file, so we need to write these out to avoid
+	 * exposing stale data.
+	 */
 	ClearPageUptodate(page);
-	UnlockPage(page);
+	bh = head;
+	need_unlock = 1;
+	/* Recovery: lock and submit the mapped buffers */
+	do {
+		if (buffer_mapped(bh)) {
+			lock_buffer(bh);
+			set_buffer_async_io(bh);
+			need_unlock = 0;
+		}
+		bh = bh->b_this_page;
+	} while (bh != head);
+	do {
+		struct buffer_head *next = bh->b_this_page;
+		if (buffer_mapped(bh)) {
+			set_bit(BH_Uptodate, &bh->b_state);
+			clear_bit(BH_Dirty, &bh->b_state);
+			submit_bh(WRITE, bh);
+		}
+		bh = next;
+	} while (bh != head);
+	if (need_unlock)
+		UnlockPage(page);
 	return err;
 }
 
@@ -1599,6 +1636,7 @@
 			continue;
 		if (block_start >= to)
 			break;
+		clear_bit(BH_New, &bh->b_state);
 		if (!buffer_mapped(bh)) {
 			err = get_block(inode, block, bh, 1);
 			if (err)
@@ -1633,12 +1671,34 @@
 	 */
 	while(wait_bh > wait) {
 		wait_on_buffer(*--wait_bh);
-		err = -EIO;
 		if (!buffer_uptodate(*wait_bh))
-			goto out;
+			return -EIO;
 	}
 	return 0;
 out:
+	/*
+	 * Zero out any newly allocated blocks to avoid exposing stale
+	 * data.  If BH_New is set, we know that the block was newly
+	 * allocated in the above loop.
+	 */
+	bh = head;
+	block_start = 0;
+	do {
+		block_end = block_start+blocksize;
+		if (block_end <= from)
+			continue;
+		if (block_start >= to)
+			break;
+		if (buffer_new(bh)) {
+			if (buffer_uptodate(bh))
+				printk(KERN_ERR "%s: zeroing uptodate buffer!\n", __FUNCTION__);
+			memset(kaddr+block_start, 0, bh->b_size);
+			set_bit(BH_Uptodate, &bh->b_state);
+			mark_buffer_dirty(bh);
+		}
+		block_start = block_end;
+		bh = bh->b_this_page;
+	} while (bh != head);
 	return err;
 }
 
diff -urN linux-2.4.18-pre3/fs/hpfs/super.c linux/fs/hpfs/super.c
--- linux-2.4.18-pre3/fs/hpfs/super.c	Thu Oct 25 00:02:26 2001
+++ linux/fs/hpfs/super.c	Tue Jan 15 15:10:18 2002
@@ -3,7 +3,7 @@
  *
  *  Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999
  *
- *  mouning, unmounting, error handling
+ *  mounting, unmounting, error handling
  */
 
 #include <linux/string.h>
diff -urN linux-2.4.18-pre3/fs/nfs/file.c linux/fs/nfs/file.c
--- linux-2.4.18-pre3/fs/nfs/file.c	Tue Jan 15 15:10:10 2002
+++ linux/fs/nfs/file.c	Tue Jan 15 15:10:18 2002
@@ -244,6 +244,7 @@
 {
 	struct inode * inode = filp->f_dentry->d_inode;
 	int	status = 0;
+	int	status2;
 
 	dprintk("NFS: nfs_lock(f=%4x/%ld, t=%x, fl=%x, r=%Ld:%Ld)\n",
 			inode->i_dev, inode->i_ino,
@@ -278,11 +279,15 @@
 	 * Flush all pending writes before doing anything
 	 * with locks..
 	 */
-	filemap_fdatasync(inode->i_mapping);
+	status = filemap_fdatasync(inode->i_mapping);
 	down(&inode->i_sem);
-	status = nfs_wb_all(inode);
+	status2 = nfs_wb_all(inode);
+	if (status2 && !status)
+		status = status2;
 	up(&inode->i_sem);
-	filemap_fdatawait(inode->i_mapping);
+	status2 = filemap_fdatawait(inode->i_mapping);
+	if (status2 && !status)
+		status = status2;
 	if (status < 0)
 		return status;
 
diff -urN linux-2.4.18-pre3/fs/nls/Config.in linux/fs/nls/Config.in
--- linux-2.4.18-pre3/fs/nls/Config.in	Wed Jun 27 17:10:55 2001
+++ linux/fs/nls/Config.in	Tue Jan 15 15:10:18 2002
@@ -43,6 +43,7 @@
   tristate 'Korean charset (CP949, EUC-KR)'        CONFIG_NLS_CODEPAGE_949
   tristate 'Thai charset (CP874, TIS-620)'         CONFIG_NLS_CODEPAGE_874
   tristate 'Hebrew charsets (ISO-8859-8, CP1255)'  CONFIG_NLS_ISO8859_8
+  tristate 'Windows CP1250 (Slavic/Central European Languages)' CONFIG_NLS_CODEPAGE_1250
   tristate 'Windows CP1251 (Bulgarian, Belarusian)' CONFIG_NLS_CODEPAGE_1251
   tristate 'NLS ISO 8859-1  (Latin 1; Western European Languages)' CONFIG_NLS_ISO8859_1
   tristate 'NLS ISO 8859-2  (Latin 2; Slavic/Central European Languages)' CONFIG_NLS_ISO8859_2
diff -urN linux-2.4.18-pre3/fs/nls/nls_cp1250.c linux/fs/nls/nls_cp1250.c
--- linux-2.4.18-pre3/fs/nls/nls_cp1250.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/nls/nls_cp1250.c	Tue Jan 15 15:10:18 2002
@@ -0,0 +1,365 @@
+/*
+ * linux/fs/nls_cp1250.c
+ *
+ * Charset cp1250 translation tables.
+ * Generated automatically from the Unicode and charset
+ * tables from the Unicode Organization (www.unicode.org).
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+#include <linux/errno.h>
+
+static wchar_t charset2uni[256] = {
+	/* 0x00*/
+	0x0000, 0x0001, 0x0002, 0x0003, 
+	0x0004, 0x0005, 0x0006, 0x0007, 
+	0x0008, 0x0009, 0x000a, 0x000b, 
+	0x000c, 0x000d, 0x000e, 0x000f, 
+	/* 0x10*/
+	0x0010, 0x0011, 0x0012, 0x0013, 
+	0x0014, 0x0015, 0x0016, 0x0017, 
+	0x0018, 0x0019, 0x001a, 0x001b, 
+	0x001c, 0x001d, 0x001e, 0x001f, 
+	/* 0x20*/
+	0x0020, 0x0021, 0x0022, 0x0023, 
+	0x0024, 0x0025, 0x0026, 0x0027, 
+	0x0028, 0x0029, 0x002a, 0x002b, 
+	0x002c, 0x002d, 0x002e, 0x002f, 
+	/* 0x30*/
+	0x0030, 0x0031, 0x0032, 0x0033, 
+	0x0034, 0x0035, 0x0036, 0x0037, 
+	0x0038, 0x0039, 0x003a, 0x003b, 
+	0x003c, 0x003d, 0x003e, 0x003f, 
+	/* 0x40*/
+	0x0040, 0x0041, 0x0042, 0x0043, 
+	0x0044, 0x0045, 0x0046, 0x0047, 
+	0x0048, 0x0049, 0x004a, 0x004b, 
+	0x004c, 0x004d, 0x004e, 0x004f, 
+	/* 0x50*/
+	0x0050, 0x0051, 0x0052, 0x0053, 
+	0x0054, 0x0055, 0x0056, 0x0057, 
+	0x0058, 0x0059, 0x005a, 0x005b, 
+	0x005c, 0x005d, 0x005e, 0x005f, 
+	/* 0x60*/
+	0x0060, 0x0061, 0x0062, 0x0063, 
+	0x0064, 0x0065, 0x0066, 0x0067, 
+	0x0068, 0x0069, 0x006a, 0x006b, 
+	0x006c, 0x006d, 0x006e, 0x006f, 
+	/* 0x70*/
+	0x0070, 0x0071, 0x0072, 0x0073, 
+	0x0074, 0x0075, 0x0076, 0x0077, 
+	0x0078, 0x0079, 0x007a, 0x007b, 
+	0x007c, 0x007d, 0x007e, 0x007f, 
+	/* 0x80*/
+	0x20ac, 0x0000, 0x201a, 0x0000, 
+	0x201e, 0x2026, 0x2020, 0x2021, 
+	0x0000, 0x2030, 0x0160, 0x2039, 
+	0x015a, 0x0164, 0x017d, 0x0179, 
+	/* 0x90*/
+	0x0000, 0x2018, 0x2019, 0x201c, 
+	0x201d, 0x2022, 0x2013, 0x2014, 
+	0x0000, 0x2122, 0x0161, 0x203a, 
+	0x015b, 0x0165, 0x017e, 0x017a, 
+	/* 0xa0*/
+	0x00a0, 0x02c7, 0x02d8, 0x0141, 
+	0x00a4, 0x0104, 0x00a6, 0x00a7, 
+	0x00a8, 0x00a9, 0x015e, 0x00ab, 
+	0x00ac, 0x00ad, 0x00ae, 0x017b, 
+	/* 0xb0*/
+	0x00b0, 0x00b1, 0x02db, 0x0142, 
+	0x00b4, 0x00b5, 0x00b6, 0x00b7, 
+	0x00b8, 0x0105, 0x015f, 0x00bb, 
+	0x013d, 0x02dd, 0x013e, 0x017c, 
+	/* 0xc0*/
+	0x0154, 0x00c1, 0x00c2, 0x0102, 
+	0x00c4, 0x0139, 0x0106, 0x00c7, 
+	0x010c, 0x00c9, 0x0118, 0x00cb, 
+	0x011a, 0x00cd, 0x00ce, 0x010e, 
+	/* 0xd0*/
+	0x0110, 0x0143, 0x0147, 0x00d3, 
+	0x00d4, 0x0150, 0x00d6, 0x00d7, 
+	0x0158, 0x016e, 0x00da, 0x0170, 
+	0x00dc, 0x00dd, 0x0162, 0x00df, 
+	/* 0xe0*/
+	0x0155, 0x00e1, 0x00e2, 0x0103, 
+	0x00e4, 0x013a, 0x0107, 0x00e7, 
+	0x010d, 0x00e9, 0x0119, 0x00eb, 
+	0x011b, 0x00ed, 0x00ee, 0x010f, 
+	/* 0xf0*/
+	0x0111, 0x0144, 0x0148, 0x00f3, 
+	0x00f4, 0x0151, 0x00f6, 0x00f7, 
+	0x0159, 0x016f, 0x00fa, 0x0171, 
+	0x00fc, 0x00fd, 0x0163, 0x02d9, 
+	};
+
+static unsigned char page00[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0xa0, 0x00, 0x00, 0x00, 0xa4, 0x00, 0xa6, 0xa7, /* 0xa0-0xa7 */
+	0xa8, 0xa9, 0x00, 0xab, 0xac, 0xad, 0xae, 0x00, /* 0xa8-0xaf */
+	0xb0, 0xb1, 0x00, 0x00, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+	0xb8, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+	0x00, 0xc1, 0xc2, 0x00, 0xc4, 0x00, 0x00, 0xc7, /* 0xc0-0xc7 */
+	0x00, 0xc9, 0x00, 0xcb, 0x00, 0xcd, 0xce, 0x00, /* 0xc8-0xcf */
+	0x00, 0x00, 0x00, 0xd3, 0xd4, 0x00, 0xd6, 0xd7, /* 0xd0-0xd7 */
+	0x00, 0x00, 0xda, 0x00, 0xdc, 0xdd, 0x00, 0xdf, /* 0xd8-0xdf */
+	0x00, 0xe1, 0xe2, 0x00, 0xe4, 0x00, 0x00, 0xe7, /* 0xe0-0xe7 */
+	0x00, 0xe9, 0x00, 0xeb, 0x00, 0xed, 0xee, 0x00, /* 0xe8-0xef */
+	0x00, 0x00, 0x00, 0xf3, 0xf4, 0x00, 0xf6, 0xf7, /* 0xf0-0xf7 */
+	0x00, 0x00, 0xfa, 0x00, 0xfc, 0xfd, 0x00, 0x00, /* 0xf8-0xff */
+	};
+
+static unsigned char page01[256] = {
+	0x00, 0x00, 0xc3, 0xe3, 0xa5, 0xb9, 0xc6, 0xe6, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0xc8, 0xe8, 0xcf, 0xef, /* 0x08-0x0f */
+	0xd0, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0xca, 0xea, 0xcc, 0xec, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0xc5, 0xe5, 0x00, 0x00, 0xbc, 0xbe, 0x00, /* 0x38-0x3f */
+	0x00, 0xa3, 0xb3, 0xd1, 0xf1, 0x00, 0x00, 0xd2, /* 0x40-0x47 */
+	0xf2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0xd5, 0xf5, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, /* 0x50-0x57 */
+	0xd8, 0xf8, 0x8c, 0x9c, 0x00, 0x00, 0xaa, 0xba, /* 0x58-0x5f */
+	0x8a, 0x9a, 0xde, 0xfe, 0x8d, 0x9d, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd9, 0xf9, /* 0x68-0x6f */
+	0xdb, 0xfb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0x00, 0x8f, 0x9f, 0xaf, 0xbf, 0x8e, 0x9e, 0x00, /* 0x78-0x7f */
+
+	};
+
+static unsigned char page02[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, /* 0xc0-0xc7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+	0xa2, 0xff, 0x00, 0xb2, 0x00, 0xbd, 0x00, 0x00, /* 0xd8-0xdf */
+	};
+
+static unsigned char page20[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x96, 0x97, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x91, 0x92, 0x82, 0x00, 0x93, 0x94, 0x84, 0x00, /* 0x18-0x1f */
+	0x86, 0x87, 0x95, 0x00, 0x00, 0x00, 0x85, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0x8b, 0x9b, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+	0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+	};
+
+static unsigned char page21[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	};
+
+static unsigned char *page_uni2charset[256] = {
+	page00,	page01,	page02,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	page20,	page21,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	};
+
+static unsigned char charset2lower[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x40-0x47 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x48-0x4f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x50-0x57 */
+	0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+	0x80, 0x00, 0x82, 0x00, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+	0x00, 0x89, 0x9a, 0x8b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x88-0x8f */
+	0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+	0x00, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* 0x98-0x9f */
+	0xa0, 0xa1, 0xa2, 0xb3, 0xa4, 0xb9, 0xa6, 0xa7, /* 0xa0-0xa7 */
+	0xa8, 0xa9, 0xba, 0xab, 0xac, 0xad, 0xae, 0xbf, /* 0xa8-0xaf */
+	0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+	0xb8, 0xb9, 0xba, 0xbb, 0xbe, 0xbd, 0xbe, 0xbf, /* 0xb8-0xbf */
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xc0-0xc7 */
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xc8-0xcf */
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xd7, /* 0xd0-0xd7 */
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xdf, /* 0xd8-0xdf */
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+	};
+
+static unsigned char charset2upper[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x60-0x67 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x68-0x6f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x70-0x77 */
+	0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+	0x80, 0x00, 0x82, 0x00, 0x84, 0x85, 0x86, 0x87, /* 0x80-0x87 */
+	0x00, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x88-0x8f */
+	0x00, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, /* 0x90-0x97 */
+	0x00, 0x99, 0x8a, 0x9b, 0x8c, 0x8d, 0x8e, 0x8f, /* 0x98-0x9f */
+	0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, /* 0xa0-0xa7 */
+	0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+	0xb0, 0xb1, 0xb2, 0xa3, 0xb4, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+	0xb8, 0xa5, 0xaa, 0xbb, 0xbc, 0xbd, 0xbc, 0xaf, /* 0xb8-0xbf */
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* 0xd8-0xdf */
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xe0-0xe7 */
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xe8-0xef */
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xf7, /* 0xf0-0xf7 */
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xff, /* 0xf8-0xff */
+	};
+
+static int uni2char(wchar_t uni, unsigned char *out, int boundlen)
+{
+        unsigned char *uni2charset;
+        unsigned char cl = uni & 0x00ff;
+        unsigned char ch = (uni & 0xff00) >> 8;
+
+        if (boundlen <= 0)
+                return -ENAMETOOLONG;
+
+        uni2charset = page_uni2charset[ch];
+        if (uni2charset && uni2charset[cl])
+                out[0] = uni2charset[cl];
+        else
+                return -EINVAL;
+        return 1;
+}
+
+static int char2uni(const unsigned char *rawstring, int boundlen, wchar_t *uni)
+{
+        *uni = charset2uni[*rawstring];
+        if (*uni == 0x0000)
+                return -EINVAL;
+        return 1;
+}
+
+static struct nls_table table = {
+        "cp1250",
+        uni2char,
+        char2uni,
+        charset2lower,
+        charset2upper,
+        THIS_MODULE,
+};
+
+static int __init init_nls_cp1250(void)
+{
+        return register_nls(&table);
+}
+static void __exit exit_nls_cp1250(void)
+{
+        unregister_nls(&table);
+}
+
+module_init(init_nls_cp1250)
+module_exit(exit_nls_cp1250)
+
+MODULE_LICENSE("BSD without advertising clause");
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * End:
+ */
+
diff -urN linux-2.4.18-pre3/fs/partitions/msdos.c linux/fs/partitions/msdos.c
--- linux-2.4.18-pre3/fs/partitions/msdos.c	Thu Oct 11 08:07:07 2001
+++ linux/fs/partitions/msdos.c	Tue Jan 15 15:10:18 2002
@@ -257,45 +257,43 @@
 #ifdef CONFIG_BSD_DISKLABEL
 static void
 check_and_add_bsd_partition(struct gendisk *hd, struct bsd_partition *bsd_p,
-	int minor, int *current_minor)
+	int baseminor, int *current_minor)
 {
-	struct hd_struct *lin_p;
-		/* check relative position of partitions.  */
-	for (lin_p = hd->part + 1 + minor;
-	     lin_p - hd->part - minor < *current_minor; lin_p++) {
-			/* no relationship -> try again */
-		if (lin_p->start_sect + lin_p->nr_sects <= le32_to_cpu(bsd_p->p_offset) ||
-		    lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size))
-			continue;	
-			/* equal -> no need to add */
-		if (lin_p->start_sect == le32_to_cpu(bsd_p->p_offset) && 
-			lin_p->nr_sects == le32_to_cpu(bsd_p->p_size)) 
-			return;
+	int i, bsd_start, bsd_size;
+
+	bsd_start = le32_to_cpu(bsd_p->p_offset);
+	bsd_size = le32_to_cpu(bsd_p->p_size);
+
+	/* check relative position of already allocated partitions */
+	for (i = baseminor+1; i < *current_minor; i++) {
+		int start = hd->part[i].start_sect;
+		int size = hd->part[i].nr_sects;
+
+		if (start+size <= bsd_start || start >= bsd_start+bsd_size)
+			continue;	/* no overlap */
+
+		if (start == bsd_start && size == bsd_size)
+			return;		/* equal -> no need to add */
+
+		if (start <= bsd_start && start+size >= bsd_start+bsd_size) {
 			/* bsd living within dos partition */
-		if (lin_p->start_sect <= le32_to_cpu(bsd_p->p_offset) && lin_p->start_sect 
-			+ lin_p->nr_sects >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(bsd_p->p_size)) {
 #ifdef DEBUG_BSD_DISKLABEL
 			printk("w: %d %ld+%ld,%d+%d", 
-				lin_p - hd->part, 
-				lin_p->start_sect, lin_p->nr_sects, 
-				le32_to_cpu(bsd_p->p_offset),
-				le32_to_cpu(bsd_p->p_size));
+			       i, start, size, bsd_start, bsd_size);
 #endif
-			break;
+			break;		/* ok */
 		}
-	 /* ouch: bsd and linux overlap. Don't even try for that partition */
+
+		/* ouch: bsd and linux overlap */
 #ifdef DEBUG_BSD_DISKLABEL
 		printk("???: %d %ld+%ld,%d+%d",
-			lin_p - hd->part, lin_p->start_sect, lin_p->nr_sects,
-			le32_to_cpu(bsd_p->p_offset), le32_to_cpu(bsd_p->p_size));
+		       i, start, size, bsd_start, bsd_size);
 #endif
 		printk("???");
 		return;
-	} /* if the bsd partition is not currently known to linux, we end
-	   * up here 
-	   */
-	add_gd_partition(hd, *current_minor, le32_to_cpu(bsd_p->p_offset),
-			 le32_to_cpu(bsd_p->p_size));
+	}
+
+	add_gd_partition(hd, *current_minor, bsd_start, bsd_size);
 	(*current_minor)++;
 }
 
@@ -311,6 +309,7 @@
 	struct bsd_disklabel *l;
 	struct bsd_partition *p;
 	int mask = (1 << hd->minor_shift) - 1;
+	int baseminor = (minor & ~mask);
 	char buf[40];
 
 	l = (struct bsd_disklabel *)read_dev_sector(bdev, offset+1, &sect);
@@ -320,7 +319,7 @@
 		put_dev_sector(sect);
 		return;
 	}
-	printk(" %s: <%s", partition_name(hd, minor, buf), name);
+	printk(" %s: <%s:", partition_name(hd, minor, buf), name);
 
 	if (le16_to_cpu(l->d_npartitions) < max_partitions)
 		max_partitions = le16_to_cpu(l->d_npartitions);
@@ -329,7 +328,7 @@
 			break;
 		if (p->p_fstype == BSD_FS_UNUSED) 
 			continue;
-		check_and_add_bsd_partition(hd, p, minor, current_minor);
+		check_and_add_bsd_partition(hd, p, baseminor, current_minor);
 	}
 	put_dev_sector(sect);
 	printk(" >\n");
diff -urN linux-2.4.18-pre3/fs/qnx4/inode.c linux/fs/qnx4/inode.c
--- linux-2.4.18-pre3/fs/qnx4/inode.c	Sun Sep 30 12:26:08 2001
+++ linux/fs/qnx4/inode.c	Tue Jan 15 15:10:18 2002
@@ -318,6 +318,10 @@
 					if (!strncmp(rootdir->di_fname, QNX4_BMNAME, sizeof QNX4_BMNAME)) {
 						found = 1;
 						sb->u.qnx4_sb.BitMap = kmalloc( sizeof( struct qnx4_inode_entry ), GFP_KERNEL );
+						if (!sb->u.qnx4_sb.BitMap) {
+							brelse (bh);
+							return "not enough memory for bitmap inode";
+						}
 						memcpy( sb->u.qnx4_sb.BitMap, rootdir, sizeof( struct qnx4_inode_entry ) );	/* keep bitmap inode known */
 						break;
 					}
diff -urN linux-2.4.18-pre3/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog
--- linux-2.4.18-pre3/fs/smbfs/ChangeLog	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/ChangeLog	Tue Jan 15 15:10:18 2002
@@ -1,5 +1,15 @@
 ChangeLog for smbfs.
 
+2001-12-31 René Scharfe <l.s.r@web.de>
+
+	* inode.c: added smb_show_options to show mount options in /proc/mounts
+	* inode.c, getopt.c, getopt.h: merged flag and has_arg in struct option
+	* inode.c: use S_IRWXUGO where appropriate
+
+2001-12-22 Urban Widmark <urban@teststation.com>
+
+	* file.c, proc.c: Fix problems triggered by the "fsx test"
+
 2001-09-17 Urban Widmark <urban@teststation.com>
 
 	* proc.c: Use 4096 (was 512) as the blocksize for better write
diff -urN linux-2.4.18-pre3/fs/smbfs/file.c linux/fs/smbfs/file.c
--- linux-2.4.18-pre3/fs/smbfs/file.c	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/file.c	Tue Jan 15 15:10:18 2002
@@ -270,7 +270,6 @@
 static int smb_prepare_write(struct file *file, struct page *page, 
 			     unsigned offset, unsigned to)
 {
-	kmap(page);
 	return 0;
 }
 
@@ -283,7 +282,6 @@
 	lock_kernel();
 	status = smb_updatepage(file, page, offset, to-offset);
 	unlock_kernel();
-	kunmap(page);
 	return status;
 }
 
@@ -349,8 +347,14 @@
 smb_file_release(struct inode *inode, struct file * file)
 {
 	lock_kernel();
-	if (!--inode->u.smbfs_i.openers)
+	if (!--inode->u.smbfs_i.openers) {
+		/* We must flush any dirty pages now as we won't be able to
+		   write anything after close. mmap can trigger this.
+		   "openers" should perhaps include mmap'ers ... */
+		filemap_fdatasync(inode->i_mapping);
+		filemap_fdatawait(inode->i_mapping);
 		smb_close(inode);
+	}
 	unlock_kernel();
 	return 0;
 }
diff -urN linux-2.4.18-pre3/fs/smbfs/getopt.c linux/fs/smbfs/getopt.c
--- linux-2.4.18-pre3/fs/smbfs/getopt.c	Fri Apr 27 14:10:32 2001
+++ linux/fs/smbfs/getopt.c	Tue Jan 15 15:10:18 2002
@@ -46,7 +46,7 @@
 
 	for (i = 0; opts[i].name != NULL; i++) {
 		if (!strcmp(opts[i].name, token)) {
-			if (opts[i].has_arg && (!val || !*val)) {
+			if (!opts[i].flag && (!val || !*val)) {
 				printk("%s: the %s option requires an argument\n",
 				       caller, token);
 				return -1;
diff -urN linux-2.4.18-pre3/fs/smbfs/getopt.h linux/fs/smbfs/getopt.h
--- linux-2.4.18-pre3/fs/smbfs/getopt.h	Mon Aug 14 13:31:10 2000
+++ linux/fs/smbfs/getopt.h	Tue Jan 15 15:10:18 2002
@@ -3,7 +3,6 @@
 
 struct option {
 	const char *name;
-	int has_arg;
 	unsigned long flag;
 	int val;
 };
diff -urN linux-2.4.18-pre3/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- linux-2.4.18-pre3/fs/smbfs/inode.c	Tue Oct  2 17:03:34 2001
+++ linux/fs/smbfs/inode.c	Tue Jan 15 15:10:18 2002
@@ -22,6 +22,7 @@
 #include <linux/dcache.h>
 #include <linux/smp_lock.h>
 #include <linux/nls.h>
+#include <linux/seq_file.h>
 
 #include <linux/smb_fs.h>
 #include <linux/smbno.h>
@@ -41,9 +42,12 @@
 #define SMB_NLS_REMOTE ""
 #endif
 
+#define SMB_TTL_DEFAULT 1000
+
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
 static int  smb_statfs(struct super_block *, struct statfs *);
+static int  smb_show_options(struct seq_file *, struct vfsmount *);
 
 static struct super_operations smb_sops =
 {
@@ -51,6 +55,7 @@
 	delete_inode:	smb_delete_inode,
 	put_super:	smb_put_super,
 	statfs:		smb_statfs,
+	show_options:	smb_show_options,
 };
 
 
@@ -259,21 +264,20 @@
 	clear_inode(ino);
 }
 
-/* FIXME: flags and has_arg could probably be merged. */
 static struct option opts[] = {
-	{ "version",	1, 0, 'v' },
-	{ "win95",	0, SMB_MOUNT_WIN95, 1 },
-	{ "oldattr",	0, SMB_MOUNT_OLDATTR, 1 },
-	{ "dirattr",	0, SMB_MOUNT_DIRATTR, 1 },
-	{ "case",	0, SMB_MOUNT_CASE, 1 },
-	{ "uid",	1, 0, 'u' },
-	{ "gid",	1, 0, 'g' },
-	{ "file_mode",	1, 0, 'f' },
-	{ "dir_mode",	1, 0, 'd' },
-	{ "iocharset",	1, 0, 'i' },
-	{ "codepage",	1, 0, 'c' },
-	{ "ttl",	1, 0, 't' },
-	{ NULL,		0, 0, 0}
+	{ "version",	0, 'v' },
+	{ "win95",	SMB_MOUNT_WIN95, 1 },
+	{ "oldattr",	SMB_MOUNT_OLDATTR, 1 },
+	{ "dirattr",	SMB_MOUNT_DIRATTR, 1 },
+	{ "case",	SMB_MOUNT_CASE, 1 },
+	{ "uid",	0, 'u' },
+	{ "gid",	0, 'g' },
+	{ "file_mode",	0, 'f' },
+	{ "dir_mode",	0, 'd' },
+	{ "iocharset",	0, 'i' },
+	{ "codepage",	0, 'c' },
+	{ "ttl",	0, 't' },
+	{ NULL,		0, 0}
 };
 
 static int
@@ -310,12 +314,10 @@
 			mnt->gid = value;
 			break;
 		case 'f':
-			mnt->file_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-			mnt->file_mode |= S_IFREG;
+			mnt->file_mode = (value & S_IRWXUGO) | S_IFREG;
 			break;
 		case 'd':
-			mnt->dir_mode = value & (S_IRWXU | S_IRWXG | S_IRWXO);
-			mnt->dir_mode |= S_IFDIR;
+			mnt->dir_mode = (value & S_IRWXUGO) | S_IFDIR;
 			break;
 		case 'i':
 			strncpy(mnt->codepage.local_name, optarg, 
@@ -338,6 +340,45 @@
 	return c;
 }
 
+/*
+ * smb_show_options() is for displaying mount options in /proc/mounts.
+ * It tries to avoid showing settings that were not changed from their
+ * defaults.
+ */
+static int
+smb_show_options(struct seq_file *s, struct vfsmount *m)
+{
+	struct smb_mount_data_kernel *mnt = m->mnt_sb->u.smbfs_sb.mnt;
+	int i;
+
+	for (i = 0; opts[i].name != NULL; i++)
+		if (mnt->flags & opts[i].flag)
+			seq_printf(s, ",%s", opts[i].name);
+
+	if (mnt->uid != 0)
+		seq_printf(s, ",uid=%d", mnt->uid);
+	if (mnt->gid != 0)
+		seq_printf(s, ",gid=%d", mnt->gid);
+	if (mnt->mounted_uid != 0)
+		seq_printf(s, ",mounted_uid=%d", mnt->mounted_uid);
+
+	/* 
+	 * Defaults for file_mode and dir_mode are unknown to us; they
+	 * depend on the current umask of the user doing the mount.
+	 */
+	seq_printf(s, ",file_mode=%04o", mnt->file_mode & S_IRWXUGO);
+	seq_printf(s, ",dir_mode=%04o", mnt->dir_mode & S_IRWXUGO);
+
+	if (strcmp(mnt->codepage.local_name, CONFIG_NLS_DEFAULT))
+		seq_printf(s, ",iocharset=%s", mnt->codepage.local_name);
+	if (strcmp(mnt->codepage.remote_name, SMB_NLS_REMOTE))
+		seq_printf(s, ",codepage=%s", mnt->codepage.remote_name);
+
+	if (mnt->ttl != SMB_TTL_DEFAULT)
+		seq_printf(s, ",ttl=%d", mnt->ttl);
+
+	return 0;
+}
 
 static void
 smb_put_super(struct super_block *sb)
@@ -425,7 +466,7 @@
 	strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
 		SMB_NLS_MAXNAMELEN);
 
-	mnt->ttl = 1000;
+	mnt->ttl = SMB_TTL_DEFAULT;
 	if (ver == SMB_MOUNT_OLDVERSION) {
 		mnt->version = oldmnt->version;
 
@@ -434,12 +475,8 @@
 		mnt->uid = oldmnt->uid;
 		mnt->gid = oldmnt->gid;
 
-		mnt->file_mode =
-			oldmnt->file_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-		mnt->dir_mode =
-			oldmnt->dir_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
-		mnt->file_mode |= S_IFREG;
-		mnt->dir_mode  |= S_IFDIR;
+		mnt->file_mode = (oldmnt->file_mode & S_IRWXUGO) | S_IFREG;
+		mnt->dir_mode = (oldmnt->dir_mode & S_IRWXUGO) | S_IFDIR;
 
 		mnt->flags = (oldmnt->file_mode >> 9);
 	} else {
@@ -510,7 +547,7 @@
 {
 	struct inode *inode = dentry->d_inode;
 	struct smb_sb_info *server = server_from_dentry(dentry);
-	unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
+	unsigned int mask = (S_IFREG | S_IFDIR | S_IRWXUGO);
 	int error, changed, refresh = 0;
 	struct smb_fattr fattr;
 
@@ -535,6 +572,10 @@
 		VERBOSE("changing %s/%s, old size=%ld, new size=%ld\n",
 			DENTRY_PATH(dentry),
 			(long) inode->i_size, (long) attr->ia_size);
+
+		filemap_fdatasync(inode->i_mapping);
+		filemap_fdatawait(inode->i_mapping);
+
 		error = smb_open(dentry, O_WRONLY);
 		if (error)
 			goto out;
diff -urN linux-2.4.18-pre3/include/asm-sparc/oplib.h linux/include/asm-sparc/oplib.h
--- linux-2.4.18-pre3/include/asm-sparc/oplib.h	Mon Aug 28 21:20:03 2000
+++ linux/include/asm-sparc/oplib.h	Tue Jan 15 15:10:18 2002
@@ -1,4 +1,4 @@
-/* $Id: oplib.h,v 1.21 2000/08/26 02:38:04 anton Exp $
+/* $Id: oplib.h,v 1.21.2.2 2001/12/21 00:52:47 davem Exp $
  * oplib.h:  Describes the interface and available routines in the
  *           Linux Prom library.
  *
@@ -298,15 +298,7 @@
 
 /* Dorking with Bus ranges... */
 
-/* Adjust reg values with the passed ranges. */
-extern void prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
-			     struct linux_prom_ranges *rangep, int nranges);
-
-/* Adjust child ranges with the passed parent ranges. */
-extern void prom_adjust_ranges(struct linux_prom_ranges *cranges, int ncranges,
-			       struct linux_prom_ranges *pranges, int npranges);
-
-/* Apply promlib probed OBIO ranges to registers. */
+/* Apply promlib probes OBIO ranges to registers. */
 extern void prom_apply_obio_ranges(struct linux_prom_registers *obioregs, int nregs);
 
 /* Apply ranges of any prom node (and optionally parent node as well) to registers. */
diff -urN linux-2.4.18-pre3/include/asm-sparc/string.h linux/include/asm-sparc/string.h
--- linux-2.4.18-pre3/include/asm-sparc/string.h	Wed May  3 01:47:57 2000
+++ linux/include/asm-sparc/string.h	Tue Jan 15 15:10:18 2002
@@ -1,4 +1,4 @@
-/* $Id: string.h,v 1.35 2000/05/02 01:47:01 davem Exp $
+/* $Id: string.h,v 1.35.2.1 2001/12/21 00:52:47 davem Exp $
  * string.h: External definitions for optimized assembly string
  *           routines for the Linux Kernel.
  *
@@ -126,9 +126,11 @@
 })
 
 #define __HAVE_ARCH_MEMCMP
+extern int memcmp(const void *,const void *,__kernel_size_t);
 
 /* Now the str*() stuff... */
 #define __HAVE_ARCH_STRLEN
+extern __kernel_size_t strlen(const char *);
 
 #define __HAVE_ARCH_STRNCMP
 
diff -urN linux-2.4.18-pre3/include/asm-sparc64/io.h linux/include/asm-sparc64/io.h
--- linux-2.4.18-pre3/include/asm-sparc64/io.h	Tue Nov 13 09:16:05 2001
+++ linux/include/asm-sparc64/io.h	Tue Jan 15 15:10:18 2002
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.40 2001/11/10 09:24:56 davem Exp $ */
+/* $Id: io.h,v 1.41.2.1 2001/12/11 22:50:52 davem Exp $ */
 #ifndef __SPARC64_IO_H
 #define __SPARC64_IO_H
 
@@ -18,6 +18,9 @@
 extern unsigned long bus_to_virt_not_defined_use_pci_map(volatile void *addr);
 #define bus_to_virt bus_to_virt_not_defined_use_pci_map
 
+extern unsigned long phys_base;
+#define page_to_phys(page)	((((page) - mem_map) << PAGE_SHIFT)+phys_base)
+
 /* Different PCI controllers we support have their PCI MEM space
  * mapped to an either 2GB (Psycho) or 4GB (Sabre) aligned area,
  * so need to chop off the top 33 or 32 bits.
@@ -252,6 +255,7 @@
 #define __raw_readb(__addr)		(_raw_readb((unsigned long)(__addr)))
 #define __raw_readw(__addr)		(_raw_readw((unsigned long)(__addr)))
 #define __raw_readl(__addr)		(_raw_readl((unsigned long)(__addr)))
+#define __raw_readq(__addr)		(_raw_readq((unsigned long)(__addr)))
 #define __raw_writeb(__b, __addr)	(_raw_writeb((u8)(__b), (unsigned long)(__addr)))
 #define __raw_writew(__w, __addr)	(_raw_writew((u16)(__w), (unsigned long)(__addr)))
 #define __raw_writel(__l, __addr)	(_raw_writel((u32)(__l), (unsigned long)(__addr)))
diff -urN linux-2.4.18-pre3/include/asm-sparc64/oplib.h linux/include/asm-sparc64/oplib.h
--- linux-2.4.18-pre3/include/asm-sparc64/oplib.h	Mon May 22 09:50:54 2000
+++ linux/include/asm-sparc64/oplib.h	Tue Jan 15 15:10:18 2002
@@ -1,4 +1,4 @@
-/* $Id: oplib.h,v 1.13 2000/05/09 17:40:15 davem Exp $
+/* $Id: oplib.h,v 1.13.2.1 2001/12/19 00:16:21 davem Exp $
  * oplib.h:  Describes the interface and available routines in the
  *           Linux Prom library.
  *
@@ -326,20 +326,6 @@
 /* Client interface level routines. */
 extern void prom_set_trap_table(unsigned long tba);
 
-/* Dorking with Bus ranges... */
-
-/* Adjust reg values with the passed ranges. */
-extern void prom_adjust_regs(struct linux_prom_registers *regp, int nregs,
-			     struct linux_prom_ranges *rangep, int nranges);
-
-/* Adjust child ranges with the passed parent ranges. */
-extern void prom_adjust_ranges(struct linux_prom_ranges *cranges, int ncranges,
-			       struct linux_prom_ranges *pranges, int npranges);
-
-/* Apply ranges of any prom node (and optionally parent node as well) to registers. */
-extern void prom_apply_generic_ranges(int node, int parent, 
-				      struct linux_prom_registers *sbusregs, int nregs);
-				      
 extern long p1275_cmd (char *, long, ...);
 				   
 
diff -urN linux-2.4.18-pre3/include/asm-sparc64/pgalloc.h linux/include/asm-sparc64/pgalloc.h
--- linux-2.4.18-pre3/include/asm-sparc64/pgalloc.h	Tue Oct 30 15:08:11 2001
+++ linux/include/asm-sparc64/pgalloc.h	Tue Jan 15 15:10:18 2002
@@ -35,8 +35,10 @@
 extern void flush_dcache_page_impl(struct page *page);
 #ifdef CONFIG_SMP
 extern void smp_flush_dcache_page_impl(struct page *page, int cpu);
+extern void flush_dcache_page_all(struct mm_struct *mm, struct page *page);
 #else
 #define smp_flush_dcache_page_impl(page,cpu) flush_dcache_page_impl(page)
+#define flush_dcache_page_all(mm,page) flush_dcache_page_impl(page)
 #endif
 
 extern void flush_dcache_page(struct page *page);
diff -urN linux-2.4.18-pre3/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.18-pre3/include/linux/fs.h	Fri Dec 21 09:42:03 2001
+++ linux/include/linux/fs.h	Tue Jan 15 15:10:18 2002
@@ -1212,8 +1212,8 @@
 extern int fsync_inode_buffers(struct inode *);
 extern int fsync_inode_data_buffers(struct inode *);
 extern int inode_has_buffers(struct inode *);
-extern void filemap_fdatasync(struct address_space *);
-extern void filemap_fdatawait(struct address_space *);
+extern int filemap_fdatasync(struct address_space *);
+extern int filemap_fdatawait(struct address_space *);
 extern void sync_supers(kdev_t);
 extern int bmap(struct inode *, int);
 extern int notify_change(struct dentry *, struct iattr *);
diff -urN linux-2.4.18-pre3/include/linux/highmem.h linux/include/linux/highmem.h
--- linux-2.4.18-pre3/include/linux/highmem.h	Fri Dec 21 09:42:03 2001
+++ linux/include/linux/highmem.h	Tue Jan 15 15:10:18 2002
@@ -56,17 +56,6 @@
 	kunmap(page);
 }
 
-static inline void memclear_highpage(struct page *page, unsigned int offset, unsigned int size)
-{
-	char *kaddr;
-
-	if (offset + size > PAGE_SIZE)
-		BUG();
-	kaddr = kmap(page);
-	memset(kaddr + offset, 0, size);
-	kunmap(page);
-}
-
 /*
  * Same but also flushes aliased cache contents to RAM.
  */
@@ -78,6 +67,7 @@
 		BUG();
 	kaddr = kmap(page);
 	memset(kaddr + offset, 0, size);
+	flush_dcache_page(page);
 	flush_page_to_ram(page);
 	kunmap(page);
 }
diff -urN linux-2.4.18-pre3/include/linux/if_arp.h linux/include/linux/if_arp.h
--- linux-2.4.18-pre3/include/linux/if_arp.h	Thu Nov 22 11:47:11 2001
+++ linux/include/linux/if_arp.h	Tue Jan 15 15:10:18 2002
@@ -82,6 +82,7 @@
 	/* 787->799 reserved for fibrechannel media types */
 #define ARPHRD_IEEE802_TR 800		/* Magic type ident for TR	*/
 #define ARPHRD_IEEE80211 801		/* IEEE 802.11			*/
+#define ARPHRD_IEEE80211_PRISM 802	/* IEEE 802.11 + Prism2 header  */
 
 #define ARPHRD_VOID	  0xFFFF	/* Void type, nothing is known */
 
diff -urN linux-2.4.18-pre3/include/linux/if_bonding.h linux/include/linux/if_bonding.h
--- linux-2.4.18-pre3/include/linux/if_bonding.h	Wed Nov  7 14:39:36 2001
+++ linux/include/linux/if_bonding.h	Tue Jan 15 15:10:18 2002
@@ -79,6 +79,15 @@
 	u32 link_failure_count;
 } slave_t;
 
+/*
+ * Here are the locking policies for the two bonding locks:
+ *
+ * 1) Get bond->lock when reading/writing slave list.
+ * 2) Get bond->ptrlock when reading/writing bond->current_slave.
+ *    (It is unnecessary when the write-lock is put with bond->lock.)
+ * 3) When we lock with bond->ptrlock, we must lock with bond->lock
+ *    beforehand.
+ */
 typedef struct bonding {
 	slave_t *next;
 	slave_t *prev;
diff -urN linux-2.4.18-pre3/include/linux/kdev_t.h linux/include/linux/kdev_t.h
--- linux-2.4.18-pre3/include/linux/kdev_t.h	Fri Feb 16 16:06:17 2001
+++ linux/include/linux/kdev_t.h	Tue Jan 15 15:10:18 2002
@@ -75,6 +75,14 @@
 
 extern const char * kdevname(kdev_t);	/* note: returns pointer to static data! */
 
+/* 2.5.x compatibility */
+
+#define mk_kdev(a,b) MKDEV(a,b)
+#define major(d) MAJOR(d)
+#define minor(d) MINOR(d)
+#define kdev_same(a,b) (a==b)
+#define kdev_none(d) (!d)
+
 /*
 As long as device numbers in the outside world have 16 bits only,
 we use these conversions.
diff -urN linux-2.4.18-pre3/include/linux/mii.h linux/include/linux/mii.h
--- linux-2.4.18-pre3/include/linux/mii.h	Thu Nov 22 11:48:09 2001
+++ linux/include/linux/mii.h	Tue Jan 15 15:10:18 2002
@@ -70,6 +70,8 @@
 #define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
 #define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
 
+#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
+			ADVERTISE_CSMA)
 #define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
                        ADVERTISE_100HALF | ADVERTISE_100FULL)
 
@@ -100,6 +102,27 @@
 #define NWAYTEST_RESV1          0x00ff  /* Unused...                   */
 #define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
 #define NWAYTEST_RESV2          0xfe00  /* Unused...                   */
+
+
+struct mii_if_info {
+	int phy_id;
+	int advertising;
+
+	unsigned int full_duplex : 1;
+	unsigned int duplex_lock : 1;
+
+	struct net_device *dev;
+	int (*mdio_read) (struct net_device *dev, int phy_id, int location);
+	void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
+};
+
+struct ethtool_cmd;
+
+int mii_link_ok (struct mii_if_info *mii);
+int mii_nway_restart (struct mii_if_info *mii);
+int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
+
 
 /* This structure is used in all SIOCxMIIxxx ioctl calls */
 struct mii_ioctl_data {
diff -urN linux-2.4.18-pre3/include/linux/netfilter_ipv4/ip_conntrack.h linux/include/linux/netfilter_ipv4/ip_conntrack.h
--- linux-2.4.18-pre3/include/linux/netfilter_ipv4/ip_conntrack.h	Tue Oct 30 15:08:12 2001
+++ linux/include/linux/netfilter_ipv4/ip_conntrack.h	Tue Jan 15 15:10:18 2002
@@ -27,6 +27,21 @@
 	IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
 };
 
+/* Bitset representing status of connection. */
+enum ip_conntrack_status {
+	/* It's an expected connection: bit 0 set.  This bit never changed */
+	IPS_EXPECTED_BIT = 0,
+	IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
+
+	/* We've seen packets both ways: bit 1 set.  Can be set, not unset. */
+	IPS_SEEN_REPLY_BIT = 1,
+	IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
+
+	/* Conntrack should never be early-expired. */
+	IPS_ASSURED_BIT = 2,
+	IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+};
+
 #ifdef __KERNEL__
 
 #include <linux/types.h>
@@ -46,21 +61,6 @@
 #else
 #define IP_NF_ASSERT(x)
 #endif
-
-/* Bitset representing status of connection. */
-enum ip_conntrack_status {
-	/* It's an expected connection: bit 0 set.  This bit never changed */
-	IPS_EXPECTED_BIT = 0,
-	IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
-
-	/* We've seen packets both ways: bit 1 set.  Can be set, not unset. */
-	IPS_SEEN_REPLY_BIT = 1,
-	IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
-
-	/* Conntrack should never be early-expired. */
-	IPS_ASSURED_BIT = 2,
-	IPS_ASSURED = (1 << IPS_ASSURED_BIT),
-};
 
 struct ip_conntrack_expect
 {
diff -urN linux-2.4.18-pre3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h
--- linux-2.4.18-pre3/include/linux/netfilter_ipv4/ip_conntrack_tuple.h	Thu Jul 26 13:58:26 2001
+++ linux/include/linux/netfilter_ipv4/ip_conntrack_tuple.h	Tue Jan 15 15:10:18 2002
@@ -62,6 +62,13 @@
 	} dst;
 };
 
+enum ip_conntrack_dir
+{
+	IP_CT_DIR_ORIGINAL,
+	IP_CT_DIR_REPLY,
+	IP_CT_DIR_MAX
+};
+
 #ifdef __KERNEL__
 
 #define DUMP_TUPLE(tp)						\
@@ -75,13 +82,19 @@
 /* If we're the first tuple, it's the original dir. */
 #define DIRECTION(h) ((enum ip_conntrack_dir)(&(h)->ctrack->tuplehash[1] == (h)))
 
-enum ip_conntrack_dir
+/* Connections have two entries in the hash table: one for each way */
+struct ip_conntrack_tuple_hash
 {
-	IP_CT_DIR_ORIGINAL,
-	IP_CT_DIR_REPLY,
-	IP_CT_DIR_MAX
+	struct list_head list;
+
+	struct ip_conntrack_tuple tuple;
+
+	/* this == &ctrack->tuplehash[DIRECTION(this)]. */
+	struct ip_conntrack *ctrack;
 };
 
+#endif /* __KERNEL__ */
+
 static inline int ip_ct_tuple_src_equal(const struct ip_conntrack_tuple *t1,
 				        const struct ip_conntrack_tuple *t2)
 {
@@ -115,16 +128,4 @@
 		     & mask->dst.protonum));
 }
 
-/* Connections have two entries in the hash table: one for each way */
-struct ip_conntrack_tuple_hash
-{
-	struct list_head list;
-
-	struct ip_conntrack_tuple tuple;
-
-	/* this == &ctrack->tuplehash[DIRECTION(this)]. */
-	struct ip_conntrack *ctrack;
-};
-
-#endif /* __KERNEL__ */
 #endif /* _IP_CONNTRACK_TUPLE_H */
diff -urN linux-2.4.18-pre3/include/linux/sysrq.h linux/include/linux/sysrq.h
--- linux-2.4.18-pre3/include/linux/sysrq.h	Sun Sep 30 12:26:42 2001
+++ linux/include/linux/sysrq.h	Tue Jan 15 15:10:18 2002
@@ -10,6 +10,8 @@
  *	overhauled to use key registration
  *	based upon discusions in irc://irc.openprojects.net/#kernelnewbies
  */
+#ifndef __LINUX_SYSRQ_H__
+#define __LINUX_SYSRQ_H__
 
 #include <linux/config.h>
 
@@ -117,3 +119,5 @@
 #else
 #define CHECK_EMERGENCY_SYNC
 #endif
+
+#endif /* __LINUX_SYSRQ_H__ */
diff -urN linux-2.4.18-pre3/include/math-emu/double.h linux/include/math-emu/double.h
--- linux-2.4.18-pre3/include/math-emu/double.h	Thu Dec  2 15:28:54 1999
+++ linux/include/math-emu/double.h	Tue Jan 15 15:10:18 2002
@@ -22,6 +22,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef    __MATH_EMU_DOUBLE_H__
+#define    __MATH_EMU_DOUBLE_H__
+
 #if _FP_W_TYPE_SIZE < 32
 #error "Here's a nickel kid.  Go buy yourself a real computer."
 #endif
@@ -197,3 +200,6 @@
 #define _FP_FRAC_HIGH_RAW_D(X)	_FP_FRAC_HIGH_1(X)
 
 #endif /* W_TYPE_SIZE < 64 */
+
+
+#endif /* __MATH_EMU_DOUBLE_H__ */
diff -urN linux-2.4.18-pre3/include/math-emu/extended.h linux/include/math-emu/extended.h
--- linux-2.4.18-pre3/include/math-emu/extended.h	Thu Dec  2 15:28:54 1999
+++ linux/include/math-emu/extended.h	Tue Jan 15 15:10:18 2002
@@ -19,6 +19,10 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+
+#ifndef    __MATH_EMU_EXTENDED_H__
+#define    __MATH_EMU_EXTENDED_H__
+
 #if _FP_W_TYPE_SIZE < 32
 #error "Here's a nickel, kid. Go buy yourself a real computer."
 #endif
@@ -388,3 +392,5 @@
 #define _FP_FRAC_HIGH_RAW_E(X)	(X##_f0)
 
 #endif /* not _FP_W_TYPE_SIZE < 64 */
+
+#endif /* __MATH_EMU_EXTENDED_H__ */
diff -urN linux-2.4.18-pre3/include/math-emu/op-1.h linux/include/math-emu/op-1.h
--- linux-2.4.18-pre3/include/math-emu/op-1.h	Mon Dec 20 22:05:52 1999
+++ linux/include/math-emu/op-1.h	Tue Jan 15 15:10:18 2002
@@ -22,6 +22,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef    __MATH_EMU_OP_1_H__
+#define    __MATH_EMU_OP_1_H__
+
 #define _FP_FRAC_DECL_1(X)	_FP_W_TYPE X##_f
 #define _FP_FRAC_COPY_1(D,S)	(D##_f = S##_f)
 #define _FP_FRAC_SET_1(X,I)	(X##_f = I)
@@ -295,3 +298,5 @@
     else								\
       D##_f <<= _FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs;		\
   } while (0)
+
+#endif /* __MATH_EMU_OP_1_H__ */
diff -urN linux-2.4.18-pre3/include/math-emu/op-2.h linux/include/math-emu/op-2.h
--- linux-2.4.18-pre3/include/math-emu/op-2.h	Mon Feb 19 11:36:34 2001
+++ linux/include/math-emu/op-2.h	Tue Jan 15 15:10:18 2002
@@ -22,6 +22,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef __MATH_EMU_OP_2_H__
+#define __MATH_EMU_OP_2_H__
+
 #define _FP_FRAC_DECL_2(X)	_FP_W_TYPE X##_f0, X##_f1
 #define _FP_FRAC_COPY_2(D,S)	(D##_f0 = S##_f0, D##_f1 = S##_f1)
 #define _FP_FRAC_SET_2(X,I)	__FP_FRAC_SET_2(X, I)
@@ -606,3 +609,4 @@
     _FP_FRAC_SLL_2(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
   } while (0)
 
+#endif
diff -urN linux-2.4.18-pre3/include/math-emu/op-4.h linux/include/math-emu/op-4.h
--- linux-2.4.18-pre3/include/math-emu/op-4.h	Tue Aug 31 11:24:24 1999
+++ linux/include/math-emu/op-4.h	Tue Jan 15 15:10:18 2002
@@ -22,6 +22,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef __MATH_EMU_OP_4_H__
+#define __MATH_EMU_OP_4_H__
+
 #define _FP_FRAC_DECL_4(X)	_FP_W_TYPE X##_f[4]
 #define _FP_FRAC_COPY_4(D,S)			\
   (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1],	\
@@ -659,3 +662,4 @@
      _FP_FRAC_SLL_4(D, (_FP_WFRACBITS_##dfs - _FP_WFRACBITS_##sfs));	\
    } while (0)
 
+#endif
diff -urN linux-2.4.18-pre3/include/math-emu/op-8.h linux/include/math-emu/op-8.h
--- linux-2.4.18-pre3/include/math-emu/op-8.h	Tue Aug 31 11:24:24 1999
+++ linux/include/math-emu/op-8.h	Tue Jan 15 15:10:18 2002
@@ -21,6 +21,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef __MATH_EMU_OP_8_H__
+#define __MATH_EMU_OP_8_H__
+
 /* We need just a few things from here for op-4, if we ever need some
    other macros, they can be added. */
 #define _FP_FRAC_DECL_8(X)	_FP_W_TYPE X##_f[8]
@@ -101,3 +104,4 @@
     X##_f[0] |= (_s != 0);						\
   } while (0)
 
+#endif
diff -urN linux-2.4.18-pre3/include/math-emu/op-common.h linux/include/math-emu/op-common.h
--- linux-2.4.18-pre3/include/math-emu/op-common.h	Thu Dec  2 15:28:54 1999
+++ linux/include/math-emu/op-common.h	Tue Jan 15 15:10:18 2002
@@ -21,6 +21,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef __MATH_EMU_OP_COMMON_H__
+#define __MATH_EMU_OP_COMMON_H__
+
 #define _FP_DECL(wc, X)			\
   _FP_I_TYPE X##_c, X##_s, X##_e;	\
   _FP_FRAC_DECL_##wc(X)
@@ -846,3 +849,4 @@
     q = n / d, r = n % d;			\
   } while (0)
 
+#endif /* __MATH_EMU_OP_COMMON_H__ */
diff -urN linux-2.4.18-pre3/include/math-emu/quad.h linux/include/math-emu/quad.h
--- linux-2.4.18-pre3/include/math-emu/quad.h	Thu Dec  2 15:28:54 1999
+++ linux/include/math-emu/quad.h	Tue Jan 15 15:10:18 2002
@@ -22,6 +22,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef  __MATH_EMU_QUAD_H__
+#define  __MATH_EMU_QUAD_H__
+
 #if _FP_W_TYPE_SIZE < 32
 #error "Here's a nickel, kid. Go buy yourself a real computer."
 #endif
@@ -201,3 +204,5 @@
 #define _FP_FRAC_HIGH_RAW_Q(X)	_FP_FRAC_HIGH_2(X)
 
 #endif /* not _FP_W_TYPE_SIZE < 64 */
+
+#endif /* __MATH_EMU_QUAD_H__ */
diff -urN linux-2.4.18-pre3/include/math-emu/single.h linux/include/math-emu/single.h
--- linux-2.4.18-pre3/include/math-emu/single.h	Thu Dec  2 15:28:54 1999
+++ linux/include/math-emu/single.h	Tue Jan 15 15:10:18 2002
@@ -22,6 +22,9 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
+#ifndef    __MATH_EMU_SINGLE_H__
+#define    __MATH_EMU_SINGLE_H__
+
 #if _FP_W_TYPE_SIZE < 32
 #error "Here's a nickel kid.  Go buy yourself a real computer."
 #endif
@@ -109,3 +112,5 @@
 
 #define _FP_FRAC_HIGH_S(X)	_FP_FRAC_HIGH_1(X)
 #define _FP_FRAC_HIGH_RAW_S(X)	_FP_FRAC_HIGH_1(X)
+
+#endif /* __MATH_EMU_SINGLE_H__ */
diff -urN linux-2.4.18-pre3/include/math-emu/soft-fp.h linux/include/math-emu/soft-fp.h
--- linux-2.4.18-pre3/include/math-emu/soft-fp.h	Thu Dec  2 15:28:54 1999
+++ linux/include/math-emu/soft-fp.h	Tue Jan 15 15:10:18 2002
@@ -21,8 +21,8 @@
    not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-#ifndef SOFT_FP_H
-#define SOFT_FP_H
+#ifndef __MATH_EMU_SOFT_FP_H__
+#define __MATH_EMU_SOFT_FP_H__
 
 #include <asm/sfp-machine.h>
 
@@ -178,4 +178,4 @@
 #include <stdlib/longlong.h>
 #endif
 
-#endif
+#endif /* __MATH_EMU_SOFT_FP_H__ */
diff -urN linux-2.4.18-pre3/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.18-pre3/kernel/ksyms.c	Tue Jan 15 15:10:10 2002
+++ linux/kernel/ksyms.c	Tue Jan 15 15:10:18 2002
@@ -208,7 +208,6 @@
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(generic_block_bmap);
-EXPORT_SYMBOL(waitfor_one_page);
 EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(do_generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
diff -urN linux-2.4.18-pre3/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.18-pre3/mm/filemap.c	Tue Jan 15 15:10:10 2002
+++ linux/mm/filemap.c	Tue Jan 15 15:10:18 2002
@@ -582,8 +582,9 @@
  *      @mapping: address space structure to write
  *
  */
-void filemap_fdatasync(struct address_space * mapping)
+int filemap_fdatasync(struct address_space * mapping)
 {
+	int ret = 0;
 	int (*writepage)(struct page *) = mapping->a_ops->writepage;
 
 	spin_lock(&pagecache_lock);
@@ -603,8 +604,11 @@
 		lock_page(page);
 
 		if (PageDirty(page)) {
+			int err;
 			ClearPageDirty(page);
-			writepage(page);
+			err = writepage(page);
+			if (err && !ret)
+				ret = err;
 		} else
 			UnlockPage(page);
 
@@ -612,6 +616,7 @@
 		spin_lock(&pagecache_lock);
 	}
 	spin_unlock(&pagecache_lock);
+	return ret;
 }
 
 /**
@@ -621,8 +626,10 @@
  *      @mapping: address space structure to wait for
  *
  */
-void filemap_fdatawait(struct address_space * mapping)
+int filemap_fdatawait(struct address_space * mapping)
 {
+	int ret = 0;
+
 	spin_lock(&pagecache_lock);
 
         while (!list_empty(&mapping->locked_pages)) {
@@ -638,11 +645,14 @@
 		spin_unlock(&pagecache_lock);
 
 		___wait_on_page(page);
+		if (PageError(page))
+			ret = -EIO;
 
 		page_cache_release(page);
 		spin_lock(&pagecache_lock);
 	}
 	spin_unlock(&pagecache_lock);
+	return ret;
 }
 
 /*
@@ -1519,12 +1529,14 @@
 		goto out_free;
 
 	/*
-	 * Flush to disk exlusively the _data_, metadata must remains
+	 * Flush to disk exclusively the _data_, metadata must remain
 	 * completly asynchronous or performance will go to /dev/null.
 	 */
-	filemap_fdatasync(mapping);
-	retval = fsync_inode_data_buffers(inode);
-	filemap_fdatawait(mapping);
+	retval = filemap_fdatasync(mapping);
+	if (retval == 0)
+		retval = fsync_inode_data_buffers(inode);
+	if (retval == 0)
+		retval = filemap_fdatawait(mapping);
 	if (retval < 0)
 		goto out_free;
 
@@ -2141,26 +2153,45 @@
  * The msync() system call.
  */
 
+/*
+ * MS_SYNC syncs the entire file - including mappings.
+ *
+ * MS_ASYNC initiates writeout of just the dirty mapped data.
+ * This provides no guarantee of file integrity - things like indirect
+ * blocks may not have started writeout.  MS_ASYNC is primarily useful
+ * where the application knows that it has finished with the data and
+ * wishes to intelligently schedule its own I/O traffic.
+ */
 static int msync_interval(struct vm_area_struct * vma,
 	unsigned long start, unsigned long end, int flags)
 {
+	int ret = 0;
 	struct file * file = vma->vm_file;
+
 	if (file && (vma->vm_flags & VM_SHARED)) {
-		int error;
-		error = filemap_sync(vma, start, end-start, flags);
+		ret = filemap_sync(vma, start, end-start, flags);
 
-		if (!error && (flags & MS_SYNC)) {
+		if (!ret && (flags & (MS_SYNC|MS_ASYNC))) {
 			struct inode * inode = file->f_dentry->d_inode;
+
 			down(&inode->i_sem);
-			filemap_fdatasync(inode->i_mapping);
-			if (file->f_op && file->f_op->fsync)
-				error = file->f_op->fsync(file, file->f_dentry, 1);
-			filemap_fdatawait(inode->i_mapping);
+			ret = filemap_fdatasync(inode->i_mapping);
+			if (flags & MS_SYNC) {
+				int err;
+
+				if (file->f_op && file->f_op->fsync) {
+					err = file->f_op->fsync(file, file->f_dentry, 1);
+					if (err && !ret)
+						ret = err;
+				}
+				err = filemap_fdatawait(inode->i_mapping);
+				if (err && !ret)
+					ret = err;
+			}
 			up(&inode->i_sem);
 		}
-		return error;
 	}
-	return 0;
+	return ret;
 }
 
 asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
@@ -3004,7 +3035,7 @@
 		kaddr = kmap(page);
 		status = mapping->a_ops->prepare_write(file, page, offset, offset+bytes);
 		if (status)
-			goto unlock;
+			goto sync_failure;
 		page_fault = __copy_from_user(kaddr+offset, buf, bytes);
 		flush_dcache_page(page);
 		status = mapping->a_ops->commit_write(file, page, offset, offset+bytes);
@@ -3029,6 +3060,7 @@
 		if (status < 0)
 			break;
 	} while (count);
+done:
 	*ppos = pos;
 
 	if (cached_page)
@@ -3050,6 +3082,18 @@
 fail_write:
 	status = -EFAULT;
 	goto unlock;
+
+sync_failure:
+	/*
+	 * If blocksize < pagesize, prepare_write() may have instantiated a
+	 * few blocks outside i_size.  Trim these off again.
+	 */
+	kunmap(page);
+	UnlockPage(page);
+	page_cache_release(page);
+	if (pos + bytes > inode->i_size)
+		vmtruncate(inode, inode->i_size);
+	goto done;
 
 o_direct:
 	written = generic_file_direct_IO(WRITE, file, (char *) buf, count, pos);
diff -urN linux-2.4.18-pre3/net/Config.in linux/net/Config.in
--- linux-2.4.18-pre3/net/Config.in	Fri Dec 21 09:42:05 2001
+++ linux/net/Config.in	Tue Jan 15 15:10:18 2002
@@ -59,7 +59,7 @@
 if [ "$CONFIG_DECNET" != "n" ]; then
    source net/decnet/Config.in
 fi
-tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE
+dep_tristate '802.1d Ethernet Bridging' CONFIG_BRIDGE $CONFIG_INET
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    tristate 'CCITT X.25 Packet Layer (EXPERIMENTAL)' CONFIG_X25
    tristate 'LAPB Data Link Driver (EXPERIMENTAL)' CONFIG_LAPB
diff -urN linux-2.4.18-pre3/net/bridge/br.c linux/net/bridge/br.c
--- linux-2.4.18-pre3/net/bridge/br.c	Wed Oct 17 14:16:39 2001
+++ linux/net/bridge/br.c	Tue Jan 15 15:10:18 2002
@@ -5,7 +5,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br.c,v 1.46 2001/10/02 02:22:36 davem Exp $
+ *	$Id: br.c,v 1.46.2.1 2001/12/24 00:56:13 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -43,9 +43,7 @@
 	printk(KERN_INFO "NET4: Ethernet Bridge 008 for NET4.0\n");
 
 	br_handle_frame_hook = br_handle_frame;
-#ifdef CONFIG_INET
 	br_ioctl_hook = br_ioctl_deviceless_stub;
-#endif
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 	br_fdb_get_hook = br_fdb_get;
 	br_fdb_put_hook = br_fdb_put;
@@ -62,9 +60,7 @@
 
 static void __br_clear_ioctl_hook(void)
 {
-#ifdef CONFIG_INET
 	br_ioctl_hook = NULL;
-#endif	
 }
 
 static void __exit br_deinit(void)
diff -urN linux-2.4.18-pre3/net/bridge/br_device.c linux/net/bridge/br_device.c
--- linux-2.4.18-pre3/net/bridge/br_device.c	Wed Aug 15 01:54:30 2001
+++ linux/net/bridge/br_device.c	Tue Jan 15 15:10:18 2002
@@ -5,7 +5,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br_device.c,v 1.5 2001/08/14 22:05:57 davem Exp $
+ *	$Id: br_device.c,v 1.5.2.1 2001/12/24 00:59:27 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -71,7 +71,7 @@
 	return 0;
 }
 
-static int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
+int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct net_bridge *br;
 	int ret;
diff -urN linux-2.4.18-pre3/net/bridge/br_if.c linux/net/bridge/br_if.c
--- linux-2.4.18-pre3/net/bridge/br_if.c	Fri Dec 21 09:42:05 2001
+++ linux/net/bridge/br_if.c	Tue Jan 15 15:10:18 2002
@@ -5,7 +5,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br_if.c,v 1.6 2001/11/24 17:51:03 davem Exp $
+ *	$Id: br_if.c,v 1.6.2.1 2001/12/24 00:59:27 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -225,6 +225,9 @@
 
 	if (dev->flags & IFF_LOOPBACK || dev->type != ARPHRD_ETHER)
 		return -EINVAL;
+
+	if (dev->hard_start_xmit == br_dev_xmit)
+		return -ELOOP;
 
 	dev_hold(dev);
 	write_lock_bh(&br->lock);
diff -urN linux-2.4.18-pre3/net/bridge/br_input.c linux/net/bridge/br_input.c
--- linux-2.4.18-pre3/net/bridge/br_input.c	Wed Aug 15 01:54:39 2001
+++ linux/net/bridge/br_input.c	Tue Jan 15 15:10:18 2002
@@ -5,7 +5,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br_input.c,v 1.9 2001/08/14 22:05:57 davem Exp $
+ *	$Id: br_input.c,v 1.9.2.1 2001/12/24 04:50:05 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -46,7 +46,7 @@
 			br_pass_frame_up_finish);
 }
 
-static void __br_handle_frame(struct sk_buff *skb)
+static int br_handle_frame_finish(struct sk_buff *skb)
 {
 	struct net_bridge *br;
 	unsigned char *dest;
@@ -57,103 +57,112 @@
 	dest = skb->mac.ethernet->h_dest;
 
 	p = skb->dev->br_port;
-	br = p->br;
-	passedup = 0;
+	if (p == NULL)
+		goto err_nolock;
 
-	if (!(br->dev.flags & IFF_UP) ||
-	    p->state == BR_STATE_DISABLED)
-		goto freeandout;
+	br = p->br;
+	read_lock(&br->lock);
+	if (skb->dev->br_port == NULL)
+		goto err;
 
+	passedup = 0;
 	if (br->dev.flags & IFF_PROMISC) {
 		struct sk_buff *skb2;
 
 		skb2 = skb_clone(skb, GFP_ATOMIC);
-		if (skb2) {
+		if (skb2 != NULL) {
 			passedup = 1;
 			br_pass_frame_up(br, skb2);
 		}
 	}
 
-	if (skb->mac.ethernet->h_source[0] & 1)
-		goto freeandout;
-
-	if (!passedup &&
-	    (dest[0] & 1) &&
-	    (br->dev.flags & IFF_ALLMULTI || br->dev.mc_list != NULL)) {
-		struct sk_buff *skb2;
-
-		skb2 = skb_clone(skb, GFP_ATOMIC);
-		if (skb2) {
-			passedup = 1;
-			br_pass_frame_up(br, skb2);
-		}
-	}
-
-	if (br->stp_enabled &&
-	    !memcmp(dest, bridge_ula, 5) &&
-	    !(dest[5] & 0xF0))
-		goto handle_special_frame;
-
-	if (p->state == BR_STATE_LEARNING ||
-	    p->state == BR_STATE_FORWARDING)
-		br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0);
-
-	if (p->state != BR_STATE_FORWARDING)
-		goto freeandout;
-
 	if (dest[0] & 1) {
-		br_flood_forward(br, skb, 1);
+		br_flood_forward(br, skb, !passedup);
 		if (!passedup)
 			br_pass_frame_up(br, skb);
-		else
-			kfree_skb(skb);
-		return;
+		goto out;
 	}
 
 	dst = br_fdb_get(br, dest);
-
 	if (dst != NULL && dst->is_local) {
 		if (!passedup)
 			br_pass_frame_up(br, skb);
 		else
 			kfree_skb(skb);
 		br_fdb_put(dst);
-		return;
+		goto out;
 	}
 
 	if (dst != NULL) {
 		br_forward(dst->dst, skb);
 		br_fdb_put(dst);
-		return;
+		goto out;
 	}
 
 	br_flood_forward(br, skb, 0);
-	return;
 
- handle_special_frame:
-	if (!dest[5]) {
-		br_stp_handle_bpdu(skb);
-		return;
-	}
+out:
+	read_unlock(&br->lock);
+	return 0;
 
- freeandout:
+err:
+	read_unlock(&br->lock);
+err_nolock:
 	kfree_skb(skb);
+	return 0;
 }
 
-static int br_handle_frame_finish(struct sk_buff *skb)
+void br_handle_frame(struct sk_buff *skb)
 {
 	struct net_bridge *br;
+	unsigned char *dest;
+	struct net_bridge_port *p;
 
-	br = skb->dev->br_port->br;
+	dest = skb->mac.ethernet->h_dest;
+
+	p = skb->dev->br_port;
+	if (p == NULL)
+		goto err_nolock;
+
+	br = p->br;
 	read_lock(&br->lock);
-	__br_handle_frame(skb);
-	read_unlock(&br->lock);
+	if (skb->dev->br_port == NULL)
+		goto err;
 
-	return 0;
-}
+	if (!(br->dev.flags & IFF_UP) ||
+	    p->state == BR_STATE_DISABLED)
+		goto err;
 
-void br_handle_frame(struct sk_buff *skb)
-{
-	NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
+	if (skb->mac.ethernet->h_source[0] & 1)
+		goto err;
+
+	if (p->state == BR_STATE_LEARNING ||
+	    p->state == BR_STATE_FORWARDING)
+		br_fdb_insert(br, p, skb->mac.ethernet->h_source, 0);
+
+	if (br->stp_enabled &&
+	    !memcmp(dest, bridge_ula, 5) &&
+	    !(dest[5] & 0xF0))
+		goto handle_special_frame;
+
+	if (p->state == BR_STATE_FORWARDING) {
+		NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
 			br_handle_frame_finish);
+		read_unlock(&br->lock);
+		return;
+	}
+
+err:
+	read_unlock(&br->lock);
+err_nolock:
+	kfree_skb(skb);
+	return;
+
+handle_special_frame:
+	if (!dest[5]) {
+		br_stp_handle_bpdu(skb);
+		return;
+	}
+
+	kfree_skb(skb);
 }
diff -urN linux-2.4.18-pre3/net/bridge/br_private.h linux/net/bridge/br_private.h
--- linux-2.4.18-pre3/net/bridge/br_private.h	Mon Jun 11 19:15:27 2001
+++ linux/net/bridge/br_private.h	Tue Jan 15 15:10:18 2002
@@ -4,7 +4,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br_private.h,v 1.6 2001/06/01 09:28:28 davem Exp $
+ *	$Id: br_private.h,v 1.6.2.1 2001/12/24 00:59:27 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -121,6 +121,7 @@
 
 /* br_device.c */
 extern void br_dev_setup(struct net_device *dev);
+extern int br_dev_xmit(struct sk_buff *skb, struct net_device *dev);
 
 /* br_fdb.c */
 extern void br_fdb_changeaddr(struct net_bridge_port *p,
diff -urN linux-2.4.18-pre3/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- linux-2.4.18-pre3/net/ipv4/icmp.c	Wed Nov  7 14:39:36 2001
+++ linux/net/ipv4/icmp.c	Tue Jan 15 15:10:18 2002
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.82 2001/11/01 23:44:31 davem Exp $
+ *	Version: $Id: icmp.c,v 1.82.2.1 2001/12/13 08:59:27 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -154,8 +154,8 @@
  * 	it's bit position.
  *
  *	default: 
- *	dest unreachable (0x03), source quench (0x04),
- *	time exceeded (0x11), parameter problem (0x12)
+ *	dest unreachable (3), source quench (4),
+ *	time exceeded (11), parameter problem (12)
  */
 
 int sysctl_icmp_ratelimit = 1*HZ;
diff -urN linux-2.4.18-pre3/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- linux-2.4.18-pre3/net/ipv4/ipconfig.c	Fri Dec 21 09:42:05 2001
+++ linux/net/ipv4/ipconfig.c	Tue Jan 15 15:10:18 2002
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.43 2001/11/21 20:27:34 davem Exp $
+ *  $Id: ipconfig.c,v 1.43.2.1 2001/12/13 10:39:53 davem Exp $
  *
  *  Automatic Configuration of IP -- use DHCP, BOOTP, RARP, or
  *  user-supplied information to configure own IP address and routes.
@@ -47,6 +47,7 @@
 #include <linux/route.h>
 #include <linux/udp.h>
 #include <linux/proc_fs.h>
+#include <linux/major.h>
 #include <net/arp.h>
 #include <net/ip.h>
 #include <net/ipconfig.h>
diff -urN linux-2.4.18-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c linux/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.4.18-pre3/net/ipv4/netfilter/ip_conntrack_standalone.c	Sun Sep 30 12:26:08 2001
+++ linux/net/ipv4/netfilter/ip_conntrack_standalone.c	Tue Jan 15 15:10:18 2002
@@ -243,7 +243,7 @@
 
 	ret = nf_register_hook(&ip_conntrack_in_ops);
 	if (ret < 0) {
-		printk("ip_conntrack: can't register in hook.\n");
+		printk("ip_conntrack: can't register pre-routing hook.\n");
 		goto cleanup_proc;
 	}
 	ret = nf_register_hook(&ip_conntrack_local_out_ops);
diff -urN linux-2.4.18-pre3/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- linux-2.4.18-pre3/net/ipv6/tcp_ipv6.c	Fri Dec 21 09:42:05 2001
+++ linux/net/ipv6/tcp_ipv6.c	Tue Jan 15 15:10:18 2002
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: tcp_ipv6.c,v 1.142 2001/11/06 22:21:08 davem Exp $
+ *	$Id: tcp_ipv6.c,v 1.142.2.1 2001/12/21 05:06:08 davem Exp $
  *
  *	Based on: 
  *	linux/net/ipv4/tcp.c
@@ -1172,6 +1172,7 @@
 
 	tcp_parse_options(skb, &tp, 0);
 
+	tp.tstamp_ok = tp.saw_tstamp;
 	tcp_openreq_init(req, &tp, skb);
 
 	req->class = &or_ipv6;
diff -urN linux-2.4.18-pre3/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- linux-2.4.18-pre3/net/sunrpc/sched.c	Thu Oct 11 08:12:52 2001
+++ linux/net/sunrpc/sched.c	Tue Jan 15 15:10:18 2002
@@ -21,6 +21,7 @@
 #include <linux/spinlock.h>
 
 #include <linux/sunrpc/clnt.h>
+#include <linux/sunrpc/xprt.h>
 
 #ifdef RPC_DEBUG
 #define RPCDBG_FACILITY		RPCDBG_SCHED
diff -urN linux-2.4.18-pre3/net/unix/af_unix.c linux/net/unix/af_unix.c
--- linux-2.4.18-pre3/net/unix/af_unix.c	Fri Dec 21 09:42:06 2001
+++ linux/net/unix/af_unix.c	Tue Jan 15 15:10:18 2002
@@ -1053,8 +1053,12 @@
 	 */
 
 	skb = skb_recv_datagram(sk, 0, flags&O_NONBLOCK, &err);
-	if (!skb)
+	if (!skb) {
+		/* This means receive shutdown. */
+		if (err == 0)
+			err = -EINVAL;
 		goto out;
+	}
 
 	tsk = skb->sk;
 	skb_free_datagram(sk, skb);
