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

diff -urN linux-2.4.17-pre7/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.4.17-pre7/Documentation/Configure.help	Mon Dec 10 13:24:24 2001
+++ linux/Documentation/Configure.help	Mon Dec 10 13:24:27 2001
@@ -11067,6 +11067,17 @@
 
   If unsure, say N.
 
+VIA Rhine MMIO support (EXPERIMENTAL)
+CONFIG_VIA_RHINE_MMIO
+  This instructs the driver to use PCI shared memory (MMIO) instead of
+  programmed I/O ports (PIO). Enabling this gives an improvement in
+  processing time in parts of the driver.
+
+  It is not known if this works reliably on all "rhine" based cards,
+  but it has been tested successfully on some DFE-530TX adapters.
+
+  If unsure, say N.
+
 Davicom DM910x/DM980x support
 CONFIG_DM9102
   This driver is for DM9102(A)/DM9132/DM9801 compatible PCI cards from
@@ -22544,10 +22555,15 @@
 National Semiconductor DP83820 support
 CONFIG_NS83820
   This is a driver for the National Semiconductor DP83820 series
-  of gigabit ethernet MACs.  Cards using this chipset include
-  the D-Link DGE-500T, PureData's PDP8023Z-TG, SMC's SMC9462TX,
-  SOHO-GA2000T, SOHO-GA2500T.  The driver supports the use of
-  zero copy.
+  of gigabit ethernet MACs.  Cards using this chipset include:
+
+        SMC 9452TX          SMC SMC9462TX       
+        D-Link DGE-500T     PureData PDP8023Z-TG
+        SOHO-GA2000T        SOHO-GA2500T.
+        NetGear GA621
+
+  This driver supports the use of zero copy on tx, checksum 
+  validation on rx, and 64 bit addressing.
 
 Toshiba Type-O IR Port device driver
 CONFIG_TOSHIBA_FIR
diff -urN linux-2.4.17-pre7/Documentation/DocBook/via-audio.tmpl linux/Documentation/DocBook/via-audio.tmpl
--- linux-2.4.17-pre7/Documentation/DocBook/via-audio.tmpl	Fri Nov  9 13:45:35 2001
+++ linux/Documentation/DocBook/via-audio.tmpl	Mon Dec 10 13:24:27 2001
@@ -8,11 +8,6 @@
    <author>
     <firstname>Jeff</firstname>
     <surname>Garzik</surname>
-    <affiliation>
-     <address>
-      <email>jgarzik@mandrakesoft.com</email>
-     </address>
-    </affiliation>
    </author>
   </authorgroup>
 
@@ -115,7 +110,7 @@
   <sect1 id="bugrepdiag"><title>Diagnostic output</title>
   <para>
 	Obtain the via-audio-diag diagnostics program from
-	http://gtf.org/garzik/drivers/via82cxxx/ and provide a dump of the
+	http://sf.net/projects/gkernel/ and provide a dump of the
 	audio chip's registers while the problem is occurring.  Sample command line:
   </para>
   <programlisting>
diff -urN linux-2.4.17-pre7/Documentation/networking/tulip.txt linux/Documentation/networking/tulip.txt
--- linux-2.4.17-pre7/Documentation/networking/tulip.txt	Fri Mar  2 11:02:14 2001
+++ linux/Documentation/networking/tulip.txt	Wed Dec 31 16:00:00 1969
@@ -1,226 +0,0 @@
-                Tulip Ethernet Card Driver
-	  Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
-
-The Tulip driver was developed by Donald Becker and changed by
-Takashi Manabe and a cast of thousands.
-
-For 2.4.x and later kernels, the Linux Tulip driver is available at
-http://sourceforge.net/projects/tulip/
-
-	This driver is for the Digital "Tulip" Ethernet adapter interface.
-	It should work with most DEC 21*4*-based chips/ethercards, as well as
-	with work-alike chips from Lite-On (PNIC) and Macronix (MXIC) and ASIX.
-
-	The author may be reached as becker@scyld.com, or C/O
-	Center of Excellence in Space Data and Information Sciences
-	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
-
-	Additional information on Donald Becker's tulip.c
-	is available at http://www.scyld.com/network/tulip.html
-
-
-
-
-				Theory of Operation
-
-Board Compatibility
-===================
-
-This device driver is designed for the DECchip "Tulip", Digital's
-single-chip ethernet controllers for PCI.  Supported members of the family
-are the 21040, 21041, 21140, 21140A, 21142, and 21143.  Similar work-alike
-chips from Lite-On, Macronics, ASIX, Compex and other listed below are also
-supported.
-
-These chips are used on at least 140 unique PCI board designs.  The great
-number of chips and board designs supported is the reason for the
-driver size and complexity.  Almost of the increasing complexity is in the
-board configuration and media selection code.  There is very little
-increasing in the operational critical path length.
-
-Board-specific settings
-=======================
-
-PCI bus devices are configured by the system at boot time, so no jumpers
-need to be set on the board.  The system BIOS preferably should assign the
-PCI INTA signal to an otherwise unused system IRQ line.
-
-Some boards have EEPROMs tables with default media entry.  The factory default
-is usually "autoselect".  This should only be overridden when using
-transceiver connections without link beat e.g. 10base2 or AUI, or (rarely!)
-for forcing full-duplex when used with old link partners that do not do
-autonegotiation.
-
-Driver operation
-================
-
-Ring buffers
-------------
-
-The Tulip can use either ring buffers or lists of Tx and Rx descriptors.
-This driver uses statically allocated rings of Rx and Tx descriptors, set at
-compile time by RX/TX_RING_SIZE.  This version of the driver allocates skbuffs
-for the Rx ring buffers at open() time and passes the skb->data field to the
-Tulip as receive data buffers.  When an incoming frame is less than
-RX_COPYBREAK bytes long, a fresh skbuff is allocated and the frame is
-copied to the new skbuff.  When the incoming frame is larger, the skbuff is
-passed directly up the protocol stack and replaced by a newly allocated
-skbuff.
-
-The RX_COPYBREAK value is chosen to trade-off the memory wasted by
-using a full-sized skbuff for small frames vs. the copying costs of larger
-frames.  For small frames the copying cost is negligible (esp. considering
-that we are pre-loading the cache with immediately useful header
-information).  For large frames the copying cost is non-trivial, and the
-larger copy might flush the cache of useful data.  A subtle aspect of this
-choice is that the Tulip only receives into longword aligned buffers, thus
-the IP header at offset 14 isn't longword aligned for further processing.
-Copied frames are put into the new skbuff at an offset of "+2", thus copying
-has the beneficial effect of aligning the IP header and preloading the
-cache.
-
-Synchronization
----------------
-The driver runs as two independent, single-threaded flows of control.  One
-is the send-packet routine, which enforces single-threaded use by the
-dev->tbusy flag.  The other thread is the interrupt handler, which is single
-threaded by the hardware and other software.
-
-The send packet thread has partial control over the Tx ring and 'dev->tbusy'
-flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'tp->tx_full' flag.
-
-The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
-we can't avoid the interrupt overhead by having the Tx routine reap the Tx
-stats.)	 After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero.	 Iff the 'tp->tx_full' flag is set, it clears both the
-tx_full and tbusy flags.
-
-Notes
-=====
-
-Thanks to Duke Kamstra of SMC for long ago providing an EtherPower board.
-Greg LaPolla at Linksys provided PNIC and other Linksys boards.
-Znyx provided a four-port card for testing.
-
-References
-==========
-
-http://cesdis.gsfc.nasa.gov/linux/misc/NWay.html
-http://www.digital.com  (search for current 21*4* datasheets and "21X4 SROM")
-http://www.national.com/pf/DP/DP83840A.html
-http://www.asix.com.tw/pmac.htm
-http://www.admtek.com.tw/
-
-Errata
-======
-
-The old DEC databooks were light on details.
-The 21040 databook claims that CSR13, CSR14, and CSR15 should each be the last
-register of the set CSR12-15 written.  Hmmm, now how is that possible?
-
-The DEC SROM format is very badly designed not precisely defined, leading to
-part of the media selection junkheap below.  Some boards do not have EEPROM
-media tables and need to be patched up.  Worse, other boards use the DEC
-design kit media table when it isn't correct for their board.
-
-We cannot use MII interrupts because there is no defined GPIO pin to attach
-them.  The MII transceiver status is polled using an kernel timer.
-
-
-Source tree tour
-================
-The following is a list of files comprising the Tulip ethernet driver in
-drivers/net/tulip subdirectory.
-
-21142.c		- 21142-specific h/w interaction
-eeprom.c	- EEPROM reading and parsing
-interrupt.c	- Interrupt handler
-media.c		- Media selection and MII support
-pnic.c		- PNIC-specific h/w interaction
-timer.c		- Main driver timer, and misc h/w timers
-tulip.h		- Private driver header
-tulip_core.c	- Driver core (a.k.a. where "everything else" goes)
-
-
-
-Version history
-===============
-0.9.14 (February 20, 2000):
-* Fix PNIC problems (Manfred Spraul)
-* Add new PCI id for Accton comet
-* Support Davicom tulips
-* Fix oops in eeprom parsing
-* Enable workarounds for early PCI chipsets
-* IA64, hppa csr0 support
-* Support media types 5, 6
-* Interpret a bit more of the 21142 SROM extended media type 3
-* Add missing delay in eeprom reading
-
-0.9.11 (November 3, 2000):
-* Eliminate extra bus accesses when sharing interrupts (prumpf)
-* Barrier following ownership descriptor bit flip (prumpf)
-* Endianness fixes for >14 addresses in setup frames (prumpf)
-* Report link beat to kernel/userspace via netif_carrier_*. (kuznet)
-* Better spinlocking in set_rx_mode.
-* Fix I/O resource request failure error messages (DaveM catch)
-* Handle DMA allocation failure.
-
-0.9.10 (September 6, 2000):
-* Simple interrupt mitigation (via jamal)
-* More PCI ids
-
-0.9.9 (August 11, 2000):
-* More PCI ids
-
-0.9.8 (July 13, 2000):
-* Correct signed/unsigned comparison for dummy frame index
-* Remove outdated references to struct enet_statistics
-
-0.9.7 (June 17, 2000):
-* Timer cleanups (Andrew Morton)
-* Alpha compile fix (somebody?)
-
-0.9.6 (May 31, 2000):
-* Revert 21143-related support flag patch
-* Add HPPA/media-table debugging printk
-
-0.9.5 (May 30, 2000):
-* HPPA support (willy@puffingroup)
-* CSR6 bits and tulip.h cleanup (Chris Smith)
-* Improve debugging messages a bit
-* Add delay after CSR13 write in t21142_start_nway
-* Remove unused ETHER_STATS code
-* Convert 'extern inline' to 'static inline' in tulip.h (Chris Smith)
-* Update DS21143 support flags in tulip_chip_info[]
-* Use spin_lock_irq, not _irqsave/restore, in tulip_start_xmit()
-* Add locking to set_rx_mode()
-* Fix race with chip setting DescOwned bit (Hal Murray)
-* Request 100% of PIO and MMIO resource space assigned to card
-* Remove error message from pci_enable_device failure
-
-0.9.4.3 (April 14, 2000):
-* mod_timer fix (Hal Murray)
-* PNIC2 resuscitation (Chris Smith)
-
-0.9.4.2 (March 21, 2000):
-* Fix 21041 CSR7, CSR13/14/15 handling
-* Merge some PCI ids from tulip 0.91x
-* Merge some HAS_xxx flags and flag settings from tulip 0.91x
-* asm/io.h fix (submitted by many) and cleanup
-* s/HAS_NWAY143/HAS_NWAY/
-* Cleanup 21041 mode reporting
-* Small code cleanups
-
-0.9.4.1 (March 18, 2000):
-* Finish PCI DMA conversion (davem)
-* Do not netif_start_queue() at end of tulip_tx_timeout() (kuznet)
-* PCI DMA fix (kuznet)
-* eeprom.c code cleanup
-* Remove Xircom Tulip crud
-
-
-[EOF]
-
diff -urN linux-2.4.17-pre7/MAINTAINERS linux/MAINTAINERS
--- linux-2.4.17-pre7/MAINTAINERS	Mon Dec 10 13:24:25 2001
+++ linux/MAINTAINERS	Mon Dec 10 13:24:28 2001
@@ -1704,10 +1704,8 @@
 
 VIA 82Cxxx AUDIO DRIVER
 P:	Jeff Garzik
-M:	jgarzik@mandrakesoft.com
 L:	linux-via@gtf.org
-W:	http://sourceforge.net/projects/gkernel/
-S:	Maintained
+S:	Odd fixes
 
 USB DIAMOND RIO500 DRIVER
 P:	Cesar Miquel
diff -urN linux-2.4.17-pre7/Makefile linux/Makefile
--- linux-2.4.17-pre7/Makefile	Mon Dec 10 13:24:25 2001
+++ linux/Makefile	Mon Dec 10 13:24:28 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 17
-EXTRAVERSION = -pre7
+EXTRAVERSION = -pre8
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -urN linux-2.4.17-pre7/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- linux-2.4.17-pre7/arch/i386/kernel/dmi_scan.c	Mon Dec 10 13:24:25 2001
+++ linux/arch/i386/kernel/dmi_scan.c	Mon Dec 10 13:24:28 2001
@@ -523,6 +523,12 @@
 			MATCH(DMI_BIOS_DATE, "05/11/00"), NO_MATCH
 			} },
 
+	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z600NE */
+			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
+			MATCH(DMI_BIOS_VERSION, "WME01Z1"),
+			MATCH(DMI_BIOS_DATE, "08/11/00"), NO_MATCH
+			} },
+
 	{ swab_apm_power_in_minutes, "Sony VAIO", {	/* Handle problems with APM on Sony Vaio PCG-Z505LS */
 			MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
 			MATCH(DMI_BIOS_VERSION, "R0203D0"),
diff -urN linux-2.4.17-pre7/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux-2.4.17-pre7/arch/i386/kernel/setup.c	Mon Dec 10 13:24:25 2001
+++ linux/arch/i386/kernel/setup.c	Mon Dec 10 13:24:28 2001
@@ -1281,7 +1281,6 @@
 			break;
 
 		case 6: /* An Athlon/Duron */
- 			mcheck_init(c);
  
 			/* Bit 15 of Athlon specific MSR 15, needs to be 0
  			 * to enable SSE on Palomino/Morgan CPU's.
@@ -1928,7 +1927,6 @@
 				c->x86_cache_size = (cc>>24)+(dd>>24);
 			}
 			sprintf( c->x86_model_id, "WinChip %s", name );
-			mcheck_init(c);
 			break;
 
 		case 6:
@@ -2214,7 +2212,7 @@
 		strcpy(c->x86_model_id, p);
 	
 #ifdef CONFIG_SMP
-	if (test_bit(X86_FEATURE_HT, &c->x86_capability[0])) {
+	if (test_bit(X86_FEATURE_HT, &c->x86_capability)) {
 		extern	int phys_proc_id[NR_CPUS];
 		
 		u32 	eax, ebx, ecx, edx;
@@ -2262,8 +2260,6 @@
 	}
 too_many_siblings:
 #endif
-	/* Enable MCA if available */
-	mcheck_init(c);
 }
 
 void __init get_cpu_vendor(struct cpuinfo_x86 *c)
@@ -2643,7 +2639,7 @@
 		init_rise(c);
 		break;
 	}
-	
+
 	printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
 	       c->x86_capability[0],
 	       c->x86_capability[1],
@@ -2669,6 +2665,9 @@
 
 	/* Disable the PN if appropriate */
 	squash_the_stupid_serial_number(c);
+
+	/* Init Machine Check Exception if available. */
+	mcheck_init(c);
 
 	/* If the model name is still unset, do table lookup. */
 	if ( !c->x86_model_id[0] ) {
diff -urN linux-2.4.17-pre7/drivers/block/nbd.c linux/drivers/block/nbd.c
--- linux-2.4.17-pre7/drivers/block/nbd.c	Fri Oct 26 15:39:02 2001
+++ linux/drivers/block/nbd.c	Mon Dec 10 13:24:28 2001
@@ -45,7 +45,6 @@
 
 #include <linux/devfs_fs_kernel.h>
 
-#include <asm/segment.h>
 #include <asm/uaccess.h>
 #include <asm/types.h>
 
diff -urN linux-2.4.17-pre7/drivers/char/console.c linux/drivers/char/console.c
--- linux-2.4.17-pre7/drivers/char/console.c	Mon Oct 15 14:00:43 2001
+++ linux/drivers/char/console.c	Mon Dec 10 13:24:28 2001
@@ -2599,10 +2599,10 @@
 
 static void set_vesa_blanking(unsigned long arg)
 {
-    char *argp = (char *)arg + 1;
-    unsigned int mode;
-    get_user(mode, argp);
-    vesa_blank_mode = (mode < 4) ? mode : 0;
+	char *argp = (char *)arg + 1;
+	unsigned int mode;
+	if (get_user(mode, argp) == 0)
+		vesa_blank_mode = (mode < 4) ? mode : 0;
 }
 
 /* We can't register the console with devfs during con_init(), because it
diff -urN linux-2.4.17-pre7/drivers/isdn/hisax/hisax_fcpcipnp.c linux/drivers/isdn/hisax/hisax_fcpcipnp.c
--- linux-2.4.17-pre7/drivers/isdn/hisax/hisax_fcpcipnp.c	Mon Dec 10 13:24:26 2001
+++ linux/drivers/isdn/hisax/hisax_fcpcipnp.c	Mon Dec 10 13:24:28 2001
@@ -947,14 +947,14 @@
 static struct pci_driver fcpci_driver = {
 	name:     "fcpci",
 	probe:    fcpci_probe,
-	remove:   fcpci_remove,
+	remove:   __devexit_p(fcpci_remove),
 	id_table: fcpci_ids,
 };
 
 static struct isapnp_driver fcpnp_driver = {
 	name:     "fcpnp",
 	probe:    fcpnp_probe,
-	remove:   fcpnp_remove,
+	remove:   __devexit_p(fcpnp_remove),
 	id_table: fcpnp_ids,
 };
 
diff -urN linux-2.4.17-pre7/drivers/net/ns83820.c linux/drivers/net/ns83820.c
--- linux-2.4.17-pre7/drivers/net/ns83820.c	Mon Dec 10 13:24:26 2001
+++ linux/drivers/net/ns83820.c	Mon Dec 10 13:24:28 2001
@@ -1,7 +1,7 @@
-#define VERSION "0.13"
-/* ns83820.c by Benjamin LaHaise <bcrl@redhat.com>
+#define _VERSION "0.15"
+/* ns83820.c by Benjamin LaHaise <bcrl@redhat.com> with contributions.
  *
- * $Revision: 1.34.2.8 $
+ * $Revision: 1.34.2.12 $
  *
  * Copyright 2001 Benjamin LaHaise.
  * Copyright 2001 Red Hat.
@@ -45,6 +45,12 @@
  *			0.12 - add statistics counters
  *			     - add allmulti/promisc support
  *	20011009	0.13 - hotplug support, other smaller pci api cleanups
+ *	20011204	0.13a - optical transceiver support added
+ *				by Michael Clark <michael@metaparadigm.com>
+ *	20011205	0.13b - call register_netdev earlier in initialization
+ *				suppress duplicate link status messages
+ *	20011117 	0.14 - ethtool GDRVINFO, GLINK support from jgarzik
+ *	20011204 	0.15	get ppc (big endian) working
  *
  * Driver Overview
  * ===============
@@ -65,6 +71,7 @@
  *	D-Link		DGE-500T
  *	PureData	PDP8023Z-TG
  *	SMC		SMC9452TX	SMC9462TX
+ *	Netgear		GA621
  *
  * Special thanks to SMC for providing hardware to test this driver on.
  *
@@ -86,23 +93,25 @@
 #include <linux/in.h>	/* for IPPROTO_... */
 #include <linux/eeprom.h>
 #include <linux/compiler.h>
+#include <linux/ethtool.h>
 //#include <linux/skbrefill.h>
 
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /* Dprintk is used for more interesting debug events */
 #undef Dprintk
 #define	Dprintk			dprintk
 
 #ifdef CONFIG_HIGHMEM64G
-#define USE_64BIT_ADDR
+#define USE_64BIT_ADDR	"+"
 #elif defined(__ia64__)
-#define USE_64BIT_ADDR
+#define USE_64BIT_ADDR	"+"
 #endif
 
 /* Tell davem to fix the pci dma api.  Grrr. */
 /* stolen from acenic.c */
-#ifdef CONFIG_HIGHMEM
+#if 0 //def CONFIG_HIGHMEM
 #if defined(CONFIG_X86)
 #define DMAADDR_OFFSET  0
 #if defined(CONFIG_HIGHMEM64G)
@@ -138,6 +147,12 @@
 }
 #endif
 
+#if defined(USE_64BIT_ADDR)
+#define	VERSION	_VERSION USE_64BIT_ADDR
+#else
+#define	VERSION	_VERSION
+#endif
+
 /* tunables */
 #define RX_BUF_SIZE	6144	/* 8192 */
 #define NR_RX_DESC	256
@@ -213,6 +228,7 @@
 #define CFG_DUPSTS	0x10000000
 #define CFG_TBI_EN	0x01000000
 #define CFG_MODE_1000	0x00400000
+#define CFG_AUTO_1000	0x00200000
 #define CFG_PINT_CTL	0x001c0000
 #define CFG_PINT_DUPSTS	0x00100000
 #define CFG_PINT_LNKSTS	0x00080000
@@ -316,6 +332,36 @@
 #define VDR		0xc4
 #define CCSR		0xcc
 
+#define TBICR		0xe0
+#define TBISR		0xe4
+#define TANAR		0xe8
+#define TANLPAR		0xec
+#define TANER		0xf0
+#define TESR		0xf4
+
+#define TBICR_MR_AN_ENABLE	0x00001000
+#define TBICR_MR_RESTART_AN	0x00000200
+
+#define TBISR_MR_LINK_STATUS	0x00000020
+#define TBISR_MR_AN_COMPLETE	0x00000004
+
+#define TANAR_PS2 		0x00000100
+#define TANAR_PS1 		0x00000080
+#define TANAR_HALF_DUP 		0x00000040
+#define TANAR_FULL_DUP 		0x00000020
+
+#define GPIOR_GP5_OE		0x00000200
+#define GPIOR_GP4_OE		0x00000100
+#define GPIOR_GP3_OE		0x00000080
+#define GPIOR_GP2_OE		0x00000040
+#define GPIOR_GP1_OE		0x00000020
+#define GPIOR_GP3_OUT		0x00000004
+#define GPIOR_GP1_OUT		0x00000001
+
+#define LINK_AUTONEGOTIATE	0x01
+#define LINK_DOWN		0x02
+#define LINK_UP			0x04
+
 #define __kick_rx(dev)	writel(CR_RXE, dev->base + CR)
 
 #define kick_rx(dev) do { \
@@ -390,6 +436,7 @@
 	u32			IMR_cache;
 	struct eeprom		ee;
 
+	unsigned		linkstate;
 
 	spinlock_t	tx_lock;
 
@@ -441,11 +488,11 @@
 
 static inline void build_rx_desc32(struct ns83820 *dev, u32 *desc, u32 link, u32 buf, u32 cmdsts, u32 extsts)
 {
-	desc[0] = link;
-	desc[1] = buf;
-	desc[3] = extsts;
+	desc[0] = cpu_to_le32(link);
+	desc[1] = cpu_to_le32(buf);
+	desc[3] = cpu_to_le32(extsts);
 	mb();
-	desc[2] = cmdsts;
+	desc[2] = cpu_to_le32(cmdsts);
 }
 
 #define build_rx_desc	build_rx_desc32
@@ -486,7 +533,7 @@
 	build_rx_desc(dev, sg, 0, buf, cmdsts, 0);
 	/* update link of previous rx */
 	if (next_empty != dev->rx_info.next_rx)
-		dev->rx_info.descs[((NR_RX_DESC + next_empty - 1) % NR_RX_DESC) * DESC_SIZE] = dev->rx_info.phy_descs + (next_empty * DESC_SIZE * 4);
+		dev->rx_info.descs[((NR_RX_DESC + next_empty - 1) % NR_RX_DESC) * DESC_SIZE] = cpu_to_le32(dev->rx_info.phy_descs + (next_empty * DESC_SIZE * 4));
 
 	return 0;
 }
@@ -545,39 +592,93 @@
 
 static void phy_intr(struct ns83820 *dev)
 {
-	static char *speeds[] = { "10", "100", "1000", "1000(?)" };
+	static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" };
 	u32 cfg, new_cfg;
+	u32 tbisr, tanar, tanlpar;
+	int speed, fullduplex, newlinkstate;
 
-	new_cfg = dev->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);
 	cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
 
-	if (cfg & CFG_SPDSTS1)
-		new_cfg |= CFG_MODE_1000 | CFG_SB;
-	else
-		new_cfg &= ~CFG_MODE_1000 | CFG_SB;
+	if (dev->CFG_cache & CFG_TBI_EN) {
 
-	if ((cfg & CFG_LNKSTS) && ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) {
-		writel(new_cfg, dev->base + CFG);
-		dev->CFG_cache = new_cfg;
-	}
+		/* we have an optical transceiver */
+		tbisr = readl(dev->base + TBISR);
+		tanar = readl(dev->base + TANAR);
+		tanlpar = readl(dev->base + TANLPAR);
+		dprintk("phy_intr: tbisr=%08x, tanar=%08x, tanlpar=%08x\n",
+			tbisr, tanar, tanlpar);
+
+		if ( (fullduplex = (tanlpar & TANAR_FULL_DUP)
+		      && (tanar & TANAR_FULL_DUP)) ) {
+
+			/* both of us are full duplex */
+			writel(readl(dev->base + TXCFG)
+			       | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP,
+			       dev->base + TXCFG);
+			writel(readl(dev->base + RXCFG) | RXCFG_RX_FD,
+			       dev->base + RXCFG);
+			/* Light up full duplex LED */
+			writel(readl(dev->base + GPIOR) | GPIOR_GP1_OUT,
+			       dev->base + GPIOR);
+
+		} else if(((tanlpar & TANAR_HALF_DUP)
+			   && (tanar & TANAR_HALF_DUP))
+			|| ((tanlpar & TANAR_FULL_DUP)
+			    && (tanar & TANAR_HALF_DUP))
+			|| ((tanlpar & TANAR_HALF_DUP)
+			    && (tanar & TANAR_FULL_DUP))) {
+
+			/* one or both of us are half duplex */
+			writel((readl(dev->base + TXCFG)
+				& ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP,
+			       dev->base + TXCFG);
+			writel(readl(dev->base + RXCFG) & ~RXCFG_RX_FD,
+			       dev->base + RXCFG);
+			/* Turn off full duplex LED */
+			writel(readl(dev->base + GPIOR) & ~GPIOR_GP1_OUT,
+			       dev->base + GPIOR);
+		}
 
-	dev->CFG_cache &= ~CFG_SPDSTS;
-	dev->CFG_cache |= cfg & CFG_SPDSTS;
+		speed = 4; /* 1000F */
 
-	if (cfg & CFG_LNKSTS) {
-		netif_start_queue(&dev->net_dev);
-		netif_wake_queue(&dev->net_dev);
 	} else {
-		netif_stop_queue(&dev->net_dev);
+		/* we have a copper transceiver */
+		new_cfg = dev->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);
+
+		if (cfg & CFG_SPDSTS1)
+			new_cfg |= CFG_MODE_1000 | CFG_SB;
+		else
+			new_cfg &= ~CFG_MODE_1000 | CFG_SB;
+
+		if ((cfg & CFG_LNKSTS) && ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) {
+			writel(new_cfg, dev->base + CFG);
+			dev->CFG_cache = new_cfg;
+		}
+
+		dev->CFG_cache &= ~CFG_SPDSTS;
+		dev->CFG_cache |= cfg & CFG_SPDSTS;
+
+		speed = ((cfg / CFG_SPDSTS0) & 3);
+		fullduplex = (cfg & CFG_DUPSTS);
 	}
 
-	if (cfg & CFG_LNKSTS)
+	newlinkstate = (cfg & CFG_LNKSTS) ? LINK_UP : LINK_DOWN;
+
+	if (newlinkstate & LINK_UP
+	    && dev->linkstate != newlinkstate) {
+		netif_start_queue(&dev->net_dev);
+		netif_wake_queue(&dev->net_dev);
 		printk(KERN_INFO "%s: link now %s mbps, %s duplex and up.\n",
 			dev->net_dev.name,
-			speeds[((cfg / CFG_SPDSTS0) & 3)],
-			(cfg & CFG_DUPSTS) ? "full" : "half");
-	else
+			speeds[speed],
+			fullduplex ? "full" : "half");
+	} else if (newlinkstate & LINK_DOWN
+		   && dev->linkstate != newlinkstate) {
+		netif_stop_queue(&dev->net_dev);
 		printk(KERN_INFO "%s: link now down.\n", dev->net_dev.name);
+	}
+
+	dev->linkstate = newlinkstate;
 }
 
 static int ns83820_setup_rx(struct ns83820 *dev)
@@ -698,15 +799,15 @@
 	dprintk("walking descs\n");
 	next_rx = info->next_rx;
 	desc = info->descs + (DESC_SIZE * next_rx);
-	while ((CMDSTS_OWN & (cmdsts = desc[CMDSTS])) &&
+	while ((CMDSTS_OWN & (cmdsts = le32_to_cpu(desc[CMDSTS]))) &&
 	       (cmdsts != CMDSTS_OWN)) {
 		struct sk_buff *skb;
-		u32 extsts = desc[EXTSTS];
-		dmaaddr_high_t bufptr = *(hw_addr_t *)(desc + BUFPTR);
+		u32 extsts = le32_to_cpu(desc[EXTSTS]);
+		dmaaddr_high_t bufptr = le32_to_cpu(desc[BUFPTR]);
 
 		dprintk("cmdsts: %08x\n", cmdsts);
-		dprintk("link: %08x\n", desc[LINK]);
-		dprintk("extsts: %08x\n", desc[EXTSTS]);
+		dprintk("link: %08x\n", cpu_to_le32(desc[LINK]));
+		dprintk("extsts: %08x\n", extsts);
 
 		skb = info->skbs[next_rx];
 		info->skbs[next_rx] = NULL;
@@ -718,14 +819,14 @@
 		pci_unmap_single(dev->pci_dev, bufptr,
 				 RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
 		if (CMDSTS_OK & cmdsts) {
-#ifndef __i386__
+#if 0 //ndef __i386__
 			struct sk_buff *tmp;
 #endif
 			int len = cmdsts & 0xffff;
 			if (!skb)
 				BUG();
 			skb_put(skb, len);
-#ifndef __i386__	/* I hate the network stack sometimes */
+#if 0 //ndef __i386__	/* I hate the network stack sometimes */
 			tmp = __dev_alloc_skb(RX_BUF_SIZE+16, GFP_ATOMIC);
 			if (!tmp)
 				goto done;
@@ -788,9 +889,9 @@
 	desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
 
 	dprintk("tx_done_idx=%d free_idx=%d cmdsts=%08x\n",
-		tx_done_idx, dev->tx_free_idx, desc[CMDSTS]);
+		tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[CMDSTS]));
 	while ((tx_done_idx != dev->tx_free_idx) &&
-	       !(CMDSTS_OWN & (cmdsts = desc[CMDSTS])) ) {
+	       !(CMDSTS_OWN & (cmdsts = le32_to_cpu(desc[CMDSTS]))) ) {
 		struct sk_buff *skb;
 
 		if (cmdsts & CMDSTS_ERR)
@@ -801,13 +902,13 @@
 			dev->stats.tx_bytes += cmdsts & 0xffff;
 
 		dprintk("tx_done_idx=%d free_idx=%d cmdsts=%08x\n",
-			tx_done_idx, dev->tx_free_idx, desc[CMDSTS]);
+			tx_done_idx, dev->tx_free_idx, cmdsts);
 		skb = dev->tx_skbs[tx_done_idx];
 		dev->tx_skbs[tx_done_idx] = NULL;
 		dprintk("done(%p)\n", skb);
 		if (skb) {
 			pci_unmap_single(dev->pci_dev,
-					*(hw_addr_t *)(desc + BUFPTR),
+					le32_to_cpu(desc[BUFPTR]),
 					skb->len,
 					PCI_DMA_TODEVICE);
 			dev_kfree_skb_irq(skb);
@@ -815,7 +916,7 @@
 
 		tx_done_idx = (tx_done_idx + 1) % NR_TX_DESC;
 		dev->tx_done_idx = tx_done_idx;
-		desc[CMDSTS] = 0;
+		desc[CMDSTS] = cpu_to_le32(0);
 		barrier();
 		desc = dev->tx_descs + (tx_done_idx * DESC_SIZE);
 	}
@@ -936,17 +1037,17 @@
 		}
 #endif
 
-		dprintk("frag[%3u]: %4u @ 0x%x%08Lx\n", free_idx, len,
+		dprintk("frag[%3u]: %4u @ 0x%08Lx\n", free_idx, len,
 			(unsigned long long)buf);
 		free_idx = (free_idx + 1) % NR_TX_DESC;
-		desc[LINK] = dev->tx_phy_descs + (free_idx * DESC_SIZE * 4);
-		*(hw_addr_t *)(desc + BUFPTR) = buf;
-		desc[EXTSTS] = extsts;
+		desc[LINK] = cpu_to_le32(dev->tx_phy_descs + (free_idx * DESC_SIZE * 4));
+		desc[BUFPTR] = cpu_to_le32(buf);
+		desc[EXTSTS] = cpu_to_le32(extsts);
 
 		cmdsts = ((nr_frags|residue) ? CMDSTS_MORE : do_intr ? CMDSTS_INTR : 0);
 		cmdsts |= (desc == first_desc) ? 0 : CMDSTS_OWN;
 		cmdsts |= len;
-		desc[CMDSTS] = cmdsts;
+		desc[CMDSTS] = cpu_to_le32(cmdsts);
 
 		if (residue) {
 			buf += len;
@@ -967,7 +1068,7 @@
 	}
 	dprintk("done pkt\n");
 	dev->tx_skbs[free_idx] = skb;
-	first_desc[CMDSTS] |= CMDSTS_OWN;
+	first_desc[CMDSTS] |= cpu_to_le32(CMDSTS_OWN);
 	dev->tx_free_idx = free_idx;
 	kick_tx(dev);
 
@@ -1007,6 +1108,59 @@
 	return &dev->stats;
 }
 
+static int ns83820_ethtool_ioctl (struct ns83820 *dev, void *useraddr)
+{
+	u32 ethcmd;
+
+	if (copy_from_user(&ethcmd, useraddr, sizeof (ethcmd)))
+		return -EFAULT;
+
+	switch (ethcmd) {
+	case ETHTOOL_GDRVINFO:
+		{
+			struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+			strcpy(info.driver, "ns83820");
+			strcpy(info.version, VERSION);
+			strcpy(info.bus_info, dev->pci_dev->slot_name);
+			if (copy_to_user(useraddr, &info, sizeof (info)))
+				return -EFAULT;
+			return 0;
+		}
+
+	/* get link status */
+	case ETHTOOL_GLINK: {
+		struct ethtool_value edata = { ETHTOOL_GLINK };
+		u32 cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
+
+		if (cfg & CFG_LNKSTS)
+			edata.data = 1;
+		else
+			edata.data = 0;
+		if (copy_to_user(useraddr, &edata, sizeof(edata)))
+			return -EFAULT;
+		return 0;
+	}
+
+	default:
+		break;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int ns83820_ioctl(struct net_device *_dev, struct ifreq *rq, int cmd)
+{
+	struct ns83820 *dev = _dev->priv;
+
+	switch(cmd) {
+	case SIOCETHTOOL:
+		return ns83820_ethtool_ioctl(dev, (void *) rq->ifr_data);
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 static void ns83820_irq(int foo, void *data, struct pt_regs *regs)
 {
 	struct ns83820 *dev = data;
@@ -1048,10 +1202,14 @@
 			Dprintk("BAD\n");
 	}
 
-	if (ISR_RXSOVR & isr)
-		Dprintk("overrun\n");
-	if (ISR_RXORN & isr)
-		Dprintk("overrun\n");
+	if (unlikely(ISR_RXSOVR & isr)) {
+		Dprintk("overrun: rxsovr\n");
+		dev->stats.rx_over_errors ++;
+	}
+	if (unlikely(ISR_RXORN & isr)) {
+		Dprintk("overrun: rxorn\n");
+		dev->stats.rx_over_errors ++;
+	}
 
 	if ((ISR_RXRCMP & isr) && dev->rx_info.up)
 		writel(CR_RXE, dev->base + CR);
@@ -1150,9 +1308,10 @@
 
 	memset(dev->tx_descs, 0, 4 * NR_TX_DESC * DESC_SIZE);
 	for (i=0; i<NR_TX_DESC; i++) {
-		*(hw_addr_t *)(dev->tx_descs + (i * DESC_SIZE) + LINK)
-				= dev->tx_phy_descs
-				  + ((i+1) % NR_TX_DESC) * DESC_SIZE * 4;
+		dev->tx_descs[(i * DESC_SIZE) + LINK]
+				= cpu_to_le32(
+				  dev->tx_phy_descs
+				  + ((i+1) % NR_TX_DESC) * DESC_SIZE * 4);
 	}
 
 	dev->tx_idx = 0;
@@ -1190,6 +1349,9 @@
 #if 0	/* I've left this in as an example of how to use eeprom.h */
 		data = eeprom_readw(&dev->ee, 0xa + 2 - i);
 #else
+		/* Read from the perfect match memory: this is loaded by
+		 * the chip from the EEPROM via the EELOAD self test.
+		 */
 		writel(i*2, dev->base + RFCR);
 		data = readl(dev->base + RFDR);
 #endif
@@ -1287,6 +1449,8 @@
 		goto out_unmap;
 	}
 
+	if(register_netdev(&dev->net_dev)) goto out_unmap;
+
 	dev->net_dev.open = ns83820_open;
 	dev->net_dev.stop = ns83820_stop;
 	dev->net_dev.hard_start_xmit = ns83820_hard_start_xmit;
@@ -1294,6 +1458,7 @@
 	dev->net_dev.get_stats = ns83820_get_stats;
 	dev->net_dev.change_mtu = ns83820_change_mtu;
 	dev->net_dev.set_multicast_list = ns83820_set_multicast;
+	dev->net_dev.do_ioctl = ns83820_ioctl;
 	//FIXME: dev->net_dev.tx_timeout = ns83820_tx_timeout;
 
 	pci_set_drvdata(pci_dev, dev);
@@ -1318,12 +1483,15 @@
 	dev->CFG_cache = readl(dev->base + CFG);
 
 	if ((dev->CFG_cache & CFG_PCI64_DET)) {
-		printk("%s: enabling 64 bit PCI.\n", dev->net_dev.name);
+		printk("%s: enabling 64 bit PCI addressing.\n",
+			dev->net_dev.name);
 		dev->CFG_cache |= CFG_T64ADDR | CFG_DATA64_EN;
-	} else {
-		printk("%s: disabling 64 bit PCI.\n", dev->net_dev.name);
+#if defined(USE_64BIT_ADDR)
+		dev->net_dev.features |= NETIF_F_HIGHDMA;
+#endif
+	} else
 		dev->CFG_cache &= ~(CFG_T64ADDR | CFG_DATA64_EN);
-	}
+
 	dev->CFG_cache &= (CFG_TBI_EN  | CFG_MRM_DIS   | CFG_MWI_DIS |
 			   CFG_T64ADDR | CFG_DATA64_EN | CFG_EXT_125 |
 			   CFG_M64ADDR);
@@ -1333,15 +1501,28 @@
 	dev->CFG_cache |= CFG_POW;
 #ifdef USE_64BIT_ADDR
 	dev->CFG_cache |= CFG_M64ADDR;
-	printk("using 64 bit addressing\n");
 #endif
-#ifdef __LITTLE_ENDIAN
+	/* Big endian mode does not seem to do what the docs suggest */
 	dev->CFG_cache &= ~CFG_BEM;
-#elif defined(__BIG_ENDIAN)
-	dev->CFG_cache |= CFG_BEM;
-#else
-#error This driver only works for big or little endian!!!
-#endif
+
+	/* setup optical transceiver if we have one */
+	if (dev->CFG_cache & CFG_TBI_EN) {
+		printk("%s: enabling optical transceiver\n", dev->net_dev.name);
+		writel(readl(dev->base + GPIOR) | 0x3e8, dev->base + GPIOR);
+
+		/* setup auto negotiation feature advertisement */
+		writel(readl(dev->base + TANAR)
+		       | TANAR_HALF_DUP | TANAR_FULL_DUP,
+		       dev->base + TANAR);
+
+		/* start auto negotiation */
+		writel(TBICR_MR_AN_ENABLE | TBICR_MR_RESTART_AN,
+		       dev->base + TBICR);
+		writel(TBICR_MR_AN_ENABLE, dev->base + TBICR);
+		dev->linkstate = LINK_AUTONEGOTIATE;
+
+		dev->CFG_cache |= CFG_MODE_1000;
+	}
 
 	writel(dev->CFG_cache, dev->base + CFG);
 	dprintk("CFG: %08x\n", dev->CFG_cache);
@@ -1397,15 +1578,15 @@
 	dev->net_dev.features |= NETIF_F_HIGHDMA;
 #endif
 
-	register_netdev(&dev->net_dev);
-
-	printk(KERN_INFO "%s: ns83820.c v" VERSION ": DP83820 %02x:%02x:%02x:%02x:%02x:%02x pciaddr=0x%08lx irq=%d rev 0x%x\n",
+	printk(KERN_INFO "%s: ns83820 v" VERSION ": DP83820 v%u.%u: %02x:%02x:%02x:%02x:%02x:%02x io=0x%08lx irq=%d f=%s\n",
 		dev->net_dev.name,
+		(unsigned)readl(dev->base + SRR) >> 8,
+		(unsigned)readl(dev->base + SRR) & 0xff,
 		dev->net_dev.dev_addr[0], dev->net_dev.dev_addr[1],
 		dev->net_dev.dev_addr[2], dev->net_dev.dev_addr[3],
 		dev->net_dev.dev_addr[4], dev->net_dev.dev_addr[5],
 		addr, pci_dev->irq,
-		(unsigned)readl(dev->base + SRR)
+		(dev->net_dev.features & NETIF_F_HIGHDMA) ? "sg" : "h,sg"
 		);
 
 	return 0;
diff -urN linux-2.4.17-pre7/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c
--- linux-2.4.17-pre7/drivers/net/pci-skeleton.c	Mon Dec 10 13:24:26 2001
+++ linux/drivers/net/pci-skeleton.c	Mon Dec 10 13:24:28 2001
@@ -834,7 +834,7 @@
 		printk (KERN_INFO
 			"%s: Media type forced to Full Duplex.\n",
 			dev->name);
-		mdio_write (dev, tp->phys[0], 4, 0x141);
+		mdio_write (dev, tp->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		tp->duplex_lock = 1;
 	}
 
@@ -1235,20 +1235,20 @@
 	struct netdrv_private *tp = dev->priv;
 	void *ioaddr = tp->mmio_addr;
 	int next_tick = 60 * HZ;
-	int mii_reg5;
+	int mii_lpa;
 
-	mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+	mii_lpa = mdio_read (dev, tp->phys[0], MII_LPA);
 
-	if (!tp->duplex_lock && mii_reg5 != 0xffff) {
-		int duplex = (mii_reg5 & 0x0100)
-		    || (mii_reg5 & 0x01C0) == 0x0040;
+	if (!tp->duplex_lock && mii_lpa != 0xffff) {
+		int duplex = (mii_lpa & LPA_100FULL)
+		    || (mii_lpa & 0x01C0) == 0x0040;
 		if (tp->full_duplex != duplex) {
 			tp->full_duplex = duplex;
 			printk (KERN_INFO
 				"%s: Setting %s-duplex based on MII #%d link"
 				" partner ability of %4.4x.\n", dev->name,
 				tp->full_duplex ? "full" : "half",
-				tp->phys[0], mii_reg5);
+				tp->phys[0], mii_lpa);
 			NETDRV_W8 (Cfg9346, Cfg9346_Unlock);
 			NETDRV_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
 			NETDRV_W8 (Cfg9346, Cfg9346_Lock);
diff -urN linux-2.4.17-pre7/drivers/parport/ChangeLog linux/drivers/parport/ChangeLog
--- linux-2.4.17-pre7/drivers/parport/ChangeLog	Mon Dec 10 13:24:26 2001
+++ linux/drivers/parport/ChangeLog	Mon Dec 10 13:24:28 2001
@@ -14,7 +14,7 @@
 	* parport_pc.c (sio_ite_8872_probe): ITE8873 is a single-port
 	serial board, not a serial+parallel.
 
-2001-11-30  Neils Kristian Bech Jensen  <nkbj@image.dk>
+2001-11-30  Niels Kristian Bech Jensen  <nkbj@image.dk>
 
 	* parport_pc.c: Fix compiler warning.
 
diff -urN linux-2.4.17-pre7/drivers/scsi/fdomain.h linux/drivers/scsi/fdomain.h
--- linux-2.4.17-pre7/drivers/scsi/fdomain.h	Mon Dec 10 13:24:26 2001
+++ linux/drivers/scsi/fdomain.h	Mon Dec 10 13:24:28 2001
@@ -34,6 +34,7 @@
 int        fdomain_16x0_biosparam( Disk *, kdev_t, int * );
 int        fdomain_16x0_proc_info( char *buffer, char **start, off_t offset,
 				   int length, int hostno, int inout );
+int        fdomain_16x0_release( struct Scsi_Host *shpnt );
 
 #define FDOMAIN_16X0 { proc_info:      fdomain_16x0_proc_info,           \
 		       detect:         fdomain_16x0_detect,              \
diff -urN linux-2.4.17-pre7/drivers/scsi/pas16.c linux/drivers/scsi/pas16.c
--- linux-2.4.17-pre7/drivers/scsi/pas16.c	Mon Dec 10 13:24:26 2001
+++ linux/drivers/scsi/pas16.c	Mon Dec 10 13:24:28 2001
@@ -1,7 +1,7 @@
 #define AUTOSENSE
 #define PSEUDO_DMA
 #define BOARD_REQUIRES_NO_UDELAY	/* PAS16 needs no I/O recovery delays */
-#define UNSAFE  /* Not unsafe for PAS16 -- use it */
+#define UNSAFE				/* Not unsafe for PAS16 -- use it */
 
 /*
  * This driver adapted from Drew Eckhardt's Trantor T128 driver
@@ -52,8 +52,6 @@
  *
  * PARITY - enable parity checking.  Not supported.
  * 
- * SCSI2 - enable support for SCSI-II tagged queueing.  Untested.
- *
  * UNSAFE - leave interrupts enabled during pseudo-DMA transfers.  This
  *	    parameter comes from the NCR5380 code.  It is NOT unsafe with
  *	    the PAS16 and you should use it.  If you don't you will have
@@ -62,8 +60,6 @@
  *	    want to use UNSAFE you can try defining LIMIT_TRANSFERSIZE or
  *	    twiddle with the transfer size in the high level code.
  *
- * USLEEP - enable support for devices that don't disconnect.  Untested.
- *
  * The card is detected and initialized in one of several ways : 
  * 1.  Autoprobe (default) - There are many different models of
  *     the Pro Audio Spectrum/Studio 16, and I only have one of
@@ -109,7 +105,7 @@
  *
  *   (IRQ_AUTO == 254, IRQ_NONE == 255 in NCR5380.h)
  */
- 
+
 #include <linux/module.h>
 
 #include <asm/system.h>
@@ -133,467 +129,402 @@
 static int pas_wmaxi = 0;
 static unsigned short pas16_addr = 0;
 static int pas16_irq = 0;
- 
 
-int scsi_irq_translate[] =
-	{ 0,  0,  1,  2,  3,  4,  5,  6, 0,  0,  7,  8,  9,  0, 10, 11 };
+static int scsi_irq_translate[] = { 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 7, 8, 9, 0, 10, 11 };
 
 /* The default_irqs array contains values used to set the irq into the
  * board via software (as must be done on newer model boards without
  * irq jumpers on the board).  The first value in the array will be
  * assigned to logical board 0, the next to board 1, etc.
  */
-int default_irqs[] __initdata = 
-	{  PAS16_DEFAULT_BOARD_1_IRQ,
-	   PAS16_DEFAULT_BOARD_2_IRQ,
-	   PAS16_DEFAULT_BOARD_3_IRQ,
-	   PAS16_DEFAULT_BOARD_4_IRQ
-	};
+
+static int default_irqs[] __initdata = {
+	PAS16_DEFAULT_BOARD_1_IRQ,
+	PAS16_DEFAULT_BOARD_2_IRQ,
+	PAS16_DEFAULT_BOARD_3_IRQ,
+	PAS16_DEFAULT_BOARD_4_IRQ
+};
 
 static struct override {
-    unsigned short io_port;
-    int  irq;
-} overrides 
+	unsigned short io_port;
+	int irq;
+} overrides
 #ifdef PAS16_OVERRIDE
-    [] __initdata = PAS16_OVERRIDE;
+[] __initdata = PAS16_OVERRIDE;
 #else
-    [4] __initdata = {{0,IRQ_AUTO}, {0,IRQ_AUTO}, {0,IRQ_AUTO},
-	{0,IRQ_AUTO}};
+[4] __initdata = { 
+	{0, IRQ_AUTO},
+	{0, IRQ_AUTO},
+	{0, IRQ_AUTO},
+	{0, IRQ_AUTO}
+};
 #endif
 
 #define NO_OVERRIDES (sizeof(overrides) / sizeof(struct override))
 
 static struct base {
-    unsigned short io_port;
-    int noauto;
-} bases[] __initdata = 
-	{ {PAS16_DEFAULT_BASE_1, 0},
-	  {PAS16_DEFAULT_BASE_2, 0},
-	  {PAS16_DEFAULT_BASE_3, 0},
-	  {PAS16_DEFAULT_BASE_4, 0}
-	};
+	unsigned short io_port;
+	int noauto;
+} bases[] __initdata = {
+	{PAS16_DEFAULT_BASE_1, 0},
+	{PAS16_DEFAULT_BASE_2, 0},
+	{PAS16_DEFAULT_BASE_3, 0},
+	{PAS16_DEFAULT_BASE_4, 0}
+};
 
 #define NO_BASES (sizeof (bases) / sizeof (struct base))
 
-unsigned short  pas16_offset[ 8 ] =
-    {
-	0x1c00,    /* OUTPUT_DATA_REG */
-	0x1c01,    /* INITIATOR_COMMAND_REG */
-	0x1c02,    /* MODE_REG */
-	0x1c03,    /* TARGET_COMMAND_REG */
-	0x3c00,    /* STATUS_REG ro, SELECT_ENABLE_REG wo */
-	0x3c01,    /* BUS_AND_STATUS_REG ro, START_DMA_SEND_REG wo */
-	0x3c02,    /* INPUT_DATA_REGISTER ro, (N/A on PAS16 ?)
-		    * START_DMA_TARGET_RECEIVE_REG wo
-		    */
-	0x3c03,    /* RESET_PARITY_INTERRUPT_REG ro,
-		    * START_DMA_INITIATOR_RECEIVE_REG wo
-		    */
-    };
+unsigned short pas16_offset[8] = {
+	0x1c00,			/* OUTPUT_DATA_REG */
+	0x1c01,			/* INITIATOR_COMMAND_REG */
+	0x1c02,			/* MODE_REG */
+	0x1c03,			/* TARGET_COMMAND_REG */
+	0x3c00,			/* STATUS_REG ro, SELECT_ENABLE_REG wo */
+	0x3c01,			/* BUS_AND_STATUS_REG ro, START_DMA_SEND_REG wo */
+	0x3c02,			/* INPUT_DATA_REGISTER ro, (N/A on PAS16 ?)
+				 * START_DMA_TARGET_RECEIVE_REG wo
+				 */
+	0x3c03,			/* RESET_PARITY_INTERRUPT_REG ro,
+				 * START_DMA_INITIATOR_RECEIVE_REG wo
+				 */
+};
 /*----------------------------------------------------------------*/
-/* the following will set the monitor border color (useful to find
- where something crashed or gets stuck at */
-/* 1 = blue
- 2 = green
- 3 = cyan
- 4 = red
- 5 = magenta
- 6 = yellow
- 7 = white
-*/
-#if 1
-#define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);}
-#else
-#define rtrc(i) {}
-#endif
-
 
-/*
- * Function : enable_board( int  board_num, unsigned short port )
- *
- * Purpose :  set address in new model board
- *
- * Inputs : board_num - logical board number 0-3, port - base address
+/**
+ * 	enable_board	-	enable a pas16 board
+ *	@board_num: logical board id
+ *	@port: port to assign it
  *
+ *	Sets the address on new model PAS16 hardware
  */
 
-static void __init
-	enable_board( int  board_num,  unsigned short port )
+static void __init enable_board(int board_num, unsigned short port)
 {
-    outb( 0xbc + board_num, MASTER_ADDRESS_PTR );
-    outb( port >> 2, MASTER_ADDRESS_PTR );
+	outb(0xbc + board_num, MASTER_ADDRESS_PTR);
+	outb(port >> 2, MASTER_ADDRESS_PTR);
 }
 
-
-
-/*
- * Function : init_board( unsigned short port, int irq )
- *
- * Purpose :  Set the board up to handle the SCSI interface
- *
- * Inputs : port - base address of the board,
- *	    irq - irq to assign to the SCSI port
- *	    force_irq - set it even if it conflicts with sound driver
+/**
+ *	init_board	-	set up board
+ *	@port: board address
+ *	@irq: interrupt line
+ *	@force_irq: if true allow scsi/audio on the same int
  *
+ *	Set the board up to handle the SCSI interface
  */
 
-static void __init 
-	init_board( unsigned short io_port, int irq, int force_irq )
+static void __init init_board(unsigned short io_port, int irq, int force_irq)
 {
-	unsigned int	tmp;
-	unsigned int	pas_irq_code;
+	unsigned int tmp;
+	unsigned int pas_irq_code;
 
 	/* Initialize the SCSI part of the board */
 
-	outb( 0x30, io_port + P_TIMEOUT_COUNTER_REG );  /* Timeout counter */
-	outb( 0x01, io_port + P_TIMEOUT_STATUS_REG_OFFSET );   /* Reset TC */
-	outb( 0x01, io_port + WAIT_STATE );   /* 1 Wait state */
+	outb(0x30, io_port + P_TIMEOUT_COUNTER_REG);		/* Timeout counter */
+	outb(0x01, io_port + P_TIMEOUT_STATUS_REG_OFFSET);	/* Reset TC */
+	outb(0x01, io_port + WAIT_STATE);			/* 1 Wait state */
 
-	NCR5380_read( RESET_PARITY_INTERRUPT_REG );
+	NCR5380_read(RESET_PARITY_INTERRUPT_REG);
 
-	/* Set the SCSI interrupt pointer without mucking up the sound
-	 * interrupt pointer in the same byte.
+	/*
+	 *	Set the SCSI interrupt pointer without mucking up the sound
+	 *	interrupt pointer in the same byte.
 	 */
-	pas_irq_code = ( irq < 16 ) ? scsi_irq_translate[irq] : 0;
-	tmp = inb( io_port + IO_CONFIG_3 );
-
-	if( (( tmp & 0x0f ) == pas_irq_code) && pas_irq_code > 0 
-	    && !force_irq )
-	{
-	    printk( "pas16: WARNING: Can't use same irq as sound "
-		    "driver -- interrupts disabled\n" );
-	    /* Set up the drive parameters, disable 5380 interrupts */
-	    outb( 0x4d, io_port + SYS_CONFIG_4 );
-	}
-	else
-	{
-	    tmp = (  tmp & 0x0f ) | ( pas_irq_code << 4 );
-	    outb( tmp, io_port + IO_CONFIG_3 );
+	 
+	pas_irq_code = (irq < 16) ? scsi_irq_translate[irq] : 0;
+	tmp = inb(io_port + IO_CONFIG_3);
+
+	if (((tmp & 0x0f) == pas_irq_code) && pas_irq_code > 0 && !force_irq) {
+		printk(KERN_WARNING "pas16: WARNING: Can't use same irq as sound " "driver -- interrupts disabled\n");
+		/* Set up the drive parameters, disable 5380 interrupts */
+		outb(0x4d, io_port + SYS_CONFIG_4);
+	} else {
+		tmp = (tmp & 0x0f) | (pas_irq_code << 4);
+		outb(tmp, io_port + IO_CONFIG_3);
 
-	    /* Set up the drive parameters and enable 5380 interrupts */
-	    outb( 0x6d, io_port + SYS_CONFIG_4 );
+		/* Set up the drive parameters and enable 5380 interrupts */
+		outb(0x6d, io_port + SYS_CONFIG_4);
 	}
 }
 
 
-/*
- * Function : pas16_hw_detect( unsigned short board_num )
- *
- * Purpose : determine if a pas16 board is present
- * 
- * Inputs : board_num - logical board number ( 0 - 3 )
+/**
+ *	pas16_hw_detect		-	probe for hardware
+ *	@board_num: logical board ID to probe for
  *
- * Returns : 0 if board not found, 1 if found.
+ *	Determine if a pas16 board is present
  */
 
-static int __init 
-     pas16_hw_detect( unsigned short  board_num )
+static int __init pas16_hw_detect(unsigned short board_num)
 {
-    unsigned char	board_rev, tmp;
-    unsigned short	io_port = bases[ board_num ].io_port;
+	unsigned char board_rev, tmp;
+	unsigned short io_port = bases[board_num].io_port;
 
-    /* See if we can find a PAS16 board at the address associated
-     * with this logical board number.
-     */
-
-    /* First, attempt to take a newer model board out of reset and
-     * give it a base address.  This shouldn't affect older boards.
-     */
-    enable_board( board_num, io_port );
+	/* See if we can find a PAS16 board at the address associated
+	 * with this logical board number.
+	 */
 
-    /* Now see if it looks like a PAS16 board */
-    board_rev = inb( io_port + PCB_CONFIG );
+	/* First, attempt to take a newer model board out of reset and
+	 * give it a base address.  This shouldn't affect older boards.
+	 */
+	enable_board(board_num, io_port);
 
-    if( board_rev == 0xff )
-	return 0;
+	/* Now see if it looks like a PAS16 board */
+	board_rev = inb(io_port + PCB_CONFIG);
 
-    tmp = board_rev ^ 0xe0;
+	if (board_rev == 0xff)
+		return 0;
 
-    outb( tmp, io_port + PCB_CONFIG );
-    tmp = inb( io_port + PCB_CONFIG );
-    outb( board_rev, io_port + PCB_CONFIG );
+	tmp = board_rev ^ 0xe0;
 
-    if( board_rev != tmp ) 	/* Not a PAS-16 */
-	return 0;
+	outb(tmp, io_port + PCB_CONFIG);
+	tmp = inb(io_port + PCB_CONFIG);
+	outb(board_rev, io_port + PCB_CONFIG);
 
-    if( ( inb( io_port + OPERATION_MODE_1 ) & 0x03 ) != 0x03 ) 
-	return 0;  	/* return if no SCSI interface found */
+	if (board_rev != tmp)	/* Not a PAS-16 */
+		return 0;
 
-    /* Mediavision has some new model boards that return ID bits
-     * that indicate a SCSI interface, but they're not (LMS).  We'll
-     * put in an additional test to try to weed them out.
-     */
-
-    outb( 0x01, io_port + WAIT_STATE ); 	/* 1 Wait state */
-    NCR5380_write( MODE_REG, 0x20 );		/* Is it really SCSI? */
-    if( NCR5380_read( MODE_REG ) != 0x20 )	/* Write to a reg.    */
-	return 0;				/* and try to read    */
-    NCR5380_write( MODE_REG, 0x00 );		/* it back.	      */
-    if( NCR5380_read( MODE_REG ) != 0x00 )
-	return 0;
+	if ((inb(io_port + OPERATION_MODE_1) & 0x03) != 0x03)
+		return 0;	/* return if no SCSI interface found */
 
-    return 1;
-}
+	/* Mediavision has some new model boards that return ID bits
+	 * that indicate a SCSI interface, but they're not (LMS).  We'll
+	 * put in an additional test to try to weed them out.
+	 */
 
+	outb(0x01, io_port + WAIT_STATE);		/* 1 Wait state       */
+	NCR5380_write(MODE_REG, 0x20);			/* Is it really SCSI? */
+	if (NCR5380_read(MODE_REG) != 0x20)		/* Write to a reg.    */
+		return 0;				/* and try to read    */
+	NCR5380_write(MODE_REG, 0x00);			/* it back.           */
+	if (NCR5380_read(MODE_REG) != 0x00)
+		return 0;
 
-/*
- * Function : pas16_setup(char *str, int *ints)
- *
- * Purpose : LILO command line initialization of the overrides array,
- * 
- * Inputs : str - unused, ints - array of integer parameters with ints[0]
- *	equal to the number of ints.
+	return 1;
+}
+
+/**
+ *	pas16_setup	-	parse command line
+ *	@str: command line block
  *
+ *	LILO command line initialization of the overrides array from
+ *	the passed in pas16= options
  */
 
-void __init pas16_setup(char *str, int *ints)
+int __init pas16_setup(char *str, int *ints)
 {
-    static int commandline_current = 0;
-    int i;
-    if (ints[0] != 2) 
-	printk("pas16_setup : usage pas16=io_port,irq\n");
-    else 
-	if (commandline_current < NO_OVERRIDES) {
-	    overrides[commandline_current].io_port = (unsigned short) ints[1];
-	    overrides[commandline_current].irq = ints[2];
-	    for (i = 0; i < NO_BASES; ++i)
-		if (bases[i].io_port == (unsigned short) ints[1]) {
- 		    bases[i].noauto = 1;
-		    break;
-		}
-	    ++commandline_current;
+	static int commandline_current = 0;
+	int i;
+	int ints[10];
+
+	get_options(str, sizeof(ints) / sizeof(int), ints);
+	if (ints[0] != 2)
+		printk(KERN_ERR "pas16_setup : usage pas16=io_port,irq\n");
+	else if (commandline_current < NO_OVERRIDES) {
+		overrides[commandline_current].io_port = (unsigned short) ints[1];
+		overrides[commandline_current].irq = ints[2];
+		for (i = 0; i < NO_BASES; ++i)
+			if (bases[i].io_port == (unsigned short) ints[1]) {
+				bases[i].noauto = 1;
+				break;
+			}
+		++commandline_current;
 	}
+	return 1;
 }
 
-/* 
- * Function : int pas16_detect(Scsi_Host_Template * tpnt)
- *
- * Purpose : detects and initializes PAS16 controllers
- *	that were autoprobed, overridden on the LILO command line, 
- *	or specified at compile time.
- *
- * Inputs : tpnt - template for this SCSI adapter.
- * 
- * Returns : 1 if a host adapter was found, 0 if not.
+__setup("pas16=", pas16_setup);
+
+/**
+ *	pas16_detect	-	detect and configure a pas16
+ *	@tpnt: template
  *
+ *	Detects and initializes PAS16 controllers that were autoprobed, 
+ *	overridden on the LILO command line, or specified at compile time.
  */
 
 int __init pas16_detect(Scsi_Host_Template * tpnt)
 {
-    static int current_override = 0;
-    static unsigned short current_base = 0;
-    struct Scsi_Host *instance;
-    unsigned short io_port;
-    int  count;
+	static int current_override = 0;
+	static unsigned short current_base = 0;
+	struct Scsi_Host *instance;
+	unsigned short io_port;
+	int count;
+
+	tpnt->proc_name = "pas16";
+	tpnt->proc_info = &pas16_proc_info;
+
+	if (pas16_addr != 0) {
+		overrides[0].io_port = pas16_addr;
+		/*
+		 *  This is how we avoid seeing more than
+		 *  one host adapter at the same I/O port.
+		 *  Cribbed shamelessly from pas16_setup().
+		 */
+		for (count = 0; count < NO_BASES; ++count)
+			if (bases[count].io_port == pas16_addr) {
+				bases[count].noauto = 1;
+				break;
+			}
+	}
+	if (pas16_irq != 0)
+		overrides[0].irq = pas16_irq;
 
-    tpnt->proc_name = "pas16";
-    tpnt->proc_info = &pas16_proc_info;
+	for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
+		io_port = 0;
 
-    if (pas16_addr != 0) {
-	overrides[0].io_port = pas16_addr;
-	/*
-	*  This is how we avoid seeing more than
-	*  one host adapter at the same I/O port.
-	*  Cribbed shamelessly from pas16_setup().
-	*/
-	for (count = 0; count < NO_BASES; ++count)
-	    if (bases[count].io_port == pas16_addr) {
- 		    bases[count].noauto = 1;
-		    break;
-	}
-    }
-    if (pas16_irq != 0)
-	overrides[0].irq = pas16_irq;
-
-    for (count = 0; current_override < NO_OVERRIDES; ++current_override) {
-	io_port = 0;
-
-	if (overrides[current_override].io_port)
-	{
-	    io_port = overrides[current_override].io_port;
-	    enable_board( current_override, io_port );
-	    init_board( io_port, overrides[current_override].irq, 1 );
-	}
-	else
-	    for (; !io_port && (current_base < NO_BASES); ++current_base) {
-#if (PDEBUG & PDEBUG_INIT)
-    printk("scsi-pas16 : probing io_port %04x\n", (unsigned int) bases[current_base].io_port);
-#endif
-		if ( !bases[current_base].noauto &&
-		     pas16_hw_detect( current_base ) ){
-			io_port = bases[current_base].io_port;
-			init_board( io_port, default_irqs[ current_base ], 0 ); 
-#if (PDEBUG & PDEBUG_INIT)
-			printk("scsi-pas16 : detected board.\n");
-#endif
+		if (overrides[current_override].io_port) {
+			io_port = overrides[current_override].io_port;
+			enable_board(current_override, io_port);
+			init_board(io_port, overrides[current_override].irq, 1);
+		}
+		else
+		{
+			for (; !io_port && (current_base < NO_BASES); ++current_base) {
+				if (!bases[current_base].noauto && pas16_hw_detect(current_base)) {
+					io_port = bases[current_base].io_port;
+					init_board(io_port, default_irqs[current_base], 0);
+				}
+			}
 		}
-    }
 
+		if (!io_port)
+			break;
 
-#if defined(PDEBUG) && (PDEBUG & PDEBUG_INIT)
-	printk("scsi-pas16 : io_port = %04x\n", (unsigned int) io_port);
-#endif
+		instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata));
+		if (instance == NULL)
+			break;
+
+		instance->io_port = io_port;
+
+		NCR5380_init(instance, 0);
+
+		if (overrides[current_override].irq != IRQ_AUTO)
+			instance->irq = overrides[current_override].irq;
+		else
+			instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
+
+		if (instance->irq != IRQ_NONE)
+			if (request_irq(instance->irq, do_pas16_intr, SA_INTERRUPT, "pas16", NULL)) {
+				printk(KERN_WARNING "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq);
+				instance->irq = IRQ_NONE;
+			}
+
+		if (instance->irq == IRQ_NONE) {
+			printk(KERN_INFO "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
+			printk(KERN_INFO "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
+			/* Disable 5380 interrupts, leave drive params the same */
+			outb(0x4d, io_port + SYS_CONFIG_4);
+			outb((inb(io_port + IO_CONFIG_3) & 0x0f), io_port + IO_CONFIG_3);
+		}
 
-	if (!io_port)
-	    break;
+		printk(KERN_INFO "scsi%d : at 0x%04x", instance->host_no, (int)
+		       instance->io_port);
+		if (instance->irq == IRQ_NONE)
+			printk(" interrupts disabled");
+		else
+			printk(" irq %d", instance->irq);
+		printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d", CAN_QUEUE, CMD_PER_LUN, PAS16_PUBLIC_RELEASE);
+		NCR5380_print_options(instance);
+		printk("\n");
 
-	instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata));
-	if(instance == NULL)
-		break;
-		
-	instance->io_port = io_port;
-
-	NCR5380_init(instance, 0);
-
-	if (overrides[current_override].irq != IRQ_AUTO)
-	    instance->irq = overrides[current_override].irq;
-	else 
-	    instance->irq = NCR5380_probe_irq(instance, PAS16_IRQS);
-
-	if (instance->irq != IRQ_NONE) 
-	    if (request_irq(instance->irq, do_pas16_intr, SA_INTERRUPT, "pas16", NULL)) {
-		printk("scsi%d : IRQ%d not free, interrupts disabled\n", 
-		    instance->host_no, instance->irq);
-		instance->irq = IRQ_NONE;
-	    } 
-
-	if (instance->irq == IRQ_NONE) {
-	    printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no);
-	    printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no);
-	    /* Disable 5380 interrupts, leave drive params the same */
-	    outb( 0x4d, io_port + SYS_CONFIG_4 );
-	    outb( (inb(io_port + IO_CONFIG_3) & 0x0f), io_port + IO_CONFIG_3 );
+		++current_override;
+		++count;
 	}
-
-#if defined(PDEBUG) && (PDEBUG & PDEBUG_INIT)
-	printk("scsi%d : irq = %d\n", instance->host_no, instance->irq);
-#endif
-
-	printk("scsi%d : at 0x%04x", instance->host_no, (int) 
-	    instance->io_port);
-	if (instance->irq == IRQ_NONE)
-	    printk (" interrupts disabled");
-	else 
-	    printk (" irq %d", instance->irq);
-	printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
-	    CAN_QUEUE, CMD_PER_LUN, PAS16_PUBLIC_RELEASE);
-	NCR5380_print_options(instance);
-	printk("\n");
-
-	++current_override;
-	++count;
-    }
-    return count;
+	return count;
 }
 
-/*
- * Function : int pas16_biosparam(Disk *disk, kdev_t dev, int *ip)
+/**
+ *	pas16_biosparam		-	generate C/H/S data
+ *	@disk: Disk to set up
+ *	@dev: device ident of disk
+ *	@ip: array to return C/H/S mapping
  *
- * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 
+ *	Generates a BIOS / DOS compatible H-C-S mapping for 
  *	the specified device / size.
- * 
- * Inputs : size = size of device in sectors (512 bytes), dev = block device
- *	major / minor, ip[] = {heads, sectors, cylinders}  
- *
- * Returns : always 0 (success), initializes ip
- *	
  */
 
-/* 
- * XXX Most SCSI boards use this mapping, I could be incorrect.  Some one
- * using hard disks on a trantor should verify that this mapping corresponds
- * to that used by the BIOS / ASPI driver by running the linux fdisk program
- * and matching the H_C_S coordinates to what DOS uses.
- */
-
-int pas16_biosparam(Disk * disk, kdev_t dev, int * ip)
+int pas16_biosparam(Disk * disk, kdev_t dev, int *ip)
 {
-  int size = disk->capacity;
-  ip[0] = 64;
-  ip[1] = 32;
-  ip[2] = size >> 11;		/* I think I have it as /(32*64) */
-  if( ip[2] > 1024 ) {		/* yes, >, not >= */
-	ip[0]=255;
-	ip[1]=63;
-	ip[2]=size/(63*255);
-	if( ip[2] > 1023 )	/* yes >1023... */
-		ip[2] = 1023;
-  }
+	int size = disk->capacity;
+	ip[0] = 64;
+	ip[1] = 32;
+	ip[2] = size >> 11;	/* I think I have it as /(32*64) */
+	if (ip[2] > 1024) {	/* yes, >, not >= */
+		ip[0] = 255;
+		ip[1] = 63;
+		ip[2] = size / (63 * 255);
+		if (ip[2] > 1023)	/* yes >1023... */
+			ip[2] = 1023;
+	}
 
-  return 0;
+	return 0;
 }
 
-/*
- * Function : int NCR5380_pread (struct Scsi_Host *instance, 
- *	unsigned char *dst, int len)
- *
- * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to 
- *	dst
- * 
- * Inputs : dst = destination, len = length in bytes
- *
- * Returns : 0 on success, non zero on a failure such as a watchdog 
- * 	timeout.
+/**
+ *	NCR5380_pread 		-	pseudo DMA read
+ *	@instance: board to read from
+ *	@dst: destination for data
+ *	@len: expected/max block length
+ *
+ *	Fast 5380 pseudo-dma read function, transfers len bytes to 
+ *	dst. Unlike most boards the PAS has IRQs enabled here, which
+ *	helps no end.
  */
 
-static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
-    int len) {
-    register unsigned char  *d = dst;
-    register unsigned short reg = (unsigned short) (instance->io_port + 
-	P_DATA_REG_OFFSET);
-    register int i = len;
-    int ii = 0;
-
-    while ( !(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY) )
-	 ++ii;
-
-    insb( reg, d, i );
-
-    if ( inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) {
-	outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET);
-	printk("scsi%d : watchdog timer fired in NCR5380_pread()\n",
-	    instance->host_no);
-	return -1;
-    }
-   if (ii > pas_maxi)
-      pas_maxi = ii;
-    return 0;
+static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len)
+{
+	unsigned char *d = dst;
+	unsigned short reg = (unsigned short) (instance->io_port + P_DATA_REG_OFFSET);
+	int i = len;
+	int ii = 0;
+
+	while (!(inb(instance->io_port + P_STATUS_REG_OFFSET) & P_ST_RDY))
+		++ii;
+
+	insb(reg, d, i);
+
+	if (inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) {
+		outb(P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET);
+		printk(KERN_ERR "scsi%d : watchdog timer fired in NCR5380_pread()\n", instance->host_no);
+		return -1;
+	}
+	if (ii > pas_maxi)
+		pas_maxi = ii;
+	return 0;
 }
 
-/*
- * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 
- *	unsigned char *src, int len)
- *
- * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from
- *	src
- * 
- * Inputs : src = source, len = length in bytes
- *
- * Returns : 0 on success, non zero on a failure such as a watchdog 
- * 	timeout.
+/**
+ *	NCR5380_pwrite 		-	pseudo DMA write
+ *	@instance: board to write to
+ *	@src: source for data
+ *	@len: expected/max block length
+ *
+ *	Fast 5380 pseudo-dma write function, transfers len bytes from
+ *	src. Unlike most boards the PAS has IRQs enabled here, which
+ *	helps no end.
  */
 
-static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src,
-    int len) {
-    register unsigned char *s = src;
-    register unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET);
-    register int i = len;
-    int ii = 0;
-
-    while ( !((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY) )
-	 ++ii;
- 
-    outsb( reg, s, i );
-
-    if (inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) {
-	outb( P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET);
-	printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n",
-	    instance->host_no);
-	return -1;
-    }
-    if (ii > pas_maxi)
-	 pas_wmaxi = ii;
-    return 0;
+static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len)
+{
+	unsigned char *s = src;
+	unsigned short reg = (instance->io_port + P_DATA_REG_OFFSET);
+	int i = len;
+	int ii = 0;
+
+	while (!((inb(instance->io_port + P_STATUS_REG_OFFSET)) & P_ST_RDY))
+		++ii;
+
+	outsb(reg, s, i);
+
+	if (inb(instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET) & P_TS_TIM) {
+		outb(P_TS_CT, instance->io_port + P_TIMEOUT_STATUS_REG_OFFSET);
+		printk(KERN_ERR "scsi%d : watchdog timer fired in NCR5380_pwrite()\n", instance->host_no);
+		return -1;
+	}
+	if (ii > pas_maxi)
+		pas_wmaxi = ii;
+	return 0;
 }
 
 #include "NCR5380.c"
diff -urN linux-2.4.17-pre7/drivers/scsi/sg.c linux/drivers/scsi/sg.c
--- linux-2.4.17-pre7/drivers/scsi/sg.c	Mon Dec 10 13:24:26 2001
+++ linux/drivers/scsi/sg.c	Mon Dec 10 13:24:28 2001
@@ -19,7 +19,7 @@
  */
 #include <linux/config.h>
 #ifdef CONFIG_PROC_FS
- static char sg_version_str[] = "Version: 3.1.22 (20011128)";
+ static char sg_version_str[] = "Version: 3.1.22 (20011208)";
 #endif
  static int sg_version_num = 30122; /* 2 digits for each component */
 /*
@@ -1284,14 +1284,15 @@
 	if (NULL == sfp->headrp) {
             SCSI_LOG_TIMEOUT(1,
 		printk("sg...bh: already closed, final cleanup\n"));
-            sg_remove_sfp(sdp, sfp);
+            if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */
+		sdp->device->access_count--;
+		if (sdp->device->host->hostt->module)
+		    __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
+	    }
+	    if (sg_template.module)
+		    __MOD_DEC_USE_COUNT(sg_template.module);
 	    sfp = NULL;
         }
-	sdp->device->access_count--;
-	if (sg_template.module)
-		__MOD_DEC_USE_COUNT(sg_template.module);
-	if (sdp->device->host->hostt->module)
-	    __MOD_DEC_USE_COUNT(sdp->device->host->hostt->module);
     }
     else if (srp && srp->orphan) {
 	if (sfp->keep_orphan)
diff -urN linux-2.4.17-pre7/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- linux-2.4.17-pre7/drivers/sound/via82cxxx_audio.c	Fri Nov  9 13:45:35 2001
+++ linux/drivers/sound/via82cxxx_audio.c	Mon Dec 10 13:24:28 2001
@@ -1,6 +1,6 @@
 /*
  * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+ * Copyright 1999,2000 Jeff Garzik
  *
  * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
  * See the "COPYING" file distributed with this software for more info.
@@ -8,9 +8,6 @@
  * For a list of known bugs (errata) and documentation,
  * see via-audio.pdf in linux/Documentation/DocBook.
  * If this documentation does not exist, run "make pdfdocs".
- * If "make pdfdocs" fails, obtain the documentation from
- * the driver's Website at
- * http://gtf.org/garzik/drivers/via82cxxx/
  *
  */
 
@@ -3357,7 +3354,7 @@
 module_init(init_via82cxxx_audio);
 module_exit(cleanup_via82cxxx_audio);
 
-MODULE_AUTHOR("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("DSP audio and mixer driver for Via 82Cxxx audio devices");
 MODULE_LICENSE("GPL");
 
diff -urN linux-2.4.17-pre7/fs/buffer.c linux/fs/buffer.c
--- linux-2.4.17-pre7/fs/buffer.c	Mon Dec 10 13:24:26 2001
+++ linux/fs/buffer.c	Mon Dec 10 13:24:28 2001
@@ -2003,12 +2003,12 @@
 {
 	int i, nr_blocks, retval;
 	unsigned long * blocks = iobuf->blocks;
+	struct buffer_head bh;
 
+	bh.b_dev = inode->i_dev;
 	nr_blocks = iobuf->length / blocksize;
 	/* build the blocklist */
 	for (i = 0; i < nr_blocks; i++, blocknr++) {
-		struct buffer_head bh;
-
 		bh.b_state = 0;
 		bh.b_dev = inode->i_dev;
 		bh.b_size = blocksize;
@@ -2034,7 +2034,7 @@
 		blocks[i] = bh.b_blocknr;
 	}
 
-	retval = brw_kiovec(rw, 1, &iobuf, inode->i_dev, iobuf->blocks, blocksize);
+	retval = brw_kiovec(rw, 1, &iobuf, bh.b_dev, iobuf->blocks, blocksize);
 
  out:
 	return retval;
diff -urN linux-2.4.17-pre7/fs/ext3/inode.c linux/fs/ext3/inode.c
--- linux-2.4.17-pre7/fs/ext3/inode.c	Mon Dec 10 13:24:26 2001
+++ linux/fs/ext3/inode.c	Mon Dec 10 13:24:29 2001
@@ -2361,11 +2361,19 @@
 {
 	struct inode *inode = dentry->d_inode;
 	int error, rc = 0;
+	const unsigned int ia_valid = attr->ia_valid;
 
 	error = inode_change_ok(inode, attr);
 	if (error)
 		return error;
-	
+
+	if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
+		(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
+		error = DQUOT_TRANSFER(inode, attr) ? -EDQUOT : 0;
+		if (error)
+			return error;
+	}
+
 	if (attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
 		handle_t *handle;
 
diff -urN linux-2.4.17-pre7/include/asm-ia64/system.h linux/include/asm-ia64/system.h
--- linux-2.4.17-pre7/include/asm-ia64/system.h	Fri Nov  9 14:26:17 2001
+++ linux/include/asm-ia64/system.h	Mon Dec 10 13:24:29 2001
@@ -405,6 +405,10 @@
 	ia64_psr(ia64_task_regs(prev))->dfh = 1;				\
 	__switch_to(prev,next,last);						\
   } while (0)
+
+/* Return true if this CPU can call the console drivers in printk() */
+#define arch_consoles_callable() (cpu_online_map & (1UL << smp_processor_id()))
+
 #else
 # define switch_to(prev,next,last) do {						\
 	ia64_psr(ia64_task_regs(next))->dfh = (ia64_get_fpu_owner() != (next));	\
diff -urN linux-2.4.17-pre7/include/linux/eeprom.h linux/include/linux/eeprom.h
--- linux-2.4.17-pre7/include/linux/eeprom.h	Thu Sep 20 14:20:14 2001
+++ linux/include/linux/eeprom.h	Mon Dec 10 13:24:29 2001
@@ -1,6 +1,7 @@
 /* credit winbond-840.c
  */
 #include <asm/io.h>
+
 struct eeprom_ops {
 	void	(*set_cs)(void *ee);
 	void	(*clear_cs)(void *ee);
diff -urN linux-2.4.17-pre7/include/pcmcia/version.h linux/include/pcmcia/version.h
--- linux-2.4.17-pre7/include/pcmcia/version.h	Mon Dec 10 13:24:26 2001
+++ linux/include/pcmcia/version.h	Thu Oct 26 16:52:16 2000
@@ -1,4 +1,4 @@
-/* version.h 1.102 2001/08/29 23:13:22 (David Hinds) */
+/* version.h 1.94 2000/10/03 17:55:48 (David Hinds) */
 
-#define CS_RELEASE "3.1.30"
-#define CS_RELEASE_CODE 0x311e
+#define CS_RELEASE "3.1.22"
+#define CS_RELEASE_CODE 0x3116
diff -urN linux-2.4.17-pre7/include/scsi/sg.h linux/include/scsi/sg.h
--- linux-2.4.17-pre7/include/scsi/sg.h	Mon Dec 10 13:24:26 2001
+++ linux/include/scsi/sg.h	Mon Dec 10 13:24:29 2001
@@ -11,13 +11,14 @@
 Version 2 and 3 extensions to driver:
 *       Copyright (C) 1998 - 2001 Douglas Gilbert
 
-    Version: 3.1.22 (20011128)
+    Version: 3.1.22 (20011208)
     This version is for 2.4 series kernels.
 
     Changes since 3.1.21 (20011029)
     	- add support for SG_FLAG_MMAP_IO [permit mmap() on sg devices]
     	- update documentation pointers in this header
     	- put KERNEL_VERSION macros around code that breaks early 2.4 series
+    	- fix use count for multiple queued requests on closed fd
     	- switch back to alloc_kiovec()
     Changes since 3.1.20 (20010814)
 	- use alloc_kiovec_sz() to speed dio [set num_buffer_heads==0]
diff -urN linux-2.4.17-pre7/kernel/printk.c linux/kernel/printk.c
--- linux-2.4.17-pre7/kernel/printk.c	Sun Nov 11 10:20:21 2001
+++ linux/kernel/printk.c	Mon Dec 10 13:24:29 2001
@@ -38,6 +38,10 @@
 
 #define LOG_BUF_MASK	(LOG_BUF_LEN-1)
 
+#ifndef arch_consoles_callable
+#define arch_consoles_callable() (1)
+#endif
+
 /* printk's without a loglevel use this.. */
 #define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
 
@@ -438,6 +442,14 @@
 			log_level_unknown = 1;
 	}
 
+	if (!arch_consoles_callable()) {
+		/*
+		 * On some architectures, the consoles are not usable
+		 * on secondary CPUs early in the boot process.
+		 */
+		spin_unlock_irqrestore(&logbuf_lock, flags);
+		goto out;
+	}
 	if (!down_trylock(&console_sem)) {
 		/*
 		 * We own the drivers.  We can drop the spinlock and let
@@ -454,6 +466,7 @@
 		 */
 		spin_unlock_irqrestore(&logbuf_lock, flags);
 	}
+out:
 	return printed_len;
 }
 EXPORT_SYMBOL(printk);
diff -urN linux-2.4.17-pre7/kernel/sysctl.c linux/kernel/sysctl.c
--- linux-2.4.17-pre7/kernel/sysctl.c	Mon Nov 26 05:29:17 2001
+++ linux/kernel/sysctl.c	Mon Dec 10 13:24:29 2001
@@ -45,7 +45,8 @@
 extern int bdf_prm[], bdflush_min[], bdflush_max[];
 extern int sysctl_overcommit_memory;
 extern int max_threads;
-extern int nr_queued_signals, max_queued_signals;
+extern atomic_t nr_queued_signals;
+extern int max_queued_signals;
 extern int sysrq_enabled;
 extern int core_uses_pid;
 extern int cad_pid;
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ip_conntrack_irc.c linux/net/ipv4/netfilter/ip_conntrack_irc.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ip_conntrack_irc.c	Tue Oct 30 15:08:12 2001
+++ linux/net/ipv4/netfilter/ip_conntrack_irc.c	Mon Dec 10 13:24:29 2001
@@ -1,8 +1,8 @@
-/* IRC extension for IP connection tracking, Version 1.19
- * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+/* IRC extension for IP connection tracking, Version 1.20
+ * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
  * based on RR's ip_conntrack_ftp.c	
  *
- * ip_conntrack_irc.c,v 1.19 2001/10/25 14:34:21 laforge Exp
+ * ip_conntrack_irc.c,v 1.20 2001/12/06 07:42:10 laforge Exp
  *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -10,7 +10,7 @@
  *      2 of the License, or (at your option) any later version.
  **
  *	Module load syntax:
- * 	insmod ip_nat_irc.o ports=port1,port2,...port<MAX_PORTS>
+ * 	insmod ip_conntrack_irc.o ports=port1,port2,...port<MAX_PORTS>
  *	
  * 	please give the ports of all IRC servers You wish to connect to.
  *	If You don't specify ports, the default will be port 6667
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ip_fw_compat.c linux/net/ipv4/netfilter/ip_fw_compat.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ip_fw_compat.c	Sat Nov 10 15:36:38 2001
+++ linux/net/ipv4/netfilter/ip_fw_compat.c	Mon Dec 10 13:24:29 2001
@@ -84,6 +84,16 @@
 	if ((*pskb)->ip_summed == CHECKSUM_HW)
 		(*pskb)->ip_summed = CHECKSUM_NONE;
 
+	/* Firewall rules can alter TOS: raw socket (tcpdump) may have
+           clone of incoming skb: don't disturb it --RR */
+	if (skb_cloned(*pskb) && !(*pskb)->sk) {
+		struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+		if (!nskb)
+			return NF_DROP;
+		kfree_skb(*pskb);
+		*pskb = nskb;
+	}
+
 	switch (hooknum) {
 	case NF_IP_PRE_ROUTING:
 		if (fwops->fw_acct_in)
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ip_nat_core.c linux/net/ipv4/netfilter/ip_nat_core.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ip_nat_core.c	Sat Nov 10 15:36:38 2001
+++ linux/net/ipv4/netfilter/ip_nat_core.c	Mon Dec 10 13:24:29 2001
@@ -734,6 +734,18 @@
 	   synchronize_bh()) can vanish. */
 	READ_LOCK(&ip_nat_lock);
 	for (i = 0; i < info->num_manips; i++) {
+		/* raw socket (tcpdump) may have clone of incoming
+                   skb: don't disturb it --RR */
+		if (skb_cloned(*pskb) && !(*pskb)->sk) {
+			struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+			if (!nskb) {
+				READ_UNLOCK(&ip_nat_lock);
+				return NF_DROP;
+			}
+			kfree_skb(*pskb);
+			*pskb = nskb;
+		}
+
 		if (info->manips[i].direction == dir
 		    && info->manips[i].hooknum == hooknum) {
 			DEBUGP("Mangling %p: %s to %u.%u.%u.%u %u\n",
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ip_nat_helper.c linux/net/ipv4/netfilter/ip_nat_helper.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ip_nat_helper.c	Tue Aug 28 07:09:44 2001
+++ linux/net/ipv4/netfilter/ip_nat_helper.c	Mon Dec 10 13:24:29 2001
@@ -143,6 +143,23 @@
 		}
 	}
 
+	/* Alexey says: if a hook changes _data_ ... it can break
+	   original packet sitting in tcp queue and this is fatal */
+	if (skb_cloned(*skb)) {
+		struct sk_buff *nskb = skb_copy(*skb, GFP_ATOMIC);
+		if (!nskb) {
+			if (net_ratelimit())
+				printk("Out of memory cloning TCP packet\n");
+			return 0;
+		}
+		/* Rest of kernel will get very unhappy if we pass it
+		   a suddenly-orphaned skbuff */
+		if ((*skb)->sk)
+			skb_set_owner_w(nskb, (*skb)->sk);
+		kfree_skb(*skb);
+		*skb = nskb;
+	}
+
 	/* skb may be copied !! */
 	iph = (*skb)->nh.iph;
 	tcph = (void *)iph + iph->ihl*4;
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ip_nat_irc.c linux/net/ipv4/netfilter/ip_nat_irc.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ip_nat_irc.c	Tue Oct 30 15:08:12 2001
+++ linux/net/ipv4/netfilter/ip_nat_irc.c	Mon Dec 10 13:24:29 2001
@@ -1,8 +1,8 @@
 /* IRC extension for TCP NAT alteration.
- * (C) 2000 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2000-2001 by Harald Welte <laforge@gnumonks.org>
  * based on a copy of RR's ip_nat_ftp.c
  *
- * ip_nat_irc.c,v 1.15 2001/10/22 10:43:53 laforge Exp
+ * ip_nat_irc.c,v 1.16 2001/12/06 07:42:10 laforge Exp
  *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
@@ -81,7 +81,7 @@
 	}
 
 	newdstip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
-	newsrcip = master->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.ip;
+	newsrcip = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.ip;
 	DEBUGP("nat_expected: DCC cmd. %u.%u.%u.%u->%u.%u.%u.%u\n",
 	       NIPQUAD(newsrcip), NIPQUAD(newdstip));
 
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ipt_MIRROR.c linux/net/ipv4/netfilter/ipt_MIRROR.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ipt_MIRROR.c	Sun Sep 30 12:26:08 2001
+++ linux/net/ipv4/netfilter/ipt_MIRROR.c	Mon Dec 10 13:24:29 2001
@@ -6,6 +6,10 @@
 
   Copyright (C) 2000 Emmanuel Roger <winfield@freegates.be>
 
+  Changes:
+	25 Aug 2001 Harald Welte <laforge@gnumonks.org>
+		- decrement and check TTL if not called from FORWARD hook
+
   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
@@ -24,6 +28,7 @@
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <net/ip.h>
+#include <net/icmp.h>
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netdevice.h>
 #include <linux/route.h>
@@ -100,15 +105,31 @@
 				      const void *targinfo,
 				      void *userinfo)
 {
-	if ((*pskb)->dst != NULL) {
-		if (route_mirror(*pskb)) {
-			ip_rewrite(*pskb);
-			/* Don't let conntrack code see this packet:
-                           it will think we are starting a new
-                           connection! --RR */
-			ip_direct_send(*pskb);
-			return NF_STOLEN;
+	if (((*pskb)->dst != NULL) &&
+	    route_mirror(*pskb)) {
+
+		ip_rewrite(*pskb);
+
+		/* If we are not at FORWARD hook (INPUT/PREROUTING),
+		 * the TTL isn't decreased by the IP stack */
+		if (hooknum != NF_IP_FORWARD) {
+			struct iphdr *iph = (*pskb)->nh.iph;
+			if (iph->ttl <= 1) {
+				/* this will traverse normal stack, and 
+				 * thus call conntrack on the icmp packet */
+				icmp_send(*pskb, ICMP_TIME_EXCEEDED, 
+					  ICMP_EXC_TTL, 0);
+				return NF_DROP;
+			}
+			ip_decrease_ttl(iph);
 		}
+
+		/* Don't let conntrack code see this packet:
+                   it will think we are starting a new
+                   connection! --RR */
+		ip_direct_send(*pskb);
+
+		return NF_STOLEN;
 	}
 	return NF_DROP;
 }
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ipt_TCPMSS.c linux/net/ipv4/netfilter/ipt_TCPMSS.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ipt_TCPMSS.c	Sat Nov 10 15:36:38 2001
+++ linux/net/ipv4/netfilter/ipt_TCPMSS.c	Mon Dec 10 13:24:29 2001
@@ -44,11 +44,22 @@
 {
 	const struct ipt_tcpmss_info *tcpmssinfo = targinfo;
 	struct tcphdr *tcph;
-	struct iphdr *iph = (*pskb)->nh.iph;
+	struct iphdr *iph;
 	u_int16_t tcplen, newtotlen, oldval, newmss;
 	unsigned int i;
 	u_int8_t *opt;
 
+	/* raw socket (tcpdump) may have clone of incoming skb: don't
+	   disturb it --RR */
+	if (skb_cloned(*pskb) && !(*pskb)->sk) {
+		struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+		if (!nskb)
+			return NF_DROP;
+		kfree_skb(*pskb);
+		*pskb = nskb;
+	}
+
+	iph = (*pskb)->nh.iph;
 	tcplen = (*pskb)->len - iph->ihl*4;
 
 	tcph = (void *)iph + iph->ihl*4;
diff -urN linux-2.4.17-pre7/net/ipv4/netfilter/ipt_TOS.c linux/net/ipv4/netfilter/ipt_TOS.c
--- linux-2.4.17-pre7/net/ipv4/netfilter/ipt_TOS.c	Sat Nov 10 15:36:38 2001
+++ linux/net/ipv4/netfilter/ipt_TOS.c	Mon Dec 10 13:24:29 2001
@@ -21,6 +21,17 @@
 	if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
 		u_int16_t diffs[2];
 
+		/* raw socket (tcpdump) may have clone of incoming
+                   skb: don't disturb it --RR */
+		if (skb_cloned(*pskb) && !(*pskb)->sk) {
+			struct sk_buff *nskb = skb_copy(*pskb, GFP_ATOMIC);
+			if (!nskb)
+				return NF_DROP;
+			*pskb = nskb;
+			kfree_skb(*pskb);
+			iph = (*pskb)->nh.iph;
+		}
+
 		diffs[0] = htons(iph->tos) ^ 0xFFFF;
 		iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
 		diffs[1] = htons(iph->tos);
