diff -u --recursive --new-file v2.1.10/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.10/linux/Documentation/Configure.help	Fri Nov 15 23:49:06 1996
+++ linux/Documentation/Configure.help	Mon Nov 18 11:31:30 1996
@@ -1,7 +1,7 @@
 # Maintained by Axel Boldt (boldt@math.ucsb.edu) 
 #
 # This version of the Linux kernel configuration help texts
-# corresponds to the kernel versions 2.0.x.
+# corresponds to the kernel versions 2.1.x.
 #
 # International versions of this file available on the WWW:
 #   - http://jf.gee.kyoto-u.ac.jp/JF/JF-ftp/euc/Configure.help.euc
@@ -847,6 +847,13 @@
   network think they're talking to a remote computer, while in reality
   the traffic is redirected by your Linux firewall to a local proxy
   server).
+
+IP: firewall packet netlink device
+CONFIG_IP_FIREWALL_NETLINK
+  When packets hit the firewall and are blocked the first 128 bytes of each
+  datagram is passed to optional user space monitoring software that can
+  then look for attacks and take actions such as paging the administrator of
+  the site.
 
 IP: accounting
 CONFIG_IP_ACCT
diff -u --recursive --new-file v2.1.10/linux/Makefile linux/Makefile
--- v2.1.10/linux/Makefile	Fri Nov 15 23:49:06 1996
+++ linux/Makefile	Mon Nov 18 11:59:10 1996
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 10
+SUBLEVEL = 11
 
 ARCH = i386
 
diff -u --recursive --new-file v2.1.10/linux/arch/alpha/kernel/bios32.c linux/arch/alpha/kernel/bios32.c
--- v2.1.10/linux/arch/alpha/kernel/bios32.c	Wed Aug  7 12:31:21 1996
+++ linux/arch/alpha/kernel/bios32.c	Mon Nov 18 10:18:58 1996
@@ -37,6 +37,14 @@
 {
         return 0;
 }
+asmlinkage int sys_pciconfig_read()
+{
+        return 0;
+}
+asmlinkage int sys_pciconfig_write()
+{
+        return 0;
+}
 
 #else /* CONFIG_PCI */
 
@@ -48,6 +56,7 @@
 
 #include <asm/hwrpb.h>
 #include <asm/io.h>
+#include <asm/segment.h>
 
 
 #define KB		1024
@@ -1193,4 +1202,81 @@
         }
 }
 
+asmlinkage int sys_pciconfig_read(
+	unsigned long bus,
+	unsigned long dfn,
+	unsigned long off,
+	unsigned long len,
+	unsigned char *buf)
+{
+        unsigned char ubyte;
+        unsigned short ushort;
+        unsigned int uint;
+	long err = 0;
+
+	switch (len) {
+	    case 1:
+	        err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
+		if (err != PCIBIOS_SUCCESSFUL)
+		    ubyte = 0xff;
+		put_user(ubyte, buf);
+		break;
+	    case 2:
+	        err = pcibios_read_config_word(bus, dfn, off, &ushort);
+		if (err != PCIBIOS_SUCCESSFUL)
+		    ushort = 0xffff;
+		put_user(ushort, (unsigned short *)buf);
+		break;
+	    case 4:
+	        err = pcibios_read_config_dword(bus, dfn, off, &uint);
+		if (err != PCIBIOS_SUCCESSFUL)
+		    uint = 0xffffffff;
+		put_user(uint, (unsigned int *)buf);
+		break;
+	    default:
+	        err = -EINVAL;
+	        break;
+	}
+        return err;
+}
+asmlinkage int sys_pciconfig_write(
+	unsigned long bus,
+	unsigned long dfn,
+	unsigned long off,
+	unsigned long len,
+	unsigned char *buf)
+{
+        unsigned char ubyte;
+        unsigned short ushort;
+        unsigned int uint;
+        long err = 0;
+
+	switch (len) {
+	    case 1:
+                ubyte = get_user(buf);
+                err = pcibios_write_config_byte(bus, dfn, off, ubyte);
+                if (err != PCIBIOS_SUCCESSFUL) {
+			err = -EFAULT;
+		}
+		break;
+	    case 2:
+                ushort = get_user((unsigned short *)buf);
+                err = pcibios_write_config_word(bus, dfn, off, ushort);
+                if (err != PCIBIOS_SUCCESSFUL) {
+			err = -EFAULT;
+		}
+		break;
+	    case 4:
+                uint = get_user((unsigned int *)buf);
+                err = pcibios_write_config_dword(bus, dfn, off, uint);
+                if (err != PCIBIOS_SUCCESSFUL) {
+			err = -EFAULT;
+		}
+		break;
+	    default:
+	        err = -EINVAL;
+	        break;
+	}
+        return err;
+}
 #endif /* CONFIG_PCI */
diff -u --recursive --new-file v2.1.10/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.1.10/linux/arch/alpha/kernel/entry.S	Fri Nov  1 17:13:14 1996
+++ linux/arch/alpha/kernel/entry.S	Mon Nov 18 23:51:30 1996
@@ -777,4 +777,4 @@
 	.quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield
 	.quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname
 	.quad sys_nanosleep, sys_mremap, do_entSys, sys_setresuid, sys_getresuid
-	.quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+	.quad sys_pciconfig_read, sys_pciconfig_write, do_entSys, do_entSys, do_entSys
diff -u --recursive --new-file v2.1.10/linux/arch/alpha/lib/strlen_user.S linux/arch/alpha/lib/strlen_user.S
--- v2.1.10/linux/arch/alpha/lib/strlen_user.S	Fri Nov 15 23:49:06 1996
+++ linux/arch/alpha/lib/strlen_user.S	Fri Nov 15 22:30:13 1996
@@ -1,8 +1,8 @@
 /*
- * arch/alpha/lib/__strlen_user.S
+ * arch/alpha/lib/strlen_user.S
  *
- * Just like strlen except returns -EFAULT if an exception occurs
- * before the terminator is found.
+ * Return the length of the string including the NUL terminator
+ * (strlen+1) or zero if an error occured.
  */
 
 #include <alpha/regdef.h>
@@ -13,7 +13,7 @@
 	99: x,##y;			\
 	.section __ex_table,"a";	\
 	.gprel32 99b;			\
-	lda zero, $exception-99b(zero);	\
+	lda v0, $exception-99b(zero);	\
 	.text
 
 
@@ -34,7 +34,7 @@
 	insqh   t1, a0, t1
 	andnot  a0, 7, v0
 	or      t1, t0, t0
-	subq	a0, 1, a0	# return "1+strlen" (0 for exception)
+	subq	a0, 1, a0	# get our +1 for the return 
 	cmpbge  zero, t0, t1	# t1 <- bitmask: bit i == 1 <==> i-th byte == 0
 	bne     t1, $found
 
@@ -56,12 +56,8 @@
 	addq	v0, t4, v0
 	addq	v0, t2, v0
 	nop			# dual issue next two on ev4 and ev5
-
 	subq    v0, a0, v0
-	ret
-
 $exception:
-	mov	zero, v0
 	ret
 
 	.end __strlen_user
diff -u --recursive --new-file v2.1.10/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.10/linux/arch/i386/defconfig	Tue Nov 12 15:56:02 1996
+++ linux/arch/i386/defconfig	Mon Nov 18 12:01:48 1996
@@ -62,6 +62,7 @@
 #
 # Networking options
 #
+# CONFIG_NETLINK is not set
 # CONFIG_FIREWALL is not set
 # CONFIG_NET_ALIAS is not set
 CONFIG_INET=y
@@ -84,7 +85,6 @@
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_AX25 is not set
-# CONFIG_NETLINK is not set
 
 #
 # SCSI support
@@ -95,12 +95,9 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+# CONFIG_ARCNET is not set
 CONFIG_DUMMY=m
 # CONFIG_EQUALIZER is not set
-# CONFIG_PLIP is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_RADIO is not set
 CONFIG_NET_ETHERNET=y
 CONFIG_NET_VENDOR_3COM=y
 # CONFIG_EL1 is not set
@@ -112,8 +109,12 @@
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
+# CONFIG_FDDI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_NET_RADIO is not set
+# CONFIG_SLIP is not set
 # CONFIG_TR is not set
-# CONFIG_ARCNET is not set
 
 #
 # ISDN subsystem
diff -u --recursive --new-file v2.1.10/linux/arch/i386/kernel/ksyms.c linux/arch/i386/kernel/ksyms.c
--- v2.1.10/linux/arch/i386/kernel/ksyms.c	Fri Nov 15 23:49:06 1996
+++ linux/arch/i386/kernel/ksyms.c	Mon Nov 18 11:31:30 1996
@@ -27,6 +27,10 @@
 	X(apic_reg),		/* Needed internally for the I386 inlines */
 	X(cpu_data),
 	X(syscall_count),
+	X(kernel_flag),
+	X(kernel_counter),
+	X(active_kernel_processor),
+	X(smp_invalidate_needed),
 #endif
 #include <linux/symtab_end.h>
 };
diff -u --recursive --new-file v2.1.10/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.1.10/linux/drivers/block/loop.c	Tue Oct 29 19:58:03 1996
+++ linux/drivers/block/loop.c	Mon Nov 18 11:31:30 1996
@@ -431,7 +431,7 @@
 	unsigned int cmd, unsigned long arg)
 {
 	struct loop_device *lo;
-	int dev, err;
+	int dev;
 
 	if (!inode)
 		return -EINVAL;
diff -u --recursive --new-file v2.1.10/linux/drivers/block/md.c linux/drivers/block/md.c
--- v2.1.10/linux/drivers/block/md.c	Fri Nov  1 17:13:14 1996
+++ linux/drivers/block/md.c	Mon Nov 18 11:31:30 1996
@@ -372,7 +372,7 @@
 
 
 static long md_read (struct inode *inode, struct file *file,
-		    char *buf, int count)
+		    char *buf, unsigned long count)
 {
   int minor=MINOR(inode->i_rdev);
 
@@ -383,7 +383,7 @@
 }
 
 static long md_write (struct inode *inode, struct file *file,
-		     const char *buf, int count)
+		     const char *buf, unsigned long count)
 {
   int minor=MINOR(inode->i_rdev);
 
diff -u --recursive --new-file v2.1.10/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c
--- v2.1.10/linux/drivers/cdrom/cm206.c	Wed Aug 14 10:21:03 1996
+++ linux/drivers/cdrom/cm206.c	Mon Nov 18 11:31:30 1996
@@ -580,7 +580,7 @@
 
 /* The new open. The real opening strategy is defined in cdrom.c. */
 
-static int cm206_open(kdev_t dev, int purpose) 
+static int cm206_open(struct cdrom_device_info *i, int purpose) 
 {
   if (!cd->openfiles) {		/* reset only first time */
     cd->background=0;
@@ -593,7 +593,7 @@
   return 0;
 }
 
-static void cm206_release(kdev_t dev)
+static void cm206_release(struct cdrom_device_info *i)
 {
   if (cd->openfiles==1) {
     if (cd->background) {
@@ -885,7 +885,7 @@
  * upon success. Memory checking has been done by cdrom_ioctl(), the
  * calling function, as well as LBA/MSF sanitization.
 */
-int cm206_audio_ioctl(kdev_t dev, unsigned int cmd, void * arg)
+int cm206_audio_ioctl(struct cdrom_device_info *i, unsigned int cmd, void * arg)
 {
   switch (cmd) {
   case CDROMREADTOCHDR: 
@@ -930,7 +930,7 @@
    some driver statistics accessible through ioctl calls.
  */
 
-static int cm206_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
+static int cm206_ioctl(struct cdrom_device_info *i, unsigned int cmd, unsigned long arg)
 {
   switch (cmd) {
 #ifdef STATISTICS
@@ -947,7 +947,7 @@
   }
 }     
 
-int cm206_media_changed(kdev_t dev) 
+int cm206_media_changed(struct cdrom_device_info *i, int n) 
 {
   if (cd != NULL) {
     int r;
@@ -963,14 +963,14 @@
    the logic should be in cdrom.c */
 
 /* returns number of times device is in use */
-int cm206_open_files(kdev_t dev)	
+int cm206_open_files(struct cdrom_device_info *i)	
 {
   if (cd) return cd->openfiles;
   return -1;
 }
 
 /* controls tray movement */
-int cm206_tray_move(kdev_t dev, int position) 
+int cm206_tray_move(struct cdrom_device_info *i, int position) 
 {
   if (position) {		/* 1: eject */
     type_0_command(c_open_tray,1);
@@ -981,7 +981,7 @@
 }
 
 /* gives current state of the drive */
-int cm206_drive_status(kdev_t dev)
+int cm206_drive_status(struct cdrom_device_info *i, int n)
 {
   get_drive_status();
   if (cd->dsb & dsb_tray_not_closed) return CDS_TRAY_OPEN;
@@ -991,7 +991,7 @@
 }
  
 /* gives current state of disc in drive */
-int cm206_disc_status(kdev_t dev)
+int cm206_disc_status(struct cdrom_device_info *i)
 {
   uch xa;
   get_drive_status();
@@ -1009,7 +1009,7 @@
 }
 
 /* locks or unlocks door lock==1: lock; return 0 upon success */
-int cm206_lock_door(kdev_t dev, int lock)
+int cm206_lock_door(struct cdrom_device_info *i, int lock)
 {
   uch command = (lock) ? c_lock_tray : c_unlock_tray;
   type_0_command(command, 1);	/* wait and get dsb */
@@ -1020,7 +1020,7 @@
 /* Although a session start should be in LBA format, we return it in 
    MSF format because it is slightly easier, and the new generic ioctl
    will take care of the necessary conversion. */
-int cm206_get_last_session(kdev_t dev, struct cdrom_multisession * mssp) 
+int cm206_get_last_session(struct cdrom_device_info *i, struct cdrom_multisession * mssp) 
 {
   if (!FIRST_TRACK) get_disc_status();
   if (mssp != NULL) {
@@ -1038,7 +1038,7 @@
   return 0;
 }
 
-int cm206_get_upc(kdev_t dev, struct cdrom_mcn * mcn)
+int cm206_get_upc(struct cdrom_device_info *info, struct cdrom_mcn * mcn)
 {
   uch upc[10];
   char * ret = mcn->medium_catalog_number;
@@ -1054,7 +1054,7 @@
   return 0;
 } 
 
-int cm206_reset(kdev_t dev)
+int cm206_reset(struct cdrom_device_info *i)
 {
   stop_read();
   reset_cm260();
@@ -1070,7 +1070,6 @@
 static struct cdrom_device_ops cm206_dops = {
   cm206_open,			/* open */
   cm206_release,		/* release */
-  cm206_open_files,		/* number of open_files */
   cm206_drive_status,		/* drive status */
   cm206_disc_status,		/* disc status */
   cm206_media_changed,		/* media changed */
@@ -1085,21 +1084,30 @@
   cm206_ioctl,			/* device-specific ioctl */
   CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION |
     CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO, /* capability */
-  0,				/* mask flags */
-  2,				/* maximum speed */
   1,				/* number of minor devices */
-  1,				/* number of discs */
-  0,				/* options, ignored */
-  0				/* mc_flags, ignored */
 };
 
+static struct cdrom_device_info cm206_info= {
+	&cm206_dops,
+	NULL,
+	NULL,
+	CM206_CDROM_MAJOR,
+	CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_MULTI_SESSION |
+		CDC_MEDIA_CHANGED | CDC_MCN | CDC_PLAY_AUDIO, /* capability */
+	2,				/* maximum speed */
+	1,				/* number of discs */
+	0,				/* options, ignored */
+	0,				/* mc_flags, ignored */
+	0
+};
+	
 /* This routine gets called during init if thing go wrong, can be used
  * in cleanup_module as well. */
 void cleanup(int level)
 {
   switch (level) {
   case 4: 
-    if (unregister_cdrom(MAJOR_NR, "cm206")) {
+    if (unregister_cdrom(&cm206_info)) {
       printk("Can't unregister cdrom cm206\n");
       return;
     }
@@ -1221,7 +1229,7 @@
     cleanup(3);
     return -EIO;
   }
-  if (register_cdrom(MAJOR_NR, "cm206", &cm206_dops) != 0) {
+  if (register_cdrom(&cm206_info,"cm206") != 0) {
     printk("Cannot register for cdrom %d!\n", MAJOR_NR);
     cleanup(3);
     return -EIO;
diff -u --recursive --new-file v2.1.10/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.1.10/linux/drivers/cdrom/optcd.c	Wed Oct 16 10:48:10 1996
+++ linux/drivers/cdrom/optcd.c	Mon Nov 18 11:31:30 1996
@@ -73,6 +73,8 @@
 #include <linux/cdrom.h>
 #include <linux/optcd.h>
 
+#include <asm/uaccess.h>
+
 
 /* Debug support */
 
diff -u --recursive --new-file v2.1.10/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.1.10/linux/drivers/char/cyclades.c	Tue Oct 29 19:58:05 1996
+++ linux/drivers/char/cyclades.c	Mon Nov 18 11:44:51 1996
@@ -1929,7 +1929,7 @@
             | ((status  & CyRI) ? TIOCM_RNG : 0)
             | ((status  & CyDSR) ? TIOCM_DSR : 0)
             | ((status  & CyCTS) ? TIOCM_CTS : 0);
-    put_fs_long(result,(unsigned long *) value);
+    put_user(result,(unsigned int *) value);
     return 0;
 } /* get_modem_info */
 
@@ -1940,7 +1940,9 @@
   int card,chip,channel,index;
   unsigned char *base_addr;
   unsigned long flags;
-  unsigned int arg = get_fs_long((unsigned long *) value);
+  unsigned int arg;
+  
+    get_user(arg,(unsigned int *) value);
 
     card = info->card;
     channel = (info->line) - (cy_card[card].first_line);
@@ -2085,7 +2087,7 @@
 		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
    tmp = base_addr[CyCOR3<<index] & CyREC_FIFO;
-   put_fs_long(tmp,value);
+   put_user(tmp,value);
    return 0;
 }
 
@@ -2099,7 +2101,7 @@
 static int
 get_default_threshold(struct cyclades_port * info, unsigned long *value)
 {
-   put_fs_long(info->default_threshold,value);
+   put_user(info->default_threshold,value);
    return 0;
 }
 
@@ -2137,7 +2139,7 @@
 		   (cy_card[card].base_addr + (cy_chip_offset[chip]<<index));
 
    tmp = base_addr[CyRTPR<<index];
-   put_fs_long(tmp,value);
+   put_user(tmp,value);
    return 0;
 }
 
@@ -2151,7 +2153,7 @@
 static int
 get_default_timeout(struct cyclades_port * info, unsigned long *value)
 {
-   put_fs_long(info->default_timeout,value);
+   put_user(info->default_timeout,value);
    return 0;
 }
 
@@ -2254,8 +2256,8 @@
                 ret_val = error;
                 break;
             }
-            put_fs_long(C_CLOCAL(tty) ? 1 : 0,
-                        (unsigned long *) arg);
+            put_user(C_CLOCAL(tty) ? 1 : 0,
+                        (unsigned int *) arg);
             break;
         case TIOCSSOFTCAR:
             error = verify_area(VERIFY_READ, (void *) arg
@@ -2265,7 +2267,7 @@
                  break;
             }
 
-            arg = get_fs_long((unsigned long *) arg);
+            get_user(arg,(unsigned int *) arg);
             tty->termios->c_cflag =
                     ((tty->termios->c_cflag & ~CLOCAL) |
                      (arg ? CLOCAL : 0));
diff -u --recursive --new-file v2.1.10/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v2.1.10/linux/drivers/char/istallion.c	Wed Oct 16 10:48:12 1996
+++ linux/drivers/char/istallion.c	Mon Nov 18 11:53:10 1996
@@ -44,7 +44,9 @@
 #include <linux/malloc.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
+#include <asm/system.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 /*****************************************************************************/
 
@@ -157,7 +159,7 @@
  *	all the local structures required by a serial tty driver.
  */
 static char	*stli_drvname = "Stallion Intelligent Multiport Serial Driver";
-static char	*stli_drvversion = "1.1.3";
+static char	*stli_drvversion = "1.1.4";
 static char	*stli_serialname = "ttyE";
 static char	*stli_calloutname = "cue";
 
@@ -1790,11 +1792,11 @@
 		break;
 	case TIOCGSOFTCAR:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long))) == 0)
-			put_fs_long(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned long *) arg);
+			put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned long *) arg);
 		break;
 	case TIOCSSOFTCAR:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0);
 		}
 		break;
@@ -1803,26 +1805,26 @@
 			if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig, sizeof(asysigs_t), 1)) < 0)
 				return(rc);
 			val = stli_mktiocm(portp->asig.sigvalue);
-			put_fs_long(val, (unsigned long *) arg);
+			put_user(val, (unsigned int *) arg);
 		}
 		break;
 	case TIOCMBIS:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			stli_mkasysigs(&portp->asig, ((arg & TIOCM_DTR) ? 1 : -1), ((arg & TIOCM_RTS) ? 1 : -1));
 			rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, sizeof(asysigs_t), 0);
 		}
 		break;
 	case TIOCMBIC:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			stli_mkasysigs(&portp->asig, ((arg & TIOCM_DTR) ? 0 : -1), ((arg & TIOCM_RTS) ? 0 : -1));
 			rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, sizeof(asysigs_t), 0);
 		}
 		break;
 	case TIOCMSET:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			stli_mkasysigs(&portp->asig, ((arg & TIOCM_DTR) ? 1 : 0), ((arg & TIOCM_RTS) ? 1 : 0));
 			rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, sizeof(asysigs_t), 0);
 		}
@@ -1837,11 +1839,11 @@
 		break;
 	case STL_GETPFLAG:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long))) == 0)
-			put_fs_long(portp->pflag, (unsigned long *) arg);
+			put_user(portp->pflag, (unsigned int *) arg);
 		break;
 	case STL_SETPFLAG:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned long))) == 0) {
-			portp->pflag = get_fs_long((unsigned long *) arg);
+			get_user(portp->pflag, (unsigned int *) arg);
 			stli_setport(portp);
 		}
 		break;
diff -u --recursive --new-file v2.1.10/linux/drivers/char/riscom8.c linux/drivers/char/riscom8.c
--- v2.1.10/linux/drivers/char/riscom8.c	Wed Oct 16 10:48:13 1996
+++ linux/drivers/char/riscom8.c	Mon Nov 18 11:31:30 1996
@@ -41,6 +41,8 @@
 #include <linux/fcntl.h>
 #include <linux/major.h>
 
+#include <asm/uaccess.h>
+
 #include "riscom8.h"
 #include "riscom8_reg.h"
 
@@ -1369,7 +1371,7 @@
 	error = verify_area(VERIFY_READ, value, sizeof(int));
 	if (error) 
 		return error;
-	arg = get_fs_long((unsigned long *) value);
+	get_user(arg,(unsigned int *) value);
 	switch (cmd) {
 	 case TIOCMBIS: 
 		if (arg & TIOCM_RTS) 
@@ -1528,7 +1530,7 @@
 			    (unsigned long *) arg);
 		return 0;
 	 case TIOCSSOFTCAR:
-		arg = get_user((unsigned long *) arg);
+		get_user(arg,(unsigned int *) arg);
 		tty->termios->c_cflag =
 			((tty->termios->c_cflag & ~CLOCAL) |
 			(arg ? CLOCAL : 0));
diff -u --recursive --new-file v2.1.10/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.1.10/linux/drivers/char/stallion.c	Tue Oct 29 19:58:07 1996
+++ linux/drivers/char/stallion.c	Mon Nov 18 11:53:10 1996
@@ -140,7 +140,7 @@
  *	all the local structures required by a serial tty driver.
  */
 static char	*stl_drvname = "Stallion Multiport Serial Driver";
-static char	*stl_drvversion = "1.1.3";
+static char	*stl_drvversion = "1.1.4";
 static char	*stl_serialname = "ttyE";
 static char	*stl_calloutname = "cue";
 
@@ -1153,35 +1153,35 @@
 		break;
 	case TIOCGSOFTCAR:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long))) == 0)
-			put_fs_long(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned long *) arg);
+			put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0), (unsigned long *) arg);
 		break;
 	case TIOCSSOFTCAR:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (arg ? CLOCAL : 0);
 		}
 		break;
 	case TIOCMGET:
 		if ((rc = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned int))) == 0) {
 			val = (unsigned long) stl_getsignals(portp);
-			put_fs_long(val, (unsigned long *) arg);
+			put_user(val, (unsigned long *) arg);
 		}
 		break;
 	case TIOCMBIS:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			stl_setsignals(portp, ((arg & TIOCM_DTR) ? 1 : -1), ((arg & TIOCM_RTS) ? 1 : -1));
 		}
 		break;
 	case TIOCMBIC:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			stl_setsignals(portp, ((arg & TIOCM_DTR) ? 0 : -1), ((arg & TIOCM_RTS) ? 0 : -1));
 		}
 		break;
 	case TIOCMSET:
 		if ((rc = verify_area(VERIFY_READ, (void *) arg, sizeof(long))) == 0) {
-			arg = get_fs_long((unsigned long *) arg);
+			get_user(arg, (unsigned long *) arg);
 			stl_setsignals(portp, ((arg & TIOCM_DTR) ? 1 : 0), ((arg & TIOCM_RTS) ? 1 : 0));
 		}
 		break;
diff -u --recursive --new-file v2.1.10/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.1.10/linux/drivers/char/wdt.c	Tue Oct 29 19:58:10 1996
+++ linux/drivers/char/wdt.c	Mon Nov 18 11:31:30 1996
@@ -105,13 +105,13 @@
 }
 
 
-static int wdt_lseek(struct inode *inode, struct file *file, off_t offset, 
+static long long wdt_llseek(struct inode *inode, struct file *file, long long offset, 
 	int origin)
 {
 	return -ESPIPE;
 }
 
-static int wdt_write(struct inode *inode, struct file *file, const char *buf, int count)
+static long wdt_write(struct inode *inode, struct file *file, const char *buf, unsigned long count)
 {
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
@@ -125,7 +125,7 @@
  *	Read reports the temperature in farenheit
  */
  
-static int wdt_read(struct inode *inode, struct file *file, char *buf, int count)
+static long wdt_read(struct inode *inode, struct file *file, char *buf, unsigned long count)
 {
 	unsigned short c=inb_p(WDT_RT);
 	unsigned char cp;
@@ -202,7 +202,7 @@
  
  
 static struct file_operations wdt_fops = {
-	wdt_lseek,
+	wdt_llseek,
 	wdt_read,
 	wdt_write,
 	NULL,		/* No Readdir */
diff -u --recursive --new-file v2.1.10/linux/drivers/isdn/icn/icn.c linux/drivers/isdn/icn/icn.c
--- v2.1.10/linux/drivers/isdn/icn/icn.c	Sat Aug 31 19:01:48 1996
+++ linux/drivers/isdn/icn/icn.c	Mon Nov 18 11:31:31 1996
@@ -842,7 +842,8 @@
         icn_lock_channel(card,0);                                  /* Lock Bank 0      */
         restore_flags(flags);
         SLEEP(1);
-        memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1);
+        if (copy_from_user(codebuf, buffer, ICN_CODE_STAGE1))
+        	return -EFAULT;
         memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);           /* Copy code        */
 #ifdef BOOT_DEBUG
         printk(KERN_DEBUG "Bootloader transfered\n");
@@ -913,7 +914,8 @@
         while (left) {
                 if (sbfree) {                           /* If there is a free buffer...  */
                         cnt = MIN(256, left);
-                        memcpy_fromfs(codebuf, p, cnt);
+                        if (copy_from_user(codebuf, p, cnt))
+                        	/* FIXME -WRONG */return -EFAULT;
                         memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data                     */ 
                         sbnext;                         /* switch to next buffer         */
                         p += cnt;
@@ -995,7 +997,7 @@
                 if (card->msg_buf_read == card->msg_buf_write)
                         return count;
                 if (user)
-                        put_fs_byte(*card->msg_buf_read++, p);
+                        put_user(*card->msg_buf_read++, p);
                 else
                         *p = *card->msg_buf_read++;
                 if (card->msg_buf_read > card->msg_buf_end)
@@ -1023,7 +1025,13 @@
                         avail = cmd_free;
                         count = MIN(avail, len);
                         if (user)
-                                memcpy_fromfs(msg, buf, count);
+                        {
+                                if (copy_from_user(msg, buf, count) != 0)
+                                {
+                                	icn_release_channel();
+                                	return -EFAULT;
+                                }
+                        }
                         else
                                 memcpy(msg, buf, count);
                         save_flags(flags);
@@ -1175,13 +1183,15 @@
                                                     (void *) a,
                                                     sizeof(ulong) * 2)))
                                         return i;
-                                memcpy_tofs((char *)a,
-                                            (char *)&card, sizeof(ulong));
+                                if (copy_to_user((char *)a,
+                                            (char *)&card, sizeof(ulong)))
+                                            	return -EFAULT;
 				a += sizeof(ulong);
 				{
                                         ulong l = (ulong)&dev;
-                                        memcpy_tofs((char *)a,
-                                                    (char *)&l, sizeof(ulong));
+                                        if (copy_to_user((char *)a,
+                                                    (char *)&l, sizeof(ulong)))
+                                                    return -EFAULT;
                                 }
                                 return 0;
                         case ICN_IOCTL_LOADBOOT:
@@ -1198,7 +1208,8 @@
                         case ICN_IOCTL_ADDCARD:
                                 if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(icn_cdef))))
                                         return i;
-                                memcpy_fromfs((char *)&cdef, (char *)a, sizeof(cdef));
+                                if (copy_from_user((char *)&cdef, (char *)a, sizeof(cdef)))
+                                	return -EFAULT;
                                 return (icn_addcard(cdef.port, cdef.id1, cdef.id2));
                                 break;
                         case ICN_IOCTL_LEASEDCFG:
diff -u --recursive --new-file v2.1.10/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h
--- v2.1.10/linux/drivers/isdn/icn/icn.h	Sat Aug 31 19:01:48 1996
+++ linux/drivers/isdn/icn/icn.h	Mon Nov 18 11:31:31 1996
@@ -118,6 +118,7 @@
 #if defined(__KERNEL__) || defined(__DEBUGVAR__)
 
 #ifdef __KERNEL__
+
 /* Kernel includes */
 
 #include <linux/module.h>
@@ -127,6 +128,7 @@
 #include <linux/major.h>
 #include <asm/segment.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/malloc.h>
@@ -136,6 +138,7 @@
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/isdnif.h>
+
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.10/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c
--- v2.1.10/linux/drivers/isdn/pcbit/drv.c	Sat Jun 29 20:36:22 1996
+++ linux/drivers/isdn/pcbit/drv.c	Mon Nov 18 11:31:31 1996
@@ -37,6 +37,7 @@
 #include <linux/isdnif.h>
 #include <asm/string.h>
 #include <asm/io.h>
+#include <asm/uaccess.h>
 
 #include "pcbit.h"
 #include "edss1.h"
@@ -428,7 +429,8 @@
 		{
 			u_char cbuf[1024];
 
-			memcpy_fromfs(cbuf, buf, len);
+			if (copy_from_user(cbuf, buf, len))
+				return -EFAULT;
 			for (i=0; i<len; i++)
 				writeb(cbuf[i], dev->sh_mem + i);
 		}
@@ -446,7 +448,11 @@
 			/* get it into kernel space */
 			if ((ptr = kmalloc(len, GFP_KERNEL))==NULL)
 				return -ENOMEM;
-			memcpy_fromfs(ptr, buf, len);
+			if (copy_from_user(ptr, buf, len))
+			{
+				kfree(ptr);
+				return -EFAULT;
+			}
 			loadbuf = ptr;
 		}
 		else
@@ -761,8 +767,13 @@
 static int stat_end = 0;
 
 
-#define memcpy_to_COND(flag, d, s, len) \
-(flag ? memcpy_tofs(d, s, len) : memcpy(d, s, len))
+extern inline int memcpy_to_COND(int flag, void *d, void *s, int len)
+{
+	if (flag)
+		return copy_to_user(d, s, len);
+	memcpy(d, s, len);
+	return 0;
+}
 
 
 int pcbit_stat(u_char* buf, int len, int user, int driver, int channel)
@@ -779,24 +790,27 @@
 
 	if (stat_st < stat_end)
 	{
-		memcpy_to_COND(user, buf, statbuf + stat_st, len);
+		if (memcpy_to_COND(user, buf, statbuf + stat_st, len))
+			return -EFAULT;
 		stat_st += len;	   
 	}
 	else
 	{
 		if (len > STATBUF_LEN - stat_st)
 		{
-			memcpy_to_COND(user, buf, statbuf + stat_st, 
-				       STATBUF_LEN - stat_st);
-			memcpy_to_COND(user, buf, statbuf, 
-				       len - (STATBUF_LEN - stat_st));
-
+			if (memcpy_to_COND(user, buf, statbuf + stat_st, 
+				       STATBUF_LEN - stat_st))
+			       	return -EFAULT;
+			if (memcpy_to_COND(user, buf, statbuf, 
+				       len - (STATBUF_LEN - stat_st)))
+				return -EFAULT;
 			stat_st = len - (STATBUF_LEN - stat_st);
 		}
 		else
 		{
-			memcpy_to_COND(user, buf, statbuf + stat_st, 
-				       len);
+			if (memcpy_to_COND(user, buf, statbuf + stat_st,
+				       len))
+			       return -EFAULT;
 
 			stat_st += len;
 			
diff -u --recursive --new-file v2.1.10/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v2.1.10/linux/drivers/net/3c505.c	Wed Oct 16 10:48:17 1996
+++ linux/drivers/net/3c505.c	Mon Nov 18 11:31:31 1996
@@ -1657,13 +1657,14 @@
 
 #ifdef MODULE
 #define NAMELEN 9
-static char devicename[ELP_MAX_CARDS][NAMELEN] = {0,};
+static char devicename[ELP_MAX_CARDS][NAMELEN] = {{0,}};
 static struct device dev_3c505[ELP_MAX_CARDS] =
 {
-	NULL,		/* device name is inserted by net_init.c */
+	{ NULL,		/* device name is inserted by net_init.c */
 	0, 0, 0, 0,
 	0, 0,
-	0, 0, 0, NULL, elplus_probe};
+	0, 0, 0, NULL, elplus_probe},
+};
 
 static int io[ELP_MAX_CARDS] = { 0, };
 static int irq[ELP_MAX_CARDS] = { 0, };
diff -u --recursive --new-file v2.1.10/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.1.10/linux/drivers/net/8390.c	Tue Oct 29 19:58:11 1996
+++ linux/drivers/net/8390.c	Mon Nov 18 11:31:31 1996
@@ -30,6 +30,7 @@
   Paul Gortmaker	: exchange static int ei_pingpong for a #define,
 			  also add better Tx error handling.
   Paul Gortmaker	: rewrite Rx overrun handling as per NS specs.
+  Alexey Kuznetsov	: use the software multicast filter.
 
 
   Sources:
@@ -679,8 +680,45 @@
 
 /*
  *	Set or clear the multicast filter for this adaptor.
+ *	(Don't assume 8bit char..)
  */
  
+extern inline __u32 upd_8390_crc(__u8 b, __u32 x)
+{
+	int i;
+	__u8 ah=0;
+	for(i=0;i<8;i++)
+	{
+		__u8 carry = (x>>31);
+		x<<=1;
+		ah = ((ah<<1)|carry)^b;
+		
+		if(ah&1)
+			x^=0x04C11DB7;
+		ah>>=1;
+		b>>=1;
+	}
+	return x;
+}
+
+extern __inline void make_8390_mc_bits(__u8 *bits, struct device *dev)
+{
+	struct dev_mc_list *dmi;
+	memset(bits,0,8);
+	
+	for(dmi=dev->mc_list;dmi!=NULL;dmi=dmi->next)
+	{
+		int i;
+		__u32 x;
+		if(dmi->dmi_addrlen!=6)
+			continue;	/* !! */
+		x=0xFFFFFFFFUL;
+		for(i=0;i<6;i++)
+			x = upd_8390_crc(dmi->dmi_addr[i],x);
+		bits[x>>29] |= (1<<((x>>26)&7));
+	}
+}
+
 static void set_multicast_list(struct device *dev)
 {
 	short ioaddr = dev->base_addr;
@@ -691,9 +729,22 @@
 	}
 	else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
 	{
-		/* The multicast-accept list is initialized to accept-all, and we
-		   rely on higher-level filtering for now. */
+		unsigned long flags;
+		__u8 mc_bits[8];
+		int i;
+		
+		if(dev->flags&IFF_ALLMULTI)
+			memset(mc_bits,0xFF,8);
+		else
+			make_8390_mc_bits(mc_bits,dev);
+		save_flags(flags);
+		cli();
+		outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr);
+		for(i = 0; i < 8; i++)
+				outb_p(mc_bits[i], ioaddr + EN1_MULT + i);
+		outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, ioaddr);
 		outb_p(E8390_RXCONFIG | 0x08, ioaddr + EN0_RXCR);
+		restore_flags(flags);
 	} 
 	else
 		outb_p(E8390_RXCONFIG, ioaddr + EN0_RXCR);
diff -u --recursive --new-file v2.1.10/linux/drivers/net/CONFIG linux/drivers/net/CONFIG
--- v2.1.10/linux/drivers/net/CONFIG	Thu May 16 20:12:56 1996
+++ linux/drivers/net/CONFIG	Mon Nov 18 11:31:31 1996
@@ -62,6 +62,10 @@
 #     DE4X5_DO_MEMCPY   Forces the Intels to use memory copies into sk_buffs
 #	                rather than straight DMA.
 #
+#  DEFXX		The DIGITAL series of FDDI EISA (DEFEA) and PCI (DEFPA)
+#			controllers
+#       DEFXX_DEBUG	Set the desired debug level
+#
 #  TULIP		Tulip (dc21040/dc21041/ds21140) driver
 #	TULIP_PORT	specify default if_port
 #			0: 10TP
@@ -92,5 +96,6 @@
 DEPCA_OPTS	= 
 EWRK3_OPTS	= 
 DE4X5_OPTS	= -DDE4X5_AUTOSENSE=AUTO
+DEFXX_OPTS	=
 ELP_OPTS	=
 TULIP_OPTS	=
diff -u --recursive --new-file v2.1.10/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.1.10/linux/drivers/net/Config.in	Tue Nov 12 15:56:06 1996
+++ linux/drivers/net/Config.in	Mon Nov 18 11:50:17 1996
@@ -1,44 +1,15 @@
 #
 # Network device configuration
 #
+
+tristate 'ARCnet support' CONFIG_ARCNET
+if [ "$CONFIG_ARCNET" != "n" ]; then
+  bool '  Enable arc0e (ARCnet "Ether-Encap" packet format)' CONFIG_ARCNET_ETH
+  bool '  Enable arc0s (ARCnet RFC1051 packet format)' CONFIG_ARCNET_1051
+fi
 tristate 'Dummy net driver support' CONFIG_DUMMY
 tristate 'EQL (serial line load balancing) support' CONFIG_EQUALIZER
-if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-  tristate 'Frame relay DLCI support (EXPERIMENTAL)' CONFIG_DLCI
-  if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then
-    int '  Max open DLCI' CONFIG_DLCI_COUNT 24
-    int '  Max DLCI per device' CONFIG_DLCI_MAX 8
-    dep_tristate '  SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
-  fi
-fi
-tristate 'PLIP (parallel port) support' CONFIG_PLIP
-tristate 'PPP (point-to-point) support' CONFIG_PPP
-if [ ! "$CONFIG_PPP" = "n" ]; then
-  comment 'CCP compressors for PPP are only built as modules.'
-fi
-tristate 'SLIP (serial line) support' CONFIG_SLIP
-if [ "$CONFIG_SLIP" != "n" ]; then
-  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
-  bool ' Keepalive and linefill' CONFIG_SLIP_SMART
-  bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
-fi
-bool 'Radio network interfaces' CONFIG_NET_RADIO
-if [ "$CONFIG_NET_RADIO" != "n" ]; then
-  if [ "$CONFIG_AX25" != "n" ]; then
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'BAYCOM ser12 and par96 driver for AX.25' CONFIG_BAYCOM
-      tristate 'Soundcard modem driver for AX.25' CONFIG_SOUNDMODEM
-    fi
-    dep_tristate 'Serial port KISS driver for AX.25' CONFIG_MKISS $CONFIG_AX25
-    dep_tristate 'BPQ Ethernet driver for AX.25' CONFIG_BPQETHER $CONFIG_AX25
-    dep_tristate 'Gracilis PackeTwin support' CONFIG_PT $CONFIG_AX25
-    dep_tristate 'Ottawa PI and PI/2 support' CONFIG_PI $CONFIG_AX25
-  fi
-  tristate 'Z8530 SCC KISS emulation driver for AX.25' CONFIG_SCC
-  tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
-  tristate 'WaveLAN support' CONFIG_WAVELAN
-  tristate 'WIC Radio IP bridge (EXPERIMENTAL)' CONFIG_WIC
-fi
+
 #
 #	Ethernet
 #
@@ -113,13 +84,54 @@
   fi
 fi
 
+bool 'FDDI driver support' CONFIG_FDDI
+if [ "$CONFIG_FDDI" = "y" ]; then
+  bool 'Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX
+fi
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'Frame relay DLCI support (EXPERIMENTAL)' CONFIG_DLCI
+  if [ "$CONFIG_DLCI" = "y" -o "$CONFIG_DLCI" = "m" ]; then
+    int '  Max open DLCI' CONFIG_DLCI_COUNT 24
+    int '  Max DLCI per device' CONFIG_DLCI_MAX 8
+    dep_tristate '  SDLA (Sangoma S502/S508) support' CONFIG_SDLA $CONFIG_DLCI
+  fi
+fi
+
+tristate 'PLIP (parallel port) support' CONFIG_PLIP
+
+tristate 'PPP (point-to-point) support' CONFIG_PPP
+if [ ! "$CONFIG_PPP" = "n" ]; then
+  comment 'CCP compressors for PPP are only built as modules.'
+fi
+
+bool 'Radio network interfaces' CONFIG_NET_RADIO
+if [ "$CONFIG_NET_RADIO" != "n" ]; then
+  if [ "$CONFIG_AX25" != "n" ]; then
+    tristate 'Serial port KISS driver for AX.25' CONFIG_MKISS
+    tristate 'BPQ Ethernet driver for AX.25' CONFIG_BPQETHER
+    tristate 'Gracilis PackeTwin driver for AX.25' CONFIG_PT
+    tristate 'Ottawa PI and PI2 driver for AX.25' CONFIG_PI
+    tristate 'Z8530 SCC driver for AX.25' CONFIG_SCC
+  fi
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    tristate 'BAYCOM ser12 and par96 driver for AX.25' CONFIG_BAYCOM
+    tristate 'Soundcard modem driver for AX.25' CONFIG_SOUNDMODEM
+  fi
+  tristate 'STRIP (Metricom starmode radio IP)' CONFIG_STRIP
+  tristate 'WaveLAN support' CONFIG_WAVELAN
+  tristate 'WIC Radio IP bridge (EXPERIMENTAL)' CONFIG_WIC
+fi
+
+tristate 'SLIP (serial line) support' CONFIG_SLIP
+if [ "$CONFIG_SLIP" != "n" ]; then
+  bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
+  bool ' Keepalive and linefill' CONFIG_SLIP_SMART
+  bool ' Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
+fi
+
 bool 'Token Ring driver support' CONFIG_TR
 if [ "$CONFIG_TR" = "y" ]; then
   tristate 'IBM Tropic chipset based adaptor support' CONFIG_IBMTR
-fi
-tristate 'ARCnet support' CONFIG_ARCNET
-if [ "$CONFIG_ARCNET" != "n" ]; then
-  bool '  Enable arc0e (ARCnet "Ether-Encap" packet format)' CONFIG_ARCNET_ETH
-  bool '  Enable arc0s (ARCnet RFC1051 packet format)' CONFIG_ARCNET_1051
 fi
 
diff -u --recursive --new-file v2.1.10/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.10/linux/drivers/net/Makefile	Tue Nov 12 15:56:06 1996
+++ linux/drivers/net/Makefile	Mon Nov 18 11:31:31 1996
@@ -233,8 +233,20 @@
   endif
 endif
 
+ifeq ($(CONFIG_DE620),y)
+L_OBJS += de620.o
+else
+  ifeq ($(CONFIG_DE620),m)
+  M_OBJS += de620.o
+  endif
+endif
+
 ifeq ($(CONFIG_AT1500),y)
 L_OBJS += lance.o
+endif
+
+ifeq ($(CONFIG_DEFXX),y)
+L_OBJS += defxx.o
 endif
 
 ifeq ($(CONFIG_LANCE),y)
diff -u --recursive --new-file v2.1.10/linux/drivers/net/README.multicast linux/drivers/net/README.multicast
--- v2.1.10/linux/drivers/net/README.multicast	Fri Nov 24 16:39:53 1995
+++ linux/drivers/net/README.multicast	Mon Nov 18 11:31:31 1996
@@ -15,11 +15,12 @@
 Board		Multicast	AllMulti	Promisc		Filter
 ------------------------------------------------------------------------
 3c501		YES		YES		YES		Software
-3c503		YES		YES		YES		Software(#)
+3c503		YES		YES		YES		Hardware
 3c505		YES		NO		YES		Hardware
 3c507		NO		NO		NO		N/A
 3c509		YES		YES		YES		Software
-ac3200		YES		YES		YES		Software(#)
+3c59x		YES		YES		YES		Software
+ac3200		YES		YES		YES		Hardware
 apricot		YES		PROMISC		YES		Hardware
 arcnet		NO		NO		NO		N/A
 at1700		PROMISC		PROMISC		YES		Software
@@ -28,29 +29,28 @@
 de600		NO		NO		NO		N/A
 de620		PROMISC		PROMISC		YES		Software
 depca		YES		PROMISC		YES		Hardware
-e2100		YES		YES		YES		Software(#)
+e2100		YES		YES		YES		Hardware
 eepro		YES		PROMISC		YES		Hardware
 eexpress	NO		NO		NO		N/A
 ewrk3		YES		PROMISC		YES		Hardware
-hp-plus		YES		YES		YES		Software(#)
-hp		YES		YES		YES		Software(#)
-hp100		YES		YES		YES		Software(#)
+hp-plus		YES		YES		YES		Hardware
+hp		YES		YES		YES		Hardware
+hp100		YES		YES		YES		Hardware
 ibmtr		NO		NO		NO		N/A
 lance		YES		YES		YES		Software(#)
-ne		YES		YES		YES		Software(#)
-ni52
-ni65		NO		NO		NO		N/A
+ne		YES		YES		YES		Hardware
+ni52		<------------------ Buggy ------------------>
+ni65		YES		YES		YES		Software(#)
 seeq		NO		NO		NO		N/A
 sk_g16		NO		NO		YES		N/A
-smc-ultra	YES		YES		YES		Software(#)
+smc-ultra	YES		YES		YES		Hardware
+sunlance	YES		YES		YES		Software(#)
 tulip		YES		YES		YES		Hardware
 wavelan		--------Buggy--------		YES		N/A
-wd		YES		YES		YES		Software(#)
+wd		YES		YES		YES		Hardware
 znet		YES		YES		YES		Software
 
 
 PROMISC = This multicasts mode is in fact promiscuous mode. Avoid using
 cards who go PROMISC on any multicast in a multicast kernel.
 (#) = Hardware multicast support is not used yet.
-
-
diff -u --recursive --new-file v2.1.10/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.1.10/linux/drivers/net/defxx.c	Thu Jan  1 02:00:00 1970
+++ linux/drivers/net/defxx.c	Mon Nov 18 11:31:31 1996
@@ -0,0 +1,3421 @@
+/*
+ * File Name:
+ *   defxx.c
+ *
+ * Copyright Information:
+ *   Copyright Digital Equipment Corporation 1996.
+ *
+ *   This software may be used and distributed according to the terms of
+ *   the GNU Public License, incorporated herein by reference.
+ *
+ * Abstract:
+ *   A Linux device driver supporting the Digital Equipment Corporation
+ *   FDDI EISA and PCI controller families.  Supported adapters include:
+ *
+ *		DEC FDDIcontroller/EISA (DEFEA)
+ *		DEC FDDIcontroller/PCI  (DEFPA)
+ *
+ * Maintainers:
+ *   LVS	Lawrence V. Stefani
+ *
+ * Contact:
+ *	 The author may be reached at:
+ *
+ *		Inet: stefani@lkg.dec.com
+ *		Mail: Digital Equipment Corporation
+ *			  550 King Street
+ *			  M/S: LKG1-3/M07
+ *			  Littleton, MA  01460
+ *
+ * Credits:
+ *   I'd like to thank Patricia Cross for helping me get started with
+ *   Linux, David Davies for a lot of help upgrading and configuring
+ *   my development system and for answering many OS and driver
+ *   development questions, and Alan Cox for recommendations and
+ *   integration help on getting FDDI support into Linux.  LVS
+ *
+ * Driver Architecture:
+ *   The driver architecture is largely based on previous driver work
+ *   for other operating systems.  The upper edge interface and
+ *   functions were largely taken from existing Linux device drivers
+ *   such as David Davies' DE4X5.C driver and Donald Becker's TULIP.C
+ *   driver.
+ *
+ *   Adapter Probe -
+ *		The driver scans for supported EISA adapters by reading the
+ *		SLOT ID register for each EISA slot and making a match
+ *		against the expected value.  The supported PCI adapters are
+ *		discovered using successive calls to pcibios_find_device.
+ *		The first time the probe routine is called, all supported
+ *		devices are discovered and initialized.  The adapters aren't
+ *		brought up to an operational state until the open routine is
+ *		called.
+ *
+ *   Bus-Specific Initialization -
+ *		This driver currently supports both EISA and PCI controller
+ *		families.  While the custom DMA chip and FDDI logic is similar
+ *		or identical, the bus logic is very different.  After
+ *		initialization, the	only bus-specific differences is in how the
+ *		driver enables and disables interrupts.  Other than that, the
+ *		run-time critical code behaves the same on both families.
+ *		It's important to note that both adapter families are configured
+ *		to I/O map, rather than memory map, the adapter registers.
+ *
+ *   Driver Open/Close -
+ *		In the driver open routine, the driver ISR (interrupt service
+ *		routine) is registered and the adapter is brought to an
+ *		operational state.  In the driver close routine, the opposite
+ *		occurs; the driver ISR is deregistered and the adapter is
+ *		brought to a safe, but closed state.  Users may use consecutive
+ *		commands to bring the adapter up and down as in the following
+ *		example:
+ *					ifconfig fddi0 up
+ *					ifconfig fddi0 down
+ *					ifconfig fddi0 up
+ *
+ *   Driver Shutdown -
+ *		Apparently, there is no shutdown or halt routine support under
+ *		Linux.  This routine would be called during "reboot" or
+ *		"shutdown" to allow the driver to place the adapter in a safe
+ *		state before a warm reboot occurs.  To be really safe, the user
+ *		should close the adapter before shutdown (eg. ifconfig fddi0 down)
+ *		to ensure that the adapter DMA engine is taken off-line.  However,
+ *		the current driver code anticipates this problem and always issues
+ *		a soft reset of the adapter	at the beginning of driver initialization.
+ *		A future driver enhancement in this area may occur in 2.1.X where
+ *		Alan indicated that a shutdown handler may be implemented.
+ *
+ *   Interrupt Service Routine -
+ *		The driver supports shared interrupts, so the ISR is registered for
+ *		each board with the appropriate flag and the pointer to that board's
+ *		device structure.  This provides the context during interrupt
+ *		processing to support shared interrupts and multiple boards.
+ *
+ *		Interrupt enabling/disabling can occur at many levels.  At the host
+ *		end, you can disable system interrupts, or disable interrupts at the
+ *		PIC (on Intel systems).  Across the bus, both EISA and PCI adapters
+ *		have a bus-logic chip interrupt enable/disable as well as a DMA
+ *		controller interrupt enable/disable.
+ *
+ *		The driver currently enables and disables adapter interrupts at the
+ *		bus-logic chip and assumes that Linux will take care of clearing or
+ *		acknowledging any host-based interrupt chips.
+ *
+ *   Control Functions -
+ *		Control functions are those used to support functions such as adding
+ *		or deleting multicast addresses, enabling or disabling packet
+ *		reception filters, or other custom/proprietary commands.  Presently,
+ *		the driver supports the "get statistics", "set multicast list", and
+ *		"set mac address" functions defined by Linux.  A list of possible
+ *		enhancements include:
+ *
+ *				- Custom ioctl interface for executing port interface commands
+ *				- Custom ioctl interface for adding unicast addresses to
+ *				  adapter CAM (to support bridge functions).
+ *				- Custom ioctl interface for supporting firmware upgrades.
+ *
+ *   Hardware (port interface) Support Routines -
+ *		The driver function names that start with "dfx_hw_" represent
+ *		low-level port interface routines that are called frequently.  They
+ *		include issuing a DMA or port control command to the adapter,
+ *		resetting the adapter, or reading the adapter state.  Since the
+ *		driver initialization and run-time code must make calls into the
+ *		port interface, these routines were written to be as generic and
+ *		usable as possible.
+ *
+ *   Receive Path -
+ *		The adapter DMA engine supports a 256 entry receive descriptor block
+ *		of which up to 255 entries can be used at any given time.  The
+ *		architecture is a standard producer, consumer, completion model in
+ *		which the driver "produces" receive buffers to the adapter, the
+ *		adapter "consumes" the receive buffers by DMAing incoming packet data,
+ *		and the driver "completes" the receive buffers by servicing the
+ *		incoming packet, then "produces" a new buffer and starts the cycle
+ *		again.  Receive buffers can be fragmented in up to 16 fragments
+ *		(descriptor	entries).  For simplicity, this driver posts
+ *		single-fragment receive buffers of 4608 bytes, then allocates a
+ *		sk_buff, copies the data, then reposts the buffer.  To reduce CPU
+ *		utilization, a better approach would be to pass up the receive
+ *		buffer (no extra copy) then allocate and post a replacement buffer.
+ *		This is a performance enhancement that should be looked into at
+ *		some point.
+ *
+ *   Transmit Path -
+ *		Like the receive path, the adapter DMA engine supports a 256 entry
+ *		transmit descriptor block of which up to 255 entries can be used at
+ *		any	given time.  Transmit buffers can be fragmented	in up to 255
+ *		fragments (descriptor entries).  This driver always posts one
+ *		fragment per transmit packet request.
+ *
+ *		The fragment contains the entire packet from FC to end of data.
+ *		Before posting the buffer to the adapter, the driver sets a three-byte
+ *		packet request header (PRH) which is required by the Motorola MAC chip
+ *		used on the adapters.  The PRH tells the MAC the type of token to
+ *		receive/send, whether or not to generate and append the CRC, whether
+ *		synchronous or asynchronous framing is used, etc.  Since the PRH
+ *		definition is not necessarily consistent across all FDDI chipsets,
+ *		the driver, rather than the common FDDI packet handler routines,
+ *		sets these bytes.
+ *
+ *		To reduce the amount of descriptor fetches needed per transmit request,
+ *		the driver takes advantage of the fact that there are at least three
+ *		bytes available before the skb->data field on the outgoing transmit
+ *		request.  This is guaranteed by having fddi_setup() in net_init.c set
+ *		dev->hard_header_len to 24 bytes.  21 bytes accounts for the largest
+ *		header in an 802.2 SNAP frame.  The other 3 bytes are the extra "pad"
+ *		bytes which we'll use to store the PRH.
+ *
+ *		There's a subtle advantage to adding these pad bytes to the
+ *		hard_header_len, it ensures that the data portion of the packet for
+ *		an 802.2 SNAP frame is longword aligned.  Other FDDI driver
+ *		implementations may not need the extra padding and can start copying
+ *		or DMAing directly from the FC byte which starts at skb->data.  Should
+ *		another driver implementation need ADDITIONAL padding, the net_init.c
+ *		module should be updated and dev->hard_header_len should be increased.
+ *		NOTE: To maintain the alignment on the data portion of the packet,
+ *		dev->hard_header_len should always be evenly divisible by 4 and at
+ *		least 24 bytes in size.
+ *
+ * Modification History:
+ *		Date		Name	Description
+ *		16-Aug-96	LVS		Created.
+ *		20-Aug-96	LVS		Updated dfx_probe so that version information
+ *							string is only displayed if 1 or more cards are
+ *							found.  Changed dfx_rcv_queue_process to copy
+ *							3 NULL bytes before FC to ensure that data is
+ *							longword aligned in receive buffer.
+ *		09-Sep-96	LVS		Updated dfx_ctl_set_multicast_list to enable
+ *							LLC group promiscuous mode if multicast list
+ *							is too large.  LLC individual/group promiscuous
+ *							mode is now disabled if IFF_PROMISC flag not set.
+ *							dfx_xmt_queue_pkt no longer checks for NULL skb
+ *							on Alan Cox recommendation.  Added node address
+ *							override support.
+ *		12-Sep-96	LVS		Reset current address to factory address during
+ *							device open.  Updated transmit path to post a
+ *							single fragment which includes PRH->end of data.
+ */
+
+/* Version information string - should be updated prior to each new release!!! */
+
+static const char *version = "defxx.c:v1.04 09/16/96  Lawrence V. Stefani (stefani@lkg.dec.com)\n";
+
+/* Include files */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <linux/delay.h>
+#include <asm/byteorder.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <linux/netdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/skbuff.h>
+
+#include "defxx.h"
+
+/* Define global routines */
+
+int	dfx_probe(struct device *dev);
+
+/* Define module-wide (static) routines */
+
+static struct	device *dfx_alloc_device(struct device *dev, u16 iobase);
+
+static void		dfx_bus_init(struct device *dev);
+static void		dfx_bus_config_check(DFX_board_t *bp);
+
+static int		dfx_driver_init(struct device *dev);
+static int		dfx_adap_init(DFX_board_t *bp);
+
+static int		dfx_open(struct device *dev);
+static int		dfx_close(struct device *dev);
+
+static void		dfx_int_pr_halt_id(DFX_board_t *bp);
+static void		dfx_int_type_0_process(DFX_board_t *bp);
+static void		dfx_int_common(DFX_board_t *bp);
+static void		dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static struct	enet_statistics *dfx_ctl_get_stats(struct device *dev);
+static void		dfx_ctl_set_multicast_list(struct device *dev);
+static int		dfx_ctl_set_mac_address(struct device *dev, void *addr);
+static int		dfx_ctl_update_cam(DFX_board_t *bp);
+static int		dfx_ctl_update_filters(DFX_board_t *bp);
+
+static int		dfx_hw_dma_cmd_req(DFX_board_t *bp);
+static int		dfx_hw_port_ctrl_req(DFX_board_t *bp, PI_UINT32	command, PI_UINT32 data_a, PI_UINT32 data_b, PI_UINT32 *host_data);
+static void		dfx_hw_adap_reset(DFX_board_t *bp, PI_UINT32 type);
+static int		dfx_hw_adap_state_rd(DFX_board_t *bp);
+static int		dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type);
+
+static void		dfx_rcv_init(DFX_board_t *bp);
+static void		dfx_rcv_queue_process(DFX_board_t *bp);
+
+static int		dfx_xmt_queue_pkt(struct sk_buff *skb, struct device *dev);
+static void		dfx_xmt_done(DFX_board_t *bp);
+static void		dfx_xmt_flush(DFX_board_t *bp);
+
+/* Define module-wide (static) variables */
+
+static int		num_boards = 0;			/* total number of adapters configured */
+static int		already_probed = 0;		/* have we already entered dfx_probe? */
+
+
+/*
+ * =======================
+ * = dfx_port_write_byte =
+ * = dfx_port_read_byte	 =
+ * = dfx_port_write_long =
+ * = dfx_port_read_long  =
+ * =======================
+ *   
+ * Overview:
+ *   Routines for reading and writing values from/to adapter
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp     - pointer to board information
+ *   offset - register offset from base I/O address
+ *   data   - for dfx_port_write_byte and dfx_port_write_long, this
+ *			  is a value to write.
+ *			  for dfx_port_read_byte and dfx_port_read_byte, this
+ *			  is a pointer to store the read value.
+ *
+ * Functional Description:
+ *   These routines perform the correct operation to read or write
+ *   the adapter register.
+ *   
+ *   EISA port block base addresses are based on the slot number in which the
+ *   controller is installed.  For example, if the EISA controller is installed
+ *   in slot 4, the port block base address is 0x4000.  If the controller is
+ *   installed in slot 2, the port block base address is 0x2000, and so on.
+ *   This port block can be used to access PDQ, ESIC, and DEFEA on-board
+ *   registers using the register offsets defined in DEFXX.H.
+ *
+ *   PCI port block base addresses are assigned by the PCI BIOS or system
+ *	 firmware.  There is one 128 byte port block which can be accessed.  It
+ *   allows for I/O mapping of both PDQ and PFI registers using the register
+ *   offsets defined in DEFXX.H.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   bp->base_addr is a valid base I/O address for this adapter.
+ *   offset is a valid register offset for this adapter.
+ *
+ * Side Effects:
+ *   Rather than produce macros for these functions, these routines
+ *   are defined using "inline" to ensure that the compiler will
+ *   generate inline code and not waste a procedure call and return.
+ *   This provides all the benefits of macros, but with the
+ *   advantage of strict data type checking.
+ */
+
+static inline void dfx_port_write_byte(
+	DFX_board_t	*bp,
+	int			offset,
+	u8			data
+	)
+
+	{
+	u16 port = bp->base_addr + offset;
+
+	outb(data, port);
+	return;
+	}
+
+static inline void dfx_port_read_byte(
+	DFX_board_t	*bp,
+	int			offset,
+	u8			*data
+	)
+
+	{
+	u16 port = bp->base_addr + offset;
+
+	*data = inb(port);
+	return;
+	}
+
+static inline void dfx_port_write_long(
+	DFX_board_t	*bp,
+	int			offset,
+	u32			data
+	)
+
+	{
+	u16 port = bp->base_addr + offset;
+
+	outl(data, port);
+	return;
+	}
+
+static inline void dfx_port_read_long(
+	DFX_board_t	*bp,
+	int			offset,
+	u32			*data
+	)
+
+	{
+	u16 port = bp->base_addr + offset;
+
+	*data = inl(port);
+	return;
+	}
+
+
+/*
+ * =============
+ * = dfx_probe =
+ * =============
+ *   
+ * Overview:
+ *   Probes for supported FDDI EISA and PCI controllers
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This routine is called by the OS for each FDDI device name (fddi0,
+ *   fddi1,...,fddi6, fddi7) specified in drivers/net/Space.c.  Since
+ *   the DEFXX.C driver currently does not support being loaded as a
+ *   module, dfx_probe() will initialize all devices the first time
+ *   it is called.
+ *
+ *   Let's say that dfx_probe() is getting called to initialize fddi0.
+ *   Furthermore, let's say there are three supported controllers in the
+ *   system.  Before dfx_probe() leaves, devices fddi0, fddi1, and fddi2
+ *   will be initialized and a global flag will be set to indicate that
+ *   dfx_probe() has already been called.
+ *
+ *   However...the OS doesn't know that we've already initialized
+ *   devices fddi1 and fddi2 so dfx_probe() gets called again and again
+ *   until it reaches the end of the device list for FDDI (presently,
+ *   fddi7).  It's important that the driver "pretend" to probe for
+ *   devices fddi1 and fddi2 and return success.  Devices fddi3
+ *   through fddi7 will return failure since they weren't initialized.
+ *
+ *   This algorithm seems to work for the time being.  As other FDDI
+ *   drivers are written for Linux, a more generic approach (perhaps
+ *   similar to the Ethernet card approach) may need to be implemented.
+ *   
+ * Return Codes:
+ *   0		 - This device (fddi0, fddi1, etc) configured successfully
+ *   -ENODEV - No devices present, or no Digital FDDI EISA or PCI device
+ *			   present for this device name
+ *
+ * Assumptions:
+ *   For the time being, DEFXX.C is the only FDDI driver under Linux.
+ *   As this assumption changes, this routine will likely be impacted.
+ *   Also, it is assumed that no more than eight (8) FDDI controllers
+ *   will be configured in the system (fddi0 through fddi7).  This
+ *   routine will not allocate new device structures.  If more than
+ *   eight FDDI controllers need to be configured, drivers/net/Space.c
+ *   should be updated as well as the DFX_MAX_NUM_BOARDS constant in
+ *   DEFXX.H.
+ *
+ * Side Effects:
+ *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
+ *   initialized and the board resources are read and stored in
+ *   the device structure.
+ */
+
+int dfx_probe(
+	struct device *dev
+	)
+
+	{
+	int				i;				/* used in for loops */
+	int				version_disp;	/* was version info string already displayed? */
+	int				port_len;		/* length of port address range (in bytes) */
+	u8				pci_bus;		/* PCI bus number (0-255) */
+	u8				pci_dev_fun;	/* PCI device and function numbers (0-255) */
+	u16				port;			/* temporary I/O (port) address */
+	u16				command;		/* PCI Configuration space Command register val */
+	u32				slot_id;		/* EISA hardware (slot) ID read from adapter */
+	DFX_board_t		*bp;			/* board pointer */
+
+	DBG_printk("In dfx_probe...\n");
+
+	/*
+	 * Verify whether we're going through dfx_probe() again
+	 *
+	 * If so, see if we're going through for a subsequent fddi device that
+	 * we've already initialized.  If we are, return success (0).  If not,
+	 * return failure (-ENODEV).
+	 */
+
+	version_disp = 0;				/* default to version string not displayed */
+	if (already_probed)
+		{
+		DBG_printk("Already entered dfx_probe\n");
+		if (dev != NULL)
+			if ((strncmp(dev->name, "fddi", 4) == 0) && (dev->base_addr != 0))
+				{
+				DBG_printk("In dfx_probe for fddi adapter (%s) we've already initialized it, so return success\n", dev->name);
+				return(0);
+				}
+		return(-ENODEV);
+		}
+	already_probed = 1;			/* set global flag */
+
+	/* Scan for FDDI EISA controllers */
+
+	for (i=0; i < DFX_MAX_EISA_SLOTS; i++)		/* only scan for up to 16 EISA slots */
+		{
+		port = (i << 12) + PI_ESIC_K_SLOT_ID;	/* port = I/O address for reading slot ID */
+		slot_id = inl(port);					/* read EISA HW (slot) ID */
+		if ((slot_id & 0xF0FFFFFF) == DEFEA_PRODUCT_ID)
+			{
+			if (!version_disp)					/* display version info if adapter is found */
+				{
+				version_disp = 1;				/* set display flag to TRUE so that */
+				printk(version);				/* we only display this string ONCE */
+				}
+				
+			port = (i << 12);					/* recalc base addr */
+
+			/* Verify port address range is not already being used */
+
+			port_len = PI_ESIC_K_CSR_IO_LEN;
+			if (check_region(port, port_len) == 0)
+				{
+				/* Allocate a new device structure for this adapter */
+
+				dev = dfx_alloc_device(dev, port);
+				if (dev != NULL)
+					{
+					/* Initialize board structure with bus-specific info */
+
+					bp = (DFX_board_t *) dev->priv;
+					bp->dev = dev;
+					bp->bus_type = DFX_BUS_TYPE_EISA;
+					if (dfx_driver_init(dev) == DFX_K_SUCCESS)
+						num_boards++;		/* only increment global board count on success */
+					else
+						dev->base_addr = 0;	/* clear port address field in device structure on failure */
+					}
+				}
+			else
+				printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
+			}
+		}
+
+	/* Scan for FDDI PCI controllers */
+
+	if (pcibios_present())						/* is PCI BIOS even present? */
+		for (i=0; i < DFX_MAX_NUM_BOARDS; i++)	/* scan for up to 8 PCI cards */
+			if (pcibios_find_device(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, i, &pci_bus, &pci_dev_fun) == 0)
+				{
+				if (!version_disp)					/* display version info if adapter is found */
+					{
+					version_disp = 1;				/* set display flag to TRUE so that */
+					printk(version);				/* we only display this string ONCE */
+					}
+
+				/* Verify that I/O enable bit is set (PCI slot is enabled) */
+
+				pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, &command);
+				if ((command & PCI_COMMAND_IO) == 0)
+					printk("I/O enable bit not set!  Verify that slot is enabled\n");
+				else
+					{
+					/* Turn off memory mapped space and enable mastering */
+
+					command |= PCI_COMMAND_MASTER;
+					command &= ~PCI_COMMAND_MEMORY;
+					pcibios_write_config_word(pci_bus, pci_dev_fun, PCI_COMMAND, command);
+
+					/* Read I/O base address from PCI Configuration Space */
+				
+					pcibios_read_config_word(pci_bus, pci_dev_fun, PCI_BASE_ADDRESS_1, &port);
+					port &= PCI_BASE_ADDRESS_IO_MASK;		/* clear I/O bit (bit 0) */
+
+					/* Verify port address range is not already being used */
+
+					port_len = PFI_K_CSR_IO_LEN;
+					if (check_region(port, port_len) == 0)
+						{
+						/* Allocate a new device structure for this adapter */
+
+						dev = dfx_alloc_device(dev, port);
+						if (dev != NULL)
+							{
+							/* Initialize board structure with bus-specific info */
+
+							bp = (DFX_board_t *) dev->priv;
+							bp->dev = dev;
+							bp->bus_type = DFX_BUS_TYPE_PCI;
+							bp->pci_bus = pci_bus;
+							bp->pci_dev_fun = pci_dev_fun;
+							if (dfx_driver_init(dev) == DFX_K_SUCCESS)
+								num_boards++;		/* only increment global board count on success */
+							else
+								dev->base_addr = 0;	/* clear port address field in device structure on failure */
+							}
+						}
+					else
+						printk("I/O range allocated to adapter (0x%X-0x%X) is already being used!\n", port, (port + port_len-1));
+					}
+				}
+
+	/*
+	 * If we're at this point we're going through dfx_probe() for the first
+	 * time.  Return success (0) if we've initialized 1 or more boards.
+	 * Otherwise, return failure (-ENODEV).
+	 */
+
+	if (num_boards > 0)
+		return(0);
+	else
+		return(-ENODEV);
+	}
+
+
+/*
+ * ====================
+ * = dfx_alloc_device =
+ * ====================
+ *   
+ * Overview:
+ *   Allocate new device structure for adapter
+ *  
+ * Returns:
+ *   Pointer to device structure for this adapter or NULL if
+ *   none are available or could not allocate memory for
+ *   private board structure.
+ *       
+ * Arguments:
+ *   dev    - pointer to device information for last device
+ *   iobase - base I/O address of new adapter
+ *
+ * Functional Description:
+ *   The algorithm for allocating a new device structure is
+ *   fairly simple.  Since we're presently the only FDDI driver
+ *   under Linux, we'll find the first device structure with an
+ *   "fddi*" device name that's free.  If we run out of devices,
+ *   we'll fail on error.  This is simpler than trying to
+ *   allocate the memory for a new device structure, determine
+ *   the next free number (beyond 7) and link it into the chain
+ *   of devices.  A user can always modify drivers/net/Space.c
+ *   to add new FDDI device structures if necessary.
+ *
+ *   Beyond finding a free FDDI device structure, this routine
+ *   initializes most of the fields, resource tags, and dispatch
+ *   pointers in the device structure and calls the common
+ *   fddi_setup() routine to perform the rest of the device
+ *   structure initialization.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   If additional FDDI drivers are integrated into Linux,
+ *   we'll likely need to use a different approach to
+ *   allocate a device structure.  Perhaps one that is
+ *   similar to what the Ethernet drivers use.
+ *
+ * Side Effects:
+ *   None
+ */
+
+struct device *dfx_alloc_device(
+	struct device	*dev,
+	u16				iobase
+	)
+
+	{
+	struct device *tmp_dev;		/* pointer to a device structure */
+
+	DBG_printk("In dfx_alloc_device...\n");
+
+	/* Find next free fddi entry */
+
+	for (tmp_dev = dev; tmp_dev != NULL; tmp_dev = tmp_dev->next)
+		if ((strncmp(tmp_dev->name, "fddi", 4) == 0) && (tmp_dev->base_addr == 0))
+			break;
+	if (tmp_dev == NULL)
+		{
+		printk("Could not find free FDDI device structure for this adapter!\n");
+		return(NULL);
+		}
+	DBG_printk("Device entry free, device name = %s\n", tmp_dev->name);
+
+	/* Allocate space for private board structure */
+
+	tmp_dev->priv = (void *) kmalloc(sizeof(DFX_board_t), GFP_KERNEL);
+	if (tmp_dev->priv == NULL)
+		{
+		printk("Could not allocate memory for private board structure!\n");
+		return(NULL);
+		}
+	memset(tmp_dev->priv, 0, sizeof(DFX_board_t));	/* clear structure */
+
+	/* Initialize new device structure */
+
+	tmp_dev->rmem_end	= 0;		/* shared memory isn't used */
+	tmp_dev->rmem_start	= 0;		/* shared memory isn't used */
+	tmp_dev->mem_end	= 0;		/* shared memory isn't used */
+	tmp_dev->mem_start	= 0;		/* shared memory isn't used */
+	tmp_dev->base_addr	= iobase;	/* save port (I/O) base address */
+	tmp_dev->irq		= 0;		/* set in dfx_bus_init() */
+	tmp_dev->if_port	= 0;		/* not applicable to FDDI adapters */
+	tmp_dev->dma		= 0;		/* Bus Master DMA doesn't require channel */
+
+	tmp_dev->get_stats				= &dfx_ctl_get_stats;
+	tmp_dev->open					= &dfx_open;
+	tmp_dev->stop					= &dfx_close;
+	tmp_dev->hard_start_xmit		= &dfx_xmt_queue_pkt;
+	tmp_dev->hard_header			= NULL;		/* set in fddi_setup() */
+	tmp_dev->rebuild_header			= NULL;		/* set in fddi_setup() */
+	tmp_dev->set_multicast_list		= &dfx_ctl_set_multicast_list;
+	tmp_dev->set_mac_address		= &dfx_ctl_set_mac_address;
+	tmp_dev->do_ioctl				= NULL;		/* not supported for now &&& */
+	tmp_dev->set_config				= NULL;		/* not supported for now &&& */
+	tmp_dev->header_cache_bind		= NULL;		/* not supported */
+	tmp_dev->header_cache_update	= NULL;		/* not supported */
+	tmp_dev->change_mtu				= NULL;		/* set in fddi_setup() */
+
+	/* Initialize remaining device structure information */
+
+	fddi_setup(tmp_dev);
+	return(tmp_dev);
+	}
+
+
+/*
+ * ================
+ * = dfx_bus_init =
+ * ================
+ *   
+ * Overview:
+ *   Initializes EISA and PCI controller bus-specific logic.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Determine and save adapter IRQ in device table,
+ *   then perform bus-specific logic initialization.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   dev->base_addr has already been set with the proper
+ *	 base I/O address for this device.
+ *
+ * Side Effects:
+ *   Interrupts are enabled at the adapter bus-specific logic.
+ *   Note:  Interrupts at the DMA engine (PDQ chip) are not
+ *   enabled yet.
+ */
+
+void dfx_bus_init(
+	struct device *dev
+	)
+
+	{
+	DFX_board_t *bp = (DFX_board_t *)dev->priv;
+	u8			val;	/* used for I/O read/writes */
+
+	DBG_printk("In dfx_bus_init...\n");
+
+	/*
+	 * Initialize base I/O address field in bp structure
+	 *
+	 * Note: bp->base_addr is the same as dev->base_addr.
+	 *		 It's useful because often we'll need to read
+	 *		 or write registers where we already have the
+	 *		 bp pointer instead of the dev pointer.  Having
+	 *		 the base address in the bp structure will
+	 *		 save a pointer dereference.
+	 *
+	 *		 IMPORTANT!! This field must be defined before
+	 *		 any of the dfx_port_* inline functions are
+	 *		 called.
+	 */
+
+	bp->base_addr = dev->base_addr;
+
+	/* Initialize adapter based on bus type */
+
+	if (bp->bus_type == DFX_BUS_TYPE_EISA)
+		{
+		/* Get the interrupt level from the ESIC chip */
+
+		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val);
+		switch ((val & PI_CONFIG_STAT_0_M_IRQ) >> PI_CONFIG_STAT_0_V_IRQ)
+			{
+			case PI_CONFIG_STAT_0_IRQ_K_9:
+				dev->irq = 9;
+				break;
+
+			case PI_CONFIG_STAT_0_IRQ_K_10:
+				dev->irq = 10;
+				break;
+
+			case PI_CONFIG_STAT_0_IRQ_K_11:
+				dev->irq = 11;
+				break;
+
+			case PI_CONFIG_STAT_0_IRQ_K_15:
+				dev->irq = 15;
+				break;
+			}
+
+		/* Enable access to I/O on the board by writing 0x03 to Function Control Register */
+
+		dfx_port_write_byte(bp, PI_ESIC_K_FUNCTION_CNTRL, PI_ESIC_K_FUNCTION_CNTRL_IO_ENB);
+
+		/* Set the I/O decode range of the board */
+
+		val = ((dev->base_addr >> 12) << PI_IO_CMP_V_SLOT);
+		dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_0_1, val);
+		dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_1_1, val);
+
+		/* Enable access to rest of module (including PDQ and packet memory) */
+
+		dfx_port_write_byte(bp, PI_ESIC_K_SLOT_CNTRL, PI_SLOT_CNTRL_M_ENB);
+
+		/*
+		 * Map PDQ registers into I/O space.  This is done by clearing a bit
+		 * in Burst Holdoff register.
+		 */
+
+		dfx_port_read_byte(bp, PI_ESIC_K_BURST_HOLDOFF, &val);
+		dfx_port_write_byte(bp, PI_ESIC_K_BURST_HOLDOFF, (val & ~PI_BURST_HOLDOFF_M_MEM_MAP));
+
+		/* Enable interrupts at EISA bus interface chip (ESIC) */
+
+		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val);
+		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, (val | PI_CONFIG_STAT_0_M_INT_ENB));
+		}
+	else
+		{
+		/* Get the interrupt level from the PCI Configuration Table */
+
+		pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_INTERRUPT_LINE, &val);
+		dev->irq = val;					/* save IRQ value in device table */
+
+		/* Check Latency Timer and set if less than minimal */
+
+		pcibios_read_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, &val);
+		if (val < PFI_K_LAT_TIMER_MIN)	/* if less than min, override with default */
+			{
+			val = PFI_K_LAT_TIMER_DEF;
+			pcibios_write_config_byte(bp->pci_bus, bp->pci_dev_fun, PCI_LATENCY_TIMER, val);
+			}
+
+		/* Enable interrupts at PCI bus interface chip (PFI) */
+
+		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, (PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB));
+		}
+	return;
+	}
+
+
+/*
+ * ========================
+ * = dfx_bus_config_check =
+ * ========================
+ *   
+ * Overview:
+ *   Checks the configuration (burst size, full-duplex, etc.)  If any parameters
+ *   are illegal, then this routine will set new defaults.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   For Revision 1 FDDI EISA, Revision 2 or later FDDI EISA with rev E or later
+ *   PDQ, and all FDDI PCI controllers, all values are legal.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   dfx_adap_init has NOT been called yet so burst size and other items have
+ *   not been set.
+ *
+ * Side Effects:
+ *   None
+ */
+
+void dfx_bus_config_check(
+	DFX_board_t *bp
+	)
+
+	{
+	int	status;				/* return code from adapter port control call */
+	u32	slot_id;			/* EISA-bus hardware id (DEC3001, DEC3002,...) */
+	u32	host_data;			/* LW data returned from port control call */
+
+	DBG_printk("In dfx_bus_config_check...\n");
+
+	/* Configuration check only valid for EISA adapter */
+
+	if (bp->bus_type == DFX_BUS_TYPE_EISA)
+		{
+		dfx_port_read_long(bp, PI_ESIC_K_SLOT_ID, &slot_id);
+
+		/*
+		 * First check if revision 2 EISA controller.  Rev. 1 cards used
+		 * PDQ revision B, so no workaround needed in this case.  Rev. 3
+		 * cards used PDQ revision E, so no workaround needed in this
+		 * case, either.  Only Rev. 2 cards used either Rev. D or E
+		 * chips, so we must verify the chip revision on Rev. 2 cards.
+		 */
+
+		if (slot_id == DEFEA_PROD_ID_2)
+			{
+			/*
+			 * Revision 2 FDDI EISA controller found, so let's check PDQ
+			 * revision of adapter.
+			 */
+
+			status = dfx_hw_port_ctrl_req(bp,
+											PI_PCTRL_M_SUB_CMD,
+											PI_SUB_CMD_K_PDQ_REV_GET,
+											0,
+											&host_data);
+			if ((status != DFX_K_SUCCESS) || (host_data == 2))
+				{
+				/*
+				 * Either we couldn't determine the PDQ revision, or
+				 * we determined that it is at revision D.  In either case,
+				 * we need to implement the workaround.
+				 */
+
+				/* Ensure that the burst size is set to 8 longwords or less */
+
+				switch (bp->burst_size)
+					{
+					case PI_PDATA_B_DMA_BURST_SIZE_32:
+					case PI_PDATA_B_DMA_BURST_SIZE_16:
+						bp->burst_size = PI_PDATA_B_DMA_BURST_SIZE_8;
+						break;
+
+					default:
+						break;
+					}
+
+				/* Ensure that full-duplex mode is not enabled */
+
+				bp->full_duplex_enb = PI_SNMP_K_FALSE;
+				}
+			}
+		}
+	return;
+	}
+
+
+/*
+ * ===================
+ * = dfx_driver_init =
+ * ===================
+ *   
+ * Overview:
+ *   Initializes remaining adapter board structure information
+ *   and makes sure adapter is in a safe state prior to dfx_open().
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This function allocates additional resources such as the host memory
+ *   blocks needed by the adapter (eg. descriptor and consumer blocks).
+ *	 Remaining bus initialization steps are also completed.  The adapter
+ *   is also reset so that it is in the DMA_UNAVAILABLE state.  The OS
+ *   must call dfx_open() to open the adapter and bring it on-line.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS	- initialization succeeded
+ *   DFX_K_FAILURE	- initialization failed - could not allocate memory
+ *						or read adapter MAC address
+ *
+ * Assumptions:
+ *   Memory allocated from kmalloc() call is physically contiguous, locked
+ *   memory whose physical address equals its virtual address.
+ *
+ * Side Effects:
+ *   Adapter is reset and should be in DMA_UNAVAILABLE state before
+ *   returning from this routine.
+ */
+
+int dfx_driver_init(
+	struct device *dev
+	)
+
+	{
+	DFX_board_t *bp = (DFX_board_t *)dev->priv;
+	int			alloc_size;			/* total buffer size needed */
+	char		*top_v, *curr_v;	/* virtual addrs into memory block */
+	u32			top_p, curr_p;		/* physical addrs into memory block */
+	u32			data;				/* host data register value */
+
+	DBG_printk("In dfx_driver_init...\n");
+
+	/* Initialize bus-specific hardware registers */
+
+	dfx_bus_init(dev);
+
+	/*
+	 * Initialize default values for configurable parameters
+	 *
+	 * Note: All of these parameters are ones that a user may
+	 *       want to customize.  It'd be nice to break these
+	 *		 out into Space.c or someplace else that's more
+	 *		 accessible/understandable than this file.
+	 */
+
+	bp->full_duplex_enb		= PI_SNMP_K_FALSE;
+	bp->req_ttrt			= 8 * 12500;		/* 8ms in 80 nanosec units */
+	bp->burst_size			= PI_PDATA_B_DMA_BURST_SIZE_DEF;
+	bp->rcv_bufs_to_post	= RCV_BUFS_DEF;
+
+	/*
+	 * Ensure that HW configuration is OK
+	 *
+	 * Note: Depending on the hardware revision, we may need to modify
+	 *       some of the configurable parameters to workaround hardware
+	 *       limitations.  We'll perform this configuration check AFTER
+	 *       setting the parameters to their default values.
+	 */
+
+	dfx_bus_config_check(bp);
+
+	/* Disable PDQ interrupts first */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+
+	/* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
+
+	(void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
+
+	/*  Read the factory MAC address from the adapter then save it */
+
+	if (dfx_hw_port_ctrl_req(bp,
+							PI_PCTRL_M_MLA,
+							PI_PDATA_A_MLA_K_LO,
+							0,
+							&data) != DFX_K_SUCCESS)
+		{
+		printk("%s: Could not read adapter factory MAC address!\n", dev->name);
+		return(DFX_K_FAILURE);
+		}
+	memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32));
+
+	if (dfx_hw_port_ctrl_req(bp,
+							PI_PCTRL_M_MLA,
+							PI_PDATA_A_MLA_K_HI,
+							0,
+							&data) != DFX_K_SUCCESS)
+		{
+		printk("%s: Could not read adapter factory MAC address!\n", dev->name);
+		return(DFX_K_FAILURE);
+		}
+	memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16));
+
+	/*
+	 * Set current address to factory address
+	 *
+	 * Note: Node address override support is handled through
+	 *       dfx_ctl_set_mac_address.
+	 */
+
+	memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
+	if (bp->bus_type == DFX_BUS_TYPE_EISA)
+		printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+				dev->name,
+				dev->base_addr,
+				dev->irq,
+				dev->dev_addr[0],
+				dev->dev_addr[1],
+				dev->dev_addr[2],
+				dev->dev_addr[3],
+				dev->dev_addr[4],
+				dev->dev_addr[5]);
+	else
+		printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+				dev->name,
+				dev->base_addr,
+				dev->irq,
+				dev->dev_addr[0],
+				dev->dev_addr[1],
+				dev->dev_addr[2],
+				dev->dev_addr[3],
+				dev->dev_addr[4],
+				dev->dev_addr[5]);
+
+	/*
+	 * Get memory for descriptor block, consumer block, and other buffers
+	 * that need to be DMA read or written to by the adapter.
+	 */
+
+	alloc_size = sizeof(PI_DESCR_BLOCK) +
+					PI_CMD_REQ_K_SIZE_MAX +
+					PI_CMD_RSP_K_SIZE_MAX +
+					(bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +
+					sizeof(PI_CONSUMER_BLOCK) +
+					(PI_ALIGN_K_DESC_BLK - 1);
+	top_v = (char *) kmalloc(alloc_size, GFP_KERNEL);
+	if (top_v == NULL)
+		{
+		printk("%s: Could not allocate memory for host buffers and structures!\n", dev->name);
+		return(DFX_K_FAILURE);
+		}
+	memset(top_v, 0, alloc_size);	/* zero out memory before continuing */
+	top_p = virt_to_bus(top_v);		/* get physical address of buffer */
+
+	/*
+	 *  To guarantee the 8K alignment required for the descriptor block, 8K - 1
+	 *  plus the amount of memory needed was allocated.  The physical address
+	 *	is now 8K aligned.  By carving up the memory in a specific order,
+	 *  we'll guarantee the alignment requirements for all other structures.
+	 *
+	 *  Note: If the assumptions change regarding the non-paged, non-cached,
+	 *		  physically contiguous nature of the memory block or the address
+	 *		  alignments, then we'll need to implement a different algorithm
+	 *		  for allocating the needed memory.
+	 */
+
+	curr_p = (u32) (ALIGN(top_p, PI_ALIGN_K_DESC_BLK));
+	curr_v = top_v + (curr_p - top_p);
+
+	/* Reserve space for descriptor block */
+
+	bp->descr_block_virt = (PI_DESCR_BLOCK *) curr_v;
+	bp->descr_block_phys = curr_p;
+	curr_v += sizeof(PI_DESCR_BLOCK);
+	curr_p += sizeof(PI_DESCR_BLOCK);
+
+	/* Reserve space for command request buffer */
+
+	bp->cmd_req_virt = (PI_DMA_CMD_REQ *) curr_v;
+	bp->cmd_req_phys = curr_p;
+	curr_v += PI_CMD_REQ_K_SIZE_MAX;
+	curr_p += PI_CMD_REQ_K_SIZE_MAX;
+
+	/* Reserve space for command response buffer */
+
+	bp->cmd_rsp_virt = (PI_DMA_CMD_RSP *) curr_v;
+	bp->cmd_rsp_phys = curr_p;
+	curr_v += PI_CMD_RSP_K_SIZE_MAX;
+	curr_p += PI_CMD_RSP_K_SIZE_MAX;
+
+	/* Reserve space for the LLC host receive queue buffers */
+
+	bp->rcv_block_virt = curr_v;
+	bp->rcv_block_phys = curr_p;
+	curr_v += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
+	curr_p += (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX);
+
+	/* Reserve space for the consumer block */
+
+	bp->cons_block_virt = (PI_CONSUMER_BLOCK *) curr_v;
+	bp->cons_block_phys = curr_p;
+
+	/* Display virtual and physical addresses if debug driver */
+
+	DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n",				dev->name, (long)bp->descr_block_virt,	bp->descr_block_phys);
+	DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n",			dev->name, (long)bp->cmd_req_virt,		bp->cmd_req_phys);
+	DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n",			dev->name, (long)bp->cmd_rsp_virt,		bp->cmd_rsp_phys);
+	DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n",			dev->name, (long)bp->rcv_block_virt,	bp->rcv_block_phys);
+	DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n",					dev->name, (long)bp->cons_block_virt,	bp->cons_block_phys);
+
+	return(DFX_K_SUCCESS);
+	}
+
+
+/*
+ * =================
+ * = dfx_adap_init =
+ * =================
+ *   
+ * Overview:
+ *   Brings the adapter to the link avail/link unavailable state.
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Issues the low-level firmware/hardware calls necessary to bring
+ *   the adapter up, or to properly reset and restore adapter during
+ *   run-time.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS - Adapter brought up successfully
+ *   DFX_K_FAILURE - Adapter initialization failed
+ *
+ * Assumptions:
+ *   bp->reset_type should be set to a valid reset type value before
+ *   calling this routine.
+ *
+ * Side Effects:
+ *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
+ *   upon a successful return of this routine.
+ */
+
+int dfx_adap_init(
+	DFX_board_t *bp
+	)
+
+	{
+	DBG_printk("In dfx_adap_init...\n");
+
+	/* Disable PDQ interrupts first */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+
+	/* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
+
+	if (dfx_hw_dma_uninit(bp, bp->reset_type) != DFX_K_SUCCESS)
+		{
+		printk("%s: Could not uninitialize/reset adapter!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/*
+	 * When the PDQ is reset, some false Type 0 interrupts may be pending,
+	 * so we'll acknowledge all Type 0 interrupts now before continuing.
+	 */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, PI_HOST_INT_K_ACK_ALL_TYPE_0);
+
+	/*
+	 * Clear Type 1 and Type 2 registers before going to DMA_AVAILABLE state
+	 *
+	 * Note: We only need to clear host copies of these registers.  The PDQ reset
+	 *       takes care of the on-board register values.
+	 */
+
+	bp->cmd_req_reg.lword	= 0;
+	bp->cmd_rsp_reg.lword	= 0;
+	bp->rcv_xmt_reg.lword	= 0;
+
+	/* Clear consumer block before going to DMA_AVAILABLE state */
+
+	memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
+
+	/* Initialize the DMA Burst Size */
+
+	if (dfx_hw_port_ctrl_req(bp,
+							PI_PCTRL_M_SUB_CMD,
+							PI_SUB_CMD_K_BURST_SIZE_SET,
+							bp->burst_size,
+							NULL) != DFX_K_SUCCESS)
+		{
+		printk("%s: Could not set adapter burst size!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/*
+	 * Set base address of Consumer Block
+	 *
+	 * Assumption: 32-bit physical address of consumer block is 64 byte
+	 *			   aligned.  That is, bits 0-5 of the address must be zero.
+	 */
+
+	if (dfx_hw_port_ctrl_req(bp,
+							PI_PCTRL_M_CONS_BLOCK,
+							bp->cons_block_phys,
+							0,
+							NULL) != DFX_K_SUCCESS)
+		{
+		printk("%s: Could not set consumer block address!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/*
+	 * Set base address of Descriptor Block and bring adapter to DMA_AVAILABLE state
+	 *
+	 * Note: We also set the literal and data swapping requirements in this
+	 *	     command.  Since this driver presently runs on Intel platforms
+	 *		 which are Little Endian, we'll tell the adapter to byte swap
+	 *		 data only.  This code will need to change when we support
+	 *		 Big Endian systems (eg. PowerPC).
+	 *
+	 * Assumption: 32-bit physical address of descriptor block is 8Kbyte
+	 *             aligned.  That is, bits 0-12 of the address must be zero.
+	 */
+
+	if (dfx_hw_port_ctrl_req(bp,
+							PI_PCTRL_M_INIT,
+							(u32) (bp->descr_block_phys | PI_PDATA_A_INIT_M_BSWAP_DATA),
+							0,
+							NULL) != DFX_K_SUCCESS)
+		{
+		printk("%s: Could not set descriptor block address!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/* Set transmit flush timeout value */
+
+	bp->cmd_req_virt->cmd_type = PI_CMD_K_CHARS_SET;
+	bp->cmd_req_virt->char_set.item[0].item_code	= PI_ITEM_K_FLUSH_TIME;
+	bp->cmd_req_virt->char_set.item[0].value		= 3;	/* 3 seconds */
+	bp->cmd_req_virt->char_set.item[0].item_index	= 0;
+	bp->cmd_req_virt->char_set.item[1].item_code	= PI_ITEM_K_EOL;
+	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+		{
+		printk("%s: DMA command request failed!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/* Set the initial values for eFDXEnable and MACTReq MIB objects */
+
+	bp->cmd_req_virt->cmd_type = PI_CMD_K_SNMP_SET;
+	bp->cmd_req_virt->snmp_set.item[0].item_code	= PI_ITEM_K_FDX_ENB_DIS;
+	bp->cmd_req_virt->snmp_set.item[0].value		= bp->full_duplex_enb;
+	bp->cmd_req_virt->snmp_set.item[0].item_index	= 0;
+	bp->cmd_req_virt->snmp_set.item[1].item_code	= PI_ITEM_K_MAC_T_REQ;
+	bp->cmd_req_virt->snmp_set.item[1].value		= bp->req_ttrt;
+	bp->cmd_req_virt->snmp_set.item[1].item_index	= 0;
+	bp->cmd_req_virt->snmp_set.item[2].item_code	= PI_ITEM_K_EOL;
+	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+		{
+		printk("%s: DMA command request failed!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/* Initialize adapter CAM */
+
+	if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
+		{
+		printk("%s: Adapter CAM update failed!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/* Initialize adapter filters */
+
+	if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
+		{
+		printk("%s: Adapter filters update failed!\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/* Initialize receive descriptor block and produce buffers */
+
+	dfx_rcv_init(bp);
+
+	/* Issue START command and bring adapter to LINK_(UN)AVAILABLE state */
+
+	bp->cmd_req_virt->cmd_type = PI_CMD_K_START;
+	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+		{
+		printk("%s: Start command failed\n", bp->dev->name);
+		return(DFX_K_FAILURE);
+		}
+
+	/* Initialization succeeded, reenable PDQ interrupts */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_ENABLE_DEF_INTS);
+	return(DFX_K_SUCCESS);
+	}
+
+
+/*
+ * ============
+ * = dfx_open =
+ * ============
+ *   
+ * Overview:
+ *   Opens the adapter
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This function brings the adapter to an operational state.
+ *
+ * Return Codes:
+ *   0		 - Adapter was successfully opened
+ *   -EAGAIN - Could not register IRQ or adapter initialization failed
+ *
+ * Assumptions:
+ *   This routine should only be called for a device that was
+ *   initialized successfully during the dfx_probe process.
+ *
+ * Side Effects:
+ *   Adapter should be in LINK_AVAILABLE or LINK_UNAVAILABLE state
+ *   if the open is successful.
+ */
+
+int dfx_open(
+	struct device *dev
+	)
+
+	{
+	DFX_board_t	*bp = (DFX_board_t *)dev->priv;
+
+	DBG_printk("In dfx_open...\n");
+
+	/* Register IRQ - support shared interrupts by passing device ptr */
+
+	if (request_irq(dev->irq, (void *)dfx_interrupt, SA_SHIRQ, dev->name, dev))
+		{
+		printk("%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
+		return(-EAGAIN);
+		}
+
+	/*
+	 * Set current address to factory MAC address
+	 *
+	 * Note: We've already done this step in dfx_driver_init.
+	 *       However, it's possible that a user has set a node
+	 *		 address override, then closed and reopened the
+	 *		 adapter.  Unless we reset the device address field
+	 *		 now, we'll continue to use the existing modified
+	 *		 address.
+	 */
+
+	memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
+
+	/* Clear local unicast/multicast address tables and counts */
+
+	memset(bp->uc_table, 0, sizeof(bp->uc_table));
+	memset(bp->mc_table, 0, sizeof(bp->mc_table));
+	bp->uc_count = 0;
+	bp->mc_count = 0;
+
+	/* Disable promiscuous filter settings */
+
+	bp->ind_group_prom	= PI_FSTATE_K_BLOCK;
+	bp->group_prom		= PI_FSTATE_K_BLOCK;
+
+	/* Reset and initialize adapter */
+
+	bp->reset_type = PI_PDATA_A_RESET_M_SKIP_ST;	/* skip self-test */
+	if (dfx_adap_init(bp) != DFX_K_SUCCESS)
+		{
+		printk("%s: Adapter open failed!\n", dev->name);
+		return(-EAGAIN);
+		}
+
+	/* Set device structure info */
+
+	dev->tbusy			= 0;
+	dev->interrupt		= DFX_UNMASK_INTERRUPTS;
+	dev->start			= 1;
+	return(0);
+	}
+
+
+/*
+ * =============
+ * = dfx_close =
+ * =============
+ *   
+ * Overview:
+ *   Closes the device/module.
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This routine closes the adapter and brings it to a safe state.
+ *   The interrupt service routine is deregistered with the OS.
+ *   The adapter can be opened again with another call to dfx_open().
+ *
+ * Return Codes:
+ *   Always return 0.
+ *
+ * Assumptions:
+ *   No further requests for this adapter are made after this routine is
+ *   called.  dfx_open() can be called to reset and reinitialize the
+ *   adapter.
+ *
+ * Side Effects:
+ *   Adapter should be in DMA_UNAVAILABLE state upon completion of this
+ *   routine.
+ */
+
+int dfx_close(
+	struct device *dev
+	)
+
+	{
+	DFX_board_t	*bp = (DFX_board_t *)dev->priv;
+
+	DBG_printk("In dfx_close...\n");
+
+	/* Disable PDQ interrupts first */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+
+	/* Place adapter in DMA_UNAVAILABLE state by resetting adapter */
+
+	(void) dfx_hw_dma_uninit(bp, PI_PDATA_A_RESET_M_SKIP_ST);
+
+	/*
+	 * Flush any pending transmit buffers
+	 *
+	 * Note: It's important that we flush the transmit buffers
+	 *		 BEFORE we clear our copy of the Type 2 register.
+	 *		 Otherwise, we'll have no idea how many buffers
+	 *		 we need to free.
+	 */
+
+	dfx_xmt_flush(bp);
+
+	/*
+	 * Clear Type 1 and Type 2 registers after adapter reset
+	 *
+	 * Note: Even though we're closing the adapter, it's
+	 *       possible that an interrupt will occur after
+	 *		 dfx_close is called.  Without some assurance to
+	 *		 the contrary we want to make sure that we don't
+	 *		 process receive and transmit LLC frames and update
+	 *		 the Type 2 register with bad information.
+	 */
+
+	bp->cmd_req_reg.lword	= 0;
+	bp->cmd_rsp_reg.lword	= 0;
+	bp->rcv_xmt_reg.lword	= 0;
+
+	/* Clear consumer block for the same reason given above */
+
+	memset(bp->cons_block_virt, 0, sizeof(PI_CONSUMER_BLOCK));
+
+	/* Clear device structure flags */
+
+	dev->start = 0;
+	dev->tbusy = 1;
+
+	/* Deregister (free) IRQ */
+
+	free_irq(dev->irq, dev);
+	return(0);
+	}
+
+
+/*
+ * ======================
+ * = dfx_int_pr_halt_id =
+ * ======================
+ *   
+ * Overview:
+ *   Displays halt id's in string form.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Determine current halt id and display appropriate string.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+void dfx_int_pr_halt_id(
+	DFX_board_t	*bp
+	)
+
+	{
+	PI_UINT32	port_status;			/* PDQ port status register value */
+	PI_UINT32	halt_id;				/* PDQ port status halt ID */
+
+	/* Read the latest port status */
+
+	dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
+
+	/* Display halt state transition information */
+
+	halt_id = (port_status & PI_PSTATUS_M_HALT_ID) >> PI_PSTATUS_V_HALT_ID;
+	switch (halt_id)
+		{
+		case PI_HALT_ID_K_SELFTEST_TIMEOUT:
+			printk("%s: Halt ID: Selftest Timeout\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_PARITY_ERROR:
+			printk("%s: Halt ID: Host Bus Parity Error\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_HOST_DIR_HALT:
+			printk("%s: Halt ID: Host-Directed Halt\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_SW_FAULT:
+			printk("%s: Halt ID: Adapter Software Fault\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_HW_FAULT:
+			printk("%s: Halt ID: Adapter Hardware Fault\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_PC_TRACE:
+			printk("%s: Halt ID: FDDI Network PC Trace Path Test\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_DMA_ERROR:
+			printk("%s: Halt ID: Adapter DMA Error\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_IMAGE_CRC_ERROR:
+			printk("%s: Halt ID: Firmware Image CRC Error\n", bp->dev->name);
+			break;
+
+		case PI_HALT_ID_K_BUS_EXCEPTION:
+			printk("%s: Halt ID: 68000 Bus Exception\n", bp->dev->name);
+			break;
+
+		default:
+			printk("%s: Halt ID: Unknown (code = %X)\n", bp->dev->name, halt_id);
+			break;
+		}
+	return;
+	}
+
+
+/*
+ * ==========================
+ * = dfx_int_type_0_process =
+ * ==========================
+ *   
+ * Overview:
+ *   Processes Type 0 interrupts.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Processes all enabled Type 0 interrupts.  If the reason for the interrupt
+ *   is a serious fault on the adapter, then an error message is displayed
+ *   and the adapter is reset.
+ *
+ *   One tricky potential timing window is the rapid succession of "link avail"
+ *   "link unavail" state change interrupts.  The acknowledgement of the Type 0
+ *   interrupt must be done before reading the state from the Port Status
+ *   register.  This is true because a state change could occur after reading
+ *   the data, but before acknowledging the interrupt.  If this state change
+ *   does happen, it would be lost because the driver is using the old state,
+ *   and it will never know about the new state because it subsequently
+ *   acknowledges the state change interrupt.
+ *
+ *          INCORRECT                                      CORRECT
+ *      read type 0 int reasons                   read type 0 int reasons
+ *      read adapter state                        ack type 0 interrupts
+ *      ack type 0 interrupts                     read adapter state
+ *      ... process interrupt ...                 ... process interrupt ...
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   An adapter reset may occur if the adapter has any Type 0 error interrupts
+ *   or if the port status indicates that the adapter is halted.  The driver
+ *   is responsible for reinitializing the adapter with the current CAM
+ *   contents and adapter filter settings.
+ */
+
+void dfx_int_type_0_process(
+	DFX_board_t	*bp
+	)
+
+	{
+	PI_UINT32	type_0_status;		/* Host Interrupt Type 0 register */
+	PI_UINT32	state;				/* current adap state (from port status) */
+
+	/*
+	 * Read host interrupt Type 0 register to determine which Type 0
+	 * interrupts are pending.  Immediately write it back out to clear
+	 * those interrupts.
+	 */
+
+	dfx_port_read_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, &type_0_status);
+	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_0_STATUS, type_0_status);
+
+	/* Check for Type 0 error interrupts */
+
+	if (type_0_status & (PI_TYPE_0_STAT_M_NXM |
+							PI_TYPE_0_STAT_M_PM_PAR_ERR |
+							PI_TYPE_0_STAT_M_BUS_PAR_ERR))
+		{
+		/* Check for Non-Existent Memory error */
+
+		if (type_0_status & PI_TYPE_0_STAT_M_NXM)
+			printk("%s: Non-Existent Memory Access Error\n", bp->dev->name);
+
+		/* Check for Packet Memory Parity error */
+
+		if (type_0_status & PI_TYPE_0_STAT_M_PM_PAR_ERR)
+			printk("%s: Packet Memory Parity Error\n", bp->dev->name);
+
+		/* Check for Host Bus Parity error */
+
+		if (type_0_status & PI_TYPE_0_STAT_M_BUS_PAR_ERR)
+			printk("%s: Host Bus Parity Error\n", bp->dev->name);
+
+		/* Reset adapter and bring it back on-line */
+
+		bp->link_available = PI_K_FALSE;	/* link is no longer available */
+		bp->reset_type = 0;					/* rerun on-board diagnostics */
+		printk("%s: Resetting adapter...\n", bp->dev->name);
+		if (dfx_adap_init(bp) != DFX_K_SUCCESS)
+			{
+			printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
+			dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+			return;
+			}
+		printk("%s: Adapter reset successful!\n", bp->dev->name);
+		return;
+		}
+
+	/* Check for transmit flush interrupt */
+
+	if (type_0_status & PI_TYPE_0_STAT_M_XMT_FLUSH)
+		{
+		/* Flush any pending xmt's and acknowledge the flush interrupt */
+
+		bp->link_available = PI_K_FALSE;		/* link is no longer available */
+		dfx_xmt_flush(bp);						/* flush any outstanding packets */
+		(void) dfx_hw_port_ctrl_req(bp,
+									PI_PCTRL_M_XMT_DATA_FLUSH_DONE,
+									0,
+									0,
+									NULL);
+		}
+
+	/* Check for adapter state change */
+
+	if (type_0_status & PI_TYPE_0_STAT_M_STATE_CHANGE)
+		{                     
+		/* Get latest adapter state */
+
+		state = dfx_hw_adap_state_rd(bp);	/* get adapter state */
+		if (state == PI_STATE_K_HALTED)
+			{
+			/*
+			 * Adapter has transitioned to HALTED state, try to reset
+			 * adapter to bring it back on-line.  If reset fails,
+			 * leave the adapter in the broken state.
+			 */
+
+			printk("%s: Controller has transitioned to HALTED state!\n", bp->dev->name);
+			dfx_int_pr_halt_id(bp);			/* display halt id as string */
+
+			/* Reset adapter and bring it back on-line */
+
+			bp->link_available = PI_K_FALSE;	/* link is no longer available */
+			bp->reset_type = 0;					/* rerun on-board diagnostics */
+			printk("%s: Resetting adapter...\n", bp->dev->name);
+			if (dfx_adap_init(bp) != DFX_K_SUCCESS)
+				{
+				printk("%s: Adapter reset failed!  Disabling adapter interrupts.\n", bp->dev->name);
+				dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
+				return;
+				}
+			printk("%s: Adapter reset successful!\n", bp->dev->name);
+			}
+		else if (state == PI_STATE_K_LINK_AVAIL)
+			{
+			bp->link_available = PI_K_TRUE;		/* set link available flag */
+			}
+		}
+	return;
+	}
+
+
+/*
+ * ==================
+ * = dfx_int_common =
+ * ==================
+ *   
+ * Overview:
+ *   Interrupt service routine (ISR)
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   This is the ISR which processes incoming adapter interrupts.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   This routine assumes PDQ interrupts have not been disabled.
+ *   When interrupts are disabled at the PDQ, the Port Status register
+ *   is automatically cleared.  This routine uses the Port Status
+ *   register value to determine whether a Type 0 interrupt occurred,
+ *   so it's important that adapter interrupts are not normally
+ *   enabled/disabled at the PDQ.
+ *
+ *   It's vital that this routine is NOT reentered for the
+ *   same board and that the OS is not in another section of
+ *   code (eg. dfx_xmt_queue_pkt) for the same board on a
+ *   different thread.
+ *
+ * Side Effects:
+ *   Pending interrupts are serviced.  Depending on the type of
+ *   interrupt, acknowledging and clearing the interrupt at the
+ *   PDQ involves writing a register to clear the interrupt bit
+ *   or updating completion indices.
+ */
+
+void dfx_int_common(
+	DFX_board_t	*bp
+	)
+
+	{
+	PI_UINT32	port_status;		/* Port Status register */
+
+	/* Process xmt interrupts - frequent case, so always call this routine */
+
+	dfx_xmt_done(bp);				/* free consumed xmt packets */
+
+	/* Process rcv interrupts - frequent case, so always call this routine */
+
+	dfx_rcv_queue_process(bp);		/* service received LLC frames */
+
+	/*
+	 * Transmit and receive producer and completion indices are updated on the
+	 * adapter by writing to the Type 2 Producer register.  Since the frequent
+	 * case is that we'll be processing either LLC transmit or receive buffers,
+	 * we'll optimize I/O writes by doing a single register write here.
+	 */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
+
+	/* Read PDQ Port Status register to find out which interrupts need processing */
+
+	dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
+
+	/* Process Type 0 interrupts (if any) - infrequent, so only call when needed */
+
+	if (port_status & PI_PSTATUS_M_TYPE_0_PENDING)
+		dfx_int_type_0_process(bp);	/* process Type 0 interrupts */
+	return;
+	}
+
+
+/*
+ * =================
+ * = dfx_interrupt =
+ * =================
+ *   
+ * Overview:
+ *   Interrupt processing routine
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   irq	- interrupt vector
+ *   dev_id	- pointer to device information
+ *	 regs	- pointer to registers structure
+ *
+ * Functional Description:
+ *   This routine calls the interrupt processing routine for this adapter.  It
+ *   disables and reenables adapter interrupts, as appropriate.  We can support
+ *   shared interrupts since the incoming dev_id pointer provides our device
+ *   structure context.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   The interrupt acknowledgement at the hardware level (eg. ACKing the PIC
+ *   on Intel-based systems) is done by the operating system outside this
+ *   routine.
+ *
+ *	 System interrupts are enabled through this call.
+ *
+ * Side Effects:
+ *   Interrupts are disabled, then reenabled at the adapter.
+ */
+
+void dfx_interrupt(
+	int				irq,
+	void			*dev_id,
+	struct pt_regs	*regs
+	)
+
+	{
+	struct device	*dev = (struct device *) dev_id;
+	DFX_board_t		*bp;	/* private board structure pointer */
+	u8				tmp;	/* used for disabling/enabling ints */
+
+	/* Get board pointer only if device structure is valid */
+
+	if (dev == NULL)
+		{
+		printk("dfx_interrupt(): irq %d for unknown device!\n", irq);
+		return;
+		}
+	bp = (DFX_board_t *) dev->priv;
+
+	/* See if we're already servicing an interrupt */
+
+	if (dev->interrupt)
+		printk("%s: Re-entering the interrupt handler!\n", dev->name);
+	dev->interrupt = DFX_MASK_INTERRUPTS;	/* ensure non reentrancy */
+
+	/* Service adapter interrupts */
+
+	if (bp->bus_type == DFX_BUS_TYPE_PCI)
+		{
+		/* Disable PDQ-PFI interrupts at PFI */
+
+		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, PFI_MODE_M_DMA_ENB);
+
+		/* Call interrupt service routine for this adapter */
+
+		dfx_int_common(bp);
+
+		/* Clear PDQ interrupt status bit and reenable interrupts */
+
+		dfx_port_write_long(bp, PFI_K_REG_STATUS, PFI_STATUS_M_PDQ_INT);
+		dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL,
+					(PFI_MODE_M_PDQ_INT_ENB + PFI_MODE_M_DMA_ENB));
+		}
+	else
+		{
+		/* Disable interrupts at the ESIC */
+
+		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp);
+		tmp &= ~PI_CONFIG_STAT_0_M_INT_ENB;
+		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp);
+
+		/* Call interrupt service routine for this adapter */
+
+		dfx_int_common(bp);
+
+		/* Reenable interrupts at the ESIC */
+
+		dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &tmp);
+		tmp |= PI_CONFIG_STAT_0_M_INT_ENB;
+		dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, tmp);
+		}
+
+	dev->interrupt = DFX_UNMASK_INTERRUPTS;
+	return;
+	}
+
+
+/*
+ * =====================
+ * = dfx_ctl_get_stats =
+ * =====================
+ *   
+ * Overview:
+ *   Get statistics for FDDI adapter
+ *  
+ * Returns:
+ *   Pointer to FDDI statistics structure
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Gets current MIB objects from adapter, then
+ *   returns FDDI statistics structure as defined
+ *   in if_fddi.h.
+ *
+ *   Note: Since the FDDI statistics structure is
+ *   still new and the device structure doesn't
+ *   have an FDDI-specific get statistics handler,
+ *   we'll return the FDDI statistics structure as
+ *   a pointer to an Ethernet statistics structure.
+ *   That way, at least the first part of the statistics
+ *   structure can be decoded properly, and it allows
+ *   "smart" applications to perform a second cast to
+ *   decode the FDDI-specific statistics.
+ *
+ *   We'll have to pay attention to this routine as the
+ *   device structure becomes more mature and LAN media
+ *   independent.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+struct enet_statistics *dfx_ctl_get_stats(
+	struct device *dev
+	)
+
+	{
+	DFX_board_t	*bp = (DFX_board_t *)dev->priv;
+
+	/* Fill the bp->stats structure with driver-maintained counters */
+
+	bp->stats.rx_packets			= bp->rcv_total_frames;
+	bp->stats.tx_packets			= bp->xmt_total_frames;
+	bp->stats.rx_errors				= (u32)(bp->rcv_crc_errors + bp->rcv_frame_status_errors + bp->rcv_length_errors);
+	bp->stats.tx_errors				= bp->xmt_length_errors;
+	bp->stats.rx_dropped			= bp->rcv_discards;
+	bp->stats.tx_dropped			= bp->xmt_discards;
+	bp->stats.multicast				= bp->rcv_multicast_frames;
+	bp->stats.transmit_collision	= 0;	/* always zero (0) for FDDI */
+
+	/* Get FDDI SMT MIB objects */
+
+	bp->cmd_req_virt->cmd_type = PI_CMD_K_SMT_MIB_GET;
+	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+		return((struct enet_statistics *) &bp->stats);
+
+	/* Fill the bp->stats structure with the SMT MIB object values */
+
+	memcpy(bp->stats.smt_station_id, &bp->cmd_rsp_virt->smt_mib_get.smt_station_id, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_station_id));
+	bp->stats.smt_op_version_id					= bp->cmd_rsp_virt->smt_mib_get.smt_op_version_id;
+	bp->stats.smt_hi_version_id					= bp->cmd_rsp_virt->smt_mib_get.smt_hi_version_id;
+	bp->stats.smt_lo_version_id					= bp->cmd_rsp_virt->smt_mib_get.smt_lo_version_id;
+	memcpy(bp->stats.smt_user_data, &bp->cmd_rsp_virt->smt_mib_get.smt_user_data, sizeof(bp->cmd_rsp_virt->smt_mib_get.smt_user_data));
+	bp->stats.smt_mib_version_id				= bp->cmd_rsp_virt->smt_mib_get.smt_mib_version_id;
+	bp->stats.smt_mac_cts						= bp->cmd_rsp_virt->smt_mib_get.smt_mac_ct;
+	bp->stats.smt_non_master_cts				= bp->cmd_rsp_virt->smt_mib_get.smt_non_master_ct;
+	bp->stats.smt_master_cts					= bp->cmd_rsp_virt->smt_mib_get.smt_master_ct;
+	bp->stats.smt_available_paths				= bp->cmd_rsp_virt->smt_mib_get.smt_available_paths;
+	bp->stats.smt_config_capabilities			= bp->cmd_rsp_virt->smt_mib_get.smt_config_capabilities;
+	bp->stats.smt_config_policy					= bp->cmd_rsp_virt->smt_mib_get.smt_config_policy;
+	bp->stats.smt_connection_policy				= bp->cmd_rsp_virt->smt_mib_get.smt_connection_policy;
+	bp->stats.smt_t_notify						= bp->cmd_rsp_virt->smt_mib_get.smt_t_notify;
+	bp->stats.smt_stat_rpt_policy				= bp->cmd_rsp_virt->smt_mib_get.smt_stat_rpt_policy;
+	bp->stats.smt_trace_max_expiration			= bp->cmd_rsp_virt->smt_mib_get.smt_trace_max_expiration;
+	bp->stats.smt_bypass_present				= bp->cmd_rsp_virt->smt_mib_get.smt_bypass_present;
+	bp->stats.smt_ecm_state						= bp->cmd_rsp_virt->smt_mib_get.smt_ecm_state;
+	bp->stats.smt_cf_state						= bp->cmd_rsp_virt->smt_mib_get.smt_cf_state;
+	bp->stats.smt_remote_disconnect_flag		= bp->cmd_rsp_virt->smt_mib_get.smt_remote_disconnect_flag;
+	bp->stats.smt_station_status				= bp->cmd_rsp_virt->smt_mib_get.smt_station_status;
+	bp->stats.smt_peer_wrap_flag				= bp->cmd_rsp_virt->smt_mib_get.smt_peer_wrap_flag;
+	bp->stats.smt_time_stamp					= bp->cmd_rsp_virt->smt_mib_get.smt_msg_time_stamp.ls;
+	bp->stats.smt_transition_time_stamp			= bp->cmd_rsp_virt->smt_mib_get.smt_transition_time_stamp.ls;
+	bp->stats.mac_frame_status_functions		= bp->cmd_rsp_virt->smt_mib_get.mac_frame_status_functions;
+	bp->stats.mac_t_max_capability				= bp->cmd_rsp_virt->smt_mib_get.mac_t_max_capability;
+	bp->stats.mac_tvx_capability				= bp->cmd_rsp_virt->smt_mib_get.mac_tvx_capability;
+	bp->stats.mac_available_paths				= bp->cmd_rsp_virt->smt_mib_get.mac_available_paths;
+	bp->stats.mac_current_path					= bp->cmd_rsp_virt->smt_mib_get.mac_current_path;
+	memcpy(bp->stats.mac_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_upstream_nbr, FDDI_K_ALEN);
+	memcpy(bp->stats.mac_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_downstream_nbr, FDDI_K_ALEN);
+	memcpy(bp->stats.mac_old_upstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_upstream_nbr, FDDI_K_ALEN);
+	memcpy(bp->stats.mac_old_downstream_nbr, &bp->cmd_rsp_virt->smt_mib_get.mac_old_downstream_nbr, FDDI_K_ALEN);
+	bp->stats.mac_dup_address_test				= bp->cmd_rsp_virt->smt_mib_get.mac_dup_address_test;
+	bp->stats.mac_requested_paths				= bp->cmd_rsp_virt->smt_mib_get.mac_requested_paths;
+	bp->stats.mac_downstream_port_type			= bp->cmd_rsp_virt->smt_mib_get.mac_downstream_port_type;
+	memcpy(bp->stats.mac_smt_address, &bp->cmd_rsp_virt->smt_mib_get.mac_smt_address, FDDI_K_ALEN);
+	bp->stats.mac_t_req							= bp->cmd_rsp_virt->smt_mib_get.mac_t_req;
+	bp->stats.mac_t_neg							= bp->cmd_rsp_virt->smt_mib_get.mac_t_neg;
+	bp->stats.mac_t_max							= bp->cmd_rsp_virt->smt_mib_get.mac_t_max;
+	bp->stats.mac_tvx_value						= bp->cmd_rsp_virt->smt_mib_get.mac_tvx_value;
+	bp->stats.mac_frame_error_threshold			= bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_threshold;
+	bp->stats.mac_frame_error_ratio				= bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_ratio;
+	bp->stats.mac_rmt_state						= bp->cmd_rsp_virt->smt_mib_get.mac_rmt_state;
+	bp->stats.mac_da_flag						= bp->cmd_rsp_virt->smt_mib_get.mac_da_flag;
+	bp->stats.mac_una_da_flag					= bp->cmd_rsp_virt->smt_mib_get.mac_unda_flag;
+	bp->stats.mac_frame_error_flag				= bp->cmd_rsp_virt->smt_mib_get.mac_frame_error_flag;
+	bp->stats.mac_ma_unitdata_available			= bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_available;
+	bp->stats.mac_hardware_present				= bp->cmd_rsp_virt->smt_mib_get.mac_hardware_present;
+	bp->stats.mac_ma_unitdata_enable			= bp->cmd_rsp_virt->smt_mib_get.mac_ma_unitdata_enable;
+	bp->stats.path_tvx_lower_bound				= bp->cmd_rsp_virt->smt_mib_get.path_tvx_lower_bound;
+	bp->stats.path_t_max_lower_bound			= bp->cmd_rsp_virt->smt_mib_get.path_t_max_lower_bound;
+	bp->stats.path_max_t_req					= bp->cmd_rsp_virt->smt_mib_get.path_max_t_req;
+	memcpy(bp->stats.path_configuration, &bp->cmd_rsp_virt->smt_mib_get.path_configuration, sizeof(bp->cmd_rsp_virt->smt_mib_get.path_configuration));
+	bp->stats.port_my_type[0]					= bp->cmd_rsp_virt->smt_mib_get.port_my_type[0];
+	bp->stats.port_my_type[1]					= bp->cmd_rsp_virt->smt_mib_get.port_my_type[1];
+	bp->stats.port_neighbor_type[0]				= bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[0];
+	bp->stats.port_neighbor_type[1]				= bp->cmd_rsp_virt->smt_mib_get.port_neighbor_type[1];
+	bp->stats.port_connection_policies[0]		= bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[0];
+	bp->stats.port_connection_policies[1]		= bp->cmd_rsp_virt->smt_mib_get.port_connection_policies[1];
+	bp->stats.port_mac_indicated[0]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[0];
+	bp->stats.port_mac_indicated[1]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_indicated[1];
+	bp->stats.port_current_path[0]				= bp->cmd_rsp_virt->smt_mib_get.port_current_path[0];
+	bp->stats.port_current_path[1]				= bp->cmd_rsp_virt->smt_mib_get.port_current_path[1];
+	memcpy(&bp->stats.port_requested_paths[0*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[0], 3);
+	memcpy(&bp->stats.port_requested_paths[1*3], &bp->cmd_rsp_virt->smt_mib_get.port_requested_paths[1], 3);
+	bp->stats.port_mac_placement[0]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[0];
+	bp->stats.port_mac_placement[1]				= bp->cmd_rsp_virt->smt_mib_get.port_mac_placement[1];
+	bp->stats.port_available_paths[0]			= bp->cmd_rsp_virt->smt_mib_get.port_available_paths[0];
+	bp->stats.port_available_paths[1]			= bp->cmd_rsp_virt->smt_mib_get.port_available_paths[1];
+	bp->stats.port_pmd_class[0]					= bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[0];
+	bp->stats.port_pmd_class[1]					= bp->cmd_rsp_virt->smt_mib_get.port_pmd_class[1];
+	bp->stats.port_connection_capabilities[0]	= bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[0];
+	bp->stats.port_connection_capabilities[1]	= bp->cmd_rsp_virt->smt_mib_get.port_connection_capabilities[1];
+	bp->stats.port_bs_flag[0]					= bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[0];
+	bp->stats.port_bs_flag[1]					= bp->cmd_rsp_virt->smt_mib_get.port_bs_flag[1];
+	bp->stats.port_ler_estimate[0]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[0];
+	bp->stats.port_ler_estimate[1]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_estimate[1];
+	bp->stats.port_ler_cutoff[0]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[0];
+	bp->stats.port_ler_cutoff[1]				= bp->cmd_rsp_virt->smt_mib_get.port_ler_cutoff[1];
+	bp->stats.port_ler_alarm[0]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[0];
+	bp->stats.port_ler_alarm[1]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_alarm[1];
+	bp->stats.port_connect_state[0]				= bp->cmd_rsp_virt->smt_mib_get.port_connect_state[0];
+	bp->stats.port_connect_state[1]				= bp->cmd_rsp_virt->smt_mib_get.port_connect_state[1];
+	bp->stats.port_pcm_state[0]					= bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[0];
+	bp->stats.port_pcm_state[1]					= bp->cmd_rsp_virt->smt_mib_get.port_pcm_state[1];
+	bp->stats.port_pc_withhold[0]				= bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[0];
+	bp->stats.port_pc_withhold[1]				= bp->cmd_rsp_virt->smt_mib_get.port_pc_withhold[1];
+	bp->stats.port_ler_flag[0]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[0];
+	bp->stats.port_ler_flag[1]					= bp->cmd_rsp_virt->smt_mib_get.port_ler_flag[1];
+	bp->stats.port_hardware_present[0]			= bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[0];
+	bp->stats.port_hardware_present[1]			= bp->cmd_rsp_virt->smt_mib_get.port_hardware_present[1];
+
+	/* Get FDDI counters */
+
+	bp->cmd_req_virt->cmd_type = PI_CMD_K_CNTRS_GET;
+	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+		return((struct enet_statistics *) &bp->stats);
+
+	/* Fill the bp->stats structure with the FDDI counter values */
+
+	bp->stats.mac_frame_cts				= bp->cmd_rsp_virt->cntrs_get.cntrs.frame_cnt.ls;
+	bp->stats.mac_copied_cts			= bp->cmd_rsp_virt->cntrs_get.cntrs.copied_cnt.ls;
+	bp->stats.mac_transmit_cts			= bp->cmd_rsp_virt->cntrs_get.cntrs.transmit_cnt.ls;
+	bp->stats.mac_error_cts				= bp->cmd_rsp_virt->cntrs_get.cntrs.error_cnt.ls;
+	bp->stats.mac_lost_cts				= bp->cmd_rsp_virt->cntrs_get.cntrs.lost_cnt.ls;
+	bp->stats.port_lct_fail_cts[0]		= bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[0].ls;
+	bp->stats.port_lct_fail_cts[1]		= bp->cmd_rsp_virt->cntrs_get.cntrs.lct_rejects[1].ls;
+	bp->stats.port_lem_reject_cts[0]	= bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[0].ls;
+	bp->stats.port_lem_reject_cts[1]	= bp->cmd_rsp_virt->cntrs_get.cntrs.lem_rejects[1].ls;
+	bp->stats.port_lem_cts[0]			= bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[0].ls;
+	bp->stats.port_lem_cts[1]			= bp->cmd_rsp_virt->cntrs_get.cntrs.link_errors[1].ls;
+
+	return((struct enet_statistics *) &bp->stats);
+	}
+
+
+/*
+ * ==============================
+ * = dfx_ctl_set_multicast_list =
+ * ==============================
+ *   
+ * Overview:
+ *   Enable/Disable LLC frame promiscuous mode reception
+ *   on the adapter and/or update multicast address table.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   This routine follows a fairly simple algorithm for setting the
+ *   adapter filters and CAM:
+ *
+ *		if IFF_PROMISC flag is set
+ *			enable LLC individual/group promiscuous mode
+ *		else
+ *			disable LLC individual/group promiscuous mode
+ *			if number of incoming multicast addresses >
+ *					(CAM max size - number of unicast addresses in CAM)
+ *				enable LLC group promiscuous mode
+ *				set driver-maintained multicast address count to zero
+ *			else
+ *				disable LLC group promiscuous mode
+ *				set driver-maintained multicast address count to incoming count
+ *			update adapter CAM
+ *		update adapter filters
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   Multicast addresses are presented in canonical (LSB) format.
+ *
+ * Side Effects:
+ *   On-board adapter CAM and filters are updated.
+ */
+
+void dfx_ctl_set_multicast_list(
+	struct device *dev
+	)
+
+	{
+	DFX_board_t			*bp = (DFX_board_t *)dev->priv;
+	int					i;			/* used as index in for loop */
+	struct dev_mc_list	*dmi;		/* ptr to multicast addr entry */
+
+	/* Enable LLC frame promiscuous mode, if necessary */
+
+	if (dev->flags & IFF_PROMISC)
+		bp->ind_group_prom = PI_FSTATE_K_PASS;		/* Enable LLC ind/group prom mode */
+
+	/* Else, update multicast address table */
+
+	else
+		{
+		bp->ind_group_prom = PI_FSTATE_K_BLOCK;		/* Disable LLC ind/group prom mode */
+		/*
+		 * Check whether incoming multicast address count exceeds table size
+		 *
+		 * Note: The adapters utilize an on-board 64 entry CAM for
+		 *       supporting perfect filtering of multicast packets
+		 *		 and bridge functions when adding unicast addresses.
+		 *		 There is no hash function available.  To support
+		 *		 additional multicast addresses, the all multicast
+		 *		 filter (LLC group promiscuous mode) must be enabled.
+		 *
+		 *		 The firmware reserves two CAM entries for SMT-related
+		 *		 multicast addresses, which leaves 62 entries available.
+		 *		 The following code ensures that we're not being asked
+		 *		 to add more than 62 addresses to the CAM.  If we are,
+		 *		 the driver will enable the all multicast filter.
+		 *		 Should the number of multicast addresses drop below
+		 *		 the high water mark, the filter will be disabled and
+		 *		 perfect filtering will be used.
+		 */
+
+		if (dev->mc_count > (PI_CMD_ADDR_FILTER_K_SIZE - bp->uc_count))
+			{
+			bp->group_prom	= PI_FSTATE_K_PASS;		/* Enable LLC group prom mode */
+			bp->mc_count	= 0;					/* Don't add mc addrs to CAM */
+			}
+		else
+			{
+			bp->group_prom	= PI_FSTATE_K_BLOCK;	/* Disable LLC group prom mode */
+			bp->mc_count	= dev->mc_count;		/* Add mc addrs to CAM */
+			}
+
+		/* Copy addresses to multicast address table, then update adapter CAM */
+
+		dmi = dev->mc_list;				/* point to first multicast addr */
+		for (i=0; i < bp->mc_count; i++)
+			{
+			memcpy(&bp->mc_table[i*FDDI_K_ALEN], dmi->dmi_addr, FDDI_K_ALEN);
+			dmi = dmi->next;			/* point to next multicast addr */
+			}
+		if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
+			{
+			DBG_printk("%s: Could not update multicast address table!\n", dev->name);
+			}
+		else
+			{
+			DBG_printk("%s: Multicast address table updated!  Added %d addresses.\n", dev->name, bp->mc_count);
+			}
+		}
+
+	/* Update adapter filters */
+
+	if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
+		{
+		DBG_printk("%s: Could not update adapter filters!\n", dev->name);
+		}
+	else
+		{
+		DBG_printk("%s: Adapter filters updated!\n", dev->name);
+		}
+	return;
+	}
+
+
+/*
+ * ===========================
+ * = dfx_ctl_set_mac_address =
+ * ===========================
+ *   
+ * Overview:
+ *   Add node address override (unicast address) to adapter
+ *   CAM and update dev_addr field in device table.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   dev  - pointer to device information
+ *   addr - pointer to sockaddr structure containing unicast address to add
+ *
+ * Functional Description:
+ *   The adapter supports node address overrides by adding one or more
+ *   unicast addresses to the adapter CAM.  This is similar to adding
+ *   multicast addresses.  In this routine we'll update the driver and
+ *   device structures with the new address, then update the adapter CAM
+ *   to ensure that the adapter will copy and strip frames destined and
+ *   sourced by that address.
+ *
+ * Return Codes:
+ *   Always returns zero.
+ *
+ * Assumptions:
+ *   The address pointed to by addr->sa_data is a valid unicast
+ *   address and is presented in canonical (LSB) format.
+ *
+ * Side Effects:
+ *   On-board adapter CAM is updated.  On-board adapter filters
+ *   may be updated.
+ */
+
+int dfx_ctl_set_mac_address(
+	struct device	*dev,
+	void			*addr
+	)
+
+	{
+	DFX_board_t		*bp = (DFX_board_t *)dev->priv;
+	struct sockaddr	*p_sockaddr = (struct sockaddr *)addr;
+
+	/* Copy unicast address to driver-maintained structs and update count */
+
+	memcpy(dev->dev_addr, p_sockaddr->sa_data, FDDI_K_ALEN);	/* update device struct */
+	memcpy(&bp->uc_table[0], p_sockaddr->sa_data, FDDI_K_ALEN);	/* update driver struct */
+	bp->uc_count = 1;
+
+	/*
+	 * Verify we're not exceeding the CAM size by adding unicast address
+	 *
+	 * Note: It's possible that before entering this routine we've
+	 *       already filled the CAM with 62 multicast addresses.
+	 *		 Since we need to place the node address override into
+	 *		 the CAM, we have to check to see that we're not
+	 *		 exceeding the CAM size.  If we are, we have to enable
+	 *		 the LLC group (multicast) promiscuous mode filter as
+	 *		 in dfx_ctl_set_multicast_list.
+	 */
+
+	if ((bp->uc_count + bp->mc_count) > PI_CMD_ADDR_FILTER_K_SIZE)
+		{
+		bp->group_prom	= PI_FSTATE_K_PASS;		/* Enable LLC group prom mode */
+		bp->mc_count	= 0;					/* Don't add mc addrs to CAM */
+
+		/* Update adapter filters */
+
+		if (dfx_ctl_update_filters(bp) != DFX_K_SUCCESS)
+			{
+			DBG_printk("%s: Could not update adapter filters!\n", dev->name);
+			}
+		else
+			{
+			DBG_printk("%s: Adapter filters updated!\n", dev->name);
+			}
+		}
+
+	/* Update adapter CAM with new unicast address */
+
+	if (dfx_ctl_update_cam(bp) != DFX_K_SUCCESS)
+		{
+		DBG_printk("%s: Could not set new MAC address!\n", dev->name);
+		}
+	else
+		{
+		DBG_printk("%s: Adapter CAM updated with new MAC address\n", dev->name);
+		}
+	return(0);			/* always return zero */
+	}
+
+
+/*
+ * ======================
+ * = dfx_ctl_update_cam =
+ * ======================
+ *
+ * Overview:
+ *   Procedure to update adapter CAM (Content Addressable Memory)
+ *   with desired unicast and multicast address entries.
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Updates adapter CAM with current contents of board structure
+ *   unicast and multicast address tables.  Since there are only 62
+ *   free entries in CAM, this routine ensures that the command
+ *   request buffer is not overrun.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS - Request succeeded
+ *   DFX_K_FAILURE - Request failed
+ *
+ * Assumptions:
+ *   All addresses being added (unicast and multicast) are in canonical
+ *   order.
+ *
+ * Side Effects:
+ *   On-board adapter CAM is updated.
+ */
+
+int dfx_ctl_update_cam(
+	DFX_board_t *bp
+	)
+
+	{
+	int			i;				/* used as index */
+	PI_LAN_ADDR	*p_addr;		/* pointer to CAM entry */
+
+	/*
+	 * Fill in command request information
+	 *
+	 * Note: Even though both the unicast and multicast address
+	 *       table entries are stored as contiguous 6 byte entries,
+	 *		 the firmware address filter set command expects each
+	 *		 entry to be two longwords (8 bytes total).  We must be
+	 *		 careful to only copy the six bytes of each unicast and
+	 *		 multicast table entry into each command entry.  This
+	 *		 is also why we must first clear the entire command
+	 *		 request buffer.
+	 */
+
+	memset(bp->cmd_req_virt, 0, PI_CMD_REQ_K_SIZE_MAX);	/* first clear buffer */
+	bp->cmd_req_virt->cmd_type = PI_CMD_K_ADDR_FILTER_SET;
+	p_addr = &bp->cmd_req_virt->addr_filter_set.entry[0];
+
+	/* Now add unicast addresses to command request buffer, if any */
+
+	for (i=0; i < (int)bp->uc_count; i++)
+		{
+		if (i < PI_CMD_ADDR_FILTER_K_SIZE)
+			{
+			memcpy(p_addr, &bp->uc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
+			p_addr++;			/* point to next command entry */
+			}
+		}
+
+	/* Now add multicast addresses to command request buffer, if any */
+
+	for (i=0; i < (int)bp->mc_count; i++)
+		{
+		if ((i + bp->uc_count) < PI_CMD_ADDR_FILTER_K_SIZE)
+			{
+			memcpy(p_addr, &bp->mc_table[i*FDDI_K_ALEN], FDDI_K_ALEN);
+			p_addr++;			/* point to next command entry */
+			}
+		}
+
+	/* Issue command to update adapter CAM, then return */
+
+	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+		return(DFX_K_FAILURE);
+	return(DFX_K_SUCCESS);
+	}
+
+
+/*
+ * ==========================
+ * = dfx_ctl_update_filters =
+ * ==========================
+ *
+ * Overview:
+ *   Procedure to update adapter filters with desired
+ *   filter settings.
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Enables or disables filter using current filter settings.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS - Request succeeded.
+ *   DFX_K_FAILURE - Request failed.
+ *
+ * Assumptions:
+ *   We must always pass up packets destined to the broadcast
+ *   address (FF-FF-FF-FF-FF-FF), so we'll always keep the
+ *   broadcast filter enabled.
+ *
+ * Side Effects:
+ *   On-board adapter filters are updated.
+ */
+
+int dfx_ctl_update_filters(
+	DFX_board_t *bp
+	)
+
+	{
+	int	i = 0;					/* used as index */
+
+	/* Fill in command request information */
+
+	bp->cmd_req_virt->cmd_type = PI_CMD_K_FILTERS_SET;
+
+	/* Initialize Broadcast filter - * ALWAYS ENABLED * */
+
+	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_BROADCAST;
+	bp->cmd_req_virt->filter_set.item[i++].value	= PI_FSTATE_K_PASS;
+
+	/* Initialize LLC Individual/Group Promiscuous filter */
+
+	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_IND_GROUP_PROM;
+	bp->cmd_req_virt->filter_set.item[i++].value	= bp->ind_group_prom;
+
+	/* Initialize LLC Group Promiscuous filter */
+
+	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_GROUP_PROM;
+	bp->cmd_req_virt->filter_set.item[i++].value	= bp->group_prom;
+
+	/* Terminate the item code list */
+
+	bp->cmd_req_virt->filter_set.item[i].item_code	= PI_ITEM_K_EOL;
+
+	/* Issue command to update adapter filters, then return */
+
+	if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
+		return(DFX_K_FAILURE);
+	return(DFX_K_SUCCESS);
+	}
+
+
+/*
+ * ======================
+ * = dfx_hw_dma_cmd_req =
+ * ======================
+ *   
+ * Overview:
+ *   Sends PDQ DMA command to adapter firmware
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   The command request and response buffers are posted to the adapter in the manner
+ *   described in the PDQ Port Specification:
+ *
+ *		1. Command Response Buffer is posted to adapter.
+ *		2. Command Request Buffer is posted to adapter.
+ *		3. Command Request consumer index is polled until it indicates that request
+ *         buffer has been DMA'd to adapter.
+ *		4. Command Response consumer index is polled until it indicates that response
+ *         buffer has been DMA'd from adapter.
+ *
+ *   This ordering ensures that a response buffer is already available for the firmware
+ *   to use once it's done processing the request buffer.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS	  - DMA command succeeded
+ * 	 DFX_K_OUTSTATE   - Adapter is NOT in proper state
+ *   DFX_K_HW_TIMEOUT - DMA command timed out
+ *
+ * Assumptions:
+ *   Command request buffer has already been filled with desired DMA command.
+ *
+ * Side Effects:
+ *   None
+ */
+
+int dfx_hw_dma_cmd_req(
+	DFX_board_t *bp
+	)
+
+	{
+	int status;			/* adapter status */
+	int timeout_cnt;	/* used in for loops */
+	
+	/* Make sure the adapter is in a state that we can issue the DMA command in */
+	
+	status = dfx_hw_adap_state_rd(bp);
+	if ((status == PI_STATE_K_RESET)		||
+		(status == PI_STATE_K_HALTED)		||
+		(status == PI_STATE_K_DMA_UNAVAIL)	||
+		(status == PI_STATE_K_UPGRADE))
+		return(DFX_K_OUTSTATE);
+
+	/* Put response buffer on the command response queue */
+
+	bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
+			((PI_CMD_RSP_K_SIZE_MAX / PI_ALIGN_K_CMD_RSP_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
+	bp->descr_block_virt->cmd_rsp[bp->cmd_rsp_reg.index.prod].long_1 = bp->cmd_rsp_phys;
+
+	/* Bump (and wrap) the producer index and write out to register */
+
+	bp->cmd_rsp_reg.index.prod += 1;
+	bp->cmd_rsp_reg.index.prod &= PI_CMD_RSP_K_NUM_ENTRIES-1;
+	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
+
+	/* Put request buffer on the command request queue */
+	
+	bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_0 = (u32) (PI_XMT_DESCR_M_SOP |
+			PI_XMT_DESCR_M_EOP | (PI_CMD_REQ_K_SIZE_MAX << PI_XMT_DESCR_V_SEG_LEN));
+	bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_1 = bp->cmd_req_phys;
+
+	/* Bump (and wrap) the producer index and write out to register */
+
+	bp->cmd_req_reg.index.prod += 1;
+	bp->cmd_req_reg.index.prod &= PI_CMD_REQ_K_NUM_ENTRIES-1;
+	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
+
+	/*
+	 * Here we wait for the command request consumer index to be equal
+	 * to the producer, indicating that the adapter has DMAed the request.
+	 */
+
+	for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
+		{
+		if (bp->cmd_req_reg.index.prod == (u8)(bp->cons_block_virt->cmd_req))
+			break;
+		udelay(100);			/* wait for 100 microseconds */
+		}
+	if (timeout_cnt == 0) 
+		return(DFX_K_HW_TIMEOUT);
+
+	/* Bump (and wrap) the completion index and write out to register */
+
+	bp->cmd_req_reg.index.comp += 1;
+	bp->cmd_req_reg.index.comp &= PI_CMD_REQ_K_NUM_ENTRIES-1;
+	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_REQ_PROD, bp->cmd_req_reg.lword);
+
+	/*
+	 * Here we wait for the command response consumer index to be equal
+	 * to the producer, indicating that the adapter has DMAed the response.
+	 */
+
+	for (timeout_cnt = 20000; timeout_cnt > 0; timeout_cnt--)
+		{
+		if (bp->cmd_rsp_reg.index.prod == (u8)(bp->cons_block_virt->cmd_rsp))
+			break;
+		udelay(100);			/* wait for 100 microseconds */
+		}
+	if (timeout_cnt == 0) 
+		return(DFX_K_HW_TIMEOUT);
+
+	/* Bump (and wrap) the completion index and write out to register */
+
+	bp->cmd_rsp_reg.index.comp += 1;
+	bp->cmd_rsp_reg.index.comp &= PI_CMD_RSP_K_NUM_ENTRIES-1;
+	dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
+	return(DFX_K_SUCCESS);
+	}
+
+
+/*
+ * ========================
+ * = dfx_hw_port_ctrl_req =
+ * ========================
+ *   
+ * Overview:
+ *   Sends PDQ port control command to adapter firmware
+ *  
+ * Returns:
+ *   Host data register value in host_data if ptr is not NULL
+ *       
+ * Arguments:
+ *   bp			- pointer to board information
+ *	 command	- port control command
+ *	 data_a		- port data A register value
+ *	 data_b		- port data B register value
+ *	 host_data	- ptr to host data register value
+ *
+ * Functional Description:
+ *   Send generic port control command to adapter by writing
+ *   to various PDQ port registers, then polling for completion.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS	  - port control command succeeded
+ *   DFX_K_HW_TIMEOUT - port control command timed out
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+int dfx_hw_port_ctrl_req(
+	DFX_board_t	*bp,
+	PI_UINT32	command,
+	PI_UINT32	data_a,
+	PI_UINT32	data_b,
+	PI_UINT32	*host_data
+	)
+
+	{
+	PI_UINT32	port_cmd;		/* Port Control command register value */
+	int			timeout_cnt;	/* used in for loops */
+
+	/* Set Command Error bit in command longword */
+	
+	port_cmd = (PI_UINT32) (command | PI_PCTRL_M_CMD_ERROR);
+
+	/* Issue port command to the adapter */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, data_a);
+	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_B, data_b);
+	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_CTRL, port_cmd);
+
+	/* Now wait for command to complete */
+
+	if (command == PI_PCTRL_M_BLAST_FLASH)
+		timeout_cnt = 600000;	/* set command timeout count to 60 seconds */
+	else
+		timeout_cnt = 20000;	/* set command timeout count to 2 seconds */
+
+	for (; timeout_cnt > 0; timeout_cnt--)
+		{
+		dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_CTRL, &port_cmd);
+		if (!(port_cmd & PI_PCTRL_M_CMD_ERROR))
+			break;
+		udelay(100);			/* wait for 100 microseconds */
+		}
+	if (timeout_cnt == 0) 
+		return(DFX_K_HW_TIMEOUT);
+
+	/*
+	 * If the address of host_data is non-zero, assume caller has supplied a  
+	 * non NULL pointer, and return the contents of the HOST_DATA register in 
+	 * it.
+	 */
+
+	if (host_data != NULL)
+		dfx_port_read_long(bp, PI_PDQ_K_REG_HOST_DATA, host_data);
+	return(DFX_K_SUCCESS);
+	}
+
+
+/*
+ * =====================
+ * = dfx_hw_adap_reset =
+ * =====================
+ *   
+ * Overview:
+ *   Resets adapter
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp   - pointer to board information
+ *   type - type of reset to perform
+ *
+ * Functional Description:
+ *   Issue soft reset to adapter by writing to PDQ Port Reset
+ *   register.  Use incoming reset type to tell adapter what
+ *   kind of reset operation to perform.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   This routine merely issues a soft reset to the adapter.
+ *   It is expected that after this routine returns, the caller
+ *   will appropriately poll the Port Status register for the
+ *   adapter to enter the proper state.
+ *
+ * Side Effects:
+ *   Internal adapter registers are cleared.
+ */
+
+void dfx_hw_adap_reset(
+	DFX_board_t	*bp,
+	PI_UINT32	type
+	)
+
+	{
+	/* Set Reset type and assert reset */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_DATA_A, type);	/* tell adapter type of reset */
+	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, PI_RESET_M_ASSERT_RESET);
+
+	/* Wait for at least 1 Microsecond according to the spec. We wait 20 just to be safe */
+
+	udelay(20);
+
+	/* Deassert reset */
+
+	dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, 0);
+	return;
+	}
+
+
+/*
+ * ========================
+ * = dfx_hw_adap_state_rd =
+ * ========================
+ *   
+ * Overview:
+ *   Returns current adapter state
+ *  
+ * Returns:
+ *   Adapter state per PDQ Port Specification
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Reads PDQ Port Status register and returns adapter state.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+int dfx_hw_adap_state_rd(
+	DFX_board_t *bp
+	)
+
+	{
+	PI_UINT32 port_status;		/* Port Status register value */
+
+	dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &port_status);
+	return((port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE);
+	}
+
+
+/*
+ * =====================
+ * = dfx_hw_dma_uninit =
+ * =====================
+ *   
+ * Overview:
+ *   Brings adapter to DMA_UNAVAILABLE state
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   bp   - pointer to board information
+ *   type - type of reset to perform
+ *
+ * Functional Description:
+ *   Bring adapter to DMA_UNAVAILABLE state by performing the following:
+ *		1. Set reset type bit in Port Data A Register then reset adapter.
+ *		2. Check that adapter is in DMA_UNAVAILABLE state.
+ *
+ * Return Codes:
+ *   DFX_K_SUCCESS	  - adapter is in DMA_UNAVAILABLE state
+ *   DFX_K_HW_TIMEOUT - adapter did not reset properly
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   Internal adapter registers are cleared.
+ */
+
+int dfx_hw_dma_uninit(
+	DFX_board_t	*bp,
+	PI_UINT32	type
+	)
+
+	{
+	int timeout_cnt;	/* used in for loops */
+
+	/* Set reset type bit and reset adapter */
+
+	dfx_hw_adap_reset(bp, type);
+
+	/* Now wait for adapter to enter DMA_UNAVAILABLE state */
+
+	for (timeout_cnt = 100000; timeout_cnt > 0; timeout_cnt--)
+		{
+		if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_DMA_UNAVAIL)
+			break;
+		udelay(100);					/* wait for 100 microseconds */
+		}
+	if (timeout_cnt == 0) 
+		return(DFX_K_HW_TIMEOUT);
+	return(DFX_K_SUCCESS);
+	}
+
+
+/*
+ * ================
+ * = dfx_rcv_init =
+ * ================
+ *   
+ * Overview:
+ *   Produces buffers to adapter LLC Host receive descriptor block
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   This routine can be called during dfx_adap_init() or during an adapter
+ *	 reset.  It initializes the descriptor block and produces all allocated
+ *   LLC Host queue receive buffers.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   The PDQ has been reset and the adapter and driver maintained Type 2
+ *   register indices are cleared.
+ *
+ * Side Effects:
+ *   Receive buffers are posted to the adapter LLC queue and the adapter
+ *   is notified.
+ */
+
+void dfx_rcv_init(
+	DFX_board_t *bp
+	)
+
+	{
+	int	i, j;					/* used in for loop */
+
+	/*
+	 *  Since each receive buffer is a single fragment of same length, initialize
+	 *  first longword in each receive descriptor for entire LLC Host descriptor
+	 *  block.  Also initialize second longword in each receive descriptor with
+	 *  physical address of receive buffer.  We'll always allocate receive
+	 *  buffers in powers of 2 so that we can easily fill the 256 entry descriptor
+	 *  block and produce new receive buffers by simply updating the receive
+	 *  producer index.
+	 *
+	 * 	Assumptions:
+	 *		To support all shipping versions of PDQ, the receive buffer size
+	 *		must be mod 128 in length and the physical address must be 128 byte
+	 *		aligned.  In other words, bits 0-6 of the length and address must
+	 *		be zero for the following descriptor field entries to be correct on
+	 *		all PDQ-based boards.  We guaranteed both requirements during
+	 *		driver initialization when we allocated memory for the receive buffers.
+	 */
+
+	for (i=0; i < (int)(bp->rcv_bufs_to_post); i++)
+		for (j=0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
+			{
+			bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
+				((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN));
+			bp->descr_block_virt->rcv_data[i+j].long_1 = (u32) (bp->rcv_block_phys + (i * PI_RCV_DATA_K_SIZE_MAX));
+			bp->p_rcv_buff_va[i+j] = (char *) (bp->rcv_block_virt + (i * PI_RCV_DATA_K_SIZE_MAX));
+			}
+
+	/* Update receive producer and Type 2 register */
+
+	bp->rcv_xmt_reg.index.rcv_prod = bp->rcv_bufs_to_post;
+	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
+	return;
+	}
+
+
+/*
+ * =========================
+ * = dfx_rcv_queue_process =
+ * =========================
+ *   
+ * Overview:
+ *   Process received LLC frames.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   Received LLC frames are processed until there are no more consumed frames.
+ *   Once all frames are processed, the receive buffers are returned to the
+ *   adapter.  Note that this algorithm fixes the length of time that can be spent
+ *   in this routine, because there are a fixed number of receive buffers to
+ *   process and buffers are not produced until this routine exits and returns
+ *   to the ISR.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   None
+ *
+ * Side Effects:
+ *   None
+ */
+
+void dfx_rcv_queue_process(
+	DFX_board_t *bp
+	)
+
+	{
+	PI_TYPE_2_CONSUMER	*p_type_2_cons;		/* ptr to rcv/xmt consumer block register */
+	char				*p_buff;			/* ptr to start of packet receive buffer (FMC descriptor) */
+	u32					descr, pkt_len;		/* FMC descriptor field and packet length */
+	struct sk_buff		*skb;				/* pointer to a sk_buff to hold incoming packet data */
+
+	/* Service all consumed LLC receive frames */
+
+	p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
+	while (bp->rcv_xmt_reg.index.rcv_comp != p_type_2_cons->index.rcv_cons)
+		{
+		/* Process any errors */
+
+		p_buff = (char *) bp->p_rcv_buff_va[bp->rcv_xmt_reg.index.rcv_comp];
+		memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32));
+
+		if (descr & PI_FMC_DESCR_M_RCC_FLUSH)
+			{
+			if (descr & PI_FMC_DESCR_M_RCC_CRC)
+				bp->rcv_crc_errors++;
+			else
+				bp->rcv_frame_status_errors++;
+			}
+		else
+			{
+			/* The frame was received without errors - verify packet length */
+
+			pkt_len = (u32)((descr & PI_FMC_DESCR_M_LEN) >> PI_FMC_DESCR_V_LEN);
+			pkt_len -= 4;				/* subtract 4 byte CRC */
+			if (!IN_RANGE(pkt_len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
+				bp->rcv_length_errors++;
+			else
+				{
+				skb = dev_alloc_skb(pkt_len+3);	/* alloc new buffer to pass up, add room for PRH */
+				if (skb == NULL)
+					{
+					printk("%s: Could not allocate receive buffer.  Dropping packet.\n", bp->dev->name);
+					bp->rcv_discards++;
+					}
+				else
+					{
+					/* Receive buffer allocated, pass receive packet up */
+
+					memcpy(skb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3);
+					skb->data += 3;			/* adjust data field so that it points to FC byte */
+					skb->len = pkt_len;		/* pass up packet length, NOT including CRC */
+					skb->dev = bp->dev;		/* pass up device pointer */
+					skb->protocol = fddi_type_trans(skb, bp->dev);
+					netif_rx(skb);
+
+					/* Update the rcv counters */
+
+					bp->rcv_total_frames++;
+					if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
+						bp->rcv_multicast_frames++;
+					}
+				}
+			}
+
+		/*
+		 * Advance the producer (for recycling) and advance the completion
+		 * (for servicing received frames).  Note that it is okay to
+		 * advance the producer without checking that it passes the
+		 * completion index because they are both advanced at the same
+		 * rate.
+		 */
+
+		bp->rcv_xmt_reg.index.rcv_prod += 1;
+		bp->rcv_xmt_reg.index.rcv_comp += 1;
+		}
+	return;
+	}
+
+
+/*
+ * =====================
+ * = dfx_xmt_queue_pkt =
+ * =====================
+ *   
+ * Overview:
+ *   Queues packets for transmission
+ *  
+ * Returns:
+ *   Condition code
+ *       
+ * Arguments:
+ *   skb - pointer to sk_buff to queue for transmission
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Here we assume that an incoming skb transmit request
+ *   is contained in a single physically contiguous buffer
+ *   in which the virtual address of the start of packet
+ *   (skb->data) can be converted to a physical address
+ *   by using virt_to_bus().
+ *
+ *   Since the adapter architecture requires a three byte
+ *   packet request header to prepend the start of packet,
+ *   we'll write the three byte field immediately prior to
+ *   the FC byte.  This assumption is valid because we've
+ *   ensured that dev->hard_header_len includes three pad
+ *   bytes.  By posting a single fragment to the adapter,
+ *   we'll reduce the number of descriptor fetches and
+ *   bus traffic needed to send the request.
+ *
+ *   Also, we can't free the skb until after it's been DMA'd
+ *   out by the adapter, so we'll queue it in the driver and
+ *   return it in dfx_xmt_done.
+ *
+ * Return Codes:
+ *   0 - driver queued packet, link is unavailable, or skbuff was bad
+ *	 1 - caller should requeue the sk_buff for later transmission
+ *
+ * Assumptions:
+ *	 First and foremost, we assume the incoming skb pointer
+ *   is NOT NULL and is pointing to a valid sk_buff structure.
+ *
+ *   The outgoing packet is complete, starting with the
+ *   frame control byte including the last byte of data,
+ *   but NOT including the 4 byte CRC.  We'll let the
+ *   adapter hardware generate and append the CRC.
+ *
+ *   The entire packet is stored in one physically
+ *   contiguous buffer which is not cached and whose
+ *   32-bit physical address can be determined.
+ *
+ *   It's vital that this routine is NOT reentered for the
+ *   same board and that the OS is not in another section of
+ *   code (eg. dfx_int_common) for the same board on a
+ *   different thread.
+ *
+ * Side Effects:
+ *   None
+ */
+
+int dfx_xmt_queue_pkt(
+	struct sk_buff	*skb,
+	struct device	*dev
+	)
+
+	{
+	DFX_board_t			*bp = (DFX_board_t *) dev->priv;
+	u8					prod;				/* local transmit producer index */
+	PI_XMT_DESCR		*p_xmt_descr;		/* ptr to transmit descriptor block entry */
+	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
+
+	/*
+	 * Verify that incoming transmit request is OK
+	 *
+	 * Note: The packet size check is consistent with other
+	 *		 Linux device drivers, although the correct packet
+	 *		 size should be verified before calling the
+	 *		 transmit routine.
+	 */
+
+	if (!IN_RANGE(skb->len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
+		{
+		printk("%s: Invalid packet length - %lu bytes\n", dev->name, skb->len);
+		bp->xmt_length_errors++;	/* bump error counter */
+		dev_tint(dev);				/* dequeue packets from xmt queue and send them */
+		return(0);					/* return "success" */
+		}
+
+	/*
+	 * See if adapter link is available, if not, free buffer
+	 *
+	 * Note: If the link isn't available, free buffer and return 0
+	 *		 rather than tell the upper layer to requeue the packet.
+	 *		 The methodology here is that by the time the link
+	 *		 becomes available, the packet to be sent will be
+	 *		 fairly stale.  By simply dropping the packet, the
+	 *		 higher layer protocols will eventually time out
+	 *		 waiting for response packets which it won't receive.
+	 */
+
+	if (bp->link_available == PI_K_FALSE)
+		{
+		if (dfx_hw_adap_state_rd(bp) == PI_STATE_K_LINK_AVAIL)	/* is link really available? */
+			bp->link_available = PI_K_TRUE;		/* if so, set flag and continue */
+		else
+			{
+			bp->xmt_discards++;					/* bump error counter */
+			dev_kfree_skb(skb, FREE_WRITE);		/* free sk_buff now */
+			return(0);							/* return "success" */
+			}
+		}
+
+	/* Get the current producer and the next free xmt data descriptor */
+
+	prod		= bp->rcv_xmt_reg.index.xmt_prod;
+	p_xmt_descr = &(bp->descr_block_virt->xmt_data[prod]);
+
+	/*
+	 * Get pointer to auxiliary queue entry to contain information for this packet.
+	 *
+	 * Note: The current xmt producer index will become the current xmt completion
+	 *       index when we complete this packet later on.  So, we'll get the
+	 *       pointer to the next auxiliary queue entry now before we bump the
+	 *		 producer index.
+	 */
+
+	p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]);	/* also bump producer index */
+
+	/* Write the three PRH bytes immediately before the FC byte */
+
+	*((char *)skb->data - 3) = DFX_PRH0_BYTE;	/* these byte values are defined */
+	*((char *)skb->data - 2) = DFX_PRH1_BYTE;	/* in the Motorola FDDI MAC chip */
+	*((char *)skb->data - 1) = DFX_PRH2_BYTE;	/* specification */
+
+	/*
+	 * Write the descriptor with buffer info and bump producer
+	 *
+	 * Note: Since we need to start DMA from the packet request
+	 *		 header, we'll add 3 bytes to the DMA buffer length,
+	 *		 and we'll determine the physical address of the
+	 *		 buffer from the PRH, not skb->data.
+	 *
+	 * Assumptions:
+	 *		 1. Packet starts with the frame control (FC) byte
+	 *		    at skb->data.
+	 *		 2. The 4-byte CRC is not appended to the buffer or
+	 *			included in the length.
+	 *		 3. Packet length (skb->len) is from FC to end of
+	 *			data, inclusive.
+	 *		 4. The packet length does not exceed the maximum
+	 *			FDDI LLC frame length of 4491 bytes.
+	 *		 5. The entire packet is contained in a physically
+	 *			contiguous, non-cached, locked memory space
+	 *			comprised of a single buffer pointed to by
+	 *			skb->data.
+	 *		 6. The physical address of the start of packet
+	 *			can be determined from the virtual address
+	 *			by using virt_to_bus() and is only 32-bits
+	 *			wide.
+	 */
+
+	p_xmt_descr->long_0	= (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len + 3) << PI_XMT_DESCR_V_SEG_LEN));
+	p_xmt_descr->long_1 = (u32) virt_to_bus(skb->data - 3);
+
+	/*
+	 * Verify that descriptor is actually available
+	 *
+	 * Note: If descriptor isn't available, return 1 which tells
+	 *		 the upper layer to requeue the packet for later
+	 *		 transmission.
+	 *
+	 *       We need to ensure that the producer never reaches the
+	 *		 completion, except to indicate that the queue is empty.
+	 */
+
+	if (prod == bp->rcv_xmt_reg.index.xmt_comp)
+		return(1);						/* requeue packet for later */
+
+	/*
+	 * Save info for this packet for xmt done indication routine
+	 *
+	 * Normally, we'd save the producer index in the p_xmt_drv_descr
+	 * structure so that we'd have it handy when we complete this
+	 * packet later (in dfx_xmt_done).  However, since the current
+	 * transmit architecture guarantees a single fragment for the
+	 * entire packet, we can simply bump the completion index by
+	 * one (1) for each completed packet.
+	 *
+	 * Note: If this assumption changes and we're presented with
+	 *		 an inconsistent number of transmit fragments for packet
+	 *		 data, we'll need to modify this code to save the current
+	 *		 transmit producer index.
+	 */
+
+	p_xmt_drv_descr->p_skb = skb;
+
+	/* Update Type 2 register */
+
+	bp->rcv_xmt_reg.index.xmt_prod = prod;
+	dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
+	return(0);							/* packet queued to adapter */
+	}
+
+
+/*
+ * ================
+ * = dfx_xmt_done =
+ * ================
+ *   
+ * Overview:
+ *   Processes all frames that have been transmitted.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   For all consumed transmit descriptors that have not
+ *   yet been completed, we'll free the skb we were holding
+ *   onto using dev_kfree_skb and bump the appropriate
+ *   counters.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   The Type 2 register is not updated in this routine.  It is
+ *   assumed that it will be updated in the ISR when dfx_xmt_done
+ *   returns.
+ *
+ * Side Effects:
+ *   None
+ */
+
+void dfx_xmt_done(
+	DFX_board_t *bp
+	)
+
+	{
+	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
+	PI_TYPE_2_CONSUMER	*p_type_2_cons;		/* ptr to rcv/xmt consumer block register */
+
+	/* Service all consumed transmit frames */
+
+	p_type_2_cons = (PI_TYPE_2_CONSUMER *)(&bp->cons_block_virt->xmt_rcv_data);
+	while (bp->rcv_xmt_reg.index.xmt_comp != p_type_2_cons->index.xmt_cons)
+		{
+		/* Get pointer to the transmit driver descriptor block information */
+
+		p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
+
+		/* Return skb to operating system */
+
+		dev_kfree_skb(p_xmt_drv_descr->p_skb, FREE_WRITE);
+
+		/* Increment transmit counters */
+
+		bp->xmt_total_frames++;
+
+		/*
+		 * Move to start of next packet by updating completion index
+		 *
+		 * Here we assume that a transmit packet request is always
+		 * serviced by posting one fragment.  We can therefore
+		 * simplify the completion code by incrementing the
+		 * completion index by one.  This code will need to be
+		 * modified if this assumption changes.  See comments
+		 * in dfx_xmt_queue_pkt for more details.
+		 */
+
+		bp->rcv_xmt_reg.index.xmt_comp += 1;
+		}
+	return;
+	}
+
+
+/*
+ * =================
+ * = dfx_xmt_flush =
+ * =================
+ *   
+ * Overview:
+ *   Processes all frames whether they've been transmitted
+ *   or not.
+ *  
+ * Returns:
+ *   None
+ *       
+ * Arguments:
+ *   bp - pointer to board information
+ *
+ * Functional Description:
+ *   For all produced transmit descriptors that have not
+ *   yet been completed, we'll free the skb we were holding
+ *   onto using dev_kfree_skb and bump the appropriate
+ *   counters.  Of course, it's possible that some of
+ *   these transmit requests actually did go out, but we
+ *   won't make that distinction here.  Finally, we'll
+ *   update the consumer index to match the producer.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   This routine does NOT update the Type 2 register.  It
+ *   is assumed that this routine is being called during a
+ *   transmit flush interrupt, or a shutdown or close routine.
+ *
+ * Side Effects:
+ *   None
+ */
+
+void dfx_xmt_flush(
+	DFX_board_t *bp
+	)
+
+	{
+	u32					prod_cons;			/* rcv/xmt consumer block longword */
+	XMT_DRIVER_DESCR	*p_xmt_drv_descr;	/* ptr to transmit driver descriptor */
+
+	/* Flush all outstanding transmit frames */
+
+	while (bp->rcv_xmt_reg.index.xmt_comp != bp->rcv_xmt_reg.index.xmt_prod)
+		{
+		/* Get pointer to the transmit driver descriptor block information */
+
+		p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[bp->rcv_xmt_reg.index.xmt_comp]);
+
+		/* Return skb to operating system */
+
+		dev_kfree_skb(p_xmt_drv_descr->p_skb, FREE_WRITE);
+
+		/* Increment transmit error counter */
+
+		bp->xmt_discards++;
+
+		/*
+		 * Move to start of next packet by updating completion index
+		 *
+		 * Here we assume that a transmit packet request is always
+		 * serviced by posting one fragment.  We can therefore
+		 * simplify the completion code by incrementing the
+		 * completion index by one.  This code will need to be
+		 * modified if this assumption changes.  See comments
+		 * in dfx_xmt_queue_pkt for more details.
+		 */
+
+		bp->rcv_xmt_reg.index.xmt_comp += 1;
+		}
+
+	/* Update the transmit consumer index in the consumer block */
+
+	prod_cons = (u32)(bp->cons_block_virt->xmt_rcv_data & ~PI_CONS_M_XMT_INDEX);
+	prod_cons |= (u32)(bp->rcv_xmt_reg.index.xmt_prod << PI_CONS_V_XMT_INDEX);
+	bp->cons_block_virt->xmt_rcv_data = prod_cons;
+	return;
+	}
+
+
+/*
+ * Local variables:
+ * kernel-compile-command: "gcc -D__KERNEL__ -I/root/linux/include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=586 -c defxx.c"
+ * End:
+ */
diff -u --recursive --new-file v2.1.10/linux/drivers/net/defxx.h linux/drivers/net/defxx.h
--- v2.1.10/linux/drivers/net/defxx.h	Thu Jan  1 02:00:00 1970
+++ linux/drivers/net/defxx.h	Mon Nov 18 11:31:31 1996
@@ -0,0 +1,1780 @@
+/*
+ * File Name:
+ *   defxx.h
+ *
+ * Copyright Information:
+ *   Copyright Digital Equipment Corporation 1996.
+ *
+ *   This software may be used and distributed according to the terms of
+ *   the GNU Public License, incorporated herein by reference.
+ *
+ * Abstract:
+ *   Contains all definitions specified by port specification and required
+ *   by the defxx.c driver.
+ *
+ * Maintainers:
+ *   LVS	Lawrence V. Stefani
+ *
+ * Contact:
+ *	 The author may be reached at:
+ *
+ *		Inet: stefani@lkg.dec.com
+ *		Mail: Digital Equipment Corporation
+ *			  550 King Street
+ *			  M/S: LKG1-3/M07
+ *			  Littleton, MA  01460
+ *
+ * Modification History:
+ *		Date		Name	Description
+ *		16-Aug-96	LVS		Created.
+ *		09-Sep-96	LVS		Added group_prom field.  Moved read/write I/O
+ *							macros to DEFXX.C.
+ *		12-Sep-96	LVS		Removed packet request header pointers.
+ */
+
+#ifndef _DEFXX_H_
+#define _DEFXX_H_
+
+/* Define basic types for unsigned chars, shorts, longs */
+
+typedef u8	PI_UINT8;
+typedef u16	PI_UINT16;
+typedef u32	PI_UINT32;
+
+/* Define general structures */
+
+typedef struct							/* 64-bit counter */
+	{
+	PI_UINT32  ms;
+	PI_UINT32  ls;
+	} PI_CNTR;
+
+typedef struct							/* LAN address */
+	{										
+	PI_UINT32  lwrd_0;
+	PI_UINT32  lwrd_1;
+	} PI_LAN_ADDR;
+
+typedef struct							/* Station ID address */
+	{
+	PI_UINT32  octet_7_4;
+	PI_UINT32  octet_3_0;
+	} PI_STATION_ID;
+
+
+/* Define general constants */
+
+#define PI_ALIGN_K_DESC_BLK	  			8192	/* Descriptor block boundary		*/
+#define PI_ALIGN_K_CONS_BLK	  	 		64		/* Consumer block boundary		  	*/
+#define PI_ALIGN_K_CMD_REQ_BUFF  		128	 	/* Xmt Command que buffer alignment */
+#define PI_ALIGN_K_CMD_RSP_BUFF	 		128	 	/* Rcv Command que buffer alignment */
+#define PI_ALIGN_K_UNSOL_BUFF	 		128	 	/* Unsol que buffer alignment	   	*/
+#define PI_ALIGN_K_XMT_DATA_BUFF 		0	   	/* Xmt data que buffer alignment	*/
+#define PI_ALIGN_K_RCV_DATA_BUFF 		128	 	/* Rcv que buffer alignment			*/
+
+/* Define PHY index values */
+
+#define PI_PHY_K_S						0		/* Index to S phy */
+#define PI_PHY_K_A						0		/* Index to A phy */
+#define PI_PHY_K_B						1		/* Index to B phy */
+#define PI_PHY_K_MAX					2		/* Max number of phys */
+
+/* Define FMC descriptor fields */
+
+#define PI_FMC_DESCR_V_SOP				31
+#define PI_FMC_DESCR_V_EOP				30
+#define PI_FMC_DESCR_V_FSC				27
+#define PI_FMC_DESCR_V_FSB_ERROR		26
+#define PI_FMC_DESCR_V_FSB_ADDR_RECOG	25
+#define PI_FMC_DESCR_V_FSB_ADDR_COPIED	24
+#define PI_FMC_DESCR_V_FSB				22
+#define PI_FMC_DESCR_V_RCC_FLUSH		21
+#define PI_FMC_DESCR_V_RCC_CRC			20
+#define PI_FMC_DESCR_V_RCC_RRR			17
+#define PI_FMC_DESCR_V_RCC_DD			15
+#define PI_FMC_DESCR_V_RCC_SS			13
+#define PI_FMC_DESCR_V_RCC				13
+#define PI_FMC_DESCR_V_LEN				0
+
+#define PI_FMC_DESCR_M_SOP				0x80000000
+#define PI_FMC_DESCR_M_EOP				0x40000000
+#define PI_FMC_DESCR_M_FSC				0x38000000
+#define PI_FMC_DESCR_M_FSB_ERROR		0x04000000
+#define PI_FMC_DESCR_M_FSB_ADDR_RECOG	0x02000000
+#define PI_FMC_DESCR_M_FSB_ADDR_COPIED	0x01000000
+#define PI_FMC_DESCR_M_FSB				0x07C00000
+#define PI_FMC_DESCR_M_RCC_FLUSH		0x00200000
+#define PI_FMC_DESCR_M_RCC_CRC			0x00100000
+#define PI_FMC_DESCR_M_RCC_RRR			0x000E0000
+#define PI_FMC_DESCR_M_RCC_DD			0x00018000
+#define PI_FMC_DESCR_M_RCC_SS			0x00006000
+#define PI_FMC_DESCR_M_RCC				0x003FE000
+#define PI_FMC_DESCR_M_LEN				0x00001FFF
+
+#define PI_FMC_DESCR_K_RCC_FMC_INT_ERR	0x01AA
+
+#define PI_FMC_DESCR_K_RRR_SUCCESS		0x00
+#define PI_FMC_DESCR_K_RRR_SA_MATCH		0x01
+#define PI_FMC_DESCR_K_RRR_DA_MATCH		0x02
+#define PI_FMC_DESCR_K_RRR_FMC_ABORT	0x03
+#define PI_FMC_DESCR_K_RRR_LENGTH_BAD	0x04
+#define PI_FMC_DESCR_K_RRR_FRAGMENT		0x05
+#define PI_FMC_DESCR_K_RRR_FORMAT_ERR	0x06
+#define PI_FMC_DESCR_K_RRR_MAC_RESET	0x07
+
+#define PI_FMC_DESCR_K_DD_NO_MATCH		0x0
+#define PI_FMC_DESCR_K_DD_PROMISCUOUS	0x1
+#define PI_FMC_DESCR_K_DD_CAM_MATCH		0x2
+#define PI_FMC_DESCR_K_DD_LOCAL_MATCH	0x3
+
+#define PI_FMC_DESCR_K_SS_NO_MATCH		0x0
+#define PI_FMC_DESCR_K_SS_BRIDGE_MATCH	0x1
+#define PI_FMC_DESCR_K_SS_NOT_POSSIBLE	0x2
+#define PI_FMC_DESCR_K_SS_LOCAL_MATCH	0x3
+
+/* Define some max buffer sizes */
+
+#define PI_CMD_REQ_K_SIZE_MAX			512
+#define PI_CMD_RSP_K_SIZE_MAX			512
+#define PI_UNSOL_K_SIZE_MAX				512
+#define PI_SMT_HOST_K_SIZE_MAX			4608		/* 4 1/2 K */
+#define PI_RCV_DATA_K_SIZE_MAX			4608		/* 4 1/2 K */
+#define PI_XMT_DATA_K_SIZE_MAX			4608		/* 4 1/2 K */
+
+/* Define adapter states */
+
+#define PI_STATE_K_RESET				0
+#define PI_STATE_K_UPGRADE		  		1
+#define PI_STATE_K_DMA_UNAVAIL			2
+#define PI_STATE_K_DMA_AVAIL			3
+#define PI_STATE_K_LINK_AVAIL			4
+#define PI_STATE_K_LINK_UNAVAIL	 		5
+#define PI_STATE_K_HALTED		   		6
+#define PI_STATE_K_RING_MEMBER			7
+#define PI_STATE_K_NUMBER				8 
+
+/* Define codes for command type */
+
+#define PI_CMD_K_START					0x00
+#define PI_CMD_K_FILTERS_SET			0x01
+#define PI_CMD_K_FILTERS_GET			0x02
+#define PI_CMD_K_CHARS_SET				0x03
+#define PI_CMD_K_STATUS_CHARS_GET		0x04
+#define PI_CMD_K_CNTRS_GET				0x05
+#define PI_CMD_K_CNTRS_SET				0x06
+#define PI_CMD_K_ADDR_FILTER_SET		0x07
+#define PI_CMD_K_ADDR_FILTER_GET		0x08
+#define PI_CMD_K_ERROR_LOG_CLEAR		0x09
+#define PI_CMD_K_ERROR_LOG_GET			0x0A
+#define PI_CMD_K_FDDI_MIB_GET			0x0B
+#define PI_CMD_K_DEC_EXT_MIB_GET		0x0C
+#define PI_CMD_K_DEVICE_SPECIFIC_GET	0x0D
+#define PI_CMD_K_SNMP_SET				0x0E
+#define PI_CMD_K_UNSOL_TEST				0x0F
+#define PI_CMD_K_SMT_MIB_GET			0x10
+#define PI_CMD_K_SMT_MIB_SET			0x11
+#define PI_CMD_K_MAX					0x11	/* Must match last */
+
+/* Define item codes for Chars_Set and Filters_Set commands */
+
+#define PI_ITEM_K_EOL					0x00 	/* End-of-Item list 		  */
+#define PI_ITEM_K_T_REQ					0x01 	/* DECnet T_REQ 			  */
+#define PI_ITEM_K_TVX					0x02 	/* DECnet TVX 				  */
+#define PI_ITEM_K_RESTRICTED_TOKEN		0x03 	/* DECnet Restricted Token 	  */	 
+#define PI_ITEM_K_LEM_THRESHOLD			0x04 	/* DECnet LEM Threshold 	  */
+#define PI_ITEM_K_RING_PURGER			0x05 	/* DECnet Ring Purger Enable  */	
+#define PI_ITEM_K_CNTR_INTERVAL			0x06 	/* Chars_Set 				  */
+#define PI_ITEM_K_IND_GROUP_PROM		0x07 	/* Filters_Set 				  */
+#define PI_ITEM_K_GROUP_PROM			0x08 	/* Filters_Set 				  */
+#define PI_ITEM_K_BROADCAST				0x09 	/* Filters_Set 				  */
+#define PI_ITEM_K_SMT_PROM				0x0A 	/* Filters_Set				  */
+#define PI_ITEM_K_SMT_USER				0x0B 	/* Filters_Set 				  */
+#define PI_ITEM_K_RESERVED				0x0C 	/* Filters_Set 				  */
+#define PI_ITEM_K_IMPLEMENTOR			0x0D 	/* Filters_Set 				  */
+#define PI_ITEM_K_LOOPBACK_MODE			0x0E 	/* Chars_Set 				  */
+#define PI_ITEM_K_CONFIG_POLICY			0x10 	/* SMTConfigPolicy 			  */
+#define PI_ITEM_K_CON_POLICY			0x11 	/* SMTConnectionPolicy 		  */
+#define PI_ITEM_K_T_NOTIFY				0x12 	/* SMTTNotify 				  */
+#define PI_ITEM_K_STATION_ACTION		0x13 	/* SMTStationAction			  */
+#define PI_ITEM_K_MAC_PATHS_REQ	   		0x15 	/* MACPathsRequested 		  */
+#define PI_ITEM_K_MAC_ACTION			0x17 	/* MACAction 				  */
+#define PI_ITEM_K_CON_POLICIES			0x18 	/* PORTConnectionPolicies	  */
+#define PI_ITEM_K_PORT_PATHS_REQ		0x19 	/* PORTPathsRequested 		  */
+#define PI_ITEM_K_MAC_LOOP_TIME			0x1A 	/* PORTMACLoopTime 			  */
+#define PI_ITEM_K_TB_MAX				0x1B 	/* PORTTBMax 				  */
+#define PI_ITEM_K_LER_CUTOFF			0x1C 	/* PORTLerCutoff 			  */
+#define PI_ITEM_K_LER_ALARM				0x1D 	/* PORTLerAlarm 			  */
+#define PI_ITEM_K_PORT_ACTION			0x1E 	/* PORTAction 				  */
+#define PI_ITEM_K_FLUSH_TIME			0x20 	/* Chars_Set 				  */
+#define PI_ITEM_K_MAC_T_REQ				0x29 	/* MACTReq 					  */
+#define PI_ITEM_K_EMAC_RING_PURGER		0x2A 	/* eMACRingPurgerEnable		  */
+#define PI_ITEM_K_EMAC_RTOKEN_TIMEOUT	0x2B 	/* eMACRestrictedTokenTimeout */
+#define PI_ITEM_K_FDX_ENB_DIS			0x2C 	/* eFDXEnable				  */
+#define PI_ITEM_K_MAX					0x2C 	/* Must equal high item		  */
+
+/* Values for some of the items */
+
+#define PI_K_FALSE						0	   /* Generic false */
+#define PI_K_TRUE						1	   /* Generic true  */
+
+#define PI_SNMP_K_TRUE					1	   /* SNMP true/false values */
+#define PI_SNMP_K_FALSE					2
+
+#define PI_FSTATE_K_BLOCK				0	   /* Filter State */
+#define PI_FSTATE_K_PASS				1
+
+/* Define command return codes */
+
+#define PI_RSP_K_SUCCESS				0x00
+#define PI_RSP_K_FAILURE				0x01
+#define PI_RSP_K_WARNING				0x02
+#define PI_RSP_K_LOOP_MODE_BAD			0x03
+#define PI_RSP_K_ITEM_CODE_BAD			0x04
+#define PI_RSP_K_TVX_BAD				0x05
+#define PI_RSP_K_TREQ_BAD				0x06
+#define PI_RSP_K_TOKEN_BAD				0x07
+#define PI_RSP_K_NO_EOL					0x0C
+#define PI_RSP_K_FILTER_STATE_BAD		0x0D
+#define PI_RSP_K_CMD_TYPE_BAD			0x0E
+#define PI_RSP_K_ADAPTER_STATE_BAD		0x0F
+#define PI_RSP_K_RING_PURGER_BAD		0x10
+#define PI_RSP_K_LEM_THRESHOLD_BAD		0x11
+#define PI_RSP_K_LOOP_NOT_SUPPORTED		0x12
+#define PI_RSP_K_FLUSH_TIME_BAD			0x13
+#define PI_RSP_K_NOT_IMPLEMENTED		0x14
+#define PI_RSP_K_CONFIG_POLICY_BAD		0x15
+#define PI_RSP_K_STATION_ACTION_BAD		0x16
+#define PI_RSP_K_MAC_ACTION_BAD			0x17
+#define PI_RSP_K_CON_POLICIES_BAD		0x18
+#define PI_RSP_K_MAC_LOOP_TIME_BAD		0x19
+#define PI_RSP_K_TB_MAX_BAD				0x1A
+#define PI_RSP_K_LER_CUTOFF_BAD			0x1B
+#define PI_RSP_K_LER_ALARM_BAD			0x1C
+#define PI_RSP_K_MAC_PATHS_REQ_BAD		0x1D
+#define PI_RSP_K_MAC_T_REQ_BAD			0x1E
+#define PI_RSP_K_EMAC_RING_PURGER_BAD	0x1F
+#define PI_RSP_K_EMAC_RTOKEN_TIME_BAD	0x20
+#define PI_RSP_K_NO_SUCH_ENTRY			0x21
+#define PI_RSP_K_T_NOTIFY_BAD			0x22
+#define PI_RSP_K_TR_MAX_EXP_BAD			0x23
+#define PI_RSP_K_MAC_FRM_ERR_THR_BAD	0x24
+#define PI_RSP_K_MAX_T_REQ_BAD			0x25
+#define PI_RSP_K_FDX_ENB_DIS_BAD		0x26
+#define PI_RSP_K_ITEM_INDEX_BAD			0x27
+#define PI_RSP_K_PORT_ACTION_BAD		0x28
+
+/* Commonly used structures */
+
+typedef struct									/* Item list */
+	{
+	PI_UINT32  item_code;
+	PI_UINT32  value;
+	} PI_ITEM_LIST;
+
+typedef struct									/* Response header */
+	{
+	PI_UINT32  reserved;
+	PI_UINT32  cmd_type;
+	PI_UINT32  status;
+	} PI_RSP_HEADER;
+
+
+/* Start Command */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	} PI_CMD_START_REQ;
+
+/* Start Response */
+
+typedef struct 
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_START_RSP;
+
+/* Filters_Set Request */
+
+#define PI_CMD_FILTERS_SET_K_ITEMS_MAX  63		/* Fits in a 512 byte buffer */
+
+typedef struct 
+	{
+	PI_UINT32		cmd_type;
+	PI_ITEM_LIST	item[PI_CMD_FILTERS_SET_K_ITEMS_MAX];
+	} PI_CMD_FILTERS_SET_REQ;
+
+/* Filters_Set Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_FILTERS_SET_RSP;
+
+/* Filters_Get Request */
+
+typedef struct
+	{
+	PI_UINT32		cmd_type;   
+	} PI_CMD_FILTERS_GET_REQ;
+
+/* Filters_Get Response */
+
+typedef struct 
+	{
+	PI_RSP_HEADER   header;	
+	PI_UINT32		ind_group_prom;
+	PI_UINT32		group_prom;
+	PI_UINT32		broadcast_all;
+	PI_UINT32		smt_all;
+	PI_UINT32		smt_user;
+	PI_UINT32		reserved_all;
+	PI_UINT32		implementor_all;
+	} PI_CMD_FILTERS_GET_RSP;
+
+
+/* Chars_Set Request */
+
+#define PI_CMD_CHARS_SET_K_ITEMS_MAX 42		/* Fits in a 512 byte buffer */
+
+typedef struct
+	{
+	PI_UINT32		cmd_type;
+	struct							  		/* Item list */
+		{
+		PI_UINT32	item_code;
+		PI_UINT32	value;
+		PI_UINT32	item_index;
+		} item[PI_CMD_CHARS_SET_K_ITEMS_MAX];	
+	} PI_CMD_CHARS_SET_REQ;
+
+/* Chars_Set Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_CHARS_SET_RSP;
+
+
+/* SNMP_Set Request */
+
+#define PI_CMD_SNMP_SET_K_ITEMS_MAX 42	   	/* Fits in a 512 byte buffer */
+
+typedef struct
+	{
+	PI_UINT32		cmd_type;
+	struct							   		/* Item list */
+		{
+		PI_UINT32	item_code;
+		PI_UINT32	value;
+		PI_UINT32	item_index;
+		} item[PI_CMD_SNMP_SET_K_ITEMS_MAX];	
+	} PI_CMD_SNMP_SET_REQ;
+
+/* SNMP_Set Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_SNMP_SET_RSP;
+
+
+/* SMT_MIB_Set Request */
+
+#define PI_CMD_SMT_MIB_SET_K_ITEMS_MAX 42	/* Max number of items */ 
+
+typedef struct
+	{
+	PI_UINT32	cmd_type;
+	struct
+		{
+		PI_UINT32	item_code;
+		PI_UINT32	value;
+		PI_UINT32	item_index;
+		} item[PI_CMD_SMT_MIB_SET_K_ITEMS_MAX];
+	} PI_CMD_SMT_MIB_SET_REQ;
+
+/* SMT_MIB_Set Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_SMT_MIB_SET_RSP;
+
+/* SMT_MIB_Get Request */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	} PI_CMD_SMT_MIB_GET_REQ;
+
+/* SMT_MIB_Get Response */
+
+typedef struct						  /* Refer to ANSI FDDI SMT Rev. 7.3 */
+	{
+	PI_RSP_HEADER  header;
+	
+	/* SMT GROUP */														  
+
+	PI_STATION_ID  	smt_station_id;
+	PI_UINT32 		smt_op_version_id;
+	PI_UINT32	   	smt_hi_version_id;
+	PI_UINT32	   	smt_lo_version_id;
+	PI_UINT32	   	smt_user_data[8];
+	PI_UINT32	   	smt_mib_version_id;
+	PI_UINT32	   	smt_mac_ct;
+	PI_UINT32	   	smt_non_master_ct;
+	PI_UINT32	   	smt_master_ct;
+	PI_UINT32	   	smt_available_paths;
+	PI_UINT32	   	smt_config_capabilities;
+	PI_UINT32	   	smt_config_policy;
+	PI_UINT32	   	smt_connection_policy;
+	PI_UINT32	   	smt_t_notify;
+	PI_UINT32	   	smt_stat_rpt_policy;
+	PI_UINT32	   	smt_trace_max_expiration;
+	PI_UINT32	   	smt_bypass_present;
+	PI_UINT32	  	smt_ecm_state;
+	PI_UINT32	   	smt_cf_state;
+	PI_UINT32	   	smt_remote_disconnect_flag;
+	PI_UINT32	   	smt_station_status;
+	PI_UINT32	   	smt_peer_wrap_flag;
+	PI_CNTR	   		smt_msg_time_stamp;
+	PI_CNTR	  		smt_transition_time_stamp;
+
+	/* MAC GROUP */
+
+	PI_UINT32		mac_frame_status_functions;
+	PI_UINT32		mac_t_max_capability;
+	PI_UINT32		mac_tvx_capability;
+	PI_UINT32		mac_available_paths;
+	PI_UINT32		mac_current_path;
+	PI_LAN_ADDR		mac_upstream_nbr;
+	PI_LAN_ADDR		mac_downstream_nbr;
+	PI_LAN_ADDR		mac_old_upstream_nbr;
+	PI_LAN_ADDR		mac_old_downstream_nbr;
+	PI_UINT32	   	mac_dup_address_test;
+	PI_UINT32	   	mac_requested_paths;
+	PI_UINT32	   	mac_downstream_port_type;
+	PI_LAN_ADDR		mac_smt_address;
+	PI_UINT32		mac_t_req;
+	PI_UINT32		mac_t_neg;
+	PI_UINT32		mac_t_max;
+	PI_UINT32		mac_tvx_value;
+	PI_UINT32		mac_frame_error_threshold;
+	PI_UINT32		mac_frame_error_ratio;
+	PI_UINT32		mac_rmt_state;
+	PI_UINT32		mac_da_flag;
+	PI_UINT32		mac_unda_flag;
+	PI_UINT32		mac_frame_error_flag;
+	PI_UINT32		mac_ma_unitdata_available;
+	PI_UINT32		mac_hardware_present;
+	PI_UINT32		mac_ma_unitdata_enable;
+
+	/* PATH GROUP */
+
+	PI_UINT32		path_configuration[8];
+	PI_UINT32		path_tvx_lower_bound;
+	PI_UINT32		path_t_max_lower_bound;
+	PI_UINT32		path_max_t_req;
+
+	/* PORT GROUP */
+
+	PI_UINT32		port_my_type[PI_PHY_K_MAX];
+	PI_UINT32		port_neighbor_type[PI_PHY_K_MAX];
+	PI_UINT32		port_connection_policies[PI_PHY_K_MAX];
+	PI_UINT32		port_mac_indicated[PI_PHY_K_MAX];
+	PI_UINT32		port_current_path[PI_PHY_K_MAX];
+	PI_UINT32		port_requested_paths[PI_PHY_K_MAX];
+	PI_UINT32		port_mac_placement[PI_PHY_K_MAX];
+	PI_UINT32		port_available_paths[PI_PHY_K_MAX];
+	PI_UINT32		port_pmd_class[PI_PHY_K_MAX];
+	PI_UINT32		port_connection_capabilities[PI_PHY_K_MAX];
+	PI_UINT32		port_bs_flag[PI_PHY_K_MAX];
+	PI_UINT32		port_ler_estimate[PI_PHY_K_MAX];
+	PI_UINT32		port_ler_cutoff[PI_PHY_K_MAX];	
+	PI_UINT32		port_ler_alarm[PI_PHY_K_MAX];
+	PI_UINT32		port_connect_state[PI_PHY_K_MAX];
+	PI_UINT32		port_pcm_state[PI_PHY_K_MAX];
+	PI_UINT32		port_pc_withhold[PI_PHY_K_MAX];
+	PI_UINT32		port_ler_flag[PI_PHY_K_MAX];
+	PI_UINT32		port_hardware_present[PI_PHY_K_MAX];
+
+	/* GROUP for things that were added later, so must be at the end. */
+
+	PI_CNTR	   		path_ring_latency;
+
+	} PI_CMD_SMT_MIB_GET_RSP; 
+
+
+/*
+ *  Item and group code definitions for SMT 7.3 mandatory objects.  These
+ *  definitions are to be used as appropriate in SMT_MIB_SET commands and
+ *  certain host-sent SMT frames such as PMF Get and Set requests.  The
+ *  codes have been taken from the MIB summary section of ANSI SMT 7.3.
+ */
+	
+#define PI_GRP_K_SMT_STATION_ID			0x100A
+#define PI_ITEM_K_SMT_STATION_ID		0x100B
+#define PI_ITEM_K_SMT_OP_VERS_ID		0x100D
+#define PI_ITEM_K_SMT_HI_VERS_ID		0x100E
+#define PI_ITEM_K_SMT_LO_VERS_ID		0x100F
+#define PI_ITEM_K_SMT_USER_DATA			0x1011
+#define PI_ITEM_K_SMT_MIB_VERS_ID	  	0x1012
+
+#define PI_GRP_K_SMT_STATION_CONFIG		0x1014
+#define PI_ITEM_K_SMT_MAC_CT			0x1015
+#define PI_ITEM_K_SMT_NON_MASTER_CT		0x1016
+#define PI_ITEM_K_SMT_MASTER_CT			0x1017
+#define PI_ITEM_K_SMT_AVAIL_PATHS		0x1018
+#define PI_ITEM_K_SMT_CONFIG_CAPS		0x1019
+#define PI_ITEM_K_SMT_CONFIG_POL		0x101A
+#define PI_ITEM_K_SMT_CONN_POL			0x101B
+#define PI_ITEM_K_SMT_T_NOTIFY			0x101D
+#define PI_ITEM_K_SMT_STAT_POL			0x101E
+#define PI_ITEM_K_SMT_TR_MAX_EXP		0x101F
+#define PI_ITEM_K_SMT_PORT_INDEXES		0x1020
+#define PI_ITEM_K_SMT_MAC_INDEXES		0x1021
+#define PI_ITEM_K_SMT_BYPASS_PRESENT	0x1022
+
+#define PI_GRP_K_SMT_STATUS				0x1028
+#define PI_ITEM_K_SMT_ECM_STATE			0x1029
+#define PI_ITEM_K_SMT_CF_STATE		 	0x102A
+#define PI_ITEM_K_SMT_REM_DISC_FLAG		0x102C
+#define PI_ITEM_K_SMT_STATION_STATUS	0x102D
+#define PI_ITEM_K_SMT_PEER_WRAP_FLAG	0x102E
+	
+#define PI_GRP_K_SMT_MIB_OPERATION	 	0x1032
+#define PI_ITEM_K_SMT_MSG_TIME_STAMP 	0x1033
+#define PI_ITEM_K_SMT_TRN_TIME_STAMP 	0x1034
+
+#define PI_ITEM_K_SMT_STATION_ACT		0x103C
+
+#define PI_GRP_K_MAC_CAPABILITIES	  	0x200A
+#define PI_ITEM_K_MAC_FRM_STAT_FUNC		0x200B
+#define PI_ITEM_K_MAC_T_MAX_CAP			0x200D
+#define PI_ITEM_K_MAC_TVX_CAP		  	0x200E
+
+#define PI_GRP_K_MAC_CONFIG				0x2014
+#define PI_ITEM_K_MAC_AVAIL_PATHS	  	0x2016
+#define PI_ITEM_K_MAC_CURRENT_PATH	 	0x2017
+#define PI_ITEM_K_MAC_UP_NBR			0x2018
+#define PI_ITEM_K_MAC_DOWN_NBR			0x2019
+#define PI_ITEM_K_MAC_OLD_UP_NBR	 	0x201A
+#define PI_ITEM_K_MAC_OLD_DOWN_NBR	 	0x201B
+#define PI_ITEM_K_MAC_DUP_ADDR_TEST		0x201D
+#define PI_ITEM_K_MAC_REQ_PATHS			0x2020
+#define PI_ITEM_K_MAC_DOWN_PORT_TYPE   	0x2021
+#define PI_ITEM_K_MAC_INDEX				0x2022
+
+#define PI_GRP_K_MAC_ADDRESS			0x2028
+#define PI_ITEM_K_MAC_SMT_ADDRESS		0x2029
+
+#define PI_GRP_K_MAC_OPERATION			0x2032
+#define PI_ITEM_K_MAC_TREQ				0x2033
+#define PI_ITEM_K_MAC_TNEG				0x2034
+#define PI_ITEM_K_MAC_TMAX				0x2035
+#define PI_ITEM_K_MAC_TVX_VALUE			0x2036
+
+#define PI_GRP_K_MAC_COUNTERS			0x2046
+#define PI_ITEM_K_MAC_FRAME_CT			0x2047
+#define PI_ITEM_K_MAC_COPIED_CT			0x2048
+#define PI_ITEM_K_MAC_TRANSMIT_CT		0x2049
+#define PI_ITEM_K_MAC_ERROR_CT			0x2051
+#define PI_ITEM_K_MAC_LOST_CT			0x2052
+
+#define PI_GRP_K_MAC_FRM_ERR_COND		0x205A
+#define PI_ITEM_K_MAC_FRM_ERR_THR		0x205F
+#define PI_ITEM_K_MAC_FRM_ERR_RAT		0x2060
+
+#define PI_GRP_K_MAC_STATUS				0x206E
+#define PI_ITEM_K_MAC_RMT_STATE			0x206F
+#define PI_ITEM_K_MAC_DA_FLAG			0x2070
+#define PI_ITEM_K_MAC_UNDA_FLAG			0x2071
+#define PI_ITEM_K_MAC_FRM_ERR_FLAG		0x2072
+#define PI_ITEM_K_MAC_MA_UNIT_AVAIL		0x2074
+#define PI_ITEM_K_MAC_HW_PRESENT		0x2075
+#define PI_ITEM_K_MAC_MA_UNIT_ENAB		0x2076
+
+#define PI_GRP_K_PATH_CONFIG			0x320A
+#define PI_ITEM_K_PATH_INDEX			0x320B
+#define PI_ITEM_K_PATH_CONFIGURATION 	0x3212
+#define PI_ITEM_K_PATH_TVX_LB			0x3215
+#define PI_ITEM_K_PATH_T_MAX_LB			0x3216
+#define PI_ITEM_K_PATH_MAX_T_REQ		0x3217
+
+#define PI_GRP_K_PORT_CONFIG			0x400A
+#define PI_ITEM_K_PORT_MY_TYPE			0x400C
+#define PI_ITEM_K_PORT_NBR_TYPE			0x400D
+#define PI_ITEM_K_PORT_CONN_POLS		0x400E
+#define PI_ITEM_K_PORT_MAC_INDICATED  	0x400F
+#define PI_ITEM_K_PORT_CURRENT_PATH		0x4010
+#define PI_ITEM_K_PORT_REQ_PATHS		0x4011
+#define PI_ITEM_K_PORT_MAC_PLACEMENT 	0x4012
+#define PI_ITEM_K_PORT_AVAIL_PATHS		0x4013
+#define PI_ITEM_K_PORT_PMD_CLASS		0x4016
+#define PI_ITEM_K_PORT_CONN_CAPS		0x4017
+#define PI_ITEM_K_PORT_INDEX			0x401D
+
+#define PI_GRP_K_PORT_OPERATION			0x401E
+#define PI_ITEM_K_PORT_BS_FLAG		 	0x4021
+
+#define PI_GRP_K_PORT_ERR_CNTRS			0x4028
+#define PI_ITEM_K_PORT_LCT_FAIL_CT	 	0x402A
+
+#define PI_GRP_K_PORT_LER			  	0x4032
+#define PI_ITEM_K_PORT_LER_ESTIMATE		0x4033
+#define PI_ITEM_K_PORT_LEM_REJ_CT		0x4034
+#define PI_ITEM_K_PORT_LEM_CT			0x4035
+#define PI_ITEM_K_PORT_LER_CUTOFF		0x403A
+#define PI_ITEM_K_PORT_LER_ALARM		0x403B
+
+#define PI_GRP_K_PORT_STATUS			0x403C
+#define PI_ITEM_K_PORT_CONNECT_STATE	0x403D
+#define PI_ITEM_K_PORT_PCM_STATE		0x403E
+#define PI_ITEM_K_PORT_PC_WITHHOLD		0x403F
+#define PI_ITEM_K_PORT_LER_FLAG			0x4040
+#define PI_ITEM_K_PORT_HW_PRESENT		0x4041
+
+#define PI_ITEM_K_PORT_ACT				0x4046
+
+/* Addr_Filter_Set Request */
+
+#define PI_CMD_ADDR_FILTER_K_SIZE   62
+
+typedef struct
+	{
+	PI_UINT32	cmd_type;
+	PI_LAN_ADDR	entry[PI_CMD_ADDR_FILTER_K_SIZE];
+	} PI_CMD_ADDR_FILTER_SET_REQ;
+
+/* Addr_Filter_Set Response */
+
+typedef struct 
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_ADDR_FILTER_SET_RSP;
+
+/* Addr_Filter_Get Request */
+
+typedef struct
+	{
+	PI_UINT32	cmd_type;
+	} PI_CMD_ADDR_FILTER_GET_REQ;
+
+/* Addr_Filter_Get Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	PI_LAN_ADDR		entry[PI_CMD_ADDR_FILTER_K_SIZE];
+	} PI_CMD_ADDR_FILTER_GET_RSP;
+
+/* Status_Chars_Get Request */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	} PI_CMD_STATUS_CHARS_GET_REQ;
+
+/* Status_Chars_Get Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	PI_STATION_ID   station_id;						/* Station */
+	PI_UINT32		station_type;
+	PI_UINT32		smt_ver_id;
+	PI_UINT32		smt_ver_id_max;
+	PI_UINT32		smt_ver_id_min;
+	PI_UINT32		station_state;
+	PI_LAN_ADDR		link_addr;						/* Link */
+	PI_UINT32		t_req;
+	PI_UINT32		tvx;
+	PI_UINT32		token_timeout;
+	PI_UINT32		purger_enb;
+	PI_UINT32		link_state;
+	PI_UINT32		tneg;
+	PI_UINT32		dup_addr_flag;
+	PI_LAN_ADDR		una;
+	PI_LAN_ADDR		una_old;
+	PI_UINT32		un_dup_addr_flag;
+	PI_LAN_ADDR		dna;
+	PI_LAN_ADDR		dna_old;
+	PI_UINT32		purger_state;
+	PI_UINT32		fci_mode;
+	PI_UINT32		error_reason;
+	PI_UINT32		loopback;
+	PI_UINT32		ring_latency;
+	PI_LAN_ADDR		last_dir_beacon_sa;
+	PI_LAN_ADDR		last_dir_beacon_una;
+	PI_UINT32		phy_type[PI_PHY_K_MAX];			/* Phy */
+	PI_UINT32		pmd_type[PI_PHY_K_MAX];
+	PI_UINT32		lem_threshold[PI_PHY_K_MAX];
+	PI_UINT32		phy_state[PI_PHY_K_MAX];
+	PI_UINT32		nbor_phy_type[PI_PHY_K_MAX];
+	PI_UINT32		link_error_est[PI_PHY_K_MAX];
+	PI_UINT32		broken_reason[PI_PHY_K_MAX];
+	PI_UINT32		reject_reason[PI_PHY_K_MAX];
+	PI_UINT32		cntr_interval;					/* Miscellaneous */
+	PI_UINT32		module_rev;
+	PI_UINT32		firmware_rev;
+	PI_UINT32		mop_device_type;
+	PI_UINT32		phy_led[PI_PHY_K_MAX];
+	PI_UINT32		flush_time;
+	} PI_CMD_STATUS_CHARS_GET_RSP;
+
+/* FDDI_MIB_Get Request */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	} PI_CMD_FDDI_MIB_GET_REQ;
+
+/* FDDI_MIB_Get Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;		
+
+	/* SMT GROUP */
+
+	PI_STATION_ID   smt_station_id;			
+	PI_UINT32		smt_op_version_id;
+	PI_UINT32		smt_hi_version_id;
+	PI_UINT32		smt_lo_version_id;
+	PI_UINT32		smt_mac_ct;				
+	PI_UINT32		smt_non_master_ct;			
+	PI_UINT32		smt_master_ct;				
+	PI_UINT32		smt_paths_available;			
+	PI_UINT32		smt_config_capabilities;		
+	PI_UINT32		smt_config_policy;		
+	PI_UINT32		smt_connection_policy;		
+	PI_UINT32		smt_t_notify;	
+	PI_UINT32		smt_status_reporting;
+	PI_UINT32		smt_ecm_state;	
+	PI_UINT32		smt_cf_state;	
+	PI_UINT32		smt_hold_state;		
+	PI_UINT32		smt_remote_disconnect_flag;
+	PI_UINT32		smt_station_action;			
+
+	/* MAC GROUP */
+
+	PI_UINT32		mac_frame_status_capabilities;	
+	PI_UINT32		mac_t_max_greatest_lower_bound;
+	PI_UINT32		mac_tvx_greatest_lower_bound;
+	PI_UINT32		mac_paths_available;
+	PI_UINT32		mac_current_path;
+	PI_LAN_ADDR		mac_upstream_nbr;			
+	PI_LAN_ADDR		mac_old_upstream_nbr;		
+	PI_UINT32		mac_dup_addr_test;			
+	PI_UINT32		mac_paths_requested;
+	PI_UINT32		mac_downstream_port_type;
+	PI_LAN_ADDR		mac_smt_address;			
+	PI_UINT32		mac_t_req;				
+	PI_UINT32		mac_t_neg;
+	PI_UINT32		mac_t_max;				
+	PI_UINT32		mac_tvx_value;			
+	PI_UINT32		mac_t_min;				
+	PI_UINT32		mac_current_frame_status;
+	/*			  	mac_frame_cts 			*/
+	/* 				mac_error_cts 			*/
+	/* 		   		mac_lost_cts 			*/
+	PI_UINT32		mac_frame_error_threshold;		
+	PI_UINT32		mac_frame_error_ratio;		
+	PI_UINT32		mac_rmt_state;
+	PI_UINT32		mac_da_flag;
+	PI_UINT32		mac_una_da_flag;			
+	PI_UINT32		mac_frame_condition;
+	PI_UINT32		mac_chip_set;			
+	PI_UINT32		mac_action;				
+
+	/* PATH GROUP => Does not need to be implemented */
+
+	/* PORT GROUP */
+
+	PI_UINT32		port_pc_type[PI_PHY_K_MAX];			
+	PI_UINT32		port_pc_neighbor[PI_PHY_K_MAX];			
+	PI_UINT32		port_connection_policies[PI_PHY_K_MAX];
+	PI_UINT32		port_remote_mac_indicated[PI_PHY_K_MAX];
+	PI_UINT32		port_ce_state[PI_PHY_K_MAX];
+	PI_UINT32		port_paths_requested[PI_PHY_K_MAX];
+	PI_UINT32		port_mac_placement[PI_PHY_K_MAX];
+	PI_UINT32		port_available_paths[PI_PHY_K_MAX];
+	PI_UINT32		port_mac_loop_time[PI_PHY_K_MAX];
+	PI_UINT32		port_tb_max[PI_PHY_K_MAX];
+	PI_UINT32		port_bs_flag[PI_PHY_K_MAX];
+	/*				port_lct_fail_cts[PI_PHY_K_MAX];	*/
+	PI_UINT32		port_ler_estimate[PI_PHY_K_MAX];				
+	/*				port_lem_reject_cts[PI_PHY_K_MAX];	*/
+	/*				port_lem_cts[PI_PHY_K_MAX];		*/
+	PI_UINT32		port_ler_cutoff[PI_PHY_K_MAX];				
+	PI_UINT32		port_ler_alarm[PI_PHY_K_MAX];				
+	PI_UINT32		port_connect_state[PI_PHY_K_MAX];
+	PI_UINT32		port_pcm_state[PI_PHY_K_MAX];
+	PI_UINT32		port_pc_withhold[PI_PHY_K_MAX];
+	PI_UINT32		port_ler_condition[PI_PHY_K_MAX];				
+	PI_UINT32		port_chip_set[PI_PHY_K_MAX];				
+	PI_UINT32		port_action[PI_PHY_K_MAX];				
+
+	/* ATTACHMENT GROUP */
+
+	PI_UINT32		attachment_class;
+	PI_UINT32		attachment_ob_present;
+	PI_UINT32		attachment_imax_expiration;
+	PI_UINT32		attachment_inserted_status;
+	PI_UINT32		attachment_insert_policy;
+
+	/* CHIP SET GROUP => Does not need to be implemented */
+
+	} PI_CMD_FDDI_MIB_GET_RSP;
+
+/* DEC_Ext_MIB_Get Request */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	} PI_CMD_DEC_EXT_MIB_GET_REQ;
+
+/* DEC_Ext_MIB_Get (efddi and efdx groups only) Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;		
+
+	/* SMT GROUP */
+
+	PI_UINT32		esmt_station_type;
+
+	/* MAC GROUP */
+
+	PI_UINT32		emac_link_state;			
+	PI_UINT32		emac_ring_purger_state;
+	PI_UINT32		emac_ring_purger_enable;
+	PI_UINT32		emac_frame_strip_mode;
+	PI_UINT32		emac_ring_error_reason;
+	PI_UINT32		emac_up_nbr_dup_addr_flag;
+	PI_UINT32		emac_restricted_token_timeout;
+
+	/* PORT GROUP */
+
+	PI_UINT32		eport_pmd_type[PI_PHY_K_MAX];
+	PI_UINT32		eport_phy_state[PI_PHY_K_MAX];
+	PI_UINT32		eport_reject_reason[PI_PHY_K_MAX];
+
+	/* FDX (Full-Duplex) GROUP */
+
+	PI_UINT32		efdx_enable;				/* Valid only in SMT 7.3 */
+	PI_UINT32		efdx_op;					/* Valid only in SMT 7.3 */
+	PI_UINT32		efdx_state;					/* Valid only in SMT 7.3 */
+
+	} PI_CMD_DEC_EXT_MIB_GET_RSP;
+
+typedef struct
+	{
+	PI_CNTR		traces_rcvd;					/* Station */
+	PI_CNTR		frame_cnt;						/* Link */
+	PI_CNTR		error_cnt;
+	PI_CNTR		lost_cnt;
+	PI_CNTR		octets_rcvd;
+	PI_CNTR		octets_sent;
+	PI_CNTR		pdus_rcvd;
+	PI_CNTR		pdus_sent;
+	PI_CNTR		mcast_octets_rcvd;
+	PI_CNTR		mcast_octets_sent;
+	PI_CNTR		mcast_pdus_rcvd;
+	PI_CNTR		mcast_pdus_sent;
+	PI_CNTR		xmt_underruns;
+	PI_CNTR		xmt_failures;
+	PI_CNTR		block_check_errors;
+	PI_CNTR		frame_status_errors;
+	PI_CNTR		pdu_length_errors;
+	PI_CNTR		rcv_overruns;
+	PI_CNTR		user_buff_unavailable;
+	PI_CNTR		inits_initiated;
+	PI_CNTR		inits_rcvd;
+	PI_CNTR		beacons_initiated;
+	PI_CNTR		dup_addrs;
+	PI_CNTR		dup_tokens;
+	PI_CNTR		purge_errors;
+	PI_CNTR		fci_strip_errors;
+	PI_CNTR		traces_initiated;
+	PI_CNTR		directed_beacons_rcvd;
+	PI_CNTR		emac_frame_alignment_errors;
+	PI_CNTR		ebuff_errors[PI_PHY_K_MAX];		/* Phy */
+	PI_CNTR		lct_rejects[PI_PHY_K_MAX];
+	PI_CNTR		lem_rejects[PI_PHY_K_MAX];
+	PI_CNTR		link_errors[PI_PHY_K_MAX];
+	PI_CNTR		connections[PI_PHY_K_MAX];
+	PI_CNTR		copied_cnt;			 			/* Valid only if using SMT 7.3 */
+	PI_CNTR		transmit_cnt;					/* Valid only if using SMT 7.3 */
+	PI_CNTR		tokens;
+	} PI_CNTR_BLK;
+
+/* Counters_Get Request */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	} PI_CMD_CNTRS_GET_REQ;
+
+/* Counters_Get Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	PI_CNTR		time_since_reset;			
+	PI_CNTR_BLK		cntrs;				
+	} PI_CMD_CNTRS_GET_RSP;
+
+/* Counters_Set Request */
+
+typedef struct
+	{
+	PI_UINT32	cmd_type;
+	PI_CNTR_BLK	cntrs;				
+	} PI_CMD_CNTRS_SET_REQ;
+
+/* Counters_Set Response */
+
+typedef struct 
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_CNTRS_SET_RSP;
+
+/* Error_Log_Clear Request */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	} PI_CMD_ERROR_LOG_CLEAR_REQ;
+
+/* Error_Log_Clear Response */
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	} PI_CMD_ERROR_LOG_CLEAR_RSP;
+
+/* Error_Log_Get Request */
+
+#define PI_LOG_ENTRY_K_INDEX_MIN	0		/* Minimum index for entry */
+
+typedef struct
+	{
+	PI_UINT32  cmd_type;
+	PI_UINT32  entry_index;
+	} PI_CMD_ERROR_LOG_GET_REQ;
+
+/* Error_Log_Get Response */
+
+#define PI_K_LOG_FW_SIZE			111		/* Max number of fw longwords */
+#define PI_K_LOG_DIAG_SIZE	 		6		/* Max number of diag longwords */
+
+typedef struct
+	{
+	struct 
+		{
+		PI_UINT32	fru_imp_mask;
+		PI_UINT32	test_id;
+		PI_UINT32	reserved[PI_K_LOG_DIAG_SIZE];
+		} diag;
+	PI_UINT32		fw[PI_K_LOG_FW_SIZE];
+	} PI_LOG_ENTRY;
+
+typedef struct
+	{
+	PI_RSP_HEADER   header;	
+	PI_UINT32		event_status;
+	PI_UINT32		caller_id;
+	PI_UINT32		timestamp_l;
+	PI_UINT32		timestamp_h;
+	PI_UINT32		write_count;
+	PI_LOG_ENTRY	entry_info;
+	} PI_CMD_ERROR_LOG_GET_RSP;
+
+/* Define error log related constants and types.					*/
+/*   Not all of the caller id's can occur.  The only ones currently */
+/*   implemented are: none, selftest, mfg, fw, console				*/
+
+#define PI_LOG_EVENT_STATUS_K_VALID		0	/* Valid Event Status 		*/
+#define PI_LOG_EVENT_STATUS_K_INVALID	1	/* Invalid Event Status 	*/
+#define PI_LOG_CALLER_ID_K_NONE		 	0	/* No caller 				*/
+#define PI_LOG_CALLER_ID_K_SELFTEST	 	1	/* Normal power-up selftest */			
+#define PI_LOG_CALLER_ID_K_MFG		 	2	/* Mfg power-up selftest 	*/
+#define PI_LOG_CALLER_ID_K_ONLINE		3	/* On-line diagnostics 		*/
+#define PI_LOG_CALLER_ID_K_HW			4	/* Hardware 				*/
+#define PI_LOG_CALLER_ID_K_FW			5	/* Firmware 				*/
+#define PI_LOG_CALLER_ID_K_CNS_HW		6	/* CNS firmware 			*/
+#define PI_LOG_CALLER_ID_K_CNS_FW		7	/* CNS hardware 			*/
+#define PI_LOG_CALLER_ID_K_CONSOLE	 	8   /* Console Caller Id 		*/
+
+/*
+ *  Place all DMA commands in the following request and response structures
+ *  to simplify code.
+ */
+
+typedef union
+	{
+	PI_UINT32					cmd_type;
+	PI_CMD_START_REQ			start;
+	PI_CMD_FILTERS_SET_REQ		filter_set;
+	PI_CMD_FILTERS_GET_REQ		filter_get;
+	PI_CMD_CHARS_SET_REQ		char_set;
+	PI_CMD_ADDR_FILTER_SET_REQ	addr_filter_set;
+	PI_CMD_ADDR_FILTER_GET_REQ	addr_filter_get;
+	PI_CMD_STATUS_CHARS_GET_REQ	stat_char_get;
+	PI_CMD_CNTRS_GET_REQ		cntrs_get;
+	PI_CMD_CNTRS_SET_REQ		cntrs_set;
+	PI_CMD_ERROR_LOG_CLEAR_REQ	error_log_clear;
+	PI_CMD_ERROR_LOG_GET_REQ	error_log_read;
+	PI_CMD_SNMP_SET_REQ			snmp_set;
+	PI_CMD_FDDI_MIB_GET_REQ		fddi_mib_get;
+	PI_CMD_DEC_EXT_MIB_GET_REQ	dec_mib_get;
+	PI_CMD_SMT_MIB_SET_REQ		smt_mib_set;
+	PI_CMD_SMT_MIB_GET_REQ		smt_mib_get;
+	char						pad[PI_CMD_REQ_K_SIZE_MAX]; 
+	} PI_DMA_CMD_REQ;
+
+typedef union
+	{
+	PI_RSP_HEADER				header;
+	PI_CMD_START_RSP			start;
+	PI_CMD_FILTERS_SET_RSP		filter_set;
+	PI_CMD_FILTERS_GET_RSP		filter_get;
+	PI_CMD_CHARS_SET_RSP		char_set;
+	PI_CMD_ADDR_FILTER_SET_RSP	addr_filter_set;
+	PI_CMD_ADDR_FILTER_GET_RSP	addr_filter_get;
+	PI_CMD_STATUS_CHARS_GET_RSP	stat_char_get;
+	PI_CMD_CNTRS_GET_RSP		cntrs_get;
+	PI_CMD_CNTRS_SET_RSP		cntrs_set;
+	PI_CMD_ERROR_LOG_CLEAR_RSP	error_log_clear;
+	PI_CMD_ERROR_LOG_GET_RSP	error_log_get;
+	PI_CMD_SNMP_SET_RSP			snmp_set;
+	PI_CMD_FDDI_MIB_GET_RSP		fddi_mib_get;
+	PI_CMD_DEC_EXT_MIB_GET_RSP	dec_mib_get;
+	PI_CMD_SMT_MIB_SET_RSP		smt_mib_set;
+	PI_CMD_SMT_MIB_GET_RSP		smt_mib_get;
+	char						pad[PI_CMD_RSP_K_SIZE_MAX]; 
+	} PI_DMA_CMD_RSP;
+
+typedef union
+	{
+	PI_DMA_CMD_REQ	request;
+	PI_DMA_CMD_RSP	response;
+	} PI_DMA_CMD_BUFFER;
+
+
+/* Define format of Consumer Block (resident in host memory) */
+
+typedef struct
+	{
+	volatile PI_UINT32	xmt_rcv_data;
+	volatile PI_UINT32	reserved_1;
+	volatile PI_UINT32	smt_host;
+	volatile PI_UINT32	reserved_2;
+	volatile PI_UINT32	unsol;
+	volatile PI_UINT32	reserved_3;
+	volatile PI_UINT32	cmd_rsp;
+	volatile PI_UINT32	reserved_4;
+	volatile PI_UINT32	cmd_req;
+	volatile PI_UINT32	reserved_5;
+	} PI_CONSUMER_BLOCK;
+
+#define PI_CONS_M_RCV_INDEX			0x000000FF
+#define PI_CONS_M_XMT_INDEX			0x00FF0000
+#define PI_CONS_V_RCV_INDEX			0
+#define PI_CONS_V_XMT_INDEX			16
+
+/* Offsets into consumer block */
+
+#define PI_CONS_BLK_K_XMT_RCV		0x00
+#define PI_CONS_BLK_K_SMT_HOST		0x08
+#define PI_CONS_BLK_K_UNSOL			0x10
+#define PI_CONS_BLK_K_CMD_RSP		0x18
+#define PI_CONS_BLK_K_CMD_REQ		0x20
+
+/* Offsets into descriptor block */
+
+#define PI_DESCR_BLK_K_RCV_DATA		0x0000
+#define PI_DESCR_BLK_K_XMT_DATA		0x0800
+#define PI_DESCR_BLK_K_SMT_HOST 	0x1000
+#define PI_DESCR_BLK_K_UNSOL		0x1200
+#define PI_DESCR_BLK_K_CMD_RSP		0x1280
+#define PI_DESCR_BLK_K_CMD_REQ		0x1300	
+
+/* Define format of a rcv descr (Rcv Data, Cmd Rsp, Unsolicited, SMT Host)   */
+/*   Note a field has been added for later versions of the PDQ to allow for  */
+/*   finer granularity of the rcv buffer alignment.  For backwards		 	 */
+/*   compatibility, the two bits (which allow the rcv buffer to be longword  */
+/*   aligned) have been added at the MBZ bits.  To support previous drivers, */
+/*   the MBZ definition is left intact.									  	 */
+
+typedef struct
+	{
+	PI_UINT32	long_0;
+	PI_UINT32	long_1;
+	} PI_RCV_DESCR;
+
+#define	PI_RCV_DESCR_M_SOP	  		0x80000000
+#define PI_RCV_DESCR_M_SEG_LEN_LO 	0x60000000 
+#define PI_RCV_DESCR_M_MBZ	  		0x60000000 
+#define PI_RCV_DESCR_M_SEG_LEN		0x1F800000
+#define PI_RCV_DESCR_M_SEG_LEN_HI	0x1FF00000	  
+#define PI_RCV_DESCR_M_SEG_CNT	  	0x000F0000
+#define PI_RCV_DESCR_M_BUFF_HI	  	0x0000FFFF
+
+#define	PI_RCV_DESCR_V_SOP	  		31
+#define PI_RCV_DESCR_V_SEG_LEN_LO 	29
+#define PI_RCV_DESCR_V_MBZ	  		29
+#define PI_RCV_DESCR_V_SEG_LEN	  	23
+#define PI_RCV_DESCR_V_SEG_LEN_HI 	20	  
+#define PI_RCV_DESCR_V_SEG_CNT	  	16
+#define PI_RCV_DESCR_V_BUFF_HI	 	0
+
+/* Define the format of a transmit descriptor (Xmt Data, Cmd Req) */
+
+typedef struct
+	{
+	PI_UINT32	long_0;
+	PI_UINT32	long_1;
+	} PI_XMT_DESCR;
+
+#define	PI_XMT_DESCR_M_SOP			0x80000000
+#define PI_XMT_DESCR_M_EOP			0x40000000
+#define PI_XMT_DESCR_M_MBZ			0x20000000 
+#define PI_XMT_DESCR_M_SEG_LEN		0x1FFF0000
+#define PI_XMT_DESCR_M_BUFF_HI		0x0000FFFF
+
+#define	PI_XMT_DESCR_V_SOP			31
+#define	PI_XMT_DESCR_V_EOP			30
+#define PI_XMT_DESCR_V_MBZ			29
+#define PI_XMT_DESCR_V_SEG_LEN		16
+#define PI_XMT_DESCR_V_BUFF_HI		0
+
+/* Define format of the Descriptor Block (resident in host memory) */
+
+#define PI_RCV_DATA_K_NUM_ENTRIES			256
+#define PI_XMT_DATA_K_NUM_ENTRIES			256
+#define PI_SMT_HOST_K_NUM_ENTRIES			64
+#define PI_UNSOL_K_NUM_ENTRIES				16
+#define PI_CMD_RSP_K_NUM_ENTRIES			16
+#define PI_CMD_REQ_K_NUM_ENTRIES			16
+
+typedef struct
+	{
+	PI_RCV_DESCR  rcv_data[PI_RCV_DATA_K_NUM_ENTRIES];
+	PI_XMT_DESCR  xmt_data[PI_XMT_DATA_K_NUM_ENTRIES];
+	PI_RCV_DESCR  smt_host[PI_SMT_HOST_K_NUM_ENTRIES];
+	PI_RCV_DESCR  unsol[PI_UNSOL_K_NUM_ENTRIES];
+	PI_RCV_DESCR  cmd_rsp[PI_CMD_RSP_K_NUM_ENTRIES];
+	PI_XMT_DESCR  cmd_req[PI_CMD_REQ_K_NUM_ENTRIES];
+	} PI_DESCR_BLOCK;
+
+/* Define Port Registers - offsets from PDQ Base address */
+
+#define PI_PDQ_K_REG_PORT_RESET			0x00000000
+#define PI_PDQ_K_REG_HOST_DATA			0x00000004
+#define PI_PDQ_K_REG_PORT_CTRL			0x00000008
+#define PI_PDQ_K_REG_PORT_DATA_A		0x0000000C
+#define PI_PDQ_K_REG_PORT_DATA_B		0x00000010
+#define PI_PDQ_K_REG_PORT_STATUS		0x00000014
+#define PI_PDQ_K_REG_TYPE_0_STATUS 		0x00000018
+#define PI_PDQ_K_REG_HOST_INT_ENB	  	0x0000001C
+#define PI_PDQ_K_REG_TYPE_2_PROD_NOINT 	0x00000020
+#define PI_PDQ_K_REG_TYPE_2_PROD		0x00000024
+#define PI_PDQ_K_REG_CMD_RSP_PROD		0x00000028
+#define PI_PDQ_K_REG_CMD_REQ_PROD		0x0000002C
+#define PI_PDQ_K_REG_SMT_HOST_PROD   	0x00000030
+#define PI_PDQ_K_REG_UNSOL_PROD			0x00000034
+
+/* Port Control Register - Command codes for primary commands */
+
+#define PI_PCTRL_M_CMD_ERROR			0x8000
+#define PI_PCTRL_M_BLAST_FLASH			0x4000
+#define PI_PCTRL_M_HALT					0x2000
+#define PI_PCTRL_M_COPY_DATA			0x1000
+#define PI_PCTRL_M_ERROR_LOG_START		0x0800
+#define PI_PCTRL_M_ERROR_LOG_READ		0x0400
+#define PI_PCTRL_M_XMT_DATA_FLUSH_DONE	0x0200
+#define PI_PCTRL_M_INIT					0x0100
+#define PI_PCTRL_M_INIT_START		    0x0080
+#define PI_PCTRL_M_CONS_BLOCK			0x0040
+#define PI_PCTRL_M_UNINIT				0x0020
+#define PI_PCTRL_M_RING_MEMBER			0x0010
+#define PI_PCTRL_M_MLA					0x0008		
+#define PI_PCTRL_M_FW_REV_READ			0x0004
+#define PI_PCTRL_M_DEV_SPECIFIC			0x0002
+#define PI_PCTRL_M_SUB_CMD				0x0001
+
+/* Define sub-commands accessed via the PI_PCTRL_M_SUB_CMD command */
+
+#define PI_SUB_CMD_K_LINK_UNINIT		0x0001
+#define PI_SUB_CMD_K_BURST_SIZE_SET		0x0002
+#define PI_SUB_CMD_K_PDQ_REV_GET		0x0004
+#define PI_SUB_CMD_K_HW_REV_GET			0x0008
+
+/* Define some Port Data B values */
+
+#define PI_PDATA_B_DMA_BURST_SIZE_4	 	0		/* valid values for command */
+#define PI_PDATA_B_DMA_BURST_SIZE_8	 	1
+#define PI_PDATA_B_DMA_BURST_SIZE_16	2
+#define PI_PDATA_B_DMA_BURST_SIZE_32	3		/* not supported on PCI */
+#define PI_PDATA_B_DMA_BURST_SIZE_DEF	PI_PDATA_B_DMA_BURST_SIZE_16
+
+/* Port Data A Reset state */
+
+#define PI_PDATA_A_RESET_M_UPGRADE		0x00000001
+#define PI_PDATA_A_RESET_M_SOFT_RESET	0x00000002
+#define PI_PDATA_A_RESET_M_SKIP_ST		0x00000004
+
+/* Read adapter MLA address port control command constants */
+
+#define PI_PDATA_A_MLA_K_LO				0
+#define PI_PDATA_A_MLA_K_HI				1
+
+/* Byte Swap values for init command */
+
+#define PI_PDATA_A_INIT_M_DESC_BLK_ADDR			0x0FFFFE000
+#define PI_PDATA_A_INIT_M_RESERVED				0x000001FFC
+#define PI_PDATA_A_INIT_M_BSWAP_DATA			0x000000002 
+#define PI_PDATA_A_INIT_M_BSWAP_LITERAL			0x000000001
+
+#define PI_PDATA_A_INIT_V_DESC_BLK_ADDR			13
+#define PI_PDATA_A_INIT_V_RESERVED				3
+#define PI_PDATA_A_INIT_V_BSWAP_DATA			1 
+#define PI_PDATA_A_INIT_V_BSWAP_LITERAL			0
+
+/* Port Reset Register */
+
+#define PI_RESET_M_ASSERT_RESET			1
+
+/* Port Status register */
+
+#define PI_PSTATUS_V_RCV_DATA_PENDING	31
+#define PI_PSTATUS_V_XMT_DATA_PENDING	30
+#define PI_PSTATUS_V_SMT_HOST_PENDING	29
+#define PI_PSTATUS_V_UNSOL_PENDING		28
+#define PI_PSTATUS_V_CMD_RSP_PENDING	27
+#define PI_PSTATUS_V_CMD_REQ_PENDING	26
+#define PI_PSTATUS_V_TYPE_0_PENDING		25
+#define PI_PSTATUS_V_RESERVED_1			16
+#define PI_PSTATUS_V_RESERVED_2			11
+#define PI_PSTATUS_V_STATE				8
+#define PI_PSTATUS_V_HALT_ID			0
+
+#define PI_PSTATUS_M_RCV_DATA_PENDING	0x80000000
+#define PI_PSTATUS_M_XMT_DATA_PENDING	0x40000000
+#define PI_PSTATUS_M_SMT_HOST_PENDING	0x20000000
+#define PI_PSTATUS_M_UNSOL_PENDING		0x10000000
+#define PI_PSTATUS_M_CMD_RSP_PENDING	0x08000000
+#define PI_PSTATUS_M_CMD_REQ_PENDING	0x04000000
+#define PI_PSTATUS_M_TYPE_0_PENDING		0x02000000
+#define PI_PSTATUS_M_RESERVED_1			0x01FF0000
+#define PI_PSTATUS_M_RESERVED_2			0x0000F800
+#define PI_PSTATUS_M_STATE				0x00000700
+#define PI_PSTATUS_M_HALT_ID			0x000000FF
+
+/* Define Halt Id's			 					*/
+/*   Do not insert into this list, only append. */
+
+#define PI_HALT_ID_K_SELFTEST_TIMEOUT	0
+#define PI_HALT_ID_K_PARITY_ERROR		1
+#define PI_HALT_ID_K_HOST_DIR_HALT		2
+#define PI_HALT_ID_K_SW_FAULT			3
+#define PI_HALT_ID_K_HW_FAULT			4
+#define PI_HALT_ID_K_PC_TRACE			5
+#define PI_HALT_ID_K_DMA_ERROR			6			/* Host Data has error reg */
+#define PI_HALT_ID_K_IMAGE_CRC_ERROR	7   		/* Image is bad, update it */
+#define PI_HALT_ID_K_BUS_EXCEPTION	 	8   		/* 68K bus exception	   */
+
+/* Host Interrupt Enable Register as seen by host */ 
+
+#define PI_HOST_INT_M_XMT_DATA_ENB		0x80000000	/* Type 2 Enables */
+#define PI_HOST_INT_M_RCV_DATA_ENB		0x40000000  
+#define PI_HOST_INT_M_SMT_HOST_ENB		0x10000000	/* Type 1 Enables */ 
+#define PI_HOST_INT_M_UNSOL_ENB			0x20000000
+#define PI_HOST_INT_M_CMD_RSP_ENB		0x08000000
+#define PI_HOST_INT_M_CMD_REQ_ENB		0x04000000
+#define	PI_HOST_INT_M_TYPE_1_RESERVED	0x00FF0000
+#define	PI_HOST_INT_M_TYPE_0_RESERVED	0x0000FF00	/* Type 0 Enables */
+#define PI_HOST_INT_M_1MS				0x00000080
+#define PI_HOST_INT_M_20MS				0x00000040
+#define PI_HOST_INT_M_CSR_CMD_DONE		0x00000020
+#define PI_HOST_INT_M_STATE_CHANGE		0x00000010
+#define PI_HOST_INT_M_XMT_FLUSH			0x00000008
+#define PI_HOST_INT_M_NXM				0x00000004
+#define PI_HOST_INT_M_PM_PAR_ERR		0x00000002
+#define PI_HOST_INT_M_BUS_PAR_ERR		0x00000001
+
+#define PI_HOST_INT_V_XMT_DATA_ENB		31			/* Type 2 Enables */
+#define PI_HOST_INT_V_RCV_DATA_ENB		30  
+#define PI_HOST_INT_V_SMT_HOST_ENB		29			/* Type 1 Enables */ 
+#define PI_HOST_INT_V_UNSOL_ENB			28
+#define PI_HOST_INT_V_CMD_RSP_ENB		27
+#define PI_HOST_INT_V_CMD_REQ_ENB		26
+#define	PI_HOST_INT_V_TYPE_1_RESERVED	16
+#define	PI_HOST_INT_V_TYPE_0_RESERVED   8			/* Type 0 Enables */
+#define PI_HOST_INT_V_1MS_ENB			7
+#define PI_HOST_INT_V_20MS_ENB			6
+#define PI_HOST_INT_V_CSR_CMD_DONE_ENB	5
+#define PI_HOST_INT_V_STATE_CHANGE_ENB	4
+#define PI_HOST_INT_V_XMT_FLUSH_ENB 	3
+#define PI_HOST_INT_V_NXM_ENB			2
+#define PI_HOST_INT_V_PM_PAR_ERR_ENB	1
+#define PI_HOST_INT_V_BUS_PAR_ERR_ENB	0
+
+#define PI_HOST_INT_K_ACK_ALL_TYPE_0	0x000000FF
+#define PI_HOST_INT_K_DISABLE_ALL_INTS	0x00000000
+#define PI_HOST_INT_K_ENABLE_ALL_INTS	0xFFFFFFFF
+#define PI_HOST_INT_K_ENABLE_DEF_INTS	0xC000001F
+
+/* Type 0 Interrupt Status Register */
+
+#define PI_TYPE_0_STAT_M_1MS			0x00000080
+#define PI_TYPE_0_STAT_M_20MS			0x00000040
+#define PI_TYPE_0_STAT_M_CSR_CMD_DONE	0x00000020
+#define PI_TYPE_0_STAT_M_STATE_CHANGE	0x00000010
+#define PI_TYPE_0_STAT_M_XMT_FLUSH		0x00000008
+#define PI_TYPE_0_STAT_M_NXM			0x00000004
+#define PI_TYPE_0_STAT_M_PM_PAR_ERR		0x00000002
+#define PI_TYPE_0_STAT_M_BUS_PAR_ERR	0x00000001
+
+#define PI_TYPE_0_STAT_V_1MS			7			
+#define PI_TYPE_0_STAT_V_20MS			6	
+#define PI_TYPE_0_STAT_V_CSR_CMD_DONE	5
+#define PI_TYPE_0_STAT_V_STATE_CHANGE	4
+#define PI_TYPE_0_STAT_V_XMT_FLUSH		3
+#define PI_TYPE_0_STAT_V_NXM			2
+#define PI_TYPE_0_STAT_V_PM_PAR_ERR		1
+#define PI_TYPE_0_STAT_V_BUS_PAR_ERR	0
+
+/* Register definition structures are defined for both big and little endian systems */
+
+#ifndef  BIG_ENDIAN
+
+/* Little endian format of Type 1 Producer register */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	prod;
+		PI_UINT8	comp;
+		PI_UINT8	mbz_1;
+		PI_UINT8	mbz_2;
+		} index;
+	} PI_TYPE_1_PROD_REG;
+
+/* Little endian format of Type 2 Producer register */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	rcv_prod;
+		PI_UINT8	xmt_prod;
+		PI_UINT8	rcv_comp;
+		PI_UINT8	xmt_comp;
+		} index;
+	} PI_TYPE_2_PROD_REG;
+
+/* Little endian format of Type 1 Consumer Block longword */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	cons;
+		PI_UINT8	res0;
+		PI_UINT8	res1;
+		PI_UINT8	res2;
+		} index;
+	} PI_TYPE_1_CONSUMER;
+
+/* Little endian format of Type 2 Consumer Block longword */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	rcv_cons;
+		PI_UINT8	res0;
+		PI_UINT8	xmt_cons;
+		PI_UINT8	res1;
+		} index;
+	} PI_TYPE_2_CONSUMER;
+
+#else
+
+/* Big endian format of Type 1 Producer register */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	mbz_2;
+		PI_UINT8	mbz_1;
+		PI_UINT8	comp;
+		PI_UINT8	prod;
+		} index;
+	} PI_TYPE_1_PROD_REG;
+
+/* Big endian format of Type 2 Producer register */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	xmt_comp;
+		PI_UINT8	rcv_comp;
+		PI_UINT8	xmt_prod;
+		PI_UINT8	rcv_prod;
+		} index;
+	} PI_TYPE_2_PROD_REG;
+
+/* Big endian format of Type 1 Consumer Block longword */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	res2;
+		PI_UINT8	res1;
+		PI_UINT8	res0;
+		PI_UINT8	cons;
+		} index;
+	} PI_TYPE_1_CONSUMER;
+
+/* Big endian format of Type 2 Consumer Block longword */
+
+typedef union
+	{
+	PI_UINT32	lword;
+	struct
+		{
+		PI_UINT8	res1;
+		PI_UINT8	xmt_cons;
+		PI_UINT8	res0;
+		PI_UINT8	rcv_cons;
+		} index;
+	} PI_TYPE_2_CONSUMER;
+
+#endif	/* #ifndef BIG_ENDIAN */
+
+/* Define EISA controller register offsets */
+
+#define PI_ESIC_K_BURST_HOLDOFF			0x040
+#define PI_ESIC_K_SLOT_ID            	0xC80
+#define PI_ESIC_K_SLOT_CNTRL			0xC84
+#define PI_ESIC_K_MEM_ADD_CMP_0     	0xC85
+#define PI_ESIC_K_MEM_ADD_CMP_1     	0xC86
+#define PI_ESIC_K_MEM_ADD_CMP_2     	0xC87
+#define PI_ESIC_K_MEM_ADD_HI_CMP_0  	0xC88
+#define PI_ESIC_K_MEM_ADD_HI_CMP_1  	0xC89
+#define PI_ESIC_K_MEM_ADD_HI_CMP_2  	0xC8A
+#define PI_ESIC_K_MEM_ADD_MASK_0     	0xC8B
+#define PI_ESIC_K_MEM_ADD_MASK_1     	0xC8C
+#define PI_ESIC_K_MEM_ADD_MASK_2     	0xC8D
+#define PI_ESIC_K_MEM_ADD_LO_CMP_0  	0xC8E
+#define PI_ESIC_K_MEM_ADD_LO_CMP_1  	0xC8F
+#define PI_ESIC_K_MEM_ADD_LO_CMP_2  	0xC90
+#define PI_ESIC_K_IO_CMP_0_0			0xC91
+#define PI_ESIC_K_IO_CMP_0_1			0xC92
+#define PI_ESIC_K_IO_CMP_1_0			0xC93
+#define PI_ESIC_K_IO_CMP_1_1			0xC94
+#define PI_ESIC_K_IO_CMP_2_0			0xC95
+#define PI_ESIC_K_IO_CMP_2_1			0xC96
+#define PI_ESIC_K_IO_CMP_3_0			0xC97
+#define PI_ESIC_K_IO_CMP_3_1			0xC98
+#define PI_ESIC_K_IO_ADD_MASK_0_0    	0xC99
+#define PI_ESIC_K_IO_ADD_MASK_0_1    	0xC9A
+#define PI_ESIC_K_IO_ADD_MASK_1_0    	0xC9B
+#define PI_ESIC_K_IO_ADD_MASK_1_1    	0xC9C
+#define PI_ESIC_K_IO_ADD_MASK_2_0    	0xC9D
+#define PI_ESIC_K_IO_ADD_MASK_2_1    	0xC9E
+#define PI_ESIC_K_IO_ADD_MASK_3_0    	0xC9F
+#define PI_ESIC_K_IO_ADD_MASK_3_1    	0xCA0
+#define PI_ESIC_K_MOD_CONFIG_1			0xCA1
+#define PI_ESIC_K_MOD_CONFIG_2			0xCA2
+#define PI_ESIC_K_MOD_CONFIG_3			0xCA3
+#define PI_ESIC_K_MOD_CONFIG_4			0xCA4
+#define PI_ESIC_K_MOD_CONFIG_5    		0xCA5
+#define PI_ESIC_K_MOD_CONFIG_6			0xCA6
+#define PI_ESIC_K_MOD_CONFIG_7			0xCA7
+#define PI_ESIC_K_DIP_SWITCH         	0xCA8
+#define PI_ESIC_K_IO_CONFIG_STAT_0   	0xCA9
+#define PI_ESIC_K_IO_CONFIG_STAT_1   	0xCAA
+#define PI_ESIC_K_DMA_CONFIG         	0xCAB
+#define PI_ESIC_K_INPUT_PORT         	0xCAC
+#define PI_ESIC_K_OUTPUT_PORT        	0xCAD
+#define PI_ESIC_K_FUNCTION_CNTRL		0xCAE
+#define PI_ESIC_K_CSR_IO_LEN			PI_ESIC_K_FUNCTION_CNTRL+1	/* always last reg + 1 */
+
+/* Define the value all drivers must write to the function control register. */
+
+#define PI_ESIC_K_FUNCTION_CNTRL_IO_ENB	0x03
+
+/* Define the bits in the slot control register. */
+
+#define PI_SLOT_CNTRL_M_RESET		0x04	/* Don't use.       */
+#define PI_SLOT_CNTRL_M_ERROR		0x02	/* Not implemented. */
+#define PI_SLOT_CNTRL_M_ENB			0x01	/* Must be set.     */
+
+/* Define the bits in the burst holdoff register. */
+
+#define PI_BURST_HOLDOFF_M_HOLDOFF	0xFC
+#define PI_BURST_HOLDOFF_M_RESERVED	0x02
+#define PI_BURST_HOLDOFF_M_MEM_MAP	0x01
+
+#define PI_BURST_HOLDOFF_V_HOLDOFF	2
+#define PI_BURST_HOLDOFF_V_RESERVED	1
+#define PI_BURST_HOLDOFF_V_MEM_MAP	0
+
+/*
+ * Define the fields in the IO Compare registers.
+ * The driver must initialize the slot field with the slot ID shifted by the
+ * amount shown below.
+ */
+
+#define PI_IO_CMP_V_SLOT		4
+
+/* Define the fields in the Interrupt Channel Configuration and Status reg */
+
+#define PI_CONFIG_STAT_0_M_PEND			0x80
+#define PI_CONFIG_STAT_0_M_RES_1		0x40
+#define PI_CONFIG_STAT_0_M_IREQ_OUT		0x20
+#define PI_CONFIG_STAT_0_M_IREQ_IN		0x10
+#define PI_CONFIG_STAT_0_M_INT_ENB		0x08
+#define PI_CONFIG_STAT_0_M_RES_0		0x04
+#define PI_CONFIG_STAT_0_M_IRQ			0x03
+
+#define PI_CONFIG_STAT_0_V_PEND			7
+#define PI_CONFIG_STAT_0_V_RES_1		6
+#define PI_CONFIG_STAT_0_V_IREQ_OUT		5
+#define PI_CONFIG_STAT_0_V_IREQ_IN		4
+#define PI_CONFIG_STAT_0_V_INT_ENB		3
+#define PI_CONFIG_STAT_0_V_RES_0		2
+#define PI_CONFIG_STAT_0_V_IRQ			0
+
+#define PI_CONFIG_STAT_0_IRQ_K_9		0
+#define PI_CONFIG_STAT_0_IRQ_K_10		1
+#define PI_CONFIG_STAT_0_IRQ_K_11		2
+#define PI_CONFIG_STAT_0_IRQ_K_15		3
+
+/* Define DEC FDDIcontroller/EISA (DEFEA) EISA hardware ID's */
+
+#define DEFEA_PRODUCT_ID	0x0030A310		/* DEC product 300 (no rev)	*/
+#define DEFEA_PROD_ID_1		0x0130A310		/* DEC product 300, rev 1	*/
+#define DEFEA_PROD_ID_2		0x0230A310		/* DEC product 300, rev 2	*/
+#define DEFEA_PROD_ID_3		0x0330A310		/* DEC product 300, rev 3	*/
+
+/**********************************************/
+/* Digital PFI Specification v1.0 Definitions */
+/**********************************************/
+
+/* PCI Configuration Space Constants */
+
+#define PFI_K_LAT_TIMER_DEF			0x88	/* def max master latency timer */
+#define PFI_K_LAT_TIMER_MIN			0x20	/* min max master latency timer */
+#define PFI_K_CSR_MEM_LEN			0x80	/* 128 bytes */
+#define PFI_K_CSR_IO_LEN			0x80	/* 128 bytes */
+#define PFI_K_PKT_MEM_LEN			0x10000	/* 64K bytes */
+
+/* PFI Register Offsets (starting at PDQ Register Base Address) */
+
+#define PFI_K_REG_RESERVED_0		 0X00000038
+#define PFI_K_REG_RESERVED_1		 0X0000003C
+#define PFI_K_REG_MODE_CTRL			 0X00000040
+#define PFI_K_REG_STATUS			 0X00000044
+#define PFI_K_REG_FIFO_WRITE		 0X00000048
+#define PFI_K_REG_FIFO_READ			 0X0000004C
+
+/* PFI Mode Control Register Constants */
+
+#define PFI_MODE_M_RESERVED			 0XFFFFFFF0
+#define PFI_MODE_M_TGT_ABORT_ENB	 0X00000008
+#define PFI_MODE_M_PDQ_INT_ENB		 0X00000004
+#define PFI_MODE_M_PFI_INT_ENB		 0X00000002
+#define PFI_MODE_M_DMA_ENB			 0X00000001
+
+#define PFI_MODE_V_RESERVED			 4
+#define PFI_MODE_V_TGT_ABORT_ENB	 3
+#define PFI_MODE_V_PDQ_INT_ENB		 2
+#define PFI_MODE_V_PFI_INT_ENB		 1
+#define PFI_MODE_V_DMA_ENB			 0
+
+#define PFI_MODE_K_ALL_DISABLE		 0X00000000
+
+/* PFI Status Register Constants */
+
+#define PFI_STATUS_M_RESERVED		 0XFFFFFFC0
+#define PFI_STATUS_M_PFI_ERROR		 0X00000020		/* only valid in rev 1 or later PFI */
+#define PFI_STATUS_M_PDQ_INT		 0X00000010
+#define PFI_STATUS_M_PDQ_DMA_ABORT	 0X00000008
+#define PFI_STATUS_M_FIFO_FULL		 0X00000004
+#define PFI_STATUS_M_FIFO_EMPTY		 0X00000002
+#define PFI_STATUS_M_DMA_IN_PROGRESS 0X00000001
+
+#define PFI_STATUS_V_RESERVED		 6
+#define PFI_STATUS_V_PFI_ERROR		 5				/* only valid in rev 1 or later PFI */
+#define PFI_STATUS_V_PDQ_INT		 4
+#define PFI_STATUS_V_PDQ_DMA_ABORT	 3
+#define PFI_STATUS_V_FIFO_FULL		 2
+#define PFI_STATUS_V_FIFO_EMPTY		 1
+#define PFI_STATUS_V_DMA_IN_PROGRESS 0
+
+#define DFX_MAX_EISA_SLOTS		16			/* maximum number of EISA slots to scan */
+#define DFX_MAX_NUM_BOARDS		8			/* maximum number of adapters supported */
+
+#define DFX_BUS_TYPE_PCI		0			/* type code for DEC FDDIcontroller/PCI */
+#define DFX_BUS_TYPE_EISA		1			/* type code for DEC FDDIcontroller/EISA */
+
+#define DFX_FC_PRH2_PRH1_PRH0	0x54003820	/* Packet Request Header bytes + FC */
+#define DFX_PRH0_BYTE			0x20		/* Packet Request Header byte 0 */
+#define DFX_PRH1_BYTE			0x38		/* Packet Request Header byte 1 */
+#define DFX_PRH2_BYTE			0x00		/* Packet Request Header byte 2 */
+
+/* Driver routine status (return) codes */
+
+#define DFX_K_SUCCESS			0			/* routine succeeded */
+#define DFX_K_FAILURE			1			/* routine failed */
+#define DFX_K_OUTSTATE			2			/* bad state for command */
+#define DFX_K_HW_TIMEOUT		3			/* command timed out */
+
+/* Define LLC host receive buffer min/max/default values */
+
+#define RCV_BUFS_MIN	2					/* minimum pre-allocated receive buffers */
+#define RCV_BUFS_MAX	32					/* maximum pre-allocated receive buffers */
+#define RCV_BUFS_DEF	8					/* default pre-allocated receive buffers */
+
+/* Define offsets into FDDI LLC or SMT receive frame buffers - used when indicating frames */
+
+#define RCV_BUFF_K_DESCR	0				/* four byte FMC descriptor */
+#define RCV_BUFF_K_PADDING	4				/* three null bytes */
+#define RCV_BUFF_K_FC		7				/* one byte frame control */
+#define RCV_BUFF_K_DA		8				/* six byte destination address */
+#define RCV_BUFF_K_SA		14				/* six byte source address */
+#define RCV_BUFF_K_DATA		20				/* offset to start of packet data */
+
+/* Define offsets into FDDI LLC transmit frame buffers - used when sending frames */
+
+#define XMT_BUFF_K_FC		0				/* one byte frame control */
+#define XMT_BUFF_K_DA		1				/* six byte destination address */
+#define XMT_BUFF_K_SA		7				/* six byte source address */
+#define XMT_BUFF_K_DATA		13				/* offset to start of packet data */
+
+/*
+ * Macro evaluates to "value" aligned to "size" bytes.  Make sure that
+ * "size" is greater than 0 bytes.
+ */
+
+#define ALIGN(value,size) ((value + (size - 1)) & ~(size - 1))
+
+/* Macro for checking a "value" is within a specific range */
+
+#define IN_RANGE(value,low,high) ((value >= low) && (value <= high))
+
+/* Only execute special print call when debug driver was built */
+
+#ifdef DEFXX_DEBUG
+#define DBG_printk(args...) printk(## args)
+#else
+#define DBG_printk(args...)
+#endif
+
+/* Define constants for masking/unmasking interrupts */
+
+#define DFX_MASK_INTERRUPTS		1
+#define DFX_UNMASK_INTERRUPTS	0
+
+/* Define structure for driver transmit descriptor block */
+
+typedef struct
+	{
+	struct sk_buff	*p_skb;					/* ptr to skb */
+	} XMT_DRIVER_DESCR;
+
+typedef struct DFX_board_tag
+	{
+	/* Keep virtual and physical pointers to locked, physically contiguous memory */
+
+	PI_DESCR_BLOCK			*descr_block_virt;				/* PDQ descriptor block virt address */
+	u32						descr_block_phys;				/* PDQ descriptor block phys address */
+	PI_DMA_CMD_REQ			*cmd_req_virt;					/* Command request buffer virt address */
+	u32						cmd_req_phys;					/* Command request buffer phys address */
+	PI_DMA_CMD_RSP			*cmd_rsp_virt;					/* Command response buffer virt address */
+	u32						cmd_rsp_phys;					/* Command response buffer phys address */
+	char					*rcv_block_virt;				/* LLC host receive queue buf blk virt */
+	u32						rcv_block_phys;					/* LLC host receive queue buf blk phys */
+	PI_CONSUMER_BLOCK		*cons_block_virt;				/* PDQ consumer block virt address */
+	u32						cons_block_phys;				/* PDQ consumer block phys address */
+
+	/* Keep local copies of Type 1 and Type 2 register data */
+
+	PI_TYPE_1_PROD_REG		cmd_req_reg;					/* Command Request register */
+	PI_TYPE_1_PROD_REG		cmd_rsp_reg;					/* Command Response register */
+	PI_TYPE_2_PROD_REG		rcv_xmt_reg;					/* Type 2 (RCV/XMT) register */
+
+	/* Storage for unicast and multicast address entries in adapter CAM */
+
+	u8						uc_table[1*FDDI_K_ALEN];
+	u32						uc_count;						/* number of unicast addresses */
+	u8						mc_table[PI_CMD_ADDR_FILTER_K_SIZE*FDDI_K_ALEN];
+	u32						mc_count;						/* number of multicast addresses */
+
+	/* Current packet filter settings */
+
+	u32						ind_group_prom;					/* LLC individual & group frame prom mode */
+	u32						group_prom;						/* LLC group (multicast) frame prom mode */
+
+	/* Link available flag needed to determine whether to drop outgoing packet requests */
+
+	u32						link_available;					/* is link available? */
+
+	/* Resources to indicate reset type when resetting adapter */
+
+	u32						reset_type;						/* skip or rerun diagnostics */
+
+	/* Store pointers to receive buffers for queue processing code */
+
+	char					*p_rcv_buff_va[PI_RCV_DATA_K_NUM_ENTRIES];
+
+	/* Store pointers to transmit buffers for transmit completion code */
+
+	XMT_DRIVER_DESCR		xmt_drv_descr_blk[PI_XMT_DATA_K_NUM_ENTRIES];
+
+	/* Store device, bus-specific, and parameter information for this adapter */
+
+	struct device			*dev;							/* pointer to device structure */
+	u32						bus_type;						/* bus type (0 == PCI, 1 == EISA) */
+	u16						base_addr;						/* base I/O address (same as dev->base_addr) */
+	u8						pci_bus;						/* PCI bus number */
+	u8						pci_dev_fun;					/* PCI device and function numbers */
+	u32						full_duplex_enb;				/* FDDI Full Duplex enable (1 == on, 2 == off) */
+	u32						req_ttrt;						/* requested TTRT value (in 80ns units) */
+	u32						burst_size;						/* adapter burst size (enumerated) */
+	u32						rcv_bufs_to_post;				/* receive buffers to post for LLC host queue */
+	u8						factory_mac_addr[FDDI_K_ALEN];	/* factory (on-board) MAC address */
+
+	/* Common FDDI statistics structure and private counters */
+
+	struct fddi_statistics	stats;
+
+	u32						rcv_discards;
+	u32						rcv_crc_errors;
+	u32						rcv_frame_status_errors;
+	u32						rcv_length_errors;
+	u32						rcv_total_frames;
+	u32						rcv_multicast_frames;
+	u32						xmt_discards;
+	u32						xmt_length_errors;
+	u32						xmt_total_frames;
+	} DFX_board_t;
+
+#endif	/* #ifndef _DEFXX_H_ */
diff -u --recursive --new-file v2.1.10/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.1.10/linux/drivers/net/dgrs.c	Wed Oct 16 10:48:17 1996
+++ linux/drivers/net/dgrs.c	Mon Nov 18 11:31:31 1996
@@ -36,6 +36,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
diff -u --recursive --new-file v2.1.10/linux/drivers/net/dlci.c linux/drivers/net/dlci.c
--- v2.1.10/linux/drivers/net/dlci.c	Wed Oct 16 10:48:17 1996
+++ linux/drivers/net/dlci.c	Mon Nov 18 11:31:31 1996
@@ -43,6 +43,8 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
+#include <asm/uaccess.h>
+
 #include <linux/errno.h>
 
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.1.10/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v2.1.10/linux/drivers/net/eth16i.c	Wed Oct  9 08:55:19 1996
+++ linux/drivers/net/eth16i.c	Mon Nov 18 11:31:31 1996
@@ -181,8 +181,8 @@
 #define BUFFER_WIDTH_8         BIT(4)       /* 1 = 8bit, 0 = 16bit */
 #define TBS1                   BIT(3)       
 #define TBS0                   BIT(2)
-#define BS1                    BIT(1)       /* 00=8kb,  01=16kb  */
-#define BS0                    BIT(0)       /* 10=32kb, 11=64kb  */
+#define MBS1                   BIT(1)       /* 00=8kb,  01=16kb  */
+#define MBS0                   BIT(0)       /* 10=32kb, 11=64kb  */
 
 #ifndef ETH16I_TX_BUF_SIZE                   /* 0 = 2kb, 1 = 4kb  */ 
 #define ETH16I_TX_BUF_SIZE     2             /* 2 = 8kb, 3 = 16kb */
@@ -327,7 +327,7 @@
 static int eth16i_tx(struct sk_buff *skb, struct device *dev);
 static void eth16i_rx(struct device *dev);
 static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static void eth16i_multicast(struct device *dev, int num_addrs, void *addrs); 
+static void eth16i_multicast(struct device *dev); 
 static void eth16i_select_regbank(unsigned char regbank, short ioaddr);
 static void eth16i_initialize(struct device *dev);
 static struct enet_statistics *eth16i_get_stats(struct device *dev);
@@ -505,10 +505,10 @@
   if( (node_w & 0xFF00) == 0x0800)
     node_byte |= BUFFER_WIDTH_8;
 
-  node_byte |= BS1;
+  node_byte |= MBS1;
 
   if( (node_w & 0x00FF) == 64)
-    node_byte |= BS0;
+    node_byte |= MBS0;
   
   node_byte |= DLC_EN | SRAM_CYCLE_TIME_100NS | (ETH16I_TX_BUF_SIZE << 2);
 
@@ -1147,7 +1147,7 @@
   return;
 }
 
-static void eth16i_multicast(struct device *dev, int num_addrs, void *addrs)
+static void eth16i_multicast(struct device *dev)
 {
   short ioaddr = dev->base_addr;
   
diff -u --recursive --new-file v2.1.10/linux/drivers/net/hdlcdrv.c linux/drivers/net/hdlcdrv.c
--- v2.1.10/linux/drivers/net/hdlcdrv.c	Fri Nov  1 17:13:18 1996
+++ linux/drivers/net/hdlcdrv.c	Mon Nov 18 11:31:31 1996
@@ -37,6 +37,7 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/net.h>
 #include <linux/in.h>
 #include <linux/if.h>
 #include <linux/malloc.h>
diff -u --recursive --new-file v2.1.10/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v2.1.10/linux/drivers/net/loopback.c	Tue Oct 29 19:58:12 1996
+++ linux/drivers/net/loopback.c	Mon Nov 18 11:31:31 1996
@@ -20,6 +20,8 @@
  *              Michael Griffith:       Don't bother computing the checksums
  *                                      on packets received on the loopback
  *                                      interface.
+ *		Alexey Kuznetsov:	Potential hang under some extreme
+ *					cases removed.
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -73,9 +75,9 @@
 	{
 	  	struct sk_buff *skb2=skb;
 	  	skb=skb_clone(skb, GFP_ATOMIC);		/* Clone the buffer */
-	  	if(skb==NULL)
-	  		return 1;
 	  	dev_kfree_skb(skb2, FREE_WRITE);
+	  	if(skb==NULL)
+	  		return 0;
   		unlock=0;
 	}
 	else if(skb->sk)
diff -u --recursive --new-file v2.1.10/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.1.10/linux/drivers/net/net_init.c	Sat Jun 29 12:00:46 1996
+++ linux/drivers/net/net_init.c	Mon Nov 18 11:31:31 1996
@@ -36,6 +36,7 @@
 #include <linux/etherdevice.h>
 #include <linux/trdevice.h>
 #include <linux/if_arp.h>
+#include <linux/fddidevice.h>
 #ifdef CONFIG_NET_ALIAS
 #include <linux/net_alias.h>
 #endif
@@ -154,6 +155,19 @@
 	return 0;
 }
 
+#ifdef CONFIG_FDDI
+
+static int fddi_change_mtu(struct device *dev, int new_mtu)
+{
+	if ((new_mtu < FDDI_K_SNAP_HLEN) || (new_mtu > FDDI_K_SNAP_DLEN))
+		return(-EINVAL);
+	dev->mtu = new_mtu;
+	return(0);
+}
+
+#endif
+
+
 void ether_setup(struct device *dev)
 {
 	int i;
@@ -228,6 +242,43 @@
 	dev->pa_mask	= 0;
 	dev->pa_alen	= 4;
 }
+
+#endif
+
+#ifdef CONFIG_FDDI
+
+void fddi_setup(struct device *dev)
+	{
+	int i;
+
+	/*
+	 * Fill in the fields of the device structure with FDDI-generic values.
+	 * This should be in a common file instead of per-driver.
+	 */
+	for (i=0; i < DEV_NUMBUFFS; i++)
+		skb_queue_head_init(&dev->buffs[i]);
+
+	dev->change_mtu			= fddi_change_mtu;
+	dev->hard_header		= fddi_header;
+	dev->rebuild_header		= fddi_rebuild_header;
+
+	dev->type				= ARPHRD_FDDI;
+	dev->hard_header_len	= FDDI_K_SNAP_HLEN+3;	/* Assume 802.2 SNAP hdr len + 3 pad bytes */
+	dev->mtu				= FDDI_K_SNAP_DLEN;		/* Assume max payload of 802.2 SNAP frame */
+	dev->addr_len			= FDDI_K_ALEN;
+	dev->tx_queue_len		= 100;	/* Long queues on FDDI */
+	
+	memset(dev->broadcast, 0xFF, FDDI_K_ALEN);
+
+	/* New-style flags */
+	dev->flags		= IFF_BROADCAST | IFF_MULTICAST;
+	dev->family		= AF_INET;
+	dev->pa_addr	= 0;
+	dev->pa_brdaddr = 0;
+	dev->pa_mask	= 0;
+	dev->pa_alen	= 4;
+	return;
+	}
 
 #endif
 
diff -u --recursive --new-file v2.1.10/linux/drivers/net/sdla.c linux/drivers/net/sdla.c
--- v2.1.10/linux/drivers/net/sdla.c	Wed Oct 16 10:48:19 1996
+++ linux/drivers/net/sdla.c	Mon Nov 18 11:31:31 1996
@@ -51,6 +51,7 @@
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/dma.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.1.10/linux/drivers/net/soundmodem.c linux/drivers/net/soundmodem.c
--- v2.1.10/linux/drivers/net/soundmodem.c	Fri Nov  1 17:13:18 1996
+++ linux/drivers/net/soundmodem.c	Mon Nov 18 11:31:31 1996
@@ -49,6 +49,7 @@
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
+#include <linux/net.h>
 #include <linux/in.h>
 #include <linux/string.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.1.10/linux/drivers/net/wic.c linux/drivers/net/wic.c
--- v2.1.10/linux/drivers/net/wic.c	Wed Oct 16 10:48:19 1996
+++ linux/drivers/net/wic.c	Mon Nov 18 11:31:32 1996
@@ -49,6 +49,7 @@
 #include <asm/bitops.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
+#include <asm/uaccess.h>
 #include <linux/string.h>
 
 #define NET_DEBUG 1
diff -u --recursive --new-file v2.1.10/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.1.10/linux/drivers/scsi/ppa.c	Tue Apr 16 16:08:21 1996
+++ linux/drivers/scsi/ppa.c	Mon Nov 18 11:31:32 1996
@@ -46,7 +46,7 @@
 #define   PPA_SPIN_TMO          5000000 /* ppa_wait loop limiter */
 #define   PPA_SECTOR_SIZE       512     /* for a performance hack only */
 
-#include  <unistd.h>
+#include  <linux/stddef.h>
 #include  <linux/module.h>
 #include  <linux/kernel.h>
 #include  <linux/tqueue.h>
diff -u --recursive --new-file v2.1.10/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.1.10/linux/drivers/scsi/scsi.c	Fri Nov 15 23:49:09 1996
+++ linux/drivers/scsi/scsi.c	Mon Nov 18 11:31:32 1996
@@ -311,7 +311,7 @@
 
 void scsi_make_blocked_list(void)  {
     int block_count = 0, index;
-    unsigned int flags;
+    unsigned long flags;
     struct Scsi_Host * sh[128], * shpnt;
     
     /*
@@ -1009,7 +1009,7 @@
     kdev_t dev;
     struct request * req = NULL;
     int tablesize;
-    unsigned int flags;
+    unsigned long flags;
     struct buffer_head * bh, *bhp;
     struct Scsi_Host * host;
     Scsi_Cmnd * SCpnt = NULL;
@@ -1277,7 +1277,7 @@
 
 static void scsi_request_sense (Scsi_Cmnd * SCpnt)
 {
-    unsigned int flags;
+    unsigned long flags;
     
     save_flags(flags);
     cli();
diff -u --recursive --new-file v2.1.10/linux/include/asm-alpha/uaccess.h linux/include/asm-alpha/uaccess.h
--- v2.1.10/linux/include/asm-alpha/uaccess.h	Fri Nov 15 23:49:10 1996
+++ linux/include/asm-alpha/uaccess.h	Fri Nov 15 22:36:52 1996
@@ -377,14 +377,14 @@
 
 extern long __strncpy_from_user(char *__to, const char *__from, long __to_len);
 
-#define strncpy_from_user(to,from,n)					      \
-({									      \
-	char * __sfu_to = (to);						      \
-	const char * __sfu_from = (from);				      \
-	long __sfu_len = (n), __sfu_ret = -EFAULT;			      \
-	if (__access_ok(((long)__sfu_from),__sfu_len,__access_mask))	      \
-		__sfu_ret=__strncpy_from_user(__sfu_to,__sfu_from,__sfu_len); \
-	__sfu_ret;							      \
+#define strncpy_from_user(to,from,n)					   \
+({									   \
+	char * __sfu_to = (to);						   \
+	const char * __sfu_from = (from);				   \
+	long __sfu_ret = -EFAULT;			      		   \
+	if (__access_ok(((long)__sfu_from),0,__access_mask))		   \
+		__sfu_ret = __strncpy_from_user(__sfu_to,__sfu_from,(n));  \
+	__sfu_ret;							   \
 })
 
 /* Returns: 0 if bad, string length+1 (memory size) of string if ok */
@@ -392,10 +392,7 @@
 
 extern inline long strlen_user(const char *str)
 {
-	long len = __strlen_user(str);
-	if (!access_ok(VERIFY_READ, str, len))
-		len = 0;
-	return len;
+	return access_ok(VERIFY_READ,str,0) ? __strlen_user(str) : 0;
 }
 
 /*
diff -u --recursive --new-file v2.1.10/linux/include/asm-alpha/unistd.h linux/include/asm-alpha/unistd.h
--- v2.1.10/linux/include/asm-alpha/unistd.h	Wed Oct 16 10:48:29 1996
+++ linux/include/asm-alpha/unistd.h	Mon Nov 18 10:25:04 1996
@@ -168,6 +168,8 @@
 #define __NR_nfsctl			342
 #define __NR_setresuid			343
 #define __NR_getresuid			344
+#define __NR_pciconfig_read		345
+#define __NR_pciconfig_write		346
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
diff -u --recursive --new-file v2.1.10/linux/include/asm-i386/socket.h linux/include/asm-i386/socket.h
--- v2.1.10/linux/include/asm-i386/socket.h	Sun Mar 24 12:47:39 1996
+++ linux/include/asm-i386/socket.h	Mon Nov 18 11:31:32 1996
@@ -21,5 +21,10 @@
 #define SO_LINGER	13
 #define SO_BSDCOMPAT	14
 /* To add :#define SO_REUSEPORT 15 */
+#define SO_RCVLOWAT	16
+#define SO_SNDLOWAT	17
+#define SO_RCVTIMEO	18
+#define SO_SNDTIMEO	19
+
 
 #endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v2.1.10/linux/include/asm-i386/uaccess.h linux/include/asm-i386/uaccess.h
--- v2.1.10/linux/include/asm-i386/uaccess.h	Fri Nov 15 23:49:10 1996
+++ linux/include/asm-i386/uaccess.h	Mon Nov 18 15:11:15 1996
@@ -22,10 +22,24 @@
 #define set_fs(x)	(current->tss.segment = (x))
 #define get_ds()	(KERNEL_DS)
 
+/*
+ * Address Ok:
+ *
+ *			    low two bits of segment
+ *			00 (kernel)		11 (user)
+ *
+ * high		00	1			1
+ * two 		01	1			1
+ * bits of	10	1			1
+ * address	11	1			0
+ */
+#define __addr_ok(x) \
+	((((unsigned long)(x)>>30)&get_fs()) != 3)
+
 #define __user_ok(addr,size) \
 	((size <= 0xC0000000UL) && (addr <= 0xC0000000UL - size))
 #define __kernel_ok \
-	(get_fs() == KERNEL_DS)
+	(!(get_fs() & 3))
 
 extern int __verify_write(const void *, unsigned long);
 
@@ -412,28 +426,25 @@
  *
  * Return 0 for error
  */
-extern inline long strlen_user(const char * s)
+
+extern inline long strlen_user(const char *s)
 {
-	long res;
+	unsigned long res;
+
 	__asm__ __volatile__(
-		"\n"
-		"0:\trepne ; scasb\n\t"
-		"notl %0\n"
+		"0:	repne; scasb\n"
+		"	notl %0\n"
 		"1:\n"
 		".section .fixup,\"ax\"\n"
-		"2:\txorl %0,%0\n\t"
-		"jmp 1b\n"
-		".section __ex_table,\"a\"\n\t"
-		".align 4\n\t"
-		".long 0b,2b\n"
+		"2:	xorl %0,%0\n"
+		"	jmp 1b\n"
+		".section __ex_table,\"a\"\n"
+		"	.align 4\n"
+		"	.long 0b,2b\n"
 		".text"
-		:"=c" (res)
-		:"D" (s),"a" (0),"0" (0xffffffff)
-		:"di");
-	if (!access_ok(VERIFY_READ, s, res))
-		res = 0;
-	return res;
+		:"=c" (res), "=D" (s)
+		:"1" (s), "a" (0), "0" (-__addr_ok(s)));
+	return res & -__addr_ok(s);
 }
-
 
 #endif /* __i386_UACCESS_H */
diff -u --recursive --new-file v2.1.10/linux/include/linux/atalk.h linux/include/linux/atalk.h
--- v2.1.10/linux/include/linux/atalk.h	Mon Mar 25 08:58:21 1996
+++ linux/include/linux/atalk.h	Mon Nov 18 11:31:32 1996
@@ -25,7 +25,7 @@
 
 struct sockaddr_at 
 {
-	short		sat_family;
+	sa_family_t	sat_family;
 	__u8		sat_port;
 	struct at_addr	sat_addr;
 	char		sat_zero[ 8 ];
diff -u --recursive --new-file v2.1.10/linux/include/linux/ax25.h linux/include/linux/ax25.h
--- v2.1.10/linux/include/linux/ax25.h	Tue Nov 12 15:56:14 1996
+++ linux/include/linux/ax25.h	Mon Nov 18 11:31:32 1996
@@ -41,7 +41,7 @@
 } ax25_address;
 
 struct sockaddr_ax25 {
-	short sax25_family;
+	sa_family_t sax25_family;
 	ax25_address sax25_call;
 	int sax25_ndigis;
 	/* Digipeater ax25_address sets follow */
diff -u --recursive --new-file v2.1.10/linux/include/linux/fddidevice.h linux/include/linux/fddidevice.h
--- v2.1.10/linux/include/linux/fddidevice.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/fddidevice.h	Mon Nov 18 11:31:32 1996
@@ -0,0 +1,42 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Definitions for the FDDI handlers.
+ *
+ * Version:	@(#)fddidevice.h	1.0.0	08/12/96
+ *
+ * Author:	Lawrence V. Stefani, <stefani@lkg.dec.com>
+ *
+ *		fddidevice.h is based on previous trdevice.h work by
+ *			Ross Biro, <bir7@leland.Stanford.Edu>
+ *			Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *			Alan Cox, <gw4pts@gw4pts.ampr.org>
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_FDDIDEVICE_H
+#define _LINUX_FDDIDEVICE_H
+
+#include <linux/if_fddi.h>
+
+#ifdef __KERNEL__
+extern int				fddi_header(struct sk_buff *skb,
+									struct device *dev,
+									unsigned short type,
+									void *daddr,
+									void *saddr,
+									unsigned len);
+extern int				fddi_rebuild_header(void *buff,
+											struct device *dev,
+											unsigned long dest,
+											struct sk_buff *skb);
+extern unsigned short	fddi_type_trans(struct sk_buff *skb,
+										struct device *dev);
+#endif
+
+#endif	/* _LINUX_FDDIDEVICE_H */
diff -u --recursive --new-file v2.1.10/linux/include/linux/if_arp.h linux/include/linux/if_arp.h
--- v2.1.10/linux/include/linux/if_arp.h	Tue Nov 12 15:56:14 1996
+++ linux/include/linux/if_arp.h	Mon Nov 18 15:13:20 1996
@@ -54,6 +54,7 @@
 #define ARPHRD_SKIP	771		/* SKIP vif			*/
 #define ARPHRD_LOOPBACK	772		/* Loopback device		*/
 #define ARPHRD_LOCALTLK 773		/* Localtalk device		*/
+#define ARPHRD_FDDI	774		/* FDDI interfaces		*/
 #define ARPHRD_SIT	776		/* sit0 device - IPv6-in-IPv4	*/
 
 /* ARP protocol opcodes. */
diff -u --recursive --new-file v2.1.10/linux/include/linux/if_fddi.h linux/include/linux/if_fddi.h
--- v2.1.10/linux/include/linux/if_fddi.h	Thu Jan  1 02:00:00 1970
+++ linux/include/linux/if_fddi.h	Mon Nov 18 11:31:32 1996
@@ -0,0 +1,202 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Global definitions for the ANSI FDDI interface.
+ *
+ * Version:	@(#)if_fddi.h	1.0.1	09/16/96
+ *
+ * Author:	Lawrence V. Stefani, <stefani@lkg.dec.com>
+ *
+ *		if_fddi.h is based on previous if_ether.h and if_tr.h work by
+ *			Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *			Donald Becker, <becker@super.org>
+ *			Alan Cox, <alan@cymru.net>
+ *			Steve Whitehouse, <gw7rrm@eeshack3.swan.ac.uk>
+ *			Peter De Schrijver, <stud11@cc4.kuleuven.ac.be>
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_FDDI_H
+#define _LINUX_IF_FDDI_H
+
+/*
+ *  Define max and min legal sizes.  The frame sizes do not include
+ *  4 byte FCS/CRC (frame check sequence).
+ */
+#define FDDI_K_ALEN			6		/* Octets in one FDDI address */
+#define FDDI_K_8022_HLEN	16		/* Total octets in 802.2 header */
+#define FDDI_K_SNAP_HLEN	21		/* Total octets in 802.2 SNAP header */
+#define FDDI_K_8022_ZLEN	16		/* Min octets in 802.2 frame sans FCS */
+#define FDDI_K_SNAP_ZLEN	21		/* Min octets in 802.2 SNAP frame sans FCS */
+#define FDDI_K_8022_DLEN	4475	/* Max octets in 802.2 payload */
+#define FDDI_K_SNAP_DLEN	4470	/* Max octets in 802.2 SNAP payload */
+#define FDDI_K_LLC_ZLEN		13		/* Min octets in LLC frame sans FCS */
+#define FDDI_K_LLC_LEN		4491	/* Max octets in LLC frame sans FCS */
+
+/* Define FDDI Frame Control (FC) Byte values */
+#define FDDI_FC_K_VOID					0x00	
+#define FDDI_FC_K_NON_RESTRICTED_TOKEN	0x80	
+#define FDDI_FC_K_RESTRICTED_TOKEN		0xC0	
+#define FDDI_FC_K_SMT_MIN				0x41
+#define FDDI_FC_K_SMT_MAX		   		0x4F
+#define FDDI_FC_K_MAC_MIN				0xC1
+#define FDDI_FC_K_MAC_MAX		  		0xCF	
+#define FDDI_FC_K_ASYNC_LLC_MIN			0x50
+#define FDDI_FC_K_ASYNC_LLC_DEF			0x54
+#define FDDI_FC_K_ASYNC_LLC_MAX			0x5F
+#define FDDI_FC_K_SYNC_LLC_MIN			0xD0
+#define FDDI_FC_K_SYNC_LLC_MAX			0xD7
+#define FDDI_FC_K_IMPLEMENTOR_MIN		0x60
+#define FDDI_FC_K_IMPLEMENTOR_MAX  		0x6F
+#define FDDI_FC_K_RESERVED_MIN			0x70
+#define FDDI_FC_K_RESERVED_MAX			0x7F
+
+/* Define LLC and SNAP constants */
+#define FDDI_EXTENDED_SAP	0xAA
+#define FDDI_UI_CMD			0x03
+
+/* Define 802.2 Type 1 header */
+struct fddi_8022_1_hdr
+	{
+	__u8	dsap;					/* destination service access point */
+	__u8	ssap;					/* source service access point */
+	__u8	ctrl;					/* control byte #1 */
+	} __attribute__ ((packed));
+
+/* Define 802.2 Type 2 header */
+struct fddi_8022_2_hdr
+	{
+	__u8	dsap;					/* destination service access point */
+	__u8	ssap;					/* source service access point */
+	__u8	ctrl_1;					/* control byte #1 */
+	__u8	ctrl_2;					/* control byte #2 */
+	} __attribute__ ((packed));
+
+/* Define 802.2 SNAP header */
+#define FDDI_K_OUI_LEN	3
+struct fddi_snap_hdr
+	{
+	__u8	dsap;					/* always 0xAA */
+	__u8	ssap;					/* always 0xAA */
+	__u8	ctrl;					/* always 0x03 */
+	__u8	oui[FDDI_K_OUI_LEN];	/* organizational universal id */
+	__u16	ethertype;				/* packet type ID field */
+	} __attribute__ ((packed));
+
+/* Define FDDI LLC frame header */
+struct fddihdr
+	{
+	__u8	fc;						/* frame control */
+	__u8	daddr[FDDI_K_ALEN];		/* destination address */
+	__u8	saddr[FDDI_K_ALEN];		/* source address */
+	union
+		{
+		struct fddi_8022_1_hdr		llc_8022_1;
+		struct fddi_8022_2_hdr		llc_8022_2;
+		struct fddi_snap_hdr		llc_snap;
+		} hdr;
+	} __attribute__ ((packed));
+
+/* Define FDDI statistics structure */
+struct fddi_statistics
+	{
+	__u32	rx_packets;				/* total packets received */
+	__u32	tx_packets;				/* total packets transmitted */
+	__u32	rx_errors;				/* bad packets received	*/
+	__u32	tx_errors;				/* packet transmit problems	*/
+	__u32	rx_dropped;				/* no space in linux buffers */
+	__u32	tx_dropped;				/* no space available in linux */
+	__u32	multicast;				/* multicast packets received */
+	__u32	transmit_collision;		/* always 0 for FDDI */
+
+	/* Detailed FDDI statistics.  Adopted from RFC 1512 */
+
+	__u8	smt_station_id[8];
+	__u32	smt_op_version_id;
+	__u32	smt_hi_version_id;
+	__u32	smt_lo_version_id;
+	__u8	smt_user_data[32];
+	__u32	smt_mib_version_id;
+	__u32	smt_mac_cts;
+	__u32	smt_non_master_cts;
+	__u32	smt_master_cts;
+	__u32	smt_available_paths;
+	__u32	smt_config_capabilities;
+	__u32	smt_config_policy;
+	__u32	smt_connection_policy;
+	__u32	smt_t_notify;
+	__u32	smt_stat_rpt_policy;
+	__u32	smt_trace_max_expiration;
+	__u32	smt_bypass_present;
+	__u32	smt_ecm_state;
+	__u32	smt_cf_state;
+	__u32	smt_remote_disconnect_flag;
+	__u32	smt_station_status;
+	__u32	smt_peer_wrap_flag;
+	__u32	smt_time_stamp;
+	__u32	smt_transition_time_stamp;
+	__u32	mac_frame_status_functions;
+	__u32	mac_t_max_capability;
+	__u32	mac_tvx_capability;
+	__u32	mac_available_paths;
+	__u32	mac_current_path;
+	__u8	mac_upstream_nbr[FDDI_K_ALEN];
+	__u8	mac_downstream_nbr[FDDI_K_ALEN];
+	__u8	mac_old_upstream_nbr[FDDI_K_ALEN];
+	__u8	mac_old_downstream_nbr[FDDI_K_ALEN];
+	__u32	mac_dup_address_test;
+	__u32	mac_requested_paths;
+	__u32	mac_downstream_port_type;
+	__u8	mac_smt_address[FDDI_K_ALEN];
+	__u32	mac_t_req;
+	__u32	mac_t_neg;
+	__u32	mac_t_max;
+	__u32	mac_tvx_value;
+	__u32	mac_frame_cts;
+	__u32	mac_copied_cts;
+	__u32	mac_transmit_cts;
+	__u32	mac_error_cts;
+	__u32	mac_lost_cts;
+	__u32	mac_frame_error_threshold;
+	__u32	mac_frame_error_ratio;
+	__u32	mac_rmt_state;
+	__u32	mac_da_flag;
+	__u32	mac_una_da_flag;
+	__u32	mac_frame_error_flag;
+	__u32	mac_ma_unitdata_available;
+	__u32	mac_hardware_present;
+	__u32	mac_ma_unitdata_enable;
+	__u32	path_tvx_lower_bound;
+	__u32	path_t_max_lower_bound;
+	__u32	path_max_t_req;
+	__u32	path_configuration[8];
+	__u32	port_my_type[2];
+	__u32	port_neighbor_type[2];
+	__u32	port_connection_policies[2];
+	__u32	port_mac_indicated[2];
+	__u32	port_current_path[2];
+	__u8	port_requested_paths[3*2];
+	__u32	port_mac_placement[2];
+	__u32	port_available_paths[2];
+	__u32	port_pmd_class[2];
+	__u32	port_connection_capabilities[2];
+	__u32	port_bs_flag[2];
+	__u32	port_lct_fail_cts[2];
+	__u32	port_ler_estimate[2];
+	__u32	port_lem_reject_cts[2];
+	__u32	port_lem_cts[2];
+	__u32	port_ler_cutoff[2];
+	__u32	port_ler_alarm[2];
+	__u32	port_connect_state[2];
+	__u32	port_pcm_state[2];
+	__u32	port_pc_withhold[2];
+	__u32	port_ler_flag[2];
+	__u32	port_hardware_present[2];
+	};
+
+#endif	/* _LINUX_IF_FDDI_H */
diff -u --recursive --new-file v2.1.10/linux/include/linux/igmp.h linux/include/linux/igmp.h
--- v2.1.10/linux/include/linux/igmp.h	Sat Aug 17 20:28:10 1996
+++ linux/include/linux/igmp.h	Mon Nov 18 11:31:32 1996
@@ -36,6 +36,7 @@
 #define IGMP_HOST_MEMBERSHIP_REPORT	0x12	/* Ditto */
 #define IGMP_DVMRP			0x13	/* DVMRP routing */
 #define IGMP_PIM			0x14	/* PIM routing */
+#define IGMP_TRACE			0x15	/* CISCO trace */
 #define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16	/* New version of 0x11 */
 #define IGMP_HOST_LEAVE_MESSAGE 	0x17	/* An extra BSD seems to send */
 
@@ -90,7 +91,8 @@
 	unsigned long multiaddr;
 	struct ip_mc_list *next;
 	struct timer_list timer;
-	int tm_running;
+	short tm_running;
+	short reporter;
 	int users;
 };
 
diff -u --recursive --new-file v2.1.10/linux/include/linux/in.h linux/include/linux/in.h
--- v2.1.10/linux/include/linux/in.h	Fri Nov 15 23:49:10 1996
+++ linux/include/linux/in.h	Mon Nov 18 15:11:02 1996
@@ -57,7 +57,7 @@
 /* Structure describing an Internet (IP) socket address. */
 #define __SOCK_SIZE__	16		/* sizeof(struct sockaddr)	*/
 struct sockaddr_in {
-  unsigned short int	sin_family;	/* Address family		*/
+  sa_family_t		sin_family;	/* Address family		*/
   unsigned short int	sin_port;	/* Port number			*/
   struct in_addr	sin_addr;	/* Internet address		*/
 
diff -u --recursive --new-file v2.1.10/linux/include/linux/ipx.h linux/include/linux/ipx.h
--- v2.1.10/linux/include/linux/ipx.h	Mon May 13 23:39:28 1996
+++ linux/include/linux/ipx.h	Mon Nov 18 11:31:32 1996
@@ -6,11 +6,11 @@
 
 struct sockaddr_ipx
 {
-	short sipx_family;
-	short sipx_port;
-	unsigned long  sipx_network;
-	unsigned char sipx_node[IPX_NODE_LEN];
-	unsigned char	sipx_type;
+	sa_family_t	 sipx_family;
+	__u16		 sipx_port;
+	__u32		sipx_network;
+	unsigned char 	sipx_node[IPX_NODE_LEN];
+	__u8		sipx_type;
 	unsigned char	sipx_zero;	/* 16 byte fill */
 };
 
diff -u --recursive --new-file v2.1.10/linux/include/linux/major.h linux/include/linux/major.h
--- v2.1.10/linux/include/linux/major.h	Tue Nov 12 15:56:14 1996
+++ linux/include/linux/major.h	Sat Nov 16 13:00:34 1996
@@ -8,8 +8,8 @@
 
 /* limits */
 
-#define MAX_CHRDEV 64
-#define MAX_BLKDEV 64
+#define MAX_CHRDEV 128
+#define MAX_BLKDEV 128
 
 #define UNNAMED_MAJOR	0
 #define MEM_MAJOR	1
diff -u --recursive --new-file v2.1.10/linux/include/linux/net.h linux/include/linux/net.h
--- v2.1.10/linux/include/linux/net.h	Mon Sep  9 16:23:58 1996
+++ linux/include/linux/net.h	Mon Nov 18 11:31:32 1996
@@ -92,14 +92,14 @@
   int	(*dup)		(struct socket *newsock, struct socket *oldsock);
   int	(*release)	(struct socket *sock, struct socket *peer);
   int	(*bind)		(struct socket *sock, struct sockaddr *umyaddr,
-			 int sockaddr_len);
+			 size_t sockaddr_len);
   int	(*connect)	(struct socket *sock, struct sockaddr *uservaddr,
-			 int sockaddr_len, int flags);
+			 size_t sockaddr_len, int flags);
   int	(*socketpair)	(struct socket *sock1, struct socket *sock2);
   int	(*accept)	(struct socket *sock, struct socket *newsock,
 			 int flags);
   int	(*getname)	(struct socket *sock, struct sockaddr *uaddr,
-			 int *usockaddr_len, int peer);
+			 size_t *usockaddr_len, int peer);
   int	(*select)	(struct socket *sock, int sel_type,
 			 select_table *wait);
   int	(*ioctl)	(struct socket *sock, unsigned int cmd,
diff -u --recursive --new-file v2.1.10/linux/include/linux/netdevice.h linux/include/linux/netdevice.h
--- v2.1.10/linux/include/linux/netdevice.h	Tue Nov 12 15:56:14 1996
+++ linux/include/linux/netdevice.h	Mon Nov 18 15:13:18 1996
@@ -295,6 +295,7 @@
 /* These functions live elsewhere (drivers/net/net_init.c, but related) */
 
 extern void		ether_setup(struct device *dev);
+extern void		fddi_setup(struct device *dev);
 extern void		tr_setup(struct device *dev);
 extern int		ether_config(struct device *dev, struct ifmap *map);
 /* Support for loadable net-drivers */
diff -u --recursive --new-file v2.1.10/linux/include/linux/rose.h linux/include/linux/rose.h
--- v2.1.10/linux/include/linux/rose.h	Tue Nov 12 15:56:14 1996
+++ linux/include/linux/rose.h	Mon Nov 18 11:31:32 1996
@@ -26,7 +26,7 @@
 } rose_address;
 
 struct sockaddr_rose {
-	short		srose_family;
+	sa_family_t	srose_family;
 	rose_address	srose_addr;
 	ax25_address	srose_call;
 	int		srose_ndigis;
diff -u --recursive --new-file v2.1.10/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.1.10/linux/include/linux/sched.h	Mon Sep 30 11:19:00 1996
+++ linux/include/linux/sched.h	Mon Nov 18 15:11:02 1996
@@ -320,7 +320,7 @@
  *	On a single processor system this comes out as current_set[0] when cpp
  *	has finished with it, which gcc will optimise away.
  */
-#define current (0+current_set[smp_processor_id()])	/* Current on this processor */
+#define current (current_set[smp_processor_id()])	/* Current on this processor */
 extern unsigned long volatile jiffies;
 extern unsigned long itimer_ticks;
 extern unsigned long itimer_next;
diff -u --recursive --new-file v2.1.10/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.1.10/linux/include/linux/skbuff.h	Fri Nov 15 23:49:10 1996
+++ linux/include/linux/skbuff.h	Mon Nov 18 15:11:13 1996
@@ -184,6 +184,16 @@
 	return (list->next == (struct sk_buff *) list);
 }
 
+extern __inline__ struct sk_buff *skb_unshare(struct sk_buff *skb, int pri, int dir)
+{
+	struct sk_buff *nskb;
+	if(skb->users==1)
+		return skb;
+	nskb=skb_copy(skb, pri);
+	kfree_skb(skb, dir);	/* Free our shared copy */
+	return nskb;
+}
+
 /*
  *	Peek an sk_buff. Unlike most other operations you _MUST_
  *	be careful with this one. A peek leaves the buffer on the
@@ -402,13 +412,14 @@
  
 extern __inline__ unsigned char *skb_put(struct sk_buff *skb, int len)
 {
+	extern char *skb_put_errstr;
 	unsigned char *tmp=skb->tail;
 	skb->tail+=len;
 	skb->len+=len;
 	if(skb->tail>skb->end)
 	{
 		__label__ here;
-		panic("skput:over: %p:%d", &&here,len);
+		panic(skb_put_errstr,&&here,len);
 here:
 	}
 	return tmp;
@@ -416,12 +427,13 @@
 
 extern __inline__ unsigned char *skb_push(struct sk_buff *skb, int len)
 {
+	extern char *skb_push_errstr;
 	skb->data-=len;
 	skb->len+=len;
 	if(skb->data<skb->head)
 	{
 		__label__ here;
-		panic("skpush:under: %p:%d", &&here,len);
+		panic(skb_push_errstr, &&here,len);
 here:
 	}
 	return skb->data;
diff -u --recursive --new-file v2.1.10/linux/include/linux/socket.h linux/include/linux/socket.h
--- v2.1.10/linux/include/linux/socket.h	Fri Nov 15 23:49:10 1996
+++ linux/include/linux/socket.h	Mon Nov 18 11:31:32 1996
@@ -5,9 +5,15 @@
 #include <linux/sockios.h>		/* the SIOCxxx I/O controls	*/
 #include <linux/uio.h>			/* iovec support		*/
 
+typedef unsigned short	sa_family_t;
+
+/*
+ *	1003.1g requires sa_family_t and that sa_data is char.
+ */
+ 
 struct sockaddr 
 {
-	unsigned short	sa_family;	/* address family, AF_xxx	*/
+	sa_family_t	sa_family;	/* address family, AF_xxx	*/
 	char		sa_data[14];	/* 14 bytes of protocol address	*/
 };
 
@@ -25,11 +31,11 @@
 struct msghdr 
 {
 	void	*	msg_name;	/* Socket name			*/
-	int		msg_namelen;	/* Length of name		*/
+	size_t		msg_namelen;	/* Length of name		*/
 	struct iovec *	msg_iov;	/* Data blocks			*/
-	int 		msg_iovlen;	/* Number of blocks		*/
+	size_t 		msg_iovlen;	/* Number of blocks		*/
 	void 	*	msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */
-	int		msg_controllen;	/* Length of rights list */
+	size_t		msg_controllen;	/* Length of rights list */
 	int		msg_flags;	/* 4.4 BSD item we dont use      */
 };
 
@@ -90,6 +96,7 @@
 /* Supported address families. */
 #define AF_UNSPEC	0
 #define AF_UNIX		1	/* Unix domain sockets 		*/
+#define AF_LOCAL	1	/* POSIX name for AF_UNIX	*/
 #define AF_INET		2	/* Internet IP Protocol 	*/
 #define AF_AX25		3	/* Amateur Radio AX.25 		*/
 #define AF_IPX		4	/* Novell IPX 			*/
@@ -100,11 +107,14 @@
 #define AF_X25		9	/* Reserved for X.25 project 	*/
 #define AF_INET6	10	/* IP version 6			*/
 #define AF_ROSE		11	/* Amateur Radio X.25 PLP	*/
-#define AF_MAX		13	/* For now.. */
+#define AF_DECNET	12	/* Reserved for DECnet project	*/
+#define AF_NETBEUI	13	/* Reserved for 802.2LLC project*/
+#define AF_MAX		32	/* For now.. */
 
 /* Protocol families, same as address families. */
 #define PF_UNSPEC	AF_UNSPEC
 #define PF_UNIX		AF_UNIX
+#define PF_LOCAL	AF_LOCAL
 #define PF_INET		AF_INET
 #define PF_AX25		AF_AX25
 #define PF_IPX		AF_IPX
@@ -115,18 +125,26 @@
 #define PF_X25		AF_X25
 #define PF_INET6	AF_INET6
 #define PR_ROSE		AF_ROSE
+#define PF_DECNET	AF_DECNET
+#define PF_NETBEUI	AF_NETBEUI
 
 #define PF_MAX		AF_MAX
 
 /* Maximum queue length specifiable by listen.  */
 #define SOMAXCONN	128
 
-/* Flags we can use with send/ and recv. */
+/* Flags we can use with send/ and recv. 
+   Added those for 1003.1g not all are supported yet
+ */
+ 
 #define MSG_OOB		1
 #define MSG_PEEK	2
 #define MSG_DONTROUTE	4
-/*#define MSG_CTRUNC	8	- We need to support this for BSD oddments */
+#define MSG_CTRUNC	8	/*  We need to support this for BSD oddments */
 #define MSG_PROXY	16	/* Supply or ask second address. */
+#define MSG_EOR		32	/* End of record */
+#define MSG_TRUNC	64	/* Data was discarded before delivery */
+#define MSG_WAITALL	128	/* Wait for a full request */
 
 /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx */
 #define SOL_IP		0
@@ -138,6 +156,7 @@
 #define SOL_ATALK	258
 #define SOL_NETROM	259
 #define SOL_ROSE	260
+#define SOL_DECNET	261
 #define SOL_TCP		6
 #define SOL_UDP		17
 
diff -u --recursive --new-file v2.1.10/linux/include/linux/uio.h linux/include/linux/uio.h
--- v2.1.10/linux/include/linux/uio.h	Thu Jun  6 21:22:24 1996
+++ linux/include/linux/uio.h	Mon Nov 18 11:31:32 1996
@@ -16,10 +16,14 @@
 
 struct iovec
 {
-	void *iov_base;		/* BSD uses caddr_t (same thing in effect) */
-	int iov_len;
+	void *iov_base;		/* BSD uses caddr_t (1003.1g requires void *) */
+	size_t iov_len;		/* Must be size_t (1003.1g) */
 };
 
+/*
+ *	UIO_MAXIOV shall be at least 16 1003.1g (5.4.1.1)
+ */
+ 
 #define UIO_MAXIOV	16	/* Maximum iovec's in one operation 
 				   16 matches BSD */
 
diff -u --recursive --new-file v2.1.10/linux/include/linux/un.h linux/include/linux/un.h
--- v2.1.10/linux/include/linux/un.h	Sun Nov 10 20:12:15 1996
+++ linux/include/linux/un.h	Mon Nov 18 11:31:32 1996
@@ -4,7 +4,7 @@
 #define UNIX_PATH_MAX	108
 
 struct sockaddr_un {
-	unsigned short sun_family;	/* AF_UNIX */
+	sa_family_t sun_family;	/* AF_UNIX */
 	char sun_path[UNIX_PATH_MAX];	/* pathname */
 };
 
diff -u --recursive --new-file v2.1.10/linux/include/net/ax25.h linux/include/net/ax25.h
--- v2.1.10/linux/include/net/ax25.h	Tue Nov 12 15:56:14 1996
+++ linux/include/net/ax25.h	Mon Nov 18 15:13:22 1996
@@ -128,8 +128,8 @@
 #define	AX25_VALUES_T1		7	/* Default T1 timeout value */
 #define	AX25_VALUES_T2		8	/* Default T2 timeout value */
 #define	AX25_VALUES_T3		9	/* Default T3 timeout value */
-#define	AX25_VALUES_N2		10	/* Default N2 value */
-#define AX25_VALUES_IDLE	11	/* mode vc idle timer */
+#define AX25_VALUES_IDLE	10	/* mode vc idle timer */
+#define	AX25_VALUES_N2		11	/* Default N2 value */
 #define AX25_VALUES_PACLEN	12	/* AX.25 MTU */
 #define AX25_VALUES_MAXQUEUE	13	/* Maximum number of buffers enqueued */
 #define	AX25_VALUES_DIGI	14	/* Digipeat mode */
diff -u --recursive --new-file v2.1.10/linux/include/net/br.h linux/include/net/br.h
--- v2.1.10/linux/include/net/br.h	Fri Apr 12 09:49:47 1996
+++ linux/include/net/br.h	Mon Nov 18 11:31:32 1996
@@ -161,15 +161,29 @@
 
 #define IS_BRIDGED	0x2e
 
+
+#define BR_MAX_PROTOCOLS 32
+#define BR_MAX_PROT_STATS BR_MAX_PROTOCOLS
+
+/* policy values for policy field */
+#define BR_ACCEPT 1
+#define BR_REJECT 0
+
 struct br_stat {
 	unsigned int flags;
 	Bridge_data bridge_data;
 	Port_data port_data[No_of_ports];
+	unsigned int policy;
+	unsigned int exempt_protocols;
+	unsigned short protocols[BR_MAX_PROTOCOLS];
+	unsigned short prot_id[BR_MAX_PROT_STATS];	/* Protocol encountered */
+	unsigned int prot_counter[BR_MAX_PROT_STATS];	/* How many packets ? */
 };
 
 /* defined flags for br_stat.flags */
 #define BR_UP		0x0001	/* bridging enabled */
 #define BR_DEBUG	0x0002	/* debugging enabled */
+#define BR_PROT_STATS	0x0004	/* protocol statistics enabled */
 
 struct br_cf {
 	unsigned int cmd;
@@ -188,6 +202,11 @@
 #define	BRCMD_DISPLAY_FDB	8	/* arg1 = port */
 #define	BRCMD_ENABLE_DEBUG	9
 #define	BRCMD_DISABLE_DEBUG	10
+#define BRCMD_SET_POLICY	11	/* arg1 = default policy (1==bridge all) */
+#define BRCMD_EXEMPT_PROTOCOL	12	/* arg1 = protocol (see net/if_ether.h) */
+#define BRCMD_ENABLE_PROT_STATS	13
+#define BRCMD_DISABLE_PROT_STATS 14
+#define BRCMD_ZERO_PROT_STATS	15
 
 /* prototypes of all bridging functions... */
 
@@ -260,6 +279,8 @@
 int br_receive_frame(struct sk_buff *skb);	/* 3.5 */
 int br_tx_frame(struct sk_buff *skb);
 int br_ioctl(unsigned int cmd, void *arg);
+
+int br_protocol_ok(unsigned short protocol);
 
 void free_fdb(struct fdb *);
 struct fdb *get_fdb(void);
diff -u --recursive --new-file v2.1.10/linux/include/net/inet_common.h linux/include/net/inet_common.h
--- v2.1.10/linux/include/net/inet_common.h	Sun Nov 10 20:12:15 1996
+++ linux/include/net/inet_common.h	Mon Nov 18 11:31:32 1996
@@ -17,7 +17,7 @@
 					     struct socket *peer);
 extern int			inet_connect(struct socket *sock, 
 					     struct sockaddr * uaddr,
-					     int addr_len, int flags);
+					     size_t addr_len, int flags);
 extern int			inet_accept(struct socket *sock, 
 					    struct socket *newsock, int flags);
 extern int			inet_recvmsg(struct socket *sock, 
diff -u --recursive --new-file v2.1.10/linux/include/net/netlink.h linux/include/net/netlink.h
--- v2.1.10/linux/include/net/netlink.h	Sun Nov 10 20:12:16 1996
+++ linux/include/net/netlink.h	Mon Nov 18 15:17:31 1996
@@ -2,16 +2,17 @@
 #define __NET_NETLINK_H
 
 #define NET_MAJOR 36		/* Major 18 is reserved for networking 						*/
-#define MAX_LINKS 12		/* 18,0 for route updates, 18,1 for SKIP, 18,2 debug tap 18,3 PPP reserved 	*/
+#define MAX_LINKS 16		/* 18,0 for route updates, 18,1 for SKIP, 18,2 debug tap 18,3 PPP reserved 	*/
 				/* 4-7 are psi0-psi3  8 is arpd 9 is ppp */
 				/* 10 is for IPSEC <John Ioannidis> */
 				/* 11 IPv6 route updates		*/
+				/* 12 is for firewall trapout	*/
 #define MAX_QBYTES 32768	/* Maximum bytes in the queue 							*/
 
 #include <linux/config.h>
 
-extern int netlink_attach(int unit, int (*function)(struct sk_buff *skb));
-extern int netlink_donothing(struct sk_buff *skb);
+extern int netlink_attach(int unit, int (*function)(int,struct sk_buff *skb));
+extern int netlink_donothing(int, struct sk_buff *skb);
 extern void netlink_detach(int unit);
 extern int netlink_post(int unit, struct sk_buff *skb);
 extern int init_netlink(void);
@@ -22,9 +23,9 @@
 #define NETLINK_FIREWALL	3	/* Firewalling hook				*/
 #define NETLINK_PSI		4	/* PSI devices - 4 to 7 */
 #define NETLINK_ARPD		8
-#define NETLINK_NET_PPP		9	/* Non tty PPP devices */
 #define NETLINK_IPSEC		10	/* IPSEC */
 #define NETLINK_ROUTE6		11	/* af_inet6 route comm channel */
+#define NETLINK_
 
 #ifdef CONFIG_RTNETLINK
 extern void ip_netlink_msg(unsigned long, __u32, __u32, __u32, short, short, char *);
diff -u --recursive --new-file v2.1.10/linux/include/net/protocol.h linux/include/net/protocol.h
--- v2.1.10/linux/include/net/protocol.h	Sun Nov 10 20:12:16 1996
+++ linux/include/net/protocol.h	Mon Nov 18 15:13:22 1996
@@ -41,7 +41,7 @@
 				   int redo, struct inet_protocol *protocol);
   void			(*err_handler)(int type, int code, unsigned char *buff,
 				       __u32 info, __u32 daddr, __u32 saddr,
-				       struct inet_protocol *protocol);
+				       struct inet_protocol *protocol, int len);
   struct inet_protocol *next;
   unsigned char		protocol;
   unsigned char		copy:1;
diff -u --recursive --new-file v2.1.10/linux/include/net/sock.h linux/include/net/sock.h
--- v2.1.10/linux/include/net/sock.h	Tue Nov 12 15:56:15 1996
+++ linux/include/net/sock.h	Mon Nov 18 15:13:22 1996
@@ -511,7 +511,7 @@
 					unsigned long timeout);
 	int			(*connect)(struct sock *sk,
 				        struct sockaddr *uaddr, 
-					int addr_len);
+					size_t addr_len);
 
 	struct sock *		(*accept) (struct sock *sk, int flags);
 	void			(*retransmit)(struct sock *sk, int all);
@@ -537,7 +537,7 @@
 					int len, int noblock, int flags, 
 					int *addr_len);
 	int			(*bind)(struct sock *sk, 
-					struct sockaddr *uaddr, int addr_len);
+					struct sockaddr *uaddr, size_t addr_len);
 
 	int			(*backlog_rcv) (struct sock *sk, 
 						struct sk_buff *skb);
diff -u --recursive --new-file v2.1.10/linux/include/net/tcp.h linux/include/net/tcp.h
--- v2.1.10/linux/include/net/tcp.h	Fri Nov 15 23:49:10 1996
+++ linux/include/net/tcp.h	Mon Nov 18 15:16:59 1996
@@ -240,7 +240,8 @@
 extern void			tcp_v4_err(int type, int code,
 					   unsigned char *header, __u32 info,
 					   __u32 daddr, __u32 saddr,
-					   struct inet_protocol *protocol);
+					   struct inet_protocol *protocol,
+					   int len);
 
 extern void			tcp_shutdown (struct sock *sk, int how);
 
@@ -315,7 +316,7 @@
 						   struct sk_buff *skb);
 extern int			tcp_v4_connect(struct sock *sk,
 					       struct sockaddr *uaddr,
-					       int addr_len);
+					       size_t addr_len);
 
 
 extern void tcp_read_wakeup(struct sock *);
diff -u --recursive --new-file v2.1.10/linux/include/net/udp.h linux/include/net/udp.h
--- v2.1.10/linux/include/net/udp.h	Sun Nov 10 20:12:18 1996
+++ linux/include/net/udp.h	Mon Nov 18 11:31:33 1996
@@ -33,16 +33,11 @@
 
 extern void	udp_err(int type, int code, unsigned char *header,
 			__u32 info, __u32 daddr, __u32 saddr,
-			struct inet_protocol *protocol);
+			struct inet_protocol *protocol, int len);
 extern void	udp_send_check(struct udphdr *uh, __u32 saddr, 
 			__u32 daddr, int len, struct sock *sk);
-extern int	udp_recvfrom(struct sock *sk, unsigned char *to,
-			     int len, int noblock, unsigned flags,
-			     struct sockaddr_in *sin, int *addr_len);
-extern int	udp_read(struct sock *sk, unsigned char *buff,
-			 int len, int noblock, unsigned flags);
 extern int	udp_connect(struct sock *sk,
-			    struct sockaddr *usin, int addr_len);
+			    struct sockaddr *usin, size_t addr_len);
 
 extern int	udp_sendmsg(struct sock *sk, struct msghdr *msg,
 			    int len, int noblock, int flags);
diff -u --recursive --new-file v2.1.10/linux/kernel/info.c linux/kernel/info.c
--- v2.1.10/linux/kernel/info.c	Tue Oct 29 19:58:48 1996
+++ linux/kernel/info.c	Mon Nov 18 12:14:26 1996
@@ -17,12 +17,8 @@
 
 asmlinkage int sys_sysinfo(struct sysinfo *info)
 {
-	int error;
 	struct sysinfo val;
 
-	error = verify_area(VERIFY_WRITE, info, sizeof(struct sysinfo));
-	if (error)
-		return error;
 	memset((char *)&val, 0, sizeof(struct sysinfo));
 
 	val.uptime = jiffies / HZ;
@@ -36,6 +32,7 @@
 	si_meminfo(&val);
 	si_swapinfo(&val);
 
-	copy_to_user(info, &val, sizeof(struct sysinfo));
+	if (copy_to_user(info, &val, sizeof(struct sysinfo)))
+		return -EFAULT;
 	return 0;
 }
diff -u --recursive --new-file v2.1.10/linux/kernel/itimer.c linux/kernel/itimer.c
--- v2.1.10/linux/kernel/itimer.c	Tue Oct 29 19:58:48 1996
+++ linux/kernel/itimer.c	Sat Nov 16 13:11:17 1996
@@ -88,11 +88,7 @@
 	error = _getitimer(which, &get_buffer);
 	if (error)
 		return error;
-	error = verify_area(VERIFY_WRITE, value, sizeof(struct itimerval));
-	if (error)
-		return error;
-	copy_to_user(value, &get_buffer, sizeof(get_buffer));
-	return 0;
+	return copy_to_user(value, &get_buffer, sizeof(get_buffer)) ? -EFAULT : 0;
 }
 
 void it_real_fn(unsigned long __data)
@@ -162,20 +158,17 @@
 		error = verify_area(VERIFY_READ, value, sizeof(*value));
 		if (error)
 			return error;
-		copy_from_user(&set_buffer, value, sizeof(set_buffer));
+		error = copy_from_user(&set_buffer, value, sizeof(set_buffer));
+		if (error)
+			return -EFAULT;
 	} else
 		memset((char *) &set_buffer, 0, sizeof(set_buffer));
 
-	if (ovalue) {
-		error = verify_area(VERIFY_WRITE, ovalue, sizeof(struct itimerval));
-		if (error)
-			return error;
-	}
-
 	error = _setitimer(which, &set_buffer, ovalue ? &get_buffer : 0);
 	if (error || !ovalue)
 		return error;
 
-	copy_to_user(ovalue, &get_buffer, sizeof(get_buffer));
+	if (copy_to_user(ovalue, &get_buffer, sizeof(get_buffer)))
+		error = -EFAULT; 
 	return error;
 }
diff -u --recursive --new-file v2.1.10/linux/kernel/module.c linux/kernel/module.c
--- v2.1.10/linux/kernel/module.c	Sun Nov 10 20:12:19 1996
+++ linux/kernel/module.c	Sat Nov 16 13:11:18 1996
@@ -54,7 +54,6 @@
 static int freeing_modules; /* true if some modules are marked for deletion */
 
 static struct module *find_module( const char *name);
-static int get_mod_name( char *user_name, char *buf);
 static int free_modules( void);
 
 extern struct symbol_table symbol_table; /* in kernel/ksyms.c */
@@ -75,6 +74,21 @@
 	kernel_module.name = "";
 }
 
+
+/*
+ * Copy the name of a module from user space.
+ */
+inline int
+get_mod_name(char *user_name, char *buf)
+{
+	/* Should return -EBIG instead of -EFAULT when the name
+       is too long, but that we couldn't detect real faults then.
+       Maybe strncpy_from_user() should return -EBIG, when
+       the source string is too long. */
+	return strncpy_from_user(buf, user_name, MOD_MAX_NAME); 
+}
+
+
 /*
  * Allocate space for a module.
  */
@@ -128,6 +142,7 @@
 	return (unsigned long) addr;
 }
 
+
 /*
  * Initialize a module.
  */
@@ -157,7 +172,8 @@
 		return error;
 	pr_debug("initializing module `%s', %d (0x%x) bytes\n",
 		name, codesize, codesize);
-	copy_from_user(&rt, routines, sizeof rt);
+	if (copy_from_user(&rt, routines, sizeof rt))
+			return -EFAULT;
 	if ((mp = find_module(name)) == NULL)
 		return -ENOENT;
 	if (codesize & MOD_AUTOCLEAN) {
@@ -170,7 +186,8 @@
 	}
 	if ((codesize + sizeof (long) + PAGE_SIZE - 1) / PAGE_SIZE > mp->size)
 		return -EINVAL;
-	copy_from_user((char *)mp->addr + sizeof (long), code, codesize);
+	if (copy_from_user((char *)mp->addr + sizeof (long), code, codesize))
+			return -EFAULT;
 	memset((char *)mp->addr + sizeof (long) + codesize, 0,
 		mp->size * PAGE_SIZE - (codesize + sizeof (long)));
 	pr_debug("module init entry = 0x%08lx, cleanup entry = 0x%08lx\n",
@@ -190,19 +207,17 @@
 		int i;
 		int legal_start;
 
-		if ((error = verify_area(VERIFY_READ, &symtab->size, sizeof(symtab->size))))
-			return error;
-		get_user(size, &symtab->size);
-
+		error = get_user(size, &symtab->size);
+		if (error)
+				return error;
 		if ((newtab = (struct symbol_table*) kmalloc(size, GFP_KERNEL)) == NULL) {
 			return -ENOMEM;
 		}
 
-		if ((error = verify_area(VERIFY_READ, symtab, size))) {
-			kfree_s(newtab, size);
-			return error;
+		if (copy_from_user((char *)(newtab), symtab, size)) {
+				kfree_s(newtab, size);
+				return -EFAULT;
 		}
-		copy_from_user((char *)(newtab), symtab, size);
 
 		/* sanity check */
 		legal_start = sizeof(struct symbol_table) +
@@ -344,6 +359,7 @@
 	struct module *mp = module_list;
 	int i;
 	int nmodsyms = 0;
+	int err;
 
 	for (mp = module_list; mp; mp = mp->next) {
 		if (mp->symtab && mp->symtab->n_symbols) {
@@ -358,16 +374,15 @@
 	if (table != NULL) {
 		to = table;
 
-		if ((i = verify_area(VERIFY_WRITE, to, nmodsyms * sizeof(*table))))
-			return i;
-
 		/* copy all module symbols first (always LIFO order) */
 		for (mp = module_list; mp; mp = mp->next) {
 			if (mp->state == MOD_RUNNING) {
 				/* magic: write module info as a pseudo symbol */
 				isym.value = (unsigned long)mp;
 				sprintf(isym.name, "#%s", mp->name);
-				copy_to_user(to, &isym, sizeof isym);
+				err = copy_to_user(to, &isym, sizeof isym);
+				if (err)
+						return -EFAULT;
 				++to;
 
 				if (mp->symtab != NULL) {
@@ -377,7 +392,9 @@
 
 						isym.value = (unsigned long)from->addr;
 						strncpy(isym.name, from->name, sizeof isym.name);
-						copy_to_user(to, &isym, sizeof isym);
+						err = copy_to_user(to, &isym, sizeof isym);
+						if (err)
+								return -EFAULT;
 					}
 				}
 			}
@@ -386,27 +403,6 @@
 
 	return nmodsyms;
 }
-
-
-/*
- * Copy the name of a module from user space.
- */
-int
-get_mod_name(char *user_name, char *buf)
-{
-	int i;
-
-	i = 0;
-	for (;;) {
-		get_user(buf[i], user_name + i);
-		if (buf[i] == '\0')
-			break;
-		if (++i >= MOD_MAX_NAME)
-			return -E2BIG;
-	}
-	return 0;
-}
-
 
 /*
  * Look for a module by name, ignoring modules marked for deletion.
diff -u --recursive --new-file v2.1.10/linux/kernel/panic.c linux/kernel/panic.c
--- v2.1.10/linux/kernel/panic.c	Tue Oct 29 19:58:48 1996
+++ linux/kernel/panic.c	Mon Nov 18 11:31:34 1996
@@ -58,11 +58,3 @@
 	for(;;);
 }
 
-/*
- * GCC 2.5.8 doesn't always optimize correctly; see include/asm/uaccess.h
- */
-
-int bad_user_access_length(void)
-{
-        panic("bad_user_access_length executed (not cool, dude)");
-}
diff -u --recursive --new-file v2.1.10/linux/kernel/sched.c linux/kernel/sched.c
--- v2.1.10/linux/kernel/sched.c	Sun Nov 10 20:12:19 1996
+++ linux/kernel/sched.c	Sat Nov 16 13:11:18 1996
@@ -1211,17 +1211,14 @@
 static int setscheduler(pid_t pid, int policy, 
 			struct sched_param *param)
 {
-	int error;
 	struct sched_param lp;
 	struct task_struct *p;
 
 	if (!param || pid < 0)
 		return -EINVAL;
 
-	error = verify_area(VERIFY_READ, param, sizeof(struct sched_param));
-	if (error)
-		return error;
-	copy_from_user(&lp, param, sizeof(struct sched_param));
+	if (copy_from_user(&lp, param, sizeof(struct sched_param)))
+		return -EFAULT;
 
 	p = find_process_by_pid(pid);
 	if (!p)
@@ -1286,25 +1283,18 @@
 
 asmlinkage int sys_sched_getparam(pid_t pid, struct sched_param *param)
 {
-	int error;
 	struct task_struct *p;
 	struct sched_param lp;
 
 	if (!param || pid < 0)
 		return -EINVAL;
 
-	error = verify_area(VERIFY_WRITE, param, sizeof(struct sched_param));
-	if (error)
-		return error;
-
 	p = find_process_by_pid(pid);
 	if (!p)
 		return -ESRCH;
 
 	lp.sched_priority = p->rt_priority;
-	copy_to_user(param, &lp, sizeof(struct sched_param));
-
-	return 0;
+	return copy_to_user(param, &lp, sizeof(struct sched_param)) ? -EFAULT : 0;
 }
 
 asmlinkage int sys_sched_yield(void)
@@ -1343,19 +1333,12 @@
 
 asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval)
 {
-	int error;
 	struct timespec t;
 
-	error = verify_area(VERIFY_WRITE, interval, sizeof(struct timespec));
-	if (error)
-		return error;
-	
 	t.tv_sec = 0;
 	t.tv_nsec = 0;   /* <-- Linus, please fill correct value in here */
 	return -ENOSYS;  /* and then delete this line. Thanks!           */
-	copy_to_user(interval, &t, sizeof(struct timespec));
-
-	return 0;
+	return copy_to_user(interval, &t, sizeof(struct timespec)) ? -EFAULT : 0;
 }
 
 /*
@@ -1387,16 +1370,9 @@
 	struct timespec t;
 	unsigned long expire;
 
-	error = verify_area(VERIFY_READ, rqtp, sizeof(struct timespec));
+	error = copy_from_user(&t, rqtp, sizeof(struct timespec));
 	if (error)
-		return error;
-	copy_from_user(&t, rqtp, sizeof(struct timespec));
-	if (rmtp) {
-		error = verify_area(VERIFY_WRITE, rmtp,
-				    sizeof(struct timespec));
-		if (error)
-			return error;
-	}
+		return -EFAULT;	
 
 	if (t.tv_nsec >= 1000000000L || t.tv_nsec < 0 || t.tv_sec < 0)
 		return -EINVAL;
@@ -1420,7 +1396,8 @@
 		if (rmtp) {
 			jiffiestotimespec(expire - jiffies -
 					  (expire > jiffies + 1), &t);
-			copy_to_user(rmtp, &t, sizeof(struct timespec));
+			if (copy_to_user(rmtp, &t, sizeof(struct timespec)))
+				return -EFAULT;	
 		}
 		return -EINTR;
 	}
diff -u --recursive --new-file v2.1.10/linux/kernel/signal.c linux/kernel/signal.c
--- v2.1.10/linux/kernel/signal.c	Tue Oct 29 19:58:48 1996
+++ linux/kernel/signal.c	Sat Nov 16 13:11:18 1996
@@ -32,10 +32,9 @@
 	int error;
 
 	if (set) {
-		error = verify_area(VERIFY_READ, set, sizeof(sigset_t));
+		error = get_user(new_set, set);
 		if (error)
-			return error;
-		get_user(new_set, set);
+			return error;	
 		new_set &= _BLOCKABLE;
 		switch (how) {
 		case SIG_BLOCK:
@@ -52,10 +51,9 @@
 		}
 	}
 	if (oset) {
-		error = verify_area(VERIFY_WRITE, oset, sizeof(sigset_t));
+		error = put_user(old_set, oset);
 		if (error)
-			return error;
-		put_user(old_set, oset);
+			return error;	
 	}
 	return 0;
 }
@@ -80,12 +78,8 @@
 
 asmlinkage int sys_sigpending(sigset_t *set)
 {
-	int error;
 	/* fill in "set" with signals pending but blocked. */
-	error = verify_area(VERIFY_WRITE, set, sizeof(sigset_t));
-	if (!error)
-		put_user(current->blocked & current->signal, set);
-	return error;
+	return put_user(current->blocked & current->signal, set);
 }
 
 /*
@@ -162,7 +156,8 @@
 			return err;
 		if (signum==SIGKILL || signum==SIGSTOP)
 			return -EINVAL;
-		copy_from_user(&new_sa, action, sizeof(struct sigaction));
+		if (copy_from_user(&new_sa, action, sizeof(struct sigaction)))
+			return -EFAULT;	
 		if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
 			err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
 			if (err)
@@ -170,10 +165,8 @@
 		}
 	}
 	if (oldaction) {
-		int err = verify_area(VERIFY_WRITE, oldaction, sizeof(*oldaction));
-		if (err)
-			return err;
-		copy_to_user(oldaction, p, sizeof(struct sigaction));
+		if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
+			return -EFAULT;	
 	}
 	if (action) {
 		*p = new_sa;
diff -u --recursive --new-file v2.1.10/linux/kernel/sys.c linux/kernel/sys.c
--- v2.1.10/linux/kernel/sys.c	Tue Oct 29 19:58:48 1996
+++ linux/kernel/sys.c	Sat Nov 16 13:11:18 1996
@@ -578,14 +578,17 @@
 
 asmlinkage long sys_times(struct tms * tbuf)
 {
+	int error;
 	if (tbuf) {
-		int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
+		error = put_user(current->utime,&tbuf->tms_utime);
+		if (!error)
+			error = put_user(current->stime,&tbuf->tms_stime);
+		if (!error)
+			error = put_user(current->cutime,&tbuf->tms_cutime);
+		if (!error)
+			error =	put_user(current->cstime,&tbuf->tms_cstime);
 		if (error)
-			return error;
-		put_user(current->utime,&tbuf->tms_utime);
-		put_user(current->stime,&tbuf->tms_stime);
-		put_user(current->cutime,&tbuf->tms_cutime);
-		put_user(current->cstime,&tbuf->tms_cstime);
+			return error;	
 	}
 	return jiffies;
 }
@@ -706,40 +709,30 @@
 			break;
 	}
 	if (gidsetsize) {
-		int error;
-		error = verify_area(VERIFY_WRITE, grouplist, sizeof(gid_t) * gidsetsize);
-		if (error)
-			return error;
 		if (i > gidsetsize)
 		        return -EINVAL;
-
-		for (i = 0 ; i < NGROUPS ; i++) {
-			if (groups[i] == NOGROUP)
-				break;
-			put_user(groups[i], grouplist);
-			grouplist++;
-		}
+		if (copy_to_user(grouplist, groups, sizeof(*groups)*i))
+				return -EFAULT;
 	}
 	return i;
 }
 
 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
 {
-	int	i;
+	int	err;
 
 	if (!suser())
 		return -EPERM;
 	if (gidsetsize > NGROUPS)
 		return -EINVAL;
-	i = verify_area(VERIFY_READ, grouplist, sizeof(gid_t) * gidsetsize);
-	if (i)
-		return i;
-	for (i = 0; i < gidsetsize; i++, grouplist++) {
-		get_user(current->groups[i], grouplist);
-	}
-	if (i < NGROUPS)
-		current->groups[i] = NOGROUP;
-	return 0;
+	err = copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t));
+	if (err) {
+		gidsetsize = err/sizeof(gid_t); /* +1? */	
+        err = -EFAULT;
+    } 
+	if (gidsetsize < NGROUPS)
+		current->groups[gidsetsize] = NOGROUP;
+	return err;
 }
 
 int in_group_p(gid_t grp)
@@ -786,20 +779,26 @@
 	int error;
 	if (!name)
 		return -EFAULT;
-	error = verify_area(VERIFY_WRITE, name,sizeof *name);
-	if (error)
-		return error;
-	copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
-	put_user(0,name->sysname+__OLD_UTS_LEN);
-	copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
-	put_user(0,name->nodename+__OLD_UTS_LEN);
-	copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
-	put_user(0,name->release+__OLD_UTS_LEN);
-	copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
-	put_user(0,name->version+__OLD_UTS_LEN);
-	copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
-	put_user(0,name->machine+__OLD_UTS_LEN);
-	return 0;
+	error = copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+	if (!error)
+		error = put_user(0,name->sysname+__OLD_UTS_LEN);
+	if (!error)
+		error = copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	if (!error)
+		error = put_user(0,name->nodename+__OLD_UTS_LEN);
+	if (!error)
+		error = copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	if (!error)
+		error = put_user(0,name->release+__OLD_UTS_LEN);
+	if (!error)
+		error = copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	if (!error)
+		error = put_user(0,name->version+__OLD_UTS_LEN);
+	if (!error)
+		error = copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	if (!error)
+		error = put_user(0,name->machine+__OLD_UTS_LEN);
+	return error ? -EFAULT : 0;
 }
 
 #endif
@@ -812,10 +811,9 @@
 		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
-	error = verify_area(VERIFY_READ, name, len);
+	error = copy_from_user(system_utsname.nodename, name, len);
 	if (error)
-		return error;
-	copy_from_user(system_utsname.nodename, name, len);
+		return -EFAULT;
 	system_utsname.nodename[len] = 0;
 	return 0;
 }
@@ -826,14 +824,10 @@
 
 	if (len < 0)
 		return -EINVAL;
-	i = verify_area(VERIFY_WRITE, name, len);
-	if (i)
-		return i;
 	i = 1+strlen(system_utsname.nodename);
 	if (i > len)
 		i = len;
-	copy_to_user(name, system_utsname.nodename, i);
-	return 0;
+	return copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
 }
 
 /*
@@ -848,25 +842,19 @@
 		return -EPERM;
 	if (len < 0 || len > __NEW_UTS_LEN)
 		return -EINVAL;
-	error = verify_area(VERIFY_READ, name, len);
+	error = copy_from_user(system_utsname.domainname, name, len);
 	if (error)
-		return error;
-	copy_from_user(system_utsname.domainname, name, len);
+		return -EFAULT;
 	system_utsname.domainname[len] = 0;
 	return 0;
 }
 
 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
 {
-	int error;
-
 	if (resource >= RLIM_NLIMITS)
 		return -EINVAL;
-	error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
-	if (error)
-		return error;
-	copy_to_user(rlim, current->rlim + resource, sizeof(*rlim));
-	return 0;	
+	return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim)) 
+			? -EFAULT : 0 ;
 }
 
 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
@@ -876,10 +864,9 @@
 
 	if (resource >= RLIM_NLIMITS)
 		return -EINVAL;
-	err = verify_area(VERIFY_READ, rlim, sizeof(*rlim));
+	err = copy_from_user(&new_rlim, rlim, sizeof(*rlim));
 	if (err)
-		return err;
-	copy_from_user(&new_rlim, rlim, sizeof(*rlim));
+		return -EFAULT;	
 	old_rlim = current->rlim + resource;
 	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
 	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
@@ -903,12 +890,8 @@
  */
 int getrusage(struct task_struct *p, int who, struct rusage *ru)
 {
-	int error;
 	struct rusage r;
 
-	error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
-	if (error)
-		return error;
 	memset((char *) &r, 0, sizeof(r));
 	switch (who) {
 		case RUSAGE_SELF:
@@ -939,8 +922,7 @@
 			r.ru_nswap = p->nswap + p->cnswap;
 			break;
 	}
-	copy_to_user(ru, &r, sizeof(r));
-	return 0;
+	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
 asmlinkage int sys_getrusage(int who, struct rusage *ru)
diff -u --recursive --new-file v2.1.10/linux/kernel/time.c linux/kernel/time.c
--- v2.1.10/linux/kernel/time.c	Tue Nov 12 15:56:15 1996
+++ linux/kernel/time.c	Sat Nov 16 13:11:18 1996
@@ -202,15 +202,13 @@
 	/* Local copy of parameter */
 	struct timex txc;
 
-	error = verify_area(VERIFY_WRITE, txc_p, sizeof(struct timex));
-	if (error)
-	  return error;
-
 	/* Copy the user data space into the kernel copy
 	 * structure. But bear in mind that the structures
 	 * may change
 	 */
-	copy_from_user(&txc, txc_p, sizeof(struct timex));
+	error = copy_from_user(&txc, txc_p, sizeof(struct timex));
+	if (error)
+		return -EFAULT;	
 
 	/* In order to modify anything, you gotta be super-user! */
 	if (txc.modes && !suser())
@@ -345,6 +343,5 @@
 
 	sti();
 
-	copy_to_user(txc_p, &txc, sizeof(struct timex));
-	return time_state;
+	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : time_state;
 }
diff -u --recursive --new-file v2.1.10/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.1.10/linux/mm/swapfile.c	Tue Oct 29 19:58:48 1996
+++ linux/mm/swapfile.c	Fri Nov 15 22:25:19 1996
@@ -518,7 +518,8 @@
 	p->flags = SWP_WRITEOK;
 	p->pages = j;
 	nr_swap_pages += j;
-	printk("Adding Swap: %dk swap-space\n",j<<(PAGE_SHIFT-10));
+	printk("Adding Swap: %dk swap-space (priority %d)\n",
+	       j<<(PAGE_SHIFT-10), p->prio);
 
 	/* insert swap space into swap_list: */
 	prev = -1;
diff -u --recursive --new-file v2.1.10/linux/net/802/Makefile linux/net/802/Makefile
--- v2.1.10/linux/net/802/Makefile	Tue Apr  9 14:36:31 1996
+++ linux/net/802/Makefile	Mon Nov 18 11:31:34 1996
@@ -14,6 +14,10 @@
 O_OBJS += tr.o
 endif
 
+ifdef CONFIG_FDDI
+O_OBJS += fddi.o
+endif
+
 ifdef CONFIG_IPX
 OX_OBJS += p8022.o psnap.o p8022tr.o
 endif
diff -u --recursive --new-file v2.1.10/linux/net/802/fddi.c linux/net/802/fddi.c
--- v2.1.10/linux/net/802/fddi.c	Thu Jan  1 02:00:00 1970
+++ linux/net/802/fddi.c	Mon Nov 18 11:31:34 1996
@@ -0,0 +1,162 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		FDDI-type device handling.
+ *
+ * Version:	@(#)fddi.c	1.0.0	08/12/96
+ *
+ * Authors:	Lawrence V. Stefani, <stefani@lkg.dec.com>
+ *
+ *		fddi.c is based on previous eth.c and tr.c work by
+ *			Ross Biro, <bir7@leland.Stanford.Edu>
+ *			Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *			Mark Evans, <evansmp@uhura.aston.ac.uk>
+ *			Florian La Roche, <rzsfl@rz.uni-sb.de>
+ *			Alan Cox, <gw4pts@gw4pts.ampr.org>
+ * 
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/socket.h>
+#include <linux/in.h>
+#include <linux/inet.h>
+#include <linux/netdevice.h>
+#include <linux/fddidevice.h>
+#include <linux/skbuff.h>
+#include <linux/errno.h>
+#include <net/arp.h>
+#include <net/sock.h>
+
+/*
+ * Create the FDDI MAC header for an arbitrary protocol layer
+ *
+ * saddr=NULL	means use device source address
+ * daddr=NULL	means leave destination address (eg unresolved arp)
+ */
+
+int fddi_header(
+	struct sk_buff	*skb,
+	struct device	*dev,
+	unsigned short	type,
+	void			*daddr,
+	void			*saddr,
+	unsigned		len
+	)
+
+	{
+	struct fddihdr *fddi = (struct fddihdr *)skb_push(skb, FDDI_K_SNAP_HLEN);
+
+	/* Fill in frame header - assume 802.2 SNAP frames for now */
+
+	fddi->fc					 = FDDI_FC_K_ASYNC_LLC_DEF;
+	fddi->hdr.llc_snap.dsap		 = FDDI_EXTENDED_SAP;
+	fddi->hdr.llc_snap.ssap		 = FDDI_EXTENDED_SAP;
+	fddi->hdr.llc_snap.ctrl		 = FDDI_UI_CMD;
+	fddi->hdr.llc_snap.oui[0]	 = 0x00;
+	fddi->hdr.llc_snap.oui[1]	 = 0x00;
+	fddi->hdr.llc_snap.oui[2]	 = 0x00;
+	fddi->hdr.llc_snap.ethertype = htons(type);
+
+	/* Set the source and destination hardware addresses */
+	 
+	if (saddr != NULL)
+		memcpy(fddi->saddr, saddr, dev->addr_len);
+	else
+		memcpy(fddi->saddr, dev->dev_addr, dev->addr_len);
+
+	if (daddr != NULL)
+		{
+		memcpy(fddi->daddr, daddr, dev->addr_len);
+		return(FDDI_K_SNAP_HLEN);
+		}
+	return(-FDDI_K_SNAP_HLEN);
+	}
+
+
+/*
+ * Rebuild the FDDI MAC header. This is called after an ARP
+ * (or in future other address resolution) has completed on
+ * this sk_buff.  We now let ARP fill in the other fields.
+ */
+ 
+int fddi_rebuild_header(
+	void			*buff,
+	struct device	*dev,
+	unsigned long	dest,
+	struct sk_buff	*skb
+	)
+
+	{
+	struct fddihdr *fddi = (struct fddihdr *)buff;
+
+	/* Only ARP/IP is currently supported */
+	 
+	if (fddi->hdr.llc_snap.ethertype != htons(ETH_P_IP))
+		{
+		printk("fddi_rebuild_header: Don't know how to resolve type %04X addresses?\n", (unsigned int)htons(fddi->hdr.llc_snap.ethertype));
+		return(0);
+		}
+
+	/* Try to get ARP to resolve the header and fill destination address */
+
+	if (arp_find(fddi->daddr, dest, dev, dev->pa_addr, skb))
+		return(1);
+	else
+		return(0);
+	}
+
+
+/*
+ * Determine the packet's protocol ID and fill in skb fields.
+ * This routine is called before an incoming packet is passed
+ * up.  It's used to fill in specific skb fields and to set
+ * the proper pointer to the start of packet data (skb->data).
+ */
+ 
+unsigned short fddi_type_trans(
+	struct sk_buff	*skb,
+	struct device	*dev
+	)
+
+	{
+	struct fddihdr *fddi = (struct fddihdr *)skb->data;
+
+	/*
+	 * Set mac.raw field to point to FC byte, set data field to point
+	 * to start of packet data.  Assume 802.2 SNAP frames for now.
+	 */
+
+	skb->mac.raw = skb->data;			/* point to frame control (FC) */
+	skb_pull(skb, FDDI_K_SNAP_HLEN);	/* adjust for 21 byte header */
+
+	/* Set packet type based on destination address and flag settings */
+			
+	if (*fddi->daddr & 0x01)
+		{
+		if (memcmp(fddi->daddr, dev->broadcast, FDDI_K_ALEN) == 0)
+			skb->pkt_type = PACKET_BROADCAST;
+		else
+			skb->pkt_type = PACKET_MULTICAST;
+		}
+	
+	else if (dev->flags & IFF_PROMISC)
+		{
+		if (memcmp(fddi->daddr, dev->dev_addr, FDDI_K_ALEN))
+			skb->pkt_type = PACKET_OTHERHOST;
+		}
+
+	/* Assume 802.2 SNAP frames, for now */
+
+	return(fddi->hdr.llc_snap.ethertype);
+	}
diff -u --recursive --new-file v2.1.10/linux/net/Config.in linux/net/Config.in
--- v2.1.10/linux/net/Config.in	Tue Nov 12 15:56:15 1996
+++ linux/net/Config.in	Mon Nov 18 11:31:34 1996
@@ -3,6 +3,10 @@
 #
 mainmenu_option next_comment
 comment 'Networking options'
+bool 'Kernel/User network link driver' CONFIG_NETLINK
+if [ "$CONFIG_NETLINK" = "y" ]; then
+  bool 'Routing messages' CONFIG_RTNETLINK
+fi
 bool 'Network firewalls' CONFIG_FIREWALL
 bool 'Network aliasing'  CONFIG_NET_ALIAS
 bool 'TCP/IP networking' CONFIG_INET
@@ -27,9 +31,5 @@
 fi
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   bool 'Bridging (EXPERIMENTAL)' CONFIG_BRIDGE
-fi
-bool 'Kernel/User network link driver' CONFIG_NETLINK
-if [ "$CONFIG_NETLINK" = "y" ]; then
-  bool 'Routing messages' CONFIG_RTNETLINK
 fi
 endmenu
diff -u --recursive --new-file v2.1.10/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.10/linux/net/appletalk/ddp.c	Fri Nov 15 23:49:10 1996
+++ linux/net/appletalk/ddp.c	Mon Nov 18 11:31:34 1996
@@ -23,6 +23,7 @@
  *		Tom Dyas		:	Module support.
  *		Alan Cox		:	Hooks for PPP (based on the
  *						localtalk hook).
+ *		Alan Cox		:	Posix bits
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -735,7 +736,6 @@
 	struct sockaddr_at *sa;
 	struct device *dev;
 	struct atalk_iface *atif;
-	int ro=(cmd==SIOCSIFADDR);
 	int err;
 	int ct;
 	int limit;
@@ -1234,7 +1234,7 @@
  *	Set the address 'our end' of the connection.
  */
  
-static int atalk_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
+static int atalk_bind(struct socket *sock, struct sockaddr *uaddr,size_t addr_len)
 {
 	atalk_socket *sk;
 	struct sockaddr_at *addr=(struct sockaddr_at *)uaddr;
@@ -1242,7 +1242,7 @@
 	sk=(atalk_socket *)sock->data;
 	
 	if(sk->zapped==0)
-		return(-EIO);
+		return(-EINVAL);
 		
 	if(addr_len!=sizeof(struct sockaddr_at))
 		return -EINVAL;
@@ -1289,7 +1289,7 @@
  */
  
 static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
-	int addr_len, int flags)
+	size_t addr_len, int flags)
 {
 	atalk_socket *sk=(atalk_socket *)sock->data;
 	struct sockaddr_at *addr;
@@ -1303,9 +1303,9 @@
 	
 	if(addr->sat_family!=AF_APPLETALK)
 		return -EAFNOSUPPORT;
-#if 0 	/* Netatalk doesn't check this */
+#if 0 	/* Netatalk doesn't check this - fix netatalk first!*/
 	if(addr->sat_addr.s_node==ATADDR_BCAST && !sk->broadcast)
-		return -EPERM;
+		return -EACCES;
 #endif		
 	if(sk->zapped)
 	{
@@ -1350,7 +1350,7 @@
  */
  
 static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
-	int *uaddr_len, int peer)
+	size_t *uaddr_len, int peer)
 {
 	struct sockaddr_at sat;
 	atalk_socket *sk;
@@ -1359,7 +1359,7 @@
 	if(sk->zapped)
 	{
 		if(atalk_autobind(sk)<0)
-			return -EBUSY;
+			return -ENOBUFS;
 	}	
 	
 	*uaddr_len = sizeof(struct sockaddr_at);
@@ -1410,6 +1410,10 @@
 	 *	Fix up the length field	[Ok this is horrible but otherwise
 	 *	I end up with unions of bit fields and messy bit field order
 	 *	compiler/endian dependencies..]
+	 *
+	 *	FIXME: This is a write to a shared object. Granted it
+	 *	happens to be safe BUT.. (Its safe as user space will not
+	 *	run until we put it back)
 	 */
 
 	*((__u16 *)ddp)=ntohs(*((__u16 *)ddp));
@@ -1520,10 +1524,13 @@
 		 *	Send the buffer onwards
 		 */
 		 
-		skb->arp = 1;	/* Resolved */
-		
-		if(aarp_send_ddp(rt->dev, skb, &ta, NULL)==-1)
-			kfree_skb(skb, FREE_READ);
+		skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
+		if(skb)
+		{
+			skb->arp = 1;	/* Resolved */
+			if(aarp_send_ddp(rt->dev, skb, &ta, NULL)==-1)
+				kfree_skb(skb, FREE_READ);
+		}
 		return 0;
 	}
 
@@ -1642,7 +1649,6 @@
 	if(usat)
 	{
 		if(sk->zapped)
-		/* put the autobinding in */
 		{
 			if(atalk_autobind(sk)<0)
 				return -EBUSY;
@@ -1738,7 +1744,7 @@
 	if (err)
 	{
 		kfree_skb(skb, FREE_WRITE);
-		return err;
+		return -EFAULT;
 	}
 		
 	if(sk->no_check==1)
@@ -1821,9 +1827,6 @@
 	struct sk_buff *skb;
 	int er = 0;
 	
-	if(sk->err)
-		return sock_error(sk);
-	
 	if(addr_len)
 		*addr_len=sizeof(*sat);
 
@@ -1836,7 +1839,10 @@
 	{
 		copied=ddp->deh_len;
 		if(copied > size)
+		{
 			copied=size;
+			msg->msg_flags|=MSG_TRUNC;
+		}
 		er = skb_copy_datagram_iovec(skb,0,msg->msg_iov,copied);
 		if (er)
 			goto out;
@@ -1845,7 +1851,10 @@
 	{
 		copied=ddp->deh_len - sizeof(*ddp);
 		if (copied > size)
+		{
 			copied = size;
+			msg->msg_flags|=MSG_TRUNC;
+		}
 		er = skb_copy_datagram_iovec(skb,sizeof(*ddp),msg->msg_iov,copied);
 		if (er) 
 			goto out; 
@@ -1881,7 +1890,6 @@
 
 static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
 {
-	int err;
 	long amount=0;
 	atalk_socket *sk=(atalk_socket *)sock->data;
 	
@@ -1908,7 +1916,7 @@
 			{
 				if(sk->stamp.tv_sec==0)
 					return -ENOENT;
-				return copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval));
+				return copy_to_user((void *)arg,&sk->stamp,sizeof(struct timeval)) ? -EFAULT : 0;
 			}
 			return -EINVAL;
 		/*
@@ -2049,7 +2057,7 @@
 	proc_net_register(&proc_atalk_iface);
 #endif	
 
-	printk(KERN_INFO "Appletalk 0.17 for Linux NET3.035\n");
+	printk(KERN_INFO "Appletalk 0.18 for Linux NET3.037\n");
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.1.10/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.10/linux/net/ax25/af_ax25.c	Tue Nov 12 15:56:15 1996
+++ linux/net/ax25/af_ax25.c	Mon Nov 18 11:31:34 1996
@@ -1,10 +1,10 @@
 /*
- *	AX.25 release 033
+ *	AX.25 release 034
  *
  *	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. 
  *
- *	This code REQUIRES 1.2.1 or higher/ NET3.029
+ *	This code REQUIRES 2.1.10 or higher/ NET3.029
  *
  *	This module:
  *		This module is free software; you can redistribute it and/or
@@ -84,6 +84,8 @@
  *	AX.25 033	Jonathan(G4KLX)		Removed auto-router.
  *			Hans(PE1AYX)		Converted to Module.
  *			Joerg(DL1BKE)		Moved BPQ Ethernet to seperate driver.
+ *	AX.25 034	Jonathan(G4KLX)		2.1 changes
+ *			Alan(GW4PTS)		Small POSIXisations
  *
  *	To do:
  *		Restructure the ax25_rcv code to be cleaner/faster and
@@ -1359,7 +1361,7 @@
  *	BSD 4.4 ADDIFADDR type support. It is however small and trivially backward
  *	compatible 8)
  */
-static int ax25_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
+static int ax25_bind(struct socket *sock, struct sockaddr *uaddr,size_t addr_len)
 {
 	struct sock *sk;
 	struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
@@ -1369,14 +1371,14 @@
 	sk = (struct sock *)sock->data;
 	
 	if (sk->zapped == 0)
-		return -EIO;
+		return -EINVAL;
 		
 	if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
 		return -EINVAL;
 
 	call = ax25_findbyuid(current->euid);
 	if (call == NULL && ax25_uid_policy && !suser())
-		return -EPERM;
+		return -EACCES;
 		
 	if (call == NULL)
 		sk->protinfo.ax25->source_addr = addr->fsa_ax25.sax25_call;
@@ -1422,7 +1424,7 @@
 }
 
 static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
-	int addr_len, int flags)
+	size_t addr_len, int flags)
 {
 	struct sock *sk = (struct sock *)sock->data;
 	struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
@@ -1460,7 +1462,7 @@
 
 		if (sk->protinfo.ax25->digipeat == NULL) {
 			if ((sk->protinfo.ax25->digipeat = (ax25_digi *)kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL)
-				return -ENOMEM;
+				return -ENOBUFS;
 		}
 
 		sk->protinfo.ax25->digipeat->ndigi = addr->sax25_ndigis;
@@ -1490,7 +1492,7 @@
 	}
 		
 	if (sk->type == SOCK_SEQPACKET && ax25_find_cb(&sk->protinfo.ax25->source_addr, &addr->sax25_call, sk->protinfo.ax25->device) != NULL)
-		return -EBUSY;				/* Already such a connection */
+		return -EADDRINUSE;			/* Already such a connection */
 
 	sk->protinfo.ax25->dest_addr = addr->sax25_call;
 	
@@ -1599,7 +1601,7 @@
 }
 
 static int ax25_getname(struct socket *sock, struct sockaddr *uaddr,
-	int *uaddr_len, int peer)
+	size_t *uaddr_len, int peer)
 {
 	struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
 	struct sock *sk;
@@ -1677,6 +1679,10 @@
 	if (dp.lastrepeat + 1 < dp.ndigi) {		/* Not yet digipeated completely */
 		if (ax25cmp(&dp.calls[dp.lastrepeat + 1], dev_addr) == 0) {
 			struct device *dev_out = dev;
+			
+			skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
+			if(skb==NULL)
+				return 0;
 
 			/* We are the digipeater. Mark ourselves as repeated
 			   and throw the packet back out of the same device */
@@ -1959,6 +1965,12 @@
 	if (sk->zapped)
 		return -EADDRNOTAVAIL;
 		
+	if (sk->shutdown & SEND_SHUTDOWN)
+	{
+		send_sig(SIGPIPE, current, 0);
+		return -EPIPE;
+	}
+		
 	if (sk->protinfo.ax25->device == NULL)
 		return -ENETUNREACH;
 		
@@ -1994,6 +2006,11 @@
 		else
 			dp = &dtmp;
 	} else {
+		/*
+		 *	FIXME: 1003.1g - if the socket is like this because
+		 *	it has become closed (not started closed) and is VC
+		 *	we ought to SIGPIPE, EPIPE
+		 */
 		if (sk->state != TCP_ESTABLISHED)
 			return -ENOTCONN;
 		sax.sax25_family = AF_AX25;
@@ -2082,9 +2099,6 @@
 	int er;
 	int dama;
 
-	if (sk->err)
-		return sock_error(sk);
-	
 	if (addr_len != NULL)
 		*addr_len = sizeof(*sax);
 
@@ -2108,7 +2122,12 @@
 		skb->h.raw = skb->data;
 	}
 
-	copied = (size < length) ? size : length;
+	copied=size;
+	if(copied>length)
+	{
+		copied = length;
+		msg->msg_flags|=MSG_TRUNC;
+	}		
 	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	
 	if (sax) {
@@ -2421,7 +2440,7 @@
 	proc_net_register(&proc_ax25_calls);
 #endif	
 
-	printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.33 for Linux NET3.035 (Linux 2.0)\n");
+	printk(KERN_INFO "G4KLX/GW4PTS AX.25 for Linux. Version 0.34 for Linux NET3.037 (Linux 2.1)\n");
 }
 
 /*
diff -u --recursive --new-file v2.1.10/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.1.10/linux/net/ax25/ax25_in.c	Tue Nov 12 15:56:15 1996
+++ linux/net/ax25/ax25_in.c	Mon Nov 18 11:31:34 1996
@@ -245,6 +245,7 @@
 					if (ax25->sk != NULL) {
 						ax25->sk->state = TCP_CLOSE;
 						ax25->sk->err   = ECONNREFUSED;
+						ax25->sk->shutdown |= SEND_SHUTDOWN;
 						if (!ax25->sk->dead)
 							ax25->sk->state_change(ax25->sk);
 						ax25->sk->dead  = 1;
@@ -289,6 +290,7 @@
 				if (ax25->sk != NULL) {
 					ax25->sk->state = TCP_CLOSE;
 					ax25->sk->err   = 0;
+					ax25->sk->shutdown |= SEND_SHUTDOWN;
 					if (!ax25->sk->dead)
 						ax25->sk->state_change(ax25->sk);
 					ax25->sk->dead  = 1;
@@ -304,6 +306,7 @@
 				if (ax25->sk != NULL) {
 					ax25->sk->state = TCP_CLOSE;
 					ax25->sk->err   = 0;
+					ax25->sk->shutdown |= SEND_SHUTDOWN;
 					if (!ax25->sk->dead)
 						ax25->sk->state_change(ax25->sk);
 					ax25->sk->dead  = 1;
@@ -319,6 +322,7 @@
 				if (ax25->sk != NULL) {
 					ax25->sk->state = TCP_CLOSE;
 					ax25->sk->err   = 0;
+					ax25->sk->shutdown|=SEND_SHUTDOWN;
 					if (!ax25->sk->dead)
 						ax25->sk->state_change(ax25->sk);
 					ax25->sk->dead  = 1;
@@ -400,6 +404,7 @@
 				if (!ax25->sk->dead)
 					ax25->sk->state_change(ax25->sk);
 				ax25->sk->dead  = 1;
+				ax25->sk->shutdown|=SEND_SHUTDOWN;
 			}
 			break;
 
@@ -411,6 +416,7 @@
 			if (ax25->sk) {
 				ax25->sk->state = TCP_CLOSE;
 				ax25->sk->err   = ECONNRESET;
+				ax25->sk->shutdown |= SEND_SHUTDOWN;
 				if (!ax25->sk->dead)
 					ax25->sk->state_change(ax25->sk);
 				ax25->sk->dead         = 1;
@@ -594,6 +600,7 @@
 			if (ax25->sk != NULL) {
 				ax25->sk->state = TCP_CLOSE;
 				ax25->sk->err   = 0;
+				ax25->sk->shutdown |= SEND_SHUTDOWN;
 				if (!ax25->sk->dead)
 					ax25->sk->state_change(ax25->sk);
 				ax25->sk->dead  = 1;
@@ -609,6 +616,7 @@
 			if (ax25->sk != NULL) {
 				ax25->sk->state = TCP_CLOSE;
 				ax25->sk->err   = ECONNRESET;
+				ax25->sk->shutdown |= SEND_SHUTDOWN;
 				if (!ax25->sk->dead)
 					ax25->sk->state_change(ax25->sk);
 				ax25->sk->dead  = 1;
diff -u --recursive --new-file v2.1.10/linux/net/ax25/ax25_timer.c linux/net/ax25/ax25_timer.c
--- v2.1.10/linux/net/ax25/ax25_timer.c	Tue Nov 12 15:56:15 1996
+++ linux/net/ax25/ax25_timer.c	Mon Nov 18 11:31:34 1996
@@ -152,6 +152,7 @@
 					printk(KERN_DEBUG "AX.25 T3 Timeout\n");
 				ax25->sk->state = TCP_CLOSE;
 				ax25->sk->err   = ETIMEDOUT;
+				ax25->sk->shutdown |= SEND_SHUTDOWN;
 				if (!ax25->sk->dead)
 					ax25->sk->state_change(ax25->sk);
 				ax25->sk->dead  = 1;
@@ -196,6 +197,7 @@
 		if (ax25->sk != NULL) {
 			ax25->sk->state = TCP_CLOSE;
 			ax25->sk->err = 0;
+			ax25->sk->shutdown |= SEND_SHUTDOWN;
 			if (!ax25->sk->dead)
 				ax25->sk->state_change(ax25->sk);
 			ax25->sk->dead = 1;
@@ -239,6 +241,7 @@
 					if (ax25->sk != NULL) {
 						ax25->sk->state = TCP_CLOSE;
 						ax25->sk->err   = ETIMEDOUT;
+						ax25->sk->shutdown |= SEND_SHUTDOWN;
 						if (!ax25->sk->dead)
 							ax25->sk->state_change(ax25->sk);
 						ax25->sk->dead  = 1;
@@ -269,6 +272,7 @@
 				if (ax25->sk != NULL) {
 					ax25->sk->state = TCP_CLOSE;
 					ax25->sk->err   = ETIMEDOUT;
+					ax25->sk->shutdown |= SEND_SHUTDOWN;
 					if (!ax25->sk->dead)
 						ax25->sk->state_change(ax25->sk);
 					ax25->sk->dead  = 1;
@@ -298,6 +302,7 @@
 						printk(KERN_DEBUG "AX.25 link Failure\n");
 					ax25->sk->state = TCP_CLOSE;
 					ax25->sk->err   = ETIMEDOUT;
+					ax25->sk->shutdown |= SEND_SHUTDOWN;
 					if (!ax25->sk->dead)
 						ax25->sk->state_change(ax25->sk);
 					ax25->sk->dead  = 1;
diff -u --recursive --new-file v2.1.10/linux/net/ax25/sysctl_net_ax25.c linux/net/ax25/sysctl_net_ax25.c
--- v2.1.10/linux/net/ax25/sysctl_net_ax25.c	Tue Nov 12 15:56:15 1996
+++ linux/net/ax25/sysctl_net_ax25.c	Sat Nov 16 14:17:53 1996
@@ -10,9 +10,9 @@
 #include <net/ax25.h>
 
 static int min_ax25[] = {0, 0, 0, 0, 0, 1,  1,  1 * PR_SLOWHZ,  1 * PR_SLOWHZ,
-	   0 * PR_SLOWHZ,     0 * PR_SLOWHZ,  1,   1, 0x00, 1};
+	   0 * PR_SLOWHZ,     0 * PR_SLOWHZ,  1,   1,  1, 0x00};
 static int max_ax25[] = {1, 1, 1, 1, 1, 7, 63, 30 * PR_SLOWHZ, 20 * PR_SLOWHZ,
-	3600 * PR_SLOWHZ, 65535 * PR_SLOWHZ, 31, 512, 0x03, 20};
+	3600 * PR_SLOWHZ, 65535 * PR_SLOWHZ, 31, 512, 20, 0x03};
 
 static struct ctl_table_header *ax25_table_header;
 
diff -u --recursive --new-file v2.1.10/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.1.10/linux/net/bridge/br.c	Fri Nov 15 23:49:11 1996
+++ linux/net/bridge/br.c	Mon Nov 18 11:31:34 1996
@@ -3,6 +3,10 @@
  *
  *	Originally by John Hayes (Network Plumbing).
  *	Minor hacks to get it to run with 1.3.x by Alan Cox <Alan.Cox@linux.org>
+ *	More hacks to be able to switch protocols on and off by Christoph Lameter
+ *	<clameter@debian.org>
+ *	Software and more Documentation for the bridge is available from ftp.debian.org
+ *	in the bridge package or at ftp.fuller.edu/Linux/bridge
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -79,6 +83,67 @@
 	0
 };
 
+/*
+ * Implementation of Protocol specific bridging
+ *
+ * The protocols to be bridged or not to be bridged are stored in a hashed array. This is the old type
+ * of unlinked hash array where one simply takes the next cell if the one the hash function points to
+ * is occupied.
+ */
+
+#define BR_PROTOCOL_HASH(x) (x % BR_MAX_PROTOCOLS)
+
+/* Checks if that protocol type is to be bridged */
+int br_protocol_ok(unsigned short protocol)
+{
+	unsigned x;
+	
+	/* See if protocol statistics are to be kept */
+	if (br_stats.flags & BR_PROT_STATS)
+	{ for(x=0;x<BR_MAX_PROT_STATS &&
+	     br_stats.prot_id[x]!=protocol && br_stats.prot_id[x];x++) ;
+	  if (x<BR_MAX_PROT_STATS)
+	  { br_stats.prot_id[x]=protocol;br_stats.prot_counter[x]++;
+	  }
+	}
+
+	for (x=BR_PROTOCOL_HASH(protocol); br_stats.protocols[x]!=0;) {
+		if (br_stats.protocols[x]==protocol) return !br_stats.policy;
+		x++;
+		if (x==BR_MAX_PROTOCOLS) x=0;
+	}
+	return br_stats.policy;
+}
+
+/* Add a protocol to be handled opposite to the standard policy of the bridge */
+
+int br_add_exempt_protocol(unsigned short p)
+{
+	unsigned x;
+	if (p == 0) return -EINVAL;
+	if (br_stats.exempt_protocols > BR_MAX_PROTOCOLS-2) return -EXFULL;
+	for (x=BR_PROTOCOL_HASH(p);br_stats.protocols[x]!=0;) {
+		if (br_stats.protocols[x]==p) return 0;	/* Attempt to add the protocol a second time */
+		x++;
+		if (x==BR_MAX_PROTOCOLS) x=0;
+	}
+	br_stats.protocols[x]=p;
+	br_stats.exempt_protocols++;
+	return 0;
+}
+
+/* Valid Policies are 0=No Protocols bridged 1=Bridge all protocols */
+int br_set_policy(int policy)
+{
+	if (policy>1) return -EINVAL;
+	br_stats.policy=policy;
+	/* Policy change means initializing the exempt table */
+	memset(br_stats.protocols,0,sizeof(br_stats.protocols));
+	br_stats.exempt_protocols = 0;
+	return 0;
+}
+
+
 /** Elements of Procedure (4.6) **/
 
 /*
@@ -579,7 +644,7 @@
 {						  /* (4.8.1)	 */
 	int             port_no;
 
-	printk(KERN_INFO "Ethernet Bridge 002 for NET3.035 (Linux 2.0)\n");
+	printk(KERN_INFO "Ethernet Bridge 003 for NET3.037 (Linux 2.1)\n");
 	bridge_info.designated_root = bridge_info.bridge_id;	/* (4.8.1.1)	 */
 	bridge_info.root_path_cost = Zero;
 	bridge_info.root_port = No_port;
@@ -611,6 +676,8 @@
 
 	register_netdevice_notifier(&br_dev_notifier);
 	br_stats.flags = 0; /*BR_UP | BR_DEBUG*/;	/* enable bridge */
+	br_stats.policy = BR_ACCEPT;			/* Enable bridge to accpet all protocols */
+	br_stats.exempt_protocols = 0;
 	/*start_hello_timer();*/
 }
 
@@ -1052,7 +1119,6 @@
 int br_receive_frame(struct sk_buff *skb)	/* 3.5 */
 {
 	int port;
-	int i;
 	
 	if (br_stats.flags & BR_DEBUG)
 		printk("br_receive_frame: ");
@@ -1511,6 +1577,20 @@
 				case BRCMD_DISABLE_DEBUG:
 					br_stats.flags &= ~BR_DEBUG;
 					break;
+				case BRCMD_SET_POLICY:
+					return br_set_policy(bcf.arg1);
+				case BRCMD_EXEMPT_PROTOCOL:
+					return br_add_exempt_protocol(bcf.arg1);
+				case BRCMD_ENABLE_PROT_STATS:
+					br_stats.flags |= BR_PROT_STATS;
+					break;
+				case BRCMD_DISABLE_PROT_STATS:
+					br_stats.flags &= ~BR_PROT_STATS;
+					break;
+				case BRCMD_ZERO_PROT_STATS:
+					memset(&br_stats.prot_id,0,sizeof(br_stats.prot_id));
+					memset(&br_stats.prot_counter,0,sizeof(br_stats.prot_counter));
+					break;
 				default:
 					return -EINVAL;
 			}
@@ -1536,4 +1616,4 @@
 	}
 	return(0);
 }
-		
+
diff -u --recursive --new-file v2.1.10/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.1.10/linux/net/core/datagram.c	Fri Nov 15 23:49:11 1996
+++ linux/net/core/datagram.c	Mon Nov 18 11:31:34 1996
@@ -19,6 +19,7 @@
  *		Linus Torvalds	:	BSD semantic fixes.
  *		Alan Cox	:	Datagram iovec handling
  *		Darryl Miles	:	Fixed non-blocking SOCK_STREAM.
+ *		Alan Cox	:	POSIXisms
  *
  */
 
@@ -80,6 +81,10 @@
  *
  *	This function will lock the socket if a skb is returned, so the caller
  *	needs to unlock the socket in that case (usually by calling skb_free_datagram)
+ *
+ *	The order of the tests when we find no data waiting are specified
+ *	quite explicitly by POSIX 1003.1g, don't change them without having
+ *	the standard around please.
  */
 
 struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
@@ -105,14 +110,14 @@
 		if(connection_based(sk) && sk->state!=TCP_ESTABLISHED)
 			goto no_packet;
 
-		/* User doesn't want to wait */
-		error = -EAGAIN;
-		if (noblock)
-			goto no_packet;
-
 		/* handle signals */
 		error = -ERESTARTSYS;
 		if (current->signal & ~current->blocked)
+			goto no_packet;
+
+		/* User doesn't want to wait */
+		error = -EAGAIN;
+		if (noblock)
 			goto no_packet;
 
 		wait_for_packet(sk);
diff -u --recursive --new-file v2.1.10/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.10/linux/net/core/dev.c	Fri Nov 15 23:49:11 1996
+++ linux/net/core/dev.c	Mon Nov 18 11:31:35 1996
@@ -597,10 +597,11 @@
 
 		/*
 		 *	If we are bridging then pass the frame up to the
-		 *	bridging code. If it is bridged then move on
+		 *	bridging code (if this protocol is to be bridged).
+		 *      If it is bridged then move on
 		 */
 		 
-		if (br_stats.flags & BR_UP)
+		if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(skb->protocol)))
 		{
 			/*
 			 *	We pass the bridge a complete frame. This means
diff -u --recursive --new-file v2.1.10/linux/net/core/iovec.c linux/net/core/iovec.c
--- v2.1.10/linux/net/core/iovec.c	Fri Nov 15 23:49:11 1996
+++ linux/net/core/iovec.c	Mon Nov 18 10:36:06 1996
@@ -94,9 +94,8 @@
 		{
 			int copy = min(iov->iov_len,len);
 			err = copy_to_user(iov->iov_base,kdata,copy);
-			if (err) {
-				return err; 
-			}
+			if (err) 
+			    return err;
 			kdata+=copy;
 			len-=copy;
 			iov->iov_len-=copy;
diff -u --recursive --new-file v2.1.10/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.1.10/linux/net/core/skbuff.c	Fri Nov 15 23:49:11 1996
+++ linux/net/core/skbuff.c	Mon Nov 18 11:31:35 1996
@@ -68,6 +68,13 @@
 
 extern atomic_t ip_frag_mem;
 
+/*
+ *	Strings we don't want inline's duplicating
+ */
+ 
+char *skb_push_errstr="skpush:under: %p:%d";
+char *skb_put_errstr ="skput:over: %p:%d";
+
 void show_net_buffers(void)
 {
 	printk(KERN_INFO "Networking buffers in use          : %u\n",net_skbcount);
diff -u --recursive --new-file v2.1.10/linux/net/core/sock.c linux/net/core/sock.c
--- v2.1.10/linux/net/core/sock.c	Fri Nov 15 23:49:11 1996
+++ linux/net/core/sock.c	Mon Nov 18 11:31:35 1996
@@ -245,6 +245,8 @@
 			sk->bsdism = valbool;
 			break;
 			
+		/* We implementation the SO_SNDLOWAT etc to
+		   not be settable (1003.1g 5.3) */
 		default:
 		  	return(-ENOPROTOOPT);
   	}
@@ -317,12 +319,24 @@
 				ling.l_onoff=sk->linger;
 				ling.l_linger=sk->lingertime;
 				err = copy_to_user(optval,&ling,sizeof(ling));
+				if (err)
+				    err = -EFAULT;
 			}
 			return err;
 		
 		case SO_BSDCOMPAT:
 			val = sk->bsdism;
 			break;
+			
+		case SO_RCVTIMEO:
+		case SO_SNDTIMEO:
+		{
+			static struct timeval tm={0,0};
+			return copy_to_user(optval,&tm,sizeof(tm));
+		}
+		case SO_RCVLOWAT:
+		case SO_SNDLOWAT:
+			val=1;
 
 		default:
 			return(-ENOPROTOOPT);
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/Config.in linux/net/ipv4/Config.in
--- v2.1.10/linux/net/ipv4/Config.in	Fri Jul 19 08:24:05 1996
+++ linux/net/ipv4/Config.in	Mon Nov 18 11:31:35 1996
@@ -6,6 +6,9 @@
 if [ "$CONFIG_FIREWALL" = "y" ]; then
   bool 'IP: firewalling' CONFIG_IP_FIREWALL
   if [ "$CONFIG_IP_FIREWALL" = "y" ]; then
+    if [ "$CONFIG_NETLINK" = "y" ]; then
+	bool 'IP: firewall packet netlink device' CONFIG_IP_FIREWALL_NETLINK
+    fi
     bool 'IP: firewall packet logging' CONFIG_IP_FIREWALL_VERBOSE
     if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_IP_FORWARD" = "y" ]; then
       bool 'IP: masquerading (EXPERIMENTAL)' CONFIG_IP_MASQUERADE
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/af_inet.c linux/net/ipv4/af_inet.c
--- v2.1.10/linux/net/ipv4/af_inet.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/af_inet.c	Mon Nov 18 11:31:35 1996
@@ -454,6 +454,10 @@
 
 /*
  *	Get a socket option on an AF_INET socket.
+ *
+ *	FIX: POSIX 1003.1g is very ambiguous here. It states that
+ *	asynchronous errors should be reported by getsockopt. We assume
+ *	this means if you specify SO_ERROR (otherwise whats the point of it).
  */
 
 int inet_getsockopt(struct socket *sock, int level, int optname,
@@ -763,7 +767,7 @@
 
 
 static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
-	       int addr_len)
+	       size_t addr_len)
 {
 	struct sockaddr_in *addr=(struct sockaddr_in *)uaddr;
 	struct sock *sk=(struct sock *)sock->data, *sk2;
@@ -919,7 +923,7 @@
  */
  
 int inet_connect(struct socket *sock, struct sockaddr * uaddr,
-		 int addr_len, int flags)
+		 size_t addr_len, int flags)
 {
 	struct sock *sk=(struct sock *)sock->data;
 	int err;
@@ -1086,7 +1090,7 @@
  */
  
 static int inet_getname(struct socket *sock, struct sockaddr *uaddr,
-		 int *uaddr_len, int peer)
+		 size_t *uaddr_len, int peer)
 {
 	struct sockaddr_in *sin=(struct sockaddr_in *)uaddr;
 	struct sock *sk;
@@ -1616,7 +1620,7 @@
 	int i;
 
 
-	printk("Swansea University Computer Society TCP/IP for NET3.034\n");
+	printk("Swansea University Computer Society TCP/IP for NET3.037\n");
 
 	/*
 	 *	Tell SOCKET that we are alive... 
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.1.10/linux/net/ipv4/icmp.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/icmp.c	Mon Nov 18 11:31:35 1996
@@ -643,9 +643,16 @@
 	struct inet_protocol *ipprot;
 	unsigned char *dp;	
 	__u32 info = 0;
+	
+	if(len<sizeof(struct iphdr))
+		goto flush_it;
 
 	iph = (struct iphdr *) (icmph + 1);
 	
+	len-=iph->ihl<<2;
+	if(len<0)
+		goto flush_it;
+	
 	dp= ((unsigned char *)iph)+(iph->ihl<<2);
 	
 	if(icmph->type==ICMP_DEST_UNREACH)
@@ -778,11 +785,12 @@
 		if (iph->protocol == ipprot->protocol && ipprot->err_handler) 
 		{
 			ipprot->err_handler(icmph->type, icmph->code, dp, info,
-					    iph->daddr, iph->saddr, ipprot);
+					    iph->daddr, iph->saddr, ipprot, len);
 		}
 
 		ipprot = nextip;
   	}
+flush_it:
 	kfree_skb(skb, FREE_READ);
 }
 
@@ -799,6 +807,9 @@
 	/*
 	 *	Get the copied header of the packet that caused the redirect
 	 */
+	
+	if(len<=sizeof(struct iphdr))
+		goto flush_it;
 	 
 	iph = (struct iphdr *) (icmph + 1);
 	ip = iph->daddr;
@@ -854,7 +865,7 @@
   	/*
   	 *	Discard the original packet
   	 */
-  	 
+flush_it:
   	kfree_skb(skb, FREE_READ);
 }
 
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/igmp.c linux/net/ipv4/igmp.c
--- v2.1.10/linux/net/ipv4/igmp.c	Tue Oct 29 19:58:49 1996
+++ linux/net/ipv4/igmp.c	Mon Nov 18 11:31:35 1996
@@ -61,6 +61,9 @@
  *					miscalculation fixed in igmp_heard_query
  *					and random() made to return unsigned to
  *					prevent negative expiry times.
+ *		Alexey Kuznetsov:	Wrong group leaving behaviour, backport
+ *					fix from pending 2.1.x patches.
+ *		Alan Cox:		Forget to enable FDDI support earlier.
  */
 
 
@@ -278,6 +281,7 @@
 		igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
 	else
 		igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
+	im->reporter=1;
 }
 
 static void igmp_init_timer(struct ip_mc_list *im)
@@ -289,17 +293,24 @@
 }
 
 
-static void igmp_heard_report(struct device *dev, unsigned long address)
+static void igmp_heard_report(struct device *dev, __u32 address, __u32 src)
 {
 	struct ip_mc_list *im;
 
-	if ((address & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP) {
-	  /* Timers are only set for non-local groups */
-	  for(im=dev->ip_mc_list;im!=NULL;im=im->next) {
-	    if(im->multiaddr==address && im->tm_running) {
-	      igmp_stop_timer(im);
-	    }
-	  }
+	if ((address & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP) 
+	{
+		/* Timers are only set for non-local groups */
+		for(im=dev->ip_mc_list;im!=NULL;im=im->next) 
+		{
+			if(im->multiaddr==address)
+			{
+				if(im->tm_running) 
+					igmp_stop_timer(im);
+				if(src!=dev->pa_addr)
+					im->reporter=0;
+				return;
+			}
+		}
 	}
 }
 
@@ -391,8 +402,8 @@
 void ip_mc_filter_add(struct device *dev, unsigned long addr)
 {
 	char buf[6];
-	if(dev->type!=ARPHRD_ETHER)
-		return; /* Only do ethernet now */
+	if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_FDDI)
+		return; /* Only do ethernet or FDDI for now */
 	ip_mc_map(addr,buf);
 	dev_mc_add(dev,buf,ETH_ALEN,0);
 }
@@ -404,8 +415,8 @@
 void ip_mc_filter_del(struct device *dev, unsigned long addr)
 {
 	char buf[6];
-	if(dev->type!=ARPHRD_ETHER)
-		return; /* Only do ethernet now */
+	if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_FDDI)
+		return; /* Only do ethernet or FDDI for now */
 	ip_mc_map(addr,buf);
 	dev_mc_delete(dev,buf,ETH_ALEN,0);
 }
@@ -473,9 +484,9 @@
 	if(ih->type==IGMP_HOST_MEMBERSHIP_QUERY && daddr==IGMP_ALL_HOSTS)
 		igmp_heard_query(dev,ih->code);
 	if(ih->type==IGMP_HOST_MEMBERSHIP_REPORT && daddr==ih->group)
-		igmp_heard_report(dev,ih->group);
+		igmp_heard_report(dev,ih->group, saddr);
 	if(ih->type==IGMP_HOST_NEW_MEMBERSHIP_REPORT && daddr==ih->group)
-		igmp_heard_report(dev,ih->group);
+		igmp_heard_report(dev,ih->group, saddr);
 	kfree_skb(skb, FREE_READ);
 	return 0;
 }
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/ip_forward.c linux/net/ipv4/ip_forward.c
--- v2.1.10/linux/net/ipv4/ip_forward.c	Thu Oct 10 19:10:58 1996
+++ linux/net/ipv4/ip_forward.c	Mon Nov 18 11:31:35 1996
@@ -16,6 +16,7 @@
  *					use output device for accounting.
  *		Jos Vos		:	Call forward firewall after routing
  *					(always use output device).
+ *		Alan Cox	: 	Unshare buffer on forward.
  */
 
 #include <linux/config.h>
@@ -120,6 +121,13 @@
 	struct sk_buff *skb_in = skb;	/* So we can remember if the masquerader did some swaps */
 #endif /* CONFIG_IP_MASQUERADE */
 #endif /* CONFIG_FIREWALL */
+
+	/*
+	 *	We may be sharing the buffer with a snooper. That won't do
+	 */
+	 
+	if((skb=skb_unshare(skb, GFP_ATOMIC,FREE_READ))==NULL)
+		return -1;
 	
 	/*
 	 *	According to the RFC, we must first decrease the TTL field. If
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c
--- v2.1.10/linux/net/ipv4/ip_fw.c	Tue Oct 29 19:58:49 1996
+++ linux/net/ipv4/ip_fw.c	Mon Nov 18 11:31:35 1996
@@ -37,6 +37,8 @@
  *		Willy Konynenberg <willy@xos.nl> 10/5/96.
  *	Make separate accounting on incoming and outgoing packets possible.
  *		Jos Vos <jos@xos.nl> 18/5/1996.
+ *	Added trap out of bad frames.
+ *		Alan Cox <alan@cymru.net> 17/11/1996
  *
  *
  * Masquerading functionality
@@ -102,6 +104,7 @@
 #include <net/udp.h>
 #include <net/sock.h>
 #include <net/icmp.h>
+#include <net/netlink.h>
 #include <linux/firewall.h>
 #include <linux/ip_fw.h>
 
@@ -567,6 +570,20 @@
 		else
 			answer = FW_BLOCK;
 
+#ifdef CONFIG_IP_FIREWALL_NETLINK
+		if(answer == FW_REJECT || answer == FW_BLOCK)
+		{
+			struct sk_buff *skb=alloc_skb(128, GFP_ATOMIC);
+			if(skb)
+			{
+				int len=min(128,ntohs(ip->tot_len));
+				skb_put(skb,len);
+				memcpy(skb->data,ip,len);
+				if(netlink_post(NETLINK_FIREWALL, skb))
+					kfree_skb(skb, FREE_WRITE);
+			}
+		}
+#endif		
 		return answer;
 	} else
 		/* we're doing accounting, always ok */
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/ip_sockglue.c linux/net/ipv4/ip_sockglue.c
--- v2.1.10/linux/net/ipv4/ip_sockglue.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/ip_sockglue.c	Mon Nov 18 10:36:06 1996
@@ -495,8 +495,11 @@
 					}
 				}
 				err = put_user(opt->optlen, optlen);
-				if (!err)
-					err = copy_to_user(optval, opt->__data, opt->optlen);
+				if (!err) 
+				{
+					if(copy_to_user(optval, opt->__data, opt->optlen))
+					    err = -EFAULT;
+				}
 				return err; 
 			}
 			return 0;
@@ -520,7 +523,11 @@
   			len=strlen(sk->ip_mc_name);
   			err = put_user(len, optlen);
 			if (!err)
+			{
 				err = copy_to_user((void *)optval,sk->ip_mc_name, len);
+				if (err)
+				    err = -EFAULT;
+			}
 			return err;
 #endif
 		default:
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/ipmr.c linux/net/ipv4/ipmr.c
--- v2.1.10/linux/net/ipv4/ipmr.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/ipmr.c	Mon Nov 18 11:31:35 1996
@@ -551,14 +551,16 @@
 		 *	Control PIM assert.
 		 */
 		case MRT_ASSERT:
+		{
+			int v;
 			if(optlen!=sizeof(int))
 				return -EINVAL;
-
-			/* BUG BUG this is wrong IMHO -AK. */ 
-			if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
-				return err;
-			mroute_do_pim= (optval)?1:0;
+			
+			if(get_user(v,(int *)optval))
+				return -EFAULT;
+			mroute_do_pim=(v)?1:0;
 			return 0;
+		}
 		/*
 		 *	Spurious command, or MRT_VERSION which you cannot
 		 *	set.
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/packet.c linux/net/ipv4/packet.c
--- v2.1.10/linux/net/ipv4/packet.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/packet.c	Mon Nov 18 11:31:35 1996
@@ -282,7 +282,7 @@
  *	Bind a packet socket to a device
  */
 
-static int packet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+static int packet_bind(struct sock *sk, struct sockaddr *uaddr, size_t addr_len)
 {
 	char name[15];
 	struct device *dev;
@@ -410,9 +410,6 @@
 	struct sockaddr_pkt *saddr=(struct sockaddr_pkt *)msg->msg_name;
 	int err;
 
-	if (sk->shutdown & RCV_SHUTDOWN) 
-		return(0);
-		
 	/*
 	 *	If there is no protocol hook then the device is down.
 	 */
@@ -450,8 +447,13 @@
 	 *	user program they can ask the device for its MTU anyway.
 	 */
 	 
-	copied = min(len, skb->len);
-
+	copied = skb->len;
+	if(copied>len)
+	{
+		copied=len;
+		msg->msg_flags|=MSG_TRUNC;
+	}
+	
 	/* We can't use skb_copy_datagram here */
 	err = memcpy_toiovec(msg->msg_iov, skb->data, copied);
 	if (err)
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/rarp.c linux/net/ipv4/rarp.c
--- v2.1.10/linux/net/ipv4/rarp.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/rarp.c	Mon Nov 18 10:36:06 1996
@@ -436,7 +436,7 @@
  *        Copy the information back
  */
   
-	return copy_to_user(req, &r, sizeof(r));
+	return copy_to_user(req, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
 
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.1.10/linux/net/ipv4/raw.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/raw.c	Mon Nov 18 11:31:36 1996
@@ -350,7 +350,12 @@
 	if(skb==NULL)
  		return err;
 
-	copied = min(len, skb->len);
+	copied=skb->len;
+	if(copied>len)
+	{
+		copied=len;
+		msg->msg_flags|=MSG_TRUNC;
+	}
 	
 	err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	sk->stamp=skb->stamp;
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- v2.1.10/linux/net/ipv4/sysctl_net_ipv4.c	Sun Nov 10 20:12:29 1996
+++ linux/net/ipv4/sysctl_net_ipv4.c	Mon Nov 18 10:36:07 1996
@@ -31,7 +31,9 @@
 extern int sysctl_arp_confirm_interval;
 extern int sysctl_arp_confirm_timeout;
 
-extern int sysctl_tcp_vegas_cong_avoidance;
+extern int sysctl_tcp_cong_avoidance;
+extern int tcp_sysctl_congavoid(ctl_table *ctl, int write, struct file * filp,
+				void *buffer, size_t *lenp);
 
 ctl_table ipv4_table[] = {
         {NET_IPV4_ARP_RES_TIME, "arp_res_time",
@@ -58,7 +60,7 @@
 #endif
 
 	{NET_IPV4_TCP_VEGAS_CONG_AVOID, "tcp_vegas_cong_avoid",
-	 &sysctl_tcp_vegas_cong_avoidance, sizeof(int), 0644,
-	 NULL, &proc_dointvec },
+	 &sysctl_tcp_cong_avoidance, sizeof(int), 0644,
+	 NULL, &tcp_sysctl_congavoid },
 	{0}
 };
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.1.10/linux/net/ipv4/tcp.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/tcp.c	Mon Nov 18 11:31:36 1996
@@ -204,8 +204,7 @@
  *
  *		Rewrite output state machine to use a single queue.
  *		Speed up input assembly algorithm.
- *		RFC1323 - PAWS and window scaling. PAWS is required for IPv6 so we
- *		could do with it working on IPv4
+ *		RFC1323 - PAWS and window scaling. 
  *		User settable/learned rtt/max window/mtu
  *
  *		Change the fundamental structure to a single send queue maintained
@@ -905,19 +904,20 @@
 				    sk->mss - tcp_size > 0 &&
 				    skb->end_seq < tp->snd_una + tp->snd_wnd) 
 				{
+					int tcopy;
 					
-					copy = tcp_append_tail(sk, skb, from,
+					tcopy = tcp_append_tail(sk, skb, from,
 							       tcp_size,
 							       seglen);
-					if (copy == -1)
+					if (tcopy == -1)
 					{
 						return -EFAULT;
 					}
 					
-					from += copy;
-					copied += copy;
-					len -= copy;
-					seglen -= copy;
+					from += tcopy;
+					copied += tcopy;
+					len -= tcopy;
+					seglen -= tcopy;
 					
 					/*
 					 *	FIXME: if we're nagling we
@@ -1092,7 +1092,7 @@
 			struct msghdr *msg, int len, int flags, 
 			int *addr_len)
 {
-	int err; 
+	int err=0; 
 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
 
 	/*
@@ -1125,7 +1125,12 @@
 		char c = sk->urg_data;
 		if (!(flags & MSG_PEEK))
 			sk->urg_data = URG_READ;
-		err = memcpy_toiovec(msg->msg_iov, &c, 1);
+			
+		if(len>0)
+			err = memcpy_toiovec(msg->msg_iov, &c, 1);
+		else
+			msg->msg_flags|=MSG_TRUNC;
+			
 		if(msg->msg_name)
 		{
 			tp->af_specific->addr2sockaddr(sk, (struct sockaddr *)
@@ -1133,7 +1138,10 @@
 		}
 		if(addr_len)
 			*addr_len= tp->af_specific->sockaddr_len;
-
+		/* 
+		 *	Read urgent data
+		 */
+		msg->msg_flags|=MSG_OOB;
 		release_sock(sk);
 		return err ? -EFAULT : 1;
 	}
@@ -1214,10 +1222,7 @@
 	volatile u32 *seq;	/* So gcc doesn't overoptimise */
 	unsigned long used;
 	int err = 0; 
-
-	/*
-	 *	This error should be checked.
-	 */
+	int target = 1;		/* Read at least this may bytes */
 
 	if (sk->state == TCP_LISTEN)
 		return -ENOTCONN;
@@ -1239,6 +1244,13 @@
 	seq = &sk->copied_seq;
 	if (flags & MSG_PEEK)
 		seq = &peek_seq;
+		
+	/*
+	 *	Handle the POSIX bogosity MSG_WAITALL
+	 */
+	 
+	if (flags & MSG_WAITALL)
+		target=len;
 
 	add_wait_queue(sk->sleep, &wait);
 	lock_sock(sk);
@@ -1256,14 +1268,13 @@
 
 		/*
 		 * We need to check signals first, to get correct SIGURG
-		 * handling.
+		 * handling. FIXME: Need to check this doesnt impact 1003.1g
+		 * and move it down to the bottom of the loop
 		 */
 		if (current->signal & ~current->blocked) {
 			if (copied)
 				break;
 			copied = -ERESTARTSYS;
-			if (nonblock)
-				copied = -EAGAIN;
 			break;
 		}
 
@@ -1300,7 +1311,7 @@
 		}
 		while (skb != (struct sk_buff *)&sk->receive_queue);
 
-		if (copied)
+		if (copied >= target)
 			break;
 
 		if (sk->err && !(flags&MSG_PEEK))
@@ -1393,11 +1404,6 @@
 		 *	a crash when cleanup_rbuf() gets called.
 		 */
 
-		/*
-		 *	FIXME: should break out of the loop early when an
-		 *	error occurs
-		 */
-		
 		err = memcpy_toiovec(msg->msg_iov, ((unsigned char *)skb->h.th) + skb->h.th->doff*4 + offset, used);
 		
 		if (err)
@@ -1427,7 +1433,8 @@
 			continue;
 
 		/*
-		 *	Process the FIN.
+		 *	Process the FIN. We may also need to handle PSH
+		 *	here and make it break out of MSG_WAITALL
 		 */
 
 		if (skb->h.th->fin)
@@ -1847,104 +1854,6 @@
 	{
 		tcp_dec_slow_timer(TCP_SLT_KEEPALIVE);
 	}
-}
-
-
-/*
- *      This function returns the amount that we can raise the
- *      usable window based on the following constraints
- *  
- *	1. The window can never be shrunk once it is offered (RFC 793)
- *	2. We limit memory per socket
- */
-
-
-unsigned short tcp_select_window(struct sock *sk)
-{
-	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
-	long free_space = sock_rspace(sk);
-	long window;
-	long cur_win;
-	long usable;
-	int mss = sk->mss;
-	
-	if (sk->window_clamp)
-	{
-		free_space = min(sk->window_clamp, free_space);
-		mss = min(sk->window_clamp, mss);
-	}
-	
-	/*
-	 * compute the actual window i.e.
-	 * old_window - received_bytes_on_that_win
-	 */
-
-	cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd);
-	window  = tp->rcv_wnd;
-	
-	if ( cur_win < 0 )
-	{
-		cur_win = 0;
-		printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n",
-		       tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup);
-	}
-
-	/*
-	 * RFC 1122:
-	 * "the suggested [SWS] avoidance algoritm for the receiver is to keep
-	 *  RECV.NEXT + RCV.WIN fixed until:
-	 *  RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
-	 *
-	 * i.e. don't raise the right edge of the window until you can't raise
-	 * it MSS bytes
-	 */
-
-	/*
-	 * It would be a good idea if it didn't break header prediction.
-	 * and BSD made the header predition standard...
-	 * It expects the same value in the header i.e. th->window to be
-	 * constant
-	 */
-
-	usable = free_space - cur_win;
-	if (usable < 0)
-	{
-		usable = 0;
-	}
-
-	if ( window <  usable )
-	{
-		/*
-		 *	Window is not blocking the sender
-		 *	and we have enought free space for it
-		 */
-
-		if (cur_win > (sk->mss << 1))
-			goto out;
-	}
-
-       	
-	if (window >= usable)
-	{
-		/*
-		 *	We are offering too much, cut it down... 
-		 *	but don't shrink the window
-		 */
-		
-		window = max(usable, cur_win);
-	}
-	else
-	{	
-		if ((usable - window) >= mss)
-		{
-			window += mss;
-		}
-	}
-
-  out:
-	tp->rcv_wnd = window;
-	tp->rcv_wup = tp->rcv_nxt;
-	return window;
 }
 
 /*
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.1.10/linux/net/ipv4/tcp_input.c	Fri Nov 15 23:49:11 1996
+++ linux/net/ipv4/tcp_input.c	Mon Nov 18 10:44:23 1996
@@ -45,12 +45,24 @@
  */
 
 #include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/sysctl.h>
 #include <net/tcp.h>
 
 
-/*
- *	Policy code extracted so it's now seperate
- */
+
+typedef void			(*tcp_sys_cong_ctl_t)(struct sock *sk,
+						      u32 seq, u32 ack,
+						      u32 seq_rtt);
+
+static void tcp_cong_avoid_vanj(struct sock *sk, u32 seq, u32 ack,
+				u32 seq_rtt);
+static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
+				 u32 seq_rtt);
+
+int sysctl_tcp_cong_avoidance = 0;
+
+static tcp_sys_cong_ctl_t tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj;
 
 /*
  *	Called each time to estimate the delayed ack timeout. This is
@@ -60,7 +72,7 @@
  *	The estimated value is changing to fast
  */
  
-extern __inline__ void tcp_delack_estimator(struct tcp_opt *tp)
+static void tcp_delack_estimator(struct tcp_opt *tp)
 {
 	int m;
 
@@ -355,8 +367,6 @@
 	
 }
 
-int sysctl_tcp_vegas_cong_avoidance = 1;
-
 /*
  *      TCP slow start and congestion avoidance in two flavors:
  *      RFC 1122 and TCP Vegas.
@@ -364,7 +374,7 @@
  *      This is a /proc/sys configurable option. 
  */
 
-#define SHIFT_FACTOR 12
+#define SHIFT_FACTOR 16
 
 static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
 				 u32 seq_rtt)
@@ -380,9 +390,11 @@
 	 *	to have improved several things over the initial spec.
 	 */
 
-	u32 Actual, Expected;
-	u32 snt_bytes;
 	struct tcp_opt * tp;
+	unsigned int Actual, Expected;
+	unsigned int inv_rtt, inv_basertt; 
+	u32 snt_bytes;
+	
 
 	tp = &(sk->tp_pinfo.af_tcp);
 
@@ -393,8 +405,7 @@
 		tp->basertt = min(seq_rtt, tp->basertt);
 	else
 		tp->basertt = seq_rtt;
-		
-		
+
 	/*
 	 * 
 	 *	Actual	 = throughput for this segment.
@@ -403,14 +414,13 @@
 	 */
 
 	snt_bytes = (ack - seq) << SHIFT_FACTOR;
-		
-	Actual =  snt_bytes / seq_rtt;
-	Expected = ((tp->snd_nxt - tp->snd_una) << SHIFT_FACTOR) / tp->basertt;
+	inv_rtt = (1 << SHIFT_FACTOR) / seq_rtt;
+       
+	Actual =  snt_bytes * inv_rtt;
+
+	inv_basertt = (1 << SHIFT_FACTOR) / tp->basertt;
+	Expected = ((tp->snd_nxt - tp->snd_una) << SHIFT_FACTOR) * inv_basertt;
 
-/*		
-	printk(KERN_DEBUG "A:%x E:%x rtt:%x srtt:%x win: %d\n", 
-	       Actual, Expected, seq_rtt, tp->srtt, sk->cong_window);
-      */
 	/*
 	 *      Slow Start
 	 */
@@ -418,23 +428,20 @@
 	if (sk->cong_window < sk->ssthresh &&
 	    (seq == tp->snd_nxt ||
 	      (((Expected - Actual) <=
-		((TCP_VEGAS_GAMMA << SHIFT_FACTOR) * sk->mss / tp->basertt))
+		((TCP_VEGAS_GAMMA << SHIFT_FACTOR) * sk->mss * inv_basertt))
 	       )
 	     ))
 	{
-			
 		/*
 		 * "Vegas allows exponential growth only every other
 		 *  RTT"
 		 */
 			
-		if (sk->cong_count || sk->cong_window <= 2)
+		if (!(sk->cong_count++))
 		{
 			sk->cong_window++;
 			sk->cong_count = 0;
 		}
-		else
-			sk->cong_count++;
 	}
 	else 
 	{
@@ -443,39 +450,32 @@
 		 */
 			
 		if (Expected - Actual <=
-		    ((TCP_VEGAS_ALPHA << SHIFT_FACTOR) * sk->mss / tp->basertt))
+		    ((TCP_VEGAS_ALPHA << SHIFT_FACTOR) * sk->mss * inv_basertt))
 		{
 			/* Increase Linearly */
 				
-			if (sk->cong_count >= sk->cong_window)
+			if (sk->cong_count++ >= sk->cong_window)
 			{
 				sk->cong_window++;
 				sk->cong_count = 0;
 			}
-			else
-				sk->cong_count++;
 		}
 			
 		if (Expected - Actual >=
-		    ((TCP_VEGAS_BETA << SHIFT_FACTOR) * sk->mss / tp->basertt))
+		    ((TCP_VEGAS_BETA << SHIFT_FACTOR) * sk->mss * inv_basertt))
 		{
 			/* Decrease Linearly */
 				
-			if (sk->cong_count >= sk->cong_window)
+			if (sk->cong_count++ >= sk->cong_window)
 			{
 				sk->cong_window--;
 				sk->cong_count = 0;
 			}
-			else
-				sk->cong_count++;
-				
-				
+			
 			/* Never less than 2 segments */
 			if (sk->cong_window < 2)
 				sk->cong_window = 2;
 		}
-
-
 	}
 }
 
@@ -520,6 +520,92 @@
 #define FLAG_DATA		0x01
 #define FLAG_WIN_UPDATE		0x02
 #define FLAG_DATA_ACKED		0x04
+
+static int tcp_clean_rtx_queue(struct sock *sk, __u32 ack, __u32 *seq,
+			       __u32 *seq_rtt)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	struct sk_buff *skb;
+	unsigned long now = jiffies;
+	int acked = 0;
+	
+	while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head))
+	{
+
+#ifdef TCP_DEBUG
+		/* Check for a bug. */
+
+		if (skb->next != (struct sk_buff*) &sk->write_queue &&
+		    after(skb->end_seq, skb->next->seq)) 
+			printk("INET: tcp_input.c: *** "
+			       "bug send_list out of order.\n");
+#endif								
+		/*
+		 *	If our packet is before the ack sequence we can
+		 *	discard it as it's confirmed to have arrived the 
+		 *	other end.
+		 */
+		 
+		if (after(skb->end_seq, ack))
+			break;
+		
+		if (sk->debug)
+		{
+			printk(KERN_DEBUG "removing seg %x-%x from "
+			       "retransmit queue\n", skb->seq, skb->end_seq);
+		}
+		
+		acked = FLAG_DATA_ACKED;
+		
+		atomic_dec(&sk->packets_out);
+
+		*seq = skb->seq;
+		*seq_rtt = now - skb->when;
+				
+		skb_unlink(skb);		
+		skb->free = 1;
+		
+		kfree_skb(skb, FREE_WRITE);
+	}
+
+	if (acked && !sk->dead)
+	{
+		tp->retrans_head = NULL;
+		sk->write_space(sk);
+	}
+	
+	return acked;
+}
+
+static void tcp_ack_probe(struct sock *sk, __u32 ack)
+{
+	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+	
+	/*
+	 *	Our probe was answered
+	 */
+	tp->probes_out = 0;
+	
+	/*
+	 *	Was it a usable window open ?
+	 */
+	
+	/* should always be non-null */
+	if (tp->send_head != NULL &&
+	    !before (ack + tp->snd_wnd, tp->send_head->end_seq))
+	{
+		tp->backoff = 0;
+		tp->pending = 0;
+		
+		tcp_clear_xmit_timer(sk, TIME_PROBE0);
+		
+	}
+	else
+	{
+		tcp_reset_xmit_timer(sk, TIME_PROBE0,
+				     min(tp->rto << tp->backoff, 120*HZ));
+	}
+}
  
 /*
  *	This routine deals with incoming acks, but not outgoing ones.
@@ -603,85 +689,18 @@
 	 *	it needs to be for normal retransmission.
 	 */
 
-	if (tp->pending == TIME_PROBE0) 
+	if (tp->pending == TIME_PROBE0)
 	{
-		tp->probes_out = 0;	/* Our probe was answered */
-		
-		/*
-		 *	Was it a usable window open ?
-		 */
-		 
-		/* should always be non-null */
-  		if (tp->send_head != NULL &&
-		    !before (ack + tp->snd_wnd, tp->send_head->end_seq))
-		{
-			tp->backoff = 0;
-			tp->pending = 0;
-
-                        tcp_clear_xmit_timer(sk, TIME_PROBE0);
-
-		}
-                else
-		{
-                        tcp_reset_xmit_timer(sk, TIME_PROBE0, 
-					     min(tp->rto << tp->backoff, 
-						 120*HZ));
-		}
+		tcp_ack_probe(sk, ack);
 	}
 
 	/* 
 	 *	See if we can take anything off of the retransmit queue.
 	 */
-   
-	start_bh_atomic();
 
-	while(((skb=skb_peek(&sk->write_queue)) != NULL) &&
-	      (skb != tp->send_head))
-	{
-		/* Check for a bug. */
+	if (tcp_clean_rtx_queue(sk, ack, &seq, &seq_rtt))
+		flag |= FLAG_DATA_ACKED;
 
-		if (skb->next != (struct sk_buff*) &sk->write_queue &&
-		    after(skb->end_seq, skb->next->seq)) 
-			printk("INET: tcp_input.c: *** "
-			       "bug send_list out of order.\n");
-								
-		/*
-		 *	If our packet is before the ack sequence we can
-		 *	discard it as it's confirmed to have arrived the 
-		 *	other end.
-		 */
-		 
-		if (!after(skb->end_seq, ack)) 
-		{
-			if (sk->debug)
-			{
-				printk(KERN_DEBUG "removing seg %x-%x from "
-				       "retransmit queue\n",
-				       skb->seq, skb->end_seq);
-			}
-			
-			tp->retrans_head = NULL;
-						
-			flag |= FLAG_DATA_ACKED;
-			seq = skb->seq;
-			seq_rtt = jiffies - skb->when;
-			
-			skb_unlink(skb);
-			atomic_dec(&sk->packets_out);
-			skb->free = 1;
-
-			kfree_skb(skb, FREE_WRITE);
-			
-			if (!sk->dead)
-				sk->write_space(sk);
-		}
-		else
-		{
-			break;
-		}
-	}
-
-	end_bh_atomic();
 
 	/* 
 	 * if we where retransmiting don't count rtt estimate
@@ -709,18 +728,13 @@
 		if (flag & FLAG_DATA_ACKED)
 		{
 			tcp_rtt_estimator(tp, seq_rtt);
-			if (sysctl_tcp_vegas_cong_avoidance)
-			{
-				tcp_cong_avoid_vegas(sk, seq, ack, seq_rtt);
-			}
-			else
-			{
-				tcp_cong_avoid_vanj(sk, seq, ack, seq_rtt);
-			}
+			
+			(*tcp_sys_cong_ctl_f)(sk, seq, ack, seq_rtt);
 		}
 	}
 
 			
+#ifdef TCP_DEBUG
 
 	/* Sanity check out packets_out counter */
 	if (skb_queue_len(&sk->write_queue) == 0 || 
@@ -733,7 +747,7 @@
                         sk->packets_out = 0;
                 }
 	}
-
+#endif
 
 	if (sk->packets_out)
 	{
@@ -773,12 +787,6 @@
 	tcp_fast_retrans(sk, ack, (flag & (FLAG_DATA|FLAG_WIN_UPDATE)));
 
 
-	/*
-	 * Maybe we can take some stuff off of the write queue,
-	 * and put it onto the xmit queue.
-	 */
-
-
 	return 1;
 
 uninteresting_ack:
@@ -895,7 +903,7 @@
 	 * out_of_order queue into the receive_queue
 	 */
 
-static __inline__ void  tcp_ofo_queue(struct sock *sk)
+static void  tcp_ofo_queue(struct sock *sk)
 {
 	struct sk_buff * skb;
 	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
@@ -930,7 +938,7 @@
 	}
 }
 
-static __inline__ void	tcp_data_queue(struct sock *sk, struct sk_buff *skb)
+static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
 {
 	struct sk_buff * skb1;
 	struct tcp_opt *tp=&(sk->tp_pinfo.af_tcp);
@@ -1255,7 +1263,7 @@
 }
 
 
-static __inline__ void prune_queue(struct sock *sk)
+static void prune_queue(struct sock *sk)
 {
 	struct sk_buff * skb;
 
@@ -1832,6 +1840,32 @@
 
 	kfree_skb(skb, FREE_READ);
 	return 0;
+}
+
+int tcp_sysctl_congavoid(ctl_table *ctl, int write, struct file * filp,
+			 void *buffer, size_t *lenp)
+{
+	int val = sysctl_tcp_cong_avoidance;
+	int retv;
+	
+	retv  = proc_dointvec(ctl, write, filp, buffer, lenp);
+	
+	if (write)
+	{
+		switch (sysctl_tcp_cong_avoidance) {
+			case 0:
+				tcp_sys_cong_ctl_f = &tcp_cong_avoid_vanj;
+				break;
+			case 1:
+				tcp_sys_cong_ctl_f = &tcp_cong_avoid_vegas;
+				break;
+			default:
+				retv = -EINVAL;
+				sysctl_tcp_cong_avoidance = val;
+		}
+	}
+	
+	return retv;
 }
 
 /*
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c
--- v2.1.10/linux/net/ipv4/tcp_ipv4.c	Tue Nov 12 15:56:16 1996
+++ linux/net/ipv4/tcp_ipv4.c	Mon Nov 18 17:01:15 1996
@@ -127,7 +127,7 @@
  *	This will initiate an outgoing connection. 
  */
  
-int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, size_t addr_len)
 {
 	struct sk_buff *buff;
 	struct sk_buff *skb1;
@@ -199,7 +199,7 @@
 	if (buff == NULL) 
 	{
 		release_sock(sk);
-		return(-ENOMEM);
+		return(-ENOBUFS);
 	}
 
 	buff->sk = sk;
@@ -250,21 +250,6 @@
 	else
 		sk->mtu = dev->mtu;
 	
-#ifdef CONFIG_SKIP
-
-	/*
-	 *	SKIP devices set their MTU to 65535. This is so they can take packets
-	 *	unfragmented to security process then fragment. They could lie to the
-	 *	TCP layer about a suitable MTU, but its easier to let skip sort it out
-	 *	simply because the final package we want unfragmented is going to be
-	 *
-	 *	[IPHDR][IPSP][Security data][Modified TCP data][Security data]
-	 */
-
-	if(skip_pick_mtu!=NULL)		/* If SKIP is loaded.. */
-		sk->mtu=skip_pick_mtu(sk->mtu,dev);
-#endif
-
 	if(sk->mtu < 64)
 		sk->mtu = 64;	/* Sanity limit */
 
@@ -370,12 +355,15 @@
  */
 
 void tcp_v4_err(int type, int code, unsigned char *header, __u32 info,
-		__u32 daddr, __u32 saddr, struct inet_protocol *protocol)
+		__u32 daddr, __u32 saddr, struct inet_protocol *protocol, int len)
 {
 	struct tcphdr *th = (struct tcphdr *)header;
 	struct tcp_opt *tp;
 	struct sock *sk;
 
+	if(len<8)	/* We use the first 8 bytes only */
+		return;
+		
 	th =(struct tcphdr *)header;
 	sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr, 0, 0);
 
@@ -410,10 +398,7 @@
 	if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
 	{
 		struct rtable * rt;
-		/*
-		 * Ugly trick to pass MTU to protocol layer.
-		 * Really we should add argument "info" to error handler.
-		 */
+
 		unsigned short new_mtu = info;
 
 		if ((rt = sk->ip_route_cache) != NULL)
@@ -897,7 +882,7 @@
 	 */
 	newsk->opt = af_req->opt;
 	rt = ip_rt_route(newsk->opt && newsk->opt->srr ? newsk->opt->faddr : 
-			 newsk->saddr, 0);
+			 newsk->daddr, 0);
 
 	newsk->ip_route_cache = rt;
 	
@@ -918,7 +903,7 @@
 		newsk->mtu = 64;
 	}
 
-	snd_mss -= sizeof(struct iphdr) - sizeof(struct tcphdr);
+	snd_mss -= sizeof(struct iphdr) + sizeof(struct tcphdr);
 
 	if (sk->user_mss)
 	{
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.1.10/linux/net/ipv4/tcp_output.c	Tue Nov 12 15:56:16 1996
+++ linux/net/ipv4/tcp_output.c	Mon Nov 18 13:43:01 1996
@@ -361,7 +361,9 @@
 void tcp_write_xmit(struct sock *sk)
 {
 	struct sk_buff *skb;
-	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;	
+	u16 rcv_wnd;
+	int sent_pkts = 0;
 
 	/*
 	 *	The bytes will have to remain here. In time closedown will
@@ -382,8 +384,14 @@
 
 	start_bh_atomic();
 
+	rcv_wnd = htons(tcp_select_window(sk));
+	
 	while((skb = tp->send_head) && tcp_snd_test(sk, skb))
 	{
+		struct tcphdr *th;
+		struct sk_buff *buff;
+		int size;
+
 		IS_SKB(skb);
 				
 		/*
@@ -393,21 +401,18 @@
 		if (!after(skb->end_seq, tp->snd_una)) 
 		{
 			tcp_wrxmit_prob(sk, skb);
+			continue;
 		} 
-		else
-		{
-			struct tcphdr *th;
-			struct sk_buff *buff;
-			int size;
-
-			/* 
-			 * Advance the send_head
-			 * This one is going out.
-			 */
 
-			update_send_head(sk);
 
-			atomic_inc(&sk->packets_out);
+		/* 
+		 * Advance the send_head
+		 * This one is going out.
+		 */
+
+		update_send_head(sk);
+
+		atomic_inc(&sk->packets_out);
 
 
 /*
@@ -418,45 +423,147 @@
  * on the write queue.
  */
 
-			th = skb->h.th;
-			size = skb->len - (((unsigned char *) th) - skb->data);
+		th = skb->h.th;
+		size = skb->len - (((unsigned char *) th) - skb->data);
 
-			if (size - (th->doff << 2) > sk->mss)
-			{
-				if (tcp_wrxmit_frag(sk, skb, size))
-					break;
-			}
-			
-			th->ack_seq = htonl(tp->rcv_nxt);
-			th->window = htons(tcp_select_window(sk));
-
-			tp->af_specific->send_check(sk, th, size, skb);
-
-			if (before(skb->end_seq, tp->snd_nxt)) 
-				printk(KERN_DEBUG "tcp_write_xmit:"
-				       " sending already sent seq\n");
-			else
-				tp->snd_nxt = skb->end_seq;
-			
-			clear_delayed_acks(sk);
-			
-			skb->when = jiffies;
-
-			buff = skb_clone(skb, GFP_ATOMIC);
-			atomic_add(buff->truesize, &sk->wmem_alloc);
-
-			tp->af_specific->queue_xmit(sk, skb->dev, buff, 1);
-			
-			if (!tcp_timer_is_set(sk, TIME_RETRANS))
-			{
-				tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
-			}
+		if (size - (th->doff << 2) > sk->mss)
+		{
+			if (tcp_wrxmit_frag(sk, skb, size))
+				break;
 		}
+
+		th->ack_seq = htonl(tp->rcv_nxt);
+		th->window = rcv_wnd;
+
+		tp->af_specific->send_check(sk, th, size, skb);
+
+#ifdef TCP_DEBUG
+		if (before(skb->end_seq, tp->snd_nxt))
+			printk(KERN_DEBUG "tcp_write_xmit:"
+			       " sending already sent seq\n");
+#endif		
+
+		tp->snd_nxt = skb->end_seq;
+
+		skb->when = jiffies;
+		clear_delayed_acks(sk);
+
+		buff = skb_clone(skb, GFP_ATOMIC);
+		atomic_add(buff->truesize, &sk->wmem_alloc);
+
+		sent_pkts = 1;
+		tp->af_specific->queue_xmit(sk, skb->dev, buff, 1);
+
+	}
+	
+	if (sent_pkts && !tcp_timer_is_set(sk, TIME_RETRANS))
+	{
+		tcp_reset_xmit_timer(sk, TIME_RETRANS, tp->rto);
 	}
 
 	end_bh_atomic();
 }
 
+
+
+/*
+ *      This function returns the amount that we can raise the
+ *      usable window based on the following constraints
+ *  
+ *	1. The window can never be shrunk once it is offered (RFC 793)
+ *	2. We limit memory per socket
+ */
+
+
+unsigned short tcp_select_window(struct sock *sk)
+{
+	struct tcp_opt *tp = &sk->tp_pinfo.af_tcp;
+	int mss = sk->mss;
+	long free_space = sock_rspace(sk);
+	long window;
+	long cur_win;
+	long usable;
+
+	
+	if (sk->window_clamp)
+	{
+		free_space = min(sk->window_clamp, free_space);
+		mss = min(sk->window_clamp, mss);
+	}
+	
+	/*
+	 * compute the actual window i.e.
+	 * old_window - received_bytes_on_that_win
+	 */
+
+	cur_win = tp->rcv_wup - (tp->rcv_nxt - tp->rcv_wnd);
+	window  = tp->rcv_wnd;
+	
+	if ( cur_win < 0 )
+	{
+		cur_win = 0;
+		printk(KERN_DEBUG "TSW: win < 0 w=%d 1=%u 2=%u\n",
+		       tp->rcv_wnd, tp->rcv_nxt, tp->rcv_wup);
+	}
+
+	/*
+	 * RFC 1122:
+	 * "the suggested [SWS] avoidance algoritm for the receiver is to keep
+	 *  RECV.NEXT + RCV.WIN fixed until:
+	 *  RCV.BUFF - RCV.USER - RCV.WINDOW >= min(1/2 RCV.BUFF, MSS)"
+	 *
+	 * i.e. don't raise the right edge of the window until you can't raise
+	 * it MSS bytes
+	 */
+
+	/*
+	 * It would be a good idea if it didn't break header prediction.
+	 * and BSD made the header predition standard...
+	 * It expects the same value in the header i.e. th->window to be
+	 * constant
+	 */
+
+	usable = free_space - cur_win;
+	if (usable < 0)
+	{
+		usable = 0;
+	}
+
+	if ( window <  usable )
+	{
+		/*
+		 *	Window is not blocking the sender
+		 *	and we have enought free space for it
+		 */
+
+		if (cur_win > (sk->mss << 1))
+			goto out;
+	}
+
+       	
+	if (window >= usable)
+	{
+		/*
+		 *	We are offering too much, cut it down... 
+		 *	but don't shrink the window
+		 */
+		
+		window = max(usable, cur_win);
+	}
+	else
+	{	
+		if ((usable - window) >= mss)
+		{
+			window += mss;
+		}
+	}
+
+  out:
+	tp->rcv_wnd = window;
+	tp->rcv_wup = tp->rcv_nxt;
+	return window;
+}
+
 static int tcp_retrans_try_collapse(struct sock *sk, struct sk_buff *skb)
 {
 	struct tcphdr *th1, *th2;
@@ -546,8 +653,10 @@
 	
 	while ((skb = tp->retrans_head) != NULL)
 	{
+		struct sk_buff *buff;
 		struct tcphdr *th;
-		u32 tcp_size;
+		int tcp_size;			
+		int size;
 
 		IS_SKB(skb);
 		
@@ -582,37 +691,35 @@
 			tcp_retrans_try_collapse(sk, skb);
 		}	       		
 
-		if (tp->af_specific->rebuild_header(sk, skb) == 0) 
-		{
-			struct sk_buff *buff;
-			int size;
-
-			if (sk->debug)
-				printk("retransmit sending\n");
-
-			/*
-			 *	update ack and window
-			 */
-			th->ack_seq = htonl(tp->rcv_nxt);
-			th->window = ntohs(tcp_select_window(sk));
-
-			size = skb->tail - (unsigned char *) th;
-			tp->af_specific->send_check(sk, th, size, skb);
-
-			skb->when = jiffies;
-			buff = skb_clone(skb, GFP_ATOMIC);
-			atomic_add(buff->truesize, &sk->wmem_alloc);
-
-			clear_delayed_acks(sk);
-
-			tp->af_specific->queue_xmit(sk, skb->dev, buff, 1);
-		}
-		else
+		if (tp->af_specific->rebuild_header(sk, skb)) 
 		{
+#ifdef TCP_DEBUG
 			printk(KERN_DEBUG "tcp_do_rebuild_header failed\n");
+#endif
 			break;
 		}
 
+		if (sk->debug)
+			printk("retransmit sending\n");
+
+		/*
+		 *	update ack and window
+		 */
+
+		th->ack_seq = htonl(tp->rcv_nxt);
+		th->window = ntohs(tcp_select_window(sk));
+
+		size = skb->tail - (unsigned char *) th;
+		tp->af_specific->send_check(sk, th, size, skb);
+		
+		skb->when = jiffies;
+		buff = skb_clone(skb, GFP_ATOMIC);
+		atomic_add(buff->truesize, &sk->wmem_alloc);
+		
+		clear_delayed_acks(sk);
+		
+		tp->af_specific->queue_xmit(sk, skb->dev, buff, 1);
+		
 		/*
 		 *	Count retransmissions
 		 */
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.1.10/linux/net/ipv4/tcp_timer.c	Tue Nov 12 15:56:16 1996
+++ linux/net/ipv4/tcp_timer.c	Mon Nov 18 11:10:14 1996
@@ -185,8 +185,9 @@
 			sk->err=sk->err_soft;
 		else
 			sk->err=ETIMEDOUT;
-
+#ifdef TCP_DEBUG
 		printk(KERN_DEBUG "syn timeout\n");
+#endif
 
 		sk->error_report(sk);
 		tcp_clear_xmit_timers(sk);
@@ -475,17 +476,14 @@
 
 				req = tp->syn_wait_queue;
 
-				while (req && tp->syn_wait_queue)
-				{
+				do {
 					struct open_request *conn;
-
+				  
 					conn = req;
 					req = req->dl_next;
 
 					if (conn->sk)
 					{
-						if (req == tp->syn_wait_queue)
-							break;
 						continue;
 					}
 					
@@ -496,11 +494,16 @@
 					
 					if (conn->retrans >= TCP_RETR1)
 					{
+#ifdef TCP_DEBUG
 						printk(KERN_DEBUG "syn_recv: "
 						       "too many retransmits\n");
+#endif
 						(*conn->class->destructor)(conn);
 						tcp_dec_slow_timer(TCP_SLT_SYNACK);
 						kfree(conn);
+
+						if (!tp->syn_wait_queue)
+							break;
 					}
 					else
 					{
@@ -509,14 +512,16 @@
 						(*conn->class->rtx_syn_ack)(sk, conn);
 
 						conn->retrans++;
+#ifdef TCP_DEBUG
 						printk(KERN_DEBUG "syn_ack rtx %d\n", conn->retrans);
+#endif
 						timeo = min((TCP_TIMEOUT_INIT 
 							     << conn->retrans),
 							    120*HZ);
 						conn->expires = now + timeo;
 						tcp_synq_queue(tp, conn);
 					}
-				}
+				} while (req != tp->syn_wait_queue);
 			}
 			
 			sk = sk->next;
diff -u --recursive --new-file v2.1.10/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.1.10/linux/net/ipv4/udp.c	Fri Nov 15 23:49:12 1996
+++ linux/net/ipv4/udp.c	Mon Nov 18 11:31:36 1996
@@ -151,7 +151,7 @@
  */
 
 void udp_err(int type, int code, unsigned char *header, __u32 info,
-	     __u32 daddr, __u32 saddr, struct inet_protocol *protocol)
+	     __u32 daddr, __u32 saddr, struct inet_protocol *protocol, int len)
 {
 	struct udphdr *uh;
 	struct sock *sk;
@@ -159,6 +159,9 @@
 	/*
 	 *	Find the 8 bytes of post IP header ICMP included for us
 	 */  
+	 
+	if(len<sizeof(struct udphdr))
+		return;
 	
 	uh = (struct udphdr *)header;  
    
@@ -550,7 +553,13 @@
   		return er;
   
   	truesize = skb->len - sizeof(struct udphdr);
-  	copied = min(len, truesize);
+  	copied = truesize;
+  	
+  	if(len<truesize)
+  	{
+  		copied=len;
+  		msg->msg_flags|=MSG_TRUNC;
+  	}
 
   	/*
   	 *	FIXME : should use udp header size info value 
@@ -590,10 +599,25 @@
   	return(copied);
 }
 
-int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int udp_connect(struct sock *sk, struct sockaddr *uaddr, size_t addr_len)
 {
 	struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
 	struct rtable *rt;
+	
+	/*
+	 *	1003.1g - break association.
+	 */
+	 
+	if (usin->sin_family==AF_UNSPEC)
+	{
+		sk->saddr=INADDR_ANY;
+		sk->rcv_saddr=INADDR_ANY;
+		sk->daddr=INADDR_ANY;
+		sk->state = TCP_CLOSE;
+		udp_cache_zap();
+		return 0;
+	}
+	
 	if (addr_len < sizeof(*usin)) 
 	  	return(-EINVAL);
 
diff -u --recursive --new-file v2.1.10/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.1.10/linux/net/ipv6/addrconf.c	Fri Nov 15 23:49:12 1996
+++ linux/net/ipv6/addrconf.c	Mon Nov 18 10:36:07 1996
@@ -862,7 +862,7 @@
 		dev = sit_add_tunnel(ireq.addr.s6_addr32[3]);
 		
 		if (dev == NULL)
-			return -ENOMEM;
+			return -ENODEV;
 
 		return 0;
 	}
diff -u --recursive --new-file v2.1.10/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.1.10/linux/net/ipv6/af_inet6.c	Fri Nov 15 23:49:12 1996
+++ linux/net/ipv6/af_inet6.c	Mon Nov 18 11:31:36 1996
@@ -254,7 +254,7 @@
  */
 
 static int inet6_bind(struct socket *sock, struct sockaddr *uaddr,
-		      int addr_len)
+		      size_t addr_len)
 {
 	struct sockaddr_in6 *addr=(struct sockaddr_in6 *)uaddr;
 	struct sock *sk=(struct sock *)sock->data, *sk2;
@@ -271,7 +271,7 @@
 		
 	/* check this error. */
 	if (sk->state != TCP_CLOSE)
-		return(-EIO);
+		return(-EINVAL);
 
 	if(addr_len < sizeof(struct sockaddr_in6))
 		return -EINVAL;
@@ -434,7 +434,7 @@
  */
  
 static int inet6_getname(struct socket *sock, struct sockaddr *uaddr,
-		 int *uaddr_len, int peer)
+		 size_t *uaddr_len, int peer)
 {
 	struct sockaddr_in6 *sin=(struct sockaddr_in6 *)uaddr;
 	struct sock *sk;
@@ -805,7 +805,7 @@
 {
 	int i;
 
-	printk(KERN_INFO "IPv6 v0.1\n");
+	printk(KERN_INFO "IPv6 v0.1 for NET3.037\n");
 
 	sock_register(inet6_proto_ops.family, &inet6_proto_ops);
 	
diff -u --recursive --new-file v2.1.10/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c
--- v2.1.10/linux/net/ipv6/ndisc.c	Tue Nov 12 15:56:16 1996
+++ linux/net/ipv6/ndisc.c	Mon Nov 18 10:36:07 1996
@@ -15,6 +15,14 @@
  */
 
 /*
+ *	Changes:
+ *
+ *	Lars Fenneberg			:	fixed MTU setting on receipt
+ *						of an RA. 
+ *
+ */
+
+/*
  *	Interface:
  *
  *	ndisc_lookup will be called from eth.c on dev->(re)build_header
@@ -1383,7 +1391,7 @@
 				int mtu;
 				struct device *dev;
 				
-				mtu = htonl(*(__u32 *)opt+4);
+				mtu = htonl(*(__u32 *)(opt+4));
 				dev = rt->rt_nexthop->dev;
 
 				if (mtu < 576)
diff -u --recursive --new-file v2.1.10/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
--- v2.1.10/linux/net/ipv6/tcp_ipv6.c	Tue Nov 12 15:56:16 1996
+++ linux/net/ipv6/tcp_ipv6.c	Mon Nov 18 11:31:36 1996
@@ -85,7 +85,7 @@
 }
 
 static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, 
-			  int addr_len)
+			  size_t addr_len)
 {
 	struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
 	struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
diff -u --recursive --new-file v2.1.10/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
--- v2.1.10/linux/net/ipv6/udp.c	Fri Nov 15 23:49:12 1996
+++ linux/net/ipv6/udp.c	Mon Nov 18 11:31:36 1996
@@ -192,7 +192,13 @@
   		return err;
   
   	truesize = skb->tail - skb->h.raw - sizeof(struct udphdr);
-  	copied = min(len, truesize);
+  	
+  	copied=truesize;
+  	if(copied>len)
+  	{
+  		copied=len;
+  		msg->msg_flags|=MSG_TRUNC;
+  	}
 
   	/*
   	 *	FIXME : should use udp header size info value 
diff -u --recursive --new-file v2.1.10/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.1.10/linux/net/ipx/af_ipx.c	Fri Nov 15 23:49:12 1996
+++ linux/net/ipx/af_ipx.c	Mon Nov 18 11:41:14 1996
@@ -44,6 +44,8 @@
  *	Revision 0.34:	Module support. <Jim Freeman>
  *	Revision 0.35:  Checksum support. <Neil Turton>, hooked in by <Alan Cox>
  *			Handles WIN95 discovery packets <Volker Lendecke>
+ *	Revision 0.36:	Internal bump up for 2.1
+ *	Revision 0.37:	Began adding POSIXisms.
  *
  *	Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
  *	pair. Also, now usage count is managed this way
@@ -141,7 +143,7 @@
 	
 	vals.ipxcfg_auto_create_interfaces = ipxcfg_auto_create_interfaces;
 	vals.ipxcfg_auto_select_primary = ipxcfg_auto_select_primary;
-	return copy_to_user(arg, &vals, sizeof(vals));
+	return copy_to_user(arg, &vals, sizeof(vals)) ? -EFAULT : 0;
 }
 
 
@@ -785,8 +787,13 @@
 		/* We only route point-to-point packets. */
 		if ((skb->pkt_type != PACKET_BROADCAST) &&
 			(skb->pkt_type != PACKET_MULTICAST))
-			return ipxrtr_route_skb(skb);
-		
+		{
+			skb=skb_unshare(skb, GFP_ATOMIC, FREE_READ);
+			if(skb)
+				return ipxrtr_route_skb(skb);
+			else
+				return 0;
+		}
 		kfree_skb(skb,FREE_READ);
 		return 0;
 	}
@@ -1785,7 +1792,7 @@
 	return	ntohs(socketNum);
 }
 	
-static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
+static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,size_t addr_len)
 {
 	ipx_socket *sk;
 	ipx_interface *intrfc;
@@ -1794,7 +1801,7 @@
 	sk=(ipx_socket *)sock->data;
 	
 	if(sk->zapped==0)
-		return -EIO;
+		return -EINVAL;
 		
 	if(addr_len!=sizeof(struct sockaddr_ipx))
 		return -EINVAL;
@@ -1810,7 +1817,7 @@
 	}
 
 	if(ntohs(addr->sipx_port)<IPX_MIN_EPHEMERAL_SOCKET && !suser())
-		return -EPERM;	/* protect IPX system stuff like routing/sap */
+		return -EACCES;	/* protect IPX system stuff like routing/sap */
 
 	sk->protinfo.af_ipx.port=addr->sipx_port;
 
@@ -1886,7 +1893,7 @@
 }
 
 static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
-	int addr_len, int flags)
+	size_t addr_len, int flags)
 {
 	ipx_socket *sk=(ipx_socket *)sock->data;
 	struct sockaddr_ipx *addr;
@@ -1942,7 +1949,7 @@
 }
 
 static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
-	int *uaddr_len, int peer)
+	size_t *uaddr_len, int peer)
 {
 	ipx_address *addr;
 	struct sockaddr_ipx sipx;
@@ -2149,29 +2156,33 @@
 	int copied = 0;
 	int truesize;
 	struct sk_buff *skb;
-	int er;
-	
-	if(sk->err)
-		return sock_error(sk);
+	int err;
 	
 	if (sk->zapped)
-		return -EIO;
+		return -ENOTCONN;
 
 
-	skb=skb_recv_datagram(sk,flags,noblock,&er);
+	skb=skb_recv_datagram(sk,flags,noblock,&err);
 	if(skb==NULL)
-		return er;
+		return err;
 	
 	if(addr_len)
 		*addr_len=sizeof(*sipx);
 
 	ipx = (ipx_packet *)(skb->h.raw);
 	truesize=ntohs(ipx->ipx_pktsize) - sizeof(ipx_packet);
-	copied = (truesize > size) ? size : truesize;
+	
+	copied = truesize;
+	if(copied > size)
+	{
+		copied=size;
+		msg->msg_flags|=MSG_TRUNC;
+	}
+	
 	err = skb_copy_datagram_iovec(skb,sizeof(struct ipx_packet),msg->msg_iov,copied);
 	
 	if (err)
-		return err; 
+		return err;
 
 	if(sipx)
 	{
@@ -2182,7 +2193,7 @@
 		sipx->sipx_type = ipx->ipx_type;
 	}
 	skb_free_datagram(sk, skb);
-	return(truesize);
+	return(copied);
 }		
 
 static int ipx_shutdown(struct socket *sk,int how)
@@ -2199,7 +2210,6 @@
 
 static int ipx_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
 {
-	int err;
 	long amount=0;
 	ipx_socket *sk=(ipx_socket *)sock->data;
 	
@@ -2363,7 +2373,7 @@
 	proc_net_register(&ipx_rt_procinfo);
 #endif	
 		
-	printk(KERN_INFO "Swansea University Computer Society IPX 0.34 for NET3.035\n");
+	printk(KERN_INFO "Swansea University Computer Society IPX 0.35 for NET3.037\n");
 	printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
 }
 
diff -u --recursive --new-file v2.1.10/linux/net/netlink.c linux/net/netlink.c
--- v2.1.10/linux/net/netlink.c	Fri Nov 15 23:49:12 1996
+++ linux/net/netlink.c	Mon Nov 18 11:31:36 1996
@@ -30,7 +30,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 
-static int (*netlink_handler[MAX_LINKS])(struct sk_buff *skb);
+static int (*netlink_handler[MAX_LINKS])(int minor, struct sk_buff *skb);
 static struct sk_buff_head skb_queue_rd[MAX_LINKS]; 
 static int rdq_size[MAX_LINKS];
 static struct wait_queue *read_space_wait[MAX_LINKS];
@@ -46,7 +46,7 @@
  *	Default write handler.
  */
  
-static int netlink_err(struct sk_buff *skb)
+static int netlink_err(int minor, struct sk_buff *skb)
 {
 	kfree_skb(skb, FREE_READ);
 	return -EUNATCH;
@@ -57,7 +57,7 @@
  *	interfaces.
  */
   
-int netlink_donothing(struct sk_buff *skb)
+int netlink_donothing(int minor, struct sk_buff *skb)
 {
 	kfree_skb(skb, FREE_READ);
 	return -EINVAL;
@@ -91,7 +91,7 @@
 	skb=alloc_skb(count, GFP_KERNEL);
 	skb->free=1;
 	err = copy_from_user(skb_put(skb,count),buf, count);
-	return err ? -EFAULT : (netlink_handler[minor])(skb);
+	return err ? -EFAULT : (netlink_handler[minor])(minor,skb);
 }
 
 /*
@@ -193,7 +193,7 @@
  *	queueing.
  */
  
-int netlink_attach(int unit, int (*function)(struct sk_buff *skb))
+int netlink_attach(int unit, int (*function)(int minor, struct sk_buff *skb))
 {
 	if(unit>=MAX_LINKS)
 		return -ENODEV;
@@ -252,7 +252,7 @@
 
 int init_module(void)
 {
-	printk(KERN_INFO "Network Kernel/User communications module 0.03\n");
+	printk(KERN_INFO "Network Kernel/User communications module 0.04\n");
 	return init_netlink();
 }
 
diff -u --recursive --new-file v2.1.10/linux/net/netrom/af_netrom.c linux/net/netrom/af_netrom.c
--- v2.1.10/linux/net/netrom/af_netrom.c	Tue Nov 12 15:56:16 1996
+++ linux/net/netrom/af_netrom.c	Mon Nov 18 11:31:36 1996
@@ -1,10 +1,10 @@
 /*
- *	NET/ROM release 004
+ *	NET/ROM release 005
  *
  *	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. 
  *
- *	This code REQUIRES 1.3.0 or higher/ NET3.029
+ *	This code REQUIRES 2.1.0 or higher/ NET3.037
  *
  *	This module:
  *		This module is free software; you can redistribute it and/or
@@ -27,6 +27,8 @@
  *			Alan(GW4PTS)	sendmsg/recvmsg only. Fixed connect clear bug
  *					inherited from AX.25
  *	NET/ROM 004	Jonathan(G4KLX)	Converted to module.
+ *	NET/ROM 005	Jonathan(G4KLX) Linux 2.1
+ *			Alan(GW4PTS)	Started POSIXisms
  */
   
 #include <linux/config.h>
@@ -772,7 +774,7 @@
 	return 0;
 }
 
-static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int nr_bind(struct socket *sock, struct sockaddr *uaddr, size_t addr_len)
 {
 	struct sock *sk;
 	struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr;
@@ -782,7 +784,7 @@
 	sk = (struct sock *)sock->data;
 
 	if (sk->zapped == 0)
-		return -EIO;
+		return -EINVAL;
 		
 	if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25))
 		return -EINVAL;
@@ -798,7 +800,7 @@
 	 */
 	if (addr->fsa_ax25.sax25_ndigis == 1) {
 		if (!suser())
-			return -EPERM;
+			return -EACCES;
 		sk->protinfo.nr->user_addr   = addr->fsa_digipeater[0];
 		sk->protinfo.nr->source_addr = addr->fsa_ax25.sax25_call;
 	} else {
@@ -826,7 +828,7 @@
 }
 
 static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
-	int addr_len, int flags)
+	size_t addr_len, int flags)
 {
 	struct sock *sk = (struct sock *)sock->data;
 	struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr;
@@ -977,7 +979,7 @@
 }
 
 static int nr_getname(struct socket *sock, struct sockaddr *uaddr,
-	int *uaddr_len, int peer)
+	size_t *uaddr_len, int peer)
 {
 	struct full_sockaddr_ax25 *sax = (struct full_sockaddr_ax25 *)uaddr;
 	struct sock *sk;
@@ -1230,9 +1232,6 @@
 	struct sk_buff *skb;
 	int er;
 
-	if (sk->err)
-		return sock_error(sk);
-	
 	if (addr_len != NULL)
 		*addr_len = sizeof(*sax);
 
@@ -1240,6 +1239,7 @@
 	 * This works for seqpacket too. The receiver has ordered the queue for
 	 * us! We do one quick check first though
 	 */
+
 	if (sk->state != TCP_ESTABLISHED)
 		return -ENOTCONN;
 
@@ -1252,7 +1252,12 @@
 		skb->h.raw = skb->data;
 	}
 
-	copied = (size < skb->len) ? size : skb->len;
+	copied = skb->len;
+	if(copied>size)
+	{
+		copied=size;
+		msg->msg_flags|=MSG_TRUNC;
+	}
 	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	
 	if (sax != NULL) {
@@ -1462,7 +1467,7 @@
 {
 	sock_register(nr_proto_ops.family, &nr_proto_ops);
 	register_netdevice_notifier(&nr_dev_notifier);
-	printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.5 for AX25.033 Linux 2.0\n");
+	printk(KERN_INFO "G4KLX NET/ROM for Linux. Version 0.5 for AX25.034 Linux 2.1\n");
 
 	if (!ax25_protocol_register(AX25_P_NETROM, nr_route_frame))
 		printk(KERN_ERR "NET/ROM unable to register protocol with AX.25\n");
diff -u --recursive --new-file v2.1.10/linux/net/netsyms.c linux/net/netsyms.c
--- v2.1.10/linux/net/netsyms.c	Tue Nov 12 15:56:16 1996
+++ linux/net/netsyms.c	Mon Nov 18 11:31:36 1996
@@ -8,8 +8,9 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#include <linux/in.h>
+#include <linux/types.h>
 #include <linux/net.h>
+#include <linux/in.h>
 #include <linux/netdevice.h>
 #include <linux/trdevice.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.1.10/linux/net/rose/af_rose.c linux/net/rose/af_rose.c
--- v2.1.10/linux/net/rose/af_rose.c	Tue Nov 12 15:56:17 1996
+++ linux/net/rose/af_rose.c	Mon Nov 18 11:31:37 1996
@@ -759,7 +759,7 @@
 	return 0;
 }
 
-static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int rose_bind(struct socket *sock, struct sockaddr *uaddr, size_t addr_len)
 {
 	struct sock *sk;
 	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
@@ -769,7 +769,7 @@
 	sk = (struct sock *)sock->data;
 
 	if (sk->zapped == 0)
-		return -EIO;
+		return -EINVAL;
 		
 	if (addr_len != sizeof(struct sockaddr_rose))
 		return -EINVAL;
@@ -784,7 +784,7 @@
 
 	if ((user = ax25_findbyuid(current->euid)) == NULL) {
 		if (ax25_uid_policy && !suser())
-			return -EPERM;
+			return -EACCES;
 		user = source;
 	}
 
@@ -807,7 +807,7 @@
 	return 0;
 }
 
-static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
+static int rose_connect(struct socket *sock, struct sockaddr *uaddr, size_t addr_len, int flags)
 {
 	struct sock *sk = (struct sock *)sock->data;
 	struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr;
@@ -957,7 +957,7 @@
 }
 
 static int rose_getname(struct socket *sock, struct sockaddr *uaddr,
-	int *uaddr_len, int peer)
+	size_t *uaddr_len, int peer)
 {
 	struct sockaddr_rose *srose = (struct sockaddr_rose *)uaddr;
 	struct sock *sk;
@@ -1181,9 +1181,6 @@
 	struct sk_buff *skb;
 	int er;
 
-	if (sk->err)
-		return sock_error(sk);
-	
 	if (addr_len != NULL)
 		*addr_len = sizeof(*srose);
 
@@ -1203,7 +1200,14 @@
 		skb->h.raw = skb->data;
 	}
 
-	copied = (size < skb->len) ? size : skb->len;
+	copied = skb->len;
+	
+	if(copied>size)
+	{
+		copied=size;
+		msg->msg_flags|=MSG_TRUNC;
+	}
+	
 	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 	
 	if (srose != NULL) {
@@ -1404,7 +1408,7 @@
 {
 	sock_register(rose_proto_ops.family, &rose_proto_ops);
 	register_netdevice_notifier(&rose_dev_notifier);
-	printk(KERN_INFO "G4KLX Rose for Linux. Version 0.1 for AX25.033 Linux 2.1\n");
+	printk(KERN_INFO "G4KLX Rose for Linux. Version 0.1 for AX25.034 Linux 2.1\n");
 
 	if (!ax25_protocol_register(AX25_P_ROSE, rose_route_frame))
 		printk(KERN_ERR "Rose unable to register protocol with AX.25\n");
diff -u --recursive --new-file v2.1.10/linux/net/rose/rose_link.c linux/net/rose/rose_link.c
--- v2.1.10/linux/net/rose/rose_link.c	Tue Nov 12 15:56:17 1996
+++ linux/net/rose/rose_link.c	Mon Nov 18 11:31:37 1996
@@ -272,7 +272,7 @@
 
 #ifdef CONFIG_FIREWALL
 	if (call_fw_firewall(PF_ROSE, skb->dev, skb->data, NULL) != FW_ACCEPT)
-		return 0;
+		return;
 #endif
 
 	if (!ax25_link_up((ax25_address *)neigh->dev->dev_addr, &neigh->callsign, neigh->dev))
diff -u --recursive --new-file v2.1.10/linux/net/socket.c linux/net/socket.c
--- v2.1.10/linux/net/socket.c	Fri Nov 15 23:49:12 1996
+++ linux/net/socket.c	Mon Nov 18 11:31:37 1996
@@ -159,7 +159,11 @@
 		if(copy_to_user(uaddr,kaddr,len))
 			return -EFAULT;
 	}
- 	return put_user(len, ulen);
+	/*
+	 *	"fromlen shall refer to the value before truncation.."
+	 *			1003.1g
+	 */
+ 	return put_user(klen, ulen);
 }
 
 /*
@@ -724,8 +728,12 @@
  *	For accept, we attempt to create a new socket, set up the link
  *	with the client, wake up the client, then return the new
  *	connected fd. We collect the address of the connector in kernel
- *	space and move it to user at the very end. This is buggy because
+ *	space and move it to user at the very end. This is unclean because
  *	we open the socket then return an error.
+ *
+ *	1003.1g addcs the ability to recvmsg() to query connection pending
+ *	status to recvmsg. We need to add that support in a way thats
+ *	clean when we restucture accept also.
  */
 
 asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen)
@@ -789,9 +797,16 @@
 /*
  *	Attempt to connect to a socket with the server address.  The address
  *	is in user space so we verify it is OK and move it to kernel space.
+ *
+ *	For 1003.1g we need to add clean support for a bind to AF_UNSPEC to
+ *	break bindings
+ *
+ *	NOTE: 1003.1g draft 6.3 is broken with respect to AX.25/NetROM and
+ *	other SEQPACKET protocols that take time to connect() as it doesn't
+ *	include the -EINPROGRESS status for such sockets.
  */
  
-asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen)
+asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, size_t addrlen)
 {
 	struct socket *sock;
 	struct file *file;
@@ -842,7 +857,7 @@
  *	name to user space.
  */
 
-asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
+asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, size_t *usockaddr_len)
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
@@ -867,7 +882,7 @@
  *	name to user space.
  */
  
-asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len)
+asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, size_t *usockaddr_len)
 {
 	struct socket *sock;
 	char address[MAX_SOCK_ADDR];
@@ -892,7 +907,7 @@
  *	in user space. We check it can be read.
  */
 
-asmlinkage int sys_send(int fd, void * buff, int len, unsigned flags)
+asmlinkage int sys_send(int fd, void * buff, size_t len, unsigned flags)
 {
 	struct socket *sock;
 	struct file *file;
@@ -926,8 +941,8 @@
  *	the protocol.
  */
 
-asmlinkage int sys_sendto(int fd, void * buff, int len, unsigned flags,
-	   struct sockaddr *addr, int addr_len)
+asmlinkage int sys_sendto(int fd, void * buff, size_t len, unsigned flags,
+	   struct sockaddr *addr, size_t addr_len)
 {
 	struct socket *sock;
 	struct file *file;
@@ -971,7 +986,7 @@
  *	Receive a datagram from a socket. Call the protocol recvmsg method
  */
 
-asmlinkage int sys_recv(int fd, void * ubuf, int size, unsigned flags)
+asmlinkage int sys_recv(int fd, void * ubuf, size_t size, unsigned flags)
 {
 	struct iovec iov;
 	struct msghdr msg;
@@ -1009,8 +1024,8 @@
  *	sender address from kernel to user space.
  */
 
-asmlinkage int sys_recvfrom(int fd, void * ubuf, int size, unsigned flags,
-	     struct sockaddr *addr, int *addr_len)
+asmlinkage int sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags,
+	     struct sockaddr *addr, size_t *addr_len)
 {
 	struct socket *sock;
 	struct file *file;
@@ -1129,7 +1144,7 @@
 	if(sock->ops->sendmsg==NULL)
 		return -EOPNOTSUPP;
 
-	if ((err = copy_from_user(&msg_sys,msg,sizeof(struct msghdr))))
+	if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
 		return -EFAULT; 
 
 	/* do not move before msg_sys is valid */
@@ -1192,7 +1207,7 @@
 	if (!(sock = sockfd_lookup(fd, NULL)))
 		return(-ENOTSOCK);
 	
-	if ((err = copy_from_user(&msg_sys,msg,sizeof(struct msghdr))))
+	if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr)))
 		return -EFAULT; 
 
 	if(msg_sys.msg_iovlen>UIO_MAXIOV)
@@ -1238,10 +1253,10 @@
 	{
 		if (!err)
 		{
-			int ret;
-			ret = copy_to_user(usr_msg_ctl, krn_msg_ctl,
+			err = copy_to_user(usr_msg_ctl, krn_msg_ctl,
 					   msg_sys.msg_controllen);
-			err = -EFAULT;
+			if (err)
+			    err = -EFAULT; 
 		}
 		kfree(krn_msg_ctl);		
 	}
@@ -1438,7 +1453,7 @@
 {
 	int i;
 
-	printk(KERN_INFO "Swansea University Computer Society NET3.035 for Linux 2.0\n");
+	printk(KERN_INFO "Swansea University Computer Society NET3.037 for Linux 2.1\n");
 
 	/*
 	 *	Initialize all address (protocol) families. 
diff -u --recursive --new-file v2.1.10/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.1.10/linux/net/unix/af_unix.c	Fri Nov 15 23:49:12 1996
+++ linux/net/unix/af_unix.c	Mon Nov 18 11:31:37 1996
@@ -28,6 +28,7 @@
  *		Nick Nevin	:	recvmsg bugfix.
  *		Alan Cox	:	Started proper garbage collector
  *		Heiko EiBfeldt	:	Missing verify_area check
+ *		Alan Cox	:	Started POSIXisms
  *
  * Known differences from reference BSD that was tested:
  *
@@ -43,6 +44,7 @@
  *		and a null first byte in the path (but not for gethost/peername - BSD bug ??)
  *	socketpair(...SOCK_RAW..) doesn't panic the kernel.
  *	BSD af_unix apparently has connect forgetting to block properly.
+ *		(need to check this with the POSIX spec in detail)
  */
 
 #include <linux/config.h>
@@ -395,7 +397,7 @@
 }
 
 
-static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int unix_bind(struct socket *sock, struct sockaddr *uaddr, size_t addr_len)
 {
 	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
 	unix_socket *sk=sock->data;
@@ -416,7 +418,7 @@
 	
 	sk->protinfo.af_unix.name=kmalloc(addr_len+1, GFP_KERNEL);
 	if(sk->protinfo.af_unix.name==NULL)
-		return -ENOMEM;
+		return -ENOBUFS;
 	memcpy(sk->protinfo.af_unix.name, sunaddr->sun_path, addr_len+1);
 	
 	old_fs=get_fs();
@@ -442,14 +444,29 @@
 	
 }
 
-static int unix_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags)
+static int unix_connect(struct socket *sock, struct sockaddr *uaddr, size_t addr_len, int flags)
 {
 	unix_socket *sk=sock->data;
 	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
 	unix_socket *other;
 	struct sk_buff *skb;
 	int err;
+	
+	/*
+	 *	1003.1g breaking connected state with AF_UNSPEC
+	 */
 
+	if(sunaddr->sun_family==AF_UNSPEC)
+	{
+		if(sk->protinfo.af_unix.other)
+		{
+			sk->protinfo.af_unix.other->protinfo.af_unix.locks--;
+			sk->protinfo.af_unix.other=NULL;
+			sock->state=SS_UNCONNECTED;
+		}
+		return 0;
+	}
+		
 	if(sk->type==SOCK_STREAM && sk->protinfo.af_unix.other)
 	{
 		if(sock->state==SS_CONNECTING && sk->state==TCP_ESTABLISHED)
@@ -652,7 +669,7 @@
 	return 0;
 }
 
-static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer)
+static int unix_getname(struct socket *sock, struct sockaddr *uaddr, size_t *uaddr_len, int peer)
 {
 	unix_socket *sk=sock->data;
 	struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr;
@@ -1011,13 +1028,15 @@
  
 static void unix_data_wait(unix_socket * sk)
 {
-	cli();
+	/*
+	 *	AF_UNIX sockets get no messages during interrupts, so this
+	 *	is safe without cli/sti.
+	 */
 	if (!skb_peek(&sk->receive_queue)) {
 		sk->socket->flags |= SO_WAITDATA;
 		interruptible_sleep_on(sk->sleep);
 		sk->socket->flags &= ~SO_WAITDATA;
 	}
-	sti();
 }
 
 static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int noblock, int flags, int *addr_len)
@@ -1033,22 +1052,23 @@
 	struct cmsghdr *cm=NULL;
 	int ct=msg->msg_iovlen;
 	int err = 0;
+	int target = 1;
 
 	if(flags&MSG_OOB)
 		return -EOPNOTSUPP;
+	if(flags&MSG_WAITALL)
+		target = size;
+		
 		
 	if(addr_len)
 		*addr_len=0;
 		
-	if(sk->err)
-		return sock_error(sk);
-
 	if(msg->msg_control) 
 	{
 		cm=msg->msg_control;
 
 		if(msg->msg_controllen<sizeof(struct cmsghdr)
-#if 0 
+#if 0
 /*		investigate this further -- Stevens example doesn't seem to care */
 		||
 		   cm->cmsg_type!=SCM_RIGHTS ||
@@ -1080,15 +1100,25 @@
 			if(skb==NULL)
 			{
 				up(&sk->protinfo.af_unix.readsem);
-				if(sk->shutdown & RCV_SHUTDOWN)
+
+				if(copied >= target)
 					return copied;
-				if(copied)
+
+				/*
+				 *	POSIX checking order...
+				 */
+				
+				if(sk->err)
+					return sock_error(sk);
+				if(sk->shutdown & RCV_SHUTDOWN)
 					return copied;
+				
+				if(current->signal & ~current->blocked)
+					return -ERESTARTSYS;
 				if(noblock)
 					return -EAGAIN;
+
 				unix_data_wait(sk);
-				if(current->signal & ~current->blocked)
-					return -ERESTARTSYS;
 				down(&sk->protinfo.af_unix.readsem);
 				continue;
 			}
@@ -1106,7 +1136,12 @@
 						*addr_len=sizeof(short);
 			}
 
-			num=min(skb->len,len-done);
+			num=skb->len;
+			if(num>len-done)
+			{
+				num=len-done;
+				msg->msg_flags|=MSG_TRUNC;
+			}
 			err = copy_to_user(sp, skb->data, num);
 
 			if (err)
@@ -1283,7 +1318,7 @@
 
 void unix_proto_init(struct net_proto *pro)
 {
-	printk(KERN_INFO "NET3: Unix domain sockets 0.13 for Linux NET3.035.\n");
+	printk(KERN_INFO "NET3: Unix domain sockets 0.14 for Linux NET3.037.\n");
 	sock_register(unix_proto_ops.family, &unix_proto_ops);
 #ifdef CONFIG_PROC_FS
 	proc_net_register(&proc_net_unix);
