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

diff -urN linux-2.4.5-pre2/CREDITS linux/CREDITS
--- linux-2.4.5-pre2/CREDITS	Fri Apr 20 16:23:12 2001
+++ linux/CREDITS	Mon Dec  3 22:43:25 2001
@@ -1869,10 +1869,13 @@
 
 N: Arnaldo Carvalho de Melo
 E: acme@conectiva.com.br
-W: http://www.conectiva.com.br/~acme
+E: acme@gnu.org
+W: http://bazar.conectiva.com.br/~acme
+W: http://advogato.org/person/acme
+P: 1024D/9224DF01 D5DF E3BB E3C8 BCBB F8AD  841A B6AB 4681 9224 DF01
 D: wanrouter hacking
-D: USB hacking
-D: miscellaneous Makefile & Config.in fixes
+D: misc Makefile, Config.in, drivers and network stacks fixes
+D: IPX Maintainer
 D: Cyclom 2X synchronous card driver
 D: i18n for minicom, net-tools, util-linux, fetchmail, etc
 S: Conectiva S.A.
diff -urN linux-2.4.5-pre2/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.5-pre2/Documentation/Configure.help	Mon Dec  3 22:43:16 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:43:25 2001
@@ -4170,22 +4170,6 @@
 
   It is safe to say N here for now.
 
-IPv6: enable EUI-64 token format
-CONFIG_IPV6_EUI64
-  6bone, the network of computers using the IPv6 protocol, is moving
-  to a new aggregatable address format and a new link local address
-  assignment (EUI-64). Say Y if your site has upgraded already, or
-  has started to upgrade.
-
-IPv6: disable provider based addresses
-CONFIG_IPV6_NO_PB
-  Linux tries to operate correctly when your site has moved to EUI-64
-  only partially. Unfortunately, the two address formats (old:
-  "provider based" and new: "aggregatable") are incompatible. Say Y if
-  your site finished the upgrade to EUI-64, and/or you encountered
-  some problems caused by the presence of two link-local addresses on
-  an interface.
-
 IPv6: routing messages via old netlink
 CONFIG_IPV6_NETLINK
   You can say Y here to receive routing messages from the IPv6 code
@@ -7188,7 +7172,7 @@
 
   This driver requires a specially patched pppd daemon.  The patch to
   pppd, along with binaries of a patched pppd package can be found at:
-  http://www.math.uwaterloo.ca/~mostrows
+  http://www.shoshin.uwaterloo.ca/~mostrows
  
 Wireless LAN (non-hamradio)
 CONFIG_NET_RADIO
@@ -12081,10 +12065,7 @@
   The nls settings can be changed at mount time, if your smbmount
   supports that, using the codepage and iocharset parameters.
 
-  Currently no smbmount distributed with samba supports this, it is
-  assumed future versions will. In the meantime you can get an
-  unofficial patch for samba 2.0.7 from:
-  http://www.hojdpunkten.ac.se/054/samba/index.html
+  smbmount from samba 2.2.0 or later supports this.
 
 nls support setting
 CONFIG_SMB_NLS_REMOTE
@@ -12096,10 +12077,7 @@
   The nls settings can be changed at mount time, if your smbmount
   supports that, using the codepage and iocharset parameters.
 
-  Currently no smbmount distributed with samba supports this, it is
-  assumed future versions will. In the meantime you can get an
-  unofficial patch for samba 2.0.7 from:
-  http://www.hojdpunkten.ac.se/054/samba/index.html
+  smbmount from samba 2.2.0 or later supports this.
 
 Coda file system support (advanced network fs)
 CONFIG_CODA_FS
diff -urN linux-2.4.5-pre2/Documentation/networking/cops.txt linux/Documentation/networking/cops.txt
--- linux-2.4.5-pre2/Documentation/networking/cops.txt	Thu Jan  6 14:46:18 2000
+++ linux/Documentation/networking/cops.txt	Mon Dec  3 22:43:25 2001
@@ -1,5 +1,5 @@
 Text File for the COPS LocalTalk Linux driver (cops.c).
-	By Jay Schulist <jschlst@turbolinux.com>
+	By Jay Schulist <jschlst@samba.org>
 
 This driver has two modes and they are: Dayna mode and Tangent mode.
 Each mode corresponds with the type of card. It has been found
diff -urN linux-2.4.5-pre2/Documentation/networking/ethertap.txt linux/Documentation/networking/ethertap.txt
--- linux-2.4.5-pre2/Documentation/networking/ethertap.txt	Wed Aug 23 09:30:13 2000
+++ linux/Documentation/networking/ethertap.txt	Mon Dec  3 22:43:25 2001
@@ -7,7 +7,7 @@
 Ethertap programming mini-HOWTO
 -------------------------------
 
-The ethertap driver was written by Jay Schulist <jschlst@turbolinux.com>,
+The ethertap driver was written by Jay Schulist <jschlst@samba.org>,
 you should contact him for further information. This document was written by
 bert hubert <bert.hubert@netherlabs.nl>. Updates are welcome.
 
diff -urN linux-2.4.5-pre2/Documentation/networking/filter.txt linux/Documentation/networking/filter.txt
--- linux-2.4.5-pre2/Documentation/networking/filter.txt	Thu Jan  6 14:46:18 2000
+++ linux/Documentation/networking/filter.txt	Mon Dec  3 22:43:25 2001
@@ -1,5 +1,5 @@
 filter.txt: Linux Socket Filtering
-Written by: Jay Schulist <jschlst@turbolinux.com>
+Written by: Jay Schulist <jschlst@samba.org>
 
 Introduction
 ============
diff -urN linux-2.4.5-pre2/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- linux-2.4.5-pre2/Documentation/networking/ip-sysctl.txt	Sun Mar 25 18:14:21 2001
+++ linux/Documentation/networking/ip-sysctl.txt	Mon Dec  3 22:43:25 2001
@@ -398,4 +398,117 @@
 Updated by:
 Andi Kleen
 ak@muc.de
-$Id: ip-sysctl.txt,v 1.18 2001/03/16 06:49:20 davem Exp $
+
+
+
+
+
+
+/proc/sys/net/ipv6/* Variables:
+
+IPv6 has no global variables such as tcp_*.  tcp_* settings under ipv4/ also
+apply to IPv6 [XXX?].
+
+conf/default/*:
+	Change the interface-specific default settings.
+
+
+conf/all/*:
+	Change all the interface-specific settings.  
+
+	[XXX:  Other special features than forwarding?]
+
+conf/all/forwarding - BOOLEAN
+	Enable global IPv6 forwarding between all interfaces.  
+
+	IPv4 and IPv6 work differently here; e.g. netfilter must be used 
+	to control which interfaces may forward packets and which not.
+
+	This also sets all interfaces' Host/Router setting 
+	'forwarding' to the specified value.  See below for details.
+
+	This referred to as global forwarding.
+
+conf/interface/*:
+	Change special settings per interface.
+
+	The functional behaviour for certain settings is different 
+	depending on whether local forwarding is enabled or not.
+
+accept_ra - BOOLEAN
+	Accept Router Advertisements; autoconfigure using them.
+	
+	Functional default: enabled if local forwarding is disabled.
+			    disabled if local forwarding is enabled.
+
+accept_redirects - BOOLEAN
+	Accept Redirects.
+
+	Functional default: enabled if local forwarding is disabled.
+			    disabled if local forwarding is enabled.
+
+autoconf - BOOLEAN
+	Configure link-local addresses using L2 hardware addresses.
+
+	Default: TRUE
+
+dad_transmits - INTEGER
+	The amount of Duplicate Address Detection probes to send.
+	Default: 1
+	
+forwarding - BOOLEAN
+	Configure interface-specific Host/Router behaviour.  
+
+	Note: It is recommended to have the same setting on all 
+	interfaces; mixed router/host scenarios are rather uncommon.
+
+	FALSE:
+
+	By default, Host behaviour is assumed.  This means:
+
+	1. IsRouter flag is not set in Neighbour Advertisements.
+	2. Router Solicitations are being sent when necessary.
+	3. If accept_ra is TRUE (default), accept Router 
+	   Advertisements (and do autoconfiguration).
+	4. If accept_redirects is TRUE (default), accept Redirects.
+
+	TRUE:
+
+	If local forwarding is enabled, Router behaviour is assumed. 
+	This means exactly the reverse from the above:
+
+	1. IsRouter flag is set in Neighbour Advertisements.
+	2. Router Solicitations are not sent.
+	3. Router Advertisements are ignored.
+	4. Redirects are ignored.
+
+	Default: FALSE if global forwarding is disabled (default),
+		 otherwise TRUE.
+
+hop_limit - INTEGER
+	Default Hop Limit to set.
+	Default: 64
+
+mtu - INTEGER
+	Default Maximum Transfer Unit
+	Default: 1280 (IPv6 required minimum)
+
+router_solicitation_delay - INTEGER
+	Number of seconds to wait after interface is brought up
+	before sending Router Solicitations.
+	Default: 1
+
+router_solicitation_interval - INTEGER
+	Number of seconds to wait between Router Solicitations.
+	Default: 4
+
+router_solicitations - INTEGER
+	Number of Router Solicitations to send until assuming no 
+	routers are present.
+	Default: 3
+
+IPv6 Update by:
+Pekka Savola
+pekkas@netcore.fi
+
+$Id: ip-sysctl.txt,v 1.19 2001/05/16 17:11:04 davem Exp $
diff -urN linux-2.4.5-pre2/Documentation/networking/ipddp.txt linux/Documentation/networking/ipddp.txt
--- linux-2.4.5-pre2/Documentation/networking/ipddp.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/networking/ipddp.txt	Mon Dec  3 22:43:25 2001
@@ -1,7 +1,7 @@
 Text file for ipddp.c:
 	AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
 
-This text file is written by Jay Schulist <jschlst@turbolinux.com>
+This text file is written by Jay Schulist <jschlst@samba.org>
 
 Introduction
 ------------
@@ -72,7 +72,7 @@
 
 Further Assistance
 -------------------
-You can contact me (Jay Schulist <jschlst@turbolinux.com>) with any
+You can contact me (Jay Schulist <jschlst@samba.org>) with any
 questions regarding decapsulation or encapsulation. Bradford W. Johnson
 <johns393@maroon.tc.umn.edu> originally wrote the ipddp.c driver for IP
 encapsulation in AppleTalk.
diff -urN linux-2.4.5-pre2/Documentation/networking/smctr.txt linux/Documentation/networking/smctr.txt
--- linux-2.4.5-pre2/Documentation/networking/smctr.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/networking/smctr.txt	Mon Dec  3 22:43:25 2001
@@ -1,5 +1,5 @@
 Text File for the SMC TokenCard TokenRing Linux driver (smctr.c).
-        By Jay Schulist <jschlst@turbolinux.com>
+        By Jay Schulist <jschlst@samba.org>
 
 The Linux SMC Token Ring driver works with the SMC TokenCard Elite (8115T) 
 ISA and SMC TokenCard Elite/A (8115T/A) MCA adapters.
@@ -22,7 +22,7 @@
 following command will suffice for most:
 
 # modprobe smctr
-smctr.c: v1.00 12/6/99 by jschlst@turbolinux.com
+smctr.c: v1.00 12/6/99 by jschlst@samba.org
 tr0: SMC TokenCard 8115T at Io 0x300, Irq 10, Rom 0xd8000, Ram 0xcc000.
 
 Now just setup the device via ifconfig and set and routes you may have. After
diff -urN linux-2.4.5-pre2/Documentation/networking/tms380tr.txt linux/Documentation/networking/tms380tr.txt
--- linux-2.4.5-pre2/Documentation/networking/tms380tr.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/networking/tms380tr.txt	Mon Dec  3 22:43:25 2001
@@ -1,5 +1,5 @@
 Text file for the Linux SysKonnect Token Ring ISA/PCI Adapter Driver.
-	Text file by: Jay Schulist <jschlst@turbolinux.com>
+	Text file by: Jay Schulist <jschlst@samba.org>
 
 The Linux SysKonnect Token Ring driver works with the SysKonnect TR4/16(+) ISA,
 SysKonnect TR4/16(+) PCI, SysKonnect TR4/16 PCI, and older revisions of the
diff -urN linux-2.4.5-pre2/MAINTAINERS linux/MAINTAINERS
--- linux-2.4.5-pre2/MAINTAINERS	Mon Dec  3 22:43:16 2001
+++ linux/MAINTAINERS	Mon Dec  3 22:43:25 2001
@@ -160,7 +160,7 @@
 
 APPLETALK NETWORK LAYER
 P:	Jay Schulist
-M:	jschlst@turbolinux.com
+M:	jschlst@samba.org
 L:	linux-atalk@lists.netspace.org
 S:	Maintained
 
@@ -682,9 +682,9 @@
 M:	jjciarla@raiz.uncu.edu.ar
 S:	Maintained
 
-IPX/SPX NETWORK LAYER
-P:	Jay Schulist
-M:	jschlst@turbolinux.com
+IPX NETWORK LAYER
+P:	Arnaldo Carvalho de Melo
+M:	acme@conectiva.com.br
 L:	linux-net@vger.kernel.org
 S:	Maintained
 
@@ -931,6 +931,8 @@
 M:	ak@muc.de
 P:	Alexey Kuznetsov
 M:	kuznet@ms2.inr.ac.ru
+P:	Pekka Savola (ipv6)
+M:	pekkas@netcore.fi
 L:	netdev@oss.sgi.com
 S:	Maintained
 
@@ -1175,7 +1177,7 @@
 
 SMB FILESYSTEM
 P:	Urban Widmark
-M:	urban@svenskatest.se
+M:	urban@teststation.com
 W:	http://samba.org/
 L:	samba@samba.org
 S:	Maintained
@@ -1226,13 +1228,13 @@
 
 SPX NETWORK LAYER
 P:	Jay Schulist
-M:	jschlst@turbolinux.com
+M:	jschlst@samba.org
 L:	linux-net@vger.kernel.org
 S:	Supported
 
 SNA NETWORK LAYER
 P:	Jay Schulist
-M:	jschlst@turbolinux.com
+M:	jschlst@samba.org
 L:	linux-sna@turbolinux.com
 W:	http://www.linux-sna.org
 S:	Supported
diff -urN linux-2.4.5-pre2/Makefile linux/Makefile
--- linux-2.4.5-pre2/Makefile	Mon Dec  3 22:43:16 2001
+++ linux/Makefile	Mon Dec  3 22:43:25 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 5
-EXTRAVERSION =-pre2
+EXTRAVERSION =-pre3
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -415,7 +415,7 @@
 distclean: mrproper
 	rm -f core `find . \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
 		-o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-		-o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -print` TAGS tags
+		-o -name '.*.rej' -o -name '.SUMS' -o -size 0 \) -type f -print` TAGS tags
 
 backup: mrproper
 	cd .. && tar cf - linux/ | gzip -9 > backup.gz
diff -urN linux-2.4.5-pre2/arch/arm/def-configs/ebsa110 linux/arch/arm/def-configs/ebsa110
--- linux-2.4.5-pre2/arch/arm/def-configs/ebsa110	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/def-configs/ebsa110	Mon Dec  3 22:43:25 2001
@@ -192,8 +192,6 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
 CONFIG_IPV6=m
-CONFIG_IPV6_EUI64=y
-# CONFIG_IPV6_NO_PB is not set
 
 #
 #   IPv6: Netfilter Configuration
diff -urN linux-2.4.5-pre2/arch/i386/config.in linux/arch/i386/config.in
--- linux-2.4.5-pre2/arch/i386/config.in	Mon Dec  3 22:43:16 2001
+++ linux/arch/i386/config.in	Mon Dec  3 22:43:25 2001
@@ -33,7 +33,7 @@
 	 Pentium-Classic			CONFIG_M586TSC \
 	 Pentium-MMX				CONFIG_M586MMX \
 	 Pentium-Pro/Celeron/Pentium-II		CONFIG_M686 \
-	 Pentium-III/Celeron(Coppermine)	CONFIG_MPENTIUMIII \
+	 Pentium-III/Celeron-Coppermine		CONFIG_MPENTIUMIII \
 	 Pentium-4				CONFIG_MPENTIUM4 \
 	 K6/K6-II/K6-III			CONFIG_MK6 \
 	 Athlon/Duron/K7			CONFIG_MK7 \
diff -urN linux-2.4.5-pre2/arch/i386/defconfig linux/arch/i386/defconfig
--- linux-2.4.5-pre2/arch/i386/defconfig	Mon Dec  3 22:43:16 2001
+++ linux/arch/i386/defconfig	Mon Dec  3 22:43:25 2001
@@ -382,6 +382,7 @@
 CONFIG_EEPRO100=y
 # CONFIG_EEPRO100_PM is not set
 # CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_NE3210 is not set
diff -urN linux-2.4.5-pre2/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- linux-2.4.5-pre2/arch/i386/kernel/i386_ksyms.c	Wed Apr 25 13:31:03 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Dec  3 22:43:25 2001
@@ -112,6 +112,7 @@
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(pcibios_penalize_isa_irq);
+EXPORT_SYMBOL(pci_mem_start);
 #endif
 
 #ifdef CONFIG_X86_USE_3DNOW
diff -urN linux-2.4.5-pre2/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c
--- linux-2.4.5-pre2/arch/i386/kernel/pci-irq.c	Mon Dec  3 22:43:16 2001
+++ linux/arch/i386/kernel/pci-irq.c	Mon Dec  3 22:43:25 2001
@@ -445,8 +445,12 @@
 		return;
 	}
 #endif
+
+	DBG("PCI: Attempting to find IRQ router for %04x:%04x\n",
+	    rt->rtr_vendor, rt->rtr_device);
+
 	/* fall back to default router if nothing else found */
-	pirq_router = pirq_routers + sizeof(pirq_routers) / sizeof(pirq_routers[0]) - 1;
+	pirq_router = &pirq_routers[ARRAY_SIZE(pirq_routers) - 1];
 
 	pirq_router_dev = pci_find_slot(rt->rtr_bus, rt->rtr_devfn);
 	if (!pirq_router_dev) {
diff -urN linux-2.4.5-pre2/arch/ppc/8xx_io/Config.in linux/arch/ppc/8xx_io/Config.in
--- linux-2.4.5-pre2/arch/ppc/8xx_io/Config.in	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/Config.in	Mon Dec  3 22:43:25 2001
@@ -18,12 +18,12 @@
   fi
   bool 'Use Big CPM Ethernet Buffers' CONFIG_ENET_BIG_BUFFERS
 fi
-bool 'Use SMC2 for UART' CONFIG_8xxSMC2
-if [ "$CONFIG_8xxSMC2" = "y" ]; then
-  bool 'Use Alternate SMC2 I/O (823/850)' CONFIG_8xx_ALTSMC2
-  bool 'Use SMC2 for Console' CONFIG_8xx_CONS_SMC2
+bool 'Use SMC2 for UART' CONFIG_SMC2_UART
+if [ "$CONFIG_SMC2_UART" = "y" ]; then
+  bool 'Use Alternate SMC2 I/O (823/850)' CONFIG_ALTSMC2
+  bool 'Use SMC2 for Console' CONFIG_CONS_SMC2
 fi
-bool 'Enable SCC2 and SCC3 for UART' CONFIG_8xxSCC
+bool 'Enable SCC2 and SCC3 for UART' CONFIG_USE_SCC_IO
 
 # This doesn't really belong here, but it is convenient to ask
 # 8xx specific questions.
diff -urN linux-2.4.5-pre2/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- linux-2.4.5-pre2/arch/ppc/8xx_io/uart.c	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/8xx_io/uart.c	Mon Dec  3 22:43:25 2001
@@ -55,17 +55,17 @@
 */
 # ifndef CONFIG_SERIAL_CONSOLE_PORT
 #  ifdef CONFIG_SCC3_ENET
-#   ifdef CONFIG_8xx_CONS_SMC2
+#   ifdef CONFIG_CONS_SMC2
 #    define CONFIG_SERIAL_CONSOLE_PORT	0	/* Console on SMC2 is 1st port */
 #   else
 #    error "Can't use SMC1 for console with Ethernet on SCC3"
 #   endif
 #  else	/* ! CONFIG_SCC3_ENET */
-#   ifdef CONFIG_8xx_CONS_SMC2			/* Console on SMC2 */
+#   ifdef CONFIG_CONS_SMC2			/* Console on SMC2 */
 #    define CONFIG_SERIAL_CONSOLE_PORT	1
 #   else					/* Console on SMC1 */
 #    define CONFIG_SERIAL_CONSOLE_PORT	0
-#   endif /* CONFIG_8xx_CONS_SMC2 */
+#   endif /* CONFIG_CONS_SMC2 */
 #  endif  /* CONFIG_SCC3_ENET */
 # endif	  /* CONFIG_SERIAL_CONSOLE_PORT */
 #endif	  /* CONFIG_SERIAL_CONSOLE */
@@ -134,15 +134,15 @@
   	{ 0,     0, PROFF_SMC1, CPMVEC_SMC1,   0,    0 },    /* SMC1 ttyS0 */
 #endif
 #if !defined(CONFIG_USB_MPC8xx) && !defined(CONFIG_USB_CLIENT_MPC8xx)
-# ifdef CONFIG_8xxSMC2
+# ifdef CONFIG_SMC2_UART
   	{ 0,     0, PROFF_SMC2, CPMVEC_SMC2,   0,    1 },    /* SMC2 ttyS1 */
 # endif
-# ifdef CONFIG_8xxSCC
+# ifdef CONFIG_USE_SCC_IO
   	{ 0,     0, PROFF_SCC2, CPMVEC_SCC2,   0,    (NUM_IS_SCC | 1) },    /* SCC2 ttyS2 */
   	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    (NUM_IS_SCC | 2) },    /* SCC3 ttyS3 */
 # endif
   #else /* CONFIG_USB_xxx */
-# ifdef CONFIG_8xxSCC
+# ifdef CONFIG_USE_SCC_IO
   	{ 0,     0, PROFF_SCC3, CPMVEC_SCC3,   0,    (NUM_IS_SCC | 2) },    /* SCC3 ttyS3 */
 # endif
 #endif	/* CONFIG_USB_xxx */
@@ -2533,7 +2533,7 @@
 
 	/* Configure SCC2, SCC3, and SCC4 instead of port A parallel I/O.
 	 */
-#ifdef CONFIG_8xxSCC
+#ifdef CONFIG_USE_SCC_IO
 #ifndef CONFIG_MBX
 	/* The "standard" configuration through the 860.
 	*/
@@ -2747,7 +2747,7 @@
 				 * parallel I/O.  On 823/850 these are on
 				 * port A for SMC2.
 				 */
-#ifndef CONFIG_8xx_ALTSMC2
+#ifndef CONFIG_ALTSMC2
 				iobits = 0xc0 << (idx * 4);
 				cp->cp_pbpar |= iobits;
 				cp->cp_pbdir &= ~iobits;
diff -urN linux-2.4.5-pre2/arch/ppc/Makefile linux/arch/ppc/Makefile
--- linux-2.4.5-pre2/arch/ppc/Makefile	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/Makefile	Mon Dec  3 22:43:25 2001
@@ -31,7 +31,7 @@
 endif
 
 ifdef CONFIG_8xx
-CFLAGS := $(CFLAGS) -mcpu=860 -I../8xx_io
+CFLAGS := $(CFLAGS) -mcpu=860
 endif
 
 ifdef CONFIG_PPC64BRIDGE
@@ -144,6 +144,9 @@
 .PHONY: clean_config
 clean_config:
 	rm -f .config arch/ppc/defconfig
+
+gemini_config: clean_config
+	cp -f arch/ppc/configs/gemini_defconfig arch/ppc/defconfig
 
 pmac_config: clean_config
 	cp -f arch/ppc/configs/pmac_defconfig arch/ppc/defconfig
diff -urN linux-2.4.5-pre2/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- linux-2.4.5-pre2/arch/ppc/boot/Makefile	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/boot/Makefile	Mon Dec  3 22:43:25 2001
@@ -31,6 +31,12 @@
 TFTPIMAGE=/tftpboot/zImage.prep$(MSIZE)
 endif
 
+ifeq ($(CONFIG_SMP),y)
+TFTPSIMAGE=/tftpboot/sImage.smp
+else
+TFTPSIMAGE=/tftpboot/sImage
+endif
+
 ifeq ($(CONFIG_PPC64BRIDGE),y)
 MSIZE=.64
 else
@@ -70,8 +76,24 @@
 		--add-section=image=../coffboot/vmlinux.gz \
 		zvmlinux.initrd.tmp $@
 	rm zvmlinux.initrd.tmp
+ifdef CONFIG_GEMINI
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+	$(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.initrd.tmp svmlinux.initrd.tmp
+	./mksimage svmlinux.initrd.tmp ../coffboot/vmlinux.gz ramdisk.image.gz \
+	-o svmlinux.initrd > sImage.map
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=`sh sioffset initrd` \
+			-DINITRD_SIZE=`sh sisize initrd` \
+			-DZIMAGE_OFFSET=`sh sioffset zimage` \
+			-DZIMAGE_SIZE=`sh sisize zimage` \
+			-c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.initrd.tmp $(OBJECTS)
+	$(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.initrd.tmp svmlinux.initrd.tmp
+	./mksimage svmlinux.initrd.tmp ../coffboot/vmlinux.gz ramdisk.image.gz \
+	-o svmlinux.initrd > /dev/null
+	rm svmlinux.initrd.tmp zvmlinux.initrd.tmp sImage.map
+endif
 
-zImage: zvmlinux mkprep
+zImage: zvmlinux mkprep sImage mksimage
 ifdef CONFIG_ALL_PPC
 	./mkprep -pbp zvmlinux zImage
 endif
@@ -80,12 +102,17 @@
 	gzip $(GZIP_FLAGS) vmapus
 endif
 
+sImage: ../../../vmlinux
+ifdef CONFIG_GEMINI
+	$(OBJCOPY) -I elf32-powerpc -O binary ../../../vmlinux sImage
+endif
+
 zImage.initrd: zvmlinux.initrd mkprep
 ifdef CONFIG_ALL_PPC
 	./mkprep -pbp zvmlinux.initrd zImage.initrd
 endif
 
-zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz
+zvmlinux: $(OBJECTS) ../coffboot/vmlinux.gz mksimage
 #
 # build the boot loader image and then compute the offset into it
 # for the kernel image
@@ -105,6 +132,19 @@
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment --add-section=image=../coffboot/vmlinux.gz \
 		zvmlinux.tmp $@
 	rm zvmlinux.tmp
+ifdef CONFIG_GEMINI
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
+	$(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.tmp svmlinux.tmp
+	./mksimage svmlinux.tmp ../coffboot/vmlinux.gz -o svmlinux > sImage.map
+	$(CC) $(CFLAGS) -DINITRD_OFFSET=0 -DINITRD_SIZE=0 \
+		-DZIMAGE_OFFSET=`sh sioffset zimage` \
+		-DZIMAGE_SIZE=`sh sisize zimage` \
+		-c -o misc.o misc.c
+	$(LD) $(ZLINKFLAGS) -o zvmlinux.tmp $(OBJECTS)
+	$(OBJCOPY) -I elf32-powerpc -O binary zvmlinux.tmp svmlinux.tmp
+	./mksimage svmlinux.tmp ../coffboot/vmlinux.gz -o svmlinux > /dev/null
+	rm svmlinux.tmp sImage.map zvmlinux.tmp
+endif
 
 floppy: $(TOPDIR)/vmlinux zImage
 	dd if=zImage of=/dev/fd0H1440 bs=64b
@@ -112,16 +152,22 @@
 mkprep : mkprep.c
 	$(HOSTCC) -o mkprep mkprep.c
 
+mksimage: mksimage.c
+	$(HOSTCC) -o mksimage mksimage.c
+
 znetboot : zImage
 ifdef CONFIG_ALL_PPC
 	cp zImage $(TFTPIMAGE)
 endif
+ifdef CONFIG_GEMINI
+	cp sImage $(TFTPSIMAGE)
+endif
 
 znetboot.initrd : zImage.initrd
 	cp zImage.initrd $(TFTPIMAGE)
 
 clean:
-	rm -f vmlinux* zvmlinux* mkprep zImage*
+	rm -f vmlinux* zvmlinux* mkprep zImage* sImage* mksimage
 
 fastdep:
 	$(TOPDIR)/scripts/mkdep *.[Sch] > .depend
diff -urN linux-2.4.5-pre2/arch/ppc/boot/mksimage.c linux/arch/ppc/boot/mksimage.c
--- linux-2.4.5-pre2/arch/ppc/boot/mksimage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/mksimage.c	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,124 @@
+/*
+ *
+ *
+ *
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+
+#define SIZE 1024
+#define BLOCK_ALIGN(x)  (((x)+SIZE-1)&(~(SIZE-1)))
+
+static void
+die(const char *fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	fputc('\n', stderr);
+	exit(1);
+}
+
+static void
+usage(void)
+{
+	printf("Usage: mkbinimg <bootstrap> <kernel> <ramdisk> -o <binary>\n");
+	exit(1);
+}
+
+static int
+copy_blocks(int ifd, int ofd, unsigned long *offset, unsigned long *size)
+{
+	off_t cur;
+	int amt;
+	unsigned long len = 0;
+	char buffer[SIZE];
+
+	cur = lseek(ofd, 0, SEEK_CUR);
+
+	if (cur % SIZE) {
+		cur = BLOCK_ALIGN(cur);
+		cur = lseek(ofd, cur, SEEK_SET);
+	}
+
+	*offset = (unsigned long) cur;
+	while((amt = read(ifd, buffer, SIZE)) > 0) {
+		write(ofd, buffer, amt);
+		len += amt;
+	}
+	*size = len;
+	return 0;
+}
+
+
+int
+main(int argc, char *argv[])
+{
+	char *kernel, *loader, *rdimage = NULL;
+	unsigned long ld_off, kern_off, rd_off;
+	unsigned long ld_size, kern_size, rd_size;
+	int fd, ofd, len;
+	char buffer[500];
+
+	if (argc < 5 && !strcmp(argv[argc-2], "-o"))
+		usage();
+
+	if (argc > 5)
+		rdimage = argv[3];
+
+	kernel = argv[2];
+	loader = argv[1];
+
+	ofd = open(argv[argc-1], (O_RDWR|O_CREAT), 0755);
+	if (ofd < 0) {
+		die("can't open %s: %s", argv[5], strerror(errno));
+	}
+
+	ld_off = kern_off = rd_off = 0;
+	ld_size = kern_size = rd_size = 0;
+	memset(buffer, 0, 500);
+	len = 0;
+
+	fd = open(loader, O_RDONLY);
+	if (fd < 0) 
+		die("can't open loader: %s", strerror(errno));
+
+	copy_blocks(fd, ofd, &ld_off, &ld_size);
+	len = sprintf(buffer, "bootloader: %x %x\n", ld_off, ld_size);
+	close(fd);
+
+	fd = open(kernel, O_RDONLY);
+	if (fd < 0)
+		die("can't open kernel: %s", strerror(errno));
+
+	copy_blocks(fd, ofd, &kern_off, &kern_size);
+	len += sprintf(buffer+len, "zimage: %x %x\n", kern_off, kern_size);
+	close(fd);
+	
+	if (rdimage) {
+		fd = open(rdimage, O_RDONLY);
+		if (fd < 0)
+			die("can't get ramdisk: %s", strerror(errno));
+		
+		copy_blocks(fd, ofd, &rd_off, &rd_size);
+		close(fd);
+	}
+
+	len += sprintf(buffer+len, "initrd: %x %x", rd_off, rd_size);
+
+	close(ofd);
+
+	printf("%s\n", buffer);
+
+	return 0;
+}
+
diff -urN linux-2.4.5-pre2/arch/ppc/boot/sioffset linux/arch/ppc/boot/sioffset
--- linux-2.4.5-pre2/arch/ppc/boot/sioffset	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/sioffset	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`grep $1 sImage.map | awk '{print $2}'`
+echo "0x"$OFFSET
diff -urN linux-2.4.5-pre2/arch/ppc/boot/sisize linux/arch/ppc/boot/sisize
--- linux-2.4.5-pre2/arch/ppc/boot/sisize	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/boot/sisize	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+OFFSET=`grep $1 sImage.map | awk '{print $3}'`
+echo "0x"$OFFSET
diff -urN linux-2.4.5-pre2/arch/ppc/coffboot/chrpmain.c linux/arch/ppc/coffboot/chrpmain.c
--- linux-2.4.5-pre2/arch/ppc/coffboot/chrpmain.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/coffboot/chrpmain.c	Mon Dec  3 22:43:25 2001
@@ -14,6 +14,8 @@
 
 extern void *finddevice(const char *);
 extern int getprop(void *, const char *, void *, int);
+extern void *claim(unsigned int, unsigned int, unsigned int);
+extern void release(void *ptr, unsigned int len);
 void make_bi_recs(unsigned long);
 void gunzip(void *, int, unsigned char *, int *);
 void stop_imac_ethernet(void);
@@ -78,6 +80,7 @@
 	printf("done %u bytes\n", len);
 	printf("%u bytes of heap consumed, max in use %u\n",
 	       avail_high - begin_avail, heap_max);
+	release(begin_avail, SCRATCH_SIZE);
     } else {
 	memmove(dst, im, len);
     }
@@ -98,8 +101,13 @@
 void make_bi_recs(unsigned long addr)
 {
 	struct bi_record *rec;
-	rec = (struct bi_record *)_ALIGN((unsigned long)addr+(1<<20)-1,(1<<20));
-	    
+
+	/* leave a 1MB gap then align to the next 1MB boundary */
+	addr = _ALIGN(addr+ (1<<20) - 1, (1<<20));
+	if (addr >= PROG_START + PROG_SIZE)
+		claim(addr, 0x1000, 0);
+
+	rec = (struct bi_record *)addr;
 	rec->tag = BI_FIRST;
 	rec->size = sizeof(struct bi_record);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
diff -urN linux-2.4.5-pre2/arch/ppc/coffboot/start.c linux/arch/ppc/coffboot/start.c
--- linux-2.4.5-pre2/arch/ppc/coffboot/start.c	Thu Dec  2 14:37:34 1999
+++ linux/arch/ppc/coffboot/start.c	Mon Dec  3 22:43:25 2001
@@ -172,6 +172,25 @@
     return args.ret;
 }
 
+void
+release(void *virt, unsigned int size)
+{
+    struct prom_args {
+	char *service;
+	int nargs;
+	int nret;
+	void *virt;
+	unsigned int size;
+    } args;
+
+    args.service = "release";
+    args.nargs = 2;
+    args.nret = 0;
+    args.virt = virt;
+    args.size = size;
+    (*prom)(&args);
+}
+
 int
 getprop(void *phandle, const char *name, void *buf, int buflen)
 {
diff -urN linux-2.4.5-pre2/arch/ppc/config.in linux/arch/ppc/config.in
--- linux-2.4.5-pre2/arch/ppc/config.in	Tue Apr 17 17:19:25 2001
+++ linux/arch/ppc/config.in	Mon Dec  3 22:43:25 2001
@@ -3,8 +3,8 @@
 # see Documentation/kbuild/config-language.txt.
 #
 define_bool CONFIG_UID16 n
-define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
-define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
+define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 
 mainmenu_name "Linux/PowerPC Kernel Configuration"
 
@@ -84,6 +84,7 @@
 if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then
   choice 'Machine Type'		\
 	"PowerMac/PReP/MTX/CHRP	CONFIG_ALL_PPC	\
+	 Gemini         CONFIG_GEMINI           \
 	 APUS		CONFIG_APUS"		PowerMac/PReP/MTX/CHRP
 fi
 
@@ -118,7 +119,6 @@
 comment 'General setup'
 
 bool 'High memory support (experimental)' CONFIG_HIGHMEM
-bool 'Mac-on-Linux support' CONFIG_MOL
 
 define_bool CONFIG_ISA n
 define_bool CONFIG_EISA n
diff -urN linux-2.4.5-pre2/arch/ppc/configs/IVMS8_defconfig linux/arch/ppc/configs/IVMS8_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/IVMS8_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/IVMS8_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -40,6 +41,7 @@
 # CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -50,8 +52,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -87,17 +93,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -116,10 +128,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -136,6 +146,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -184,11 +195,10 @@
 # CONFIG_BLK_DEV_CMD640 is not set
 # CONFIG_BLK_DEV_CMD640_ENHANCED is not set
 # CONFIG_BLK_DEV_ISAPNP is not set
-CONFIG_BLK_DEV_MPC8xx_IDE=y
 # CONFIG_IDE_CHIPSETS is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_DMA_NONPCI is not set
-CONFIG_BLK_DEV_IDE_MODES=y
+# CONFIG_BLK_DEV_IDE_MODES is not set
 
 #
 # SCSI support
@@ -207,6 +217,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -232,8 +243,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -288,6 +300,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -312,6 +333,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -321,12 +346,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-# CONFIG_FLASH is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -335,8 +354,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -344,6 +368,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -356,6 +382,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -398,8 +425,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -416,6 +441,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -430,14 +456,15 @@
 CONFIG_FEC_ENET=y
 CONFIG_USE_MDIO=y
 CONFIG_ENET_BIG_BUFFERS=y
-# CONFIG_8xxSMC2 is not set
-# CONFIG_8xxSCC is not set
+# CONFIG_SMC2_UART is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
 #
 CONFIG_8xx_COPYBACK=y
 # CONFIG_8xx_CPU6 is not set
+CONFIG_BLK_DEV_MPC8xx_IDE=y
 
 #
 # USB support
diff -urN linux-2.4.5-pre2/arch/ppc/configs/SM850_defconfig linux/arch/ppc/configs/SM850_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/SM850_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/SM850_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,10 +37,12 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
 CONFIG_SM850=y
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -50,8 +53,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -87,17 +94,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -116,10 +129,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -136,6 +147,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -170,6 +182,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -195,8 +208,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -251,6 +265,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -275,6 +298,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -284,13 +311,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -299,8 +319,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -308,6 +333,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -320,6 +347,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -362,8 +390,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -380,6 +406,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -396,10 +423,10 @@
 CONFIG_SCC3_ENET=y
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-CONFIG_8xx_CONS_SMC2=y
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+CONFIG_CONS_SMC2=y
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/SPD823TS_defconfig linux/arch/ppc/configs/SPD823TS_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/SPD823TS_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/SPD823TS_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,8 +37,11 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 CONFIG_SPD823TS=y
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -48,8 +52,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -85,17 +93,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -114,10 +128,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -134,6 +146,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -168,6 +181,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -193,8 +207,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -249,6 +264,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -273,6 +297,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -282,12 +310,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-# CONFIG_FLASH is not set
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -296,8 +318,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -305,6 +332,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -317,6 +346,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -359,8 +389,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -377,6 +405,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -390,12 +419,13 @@
 CONFIG_SCC_ENET=y
 # CONFIG_SCC1_ENET is not set
 CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/TQM823L_defconfig linux/arch/ppc/configs/TQM823L_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/TQM823L_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/TQM823L_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,9 +37,12 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -49,8 +53,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -86,17 +94,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -115,10 +129,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -135,6 +147,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -169,6 +182,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -194,8 +208,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -250,6 +265,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -274,6 +298,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -283,13 +311,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -298,8 +319,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -307,6 +333,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -319,6 +347,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -361,8 +390,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -379,6 +406,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -395,10 +423,10 @@
 # CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/TQM850L_defconfig linux/arch/ppc/configs/TQM850L_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/TQM850L_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/TQM850L_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,9 +37,12 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -49,8 +53,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -86,17 +94,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -115,10 +129,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -135,6 +147,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -169,6 +182,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -194,8 +208,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -250,6 +265,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -274,6 +298,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -283,13 +311,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -298,8 +319,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -307,6 +333,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -319,6 +347,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -361,8 +390,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -379,6 +406,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -395,10 +423,10 @@
 # CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-CONFIG_8xx_ALTSMC2=y
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+CONFIG_ALTSMC2=y
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/TQM860L_defconfig linux/arch/ppc/configs/TQM860L_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/TQM860L_defconfig	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/configs/TQM860L_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,7 +25,6 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 CONFIG_8xx=y
 CONFIG_SERIAL_CONSOLE=y
 # CONFIG_RPXLITE is not set
@@ -36,9 +37,12 @@
 # CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
 # CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_TQM8xxL=y
+# CONFIG_PPC601_SYNC_FIX is not set
 # CONFIG_ALL_PPC is not set
 # CONFIG_SMP is not set
 CONFIG_MACH_SPECIFIC=y
@@ -49,8 +53,12 @@
 #
 # General setup
 #
+# CONFIG_HIGHMEM is not set
 # CONFIG_ISA is not set
+# CONFIG_EISA is not set
 # CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+# CONFIG_PCI_QSPAN is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
 CONFIG_SYSCTL=y
@@ -86,17 +94,23 @@
 # CONFIG_BLK_DEV_XD is not set
 # CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_LVM is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
 # CONFIG_BLK_DEV_MD is not set
 # CONFIG_MD_LINEAR is not set
 # CONFIG_MD_RAID0 is not set
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
-# CONFIG_BLK_DEV_RAM is not set
-# CONFIG_BLK_DEV_INITRD is not set
+# CONFIG_BLK_DEV_LVM is not set
 
 #
 # Networking options
@@ -115,10 +129,8 @@
 CONFIG_IP_PNP=y
 # CONFIG_IP_PNP_BOOTP is not set
 # CONFIG_IP_PNP_RARP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
@@ -135,6 +147,7 @@
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -169,6 +182,7 @@
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 # CONFIG_ETHERTAP is not set
 # CONFIG_NET_SB1000 is not set
 
@@ -194,8 +208,9 @@
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_YELLOWFIN is not set
 # CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
@@ -250,6 +265,15 @@
 # CONFIG_FB is not set
 
 #
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
 # Character devices
 #
 # CONFIG_VT is not set
@@ -274,6 +298,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -283,13 +311,6 @@
 # CONFIG_INTEL_RNG is not set
 # CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
-CONFIG_FLASH=y
-CONFIG_AMD_FLASH=y
-
-#
-# Video For Linux
-#
-# CONFIG_VIDEO_DEV is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
@@ -298,8 +319,13 @@
 # Ftape, the floppy tape device driver
 #
 # CONFIG_FTAPE is not set
-# CONFIG_DRM is not set
 # CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
 
 #
 # File systems
@@ -307,6 +333,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -319,6 +347,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -361,8 +390,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -379,6 +406,7 @@
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
@@ -395,10 +423,10 @@
 # CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-# CONFIG_8xx_CONS_SMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/apus_defconfig linux/arch/ppc/configs/apus_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/apus_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/apus_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -24,6 +26,7 @@
 # CONFIG_8xx is not set
 # CONFIG_8260 is not set
 # CONFIG_ALL_PPC is not set
+# CONFIG_GEMINI is not set
 CONFIG_APUS=y
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
@@ -34,7 +37,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -115,7 +117,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -238,6 +239,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -290,6 +292,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 CONFIG_ARIADNE=y
 # CONFIG_NE2K_ZORRO is not set
@@ -316,6 +319,7 @@
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
 CONFIG_PPP_DEFLATE=y
@@ -394,6 +398,7 @@
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
 CONFIG_FBCON_MFB=y
@@ -479,6 +484,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 CONFIG_AFFS_FS=y
@@ -491,6 +498,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -563,11 +571,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -575,11 +585,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
diff -urN linux-2.4.5-pre2/arch/ppc/configs/bseip_defconfig linux/arch/ppc/configs/bseip_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/bseip_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/bseip_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,9 +28,15 @@
 # CONFIG_RPXLITE is not set
 # CONFIG_RPXCLASSIC is not set
 CONFIG_BSEIP=y
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
@@ -41,7 +49,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -100,7 +107,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -184,6 +190,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -323,6 +330,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -335,6 +344,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -407,11 +417,13 @@
 CONFIG_SCC_ENET=y
 # CONFIG_SCC1_ENET is not set
 CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 # CONFIG_ENET_BIG_BUFFERS is not set
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-# CONFIG_8xxSCC is not set
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/common_defconfig linux/arch/ppc/configs/common_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/common_defconfig	Sun Mar  4 14:30:18 2001
+++ linux/arch/ppc/configs/common_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,6 +28,7 @@
 # CONFIG_8xx is not set
 # CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
+# CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
@@ -35,7 +38,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-CONFIG_MOL=y
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -105,7 +107,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -141,6 +142,7 @@
 CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
 CONFIG_IP_NF_MATCH_OWNER=m
@@ -151,8 +153,10 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
@@ -296,6 +300,8 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 CONFIG_SCSI_AIC7XXX=m
+CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
+CONFIG_AIC7XXX_RESET_DELAY=5000
 CONFIG_SCSI_AIC7XXX_OLD=m
 # CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT is not set
 CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8
@@ -376,8 +382,10 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
+# CONFIG_MACE_AAUI_PORT is not set
 CONFIG_BMAC=y
 CONFIG_GMAC=y
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -404,7 +412,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -425,6 +435,7 @@
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
 CONFIG_PPP_ASYNC=y
 # CONFIG_PPP_SYNC_TTY is not set
 CONFIG_PPP_DEFLATE=y
@@ -492,6 +503,7 @@
 CONFIG_FB_IMSTT=y
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -544,6 +556,7 @@
 CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_ADBKEYCODES=y
 CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -612,6 +625,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -624,6 +639,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -680,6 +696,7 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
@@ -707,11 +724,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -719,11 +738,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
@@ -740,6 +760,8 @@
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -814,7 +836,6 @@
 # USB Serial Converter support
 #
 CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
@@ -822,6 +843,7 @@
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
 CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_EDGEPORT is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
 # CONFIG_USB_SERIAL_KEYSPAN is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
diff -urN linux-2.4.5-pre2/arch/ppc/configs/est8260_defconfig linux/arch/ppc/configs/est8260_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/est8260_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/est8260_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -34,7 +36,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -93,7 +94,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -177,6 +177,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -317,6 +318,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -329,6 +332,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
diff -urN linux-2.4.5-pre2/arch/ppc/configs/gemini_defconfig linux/arch/ppc/configs/gemini_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/gemini_defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/configs/gemini_defconfig	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,510 @@
+#
+# Automatically generated make config: don't edit
+#
+# CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Platform support
+#
+CONFIG_PPC=y
+CONFIG_6xx=y
+# CONFIG_4xx is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_8260 is not set
+# CONFIG_ALL_PPC is not set
+CONFIG_GEMINI=y
+# CONFIG_APUS is not set
+# CONFIG_PPC601_SYNC_FIX is not set
+# CONFIG_SMP is not set
+CONFIG_ALTIVEC=y
+CONFIG_MACH_SPECIFIC=y
+
+#
+# General setup
+#
+# CONFIG_HIGHMEM is not set
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_SBUS is not set
+# CONFIG_MCA is not set
+CONFIG_PCI=y
+CONFIG_NET=y
+CONFIG_SYSCTL=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_KCORE_ELF=y
+CONFIG_BINFMT_ELF=y
+CONFIG_KERNEL_ELF=y
+# CONFIG_BINFMT_MISC is not set
+CONFIG_PCI_NAMES=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_PCMCIA is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+# CONFIG_PPC_RTC is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Plug and Play configuration
+#
+# CONFIG_PNP is not set
+# CONFIG_ISAPNP is not set
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+# CONFIG_BLK_DEV_MD is not set
+# CONFIG_MD_LINEAR is not set
+# CONFIG_MD_RAID0 is not set
+# CONFIG_MD_RAID1 is not set
+# CONFIG_MD_RAID5 is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+
+#
+#   IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
+# CONFIG_IP_NF_COMPAT_IPFWADM is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# ATA/IDE/MFM/RLL support
+#
+# CONFIG_IDE is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI support
+#
+CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+CONFIG_SD_EXTRA_DEVS=40
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_SR_EXTRA_DEVS=2
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_DEBUG_QUEUES is not set
+# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_NCR53C406A is not set
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_NCR53C8XX is not set
+CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
+CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
+CONFIG_SCSI_NCR53C8XX_SYNC=20
+# CONFIG_SCSI_NCR53C8XX_PROFILE is not set
+# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_MESH is not set
+# CONFIG_SCSI_MAC53C94 is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_ETHERTAP is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
+# CONFIG_GMAC is not set
+CONFIG_NCR885E=y
+# CONFIG_OAKNET is not set
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# Amateur Radio support
+#
+# CONFIG_HAMRADIO is not set
+
+#
+# IrDA (infrared) support
+#
+# CONFIG_IRDA is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Old CD-ROM drivers (not SCSI, not IDE)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# Console drivers
+#
+# CONFIG_VGA_CONSOLE is not set
+
+#
+# Frame-buffer support
+#
+# CONFIG_FB is not set
+
+#
+# Input core support
+#
+# CONFIG_INPUT is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
+# CONFIG_RAMFS is not set
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+CONFIG_DEVFS_FS=y
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+CONFIG_DEVPTS_FS=y
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+CONFIG_NFSD=y
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+CONFIG_SOLARIS_X86_PARTITION=y
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
+# CONFIG_NLS is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# Kernel hacking
+#
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_KGDB is not set
+CONFIG_XMON=y
diff -urN linux-2.4.5-pre2/arch/ppc/configs/ibmchrp_defconfig linux/arch/ppc/configs/ibmchrp_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/ibmchrp_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/ibmchrp_defconfig	Mon Dec  3 22:43:25 2001
@@ -1,7 +1,9 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -23,8 +25,8 @@
 # CONFIG_4xx is not set
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
-# CONFIG_8260 is not set
 # CONFIG_8xx is not set
+# CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
 # CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
@@ -36,7 +38,6 @@
 # General setup
 #
 CONFIG_HIGHMEM=y
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -101,7 +102,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -137,6 +137,7 @@
 CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
 CONFIG_IP_NF_MATCH_OWNER=m
@@ -147,14 +148,20 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
@@ -184,6 +191,10 @@
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -192,6 +203,10 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
@@ -207,6 +222,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -306,7 +322,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -337,11 +355,9 @@
 # Token Ring devices
 #
 CONFIG_TR=y
-# CONFIG_IBMTR is not set
 CONFIG_IBMOL=y
 # CONFIG_IBMLS is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_SMCTR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
@@ -393,6 +409,7 @@
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -439,6 +456,7 @@
 # CONFIG_MAC_FLOPPY is not set
 # CONFIG_MAC_SERIAL is not set
 # CONFIG_ADB is not set
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -473,6 +491,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -504,6 +526,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -516,6 +540,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -572,6 +597,7 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
@@ -599,11 +625,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -611,11 +639,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
diff -urN linux-2.4.5-pre2/arch/ppc/configs/mbx_defconfig linux/arch/ppc/configs/mbx_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/mbx_defconfig	Mon Jan 22 15:41:14 2001
+++ linux/arch/ppc/configs/mbx_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,9 +28,15 @@
 # CONFIG_RPXLITE is not set
 # CONFIG_RPXCLASSIC is not set
 # CONFIG_BSEIP is not set
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 CONFIG_MBX=y
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
@@ -41,7 +49,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -99,7 +106,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -178,6 +184,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -316,6 +323,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -328,6 +337,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -399,11 +409,14 @@
 #
 CONFIG_SCC_ENET=y
 CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-CONFIG_8xxSCC=y
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+CONFIG_USE_SCC_IO=y
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/oak_defconfig linux/arch/ppc/configs/oak_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/oak_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/oak_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -35,7 +37,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -93,7 +94,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -173,6 +173,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 CONFIG_OAKNET=y
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -312,6 +313,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -324,6 +327,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
diff -urN linux-2.4.5-pre2/arch/ppc/configs/power3_defconfig linux/arch/ppc/configs/power3_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/power3_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/power3_defconfig	Mon Dec  3 22:43:25 2001
@@ -1,7 +1,9 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -27,12 +29,12 @@
 CONFIG_PPC64BRIDGE=y
 CONFIG_ALL_PPC=y
 CONFIG_SMP=y
+# CONFIG_IRQ_ALL_CPUS is not set
 
 #
 # General setup
 #
 CONFIG_HIGHMEM=y
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -105,10 +107,7 @@
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
 CONFIG_MD_RAID5=y
-# CONFIG_MD_BOOT is not set
-# CONFIG_AUTODETECT_RAID is not set
 CONFIG_BLK_DEV_LVM=y
-CONFIG_LVM_PROC_FS=y
 
 #
 # Networking options
@@ -133,6 +132,10 @@
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
@@ -162,6 +165,10 @@
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
@@ -170,6 +177,10 @@
 CONFIG_BLK_DEV_SR_VENDOR=y
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
 # CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 CONFIG_SCSI_CONSTANTS=y
@@ -185,6 +196,7 @@
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
 # CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
@@ -259,6 +271,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -285,7 +298,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -317,11 +332,9 @@
 # Token Ring devices
 #
 CONFIG_TR=y
-# CONFIG_IBMTR is not set
 CONFIG_IBMOL=y
 # CONFIG_IBMLS is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_SMCTR is not set
 # CONFIG_NET_FC is not set
 # CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
@@ -373,6 +386,7 @@
 # CONFIG_FB_IMSTT is not set
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -421,6 +435,7 @@
 # CONFIG_MAC_FLOPPY is not set
 # CONFIG_MAC_SERIAL is not set
 # CONFIG_ADB is not set
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -462,6 +477,10 @@
 # Joysticks
 #
 # CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -507,6 +526,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
@@ -579,11 +599,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -591,11 +613,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
@@ -611,6 +634,8 @@
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -626,7 +651,6 @@
 CONFIG_SOUND_CS4232=m
 # CONFIG_SOUND_SSCAPE is not set
 # CONFIG_SOUND_GUS is not set
-# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_VMIDI is not set
 # CONFIG_SOUND_TRIX is not set
 CONFIG_SOUND_MSS=m
@@ -643,8 +667,8 @@
 # CONFIG_SOUND_YM3812 is not set
 # CONFIG_SOUND_OPL3SA1 is not set
 # CONFIG_SOUND_OPL3SA2 is not set
-# CONFIG_SOUND_YMPCI is not set
 # CONFIG_SOUND_YMFPCI is not set
+# CONFIG_SOUND_YMFPCI_LEGACY is not set
 # CONFIG_SOUND_UART6850 is not set
 # CONFIG_SOUND_AEDSP16 is not set
 CONFIG_SOUND_TVMIXER=y
diff -urN linux-2.4.5-pre2/arch/ppc/configs/rpxcllf_defconfig linux/arch/ppc/configs/rpxcllf_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/rpxcllf_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/rpxcllf_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,9 +28,15 @@
 # CONFIG_RPXLITE is not set
 CONFIG_RPXCLASSIC=y
 # CONFIG_BSEIP is not set
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
@@ -41,7 +49,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -100,7 +107,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -184,6 +190,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -323,6 +330,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -335,6 +344,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -406,11 +416,15 @@
 #
 CONFIG_SCC_ENET=y
 CONFIG_SCC1_ENET=y
+# CONFIG_SCC2_ENET is not set
+# CONFIG_SCC3_ENET is not set
 CONFIG_FEC_ENET=y
+# CONFIG_USE_MDIO is not set
 CONFIG_ENET_BIG_BUFFERS=y
-CONFIG_8xxSMC2=y
-# CONFIG_8xx_ALTSMC2 is not set
-CONFIG_8xxSCC=y
+CONFIG_SMC2_UART=y
+# CONFIG_ALTSMC2 is not set
+# CONFIG_CONS_SMC2 is not set
+CONFIG_USE_SCC_IO=y
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/rpxlite_defconfig linux/arch/ppc/configs/rpxlite_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/rpxlite_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/rpxlite_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,9 +28,15 @@
 CONFIG_RPXLITE=y
 # CONFIG_RPXCLASSIC is not set
 # CONFIG_BSEIP is not set
-# CONFIG_TQM8xxL is not set
+# CONFIG_TQM823L is not set
+# CONFIG_TQM850L is not set
+# CONFIG_TQM855L is not set
 # CONFIG_TQM860L is not set
+# CONFIG_FPS850L is not set
 # CONFIG_TQM860 is not set
+# CONFIG_SPD823TS is not set
+# CONFIG_IVMS8 is not set
+# CONFIG_SM850 is not set
 # CONFIG_MBX is not set
 # CONFIG_WINCEPT is not set
 CONFIG_PPC601_SYNC_FIX=y
@@ -41,7 +49,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -100,7 +107,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -184,6 +190,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -323,6 +330,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -335,6 +344,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
@@ -407,10 +417,11 @@
 CONFIG_SCC_ENET=y
 # CONFIG_SCC1_ENET is not set
 CONFIG_SCC2_ENET=y
+# CONFIG_SCC3_ENET is not set
 # CONFIG_FEC_ENET is not set
 # CONFIG_ENET_BIG_BUFFERS is not set
-# CONFIG_8xxSMC2 is not set
-# CONFIG_8xxSCC is not set
+# CONFIG_SMC2_UART is not set
+# CONFIG_USE_SCC_IO is not set
 
 #
 # Generic MPC8xx Options
diff -urN linux-2.4.5-pre2/arch/ppc/configs/walnut_defconfig linux/arch/ppc/configs/walnut_defconfig
--- linux-2.4.5-pre2/arch/ppc/configs/walnut_defconfig	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/configs/walnut_defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -35,7 +37,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-# CONFIG_MOL is not set
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -93,7 +94,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -173,6 +173,7 @@
 # CONFIG_MACE is not set
 # CONFIG_BMAC is not set
 # CONFIG_GMAC is not set
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -315,6 +316,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -327,6 +330,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
diff -urN linux-2.4.5-pre2/arch/ppc/defconfig linux/arch/ppc/defconfig
--- linux-2.4.5-pre2/arch/ppc/defconfig	Mon Dec  3 22:43:16 2001
+++ linux/arch/ppc/defconfig	Mon Dec  3 22:43:25 2001
@@ -2,6 +2,8 @@
 # Automatically generated make config: don't edit
 #
 # CONFIG_UID16 is not set
+# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 
 #
 # Code maturity level options
@@ -26,6 +28,7 @@
 # CONFIG_8xx is not set
 # CONFIG_8260 is not set
 CONFIG_ALL_PPC=y
+# CONFIG_GEMINI is not set
 # CONFIG_APUS is not set
 CONFIG_PPC601_SYNC_FIX=y
 # CONFIG_SMP is not set
@@ -35,7 +38,6 @@
 # General setup
 #
 # CONFIG_HIGHMEM is not set
-CONFIG_MOL=y
 # CONFIG_ISA is not set
 # CONFIG_EISA is not set
 # CONFIG_SBUS is not set
@@ -105,7 +107,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -141,6 +142,7 @@
 CONFIG_IP_NF_MATCH_MARK=m
 CONFIG_IP_NF_MATCH_MULTIPORT=m
 CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_UNCLEAN=m
 CONFIG_IP_NF_MATCH_OWNER=m
@@ -151,8 +153,10 @@
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
 CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_NAT_FTP=m
 # CONFIG_IP_NF_MANGLE is not set
 # CONFIG_IP_NF_TARGET_LOG is not set
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_COMPAT_IPCHAINS=m
 CONFIG_IP_NF_NAT_NEEDED=y
 # CONFIG_IP_NF_COMPAT_IPFWADM is not set
@@ -375,8 +379,10 @@
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MACE=y
+# CONFIG_MACE_AAUI_PORT is not set
 CONFIG_BMAC=y
 CONFIG_GMAC=y
+# CONFIG_NCR885E is not set
 # CONFIG_OAKNET is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
@@ -403,7 +409,9 @@
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
 # CONFIG_8139TOO is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -424,6 +432,7 @@
 # CONFIG_HIPPI is not set
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
+# CONFIG_PPP_FILTER is not set
 CONFIG_PPP_ASYNC=y
 # CONFIG_PPP_SYNC_TTY is not set
 CONFIG_PPP_DEFLATE=y
@@ -491,6 +500,7 @@
 CONFIG_FB_IMSTT=y
 # CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
+# CONFIG_FB_E1355 is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
@@ -543,6 +553,7 @@
 CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_ADBKEYCODES=y
 CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_MAC_HID=y
 
 #
 # Character devices
@@ -611,6 +622,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -623,6 +636,7 @@
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+CONFIG_TMPFS=y
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
@@ -679,6 +693,7 @@
 CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
 # CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_SGI_PARTITION is not set
@@ -706,11 +721,13 @@
 # CONFIG_NLS_CODEPAGE_865 is not set
 # CONFIG_NLS_CODEPAGE_866 is not set
 # CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
 # CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
 CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -718,11 +735,12 @@
 # CONFIG_NLS_ISO8859_5 is not set
 # CONFIG_NLS_ISO8859_6 is not set
 # CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
 # CONFIG_NLS_ISO8859_15 is not set
 # CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
 # CONFIG_NLS_UTF8 is not set
 
 #
@@ -739,6 +757,8 @@
 # CONFIG_SOUND_ES1371 is not set
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
@@ -813,7 +833,6 @@
 # USB Serial Converter support
 #
 CONFIG_USB_SERIAL=m
-# CONFIG_USB_SERIAL_DEBUG is not set
 # CONFIG_USB_SERIAL_GENERIC is not set
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
@@ -821,6 +840,7 @@
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
 CONFIG_USB_SERIAL_VISOR=m
+# CONFIG_USB_SERIAL_EDGEPORT is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
 # CONFIG_USB_SERIAL_KEYSPAN is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- linux-2.4.5-pre2/arch/ppc/kernel/Makefile	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/kernel/Makefile	Mon Dec  3 22:43:25 2001
@@ -7,12 +7,10 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
+USE_STANDARD_AS_RULE	:= true
+
 ifdef CONFIG_PPC64BRIDGE
-.S.o:
-	$(CC) $(CFLAGS) -D__ASSEMBLY__ -mppc64bridge -c $< -o $*.o
-else
-.S.o:
-	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c $< -o $*.o
+EXTRA_AFLAGS		:= -Wa,-mppc64bridge
 endif
 
 ifeq ($(CONFIG_4xx),y)
@@ -31,7 +29,7 @@
 
 export-objs			:= ppc_ksyms.o prep_setup.o 
 
-obj-$(CONFIG_PPC)		:= entry.o traps.o irq.o idle.o time.o misc.o \
+obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
 					process.o signal.o bitops.o ptrace.o \
 					ppc_htab.o semaphore.o syscalls.o  \
 					align.o setup.o
@@ -54,7 +52,7 @@
 ifeq ($(CONFIG_8xx),y)
 obj-$(CONFIG_PCI)		+= qspan_pci.c
 else
-obj-$(CONFIG_PPC)		+= hashtable.o
+obj-y				+= hashtable.o
 endif
 obj-$(CONFIG_MATH_EMULATION)	+= softemu8xx.o
 obj-$(CONFIG_MBX)		+= i8259.o
@@ -65,6 +63,8 @@
 					indirect_pci.o i8259.o prep_pci.o \
 					prep_time.o prep_nvram.o prep_setup.o
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
+obj-$(CONFIG_GEMINI)		+= gemini_prom.o gemini_pci.o gemini_setup.o \
+					open_pic.o
 obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
 
 
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/apus_setup.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/apus_setup.c	Mon Dec  3 22:43:25 2001
@@ -1017,6 +1017,59 @@
 	0
 };
 
+#define HARDWARE_MAPPED_SIZE (512*1024)
+unsigned long __init apus_find_end_of_memory(void)
+{
+	int shadow = 0;
+	unsigned long total;
+
+	/* The memory size reported by ADOS excludes the 512KB
+	   reserved for PPC exception registers and possibly 512KB
+	   containing a shadow of the ADOS ROM. */
+	{
+		unsigned long size = memory[0].size;
+
+		/* If 2MB aligned, size was probably user
+                   specified. We can't tell anything about shadowing
+                   in this case so skip shadow assignment. */
+		if (0 != (size & 0x1fffff)){
+			/* Align to 512KB to ensure correct handling
+			   of both memfile and system specified
+			   sizes. */
+			size = ((size+0x0007ffff) & 0xfff80000);
+			/* If memory is 1MB aligned, assume
+                           shadowing. */
+			shadow = !(size & 0x80000);
+		}
+
+		/* Add the chunk that ADOS does not see. by aligning
+                   the size to the nearest 2MB limit upwards.  */
+		memory[0].size = ((size+0x001fffff) & 0xffe00000);
+	}
+
+	total = memory[0].size;
+
+	/* Remove the memory chunks that are controlled by special
+           Phase5 hardware. */
+
+	/* Remove the upper 512KB if it contains a shadow of
+	   the ADOS ROM. FIXME: It might be possible to
+	   disable this shadow HW. Check the booter
+	   (ppc_boot.c) */
+	if (shadow)
+		total -= HARDWARE_MAPPED_SIZE;
+
+	/* Remove the upper 512KB where the PPC exception
+	   vectors are mapped. */
+	total -= HARDWARE_MAPPED_SIZE;
+
+	/* Linux/APUS only handles one block of memory -- the one on
+	   the PowerUP board. Other system memory is horrible slow in
+	   comparison. The user can use other memory for swapping
+	   using the z2ram device. */
+	ram_phys_base = memory[0].addr;
+	return total;
+}
 
 __init
 void apus_init_IRQ(void)
@@ -1037,10 +1090,6 @@
 
 	amiga_init_IRQ();
 
-	int_control.int_sti = __no_use_sti;
-	int_control.int_cli = __no_use_cli;
-	int_control.int_save_flags = __no_use_save_flags;
-	int_control.int_restore_flags = __no_use_restore_flags;
 }
 
 __init
@@ -1072,7 +1121,10 @@
 	ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
 	ppc_md.init_IRQ       = apus_init_IRQ;
 	ppc_md.get_irq        = apus_get_irq;
-	ppc_md.post_irq       = apus_post_irq;
+	
+#error Should use the ->end() member of irq_desc[x]. -- Cort
+	/*ppc_md.post_irq       = apus_post_irq;*/
+	
 #ifdef CONFIG_HEARTBEAT
 	ppc_md.heartbeat      = apus_heartbeat;
 	ppc_md.heartbeat_count = 1;
@@ -1091,6 +1143,8 @@
 	ppc_md.set_rtc_time   = apus_set_rtc_time;
 	ppc_md.get_rtc_time   = apus_get_rtc_time;
 	ppc_md.calibrate_decr = apus_calibrate_decr;
+
+	ppc_md.find_end_of_memory = apus_find_end_of_memory;
 
 	ppc_md.nvram_read_val = NULL;
 	ppc_md.nvram_write_val = NULL;
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/bitops.c linux/arch/ppc/kernel/bitops.c
--- linux-2.4.5-pre2/arch/ppc/kernel/bitops.c	Thu Jul 13 09:42:50 2000
+++ linux/arch/ppc/kernel/bitops.c	Mon Dec  3 22:43:25 2001
@@ -16,10 +16,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 	
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%3
-	or	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%3 \n\
+	or	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=m" (*p)
@@ -33,10 +33,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%3
-	andc	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%3 \n\
+	andc	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=m" (*p)
@@ -50,10 +50,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%3
-	xor	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%3 \n\
+	xor	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=m" (*p)
@@ -67,10 +67,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	or	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	or	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -86,10 +86,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	andc	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	andc	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -105,10 +105,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	xor	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	xor	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- linux-2.4.5-pre2/arch/ppc/kernel/chrp_pci.c	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/kernel/chrp_pci.c	Mon Dec  3 22:43:25 2001
@@ -264,6 +264,7 @@
 	}
 }
 
+#if 0
 static struct {
     /* parent is iomem */
     struct resource ram, pci_mem, isa_mem, pci_io, pci_cfg, rom_exp, flash;
@@ -297,62 +298,7 @@
 {
     	bus->resource[1] = &gg2_resources.pci_mem;
 }
-
-/* this is used by the pmac_pci code too... - paulus */
-void process_bridge_ranges(struct pci_controller *hose,
-			   struct device_node *dev, int primary)
-{
-	unsigned int *ranges;
-	int rlen = 0;
-	int memno = 0;
-	struct resource *res;
-
-	hose->io_base_phys = 0;
-	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
-	while ((rlen -= 6 * sizeof(unsigned int)) >= 0) {
-		res = NULL;
-		switch (ranges[0] >> 24) {
-		case 1:		/* I/O space */
-			if (ranges[2] != 0)
-				break;
-			hose->io_base_phys = ranges[3];
-			hose->io_base_virt = ioremap(ranges[3], ranges[5]);
-			if (primary)
-				isa_io_base = (unsigned long) hose->io_base_virt;
-			res = &hose->io_resource;
-			res->flags = IORESOURCE_IO;
-			res->start = ranges[2];
-			break;
-		case 2:		/* memory space */
-			memno = 0;
-			if (ranges[1] == 0 && ranges[2] == 0
-			    && ranges[5] <= (16 << 20)) {
-				/* 1st 16MB, i.e. ISA memory area */
-				if (primary)
-					isa_mem_base = ranges[3];
-				memno = 1;
-			}
-			while (memno < 3 && hose->mem_resources[memno].flags)
-				++memno;
-			if (memno == 0)
-				hose->pci_mem_offset = ranges[3] - ranges[2];
-			if (memno < 3) {
-				res = &hose->mem_resources[memno];
-				res->flags = IORESOURCE_MEM;
-				res->start = ranges[3];
-			}
-			break;
-		}
-		if (res != NULL) {
-			res->name = dev->full_name;
-			res->end = res->start + ranges[5] - 1;
-			res->parent = NULL;
-			res->sibling = NULL;
-			res->child = NULL;
-		}
-		ranges += 6;
-	}
-}
+#endif /* 0 */
 
 /* this is largely modeled and stolen after the pmac_pci code -- tgall
  */
@@ -366,8 +312,10 @@
 	volatile unsigned char *cfg;
 	unsigned int *dma;
 #ifdef CONFIG_POWER3
-	unsigned long *opprop = (unsigned long *)
-		get_property(find_path_device("/"), "platform-open-pic", NULL);
+	struct device_node *root = find_path_device("/");
+	unsigned int *opprop = (unsigned int *)
+		get_property(root, "platform-open-pic", NULL);
+	int i;
 #endif
 
 	for(; dev != NULL; dev = dev->next, ++index) {
@@ -405,10 +353,11 @@
        		hose->cfg_addr = (volatile unsigned int *) cfg;
        		hose->cfg_data = cfg + 0x10;
 
-		process_bridge_ranges(hose, dev, index == 0);
+		pci_process_bridge_OF_ranges(hose, dev, index == 0);
 
 #ifdef CONFIG_POWER3
-                openpic_setup_ISU(index, opprop[index+1]);
+		i = prom_n_addr_cells(root) * (index + 2) - 1;
+                openpic_setup_ISU(index, opprop[i]);
 #endif /* CONFIG_POWER3 */
 
 		/* check the first bridge for a property that we can
@@ -442,7 +391,7 @@
 void __init
 chrp_find_bridges(void)
 {
-	struct device_node *py;
+	struct device_node *py, *dev;
 	char *model, *name;
 	struct pci_controller* hose;
 
@@ -453,7 +402,7 @@
 #else /* CONFIG_POWER4 */
 	model = get_property(find_path_device("/"), "model", NULL);
         if (!strncmp("MOT", model, 3)) {
-		struct pci_controller* hose;
+		struct pci_controller *hose;
 
 		hose = pcibios_alloc_controller();
 		if (!hose)
@@ -463,8 +412,9 @@
         	/* Check that please. This must be the root of the OF
         	 * PCI tree (the root host bridge
         	 */
-               	hose->arch_data = find_devices("pci");
+               	hose->arch_data = dev = find_devices("pci");
                 setup_grackle(hose, 0x20000);
+		pci_process_bridge_OF_ranges(hose, dev, 1);
 		return;
         }
 
@@ -485,25 +435,22 @@
 	/* Check that please. This must be the root of the OF
 	 * PCI tree (the root host bridge
 	 */
-	hose->arch_data = find_devices("pci");
+	hose->arch_data = dev = find_devices("pci");
 	name = get_property(find_path_device("/"), "name", NULL);
 	if (!strncmp("IBM,7043-150", name, 12) ||
 	    !strncmp("IBM,7046-155", name, 12) ||
 	    !strncmp("IBM,7046-B50", name, 12) ) {
 		setup_grackle(hose, 0x01000000);
-		isa_mem_base = 0x80000000;
+		pci_process_bridge_OF_ranges(hose, dev, 1);
 		return;
 	}
 
 	/* LongTrail */
 	hose->ops = &gg2_pci_ops;
 	pci_dram_offset = 0;
-	isa_mem_base = 0xf7000000;
-	hose->io_base_phys = (unsigned long) 0xf8000000;
-	hose->io_base_virt = ioremap(hose->io_base_phys, 0x10000);
-	isa_io_base = (unsigned long) hose->io_base_virt;
-	ppc_md.pcibios_fixup = gg2_pcibios_fixup;
-	ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
+	pci_process_bridge_OF_ranges(hose, find_devices("pci"), 1);
+//	ppc_md.pcibios_fixup = gg2_pcibios_fixup;
+//	ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
 #endif /* CONFIG_POWER4 */
 }
 
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/chrp_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon Dec  3 22:43:25 2001
@@ -67,6 +67,7 @@
 void rtas_indicator_progress(char *, unsigned short);
 void bootx_text_progress(char *, unsigned short);
 
+extern unsigned long pmac_find_end_of_memory(void);
 extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
 extern int pckbd_getkeycode(unsigned int scancode);
 extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
@@ -194,37 +195,36 @@
 				     u8 type)
 {
 	u8 level0, type0, active;
-	struct device_node *root;
-	
-	root = find_path_device("/");
-	if (root &&
-	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13 ) )
-	{
-		/* select logical device */
-		sio_write(device, 0x07);
-		active = sio_read(0x30);
-		level0 = sio_read(0x70);
-		type0 = sio_read(0x71);
-		printk("sio: %s irq level %d, type %d, %sactive: ", name, level0, type0,
-		       !active ? "in" : "");
-		if (level0 == level && type0 == type && active)
-			printk("OK\n");
-		else {
-			printk("remapping to level %d, type %d, active\n", level, type);
-			sio_write(0x01, 0x30);
-			sio_write(level, 0x70);
-			sio_write(type, 0x71);
-		}
-	}
 
+	/* select logical device */
+	sio_write(device, 0x07);
+	active = sio_read(0x30);
+	level0 = sio_read(0x70);
+	type0 = sio_read(0x71);
+	printk("sio: %s irq level %d, type %d, %sactive: ", name, level0,
+	       type0, !active ? "in" : "");
+	if (level0 == level && type0 == type && active)
+		printk("OK\n");
+	else {
+		printk("remapping to level %d, type %d, active\n", level,
+		       type);
+		sio_write(0x01, 0x30);
+		sio_write(level, 0x70);
+		sio_write(type, 0x71);
+	}
 }
 
 static void __init sio_init(void)
 {
-	/* logical device 0 (KBC/Keyboard) */
-	sio_fixup_irq("keyboard", 0, 1, 2);
-	/* select logical device 1 (KBC/Mouse) */
-	sio_fixup_irq("mouse", 1, 12, 2);
+	struct device_node *root;
+
+	if ((root = find_path_device("/")) &&
+	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
+		/* logical device 0 (KBC/Keyboard) */
+		sio_fixup_irq("keyboard", 0, 1, 2);
+		/* select logical device 1 (KBC/Mouse) */
+		sio_fixup_irq("mouse", 1, 12, 2);
+	}
 }
 
 
@@ -263,16 +263,19 @@
 
 #ifndef CONFIG_POWER4
 	/* Some IBM machines don't have the hydra -- Cort */
-	if ( !OpenPIC_Addr )
-	{
+	if (!OpenPIC_Addr) {
+		struct device_node *root;
 		unsigned long *opprop;
+		int n;
 
-		opprop = (unsigned long *)get_property(find_path_device("/"),
-						"platform-open-pic", NULL);
+		root = find_path_device("/");
+		opprop = (unsigned long *) get_property
+			(root, "platform-open-pic", NULL);
+		n = prom_n_addr_cells(root);
 		if (opprop != 0) {
 			printk("OpenPIC addrs: %lx %lx %lx\n",
-			       opprop[0], opprop[1], opprop[2]);
-			OpenPIC_Addr = ioremap(opprop[0], 0x40000);
+			       opprop[n-1], opprop[2*n-1], opprop[3*n-1]);
+			OpenPIC_Addr = ioremap(opprop[n-1], 0x40000);
 		}
 	}
 #endif
@@ -281,6 +284,10 @@
 	 *  Fix the Super I/O configuration
 	 */
 	sio_init();
+
+	/*
+	 *  Setup the console operations
+	 */
 #ifdef CONFIG_DUMMY_CONSOLE
 	conswitchp = &dummy_con;
 #endif
@@ -356,7 +363,7 @@
 {
 	struct device_node *np;
 	int i;
-	unsigned long *addrp;
+	unsigned int *addrp;
 	unsigned char* chrp_int_ack_special = 0;
 	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
 	int nmi_irq = -1;
@@ -365,11 +372,12 @@
 #endif
 
 	if (!(np = find_devices("pci"))
-	    || !(addrp = (unsigned long *)
+	    || !(addrp = (unsigned int *)
 		 get_property(np, "8259-interrupt-acknowledge", NULL)))
 		printk("Cannot find pci to get ack address\n");
 	else
-		chrp_int_ack_special = (unsigned char *)ioremap(*addrp, 1);
+		chrp_int_ack_special = (unsigned char *)
+			ioremap(addrp[prom_n_addr_cells(np)-1], 1);
 	/* hydra still sets OpenPIC_InitSenses to a static set of values */
 	if (OpenPIC_InitSenses == NULL) {
 		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
@@ -553,11 +561,9 @@
 #ifndef CONFIG_POWER4
 	ppc_md.init_IRQ       = chrp_init_IRQ;
 	ppc_md.get_irq        = openpic_get_irq;
-	ppc_md.post_irq	      = NULL;
 #else
 	ppc_md.init_IRQ	      = xics_init_IRQ;
 	ppc_md.get_irq	      = xics_get_irq;
-	ppc_md.post_irq	      = NULL;
 #endif /* CONFIG_POWER4 */
 
 	ppc_md.init           = chrp_init2;
@@ -570,6 +576,8 @@
 	ppc_md.set_rtc_time   = chrp_set_rtc_time;
 	ppc_md.get_rtc_time   = chrp_get_rtc_time;
 	ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
 
 #ifdef CONFIG_VT
 	/* these are adjusted in chrp_init2 if we have an ADB keyboard */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- linux-2.4.5-pre2/arch/ppc/kernel/chrp_time.c	Sun Sep 17 09:48:06 2000
+++ linux/arch/ppc/kernel/chrp_time.c	Mon Dec  3 22:43:25 2001
@@ -29,6 +29,8 @@
 #include <asm/init.h>
 #include <asm/time.h>
 
+extern spinlock_t rtc_lock;
+
 static int nvram_as1 = NVRAM_AS1;
 static int nvram_as0 = NVRAM_AS0;
 static int nvram_data = NVRAM_DATA;
@@ -74,6 +76,7 @@
 	unsigned char save_control, save_freq_select;
 	struct rtc_time tm;
 
+	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
 
 	save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
@@ -112,6 +115,7 @@
 
 	if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
 		time_state = TIME_OK;
+	spin_unlock(&rtc_lock);
 	return 0;
 }
 
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- linux-2.4.5-pre2/arch/ppc/kernel/entry.S	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/entry.S	Mon Dec  3 22:43:25 2001
@@ -30,7 +30,6 @@
 #include <linux/errno.h>
 #include <linux/sys.h>
 #include <linux/config.h>
-#include "mol.h"
 
 #undef SHOW_SYSCALLS
 #undef SHOW_SYSCALLS_TASK
@@ -315,21 +314,12 @@
 	lwz	r5,_MSR(r1)
 	andi.	r5,r5,MSR_EE
 	beq	2f
-	.globl	lost_irq_ret
-lost_irq_ret:
-3:	lis	r4,ppc_n_lost_interrupts@ha
-	lwz	r4,ppc_n_lost_interrupts@l(r4)
-	cmpi	0,r4,0
-	beq+	1f
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	do_IRQ
-	b	3b
-1:	lis	r4,irq_stat@ha		/* &softirq_active for cpu 0 */
+	lis	r4,irq_stat@ha		/* &softirq_active for cpu 0 */
 	addi	r4,r4,irq_stat@l
 #ifdef CONFIG_SMP
 	/* get processor # */
 	lwz	r3,PROCESSOR(r2)
-	slwi	r3,r3,5
+	slwi	r3,r3,LG_CACHE_LINE_SIZE
 	add	r4,r4,r3
 #endif /* CONFIG_SMP */
 	lwz	r5,0(r4)		/* softirq_active */
@@ -351,7 +341,6 @@
 	beq+	do_signal_ret
 	li	r3,0
 	addi	r4,r1,STACK_FRAME_OVERHEAD
-	MOL_HOOK_MMU(8,r8)
 	bl	do_signal
 	.globl	do_signal_ret
 do_signal_ret:
@@ -391,7 +380,6 @@
 	stw	r0,THREAD+KSP(r2)	/* save kernel stack pointer */
 	tophys(r8,r1)
 	CLR_TOP32(r8)
-	MOL_HOOK_MMU(9, r4)		/* mod. r0,r2-r7, lr, ctr */
 	mtspr	SPRG2,r8		/* phys exception stack pointer */	
 1:
 	lwz	r3,_CTR(r1)
@@ -412,29 +400,6 @@
 	lwz	r1,GPR1(r1)
 	SYNC
 	RFI
-
-/*
- * Fake an interrupt from kernel mode.
- * This is used when enable_irq loses an interrupt.
- * We only fill in the stack frame minimally.
- */
-_GLOBAL(fake_interrupt)
-	mflr	r0
-	stw	r0,4(r1)
-	stwu	r1,-INT_FRAME_SIZE(r1)
-	stw	r0,_NIP(r1)
-	stw	r0,_LINK(r1)
-	mfmsr	r3
-	stw	r3,_MSR(r1)
-	li	r0,0x0fac
-	stw	r0,TRAP(r1)
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	li	r4,1
-	bl	do_IRQ
-	addi	r1,r1,INT_FRAME_SIZE
-	lwz	r0,4(r1)
-	mtlr	r0
-	blr
 
 
 /*
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
--- linux-2.4.5-pre2/arch/ppc/kernel/feature.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/feature.c	Mon Dec  3 22:43:25 2001
@@ -2,17 +2,13 @@
  *  arch/ppc/kernel/feature.c
  *
  *  Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *                     Ben. Herrenschmidt (bh40@calva.net)
+ *                     Ben. Herrenschmidt (benh@kernel.crashing.org)
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
  *  as published by the Free Software Foundation; either version
  *  2 of the License, or (at your option) any later version.
  *
- *  BenH: Changed implementation to work on multiple registers
- * 	  polarity is also taken into account. Removed delay (now
- * 	  responsibility of the caller). Added spinlocks.
- *
  */
 #include <linux/config.h>
 #include <linux/types.h>
@@ -29,11 +25,12 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/feature.h>
+#include <asm/dbdma.h>
+#include <asm/machdep.h>
 
 #undef DEBUG_FEATURE
 
 #define MAX_FEATURE_CONTROLLERS		2
-#define MAX_FEATURE_OFFSET		0x100
 #define FREG(c,r)			(&(((c)->reg)[(r)>>2]))
 
 /* Keylargo reg. access. */
@@ -56,9 +53,7 @@
 	unsigned int	mask;		/* bit mask */
 } fbit;
 
-/* I don't have an OHare machine to test with, so I left those as they
- * were. Someone with such a machine chould check out what OF says and
- * try too see if they match the heathrow ones and should be changed too
+/* Those features concern for OHare-based PowerBooks (2400, 3400, 3500)
  */
 static fbit feature_bits_ohare_pbook[] = {
 	{0x38,0,0},			/* FEATURE_null */
@@ -159,11 +154,12 @@
 
 /*
  * Those bits are from a 1999 G3 PowerBook, with a paddington chip.
- * Mostly the same as the heathrow.
+ * Mostly the same as the heathrow. They are used on both PowerBooks
+ * and desktop machines using the paddington chip
  */
 static fbit feature_bits_paddington[] = {
 	{0x38,0,0},			/* FEATURE_null */
-	{0x38,0,0},			/* FEATURE_Serial_reset */
+	{0x38,0,PADD_RESET_SCC},	/* FEATURE_Serial_reset */
 	{0x38,0,HRW_SCC_ENABLE},	/* FEATURE_Serial_enable */
 	{0x38,0,HRW_SCCA_IO},		/* FEATURE_Serial_IO_A */
 	{0x38,0,HRW_SCCB_IO},		/* FEATURE_Serial_IO_B */
@@ -192,6 +188,7 @@
 };
 
 /* Those bits are for Core99 machines (iBook,G4,iMacSL/DV,Pismo,...).
+ * Note: Different sets may be needed for iBook, especially for sound
  */
 static fbit feature_bits_keylargo[] = {
 	{0x38,0,0},			/* FEATURE_null */
@@ -201,13 +198,13 @@
 	{0x38,0,KL0_SCC_B_INTF_ENABLE},	/* FEATURE_Serial_IO_B */
 	{0x38,0,0},			/* FEATURE_SWIM3_enable */
 	{0x38,0,0},			/* FEATURE_MESH_enable */
-	{0x3c,0,0},			/* FEATURE_IDE0_enable */
+	{0x3c,0,KL1_EIDE0_ENABLE},	/* FEATURE_IDE0_enable */
  	{0x3c,1,KL1_EIDE0_RESET_N},	/* FEATURE_IDE0_reset */
 	{0x38,0,0},			/* FEATURE_IOBUS_enable */
-	{0x34,1,0x00000200},		/* FEATURE_Mediabay_reset */
-	{0x34,1,0x00000400},		/* FEATURE_Mediabay_power */
+	{0x34,1,KL_MBCR_MB0_DEV_RESET},	/* FEATURE_Mediabay_reset */
+	{0x34,1,KL_MBCR_MB0_DEV_POWER},	/* FEATURE_Mediabay_power */
 	{0x38,0,0},			/* FEATURE_Mediabay_PCI_enable */
-	{0x3c,0,0x0},			/* FEATURE_IDE1_enable */
+	{0x3c,0,KL1_EIDE1_ENABLE},	/* FEATURE_IDE1_enable */
 	{0x3c,1,KL1_EIDE1_RESET_N},	/* FEATURE_IDE1_reset */
 	{0x38,0,0},			/* FEATURE_Mediabay_floppy_enable */
 	{0x38,0,0},			/* FEATURE_BMac_reset */
@@ -216,10 +213,10 @@
 	{0x38,0,0},			/* FEATURE_Slow_SCC_PCLK */
 	{0x38,0,0},			/* FEATURE_Sound_Power */
 	{0x38,0,0},			/* FEATURE_Sound_CLK_Enable */
-	{0x38,0,0},			/* FEATURE_IDE2_enable */
+	{0x3c,0,KL1_UIDE_ENABLE},	/* FEATURE_IDE2_enable */
 	{0x3c,1,KL1_UIDE_RESET_N},	/* FEATURE_IDE2_reset */
-	{0x34,0,KL_MBCR_MBDEV_ENABLE},	/* FEATURE_Mediabay_IDE_switch */
-	{0x34,0,0x00000100},		/* FEATURE_Mediabay_content */
+	{0x34,0,KL_MBCR_MB0_DEV_ENABLE},/* FEATURE_Mediabay_IDE_switch */
+	{0x34,0,KL_MBCR_MB0_ENABLE},	/* FEATURE_Mediabay_content */
 	{0x40,1,KL2_AIRPORT_RESET_N},	/* FEATURE_Airport_reset */
 };
 
@@ -238,6 +235,8 @@
 static struct feature_controller*
 feature_lookup_controller(struct device_node *device);
 
+static void uninorth_init(void);
+static void keylargo_init(void);
 #ifdef CONFIG_PMAC_PBOOK
 static void heathrow_prepare_for_sleep(struct feature_controller* ctrler);
 static void heathrow_wakeup(struct feature_controller* ctrler);
@@ -245,32 +244,80 @@
 static void core99_wake_up(struct feature_controller* ctrler);
 #endif /* CONFIG_PMAC_PBOOK */
 
-static void keylargo_init(void);
-static void uninorth_init(void);
-
 /* static variables */
 static struct feature_controller	controllers[MAX_FEATURE_CONTROLLERS];
 static int				controller_count = 0;
 
 /* Core99 stuffs */
-static volatile u32*			uninorth_base = NULL;
-static volatile u32*			keylargo_base = NULL;
+/*static*/ volatile u32*		uninorth_base;
+static volatile u32*			keylargo_base;
+static struct feature_controller*	keylargo;
 static int				uninorth_rev;
 static int				keylargo_rev;
+static u32				board_features;
+static u8				airport_pwr_regs[5];
+static int				airport_pwr_state;
+static struct device_node*		airport_dev;
+
+#define FTR_NEED_OPENPIC_TWEAK		0x00000001
+#define FTR_CAN_NAP			0x00000002
+#define FTR_HAS_FW_POWER		0x00000004
+#define FTR_CAN_SLEEP			0x00000008
+
+static struct board_features_t {
+	char*	compatible;
+	u32	features;
+} board_features_datas[] __init = 
+{
+  {	"AAPL,PowerMac G3",	0				}, /* Beige G3 */
+  {	"iMac,1",		0				}, /* First iMac (gossamer) */
+  {	"PowerMac1,1",		0				}, /* B&W G3 / Yikes */
+  {	"PowerMac1,2",		0				}, /* B&W G3 / Yikes */
+  {	"PowerMac2,1",		FTR_CAN_SLEEP			}, /* r128 based iMac */
+  {	"PowerMac2,2",		FTR_HAS_FW_POWER|FTR_CAN_SLEEP	}, /* Summer 2000 iMac */
+  {	"PowerMac4,1",		FTR_CAN_SLEEP			}, /* iMac "Flower Power" */
+  {	"PowerMac3,1",		FTR_NEED_OPENPIC_TWEAK		}, /* Sawtooth (G4) */
+  {	"PowerMac3,2",		0				}, /* G4/Dual G4 */
+  {	"PowerMac3,3",		FTR_NEED_OPENPIC_TWEAK		}, /* G4/Dual G4 */
+  {	"PowerMac5,1",		0				}, /* Cube */
+  {	"AAPL,3400/2400",	FTR_CAN_SLEEP			}, /* 2400/3400 PowerBook */
+  {	"AAPL,3500",		FTR_CAN_SLEEP			}, /* 3500 PowerBook (G3) */
+  {	"AAPL,PowerBook1998",	FTR_CAN_SLEEP			}, /* Wallstreet PowerBook */
+  {	"PowerBook1,1",		FTR_CAN_SLEEP			}, /* 101 (Lombard) PowerBook */
+  {	"PowerBook2,1",		FTR_CAN_SLEEP 			}, /* iBook */
+  {	"PowerBook2,2",		FTR_CAN_SLEEP /*| FTR_CAN_NAP*/	}, /* iBook FireWire */
+  {	"PowerBook3,1",		FTR_CAN_SLEEP|FTR_CAN_NAP|	   /* PowerBook 2000 (Pismo) */
+  				FTR_HAS_FW_POWER		}, 
+  {	"PowerBook3,2",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* PowerBook Titanium */
+  {	"PowerBook4,1",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* New polycarbonate iBook */
+  {	NULL, 0 }
+};
+
+extern unsigned long powersave_nap;
 
-/*
- * WARNING ! This function is called early in setup_arch, neither the IO base
- * nor the udelay calibration have been done yet
- */
 void
 feature_init(void)
 {
 	struct device_node *np;
 	u32 *rev;
-	
+	int i;
+
 	if (_machine != _MACH_Pmac)
 		return;
 
+	/* Figure out motherboard type & options */
+	for(i=0;board_features_datas[i].compatible;i++) {
+		if (machine_is_compatible(board_features_datas[i].compatible)) {
+			board_features = board_features_datas[i].features;
+			break;
+		}
+	}
+
+	/* Set default value of powersave_nap on machines that support it */
+	if (board_features & FTR_CAN_NAP)
+		powersave_nap = 1;
+		
+	/* Track those poor mac-io's */
 	np = find_devices("mac-io");
 	while (np != NULL) {
 		/* KeyLargo contains several (5 ?) FCR registers in mac-io,
@@ -280,13 +327,25 @@
 			struct feature_controller* ctrler =
 				feature_add_controller(np, feature_bits_keylargo);
 			if (ctrler) {
+				keylargo = ctrler;
 				keylargo_base = ctrler->reg;
 				rev = (u32 *)get_property(ctrler->device, "revision-id", NULL);
 				if (rev)
 					keylargo_rev = *rev;
+				
+				rev = (u32 *)get_property(ctrler->device, "device-id", NULL);
+				if (rev && (*rev) == 0x0025)
+					keylargo_rev |= KL_PANGEA_REV;
 			}
 		} else if (device_is_compatible(np, "paddington")) {
 			feature_add_controller(np, feature_bits_paddington);
+			/* We disable the modem power bit on Yikes as it can
+			 * do bad things (it's the nvram power)
+			 */
+			if (machine_is_compatible("PowerMac1,1") ||
+				machine_is_compatible("PowerMac1,2")) {
+				feature_bits_paddington[FEATURE_Modem_power].mask = 0;
+			}
 		} else if (machine_is_compatible("AAPL,PowerBook1998")) {
 			feature_add_controller(np, feature_bits_wallstreet);
 		} else {
@@ -311,11 +370,12 @@
 		}
 	}
 
-	/* Handle core99 Uni-N */
+	/* Locate core99 Uni-N */
 	np = find_devices("uni-n");
 	if (np && np->n_addrs > 0) {
 		uninorth_base = ioremap(np->addrs[0].address, 0x1000);
 		uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+		printk("Uninorth at 0x%08x\n", np->addrs[0].address);
 	}
 	if (uninorth_base && keylargo_base)
 		printk("Uni-N revision: %d, KeyLargo revision: %d\n",
@@ -360,8 +420,12 @@
 		return NULL;
 	}
 
+	/* We remap the entire mac-io here. Normally, this will just
+	 * give us back our already existing BAT mapping
+	 */
 	controller->reg		= (volatile u32 *)ioremap(
-		controller_device->addrs[0].address, MAX_FEATURE_OFFSET);
+		controller_device->addrs[0].address,
+		controller_device->addrs[0].size);
 
 	if (bits == NULL) {
 		printk(KERN_INFO "Twiddling the magic ohare bits\n");
@@ -495,6 +559,12 @@
 	return bit->polarity ? (value == 0) : (value == bit->mask);
 }
 
+int
+feature_can_sleep(void)
+{
+	return ((board_features & FTR_CAN_SLEEP) != 0);	
+}
+
 /*
  * Core99 functions
  * 
@@ -506,53 +576,220 @@
 void
 feature_set_gmac_power(struct device_node* device, int power)
 {
-	if (!uninorth_base)
+	unsigned long flags;
+	
+	if (!uninorth_base || !keylargo)
 		return;
+		
+	/* TODO: Handle save/restore of PCI config space here
+	 */
+
+	spin_lock_irqsave(&keylargo->lock, flags);
 	if (power)
 		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
 	else
 		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+	spin_unlock_irqrestore(&keylargo->lock, flags);
 	udelay(20);
 }
 
 void
-feature_set_gmac_phy_reset(struct device_node* device, int reset)
+feature_gmac_phy_reset(struct device_node* device)
 {
-	if (!keylargo_base)
+	unsigned long flags;
+	
+	if (!keylargo_base || !keylargo)
 		return;
-	out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET), reset);
+		
+	spin_lock_irqsave(&keylargo->lock, flags);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET),
+		KEYLARGO_GPIO_OUTPUT_ENABLE);
+	(void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET));
+	spin_unlock_irqrestore(&keylargo->lock, flags);
+	mdelay(10);
+	spin_lock_irqsave(&keylargo->lock, flags);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET),
+		KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
 	(void)in_8((volatile u8 *)KL_FCR(KL_GPIO_ETH_PHY_RESET));
+	spin_unlock_irqrestore(&keylargo->lock, flags);
+	mdelay(10);
 }
 
 /* Pass the node of the correct controller, please */
 void
 feature_set_usb_power(struct device_node* device, int power)
 {
+	char* prop;
+	int number;
+	u32 reg;
+	
+	unsigned long flags;
+	
+	if (!keylargo_base || !keylargo)
+		return;
+		
+	prop = (char *)get_property(device, "AAPL,clock-id", NULL);
+	if (!prop)
+		return;
+	if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
+		number = 0;
+	else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
+		number = 2;
+	else
+		return;
+
+	spin_lock_irqsave(&keylargo->lock, flags);
+	if (power) {
+		/* Turn ON */
+			
+		if (number == 0) {
+			KL_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			mdelay(1);
+			KL_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+		} else {
+			KL_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			mdelay(1);
+			KL_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+		}
+		reg = KL_IN(KEYLARGO_FCR4);
+		reg &=	~(KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
+			KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number));
+		reg &=	~(KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
+			KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1));
+		KL_OUT(KEYLARGO_FCR4, reg);
+		(void)KL_IN(KEYLARGO_FCR4);
+		udelay(10);
+	} else {
+		/* Turn OFF */
+		
+		reg = KL_IN(KEYLARGO_FCR4);
+		reg |=	KL4_SET_PORT_ENABLE(number) | KL4_SET_PORT_RESUME(number) |
+			KL4_SET_PORT_CONNECT(number) | KL4_SET_PORT_DISCONNECT(number);
+		reg |=	KL4_SET_PORT_ENABLE(number+1) | KL4_SET_PORT_RESUME(number+1) |
+			KL4_SET_PORT_CONNECT(number+1) | KL4_SET_PORT_DISCONNECT(number+1);
+		KL_OUT(KEYLARGO_FCR4, reg);
+		(void)KL_IN(KEYLARGO_FCR4);
+		udelay(1);
+		if (number == 0) {
+			KL_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+			(void)KL_IN(KEYLARGO_FCR0);
+			udelay(1);
+			KL_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			(void)KL_IN(KEYLARGO_FCR0);
+		} else {
+			KL_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+			(void)KL_IN(KEYLARGO_FCR0);
+			udelay(1);
+			KL_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			(void)KL_IN(KEYLARGO_FCR0);
+		}
+		udelay(1);
+	}
+	spin_unlock_irqrestore(&keylargo->lock, flags);
 }
 
-/* Not yet implemented */
 void 
 feature_set_firewire_power(struct device_node* device, int power)
 {
+	unsigned long flags;
+
+	/* TODO: Handle save/restore of PCI config space here
+	 */
+		
 	if (!uninorth_base)
 		return;
+	spin_lock_irqsave(&keylargo->lock, flags);
 	if (power)
 		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
 	else
 		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
 	udelay(20);
+	spin_unlock_irqrestore(&keylargo->lock, flags);
+}
+
+/* Warning: will kill the PHY.. */
+void 
+feature_set_firewire_cable_power(struct device_node* device, int power)
+{
+	unsigned long flags;
+	u8 gpioValue = power ? 0 : 4;
+	
+	if (!keylargo_base || !(board_features & FTR_HAS_FW_POWER))
+		return;
+	spin_lock_irqsave(&keylargo->lock, flags);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER), gpioValue);
+	(void)in_8((volatile u8 *)KL_FCR(KL_GPIO_FW_CABLE_POWER));
+	spin_unlock_irqrestore(&keylargo->lock, flags);		
 }
 
 #ifdef CONFIG_SMP
 void
-feature_core99_kick_cpu1(void)
+feature_core99_kick_cpu(int cpu_nr)
 {
-	out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_UP);
+#if 1 /* New way */
+	const int reset_lines[] = {	KL_GPIO_RESET_CPU0,
+					KL_GPIO_RESET_CPU1,
+					KL_GPIO_RESET_CPU2,
+					KL_GPIO_RESET_CPU3 };
+	volatile u8* reset_io;
+
+	if (!keylargo_base || cpu_nr > 3)
+		return;
+	reset_io = (volatile u8*)KL_FCR(reset_lines[cpu_nr]);
+	out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
 	udelay(1);
-	out_8((volatile u8 *)KL_FCR(KL_GPIO_KICK_CPU1), KL_GPIO_KICK_CPU1_DOWN);
+	out_8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+#else
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_ASSERT);
+	udelay(1);
+	out_8((volatile u8 *)KL_FCR(KL_GPIO_EXTINT_CPU1), KL_GPIO_EXTINT_CPU1_RELEASE);
+#endif	
 }
 #endif /* CONFIG_SMP */
 
+void
+feature_set_airport_power(struct device_node* device, int power)
+{
+	if (!keylargo_base || !airport_dev || airport_dev != device)
+		return;
+	if (airport_pwr_state == power)
+		return;
+	if (power) {
+		/* Some if this is from Darwin code, some is from tracing of
+		 * MacOS driver with Macsbug. Some real bit definitions would
+		 * really help here...
+		 */
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), airport_pwr_regs[0]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), airport_pwr_regs[1]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), airport_pwr_regs[2]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), airport_pwr_regs[3]);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), airport_pwr_regs[4]);
+		udelay(20);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 5);
+		udelay(20);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 4);
+		mdelay(20);
+		KL_BIC(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
+		udelay(10);
+		out_8((volatile u8*)KL_FCR(0x1a3e0), 0x41);
+		udelay(10);
+		KL_BIS(KEYLARGO_FCR2, KL2_AIRPORT_RESET_N);
+		udelay(10);
+	} else {
+		airport_pwr_regs[0] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0));
+		airport_pwr_regs[1] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1));
+		airport_pwr_regs[2] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2));
+		airport_pwr_regs[3] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3));
+		airport_pwr_regs[4] = in_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4));
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_0), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_1), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_2), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_3), 0);
+		out_8((volatile u8*)KL_FCR(KL_GPIO_AIRPORT_4), 0);
+	}
+	airport_pwr_state = power;	
+}
+
 /* Initialize the Core99 UniNorth host bridge and memory controller
  */
 static void
@@ -563,51 +800,106 @@
 	
 	/* Set the arbitrer QAck delay according to what Apple does
 	 */
-	actrl = in_be32(UN_REG(UNI_N_ARB_CTRL)) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
-	actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 : UNI_N_ARB_CTRL_QACK_DELAY)
-		<< UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
-	UN_OUT(UNI_N_ARB_CTRL, actrl);
+	if (uninorth_rev < 0x10) {
+		actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
+		actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
+			UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+		UN_OUT(UNI_N_ARB_CTRL, actrl);
+	}
 	
-	/* 
-	 * Turns OFF the gmac clock. The gmac driver will turn
-	 * it back ON when the interface is enabled. This save
-	 * power on portables.
-	 * 
-	 * Note: We could also try to turn OFF the PHY. Since this
-	 * has to be done by both the gmac driver and this code,
-	 * I'll probably end-up moving some of this out of the
-	 * modular gmac driver into a non-modular stub containing
-	 * some basic PHY management and power management stuffs
+	/* Enable GMAC for now for PCI probing. It will be disabled
+	 * later on after PCI probe
 	 */
 	gmac = find_devices("ethernet");
-
 	while(gmac) {
 		if (device_is_compatible(gmac, "gmac"))
 			break;
 		gmac = gmac->next;
 	}
 	if (gmac)
-		feature_set_gmac_power(gmac, 0);
+		feature_set_gmac_power(gmac, 1);
 
-	/* Kludge (enable FW before PCI probe) */
+	/* Enable FW before PCI probe. Will be disabled later on
+	 */
 	fw = find_devices("firewire");
 	if (fw && device_is_compatible(fw, "pci106b,18"))
 		feature_set_firewire_power(fw, 1);
 }
 
-/* Initialize the Core99 KeyLargo ASIC. Currently, we just make sure
- * OpenPIC is enabled
+/* Initialize the Core99 KeyLargo ASIC. 
  */
 static void
 keylargo_init(void)
 {
+	struct device_node* np;
+	
 	KL_BIS(KEYLARGO_FCR2, KL2_MPIC_ENABLE);
+
+	/* Lookup for an airport card, and disable it if found
+	 * to save power (will be re-enabled by driver if used)
+	 */
+	np = find_devices("radio");
+	if (np && np->parent == keylargo->device)
+		airport_dev = np;
+
+	if (airport_dev) {
+		airport_pwr_state = 1;
+		feature_set_airport_power(airport_dev, 0);
+	}
+	
 }
 
 #ifdef CONFIG_PMAC_PBOOK
+void
+feature_prepare_for_sleep(void)
+{
+	/* We assume gatwick is second */
+	struct feature_controller* ctrler = &controllers[0];
+
+	if (controller_count > 1 &&
+		device_is_compatible(ctrler->device, "gatwick"))
+		ctrler = &controllers[1];
+
+	if (ctrler->bits == feature_bits_heathrow ||
+		ctrler->bits == feature_bits_paddington) {
+		heathrow_prepare_for_sleep(ctrler);
+		return;
+	}
+	if (ctrler->bits == feature_bits_keylargo) {
+		core99_prepare_for_sleep(ctrler);
+		return;
+	}
+}
+
+
+void
+feature_wake_up(void)
+{
+	struct feature_controller* ctrler = &controllers[0];
+
+	if (controller_count > 1 &&
+		device_is_compatible(ctrler->device, "gatwick"))
+		ctrler = &controllers[1];
+	
+	if (ctrler->bits == feature_bits_heathrow ||
+		ctrler->bits == feature_bits_paddington) {
+		heathrow_wakeup(ctrler);
+		return;
+	}
+	if (ctrler->bits == feature_bits_keylargo) {
+		core99_wake_up(ctrler);
+		return;
+	}
+}
 
 static u32 save_fcr[5];
 static u32 save_mbcr;
+static u32 save_gpio_levels[2];
+static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT];
+static u8 save_gpio_normal[KEYLARGO_GPIO_CNT];
+static u32 save_unin_clock_ctl;
+static struct dbdma_regs save_dbdma[13];
+
 
 static void
 heathrow_prepare_for_sleep(struct feature_controller* ctrler)
@@ -631,60 +923,226 @@
 }
 
 static void
-core99_prepare_for_sleep(struct feature_controller* ctrler)
+turn_off_keylargo(void)
 {
-	/* Not yet implemented */
+	u32 temp;
+
+	/* For now, suspending the USB ref cause the machine to die on
+	 * wakeup -- BenH
+	 */
+#if 0
+	mdelay(1);
+	KL_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
+	(void)KL_IN(KEYLARGO_FCR0);
+	mdelay(1500);
+#endif
+
+	KL_BIC(KEYLARGO_FCR0,	KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+		      		KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
+		      		KL0_IRDA_CLK19_ENABLE);
+
+	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
+	KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
+	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
+
+	KL_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
+		KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
+		KL1_UIDE_ENABLE);
+	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
+
+	KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
+ 	udelay(10);
+ 	KL_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
+ 	udelay(10);
+	temp = KL_IN(KEYLARGO_FCR3);
+	if (keylargo_rev >= 2)
+		temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
+		
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
+	temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
+		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+	KL_OUT(KEYLARGO_FCR3, temp);
+	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
 }
 
 static void
-core99_wake_up(struct feature_controller* ctrler)
+turn_off_pangea(void)
 {
-	/* Not yet implemented */
+	u32 temp;
+
+	KL_BIC(KEYLARGO_FCR0,	KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+				KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
+
+	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
+	KL_BIS(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_ENABLE);
+	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
+
+	KL_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_UIDE_ENABLE);
+	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
+
+	KL_BIS(KEYLARGO_FCR2, KL2_MODEM_POWER_N);
+ 	udelay(10);
+	temp = KL_IN(KEYLARGO_FCR3);
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35;
+	temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
+		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+	KL_OUT(KEYLARGO_FCR3, temp);
+	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
 }
 
-void
-feature_prepare_for_sleep(void)
+static void
+core99_prepare_for_sleep(struct feature_controller* ctrler)
 {
-	/* We assume gatwick is second */
-	struct feature_controller* ctrler = &controllers[0];
+	int i;
+	u8* base8;
+	
+	/*
+	 * Save various bits of KeyLargo
+	 */
 
-	if (!ctrler)
-		return;
-	if (controller_count > 1 &&
-		device_is_compatible(ctrler->device, "gatwick"))
-		ctrler = &controllers[1];
+	/* We power off the wireless slot in case it was not done
+	 * by the driver. We don't power it on automatically however
+	 */
+	feature_set_airport_power(airport_dev, 0);
 
-	if (ctrler->bits == feature_bits_heathrow ||
-		ctrler->bits == feature_bits_paddington) {
-		heathrow_prepare_for_sleep(ctrler);
-		return;
+	/* We power off the FW cable. Should be done by the driver... */
+	feature_set_firewire_cable_power(NULL, 0);
+	 
+	/* Save the state of the various GPIOs */
+	save_gpio_levels[0] = KL_IN(KEYLARGO_GPIO_LEVELS0);
+	save_gpio_levels[1] = KL_IN(KEYLARGO_GPIO_LEVELS1);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_EXTINT_0);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		save_gpio_extint[i] = in_8(base8+i);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_0);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		save_gpio_normal[i] = in_8(base8+i);
+
+	/* Save the FCRs */
+	save_mbcr = KL_IN(KEYLARGO_MBCR);
+	save_fcr[0] = KL_IN(KEYLARGO_FCR0);
+	save_fcr[1] = KL_IN(KEYLARGO_FCR1);
+	save_fcr[2] = KL_IN(KEYLARGO_FCR2);
+	save_fcr[3] = KL_IN(KEYLARGO_FCR3);
+	save_fcr[4] = KL_IN(KEYLARGO_FCR4);
+
+	/* Save state & config of DBDMA channels */
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
+			(keylargo_base + ((0x8000+i*0x100)>>2));
+		save_dbdma[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
+		save_dbdma[i].cmdptr = in_le32(&chan->cmdptr);
+		save_dbdma[i].intr_sel = in_le32(&chan->intr_sel);
+		save_dbdma[i].br_sel = in_le32(&chan->br_sel);
+		save_dbdma[i].wait_sel = in_le32(&chan->wait_sel);
 	}
-	if (ctrler->bits == feature_bits_keylargo) {
-		core99_prepare_for_sleep(ctrler);
-		return;
+
+	/*
+	 * Turn off as much as we can
+	 */
+	if (keylargo_rev & KL_PANGEA_REV)
+		turn_off_pangea();
+	else
+		turn_off_keylargo();
+	
+	/* 
+	 * Put the host bridge to sleep
+	 */
+
+	save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
+		~(UNI_N_CLOCK_CNTL_GMAC|UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
+	udelay(100);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
+
+	/*
+	 * FIXME: A bit of black magic with OpenPIC (don't ask me why)
+	 */
+	if (board_features & FTR_NEED_OPENPIC_TWEAK) {
+		KL_BIS(0x506e0, 0x00400000);
+		KL_BIS(0x506e0, 0x80000000);
 	}
 }
 
-void
-feature_wake_up(void)
+static void
+core99_wake_up(struct feature_controller* ctrler)
 {
-	struct feature_controller* ctrler = &controllers[0];
+	int i;
+	u8* base8;
 
-	if (!ctrler)
-		return;
-	if (controller_count > 1 &&
-		device_is_compatible(ctrler->device, "gatwick"))
-		ctrler = &controllers[1];
+	/*
+	 * Wakeup the host bridge
+	 */
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+	udelay(10);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+	udelay(10);
 	
-	if (ctrler->bits == feature_bits_heathrow ||
-		ctrler->bits == feature_bits_paddington) {
-		heathrow_wakeup(ctrler);
-		return;
+	/*
+	 * Restore KeyLargo
+	 */
+	 
+	KL_OUT(KEYLARGO_MBCR, save_mbcr);
+	(void)KL_IN(KEYLARGO_MBCR); udelay(10);
+	KL_OUT(KEYLARGO_FCR0, save_fcr[0]);
+	(void)KL_IN(KEYLARGO_FCR0); udelay(10);
+	KL_OUT(KEYLARGO_FCR1, save_fcr[1]);
+	(void)KL_IN(KEYLARGO_FCR1); udelay(10);
+	KL_OUT(KEYLARGO_FCR2, save_fcr[2]);
+	(void)KL_IN(KEYLARGO_FCR2); udelay(10);
+	KL_OUT(KEYLARGO_FCR3, save_fcr[3]);
+	(void)KL_IN(KEYLARGO_FCR3); udelay(10);
+	KL_OUT(KEYLARGO_FCR4, save_fcr[4]);
+	(void)KL_IN(KEYLARGO_FCR4); udelay(10);
+
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
+			(keylargo_base + ((0x8000+i*0x100)>>2));
+		out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
+		while (in_le32(&chan->status) & ACTIVE)
+			mb();
+		out_le32(&chan->cmdptr_hi, save_dbdma[i].cmdptr_hi);
+		out_le32(&chan->cmdptr, save_dbdma[i].cmdptr);
+		out_le32(&chan->intr_sel, save_dbdma[i].intr_sel);
+		out_le32(&chan->br_sel, save_dbdma[i].br_sel);
+		out_le32(&chan->wait_sel, save_dbdma[i].wait_sel);
 	}
-	if (ctrler->bits == feature_bits_keylargo) {
-		core99_wake_up(ctrler);
-		return;
+
+	KL_OUT(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
+	KL_OUT(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_EXTINT_0);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		out_8(base8+i, save_gpio_extint[i]);
+	base8 = (u8 *)KL_FCR(KEYLARGO_GPIO_0);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		out_8(base8+i, save_gpio_normal[i]);
+
+	/* FIXME more black magic with OpenPIC ... */
+	if (board_features & FTR_NEED_OPENPIC_TWEAK) {
+		KL_BIC(0x506e0, 0x00400000);
+		KL_BIC(0x506e0, 0x80000000);
 	}
-}
 
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
+	udelay(100);
+}
 #endif /* CONFIG_PMAC_PBOOK */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/gemini_pci.c linux/arch/ppc/kernel/gemini_pci.c
--- linux-2.4.5-pre2/arch/ppc/kernel/gemini_pci.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_pci.c	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,121 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+
+#include <asm/machdep.h>
+#include <asm/gemini.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pci-bridge.h>
+
+#include "pci.h"
+
+#define pci_config_addr(bus,dev,offset) \
+        (0x80000000 | (bus<<16) | (dev<<8) | offset)
+
+
+int
+gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val)
+{
+	unsigned long reg;
+	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					   (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val)
+{
+	unsigned long reg;
+	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					   (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val)
+{
+	*val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3))));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3)));
+
+	reg = grackle_read(addr);
+	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write(addr, reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3)));
+
+	reg = grackle_read(addr);
+	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write(addr, reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val)
+{
+	grackle_write(pci_config_addr(dev->bus->number, dev->devfn,
+				      (offset & ~(0x3))), val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops gemini_pci_ops =
+{
+	gemini_pcibios_read_config_byte,
+	gemini_pcibios_read_config_word,
+	gemini_pcibios_read_config_dword,
+	gemini_pcibios_write_config_byte,
+	gemini_pcibios_write_config_word,
+	gemini_pcibios_write_config_dword
+};
+
+void __init gemini_pcibios_fixup(void)
+{
+	int i;
+	struct pci_dev *dev;
+	
+	pci_for_each_dev(dev) {
+		for(i = 0; i < 6; i++) {
+			if (dev->resource[i].flags & IORESOURCE_IO) {
+				dev->resource[i].start |= (0xfe << 24);
+				dev->resource[i].end |= (0xfe << 24);
+			}
+		}
+	}
+}
+
+
+/* The "bootloader" for Synergy boards does none of this for us, so we need to
+   lay it all out ourselves... --Dan */
+void __init gemini_find_bridges(void)
+{
+	struct pci_controller* hose;
+	
+	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+	hose->ops = &gemini_pci_ops;
+}
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/gemini_prom.S linux/arch/ppc/kernel/gemini_prom.S
--- linux-2.4.5-pre2/arch/ppc/kernel/gemini_prom.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_prom.S	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,96 @@
+/*
+ *  arch/ppc/kernel/gemini_prom.S
+ *
+ *  Not really prom support code (yet), but sort of anti-prom code.  The current
+ *  bootloader does a number of things it shouldn't and doesn't do things that it
+ *  should.  The stuff in here is mainly a hodge-podge collection of setup code
+ *  to get the board up and running.
+ *    ---Dan
+ */
+
+#include "ppc_asm.tmpl"
+#include "ppc_defs.h"
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/gemini.h>
+
+#define HID0_ABE (1<<3)
+
+/*
+ *  On 750's the MMU is on when Linux is booted, so we need to clear out the
+ *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
+ *  and turn off the MMU.
+ *
+ */
+
+_GLOBAL(gemini_prom_init)
+#ifdef CONFIG_SMP
+	/* Since the MMU's on, get stuff in rom space that we'll need */
+	lis	r4,GEMINI_CPUSTAT@h
+	ori	r4,r4,GEMINI_CPUSTAT@l
+	lbz	r5,0(r4)
+	andi.	r5,r5,3
+	mr	r24,r5		/* cpu # used later on */
+#endif
+	mfmsr	r4
+	li	r3,MSR_PR	/* ensure supervisor! */
+	ori	r3,r3,MSR_IR|MSR_DR
+	andc	r4,r4,r3
+	mtmsr	r4
+	isync
+#if 0
+	/* zero out the bats now that the MMU is off */
+prom_no_mmu:	
+	li	r3,0
+        mtspr   IBAT0U,r3
+        mtspr   IBAT0L,r3
+        mtspr   IBAT1U,r3
+        mtspr   IBAT1L,r3
+        mtspr   IBAT2U,r3
+        mtspr   IBAT2L,r3
+        mtspr   IBAT3U,r3
+        mtspr   IBAT3L,r3
+
+        mtspr   DBAT0U,r3
+        mtspr   DBAT0L,r3
+        mtspr   DBAT1U,r3
+        mtspr   DBAT1L,r3
+        mtspr   DBAT2U,r3
+	mtspr   DBAT2L,r3
+        mtspr   DBAT3U,r3
+        mtspr   DBAT3L,r3
+#endif
+
+	/* the bootloader (as far as I'm currently aware) doesn't mess with page
+	   tables, but since we're already here, might as well zap these, too */
+	li	r4,0
+	mtspr	SDR1,r4
+
+	li	r4,16
+	mtctr	r4
+	li	r3,0
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,1
+	bdnz	3b
+
+#ifdef CONFIG_SMP
+	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
+	   when in SMP.  Not sure yet whether this should stay or leave... */
+	mfspr	r4,HID0
+	ori	r4,r4,HID0_ABE
+	mtspr	HID0,r4
+	sync
+#endif /* CONFIG_SMP */
+	blr
+
+/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
+    branch to 0xfff00100 */
+_GLOBAL(_gemini_reboot)
+	lis	r5,GEMINI_BOOT_INIT@h
+	ori	r5,r5,GEMINI_BOOT_INIT@l
+	li	r6,MSR_IP
+	mtspr	SRR0,r5
+	mtspr	SRR1,r6
+	rfi
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/gemini_setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/kernel/gemini_setup.c	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,537 @@
+/*
+ *  linux/arch/ppc/kernel/setup.c
+ *
+ *  Copyright (C) 1995 Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h> 
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/console.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/m48t35.h>
+#include <asm/gemini.h>
+#include <asm/time.h>
+
+#include "local_irq.h"
+#include "open_pic.h"
+
+void gemini_find_bridges(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
+
+static char *gemini_board_families[] = {
+  "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
+};
+static int gemini_board_count = sizeof(gemini_board_families) /
+                                 sizeof(gemini_board_families[0]);
+
+static unsigned int cpu_7xx[16] = {
+	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+int chrp_get_irq(struct pt_regs *);
+void chrp_post_irq(struct pt_regs* regs, int);
+
+static inline unsigned long _get_HID1(void)
+{
+	unsigned long val;
+
+	__asm__ __volatile__("mfspr %0,1009" : "=r" (val));
+	return val;
+}
+
+/*
+ * prom_init is the Gemini version of prom.c:prom_init.  We only need
+ * the BSS clearing code, so I copied that out of prom.c.  This is a
+ * lot simpler than hacking prom.c so it will build with Gemini. -VAL
+ */
+
+#define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
+
+unsigned long
+prom_init(void)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long phys;
+	extern char __bss_start, _end;
+
+	/* First zero the BSS -- use memset, some arches don't have
+	 * caches on yet */
+	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+
+ 	/* Default */
+ 	phys = offset + KERNELBASE;
+
+	gemini_prom_init();
+
+	return phys;
+}
+
+int
+gemini_get_cpuinfo(char *buffer)
+{
+	int len;
+	unsigned char reg, rev;
+	char *family;
+	unsigned int type;
+
+	reg = readb(GEMINI_FEAT);
+	family = gemini_board_families[((reg>>4) & 0xf)];
+	if (((reg>>4) & 0xf) > gemini_board_count)
+		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
+
+	reg = readb(GEMINI_BREV);
+	type = (reg>>4) & 0xf;
+	rev = reg & 0xf;
+
+	reg = readb(GEMINI_BECO);
+
+	len = sprintf( buffer, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 
+		       family, type, (rev + 'A'), (reg & 0xf));
+
+	len = sprintf(buffer, "board\t\t: Gemini %s", family);
+	if (type > 9)
+		len += sprintf(buffer+len, "%c", (type - 10) + 'A');
+	else
+		len += sprintf(buffer+len, "%d", type);
+
+	len += sprintf(buffer+len, ", rev %c, eco %d\n",
+		       (rev + 'A'), (reg & 0xf));
+
+	len += sprintf(buffer+len, "clock\t\t: %dMhz\n", 
+		       gemini_get_clock_speed());
+
+	return len;
+}
+
+static u_char gemini_openpic_initsenses[] = {
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	1, /* remainder are level-triggered */
+};
+
+#define GEMINI_MPIC_ADDR (0xfcfc0000)
+#define GEMINI_MPIC_PCI_CFG (0x80005800)
+
+void __init gemini_openpic_init(void)
+{
+
+	OpenPIC_Addr = (volatile struct OpenPIC *)
+		grackle_read(GEMINI_MPIC_PCI_CFG + 0x10);
+	OpenPIC_InitSenses = gemini_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
+
+	ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE);
+}
+
+
+extern unsigned long loops_per_jiffy;
+extern int root_mountflags;
+extern char cmd_line[];
+
+void
+gemini_heartbeat(void)
+{
+	static unsigned long led = GEMINI_LEDBASE+(4*8);
+	static char direction = 8;
+	*(char *)led = 0;
+	if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
+	     (led + direction) < (GEMINI_LEDBASE+(4*8)) )
+		direction *= -1;
+	led += direction;
+	*(char *)led = 0xff;
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+void __init gemini_setup_arch(void)
+{
+	extern char cmd_line[];
+
+
+	loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* bootable off CDROM */
+	if (initrd_start)
+		ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(0x0801);
+
+	/* nothing but serial consoles... */
+	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
+
+	printk("Boot arguments: %s\n", cmd_line);
+
+	ppc_md.heartbeat = gemini_heartbeat;
+	ppc_md.heartbeat_reset = HZ/8;
+	ppc_md.heartbeat_count = 1;
+	
+	/* Lookup PCI hosts */
+	gemini_find_bridges();
+	/* take special pains to map the MPIC, since it isn't mapped yet */
+	gemini_openpic_init();
+	/* start the L2 */
+	gemini_init_l2();
+}
+
+
+int
+gemini_get_clock_speed(void)
+{
+	unsigned long hid1, pvr = _get_PVR();
+	int clock;
+
+	hid1 = (_get_HID1() >> 28) & 0xf;
+	if (PVR_VER(pvr) == 8 ||
+	    PVR_VER(pvr) == 12)
+		hid1 = cpu_7xx[hid1];
+	else
+		hid1 = cpu_6xx[hid1];
+
+	switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
+
+	case 0:
+	default:
+		clock = (hid1*100)/3;
+		break;
+  
+	case 1:
+		clock = (hid1*125)/3;
+		break;
+  
+	case 2:
+		clock = (hid1*50);
+		break;
+	}
+
+	return clock;
+}
+
+void __init gemini_init_l2(void)
+{
+        unsigned char reg, brev, fam, creg;
+        unsigned long cache;
+        unsigned long pvr = _get_PVR();
+
+        reg = readb(GEMINI_L2CFG);
+        brev = readb(GEMINI_BREV);
+        fam = readb(GEMINI_FEAT);
+
+        switch(PVR_VER(pvr)) {
+
+        case 8:
+                if (reg & 0xc0)
+                        cache = (((reg >> 6) & 0x3) << 28);
+                else
+                        cache = 0x3 << 28;
+
+#ifdef CONFIG_SMP
+                /* Pre-3.0 processor revs had snooping errata.  Leave
+                   their L2's disabled with SMP. -- Dan */
+                if (PVR_CFG(pvr) < 3) {
+                        printk("Pre-3.0 750; L2 left disabled!\n");
+                        return;
+                }
+#endif /* CONFIG_SMP */
+
+                /* Special case: VGM5-B's came before L2 ratios were set on
+                   the board.  Processor speed shouldn't be too high, so
+                   set L2 ratio to 1:1.5.  */
+                if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
+                        reg |= 1;
+
+                /* determine best cache ratio based upon what the board
+                   tells us (which sometimes _may_ not be true) and
+                   the processor speed. */
+                else {
+                        if (gemini_get_clock_speed() > 250)
+                                reg = 2;
+                }
+                break;
+        case 12:
+	{
+		static unsigned long l2_size_val = 0;
+		
+		if (!l2_size_val)
+			l2_size_val = _get_L2CR();
+		cache = l2_size_val;
+                break;
+	}
+        case 4:
+        case 9:
+                creg = readb(GEMINI_CPUSTAT);
+                if (((creg & 0xc) >> 2) != 1)
+                        printk("Dual-604 boards don't support the use of L2\n");
+                else
+                        writeb(1, GEMINI_L2CFG);
+                return;
+        default:
+                printk("Unknown processor; L2 left disabled\n");
+                return;
+        }
+
+        cache |= ((1<<reg) << 25);
+        cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO);
+        _set_L2CR(0);
+        _set_L2CR(cache | L2CR_L2E);
+
+}
+
+void
+gemini_restart(char *cmd)
+{
+	__cli();
+	/* make a clean restart, not via the MPIC */
+	_gemini_reboot();
+	for(;;);
+}
+
+void
+gemini_power_off(void)
+{
+	for(;;);
+}
+
+void
+gemini_halt(void)
+{
+	gemini_restart(NULL);
+}
+
+void __init gemini_init_IRQ(void)
+{
+	/* gemini has no 8259 */
+	openpic_init(1, 0, 0, -1);
+}
+
+#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
+#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
+
+/* ensure that the RTC is up and running */
+long __init gemini_time_init(void)
+{
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+
+	if ( reg & M48T35_RTC_STOPPED ) {
+		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
+		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
+		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
+	}
+	return 0;
+}
+
+#undef DEBUG_RTC
+
+unsigned long
+gemini_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("get rtc: reg = %x\n", reg);
+#endif
+  
+	do {
+		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
+		min = gemini_rtc_read(M48T35_RTC_MINUTES);
+		hour = gemini_rtc_read(M48T35_RTC_HOURS);
+		day = gemini_rtc_read(M48T35_RTC_DOM);
+		mon = gemini_rtc_read(M48T35_RTC_MONTH);
+		year = gemini_rtc_read(M48T35_RTC_YEAR);
+	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	if ((year += 1900) < 1970)
+		year += 100;
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	return mktime( year, mon, day, hour, min, sec );
+}
+
+
+int
+gemini_set_rtc_time( unsigned long now )
+{
+	unsigned char reg;
+	struct rtc_time tm;
+
+	to_tm( now, &tm );
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: reg = %x\n", reg);
+#endif
+  
+	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+  
+	tm.tm_year -= 1900;
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+#ifdef DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
+	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
+	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
+	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
+	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
+	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
+
+	/* done writing */
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
+		time_state = TIME_OK;
+  
+	return 0;
+}
+
+/*  use the RTC to determine the decrementer count */
+void __init gemini_calibrate_decr(void)
+{
+	int freq, divisor;
+	unsigned char reg;
+
+	/* determine processor bus speed */
+	reg = readb(GEMINI_BSTAT);
+
+	switch(((reg & 0x0c)>>2)&0x3) {
+	case 0:
+	default:
+		freq = 66667;
+		break;
+	case 1:
+		freq = 83000;
+		break;
+	case 2:
+		freq = 100000;
+		break;
+	}
+
+	freq *= 1000;
+	divisor = 4;
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+unsigned long __init gemini_find_end_of_memory(void)
+{
+	unsigned long total;
+	unsigned char reg;
+
+	reg = readb(GEMINI_MEMCFG);
+	total = ((1<<((reg & 0x7) - 1)) *
+		 (8<<((reg >> 3) & 0x7)));
+	total *= (1024*1024);
+	return total;
+}
+
+void __init gemini_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			unsigned long r6, unsigned long r7)
+{
+	int i;
+	int chrp_get_irq( struct pt_regs * );
+
+	for(i = 0; i < GEMINI_LEDS; i++)
+		gemini_led_off(i);
+ 
+	ISA_DMA_THRESHOLD = 0;
+	DMA_MODE_READ = 0;
+	DMA_MODE_WRITE = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif
+
+	ppc_md.setup_arch = gemini_setup_arch;
+	ppc_md.setup_residual = NULL;
+	ppc_md.get_cpuinfo = gemini_get_cpuinfo;
+	ppc_md.irq_cannonicalize = NULL;
+	ppc_md.init_IRQ = gemini_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+	ppc_md.init = NULL;
+
+	ppc_md.restart = gemini_restart;
+	ppc_md.power_off = gemini_power_off;
+	ppc_md.halt = gemini_halt;
+
+	ppc_md.time_init = gemini_time_init;
+	ppc_md.set_rtc_time = gemini_set_rtc_time;
+	ppc_md.get_rtc_time = gemini_get_rtc_time;
+	ppc_md.calibrate_decr = gemini_calibrate_decr;
+
+	ppc_md.find_end_of_memory = gemini_find_end_of_memory;
+
+	/* no keyboard/mouse/video stuff yet.. */
+	ppc_md.kbd_setkeycode = NULL;
+	ppc_md.kbd_getkeycode = NULL;
+	ppc_md.kbd_translate = NULL;
+	ppc_md.kbd_unexpected_up = NULL;
+	ppc_md.kbd_leds = NULL;
+	ppc_md.kbd_init_hw = NULL;
+#ifdef CONFIG_MAGIC_SYSRQ
+	ppc_md.ppc_kbd_sysrq_xlate = NULL;
+#endif
+	ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
+}
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S
--- linux-2.4.5-pre2/arch/ppc/kernel/hashtable.S	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/hashtable.S	Mon Dec  3 22:43:25 2001
@@ -27,7 +27,6 @@
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <linux/config.h>
-#include "mol.h"
 
 /*
  * Load a PTE into the hash table, if possible.
@@ -609,11 +608,6 @@
  * flush_hash_page(unsigned context, unsigned long va)
  */
 _GLOBAL(flush_hash_page)
-#ifdef CONFIG_MOL
-	mflr    r10
-	MOL_HOOK_MMU(10, r6)
-	mtlr    r10
-#endif
 	lis	r6,Hash@ha
 	lwz	r6,Hash@l(r6)		/* hash table base */
 	cmpwi	0,r6,0			/* hash table in use? */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- linux-2.4.5-pre2/arch/ppc/kernel/head.S	Sat Mar  3 10:52:13 2001
+++ linux/arch/ppc/kernel/head.S	Mon Dec  3 22:43:25 2001
@@ -31,24 +31,11 @@
 #include <asm/page.h>
 #include <linux/config.h>
 #include <asm/mmu.h>
-#include "mol.h"
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
 #endif
 
-#ifndef CONFIG_PPC64BRIDGE
-CACHELINE_BYTES = 32
-LG_CACHELINE_BYTES = 5
-CACHELINE_MASK = 0x1f
-CACHELINE_WORDS = 8
-#else
-CACHELINE_BYTES = 128
-LG_CACHELINE_BYTES = 7
-CACHELINE_MASK = 0x7f
-CACHELINE_WORDS = 32
-#endif /* CONFIG_PPC64BRIDGE */
-
 #ifdef CONFIG_PPC64BRIDGE
 #define LOAD_BAT(n, reg, RA, RB)	\
 	ld	RA,(n*32)+0(reg);	\
@@ -161,6 +148,7 @@
 	bl	fix_mem_constants
 #endif /* CONFIG_APUS */
 
+#ifndef CONFIG_GEMINI
 /* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains
  * the physical address we are running at, returned by prom_init()
  */
@@ -168,6 +156,7 @@
 __after_mmu_off:
 	bl	clear_bats
 	bl	flush_tlbs
+#endif
 
 #ifndef CONFIG_POWER4
 	/* POWER4 doesn't have BATs */
@@ -294,21 +283,14 @@
 	.long	hdlr;				\
 	.long	ret_from_except
 
-#define STD_MOL_EXCEPTION(n, label, hdlr, hook)	\
-	. = n;					\
-label:						\
-	EXCEPTION_PROLOG;			\
-	MOL_HOOK(hook); 			\
-	addi	r3,r1,STACK_FRAME_OVERHEAD;	\
-	li	r20,MSR_KERNEL;			\
-	bl	transfer_to_handler; 		\
-i##n:						\
-	.long	hdlr;				\
-	.long	ret_from_except
-
 /* System reset */
-#ifdef CONFIG_SMP /* MVME/MTX start the secondary here */
+#ifdef CONFIG_SMP /* MVME/MTX and gemini start the secondary here */
+#ifdef CONFIG_GEMINI
+	. = 0x100
+	b	__secondary_start_gemini
+#else /* CONFIG_GEMINI */
 	STD_EXCEPTION(0x100, Reset, __secondary_start_psurge)
+#endif /* CONFIG_GEMINI */
 #else
 	STD_EXCEPTION(0x100, Reset, UnknownException)
 #endif
@@ -325,7 +307,6 @@
 DataAccess:
 	EXCEPTION_PROLOG
 #endif /* CONFIG_PPC64BRIDGE */
-	MOL_HOOK(0)
 	mfspr	r20,DSISR
 	andis.	r0,r20,0xa470		/* weird error? */
 	bne	1f			/* if not, try to put a PTE */
@@ -369,7 +350,6 @@
 InstructionAccess:
 	EXCEPTION_PROLOG
 #endif /* CONFIG_PPC64BRIDGE */
-	MOL_HOOK(1)
 	andis.	r0,r23,0x4000		/* no pte found? */
 	beq	1f			/* if so, try to put a PTE */
 	mr	r3,r22			/* into the hash table */
@@ -436,7 +416,6 @@
 	. = 0x700
 ProgramCheck:
 	EXCEPTION_PROLOG
-	MOL_HOOK(2)
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	li	r20,MSR_KERNEL
 	rlwimi	r20,r23,0,16,16		/* copy EE bit from saved MSR */
@@ -449,7 +428,6 @@
 	. = 0x800
 FPUnavailable:
 	EXCEPTION_PROLOG
-	MOL_HOOK_RESTORE(3)
 	bne	load_up_fpu		/* if from user, just load it up */
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler	/* if from kernel, take a trap */
@@ -460,7 +438,6 @@
 	. = 0x900
 Decrementer:
 	EXCEPTION_PROLOG
-	MOL_HOOK(4)	
 	addi	r3,r1,STACK_FRAME_OVERHEAD
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler
@@ -484,7 +461,7 @@
 	.long	ret_from_except
 
 /* Single step - not used on 601 */
-	STD_MOL_EXCEPTION(0xd00, SingleStep, SingleStepException, 5)
+	STD_EXCEPTION(0xd00, SingleStep, SingleStepException)
 	STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
 
 /*
@@ -514,7 +491,6 @@
  */
 	. = 0x1000
 InstructionTLBMiss:
-	MOL_HOOK_TLBMISS( 14 )
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -586,7 +562,6 @@
  */
 	. = 0x1100
 DataLoadTLBMiss:
-	MOL_HOOK_TLBMISS( 15 )
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -657,7 +632,6 @@
  */
 	. = 0x1200
 DataStoreTLBMiss:
-	MOL_HOOK_TLBMISS( 16 )
 /*
  * r0:	stored ctr
  * r1:	linux style pte ( later becomes ppc hardware pte )
@@ -704,7 +678,7 @@
 	mtcrf	0x80,r3
 	rfi
 
-	STD_MOL_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint, 11)
+	STD_EXCEPTION(0x1300, Trap_13, InstructionBreakpoint)
 	STD_EXCEPTION(0x1400, SMI, SMIException)
 	STD_EXCEPTION(0x1500, Trap_15, UnknownException)
 	STD_EXCEPTION(0x1600, Trap_16, UnknownException)
@@ -717,7 +691,7 @@
 	STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
 	STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
 	STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
-	STD_MOL_EXCEPTION(0x2000, RunMode, RunModeException, 5)
+	STD_EXCEPTION(0x2000, RunMode, RunModeException)
 	STD_EXCEPTION(0x2100, Trap_21, UnknownException)
 	STD_EXCEPTION(0x2200, Trap_22, UnknownException)
 	STD_EXCEPTION(0x2300, Trap_23, UnknownException)
@@ -739,7 +713,6 @@
 #ifdef CONFIG_ALTIVEC
 AltiVecUnavailable:
 	EXCEPTION_PROLOG
-	MOL_HOOK_RESTORE(12)
 	bne	load_up_altivec		/* if from user, just load it up */
 	li	r20,MSR_KERNEL
 	bl	transfer_to_handler	/* if from kernel, take a trap */
@@ -805,7 +778,6 @@
 	lwz	r24,0(r23)		/* virtual address of handler */
 	lwz	r23,4(r23)		/* where to go when done */
 	FIX_SRR1(r20,r22)
-	MOL_HOOK(6)
 	mtspr	SRR0,r24
 	mtspr	SRR1,r20
 	mtlr	r23
@@ -1016,11 +988,6 @@
 
 	.globl	giveup_altivec
 giveup_altivec:
-#ifdef CONFIG_MOL
-	mflr	r4
-	MOL_HOOK_MMU(13, r5)
-	mtlr	r4
-#endif
 	mfmsr	r5
 	oris	r5,r5,MSR_VEC@h
 	SYNC
@@ -1057,11 +1024,6 @@
  */
 	.globl	giveup_fpu
 giveup_fpu:
-#ifdef CONFIG_MOL
-	mflr	r4
-	MOL_HOOK_MMU(7, r5)
-	mtlr	r4
-#endif		
 	mfmsr	r5
 	ori	r5,r5,MSR_FP
 	SYNC
@@ -1116,7 +1078,7 @@
 copy_and_flush:
 	addi	r5,r5,-4
 	addi	r6,r6,-4
-4:	li	r0,CACHELINE_WORDS
+4:	li	r0,CACHE_LINE_SIZE/4
 	mtctr	r0
 3:	addi	r6,r6,4			/* copy a cache line */
 	lwzx	r0,r6,r4
@@ -1127,6 +1089,7 @@
 	icbi	r6,r3			/* flush the icache line */
 	cmplw	0,r6,r5
 	blt	4b
+	sync				/* additional sync needed on g4 */
 	isync
 	addi	r5,r5,4
 	addi	r6,r6,4
@@ -1165,6 +1128,7 @@
 	icbi	r0,r14			 /* flush the icache line */
 	cmpw	r12,r13
 	bne     1b
+	sync				/* additional sync needed on g4 */
 	isync
 
 /*
@@ -1199,6 +1163,7 @@
 	cmpw	r12,r13
 	bne     1b
 
+	sync				/* additional sync needed on g4 */
 	isync				/* No speculative loading until now */
 	blr
 	
@@ -1266,6 +1231,20 @@
 #endif /* CONFIG_APUS */
 
 #ifdef CONFIG_SMP
+#ifdef CONFIG_GEMINI
+	.globl	__secondary_start_gemini
+__secondary_start_gemini:
+        mfspr   r4,HID0
+        ori     r4,r4,HID0_ICFI
+        li      r3,0
+        ori     r3,r3,HID0_ICE
+        andc    r4,r4,r3
+        mtspr   HID0,r4
+        sync
+        bl      prom_init
+        b       __secondary_start
+#endif /* CONFIG_GEMINI */
+	
 	.globl	__secondary_start_psurge
 __secondary_start_psurge:
 	li	r24,1			/* cpu # */
@@ -1536,6 +1515,7 @@
  *  -- Cort 
  */
 clear_bats:
+#if !defined(CONFIG_GEMINI)
 	li	r20,0
 	mfspr	r9,PVR
 	rlwinm	r9,r9,16,16,31		/* r9 = 1 for 601, 4 for 604 */
@@ -1559,8 +1539,10 @@
 	mtspr	IBAT2L,r20
 	mtspr	IBAT3U,r20
 	mtspr	IBAT3L,r20
+#endif /* !defined(CONFIG_GEMINI) */
 	blr
 
+#ifndef CONFIG_GEMINI
 flush_tlbs:
 	lis	r20, 0x40
 1:	addic.	r20, r20, -0x1000
@@ -1579,6 +1561,7 @@
 	mtspr	SRR1,r3
 	sync
 	RFI
+#endif
 
 #ifndef CONFIG_POWER4	
 /*
@@ -1688,17 +1671,6 @@
 2:
 	mtlr	r4
 	blr
-#endif
-
-#ifdef CONFIG_MOL
-/*
- * Mac-on-linux hook_table. Don't put this in the data section -
- * the base address must be within the first 32KB of RAM.
- */
-	.globl mol_interface
-mol_interface:
-	.long   MOL_INTERFACE_VERSION
-	.fill	24,4,0		/* space for 24 hooks */
 #endif
 
 
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- linux-2.4.5-pre2/arch/ppc/kernel/head_8xx.S	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/head_8xx.S	Mon Dec  3 22:43:25 2001
@@ -30,13 +30,6 @@
 #include <asm/mmu.h>
 #include <asm/cache.h>
 #include <asm/pgtable.h>
-	
-/* XXX need definitions here for 16 byte cachelines on some/all 8xx
-   -- paulus */
-CACHELINE_BYTES = 32
-LG_CACHELINE_BYTES = 5
-CACHELINE_MASK = 0x1f
-CACHELINE_WORDS = 8
 
 	.text
 	.globl	_stext
@@ -757,7 +750,7 @@
 copy_and_flush:
 	addi	r5,r5,-4
 	addi	r6,r6,-4
-4:	li	r0,CACHELINE_WORDS
+4:	li	r0,CACHE_LINE_SIZE/4
 	mtctr	r0
 3:	addi	r6,r6,4			/* copy a cache line */
 	lwzx	r0,r6,r4
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- linux-2.4.5-pre2/arch/ppc/kernel/idle.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/kernel/idle.c	Mon Dec  3 22:43:25 2001
@@ -56,6 +56,7 @@
 	case 7:			/* 603ev */
 	case 8:			/* 750 */
 	case 12:		/* 7400 */
+	case 0x800c:		/* 7410 */
 		do_power_save = 1;
 	}
 
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- linux-2.4.5-pre2/arch/ppc/kernel/irq.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/irq.c	Mon Dec  3 22:43:25 2001
@@ -176,9 +176,19 @@
 	return 0;
 }
 
-/* This could be promoted to a real free_irq() ... */
-static int
-do_free_irq(int irq, void* dev_id)
+#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
+/* Name change so we can catch standard drivers that potentially mess up
+ * the internal interrupt controller on 8xx and 8260.  Just bear with me,
+ * I don't like this either and I am searching a better solution.  For
+ * now, this is what I need. -- Dan
+ */
+#define request_irq	request_8xxirq
+#elif defined(CONFIG_APUS)
+#define request_irq	request_sysirq
+#define free_irq	sys_free_irq
+#endif
+
+void free_irq(unsigned int irq, void* dev_id)
 {
 	irq_desc_t *desc;
 	struct irqaction **p;
@@ -209,27 +219,15 @@
 				barrier();
 #endif
 			irq_kfree(action);
-			return 0;
+			return;
 		}
 		printk("Trying to free free IRQ%d\n",irq);
 		spin_unlock_irqrestore(&desc->lock,flags);
 		break;
 	}
-	return -ENOENT;
+	return;
 }
 
-#if (defined(CONFIG_8xx) || defined(CONFIG_8260))
-/* Name change so we can catch standard drivers that potentially mess up
- * the internal interrupt controller on 8xx and 8260.  Just bear with me,
- * I don't like this either and I am searching a better solution.  For
- * now, this is what I need. -- Dan
- */
-#define request_irq	request_8xxirq
-#elif defined(CONFIG_APUS)
-#define request_irq	request_sysirq
-#define free_irq	sys_free_irq
-#endif
-
 int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
 	unsigned long irqflags, const char * devname, void *dev_id)
 {
@@ -239,8 +237,17 @@
 	if (irq >= NR_IRQS)
 		return -EINVAL;
 	if (!handler)
-		/* We could implement really free_irq() instead of that... */
-		return do_free_irq(irq, dev_id);
+	{
+		/*
+		 * free_irq() used to be implemented as a call to
+		 * request_irq() with handler being NULL.  Now we have
+		 * a real free_irq() but need to allow the old behavior
+		 * for old code that hasn't caught up yet.
+		 *  -- Cort <cort@fsmlabs.com>
+		 */
+		free_irq(irq, dev_id);
+		return 0;
+	}
 	
 	action = (struct irqaction *)
 		irq_kmalloc(sizeof(struct irqaction), GFP_KERNEL);
@@ -266,11 +273,6 @@
 	return 0;
 }
 
-void free_irq(unsigned int irq, void *dev_id)
-{
-	request_irq(irq, NULL, 0, NULL, dev_id);
-}
-
 /*
  * Generic enable/disable code: this just calls
  * down into the PIC-specific version for the actual
@@ -524,7 +526,7 @@
 	spin_unlock(&desc->lock);
 }
 
-int do_IRQ(struct pt_regs *regs, int isfake)
+int do_IRQ(struct pt_regs *regs)
 {
 	int cpu = smp_processor_id();
 	int irq;
@@ -546,10 +548,7 @@
 		goto out;
 	}
 	ppc_irq_dispatch_handler( regs, irq );
-	if (ppc_md.post_irq)
-		ppc_md.post_irq( regs, irq );
-
- out:	
+out:	
         hardirq_exit( cpu );
 	return 1; /* lets ret_from_int know we can do checks */
 }
@@ -851,15 +850,18 @@
 }
 #endif /* CONFIG_SMP */
 
-static struct proc_dir_entry * root_irq_dir;
-static struct proc_dir_entry * irq_dir [NR_IRQS];
-static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
+static struct proc_dir_entry *root_irq_dir;
+static struct proc_dir_entry *irq_dir[NR_IRQS];
+static struct proc_dir_entry *smp_affinity_entry[NR_IRQS];
 
 #ifdef CONFIG_IRQ_ALL_CPUS
-unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0xffffffff};
-#else  /* CONFIG_IRQ_ALL_CPUS */
-unsigned int irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = 0x00000000};
-#endif /* CONFIG_IRQ_ALL_CPUS */
+#define DEFAULT_CPU_AFFINITY 0xffffffff
+#else
+#define DEFAULT_CPU_AFFINITY 0x00000001
+#endif
+
+unsigned int irq_affinity [NR_IRQS] =
+	{ [0 ... NR_IRQS-1] = DEFAULT_CPU_AFFINITY };
 
 #define HEX_DIGITS 8
 
@@ -919,16 +921,18 @@
 
 	err = parse_hex_value(buffer, count, &new_value);
 
-/* Why is this disabled ? --BenH */
-#if 0/*CONFIG_SMP*/
 	/*
 	 * Do not allow disabling IRQs completely - it's a too easy
 	 * way to make the system unusable accidentally :-) At least
 	 * one online CPU still has to be targeted.
+	 *
+	 * We assume a 1-1 logical<->physical cpu mapping here.  If
+	 * we assume that the cpu indices in /proc/irq/../smp_affinity
+	 * are actually logical cpu #'s then we have no problem.
+	 *  -- Cort <cort@fsmlabs.com>
 	 */
 	if (!(new_value & cpu_online_map))
 		return -EINVAL;
-#endif
 
 	irq_affinity[irq] = new_value;
 	irq_desc[irq].handler->set_affinity(irq, new_value);
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/m8260_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/m8260_setup.c	Mon Dec  3 22:43:25 2001
@@ -119,7 +119,7 @@
 	return(0);
 }
 
-unsigned long __init
+unsigned long
 m8260_get_rtc_time(void)
 {
 
@@ -206,6 +206,18 @@
 
 }
 
+/*
+ * Same hack as 8xx
+ */
+unsigned long __init m8260_find_end_of_memory(void)
+{
+	bd_t	*binfo;
+	extern unsigned char __res[];
+	
+	binfo = (bd_t *)__res;
+
+	return binfo->bi_memsize;
+}
 
 void __init
 m8260_init(unsigned long r3, unsigned long r4, unsigned long r5,
@@ -248,18 +260,8 @@
 	ppc_md.get_rtc_time   = m8260_get_rtc_time;
 	ppc_md.calibrate_decr = m8260_calibrate_decr;
 
-#if 0
-	ppc_md.kbd_setkeycode    = pckbd_setkeycode;
-	ppc_md.kbd_getkeycode    = pckbd_getkeycode;
-	ppc_md.kbd_pretranslate  = pckbd_pretranslate;
-	ppc_md.kbd_translate     = pckbd_translate;
-	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
-	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_init_hw       = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-#endif
-#else
+	ppc_md.find_end_of_memory = m8260_find_end_of_memory;
+
 	ppc_md.kbd_setkeycode    = NULL;
 	ppc_md.kbd_getkeycode    = NULL;
 	ppc_md.kbd_translate     = NULL;
@@ -268,7 +270,6 @@
 	ppc_md.kbd_init_hw       = NULL;
 #ifdef CONFIG_MAGIC_SYSRQ
 	ppc_md.kbd_sysrq_xlate	 = NULL;
-#endif
 #endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/m8xx_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/m8xx_setup.c	Mon Dec  3 22:43:25 2001
@@ -584,6 +584,25 @@
 
 /* -------------------------------------------------------------------- */
 
+/*
+ * This is a big hack right now, but it may turn into something real
+ * someday.
+ *
+ * For the 8xx boards (at this time anyway), there is nothing to initialize
+ * associated the PROM.  Rather than include all of the prom.c
+ * functions in the image just to get prom_init, all we really need right
+ * now is the initialization of the physical memory region.
+ */
+unsigned long __init m8xx_find_end_of_memory(void)
+{
+	bd_t	*binfo;
+	extern unsigned char __res[];
+	
+	binfo = (bd_t *)__res;
+
+	return binfo->bi_memsize;
+}
+
 void __init
 m8xx_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	 unsigned long r6, unsigned long r7)
@@ -629,18 +648,8 @@
 	ppc_md.get_rtc_time   = m8xx_get_rtc_time;
 	ppc_md.calibrate_decr = m8xx_calibrate_decr;
 
-#if 0
-	ppc_md.kbd_setkeycode    = pckbd_setkeycode;
-	ppc_md.kbd_getkeycode    = pckbd_getkeycode;
-	ppc_md.kbd_pretranslate  = pckbd_pretranslate;
-	ppc_md.kbd_translate     = pckbd_translate;
-	ppc_md.kbd_unexpected_up = pckbd_unexpected_up;
-	ppc_md.kbd_leds          = pckbd_leds;
-	ppc_md.kbd_init_hw       = pckbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-#endif
-#else
+	ppc_md.find_end_of_memory = m8xx_find_end_of_memory;
+
 	ppc_md.kbd_setkeycode    = NULL;
 	ppc_md.kbd_getkeycode    = NULL;
 	ppc_md.kbd_translate     = NULL;
@@ -649,7 +658,6 @@
 	ppc_md.kbd_init_hw       = NULL;
 #ifdef CONFIG_MAGIC_SYSRQ
 	ppc_md.kbd_sysrq_xlate	 = NULL;
-#endif
 #endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- linux-2.4.5-pre2/arch/ppc/kernel/misc.S	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/misc.S	Mon Dec  3 22:43:25 2001
@@ -21,20 +21,6 @@
 #include <asm/cache.h>
 #include "ppc_asm.h"
 
-#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
-#define CACHE_LINE_SIZE		16
-#define LG_CACHE_LINE_SIZE	4
-#define MAX_COPY_PREFETCH	1
-#elif !defined(CONFIG_PPC64BRIDGE)
-#define CACHE_LINE_SIZE		32
-#define LG_CACHE_LINE_SIZE	5
-#define MAX_COPY_PREFETCH	4
-#else
-#define CACHE_LINE_SIZE		128
-#define LG_CACHE_LINE_SIZE	7
-#define MAX_COPY_PREFETCH	1
-#endif /* CONFIG_4xx || CONFIG_8xx */
-
 	.text
 
 	.align	5
@@ -60,14 +46,37 @@
 	mtlr	r0
 	blr
 
-/* void __no_use_save_flags(unsigned long *flags) */
-_GLOBAL(__no_use_save_flags)
+/* void __save_flags_ptr(unsigned long *flags) */
+_GLOBAL(__save_flags_ptr)
 	mfmsr	r4
 	stw	r4,0(r3)
 	blr
+	/* 
+	 * Need these nops here for taking over save/restore to
+	 * handle lost intrs
+	 * -- Cort
+	 */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__save_flags_ptr_end)
 
-/* void __no_use_restore_flags(unsigned long flags) */	
-_GLOBAL(__no_use_restore_flags)
+/* void __restore_flags(unsigned long flags) */	
+_GLOBAL(__restore_flags)
 /*
  * Just set/clear the MSR_EE bit through restore/flags but do not
  * change anything else.  This is needed by the RT system and makes
@@ -82,66 +91,95 @@
 	 /* Check if things are setup the way we want _already_. */
 	cmpw	0,r3,r4
 	beqlr
-	/* are we enabling interrupts? */
-	rlwinm.	r0,r3,0,16,16
-	beq	1f
-	/* if so, check if there are any lost interrupts */
-	lis	r7,ppc_n_lost_interrupts@ha
-	lwz	r7,ppc_n_lost_interrupts@l(r7)
-	cmpi	0,r7,0		/* lost interrupts to process first? */
-	bne-	do_lost_interrupts
 1:	SYNC
 	mtmsr	r3
 	SYNC
 	blr
-	
-_GLOBAL(__no_use_cli)
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__restore_flags_end)
+
+_GLOBAL(__cli)
 	mfmsr	r0		/* Get current interrupt state */
 	rlwinm	r3,r0,16+1,32-1,31	/* Extract old value of 'EE' */
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
 	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
 	blr			/* Done */
+	/* 
+	 * Need these nops here for taking over save/restore to
+	 * handle lost intrs
+	 * -- Cort
+	 */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__cli_end)
 
-_GLOBAL(__no_use_sti)
-	lis	r4,ppc_n_lost_interrupts@ha
-	lwz	r4,ppc_n_lost_interrupts@l(r4)
+_GLOBAL(__sti)
 	mfmsr	r3		/* Get current state */
 	ori	r3,r3,MSR_EE	/* Turn on 'EE' bit */
-	cmpi	0,r4,0		/* lost interrupts to process first? */
-	bne-	do_lost_interrupts
 	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r3		/* Update machine state */
 	blr
-
-/*
- * We were about to enable interrupts but we have to simulate
- * some interrupts that were lost by enable_irq first.
- */
-_GLOBAL(do_lost_interrupts)
-	stwu	r1,-16(r1)
-	mflr	r0
-	stw	r0,20(r1)
-	stw	r3,8(r1)
-1:	bl	fake_interrupt
-	lis	r4,ppc_n_lost_interrupts@ha
-	lwz	r4,ppc_n_lost_interrupts@l(r4)
-	cmpi	0,r4,0
-	bne-	1b
-	lwz	r3,8(r1)
-	SYNC
-	mtmsr	r3
-	lwz	r0,20(r1)
-	mtlr	r0
-	addi	r1,r1,16
-	blr
+	/* 
+	 * Need these nops here for taking over save/restore to
+	 * handle lost intrs
+	 * -- Cort
+	 */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+_GLOBAL(__sti_end)
 
 
 /*
  * complement mask on the msr then "or" some values on.
  *     _nmask_and_or_msr(nmask, value_to_or)
  */
-	_GLOBAL(_nmask_and_or_msr)
+_GLOBAL(_nmask_and_or_msr)
 	mfmsr	r0		/* Get current msr */
 	andc	r0,r0,r3	/* And off the bits set in r3 (first parm) */
 	or	r0,r0,r4		/* Or on the bits in r4 (second parm) */
@@ -267,6 +305,7 @@
 2:	icbi	0,r6
 	addi	r6,r6,CACHE_LINE_SIZE
 	bdnz	2b
+	sync				/* additional sync needed on g4 */
 	isync
 	blr
 
@@ -1283,7 +1322,7 @@
 	.long sys_vfork
 	.long sys_getrlimit	/* 190 */
 	.long sys_ni_syscall		/* 191 */	/* Unused */
-	.long sys_ni_syscall		/* 192 - reserved - mmap2 */
+	.long sys_mmap2			/* 192 */
 	.long sys_truncate64		/* 193 */
 	.long sys_ftruncate64		/* 194 */
 	.long sys_stat64		/* 195 */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/mol.h linux/arch/ppc/kernel/mol.h
--- linux-2.4.5-pre2/arch/ppc/kernel/mol.h	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/mol.h	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-/* 
- *   arch/ppc/kernel/mol.h
- *   
- *	<mol.h>
- *	
- *	Mac-on-Linux hook macros
- *	<http://www.maconlinux.org>
- *   
- *   Copyright (C) 2000 Samuel Rydh (samuel@ibrium.se)
- *   
- *   This program is free software; you can redistribute it and/or
- *   modify it under the terms of the GNU General Public License
- *   as published by the Free Software Foundation
- *   
- */
-
-#ifndef _PPC_KERNEL_MOL
-#define _PPC_KERNEL_MOL
-
-#include <linux/config.h>
-
-#ifdef CONFIG_MOL
-#define MOL_INTERFACE_VERSION		3
-
-#define MOL_HOOK(hook_num)					\
-	lwz	r0,(mol_interface + 4 * hook_num + 4)@l(0); 	\
-	cmpwi	cr1,r0,0; 					\
-	beq+	cr1,777f; 					\
-	mtctr	r0; 						\
-	bctrl; 							\
-777:	lwz	r0,GPR0(r21)
-
-#define MOL_HOOK_RESTORE(hook_num)				\
-	mfcr	r2;						\
-	MOL_HOOK(hook_num);					\
-	mtcrf	0x80,r2;					\
-	lwz	r2,_CTR(r21);					\
-	mtctr	r2;						\
-	lwz	r2,GPR2(r21)
-
-#define MOL_HOOK_MMU(hook_num, scr)				\
-	lis	scr,(mol_interface + 4 * hook_num + 4)@ha;	\
-	lwz	scr,(mol_interface + 4 * hook_num + 4)@l(scr);	\
-	cmpwi	cr1,scr,0;					\
-	beq+	cr1,778f;					\
-	mtctr	scr;						\
-	bctrl;							\
-778:
-
-#define MOL_HOOK_TLBMISS(hook_num)				\
-	lwz	r0,(mol_interface + 4 * hook_num + 4)@l(0);	\
-	cmpwi	r0,0;						\
-	beq+	779f;						\
-	mflr	r3;						\
-	mtlr	r0;						\
-	blrl;							\
-	mtlr	r3;						\
-779:
-
-#else
-#define MOL_HOOK(num)
-#define MOL_HOOK_RESTORE(num)
-#define MOL_HOOK_MMU(num, scr)
-#define MOL_HOOK_TLBMISS(num)
-#endif
-
-
-#endif   /* _PPC_KERNEL_MOL */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- linux-2.4.5-pre2/arch/ppc/kernel/open_pic.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/open_pic.c	Mon Dec  3 22:43:25 2001
@@ -775,11 +775,17 @@
 int
 openpic_get_irq(struct pt_regs *regs)
 {
+/*
+ * Clean up needed. -VAL
+ */
+#ifndef CONFIG_GEMINI
 	extern int i8259_irq(int cpu);
-
+#endif
 	int irq = openpic_irq();
 
 	/* Management of the cascade should be moved out of here */
+
+	/* Yep - because openpic !=> i8259, for one thing. -VAL */
         if (open_pic_irq_offset && irq == open_pic_irq_offset)
         {
                 /*
@@ -787,8 +793,10 @@
                  */
 		if ( chrp_int_ack_special )
 			irq = *chrp_int_ack_special;
+#ifndef CONFIG_GEMINI
 		else
 			irq = i8259_irq( smp_processor_id() );
+#endif
 		openpic_eoi();
         }
 	if (irq == OPENPIC_VEC_SPURIOUS + open_pic_irq_offset) {
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- linux-2.4.5-pre2/arch/ppc/kernel/pci.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/pci.c	Mon Dec  3 22:43:25 2001
@@ -399,6 +399,10 @@
 	return hose;
 }
 
+#ifdef CONFIG_ALL_PPC
+/*
+ * Functions below are used on OpenFirmware machines.
+ */
 static void
 make_one_node_map(struct device_node* node, u8 pci_bus)
 {
@@ -579,6 +583,95 @@
 }
 
 void __init
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+			   struct device_node *dev, int primary)
+{
+	unsigned int *ranges, *prev;
+	int rlen = 0;
+	int memno = 0;
+	struct resource *res;
+	int np, na = prom_n_addr_cells(dev);
+	np = na + 5;
+
+	/* First we try to merge ranges to fix a problem with some pmacs
+	 * that can have more than 3 ranges, fortunately using contiguous
+	 * addresses -- BenH
+	 */
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	prev = NULL;
+	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+		if (prev) {
+			if (prev[0] == ranges[0] && prev[1] == ranges[1] &&
+				(prev[2] + prev[na+4]) == ranges[2] &&
+				(prev[na+2] + prev[na+4]) == ranges[na+2]) {
+				prev[na+4] += ranges[na+4];
+				ranges[0] = 0;
+				ranges += np;
+				continue;
+			}
+		}
+		prev = ranges;
+		ranges += np;
+	}
+
+	/*
+	 * The ranges property is laid out as an array of elements,
+	 * each of which comprises:
+	 *   cells 0 - 2:	a PCI address
+	 *   cells 3 or 3+4:	a CPU physical address
+	 *			(size depending on dev->n_addr_cells)
+	 *   cells 4+5 or 5+6:	the size of the range
+	 */
+	rlen = 0;
+	hose->io_base_phys = 0;
+	ranges = (unsigned int *) get_property(dev, "ranges", &rlen);
+	while ((rlen -= np * sizeof(unsigned int)) >= 0) {
+		res = NULL;
+		switch (ranges[0] >> 24) {
+		case 1:		/* I/O space */
+			if (ranges[2] != 0)
+				break;
+			hose->io_base_phys = ranges[na+2];
+			hose->io_base_virt = ioremap(ranges[na+2], ranges[na+4]);
+			if (primary)
+				isa_io_base = (unsigned long) hose->io_base_virt;
+			res = &hose->io_resource;
+			res->flags = IORESOURCE_IO;
+			res->start = ranges[2];
+			break;
+		case 2:		/* memory space */
+			memno = 0;
+			if (ranges[1] == 0 && ranges[2] == 0
+			    && ranges[na+4] <= (16 << 20)) {
+				/* 1st 16MB, i.e. ISA memory area */
+				if (primary)
+					isa_mem_base = ranges[na+2];
+				memno = 1;
+			}
+			while (memno < 3 && hose->mem_resources[memno].flags)
+				++memno;
+			if (memno == 0)
+				hose->pci_mem_offset = ranges[na+2] - ranges[2];
+			if (memno < 3) {
+				res = &hose->mem_resources[memno];
+				res->flags = IORESOURCE_MEM;
+				res->start = ranges[na+2];
+			}
+			break;
+		}
+		if (res != NULL) {
+			res->name = dev->full_name;
+			res->end = res->start + ranges[na+4] - 1;
+			res->parent = NULL;
+			res->sibling = NULL;
+			res->child = NULL;
+		}
+		ranges += np;
+	}
+}
+#endif /* CONFIG_ALL_PPC */
+
+void __init
 pcibios_init(void)
 {
 	struct pci_controller *hose;
@@ -632,9 +725,6 @@
 	/* OF fails to initialize IDE controllers on macs
 	 * (and maybe other machines)
 	 * 
-	 * This late fixup is done here since I want it to happen after
-	 * resource assignement, and there's no "late-init" arch hook
-	 * 
 	 * Ideally, this should be moved to the IDE layer, but we need
 	 * to check specifically with Andre Hedrick how to do it cleanly
 	 * since the common IDE code seem to care about the fact that the
@@ -651,6 +741,9 @@
 		}
 	}
 #endif /* CONFIG_BLK_DEV_IDE */
+
+	if (ppc_md.pcibios_after_init)
+		ppc_md.pcibios_after_init();
 }
 
 int __init
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- linux-2.4.5-pre2/arch/ppc/kernel/pmac_pci.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/pmac_pci.c	Mon Dec  3 22:43:25 2001
@@ -24,13 +24,12 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
+#include <asm/feature.h>
 
 #include "pci.h"
 
 #undef DEBUG
 
-extern void process_bridge_ranges(struct pci_controller *hose,
-				  struct device_node *dev, int primary);
 static void add_bridges(struct device_node *dev);
 
 /* XXX Could be per-controller, but I don't think we risk anything by
@@ -382,17 +381,6 @@
 	hose->ops = &macrisc_pci_ops;
 	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
 	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = addr->address;
-	/* is 0x10000 enough for io space ? */
-	hose->io_base_virt = (void *)ioremap(addr->address, 0x10000);
-
-	/* XXX This is the bridge with the PCI expansion bus. We route
-	 * legacy IOs to it.
-	 */
-	if (addr->address == 0xf2000000)
-		isa_io_base = (unsigned long)hose->io_base_virt;
-#endif
 	/* We "know" that the bridge at f2000000 has the PCI slots. */
 	return addr->address == 0xf2000000;
 }
@@ -405,10 +393,6 @@
 		ioremap(addr->address + 0x800000, 0x1000);
 	hose->cfg_data = (volatile unsigned char *)
 		ioremap(addr->address + 0xc00000, 0x1000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = addr->address;
-	hose->io_base_virt = (void *) ioremap(addr->address, 0x10000);
-#endif
 	init_bandit(hose);
 }
 
@@ -421,23 +405,12 @@
 		ioremap(addr->address + 0x800000, 0x1000);
 	hose->cfg_data = (volatile unsigned char *)
 		ioremap(addr->address + 0xc00000, 0x1000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = addr->address;
-	hose->io_base_virt = (void *) ioremap(addr->address, 0x10000);
-#endif
 }
 
 void __init
 setup_grackle(struct pci_controller *hose, unsigned io_space_size)
 {
 	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
-#if 0 /* done in process_bridge_ranges now - paulus */
-	hose->io_base_phys = 0xfe000000;
-	hose->io_base_virt = (void *) ioremap(0xfe000000, io_space_size);
-	pci_dram_offset = 0;
-	isa_mem_base = 0xfd000000;
-	isa_io_base = (unsigned long) hose->io_base_virt;
-#endif
 	if (machine_is_compatible("AAPL,PowerBook1998"))
 		grackle_set_loop_snoop(hose, 1);
 #if 0	/* Disabled for now, HW problems ??? */
@@ -505,7 +478,7 @@
 		
 		/* Interpret the "ranges" property */
 		/* This also maps the I/O region and sets isa_io/mem_base */
-		process_bridge_ranges(hose, dev, primary);
+		pci_process_bridge_OF_ranges(hose, dev, primary);
 
 		/* Fixup "bus-range" OF property */
 		fixup_bus_range(dev);
@@ -557,19 +530,56 @@
 	pcibios_fixup_OF_interrupts();
 }
 
-/* We don't want to enable USB controllers absent from the OF tree
- * (iBook second controller)
- */
 int
 pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
 {
+	struct device_node* node;
+
+	node = pci_device_to_OF_node(dev);
+
+	/* We don't want to enable USB controllers absent from the OF tree
+	 * (iBook second controller)
+	 */
 	if (dev->vendor == PCI_VENDOR_ID_APPLE
-	    && dev->device == PCI_DEVICE_ID_APPLE_KL_USB) {
-		struct device_node* node;
-		node = pci_device_to_OF_node(dev);
-		if (!node)
-			return -EINVAL;
+	    && dev->device == PCI_DEVICE_ID_APPLE_KL_USB && !node)
+		return -EINVAL;
+		
+	/* Firewire was disabled after PCI probe, the driver is claiming it,
+	 * so we must re-enable it now, at least until the driver can do it
+	 * itself.
+	 */
+	if (node && !strcmp(node->name, "firewire") && 
+	    device_is_compatible(node, "pci106b,18")) {
+		feature_set_firewire_cable_power(node, 1);
+		feature_set_firewire_power(node, 1);
 	}
+	
 	return 0;
+}
+
+/* We power down some devices after they have been probed. They'll
+ * be powered back on later on
+ */
+void
+pmac_pcibios_after_init(void)
+{
+	struct device_node* nd;
+
+	nd = find_devices("firewire");
+	while (nd) {
+		if (nd->parent && device_is_compatible(nd, "pci106b,18")
+		    && device_is_compatible(nd->parent, "uni-north")) {
+			feature_set_firewire_power(nd, 0);
+			feature_set_firewire_cable_power(nd, 0);
+		}
+		nd = nd->next;
+	}
+	nd = find_devices("ethernet");
+	while (nd) {
+		if (nd->parent && device_is_compatible(nd, "gmac")
+		    && device_is_compatible(nd->parent, "uni-north"))
+			feature_set_gmac_power(nd, 0);
+		nd = nd->next;
+	}
 }
 
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- linux-2.4.5-pre2/arch/ppc/kernel/pmac_pic.c	Fri Feb 16 16:02:34 2001
+++ linux/arch/ppc/kernel/pmac_pic.c	Mon Dec  3 22:43:25 2001
@@ -10,6 +10,7 @@
 #include <asm/smp.h>
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
+#include <asm/time.h>
 
 #include "pmac_pic.h"
 #include "open_pic.h"
@@ -44,10 +45,12 @@
  * since it can lose interrupts (see pmac_set_irq_mask).
  * -- Cort
  */
-void __pmac __no_use_set_lost(unsigned long irq_nr)
+void __pmac __set_lost(unsigned long irq_nr)
 {
-	if (!test_and_set_bit(irq_nr, ppc_lost_interrupts))
+	if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
 		atomic_inc(&ppc_n_lost_interrupts);
+		set_dec(1);
+	}
 }
 
 static void __pmac pmac_mask_and_ack_irq(unsigned int irq_nr)
@@ -373,7 +376,6 @@
 		irqctrler = NULL;
 	}
 
-	int_control.int_set_lost = __no_use_set_lost;
 	/*
 	 * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
 	 * 1998 G3 Series PowerBooks have 128, 
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/pmac_setup.c	Tue Mar  6 19:28:35 2001
+++ linux/arch/ppc/kernel/pmac_setup.c	Mon Dec  3 22:43:25 2001
@@ -66,6 +66,7 @@
 #include <asm/time.h>
 #include "local_irq.h"
 #include "pmac_pic.h"
+#include "../mm/mem_pieces.h"
 
 #undef SHOW_GATWICK_IRQS
 
@@ -102,6 +103,9 @@
 extern void pmac_nvram_update(void);
 
 extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern void pmac_pcibios_after_init(void);
+
+struct device_node *memory_node;
 
 unsigned char drive_info;
 
@@ -470,7 +474,7 @@
 	char *p;
 
 	/* Do nothing if the root has been set already. */
-	if ((goodness < current_root_goodness) &&
+	if ((goodness <= current_root_goodness) &&
 		(ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE)))
 		return;
 	p = strstr(saved_command_line, "root=");
@@ -635,6 +639,88 @@
 #endif
 #endif
 
+/*
+ * Read in a property describing some pieces of memory.
+ */
+
+static void __init get_mem_prop(char *name, struct mem_pieces *mp)
+{
+	struct reg_property *rp;
+	int i, s;
+	unsigned int *ip;
+	int nac = prom_n_addr_cells(memory_node);
+	int nsc = prom_n_size_cells(memory_node);
+
+	ip = (unsigned int *) get_property(memory_node, name, &s);
+	if (ip == NULL) {
+		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
+		       name);
+		abort();
+	}
+	s /= (nsc + nac) * 4;
+	rp = mp->regions;
+	for (i = 0; i < s; ++i, ip += nac+nsc) {
+		if (nac >= 2 && ip[nac-2] != 0)
+			continue;
+		rp->address = ip[nac-1];
+		if (nsc >= 2 && ip[nac+nsc-2] != 0)
+			rp->size = ~0U;
+		else
+			rp->size = ip[nac+nsc-1];
+		++rp;
+	}
+	mp->n_regions = rp - mp->regions;
+
+	/* Make sure the pieces are sorted. */
+	mem_pieces_sort(mp);
+	mem_pieces_coalesce(mp);
+}
+
+/*
+ * On systems with Open Firmware, collect information about
+ * physical RAM and which pieces are already in use.
+ * At this point, we have (at least) the first 8MB mapped with a BAT.
+ * Our text, data, bss use something over 1MB, starting at 0.
+ * Open Firmware may be using 1MB at the 4MB point.
+ */
+unsigned long __init pmac_find_end_of_memory(void)
+{
+	unsigned long a, total;
+	struct mem_pieces phys_mem;
+
+	memory_node = find_devices("memory");
+	if (memory_node == NULL) {
+		printk(KERN_ERR "can't find memory node\n");
+		abort();
+	}
+
+	/*
+	 * Find out where physical memory is, and check that it
+	 * starts at 0 and is contiguous.  It seems that RAM is
+	 * always physically contiguous on Power Macintoshes.
+	 *
+	 * Supporting discontiguous physical memory isn't hard,
+	 * it just makes the virtual <-> physical mapping functions
+	 * more complicated (or else you end up wasting space
+	 * in mem_map).
+	 */
+	get_mem_prop("reg", &phys_mem);
+	if (phys_mem.n_regions == 0)
+		panic("No RAM??");
+	a = phys_mem.regions[0].address;
+	if (a != 0)
+		panic("RAM doesn't start at physical address 0");
+	total = phys_mem.regions[0].size;
+
+	if (phys_mem.n_regions > 1) {
+		printk("RAM starting at 0x%x is not contiguous\n",
+		       phys_mem.regions[1].address);
+		printk("Using RAM from 0 to 0x%lx\n", total-1);
+	}
+
+	return total;
+}
+
 void __init
 pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
 	  unsigned long r6, unsigned long r7)
@@ -656,6 +742,7 @@
 	
 	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
 	ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
+	ppc_md.pcibios_after_init = pmac_pcibios_after_init;
 
 	ppc_md.restart        = pmac_restart;
 	ppc_md.power_off      = pmac_power_off;
@@ -665,6 +752,8 @@
 	ppc_md.set_rtc_time   = pmac_set_rtc_time;
 	ppc_md.get_rtc_time   = pmac_get_rtc_time;
 	ppc_md.calibrate_decr = pmac_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
 
 #ifdef CONFIG_VT
 #ifdef CONFIG_INPUT
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/ppc8260_pic.h linux/arch/ppc/kernel/ppc8260_pic.h
--- linux-2.4.5-pre2/arch/ppc/kernel/ppc8260_pic.h	Tue May  2 13:05:40 2000
+++ linux/arch/ppc/kernel/ppc8260_pic.h	Mon Dec  3 22:43:25 2001
@@ -8,8 +8,7 @@
 
 void m8260_pic_init(void);
 void m8260_do_IRQ(struct pt_regs *regs,
-                 int            cpu,
-                 int            isfake);
+                 int            cpu);
 int m8260_get_irq(struct pt_regs *regs);
 
 #endif /* _PPC_KERNEL_PPC8260_H */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/ppc8xx_pic.c linux/arch/ppc/kernel/ppc8xx_pic.c
--- linux-2.4.5-pre2/arch/ppc/kernel/ppc8xx_pic.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/ppc8xx_pic.c	Mon Dec  3 22:43:25 2001
@@ -67,8 +67,7 @@
 #if 0
 void
 m8xx_do_IRQ(struct pt_regs *regs,
-	   int            cpu,
-           int            isfake)
+	   int            cpu)
 {
 	int irq;
         unsigned long bits = 0;
@@ -158,13 +157,15 @@
 	 */
 	switch (irq) {
 #ifdef	IDE0_INTERRUPT
-	case IDE0_INTERRUPT:		/* fall through */
+		case IDE0_INTERRUPT:	/* IDE0 */
+			return (request_8xxirq(irq, handler, irqflags, devname,
+						dev_id));
 #endif
 #ifdef	IDE1_INTERRUPT
-	case IDE1_INTERRUPT:		/* fall through */
+		case IDE1_INTERRUPT:	/* IDE1 */
+			return (request_8xxirq(irq, handler, irqflags, devname,
+						dev_id));
 #endif
-		return (request_8xxirq(irq, handler, irqflags, devname, dev_id));
-	
 	default:			/* unknown IRQ -> panic */
 		panic("request_irq");
 	}
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/ppc8xx_pic.h linux/arch/ppc/kernel/ppc8xx_pic.h
--- linux-2.4.5-pre2/arch/ppc/kernel/ppc8xx_pic.h	Fri Nov 12 04:29:47 1999
+++ linux/arch/ppc/kernel/ppc8xx_pic.h	Mon Dec  3 22:43:25 2001
@@ -8,8 +8,7 @@
 
 void m8xx_pic_init(void);
 void m8xx_do_IRQ(struct pt_regs *regs,
-                 int            cpu,
-                 int            isfake);
+                 int            cpu);
 int m8xx_get_irq(struct pt_regs *regs);
 
 #ifdef CONFIG_MBX
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/ppc_asm.h linux/arch/ppc/kernel/ppc_asm.h
--- linux-2.4.5-pre2/arch/ppc/kernel/ppc_asm.h	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/kernel/ppc_asm.h	Mon Dec  3 22:43:25 2001
@@ -130,3 +130,22 @@
 #define MTMSRD(r)	mtmsr	r
 #define CLR_TOP32(r)
 #endif /* CONFIG_PPC64BRIDGE */
+
+/*
+ * Defines for cache-line size etc.
+ */
+#if defined(CONFIG_4xx) || defined(CONFIG_8xx)
+#define CACHE_LINE_SIZE		16
+#define LG_CACHE_LINE_SIZE	4
+#define MAX_COPY_PREFETCH	1
+
+#elif !defined(CONFIG_PPC64BRIDGE)
+#define CACHE_LINE_SIZE		32
+#define LG_CACHE_LINE_SIZE	5
+#define MAX_COPY_PREFETCH	4
+
+#else
+#define CACHE_LINE_SIZE		128
+#define LG_CACHE_LINE_SIZE	7
+#define MAX_COPY_PREFETCH	1
+#endif /* CONFIG_4xx || CONFIG_8xx */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- linux-2.4.5-pre2/arch/ppc/kernel/ppc_ksyms.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Dec  3 22:43:25 2001
@@ -55,12 +55,11 @@
 
 extern void transfer_to_handler(void);
 extern void syscall_trace(void);
-extern void do_IRQ(struct pt_regs *regs, int isfake);
+extern void do_IRQ(struct pt_regs *regs);
 extern void MachineCheckException(struct pt_regs *regs);
 extern void AlignmentException(struct pt_regs *regs);
 extern void ProgramCheckException(struct pt_regs *regs);
 extern void SingleStepException(struct pt_regs *regs);
-extern void do_lost_interrupts(unsigned long);
 extern int do_signal(sigset_t *, struct pt_regs *);
 extern int pmac_newworld;
 extern int sys_sigreturn(struct pt_regs *regs);
@@ -83,7 +82,6 @@
 EXPORT_SYMBOL(sys_sigreturn);
 EXPORT_SYMBOL(ppc_n_lost_interrupts);
 EXPORT_SYMBOL(ppc_lost_interrupts);
-EXPORT_SYMBOL(do_lost_interrupts);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(disable_irq_nosync);
@@ -277,9 +275,11 @@
 EXPORT_SYMBOL(feature_clear);
 EXPORT_SYMBOL(feature_test);
 EXPORT_SYMBOL(feature_set_gmac_power);
-EXPORT_SYMBOL(feature_set_gmac_phy_reset);
+EXPORT_SYMBOL(feature_gmac_phy_reset);
 EXPORT_SYMBOL(feature_set_usb_power);
 EXPORT_SYMBOL(feature_set_firewire_power);
+EXPORT_SYMBOL(feature_set_firewire_cable_power);
+EXPORT_SYMBOL(feature_set_airport_power);
 #endif /* defined(CONFIG_ALL_PPC) */
 #if defined(CONFIG_BOOTX_TEXT)
 EXPORT_SYMBOL(bootx_update_display);
@@ -314,7 +314,14 @@
 #endif
 
 EXPORT_SYMBOL(__delay);
-EXPORT_SYMBOL(int_control);
+EXPORT_SYMBOL(__sti);
+EXPORT_SYMBOL(__sti_end);
+EXPORT_SYMBOL(__cli);
+EXPORT_SYMBOL(__cli_end);
+EXPORT_SYMBOL(__save_flags_ptr);
+EXPORT_SYMBOL(__save_flags_ptr_end);
+EXPORT_SYMBOL(__restore_flags);
+EXPORT_SYMBOL(__restore_flags_end);
 EXPORT_SYMBOL(timer_interrupt_intercept);
 EXPORT_SYMBOL(timer_interrupt);
 EXPORT_SYMBOL(do_IRQ_intercept);
@@ -331,9 +338,6 @@
 EXPORT_SYMBOL(__up);
 EXPORT_SYMBOL(__down);
 EXPORT_SYMBOL(__down_interruptible);
-EXPORT_SYMBOL(__down_trylock);
-EXPORT_SYMBOL(down_read_failed);
-EXPORT_SYMBOL(down_write_failed);
 
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
 extern void (*debugger)(struct pt_regs *regs);
@@ -362,6 +366,8 @@
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);
 EXPORT_SYMBOL(mmu_context_overflow);
+EXPORT_SYMBOL(flush_hash_page); /* For MOL */
+EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
 EXPORT_SYMBOL_NOVERS(disarm_decr);
 #if !defined(CONFIG_8xx) && !defined(CONFIG_4xx)
 extern long *intercept_table;
@@ -369,17 +375,3 @@
 #endif
 extern long *ret_from_intercept;
 EXPORT_SYMBOL(ret_from_intercept);
-
-#ifdef CONFIG_MOL
-extern ulong mol_interface[];
-extern PTE *Hash;
-extern unsigned long Hash_mask;
-extern void (*ret_from_except)(void);
-extern struct task_struct *last_task_used_altivec;
-EXPORT_SYMBOL_NOVERS(mol_interface);
-EXPORT_SYMBOL(Hash);
-EXPORT_SYMBOL(Hash_mask);
-EXPORT_SYMBOL(handle_mm_fault);
-EXPORT_SYMBOL(last_task_used_math);
-EXPORT_SYMBOL(ret_from_except);
-#endif /* CONFIG_MOL */
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- linux-2.4.5-pre2/arch/ppc/kernel/prep_pci.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/prep_pci.c	Mon Dec  3 22:43:25 2001
@@ -437,8 +437,8 @@
 
 static char ibm8xx_pci_IRQ_routes[] __prepdata = {
         0,      /* Line 0 - unused */
-        13,     /* Line 1 */
-        10,     /* Line 2 */
+        15,     /* Line 1 */
+        15,     /* Line 2 */
         15,     /* Line 3 */
         15,     /* Line 4 */
 };
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/prep_setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/ppc/kernel/prep_setup.c	Mon Dec  3 22:43:25 2001
@@ -312,7 +312,9 @@
 	/* remap the VGA memory */
 	vgacon_remap_base = 0xf0000000;
 	/*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
-        conswitchp = &vga_con;
+	conswitchp = &vga_con;
+#else
+	conswitchp = &dummy_con;
 #endif
 }
 
@@ -504,8 +506,8 @@
 	__cli();
 
 	__asm__ __volatile__("\n\
-	mtspr   26, %1  /* SRR0 */
-	mtspr   27, %0  /* SRR1 */
+	mtspr   26, %1  /* SRR0 */	\n\
+	mtspr   27, %0  /* SRR1 */	\n\
 	rfi"
 	:
 	: "r" (defaultmsr), "r" (jumpaddr));
@@ -575,7 +577,7 @@
 
 #if 0
 void __prep
-prep_do_IRQ(struct pt_regs *regs, int cpu, int isfake)
+prep_do_IRQ(struct pt_regs *regs, int cpu)
 {
         int irq;
 
@@ -691,6 +693,35 @@
 }
 #endif
 
+/*
+ * This finds the amount of physical ram and does necessary
+ * setup for prep.  This is pretty architecture specific so
+ * this will likely stay separate from the pmac.
+ * -- Cort
+ */
+unsigned long __init prep_find_end_of_memory(void)
+{
+	unsigned long total;
+#ifdef CONFIG_PREP_RESIDUAL	
+	total = res->TotalMemory;
+#else
+	total = 0;
+#endif	
+
+	if (total == 0 )
+	{
+		/*
+		 * I need a way to probe the amount of memory if the residual
+		 * data doesn't contain it. -- Cort
+		 */
+		printk("Ramsize from residual data was 0 -- Probing for value\n");
+		total = 0x02000000;
+		printk("Ramsize default to be %ldM\n", total>>20);
+	}
+
+	return (total);
+}
+
 unsigned long *MotSave_SmpIar;
 unsigned char *MotSave_CpusState[2];
 
@@ -750,7 +781,8 @@
 	{
 		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
 			_prep_type = _PREP_IBM;
-		_prep_type = _PREP_Motorola;
+		else
+			_prep_type = _PREP_Motorola;
 	}
 	else /* assume motorola if no residual (netboot?) */
 #endif	  
@@ -783,6 +815,8 @@
 		ppc_md.calibrate_decr = mk48t59_calibrate_decr;
 		ppc_md.time_init      = mk48t59_init;
 	}
+
+	ppc_md.find_end_of_memory = prep_find_end_of_memory;
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
         ppc_ide_md.insw = prep_ide_insw;
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c
--- linux-2.4.5-pre2/arch/ppc/kernel/prep_time.c	Sun Sep 17 09:48:07 2000
+++ linux/arch/ppc/kernel/prep_time.c	Mon Dec  3 22:43:25 2001
@@ -30,6 +30,8 @@
 
 #include <asm/time.h>
 
+extern spinlock_t rtc_lock;
+
 /*
  * The motorola uses the m48t18 rtc (includes DS1643) whose registers
  * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818
@@ -55,6 +57,7 @@
 	unsigned char save_control, save_freq_select;
 	struct rtc_time tm;
 
+	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
 
 	/* tell the clock it's being set */
@@ -92,6 +95,7 @@
 	 */
 	CMOS_WRITE(save_control,     RTC_CONTROL);
 	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	spin_unlock(&rtc_lock);
 
 	return 0;
 }
@@ -149,7 +153,7 @@
 	unsigned char save_control;
 	struct rtc_time tm;
 
-
+	spin_lock(&rtc_lock);
 	to_tm(nowtime, &tm);
 
 	/* tell the clock it's being written */
@@ -175,6 +179,7 @@
 	
 	/* Turn off the write bit. */
 	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+	spin_unlock(&rtc_lock);
 
 	return 0;
 }
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- linux-2.4.5-pre2/arch/ppc/kernel/process.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/ppc/kernel/process.c	Mon Dec  3 22:43:25 2001
@@ -378,45 +378,6 @@
 }
 
 /*
- * XXX ld.so expects the auxiliary table to start on
- * a 16-byte boundary, so we have to find it and
- * move it up. :-(
- */
-static inline void shove_aux_table(unsigned long sp)
-{
-	int argc;
-	char *p;
-	unsigned long e;
-	unsigned long aux_start, offset;
-
-	if (__get_user(argc, (int *)sp))
-		return;
-	sp += sizeof(int) + (argc + 1) * sizeof(char *);
-	/* skip over the environment pointers */
-	do {
-		if (__get_user(p, (char **)sp))
-			return;
-		sp += sizeof(char *);
-	} while (p != NULL);
-	aux_start = sp;
-	/* skip to the end of the auxiliary table */
-	do {
-		if (__get_user(e, (unsigned long *)sp))
-			return;
-		sp += 2 * sizeof(unsigned long);
-	} while (e != AT_NULL);
-	offset = ((aux_start + 15) & ~15) - aux_start;
-	if (offset != 0) {
-		do {
-			sp -= sizeof(unsigned long);
-			if (__get_user(e, (unsigned long *)sp)
-			    || __put_user(e, (unsigned long *)(sp + offset)))
-				return;
-		} while (sp > aux_start);
-	}
-}
-
-/*
  * Set up a thread for executing a new program
  */
 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp)
@@ -425,7 +386,6 @@
 	regs->nip = nip;
 	regs->gpr[1] = sp;
 	regs->msr = MSR_USER;
-	shove_aux_table(sp);
 	if (last_task_used_math == current)
 		last_task_used_math = 0;
 	if (last_task_used_altivec == current)
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- linux-2.4.5-pre2/arch/ppc/kernel/prom.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/prom.c	Mon Dec  3 22:43:25 2001
@@ -757,14 +757,9 @@
 		setup_disp_fake_bi(RELOC(prom_disp_node));
 #endif
 
-	/* If pmac, then use quiesce call. We can't rely on prom_version
-	 * since some old iMacs appear to have an incorrect /openprom/model
-	 * entry in the device tree
-	 */
-	if (!chrp) {
-		prom_print(RELOC("Calling quiesce ...\n"));
-		call_prom(RELOC("quiesce"), 0, 0);
-	}
+	/* Use quiesce call to get OF to shut down any devices it's using */
+	prom_print(RELOC("Calling quiesce ...\n"));
+	call_prom(RELOC("quiesce"), 0, 0);
 
 #ifdef CONFIG_BOOTX_TEXT
 	if (!chrp && RELOC(disp_bi)) {
@@ -839,7 +834,7 @@
 	    __asm__ __volatile__ ("mfspr %0, 1008" : "=r" (flags));
 	    prom_drawhex(flags);
 	}
-	if (pvr == 8 || pvr == 12) {
+	if (pvr == 8 || pvr == 12 || pvr == 0x800c) {
 	    prom_drawstring(RELOC("\nICTC             : 0x"));
 	    __asm__ __volatile__ ("mfspr %0, 1019" : "=r" (flags));
 	    prom_drawhex(flags);
@@ -986,9 +981,11 @@
 			prom_print(RELOC("... failed\n"));
 		} else {
 			prom_print(RELOC("... ok\n"));
-
-			/* Setup a useable color table when the appropriate
-			 * method is available. Should update this to set-colors */
+			/*
+			 * Setup a usable color table when the appropriate
+			 * method is available.
+			 * Should update this to use set-colors.
+			 */
 			for (i = 0; i < 32; i++)
 				if (prom_set_color(ih, i, RELOC(default_colors)[i*3],
 						   RELOC(default_colors)[i*3+1],
@@ -1267,7 +1264,10 @@
 
 	np->name = get_property(np, "name", 0);
 	np->type = get_property(np, "device_type", 0);
-
+#if 0
+	np->n_addr_cells = naddrc;
+	np->n_size_cells = nsizec;
+#endif
 	/* get the device addresses and interrupts */
 	if (ifunc != NULL) {
 		mem_start = ifunc(np, mem_start, naddrc, nsizec);
@@ -1283,6 +1283,16 @@
 	ip = (int *) get_property(np, "#size-cells", 0);
 	if (ip != NULL)
 		nsizec = *ip;
+#if 0
+	if (np->parent == NULL) {
+		/*
+		 * Set the n_addr/size_cells on the root to its
+		 * own values, rather than 0.
+		 */
+		np->n_addr_cells = naddrc;
+		np->n_size_cells = nsizec;
+	}
+#endif	
 
 	/* the f50 sets the name to 'display' and 'compatible' to what we
 	 * expect for the name -- Cort
@@ -1497,6 +1507,34 @@
 	}
 }
 
+int
+prom_n_addr_cells(struct device_node* np)
+{
+	int* ip;
+	do {
+		if (np->parent)
+			np = np->parent;
+		ip = (int *) get_property(np, "#address-cells", 0);
+		if (ip != NULL)
+			return *ip;
+	} while(np->parent);
+	return 0;
+}
+
+int
+prom_n_size_cells(struct device_node* np)
+{
+	int* ip;
+	do {
+		if (np->parent)
+			np = np->parent;
+		ip = (int *) get_property(np, "#size-cells", 0);
+		if (ip != NULL)
+			return *ip;
+	} while(np->parent);
+	return 0;
+}
+
 __init
 static unsigned long
 interpret_pci_props(struct device_node *np, unsigned long mem_start,
@@ -1566,6 +1604,8 @@
 	}
 
 	ip = (int *) get_property(np, "AAPL,interrupts", &l);
+	if (ip == 0 && np->parent)
+		ip = (int *) get_property(np->parent, "AAPL,interrupts", &l);
 	if (ip == 0)
 		ip = (int *) get_property(np, "interrupts", &l);
 	if (ip != 0) {
@@ -1761,7 +1801,7 @@
 		i = 0;
 		adr = (struct address_range *) mem_start;
 		while ((l -= rpsize) >= 0) {
-			adr[i].space = 0;
+			adr[i].space = (naddrc >= 2? rp[naddrc-2]: 0);
 			adr[i].address = rp[naddrc - 1];
 			adr[i].size = rp[naddrc + nsizec - 1];
 			++i;
@@ -1978,12 +2018,13 @@
 {
 	struct property *pp;
 
-	for (pp = np->properties; pp != 0; pp = pp->next)
-		if (strcmp(pp->name, name) == 0) {
+	for (pp = np->properties; pp != 0; pp = pp->next) {
+		if (name && strcmp(pp->name, name) == 0) {
 			if (lenp != 0)
 				*lenp = pp->length;
 			return pp->value;
 		}
+	}
 	return 0;
 }
 
@@ -2161,9 +2202,10 @@
 {
 	if (disp_bi == 0)
 		return;
-	/* check it's the same frame buffer (within 16MB) */
-	if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xff000000)
+	/* check it's the same frame buffer (within 64MB) */
+	if ((phys ^ (unsigned long)disp_bi->dispDeviceBase) & 0xfc000000) {
 		return;
+	}
 
 	disp_bi->dispDeviceBase = (__u8 *) phys;
 	disp_bi->dispDeviceRect[0] = 0;
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/semaphore.c linux/arch/ppc/kernel/semaphore.c
--- linux-2.4.5-pre2/arch/ppc/kernel/semaphore.c	Tue Apr 17 17:19:25 2001
+++ linux/arch/ppc/kernel/semaphore.c	Mon Dec  3 22:43:25 2001
@@ -9,131 +9,122 @@
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
+ *
+ * April 2001 - Reworked by Paul Mackerras <paulus@samba.org>
+ * to eliminate the SMP races in the old version between the updates
+ * of `count' and `waking'.  Now we use negative `count' values to
+ * indicate that some process(es) are waiting for the semaphore.
  */
 
 #include <linux/sched.h>
-
+#include <asm/atomic.h>
 #include <asm/semaphore.h>
-#include <asm/semaphore-helper.h>
 
 /*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to sleep, while the "waking" variable is
- * incremented when the "up()" code goes to wake up waiting
- * processes.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * waking_non_zero() (from asm/semaphore.h) must execute
- * atomically.
- *
- * When __up() is called, the count was negative before
- * incrementing it, and we need to wake up somebody.
- *
- * This routine adds one to the count of processes that need to
- * wake up and exit.  ALL waiting processes actually wake up but
- * only the one that gets to the "waking" field first will gate
- * through and acquire the semaphore.  The others will go back
- * to sleep.
+ * Atomically update sem->count.
+ * This does the equivalent of the following:
  *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
+ *	old_count = sem->count;
+ *	tmp = MAX(old_count, 0) + incr;
+ *	sem->count = tmp;
+ *	return old_count;
  */
+static inline int __sem_update_count(struct semaphore *sem, int incr)
+{
+	int old_count, tmp;
+
+	__asm__ __volatile__("\n"
+"1:	lwarx	%0,0,%3\n"
+"	srawi	%1,%0,31\n"
+"	andc	%1,%0,%1\n"
+"	add	%1,%1,%4\n"
+"	stwcx.	%1,0,%3\n"
+"	bne	1b"
+	: "=&r" (old_count), "=&r" (tmp), "=m" (sem->count)
+	: "r" (&sem->count), "r" (incr), "m" (sem->count)
+	: "cc");
+
+	return old_count;
+}
+
 void __up(struct semaphore *sem)
 {
-	wake_one_more(sem);
+	/*
+	 * Note that we incremented count in up() before we came here,
+	 * but that was ineffective since the result was <= 0, and
+	 * any negative value of count is equivalent to 0.
+	 * This ends up setting count to 1, unless count is now > 0
+	 * (i.e. because some other cpu has called up() in the meantime),
+	 * in which case we just increment count.
+	 */
+	__sem_update_count(sem, 1);
 	wake_up(&sem->wait);
 }
 
 /*
- * Perform the "down" function.  Return zero for semaphore acquired,
- * return negative for signalled out of the function.
- *
- * If called from __down, the return is ignored and the wait loop is
- * not interruptible.  This means that a task waiting on a semaphore
- * using "down()" cannot be killed until someone does an "up()" on
- * the semaphore.
- *
- * If called from __down_interruptible, the return value gets checked
- * upon return.  If the return value is negative then the task continues
- * with the negative value in the return register (it can be tested by
- * the caller).
- *
- * Either form may be used in conjunction with "up()".
- *
+ * Note that when we come in to __down or __down_interruptible,
+ * we have already decremented count, but that decrement was
+ * ineffective since the result was < 0, and any negative value
+ * of count is equivalent to 0.
+ * Thus it is only when we decrement count from some value > 0
+ * that we have actually got the semaphore.
  */
+void __down(struct semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
 
-#define DOWN_VAR				\
-	struct task_struct *tsk = current;	\
-	wait_queue_t wait;			\
-	init_waitqueue_entry(&wait, tsk);
-
-#define DOWN_HEAD(task_state)						\
-									\
-									\
-	tsk->state = (task_state);					\
-	add_wait_queue(&sem->wait, &wait);				\
-									\
-	/*								\
-	 * Ok, we're set up.  sem->count is known to be less than zero	\
-	 * so we must wait.						\
-	 *								\
-	 * We can let go the lock for purposes of waiting.		\
-	 * We re-acquire it after awaking so as to protect		\
-	 * all semaphore operations.					\
-	 *								\
-	 * If "up()" is called before we call waking_non_zero() then	\
-	 * we will catch it right away.  If it is called later then	\
-	 * we will have to go through a wakeup cycle to catch it.	\
-	 *								\
-	 * Multiple waiters contend for the semaphore lock to see	\
-	 * who gets to gate through and who has to wait some more.	\
-	 */								\
-	for (;;) {
-
-#define DOWN_TAIL(task_state)			\
-		tsk->state = (task_state);	\
-	}					\
-	tsk->state = TASK_RUNNING;		\
+	tsk->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+	smp_wmb();
+
+	/*
+	 * Try to get the semaphore.  If the count is > 0, then we've
+	 * got the semaphore; we decrement count and exit the loop.
+	 * If the count is 0 or negative, we set it to -1, indicating
+	 * that we are asleep, and then sleep.
+	 */
+	while (__sem_update_count(sem, -1) <= 0) {
+		schedule();
+		tsk->state = TASK_UNINTERRUPTIBLE;
+	}
 	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
 
-void __down(struct semaphore * sem)
-{
-	DOWN_VAR
-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
-	if (waking_non_zero(sem))
-		break;
-	schedule();
-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+	/*
+	 * If there are any more sleepers, wake one of them up so
+	 * that it can either get the semaphore, or set count to -1
+	 * indicating that there are still processes sleeping.
+	 */
+	wake_up(&sem->wait);
 }
 
 int __down_interruptible(struct semaphore * sem)
 {
-	int ret = 0;
-	DOWN_VAR
-	DOWN_HEAD(TASK_INTERRUPTIBLE)
-
-	ret = waking_non_zero_interruptible(sem, tsk);
-	if (ret)
-	{
-		if (ret == 1)
-			/* ret != 0 only if we get interrupted -arca */
-			ret = 0;
-		break;
+	int retval = 0;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	tsk->state = TASK_INTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+	smp_wmb();
+
+	while (__sem_update_count(sem, -1) <= 0) {
+		if (signal_pending(current)) {
+			/*
+			 * A signal is pending - give up trying.
+			 * Set sem->count to 0 if it is negative,
+			 * since we are no longer sleeping.
+			 */
+			__sem_update_count(sem, 0);
+			retval = -EINTR;
+			break;
+		}
+		schedule();
+		tsk->state = TASK_INTERRUPTIBLE;
 	}
-	schedule();
-	DOWN_TAIL(TASK_INTERRUPTIBLE)
-	return ret;
-}
-
-int __down_trylock(struct semaphore * sem)
-{
-	return waking_non_zero_trylock(sem);
+	tsk->state = TASK_RUNNING;
+	remove_wait_queue(&sem->wait, &wait);
+	wake_up(&sem->wait);
+	return retval;
 }
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- linux-2.4.5-pre2/arch/ppc/kernel/setup.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/setup.c	Mon Dec  3 22:43:25 2001
@@ -73,6 +73,12 @@
                       unsigned long r6,
                       unsigned long r7);
 
+extern void gemini_init(unsigned long r3,
+                      unsigned long r4,
+                      unsigned long r5,
+                      unsigned long r6,
+                      unsigned long r7);
+
 #ifdef CONFIG_XMON
 extern void xmon_map_scc(void);
 #endif
@@ -80,13 +86,6 @@
 extern boot_infos_t *boot_infos;
 char saved_command_line[256];
 unsigned char aux_device_present;
-struct int_control_struct int_control =
-{
-	__no_use_cli,
-	__no_use_sti,
-	__no_use_restore_flags,
-	__no_use_save_flags
-};
 struct ide_machdep_calls ppc_ide_md;
 int parse_bootinfo(void);
 
@@ -547,6 +546,11 @@
 #ifdef CONFIG_APUS
 	case _MACH_apus:
                 apus_init(r3, r4, r5, r6, r7);
+		break;
+#endif
+#ifdef CONFIG_GEMINI
+	case _MACH_gemini:
+		gemini_init(r3, r4, r5, r6, r7);
 		break;
 #endif
 	default:
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S
--- linux-2.4.5-pre2/arch/ppc/kernel/sleep.S	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/kernel/sleep.S	Mon Dec  3 22:43:25 2001
@@ -1,6 +1,6 @@
 /*
  * This file contains sleep low-level functions for PowerBook G3.
- *    Copyright (C) 1999 Benjamin Herrenschmidt (bh40@calva.net)
+ *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
  *    and Paul Mackerras (paulus@cs.anu.edu.au).
  *
  * This program is free software; you can redistribute it and/or
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- linux-2.4.5-pre2/arch/ppc/kernel/smp.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/smp.c	Mon Dec  3 22:43:25 2001
@@ -40,6 +40,7 @@
 #include <asm/residual.h>
 #include <asm/feature.h>
 #include <asm/time.h>
+#include <asm/gemini.h>
 
 #include "open_pic.h"
 int smp_threads_ready;
@@ -55,7 +56,7 @@
 unsigned int prof_counter[NR_CPUS];
 cycles_t cacheflush_time;
 static int max_cpus __initdata = NR_CPUS;
-
+unsigned long cpu_online_map;
 int smp_hw_index[NR_CPUS];
 
 /* all cpu mappings are 1-1 -- Cort */
@@ -452,32 +453,48 @@
 static void
 smp_core99_kick_cpu(int nr)
 {
-	unsigned long save_int;
+	unsigned long save_vector, new_vector;
 	unsigned long flags;
+#if 1 /* New way... */
+	volatile unsigned long *vector
+		 = ((volatile unsigned long *)(KERNELBASE+0x100));
+	if (nr < 1 || nr > 3)
+		return;
+#else
 	volatile unsigned long *vector
 		 = ((volatile unsigned long *)(KERNELBASE+0x500));
-
 	if (nr != 1)
 		return;
+#endif
 	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
 
 	local_irq_save(flags);
 	local_irq_disable();
 	
-	/* Save EE vector */
-	save_int = *vector;
+	/* Save reset vector */
+	save_vector = *vector;
 	
-	/* Setup fake EE vector that does	  
+	/* Setup fake reset vector that does	  
 	 *   b __secondary_start_psurge - KERNELBASE
-	 */   
-	*vector = 0x48000002 +
-		((unsigned long)__secondary_start_psurge - KERNELBASE);
+	 */  
+	switch(nr) {
+		case 1:
+			new_vector = (unsigned long)__secondary_start_psurge;
+			break;
+		case 2:
+			new_vector = (unsigned long)__secondary_start_psurge2;
+			break;
+		case 3:
+			new_vector = (unsigned long)__secondary_start_psurge3;
+			break;
+	}
+	*vector = 0x48000002 + new_vector - KERNELBASE;
 	
 	/* flush data cache and inval instruction cache */
 	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
 	
 	/* Put some life in our friend */
-	feature_core99_kick_cpu1();
+	feature_core99_kick_cpu(nr);
 	
 	/* FIXME: We wait a bit for the CPU to take the exception, I should
 	 * instead wait for the entry code to set something for me. Well,
@@ -487,11 +504,11 @@
 	mdelay(1);
 	
 	/* Restore our exception vector */
-	*vector = save_int;
+	*vector = save_vector;
 	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
 	
 	local_irq_restore(flags);
-	if (ppc_md.progress) ppc_md.progress("smp_core99_probe done", 0x347);
+	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
 }
 
 static void
@@ -628,6 +645,43 @@
 		do_openpic_setup_cpu();
 }
 
+#ifdef CONFIG_GEMINI	
+static int
+smp_gemini_probe(void)
+{
+	int i, nr;
+
+        nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2;
+	if (nr == 0)
+		nr = 4;
+
+	if (nr > 1) {
+		openpic_request_IPIs();
+		for (i = 1; i < nr; ++i)
+			smp_hw_index[i] = i;
+	}
+
+	return nr;
+}
+
+static void
+smp_gemini_kick_cpu(int nr)
+{
+	openpic_init_processor( 1<<i );
+	openpic_init_processor( 0 );
+}
+
+static void
+smp_gemini_setup_cpu(void)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+	if (cpu_nr > 0)
+		gemini_init_l2();
+}
+#endif /* CONFIG_GEMINI */
+
+
 static struct smp_ops_t {
 	void  (*message_pass)(int target, int msg, unsigned long data, int wait);
 	int   (*probe)(void);
@@ -685,6 +739,16 @@
 	smp_prep_setup_cpu,
 };
 
+#ifdef CONFIG_GEMINI	
+/* Gemini */
+static struct smp_ops_t gemini_smp_ops = {
+	smp_openpic_message_pass,
+	smp_gemini_probe,
+	smp_gemini_kick_cpu,
+	smp_gemini_setup_cpu,
+};
+#endif /* CONFIG_GEMINI	*/
+
 /* 
  * Common functions
  */
@@ -925,6 +989,11 @@
 	case _MACH_prep:
 		smp_ops = &prep_smp_ops;
 		break;
+#ifdef CONFIG_GEMINI		
+	case _MACH_gemini:
+		smp_ops = &gemini_smp_ops;
+		break;
+#endif /* CONFIG_GEMINI	*/
 	default:
 		printk("SMP not supported on this machine.\n");
 		return;
@@ -946,6 +1015,19 @@
 		/* create a process for the processor */
 		/* we don't care about the values in regs since we'll
 		   never reschedule the forked task. */
+		/* We DO care about one bit in the pt_regs we
+		   pass to do_fork.  That is the MSR_FP bit in 
+		   regs.msr.  If that bit is on, then do_fork
+		   (via copy_thread) will call giveup_fpu.
+		   giveup_fpu will get a pointer to our (current's)
+		   last register savearea via current->thread.regs 
+		   and using that pointer will turn off the MSR_FP,
+		   MSR_FE0 and MSR_FE1 bits.  At this point, this 
+		   pointer is pointing to some arbitrary point within
+		   our stack. */
+
+		memset(&regs, 0, sizeof(struct pt_regs));
+		
 		if (do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0) < 0)
 			panic("failed fork for CPU %d", i);
 		p = init_task.prev_task;
@@ -1114,8 +1196,18 @@
 
 	init_idle();
 
+	/*
+	 * This cpu is now "online".  Only set them online
+	 * before they enter the loop below since write access
+	 * to the below variable is _not_ guaranteed to be
+	 * atomic.
+	 *   -- Cort <cort@fsmlabs.com>
+	 */
+	cpu_online_map |= 1UL << smp_processor_id();
+	
 	while(!smp_commenced)
 		barrier();
+
 	/* see smp_commence for more info */
 	if (!smp_tb_synchronized && smp_num_cpus == 2) {
 		smp_software_tb_sync(cpu);
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/syscalls.c linux/arch/ppc/kernel/syscalls.c
--- linux-2.4.5-pre2/arch/ppc/kernel/syscalls.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/ppc/kernel/syscalls.c	Mon Dec  3 22:43:25 2001
@@ -185,9 +185,10 @@
 	return error;
 }
 
-unsigned long sys_mmap(unsigned long addr, size_t len,
-		       unsigned long prot, unsigned long flags,
-		       unsigned long fd, off_t offset)
+static inline unsigned long
+do_mmap2(unsigned long addr, size_t len,
+	 unsigned long prot, unsigned long flags,
+	 unsigned long fd, unsigned long pgoff)
 {
 	struct file * file = NULL;
 	int ret = -EBADF;
@@ -199,12 +200,33 @@
 	}
 	
 	down_write(&current->mm->mmap_sem);
-	ret = do_mmap(file, addr, len, prot, flags, offset);
+	ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
 	if (file)
 		fput(file);
 out:
 	return ret;
+}
+
+unsigned long sys_mmap2(unsigned long addr, size_t len,
+			unsigned long prot, unsigned long flags,
+			unsigned long fd, unsigned long pgoff)
+{
+	return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+unsigned long sys_mmap(unsigned long addr, size_t len,
+		       unsigned long prot, unsigned long flags,
+		       unsigned long fd, off_t offset)
+{
+	int err = -EINVAL;
+
+	if (offset & ~PAGE_MASK)
+		goto out;
+
+	err = do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+out:
+	return err;
 }
 
 extern int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
diff -urN linux-2.4.5-pre2/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- linux-2.4.5-pre2/arch/ppc/kernel/time.c	Sat Mar  3 10:52:14 2001
+++ linux/arch/ppc/kernel/time.c	Mon Dec  3 22:43:25 2001
@@ -50,6 +50,7 @@
 #include <linux/param.h>
 #include <linux/string.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
 #include <linux/kernel_stat.h>
@@ -91,6 +92,10 @@
 
 static long time_offset;
 
+spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
+
+EXPORT_SYMBOL(rtc_lock);
+
 /* Timer interrupt helper function */
 static inline int tb_delta(unsigned *jiffy_stamp) {
 	int delta;
@@ -144,14 +149,20 @@
 	int next_dec;
 	unsigned long cpu = smp_processor_id();
 	unsigned jiffy_stamp = last_jiffy_stamp(cpu);
+	extern void do_IRQ(struct pt_regs *);
+
+	if (atomic_read(&ppc_n_lost_interrupts) != 0)
+		do_IRQ(regs);
 
 	hardirq_enter(cpu);
 	
-	if (!user_mode(regs))
-		ppc_do_profile(instruction_pointer(regs));
-	do { 
+	while ((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0) {
 		jiffy_stamp += tb_ticks_per_jiffy;
-	  	if (smp_processor_id()) continue;
+		if (!user_mode(regs))
+			ppc_do_profile(instruction_pointer(regs));
+	  	if (smp_processor_id())
+			continue;
+
 		/* We are in an interrupt, no need to save/restore flags */
 		write_lock(&xtime_lock);
 		tb_last_stamp = jiffy_stamp;
@@ -184,7 +195,7 @@
 				last_rtc_update += 60;
 		}
 		write_unlock(&xtime_lock);
-	} while((next_dec = tb_ticks_per_jiffy - tb_delta(&jiffy_stamp)) < 0);
+	}
 	if ( !disarm_decr[smp_processor_id()] )
 		set_dec(next_dec);
 	last_jiffy_stamp(cpu) = jiffy_stamp;
@@ -337,6 +348,8 @@
         	tz.tz_dsttime = 0;
         	do_sys_settimeofday(NULL, &tz);
         }
+
+       do_get_fast_time = do_gettimeofday;
 }
 
 #define TICK_SIZE tick
diff -urN linux-2.4.5-pre2/arch/ppc/lib/Makefile linux/arch/ppc/lib/Makefile
--- linux-2.4.5-pre2/arch/ppc/lib/Makefile	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/lib/Makefile	Mon Dec  3 22:43:25 2001
@@ -2,8 +2,7 @@
 # Makefile for ppc-specific library files..
 #
 
-.S.o:
-	$(CC) $(AFLAGS) -c $< -o $*.o
+USE_STANDARD_AS_RULE	:= true
 
 O_TARGET		:= lib.o
 
diff -urN linux-2.4.5-pre2/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- linux-2.4.5-pre2/arch/ppc/mm/init.c	Mon Mar 26 15:29:44 2001
+++ linux/arch/ppc/mm/init.c	Mon Dec  3 22:43:25 2001
@@ -46,7 +46,6 @@
 #include <asm/mmu_context.h>
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
-#include <asm/residual.h>
 #include <asm/uaccess.h>
 #ifdef CONFIG_8xx
 #include <asm/8xx_immap.h>
@@ -61,6 +60,7 @@
 #include <asm/machdep.h>
 #include <asm/setup.h>
 #include <asm/amigahw.h>
+#include <asm/gemini.h>
 
 #include "mem_pieces.h"
 
@@ -93,7 +93,6 @@
 extern char __pmac_begin, __pmac_end;
 extern char __apus_begin, __apus_end;
 extern char __openfirmware_begin, __openfirmware_end;
-struct device_node *memory_node;
 unsigned long ioremap_base;
 unsigned long ioremap_bot;
 unsigned long avail_start;
@@ -111,19 +110,6 @@
 
 void MMU_init(void);
 void *early_get_page(void);
-unsigned long prep_find_end_of_memory(void);
-unsigned long pmac_find_end_of_memory(void);
-unsigned long apus_find_end_of_memory(void);
-extern unsigned long find_end_of_memory(void);
-#ifdef CONFIG_8xx
-unsigned long m8xx_find_end_of_memory(void);
-#endif /* CONFIG_8xx */
-#ifdef CONFIG_4xx
-unsigned long oak_find_end_of_memory(void);
-#endif
-#ifdef CONFIG_8260
-unsigned long m8260_find_end_of_memory(void);
-#endif /* CONFIG_8260 */
 static void mapin_ram(void);
 int map_page(unsigned long va, unsigned long pa, int flags);
 void set_phys_avail(unsigned long total_ram);
@@ -436,11 +422,9 @@
 	 * Should check if it is a candidate for a BAT mapping
 	 */
 
-	spin_lock(&init_mm.page_table_lock);
 	err = 0;
 	for (i = 0; i < size && err == 0; i += PAGE_SIZE)
 		err = map_page(v+i, p+i, flags);
-	spin_unlock(&init_mm.page_table_lock);
 	if (err) {
 		if (mem_init_done)
 			vfree((void *)v);
@@ -487,17 +471,21 @@
 {
 	pmd_t *pd;
 	pte_t *pg;
+	int err = -ENOMEM;
 
+	spin_lock(&init_mm.page_table_lock);
 	/* Use upper 10 bits of VA to index the first level map */
 	pd = pmd_offset(pgd_offset_k(va), va);
 	/* Use middle 10 bits of VA to index the second-level map */
 	pg = pte_alloc(&init_mm, pd, va);
-	if (pg == 0)
-		return -ENOMEM;
-	set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
-	if (mem_init_done)
-		flush_hash_page(0, va);
-	return 0;
+	if (pg != 0) {
+		err = 0;
+		set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
+		if (mem_init_done)
+			flush_hash_page(0, va);
+	}
+	spin_unlock(&init_mm.page_table_lock);
+	return err;
 }
 
 #ifndef CONFIG_8xx
@@ -668,33 +656,6 @@
 }
 
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-static void get_mem_prop(char *, struct mem_pieces *);
-
-#if defined(CONFIG_ALL_PPC)
-/*
- * Read in a property describing some pieces of memory.
- */
-
-static void __init get_mem_prop(char *name, struct mem_pieces *mp)
-{
-	struct reg_property *rp;
-	int s;
-
-	rp = (struct reg_property *) get_property(memory_node, name, &s);
-	if (rp == NULL) {
-		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
-		       name);
-		abort();
-	}
-	mp->n_regions = s / sizeof(mp->regions[0]);
-	memcpy(mp->regions, rp, s);
-
-	/* Make sure the pieces are sorted. */
-	mem_pieces_sort(mp);
-	mem_pieces_coalesce(mp);
-}
-#endif /* CONFIG_ALL_PPC */
-
 /*
  * Set up one of the I/D BAT (block address translation) register pairs.
  * The parameters are not checked; in particular size must be a power
@@ -877,14 +838,13 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
-
 	for (; start < end; start += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(start));
 		set_page_count(virt_to_page(start), 1);
 		free_page(start);
 		totalram_pages++;
 	}
+	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
 
@@ -904,27 +864,28 @@
 	/*
 	 * The Zone Protection Register (ZPR) defines how protection will
 	 * be applied to every page which is a member of a given zone. At
-	 * present, we utilize only two of the 4xx's zones. The first, zone
-	 * 0, is set at '00b and only allows access in supervisor-mode based
-	 * on the EX and WR bits. No user-mode access is allowed. The second,
-	 * zone 1, is set at '10b and in supervisor-mode allows access
-	 * without regard to the EX and WR bits. In user-mode, access is
-	 * allowed based on the EX and WR bits.
+	 * present, we utilize only two of the 4xx's zones.
+	 * The zone index bits (of ZSEL) in the PTE are used for software
+	 * indicators, except the LSB.  For user access, zone 15 is used,
+	 * for kernel access, zone 14 is used.  We set all but zone 15
+	 * to zero, allowing only kernel access as indicated in the PTE.
+	 * For zone 15, we set a 10 binary (I guess a 01 would work too)
+	 * to allow user access as indicated in the PTE.  This also allows
+	 * kernel access as indicated in the PTE.
 	 */
 
-        mtspr(SPRN_ZPR, 0x2aaaaaaa);
-
-	/* Hardwire any TLB entries necessary here. */
+        mtspr(SPRN_ZPR, 0x00000002);
 
-	PPC4xx_tlb_pin(KERNELBASE, 0, TLB_PAGESZ(PAGESZ_16M), 1);
+	flush_instruction_cache();
 
 	/*
 	 * Find the top of physical memory and map all of it in starting
 	 * at KERNELBASE.
 	 */
 
-        total_memory = total_lowmem = oak_find_end_of_memory();
-	end_of_DRAM = __va(total_memory);
+        total_memory = total_lowmem = ppc_md.find_end_of_memory();
+	end_of_DRAM = __va(total_lowmem);
+	set_phys_avail(total_lowmem);
         mapin_ram();
 
 	/*
@@ -943,70 +904,13 @@
         mtspr(SPRN_ICCR, 0x80000000);	/* 128 MB of instr. space at 0x0. */
 }
 
-#elif defined(CONFIG_8xx)
+#else /* !CONFIG_4xx */
 void __init MMU_init(void)
 {
 	if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
 
-	total_memory = total_lowmem = m8xx_find_end_of_memory();
-#ifdef CONFIG_HIGHMEM
-	if (total_lowmem > MAX_LOW_MEM) {
-		total_lowmem = MAX_LOW_MEM;
-		mem_pieces_remove(&phys_avail, total_lowmem,
-				  total_memory - total_lowmem, 0);
-	}
-#endif /* CONFIG_HIGHMEM */
-	end_of_DRAM = __va(total_lowmem);
-	set_phys_avail(total_lowmem);
-
-        /* Map in all of RAM starting at KERNELBASE */
-        mapin_ram();
+	total_memory = ppc_md.find_end_of_memory();
 
-        /* Now map in some of the I/O space that is generically needed
-         * or shared with multiple devices.
-         * All of this fits into the same 4Mbyte region, so it only
-         * requires one page table page.
-         */
-        ioremap(IMAP_ADDR, IMAP_SIZE);
-#ifdef CONFIG_MBX
-        ioremap(NVRAM_ADDR, NVRAM_SIZE);
-        ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
-        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
-
-	/* Map some of the PCI/ISA I/O space to get the IDE interface.
-	*/
-        ioremap(PCI_ISA_IO_ADDR, 0x4000);
-        ioremap(PCI_IDE_ADDR, 0x4000);
-#endif
-#ifdef CONFIG_RPXLITE
-	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
-	ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE);
-#endif
-#ifdef CONFIG_RPXCLASSIC
-        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
-	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
-#endif
-	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
-}
-
-#else /* not 4xx or 8xx */
-void __init MMU_init(void)
-{
-	if ( ppc_md.progress ) ppc_md.progress("MMU:enter", 0x111);
-
-	if (have_of)
-		total_memory = pmac_find_end_of_memory();
-#ifdef CONFIG_APUS
-	else if (_machine == _MACH_apus )
-		total_memory = apus_find_end_of_memory();
-#endif
-#if defined(CONFIG_8260)
-	else
-		total_memory = m8260_find_end_of_memory();
-#else
-	else /* prep */
-		total_memory = prep_find_end_of_memory();
-#endif
 	if (__max_memory && total_memory > __max_memory)
 		total_memory = __max_memory;
 	total_lowmem = total_memory;
@@ -1019,6 +923,7 @@
 	end_of_DRAM = __va(total_lowmem);
 	set_phys_avail(total_lowmem);
 
+#if !defined(CONFIG_8xx)
 	if ( ppc_md.progress ) ppc_md.progress("MMU:hash init", 0x300);
         hash_init();
 #ifndef CONFIG_PPC64BRIDGE
@@ -1026,16 +931,49 @@
 #endif
 	
 	ioremap_base = 0xf8000000;
+#endif /* CONFIG_8xx */
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:mapin", 0x301);
 	/* Map in all of RAM starting at KERNELBASE */
 	mapin_ram();
 
-#ifdef CONFIG_POWER4
+#if defined(CONFIG_POWER4)
 	ioremap_base = ioremap_bot = 0xfffff000;
 	isa_io_base = (unsigned long) ioremap(0xffd00000, 0x200000) + 0x100000;
 
-#else /* CONFIG_POWER4 */
+#elif defined(CONFIG_8xx)
+        /* Now map in some of the I/O space that is generically needed
+         * or shared with multiple devices.
+         * All of this fits into the same 4Mbyte region, so it only
+         * requires one page table page.
+         */
+        ioremap(IMAP_ADDR, IMAP_SIZE);
+#ifdef CONFIG_MBX
+        ioremap(NVRAM_ADDR, NVRAM_SIZE);
+        ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
+        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+
+	/* Map some of the PCI/ISA I/O space to get the IDE interface.
+	*/
+        ioremap(PCI_ISA_IO_ADDR, 0x4000);
+        ioremap(PCI_IDE_ADDR, 0x4000);
+#endif
+#if defined(CONFIG_RPXLITE) || defined(CONFIG_RPXCLASSIC)
+	ioremap(RPX_CSR_ADDR, RPX_CSR_SIZE);
+#if !defined(CONFIG_PCI)
+	ioremap(_IO_BASE,_IO_BASE_SIZE);
+#endif
+#endif
+#ifdef CONFIG_HTDMSOUND
+	ioremap(HIOX_CSR_ADDR, HIOX_CSR_SIZE);
+#endif
+#ifdef CONFIG_FADS
+	ioremap(BCSR_ADDR, BCSR_SIZE);
+#endif
+#ifdef CONFIG_PCI
+        ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
+#endif
+#else /* !CONFIG_POWER4 && !CONFIG_8xx */
 	/*
 	 * Setup the bat mappings we're going to load that cover
 	 * the io areas.  RAM was mapped by mapin_ram().
@@ -1069,6 +1007,10 @@
 		/* Map chip and ZorroII memory */
 		setbat(1, zTwoBase,   0x00000000, 0x01000000, IO_PAGE);
 		break;
+	case _MACH_gemini:
+		setbat(0, 0xf0000000, 0xf0000000, 0x10000000, IO_PAGE);
+		setbat(1, 0x80000000, 0x80000000, 0x10000000, IO_PAGE);
+		break;
 	case _MACH_8260:
 		/* Map the IMMR, plus anything else we can cover
 		 * in that upper space according to the memory controller
@@ -1081,7 +1023,7 @@
 		break;
 	}
 	ioremap_bot = ioremap_base;
-#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_POWER4 || CONFIG_8xx */
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
 #ifdef CONFIG_BOOTX_TEXT
@@ -1257,155 +1199,6 @@
 }
 
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-#if defined(CONFIG_ALL_PPC)
-/*
- * On systems with Open Firmware, collect information about
- * physical RAM and which pieces are already in use.
- * At this point, we have (at least) the first 8MB mapped with a BAT.
- * Our text, data, bss use something over 1MB, starting at 0.
- * Open Firmware may be using 1MB at the 4MB point.
- */
-unsigned long __init pmac_find_end_of_memory(void)
-{
-	unsigned long a, total;
-	struct mem_pieces phys_mem;
-
-	memory_node = find_devices("memory");
-	if (memory_node == NULL) {
-		printk(KERN_ERR "can't find memory node\n");
-		abort();
-	}
-
-	/*
-	 * Find out where physical memory is, and check that it
-	 * starts at 0 and is contiguous.  It seems that RAM is
-	 * always physically contiguous on Power Macintoshes.
-	 *
-	 * Supporting discontiguous physical memory isn't hard,
-	 * it just makes the virtual <-> physical mapping functions
-	 * more complicated (or else you end up wasting space
-	 * in mem_map).
-	 */
-	get_mem_prop("reg", &phys_mem);
-	if (phys_mem.n_regions == 0)
-		panic("No RAM??");
-	a = phys_mem.regions[0].address;
-	if (a != 0)
-		panic("RAM doesn't start at physical address 0");
-	total = phys_mem.regions[0].size;
-
-	if (phys_mem.n_regions > 1) {
-		printk("RAM starting at 0x%x is not contiguous\n",
-		       phys_mem.regions[1].address);
-		printk("Using RAM from 0 to 0x%lx\n", total-1);
-	}
-
-	return total;
-}
-#endif /* CONFIG_ALL_PPC */
-
-#if defined(CONFIG_ALL_PPC)
-/*
- * This finds the amount of physical ram and does necessary
- * setup for prep.  This is pretty architecture specific so
- * this will likely stay separate from the pmac.
- * -- Cort
- */
-unsigned long __init prep_find_end_of_memory(void)
-{
-	unsigned long total;
-#ifdef CONFIG_PREP_RESIDUAL
-	total = res->TotalMemory;
-#else
-	total = 0;
-#endif
-
-	if (total == 0 )
-	{
-		/*
-		 * I need a way to probe the amount of memory if the residual
-		 * data doesn't contain it. -- Cort
-		 */
-		printk("Ramsize from residual data was 0 -- Probing for value\n");
-		total = 0x02000000;
-		printk("Ramsize default to be %ldM\n", total>>20);
-	}
-
-	return (total);
-}
-#endif /* defined(CONFIG_ALL_PPC) */
-
-#ifdef CONFIG_8260
-/*
- * Same hack as 8xx.
- */
-unsigned long __init m8260_find_end_of_memory(void)
-{
-	bd_t	*binfo;
-	extern unsigned char __res[];
-	
-	binfo = (bd_t *)__res;
-
-	return binfo->bi_memsize;
-}
-#endif /* CONFIG_8260 */
-
-#ifdef CONFIG_APUS
-#define HARDWARE_MAPPED_SIZE (512*1024)
-unsigned long __init apus_find_end_of_memory(void)
-{
-	int shadow = 0;
-	unsigned long total;
-
-	/* The memory size reported by ADOS excludes the 512KB
-	   reserved for PPC exception registers and possibly 512KB
-	   containing a shadow of the ADOS ROM. */
-	{
-		unsigned long size = memory[0].size;
-
-		/* If 2MB aligned, size was probably user
-                   specified. We can't tell anything about shadowing
-                   in this case so skip shadow assignment. */
-		if (0 != (size & 0x1fffff)){
-			/* Align to 512KB to ensure correct handling
-			   of both memfile and system specified
-			   sizes. */
-			size = ((size+0x0007ffff) & 0xfff80000);
-			/* If memory is 1MB aligned, assume
-                           shadowing. */
-			shadow = !(size & 0x80000);
-		}
-
-		/* Add the chunk that ADOS does not see. by aligning
-                   the size to the nearest 2MB limit upwards.  */
-		memory[0].size = ((size+0x001fffff) & 0xffe00000);
-	}
-
-	total = memory[0].size;
-
-	/* Remove the memory chunks that are controlled by special
-           Phase5 hardware. */
-
-	/* Remove the upper 512KB if it contains a shadow of
-	   the ADOS ROM. FIXME: It might be possible to
-	   disable this shadow HW. Check the booter
-	   (ppc_boot.c) */
-	if (shadow)
-		total -= HARDWARE_MAPPED_SIZE;
-
-	/* Remove the upper 512KB where the PPC exception
-	   vectors are mapped. */
-	total -= HARDWARE_MAPPED_SIZE;
-
-	/* Linux/APUS only handles one block of memory -- the one on
-	   the PowerUP board. Other system memory is horrible slow in
-	   comparison. The user can use other memory for swapping
-	   using the z2ram device. */
-	ram_phys_base = memory[0].addr;
-	return total;
-}
-#endif /* CONFIG_APUS */
-
 /*
  * Initialize the hash table and patch the instructions in head.S.
  */
@@ -1514,43 +1307,7 @@
 	}
 	if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
-#elif defined(CONFIG_8xx)
-/*
- * This is a big hack right now, but it may turn into something real
- * someday.
- *
- * For the 8xx boards (at this time anyway), there is nothing to initialize
- * associated the PROM.  Rather than include all of the prom.c
- * functions in the image just to get prom_init, all we really need right
- * now is the initialization of the physical memory region.
- */
-unsigned long __init m8xx_find_end_of_memory(void)
-{
-	bd_t	*binfo;
-	extern unsigned char __res[];
-	
-	binfo = (bd_t *)__res;
-
-	return binfo->bi_memsize;
-}
 #endif /* !CONFIG_4xx && !CONFIG_8xx */
-
-#ifdef CONFIG_OAK
-/*
- * Return the virtual address representing the top of physical RAM
- * on the Oak board.
- */
-unsigned long __init
-oak_find_end_of_memory(void)
-{
-	extern unsigned char __res[];
-
-	unsigned long *ret;
-	bd_t *bip = (bd_t *)__res;
-	
-	return bip->bi_memsize;
-}
-#endif
 
 /*
  * Set phys_avail to the amount of physical memory,
diff -urN linux-2.4.5-pre2/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c
--- linux-2.4.5-pre2/arch/ppc/xmon/start.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/xmon/start.c	Mon Dec  3 22:43:25 2001
@@ -61,27 +61,37 @@
 		struct device_node *np;
 		unsigned long addr;
 #ifdef CONFIG_BOOTX_TEXT
-		extern boot_infos_t *disp_bi;
+		if (!machine_is_compatible("iMac")) {
+			extern boot_infos_t *disp_bi;
 
-		/* see if there is a keyboard in the device tree
-		   with a parent of type "adb" */
-		for (np = find_devices("keyboard"); np; np = np->next)
-			if (np->parent && np->parent->type
-			    && strcmp(np->parent->type, "adb") == 0)
-				break;
+			/* see if there is a keyboard in the device tree
+			   with a parent of type "adb" */
+			for (np = find_devices("keyboard"); np; np = np->next)
+				if (np->parent && np->parent->type
+				    && strcmp(np->parent->type, "adb") == 0)
+					break;
 
-		/* needs to be hacked if xmon_printk is to be used
- 		   from within find_via_pmu() */
+			/* needs to be hacked if xmon_printk is to be used
+			   from within find_via_pmu() */
 #ifdef CONFIG_ADB_PMU
-		if (np != NULL && disp_bi && find_via_pmu())
-			use_screen = 1;
+			if (np != NULL && disp_bi && find_via_pmu())
+				use_screen = 1;
 #endif
 #ifdef CONFIG_ADB_CUDA
-		if (np != NULL && disp_bi && find_via_cuda())
-			use_screen = 1;
+			if (np != NULL && disp_bi && find_via_cuda())
+				use_screen = 1;
 #endif
+		}
+		prom_drawstring("xmon uses ");
 		if (use_screen)
-			prom_drawstring("xmon uses screen and keyboard\n");
+			prom_drawstring("screen and keyboard\n");
+		else {
+			if (via_modem)
+				prom_drawstring("modem on ");
+			prom_drawstring(xmon_use_sccb? "printer": "modem");
+			prom_drawstring(" port\n");
+		}
+
 #endif /* CONFIG_BOOTX_TEXT */
 
 #ifdef CHRP_ESCC
@@ -100,6 +110,15 @@
 		base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
 		sccc = base + (addr & ~PAGE_MASK);
 		sccd = sccc + 0x10;
+	}
+	else if ( _machine & _MACH_gemini )
+	{
+		/* should already be mapped by the kernel boot */
+		sccc = (volatile unsigned char *) 0xffeffb0d;
+		sccd = (volatile unsigned char *) 0xffeffb08;
+		TXRDY = 0x20;
+		RXRDY = 1;
+		console = 1;
 	}
 	else
 	{
diff -urN linux-2.4.5-pre2/arch/ppc/xmon/start_8xx.c linux/arch/ppc/xmon/start_8xx.c
--- linux-2.4.5-pre2/arch/ppc/xmon/start_8xx.c	Wed May  3 01:47:57 2000
+++ linux/arch/ppc/xmon/start_8xx.c	Mon Dec  3 22:43:25 2001
@@ -15,7 +15,7 @@
 #include <asm/processor.h>
 #include <asm/8xx_immap.h>
 #include <asm/mpc8xx.h>
-#include "commproc.h"
+#include "../8xx_io/commproc.h"
 
 extern void xmon_printf(const char *fmt, ...);
 extern int xmon_8xx_write(char *str, int nb);
diff -urN linux-2.4.5-pre2/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- linux-2.4.5-pre2/arch/ppc/xmon/xmon.c	Mon Jan 22 15:41:15 2001
+++ linux/arch/ppc/xmon/xmon.c	Mon Dec  3 22:43:25 2001
@@ -208,10 +208,11 @@
 xmon_irq(int irq, void *d, struct pt_regs *regs)
 {
 	unsigned long flags;
-	save_flags(flags);cli();
+	__save_flags(flags);
+	__cli();
 	printf("Keyboard interrupt\n");
 	xmon(regs);
-	restore_flags(flags);
+	__restore_flags(flags);
 }
 
 int
@@ -657,7 +658,7 @@
 	unsigned stack[2];
 	struct pt_regs regs;
 	extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
-	extern char lost_irq_ret, do_bottom_half_ret, do_signal_ret;
+	extern char do_bottom_half_ret, do_signal_ret;
 	extern char ret_from_except;
 
 	printf("backtrace:\n");
@@ -676,7 +677,6 @@
 		    || stack[1] == (unsigned) &ret_from_except
 		    || stack[1] == (unsigned) &ret_from_syscall_1
 		    || stack[1] == (unsigned) &ret_from_syscall_2
-		    || stack[1] == (unsigned) &lost_irq_ret
 		    || stack[1] == (unsigned) &do_bottom_half_ret
 		    || stack[1] == (unsigned) &do_signal_ret) {
 			if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
diff -urN linux-2.4.5-pre2/arch/sparc/defconfig linux/arch/sparc/defconfig
--- linux-2.4.5-pre2/arch/sparc/defconfig	Sun Mar 25 18:14:21 2001
+++ linux/arch/sparc/defconfig	Mon Dec  3 22:43:25 2001
@@ -148,7 +148,6 @@
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
-# CONFIG_IPV6_EUI64 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
 
diff -urN linux-2.4.5-pre2/arch/sparc64/config.in linux/arch/sparc64/config.in
--- linux-2.4.5-pre2/arch/sparc64/config.in	Thu Apr 19 08:38:48 2001
+++ linux/arch/sparc64/config.in	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.141 2001/04/19 01:52:04 davem Exp $
+# $Id: config.in,v 1.142 2001/05/05 07:46:04 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -337,6 +337,15 @@
 source drivers/input/Config.in
 
 source fs/Config.in
+
+mainmenu_option next_comment
+comment 'Sound'
+
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+   source drivers/sound/Config.in
+fi
+endmenu
 
 source drivers/usb/Config.in
 
diff -urN linux-2.4.5-pre2/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux-2.4.5-pre2/arch/sparc64/defconfig	Mon Dec  3 22:43:16 2001
+++ linux/arch/sparc64/defconfig	Mon Dec  3 22:43:25 2001
@@ -178,7 +178,6 @@
 CONFIG_INET_ECN=y
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
-# CONFIG_IPV6_EUI64 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
 
@@ -312,6 +311,7 @@
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
 CONFIG_AIC7XXX_RESET_DELAY_MS=5000
+# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
 CONFIG_SCSI_AIC7XXX_OLD=m
 CONFIG_AIC7XXX_OLD_TCQ_ON_BY_DEFAULT=y
 CONFIG_AIC7XXX_OLD_CMDS_PER_DEVICE=8
@@ -547,6 +547,28 @@
 # CONFIG_NLS_UTF8 is not set
 
 #
+# Sound
+#
+CONFIG_SOUND=m
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+CONFIG_SOUND_ES1371=m
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+# CONFIG_SOUND_SONICVIBES is not set
+CONFIG_SOUND_TRIDENT=m
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
 # USB support
 #
 CONFIG_USB=y
@@ -561,8 +583,7 @@
 #
 # USB Controllers
 #
-# CONFIG_USB_UHCI is not set
-# CONFIG_USB_UHCI_ALT is not set
+CONFIG_USB_UHCI=y
 CONFIG_USB_OHCI=y
 
 #
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- linux-2.4.5-pre2/arch/sparc64/kernel/Makefile	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/Makefile	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.66 2001/04/03 12:29:38 davem Exp $
+# $Id: Makefile,v 1.67 2001/05/11 04:31:55 davem Exp $
 # Makefile for the linux kernel.
 #
 # Note! Dependencies are done automagically by 'make dep', which also
@@ -26,7 +26,7 @@
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
 		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o
 
-obj-$(CONFIG_PCI)	 += ebus.o pci_common.o pci_iommu.o \
+obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o
 obj-$(CONFIG_SMP)	 += smp.o trampoline.o
 obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o ioctl32.o
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/ioctl32.c	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/ioctl32.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.111 2001/03/27 07:28:43 davem Exp $
+/* $Id: ioctl32.c,v 1.115 2001/05/12 06:41:58 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -49,6 +49,7 @@
 #include <linux/blk.h>
 #include <linux/elevator.h>
 #include <linux/rtc.h>
+#include <linux/pci.h>
 #if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
 /* Ugh. This header really is not clean */
 #define min min
@@ -514,10 +515,19 @@
 			}
 		}
 		if (!err) {
-			if (i <= ifc32.ifc_len)
+			if (ifc32.ifcbuf == 0) {
+				/* Translate from 64-bit structure multiple to
+				 * a 32-bit one.
+				 */
+				i = ifc.ifc_len;
+				i = ((i / sizeof(struct ifreq)) * sizeof(struct ifreq32));
 				ifc32.ifc_len = i;
-			else
-				ifc32.ifc_len = i - sizeof (struct ifreq32);
+			} else {
+				if (i <= ifc32.ifc_len)
+					ifc32.ifc_len = i;
+				else
+					ifc32.ifc_len = i - sizeof (struct ifreq32);
+			}
 			if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32)))
 				err = -EFAULT;
 		}
@@ -3369,11 +3379,6 @@
 COMPATIBLE_IOCTL(SIOCSARP)
 COMPATIBLE_IOCTL(SIOCGARP)
 COMPATIBLE_IOCTL(SIOCDARP)
-#if 0 /* XXX No longer exist in new routing code. XXX */
-COMPATIBLE_IOCTL(OLD_SIOCSARP)
-COMPATIBLE_IOCTL(OLD_SIOCGARP)
-COMPATIBLE_IOCTL(OLD_SIOCDARP)
-#endif
 COMPATIBLE_IOCTL(SIOCSRARP)
 COMPATIBLE_IOCTL(SIOCGRARP)
 COMPATIBLE_IOCTL(SIOCDRARP)
@@ -3714,6 +3719,13 @@
 COMPATIBLE_IOCTL(WIOCSTART)
 COMPATIBLE_IOCTL(WIOCSTOP)
 COMPATIBLE_IOCTL(WIOCGSTAT)
+/* Misc. */
+COMPATIBLE_IOCTL(0x41545900)		/* ATYIO_CLKR */
+COMPATIBLE_IOCTL(0x41545901)		/* ATYIO_CLKW */
+COMPATIBLE_IOCTL(PCIIOC_CONTROLLER)
+COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO)
+COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM)
+COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE)
 /* And these ioctls need translation */
 HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
 HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
@@ -3991,8 +4003,9 @@
 	} else {
 		static int count = 0;
 		if (++count <= 20)
-			printk("sys32_ioctl: Unknown cmd fd(%d) "
+			printk("sys32_ioctl(%s:%d): Unknown cmd fd(%d) "
 			       "cmd(%08x) arg(%08x)\n",
+			       current->comm, current->pid,
 			       (int)fd, (unsigned int)cmd, (unsigned int)arg);
 		error = -EINVAL;
 	}
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/isa.c linux/arch/sparc64/kernel/isa.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/isa.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sparc64/kernel/isa.c	Mon Dec  3 22:43:25 2001
@@ -0,0 +1,269 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <asm/oplib.h>
+#include <asm/isa.h>
+
+struct isa_bridge *isa_chain;
+
+static void __init fatal_err(const char *reason)
+{
+	prom_printf("ISA: fatal error, %s.\n", reason);
+}
+
+static void __init report_dev(struct isa_device *isa_dev, int child)
+{
+	if (child)
+		printk(" (%s)", isa_dev->prom_name);
+	else
+		printk(" [%s", isa_dev->prom_name);
+}
+
+static void __init isa_dev_get_resource(struct isa_device *isa_dev)
+{
+	struct linux_prom_registers regs[PROMREG_MAX];
+	unsigned long base, len;
+	int prop_len;
+
+	prop_len = prom_getproperty(isa_dev->prom_node, "reg",
+				    (char *) regs, sizeof(regs));
+
+	if (prop_len <= 0)
+		return;
+
+	/* Only the first one is interesting. */
+	len = regs[0].reg_size;
+	base = (((unsigned long)regs[0].which_io << 32) |
+		(unsigned long)regs[0].phys_addr);
+	base += isa_dev->bus->parent->io_space.start;
+
+	isa_dev->resource.start = base;
+	isa_dev->resource.end   = (base + len - 1UL);
+	isa_dev->resource.flags = IORESOURCE_IO;
+	isa_dev->resource.name  = isa_dev->prom_name;
+
+	request_resource(&isa_dev->bus->parent->io_space,
+			 &isa_dev->resource);
+}
+
+/* I can't believe they didn't put a real INO in the isa device
+ * interrupts property.  The whole point of the OBP properties
+ * is to shield the kernel from IRQ routing details.
+ *
+ * The P1275 standard for ISA devices seems to also have been
+ * totally ignored.
+ */
+static struct {
+	int	obp_irq;
+	int	pci_ino;
+} grover_irq_table[] = {
+	{ 1, 0x00 },	/* dma, unknown ino at this point */
+	{ 2, 0x27 },	/* floppy */
+	{ 3, 0x22 },	/* parallel */
+	{ 4, 0x2b },	/* serial */
+	{ 5, 0x25 },	/* acpi power management */
+
+	{ 0, 0x00 }	/* end of table */
+};
+
+static void __init isa_dev_get_irq(struct isa_device *isa_dev)
+{
+	int irq_prop;
+
+	irq_prop = prom_getintdefault(isa_dev->prom_node,
+				      "interrupts", -1);
+	if (irq_prop <= 0) {
+		isa_dev->irq = 0;
+	} else {
+		int i;
+
+		for (i = 0; grover_irq_table[i].obp_irq != 0; i++) {
+			if (grover_irq_table[i].obp_irq == irq_prop) {
+				struct pci_controller_info *pcic;
+				struct pci_pbm_info *pbm;
+				int ino = grover_irq_table[i].pci_ino;
+
+				if (ino == 0) {
+					isa_dev->irq = 0;
+				} else {
+					pbm = isa_dev->bus->parent;
+					pcic = pbm->parent;
+					isa_dev->irq = pcic->irq_build(pbm, NULL, ino);
+				}
+			}
+		}
+	}
+}
+
+static void __init isa_fill_children(struct isa_device *parent_isa_dev)
+{
+	int node = prom_getchild(parent_isa_dev->prom_node);
+
+	if (node == 0)
+		return;
+
+	printk(" ->");
+	while (node != 0) {
+		struct isa_device *isa_dev;
+		int prop_len;
+
+		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+		if (!isa_dev) {
+			fatal_err("cannot allocate child isa_dev");
+			prom_halt();
+		}
+
+		memset(isa_dev, 0, sizeof(*isa_dev));
+
+		/* Link it in to parent. */
+		isa_dev->next = parent_isa_dev->child;
+		parent_isa_dev->child = isa_dev;
+
+		isa_dev->bus = parent_isa_dev->bus;
+		isa_dev->prom_node = node;
+		prop_len = prom_getproperty(node, "name",
+					    (char *) isa_dev->prom_name,
+					    sizeof(isa_dev->prom_name));
+		if (prop_len <= 0) {
+			fatal_err("cannot get child isa_dev OBP node name");
+			prom_halt();
+		}
+
+		prop_len = prom_getproperty(node, "compatible",
+					    (char *) isa_dev->compatible,
+					    sizeof(isa_dev->compatible));
+
+		/* Not having this is OK. */
+		if (prop_len <= 0)
+			isa_dev->compatible[0] = '\0';
+
+		isa_dev_get_resource(isa_dev);
+		isa_dev_get_irq(isa_dev);
+
+		report_dev(isa_dev, 1);
+
+		node = prom_getsibling(node);
+	}
+}
+
+static void __init isa_fill_devices(struct isa_bridge *isa_br)
+{
+	int node = prom_getchild(isa_br->prom_node);
+
+	while (node != 0) {
+		struct isa_device *isa_dev;
+		int prop_len;
+
+		isa_dev = kmalloc(sizeof(*isa_dev), GFP_KERNEL);
+		if (!isa_dev) {
+			fatal_err("cannot allocate isa_dev");
+			prom_halt();
+		}
+
+		memset(isa_dev, 0, sizeof(*isa_dev));
+
+		/* Link it in. */
+		isa_dev->next = NULL;
+		if (isa_br->devices == NULL) {
+			isa_br->devices = isa_dev;
+		} else {
+			struct isa_device *tmp = isa_br->devices;
+
+			while (tmp->next)
+				tmp = tmp->next;
+
+			tmp->next = isa_dev;
+		}
+
+		isa_dev->bus = isa_br;
+		isa_dev->prom_node = node;
+		prop_len = prom_getproperty(node, "name",
+					    (char *) isa_dev->prom_name,
+					    sizeof(isa_dev->prom_name));
+		if (prop_len <= 0) {
+			fatal_err("cannot get isa_dev OBP node name");
+			prom_halt();
+		}
+
+		prop_len = prom_getproperty(node, "compatible",
+					    (char *) isa_dev->compatible,
+					    sizeof(isa_dev->compatible));
+
+		/* Not having this is OK. */
+		if (prop_len <= 0)
+			isa_dev->compatible[0] = '\0';
+
+		isa_dev_get_resource(isa_dev);
+		isa_dev_get_irq(isa_dev);
+
+		report_dev(isa_dev, 0);
+
+		isa_fill_children(isa_dev);
+
+		printk("]");
+
+		node = prom_getsibling(node);
+	}
+}
+
+void __init isa_init(void)
+{
+	struct pci_dev *pdev;
+	unsigned short vendor, device;
+	int index = 0;
+
+	vendor = PCI_VENDOR_ID_AL;
+	device = PCI_DEVICE_ID_AL_M1533;
+
+	pdev = NULL;
+	while ((pdev = pci_find_device(vendor, device, pdev)) != NULL) {
+		struct pcidev_cookie *pdev_cookie;
+		struct pci_pbm_info *pbm;
+		struct isa_bridge *isa_br;
+		int prop_len;
+
+		pdev_cookie = pdev->sysdata;
+		if (!pdev_cookie) {
+			printk("ISA: Warning, ISA bridge ignored due to "
+			       "lack of OBP data.\n");
+			continue;
+		}
+		pbm = pdev_cookie->pbm;
+
+		isa_br = kmalloc(sizeof(*isa_br), GFP_KERNEL);
+		if (!isa_br) {
+			fatal_err("cannot allocate isa_bridge");
+			prom_halt();
+		}
+
+		memset(isa_br, 0, sizeof(*isa_br));
+
+		/* Link it in. */
+		isa_br->next = isa_chain;
+		isa_chain = isa_br;
+
+		isa_br->parent = pbm;
+		isa_br->self = pdev;
+		isa_br->index = index++;
+		isa_br->prom_node = pdev_cookie->prom_node;
+		strncpy(isa_br->prom_name, pdev_cookie->prom_name,
+			sizeof(isa_br->prom_name));
+
+		prop_len = prom_getproperty(isa_br->prom_node,
+					    "ranges",
+					    (char *) isa_br->isa_ranges,
+					    sizeof(isa_br->isa_ranges));
+		if (prop_len <= 0)
+			isa_br->num_isa_ranges = 0;
+		else
+			isa_br->num_isa_ranges =
+				(prop_len / sizeof(struct linux_prom_isa_ranges));
+
+		printk("isa%d:", isa_br->index);
+
+		isa_fill_devices(isa_br);
+
+		printk("\n");
+	}
+}
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/pci.c	Mon Dec  3 22:43:16 2001
+++ linux/arch/sparc64/kernel/pci.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.25 2001/05/02 00:27:27 davem Exp $
+/* $Id: pci.c,v 1.29 2001/05/15 08:54:30 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -19,6 +19,7 @@
 #include <asm/pbm.h>
 #include <asm/irq.h>
 #include <asm/ebus.h>
+#include <asm/isa.h>
 
 unsigned long pci_memspace_mask = 0xffffffffUL;
 
@@ -187,6 +188,7 @@
 	if (pci_device_reorder)
 		pci_reorder_devs();
 
+	isa_init();
 	ebus_init();
 }
 
@@ -232,6 +234,149 @@
 		return NULL;
 	}
 	return str;
+}
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+/* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding
+ * to the 32-bit pci bus offset for DEV requested by the user.
+ *
+ * Basically, the user finds the base address for his device which he wishes
+ * to mmap.  They read the 32-bit value from the config space base register,
+ * add whatever PAGE_SIZE multiple offset they wish, and feed this into the
+ * offset parameter of mmap on /proc/bus/pci/XXX for that device.
+ *
+ * Returns negative error code on failure, zero on success.
+ */
+static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+					     enum pci_mmap_state mmap_state)
+{
+	unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT;
+	unsigned long user32 = user_offset & 0xffffffffUL;
+	unsigned long largest_base, this_base, addr32;
+	int i;
+
+	/* Figure out which base address this is for. */
+	largest_base = 0UL;
+	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
+		struct resource *rp = &dev->resource[i];
+
+		/* Active? */
+		if (!rp->flags)
+			continue;
+
+		/* Same type? */
+		if (i == PCI_ROM_RESOURCE) {
+			if (mmap_state != pci_mmap_mem)
+				continue;
+		} else {
+			if ((mmap_state == pci_mmap_io &&
+			     (rp->flags & IORESOURCE_IO) == 0) ||
+			    (mmap_state == pci_mmap_mem &&
+			     (rp->flags & IORESOURCE_MEM) == 0))
+				continue;
+		}
+
+		this_base = rp->start;
+
+		addr32 = (this_base & PAGE_MASK) & 0xffffffffUL;
+
+		if (mmap_state == pci_mmap_io)
+			addr32 &= 0xffffff;
+
+		if (addr32 <= user32 && this_base > largest_base)
+			largest_base = this_base;
+	}
+
+	if (largest_base == 0UL)
+		return -EINVAL;
+
+	/* Now construct the final physical address. */
+	if (mmap_state == pci_mmap_io)
+		vma->vm_pgoff = (((largest_base & ~0xffffffUL) | user32) >> PAGE_SHIFT);
+	else
+		vma->vm_pgoff = (((largest_base & ~0xffffffffUL) | user32) >> PAGE_SHIFT);
+
+	return 0;
+}
+
+/* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
+ * mapping.
+ */
+static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
+					    enum pci_mmap_state mmap_state)
+{
+	vma->vm_flags |= (VM_SHM | VM_LOCKED);
+}
+
+/* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
+ * device mapping.
+ */
+static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+					     enum pci_mmap_state mmap_state)
+{
+	/* Our io_remap_page_range takes care of this, do nothing. */
+}
+
+extern int io_remap_page_range(unsigned long from, unsigned long offset,
+			       unsigned long size, pgprot_t prot, int space);
+
+/* Perform the actual remap of the pages for a PCI device mapping, as appropriate
+ * for this architecture.  The region in the process to map is described by vm_start
+ * and vm_end members of VMA, the base physical address is found in vm_pgoff.
+ * The pci device structure is provided so that architectures may make mapping
+ * decisions on a per-device or per-bus basis.
+ *
+ * Returns a negative error code on failure, zero on success.
+ */
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state,
+			int write_combine)
+{
+	int ret;
+
+	ret = __pci_mmap_make_offset(dev, vma, mmap_state);
+	if (ret < 0)
+		return ret;
+
+	__pci_mmap_set_flags(dev, vma, mmap_state);
+	__pci_mmap_set_pgprot(dev, vma, mmap_state);
+
+	ret = io_remap_page_range(vma->vm_start,
+				  (vma->vm_pgoff << PAGE_SHIFT |
+				   (write_combine ? 0x1UL : 0x0UL)),
+				  vma->vm_end - vma->vm_start, vma->vm_page_prot, 0);
+	if (ret)
+		return ret;
+
+	vma->vm_flags |= VM_IO;
+	return 0;
+}
+
+/* Return the index of the PCI controller for device PDEV. */
+
+int pci_controller_num(struct pci_dev *pdev)
+{
+	struct pcidev_cookie *cookie = pdev->sysdata;
+	int ret;
+
+	if (cookie != NULL) {
+		struct pci_pbm_info *pbm = cookie->pbm;
+		if (pbm == NULL || pbm->parent == NULL) {
+			ret = -ENXIO;
+		} else {
+			struct pci_controller_info *p = pbm->parent;
+
+			ret = p->index;
+			if (p->pbms_same_domain == 0)
+				ret = ((ret << 1) +
+				       ((pbm == &pbm->parent->pbm_B) ? 1 : 0));
+		}
+	} else {
+		ret = -ENXIO;
+	}
+
+	return ret;
 }
 
 #endif /* !(CONFIG_PCI) */
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/pci_common.c	Tue Mar  6 22:44:16 2001
+++ linux/arch/sparc64/kernel/pci_common.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.14 2001/02/28 03:28:55 davem Exp $
+/* $Id: pci_common.c,v 1.17 2001/05/15 12:32:52 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -10,6 +10,29 @@
 
 #include <asm/pbm.h>
 
+/* Fix self device of BUS and hook it into BUS->self.
+ * The pci_scan_bus does not do this for the host bridge.
+ */
+void __init pci_fixup_host_bridge_self(struct pci_bus *pbus)
+{
+	struct list_head *walk = &pbus->devices;
+
+	walk = walk->next;
+	while (walk != &pbus->devices) {
+		struct pci_dev *pdev = pci_dev_b(walk);
+
+		if (pdev->class >> 8 == PCI_CLASS_BRIDGE_HOST) {
+			pbus->self = pdev;
+			return;
+		}
+
+		walk = walk->next;
+	}
+
+	prom_printf("PCI: Critical error, cannot find host bridge PDEV.\n");
+	prom_halt();
+}
+
 /* Find the OBP PROM device tree node for a PCI device.
  * Return zero if not found.
  */
@@ -29,7 +52,10 @@
 	 */
 	if ((pdev->bus->number == pbm->pci_bus->number) && (pdev->devfn == 0) &&
 	    (pdev->vendor == PCI_VENDOR_ID_SUN) &&
-	    (pdev->device == PCI_DEVICE_ID_SUN_PBM)) {
+	    (pdev->device == PCI_DEVICE_ID_SUN_PBM ||
+	     pdev->device == PCI_DEVICE_ID_SUN_SCHIZO ||
+	     pdev->device == PCI_DEVICE_ID_SUN_SABRE ||
+	     pdev->device == PCI_DEVICE_ID_SUN_HUMMINGBIRD)) {
 		*nregs = 0;
 		return bus_prom_node;
 	}
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h
--- linux-2.4.5-pre2/arch/sparc64/kernel/pci_impl.h	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/pci_impl.h	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_impl.h,v 1.7 2001/03/28 10:56:34 davem Exp $
+/* $Id: pci_impl.h,v 1.8 2001/05/15 08:54:30 davem Exp $
  * pci_impl.h: Helper definitions for PCI controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -19,6 +19,7 @@
 extern int pci_num_controllers;
 
 /* PCI bus scanning and fixup support. */
+extern void pci_fixup_host_bridge_self(struct pci_bus *pbus);
 extern void pci_fill_in_pbm_cookies(struct pci_bus *pbus,
 				    struct pci_pbm_info *pbm,
 				    int prom_node);
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/pci_psycho.c	Mon Dec  3 22:43:16 2001
+++ linux/arch/sparc64/kernel/pci_psycho.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.23 2001/05/02 00:27:27 davem Exp $
+/* $Id: pci_psycho.c,v 1.24 2001/05/15 08:54:30 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1235,9 +1235,23 @@
 static void __init pbm_scan_bus(struct pci_controller_info *p,
 				struct pci_pbm_info *pbm)
 {
+	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+
+	if (!cookie) {
+		prom_printf("PSYCHO: Critical allocation failure.\n");
+		prom_halt();
+	}
+
+	/* All we care about is the PBM. */
+	memset(cookie, 0, sizeof(*cookie));
+	cookie->pbm = pbm;
+
 	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
 				    p->pci_ops,
 				    pbm);
+	pci_fixup_host_bridge_self(pbm->pci_bus);
+	pbm->pci_bus->self->sysdata = cookie;
+
 	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
@@ -1564,6 +1578,7 @@
 
 	p->portid = upa_portid;
 	p->index = pci_num_controllers++;
+	p->pbms_same_domain = 0;
 	p->scan_bus = psycho_scan_bus;
 	p->irq_build = psycho_irq_build;
 	p->base_address_update = psycho_base_address_update;
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/pci_sabre.c	Mon Dec  3 22:43:16 2001
+++ linux/arch/sparc64/kernel/pci_sabre.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.29 2001/05/02 00:32:56 davem Exp $
+/* $Id: pci_sabre.c,v 1.32 2001/05/15 11:10:01 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -1112,11 +1112,28 @@
 	}
 }
 
+static struct pcidev_cookie *alloc_bridge_cookie(struct pci_pbm_info *pbm)
+{
+	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+
+	if (!cookie) {
+		prom_printf("SABRE: Critical allocation failure.\n");
+		prom_halt();
+	}
+
+	/* All we care about is the PBM. */
+	memset(cookie, 0, sizeof(*cookie));
+	cookie->pbm = pbm;
+
+	return cookie;
+}
+
 static void __init sabre_scan_bus(struct pci_controller_info *p)
 {
 	static int once = 0;
 	struct pci_bus *sabre_bus;
 	struct pci_pbm_info *pbm;
+	struct pcidev_cookie *cookie;
 	struct list_head *walk;
 	int sabres_scanned;
 
@@ -1142,10 +1159,15 @@
 	}
 	once++;
 
+	cookie = alloc_bridge_cookie(&p->pbm_A);
+
 	/* The pci_bus2pbm table has already been setup in sabre_init. */
 	sabre_bus = pci_scan_bus(p->pci_first_busno,
 				 p->pci_ops,
 				 &p->pbm_A);
+	pci_fixup_host_bridge_self(sabre_bus);
+	sabre_bus->self->sysdata = cookie;
+
 	apb_init(p, sabre_bus);
 
 	sabres_scanned = 0;
@@ -1161,6 +1183,9 @@
 		} else
 			continue;
 
+		cookie = alloc_bridge_cookie(pbm);
+		pbus->self->sysdata = cookie;
+
 		sabres_scanned++;
 
 		pbus->sysdata = pbm;
@@ -1444,6 +1469,11 @@
 			memset(&pbm->pbm_intmask, 0, sizeof(pbm->pbm_intmask));
 		}
 
+
+		sprintf(pbm->name, "SABRE%d PBM%c", p->index,
+			(pbm == &p->pbm_A ? 'A' : 'B'));
+		pbm->io_space.name = pbm->mem_space.name = pbm->name;
+
 		/* Hack up top-level resources. */
 		pbm->io_space.start = p->controller_regs + SABRE_IOSPACE;
 		pbm->io_space.end   = pbm->io_space.start + (1UL << 16) - 1UL;
@@ -1512,6 +1542,7 @@
 
 	p->portid = upa_portid;
 	p->index = pci_num_controllers++;
+	p->pbms_same_domain = 1;
 	p->scan_bus = sabre_scan_bus;
 	p->irq_build = sabre_irq_build;
 	p->base_address_update = sabre_base_address_update;
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/pci_schizo.c	Mon Dec  3 22:43:16 2001
+++ linux/arch/sparc64/kernel/pci_schizo.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_schizo.c,v 1.15 2001/05/02 00:27:27 davem Exp $
+/* $Id: pci_schizo.c,v 1.16 2001/05/15 08:54:30 davem Exp $
  * pci_schizo.c: SCHIZO specific PCI controller support.
  *
  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
@@ -1328,9 +1328,23 @@
 static void __init pbm_scan_bus(struct pci_controller_info *p,
 				struct pci_pbm_info *pbm)
 {
+	struct pcidev_cookie *cookie = kmalloc(sizeof(*cookie), GFP_KERNEL);
+
+	if (!cookie) {
+		prom_printf("SCHIZO: Critical allocation failure.\n");
+		prom_halt();
+	}
+
+	/* All we care about is the PBM. */
+	memset(cookie, 0, sizeof(*cookie));
+	cookie->pbm = pbm;
+
 	pbm->pci_bus = pci_scan_bus(pbm->pci_first_busno,
 				    p->pci_ops,
 				    pbm);
+	pci_fixup_host_bridge_self(pbm->pci_bus);
+	pbm->pci_bus->self->sysdata = cookie;
+
 	pci_fill_in_pbm_cookies(pbm->pci_bus, pbm, pbm->prom_node);
 	pci_record_assignments(pbm, pbm->pci_bus);
 	pci_assign_unassigned(pbm, pbm->pci_bus);
@@ -1761,6 +1775,7 @@
 
 	p->portid = portid;
 	p->index = pci_num_controllers++;
+	p->pbms_same_domain = 0;
 	p->scan_bus = schizo_scan_bus;
 	p->irq_build = schizo_irq_build;
 	p->base_address_update = schizo_base_address_update;
diff -urN linux-2.4.5-pre2/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- linux-2.4.5-pre2/arch/sparc64/kernel/sparc64_ksyms.c	Fri Apr 13 20:15:55 2001
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.105 2001/04/14 01:12:02 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.106 2001/05/11 07:46:28 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -47,6 +47,7 @@
 #endif
 #ifdef CONFIG_PCI
 #include <asm/ebus.h>
+#include <asm/isa.h>
 #endif
 #include <asm/a.out.h>
 
@@ -199,6 +200,7 @@
 #endif
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(ebus_chain);
+EXPORT_SYMBOL(isa_chain);
 EXPORT_SYMBOL(pci_memspace_mask);
 EXPORT_SYMBOL(empty_zero_page);
 EXPORT_SYMBOL(outsb);
diff -urN linux-2.4.5-pre2/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- linux-2.4.5-pre2/arch/sparc64/mm/init.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/mm/init.c	Mon Dec  3 22:43:25 2001
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.175 2001/04/24 01:09:12 davem Exp $
+/*  $Id: init.c,v 1.176 2001/05/16 15:07:11 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -1139,8 +1139,16 @@
 	unsigned long second_alias_page = 0;
 	unsigned long pt, flags, end_pfn, pages_avail;
 	unsigned long shift = alias_base - ((unsigned long)&empty_zero_page);
+	unsigned long real_end;
 
 	set_bit(0, mmu_context_bmap);
+
+	real_end = (unsigned long)&_end;
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (sparc_ramdisk_image)
+		real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size));
+#endif
+
 	/* We assume physical memory starts at some 4mb multiple,
 	 * if this were not true we wouldn't boot up to this point
 	 * anyways.
@@ -1161,7 +1169,7 @@
 		: "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
 		  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
 		: "memory");
-		if (((unsigned long)&_end) >= KERNBASE + 0x340000) {
+		if (real_end >= KERNBASE + 0x340000) {
 			second_alias_page = alias_base + 0x400000;
 			__asm__ __volatile__(
 		"	stxa	%1, [%0] %3\n"
@@ -1189,7 +1197,7 @@
 		: "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
 		  "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (13<<3))
 		: "memory");
-		if (((unsigned long)&_end) >= KERNBASE + 0x340000) {
+		if (real_end >= KERNBASE + 0x340000) {
 			second_alias_page = alias_base + 0x400000;
 			__asm__ __volatile__(
 		"	stxa	%1, [%0] %3\n"
diff -urN linux-2.4.5-pre2/drivers/Makefile linux/drivers/Makefile
--- linux-2.4.5-pre2/drivers/Makefile	Fri Dec 29 14:07:21 2000
+++ linux/drivers/Makefile	Mon Dec  3 22:43:25 2001
@@ -9,7 +9,7 @@
 mod-subdirs :=	dio mtd sbus video macintosh usb input telephony sgi i2o ide \
 		scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi
 
-subdir-y :=	block char net parport sound misc media cdrom
+subdir-y :=	parport char block net sound misc media cdrom
 subdir-m :=	$(subdir-y)
 
 
diff -urN linux-2.4.5-pre2/drivers/atm/eni.c linux/drivers/atm/eni.c
--- linux-2.4.5-pre2/drivers/atm/eni.c	Thu Jul  6 21:37:24 2000
+++ linux/drivers/atm/eni.c	Mon Dec  3 22:43:25 2001
@@ -1796,6 +1796,7 @@
 		return -EAGAIN;
 	}
 	/* @@@ should release IRQ on error */
+	pci_set_master(eni_dev->pci_dev);
 	if ((error = pci_write_config_word(eni_dev->pci_dev,PCI_COMMAND,
 	    PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER |
 	    (eni_dev->asic ? PCI_COMMAND_PARITY | PCI_COMMAND_SERR : 0)))) {
diff -urN linux-2.4.5-pre2/drivers/block/genhd.c linux/drivers/block/genhd.c
--- linux-2.4.5-pre2/drivers/block/genhd.c	Sun Sep 17 23:16:35 2000
+++ linux/drivers/block/genhd.c	Mon Dec  3 22:43:25 2001
@@ -17,8 +17,6 @@
 #include <linux/blk.h>
 #include <linux/init.h>
 
-extern int parport_init(void);
-extern int chr_dev_init(void);
 extern int blk_dev_init(void);
 #ifdef CONFIG_BLK_DEV_DAC960
 extern void DAC960_Initialize(void);
@@ -33,10 +31,6 @@
 
 void __init device_init(void)
 {
-#ifdef CONFIG_PARPORT
-	parport_init();
-#endif
-	chr_dev_init();
 	blk_dev_init();
 	sti();
 #ifdef CONFIG_I2O
diff -urN linux-2.4.5-pre2/drivers/char/Makefile linux/drivers/char/Makefile
--- linux-2.4.5-pre2/drivers/char/Makefile	Thu Apr 26 14:11:29 2001
+++ linux/drivers/char/Makefile	Mon Dec  3 22:43:25 2001
@@ -16,7 +16,7 @@
 
 O_TARGET := char.o
 
-obj-y	 += tty_io.o n_tty.o tty_ioctl.o mem.o raw.o pty.o misc.o random.o
+obj-y	 += mem.o tty_io.o n_tty.o tty_ioctl.o raw.o pty.o misc.o random.o
 
 # All of the (potential) objects that export symbols.
 # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
diff -urN linux-2.4.5-pre2/drivers/char/agp/agpgart_fe.c linux/drivers/char/agp/agpgart_fe.c
--- linux-2.4.5-pre2/drivers/char/agp/agpgart_fe.c	Wed Apr 11 19:02:30 2001
+++ linux/drivers/char/agp/agpgart_fe.c	Mon Dec  3 22:43:25 2001
@@ -852,6 +852,9 @@
 	if (copy_from_user(&reserve, (void *) arg, sizeof(agp_region))) {
 		return -EFAULT;
 	}
+	if ((unsigned) reserve.seg_count >= ~0U/sizeof(agp_segment))
+		return -EFAULT;
+
 	client = agp_find_client_by_pid(reserve.pid);
 
 	if (reserve.seg_count == 0) {
diff -urN linux-2.4.5-pre2/drivers/char/mem.c linux/drivers/char/mem.c
--- linux-2.4.5-pre2/drivers/char/mem.c	Fri Apr 27 14:23:25 2001
+++ linux/drivers/char/mem.c	Mon Dec  3 22:43:25 2001
@@ -653,3 +653,5 @@
 #endif
 	return 0;
 }
+
+__initcall(chr_dev_init);
diff -urN linux-2.4.5-pre2/drivers/char/moxa.c linux/drivers/char/moxa.c
--- linux-2.4.5-pre2/drivers/char/moxa.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/moxa.c	Mon Dec  3 22:43:25 2001
@@ -705,14 +705,24 @@
 		return (0);
 	port = ch->port;
 	save_flags(flags);
-	cli();
 	if (from_user) {
-		copy_from_user(moxaXmitBuff, buf, count);
-		temp = moxaXmitBuff;
-	} else
-		temp = (unsigned char *) buf;
-	len = MoxaPortWriteData(port, temp, count);
-	restore_flags(flags);
+		down(&moxaBuffSem);
+		if (copy_from_user(moxaXmitBuff, buf, count)) {
+			len = -EFAULT;
+		} else {
+			cli();
+			len = MoxaPortWriteData(port, moxaXmitBuff, count);
+			restore_flags(flags);
+		}
+		up(&moxaBuffSem);
+		if (len < 0)
+			return len;
+	} else {
+		cli();
+		len = MoxaPortWriteData(port, (unsigned char *) buf, count);
+		restore_flags(flags);
+	}
+
 	/*********************************************
 	if ( !(ch->statusflags & LOWWAIT) &&
 	     ((len != count) || (MoxaPortTxFree(port) <= 100)) )
diff -urN linux-2.4.5-pre2/drivers/char/mxser.c linux/drivers/char/mxser.c
--- linux-2.4.5-pre2/drivers/char/mxser.c	Mon Dec  3 22:43:16 2001
+++ linux/drivers/char/mxser.c	Mon Dec  3 22:43:25 2001
@@ -887,29 +887,56 @@
 	if (from_user)
 		down(&mxvar_tmp_buf_sem);
 	save_flags(flags);
-	while (1) {
-		cli();
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
+	if (from_user) {
+		down(&mxvar_tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0)
+				break;
 
-		if (from_user) {
-			copy_from_user(mxvar_tmp_buf, buf, c);
+			c -= copy_from_user(mxvar_tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
+
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				    SERIAL_XMIT_SIZE - info->xmit_head));
+				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, mxvar_tmp_buf, c);
-		} else
+			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+			info->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&mxvar_tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
+
 			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
+			info->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&mxvar_tmp_buf_sem);
+
+	cli();
 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
diff -urN linux-2.4.5-pre2/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- linux-2.4.5-pre2/drivers/char/riscom8.c	Thu Jan  4 12:50:12 2001
+++ linux/drivers/char/riscom8.c	Mon Dec  3 22:43:25 2001
@@ -1217,33 +1217,58 @@
 	if (!tty || !port->xmit_buf || !tmp_buf)
 		return 0;
 
-	if (from_user)
+	save_flags(flags);
+	if (from_user) {
 		down(&tmp_buf_sem);
+		while (1) {
+			cli();		
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0)
+				break;
 
-	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
 
-		if (from_user) {
-			copy_from_user(tmp_buf, buf, c);
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
-		} else
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();		
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
+
 			memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&tmp_buf_sem);
+
+	cli();
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->IER & IER_TXRDY)) {
 		port->IER |= IER_TXRDY;
@@ -1251,6 +1276,7 @@
 		rc_out(bp, CD180_IER, port->IER);
 	}
 	restore_flags(flags);
+
 	return total;
 }
 
diff -urN linux-2.4.5-pre2/drivers/char/serial167.c linux/drivers/char/serial167.c
--- linux-2.4.5-pre2/drivers/char/serial167.c	Mon Nov 27 17:11:26 2000
+++ linux/drivers/char/serial167.c	Mon Dec  3 22:43:25 2001
@@ -1247,36 +1247,54 @@
         return 0;
     }
 
-    while (1) {
-        save_flags(flags); cli();		
-	c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-			   SERIAL_XMIT_SIZE - info->xmit_head));
-	if (c <= 0){
-	    restore_flags(flags);
-	    break;
-	}
-
-	if (from_user) {
+    if (from_user) {
 	    down(&tmp_buf_sem);
-	    if (copy_from_user(tmp_buf, buf, c)) {
-	    	up(&tmp_buf_sem);
-	        restore_flags(flags);
-		return 0;
+	    while (1) {
+		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    if (c <= 0)
+			    break;
+
+		    c -= copy_from_user(tmp_buf, buf, c);
+		    if (!c) {
+			    if (!total)
+				    total = -EFAULT;
+			    break;
+		    }
+
+		    cli();
+		    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				   SERIAL_XMIT_SIZE - info->xmit_head));
+		    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
+		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		    info->xmit_cnt += c;
+		    restore_flags(flags);
+
+		    buf += c;
+		    count -= c;
+		    total += c;
 	    }
-	    c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-		       SERIAL_XMIT_SIZE - info->xmit_head));
-	    memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
 	    up(&tmp_buf_sem);
-	} else
-	    memcpy(info->xmit_buf + info->xmit_head, buf, c);
-	info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-	info->xmit_cnt += c;
-	restore_flags(flags);
-	buf += c;
-	count -= c;
-	total += c;
-    }
+    } else {
+	    while (1) {
+		    cli();
+		    c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+				       SERIAL_XMIT_SIZE - info->xmit_head));
+		    if (c <= 0) {
+			    restore_flags(flags);
+			    break;
+		    }
+
+		    memcpy(info->xmit_buf + info->xmit_head, buf, c);
+		    info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+		    info->xmit_cnt += c;
+		    restore_flags(flags);
 
+		    buf += c;
+		    count -= c;
+		    total += c;
+	    }
+    }
 
     if (info->xmit_cnt
     && !tty->stopped
diff -urN linux-2.4.5-pre2/drivers/char/specialix.c linux/drivers/char/specialix.c
--- linux-2.4.5-pre2/drivers/char/specialix.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/specialix.c	Mon Dec  3 22:43:25 2001
@@ -1611,33 +1611,56 @@
 	if (!tty || !port->xmit_buf || !tmp_buf)
 		return 0;
 
-	if (from_user)
+	save_flags(flags);
+	if (from_user) {
 		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0)
+				break;
 
-	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-		                   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
 
-		if (from_user) {
-			copy_from_user(tmp_buf, buf, c);
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-			               SERIAL_XMIT_SIZE - port->xmit_head));
+				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
-		} else
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
 			memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&tmp_buf_sem);
+
+	cli();
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->IER & IER_TXRDY)) {
 		port->IER |= IER_TXRDY;
diff -urN linux-2.4.5-pre2/drivers/md/md.c linux/drivers/md/md.c
--- linux-2.4.5-pre2/drivers/md/md.c	Fri Apr  6 10:42:55 2001
+++ linux/drivers/md/md.c	Mon Dec  3 22:43:26 2001
@@ -2464,7 +2464,7 @@
 	int ret;
 
 	fsync_dev(mddev_to_kdev(mddev));
-	ret = md_error(mddev_to_kdev(mddev), dev);
+	ret = md_error(mddev, dev);
 	return ret;
 }
 
@@ -2938,13 +2938,11 @@
 }
 
 
-int md_error (kdev_t dev, kdev_t rdev)
+int md_error (mddev_t *mddev, kdev_t rdev)
 {
-	mddev_t *mddev;
 	mdk_rdev_t * rrdev;
 	int rc;
 
-	mddev = kdev_to_mddev(dev);
 /*	printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
  */
 	if (!mddev) {
diff -urN linux-2.4.5-pre2/drivers/md/raid1.c linux/drivers/md/raid1.c
--- linux-2.4.5-pre2/drivers/md/raid1.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/md/raid1.c	Mon Dec  3 22:43:26 2001
@@ -388,7 +388,7 @@
 	 * this branch is our 'one mirror IO has finished' event handler:
 	 */
 	if (!uptodate)
-		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);
+		md_error (r1_bh->mddev, bh->b_dev);
 	else
 		/*
 		 * Set R1BH_Uptodate in our master buffer_head, so that
@@ -832,6 +832,7 @@
 	struct mirror_info *tmp, *sdisk, *fdisk, *rdisk, *adisk;
 	mdp_super_t *sb = mddev->sb;
 	mdp_disk_t *failed_desc, *spare_desc, *added_desc;
+	mdk_rdev_t *spare_rdev, *failed_rdev;
 
 	print_raid1_conf(conf);
 	md_spin_lock_irq(&conf->device_lock);
@@ -989,6 +990,16 @@
 		/*
 		 * do the switch finally
 		 */
+		spare_rdev = find_rdev_nr(mddev, spare_desc->number);
+		failed_rdev = find_rdev_nr(mddev, failed_desc->number);
+
+		/* There must be a spare_rdev, but there may not be a
+		 * failed_rdev.  That slot might be empty...
+		 */
+		spare_rdev->desc_nr = failed_desc->number;
+		if (failed_rdev)
+			failed_rdev->desc_nr = spare_desc->number;
+		
 		xchg_values(*spare_desc, *failed_desc);
 		xchg_values(*fdisk, *sdisk);
 
@@ -1415,7 +1426,7 @@
 	 * We don't do much here, just schedule handling by raid1d
 	 */
 	if (!uptodate)
-		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);
+		md_error (r1_bh->mddev, bh->b_dev);
 	else
 		set_bit(R1BH_Uptodate, &r1_bh->state);
 	raid1_reschedule_retry(r1_bh);
@@ -1426,7 +1437,7 @@
  	struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_private);
 	
 	if (!uptodate)
- 		md_error (mddev_to_kdev(r1_bh->mddev), bh->b_dev);
+ 		md_error (r1_bh->mddev, bh->b_dev);
 	if (atomic_dec_and_test(&r1_bh->remaining)) {
 		mddev_t *mddev = r1_bh->mddev;
  		unsigned long sect = bh->b_blocknr * (bh->b_size>>9);
@@ -1437,69 +1448,6 @@
 	}
 }
 
-/*
- * This will catch the scenario in which one of the mirrors was
- * mounted as a normal device rather than as a part of a raid set.
- *
- * check_consistency is very personality-dependent, eg. RAID5 cannot
- * do this check, it uses another method.
- */
-static int __check_consistency (mddev_t *mddev, int row)
-{
-	raid1_conf_t *conf = mddev_to_conf(mddev);
-	int disks = MD_SB_DISKS;
-	kdev_t dev;
-	struct buffer_head *bh = NULL;
-	int i, rc = 0;
-	char *buffer = NULL;
-
-	for (i = 0; i < disks; i++) {
-		printk("(checking disk %d)\n",i);
-		if (!conf->mirrors[i].operational)
-			continue;
-		printk("(really checking disk %d)\n",i);
-		dev = conf->mirrors[i].dev;
-		set_blocksize(dev, 4096);
-		if ((bh = bread(dev, row / 4, 4096)) == NULL)
-			break;
-		if (!buffer) {
-			buffer = (char *) __get_free_page(GFP_KERNEL);
-			if (!buffer)
-				break;
-			memcpy(buffer, bh->b_data, 4096);
-		} else if (memcmp(buffer, bh->b_data, 4096)) {
-			rc = 1;
-			break;
-		}
-		bforget(bh);
-		fsync_dev(dev);
-		invalidate_buffers(dev);
-		bh = NULL;
-	}
-	if (buffer)
-		free_page((unsigned long) buffer);
-	if (bh) {
-		dev = bh->b_dev;
-		bforget(bh);
-		fsync_dev(dev);
-		invalidate_buffers(dev);
-	}
-	return rc;
-}
-
-static int check_consistency (mddev_t *mddev)
-{
-	if (__check_consistency(mddev, 0))
-/*
- * we do not do this currently, as it's perfectly possible to
- * have an inconsistent array when it's freshly created. Only
- * newly written data has to be consistent.
- */
-		return 0;
-
-	return 0;
-}
-
 #define INVALID_LEVEL KERN_WARNING \
 "raid1: md%d: raid level not set to mirroring (%d)\n"
 
@@ -1530,9 +1478,6 @@
 #define NONE_OPERATIONAL KERN_ERR \
 "raid1: no operational mirrors for md%d\n"
 
-#define RUNNING_CKRAID KERN_ERR \
-"raid1: detected mirror differences -- running resync\n"
-
 #define ARRAY_IS_ACTIVE KERN_INFO \
 "raid1: raid set md%d active with %d out of %d mirrors\n"
 
@@ -1714,17 +1659,6 @@
 		start_recovery = 1;
 	}
 
-	if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) {
-		/*
-		 * we do sanity checks even if the device says
-		 * it's clean ...
-		 */
-		if (check_consistency(mddev)) {
-			printk(RUNNING_CKRAID);
-			sb->state &= ~(1 << MD_SB_CLEAN);
-		}
-	}
-
 	{
 		const char * name = "raid1d";
 
@@ -1794,7 +1728,6 @@
 #undef OPERATIONAL
 #undef SPARE
 #undef NONE_OPERATIONAL
-#undef RUNNING_CKRAID
 #undef ARRAY_IS_ACTIVE
 
 static int raid1_stop_resync (mddev_t *mddev)
diff -urN linux-2.4.5-pre2/drivers/md/raid5.c linux/drivers/md/raid5.c
--- linux-2.4.5-pre2/drivers/md/raid5.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/md/raid5.c	Mon Dec  3 22:43:26 2001
@@ -156,9 +156,9 @@
 			return 1;
 		memset(bh, 0, sizeof (struct buffer_head));
 		init_waitqueue_head(&bh->b_wait);
-		page = alloc_page(priority);
-		bh->b_data = page_address(page);
-		if (!bh->b_data) {
+		if ((page = alloc_page(priority)))
+			bh->b_data = page_address(page);
+		else {
 			kfree(bh);
 			return 1;
 		}
@@ -412,7 +412,7 @@
 			spin_lock_irqsave(&conf->device_lock, flags);
 		}
 	} else {
-		md_error(mddev_to_kdev(conf->mddev), bh->b_dev);
+		md_error(conf->mddev, bh->b_dev);
 		clear_bit(BH_Uptodate, &bh->b_state);
 	}
 	clear_bit(BH_Lock, &bh->b_state);
@@ -440,7 +440,7 @@
 
 	md_spin_lock_irqsave(&conf->device_lock, flags);
 	if (!uptodate)
-		md_error(mddev_to_kdev(conf->mddev), bh->b_dev);
+		md_error(conf->mddev, bh->b_dev);
 	clear_bit(BH_Lock, &bh->b_state);
 	set_bit(STRIPE_HANDLE, &sh->state);
 	__release_stripe(conf, sh);
@@ -1256,76 +1256,6 @@
 	printk("raid5: resync finished.\n");
 }
 
-static int __check_consistency (mddev_t *mddev, int row)
-{
-	raid5_conf_t *conf = mddev->private;
-	kdev_t dev;
-	struct buffer_head *bh[MD_SB_DISKS], *tmp = NULL;
-	int i, ret = 0, nr = 0, count;
-	struct buffer_head *bh_ptr[MAX_XOR_BLOCKS];
-
-	if (conf->working_disks != conf->raid_disks)
-		goto out;
-	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-	tmp->b_size = 4096;
-	tmp->b_page = alloc_page(GFP_KERNEL);
-	tmp->b_data = page_address(tmp->b_page);
-	if (!tmp->b_data)
-		goto out;
-	md_clear_page(tmp->b_data);
-	memset(bh, 0, MD_SB_DISKS * sizeof(struct buffer_head *));
-	for (i = 0; i < conf->raid_disks; i++) {
-		dev = conf->disks[i].dev;
-		set_blocksize(dev, 4096);
-		bh[i] = bread(dev, row / 4, 4096);
-		if (!bh[i])
-			break;
-		nr++;
-	}
-	if (nr == conf->raid_disks) {
-		bh_ptr[0] = tmp;
-		count = 1;
-		for (i = 1; i < nr; i++) {
-			bh_ptr[count++] = bh[i];
-			if (count == MAX_XOR_BLOCKS) {
-				xor_block(count, &bh_ptr[0]);
-				count = 1;
-			}
-		}
-		if (count != 1) {
-			xor_block(count, &bh_ptr[0]);
-		}
-		if (memcmp(tmp->b_data, bh[0]->b_data, 4096))
-			ret = 1;
-	}
-	for (i = 0; i < conf->raid_disks; i++) {
-		dev = conf->disks[i].dev;
-		if (bh[i]) {
-			bforget(bh[i]);
-			bh[i] = NULL;
-		}
-		fsync_dev(dev);
-		invalidate_buffers(dev);
-	}
-	free_page((unsigned long) tmp->b_data);
-out:
-	if (tmp)
-		kfree(tmp);
-	return ret;
-}
-
-static int check_consistency (mddev_t *mddev)
-{
-	if (__check_consistency(mddev, 0))
-/*
- * We are not checking this currently, as it's legitimate to have
- * an inconsistent array, at creation time.
- */
-		return 0;
-
-	return 0;
-}
-
 static int raid5_run (mddev_t *mddev)
 {
 	raid5_conf_t *conf;
@@ -1485,12 +1415,6 @@
 		start_recovery = 1;
 	}
 
-	if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN)) &&
-			check_consistency(mddev)) {
-		printk(KERN_ERR "raid5: detected raid-5 superblock xor inconsistency -- running resync\n");
-		sb->state &= ~(1 << MD_SB_CLEAN);
-	}
-
 	{
 		const char * name = "raid5d";
 
@@ -1704,6 +1628,7 @@
 	struct disk_info *tmp, *sdisk, *fdisk, *rdisk, *adisk;
 	mdp_super_t *sb = mddev->sb;
 	mdp_disk_t *failed_desc, *spare_desc, *added_desc;
+	mdk_rdev_t *spare_rdev, *failed_rdev;
 
 	print_raid5_conf(conf);
 	md_spin_lock_irq(&conf->device_lock);
@@ -1875,6 +1800,16 @@
 		/*
 		 * do the switch finally
 		 */
+		spare_rdev = find_rdev_nr(mddev, spare_desc->number);
+		failed_rdev = find_rdev_nr(mddev, failed_desc->number);
+
+		/* There must be a spare_rdev, but there may not be a
+		 * failed_rdev.  That slot might be empty...
+		 */
+		spare_rdev->desc_nr = failed_desc->number;
+		if (failed_rdev)
+			failed_rdev->desc_nr = spare_desc->number;
+		
 		xchg_values(*spare_desc, *failed_desc);
 		xchg_values(*fdisk, *sdisk);
 
diff -urN linux-2.4.5-pre2/drivers/net/8390.c linux/drivers/net/8390.c
--- linux-2.4.5-pre2/drivers/net/8390.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/8390.c	Mon Dec  3 22:43:26 2001
@@ -453,6 +453,8 @@
 	{
 		if (!netif_running(dev)) {
 			printk(KERN_WARNING "%s: interrupt from stopped card\n", dev->name);
+			/* rmk - acknowledge the interrupts */
+			outb_p(interrupts, e8390_base + EN0_ISR);
 			interrupts = 0;
 			break;
 		}
diff -urN linux-2.4.5-pre2/drivers/net/Config.in linux/drivers/net/Config.in
--- linux-2.4.5-pre2/drivers/net/Config.in	Mon Dec  3 22:43:16 2001
+++ linux/drivers/net/Config.in	Mon Dec  3 22:43:26 2001
@@ -35,6 +35,9 @@
    fi
    if [ "$CONFIG_PPC" = "y" ]; then
       tristate '  MACE (Power Mac ethernet) support' CONFIG_MACE
+      if [ "$CONFIG_MACE" != "n" ]; then
+        bool '    Use AAUI port instead of TP by default' CONFIG_MACE_AAUI_PORT
+      fi
       tristate '  BMAC (G3 ethernet) support' CONFIG_BMAC
       tristate '  GMAC (G4/iBook ethernet) support' CONFIG_GMAC
       tristate '  Symbios 53c885 (Synergy ethernet) support' CONFIG_NCR885E
@@ -147,6 +150,7 @@
       dep_tristate '    EtherExpressPro/100 support' CONFIG_EEPRO100 $CONFIG_PCI
       dep_mbool '      Enable Power Management (EXPERIMENTAL)' CONFIG_EEPRO100_PM $CONFIG_EEPRO100 $CONFIG_EXPERIMENTAL
       dep_tristate '    Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL
+      dep_tristate '    Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
       dep_tristate '    National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
       dep_tristate '    PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI
       dep_tristate '    Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
diff -urN linux-2.4.5-pre2/drivers/net/Makefile linux/drivers/net/Makefile
--- linux-2.4.5-pre2/drivers/net/Makefile	Mon Dec  3 22:43:16 2001
+++ linux/drivers/net/Makefile	Mon Dec  3 22:43:26 2001
@@ -76,6 +76,7 @@
 obj-$(CONFIG_ACENIC) += acenic.o
 obj-$(CONFIG_NATSEMI) += natsemi.o
 obj-$(CONFIG_STNIC) += stnic.o 8390.o
+obj-$(CONFIG_FEALNX) += fealnx.o
 
 ifeq ($(CONFIG_SK98LIN),y)
 obj-y += sk98lin/sk98lin.o
diff -urN linux-2.4.5-pre2/drivers/net/appletalk/cops.c linux/drivers/net/appletalk/cops.c
--- linux-2.4.5-pre2/drivers/net/appletalk/cops.c	Wed Apr 18 14:40:05 2001
+++ linux/drivers/net/appletalk/cops.c	Mon Dec  3 22:43:26 2001
@@ -1,7 +1,7 @@
 /*      cops.c: LocalTalk driver for Linux.
  *
  *	Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  *
  *	With more than a little help from;
  *	- Alan Cox <Alan.Cox@linux.org> 
@@ -34,7 +34,7 @@
  */
 
 static const char *version =
-"cops.c:v0.04 6/7/98 Jay Schulist <jschlst@turbolinux.com>\n";
+"cops.c:v0.04 6/7/98 Jay Schulist <jschlst@samba.org>\n";
 /*
  *  Sources:
  *      COPS Localtalk SDK. This provides almost all of the information
diff -urN linux-2.4.5-pre2/drivers/net/appletalk/cops.h linux/drivers/net/appletalk/cops.h
--- linux-2.4.5-pre2/drivers/net/appletalk/cops.h	Fri Mar  3 12:54:44 2000
+++ linux/drivers/net/appletalk/cops.h	Mon Dec  3 22:43:26 2001
@@ -1,7 +1,7 @@
 /*      cops.h: LocalTalk driver for Linux.
  *
  *      Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  */
 
 #ifndef __LINUX_COPSLTALK_H
diff -urN linux-2.4.5-pre2/drivers/net/appletalk/cops_ffdrv.h linux/drivers/net/appletalk/cops_ffdrv.h
--- linux-2.4.5-pre2/drivers/net/appletalk/cops_ffdrv.h	Mon Dec 11 13:00:20 2000
+++ linux/drivers/net/appletalk/cops_ffdrv.h	Mon Dec  3 22:43:26 2001
@@ -21,7 +21,7 @@
 /*      cops_ffdrv.h: LocalTalk driver firmware dump for Linux.
  *
  *      Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  */
 
 #include <linux/config.h>
diff -urN linux-2.4.5-pre2/drivers/net/appletalk/cops_ltdrv.h linux/drivers/net/appletalk/cops_ltdrv.h
--- linux-2.4.5-pre2/drivers/net/appletalk/cops_ltdrv.h	Mon Dec 11 13:00:20 2000
+++ linux/drivers/net/appletalk/cops_ltdrv.h	Mon Dec  3 22:43:26 2001
@@ -20,7 +20,7 @@
 /*      cops_ltdrv.h: LocalTalk driver firmware dump for Linux.
  *
  *      Authors:
- *      - Jay Schulist <jschlst@turbolinux.com>
+ *      - Jay Schulist <jschlst@samba.org>
  */
  
 #include <linux/config.h>
diff -urN linux-2.4.5-pre2/drivers/net/appletalk/ipddp.c linux/drivers/net/appletalk/ipddp.c
--- linux-2.4.5-pre2/drivers/net/appletalk/ipddp.c	Fri Apr 13 20:26:07 2001
+++ linux/drivers/net/appletalk/ipddp.c	Mon Dec  3 22:43:26 2001
@@ -4,7 +4,7 @@
  *
  *	Authors:
  *      - DDP-IP Encap by: Bradford W. Johnson <johns393@maroon.tc.umn.edu>
- *	- DDP-IP Decap by: Jay Schulist <jschlst@turbolinux.com>
+ *	- DDP-IP Decap by: Jay Schulist <jschlst@samba.org>
  *
  *	Derived from:
  *	- Almost all code already existed in net/appletalk/ddp.c I just
@@ -14,7 +14,7 @@
  *        Written 1993-94 by Donald Becker.
  *	- dummy.c: A dummy net driver. By Nick Holloway.
  *	- MacGate: A user space Daemon for Appletalk-IP Decap for
- *	  Linux by Jay Schulist <jschlst@turbolinux.com>
+ *	  Linux by Jay Schulist <jschlst@samba.org>
  *
  *      Copyright 1993 United States Government as represented by the
  *      Director, National Security Agency.
@@ -69,7 +69,7 @@
 		printk("%s: Appletalk-IP Encap. mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n", 
 			dev->name);
 	if(ipddp_mode == IPDDP_DECAP)
-		printk("%s: Appletalk-IP Decap. mode by Jay Schulist <jschlst@turbolinux.com>\n", 
+		printk("%s: Appletalk-IP Decap. mode by Jay Schulist <jschlst@samba.org>\n", 
 			dev->name);
 
 	/* Fill in the device structure with ethernet-generic values. */
diff -urN linux-2.4.5-pre2/drivers/net/bmac.c linux/drivers/net/bmac.c
--- linux-2.4.5-pre2/drivers/net/bmac.c	Tue Feb 13 13:15:05 2001
+++ linux/drivers/net/bmac.c	Mon Dec  3 22:43:26 2001
@@ -76,9 +76,6 @@
 	struct net_device_stats stats;
 	struct timer_list tx_timeout;
 	int timeout_active;
-	int reset_and_enabled;
-	int rx_allocated;
-	int tx_allocated;
 	unsigned short hash_use_count[64];
 	unsigned short hash_table_mask[4];
 	struct net_device *next_bmac;
@@ -126,6 +123,7 @@
 };
 
 static struct net_device *bmac_devs;
+static unsigned char *bmac_emergency_rxbuf;
 
 #ifdef CONFIG_PMAC_PBOOK
 static int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
@@ -151,9 +149,9 @@
 static int bmac_transmit_packet(struct sk_buff *skb, struct net_device *dev);
 static struct net_device_stats *bmac_stats(struct net_device *dev);
 static void bmac_set_multicast(struct net_device *dev);
-static int bmac_reset_and_enable(struct net_device *dev, int enable);
+static void bmac_reset_and_enable(struct net_device *dev);
 static void bmac_start_chip(struct net_device *dev);
-static int bmac_init_chip(struct net_device *dev);
+static void bmac_init_chip(struct net_device *dev);
 static void bmac_init_registers(struct net_device *dev);
 static void bmac_reset_chip(struct net_device *dev);
 static int bmac_set_address(struct net_device *dev, void *addr);
@@ -185,17 +183,6 @@
 }
 
 static void
-dbdma_stop(volatile struct dbdma_regs *dmap)
-{
-	dbdma_st32((volatile unsigned long *)&dmap->control,
-		   DBDMA_CLEAR(RUN) | DBDMA_SET(FLUSH));
-	eieio();
-
-	while (dbdma_ld32((volatile unsigned long *)&dmap->status) & (ACTIVE|FLUSH))
-		eieio();
-}
-
-static void
 dbdma_continue(volatile struct dbdma_regs *dmap)
 {
 	dbdma_st32((volatile unsigned long *)&dmap->control,
@@ -467,12 +454,11 @@
 	}
 }
 
-static int
+static void
 bmac_init_chip(struct net_device *dev)
 {
 	bmac_init_phy(dev);
 	bmac_init_registers(dev);
-	return 1;
 }
 
 #ifdef CONFIG_PMAC_PBOOK
@@ -503,7 +489,7 @@
 		break;
 	case PBOOK_WAKE:
 		/* see if this is enough */
-		bmac_reset_and_enable(bmac_devs, 1);
+		bmac_reset_and_enable(bmac_devs);
 		enable_irq(bmac_devs->irq);
 		enable_irq(bp->tx_dma_intr);
 		enable_irq(bp->rx_dma_intr);
@@ -569,9 +555,12 @@
 }
 
 static void
-bmac_construct_rxbuff(unsigned char *addr, volatile struct dbdma_cmd *cp)
+bmac_construct_rxbuff(struct sk_buff *skb, volatile struct dbdma_cmd *cp)
 {
-	dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN, virt_to_bus(addr), 0);
+	unsigned char *addr = skb? skb->data: bmac_emergency_rxbuf;
+
+	dbdma_setcmd(cp, (INPUT_LAST | INTR_ALWAYS), RX_BUFLEN,
+		     virt_to_bus(addr), 0);
 }
 
 /* Bit-reverse one byte of an ethernet hardware address. */
@@ -586,7 +575,7 @@
 }
 
 
-static int
+static void
 bmac_init_tx_ring(struct bmac_data *bp)
 {
 	volatile struct dbdma_regs *td = bp->tx_dma;
@@ -605,9 +594,6 @@
 	dbdma_reset(td);
 	out_le32(&td->wait_sel, 0x00200020);
 	out_le32(&td->cmdptr, virt_to_bus(bp->tx_cmds));
-
-	return 1;
-
 }
 
 static int
@@ -615,22 +601,20 @@
 {
 	volatile struct dbdma_regs *rd = bp->rx_dma;
 	int i;
+	struct sk_buff *skb;
 
 	/* initialize list of sk_buffs for receiving and set up recv dma */
-	if (!bp->rx_allocated) {
-		for (i = 0; i < N_RX_RING; i++) {
-			bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
-			if (bp->rx_bufs[i] == NULL)
-				return 0;
-			skb_reserve(bp->rx_bufs[i], 2);
+	memset((char *)bp->rx_cmds, 0,
+	       (N_RX_RING + 1) * sizeof(struct dbdma_cmd));
+	for (i = 0; i < N_RX_RING; i++) {
+		if ((skb = bp->rx_bufs[i]) == NULL) {
+			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+			if (skb != NULL)
+				skb_reserve(skb, 2);
 		}
-		bp->rx_allocated = 1;
+		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
 	}
 
-	memset((char *)bp->rx_cmds, 0, (N_RX_RING+1) * sizeof(struct dbdma_cmd));
-	for (i = 0; i < N_RX_RING; i++)
-		bmac_construct_rxbuff(bp->rx_bufs[i]->data, &bp->rx_cmds[i]);
-
 	bp->rx_empty = 0;
 	bp->rx_fill = i;
 
@@ -706,27 +690,36 @@
 		cp = &bp->rx_cmds[i];
 		stat = ld_le16(&cp->xfer_status);
 		residual = ld_le16(&cp->res_count);
-		if ((stat & ACTIVE) == 0) break;
+		if ((stat & ACTIVE) == 0)
+			break;
 		nb = RX_BUFLEN - residual - 2;
 		if (nb < (ETHERMINPACKET - ETHERCRC)) {
 			skb = NULL;
 			bp->stats.rx_length_errors++;
 			bp->stats.rx_errors++;
-		} else skb =  bp->rx_bufs[i];
+		} else {
+			skb = bp->rx_bufs[i];
+			bp->rx_bufs[i] = NULL;
+		}
 		if (skb != NULL) {
 			nb -= ETHERCRC;
 			skb_put(skb, nb);
 			skb->dev = dev;
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
-			bp->rx_bufs[i] = dev_alloc_skb(RX_BUFLEN+2);
-			skb_reserve(bp->rx_bufs[i], 2);
-			bmac_construct_rxbuff(bp->rx_bufs[i]->data, &bp->rx_cmds[i]);
+			dev->last_rx = jiffies;
 			++bp->stats.rx_packets;
 			bp->stats.rx_bytes += nb;
 		} else {
 			++bp->stats.rx_dropped;
 		}
+		dev->last_rx = jiffies;
+		if ((skb = bp->rx_bufs[i]) == NULL) {
+			bp->rx_bufs[i] = skb = dev_alloc_skb(RX_BUFLEN+2);
+			if (skb != NULL)
+				skb_reserve(bp->rx_bufs[i], 2);
+		}
+		bmac_construct_rxbuff(skb, &bp->rx_cmds[i]);
 		st_le16(&cp->res_count, 0);
 		st_le16(&cp->xfer_status, 0);
 		last = i;
@@ -772,7 +765,13 @@
 		if (txintcount < 10) {
 			XXDEBUG(("bmac_txdma_xfer_stat=%#0x\n", stat));
 		}
-		if (!(stat & ACTIVE)) break;
+		if (!(stat & ACTIVE)) {
+			/*
+			 * status field might not have been filled by DBDMA
+			 */
+			if (cp == bus_to_virt(in_le32(&bp->tx_dma->cmdptr)))
+				break;
+		}
 
 		if (bp->tx_bufs[bp->tx_empty]) {
 			++bp->stats.tx_packets;
@@ -1215,7 +1214,7 @@
 		}
 }
 
-static int bmac_reset_and_enable(struct net_device *dev, int enable)
+static void bmac_reset_and_enable(struct net_device *dev)
 {
 	struct bmac_data *bp = dev->priv;
 	unsigned long flags;
@@ -1223,22 +1222,19 @@
 	unsigned char *data;
 
 	save_flags(flags); cli();
-	bp->reset_and_enabled = 0;
 	bmac_reset_chip(dev);
-	if (enable) {
-		if (!bmac_init_tx_ring(bp) || !bmac_init_rx_ring(bp))
-			return 0;
-		if (!bmac_init_chip(dev))
-			return 0;
-		bmac_start_chip(dev);
-		bmwrite(dev, INTDISABLE, EnableNormal);
-		bp->reset_and_enabled = 1;
-
-		/*
-		 * It seems that the bmac can't receive until it's transmitted
-		 * a packet.  So we give it a dummy packet to transmit.
-		 */
-		skb = dev_alloc_skb(ETHERMINPACKET);
+	bmac_init_tx_ring(bp);
+	bmac_init_rx_ring(bp);
+	bmac_init_chip(dev);
+	bmac_start_chip(dev);
+	bmwrite(dev, INTDISABLE, EnableNormal);
+
+	/*
+	 * It seems that the bmac can't receive until it's transmitted
+	 * a packet.  So we give it a dummy packet to transmit.
+	 */
+	skb = dev_alloc_skb(ETHERMINPACKET);
+	if (skb != NULL) {
 		data = skb_put(skb, ETHERMINPACKET);
 		memset(data, 0, ETHERMINPACKET);
 		memcpy(data, dev->dev_addr, 6);
@@ -1246,13 +1242,14 @@
 		bmac_transmit_packet(skb, dev);
 	}
 	restore_flags(flags);
-	return 1;
 }
 
 static int __init bmac_probe(void)
 {
 	struct device_node *bmac;
 
+	MOD_INC_USE_COUNT;
+
 	for (bmac = find_devices("bmac"); bmac != 0; bmac = bmac->next)
 		bmac_probe1(bmac, 0);
 	for (bmac = find_compatible_devices("network", "bmac+"); bmac != 0;
@@ -1265,7 +1262,10 @@
 		pmu_register_sleep_notifier(&bmac_sleep_notifier);
 #endif
 	}
-	return 0;
+
+	MOD_DEC_USE_COUNT;
+
+	return bmac_devs? 0: -ENODEV;
 }
 
 static void __init bmac_probe1(struct device_node *bmac, int is_bmac_plus)
@@ -1290,6 +1290,14 @@
 		}
 	}
 
+	if (bmac_emergency_rxbuf == NULL) {
+		bmac_emergency_rxbuf = kmalloc(RX_BUFLEN, GFP_KERNEL);
+		if (bmac_emergency_rxbuf == NULL) {
+			printk(KERN_ERR "BMAC: can't allocate emergency RX buffer\n");
+			return;
+		}
+	}
+
 	dev = init_etherdev(NULL, PRIV_BYTES);
 	if (!dev) {
 		printk(KERN_ERR "init_etherdev failed, out of memory for BMAC %s\n",
@@ -1390,9 +1398,7 @@
 {
 	/* XXDEBUG(("bmac: enter open\n")); */
 	/* reset the chip */
-	if (!bmac_reset_and_enable(dev, 1))
-		return -ENOMEM;
-
+	bmac_reset_and_enable(dev);
 	dev->flags |= IFF_RUNNING;
 	return 0;
 }
@@ -1428,7 +1434,6 @@
 			bp->rx_bufs[i] = NULL;
 		}
 	}
-	bp->rx_allocated = 0;
 	XXDEBUG(("bmac: free tx bufs\n"));
 	for (i = 0; i<N_TX_RING; i++) {
 		if (bp->tx_bufs[i] != NULL) {
@@ -1436,7 +1441,6 @@
 			bp->tx_bufs[i] = NULL;
 		}
 	}
-	bp->reset_and_enabled = 0;
 	XXDEBUG(("bmac: all bufs freed\n"));
 
 	return 0;
@@ -1607,6 +1611,11 @@
 {
 	struct bmac_data *bp;
 	struct net_device *dev;
+
+	if (bmac_emergency_rxbuf != NULL) {
+		kfree(bmac_emergency_rxbuf);
+		bmac_emergency_rxbuf = NULL;
+	}
 
 	if (bmac_devs == 0)
 		return;
diff -urN linux-2.4.5-pre2/drivers/net/fealnx.c linux/drivers/net/fealnx.c
--- linux-2.4.5-pre2/drivers/net/fealnx.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/fealnx.c	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,1777 @@
+/*
+	Written 1998-2000 by Donald Becker.
+
+	This software may be used and distributed according to the terms of
+	the GNU General Public License (GPL), incorporated herein by reference.
+	Drivers based on or derived from this code fall under the GPL and must
+	retain the authorship, copyright and license notice.  This file is not
+	a complete program and may only be used when the entire operating
+	system is licensed under the GPL.
+
+	The author may be reached as becker@scyld.com, or C/O
+	Scyld Computing Corporation
+	410 Severn Ave., Suite 210
+	Annapolis MD 21403
+
+	Support information and updates available at
+	http://www.scyld.com/network/pci-skeleton.html
+*/
+
+static int debug = 0;		/* 1-> print debug message */
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). */
+static int multicast_filter_limit = 32;
+
+/* Set the copy breakpoint for the copy-only-tiny-frames scheme. */
+/* Setting to > 1518 effectively disables this feature.          */
+static int rx_copybreak = 0;
+
+/* Used to pass the media type, etc.                            */
+/* Both 'options[]' and 'full_duplex[]' should exist for driver */
+/* interoperability.                                            */
+/* The media type is usually passed in 'options[]'.             */
+#define MAX_UNITS 8		/* More are supported, limit only on options */
+static int options[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
+
+/* Operational parameters that are set at compile time.                 */
+/* Keep the ring sizes a power of two for compile efficiency.           */
+/* The compiler will convert <unsigned>'%'<2^N> into a bit mask.        */
+/* Making the Tx ring too large decreases the effectiveness of channel  */
+/* bonding and packet priority.                                         */
+/* There are no ill effects from too-large receive rings.               */
+// 88-12-9 modify,
+// #define TX_RING_SIZE    16
+// #define RX_RING_SIZE    32
+#define TX_RING_SIZE    6
+#define RX_RING_SIZE    12
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT      (2*HZ)
+
+#define PKT_BUF_SZ      1536	/* Size of each temporary Rx buffer. */
+
+
+/* Include files, designed to support most kernel versions 2.0.0 and later. */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <asm/processor.h>	/* Processor type for cache alignment. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+/* These identify the driver base version and may not be removed. */
+static char version[] __devinitdata =
+KERN_INFO "fealnx.c:v2.50 1/17/2001\n";
+
+
+/* This driver was written to use PCI memory space, however some x86 systems
+   work only with I/O space accesses. */
+#ifndef __alpha__
+#define USE_IO_OPS
+#endif
+
+#ifdef USE_IO_OPS
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+#define readb inb
+#define readw inw
+#define readl inl
+#define writeb outb
+#define writew outw
+#define writel outl
+#endif
+
+/* Kernel compatibility defines, some common to David Hinds' PCMCIA package. */
+/* This is only in the support-all-kernels source code. */
+
+#define RUN_AT(x) (jiffies + (x))
+
+MODULE_AUTHOR("Myson or whoever");
+MODULE_DESCRIPTION("Myson MTD-8xx 100/10M Ethernet PCI Adapter Driver");
+MODULE_PARM(max_interrupt_work, "i");
+MODULE_PARM(min_pci_latency, "i");
+MODULE_PARM(debug, "i");
+MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM(multicast_filter_limit, "i");
+MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
+MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
+
+#define MIN_REGION_SIZE 136
+
+enum pci_flags_bit {
+	PCI_USES_IO = 1,
+	PCI_USES_MEM = 2,
+	PCI_USES_MASTER = 4,
+	PCI_ADDR0 = 0x10 << 0,
+	PCI_ADDR1 = 0x10 << 1,
+	PCI_ADDR2 = 0x10 << 2,
+	PCI_ADDR3 = 0x10 << 3,
+};
+
+/* A chip capabilities table, matching the entries in pci_tbl[] above. */
+enum chip_capability_flags {
+	HAS_MII_XCVR,
+	HAS_CHIP_XCVR,
+};
+
+/* 89/6/13 add, */
+/* for different PHY */
+enum phy_type_flags {
+	MysonPHY = 1,
+	AhdocPHY = 2,
+	SeeqPHY = 3,
+	MarvellPHY = 4,
+	Myson981 = 5,
+	LevelOnePHY = 6,
+	OtherPHY = 10,
+};
+
+struct chip_info {
+	char *chip_name;
+	int io_size;
+	int flags;
+};
+
+static struct chip_info skel_netdrv_tbl[] = {
+	{"100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
+	{"100/10M Ethernet PCI Adapter", 136, HAS_CHIP_XCVR},
+	{"1000/100/10M Ethernet PCI Adapter", 136, HAS_MII_XCVR},
+};
+
+/* Offsets to the Command and Status Registers. */
+enum fealnx_offsets {
+	PAR0 = 0x0,		/* physical address 0-3 */
+	PAR1 = 0x04,		/* physical address 4-5 */
+	MAR0 = 0x08,		/* multicast address 0-3 */
+	MAR1 = 0x0C,		/* multicast address 4-7 */
+	FAR0 = 0x10,		/* flow-control address 0-3 */
+	FAR1 = 0x14,		/* flow-control address 4-5 */
+	TCRRCR = 0x18,		/* receive & transmit configuration */
+	BCR = 0x1C,		/* bus command */
+	TXPDR = 0x20,		/* transmit polling demand */
+	RXPDR = 0x24,		/* receive polling demand */
+	RXCWP = 0x28,		/* receive current word pointer */
+	TXLBA = 0x2C,		/* transmit list base address */
+	RXLBA = 0x30,		/* receive list base address */
+	ISR = 0x34,		/* interrupt status */
+	IMR = 0x38,		/* interrupt mask */
+	FTH = 0x3C,		/* flow control high/low threshold */
+	MANAGEMENT = 0x40,	/* bootrom/eeprom and mii management */
+	TALLY = 0x44,		/* tally counters for crc and mpa */
+	TSR = 0x48,		/* tally counter for transmit status */
+	BMCRSR = 0x4c,		/* basic mode control and status */
+	PHYIDENTIFIER = 0x50,	/* phy identifier */
+	ANARANLPAR = 0x54,	/* auto-negotiation advertisement and link
+				   partner ability */
+	ANEROCR = 0x58,		/* auto-negotiation expansion and pci conf. */
+	BPREMRPSR = 0x5c,	/* bypass & receive error mask and phy status */
+};
+
+/* Bits in the interrupt status/enable registers. */
+/* The bits in the Intr Status/Enable registers, mostly interrupt sources. */
+enum intr_status_bits {
+	RFCON = 0x00020000,	/* receive flow control xon packet */
+	RFCOFF = 0x00010000,	/* receive flow control xoff packet */
+	LSCStatus = 0x00008000,	/* link status change */
+	ANCStatus = 0x00004000,	/* autonegotiation completed */
+	FBE = 0x00002000,	/* fatal bus error */
+	FBEMask = 0x00001800,	/* mask bit12-11 */
+	ParityErr = 0x00000000,	/* parity error */
+	TargetErr = 0x00001000,	/* target abort */
+	MasterErr = 0x00000800,	/* master error */
+	TUNF = 0x00000400,	/* transmit underflow */
+	ROVF = 0x00000200,	/* receive overflow */
+	ETI = 0x00000100,	/* transmit early int */
+	ERI = 0x00000080,	/* receive early int */
+	CNTOVF = 0x00000040,	/* counter overflow */
+	RBU = 0x00000020,	/* receive buffer unavailable */
+	TBU = 0x00000010,	/* transmit buffer unavilable */
+	TI = 0x00000008,	/* transmit interrupt */
+	RI = 0x00000004,	/* receive interrupt */
+	RxErr = 0x00000002,	/* receive error */
+};
+
+/* Bits in the NetworkConfig register. */
+enum rx_mode_bits {
+	RxModeMask = 0xe0,
+	PROM = 0x80,		/* promiscuous mode */
+	AB = 0x40,		/* accept broadcast */
+	AM = 0x20,		/* accept mutlicast */
+	ARP = 0x08,		/* receive runt pkt */
+	ALP = 0x04,		/* receive long pkt */
+	SEP = 0x02,		/* receive error pkt */
+};
+
+/* The Tulip Rx and Tx buffer descriptors. */
+struct fealnx_desc {
+	s32 status;
+	s32 control;
+	u32 buffer;
+	u32 next_desc;
+	struct fealnx_desc *next_desc_logical;
+	struct sk_buff *skbuff;
+	u32 reserved1;
+	u32 reserved2;
+};
+
+/* Bits in network_desc.status */
+enum rx_desc_status_bits {
+	RXOWN = 0x80000000,	/* own bit */
+	FLNGMASK = 0x0fff0000,	/* frame length */
+	FLNGShift = 16,
+	MARSTATUS = 0x00004000,	/* multicast address received */
+	BARSTATUS = 0x00002000,	/* broadcast address received */
+	PHYSTATUS = 0x00001000,	/* physical address received */
+	RXFSD = 0x00000800,	/* first descriptor */
+	RXLSD = 0x00000400,	/* last descriptor */
+	ErrorSummary = 0x80,	/* error summary */
+	RUNT = 0x40,		/* runt packet received */
+	LONG = 0x20,		/* long packet received */
+	FAE = 0x10,		/* frame align error */
+	CRC = 0x08,		/* crc error */
+	RXER = 0x04,		/* receive error */
+};
+
+enum rx_desc_control_bits {
+	RXIC = 0x00800000,	/* interrupt control */
+	RBSShift = 0,
+};
+
+enum tx_desc_status_bits {
+	TXOWN = 0x80000000,	/* own bit */
+	JABTO = 0x00004000,	/* jabber timeout */
+	CSL = 0x00002000,	/* carrier sense lost */
+	LC = 0x00001000,	/* late collision */
+	EC = 0x00000800,	/* excessive collision */
+	UDF = 0x00000400,	/* fifo underflow */
+	DFR = 0x00000200,	/* deferred */
+	HF = 0x00000100,	/* heartbeat fail */
+	NCRMask = 0x000000ff,	/* collision retry count */
+	NCRShift = 0,
+};
+
+enum tx_desc_control_bits {
+	TXIC = 0x80000000,	/* interrupt control */
+	ETIControl = 0x40000000,	/* early transmit interrupt */
+	TXLD = 0x20000000,	/* last descriptor */
+	TXFD = 0x10000000,	/* first descriptor */
+	CRCEnable = 0x08000000,	/* crc control */
+	PADEnable = 0x04000000,	/* padding control */
+	RetryTxLC = 0x02000000,	/* retry late collision */
+	PKTSMask = 0x3ff800,	/* packet size bit21-11 */
+	PKTSShift = 11,
+	TBSMask = 0x000007ff,	/* transmit buffer bit 10-0 */
+	TBSShift = 0,
+};
+
+/* BootROM/EEPROM/MII Management Register */
+#define MASK_MIIR_MII_READ       0x00000000
+#define MASK_MIIR_MII_WRITE      0x00000008
+#define MASK_MIIR_MII_MDO        0x00000004
+#define MASK_MIIR_MII_MDI        0x00000002
+#define MASK_MIIR_MII_MDC        0x00000001
+
+/* ST+OP+PHYAD+REGAD+TA */
+#define OP_READ             0x6000	/* ST:01+OP:10+PHYAD+REGAD+TA:Z0 */
+#define OP_WRITE            0x5002	/* ST:01+OP:01+PHYAD+REGAD+TA:10 */
+
+/* ------------------------------------------------------------------------- */
+/*      Constants for Myson PHY                                              */
+/* ------------------------------------------------------------------------- */
+#define MysonPHYID      0xd0000302
+/* 89-7-27 add, (begin) */
+#define MysonPHYID0     0x0302
+#define StatusRegister  18
+#define SPEED100        0x0400	// bit10
+#define FULLMODE        0x0800	// bit11
+/* 89-7-27 add, (end) */
+
+/* ------------------------------------------------------------------------- */
+/*      Constants for Seeq 80225 PHY                                         */
+/* ------------------------------------------------------------------------- */
+#define SeeqPHYID0      0x0016
+
+#define MIIRegister18   18
+#define SPD_DET_100     0x80
+#define DPLX_DET_FULL   0x40
+
+/* ------------------------------------------------------------------------- */
+/*      Constants for Ahdoc 101 PHY                                          */
+/* ------------------------------------------------------------------------- */
+#define AhdocPHYID0     0x0022
+
+#define DiagnosticReg   18
+#define DPLX_FULL       0x0800
+#define Speed_100       0x0400
+
+/* 89/6/13 add, */
+/* -------------------------------------------------------------------------- */
+/*      Constants                                                             */
+/* -------------------------------------------------------------------------- */
+#define MarvellPHYID0           0x0141
+#define LevelOnePHYID0		0x0013
+
+#define MII1000BaseTControlReg  9
+#define MII1000BaseTStatusReg   10
+#define SpecificReg		17
+
+/* for 1000BaseT Control Register */
+#define PHYAbletoPerform1000FullDuplex  0x0200
+#define PHYAbletoPerform1000HalfDuplex  0x0100
+#define PHY1000AbilityMask              0x300
+
+// for phy specific status register, marvell phy.
+#define SpeedMask       0x0c000
+#define Speed_1000M     0x08000
+#define Speed_100M      0x4000
+#define Speed_10M       0
+#define Full_Duplex     0x2000
+
+// 89/12/29 add, for phy specific status register, levelone phy, (begin)
+#define LXT1000_100M    0x08000
+#define LXT1000_1000M   0x0c000
+#define LXT1000_Full    0x200
+// 89/12/29 add, for phy specific status register, levelone phy, (end)
+
+/* for 3-in-1 case */
+#define PS10            0x00080000
+#define FD              0x00100000
+#define PS1000          0x00010000
+#define LinkIsUp2	0x00040000
+
+/* for PHY */
+#define LinkIsUp        0x0004
+
+
+struct netdev_private {
+	/* Descriptor rings first for alignment. */
+	struct fealnx_desc rx_ring[RX_RING_SIZE];
+	struct fealnx_desc tx_ring[TX_RING_SIZE];
+
+	struct net_device_stats stats;
+
+	/* Media monitoring timer. */
+	struct timer_list timer;
+
+	/* Frequently used values: keep some adjacent for cache effect. */
+	int flags;
+	struct pci_dev *pci_dev;
+	unsigned long crvalue;
+	unsigned long bcrvalue;
+	unsigned long imrvalue;
+	struct fealnx_desc *cur_rx;
+	struct fealnx_desc *lack_rxbuf;
+	int really_rx_count;
+	struct fealnx_desc *cur_tx;
+	struct fealnx_desc *cur_tx_copy;
+	int really_tx_count;
+	int free_tx_count;
+	unsigned int rx_buf_sz;	/* Based on MTU+slack. */
+
+	/* These values are keep track of the transceiver/media in use. */
+	unsigned int linkok;
+	unsigned int line_speed;
+	unsigned int duplexmode;
+	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
+	unsigned int duplex_lock:1;
+	unsigned int medialock:1;	/* Do not sense media. */
+	unsigned int default_port:4;	/* Last dev->if_port value. */
+	unsigned int PHYType;
+
+	/* MII transceiver section. */
+	int mii_cnt;		/* MII device addresses. */
+	unsigned char phys[2];	/* MII device addresses. */
+};
+
+
+static unsigned int mdio_read(struct net_device *dev, int phy_id, int location);
+static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
+static int netdev_open(struct net_device *dev);
+static void getlinktype(struct net_device *dev);
+static void getlinkstatus(struct net_device *dev);
+static void netdev_timer(unsigned long data);
+static void tx_timeout(struct net_device *dev);
+static void init_ring(struct net_device *dev);
+static int start_tx(struct sk_buff *skb, struct net_device *dev);
+static void intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static int netdev_rx(struct net_device *dev);
+static inline unsigned ether_crc(int length, unsigned char *data);
+static void set_rx_mode(struct net_device *dev);
+static struct net_device_stats *get_stats(struct net_device *dev);
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int netdev_close(struct net_device *dev);
+
+
+void stop_nic_tx(long ioaddr, long crvalue)
+{
+	writel(crvalue & (~0x40000), ioaddr + TCRRCR);
+
+	/* wait for tx stop */
+	{
+		int i = 0, delay = 0x1000;
+
+		while ((!(readl(ioaddr + TCRRCR) & 0x04000000)) && (i < delay)) {
+			++i;
+		}
+	}
+}
+
+
+void stop_nic_rx(long ioaddr, long crvalue)
+{
+	writel(crvalue & (~0x1), ioaddr + TCRRCR);
+
+	/* wait for rx stop */
+	{
+		int i = 0, delay = 0x1000;
+
+		while ((!(readl(ioaddr + TCRRCR) & 0x00008000)) && (i < delay)) {
+			++i;
+		}
+	}
+}
+
+
+
+static int __devinit fealnx_init_one(struct pci_dev *pdev,
+				     const struct pci_device_id *ent)
+{
+	struct netdev_private *np;
+	int i, option, err, irq;
+	static int card_idx = -1;
+	char boardname[12];
+	long ioaddr;
+	unsigned int chip_id = ent->driver_data;
+	struct net_device *dev;
+	
+/* when built into the kernel, we only print version if device is found */
+#ifndef MODULE
+	static int printed_version;
+	if (!printed_version++)
+		printk (version);
+#endif
+	
+	card_idx++;
+	sprintf(boardname, "fealnx%d", card_idx);
+	
+	option = card_idx < MAX_UNITS ? options[card_idx] : 0;
+
+	i = pci_enable_device(pdev);
+	if (i) return i;
+	pci_set_master(pdev);
+	
+#ifdef USE_IO_OPS
+	ioaddr = pci_resource_len(pdev, 0);
+#else
+	ioaddr = pci_resource_len(pdev, 1);
+#endif
+	if (ioaddr < MIN_REGION_SIZE) {
+		printk(KERN_ERR "%s: region size %ld too small, aborting\n",
+		       boardname, ioaddr);
+		return -ENODEV;
+	}
+
+	i = pci_request_regions(pdev, boardname);
+	if (i) return i;
+	
+	irq = pdev->irq;
+
+#ifdef USE_IO_OPS
+	ioaddr = pci_resource_start(pdev, 0);
+#else
+	ioaddr = (long) ioremap(pci_resource_start(pdev, 1),
+				pci_resource_len(pdev, 1));
+	if (!ioaddr) {
+		err = -ENOMEM;
+		goto err_out_res;
+	}
+#endif
+	
+	dev = alloc_etherdev(sizeof(struct netdev_private));
+	if (!dev) {
+		err = -ENOMEM;
+		goto err_out_unmap;
+	}
+	SET_MODULE_OWNER(dev);
+
+	/* read ethernet id */
+	for (i = 0; i < 6; ++i)
+		dev->dev_addr[i] = readb(ioaddr + PAR0 + i);
+
+	/* Reset the chip to erase previous misconfiguration. */
+	writel(0x00000001, ioaddr + BCR);
+
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+
+	/* Make certain the descriptor lists are aligned. */
+	np = dev->priv;
+	np->pci_dev = pdev;
+	np->flags = skel_netdrv_tbl[chip_id].flags;
+	pci_set_drvdata(pdev, dev);
+
+	/* find the connected MII xcvrs */
+	if (np->flags == HAS_MII_XCVR) {
+		int phy, phy_idx = 0;
+
+		for (phy = 1; phy < 32 && phy_idx < 4; phy++) {
+			int mii_status = mdio_read(dev, phy, 1);
+
+			if (mii_status != 0xffff && mii_status != 0x0000) {
+				np->phys[phy_idx++] = phy;
+				printk(KERN_INFO
+				       "%s: MII PHY found at address %d, status "
+				       "0x%4.4x.\n", dev->name, phy, mii_status);
+				/* get phy type */
+				{
+					unsigned int data;
+
+					data = mdio_read(dev, np->phys[0], 2);
+					if (data == SeeqPHYID0)
+						np->PHYType = SeeqPHY;
+					else if (data == AhdocPHYID0)
+						np->PHYType = AhdocPHY;
+					else if (data == MarvellPHYID0)
+						np->PHYType = MarvellPHY;
+					else if (data == MysonPHYID0)
+						np->PHYType = Myson981;
+					else if (data == LevelOnePHYID0)
+						np->PHYType = LevelOnePHY;
+					else
+						np->PHYType = OtherPHY;
+				}
+			}
+		}
+
+		np->mii_cnt = phy_idx;
+		if (phy_idx == 0) {
+			printk(KERN_WARNING "%s: MII PHY not found -- this device may "
+			       "not operate correctly.\n", dev->name);
+		}
+	} else {
+		np->phys[0] = 32;
+/* 89/6/23 add, (begin) */
+		/* get phy type */
+		if (readl(dev->base_addr + PHYIDENTIFIER) == MysonPHYID)
+			np->PHYType = MysonPHY;
+		else
+			np->PHYType = OtherPHY;
+	}
+
+	if (dev->mem_start)
+		option = dev->mem_start;
+
+	/* The lower four bits are the media type. */
+	if (option > 0) {
+		if (option & 0x200)
+			np->full_duplex = 1;
+		np->default_port = option & 15;
+
+		if (np->default_port)
+			np->medialock = 1;
+	}
+
+	if (card_idx < MAX_UNITS && full_duplex[card_idx] > 0)
+		np->full_duplex = full_duplex[card_idx];
+
+	if (np->full_duplex) {
+		printk(KERN_INFO "%s: Media type forced to Full Duplex.\n", dev->name);
+/* 89/6/13 add, (begin) */
+//      if (np->PHYType==MarvellPHY)
+		if ((np->PHYType == MarvellPHY) || (np->PHYType == LevelOnePHY)) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], 9);
+			data = (data & 0xfcff) | 0x0200;
+			mdio_write(dev, np->phys[0], 9, data);
+		}
+/* 89/6/13 add, (end) */
+		if (np->flags == HAS_MII_XCVR)
+			mdio_write(dev, np->phys[0], 4, 0x141);
+		else
+			writel(0x141, dev->base_addr + ANARANLPAR);
+		np->duplex_lock = 1;
+	}
+
+	/* The chip-specific entries in the device structure. */
+	dev->open = &netdev_open;
+	dev->hard_start_xmit = &start_tx;
+	dev->stop = &netdev_close;
+	dev->get_stats = &get_stats;
+	dev->set_multicast_list = &set_rx_mode;
+	dev->do_ioctl = &mii_ioctl;
+	dev->tx_timeout = tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+	
+	err = register_netdev(dev);
+	if (err)
+		goto err_out_free;
+
+	printk(KERN_INFO "%s: %s at 0x%lx, ",
+	       dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
+	for (i = 0; i < 5; i++)
+		printk("%2.2x:", dev->dev_addr[i]);
+	printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
+
+	return 0;
+
+err_out_free:
+	kfree(dev);
+err_out_unmap:
+#ifndef USE_IO_OPS
+	iounmap((void *)ioaddr);
+err_out_res:
+#endif
+	pci_release_regions(pdev);
+	return err;
+}
+
+static void __devexit fealnx_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+	if (dev) {
+		unregister_netdev(dev);
+#ifndef USE_IO_OPS
+		iounmap((void *)dev->base_addr);
+#endif
+		kfree(dev);
+		pci_release_regions(pdev);
+		pci_set_drvdata(pdev, NULL);
+	} else
+		printk(KERN_ERR "fealnx: remove for unknown device\n");
+}
+
+unsigned int m80x_read_tick(void)
+/* function: Reads the Timer tick count register which decrements by 2 from  */
+/*           65536 to 0 every 1/36.414 of a second. Each 2 decrements of the *//*           count represents 838 nsec's.                                    */
+/* input   : none.                                                           */
+/* output  : none.                                                           */
+{
+	unsigned char tmp;
+	int value;
+
+	writeb((char) 0x06, 0x43);	// Command 8254 to latch T0's count
+
+	// now read the count.
+	tmp = (unsigned char) readb(0x40);
+	value = ((int) tmp) << 8;
+	tmp = (unsigned char) readb(0x40);
+	value |= (((int) tmp) & 0xff);
+	return (value);
+}
+
+
+void m80x_delay(unsigned int interval)
+/* function: to wait for a specified time.                                   */
+/* input   : interval ... the specified time.                                */
+/* output  : none.                                                           */
+{
+	unsigned int interval1, interval2, i = 0;
+
+	interval1 = m80x_read_tick();	// get initial value
+	do {
+		interval2 = m80x_read_tick();
+		if (interval1 < interval2)
+			interval1 = interval2;
+		++i;
+	} while (((interval1 - interval2) < (ushort) interval) && (i < 65535));
+}
+
+
+static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
+{
+	ulong miir;
+	int i;
+	unsigned int mask, data;
+
+	/* enable MII output */
+	miir = (ulong) readl(miiport);
+	miir &= 0xfffffff0;
+
+	miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
+
+	/* send 32 1's preamble */
+	for (i = 0; i < 32; i++) {
+		/* low MDC; MDO is already high (miir) */
+		miir &= ~MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+
+		/* high MDC */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+	}
+
+	/* calculate ST+OP+PHYAD+REGAD+TA */
+	data = opcode | (phyad << 7) | (regad << 2);
+
+	/* sent out */
+	mask = 0x8000;
+	while (mask) {
+		/* low MDC, prepare MDO */
+		miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
+		if (mask & data)
+			miir |= MASK_MIIR_MII_MDO;
+
+		writel(miir, miiport);
+		/* high MDC */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+		m80x_delay(30);
+
+		/* next */
+		mask >>= 1;
+		if (mask == 0x2 && opcode == OP_READ)
+			miir &= ~MASK_MIIR_MII_WRITE;
+	}
+	return miir;
+}
+
+
+static unsigned int mdio_read(struct net_device *dev, int phyad, int regad)
+{
+	long miiport = dev->base_addr + MANAGEMENT;
+	ulong miir;
+	unsigned int mask, data;
+
+	miir = m80x_send_cmd_to_phy(miiport, OP_READ, phyad, regad);
+
+	/* read data */
+	mask = 0x8000;
+	data = 0;
+	while (mask) {
+		/* low MDC */
+		miir &= ~MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+
+		/* read MDI */
+		miir = readl(miiport);
+		if (miir & MASK_MIIR_MII_MDI)
+			data |= mask;
+
+		/* high MDC, and wait */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+		m80x_delay((int) 30);
+
+		/* next */
+		mask >>= 1;
+	}
+
+	/* low MDC */
+	miir &= ~MASK_MIIR_MII_MDC;
+	writel(miir, miiport);
+
+	return data;
+}
+
+
+static void mdio_write(struct net_device *dev, int phyad, int regad, int data)
+{
+	long miiport = dev->base_addr + MANAGEMENT;
+	ulong miir;
+	unsigned int mask;
+
+	miir = m80x_send_cmd_to_phy(miiport, OP_WRITE, phyad, regad);
+
+	/* write data */
+	mask = 0x8000;
+	while (mask) {
+		/* low MDC, prepare MDO */
+		miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
+		if (mask & data)
+			miir |= MASK_MIIR_MII_MDO;
+		writel(miir, miiport);
+
+		/* high MDC */
+		miir |= MASK_MIIR_MII_MDC;
+		writel(miir, miiport);
+
+		/* next */
+		mask >>= 1;
+	}
+
+	/* low MDC */
+	miir &= ~MASK_MIIR_MII_MDC;
+	writel(miir, miiport);
+
+	return;
+}
+
+
+static int netdev_open(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+
+	writel(0x00000001, ioaddr + BCR);	/* Reset */
+
+	if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))
+		return -EAGAIN;
+
+	init_ring(dev);
+
+	writel(virt_to_bus(np->rx_ring), ioaddr + RXLBA);
+	writel(virt_to_bus(np->tx_ring), ioaddr + TXLBA);
+
+	/* Initialize other registers. */
+	/* Configure the PCI bus bursts and FIFO thresholds.
+	   486: Set 8 longword burst.
+	   586: no burst limit.
+	   Burst length 5:3
+	   0 0 0   1
+	   0 0 1   4
+	   0 1 0   8
+	   0 1 1   16
+	   1 0 0   32
+	   1 0 1   64
+	   1 1 0   128
+	   1 1 1   256
+	   Wait the specified 50 PCI cycles after a reset by initializing
+	   Tx and Rx queues and the address filter list. */
+#if defined(__powerpc__)
+// 89/9/1 modify, 
+//   np->bcrvalue=0x04 | 0x0x38;  /* big-endian, 256 burst length */
+	np->bcrvalue = 0x04 | 0x0 x10;	/* big-endian, tx 8 burst length */
+	a np->cralue = 0xe00;	/* rx 128 burst length */
+#elif defined(__alpha__)
+// 89/9/1 modify, 
+//   np->bcrvalue=0x38;           /* little-endian, 256 burst length */
+	np->bcrvalue = 0x10;	/* little-endian, 8 burst length */
+	np->cralue = 0xe00;	/* rx 128 burst length */
+#elif defined(__i386__)
+#if defined(MODULE)
+// 89/9/1 modify, 
+//   np->bcrvalue=0x38;           /* little-endian, 256 burst length */
+	np->bcrvalue = 0x10;	/* little-endian, 8 burst length */
+	np->crvalue = 0xe00;	/* rx 128 burst length */
+#else
+	/* When not a module we can work around broken '486 PCI boards. */
+#define x86 boot_cpu_data.x86
+// 89/9/1 modify, 
+//   np->bcrvalue=(x86 <= 4 ? 0x10 : 0x38);
+	np->bcrvalue = 0x10;
+	np->crvalue = (x86 <= 4 ? 0xa00 : 0xe00);
+	if (x86 <= 4)
+		printk(KERN_INFO "%s: This is a 386/486 PCI system, setting burst "
+		       "length to %x.\n", dev->name, (x86 <= 4 ? 0x10 : 0x38));
+#endif
+#else
+// 89/9/1 modify,
+//   np->bcrvalue=0x38;
+	np->bcrvalue = 0x10;
+	np->cralue = 0xe00;	/* rx 128 burst length */
+#warning Processor architecture undefined!
+#endif
+// 89/12/29 add,
+// 90/1/16 modify,
+//   np->imrvalue=FBE|TUNF|CNTOVF|RBU|TI|RI;
+	np->imrvalue = TUNF | CNTOVF | RBU | TI | RI;
+	if (np->pci_dev->device == 0x891) {
+		np->bcrvalue |= 0x200;	/* set PROG bit */
+		np->crvalue |= 0x02000000;	/* set enhanced bit */
+		np->imrvalue |= ETI;
+	}
+	writel(np->bcrvalue, ioaddr + BCR);
+
+	if (dev->if_port == 0)
+		dev->if_port = np->default_port;
+
+	writel(0, dev->base_addr + RXPDR);
+// 89/9/1 modify,
+//   np->crvalue = 0x00e40001;    /* tx store and forward, tx/rx enable */
+	np->crvalue |= 0x00e40001;	/* tx store and forward, tx/rx enable */
+	np->full_duplex = np->duplex_lock;
+	getlinkstatus(dev);
+	if (np->linkok)
+		getlinktype(dev);
+	set_rx_mode(dev);
+
+	netif_start_queue(dev);
+
+	/* Clear and Enable interrupts by setting the interrupt mask. */
+	writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
+	writel(np->imrvalue, ioaddr + IMR);
+
+	if (debug)
+		printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name);
+
+	/* Set the timer to check for link beat. */
+	init_timer(&np->timer);
+	np->timer.expires = RUN_AT(3 * HZ);
+	np->timer.data = (unsigned long) dev;
+	np->timer.function = &netdev_timer;
+
+	/* timer handler */
+	add_timer(&np->timer);
+
+	return 0;
+}
+
+
+static void getlinkstatus(struct net_device *dev)
+/* function: Routine will read MII Status Register to get link status.       */
+/* input   : dev... pointer to the adapter block.                            */
+/* output  : none.                                                           */
+{
+	struct netdev_private *np = dev->priv;
+	unsigned int i, DelayTime = 0x1000;
+
+	np->linkok = 0;
+
+	if (np->PHYType == MysonPHY) {
+		for (i = 0; i < DelayTime; ++i) {
+			if (readl(dev->base_addr + BMCRSR) & LinkIsUp2) {
+				np->linkok = 1;
+				return;
+			}
+			// delay
+			m80x_delay(100);
+		}
+	} else {
+		for (i = 0; i < DelayTime; ++i) {
+			if (mdio_read(dev, np->phys[0], 1) & 0x4) {
+				np->linkok = 1;
+				return;
+			}
+			// delay
+			m80x_delay(100);
+		}
+	}
+}
+
+
+static void getlinktype(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	if (np->PHYType == MysonPHY) {	/* 3-in-1 case */
+		if (readl(dev->base_addr + TCRRCR) & FD)
+			np->duplexmode = 2;	/* full duplex */
+		else
+			np->duplexmode = 1;	/* half duplex */
+		if (readl(dev->base_addr + TCRRCR) & PS10)
+			np->line_speed = 1;	/* 10M */
+		else
+			np->line_speed = 2;	/* 100M */
+	} else {
+		if (np->PHYType == SeeqPHY) {	/* this PHY is SEEQ 80225 */
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], MIIRegister18);
+			if (data & SPD_DET_100)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+			if (data & DPLX_DET_FULL)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+		} else if (np->PHYType == AhdocPHY) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], DiagnosticReg);
+			if (data & Speed_100)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+			if (data & DPLX_FULL)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+		}
+/* 89/6/13 add, (begin) */
+		else if (np->PHYType == MarvellPHY) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], SpecificReg);
+			if (data & Full_Duplex)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+			data &= SpeedMask;
+			if (data == Speed_1000M)
+				np->line_speed = 3;	/* 1000M */
+			else if (data == Speed_100M)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+		}
+/* 89/6/13 add, (end) */
+/* 89/7/27 add, (begin) */
+		else if (np->PHYType == Myson981) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], StatusRegister);
+
+			if (data & SPEED100)
+				np->line_speed = 2;
+			else
+				np->line_speed = 1;
+
+			if (data & FULLMODE)
+				np->duplexmode = 2;
+			else
+				np->duplexmode = 1;
+		}
+/* 89/7/27 add, (end) */
+/* 89/12/29 add */
+		else if (np->PHYType == LevelOnePHY) {
+			unsigned int data;
+
+			data = mdio_read(dev, np->phys[0], SpecificReg);
+			if (data & LXT1000_Full)
+				np->duplexmode = 2;	/* full duplex mode */
+			else
+				np->duplexmode = 1;	/* half duplex mode */
+			data &= SpeedMask;
+			if (data == LXT1000_1000M)
+				np->line_speed = 3;	/* 1000M */
+			else if (data == LXT1000_100M)
+				np->line_speed = 2;	/* 100M */
+			else
+				np->line_speed = 1;	/* 10M */
+		}
+		// chage crvalue
+		// np->crvalue&=(~PS10)&(~FD);
+		np->crvalue &= (~PS10) & (~FD) & (~PS1000);
+		if (np->line_speed == 1)
+			np->crvalue |= PS10;
+		else if (np->line_speed == 3)
+			np->crvalue |= PS1000;
+		if (np->duplexmode == 2)
+			np->crvalue |= FD;
+	}
+}
+
+
+static void allocate_rx_buffers(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	/*  allocate skb for rx buffers */
+	while (np->really_rx_count != RX_RING_SIZE) {
+		struct sk_buff *skb;
+
+		skb = dev_alloc_skb(np->rx_buf_sz);
+		np->lack_rxbuf->skbuff = skb;
+
+		if (skb == NULL)
+			break;	/* Better luck next round. */
+
+		skb->dev = dev;	/* Mark as being used by this device. */
+		np->lack_rxbuf->buffer = virt_to_bus(skb->tail);
+		np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
+		++np->really_rx_count;
+	}
+}
+
+
+static void netdev_timer(unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+	int next_tick = 10 * HZ;
+	int old_crvalue = np->crvalue;
+	unsigned int old_linkok = np->linkok;
+
+	if (debug)
+		printk(KERN_DEBUG "%s: Media selection timer tick, status %8.8x "
+		       "config %8.8x.\n", dev->name, readl(ioaddr + ISR),
+		       readl(ioaddr + TCRRCR));
+
+	if (np->flags == HAS_MII_XCVR) {
+		getlinkstatus(dev);
+		if ((old_linkok == 0) && (np->linkok == 1)) {	/* we need to detect the media type again */
+			getlinktype(dev);
+			if (np->crvalue != old_crvalue) {
+				stop_nic_tx(ioaddr, np->crvalue);
+				stop_nic_rx(ioaddr, np->crvalue & (~0x40000));
+				writel(np->crvalue, ioaddr + TCRRCR);
+			}
+		}
+	}
+
+	allocate_rx_buffers(dev);
+
+	np->timer.expires = RUN_AT(next_tick);
+	add_timer(&np->timer);
+}
+
+
+static void tx_timeout(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+
+	printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
+	       " resetting...\n", dev->name, readl(ioaddr + ISR));
+
+#ifndef __alpha__
+	{
+		int i;
+
+		printk(KERN_DEBUG "  Rx ring %8.8x: ", (int) np->rx_ring);
+		for (i = 0; i < RX_RING_SIZE; i++)
+			printk(" %8.8x", (unsigned int) np->rx_ring[i].status);
+		printk("\n" KERN_DEBUG "  Tx ring %8.8x: ", (int) np->tx_ring);
+		for (i = 0; i < TX_RING_SIZE; i++)
+			printk(" %4.4x", np->tx_ring[i].status);
+		printk("\n");
+	}
+#endif
+
+	/* Perhaps we should reinitialize the hardware here.  Just trigger a
+	   Tx demand for now. */
+	writel(0, dev->base_addr + TXPDR);
+	dev->if_port = 0;
+
+	/* Stop and restart the chip's Tx processes . */
+	dev->trans_start = jiffies;
+	np->stats.tx_errors++;
+
+	return;
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void init_ring(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	int i;
+
+	/* initialize rx variables */
+	np->rx_buf_sz = (dev->mtu <= 1500 ? PKT_BUF_SZ : dev->mtu + 32);
+	np->cur_rx = &np->rx_ring[0];
+	np->lack_rxbuf = NULL;
+	np->really_rx_count = 0;
+
+	/* initial rx descriptors. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].status = 0;
+		np->rx_ring[i].control = np->rx_buf_sz << RBSShift;
+		np->rx_ring[i].next_desc = virt_to_bus(&np->rx_ring[i + 1]);
+		np->rx_ring[i].next_desc_logical = &np->rx_ring[i + 1];
+		np->rx_ring[i].skbuff = NULL;
+	}
+
+	/* for the last rx descriptor */
+	np->rx_ring[i - 1].next_desc = virt_to_bus(&np->rx_ring[0]);
+	np->rx_ring[i - 1].next_desc_logical = &np->rx_ring[0];
+
+	/* allocate skb for rx buffers */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb = dev_alloc_skb(np->rx_buf_sz);
+
+		if (skb == NULL) {
+			np->lack_rxbuf = &np->rx_ring[i];
+			break;
+		}
+
+		++np->really_rx_count;
+		np->rx_ring[i].skbuff = skb;
+		skb->dev = dev;	/* Mark as being used by this device. */
+		np->rx_ring[i].buffer = virt_to_bus(skb->tail);
+		np->rx_ring[i].status = RXOWN;
+		np->rx_ring[i].control |= RXIC;
+	}
+
+	/* initialize tx variables */
+	np->cur_tx = &np->tx_ring[0];
+	np->cur_tx_copy = &np->tx_ring[0];
+	np->really_tx_count = 0;
+	np->free_tx_count = TX_RING_SIZE;
+
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		np->tx_ring[i].status = 0;
+		np->tx_ring[i].next_desc = virt_to_bus(&np->tx_ring[i + 1]);
+		np->tx_ring[i].next_desc_logical = &np->tx_ring[i + 1];
+		np->tx_ring[i].skbuff = NULL;
+	}
+
+	/* for the last tx descriptor */
+	np->tx_ring[i - 1].next_desc = virt_to_bus(&np->tx_ring[0]);
+	np->tx_ring[i - 1].next_desc_logical = &np->tx_ring[0];
+
+	return;
+}
+
+
+static int start_tx(struct sk_buff *skb, struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	np->cur_tx_copy->skbuff = skb;
+	np->cur_tx_copy->buffer = virt_to_bus(skb->data);
+
+#define one_buffer
+#define BPT 1022
+#if defined(one_buffer)
+	np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable;
+	np->cur_tx_copy->control |= (skb->len << PKTSShift);	/* pkt size */
+	np->cur_tx_copy->control |= (skb->len << TBSShift);	/* buffer size */
+// 89/12/29 add,
+	if (np->pci_dev->device == 0x891)
+		np->cur_tx_copy->control |= ETIControl | RetryTxLC;
+	np->cur_tx_copy->status = TXOWN;
+	np->cur_tx_copy = np->cur_tx_copy->next_desc_logical;
+	--np->free_tx_count;
+#elif defined(two_buffer)
+	if (skb->len > BPT) {
+		struct fealnx_desc *next;
+
+		/* for the first descriptor */
+		np->cur_tx_copy->control = TXIC | TXFD | CRCEnable | PADEnable;
+		np->cur_tx_copy->control |= (skb->len << PKTSShift);	/* pkt size */
+		np->cur_tx_copy->control |= (BPT << TBSShift);	/* buffer size */
+
+		/* for the last descriptor */
+		next = (struct fealnx *) np->cur_tx_copy.next_desc_logical;
+		next->skbuff = skb;
+		next->control = TXIC | TXLD | CRCEnable | PADEnable;
+		next->control |= (skb->len << PKTSShift);	/* pkt size */
+		next->control |= ((skb->len - BPT) << TBSShift);	/* buf size */
+// 89/12/29 add,
+		if (np->pci_dev->device == 0x891)
+			np->cur_tx_copy->control |= ETIControl | RetryTxLC;
+		next->buffer = virt_to_bus(skb->data) + BPT;
+
+		next->status = TXOWN;
+		np->cur_tx_copy->status = TXOWN;
+
+		np->cur_tx_copy = next->next_desc_logical;
+		np->free_tx_count -= 2;
+	} else {
+		np->cur_tx_copy->control = TXIC | TXLD | TXFD | CRCEnable | PADEnable;
+		np->cur_tx_copy->control |= (skb->len << PKTSShift);	/* pkt size */
+		np->cur_tx_copy->control |= (skb->len << TBSShift);	/* buffer size */
+// 89/12/29 add,
+		if (np->pci_dev->device == 0x891)
+			np->cur_tx_copy->control |= ETIControl | RetryTxLC;
+		np->cur_tx_copy->status = TXOWN;
+		np->cur_tx_copy = np->cur_tx_copy->next_desc_logical;
+		--np->free_tx_count;
+	}
+#endif
+
+	if (np->free_tx_count < 2)
+		netif_stop_queue(dev);
+	++np->really_tx_count;
+	writel(0, dev->base_addr + TXPDR);
+	dev->trans_start = jiffies;
+
+	return 0;
+}
+
+
+void free_one_rx_descriptor(struct netdev_private *np)
+{
+	if (np->really_rx_count == RX_RING_SIZE)
+		np->cur_rx->status = RXOWN;
+	else {
+		np->lack_rxbuf->skbuff = np->cur_rx->skbuff;
+		np->lack_rxbuf->buffer = np->cur_rx->buffer;
+		np->lack_rxbuf->status = RXOWN;
+		++np->really_rx_count;
+		np->lack_rxbuf = np->lack_rxbuf->next_desc_logical;
+	}
+	np->cur_rx = np->cur_rx->next_desc_logical;
+}
+
+
+void reset_rx_descriptors(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	stop_nic_rx(dev->base_addr, np->crvalue);
+
+	while (!(np->cur_rx->status & RXOWN))
+		free_one_rx_descriptor(np);
+
+	allocate_rx_buffers(dev);
+
+	writel(virt_to_bus(np->cur_rx), dev->base_addr + RXLBA);
+	writel(np->crvalue, dev->base_addr + TCRRCR);
+}
+
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+{
+	struct net_device *dev = (struct net_device *) dev_instance;
+	struct netdev_private *np = dev->priv;
+	long ioaddr, boguscnt = max_interrupt_work;
+	unsigned int num_tx = 0;
+
+	writel(0, dev->base_addr + IMR);
+
+	ioaddr = dev->base_addr;
+	np = (struct netdev_private *) dev->priv;
+
+	do {
+		u32 intr_status = readl(ioaddr + ISR);
+
+		/* Acknowledge all of the current interrupt sources ASAP. */
+		writel(intr_status, ioaddr + ISR);
+
+		if (debug)
+			printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name,
+			       intr_status);
+
+		if (!(intr_status & np->imrvalue))
+			break;
+
+// 90/1/16 delete,
+//
+//      if (intr_status & FBE)
+//      {   /* fatal error */
+//          stop_nic_tx(ioaddr, 0);
+//          stop_nic_rx(ioaddr, 0);
+//          break;
+//      };
+
+		if (intr_status & TUNF)
+			writel(0, ioaddr + TXPDR);
+
+		if (intr_status & CNTOVF) {
+			/* missed pkts */
+			np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+
+			/* crc error */
+			np->stats.rx_crc_errors +=
+			    (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+		}
+
+		if (intr_status & (RI | RBU)) {
+			if (intr_status & RI)
+				netdev_rx(dev);
+			else
+				reset_rx_descriptors(dev);
+		}
+
+		while (np->really_tx_count) {
+			long tx_status = np->cur_tx->status;
+			long tx_control = np->cur_tx->control;
+
+			if (!(tx_control & TXLD)) {	/* this pkt is combined by two tx descriptors */
+				struct fealnx_desc *next;
+
+				next = np->cur_tx->next_desc_logical;
+				tx_status = next->status;
+				tx_control = next->control;
+			}
+
+			if (tx_status & TXOWN)
+				break;
+
+			if (!(np->crvalue & 0x02000000)) {
+				if (tx_status & (CSL | LC | EC | UDF | HF)) {
+					np->stats.tx_errors++;
+					if (tx_status & EC)
+						np->stats.tx_aborted_errors++;
+					if (tx_status & CSL)
+						np->stats.tx_carrier_errors++;
+					if (tx_status & LC)
+						np->stats.tx_window_errors++;
+					if (tx_status & UDF)
+						np->stats.tx_fifo_errors++;
+					if ((tx_status & HF) && np->full_duplex == 0)
+						np->stats.tx_heartbeat_errors++;
+
+#ifdef ETHER_STATS
+					if (tx_status & EC)
+						np->stats.collisions16++;
+#endif
+				} else {
+#ifdef ETHER_STATS
+					if (tx_status & DFR)
+						np->stats.tx_deferred++;
+#endif
+
+					np->stats.tx_bytes +=
+					    ((tx_control & PKTSMask) >> PKTSShift);
+
+					np->stats.collisions +=
+					    ((tx_status & NCRMask) >> NCRShift);
+					np->stats.tx_packets++;
+				}
+			} else {
+				np->stats.tx_bytes +=
+				    ((tx_control & PKTSMask) >> PKTSShift);
+				np->stats.tx_packets++;
+			}
+
+			/* Free the original skb. */
+			dev_kfree_skb_irq(np->cur_tx->skbuff);
+			np->cur_tx->skbuff = NULL;
+			--np->really_tx_count;
+			if (np->cur_tx->control & TXLD) {
+				np->cur_tx = np->cur_tx->next_desc_logical;
+				++np->free_tx_count;
+			} else {
+				np->cur_tx = np->cur_tx->next_desc_logical;
+				np->cur_tx = np->cur_tx->next_desc_logical;
+				np->free_tx_count += 2;
+			}
+			num_tx++;
+		}		/* end of for loop */
+		
+		if (num_tx && np->free_tx_count >= 2)
+			netif_wake_queue(dev);
+
+		/* read transmit status for enhanced mode only */
+		if (np->crvalue & 0x02000000) {
+			long data;
+
+			data = readl(ioaddr + TSR);
+			np->stats.tx_errors += (data & 0xff000000) >> 24;
+			np->stats.tx_aborted_errors += (data & 0xff000000) >> 24;
+			np->stats.tx_window_errors += (data & 0x00ff0000) >> 16;
+#ifdef ETHER_STATS
+			np->stats.collisions16 += (data & 0xff000000) >> 24;
+#endif
+			np->stats.collisions += (data & 0x0000ffff);
+		}
+
+		if (--boguscnt < 0) {
+			printk(KERN_WARNING "%s: Too much work at interrupt, "
+			       "status=0x%4.4x.\n", dev->name, intr_status);
+			break;
+		}
+	} while (1);
+
+	/* read the tally counters */
+	/* missed pkts */
+	np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+
+	/* crc error */
+	np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+
+	if (debug)
+		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
+		       dev->name, readl(ioaddr + ISR));
+
+	writel(np->imrvalue, ioaddr + IMR);
+
+	return;
+}
+
+
+/* This routine is logically part of the interrupt handler, but seperated
+   for clarity and better register allocation. */
+static int netdev_rx(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+
+	/* If EOP is set on the next entry, it's a new packet. Send it up. */
+	while (!(np->cur_rx->status & RXOWN)) {
+		s32 rx_status = np->cur_rx->status;
+
+		if (np->really_rx_count == 0)
+			break;
+
+		if (debug)
+			printk(KERN_DEBUG "  netdev_rx() status was %8.8x.\n", rx_status);
+
+		if ((!((rx_status & RXFSD) && (rx_status & RXLSD)))
+		    || (rx_status & ErrorSummary)) {
+			if (rx_status & ErrorSummary) {	/* there was a fatal error */
+				if (debug)
+					printk(KERN_DEBUG
+					       "%s: Receive error, Rx status %8.8x.\n",
+					       dev->name, rx_status);
+
+				np->stats.rx_errors++;	/* end of a packet. */
+				if (rx_status & (LONG | RUNT))
+					np->stats.rx_length_errors++;
+				if (rx_status & RXER)
+					np->stats.rx_frame_errors++;
+				if (rx_status & CRC)
+					np->stats.rx_crc_errors++;
+			} else {
+				int need_to_reset = 0;
+				int desno = 0;
+
+				if (rx_status & RXFSD) {	/* this pkt is too long, over one rx buffer */
+					struct fealnx_desc *cur;
+
+					/* check this packet is received completely? */
+					cur = np->cur_rx;
+					while (desno <= np->really_rx_count) {
+						++desno;
+						if ((!(cur->status & RXOWN))
+						    && (cur->status & RXLSD))
+							break;
+						/* goto next rx descriptor */
+						cur = cur->next_desc_logical;
+					}
+					if (desno > np->really_rx_count)
+						need_to_reset = 1;
+				} else	/* RXLSD did not find, something error */
+					need_to_reset = 1;
+
+				if (need_to_reset == 0) {
+					int i;
+
+					np->stats.rx_length_errors++;
+
+					/* free all rx descriptors related this long pkt */
+					for (i = 0; i < desno; ++i)
+						free_one_rx_descriptor(np);
+					continue;
+				} else {	/* something error, need to reset this chip */
+					reset_rx_descriptors(dev);
+				}
+				break;	/* exit the while loop */
+			}
+		} else {	/* this received pkt is ok */
+
+			struct sk_buff *skb;
+			/* Omit the four octet CRC from the length. */
+			short pkt_len = ((rx_status & FLNGMASK) >> FLNGShift) - 4;
+
+#ifndef final_version
+			if (debug)
+				printk(KERN_DEBUG "  netdev_rx() normal Rx pkt length %d"
+				       " status %x.\n", pkt_len, rx_status);
+#endif
+
+			/* Check if the packet is long enough to accept without copying
+			   to a minimally-sized skbuff. */
+			if (pkt_len < rx_copybreak &&
+			    (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+				skb->dev = dev;
+				skb_reserve(skb, 2);	/* 16 byte align the IP header */
+				/* Call copy + cksum if available. */
+
+#if ! defined(__alpha__)
+				eth_copy_and_sum(skb, bus_to_virt(np->cur_rx->buffer),
+						 pkt_len, 0);
+				skb_put(skb, pkt_len);
+#else
+				memcpy(skb_put(skb, pkt_len),
+				       bus_to_virt(np->cur_rx->buffer), pkt_len);
+#endif
+			} else {
+				skb_put(skb = np->cur_rx->skbuff, pkt_len);
+				np->cur_rx->skbuff = NULL;
+				if (np->really_rx_count == RX_RING_SIZE)
+					np->lack_rxbuf = np->cur_rx;
+				--np->really_rx_count;
+			}
+			skb->protocol = eth_type_trans(skb, dev);
+			netif_rx(skb);
+			dev->last_rx = jiffies;
+			np->stats.rx_packets++;
+			np->stats.rx_bytes += pkt_len;
+		}
+
+		if (np->cur_rx->skbuff == NULL) {
+			struct sk_buff *skb;
+
+			skb = dev_alloc_skb(np->rx_buf_sz);
+
+			if (skb != NULL) {
+				skb->dev = dev;	/* Mark as being used by this device. */
+				np->cur_rx->buffer = virt_to_bus(skb->tail);
+				np->cur_rx->skbuff = skb;
+				++np->really_rx_count;
+			}
+		}
+
+		if (np->cur_rx->skbuff != NULL)
+			free_one_rx_descriptor(np);
+	}			/* end of while loop */
+
+	/*  allocate skb for rx buffers */
+	allocate_rx_buffers(dev);
+
+	return 0;
+}
+
+
+static struct net_device_stats *get_stats(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct netdev_private *np = dev->priv;
+
+	/* The chip only need report frame silently dropped. */
+	if (netif_running(dev)) {
+		np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+		np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+	}
+
+	return &np->stats;
+}
+
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+	int crc = -1;
+
+	while (--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+
+		for (bit = 0; bit < 8; bit++, current_octet >>= 1) {
+			crc = (crc << 1) ^
+			    ((crc < 0) ^ (current_octet & 1) ? ethernet_polynomial : 0);
+		}
+	}
+
+	return crc;
+}
+
+
+static void set_rx_mode(struct net_device *dev)
+{
+	struct netdev_private *np = dev->priv;
+	long ioaddr = dev->base_addr;
+	u32 mc_filter[2];	/* Multicast hash filter */
+	u32 rx_mode;
+
+	if (dev->flags & IFF_PROMISC) {	/* Set promiscuous. */
+		/* Unconditionally log net taps. */
+		printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", dev->name);
+		memset(mc_filter, 0xff, sizeof(mc_filter));
+		rx_mode = PROM | AB | AM;
+	} else if ((dev->mc_count > multicast_filter_limit)
+		   || (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to match, or accept all multicasts. */
+		memset(mc_filter, 0xff, sizeof(mc_filter));
+		rx_mode = AB | AM;
+	} else {
+		struct dev_mc_list *mclist;
+		int i;
+
+		memset(mc_filter, 0, sizeof(mc_filter));
+		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+		     i++, mclist = mclist->next) {
+			set_bit((ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26) ^ 0x3F,
+				mc_filter);
+		}
+		rx_mode = AB | AM;
+	}
+
+	stop_nic_tx(ioaddr, np->crvalue);
+	stop_nic_rx(ioaddr, np->crvalue & (~0x40000));
+
+	writel(mc_filter[0], ioaddr + MAR0);
+	writel(mc_filter[1], ioaddr + MAR1);
+	np->crvalue &= ~RxModeMask;
+	np->crvalue |= rx_mode;
+	writel(np->crvalue, ioaddr + TCRRCR);
+}
+
+
+static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	u16 *data = (u16 *) & rq->ifr_data;
+
+	switch (cmd) {
+	case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
+		data[0] = ((struct netdev_private *) dev->priv)->phys[0] & 0x1f;
+		/* Fall Through */
+	case SIOCDEVPRIVATE + 1:	/* Read the specified MII register. */
+		data[3] = mdio_read(dev, data[0] & 0x1f, data[1] & 0x1f);
+		return 0;
+	case SIOCDEVPRIVATE + 2:	/* Write the specified MII register */
+		if (!suser())
+			return -EPERM;
+		mdio_write(dev, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+
+static int netdev_close(struct net_device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct netdev_private *np = dev->priv;
+	int i;
+
+	netif_stop_queue(dev);
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	writel(0x0000, ioaddr + IMR);
+
+	/* Stop the chip's Tx and Rx processes. */
+	stop_nic_tx(ioaddr, 0);
+	stop_nic_rx(ioaddr, 0);
+
+	del_timer_sync(&np->timer);
+
+	free_irq(dev->irq, dev);
+
+	/* Free all the skbuffs in the Rx queue. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		np->rx_ring[i].status = 0;
+		if (np->rx_ring[i].skbuff)
+			dev_kfree_skb(np->rx_ring[i].skbuff);
+		np->rx_ring[i].skbuff = NULL;
+	}
+
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (np->tx_ring[i].skbuff)
+			dev_kfree_skb(np->tx_ring[i].skbuff);
+		np->tx_ring[i].skbuff = NULL;
+	}
+
+	return 0;
+}
+
+static struct pci_device_id fealnx_pci_tbl[] = __devinitdata {
+	{0x1516, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0x1516, 0x0803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
+	{0x1516, 0x0891, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2},
+	{} /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, fealnx_pci_tbl);
+
+
+static struct pci_driver fealnx_driver = {
+	name:		"fealnx",
+	id_table:	fealnx_pci_tbl,
+	probe:		fealnx_init_one,
+	remove:		fealnx_remove_one,
+};
+
+static int __init fealnx_init(void)
+{
+/* when a module, this is printed whether or not devices are found in probe */
+#ifdef MODULE
+	printk (version);
+#endif
+
+	return pci_module_init(&fealnx_driver);
+}
+
+static void __exit fealnx_exit(void)
+{
+	pci_unregister_driver(&fealnx_driver);
+}
+
+module_init(fealnx_init);
+module_exit(fealnx_exit);
diff -urN linux-2.4.5-pre2/drivers/net/gmac.c linux/drivers/net/gmac.c
--- linux-2.4.5-pre2/drivers/net/gmac.c	Tue Feb 13 13:15:05 2001
+++ linux/drivers/net/gmac.c	Mon Dec  3 22:43:26 2001
@@ -9,7 +9,7 @@
  * Changes:
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/06/2000
  * - check init_etherdev return in gmac_probe1
- * BenH <bh40@calva.net> - 03/09/2000
+ * BenH <benh@kernel.crashing.org> - 03/09/2000
  * - Add support for new PHYs
  * - Add some PowerBook sleep code
  * 
@@ -47,10 +47,11 @@
 #define DEBUG_PHY
 
 /* Driver version 1.3, kernel 2.4.x */
-#define GMAC_VERSION	"v1.3k4"
+#define GMAC_VERSION	"v1.4k4"
 
-static unsigned char dummy_buf[RX_BUF_ALLOC_SIZE + RX_OFFSET + GMAC_BUFFER_ALIGN];
-static struct net_device *gmacs = NULL;
+#define DUMMY_BUF_LEN	RX_BUF_ALLOC_SIZE + RX_OFFSET + GMAC_BUFFER_ALIGN
+static unsigned char *dummy_buf;
+static struct net_device *gmacs;
 
 /* Prototypes */
 static int mii_read(struct gmac *gm, int phy, int r);
@@ -62,6 +63,7 @@
 static void mii_setup_phy(struct gmac *gm);
 static int mii_do_reset_phy(struct gmac *gm, int phy_addr);
 static void mii_init_BCM5400(struct gmac *gm);
+static void mii_init_BCM5401(struct gmac *gm);
 
 static void gmac_set_power(struct gmac *gm, int power_up);
 static int gmac_powerup_and_reset(struct net_device *dev);
@@ -211,10 +213,12 @@
 		int		link_100 = 0;
 		int		gigabit = 0;
 #ifdef DEBUG_PHY
-		printk("Link state change, phy_status: 0x%04x\n", phy_status);
+		printk("%s: Link state change, phy_status: 0x%04x\n",
+			gm->dev->name, phy_status);
 #endif
 		gm->phy_status = phy_status;
 
+		/* Should we enable that in generic mode ? */
 		lpar_ability = mii_read(gm, gm->phy_addr, MII_ANLPA);
 		if (lpar_ability & MII_ANLPA_PAUS)
 			GM_BIS(GM_MAC_CTRL_CONFIG, GM_MAC_CTRL_CONF_SND_PAUSE_EN);
@@ -249,6 +253,9 @@
 #endif
 		    	full_duplex = ((stat2 & MII_LXT971_STATUS2_FULLDUPLEX) != 0);
 		    	link_100 = ((stat2 & MII_LXT971_STATUS2_SPEED) != 0);
+		    } else {
+		    	full_duplex = (lpar_ability & MII_ANLPA_FDAM) != 0;
+		    	link_100 = (lpar_ability & MII_ANLPA_100M) != 0;
 		    }
 #ifdef DEBUG_PHY
 		    printk("    full_duplex: %d, speed: %s\n", full_duplex,
@@ -274,6 +281,144 @@
 	}
 }
 
+/* Power management: stop PHY chip for suspend mode
+ */
+static void
+gmac_suspend(struct gmac* gm)
+{
+	int data, timeout;
+	unsigned long flags;
+	
+	gm->sleeping = 1;
+	netif_stop_queue(gm->dev);
+
+
+	spin_lock_irqsave(&gm->lock, flags);
+	if (gm->opened) {
+		disable_irq(gm->dev->irq);
+		/* Stop polling PHY */
+		mii_poll_stop(gm);
+	}
+	/* Mask out all chips interrupts */
+	GM_OUT(GM_IRQ_MASK, 0xffffffff);
+	spin_unlock_irqrestore(&gm->lock, flags);
+	
+	if (gm->opened) {
+		int i;
+		/* Empty Tx ring of any remaining gremlins */
+		gmac_tx_cleanup(gm->dev, 1);
+	
+		/* Empty Rx ring of any remaining gremlins */
+		for (i = 0; i < NRX; ++i) {
+			if (gm->rx_buff[i] != 0) {
+				dev_kfree_skb_irq(gm->rx_buff[i]);
+				gm->rx_buff[i] = 0;
+			}
+		}
+	}
+
+	/* Clear interrupts on 5201 */
+	if (gm->phy_type == PHY_B5201)
+		mii_write(gm, gm->phy_addr, MII_BCM5201_INTERRUPT, 0);
+		
+	/* Drive MDIO high */
+	GM_OUT(GM_MIF_CFG, 0);
+	
+	/* Unchanged, don't ask me why */
+	data = mii_read(gm, gm->phy_addr, MII_ANLPA);
+	mii_write(gm, gm->phy_addr, MII_ANLPA, data);
+	
+	/* Put MDIO in sane state */
+	GM_OUT(GM_MIF_CFG, GM_MIF_CFGBB);
+	GM_OUT(GM_MIF_BB_CLOCK, 0);
+	GM_OUT(GM_MIF_BB_DATA, 0);
+	GM_OUT(GM_MIF_BB_OUT_ENABLE, 0);
+	
+	/* Stop everything */
+	GM_OUT(GM_MAC_RX_CONFIG, 0);
+	GM_OUT(GM_MAC_TX_CONFIG, 0);
+	GM_OUT(GM_MAC_XIF_CONFIG, 0);
+	GM_OUT(GM_TX_CONF, 0);
+	GM_OUT(GM_RX_CONF, 0);
+	
+	/* Set reset state */
+	GM_OUT(GM_RESET, GM_RESET_TX | GM_RESET_RX);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mdelay(10);
+		if ((GM_IN(GM_RESET) & (GM_RESET_TX | GM_RESET_RX)) == 0)
+			break;
+	}
+	GM_OUT(GM_MAC_TX_RESET, GM_MAC_TX_RESET_NOW);
+	GM_OUT(GM_MAC_RX_RESET, GM_MAC_RX_RESET_NOW);
+
+	/* Superisolate PHY */
+	if (gm->phy_type == PHY_B5201)
+		mii_write(gm, gm->phy_addr, MII_BCM5201_MULTIPHY,
+			MII_BCM5201_MULTIPHY_SUPERISOLATE);
+
+	/* Unclock chip */
+	gmac_set_power(gm, 0);
+}
+
+static void
+gmac_resume(struct gmac *gm)
+{
+	int data;
+
+	if (gmac_powerup_and_reset(gm->dev)) {
+		printk(KERN_ERR "%s: Couldn't revive gmac ethernet !\n", gm->dev->name);
+		return;
+	}
+
+	gm->sleeping = 0;
+	
+	if (gm->opened) {
+		/* Create fresh rings */
+		gmac_init_rings(gm, 1);
+		/* re-initialize the MAC */
+		gmac_mac_init(gm, gm->dev->dev_addr);	
+		/* re-initialize the multicast tables & promisc mode if any */
+		gmac_set_multicast(gm->dev);
+	}
+
+	/* Early enable Tx and Rx so that we are clocked */
+	GM_BIS(GM_TX_CONF, GM_TX_CONF_DMA_EN);
+	mdelay(20);
+	GM_BIS(GM_RX_CONF, GM_RX_CONF_DMA_EN);
+	mdelay(20);
+	GM_BIS(GM_MAC_TX_CONFIG, GM_MAC_TX_CONF_ENABLE);
+	mdelay(20);
+	GM_BIS(GM_MAC_RX_CONFIG, GM_MAC_RX_CONF_ENABLE);
+	mdelay(20);
+	if (gm->phy_type == PHY_B5201) {
+		data = mii_read(gm, gm->phy_addr, MII_BCM5201_MULTIPHY);
+		mii_write(gm, gm->phy_addr, MII_BCM5201_MULTIPHY,
+			data & ~MII_BCM5201_MULTIPHY_SUPERISOLATE);
+	}
+	mdelay(1);
+
+	if (gm->opened) {
+		/* restart polling PHY */
+		mii_interrupt(gm);
+		/* restart DMA operations */
+		gmac_start_dma(gm);
+		netif_start_queue(gm->dev);
+		enable_irq(gm->dev->irq);
+	} else {
+		/* Driver not opened, just leave things off. Note that
+		 * we could be smart and superisolate the PHY when the
+		 * driver is closed, but I won't do that unless I have
+		 * a better understanding of some electrical issues with
+		 * this PHY chip --BenH
+		 */
+		GM_OUT(GM_MAC_RX_CONFIG, 0);
+		GM_OUT(GM_MAC_TX_CONFIG, 0);
+		GM_OUT(GM_MAC_XIF_CONFIG, 0);
+		GM_OUT(GM_TX_CONF, 0);
+		GM_OUT(GM_RX_CONF, 0);
+	}
+}
+
 static int
 mii_do_reset_phy(struct gmac *gm, int phy_addr)
 {
@@ -326,6 +471,40 @@
 	mii_write(gm, gm->phy_addr, MII_BCM5400_AUXCONTROL, data);
 }
 
+static void
+mii_init_BCM5401(struct gmac *gm)
+{
+	int data;
+	int rev;
+
+	rev = mii_read(gm, gm->phy_addr, MII_ID1) & 0x000f;
+	if (rev == 0 || rev == 3) {
+		/* A bit of black magic from Apple */
+		mii_write(gm, gm->phy_addr, 0x18, 0x0c20);
+		mii_write(gm, gm->phy_addr, 0x17, 0x0012);
+		mii_write(gm, gm->phy_addr, 0x15, 0x1804);
+		mii_write(gm, gm->phy_addr, 0x17, 0x0013);
+		mii_write(gm, gm->phy_addr, 0x15, 0x1204);
+		mii_write(gm, gm->phy_addr, 0x17, 0x8006);
+		mii_write(gm, gm->phy_addr, 0x15, 0x0132);
+		mii_write(gm, gm->phy_addr, 0x17, 0x8006);
+		mii_write(gm, gm->phy_addr, 0x15, 0x0232);
+		mii_write(gm, gm->phy_addr, 0x17, 0x201f);
+		mii_write(gm, gm->phy_addr, 0x15, 0x0a20);
+	}
+	
+	data = mii_read(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL);
+	data |= MII_BCM5400_GB_CONTROL_FULLDUPLEXCAP;
+	mii_write(gm, gm->phy_addr, MII_BCM5400_GB_CONTROL, data);
+
+	mdelay(10);
+	mii_do_reset_phy(gm, 0x1f);
+	
+	data = mii_read(gm, 0x1f, MII_BCM5201_MULTIPHY);
+	data |= MII_BCM5201_MULTIPHY_SERIALMODE;
+	mii_write(gm, 0x1f, MII_BCM5201_MULTIPHY, data);
+}
+
 static int
 mii_lookup_and_reset(struct gmac *gm)
 {
@@ -335,10 +514,7 @@
 	gm->phy_type = PHY_UNKNOWN;
 
 	/* Hard reset the PHY */
-	feature_set_gmac_phy_reset(gm->of_node, KL_GPIO_ETH_PHY_RESET_ASSERT);
-	mdelay(10);
-	feature_set_gmac_phy_reset(gm->of_node, KL_GPIO_ETH_PHY_RESET_RELEASE);
-	mdelay(10);
+	feature_gmac_phy_reset(gm->of_node);
 	
 	/* Find the PHY */
 	for(i=0; i<=31; i++) {
@@ -367,14 +543,22 @@
 		printk(KERN_ERR "%s Found Broadcom BCM5400 PHY (Gigabit)\n",
 			gm->dev->name);
 		mii_init_BCM5400(gm);		
+	} else if ((gm->phy_id & MII_BCM5401_MASK) == MII_BCM5401_ID) {
+		gm->phy_type = PHY_B5401;
+		printk(KERN_ERR "%s Found Broadcom BCM5401 PHY (Gigabit)\n",
+			gm->dev->name);
+		mii_init_BCM5401(gm);		
 	} else if ((gm->phy_id & MII_BCM5201_MASK) == MII_BCM5201_ID) {
 		gm->phy_type = PHY_B5201;
 		printk(KERN_INFO "%s Found Broadcom BCM5201 PHY\n", gm->dev->name);
+	} else if ((gm->phy_id & MII_BCM5221_MASK) == MII_BCM5221_ID) {
+		gm->phy_type = PHY_B5201; /* Same as 5201 for now */
+		printk(KERN_INFO "%s Found Broadcom BCM5221 PHY\n", gm->dev->name);
 	} else if ((gm->phy_id & MII_LXT971_MASK) == MII_LXT971_ID) {
 		gm->phy_type = PHY_LXT971;
 		printk(KERN_INFO "%s Found LevelOne LX971 PHY\n", gm->dev->name);
 	} else {
-		printk(KERN_ERR "%s: Warning ! Unknown PHY ID 0x%08x !\n",
+		printk(KERN_ERR "%s: Warning ! Unknown PHY ID 0x%08x, using generic mode...\n",
 			gm->dev->name, gm->phy_id);
 	}
 
@@ -448,8 +632,6 @@
 	    			PCI_CACHE_LINE_SIZE, 8);
 		}
 	} else {
-		/* FIXME: Add PHY power down */
-		gm->phy_type = 0;
 		feature_set_gmac_power(gm->of_node, 0);
 	}
 }
@@ -472,11 +654,14 @@
 		if ((GM_IN(GM_RESET) & (GM_RESET_TX | GM_RESET_RX)) == 0) {
 			/* Mask out all chips interrupts */
 			GM_OUT(GM_IRQ_MASK, 0xffffffff);
+			GM_OUT(GM_MAC_TX_RESET, GM_MAC_TX_RESET_NOW);
+			GM_OUT(GM_MAC_RX_RESET, GM_MAC_RX_RESET_NOW);
 			return 0;
 		}
 	}
 	printk(KERN_ERR "%s reset failed!\n", dev->name);
 	gmac_set_power(gm, 0);
+	gm->phy_type = 0;
 	return -1;
 }
 
@@ -747,7 +932,9 @@
 	int multicast_hash = 0;
 	int multicast_all = 0;
 	int promisc = 0;
-	
+
+	if (gm->sleeping)
+		return;
 
 	/* Lock out others. */
 	netif_stop_queue(dev);
@@ -881,6 +1068,7 @@
 	
 	/* Shut down chip */
 	gmac_set_power(gm, 0);
+	gm->phy_type = 0;
 
 	/* Empty rings of any remaining gremlins */
 	for (i = 0; i < NRX; ++i) {
@@ -904,7 +1092,6 @@
 gmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
 	struct gmac *gm;
-	int i;
 	
 	/* XXX should handle more than one */
 	if (gmacs == NULL)
@@ -920,38 +1107,10 @@
 	case PBOOK_SLEEP_REJECT:
 		break;
 	case PBOOK_SLEEP_NOW:
-		disable_irq(gm->dev->irq);
-		netif_stop_queue(gm->dev);
-		gmac_stop_dma(gm);
-		mii_poll_stop(gm);
-		gmac_set_power(gm, 0);
-		for (i = 0; i < NRX; ++i) {
-			if (gm->rx_buff[i] != 0) {
-				dev_kfree_skb(gm->rx_buff[i]);
-				gm->rx_buff[i] = 0;
-			}
-		}
-		for (i = 0; i < NTX; ++i) {
-			if (gm->tx_buff[i] != 0) {
-				dev_kfree_skb(gm->tx_buff[i]);
-				gm->tx_buff[i] = 0;
-			}
-		}
+		gmac_suspend(gm);
 		break;
 	case PBOOK_WAKE:
-		/* see if this is enough */
-		gmac_powerup_and_reset(gm->dev);
-		gm->full_duplex = 0;
-		gm->phy_status = 0;
-		mii_lookup_and_reset(gm);
-		mii_setup_phy(gm);
-		gmac_init_rings(gm, 0);
-		gmac_mac_init(gm, gm->dev->dev_addr);
-		gmac_set_multicast(gm->dev);
-		mii_interrupt(gm);
-		gmac_start_dma(gm);
-		netif_start_queue(gm->dev);
-		enable_irq(gm->dev->irq);
+		gmac_resume(gm);
 		break;
 	}
 	return PBOOK_SLEEP_OK;
@@ -967,7 +1126,10 @@
 	struct gmac *gm = (struct gmac *) dev->priv;
 	int i, timeout;
 	unsigned long flags;
-		
+
+	if (gm->sleeping)
+		return;
+
 	printk (KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
 
 	spin_lock_irqsave(&gm->lock, flags);
@@ -990,6 +1152,8 @@
 		if ((GM_IN(GM_RESET) & (GM_RESET_TX | GM_RESET_RX)) == 0) {
 			/* Mask out all chips interrupts */
 			GM_OUT(GM_IRQ_MASK, 0xffffffff);
+			GM_OUT(GM_MAC_TX_RESET, GM_MAC_TX_RESET_NOW);
+			GM_OUT(GM_MAC_RX_RESET, GM_MAC_RX_RESET_NOW);
 			break;
 		}
 	}
@@ -1022,6 +1186,9 @@
 	unsigned long flags;
 	int i;
 
+	if (gm->sleeping)
+		return 1;
+		
 	spin_lock_irqsave(&gm->lock, flags);
 
 	i = gm->next_tx;
@@ -1274,7 +1441,7 @@
 	struct gmac *gm = (struct gmac *) dev->priv;
 	struct net_device_stats *stats = &gm->stats;
 
-	if (gm && gm->opened) {
+	if (gm && gm->opened && !gm->sleeping) {
 		stats->rx_crc_errors += GM_IN(GM_MAC_RX_CRC_ERR_CTR);
 		GM_OUT(GM_MAC_RX_CRC_ERR_CTR, 0);
 
@@ -1315,10 +1482,14 @@
 	     gmac = gmac->next)
 		gmac_probe1(gmac);
 
+#ifdef CONFIG_PMAC_PBOOK
+	if (gmacs)
+		pmu_register_sleep_notifier(&gmac_sleep_notifier);
+#endif
 
 	MOD_DEC_USE_COUNT;
 
-	return 0;
+	return gmacs? 0: -ENODEV;
 }
 
 static void
@@ -1343,6 +1514,14 @@
 		return;
 	}
 
+	if (dummy_buf == NULL) {
+		dummy_buf = kmalloc(DUMMY_BUF_LEN, GFP_KERNEL);
+		if (dummy_buf == NULL) {
+			printk(KERN_ERR "GMAC: failed to allocated dummy buffer\n");
+			return;
+		}
+	}
+
 	tx_descpage = get_free_page(GFP_KERNEL);
 	if (tx_descpage == 0) {
 		printk(KERN_ERR "GMAC: can't get a page for tx descriptors\n");
@@ -1351,17 +1530,13 @@
 	rx_descpage = get_free_page(GFP_KERNEL);
 	if (rx_descpage == 0) {
 		printk(KERN_ERR "GMAC: can't get a page for rx descriptors\n");
-		free_page(tx_descpage);
-		return;
+		goto out_txdesc;
 	}
 
 	dev = init_etherdev(NULL, sizeof(struct gmac));
-
 	if (!dev) {
 		printk(KERN_ERR "GMAC: init_etherdev failed, out of memory\n");
-		free_page(tx_descpage);
-		free_page(rx_descpage);
-		return;
+		goto out_rxdesc;
 	}
 	SET_MODULE_OWNER(dev);
 
@@ -1369,6 +1544,10 @@
 	dev->base_addr = gmac->addrs[0].address;
 	gm->regs = (volatile unsigned int *)
 		ioremap(gmac->addrs[0].address, 0x10000);
+	if (!gm->regs) {
+		printk(KERN_ERR "GMAC: unable to map I/O registers\n");
+		goto out_unreg;
+	}
 	dev->irq = gmac->intrs[0].line;
 	gm->dev = dev;
 	gm->of_node = gmac;
@@ -1394,6 +1573,7 @@
 
 	gm->phy_addr = 0;
 	gm->opened = 0;
+	gm->sleeping = 0;
 
 	dev->open = gmac_open;
 	dev->stop = gmac_close;
@@ -1404,13 +1584,18 @@
 	dev->watchdog_timeo = 5*HZ;
 
 	ether_setup(dev);
-	
+
 	gm->next_gmac = gmacs;
 	gmacs = dev;
+	return;
 
-#ifdef CONFIG_PMAC_PBOOK
-	pmu_register_sleep_notifier(&gmac_sleep_notifier);
-#endif
+out_unreg:
+	unregister_netdev(dev);
+	kfree(dev);
+out_rxdesc:
+	free_page(rx_descpage);
+out_txdesc:
+	free_page(tx_descpage);
 }
 
 MODULE_AUTHOR("Paul Mackerras/Ben Herrenschmidt");
@@ -1421,16 +1606,25 @@
 	struct gmac *gm;
 	struct net_device *dev;
 
+#ifdef CONFIG_PMAC_PBOOK
+	if (gmacs)
+		pmu_unregister_sleep_notifier(&gmac_sleep_notifier);
+#endif
+
 	while ((dev = gmacs) != NULL) {
 		gm = (struct gmac *) dev->priv;
 		unregister_netdev(dev);
+		iounmap((void *) gm->regs);
 		free_page(gm->tx_desc_page);
 		free_page(gm->rx_desc_page);
 		gmacs = gm->next_gmac;
 		kfree(dev);
 	}
+	if (dummy_buf != NULL) {
+		kfree(dummy_buf);
+		dummy_buf = NULL;
+	}
 }
 
 module_init(gmac_probe);
 module_exit(gmac_cleanup_module);
-
diff -urN linux-2.4.5-pre2/drivers/net/gmac.h linux/drivers/net/gmac.h
--- linux-2.4.5-pre2/drivers/net/gmac.h	Sun Sep 17 09:48:05 2000
+++ linux/drivers/net/gmac.h	Mon Dec  3 22:43:26 2001
@@ -722,6 +722,13 @@
 #define MII_ANLPA_CSMA 0x0001      /* CSMA-CD Capable */
 #define MII_ANLPA_PAUS 0x0400 
 
+/* Generic PHYs
+ * 
+ * These GENERIC values assumes that the PHY devices follow 802.3u and
+ * allow parallel detection to set the link partner ability register.
+ * Detection of 100Base-TX [H/F Duplex] and 100Base-T4 is supported.
+ */
+
 /*
  * Model-specific PHY registers
  *
@@ -731,6 +738,7 @@
 
 /* Supported PHYs (phy_type field ) */
 #define PHY_B5400	0x5400
+#define PHY_B5401	0x5401
 #define PHY_B5201	0x5201
 #define PHY_LXT971	0x0971
 #define PHY_UNKNOWN	0
@@ -741,11 +749,21 @@
 #define MII_BCM5201_REV                         0x01
 #define MII_BCM5201_ID                          ((MII_BCM5201_OUI << 10) | (MII_BCM5201_MODEL << 4))
 #define MII_BCM5201_MASK                        0xfffffff0
+#define MII_BCM5221_OUI                         0x001018
+#define MII_BCM5221_MODEL                       0x1e
+#define MII_BCM5221_REV                         0x00
+#define MII_BCM5221_ID                          ((MII_BCM5221_OUI << 10) | (MII_BCM5221_MODEL << 4))
+#define MII_BCM5221_MASK                        0xfffffff0
 #define MII_BCM5400_OUI                         0x000818
 #define MII_BCM5400_MODEL                       0x04
 #define MII_BCM5400_REV                         0x01
 #define MII_BCM5400_ID                          ((MII_BCM5400_OUI << 10) | (MII_BCM5400_MODEL << 4))
 #define MII_BCM5400_MASK                        0xfffffff0
+#define MII_BCM5401_OUI                         0x000818
+#define MII_BCM5401_MODEL                       0x05
+#define MII_BCM5401_REV                         0x01
+#define MII_BCM5401_ID                          ((MII_BCM5401_OUI << 10) | (MII_BCM5401_MODEL << 4))
+#define MII_BCM5401_MASK                        0xfffffff0
 #define MII_LXT971_OUI                          0x0004de
 #define MII_LXT971_MODEL                        0x0e
 #define MII_LXT971_REV                          0x00
@@ -791,7 +809,6 @@
 #define MII_LXT971_STATUS2_AUTONEG_COMPLETE	0x0080
 
 
-
 	/*
 	 * DMA descriptors
 	 */
@@ -877,6 +894,7 @@
 	u8				pci_devfn;
 	spinlock_t			lock;
 	int				opened;
+	int				sleeping;
 	struct net_device		*next_gmac;
 };
 
diff -urN linux-2.4.5-pre2/drivers/net/hp100.h linux/drivers/net/hp100.h
--- linux-2.4.5-pre2/drivers/net/hp100.h	Wed May 20 18:55:04 1998
+++ linux/drivers/net/hp100.h	Mon Dec  3 22:43:26 2001
@@ -38,10 +38,10 @@
 #define HP100_REG_HW_ID		0x00	/* R:  (16) Unique card ID           */
 #define HP100_REG_TRACE		0x00	/* W:  (16) Used for debug output    */
 #define HP100_REG_PAGING	0x02	/* R:  (16),15:4 Card ID             */
-                                        /* W:  (16),3:0 Switch pages         */
+					/* W:  (16),3:0 Switch pages         */
 #define HP100_REG_OPTION_LSW	0x04	/* RW: (16) Select card functions    */
 #define HP100_REG_OPTION_MSW	0x06	/* RW: (16) Select card functions    */
-                                        
+
 /*  Page 0 - Performance  */
 
 #define HP100_REG_IRQ_STATUS	0x08	/* RW: (16) Which ints are pending   */
@@ -53,27 +53,27 @@
 #define HP100_REG_DATA32	0x10	/* RW: (32) I/O mode data port       */
 #define HP100_REG_DATA16	0x12	/* RW: WORDs must be read from here  */
 #define HP100_REG_TX_MEM_FREE	0x14	/* RD: (32) Amount of free Tx mem    */
-#define HP100_REG_TX_PDA_L      0x14    /* W: (32) BM: Ptr to PDL, Low Pri  */
-#define HP100_REG_TX_PDA_H      0x1c    /* W: (32) BM: Ptr to PDL, High Pri */
+#define HP100_REG_TX_PDA_L      0x14	/* W: (32) BM: Ptr to PDL, Low Pri  */
+#define HP100_REG_TX_PDA_H      0x1c	/* W: (32) BM: Ptr to PDL, High Pri */
 #define HP100_REG_RX_PKT_CNT	0x18	/* RD: (8) Rx count of pkts on card  */
 #define HP100_REG_TX_PKT_CNT	0x19	/* RD: (8) Tx count of pkts on card  */
-#define HP100_REG_RX_PDL        0x1a    /* R: (8) BM: # rx pdl not executed */
-#define HP100_REG_TX_PDL        0x1b    /* R: (8) BM: # tx pdl not executed */
-#define HP100_REG_RX_PDA        0x18    /* W: (32) BM: Up to 31 addresses */
-                                        /*             which point to a PDL */
-#define HP100_REG_SL_EARLY      0x1c    /*    (32) Enhanced Slave Early Rx */
-#define HP100_REG_STAT_DROPPED  0x20    /* R (12) Dropped Packet Counter */
-#define HP100_REG_STAT_ERRORED  0x22    /* R (8) Errored Packet Counter */
-#define HP100_REG_STAT_ABORT    0x23    /* R (8) Abort Counter/OW Coll. Flag */
-#define HP100_REG_RX_RING       0x24    /* W (32) Slave: RX Ring Pointers */
-#define HP100_REG_32_FRAGMENT_LEN 0x28  /* W (13) Slave: Fragment Length Reg */
-#define HP100_REG_32_OFFSET     0x2c    /* W (16) Slave: Offset Register */
+#define HP100_REG_RX_PDL        0x1a	/* R: (8) BM: # rx pdl not executed */
+#define HP100_REG_TX_PDL        0x1b	/* R: (8) BM: # tx pdl not executed */
+#define HP100_REG_RX_PDA        0x18	/* W: (32) BM: Up to 31 addresses */
+					/*             which point to a PDL */
+#define HP100_REG_SL_EARLY      0x1c	/*    (32) Enhanced Slave Early Rx */
+#define HP100_REG_STAT_DROPPED  0x20	/* R (12) Dropped Packet Counter */
+#define HP100_REG_STAT_ERRORED  0x22	/* R (8) Errored Packet Counter */
+#define HP100_REG_STAT_ABORT    0x23	/* R (8) Abort Counter/OW Coll. Flag */
+#define HP100_REG_RX_RING       0x24	/* W (32) Slave: RX Ring Pointers */
+#define HP100_REG_32_FRAGMENT_LEN 0x28	/* W (13) Slave: Fragment Length Reg */
+#define HP100_REG_32_OFFSET     0x2c	/* W (16) Slave: Offset Register */
 
 /*  Page 1 - MAC Address/Hash Table  */
 
-#define HP100_REG_MAC_ADDR	0x08	/* RW: (8) Cards MAC address	     */
+#define HP100_REG_MAC_ADDR	0x08	/* RW: (8) Cards MAC address         */
 #define HP100_REG_HASH_BYTE0	0x10	/* RW: (8) Cards multicast filter    */
-                                        
+
 /*  Page 2 - Hardware Mapping  */
 
 #define HP100_REG_MEM_MAP_LSW	0x08	/* RW: (16) LSW of cards mem addr    */
@@ -84,44 +84,44 @@
 #define HP100_REG_BM		0x0f	/* RW: (8) Controls BM functions     */
 
 /* New on Page 2 for ETR chips: */
-#define HP100_REG_MODECTRL1     0x10    /* RW: (8) Mode Control 1 */
-#define HP100_REG_MODECTRL2     0x11    /* RW: (8) Mode Control 2 */
-#define HP100_REG_PCICTRL1      0x12    /* RW: (8) PCI Cfg 1 */
-#define HP100_REG_PCICTRL2      0x13    /* RW: (8) PCI Cfg 2 */
-#define HP100_REG_PCIBUSMLAT    0x15    /* RW: (8) PCI Bus Master Latency */
-#define HP100_REG_EARLYTXCFG    0x16    /* RW: (16) Early TX Cfg/Cntrl Reg */
-#define HP100_REG_EARLYRXCFG    0x18    /* RW: (8) Early RX Cfg/Cntrl Reg */
-#define HP100_REG_ISAPNPCFG1    0x1a    /* RW: (8) ISA PnP Cfg/Cntrl Reg 1 */
-#define HP100_REG_ISAPNPCFG2    0x1b    /* RW: (8) ISA PnP Cfg/Cntrl Reg 2 */
-                                        
+#define HP100_REG_MODECTRL1     0x10	/* RW: (8) Mode Control 1 */
+#define HP100_REG_MODECTRL2     0x11	/* RW: (8) Mode Control 2 */
+#define HP100_REG_PCICTRL1      0x12	/* RW: (8) PCI Cfg 1 */
+#define HP100_REG_PCICTRL2      0x13	/* RW: (8) PCI Cfg 2 */
+#define HP100_REG_PCIBUSMLAT    0x15	/* RW: (8) PCI Bus Master Latency */
+#define HP100_REG_EARLYTXCFG    0x16	/* RW: (16) Early TX Cfg/Cntrl Reg */
+#define HP100_REG_EARLYRXCFG    0x18	/* RW: (8) Early RX Cfg/Cntrl Reg */
+#define HP100_REG_ISAPNPCFG1    0x1a	/* RW: (8) ISA PnP Cfg/Cntrl Reg 1 */
+#define HP100_REG_ISAPNPCFG2    0x1b	/* RW: (8) ISA PnP Cfg/Cntrl Reg 2 */
+
 /*  Page 3 - EEPROM/Boot ROM  */
 
 #define HP100_REG_EEPROM_CTRL	0x08	/* RW: (16) Used to load EEPROM      */
 #define HP100_REG_BOOTROM_CTRL  0x0a
-                                        
+
 /*  Page 4 - LAN Configuration  (MAC_CTRL) */
 
 #define HP100_REG_10_LAN_CFG_1	0x08	/* RW: (8) Set 10M XCVR functions   */
-#define HP100_REG_10_LAN_CFG_2  0x09    /* RW: (8)     10M XCVR functions   */
+#define HP100_REG_10_LAN_CFG_2  0x09	/* RW: (8)     10M XCVR functions   */
 #define HP100_REG_VG_LAN_CFG_1	0x0a	/* RW: (8) Set 100M XCVR functions  */
-#define HP100_REG_VG_LAN_CFG_2  0x0b    /* RW: (8) 100M LAN Training cfgregs */
+#define HP100_REG_VG_LAN_CFG_2  0x0b	/* RW: (8) 100M LAN Training cfgregs */
 #define HP100_REG_MAC_CFG_1	0x0c	/* RW: (8) Types of pkts to accept   */
 #define HP100_REG_MAC_CFG_2	0x0d	/* RW: (8) Misc MAC functions        */
-#define HP100_REG_MAC_CFG_3     0x0e    /* RW: (8) Misc MAC functions */
-#define HP100_REG_MAC_CFG_4     0x0f    /* R:  (8) Misc MAC states */
-#define HP100_REG_DROPPED	0x10	/* R:  (16),11:0 Pkts cant fit in mem*/
+#define HP100_REG_MAC_CFG_3     0x0e	/* RW: (8) Misc MAC functions */
+#define HP100_REG_MAC_CFG_4     0x0f	/* R:  (8) Misc MAC states */
+#define HP100_REG_DROPPED	0x10	/* R:  (16),11:0 Pkts cant fit in mem */
 #define HP100_REG_CRC		0x12	/* R:  (8) Pkts with CRC             */
 #define HP100_REG_ABORT		0x13	/* R:  (8) Aborted Tx pkts           */
-#define HP100_REG_TRAIN_REQUEST 0x14    /* RW: (16) Endnode MAC register.*/
-#define HP100_REG_TRAIN_ALLOW   0x16    /* R:  (16) Hub allowed register */
-                    
+#define HP100_REG_TRAIN_REQUEST 0x14	/* RW: (16) Endnode MAC register. */
+#define HP100_REG_TRAIN_ALLOW   0x16	/* R:  (16) Hub allowed register */
+
 /*  Page 5 - MMU  */
 
 #define HP100_REG_RX_MEM_STOP	0x0c	/* RW: (16) End of Rx ring addr      */
 #define HP100_REG_TX_MEM_STOP	0x0e	/* RW: (16) End of Tx ring addr      */
-#define HP100_REG_PDL_MEM_STOP  0x10    /* Not used by 802.12 devices */
-#define HP100_REG_ECB_MEM_STOP  0x14    /* I've no idea what this is */
-          
+#define HP100_REG_PDL_MEM_STOP  0x10	/* Not used by 802.12 devices */
+#define HP100_REG_ECB_MEM_STOP  0x14	/* I've no idea what this is */
+
 /*  Page 6 - Card ID/Physical LAN Address  */
 
 #define HP100_REG_BOARD_ID	0x08	/* R:  (8) EISA/ISA card ID          */
@@ -129,7 +129,7 @@
 #define HP100_REG_SOFT_MODEL	0x0d	/* R:  (8) Config program defined    */
 #define HP100_REG_LAN_ADDR	0x10	/* R:  (8) MAC addr of card          */
 #define HP100_REG_LAN_ADDR_CHCK 0x16	/* R:  (8) Added to addr to get FFh  */
-                                        
+
 /*  Page 7 - MMU Current Pointers  */
 
 #define HP100_REG_PTR_RXSTART	0x08	/* R:  (16) Current begin of Rx ring */
@@ -146,7 +146,7 @@
 /* 
  * Hardware ID Register I (Always available, HW_ID, Offset 0x00)
  */
-#define HP100_HW_ID_CASCADE     0x4850  /* Identifies Cascade Chip */
+#define HP100_HW_ID_CASCADE     0x4850	/* Identifies Cascade Chip */
 
 /* 
  * Hardware ID Register 2 & Paging Register
@@ -154,12 +154,12 @@
  * Bits 15:4 are for the Chip ID 
  */
 #define HP100_CHIPID_MASK        0xFFF0
-#define HP100_CHIPID_SHASTA      0x5350  /* Not 802.12 compliant */
-                                         /* EISA BM/SL, MCA16/32 SL, ISA SL */
-#define HP100_CHIPID_RAINIER     0x5360  /* Not 802.12 compliant EISA BM,*/
-                                         /* PCI SL, MCA16/32 SL, ISA SL */
-#define HP100_CHIPID_LASSEN      0x5370  /* 802.12 compliant PCI BM, PCI SL */
-                                         /* LRF supported */
+#define HP100_CHIPID_SHASTA      0x5350	/* Not 802.12 compliant */
+					 /* EISA BM/SL, MCA16/32 SL, ISA SL */
+#define HP100_CHIPID_RAINIER     0x5360	/* Not 802.12 compliant EISA BM, */
+					 /* PCI SL, MCA16/32 SL, ISA SL */
+#define HP100_CHIPID_LASSEN      0x5370	/* 802.12 compliant PCI BM, PCI SL */
+					 /* LRF supported */
 
 /*
  *  Option Registers I and II 
@@ -167,24 +167,24 @@
  */
 #define HP100_DEBUG_EN		0x8000	/* 0:Dis., 1:Enable Debug Dump Ptr. */
 #define HP100_RX_HDR		0x4000	/* 0:Dis., 1:Enable putting pkt into */
-                                        /*   system mem. before Rx interrupt */
+					/*   system mem. before Rx interrupt */
 #define HP100_MMAP_DIS		0x2000	/* 0:Enable, 1:Disable mem.mapping. */
-                                        /*   MMAP_DIS must be 0 and MEM_EN */
-                                        /*   must be 1 for memory-mapped */
-                                        /*   mode to be enabled */
+					/*   MMAP_DIS must be 0 and MEM_EN */
+					/*   must be 1 for memory-mapped */
+					/*   mode to be enabled */
 #define HP100_EE_EN		0x1000	/* 0:Disable,1:Enable EEPROM writing */
 #define HP100_BM_WRITE		0x0800	/* 0:Slave, 1:Bus Master for Tx data */
 #define HP100_BM_READ		0x0400	/* 0:Slave, 1:Bus Master for Rx data */
 #define HP100_TRI_INT		0x0200	/* 0:Don't, 1:Do tri-state the int */
 #define HP100_MEM_EN		0x0040	/* Config program set this to */
-                                        /*   0:Disable, 1:Enable mem map. */
-                                        /*   See MMAP_DIS. */
+					/*   0:Disable, 1:Enable mem map. */
+					/*   See MMAP_DIS. */
 #define HP100_IO_EN		0x0020	/* 1:Enable I/O transfers */
 #define HP100_BOOT_EN		0x0010	/* 1:Enable boot ROM access */
 #define HP100_FAKE_INT		0x0008	/* 1:int */
 #define HP100_INT_EN		0x0004	/* 1:Enable ints from card */
 #define HP100_HW_RST		0x0002	/* 0:Reset, 1:Out of reset */
-                                        /* NIC reset on 0 to 1 transition */
+					/* NIC reset on 0 to 1 transition */
 
 /*
  *  Option Register III 
@@ -193,9 +193,9 @@
 #define HP100_PRIORITY_TX	0x0080	/* 1:Do all Tx pkts as priority */
 #define HP100_EE_LOAD		0x0040	/* 1:EEPROM loading, 0 when done */
 #define HP100_ADV_NXT_PKT	0x0004	/* 1:Advance to next pkt in Rx queue */
-                                        /*   h/w will set to 0 when done */
+					/*   h/w will set to 0 when done */
 #define HP100_TX_CMD		0x0002	/* 1:Tell h/w download done, h/w */
-                                        /*   will set to 0 when done */
+					/*   will set to 0 when done */
 
 /*
  * Interrupt Status Registers I and II
@@ -208,10 +208,10 @@
 #define HP100_RX_PDL_FILL_COMPL 0x0800
 #define HP100_RX_PACKET		0x0400	/* 0:No, 1:Yes pkt has been Rx */
 #define HP100_RX_ERROR		0x0200	/* 0:No, 1:Yes Rx pkt had error */
-#define HP100_TX_PDA_ZERO       0x0020  /* 1 when PDA count goes to zero */
+#define HP100_TX_PDA_ZERO       0x0020	/* 1 when PDA count goes to zero */
 #define HP100_TX_SPACE_AVAIL	0x0010	/* 0:<8192, 1:>=8192 Tx free bytes */
 #define HP100_TX_COMPLETE	0x0008	/* 0:No, 1:Yes a Tx has completed */
-#define HP100_MISC_ERROR        0x0004  /* 0:No, 1:Lan Link down or bus error*/
+#define HP100_MISC_ERROR        0x0004	/* 0:No, 1:Lan Link down or bus error */
 #define HP100_TX_ERROR		0x0002	/* 0:No, 1:Yes Tx pkt had error */
 
 /*
@@ -229,7 +229,7 @@
 #define HP100_IRQ_SCRAMBLE      0x40
 #define HP100_BOND_HP           0x20
 #define HP100_LEVEL_IRQ		0x10	/* 0:Edge, 1:Level type interrupts. */
-                                        /* (Only valid on EISA cards) */
+					/* (Only valid on EISA cards) */
 #define HP100_IRQMASK		0x0F	/* Isolate the IRQ bits */
 
 /*
@@ -237,20 +237,20 @@
  * (Page HW_MAP, SRAM, Offset 0x0e)
  */
 #define HP100_RAM_SIZE_MASK	0xe0	/* AND to get SRAM size index */
-#define HP100_RAM_SIZE_SHIFT	0x05	/* Shift count(put index in lwr bits)*/
+#define HP100_RAM_SIZE_SHIFT	0x05	/* Shift count(put index in lwr bits) */
 
 /*
  * Bus Master Register
  * (Page HW_MAP, BM, Offset 0x0f)
  */
-#define HP100_BM_BURST_RD       0x01    /* EISA only: 1=Use burst trans. fm system */
-                                        /* memory to chip (tx) */
-#define HP100_BM_BURST_WR       0x02    /* EISA only: 1=Use burst trans. fm system */
-                                        /* memory to chip (rx) */
+#define HP100_BM_BURST_RD       0x01	/* EISA only: 1=Use burst trans. fm system */
+					/* memory to chip (tx) */
+#define HP100_BM_BURST_WR       0x02	/* EISA only: 1=Use burst trans. fm system */
+					/* memory to chip (rx) */
 #define HP100_BM_MASTER		0x04	/* 0:Slave, 1:BM mode */
-#define HP100_BM_PAGE_CK        0x08    /* This bit should be set whenever in*/
-                                        /* an EISA system */
-#define HP100_BM_PCI_8CLK       0x40    /* ... cycles 8 clocks apart */
+#define HP100_BM_PAGE_CK        0x08	/* This bit should be set whenever in */
+					/* an EISA system */
+#define HP100_BM_PCI_8CLK       0x40	/* ... cycles 8 clocks apart */
 
 
 /* 
@@ -258,82 +258,82 @@
  * (Page HW_MAP, MODECTRL1, Offset0x10)
  */
 #define HP100_TX_DUALQ          0x10
-   /* If set and BM -> dual tx pda queues*/
-#define HP100_ISR_CLRMODE       0x02   /* If set ISR will clear all pending */
-                                       /* interrupts on read (etr only?) */
-#define HP100_EE_NOLOAD         0x04   /* Status whether res will be loaded */
-                                       /* from the eeprom */
-#define HP100_TX_CNT_FLG        0x08   /* Controls Early TX Reg Cnt Field */
-#define HP100_PDL_USE3          0x10   /* If set BM engine will read only */
-                                       /* first three data elements of a PDL */
-                                       /* on the first access. */
-#define HP100_BUSTYPE_MASK      0xe0   /* Three bit bus type info */
+   /* If set and BM -> dual tx pda queues */
+#define HP100_ISR_CLRMODE       0x02	/* If set ISR will clear all pending */
+				       /* interrupts on read (etr only?) */
+#define HP100_EE_NOLOAD         0x04	/* Status whether res will be loaded */
+				       /* from the eeprom */
+#define HP100_TX_CNT_FLG        0x08	/* Controls Early TX Reg Cnt Field */
+#define HP100_PDL_USE3          0x10	/* If set BM engine will read only */
+				       /* first three data elements of a PDL */
+				       /* on the first access. */
+#define HP100_BUSTYPE_MASK      0xe0	/* Three bit bus type info */
 
 /*
  * Mode Control Register II
  * (Page HW_MAP, MODECTRL2, Offset0x11)
  */
-#define HP100_EE_MASK           0x0f   /* Tell EEPROM circuit not to load */ 
-                                       /* certain resources */
-#define HP100_DIS_CANCEL        0x20   /* For tx dualq mode operation */
-#define HP100_EN_PDL_WB         0x40   /* 1: Status of PDL completion may be */
-                                       /* written back to system mem */
-#define HP100_EN_BUS_FAIL       0x80   /* Enables bus-fail portion of misc */
-                                       /* interrupt */
+#define HP100_EE_MASK           0x0f	/* Tell EEPROM circuit not to load */
+				       /* certain resources */
+#define HP100_DIS_CANCEL        0x20	/* For tx dualq mode operation */
+#define HP100_EN_PDL_WB         0x40	/* 1: Status of PDL completion may be */
+				       /* written back to system mem */
+#define HP100_EN_BUS_FAIL       0x80	/* Enables bus-fail portion of misc */
+				       /* interrupt */
 
 /* 
  * PCI Configuration and Control Register I
  * (Page HW_MAP, PCICTRL1, Offset 0x12)
  */
-#define HP100_LO_MEM            0x01   /* 1: Mapped Mem requested below 1MB */
-#define HP100_NO_MEM            0x02   /* 1: Disables Req for sysmem to PCI */ 
-                                       /* bios */
-#define HP100_USE_ISA           0x04   /* 1: isa type decodes will occur */
-                                       /* simultaneously with PCI decodes */
-#define HP100_IRQ_HI_MASK       0xf0   /* pgmed by pci bios */
-#define HP100_PCI_IRQ_HI_MASK   0x78    /* Isolate 4 bits for PCI IRQ  */
- 
+#define HP100_LO_MEM            0x01	/* 1: Mapped Mem requested below 1MB */
+#define HP100_NO_MEM            0x02	/* 1: Disables Req for sysmem to PCI */
+				       /* bios */
+#define HP100_USE_ISA           0x04	/* 1: isa type decodes will occur */
+				       /* simultaneously with PCI decodes */
+#define HP100_IRQ_HI_MASK       0xf0	/* pgmed by pci bios */
+#define HP100_PCI_IRQ_HI_MASK   0x78	/* Isolate 4 bits for PCI IRQ  */
+
 /*
  * PCI Configuration and Control Register II
  * (Page HW_MAP, PCICTRL2, Offset 0x13)
  */
-#define HP100_RD_LINE_PDL       0x01   /* 1: PCI command Memory Read Line en */
-#define HP100_RD_TX_DATA_MASK   0x06   /* choose PCI memread cmds for TX */ 
-#define HP100_MWI               0x08   /* 1: en. PCI memory write invalidate */
-#define HP100_ARB_MODE          0x10   /* Select PCI arbitor type */
-#define HP100_STOP_EN           0x20   /* Enables PCI state machine to issue */
-                                       /* pci stop if cascade not ready */
-#define HP100_IGNORE_PAR        0x40   /* 1: PCI state machine ignores parity*/
-#define HP100_PCI_RESET         0x80   /* 0->1: Reset PCI block */
+#define HP100_RD_LINE_PDL       0x01	/* 1: PCI command Memory Read Line en */
+#define HP100_RD_TX_DATA_MASK   0x06	/* choose PCI memread cmds for TX */
+#define HP100_MWI               0x08	/* 1: en. PCI memory write invalidate */
+#define HP100_ARB_MODE          0x10	/* Select PCI arbitor type */
+#define HP100_STOP_EN           0x20	/* Enables PCI state machine to issue */
+				       /* pci stop if cascade not ready */
+#define HP100_IGNORE_PAR        0x40	/* 1: PCI state machine ignores parity */
+#define HP100_PCI_RESET         0x80	/* 0->1: Reset PCI block */
 
 /*
  * Early TX Configuration and Control Register
  * (Page HW_MAP, EARLYTXCFG, Offset 0x16)
  */
-#define HP100_EN_EARLY_TX       0x8000  /* 1=Enable Early TX */
-#define HP100_EN_ADAPTIVE       0x4000  /* 1=Enable adaptive mode */
-#define HP100_EN_TX_UR_IRQ      0x2000  /* reserved, must be 0 */
-#define HP100_EN_LOW_TX         0x1000  /* reserved, must be 0 */
-#define HP100_ET_CNT_MASK       0x0fff  /* bits 11..0: ET counters */
+#define HP100_EN_EARLY_TX       0x8000	/* 1=Enable Early TX */
+#define HP100_EN_ADAPTIVE       0x4000	/* 1=Enable adaptive mode */
+#define HP100_EN_TX_UR_IRQ      0x2000	/* reserved, must be 0 */
+#define HP100_EN_LOW_TX         0x1000	/* reserved, must be 0 */
+#define HP100_ET_CNT_MASK       0x0fff	/* bits 11..0: ET counters */
 
 /*
  * Early RX Configuration and Control Register
  * (Page HW_MAP, EARLYRXCFG, Offset 0x18)
  */
-#define HP100_EN_EARLY_RX       0x80     /* 1=Enable Early RX */
-#define HP100_EN_LOW_RX         0x40     /* reserved, must be 0 */
-#define HP100_RX_TRIP_MASK      0x1f     /* bits 4..0: threshold at which the
-					  * early rx circuit will start the
-					  * dma of received packet into system
-					  * memory for BM */
+#define HP100_EN_EARLY_RX       0x80	/* 1=Enable Early RX */
+#define HP100_EN_LOW_RX         0x40	/* reserved, must be 0 */
+#define HP100_RX_TRIP_MASK      0x1f	/* bits 4..0: threshold at which the
+					 * early rx circuit will start the
+					 * dma of received packet into system
+					 * memory for BM */
 
 /*
  *  Serial Devices Control Register
  * (Page EEPROM_CTRL, EEPROM_CTRL, Offset 0x08)
  */
 #define HP100_EEPROM_LOAD	0x0001	/* 0->1 loads EEPROM into registers. */
-                                        /* When it goes back to 0, load is   */
-                                        /* complete. This should take ~600us.*/
+					/* When it goes back to 0, load is   */
+					/* complete. This should take ~600us. */
 
 /*
  * 10MB LAN Control and Configuration Register I
@@ -345,7 +345,7 @@
 #define HP100_LINK_BEAT_DIS	0x08	/* 0:Enable, 1:Disable link beat */
 #define HP100_LINK_BEAT_ST	0x04	/* 0:No, 1:Yes link beat being Rx */
 #define HP100_R_ROL_ST		0x02	/* 0:No, 1:Yes Rx twisted pair has */
-                                        /*             been reversed */
+					/*             been reversed */
 #define HP100_AUI_ST		0x01	/* 0:No, 1:Yes use AUI on TP card */
 
 /*
@@ -353,9 +353,9 @@
  * (Page MAC_CTRL, 10_LAN_CFG_2, Offset 0x09)
  */
 #define HP100_SQU_ST		0x01	/* 0:No, 1:Yes collision signal sent */
-                                        /*       after Tx.Only used for AUI. */
-#define HP100_FULLDUP           0x02    /* 1: LXT901 XCVR fullduplx enabled */
-#define HP100_DOT3_MAC          0x04    /* 1: DOT 3 Mac sel. unless Autosel */
+					/*       after Tx.Only used for AUI. */
+#define HP100_FULLDUP           0x02	/* 1: LXT901 XCVR fullduplx enabled */
+#define HP100_DOT3_MAC          0x04	/* 1: DOT 3 Mac sel. unless Autosel */
 
 /*
  * MAC Selection, use with MAC10_SEL bits
@@ -372,9 +372,9 @@
 #define HP100_FRAME_FORMAT	0x08	/* 0:802.3, 1:802.5 frames */
 #define HP100_BRIDGE		0x04	/* 0:No, 1:Yes tell hub i am a bridge */
 #define HP100_PROM_MODE		0x02	/* 0:No, 1:Yes tell hub card is */
-                                        /*         promiscuous */
+					/*         promiscuous */
 #define HP100_REPEATER		0x01	/* 0:No, 1:Yes tell hub MAC wants to */
-                                        /*         be a cascaded repeater */
+					/*         be a cascaded repeater */
 
 /*
  * 100MB LAN Control and Configuration Register
@@ -383,16 +383,16 @@
 #define HP100_VG_SEL	        0x80	/* 0:No, 1:Yes use 100 Mbit MAC */
 #define HP100_LINK_UP_ST	0x40	/* 0:No, 1:Yes endnode logged in */
 #define HP100_LINK_CABLE_ST	0x20	/* 0:No, 1:Yes cable can hear tones */
-                                        /*         from  hub */
+					/*         from  hub */
 #define HP100_LOAD_ADDR		0x10	/* 0->1 card addr will be sent  */
-                                        /* 100ms later the link status  */
-                                        /* bits are valid */
+					/* 100ms later the link status  */
+					/* bits are valid */
 #define HP100_LINK_CMD		0x08	/* 0->1 link will attempt to log in. */
-                                        /* 100ms later the link status */
-                                        /* bits are valid */
-#define HP100_TRN_DONE          0x04    /* NEW ETR-Chips only: Will be reset */
-                                        /* after LinkUp Cmd is given and set */
-                                        /* when training has completed. */
+					/* 100ms later the link status */
+					/* bits are valid */
+#define HP100_TRN_DONE          0x04	/* NEW ETR-Chips only: Will be reset */
+					/* after LinkUp Cmd is given and set */
+					/* when training has completed. */
 #define HP100_LINK_GOOD_ST	0x02	/* 0:No, 1:Yes cable passed training */
 #define HP100_VG_RESET		0x01	/* 0:Yes, 1:No reset the 100VG MAC */
 
@@ -414,7 +414,7 @@
 #define HP100_MAC1MODE2		0x00
 #define HP100_MAC1MODE3		HP100_MAC1MODE2 | HP100_ACC_BC
 #define HP100_MAC1MODE4		HP100_MAC1MODE3 | HP100_ACC_MC
-#define HP100_MAC1MODE5		HP100_MAC1MODE4 /* set mc hash to all ones also */
+#define HP100_MAC1MODE5		HP100_MAC1MODE4	/* set mc hash to all ones also */
 #define HP100_MAC1MODE6		HP100_MAC1MODE5 | HP100_ACC_PHY	/* Promiscuous */
 /* Note MODE6 will receive all GOOD packets on the LAN. This really needs
    a mode 7 defined to be LAN Analyzer mode, which will receive errored and
@@ -428,14 +428,14 @@
 #define HP100_TR_MODE		0x80	/* 0:No, 1:Yes support Token Ring formats */
 #define HP100_TX_SAME		0x40	/* 0:No, 1:Yes Tx same packet continuous */
 #define HP100_LBK_XCVR		0x20	/* 0:No, 1:Yes loopback through MAC & */
-                                        /*   transceiver */
+					/*   transceiver */
 #define HP100_LBK_MAC		0x10	/* 0:No, 1:Yes loopback through MAC */
 #define HP100_CRC_I		0x08	/* 0:No, 1:Yes inhibit CRC on Tx packets */
-#define HP100_ACCNA             0x04    /* 1: For 802.5: Accept only token ring
+#define HP100_ACCNA             0x04	/* 1: For 802.5: Accept only token ring
 					 * group addr that maches NA mask */
 #define HP100_KEEP_CRC		0x02	/* 0:No, 1:Yes keep CRC on Rx packets. */
-                                        /*   The length will reflect this. */
-#define HP100_ACCFA             0x01    /* 1: For 802.5: Accept only functional
+					/*   The length will reflect this. */
+#define HP100_ACCFA             0x01	/* 1: For 802.5: Accept only functional
 					 * addrs that match FA mask (page1) */
 #define HP100_MAC2MODEMASK	0x02
 #define HP100_MAC2MODE1		0x00
@@ -450,58 +450,58 @@
  * MAC Configuration Register III 
  * (Page MAC_CTRL, MAC_CFG_3, Offset 0x0e) 
  */
-#define HP100_PACKET_PACE       0x03     /* Packet Pacing:
-					  * 00: No packet pacing
-                                          * 01: 8 to 16 uS delay
-                                          * 10: 16 to 32 uS delay
-                                          * 11: 32 to 64 uS delay
-					  */
-#define HP100_LRF_EN            0x04     /* 1: External LAN Rcv Filter and
-					  * TCP/IP Checksumming enabled. */
-#define HP100_AUTO_MODE         0x10     /* 1: AutoSelect between 10/100 */
+#define HP100_PACKET_PACE       0x03	/* Packet Pacing:
+					 * 00: No packet pacing
+					 * 01: 8 to 16 uS delay
+					 * 10: 16 to 32 uS delay
+					 * 11: 32 to 64 uS delay
+					 */
+#define HP100_LRF_EN            0x04	/* 1: External LAN Rcv Filter and
+					 * TCP/IP Checksumming enabled. */
+#define HP100_AUTO_MODE         0x10	/* 1: AutoSelect between 10/100 */
 
 /*
  * MAC Configuration Register IV 
  * (Page MAC_CTRL, MAC_CFG_4, Offset 0x0f)
  */
-#define HP100_MAC_SEL_ST        0x01      /* (R): Status of external VGSEL
-					   * Signal, 1=100VG, 0=10Mbit sel. */
-#define HP100_LINK_FAIL_ST      0x02      /* (R): Status of Link Fail portion
-                                           * of the Misc. Interrupt */
+#define HP100_MAC_SEL_ST        0x01	/* (R): Status of external VGSEL
+					 * Signal, 1=100VG, 0=10Mbit sel. */
+#define HP100_LINK_FAIL_ST      0x02	/* (R): Status of Link Fail portion
+					 * of the Misc. Interrupt */
 
 /* 
  *  100 MB LAN Training Request/Allowed Registers 
  * (Page MAC_CTRL, TRAIN_REQUEST and TRAIN_ALLOW, Offset 0x14-0x16)(ETR parts only)
  */
-#define HP100_MACRQ_REPEATER         0x0001  /* 1: MAC tells HUB it wants to be 
-				              *    a cascaded repeater
-					      * 0: ... wants to be a DTE */
-#define HP100_MACRQ_PROMSC           0x0006  /* 2 bits: Promiscious mode
-					      * 00: Rcv only unicast packets
-					      *     specifically addr to this
-					      *     endnode
-					      * 10: Rcv all pckts fwded by 
-					      *     the local repeater */
-#define HP100_MACRQ_FRAMEFMT_EITHER  0x0018  /* 11: either format allowed */
-#define HP100_MACRQ_FRAMEFMT_802_3   0x0000  /* 00: 802.3 is requested */
-#define HP100_MACRQ_FRAMEFMT_802_5   0x0010  /* 10: 802.5 format is requested */
-#define HP100_CARD_MACVER            0xe000  /* R: 3 bit Cards 100VG MAC version */
-#define HP100_MALLOW_REPEATER        0x0001  /* If reset, requested access as an
-					      * end node is allowed */
-#define HP100_MALLOW_PROMSC          0x0004  /* 2 bits: Promiscious mode
-					      * 00: Rcv only unicast packets
-					      *     specifically addr to this
-					      *     endnode
-					      * 10: Rcv all pckts fwded by 
-					      *     the local repeater */
-#define HP100_MALLOW_FRAMEFMT        0x00e0  /* 2 bits: Frame Format
-					      * 00: 802.3 format will be used
-					      * 10: 802.5 format will be used */
-#define HP100_MALLOW_ACCDENIED       0x0400  /* N bit */
-#define HP100_MALLOW_CONFIGURE       0x0f00  /* C bit */
-#define HP100_MALLOW_DUPADDR         0x1000  /* D bit */
-#define HP100_HUB_MACVER             0xe000  /* R: 3 bit 802.12 MAC/RMAC training */
-                                             /*    protocol of repeater */
+#define HP100_MACRQ_REPEATER         0x0001	/* 1: MAC tells HUB it wants to be 
+						 *    a cascaded repeater
+						 * 0: ... wants to be a DTE */
+#define HP100_MACRQ_PROMSC           0x0006	/* 2 bits: Promiscious mode
+						 * 00: Rcv only unicast packets
+						 *     specifically addr to this
+						 *     endnode
+						 * 10: Rcv all pckts fwded by 
+						 *     the local repeater */
+#define HP100_MACRQ_FRAMEFMT_EITHER  0x0018	/* 11: either format allowed */
+#define HP100_MACRQ_FRAMEFMT_802_3   0x0000	/* 00: 802.3 is requested */
+#define HP100_MACRQ_FRAMEFMT_802_5   0x0010	/* 10: 802.5 format is requested */
+#define HP100_CARD_MACVER            0xe000	/* R: 3 bit Cards 100VG MAC version */
+#define HP100_MALLOW_REPEATER        0x0001	/* If reset, requested access as an
+						 * end node is allowed */
+#define HP100_MALLOW_PROMSC          0x0004	/* 2 bits: Promiscious mode
+						 * 00: Rcv only unicast packets
+						 *     specifically addr to this
+						 *     endnode
+						 * 10: Rcv all pckts fwded by 
+						 *     the local repeater */
+#define HP100_MALLOW_FRAMEFMT        0x00e0	/* 2 bits: Frame Format
+						 * 00: 802.3 format will be used
+						 * 10: 802.5 format will be used */
+#define HP100_MALLOW_ACCDENIED       0x0400	/* N bit */
+#define HP100_MALLOW_CONFIGURE       0x0f00	/* C bit */
+#define HP100_MALLOW_DUPADDR         0x1000	/* D bit */
+#define HP100_HUB_MACVER             0xe000	/* R: 3 bit 802.12 MAC/RMAC training */
+					     /*    protocol of repeater */
 
 /* ****************************************************************************** */
 
@@ -516,7 +516,7 @@
 /*
  *  Misc. Constants
  */
-#define HP100_LAN_100		100     /* lan_type value for VG */
+#define HP100_LAN_100		100	/* lan_type value for VG */
 #define HP100_LAN_10		10	/* lan_type value for 10BaseT */
 #define HP100_LAN_ERR		(-1)	/* lan_type value for link down */
 
@@ -528,10 +528,10 @@
  * Bus Master Data Structures  ----------------------------------------------
  */
 
-#define MAX_RX_PDL              30   /* Card limit = 31 */
-#define MAX_RX_FRAG             2    /* Don't need more... */
+#define MAX_RX_PDL              30	/* Card limit = 31 */
+#define MAX_RX_FRAG             2	/* Don't need more... */
 #define MAX_TX_PDL              29
-#define MAX_TX_FRAG             2   /* Limit = 31 */
+#define MAX_TX_FRAG             2	/* Limit = 31 */
 
 /* Define total PDL area size in bytes (should be 4096) */
 /* This is the size of kernel (dma) memory that will be allocated. */
@@ -539,16 +539,16 @@
 
 /* Ethernet Packet Sizes */
 #define MIN_ETHER_SIZE          60
-#define MAX_ETHER_SIZE          1514    /* Needed for preallocation of */
-                                        /* skb buffer when busmastering */
+#define MAX_ETHER_SIZE          1514	/* Needed for preallocation of */
+					/* skb buffer when busmastering */
 
 /* Tx or Rx Ring Entry */
 typedef struct hp100_ring {
-  u_int                     *pdl;       /* Address of PDLs PDH, dword before
-					 * this address is used for rx hdr */
-  u_int                     pdl_paddr;  /* Physical address of PDL */
-  struct sk_buff            *skb;
-  struct hp100_ring         *next;      
+	u_int *pdl;		/* Address of PDLs PDH, dword before
+				 * this address is used for rx hdr */
+	u_int pdl_paddr;	/* Physical address of PDL */
+	struct sk_buff *skb;
+	struct hp100_ring *next;
 } hp100_ring_t;
 
 
@@ -564,12 +564,12 @@
 #define HP100_SKEW_ERR		0x2000	/* 0:No, 1:Yes skew out of range */
 #define HP100_BAD_SYMBOL_ERR	0x1000	/* 0:No, 1:Yes invalid symbol received */
 #define HP100_RCV_IPM_ERR	0x0800	/* 0:No, 1:Yes pkt had an invalid packet */
-                                        /*   marker */
+					/*   marker */
 #define HP100_SYMBOL_BAL_ERR	0x0400	/* 0:No, 1:Yes symbol balance error */
 #define HP100_VG_ALN_ERR	0x0200	/* 0:No, 1:Yes non-octet received */
 #define HP100_TRUNC_ERR		0x0100	/* 0:No, 1:Yes the packet was truncated */
 #define HP100_RUNT_ERR		0x0040	/* 0:No, 1:Yes pkt length < Min Pkt */
-                                        /*   Length Reg. */
+					/*   Length Reg. */
 #define HP100_ALN_ERR		0x0010	/* 0:No, 1:Yes align error. */
 #define HP100_CRC_ERR		0x0008	/* 0:No, 1:Yes CRC occurred. */
 
@@ -616,11 +616,3 @@
 	outw( HP100_MMAP_DIS | HP100_RESET_HB, ioaddr + HP100_REG_OPTION_LSW )
 #define hp100_mem_map_disable() \
 	outw( HP100_MMAP_DIS | HP100_SET_HB, ioaddr + HP100_REG_OPTION_LSW )
-
-
-/*
- * Local variables:
- *  c-indent-level: 2
- *  tab-width: 8
- * End:
-*/
diff -urN linux-2.4.5-pre2/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
--- linux-2.4.5-pre2/drivers/net/ioc3-eth.c	Tue Mar 20 12:04:58 2001
+++ linux/drivers/net/ioc3-eth.c	Mon Dec  3 22:43:26 2001
@@ -402,7 +402,7 @@
 
 static struct net_device_stats *ioc3_get_stats(struct net_device *dev)
 {
-	struct ioc3_private *ip = (struct ioc3_private *) dev->priv;
+	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
 
 	ip->stats.collisions += (ioc3->etcdc & ETCDC_COLLCNT_MASK);
@@ -566,7 +566,7 @@
    after the Tx thread.  */
 static void ioc3_interrupt(int irq, void *_dev, struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *)_dev;
+	struct net_device *dev = _dev;
 	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
 	const u32 enabled = EISR_RXTIMERINT | EISR_RXOFLO | EISR_RXBUFOFLO |
@@ -595,7 +595,7 @@
 static void negotiate(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
-	struct ioc3_private *ip = (struct ioc3_private *) dev->priv;
+	struct ioc3_private *ip = dev->priv;
 	struct ioc3 *ioc3 = ip->regs;
 
 	mod_timer(&ip->negtimer, jiffies + 20 * HZ);
@@ -864,7 +864,7 @@
 		return -EAGAIN;
 	}
 
-	ip = (struct ioc3_private *) dev->priv;
+	ip = dev->priv;
 
 	ip->ehar_h = 0;
 	ip->ehar_l = 0;
@@ -1131,7 +1131,7 @@
 /* Provide ioctl() calls to examine the MII xcvr state. */
 static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct ioc3_private *ip = (struct ioc3_private *) dev->priv;
+	struct ioc3_private *ip = dev->priv;
 	u16 *data = (u16 *)&rq->ifr_data;
 	struct ioc3 *ioc3 = ip->regs;
 	int phy = ip->phy;
diff -urN linux-2.4.5-pre2/drivers/net/mace.c linux/drivers/net/mace.c
--- linux-2.4.5-pre2/drivers/net/mace.c	Thu Apr 12 12:15:25 2001
+++ linux/drivers/net/mace.c	Mon Dec  3 22:43:26 2001
@@ -21,6 +21,9 @@
 #include "mace.h"
 
 static struct net_device *mace_devs;
+static int port_aaui = -1;
+
+MODULE_PARM(port_aaui, "i");
 
 #define N_RX_RING	8
 #define N_TX_RING	6
@@ -53,6 +56,7 @@
     struct net_device_stats stats;
     struct timer_list tx_timeout;
     int timeout_active;
+    int port_aaui;
     struct net_device *next_mace;
 };
 
@@ -178,6 +182,21 @@
 	init_timer(&mp->tx_timeout);
 	mp->timeout_active = 0;
 
+	if (port_aaui >= 0)
+		mp->port_aaui = port_aaui;
+	else {
+		/* Apple Network Server uses the AAUI port */
+		if (machine_is_compatible("AAPL,ShinerESB"))
+			mp->port_aaui = 1;
+		else {
+#ifdef CONFIG_MACE_AAUI_PORT
+			mp->port_aaui = 1;
+#else
+			mp->port_aaui = 0;
+#endif			
+		}
+	}
+
 	dev->open = mace_open;
 	dev->stop = mace_close;
 	dev->hard_start_xmit = mace_xmit_start;
@@ -261,7 +280,10 @@
     /* done changing address */
     out_8(&mb->iac, 0);
 
-    out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
+    if (mp->port_aaui)
+    	out_8(&mb->plscc, PORTSEL_AUI + ENPLSIO);
+    else
+    	out_8(&mb->plscc, PORTSEL_GPSI + ENPLSIO);
 }
 
 static void __mace_set_address(struct net_device *dev, void *addr)
diff -urN linux-2.4.5-pre2/drivers/net/natsemi.c linux/drivers/net/natsemi.c
--- linux-2.4.5-pre2/drivers/net/natsemi.c	Fri Apr 20 11:54:23 2001
+++ linux/drivers/net/natsemi.c	Mon Dec  3 22:43:26 2001
@@ -92,6 +92,8 @@
 
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
+#define final_version
+
 #if !defined(__OPTIMIZE__)
 #warning  You must compile this file with the correct options!
 #warning  See the last lines of the source file.
diff -urN linux-2.4.5-pre2/drivers/net/net_init.c linux/drivers/net/net_init.c
--- linux-2.4.5-pre2/drivers/net/net_init.c	Wed Apr 18 14:40:06 2001
+++ linux/drivers/net/net_init.c	Mon Dec  3 22:43:26 2001
@@ -205,11 +205,12 @@
 }
 
 /**
- * alloc_etherdev - Register ethernet device
+ * alloc_etherdev - Allocates and sets up an ethernet device
  * @sizeof_priv: Size of additional driver-private structure to be allocated
  *	for this ethernet device
  *
- * Fill in the fields of the device structure with ethernet-generic values.
+ * Fill in the fields of the device structure with ethernet-generic
+ * values. Basically does everything except registering the device.
  *
  * Constructs a new net device, complete with a private data area of
  * size @sizeof_priv.  A 32-byte (not bit) alignment is enforced for
diff -urN linux-2.4.5-pre2/drivers/net/pppoe.c linux/drivers/net/pppoe.c
--- linux-2.4.5-pre2/drivers/net/pppoe.c	Tue Mar  6 19:44:35 2001
+++ linux/drivers/net/pppoe.c	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
  * PPPoE --- PPP over Ethernet (RFC 2516)
  *
  *
- * Version:    0.6.5
+ * Version:    0.6.6
  *
  * 030700 :     Fixed connect logic to allow for disconnect.
  * 270700 :	Fixed potential SMP problems; we must protect against
@@ -19,6 +19,7 @@
  * 051000 :	Initialization cleanup.
  * 111100 :	Fix recvmsg.
  * 050101 :	Fix PADT procesing.
+ * 140501 :	Use pppoe_rcv_core to handle all backlog. (Alexey)
  *
  * Author:	Michal Ostrowski <mostrows@styx.uwaterloo.ca>
  * Contributors:
@@ -376,22 +377,6 @@
 	return ret;
 }
 
-
-/************************************************************************
- *
- * Receive wrapper called in process context.
- *
- ***********************************************************************/
-int pppoe_backlog_rcv(struct sock *sk, struct sk_buff *skb)
-{
-	lock_sock(sk);
-	pppoe_rcv_core(sk, skb);
-	release_sock(sk);
-	return 0;
-}
-
-
-
 /************************************************************************
  *
  * Receive a PPPoE Discovery frame.
@@ -481,7 +466,7 @@
 	sk->protocol = PX_PROTO_OE;
 	sk->family = PF_PPPOX;
 
-	sk->backlog_rcv = pppoe_backlog_rcv;
+	sk->backlog_rcv = pppoe_rcv_core;
 	sk->next = NULL;
 	sk->pprev = NULL;
 	sk->state = PPPOX_NONE;
diff -urN linux-2.4.5-pre2/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- linux-2.4.5-pre2/drivers/net/sunhme.c	Thu Apr 26 22:17:26 2001
+++ linux/drivers/net/sunhme.c	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.117 2001/04/19 22:32:41 davem Exp $
+/* $Id: sunhme.c,v 1.118 2001/05/11 02:09:30 davem Exp $
  * sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
  *           auto carrier detecting ethernet driver.  Also known as the
  *           "Happy Meal Ethernet" found on SunSwift SBUS cards.
@@ -2206,6 +2206,7 @@
 static int happy_meal_open(struct net_device *dev)
 {
 	struct happy_meal *hp = dev->priv;
+	int res;
 
 	HMD(("happy_meal_open: "));
 
@@ -2229,7 +2230,10 @@
 	}
 
 	HMD(("to happy_meal_init\n"));
-	return happy_meal_init(hp, 0);
+	res = happy_meal_init(hp, 0);
+	if (res && ((hp->happy_flags & (HFLAG_QUATTRO|HFLAG_PCI)) != HFLAG_QUATTRO))
+		free_irq(dev->irq, dev);
+	return res;
 }
 
 static int happy_meal_close(struct net_device *dev)
@@ -2441,7 +2445,7 @@
 	if (copy_from_user(&ecmd, ep_user, sizeof(ecmd)))
 		return -EFAULT;
 
-	if (ecmd.cmd == SPARC_ETH_GSET) {
+	if (ecmd.cmd == ETHTOOL_GSET) {
 		ecmd.supported =
 			(SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
 			 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
@@ -2480,7 +2484,7 @@
 		if (copy_to_user(ep_user, &ecmd, sizeof(ecmd)))
 			return -EFAULT;
 		return 0;
-	} else if (ecmd.cmd == SPARC_ETH_SSET) {
+	} else if (ecmd.cmd == ETHTOOL_SSET) {
 		if (!capable(CAP_NET_ADMIN))
 			return -EPERM;
 
@@ -2864,7 +2868,7 @@
 	
 	prom_getstring(node, "name", prom_name, sizeof(prom_name));
 #else
-#warning This needs to be corrected... -DaveM
+/* This needs to be corrected... -DaveM */
 	strcpy(prom_name, "qfe");
 #endif
 
diff -urN linux-2.4.5-pre2/drivers/net/tokenring/ibmtr.h linux/drivers/net/tokenring/ibmtr.h
--- linux-2.4.5-pre2/drivers/net/tokenring/ibmtr.h	Thu Mar  2 10:15:30 2000
+++ linux/drivers/net/tokenring/ibmtr.h	Wed Dec 31 16:00:00 1969
@@ -1,454 +0,0 @@
-/* Definitions for an IBM Token Ring card. */
-/* This file is distributed under the GNU GPL   */
-
-/* ported to the Alpha architecture 02/20/96 (just used the HZ macro) */
-
-#define TR_RETRY_INTERVAL (5*HZ) /* 500 on PC = 5 s */
-#define TR_RESET_INTERVAL (HZ/20) /* 5 on PC = 50 ms */
-#define TR_BUSY_INTERVAL (HZ/5) /* 5 on PC = 200 ms */
-#define TR_SPIN_INTERVAL (3*HZ) /* 3 seconds before init timeout */
-#define TR_RETRIES 6            /* number of open retries */ 
-
-#define TR_ISA 1
-#define TR_MCA 2
-#define TR_ISAPNP 3
-#define NOTOK 0
-#define TOKDEBUG 1
-
-#define IBMTR_SHARED_RAM_SIZE 0x10000
-#define IBMTR_IO_EXTENT 4
-#define IBMTR_MAX_ADAPTERS 2
-
-#define CHANNEL_ID      0X1F30
-#define AIP             0X1F00
-#define AIPCHKSUM1      0X1F60
-#define AIPCHKSUM2      0X1FF0
-#define AIPADAPTYPE     0X1FA0
-#define AIPDATARATE     0X1FA2
-#define AIPEARLYTOKEN   0X1FA4
-#define AIPAVAILSHRAM   0X1FA6
-#define AIPSHRAMPAGE    0X1FA8
-#define AIP4MBDHB       0X1FAA
-#define AIP16MBDHB      0X1FAC
-#define AIPFID		0X1FBA
-
-/* Note, 0xA20 == 0x220 since motherboard decodes 10 bits.  I left everything
-   the way my documentation had it, ie: 0x0A20.     */
-#define ADAPTINTCNTRL   0x02f0  /* Adapter interrupt control */
-#define ADAPTRESET      0x1     /* Control Adapter reset (add to base) */
-#define ADAPTRESETREL   0x2     /* Release Adapter from reset ( """)  */
-#define ADAPTINTREL	0x3 	/* Adapter interrupt release */
-
-#define MMIOStartLocP   0x0a20  /* Primary adapter's starting MMIO area */
-#define MMIOStartLocA   0x0a24  /* Alternate adapter's starting MMIO area */
-
-#define GLOBAL_INT_ENABLE 0x02f0
-
-/* MMIO bits 0-4 select register */
-#define RRR_EVEN        0x00    /* Shared RAM relocation registers - even and odd */
-/* Used to set the starting address of shared RAM  */
-/* Bits 1 through 7 of this register map to bits 13 through 19 of the shared RAM address.*/
-/* ie: 0x02 sets RAM address to ...ato!  issy su wazzoo !! GODZILLA!!! */
-#define RRR_ODD         0x01
-/* Bits 2 and 3 of this register can be read to determine shared RAM size */
-/* 00 for 8k, 01 for 16k, 10 for 32k, 11 for 64k  */
-#define WRBR_EVEN       0x02    /* Write region base registers - even and odd */
-#define WRBR_ODD        0x03
-#define WWOR_EVEN       0x04    /* Write window open registers - even and odd */
-#define WWOR_ODD        0x05
-#define WWCR_EVEN       0x06    /* Write window close registers - even and odd */
-#define WWCR_ODD        0x07
-
-/* Interrupt status registers - PC system  - even and odd */
-#define ISRP_EVEN       0x08
-
-#define TCR_INT 0x10    /* Bit 4 - Timer interrupt.  The TVR_EVEN timer has
-                                                                   expired. */
-#define ERR_INT 0x08    /* Bit 3 - Error interrupt.  The adapter has had an
-                                                                   internal error. */
-#define ACCESS_INT 0x04    /* Bit 2 - Access interrupt.  You have attempted to
-                                                           write to an invalid area of shared RAM or an invalid
-                                                                   register within the MMIO. */
-/*      In addition, the following bits within ISRP_EVEN can be turned on or off by you */
-/*      to control the interrupt processing:   */
-#define INT_IRQ 0x80    /* Bit 7 - If 0 the adapter will issue a CHCK, if 1 and
-                                                              IRQ.  This should normally be set (by you) to 1.  */
-#define INT_ENABLE 0x40 /* Bit 6 - Interrupt enable.  If 0, no interrupts will
-                                                                   occur.  If 1, interrupts will occur normally.
-                                                                   Normally set to 1.  */
-/* Bit 0 - Primary or alternate adapter.  Set to zero if this adapter is the primary adapter,*/
-/*         1 if this adapter is the alternate adapter. */
-
-
-#define ISRP_ODD        0x09
-
-#define ADAP_CHK_INT 0x40 /* Bit 6 - Adapter check.  the adapter has
-                             encountered a serious problem and has closed
-                             itself.  Whoa.  */
-#define SRB_RESP_INT 0x20 /* Bit 5 - SRB response.  The adapter has accepted
-                             an SRB request and set the return code within
-                             the SRB. */
-#define ASB_FREE_INT 0x10 /* Bit 4 - ASB free.  The adapter has read the ASB
-                                                                          and this area can be safely reused. This interrupt
-                                                                          is only used if your application has set the ASB
-                                                                          free request bit in ISRA_ODD or if an error was
-                                                                detected in your response. */
-#define ARB_CMD_INT  0x08 /* Bit 3 - ARB command.  The adapter has given you a
-                                                                          command for action.  The command is located in the
-                                                                          ARB area of shared memory. */
-#define SSB_RESP_INT 0x04 /* Bit 2 - SSB response.  The adapter has posted a
-                                                                          response to your SRB (the response is located in
-                                                                          the SSB area of shared memory). */
-/* Bit 1 - Bridge frame forward complete. */
-
-
-
-#define ISRA_EVEN       0x0A    /* Interrupt status registers - adapter  - even and odd */
-/* Bit 7 - Internal parity error (on adapter's internal bus) */
-/* Bit 6 - Timer interrupt pending */
-/* Bit 5 - Access interrupt (attempt by adapter to access illegal address) */
-/* Bit 4 - Adapter microcode problem (microcode dead-man timer expired) */
-/* Bit 3 - Adapter processor check status */
-/* Bit 2 - Reserved */
-/* Bit 1 - Adapter hardware interrupt mask (prevents internal interrupts) */
-/* Bit 0 - Adapter software interrupt mask (prevents internal software interrupts) */
-
-#define ISRA_ODD        0x0B
-#define CMD_IN_SRB 0x20 /* Bit 5  - Indicates that you have placed a new
-                           command in the SRB and are ready for the adapter to
-                           process the command. */
-#define RESP_IN_ASB 0x10 /* Bit 4 - Indicates that you have placed a response
-                                                                    (an ASB) in the shared RAM which is available for
-                                                                         the adapter's use. */
-/* Bit 3 - Indicates that you are ready to put an SRB in the shared RAM, but that a previous */
-/*         command is still pending.  The adapter will then interrupt you when the previous */
-/*         command is completed */
-/* Bit 2 - Indicates that you are ready to put an ASB in the shared RAM, but that a previous */
-/*         ASB is still pending.  The adapter will then interrupt you when the previous ASB */
-/*         is copied.  */
-#define ARB_FREE 0x2
-#define SSB_FREE 0x1
-
-#define TCR_EVEN        0x0C    /* Timer control registers - even and odd */
-#define TCR_ODD         0x0D
-#define TVR_EVEN        0x0E    /* Timer value registers - even and odd */
-#define TVR_ODD         0x0F
-#define SRPR_EVEN       0x18    /* Shared RAM paging registers - even and odd */
-#define SRPR_ENABLE_PAGING 0xc0
-#define SRPR_ODD        0x19 /* Not used. */
-#define TOKREAD         0x60
-#define TOKOR           0x40
-#define TOKAND          0x20
-#define TOKWRITE        0x00
-
-/* MMIO bits 5-6 select operation */
-/* 00 is used to write to a register */
-/* 01 is used to bitwise AND a byte with a register */
-/* 10 is used to bitwise OR a byte with a register  */
-/* 11 is used to read from a register */
-
-/* MMIO bits 7-8 select area of interest.. see below */
-/* 00 selects attachment control area. */
-/* 01 is reserved. */
-/* 10 selects adapter identification area A containing the adapter encoded address. */
-/* 11 selects the adapter identification area B containing test patterns. */
-
-#define PCCHANNELID 5049434F3631313039393020
-#define MCCHANNELID 4D4152533633583435313820
-
-#define ACA_OFFSET 0x1e00
-#define ACA_SET 0x40
-#define ACA_RESET 0x20
-#define ACA_RW 0x00
-
-#ifdef ENABLE_PAGING
-#define SET_PAGE(x) (isa_writeb((x), \
-  ti->mmio + ACA_OFFSET + ACA_RW + SRPR_EVEN))
-#else
-#define SET_PAGE(x)
-#endif
-
-typedef enum { IN_PROGRESS, SUCCESS, FAILURE, CLOSED } open_state;
-
-/* do_tok_int possible values */
-#define FIRST_INT 1
-#define NOT_FIRST 2
-
-struct tok_info {
-	unsigned char irq;
-	__u32 mmio;
-	unsigned char hw_address[32];
-	unsigned char adapter_type;
-	unsigned char data_rate;
-	unsigned char token_release;
-	unsigned char avail_shared_ram;
-	unsigned char shared_ram_paging;
-	unsigned short dhb_size4mb;
-	unsigned short rbuf_len4;
-	unsigned short rbuf_cnt4;
-	unsigned short maxmtu4;
-	unsigned short dhb_size16mb;
-	unsigned short rbuf_len16;
-	unsigned short rbuf_cnt16;
-	unsigned short maxmtu16;
-	/* Additions by David Morris       */
-	unsigned char do_tok_int;
-	wait_queue_head_t wait_for_tok_int;
-	wait_queue_head_t wait_for_reset;
-	unsigned char sram_base;
-	/* Additions by Peter De Schrijver */
-	unsigned char page_mask;          /* mask to select RAM page to Map*/
-	unsigned char mapped_ram_size;    /* size of RAM page */
-	__u32 sram;                       /* Shared memory base address */
-	__u32 init_srb;                   /* Initial System Request Block address */
-	__u32 srb;                        /* System Request Block address */
-	__u32 ssb;                        /* System Status Block address */
-	__u32 arb;                        /* Adapter Request Block address */
-	__u32 asb;                        /* Adapter Status Block address */
-        __u8  init_srb_page;
-        __u8  srb_page;
-        __u8  ssb_page;
-        __u8  arb_page;
-        __u8  asb_page;
-	unsigned short exsap_station_id;
-	unsigned short global_int_enable;
-	struct sk_buff *current_skb;
-	struct net_device_stats tr_stats;
-	unsigned char auto_ringspeedsave;
-	open_state open_status;
-	unsigned char readlog_pending;
-	unsigned short adapter_int_enable; /* Adapter-specific int enable */
-        struct timer_list tr_timer;
-	unsigned char ring_speed;
-	__u32 func_addr;
-	unsigned int retry_count;
-	spinlock_t lock;		/* SMP protection */
-};
-
-/* token ring adapter commands */
-#define DIR_INTERRUPT 		0x00 /* struct srb_interrupt */
-#define DIR_MOD_OPEN_PARAMS 	0x01
-#define DIR_OPEN_ADAPTER 	0x03 /* struct dir_open_adapter */
-#define DIR_CLOSE_ADAPTER   	0x04
-#define DIR_SET_GRP_ADDR    	0x06
-#define DIR_SET_FUNC_ADDR   	0x07 /* struct srb_set_funct_addr */
-#define DIR_READ_LOG 		0x08 /* struct srb_read_log */
-#define DLC_OPEN_SAP 		0x15 /* struct dlc_open_sap */
-#define DLC_CLOSE_SAP       	0x16
-#define DATA_LOST 		0x20 /* struct asb_rec */
-#define REC_DATA 		0x81 /* struct arb_rec_req */
-#define XMIT_DATA_REQ 		0x82 /* struct arb_xmit_req */
-#define DLC_STATUS 		0x83 /* struct arb_dlc_status */
-#define RING_STAT_CHANGE    	0x84 /* struct dlc_open_sap ??? */
-
-/* DIR_OPEN_ADAPTER options */
-#define OPEN_PASS_BCON_MAC 0x0100
-#define NUM_RCV_BUF 2
-#define RCV_BUF_LEN 1024
-#define DHB_LENGTH 2048
-#define NUM_DHB 2
-#define DLC_MAX_SAP 2
-#define DLC_MAX_STA 1
-
-/* DLC_OPEN_SAP options */
-#define MAX_I_FIELD 0x0088
-#define SAP_OPEN_IND_SAP 0x04
-#define SAP_OPEN_PRIORITY 0x20
-#define SAP_OPEN_STATION_CNT 0x1
-#define XMIT_DIR_FRAME 0x0A
-#define XMIT_UI_FRAME  0x0d
-#define XMIT_XID_CMD   0x0e
-#define XMIT_TEST_CMD  0x11
-
-/* srb close return code */
-#define SIGNAL_LOSS  0x8000
-#define HARD_ERROR   0x4000
-#define XMIT_BEACON  0x1000
-#define LOBE_FAULT   0x0800
-#define AUTO_REMOVAL 0x0400
-#define REMOVE_RECV  0x0100
-#define LOG_OVERFLOW 0x0080
-#define RING_RECOVER 0x0020
-
-struct srb_init_response {
-	unsigned char command;
-	unsigned char init_status;
-	unsigned char init_status_2;
-	unsigned char reserved[3];
-	__u16 bring_up_code;
-	__u16 encoded_address;
-	__u16 level_address;
-	__u16 adapter_address;
-	__u16 parms_address;
-	__u16 mac_address;
-};
-
-struct dir_open_adapter {
-	unsigned char command;
-	char reserved[7];
-	__u16 open_options;
-	unsigned char node_address[6];
-	unsigned char group_address[4];
-	unsigned char funct_address[4];
-	__u16 num_rcv_buf;
-	__u16 rcv_buf_len;
-	__u16 dhb_length;
-	unsigned char num_dhb;
-	char reserved2;
-	unsigned char dlc_max_sap;
-	unsigned char dlc_max_sta;
-	unsigned char dlc_max_gsap;
-	unsigned char dlc_max_gmem;
-	unsigned char dlc_t1_tick_1;
-	unsigned char dlc_t2_tick_1;
-	unsigned char dlc_ti_tick_1;
-	unsigned char dlc_t1_tick_2;
-	unsigned char dlc_t2_tick_2;
-	unsigned char dlc_ti_tick_2;
-	unsigned char product_id[18];
-};
-
-struct srb_open_response {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2[3];
-	__u16 error_code;
-	__u16 asb_addr;
-	__u16 srb_addr;
-	__u16 arb_addr;
-	__u16 ssb_addr;
-};
-
-struct dlc_open_sap {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2;
-	__u16 station_id;
-	unsigned char timer_t1;
-	unsigned char timer_t2;
-	unsigned char timer_ti;
-	unsigned char maxout;
-	unsigned char maxin;
-	unsigned char maxout_incr;
-	unsigned char max_retry_count;
-	unsigned char gsap_max_mem;
-	__u16 max_i_field;
-	unsigned char sap_value;
-	unsigned char sap_options;
-	unsigned char station_count;
-	unsigned char sap_gsap_mem;
-	unsigned char gsap[0];
-};
-
-struct srb_xmit {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char ret_code;
-	unsigned char reserved1;
-	__u16 station_id;
-};
-
-struct srb_interrupt {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char ret_code;
-};
-
-struct srb_read_log {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2;
-	unsigned char line_errors;
-	unsigned char internal_errors;
-	unsigned char burst_errors;
-	unsigned char A_C_errors;
-	unsigned char abort_delimiters;
-	unsigned char reserved3;
-	unsigned char lost_frames;
-	unsigned char recv_congest_count;
-	unsigned char frame_copied_errors;
-	unsigned char frequency_errors;
-	unsigned char token_errors;
-};
-
-struct asb_xmit_resp {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char ret_code;
-	unsigned char reserved;
-	__u16 station_id;
-	__u16 frame_length;
-	unsigned char hdr_length;
-	unsigned char rsap_value;
-};
-
-struct arb_xmit_req {
-	unsigned char command;
-	unsigned char cmd_corr;
-	unsigned char reserved1[2];
-	__u16 station_id;
-	__u16 dhb_address;
-};
-
-struct arb_rec_req {
-	unsigned char command;
-	unsigned char reserved1[3];
-	__u16 station_id;
-	__u16 rec_buf_addr;
-	unsigned char lan_hdr_len;
-	unsigned char dlc_hdr_len;
-	__u16 frame_len;
-	unsigned char msg_type;
-};
-
-struct asb_rec {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2;
-	__u16 station_id;
-	__u16 rec_buf_addr;
-};
-
-struct rec_buf {
-  /*	unsigned char reserved1[2]; */
-	__u16 buf_ptr;
-	unsigned char reserved2;
-	__u16 buf_len;
-	unsigned char data[0];
-};
-
-struct arb_dlc_status {
-	unsigned char command;
-	unsigned char reserved1[3];
-	__u16 station_id;
-	__u16 status;
-	unsigned char frmr_data[5];
-	unsigned char access_prio;
-	unsigned char rem_addr[TR_ALEN];
-	unsigned char rsap_value;
-};
-
-struct arb_ring_stat_change {
-	unsigned char command;
-	unsigned char reserved1[5];
-	__u16 ring_status;
-};
-
-struct srb_close_adapter {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-};
-
-struct srb_set_funct_addr {
-	unsigned char command;
-	unsigned char reserved1;
-	unsigned char ret_code;
-	unsigned char reserved2[3];
-	unsigned char funct_address[4];
-};
-
diff -urN linux-2.4.5-pre2/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c
--- linux-2.4.5-pre2/drivers/net/tokenring/smctr.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/tokenring/smctr.c	Mon Dec  3 22:43:26 2001
@@ -1,7 +1,7 @@
 /*
  *  smctr.c: A network driver for the SMC Token Ring Adapters.
  *
- *  Written by Jay Schulist <jschlst@turbolinux.com>
+ *  Written by Jay Schulist <jschlst@samba.org>
  *
  *  This software may be used and distributed according to the terms
  *  of the GNU General Public License, incorporated herein by reference.
@@ -14,7 +14,7 @@
  *  	- SMC TokenCard SDK.
  *
  *  Maintainer(s):
- *    JS        Jay Schulist <jschlst@turbolinux.com>
+ *    JS        Jay Schulist <jschlst@samba.org>
  *
  * Changes:
  *    07102000          JS      Fixed a timing problem in smctr_wait_cmd();
@@ -62,7 +62,7 @@
 #include "smctr.h"               /* Our Stuff */
 #include "smctr_firmware.h"      /* SMC adapter firmware */
 
-static char version[] __initdata = KERN_INFO "smctr.c: v1.4 7/12/00 by jschlst@turbolinux.com\n";
+static char version[] __initdata = KERN_INFO "smctr.c: v1.4 7/12/00 by jschlst@samba.org\n";
 static const char cardname[] = "smctr";
 
 
diff -urN linux-2.4.5-pre2/drivers/net/tokenring/smctr.h linux/drivers/net/tokenring/smctr.h
--- linux-2.4.5-pre2/drivers/net/tokenring/smctr.h	Wed May 10 16:56:42 2000
+++ linux/drivers/net/tokenring/smctr.h	Mon Dec  3 22:43:26 2001
@@ -1,7 +1,7 @@
 /* smctr.h: SMC Token Ring driver header for Linux
  *
  * Authors:
- *  - Jay Schulist <jschlst@turbolinux.com>
+ *  - Jay Schulist <jschlst@samba.org>
  */
 
 #ifndef __LINUX_SMCTR_H
diff -urN linux-2.4.5-pre2/drivers/net/tokenring/smctr_firmware.h linux/drivers/net/tokenring/smctr_firmware.h
--- linux-2.4.5-pre2/drivers/net/tokenring/smctr_firmware.h	Mon Dec 11 12:59:51 2000
+++ linux/drivers/net/tokenring/smctr_firmware.h	Mon Dec  3 22:43:26 2001
@@ -14,7 +14,7 @@
  *  - This is an 8K binary image. (MCT.BIN v6.3C1 03/01/95)
  *
  * Authors:
- *  - Jay Schulist <jschlst@turbolinux.com>
+ *  - Jay Schulist <jschlst@samba.org>
  */
 
 #include <linux/config.h>
diff -urN linux-2.4.5-pre2/drivers/net/tokenring/tms380tr.c linux/drivers/net/tokenring/tms380tr.c
--- linux-2.4.5-pre2/drivers/net/tokenring/tms380tr.c	Thu Apr 19 09:34:52 2001
+++ linux/drivers/net/tokenring/tms380tr.c	Mon Dec  3 22:43:26 2001
@@ -28,7 +28,7 @@
  *  	- Various Madge employees
  *
  *  Maintainer(s):
- *    JS	Jay Schulist		jschlst@turbolinux.com
+ *    JS	Jay Schulist		jschlst@samba.org
  *    CG	Christoph Goos		cgoos@syskonnect.de
  *    AF	Adam Fritzler		mid@auk.cx
  *    MLP       Mike Phillips           phillim@amtrak.com
diff -urN linux-2.4.5-pre2/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c
--- linux-2.4.5-pre2/drivers/net/tulip/21142.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/21142.c	Mon Dec  3 22:43:26 2001
@@ -100,16 +100,14 @@
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	long ioaddr = dev->base_addr;
-	int csr14 = ((tp->to_advertise & 0x0780) << 9)  |
-		((tp->to_advertise&0x0020)<<1) | 0xffbf;
-
-	DPRINTK("ENTER\n");
+	int csr14 = ((tp->sym_advertise & 0x0780) << 9)  |
+		((tp->sym_advertise & 0x0020) << 1) | 0xffbf;
 
 	dev->if_port = 0;
 	tp->nway = tp->mediasense = 1;
 	tp->nwayset = tp->lpar = 0;
 	if (tp->chip_id == PNIC2) {
-		tp->csr6 = 0x01000000 | (tp->to_advertise & 0x0040 ? FullDuplex : 0);
+		tp->csr6 = 0x01000000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0);
 		return;
 	}
 	if (tulip_debug > 1)
@@ -118,7 +116,7 @@
 	outl(0x0001, ioaddr + CSR13);
 	udelay(100);
 	outl(csr14, ioaddr + CSR14);
-	tp->csr6 = 0x82420000 | (tp->to_advertise & 0x0040 ? FullDuplex : 0);
+	tp->csr6 = 0x82420000 | (tp->sym_advertise & 0x0040 ? FullDuplex : 0);
 	tulip_outl_csr(tp, tp->csr6, CSR6);
 	if (tp->mtable  &&  tp->mtable->csr15dir) {
 		outl(tp->mtable->csr15dir, ioaddr + CSR15);
@@ -129,6 +127,24 @@
 }
 
 
+void pnic2_lnk_change(struct net_device *dev, int csr5)
+{
+	struct tulip_private *tp = (struct tulip_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int csr12 = inl(ioaddr + CSR12);
+
+	if (tulip_debug > 1)
+		printk(KERN_INFO"%s: PNIC-2 link status changed, CSR5/12/14 %8.8x"
+			" %8.8x, %8.8x.\n",
+			dev->name, csr12, csr5, (int)inl(ioaddr + CSR14));
+	dev->if_port = 5;
+	tp->lpar = csr12 >> 16;
+	tp->nwayset = 1;
+	tp->csr6 = 0x01000000 | (tp->csr6 & 0xffff);
+	outl(tp->csr6, ioaddr + CSR6);
+
+}
+
 void t21142_lnk_change(struct net_device *dev, int csr5)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -142,7 +158,7 @@
 	/* If NWay finished and we have a negotiated partner capability. */
 	if (tp->nway  &&  !tp->nwayset  &&  (csr12 & 0x7000) == 0x5000) {
 		int setup_done = 0;
-		int negotiated = tp->to_advertise & (csr12 >> 16);
+		int negotiated = tp->sym_advertise & (csr12 >> 16);
 		tp->lpar = csr12 >> 16;
 		tp->nwayset = 1;
 		if (negotiated & 0x0100)		dev->if_port = 5;
@@ -151,7 +167,7 @@
 		else if (negotiated & 0x0020)	dev->if_port = 0;
 		else {
 			tp->nwayset = 0;
-			if ((csr12 & 2) == 0  &&  (tp->to_advertise & 0x0180))
+			if ((csr12 & 2) == 0  &&  (tp->sym_advertise & 0x0180))
 				dev->if_port = 3;
 		}
 		tp->full_duplex = (tulip_media_cap[dev->if_port] & MediaAlwaysFD) ? 1:0;
@@ -160,7 +176,7 @@
 			if (tp->nwayset)
 				printk(KERN_INFO "%s: Switching to %s based on link "
 					   "negotiation %4.4x & %4.4x = %4.4x.\n",
-					   dev->name, medianame[dev->if_port], tp->to_advertise,
+					   dev->name, medianame[dev->if_port], tp->sym_advertise,
 					   tp->lpar, negotiated);
 			else
 				printk(KERN_INFO "%s: Autonegotiation failed, using %s,"
@@ -173,7 +189,7 @@
 			for (i = 0; i < tp->mtable->leafcount; i++)
 				if (tp->mtable->mleaf[i].media == dev->if_port) {
 					tp->cur_index = i;
-					tulip_select_media(dev, 0);
+					tulip_select_media(dev, 1);
 					setup_done = 1;
 					break;
 				}
diff -urN linux-2.4.5-pre2/drivers/net/tulip/ChangeLog linux/drivers/net/tulip/ChangeLog
--- linux-2.4.5-pre2/drivers/net/tulip/ChangeLog	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/tulip/ChangeLog	Mon Dec  3 22:43:26 2001
@@ -1,3 +1,163 @@
+2001-05-13  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c: Remove HAS_PCI_MWI flag from Comet, untested.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c, tulip.h: Remove Conexant PCI id, no chip
+	docs are available to fix problems with support.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_init_one): Do not call
+	unregister_netdev in error cleanup.  Remnant of old
+	usage of init_etherdev.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_find_mii): Simple write the updated BMCR
+	twice, as it seems the best thing to do for both broken and
+	sane chips.
+	If the mii_advert value, as read from MII_ADVERTISE, is zero,
+	then generate a value we should advertise from the capability
+	bits in BMSR.
+	Fill in tp->advertising for all cases.
+	Just to be safe, clear all unwanted bits.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (private_ioctl):  Fill in tp->advertising
+	when advertising value is changed by the user.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c: Mark Comet chips as needed the updated MWI
+	csr0 configuration.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c, tulip_core.c:  Move MII scan into
+	from inlined inside tulip_init_one to new function
+	tulip_find_mii in media.c.
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_check_duplex):
+	Only restart Rx/Tx engines if they are active
+	(and csr6 changes)
+
+2001-05-12  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_mwi_config):
+	Clamp values read from PCI cache line size register to
+	values acceptable to tulip chip.  Done for safety and
+	-almost- certainly unneeded.
+
+2001-05-11  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_init_one):
+	Instead of unconditionally enabling autonegotiation, disable
+	autonegotiation if not using the default port.  Further,
+	flip the nway bit immediately, and then update the
+	speed/duplex in a separate MII transaction.  We do this
+	because some boards require that nway be disabled separately,
+	before media selection is forced.
+
+	TODO: Investigate if we can simply write the same value
+	to BMCR twice, to avoid setting unnecessarily changing
+	phy settings.
+
+2001-05-11  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip.h, tulip_core.c:  If HAS_PCI_MWI is set for a
+	given chip, adjust the csr0 values not according to
+	provided values but according to system cache line size.
+	Currently cache alignment is matched as closely to cache
+	line size as possible.  Currently programmable burst limit
+	is set (ie. never unlimited), and always equal to cache
+	alignment and system cache size.  Currently MWI bit is set
+	only if the MWI bit is present in the PCI command register.
+
+2001-05-11  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_select_media):
+	For media types 1 and 3, only use the provided eeprom
+	advertising value if it is non-zero.
+	(tulip_check_duplex):
+	Do not exit ASAP if full_duplex_lock is set.  This
+	ensures that the csr6 value is written if an update
+	is needed.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	Merge PNIC-II-specific stuff from Becker's tulip.c:
+
+	* tulip.h, 21142.c (pnic2_lnk_change): new function
+	* tulip_core.c (tulip_init_one): use it
+
+	* tulip_core.c (tulip_tx_timeout): Add specific
+	debugging for PNIC2.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* tulip_core.c (tulip_init_one): Print out
+	tulip%d instead of PCI device number, for
+	consistency.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* Merge changes from Becker's tulip.c:
+	Fix bugs in ioctl.
+	Fix several bugs by distinguishing between MII
+	and SYM advertising values.
+	Set CSR14 autonegotiation bit for media types 2 and 4,
+	where the SIA CSR setup values are not provided.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* media.c (tulip_select_media): Only update MII
+	advertising value if startup arg < 2.
+
+	* tulip.h: Do not enable CSR13/14/15 autoconfiguration
+	for 21041.
+
+	* tulip_core.c:
+	21041: add specific code for reset, and do not set CAC bit
+	When resetting media, for media table type 11 media, pass
+	value 2 as 'startup' arg to select_media, to avoid updating
+	MII advertising value.
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* pnic.c (pnic_check_duplex): remove
+	pnic.c (pnic_lnk_change, pnic_timer): use
+	tulip_check_duplex not pnic_check_duplex.
+
+	* media.c (tulip_check_duplex):
+	Clean up to use symbolic names instead of numeric constants.
+	Set TxThreshold mode as necessary as well as clearing it.
+	Update csr6 if csr6 changes, not simply if duplex changes.
+
+	(found by Manfred Spraul)
+
+2001-05-10  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* 21142.c, eeprom.c, tulip.h, tulip_core.c:
+	Remove DPRINTK as another, better method of
+	debug message printing is available.
+
+2001-05-09  Jeff Garzik  <jgarzik@mandrakesoft.com>
+
+	* 21142.c (t21142_lnk_change): Pass arg startup==1
+	to tulip_select_media, in order to force csr13 to be
+	zeroed out prior to going to full duplex mode.  Fixes
+	autonegotiation on a quad-port Znyx card.
+	(from Stephen Dengler)
+
+2001-05-09  Russell King  <rmk@arm.linux.org.uk>
+
+	* interrupt.c: Better PCI bus error reporting.
+
 2001-04-03  Jeff Garzik  <jgarzik@mandrakesoft.com>
 
 	* tulip_core.c: Now that dev->name is only available late
@@ -29,7 +189,7 @@
 	  the following defines existed.  These defines were never used
 	  by normal users in practice: TULIP_FULL_DUPLEX,
 	  TULIP_DEFAULT_MEDIA, and TULIP_NO_MEDIA_SWITCH.
-	  
+
 	* tulip.h, eeprom.c: Move EE_* constants from tulip.h to eeprom.c.
 	* tulip.h, media.c: Move MDIO_* constants from tulip.h to media.c.
 
diff -urN linux-2.4.5-pre2/drivers/net/tulip/eeprom.c linux/drivers/net/tulip/eeprom.c
--- linux-2.4.5-pre2/drivers/net/tulip/eeprom.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/eeprom.c	Mon Dec  3 22:43:26 2001
@@ -167,7 +167,8 @@
 
 	        /* there is no phy information, don't even try to build mtable */
 	        if (count == 0) {
-			DPRINTK("no phy info, aborting mtable build\n");
+			if (tulip_debug > 0)
+				printk(KERN_WARNING "%s: no phy info, aborting mtable build\n", dev->name);
 		        return;
 		}
 
@@ -259,7 +260,7 @@
 				   leaf->type);
 		}
 		if (new_advertise)
-			tp->to_advertise = new_advertise;
+			tp->sym_advertise = new_advertise;
 	}
 }
 /* Reading a serial EEPROM is a "bit" grungy, but we work our way through:->.*/
diff -urN linux-2.4.5-pre2/drivers/net/tulip/media.c linux/drivers/net/tulip/media.c
--- linux-2.4.5-pre2/drivers/net/tulip/media.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/media.c	Mon Dec  3 22:43:26 2001
@@ -14,6 +14,10 @@
 
 */
 
+#include <linux/kernel.h>
+#include <linux/mii.h>
+#include <linux/init.h>
+#include <linux/delay.h>
 #include "tulip.h"
 
 
@@ -228,7 +232,7 @@
 				outl(csr13val, ioaddr + CSR13);
 			} else {
 				csr13val = 1;
-				csr14val = 0x0003FF7F;
+				csr14val = 0x0003FFFF;
 				csr15dir = (setup[0]<<16) | 0x0008;
 				csr15val = (setup[1]<<16) | 0x0008;
 				if (dev->if_port <= 4)
@@ -253,8 +257,7 @@
 		case 1: case 3: {
 			int phy_num = p[0];
 			int init_length = p[1];
-			u16 *misc_info;
-			u16 to_advertise;
+			u16 *misc_info, tmp_info;
 
 			dev->if_port = 11;
 			new_csr6 = 0x020E0000;
@@ -281,13 +284,17 @@
 				for (i = 0; i < init_length; i++)
 					outl(init_sequence[i], ioaddr + CSR12);
 			}
-			to_advertise = (get_u16(&misc_info[1]) & tp->to_advertise) | 1;
-			tp->advertising[phy_num] = to_advertise;
-			if (tulip_debug > 1)
-				printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d (%d).\n",
-					   dev->name, to_advertise, phy_num, tp->phys[phy_num]);
-			/* Bogus: put in by a committee?  */
-			tulip_mdio_write(dev, tp->phys[phy_num], 4, to_advertise);
+			tmp_info = get_u16(&misc_info[1]);
+			if (tmp_info)
+				tp->advertising[phy_num] = tmp_info | 1;
+			if (tmp_info && startup < 2) {
+				if (tp->mii_advertise == 0)
+					tp->mii_advertise = tp->advertising[phy_num];
+				if (tulip_debug > 1)
+					printk(KERN_DEBUG "%s:  Advertising %4.4x on MII %d.\n",
+					       dev->name, tp->mii_advertise, tp->phys[phy_num]);
+				tulip_mdio_write(dev, tp->phys[phy_num], 4, tp->mii_advertise);
+			}
 			break;
 		}
 		case 5: case 6: {
@@ -397,52 +404,164 @@
 }
 
 /*
-  Check the MII negotiated duplex, and change the CSR6 setting if
+  Check the MII negotiated duplex and change the CSR6 setting if
   required.
   Return 0 if everything is OK.
   Return < 0 if the transceiver is missing or has no link beat.
   */
 int tulip_check_duplex(struct net_device *dev)
 {
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	int mii_reg1, mii_reg5, negotiated, duplex;
+	long ioaddr = dev->base_addr;
+	struct tulip_private *tp = dev->priv;
+	unsigned int bmsr, lpa, negotiated, new_csr6;
 
-	if (tp->full_duplex_lock)
-		return 0;
-	mii_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-	mii_reg5 = tulip_mdio_read(dev, tp->phys[0], 5);
+	bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
+	lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA);
 	if (tulip_debug > 1)
 		printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
-			   "%4.4x.\n", dev->name, mii_reg1, mii_reg5);
-	if (mii_reg1 == 0xffff)
+			   "%4.4x.\n", dev->name, bmsr, lpa);
+	if (bmsr == 0xffff)
 		return -2;
-	if ((mii_reg1 & 0x0004) == 0) {
-		int new_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-		if ((new_reg1 & 0x0004) == 0) {
+	if ((bmsr & BMSR_LSTATUS) == 0) {
+		int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
+		if ((new_bmsr & BMSR_LSTATUS) == 0) {
 			if (tulip_debug  > 1)
 				printk(KERN_INFO "%s: No link beat on the MII interface,"
-					   " status %4.4x.\n", dev->name, new_reg1);
+					   " status %4.4x.\n", dev->name, new_bmsr);
 			return -1;
 		}
 	}
-	negotiated = mii_reg5 & tp->advertising[0];
-	duplex = ((negotiated & 0x0300) == 0x0100
-			  || (negotiated & 0x00C0) == 0x0040);
-	/* 100baseTx-FD  or  10T-FD, but not 100-HD */
-	if (tp->full_duplex != duplex) {
-		tp->full_duplex = duplex;
-		if (negotiated & 0x038)	/* 100mbps. */
-			tp->csr6 &= ~0x00400000;
-		if (tp->full_duplex) tp->csr6 |= 0x0200;
-		else				 tp->csr6 &= ~0x0200;
-		tulip_restart_rxtx(tp, tp->csr6);
+	negotiated = lpa & tp->advertising[0];
+	tp->full_duplex = mii_duplex(tp->full_duplex_lock, negotiated);
+
+	new_csr6 = tp->csr6;
+
+	if (negotiated & LPA_100) new_csr6 &= ~TxThreshold;
+	else			  new_csr6 |= TxThreshold;
+	if (tp->full_duplex) new_csr6 |= FullDuplex;
+	else		     new_csr6 &= ~FullDuplex;
+
+	if (new_csr6 != tp->csr6) {
+		if (inl(ioaddr + CSR6) & (csr6_st | csr6_sr))
+			tulip_restart_rxtx(tp, new_csr6);
+		else
+			outl(new_csr6, ioaddr + CSR6);
+		tp->csr6 = new_csr6;
+
 		if (tulip_debug > 0)
 			printk(KERN_INFO "%s: Setting %s-duplex based on MII"
 				   "#%d link partner capability of %4.4x.\n",
 				   dev->name, tp->full_duplex ? "full" : "half",
-				   tp->phys[0], mii_reg5);
+				   tp->phys[0], lpa);
 		return 1;
 	}
+
 	return 0;
 }
 
+void __devinit tulip_find_mii (struct net_device *dev, int board_idx)
+{
+	struct tulip_private *tp = dev->priv;
+	int phyn, phy_idx = 0;
+	int mii_reg0;
+	int mii_advert;
+	unsigned int to_advert, new_bmcr, ane_switch;
+
+	/* Find the connected MII xcvrs.
+	   Doing this in open() would allow detecting external xcvrs later,
+	   but takes much time. */
+	for (phyn = 1; phyn <= 32 && phy_idx < sizeof (tp->phys); phyn++) {
+		int phy = phyn & 0x1f;
+		int mii_status = tulip_mdio_read (dev, phy, MII_BMSR);
+		if ((mii_status & 0x8301) == 0x8001 ||
+		    ((mii_status & BMSR_100BASE4) == 0
+		     && (mii_status & 0x7800) != 0)) {
+			/* preserve Becker logic, gain indentation level */
+		} else {
+			continue;
+		}
+
+		mii_reg0 = tulip_mdio_read (dev, phy, MII_BMCR);
+		mii_advert = tulip_mdio_read (dev, phy, MII_ADVERTISE);
+		ane_switch = 0;
+
+		/* if not advertising at all, gen an
+		 * advertising value from the capability
+		 * bits in BMSR
+		 */
+		if ((mii_advert & ADVERTISE_ALL) == 0) {
+			unsigned int tmpadv = tulip_mdio_read (dev, phy, MII_BMSR);
+			mii_advert = ((tmpadv >> 6) & 0x3e0) | 1;
+		}
+
+		if (tp->mii_advertise) {
+			tp->advertising[phy_idx] =
+			to_advert = tp->mii_advertise;
+		} else if (tp->advertising[phy_idx]) {
+			to_advert = tp->advertising[phy_idx];
+		} else {
+			tp->advertising[phy_idx] =
+			tp->mii_advertise =
+			to_advert = mii_advert;
+		}
+
+		tp->phys[phy_idx++] = phy;
+
+		printk (KERN_INFO "tulip%d:  MII transceiver #%d "
+			"config %4.4x status %4.4x advertising %4.4x.\n",
+			board_idx, phy, mii_reg0, mii_status, mii_advert);
+
+		/* Fixup for DLink with miswired PHY. */
+		if (mii_advert != to_advert) {
+			printk (KERN_DEBUG "tulip%d:  Advertising %4.4x on PHY %d,"
+				" previously advertising %4.4x.\n",
+				board_idx, to_advert, phy, mii_advert);
+			tulip_mdio_write (dev, phy, 4, to_advert);
+		}
+
+		/* Enable autonegotiation: some boards default to off. */
+		if (tp->default_port == 0) {
+			new_bmcr = mii_reg0 | BMCR_ANENABLE;
+			if (new_bmcr != mii_reg0) {
+				new_bmcr |= BMCR_ANRESTART;
+				ane_switch = 1;
+			}
+		}
+		/* ...or disable nway, if forcing media */
+		else {
+			new_bmcr = mii_reg0 & ~BMCR_ANENABLE;
+			if (new_bmcr != mii_reg0)
+				ane_switch = 1;
+		}
+
+		/* clear out bits we never want at this point */
+		new_bmcr &= ~(BMCR_CTST | BMCR_FULLDPLX | BMCR_ISOLATE |
+			      BMCR_PDOWN | BMCR_SPEED100 | BMCR_LOOPBACK |
+			      BMCR_RESET);
+
+		if (tp->full_duplex)
+			new_bmcr |= BMCR_FULLDPLX;
+		if (tulip_media_cap[tp->default_port] & MediaIs100)
+			new_bmcr |= BMCR_SPEED100;
+
+		if (new_bmcr != mii_reg0) {
+			/* some phys need the ANE switch to
+			 * happen before forced media settings
+			 * will "take."  However, we write the
+			 * same value twice in order not to
+			 * confuse the sane phys.
+			 */
+			if (ane_switch) {
+				tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
+				udelay (10);
+			}
+			tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
+		}
+	}
+	tp->mii_cnt = phy_idx;
+	if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
+		printk (KERN_INFO "tulip%d: ***WARNING***: No MII transceiver found!\n",
+			board_idx);
+		tp->phys[0] = 1;
+	}
+}
diff -urN linux-2.4.5-pre2/drivers/net/tulip/pnic.c linux/drivers/net/tulip/pnic.c
--- linux-2.4.5-pre2/drivers/net/tulip/pnic.c	Tue Apr  3 10:19:43 2001
+++ linux/drivers/net/tulip/pnic.c	Mon Dec  3 22:43:26 2001
@@ -51,62 +51,6 @@
 	}
 }
 
-/* Modified version of tulip_check_duplex:
- * Always update the 100mbps bit, even if the
- * full duplex bit didn't change.
- *	Manfred Spraul <manfred@colorfullife.com>
- */
-int pnic_check_duplex(struct net_device *dev)
-{
-	struct tulip_private *tp = (struct tulip_private *)dev->priv;
-	int mii_reg1, mii_reg5, negotiated, duplex;
-	int new_csr6;
-
-	mii_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-	mii_reg5 = tulip_mdio_read(dev, tp->phys[0], 5);
-	if (tulip_debug > 1)
-		printk(KERN_INFO "%s: MII status %4.4x, Link partner report "
-			   "%4.4x.\n", dev->name, mii_reg1, mii_reg5);
-	if (mii_reg1 == 0xffff)
-		return -2;
-	if ((mii_reg1 & 0x0004) == 0) {
-		int new_reg1 = tulip_mdio_read(dev, tp->phys[0], 1);
-		if ((new_reg1 & 0x0004) == 0) {
-			if (tulip_debug  > 1)
-				printk(KERN_INFO "%s: No link beat on the MII interface,"
-					   " status %4.4x.\n", dev->name, new_reg1);
-			return -1;
-		}
-	}
-	negotiated = mii_reg5 & tp->advertising[0];
-	/* 100baseTx-FD  or  10T-FD, but not 100-HD */
-	duplex = ((negotiated & 0x0300) == 0x0100
-			  || (negotiated & 0x00C0) == 0x0040) ||
-		tp->full_duplex_lock;
-
-	new_csr6 = tp->csr6;
-	if (negotiated & 0x0380)	/* 100mbps. */
-		new_csr6 &= ~0x00400000;
-	 else
-		new_csr6 |= 0x00400000;
-	if (duplex)
-		new_csr6 |= 0x0200;
-	 else	
-		new_csr6 &= ~0x0200;
-	if (new_csr6 != tp->csr6) {
-		tp->full_duplex = duplex;
-		tp->csr6 = new_csr6;
-		if (tulip_debug > 0)
-			printk(KERN_INFO "%s: Setting %s-duplex based on MII"
-				   "#%d link partner capability of %4.4x.\n",
-				   dev->name, tp->full_duplex ? "full" : "half",
-				   tp->phys[0], mii_reg5);
-		tulip_restart_rxtx(tp, tp->csr6);
-		return 1;
-	}
-	return 0;
-}
-
 void pnic_lnk_change(struct net_device *dev, int csr5)
 {
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
@@ -133,7 +77,7 @@
 	} else if (inl(ioaddr + CSR5) & TPLnkPass) {
 		if (tulip_media_cap[dev->if_port] & MediaIsMII) {
 			spin_lock(&tp->lock);
-			pnic_check_duplex(dev);
+			tulip_check_duplex(dev);
 			spin_unlock(&tp->lock);
 		} else {
 			pnic_do_nway(dev);
@@ -162,7 +106,7 @@
 
 	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
 		spin_lock_irq(&tp->lock);
-		if (pnic_check_duplex(dev) > 0)
+		if (tulip_check_duplex(dev) > 0)
 			next_tick = 3*HZ;
 		spin_unlock_irq(&tp->lock);
 	} else {
diff -urN linux-2.4.5-pre2/drivers/net/tulip/tulip.h linux/drivers/net/tulip/tulip.h
--- linux-2.4.5-pre2/drivers/net/tulip/tulip.h	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/tulip/tulip.h	Mon Dec  3 22:43:26 2001
@@ -27,17 +27,7 @@
 
 
 /* undefine, or define to various debugging levels (>4 == obscene levels) */
-#undef TULIP_DEBUG
-
-
-#ifdef TULIP_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-
+#define TULIP_DEBUG 1
 
 
 struct tulip_chip_table {
@@ -62,6 +52,7 @@
 	IS_ASIX			= 0x0200,
 	HAS_8023X		= 0x0400,
 	COMET_MAC_ADDR		= 0x0800,
+	HAS_PCI_MWI		= 0x1000,
 };
 
 
@@ -83,7 +74,6 @@
 	COMPEX9881,
 	I21145,
 	DM910X,
-	CONEXANT,
 };
 
 
@@ -145,8 +135,9 @@
 };
 
 
-enum tulip_rx_modes {
-	FullDuplex		= 0x0200,
+enum tulip_mode_bits {
+	TxThreshold		= (1 << 22),
+	FullDuplex		= (1 << 9),
 	AcceptBroadcast		= 0x0100,
 	AcceptAllMulticast	= 0x0080,
 	AcceptAllPhys		= 0x0040,
@@ -154,6 +145,15 @@
 };
 
 
+enum tulip_busconfig_bits {
+	MWI			= (1 << 24),
+	MRL			= (1 << 23),
+	MRM			= (1 << 21),
+	CALShift		= 14,
+	BurstLenShift		= 8,
+};
+
+
 /* The Tulip Rx and Tx buffer descriptors. */
 struct tulip_rx_desc {
 	s32 status;
@@ -184,8 +184,8 @@
 	csr13_cac = (1<<2), /* CSR13/14/15 autoconfiguration */
 	csr13_srl = (1<<0), /* When reset, resets all SIA functions, machines */
 
-	csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_cac | csr13_srl),
-	csr13_mask_10bt = (csr13_eng | csr13_cac | csr13_srl),
+	csr13_mask_auibnc = (csr13_eng | csr13_aui | csr13_srl),
+	csr13_mask_10bt = (csr13_eng | csr13_srl),
 };
 
 enum t21143_csr6_bits {
@@ -255,6 +255,18 @@
 
 #define PKT_BUF_SZ		1536	/* Size of each temporary Rx buffer. */
 
+#define TULIP_MIN_CACHE_LINE	8	/* in units of 32-bit words */
+
+#if defined(__sparc__) || defined(__hppa__)
+/* The UltraSparc PCI controllers will disconnect at every 64-byte
+ * crossing anyways so it makes no sense to tell Tulip to burst
+ * any more than that.
+ */
+#define TULIP_MAX_CACHE_LINE	16	/* in units of 32-bit words */
+#else
+#define TULIP_MAX_CACHE_LINE	32	/* in units of 32-bit words */
+#endif
+
 
 /* Ring-wrap flag in length field, use for last ring entry.
 	0x01000000 means chain on buffer2 address,
@@ -345,7 +357,7 @@
 	unsigned int csr6;	/* Current CSR6 control settings. */
 	unsigned char eeprom[EEPROM_SIZE];	/* Serial EEPROM contents. */
 	void (*link_change) (struct net_device * dev, int csr5);
-	u16 to_advertise;	/* NWay capabilities advertised.  */
+	u16 sym_advertise, mii_advertise; /* NWay capabilities advertised.  */
 	u16 lpar;		/* 21143 Link partner ability. */
 	u16 advertising[4];
 	signed char phys[4], mii_cnt;	/* MII device addresses. */
@@ -375,6 +387,7 @@
 void t21142_timer(unsigned long data);
 void t21142_start_nway(struct net_device *dev);
 void t21142_lnk_change(struct net_device *dev, int csr5);
+void pnic2_lnk_change(struct net_device *dev, int csr5);
 
 /* eeprom.c */
 void tulip_parse_eeprom(struct net_device *dev);
@@ -390,6 +403,7 @@
 void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int value);
 void tulip_select_media(struct net_device *dev, int startup);
 int tulip_check_duplex(struct net_device *dev);
+void tulip_find_mii (struct net_device *dev, int board_idx);
 
 /* pnic.c */
 void pnic_do_nway(struct net_device *dev);
diff -urN linux-2.4.5-pre2/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- linux-2.4.5-pre2/drivers/net/tulip/tulip_core.c	Fri Apr 20 11:54:22 2001
+++ linux/drivers/net/tulip/tulip_core.c	Mon Dec  3 22:43:26 2001
@@ -20,10 +20,11 @@
 #include <linux/init.h>
 #include <linux/etherdevice.h>
 #include <linux/delay.h>
+#include <linux/mii.h>
 #include <asm/unaligned.h>
 
 static char version[] __devinitdata =
-	"Linux Tulip driver version 0.9.14e (April 20, 2001)\n";
+	"Linux Tulip driver version 0.9.15-pre1 (May 12, 2001)\n";
 
 
 /* A few user-configurable values. */
@@ -127,12 +128,12 @@
 
   /* DC21140 */
   { "Digital DS21140 Tulip", 128, 0x0001ebef,
-	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM, tulip_timer },
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_PCI_MWI, tulip_timer },
 
   /* DC21142, DC21143 */
   { "Digital DS21143 Tulip", 128, 0x0801fbff,
 	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY
-	| HAS_INTR_MITIGATION, t21142_timer },
+	| HAS_INTR_MITIGATION | HAS_PCI_MWI, t21142_timer },
 
   /* LC82C168 */
   { "Lite-On 82c168 PNIC", 256, 0x0001fbef,
@@ -152,11 +153,12 @@
 
   /* AX88140 */
   { "ASIX AX88140", 128, 0x0001fbff,
-	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY | IS_ASIX, tulip_timer },
+	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | MC_HASH_ONLY
+	| IS_ASIX, tulip_timer },
 
   /* PNIC2 */
   { "Lite-On PNIC-II", 256, 0x0801fbff,
-	HAS_MII | HAS_NWAY | HAS_8023X, t21142_timer },
+	HAS_MII | HAS_NWAY | HAS_8023X | HAS_PCI_MWI, t21142_timer },
 
   /* COMET */
   { "ADMtek Comet", 256, 0x0001abef,
@@ -168,18 +170,13 @@
 
   /* I21145 */
   { "Intel DS21145 Tulip", 128, 0x0801fbff,
-	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI | HAS_NWAY,
-	t21142_timer },
+	HAS_MII | HAS_MEDIA_TABLE | ALWAYS_CHECK_MII | HAS_ACPI
+	| HAS_NWAY | HAS_PCI_MWI, t21142_timer },
 
   /* DM910X */
   { "Davicom DM9102/DM9102A", 128, 0x0001ebef,
 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
 	tulip_timer },
-
-  /* CONEXANT */
-  { "Conexant LANfinity", 0x100, 0x0001ebef,
-	HAS_MII | HAS_ACPI,
-	tulip_timer },
 };
 
 
@@ -208,7 +205,6 @@
 	{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
 	{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
 	{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
-	{ 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
 	{ } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
@@ -269,8 +265,6 @@
 	int next_tick = 3*HZ;
 	int i;
 
-	DPRINTK("ENTER\n");
-
 	/* Wake the chip from sleep/snooze mode. */
 	tulip_set_power_state (tp, 0, 0);
 
@@ -379,10 +373,30 @@
 	tp->csr6 = 0;
 	tp->cur_index = i;
 	tp->nwayset = 0;
-	if (dev->if_port == 0  && tp->chip_id == DC21041)
-		tp->nway = 1;
 
-	if (dev->if_port == 0  &&  tp->chip_id == DC21142) {
+	if (dev->if_port) {
+		if (tp->chip_id == DC21143  &&
+		    (tulip_media_cap[dev->if_port] & MediaIsMII)) {
+			/* We must reset the media CSRs when we force-select MII mode. */
+			outl(0x0000, ioaddr + CSR13);
+			outl(0x0000, ioaddr + CSR14);
+			outl(0x0008, ioaddr + CSR15);
+		}
+		tulip_select_media(dev, 1);
+	} else if (tp->chip_id == DC21041) {
+		dev->if_port = 0;
+		tp->nway = tp->mediasense = 1;
+		tp->nwayset = tp->lpar = 0;
+		outl(0x00000000, ioaddr + CSR13);
+		outl(0xFFFFFFFF, ioaddr + CSR14);
+		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
+		tp->csr6 = 0x80020000;
+		if (tp->sym_advertise & 0x0040)
+			tp->csr6 |= FullDuplex;
+		outl(tp->csr6, ioaddr + CSR6);
+		outl(0x0000EF01, ioaddr + CSR13);
+
+	} else if (tp->chip_id == DC21142) {
 		if (tp->mii_cnt) {
 			tulip_select_media(dev, 1);
 			if (tulip_debug > 1)
@@ -424,12 +438,6 @@
 		tp->csr6 = 0x01a80200;
 		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
 		outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
-	} else if (tp->chip_id == DC21143  &&
-			   tulip_media_cap[dev->if_port] & MediaIsMII) {
-		/* We must reset the media CSRs when we force-select MII mode. */
-		outl(0x0000, ioaddr + CSR13);
-		outl(0x0000, ioaddr + CSR14);
-		outl(0x0008, ioaddr + CSR15);
 	} else if (tp->chip_id == COMET) {
 		/* Enable automatic Tx underrun recovery. */
 		outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
@@ -492,8 +500,6 @@
 	long ioaddr = dev->base_addr;
 	unsigned long flags;
 
-	DPRINTK("ENTER\n");
-
 	spin_lock_irqsave (&tp->lock, flags);
 
 	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
@@ -549,6 +555,11 @@
 			printk(KERN_WARNING "%s: transmit timed out, switching to %s "
 				   "media.\n", dev->name, medianame[dev->if_port]);
 		}
+	} else if (tp->chip_id == PNIC2) {
+		printk(KERN_WARNING "%s: PNIC2 transmit timed out, status %8.8x, "
+		       "CSR6/7 %8.8x / %8.8x CSR12 %8.8x, resetting...\n",
+		       dev->name, (int)inl(ioaddr + CSR5), (int)inl(ioaddr + CSR6),
+		       (int)inl(ioaddr + CSR7), (int)inl(ioaddr + CSR12));
 	} else {
 		printk(KERN_WARNING "%s: Transmit timed out, status %8.8x, CSR12 "
 			   "%8.8x, resetting...\n",
@@ -603,8 +614,6 @@
 	struct tulip_private *tp = (struct tulip_private *)dev->priv;
 	int i;
 
-	DPRINTK("ENTER\n");
-
 	tp->cur_rx = tp->cur_tx = 0;
 	tp->dirty_rx = tp->dirty_tx = 0;
 	tp->susp_rx = 0;
@@ -809,7 +818,8 @@
 	struct tulip_private *tp = dev->priv;
 	long ioaddr = dev->base_addr;
 	u16 *data = (u16 *) & rq->ifr_data;
-	int phy = tp->phys[0] & 0x1f;
+	const unsigned int phy_idx = 0;
+	int phy = tp->phys[phy_idx] & 0x1f;
 	unsigned int regnum = data[1];
 
 	switch (cmd) {
@@ -828,26 +838,31 @@
 			int csr14 = inl (ioaddr + CSR14);
 			switch (regnum) {
 			case 0:
-				data[3] = (csr14 << 5) & 0x1000;
+                                if (((csr14<<5) & 0x1000) ||
+                                        (dev->if_port == 5 && tp->nwayset))
+                                        data[3] = 0x1000;
+                                else
+                                        data[3] = (tulip_media_cap[dev->if_port]&MediaIs100 ? 0x2000 : 0)
+                                                | (tulip_media_cap[dev->if_port]&MediaIsFD ? 0x0100 : 0);
 				break;
 			case 1:
-				data[3] =
-				  0x7848 +
-				  ((csr12 & 0x7000) == 0x5000 ? 0x20 : 0) +
-				  (csr12 & 0x06 ? 0x04 : 0);
+                                data[3] =
+					0x1848 +
+					((csr12&0x7000) == 0x5000 ? 0x20 : 0) +
+					((csr12&0x06) == 6 ? 0 : 4);
+                                if (tp->chip_id != DC21041)
+                                        data[3] |= 0x6048;
 				break;
 			case 4:
-				data[3] =
-				  ((csr14 >> 9) & 0x07C0) +
-				  ((inl (ioaddr + CSR6) >> 3) & 0x0040) +
-				  ((csr14 >> 1) & 0x20) + 1;
-				break;
-			case 5:
-				data[3] = csr12 >> 16;
-				break;
-			default:
-				data[3] = 0;
+                                /* Advertised value, bogus 10baseTx-FD value from CSR6. */
+                                data[3] =
+					((inl(ioaddr + CSR6) >> 3) & 0x0040) + 
+					((csr14 >> 1) & 0x20) + 1;
+                                if (tp->chip_id != DC21041)
+                                         data[3] |= ((csr14 >> 9) & 0x03C0);
 				break;
+			case 5: data[3] = tp->lpar; break;
+			default: data[3] = 0; break;
 			}
 		} else {
 			data[3] = tulip_mdio_read (dev, data[0] & 0x1f, regnum);
@@ -867,7 +882,8 @@
 					tp->full_duplex = (value & 0x0100) ? 1 : 0;
 				break;
 			case 4:
-				tp->to_advertise = data[2];
+				tp->advertising[phy_idx] =
+				tp->mii_advertise = data[2];
 				break;
 			}
 		}
@@ -877,7 +893,7 @@
 				if ((value & 0x1200) == 0x1200)
 					t21142_start_nway (dev);
 			} else if (regnum == 4)
-				tp->to_advertise = value;
+				tp->sym_advertise = value;
 		} else {
 			tulip_mdio_write (dev, data[0] & 0x1f, regnum, data[2]);
 		}
@@ -998,8 +1014,6 @@
 	long ioaddr = dev->base_addr;
 	int csr6;
 
-	DPRINTK("ENTER\n");
-
 	csr6 = inl(ioaddr + CSR6) & ~0x00D5;
 
 	tp->csr6 &= ~0x00D5;
@@ -1119,6 +1133,91 @@
 	tulip_outl_csr(tp, csr6 | 0x0000, CSR6);
 }
 
+static void __devinit tulip_mwi_config (struct pci_dev *pdev,
+					struct net_device *dev)
+{
+	struct tulip_private *tp = dev->priv;
+	u8 pci_cacheline;
+	u16 pci_command, new_command;
+	unsigned mwi = 1;
+	
+	if (tulip_debug > 3)
+		printk(KERN_DEBUG "%s: tulip_mwi_config()\n", pdev->slot_name);
+
+	/* get a sane cache line size, if possible */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+	if (pci_cacheline < (SMP_CACHE_BYTES / 4))
+		pci_cacheline = SMP_CACHE_BYTES / 4;
+	if (pci_cacheline > TULIP_MAX_CACHE_LINE)
+		pci_cacheline = TULIP_MAX_CACHE_LINE;
+	switch (pci_cacheline) {
+	case 8:
+	case 16:
+	case 32: break;
+	default: pci_cacheline = TULIP_MIN_CACHE_LINE; break;
+	}
+	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, pci_cacheline);
+
+	/* read back the result.  if zero, or if a buggy chip rev,
+	 * disable MWI
+	 */
+	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &pci_cacheline);
+	if (!pci_cacheline || (tp->chip_id == DC21143 && tp->revision == 65))
+		mwi = 0;
+
+	/* re-clamp cache line values to ones supported by tulip */
+	/* From this point forward, 'pci_cacheline' is really
+	 * the value used for csr0 cache alignment and
+	 * csr0 programmable burst length
+	 */
+	switch (pci_cacheline) {
+	case 0:
+	case 8:
+	case 16:
+	case 32: break;
+	default: pci_cacheline = TULIP_MIN_CACHE_LINE; break;
+	}
+
+	/* set or disable MWI in the standard PCI command bit.
+	 * Check for the case where  mwi is desired but not available
+	 */
+	pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+	if (mwi)	new_command = pci_command | PCI_COMMAND_INVALIDATE;
+	else		new_command = pci_command & ~PCI_COMMAND_INVALIDATE;
+	if (new_command != pci_command) {
+		pci_write_config_word(pdev, PCI_COMMAND, new_command);
+		pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
+		if ((new_command != pci_command) && mwi &&
+		    ((pci_command & PCI_COMMAND_INVALIDATE) == 0))
+			mwi = 0;
+	}
+
+	tp->csr0 = MRL | MRM;	
+
+	/* if no PCI cache line size, bail out with minimal
+	 * burst size and cache alignment of 8 dwords.
+	 * We always want to have some sort of limit.
+	 */
+	if (!pci_cacheline) {
+		tp->csr0 |= (8 << BurstLenShift) | (1 << CALShift);
+		goto out;
+	}
+	
+	/* finally, build the csr0 value */
+	if (mwi)
+		tp->csr0 |= MWI;
+	tp->csr0 |= (pci_cacheline << BurstLenShift);
+	switch (pci_cacheline) {
+	case 8:  tp->csr0 |= (1 << CALShift);
+	case 16: tp->csr0 |= (2 << CALShift);
+	case 32: tp->csr0 |= (3 << CALShift);
+	}
+
+out:
+	if (tulip_debug > 2)
+		printk(KERN_DEBUG "%s: MWI config mwi=%d, cacheline=%d, csr0=%08x\n",
+		       pdev->slot_name, mwi, pci_cacheline, tp->csr0);
+}
 
 static int __devinit tulip_init_one (struct pci_dev *pdev,
 				     const struct pci_device_id *ent)
@@ -1136,8 +1235,9 @@
 	long ioaddr;
 	static int board_idx = -1;
 	int chip_idx = ent->driver_data;
-	int t2104x_mode = 0;
-	int eeprom_missing = 0;
+	unsigned int t2104x_mode = 0;
+	unsigned int eeprom_missing = 0;
+	unsigned int force_csr0 = 0;
 
 #ifndef MODULE
 	static int did_version;		/* Already printed version info. */
@@ -1183,12 +1283,26 @@
 	   thankfully its an old 486 chipset.
 	*/
 	
-	if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL))
-		csr0 = 0x00A04800;
+	if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82424, NULL)) {
+		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
+		force_csr0 = 1;
+	}
 	/* The dreaded SiS496 486 chipset. Same workaround as above. */
-	if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL))
-		csr0 = 0x00A04800;
+	if (pci_find_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, NULL)) {
+		csr0 = MRL | MRM | (8 << BurstLenShift) | (1 << CALShift);
+		force_csr0 = 1;
+	}
 		
+	/* bugfix: the ASIX must have a burst limit or horrible things happen. */
+	if (chip_idx == AX88140) {
+		if ((csr0 & 0x3f00) == 0)
+			csr0 |= 0x2000;
+	}
+	
+	/* PNIC doesn't have MWI/MRL/MRM... */
+	if (chip_idx == LC82C168)
+		csr0 &= ~0xfff10000; /* zero reserved bits 31:20, 16 */
+
 	/*
 	 *	And back to business
 	 */
@@ -1255,13 +1369,8 @@
 	dev->base_addr = ioaddr;
 	dev->irq = irq;
 
-	/* bugfix: the ASIX must have a burst limit or horrible things happen. */
-	if (chip_idx == AX88140) {
-		if ((tp->csr0 & 0x3f00) == 0)
-			tp->csr0 |= 0x2000;
-	}
-	else if (chip_idx == DC21143  &&  chip_rev == 65)
-		tp->csr0 &= ~0x01000000;
+	if (!force_csr0 && (tp->flags & HAS_PCI_MWI))
+		tulip_mwi_config (pdev, dev);
 
 	/* Stop the chip's Tx and Rx processes. */
 	tulip_stop_rxtx(tp, inl(ioaddr + CSR6));
@@ -1373,8 +1482,8 @@
 	if (dev->mem_start & MEDIA_MASK)
 		tp->default_port = dev->mem_start & MEDIA_MASK;
 	if (tp->default_port) {
-		printk(KERN_INFO "%s: Transceiver selection forced to %s.\n",
-		       pdev->slot_name, medianame[tp->default_port & MEDIA_MASK]);
+		printk(KERN_INFO "tulip%d: Transceiver selection forced to %s.\n",
+		       board_idx, medianame[tp->default_port & MEDIA_MASK]);
 		tp->medialock = 1;
 		if (tulip_media_cap[tp->default_port] & MediaAlwaysFD)
 			tp->full_duplex = 1;
@@ -1384,11 +1493,9 @@
 
 	if (tulip_media_cap[tp->default_port] & MediaIsMII) {
 		u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };
-		tp->to_advertise = media2advert[tp->default_port - 9];
-	} else if (tp->flags & HAS_8023X)
-		tp->to_advertise = 0x05e1;
-	else
-		tp->to_advertise = 0x01e1;
+		tp->mii_advertise = media2advert[tp->default_port - 9];
+		tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */
+	}
 
 	if (tp->flags & HAS_MEDIA_TABLE) {
 		memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
@@ -1401,55 +1508,21 @@
 	if ((tp->flags & ALWAYS_CHECK_MII) ||
 		(tp->mtable  &&  tp->mtable->has_mii) ||
 		( ! tp->mtable  &&  (tp->flags & HAS_MII))) {
-		int phyn, phy_idx = 0;
 		if (tp->mtable  &&  tp->mtable->has_mii) {
 			for (i = 0; i < tp->mtable->leafcount; i++)
 				if (tp->mtable->mleaf[i].media == 11) {
 					tp->cur_index = i;
 					tp->saved_if_port = dev->if_port;
-					tulip_select_media(dev, 1);
+					tulip_select_media(dev, 2);
 					dev->if_port = tp->saved_if_port;
 					break;
 				}
 		}
+
 		/* Find the connected MII xcvrs.
-		   Doing this in open() would allow detecting external xcvrs later,
-		   but takes much time. */
-		for (phyn = 1; phyn <= 32 && phy_idx < sizeof(tp->phys); phyn++) {
-			int phy = phyn & 0x1f;
-			int mii_status = tulip_mdio_read(dev, phy, 1);
-			if ((mii_status & 0x8301) == 0x8001 ||
-				((mii_status & 0x8000) == 0  && (mii_status & 0x7800) != 0)) {
-				int mii_reg0 = tulip_mdio_read(dev, phy, 0);
-				int mii_advert = tulip_mdio_read(dev, phy, 4);
-				int reg4 = ((mii_status>>6) & tp->to_advertise) | 1;
-				tp->phys[phy_idx] = phy;
-				tp->advertising[phy_idx++] = reg4;
-				printk(KERN_INFO "%s:  MII transceiver #%d "
-					   "config %4.4x status %4.4x advertising %4.4x.\n",
-					   pdev->slot_name, phy, mii_reg0, mii_status, mii_advert);
-				/* Fixup for DLink with miswired PHY. */
-				if (mii_advert != reg4) {
-					printk(KERN_DEBUG "%s:  Advertising %4.4x on PHY %d,"
-						   " previously advertising %4.4x.\n",
-						   pdev->slot_name, reg4, phy, mii_advert);
-					printk(KERN_DEBUG "%s:  Advertising %4.4x (to advertise"
-						   " is %4.4x).\n",
-						   pdev->slot_name, reg4, tp->to_advertise);
-					tulip_mdio_write(dev, phy, 4, reg4);
-				}
-				/* Enable autonegotiation: some boards default to off. */
-				tulip_mdio_write(dev, phy, 0, mii_reg0 |
-						   (tp->full_duplex ? 0x1100 : 0x1000) |
-						   (tulip_media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));
-			}
-		}
-		tp->mii_cnt = phy_idx;
-		if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {
-			printk(KERN_INFO "%s: ***WARNING***: No MII transceiver found!\n",
-			       pdev->slot_name);
-			tp->phys[0] = 1;
-		}
+		   Doing this in open() would allow detecting external xcvrs
+		   later, but takes much time. */
+		tulip_find_mii (dev, board_idx);
 	}
 
 	/* The Tulip-specific entries in the device structure. */
@@ -1481,18 +1554,21 @@
 
 	if ((tp->flags & HAS_NWAY)  || tp->chip_id == DC21041)
 		tp->link_change = t21142_lnk_change;
+	else if (tp->chip_id == PNIC2)
+		tp->link_change = pnic2_lnk_change;
 	else if (tp->flags & HAS_PNICNWAY)
 		tp->link_change = pnic_lnk_change;
 
 	/* Reset the xcvr interface and turn on heartbeat. */
 	switch (chip_idx) {
 	case DC21041:
-		tp->to_advertise = 0x0061;
+		if (tp->sym_advertise == 0)
+			tp->sym_advertise = 0x0061;
 		outl(0x00000000, ioaddr + CSR13);
 		outl(0xFFFFFFFF, ioaddr + CSR14);
 		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
 		tulip_outl_csr(tp, inl(ioaddr + CSR6) | csr6_fd, CSR6);
-		outl(0x0000EF05, ioaddr + CSR13);
+		outl(0x0000EF01, ioaddr + CSR13);
 		break;
 	case DC21040:
 		outl(0x00000000, ioaddr + CSR13);
@@ -1552,7 +1628,6 @@
 err_out_free_res:
 	pci_release_regions (pdev);
 err_out_free_netdev:
-	unregister_netdev (dev);
 	kfree (dev);
 	return -ENODEV;
 }
diff -urN linux-2.4.5-pre2/drivers/net/wan/comx-hw-comx.c linux/drivers/net/wan/comx-hw-comx.c
--- linux-2.4.5-pre2/drivers/net/wan/comx-hw-comx.c	Mon Oct  2 12:00:16 2000
+++ linux/drivers/net/wan/comx-hw-comx.c	Mon Dec  3 22:43:26 2001
@@ -1045,8 +1045,13 @@
 			return -ENOMEM;
 		}
 		copy_from_user(page, buffer, count = (min(count, PAGE_SIZE)));
-		if (*(page + count - 1) == '\n') {
-			*(page + count - 1) = 0;
+		if (page[count-1] == '\n')
+			page[count-1] = '\0';
+		else if (count < PAGE_SIZE)
+			page[count] = '\0';
+		else if (page[count]) {
+			count = -EINVAL;
+			goto out;
 		}
 	} else {
 		byte *tmp;
@@ -1140,7 +1145,7 @@
 			hw->clock = kbps ? COMX_CLOCK_CONST/kbps : 0;
 		}
 	}
-
+out:
 	free_page((unsigned long)page);
 	return count;
 }
diff -urN linux-2.4.5-pre2/drivers/net/wan/comx.c linux/drivers/net/wan/comx.c
--- linux-2.4.5-pre2/drivers/net/wan/comx.c	Tue Mar  6 19:44:36 2001
+++ linux/drivers/net/wan/comx.c	Mon Dec  3 22:43:26 2001
@@ -623,7 +623,14 @@
 
 	copy_from_user(page, buffer, count);
 
-	if (*(page + count - 1) == '\n') *(page + count - 1) = 0;
+	if (page[count-1] == '\n')
+		page[count-1] = '\0';
+	else if (count < PAGE_SIZE)
+		page[count] = '\0';
+	else if (page[count]) {
+		count = -EINVAL;
+		goto out;
+	}
 
 	if (strcmp(entry->name, FILENAME_DEBUG) == 0) {
 		int i;
@@ -764,7 +771,7 @@
 			}
 		}
 	}
-
+out:
 	free_page((unsigned long)page);
 	return count;
 }
diff -urN linux-2.4.5-pre2/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- linux-2.4.5-pre2/drivers/net/yellowfin.c	Fri Apr 20 11:54:23 2001
+++ linux/drivers/net/yellowfin.c	Mon Dec  3 22:43:26 2001
@@ -29,6 +29,11 @@
 	LK1.1.2 (jgarzik):
 	* Merge in becker version 1.05
 
+	LK1.1.3 (jgarzik):
+	* Various cleanups
+	* Update yellowfin_timer to correctly calculate duplex.
+	(suggested by Manfred Spraul)
+	
 */
 
 /* The user-configurable values.
@@ -99,6 +104,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/mii.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
@@ -111,7 +117,7 @@
 static char version[] __devinitdata =
 KERN_INFO "yellowfin.c:v1.05  1/09/2001  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO "  http://www.scyld.com/network/yellowfin.html\n"
-KERN_INFO "  (unofficial 2.4.x port, LK1.1.2, January 11, 2001)\n";
+KERN_INFO "  (unofficial 2.4.x port, LK1.1.3, May 10, 2001)\n";
 
 /* Condensed operations for readability. */
 #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
@@ -652,22 +658,19 @@
 	}
 
 	if (yp->mii_cnt) {
-		int mii_reg1 = mdio_read(ioaddr, yp->phys[0], 1);
-		int mii_reg5 = mdio_read(ioaddr, yp->phys[0], 5);
-		int negotiated = mii_reg5 & yp->advertising;
+		int bmsr = mdio_read(ioaddr, yp->phys[0], MII_BMSR);
+		int lpa = mdio_read(ioaddr, yp->phys[0], MII_LPA);
+		int negotiated = lpa & yp->advertising;
 		if (yellowfin_debug > 1)
 			printk(KERN_DEBUG "%s: MII #%d status register is %4.4x, "
 				   "link partner capability %4.4x.\n",
-				   dev->name, yp->phys[0], mii_reg1, mii_reg5);
+				   dev->name, yp->phys[0], bmsr, lpa);
 
-		if ( ! yp->duplex_lock &&
-			 ((negotiated & 0x0300) == 0x0100
-			  || (negotiated & 0x00C0) == 0x0040)) {
-			yp->full_duplex = 1;
-		}
+		yp->full_duplex = mii_duplex(yp->duplex_lock, negotiated);
+			
 		outw(0x101C | (yp->full_duplex ? 2 : 0), ioaddr + Cnfg);
 
-		if (mii_reg1 & 0x0004)
+		if (bmsr & BMSR_LSTATUS)
 			next_tick = 60*HZ;
 		else
 			next_tick = 3*HZ;
diff -urN linux-2.4.5-pre2/drivers/parport/init.c linux/drivers/parport/init.c
--- linux-2.4.5-pre2/drivers/parport/init.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/parport/init.c	Mon Dec  3 22:43:26 2001
@@ -165,6 +165,8 @@
 	return 0;
 }
 
+__initcall(parport_init);
+
 #endif
 
 /* Exported symbols for modules. */
diff -urN linux-2.4.5-pre2/drivers/pci/pci.c linux/drivers/pci/pci.c
--- linux-2.4.5-pre2/drivers/pci/pci.c	Mon Dec  3 22:43:16 2001
+++ linux/drivers/pci/pci.c	Mon Dec  3 22:43:26 2001
@@ -1484,7 +1484,7 @@
 	page->vaddr = pci_alloc_consistent (pool->dev,
 				pool->allocation, &page->dma);
 	if (page->vaddr) {
-		memset (page->bitmap, ~0, mapsize);	// bit set == free
+		memset (page->bitmap, 0xff, mapsize);	// bit set == free
 		if (pool->flags & SLAB_POISON)
 			memset (page->vaddr, POOL_POISON_BYTE, pool->allocation);
 		list_add (&page->page_list, &pool->page_list);
@@ -1500,7 +1500,7 @@
 is_page_busy (int blocks, unsigned long *bitmap)
 {
 	while (blocks > 0) {
-		if (*bitmap++ != ~0)
+		if (*bitmap++ != ~0UL)
 			return 1;
 		blocks -= BITS_PER_LONG;
 	}
@@ -1589,9 +1589,8 @@
 				i += BITS_PER_LONG, map++) {
 			if (page->bitmap [map] == 0)
 				continue;
-			block = ffs (page->bitmap [map]);
-			if ((i + block) <= pool->blocks_per_page) {
-				block--;
+			block = ffz (~ page->bitmap [map]);
+			if ((i + block) < pool->blocks_per_page) {
 				clear_bit (block, &page->bitmap [map]);
 				offset = (BITS_PER_LONG * map) + block;
 				offset *= pool->size;
@@ -1687,7 +1686,7 @@
 	block %= BITS_PER_LONG;
 
 #ifdef	CONFIG_PCIPOOL_DEBUG
-	if (page->bitmap [map] & (1 << block)) {
+	if (page->bitmap [map] & (1UL << block)) {
 		printk (KERN_ERR "pci_pool_free %s/%s, dma %x already free\n",
 			pool->dev ? pool->dev->slot_name : NULL,
 			pool->name, dma);
diff -urN linux-2.4.5-pre2/drivers/pci/proc.c linux/drivers/pci/proc.c
--- linux-2.4.5-pre2/drivers/pci/proc.c	Fri Nov 17 16:51:47 2000
+++ linux/drivers/pci/proc.c	Mon Dec  3 22:43:26 2001
@@ -191,10 +191,106 @@
 	return nbytes;
 }
 
+struct pci_filp_private {
+	enum pci_mmap_state mmap_state;
+	int write_combine;
+};
+
+static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct pci_dev *dev = dp->data;
+#ifdef HAVE_PCI_MMAP
+	struct pci_filp_private *fpriv = file->private_data;
+#endif /* HAVE_PCI_MMAP */
+	int ret = 0;
+
+	switch (cmd) {
+	case PCIIOC_CONTROLLER:
+		ret = pci_controller_num(dev);
+		break;
+
+#ifdef HAVE_PCI_MMAP
+	case PCIIOC_MMAP_IS_IO:
+		fpriv->mmap_state = pci_mmap_io;
+		break;
+
+	case PCIIOC_MMAP_IS_MEM:
+		fpriv->mmap_state = pci_mmap_mem;
+		break;
+
+	case PCIIOC_WRITE_COMBINE:
+		if (arg)
+			fpriv->write_combine = 1;
+		else
+			fpriv->write_combine = 0;
+		break;
+
+#endif /* HAVE_PCI_MMAP */
+
+	default:
+		ret = -EINVAL;
+		break;
+	};
+
+	return ret;
+}
+
+#ifdef HAVE_PCI_MMAP
+static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct inode *inode = file->f_dentry->d_inode;
+	const struct proc_dir_entry *dp = inode->u.generic_ip;
+	struct pci_dev *dev = dp->data;
+	struct pci_filp_private *fpriv = file->private_data;
+	int ret;
+
+	ret = pci_mmap_page_range(dev, vma,
+				  fpriv->mmap_state,
+				  fpriv->write_combine);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int proc_bus_pci_open(struct inode *inode, struct file *file)
+{
+	struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
+
+	if (!fpriv)
+		return -ENOMEM;
+
+	fpriv->mmap_state = pci_mmap_io;
+	fpriv->write_combine = 0;
+
+	file->private_data = fpriv;
+
+	return 0;
+}
+
+static int proc_bus_pci_release(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	file->private_data = NULL;
+
+	return 0;
+}
+#endif /* HAVE_PCI_MMAP */
+
 static struct file_operations proc_bus_pci_operations = {
-	llseek:	proc_bus_pci_lseek,
-	read:	proc_bus_pci_read,
-	write:	proc_bus_pci_write,
+	llseek:		proc_bus_pci_lseek,
+	read:		proc_bus_pci_read,
+	write:		proc_bus_pci_write,
+	ioctl:		proc_bus_pci_ioctl,
+#ifdef HAVE_PCI_MMAP
+	open:		proc_bus_pci_open,
+	release:	proc_bus_pci_release,
+	mmap:		proc_bus_pci_mmap,
+#ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+	get_unmapped_area: get_pci_unmapped_area,
+#endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
+#endif /* HAVE_PCI_MMAP */
 };
 
 #if BITS_PER_LONG == 32
diff -urN linux-2.4.5-pre2/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- linux-2.4.5-pre2/drivers/pci/quirks.c	Thu Apr 19 22:57:06 2001
+++ linux/drivers/pci/quirks.c	Mon Dec  3 22:43:26 2001
@@ -12,6 +12,7 @@
  *  use the PowerTweak utility (see http://powertweak.sourceforge.net).
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -238,6 +239,30 @@
 	quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
 }
 
+
+#ifdef CONFIG_X86_IO_APIC 
+extern int nr_ioapics;
+
+/*
+ * VIA 686A/B: If an IO-APIC is active, we need to route all on-chip
+ * devices to the external APIC.
+ */
+static void __init quirk_via_ioapic(struct pci_dev *dev)
+{
+	u8 tmp;
+	
+	if (nr_ioapics < 1)
+		tmp = 0;    /* nothing routed to external APIC */
+	else
+		tmp = 0x1f; /* all known bits (4-0) routed to external APIC */
+		
+	/* Offset 0x58: External APIC IRQ output control */
+	pci_write_config_byte (dev, 0x58, tmp);
+}
+
+#endif /* CONFIG_X86_IO_APIC */
+
+
 /*
  * PIIX3 USB: We have to disable USB interrupts that are
  * hardwired to PIRQD# and may be shared with an
@@ -322,6 +347,11 @@
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371SB_2,	quirk_piix3_usb },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_2,	quirk_piix3_usb },
 	{ PCI_FIXUP_FINAL,	PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy },
+
+#ifdef CONFIG_X86_IO_APIC 
+	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686,	quirk_via_ioapic },
+#endif
+
 	{ 0 }
 };
 
diff -urN linux-2.4.5-pre2/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c
--- linux-2.4.5-pre2/drivers/pci/setup-res.c	Fri Apr  6 10:51:19 2001
+++ linux/drivers/pci/setup-res.c	Mon Dec  3 22:43:26 2001
@@ -115,7 +115,8 @@
 		 * window (it will just not perform as well).
 		 */
 		if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
-			printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n", i, dev->name);
+			printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
+			       i, res->start, res->end, dev->slot_name);
 			return -EBUSY;
 		}
 	}
diff -urN linux-2.4.5-pre2/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c
--- linux-2.4.5-pre2/drivers/s390/block/dasd.c	Wed Apr 11 19:02:28 2001
+++ linux/drivers/s390/block/dasd.c	Mon Dec  3 22:43:26 2001
@@ -2892,7 +2892,7 @@
 static ssize_t
 dasd_devices_write (struct file *file, const char *user_buf, size_t user_len, loff_t * offset)
 {
-	char *buffer = vmalloc (user_len);
+	char *buffer = vmalloc (user_len+1);
 	int off = 0;
 	char *temp;
         int irq;
diff -urN linux-2.4.5-pre2/drivers/sbus/char/aurora.c linux/drivers/sbus/char/aurora.c
--- linux-2.4.5-pre2/drivers/sbus/char/aurora.c	Sun Mar 25 18:14:20 2001
+++ linux/drivers/sbus/char/aurora.c	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/*	$Id: aurora.c,v 1.11 2001/03/08 01:43:30 davem Exp $
+/*	$Id: aurora.c,v 1.13 2001/05/10 01:45:38 davem Exp $
  *	linux/drivers/sbus/char/aurora.c -- Aurora multiport driver
  *
  *	Copyright (c) 1999 by Oliver Aldulea (oli@bv.ro)
@@ -1632,33 +1632,55 @@
 	if (!tty || !port->xmit_buf || !tmp_buf)
 		return 0;
 
-	if (from_user)
-		down(&tmp_buf_sem);
-
 	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0)
+				break;
 
-		if (from_user) {
-			copy_from_user(tmp_buf, buf, c);
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - port->xmit_head));
 			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, c);
-		} else
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - port->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
 			memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+			port->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
-	if (from_user)
-		up(&tmp_buf_sem);
+
+	cli();
 	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
 	    !(port->SRER & SRER_TXRDY)) {
 		port->SRER |= SRER_TXRDY;
diff -urN linux-2.4.5-pre2/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- linux-2.4.5-pre2/drivers/sbus/char/pcikbd.c	Sun Mar 25 18:14:20 2001
+++ linux/drivers/sbus/char/pcikbd.c	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.53 2001/03/21 00:28:33 davem Exp $
+/* $Id: pcikbd.c,v 1.54 2001/05/11 07:46:28 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -28,6 +28,9 @@
 #include <linux/init.h>
 
 #include <asm/ebus.h>
+#if defined(CONFIG_USB) && defined(CONFIG_SPARC64)
+#include <asm/isa.h>
+#endif
 #include <asm/oplib.h>
 #include <asm/irq.h>
 #include <asm/io.h>
@@ -451,6 +454,47 @@
 	}
 	restore_flags(flags);
 }
+
+#if defined(CONFIG_USB) && defined(CONFIG_SPARC64)
+static void isa_kd_nosound(unsigned long __unused)
+{
+	/* disable counter 2 */
+	outb(inb(pcibeep_iobase + 0x61)&0xFC, pcibeep_iobase + 0x61);
+	return;
+}
+
+static void isa_kd_mksound(unsigned int hz, unsigned int ticks)
+{
+	static struct timer_list sound_timer = { function: isa_kd_nosound };
+	unsigned int count = 0;
+	unsigned long flags;
+
+	if (hz > 20 && hz < 32767)
+		count = 1193180 / hz;
+	
+	save_flags(flags);
+	cli();
+	del_timer(&sound_timer);
+	if (count) {
+		/* enable counter 2 */
+		outb(inb(pcibeep_iobase + 0x61)|3, pcibeep_iobase + 0x61);
+		/* set command for counter 2, 2 byte write */
+		outb(0xB6, pcibeep_iobase + 0x43);
+		/* select desired HZ */
+		outb(count & 0xff, pcibeep_iobase + 0x42);
+		outb((count >> 8) & 0xff, pcibeep_iobase + 0x42);
+
+		if (ticks) {
+			sound_timer.expires = jiffies+ticks;
+			add_timer(&sound_timer);
+		}
+	} else
+		isa_kd_nosound(0);
+	restore_flags(flags);
+	return;
+}
+#endif
+
 #endif
 
 static void nop_kd_mksound(unsigned int hz, unsigned int ticks)
@@ -550,6 +594,30 @@
 				}
 			}
 		}
+
+#ifdef CONFIG_SPARC64
+		/* Maybe we have one inside the ALI southbridge? */
+		{
+			struct isa_bridge *isa_br;
+			struct isa_device *isa_dev;
+			for_each_isa(isa_br) {
+				for_each_isadev(isa_dev, isa_br) {
+					/* This is a hack, the 'dma' device node has
+					 * the base of the I/O port space for that PBM
+					 * as it's resource, so we use that. -DaveM
+					 */
+					if (!strcmp(isa_dev->prom_name, "dma")) {
+						pcibeep_iobase = isa_dev->resource.start;
+						kd_mksound = isa_kd_mksound;
+						printk("isa(speaker): iobase[%016lx:%016lx]\n",
+						       pcibeep_iobase + 0x42,
+						       pcibeep_iobase + 0x61);
+						return;
+					}
+				}
+			}
+		}
+#endif
 
 		/* No beeper found, ok complain. */
 #endif
diff -urN linux-2.4.5-pre2/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- linux-2.4.5-pre2/drivers/sbus/char/su.c	Mon Dec  3 22:43:16 2001
+++ linux/drivers/sbus/char/su.c	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.48 2001/04/27 07:02:42 davem Exp $
+/* $Id: su.c,v 1.49 2001/05/11 05:35:02 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -75,6 +75,9 @@
 #include <asm/oplib.h>
 #include <asm/io.h>
 #include <asm/ebus.h>
+#ifdef CONFIG_SPARC64
+#include <asm/isa.h>
+#endif
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 #include <asm/bitops.h>
@@ -2220,7 +2223,7 @@
  */
 static __inline__ void __init show_su_version(void)
 {
-	char *revision = "$Revision: 1.48 $";
+	char *revision = "$Revision: 1.49 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
@@ -2243,6 +2246,10 @@
 	unsigned char status1, status2, scratch, scratch2;
 	struct linux_ebus_device *dev = 0;
 	struct linux_ebus *ebus;
+#ifdef CONFIG_SPARC64
+	struct isa_bridge *isa_br;
+	struct isa_device *isa_dev;
+#endif
 #ifndef __sparc_v9__
 	struct linux_prom_registers reg0;
 #endif
@@ -2263,6 +2270,18 @@
 			}
 		}
 	}
+
+#ifdef CONFIG_SPARC64
+	for_each_isa(isa_br) {
+		for_each_isadev(isa_dev, isa_br) {
+			if (isa_dev->prom_node == info->port_node) {
+				info->port = isa_dev->resource.start;
+				info->irq = isa_dev->irq;
+				goto ebus_done;
+			}
+		}
+	}
+#endif
 
 #ifdef __sparc_v9__
 	/*
diff -urN linux-2.4.5-pre2/drivers/sbus/char/zs.c linux/drivers/sbus/char/zs.c
--- linux-2.4.5-pre2/drivers/sbus/char/zs.c	Mon Dec  3 22:43:16 2001
+++ linux/drivers/sbus/char/zs.c	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.64 2001/04/27 07:02:42 davem Exp $
+/* $Id: zs.c,v 1.65 2001/05/09 07:00:10 davem Exp $
  * zs.c: Zilog serial port driver for the Sparc.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1156,28 +1156,51 @@
 		return 0;
 
 	save_flags(flags);
-	while (1) {
-		cli();		
-		c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
-
-		if (from_user) {
-			down(&tmp_buf_sem);
-			copy_from_user(tmp_buf, buf, c);
+	if (from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0)
+				break;
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!total)
+					total = -EFAULT;
+				break;
+			}
+			cli();
 			c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
 				       SERIAL_XMIT_SIZE - info->xmit_head));
 			memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-			up(&tmp_buf_sem);
-		} else
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE - 1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+
+			buf += c;
+			count -= c;
+			total += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		while (1) {
+			cli();		
+			c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+					   SERIAL_XMIT_SIZE - info->xmit_head));
+			if (c <= 0) {
+				restore_flags(flags);
+				break;
+			}
 			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		info->xmit_cnt += c;
-		restore_flags(flags);
-		buf += c;
-		count -= c;
-		total += c;
+			info->xmit_head = ((info->xmit_head + c) &
+					   (SERIAL_XMIT_SIZE - 1));
+			info->xmit_cnt += c;
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			total += c;
+		}
 	}
 
 	cli();		
@@ -1922,7 +1945,7 @@
 
 static void show_serial_version(void)
 {
-	char *revision = "$Revision: 1.64 $";
+	char *revision = "$Revision: 1.65 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -urN linux-2.4.5-pre2/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- linux-2.4.5-pre2/drivers/scsi/scsi.c	Mon Dec  3 22:43:16 2001
+++ linux/drivers/scsi/scsi.c	Mon Dec  3 22:43:26 2001
@@ -1572,6 +1572,11 @@
 	copy_from_user(buffer, buf, length);
 
 	err = -EINVAL;
+	if (length < PAGE_SIZE)
+		buffer[length] ='\0';
+	else if (buffer[length])
+		goto out;
+
 	if (length < 11 || strncmp("scsi", buffer, 4))
 		goto out;
 
diff -urN linux-2.4.5-pre2/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- linux-2.4.5-pre2/drivers/scsi/scsi_proc.c	Fri Feb  9 11:30:23 2001
+++ linux/drivers/scsi/scsi_proc.c	Mon Dec  3 22:43:26 2001
@@ -105,6 +105,7 @@
 	if (!(page = (char *) __get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
 	copy_from_user(page, buf, count);
+	page[count] = '\0';
 
 	if (hpnt->hostt->proc_info == NULL)
 		ret = -ENOSYS;
diff -urN linux-2.4.5-pre2/drivers/sound/trident.c linux/drivers/sound/trident.c
--- linux-2.4.5-pre2/drivers/sound/trident.c	Mon Dec  3 22:43:16 2001
+++ linux/drivers/sound/trident.c	Mon Dec  3 22:43:26 2001
@@ -732,7 +732,7 @@
 	struct dmabuf *dmabuf = &state->dmabuf;
 	struct trident_channel *channel = dmabuf->channel;
 
-	channel->lba = virt_to_bus(dmabuf->rawbuf);
+	channel->lba = dmabuf->dma_handle;
 	channel->delta = compute_rate_play(dmabuf->rate);
 
 	channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
@@ -808,7 +808,7 @@
 		return;
 	}
 
-	channel->lba = virt_to_bus(dmabuf->rawbuf);
+	channel->lba = dmabuf->dma_handle;
 	channel->delta = compute_rate_rec(dmabuf->rate);
 	if ((card->pci_id == PCI_DEVICE_ID_ALI_5451) && (channel->num == ALI_SPDIF_IN_CHANNEL)) {
 		rate = ali_get_spdif_in_rate(card);
@@ -1074,14 +1074,21 @@
 				}
 			}
 			else {
-				if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER)
-					dmabuf->rawbuf = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA, order);
+				if ((order = state->dmabuf.buforder - 1) >= DMABUF_MINORDER) {
+					dmabuf->rawbuf = pci_alloc_consistent(state->card->pci_dev,
+									      PAGE_SIZE << order,
+									      &dmabuf->dma_handle);
+				}
 				if (!dmabuf->rawbuf) {
 					free_pages((unsigned long)state->dmabuf.rawbuf, state->dmabuf.buforder);
 					state->dmabuf.rawbuf = NULL;
 					i-=2;
-					for (; i >= 0; i--)
-						free_pages((unsigned long)state->other_states[i]->dmabuf.rawbuf, state->other_states[i]->dmabuf.buforder);
+					for (; i >= 0; i--) {
+						pci_free_consistent(state->card->pci_dev,
+								    PAGE_SIZE << state->other_states[i]->dmabuf.buforder,
+								    state->other_states[i]->dmabuf.rawbuf,
+								    state->other_states[i]->dmabuf.dma_handle);
+					}
 					unlock_set_fmt(state);
 					return -ENOMEM;
 				}
@@ -3157,20 +3164,34 @@
 {
 	struct trident_card *card = (struct trident_card *)data;
 	unsigned long flags;
+	char c;
+
+	if (count<0)
+		return -EINVAL;
+	if (count == 0)
+		return 0;
+	if (get_user(&c, buffer))
+		return -EFAULT;
 	
 	spin_lock_irqsave(&card->lock, flags);
-	if (*buffer == '0') {	//default
+	switch (c) {
+	    case '0':
 		ali_setup_spdif_out(card, ALI_PCM_TO_SPDIF_OUT);
 		ali_disable_special_channel(card, ALI_SPDIF_OUT_CHANNEL);
-	}	
-	else if (*buffer == '1')
+		break;
+	    case '1':
 		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT|ALI_SPDIF_OUT_PCM);
-	else if (*buffer == '2')	//AC3 data
+		break;
+	    case '2':
 		ali_setup_spdif_out(card, ALI_SPDIF_OUT_TO_SPDIF_OUT|ALI_SPDIF_OUT_NON_PCM);
-	else if (*buffer == '3') 
+		break;
+	    case '3':
 		ali_disable_spdif_in(card);	//default
-	else if (*buffer == '4')
+		break;
+	    case '4':
 		ali_setup_spdif_in(card);
+		break;
+	}
 	spin_unlock_irqrestore(&card->lock, flags);
 
 	return count;
@@ -3307,14 +3328,23 @@
 {
 	unsigned long iobase;
 	struct trident_card *card;
+	dma_addr_t mask;
+	int bits;
 	u8 revision;
 
 	if (pci_enable_device(pci_dev))
 	    return -ENODEV;
 
-	if (pci_set_dma_mask(pci_dev, TRIDENT_DMA_MASK)) {
+	if (pci_dev->device == PCI_DEVICE_ID_ALI_5451) {
+		mask = 0xffffffff;
+		bits = 32;
+	} else {
+		mask = TRIDENT_DMA_MASK;
+		bits = 30;
+	}
+	if (pci_set_dma_mask(pci_dev, mask)) {
 		printk(KERN_ERR "trident: architecture does not support"
-		       " 30bit PCI busmaster DMA\n");
+		       " %dbit PCI busmaster DMA\n", bits);
 		return -ENODEV;
 	}
 	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
diff -urN linux-2.4.5-pre2/drivers/sound/ymfpci.h linux/drivers/sound/ymfpci.h
--- linux-2.4.5-pre2/drivers/sound/ymfpci.h	Fri Jan 26 23:31:16 2001
+++ linux/drivers/sound/ymfpci.h	Mon Dec  3 22:43:26 2001
@@ -135,6 +135,8 @@
 #define PCIR_LEGCTRL			0x40
 #define PCIR_ELEGCTRL			0x42
 #define PCIR_DSXGCTRL			0x48
+#define PCIR_DSXPWRCTRL1		0x4a
+#define PCIR_DSXPWRCTRL2		0x4e
 #define PCIR_OPLADR			0x60
 #define PCIR_SBADR			0x62
 #define PCIR_MPUADR			0x64
diff -urN linux-2.4.5-pre2/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c
--- linux-2.4.5-pre2/drivers/telephony/ixj.c	Fri Mar  2 18:38:39 2001
+++ linux/drivers/telephony/ixj.c	Mon Dec  3 22:43:26 2001
@@ -4434,7 +4434,8 @@
 	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
 	if (lcp == NULL)
 		return -ENOMEM;
-	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)))
+	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_CADENCE)) ||
+	    (unsigned)lcp->elements_used >= ~0U/sizeof(IXJ_CADENCE) )
 	{
 		kfree(lcp);
 		return -EFAULT;
diff -urN linux-2.4.5-pre2/drivers/usb/usb-uhci-debug.h linux/drivers/usb/usb-uhci-debug.h
--- linux-2.4.5-pre2/drivers/usb/usb-uhci-debug.h	Sat Jul  8 19:38:16 2000
+++ linux/drivers/usb/usb-uhci-debug.h	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
 		dbg("qh has not QH_TYPE");
 		return;
 	}
-	dbg("QH @ %p/%08lX:", qh, virt_to_bus (qh));
+	dbg("QH @ %p/%08X:", qh, qh->dma_addr);
 
 	if (qh->hw.qh.head & UHCI_PTR_TERM)
 		dbg("    Head Terminate");
@@ -23,6 +23,7 @@
 }
 #endif
 
+#if 0
 static void uhci_show_td (puhci_desc_t td)
 {
 	char *spid;
@@ -42,8 +43,8 @@
 		break;
 	}
 
-	warn("  TD @ %p/%08lX, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x",
-	     td, virt_to_bus (td),
+	warn("  TD @ %p/%08X, MaxLen=%02x DT%d EP=%x Dev=%x PID=(%s) buf=%08x",
+	     td, td->dma_addr,
 	     td->hw.td.info >> 21,
 	     ((td->hw.td.info >> 19) & 1),
 	     (td->hw.td.info >> 15) & 15,
@@ -74,10 +75,15 @@
 		     td->hw.td.link & ~UHCI_PTR_BITS,
 		     (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : "Breadth first"));
 }
+#endif
+
 #ifdef DEBUG
 static void __attribute__((__unused__)) uhci_show_td_queue (puhci_desc_t td)
 {
-	//dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td));
+	//dbg("uhci_show_td_queue %p (%08lX):", td, td->dma_addr);
+#if 1
+	return;
+#else
 	while (1) {
 		uhci_show_td (td);
 		if (td->hw.td.link & UHCI_PTR_TERM)
@@ -89,13 +95,19 @@
 			break;
 		}
 	}
+#endif
 }
 
 static void __attribute__((__unused__)) uhci_show_queue (puhci_desc_t qh)
 {
+#if 0
 	uhci_desc_t *start_qh=qh;
+#endif
 
 	dbg("uhci_show_queue %p:", qh);
+#if 1
+	return;
+#else
 	while (1) {
 		uhci_show_qh (qh);
 
@@ -117,6 +129,7 @@
 			break;
 		}
 	}		
+#endif
 }
 
 static void __attribute__((__unused__)) uhci_show_sc (int port, unsigned short status)
diff -urN linux-2.4.5-pre2/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- linux-2.4.5-pre2/drivers/usb/usb-uhci.c	Fri Apr 27 15:13:07 2001
+++ linux/drivers/usb/usb-uhci.c	Mon Dec  3 22:43:26 2001
@@ -75,7 +75,6 @@
 #define async_dbg dbg //err
 
 #ifdef DEBUG_SLAB
-	static kmem_cache_t *uhci_desc_kmem;
 	static kmem_cache_t *urb_priv_kmem;
 #endif
 
@@ -128,17 +127,17 @@
 {
 
 	if (!list_empty(&s->urb_unlinked)) {
-		s->td1ms->hw.td.status |= TD_CTRL_IOC;
+		s->td1ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC);
 	}
 	else {
-		s->td1ms->hw.td.status &= ~TD_CTRL_IOC;
+		s->td1ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC);
 	}
 
 	if (s->timeout_urbs) {
-		s->td32ms->hw.td.status |= TD_CTRL_IOC;
+		s->td32ms->hw.td.status |= cpu_to_le32(TD_CTRL_IOC);
 	}
 	else {
-		s->td32ms->hw.td.status &= ~TD_CTRL_IOC;
+		s->td32ms->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC);
 	}
 
 	wmb();
@@ -153,7 +152,7 @@
 		return;
 
 	spin_lock_irqsave (&s->qh_lock, flags);
-	s->chain_end->hw.qh.head&=~UHCI_PTR_TERM; 
+	s->chain_end->hw.qh.head&=cpu_to_le32(~UHCI_PTR_TERM);
 	mb();
 	s->loop_usage++;
 	((urb_priv_t*)urb->hcpriv)->use_loop=1;
@@ -172,7 +171,7 @@
 		s->loop_usage--;
 
 		if (!s->loop_usage) {
-			s->chain_end->hw.qh.head|=UHCI_PTR_TERM;
+			s->chain_end->hw.qh.head|=cpu_to_le32(UHCI_PTR_TERM);
 			mb();
 		}
 		((urb_priv_t*)urb->hcpriv)->use_loop=0;
@@ -226,17 +225,16 @@
 
 }
 /*-------------------------------------------------------------------*/
-_static int alloc_td (uhci_desc_t ** new, int flags)
+_static int alloc_td (uhci_t *s, uhci_desc_t ** new, int flags)
 {
-#ifdef DEBUG_SLAB
-	*new= kmem_cache_alloc(uhci_desc_kmem, SLAB_FLAG);
-#else
-	*new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), KMALLOC_FLAG);
-#endif
+	dma_addr_t dma_handle;
+
+	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
 	if (!*new)
 		return -ENOMEM;
-	 memset (*new, 0, sizeof (uhci_desc_t));
-	(*new)->hw.td.link = UHCI_PTR_TERM | (flags & UHCI_PTR_BITS);	// last by default
+	memset (*new, 0, sizeof (uhci_desc_t));
+	(*new)->dma_addr = dma_handle;
+	(*new)->hw.td.link = cpu_to_le32(UHCI_PTR_TERM | (flags & UHCI_PTR_BITS));	// last by default
 	(*new)->type = TD_TYPE;
 	mb();
 	INIT_LIST_HEAD (&(*new)->vertical);
@@ -252,7 +250,7 @@
 	
 	spin_lock_irqsave (&s->td_lock, xxx);
 
-	td->hw.td.link = virt_to_bus (qh) | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH;
+	td->hw.td.link = cpu_to_le32(qh->dma_addr | (flags & UHCI_PTR_DEPTH) | UHCI_PTR_QH);
        
 	mb();
 	spin_unlock_irqrestore (&s->td_lock, xxx);
@@ -272,11 +270,11 @@
 
 	if (qh == prev ) {
 		// virgin qh without any tds
-		qh->hw.qh.element = virt_to_bus (new) | UHCI_PTR_TERM;
+		qh->hw.qh.element = cpu_to_le32(new->dma_addr | UHCI_PTR_TERM);
 	}
 	else {
 		// already tds inserted, implicitely remove TERM bit of prev
-		prev->hw.td.link = virt_to_bus (new) | (flags & UHCI_PTR_DEPTH);
+		prev->hw.td.link = cpu_to_le32(new->dma_addr | (flags & UHCI_PTR_DEPTH));
 	}
 	mb();
 	spin_unlock_irqrestore (&s->td_lock, xxx);
@@ -295,7 +293,7 @@
 	next = list_entry (td->horizontal.next, uhci_desc_t, horizontal);
 	list_add (&new->horizontal, &td->horizontal);
 	new->hw.td.link = td->hw.td.link;
-	td->hw.td.link = virt_to_bus (new);
+	td->hw.td.link = cpu_to_le32(new->dma_addr);
 	mb();
 	spin_unlock_irqrestore (&s->td_lock, flags);	
 	
@@ -340,29 +338,24 @@
 }
 
 /*-------------------------------------------------------------------*/
-_static int delete_desc (uhci_desc_t *element)
+_static int delete_desc (uhci_t *s, uhci_desc_t *element)
 {
-#ifdef DEBUG_SLAB
-	kmem_cache_free(uhci_desc_kmem, element);
-#else
-	kfree (element);
-#endif
+	pci_pool_free(s->desc_pool, element, element->dma_addr);
 	return 0;
 }
 /*-------------------------------------------------------------------*/
 // Allocates qh element
-_static int alloc_qh (uhci_desc_t ** new)
+_static int alloc_qh (uhci_t *s, uhci_desc_t ** new)
 {
-#ifdef DEBUG_SLAB
-	*new= kmem_cache_alloc(uhci_desc_kmem, SLAB_FLAG);
-#else
-	*new = (uhci_desc_t *) kmalloc (sizeof (uhci_desc_t), KMALLOC_FLAG);
-#endif	
+	dma_addr_t dma_handle;
+
+	*new = pci_pool_alloc(s->desc_pool, GFP_DMA | GFP_ATOMIC, &dma_handle);
 	if (!*new)
 		return -ENOMEM;
 	memset (*new, 0, sizeof (uhci_desc_t));
-	(*new)->hw.qh.head = UHCI_PTR_TERM;
-	(*new)->hw.qh.element = UHCI_PTR_TERM;
+	(*new)->dma_addr = dma_handle;
+	(*new)->hw.qh.head = cpu_to_le32(UHCI_PTR_TERM);
+	(*new)->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM);
 	(*new)->type = QH_TYPE;
 	
 	mb();
@@ -387,16 +380,16 @@
 		// (OLD) (POS) -> (OLD) (NEW) (POS)
 		old = list_entry (pos->horizontal.prev, uhci_desc_t, horizontal);
 		list_add_tail (&new->horizontal, &pos->horizontal);
-		new->hw.qh.head = MAKE_QH_ADDR (pos) ;
-		if (!(old->hw.qh.head & UHCI_PTR_TERM))
-			old->hw.qh.head = MAKE_QH_ADDR (new) ;
+		new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (pos)) ;
+		if (!(old->hw.qh.head & cpu_to_le32(UHCI_PTR_TERM)))
+			old->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ;
 	}
 	else {
 		// (POS) (OLD) -> (POS) (NEW) (OLD)
 		old = list_entry (pos->horizontal.next, uhci_desc_t, horizontal);
 		list_add (&new->horizontal, &pos->horizontal);
-		new->hw.qh.head = MAKE_QH_ADDR (old);
-		pos->hw.qh.head = MAKE_QH_ADDR (new) ;
+		new->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (old));
+		pos->hw.qh.head = cpu_to_le32(MAKE_QH_ADDR (new)) ;
 	}
 
 	mb ();
@@ -418,7 +411,7 @@
 	prev->hw.qh.head = element->hw.qh.head;
 
 	dbg("unlink qh %p, pqh %p, nxqh %p, to %08x", element, prev, 
-	    list_entry (element->horizontal.next, uhci_desc_t, horizontal),element->hw.qh.head &~15);
+	    list_entry (element->horizontal.next, uhci_desc_t, horizontal),le32_to_cpu(element->hw.qh.head) &~15);
 	
 	list_del(&element->horizontal);
 
@@ -439,15 +432,15 @@
 		td = list_entry (p, uhci_desc_t, vertical);
 		dbg("unlink td @ %p",td);
 		unlink_td (s, td, 0); // no physical unlink
-		delete_desc (td);
+		delete_desc (s, td);
 	}
 
-	delete_desc (qh);
+	delete_desc (s, qh);
 	
 	return 0;
 }
 /*-------------------------------------------------------------------*/
-_static void clean_td_chain (uhci_desc_t *td)
+_static void clean_td_chain (uhci_t *s, uhci_desc_t *td)
 {
 	struct list_head *p;
 	uhci_desc_t *td1;
@@ -457,18 +450,18 @@
 	
 	while ((p = td->horizontal.next) != &td->horizontal) {
 		td1 = list_entry (p, uhci_desc_t, horizontal);
-		delete_desc (td1);
+		delete_desc (s, td1);
 	}
 	
-	delete_desc (td);
+	delete_desc (s, td);
 }
 
 /*-------------------------------------------------------------------*/
 _static void fill_td (uhci_desc_t *td, int status, int info, __u32 buffer)
 {
-	td->hw.td.status = status;
-	td->hw.td.info = info;
-	td->hw.td.buffer = buffer;
+	td->hw.td.status = cpu_to_le32(status);
+	td->hw.td.info = cpu_to_le32(info);
+	td->hw.td.buffer = cpu_to_le32(buffer);
 }
 /*-------------------------------------------------------------------*/
 // Removes ALL qhs in chain (paranoia!)
@@ -485,24 +478,25 @@
 	if (s->td32ms) {
 	
 		unlink_td(s,s->td32ms,1);
-		delete_desc(s->td32ms);
+		delete_desc(s, s->td32ms);
 	}
 
 	for (n = 0; n < 8; n++) {
 		td = s->int_chain[n];
-		clean_td_chain (td);
+		clean_td_chain (s, td);
 	}
 
 	if (s->iso_td) {
 		for (n = 0; n < 1024; n++) {
 			td = s->iso_td[n];
-			clean_td_chain (td);
+			clean_td_chain (s, td);
 		}
 		kfree (s->iso_td);
 	}
 
 	if (s->framelist)
-		free_page ((unsigned long) s->framelist);
+		pci_free_consistent(s->uhci_pci, PAGE_SIZE,
+				    s->framelist, s->framelist_dma);
 
 	if (s->control_chain) {
 		// completed init_skel?
@@ -519,14 +513,20 @@
 	}
 	else {
 		if (s->ls_control_chain)
-			delete_desc (s->ls_control_chain);
+			delete_desc (s, s->ls_control_chain);
 		if (s->control_chain)
-			 delete_desc(s->control_chain);
+			 delete_desc(s, s->control_chain);
 		if (s->bulk_chain)
-			delete_desc (s->bulk_chain);
+			delete_desc (s, s->bulk_chain);
 		if (s->chain_end)
-			delete_desc (s->chain_end);
+			delete_desc (s, s->chain_end);
 	}
+
+	if (s->desc_pool) {
+		pci_pool_destroy(s->desc_pool);
+		s->desc_pool = NULL;
+	}
+
 	dbg("cleanup_skel finished");	
 }
 /*-------------------------------------------------------------------*/
@@ -539,13 +539,22 @@
 	
 	dbg("init_skel");
 	
-	s->framelist = (__u32 *) get_free_page (GFP_KERNEL);
+	s->framelist = pci_alloc_consistent(s->uhci_pci, PAGE_SIZE,
+					    &s->framelist_dma);
 
 	if (!s->framelist)
 		return -ENOMEM;
 
 	memset (s->framelist, 0, 4096);
 
+	dbg("creating descriptor pci_pool");
+
+	s->desc_pool = pci_pool_create("uhci_desc", s->uhci_pci,
+				       sizeof(uhci_desc_t), 16, 0,
+				       GFP_DMA | GFP_ATOMIC);	
+	if (!s->desc_pool)
+		goto init_skel_cleanup;
+
 	dbg("allocating iso desc pointer list");
 	s->iso_td = (uhci_desc_t **) kmalloc (1024 * sizeof (uhci_desc_t*), GFP_KERNEL);
 	
@@ -560,33 +569,33 @@
 	dbg("allocating iso descs");
 	for (n = 0; n < 1024; n++) {
 	 	// allocate skeleton iso/irq-tds
-		ret = alloc_td (&td, 0);
+		ret = alloc_td (s, &td, 0);
 		if (ret)
 			goto init_skel_cleanup;
 		s->iso_td[n] = td;
-		s->framelist[n] = ((__u32) virt_to_bus (td));
+		s->framelist[n] = cpu_to_le32((__u32) td->dma_addr);
 	}
 
 	dbg("allocating qh: chain_end");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	
 	if (ret)
 		goto init_skel_cleanup;
 				
 	s->chain_end = qh;
 
-	ret = alloc_td (&td, 0);
+	ret = alloc_td (s, &td, 0);
 
 	if (ret)
 		goto init_skel_cleanup;
 	
 	fill_td (td, 0 * TD_CTRL_IOC, 0, 0); // generate 1ms interrupt (enabled on demand)
 	insert_td (s, qh, td, 0);
-	qh->hw.qh.element &= ~UHCI_PTR_TERM; // remove TERM bit
+	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM); // remove TERM bit
 	s->td1ms=td;
 
 	dbg("allocating qh: bulk_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -594,7 +603,7 @@
 	s->bulk_chain = qh;
 
 	dbg("allocating qh: control_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -603,11 +612,11 @@
 
 #ifdef	CONFIG_USB_UHCI_HIGH_BANDWIDTH
 	// disabled reclamation loop
-	s->chain_end->hw.qh.head=virt_to_bus(s->control_chain) | UHCI_PTR_QH | UHCI_PTR_TERM;
+	s->chain_end->hw.qh.head = cpu_to_le32(s->control_chain->dma_addr | UHCI_PTR_QH | UHCI_PTR_TERM);
 #endif
 
 	dbg("allocating qh: ls_control_chain");
-	ret = alloc_qh (&qh);
+	ret = alloc_qh (s, &qh);
 	if (ret)
 		goto init_skel_cleanup;
 	
@@ -622,15 +631,15 @@
 	for (n = 0; n < 8; n++) {
 		uhci_desc_t *td;
 
-		alloc_td (&td, 0);
+		alloc_td (s, &td, 0);
 		if (!td)
 			goto init_skel_cleanup;
 		s->int_chain[n] = td;
 		if (n == 0) {
-			s->int_chain[0]->hw.td.link = virt_to_bus (s->ls_control_chain) | UHCI_PTR_QH;
+			s->int_chain[0]->hw.td.link = cpu_to_le32(s->ls_control_chain->dma_addr | UHCI_PTR_QH);
 		}
 		else {
-			s->int_chain[n]->hw.td.link = virt_to_bus (s->int_chain[0]);
+			s->int_chain[n]->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr);
 		}
 	}
 
@@ -639,16 +648,17 @@
 	for (n = 0; n < 1024; n++) {
 		// link all iso-tds to the interrupt chains
 		int m, o;
-		dbg("framelist[%i]=%x",n,s->framelist[n]);
+		dbg("framelist[%i]=%x",n,le32_to_cpu(s->framelist[n]));
 		if ((n&127)==127) 
-			((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus(s->int_chain[0]);
+			((uhci_desc_t*) s->iso_td[n])->hw.td.link = cpu_to_le32(s->int_chain[0]->dma_addr);
 		else 
 			for (o = 1, m = 2; m <= 128; o++, m += m)
 				if ((n & (m - 1)) == ((m - 1) / 2))
-					((uhci_desc_t*) s->iso_td[n])->hw.td.link = virt_to_bus (s->int_chain[o]);
+					((uhci_desc_t*) s->iso_td[n])->hw.td.link =
+						cpu_to_le32(s->int_chain[o]->dma_addr);
 	}
 
-	ret = alloc_td (&td, 0);
+	ret = alloc_td (s, &td, 0);
 
 	if (ret)
 		goto init_skel_cleanup;
@@ -689,12 +699,12 @@
 	}
 
 	dbg("uhci_submit_control start");
-	alloc_qh (&qh);		// alloc qh for this request
+	alloc_qh (s, &qh);		// alloc qh for this request
 
 	if (!qh)
 		return -ENOMEM;
 
-	alloc_td (&td, UHCI_PTR_DEPTH * depth_first);		// get td for setup stage
+	alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);		// get td for setup stage
 
 	if (!td) {
 		delete_qh (s, qh);
@@ -709,7 +719,7 @@
 		(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
 
 	/*  Build the TD for the control request, try forever, 8 bytes of data */
-	fill_td (td, status, destination | (7 << 21), virt_to_bus (urb->setup_packet));
+	fill_td (td, status, destination | (7 << 21), urb_priv->setup_packet_dma);
 
 	insert_td (s, qh, td, 0);	// queue 'setup stage'-td in qh
 #if 0
@@ -732,19 +742,18 @@
 	while (len > 0) {
 		int pktsze = len;
 
-		alloc_td (&td, UHCI_PTR_DEPTH * depth_first);
-		if (!td) {
-			delete_qh (s, qh);
-			return -ENOMEM;
-		}
+		alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);
+		if (!td)
+			goto fail_unmap_enomem;
 
 		if (pktsze > maxsze)
 			pktsze = maxsze;
 
 		destination ^= 1 << TD_TOKEN_TOGGLE;	// toggle DATA0/1
 
+		// Status, pktsze bytes of data
 		fill_td (td, status, destination | ((pktsze - 1) << 21),
-			 virt_to_bus (data));	// Status, pktsze bytes of data
+			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
 
 		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);	// queue 'data stage'-td in qh
 
@@ -764,12 +773,11 @@
 
 	destination |= 1 << TD_TOKEN_TOGGLE;	/* End in Data1 */
 
-	alloc_td (&td, UHCI_PTR_DEPTH);
+	alloc_td (s, &td, UHCI_PTR_DEPTH);
 	
-	if (!td) {
-		delete_qh (s, qh);
-		return -ENOMEM;
-	}
+	if (!td)
+		goto fail_unmap_enomem;
+
 	status &=~TD_CTRL_SPD;
 
 	/* no limit on errors on final packet , 0 bytes of data */
@@ -783,7 +791,7 @@
 	urb->status = -EINPROGRESS;
 	queue_urb (s, urb);	// queue before inserting in desc chain
 
-	qh->hw.qh.element &= ~UHCI_PTR_TERM;
+	qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);
 
 	//uhci_show_queue(qh);
 	/* Start it up... put low speed first */
@@ -794,6 +802,10 @@
 
 	dbg("uhci_submit_control end");
 	return 0;
+
+fail_unmap_enomem:
+	delete_qh(s, qh);
+	return -ENOMEM;
 }
 /*-------------------------------------------------------------------*/
 // For queued bulk transfers, two additional QH helpers are allocated (nqh, bqh)
@@ -829,15 +841,15 @@
 	upriv = (urb_priv_t*)urb->hcpriv;
 
 	if (!bulk_urb) {
-		alloc_qh (&qh);		// get qh for this request
+		alloc_qh (s, &qh);		// get qh for this request
 		
 		if (!qh)
 			return -ENOMEM;
 
 		if (urb->transfer_flags & USB_QUEUE_BULK) {
-			alloc_qh(&nqh); // placeholder for clean unlink
+			alloc_qh(s, &nqh); // placeholder for clean unlink
 			if (!nqh) {
-				delete_desc (qh);
+				delete_desc (s, qh);
 				return -ENOMEM;
 			}
 			upriv->next_qh = nqh;
@@ -853,17 +865,17 @@
 	}
 
 	if (urb->transfer_flags & USB_QUEUE_BULK) {
-		alloc_qh (&bqh); // "bottom" QH,
+		alloc_qh (s, &bqh); // "bottom" QH,
 		
 		if (!bqh) {
 			if (!bulk_urb) { 
-				delete_desc(qh);
-				delete_desc(nqh);
+				delete_desc(s, qh);
+				delete_desc(s, nqh);
 			}
 			return -ENOMEM;
 		}
-		bqh->hw.qh.element = UHCI_PTR_TERM;
-		bqh->hw.qh.head = virt_to_bus(nqh) | UHCI_PTR_QH; // element
+		bqh->hw.qh.element = cpu_to_le32(UHCI_PTR_TERM);
+		bqh->hw.qh.head = cpu_to_le32(nqh->dma_addr | UHCI_PTR_QH); // element
 		upriv->bottom_qh = bqh;
 	}
 	queue_dbg("uhci_submit_bulk: qh %p bqh %p nqh %p",qh, bqh, nqh);
@@ -882,7 +894,7 @@
 	do {					// TBD: Really allow zero-length packets?
 		int pktsze = len;
 
-		alloc_td (&td, UHCI_PTR_DEPTH * depth_first);
+		alloc_td (s, &td, UHCI_PTR_DEPTH * depth_first);
 
 		if (!td) {
 			delete_qh (s, qh);
@@ -896,7 +908,8 @@
 		info = destination | (((pktsze - 1)&UHCI_NULL_DATA_SIZE) << 21) |
 			(usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
 
-		fill_td (td, status, info, virt_to_bus (data));
+		fill_td (td, status, info,
+			 urb_priv->transfer_buffer_dma + (data - (char *)urb->transfer_buffer));
 
 		data += pktsze;
 		len -= pktsze;
@@ -904,7 +917,7 @@
 		last = (len == 0 && (usb_pipein(pipe) || pktsze < maxsze || !(urb->transfer_flags & USB_ZERO_PACKET)));
 
 		if (last)
-			td->hw.td.status |= TD_CTRL_IOC;	// last one generates INT
+			td->hw.td.status |= cpu_to_le32(TD_CTRL_IOC);	// last one generates INT
 
 		insert_td (s, qh, td, UHCI_PTR_DEPTH * depth_first);
 		if (!first_td)
@@ -925,9 +938,9 @@
 	queue_urb_unlocked (s, urb);
 	
 	if (urb->transfer_flags & USB_QUEUE_BULK)
-		qh->hw.qh.element = virt_to_bus (first_td);
+		qh->hw.qh.element = cpu_to_le32(first_td->dma_addr);
 	else
-		qh->hw.qh.element &= ~UHCI_PTR_TERM;    // arm QH
+		qh->hw.qh.element &= cpu_to_le32(~UHCI_PTR_TERM);    // arm QH
 
 	if (!bulk_urb) { 					// new bulk queue	
 		if (urb->transfer_flags & USB_QUEUE_BULK) {
@@ -964,7 +977,7 @@
 	while ((p = urb_priv->desc_list.next) != &urb_priv->desc_list) {
 				td = list_entry (p, uhci_desc_t, desc_list);
 				list_del (p);
-				delete_desc (td);
+				delete_desc (s, td);
 	}
 }
 /*-------------------------------------------------------------------*/
@@ -996,7 +1009,7 @@
 				spin_lock_irqsave (&s->qh_lock, flags);
 				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
 				prevtd = list_entry (prevqh->vertical.prev, uhci_desc_t, vertical);
-				prevtd->hw.td.link = virt_to_bus(priv->bottom_qh) | UHCI_PTR_QH; // skip current qh
+				prevtd->hw.td.link = cpu_to_le32(priv->bottom_qh->dma_addr | UHCI_PTR_QH); // skip current qh
 				mb();
 				queue_dbg("uhci_clean_transfer: relink pqh %p, ptd %p",prevqh, prevtd);
 				spin_unlock_irqrestore (&s->qh_lock, flags);
@@ -1039,7 +1052,7 @@
 			if (!priv->prev_queued_urb) { // top QH
 				
 				prevqh = list_entry (qh->horizontal.prev, uhci_desc_t, horizontal);
-				prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH;
+				prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH);
 				list_del (&qh->horizontal);  // remove this qh form horizontal chain
 				list_add (&bqh->horizontal, &prevqh->horizontal); // insert next bqh in horizontal chain
 			}
@@ -1052,7 +1065,7 @@
 				ppriv->bottom_qh = bnqh;
 				ppriv->next_queued_urb = nurb;				
 				prevqh = list_entry (ppriv->desc_list.next, uhci_desc_t, desc_list);
-				prevqh->hw.qh.head = virt_to_bus(bqh) | UHCI_PTR_QH;
+				prevqh->hw.qh.head = cpu_to_le32(bqh->dma_addr | UHCI_PTR_QH);
 			}
 
 			mb();
@@ -1083,6 +1096,38 @@
 		}
 	}	
 }
+
+_static void uhci_urb_dma_sync(uhci_t *s, urb_t *urb, urb_priv_t *urb_priv)
+{
+	if (urb_priv->setup_packet_dma)
+		pci_dma_sync_single(s->uhci_pci, urb_priv->setup_packet_dma,
+				    sizeof(devrequest), PCI_DMA_TODEVICE);
+
+	if (urb_priv->transfer_buffer_dma)
+		pci_dma_sync_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
+				    urb->transfer_buffer_length,
+				    usb_pipein(urb->pipe) ?
+				    PCI_DMA_FROMDEVICE :
+				    PCI_DMA_TODEVICE);
+}
+
+_static void uhci_urb_dma_unmap(uhci_t *s, urb_t *urb, urb_priv_t *urb_priv)
+{
+	if (urb_priv->setup_packet_dma) {
+		pci_unmap_single(s->uhci_pci, urb_priv->setup_packet_dma,
+				 sizeof(devrequest), PCI_DMA_TODEVICE);
+		urb_priv->setup_packet_dma = 0;
+	}
+	if (urb_priv->transfer_buffer_dma) {
+		pci_unmap_single(s->uhci_pci, urb_priv->transfer_buffer_dma,
+				 urb->transfer_buffer_length,
+				 usb_pipein(urb->pipe) ?
+				 PCI_DMA_FROMDEVICE :
+				 PCI_DMA_TODEVICE);
+		urb_priv->transfer_buffer_dma = 0;
+	}
+}
+
 /*-------------------------------------------------------------------*/
 // unlinks an urb by dequeuing its qh, waits some frames and forgets it
 _static int uhci_unlink_urb_sync (uhci_t *s, urb_t *urb)
@@ -1133,6 +1178,8 @@
 			uhci_wait_ms(1);
 		}
 		
+		uhci_urb_dma_unmap(s, urb, urb->hcpriv);
+
 #ifdef DEBUG_SLAB
 		kmem_cache_free (urb_priv_kmem, urb->hcpriv);
 #else
@@ -1210,6 +1257,7 @@
 			urb_priv = urb->hcpriv;
 			list_del (&urb->urb_list);
 			
+			uhci_urb_dma_sync(s, urb, urb_priv);
 			if (urb->complete) {
 				spin_unlock(&s->urb_list_lock);
 				urb->dev = NULL;
@@ -1226,6 +1274,8 @@
 				break;
 			}
 	
+			uhci_urb_dma_unmap(s, urb, urb_priv);
+
 			usb_dec_dev_use (dev);
 #ifdef DEBUG_SLAB
 			kmem_cache_free (urb_priv_kmem, urb_priv);
@@ -1452,7 +1502,7 @@
 	if (urb->transfer_buffer_length > usb_maxpacket (urb->dev, pipe, usb_pipeout (pipe)))
 		return -EINVAL;
 
-	ret = alloc_td (&td, UHCI_PTR_DEPTH);
+	ret = alloc_td (s, &td, UHCI_PTR_DEPTH);
 
 	if (ret)
 		return -ENOMEM;
@@ -1466,7 +1516,7 @@
 
 	info = destination | (usb_gettoggle (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe)) << TD_TOKEN_TOGGLE);
 
-	fill_td (td, status, info, virt_to_bus (urb->transfer_buffer));
+	fill_td (td, status, info, urb_priv->transfer_buffer_dma);
 	list_add_tail (&td->desc_list, &urb_priv->desc_list);
 
 	urb->status = -EINPROGRESS;
@@ -1524,14 +1574,14 @@
 		}
 		else
 #endif
-		ret = alloc_td (&td, UHCI_PTR_DEPTH);
+		ret = alloc_td (s, &td, UHCI_PTR_DEPTH);
 
 		if (ret) {
 			int i;	// Cleanup allocated TDs
 
 			for (i = 0; i < n; n++)
 				if (tdm[i])
-					 delete_desc(tdm[i]);
+					 delete_desc(s, tdm[i]);
 			kfree (tdm);
 			goto err;
 		}
@@ -1554,7 +1604,7 @@
 			status |= TD_CTRL_IOC;
 
 		fill_td (td, status, destination | (((urb->iso_frame_desc[n].length - 1) & 0x7ff) << 21),
-			 virt_to_bus (urb->transfer_buffer + urb->iso_frame_desc[n].offset));
+			 urb_priv->transfer_buffer_dma + urb->iso_frame_desc[n].offset);
 		list_add_tail (&td->desc_list, &urb_priv->desc_list);
 	
 		if (n == last) {
@@ -1663,6 +1713,22 @@
 	urb_priv->bottom_qh = NULL;
 	urb_priv->next_qh = NULL;
 	
+	if (usb_pipetype (urb->pipe) == PIPE_CONTROL)
+		urb_priv->setup_packet_dma = pci_map_single(s->uhci_pci, urb->setup_packet,
+							    sizeof(devrequest), PCI_DMA_TODEVICE);
+	else
+		urb_priv->setup_packet_dma = 0;
+
+	if (urb->transfer_buffer_length)
+		urb_priv->transfer_buffer_dma = pci_map_single(s->uhci_pci,
+							       urb->transfer_buffer,
+							       urb->transfer_buffer_length,
+							       usb_pipein(urb->pipe) ?
+							       PCI_DMA_FROMDEVICE :
+							       PCI_DMA_TODEVICE);
+	else
+		urb_priv->transfer_buffer_dma = 0;
+
 	if (usb_pipetype (urb->pipe) == PIPE_BULK) {
 	
 		if (queued_urb) {
@@ -1724,6 +1790,7 @@
 	dbg("submit_urb: scheduled with ret: %d", ret);
 	
 	if (ret != 0) {
+		uhci_urb_dma_unmap(s, urb, urb_priv);
 		usb_dec_dev_use (urb->dev);
 #ifdef DEBUG_SLAB
 		kmem_cache_free(urb_priv_kmem, urb_priv);
@@ -2277,7 +2344,7 @@
 	 */
 
 	if (urb_priv->flags && 
-		((qh->hw.qh.element == UHCI_PTR_TERM) ||(!(last_desc->hw.td.status & TD_CTRL_ACTIVE)))) 
+		((qh->hw.qh.element == cpu_to_le32(UHCI_PTR_TERM)) ||(!(last_desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE))))) 
 		goto transfer_finished;
 
 	urb->actual_length=0;
@@ -2285,15 +2352,15 @@
 	for (; p != &qh->vertical; p = p->next) {
 		desc = list_entry (p, uhci_desc_t, vertical);
 
-		if (desc->hw.td.status & TD_CTRL_ACTIVE) {	// do not process active TDs
+		if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) {	// do not process active TDs
 			if (mode==2) // if called from async_unlink
 				uhci_clean_transfer(s, urb, qh, mode);
 			return ret;
 		}
 	
-		actual_length = (desc->hw.td.status + 1) & 0x7ff;		// extract transfer parameters from TD
-		maxlength = (((desc->hw.td.info >> 21) & 0x7ff) + 1) & 0x7ff;
-		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
+		actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff;		// extract transfer parameters from TD
+		maxlength = (((le32_to_cpu(desc->hw.td.info) >> 21) & 0x7ff) + 1) & 0x7ff;
+		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
 
 		if (status == -EPIPE) { 		// see if EP is stalled
 			// set up stalled condition
@@ -2307,7 +2374,7 @@
 			urb->error_count++;
 			break;
 		}
-		else if ((desc->hw.td.info & 0xff) != USB_PID_SETUP)
+		else if ((le32_to_cpu(desc->hw.td.info) & 0xff) != USB_PID_SETUP)
 			urb->actual_length += actual_length;
 
 		// got less data than requested
@@ -2320,9 +2387,9 @@
 
 			// short read during control-IN: re-start status stage
 			if ((usb_pipetype (urb->pipe) == PIPE_CONTROL)) {
-				if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) {
+				if (uhci_packetid(le32_to_cpu(last_desc->hw.td.info)) == USB_PID_OUT) {
 			
-					qh->hw.qh.element = virt_to_bus (last_desc);  // re-trigger status stage
+					qh->hw.qh.element = cpu_to_le32(last_desc->dma_addr);  // re-trigger status stage
 					dbg("short packet during control transfer, retrigger status stage @ %p",last_desc);
 					//uhci_show_td (desc);
 					//uhci_show_td (last_desc);
@@ -2331,14 +2398,14 @@
 				}
 			}
 			// all other cases: short read is OK
-			data_toggle = uhci_toggle (desc->hw.td.info);
+			data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
 			break;
 		}
 		else if (status)
 			goto is_error;
 
-		data_toggle = uhci_toggle (desc->hw.td.info);
-		queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle);      
+		data_toggle = uhci_toggle (le32_to_cpu(desc->hw.td.info));
+		queue_dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, le32_to_cpu(desc->hw.td.status),status, data_toggle);      
 
 	}
 
@@ -2375,20 +2442,20 @@
 	{
 		desc = list_entry (p, uhci_desc_t, desc_list);
 
-		if (desc->hw.td.status & TD_CTRL_ACTIVE) {
+		if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) {
 			// do not process active TDs
-			//dbg("TD ACT Status @%p %08x",desc,desc->hw.td.status);
+			//dbg("TD ACT Status @%p %08x",desc,le32_to_cpu(desc->hw.td.status));
 			break;
 		}
 
-		if (!desc->hw.td.status & TD_CTRL_IOC) {
+		if (!desc->hw.td.status & cpu_to_le32(TD_CTRL_IOC)) {
 			// do not process one-shot TDs, no recycling
 			break;
 		}
 		// extract transfer parameters from TD
 
-		actual_length = (desc->hw.td.status + 1) & 0x7ff;
-		status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
+		actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff;
+		status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
 
 		// see if EP is stalled
 		if (status == -EPIPE) {
@@ -2406,6 +2473,7 @@
 			urb->actual_length = actual_length;
 
 	recycle:
+		uhci_urb_dma_sync(s, urb, urb->hcpriv);
 		if (urb->complete) {
 			//dbg("process_interrupt: calling completion, status %i",status);
 			urb->status = status;
@@ -2428,23 +2496,23 @@
 			// Recycle INT-TD if interval!=0, else mark TD as one-shot
 			if (urb->interval) {
 				
-				desc->hw.td.info &= ~(1 << TD_TOKEN_TOGGLE);
+				desc->hw.td.info &= cpu_to_le32(~(1 << TD_TOKEN_TOGGLE));
 				if (status==0) {
 					((urb_priv_t*)urb->hcpriv)->started=jiffies;
-					desc->hw.td.info |= (usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+					desc->hw.td.info |= cpu_to_le32((usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									    usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
 					usb_dotoggle (urb->dev, usb_pipeendpoint (urb->pipe), usb_pipeout (urb->pipe));
 				} else {
-					desc->hw.td.info |= (!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
-									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE);
+					desc->hw.td.info |= cpu_to_le32((!usb_gettoggle (urb->dev, usb_pipeendpoint (urb->pipe),
+									     usb_pipeout (urb->pipe)) << TD_TOKEN_TOGGLE));
 				}
-				desc->hw.td.status= (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
-					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27);
+				desc->hw.td.status= cpu_to_le32((urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_IOC |
+					(urb->transfer_flags & USB_DISABLE_SPD ? 0 : TD_CTRL_SPD) | (3 << 27));
 				mb();
 			}
 			else {
 				uhci_unlink_urb_async(s, urb);
-				desc->hw.td.status &= ~TD_CTRL_IOC; // inactivate TD
+				desc->hw.td.status &= cpu_to_le32(~TD_CTRL_IOC); // inactivate TD
 			}
 		}
 	}
@@ -2462,23 +2530,23 @@
 	uhci_desc_t *desc = list_entry (urb_priv->desc_list.prev, uhci_desc_t, desc_list);
 
 	dbg("urb contains iso request");
-	if ((desc->hw.td.status & TD_CTRL_ACTIVE) && !mode)
+	if ((desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) && !mode)
 		return -EXDEV;	// last TD not finished
 
 	urb->error_count = 0;
 	urb->actual_length = 0;
 	urb->status = 0;
 	dbg("process iso urb %p, %li, %i, %i, %i %08x",urb,jiffies,UHCI_GET_CURRENT_FRAME(s),
-	    urb->number_of_packets,mode,desc->hw.td.status);
+	    urb->number_of_packets,mode,le32_to_cpu(desc->hw.td.status));
 
 	for (i = 0; p != &urb_priv->desc_list;  i++) {
 		desc = list_entry (p, uhci_desc_t, desc_list);
 		
 		//uhci_show_td(desc);
-		if (desc->hw.td.status & TD_CTRL_ACTIVE) {
+		if (desc->hw.td.status & cpu_to_le32(TD_CTRL_ACTIVE)) {
 			// means we have completed the last TD, but not the TDs before
-			desc->hw.td.status &= ~TD_CTRL_ACTIVE;
-			dbg("TD still active (%x)- grrr. paranoia!", desc->hw.td.status);
+			desc->hw.td.status &= cpu_to_le32(~TD_CTRL_ACTIVE);
+			dbg("TD still active (%x)- grrr. paranoia!", le32_to_cpu(desc->hw.td.status));
 			ret = -EXDEV;
 			urb->iso_frame_desc[i].status = ret;
 			unlink_td (s, desc, 1);
@@ -2495,15 +2563,8 @@
 			goto err;
 		}
 
-		if (urb->iso_frame_desc[i].offset + urb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) {
-			// Hm, something really weird is going on
-			dbg("Pointer Paranoia: %p!=%p", urb->iso_frame_desc[i].offset + urb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
-			ret = -EINVAL;
-			urb->iso_frame_desc[i].status = ret;
-			goto err;
-		}
-		urb->iso_frame_desc[i].actual_length = (desc->hw.td.status + 1) & 0x7ff;
-		urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (desc->hw.td.status), usb_pipeout (urb->pipe));
+		urb->iso_frame_desc[i].actual_length = (le32_to_cpu(desc->hw.td.status) + 1) & 0x7ff;
+		urb->iso_frame_desc[i].status = uhci_map_status (uhci_status_bits (le32_to_cpu(desc->hw.td.status)), usb_pipeout (urb->pipe));
 		urb->actual_length += urb->iso_frame_desc[i].actual_length;
 
 	      err:
@@ -2513,11 +2574,11 @@
 			urb->status = urb->iso_frame_desc[i].status;
 		}
 		dbg("process_iso: %i: len:%d %08x status:%x",
-		     i, urb->iso_frame_desc[i].actual_length, desc->hw.td.status,urb->iso_frame_desc[i].status);
+		     i, urb->iso_frame_desc[i].actual_length, le32_to_cpu(desc->hw.td.status),urb->iso_frame_desc[i].status);
 
 		list_del (p);
 		p = p->next;
-		delete_desc (desc);
+		delete_desc (s, desc);
 	}
 	
 	dbg("process_iso: exit %i (%d), actual_len %i", i, ret,urb->actual_length);
@@ -2552,6 +2613,7 @@
 	}
 
 	if (urb->status != -EINPROGRESS) {
+		urb_priv_t *urb_priv;
 		struct usb_device *usb_dev;
 		
 		usb_dev=urb->dev;
@@ -2567,10 +2629,14 @@
 		dbg("dequeued urb: %p", urb);
 		dequeue_urb (s, urb);
 
+		urb_priv = urb->hcpriv;
+
+		uhci_urb_dma_unmap(s, urb, urb_priv);
+
 #ifdef DEBUG_SLAB
-		kmem_cache_free(urb_priv_kmem, urb->hcpriv);
+		kmem_cache_free(urb_priv_kmem, urb_priv);
 #else
-		kfree (urb->hcpriv);
+		kfree (urb_priv);
 #endif
 
 		if ((usb_pipetype (urb->pipe) != PIPE_INTERRUPT)) {  // process_interrupt does completion on its own		
@@ -2769,7 +2835,7 @@
 
 	/* Start at frame 0 */
 	outw (0, io_addr + USBFRNUM);
-	outl (virt_to_bus (s->framelist), io_addr + USBFLBASEADD);
+	outl (s->framelist_dma, io_addr + USBFLBASEADD);
 
 	/* Run and mark it configured with a 64-byte max packet */
 	outw (USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
@@ -3012,19 +3078,10 @@
 	int retval;
 
 #ifdef DEBUG_SLAB
-
-	uhci_desc_kmem = kmem_cache_create("uhci_desc", sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
-	
-	if(!uhci_desc_kmem) {
-		err("kmem_cache_create for uhci_desc failed (out of memory)");
-		return -ENOMEM;
-	}
-
 	urb_priv_kmem = kmem_cache_create("urb_priv", sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 	
 	if(!urb_priv_kmem) {
 		err("kmem_cache_create for urb_priv_t failed (out of memory)");
-		kmem_cache_destroy(uhci_desc_kmem);
 		return -ENOMEM;
 	}
 #endif	
@@ -3040,8 +3097,6 @@
 	if (retval < 0 ) {
 		if (kmem_cache_destroy(urb_priv_kmem))
 			err("urb_priv_kmem remained");
-		if (kmem_cache_destroy(uhci_desc_kmem))
-			err("uhci_desc_kmem remained");
 	}
 #endif
 	
@@ -3053,9 +3108,6 @@
 	pci_unregister_driver (&uhci_pci_driver);
 	
 #ifdef DEBUG_SLAB
-	if(kmem_cache_destroy(uhci_desc_kmem))
-		err("uhci_desc_kmem remained");
-
 	if(kmem_cache_destroy(urb_priv_kmem))
 		err("urb_priv_kmem remained");
 #endif
diff -urN linux-2.4.5-pre2/drivers/usb/usb-uhci.h linux/drivers/usb/usb-uhci.h
--- linux-2.4.5-pre2/drivers/usb/usb-uhci.h	Mon May 15 12:05:15 2000
+++ linux/drivers/usb/usb-uhci.h	Mon Dec  3 22:43:26 2001
@@ -146,6 +146,7 @@
 		uhci_qh_t qh;
 	} hw;
 	uhci_desc_type_t type;
+	dma_addr_t dma_addr;
 	struct list_head horizontal;
 	struct list_head vertical;
 	struct list_head desc_list;
@@ -154,6 +155,8 @@
 
 typedef struct {
 	struct list_head desc_list;	// list pointer to all corresponding TDs/QHs associated with this request
+	dma_addr_t setup_packet_dma;
+	dma_addr_t transfer_buffer_dma;
 	unsigned long started;
 	urb_t *next_queued_urb;         // next queued urb for this EP
 	urb_t *prev_queued_urb;
@@ -195,6 +198,7 @@
 	struct usb_bus *bus;	// our bus
 
 	__u32 *framelist;
+	dma_addr_t framelist_dma;
 	uhci_desc_t **iso_td;
 	uhci_desc_t *int_chain[8];
 	uhci_desc_t *ls_control_chain;
@@ -213,11 +217,12 @@
 	long timeout_check;
 	int timeout_urbs;
 	struct pci_dev *uhci_pci;
+	struct pci_pool *desc_pool;
 } uhci_t, *puhci_t;
 
 
-#define MAKE_TD_ADDR(a) (virt_to_bus(a)&~UHCI_PTR_QH)
-#define MAKE_QH_ADDR(a) (virt_to_bus(a)|UHCI_PTR_QH)
+#define MAKE_TD_ADDR(a) ((a)->dma_addr&~UHCI_PTR_QH)
+#define MAKE_QH_ADDR(a) ((a)->dma_addr|UHCI_PTR_QH)
 #define UHCI_GET_CURRENT_FRAME(uhci) (inw ((uhci)->io_addr + USBFRNUM))
 
 /* ------------------------------------------------------------------------------------ 
diff -urN linux-2.4.5-pre2/drivers/video/aty.h linux/drivers/video/aty.h
--- linux-2.4.5-pre2/drivers/video/aty.h	Sun Sep 17 09:48:04 2000
+++ linux/drivers/video/aty.h	Mon Dec  3 22:43:26 2001
@@ -738,6 +738,7 @@
 #define LI_CHIP_ID	0x4c49	/* RAGE LT PRO */
 #define LP_CHIP_ID	0x4c50	/* RAGE LT PRO */
 #define LT_CHIP_ID	0x4c54	/* RAGE LT */
+#define XL_CHIP_ID	0x4752	/* RAGE (XL) */
 #define GT_CHIP_ID	0x4754	/* RAGE (GT) */
 #define GU_CHIP_ID	0x4755	/* RAGE II/II+ (GTB) */
 #define GV_CHIP_ID	0x4756	/* RAGE IIC, PCI */
diff -urN linux-2.4.5-pre2/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- linux-2.4.5-pre2/drivers/video/atyfb.c	Thu Apr 12 12:10:25 2001
+++ linux/drivers/video/atyfb.c	Mon Dec  3 22:43:26 2001
@@ -561,6 +561,7 @@
     { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
     { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
     { 0x4c54, 0x4c54, "3D RAGE LT" },
+    { 0x4752, 0x4752, "3D RAGE (XL)" },
     { 0x4754, 0x4754, "3D RAGE (GT)" },
     { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
     { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
@@ -722,7 +723,7 @@
     if (Gx == LB_CHIP_ID || Gx == LD_CHIP_ID || Gx == LI_CHIP_ID ||
     	Gx == LP_CHIP_ID || Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
     	Gx == GI_CHIP_ID || Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID ||
-    	Gx == LM_CHIP_ID || Gx == LN_CHIP_ID)
+    	Gx == LM_CHIP_ID || Gx == LN_CHIP_ID || Gx == XL_CHIP_ID)
     	reset_GTC_3D_engine(info);
 
     /* Reset engine, enable, and clear any engine errors */
@@ -2209,10 +2210,14 @@
     if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
 	  Gx == ET_CHIP_ID ||
 	  ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
-	if (info->ram_type >= SDRAM)
-	    aty_st_pll(DLL_CNTL, 0xa6, info);
-	else
-	    aty_st_pll(DLL_CNTL, 0xa0, info);
+	if (Gx == XL_CHIP_ID) {
+	    aty_st_pll(DLL_CNTL, 0x80, info);
+	} else {
+	    if (info->ram_type >= SDRAM)
+		aty_st_pll(DLL_CNTL, 0xa6, info);
+	    else
+		aty_st_pll(DLL_CNTL, 0xa0, info);
+	}
 	aty_st_pll(VFC_CNTL, 0x1b, info);
 	aty_st_le32(DSP_CONFIG, pll->dsp_config, info);
 	aty_st_le32(DSP_ON_OFF, pll->dsp_on_off, info);
@@ -2334,6 +2339,7 @@
 	 (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
 	 (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
 	 (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
+	 (Gx == XL_CHIP_ID) ||
 	 (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
 	pll->pll_gen_cntl = 0x04;
     else
@@ -3214,7 +3220,7 @@
 		if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
 		    Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
 		    Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
-		    Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID)
+		    Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == XL_CHIP_ID)
 			tmp |= 0x2;
 		aty_st_8(DAC_CNTL, tmp, info);
 		aty_st_8(DAC_MASK, 0xff, info);
@@ -3367,6 +3373,9 @@
 		/* RAGE PRO or LT PRO */
 		pll = 230;
 		mclk = 100;
+	    } else if (Gx == XL_CHIP_ID) {
+		pll = 230;
+		mclk = 120;
 	    } else if (Gx == LG_CHIP_ID) {
 		/* Rage LT */
 		pll = 230;
@@ -3801,34 +3810,36 @@
 		j++;
 	    }
 
-	    /*
-	     * Fix PROMs idea of MEM_CNTL settings...
-	     */
-	    mem = aty_ld_le32(MEM_CNTL, info);
-	    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
-	    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
-		!((chip_id >> 24) & 1)) {
-		switch (mem & 0x0f) {
-		    case 3:
-			mem = (mem & ~(0x0f)) | 2;
-			break;
-		    case 7:
-			mem = (mem & ~(0x0f)) | 3;
-			break;
-		    case 9:
-			mem = (mem & ~(0x0f)) | 4;
-			break;
-		    case 11:
-			mem = (mem & ~(0x0f)) | 5;
-			break;
-		    default:
-			break;
-		}
-		if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
-			mem &= ~(0x00700000);
+	    if (pdev->device != XL_CHIP_ID) {
+		    /*
+		     * Fix PROMs idea of MEM_CNTL settings...
+		     */
+		    mem = aty_ld_le32(MEM_CNTL, info);
+		    chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
+		    if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
+			!((chip_id >> 24) & 1)) {
+			    switch (mem & 0x0f) {
+			    case 3:
+				    mem = (mem & ~(0x0f)) | 2;
+				    break;
+			    case 7:
+				    mem = (mem & ~(0x0f)) | 3;
+				    break;
+			    case 9:
+				    mem = (mem & ~(0x0f)) | 4;
+				    break;
+			    case 11:
+				    mem = (mem & ~(0x0f)) | 5;
+				    break;
+			    default:
+				    break;
+			    }
+			    if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
+				    mem &= ~(0x00700000);
+		    }
+		    mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
+		    aty_st_le32(MEM_CNTL, mem, info);
 	    }
-	    mem &= ~(0xcf80e000);	/* Turn off all undocumented bits. */
-	    aty_st_le32(MEM_CNTL, mem, info);
 
 	    /*
 	     * If this is the console device, we will set default video
@@ -3850,7 +3861,7 @@
 	    if (node == pcp->prom_node) {
 
 		struct fb_var_screeninfo *var = &default_var;
-		unsigned int N, P, Q, M, T;
+		unsigned int N, P, Q, M, T, R;
 		u32 v_total, h_total;
 		struct crtc crtc;
 		u8 pll_regs[16];
@@ -3891,7 +3902,7 @@
 		N = pll_regs[7 + (clock_cntl & 3)];
 
 		/*
-		 * PLL Post Devider P (Dependant on CLOCK_CNTL):
+		 * PLL Post Divider P (Dependant on CLOCK_CNTL):
 		 */
 		P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
 
@@ -3907,13 +3918,17 @@
 		 * Q = -------
 		 *      2 * R
 		 *
-		 * where R is XTALIN (= 14318 kHz).
+		 * where R is XTALIN (= 14318 or 29498 kHz).
 		 */
-		T = 2 * Q * 14318 / M;
+		if (pdev->device == XL_CHIP_ID)
+			R = 29498;
+		else
+			R = 14318;
+
+		T = 2 * Q * R / M;
 
 		default_var.pixclock = 1000000000 / T;
 	    }
-
 #else /* __sparc__ */
 
 	    info->ati_regbase_phys = 0x7ff000 + addr;
@@ -4297,7 +4312,8 @@
     if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == GV_CHIP_ID ||
 	Gx == GW_CHIP_ID || Gx == GZ_CHIP_ID || Gx == LG_CHIP_ID ||
 	Gx == GB_CHIP_ID || Gx == GD_CHIP_ID || Gx == GI_CHIP_ID ||
-	Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == LI_CHIP_ID)
+	Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID || Gx == LI_CHIP_ID ||
+	Gx == XL_CHIP_ID)
 	i |= 0x2;	/*DAC_CNTL|0x2 turns off the extra brightness for gt*/
     aty_st_8(DAC_CNTL, i, info);
     aty_st_8(DAC_MASK, 0xff, info);
diff -urN linux-2.4.5-pre2/fs/block_dev.c linux/fs/block_dev.c
--- linux-2.4.5-pre2/fs/block_dev.c	Mon Dec  3 22:43:16 2001
+++ linux/fs/block_dev.c	Mon Dec  3 22:43:26 2001
@@ -31,7 +31,7 @@
 	ssize_t block, blocks;
 	loff_t offset;
 	ssize_t chars;
-	ssize_t written;
+	ssize_t written, retval;
 	struct buffer_head * bhlist[NBUF];
 	size_t size;
 	kdev_t dev = inode->i_rdev;
@@ -41,7 +41,7 @@
 	if (is_read_only(dev))
 		return -EPERM;
 
-	written = write_error = buffercount = 0;
+	retval = written = write_error = buffercount = 0;
 	blocksize = BLOCK_SIZE;
 	if (blksize_size[MAJOR(dev)] && blksize_size[MAJOR(dev)][MINOR(dev)])
 		blocksize = blksize_size[MAJOR(dev)][MINOR(dev)];
@@ -61,8 +61,10 @@
 	else
 		size = INT_MAX;
 	while (count>0) {
-		if (block >= size)
-			return written ? written : -ENOSPC;
+		if (block >= size) {
+			retval = -ENOSPC;
+			goto cleanup;
+		}
 		chars = blocksize - offset;
 		if (chars > count)
 			chars=count;
@@ -74,15 +76,19 @@
 			if (chars != blocksize)
 				fn = bread;
 			bh = fn(dev, block, blocksize);
-			if (!bh)
-				return written ? written : -EIO;
+			if (!bh) {
+				retval = -EIO;
+				goto cleanup;
+			}
 			if (!buffer_uptodate(bh))
 				wait_on_buffer(bh);
 		}
 #else
 		bh = getblk(dev, block, blocksize);
-		if (!bh)
-			return written ? written : -EIO;
+		if (!bh) {
+			retval = -EIO;
+			goto cleanup;
+		}
 
 		if (!buffer_uptodate(bh))
 		{
@@ -106,7 +112,8 @@
 		        if (!bhlist[i])
 			{
 			  while(i >= 0) brelse(bhlist[i--]);
-			  return written ? written : -EIO;
+			  retval = -EIO;
+			  goto cleanup;
 		        }
 		      }
 		    }
@@ -115,7 +122,8 @@
 		    wait_on_buffer(bh);
 		    if (!buffer_uptodate(bh)) {
 			  brelse(bh);
-			  return written ? written : -EIO;
+			  retval = -EIO;
+			  goto cleanup;
 		    }
 		  };
 		};
@@ -149,6 +157,7 @@
 		if (write_error)
 			break;
 	}
+	cleanup:
 	if ( buffercount ){
 		ll_rw_block(WRITE, buffercount, bufferlist);
 		for(i=0; i<buffercount; i++){
@@ -158,10 +167,11 @@
 			brelse(bufferlist[i]);
 		}
 	}		
-	filp->f_reada = 1;
+	if(!retval)
+		filp->f_reada = 1;
 	if(write_error)
 		return -EIO;
-	return written;
+	return written ? written : retval;
 }
 
 ssize_t block_read(struct file * filp, char * buf, size_t count, loff_t *ppos)
diff -urN linux-2.4.5-pre2/fs/ext2/super.c linux/fs/ext2/super.c
--- linux-2.4.5-pre2/fs/ext2/super.c	Wed Apr 18 11:49:13 2001
+++ linux/fs/ext2/super.c	Mon Dec  3 22:43:26 2001
@@ -76,9 +76,6 @@
 	va_start (args, fmt);
 	vsprintf (error_buf, fmt, args);
 	va_end (args);
-	/* this is to prevent panic from syncing this filesystem */
-	if (sb->s_lock)
-		sb->s_lock=0;
 	sb->s_flags |= MS_RDONLY;
 	panic ("EXT2-fs panic (device %s): %s: %s\n",
 	       bdevname(sb->s_dev), function, error_buf);
diff -urN linux-2.4.5-pre2/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- linux-2.4.5-pre2/fs/nfsd/nfsctl.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/nfsd/nfsctl.c	Mon Dec  3 22:43:26 2001
@@ -158,7 +158,7 @@
 			err = -EINVAL;
 		else {
 			memset(res,0, NFS_FHSIZE);
-			memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+			memcpy(res, &fh.fh_base, fh.fh_size);
 		}
 	}
 
@@ -191,7 +191,7 @@
 			err = -EINVAL;
 		else {
 			memset(res,0, NFS_FHSIZE);
-			memcpy(res, fh.fh_base.fh_pad, fh.fh_size);
+			memcpy(res, &fh.fh_base, fh.fh_size);
 		}
 	}
 
diff -urN linux-2.4.5-pre2/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- linux-2.4.5-pre2/fs/nfsd/nfsfh.c	Mon Dec  3 22:43:16 2001
+++ linux/fs/nfsd/nfsfh.c	Mon Dec  3 22:43:26 2001
@@ -245,6 +245,11 @@
 	 */
 	pdentry = child->d_inode->i_op->lookup(child->d_inode, tdentry);
 	d_drop(tdentry); /* we never want ".." hashed */
+	if (!pdentry && tdentry->d_inode == NULL) {
+		/* File system cannot find ".." ... sad but possible */
+		dput(tdentry);
+		pdentry = ERR_PTR(-EINVAL);
+	}
 	if (!pdentry) {
 		/* I don't want to return a ".." dentry.
 		 * I would prefer to return an unconnected "IS_ROOT" dentry,
diff -urN linux-2.4.5-pre2/fs/reiserfs/prints.c linux/fs/reiserfs/prints.c
--- linux-2.4.5-pre2/fs/reiserfs/prints.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/reiserfs/prints.c	Mon Dec  3 22:43:26 2001
@@ -349,8 +349,6 @@
 #endif
 
   /* this is to prevent panic from syncing this filesystem */
-  if (sb && sb->s_lock)
-    sb->s_lock=0;
   if (sb)
     sb->s_flags |= MS_RDONLY;
 
diff -urN linux-2.4.5-pre2/fs/select.c linux/fs/select.c
--- linux-2.4.5-pre2/fs/select.c	Fri Feb  9 11:29:44 2001
+++ linux/fs/select.c	Mon Dec  3 22:43:26 2001
@@ -414,8 +414,11 @@
 	int nchunks, nleft;
 
 	/* Do a sanity check on nfds ... */
-	if (nfds > current->files->max_fds)
+	if (nfds > NR_OPEN)
 		return -EINVAL;
+
+	if (nfds > current->files->max_fds)
+		nfds = current->files->max_fds;
 
 	if (timeout) {
 		/* Careful about overflow in the intermediate values */
diff -urN linux-2.4.5-pre2/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog
--- linux-2.4.5-pre2/fs/smbfs/ChangeLog	Tue Mar  6 19:14:59 2001
+++ linux/fs/smbfs/ChangeLog	Mon Dec  3 22:43:26 2001
@@ -1,5 +1,30 @@
 ChangeLog for smbfs.
 
+2001-05-08 Urban Widmark <urban@teststation.com>
+
+	* inode.c: Fix for changes on the server side not being detected
+	  properly. Must always drop cached pages when updating an inode with
+	  new size.
+
+2001-05-05 Urban Widmark <urban@teststation.com>
+
+	* file.c, proc.c: Drop SMB_F_LOCALWRITE to detect changes made on
+	  both server and client, using flush with to force win9x to remember
+	  the right filesize.
+
+2001-04-25 René Scharfe <l.s.r@web.de>
+
+	* inode.c: Don't clear s_flags and allow ro mounts
+
+2001-04-21 Urban Widmark <urban@teststation.com>
+
+	* dir.c, proc.c: replace tests on conn_pid with tests on state to
+	  fix smbmount reconnect on smb_retry timeout and up the timeout to 30s.
+	* proc.c: smb_newconn must have the server locked while updating it.
+	* inode.c, proc.c: need flush after truncate on some servers (win9x)
+	* file.c: add call to send SMBflush on fsync
+	  (as suggested by Jochen Dolze <dolze@epcnet.de>)
+
 2001-03-06 Urban Widmark <urban@teststation.com>
 
 	* cache.c: d_add on hashed dentries corrupts d_hash list and
diff -urN linux-2.4.5-pre2/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- linux-2.4.5-pre2/fs/smbfs/dir.c	Fri Feb 16 16:03:24 2001
+++ linux/fs/smbfs/dir.c	Mon Dec  3 22:43:26 2001
@@ -210,10 +210,6 @@
 	return result;
 }
 
-/*
- * Note: in order to allow the smbmount process to open the
- * mount point, we don't revalidate if conn_pid is NULL.
- */
 static int
 smb_dir_open(struct inode *dir, struct file *file)
 {
@@ -230,14 +226,18 @@
 	 */
 	lock_kernel();
 	server = server_from_dentry(dentry);
-	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2)
-	{
+	if (server->opt.protocol < SMB_PROTOCOL_LANMAN2) {
 		unsigned long age = jiffies - dir->u.smbfs_i.oldmtime;
 		if (age > 2*HZ)
 			smb_invalid_dir_cache(dir);
 	}
 
-	if (server->conn_pid)
+	/*
+	 * Note: in order to allow the smbmount process to open the
+	 * mount point, we only revalidate if the connection is valid or
+	 * if the process is trying to access something other than the root.
+	 */
+	if (server->state == CONN_VALID || !IS_ROOT(dentry))
 		error = smb_revalidate_inode(dentry);
 	unlock_kernel();
 	return error;
diff -urN linux-2.4.5-pre2/fs/smbfs/file.c linux/fs/smbfs/file.c
--- linux-2.4.5-pre2/fs/smbfs/file.c	Fri Feb 16 16:03:24 2001
+++ linux/fs/smbfs/file.c	Mon Dec  3 22:43:26 2001
@@ -28,8 +28,23 @@
 static int
 smb_fsync(struct file *file, struct dentry * dentry, int datasync)
 {
+	struct smb_sb_info *server = server_from_dentry(dentry);
+	int result;
+
 	VERBOSE("sync file %s/%s\n", DENTRY_PATH(dentry));
-	return 0;
+
+	/*
+	 * The VFS will writepage() all dirty pages for us, but we
+	 * should send a SMBflush to the server, letting it know that
+	 * we want things synchronized with actual storage.
+	 *
+	 * Note: this function requires all pages to have been written already
+	 *       (should be ok with writepage_sync)
+	 */
+	smb_lock_server(server);
+	result = smb_proc_flush(server, dentry->d_inode->u.smbfs_i.fileid);
+	smb_unlock_server(server);
+	return result;
 }
 
 /*
@@ -138,7 +153,6 @@
 		inode->i_mtime = inode->i_atime = CURRENT_TIME;
 		if (offset > inode->i_size)
 			inode->i_size = offset;
-		inode->u.smbfs_i.flags |= SMB_F_LOCALWRITE;
 	} while (count);
 
 	kunmap(page);
@@ -207,8 +221,7 @@
 		(unsigned long) count, (unsigned long) *ppos);
 
 	status = smb_revalidate_inode(dentry);
-	if (status)
-	{
+	if (status) {
 		PARANOIA("%s/%s validation failed, error=%Zd\n",
 			 DENTRY_PATH(dentry), status);
 		goto out;
@@ -233,8 +246,7 @@
 		DENTRY_PATH(dentry), vma->vm_start, vma->vm_end);
 
 	status = smb_revalidate_inode(dentry);
-	if (status)
-	{
+	if (status) {
 		PARANOIA("%s/%s validation failed, error=%d\n",
 			 DENTRY_PATH(dentry), status);
 		goto out;
@@ -294,8 +306,7 @@
 		(unsigned long) count, (unsigned long) *ppos);
 
 	result = smb_revalidate_inode(dentry);
-	if (result)
-	{
+	if (result) {
 		PARANOIA("%s/%s validation failed, error=%Zd\n",
 			 DENTRY_PATH(dentry), result);
 		goto out;
@@ -305,8 +316,7 @@
 	if (result)
 		goto out;
 
-	if (count > 0)
-	{
+	if (count > 0) {
 		result = generic_file_write(file, buf, count, ppos);
 		VERBOSE("pos=%ld, size=%ld, mtime=%ld, atime=%ld\n",
 			(long) file->f_pos, (long) dentry->d_inode->i_size,
diff -urN linux-2.4.5-pre2/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- linux-2.4.5-pre2/fs/smbfs/inode.c	Tue Apr 17 23:16:39 2001
+++ linux/fs/smbfs/inode.c	Mon Dec  3 22:43:26 2001
@@ -109,9 +109,20 @@
 		fattr->attr |= aRONLY;
 }
 
+/*
+ * Update the inode, possibly causing it to invalidate its pages if mtime/size
+ * is different from last time.
+ */
 void
 smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
 {
+	/*
+	 * A size change should have a different mtime, or same mtime
+	 * but different size.
+	 */
+	time_t last_time = inode->i_mtime;
+	loff_t last_sz = inode->i_size;
+
 	inode->i_mode	= fattr->f_mode;
 	inode->i_nlink	= fattr->f_nlink;
 	inode->i_uid	= fattr->f_uid;
@@ -120,21 +131,24 @@
 	inode->i_ctime	= fattr->f_ctime;
 	inode->i_blksize= fattr->f_blksize;
 	inode->i_blocks = fattr->f_blocks;
-	/*
-	 * Don't change the size and mtime/atime fields
-	 * if we're writing to the file.
-	 */
-	if (!(inode->u.smbfs_i.flags & SMB_F_LOCALWRITE)) {
-		inode->i_size  = fattr->f_size;
-		inode->i_mtime = fattr->f_mtime;
-		inode->i_atime = fattr->f_atime;
-	}
-
+	inode->i_size	= fattr->f_size;
+	inode->i_mtime	= fattr->f_mtime;
+	inode->i_atime	= fattr->f_atime;
 	inode->u.smbfs_i.attr = fattr->attr;
 	/*
 	 * Update the "last time refreshed" field for revalidation.
 	 */
 	inode->u.smbfs_i.oldmtime = jiffies;
+
+	if (inode->i_mtime != last_time || inode->i_size != last_sz) {
+		VERBOSE("%s/%s changed, old=%ld, new=%ld, oz=%ld, nz=%ld\n",
+			DENTRY_PATH(dentry),
+			(long) last_time, (long) inode->i_mtime,
+			(long) last_sz, (long) inode->i_size);
+
+		if (!S_ISDIR(inode->i_mode))
+			invalidate_inode_pages(inode);
+	}
 }
 
 /*
@@ -209,8 +223,6 @@
 {
 	struct smb_sb_info *s = server_from_dentry(dentry);
 	struct inode *inode = dentry->d_inode;
-	time_t last_time;
-	loff_t last_sz;
 	int error = 0;
 
 	DEBUG1("smb_revalidate_inode\n");
@@ -225,22 +237,7 @@
 		goto out;
 	}
 
-	/*
-	 * Save the last modified time, then refresh the inode.
-	 * (Note: a size change should have a different mtime,
-	 *  or same mtime but different size.)
-	 */
-	last_time = inode->i_mtime;
-	last_sz   = inode->i_size;
 	error = smb_refresh_inode(dentry);
-	if (error || inode->i_mtime != last_time || inode->i_size != last_sz) {
-		VERBOSE("%s/%s changed, old=%ld, new=%ld\n",
-			DENTRY_PATH(dentry),
-			(long) last_time, (long) inode->i_mtime);
-
-		if (!S_ISDIR(inode->i_mode))
-			invalidate_inode_pages(inode);
-	}
 out:
 	unlock_kernel();
 	return error;
@@ -355,8 +352,8 @@
 	if (server->conn_pid)
 	       kill_proc(server->conn_pid, SIGTERM, 1);
 
-	kfree(server->mnt);
-	kfree(sb->u.smbfs_sb.temp_buf);
+	smb_kfree(server->mnt);
+	smb_kfree(sb->u.smbfs_sb.temp_buf);
 	if (server->packet)
 		smb_vfree(server->packet);
 
@@ -390,7 +387,6 @@
 	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = SMB_SUPER_MAGIC;
-	sb->s_flags = 0;
 	sb->s_op = &smb_sops;
 
 	sb->u.smbfs_sb.mnt = NULL;
@@ -400,13 +396,13 @@
 	sb->u.smbfs_sb.conn_pid = 0;
 	sb->u.smbfs_sb.state = CONN_INVALID; /* no connection yet */
 	sb->u.smbfs_sb.generation = 0;
-	sb->u.smbfs_sb.packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);	
+	sb->u.smbfs_sb.packet_size = smb_round_length(SMB_INITIAL_PACKET_SIZE);
 	sb->u.smbfs_sb.packet = smb_vmalloc(sb->u.smbfs_sb.packet_size);
 	if (!sb->u.smbfs_sb.packet)
 		goto out_no_mem;
 
 	/* Allocate the global temp buffer */
-	sb->u.smbfs_sb.temp_buf = kmalloc(2*SMB_MAXPATHLEN + 20, GFP_KERNEL);
+	sb->u.smbfs_sb.temp_buf = smb_kmalloc(2*SMB_MAXPATHLEN+20, GFP_KERNEL);
 	if (!sb->u.smbfs_sb.temp_buf)
 		goto out_no_temp;
 
@@ -417,7 +413,7 @@
 
 	/* Allocate the mount data structure */
 	/* FIXME: merge this with the other malloc and get a whole page? */
-	mnt = kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
+	mnt = smb_kmalloc(sizeof(struct smb_mount_data_kernel), GFP_KERNEL);
 	if (!mnt)
 		goto out_no_mount;
 	sb->u.smbfs_sb.mnt = mnt;
@@ -482,9 +478,9 @@
 out_no_root:
 	iput(root_inode);
 out_bad_option:
-	kfree(sb->u.smbfs_sb.mnt);
+	smb_kfree(sb->u.smbfs_sb.mnt);
 out_no_mount:
-	kfree(sb->u.smbfs_sb.temp_buf);
+	smb_kfree(sb->u.smbfs_sb.temp_buf);
 out_no_temp:
 	smb_vfree(sb->u.smbfs_sb.packet);
 out_no_mem:
diff -urN linux-2.4.5-pre2/fs/smbfs/ioctl.c linux/fs/smbfs/ioctl.c
--- linux-2.4.5-pre2/fs/smbfs/ioctl.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/smbfs/ioctl.c	Mon Dec  3 22:43:26 2001
@@ -23,7 +23,7 @@
 smb_ioctl(struct inode *inode, struct file *filp,
 	  unsigned int cmd, unsigned long arg)
 {
-	struct smb_sb_info *server = SMB_SERVER(inode);
+	struct smb_sb_info *server = server_from_inode(inode);
 	struct smb_conn_opt opt;
 	int result = -EINVAL;
 
@@ -37,7 +37,7 @@
 		break;
 
 	case SMB_IOC_NEWCONN:
-		/* require an argument == the mount data, else it is EINVAL */
+		/* require an argument == smb_conn_opt, else it is EINVAL */
 		if (!arg)
 			break;
 
@@ -45,7 +45,8 @@
 		if (!copy_from_user(&opt, (void *)arg, sizeof(opt)))
 			result = smb_newconn(server, &opt);
 		break;
-	default:;
+	default:
+		break;
 	}
 
 	return result;
diff -urN linux-2.4.5-pre2/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- linux-2.4.5-pre2/fs/smbfs/proc.c	Fri Apr 13 20:26:07 2001
+++ linux/fs/smbfs/proc.c	Mon Dec  3 22:43:26 2001
@@ -54,18 +54,6 @@
 		    struct smb_fattr *fattr);
 
 
-static inline void
-smb_lock_server(struct smb_sb_info *server)
-{
-	down(&(server->sem));
-}
-
-static inline void
-smb_unlock_server(struct smb_sb_info *server)
-{
-	up(&(server->sem));
-}
-
 
 static void
 str_upper(char *name, int len)
@@ -661,7 +649,7 @@
 	pid_t pid = server->conn_pid;
 	int error, result = 0;
 
-	if (server->state != CONN_INVALID)
+	if (server->state == CONN_VALID || server->state == CONN_RETRYING)
 		goto out;
 
 	smb_close_socket(server);
@@ -673,17 +661,18 @@
 	}
 
 	/*
-	 * Clear the pid to enable the ioctl.
+	 * Change state so that only one retry per server will be started.
 	 */
-	server->conn_pid = 0;
+	server->state = CONN_RETRYING;
 
 	/*
 	 * Note: use the "priv" flag, as a user process may need to reconnect.
 	 */
 	error = kill_proc(pid, SIGUSR1, 1);
 	if (error) {
+		/* FIXME: this is fatal */
 		printk(KERN_ERR "smb_retry: signal failed, error=%d\n", error);
-		goto out_restore;
+		goto out;
 	}
 	VERBOSE("signalled pid %d, waiting for new connection\n", pid);
 
@@ -691,7 +680,9 @@
 	 * Wait for the new connection.
 	 */
 #ifdef SMB_RETRY_INTR
-	interruptible_sleep_on_timeout(&server->wait,  5*HZ);
+	smb_unlock_server(server);
+	interruptible_sleep_on_timeout(&server->wait,  30*HZ);
+	smb_lock_server(server);
 	if (signal_pending(current))
 		printk(KERN_INFO "smb_retry: caught signal\n");
 #else
@@ -702,8 +693,13 @@
 	 *
 	 * smbmount should be able to reconnect later, but it can't because
 	 * it will get an -EIO on attempts to open the mountpoint!
+	 *
+	 * FIXME: go back to the interruptable version now that smbmount
+	 * can avoid -EIO on the mountpoint when reconnecting?
 	 */
-	sleep_on_timeout(&server->wait, 5*HZ);
+	smb_unlock_server(server);
+	sleep_on_timeout(&server->wait, 30*HZ);
+	smb_lock_server(server);
 #endif
 
 	/*
@@ -715,15 +711,11 @@
 		PARANOIA("successful, new pid=%d, generation=%d\n",
 			 server->conn_pid, server->generation);
 		result = 1;
+	} else if (server->state == CONN_RETRYING) {
+		/* allow further attempts later */
+		server->state = CONN_RETRIED;
 	}
 
-	/*
-	 * Restore the original pid if we didn't get a new one.
-	 */
-out_restore:
-	if (!server->conn_pid)
-		server->conn_pid = pid;
-
 out:
 	return result;
 }
@@ -742,19 +734,16 @@
 	s->err = 0;
 
 	/* Make sure we have a connection */
-	if (s->state != CONN_VALID)
-	{
+	if (s->state != CONN_VALID) {
 		if (!smb_retry(s))
 			goto out;
 	}
 
-	if (smb_request(s) < 0)
-	{
+	if (smb_request(s) < 0) {
 		DEBUG1("smb_request failed\n");
 		goto out;
 	}
-	if (smb_valid_packet(s->packet) != 0)
-	{
+	if (smb_valid_packet(s->packet) != 0) {
 		PARANOIA("invalid packet!\n");
 		goto out;
 	}
@@ -764,8 +753,7 @@
 	 * is squashing some error codes, but I don't think this is
 	 * correct: after a server error the packet won't be valid.
 	 */
-	if (s->rcls != 0)
-	{
+	if (s->rcls != 0) {
 		result = -smb_errno(s);
 		if (!result)
 			printk(KERN_DEBUG "smb_request_ok: rcls=%d, err=%d mapped to 0\n",
@@ -785,10 +773,6 @@
 /*
  * This implements the NEWCONN ioctl. It installs the server pid,
  * sets server->state to CONN_VALID, and wakes up the waiting process.
- *
- * Note that this must be called with the server locked, except for
- * the first call made after mounting the volume. The server pid
- * will be set to zero to indicate that smbfs is awaiting a connection.
  */
 int
 smb_newconn(struct smb_sb_info *server, struct smb_conn_opt *opt)
@@ -798,11 +782,13 @@
 
 	VERBOSE("fd=%d, pid=%d\n", opt->fd, current->pid);
 
+	smb_lock_server(server);
+
 	/*
-	 * Make sure we don't already have a pid ...
+	 * Make sure we don't already have a valid connection ...
 	 */
 	error = -EINVAL;
-	if (server->conn_pid)
+	if (server->state == CONN_VALID)
 		goto out;
 
 	error = -EACCES;
@@ -836,9 +822,7 @@
 	    (server->opt.max_xmit < 0x1000) &&
 	    !(server->opt.capabilities & SMB_CAP_NT_SMBS)) {
 		server->mnt->flags |= SMB_MOUNT_WIN95;
-#ifdef SMBFS_DEBUG_VERBOSE
-		printk(KERN_NOTICE "smb_newconn: detected WIN95 server\n");
-#endif
+		VERBOSE("smb_newconn: detected WIN95 server\n");
 	}
 
 	VERBOSE("protocol=%d, max_xmit=%d, pid=%d capabilities=0x%x\n",
@@ -851,6 +835,8 @@
 		int len = smb_round_length(server->opt.max_xmit);
 		char *buf = smb_vmalloc(len);
 		if (buf) {
+			if (server->packet)
+				smb_vfree(server->packet);
 			server->packet = buf;
 			server->packet_size = len;
 		} else {
@@ -863,6 +849,8 @@
 	}
 
 out:
+	smb_unlock_server(server);
+
 #ifdef SMB_RETRY_INTR
 	wake_up_interruptible(&server->wait);
 #else
@@ -1016,7 +1004,7 @@
 	}
 
 	if (!smb_is_open(inode)) {
-		struct smb_sb_info *server = SMB_SERVER(inode);
+		struct smb_sb_info *server = server_from_inode(inode);
 		smb_lock_server(server);
 		result = 0;
 		if (!smb_is_open(inode))
@@ -1102,7 +1090,6 @@
 
 		result = smb_proc_close(server, ino->u.smbfs_i.fileid,
 						ino->i_mtime);
-		ino->u.smbfs_i.flags &= ~SMB_F_LOCALWRITE;
 		/*
 		 * Force a revalidation after closing ... some servers
 		 * don't post the size until the file has been closed.
@@ -1119,9 +1106,8 @@
 {
 	int result = 0;
 
-	if (smb_is_open(ino))
-	{
-		struct smb_sb_info *server = SMB_SERVER(ino);
+	if (smb_is_open(ino)) {
+		struct smb_sb_info *server = server_from_inode(ino);
 		smb_lock_server(server);
 		result = smb_proc_close_inode(server, ino);
 		smb_unlock_server(server);
@@ -1203,14 +1189,15 @@
 	struct smb_sb_info *server = server_from_inode(inode);
 	int result;
 	__u8 *p;
-	
+	__u16 fileid = inode->u.smbfs_i.fileid;
+
 	VERBOSE("ino=%ld, fileid=%d, count=%d@%ld, packet_size=%d\n",
 		inode->i_ino, inode->u.smbfs_i.fileid, count, offset,
 		server->packet_size);
 
 	smb_lock_server(server);
 	p = smb_setup_header(server, SMBwrite, 5, count + 3);
-	WSET(server->packet, smb_vwv0, inode->u.smbfs_i.fileid);
+	WSET(server->packet, smb_vwv0, fileid);
 	WSET(server->packet, smb_vwv1, count);
 	DSET(server->packet, smb_vwv2, offset);
 	WSET(server->packet, smb_vwv4, 0);
@@ -1223,6 +1210,11 @@
 	if (result >= 0)
 		result = WVAL(server->packet, smb_vwv0);
 
+	/* flush to disk, to trigger win9x to update its filesize */
+	/* FIXME: this will be rather costly, won't it? */
+	if (server->mnt->flags & SMB_MOUNT_WIN95)
+		smb_proc_flush(server, fileid);
+
 	smb_unlock_server(server);
 	return result;
 }
@@ -1423,6 +1415,17 @@
 	return result;
 }
 
+/*
+ * Called with the server locked
+ */
+int
+smb_proc_flush(struct smb_sb_info *server, __u16 fileid)
+{
+	smb_setup_header(server, SMBflush, 1, 0);
+	WSET(server->packet, smb_vwv0, fileid);
+	return smb_request_ok(server, SMBflush, 0, 0);
+}
+
 int
 smb_proc_trunc(struct smb_sb_info *server, __u16 fid, __u32 length)
 {
@@ -1431,7 +1434,7 @@
 
 	smb_lock_server(server);
 
-      retry:
+retry:
 	p = smb_setup_header(server, SMBwrite, 5, 3);
 	WSET(server->packet, smb_vwv0, fid);
 	WSET(server->packet, smb_vwv1, 0);
@@ -1445,7 +1448,15 @@
 			goto retry;
 		goto out;
 	}
-	result = 0;
+
+	/*
+	 * win9x doesn't appear to update the size immediately.
+	 * It will return the old file size after the truncate,
+	 * confusing smbfs.
+	 * NT and Samba return the new value immediately.
+	 */
+	if (server->mnt->flags & SMB_MOUNT_WIN95)
+		smb_proc_flush(server, fid);
 out:
 	smb_unlock_server(server);
 	return result;
diff -urN linux-2.4.5-pre2/fs/smbfs/sock.c linux/fs/smbfs/sock.c
--- linux-2.4.5-pre2/fs/smbfs/sock.c	Fri Feb 16 16:03:24 2001
+++ linux/fs/smbfs/sock.c	Mon Dec  3 22:43:26 2001
@@ -150,14 +150,14 @@
 	DEBUG1("found=%d, count=%d, result=%d\n", found, count, result);
 	if (found)
 		found_data(job->sk);
-	kfree(ptr);
+	smb_kfree(ptr);
 }
 
 static void
 smb_data_ready(struct sock *sk, int len)
 {
 	struct data_callback* job;
-	job = kmalloc(sizeof(struct data_callback),GFP_ATOMIC);
+	job = smb_kmalloc(sizeof(struct data_callback),GFP_ATOMIC);
 	if(job == 0) {
 		printk("smb_data_ready: lost SESSION KEEPALIVE due to OOM.\n");
 		found_data(sk);
diff -urN linux-2.4.5-pre2/fs/super.c linux/fs/super.c
--- linux-2.4.5-pre2/fs/super.c	Mon Dec  3 22:43:16 2001
+++ linux/fs/super.c	Mon Dec  3 22:43:26 2001
@@ -580,30 +580,7 @@
 #undef MANGLE
 #undef FREEROOM
 }
-
-/**
- *	__wait_on_super	- wait on a superblock
- *	@sb: superblock to wait on
- *
- *	Waits for a superblock to become unlocked and then returns. It does
- *	not take the lock. This is an internal function. See wait_on_super().
- */
  
-void __wait_on_super(struct super_block * sb)
-{
-	DECLARE_WAITQUEUE(wait, current);
-
-	add_wait_queue(&sb->s_wait, &wait);
-repeat:
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	if (sb->s_lock) {
-		schedule();
-		goto repeat;
-	}
-	remove_wait_queue(&sb->s_wait, &wait);
-	current->state = TASK_RUNNING;
-}
-
 /*
  * Note: check the dirty flag before waiting, so we don't
  * hold up the sync while mounting a device. (The newly
@@ -648,7 +625,9 @@
 	s = sb_entry(super_blocks.next);
 	while (s != sb_entry(&super_blocks))
 		if (s->s_dev == dev) {
-			wait_on_super(s);
+			/* Yes, it sucks. As soon as we get refcounting... */
+			lock_super(s);
+			unlock_super(s);
 			if (s->s_dev == dev)
 				return s;
 			goto restart;
@@ -700,9 +679,7 @@
 	     s  = sb_entry(s->s_list.next)) {
 		if (s->s_dev)
 			continue;
-		if (!s->s_lock)
-			return s;
-		printk("VFS: empty superblock %p locked!\n", s);
+		return s;
 	}
 	/* Need a new one... */
 	if (nr_super_blocks >= max_super_blocks)
@@ -714,10 +691,14 @@
 		INIT_LIST_HEAD(&s->s_dirty);
 		INIT_LIST_HEAD(&s->s_locked_inodes);
 		list_add (&s->s_list, super_blocks.prev);
-		init_waitqueue_head(&s->s_wait);
 		INIT_LIST_HEAD(&s->s_files);
 		INIT_LIST_HEAD(&s->s_mounts);
 		init_rwsem(&s->s_umount);
+		sema_init(&s->s_lock, 1);
+		sema_init(&s->s_vfs_rename_sem,1);
+		sema_init(&s->s_nfsd_free_path_sem,1);
+		sema_init(&s->s_dquot.dqio_sem, 1);
+		sema_init(&s->s_dquot.dqoff_sem, 1);
 	}
 	return s;
 }
@@ -734,11 +715,7 @@
 	s->s_bdev = bdev;
 	s->s_flags = flags;
 	s->s_dirt = 0;
-	sema_init(&s->s_vfs_rename_sem,1);
-	sema_init(&s->s_nfsd_free_path_sem,1);
 	s->s_type = type;
-	sema_init(&s->s_dquot.dqio_sem, 1);
-	sema_init(&s->s_dquot.dqoff_sem, 1);
 	s->s_dquot.flags = 0;
 	s->s_maxbytes = MAX_NON_LFS;
 	lock_super(s);
diff -urN linux-2.4.5-pre2/fs/ufs/super.c linux/fs/ufs/super.c
--- linux-2.4.5-pre2/fs/ufs/super.c	Tue Apr 17 23:16:39 2001
+++ linux/fs/ufs/super.c	Mon Dec  3 22:43:26 2001
@@ -230,9 +230,6 @@
 	va_start (args, fmt);
 	vsprintf (error_buf, fmt, args);
 	va_end (args);
-	/* this is to prevent panic from syncing this filesystem */
-	if (sb->s_lock)
-		sb->s_lock = 0;
 	sb->s_flags |= MS_RDONLY;
 	printk (KERN_CRIT "UFS-fs panic (device %s): %s: %s\n",
 		kdevname(sb->s_dev), function, error_buf);
diff -urN linux-2.4.5-pre2/include/asm-alpha/pci.h linux/include/asm-alpha/pci.h
--- linux-2.4.5-pre2/include/asm-alpha/pci.h	Fri Mar  2 11:12:07 2001
+++ linux/include/asm-alpha/pci.h	Mon Dec  3 22:43:26 2001
@@ -146,6 +146,17 @@
 
 extern int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask);
 
+/* Return the index of the PCI controller for device PDEV. */
+static __inline__ int pci_controller_num(struct pci_dev *pdev)
+{
+	struct pci_controller *hose = pdev->sysdata;
+
+	if (hose != NULL)
+		return hose->index;
+
+	return -ENXIO;
+}
+
 #endif /* __KERNEL__ */
 
 /* Values for the `which' argument to sys_pciconfig_iobase.  */
diff -urN linux-2.4.5-pre2/include/asm-arm/pci.h linux/include/asm-arm/pci.h
--- linux-2.4.5-pre2/include/asm-arm/pci.h	Mon Nov 27 17:07:59 2000
+++ linux/include/asm-arm/pci.h	Mon Dec  3 22:43:26 2001
@@ -148,6 +148,9 @@
 	return 1;
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* __KERNEL__ */
  
 #endif
diff -urN linux-2.4.5-pre2/include/asm-i386/pci.h linux/include/asm-i386/pci.h
--- linux-2.4.5-pre2/include/asm-i386/pci.h	Mon Dec  3 22:43:16 2001
+++ linux/include/asm-i386/pci.h	Mon Dec  3 22:43:26 2001
@@ -173,6 +173,12 @@
 #define sg_dma_address(sg)	(virt_to_bus((sg)->address))
 #define sg_dma_len(sg)		((sg)->length)
 
+/* Return the index of the PCI controller for device. */
+static inline int pci_controller_num(struct pci_dev *dev)
+{
+	return 0;
+}
+
 #endif /* __KERNEL__ */
 
 #endif /* __i386_PCI_H */
diff -urN linux-2.4.5-pre2/include/asm-ia64/pci.h linux/include/asm-ia64/pci.h
--- linux-2.4.5-pre2/include/asm-ia64/pci.h	Thu Jan  4 15:25:55 2001
+++ linux/include/asm-ia64/pci.h	Mon Dec  3 22:43:26 2001
@@ -57,6 +57,9 @@
 	return 1;
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #define sg_dma_len(sg)		((sg)->length)
 
 #endif /* _ASM_IA64_PCI_H */
diff -urN linux-2.4.5-pre2/include/asm-m68k/pci.h linux/include/asm-m68k/pci.h
--- linux-2.4.5-pre2/include/asm-m68k/pci.h	Thu Jun 22 07:17:16 2000
+++ linux/include/asm-m68k/pci.h	Mon Dec  3 22:43:26 2001
@@ -45,4 +45,7 @@
 	/* We don't do dynamic PCI IRQ allocation */
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* _ASM_M68K_PCI_H */
diff -urN linux-2.4.5-pre2/include/asm-mips/pci.h linux/include/asm-mips/pci.h
--- linux-2.4.5-pre2/include/asm-mips/pci.h	Fri Apr 13 20:26:07 2001
+++ linux/include/asm-mips/pci.h	Mon Dec  3 22:43:26 2001
@@ -201,6 +201,9 @@
 #endif
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 /*
  * These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
diff -urN linux-2.4.5-pre2/include/asm-mips64/pci.h linux/include/asm-mips64/pci.h
--- linux-2.4.5-pre2/include/asm-mips64/pci.h	Tue Nov 28 21:42:04 2000
+++ linux/include/asm-mips64/pci.h	Mon Dec  3 22:43:26 2001
@@ -196,6 +196,9 @@
 #endif
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 /*
  * These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
diff -urN linux-2.4.5-pre2/include/asm-parisc/pci.h linux/include/asm-parisc/pci.h
--- linux-2.4.5-pre2/include/asm-parisc/pci.h	Tue Dec  5 12:29:39 2000
+++ linux/include/asm-parisc/pci.h	Mon Dec  3 22:43:26 2001
@@ -212,4 +212,7 @@
 #define PCIBIOS_MIN_IO          0x10
 #define PCIBIOS_MIN_MEM         0x1000 /* NBPG - but pci/setup-res.c dies */
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* __ASM_PARISC_PCI_H */
diff -urN linux-2.4.5-pre2/include/asm-ppc/atomic.h linux/include/asm-ppc/atomic.h
--- linux-2.4.5-pre2/include/asm-ppc/atomic.h	Mon Oct  2 11:54:51 2000
+++ linux/include/asm-ppc/atomic.h	Mon Dec  3 22:43:26 2001
@@ -86,4 +86,26 @@
 #define atomic_dec(v)			((void) atomic_dec_return((v)))
 #define atomic_dec_and_test(v)		(atomic_dec_return((v)) == 0)
 
+/*
+ * Atomically test *v and decrement if it is greater than 0.
+ * The function returns the old value of *v minus 1.
+ */
+static __inline__ int atomic_dec_if_positive(atomic_t *v)
+{
+	int t;
+
+	__asm__ __volatile__("\n"
+"1:	lwarx	%0,0,%2\n"
+"	addic.	%0,%0,-1\n"
+"	blt	2f\n"
+"	stwcx.	%0,0,%2\n"
+"	bne	1b\n"
+"2:"
+	: "=&r" (t), "=m" (v->counter)
+	: "r" (&v->counter), "m" (v->counter)
+	: "cc");
+
+	return t;
+}
+
 #endif /* _ASM_PPC_ATOMIC_H_ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/bitops.h linux/include/asm-ppc/bitops.h
--- linux-2.4.5-pre2/include/asm-ppc/bitops.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/bitops.h	Mon Dec  3 22:43:26 2001
@@ -35,10 +35,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 	
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	or	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	or	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=m" (*p)
 	: "r" (mask), "r" (p), "m" (*p)
@@ -68,10 +68,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	andc	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	andc	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=m" (*p)
 	: "r" (mask), "r" (p), "m" (*p)
@@ -84,10 +84,10 @@
 	unsigned long mask = 1 << (nr & 0x1f);
 	unsigned long *p = ((unsigned long *)addr) + (nr >> 5);
 
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	xor	%0,%0,%2
-	stwcx.	%0,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	xor	%0,%0,%2 \n\
+	stwcx.	%0,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=m" (*p)
 	: "r" (mask), "r" (p), "m" (*p)
@@ -103,10 +103,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	or	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	or	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -135,10 +135,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	andc	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	andc	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
@@ -167,10 +167,10 @@
 	unsigned int mask = 1 << (nr & 0x1f);
 	volatile unsigned int *p = ((volatile unsigned int *)addr) + (nr >> 5);
 
-	__asm__ __volatile__(SMP_WMB "\
-1:	lwarx	%0,0,%4
-	xor	%1,%0,%3
-	stwcx.	%1,0,%4
+	__asm__ __volatile__(SMP_WMB "\n\
+1:	lwarx	%0,0,%4 \n\
+	xor	%1,%0,%3 \n\
+	stwcx.	%1,0,%4 \n\
 	bne	1b"
 	SMP_MB
 	: "=&r" (old), "=&r" (t), "=m" (*p)
diff -urN linux-2.4.5-pre2/include/asm-ppc/bseip.h linux/include/asm-ppc/bseip.h
--- linux-2.4.5-pre2/include/asm-ppc/bseip.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/bseip.h	Mon Dec  3 22:43:26 2001
@@ -8,6 +8,7 @@
 #ifndef __MACH_BSEIP_DEFS
 #define __MACH_BSEIP_DEFS
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -29,6 +30,7 @@
 #define IMAP_SIZE		((uint)(64 * 1024))
 #define PCMCIA_MEM_ADDR		((uint)0x04000000)
 #define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#endif	/* !__ASSEMBLY__ */
 
 /* We don't use the 8259.
 */
diff -urN linux-2.4.5-pre2/include/asm-ppc/checksum.h linux/include/asm-ppc/checksum.h
--- linux-2.4.5-pre2/include/asm-ppc/checksum.h	Sat Nov 11 18:23:10 2000
+++ linux/include/asm-ppc/checksum.h	Mon Dec  3 22:43:26 2001
@@ -84,10 +84,10 @@
 						   unsigned int sum) 
 {
     __asm__("
-	addc %0,%0,%1
-	adde %0,%0,%2
-	adde %0,%0,%3
-	addze %0,%0
+	addc %0,%0,%1 \n\
+	adde %0,%0,%2 \n\
+	adde %0,%0,%3 \n\
+	addze %0,%0 \n\
 	"
 	: "=r" (sum)
 	: "r" (daddr), "r"(saddr), "r"((proto<<16)+len), "0"(sum));
diff -urN linux-2.4.5-pre2/include/asm-ppc/elf.h linux/include/asm-ppc/elf.h
--- linux-2.4.5-pre2/include/asm-ppc/elf.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/elf.h	Mon Dec  3 22:43:26 2001
@@ -74,20 +74,39 @@
  * We need to put in some extra aux table entries to tell glibc what
  * the cache block size is, so it can use the dcbz instruction safely.
  */
-#define AT_DCACHEBSIZE		17
-#define AT_ICACHEBSIZE		18
-#define AT_UCACHEBSIZE		19
+#define AT_DCACHEBSIZE		19
+#define AT_ICACHEBSIZE		20
+#define AT_UCACHEBSIZE		21
+/* A special ignored type value for PPC, for glibc compatibility.  */
+#define AT_IGNOREPPC		22
 
 extern int dcache_bsize;
 extern int icache_bsize;
 extern int ucache_bsize;
 
-#define DLINFO_EXTRA_ITEMS	3
-#define EXTRA_DLINFO		do {			\
-	NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize);	\
-	NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize);	\
-	NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize);	\
-} while (0)
+/*
+ * The requirements here are:
+ * - keep the final alignment of sp (sp & 0xf)
+ * - make sure the 32-bit value at the first 16 byte aligned position of
+ *   AUXV is greater than 16 for glibc compatibility.
+ *   AT_IGNOREPPC is used for that.
+ * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
+ *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
+ */
+#define DLINFO_ARCH_ITEMS	3
+#define ARCH_DLINFO							\
+do {									\
+	sp -= DLINFO_ARCH_ITEMS * 2;					\
+	NEW_AUX_ENT(0, AT_DCACHEBSIZE, dcache_bsize);			\
+	NEW_AUX_ENT(1, AT_ICACHEBSIZE, icache_bsize);			\
+	NEW_AUX_ENT(2, AT_UCACHEBSIZE, ucache_bsize);			\
+	/*								\
+	 * Now handle glibc compatibility.				\
+	 */								\
+	sp -= 2*2;							\
+	NEW_AUX_ENT(0, AT_IGNOREPPC, AT_IGNOREPPC);			\
+	NEW_AUX_ENT(1, AT_IGNOREPPC, AT_IGNOREPPC);			\
+ } while (0)
 
 #endif /* __KERNEL__ */
 #endif
diff -urN linux-2.4.5-pre2/include/asm-ppc/fads.h linux/include/asm-ppc/fads.h
--- linux-2.4.5-pre2/include/asm-ppc/fads.h	Sat Nov 27 15:42:33 1999
+++ linux/include/asm-ppc/fads.h	Mon Dec  3 22:43:26 2001
@@ -8,6 +8,7 @@
 #ifndef __MACH_FADS_DEFS
 #define __MACH_FADS_DEFS
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -16,24 +17,54 @@
 	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
 	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
 	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
 } bd_t;
 
 extern bd_t m8xx_board_info;
 
 /* Memory map is configured by the PROM startup.
  * I tried to follow the FADS manual, although the startup PROM
- * dictates this.
+ * dictates this and we simply have to move some of the physical
+ * addresses for Linux.
  */
-#define BCSR_ADDR		((uint)0x02100000)
+#define BCSR_ADDR		((uint)0xfe000000)
 #define BCSR_SIZE		((uint)(64 * 1024))
-#define	BCSR0			((uint)0x02100000)
-#define	BCSR1			((uint)0x02100004)
-#define	BCSR2			((uint)0x02100008)
-#define	BCSR3			((uint)0x0210000c)
-#define	BCSR4			((uint)0x02100010)
-#define IMAP_ADDR		((uint)0x02200000)
+#define	BCSR0			((uint)0xfe000000)
+#define	BCSR1			((uint)0xfe000004)
+#define	BCSR2			((uint)0xfe000008)
+#define	BCSR3			((uint)0xfe00000c)
+#define	BCSR4			((uint)0xfe000010)
+#define IMAP_ADDR		((uint)0xf0000000)
 #define IMAP_SIZE		((uint)(64 * 1024))
 #define PCMCIA_MEM_ADDR		((uint)0x04000000)
 #define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+ 
+/* Bits of interest in the BCSRs.
+ */
+#define BCSR1_ETHEN		((uint)0x20000000)
+#define BCSR1_RS232EN_1		((uint)0x01000000)
+#define BCSR1_RS232EN_2		((uint)0x00040000)
+#define BCSR4_ETHLOOP		((uint)0x80000000)	/* EEST Loopback */
+#define BCSR4_EEFDX		((uint)0x40000000)	/* EEST FDX enable */
+#define BCSR4_FETH_EN		((uint)0x08000000)	/* PHY enable */
+#define BCSR4_FETHCFG0		((uint)0x04000000)	/* PHY autoneg mode */
+#define BCSR4_FETHCFG1		((uint)0x00400000)	/* PHY autoneg mode */
+#define BCSR4_FETHFDE		((uint)0x02000000)	/* PHY FDX advertise */
+#define BCSR4_FETHRST		((uint)0x00200000)	/* PHY Reset */
+#endif /* !__ASSEMBLY__ */
+ 
+/* Interrupt level assignments.
+ */
+#define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+#define PHY_INTERRUPT	SIU_IRQ2	/* PHY link change interrupt */
+
+/* We don't use the 8259.
+ */
+#define NR_8259_INTS	0
+ 
+/* Machine type
+ */
+#define _MACH_8xx (_MACH_fads)
 
 #endif
diff -urN linux-2.4.5-pre2/include/asm-ppc/feature.h linux/include/asm-ppc/feature.h
--- linux-2.4.5-pre2/include/asm-ppc/feature.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/feature.h	Mon Dec  3 22:43:26 2001
@@ -75,25 +75,32 @@
 
 
 /*
- * Additional functions related to Core99 machines
+ * Additional functions related to Core99 machines. We should extend the
+ * feature mecanism to make those fit into it. For now, they are still
+ * separate functions.
  */
 extern void	feature_set_gmac_power(struct device_node* device, int power);
 
 	/* use constants in KeyLargo.h for the reset parameter */
-extern void	feature_set_gmac_phy_reset(struct device_node* device, int reset);
+extern void	feature_gmac_phy_reset(struct device_node* device);
 
 extern void	feature_set_usb_power(struct device_node* device, int power);
 
 extern void 	feature_set_firewire_power(struct device_node* device, int power);
+extern void 	feature_set_firewire_cable_power(struct device_node* device, int power);
 
-extern void	feature_core99_kick_cpu1(void);
+extern void	feature_set_airport_power(struct device_node* device, int power);
+
+extern void	feature_core99_kick_cpu(int cpu_nr);
 
 /*
- * Sleep related functions. At term, they should be high-priority notifiers
+ * Sleep related functions. At term, they should be high-priority notifiers,
+ * but this would require some changes to the current sleep scheme that won't
+ * be done in 2.4.
  */
 extern void	feature_prepare_for_sleep(void);
-
 extern void	feature_wake_up(void);
+extern int	feature_can_sleep(void);
 
 #endif /* __ASM_PPC_FEATURE_H */
 #endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/gemini.h linux/include/asm-ppc/gemini.h
--- linux-2.4.5-pre2/include/asm-ppc/gemini.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/gemini.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,168 @@
+/*
+ *  include/asm-ppc/gemini.h
+ *
+ *
+ *  Onboard registers and descriptions for Synergy Microsystems' 
+ *  "Gemini" boards.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_GEMINI_H
+#define __PPC_GEMINI_H
+
+/*  Registers  */
+
+#define GEMINI_SERIAL_B     (0xffeffb00)
+#define GEMINI_SERIAL_A     (0xffeffb08)
+#define GEMINI_USWITCH      (0xffeffd00)
+#define GEMINI_BREV         (0xffeffe00)
+#define GEMINI_BECO         (0xffeffe08)
+#define GEMINI_FEAT         (0xffeffe10)
+#define GEMINI_BSTAT        (0xffeffe18)
+#define GEMINI_CPUSTAT      (0xffeffe20)
+#define GEMINI_L2CFG        (0xffeffe30)
+#define GEMINI_MEMCFG       (0xffeffe38)
+#define GEMINI_FLROM        (0xffeffe40)
+#define GEMINI_P0PCI        (0xffeffe48)
+#define GEMINI_FLWIN        (0xffeffe50)
+#define GEMINI_P0INTMASK    (0xffeffe60)
+#define GEMINI_P0INTAP      (0xffeffe68)
+#define GEMINI_PCIERR       (0xffeffe70)
+#define GEMINI_LEDBASE      (0xffeffe80)
+#define GEMINI_RTC          (0xffe9fff8)
+#define GEMINI_LEDS         8
+#define GEMINI_SWITCHES     8
+
+
+/* Flash ROM bit definitions */
+#define GEMINI_FLS_WEN      (1<<0)
+#define GEMINI_FLS_JMP      (1<<6)
+#define GEMINI_FLS_BOOT     (1<<7)
+
+/* Memory bit definitions */
+#define GEMINI_MEM_TYPE_MASK 0xc0
+#define GEMINI_MEM_SIZE_MASK 0x38
+#define GEMINI_MEM_BANK_MASK 0x07
+
+/* L2 cache bit definitions */
+#define GEMINI_L2_SIZE_MASK  0xc0
+#define GEMINI_L2_RATIO_MASK 0x03
+
+/* Timebase register bit definitons */
+#define GEMINI_TIMEB0_EN     (1<<0)
+#define GEMINI_TIMEB1_EN     (1<<1)
+#define GEMINI_TIMEB2_EN     (1<<2)
+#define GEMINI_TIMEB3_EN     (1<<3)
+
+/* CPU status bit definitions */
+#define GEMINI_CPU_ID_MASK   0x03
+#define GEMINI_CPU_COUNT_MASK 0x0c
+#define GEMINI_CPU0_HALTED   (1<<4)
+#define GEMINI_CPU1_HALTED   (1<<5)
+#define GEMINI_CPU2_HALTED   (1<<6)
+#define GEMINI_CPU3_HALTED   (1<<7)
+
+/* Board status bit definitions */
+#define GEMINI_BRD_FAIL      (1<<0)   /* FAIL led is lit */
+#define GEMINI_BRD_BUS_MASK  0x0c     /* PowerPC bus speed */
+
+/* Board family/feature bit descriptions */
+#define GEMINI_FEAT_HAS_FLASH (1<<0)
+#define GEMINI_FEAT_HAS_ETH   (1<<1)
+#define GEMINI_FEAT_HAS_SCSI  (1<<2)
+#define GEMINI_FEAT_HAS_P0    (1<<3)
+#define GEMINI_FEAT_FAM_MASK  0xf0
+
+/* Mod/ECO bit definitions */
+#define GEMINI_ECO_LEVEL_MASK 0x0f
+#define GEMINI_MOD_MASK       0xf0
+
+/* Type/revision bit definitions */
+#define GEMINI_REV_MASK       0x0f
+#define GEMINI_TYPE_MASK      0xf0
+
+/* User switch definitions */
+#define GEMINI_SWITCH_VERBOSE    1     /* adds "debug" to boot cmd line */
+#define GEMINI_SWITCH_SINGLE_USER 7    /* boots into "single-user" mode */
+
+#define SGS_RTC_CONTROL  0
+#define SGS_RTC_SECONDS  1
+#define SGS_RTC_MINUTES  2
+#define SGS_RTC_HOURS    3
+#define SGS_RTC_DAY      4
+#define SGS_RTC_DAY_OF_MONTH 5
+#define SGS_RTC_MONTH    6
+#define SGS_RTC_YEAR     7
+
+#define SGS_RTC_SET  0x80
+#define SGS_RTC_IS_STOPPED 0x80
+
+#define GRACKLE_CONFIG_ADDR_ADDR  (0xfec00000)
+#define GRACKLE_CONFIG_DATA_ADDR  (0xfee00000)
+
+#define GEMINI_BOOT_INIT  (0xfff00100)
+
+#ifndef __ASSEMBLY__
+
+static inline void grackle_write( unsigned long addr, unsigned long data )
+{
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync "
+  : /* no output */
+  : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr),
+    "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data));
+}
+
+static inline unsigned long grackle_read( unsigned long addr )
+{
+  unsigned long val;
+
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync "
+  : "=r" (val)
+  : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR),
+    "r" (GRACKLE_CONFIG_DATA_ADDR));
+
+  return val;
+}
+
+static inline void gemini_led_on( int led )
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1;
+}
+
+static inline void gemini_led_off(int led)
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0;
+}
+
+static inline int gemini_led_val(int led)
+{
+  int val = 0;
+  if (led >= 0 && led < GEMINI_LEDS)
+    val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3));
+  return (val & 0x1);
+}
+
+/* returns processor id from the board */
+static inline int gemini_processor(void)
+{
+  unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT);
+  return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK));
+}
+
+
+extern void _gemini_reboot(void);
+extern void gemini_prom_init(void);
+extern void gemini_init_l2(void);
+#endif /* __ASSEMBLY__ */
+#endif
+#endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/gemini_serial.h linux/include/asm-ppc/gemini_serial.h
--- linux-2.4.5-pre2/include/asm-ppc/gemini_serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/gemini_serial.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,41 @@
+#ifdef __KERNEL__
+#ifndef __ASMPPC_GEMINI_SERIAL_H
+#define __ASMPPC_GEMINI_SERIAL_H
+
+#include <linux/config.h>
+#include <asm/gemini.h>
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 24.576 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (24576000 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \
+        { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \
+
+#ifdef CONFIG_GEMINI_PU32
+#define PU32_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS },
+#else
+#define PU32_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DEFNS \
+        PU32_SERIAL_PORT_DEFNS
+
+#endif
+#endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/heathrow.h linux/include/asm-ppc/heathrow.h
--- linux-2.4.5-pre2/include/asm-ppc/heathrow.h	Sun Sep 17 09:48:08 2000
+++ linux/include/asm-ppc/heathrow.h	Mon Dec  3 22:43:26 2001
@@ -6,14 +6,21 @@
  * Copyright (C) 1997 Paul Mackerras.
  */
 
+/* Front light color on Yikes/B&W G3. 32 bits */
+#define HEATHROW_FRONT_LIGHT		0x32 /* (set to 0 or 0xffffffff) */
+
+/* Brightness/contrast (gossamer iMac ?). 8 bits */
+#define HEATHROW_BRIGHTNESS_CNTL	0x32
+#define HEATHROW_CONTRAST_CNTL		0x33
+
 /* offset from ohare base for feature control register */
-#define HEATHROW_FEATURE_REG	0x38
+#define HEATHROW_FEATURE_REG		0x38
 
 /*
  * Bits in feature control register.
  * Bits postfixed with a _N are in inverse logic
  */
-#define HRW_RESET_SCC		0x00000001	/* Named in_use_led in OF ??? */
+#define HRW_RESET_SCC		0x00000001	/* actually controls transceiver... */
 #define HRW_BAY_POWER_N		0x00000002
 #define HRW_BAY_PCI_ENABLE	0x00000004
 #define HRW_BAY_IDE_ENABLE	0x00000008
diff -urN linux-2.4.5-pre2/include/asm-ppc/hw_irq.h linux/include/asm-ppc/hw_irq.h
--- linux-2.4.5-pre2/include/asm-ppc/hw_irq.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/hw_irq.h	Mon Dec  3 22:43:26 2001
@@ -7,31 +7,18 @@
 #ifndef _PPC_HW_IRQ_H
 #define _PPC_HW_IRQ_H
 
-struct int_control_struct
-{
-	void (*int_cli)(void);
-	void (*int_sti)(void);
-	void (*int_restore_flags)(unsigned long);
-	void (*int_save_flags)(unsigned long *);
-	void (*int_set_lost)(unsigned long);
-};
-extern struct int_control_struct int_control;
 extern unsigned long timer_interrupt_intercept;
 extern unsigned long do_IRQ_intercept;
 int timer_interrupt(struct pt_regs *);
 
-extern void __no_use_sti(void);
-extern void __no_use_cli(void);
-extern void __no_use_restore_flags(unsigned long);
-extern void __no_use_save_flags(unsigned long *);
-extern void __no_use_set_lost(unsigned long);
+extern void __sti(void);
+extern void __cli(void);
+extern void __restore_flags(unsigned long);
+extern void __save_flags_ptr(unsigned long *);
+extern unsigned long __sti_end, __cli_end, __restore_flags_end, __save_flags_ptr_end;
 
-#define __cli() int_control.int_cli()
-#define __sti() int_control.int_sti()
-#define __save_flags(flags) int_control.int_save_flags((unsigned long *)&flags)
-#define __restore_flags(flags) int_control.int_restore_flags((unsigned long)flags)
+#define __save_flags(flags) __save_flags_ptr((unsigned long *)&flags)
 #define __save_and_cli(flags) ({__save_flags(flags);__cli();})
-#define __set_lost(irq) ({ if ((unsigned long)int_control.int_set_lost) int_control.int_set_lost(irq); })
 
 extern void do_lost_interrupts(unsigned long);
 
diff -urN linux-2.4.5-pre2/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
--- linux-2.4.5-pre2/include/asm-ppc/ide.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/ide.h	Mon Dec  3 22:43:26 2001
@@ -16,7 +16,7 @@
 #include <asm/processor.h>
 
 #ifndef MAX_HWIFS
-#define MAX_HWIFS	4
+#define MAX_HWIFS	8
 #endif
 
 #include <asm/hdreg.h>
@@ -159,8 +159,13 @@
 	} b;
 } select_t;
 
+#if !defined(ide_request_irq)
 #define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#endif
+
+#if !defined(ide_free_irq)
 #define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#endif
 
 /*
  * The following are not needed for the non-m68k ports
diff -urN linux-2.4.5-pre2/include/asm-ppc/keylargo.h linux/include/asm-ppc/keylargo.h
--- linux-2.4.5-pre2/include/asm-ppc/keylargo.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/keylargo.h	Mon Dec  3 22:43:26 2001
@@ -3,6 +3,12 @@
  *
  */
 
+/* "Pangea" chipset has keylargo device-id 0x25 while core99
+ * has device-id 0x22. The rev. of the pangea one is 0, so we
+ * fake an artificial rev. in keylargo_rev by oring 0x100
+ */
+#define KL_PANGEA_REV		0x100
+
 /* offset from base for feature control registers */
 #define KEYLARGO_MBCR		0x34	/* Media bay control/status */
 #define KEYLARGO_FCR0		0x38
@@ -18,25 +24,47 @@
 #define KEYLARGO_GPIO_EXTINT_CNT	18
 #define KEYLARGO_GPIO_0			0x6A
 #define KEYLARGO_GPIO_CNT		17
+#define KEYLARGO_GPIO_OUTPUT_ENABLE	0x04
+#define KEYLARGO_GPIO_OUTOUT_DATA	0x01
 
 /* Specific GPIO regs */
 
+#define KL_GPIO_MODEM_RESET		(KEYLARGO_GPIO_0+0x03) /* Pangea */
+#define KL_GPIO_MODEM_POWER		(KEYLARGO_GPIO_0+0x02) /* Pangea */
+
+#define KL_GPIO_FW_CABLE_POWER		(KEYLARGO_GPIO_0+0x09)
+
 #define KL_GPIO_ETH_PHY_RESET		(KEYLARGO_GPIO_0+0x10)
-#define KL_GPIO_ETH_PHY_RESET_ASSERT	0x04
-#define KL_GPIO_ETH_PHY_RESET_RELEASE	0x05
-#define KL_GPIO_ETH_PHY_RESET_TRISTATE	0x00
-
-#define KL_GPIO_KICK_CPU1		(KEYLARGO_GPIO_0+0x0a)
-#define KL_GPIO_KICK_CPU1_UP		0x04
-#define KL_GPIO_KICK_CPU1_DOWN		0x38
+
+#define KL_GPIO_EXTINT_CPU1		(KEYLARGO_GPIO_0+0x0a)
+#define KL_GPIO_EXTINT_CPU1_ASSERT	0x04
+#define KL_GPIO_EXTINT_CPU1_RELEASE	0x38
+
+#define KL_GPIO_RESET_CPU0		(KEYLARGO_GPIO_EXTINT_0+0x03)
+#define KL_GPIO_RESET_CPU1		(KEYLARGO_GPIO_EXTINT_0+0x04)
+#define KL_GPIO_RESET_CPU2		(KEYLARGO_GPIO_EXTINT_0+0x0f)
+#define KL_GPIO_RESET_CPU3		(KEYLARGO_GPIO_EXTINT_0+0x10)
 
 #define KL_GPIO_PMU_MESSAGE_IRQ		(KEYLARGO_GPIO_EXTINT_0+0x09)
 #define KL_GPIO_PMU_MESSAGE_BIT		0x02
 
+#define KL_GPIO_AIRPORT_0		(KEYLARGO_GPIO_EXTINT_0+0x0a)
+#define KL_GPIO_AIRPORT_1		(KEYLARGO_GPIO_EXTINT_0+0x0d)
+#define KL_GPIO_AIRPORT_2		(KEYLARGO_GPIO_0+0x0d)
+#define KL_GPIO_AIRPORT_3		(KEYLARGO_GPIO_0+0x0e)
+#define KL_GPIO_AIRPORT_4		(KEYLARGO_GPIO_0+0x0f)
+
 /*
  * Bits in feature control register
  */
-#define KL_MBCR_MBDEV_ENABLE		0x00001000
+#define KL_MBCR_MB0_DEV_ENABLE		0x00001000
+#define KL_MBCR_MB0_DEV_POWER		0x00000400
+#define KL_MBCR_MB0_DEV_RESET		0x00000200
+#define KL_MBCR_MB0_ENABLE		0x00000100
+#define KL_MBCR_MB1_DEV_ENABLE		0x10000000
+#define KL_MBCR_MB1_DEV_POWER		0x04000000
+#define KL_MBCR_MB1_DEV_RESET		0x02000000
+#define KL_MBCR_MB1_ENABLE		0x01000000
 
 #define KL0_SCC_B_INTF_ENABLE		0x00000001	/* ??? */
 #define KL0_SCC_A_INTF_ENABLE		0x00000002	/* ??? */
@@ -45,16 +73,27 @@
 #define KL0_SCCA_ENABLE			0x00000010
 #define KL0_SCCB_ENABLE			0x00000020
 #define KL0_SCC_CELL_ENABLE		0x00000040
-#define KL0_IRDA_ENABLE			0x00008000
-#define KL0_IRDA_CLK32_ENABLE		0x00010000
-#define KL0_IRDA_CLK19_ENABLE		0x00020000
 #define KL0_USB0_PAD_SUSPEND0		0x00040000
 #define KL0_USB0_PAD_SUSPEND1		0x00080000
 #define KL0_USB0_CELL_ENABLE		0x00100000
 #define KL0_USB1_PAD_SUSPEND0		0x00400000
 #define KL0_USB1_PAD_SUSPEND1		0x00800000
 #define KL0_USB1_CELL_ENABLE		0x01000000
+/* KL id 0x22 only */
 #define KL0_USB_REF_SUSPEND		0x10000000
+#define KL0_IRDA_ENABLE			0x00008000
+#define KL0_IRDA_CLK32_ENABLE		0x00010000
+#define KL0_IRDA_CLK19_ENABLE		0x00020000
+/* KL id 0x25 (pangea) only */
+#define KL0_USB1_PAD_SUSPEND_SEL	0x00020000
+#define KL0_USB1_REF_SUSPEND		0x00010000
+#define KL0_USB1_REF_SUSPEND_SEL	0x00008000
+#define KL0_USB1_PMI			0x00004000
+#define KL0_USB0_PAD_SUSPEND_SEL	0x00002000
+#define KL0_USB0_REF_SUSPEND		0x00001000
+#define KL0_USB0_REF_SUSPEND_SEL	0x00000800
+#define KL0_USB0_PMI			0x00000400
+
 
 #define KL0_SERIAL_ENABLE		(KL0_SCC_B_INTF_ENABLE | \
 					KL0_SCC_SLOWPCLK | \
@@ -102,11 +141,11 @@
 #define KL3_STOPPING33_ENABLED		0x00080000
 
 /* Port 0,1 : bus 0, port 2,3 : bus 1 */
-#define KL4_SET_PORT_ENABLE(p)		(0x00000008 << (p<<3))
-#define KL4_SET_PORT_RESUME(p)		(0x00000004 << (p<<3))
-#define KL4_SET_PORT_CONNECT(p)		(0x00000002 << (p<<3))
-#define KL4_SET_PORT_DISCONNECT(p)	(0x00000001 << (p<<3))
-#define KL4_GET_PORT_RESUME(p)		(0x00000040 << (p<<3))
-#define KL4_GET_PORT_CONNECT(p)		(0x00000020 << (p<<3))
-#define KL4_GET_PORT_DISCONNECT(p)	(0x00000010 << (p<<3))
+#define KL4_SET_PORT_ENABLE(p)		(0x00000008 << ((p)<<3))
+#define KL4_SET_PORT_RESUME(p)		(0x00000004 << ((p)<<3))
+#define KL4_SET_PORT_CONNECT(p)		(0x00000002 << ((p)<<3))
+#define KL4_SET_PORT_DISCONNECT(p)	(0x00000001 << ((p)<<3))
+#define KL4_GET_PORT_RESUME(p)		(0x00000040 << ((p)<<3))
+#define KL4_GET_PORT_CONNECT(p)		(0x00000020 << ((p)<<3))
+#define KL4_GET_PORT_DISCONNECT(p)	(0x00000010 << ((p)<<3))
 
diff -urN linux-2.4.5-pre2/include/asm-ppc/machdep.h linux/include/asm-ppc/machdep.h
--- linux-2.4.5-pre2/include/asm-ppc/machdep.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/machdep.h	Mon Dec  3 22:43:26 2001
@@ -22,7 +22,6 @@
 	unsigned int	(*irq_cannonicalize)(unsigned int irq);
 	void		(*init_IRQ)(void);
 	int		(*get_irq)(struct pt_regs *);
-	void		(*post_irq)( struct pt_regs *, int );
 	
 	/* A general init function, called by ppc_init in init/main.c.
 	   May be NULL. */
@@ -41,6 +40,7 @@
 	unsigned long	heartbeat_reset;
 	unsigned long	heartbeat_count;
 
+	unsigned long	(*find_end_of_memory)(void);
   	void		(*progress)(char *, unsigned short);
 
 	unsigned char 	(*nvram_read_val)(int addr);
@@ -79,6 +79,11 @@
 		 * Returns 0 to allow assignement/enabling of the device
 		 */
 	int  (*pcibios_enable_device_hook)(struct pci_dev *, int initial);
+
+		/* Called at then very end of pcibios_init()
+		 */
+	void (*pcibios_after_init)(void);
+		 
 
 	/* this is for modules, since _machine can be a define -- Cort */
 	int ppc_machine;
diff -urN linux-2.4.5-pre2/include/asm-ppc/mbx.h linux/include/asm-ppc/mbx.h
--- linux-2.4.5-pre2/include/asm-ppc/mbx.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/mbx.h	Mon Dec  3 22:43:26 2001
@@ -11,6 +11,7 @@
 #ifndef __MACH_MBX_DEFS
 #define __MACH_MBX_DEFS
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * EPPC-Bug starts it up.
  */
@@ -25,7 +26,13 @@
 	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
 	unsigned int	bi_clun;	/* Boot device controller */
 	unsigned int	bi_dlun;	/* Boot device logical dev */
-	unsigned int	bi_baudrate;	/* ...to be like everyone else */
+
+	/* These fields are not part of the board information structure
+	 * provided by the boot rom.  They are filled in by embed_config.c
+	 * so we have the information consistent with other platforms.
+	 */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
 } bd_t;
 
 /* Memory map for the MBX as configured by EPPC-Bug.  We could reprogram
@@ -78,6 +85,7 @@
 #define ISA_BRIDGE_INT	SIU_IRQ3	/* All those PC things */
 #define COMM_L_INT	SIU_IRQ6	/* MBX Comm expansion connector pin */
 #define STOP_ABRT_INT	SIU_IRQ7	/* Stop/Abort header pin */
+#endif /* !__ASSEMBLY__ */
 
 /* The MBX uses the 8259.
 */
diff -urN linux-2.4.5-pre2/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- linux-2.4.5-pre2/include/asm-ppc/mmu_context.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/mmu_context.h	Mon Dec  3 22:43:26 2001
@@ -18,6 +18,12 @@
    of any task that makes a kernel entry.  Shared does not mean they
    are not protected, just that the ASID comparison is not performed.
         -- Dan
+
+   The IBM4xx has 256 contexts, so we can just rotate through these
+   as a way of "switching" contexts.  If the TID of the TLB is zero,
+   the PID/TID comparison is disabled, so we can use a TID of zero
+   to represent all kernel pages as shared among all contexts.
+   	-- Dan
  */
 
 static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
@@ -26,12 +32,22 @@
 #ifdef CONFIG_8xx
 #define NO_CONTEXT      	16
 #define LAST_CONTEXT    	15
+#define BASE_CONTEXT		(-1)
+#define MUNGE_CONTEXT(n)        (n)
+#define flush_hash_segments(X, Y)	do { } while (0)
+
+#elif CONFIG_4xx
+#define NO_CONTEXT      	256
+#define LAST_CONTEXT    	255
+#define BASE_CONTEXT		(0)
 #define MUNGE_CONTEXT(n)        (n)
+#define flush_hash_segments(X, Y)	do { } while (0)
 
 #else
 
 /* PPC 6xx, 7xx CPUs */
 #define NO_CONTEXT      	0
+#define BASE_CONTEXT		(0)
 #define LAST_CONTEXT    	0xfffff
 
 /*
diff -urN linux-2.4.5-pre2/include/asm-ppc/mpc8xx.h linux/include/asm-ppc/mpc8xx.h
--- linux-2.4.5-pre2/include/asm-ppc/mpc8xx.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/mpc8xx.h	Mon Dec  3 22:43:26 2001
@@ -63,11 +63,14 @@
 #define PCI_DRAM_OFFSET 0
 #endif
 #else
+#if !defined(_IO_BASE)  /* defined in board specific header */
 #define _IO_BASE        0
+#endif
 #define _ISA_MEM_BASE   0
 #define PCI_DRAM_OFFSET 0
 #endif
 
+#ifndef __ASSEMBLY__
 extern unsigned long isa_io_base;
 extern unsigned long isa_mem_base;
 extern unsigned long pci_dram_offset;
@@ -82,6 +85,7 @@
 		       unsigned long flags, 
 		       const char *device,
 		       void *dev_id);
+#endif /* !__ASSEMBLY__ */
 #endif /* CONFIG_8xx */
 #endif
 #endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/oak.h linux/include/asm-ppc/oak.h
--- linux-2.4.5-pre2/include/asm-ppc/oak.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/oak.h	Mon Dec  3 22:43:26 2001
@@ -66,5 +66,10 @@
 }
 #endif
 
+/* Generic 4xx type
+*/
+#define _MACH_4xx (_MACH_oak)
+
+
 #endif /* __OAK_H__ */
 #endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/pci-bridge.h linux/include/asm-ppc/pci-bridge.h
--- linux-2.4.5-pre2/include/asm-ppc/pci-bridge.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/pci-bridge.h	Mon Dec  3 22:43:26 2001
@@ -27,6 +27,11 @@
 extern struct pci_controller*
 pci_find_hose_for_OF_device(struct device_node* node);
 
+/* Fill up host controller resources from the OF node */
+extern void
+pci_process_bridge_OF_ranges(struct pci_controller *hose,
+			   struct device_node *dev, int primary);
+
 /*
  * Structure of a PCI controller (host bridge)
  */
diff -urN linux-2.4.5-pre2/include/asm-ppc/pci.h linux/include/asm-ppc/pci.h
--- linux-2.4.5-pre2/include/asm-ppc/pci.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/pci.h	Mon Dec  3 22:43:26 2001
@@ -110,6 +110,9 @@
 	return 1;
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #define sg_dma_address(sg)	(virt_to_bus((sg)->address))
 #define sg_dma_len(sg)		((sg)->length)
 
diff -urN linux-2.4.5-pre2/include/asm-ppc/pgtable.h linux/include/asm-ppc/pgtable.h
--- linux-2.4.5-pre2/include/asm-ppc/pgtable.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/pgtable.h	Mon Dec  3 22:43:26 2001
@@ -418,11 +418,11 @@
 {
 	unsigned long old, tmp;
 	
-	__asm__ __volatile__("\
-1:	lwarx	%0,0,%3
-	andc	%1,%0,%4
-	or	%1,%1,%5
-	stwcx.	%1,0,%3
+	__asm__ __volatile__("\n\
+1:	lwarx	%0,0,%3 \n\
+	andc	%1,%0,%4 \n\
+	or	%1,%1,%5 \n\
+	stwcx.	%1,0,%3 \n\
 	bne-	1b"
 	: "=&r" (old), "=&r" (tmp), "=m" (*p)
 	: "r" (p), "r" (clr), "r" (set), "m" (*p)
diff -urN linux-2.4.5-pre2/include/asm-ppc/ppc4xx.h linux/include/asm-ppc/ppc4xx.h
--- linux-2.4.5-pre2/include/asm-ppc/ppc4xx.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/ppc4xx.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,282 @@
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: ppc4xx.h
+ *
+ *    Description:
+ *	A generic include file which pulls in appropriate include files
+ *      for specific board types based on configuration settings.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef __PPC4XX_H__
+#define	__PPC4XX_H__
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+
+#if defined(CONFIG_OAK)
+#include <asm/oak.h>
+#endif
+
+#if defined(CONFIG_WALNUT)
+#include <asm/walnut.h>
+#endif
+
+/* IO_BASE is for PCI I/O.
+ * ISA not supported, just here to resolve copilation.
+ */
+
+#define _IO_BASE	0xe8000000	/* The PCI address window */
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+extern unsigned long isa_io_base;
+
+/*
+ * The "residual" board information structure the boot loader passes
+ * into the kernel.
+ */
+extern unsigned char __res[];
+
+/* I don't know if this is general to 4xx, or unique to a specific
+ * processor or board.  In any case it is easy to move.
+ */
+#define PPC4xx_PCI_IO_ADDR	((uint)0xe8000000)
+#define PPC4xx_PCI_IO_SIZE	((uint)64*1024)
+#define PPC4xx_PCI_CFG_ADDR	((uint)0xeec00000)
+#define PPC4xx_PCI_CFG_SIZE	((uint)4*1024)
+#define PPC4xx_PCI_LCFG_ADDR	((uint)0xef400000)
+#define PPC4xx_PCI_LCFG_SIZE	((uint)4*1024)
+#define PPC4xx_ONB_IO_ADDR	((uint)0xef600000)
+#define PPC4xx_ONB_IO_SIZE	((uint)4*1024)
+
+#endif /* __ASSEMBLY__ */
+
+/* Device Control Registers unique to 4xx */
+
+#define	DCRN_BEAR	0x090	/* Bus Error Address Register */
+#define	DCRN_BESR	0x091	/* Bus Error Syndrome Register */
+#define	  BESR_DSES    	0x80000000	/* Data-Side Error Status */
+#define	  BESR_DMES	0x40000000	/* DMA Error Status */
+#define	  BESR_RWS	0x20000000	/* Read/Write Status */
+#define	  BESR_ETMASK	0x1C000000	/* Error Type */
+#define	    ET_PROT	0
+#define	    ET_PARITY	1
+#define	    ET_NCFG	2
+#define	    ET_BUSERR	4
+#define	    ET_BUSTO	6
+#define DCRN_CHCR0	0x0B1	/* Chip Control Register 1                    */
+#define DCRN_CHCR1	0x0B2	/* Chip Control Register 2                    */
+#define DCRN_CHPSR	0x0B4	/* Chip Pin Strapping                         */
+#define DCRN_CPMER	0x0B9	/* CPM Enable                                 */
+#define DCRN_CPMFR	0x0BA	/* CPM Force                                  */
+#define   CPM_IIC	0x80000000  /* IIC interface                          */
+#define   CPM_PCI	0x40000000  /* PCI bridge                             */
+#define   CPM_CPU	0x20000000  /* processor core                         */
+#define   CPM_DMA	0x10000000  /* DMA controller                         */
+#define   CPM_BRG	0x08000000  /* PLB to OPB bridge                      */
+#define   CPM_DCP	0x04000000  /* CodePack                               */
+#define   CPM_EBC	0x02000000  /* ROM/SRAM peripheral controller         */
+#define   CPM_SDRAM	0x01000000  /* SDRAM memory controller                */
+#define   CPM_PLB	0x00800000  /* PLB bus arbiter                        */
+#define   CPM_GPIO	0x00400000  /* General Purpose IO (??)                */
+#define   CPM_UART0	0x00200000  /* serial port 0                          */
+#define   CPM_UART1	0x00100000  /* serial port 1                          */
+#define   CPM_UIC	0x00080000  /* Universal Interrupt Controller         */
+#define   CPM_TMRCLK	0x00040000  /* CPU timers                             */
+#define   CPM_EMAC_MM	0x00020000  /* on-chip ethernet MM unit               */
+#define   CPM_EMAC_RM	0x00010000  /* on-chip ethernet RM unit               */
+#define   CPM_EMAC_TM	0x00008000  /* on-chip ethernet TM unit               */
+#define DCRN_CPMSR	0x0B8	/* CPM Status                                 */
+
+#define	DCRN_DMACR0	0x100	/* DMA Channel Control Register 0             */
+#define	DCRN_DMACT0	0x101	/* DMA Count Register 0                       */
+#define	DCRN_DMADA0	0x102	/* DMA Destination Address Register 0         */
+#define	DCRN_DMASA0	0x103	/* DMA Source Address Register 0              */
+#define DCRN_ASG0	0x104	/* DMA Scatter/Gather Descriptor Addr 0       */
+
+#define	DCRN_DMACR1	0x108	/* DMA Channel Control Register 1             */
+#define	DCRN_DMACT1	0x109	/* DMA Count Register 1                       */
+#define	DCRN_DMADA1	0x10A	/* DMA Destination Address Register 1         */
+#define	DCRN_DMASA1	0x10B	/* DMA Source Address Register 1              */
+#define DCRN_ASG1	0x10C	/* DMA Scatter/Gather Descriptor Addr 1       */
+
+#define	DCRN_DMACR2	0x110	/* DMA Channel Control Register 2             */
+#define	DCRN_DMACT2	0x111	/* DMA Count Register 2                       */
+#define	DCRN_DMADA2	0x112	/* DMA Destination Address Register 2         */
+#define	DCRN_DMASA2	0x113	/* DMA Source Address Register 2              */
+#define DCRN_ASG2	0x114	/* DMA Scatter/Gather Descriptor Addr 2       */
+
+#define	DCRN_DMACR3	0x118	/* DMA Channel Control Register 3             */
+#define	DCRN_DMACT3	0x119	/* DMA Count Register 3                       */
+#define	DCRN_DMADA3	0x11A	/* DMA Destination Address Register 3         */
+#define	DCRN_DMASA3	0x11B	/* DMA Source Address Register 3              */
+#define DCRN_ASG3	0x11C	/* DMA Scatter/Gather Descriptor Addr 3       */
+
+#define	DCRN_DMASR	0x120	/* DMA Status Register                        */
+#define DCRN_ASGC	0x123	/* DMA Scatter/Gather Command                 */
+#define DCRN_ADR	0x124	/* DMA Address Decode                         */
+
+#define DCRN_SLP        0x125   /* DMA Sleep Register                         */
+#define DCRN_POL        0x126   /* DMA Polarity Register                      */
+
+
+#define DCRN_EBCCFGADR	0x012	/* Peripheral Controller Address              */
+#define DCRN_EBCCFGDATA	0x013	/* Peripheral Controller Data                 */
+#define	DCRN_EXISR	0x040    /* External Interrupt Status Register */
+#define	DCRN_EXIER	0x042    /* External Interrupt Enable Register */
+#define	  EXIER_CIE	0x80000000	/* Critical Interrupt Enable */
+#define	  EXIER_SRIE	0x08000000	/* Serial Port Rx Int. Enable */
+#define	  EXIER_STIE	0x04000000	/* Serial Port Tx Int. Enable */
+#define	  EXIER_JRIE	0x02000000	/* JTAG Serial Port Rx Int. Enable */
+#define	  EXIER_JTIE	0x01000000	/* JTAG Serial Port Tx Int. Enable */
+#define	  EXIER_D0IE	0x00800000	/* DMA Channel 0 Interrupt Enable */
+#define	  EXIER_D1IE	0x00400000	/* DMA Channel 1 Interrupt Enable */
+#define	  EXIER_D2IE	0x00200000	/* DMA Channel 2 Interrupt Enable */
+#define	  EXIER_D3IE	0x00100000	/* DMA Channel 3 Interrupt Enable */
+#define	  EXIER_E0IE	0x00000010	/* External Interrupt 0 Enable */
+#define	  EXIER_E1IE	0x00000008	/* External Interrupt 1 Enable */
+#define	  EXIER_E2IE	0x00000004	/* External Interrupt 2 Enable */
+#define	  EXIER_E3IE	0x00000002	/* External Interrupt 3 Enable */
+#define	  EXIER_E4IE	0x00000001	/* External Interrupt 4 Enable */
+#define	DCRN_IOCR	0x0A0    /* Input/Output Configuration Register */
+#define	  IOCR_E0TE	0x80000000
+#define	  IOCR_E0LP	0x40000000
+#define	  IOCR_E1TE	0x20000000
+#define	  IOCR_E1LP	0x10000000
+#define	  IOCR_E2TE	0x08000000
+#define	  IOCR_E2LP	0x04000000
+#define	  IOCR_E3TE	0x02000000
+#define	  IOCR_E3LP	0x01000000
+#define	  IOCR_E4TE	0x00800000
+#define	  IOCR_E4LP	0x00400000
+#define	  IOCR_EDT     	0x00080000
+#define	  IOCR_SOR     	0x00040000
+#define	  IOCR_EDO	0x00008000
+#define	  IOCR_2XC	0x00004000
+#define	  IOCR_ATC	0x00002000
+#define	  IOCR_SPD	0x00001000
+#define	  IOCR_BEM	0x00000800
+#define	  IOCR_PTD	0x00000400
+#define	  IOCR_ARE	0x00000080
+#define	  IOCR_DRC	0x00000020
+#define	  IOCR_RDM(x)	(((x) & 0x3) << 3)
+#define	  IOCR_TCS	0x00000004
+#define	  IOCR_SCS	0x00000002
+#define	  IOCR_SPC	0x00000001
+#define DCRN_KIAR	0x014	/* Decompression Controller Address           */
+#define DCRN_KIDR	0x015	/* Decompression Controller Data              */
+#define DCRN_MALCR	0x180	/* MAL Configuration                          */
+#define   MALCR_MMSR    0x80000000    /* MAL Software reset                   */
+#define   MALCR_PLBP_1  0x00400000    /* MAL reqest priority:                 */
+#define   MALCR_PLBP_2  0x00800000    /*   lowsest is 00                      */
+#define   MALCR_PLBP_3  0x00C00000    /*   highest                            */
+#define   MALCR_GA      0x00200000    /* Guarded Active Bit                   */
+#define   MALCR_OA      0x00100000    /* Ordered Active Bit                   */
+#define   MALCR_PLBLE   0x00080000    /* PLB Lock Error Bit                   */
+#define   MALCR_PLBLT_1 0x00040000    /* PLB Latency Timer                    */
+#define   MALCR_PLBLT_2 0x00020000
+#define   MALCR_PLBLT_3 0x00010000
+#define   MALCR_PLBLT_4 0x00008000
+#define   MALCR_PLBLT_DEFAULT 0x00078000 /* JSP: Is this a valid default??    */
+#define   MALCR_PLBB    0x00004000    /* PLB Burst Deactivation Bit           */
+#define   MALCR_OPBBL   0x00000080    /* OPB Lock Bit                         */
+#define   MALCR_EOPIE   0x00000004    /* End Of Packet Interrupt Enable       */
+#define   MALCR_LEA     0x00000002    /* Locked Error Active                  */
+#define   MALCR_MSD     0x00000001    /* MAL Scroll Descriptor Bit            */
+#define DCRN_MALDBR     0x183   /* Debug Register                             */
+#define DCRN_MALESR	0x181	/* Error Status                               */
+#define   MALESR_EVB    0x80000000    /* Error Valid Bit                      */
+#define   MALESR_CID    0x40000000    /* Channel ID Bit  for channel 0        */
+#define   MALESR_DE     0x00100000    /* Descriptor Error                     */
+#define   MALESR_OEN    0x00080000    /* OPB Non-Fullword Error               */
+#define   MALESR_OTE    0x00040000    /* OPB Timeout Error                    */
+#define   MALESR_OSE    0x00020000    /* OPB Slave Error                      */
+#define   MALESR_PEIN   0x00010000    /* PLB Bus Error Indication             */
+#define   MALESR_DEI    0x00000010    /* Descriptor Error Interrupt           */
+#define   MALESR_ONEI   0x00000008    /* OPB Non-Fullword Error Interrupt     */
+#define   MALESR_OTEI   0x00000004    /* OPB Timeout Error Interrupt          */
+#define   MALESR_OSEI   0x00000002    /* OPB Slace Error Interrupt            */
+#define   MALESR_PBEI   0x00000001    /* PLB Bus Error Interrupt              */
+#define DCRN_MALIER	0x182	/* Interrupt Enable                           */
+#define   MALIER_DE     0x00000010    /* Descriptor Error Interrupt Enable    */
+#define   MALIER_NE     0x00000008    /* OPB Non-word Transfer Int Enable     */
+#define   MALIER_TE     0x00000004    /* OPB Time Out Error Interrupt Enable  */
+#define   MALIER_OPBE   0x00000002    /* OPB Slave Error Interrupt Enable     */
+#define   MALIER_PLBE   0x00000001    /* PLB Error Interrupt Enable           */
+#define DCRN_MALTXCARR  0x185   /* TX Channed Active Reset Register           */
+#define DCRN_MALTXCASR  0x184   /* TX Channel Active Set Register             */
+#define DCRN_MALTXDEIR	0x187	/* Tx Descriptor Error Interrupt              */
+#define DCRN_MALTXEOBISR    0x186   /* Tx End of Buffer Interrupt Status      */
+#define   MALOBISR_CH0  0x80000000    /* EOB channel 1 bit                    */
+#define   MALOBISR_CH2  0x40000000    /* EOB channel 2 bit                    */
+#define DCRN_MALRXCARR  0x191   /* RX Channed Active Reset Register           */
+#define DCRN_MALRXCASR  0x190   /* RX Channel Active Set Register             */
+#define DCRN_MALRXDEIR	0x193	/* Rx Descriptor Error Interrupt              */
+#define DCRN_MALRXEOBISR    0x192   /* Rx End of Buffer Interrupt Status      */
+#define DCRN_MALRXCTP0R	0x1C0	/* Channel Rx 0 Channel Table Pointer         */
+#define DCRN_MALTXCTP0R	0x1A0	/* Channel Tx 0 Channel Table Pointer         */
+#define DCRN_MALTXCTP1R	0x1A1	/* Channel Tx 1 Channel Table Pointer         */
+#define DCRN_MALRCBS0	0x1E0	/* Channel Rx 0 Channel Buffer Size           */
+#define DCRN_MEMCFGADR	0x010	/* Memory Controller Address                  */
+#define DCRN_MEMCFGDATA	0x011	/* Memory Controller Data                     */
+#define DCRN_OCMISARC	0x018	/* OCM Instr Side Addr Range Compare          */
+#define DCRN_OCMISCR	0x019	/* OCM Instr Side Control                     */
+#define DCRN_OCMDSARC	0x01A	/* OCM Data Side Addr Range Compare           */
+#define DCRN_OCMDSCR	0x01B	/* OCM Data Side Control                      */
+#define DCRN_PLB0_ACR	0x087	/* PLB Arbiter Control                        */
+#define DCRN_PLB0_BEAR	0x086	/* PLB Error Address                          */
+#define DCRN_PLB0_BESR	0x084	/* PLB Error Status                           */
+#define DCRN_PLLMR	0x0B0	/* PLL Mode                                   */
+#define DCRN_POB0_BEAR	0x0A2	/* PLB to OPB Error Address                   */
+#define DCRN_POB0_BESR0	0x0A0	/* PLB to OPB Error Status Register 1         */
+#define DCRN_POB0_BESR1	0x0A4	/* PLB to OPB Error Status Register 1         */
+#define DCRN_UICCR	0x0C3	/* UIC Critical                               */
+#define DCRN_UICER	0x0C2	/* UIC Enable                                 */
+#define DCRN_UICPR	0x0C4	/* UIC Polarity                               */
+#define DCRN_UICSR	0x0C0	/* UIC Status                                 */
+#define DCRN_UICTR	0x0C5	/* UIC Triggering                             */
+#define DCRN_UICMSR	0x0C6	/* UIC Masked Status                          */
+#define DCRN_UICVR	0x0C7	/* UIC Vector                                 */
+#define DCRN_UICVCR	0x0C8	/* UIC Vector Configuration                   */
+#define   UIC_U0	0x80000000  /* UART0                                  */
+#define   UIC_U1	0x40000000  /* UART1                                  */
+#define   UIC_IIC	0x20000000  /* IIC                                    */
+#define   UIC_EM	0x10000000  /* External Master                        */
+#define   UIC_PCI	0x08000000  /* PCI                                    */
+#define   UIC_D0	0x04000000  /* DMA Channel 0                          */
+#define   UIC_D1	0x02000000  /* DMA Channel 1                          */
+#define   UIC_D2	0x01000000  /* DMA Channel 2                          */
+#define   UIC_D3	0x00800000  /* DMA Channel 3                          */
+#define   UIC_EW	0x00400000  /* Ethernet Wake-up                       */
+#define   UIC_MS	0x00200000  /* MAL SERR                               */
+#define   UIC_MTE	0x00100000  /* MAL TX EOB                             */
+#define   UIC_MRE	0x00080000  /* MAL RX EOB                             */
+#define   UIC_MTD	0x00040000  /* MAL TX DE                              */
+#define   UIC_MRD	0x00020000  /* MAL RX DE                              */
+#define   UIC_E		0x00010000  /* Ethernet                               */
+#define   UIC_EPS	0x00008000  /* External PCI SERR                      */
+#define   UIC_EC	0x00004000  /* ECC Correctable Error                  */
+#define   UIC_PPM	0x00002000  /* PCI Power Management                   */
+/*
+**			0x00001000  reserved
+**			0x00000800  reserved
+**			0x00000400  reserved
+**			0x00000200  reserved
+**			0x00000100  reserved
+**			0x00000080  reserved
+*/
+#define   UIC_EIR0	0x00000040  /* External IRQ 0                         */
+#define   UIC_EIR1	0x00000020  /* External IRQ 0                         */
+#define   UIC_EIR2	0x00000010  /* External IRQ 0                         */
+#define   UIC_EIR3	0x00000008  /* External IRQ 0                         */
+#define   UIC_EIR4	0x00000004  /* External IRQ 0                         */
+#define   UIC_EIR5	0x00000002  /* External IRQ 0                         */
+#define   UIC_EIR6	0x00000001  /* External IRQ 0                         */
+
+#endif /* __PPC4XX_H__ */
+#endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/ppc4xx_serial.h linux/include/asm-ppc/ppc4xx_serial.h
--- linux-2.4.5-pre2/include/asm-ppc/ppc4xx_serial.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/ppc4xx_serial.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,101 @@
+/*
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405GP modifications
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *
+ *    Module name: ppc405_serial.h
+ *
+ *    Description:
+ *      Macros, definitions, and data structures specific to the IBM PowerPC
+ *      405 on-chip serial port devices.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASMPPC_PPC4xx_SERIAL_H
+#define __ASMPPC_PPC4xx_SERIAL_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE	64
+#else
+#define RS_TABLE_SIZE	4
+#endif
+
+#define PPC405GP_UART0_INT	0
+#define PPC405GP_UART1_INT	1
+
+/*
+** 405GP UARTs are *not* PCI devices, so need to specify a non-pci memory
+** address and an io_type of SERIAL_IO_MEM.
+*/
+
+#define PPC405GP_UART0_IO_BASE	(u8 *) 0xef600300
+#define PPC405GP_UART1_IO_BASE	(u8 *) 0xef600400
+
+/*
+**  - there is no config option for this
+**  - this name could be more informative
+**  - also see arch/ppc/kernel/ppc405_serial.c
+**
+** #define CONFIG_PPC405GP_INTERNAL_CLOCK
+*/
+#ifdef	CONFIG_PPC405GP_INTERNAL_CLOCK
+#define BASE_BAUD		201600
+#else
+#define BASE_BAUD		691200
+#endif
+
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS	(ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS	(ASYNC_BOOT_AUTOCONF)
+#endif
+
+
+#ifdef CONFIG_STB03XXX
+
+#define UART0_IO_BASE 0x40040000
+#define UART0_INT     20
+
+#define STD_SERIAL_PORT_DFNS \
+    /* ttyS0 */ \
+    { 0, BASE_BAUD, 0, UART0_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    UART0_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },
+
+#elif defined(CONFIG_UART1_DFLT_CONSOLE)
+
+#define STD_SERIAL_PORT_DFNS \
+    /* ttyS1 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART1_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART1_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },        \
+    /* ttyS0 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART0_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART0_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },
+
+#else
+
+#define STD_SERIAL_PORT_DFNS \
+    /* ttyS0 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART0_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART0_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },        \
+    /* ttyS1 */ \
+    { 0, BASE_BAUD, 0, PPC405GP_UART1_INT, STD_COM_FLAGS, 0, 0, 0, 0, 0, 0, 0, \
+    PPC405GP_UART1_IO_BASE, 0, 0, 0, {}, {}, {}, SERIAL_IO_MEM, NULL },
+
+#endif
+
+
+#define SERIAL_PORT_DFNS     \
+	STD_SERIAL_PORT_DFNS \
+	{}
+
+
+
+#endif	/* __ASMPPC_PPC4xx_SERIAL_H */
+#endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h
--- linux-2.4.5-pre2/include/asm-ppc/processor.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/processor.h	Mon Dec  3 22:43:26 2001
@@ -12,6 +12,7 @@
 
 #include <asm/ptrace.h>
 #include <asm/types.h>
+#include <asm/mpc8xx.h>
 
 /* Machine State Register (MSR) Fields */
 
@@ -31,6 +32,7 @@
 #define MSR_ME		(1<<12)		/* Machine Check Enable */
 #define MSR_FE0		(1<<11)		/* Floating Exception mode 0 */
 #define MSR_SE		(1<<10)		/* Single Step */
+#define MSR_DWE		(1<<10)		/* Debug Wait Enable (4xx) */
 #define MSR_BE		(1<<9)		/* Branch Trace */
 #define MSR_DE		(1<<9) 		/* Debug Exception Enable */
 #define MSR_FE1		(1<<8)		/* Floating Exception mode 1 */
@@ -82,6 +84,7 @@
 
 /* Special Purpose Registers (SPRNs)*/
 
+#define	SPRN_CCR0	0x3B3	/* Core Configuration Register (4xx) */
 #define	SPRN_CDBCR	0x3D7	/* Cache Debug Control Register */
 #define	SPRN_CTR	0x009	/* Count Register */
 #define	SPRN_DABR	0x3F5	/* Data Address Breakpoint Register */
@@ -132,6 +135,8 @@
 #define	SPRN_DBCR0	0x3F2	/* Debug Control Register 0 */
 #define	SPRN_DBCR1	0x3BD	/* Debug Control Register 1 */
 #define	SPRN_DBSR	0x3F0	/* Debug Status Register */
+#define   DBSR_IC	    0x80000000	/* Instruction Completion             */
+#define   DBSR_TIE	    0x10000000	/* Trap Instruction debug Event       */
 #define	SPRN_DCCR	0x3FA	/* Data Cache Cacheability Register */
 #define	  DCCR_NOCACHE		0	/* Noncacheable */
 #define	  DCCR_CACHE		1	/* Cacheable */
@@ -141,6 +146,26 @@
 #define	  DCWR_WRITE		1	/* Write-through */
 #define	SPRN_DEAR	0x3D5	/* Data Error Address Register */
 #define	SPRN_DEC	0x016	/* Decrement Register */
+#define	SPRN_DER	0x095	/* Debug Enable Regsiter */
+#define   DER_RSTE	0x40000000	/* Reset Interrupt */
+#define   DER_CHSTPE	0x20000000	/* Check Stop */
+#define   DER_MCIE	0x10000000	/* Machine Check Interrupt */
+#define   DER_EXTIE	0x02000000	/* External Interrupt */
+#define   DER_ALIE	0x01000000	/* Alignment Interrupt */
+#define   DER_PRIE	0x00800000	/* Program Interrupt */
+#define   DER_FPUVIE	0x00400000	/* FP Unavailable Interrupt */
+#define   DER_DECIE	0x00200000	/* Decrementer Interrupt */
+#define   DER_SYSIE	0x00040000	/* System Call Interrupt */
+#define   DER_TRE	0x00020000	/* Trace Interrupt */
+#define   DER_SEIE	0x00004000	/* FP SW Emulation Interrupt */
+#define   DER_ITLBMSE	0x00002000	/* Imp. Spec. Instruction TLB Miss */
+#define   DER_ITLBERE	0x00001000	/* Imp. Spec. Instruction TLB Error */
+#define   DER_DTLBMSE	0x00000800	/* Imp. Spec. Data TLB Miss */
+#define   DER_DTLBERE	0x00000400	/* Imp. Spec. Data TLB Error */
+#define   DER_LBRKE	0x00000008	/* Load/Store Breakpoint Interrupt */
+#define   DER_IBRKE	0x00000004	/* Instruction Breakpoint Interrupt */
+#define   DER_EBRKE	0x00000002	/* External Breakpoint Interrupt */
+#define   DER_DPIE	0x00000001	/* Dev. Port Nonmaskable Request */
 #define	SPRN_DMISS	0x3D0	/* Data TLB Miss Register */
 #define	SPRN_DSISR	0x012	/* Data Storage Interrupt Status Register */
 #define	SPRN_EAR	0x11A	/* External Address Register */
@@ -178,6 +203,7 @@
 #define   HID0_SPD	(1<<9)		/* Speculative disable */
 #define   HID0_SGE	(1<<7)		/* Store Gathering Enable */
 #define	  HID0_SIED	(1<<7)		/* Serial Instr. Execution [Disable] */
+#define	  HID0_DFCA	(1<<6)		/* Data Cache Flush Assist */
 #define   HID0_BTIC	(1<<5)		/* Branch Target Instruction Cache Enable */
 #define   HID0_ABE	(1<<3)		/* Address Broadcast Enable */
 #define	  HID0_BHTE	(1<<2)		/* Branch History Table Enable */
@@ -203,12 +229,35 @@
 #define	SPRN_IMISS	0x3D4	/* Instruction TLB Miss Register */
 #define	SPRN_IMMR	0x27E  	/* Internal Memory Map Register */
 #define	SPRN_L2CR	0x3F9	/* Level 2 Cache Control Regsiter */
-#define   L2CR_PIPE_LATEWR   (0x01800000)   /* late-write SRAM */
-#define   L2CR_L2CTL         (0x00100000)   /* RAM control */
-#define   L2CR_INST_DISABLE  (0x00400000)   /* disable for insn's */
-#define   L2CR_L2I           (0x00200000)   /* global invalidate */
-#define   L2CR_L2E           (0x80000000)   /* enable */
-#define   L2CR_L2WT          (0x00080000)   /* write-through */
+#define L2CR_L2E		0x80000000	/* L2 enable */
+#define L2CR_L2PE		0x40000000	/* L2 parity enable */
+#define	L2CR_L2SIZ_MASK		0x30000000	/* L2 size mask */
+#define L2CR_L2SIZ_256KB	0x10000000	/* L2 size 256KB */
+#define L2CR_L2SIZ_512KB	0x20000000	/* L2 size 512KB */
+#define L2CR_L2SIZ_1MB		0x30000000	/* L2 size 1MB */
+#define L2CR_L2CLK_MASK		0x0e000000	/* L2 clock mask */
+#define L2CR_L2CLK_DISABLED	0x00000000	/* L2 clock disabled */
+#define L2CR_L2CLK_DIV1		0x02000000	/* L2 clock / 1 */
+#define L2CR_L2CLK_DIV1_5	0x04000000	/* L2 clock / 1.5 */
+#define L2CR_L2CLK_DIV2		0x08000000	/* L2 clock / 2 */
+#define L2CR_L2CLK_DIV2_5	0x0a000000	/* L2 clock / 2.5 */
+#define L2CR_L2CLK_DIV3		0x0c000000	/* L2 clock / 3 */
+#define L2CR_L2RAM_MASK		0x01800000	/* L2 RAM type mask */
+#define L2CR_L2RAM_FLOW		0x00000000	/* L2 RAM flow through */
+#define L2CR_L2RAM_PIPE		0x01000000	/* L2 RAM pipelined */
+#define L2CR_L2RAM_PIPE_LW	0x01800000	/* L2 RAM pipelined latewr */
+#define	L2CR_L2DO		0x00400000	/* L2 data only */
+#define L2CR_L2I		0x00200000	/* L2 global invalidate */
+#define L2CR_L2CTL		0x00100000	/* L2 RAM control */
+#define L2CR_L2WT		0x00080000	/* L2 write-through */
+#define L2CR_L2TS		0x00040000	/* L2 test support */
+#define L2CR_L2OH_MASK		0x00030000	/* L2 output hold mask */
+#define L2CR_L2OH_0_5		0x00000000	/* L2 output hold 0.5 ns */
+#define L2CR_L2OH_1_0		0x00010000	/* L2 output hold 1.0 ns */
+#define L2CR_L2SL		0x00008000	/* L2 DLL slow */
+#define L2CR_L2DF		0x00004000	/* L2 differential clock */
+#define L2CR_L2BYP		0x00002000	/* L2 DLL bypass */
+#define L2CR_L2IP		0x00000001	/* L2 GI in progress */
 #define	SPRN_LR		0x008	/* Link Register */
 #define	SPRN_MMCR0	0x3B8	/* Monitor Mode Control Register 0 */
 #define	SPRN_MMCR1	0x3BC	/* Monitor Mode Control Register 1 */
@@ -235,6 +284,10 @@
 #define	SPRN_SPRG1	0x111	/* Special Purpose Register General 1 */
 #define	SPRN_SPRG2	0x112	/* Special Purpose Register General 2 */
 #define	SPRN_SPRG3	0x113	/* Special Purpose Register General 3 */
+#define	SPRN_SPRG4	0x114	/* Special Purpose Register General 4 (4xx) */
+#define	SPRN_SPRG5	0x115	/* Special Purpose Register General 5 (4xx) */
+#define	SPRN_SPRG6	0x116	/* Special Purpose Register General 6 (4xx) */
+#define	SPRN_SPRG7	0x117	/* Special Purpose Register General 7 (4xx) */
 #define	SPRN_SRR0	0x01A	/* Save/Restore Register 0 */
 #define	SPRN_SRR1	0x01B	/* Save/Restore Register 1 */
 #define	SPRN_SRR2	0x3DE	/* Save/Restore Register 2 */
@@ -243,10 +296,6 @@
 #define	SPRN_TBRU	0x10D	/* Time Base Read Upper Register (user, R/O) */
 #define	SPRN_TBWL	0x11C	/* Time Base Lower Register (supervisor, R/W) */
 #define	SPRN_TBWU	0x11D	/* Time Base Upper Register (supervisor, R/W) */
-#define	SPRN_TBHI	0x3DC	/* Time Base High (4xx) */
-#define	SPRN_TBHU	0x3CC	/* Time Base High User-mode (4xx) */
-#define	SPRN_TBLO	0x3DD	/* Time Base Low (4xx) */
-#define	SPRN_TBLU	0x3CD	/* Time Base Low User-mode (4xx) */
 #define	SPRN_TCR	0x3DA	/* Timer Control Register */
 #define	  TCR_WP(x)		(((x)&0x3)<<30)	/* WDT Period */
 #define	    WP_2_17		0		/* 2^17 clocks */
@@ -343,10 +392,18 @@
 #define	SPR1	SPRN_SPRG1
 #define	SPR2	SPRN_SPRG2
 #define	SPR3	SPRN_SPRG3
+#define	SPR4	SPRN_SPRG4	/* Supervisor Private Registers (4xx) */
+#define	SPR5	SPRN_SPRG5
+#define	SPR6	SPRN_SPRG6
+#define	SPR7	SPRN_SPRG7
 #define	SPRG0   SPRN_SPRG0
 #define	SPRG1   SPRN_SPRG1
 #define	SPRG2   SPRN_SPRG2
 #define	SPRG3   SPRN_SPRG3
+#define	SPRG4   SPRN_SPRG4
+#define	SPRG5   SPRN_SPRG5
+#define	SPRG6   SPRN_SPRG6
+#define	SPRG7   SPRN_SPRG7
 #define	SRR0	SPRN_SRR0	/* Save and Restore Register 0 */
 #define	SRR1	SPRN_SRR1	/* Save and Restore Register 1 */
 #define	TBRL	SPRN_TBRL	/* Time Base Read Lower Register */
@@ -359,84 +416,6 @@
 #define	THRM3	SPRN_THRM3	/* Thermal Management Register 3 */
 #define	XER	SPRN_XER
 
-
-/* Device Control Registers */
-
-#define	DCRN_BEAR	0x090	/* Bus Error Address Register */
-#define	DCRN_BESR	0x091	/* Bus Error Syndrome Register */
-#define	  BESR_DSES    	0x80000000	/* Data-Side Error Status */
-#define	  BESR_DMES	0x40000000	/* DMA Error Status */
-#define	  BESR_RWS	0x20000000	/* Read/Write Status */
-#define	  BESR_ETMASK	0x1C000000	/* Error Type */
-#define	    ET_PROT	0
-#define	    ET_PARITY	1
-#define	    ET_NCFG	2
-#define	    ET_BUSERR	4
-#define	    ET_BUSTO	6
-#define	DCRN_DMACC0	0x0C4	/* DMA Chained Count Register 0 */
-#define	DCRN_DMACC1	0x0CC	/* DMA Chained Count Register 1 */
-#define	DCRN_DMACC2	0x0D4	/* DMA Chained Count Register 2 */
-#define	DCRN_DMACC3	0x0DC    /* DMA Chained Count Register 3 */
-#define	DCRN_DMACR0	0x0C0    /* DMA Channel Control Register 0 */
-#define	DCRN_DMACR1	0x0C8    /* DMA Channel Control Register 1 */
-#define	DCRN_DMACR2	0x0D0    /* DMA Channel Control Register 2 */
-#define	DCRN_DMACR3	0x0D8    /* DMA Channel Control Register 3 */
-#define	DCRN_DMACT0	0x0C1    /* DMA Count Register 0 */
-#define	DCRN_DMACT1	0x0C9    /* DMA Count Register 1 */
-#define	DCRN_DMACT2	0x0D1    /* DMA Count Register 2 */
-#define	DCRN_DMACT3	0x0D9    /* DMA Count Register 3 */
-#define	DCRN_DMADA0	0x0C2    /* DMA Destination Address Register 0 */
-#define	DCRN_DMADA1	0x0CA    /* DMA Destination Address Register 1 */
-#define	DCRN_DMADA2	0x0D2    /* DMA Destination Address Register 2 */
-#define	DCRN_DMADA3	0x0DA    /* DMA Destination Address Register 3 */
-#define	DCRN_DMASA0	0x0C3    /* DMA Source Address Register 0 */
-#define	DCRN_DMASA1	0x0CB    /* DMA Source Address Register 1 */
-#define	DCRN_DMASA2	0x0D3    /* DMA Source Address Register 2 */
-#define	DCRN_DMASA3	0x0DB    /* DMA Source Address Register 3 */
-#define	DCRN_DMASR	0x0E0    /* DMA Status Register */
-#define	DCRN_EXIER	0x042    /* External Interrupt Enable Register */
-#define	  EXIER_CIE	0x80000000	/* Critical Interrupt Enable */
-#define	  EXIER_SRIE	0x08000000	/* Serial Port Rx Int. Enable */
-#define	  EXIER_STIE	0x04000000	/* Serial Port Tx Int. Enable */
-#define	  EXIER_JRIE	0x02000000	/* JTAG Serial Port Rx Int. Enable */
-#define	  EXIER_JTIE	0x01000000	/* JTAG Serial Port Tx Int. Enable */
-#define	  EXIER_D0IE	0x00800000	/* DMA Channel 0 Interrupt Enable */
-#define	  EXIER_D1IE	0x00400000	/* DMA Channel 1 Interrupt Enable */
-#define	  EXIER_D2IE	0x00200000	/* DMA Channel 2 Interrupt Enable */
-#define	  EXIER_D3IE	0x00100000	/* DMA Channel 3 Interrupt Enable */
-#define	  EXIER_E0IE	0x00000010	/* External Interrupt 0 Enable */
-#define	  EXIER_E1IE	0x00000008	/* External Interrupt 1 Enable */
-#define	  EXIER_E2IE	0x00000004	/* External Interrupt 2 Enable */
-#define	  EXIER_E3IE	0x00000002	/* External Interrupt 3 Enable */
-#define	  EXIER_E4IE	0x00000001	/* External Interrupt 4 Enable */
-#define	DCRN_EXISR	0x040    /* External Interrupt Status Register */
-#define	DCRN_IOCR	0x0A0    /* Input/Output Configuration Register */
-#define	  IOCR_E0TE	0x80000000
-#define	  IOCR_E0LP	0x40000000
-#define	  IOCR_E1TE	0x20000000
-#define	  IOCR_E1LP	0x10000000
-#define	  IOCR_E2TE	0x08000000
-#define	  IOCR_E2LP	0x04000000
-#define	  IOCR_E3TE	0x02000000
-#define	  IOCR_E3LP	0x01000000
-#define	  IOCR_E4TE	0x00800000
-#define	  IOCR_E4LP	0x00400000
-#define	  IOCR_EDT     	0x00080000
-#define	  IOCR_SOR     	0x00040000
-#define	  IOCR_EDO	0x00008000
-#define	  IOCR_2XC	0x00004000
-#define	  IOCR_ATC	0x00002000
-#define	  IOCR_SPD	0x00001000
-#define	  IOCR_BEM	0x00000800
-#define	  IOCR_PTD	0x00000400
-#define	  IOCR_ARE	0x00000080
-#define	  IOCR_DRC	0x00000020
-#define	  IOCR_RDM(x)	(((x) & 0x3) << 3)
-#define	  IOCR_TCS	0x00000004
-#define	  IOCR_SCS	0x00000002
-#define	  IOCR_SPC	0x00000001
-
-
 /* Processor Version Register */
 
 /* Processor Version Register (PVR) field extraction */
@@ -509,15 +488,15 @@
 #define _MACH_rpxlite	0x00000040	/* RPCG RPX-Lite 8xx board */
 #define _MACH_bseip	0x00000080	/* Bright Star Engineering ip-Engine */
 #define _MACH_unused0	0x00000100	/* Now free to be used */
-#define _MACH_unused1	0x00000200	/* Now free to be used */
+#define _MACH_gemini	0x00000200      /* Synergy Microsystems gemini board */
 #define _MACH_classic	0x00000400	/* RPCG RPX-Classic 8xx board */
 #define _MACH_oak	0x00000800	/* IBM "Oak" 403 eval. board */
 #define _MACH_walnut	0x00001000	/* IBM "Walnut" 405GP eval. board */
 #define _MACH_8260	0x00002000	/* Generic 8260 */
 #define _MACH_tqm860	0x00004000	/* TQM860/L */
 #define _MACH_tqm8xxL	0x00008000	/* TQM8xxL */
-#define _MACH_spd8xxL	0x00010000	/* SPD8xx */
-#define _MACH_ibms8	0x00020000	/* IVMS8 */
+#define _MACH_spd8xx	0x00010000	/* SPD8xx */
+#define _MACH_ivms8	0x00020000	/* IVMS8 */
 
 /* see residual.h for these */
 #define _PREP_Motorola 0x01  /* motorola prep */
@@ -711,6 +690,9 @@
 #define have_of 0
 #elif defined(CONFIG_APUS)
 #define _machine _MACH_apus
+#define have_of 0
+#elif defined(CONFIG_GEMINI)
+#define _machine _MACH_gemini
 #define have_of 0
 #elif defined(CONFIG_8260)
 #define _machine _MACH_8260
diff -urN linux-2.4.5-pre2/include/asm-ppc/prom.h linux/include/asm-ppc/prom.h
--- linux-2.4.5-pre2/include/asm-ppc/prom.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/prom.h	Mon Dec  3 22:43:26 2001
@@ -35,13 +35,6 @@
 	unsigned int size;
 };
 
-struct translation_property {
-	unsigned int virt;
-	unsigned int size;
-	unsigned int phys;
-	unsigned int flags;
-};
-
 struct property {
 	char	*name;
 	int	length;
@@ -64,6 +57,10 @@
 	struct	device_node *sibling;
 	struct	device_node *next;	/* next device of same type */
 	struct	device_node *allnext;	/* next in list of all nodes */
+#if 0 /* Don't change this structure for now or you'll break BootX ! */
+	int	n_addr_cells;
+	int	n_size_cells;
+#endif	
 };
 
 struct prom_args;
@@ -88,6 +85,8 @@
 				   int *lenp);
 extern void prom_add_property(struct device_node* np, struct property* prop);
 extern void prom_get_irq_senses(unsigned char *, int, int);
+extern int prom_n_addr_cells(struct device_node* np);
+extern int prom_n_size_cells(struct device_node* np);
 
 extern void print_properties(struct device_node *node);
 extern int call_rtas(const char *service, int nargs, int nret,
diff -urN linux-2.4.5-pre2/include/asm-ppc/rpxclassic.h linux/include/asm-ppc/rpxclassic.h
--- linux-2.4.5-pre2/include/asm-ppc/rpxclassic.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/rpxclassic.h	Mon Dec  3 22:43:26 2001
@@ -11,6 +11,7 @@
 
 #include <linux/config.h>
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -60,19 +61,37 @@
 #define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)	/* CLLF */
 #define BCSR0_PCMCIA5VOLT	((uint)0x00060000)	/* CLLF */
 
+#define BCSR1_IPB5SEL           ((uint)0x00100000)
+#define BCSR1_PCVCTL4           ((uint)0x00080000)
+#define BCSR1_PCVCTL5           ((uint)0x00040000)
+#define BCSR1_PCVCTL6           ((uint)0x00020000)
+#define BCSR1_PCVCTL7           ((uint)0x00010000)
+
 #define BCSR2_EN232XCVR		((uint)0x00008000)
 #define BCSR2_QSPACESEL		((uint)0x00004000)
 #define BCSR2_FETHLEDMODE	((uint)0x00000800)	/* CLLF */
 
-#if defined(CONFIG_RPXLCD) || defined(CONFIG_HTDMSOUND)
-/* HIOX Expansion card.
-*/
-#include <asm/rpx_hiox.h>
+#if defined(CONFIG_HTDMSOUND)
+#include <asm/rpxhiox.h>
+#endif
+
+/* define IO_BASE for pcmcia, CLLF only */
+#if !defined(CONFIG_PCI)
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+/* for pcmcia sandisk */
+#ifdef CONFIG_IDE
+#define MAX_HWIFS 1
+#define ide_request_irq(irq,hand,flg,dev,id)    request_8xxirq((irq),(hand),(flg),(dev),(id))
+#endif
 #endif
 
 /* Interrupt level assignments.
 */
 #define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+
+#endif /* !__ASSEMBLY__ */
 
 /* We don't use the 8259.
 */
diff -urN linux-2.4.5-pre2/include/asm-ppc/rpxhiox.h linux/include/asm-ppc/rpxhiox.h
--- linux-2.4.5-pre2/include/asm-ppc/rpxhiox.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/rpxhiox.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,42 @@
+
+/*
+ * The Embedded Planet HIOX expansion card definitions.
+ * There were a few different versions of these cards, but only
+ * the one that escaped real production is defined here.
+ *
+ * Copyright (c) 2000 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_RPX_HIOX_DEFS
+#define __MACH_RPX_HIOX_DEFS
+
+#define HIOX_CSR_ADDR		((uint)0xfac00000)
+#define HIOX_CSR_SIZE		((uint)(4 * 1024))
+#define HIOX_CSR0_ADDR		HIOX_CSR_ADDR
+#define HIOX_CSR4_ADDR		((uint)0xfac00004)
+
+#define HIOX_CSR0_DEFAULT	((uint)0x380f3c00)
+#define HIOX_CSR0_ENSCC2	((uint)0x80000000)
+#define HIOX_CSR0_ENSMC2	((uint)0x04000000)
+#define HIOX_CSR0_ENVDOCLK	((uint)0x02000000)
+#define HIOX_CSR0_VDORST_HL	((uint)0x01000000)
+#define HIOX_CSR0_RS232SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SCC3SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SMC1SEL	((uint)0x00008000)
+#define HIOX_CSR0_SCC1SEL	((uint)0x00004000)
+#define HIOX_CSR0_ENTOUCH	((uint)0x00000080)
+#define HIOX_CSR0_PDOWN100	((uint)0x00000060)
+#define HIOX_CSR0_PDOWN10	((uint)0x00000040)
+#define HIOX_CSR0_PDOWN1	((uint)0x00000020)
+#define HIOX_CSR0_TSELSPI	((uint)0x00000010)
+#define HIOX_CSR0_TIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_DEFAULT	((uint)0x00000000)
+#define HIOX_CSR4_ENTIRQ2	((uint)0x20000000)
+#define HIOX_CSR4_ENTIRQ3	((uint)0x10000000)
+#define HIOX_CSR4_ENAUDIO	((uint)0x00000080)
+#define HIOX_CSR4_RSTAUDIO	((uint)0x00000040)	/* 0 == reset */
+#define HIOX_CSR4_AUDCLKHI	((uint)0x00000020)
+#define HIOX_CSR4_AUDSPISEL	((uint)0x00000010)
+#define HIOX_CSR4_AUDIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_AUDCLKSEL	((uint)0x00000007)
+
+#endif
diff -urN linux-2.4.5-pre2/include/asm-ppc/rpxlite.h linux/include/asm-ppc/rpxlite.h
--- linux-2.4.5-pre2/include/asm-ppc/rpxlite.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/rpxlite.h	Mon Dec  3 22:43:26 2001
@@ -9,6 +9,7 @@
 #ifndef __MACH_RPX_DEFS
 #define __MACH_RPX_DEFS
 
+#ifndef __ASSEMBLY__
 /* A Board Information structure that is given to a program when
  * prom starts it up.
  */
@@ -31,8 +32,6 @@
 #define RPX_CSR_SIZE		((uint)(4 * 1024))
 #define IMAP_ADDR		((uint)0xfa200000)
 #define IMAP_SIZE		((uint)(64 * 1024))
-#define HIOX_CSR_ADDR		((uint)0xfac00000)
-#define HIOX_CSR_SIZE		((uint)(4 * 1024))
 #define PCMCIA_MEM_ADDR		((uint)0x04000000)
 #define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
 #define PCMCIA_IO_ADDR		((uint)0x04400000)
@@ -52,10 +51,25 @@
 #define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)
 #define BCSR0_PCMCIA5VOLT	((uint)0x00060000)
 
-/* HIO Expansion card.
-*/
-#define HIOX_CSR_ENAUDIO	((uint)0x00000200)
-#define HIOX_CSR_RSTAUDIO	((uint)0x00000100)	/* 0 == reset */
+#define BCSR1_IPB5SEL          ((uint)0x00100000)
+#define BCSR1_PCVCTL4          ((uint)0x00080000)
+#define BCSR1_PCVCTL5          ((uint)0x00040000)
+#define BCSR1_PCVCTL6          ((uint)0x00020000)
+#define BCSR1_PCVCTL7          ((uint)0x00010000)
+
+#if defined(CONFIG_HTDMSOUND)
+#include <asm/rpxhiox.h>
+#endif
+#endif /* !__ASSEMBLY__ */
+
+/* define IO_BASE for pcmcia */
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+#ifdef CONFIG_IDE
+#define MAX_HWIFS 1
+#define ide_request_irq(irq,hand,flg,dev,id)    request_8xxirq((irq),(hand),(flg),(dev),(id))
+#endif
 
 /* We don't use the 8259.
 */
diff -urN linux-2.4.5-pre2/include/asm-ppc/rwsem.h linux/include/asm-ppc/rwsem.h
--- linux-2.4.5-pre2/include/asm-ppc/rwsem.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-ppc/rwsem.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,134 @@
+/*
+ * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff
+ * in lib/rwsem.c.  Adapted largely from include/asm-i386/rwsem.h
+ * by Paul Mackerras <paulus@samba.org>.
+ */
+
+#ifndef _PPC_RWSEM_H
+#define _PPC_RWSEM_H
+
+#ifdef __KERNEL__
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+#include <asm/system.h>
+
+/*
+ * the semaphore definition
+ */
+struct rw_semaphore {
+	/* XXX this should be able to be an atomic_t  -- paulus */
+	signed long		count;
+#define RWSEM_UNLOCKED_VALUE		0x00000000
+#define RWSEM_ACTIVE_BIAS		0x00000001
+#define RWSEM_ACTIVE_MASK		0x0000ffff
+#define RWSEM_WAITING_BIAS		(-0x00010000)
+#define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
+#define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
+	spinlock_t		wait_lock;
+	struct list_head	wait_list;
+#if RWSEM_DEBUG
+	int			debug;
+#endif
+};
+
+/*
+ * initialisation
+ */
+#if RWSEM_DEBUG
+#define __RWSEM_DEBUG_INIT      , 0
+#else
+#define __RWSEM_DEBUG_INIT	/* */
+#endif
+
+#define __RWSEM_INITIALIZER(name) \
+	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
+	  LIST_HEAD_INIT((name).wait_list) \
+	  __RWSEM_DEBUG_INIT }
+
+#define DECLARE_RWSEM(name)		\
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
+
+extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
+extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
+
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+	sem->count = RWSEM_UNLOCKED_VALUE;
+	spin_lock_init(&sem->wait_lock);
+	INIT_LIST_HEAD(&sem->wait_list);
+#if RWSEM_DEBUG
+	sem->debug = 0;
+#endif
+}
+
+/*
+ * lock for reading
+ */
+static inline void __down_read(struct rw_semaphore *sem)
+{
+	if (atomic_inc_return((atomic_t *)(&sem->count)) >= 0)
+		smp_wmb();
+	else
+		rwsem_down_read_failed(sem);
+}
+
+/*
+ * lock for writing
+ */
+static inline void __down_write(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
+				(atomic_t *)(&sem->count));
+	if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
+		smp_wmb();
+	else
+		rwsem_down_write_failed(sem);
+}
+
+/*
+ * unlock after reading
+ */
+static inline void __up_read(struct rw_semaphore *sem)
+{
+	int tmp;
+
+	smp_wmb();
+	tmp = atomic_dec_return((atomic_t *)(&sem->count));
+	if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * unlock after writing
+ */
+static inline void __up_write(struct rw_semaphore *sem)
+{
+	smp_wmb();
+	if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
+			      (atomic_t *)(&sem->count)) < 0)
+		rwsem_wake(sem);
+}
+
+/*
+ * implement atomic add functionality
+ */
+static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
+{
+	atomic_add(delta, (atomic_t *)(&sem->count));
+}
+
+/*
+ * implement exchange and add functionality
+ */
+static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
+{
+	smp_mb();
+	return atomic_add_return(delta, (atomic_t *)(&sem->count));
+}
+
+#endif /* __KERNEL__ */
+#endif /* _PPC_RWSEM_XADD_H */
diff -urN linux-2.4.5-pre2/include/asm-ppc/semaphore-helper.h linux/include/asm-ppc/semaphore-helper.h
--- linux-2.4.5-pre2/include/asm-ppc/semaphore-helper.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/semaphore-helper.h	Wed Dec 31 16:00:00 1969
@@ -1,109 +0,0 @@
-#ifdef __KERNEL__
-#ifndef _PPC_SEMAPHORE_HELPER_H
-#define _PPC_SEMAPHORE_HELPER_H
-
-/*
- * SMP- and interrupt-safe semaphores..
- *
- * (C) Copyright 1996 Linus Torvalds
- * Adapted for PowerPC by Gary Thomas and Paul Mackerras
- */
-
-#include <asm/atomic.h>
-
-/*
- * These two (wake_one_more and waking_non_zero) _must_ execute
- * atomically wrt each other.
- *
- * This is trivially done with load with reservation and
- * store conditional on the ppc.
- */
-
-static inline void wake_one_more(struct semaphore * sem)
-{
-	atomic_inc(&sem->waking);
-}
-
-static inline int waking_non_zero(struct semaphore *sem)
-{
-	int ret, tmp;
-
-	/* Atomic decrement sem->waking iff it is > 0 */
-	__asm__ __volatile__(
-		"1:	lwarx %1,0,%2\n"	/* tmp = sem->waking */
-		"	cmpwi 0,%1,0\n"		/* test tmp */
-		"	addic %1,%1,-1\n"	/* --tmp */
-		"	ble- 2f\n"		/* exit if tmp was <= 0 */
-		"	stwcx. %1,0,%2\n"	/* update sem->waking */
-		"	bne- 1b\n"		/* try again if update failed*/
-		"	li %0,1\n"		/* ret = 1 */
-		"2:"
-		: "=r" (ret), "=&r" (tmp)
-		: "r" (&sem->waking), "0" (0)
-		: "cr0", "memory");
-
-	return ret;
-}
-/*
- * waking_non_zero_interruptible:
- *	1	got the lock
- *	0	go to sleep
- *	-EINTR	interrupted
- */
-static inline int waking_non_zero_interruptible(struct semaphore *sem,
-						struct task_struct *tsk)
-{
-	int ret, tmp;
-
-	/* Atomic decrement sem->waking iff it is > 0 */
-	__asm__ __volatile__(
-		"1:	lwarx %1,0,%2\n"	/* tmp = sem->waking */
-		"	cmpwi 0,%1,0\n"		/* test tmp */
-		"	addic %1,%1,-1\n"	/* --tmp */
-		"	ble- 2f\n"		/* exit if tmp was <= 0 */
-		"	stwcx. %1,0,%2\n"	/* update sem->waking */
-		"	bne- 1b\n"		/* try again if update failed*/
-		"	li %0,1\n"		/* ret = 1 */
-		"2:"
-		: "=r" (ret), "=&r" (tmp)
-		: "r" (&sem->waking), "0" (0)
-		: "cr0", "memory");
-
-	if (ret == 0 && signal_pending(tsk)) {
-		atomic_inc(&sem->count);
-		ret = -EINTR;
-	}
-	return ret;
-}
-
-/*
- * waking_non_zero_trylock:
- *	1	failed to lock
- *	0	got the lock
- */
-static inline int waking_non_zero_trylock(struct semaphore *sem)
-{
-	int ret, tmp;
-
-	/* Atomic decrement sem->waking iff it is > 0 */
-	__asm__ __volatile__(
-		"1:	lwarx %1,0,%2\n"	/* tmp = sem->waking */
-		"	cmpwi 0,%1,0\n"		/* test tmp */
-		"	addic %1,%1,-1\n"	/* --tmp */
-		"	ble- 2f\n"		/* exit if tmp was <= 0 */
-		"	stwcx. %1,0,%2\n"	/* update sem->waking */
-		"	bne- 1b\n"		/* try again if update failed*/
-		"	li %0,0\n"		/* ret = 0 */
-		"2:"
-		: "=r" (ret), "=&r" (tmp)
-		: "r" (&sem->waking), "0" (1)
-		: "cr0", "memory");
-
-	if (ret)
-		atomic_inc(&sem->count);
-
-	return ret;
-}
-
-#endif /* _PPC_SEMAPHORE_HELPER_H */
-#endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/semaphore.h linux/include/asm-ppc/semaphore.h
--- linux-2.4.5-pre2/include/asm-ppc/semaphore.h	Tue Apr 17 17:19:31 2001
+++ linux/include/asm-ppc/semaphore.h	Mon Dec  3 22:43:26 2001
@@ -7,6 +7,11 @@
  *
  * Stole some rw spinlock-based semaphore stuff from asm-alpha/semaphore.h
  * -- Ani Joshi (ajoshi@unixbox.com)
+ *
+ * Remove spinlock-based RW semaphores; RW semaphore definitions are
+ * now in rwsem.h and we use the the generic lib/rwsem.c implementation.
+ * Rework semaphores to use atomic_dec_if_positive.
+ * -- Paul Mackerras (paulus@samba.org)
  */
 
 #ifdef __KERNEL__
@@ -17,8 +22,12 @@
 #include <linux/rwsem.h>
 
 struct semaphore {
+	/*
+	 * Note that any negative value of count is equivalent to 0,
+	 * but additionally indicates that some process(es) might be
+	 * sleeping on `wait'.
+	 */
 	atomic_t count;
-	atomic_t waking;
 	wait_queue_head_t wait;
 #if WAITQUEUE_DEBUG
 	long __magic;
@@ -32,23 +41,23 @@
 # define __SEM_DEBUG_INIT(name)
 #endif
 
-#define __SEMAPHORE_INITIALIZER(name,count) \
-{ ATOMIC_INIT(count), ATOMIC_INIT(0), __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
-	__SEM_DEBUG_INIT(name) }
+#define __SEMAPHORE_INITIALIZER(name, count) \
+	{ ATOMIC_INIT(count), \
+	  __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	  __SEM_DEBUG_INIT(name) }
 
 #define __MUTEX_INITIALIZER(name) \
-	__SEMAPHORE_INITIALIZER(name,1)
+	__SEMAPHORE_INITIALIZER(name, 1)
 
-#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+#define __DECLARE_SEMAPHORE_GENERIC(name, count) \
 	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
 
-#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
-#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+#define DECLARE_MUTEX(name)		__DECLARE_SEMAPHORE_GENERIC(name, 1)
+#define DECLARE_MUTEX_LOCKED(name)	__DECLARE_SEMAPHORE_GENERIC(name, 0)
 
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
 {
 	atomic_set(&sem->count, val);
-	atomic_set(&sem->waking, 0);
 	init_waitqueue_head(&sem->wait);
 #if WAITQUEUE_DEBUG
 	sem->__magic = (long)&sem->__magic;
@@ -67,46 +76,59 @@
 
 extern void __down(struct semaphore * sem);
 extern int  __down_interruptible(struct semaphore * sem);
-extern int  __down_trylock(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
 extern inline void down(struct semaphore * sem)
 {
-	if (atomic_dec_return(&sem->count) >= 0)
-		wmb();
-	else
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	/*
+	 * Try to get the semaphore, take the slow path if we fail.
+	 */
+	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
+	smp_wmb();
 }
 
 extern inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 
-	if (atomic_dec_return(&sem->count) >= 0)
-		wmb();
-	else
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	if (atomic_dec_return(&sem->count) < 0)
 		ret = __down_interruptible(sem);
+	smp_wmb();
 	return ret;
 }
 
 extern inline int down_trylock(struct semaphore * sem)
 {
-	int ret = 0;
+	int ret;
 
-	if (atomic_dec_return(&sem->count) >= 0)
-		wmb();
-	else
-		ret = __down_trylock(sem);
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	ret = atomic_dec_if_positive(&sem->count) < 0;
+	smp_wmb();
 	return ret;
 }
 
 extern inline void up(struct semaphore * sem)
 {
-	mb();
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	smp_wmb();
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
-}	
-
+}
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.4.5-pre2/include/asm-ppc/serial.h linux/include/asm-ppc/serial.h
--- linux-2.4.5-pre2/include/asm-ppc/serial.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/serial.h	Mon Dec  3 22:43:26 2001
@@ -5,6 +5,12 @@
 #ifdef __KERNEL__
 #include <linux/config.h>
 
+#ifdef CONFIG_GEMINI
+#include <asm/gemini_serial.h>
+#elif defined(CONFIG_4xx)
+#include <asm/ppc4xx_serial.h>
+#else
+
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
@@ -123,4 +129,5 @@
 	HUB6_SERIAL_PORT_DFNS		\
 	MCA_SERIAL_PORT_DFNS
 
+#endif /* !CONFIG_GEMINI and others */
 #endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/smp.h linux/include/asm-ppc/smp.h
--- linux-2.4.5-pre2/include/asm-ppc/smp.h	Mon Jan 22 15:41:15 2001
+++ linux/include/asm-ppc/smp.h	Mon Dec  3 22:43:26 2001
@@ -1,8 +1,11 @@
 /* smp.h: PPC specific SMP stuff.
  *
- * Taken from asm-sparc/smp.h
+ * Original was a copy of sparc smp.h.  Now heavily modified
+ * for PPC.
+ *
+ * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996-2001 Cort Dougan <cort@fsmlabs.com>
  */
-
 #ifdef __KERNEL__
 #ifndef _PPC_SMP_H
 #define _PPC_SMP_H
@@ -21,9 +24,11 @@
 	unsigned long *pte_cache;
 	unsigned long pgtable_cache_sz;
 };
-extern struct cpuinfo_PPC cpu_data[NR_CPUS];
 
+extern struct cpuinfo_PPC cpu_data[NR_CPUS];
+extern unsigned long cpu_online_map;
 extern unsigned long smp_proc_in_lock[NR_CPUS];
+extern volatile unsigned long cpu_callin_map[NR_CPUS];
 
 extern void smp_store_cpu_info(int id);
 extern void smp_send_tlb_invalidate(int);
@@ -37,7 +42,6 @@
 /* 1 to 1 mapping on PPC -- Cort */
 #define cpu_logical_map(cpu) (cpu)
 #define cpu_number_map(x) (x)
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
 
 #define smp_processor_id() (current->processor)
 
diff -urN linux-2.4.5-pre2/include/asm-ppc/system.h linux/include/asm-ppc/system.h
--- linux-2.4.5-pre2/include/asm-ppc/system.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/system.h	Mon Dec  3 22:43:26 2001
@@ -3,7 +3,6 @@
  *
  * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
  */
-#ifdef __KERNEL__
 #ifndef __PPC_SYSTEM_H
 #define __PPC_SYSTEM_H
 
@@ -47,6 +46,7 @@
 #define smp_wmb()	__asm__ __volatile__("": : :"memory")
 #endif /* CONFIG_SMP */
 
+#ifdef __KERNEL__
 extern void xmon_irq(int, void *, struct pt_regs *);
 extern void xmon(struct pt_regs *excp);
 extern void print_backtrace(unsigned long *);
@@ -115,6 +115,8 @@
 #define local_irq_save(flags)		__save_and_cli(flags)
 #define local_irq_restore(flags)	__restore_flags(flags)
 
+#endif /* __KERNEL__ */
+
 #define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
 
 static __inline__ unsigned long
@@ -122,9 +124,9 @@
 {
 	unsigned long prev;
 
-	__asm__ __volatile__ ("
-1:	lwarx	%0,0,%2
-	stwcx.	%3,0,%2
+	__asm__ __volatile__ ("\n\
+1:	lwarx	%0,0,%2 \n\
+	stwcx.	%3,0,%2 \n\
 	bne-	1b"
 	: "=&r" (prev), "=m" (*(volatile unsigned long *)p)
 	: "r" (p), "r" (val), "m" (*(volatile unsigned long *)p)
@@ -171,11 +173,11 @@
 {
 	int prev;
 
-	__asm__ __volatile__ ("
-1:	lwarx	%0,0,%2
-	cmpw	0,%0,%3
-	bne	2f
-	stwcx.	%4,0,%2
+	__asm__ __volatile__ ("\n\
+1:	lwarx	%0,0,%2 \n\
+	cmpw	0,%0,%3 \n\
+	bne	2f \n\
+	stwcx.	%4,0,%2 \n\
 	bne-	1b\n"
 #ifdef CONFIG_SMP
 "	sync\n"
@@ -216,4 +218,3 @@
   })
 
 #endif /* __PPC_SYSTEM_H */
-#endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/time.h linux/include/asm-ppc/time.h
--- linux-2.4.5-pre2/include/asm-ppc/time.h	Sat Mar  3 10:52:14 2001
+++ linux/include/asm-ppc/time.h	Mon Dec  3 22:43:26 2001
@@ -9,6 +9,7 @@
 #ifdef __KERNEL__
 #include <linux/config.h>
 #include <linux/mc146818rtc.h>
+#include <linux/threads.h>
 
 #include <asm/processor.h>
 
@@ -23,7 +24,12 @@
 
 int via_calibrate_decr(void);
 
-/* Accessor functions for the decrementer register. */
+/* Accessor functions for the decrementer register.
+ * The 4xx doesn't even have a decrementer.  I tried to use the
+ * generic timer interrupt code, which seems OK, with the 4xx PIT
+ * in auto-reload mode.  The problem is PIT stops counting when it
+ * hits zero.  If it would wrap, we could use it just like a decrementer.
+ */
 static __inline__ unsigned int get_dec(void)
 {
 #if defined(CONFIG_4xx)
@@ -36,14 +42,12 @@
 static __inline__ void set_dec(unsigned int val)
 {
 #if defined(CONFIG_4xx)
-	mtspr(SPRN_PIT, val);
-#else
-#ifdef CONFIG_8xx_CPU6
+	return;		/* Have to let it auto-reload */
+#elif defined(CONFIG_8xx_CPU6)
 	set_dec_cpu6(val);
 #else
 	mtspr(SPRN_DEC, val);
 #endif
-#endif
 }
 
 /* Accessor functions for the timebase (RTC on 601) registers. */
@@ -59,6 +63,12 @@
 extern __inline__ unsigned long get_tbl(void) {
 	unsigned long tbl;
 	asm volatile("mftb %0" : "=r" (tbl));
+	return tbl;
+}
+
+extern __inline__ unsigned long get_tbu(void) {
+	unsigned long tbl;
+	asm volatile("mftbu %0" : "=r" (tbl));
 	return tbl;
 }
 
diff -urN linux-2.4.5-pre2/include/asm-ppc/uninorth.h linux/include/asm-ppc/uninorth.h
--- linux-2.4.5-pre2/include/asm-ppc/uninorth.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/uninorth.h	Mon Dec  3 22:43:26 2001
@@ -42,13 +42,13 @@
 /* Version of the UniNorth chip */
 #define UNI_N_VERSION			0x0000		/* Known versions: 3,7 and 8 */
  
-/* This register is used to enable/disable various parts */
+/* This register is used to enable/disable various clocks */
 #define UNI_N_CLOCK_CNTL		0x0020
-#define UNI_N_CLOCK_CNTL_PCI		0x00000001	/* guess ? */
-#define UNI_N_CLOCK_CNTL_GMAC		0x00000002
-#define UNI_N_CLOCK_CNTL_FW		0x00000004	/* guess ? */
+#define UNI_N_CLOCK_CNTL_PCI		0x00000001	/* PCI2 clock control */
+#define UNI_N_CLOCK_CNTL_GMAC		0x00000002	/* GMAC clock control */
+#define UNI_N_CLOCK_CNTL_FW		0x00000004	/* FireWire clock control */
 
-/* Power Management control ? (from Darwin) */
+/* Power Management control */
 #define UNI_N_POWER_MGT			0x0030
 #define UNI_N_POWER_MGT_NORMAL		0x00
 #define UNI_N_POWER_MGT_IDLE2		0x01
@@ -79,5 +79,7 @@
  * CPU has started and will enter it's sleep loop with IP=0
  */
 #define UNI_N_HWINIT_STATE_CPU1_FLAG	0x10000000
+
+/* Uninorth 1.5 rev. has additional perf. monitor registers at 0xf00-0xf50 */
 
 #endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-ppc/walnut.h linux/include/asm-ppc/walnut.h
--- linux-2.4.5-pre2/include/asm-ppc/walnut.h	Sat Nov 11 18:23:11 2000
+++ linux/include/asm-ppc/walnut.h	Mon Dec  3 22:43:26 2001
@@ -2,12 +2,21 @@
  *
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
  *
- *    Module name: walnut.h
+ *    Copyright 2000 MontaVista Software Inc.
+ *	PPC405 modifications
+ * 	Author: MontaVista Software, Inc.
+ *         	frank_rowand@mvista.com or source@mvista.com
+ * 	   	debbie_chu@mvista.com
+ *
+ *    Module name: ppc405.h
  *
  *    Description:
- *	Macros, definitions, and data structures specific to the IBM PowerPC
- *      405GP "Walnut" evaluation board. Anything specific to the processor
- *      itself is defined elsewhere.
+ *      Macros, definitions, and data structures specific to the IBM PowerPC
+ *      based boards.
+ *
+ *      This includes:
+ *
+ *         405GP "Walnut" evaluation board
  *
  */
 
@@ -19,12 +28,37 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Walnut" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
 
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Local Ethernet MAC address */
+	unsigned char	 bi_pci_enetaddr[6];	/* PCI Ethernet MAC address */
+	unsigned int	 bi_procfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_plb_busfreq;	/* PLB Bus speed, in Hz */
+	unsigned int	 bi_pci_busfreq;	/* PCI Bus speed, in Hz */
+} bd_t;
 
+/* Memory map for the IBM "Walnut" 405GP evaluation board.
+ * Generic 4xx plus RTC.
+ */
+#define WALNUT_RTC_ADDR		((uint)0xf0001000)
+#define WALNUT_RTC_SIZE		((uint)4*1024)
 
 #ifdef __cplusplus
 }
 #endif
+
+/* Generic 4xx type
+*/
+#define _MACH_4xx (_MACH_walnut)
 
 #endif /* __WALNUT_H__ */
 #endif /* __KERNEL__ */
diff -urN linux-2.4.5-pre2/include/asm-sh/pci.h linux/include/asm-sh/pci.h
--- linux-2.4.5-pre2/include/asm-sh/pci.h	Wed Apr 11 21:24:52 2001
+++ linux/include/asm-sh/pci.h	Mon Dec  3 22:43:26 2001
@@ -160,7 +160,8 @@
 	return 1;
 }
 
-
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
 
 /* These macros should be used after a pci_map_sg call has been done
  * to get bus addresses of each of the SG entries and their lengths.
diff -urN linux-2.4.5-pre2/include/asm-sparc/pci.h linux/include/asm-sparc/pci.h
--- linux-2.4.5-pre2/include/asm-sparc/pci.h	Thu Jun 22 07:17:16 2000
+++ linux/include/asm-sparc/pci.h	Mon Dec  3 22:43:26 2001
@@ -113,6 +113,9 @@
 	return 1;
 }
 
+/* Return the index of the PCI controller for device PDEV. */
+#define pci_controller_num(PDEV)	(0)
+
 #endif /* __KERNEL__ */
 
 #endif /* __SPARC_PCI_H */
diff -urN linux-2.4.5-pre2/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- linux-2.4.5-pre2/include/asm-sparc64/floppy.h	Sun Mar 25 18:14:21 2001
+++ linux/include/asm-sparc64/floppy.h	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.29 2001/03/24 00:07:23 davem Exp $
+/* $Id: floppy.h,v 1.30 2001/05/11 07:05:38 davem Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -173,11 +173,6 @@
 unsigned long pdma_areasize;
 
 /* Common routines to all controller types on the Sparc. */
-static __inline__ void virtual_dma_init(void)
-{
-	/* nothing... */
-}
-
 static void sun_fd_disable_dma(void)
 {
 	doing_pdma = 0;
@@ -231,7 +226,7 @@
 		once = 1;
 
 		error = request_fast_irq(FLOPPY_IRQ, floppy_hardint, 
-					SA_INTERRUPT, "floppy", NULL);
+					 SA_INTERRUPT, "floppy", NULL);
 
 		return ((error == 0) ? 0 : -1);
 	}
@@ -267,6 +262,7 @@
 
 #ifdef CONFIG_PCI
 #include <asm/ebus.h>
+#include <asm/isa.h>
 #include <asm/ns87303.h>
 
 static struct linux_ebus_dma *sun_pci_fd_ebus_dma;
@@ -583,6 +579,83 @@
 }
 #endif
 
+#ifdef CONFIG_PCI
+#undef ISA_FLOPPY_WORKS
+
+#ifdef ISA_FLOPPY_WORKS
+static unsigned long __init isa_floppy_init(void)
+{
+	struct isa_bridge *isa_br;
+	struct isa_device *isa_dev = NULL;
+
+	for_each_isa(isa_br) {
+		for_each_isadev(isa_dev, isa_br) {
+			if (!strcmp(isa_dev->prom_name, "dma")) {
+				struct isa_device *child = isa_dev->child;
+
+				while (child) {
+					if (!strcmp(child->prom_name, "floppy")) {
+						isa_dev = child;
+						goto isa_done;
+					}
+					child = child->next;
+				}
+			}
+		}
+	}
+isa_done:
+	if (!isa_dev)
+		return 0;
+
+	/* We could use DMA on devices behind the ISA bridge, but...
+	 *
+	 * There is a slight problem.  Normally on x86 kit the x86 processor
+	 * delays I/O port instructions when the ISA bus "dma in progress"
+	 * signal is active.  Well, sparc64 systems do not monitor this
+	 * signal thus we would need to block all I/O port accesses in software
+	 * when a dma transfer is active for some device.
+	 */
+
+	sun_fdc = (struct sun_flpy_controller *)isa_dev->resource.start;
+	FLOPPY_IRQ = isa_dev->irq;
+
+	sun_fdops.fd_inb = sun_pci_fd_inb;
+	sun_fdops.fd_outb = sun_pci_fd_outb;
+
+	can_use_virtual_dma = use_virtual_dma = 1;
+	sun_fdops.fd_enable_dma = sun_fd_enable_dma;
+	sun_fdops.fd_disable_dma = sun_fd_disable_dma;
+	sun_fdops.fd_set_dma_mode = sun_fd_set_dma_mode;
+	sun_fdops.fd_set_dma_addr = sun_fd_set_dma_addr;
+	sun_fdops.fd_set_dma_count = sun_fd_set_dma_count;
+	sun_fdops.get_dma_residue = sun_get_dma_residue;
+
+	sun_fdops.fd_enable_irq = sun_fd_enable_irq;
+	sun_fdops.fd_disable_irq = sun_fd_disable_irq;
+	sun_fdops.fd_request_irq = sun_fd_request_irq;
+	sun_fdops.fd_free_irq = sun_fd_free_irq;
+
+	/* Floppy eject is manual.   Actually, could determine this
+	 * via presence of 'manual' property in OBP node.
+	 */
+	sun_fdops.fd_eject = sun_pci_fd_eject;
+
+        fdc_status = (unsigned long) &sun_fdc->status_82077;
+	FLOPPY_MOTOR_MASK = 0xf0;
+
+	allowed_drive_mask = 0;
+	sun_floppy_types[0] = 0;
+	sun_floppy_types[1] = 4;
+
+	sun_pci_broken_drive = 1;
+	sun_fdops.fd_outb = sun_pci_fd_broken_outb;
+
+	return sun_floppy_types[0];
+}
+#endif /* ISA_FLOPPY_WORKS */
+
+#endif
+
 static unsigned long __init sun_floppy_init(void)
 {
 	char state[128];
@@ -615,8 +688,13 @@
 			}
 		}
 	ebus_done:
-		if (!edev)
+		if (!edev) {
+#ifdef ISA_FLOPPY_WORKS
+			return isa_floppy_init();
+#else
 			return 0;
+#endif
+		}
 
 		prom_getproperty(edev->prom_node, "status",
 				 state, sizeof(state));
diff -urN linux-2.4.5-pre2/include/asm-sparc64/isa.h linux/include/asm-sparc64/isa.h
--- linux-2.4.5-pre2/include/asm-sparc64/isa.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-sparc64/isa.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,47 @@
+/* $Id: isa.h,v 1.1 2001/05/11 04:31:55 davem Exp $
+ * isa.h: Sparc64 layer for PCI to ISA bridge devices.
+ *
+ * Copyright (C) 2001 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __SPARC64_ISA_H
+#define __SPARC64_ISA_H
+
+#include <asm/pbm.h>
+#include <asm/oplib.h>
+
+struct isa_device {
+	struct isa_device	*next;
+	struct isa_device	*child;
+	struct isa_bridge	*bus;
+	int			prom_node;
+	char			prom_name[64];
+	char			compatible[64];
+	struct resource		resource;
+	unsigned int		irq;
+};
+
+struct isa_bridge {
+	struct isa_bridge	*next;
+	struct isa_device	*devices;
+	struct pci_pbm_info	*parent;
+	struct pci_dev		*self;
+	int			index;
+	int			prom_node;
+	char			prom_name[64];
+#define linux_prom_isa_ranges linux_prom_ebus_ranges
+	struct linux_prom_isa_ranges	isa_ranges[PROMREG_MAX];
+	int			num_isa_ranges;
+};
+
+extern struct isa_bridge	*isa_chain;
+
+extern void isa_init(void);
+
+#define for_each_isa(bus)						\
+        for((bus) = isa_chain; (bus); (bus) = (bus)->next)
+
+#define for_each_isadev(dev, bus)					\
+        for((dev) = (bus)->devices; (dev); (dev) = (dev)->next)
+
+#endif /* !(__SPARC64_ISA_H) */
diff -urN linux-2.4.5-pre2/include/asm-sparc64/parport.h linux/include/asm-sparc64/parport.h
--- linux-2.4.5-pre2/include/asm-sparc64/parport.h	Sun Mar 25 18:14:21 2001
+++ linux/include/asm-sparc64/parport.h	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/* $Id: parport.h,v 1.10 2001/03/24 00:18:57 davem Exp $
+/* $Id: parport.h,v 1.11 2001/05/11 07:54:24 davem Exp $
  * parport.h: sparc64 specific parport initialization and dma.
  *
  * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
@@ -8,6 +8,7 @@
 #define _ASM_SPARC64_PARPORT_H 1
 
 #include <asm/ebus.h>
+#include <asm/isa.h>
 #include <asm/ns87303.h>
 
 #define PARPORT_PC_MAX_PORTS	PARPORT_MAX
@@ -118,6 +119,43 @@
 	return 0;
 }
 
+static int parport_isa_probe(int count)
+{
+	struct isa_bridge *isa_br;
+	struct isa_device *isa_dev;
+
+	for_each_isa(isa_br) {
+		for_each_isadev(isa_dev, isa_br) {
+			struct isa_device *child;
+			unsigned long base;
+
+			if (strcmp(isa_dev->prom_name, "dma"))
+				continue;
+
+			child = isa_dev->child;
+			while (child) {
+				if (!strcmp(child->prom_name, "parallel"))
+					break;
+				child = child->next;
+			}
+			if (!child)
+				continue;
+
+			base = child->resource.start;
+
+			/* No DMA, see commentary in
+			 * asm-sparc64/floppy.h:isa_floppy_init()
+			 */
+			if (parport_pc_probe_port(base, base + 0x400,
+						  child->irq, PARPORT_DMA_NOFIFO,
+						  child->bus->self))
+				count++;
+		}
+	}
+
+	return count;
+}
+
 static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
 {
 	struct linux_ebus *ebus;
@@ -159,6 +197,8 @@
 			}
 		}
 	}
+
+	count = parport_isa_probe(count);
 
 	return count;
 }
diff -urN linux-2.4.5-pre2/include/asm-sparc64/pbm.h linux/include/asm-sparc64/pbm.h
--- linux-2.4.5-pre2/include/asm-sparc64/pbm.h	Tue Mar  6 22:44:16 2001
+++ linux/include/asm-sparc64/pbm.h	Mon Dec  3 22:43:26 2001
@@ -1,4 +1,4 @@
-/* $Id: pbm.h,v 1.25 2001/02/28 03:28:55 davem Exp $
+/* $Id: pbm.h,v 1.26 2001/05/15 08:54:30 davem Exp $
  * pbm.h: UltraSparc PCI controller software state.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -177,6 +177,9 @@
 	 * error logging purposes.
 	 */
 	int				index;
+
+	/* Do the PBMs both exist in the same PCI domain? */
+	int				pbms_same_domain;
 
 	/* The PCI bus modules controlled by us. */
 	struct pci_pbm_info		pbm_A;
diff -urN linux-2.4.5-pre2/include/asm-sparc64/pci.h linux/include/asm-sparc64/pci.h
--- linux-2.4.5-pre2/include/asm-sparc64/pci.h	Thu Jun 22 07:17:16 2000
+++ linux/include/asm-sparc64/pci.h	Mon Dec  3 22:43:26 2001
@@ -3,6 +3,9 @@
 
 #ifdef __KERNEL__
 
+#include <linux/fs.h>
+#include <linux/mm.h>
+
 /* Can be used to override the logic in pci_scan_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
  * or architectures with incomplete PCI setup by the loader.
@@ -109,6 +112,20 @@
  * you would pass 0x00ffffff as the mask to this function.
  */
 extern int pci_dma_supported(struct pci_dev *hwdev, dma_addr_t mask);
+
+/* Return the index of the PCI controller for device PDEV. */
+
+extern int pci_controller_num(struct pci_dev *pdev);
+
+/* Platform support for /proc/bus/pci/X/Y mmap()s. */
+
+#define HAVE_PCI_MMAP
+#define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+#define get_pci_unmapped_area get_fb_unmapped_area
+
+extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			       enum pci_mmap_state mmap_state,
+			       int write_combine);
 
 #endif /* __KERNEL__ */
 
diff -urN linux-2.4.5-pre2/include/linux/fs.h linux/include/linux/fs.h
--- linux-2.4.5-pre2/include/linux/fs.h	Mon Dec  3 22:43:16 2001
+++ linux/include/linux/fs.h	Mon Dec  3 22:43:26 2001
@@ -652,7 +652,6 @@
 	kdev_t			s_dev;
 	unsigned long		s_blocksize;
 	unsigned char		s_blocksize_bits;
-	unsigned char		s_lock;
 	unsigned char		s_dirt;
 	unsigned long long	s_maxbytes;	/* Max file size */
 	struct file_system_type	*s_type;
@@ -662,7 +661,7 @@
 	unsigned long		s_magic;
 	struct dentry		*s_root;
 	struct rw_semaphore	s_umount;
-	wait_queue_head_t	s_wait;
+	struct semaphore	s_lock;
 
 	struct list_head	s_dirty;	/* dirty inodes */
 	struct list_head	s_locked_inodes;/* inodes being synced */
@@ -1279,6 +1278,7 @@
 int generic_commit_write(struct file *, struct page *, unsigned, unsigned);
 int block_truncate_page(struct address_space *, loff_t, get_block_t *);
 
+extern int waitfor_one_page(struct page*);
 extern int generic_file_mmap(struct file *, struct vm_area_struct *);
 extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size);
 extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *);
diff -urN linux-2.4.5-pre2/include/linux/inetdevice.h linux/include/linux/inetdevice.h
--- linux-2.4.5-pre2/include/linux/inetdevice.h	Mon Aug 23 10:01:02 1999
+++ linux/include/linux/inetdevice.h	Mon Dec  3 22:43:26 2001
@@ -17,6 +17,7 @@
 	int	forwarding;
 	int	mc_forwarding;
 	int	tag;
+	int     arp_filter;
 	void	*sysctl;
 };
 
@@ -53,6 +54,8 @@
 	  (ipv4_devconf.accept_redirects && (in_dev)->cnf.accept_redirects)) \
 	 || (!IN_DEV_FORWARD(in_dev) && \
 	  (ipv4_devconf.accept_redirects || (in_dev)->cnf.accept_redirects)))
+
+#define IN_DEV_ARPFILTER(in_dev)	(ipv4_devconf.arp_filter || (in_dev)->cnf.arp_filter)
 
 struct in_ifaddr
 {
diff -urN linux-2.4.5-pre2/include/linux/locks.h linux/include/linux/locks.h
--- linux-2.4.5-pre2/include/linux/locks.h	Fri Apr 27 15:49:14 2001
+++ linux/include/linux/locks.h	Mon Dec  3 22:43:26 2001
@@ -39,30 +39,15 @@
  * a super-block (although even this isn't done right now.
  * nfs may need it).
  */
-extern void __wait_on_super(struct super_block *);
-
-extern inline void wait_on_super(struct super_block * sb)
-{
-	if (sb->s_lock)
-		__wait_on_super(sb);
-}
 
 extern inline void lock_super(struct super_block * sb)
 {
-	if (sb->s_lock)
-		__wait_on_super(sb);
-	sb->s_lock = 1;
+	down(&sb->s_lock);
 }
 
 extern inline void unlock_super(struct super_block * sb)
 {
-	sb->s_lock = 0;
-	/*
-	 * No need of any barrier, we're protected by
-	 * the big kernel lock here... unfortunately :)
-	 */
-	if (waitqueue_active(&sb->s_wait))
-		wake_up(&sb->s_wait);
+	up(&sb->s_lock);
 }
 
 #endif /* _LINUX_LOCKS_H */
diff -urN linux-2.4.5-pre2/include/linux/mii.h linux/include/linux/mii.h
--- linux-2.4.5-pre2/include/linux/mii.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/mii.h	Mon Dec  3 22:43:26 2001
@@ -0,0 +1,181 @@
+/*
+ * linux/mii.h: definitions for MII-compatible transceivers
+ * Originally drivers/net/sunhme.h.
+ *
+ * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
+ */
+
+#ifndef __LINUX_MII_H__
+#define __LINUX_MII_H__
+
+/* Inside the Happy Meal transceiver is the physical layer, they use an
+ * implementations for National Semiconductor, part number DP83840VCE.
+ * You can retrieve the data sheets and programming docs for this beast
+ * from http://www.national.com/
+ *
+ * The DP83840 is capable of both 10 and 100Mbps ethernet, in both
+ * half and full duplex mode.  It also supports auto negotiation.
+ *
+ * But.... THIS THING IS A PAIN IN THE ASS TO PROGRAM!
+ * Debugging eeprom burnt code is more fun than programming this chip!
+ */
+
+/* First, the MII register numbers (actually DP83840 register numbers). */
+#define MII_BMCR            0x00        /* Basic mode control register */
+#define MII_BMSR            0x01        /* Basic mode status register  */
+#define MII_PHYSID1         0x02        /* PHYS ID 1                   */
+#define MII_PHYSID2         0x03        /* PHYS ID 2                   */
+#define MII_ADVERTISE       0x04        /* Advertisement control reg   */
+#define MII_LPA             0x05        /* Link partner ability reg    */
+#define MII_EXPANSION       0x06        /* Expansion register          */
+#define MII_DCOUNTER        0x12        /* Disconnect counter          */
+#define MII_FCSCOUNTER      0x13        /* False carrier counter       */
+#define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
+#define MII_RERRCOUNTER     0x15        /* Receive error counter       */
+#define MII_SREVISION       0x16        /* Silicon revision            */
+#define MII_CSCONFIG        0x17        /* CS configuration            */
+#define MII_LBRERROR        0x18        /* Lpback, rx, bypass error    */
+#define MII_PHYADDR         0x19        /* PHY address                 */
+#define MII_RESERVED        0x1a        /* Unused...                   */
+#define MII_TPISTATUS       0x1b        /* TPI status for 10mbps       */
+#define MII_NCONFIG         0x1c        /* Network interface config    */
+
+/* Basic mode control register. */
+#define BMCR_RESV               0x007f  /* Unused...                   */
+#define BMCR_CTST               0x0080  /* Collision test              */
+#define BMCR_FULLDPLX           0x0100  /* Full duplex                 */
+#define BMCR_ANRESTART          0x0200  /* Auto negotiation restart    */
+#define BMCR_ISOLATE            0x0400  /* Disconnect DP83840 from MII */
+#define BMCR_PDOWN              0x0800  /* Powerdown the DP83840       */
+#define BMCR_ANENABLE           0x1000  /* Enable auto negotiation     */
+#define BMCR_SPEED100           0x2000  /* Select 100Mbps              */
+#define BMCR_LOOPBACK           0x4000  /* TXD loopback bits           */
+#define BMCR_RESET              0x8000  /* Reset the DP83840           */
+
+/* Basic mode status register. */
+#define BMSR_ERCAP              0x0001  /* Ext-reg capability          */
+#define BMSR_JCD                0x0002  /* Jabber detected             */
+#define BMSR_LSTATUS            0x0004  /* Link status                 */
+#define BMSR_ANEGCAPABLE        0x0008  /* Able to do auto-negotiation */
+#define BMSR_RFAULT             0x0010  /* Remote fault detected       */
+#define BMSR_ANEGCOMPLETE       0x0020  /* Auto-negotiation complete   */
+#define BMSR_RESV               0x07c0  /* Unused...                   */
+#define BMSR_10HALF             0x0800  /* Can do 10mbps, half-duplex  */
+#define BMSR_10FULL             0x1000  /* Can do 10mbps, full-duplex  */
+#define BMSR_100HALF            0x2000  /* Can do 100mbps, half-duplex */
+#define BMSR_100FULL            0x4000  /* Can do 100mbps, full-duplex */
+#define BMSR_100BASE4           0x8000  /* Can do 100mbps, 4k packets  */
+
+/* Advertisement control register. */
+#define ADVERTISE_SLCT          0x001f  /* Selector bits               */
+#define ADVERTISE_CSMA          0x0001  /* Only selector supported     */
+#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
+#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
+#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
+#define ADVERTISE_100BASE4      0x0200  /* Try for 100mbps 4k packets  */
+#define ADVERTISE_RESV          0x1c00  /* Unused...                   */
+#define ADVERTISE_RFAULT        0x2000  /* Say we can detect faults    */
+#define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
+#define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
+
+#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
+                       ADVERTISE_100HALF | ADVERTISE_100FULL)
+
+/* Link partner ability register. */
+#define LPA_SLCT                0x001f  /* Same as advertise selector  */
+#define LPA_10HALF              0x0020  /* Can do 10mbps half-duplex   */
+#define LPA_10FULL              0x0040  /* Can do 10mbps full-duplex   */
+#define LPA_100HALF             0x0080  /* Can do 100mbps half-duplex  */
+#define LPA_100FULL             0x0100  /* Can do 100mbps full-duplex  */
+#define LPA_100BASE4            0x0200  /* Can do 100mbps 4k packets   */
+#define LPA_RESV                0x1c00  /* Unused...                   */
+#define LPA_RFAULT              0x2000  /* Link partner faulted        */
+#define LPA_LPACK               0x4000  /* Link partner acked us       */
+#define LPA_NPAGE               0x8000  /* Next page bit               */
+
+#define LPA_DUPLEX		(LPA_10FULL | LPA_100FULL)
+#define LPA_100			(LPA_100FULL | LPA_100HALF | LPA_100BASE4)
+
+/* Expansion register for auto-negotiation. */
+#define EXPANSION_NWAY          0x0001  /* Can do N-way auto-nego      */
+#define EXPANSION_LCWP          0x0002  /* Got new RX page code word   */
+#define EXPANSION_ENABLENPAGE   0x0004  /* This enables npage words    */
+#define EXPANSION_NPCAPABLE     0x0008  /* Link partner supports npage */
+#define EXPANSION_MFAULTS       0x0010  /* Multiple faults detected    */
+#define EXPANSION_RESV          0xffe0  /* Unused...                   */
+
+/* N-way test register. */
+#define NWAYTEST_RESV1          0x00ff  /* Unused...                   */
+#define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
+#define NWAYTEST_RESV2          0xfe00  /* Unused...                   */
+
+/* The Carrier Sense config register. */
+#define CSCONFIG_RESV1          0x0001  /* Unused...                   */
+#define CSCONFIG_LED4           0x0002  /* Pin for full-dplx LED4      */
+#define CSCONFIG_LED1           0x0004  /* Pin for conn-status LED1    */
+#define CSCONFIG_RESV2          0x0008  /* Unused...                   */
+#define CSCONFIG_TCVDISAB       0x0010  /* Turns off the transceiver   */
+#define CSCONFIG_DFBYPASS       0x0020  /* Bypass disconnect function  */
+#define CSCONFIG_GLFORCE        0x0040  /* Good link force for 100mbps */
+#define CSCONFIG_CLKTRISTATE    0x0080  /* Tristate 25m clock          */
+#define CSCONFIG_RESV3          0x0700  /* Unused...                   */
+#define CSCONFIG_ENCODE         0x0800  /* 1=MLT-3, 0=binary           */
+#define CSCONFIG_RENABLE        0x1000  /* Repeater mode enable        */
+#define CSCONFIG_TCDISABLE      0x2000  /* Disable timeout counter     */
+#define CSCONFIG_RESV4          0x4000  /* Unused...                   */
+#define CSCONFIG_NDISABLE       0x8000  /* Disable NRZI                */
+
+/**
+ * mii_nway_result
+ * @negotiated: value of MII ANAR and'd with ANLPAR
+ *
+ * Given a set of MII abilities, check each bit and returns the
+ * currently supported media, in the priority order defined by
+ * IEEE 802.3u.  We use LPA_xxx constants but note this is not the
+ * value of LPA solely, as described above.
+ *
+ * The one exception to IEEE 802.3u is that 100baseT4 is placed
+ * between 100T-full and 100T-half.  If your phy does not support
+ * 100T4 this is fine.  If your phy places 100T4 elsewhere in the
+ * priority order, you will need to roll your own function.
+ */
+static inline unsigned int mii_nway_result (unsigned int negotiated)
+{
+	unsigned int ret;
+
+	if (negotiated & LPA_100FULL)
+		ret = LPA_100FULL;
+	else if (negotiated & LPA_100BASE4)
+		ret = LPA_100BASE4;
+	else if (negotiated & LPA_100HALF)
+		ret = LPA_100HALF;
+	else if (negotiated & LPA_10FULL)
+		ret = LPA_10FULL;
+	else
+		ret = LPA_10HALF;
+
+	return ret;
+}
+
+/**
+ * mii_duplex
+ * @duplex_lock: Non-zero if duplex is locked at full
+ * @negotiated: value of MII ANAR and'd with ANLPAR
+ *
+ * A small helper function for a common case.  Returns one
+ * if the media is operating or locked at full duplex, and
+ * returns zero otherwise.
+ */
+static inline unsigned int mii_duplex (unsigned int duplex_lock,
+				       unsigned int negotiated)
+{
+	if (duplex_lock)
+		return 1;
+	if (mii_nway_result(negotiated) & LPA_DUPLEX)
+		return 1;
+	return 0;
+}
+
+
+#endif /* __LINUX_MII_H__ */
diff -urN linux-2.4.5-pre2/include/linux/nfsd/nfsfh.h linux/include/linux/nfsd/nfsfh.h
--- linux-2.4.5-pre2/include/linux/nfsd/nfsfh.h	Fri Apr 27 15:48:33 2001
+++ linux/include/linux/nfsd/nfsfh.h	Mon Dec  3 22:43:26 2001
@@ -31,7 +31,7 @@
  * ino/dev of the exported inode.
  */
 struct nfs_fhbase_old {
-	struct dentry *	fb_dentry;	/* dentry cookie - always 0xfeebbaca */
+	__u32		fb_dcookie;	/* dentry cookie - always 0xfeebbaca */
 	__u32		fb_ino;		/* our inode number */
 	__u32		fb_dirino;	/* dir inode number, 0 for directories */
 	__u32		fb_dev;		/* our device */
@@ -101,7 +101,7 @@
 	} fh_base;
 };
 
-#define ofh_dcookie		fh_base.fh_old.fb_dentry
+#define ofh_dcookie		fh_base.fh_old.fb_dcookie
 #define ofh_ino			fh_base.fh_old.fb_ino
 #define ofh_dirino		fh_base.fh_old.fb_dirino
 #define ofh_dev			fh_base.fh_old.fb_dev
diff -urN linux-2.4.5-pre2/include/linux/pci.h linux/include/linux/pci.h
--- linux-2.4.5-pre2/include/linux/pci.h	Fri Apr 27 15:49:27 2001
+++ linux/include/linux/pci.h	Mon Dec  3 22:43:26 2001
@@ -279,6 +279,13 @@
 #define PCI_SLOT(devfn)		(((devfn) >> 3) & 0x1f)
 #define PCI_FUNC(devfn)		((devfn) & 0x07)
 
+/* Ioctls for /proc/bus/pci/X/Y nodes. */
+#define PCIIOC_BASE		('P' << 24 | 'C' << 16 | 'I' << 8)
+#define PCIIOC_CONTROLLER	(PCIIOC_BASE | 0x00)	/* Get controller for PCI device. */
+#define PCIIOC_MMAP_IS_IO	(PCIIOC_BASE | 0x01)	/* Set mmap state to I/O space. */
+#define PCIIOC_MMAP_IS_MEM	(PCIIOC_BASE | 0x02)	/* Set mmap state to MEM space. */
+#define PCIIOC_WRITE_COMBINE	(PCIIOC_BASE | 0x03)	/* Enable/disable write-combining. */
+
 #ifdef __KERNEL__
 
 #include <linux/types.h>
@@ -286,6 +293,12 @@
 #include <linux/ioport.h>
 #include <linux/list.h>
 #include <linux/errno.h>
+
+/* File state for mmap()s on /proc/bus/pci/X/Y */
+enum pci_mmap_state {
+	pci_mmap_io,
+	pci_mmap_mem
+};
 
 /* This defines the direction arg to the DMA mapping routines. */
 #define PCI_DMA_BIDIRECTIONAL	0
diff -urN linux-2.4.5-pre2/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- linux-2.4.5-pre2/include/linux/pci_ids.h	Wed Apr 18 14:40:06 2001
+++ linux/include/linux/pci_ids.h	Mon Dec  3 22:43:26 2001
@@ -978,6 +978,10 @@
 #define PCI_VENDOR_ID_MUTECH		0x1159
 #define PCI_DEVICE_ID_MUTECH_MV1000	0x0001
 
+#define PCI_VENDOR_ID_XIRCOM		0x115d
+#define PCI_DEVICE_ID_XIRCOM_X3201_ETH	0x0003
+#define PCI_DEVICE_ID_XIRCOM_X3201_MDM	0x0103
+
 #define PCI_VENDOR_ID_RENDITION		0x1163
 #define PCI_DEVICE_ID_RENDITION_VERITE	0x0001
 #define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000
diff -urN linux-2.4.5-pre2/include/linux/raid/md.h linux/include/linux/raid/md.h
--- linux-2.4.5-pre2/include/linux/raid/md.h	Fri Apr 27 15:49:20 2001
+++ linux/include/linux/raid/md.h	Mon Dec  3 22:43:26 2001
@@ -80,7 +80,7 @@
 extern struct gendisk * find_gendisk (kdev_t dev);
 extern int md_notify_reboot(struct notifier_block *this,
 					unsigned long code, void *x);
-extern int md_error (kdev_t mddev, kdev_t rdev);
+extern int md_error (mddev_t *mddev, kdev_t rdev);
 extern int md_run_setup(void);
 
 extern void md_print_devices (void);
diff -urN linux-2.4.5-pre2/include/linux/raid/md_k.h linux/include/linux/raid/md_k.h
--- linux-2.4.5-pre2/include/linux/raid/md_k.h	Fri Dec 29 14:07:24 2000
+++ linux/include/linux/raid/md_k.h	Mon Dec  3 22:43:26 2001
@@ -25,7 +25,7 @@
 #define HSM               6UL
 #define MAX_PERSONALITY   7UL
 
-extern inline int pers_to_level (int pers)
+static inline int pers_to_level (int pers)
 {
 	switch (pers) {
 		case HSM:		return -3;
@@ -72,7 +72,7 @@
 
 extern dev_mapping_t mddev_map [MAX_MD_DEVS];
 
-extern inline mddev_t * kdev_to_mddev (kdev_t dev)
+static inline mddev_t * kdev_to_mddev (kdev_t dev)
 {
 	if (MAJOR(dev) != MD_MAJOR)
 		BUG();
@@ -90,62 +90,62 @@
  */
 #define MD_READAHEAD	MAX_READAHEAD
 
-extern inline int disk_faulty(mdp_disk_t * d)
+static inline int disk_faulty(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_FAULTY);
 }
 
-extern inline int disk_active(mdp_disk_t * d)
+static inline int disk_active(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_ACTIVE);
 }
 
-extern inline int disk_sync(mdp_disk_t * d)
+static inline int disk_sync(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_SYNC);
 }
 
-extern inline int disk_spare(mdp_disk_t * d)
+static inline int disk_spare(mdp_disk_t * d)
 {
 	return !disk_sync(d) && !disk_active(d) && !disk_faulty(d);
 }
 
-extern inline int disk_removed(mdp_disk_t * d)
+static inline int disk_removed(mdp_disk_t * d)
 {
 	return d->state & (1 << MD_DISK_REMOVED);
 }
 
-extern inline void mark_disk_faulty(mdp_disk_t * d)
+static inline void mark_disk_faulty(mdp_disk_t * d)
 {
 	d->state |= (1 << MD_DISK_FAULTY);
 }
 
-extern inline void mark_disk_active(mdp_disk_t * d)
+static inline void mark_disk_active(mdp_disk_t * d)
 {
 	d->state |= (1 << MD_DISK_ACTIVE);
 }
 
-extern inline void mark_disk_sync(mdp_disk_t * d)
+static inline void mark_disk_sync(mdp_disk_t * d)
 {
 	d->state |= (1 << MD_DISK_SYNC);
 }
 
-extern inline void mark_disk_spare(mdp_disk_t * d)
+static inline void mark_disk_spare(mdp_disk_t * d)
 {
 	d->state = 0;
 }
 
-extern inline void mark_disk_removed(mdp_disk_t * d)
+static inline void mark_disk_removed(mdp_disk_t * d)
 {
 	d->state = (1 << MD_DISK_FAULTY) | (1 << MD_DISK_REMOVED);
 }
 
-extern inline void mark_disk_inactive(mdp_disk_t * d)
+static inline void mark_disk_inactive(mdp_disk_t * d)
 {
 	d->state &= ~(1 << MD_DISK_ACTIVE);
 }
 
-extern inline void mark_disk_nonsync(mdp_disk_t * d)
+static inline void mark_disk_nonsync(mdp_disk_t * d)
 {
 	d->state &= ~(1 << MD_DISK_SYNC);
 }
@@ -245,12 +245,12 @@
  * number. This will have to change to dynamic allocation
  * once we start supporting partitioning of md devices.
  */
-extern inline int mdidx (mddev_t * mddev)
+static inline int mdidx (mddev_t * mddev)
 {
 	return mddev->__minor;
 }
 
-extern inline kdev_t mddev_to_kdev(mddev_t * mddev)
+static inline kdev_t mddev_to_kdev(mddev_t * mddev)
 {
 	return MKDEV(MD_MAJOR, mdidx(mddev));
 }
@@ -304,12 +304,12 @@
 			tmp = tmp->next, tmp->prev != &all_mddevs	\
 		; )
 
-extern inline int lock_mddev (mddev_t * mddev)
+static inline int lock_mddev (mddev_t * mddev)
 {
 	return down_interruptible(&mddev->reconfig_sem);
 }
 
-extern inline void unlock_mddev (mddev_t * mddev)
+static inline void unlock_mddev (mddev_t * mddev)
 {
 	up(&mddev->reconfig_sem);
 }
diff -urN linux-2.4.5-pre2/include/linux/smb.h linux/include/linux/smb.h
--- linux-2.4.5-pre2/include/linux/smb.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/smb.h	Mon Dec  3 22:43:26 2001
@@ -94,21 +94,14 @@
 };
 
 enum smb_conn_state {
-        CONN_VALID,             /* everything's fine */
-        CONN_INVALID,           /* Something went wrong, but did not
-                                   try to reconnect yet. */
-        CONN_RETRIED            /* Tried a reconnection, but was refused */
+	CONN_VALID,		/* everything's fine */
+	CONN_INVALID,		/* Something went wrong, but did not
+				   try to reconnect yet. */
+	CONN_RETRIED,		/* Tried a reconnection, but was refused */
+	CONN_RETRYING		/* Currently trying to reconnect */
 };
 
-/*
- * The readdir cache size controls how many directory entries are cached.
- */
-#define SMB_READDIR_CACHE_SIZE        64
-
 #define SMB_SUPER_MAGIC               0x517B
-
-#define SMB_SERVER(inode)    (&(inode->i_sb->u.smbfs_sb))
-#define SMB_INOP(inode)      (&(inode->u.smbfs_i))
 
 #define SMB_HEADER_LEN   37     /* includes everything up to, but not
                                  * including smb_bcc */
diff -urN linux-2.4.5-pre2/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- linux-2.4.5-pre2/include/linux/smb_fs.h	Fri Feb 16 16:03:24 2001
+++ linux/include/linux/smb_fs.h	Mon Dec  3 22:43:26 2001
@@ -48,8 +48,11 @@
 
 #ifdef DEBUG_SMB_MALLOC
 
+#include <linux/slab.h>
+
 extern int smb_malloced;
 extern int smb_current_vmalloced;
+extern int smb_current_kmalloced;
 
 static inline void *
 smb_vmalloc(unsigned int size)
@@ -66,20 +69,30 @@
         vfree(obj);
 }
 
+static inline void *
+smb_kmalloc(size_t size, int flags)
+{
+	smb_malloced += 1;
+	smb_current_kmalloced += 1;
+	return kmalloc(size, flags);
+}
+
+static inline void
+smb_kfree(void *obj)
+{
+	smb_current_kmalloced -= 1;
+	kfree(obj);
+}
+
 #else /* DEBUG_SMB_MALLOC */
 
-#define smb_kmalloc(s,p) kmalloc(s,p)
-#define smb_kfree_s(o,s) kfree(o)
-#define smb_vmalloc(s)   vmalloc(s)
-#define smb_vfree(o)     vfree(o)
+#define smb_kmalloc(s,p)	kmalloc(s,p)
+#define smb_kfree(o)		kfree(o)
+#define smb_vmalloc(s)		vmalloc(s)
+#define smb_vfree(o)		vfree(o)
 
 #endif /* DEBUG_SMB_MALLOC */
 
-/*
- * Flags for the in-memory inode
- */
-#define SMB_F_LOCALWRITE	0x02	/* file modified locally */
-
 
 /* NT1 protocol capability bits */
 #define SMB_CAP_RAW_MODE         0x0001
@@ -139,7 +152,7 @@
 static inline int
 smb_is_open(struct inode *i)
 {
-	return (i->u.smbfs_i.open == SMB_SERVER(i)->generation);
+	return (i->u.smbfs_i.open == server_from_inode(i)->generation);
 }
 
 
@@ -194,6 +207,7 @@
 int smb_proc_dskattr(struct super_block *, struct statfs *);
 int smb_proc_disconnect(struct smb_sb_info *);
 int smb_proc_trunc(struct smb_sb_info *, __u16, __u32);
+int smb_proc_flush(struct smb_sb_info *, __u16);
 void smb_init_root_dirent(struct smb_sb_info *, struct smb_fattr *);
 
 /* linux/fs/smbfs/sock.c */
diff -urN linux-2.4.5-pre2/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h
--- linux-2.4.5-pre2/include/linux/smb_fs_i.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/smb_fs_i.h	Mon Dec  3 22:43:26 2001
@@ -26,7 +26,6 @@
 	__u16 attr;		/* Attribute fields, DOS value */
 
 	__u16 access;		/* Access mode */
-	__u16 flags;		/* status flags */
 	unsigned long oldmtime;	/* last time refreshed */
 	unsigned long closed;	/* timestamp when closed */
 	unsigned openers;	/* number of fileid users */
diff -urN linux-2.4.5-pre2/include/linux/smb_fs_sb.h linux/include/linux/smb_fs_sb.h
--- linux-2.4.5-pre2/include/linux/smb_fs_sb.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/smb_fs_sb.h	Mon Dec  3 22:43:26 2001
@@ -58,6 +58,19 @@
 		       struct nls_table *, struct nls_table *);
 };
 
+
+static inline void
+smb_lock_server(struct smb_sb_info *server)
+{
+	down(&(server->sem));
+}
+
+static inline void
+smb_unlock_server(struct smb_sb_info *server)
+{
+	up(&(server->sem));
+}
+
 #endif /* __KERNEL__ */
 
 #endif
diff -urN linux-2.4.5-pre2/include/linux/sysctl.h linux/include/linux/sysctl.h
--- linux-2.4.5-pre2/include/linux/sysctl.h	Fri Apr 27 15:48:20 2001
+++ linux/include/linux/sysctl.h	Mon Dec  3 22:43:26 2001
@@ -324,7 +324,8 @@
 	NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9,
 	NET_IPV4_CONF_BOOTP_RELAY=10,
 	NET_IPV4_CONF_LOG_MARTIANS=11,
-	NET_IPV4_CONF_TAG=12
+	NET_IPV4_CONF_TAG=12,
+	NET_IPV4_CONF_ARPFILTER=13
 };
 
 /* /proc/sys/net/ipv6 */
diff -urN linux-2.4.5-pre2/include/net/addrconf.h linux/include/net/addrconf.h
--- linux-2.4.5-pre2/include/net/addrconf.h	Thu Apr 26 22:17:26 2001
+++ linux/include/net/addrconf.h	Mon Dec  3 22:43:26 2001
@@ -158,16 +158,8 @@
  *	compute link-local solicited-node multicast address
  */
 
-static inline void addrconf_addr_solict_mult_old(struct in6_addr *addr,
-						     struct in6_addr *solicited)
-{
-	ipv6_addr_set(solicited,
-		      __constant_htonl(0xFF020000), 0,
-		      __constant_htonl(0x1), addr->s6_addr32[3]);
-}
-
-static inline void addrconf_addr_solict_mult_new(struct in6_addr *addr,
-						     struct in6_addr *solicited)
+static inline void addrconf_addr_solict_mult(struct in6_addr *addr,
+					     struct in6_addr *solicited)
 {
 	ipv6_addr_set(solicited,
 		      __constant_htonl(0xFF020000), 0,
diff -urN linux-2.4.5-pre2/include/net/snmp.h linux/include/net/snmp.h
--- linux-2.4.5-pre2/include/net/snmp.h	Fri Apr 27 15:48:20 2001
+++ linux/include/net/snmp.h	Mon Dec  3 22:43:26 2001
@@ -14,7 +14,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- *		$Id: snmp.h,v 1.17 2000/09/21 01:31:50 davem Exp $
+ *		$Id: snmp.h,v 1.18 2001/05/16 16:45:35 davem Exp $
  *
  */
  
@@ -199,6 +199,7 @@
 	unsigned long	OfoPruned;
 	unsigned long	OutOfWindowIcmps; 
 	unsigned long	LockDroppedIcmps; 
+        unsigned long   ArpFilter;
 	unsigned long	TimeWaited; 
 	unsigned long	TimeWaitRecycled; 
 	unsigned long	TimeWaitKilled; 
diff -urN linux-2.4.5-pre2/kernel/ksyms.c linux/kernel/ksyms.c
--- linux-2.4.5-pre2/kernel/ksyms.c	Mon Dec  3 22:43:16 2001
+++ linux/kernel/ksyms.c	Mon Dec  3 22:43:26 2001
@@ -203,6 +203,7 @@
 EXPORT_SYMBOL(generic_commit_write);
 EXPORT_SYMBOL(block_truncate_page);
 EXPORT_SYMBOL(generic_block_bmap);
+EXPORT_SYMBOL(waitfor_one_page);
 EXPORT_SYMBOL(generic_file_read);
 EXPORT_SYMBOL(do_generic_file_read);
 EXPORT_SYMBOL(generic_file_write);
@@ -478,7 +479,6 @@
 
 /* Added to make file system as module */
 EXPORT_SYMBOL(sys_tz);
-EXPORT_SYMBOL(__wait_on_super);
 EXPORT_SYMBOL(file_fsync);
 EXPORT_SYMBOL(fsync_inode_buffers);
 EXPORT_SYMBOL(clear_inode);
diff -urN linux-2.4.5-pre2/mm/filemap.c linux/mm/filemap.c
--- linux-2.4.5-pre2/mm/filemap.c	Wed Apr 25 16:13:50 2001
+++ linux/mm/filemap.c	Mon Dec  3 22:43:26 2001
@@ -284,6 +284,34 @@
 	spin_unlock(&pagecache_lock);
 }
 
+/*
+ * This function is pretty much like __find_page_nolock(), but it only
+ * requires 2 arguments and doesn't mark the page as touched, making it
+ * ideal for ->writepage() clustering and other places where you don't
+ * want to mark the page referenced.
+ *
+ * The caller needs to hold the pagecache_lock.
+ */
+static struct page * FASTCALL(__find_page_simple(struct address_space *, unsigned long));
+static struct page * __find_page_simple(struct address_space *mapping, unsigned long index)
+{
+	struct page **next = page_hash(mapping, index);;
+
+	for (;;) {
+		struct page *page = *next;
+		if (!page)
+			break;
+		next = &page->next_hash;
+		if (page->mapping != mapping)
+			continue;
+		if (page->index != index)
+			continue;
+		return page;
+	}
+
+	return NULL;
+}
+
 static inline struct page * __find_page_nolock(struct address_space *mapping, unsigned long offset, struct page *page)
 {
 	goto inside;
@@ -298,14 +326,9 @@
 		if (page->index == offset)
 			break;
 	}
-	/*
-	 * Touching the page may move it to the active list.
-	 * If we end up with too few inactive pages, we wake
-	 * up kswapd.
-	 */
-	age_page_up(page);
-	if (inactive_shortage() > inactive_target / 2 && free_shortage())
-			wakeup_kswapd();
+	/* Mark the page referenced, kswapd will find it later. */
+	SetPageReferenced(page);
+
 not_found:
 	return page;
 }
@@ -331,7 +354,7 @@
 	return 0;
 }
 
-static int waitfor_one_page(struct page *page)
+int waitfor_one_page(struct page *page)
 {
 	int error = 0;
 	struct buffer_head *bh, *head = page->buffers;
@@ -762,7 +785,6 @@
 {
 	struct inode *inode = file->f_dentry->d_inode;
 	struct address_space *mapping = inode->i_mapping;
-	struct page **hash;
 	struct page *page;
 	unsigned long start;
 
@@ -783,8 +805,7 @@
 	 */
 	spin_lock(&pagecache_lock);
 	while (--index >= start) {
-		hash = page_hash(mapping, index);
-		page = __find_page_nolock(mapping, index, *hash);
+		page = __find_page_simple(mapping, index);
 		if (!page)
 			break;
 		deactivate_page(page);
diff -urN linux-2.4.5-pre2/mm/slab.c linux/mm/slab.c
--- linux-2.4.5-pre2/mm/slab.c	Sun Mar 25 10:37:48 2001
+++ linux/mm/slab.c	Mon Dec  3 22:43:26 2001
@@ -1958,7 +1958,7 @@
 				unsigned long count, void *data)
 {
 #ifdef CONFIG_SMP
-	char kbuf[MAX_SLABINFO_WRITE], *tmp;
+	char kbuf[MAX_SLABINFO_WRITE+1], *tmp;
 	int limit, batchcount, res;
 	struct list_head *p;
 	
@@ -1966,6 +1966,7 @@
 		return -EINVAL;
 	if (copy_from_user(&kbuf, buffer, count))
 		return -EFAULT;
+	kbuf[MAX_SLABINFO_WRITE] = '\0'; 
 
 	tmp = strchr(kbuf, ' ');
 	if (!tmp)
diff -urN linux-2.4.5-pre2/mm/vmscan.c linux/mm/vmscan.c
--- linux-2.4.5-pre2/mm/vmscan.c	Mon Dec  3 22:43:16 2001
+++ linux/mm/vmscan.c	Mon Dec  3 22:43:26 2001
@@ -24,6 +24,8 @@
 
 #include <asm/pgalloc.h>
 
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+
 /*
  * The swap-out function returns 1 if it successfully
  * scanned all the pages it was asked to (`count').
@@ -228,6 +230,8 @@
 	unsigned long address;
 	struct vm_area_struct* vma;
 
+	if (!count)
+		return 1;
 	/*
 	 * Go through process' page directory.
 	 */
@@ -271,7 +275,12 @@
 static inline int swap_amount(struct mm_struct *mm)
 {
 	int nr = mm->rss >> SWAP_SHIFT;
-	return nr < SWAP_MIN ? SWAP_MIN : nr;
+	if (nr < SWAP_MIN) {
+		nr = SWAP_MIN;
+		if (nr > mm->rss)
+			nr = mm->rss;
+	}
+	return nr;
 }
 
 static int swap_out(unsigned int priority, int gfp_mask)
@@ -285,7 +294,7 @@
 		retval = swap_out_mm(mm, swap_amount(mm));
 
 	/* Then, look at the other mm's */
-	counter = mmlist_nr >> priority;
+	counter = (mmlist_nr << SWAP_SHIFT) >> priority;
 	do {
 		struct list_head *p;
 
@@ -350,7 +359,7 @@
 		}
 
 		/* Page is or was in use?  Move it to the active list. */
-		if (PageTestandClearReferenced(page) || page->age > 0 ||
+		if (PageReferenced(page) || page->age > 0 ||
 				(!page->buffers && page_count(page) > 1)) {
 			del_page_from_inactive_clean_list(page);
 			add_page_to_active_list(page);
@@ -453,7 +462,7 @@
 		}
 
 		/* Page is or was in use?  Move it to the active list. */
-		if (PageTestandClearReferenced(page) || page->age > 0 ||
+		if (PageReferenced(page) || page->age > 0 ||
 				(!page->buffers && page_count(page) > 1) ||
 				page_ramdisk(page)) {
 			del_page_from_inactive_dirty_list(page);
@@ -631,21 +640,42 @@
 /**
  * refill_inactive_scan - scan the active list and find pages to deactivate
  * @priority: the priority at which to scan
- * @oneshot: exit after deactivating one page
+ * @target: number of pages to deactivate, zero for background aging
  *
  * This function will scan a portion of the active list to find
  * unused pages, those pages will then be moved to the inactive list.
  */
-int refill_inactive_scan(unsigned int priority, int oneshot)
+int refill_inactive_scan(unsigned int priority, int target)
 {
 	struct list_head * page_lru;
 	struct page * page;
-	int maxscan, page_active = 0;
-	int ret = 0;
+	int maxscan = nr_active_pages >> priority;
+	int page_active = 0;
+	int nr_deactivated = 0;
+
+	/*
+	 * When we are background aging, we try to increase the page aging
+	 * information in the system. When we have too many inactive pages
+	 * we don't do background aging since having all pages on the
+	 * inactive list decreases aging information.
+	 *
+	 * Since not all active pages have to be on the active list, we round
+	 * nr_active_pages up to num_physpages/2, if needed.
+	 */
+	if (!target) {
+		int inactive = nr_free_pages() + nr_inactive_clean_pages() +
+						nr_inactive_dirty_pages;
+		int active = MAX(nr_active_pages, num_physpages / 2);
+		if (active > 10 * inactive)
+			maxscan = nr_active_pages >> 4;
+		else if (active > 3 * inactive)
+			maxscan = nr_active_pages >> 8;
+		else
+			return 0;
+	}
 
 	/* Take the lock while messing with the list... */
 	spin_lock(&pagemap_lru_lock);
-	maxscan = nr_active_pages >> priority;
 	while (maxscan-- > 0 && (page_lru = active_list.prev) != &active_list) {
 		page = list_entry(page_lru, struct page, lru);
 
@@ -683,21 +713,21 @@
 		}
 		/*
 		 * If the page is still on the active list, move it
-		 * to the other end of the list. Otherwise it was
-		 * deactivated by age_page_down and we exit successfully.
+		 * to the other end of the list. Otherwise we exit if
+		 * we have done enough work.
 		 */
 		if (page_active || PageActive(page)) {
 			list_del(page_lru);
 			list_add(page_lru, &active_list);
 		} else {
-			ret = 1;
-			if (oneshot)
+			nr_deactivated++;
+			if (target && nr_deactivated >= target)
 				break;
 		}
 	}
 	spin_unlock(&pagemap_lru_lock);
 
-	return ret;
+	return nr_deactivated;
 }
 
 /*
@@ -709,7 +739,7 @@
 	pg_data_t *pgdat = pgdat_list;
 	int sum = 0;
 	int freeable = nr_free_pages() + nr_inactive_clean_pages();
-	int freetarget = freepages.high + inactive_target / 3;
+	int freetarget = freepages.high;
 
 	/* Are we low on free pages globally? */
 	if (freeable < freetarget)
@@ -721,9 +751,8 @@
 		for(i = 0; i < MAX_NR_ZONES; i++) {
 			zone_t *zone = pgdat->node_zones+ i;
 			if (zone->size && (zone->inactive_clean_pages +
-					zone->free_pages < zone->pages_min+1)) {
-				/* + 1 to have overlap with alloc_pages() !! */
-				sum += zone->pages_min + 1;
+					zone->free_pages < zone->pages_min)) {
+				sum += zone->pages_min;
 				sum -= zone->free_pages;
 				sum -= zone->inactive_clean_pages;
 			}
@@ -777,38 +806,46 @@
 }
 
 /*
- * We need to make the locks finer granularity, but right
- * now we need this so that we can do page allocations
- * without holding the kernel lock etc.
+ * Refill_inactive is the function used to scan and age the pages on
+ * the active list and in the working set of processes, moving the
+ * little-used pages to the inactive list.
  *
- * We want to try to free "count" pages, and we want to 
- * cluster them so that we get good swap-out behaviour.
+ * When called by kswapd, we try to deactivate as many pages as needed
+ * to recover from the inactive page shortage. This makes it possible
+ * for kswapd to keep up with memory demand so user processes can get
+ * low latency on memory allocations.
  *
- * OTOH, if we're a user process (and not kswapd), we
- * really care about latency. In that case we don't try
- * to free too many pages.
+ * However, when the system starts to get overloaded we can get called
+ * by user processes. For user processes we want to both reduce the
+ * latency and make sure that multiple user processes together don't
+ * deactivate too many pages. To achieve this we simply do less work
+ * when called from a user process.
  */
 #define DEF_PRIORITY (6)
 static int refill_inactive(unsigned int gfp_mask, int user)
 {
 	int count, start_count, maxtry;
 
-	count = inactive_shortage() + free_shortage();
-	if (user)
+	if (user) {
 		count = (1 << page_cluster);
-	start_count = count;
+		maxtry = 6;
+	} else {
+		count = inactive_shortage();
+		maxtry = 1 << DEF_PRIORITY;
+	}
 
-	maxtry = 6;
+	start_count = count;
 	do {
 		if (current->need_resched) {
 			__set_current_state(TASK_RUNNING);
 			schedule();
+			if (!inactive_shortage())
+				return 1;
 		}
 
-		while (refill_inactive_scan(DEF_PRIORITY, 1)) {
-			if (--count <= 0)
-				goto done;
-		}
+		count -= refill_inactive_scan(DEF_PRIORITY, count);
+		if (count <= 0)
+			goto done;
 
 		/* If refill_inactive_scan failed, try to page stuff out.. */
 		swap_out(DEF_PRIORITY, gfp_mask);
@@ -834,8 +871,7 @@
 	 * before we get around to moving them to the other
 	 * list, so this is a relatively cheap operation.
 	 */
-	if (free_shortage() || nr_inactive_dirty_pages > nr_free_pages() +
-			nr_inactive_clean_pages())
+	if (free_shortage())
 		ret += page_launder(gfp_mask, user);
 
 	/*
@@ -916,18 +952,15 @@
 		if (inactive_shortage() || free_shortage()) 
 			do_try_to_free_pages(GFP_KSWAPD, 0);
 
-		/*
-		 * Do some (very minimal) background scanning. This
-		 * will scan all pages on the active list once
-		 * every minute. This clears old referenced bits
-		 * and moves unused pages to the inactive list.
-		 */
-		refill_inactive_scan(DEF_PRIORITY, 0);
-
-		/* Once a second, recalculate some VM stats. */
+		/* Once a second ... */
 		if (time_after(jiffies, recalc + HZ)) {
 			recalc = jiffies;
+
+			/* Recalculate VM statistics. */
 			recalculate_vm_stats();
+
+			/* Do background page aging. */
+			refill_inactive_scan(DEF_PRIORITY, 0);
 		}
 
 		run_task_queue(&tq_disk);
diff -urN linux-2.4.5-pre2/net/README linux/net/README
--- linux-2.4.5-pre2/net/README	Thu Nov  9 15:57:53 2000
+++ linux/net/README	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
 -------------------+-------------------------------------------
 802 [other	]	alan@lxorguk.ukuu.org.uk	
     [token ring	]	p.norton@computer.org
-appletalk		jschlst@turbolinux.com
+appletalk		jschlst@samba.org
 ax25			g4klx@g4klx.demon.co.uk
 bridge			buytenh@gnu.org
 core			alan@lxorguk.ukuu.org.uk
@@ -13,7 +13,8 @@
 ethernet		alan@lxorguk.ukuu.org.uk
 ipv4			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
 ipv6			davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
-ipx/spx			jschlst@turbolinux.com
+ipx			acme@conectiva.com.br
+spx			jschlst@samba.org
 irda                    dagb@cs.uit.no
 lapb			g4klx@g4klx.demon.co.uk
 netrom			g4klx@g4klx.demon.co.uk
diff -urN linux-2.4.5-pre2/net/atm/mpoa_proc.c linux/net/atm/mpoa_proc.c
--- linux-2.4.5-pre2/net/atm/mpoa_proc.c	Fri Sep  1 09:07:01 2000
+++ linux/net/atm/mpoa_proc.c	Mon Dec  3 22:43:26 2001
@@ -175,7 +175,7 @@
 
         if (nbytes < 0) return -EINVAL;
         if (nbytes == 0) return 0;
-        if (nbytes > PAGE_SIZE) nbytes = PAGE_SIZE-1;
+        if (nbytes >= PAGE_SIZE) nbytes = PAGE_SIZE-1;
 
         error = verify_area(VERIFY_READ, buff, nbytes);
         if (error) return error;
diff -urN linux-2.4.5-pre2/net/core/dev.c linux/net/core/dev.c
--- linux-2.4.5-pre2/net/core/dev.c	Thu Apr 19 08:38:50 2001
+++ linux/net/core/dev.c	Mon Dec  3 22:43:26 2001
@@ -400,7 +400,7 @@
 	struct net_device *dev;
 
 	for (dev = dev_base; dev != NULL; dev = dev->next) {
-		if (strcmp(dev->name, name) == 0)
+		if (strncmp(dev->name, name, IFNAMSIZ) == 0)
 			return dev;
 	}
 	return NULL;
diff -urN linux-2.4.5-pre2/net/core/filter.c linux/net/core/filter.c
--- linux-2.4.5-pre2/net/core/filter.c	Thu Apr 12 12:11:39 2001
+++ linux/net/core/filter.c	Mon Dec  3 22:43:26 2001
@@ -2,7 +2,7 @@
  * Linux Socket Filter - Kernel level socket filtering
  *
  * Author:
- *     Jay Schulist <jschlst@turbolinux.com>
+ *     Jay Schulist <jschlst@samba.org>
  *
  * Based on the design of:
  *     - The Berkeley Packet Filter
@@ -382,6 +382,9 @@
 	struct sock_filter *ftest;
         int pc;
 
+	if ((unsigned int) flen >= (~0U / sizeof(struct sock_filter)))
+		return -EINVAL;
+
        /*
         * Check the filter code now.
         */
@@ -404,7 +407,7 @@
 				   jumps below, where offsets are limited. --ANK (981016)
 				 */
 				if (ftest->k >= (unsigned)(flen-pc-1))
-					return (-EINVAL);
+					return -EINVAL;
 			}
                         else
 			{
@@ -412,7 +415,7 @@
 				 *	For conditionals both must be safe
 				 */
  				if(pc + ftest->jt +1 >= flen || pc + ftest->jf +1 >= flen)
-					return (-EINVAL);
+					return -EINVAL;
 			}
                 }
 
diff -urN linux-2.4.5-pre2/net/ipv4/arp.c linux/net/ipv4/arp.c
--- linux-2.4.5-pre2/net/ipv4/arp.c	Mon Dec  3 22:43:16 2001
+++ linux/net/ipv4/arp.c	Mon Dec  3 22:43:26 2001
@@ -1,6 +1,6 @@
 /* linux/net/inet/arp.c
  *
- * Version:	$Id: arp.c,v 1.97 2001/04/30 04:36:12 davem Exp $
+ * Version:	$Id: arp.c,v 1.98 2001/05/16 16:45:35 davem Exp $
  *
  * Copyright (C) 1994 by Florian  La Roche
  *
@@ -345,6 +345,22 @@
 		read_unlock_bh(&neigh->lock);
 }
 
+static int arp_filter(__u32 sip, __u32 tip, struct net_device *dev)
+{
+	struct rtable *rt;
+	int flag = 0; 
+	/*unsigned long now; */
+
+	if (ip_route_output(&rt, sip, tip, 0, 0) < 0) 
+		return 1;
+	if (rt->u.dst.dev != dev) { 
+		NET_INC_STATS_BH(ArpFilter);
+		flag = 1;
+	} 
+	ip_rt_put(rt); 
+	return flag; 
+} 
+
 /* OBSOLETE FUNCTIONS */
 
 /*
@@ -741,7 +757,12 @@
 		if (addr_type == RTN_LOCAL) {
 			n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
 			if (n) {
-				arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+				int dont_send = 0;
+				if (IN_DEV_ARPFILTER(in_dev))
+					dont_send |= arp_filter(sip,tip,dev); 
+				if (!dont_send)
+					arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
+
 				neigh_release(n);
 			}
 			goto out;
diff -urN linux-2.4.5-pre2/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- linux-2.4.5-pre2/net/ipv4/devinet.c	Sun Mar 25 18:14:25 2001
+++ linux/net/ipv4/devinet.c	Mon Dec  3 22:43:26 2001
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.41 2001/02/18 09:26:26 davem Exp $
+ *	Version: $Id: devinet.c,v 1.42 2001/05/16 16:45:35 davem Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -1016,7 +1016,7 @@
 static struct devinet_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table devinet_vars[13];
+	ctl_table devinet_vars[14];
 	ctl_table devinet_dev[2];
 	ctl_table devinet_conf_dir[2];
 	ctl_table devinet_proto_dir[2];
@@ -1058,6 +1058,9 @@
          &proc_dointvec},
 	{NET_IPV4_CONF_TAG, "tag",
 	 &ipv4_devconf.tag, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
+	{NET_IPV4_CONF_ARPFILTER, "arp_filter",
+	 &ipv4_devconf.arp_filter, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
 	 {0}},
 
diff -urN linux-2.4.5-pre2/net/ipv4/fib_frontend.c linux/net/ipv4/fib_frontend.c
--- linux-2.4.5-pre2/net/ipv4/fib_frontend.c	Mon Dec  3 22:43:16 2001
+++ linux/net/ipv4/fib_frontend.c	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
  *
  *		IPv4 Forwarding Information Base: FIB frontend.
  *
- * Version:	$Id: fib_frontend.c,v 1.23 2001/05/01 23:21:37 davem Exp $
+ * Version:	$Id: fib_frontend.c,v 1.24 2001/05/13 18:14:46 davem Exp $
  *
  * Authors:	Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  *
@@ -569,9 +569,9 @@
 #undef BRD1_OK
 }
 
-static void fib_disable_ip(struct net_device *dev, u32 addr, int force)
+static void fib_disable_ip(struct net_device *dev, int force)
 {
-	if (fib_sync_down(addr, dev, force))
+	if (fib_sync_down(0, dev, force))
 		fib_flush();
 	rt_cache_flush(0);
 	arp_ifdown(dev);
@@ -587,13 +587,13 @@
 		rt_cache_flush(-1);
 		break;
 	case NETDEV_DOWN:
+		fib_del_ifaddr(ifa);
 		if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
 			/* Last address was deleted from this interface.
 			   Disable IP.
 			 */
-			fib_disable_ip(ifa->ifa_dev->dev, ifa->ifa_local, 1);
+			fib_disable_ip(ifa->ifa_dev->dev, 1);
 		} else {
-			fib_del_ifaddr(ifa);
 			rt_cache_flush(-1);
 		}
 		break;
@@ -620,10 +620,10 @@
 		rt_cache_flush(-1);
 		break;
 	case NETDEV_DOWN:
-		fib_disable_ip(dev, 0, 0);
+		fib_disable_ip(dev, 0);
 		break;
 	case NETDEV_UNREGISTER:
-		fib_disable_ip(dev, 0, 1);
+		fib_disable_ip(dev, 1);
 		break;
 	case NETDEV_CHANGEMTU:
 	case NETDEV_CHANGE:
diff -urN linux-2.4.5-pre2/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- linux-2.4.5-pre2/net/ipv4/icmp.c	Mon Dec  3 22:43:16 2001
+++ linux/net/ipv4/icmp.c	Mon Dec  3 22:43:26 2001
@@ -3,7 +3,7 @@
  *	
  *		Alan Cox, <alan@redhat.com>
  *
- *	Version: $Id: icmp.c,v 1.75 2001/04/30 04:40:40 davem Exp $
+ *	Version: $Id: icmp.c,v 1.76 2001/05/10 01:20:58 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -1006,6 +1006,7 @@
 	icmp_socket->sk->allocation=GFP_ATOMIC;
 	icmp_socket->sk->sndbuf = SK_WMEM_MAX*2;
 	icmp_socket->sk->protinfo.af_inet.ttl = MAXTTL;
+	icmp_socket->sk->protinfo.af_inet.pmtudisc = IP_PMTUDISC_DONT;
 
 	/* Unhash it so that IP input processing does not even
 	 * see it, we do not wish this socket to see incoming
diff -urN linux-2.4.5-pre2/net/ipv4/ip_gre.c linux/net/ipv4/ip_gre.c
--- linux-2.4.5-pre2/net/ipv4/ip_gre.c	Wed Apr 18 14:40:07 2001
+++ linux/net/ipv4/ip_gre.c	Mon Dec  3 22:43:26 2001
@@ -273,6 +273,7 @@
 	dev->init = ipgre_tunnel_init;
 	dev->features |= NETIF_F_DYNALLOC;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	nt->parms.name[IFNAMSIZ-1] = '\0';
 	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
diff -urN linux-2.4.5-pre2/net/ipv4/ipip.c linux/net/ipv4/ipip.c
--- linux-2.4.5-pre2/net/ipv4/ipip.c	Wed Apr 25 14:57:39 2001
+++ linux/net/ipv4/ipip.c	Mon Dec  3 22:43:26 2001
@@ -244,6 +244,7 @@
 	dev->init = ipip_tunnel_init;
 	dev->features |= NETIF_F_DYNALLOC;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	nt->parms.name[IFNAMSIZ-1] = '\0';
 	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
diff -urN linux-2.4.5-pre2/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.5-pre2/net/ipv4/netfilter/ip_nat_core.c	Fri Apr 27 14:15:01 2001
+++ linux/net/ipv4/netfilter/ip_nat_core.c	Mon Dec  3 22:43:26 2001
@@ -890,13 +890,14 @@
 }
 
 /* Clear NAT section of all conntracks, in case we're loaded again. */
-static int __exit clean_nat(const struct ip_conntrack *i, void *data)
+static int clean_nat(const struct ip_conntrack *i, void *data)
 {
 	memset((void *)&i->nat, 0, sizeof(i->nat));
 	return 0;
 }
 
-void __exit ip_nat_cleanup(void)
+/* Not __exit: called from ip_nat_standalone.c:init_or_cleanup() --RR */
+void ip_nat_cleanup(void)
 {
 	ip_ct_selective_cleanup(&clean_nat, NULL);
 	ip_conntrack_destroyed = NULL;
diff -urN linux-2.4.5-pre2/net/ipv4/netfilter/ip_tables.c linux/net/ipv4/netfilter/ip_tables.c
--- linux-2.4.5-pre2/net/ipv4/netfilter/ip_tables.c	Mon Dec  4 18:43:02 2000
+++ linux/net/ipv4/netfilter/ip_tables.c	Mon Dec  3 22:43:26 2001
@@ -1243,6 +1243,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		name[IPT_TABLE_MAXNAMELEN-1] = '\0';
 		t = find_table_lock(name, &ret, &ipt_mutex);
 		if (t) {
 			struct ipt_getinfo info;
diff -urN linux-2.4.5-pre2/net/ipv4/proc.c linux/net/ipv4/proc.c
--- linux-2.4.5-pre2/net/ipv4/proc.c	Thu Aug 10 13:01:26 2000
+++ linux/net/ipv4/proc.c	Mon Dec  3 22:43:26 2001
@@ -7,7 +7,7 @@
  *		PROC file system.  It is mainly used for debugging and
  *		statistics.
  *
- * Version:	$Id: proc.c,v 1.44 2000/08/09 11:59:04 davem Exp $
+ * Version:	$Id: proc.c,v 1.45 2001/05/16 16:45:35 davem Exp $
  *
  * Authors:	Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  *		Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de>
@@ -170,7 +170,7 @@
 	len = sprintf(buffer,
 		      "TcpExt: SyncookiesSent SyncookiesRecv SyncookiesFailed"
 		      " EmbryonicRsts PruneCalled RcvPruned OfoPruned"
-		      " OutOfWindowIcmps LockDroppedIcmps"
+		      " OutOfWindowIcmps LockDroppedIcmps ArpFilter"
 		      " TW TWRecycled TWKilled"
 		      " PAWSPassive PAWSActive PAWSEstab"
 		      " DelayedACKs DelayedACKLocked DelayedACKLost"
diff -urN linux-2.4.5-pre2/net/ipv4/raw.c linux/net/ipv4/raw.c
--- linux-2.4.5-pre2/net/ipv4/raw.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/raw.c	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
  *
  *		RAW - implementation of IP "raw" sockets.
  *
- * Version:	$Id: raw.c,v 1.60 2001/02/23 06:32:11 davem Exp $
+ * Version:	$Id: raw.c,v 1.61 2001/05/03 20:56:04 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -14,8 +14,9 @@
  *		Alan Cox	:	verify_area() fixed up
  *		Alan Cox	:	ICMP error handling
  *		Alan Cox	:	EMSGSIZE if you send too big a packet
- *		Alan Cox	: 	Now uses generic datagrams and shared skbuff
- *					library. No more peek crashes, no more backlogs
+ *		Alan Cox	: 	Now uses generic datagrams and shared
+ *					skbuff library. No more peek crashes,
+ *					no more backlogs
  *		Alan Cox	:	Checks sk->broadcast.
  *		Alan Cox	:	Uses skb_free_datagram/skb_copy_datagram
  *		Alan Cox	:	Raw passes ip options too
@@ -101,11 +102,11 @@
 {
 	struct sock *s = sk;
 
-	for(s = sk; s; s = s->next) {
-		if((s->num == num) 				&&
-		   !(s->daddr && s->daddr != raddr) 		&&
-		   !(s->rcv_saddr && s->rcv_saddr != laddr)	&&
-		   !(s->bound_dev_if && s->bound_dev_if != dif))
+	for (s = sk; s; s = s->next) {
+		if (s->num == num 				&&
+		    !(s->daddr && s->daddr != raddr) 		&&
+		    !(s->rcv_saddr && s->rcv_saddr != laddr)	&&
+		    !(s->bound_dev_if && s->bound_dev_if != dif))
 			break; /* gotcha */
 	}
 	return s;
@@ -117,7 +118,7 @@
  */
 static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
 {
-	int    type;
+	int type;
 
 	type = skb->h.icmph->type;
 	if (type < 32)
@@ -145,19 +146,19 @@
 			     iph->saddr, iph->daddr,
 			     skb->dev->ifindex);
 
-	while(sk != NULL) {
+	while (sk) {
 		struct sock *sknext = __raw_v4_lookup(sk->next, iph->protocol,
 						      iph->saddr, iph->daddr,
 						      skb->dev->ifindex);
 		if (iph->protocol != IPPROTO_ICMP ||
-		    ! icmp_filter(sk, skb)) {
+		    !icmp_filter(sk, skb)) {
 			struct sk_buff *clone;
 
-			if(sknext == NULL)
+			if (!sknext)
 				break;
 			clone = skb_clone(skb, GFP_ATOMIC);
 			/* Not releasing hash table! */
-			if(clone)
+			if (clone)
 				raw_rcv(sk, clone);
 		}
 		sk = sknext;
@@ -203,14 +204,15 @@
 		err = icmp_err_convert[code].errno;
 		harderr = icmp_err_convert[code].fatal;
 		if (code == ICMP_FRAG_NEEDED) {
-			harderr = (sk->protinfo.af_inet.pmtudisc != IP_PMTUDISC_DONT);
+			harderr = sk->protinfo.af_inet.pmtudisc !=
+					IP_PMTUDISC_DONT;
 			err = EMSGSIZE;
 		}
 	}
 
 	if (sk->protinfo.af_inet.recverr) {
 		struct iphdr *iph = (struct iphdr*)skb->data;
-		u8 *payload = skb->data+(iph->ihl<<2);
+		u8 *payload = skb->data + (iph->ihl << 2);
 
 		if (sk->protinfo.af_inet.hdrincl)
 			payload = skb->data;
@@ -227,8 +229,7 @@
 {
 	/* Charge it to the socket. */
 	
-	if (sock_queue_rcv_skb(sk,skb)<0)
-	{
+	if (sock_queue_rcv_skb(sk, skb) < 0) {
 		IP_INC_STATS(IpInDiscards);
 		kfree_skb(skb);
 		return NET_RX_DROP;
@@ -240,7 +241,7 @@
 
 int raw_rcv(struct sock *sk, struct sk_buff *skb)
 {
-	skb_push(skb, skb->data-skb->nh.raw);
+	skb_push(skb, skb->data - skb->nh.raw);
 
 	raw_rcv_skb(sk, skb);
 	return 0;
@@ -248,9 +249,9 @@
 
 struct rawfakehdr 
 {
-	struct  iovec *iov;
+	struct	iovec *iov;
 	u32	saddr;
-	struct dst_entry *dst;
+	struct	dst_entry *dst;
 };
 
 /*
@@ -261,7 +262,8 @@
  *	Callback support is trivial for SOCK_RAW
  */
   
-static int raw_getfrag(const void *p, char *to, unsigned int offset, unsigned int fraglen)
+static int raw_getfrag(const void *p, char *to, unsigned int offset,
+			unsigned int fraglen)
 {
 	struct rawfakehdr *rfh = (struct rawfakehdr *) p;
 	return memcpy_fromiovecend(to, rfh->iov, offset, fraglen);
@@ -271,27 +273,28 @@
  *	IPPROTO_RAW needs extra work.
  */
  
-static int raw_getrawfrag(const void *p, char *to, unsigned int offset, unsigned int fraglen)
+static int raw_getrawfrag(const void *p, char *to, unsigned int offset,
+				unsigned int fraglen)
 {
 	struct rawfakehdr *rfh = (struct rawfakehdr *) p;
 
 	if (memcpy_fromiovecend(to, rfh->iov, offset, fraglen))
 		return -EFAULT;
 
-	if (offset==0) {
+	if (!offset) {
 		struct iphdr *iph = (struct iphdr *)to;
 		if (!iph->saddr)
 			iph->saddr = rfh->saddr;
-		iph->check=0;
-		iph->tot_len=htons(fraglen);	/* This is right as you can't frag
-						   RAW packets */
+		iph->check   = 0;
+		iph->tot_len = htons(fraglen); /* This is right as you can't
+						  frag RAW packets */
 		/*
 	 	 *	Deliberate breach of modularity to keep 
 	 	 *	ip_build_xmit clean (well less messy).
 		 */
 		if (!iph->id)
 			ip_select_ident(iph, rfh->dst, NULL);
-		iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl);
+		iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
 	}
 	return 0;
 }
@@ -317,15 +320,17 @@
 	   If len was ULONG_MAX-10 it would be cathastrophe  --ANK
 	 */
 
+	err = -EMSGSIZE;
 	if (len < 0 || len > 0xFFFF)
-		return -EMSGSIZE;
+		goto out;
 
 	/*
 	 *	Check the flags.
 	 */
 
-	if (msg->msg_flags & MSG_OOB)		/* Mirror BSD error message compatibility */
-		return -EOPNOTSUPP;
+	err = -EOPNOTSUPP;
+	if (msg->msg_flags & MSG_OOB)	/* Mirror BSD error message */
+		goto out;               /* compatibility */
 			 
 	/*
 	 *	Get and verify the address. 
@@ -333,14 +338,18 @@
 
 	if (msg->msg_namelen) {
 		struct sockaddr_in *usin = (struct sockaddr_in*)msg->msg_name;
+		err = -EINVAL;
 		if (msg->msg_namelen < sizeof(*usin))
-			return(-EINVAL);
+			goto out;
 		if (usin->sin_family != AF_INET) {
 			static int complained;
 			if (!complained++)
-				printk(KERN_INFO "%s forgot to set AF_INET in raw sendmsg. Fix it!\n", current->comm);
+				printk(KERN_INFO "%s forgot to set AF_INET in "
+						 "raw sendmsg. Fix it!\n",
+						 current->comm);
+			err = -EINVAL;
 			if (usin->sin_family)
-				return -EINVAL;
+				goto out;
 		}
 		daddr = usin->sin_addr.s_addr;
 		/* ANK: I did not forget to get protocol from port field.
@@ -348,8 +357,9 @@
 		 * IP_HDRINCL is much more convenient.
 		 */
 	} else {
+		err = -EINVAL;
 		if (sk->state != TCP_ESTABLISHED) 
-			return(-EINVAL);
+			goto out;
 		daddr = sk->daddr;
 	}
 
@@ -358,11 +368,11 @@
 	ipc.oif = sk->bound_dev_if;
 
 	if (msg->msg_controllen) {
-		int tmp = ip_cmsg_send(msg, &ipc);
-		if (tmp)
-			return tmp;
+		err = ip_cmsg_send(msg, &ipc);
+		if (err)
+			goto out;
 		if (ipc.opt)
-			free=1;
+			free = 1;
 	}
 
 	rfh.saddr = ipc.addr;
@@ -385,7 +395,7 @@
 		}
 	}
 	tos = RT_TOS(sk->protinfo.af_inet.tos) | sk->localroute;
-	if (msg->msg_flags&MSG_DONTROUTE)
+	if (msg->msg_flags & MSG_DONTROUTE)
 		tos |= RTO_ONLINK;
 
 	if (MULTICAST(daddr)) {
@@ -401,31 +411,31 @@
 		goto done;
 
 	err = -EACCES;
-	if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast)
+	if (rt->rt_flags & RTCF_BROADCAST && !sk->broadcast)
 		goto done;
 
-	if (msg->msg_flags&MSG_CONFIRM)
+	if (msg->msg_flags & MSG_CONFIRM)
 		goto do_confirm;
 back_from_confirm:
 
-	rfh.iov = msg->msg_iov;
-	rfh.saddr = rt->rt_src;
-	rfh.dst = &rt->u.dst;
+	rfh.iov		= msg->msg_iov;
+	rfh.saddr	= rt->rt_src;
+	rfh.dst		= &rt->u.dst;
 	if (!ipc.addr)
 		ipc.addr = rt->rt_dst;
-	err=ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag : raw_getfrag,
-			  &rfh, len, &ipc, rt, msg->msg_flags);
+	err = ip_build_xmit(sk, sk->protinfo.af_inet.hdrincl ? raw_getrawfrag :
+		       	    raw_getfrag, &rfh, len, &ipc, rt, msg->msg_flags);
 
 done:
 	if (free)
 		kfree(ipc.opt);
 	ip_rt_put(rt);
 
-	return err<0 ? err : len;
+out:	return err < 0 ? err : len;
 
 do_confirm:
 	dst_confirm(&rt->u.dst);
-	if (!(msg->msg_flags&MSG_PROBE) || len)
+	if (!(msg->msg_flags & MSG_PROBE) || len)
 		goto back_from_confirm;
 	err = 0;
 	goto done;
@@ -445,19 +455,22 @@
 static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
 	struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
+	int ret = -EINVAL;
 	int chk_addr_ret;
 
-	if((sk->state != TCP_CLOSE) || (addr_len < sizeof(struct sockaddr_in)))
-		return -EINVAL;
+	if (sk->state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_in))
+		goto out;
 	chk_addr_ret = inet_addr_type(addr->sin_addr.s_addr);
-	if(addr->sin_addr.s_addr != 0 && chk_addr_ret != RTN_LOCAL &&
-	   chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
-		return -EADDRNOTAVAIL;
+	ret = -EADDRNOTAVAIL;
+	if (addr->sin_addr.s_addr && chk_addr_ret != RTN_LOCAL &&
+	    chk_addr_ret != RTN_MULTICAST && chk_addr_ret != RTN_BROADCAST)
+		goto out;
 	sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;
-	if(chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
+	if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
 		sk->saddr = 0;  /* Use device */
 	sk_dst_reset(sk);
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 /*
@@ -466,29 +479,30 @@
  */
 
 int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
-		int noblock, int flags,int *addr_len)
+		int noblock, int flags, int *addr_len)
 {
-	int copied=0;
+	int copied = 0;
+	int err = -EOPNOTSUPP;
+	struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name;
 	struct sk_buff *skb;
-	int err;
-	struct sockaddr_in *sin=(struct sockaddr_in *)msg->msg_name;
 
 	if (flags & MSG_OOB)
-		return -EOPNOTSUPP;
+		goto out;
 
 	if (addr_len)
-		*addr_len=sizeof(*sin);
+		*addr_len = sizeof(*sin);
 
-	if (flags & MSG_ERRQUEUE)
-		return ip_recv_error(sk, msg, len);
+	if (flags & MSG_ERRQUEUE) {
+		err = ip_recv_error(sk, msg, len);
+		goto out;
+	}
 
-	skb=skb_recv_datagram(sk,flags,noblock,&err);
-	if(skb==NULL)
- 		return err;
+	skb = skb_recv_datagram(sk, flags, noblock, &err);
+	if (!skb)
+		goto out;
 
 	copied = skb->len;
-	if (len < copied)
-	{
+	if (len < copied) {
 		msg->msg_flags |= MSG_TRUNC;
 		copied = len;
 	}
@@ -508,7 +522,7 @@
 		ip_cmsg_recv(msg, skb);
 done:
 	skb_free_datagram(sk, skb);
-	return (err ? : copied);
+out:	return err ? : copied;
 }
 
 static int raw_init(struct sock *sk)
@@ -530,19 +544,21 @@
 
 static int raw_geticmpfilter(struct sock *sk, char *optval, int *optlen)
 {
-	int len;
+	int len, ret = -EFAULT;
 
-	if (get_user(len,optlen))
-		return -EFAULT;
+	if (get_user(len, optlen))
+		goto out;
+	ret = -EINVAL;
 	if (len < 0)
-		return -EINVAL;
+		goto out;
 	if (len > sizeof(struct icmp_filter))
 		len = sizeof(struct icmp_filter);
-	if (put_user(len, optlen))
-		return -EFAULT;
-	if (copy_to_user(optval, &sk->tp_pinfo.tp_raw4.filter, len))
-		return -EFAULT;
-	return 0;
+	ret = -EFAULT;
+	if (put_user(len, optlen) ||
+	    copy_to_user(optval, &sk->tp_pinfo.tp_raw4.filter, len))
+		goto out;
+	ret = 0;
+out:	return ret;
 }
 
 static int raw_setsockopt(struct sock *sk, int level, int optname, 
@@ -551,13 +567,12 @@
 	if (level != SOL_RAW)
 		return ip_setsockopt(sk, level, optname, optval, optlen);
 
-	switch (optname) {
-	case ICMP_FILTER:
+	if (optname == ICMP_FILTER) {
 		if (sk->num != IPPROTO_ICMP)
 			return -EOPNOTSUPP;
-		return raw_seticmpfilter(sk, optval, optlen);
-	};
-
+		else
+			return raw_seticmpfilter(sk, optval, optlen);
+	}
 	return -ENOPROTOOPT;
 }
 
@@ -567,26 +582,23 @@
 	if (level != SOL_RAW)
 		return ip_getsockopt(sk, level, optname, optval, optlen);
 
-	switch (optname) {
-	case ICMP_FILTER:
+	if (optname == ICMP_FILTER) {
 		if (sk->num != IPPROTO_ICMP)
 			return -EOPNOTSUPP;
-		return raw_geticmpfilter(sk, optval, optlen);
-	};
-
+		else
+			return raw_geticmpfilter(sk, optval, optlen);
+	}
 	return -ENOPROTOOPT;
 }
 
 static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
 {
-	switch(cmd) {
-		case SIOCOUTQ:
-		{
+	switch (cmd) {
+		case SIOCOUTQ: {
 			int amount = atomic_read(&sk->wmem_alloc);
 			return put_user(amount, (int *)arg);
 		}
-		case SIOCINQ:
-		{
+		case SIOCINQ: {
 			struct sk_buff *skb;
 			int amount = 0;
 
@@ -609,13 +621,11 @@
 
 static void get_raw_sock(struct sock *sp, char *tmpbuf, int i)
 {
-	unsigned int dest, src;
-	__u16 destp, srcp;
+	unsigned int dest = sp->daddr,
+		     src = sp->rcv_saddr;
+	__u16 destp = 0,
+	      srcp  = sp->num;
 
-	dest  = sp->daddr;
-	src   = sp->rcv_saddr;
-	destp = 0;
-	srcp  = sp->num;
 	sprintf(tmpbuf, "%4d: %08X:%04X %08X:%04X"
 		" %02X %08X:%08X %02X:%08lX %08X %5d %8d %ld %d %p",
 		i, src, srcp, dest, destp, sp->state, 
@@ -629,15 +639,15 @@
 int raw_get_info(char *buffer, char **start, off_t offset, int length)
 {
 	int len = 0, num = 0, i;
-	off_t pos = 0;
+	off_t pos = 128;
 	off_t begin;
 	char tmpbuf[129];
 
 	if (offset < 128) 
 		len += sprintf(buffer, "%-127s\n",
 			       "  sl  local_address rem_address   st tx_queue "
-			       "rx_queue tr tm->when retrnsmt   uid  timeout inode");
-	pos = 128;
+			       "rx_queue tr tm->when retrnsmt   uid  timeout "
+			       "inode");
 	read_lock(&raw_v4_lock);
 	for (i = 0; i < RAWV4_HTABLE_SIZE; i++) {
 		struct sock *sk;
@@ -649,8 +659,8 @@
 			if (pos <= offset)
 				continue;
 			get_raw_sock(sk, tmpbuf, i);
-			len += sprintf(buffer+len, "%-127s\n", tmpbuf);
-			if(len >= length)
+			len += sprintf(buffer + len, "%-127s\n", tmpbuf);
+			if (len >= length)
 				goto out;
 		}
 	}
@@ -659,7 +669,7 @@
 	begin = len - (pos - offset);
 	*start = buffer + begin;
 	len -= begin;
-	if(len > length)
+	if (len > length)
 		len = length;
 	if (len < 0)
 		len = 0; 
diff -urN linux-2.4.5-pre2/net/ipv4/route.c linux/net/ipv4/route.c
--- linux-2.4.5-pre2/net/ipv4/route.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/route.c	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
  *
  *		ROUTE - implementation of the IP router.
  *
- * Version:	$Id: route.c,v 1.93 2001/02/22 01:03:05 davem Exp $
+ * Version:	$Id: route.c,v 1.94 2001/05/05 01:01:02 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -101,21 +101,21 @@
 
 #define RT_GC_TIMEOUT (300*HZ)
 
-int ip_rt_min_delay = 2*HZ;
-int ip_rt_max_delay = 10*HZ;
+int ip_rt_min_delay		= 2 * HZ;
+int ip_rt_max_delay		= 10 * HZ;
 int ip_rt_max_size;
-int ip_rt_gc_timeout = RT_GC_TIMEOUT;
-int ip_rt_gc_interval = 60*HZ;
-int ip_rt_gc_min_interval = 5*HZ;
-int ip_rt_redirect_number = 9;
-int ip_rt_redirect_load = HZ/50;
-int ip_rt_redirect_silence = ((HZ/50) << (9+1));
-int ip_rt_error_cost = HZ;
-int ip_rt_error_burst = 5*HZ;
-int ip_rt_gc_elasticity = 8;
-int ip_rt_mtu_expires = 10*60*HZ;
-int ip_rt_min_pmtu = 512+20+20;
-int ip_rt_min_advmss = 256;
+int ip_rt_gc_timeout		= RT_GC_TIMEOUT;
+int ip_rt_gc_interval		= 60 * HZ;
+int ip_rt_gc_min_interval	= 5 * HZ;
+int ip_rt_redirect_number	= 9;
+int ip_rt_redirect_load		= HZ / 50;
+int ip_rt_redirect_silence	= ((HZ / 50) << (9 + 1));
+int ip_rt_error_cost		= HZ;
+int ip_rt_error_burst		= 5 * HZ;
+int ip_rt_gc_elasticity		= 8;
+int ip_rt_mtu_expires		= 10 * 60 * HZ;
+int ip_rt_min_pmtu		= 512 + 20 + 20;
+int ip_rt_min_advmss		= 256;
 
 static unsigned long rt_deadline;
 
@@ -128,28 +128,25 @@
  *	Interface to generic destination cache.
  */
 
-static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32);
-static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
-					   struct sk_buff *);
-static void		  ipv4_dst_destroy(struct dst_entry * dst);
-static struct dst_entry * ipv4_negative_advice(struct dst_entry *);
-static void		  ipv4_link_failure(struct sk_buff *skb);
+static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
+static struct dst_entry *ipv4_dst_reroute(struct dst_entry *dst,
+					   struct sk_buff *skb);
+static void		 ipv4_dst_destroy(struct dst_entry *dst);
+static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
+static void		 ipv4_link_failure(struct sk_buff *skb);
 static int rt_garbage_collect(void);
 
 
-struct dst_ops ipv4_dst_ops =
-{
-	AF_INET,
-	__constant_htons(ETH_P_IP),
-	0,
-
-	rt_garbage_collect,
-	ipv4_dst_check,
-	ipv4_dst_reroute,
-	ipv4_dst_destroy,
-	ipv4_negative_advice,
-	ipv4_link_failure,
-	sizeof(struct rtable),
+struct dst_ops ipv4_dst_ops = {
+	family:			AF_INET,
+	protocol:		__constant_htons(ETH_P_IP),
+	gc:			rt_garbage_collect,
+	check:			ipv4_dst_check,
+	reroute:		ipv4_dst_reroute,
+	destroy:		ipv4_dst_destroy,
+	negative_advice:	ipv4_negative_advice,
+	link_failure:		ipv4_link_failure,
+	entry_size:		sizeof(struct rtable),
 };
 
 #ifdef CONFIG_INET_ECN
@@ -201,32 +198,36 @@
 static unsigned			rt_hash_mask;
 static int			rt_hash_log;
 
-static int rt_intern_hash(unsigned hash, struct rtable * rth, struct rtable ** res);
+static int rt_intern_hash(unsigned hash, struct rtable *rth,
+				struct rtable **res);
 
 static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
 {
-	unsigned hash = ((daddr&0xF0F0F0F0)>>4)|((daddr&0x0F0F0F0F)<<4);
-	hash ^= saddr^tos;
-	hash ^= (hash>>16);
-	return (hash^(hash>>8)) & rt_hash_mask;
+	unsigned hash = ((daddr & 0xF0F0F0F0) >> 4) |
+			((daddr & 0x0F0F0F0F) << 4);
+	hash ^= saddr ^ tos;
+	hash ^= (hash >> 16);
+	return (hash ^ (hash >> 8)) & rt_hash_mask;
 }
 
-static int rt_cache_get_info(char *buffer, char **start, off_t offset, int length)
+static int rt_cache_get_info(char *buffer, char **start, off_t offset,
+				int length)
 {
-	int len=0;
-	off_t pos=0;
+	int len = 0;
+	off_t pos = 128;
 	char temp[129];
 	struct rtable *r;
 	int i;
 
-	pos = 128;
-
-	if (offset<128)	{
-		sprintf(buffer,"%-127s\n", "Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\tMetric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\tHHUptod\tSpecDst");
+	if (offset < 128) {
+		sprintf(buffer, "%-127s\n",
+			"Iface\tDestination\tGateway \tFlags\t\tRefCnt\tUse\t"
+			"Metric\tSource\t\tMTU\tWindow\tIRTT\tTOS\tHHRef\t"
+			"HHUptod\tSpecDst");
 		len = 128;
   	}
 	
-	for (i = rt_hash_mask; i>=0; i--) {
+	for (i = rt_hash_mask; i >= 0; i--) {
 		read_lock_bh(&rt_hash_table[i].lock);
 		for (r = rt_hash_table[i].chain; r; r = r->u.rt_next) {
 			/*
@@ -238,7 +239,8 @@
 				len = 0;
 				continue;
 			}
-			sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
+			sprintf(temp, "%s\t%08lX\t%08lX\t%8X\t%d\t%u\t%d\t"
+				"%08lX\t%d\t%u\t%u\t%02X\t%d\t%1d\t%08X",
 				r->u.dst.dev ? r->u.dst.dev->name : "*",
 				(unsigned long)r->rt_dst,
 				(unsigned long)r->rt_gateway,
@@ -246,14 +248,19 @@
 				atomic_read(&r->u.dst.__refcnt),
 				r->u.dst.__use,
 				0,
-				(unsigned long)r->rt_src, (int)r->u.dst.advmss + 40,
+				(unsigned long)r->rt_src,
+				(int)r->u.dst.advmss + 40,
 				r->u.dst.window,
-				(int)((r->u.dst.rtt>>3) + r->u.dst.rttvar),
+				(int)((r->u.dst.rtt >> 3) + r->u.dst.rttvar),
 				r->key.tos,
-				r->u.dst.hh ? atomic_read(&r->u.dst.hh->hh_refcnt) : -1,
-				r->u.dst.hh ? (r->u.dst.hh->hh_output == dev_queue_xmit) : 0,
+				r->u.dst.hh ?
+					atomic_read(&r->u.dst.hh->hh_refcnt) :
+					-1,
+				r->u.dst.hh ?
+			       		(r->u.dst.hh->hh_output ==
+					 dev_queue_xmit) : 0,
 				r->rt_spec_dst);
-			sprintf(buffer+len,"%-127s\n",temp);
+			sprintf(buffer + len, "%-127s\n", temp);
 			len += 128;
 			if (pos >= offset+length) {
 				read_unlock_bh(&rt_hash_table[i].lock);
@@ -264,9 +271,9 @@
         }
 
 done:
-  	*start = buffer+len-(pos-offset);
-  	len = pos-offset;
-  	if (len>length)
+  	*start = buffer + len - (pos - offset);
+  	len = pos - offset;
+  	if (len > length)
   		len = length;
   	return len;
 }
@@ -286,45 +293,47 @@
 {
 	/* Kill broadcast/multicast entries very aggresively, if they
 	   collide in hash table with more useful entries */
-	return ((rth->rt_flags&(RTCF_BROADCAST|RTCF_MULTICAST))
-		&& rth->key.iif && rth->u.rt_next);
+	return (rth->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) &&
+		rth->key.iif && rth->u.rt_next;
 }
 
 static __inline__ int rt_valuable(struct rtable *rth)
 {
-	return ((rth->rt_flags&(RTCF_REDIRECTED|RTCF_NOTIFY))
-		|| rth->u.dst.expires);
+	return (rth->rt_flags & (RTCF_REDIRECTED | RTCF_NOTIFY)) ||
+		rth->u.dst.expires;
 }
 
 static __inline__ int rt_may_expire(struct rtable *rth, int tmo1, int tmo2)
 {
 	int age;
+	int ret = 0;
 
 	if (atomic_read(&rth->u.dst.__refcnt))
-		return 0;
+		goto out;
 
+	ret = 1;
 	if (rth->u.dst.expires && (long)(rth->u.dst.expires - jiffies) <= 0)
-		return 1;
+		goto out;
 
 	age = jiffies - rth->u.dst.lastuse;
-	if (age <= tmo1 && !rt_fast_clean(rth))
-		return 0;
-	if (age <= tmo2 && rt_valuable(rth))
-		return 0;
-	return 1;
+	ret = 0;
+	if ((age <= tmo1 && !rt_fast_clean(rth)) ||
+	    (age <= tmo2 && rt_valuable(rth)))
+		goto out;
+	ret = 1;
+out:	return ret;
 }
 
 /* This runs via a timer and thus is always in BH context. */
 static void SMP_TIMER_NAME(rt_check_expire)(unsigned long dummy)
 {
-	int i, t;
 	static int rover;
+	int i = rover, t;
 	struct rtable *rth, **rthp;
 	unsigned long now = jiffies;
 
-	i = rover;
-
-	for (t=(ip_rt_gc_interval<<rt_hash_log); t>=0; t -= ip_rt_gc_timeout) {
+	for (t = ip_rt_gc_interval << rt_hash_log; t >= 0;
+	     t -= ip_rt_gc_timeout) {
 		unsigned tmo = ip_rt_gc_timeout;
 
 		i = (i + 1) & rt_hash_mask;
@@ -345,9 +354,7 @@
 				continue;
 			}
 
-			/*
-			 * Cleanup aged off entries.
-			 */
+			/* Cleanup aged off entries. */
 			*rthp = rth->u.rt_next;
 			rt_free(rth);
 		}
@@ -369,18 +376,18 @@
 static void SMP_TIMER_NAME(rt_run_flush)(unsigned long dummy)
 {
 	int i;
-	struct rtable * rth, * next;
+	struct rtable *rth, *next;
 
 	rt_deadline = 0;
 
-	for (i=rt_hash_mask; i>=0; i--) {
+	for (i = rt_hash_mask; i >= 0; i--) {
 		write_lock_bh(&rt_hash_table[i].lock);
 		rth = rt_hash_table[i].chain;
 		if (rth)
 			rt_hash_table[i].chain = NULL;
 		write_unlock_bh(&rt_hash_table[i].lock);
 
-		for (; rth; rth=next) {
+		for (; rth; rth = next) {
 			next = rth->u.rt_next;
 			rt_free(rth);
 		}
@@ -460,23 +467,24 @@
 	 */
 	if (now - last_gc < ip_rt_gc_min_interval &&
 	    atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
-		return 0;
+		goto out;
 
 	/* Calculate number of entries, which we want to expire now. */
-	goal = atomic_read(&ipv4_dst_ops.entries) - (ip_rt_gc_elasticity<<rt_hash_log);
+	goal = atomic_read(&ipv4_dst_ops.entries) -
+		(ip_rt_gc_elasticity << rt_hash_log);
 	if (goal <= 0) {
 		if (equilibrium < ipv4_dst_ops.gc_thresh)
 			equilibrium = ipv4_dst_ops.gc_thresh;
 		goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
 		if (goal > 0) {
-			equilibrium += min(goal/2, rt_hash_mask+1);
+			equilibrium += min(goal / 2, rt_hash_mask + 1);
 			goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
 		}
 	} else {
 		/* We are in dangerous area. Try to reduce cache really
 		 * aggressively.
 		 */
-		goal = max(goal/2, rt_hash_mask+1);
+		goal = max(goal / 2, rt_hash_mask + 1);
 		equilibrium = atomic_read(&ipv4_dst_ops.entries) - goal;
 	}
 
@@ -491,7 +499,7 @@
 	do {
 		int i, k;
 
-		for (i=rt_hash_mask, k=rover; i>=0; i--) {
+		for (i = rt_hash_mask, k = rover; i >= 0; i--) {
 			unsigned tmo = expire;
 
 			k = (k + 1) & rt_hash_mask;
@@ -530,15 +538,16 @@
 
 		expire >>= 1;
 #if RT_CACHE_DEBUG >= 2
-		printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire, atomic_read(&ipv4_dst_ops.entries), goal, i);
+		printk(KERN_DEBUG "expire>> %u %d %d %d\n", expire,
+				atomic_read(&ipv4_dst_ops.entries), goal, i);
 #endif
 
 		if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
-			return 0;
+			goto out;
 	} while (!in_softirq() && jiffies - now < 1);
 
 	if (atomic_read(&ipv4_dst_ops.entries) < ip_rt_max_size)
-		return 0;
+		goto out;
 	if (net_ratelimit())
 		printk("dst cache overflow\n");
 	return 1;
@@ -549,12 +558,13 @@
 	    atomic_read(&ipv4_dst_ops.entries) < ipv4_dst_ops.gc_thresh)
 		expire = ip_rt_gc_timeout;
 #if RT_CACHE_DEBUG >= 2
-	printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire, atomic_read(&ipv4_dst_ops.entries), goal, rover);
+	printk(KERN_DEBUG "expire++ %u %d %d %d\n", expire,
+			atomic_read(&ipv4_dst_ops.entries), goal, rover);
 #endif
-	return 0;
+out:	return 0;
 }
 
-static int rt_intern_hash(unsigned hash, struct rtable * rt, struct rtable ** rp)
+static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
 {
 	struct rtable	*rth, **rthp;
 	unsigned long	now = jiffies;
@@ -604,11 +614,11 @@
 			if (attempts-- > 0) {
 				int saved_elasticity = ip_rt_gc_elasticity;
 				int saved_int = ip_rt_gc_min_interval;
-				ip_rt_gc_elasticity = 1;
-				ip_rt_gc_min_interval = 0;
+				ip_rt_gc_elasticity	= 1;
+				ip_rt_gc_min_interval	= 0;
 				rt_garbage_collect();
-				ip_rt_gc_min_interval = saved_int;
-				ip_rt_gc_elasticity = saved_elasticity;
+				ip_rt_gc_min_interval	= saved_int;
+				ip_rt_gc_elasticity	= saved_elasticity;
 				goto restart;
 			}
 
@@ -622,9 +632,10 @@
 	rt->u.rt_next = rt_hash_table[hash].chain;
 #if RT_CACHE_DEBUG >= 2
 	if (rt->u.rt_next) {
-		struct rtable * trt;
-		printk("rt_cache @%02x: %u.%u.%u.%u", hash, NIPQUAD(rt->rt_dst));
-		for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next)
+		struct rtable *trt;
+		printk("rt_cache @%02x: %u.%u.%u.%u", hash,
+				NIPQUAD(rt->rt_dst));
+		for (trt = rt->u.rt_next; trt; trt = trt->u.rt_next)
 			printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst));
 		printk("\n");
 	}
@@ -687,9 +698,8 @@
 			iph->id = htons(inet_getid(rt->peer));
 			return;
 		}
-	} else {
+	} else
 		printk(KERN_DEBUG "rt_bind_peer(0) @%p\n", NET_CALLER(iph));
-	}
 
 	ip_select_fb_ident(iph);
 }
@@ -700,13 +710,13 @@
 
 	write_lock_bh(&rt_hash_table[hash].lock);
 	ip_rt_put(rt);
-	for (rthp = &rt_hash_table[hash].chain; *rthp; rthp = &(*rthp)->u.rt_next) {
+	for (rthp = &rt_hash_table[hash].chain; *rthp;
+	     rthp = &(*rthp)->u.rt_next)
 		if (*rthp == rt) {
 			*rthp = rt->u.rt_next;
 			rt_free(rt);
 			break;
 		}
-	}
 	write_unlock_bh(&rt_hash_table[hash].lock);
 }
 
@@ -738,14 +748,16 @@
 			goto reject_redirect;
 	}
 
-	for (i=0; i<2; i++) {
-		for (k=0; k<2; k++) {
-			unsigned hash = rt_hash_code(daddr, skeys[i]^(ikeys[k]<<5), tos);
+	for (i = 0; i < 2; i++) {
+		for (k = 0; k < 2; k++) {
+			unsigned hash = rt_hash_code(daddr,
+						     skeys[i] ^ (ikeys[k] << 5),
+						     tos);
 
 			rthp=&rt_hash_table[hash].chain;
 
 			read_lock(&rt_hash_table[hash].lock);
-			while ( (rth = *rthp) != NULL) {
+			while ((rth = *rthp) != NULL) {
 				struct rtable *rt;
 
 				if (rth->key.dst != daddr ||
@@ -774,23 +786,21 @@
 					return;
 				}
 
-				/*
-				 * Copy all the information.
-				 */
+				/* Copy all the information. */
 				*rt = *rth;
-				rt->u.dst.__use = 1;
+				rt->u.dst.__use		= 1;
 				atomic_set(&rt->u.dst.__refcnt, 1);
 				if (rt->u.dst.dev)
 					dev_hold(rt->u.dst.dev);
-				rt->u.dst.lastuse = jiffies;
-				rt->u.dst.neighbour = NULL;
-				rt->u.dst.hh = NULL;
-				rt->u.dst.obsolete = 0;
+				rt->u.dst.lastuse	= jiffies;
+				rt->u.dst.neighbour	= NULL;
+				rt->u.dst.hh		= NULL;
+				rt->u.dst.obsolete	= 0;
 
-				rt->rt_flags |= RTCF_REDIRECTED;
+				rt->rt_flags		|= RTCF_REDIRECTED;
 
 				/* Gateway is different ... */
-				rt->rt_gateway = new_gw;
+				rt->rt_gateway		= new_gw;
 
 				/* Redirect received -> path was valid */
 				dst_confirm(&rth->u.dst);
@@ -799,7 +809,8 @@
 					atomic_inc(&rt->peer->refcnt);
 
 				if (arp_bind_neighbour(&rt->u.dst) ||
-				    !(rt->u.dst.neighbour->nud_state&NUD_VALID)) {
+				    !(rt->u.dst.neighbour->nud_state &
+					    NUD_VALID)) {
 					if (rt->u.dst.neighbour)
 						neigh_event_send(rt->u.dst.neighbour, NULL);
 					ip_rt_put(rth);
@@ -823,8 +834,10 @@
 reject_redirect:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-		printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about %u.%u.%u.%u ignored.\n"
-		       "  Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, tos %02x\n",
+		printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about "
+			"%u.%u.%u.%u ignored.\n"
+			"  Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, "
+			"tos %02x\n",
 		       NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw),
 		       NIPQUAD(saddr), NIPQUAD(daddr), tos);
 #endif
@@ -834,23 +847,28 @@
 static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
 {
 	struct rtable *rt = (struct rtable*)dst;
+	struct dst_entry *ret = dst;
 
-	if (rt != NULL) {
+	if (rt) {
 		if (dst->obsolete) {
 			ip_rt_put(rt);
-			return NULL;
-		}
-		if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) {
-			unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos);
+			ret = NULL;
+		} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
+			   rt->u.dst.expires) {
+			unsigned hash = rt_hash_code(rt->key.dst,
+						     rt->key.src ^
+							(rt->key.oif << 5),
+						     rt->key.tos);
 #if RT_CACHE_DEBUG >= 1
-			printk(KERN_DEBUG "ip_rt_advice: redirect to %u.%u.%u.%u/%02x dropped\n",
+			printk(KERN_DEBUG "ip_rt_advice: redirect to "
+					  "%u.%u.%u.%u/%02x dropped\n",
 				NIPQUAD(rt->rt_dst), rt->key.tos);
 #endif
 			rt_del(hash, rt);
-			return NULL;
+			ret = NULL;
 		}
 	}
-	return dst;
+	return ret;
 }
 
 /*
@@ -897,15 +915,17 @@
 	/* Check for load limit; set rate_last to the latest sent
 	 * redirect.
 	 */
-	if (jiffies - rt->u.dst.rate_last > (ip_rt_redirect_load<<rt->u.dst.rate_tokens)) {
+	if (jiffies - rt->u.dst.rate_last >
+	    (ip_rt_redirect_load << rt->u.dst.rate_tokens)) {
 		icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway);
 		rt->u.dst.rate_last = jiffies;
 		++rt->u.dst.rate_tokens;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 		if (IN_DEV_LOG_MARTIANS(in_dev) &&
-		    rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit())
-			printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores redirects for "
-				"%u.%u.%u.%u to %u.%u.%u.%u.\n",
+		    rt->u.dst.rate_tokens == ip_rt_redirect_number &&
+		    net_ratelimit())
+			printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores "
+				"redirects for %u.%u.%u.%u to %u.%u.%u.%u.\n",
 				NIPQUAD(rt->rt_src), rt->rt_iif,
 				NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway));
 #endif
@@ -921,23 +941,23 @@
 	int code;
 
 	switch (rt->u.dst.error) {
-	case EINVAL:
-	default:
-		kfree_skb(skb);
-		return 0;
-	case EHOSTUNREACH:
-		code = ICMP_HOST_UNREACH;
-		break;
-	case ENETUNREACH:
-		code = ICMP_NET_UNREACH;
-		break;
-	case EACCES:
-		code = ICMP_PKT_FILTERED;
-		break;
+		case EINVAL:
+		default:
+			goto out;
+		case EHOSTUNREACH:
+			code = ICMP_HOST_UNREACH;
+			break;
+		case ENETUNREACH:
+			code = ICMP_NET_UNREACH;
+			break;
+		case EACCES:
+			code = ICMP_PKT_FILTERED;
+			break;
 	}
 
 	now = jiffies;
-	if ((rt->u.dst.rate_tokens += (now - rt->u.dst.rate_last)) > ip_rt_error_burst)
+	rt->u.dst.rate_tokens += now - rt->u.dst.rate_last;
+	if (rt->u.dst.rate_tokens > ip_rt_error_burst)
 		rt->u.dst.rate_tokens = ip_rt_error_burst;
 	rt->u.dst.rate_last = now;
 	if (rt->u.dst.rate_tokens >= ip_rt_error_cost) {
@@ -945,7 +965,7 @@
 		icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
 	}
 
-	kfree_skb(skb);
+out:	kfree_skb(skb);
 	return 0;
 } 
 
@@ -961,7 +981,7 @@
 {
 	int i;
 	
-	for (i = 0; i < sizeof(mtu_plateau)/sizeof(mtu_plateau[0]); i++)
+	for (i = 0; i < sizeof(mtu_plateau) / sizeof(mtu_plateau[0]); i++)
 		if (old_mtu > mtu_plateau[i])
 			return mtu_plateau[i];
 	return 68;
@@ -980,26 +1000,28 @@
 	if (ipv4_config.no_pmtu_disc)
 		return 0;
 
-	for (i=0; i<2; i++) {
+	for (i = 0; i < 2; i++) {
 		unsigned hash = rt_hash_code(daddr, skeys[i], tos);
 
 		read_lock(&rt_hash_table[hash].lock);
-		for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
+		for (rth = rt_hash_table[hash].chain; rth;
+		     rth = rth->u.rt_next) {
 			if (rth->key.dst == daddr &&
 			    rth->key.src == skeys[i] &&
-			    rth->rt_dst == daddr &&
-			    rth->rt_src == iph->saddr &&
+			    rth->rt_dst  == daddr &&
+			    rth->rt_src  == iph->saddr &&
 			    rth->key.tos == tos &&
 			    rth->key.iif == 0 &&
-			    !(rth->u.dst.mxlock&(1<<RTAX_MTU))) {
+			    !(rth->u.dst.mxlock & (1 << RTAX_MTU))) {
 				unsigned short mtu = new_mtu;
 
 				if (new_mtu < 68 || new_mtu >= old_mtu) {
 
 					/* BSD 4.2 compatibility hack :-( */
-					if (mtu == 0 && old_mtu >= rth->u.dst.pmtu &&
-					    old_mtu >= 68 + (iph->ihl<<2))
-						old_mtu -= iph->ihl<<2;
+					if (mtu == 0 &&
+					    old_mtu >= rth->u.dst.pmtu &&
+					    old_mtu >= 68 + (iph->ihl << 2))
+						old_mtu -= iph->ihl << 2;
 
 					mtu = guess_mtu(old_mtu);
 				}
@@ -1008,10 +1030,12 @@
 						dst_confirm(&rth->u.dst);
 						if (mtu < ip_rt_min_pmtu) {
 							mtu = ip_rt_min_pmtu;
-							rth->u.dst.mxlock |= (1<<RTAX_MTU);
+							rth->u.dst.mxlock |=
+								(1 << RTAX_MTU);
 						}
 						rth->u.dst.pmtu = mtu;
-						dst_set_expires(&rth->u.dst, ip_rt_mtu_expires);
+						dst_set_expires(&rth->u.dst,
+							ip_rt_mtu_expires);
 					}
 					est_mtu = mtu;
 				}
@@ -1025,29 +1049,29 @@
 void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu)
 {
 	if (dst->pmtu > mtu && mtu >= 68 &&
-	    !(dst->mxlock&(1<<RTAX_MTU))) {
+	    !(dst->mxlock & (1 << RTAX_MTU))) {
 		if (mtu < ip_rt_min_pmtu) {
 			mtu = ip_rt_min_pmtu;
-			dst->mxlock |= (1<<RTAX_MTU);
+			dst->mxlock |= (1 << RTAX_MTU);
 		}
 		dst->pmtu = mtu;
 		dst_set_expires(dst, ip_rt_mtu_expires);
 	}
 }
 
-static struct dst_entry * ipv4_dst_check(struct dst_entry * dst, u32 cookie)
+static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 {
 	dst_release(dst);
 	return NULL;
 }
 
-static struct dst_entry * ipv4_dst_reroute(struct dst_entry * dst,
-					   struct sk_buff *skb)
+static struct dst_entry *ipv4_dst_reroute(struct dst_entry *dst,
+					  struct sk_buff *skb)
 {
 	return NULL;
 }
 
-static void ipv4_dst_destroy(struct dst_entry * dst)
+static void ipv4_dst_destroy(struct dst_entry *dst)
 {
 	struct rtable *rt = (struct rtable *) dst;
 	struct inet_peer *peer = rt->peer;
@@ -1097,23 +1121,25 @@
 	else if (fib_lookup(&rt->key, &res) == 0) {
 #ifdef CONFIG_IP_ROUTE_NAT
 		if (res.type == RTN_NAT)
-			src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+			src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
+						RT_SCOPE_UNIVERSE);
 		else
 #endif
 			src = FIB_RES_PREFSRC(res);
 		fib_res_put(&res);
 	} else
-		src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+		src = inet_select_addr(rt->u.dst.dev, rt->rt_gateway,
+					RT_SCOPE_UNIVERSE);
 	memcpy(addr, &src, 4);
 }
 
 #ifdef CONFIG_NET_CLS_ROUTE
 static void set_class_tag(struct rtable *rt, u32 tag)
 {
-	if (!(rt->u.dst.tclassid&0xFFFF))
-		rt->u.dst.tclassid |= tag&0xFFFF;
-	if (!(rt->u.dst.tclassid&0xFFFF0000))
-		rt->u.dst.tclassid |= tag&0xFFFF0000;
+	if (!(rt->u.dst.tclassid & 0xFFFF))
+		rt->u.dst.tclassid |= tag & 0xFFFF;
+	if (!(rt->u.dst.tclassid & 0xFFFF0000))
+		rt->u.dst.tclassid |= tag & 0xFFFF0000;
 }
 #endif
 
@@ -1122,12 +1148,14 @@
 	struct fib_info *fi = res->fi;
 
 	if (fi) {
-		if (FIB_RES_GW(*res) && FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
+		if (FIB_RES_GW(*res) &&
+		    FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
 			rt->rt_gateway = FIB_RES_GW(*res);
-		memcpy(&rt->u.dst.mxlock, fi->fib_metrics, sizeof(fi->fib_metrics));
+		memcpy(&rt->u.dst.mxlock, fi->fib_metrics,
+			sizeof(fi->fib_metrics));
 		if (fi->fib_mtu == 0) {
 			rt->u.dst.pmtu = rt->u.dst.dev->mtu;
-			if (rt->u.dst.mxlock&(1<<RTAX_MTU) &&
+			if (rt->u.dst.mxlock & (1 << RTAX_MTU) &&
 			    rt->rt_gateway != rt->rt_dst &&
 			    rt->u.dst.pmtu > 576)
 				rt->u.dst.pmtu = 576;
@@ -1135,15 +1163,16 @@
 #ifdef CONFIG_NET_CLS_ROUTE
 		rt->u.dst.tclassid = FIB_RES_NH(*res).nh_tclassid;
 #endif
-	} else {
+	} else
 		rt->u.dst.pmtu	= rt->u.dst.dev->mtu;
-	}
+
 	if (rt->u.dst.pmtu > IP_MAX_MTU)
 		rt->u.dst.pmtu = IP_MAX_MTU;
 	if (rt->u.dst.advmss == 0)
-		rt->u.dst.advmss = max(rt->u.dst.dev->mtu-40, ip_rt_min_advmss);
-	if (rt->u.dst.advmss > 65535-40)
-		rt->u.dst.advmss = 65535-40;
+		rt->u.dst.advmss = max(rt->u.dst.dev->mtu - 40,
+					ip_rt_min_advmss);
+	if (rt->u.dst.advmss > 65535 - 40)
+		rt->u.dst.advmss = 65535 - 40;
 
 #ifdef CONFIG_NET_CLS_ROUTE
 #ifdef CONFIG_IP_MULTIPLE_TABLES
@@ -1154,9 +1183,8 @@
         rt->rt_type = res->type;
 }
 
-static int
-ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
-		  u8 tos, struct net_device *dev, int our)
+static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,
+				u8 tos, struct net_device *dev, int our)
 {
 	unsigned hash;
 	struct rtable *rth;
@@ -1177,7 +1205,8 @@
 		if (!LOCAL_MCAST(daddr))
 			goto e_inval;
 		spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
-	} else if (fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag) < 0)
+	} else if (fib_validate_source(saddr, 0, tos, 0,
+					dev, &spec_dst, &itag) < 0)
 		goto e_inval;
 
 	rth = dst_alloc(&ipv4_dst_ops);
@@ -1223,8 +1252,8 @@
 #endif
 
 	in_dev_put(in_dev);
-	hash = rt_hash_code(daddr, saddr^(dev->ifindex<<5), tos);
-	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+	hash = rt_hash_code(daddr, saddr ^ (dev->ifindex << 5), tos);
+	return rt_intern_hash(hash, rth, (struct rtable**) &skb->dst);
 
 e_nobufs:
 	in_dev_put(in_dev);
@@ -1260,24 +1289,22 @@
 	int		err = -EINVAL;
 	int		free_res = 0;
 
-	/*
-	 *	IP on this device is disabled.
-	 */
+	/* IP on this device is disabled. */
 
 	if (!in_dev)
-		return -EINVAL;
+		goto out;
 
-	key.dst = daddr;
-	key.src = saddr;
-	key.tos = tos;
+	key.dst		= daddr;
+	key.src		= saddr;
+	key.tos		= tos;
 #ifdef CONFIG_IP_ROUTE_FWMARK
-	key.fwmark = skb->nfmark;
+	key.fwmark	= skb->nfmark;
 #endif
-	key.iif = dev->ifindex;
-	key.oif = 0;
-	key.scope = RT_SCOPE_UNIVERSE;
+	key.iif		= dev->ifindex;
+	key.oif		= 0;
+	key.scope	= RT_SCOPE_UNIVERSE;
 
-	hash = rt_hash_code(daddr, saddr^(key.iif<<5), tos);
+	hash = rt_hash_code(daddr, saddr ^ (key.iif << 5), tos);
 
 	/* Check for the most weird martians, which can be not detected
 	   by fib_lookup.
@@ -1338,7 +1365,8 @@
 
 	if (res.type == RTN_LOCAL) {
 		int result;
-		result = fib_validate_source(saddr, daddr, tos, loopback_dev.ifindex,
+		result = fib_validate_source(saddr, daddr, tos,
+					     loopback_dev.ifindex,
 					     dev, &spec_dst, &itag);
 		if (result < 0)
 			goto martian_source;
@@ -1360,27 +1388,29 @@
 	out_dev = in_dev_get(FIB_RES_DEV(res));
 	if (out_dev == NULL) {
 		if (net_ratelimit())
-			printk(KERN_CRIT "Bug in ip_route_input_slow(). Please, report\n");
+			printk(KERN_CRIT "Bug in ip_route_input_slow(). "
+					 "Please, report\n");
 		goto e_inval;
 	}
 
-	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev, &spec_dst, &itag);
+	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev,
+				  &spec_dst, &itag);
 	if (err < 0)
 		goto martian_source;
 
 	if (err)
 		flags |= RTCF_DIRECTSRC;
 
-	if (out_dev == in_dev && err && !(flags&(RTCF_NAT|RTCF_MASQ)) &&
-	    (IN_DEV_SHARED_MEDIA(out_dev)
-	     || inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
+	if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
+	    (IN_DEV_SHARED_MEDIA(out_dev) ||
+	     inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
 		flags |= RTCF_DOREDIRECT;
 
 	if (skb->protocol != __constant_htons(ETH_P_IP)) {
 		/* Not IP (i.e. ARP). Do not create route, if it is
 		 * invalid for proxy arp. DNAT routes are always valid.
 		 */
-		if (out_dev == in_dev && !(flags&RTCF_DNAT))
+		if (out_dev == in_dev && !(flags & RTCF_DNAT))
 			goto e_inval;
 	}
 
@@ -1438,16 +1468,17 @@
 		in_dev_put(out_dev);
 	if (free_res)
 		fib_res_put(&res);
-	return err;
+out:	return err;
 
 brd_input:
 	if (skb->protocol != __constant_htons(ETH_P_IP))
 		goto e_inval;
 
-	if (ZERONET(saddr)) {
+	if (ZERONET(saddr))
 		spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK);
-	} else {
-		err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, &itag);
+	else {
+		err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,
+					  &itag);
 		if (err < 0)
 			goto martian_source;
 		if (err)
@@ -1508,7 +1539,8 @@
 martian_destination:
 #ifdef CONFIG_IP_ROUTE_VERBOSE
 	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit())
-		printk(KERN_WARNING "martian destination %u.%u.%u.%u from %u.%u.%u.%u, dev %s\n",
+		printk(KERN_WARNING "martian destination %u.%u.%u.%u from "
+			"%u.%u.%u.%u, dev %s\n",
 			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
 #endif
 e_inval:
@@ -1526,15 +1558,16 @@
 		 *	RFC1812 recommendation, if source is martian,
 		 *	the only hint is MAC header.
 		 */
-		printk(KERN_WARNING "martian source %u.%u.%u.%u from %u.%u.%u.%u, on dev %s\n",
+		printk(KERN_WARNING "martian source %u.%u.%u.%u from "
+			"%u.%u.%u.%u, on dev %s\n",
 			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
 		if (dev->hard_header_len) {
 			int i;
 			unsigned char *p = skb->mac.raw;
 			printk(KERN_WARNING "ll header: ");
-			for (i=0; i<dev->hard_header_len; i++, p++) {
+			for (i = 0; i < dev->hard_header_len; i++, p++) {
 				printk("%02x", *p);
-				if(i<(dev->hard_header_len-1))
+				if (i < (dev->hard_header_len - 1))
 					printk(":");
 			}
 			printk("\n");
@@ -1552,10 +1585,10 @@
 	int iif = dev->ifindex;
 
 	tos &= IPTOS_RT_MASK;
-	hash = rt_hash_code(daddr, saddr^(iif<<5), tos);
+	hash = rt_hash_code(daddr, saddr ^ (iif << 5), tos);
 
 	read_lock(&rt_hash_table[hash].lock);
-	for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
+	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
 		if (rth->key.dst == daddr &&
 		    rth->key.src == saddr &&
 		    rth->key.iif == iif &&
@@ -1597,7 +1630,8 @@
 #endif
 			    ) {
 				read_unlock(&inetdev_lock);
-				return ip_route_input_mc(skb, daddr, saddr, tos, dev, our);
+				return ip_route_input_mc(skb, daddr, saddr,
+							 tos, dev, our);
 			}
 		}
 		read_unlock(&inetdev_lock);
@@ -1622,31 +1656,33 @@
 	int err;
 	u32 tos;
 
-	tos = oldkey->tos & (IPTOS_RT_MASK|RTO_ONLINK);
-	key.dst = oldkey->dst;
-	key.src = oldkey->src;
-	key.tos = tos&IPTOS_RT_MASK;
-	key.iif = loopback_dev.ifindex;
-	key.oif = oldkey->oif;
+	tos		= oldkey->tos & (IPTOS_RT_MASK | RTO_ONLINK);
+	key.dst		= oldkey->dst;
+	key.src		= oldkey->src;
+	key.tos		= tos & IPTOS_RT_MASK;
+	key.iif		= loopback_dev.ifindex;
+	key.oif		= oldkey->oif;
 #ifdef CONFIG_IP_ROUTE_FWMARK
-	key.fwmark = oldkey->fwmark;
+	key.fwmark	= oldkey->fwmark;
 #endif
-	key.scope = (tos&RTO_ONLINK) ? RT_SCOPE_LINK : RT_SCOPE_UNIVERSE;
-	res.fi = NULL;
+	key.scope	= (tos & RTO_ONLINK) ? RT_SCOPE_LINK :
+						RT_SCOPE_UNIVERSE;
+	res.fi		= NULL;
 #ifdef CONFIG_IP_MULTIPLE_TABLES
-	res.r = NULL;
+	res.r		= NULL;
 #endif
 
 	if (oldkey->src) {
-		if (MULTICAST(oldkey->src)
-		    || BADCLASS(oldkey->src)
-		    || ZERONET(oldkey->src))
-			return -EINVAL;
+		err = -EINVAL;
+		if (MULTICAST(oldkey->src) ||
+		    BADCLASS(oldkey->src) ||
+		    ZERONET(oldkey->src))
+			goto out;
 
 		/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
 		dev_out = ip_dev_find(oldkey->src);
 		if (dev_out == NULL)
-			return -EINVAL;
+			goto out;
 
 		/* I removed check for oif == dev_out->oif here.
 		   It was wrong by three reasons:
@@ -1682,23 +1718,27 @@
 	}
 	if (oldkey->oif) {
 		dev_out = dev_get_by_index(oldkey->oif);
+		err = -ENODEV;
 		if (dev_out == NULL)
-			return -ENODEV;
+			goto out;
 		if (__in_dev_get(dev_out) == NULL) {
 			dev_put(dev_out);
-			return -ENODEV;	/* Wrong error code */
+			goto out;	/* Wrong error code */
 		}
 
 		if (LOCAL_MCAST(oldkey->dst) || oldkey->dst == 0xFFFFFFFF) {
 			if (!key.src)
-				key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
+				key.src = inet_select_addr(dev_out, 0,
+								RT_SCOPE_LINK);
 			goto make_route;
 		}
 		if (!key.src) {
 			if (MULTICAST(oldkey->dst))
-				key.src = inet_select_addr(dev_out, 0, key.scope);
+				key.src = inet_select_addr(dev_out, 0,
+								key.scope);
 			else if (!oldkey->dst)
-				key.src = inet_select_addr(dev_out, 0, RT_SCOPE_HOST);
+				key.src = inet_select_addr(dev_out, 0,
+								RT_SCOPE_HOST);
 		}
 	}
 
@@ -1738,13 +1778,15 @@
 			 */
 
 			if (key.src == 0)
-				key.src = inet_select_addr(dev_out, 0, RT_SCOPE_LINK);
+				key.src = inet_select_addr(dev_out, 0,
+							   RT_SCOPE_LINK);
 			res.type = RTN_UNICAST;
 			goto make_route;
 		}
 		if (dev_out)
 			dev_put(dev_out);
-		return -ENETUNREACH;
+		err = -ENETUNREACH;
+		goto out;
 	}
 	free_res = 1;
 
@@ -1771,7 +1813,7 @@
 		fib_select_multipath(&key, &res);
 	else
 #endif
-	if (res.prefixlen==0 && res.type == RTN_UNICAST && key.oif == 0)
+	if (!res.prefixlen && res.type == RTN_UNICAST && !key.oif)
 		fib_select_default(&key, &res);
 
 	if (!key.src)
@@ -1794,11 +1836,11 @@
 	else if (BADCLASS(key.dst) || ZERONET(key.dst))
 		goto e_inval;
 
-	if (dev_out->flags&IFF_LOOPBACK)
+	if (dev_out->flags & IFF_LOOPBACK)
 		flags |= RTCF_LOCAL;
 
 	if (res.type == RTN_BROADCAST) {
-		flags |= RTCF_BROADCAST|RTCF_LOCAL;
+		flags |= RTCF_BROADCAST | RTCF_LOCAL;
 		if (res.fi) {
 			fib_info_put(res.fi);
 			res.fi = NULL;
@@ -1806,7 +1848,8 @@
 	} else if (res.type == RTN_MULTICAST) {
 		flags |= RTCF_MULTICAST|RTCF_LOCAL;
 		read_lock(&inetdev_lock);
-		if (!__in_dev_get(dev_out) || !ip_check_mc(__in_dev_get(dev_out), oldkey->dst))
+		if (!__in_dev_get(dev_out) ||
+		    !ip_check_mc(__in_dev_get(dev_out), oldkey->dst))
 			flags &= ~RTCF_LOCAL;
 		read_unlock(&inetdev_lock);
 		/* If multicast route do not exist use
@@ -1847,19 +1890,20 @@
 
 	rth->u.dst.output=ip_output;
 
-	if (flags&RTCF_LOCAL) {
+	if (flags & RTCF_LOCAL) {
 		rth->u.dst.input = ip_local_deliver;
 		rth->rt_spec_dst = key.dst;
 	}
-	if (flags&(RTCF_BROADCAST|RTCF_MULTICAST)) {
+	if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
 		rth->rt_spec_dst = key.src;
-		if (flags&RTCF_LOCAL && !(dev_out->flags&IFF_LOOPBACK))
+		if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK))
 			rth->u.dst.output = ip_mc_output;
 #ifdef CONFIG_IP_MROUTE
 		if (res.type == RTN_MULTICAST) {
 			struct in_device *in_dev = in_dev_get(dev_out);
 			if (in_dev) {
-				if (IN_DEV_MFORWARD(in_dev) && !LOCAL_MCAST(oldkey->dst)) {
+				if (IN_DEV_MFORWARD(in_dev) &&
+				    !LOCAL_MCAST(oldkey->dst)) {
 					rth->u.dst.input = ip_mr_input;
 					rth->u.dst.output = ip_mc_output;
 				}
@@ -1873,14 +1917,14 @@
 
 	rth->rt_flags = flags;
 
-	hash = rt_hash_code(oldkey->dst, oldkey->src^(oldkey->oif<<5), tos);
+	hash = rt_hash_code(oldkey->dst, oldkey->src ^ (oldkey->oif << 5), tos);
 	err = rt_intern_hash(hash, rth, rp);
 done:
 	if (free_res)
 		fib_res_put(&res);
 	if (dev_out)
 		dev_put(dev_out);
-	return err;
+out:	return err;
 
 e_inval:
 	err = -EINVAL;
@@ -1895,10 +1939,10 @@
 	unsigned hash;
 	struct rtable *rth;
 
-	hash = rt_hash_code(key->dst, key->src^(key->oif<<5), key->tos);
+	hash = rt_hash_code(key->dst, key->src ^ (key->oif << 5), key->tos);
 
 	read_lock_bh(&rt_hash_table[hash].lock);
-	for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
+	for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
 		if (rth->key.dst == key->dst &&
 		    rth->key.src == key->src &&
 		    rth->key.iif == 0 &&
@@ -1906,9 +1950,10 @@
 #ifdef CONFIG_IP_ROUTE_FWMARK
 		    rth->key.fwmark == key->fwmark &&
 #endif
-		    !((rth->key.tos^key->tos)&(IPTOS_RT_MASK|RTO_ONLINK)) &&
-		    ((key->tos&RTO_TPROXY) || !(rth->rt_flags&RTCF_TPROXY))
-		) {
+		    !((rth->key.tos ^ key->tos) &
+			    (IPTOS_RT_MASK | RTO_ONLINK)) &&
+		    ((key->tos & RTO_TPROXY) ||
+		     !(rth->rt_flags & RTCF_TPROXY))) {
 			rth->u.dst.lastuse = jiffies;
 			dst_hold(&rth->u.dst);
 			rth->u.dst.__use++;
@@ -1923,8 +1968,8 @@
 }	
 
 #ifdef CONFIG_RTNETLINK
-
-static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event, int nowait)
+static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
+			int nowait)
 {
 	struct rtable *rt = (struct rtable*)skb->dst;
 	struct rtmsg *r;
@@ -1934,19 +1979,18 @@
 #ifdef CONFIG_IP_MROUTE
 	struct rtattr *eptr;
 #endif
-
 	nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*r));
 	r = NLMSG_DATA(nlh);
 	nlh->nlmsg_flags = (nowait && pid) ? NLM_F_MULTI : 0;
-	r->rtm_family = AF_INET;
-	r->rtm_dst_len = 32;
-	r->rtm_src_len = 0;
-	r->rtm_tos = rt->key.tos;
-	r->rtm_table = RT_TABLE_MAIN;
-	r->rtm_type = rt->rt_type;
-	r->rtm_scope = RT_SCOPE_UNIVERSE;
+	r->rtm_family	 = AF_INET;
+	r->rtm_dst_len	= 32;
+	r->rtm_src_len	= 0;
+	r->rtm_tos	= rt->key.tos;
+	r->rtm_table	= RT_TABLE_MAIN;
+	r->rtm_type	= rt->rt_type;
+	r->rtm_scope	= RT_SCOPE_UNIVERSE;
 	r->rtm_protocol = RTPROT_UNSPEC;
-	r->rtm_flags = (rt->rt_flags&~0xFFFF) | RTM_F_CLONED;
+	r->rtm_flags	= (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
 	if (rt->rt_flags & RTCF_NOTIFY)
 		r->rtm_flags |= RTM_F_NOTIFY;
 	RTA_PUT(skb, RTA_DST, 4, &rt->rt_dst);
@@ -1968,17 +2012,15 @@
 		RTA_PUT(skb, RTA_GATEWAY, 4, &rt->rt_gateway);
 	if (rtnetlink_put_metrics(skb, &rt->u.dst.mxlock) < 0)
 		goto rtattr_failure;
-	ci.rta_lastuse = jiffies - rt->u.dst.lastuse;
-	ci.rta_used = rt->u.dst.__use;
-	ci.rta_clntref = atomic_read(&rt->u.dst.__refcnt);
+	ci.rta_lastuse	= jiffies - rt->u.dst.lastuse;
+	ci.rta_used	= rt->u.dst.__use;
+	ci.rta_clntref	= atomic_read(&rt->u.dst.__refcnt);
 	if (rt->u.dst.expires)
 		ci.rta_expires = rt->u.dst.expires - jiffies;
 	else
 		ci.rta_expires = 0;
-	ci.rta_error = rt->u.dst.error;
-	ci.rta_id = 0;
-	ci.rta_ts = 0;
-	ci.rta_tsage = 0;
+	ci.rta_error	= rt->u.dst.error;
+	ci.rta_id	= ci.rta_ts = ci.rta_tsage = 0;
 	if (rt->peer) {
 		ci.rta_id = rt->peer->ip_id_count;
 		if (rt->peer->tcp_ts_stamp) {
@@ -1994,7 +2036,8 @@
 #ifdef CONFIG_IP_MROUTE
 		u32 dst = rt->rt_dst;
 
-		if (MULTICAST(dst) && !LOCAL_MCAST(dst) && ipv4_devconf.mc_forwarding) {
+		if (MULTICAST(dst) && !LOCAL_MCAST(dst) &&
+		    ipv4_devconf.mc_forwarding) {
 			int err = ipmr_get_route(skb, r, nowait);
 			if (err <= 0) {
 				if (!nowait) {
@@ -2009,9 +2052,7 @@
 			}
 		} else
 #endif
-		{
 			RTA_PUT(skb, RTA_IIF, sizeof(int), &rt->key.iif);
-		}
 	}
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -2031,12 +2072,12 @@
 	u32 dst = 0;
 	u32 src = 0;
 	int iif = 0;
-	int err;
+	int err = -ENOBUFS;
 	struct sk_buff *skb;
 
 	skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
-	if (skb == NULL)
-		return -ENOBUFS;
+	if (!skb)
+		goto out;
 
 	/* Reserve room for dummy headers, this skb can pass
 	   through good chunk of routing engine.
@@ -2044,20 +2085,20 @@
 	skb->mac.raw = skb->data;
 	skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
 
-	if (rta[RTA_SRC-1])
-		memcpy(&src, RTA_DATA(rta[RTA_SRC-1]), 4);
-	if (rta[RTA_DST-1])
-		memcpy(&dst, RTA_DATA(rta[RTA_DST-1]), 4);
-	if (rta[RTA_IIF-1])
-		memcpy(&iif, RTA_DATA(rta[RTA_IIF-1]), sizeof(int));
+	if (rta[RTA_SRC - 1])
+		memcpy(&src, RTA_DATA(rta[RTA_SRC - 1]), 4);
+	if (rta[RTA_DST - 1])
+		memcpy(&dst, RTA_DATA(rta[RTA_DST - 1]), 4);
+	if (rta[RTA_IIF - 1])
+		memcpy(&iif, RTA_DATA(rta[RTA_IIF - 1]), sizeof(int));
 
 	if (iif) {
-		struct net_device *dev;
-		dev = __dev_get_by_index(iif);
+		struct net_device *dev = __dev_get_by_index(iif);
+		err = -ENODEV;
 		if (!dev)
-			return -ENODEV;
-		skb->protocol = __constant_htons(ETH_P_IP);
-		skb->dev = dev;
+			goto out;
+		skb->protocol	= __constant_htons(ETH_P_IP);
+		skb->dev	= dev;
 		local_bh_disable();
 		err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
 		local_bh_enable();
@@ -2066,13 +2107,13 @@
 			err = -rt->u.dst.error;
 	} else {
 		int oif = 0;
-		if (rta[RTA_OIF-1])
-			memcpy(&oif, RTA_DATA(rta[RTA_OIF-1]), sizeof(int));
+		if (rta[RTA_OIF - 1])
+			memcpy(&oif, RTA_DATA(rta[RTA_OIF - 1]), sizeof(int));
 		err = ip_route_output(&rt, dst, src, rtm->rtm_tos, oif);
 	}
 	if (err) {
 		kfree_skb(skb);
-		return err;
+		goto out;
 	}
 
 	skb->dst = &rt->u.dst;
@@ -2081,19 +2122,21 @@
 
 	NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid;
 
-	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq, RTM_NEWROUTE, 0);
-	if (err == 0)
-		return 0;
-	if (err < 0)
-		return -EMSGSIZE;
+	err = rt_fill_info(skb, NETLINK_CB(in_skb).pid, nlh->nlmsg_seq,
+				RTM_NEWROUTE, 0);
+	if (!err)
+		goto out;
+	if (err < 0) {
+		err = -EMSGSIZE;
+		goto out;
+	}
 
 	err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT);
-	if (err < 0)
-		return err;
-	return 0;
+	if (err > 0)
+		err = 0;
+out:	return err;
 }
 
-
 int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
 {
 	struct rtable *rt;
@@ -2102,17 +2145,19 @@
 
 	s_h = cb->args[0];
 	s_idx = idx = cb->args[1];
-	for (h=0; h <= rt_hash_mask; h++) {
+	for (h = 0; h <= rt_hash_mask; h++) {
 		if (h < s_h) continue;
 		if (h > s_h)
 			s_idx = 0;
 		read_lock_bh(&rt_hash_table[h].lock);
-		for (rt = rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
+		for (rt = rt_hash_table[h].chain, idx = 0; rt;
+		     rt = rt->u.rt_next, idx++) {
 			if (idx < s_idx)
 				continue;
 			skb->dst = dst_clone(&rt->u.dst);
 			if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
-					 cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
+					 cb->nlh->nlmsg_seq,
+					 RTM_NEWROUTE, 1) <= 0) {
 				dst_release(xchg(&skb->dst, NULL));
 				read_unlock_bh(&rt_hash_table[h].lock);
 				goto done;
@@ -2135,91 +2180,181 @@
 	rt_cache_flush(0);
 }
 
-
-
 #ifdef CONFIG_SYSCTL
-
 static int flush_delay;
 
-static
-int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write, struct file * filp,
-			      void *buffer, size_t *lenp)
+static int ipv4_sysctl_rtcache_flush(ctl_table *ctl, int write,
+					struct file *filp, void *buffer,
+					size_t *lenp)
 {
 	if (write) {
 		proc_dointvec(ctl, write, filp, buffer, lenp);
 		rt_cache_flush(flush_delay);
 		return 0;
-	} else
-		return -EINVAL;
+	} 
+
+	return -EINVAL;
 }
 
-static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name, int nlen,
-			 void *oldval, size_t *oldlenp,
-			 void *newval, size_t newlen, 
-			 void **context)
+static int ipv4_sysctl_rtcache_flush_strategy(ctl_table *table, int *name,
+						int nlen, void *oldval,
+						size_t *oldlenp, void *newval,
+						size_t newlen, void **context)
 {
 	int delay;
 	if (newlen != sizeof(int))
 		return -EINVAL;
-	if (get_user(delay,(int *)newval))
+	if (get_user(delay, (int *)newval))
 		return -EFAULT; 
 	rt_cache_flush(delay); 
 	return 0;
 }
 
 ctl_table ipv4_route_table[] = {
-        {NET_IPV4_ROUTE_FLUSH, "flush",
-         &flush_delay, sizeof(int), 0644, NULL,
-         &ipv4_sysctl_rtcache_flush, &ipv4_sysctl_rtcache_flush_strategy },
-	{NET_IPV4_ROUTE_MIN_DELAY, "min_delay",
-         &ip_rt_min_delay, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_MAX_DELAY, "max_delay",
-         &ip_rt_max_delay, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_GC_THRESH, "gc_thresh",
-         &ipv4_dst_ops.gc_thresh, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_MAX_SIZE, "max_size",
-         &ip_rt_max_size, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_GC_MIN_INTERVAL, "gc_min_interval",
-         &ip_rt_gc_min_interval, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_GC_TIMEOUT, "gc_timeout",
-         &ip_rt_gc_timeout, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_GC_INTERVAL, "gc_interval",
-         &ip_rt_gc_interval, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_REDIRECT_LOAD, "redirect_load",
-         &ip_rt_redirect_load, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_REDIRECT_NUMBER, "redirect_number",
-         &ip_rt_redirect_number, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_REDIRECT_SILENCE, "redirect_silence",
-         &ip_rt_redirect_silence, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_ERROR_COST, "error_cost",
-         &ip_rt_error_cost, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_ERROR_BURST, "error_burst",
-         &ip_rt_error_burst, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_GC_ELASTICITY, "gc_elasticity",
-         &ip_rt_gc_elasticity, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_MTU_EXPIRES, "mtu_expires",
-         &ip_rt_mtu_expires, sizeof(int), 0644, NULL,
-         &proc_dointvec_jiffies, &sysctl_jiffies},
-	{NET_IPV4_ROUTE_MIN_PMTU, "min_pmtu",
-         &ip_rt_min_pmtu, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	{NET_IPV4_ROUTE_MIN_ADVMSS, "min_adv_mss",
-         &ip_rt_min_advmss, sizeof(int), 0644, NULL,
-         &proc_dointvec},
-	 {0}
+        {
+		ctl_name:	NET_IPV4_ROUTE_FLUSH,
+		procname:	"flush",
+		data:		&flush_delay,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&ipv4_sysctl_rtcache_flush,
+		strategy:	&ipv4_sysctl_rtcache_flush_strategy,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MIN_DELAY,
+		procname:	"min_delay",
+		data:		&ip_rt_min_delay,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MAX_DELAY,
+		procname:	"max_delay",
+		data:		&ip_rt_max_delay,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_THRESH,
+		procname:	"gc_thresh",
+		data:		&ipv4_dst_ops.gc_thresh,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MAX_SIZE,
+		procname:	"max_size",
+		data:		&ip_rt_max_size,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_MIN_INTERVAL,
+		procname:	"gc_min_interval",
+		data:		&ip_rt_gc_min_interval,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_TIMEOUT,
+		procname:	"gc_timeout",
+		data:		&ip_rt_gc_timeout,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_INTERVAL,
+		procname:	"gc_interval",
+		data:		&ip_rt_gc_interval,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_REDIRECT_LOAD,
+		procname:	"redirect_load",
+		data:		&ip_rt_redirect_load,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_REDIRECT_NUMBER,
+		procname:	"redirect_number",
+		data:		&ip_rt_redirect_number,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_REDIRECT_SILENCE,
+		procname:	"redirect_silence",
+		data:		&ip_rt_redirect_silence,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_ERROR_COST,
+		procname:	"error_cost",
+		data:		&ip_rt_error_cost,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_ERROR_BURST,
+		procname:	"error_burst",
+		data:		&ip_rt_error_burst,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_GC_ELASTICITY,
+		procname:	"gc_elasticity",
+		data:		&ip_rt_gc_elasticity,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MTU_EXPIRES,
+		procname:	"mtu_expires",
+		data:		&ip_rt_mtu_expires,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec_jiffies,
+		strategy:	&sysctl_jiffies,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MIN_PMTU,
+		procname:	"min_pmtu",
+		data:		&ip_rt_min_pmtu,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	{
+		ctl_name:	NET_IPV4_ROUTE_MIN_ADVMSS,
+		procname:	"min_adv_mss",
+		data:		&ip_rt_min_advmss,
+		maxlen:		sizeof(int),
+		mode:		0644,
+		proc_handler:	&proc_dointvec,
+	},
+	 { 0 }
 };
 #endif
 
@@ -2229,13 +2364,13 @@
 static int ip_rt_acct_read(char *buffer, char **start, off_t offset,
 			   int length, int *eof, void *data)
 {
-	*start=buffer;
+	*start = buffer;
 
-	if ((offset&3) || (length&3))
+	if ((offset & 3) || (length & 3))
 		return -EIO;
 
-	if (offset + length >= sizeof(struct ip_rt_acct)*256) {
-		length = sizeof(struct ip_rt_acct)*256 - offset;
+	if (offset + length >= sizeof(struct ip_rt_acct) * 256) {
+		length = sizeof(struct ip_rt_acct) * 256 - offset;
 		*eof = 1;
 	}
 	if (length > 0) {
@@ -2247,9 +2382,9 @@
 #ifdef CONFIG_SMP
 		if (smp_num_cpus > 1 || cpu_logical_map(0) != 0) {
 			int i;
-			int cnt = length/4;
+			int cnt = length / 4;
 
-			for (i=0; i<smp_num_cpus; i++) {
+			for (i = 0; i < smp_num_cpus; i++) {
 				int cpu = cpu_logical_map(i);
 				int k;
 
@@ -2257,9 +2392,9 @@
 					continue;
 
 				src = (u32*)(((u8*)ip_rt_acct) + offset +
-					     cpu*256*sizeof(struct ip_rt_acct));
+					cpu * 256 * sizeof(struct ip_rt_acct));
 
-				for (k=0; k<cnt; k++)
+				for (k = 0; k < cnt; k++)
 					dst[k] += src[k];
 			}
 		}
@@ -2275,13 +2410,13 @@
 	int i, order, goal;
 
 #ifdef CONFIG_NET_CLS_ROUTE
-	for (order=0;
-	     (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*NR_CPUS; order++)
+	for (order = 0;
+	     (PAGE_SIZE << order) < 256 * sizeof(ip_rt_acct) * NR_CPUS; order++)
 		/* NOTHING */;
 	ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order);
 	if (!ip_rt_acct)
 		panic("IP: failed to allocate ip_rt_acct\n");
-	memset(ip_rt_acct, 0, PAGE_SIZE<<order);
+	memset(ip_rt_acct, 0, PAGE_SIZE << order);
 #endif
 
 	ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
@@ -2300,7 +2435,7 @@
 	do {
 		rt_hash_mask = (1UL << order) * PAGE_SIZE /
 			sizeof(struct rt_hash_bucket);
-		while (rt_hash_mask & (rt_hash_mask-1))
+		while (rt_hash_mask & (rt_hash_mask - 1))
 			rt_hash_mask--;
 		rt_hash_table = (struct rt_hash_bucket *)
 			__get_free_pages(GFP_ATOMIC, order);
@@ -2311,9 +2446,9 @@
 
 	printk("IP: routing cache hash table of %u buckets, %ldKbytes\n",
 	       rt_hash_mask,
-	       (long) (rt_hash_mask*sizeof(struct rt_hash_bucket))/1024);
+	       (long) (rt_hash_mask * sizeof(struct rt_hash_bucket)) / 1024);
 
-	for (rt_hash_log=0; (1<<rt_hash_log) != rt_hash_mask; rt_hash_log++)
+	for (rt_hash_log = 0; (1 << rt_hash_log) != rt_hash_mask; rt_hash_log++)
 		/* NOTHING */;
 
 	rt_hash_mask--;
@@ -2322,8 +2457,8 @@
 		rt_hash_table[i].chain = NULL;
 	}
 
-	ipv4_dst_ops.gc_thresh = (rt_hash_mask+1);
-	ip_rt_max_size = (rt_hash_mask+1)*16;
+	ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);
+	ip_rt_max_size = (rt_hash_mask + 1) * 16;
 
 	devinet_init();
 	ip_fib_init();
@@ -2334,8 +2469,8 @@
 	/* All the timers, started at system startup tend
 	   to synchronize. Perturb it a bit.
 	 */
-	rt_periodic_timer.expires = jiffies + net_random()%ip_rt_gc_interval
-		+ ip_rt_gc_interval;
+	rt_periodic_timer.expires = jiffies + net_random() % ip_rt_gc_interval +
+					ip_rt_gc_interval;
 	add_timer(&rt_periodic_timer);
 
 	proc_net_create ("rt_cache", 0, rt_cache_get_info);
diff -urN linux-2.4.5-pre2/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c
--- linux-2.4.5-pre2/net/ipv4/syncookies.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipv4/syncookies.c	Mon Dec  3 22:43:26 2001
@@ -9,7 +9,7 @@
  *      as published by the Free Software Foundation; either version
  *      2 of the License, or (at your option) any later version.
  * 
- *  $Id: syncookies.c,v 1.13 2001/02/13 01:17:26 davem Exp $
+ *  $Id: syncookies.c,v 1.14 2001/05/05 01:01:55 davem Exp $
  *
  *  Missing: IPv6 support. 
  */
@@ -31,14 +31,14 @@
  * Unresolved Issues: HIPPI with a 64k MSS is not well supported.
  */
 static __u16 const msstab[] = {
-	64-1,
-	256-1,	
-	512-1,
-	536-1,
-	1024-1,	
-	1440-1,
-	1460-1,
-	4312-1,
+	64 - 1,
+	256 - 1,	
+	512 - 1,
+	536 - 1,
+	1024 - 1,	
+	1440 - 1,
+	1460 - 1,
+	4312 - 1,
 	(__u16)-1
 };
 /* The number doesn't include the -1 terminator */
@@ -48,24 +48,23 @@
  * Generate a syncookie.  mssp points to the mss, which is returned
  * rounded down to the value encoded in the cookie.
  */
-__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, 
-			      __u16 *mssp)
+__u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
 {
 	int mssind;
 	const __u16 mss = *mssp;
 
 	tcp_lastsynq_overflow = jiffies;
 	/* XXX sort msstab[] by probability?  Binary search? */
-	for (mssind = 0; mss > msstab[mssind+1]; mssind++)
+	for (mssind = 0; mss > msstab[mssind + 1]; mssind++)
 		;
-	*mssp = msstab[mssind]+1;
+	*mssp = msstab[mssind] + 1;
 
 	NET_INC_STATS_BH(SyncookiesSent);
 
 	return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr,
 				     skb->h.th->source, skb->h.th->dest,
 				     ntohl(skb->h.th->seq),
-				     jiffies / (HZ*60), mssind);
+				     jiffies / (HZ * 60), mssind);
 }
 
 /* 
@@ -91,16 +90,16 @@
 	mssind = check_tcp_syn_cookie(cookie,
 				      skb->nh.iph->saddr, skb->nh.iph->daddr,
 				      skb->h.th->source, skb->h.th->dest,
-				      seq, jiffies/(HZ*60), COUNTER_TRIES);
+				      seq, jiffies / (HZ * 60), COUNTER_TRIES);
 
-	return mssind < NUM_MSS ? msstab[mssind]+1 : 0;
+	return mssind < NUM_MSS ? msstab[mssind] + 1 : 0;
 }
 
 extern struct or_calltable or_ipv4;
 
-static inline struct sock *
-get_cookie_sock(struct sock *sk, struct sk_buff *skb, struct open_request *req,
-		struct dst_entry *dst)
+static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
+					   struct open_request *req,
+					   struct dst_entry *dst)
 {
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	struct sock *child;
@@ -114,41 +113,40 @@
 	return child;
 }
 
-struct sock *
-cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
+struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
+			     struct ip_options *opt)
 {
-	__u32 cookie = ntohl(skb->h.th->ack_seq)-1; 
+	__u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 
+	struct sock *ret = sk;
 	struct open_request *req; 
 	int mss; 
 	struct rtable *rt; 
 	__u8 rcv_wscale;
 
-	if (!sysctl_tcp_syncookies)
-		return sk;
-	if (!skb->h.th->ack)
-		return sk; 
+	if (!sysctl_tcp_syncookies || !skb->h.th->ack)
+		goto out;
 
 	mss = cookie_check(skb, cookie);
-	if (mss == 0) {
+	if (!mss) {
 	 	NET_INC_STATS_BH(SyncookiesFailed);
-		return sk;
+		goto out;
 	}
 
 	NET_INC_STATS_BH(SyncookiesRecv);
 
 	req = tcp_openreq_alloc();
-	if (req == NULL)
-		return NULL;	
-
-	req->rcv_isn = htonl(skb->h.th->seq)-1;
-	req->snt_isn = cookie; 
-	req->mss = mss;
- 	req->rmt_port = skb->h.th->source;
+	ret = NULL;
+	if (!req)
+		goto out;
+
+	req->rcv_isn		= htonl(skb->h.th->seq) - 1;
+	req->snt_isn		= cookie; 
+	req->mss		= mss;
+ 	req->rmt_port		= skb->h.th->source;
 	req->af.v4_req.loc_addr = skb->nh.iph->daddr;
 	req->af.v4_req.rmt_addr = skb->nh.iph->saddr;
-	req->class = &or_ipv4; /* for savety */
-
-	req->af.v4_req.opt = NULL;
+	req->class		= &or_ipv4; /* for savety */
+	req->af.v4_req.opt	= NULL;
 
 	/* We throwed the options of the initial SYN away, so we hope
 	 * the ACK carries the same options again (see RFC1122 4.2.3.8)
@@ -166,9 +164,9 @@
 	}
 
 	req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0;
-	req->wscale_ok = req->sack_ok = 0; 
-	req->expires = 0UL; 
-	req->retrans = 0; 
+	req->wscale_ok	= req->sack_ok = 0; 
+	req->expires	= 0UL; 
+	req->retrans	= 0; 
 	
 	/*
 	 * We need to lookup the route here to get at the correct
@@ -183,18 +181,18 @@
 			    sk->protinfo.af_inet.tos | RTO_CONN,
 			    0)) { 
 		tcp_openreq_free(req);
-		return NULL; 
+		goto out; 
 	}
 
 	/* Try to redo what tcp_v4_send_synack did. */
 	req->window_clamp = rt->u.dst.window;  
-	tcp_select_initial_window(tcp_full_space(sk),req->mss,
+	tcp_select_initial_window(tcp_full_space(sk), req->mss,
 				  &req->rcv_wnd, &req->window_clamp, 
 				  0, &rcv_wscale);
 	/* BTW win scale with syncookies is 0 by definition */
-	req->rcv_wscale = rcv_wscale; 
+	req->rcv_wscale	  = rcv_wscale; 
 
-	return get_cookie_sock(sk, skb, req, &rt->u.dst);
+	ret = get_cookie_sock(sk, skb, req, &rt->u.dst);
+out:	return ret;
 }
-
 #endif
diff -urN linux-2.4.5-pre2/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- linux-2.4.5-pre2/net/ipv4/tcp.c	Mon Dec  3 22:43:16 2001
+++ linux/net/ipv4/tcp.c	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp.c,v 1.204 2001/05/01 23:07:49 davem Exp $
+ * Version:	$Id: tcp.c,v 1.205 2001/05/05 22:25:30 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -2357,7 +2357,7 @@
 		break;
 	case TCP_LINGER2:
 		val = tp->linger2;
-		if (val > 0)
+		if (val >= 0)
 			val = (val ? : sysctl_tcp_fin_timeout)/HZ;
 		break;
 	case TCP_DEFER_ACCEPT:
diff -urN linux-2.4.5-pre2/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- linux-2.4.5-pre2/net/ipv4/tcp_input.c	Wed Apr 25 14:57:39 2001
+++ linux/net/ipv4/tcp_input.c	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_input.c,v 1.228 2001/04/20 20:46:19 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.229 2001/05/13 18:14:46 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -2527,11 +2527,11 @@
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 	int eaten = -1;
 
+	if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
+		goto drop;
+
 	th = skb->h.th;
 	__skb_pull(skb, th->doff*4);
-
-        if (skb->len == 0 && !th->fin)
-		goto drop;
 
 	TCP_ECN_accept_cwr(tp, skb);
 
diff -urN linux-2.4.5-pre2/net/ipv6/Config.in linux/net/ipv6/Config.in
--- linux-2.4.5-pre2/net/ipv6/Config.in	Mon May 22 09:50:55 2000
+++ linux/net/ipv6/Config.in	Mon Dec  3 22:43:26 2001
@@ -1,10 +1,6 @@
 #
 # IPv6 configuration
 # 
-bool '    IPv6: enable EUI-64 token format' CONFIG_IPV6_EUI64
-if [ "$CONFIG_IPV6_EUI64" = "y" ]; then
-   bool '      IPv6: disable provider based addresses' CONFIG_IPV6_NO_PB
-fi
 if [ "$CONFIG_NETLINK" = "y" ]; then
    if [ "$CONFIG_RTNETLINK" = "n" ]; then
       bool '    IPv6: routing messages via old netlink' CONFIG_IPV6_NETLINK
diff -urN linux-2.4.5-pre2/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- linux-2.4.5-pre2/net/ipv6/addrconf.c	Mon Dec  3 22:43:16 2001
+++ linux/net/ipv6/addrconf.c	Mon Dec  3 22:43:26 2001
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: addrconf.c,v 1.64 2001/05/01 23:05:47 davem Exp $
+ *	$Id: addrconf.c,v 1.65 2001/05/03 07:02:47 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -643,14 +643,8 @@
 	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
 		return;
 
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_inc(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
-	ipv6_dev_mc_inc(dev, &maddr);
-#endif
 }
 
 static void addrconf_leave_solict(struct net_device *dev, struct in6_addr *addr)
@@ -660,18 +654,11 @@
 	if (dev->flags&(IFF_LOOPBACK|IFF_NOARP))
 		return;
 
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_dec(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
-	ipv6_dev_mc_dec(dev, &maddr);
-#endif
 }
 
 
-#ifdef CONFIG_IPV6_EUI64
 static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
 {
 	switch (dev->type) {
@@ -706,7 +693,6 @@
 	read_unlock_bh(&idev->lock);
 	return err;
 }
-#endif
 
 /*
  *	Add prefix route.
@@ -880,7 +866,6 @@
 
 		plen = pinfo->prefix_len >> 3;
 
-#ifdef CONFIG_IPV6_EUI64
 		if (pinfo->prefix_len == 64) {
 			memcpy(&addr, &pinfo->prefix, 8);
 			if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
@@ -890,15 +875,6 @@
 			}
 			goto ok;
 		}
-#endif
-#ifndef CONFIG_IPV6_NO_PB
-		if (pinfo->prefix_len == ((sizeof(struct in6_addr) - dev->addr_len)<<3)) {
-			memcpy(&addr, &pinfo->prefix, plen);
-			memcpy(addr.s6_addr + plen, dev->dev_addr,
-			       dev->addr_len);
-			goto ok;
-		}
-#endif
 		printk(KERN_DEBUG "IPv6 addrconf: prefix with wrong length %d\n", pinfo->prefix_len);
 		in6_dev_put(in6_dev);
 		return;
@@ -1228,7 +1204,6 @@
 	if (idev == NULL)
 		return;
 
-#ifdef CONFIG_IPV6_EUI64
 	memset(&addr, 0, sizeof(struct in6_addr));
 
 	addr.s6_addr[0] = 0xFE;
@@ -1236,18 +1211,6 @@
 
 	if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0)
 		addrconf_add_linklocal(idev, &addr);
-#endif
-
-#ifndef CONFIG_IPV6_NO_PB
-	memset(&addr, 0, sizeof(struct in6_addr));
-
-	addr.s6_addr[0] = 0xFE;
-	addr.s6_addr[1] = 0x80;
-
-	memcpy(addr.s6_addr + (sizeof(struct in6_addr) - dev->addr_len), 
-	       dev->dev_addr, dev->addr_len);
-	addrconf_add_linklocal(idev, &addr);
-#endif
 }
 
 static void addrconf_sit_config(struct net_device *dev)
@@ -1518,14 +1481,8 @@
 
 	/* send a neighbour solicitation for our addr */
 	memset(&unspec, 0, sizeof(unspec));
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(&ifp->addr, &mcaddr);
+	addrconf_addr_solict_mult(&ifp->addr, &mcaddr);
 	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
-#endif
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(&ifp->addr, &mcaddr);
-	ndisc_send_ns(ifp->idev->dev, NULL, &ifp->addr, &mcaddr, &unspec);
-#endif
 
 	in6_ifa_put(ifp);
 }
diff -urN linux-2.4.5-pre2/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- linux-2.4.5-pre2/net/ipv6/ndisc.c	Thu Apr 26 22:17:26 2001
+++ linux/net/ipv6/ndisc.c	Mon Dec  3 22:43:26 2001
@@ -21,6 +21,7 @@
  *	Janos Farkas			:	kmalloc failure checks
  *	Alexey Kuznetsov		:	state machine reworked
  *						and moved to net/core.
+ *	Pekka Savola			:	RFC2461 validation
  */
 
 /* Set to 3 to get tracing... */
@@ -242,14 +243,8 @@
 
 	if (dev == NULL || __in6_dev_get(dev) == NULL)
 		return -EINVAL;
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_inc(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
-	ipv6_dev_mc_inc(dev, &maddr);
-#endif
 	return 0;
 }
 
@@ -261,14 +256,8 @@
 
 	if (dev == NULL || __in6_dev_get(dev) == NULL)
 		return;
-#ifndef CONFIG_IPV6_NO_PB
-	addrconf_addr_solict_mult_old(addr, &maddr);
-	ipv6_dev_mc_dec(dev, &maddr);
-#endif
-#ifdef CONFIG_IPV6_EUI64
-	addrconf_addr_solict_mult_new(addr, &maddr);
+	addrconf_addr_solict_mult(addr, &maddr);
 	ipv6_dev_mc_dec(dev, &maddr);
-#endif
 }
 
 
@@ -393,6 +382,12 @@
 	int err;
 	int send_llinfo;
 
+	if (saddr == NULL) {
+		if (ipv6_get_lladdr(dev, &addr_buf))
+			return;
+		saddr = &addr_buf;
+	}
+
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 	send_llinfo = dev->addr_len && ipv6_addr_type(saddr) != IPV6_ADDR_ANY;
 	if (send_llinfo)
@@ -405,14 +400,6 @@
 		return;
 	}
 
-	if (saddr == NULL) {
-		if (ipv6_get_lladdr(dev, &addr_buf)) {
-			kfree_skb(skb);
-			return;
-		}
-		saddr = &addr_buf;
-	}
-
 	if (ndisc_build_ll_hdr(skb, dev, daddr, neigh, len) == 0) {
 		kfree_skb(skb);
 		return;
@@ -550,14 +537,8 @@
 		neigh_app_ns(neigh);
 #endif
 	} else {
-#ifdef CONFIG_IPV6_EUI64
-		addrconf_addr_solict_mult_new(target, &mcaddr);
+		addrconf_addr_solict_mult(target, &mcaddr);
 		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
-#endif
-#ifndef CONFIG_IPV6_NO_PB
-		addrconf_addr_solict_mult_old(target, &mcaddr);
-		ndisc_send_ns(dev, NULL, target, &mcaddr, saddr);
-#endif
 	}
 }
 
@@ -581,9 +562,9 @@
 
 	optlen = (skb->tail - skb->h.raw) - sizeof(struct ra_msg);
 
-	if (skb->nh.ipv6h->hop_limit != 255) {
-		printk(KERN_INFO
-		       "NDISC: fake router advertisment received\n");
+	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP RA: source address is not linklocal\n");
 		return;
 	}
 
@@ -756,13 +737,9 @@
 	int on_link = 0;
 	int optlen;
 
-	if (skb->nh.ipv6h->hop_limit != 255) {
-		printk(KERN_WARNING "NDISC: fake ICMP redirect received\n");
-		return;
-	}
-
 	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
-		printk(KERN_WARNING "ICMP redirect: source address is not linklocal\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect: source address is not linklocal\n");
 		return;
 	}
 
@@ -770,7 +747,8 @@
 	optlen -= sizeof(struct icmp6hdr) + 2 * sizeof(struct in6_addr);
 
 	if (optlen < 0) {
-		printk(KERN_WARNING "ICMP redirect: packet too small\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect: packet too small\n");
 		return;
 	}
 
@@ -779,14 +757,16 @@
 	dest = target + 1;
 
 	if (ipv6_addr_type(dest) & IPV6_ADDR_MULTICAST) {
-		printk(KERN_WARNING "ICMP redirect for multicast addr\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect for multicast addr\n");
 		return;
 	}
 
 	if (ipv6_addr_cmp(dest, target) == 0) {
 		on_link = 1;
 	} else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) {
-		printk(KERN_WARNING "ICMP redirect: target address is not linklocal\n");
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP redirect: target address is not linklocal\n");
 		return;
 	}
 
@@ -798,6 +778,11 @@
 		return;
 	}
 
+	/* XXX: RFC2461 8.1: 
+	 *	The IP source address of the Redirect MUST be the same as the current
+	 *	first-hop router for the specified ICMP Destination Address.
+	 */
+		
 	/* passed validation tests */
 
 	/*
@@ -974,8 +959,52 @@
 
 	__skb_push(skb, skb->data-skb->h.raw);
 
+	if (skb->nh.ipv6h->hop_limit != 255) {
+		if (net_ratelimit())
+			printk(KERN_WARNING
+			       "ICMP NDISC: fake message with non-255 Hop Limit received: %d\n",
+			       		skb->nh.ipv6h->hop_limit);
+		return 0;
+	}
+
+	if (msg->icmph.icmp6_code != 0) {
+		if (net_ratelimit())
+			printk(KERN_WARNING "ICMP NDISC: code is not zero\n");
+		return 0;
+	}
+
+	/* XXX: RFC2461 Validation of [all ndisc messages]:
+	 *	All included ndisc options MUST be of non-zero length
+	 *	(Some checking in ndisc_find_option)
+	 */
+
 	switch (msg->icmph.icmp6_type) {
 	case NDISC_NEIGHBOUR_SOLICITATION:
+		/* XXX: import nd_neighbor_solicit from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8+16) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NS: packet too short\n");
+			return 0;
+		}
+
+		if (ipv6_addr_type(&msg->target)&IPV6_ADDR_MULTICAST) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NS: target address is multicast\n");
+			return 0;
+		}
+
+		/* XXX: RFC2461 7.1.1:
+		 * 	If the IP source address is the unspecified address, there
+		 *	MUST NOT be source link-layer address option in the message.
+		 *
+		 *	NOTE! Linux kernel < 2.4.4 broke this rule.
+		 */
+		 	
+		/* XXX: RFC2461 7.1.1:
+		 *	If the IP source address is the unspecified address, the IP
+      		 *	destination address MUST be a solicited-node multicast address.
+		 */
+
 		if ((ifp = ipv6_get_ifaddr(&msg->target, dev)) != NULL) {
 			int addr_type = ipv6_addr_type(saddr);
 
@@ -1010,7 +1039,9 @@
 
 				ipv6_addr_all_nodes(&maddr);
 				ndisc_send_na(dev, NULL, &maddr, &ifp->addr, 
-					      ifp->idev->cnf.forwarding, 0, 1, 1);
+					      ifp->idev->cnf.forwarding, 0, 
+					      ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1, 
+					      1);
 				in6_ifa_put(ifp);
 				return 0;
 			}
@@ -1032,7 +1063,9 @@
 
 				if (neigh) {
 					ndisc_send_na(dev, neigh, saddr, &ifp->addr, 
-						      ifp->idev->cnf.forwarding, 1, inc, inc);
+						      ifp->idev->cnf.forwarding, 1, 
+						      ipv6_addr_type(&ifp->addr)&IPV6_ADDR_ANYCAST ? 0 : 1, 
+						      1);
 					neigh_release(neigh);
 				}
 			}
@@ -1059,7 +1092,7 @@
 
 					if (neigh) {
 						ndisc_send_na(dev, neigh, saddr, &msg->target,
-							      0, 1, 0, inc);
+							      0, 1, 0, 1);
 						neigh_release(neigh);
 					}
 				} else {
@@ -1077,11 +1110,25 @@
 		return 0;
 
 	case NDISC_NEIGHBOUR_ADVERTISEMENT:
+		/* XXX: import nd_neighbor_advert from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 16+8 ) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP NA: packet too short\n");
+			return 0;
+		}
+
+		if (ipv6_addr_type(&msg->target)&IPV6_ADDR_MULTICAST) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "NDISC NA: target address is multicast\n");
+			return 0;
+		}
+
 		if ((ipv6_addr_type(daddr)&IPV6_ADDR_MULTICAST) &&
 		    msg->icmph.icmp6_solicited) {
 			ND_PRINTK0("NDISC: solicited NA is multicasted\n");
 			return 0;
 		}
+		
 		if ((ifp = ipv6_get_ifaddr(&msg->target, dev))) {
 			if (ifp->flags & IFA_F_TENTATIVE) {
 				addrconf_dad_failure(ifp);
@@ -1092,7 +1139,7 @@
 			   about it. It could be misconfiguration, or
 			   an smart proxy agent tries to help us :-)
 			 */
-			ND_PRINTK0("%s: someone avertise our address!\n",
+			ND_PRINTK0("%s: someone advertises our address!\n",
 				   ifp->idev->dev->name);
 			in6_ifa_put(ifp);
 			return 0;
@@ -1125,12 +1172,35 @@
 		break;
 
 	case NDISC_ROUTER_ADVERTISEMENT:
+		/* XXX: import nd_router_advert from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8+4+4) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP RA: packet too short\n");
+			return 0;
+		}
 		ndisc_router_discovery(skb);
 		break;
 
 	case NDISC_REDIRECT:
+		/* XXX: import nd_redirect from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8+16+16) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP redirect: packet too short\n");
+			return 0;
+		}
 		ndisc_redirect_rcv(skb);
 		break;
+
+	case NDISC_ROUTER_SOLICITATION:
+		/* No RS support in the kernel, but we do some required checks */
+
+		/* XXX: import nd_router_solicit from glibc netinet/icmp6.h */
+		if (skb->nh.ipv6h->payload_len < 8) {
+			if (net_ratelimit())
+				printk(KERN_WARNING "ICMP RS: packet too short\n");
+			return 0;
+		}
+		break;
 	};
 
 	return 0;
@@ -1228,7 +1298,7 @@
 
 	if((err = ops->create(ndisc_socket, IPPROTO_ICMPV6)) < 0) {
 		printk(KERN_DEBUG 
-		       "Failed to initializee the NDISC control socket (err %d).\n",
+		       "Failed to initialize the NDISC control socket (err %d).\n",
 		       err);
 		sock_release(ndisc_socket);
 		ndisc_socket = NULL; /* For safety. */
diff -urN linux-2.4.5-pre2/net/ipv6/netfilter/ip6_tables.c linux/net/ipv6/netfilter/ip6_tables.c
--- linux-2.4.5-pre2/net/ipv6/netfilter/ip6_tables.c	Mon Jan 22 13:30:21 2001
+++ linux/net/ipv6/netfilter/ip6_tables.c	Mon Dec  3 22:43:26 2001
@@ -1286,6 +1286,7 @@
 			ret = -EFAULT;
 			break;
 		}
+		name[IP6T_TABLE_MAXNAMELEN-1] = '\0';
 		t = find_table_lock(name, &ret, &ip6t_mutex);
 		if (t) {
 			struct ip6t_getinfo info;
diff -urN linux-2.4.5-pre2/net/ipv6/route.c linux/net/ipv6/route.c
--- linux-2.4.5-pre2/net/ipv6/route.c	Thu Apr 26 22:17:26 2001
+++ linux/net/ipv6/route.c	Mon Dec  3 22:43:26 2001
@@ -5,7 +5,7 @@
  *	Authors:
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *
- *	$Id: route.c,v 1.50 2001/04/25 20:46:35 davem Exp $
+ *	$Id: route.c,v 1.51 2001/05/03 07:02:47 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -892,12 +892,6 @@
 	if (!(rt->rt6i_flags&RTF_GATEWAY))
 		goto out;
 
-#if !defined(CONFIG_IPV6_EUI64) || defined(CONFIG_IPV6_NO_PB)
-	/*
-	 *	During transition gateways have more than
-	 *	one link local address. Certainly, it is violation
-	 *	of basic principles, but it is temporary.
-	 */
 	/*
 	 *	RFC 1970 specifies that redirects should only be
 	 *	accepted if they come from the nexthop to the target.
@@ -929,7 +923,6 @@
 	}
 
 source_ok:
-#endif
 
 	/*
 	 *	We have finally decided to accept it.
diff -urN linux-2.4.5-pre2/net/ipv6/sit.c linux/net/ipv6/sit.c
--- linux-2.4.5-pre2/net/ipv6/sit.c	Wed Apr 25 14:57:39 2001
+++ linux/net/ipv6/sit.c	Mon Dec  3 22:43:26 2001
@@ -182,6 +182,7 @@
 	dev->init = ipip6_tunnel_init;
 	dev->features |= NETIF_F_DYNALLOC;
 	memcpy(&nt->parms, parms, sizeof(*parms));
+	nt->parms.name[IFNAMSIZ-1] = '\0';
 	strcpy(dev->name, nt->parms.name);
 	if (dev->name[0] == 0) {
 		int i;
diff -urN linux-2.4.5-pre2/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- linux-2.4.5-pre2/net/ipx/af_ipx.c	Thu Apr 12 12:11:39 2001
+++ linux/net/ipx/af_ipx.c	Mon Dec  3 22:43:26 2001
@@ -71,6 +71,8 @@
  *			sysctl for ipx_pprop_broacasting, fix the ipx sysctl
  *			handling, making it dynamic, some cleanups, thanks to
  *			Petr Vandrovec for review and good suggestions. (acme)
+ *	Revision 047:	Cleanups, CodingStyle changes, move the ncp connection
+ *			hack out of line (acme)
  *
  *	Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
  *	pair. Also, now usage count is managed this way
@@ -116,8 +118,13 @@
 #include <linux/init.h>
 #include <linux/if_arp.h>
 
+#ifdef CONFIG_SYSCTL
 extern void ipx_register_sysctl(void);
 extern void ipx_unregister_sysctl(void);
+#else
+#define ipx_register_sysctl()
+#define ipx_unregister_sysctl()
+#endif
 
 /* Configuration Variables */
 static unsigned char ipxcfg_max_hops = 16;
@@ -175,16 +182,12 @@
 	ipx_config_data	vals;
 
 	vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
-	vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
+	vals.ipxcfg_auto_select_primary	   = ipxcfg_auto_select_primary;
 
 	return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
 }
 
-/**************************************************************************\
-*                                                                          *
-* Handlers for the socket list.                                            *
-*                                                                          *
-\**************************************************************************/
+/* Handlers for the socket list. */
 
 static inline void ipxitf_hold(ipx_interface *intrfc)
 {
@@ -220,26 +223,28 @@
 	/* Determine interface with which socket is associated */
 	intrfc = sk->protinfo.af_ipx.intrfc;
 	if (!intrfc)
-		return;
+		goto out;
 
 	ipxitf_hold(intrfc);
 	spin_lock_bh(&intrfc->if_sklist_lock);
 	s = intrfc->if_sklist;
 	if (s == sk) {
 		intrfc->if_sklist = s->next;
-		goto out;
+		goto out_unlock;
 	}
 
 	while (s && s->next) {
 		if (s->next == sk) {
 			s->next = sk->next;
-			goto out;
+			goto out_unlock;
 		}
 		s = s->next;
 	}
-out:	spin_unlock_bh(&intrfc->if_sklist_lock);
+out_unlock:
+	spin_unlock_bh(&intrfc->if_sklist_lock);
 	sock_put(sk);
 	ipxitf_put(intrfc);
+out:	return;
 }
 
 static void ipx_destroy_socket(struct sock *sk)
@@ -267,21 +272,16 @@
 
 static void ipxitf_clear_primary_net(void)
 {
-	if (ipxcfg_auto_select_primary && ipx_interfaces)
-		ipx_primary_net = ipx_interfaces;
-	else
-		ipx_primary_net = NULL;
+	ipx_primary_net = ipxcfg_auto_select_primary ? ipx_interfaces : NULL;
 }
 
 static ipx_interface *__ipxitf_find_using_phys(struct net_device *dev,
 						unsigned short datalink)
 {
-	ipx_interface *i;
+	ipx_interface *i = ipx_interfaces;
 
-	for (i = ipx_interfaces;
-		i && (i->if_dev != dev || i->if_dlink_type != datalink);
-		i = i->if_next)
-		;
+	while (i && (i->if_dev != dev || i->if_dlink_type != datalink))
+		i = i->if_next;
 
 	return i;
 }
@@ -320,8 +320,6 @@
 /* Sockets are bound to a particular IPX interface. */
 static void ipxitf_insert_socket(ipx_interface *intrfc, struct sock *sk)
 {
-	struct sock *s;
-
 	ipxitf_hold(intrfc);
 	sock_hold(sk);
 	spin_lock_bh(&intrfc->if_sklist_lock);
@@ -330,8 +328,9 @@
 	if (!intrfc->if_sklist)
 		intrfc->if_sklist = sk;
 	else {
-		for (s = intrfc->if_sklist; s->next; s = s->next)
-			;
+		struct sock *s = intrfc->if_sklist;
+		while (s->next)
+			s = s->next;
 		s->next = sk;
 	}
 	spin_unlock_bh(&intrfc->if_sklist_lock);
@@ -342,12 +341,11 @@
 static struct sock *__ipxitf_find_socket(ipx_interface *intrfc,
 					 unsigned short port)
 {
-	struct sock *s;
+	struct sock *s = intrfc->if_sklist;
+
+	while (s && s->protinfo.af_ipx.port != port)
+	     s = s->next;
 
-	for (s = intrfc->if_sklist;
-	     s && s->protinfo.af_ipx.port != port;
-	     s = s->next)
-		;
 	return s;
 }
 
@@ -393,7 +391,6 @@
 
 static void __ipxitf_down(ipx_interface *intrfc)
 {
-	ipx_interface *i;
 	struct sock *s, *t;
 
 	/* Delete all routes associated with this interface */
@@ -401,12 +398,12 @@
 
 	spin_lock_bh(&intrfc->if_sklist_lock);
 	/* error sockets */
-	for (s = intrfc->if_sklist; s; ) {
+	for (s = intrfc->if_sklist; s;) {
 		s->err = ENOLINK;
 		s->error_report(s);
 		s->protinfo.af_ipx.intrfc = NULL;
-		s->protinfo.af_ipx.port = 0;
-		s->zapped=1;	/* Indicates it is no longer bound */
+		s->protinfo.af_ipx.port	  = 0;
+		s->zapped = 1;	/* Indicates it is no longer bound */
 		t = s;
 		s = s->next;
 		t->next = NULL;
@@ -418,10 +415,9 @@
 	if (intrfc == ipx_interfaces)
 		ipx_interfaces = intrfc->if_next;
 	else {
-		for (i = ipx_interfaces;
-		     i && i->if_next != intrfc;
-		     i = i->if_next)
-			;
+		ipx_interface *i = ipx_interfaces;
+		while (i && i->if_next != intrfc)
+		     i = i->if_next;
 		if (i && i->if_next == intrfc)
 			i->if_next = intrfc->if_next;
 	}
@@ -482,15 +478,15 @@
 /* caller must hold a reference to intrfc */
 
 #ifdef CONFIG_IPX_INTERN
-static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb, int copy)
+static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb,
+				int copy)
 {
 	struct ipxhdr *ipx = skb->nh.ipxh;
+	int is_broadcast = !memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
+				   IPX_NODE_LEN);
 	struct sock *s;
 	int ret;
 
-	int is_broadcast = (memcmp(ipx->ipx_dest.node, ipx_broadcast_node,
-				   IPX_NODE_LEN) == 0);
-
 	spin_lock_bh(&intrfc->if_sklist_lock);
 	s = intrfc->if_sklist;
 
@@ -529,6 +525,40 @@
 	return ret;
 }
 #else
+static struct sock *ncp_connection_hack(ipx_interface *intrfc,
+					struct ipxhdr *ipx)
+{
+	/* The packet's target is a NCP connection handler. We want to hand it
+	 * to the correct socket directly within the kernel, so that the
+	 * mars_nwe packet distribution process does not have to do it. Here we
+	 * only care about NCP and BURST packets.
+	 *
+	 * You might call this a hack, but believe me, you do not want a
+	 * complete NCP layer in the kernel, and this is VERY fast as well. */
+	struct sock *sk = NULL;
+ 	int connection = 0;
+	u8 *ncphdr = (u8 *)(ipx + 1);
+
+ 	if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22) /* NCP request */
+		connection = (((int) *(ncphdr + 5)) << 8) | (int) *(ncphdr + 3);
+	else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77) /* BURST packet */
+		connection = (((int) *(ncphdr + 9)) << 8) | (int) *(ncphdr + 8);
+
+	if (connection) {
+		/* Now we have to look for a special NCP connection handling
+		 * socket. Only these sockets have ipx_ncp_conn != 0, set by
+		 * SIOCIPXNCPCONN. */
+		spin_lock_bh(&intrfc->if_sklist_lock);
+		for (sk = intrfc->if_sklist;
+		     sk && sk->protinfo.af_ipx.ipx_ncp_conn != connection;
+		     sk = sk->next);
+		if (sk)
+			sock_hold(sk);
+		spin_unlock_bh(&intrfc->if_sklist_lock);
+	}
+	return sk;
+}
+
 static int ipxitf_demux_socket(ipx_interface *intrfc, struct sk_buff *skb,
 				int copy)
 {
@@ -537,43 +567,8 @@
 	struct sk_buff *skb1 = NULL, *skb2 = NULL;
 	int ret;
 
-	if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451) {
-		/* 
-	 	 * The packet's target is a NCP connection handler. We want to
-	 	 * hand it to the correct socket directly within the kernel,
-	 	 * so that the mars_nwe packet distribution process
-	 	 * does not have to do it. Here we only care about NCP and
-	 	 * BURST packets.
-	 	 * You might call this a hack, but believe me, you do not
-	 	 * want a complete NCP layer in the kernel, and this is
-	 	 * VERY fast as well.
-	 	 */
-	 	int connection = 0;
-		u8 *ncphdr = (u8 *)(ipx + 1);
-
-	 	if (*ncphdr == 0x22 && *(ncphdr + 1) == 0x22)
-	  		/* The packet is a NCP request */
-			connection = (((int) *(ncphdr + 5)) << 8) |
-					(int) *(ncphdr+3);
-		else if (*ncphdr == 0x77 && *(ncphdr + 1) == 0x77)
-			/* The packet is a BURST packet */
-			connection = (((int) *(ncphdr+9)) << 8) |
-					(int) *(ncphdr+8);
-
-        	if (connection) {
-			/* Now we have to look for a special NCP connection
-			 * handling socket. Only these sockets have
-			 * ipx_ncp_conn != 0, set by SIOCIPXNCPCONN. */
-			spin_lock_bh(&intrfc->if_sklist_lock);
-			for (sock1 = intrfc->if_sklist;
-			     sock1 &&
-			     sock1->protinfo.af_ipx.ipx_ncp_conn != connection;
-			     sock1 = sock1->next);
-			if (sock1)
-				sock_hold(sock1);
-			spin_unlock_bh(&intrfc->if_sklist_lock);
-		}
-        }
+	if (intrfc == ipx_primary_net && ntohs(ipx->ipx_dest.sock) == 0x451)
+		sock1 = ncp_connection_hack(intrfc, ipx);
         if (!sock1)
 		/* No special socket found, forward the packet the normal way */
 		sock1 = ipxitf_find_socket(intrfc, ipx->ipx_dest.sock);
@@ -587,22 +582,15 @@
 	 */
 
 	if (ipx_primary_net && intrfc != ipx_primary_net) {
-		switch (ntohs(ipx->ipx_dest.sock)) {
-			case 0x452:
-			case 0x453:
-			case 0x456:
-				/*
-				 * The appropriate thing to do here is to
-				 * dup the packet and route to the primary net
-				 * interface via ipxitf_send; however, we'll 
-				 * cheat and just demux it here.
-				 */
-				sock2 = ipxitf_find_socket(ipx_primary_net,
-					ipx->ipx_dest.sock);
-				break;
-			default:
-				break;
-		}
+		const int dsock = ntohs(ipx->ipx_dest.sock);
+
+		if (dsock == 0x452 || dsock == 0x453 || dsock == 0x456)
+			/* The appropriate thing to do here is to dup the
+			 * packet and route to the primary net interface via
+			 * ipxitf_send; however, we'll cheat and just demux it
+			 * here. */
+			sock2 = ipxitf_find_socket(ipx_primary_net,
+							ipx->ipx_dest.sock);
 	}
 
 	/*
@@ -673,8 +661,7 @@
 	skb2 = alloc_skb(len, GFP_ATOMIC);
 	if (skb2) {
 		skb_reserve(skb2, out_offset);
-		skb2->nh.raw =
-		skb2->h.raw = skb_put(skb2,skb->len);
+		skb2->nh.raw = skb2->h.raw = skb_put(skb2, skb->len);
 		memcpy(skb2->h.raw, skb->h.raw, skb->len);
 		memcpy(skb2->cb, skb->cb, sizeof(skb->cb));
 	}
@@ -742,7 +729,7 @@
 				skb_orphan(skb);
 			ipxitf_demux_socket(intrfc, skb, send_to_wire);
 			if (!send_to_wire)
-				return 0;
+				goto out;
 		}
 	}
 
@@ -758,14 +745,14 @@
 		 */
 		skb = skb_unshare(skb, GFP_ATOMIC);
 		if (!skb)
-			return 0;
+			goto out;
 		if (++ipx->ipx_tctrl > ipxcfg_max_hops)
 			send_to_wire = 0;
 	}
 
 	if (!send_to_wire) {
 		kfree_skb(skb);
-		return 0;
+		goto out;
 	}
 
 	/* Determine the appropriate hardware address */
@@ -778,16 +765,16 @@
 	/* Make any compensation for differing physical/data link size */
 	skb = ipxitf_adjust_skbuff(intrfc, skb);
 	if (!skb)
-		return 0;
+		goto out;
 
 	/* set up data link and physical headers */
-	skb->dev = dev;
-	skb->protocol = htons(ETH_P_IPX);
+	skb->dev	= dev;
+	skb->protocol	= __constant_htons(ETH_P_IPX);
 	dl->datalink_header(dl, skb, dest_node);
 
 	/* Send it out */
 	dev_queue_xmit(skb);
-	return 0;
+out:	return 0;
 }
 
 static int ipxrtr_add_route(__u32, ipx_interface *, unsigned char *);
@@ -976,15 +963,14 @@
 
 static void ipxitf_insert(ipx_interface *intrfc)
 {
-	ipx_interface *i;
-
 	intrfc->if_next = NULL;
 	spin_lock_bh(&ipx_interfaces_lock);
 	if (!ipx_interfaces)
 		ipx_interfaces = intrfc;
 	else {
-		for (i = ipx_interfaces; i->if_next; i = i->if_next)
-			;
+		ipx_interface *i = ipx_interfaces;
+		while (i->if_next)
+			i = i->if_next;
 		i->if_next = intrfc;
 	}
 	spin_unlock_bh(&ipx_interfaces_lock);
@@ -998,7 +984,7 @@
 				   struct datalink_proto *dlink,
 				   unsigned char internal, int ipx_offset)
 {
-	ipx_interface *intrfc = kmalloc(sizeof(ipx_interface), GFP_ATOMIC);
+	ipx_interface *intrfc = kmalloc(sizeof(*intrfc), GFP_ATOMIC);
 
 	if (intrfc) {
 		intrfc->if_dev		= dev;
@@ -1020,23 +1006,26 @@
 static int ipxitf_create_internal(ipx_interface_definition *idef)
 {
 	ipx_interface *intrfc;
-	int ret;
+	int ret = -EEXIST;
 
 	/* Only one primary network allowed */
 	if (ipx_primary_net)
-		return -EEXIST;
+		goto out;
 
 	/* Must have a valid network number */
+	ret = -EADDRNOTAVAIL;
 	if (!idef->ipx_network)
-		return -EADDRNOTAVAIL;
+		goto out;
 	intrfc = ipxitf_find_using_net(idef->ipx_network);
+	ret = -EADDRINUSE;
 	if (intrfc) {
 		ipxitf_put(intrfc);
-		return -EADDRINUSE;
+		goto out;
 	}
 	intrfc = ipxitf_alloc(NULL, idef->ipx_network, 0, NULL, 1, 0);
+	ret = -EAGAIN;
 	if (!intrfc)
-		return -EAGAIN;
+		goto out;
 	memcpy((char *)&(intrfc->if_node), idef->ipx_node, IPX_NODE_LEN);
 	ipx_internal_net = ipx_primary_net = intrfc;
 	ipxitf_hold(intrfc);
@@ -1044,26 +1033,29 @@
 
 	ret = ipxitf_add_local_route(intrfc);
 	ipxitf_put(intrfc);
-	return ret;
+out:	return ret;
 }
 
 static int ipx_map_frame_type(unsigned char type)
 {
+	int ret = 0;
+
 	switch (type) {
 		case IPX_FRAME_ETHERII:
-			return htons(ETH_P_IPX);
-
+			ret = __constant_htons(ETH_P_IPX);
+			break;
 		case IPX_FRAME_8022:
-			return htons(ETH_P_802_2);
-
+			ret = __constant_htons(ETH_P_802_2);
+			break;
 		case IPX_FRAME_SNAP:
-			return htons(ETH_P_SNAP);
-
+			ret = __constant_htons(ETH_P_SNAP);
+			break;
 		case IPX_FRAME_8023:
-			return htons(ETH_P_802_3);
+			ret = __constant_htons(ETH_P_802_3);
+			break;
 	}
 
-	return 0;
+	return ret;
 }
 
 static int ipxitf_create(ipx_interface_definition *idef)
@@ -1074,39 +1066,42 @@
 	ipx_interface *intrfc;
 	int err;
 
-	if (idef->ipx_special == IPX_INTERNAL)
-		return ipxitf_create_internal(idef);
+	if (idef->ipx_special == IPX_INTERNAL) {
+		err = ipxitf_create_internal(idef);
+		goto out;
+	}
 
+	err = -EEXIST;
 	if (idef->ipx_special == IPX_PRIMARY && ipx_primary_net)
-		return -EEXIST;
+		goto out;
 
 	intrfc = ipxitf_find_using_net(idef->ipx_network);
+	err = -EADDRINUSE;
 	if (idef->ipx_network && intrfc) {
 		ipxitf_put(intrfc);
-		return -EADDRINUSE;
+		goto out;
 	}
 
 	if (intrfc)
 		ipxitf_put(intrfc);
 
 	dev = dev_get_by_name(idef->ipx_device);
+	err = -ENODEV;
 	if (!dev)
-		return -ENODEV;
+		goto out;
 
 	switch (idef->ipx_dlink_type) {
 		case IPX_FRAME_TR_8022:
 			printk(KERN_WARNING "IPX frame type 802.2TR is "
 				"obsolete Use 802.2 instead.\n");
 			/* fall through */
-
 		case IPX_FRAME_8022:
-			dlink_type 	= htons(ETH_P_802_2);
+			dlink_type 	= __constant_htons(ETH_P_802_2);
 			datalink 	= p8022_datalink;
 			break;
-
 		case IPX_FRAME_ETHERII:
 			if (dev->type != ARPHRD_IEEE802) {
-				dlink_type 	= htons(ETH_P_IPX);
+				dlink_type 	= __constant_htons(ETH_P_IPX);
 				datalink 	= pEII_datalink;
 				break;
 			} else 
@@ -1114,17 +1109,14 @@
 					"over token-ring is obsolete. Use SNAP "
 					"instead.\n");
 			/* fall through */
-
 		case IPX_FRAME_SNAP:
-			dlink_type 	= htons(ETH_P_SNAP);
+			dlink_type 	= __constant_htons(ETH_P_SNAP);
 			datalink 	= pSNAP_datalink;
 			break;
-
 		case IPX_FRAME_8023:
-			dlink_type 	= htons(ETH_P_802_3);
+			dlink_type 	= __constant_htons(ETH_P_802_3);
 			datalink 	= p8023_datalink;
 			break;
-
 		case IPX_FRAME_NONE:
 		default:
 			err = -EPROTONOSUPPORT;
@@ -1155,7 +1147,7 @@
 		if (!memcmp(idef->ipx_node, "\000\000\000\000\000\000",
 			    IPX_NODE_LEN)) {
 			memset(intrfc->if_node, 0, IPX_NODE_LEN);
-			memcpy((char *)&(intrfc->if_node[IPX_NODE_LEN-dev->addr_len]),
+			memcpy(intrfc->if_node + IPX_NODE_LEN - dev->addr_len,
 				dev->dev_addr, dev->addr_len);
 		} else
 			memcpy(intrfc->if_node, idef->ipx_node, IPX_NODE_LEN);
@@ -1172,10 +1164,10 @@
 	err = ipxitf_add_local_route(intrfc);
 out_intrfc:
 	ipxitf_put(intrfc);
-	return err;
+	goto out;
 out_dev:
 	dev_put(dev);
-	return err;
+out:	return err;
 }
 
 static int ipxitf_delete(ipx_interface_definition *idef)
@@ -1196,23 +1188,22 @@
 	}
 
 	dlink_type = ipx_map_frame_type(idef->ipx_dlink_type);
-	if (!dlink_type) {
-		ret = -EPROTONOSUPPORT;
+	ret = -EPROTONOSUPPORT;
+	if (!dlink_type)
 		goto out;
-	}
 
 	dev = __dev_get_by_name(idef->ipx_device);
-	if (!dev) {
-		ret = -ENODEV;
+	ret = -ENODEV;
+	if (!dev)
 		goto out;
-	}
 
 	intrfc = __ipxitf_find_using_phys(dev, dlink_type);
-	if (intrfc)
-		__ipxitf_put(intrfc);
-	else
-		ret = -EINVAL;
+	ret = -EINVAL;
+	if (!intrfc)
+		goto out;
+	__ipxitf_put(intrfc);
 
+	ret = 0;
 out:	spin_unlock_bh(&ipx_interfaces_lock);
 	return ret;
 }
@@ -1270,7 +1261,7 @@
 static int ipxitf_ioctl(unsigned int cmd, void *arg)
 {
 	struct ifreq ifr;
-	int err = 0, val;
+	int val;
 
 	switch (cmd) {
 		case SIOCSIFADDR: {
@@ -1285,7 +1276,8 @@
 				return -EINVAL;
 
 			f.ipx_network = sipx->sipx_network;
-			memcpy(f.ipx_device,ifr.ifr_name,sizeof(f.ipx_device));
+			memcpy(f.ipx_device, ifr.ifr_name,
+				sizeof(f.ipx_device));
 			memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN);
 			f.ipx_dlink_type = sipx->sipx_type;
 			f.ipx_special = sipx->sipx_special;
@@ -1296,8 +1288,8 @@
 				return ipxitf_create(&f);
 		}
 
-		case SIOCGIFADDR: 
-		{
+		case SIOCGIFADDR: {
+			int err = 0;
 			struct sockaddr_ipx *sipx;
 			ipx_interface *ipxif;
 			struct net_device *dev;
@@ -1344,11 +1336,7 @@
 	return 0;
 }
 
-/**************************************************************************\
-*                                                                          *
-* Routing tables for the IPX socket layer.                                 *
-*                                                                          *
-\**************************************************************************/
+/* Routing tables for the IPX socket layer. */
 
 static inline void ipxrtr_hold(ipx_route *rt)
 {
@@ -1377,7 +1365,8 @@
 
 /* caller must hold a reference to intrfc */
 
-static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc, unsigned char *node)
+static int ipxrtr_add_route(__u32 network, ipx_interface *intrfc,
+				unsigned char *node)
 {
 	ipx_route *rt;
 	int ret;
@@ -1385,7 +1374,7 @@
 	/* Get a route structure; either existing or create */
 	rt = ipxrtr_lookup(network);
 	if (!rt) {
-		rt = kmalloc(sizeof(ipx_route),GFP_ATOMIC);
+		rt = kmalloc(sizeof(ipx_route), GFP_ATOMIC);
 		ret = -EAGAIN;
 		if (!rt)
 			goto out;
@@ -1436,15 +1425,15 @@
 static int ipxrtr_create(ipx_route_definition *rd)
 {
 	ipx_interface *intrfc;
-	int ret;
+	int ret = -ENETUNREACH;
 
 	/* Find the appropriate interface */
 	intrfc = ipxitf_find_using_net(rd->ipx_router_network);
 	if (!intrfc)
-		return -ENETUNREACH;
+		goto out;
 	ret = ipxrtr_add_route(rd->ipx_network, intrfc, rd->ipx_router_node);
 	ipxitf_put(intrfc);
-	return ret;
+out:	return ret;
 }
 
 static int ipxrtr_delete(long net)
@@ -1481,7 +1470,7 @@
 /* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
 /* This functions should *not* mess with packet contents */
 
-static __u16 ipx_cksum(struct ipxhdr *packet,int length) 
+static __u16 ipx_cksum(struct ipxhdr *packet, int length) 
 {
 	/* 
 	 *	NOTE: sum is a net byte order quantity, which optimizes the 
@@ -1500,7 +1489,7 @@
 		sum += *p++;
 
 	/* Add on the last part word if it exists */
-	if (packet->ipx_pktsize & htons(1))
+	if (packet->ipx_pktsize & __constant_htons(1))
 		sum += ntohs(0xff00) & *p;
 
 	/* Do final fixup */
@@ -1516,7 +1505,8 @@
 /*
  * Route an outgoing frame from a socket.
  */
-static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx, struct iovec *iov, int len, int noblock)
+static int ipxrtr_route_packet(struct sock *sk, struct sockaddr_ipx *usipx,
+				struct iovec *iov, int len, int noblock)
 {
 	struct sk_buff *skb;
 	ipx_interface *intrfc;
@@ -1546,15 +1536,15 @@
 	if (!skb)
 		goto out_put;
 
-	skb_reserve(skb,ipx_offset);
+	skb_reserve(skb, ipx_offset);
 	skb->sk = sk;
 
 	/* Fill in IPX header */
 	ipx = (struct ipxhdr *)skb_put(skb, sizeof(struct ipxhdr));
-	ipx->ipx_pktsize= htons(len + sizeof(struct ipxhdr));
+	ipx->ipx_pktsize = htons(len + sizeof(struct ipxhdr));
 	IPX_SKB_CB(skb)->ipx_tctrl = 0;
-	ipx->ipx_type 	= usipx->sipx_type;
-	skb->h.raw 	= (void *)skb->nh.ipxh = ipx;
+	ipx->ipx_type 	 = usipx->sipx_type;
+	skb->h.raw 	 = (void *)skb->nh.ipxh = ipx;
 
 	IPX_SKB_CB(skb)->last_hop.index = -1;
 #ifdef CONFIG_IPX_INTERN
@@ -1572,13 +1562,12 @@
 		memcpy(ipx->ipx_source.node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
 	}
 #endif	/* CONFIG_IPX_INTERN */
-
-	ipx->ipx_source.sock 	= sk->protinfo.af_ipx.port;
+	ipx->ipx_source.sock		= sk->protinfo.af_ipx.port;
 	IPX_SKB_CB(skb)->ipx_dest_net	= usipx->sipx_network;
-	memcpy(ipx->ipx_dest.node,usipx->sipx_node,IPX_NODE_LEN);
-	ipx->ipx_dest.sock	= usipx->sipx_port;
+	memcpy(ipx->ipx_dest.node, usipx->sipx_node, IPX_NODE_LEN);
+	ipx->ipx_dest.sock		= usipx->sipx_port;
 
-	err = memcpy_fromiovec(skb_put(skb,len),iov,len);
+	err = memcpy_fromiovec(skb_put(skb, len), iov, len);
 	if (err) {
 		kfree_skb(skb);
 		goto out_put;
@@ -1586,7 +1575,7 @@
 
 	/* Apply checksum. Not allowed on 802.3 links. */
 	if (sk->no_check || intrfc->if_dlink_type == IPX_FRAME_8023)
-		ipx->ipx_checksum=0xFFFF;
+		ipx->ipx_checksum = 0xFFFF;
 	else
 		ipx->ipx_checksum = ipx_cksum(ipx, len + sizeof(struct ipxhdr));
 
@@ -1612,7 +1601,7 @@
 	}
 
 	ipxitf_hold(r->ir_intrfc);
-	ipxitf_send(r->ir_intrfc, skb, (r->ir_routed) ?
+	ipxitf_send(r->ir_intrfc, skb, r->ir_routed ?
 			r->ir_router_node : ipx->ipx_dest.node);
 	ipxitf_put(r->ir_intrfc);
 	ipxrtr_put(r);
@@ -1626,61 +1615,51 @@
 static int ipxrtr_ioctl(unsigned int cmd, void *arg)
 {
 	struct rtentry rt;	/* Use these to behave like 'other' stacks */
-	struct sockaddr_ipx *sg,*st;
-	int err;
+	struct sockaddr_ipx *sg, *st;
+	int ret = -EFAULT;
 
-	err = copy_from_user(&rt,arg,sizeof(rt));
-	if (err)
-		return -EFAULT;
+	if (copy_from_user(&rt, arg, sizeof(rt)))
+		goto out;
 
 	sg = (struct sockaddr_ipx *)&rt.rt_gateway;
 	st = (struct sockaddr_ipx *)&rt.rt_dst;
 
-	if (!(rt.rt_flags & RTF_GATEWAY))
-		return -EINVAL;	/* Direct routes are fixed */
-	if (sg->sipx_family != AF_IPX)
-		return -EINVAL;
-	if (st->sipx_family != AF_IPX)
-		return -EINVAL;
+	ret = -EINVAL;
+	if (!(rt.rt_flags & RTF_GATEWAY) || /* Direct routes are fixed */
+	    sg->sipx_family != AF_IPX ||
+	    st->sipx_family != AF_IPX)
+		goto out;
 
 	switch (cmd) {
 		case SIOCDELRT:
-			return ipxrtr_delete(st->sipx_network);
-
-		case SIOCADDRT:
-		{
+			ret = ipxrtr_delete(st->sipx_network);
+			break;
+		case SIOCADDRT: {
 			struct ipx_route_definition f;
-			f.ipx_network=st->sipx_network;
-			f.ipx_router_network=sg->sipx_network;
+			f.ipx_network		= st->sipx_network;
+			f.ipx_router_network	= sg->sipx_network;
 			memcpy(f.ipx_router_node, sg->sipx_node, IPX_NODE_LEN);
-			return ipxrtr_create(&f);
+			ret = ipxrtr_create(&f);
+			break;
 		}
 	}
 
-	return -EINVAL;
+out:	return ret;
 }
 
 static const char *ipx_frame_name(unsigned short frame)
 {
-	switch (ntohs(frame)) {
-		case ETH_P_IPX:
-			return "EtherII";
-
-		case ETH_P_802_2:
-			return "802.2";
-
-		case ETH_P_SNAP:
-			return "SNAP";
-
-		case ETH_P_802_3:
-			return "802.3";
+	char* ret = "None";
 
-		case ETH_P_TR_802_2:
-			return "802.2TR";
-
-		default:
-			return "None";
+	switch (ntohs(frame)) {
+		case ETH_P_IPX:		ret = "EtherII";	break;
+		case ETH_P_802_2:	ret = "802.2";		break;
+		case ETH_P_SNAP:	ret = "SNAP";		break;
+		case ETH_P_802_3:	ret = "802.3";		break;
+		case ETH_P_TR_802_2:	ret = "802.2TR";	break;
 	}
+
+	return ret;
 }
 
 static const char *ipx_device_name(ipx_interface *intrfc)
@@ -1699,27 +1678,28 @@
 
 	/* Theory.. Keep printing in the same place until we pass offset */
 
-	len += sprintf(buffer,"%-11s%-15s%-9s%-11s%s", "Network",
+	len += sprintf(buffer, "%-11s%-15s%-9s%-11s%s", "Network",
 		"Node_Address", "Primary", "Device", "Frame_Type");
 #ifdef IPX_REFCNT_DEBUG
 	len += sprintf(buffer + len, "  refcnt");
 #endif
-	strcat(buffer+len++, "\n");
+	strcat(buffer + len++, "\n");
 	spin_lock_bh(&ipx_interfaces_lock);
 	for (i = ipx_interfaces; i; i = i->if_next) {
-		len += sprintf(buffer+len, "%08lX   ", (long unsigned int)ntohl(i->if_netnum));
-		len += sprintf(buffer+len,"%02X%02X%02X%02X%02X%02X   ",
+		len += sprintf(buffer + len, "%08lX   ",
+				(long unsigned int) ntohl(i->if_netnum));
+		len += sprintf(buffer + len, "%02X%02X%02X%02X%02X%02X   ",
 				i->if_node[0], i->if_node[1], i->if_node[2],
 				i->if_node[3], i->if_node[4], i->if_node[5]);
-		len += sprintf(buffer+len, "%-9s", i == ipx_primary_net ?
+		len += sprintf(buffer + len, "%-9s", i == ipx_primary_net ?
 			"Yes" : "No");
-		len += sprintf(buffer+len, "%-11s", ipx_device_name(i));
-		len += sprintf(buffer+len, "%-9s",
+		len += sprintf(buffer + len, "%-11s", ipx_device_name(i));
+		len += sprintf(buffer + len, "%-9s",
 			ipx_frame_name(i->if_dlink_type));
 #ifdef IPX_REFCNT_DEBUG
-		len += sprintf(buffer+len,"%6d",atomic_read(&i->refcnt));
+		len += sprintf(buffer + len, "%6d", atomic_read(&i->refcnt));
 #endif
-		strcat(buffer+len++, "\n");
+		strcat(buffer + len++, "\n");
 		/* Are we still dumping unwanted data then discard the record */
 		pos = begin + len;
 
@@ -1751,9 +1731,9 @@
 	/* Theory.. Keep printing in the same place until we pass offset */
 
 #ifdef CONFIG_IPX_INTERN
-	len += sprintf(buffer,"%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
+	len += sprintf(buffer, "%-28s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
 #else
-	len += sprintf(buffer,"%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
+	len += sprintf(buffer, "%-15s%-28s%-10s%-10s%-7s%s\n", "Local_Address",
 #endif	/* CONFIG_IPX_INTERN */
 			"Remote_Address", "Tx_Queue", "Rx_Queue",
 			"State", "Uid");
@@ -1764,7 +1744,7 @@
 		spin_lock_bh(&i->if_sklist_lock);
 		for (s = i->if_sklist; s; s = s->next) {
 #ifdef CONFIG_IPX_INTERN
-			len += sprintf(buffer+len,
+			len += sprintf(buffer + len,
 				       "%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
                                        (unsigned long) htonl(s->protinfo.af_ipx.intrfc->if_netnum),
 				       s->protinfo.af_ipx.node[0],
@@ -1775,15 +1755,15 @@
 				       s->protinfo.af_ipx.node[5],
 				       htons(s->protinfo.af_ipx.port));
 #else
-			len += sprintf(buffer+len,"%08lX:%04X  ",
-				       (unsigned long)htonl(i->if_netnum),
+			len += sprintf(buffer + len, "%08lX:%04X  ",
+				       (unsigned long) htonl(i->if_netnum),
 				       htons(s->protinfo.af_ipx.port));
 #endif	/* CONFIG_IPX_INTERN */
-
 			if (s->state != TCP_ESTABLISHED)
-				len += sprintf(buffer+len, "%-28s", "Not_Connected");
+				len += sprintf(buffer + len, "%-28s",
+						"Not_Connected");
 			else {
-				len += sprintf(buffer+len,
+				len += sprintf(buffer + len,
 					"%08lX:%02X%02X%02X%02X%02X%02X:%04X  ",
 					(unsigned long) htonl(s->protinfo.af_ipx.dest_addr.net),
 					s->protinfo.af_ipx.dest_addr.node[0],
@@ -1795,10 +1775,10 @@
 					htons(s->protinfo.af_ipx.dest_addr.sock));
 			}
 
-			len += sprintf(buffer+len,"%08X  %08X  ",
+			len += sprintf(buffer + len, "%08X  %08X  ",
 				atomic_read(&s->wmem_alloc),
 				atomic_read(&s->rmem_alloc));
-			len += sprintf(buffer+len,"%02X     %03d\n",
+			len += sprintf(buffer + len, "%02X     %03d\n",
 				s->state, SOCK_INODE(s->socket)->i_uid);
 
 			pos = begin + len;
@@ -1816,7 +1796,7 @@
 	spin_unlock_bh(&ipx_interfaces_lock);
 
 	/* The data in question runs from begin to begin+len */
-	*start = buffer + (offset-begin);
+	*start = buffer + offset - begin;
 	len -= (offset - begin);
 	if (len > length)
 		len = length;
@@ -1830,19 +1810,21 @@
 	off_t begin = 0, pos = 0;
 	int len = 0;
 
-	len += sprintf(buffer,"%-11s%-13s%s\n",
+	len += sprintf(buffer, "%-11s%-13s%s\n",
 			"Network", "Router_Net", "Router_Node");
 	read_lock_bh(&ipx_routes_lock);
 	for (rt = ipx_routes; rt; rt = rt->ir_next) {
-		len += sprintf(buffer+len,"%08lX   ", (long unsigned int) ntohl(rt->ir_net));
+		len += sprintf(buffer + len, "%08lX   ",
+				(long unsigned int) ntohl(rt->ir_net));
 		if (rt->ir_routed) {
-			len += sprintf(buffer+len,"%08lX     %02X%02X%02X%02X%02X%02X\n",
-				(long unsigned int) ntohl(rt->ir_intrfc->if_netnum),
+			len += sprintf(buffer + len,
+					"%08lX     %02X%02X%02X%02X%02X%02X\n",
+			(long unsigned int) ntohl(rt->ir_intrfc->if_netnum),
 				rt->ir_router_node[0], rt->ir_router_node[1],
 				rt->ir_router_node[2], rt->ir_router_node[3],
 				rt->ir_router_node[4], rt->ir_router_node[5]);
 		} else {
-			len += sprintf(buffer+len, "%-13s%s\n",
+			len += sprintf(buffer + len, "%-13s%s\n",
 					"Directly", "Connected");
 		}
 
@@ -1865,40 +1847,30 @@
 	return len;
 }
 
-/**************************************************************************\
-*                                                                          *
-* Handling for system calls applied via the various interfaces to an       *
-* IPX socket object.                                                       *
-*                                                                          *
-\**************************************************************************/
+/* Handling for system calls applied via the various interfaces to an IPX
+ * socket object. */
 
 static int ipx_setsockopt(struct socket *sock, int level, int optname,
 			  char *optval, int optlen)
 {
 	struct sock *sk = sock->sk;
 	int opt;
+	int ret = -EINVAL;
 
 	if (optlen != sizeof(int))
-		return -EINVAL;
+		goto out;
 
+	ret = -EFAULT;
 	if (get_user(opt, (unsigned int *)optval))
-		return -EFAULT;
-
-	switch (level) {
-		case SOL_IPX:
-			switch (optname) {
-				case IPX_TYPE:
-					sk->protinfo.af_ipx.type = opt;
-					return 0;
+		goto out;
 
-				default:
-					return -ENOPROTOOPT;
-			}
-			break;
+	ret = -ENOPROTOOPT;
+	if (!(level == SOL_IPX && optname == IPX_TYPE))
+		goto out;
 
-		default:
-			return -ENOPROTOOPT;
-	}
+	sk->protinfo.af_ipx.type = opt;
+	ret = 0;
+out:	return ret;
 }
 
 static int ipx_getsockopt(struct socket *sock, int level, int optname,
@@ -1907,49 +1879,41 @@
 	struct sock *sk = sock->sk;
 	int val = 0;
 	int len;
+	int ret = -ENOPROTOOPT;
 
-	switch (level) {
-		case SOL_IPX:
-			switch (optname) {
-				case IPX_TYPE:
-					val = sk->protinfo.af_ipx.type;
-					break;
+	if (!(level == SOL_IPX && optname == IPX_TYPE))
+		goto out;
 
-				default:
-					return -ENOPROTOOPT;
-			}
-			break;
-
-		default:
-			return -ENOPROTOOPT;
-	}
+	val = sk->protinfo.af_ipx.type;
 
+	ret = -EFAULT;
 	if (get_user(len, optlen))
-		return -EFAULT;
+		goto out;
 
 	len = min(len, sizeof(int));
-	
+	ret = -EINVAL;
 	if(len < 0)
-		return -EINVAL;
+		goto out;
 		
-	if (put_user(len, optlen))
-		return -EFAULT;
-
-	if (copy_to_user(optval, &val, len))
-		return -EFAULT;
+	ret = -EFAULT;
+	if (put_user(len, optlen) || copy_to_user(optval, &val, len))
+		goto out;
 
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 static int ipx_create(struct socket *sock, int protocol)
 {
+	int ret = -ESOCKTNOSUPPORT;
 	struct sock *sk;
 
 	switch (sock->type) {
 		case SOCK_DGRAM:
 			sk = sk_alloc(PF_IPX, GFP_KERNEL, 1);
+                	ret = -ENOMEM;
 			if (!sk)
-                		return -ENOMEM;
+				goto out;
                         sock->ops = &ipx_dgram_ops;
                         break;
 
@@ -1958,12 +1922,14 @@
 			 * From this point on SPX sockets are handled
 			 * by af_spx.c and the methods replaced.
 			 */
-			if (spx_family_ops)
-				return spx_family_ops->create(sock,protocol);
+			if (spx_family_ops) {
+				ret = spx_family_ops->create(sock, protocol);
+				goto out;
+			}
 			/* Fall through if SPX is not loaded */
 		case SOCK_STREAM:       /* Allow higher levels to piggyback */
 		default:
-			return -ESOCKTNOSUPPORT;
+			goto out;
 	}
 #ifdef IPX_REFCNT_DEBUG
         atomic_inc(&ipx_sock_nr);
@@ -1975,7 +1941,8 @@
 	sk->no_check 	= 1;		/* Checksum off by default */
 
 	MOD_INC_USE_COUNT;
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 static int ipx_release(struct socket *sock)
@@ -1983,7 +1950,7 @@
 	struct sock *sk = sock->sk;
 
 	if (!sk)
-		return 0;
+		goto out;
 
 	if (!sk->dead)
 		sk->state_change(sk);
@@ -1995,7 +1962,7 @@
 	if (sock->type == SOCK_DGRAM)
 		MOD_DEC_USE_COUNT;
 
-	return 0;
+out:	return 0;
 }
 
 /* caller must hold a reference to intrfc */
@@ -2026,30 +1993,28 @@
 	struct sock *sk = sock->sk;
 	ipx_interface *intrfc;
 	struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
-	int ret;
-
-	if (!sk->zapped)
-		return -EINVAL;
+	int ret = -EINVAL;
 
-	if (addr_len != sizeof(struct sockaddr_ipx))
-		return -EINVAL;
+	if (!sk->zapped || addr_len != sizeof(struct sockaddr_ipx))
+		goto out;
 
 	intrfc = ipxitf_find_using_net(addr->sipx_network);
+	ret = -EADDRNOTAVAIL;
 	if (!intrfc)
-		return -EADDRNOTAVAIL;
+		goto out;
 
 	if (!addr->sipx_port) {
 		addr->sipx_port = ipx_first_free_socketnum(intrfc);
 		ret = -EINVAL;
 		if (!addr->sipx_port)
-			goto out;
+			goto out_put;
 	}
 
 	/* protect IPX system stuff like routing/sap */
 	ret = -EACCES;
 	if (ntohs(addr->sipx_port) < IPX_MIN_EPHEMERAL_SOCKET &&
 	    !capable(CAP_NET_ADMIN))
-		goto out;
+		goto out_put;
 
 	sk->protinfo.af_ipx.port = addr->sipx_port;
 
@@ -2061,8 +2026,8 @@
 		 */
 
 		ret = -EINVAL;
-		if (!memcmp(addr->sipx_node,ipx_broadcast_node,IPX_NODE_LEN))
-			goto out;
+		if (!memcmp(addr->sipx_node, ipx_broadcast_node, IPX_NODE_LEN))
+			goto out_put;
 		if (!memcmp(addr->sipx_node, ipx_this_node, IPX_NODE_LEN))
 			memcpy(sk->protinfo.af_ipx.node, intrfc->if_node,
 			       IPX_NODE_LEN);
@@ -2077,7 +2042,7 @@
 			SOCK_DEBUG(sk,
 				"IPX: bind failed because port %X in use.\n",
 				ntohs((int)addr->sipx_port));
-			goto out;
+			goto out_put;
 		}
 	} else {
 		/* Source addresses are easy. It must be our
@@ -2093,7 +2058,7 @@
 			SOCK_DEBUG(sk,
 				"IPX: bind failed because port %X in use.\n",
 				ntohs((int)addr->sipx_port));
-			goto out;
+			goto out_put;
 		}
 	}
 
@@ -2106,7 +2071,7 @@
 	if (ipxitf_find_socket(intrfc, addr->sipx_port)) {
 		SOCK_DEBUG(sk, "IPX: bind failed because port %X in use.\n",
 				ntohs((int)addr->sipx_port));
-		goto out;
+		goto out_put;
 	}
 
 #endif	/* CONFIG_IPX_INTERN */
@@ -2116,8 +2081,9 @@
 	SOCK_DEBUG(sk, "IPX: bound socket 0x%04X.\n", ntohs(addr->sipx_port) );
 
 	ret = 0;
-out:	ipxitf_put(intrfc);
-	return ret;
+out_put:
+	ipxitf_put(intrfc);
+out:	return ret;
 }
 
 static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
@@ -2125,46 +2091,48 @@
 {
 	struct sock *sk = sock->sk;
 	struct sockaddr_ipx *addr;
+	int ret = -EINVAL;
 	ipx_route *rt;
 
 	sk->state	= TCP_CLOSE;
 	sock->state 	= SS_UNCONNECTED;
 
 	if (addr_len != sizeof(*addr))
-		return -EINVAL;
+		goto out;
 	addr = (struct sockaddr_ipx *)uaddr;
 
 	/* put the autobinding in */
 	if (!sk->protinfo.af_ipx.port) {
 		struct sockaddr_ipx uaddr;
-		int ret;
 
 		uaddr.sipx_port		= 0;
 		uaddr.sipx_network 	= 0;
 
 #ifdef CONFIG_IPX_INTERN
-		if (sk->protinfo.af_ipx.intrfc)
-			memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);
-		else
-			return -ENETDOWN;		/* Someone zonked the iface */
+		ret = -ENETDOWN;
+		if (!sk->protinfo.af_ipx.intrfc)
+			goto out; /* Someone zonked the iface */
+		memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,
+			IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
 		ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
 				sizeof(struct sockaddr_ipx));
 		if (ret)
-			return ret;
+			goto out;
 	}
 
         /* We can either connect to primary network or somewhere
 	 * we can route to */
 	rt = ipxrtr_lookup(addr->sipx_network);
+	ret = -ENETUNREACH;
 	if (!rt && !(!addr->sipx_network && ipx_primary_net))
-		return -ENETUNREACH;
+		goto out;
 
 	sk->protinfo.af_ipx.dest_addr.net  = addr->sipx_network;
 	sk->protinfo.af_ipx.dest_addr.sock = addr->sipx_port;
 	memcpy(sk->protinfo.af_ipx.dest_addr.node,
-		addr->sipx_node,IPX_NODE_LEN);
+		addr->sipx_node, IPX_NODE_LEN);
 	sk->protinfo.af_ipx.type = addr->sipx_type;
 
 	if (sock->type == SOCK_DGRAM) {
@@ -2174,7 +2142,8 @@
 
 	if (rt)
 		ipxrtr_put(rt);
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 
@@ -2184,24 +2153,30 @@
 	ipx_address *addr;
 	struct sockaddr_ipx sipx;
 	struct sock *sk = sock->sk;
+	int ret;
 
 	*uaddr_len = sizeof(struct sockaddr_ipx);
 
 	if (peer) {
+		ret = -ENOTCONN;
 		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			goto out;
 
 		addr = &sk->protinfo.af_ipx.dest_addr;
-		sipx.sipx_network = addr->net;
-		memcpy(sipx.sipx_node,addr->node,IPX_NODE_LEN);
-		sipx.sipx_port = addr->sock;
+		sipx.sipx_network	= addr->net;
+		sipx.sipx_port		= addr->sock;
+		memcpy(sipx.sipx_node, addr->node, IPX_NODE_LEN);
 	} else {
 		if (sk->protinfo.af_ipx.intrfc) {
-			sipx.sipx_network=sk->protinfo.af_ipx.intrfc->if_netnum;
+			sipx.sipx_network =
+				sk->protinfo.af_ipx.intrfc->if_netnum;
 #ifdef CONFIG_IPX_INTERN
-			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node, IPX_NODE_LEN);
+			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.node,
+				IPX_NODE_LEN);
 #else
-			memcpy(sipx.sipx_node, sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
+			memcpy(sipx.sipx_node,
+				sk->protinfo.af_ipx.intrfc->if_node,
+				IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
 		} else {
@@ -2213,10 +2188,11 @@
 	}
 
 	sipx.sipx_family = AF_IPX;
-	sipx.sipx_type = sk->protinfo.af_ipx.type;
-	memcpy(uaddr,&sipx,sizeof(sipx));
+	sipx.sipx_type	 = sk->protinfo.af_ipx.type;
+	memcpy(uaddr, &sipx, sizeof(sipx));
 
-	return 0;
+	ret = 0;
+out:	return ret;
 }
 
 int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
@@ -2225,7 +2201,7 @@
 	ipx_interface *intrfc;
 	struct ipxhdr *ipx;
 	u16 ipx_pktsize;
-	int ret;
+	int ret = 0;
 		
 	/* Not ours */	
         if (skb->pkt_type == PACKET_OTHERHOST)
@@ -2234,8 +2210,8 @@
 	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL)
 		goto out;
 
-	ipx = skb->nh.ipxh;
-	ipx_pktsize = ntohs(ipx->ipx_pktsize);
+	ipx		= skb->nh.ipxh;
+	ipx_pktsize	= ntohs(ipx->ipx_pktsize);
 	
 	/* Too small or invalid header? */
 	if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len)
@@ -2245,8 +2221,8 @@
 	   ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize))
 		goto drop;
 
-	IPX_SKB_CB(skb)->ipx_tctrl = ipx->ipx_tctrl;
-	IPX_SKB_CB(skb)->ipx_dest_net = ipx->ipx_dest.net;
+	IPX_SKB_CB(skb)->ipx_tctrl	= ipx->ipx_tctrl;
+	IPX_SKB_CB(skb)->ipx_dest_net	= ipx->ipx_dest.net;
 	IPX_SKB_CB(skb)->ipx_source_net = ipx->ipx_source.net;
 
 	/* Determine what local ipx endpoint this is */
@@ -2266,9 +2242,9 @@
 
 	ret = ipxitf_rcv(intrfc, skb);
 	ipxitf_put(intrfc);
-	return ret;
+	goto out;
 drop:	kfree_skb(skb);
-out:	return 0;
+out:	return ret;
 }
 
 static int ipx_sendmsg(struct socket *sock, struct msghdr *msg, int len,
@@ -2277,58 +2253,58 @@
 	struct sock *sk = sock->sk;
 	struct sockaddr_ipx *usipx = (struct sockaddr_ipx *)msg->msg_name;
 	struct sockaddr_ipx local_sipx;
-	int retval;
+	int ret = -EINVAL;
 	int flags = msg->msg_flags;
 
 	/* Socket gets bound below anyway */
 /*	if (sk->zapped)
 		return -EIO; */	/* Socket not bound */
 	if (flags & ~MSG_DONTWAIT)
-		return -EINVAL;
+		goto out;
 
 	if (usipx) {
 		if (!sk->protinfo.af_ipx.port) {
 			struct sockaddr_ipx uaddr;
-			int ret;
 
-			uaddr.sipx_port = 0;
-			uaddr.sipx_network = 0L;
+			uaddr.sipx_port		= 0;
+			uaddr.sipx_network	= 0;
 #ifdef CONFIG_IPX_INTERN
-			if (sk->protinfo.af_ipx.intrfc)
-				memcpy(uaddr.sipx_node,
-					sk->protinfo.af_ipx.intrfc->if_node,
-					IPX_NODE_LEN);
-			else
-				return -ENETDOWN;               /* Someone zonked the iface */
+			ret = -ENETDOWN;
+			if (!sk->protinfo.af_ipx.intrfc)
+				goto out; /* Someone zonked the iface */
+			memcpy(uaddr.sipx_node,
+				sk->protinfo.af_ipx.intrfc->if_node,
+				IPX_NODE_LEN);
 #endif
 			ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
 					sizeof(struct sockaddr_ipx));
 			if (ret)
-				return ret;
+				goto out;
 		}
 
-		if (msg->msg_namelen < sizeof(*usipx))
-			return -EINVAL;
-		if (usipx->sipx_family != AF_IPX)
-			return -EINVAL;
+		ret = -EINVAL;
+		if (msg->msg_namelen < sizeof(*usipx) ||
+		    usipx->sipx_family != AF_IPX)
+			goto out;
 	} else {
+		ret = -ENOTCONN;
 		if (sk->state != TCP_ESTABLISHED)
-			return -ENOTCONN;
+			goto out;
 
-		usipx=&local_sipx;
+		usipx = &local_sipx;
 		usipx->sipx_family 	= AF_IPX;
 		usipx->sipx_type 	= sk->protinfo.af_ipx.type;
 		usipx->sipx_port 	= sk->protinfo.af_ipx.dest_addr.sock;
 		usipx->sipx_network 	= sk->protinfo.af_ipx.dest_addr.net;
-		memcpy(usipx->sipx_node,sk->protinfo.af_ipx.dest_addr.node,IPX_NODE_LEN);
+		memcpy(usipx->sipx_node, sk->protinfo.af_ipx.dest_addr.node,
+				IPX_NODE_LEN);
 	}
 
-	retval = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len,
+	ret = ipxrtr_route_packet(sk, usipx, msg->msg_iov, len,
 				     flags & MSG_DONTWAIT);
-	if (retval < 0)
-		return retval;
-
-	return len;
+	if (ret >= 0)
+		ret = len;
+out:	return ret;
 }
 
 
@@ -2344,35 +2320,37 @@
 	/* put the autobinding in */
 	if (!sk->protinfo.af_ipx.port) {
 		struct sockaddr_ipx uaddr;
-		int ret;
 
 		uaddr.sipx_port		= 0;
 		uaddr.sipx_network 	= 0;
 
 #ifdef CONFIG_IPX_INTERN
-		if (sk->protinfo.af_ipx.intrfc)
-			memcpy(uaddr.sipx_node, sk->protinfo.af_ipx.intrfc->if_node,IPX_NODE_LEN);
-		else
-			return -ENETDOWN;		/* Someone zonked the iface */
+		err = -ENETDOWN;
+		if (!sk->protinfo.af_ipx.intrfc)
+			goto out; /* Someone zonked the iface */
+		memcpy(uaddr.sipx_node,
+			sk->protinfo.af_ipx.intrfc->if_node, IPX_NODE_LEN);
 #endif	/* CONFIG_IPX_INTERN */
 
-		ret = ipx_bind(sock, (struct sockaddr *)&uaddr,
+		err = ipx_bind(sock, (struct sockaddr *)&uaddr,
 				sizeof(struct sockaddr_ipx));
-		if (ret)
-			return ret;
+		if (err)
+			goto out;
 	}
 	
+	err = -ENOTCONN;
 	if (sk->zapped)
-		return -ENOTCONN;
+		goto out;
 
-	skb = skb_recv_datagram(sk,flags&~MSG_DONTWAIT,flags&MSG_DONTWAIT,&err);
+	skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+					flags & MSG_DONTWAIT, &err);
 	if (!skb)
 		goto out;
 
 	ipx 	= skb->nh.ipxh;
 	copied 	= ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr);
 	if (copied > size) {
-		copied=size;
+		copied = size;
 		msg->msg_flags |= MSG_TRUNC;
 	}
 
@@ -2387,7 +2365,7 @@
 	if (sipx) {
 		sipx->sipx_family	= AF_IPX;
 		sipx->sipx_port		= ipx->ipx_source.sock;
-		memcpy(sipx->sipx_node,ipx->ipx_source.node,IPX_NODE_LEN);
+		memcpy(sipx->sipx_node, ipx->ipx_source.node, IPX_NODE_LEN);
 		sipx->sipx_network	= IPX_SKB_CB(skb)->ipx_source_net;
 		sipx->sipx_type 	= ipx->ipx_type;
 	}
@@ -2399,7 +2377,7 @@
 }
 
 
-static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
+static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	long amount = 0;
 	struct sock *sk = sock->sk;
@@ -2411,10 +2389,10 @@
 				amount = 0;
 			return put_user(amount, (int *)arg);
 
-		case TIOCINQ:
-		{
+		case TIOCINQ: {
 			struct sk_buff *skb = skb_peek(&sk->receive_queue);
-			/* These two are safe on a single CPU system as only user tasks fiddle here */
+			/* These two are safe on a single CPU system as only
+			 * user tasks fiddle here */
 			if (skb)
 				amount = skb->len - sizeof(struct ipxhdr);
 			return put_user(amount, (int *)arg);
@@ -2424,7 +2402,7 @@
 		case SIOCDELRT:
 			if (!capable(CAP_NET_ADMIN))
 				return -EPERM;
-			return ipxrtr_ioctl(cmd,(void *)arg);
+			return ipxrtr_ioctl(cmd, (void *)arg);
 
 		case SIOCSIFADDR:
 		case SIOCAIPXITFCRT:
@@ -2433,13 +2411,12 @@
 				return -EPERM;
 
 		case SIOCGIFADDR:
-			return ipxitf_ioctl(cmd,(void *)arg);
+			return ipxitf_ioctl(cmd, (void *)arg);
 
 		case SIOCIPXCFGDATA:
 			return ipxcfg_get_config_data((void *)arg);
 
 		case SIOCIPXNCPCONN:
-                {
 			/*
 			 * This socket wants to take care of the NCP connection
 			 * handed to us in arg.
@@ -2448,10 +2425,8 @@
                 		return -EPERM;
 			return get_user(sk->protinfo.af_ipx.ipx_ncp_conn,
 					(const unsigned short *)(arg));
-                }
 
-		case SIOCGSTAMP:
-		{
+		case SIOCGSTAMP: {
 			int ret = -EINVAL;
 			if (sk) {
 				if (!sk->stamp.tv_sec)
@@ -2537,16 +2512,13 @@
 #include <linux/smp_lock.h>
 SOCKOPS_WRAP(ipx_dgram, PF_IPX);
 
-static struct packet_type ipx_8023_packet_type =
-
-{
+static struct packet_type ipx_8023_packet_type = {
 	type:		__constant_htons(ETH_P_802_3),
 	func:		ipx_rcv,
 	data:		(void *) 1,	/* yap, I understand shared skbs :-) */
 };
 
-static struct packet_type ipx_dix_packet_type =
-{
+static struct packet_type ipx_dix_packet_type = {
 	type:		__constant_htons(ETH_P_IPX),
 	func:		ipx_rcv,
 	data:		(void *) 1,	/* yap, I understand shared skbs :-) */
@@ -2565,7 +2537,7 @@
 static unsigned char ipx_8022_type = 0xE0;
 static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
 static const char banner[] __initdata =
-	KERN_INFO "NET4: Linux IPX 0.46 for NET4.0\n"
+	KERN_INFO "NET4: Linux IPX 0.47 for NET4.0\n"
 	KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n" \
 	KERN_INFO "IPX Portions Copyright (c) 2000, 2001 Conectiva, Inc.\n";
 
@@ -2579,11 +2551,11 @@
 	p8023_datalink = make_8023_client();
 	dev_add_pack(&ipx_8023_packet_type);
 
-	p8022_datalink = register_8022_client(ipx_8022_type,ipx_rcv);
+	p8022_datalink = register_8022_client(ipx_8022_type, ipx_rcv);
 	if (!p8022_datalink)
 		printk(KERN_CRIT "IPX: Unable to register with 802.2\n");
 
-	pSNAP_datalink = register_snap_client(ipx_snap_id,ipx_rcv);
+	pSNAP_datalink = register_snap_client(ipx_snap_id, ipx_rcv);
 	if (!pSNAP_datalink)
 		printk(KERN_CRIT "IPX: Unable to register with SNAP\n");
 
diff -urN linux-2.4.5-pre2/net/ipx/af_spx.c linux/net/ipx/af_spx.c
--- linux-2.4.5-pre2/net/ipx/af_spx.c	Thu Apr 19 08:38:50 2001
+++ linux/net/ipx/af_spx.c	Mon Dec  3 22:43:26 2001
@@ -6,7 +6,7 @@
  *		 Revision Date:  February 9, 1993
  *
  *	Developers:
- *      Jay Schulist    <jschlst@turbolinux.com>
+ *      Jay Schulist    <jschlst@samba.org>
  *	Jim Freeman	<jfree@caldera.com>
  *
  *	Changes:
diff -urN linux-2.4.5-pre2/net/ipx/sysctl_net_ipx.c linux/net/ipx/sysctl_net_ipx.c
--- linux-2.4.5-pre2/net/ipx/sysctl_net_ipx.c	Thu Apr 12 12:16:36 2001
+++ linux/net/ipx/sysctl_net_ipx.c	Mon Dec  3 22:43:26 2001
@@ -10,10 +10,13 @@
 #include <linux/mm.h>
 #include <linux/sysctl.h>
 
+#ifndef CONFIG_SYSCTL
+#error This file should not be compiled without CONFIG_SYSCTL defined
+#endif
+
 /* From af_ipx.c */
 extern int sysctl_ipx_pprop_broadcasting;
 
-#ifdef CONFIG_SYSCTL
 ctl_table ipx_table[] = {
 	{ NET_IPX_PPROP_BROADCASTING, "ipx_pprop_broadcasting",
 	  &sysctl_ipx_pprop_broadcasting, sizeof(int), 0644, NULL,
@@ -42,13 +45,3 @@
 {
 	unregister_sysctl_table(ipx_table_header);
 }
-
-#else
-void ipx_register_sysctl(void)
-{
-}
-
-void ipx_unregister_sysctl(void)
-{
-}
-#endif
