diff -u --recursive --new-file v2.0.11/linux/CREDITS linux/CREDITS
--- v2.0.11/linux/CREDITS	Thu Jul 25 09:08:27 1996
+++ linux/CREDITS	Fri Aug  9 10:44:54 1996
@@ -129,6 +129,15 @@
 E: bir7@leland.Stanford.Edu
 D: Original author of the Linux networking code
 
+N: Philip Blundell
+E: pjb27@cam.ac.uk 
+E: pb@nexus.co.uk
+E: phil@tazenda.demon.co.uk
+D: Device driver hacking (especially EtherExpress16/3C505 net cards)
+D: Some Linux/ARM stuff
+S: Trinity College
+S: Cambridge, UK. CB2 1TQ
+
 N: Thomas Bogendoerfer
 E: tsbogend@bigbug.franken.de
 D: Lance32 driver
@@ -545,6 +554,13 @@
 S: 34266 Niestetal
 S: Germany
 
+N: Richard Henderson
+E: rth@tamu.edu
+D: Alpha/ELF, gcc, binutils, and glibc
+S: 304 E. North Ave.
+S: Bryan, TX  77801-3431
+S: USA
+
 N: Sebastian Hetze
 E: she@lunetix.de
 D: German Linux Documentation,
@@ -566,6 +582,14 @@
 S: AIB Software Corporation
 S: 46030 Manekin Plaza, Suite 160
 S: Dulles, Virginia 20166
+S: USA
+
+N: Kenji Tsutomu Hollis
+E: khollis@bitgate.com
+W: http://www.nurk.org/
+D: Berkshire PC Watchdog Driver
+S: PO Box 15
+S: Grants Pass, OR 97526
 S: USA
 
 N: Nick Holloway
diff -u --recursive --new-file v2.0.11/linux/Documentation/Changes linux/Documentation/Changes
--- v2.0.11/linux/Documentation/Changes	Mon Aug  5 10:13:49 1996
+++ linux/Documentation/Changes	Fri Aug  9 12:08:05 1996
@@ -26,11 +26,11 @@
 valtozasokrol, az alabbi cimen megtalaljak Nyitrai Tamas forditasat:
 http://www.datanet.hu/generations/linux/newkernel.html.
 
-   For people who prefer Japanse (thanks to Mitsuhiro Kojima): Kono
-bunshou no nihongo ban ha
+   For people who prefer Japanese (thanks to Mitsuhiro Kojima): Kono
+bunshou no nihongo ban wa
 http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
 
-Last updated: July 29, 1996.
+Last updated: August 6, 1996.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -135,6 +135,18 @@
 to fix this problem.  Libc is available from
 ftp://sunsite.unc.edu/pub/Linux/GCC/.
 
+GCC Signal 11 error
+===================
+
+   Many people have been reporting messages like the following,
+especially when compiling a new kernel:
+
+   `gcc:  Internal compiler error:  program cc1 got fatal signal 11'.
+
+   This is NOT a kernel bug.  Rather, these messages are generally
+caused by hardware problems.  See http://www.bitwizard.nl/sig11/ for
+the sig11 FAQ.
+
 Procps utilities
 ================
 
@@ -259,7 +271,11 @@
 ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.tar.gz.  If you
 upgrade to this release read the `README' file contained into the
 package to get some important information about the `tgetent' function
-changes!
+changes!  Note that there is now a fixed version at
+ftp://sunsite.unc.edu/pub/Linux/GCC/termcap-2.0.8.fix.  If some of your
+apps complain that termcap entries are too long and you don't need some
+of the more esoteric terms in the standard 2.0.8 termcap, just download
+termcap-2.0.8.fix and move it to /etc/termcap.
 
    Also, the console driver is now responsible for keeping track of
 correspondence between character codes and glyph bitmaps.  If you
@@ -271,7 +287,7 @@
 
    Hdparm has been upgraded to take advantage of the latest features of
 the kernel drivers.  The latest non-beta version can be found at
-ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.0.tar.gz.
+ftp://sunsite.unc.edu/pub/Linux/kernel/patches/diskdrives/hdparm-3.1.tar.gz.
 
 IP Accounting
 =============
@@ -285,7 +301,7 @@
    There also exists a possibility to match on device names and/or
 device addresses, so that only packets coming in/going out via that
 device (network interface) match with a rule.  You'll need to get
-ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to
+ipfwadm from ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to
 use this.
 
 IP Firewalls
@@ -298,7 +314,7 @@
 so that only packets coming in/going out via that device (network
 interface) match with a rule.  This is especially useful to prevent
 spoofing.  You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to use this.
+ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
 
 IP Masquerading
 ===============
@@ -307,7 +323,7 @@
 always need to load separate modules (ip_masq_ftp.o and/or
 ip_masq_irc.o) if you are going to use FTP or IRC in combination with
 masquerading.  You'll need to get
-ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.2.tar.gz to use this.
+ftp://ftp.xos.nl/pub/linux/ipfwadm/ipfwadm-2.3.0.tar.gz to use this.
 
 ISDN support
 ============
@@ -473,9 +489,9 @@
 ======================
 
    The Cyclades driver has been changed so that the minor numbers start
-at 0 instead of 32 (ie: ttyC0 should be major 19, minor 0 in the 2.0.x
-kernels while it used to be major 19, minor 32 in the older kernels).
-You can use mknod to manually fix this or use a newer version of MAKEDEV.
+at 0 instead of 32 (for example, ttyC0 should be major 19, minor 0 for
+2.0.x kernels; in older kernels, it would have been major 19, minor
+32).  Use mknod or a sufficiently new version of MAKEDEV to fix this.
 
 NCR 53c810 SCSI Driver
 ======================
@@ -492,8 +508,9 @@
 
    While we're on the subject, changes made for the 2.0.x series cause
 the connect() Perl (both 4 and 5) call to time out while connecting to
-remote systems.  If you need the connect call for your program, use C
-instead of Perl.
+remote systems.  The problem is not actually in the connect() call;
+rather, the optional bind() call usually used with connect() causes the
+problem.  Remove the bind() call and your Perl scripts should connect.
 
    Also, Perl scripts using the readdir call now misbehave if you're
 using an old version of Perl, due to changes in libc.  Upgrade to a
@@ -508,7 +525,10 @@
 (many have reported success with "latin1", for example) for the
 environmental variable LESSCHARSET.  Another, and probably better,
 solution is to edit the file /usr/lib/man.config and change all
-`-Tlatin1' options to `-Tascii'.
+`-Tlatin1' options to `-Tascii'.  An alternate solution, for those of
+you who can't reformat your man files in .../cat* directories is to
+edit /usr/lib/man.config, setting the PAGER to `PAGER
+(LESSCHARSET=latin1;export LESSCHARSET;/usr/bin/less -is'.
 
 E2fsprogs
 =========
diff -u --recursive --new-file v2.0.11/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.0.11/linux/Documentation/Configure.help	Mon Aug  5 10:13:49 1996
+++ linux/Documentation/Configure.help	Wed Aug  7 09:45:41 1996
@@ -3483,7 +3483,7 @@
   it resets your computer after a certain amount of time.  This driver is
   like the WDT501 driver but for different hardware. The PC watchdog cards
   can be ordered from http://www.berkprod.com. Some example rc.local files
-  are available from ftp.bitgame.com.
+  are available from ftp.bitgate.com.
 
 Enhanced Real Time Clock Support
 CONFIG_RTC
diff -u --recursive --new-file v2.0.11/linux/Documentation/ide.txt linux/Documentation/ide.txt
--- v2.0.11/linux/Documentation/ide.txt	Mon Aug  5 10:13:50 1996
+++ linux/Documentation/ide.txt	Wed Aug  7 12:31:22 1996
@@ -257,7 +257,7 @@
 				older/odd IDE drives.
 
  "idebus=xx"		: inform IDE driver of VESA/PCI bus speed in Mhz,
-				where "xx" is between 25 and 66 inclusive,
+				where "xx" is between 20 and 66 inclusive,
 				used when tuning chipset PIO modes.
 				For PCI bus, 25 is correct for a P75 system,
 				30 is correct for P90,P120,P180 systems,
diff -u --recursive --new-file v2.0.11/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- v2.0.11/linux/Documentation/ioctl-number.txt	Wed Jun 26 11:05:25 1996
+++ linux/Documentation/ioctl-number.txt	Wed Aug  7 12:31:18 1996
@@ -1,5 +1,5 @@
 Ioctl Numbers
-12 Jun 1996
+6 Aug 1996
 Michael Chastain
 <mec@duracef.shout.net>
 
@@ -50,7 +50,8 @@
 (5) When following the convention, the driver code can use generic
     code to call verify_area to validate parameters.
 
-This table is current to Linux pre2.0.9.
+This table lists ioctls visible from user land for Linux/i386.  It is
+current to Linux 2.0.11.
 
 Code	Seq#	Include File		Comments
 ========================================================
@@ -83,6 +84,7 @@
 'T'	all	linux/soundcard.h	conflict!
 'T'	all	asm-i386/ioctls.h	conflict!
 'V'	all	linux/vt.h
+'W'	00-1F	linux/pcwd.h
 'Y'	all	linux/cyclades.h
 'Z'	all	linux/scc.h		version 2.2 of z8530drv
 'a'	all	various, see http://lrcwww.epfl.ch/linux-atm/magic.html
diff -u --recursive --new-file v2.0.11/linux/MAINTAINERS linux/MAINTAINERS
--- v2.0.11/linux/MAINTAINERS	Mon Aug  5 10:13:50 1996
+++ linux/MAINTAINERS	Wed Aug  7 12:31:22 1996
@@ -86,7 +86,7 @@
 L:	linux-net@vger.rutgers.edu
 S:	Maintained
 
-ETHEREXPRESS NETWORK DRIVER
+ETHEREXPRESS-16 NETWORK DRIVER
 P:	Philip Blundell
 M:	pjb27@cam.ac.uk
 L:	linux-net@vger.rutgers.edu
diff -u --recursive --new-file v2.0.11/linux/Makefile linux/Makefile
--- v2.0.11/linux/Makefile	Mon Aug  5 10:13:50 1996
+++ linux/Makefile	Mon Aug  5 10:15:21 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 11
+SUBLEVEL = 12
 
 ARCH = i386
 
diff -u --recursive --new-file v2.0.11/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.0.11/linux/arch/alpha/kernel/bios32.c	Mon Jul 15 14:22:53 1996
+++ linux/arch/alpha/kernel/bios32.c	Wed Aug  7 12:31:21 1996
@@ -993,6 +993,7 @@
 		{ 0,  0,  2,  1,  0}, /* idsel 11 KN25_PCI_SLOT0 */
 		{ 1,  1,  0,  2,  1}, /* idsel 12 KN25_PCI_SLOT1 */
 		{ 2,  2,  1,  0,  2}, /* idsel 13 KN25_PCI_SLOT2 */
+		{ 0,  0,  0,  0,  0}, /* idsel 14 AS255 TULIP */
 #endif
 	};
 	/*
@@ -1005,7 +1006,21 @@
 	 * This probably ought to be configurable via MILO.  For
 	 * example, sound boards seem to like using IRQ 9.
 	 */
+#ifdef CONFIG_ALPHA_NONAME
+	/*
+	 * For UDB, the only available PCI slot must not map to IRQ 9,
+	 *  since that's the builtin MSS sound chip. That PCI slot
+	 *  will map to PIRQ1 (for INTA at least), so we give it IRQ 15
+	 *  instead.
+	 *
+	 * Unfortunately we have to do this for NONAME as well, since
+	 *  they are co-indicated when the platform type "Noname" is
+	 *  selected... :-(
+	 */
+	const unsigned int route_tab = 0x0b0a0f09;
+#else /* CONFIG_ALPHA_NONAME */
 	const unsigned int route_tab = 0x0b0a090f;
+#endif /* CONFIG_ALPHA_NONAME */
 	unsigned int level_bits;
 	unsigned char pin, slot;
 	int pirq;
@@ -1093,8 +1108,13 @@
 	 * Now, make all PCI interrupts level sensitive.  Notice:
 	 * these registers must be accessed byte-wise.  inw()/outw()
 	 * don't work.
+	 *
+	 * Make sure to turn off any level bits set for IRQs 9,10,11,15,
+	 *  so that the only bits getting set are for devices actually found.
+	 * Note that we do preserve the remainder of the bits, which we hope
+	 *  will be set correctly by ARC/SRM.
 	 */
-	level_bits |= (inb(0x4d0) | (inb(0x4d1) << 8));
+	level_bits |= ((inb(0x4d0) | (inb(0x4d1) << 8)) & 0x71ff);
 	outb((level_bits >> 0) & 0xff, 0x4d0);
 	outb((level_bits >> 8) & 0xff, 0x4d1);
 	enable_ide(0x26e);
diff -u --recursive --new-file v2.0.11/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.0.11/linux/arch/alpha/kernel/irq.c	Mon Jul 15 09:47:41 1996
+++ linux/arch/alpha/kernel/irq.c	Wed Aug  7 12:31:22 1996
@@ -32,6 +32,10 @@
 #  error Unable to handle more than 64 irq levels.
 #endif
 
+/* Reserved interrupts.  These must NEVER be requested by any driver!
+ */
+#define	IS_RESERVED_IRQ(irq)	((irq)==2)	/* IRQ 2 used by hw cascade */
+
 /*
  * Shadow-copy of masked interrupts.
  *  The bits are used as follows:
@@ -185,6 +189,8 @@
 
 	if (irq >= NR_IRQS)
 		return -EINVAL;
+	if (IS_RESERVED_IRQ(irq))
+		return -EINVAL;
 	if (!handler)
 		return -EINVAL;
 	p = irq_action + irq;
@@ -239,6 +245,10 @@
 
 	if (irq >= NR_IRQS) {
 		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+	if (IS_RESERVED_IRQ(irq)) {
+		printk("Trying to free reserved IRQ %d\n", irq);
 		return;
 	}
 	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
diff -u --recursive --new-file v2.0.11/linux/drivers/block/Makefile linux/drivers/block/Makefile
--- v2.0.11/linux/drivers/block/Makefile	Sun May  5 09:09:40 1996
+++ linux/drivers/block/Makefile	Wed Aug  7 12:31:22 1996
@@ -10,13 +10,13 @@
 #
 
 #
-# Note : at this point, these files are compiled on all systems. 
+# Note : at this point, these files are compiled on all systems.
 # In the future, some of these should be built conditionally.
 #
 
 
 L_TARGET := block.a
-L_OBJS   := ll_rw_blk.o genhd.o 
+L_OBJS   := ll_rw_blk.o genhd.o
 M_OBJS   :=
 MOD_LIST_NAME := BLOCK_MODULES
 LX_OBJS :=
diff -u --recursive --new-file v2.0.11/linux/drivers/block/cmd640.c linux/drivers/block/cmd640.c
--- v2.0.11/linux/drivers/block/cmd640.c	Mon Aug  5 10:13:50 1996
+++ linux/drivers/block/cmd640.c	Wed Aug  7 12:31:22 1996
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/block/cmd640.c	Version 0.97  Aug  4, 1996
+ *  linux/drivers/block/cmd640.c	Version 0.99  Aug  6, 1996
  *
  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see below)
  */
@@ -90,6 +90,8 @@
  *  Version 0.96	prevent use of io_32bit when prefetch is off
  *  Version 0.97	fix VLB secondary interface for sjd@slip.net
  *			other minor tune-ups:  0.96 was very good.
+ *  Version 0.98	ignore PCI version when disabled by BIOS
+ *  Version 0.99	display setup/active/recovery clocks with PIO mode
  */
 
 #undef REALLY_SLOW_IO		/* most systems can safely undef this */
@@ -119,6 +121,7 @@
 #define VID		0x00
 #define DID		0x02
 #define PCMD		0x04
+#define   PCMD_ENA	0x01
 #define PSTTS		0x06
 #define REVID		0x08
 #define PROGIF		0x09
@@ -288,6 +291,10 @@
 		if (get_cmd640_reg(i) != ven_dev[i])
 			return 0;
 	}
+	if ((get_cmd640_reg(PCMD) & PCMD_ENA) == 0) {
+		printk("ide: cmd640 on PCI disabled by BIOS\n");
+		return 0;
+	}
 	return 1; /* success */
 }
 
@@ -458,6 +465,24 @@
 }
 
 /*
+ * Dump out current drive clocks settings
+ */
+static void display_clocks (unsigned int index)
+{
+	byte active_count, recovery_count;
+
+	active_count = active_counts[index];
+	if (active_count == 1)
+		++active_count;
+	recovery_count = recovery_counts[index];
+	if (active_count > 3 && recovery_count == 1)
+		++recovery_count;
+	if (cmd640_chip_version > 1)
+		recovery_count += 1;  /* cmd640b uses (count + 1)*/
+	printk(", clocks=%d/%d/%d\n", setup_counts[index], active_count, recovery_count);
+}
+
+/*
  * Pack active and recovery counts into single byte representation
  * used by controller
  */
@@ -564,7 +589,7 @@
 	active_time = ide_pio_timings[pio_mode].active_time;
 	recovery_time = cycle_time - (setup_time + active_time);
 	clock_time = 1000 / bus_speed;
-	cycle_count = (cycle_time + clock_time - 1) / clock_time; 
+	cycle_count = (cycle_time + clock_time - 1) / clock_time;
 
 	setup_count = (setup_time + clock_time - 1) / clock_time;
 
@@ -635,12 +660,13 @@
 	(void) ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
 	cmd640_set_mode (index, d.pio_mode, d.cycle_time);
 
-	printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s\n",
+	printk ("%s: selected cmd640 PIO mode%d (%dns) %s/IORDY%s",
 		drive->name,
 		d.pio_mode,
 		d.cycle_time,
 		d.use_iordy ? "w" : "wo",
 		d.overridden ? " (overriding vendor mode)" : "");
+	display_clocks(index);
 }
 
 #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */
@@ -784,8 +810,9 @@
 			 */
 			retrieve_drive_counts (index);
 			check_prefetch (index);
-			printk("cmd640: drive%d timings/prefetch(%s) preserved\n",
+			printk("cmd640: drive%d timings/prefetch(%s) preserved",
 				index, drive->no_io_32bit ? "off" : "on");
+			display_clocks(index);
 		}
 #else
 		/*
diff -u --recursive --new-file v2.0.11/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.0.11/linux/drivers/block/floppy.c	Mon Aug  5 10:13:50 1996
+++ linux/drivers/block/floppy.c	Thu Aug  8 12:30:42 1996
@@ -1685,15 +1685,9 @@
 		} while ((ST0 & 0x83) != UNIT(current_drive) && inr == 2);
 	}
 	if (handler) {
-		if(intr_count >= 2)
-			{
-				/* expected interrupt */
-				floppy_tq.routine = (void *)(void *) handler;
-				queue_task_irq(&floppy_tq, &tq_immediate);
-				mark_bh(IMMEDIATE_BH);
-			}
-		else
-			handler();
+		/* expected interrupt */
+		floppy_tq.routine = (void *)(void *) handler;
+		queue_task_irq(&floppy_tq, &tq_timer);
 	} else
 		FDCS->reset = 1;
 	is_alive("normal interrupt end");
@@ -1931,8 +1925,7 @@
 	unsigned long flags;
 
 	floppy_tq.routine = (void *)(void *) handler;
-	queue_task(&floppy_tq, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	queue_task(&floppy_tq, &tq_timer);
 	INT_OFF;
 	while(command_status < 2 && NO_SIGNAL){
 		is_alive("wait_til_done");
@@ -2740,8 +2733,7 @@
 		if (TESTF(FD_NEED_TWADDLE))
 			twaddle();
 		floppy_tq.routine = (void *)(void *) floppy_start;
-		queue_task(&floppy_tq, &tq_immediate);
-		mark_bh(IMMEDIATE_BH);
+		queue_task(&floppy_tq, &tq_timer);
 #ifdef DEBUGT
 		debugt("queue fd request");
 #endif
@@ -2762,8 +2754,7 @@
 static void process_fd_request(void)
 {
 	cont = &rw_cont;
-	queue_task(&request_tq, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
+	queue_task(&request_tq, &tq_timer);
 }
 
 static void do_fd_request(void)
diff -u --recursive --new-file v2.0.11/linux/drivers/block/ide.c linux/drivers/block/ide.c
--- v2.0.11/linux/drivers/block/ide.c	Mon Aug  5 10:13:51 1996
+++ linux/drivers/block/ide.c	Wed Aug  7 12:31:22 1996
@@ -256,6 +256,7 @@
  *			fix missing restore_flags() in ide_ioctl
  *			prevent use of io_32bit on cmd640 with no prefetch
  * Version 5.49		fix minor quirks in probing routines
+ * Version 5.50		allow values as small as 20 for idebus=
  *
  *  Some additional driver compile-time options are in ide.h
  *
@@ -2807,7 +2808,7 @@
  *				older/odd IDE drives.
  *
  * "idebus=xx"		: inform IDE driver of VESA/PCI bus speed in Mhz,
- *				where "xx" is between 25 and 66 inclusive,
+ *				where "xx" is between 20 and 66 inclusive,
  *				used when tuning chipset PIO modes.
  *				For PCI bus, 25 is correct for a P75 system,
  *				30 is correct for P90,P120,P180 systems,
@@ -2912,10 +2913,10 @@
 	if (s[3] == 'b' && s[4] == 'u' && s[5] == 's') {
 		if (match_parm(&s[6], NULL, vals, 1) != 1)
 			goto bad_option;
-		if (vals[0] >= 25 && vals[0] <= 66)
+		if (vals[0] >= 20 && vals[0] <= 66)
 			idebus_parameter = vals[0];
 		else
-			printk(" -- BAD BUS SPEED! Expected value from 25 to 66");
+			printk(" -- BAD BUS SPEED! Expected value from 20 to 66");
 		goto done;
 	}
 	/*
diff -u --recursive --new-file v2.0.11/linux/drivers/block/ide.h linux/drivers/block/ide.h
--- v2.0.11/linux/drivers/block/ide.h	Mon Aug  5 10:13:51 1996
+++ linux/drivers/block/ide.h	Fri Aug  9 16:25:54 1996
@@ -42,7 +42,7 @@
 #endif
 
 #ifdef CONFIG_BLK_DEV_CMD640
-#if 1
+#if 0	/* change to 1 when debugging cmd640 problems */
 void cmd640_dump_regs (void);
 #define CMD640_DUMP_REGS cmd640_dump_regs() /* for debugging cmd640 chipset */
 #endif
diff -u --recursive --new-file v2.0.11/linux/drivers/net/arcnet.c linux/drivers/net/arcnet.c
--- v2.0.11/linux/drivers/net/arcnet.c	Mon Jul  8 14:17:58 1996
+++ linux/drivers/net/arcnet.c	Tue Aug  6 12:58:35 1996
@@ -17,6 +17,11 @@
          
 	**********************
 	
+	v2.55 (96/08/05)
+	  - A couple more messages moved to D_EXTRA.
+	  - SLOW_XMIT_COPY off by default.
+	  - Some tiny changes.
+	
 	v2.54 (96/07/05)
 	  - Under some situations, Stage 5 autoprobe was a little bit too
 	    picky about the TXACK flag.
@@ -154,14 +159,19 @@
          
 	TO DO: (semi-prioritized)
 	
-         - Smarter recovery from RECON-during-transmit conditions.
+         - Support "arpless" mode like NetBSD does, and as recommended
+           by the (obsoleted) RFC1051.
+         - Smarter recovery from RECON-during-transmit conditions. (ie.
+           retransmit immediately)
          - Make arcnetE_send_packet use arcnet_prepare_tx for loading the
            packet into ARCnet memory.
-	 - Probe for multiple devices in one shot (trying to decide whether
-	   to do it the "ugly" way or not).
-         - Add support for the new 1.3.x IP header cache features.
-	 - Debug level should be changed with a system call, not a hack to
-	   the "metric" flag.
+         - Some cards have shared memory with 4k mirrors instead of just 2k,
+           so we (uneventfully) find the "wrong" shmem when probing.
+         - Probe for multiple devices in one shot (trying to decide whether
+           to do it the "ugly" way or not).
+         - Add support for the new 1.3.x IP header cache, and other features.
+         - Debug level should be changed with a system call, not a hack to
+           the "metric" flag.
          - What about cards with shared memory that can be "turned off?"
            (or that have none at all, like the SMC PC500longboard)
          - Autoconfigure PDI5xxPlus cards. (I now have a PDI508Plus to play
@@ -192,7 +202,7 @@
 */
 
 static const char *version =
- "arcnet.c: v2.54 96/07/05 Avery Pennarun <apenwarr@foxnet.net>\n";
+ "arcnet.c: v2.55 96/08/05 Avery Pennarun <apenwarr@foxnet.net>\n";
 
  
 
@@ -244,11 +254,11 @@
  * defines; ARCnet probably is not the only driver that can screw up an
  * ftape DMA transfer.
  *
- * Turn this off if you don't have timing-sensitive DMA (ie. a tape drive)
- * and would like the little bit of speed back.  It's on by default because
- * - trust me - it's very difficult to figure out that you need it!
+ * Turn this on if you have timing-sensitive DMA (ie. a tape drive) and
+ * would like to sacrifice a little bit of network speed to reduce tape
+ * write retries or some related problem.
  */
-#define SLOW_XMIT_COPY
+#undef SLOW_XMIT_COPY
 
 /* The card sends the reconfiguration signal when it loses the connection to
  * the rest of its network. It is a 'Hello, is anybody there?' cry.  This
@@ -2310,7 +2320,7 @@
 			
 		if (in->skb)	/* already assembling one! */
         	{
-        		BUGMSG(D_NORMAL,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
+        		BUGMSG(D_EXTRA,"aborting assembly (seq=%d) for unsplit packet (splitflag=%d, seq=%d)\n",
         			in->sequence,arcsoft->split_flag,
         			arcsoft->sequence);
         		kfree_skb(in->skb,FREE_WRITE);
@@ -2407,7 +2417,7 @@
 
 		if (in->skb && in->sequence!=arcsoft->sequence)
 		{
-			BUGMSG(D_NORMAL,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
+			BUGMSG(D_EXTRA,"wrong seq number (saddr=%d, expected=%d, seq=%d, splitflag=%d)\n",
 				saddr,in->sequence,arcsoft->sequence,
 				arcsoft->split_flag);
 	        	kfree_skb(in->skb,FREE_WRITE);
@@ -2423,7 +2433,7 @@
 	        		arcsoft->split_flag);
 	        	if (in->skb)	/* already assembling one! */
 	        	{
-	        		BUGMSG(D_NORMAL,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
+	        		BUGMSG(D_EXTRA,"aborting previous (seq=%d) assembly (splitflag=%d, seq=%d)\n",
 	        			in->sequence,arcsoft->split_flag,
 	        			arcsoft->sequence);
 				lp->stats.rx_errors++;
@@ -2437,7 +2447,7 @@
 	        	
 	        	if (in->numpackets>16)
 	        	{
-	        		BUGMSG(D_NORMAL,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
+	        		BUGMSG(D_EXTRA,"incoming packet more than 16 segments; dropping. (splitflag=%d)\n",
 	        			arcsoft->split_flag);
 	        		lp->stats.rx_errors++;
 	        		lp->stats.rx_length_errors++;
@@ -2477,7 +2487,7 @@
 			 */			
 			if (!in->skb)
 			{
-				BUGMSG(D_NORMAL,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
+				BUGMSG(D_EXTRA,"can't continue split without starting first! (splitflag=%d, seq=%d)\n",
 					arcsoft->split_flag,arcsoft->sequence);
 				lp->stats.rx_errors++;
 				lp->stats.rx_missed_errors++;
@@ -2490,7 +2500,7 @@
 				/* harmless duplicate? ignore. */
 				if (packetnum<=in->lastpacket-1)
 				{
-					BUGMSG(D_NORMAL,"duplicate splitpacket ignored! (splitflag=%d)\n",
+					BUGMSG(D_EXTRA,"duplicate splitpacket ignored! (splitflag=%d)\n",
 						arcsoft->split_flag);
 					lp->stats.rx_errors++;
 					lp->stats.rx_frame_errors++;
@@ -2498,7 +2508,7 @@
 				}
 				
 				/* "bad" duplicate, kill reassembly */
-				BUGMSG(D_NORMAL,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",	
+				BUGMSG(D_EXTRA,"out-of-order splitpacket, reassembly (seq=%d) aborted (splitflag=%d, seq=%d)\n",
 					in->sequence,arcsoft->split_flag,
 					arcsoft->sequence);
 	        		kfree_skb(in->skb,FREE_WRITE);
diff -u --recursive --new-file v2.0.11/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.0.11/linux/drivers/net/eepro.c	Fri Apr 12 09:49:37 1996
+++ linux/drivers/net/eepro.c	Tue Aug  6 09:40:29 1996
@@ -8,16 +8,13 @@
 	according to the terms of the GNU Public License,
 	incorporated herein by reference.
 
-	The author may be reached at bao@saigon.async.com 
+	The author may be reached at bao.ha@srs.gov 
 	or 418 Hastings Place, Martinez, GA 30907.
 
 	Things remaining to do:
 	Better record keeping of errors.
 	Eliminate transmit interrupt to reduce overhead.
 	Implement "concurrent processing". I won't be doing it!
-	Allow changes to the partition of the transmit and receive
-	buffers, currently the ratio is 3:1 of receive to transmit
-	buffer ratio.  
 
 	Bugs:
 
@@ -27,6 +24,13 @@
 
 	Versions:
 
+	0.09	Fixed a race condition in the transmit algorithm,
+		which causes crashes under heavy load with fast
+		pentium computers.  The performance should also
+		improve a bit.  The size of RX buffer, and hence
+		TX buffer, can also be changed via lilo or insmod.
+		(BCH, 7/31/96)
+
 	0.08	Implement 32-bit I/O for the 82595TX and 82595FX
 		based lan cards.  Disable full-duplex mode if TPE
 		is not used.  (BCH, 4/8/96)
@@ -56,7 +60,7 @@
 */
 
 static const char *version =
-	"eepro.c: v0.08 4/8/96 Bao C. Ha (bao.ha@srs.gov)\n";
+	"eepro.c: v0.09 7/31/96 Bao C. Ha (bao.ha@srs.gov)\n";
 
 #include <linux/module.h>
 
@@ -110,7 +114,7 @@
 
 /* use 0 for production, 1 for verification, >2 for debug */
 #ifndef NET_DEBUG
-#define NET_DEBUG 2
+#define NET_DEBUG 3
 #endif
 static unsigned int net_debug = NET_DEBUG;
 
@@ -180,15 +184,26 @@
 network traffics, the ring linked list should improve performance by
 allowing up to 8K worth of packets to be queued.
 
+The sizes of the receive and transmit buffers can now be changed via lilo 
+or insmod.  Lilo uses the appended line "ether=io,irq,debug,rx-buffer,eth0"
+where rx-buffer is in KB unit.  Modules uses the parameter mem which is
+also in KB unit, for example "insmod io=io-address irq=0 mem=rx-buffer."  
+The receive buffer has to be more than 3K or less than 29K.  Otherwise,
+it is reset to the default of 24K, and, hence, 8K for the trasnmit
+buffer (transmit-buffer = 32K - receive-buffer).
+
 */
 #define	RAM_SIZE	0x8000
 #define	RCV_HEADER	8
-#define	RCV_RAM		0x6000	/* 24KB for RCV buffer */
-#define	RCV_LOWER_LIMIT	0x00	/* 0x0000 */
-#define	RCV_UPPER_LIMIT	((RCV_RAM - 2) >> 8)	/* 0x5ffe */
-#define	XMT_RAM		(RAM_SIZE - RCV_RAM)	/* 8KB for XMT buffer */
-#define	XMT_LOWER_LIMIT	(RCV_RAM >> 8)	/* 0x6000 */
-#define	XMT_UPPER_LIMIT	((RAM_SIZE - 2) >> 8)	/* 0x7ffe */
+#define RCV_RAM         0x6000  /* 24KB default for RCV buffer */
+#define RCV_LOWER_LIMIT 0x00    /* 0x0000 */
+/* #define RCV_UPPER_LIMIT ((RCV_RAM - 2) >> 8) */    /* 0x5ffe */
+#define RCV_UPPER_LIMIT (((rcv_ram) - 2) >> 8)   
+/* #define XMT_RAM         (RAM_SIZE - RCV_RAM) */    /* 8KB for XMT buffer */
+#define XMT_RAM         (RAM_SIZE - (rcv_ram))    /* 8KB for XMT buffer */
+/* #define XMT_LOWER_LIMIT (RCV_RAM >> 8) */  /* 0x6000 */
+#define XMT_LOWER_LIMIT ((rcv_ram) >> 8) 
+#define XMT_UPPER_LIMIT ((RAM_SIZE - 2) >> 8)   /* 0x7ffe */
 #define	XMT_HEADER	8
 
 #define	RCV_DONE	0x0008
@@ -368,6 +383,16 @@
 				dev->dev_addr[i] = ((unsigned char *) station_addr)[5-i];
 				printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
 			}
+			
+			if ((dev->mem_end & 0x3f) < 3 ||	/* RX buffer must be more than 3K */
+				(dev->mem_end & 0x3f) > 29)	/* and less than 29K */
+				dev->mem_end = RCV_RAM;		/* or it will be set to 24K */
+			else dev->mem_end = 1024*dev->mem_end;  /* Maybe I should shift << 10 */
+
+			/* From now on, dev->mem_end contains the actual size of rx buffer */
+			
+			if (net_debug > 3)
+				printk(", %dK RCV buffer", (int)(dev->mem_end)/1024);
 				
 			outb(BANK2_SELECT, ioaddr); /* be CAREFUL, BANK 2 now */
 			id = inb(ioaddr + REG3);
@@ -401,8 +426,8 @@
 			}
 			else printk(", %s.\n", ifmap[dev->if_port]);
 			
-			if ((dev->mem_start & 0xf) > 0)
-				net_debug = dev->mem_start & 7;
+			if ((dev->mem_start & 0xf) > 0)	/* I don't know if this is */
+				net_debug = dev->mem_start & 7; /* still useful or not */
 
 			if (net_debug > 3) {
 				i = read_eeprom(ioaddr, 5);
@@ -516,7 +541,7 @@
 eepro_open(struct device *dev)
 {
 	unsigned short temp_reg, old8, old9;
-	int i, ioaddr = dev->base_addr;
+	int i, ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 
 	if (net_debug > 3)
@@ -654,6 +679,7 @@
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	int ioaddr = dev->base_addr;
+	int rcv_ram = dev->mem_end;
 
 	if (net_debug > 5)
 		printk("eepro: entering eepro_send_packet routine.\n");
@@ -662,12 +688,13 @@
 		/* If we get here, some higher level has decided we are broken.
 		   There should really be a "kick me" function call instead. */
 		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 5)
+		if (tickssofar < 40)
 			return 1;
 		if (net_debug > 1)
 			printk("%s: transmit timed out, %s?\n", dev->name,
 				   "network cable problem");
 		lp->stats.tx_errors++;
+
 		/* Try to restart the adaptor. */
 		outb(SEL_RESET_CMD, ioaddr); 
 		/* We are supposed to wait for 2 us after a SEL_RESET */
@@ -675,7 +702,7 @@
 		SLOW_DOWN_IO;
 
 		/* Do I also need to flush the transmit buffers here? YES? */
-		lp->tx_start = lp->tx_end = RCV_RAM; 
+		lp->tx_start = lp->tx_end = rcv_ram; 
 		lp->tx_last = 0;
 	
 		dev->tbusy=0;
@@ -722,7 +749,7 @@
 eepro_interrupt(int irq, void *dev_id, struct pt_regs * regs)
 {
 	struct device *dev = (struct device *)(irq2dev_map[irq]);
-	int ioaddr, status, boguscount = 0;
+	int ioaddr, status, boguscount = 20;
 
 	if (net_debug > 5)
 		printk("eepro: entering eepro_interrupt routine.\n");
@@ -737,7 +764,7 @@
 
 	do { 
 		status = inb(ioaddr + STATUS_REG);
-
+		
 		if (status & RX_INT) {
 			if (net_debug > 4)
 				printk("eepro: packet received interrupt.\n");
@@ -748,6 +775,7 @@
 			/* Get the received packets */
 			eepro_rx(dev);
 		}
+
 		else if (status & TX_INT) {
 			if (net_debug > 4)
 				printk("eepro: packet transmit interrupt.\n");
@@ -757,10 +785,9 @@
 
 			/* Process the status of transmitted packets */
 			eepro_transmit_interrupt(dev);
-			dev->tbusy = 0;
-			mark_bh(NET_BH);
-		}		
-	} while ((++boguscount < 10) && (status & 0x06));
+		}
+	
+	} while ((boguscount-- > 0) && (status & 0x06));
 
 	dev->interrupt = 0;
 	if (net_debug > 5)
@@ -774,6 +801,7 @@
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	int ioaddr = dev->base_addr;
+	int rcv_ram = dev->mem_end;
 	short temp_reg;
 
 	dev->tbusy = 1;
@@ -789,7 +817,7 @@
 
 	/* Flush the Tx and disable Rx. */
 	outb(STOP_RCV_CMD, ioaddr); 
-	lp->tx_start = lp->tx_end = RCV_RAM ;
+	lp->tx_start = lp->tx_end = rcv_ram ;
 	lp->tx_last = 0;  
 
 	/* Mask all the interrupts. */
@@ -912,7 +940,9 @@
 			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
 			lp->tx_end = i ;
 		}
-		else lp->tx_start = lp->tx_end = i ;
+		else {
+			lp->tx_start = lp->tx_end = i ;
+		}
 
 		/* Acknowledge that the MC setup is done */
 		do { /* We should be doing this in the eepro_interrupt()! */
@@ -993,13 +1023,25 @@
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	short ioaddr = dev->base_addr;
-	unsigned status, tx_available, last, end, boguscount = 10;
+	int rcv_ram = dev->mem_end;
+	unsigned status, tx_available, last, end, boguscount = 100;
 
 	if (net_debug > 5)
 		printk("eepro: entering hardware_send_packet routine.\n");
 
 	while (boguscount-- > 0) {
 
+		/* Disable RX and TX interrupts.  Necessary to avoid
+	   	corruption of the HOST_ADDRESS_REG by interrupt
+	   	service routines. */
+		outb(ALL_MASK, ioaddr + INT_MASK_REG);
+
+		if (dev->interrupt == 1) {  
+			/* Enable RX and TX interrupts */
+			outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+			continue;
+		}
+
 		/* determine how much of the transmit buffer space is available */
 		if (lp->tx_end > lp->tx_start)
 			tx_available = XMT_RAM - (lp->tx_end - lp->tx_start);
@@ -1007,14 +1049,15 @@
 			tx_available = lp->tx_start - lp->tx_end;
 		else tx_available = XMT_RAM;
 
-		/* Disable RX and TX interrupts.  Necessary to avoid
-		   corruption of the HOST_ADDRESS_REG by interrupt
-		   service routines. */
-		outb(ALL_MASK, ioaddr + INT_MASK_REG);
-
 		if (((((length + 3) >> 1) << 1) + 2*XMT_HEADER) 
 			>= tx_available)   /* No space available ??? */
+			{
+			eepro_transmit_interrupt(dev); /* Clean up the transmiting queue */
+
+			/* Enable RX and TX interrupts */
+			outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
 			continue;
+		}
 
 		last = lp->tx_end;
 		end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
@@ -1023,10 +1066,10 @@
 			if ((RAM_SIZE - last) <= XMT_HEADER) {	
 			/* Arrrr!!!, must keep the xmt header together,
 			  several days were lost to chase this one down. */
-				last = RCV_RAM;
+				last = rcv_ram;
 				end = last + (((length + 3) >> 1) << 1) + XMT_HEADER;
 			}	
-			else end = RCV_RAM + (end - RAM_SIZE);
+			else end = rcv_ram + (end - RAM_SIZE);
 		}
 
 		outw(last, ioaddr + HOST_ADDRESS_REG);
@@ -1044,9 +1087,17 @@
 			outb(temp & ~(IO_32_BIT), ioaddr + INT_MASK_REG);
 		}
 
-		if (lp->tx_start != lp->tx_end) { 
+		/* A dummy read to flush the DRAM write pipeline */
+		status = inw(ioaddr + IO_PORT); 
+
+		if (lp->tx_start == lp->tx_end) {	
+			outw(last, ioaddr + XMT_BAR);
+			outb(XMT_CMD, ioaddr);
+			lp->tx_start = last;   /* I don't like to change tx_start here */
+		}
+		else {
 			/* update the next address and the chain bit in the 
-			   last packet */
+		   	last packet */
 			if (lp->tx_end != last) {
 				outw(lp->tx_last + XMT_CHAIN, ioaddr + HOST_ADDRESS_REG);
 				outw(last, ioaddr + IO_PORT);
@@ -1054,33 +1105,26 @@
 			outw(lp->tx_last + XMT_COUNT, ioaddr + HOST_ADDRESS_REG);
 			status = inw(ioaddr + IO_PORT);
 			outw(status | CHAIN_BIT, ioaddr + IO_PORT);
-		}
 
-		/* A dummy read to flush the DRAM write pipeline */
-		status = inw(ioaddr + IO_PORT); 
-
-		/* Enable RX and TX interrupts */
-		outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
-	
-		if (lp->tx_start == lp->tx_end) {
-			outw(last, ioaddr + XMT_BAR);
-			outb(XMT_CMD, ioaddr);
-			lp->tx_start = last;   /* I don't like to change tx_start here */
+			/* Continue the transmit command */
+			outb(RESUME_XMT_CMD, ioaddr);
 		}
-		else	outb(RESUME_XMT_CMD, ioaddr);
 
 		lp->tx_last = last;
 		lp->tx_end = end;
 
+		/* Enable RX and TX interrupts */
+		outb(ALL_MASK & ~(RX_MASK | TX_MASK), ioaddr + INT_MASK_REG); 
+	
 		if (dev->tbusy) {
 			dev->tbusy = 0;
-			mark_bh(NET_BH);
 		}
 
 		if (net_debug > 5)
 			printk("eepro: exiting hardware_send_packet routine.\n");
 		return;
 	}
+
 	dev->tbusy = 1;
 	if (net_debug > 5)
 		printk("eepro: exiting hardware_send_packet routine.\n");
@@ -1090,7 +1134,7 @@
 eepro_rx(struct device *dev)
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
-	short ioaddr = dev->base_addr;
+	short ioaddr = dev->base_addr, rcv_ram = dev->mem_end;
 	short boguscount = 20;
 	short rcv_car = lp->rx_start;
 	unsigned rcv_event, rcv_status, rcv_next_frame, rcv_size;
@@ -1171,7 +1215,7 @@
 {
 	struct eepro_local *lp = (struct eepro_local *)dev->priv;
 	short ioaddr = dev->base_addr;
-	short boguscount = 10; 
+	short boguscount = 20; 
 	short xmt_status;
 
 	while (lp->tx_start != lp->tx_end) { 
@@ -1179,16 +1223,15 @@
 		outw(lp->tx_start, ioaddr + HOST_ADDRESS_REG);
 		xmt_status = inw(ioaddr+IO_PORT);
 		if ((xmt_status & TX_DONE_BIT) == 0) break;
+
 		xmt_status = inw(ioaddr+IO_PORT);
 		lp->tx_start = inw(ioaddr+IO_PORT);
-	
-		if (dev->tbusy) {
-			dev->tbusy = 0;
-			mark_bh(NET_BH);
-		}
+
+		dev->tbusy = 0;
+		mark_bh(NET_BH);
 
 		if (xmt_status & 0x2000)
-			lp->stats.tx_packets++;
+			lp->stats.tx_packets++; 
 		else {
 			lp->stats.tx_errors++;
 			if (xmt_status & 0x0400)
@@ -1196,10 +1239,12 @@
 			printk("%s: XMT status = %#x\n",
 				dev->name, xmt_status);
 		}
-		if (xmt_status & 0x000f)
+		if (xmt_status & 0x000f) {
 			lp->stats.collisions += (xmt_status & 0x000f);
-		if ((xmt_status & 0x0040) == 0x0)
+		}
+		if ((xmt_status & 0x0040) == 0x0) {
 			lp->stats.tx_heartbeat_errors++;
+		}
 
 		if (--boguscount == 0)
 			break;  
@@ -1216,6 +1261,7 @@
 
 static int io = 0x200;
 static int irq = 0;
+static int mem = (RCV_RAM/1024);	/* Size of the rx buffer in KB */
 
 int
 init_module(void)
@@ -1224,6 +1270,7 @@
 		printk("eepro: You should not use auto-probing with insmod!\n");
 	dev_eepro.base_addr = io;
 	dev_eepro.irq       = irq;
+	dev_eepro.mem_end   = mem;
 
 	if (register_netdev(&dev_eepro) != 0)
 		return -EIO;
diff -u --recursive --new-file v2.0.11/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v2.0.11/linux/drivers/net/plip.c	Sun May 19 14:57:51 1996
+++ linux/drivers/net/plip.c	Fri Aug  9 13:33:52 1996
@@ -873,9 +873,9 @@
 		return 0;
 	}
 
-	for (i=0; i < ETH_ALEN - sizeof(unsigned long); i++)
+	for (i=0; i < ETH_ALEN - sizeof(u32); i++)
 		eth->h_dest[i] = 0xfc;
-	memcpy(&(eth->h_dest[i]), &dst, sizeof(unsigned long));
+	*(u32 *)(eth->h_dest+i) = dst;
 	return 0;
 }
 
@@ -964,9 +964,9 @@
 	nl->is_deferred = 0;
 
 	/* Fill in the MAC-level header. */
-	for (i=0; i < ETH_ALEN - sizeof(unsigned long); i++)
+	for (i=0; i < ETH_ALEN - sizeof(u32); i++)
 		dev->dev_addr[i] = 0xfc;
-	memcpy(&(dev->dev_addr[i]), &dev->pa_addr, sizeof(unsigned long));
+	*(u32 *)(dev->dev_addr+i) = dev->pa_addr;
 
 	dev->interrupt = 0;
 	dev->start = 1;
diff -u --recursive --new-file v2.0.11/linux/drivers/scsi/fdomain.c linux/drivers/scsi/fdomain.c
--- v2.0.11/linux/drivers/scsi/fdomain.c	Mon May  6 12:26:11 1996
+++ linux/drivers/scsi/fdomain.c	Fri Aug  9 10:43:24 1996
@@ -1,10 +1,10 @@
 /* fdomain.c -- Future Domain TMC-16x0 SCSI driver
  * Created: Sun May  3 18:53:19 1992 by faith@cs.unc.edu
- * Revised: Thu Apr  4 20:44:47 1996 by r.faith@ieee.org
+ * Revised: Thu Aug  8 14:58:51 1996 by r.faith@ieee.org
  * Author: Rickard E. Faith, faith@cs.unc.edu
  * Copyright 1992, 1993, 1994, 1995, 1996 Rickard E. Faith
  *
- * $Id: fdomain.c,v 5.41 1996/04/05 04:22:25 root Exp $
+ * $Id: fdomain.c,v 5.44 1996/08/08 18:58:53 root Exp $
 
  * 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
@@ -104,6 +104,7 @@
  1.3.34      5.39        12 Oct 1995  V3.60 BIOS; /proc
  1.3.72      5.39         8 Feb 1996  Adaptec AHA-2920 board
  1.3.85      5.41         4 Apr 1996
+ 2.0.12      5.44         8 Aug 1996  Use ID 7 for all PCI cards
 
  
 
@@ -275,7 +276,7 @@
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
   
-#define VERSION          "$Revision: 5.41 $"
+#define VERSION          "$Revision: 5.44 $"
 
 /* START OF USER DEFINABLE OPTIONS */
 
@@ -580,8 +581,8 @@
 
 				/* Try to toggle 32-bit mode.  This only
 				   works on an 18c30 chip.  (User reports
-				   say that this doesn't work at all, so
-				   we'll use the other method.) */
+				   say this works, so we should switch to
+				   it in the near future.) */
 
       outb( 0x80, port + IO_Control );
       if ((inb( port + Configuration2 ) & 0x80) == 0x80) {
@@ -1018,7 +1019,7 @@
       tpnt->this_id = (this_id & 0x07);
       adapter_mask  = (1 << tpnt->this_id);
    } else {
-      if ((bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
+      if (PCI_bus || (bios_major == 3 && bios_minor >= 2) || bios_major < 0) {
 	 tpnt->this_id = 7;
 	 adapter_mask  = 0x80;
       } else {
@@ -1246,7 +1247,7 @@
 #endif
 #if ERRORS_ONLY
    if (!target) {
-      if (chip == tmc18c30 && !flag) /* Skip first failure for 18C30 chips. */
+      if (!flag) /* Skip first failure for all chips. */
 	    ++flag;
       else
 	    printk( "fdomain: Selection failed\n" );
@@ -1394,7 +1395,9 @@
 	 printk( "Status = %x, ", current_SC->SCp.Status );
 #endif
 #if ERRORS_ONLY
-	 if (current_SC->SCp.Status && current_SC->SCp.Status != 2) {
+	 if (current_SC->SCp.Status
+	     && current_SC->SCp.Status != 2
+	     && current_SC->SCp.Status != 8) {
 	    printk( "fdomain: target = %d, command = %x, status = %x\n",
 		    current_SC->target,
 		    current_SC->cmnd[0],
@@ -1666,7 +1669,7 @@
 	    qualifier = (unsigned char)(*((char *)current_SC->request_buffer
 					  + 13));
 
-	    if (!(key == UNIT_ATTENTION && (code == 0x29 || !code))
+	    if (key != UNIT_ATTENTION
 		&& !(key == NOT_READY
 		     && code == 0x04
 		     && (!qualifier || qualifier == 0x02 || qualifier == 0x01))
diff -u --recursive --new-file v2.0.11/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.0.11/linux/drivers/scsi/hosts.c	Sat Jul  6 12:06:37 1996
+++ linux/drivers/scsi/hosts.c	Wed Aug  7 12:31:21 1996
@@ -261,6 +261,9 @@
 #ifdef CONFIG_SCSI_QLOGIC_FAS
     QLOGICFAS,
 #endif
+#ifdef CONFIG_SCSI_QLOGIC_ISP
+    QLOGICISP,
+#endif
 #ifdef CONFIG_SCSI_PAS16
     MV_PAS16,
 #endif
@@ -293,9 +296,6 @@
 #endif
 #ifdef CONFIG_SCSI_AM53C974
     AM53C974,
-#endif
-#ifdef CONFIG_SCSI_QLOGIC_ISP
-    QLOGICISP,
 #endif
 #ifdef CONFIG_SCSI_PPA
     PPA,
diff -u --recursive --new-file v2.0.11/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.0.11/linux/drivers/scsi/sd.c	Thu Jul 18 14:28:48 1996
+++ linux/drivers/scsi/sd.c	Fri Aug  9 11:20:56 1996
@@ -490,6 +490,9 @@
 	    if( SDev->removable && !intr_count )
 	    {
                 scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, 0);
+		/* scsi_ioctl may allow CURRENT to change, so start over. */
+		SDev->was_reset = 0;
+		continue;
 	    }
 	    SDev->was_reset = 0;
         }
diff -u --recursive --new-file v2.0.11/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.0.11/linux/drivers/scsi/sr.c	Mon Aug  5 10:13:53 1996
+++ linux/drivers/scsi/sr.c	Thu Aug  8 12:21:48 1996
@@ -485,11 +485,11 @@
 		printk(KERN_WARNING"sr_photocd: ioctl error (TOSHIBA #1): 0x%x\n",rc);
 	    break; /* if the first ioctl fails, we don't call the second one */
 	}
+	is_xa  = (rec[0] == 0x20);
 	min    = (unsigned long) rec[1]/16*10 + (unsigned long) rec[1]%16;
 	sec    = (unsigned long) rec[2]/16*10 + (unsigned long) rec[2]%16;
 	frame  = (unsigned long) rec[3]/16*10 + (unsigned long) rec[3]%16;
 	sector = min*CD_SECS*CD_FRAMES + sec*CD_FRAMES + frame;
-	is_xa  = (rec[0] == 0x20) || sector;
 	if (sector) {
 	    sector -= CD_BLOCK_OFFSET;
 #ifdef DEBUG
@@ -566,9 +566,6 @@
 	    break;
 	}
 	sector = rec[11] + (rec[10] << 8) + (rec[9] << 16) + (rec[8] << 24);
-	if (rec[6] <= 1) {
-	    sector = 0; /* ignore sector offsets from first track */
-	}
 	is_xa = !!sector;
 #ifdef DEBUG
 	if (sector)
diff -u --recursive --new-file v2.0.11/linux/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c
--- v2.0.11/linux/drivers/sound/sb_audio.c	Sat Jul  6 11:31:42 1996
+++ linux/drivers/sound/sb_audio.c	Fri Aug  9 16:18:48 1996
@@ -629,7 +629,7 @@
 
   if (devc->channels == 1)
     {
-      if (devc->bits == AFMT_U8 == 0)
+      if (devc->bits == AFMT_U8)
 	{			/* 8 bit mono */
 	  ess_write (devc, 0xb7, 0x51);
 	  ess_write (devc, 0xb7, 0xd0);
diff -u --recursive --new-file v2.0.11/linux/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c
--- v2.0.11/linux/drivers/sound/sb_midi.c	Sat Jul  6 11:31:43 1996
+++ linux/drivers/sound/sb_midi.c	Wed Aug  7 12:31:22 1996
@@ -87,6 +87,7 @@
   sb_dsp_reset (devc);
   devc->intr_active = 0;
   devc->input_opened = 0;
+  devc->opened = 0;
   restore_flags (flags);
 }
 
diff -u --recursive --new-file v2.0.11/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.0.11/linux/drivers/sound/soundcard.c	Thu Jul 11 18:22:34 1996
+++ linux/drivers/sound/soundcard.c	Wed Aug  7 12:31:21 1996
@@ -289,7 +289,7 @@
 	      size, dmap->bytes_in_use);
     }
 
-  if (remap_page_range (vma_get_start (vma), virt_to_phys(dmap->raw_buf),
+  if (remap_page_range (vma_get_start (vma), (unsigned long)dmap->raw_buf,
 			vma_get_end (vma) - vma_get_start (vma),
 			vma_get_page_prot (vma)))
     return -EAGAIN;
diff -u --recursive --new-file v2.0.11/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.0.11/linux/fs/binfmt_elf.c	Mon Aug  5 10:13:53 1996
+++ linux/fs/binfmt_elf.c	Thu Aug  8 12:25:46 1996
@@ -765,7 +765,7 @@
 
 	/* First of all, some simple consistency checks */
 	if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
-	   (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
+	   !elf_check_arch(elf_ex.e_machine) ||
 	   (!inode->i_op || !inode->i_op->default_file_ops->mmap))
 		return -ENOEXEC;
 	
diff -u --recursive --new-file v2.0.11/linux/fs/buffer.c linux/fs/buffer.c
--- v2.0.11/linux/fs/buffer.c	Tue Jun  4 16:41:44 1996
+++ linux/fs/buffer.c	Fri Aug  9 16:15:58 1996
@@ -1101,7 +1101,7 @@
 	if (clear_bit(PG_decr_after, &page->flags))
 		atomic_dec(&nr_async_pages);
 	if (clear_bit(PG_free_after, &page->flags))
-		free_page(page_address(page));
+		__free_page(page);
 	if (clear_bit(PG_swap_unlock_after, &page->flags))
 		swap_after_unlock_page(page->swap_unlock_entry);
 }
@@ -1322,11 +1322,10 @@
  */
 int generic_readpage(struct inode * inode, struct page * page)
 {
-	unsigned long block, address;
+	unsigned long block;
 	int *p, nr[PAGE_SIZE/512];
 	int i;
 
-	address = page_address(page);
 	page->count++;
 	set_bit(PG_locked, &page->flags);
 	set_bit(PG_free_after, &page->flags);
@@ -1342,7 +1341,7 @@
 	} while (i > 0);
 
 	/* IO start */
-	brw_page(READ, address, inode->i_dev, nr, inode->i_sb->s_blocksize, 1);
+	brw_page(READ, page_address(page), inode->i_dev, nr, inode->i_sb->s_blocksize, 1);
 	return 0;
 }
 
diff -u --recursive --new-file v2.0.11/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.0.11/linux/fs/proc/array.c	Mon Jun 10 08:14:28 1996
+++ linux/fs/proc/array.c	Tue Aug  6 13:00:12 1996
@@ -25,6 +25,9 @@
  *
  * Bruno Haible      :  remove 4K limit for the maps file
  * <haible@ma2s2.mathematik.uni-karlsruhe.de>
+ *
+ * Yves Arrouye      :  remove removal of trailing spaces in get_array.
+ *			<Yves.Arrouye@marin.fdn.fr>
  */
 
 #include <linux/types.h>
@@ -370,7 +373,7 @@
 	for (;;) {
 		addr = get_phys_addr(*p, start);
 		if (!addr)
-			goto ready;
+			return result;
 		do {
 			c = *(char *) addr;
 			if (!c)
@@ -378,17 +381,13 @@
 			if (size < PAGE_SIZE)
 				buffer[size++] = c;
 			else
-				goto ready;
+				return result;
 			addr++;
 			start++;
 			if (!c && start >= end)
-				goto ready;
+				return result;
 		} while (addr & ~PAGE_MASK);
 	}
-ready:
-	/* remove the trailing blanks, used to fill out argv,envp space */
-	while (result>0 && buffer[result-1]==' ')
-		result--;
 	return result;
 }
 
diff -u --recursive --new-file v2.0.11/linux/fs/super.c linux/fs/super.c
--- v2.0.11/linux/fs/super.c	Mon Aug  5 10:13:54 1996
+++ linux/fs/super.c	Tue Aug  6 09:10:48 1996
@@ -967,7 +967,7 @@
 #ifdef CONFIG_BLK_DEV_FD
 	if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
 		floppy_eject();
-#ifdef CONFIG_BLK_DEV_RAM
+#ifndef CONFIG_BLK_DEV_RAM
 		printk(KERN_NOTICE "(Warning, this kernel has no ramdisk support)\n");
 #endif
 		printk(KERN_NOTICE "VFS: Insert root floppy and press ENTER\n");
diff -u --recursive --new-file v2.0.11/linux/include/asm-alpha/elf.h linux/include/asm-alpha/elf.h
--- v2.0.11/linux/include/asm-alpha/elf.h	Mon Aug  5 10:13:54 1996
+++ linux/include/asm-alpha/elf.h	Fri Aug  9 10:44:54 1996
@@ -38,4 +38,15 @@
 	memcpy((char *) &_dest, (char *) &_dump.regs,	\
 	       sizeof(elf_gregset_t)); }
 
+/* $0 is set by ld.so to a pointer to a function which might be 
+   registered using atexit.  This provides a mean for the dynamic
+   linker to call DT_FINI functions for shared libraries that have
+   been loaded before the code runs.
+
+   So that we can use the same startup file with static executables,
+   we start programs with a value of 0 to indicate that there is no
+   such function.  */
+
+#define ELF_PLAT_INIT(_r)       _r->r0 = 0
+
 #endif
diff -u --recursive --new-file v2.0.11/linux/include/asm-m68k/elf.h linux/include/asm-m68k/elf.h
--- v2.0.11/linux/include/asm-m68k/elf.h	Mon Aug  5 10:13:54 1996
+++ linux/include/asm-m68k/elf.h	Thu Aug  8 12:25:46 1996
@@ -17,17 +17,46 @@
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x) ((x) == EM_M68K)
+#define elf_check_arch(x) ((x) == EM_68K)
 
 /*
  * These are used to set parameters in the core dumps.
- * FIXME(eric) I don't know what the correct endianness to use is.
  */
 #define ELF_CLASS	ELFCLASS32
 #define ELF_DATA	ELFDATA2MSB;
-#define ELF_ARCH	EM_M68K
+#define ELF_ARCH	EM_68K
+
+	/* For SVR4/m68k the function pointer to be registered with
+	   `atexit' is passed in %a1.  Although my copy of the ABI has
+	   no such statement, it is actually used on ASV.  */
+#define ELF_PLAT_INIT(_r)	_r->a1 = 0
 
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs)				\
+	/* Bleech. */							\
+	pr_reg[0] = regs->d1;						\
+	pr_reg[1] = regs->d2;						\
+	pr_reg[2] = regs->d3;						\
+	pr_reg[3] = regs->d4;						\
+	pr_reg[4] = regs->d5;						\
+	pr_reg[7] = regs->a0;						\
+	pr_reg[8] = regs->a1;						\
+	pr_reg[14] = regs->d0;						\
+	pr_reg[15] = rdusp();						\
+	pr_reg[16] = 0; /* orig_d0 */					\
+	pr_reg[17] = regs->sr;						\
+	pr_reg[18] = regs->pc;						\
+	{								\
+	  struct switch_stack *sw = ((struct switch_stack *)regs) - 1;	\
+	  pr_reg[5] = sw->d6;						\
+	  pr_reg[6] = sw->d7;						\
+	  pr_reg[9] = sw->a2;						\
+	  pr_reg[10] = sw->a3;						\
+	  pr_reg[11] = sw->a4;						\
+	  pr_reg[12] = sw->a5;						\
+	  pr_reg[13] = sw->a6;						\
+	}
 
 #endif
diff -u --recursive --new-file v2.0.11/linux/include/linux/ax25.h linux/include/linux/ax25.h
--- v2.0.11/linux/include/linux/ax25.h	Mon Apr  1 10:46:30 1996
+++ linux/include/linux/ax25.h	Wed Aug  7 08:41:57 1996
@@ -1,59 +1,14 @@
+/*
+ * These are the public elements of the Linux kernel AX.25 code. A similar
+ * file netrom.h exists for the NET/ROM protocol.
+ */
+ 
+#ifndef	AX25_KERNEL_H
+#define	AX25_KERNEL_H
+ 
 #define PF_AX25		AF_AX25
 #define AX25_MTU	256
-#define AX25_MAX_DIGIS	6
-
-typedef struct
-{
-	char ax25_call[7];	/* 6 call + SSID (shifted ascii!) */
-}
-ax25_address;
-
-struct sockaddr_ax25
-{
-	short sax25_family;
-	ax25_address sax25_call;
-	int sax25_ndigis;
-	/* Digipeater ax25_address sets follow */
-};
-
-#define sax25_uid	sax25_ndigis
-
-struct full_sockaddr_ax25
-{
-	struct sockaddr_ax25 fsa_ax25;
-	ax25_address fsa_digipeater[AX25_MAX_DIGIS];
-};
-
-struct ax25_routes_struct
-{
-	ax25_address port_addr;
-	ax25_address dest_addr;
-	unsigned char digi_count;
-	ax25_address digi_addr[AX25_MAX_DIGIS];
-};
-
-struct ax25_route_opt_struct
-{
-	ax25_address port_addr;
-	ax25_address dest_addr;
-	int cmd;
-	int arg;
-};
-
-struct ax25_ctl_struct
-{
-	ax25_address port_addr;
-	ax25_address source_addr;
-	ax25_address dest_addr;
-	unsigned int cmd;
-	unsigned long arg;
-};
-
-struct ax25_bpqaddr_struct
-{
-	char dev[16];
-	ax25_address addr;
-};
+#define AX25_MAX_DIGIS	6	/* This is wrong, should be 8 */
 
 #define AX25_WINDOW	1
 #define AX25_T1		2
@@ -79,16 +34,8 @@
 #define SIOCAX25OPTRT		(SIOCPROTOPRIVATE+7)
 #define SIOCAX25CTLCON		(SIOCPROTOPRIVATE+8)
 
-#define AX25_SET_RT_PERMANENT	1
 #define AX25_SET_RT_IPMODE	2
 
-#define AX25_RT_DYNAMIC		0
-#define AX25_RT_PERMANENT	1
-
-#define AX25_RT_IPMODE_DEFAULT	' '
-#define AX25_RT_IPMODE_DATAGRAM	'D'
-#define AX25_RT_IPMODE_VC	'V'
-
 #define AX25_NOUID_DEFAULT	0
 #define AX25_NOUID_BLOCK	1
 
@@ -113,8 +60,54 @@
 #define AX25_VALUES_IPMAXQUEUE  15	/* Maximum number of buffers enqueued */
 #define	AX25_MAX_VALUES		20
 
-struct ax25_parms_struct
-{
+typedef struct {
+	char ax25_call[7];	/* 6 call + SSID (shifted ascii!) */
+} ax25_address;
+
+struct sockaddr_ax25 {
+	short sax25_family;
+	ax25_address sax25_call;
+	int sax25_ndigis;
+	/* Digipeater ax25_address sets follow */
+};
+
+#define sax25_uid	sax25_ndigis
+
+struct full_sockaddr_ax25 {
+	struct sockaddr_ax25 fsa_ax25;
+	ax25_address fsa_digipeater[AX25_MAX_DIGIS];
+};
+
+struct ax25_routes_struct {
+	ax25_address port_addr;
+	ax25_address dest_addr;
+	unsigned char digi_count;
+	ax25_address digi_addr[AX25_MAX_DIGIS];
+};
+
+struct ax25_route_opt_struct {
+	ax25_address port_addr;
+	ax25_address dest_addr;
+	int cmd;
+	int arg;
+};
+
+struct ax25_ctl_struct {
+	ax25_address port_addr;
+	ax25_address source_addr;
+	ax25_address dest_addr;
+	unsigned int cmd;
+	unsigned long arg;
+};
+
+struct ax25_bpqaddr_struct {
+	char dev[16];
+	ax25_address addr;
+};
+
+struct ax25_parms_struct {
 	ax25_address port_addr;
 	unsigned short values[AX25_MAX_VALUES];
 };
+
+#endif
diff -u --recursive --new-file v2.0.11/linux/include/linux/elf.h linux/include/linux/elf.h
--- v2.0.11/linux/include/linux/elf.h	Mon Aug  5 10:13:54 1996
+++ linux/include/linux/elf.h	Wed Aug  7 10:08:46 1996
@@ -38,7 +38,6 @@
 #define EM_88K   5
 #define EM_486   6   /* Perhaps disused */
 #define EM_860   7
-#define EM_PPC   20
 
 #define EM_MIPS		8	/* MIPS R3000 (officially, big-endian only) */
 
diff -u --recursive --new-file v2.0.11/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.0.11/linux/include/linux/mm.h	Thu Jul 25 20:26:46 1996
+++ linux/include/linux/mm.h	Fri Aug  9 16:25:00 1996
@@ -116,6 +116,9 @@
  * is used for linear searches (eg. clock algorithm scans). 
  */
 typedef struct page {
+	/* these must be first (free area handling) */
+	struct page *next;
+	struct page *prev;
 	struct inode *inode;
 	unsigned long offset;
 	struct page *next_hash;
@@ -124,8 +127,6 @@
 	unsigned dirty:16,
 		 age:8;
 	struct wait_queue *wait;
-	struct page *next;
-	struct page *prev;
 	struct page *prev_hash;
 	struct buffer_head * buffers;
 	unsigned long swap_unlock_entry;
@@ -247,6 +248,7 @@
 
 #define free_page(addr) free_pages((addr),0)
 extern void free_pages(unsigned long addr, unsigned long order);
+extern void __free_page(struct page *);
 
 extern void show_free_areas(void);
 extern unsigned long put_dirty_page(struct task_struct * tsk,unsigned long page,
diff -u --recursive --new-file v2.0.11/linux/include/linux/netrom.h linux/include/linux/netrom.h
--- v2.0.11/linux/include/linux/netrom.h	Thu Apr 18 14:35:33 1996
+++ linux/include/linux/netrom.h	Wed Aug  7 08:41:57 1996
@@ -1,3 +1,12 @@
+/*
+ * These are the public elements of the Linux kernel NET/ROM implementation.
+ * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the
+ * definition of the ax25_address structure.
+ */
+ 
+#ifndef	NETROM_KERNEL_H
+#define	NETROM_KERNEL_H
+
 #define PF_NETROM	AF_NETROM
 #define NETROM_MTU	236
 
@@ -45,3 +54,5 @@
 	unsigned int  cmd;
 	unsigned long arg;
 };
+
+#endif
diff -u --recursive --new-file v2.0.11/linux/include/net/ax25.h linux/include/net/ax25.h
--- v2.0.11/linux/include/net/ax25.h	Thu Jul 25 20:28:50 1996
+++ linux/include/net/ax25.h	Fri Aug  9 16:27:06 1996
@@ -126,7 +126,7 @@
 #define	AX25_DEF_N2		10
 #define AX25_DEF_IDLE		20
 #define AX25_DEF_PACLEN		256
-#define AX25_DEF_IPMAXQUEUE	1		/* 1 * ax25->window */
+#define AX25_DEF_IPMAXQUEUE	2		/* 1 * ax25->window */
 #define	AX25_DEF_DIGI		(AX25_DIGI_INBAND|AX25_DIGI_XBAND)
 
 typedef struct ax25_uid_assoc {
@@ -203,15 +203,13 @@
 extern void dama_establish_data_link(ax25_cb *);
 
 /* ax25_route.c */
-extern void ax25_rt_rx_frame(ax25_address *, struct device *, ax25_digi *);
 extern int  ax25_rt_get_info(char *, char **, off_t, int, int);
 extern int  ax25_cs_get_info(char *, char **, off_t, int, int);
 extern int  ax25_rt_autobind(ax25_cb *, ax25_address *);
-extern void ax25_rt_build_path(ax25_cb *, ax25_address *);
+extern void ax25_rt_build_path(ax25_cb *, ax25_address *, struct device *);
 extern void ax25_dg_build_path(struct sk_buff *, ax25_address *, struct device *);
 extern void ax25_rt_device_down(struct device *);
 extern int  ax25_rt_ioctl(unsigned int, void *);
-extern void ax25_ip_mode_set(ax25_address *, struct device *, char);
 extern char ax25_ip_mode_get(ax25_address *, struct device *);
 extern unsigned short ax25_dev_get_value(struct device *, int);
 extern void ax25_dev_device_up(struct device *);
diff -u --recursive --new-file v2.0.11/linux/include/net/netrom.h linux/include/net/netrom.h
--- v2.0.11/linux/include/net/netrom.h	Thu Apr 18 14:35:33 1996
+++ linux/include/net/netrom.h	Wed Aug  7 08:41:57 1996
@@ -64,10 +64,21 @@
 	struct sock		*sk;		/* Backlink to socket */
 } nr_cb;
 
+struct nr_neigh {
+	struct nr_neigh *next;
+	ax25_address    callsign;
+	ax25_digi       *digipeat;
+	struct device   *dev;
+	unsigned char   quality;
+	unsigned char   locked;
+	unsigned short  count;
+	unsigned int    number;
+};
+
 struct nr_route {
-	unsigned char  quality;
-	unsigned char  obs_count;
-	unsigned short neighbour;
+	unsigned char   quality;
+	unsigned char   obs_count;
+	struct nr_neigh *neighbour;
 };
 
 struct nr_node {
@@ -77,17 +88,6 @@
 	unsigned char   which;
 	unsigned char   count;
 	struct nr_route routes[3];
-};
-
-struct nr_neigh {
-	struct nr_neigh *next;
-	ax25_address    callsign;
-	ax25_digi       *digipeat;
-	struct device   *dev;
-	unsigned char   quality;
-	unsigned char   locked;
-	unsigned short  count;
-	unsigned short  number;
 };
 
 /* af_netrom.c */
diff -u --recursive --new-file v2.0.11/linux/mm/filemap.c linux/mm/filemap.c
--- v2.0.11/linux/mm/filemap.c	Mon Aug  5 10:13:55 1996
+++ linux/mm/filemap.c	Fri Aug  9 14:55:35 1996
@@ -78,7 +78,7 @@
 		page->prev = NULL;
 		remove_page_from_hash_queue(page);
 		page->inode = NULL;
-		free_page(page_address(page));
+		__free_page(page);
 		continue;
 	}
 }
@@ -111,15 +111,16 @@
 			page->prev = NULL;
 			remove_page_from_hash_queue(page);
 			page->inode = NULL;
-			free_page(page_address(page));
+			__free_page(page);
 			continue;
 		}
 		p = &page->next;
 		offset = start - offset;
 		/* partial truncate, clear end of page */
 		if (offset < PAGE_SIZE) {
-			memset((void *) (offset + page_address(page)), 0, PAGE_SIZE - offset);
-			flush_page_to_ram(page_address(page));
+			unsigned long address = page_address(page);
+			memset((void *) (offset + address), 0, PAGE_SIZE - offset);
+			flush_page_to_ram(address);
 		}
 	}
 }
@@ -175,7 +176,7 @@
 				if (page->inode) {
 					remove_page_from_hash_queue(page);
 					remove_page_from_inode_queue(page);
-					free_page(page_address(page));
+					__free_page(page);
 					return 1;
 				}
 
diff -u --recursive --new-file v2.0.11/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.0.11/linux/mm/page_alloc.c	Mon Jun  3 12:27:05 1996
+++ linux/mm/page_alloc.c	Fri Aug  9 15:20:25 1996
@@ -36,30 +36,34 @@
 
 #define NR_MEM_LISTS 6
 
+/* The start of this MUST match the start of "struct page" */
 struct free_area_struct {
-	struct page list;
+	struct page *next;
+	struct page *prev;
 	unsigned int * map;
 };
 
+#define memory_head(x) ((struct page *)x)
+
 static struct free_area_struct free_area[NR_MEM_LISTS];
 
-static inline void init_mem_queue(struct page * head)
+static inline void init_mem_queue(struct free_area_struct * head)
 {
-	head->next = head;
-	head->prev = head;
+	head->next = memory_head(head);
+	head->prev = memory_head(head);
 }
 
-static inline void add_mem_queue(struct page * head, struct page * entry)
+static inline void add_mem_queue(struct free_area_struct * head, struct page * entry)
 {
 	struct page * next = head->next;
 
-	entry->prev = head;
+	entry->prev = memory_head(head);
 	entry->next = next;
 	next->prev = entry;
 	head->next = entry;
 }
 
-static inline void remove_mem_queue(struct page * head, struct page * entry)
+static inline void remove_mem_queue(struct page * entry)
 {
 	struct page * next = entry->next;
 	struct page * prev = entry->prev;
@@ -85,9 +89,12 @@
 
 /*
  * Buddy system. Hairy. You really aren't expected to understand this
+ *
+ * Hint: -mask = 1+~mask
  */
 static inline void free_pages_ok(unsigned long map_nr, unsigned long order)
 {
+	struct free_area_struct *area = free_area + order;
 	unsigned long index = map_nr >> (1 + order);
 	unsigned long mask = (~0UL) << order;
 	unsigned long flags;
@@ -98,23 +105,32 @@
 #define list(x) (mem_map+(x))
 
 	map_nr &= mask;
-	nr_free_pages += 1 << order;
-	while (order < NR_MEM_LISTS-1) {
-		if (!change_bit(index, free_area[order].map))
+	nr_free_pages -= mask;
+	while (mask + (1 << (NR_MEM_LISTS-1))) {
+		if (!change_bit(index, area->map))
 			break;
-		remove_mem_queue(&free_area[order].list, list(map_nr ^ (1+~mask)));
+		remove_mem_queue(list(map_nr ^ -mask));
 		mask <<= 1;
-		order++;
+		area++;
 		index >>= 1;
 		map_nr &= mask;
 	}
-	add_mem_queue(&free_area[order].list, list(map_nr));
+	add_mem_queue(area, list(map_nr));
 
 #undef list
 
 	restore_flags(flags);
 }
 
+void __free_page(struct page *page)
+{
+	if (!PageReserved(page) && atomic_dec_and_test(&page->count)) {
+		unsigned long map_nr = page->map_nr;
+		delete_from_swap_cache(map_nr);
+		free_pages_ok(map_nr, 0);
+	}
+}
+
 void free_pages(unsigned long addr, unsigned long order)
 {
 	unsigned long map_nr = MAP_NR(addr);
@@ -141,8 +157,8 @@
 #define RMQUEUE(order, dma) \
 do { struct free_area_struct * area = free_area+order; \
      unsigned long new_order = order; \
-	do { struct page *prev = &area->list, *ret; \
-		while (&area->list != (ret = prev->next)) { \
+	do { struct page *prev = memory_head(area), *ret; \
+		while (memory_head(area) != (ret = prev->next)) { \
 			if (!dma || CAN_DMA(ret)) { \
 				unsigned long map_nr = ret->map_nr; \
 				(prev->next = ret->next)->prev = prev; \
@@ -162,7 +178,7 @@
 do { unsigned long size = 1 << high; \
 	while (high > low) { \
 		area--; high--; size >>= 1; \
-		add_mem_queue(&area->list, map); \
+		add_mem_queue(area, map); \
 		MARK_USED(index, high, area); \
 		index += size; \
 		map += size; \
@@ -219,7 +235,7 @@
  	for (order=0 ; order < NR_MEM_LISTS; order++) {
 		struct page * tmp;
 		unsigned long nr = 0;
-		for (tmp = free_area[order].list.next ; tmp != &free_area[order].list ; tmp = tmp->next) {
+		for (tmp = free_area[order].next ; tmp != memory_head(free_area+order) ; tmp = tmp->next) {
 			nr ++;
 		}
 		total += nr * ((PAGE_SIZE>>10) << order);
@@ -269,7 +285,7 @@
 
 	for (i = 0 ; i < NR_MEM_LISTS ; i++) {
 		unsigned long bitmap_size;
-		init_mem_queue(&free_area[i].list);
+		init_mem_queue(free_area+i);
 		mask += mask;
 		end_mem = (end_mem + ~mask) & mask;
 		bitmap_size = (end_mem - PAGE_OFFSET) >> (PAGE_SHIFT + i);
diff -u --recursive --new-file v2.0.11/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.0.11/linux/net/ax25/af_ax25.c	Fri May 31 13:46:27 1996
+++ linux/net/ax25/af_ax25.c	Wed Aug  7 08:41:57 1996
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 031
+ *	AX.25 release 032
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -81,6 +81,7 @@
  *      AX.25 032	Joerg(DL1BKE)		Fixed DAMA timeout error.
  *						ax25_send_frame() limits the number of enqueued
  *						datagrams per socket.
+ *			Jonathan(G4KLX)		Remove auto-router.
  *
  *	To do:
  *		Restructure the ax25_rcv code to be cleaner/faster and
@@ -124,7 +125,7 @@
  *	The null address is defined as a callsign of all spaces with an
  *	SSID of zero.
  */
-ax25_address null_ax25_address = {{0x40,0x40,0x40,0x40,0x40,0x40,0x00}};
+ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}};
 
 ax25_cb *volatile ax25_list = NULL;
 
@@ -137,8 +138,7 @@
 	char c, *s;
 	int n;
 
-	for (n = 0, s = buf; n < 6; n++)
-	{
+	for (n = 0, s = buf; n < 6; n++) {
 		c = (a->ax25_call[n] >> 1) & 0x7F;
 
 		if (c != ' ') *s++ = c;
@@ -146,8 +146,7 @@
 	
 	*s++ = '-';
 
-	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9)
-	{
+	if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) {
 		*s++ = '1';
 		n -= 10;
 	}
@@ -492,6 +491,7 @@
 					return a->uid;
 			}
 			return -ENOENT;
+
 		case SIOCAX25ADDUID:
 			if(!suser())
 				return -EPERM;
@@ -505,8 +505,8 @@
 			a->next = ax25_uid_list;
 			ax25_uid_list = a;
 			return 0;
-		case SIOCAX25DELUID:
-		{
+
+		case SIOCAX25DELUID: {
 			ax25_uid_assoc **l;
 			
 			if(!suser())
@@ -524,6 +524,9 @@
 			}
 			return -ENOENT;
 		}
+		
+		default:
+			return -EINVAL;
 	}
 
 	return -EINVAL;	/*NOTREACHED */
@@ -673,7 +676,7 @@
 
 	init_timer(&ax25->timer);
 
-	ax25->dama_slave = 0;	/* dl1bke 951121 */
+	ax25->dama_slave = 0;
 
 	ax25->rtt     = (AX25_DEF_T1 * PR_SLOWHZ) / 2;
 	ax25->t1      = AX25_DEF_T1 * PR_SLOWHZ;
@@ -705,6 +708,7 @@
 	} else {
 		ax25->window = AX25_DEF_WINDOW;
 	}
+
 	ax25->device   = NULL;
 	ax25->digipeat = NULL;
 	ax25->sk       = NULL;
@@ -789,7 +793,7 @@
 			} else {
 				ax25_output(ax25, skb);
 			}
-			ax25->idletimer = ax25->idle;	/* dl1bke 960228 */
+			ax25->idletimer = ax25->idle;
 			return 1;		/* It already existed */
 		}
 	}
@@ -809,10 +813,10 @@
 		}
 		*ax25->digipeat = *digi;
 	} else {
-		ax25_rt_build_path(ax25, dest);
+		ax25_rt_build_path(ax25, dest, dev);
 	}
 
-	if (ax25_dev_is_dama_slave(ax25->device))	/* dl1bke 960116 */
+	if (ax25_dev_is_dama_slave(ax25->device))
 		dama_establish_data_link(ax25);
 	else
 		ax25_establish_data_link(ax25);
@@ -1208,7 +1212,6 @@
 			return NULL;
 		}
 		
-		/* dl1bke 960119: we have to copy the old digipeater list! */
 		*ax25->digipeat = *osk->ax25->digipeat;
 	}
 
@@ -1414,10 +1417,6 @@
 		}
 
 		sk->ax25->digipeat->lastrepeat = 0;
-	} else { /* dl1bke 960117 */
-		if (sk->debug)
-			printk("building digipeater path\n");
-		ax25_rt_build_path(sk->ax25, &addr->sax25_call);
 	}
 
 	/*
@@ -1548,7 +1547,6 @@
 static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
 	int *uaddr_len, int peer)
 {
-	ax25_address *addr;
 	struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
 	struct sock *sk;
 	unsigned char ndigi, i;
@@ -1558,25 +1556,30 @@
 	if (peer != 0) {
 		if (sk->state != TCP_ESTABLISHED)
 			return -ENOTCONN;
-		addr = &sk->ax25->dest_addr;
+
+		sax->fsa_ax25.sax25_family = AF_AX25;
+		sax->fsa_ax25.sax25_call   = sk->ax25->dest_addr;
+		sax->fsa_ax25.sax25_ndigis = 0;
+		*uaddr_len = sizeof(struct full_sockaddr_ax25);
+
+		if (sk->ax25->digipeat != NULL) {
+			ndigi = sk->ax25->digipeat->ndigi;
+			sax->fsa_ax25.sax25_ndigis = ndigi;
+			for (i = 0; i < ndigi; i++)
+				sax->fsa_digipeater[i] = sk->ax25->digipeat->calls[i];
+		}
 	} else {
-		addr = &sk->ax25->source_addr;
+		sax->fsa_ax25.sax25_family = AF_AX25;
+		sax->fsa_ax25.sax25_call   = sk->ax25->source_addr;
+		sax->fsa_ax25.sax25_ndigis = 1;
+		*uaddr_len = sizeof(struct full_sockaddr_ax25);
+
+		if (sk->ax25->device != NULL)
+			memcpy(&sax->fsa_digipeater[0], sk->ax25->device->dev_addr, AX25_ADDR_LEN);
+		else
+			sax->fsa_digipeater[0] = null_ax25_address;
 	}
 		
-	sax->fsa_ax25.sax25_family = AF_AX25;
-	sax->fsa_ax25.sax25_call   = *addr;
-	sax->fsa_ax25.sax25_ndigis = 0;
-	*uaddr_len = sizeof(struct sockaddr_ax25);
-
-	/* This will supply digipeat path on both getpeername() and getsockname() */
-	if (sk->ax25->digipeat != NULL) {
-		ndigi = sk->ax25->digipeat->ndigi;
-		sax->fsa_ax25.sax25_ndigis = ndigi;
-		*uaddr_len += AX25_ADDR_LEN * ndigi;
-		for (i = 0; i < ndigi; i++)
-			sax->fsa_digipeater[i] = sk->ax25->digipeat->calls[i];
-	}
-
 	return 0;
 }
  
@@ -1615,13 +1618,6 @@
 	}
 
 	/*
-	 *	Send the frame to the AX.25 auto-router
-	 */
-#ifdef notdef	/* dl1bke 960310 */
-	ax25_rt_rx_frame(&src, dev, &dp);
-#endif
-	
-	/*
 	 *	Ours perhaps ?
 	 */
 	if (dp.lastrepeat + 1 < dp.ndigi) {		/* Not yet digipeated completely */
@@ -1653,8 +1649,6 @@
 				return 0;
 			}
 
-			ax25_rt_rx_frame(&src, dev, &dp);
-
 			build_ax25_addr(skb->data, &src, &dest, &dp, type, MODULUS);
 #ifdef CONFIG_FIREWALL
 			if (call_fw_firewall(PF_AX25, skb->dev, skb->data, NULL) != FW_ACCEPT) {
@@ -1702,14 +1696,11 @@
 		switch (skb->data[1]) {
 #ifdef CONFIG_INET		
 			case AX25_P_IP:
-				ax25_rt_rx_frame(&src, dev, &dp);
 				skb_pull(skb,2);		/* drop PID/CTRL */
-				ax25_ip_mode_set(&src, dev, 'D');
 				ip_rcv(skb, dev, ptype);	/* Note ptype here is the wrong one, fix me later */
 				break;
 
 			case AX25_P_ARP:
-				ax25_rt_rx_frame(&src, dev, &dp);
 				skb_pull(skb,2);
 				arp_rcv(skb, dev, ptype);	/* Note ptype here is wrong... */
 				break;
@@ -1720,7 +1711,6 @@
 					if (sk->rmem_alloc >= sk->rcvbuf) {
 						kfree_skb(skb, FREE_READ);
 					} else {
-						ax25_rt_rx_frame(&src, dev, &dp);
 						/*
 						 *	Remove the control and PID.
 						 */
@@ -1764,7 +1754,6 @@
 		 *	free it immediately. This routine itself wakes the user context layers so we
 		 *	do no further work
 		 */
-		ax25_rt_rx_frame(&src, dev, &dp);
 		if (ax25_process_rx_frame(ax25, skb, type, dama) == 0)
 			kfree_skb(skb, FREE_READ);
 
@@ -1790,7 +1779,6 @@
 	/* b) received SABM(E) */
 	
 	if ((sk = ax25_find_listener(&dest, dev, SOCK_SEQPACKET)) != NULL) {
-		ax25_rt_rx_frame(&src, dev, &dp);
 		if (sk->ack_backlog == sk->max_ack_backlog || (make = ax25_make_new(sk, dev)) == NULL) {
 			if (mine)
 				ax25_return_dm(dev, &src, &dest, &dp);
@@ -1815,8 +1803,6 @@
 			return 0;
 		}
 		
-		ax25_rt_rx_frame(&src, dev, &dp);
-
 		if ((ax25 = ax25_create_cb()) == NULL) {
 			ax25_return_dm(dev, &src, &dest, &dp);
 			kfree_skb(skb, FREE_READ);
@@ -1826,10 +1812,8 @@
 		ax25_fillin_cb(ax25, dev);
 		ax25->idletimer = ax25->idle;
 #else
-		if (mine) {
-			ax25_rt_rx_frame(&src, dev, &dp);
+		if (mine)
 			ax25_return_dm(dev, &src, &dest, &dp);
-		}
 
 		kfree_skb(skb, FREE_READ);
 		return 0;
@@ -1882,7 +1866,7 @@
 
 	if (sk != NULL) {
 		if (!sk->dead)
-			sk->data_ready(sk, skb->len );
+			sk->data_ready(sk, skb->len);
 	} else {
 		kfree_skb(skb, FREE_READ);
 	}
@@ -1944,13 +1928,12 @@
 	ax25_digi *dp;
 	ax25_digi dtmp;
 	int lv;
-	int addr_len=msg->msg_namelen;
+	int addr_len = msg->msg_namelen;
 	
-	if (sk->err) {
+	if (sk->err)
 		return sock_error(sk);
-	}
 
-	if (flags|| msg->msg_control)
+	if (flags || msg->msg_control)
 		return -EINVAL;
 
 	if (sk->zapped)
@@ -2079,9 +2062,8 @@
 	int er;
 	int dama;
 
-	if (sk->err) {
+	if (sk->err)
 		return sock_error(sk);
-	}
 	
 	if (addr_len != NULL)
 		*addr_len = sizeof(*sax);
@@ -2176,8 +2158,7 @@
 			put_fs_long(amount, (unsigned long *)arg);
 			return 0;
 
-		case TIOCINQ:
-		{
+		case TIOCINQ: {
 			struct sk_buff *skb;
 			/* These two are safe on a single CPU system as only user tasks fiddle here */
 			if ((skb = skb_peek(&sk->receive_queue)) != NULL)
@@ -2201,8 +2182,7 @@
 
 		case SIOCAX25ADDUID:	/* Add a uid to the uid/call map table */
 		case SIOCAX25DELUID:	/* Delete a uid from the uid/call map table */
-		case SIOCAX25GETUID:
-		{
+		case SIOCAX25GETUID: {
 			struct sockaddr_ax25 sax25;
 			if ((err = verify_area(VERIFY_READ, (void *)arg, sizeof(struct sockaddr_ax25))) != 0)
 				return err;
@@ -2303,7 +2283,7 @@
 			ax25->window,
 			ax25->paclen);
 			
-		len += sprintf(buffer + len, " %s", ax25->dama_slave? " slave" : "    no");
+		len += sprintf(buffer + len, " %s", ax25->dama_slave ? " slave" : "    no");
 
 		if (ax25->sk != NULL) {
 			len += sprintf(buffer + len, " %5d %5d\n",
@@ -2434,7 +2414,6 @@
  *	A small shim to dev_queue_xmit to handle the difference between
  *	KISS AX.25 and BPQ AX.25.
  */
-
 void ax25_queue_xmit(struct sk_buff *skb, struct device *dev, int pri)
 {
 	unsigned char *ptr;
@@ -2449,8 +2428,8 @@
 	skb->protocol = htons (ETH_P_AX25);
 
 #ifdef CONFIG_BPQETHER
-	if(dev->type == ARPHRD_ETHER) {
-		static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+	if (dev->type == ARPHRD_ETHER) {
+		static char bcast_addr[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 		int size;
 
 		if(skb_headroom(skb) < AX25_BPQ_HEADER_LEN) {
@@ -2546,8 +2525,7 @@
 
 	if (bp[16] == AX25_P_IP) {
 		mode = ax25_ip_mode_get((ax25_address *)(bp + 1), dev);
-		if (mode == 'V' || mode == 'v' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) 
-		{
+		if (mode == 'V' || (mode == ' ' && ax25_dev_get_value(dev, AX25_VALUES_IPDEFMODE) == 'V')) {
 			/*
 			 *	This is a workaround to try to keep the device locking
 			 *	straight until skb->free=0 is abolished post 1.4.
@@ -2593,7 +2571,6 @@
   	 * dl1bke 960317: we use ax25_queue_xmit here to allow mode datagram
   	 *		  over ethernet. I don't know if this is valid, though.
   	 */
-
 	ax25_dg_build_path(skb, (ax25_address *)(bp + 1), dev);
 	ax25_queue_xmit(skb, dev, SOPRI_NORMAL);
 
diff -u --recursive --new-file v2.0.11/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.0.11/linux/net/ax25/ax25_in.c	Fri Apr 26 10:42:04 1996
+++ linux/net/ax25/ax25_in.c	Wed Aug  7 08:41:57 1996
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 031
+ *	AX.25 release 032
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -32,6 +32,8 @@
  *			Joerg(DL1BKE)   Renamed it to "IDLE" with a slightly
  *					different behaviour. Fixed defrag
  *					routine (I hope)
+ *	AX.25 032	Jonathan(G4KLX)	Remove auto-router.
+ *			Darryl(G7LED)	AX.25 segmentation fixed.
  */
 
 #include <linux/config.h>
@@ -70,66 +72,57 @@
 static int ax25_rx_fragment(ax25_cb *ax25, struct sk_buff *skb)
 {
 	struct sk_buff *skbn, *skbo;
-	int hdrlen;
+	int hdrlen, nhdrlen;
 	
 	if (ax25->fragno != 0) {
 		if (!(*skb->data & SEG_FIRST)) {
 			if ((ax25->fragno - 1) == (*skb->data & SEG_REM)) {
-			
-				/* enqueue fragment */
-				
+				/* Enqueue fragment */
 				ax25->fragno = *skb->data & SEG_REM;
 				skb_pull(skb, 1);	/* skip fragno */
 				ax25->fraglen += skb->len;
 				skb_queue_tail(&ax25->frag_queue, skb);
-				
-				/* last fragment received? */
 
+				/* Last fragment received ? */
 				if (ax25->fragno == 0) {
-					if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL)
-						return 0;
+					if ((skbn = alloc_skb(AX25_MAX_HEADER_LEN + ax25->fraglen, GFP_ATOMIC)) == NULL) {
+						while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+							kfree_skb(skbo, FREE_READ);
+						return 1;
+					}
 
 					skbn->free = 1;
 					skbn->arp  = 1;
-					skbn->dev  = skb->dev;
+					skbn->dev  = ax25->device;
 
 					if (ax25->sk != NULL) {
 						skbn->sk = ax25->sk;
 						atomic_add(skbn->truesize, &ax25->sk->rmem_alloc);
 					}
 
-					/* get first fragment from queue */
-					
-					skbo = skb_dequeue(&ax25->frag_queue);
-					hdrlen = skbo->data - skbo->h.raw - 2;	/* skip PID & fragno */
-					
-					skb_push(skbo, hdrlen + 2);		/* start of address field */
-					skbn->data = skb_put(skbn, hdrlen);	/* get space for info */
-					memcpy(skbn->data, skbo->data, hdrlen);	/* copy address field */
-					skb_pull(skbo, hdrlen + 2);		/* start of data */
-					skb_pull(skbn, hdrlen + 1);		/* ditto */
+					skb_reserve(skbn, AX25_MAX_HEADER_LEN);
 
-					/* copy data from first fragment */
+					/* Get first fragment from queue */
+					skbo = skb_dequeue(&ax25->frag_queue);
+					hdrlen  = skbo->data - skbo->h.raw;
+					nhdrlen = hdrlen - 2;
 
-					memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
-					kfree_skb(skbo, FREE_READ);
-					
-					/* add other fragment's data */
+					skb_push(skbo, hdrlen);
+					skb_push(skbn, nhdrlen);
+					skbn->h.raw = skbn->data;
+
+					/* Copy AX.25 headers */
+					memcpy(skbn->data, skbo->data, nhdrlen);
+					skb_pull(skbn, nhdrlen);
+					skb_pull(skbo, hdrlen);
 
-					while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL) {
+					/* Copy data from the fragments */
+					do {
 						memcpy(skb_put(skbn, skbo->len), skbo->data, skbo->len);
 						kfree_skb(skbo, FREE_READ);
-					}
+					} while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL);
 
-					ax25->fraglen = 0;		/* reset counter */
-					
-					/* 
-					 * mysteriously we need to re-adjust skb->data.
-					 * Anyway, it seems to work. Do we have the address fields
-					 * encoded TWICE in one sk_buff?
-					 */
-					
-					skb_pull(skbn, hdrlen);
+					ax25->fraglen = 0;
 
 					if (ax25_rx_iframe(ax25, skbn) == 0)
 						kfree_skb(skbn, FREE_READ);
@@ -139,9 +132,10 @@
 			}
 		}
 	} else {
-		/* first fragment received? */
-
+		/* First fragment received */
 		if (*skb->data & SEG_FIRST) {
+			while ((skbo = skb_dequeue(&ax25->frag_queue)) != NULL)
+				kfree_skb(skbo, FREE_READ);
 			ax25->fragno = *skb->data & SEG_REM;
 			skb_pull(skb, 1);		/* skip fragno */
 			ax25->fraglen = skb->len;
@@ -181,7 +175,6 @@
 		case AX25_P_IP:
 			skb_pull(skb, 1);	/* Remove PID */
 			skb->h.raw = skb->data;
-			ax25_ip_mode_set(&ax25->dest_addr, ax25->device, 'V');
 			ip_rcv(skb, ax25->device, NULL);	/* Wrong ptype */
 			queued = 1;
 			break;
@@ -273,7 +266,7 @@
 			break;
 
 		default:
-			if (dama && pf)	/* dl1bke 960116 */
+			if (dama && pf)
 				ax25_send_control(ax25, SABM, POLLON, C_COMMAND);
 			break;
 	}
@@ -490,7 +483,7 @@
 			}
 			if (ax25->condition & OWN_RX_BUSY_CONDITION) {
 				if (pf)	{
-					if (ax25->dama_slave)	/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_enquiry_response(ax25);
@@ -498,20 +491,21 @@
 				break;
 			}
 			if (ns == ax25->vr) {
+				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				queued = ax25_rx_iframe(ax25, skb);
 				if (ax25->condition & OWN_RX_BUSY_CONDITION) {
+					ax25->vr = ns;	/* ax25->vr - 1 */
 					if (pf) {
-						if (ax25->dama_slave)	/* dl1bke 960114 */
+						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
 							ax25_enquiry_response(ax25);
 					}
 					break;
 				}
-				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				ax25->condition &= ~REJECT_CONDITION;
 				if (pf) {
-					if (ax25->dama_slave)	/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_enquiry_response(ax25);
@@ -524,14 +518,14 @@
 			} else {
 				if (ax25->condition & REJECT_CONDITION) {
 					if (pf) {
-						if (ax25->dama_slave)	/* dl1bke 960114 */
+						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
 							ax25_enquiry_response(ax25);
 					}
 				} else {
 					ax25->condition |= REJECT_CONDITION;
-					if (ax25->dama_slave)		/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_send_control(ax25, REJ, pf, C_RESPONSE);
@@ -660,7 +654,7 @@
 			
 		case RR:
 			ax25->condition &= ~PEER_RX_BUSY_CONDITION;
-			if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+			if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
 				ax25->t1timer = 0;
 				if (ax25_validate_nr(ax25, nr)) {
 					ax25_frames_acked(ax25, nr);
@@ -691,7 +685,7 @@
 
 		case REJ:
 			ax25->condition &= ~PEER_RX_BUSY_CONDITION;
-			if ( pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND)) ) {
+			if (pf && (type == C_RESPONSE || (ax25->dama_slave && type == C_COMMAND))) {
 				ax25->t1timer = 0;
 				if (ax25_validate_nr(ax25, nr)) {
 					ax25_frames_acked(ax25, nr);
@@ -735,7 +729,7 @@
 			}
 			ax25_frames_acked(ax25, nr);
 			if (ax25->condition & OWN_RX_BUSY_CONDITION) {
-				if (pf) {	/* dl1bke 960114 */
+				if (pf) {
 					if (ax25->dama_slave)
 						ax25_enquiry_response(ax25);
 					else
@@ -744,9 +738,11 @@
 				break;
 			}
 			if (ns == ax25->vr) {
+				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				queued = ax25_rx_iframe(ax25, skb);
 				if (ax25->condition & OWN_RX_BUSY_CONDITION) {
-					if (pf) {	/* dl1bke 960114 */
+					ax25->vr = ns;	/* ax25->vr - 1 */
+					if (pf) {
 						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
@@ -754,10 +750,9 @@
 					}
 					break;
 				}
-				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				ax25->condition &= ~REJECT_CONDITION;
 				if (pf) {
-					if (ax25->dama_slave) 	/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_enquiry_response(ax25);
@@ -769,7 +764,7 @@
 				}
 			} else {
 				if (ax25->condition & REJECT_CONDITION) {
-					if (pf) { 	/* dl1bke 960114 */
+					if (pf) {
 						if (ax25->dama_slave)
 							dama_enquiry_response(ax25);
 						else
@@ -777,7 +772,7 @@
 					}
 				} else {
 					ax25->condition |= REJECT_CONDITION;
-					if (ax25->dama_slave)		/* dl1bke 960114 */
+					if (ax25->dama_slave)
 						dama_enquiry_response(ax25);
 					else
 						ax25_send_control(ax25, REJ, pf, C_RESPONSE);
diff -u --recursive --new-file v2.0.11/linux/net/ax25/ax25_out.c linux/net/ax25/ax25_out.c
--- v2.0.11/linux/net/ax25/ax25_out.c	Mon May 13 12:15:23 1996
+++ linux/net/ax25/ax25_out.c	Wed Aug  7 08:41:57 1996
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 031
+ *	AX.25 release 032
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -25,7 +25,6 @@
  *	AX.25 030	Jonathan(G4KLX)	Added fragmentation to ax25_output.
  *					Added support for extended AX.25.
  *	AX.25 031	Joerg(DL1BKE)	Added DAMA support
- *
  *			Joerg(DL1BKE)	Modified fragmenter to fragment vanilla 
  *					AX.25 I-Frames. Added PACLEN parameter.
  *			Joerg(DL1BKE)	Fixed a problem with buffer allocation
@@ -214,7 +213,7 @@
 		do {
 			if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 				skb_queue_head(&ax25->write_queue, skb);
-				return;
+				break;
 			}
 
 			next = (ax25->vs + 1) % ax25->modulus;
diff -u --recursive --new-file v2.0.11/linux/net/ax25/ax25_route.c linux/net/ax25/ax25_route.c
--- v2.0.11/linux/net/ax25/ax25_route.c	Mon May 13 12:15:23 1996
+++ linux/net/ax25/ax25_route.c	Wed Aug  7 08:41:57 1996
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 031
+ *	AX.25 release 032
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -37,6 +37,7 @@
  *			Joerg(DL1BKE)	Fixed AX.25 routing of IP datagram and VC, new ioctl()
  *					"SIOCAX25OPTRT" to set IP mode and a 'permanent' flag
  *					on routes.
+ *	AX.25 032	Jonathan(G4KLX)	Remove auto-router.
  */
  
 #include <linux/config.h>
@@ -63,17 +64,12 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 
-#define	AX25_ROUTE_MAX	128
-
 static struct ax25_route {
 	struct ax25_route *next;
 	ax25_address callsign;
 	struct device *dev;
 	ax25_digi *digipeat;
-	struct timeval stamp;
-	int n;
 	char ip_mode;
-	char perm;
 } *ax25_route = NULL;
 
 static struct ax25_dev {
@@ -82,120 +78,22 @@
 	unsigned short values[AX25_MAX_VALUES];
 } *ax25_device = NULL;
 
-static struct ax25_route * ax25_find_route(ax25_address *addr);
+static struct ax25_route *ax25_find_route(ax25_address *, struct device *);
 
 /*
  * small macro to drop non-digipeated digipeaters and reverse path
  */
- 
 static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out)
 {
 	int k;
+
 	for (k = 0; k < in->ndigi; k++)
 		if (!in->repeated[k])
 			break;
-	in->ndigi = k;
-	ax25_digi_invert(in, out);
-
-}
-
-/*
- * dl1bke 960310: new behaviour:
- *
- * * try to find an existing route to 'src', if found:
- *   - if the route was added manually don't adjust the timestamp
- *   - if this route is 'permanent' just do some statistics and return
- *   - overwrite device and digipeater path
- * * no existing route found:
- *   - try to alloc a new entry
- *   - overwrite the oldest, not manually added entry if this fails.
- *
- * * updated on reception of frames directed to us _only_
- *
- */
-
-void ax25_rt_rx_frame(ax25_address *src, struct device *dev, ax25_digi *digi)
-{
-	unsigned long flags;
-	extern struct timeval xtime;
-	struct ax25_route *ax25_rt;
-	struct ax25_route *oldest;
-	int count;
-
-	count  = 0;
-	oldest = NULL;
 
-	for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-		if (count == 0 || oldest->stamp.tv_sec == 0 || (ax25_rt->stamp.tv_sec != 0 && ax25_rt->stamp.tv_sec < oldest->stamp.tv_sec))
-			oldest = ax25_rt;
-		
-		if (ax25cmp(&ax25_rt->callsign, src) == 0) {
-			if (ax25_rt->stamp.tv_sec != 0)
-				ax25_rt->stamp = xtime;
-
-			if (ax25_rt->perm == AX25_RT_PERMANENT) {
-				ax25_rt->n++;
-				return;
-			}
-			
-			ax25_rt->dev = dev;
-			if (digi == NULL) {
-				/* drop old digipeater list */
-				if (ax25_rt->digipeat != NULL) {
-					kfree_s(ax25_rt->digipeat, sizeof(ax25_digi));
-					ax25_rt->digipeat = NULL;
-				}
-				return;
-			}
-			
-			if (ax25_rt->digipeat == NULL && (ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
-					return;
-			
-			ax25_route_invert(digi, ax25_rt->digipeat);
-			return;
-		}
-
-		count++;
-	}
-
-	if (count > AX25_ROUTE_MAX) {
-		if (oldest->stamp.tv_sec == 0)
-			return;
-		if (oldest->digipeat != NULL)
-			kfree_s(oldest->digipeat, sizeof(ax25_digi));
-		ax25_rt = oldest;
-	} else {
-		if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL)
-			return;		/* No space */
-	}
-	
-	ax25_rt->callsign = *src;
-	ax25_rt->dev      = dev;
-	ax25_rt->digipeat = NULL;
-	ax25_rt->stamp    = xtime;
-	ax25_rt->n        = 1;
-	ax25_rt->ip_mode  = ' ';
-	ax25_rt->perm	  = AX25_RT_DYNAMIC;
-
-	if (digi != NULL) {
-		if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
-			kfree_s(ax25_rt, sizeof(struct ax25_route));
-			return;
-		}
-		
-		ax25_route_invert(digi, ax25_rt->digipeat);
-		/* used to be: *ax25_rt->digipeat = *digi; */
-	}
-
-	if (ax25_rt != oldest) {
-		save_flags(flags);
-		cli();
-
-		ax25_rt->next = ax25_route;
-		ax25_route    = ax25_rt;
+	in->ndigi = k;
 
-		restore_flags(flags);
-	}
+	ax25_digi_invert(in, out);
 }
 
 void ax25_rt_device_down(struct device *dev)
@@ -261,7 +159,6 @@
 							ax25_rt->digipeat->calls[i]    = route.digi_addr[i];
 						}
 					}
-					ax25_rt->stamp.tv_sec = 0;
 					return 0;
 				}
 			}
@@ -270,10 +167,7 @@
 			ax25_rt->callsign     = route.dest_addr;
 			ax25_rt->dev          = dev;
 			ax25_rt->digipeat     = NULL;
-			ax25_rt->stamp.tv_sec = 0;
-			ax25_rt->n            = 0;
 			ax25_rt->ip_mode      = ' ';
-			ax25_rt->perm	      = AX25_RT_DYNAMIC;
 			if (route.digi_count != 0) {
 				if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
 					kfree_s(ax25_rt, sizeof(struct ax25_route));
@@ -323,40 +217,36 @@
 				}
 			}
 			break;
+
 		case SIOCAX25OPTRT:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(rt_option))) != 0)
 				return err;
 			memcpy_fromfs(&rt_option, arg, sizeof(rt_option));
 			if ((dev = ax25rtr_get_dev(&rt_option.port_addr)) == NULL)
 				return -EINVAL;
-			ax25_rt = ax25_route;
-			while (ax25_rt != NULL) {
+			for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
 				if (ax25_rt->dev == dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) {
-					switch(rt_option.cmd) {
-						case AX25_SET_RT_PERMANENT:
-							ax25_rt->perm = (char) rt_option.arg;
-							ax25_rt->stamp.tv_sec = 0;
-							break;
+					switch (rt_option.cmd) {
 						case AX25_SET_RT_IPMODE:
 							switch (rt_option.arg) {
-								case AX25_RT_IPMODE_DEFAULT:
-									ax25_rt->ip_mode = ' ';
-									break;
-								case AX25_RT_IPMODE_DATAGRAM:
-									ax25_rt->ip_mode = 'D';
-									break;
-								case AX25_RT_IPMODE_VC:
-									ax25_rt->ip_mode = 'V';
+								case ' ':
+								case 'D':
+								case 'V':
+									ax25_rt->ip_mode = rt_option.arg;
 									break;
 								default:
 									return -EINVAL;
 							}
 							break;
+						default:
+							return -EINVAL;
 					}
 				}
-				ax25_rt = ax25_rt->next;
 			}
 			break;
+
+		default:
+			return -EINVAL;
 	}
 
 	return 0;
@@ -373,26 +263,22 @@
   
 	cli();
 
-	len += sprintf(buffer, "callsign  dev  count time      mode F digipeaters\n");
+	len += sprintf(buffer, "callsign  dev  mode digipeaters\n");
 
 	for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
 		if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
 			callsign = "default";
 		else
 			callsign = ax2asc(&ax25_rt->callsign);
-		len += sprintf(buffer + len, "%-9s %-4s %5d %9d",
+		len += sprintf(buffer + len, "%-9s %-4s",
 			callsign,
-			ax25_rt->dev ? ax25_rt->dev->name : "???",
-			ax25_rt->n,
-			ax25_rt->stamp.tv_sec);
+			ax25_rt->dev ? ax25_rt->dev->name : "???");
 
 		switch (ax25_rt->ip_mode) {
 			case 'V':
-			case 'v':
 				len += sprintf(buffer + len, "   vc");
 				break;
 			case 'D':
-			case 'd':
 				len += sprintf(buffer + len, "   dg");
 				break;
 			default:
@@ -400,20 +286,6 @@
 				break;
 		}
 		
-		switch (ax25_rt->perm) {
-			case AX25_RT_DYNAMIC:
-				if (ax25_rt->stamp.tv_sec == 0)
-					len += sprintf(buffer + len, " M");
-				else
-					len += sprintf(buffer + len, "  ");
-				break;
-			case AX25_RT_PERMANENT:
-				len += sprintf(buffer + len, " P");
-				break;
-			default:
-				len += sprintf(buffer + len, " ?");
-		}
-
 		if (ax25_rt->digipeat != NULL)
 			for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
 				len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i]));
@@ -479,8 +351,7 @@
 /*
  *	Find AX.25 route
  */
- 
-static struct ax25_route * ax25_find_route(ax25_address *addr)
+static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev)
 {
 	struct ax25_route *ax25_spe_rt = NULL;
 	struct ax25_route *ax25_def_rt = NULL;
@@ -491,10 +362,17 @@
 	 *	route if none is found;
 	 */
 	for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-		if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
-			ax25_spe_rt = ax25_rt;
-		if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
-			ax25_def_rt = ax25_rt;
+		if (dev == NULL) {
+			if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
+				ax25_spe_rt = ax25_rt;
+			if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
+				ax25_def_rt = ax25_rt;
+		} else {
+			if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev)
+				ax25_spe_rt = ax25_rt;
+			if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev)
+				ax25_def_rt = ax25_rt;
+		}
 	}
 
 	if (ax25_spe_rt != NULL)
@@ -508,7 +386,6 @@
  *      a target on the digipeater path but w/o having a special route
  *	set before, the path has to be truncated from your target on.
  */
- 
 static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
 {
 	int k;
@@ -530,14 +407,14 @@
 	struct ax25_route *ax25_rt;
 	ax25_address *call;
 
-	if ((ax25_rt = ax25_find_route(addr)) == NULL)
+	if ((ax25_rt = ax25_find_route(addr, NULL)) == NULL)
 		return -EHOSTUNREACH;
 		
+	ax25->device = ax25_rt->dev;
+
 	if ((call = ax25_findbyuid(current->euid)) == NULL) {
 		if (ax25_uid_policy && !suser())
 			return -EPERM;
-		if (ax25->device == NULL)
-			return -ENODEV;
 		call = (ax25_address *)ax25->device->dev_addr;
 	}
 
@@ -560,19 +437,20 @@
  *	dl1bke 960117: build digipeater path
  *	dl1bke 960301: use the default route if it exists
  */
-void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr)
+void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr, struct device *dev)
 {
 	struct ax25_route *ax25_rt;
 	
-	ax25_rt = ax25_find_route(addr);
+	if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
+		return;
 	
-	if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
+	if (ax25_rt->digipeat == NULL)
 		return;
 
 	if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL)
 		return;
 
-	ax25->device = ax25_rt->dev;
+	ax25->device    = ax25_rt->dev;
 	*ax25->digipeat = *ax25_rt->digipeat;
 	ax25_adjust_path(addr, ax25->digipeat);
 }
@@ -587,8 +465,10 @@
 
 	skb_pull(skb, 1);	/* skip KISS command */
 
-	ax25_rt = ax25_find_route(addr);
-	if (ax25_rt == NULL || ax25_rt->digipeat == NULL)
+	if ((ax25_rt = ax25_find_route(addr, dev)) == NULL)
+		return;
+
+	if (ax25_rt->digipeat == NULL)
 		return;
 		
 	digipeat = *ax25_rt->digipeat;
@@ -611,22 +491,6 @@
 }
 
 /*
- *	Register the mode of an incoming IP frame. It is assumed that an entry
- *	already exists in the routing table.
- */
-void ax25_ip_mode_set(ax25_address *callsign, struct device *dev, char ip_mode)
-{
-	struct ax25_route *ax25_rt;
-
-	for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
-		if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev) {
-			ax25_rt->ip_mode = ip_mode;
-			return;
-		}
-	}
-}
-
-/*
  *	Return the IP mode of a given callsign/device pair.
  */
 char ax25_ip_mode_get(ax25_address *callsign, struct device *dev)
@@ -908,6 +772,9 @@
 			ax25_bpqdev  = bpqdev;
 			restore_flags(flags);
 			break;
+			
+		default:
+			return -EINVAL;
 	}
 
 	return 0;
diff -u --recursive --new-file v2.0.11/linux/net/ax25/ax25_subr.c linux/net/ax25/ax25_subr.c
--- v2.0.11/linux/net/ax25/ax25_subr.c	Mon May  6 12:26:17 1996
+++ linux/net/ax25/ax25_subr.c	Wed Aug  7 08:41:57 1996
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 031
+ *	AX.25 release 032
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -101,7 +101,7 @@
 			skb->free = 1;
 			kfree_skb(skb, FREE_WRITE);
 			ax25->va = (ax25->va + 1) % ax25->modulus;
-			if (ax25->dama_slave)		/* dl1bke 960120 */
+			if (ax25->dama_slave)
 				ax25->n2count = 0;
 		}
 	}
diff -u --recursive --new-file v2.0.11/linux/net/ax25/ax25_timer.c linux/net/ax25/ax25_timer.c
--- v2.0.11/linux/net/ax25/ax25_timer.c	Fri Apr 26 10:42:04 1996
+++ linux/net/ax25/ax25_timer.c	Wed Aug  7 08:41:57 1996
@@ -1,5 +1,5 @@
 /*
- *	AX.25 release 031
+ *	AX.25 release 032
  *
  *	This is ALPHA test software. This code may break your machine, randomly fail to work with new 
  *	releases, misbehave and/or generally screw up. It might even work. 
@@ -113,7 +113,7 @@
 			if (ax25->sk != NULL) {
 				if (ax25->sk->rmem_alloc < (ax25->sk->rcvbuf / 2) && (ax25->condition & OWN_RX_BUSY_CONDITION)) {
 					ax25->condition &= ~OWN_RX_BUSY_CONDITION;
-					if (!ax25->dama_slave) /* dl1bke */
+					if (!ax25->dama_slave)
 						ax25_send_control(ax25, RR, POLLOFF, C_RESPONSE);
 					ax25->condition &= ~ACK_PENDING_CONDITION;
 					break;
@@ -123,7 +123,7 @@
 			 * Check for frames to transmit.
 			 */
 			if (!ax25->dama_slave)
-				ax25_kick(ax25);	/* dl1bke 960114 */
+				ax25_kick(ax25);
 			break;
 
 		default:
@@ -134,7 +134,7 @@
 		if (ax25->state == AX25_STATE_3 || ax25->state == AX25_STATE_4) {
 			if (ax25->condition & ACK_PENDING_CONDITION) {
 				ax25->condition &= ~ACK_PENDING_CONDITION;
-				if (!ax25->dama_slave)			/* dl1bke 960114 */
+				if (!ax25->dama_slave)
 					ax25_timeout_response(ax25);
 			}
 		}
@@ -272,7 +272,7 @@
 #endif
 				ax25_clear_queues(ax25);
 				ax25->state = AX25_STATE_0;
-				ax25_send_control(ax25, DISC, POLLON, C_COMMAND); /* dl1bke */
+				ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
 				
 				if (ax25->sk != NULL) {
 					ax25->sk->state = TCP_CLOSE;
@@ -283,14 +283,14 @@
 				}
 			} else {
 				ax25->n2count++;
-				if (!ax25_dev_is_dama_slave(ax25->device))	/* dl1bke */
+				if (!ax25_dev_is_dama_slave(ax25->device))
 					ax25_send_control(ax25, DISC, POLLON, C_COMMAND);
 			}
 			break;
 
 		case AX25_STATE_3: 
 			ax25->n2count = 1;
-			if (!ax25->dama_slave)			/* dl1bke 960114 */
+			if (!ax25->dama_slave)
 				ax25_transmit_enquiry(ax25);
 			ax25->state   = AX25_STATE_4;
 			break;
@@ -314,7 +314,7 @@
 				}
 			} else {
 				ax25->n2count++;
-				if (!ax25->dama_slave)		/* dl1bke 960114 */
+				if (!ax25->dama_slave)
 					ax25_transmit_enquiry(ax25);
 			}
 			break;
diff -u --recursive --new-file v2.0.11/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- v2.0.11/linux/net/ipv4/ip_forward.c	Fri Jul 19 19:48:43 1996
+++ linux/net/ipv4/ip_forward.c	Wed Aug  7 13:59:29 1996
@@ -315,7 +315,7 @@
 #endif
 		IS_SKB(skb);
 
-		if (skb->len+encap > dev2->mtu && (ntohs(iph->frag_off) & IP_DF)) 
+		if (skb->len+encap > dev2->mtu && (iph->frag_off & htons(IP_DF))) 
 		{
 			ip_statistics.IpFragFails++;
 			icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(dev2->mtu), dev);
diff -u --recursive --new-file v2.0.11/linux/net/ipv4/ip_fragment.c linux/net/ipv4/ip_fragment.c
--- v2.0.11/linux/net/ipv4/ip_fragment.c	Sat Jul 20 08:58:28 1996
+++ linux/net/ipv4/ip_fragment.c	Wed Aug  7 14:00:08 1996
@@ -645,7 +645,7 @@
 	 *	Check for any "DF" flag. [DF means do not fragment]
 	 */
 
-	if (ntohs(iph->frag_off) & IP_DF)
+	if (iph->frag_off & htons(IP_DF))
 	{
 		ip_statistics.IpFragFails++;
 		NETDEBUG(printk("ip_queue_xmit: frag needed\n"));
diff -u --recursive --new-file v2.0.11/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.0.11/linux/net/ipv4/tcp_output.c	Mon Aug  5 10:13:56 1996
+++ linux/net/ipv4/tcp_output.c	Wed Aug  7 09:37:34 1996
@@ -279,7 +279,7 @@
 	/*
 	 *	Wait up to 1 second for the buffer to fill.
 	 */
-	sk->partial_timer.expires = jiffies+HZ;
+	sk->partial_timer.expires = jiffies+HZ/10;
 	sk->partial_timer.function = (void (*)(unsigned long)) tcp_send_partial;
 	sk->partial_timer.data = (unsigned long) sk;
 	add_timer(&sk->partial_timer);
@@ -966,6 +966,10 @@
 		sock_wfree(sk, buff);
 		return;
 	}
+#ifndef CONFIG_NO_PATH_MTU_DISCOVERY
+	buff->ip_hdr->frag_off |= htons(IP_DF);
+#endif
+
 	t1 =(struct tcphdr *)skb_put(buff,sizeof(struct tcphdr));
 
   	/*
diff -u --recursive --new-file v2.0.11/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.0.11/linux/net/netrom/af_netrom.c	Fri May 31 13:46:27 1996
+++ linux/net/netrom/af_netrom.c	Wed Aug  7 08:41:57 1996
@@ -934,7 +934,7 @@
 		sax->fsa_ax25.sax25_ndigis = 1;
 		sax->fsa_ax25.sax25_call = sk->nr->user_addr;
 		sax->fsa_digipeater[0]   = sk->nr->dest_addr;
-		*uaddr_len = sizeof(struct sockaddr_ax25) + AX25_ADDR_LEN;
+		*uaddr_len = sizeof(struct full_sockaddr_ax25);
 	} else {
 		sax->fsa_ax25.sax25_family = AF_NETROM;
 		sax->fsa_ax25.sax25_ndigis = 0;
@@ -952,14 +952,13 @@
 	ax25_address *src, *dest, *user;
 	unsigned short circuit_index, circuit_id;
 	unsigned short frametype, window, timeout;
-	
 
 	skb->sk = NULL;		/* Initially we don't know who it's for */
 
 	/*
 	 *	skb->data points to the netrom frame start
 	 */
-	
+
 	src  = (ax25_address *)(skb->data + 0);
 	dest = (ax25_address *)(skb->data + 7);
 
@@ -1327,7 +1326,7 @@
   
 	cli();
 
-	len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st vs vr va    t1     t2    n2  rtt wnd paclen Snd-Q Rcv-Q\n");
+	len += sprintf(buffer, "user_addr dest_node src_node  dev    my  your  st  vs  vr  va    t1     t2    n2  rtt wnd paclen Snd-Q Rcv-Q\n");
 
 	for (s = nr_list; s != NULL; s = s->next) {
 		if ((dev = s->nr->device) == NULL)
@@ -1339,7 +1338,7 @@
 			ax2asc(&s->nr->user_addr));
 		len += sprintf(buffer + len, "%-9s ",
 			ax2asc(&s->nr->dest_addr));
-		len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %2d %2d %2d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
+		len += sprintf(buffer + len, "%-9s %-3s  %02X/%02X %02X/%02X %2d %3d %3d %3d %3d/%03d %2d/%02d %2d/%02d %3d %3d %6d %5d %5d\n",
 			ax2asc(&s->nr->source_addr),
 			devname, s->nr->my_index, s->nr->my_id,
 			s->nr->your_index, s->nr->your_id,
diff -u --recursive --new-file v2.0.11/linux/net/netrom/nr_out.c linux/net/netrom/nr_out.c
--- v2.0.11/linux/net/netrom/nr_out.c	Thu Apr 18 14:35:34 1996
+++ linux/net/netrom/nr_out.c	Wed Aug  7 08:41:57 1996
@@ -168,7 +168,7 @@
 		do {
 			if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) {
 				skb_queue_head(&sk->write_queue, skb);
-				return;
+				break;
 			}
 
 			next = (sk->nr->vs + 1) % NR_MODULUS;
diff -u --recursive --new-file v2.0.11/linux/net/netrom/nr_route.c linux/net/netrom/nr_route.c
--- v2.0.11/linux/net/netrom/nr_route.c	Sun May 19 23:40:51 1996
+++ linux/net/netrom/nr_route.c	Wed Aug  7 08:41:57 1996
@@ -16,13 +16,10 @@
  *	NET/ROM 001	Jonathan(G4KLX)	First attempt.
  *	NET/ROM	003	Jonathan(G4KLX)	Use SIOCADDRT/SIOCDELRT ioctl values
  *					for NET/ROM routes.
+ *					Use '*' for a blank mnemonic in /proc/net/nr_nodes.
+ *					Change default quality for new neighbour when same
+ *					as node callsign.
  *			Alan Cox(GW4PTS) Added the firewall hooks.
- *
- *	TO DO
- *	Sort out the which pointer when shuffling entries in the routes
- *	section. Also reset the which pointer when a route becomes "good"
- *	again, ie when a NODES broadcast is processed via calls to
- *	nr_add_node().
  */
  
 #include <linux/config.h>
@@ -54,12 +51,14 @@
 #include <linux/firewall.h>
 #include <net/netrom.h>
 
-static int nr_neigh_no = 1;
+static unsigned int nr_neigh_no = 1;
 static int nr_route_on = 1;
 
 static struct nr_node  *nr_node_list  = NULL;
 static struct nr_neigh *nr_neigh_list = NULL;
 
+static void nr_remove_neigh(struct nr_neigh *);
+
 /*
  *	Add a new route to a node, and in the process add the node and the
  *	neighbour if it is new.
@@ -72,7 +71,10 @@
 	struct nr_route nr_route;
 	unsigned long flags;
 	int i, found;
-	
+
+	if (nr_dev_get(nr) != NULL)	/* Can't add routes to ourself */
+		return -EINVAL;
+
 	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
 		if (ax25cmp(nr, &nr_node->callsign) == 0)
 			break;
@@ -91,7 +93,10 @@
 		nr_neigh->callsign = *ax25;
 		nr_neigh->digipeat = NULL;
 		nr_neigh->dev      = dev;
-		nr_neigh->quality  = nr_default.quality;
+		if (ax25cmp(nr, ax25) == 0)
+			nr_neigh->quality = quality;
+		else
+			nr_neigh->quality = nr_default.quality;
 		nr_neigh->locked   = 0;
 		nr_neigh->count    = 0;
 		nr_neigh->number   = nr_neigh_no++;
@@ -118,14 +123,14 @@
 			return -ENOMEM;
 
 		nr_node->callsign = *nr;
-		memcpy(&nr_node->mnemonic, mnemonic, sizeof(nr_node->mnemonic));
+		strcpy(nr_node->mnemonic, mnemonic);
 
 		nr_node->which = 0;
 		nr_node->count = 1;
 
 		nr_node->routes[0].quality   = quality;
 		nr_node->routes[0].obs_count = obs_count;
-		nr_node->routes[0].neighbour = nr_neigh->number;
+		nr_node->routes[0].neighbour = nr_neigh;
 			
 		save_flags(flags);
 		cli();
@@ -138,10 +143,13 @@
 		nr_neigh->count++;
 
 		return 0;
+	} else {
+		if (nr_node->mnemonic[0] == '\0')
+			strcpy(nr_node->mnemonic, mnemonic);
 	}
 
 	for (found = 0, i = 0; i < nr_node->count; i++) {
-		if (nr_node->routes[i].neighbour == nr_neigh->number) {
+		if (nr_node->routes[i].neighbour == nr_neigh) {
 			nr_node->routes[i].quality   = quality;
 			nr_node->routes[i].obs_count = obs_count;
 			found = 1;
@@ -157,16 +165,22 @@
 
 			nr_node->routes[0].quality   = quality;
 			nr_node->routes[0].obs_count = obs_count;
-			nr_node->routes[0].neighbour = nr_neigh->number;
+			nr_node->routes[0].neighbour = nr_neigh;
 				
+			nr_node->which++;
 			nr_node->count++;
 			nr_neigh->count++;
 		} else {
 			/* It must be better than the worst */
 			if (quality > nr_node->routes[2].quality) {
+				nr_node->routes[2].neighbour->count--;
+				
+				if (nr_node->routes[2].neighbour->count == 0 && !nr_node->routes[2].neighbour->locked)
+					nr_remove_neigh(nr_node->routes[2].neighbour);
+			
 				nr_node->routes[2].quality   = quality;
 				nr_node->routes[2].obs_count = obs_count;
-				nr_node->routes[2].neighbour = nr_neigh->number;
+				nr_node->routes[2].neighbour = nr_neigh;
 
 				nr_neigh->count++;
 			}
@@ -212,7 +226,7 @@
 	}
 
 	for (i = 0; i < nr_node->count; i++) {
-		if (nr_node->routes[i].neighbour == nr_neigh->number) {
+		if (nr_node->routes[i].neighbour == nr_neigh) {
 			if (i < nr_node->which)
 				nr_node->which = i;
 			break;
@@ -307,7 +321,7 @@
 	if (nr_neigh == NULL) return -EINVAL;
 	
 	for (i = 0; i < nr_node->count; i++) {
-		if (nr_node->routes[i].neighbour == nr_neigh->number) {
+		if (nr_node->routes[i].neighbour == nr_neigh) {
 			nr_neigh->count--;
 
 			if (nr_neigh->count == 0 && !nr_neigh->locked)
@@ -403,7 +417,7 @@
  */
 static int nr_dec_obs(void)
 {
-	struct nr_neigh *t, *nr_neigh;
+	struct nr_neigh *nr_neigh;
 	struct nr_node  *s, *nr_node;
 	int i;
 
@@ -420,21 +434,12 @@
 				break;
 
 			case 1:		/* From 1 -> 0 */
-				nr_neigh = nr_neigh_list;
-
-				while (nr_neigh != NULL) {
-					t        = nr_neigh;
-					nr_neigh = nr_neigh->next;
-
-					if (t->number == s->routes[i].neighbour) {
-						t->count--;
+				nr_neigh = s->routes[i].neighbour;
+				
+				nr_neigh->count--;
 						
-						if (t->count == 0 && !t->locked)
-							nr_remove_neigh(t);
-
-						break;
-					}
-				}
+				if (nr_neigh->count == 0 && !nr_neigh->locked)
+					nr_remove_neigh(nr_neigh);
 
 				s->count--;
 
@@ -483,7 +488,7 @@
 				nr_node = nr_node->next;
 				
 				for (i = 0; i < t->count; i++) {
-					if (t->routes[i].neighbour == s->number) {
+					if (t->routes[i].neighbour == s) {
 						t->count--;
 
 						switch (i) {
@@ -609,13 +614,16 @@
 
 		case SIOCNRDECOBS:
 			return nr_dec_obs();
-			
+
 		case SIOCNRRTCTL:
 			if ((err = verify_area(VERIFY_READ, arg, sizeof(int))) != 0)
 				return err;
 			opt = get_fs_long((void *)arg);
 			nr_route_on = opt ? 1 : 0;
 			return 0;
+
+		default:
+			return -EINVAL;
 	}
 
 	return 0;
@@ -637,7 +645,7 @@
 	if (nr_neigh == NULL) return;
 	
 	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next)
-		if (nr_node->which >= nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh->number)
+		if (nr_node->which < nr_node->count && nr_node->routes[nr_node->which].neighbour == nr_neigh)
 			nr_node->which++;
 }
 
@@ -645,7 +653,6 @@
  *	Route a frame to an appropriate AX.25 connection. A NULL ax25_cb
  *	indicates an internally generated frame.
  */
-
 int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 {
 	ax25_address *nr_src, *nr_dest;
@@ -655,12 +662,12 @@
 	unsigned char *dptr;
 	
 #ifdef CONFIG_FIREWALL
-
-	if(ax25 && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+	if (ax25 != NULL && call_in_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
 		return 0;
-	if(!ax25 && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+	if (ax25 == NULL && call_out_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
 		return 0;
 #endif
+
 	nr_src  = (ax25_address *)(skb->data + 0);
 	nr_dest = (ax25_address *)(skb->data + 7);
 
@@ -684,27 +691,20 @@
 	if (nr_node == NULL || nr_node->which >= nr_node->count)
 		return 0;
 
-	for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)
-		if (nr_neigh->number == nr_node->routes[nr_node->which].neighbour)
-			break;
-			
-	if (nr_neigh == NULL)
-		return 0;
+	nr_neigh = nr_node->routes[nr_node->which].neighbour;
 
 	if ((dev = nr_dev_first()) == NULL)
 		return 0;
 
 #ifdef CONFIG_FIREWALL
-	if(ax25 && call_fw_firewall(PF_NETROM, skb->dev, skb->data, NULL)!=FW_ACCEPT)
+	if (ax25 != NULL && call_fw_firewall(PF_NETROM, skb->dev, skb->data, NULL) != FW_ACCEPT)
 		return 0;
 #endif
 
 	dptr  = skb_push(skb, 1);
 	*dptr = AX25_P_NETROM;
 
-	ax25_send_frame(skb, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
-
-	return 1;
+	return ax25_send_frame(skb, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
 }
 
 int nr_nodes_get_info(char *buffer, char **start, off_t offset,
@@ -715,7 +715,7 @@
 	off_t pos   = 0;
 	off_t begin = 0;
 	int i;
-  
+
 	cli();
 
 	len += sprintf(buffer, "callsign  mnemonic w n qual obs neigh qual obs neigh qual obs neigh\n");
@@ -723,7 +723,7 @@
 	for (nr_node = nr_node_list; nr_node != NULL; nr_node = nr_node->next) {
 		len += sprintf(buffer + len, "%-9s %-7s  %d %d",
 			ax2asc(&nr_node->callsign),
-			nr_node->mnemonic,
+			(nr_node->mnemonic[0] == '\0') ? "*" : nr_node->mnemonic,
 			nr_node->which + 1,
 			nr_node->count);			
 
@@ -731,7 +731,7 @@
 			len += sprintf(buffer + len, "  %3d   %d %05d",
 				nr_node->routes[i].quality,
 				nr_node->routes[i].obs_count,
-				nr_node->routes[i].neighbour);
+				nr_node->routes[i].neighbour->number);
 		}
 
 		len += sprintf(buffer + len, "\n");
@@ -742,7 +742,7 @@
 			len   = 0;
 			begin = pos;
 		}
-		
+
 		if (pos > offset + length)
 			break;
 	}
@@ -754,7 +754,7 @@
 
 	if (len > length) len = length;
 
-	return(len);
+	return len;
 } 
 
 int nr_neigh_get_info(char *buffer, char **start, off_t offset,
@@ -764,7 +764,7 @@
 	int len     = 0;
 	off_t pos   = 0;
 	off_t begin = 0;
-  
+
 	cli();
 
 	len += sprintf(buffer, "addr  callsign  dev  qual lock count\n");
@@ -796,7 +796,7 @@
 
 	if (len > length) len = length;
 
-	return(len);
+	return len;
 } 
 
 #endif
