]> git.neil.brown.name Git - history.git/commitdiff
Import 2.1.11 2.1.11
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:40 +0000 (15:12 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:12:40 +0000 (15:12 -0500)
121 files changed:
Documentation/Configure.help
Makefile
arch/alpha/kernel/bios32.c
arch/alpha/kernel/entry.S
arch/alpha/lib/strlen_user.S
arch/i386/defconfig
arch/i386/kernel/ksyms.c
drivers/block/loop.c
drivers/block/md.c
drivers/cdrom/cm206.c
drivers/cdrom/optcd.c
drivers/char/cyclades.c
drivers/char/istallion.c
drivers/char/riscom8.c
drivers/char/stallion.c
drivers/char/wdt.c
drivers/isdn/icn/icn.c
drivers/isdn/icn/icn.h
drivers/isdn/pcbit/drv.c
drivers/net/3c505.c
drivers/net/8390.c
drivers/net/CONFIG
drivers/net/Config.in
drivers/net/Makefile
drivers/net/README.multicast
drivers/net/defxx.c [new file with mode: 0644]
drivers/net/defxx.h [new file with mode: 0644]
drivers/net/dgrs.c
drivers/net/dlci.c
drivers/net/eth16i.c
drivers/net/hdlcdrv.c
drivers/net/loopback.c
drivers/net/net_init.c
drivers/net/sdla.c
drivers/net/soundmodem.c
drivers/net/wic.c
drivers/scsi/ppa.c
drivers/scsi/scsi.c
include/asm-alpha/uaccess.h
include/asm-alpha/unistd.h
include/asm-i386/socket.h
include/asm-i386/uaccess.h
include/linux/atalk.h
include/linux/ax25.h
include/linux/fddidevice.h [new file with mode: 0644]
include/linux/if_arp.h
include/linux/if_fddi.h [new file with mode: 0644]
include/linux/igmp.h
include/linux/in.h
include/linux/ipx.h
include/linux/major.h
include/linux/net.h
include/linux/netdevice.h
include/linux/rose.h
include/linux/sched.h
include/linux/skbuff.h
include/linux/socket.h
include/linux/uio.h
include/linux/un.h
include/net/ax25.h
include/net/br.h
include/net/inet_common.h
include/net/netlink.h
include/net/protocol.h
include/net/sock.h
include/net/tcp.h
include/net/udp.h
kernel/info.c
kernel/itimer.c
kernel/module.c
kernel/panic.c
kernel/sched.c
kernel/signal.c
kernel/sys.c
kernel/time.c
mm/swapfile.c
net/802/Makefile
net/802/fddi.c [new file with mode: 0644]
net/Config.in
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/ax25/ax25_in.c
net/ax25/ax25_timer.c
net/ax25/sysctl_net_ax25.c
net/bridge/br.c
net/core/datagram.c
net/core/dev.c
net/core/iovec.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/Config.in
net/ipv4/af_inet.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_forward.c
net/ipv4/ip_fw.c
net/ipv4/ip_sockglue.c
net/ipv4/ipmr.c
net/ipv4/packet.c
net/ipv4/rarp.c
net/ipv4/raw.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/tcp_timer.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/af_inet6.c
net/ipv6/ndisc.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipx/af_ipx.c
net/netlink.c
net/netrom/af_netrom.c
net/netsyms.c
net/rose/af_rose.c
net/rose/rose_link.c
net/socket.c
net/unix/af_unix.c

index 884290c4739b324bcb1902b93a1dc6bc4e90791b..3833edf3a66cf738e2bc638043e2a2ba83fb1c84 100644 (file)
@@ -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
@@ -848,6 +848,13 @@ CONFIG_IP_FIREWALL
   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
   This keeps track of your IP network traffic and produces some
index 5672f526ee957e6dab50583d37efbc121a6c73c8..cdf0fd8d71675234eb23a7058609cfd2f317b0f0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 10
+SUBLEVEL = 11
 
 ARCH = i386
 
index 1e0a5050dd20b76b238e76d1ac9e3200646520d3..37f03b3549c80617788628bfae95cfe2b88b0573 100644 (file)
@@ -37,6 +37,14 @@ int pcibios_present(void)
 {
         return 0;
 }
+asmlinkage int sys_pciconfig_read()
+{
+        return 0;
+}
+asmlinkage int sys_pciconfig_write()
+{
+        return 0;
+}
 
 #else /* CONFIG_PCI */
 
@@ -48,6 +56,7 @@ int pcibios_present(void)
 
 #include <asm/hwrpb.h>
 #include <asm/io.h>
+#include <asm/segment.h>
 
 
 #define KB             1024
@@ -1193,4 +1202,81 @@ const char *pcibios_strerror (int error)
         }
 }
 
+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 */
index d091429f38bcb528429bcc49c5ea800fa0f13a39..6f63fdb7efb6ec6660a5cc95c89f24f305405ff4 100644 (file)
@@ -777,4 +777,4 @@ sys_call_table:
        .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
index c230afbfe4f0391d8d5a91f791a39975f0515059..92834e96e2d03bbc42620629c2c97b4c541d6a9f 100644 (file)
@@ -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 @@ __strlen_user:
        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 @@ $found:      negq    t1, t2          # clear all but least set bit
        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
index 744aa748a90ed4d1f4c714d99455bc0c458cba0c..0e30c600ae611e303cf9bad841bc42a1ad1ce470 100644 (file)
@@ -62,6 +62,7 @@ CONFIG_BLK_DEV_RZ1000=y
 #
 # 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_SKB_LARGE=y
 # 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 @@ CONFIG_SKB_LARGE=y
 # 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_EL3=y
 # 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
index d84faf24624d5a85cc7bff8daae477f6de6d6013..bdb6e80057fe795a1fbd24ecafc2dc09c3bc82cb 100644 (file)
@@ -27,6 +27,10 @@ static struct symbol_table arch_symbol_table = {
        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>
 };
index b07cfe49f603d2505890f8035b44326c77c9d84e..c61549c379acc0a739ffa07089bbdf51c563c8cd 100644 (file)
@@ -431,7 +431,7 @@ static int lo_ioctl(struct inode * inode, struct file * file,
        unsigned int cmd, unsigned long arg)
 {
        struct loop_device *lo;
-       int dev, err;
+       int dev;
 
        if (!inode)
                return -EINVAL;
index bb9992d807a130cd3cca357fdbbc31128d400e47..a5c8d262e38f04d57b82a80eb077b9a2bb020b2e 100644 (file)
@@ -372,7 +372,7 @@ static void md_release (struct inode *inode, struct file *file)
 
 
 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_read (struct inode *inode, struct file *file,
 }
 
 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);
 
index 3196ac2120ced0c3db5694c02938c2a26339903a..4870b8dc07d6c196ef76828459f6f70d81ff90a2 100644 (file)
@@ -580,7 +580,7 @@ void get_disc_status(void)
 
 /* 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 @@ static int cm206_open(kdev_t dev, int purpose)
   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 @@ void get_toc_entry(struct cdrom_tocentry * ep)
  * 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 @@ int cm206_audio_ioctl(kdev_t dev, unsigned int cmd, void * arg)
    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 @@ static int cm206_ioctl(kdev_t dev, unsigned int cmd, unsigned long arg)
   }
 }     
 
-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 @@ int cm206_media_changed(kdev_t dev)
    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 @@ int cm206_tray_move(kdev_t dev, int position)
 }
 
 /* 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 @@ int cm206_drive_status(kdev_t dev)
 }
  
 /* 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 @@ int cm206_disc_status(kdev_t dev)
 }
 
 /* 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 @@ int cm206_lock_door(kdev_t dev, int lock)
 /* 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 @@ int cm206_get_last_session(kdev_t dev, struct cdrom_multisession * mssp)
   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 @@ int cm206_get_upc(kdev_t dev, struct cdrom_mcn * mcn)
   return 0;
 } 
 
-int cm206_reset(kdev_t dev)
+int cm206_reset(struct cdrom_device_info *i)
 {
   stop_read();
   reset_cm260();
@@ -1070,7 +1070,6 @@ int cm206_reset(kdev_t dev)
 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 @@ static struct cdrom_device_ops cm206_dops = {
   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 @@ int cm206_init(void)
     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;
index d14bdf229db17ff6f5aca1fef7bca6385180fa3a..4644ea48186f425918672dbc6dcf03fb8863ea36 100644 (file)
@@ -73,6 +73,8 @@
 #include <linux/cdrom.h>
 #include <linux/optcd.h>
 
+#include <asm/uaccess.h>
+
 \f
 /* Debug support */
 
index cc90ba4f6e49729f7c77cc7da41eadccfe1af333..c18d3e35bdf7d3b4e5de22d8252ad19c2f836ad0 100644 (file)
@@ -1929,7 +1929,7 @@ get_modem_info(struct cyclades_port * info, unsigned int *value)
             | ((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 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd,
   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 @@ get_threshold(struct cyclades_port * info, unsigned long *value)
                   (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 @@ set_default_threshold(struct cyclades_port * info, unsigned long value)
 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 @@ get_timeout(struct cyclades_port * info, unsigned long *value)
                   (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 @@ set_default_timeout(struct cyclades_port * info, unsigned long value)
 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 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
                 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 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
                  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));
index e17a66ab4fa9f240d0d2dee65e4197270c962b4d..7729e6ccb8b7f5a77fc39c3b895b5e45b3996168 100644 (file)
@@ -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 @@ static int  stli_nrbrds = sizeof(stli_brdconf) / sizeof(stlconf_t);
  *     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 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
                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 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
                        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 @@ static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
                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;
index 9df6952b7796b96ed3cbf936ae4f4803caeabf67..8a66ea259dacdb5eed440e82bfcb9eccdddd3ac2 100644 (file)
@@ -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 @@ static int rc_set_modem_info(struct riscom_port * port, unsigned int cmd,
        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 @@ static int rc_ioctl(struct tty_struct * tty, struct file * filp,
                            (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));
index 872afdd42bbefd53683ce23409d470e748dfbebd..3ac1d26543e81981f2f57714c5616ce3a659556b 100644 (file)
@@ -140,7 +140,7 @@ static int  stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
  *     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 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
                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;
index 77d8d71cf9001c7a52fb1b4095f47076f9e9820f..62129edd36e15257a6e3de71891f5c0b0a195983 100644 (file)
@@ -105,13 +105,13 @@ static void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 }
 
 
-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 @@ static int wdt_write(struct inode *inode, struct file *file, const char *buf, in
  *     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 void wdt_release(struct inode *inode, struct file *file)
  
  
 static struct file_operations wdt_fops = {
-       wdt_lseek,
+       wdt_llseek,
        wdt_read,
        wdt_write,
        NULL,           /* No Readdir */
index 65723fef99c9a45df81d2565dd3f79905c9237cb..aca9fe72b976b61738ec38a0a712e15039d1b654 100644 (file)
@@ -842,7 +842,8 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
         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 @@ static int icn_loadproto(u_char * buffer, icn_card * card)
         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 @@ static int icn_readstatus(u_char * buf, int len, int user, icn_card * card)
                 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 @@ static int icn_writecmd(const u_char * buf, int len, int user, icn_card * card,
                         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 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                                     (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 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                         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:
index acbc113a260bb15c5608e35655a2318f8bb523d9..655117f42d70b7526b9a8fc7380fc95b37144ac9 100644 (file)
@@ -118,6 +118,7 @@ typedef struct icn_cdef {
 #if defined(__KERNEL__) || defined(__DEBUGVAR__)
 
 #ifdef __KERNEL__
+
 /* Kernel includes */
 
 #include <linux/module.h>
@@ -127,6 +128,7 @@ typedef struct icn_cdef {
 #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>
@@ -137,6 +139,7 @@ typedef struct icn_cdef {
 #include <linux/wait.h>
 #include <linux/isdnif.h>
 
+
 #endif /* __KERNEL__ */
 
 /* some useful macros for debugging */
index 806a27a2f535321dae2b03d16efe2a20436fd3a4..7347fa8885a8e805890d97e0604ce39d25fdc0ed 100644 (file)
@@ -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 @@ int pcbit_writecmd(const u_char* buf, int len, int user, int driver, int channel
                {
                        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 @@ int pcbit_writecmd(const u_char* buf, int len, int user, int driver, int channel
                        /* 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_st = 0;
 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 @@ int pcbit_stat(u_char* buf, int len, int user, int driver, int channel)
 
        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;
                        
index d27b4a0ced45b1ac684df57cce0826548244021b..fd6f8e99a4d96ed3a1e65a1653cc3d4c3e4ac4ed 100644 (file)
@@ -1657,13 +1657,14 @@ int elplus_probe(struct device *dev)
 
 #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, };
index e9c56d6c8e4111005062bdb348e7bf3272960b02..cce0e4001dedc08f1aa981b583b170db65a0fda2 100644 (file)
@@ -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 @@ static struct enet_statistics *get_stats(struct device *dev)
 
 /*
  *     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 @@ static void set_multicast_list(struct device *dev)
        }
        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);
index f51eea14c2aaab5ca1a4de9409fdec318b6b6f48..bb60633b5bc6329b15d5f68822ec046683036b38 100644 (file)
 #     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 @@ PLIP_OPTS     =
 DEPCA_OPTS     = 
 EWRK3_OPTS     = 
 DE4X5_OPTS     = -DDE4X5_AUTOSENSE=AUTO
+DEFXX_OPTS     =
 ELP_OPTS       =
 TULIP_OPTS     =
index 6cf086c034435ce55eea03aef951cf6652c38db0..efc440badbdca46640debcfe63dd2003185db279 100644 (file)
@@ -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 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
   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
 
index 98385e79dce317ee0d89ad261610b91dc9cad79b..faba5c0f85673f4d3b7cd27548479402391ea009 100644 (file)
@@ -233,10 +233,22 @@ else
   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)
 L_OBJS += lance.o
   ifeq ($(CONFIG_LANCE32),y)
index 73ad973bedb440469545ed4dd8cecd5406ba61d0..47651fd6357f905e51c1504050ab9090d823c5c4 100644 (file)
@@ -15,11 +15,12 @@ IP-MRoute   AllMulti        hardware filters are of no help
 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 @@ de4x5               YES             NO              YES             Hardware
 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 --git a/drivers/net/defxx.c b/drivers/net/defxx.c
new file mode 100644 (file)
index 0000000..0f754ad
--- /dev/null
@@ -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? */
+
+\f
+/*
+ * =======================
+ * = 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;
+       }
+
+\f
+/*
+ * =============
+ * = 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);
+       }
+
+\f
+/*
+ * ====================
+ * = 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);
+       }
+
+\f
+/*
+ * ================
+ * = 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;
+       }
+
+\f
+/*
+ * ========================
+ * = 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;
+       }
+
+\f
+/*
+ * ===================
+ * = 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);
+       }
+
+\f
+/*
+ * =================
+ * = 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);
+       }
+
+\f
+/*
+ * ============
+ * = 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);
+       }
+
+\f
+/*
+ * =============
+ * = 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);
+       }
+
+\f
+/*
+ * ======================
+ * = 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;
+       }
+
+\f
+/*
+ * ==========================
+ * = 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;
+       }
+
+\f
+/*
+ * ==================
+ * = 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;
+       }
+
+\f
+/*
+ * =================
+ * = 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;
+       }
+
+\f
+/*
+ * =====================
+ * = 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);
+       }
+
+\f
+/*
+ * ==============================
+ * = 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;
+       }
+
+\f
+/*
+ * ===========================
+ * = 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 */
+       }
+
+\f
+/*
+ * ======================
+ * = 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);
+       }
+
+\f
+/*
+ * ==========================
+ * = 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);
+       }
+
+\f
+/*
+ * ======================
+ * = 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);
+       }
+
+\f
+/*
+ * ========================
+ * = 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);
+       }
+
+\f
+/*
+ * =====================
+ * = 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;
+       }
+
+\f
+/*
+ * ========================
+ * = 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);
+       }
+
+\f
+/*
+ * =====================
+ * = 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);
+       }
+
+\f
+/*
+ * ================
+ * = 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;
+       }
+
+\f
+/*
+ * =========================
+ * = 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;
+       }
+
+\f
+/*
+ * =====================
+ * = 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 */
+       }
+
+\f
+/*
+ * ================
+ * = 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;
+       }
+
+\f
+/*
+ * =================
+ * = 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;
+       }
+
+\f
+/*
+ * 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 --git a/drivers/net/defxx.h b/drivers/net/defxx.h
new file mode 100644 (file)
index 0000000..83d6645
--- /dev/null
@@ -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_ */
index c7cfeb4bfdb683ff6ebb3cf373109a2e9fd53f15..352652ff063df13d8ba54ffb66ec13bb14ffc505 100644 (file)
@@ -36,6 +36,7 @@ static char *version = "$Id: dgrs.c,v 1.8 1996/04/18 03:11:14 rick Exp $";
 #include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
+#include <asm/uaccess.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 6f4c187ab66340f3f5abebaa1c1a4b40887ac36f..8eb2d0416f488702d7413aeade8f973dfc2ac236 100644 (file)
@@ -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>
index b079be80316d024d19fc08e67e97df19384cb0c4..143578a939b2273faad378ff3eeafdf9728c6511 100644 (file)
@@ -181,8 +181,8 @@ static char *version =
 #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_close(struct device *dev);
 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 @@ static void eth16i_initialize(struct device *dev)
   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 @@ static void eth16i_interrupt(int irq, void *dev_id, struct pt_regs *regs)
   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;
   
index c43808f44c0a5dbc17d73c207d2625259c1b0aed..420d02ca2a475a5079ba108a40b14da9bdcce23c 100644 (file)
@@ -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>
index 443f67ec001081fd513f23b214d4311d5e77b97e..e2daa7cbd701b3c02e86221d7457f7486e5c20f6 100644 (file)
@@ -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 @@ static int loopback_xmit(struct sk_buff *skb, struct device *dev)
        {
                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)
index 911a91b90de92e422a27ea31cba39d7b765a6401..370ce6cc01fce6e804b9ac771daa86b88d020276 100644 (file)
@@ -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 @@ static int eth_change_mtu(struct device *dev, int new_mtu)
        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;
@@ -231,6 +245,43 @@ void tr_setup(struct device *dev)
 
 #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
+
 int ether_config(struct device *dev, struct ifmap *map)
 {
        if (map->mem_start != (u_long)(-1))
index e6b672fcf9bd90b532fcf570341ca3f9de252ba3..f5e4b16a6314a494c6b61c36e9ec7267559b39ed 100644 (file)
@@ -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>
index c5e4388e84edbdedfd402125717195c2977ae319..12917a5d18b1254e1b042854486783aa10ee5af5 100644 (file)
@@ -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>
index c8d1f88170744a86bbcdc1b373ff0db50e0a1831..16b21dabc6eefc18fb1ecfd5c589ba39fd73fddf 100644 (file)
@@ -49,6 +49,7 @@ char *version = "NET3 WIC version 0.9 hayes@netplumbing.com";
 #include <asm/bitops.h>
 #include <asm/irq.h>
 #include <asm/byteorder.h>
+#include <asm/uaccess.h>
 #include <linux/string.h>
 
 #define NET_DEBUG 1
index 82a4d979412378b152efaacb0f32715ce6e6c8fd..1793de1145bac8ca33e6a037feab0971e6818b3a 100644 (file)
@@ -46,7 +46,7 @@ static int      ppa_nybble     = 0;      /* don't force nybble mode  */
 #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>
index b1793404df3c5c6d9bb076f595ab7e77b5ae21dd..40140e06d67f929e6351afb6e59317296b8df501 100644 (file)
@@ -311,7 +311,7 @@ static int get_device_flags(unsigned char * response_data){
 
 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 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device,
     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 @@ inline void internal_cmnd (Scsi_Cmnd * SCpnt)
 
 static void scsi_request_sense (Scsi_Cmnd * SCpnt)
 {
-    unsigned int flags;
+    unsigned long flags;
     
     save_flags(flags);
     cli();
index 6e639f4aa0b5aa9dfab205bbfdc35a2faee0812c..526767e41ebf09d50a27ab5ea55dc2462deb28b8 100644 (file)
@@ -377,14 +377,14 @@ extern void __clear_user(void);
 
 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 long __strlen_user(const char *);
 
 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;
 }
 
 /*
index 18cf2edab37eaa966469473e9efc02ddfeb06a42..03f74548188d673d57facd431b31ba165a7c6aa8 100644 (file)
 #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__)
 
index 529a3ffefa6f89c51dc04fe0367af135cb8ff768..4e8b652771bb11ac3a4501aa6f84eb3dc198962c 100644 (file)
 #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 */
index 93f6fd2a281ba387283b260ec4671a970ea053f0..bb7fe8b8db0b62f725c17d061f8ab04a27467645 100644 (file)
 #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 @@ strncpy_from_user(char *dst, const char *src, long count)
  *
  * 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 */
index c70d0577b698ffb73f35df42f379fcfef29c9b31..9035ddbd8c7f73c99ab528ac597748fbb93453b0 100644 (file)
@@ -25,7 +25,7 @@ struct at_addr
 
 struct sockaddr_at 
 {
-       short           sat_family;
+       sa_family_t     sat_family;
        __u8            sat_port;
        struct at_addr  sat_addr;
        char            sat_zero[ 8 ];
index b9f51c687c0a575c30f23dc923750c515f688be7..7cf2c64109596c87018ccef9e5de1b3d371be013 100644 (file)
@@ -41,7 +41,7 @@ typedef struct {
 } 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 --git a/include/linux/fddidevice.h b/include/linux/fddidevice.h
new file mode 100644 (file)
index 0000000..bb0b298
--- /dev/null
@@ -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 */
index 386d90ed81e0276ebea979f84fe2cbd1772000a6..fffb67990fdb71ba73105c33f31dea9ff36b0e94 100644 (file)
@@ -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 --git a/include/linux/if_fddi.h b/include/linux/if_fddi.h
new file mode 100644 (file)
index 0000000..6db6745
--- /dev/null
@@ -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 */
index 272be68948bf0428751cba86370e168cc3d10099..82569a65353afd29db701878581285210a0fe26b 100644 (file)
@@ -36,6 +36,7 @@ struct igmphdr
 #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 @@ struct ip_mc_list
        unsigned long multiaddr;
        struct ip_mc_list *next;
        struct timer_list timer;
-       int tm_running;
+       short tm_running;
+       short reporter;
        int users;
 };
 
index 6174845e20deea49a7652918c909ffad97243cf3..61566713f034643391d1d59e15ff7c0699a61fbe 100644 (file)
@@ -57,7 +57,7 @@ struct ip_mreq
 /* 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             */
 
index e3cc49a9a6bfe056aace382d6a900dd9a11f29cd..a2d86a9832b16cc6f0e5eaa2932d74eff632bcf3 100644 (file)
@@ -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 */
 };
 
index e33e7dc3aa52555461dfdb9d26dbdf18eed188d5..396b33a02535d5b682ff22570ee84e8103c9ff36 100644 (file)
@@ -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
index a338a8efda66e553a78d1aca58092f61d9cf963b..5673b7e42077c1e9c45874f0952ccabea9cb1c9c 100644 (file)
@@ -92,14 +92,14 @@ struct proto_ops {
   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,
index bba7c5e1f3639124723fa760014d647407bc1d60..55c72a1c7bcc7aadc4e85f81ab696fa613c5558b 100644 (file)
@@ -295,6 +295,7 @@ extern __inline__ void dev_lock_wait(void)
 /* 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 */
index 13277b38d6421a5487c1c482a52580a52ce2520e..ca69e1e8b2e87066564f2c7405c39d76fcaab967 100644 (file)
@@ -26,7 +26,7 @@ typedef struct {
 } rose_address;
 
 struct sockaddr_rose {
-       short           srose_family;
+       sa_family_t     srose_family;
        rose_address    srose_addr;
        ax25_address    srose_call;
        int             srose_ndigis;
index 135ddfe6079bf3851acf6f00272da41f4384968a..b0fff062db79f5153f99fbc35130c2ffcdb9b028 100644 (file)
@@ -320,7 +320,7 @@ extern struct task_struct *current_set[NR_CPUS];
  *     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;
index e8ddfb05d2ea96bd0a71d770143b8368dc4048da..342e5a3352a904711577f9ef845d80ca1755e444 100644 (file)
@@ -184,6 +184,16 @@ extern __inline__ int skb_queue_empty(struct sk_buff_head *list)
        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__ void skb_unlink(struct sk_buff *skb)
  
 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 @@ here:
 
 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;
index d862f8f6d48bdec63e4db3335db5121ef5909895..4d29e6ff1f43f71a92777378ef2c18029cea1747 100644 (file)
@@ -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 linger {
 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 @@ extern __inline__ struct cmsghdr * cmsg_nxthdr(struct msghdr *mhdr,
 /* 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 @@ extern __inline__ struct cmsghdr * cmsg_nxthdr(struct msghdr *mhdr,
 #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 @@ extern __inline__ struct cmsghdr * cmsg_nxthdr(struct msghdr *mhdr,
 #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 @@ extern __inline__ struct cmsghdr * cmsg_nxthdr(struct msghdr *mhdr,
 #define SOL_ATALK      258
 #define SOL_NETROM     259
 #define SOL_ROSE       260
+#define SOL_DECNET     261
 #define SOL_TCP                6
 #define SOL_UDP                17
 
index 8027bc8d7a588b9bd2a27768d90accde004784b1..5fbc2f7f1ec194cd4106f77a20f481bddc707d3c 100644 (file)
 
 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 */
 
index e11ad75fe0a21ecfb95bb7b7dd2b4955bbac633b..45561c564b8e004bde76a069ce9823f5085226dd 100644 (file)
@@ -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 */
 };
 
index f2bc1553fa9da8b0ae6989b9c051d00a1d69862e..43cedaafbbbce2410903951599bc067387bebadc 100644 (file)
 #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 */
index f1d6678de7c11c0856610c44a68aa4d5f95d5f02..a1d3fa3092ab6bffd97d1a68a5d6fcb12412a2d0 100644 (file)
@@ -161,15 +161,29 @@ struct fdb {
 
 #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 @@ struct br_cf {
 #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... */
 
@@ -261,6 +280,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);
 
index c72c7533336bf2955e6ebb599ac20d9adbb02509..7fa56112d0dd14346ae42afd43ca2cffe96090e1 100644 (file)
@@ -17,7 +17,7 @@ extern int                    inet_release(struct socket *sock,
                                             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, 
index 3b92e80bcac91df73426d6498dc92d6267fae8b6..f0b9c9d74420fc85eafb7c674213f46e4ad90c96 100644 (file)
@@ -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 @@ extern int init_netlink(void);
 #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 *);
index 1556c2cc8a02913e154a0ce9db874828c377861d..97929883264f06d7228efe68edabc9f5ee932fd3 100644 (file)
@@ -41,7 +41,7 @@ struct inet_protocol {
                                   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;
index a8b09e4b6ceeddc5da88d3b76af54669dd7b1a6d..0d8ab37fa0c683034210e8b99104ca3e8c48d1a0 100644 (file)
@@ -511,7 +511,7 @@ struct proto
                                        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 @@ struct proto
                                        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);
index 8c1bf9e26f297e0d6011aeba88ec80fd3578aa9b..aa1e74bb2b22e1e556283209c6834504ff854401 100644 (file)
@@ -240,7 +240,8 @@ extern struct tcp_mib tcp_statistics;
 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 @@ extern int                  tcp_v4_backlog_rcv(struct sock *sk,
                                                   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 *);
index df25b24912c221169fe384cb719c93cb988ce0e9..5a86f93fc7f5fa8561ef7baee06f36cedf2e5e8c 100644 (file)
@@ -33,16 +33,11 @@ extern struct proto udp_prot;
 
 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);
index e6dc55734aaf5454be5857bad6117c39e18ec48a..20b6ad6aee2204640a955ff9df55ab0aadb18826 100644 (file)
 
 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 @@ asmlinkage int sys_sysinfo(struct sysinfo *info)
        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;
 }
index 44bd8150f4f30eae59b2cee9800706c81ef35eaf..efcc8351b75ffdd5c8428b4f5a6a5012824d3eba 100644 (file)
@@ -88,11 +88,7 @@ asmlinkage int sys_getitimer(int which, struct itimerval *value)
        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 @@ asmlinkage int sys_setitimer(int which, struct itimerval *value, struct itimerva
                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;
 }
index 14717bec3eb3cc628dbc1843eeec7139c4d7f05e..71297a98882e538ea674a10b538fe549f76798e4 100644 (file)
@@ -54,7 +54,6 @@ struct module *module_list = &kernel_module;
 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 @@ void init_modules(void) {
        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 @@ sys_create_module(char *module_name, unsigned long size)
        return (unsigned long) addr;
 }
 
+
 /*
  * Initialize a module.
  */
@@ -157,7 +172,8 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
                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 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
        }
        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 @@ sys_init_module(char *module_name, char *code, unsigned codesize,
                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 @@ sys_get_kernel_syms(struct kernel_sym *table)
        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 @@ sys_get_kernel_syms(struct kernel_sym *table)
        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 @@ sys_get_kernel_syms(struct kernel_sym *table)
 
                                                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;
                                        }
                                }
                        }
@@ -387,27 +404,6 @@ sys_get_kernel_syms(struct kernel_sym *table)
        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.
  */
index a0446d37381afd1247459c18a6ad3a9deb577604..96b04ddbf4c334f5ef72124aeb5042235cfe574f 100644 (file)
@@ -58,11 +58,3 @@ NORET_TYPE void panic(const char * fmt, ...)
        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)");
-}
index 73bb8e476c2fb705d80b2110e0e088a5a07566a5..8d13c21a62b7ec9e4b0df69289fdbce081dd2b99 100644 (file)
@@ -1211,17 +1211,14 @@ found:
 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_getscheduler(pid_t pid)
 
 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_get_priority_min(int policy)
 
 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 @@ asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
        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 @@ asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp)
                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;
        }
index 99f82331ebdd6fe18dff7967679b5bc9a11e06f7..c41728dac83730ae2636f9b0fbb0dd7d2e5a42f3 100644 (file)
@@ -32,10 +32,9 @@ asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
        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 @@ asmlinkage int sys_sigprocmask(int how, sigset_t *set, sigset_t *oset)
                }
        }
        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_ssetmask(int newmask)
 
 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 @@ asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
                        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 @@ asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
                }
        }
        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;
index 2017b81d6c39638dbe86effcda04c51f95d3d91f..5a0ecada2f73e3714183102bba2a44b888348974 100644 (file)
@@ -578,14 +578,17 @@ asmlinkage int sys_setfsgid(gid_t gid)
 
 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 @@ asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
                        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 @@ asmlinkage int sys_olduname(struct oldold_utsname * name)
        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 @@ asmlinkage int sys_sethostname(char *name, int len)
                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 @@ asmlinkage int sys_gethostname(char *name, int len)
 
        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 @@ asmlinkage int sys_setdomainname(char *name, int len)
                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 @@ asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 
        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 @@ asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
  */
 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 @@ int getrusage(struct task_struct *p, int who, struct rusage *ru)
                        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)
index 058e642106cb0b2e2ac14c9f70ad547b56dfda5f..c2090a5830be009491ae632ce2c0e4249c906ae9 100644 (file)
@@ -202,15 +202,13 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
        /* 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 @@ asmlinkage int sys_adjtimex(struct timex *txc_p)
 
        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;
 }
index 7012a4eda94231e38486784a043d94af9b41074d..c35a7ffc1e13b02bf0aa56fdc00f5a6d875f6b52 100644 (file)
@@ -518,7 +518,8 @@ asmlinkage int sys_swapon(const char * specialfile, int swap_flags)
        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;
index 12b299e8d523427187f056f9fb13cb6b0498fc63..cb8d33a61b8e28872e4938ca6108d1b1e44665ba 100644 (file)
@@ -14,6 +14,10 @@ ifdef CONFIG_TR
 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 --git a/net/802/fddi.c b/net/802/fddi.c
new file mode 100644 (file)
index 0000000..24fcff1
--- /dev/null
@@ -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);
+       }
index b6d5c15fb994087ac2b666d1c24cc30a5f7de683..751f22bfd9fa2c84bceca9faf449acdf12275ea4 100644 (file)
@@ -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
@@ -28,8 +32,4 @@ 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
index aef113cd9b6cabc2e6afa6faf9617d902cf805a7..24758530a71b6ebc67d46e697dea06602b9087d1 100644 (file)
@@ -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 @@ int atif_ioctl(int cmd, void *arg)
        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 @@ static int atalk_autobind(atalk_socket *sk)
  *     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 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
        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_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
  */
  
 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 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
        
        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_accept(struct socket *sock, struct socket *newsock, int flags)
  */
  
 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 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
        if(sk->zapped)
        {
                if(atalk_autobind(sk)<0)
-                       return -EBUSY;
+                       return -ENOBUFS;
        }       
        
        *uaddr_len = sizeof(struct sockaddr_at);
@@ -1410,6 +1410,10 @@ static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type
         *      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 @@ static int atalk_rcv(struct sk_buff *skb, struct device *dev, struct packet_type
                 *      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 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int n
        if(usat)
        {
                if(sk->zapped)
-               /* put the autobinding in */
                {
                        if(atalk_autobind(sk)<0)
                                return -EBUSY;
@@ -1738,7 +1744,7 @@ static int atalk_sendmsg(struct socket *sock, struct msghdr *msg, int len, int n
        if (err)
        {
                kfree_skb(skb, FREE_WRITE);
-               return err;
+               return -EFAULT;
        }
                
        if(sk->no_check==1)
@@ -1821,9 +1827,6 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, int
        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 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, int
        {
                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 @@ static int atalk_recvmsg(struct socket *sock, struct msghdr *msg, int size, int
        {
                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_select(struct socket *sock , int sel_type, select_table *wait)
 
 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 @@ static int atalk_ioctl(struct socket *sock,unsigned int cmd, unsigned long arg)
                        {
                                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 @@ void atalk_proto_init(struct net_proto *pro)
        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
index a32fb08c5a6282d6f3049e700ed9a60158486218..0603f7dd58429aceb0d72e6307f73f0132c7d2bf 100644 (file)
@@ -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 @@ static int ax25_release(struct socket *sock, struct socket *peer)
  *     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 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
        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_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
 }
 
 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 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
 
                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 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
        }
                
        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_accept(struct socket *sock, struct socket *newsock, int flags)
 }
 
 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 @@ static int ax25_rcv(struct sk_buff *skb, struct device *dev, ax25_address *dev_a
        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 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
        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 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
                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 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
        int er;
        int dama;
 
-       if (sk->err)
-               return sock_error(sk);
-       
        if (addr_len != NULL)
                *addr_len = sizeof(*sax);
 
@@ -2108,7 +2122,12 @@ static int ax25_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                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 @@ void ax25_proto_init(struct net_proto *pro)
        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");
 }
 
 /*
index a2b59825f045f825e2b1132a1b9e3e51dc2e628c..e77378098ad659b31a4779470babaf89d7a453e9 100644 (file)
@@ -245,6 +245,7 @@ static int ax25_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                        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 @@ static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                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 @@ static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                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 @@ static int ax25_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                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 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                                if (!ax25->sk->dead)
                                        ax25->sk->state_change(ax25->sk);
                                ax25->sk->dead  = 1;
+                               ax25->sk->shutdown|=SEND_SHUTDOWN;
                        }
                        break;
 
@@ -411,6 +416,7 @@ static int ax25_state3_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        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 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        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 @@ static int ax25_state4_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype
                        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;
index 78c56fe8e5aaa111ce54f46a0d3e18bf7f16a5ae..0611daefa91fa250803ae4af4877a46718e45142 100644 (file)
@@ -152,6 +152,7 @@ static void ax25_timer(unsigned long param)
                                        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 @@ static void ax25_timer(unsigned long param)
                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 @@ void ax25_t1_timeout(ax25_cb * ax25)
                                        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 @@ void ax25_t1_timeout(ax25_cb * ax25)
                                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 @@ void ax25_t1_timeout(ax25_cb * ax25)
                                                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;
index 35d5ac99900974dcadfb3cd6d7ebdca66024a45c..12fae19038eecf8e5f34a5b0408f3a9f07e90e2e 100644 (file)
@@ -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;
 
index c1fd04321f82490c18fa789a364bac67d25f82d8..70e54dbc362314bc53c6b08cb5091201229a84c7 100644 (file)
@@ -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 @@ static struct notifier_block br_dev_notifier={
        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 @@ void br_init(void)
 {                                                /* (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 @@ void br_init(void)
 
        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 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
 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 @@ int br_ioctl(unsigned int cmd, void *arg)
                                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 @@ int br_cmp(unsigned int *a, unsigned int *b)
        }
        return(0);
 }
-               
+
index 8480bebd9facb723b96cfbe34fca522ee4340c40..74f10f8a5f192d71609b48679b0adc23606a6d69 100644 (file)
@@ -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 @@ static inline int connection_based(struct sock *sk)
  *
  *     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,16 +110,16 @@ restart:
                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);
          }
 
index 5cfa093ddd0adf5d97abc826e18b9c40fefb8f52..f6bc01f9d3bb2000e9df62e785d19a22d18a3d53 100644 (file)
@@ -597,10 +597,11 @@ void net_bh(void)
 
                /*
                 *      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
index b18e062d9525f56c684ba79c85ccd3c417a876b8..6db6ac3e901efae5c3d6efd6db34ba4b2d838c72 100644 (file)
@@ -94,9 +94,8 @@ int memcpy_toiovec(struct iovec *iov, unsigned char *kdata, int len)
                {
                        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;
index e041c11fdbe514930561892421556c5d1c6919c0..0fb11f1178e88f134a13fb41794a877ecc25d609 100644 (file)
@@ -68,6 +68,13 @@ atomic_t net_free_locked = 0;
 
 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);
index 0654192dcf0f31c3cbe71f007918b3b354805361..28c3eb897675020d241aef99e6a9cc1cf38df34c 100644 (file)
@@ -245,6 +245,8 @@ int sock_setsockopt(struct sock *sk, int level, int optname,
                        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 @@ int sock_getsockopt(struct sock *sk, int level, int optname,
                                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);
index 8e655058690a2ae7b3cc89afcc60c93cbbd8d762..25596cc4f3f79221572691dfb5e61abe9896183e 100644 (file)
@@ -6,6 +6,9 @@ bool 'IP: multicasting' CONFIG_IP_MULTICAST
 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
index 092eaad4f6bd34a879f0de2a5c66c7e2afa97f3a..b28fc1e0c764c2bf26c63db9a26d13637223b279 100644 (file)
@@ -454,6 +454,10 @@ int inet_setsockopt(struct socket *sock, int level, int optname,
 
 /*
  *     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 @@ int inet_release(struct socket *sock, struct socket *peer)
 
 
 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 @@ static int inet_bind(struct socket *sock, struct sockaddr *uaddr,
  */
  
 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 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags)
  */
  
 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 @@ void inet_proto_init(struct net_proto *pro)
        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... 
index 173704f34aac7884751cf63d19d05e58b83e8864..787f69d7fa4ebb8c9c6fe6892bb85ace255f9edc 100644 (file)
@@ -643,9 +643,16 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct devi
        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 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct devi
                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 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct dev
        /*
         *      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 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct dev
        /*
         *      Discard the original packet
         */
-        
+flush_it:
        kfree_skb(skb, FREE_READ);
 }
 
index f8f4e2ec2f42d9c74e070a30006d8b7b60e9efb5..8fd37eb9d2fbad2706bc0c3e261f8e7ded068e33 100644 (file)
@@ -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 @@ static void igmp_timer_expire(unsigned long data)
                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_init_timer(struct ip_mc_list *im)
 }
 
 
-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 @@ extern __inline__ void ip_mc_map(unsigned long addr, char *buf)
 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_add(struct device *dev, unsigned long addr)
 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 @@ int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        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;
 }
index eaa74a6387d62ded61bc2d09ec75d0ec414a5327..81d90f5de3372052a4211f001af45feef37bfcc4 100644 (file)
@@ -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 @@ int ip_forward(struct sk_buff *skb, struct device *dev, int is_frag,
        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
index b687b650e172921fc88ef1d161e2ed251075b9b6..f0ae86e36a5a22099f12fc0f32984bc310bcff9b 100644 (file)
@@ -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
 #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 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, __u16 *redirport, struct ip_
                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 */
index 89092deabfd8bc5a1cfd356cc8abb12f6cbd4512..7337fc08c526e5683fcc93b97e1cbe930b8b05b1 100644 (file)
@@ -495,8 +495,11 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
                                        }
                                }
                                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 @@ int ip_getsockopt(struct sock *sk, int level, int optname, char *optval, int *op
                        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:
index 99c0d33cb39550e8823b2c0b820d1adbda618a1a..79736745cb97ec5a28dacee8e0c7b97b07ab3b09 100644 (file)
@@ -551,14 +551,16 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
                 *      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.
index 27107fa630af5fa57ee797f5d316208709be85a8..66f79cc446eb91653ffd8d7c626e0c2743b1621e 100644 (file)
@@ -282,7 +282,7 @@ int packet_attach(struct sock *sk, struct device *dev)
  *     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 @@ int packet_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        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 @@ int packet_recvmsg(struct sock *sk, struct msghdr *msg, int len,
         *      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)
index a97744e9f1142161c9392b6b425ebafbdf93ffed..28e2f40872b8aa1914fe802c81bba0bd2f461e82 100644 (file)
@@ -436,7 +436,7 @@ static int rarp_req_get(struct arpreq *req)
  *        Copy the information back
  */
   
-       return copy_to_user(req, &r, sizeof(r));
+       return copy_to_user(req, &r, sizeof(r)) ? -EFAULT : 0;
 }
 
 
index 68852dfcdcf529db3d2c2dff97353fa7631b1eaa..89e03aed62a20ef3d9ef098e74003bc9c899e43d 100644 (file)
@@ -350,7 +350,12 @@ int raw_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        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;
index c2d8a06aff0951ed11865251240a88b9eb95c450..5f6328d68c3df966468389aa16629bba64b246c8 100644 (file)
@@ -31,7 +31,9 @@ extern int sysctl_arp_check_interval;
 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 @@ ctl_table ipv4_table[] = {
 #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}
 };
index a6556bf94f7d81fed11dd475152cf2c409710088..ac6e2ea536fc7eebef85409d23dd64fe3e917db6 100644 (file)
  *
  *             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 @@ int tcp_do_sendmsg(struct sock *sk, int iovlen, struct iovec *iov,
                                    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 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
                        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 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
                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 @@ static int tcp_recv_urg(struct sock * sk, int nonblock,
                }
                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 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
        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 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
        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 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
 
                /*
                 * 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 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                }
                while (skb != (struct sk_buff *)&sk->receive_queue);
 
-               if (copied)
+               if (copied >= target)
                        break;
 
                if (sk->err && !(flags&MSG_PEEK))
@@ -1393,11 +1404,6 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                 *      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 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                        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)
@@ -1849,104 +1856,6 @@ void tcp_set_keepalive(struct sock *sk, int val)
        }
 }
 
-
-/*
- *      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;
-}
-
 /*
  * Local variables:
  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -c -o tcp.o tcp.c"
index 7ce6f0635e50fc827663027acfdd3bd1c8bd3ff1..076568961377a021f633fb8590dd47952dc01dd6 100644 (file)
  */
 
 #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 @@ static void tcp_fast_retrans(struct sock *sk, u32 ack, int not_dup)
        
 }
 
-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 @@ int sysctl_tcp_vegas_cong_avoidance = 1;
  *      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 @@ static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
         *      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 @@ static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
                tp->basertt = min(seq_rtt, tp->basertt);
        else
                tp->basertt = seq_rtt;
-               
-               
+
        /*
         * 
         *      Actual   = throughput for this segment.
@@ -403,14 +414,13 @@ static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
         */
 
        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 @@ static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
        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 @@ static void tcp_cong_avoid_vegas(struct sock *sk, u32 seq, u32 ack,
                 */
                        
                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 @@ static void tcp_cong_avoid_vanj(struct sock *sk, u32 seq, u32 ack, u32 seq_rtt)
 #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 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th,
         *      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 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th,
                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 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th,
                         sk->packets_out = 0;
                 }
        }
-
+#endif
 
        if (sk->packets_out)
        {
@@ -773,12 +787,6 @@ static int tcp_ack(struct sock *sk, struct tcphdr *th,
        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 @@ static int tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th)
         * 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_ofo_queue(struct sock *sk)
        }
 }
 
-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 tcp_urg(struct sock *sk, struct tcphdr *th, unsigned long len
 }
 
 
-static __inline__ void prune_queue(struct sock *sk)
+static void prune_queue(struct sock *sk)
 {
        struct sk_buff * skb;
 
@@ -1834,6 +1842,32 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        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;
+}
+
 /*
  * Local variables:
  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -c -o tcp_input.o tcp_input.c"
index 4e1e3e7153a1e341a0bd077c2692fd4cdcb3e320..fcc139056631129d46889fed9cd2627a518ea06a 100644 (file)
@@ -127,7 +127,7 @@ static int tcp_unique_address(u32 saddr, u16 snum, u32 daddr, u16 dnum)
  *     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 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (buff == NULL) 
        {
                release_sock(sk);
-               return(-ENOMEM);
+               return(-ENOBUFS);
        }
 
        buff->sk = sk;
@@ -250,21 +250,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        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 @@ out:
  */
 
 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 @@ void tcp_v4_err(int type, int code, unsigned char *header, __u32 info,
        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 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
         */
        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 @@ struct sock * tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
                newsk->mtu = 64;
        }
 
-       snd_mss -= sizeof(struct iphdr) - sizeof(struct tcphdr);
+       snd_mss -= sizeof(struct iphdr) + sizeof(struct tcphdr);
 
        if (sk->user_mss)
        {
index d0e7c3572951a6ecec971f0192b2a1caf2947934..2dff0b6d8e8385d90c58273bbf227426749279e3 100644 (file)
@@ -361,7 +361,9 @@ static int tcp_wrxmit_frag(struct sock *sk, struct sk_buff *skb, int size)
 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 @@ void tcp_write_xmit(struct sock *sk)
 
        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 @@ void tcp_write_xmit(struct sock *sk)
                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);
+               /* 
+                * Advance the send_head
+                * This one is going out.
+                */
+
+               update_send_head(sk);
 
-                       atomic_inc(&sk->packets_out);
+               atomic_inc(&sk->packets_out);
 
 
 /*
@@ -418,45 +423,147 @@ void tcp_write_xmit(struct sock *sk)
  * 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 @@ void tcp_do_retransmit(struct sock *sk, int all)
        
        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 @@ void tcp_do_retransmit(struct sock *sk, int all)
                        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
                 */
index f9be0ea339d14e692f4df0b6decee75d2a1a0c55..dfc372ad7e704084a6a1b066cd85e332322e5dca 100644 (file)
@@ -185,8 +185,9 @@ static int tcp_write_timeout(struct sock *sk)
                        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 @@ static void tcp_syn_recv_timer(unsigned long data)
 
                                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 @@ static void tcp_syn_recv_timer(unsigned long data)
                                        
                                        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 @@ static void tcp_syn_recv_timer(unsigned long data)
                                                (*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;
index 59d6c28305bc22e0f3ca7f67870fc0d673ca7b3d..af592b412017582d55ca50c621e898011a192a2f 100644 (file)
@@ -151,7 +151,7 @@ void udp_cache_zap(void)
  */
 
 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 @@ void udp_err(int type, int code, unsigned char *header, __u32 info,
        /*
         *      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 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
                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 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, int len,
        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);
 
index e412e85bf427b60ed2ca583e615035f4ae8de1ca..ac87944961b38520bd1c1ea25abad9517ebdddbe 100644 (file)
@@ -862,7 +862,7 @@ int addrconf_set_dstaddr(void *arg)
                dev = sit_add_tunnel(ireq.addr.s6_addr32[3]);
                
                if (dev == NULL)
-                       return -ENOMEM;
+                       return -ENODEV;
 
                return 0;
        }
index 76124d2ec35de67bdbcb4fae606501f7d3c8a135..8dc0a7c567f80c215027d67799b63897d26b090f 100644 (file)
@@ -254,7 +254,7 @@ static int inet6_dup(struct socket *newsock, struct socket *oldsock)
  */
 
 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 @@ static int inet6_bind(struct socket *sock, struct sockaddr *uaddr,
                
        /* 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_socketpair(struct socket *sock1, struct socket *sock2)
  */
  
 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 @@ void inet6_proto_init(struct net_proto *pro)
 {
        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);
        
index 52e22a66d06a3a4ad872576818a7d4ea9029d41d..e004417fc6bb2eec5e7d93fd5b3be307cdf28028 100644 (file)
  *      2 of the License, or (at your option) any later version.
  */
 
+/*
+ *     Changes:
+ *
+ *     Lars Fenneberg                  :       fixed MTU setting on receipt
+ *                                             of an RA. 
+ *
+ */
+
 /*
  *     Interface:
  *
@@ -1383,7 +1391,7 @@ static void ndisc_router_discovery(struct sk_buff *skb)
                                int mtu;
                                struct device *dev;
                                
-                               mtu = htonl(*(__u32 *)opt+4);
+                               mtu = htonl(*(__u32 *)(opt+4));
                                dev = rt->rt_nexthop->dev;
 
                                if (mtu < 576)
index bb03b34dd49646f323b3e02708e6bc011e475dc6..11a542c206e2b47514bfb93b9442eed2bc9d3b7c 100644 (file)
@@ -85,7 +85,7 @@ static __u32 tcp_v6_init_sequence(struct sock *sk, struct sk_buff *skb)
 }
 
 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;
index 7ec7a0008e7064e80633ed1092fa7d0fce91dc46..380122210f08a50169c2bc7657d2d9301db79903 100644 (file)
@@ -192,7 +192,13 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, int len,
                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 
index 0a636dd8f4801ce05f7be2c4074498814469cc9d..721ef622164112ef03279f16492438b1e36c8f35 100644 (file)
@@ -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 @@ ipxcfg_get_config_data(ipx_config_data *arg)
        
        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 @@ static int ipxitf_rcv(ipx_interface *intrfc, struct sk_buff *skb)
                /* 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 @@ ipx_first_free_socketnum(ipx_interface *intrfc)
        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 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
        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 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
        }
 
        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_bind(struct socket *sock, struct sockaddr *uaddr,int addr_len)
 }
 
 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_accept(struct socket *sock, struct socket *newsock, int flags)
 }
 
 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 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, int no
        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 @@ static int ipx_recvmsg(struct socket *sock, struct msghdr *msg, int size, int no
                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_select(struct socket *sock , int sel_type, select_table *wait)
 
 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 @@ ipx_proto_init(struct net_proto *pro)
        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");
 }
 
index f1a5c90d3151f0435d437ee83235cb69e160c46c..355b35f796e44bfb561c9bd19e4de6c9170ae561 100644 (file)
@@ -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 @@ static int open_map = 0;
  *     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 @@ static int netlink_err(struct sk_buff *skb)
  *     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 @@ static long netlink_write(struct inode * inode, struct file * file,
        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 @@ static struct file_operations netlink_fops = {
  *     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_netlink(void)
 
 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();
 }
 
index a4f9a84dd5691ec5aefc5513dceea4c822474858..b50051f4167716e679a3809584b29e39063e1315 100644 (file)
@@ -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 @@ static int nr_release(struct socket *sock, struct socket *peer)
        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 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        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 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
         */
        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_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 }
 
 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_accept(struct socket *sock, struct socket *newsock, int flags)
 }
 
 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 @@ static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size, int nob
        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 @@ static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size, int nob
         * 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 @@ static int nr_recvmsg(struct socket *sock, struct msghdr *msg, int size, int nob
                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 @@ void nr_proto_init(struct net_proto *pro)
 {
        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");
index 8bca8333684673d7662621d7cce8d65afd8998ca..aa856d5deb76214cace9d936be13ba6ea6df2cde 100644 (file)
@@ -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>
index 316ca7cdce386f83e15b760cecd81bf924966d3a..8f14318c1a0a113577b0733180633c2196b2c398 100644 (file)
@@ -759,7 +759,7 @@ static int rose_release(struct socket *sock, struct socket *peer)
        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 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        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 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        if ((user = ax25_findbyuid(current->euid)) == NULL) {
                if (ax25_uid_policy && !suser())
-                       return -EPERM;
+                       return -EACCES;
                user = source;
        }
 
@@ -807,7 +807,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        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_accept(struct socket *sock, struct socket *newsock, int flags)
 }
 
 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 @@ static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
        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 @@ static int rose_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                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 @@ void rose_proto_init(struct net_proto *pro)
 {
        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");
index 33b27c57d9e0cfb484d9190b13e9d8fae3655ad4..8f513b250c55e7de5e4afc7c7db3d293967bd598 100644 (file)
@@ -272,7 +272,7 @@ void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
 
 #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))
index 533fa8aa7ee333e91ed7ff41efe175db7d279e5c..0e00aa9306fd566125dd9411e4f6218289897a80 100644 (file)
@@ -159,7 +159,11 @@ int move_addr_to_user(void *kaddr, int klen, void *uaddr, int *ulen)
                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 @@ asmlinkage int sys_listen(int fd, int backlog)
  *     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 @@ asmlinkage int sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_ad
 /*
  *     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 @@ asmlinkage int sys_connect(int fd, struct sockaddr *uservaddr, int addrlen)
  *     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 @@ asmlinkage int sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockadd
  *     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 @@ asmlinkage int sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockadd
  *     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 @@ asmlinkage int sys_send(int fd, void * buff, int len, unsigned flags)
  *     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 @@ asmlinkage int sys_sendto(int fd, void * buff, int len, unsigned flags,
  *     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 @@ asmlinkage int sys_recv(int fd, void * ubuf, int size, unsigned flags)
  *     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 @@ asmlinkage int sys_sendmsg(int fd, struct msghdr *msg, unsigned int flags)
        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 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
        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 @@ asmlinkage int sys_recvmsg(int fd, struct msghdr *msg, unsigned int flags)
        {
                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 @@ void sock_init(void)
 {
        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. 
index 2361efbe8e36fc3c01e880666d5e791838719544..aaddee6beb6a0a685a238f45813a42ef5d308b9e 100644 (file)
@@ -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 unix_socket *unix_find_other(char *path, int *error)
 }
 
 
-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 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        
        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_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        
 }
 
-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 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags)
        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 int unix_sendmsg(struct socket *sock, struct msghdr *msg, int len, int no
  
 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 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
        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 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                        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 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                                                *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 @@ static struct proc_dir_entry proc_net_unix = {
 
 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);