diff --git a/net/net-2/README b/net/net-2/README new file mode 100644 index 00000000..e5061442 --- /dev/null +++ b/net/net-2/README @@ -0,0 +1,173 @@ + + Installation and Release Notes for NET-2 + + Version: 0.99.9 NET-2 Rev.B + + Sat, 08 May 14:07:00 1993 METDST + + + Fred N. van Kempen, + + + + + +PREFACE +This document describes what yet has to be done in NET-2, how to install +it, and more of that stuff. + + +NEWS +New items in this (Rev.B) release of NET-2: + +- about 48Kbyte worth of patches from Ross Biro. These should fix the + last "locking telnet" bugs, and some others. + +- many, many small fixes like those in the Makefiles. You all know what + I am talking about here. + +- rewrites of some system header files. + +- better ICMP. Not complete yet, but I am getting there. Slowly... + +- IP routing ("*** datagram routing IS NOW implemented ***"). Grin. + +- Patches from Fred Baumgarten (and, I assume, Gerald Heim) to clean + out some remaining 'volatile' keywords, and to prepare for a decent + netstat(8) program. + +- Mew distribution format, with this text included. Also: the *new* + net-base utils. *GRIN* + +- The "current" versions of Donald Becker's driver kit. Donald, can + you check && maintain please? + + +BUGS + +Several known bugs remain: + +- no IP fragmentation yet. We need 'mbuf's for that, on which work is + already being done. Will be after Linux 1.0, alas. + +- for the same reason: DDI is not finished yet. + +- ARP still acts weird. Any takers? + +- There seems to be a memory leak in the NET-2 code. Especially when + using the IP routing ("gatewaying") code, the leak appears. + +- No IP Option Processing yet. Partly because I don't yet feel like + it... + +INSTALLATION + + 1. Create a source directory called /usr/src/linux, and unpack + the standard (0.99 PL9) kernel source there. + + 2. Remove the old NET code with the commands: + + # rm -rf /usr/src/linux/net + + 3. Remove an old include file: + + # rm -f /usr/src/linux/include/linux/sock_ioctl.h + + 4. Unpack the "net-ksrc.tgz" file: + + # cd /usr/src/linux + # tar xfvz /tmp/net-ksrc.tgz + + This contains the new NET code. Then, patch the rest of the + kernel: + + # patch -p0 /conf/net/bootptab +lrwxrwxrwx 1 root staff 18 Mar 31 12:47 diphosts -> /conf/net/diphosts +lrwxrwxrwx 1 root staff 17 Mar 31 12:47 exports -> /conf/net/exports +lrwxrwxrwx 1 root staff 18 Mar 31 12:47 ftpusers -> /conf/net/ftpusers +lrwxrwxrwx 1 root staff 19 Mar 31 12:47 host.conf -> /conf/net/host.conf +lrwxrwxrwx 1 root staff 15 Mar 31 12:47 hosts -> /conf/net/hosts +lrwxrwxrwx 1 root staff 21 Mar 31 12:47 hosts.equiv -> /conf/net/hosts.equiv +lrwxrwxrwx 1 root staff 11 Mar 31 12:47 hosts.lpd -> hosts.equiv +-r-x------ 1 bin bin 6272 Apr 23 19:44 ifconfig +-r-x------ 1 bin bin 2692 Apr 23 19:44 iflink +-r-x------ 1 bin bin 3480 Apr 23 19:44 ifsetup +lrwxrwxrwx 1 root staff 19 Mar 31 12:47 inetd.conf -> /usr/etc/inetd.conf +lrwxrwxrwx 1 root staff 28 Mar 31 12:47 named.boot -> /conf/net/named.d/named.boot +-rw-r--r-- 1 root root 3 May 8 09:06 named.pid +lrwxrwxrwx 1 root staff 21 Mar 31 12:47 named.reload -> /usr/etc/named.reload +lrwxrwxrwx 1 root staff 22 Mar 31 12:47 named.restart -> /usr/etc/named.restart +lrwxrwxrwx 1 root staff 18 Mar 31 12:47 networks -> /conf/net/networks +lrwxrwxrwx 1 root staff 26 Mar 31 12:47 nntpserver -> /conf/news/nntp/nntpserver +lrwxrwxrwx 1 root staff 18 Mar 31 12:47 printcap -> /conf/net/printcap +lrwxrwxrwx 1 root staff 18 Mar 31 12:47 protocols -> /usr/etc/protocols +lrwxrwxrwx 1 root staff 21 Mar 31 12:47 resolv.conf -> /conf/net/resolv.conf +-r-x------ 1 bin bin 4492 Apr 23 19:44 route +lrwxrwxrwx 1 root staff 12 Mar 31 12:47 rpc -> /usr/etc/rpc +lrwxrwxrwx 1 root staff 17 Mar 31 12:47 services -> /usr/etc/services +lrwxrwxrwx 1 root staff 21 Mar 31 12:47 syslog.conf -> /conf/net/syslog.conf +-rw------- 1 root root 3 May 8 09:06 syslog.pid +-r-x------ 1 bin bin 27202 May 7 20:06 wdsetup + +Note, that in LINUX/Pro, all system config files are kept in /conf, and +all non-needed binaries (like the TCP/IP and RPC servers) are in /usr/etc. + +Have a look at the sample config files in the net-base distribution, and +pay close attention to the "rc.inet[12]" files, which set up your network. + + +SLIP + +For SLIP users: yes, SLIP works. Have a look at the new "dip" program +and its config file. Dip is not perfect yet, but I am sure the guys +at Demon.Co.Uk will change this. Right, guys? :-) + diff --git a/net/net-2/amd920824upl67.tar.gz b/net/net-2/amd920824upl67.tar.gz new file mode 100644 index 00000000..4c3c5df5 Binary files /dev/null and b/net/net-2/amd920824upl67.tar.gz differ diff --git a/net/net-2/dip-313.tar.z b/net/net-2/dip-313.tar.z new file mode 100644 index 00000000..7e4efb8f Binary files /dev/null and b/net/net-2/dip-313.tar.z differ diff --git a/net/net-2/dip334a.tar.gz b/net/net-2/dip334a.tar.gz new file mode 100644 index 00000000..61e2ad99 Binary files /dev/null and b/net/net-2/dip334a.tar.gz differ diff --git a/net/net-2/dip337-uri.tgz b/net/net-2/dip337-uri.tgz new file mode 100644 index 00000000..757f7132 Binary files /dev/null and b/net/net-2/dip337-uri.tgz differ diff --git a/net/net-2/net-0.20.tar.z b/net/net-2/net-0.20.tar.z new file mode 100644 index 00000000..285aa88c Binary files /dev/null and b/net/net-2/net-0.20.tar.z differ diff --git a/net/net-2/net-0.21.tar.z b/net/net-2/net-0.21.tar.z new file mode 100644 index 00000000..10c9c6f1 Binary files /dev/null and b/net/net-2/net-0.21.tar.z differ diff --git a/net/net-2/net-007.tar.z b/net/net-2/net-007.tar.z new file mode 100644 index 00000000..e2c31d2b Binary files /dev/null and b/net/net-2/net-007.tar.z differ diff --git a/net/net-2/net-base.tar.z b/net/net-2/net-base.tar.z new file mode 100644 index 00000000..373f9ce5 Binary files /dev/null and b/net/net-2/net-base.tar.z differ diff --git a/net/net-2/net-ext.tar.z b/net/net-2/net-ext.tar.z new file mode 100644 index 00000000..b95aa10f Binary files /dev/null and b/net/net-2/net-ext.tar.z differ diff --git a/net/net-2/net-kernel.cdif b/net/net-2/net-kernel.cdif new file mode 100644 index 00000000..4bc9e0e6 --- /dev/null +++ b/net/net-2/net-kernel.cdif @@ -0,0 +1,2382 @@ +diff -c --recursive --new-file /project/LINUX/Orig/Configure /project/LINUX/new/Configure +*** /project/LINUX/Orig/Configure Wed Mar 31 16:36:25 1993 +--- /project/LINUX/new/Configure Sat Apr 24 19:39:35 1993 +*************** +*** 1,27 **** + #! /bin/sh + # +! # This script is used to configure the linux kernel. +! # It's a fast hack - feel free to do something better. +! CONFIG=.config~ +! CONFIG_H=include/linux/autoconf.h +! > config.new +! echo "#" > $CONFIG +! echo "# Automatically generated make config: don't edit" >> $CONFIG +! echo "#" >> $CONFIG +! +! echo "/*" > $CONFIG_H +! echo " * Automatically generated C config: don't edit" >> $CONFIG_H +! echo " */" >> $CONFIG_H +! +! next="y" +! old="y" + +! while read i +! do + echo $i >> config.new +! echo >> $CONFIG +! echo >> $CONFIG_H +! echo + echo "#" >> $CONFIG + echo "/*" >> $CONFIG_H + echo "**" +--- 1,55 ---- + #! /bin/sh ++ # Configure This script is used to configure the Linux kernel. + # +! # Usage: Configure [-pro] +! # +! # Version; @(#)Configure 1.3 04/05/93 +! # +! # Author: Linus Torvalds, +! # + +! # Set variables to initial state. +! OPTS="" +! CONFIG=.config~ +! CONFIG_H=include/linux/autoconf.h +! next="y" +! old="y" +! +! # Check commandline arguments. +! >config.new +! while [ $# != 0 ] +! do +! case $1 in +! -pro) OPTS="UTS_SYSNAME \"LINUX/Pro\"" +! ;; +! *) echo "Usage: Configure [-pro]" +! exit 1 +! ;; +! esac +! shift +! done +! +! echo "#" > $CONFIG +! echo "# Automatically generated make config: don't edit" >> $CONFIG +! echo "#" >> $CONFIG +! +! echo "/*" > $CONFIG_H +! echo " * Automatically generated C config: don't edit" >> $CONFIG_H +! echo " */" >> $CONFIG_H +! +! # First of all, emit the "special" features to . +! if [ "${OPTS}" ] +! then +! echo "#define ${OPTS}" >> $CONFIG_H +! fi +! +! # Read our standard input (which is the CONFIG.IN file). +! while read i +! do + echo $i >> config.new +! echo >> $CONFIG +! echo >> $CONFIG_H +! echo + echo "#" >> $CONFIG + echo "/*" >> $CONFIG_H + echo "**" +*************** +*** 69,83 **** + then + next="n" + fi +! done +! +! mv config.new config.in + +! echo +! echo "The linux kernel is now hopefully configured for your setup." +! echo "Check the top-level Makefile for additional configuration," +! echo "and do a 'make dep ; make clean' if you want to be sure all" +! echo "the files are correctly re-made" +! echo + +! exit 0 +--- 97,110 ---- + then + next="n" + fi +! done +! mv config.new config.in + +! echo +! echo "The linux kernel is now hopefully configured for your setup." +! echo "Check the top-level Makefile for additional configuration," +! echo "and do a 'make dep ; make clean' if you want to be sure all" +! echo "the files are correctly re-made" +! echo + +! exit 0 +diff -c --recursive --new-file /project/LINUX/Orig/Makefile /project/LINUX/new/Makefile +*** /project/LINUX/Orig/Makefile Thu Apr 22 23:10:11 1993 +--- /project/LINUX/new/Makefile Tue Apr 27 12:12:19 1993 +*************** +*** 68,75 **** + # The number is the same as you would ordinarily press at bootup. + # + +! SVGA_MODE= -DSVGA_MODE=3 + + # + # standard CFLAGS + # +--- 68,78 ---- + # The number is the same as you would ordinarily press at bootup. + # + +! SVGA_MODE= -DSVGA_MODE=NORMAL_VGA + ++ # Special options. ++ OPTS = -pro ++ + # + # standard CFLAGS + # +*************** +*** 99,111 **** + AR =ar + STRIP =strip + +! ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o net/net.o + FILESYSTEMS =fs/filesystems.a + DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \ + kernel/blk_drv/scsi/scsi.a kernel/chr_drv/sound/sound.a + MATH =kernel/FPU-emu/math.a + LIBS =lib/lib.a +! SUBDIRS =kernel mm fs net lib + + KERNELHDRS =/usr/src/linux/include + +--- 102,120 ---- + AR =ar + STRIP =strip + +! #ifdef CONFIG_TCPIP +! NETDIR = net-1 +! #endif +! #ifdef CONFIG_INET +! NETDIR = net-2 +! #endif +! ARCHIVES =kernel/kernel.o mm/mm.o fs/fs.o $(NETDIR)/net.o + FILESYSTEMS =fs/filesystems.a + DRIVERS =kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \ + kernel/blk_drv/scsi/scsi.a kernel/chr_drv/sound/sound.a + MATH =kernel/FPU-emu/math.a + LIBS =lib/lib.a +! SUBDIRS =kernel mm fs $(NETDIR) lib + + KERNELHDRS =/usr/src/linux/include + +*************** +*** 125,131 **** + /etc/lilo/install + + config: +! sh Configure < config.in + mv .config~ .config + $(MAKE) soundconf + +--- 134,140 ---- + /etc/lilo/install + + config: +! sh Configure $(OPTS) < config.in + mv .config~ .config + $(MAKE) soundconf + +*************** +*** 139,146 **** + + tools/version.h: $(CONFIGURE) Makefile + @./makever.sh +! @echo \#define UTS_RELEASE \"0.99.pl9-`cat .version`\" > tools/version.h +! @echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h + @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h + @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h + @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h +--- 148,155 ---- + + tools/version.h: $(CONFIGURE) Makefile + @./makever.sh +! @echo \#define UTS_RELEASE \"0.99.9-`cat .version`\" > tools/version.h +! @echo \#define UTS_VERSION \"`date`\" >> tools/version.h + @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h + @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h + @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h +diff -c --recursive --new-file /project/LINUX/Orig/config.in /project/LINUX/new/config.in +*** /project/LINUX/Orig/config.in Fri Apr 23 20:41:46 1993 +--- /project/LINUX/new/config.in Sat May 8 14:36:52 1993 +*************** +*** 1,53 **** + General setup + . + Kernel math emulation +! CONFIG_MATH_EMULATION y/n n + Normal harddisk support + CONFIG_BLK_DEV_HD y/n y + XT harddisk support + CONFIG_BLK_DEV_XD y/n n +! TCP/IP +! CONFIG_TCPIP y/n y + Kernel profiling support + CONFIG_PROFILE y/n n + Limit memory to low 16MB +! CONFIG_MAX_16M y/n n + Use -m486 flag for 486-specific optimizations + CONFIG_M486 y/n y + : + SCSI support + . + SCSI support? +! CONFIG_SCSI y/n n + : + SCSI support type (disk, tape, CDrom) + . + Scsi disk support +! CONFIG_BLK_DEV_SD y/n n + Scsi tape support +! CONFIG_BLK_DEV_ST y/n n + Scsi CDROM support +! CONFIG_BLK_DEV_SR y/n n + . + SCSI low-level drivers + . + Adaptec AHA1542 support +! CONFIG_SCSI_AHA1542 y/n n + Adaptec AHA1740 support +! CONFIG_SCSI_AHA1740 y/n n + Future Domain SCSI support +! CONFIG_SCSI_FUTURE_DOMAIN y/n n + Seagate ST-02 and Future Domain TMC-8xx SCSI support +! CONFIG_SCSI_SEAGATE y/n n + UltraStor SCSI support +! CONFIG_SCSI_ULTRASTOR y/n n + 7000FASST SCSI support +! CONFIG_SCSI_7000FASST y/n n + . + Filesystems + . + Mount root initially readonly + CONFIG_ROOT_RDONLY y/n n + Standard (minix) fs support + CONFIG_MINIX_FS y/n y + Extended fs support +--- 1,55 ---- + General setup + . + Kernel math emulation +! CONFIG_MATH_EMULATION y/n y + Normal harddisk support + CONFIG_BLK_DEV_HD y/n y + XT harddisk support + CONFIG_BLK_DEV_XD y/n n +! TCP/IP version 1 Networking +! CONFIG_TCPIP y/n n +! TCP/IP version 2 Networking +! CONFIG_INET y/n y + Kernel profiling support + CONFIG_PROFILE y/n n + Limit memory to low 16MB +! CONFIG_MAX_16M y/n y + Use -m486 flag for 486-specific optimizations + CONFIG_M486 y/n y + : + SCSI support + . + SCSI support? +! CONFIG_SCSI y/n y + : + SCSI support type (disk, tape, CDrom) + . + Scsi disk support +! CONFIG_BLK_DEV_SD y/n y + Scsi tape support +! CONFIG_BLK_DEV_ST y/n y + Scsi CDROM support +! CONFIG_BLK_DEV_SR y/n y + . + SCSI low-level drivers + . + Adaptec AHA1542 support +! CONFIG_SCSI_AHA1542 y/n y + Adaptec AHA1740 support +! CONFIG_SCSI_AHA1740 y/n y + Future Domain SCSI support +! CONFIG_SCSI_FUTURE_DOMAIN y/n y + Seagate ST-02 and Future Domain TMC-8xx SCSI support +! CONFIG_SCSI_SEAGATE y/n y + UltraStor SCSI support +! CONFIG_SCSI_ULTRASTOR y/n y + 7000FASST SCSI support +! CONFIG_SCSI_7000FASST y/n y + . + Filesystems + . + Mount root initially readonly + CONFIG_ROOT_RDONLY y/n n + Standard (minix) fs support + CONFIG_MINIX_FS y/n y + Extended fs support +*************** +*** 55,78 **** + Second extended fs support + CONFIG_EXT2_FS y/n n + xiafs filesystem support +! CONFIG_XIA_FS y/n n + msdos fs support + CONFIG_MSDOS_FS y/n y + /proc filesystem support + CONFIG_PROC_FS y/n y + NFS filesystem support +! CONFIG_NFS_FS y/n n + ISO9660 cdrom filesystem support +! CONFIG_ISO9660_FS y/n n + . + Various character device drivers.. + . + Keyboard meta-key sends ESC-prefix + CONFIG_KBD_META y/n y + Autoconfigure serial IRQ lines at bootup + CONFIG_AUTO_IRQ y/n n + AST Fourport serial driver support + CONFIG_AST_FOURPORT y/n n + Accent Async 4 serial support + CONFIG_ACCENT_ASYNC y/n n + Logitech busmouse support +--- 55,78 ---- + Second extended fs support + CONFIG_EXT2_FS y/n n + xiafs filesystem support +! CONFIG_XIA_FS y/n y + msdos fs support + CONFIG_MSDOS_FS y/n y + /proc filesystem support + CONFIG_PROC_FS y/n y + NFS filesystem support +! CONFIG_NFS_FS y/n y + ISO9660 cdrom filesystem support +! CONFIG_ISO9660_FS y/n y + . + Various character device drivers.. + . + Keyboard meta-key sends ESC-prefix + CONFIG_KBD_META y/n n + Autoconfigure serial IRQ lines at bootup + CONFIG_AUTO_IRQ y/n n + AST Fourport serial driver support + CONFIG_AST_FOURPORT y/n y + Accent Async 4 serial support + CONFIG_ACCENT_ASYNC y/n n + Logitech busmouse support +diff -c --recursive --new-file /project/LINUX/Orig/fs/nfs/proc.c /project/LINUX/new/fs/nfs/proc.c +*** /project/LINUX/Orig/fs/nfs/proc.c Mon Mar 1 10:16:26 1993 +--- /project/LINUX/new/fs/nfs/proc.c Sat Apr 24 23:53:27 1993 +*************** +*** 16,21 **** +--- 16,22 ---- + #define NFS_PROC_DEBUG + #endif + ++ #include + #include + #include + #include +*************** +*** 24,30 **** +--- 25,36 ---- + #include + #include + ++ #ifdef CONFIG_TCPIP + #include ++ #endif ++ #ifdef CONFIG_INET ++ #include ++ #endif + + #ifdef NFS_PROC_DEBUG + static int proc_debug = 0; +diff -c --recursive --new-file /project/LINUX/Orig/fs/nfs/sock.c /project/LINUX/new/fs/nfs/sock.c +*** /project/LINUX/Orig/fs/nfs/sock.c Mon Mar 1 10:16:26 1993 +--- /project/LINUX/new/fs/nfs/sock.c Sat Apr 24 21:15:57 1993 +*************** +*** 6,11 **** +--- 6,12 ---- + * low-level nfs remote procedure call interface + */ + ++ #include + #include + #include + #include +*************** +*** 13,21 **** + #include + #include + + #include +- + #include "../../net/kern_sock.h" + + extern struct socket *socki_lookup(struct inode *inode); + +--- 14,28 ---- + #include + #include + ++ #ifdef CONFIG_TCPIP /* FIXME: old-style NET */ + #include + #include "../../net/kern_sock.h" ++ #endif ++ #ifdef CONFIG_INET /* FIXME: new-style NET */ ++ #include ++ #include ++ #endif ++ + + extern struct socket *socki_lookup(struct inode *inode); + +diff -c --recursive --new-file /project/LINUX/Orig/fs/proc/Makefile /project/LINUX/new/fs/proc/Makefile +*** /project/LINUX/Orig/fs/proc/Makefile Fri Dec 25 21:34:36 1992 +--- /project/LINUX/new/fs/proc/Makefile Sat Apr 24 19:39:35 1993 +*************** +*** 14,20 **** + .s.o: + $(AS) -o $*.o $< + +! OBJS= inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o + + proc.o: $(OBJS) + $(LD) -r -o proc.o $(OBJS) +--- 14,20 ---- + .s.o: + $(AS) -o $*.o $< + +! OBJS= inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o + + proc.o: $(OBJS) + $(LD) -r -o proc.o $(OBJS) +diff -c --recursive --new-file /project/LINUX/Orig/fs/proc/inode.c /project/LINUX/new/fs/proc/inode.c +*** /project/LINUX/Orig/fs/proc/inode.c Thu Apr 8 06:17:54 1993 +--- /project/LINUX/new/fs/proc/inode.c Sat Apr 24 19:39:35 1993 +*************** +*** 100,111 **** + inode->i_op = &proc_root_inode_operations; + return; + } +! if (!pid) { + inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_array_inode_operations; +! if (ino == 5) { +! inode->i_mode = S_IFREG | 0400; +! inode->i_op = &proc_kmsg_inode_operations; + } + return; + } +--- 100,125 ---- + inode->i_op = &proc_root_inode_operations; + return; + } +! if ((ino >= 128) && (ino <= 160)) { /* files within /proc/net */ + inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_net_inode_operations; +! return; +! } +! if (!pid) { +! switch (ino) { +! case 5: +! inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_kmsg_inode_operations; +! break; +! case 8: /* for the net directory */ +! inode->i_mode = S_IFDIR | 0555; +! inode->i_nlink = 2; +! inode->i_op = &proc_net_inode_operations; +! break; +! default: +! inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_array_inode_operations; +! break; + } + return; + } +diff -c --recursive --new-file /project/LINUX/Orig/fs/proc/net.c /project/LINUX/new/fs/proc/net.c +*** /project/LINUX/Orig/fs/proc/net.c +--- /project/LINUX/new/fs/proc/net.c Sat Apr 24 21:05:18 1993 +*************** +*** 0 **** +--- 1,211 ---- ++ /* ++ * linux/fs/proc/net.c ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * ++ * gjh 3/'93 heim@peanuts.informatik.uni-tuebingen.de (Gerald J. Heim) ++ * most of this file is stolen from base.c ++ * it works, but you shouldn't use it as a guideline ++ * for new proc-fs entries. once i'll make it better. ++ * fvk 3/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen) ++ * cleaned up the whole thing, moved "net" specific code to ++ * the NET kernel layer (where it belonged in the first place). ++ * Michael K. Johnson (johnsonm@stolaf.edu) 3/93 ++ * Added support from my previous inet.c. Cleaned things up ++ * quite a bit, modularized the code. ++ * fvk 4/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen) ++ * Renamed "route_get_info()" to "rt_get_info()" for consistency. ++ * ++ * proc net directory handling functions ++ */ ++ #include ++ ++ #include ++ ++ #include ++ #include ++ #include ++ #include ++ ++ /* forward references */ ++ static int proc_readnet(struct inode * inode, struct file * file, ++ char * buf, int count); ++ static int proc_readnetdir(struct inode *, struct file *, ++ struct dirent *, int); ++ static int proc_lookupnet(struct inode *,const char *,int,struct inode **); ++ ++ /* the get_*_info() functions are in the net code, and are configured ++ in via the standard mechanism... */ ++ #ifdef CONFIG_INET ++ extern int unix_get_info(char *); ++ extern int tcp_get_info(char *); ++ extern int udp_get_info(char *); ++ extern int raw_get_info(char *); ++ extern int arp_get_info(char *); ++ extern int dev_get_info(char *); ++ extern int rt_get_info(char *); ++ #endif /* CONFIG_INET */ ++ ++ ++ static struct file_operations proc_net_operations = { ++ NULL, /* lseek - default */ ++ proc_readnet, /* read - bad */ ++ NULL, /* write - bad */ ++ proc_readnetdir, /* readdir */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ NULL, /* mmap */ ++ NULL, /* no special open code */ ++ NULL, /* no special release code */ ++ NULL /* can't fsync */ ++ }; ++ ++ /* ++ * proc directories can do almost nothing.. ++ */ ++ struct inode_operations proc_net_inode_operations = { ++ &proc_net_operations, /* default net directory file-ops */ ++ NULL, /* create */ ++ proc_lookupnet, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ NULL, /* bmap */ ++ NULL, /* truncate */ ++ NULL /* permission */ ++ }; ++ ++ static struct proc_dir_entry net_dir[] = { ++ { 1,2,".." }, ++ { 8,1,"." } ++ #ifdef CONFIG_INET ++ ,{ 128,4,"unix" }, ++ { 129,3,"arp" }, ++ { 130,5,"route" }, ++ { 131,3,"dev" }, ++ { 132,3,"raw" }, ++ { 133,3,"tcp" }, ++ { 134,3,"udp" } ++ #endif /* CONFIG_INET */ ++ }; ++ ++ #define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0]))) ++ ++ ++ static int proc_lookupnet(struct inode * dir,const char * name, int len, ++ struct inode ** result) ++ { ++ unsigned int ino; ++ int i; ++ ++ *result = NULL; ++ if (!dir) ++ return -ENOENT; ++ if (!S_ISDIR(dir->i_mode)) { ++ iput(dir); ++ return -ENOENT; ++ } ++ i = NR_NET_DIRENTRY; ++ while (i-- > 0 && !proc_match(len,name,net_dir+i)) ++ /* nothing */; ++ if (i < 0) { ++ iput(dir); ++ return -ENOENT; ++ } ++ ino = net_dir[i].low_ino; ++ if (!(*result = iget(dir->i_sb,ino))) { ++ iput(dir); ++ return -ENOENT; ++ } ++ iput(dir); ++ return 0; ++ } ++ ++ static int proc_readnetdir(struct inode * inode, struct file * filp, ++ struct dirent * dirent, int count) ++ { ++ struct proc_dir_entry * de; ++ unsigned int ino; ++ int i,j; ++ ++ if (!inode || !S_ISDIR(inode->i_mode)) ++ return -EBADF; ++ ino = inode->i_ino; ++ if (((unsigned) filp->f_pos) < NR_NET_DIRENTRY) { ++ de = net_dir + filp->f_pos; ++ filp->f_pos++; ++ i = de->namelen; ++ ino = de->low_ino; ++ put_fs_long(ino, &dirent->d_ino); ++ put_fs_word(i,&dirent->d_reclen); ++ put_fs_byte(0,i+dirent->d_name); ++ j = i; ++ while (i--) ++ put_fs_byte(de->name[i], i+dirent->d_name); ++ return j; ++ } ++ return 0; ++ } ++ ++ ++ static int proc_readnet(struct inode * inode, struct file * file, ++ char * buf, int count) ++ { ++ char * page; ++ int length; ++ int end; ++ unsigned int ino; ++ ++ if (count < 0) ++ return -EINVAL; ++ page = (char *) get_free_page(GFP_KERNEL); ++ if (!page) ++ return -ENOMEM; ++ ino = inode->i_ino; ++ switch (ino) { ++ #ifdef CONFIG_INET ++ case 128: ++ length = unix_get_info(page); ++ break; ++ case 129: ++ length = arp_get_info(page); ++ break; ++ case 130: ++ length = rt_get_info(page); ++ break; ++ case 131: ++ length = dev_get_info(page); ++ break; ++ case 132: ++ length = raw_get_info(page); ++ break; ++ case 133: ++ length = tcp_get_info(page); ++ break; ++ case 134: ++ length = udp_get_info(page); ++ break; ++ #endif /* CONFIG_INET */ ++ default: ++ free_page((unsigned long) page); ++ return -EBADF; ++ } ++ if (file->f_pos >= length) { ++ free_page((unsigned long) page); ++ return 0; ++ } ++ if (count + file->f_pos > length) ++ count = length - file->f_pos; ++ end = count + file->f_pos; ++ memcpy_tofs(buf, page + file->f_pos, count); ++ free_page((unsigned long) page); ++ file->f_pos = end; ++ return count; ++ ++ } +diff -c --recursive --new-file /project/LINUX/Orig/fs/proc/root.c /project/LINUX/new/fs/proc/root.c +*** /project/LINUX/Orig/fs/proc/root.c Sun Feb 28 11:59:43 1993 +--- /project/LINUX/new/fs/proc/root.c Sat Apr 24 19:39:35 1993 +*************** +*** 58,64 **** + { 4,7,"meminfo" }, + { 5,4,"kmsg" }, + { 6,7,"version" }, +! { 7,4,"self" } /* will change inode # */ + }; + + #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0]))) +--- 58,65 ---- + { 4,7,"meminfo" }, + { 5,4,"kmsg" }, + { 6,7,"version" }, +! { 7,4,"self" }, /* will change inode # */ +! { 8,3,"net" } + }; + + #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0]))) +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/ddi.h /project/LINUX/new/include/linux/ddi.h +*** /project/LINUX/Orig/include/linux/ddi.h +--- /project/LINUX/new/include/linux/ddi.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,79 ---- ++ /* ++ * ddi.h Define the structure for linking in I/O drivers into the ++ * operating system kernel. This method is currently only ++ * used by NET layer drivers, but it will be expanded into ++ * a link methos for ALL kernel-resident device drivers. ++ * ++ * Version: @(#)ddi.h 1.0.2 04/22/93 ++ * ++ * Author: Fred N. van Kempen, ++ */ ++ #ifndef _LINUX_DDI_H ++ #define _LINUX_DDI_H ++ ++ ++ /* DDI control block flags. */ ++ #define DDI_FREADY 0x10000000 /* device is initialized */ ++ #define DDI_FPRESENT 0x20000000 /* device hardware is present */ ++ #define DDI_FBLKDEV 0x00000001 /* device has a BLK spec. file */ ++ #define DDI_FCHRDEV 0x00000002 /* device has a CHR spec. file */ ++ ++ /* Various constants. */ ++ #define DDI_MAXNAME 16 /* length of a DDI ID string */ ++ ++ ++ /* This structure is used to set up a DDI driver. */ ++ struct ddconf { ++ int ioaddr; /* main I/O (port) address */ ++ int ioaux; /* auxiliary I/O (HD, AST) */ ++ int irq; /* IRQ channel */ ++ int dma; /* DMA channel to use */ ++ unsigned long memsize; /* size of onboard memory */ ++ unsigned long memaddr; /* base address of memory */ ++ }; ++ ++ ++ /* The DDI device control block. */ ++ struct ddi_device { ++ char *title; /* title of the driver */ ++ char name[DDI_MAXNAME]; /* unit name of the I/O driver */ ++ short int unit; /* unit number of this driver */ ++ short int nunits; /* number of units in driver */ ++ int (*init)(struct ddi_device *); /* initialization func */ ++ int (*handler)(int, ...); /* command handler */ ++ short int major; /* driver major dev number */ ++ short int minor; /* driver minor dev number */ ++ unsigned long flags; /* various flags */ ++ struct ddconf config; /* driver HW setup */ ++ }; ++ ++ ++ /* This structure is used to set up networking protocols. */ ++ struct ddi_proto { ++ char *name; /* protocol name */ ++ void (*init)(struct ddi_proto *); /* initialization func */ ++ }; ++ ++ ++ /* This structure is used to link a STREAMS interface. */ ++ struct iflink { ++ char id[DDI_MAXNAME]; /* DDI ID string */ ++ char stream[DDI_MAXNAME]; /* STREAMS interface name */ ++ int family; /* address (protocol) family */ ++ unsigned int flags; /* any flags needed (unused) */ ++ }; ++ ++ ++ /* DDI control requests. */ ++ #define DDIOCSDBG 0x9000 /* set DDI debug level */ ++ #define DDIOCGNAME 0x9001 /* get DDI ID name */ ++ #define DDIOCGCONF 0x9002 /* get DDI HW config */ ++ #define DDIOCSCONF 0x9003 /* set DDI HW config */ ++ ++ ++ /* DDI global functions. */ ++ extern void ddi_init(void); ++ extern struct ddi_device *ddi_map(const char *id); ++ ++ ++ #endif /* _LINUX_DDI_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/fs.h /project/LINUX/new/include/linux/fs.h +*** /project/LINUX/Orig/include/linux/fs.h Thu Apr 22 10:06:20 1993 +--- /project/LINUX/new/include/linux/fs.h Sat Apr 24 19:39:35 1993 +*************** +*** 21,31 **** + * recompiled to take full advantage of the new limits.. + */ + #undef NR_OPEN +! #define NR_OPEN 256 /* don't change - fd_set etc depend on this */ + +! #define NR_INODE 256 /* this should be bigger than NR_FILE */ +! #define NR_FILE 128 /* this can well be larger on a larger system */ +! #define NR_SUPER 16 + #define NR_HASH 997 + #define NR_FILE_LOCKS 32 + #define BLOCK_SIZE 1024 +--- 21,31 ---- + * recompiled to take full advantage of the new limits.. + */ + #undef NR_OPEN +! #define NR_OPEN 256 + +! #define NR_INODE 1024 /* changed for LINUX/Pro - FvK */ +! #define NR_FILE 512 /* changed for LINUX/Pro - FvK */ +! #define NR_SUPER 32 /* changed for LINUX/Pro - FvK */ + #define NR_HASH 997 + #define NR_FILE_LOCKS 32 + #define BLOCK_SIZE 1024 +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/icmp.h /project/LINUX/new/include/linux/icmp.h +*** /project/LINUX/Orig/include/linux/icmp.h +--- /project/LINUX/new/include/linux/icmp.h Wed Apr 28 15:27:13 1993 +*************** +*** 0 **** +--- 1,81 ---- ++ /* ++ * 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 ICMP protocol. ++ * ++ * Version: @(#)icmp.h 1.0.3 04/28/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_ICMP_H ++ #define _LINUX_ICMP_H ++ ++ #define ICMP_ECHOREPLY 0 /* Echo Reply */ ++ #define ICMP_DEST_UNREACH 3 /* Destination Unreachable */ ++ #define ICMP_SOURCE_QUENCH 4 /* Source Quench */ ++ #define ICMP_REDIRECT 5 /* Redirect (change route) */ ++ #define ICMP_ECHO 8 /* Echo Request */ ++ #define ICMP_TIME_EXCEEDED 11 /* Time Exceeded */ ++ #define ICMP_PARAMETERPROB 12 /* Parameter Problem */ ++ #define ICMP_TIMESTAMP 13 /* Timestamp Request */ ++ #define ICMP_TIMESTAMPREPLY 14 /* Timestamp Reply */ ++ #define ICMP_INFO_REQUEST 15 /* Information Request */ ++ #define ICMP_INFO_REPLY 16 /* Information Reply */ ++ #define ICMP_ADDRESS 17 /* Address Mask Request */ ++ #define ICMP_ADDRESSREPLY 18 /* Address Mask Reply */ ++ ++ ++ /* Codes for UNREACH. */ ++ #define ICMP_NET_UNREACH 0 /* Network Unreachable */ ++ #define ICMP_HOST_UNREACH 1 /* Host Unreachable */ ++ #define ICMP_PROT_UNREACH 2 /* Protocol Unreachable */ ++ #define ICMP_PORT_UNREACH 3 /* Port Unreachable */ ++ #define ICMP_FRAG_NEEDED 4 /* Fragmentation Needed/DF set */ ++ #define ICMP_SR_FAILED 5 /* Source Route failed */ ++ #define ICMP_NET_UNKNOWN 6 ++ #define ICMP_HOST_UNKNOWN 7 ++ #define ICMP_HOST_ISOLATED 8 ++ #define ICMP_NET_ANO 9 ++ #define ICMP_HOST_ANO 10 ++ #define ICMP_NET_UNR_TOS 11 ++ #define ICMP_HOST_UNR_TOS 12 ++ ++ /* Codes for REDIRECT. */ ++ #define ICMP_REDIR_NET 0 /* Redirect Net */ ++ #define ICMP_REDIR_HOST 1 /* Redirect Host */ ++ #define ICMP_REDIR_NETTOS 2 /* Redirect Net for TOS */ ++ #define ICMP_REDIR_HOSTTOS 3 /* Redirect Host for TOS */ ++ ++ /* Codes for TIME_EXCEEDED. */ ++ #define ICMP_EXC_TTL 0 /* TTL count exceeded */ ++ #define ICMP_EXC_FRAGTIME 1 /* Fragment Reass time exceeded */ ++ ++ ++ struct icmphdr { ++ unsigned char type; ++ unsigned char code; ++ unsigned short checksum; ++ union { ++ struct { ++ unsigned short id; ++ unsigned short sequence; ++ } echo; ++ unsigned long gateway; ++ } un; ++ }; ++ ++ ++ struct icmp_err { ++ int errno; ++ unsigned fatal:1; ++ }; ++ ++ ++ #endif /* _LINUX_ICMP_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/if.h /project/LINUX/new/include/linux/if.h +*** /project/LINUX/Orig/include/linux/if.h +--- /project/LINUX/new/include/linux/if.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,147 ---- ++ /* ++ * 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 INET interface module. ++ * ++ * Version: @(#)if.h 1.0.2 04/18/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 ++ * Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_H ++ #define _LINUX_IF_H ++ ++ #include /* for "caddr_t" et al */ ++ #include /* for "struct sockaddr" et al */ ++ ++ ++ /* Structure defining a queue for a network interface. */ ++ struct ifnet { ++ char *if_name; /* name, e.g. ``en'' or ``lo'' */ ++ short if_unit; /* sub-unit for device driver */ ++ short if_mtu; /* maximum transmission unit */ ++ short if_flags; /* up/down, broadcast, etc. */ ++ short if_timer; /* time 'til if_watchdog called */ ++ int if_metric; /* routing metric (not used) */ ++ struct ifaddr *if_addrlist; /* linked list of addrs per if */ ++ struct ifqueue { ++ #ifdef not_yet_in_linux ++ struct mbuf *ifq_head; ++ struct mbuf *ifq_tail; ++ int ifq_len; ++ int ifq_maxlen; ++ int ifq_drops; ++ #endif ++ } if_snd; /* output queue */ ++ ++ /* Procedure handles. */ ++ int (*if_init)(); /* init routine */ ++ int (*if_output)(); /* output routine */ ++ int (*if_ioctl)(); /* ioctl routine */ ++ int (*if_reset)(); /* bus reset routine */ ++ int (*if_watchdog)(); /* timer routine */ ++ ++ /* Generic interface statistics. */ ++ int if_ipackets; /* packets recv'd on interface */ ++ int if_ierrors; /* input errors on interface */ ++ int if_opackets; /* packets sent on interface */ ++ int if_oerrors; /* output errors on interface */ ++ int if_collisions; /* collisions on CSMA i'faces */ ++ ++ /* Linked list: pointer to next interface. */ ++ struct ifnet *if_next; ++ }; ++ ++ /* Standard interface flags. */ ++ #define IFF_UP 0x1 /* interface is up */ ++ #define IFF_BROADCAST 0x2 /* broadcast address valid */ ++ #define IFF_DEBUG 0x4 /* turn on debugging */ ++ #define IFF_LOOPBACK 0x8 /* is a loopback net */ ++ #define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ ++ #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ ++ #define IFF_RUNNING 0x40 /* resources allocated */ ++ #define IFF_NOARP 0x80 /* no ARP protocol */ ++ ++ /* These are not yet used: */ ++ #define IFF_PROMISC 0x100 /* recve all packets */ ++ #define IFF_ALLMULTI 0x200 /* recve all multicast packets */ ++ ++ ++ /* ++ * The ifaddr structure contains information about one address ++ * of an interface. They are maintained by the different address ++ * families, are allocated and attached when an address is set, ++ * and are linked together so all addresses for an interface can ++ * be located. ++ */ ++ struct ifaddr { ++ struct sockaddr ifa_addr; /* address of interface */ ++ union { ++ struct sockaddr ifu_broadaddr; ++ struct sockaddr ifu_dstaddr; ++ } ifa_ifu; ++ struct iface *ifa_ifp; /* back-pointer to interface */ ++ struct ifaddr *ifa_next; /* next address for interface */ ++ }; ++ #define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ ++ #define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ ++ ++ /* ++ * Interface request structure used for socket ++ * ioctl's. All interface ioctl's must have parameter ++ * definitions which begin with ifr_name. The ++ * remainder may be interface specific. ++ */ ++ struct ifreq { ++ #define IFNAMSIZ 16 ++ char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ ++ union { ++ struct sockaddr ifru_addr; ++ struct sockaddr ifru_dstaddr; ++ struct sockaddr ifru_broadaddr; ++ struct sockaddr ifru_netmask; ++ short ifru_flags; ++ int ifru_metric; ++ int ifru_mtu; ++ caddr_t ifru_data; ++ } ifr_ifru; ++ }; ++ #define ifr_addr ifr_ifru.ifru_addr /* address */ ++ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ ++ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ ++ #define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ ++ #define ifr_flags ifr_ifru.ifru_flags /* flags */ ++ #define ifr_metric ifr_ifru.ifru_metric /* metric */ ++ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ ++ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ ++ ++ /* ++ * Structure used in SIOCGIFCONF request. ++ * Used to retrieve interface configuration ++ * for machine (useful for programs which ++ * must know all networks accessible). ++ */ ++ struct ifconf { ++ int ifc_len; /* size of buffer */ ++ union { ++ caddr_t ifcu_buf; ++ struct ifreq *ifcu_req; ++ } ifc_ifcu; ++ }; ++ #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ ++ #define ifc_req ifc_ifcu.ifcu_req /* array of structures */ ++ ++ ++ /* BSD UNIX expects to find these here, so here we go: */ ++ #include ++ #include ++ ++ #endif /* _NET_IF_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/if_arp.h /project/LINUX/new/include/linux/if_arp.h +*** /project/LINUX/Orig/include/linux/if_arp.h +--- /project/LINUX/new/include/linux/if_arp.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,83 ---- ++ /* ++ * 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 ARP (RFC 826) protocol. ++ * ++ * Version: @(#)if_arp.h 1.0.1 04/16/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 ++ * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source. ++ * Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_ARP_H ++ #define _LINUX_IF_ARP_H ++ ++ /* ARP protocol HARDWARE identifiers. */ ++ #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */ ++ #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ ++ #define ARPHRD_EETHER 2 /* Experimental Ethernet */ ++ #define ARPHRD_AX25 3 /* AX.25 Level 2 */ ++ #define ARPHRD_PRONET 4 /* PROnet token ring */ ++ #define ARPHRD_CHAOS 5 /* Chaosnet */ ++ #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet- huh? */ ++ #define ARPHRD_ARCNET 7 /* ARCnet */ ++ #define ARPHRD_APPLETLK 8 /* APPLEtalk */ ++ ++ /* ARP protocol opcodes. */ ++ #define ARPOP_REQUEST 1 /* ARP request */ ++ #define ARPOP_REPLY 2 /* ARP reply */ ++ #define ARPOP_RREQUEST 3 /* RARP request */ ++ #define ARPOP_RREPLY 4 /* RARP reply */ ++ ++ ++ /* ++ * Address Resolution Protocol. ++ * ++ * See RFC 826 for protocol description. ARP packets are variable ++ * in size; the arphdr structure defines the fixed-length portion. ++ * Protocol type values are the same as those for 10 Mb/s Ethernet. ++ * It is followed by the variable-sized fields ar_sha, arp_spa, ++ * arp_tha and arp_tpa in that order, according to the lengths ++ * specified. Field names used correspond to RFC 826. ++ */ ++ struct arphdr { ++ unsigned short ar_hrd; /* format of hardware address */ ++ unsigned short ar_pro; /* format of protocol address */ ++ unsigned char ar_hln; /* length of hardware address */ ++ unsigned char ar_pln; /* length of protocol address */ ++ unsigned short ar_op; /* ARP opcode (command) */ ++ ++ /* The rest is variable in size, according to the sizes above. */ ++ #if 0 ++ unsigned char ar_sha[]; /* sender hardware address */ ++ unsigned char ar_spa[]; /* sender protocol address */ ++ unsigned char ar_tha[]; /* target hardware address */ ++ unsigned char ar_tpa[]; /* target protocol address */ ++ #endif /* not actually included! */ ++ }; ++ ++ ++ /* ARP ioctl request. */ ++ struct arpreq { ++ struct sockaddr arp_pa; /* protocol address */ ++ struct sockaddr arp_ha; /* hardware address */ ++ int arp_flags; /* flags */ ++ }; ++ ++ /* ARP Flag values. */ ++ #define ATF_INUSE 0x01 /* entry in use */ ++ #define ATF_COM 0x02 /* completed entry (ha valid) */ ++ #define ATF_PERM 0x04 /* permanent entry */ ++ #define ATF_PUBL 0x08 /* publish entry */ ++ #define ATF_USETRAILERS 0x10 /* has requested trailers */ ++ ++ ++ #endif /* _LINUX_IF_ARP_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/if_ether.h /project/LINUX/new/include/linux/if_ether.h +*** /project/LINUX/Orig/include/linux/if_ether.h +--- /project/LINUX/new/include/linux/if_ether.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,88 ---- ++ /* ++ * 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 Ethernet IEE 802.3 interface. ++ * ++ * Version: @(#)if_ether.h 1.0.1 03/15/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_ETHER_H ++ #define _LINUX_IF_ETHER_H ++ ++ ++ /* IEEE 802.3 Ethernet magic constants. */ ++ #define ETH_ALEN 6 /* #bytes in eth addr */ ++ #define ETH_HLEN 14 /* #bytes in eth header */ ++ #define ETH_ZLEN 64 /* min #bytes in frame */ ++ #define ETH_FLEN 1536 /* max #bytes in frame */ ++ #define ETH_DLEN (ETH_FLEN - ETH_HLEN) /* max #bytes of data */ ++ ++ /* These are the defined Ethernet Protocol ID's. */ ++ #define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ ++ #define ETH_P_ECHO 0x0200 /* Ethernet Echo packet */ ++ #define ETH_P_PUP 0x0400 /* Xerox PUP packet */ ++ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ ++ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ ++ #define ETH_P_RARP 0x0835 /* Reverse Addr Res packet */ ++ ++ /* Define the Ethernet Broadcast Address (48 bits set to "1"). */ ++ #define ETH_A_BCAST "\377\377\377\377\377\377" ++ ++ /* This is an Ethernet frame header. */ ++ struct ethhdr { ++ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ ++ unsigned char h_source[ETH_ALEN]; /* source ether addr */ ++ unsigned short h_proto; /* packet type ID field */ ++ }; ++ ++ /* This is the complete Ethernet frame. */ ++ struct ethframe { ++ struct ethhdr f_hdr; /* frame header */ ++ char f_data[ETH_DLEN]; /* frame data (variable)*/ ++ }; ++ ++ ++ /* Receiver modes */ ++ #define ETH_MODE_MONITOR 1 /* Monitor mode - no receive */ ++ #define ETH_MODE_PHYS 2 /* Physical address receive only */ ++ #define ETH_MODE_BCAST 3 /* Broadcast receive + mode 2 */ ++ #define ETH_MODE_MCAST 4 /* Multicast receive + mode 3 */ ++ #define ETH_MODE_PROMISC 5 /* Promiscuous mode - receive all */ ++ ++ ++ /* Ethernet statistics collection data. */ ++ struct enet_statistics{ ++ int rx_packets; /* total packets received */ ++ int tx_packets; /* total packets transmitted */ ++ int rx_errors; /* bad packets received */ ++ int tx_errors; /* packet transmit problems */ ++ int rx_dropped; /* no space in linux buffers */ ++ int tx_dropped; /* no space available in linux */ ++ int multicast; /* multicast packets received */ ++ int collisions; ++ ++ /* detailed rx_errors: */ ++ int rx_length_errors; ++ int rx_over_errors; /* receiver ring buff overflow */ ++ int rx_crc_errors; /* recved pkt with crc error */ ++ int rx_frame_errors; /* recv'd frame alignment error */ ++ int rx_fifo_errors; /* recv'r fifo overrun */ ++ int rx_missed_errors; /* receiver missed packet */ ++ ++ /* detailed tx_errors */ ++ int tx_aborted_errors; ++ int tx_carrier_errors; ++ int tx_fifo_errors; ++ int tx_heartbeat_errors; ++ int tx_window_errors; ++ }; ++ ++ #endif /* _LINUX_IF_ETHER_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/in.h /project/LINUX/new/include/linux/in.h +*** /project/LINUX/Orig/include/linux/in.h +--- /project/LINUX/new/include/linux/in.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,171 ---- ++ /* ++ * 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 of the Internet Protocol. ++ * ++ * Version: @(#)in.h 1.0.1 04/21/93 ++ * ++ * Authors: Original taken from the GNU Project file. ++ * Fred N. van Kempen, ++ * ++ * 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_IN_H ++ #define _LINUX_IN_H ++ ++ ++ /* Standard well-defined IP protocols. */ ++ enum { ++ IPPROTO_IP = 0, /* Dummy protocol for TCP */ ++ IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ ++ IPPROTO_GGP = 2, /* Gateway Protocol (deprecated) */ ++ IPPROTO_TCP = 6, /* Transmission Control Protocol */ ++ IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ ++ IPPROTO_PUP = 12, /* PUP protocol */ ++ IPPROTO_UDP = 17, /* User Datagram Protocol */ ++ IPPROTO_IDP = 22, /* XNS IDP protocol */ ++ ++ IPPROTO_RAW = 255, /* Raw IP packets */ ++ IPPROTO_MAX ++ }; ++ ++ ++ /* Internet address. */ ++ struct in_addr { ++ unsigned long int s_addr; ++ }; ++ ++ ++ /* Structure describing an Internet (IP) socket address. */ ++ #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ ++ struct sockaddr_in { ++ short int sin_family; /* Address family */ ++ unsigned short int sin_port; /* Port number */ ++ struct in_addr sin_addr; /* Internet address */ ++ ++ /* Pad to size of `struct sockaddr'. */ ++ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - ++ sizeof(unsigned short int) - sizeof(struct in_addr)]; ++ }; ++ #define sin_zero __pad /* for BSD UNIX comp. -FvK */ ++ ++ ++ /* ++ * Definitions of the bits in an Internet address integer. ++ * On subnets, host and network parts are found according ++ * to the subnet mask, not these masks. ++ */ ++ #define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) ++ #define IN_CLASSA_NET 0xff000000 ++ #define IN_CLASSA_NSHIFT 24 ++ #define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) ++ #define IN_CLASSA_MAX 128 ++ ++ #define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) ++ #define IN_CLASSB_NET 0xffff0000 ++ #define IN_CLASSB_NSHIFT 16 ++ #define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) ++ #define IN_CLASSB_MAX 65536 ++ ++ #define IN_CLASSC(a) ((((long int) (a)) & 0xc0000000) == 0xc0000000) ++ #define IN_CLASSC_NET 0xffffff00 ++ #define IN_CLASSC_NSHIFT 8 ++ #define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) ++ ++ #define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) = 0xe0000000) ++ #define IN_MULTICAST(a) IN_CLASSD(a) ++ ++ #define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xe0000000) = 0xe0000000) ++ #define IN_BADCLASS(a) ((((long int) (a)) & 0xf0000000) = 0xf0000000) ++ ++ /* Address to accept any incoming messages. */ ++ #define INADDR_ANY ((unsigned long int) 0x00000000) ++ ++ /* Address to send to all hosts. */ ++ #define INADDR_BROADCAST ((unsigned long int) 0xffffffff) ++ ++ /* Address indicating an error return. */ ++ #define INADDR_NONE 0xffffffff ++ ++ /* Network number for local host loopback. */ ++ #define IN_LOOPBACKNET 127 ++ ++ /* Address to loopback in software to local host. */ ++ #define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ ++ ++ ++ /* ++ * Options for use with `getsockopt' and `setsockopt' at ++ * the IP level. LINUX does not yet have the IP_OPTIONS ++ * option (grin), so we undefine it for now.- HJ && FvK ++ */ ++ #if 0 ++ # define IP_OPTIONS 1 /* IP per-packet options */ ++ #endif ++ #define IP_HDRINCL 2 /* raw packet header option */ ++ ++ ++ /* Linux Internet number representation function declarations. */ ++ #undef ntohl ++ #undef ntohs ++ #undef htonl ++ #undef htons ++ ++ extern unsigned long int ntohl(unsigned long int); ++ extern unsigned short int ntohs(unsigned short int); ++ extern unsigned long int htonl(unsigned long int); ++ extern unsigned short int htons(unsigned short int); ++ ++ static __inline__ unsigned long int ++ __ntohl(unsigned long int x) ++ { ++ register unsigned long int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap lower bytes */ ++ "rorl $16,%%eax\n\t" /* swap words */ ++ "xchgb %%al,%%ah\n\t" /* swap higher bytes */ ++ : "=a" (tmp) : "a" (tmp) ); ++ return(tmp); ++ } ++ ++ static __inline__ unsigned short int ++ __ntohs(unsigned short int x) ++ { ++ register unsigned short int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap bytes */ ++ : "=a" (tmp) : "a" (tmp)); ++ return(tmp); ++ } ++ ++ static __inline__ unsigned long int ++ __htonl(unsigned long int x) ++ { ++ register unsigned long int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap lower bytes */ ++ "rorl $16,%%eax\n\t" /* swap words */ ++ "xchgb %%al,%%ah\n\t" /* swap higher bytes */ ++ : "=a" (tmp) : "a" (tmp)); ++ return(tmp); ++ } ++ ++ static __inline__ unsigned short int ++ __htons(unsigned short int x) ++ { ++ register unsigned short int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap bytes */ ++ : "=a" (tmp) : "a" (tmp)); ++ return(tmp); ++ } ++ ++ #ifdef __OPTIMIZE__ ++ # define ntohl(x) __ntohl((x)) ++ # define ntohs(x) __ntohs((x)) ++ # define htonl(x) __htonl((x)) ++ # define htons(x) __htons((x)) ++ #endif ++ ++ #endif /* _LINUX_IN_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/ip.h /project/LINUX/new/include/linux/ip.h +*** /project/LINUX/Orig/include/linux/ip.h +--- /project/LINUX/new/include/linux/ip.h Wed Apr 28 14:40:47 1993 +*************** +*** 0 **** +--- 1,81 ---- ++ /* ++ * 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 IP protocol. ++ * ++ * Version: @(#)ip.h 1.0.2 04/28/93 ++ * ++ * Authors: Fred N. van Kempen, ++ * ++ * 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_IP_H ++ #define _LINUX_IP_H ++ ++ ++ #define IPOPT_END 0 ++ #define IPOPT_NOOP 1 ++ #define IPOPT_SEC 130 ++ #define IPOPT_LSRR 131 ++ #define IPOPT_SSRR 137 ++ #define IPOPT_RR 7 ++ #define IPOPT_SID 136 ++ #define IPOPT_TIMESTAMP 68 ++ ++ ++ struct timestamp { ++ unsigned char len; ++ unsigned char ptr; ++ union { ++ unsigned char flags:4, ++ overflow:4; ++ unsigned char full_char; ++ } x; ++ unsigned long data[9]; ++ }; ++ ++ ++ #define MAX_ROUTE 16 ++ ++ struct route { ++ char route_size; ++ char pointer; ++ unsigned long route[MAX_ROUTE]; ++ }; ++ ++ ++ struct options { ++ struct route record_route; ++ struct route loose_route; ++ struct route strict_route; ++ struct timestamp tstamp; ++ unsigned short security; ++ unsigned short compartment; ++ unsigned short handling; ++ unsigned short stream; ++ unsigned tcc; ++ }; ++ ++ ++ struct iphdr { ++ unsigned char ihl:4, ++ version:4; ++ unsigned char tos; ++ unsigned short tot_len; ++ unsigned short id; ++ unsigned short frag_off; ++ unsigned char ttl; ++ unsigned char protocol; ++ unsigned short check; ++ unsigned long saddr; ++ unsigned long daddr; ++ /*The options start here. */ ++ }; ++ ++ ++ #endif /* _LINUX_IP_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/net.h /project/LINUX/new/include/linux/net.h +*** /project/LINUX/Orig/include/linux/net.h +--- /project/LINUX/new/include/linux/net.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,130 ---- ++ /* ++ * NET An implementation of the SOCKET network access protocol. ++ * This is the master header file for the Linux NET layer, ++ * or, in plain English: the networking handling part of the ++ * kernel. ++ * ++ * Version: @(#)net.h 1.0.1 04/22/93 ++ * ++ * Authors: ??? ++ * Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_NET_H ++ #define _LINUX_NET_H ++ ++ ++ #define NSOCKETS 128 /* should be dynamic, later... */ ++ #define NPROTO 16 /* should be enough for now.. */ ++ #define SOCKET_MAJOR 16 /* Linux VFS major dev number */ ++ ++ ++ #define SYS_SOCKET 1 /* sys_socket(2) */ ++ #define SYS_BIND 2 /* sys_bind(2) */ ++ #define SYS_CONNECT 3 /* sys_connect(2) */ ++ #define SYS_LISTEN 4 /* sys_listen(2) */ ++ #define SYS_ACCEPT 5 /* sys_accept(2) */ ++ #define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ ++ #define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ ++ #define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ ++ #define SYS_SEND 9 /* sys_send(2) */ ++ #define SYS_RECV 10 /* sys_recv(2) */ ++ #define SYS_SENDTO 11 /* sys_sendto(2) */ ++ #define SYS_RECVFROM 12 /* sys_recvfrom(2) */ ++ #define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ ++ #define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ ++ #define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ ++ ++ ++ typedef enum { ++ SS_FREE = 0, /* not allocated */ ++ SS_UNCONNECTED, /* unconnected to any socket */ ++ SS_CONNECTING, /* in process of connecting */ ++ SS_CONNECTED, /* connected to socket */ ++ SS_DISCONNECTING, /* in process of disconnecting */ ++ } socket_state; ++ ++ #define SO_ACCEPTCON (1<<16) /* performed a listen */ ++ ++ ++ /* ++ * Internel representation of a socket. not all the fields are used by ++ * all configurations: ++ * ++ * server client ++ * conn client connected to server connected to ++ * iconn list of clients -unused- ++ * awaiting connections ++ * wait sleep for clients, sleep for connection, ++ * sleep for i/o sleep for i/o ++ */ ++ struct socket { ++ short type; /* SOCK_STREAM, ... */ ++ socket_state state; ++ long flags; ++ struct proto_ops *ops; /* protocols do most everything */ ++ void *data; /* protocol data */ ++ struct socket *conn; /* server socket connected to */ ++ struct socket *iconn; /* incomplete client conn.s */ ++ struct socket *next; ++ struct wait_queue **wait; /* ptr to place to wait on */ ++ void *dummy; ++ }; ++ ++ #define SOCK_INODE(S) ((struct inode *)(S)->dummy) ++ extern struct socket sockets[NSOCKETS]; ++ #define last_socket (sockets + NSOCKETS - 1) ++ ++ ++ struct proto_ops { ++ int family; ++ ++ int (*create) (struct socket *sock, int protocol); ++ 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); ++ int (*connect) (struct socket *sock, struct sockaddr *uservaddr, ++ int 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); ++ int (*read) (struct socket *sock, char *ubuf, int size, ++ int nonblock); ++ int (*write) (struct socket *sock, char *ubuf, int size, ++ int nonblock); ++ int (*select) (struct socket *sock, int sel_type, ++ select_table *wait); ++ int (*ioctl) (struct socket *sock, unsigned int cmd, ++ unsigned long arg); ++ int (*listen) (struct socket *sock, int len); ++ int (*send) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags); ++ int (*recv) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags); ++ int (*sendto) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags, struct sockaddr *, int addr_len); ++ int (*recvfrom) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags, struct sockaddr *, int *addr_len); ++ int (*shutdown) (struct socket *sock, int flags); ++ int (*setsockopt) (struct socket *sock, int level, int optname, ++ char *optval, int optlen); ++ int (*getsockopt) (struct socket *sock, int level, int optname, ++ char *optval, int *optlen); ++ int (*fcntl) (struct socket *sock, unsigned int cmd, ++ unsigned long arg); ++ }; ++ ++ ++ extern int sock_awaitconn(struct socket *mysock, struct socket *servsock); ++ extern int sock_register(int family, struct proto_ops *ops); ++ ++ ++ #endif /* _LINUX_NET_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/nfs_fs.h /project/LINUX/new/include/linux/nfs_fs.h +*** /project/LINUX/Orig/include/linux/nfs_fs.h Tue Apr 6 20:57:21 1993 +--- /project/LINUX/new/include/linux/nfs_fs.h Sat Apr 24 19:39:35 1993 +*************** +*** 11,17 **** + + #include + +! #include + #include + + /* +--- 11,17 ---- + + #include + +! #include + #include + + /* +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/proc_fs.h /project/LINUX/new/include/linux/proc_fs.h +*** /project/LINUX/Orig/include/linux/proc_fs.h Tue Apr 6 20:57:21 1993 +--- /project/LINUX/new/include/linux/proc_fs.h Sat Apr 24 19:39:35 1993 +*************** +*** 25,34 **** +--- 25,36 ---- + + extern struct inode_operations proc_root_inode_operations; + extern struct inode_operations proc_base_inode_operations; ++ extern struct inode_operations proc_net_inode_operations; + extern struct inode_operations proc_mem_inode_operations; + extern struct inode_operations proc_array_inode_operations; + extern struct inode_operations proc_kmsg_inode_operations; + extern struct inode_operations proc_link_inode_operations; + extern struct inode_operations proc_fd_inode_operations; ++ extern struct inode_operations proc_net_inode_operations; + + #endif +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/route.h /project/LINUX/new/include/linux/route.h +*** /project/LINUX/Orig/include/linux/route.h +--- /project/LINUX/new/include/linux/route.h Sat Apr 24 19:39:36 1993 +*************** +*** 0 **** +--- 1,49 ---- ++ /* ++ * 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 IP router interface. ++ * ++ * Version: @(#)route.h 1.0.2 04/16/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 ++ * Fred N. van Kempen, ++ * ++ * 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_ROUTE_H ++ #define _LINUX_ROUTE_H ++ ++ #include ++ ++ ++ /* ++ * This structure gets passed by the SIOCADDRT and SIOCDELRT calls. ++ * It is not exactly identical to the BSD UNIX version of "rtentry", ++ * because BSD used /dev/kmem to figure out interface addresses. We ++ * do it cleaner, using a character array to stuff the name into. ++ * Also, to clean up things, the real IP routing table does not use ++ * the "struct sockaddr" addresses- it uses simple "unsigned long" ++ * fields. Routing is a protocol-dependent thing anyway. -FvK ++ */ ++ struct rtentry { ++ char rt_dev[IFNAMSIZ]; ++ struct sockaddr rt_dst; ++ struct sockaddr rt_gateway; ++ u_char rt_flags; ++ u_char rt_metric; ++ short rt_refcnt; ++ unsigned long rt_use; ++ }; ++ #define RTF_UP 0x0001 /* route useable */ ++ #define RTF_GATEWAY 0x0002 /* destination is a gateway */ ++ #define RTF_HOST 0x0004 /* host entry (net otherwise) */ ++ #define RTF_REINSTATE 0x0008 /* re-instate route after tmout */ ++ #define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */ ++ #define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */ ++ ++ #endif /* _LINUX_ROUTE_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/socket.h /project/LINUX/new/include/linux/socket.h +*** /project/LINUX/Orig/include/linux/socket.h Tue Nov 10 12:54:55 1992 +--- /project/LINUX/new/include/linux/socket.h Sat Apr 24 19:39:36 1993 +*************** +*** 1,51 **** + #ifndef _LINUX_SOCKET_H + #define _LINUX_SOCKET_H + + struct sockaddr { +! unsigned short sa_family; /* address family, AF_xxx */ +! char sa_data[14]; /* 14 bytes of protocol address */ + }; + +! /* +! * socket types +! */ +! #define SOCK_STREAM 1 /* stream (connection) socket */ +! #define SOCK_DGRAM 2 /* datagram (connectionless) socket */ +! #define SOCK_RAW 3 /* raw socket */ +! #define SOCK_RDM 4 /* reliably-delivered message */ +! #define SOCK_SEQPACKET 5 /* sequential packet socket */ +! #define SOCK_PACKET 10 /* linux specific way of getting +! packets at the dev level. For +! writing rarp and other similiar +! things on the user level. */ +! +! /* +! * supported address families +! */ + #define AF_UNSPEC 0 + #define AF_UNIX 1 + #define AF_INET 2 + +! /* +! * protocol families, same as address families +! */ + #define PF_UNIX AF_UNIX + #define PF_INET AF_INET + +! /* flags we can use with send/ and recv. */ + #define MSG_OOB 1 + #define MSG_PEEK 2 + +! /* ioctl's */ +! #define FIOSETOWN 0x8901 /* the 89 is for uniqueness. +! This should be somewhere else. */ +! #define SIOCSPGRP 0x8902 +! #define FIOGETOWN 0x8903 /* this too. */ +! #define SIOCGPGRP 0x8904 +! #define SIOCATMARK 0x8905 +! + +! /* for setsockoptions */ + #define SO_DEBUG 1 + #define SO_REUSEADDR 2 + #define SO_TYPE 3 +--- 1,43 ---- + #ifndef _LINUX_SOCKET_H + #define _LINUX_SOCKET_H + ++ #include /* the SIOCxxx I/O controls */ ++ ++ + struct sockaddr { +! unsigned short sa_family; /* address family, AF_xxx */ +! char sa_data[14]; /* 14 bytes of protocol address */ + }; + +! /* Socket types. */ +! #define SOCK_STREAM 1 /* stream (connection) socket */ +! #define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +! #define SOCK_RAW 3 /* raw socket */ +! #define SOCK_RDM 4 /* reliably-delivered message */ +! #define SOCK_SEQPACKET 5 /* sequential packet socket */ +! #define SOCK_PACKET 10 /* linux specific way of */ +! /* getting packets at the dev */ +! /* level. For writing rarp and */ +! /* other similiar things on the */ +! /* user level. */ +! +! /* Supported address families. */ + #define AF_UNSPEC 0 + #define AF_UNIX 1 + #define AF_INET 2 + +! /* Protocol families, same as address families. */ + #define PF_UNIX AF_UNIX + #define PF_INET AF_INET + +! /* Flags we can use with send/ and recv. */ + #define MSG_OOB 1 + #define MSG_PEEK 2 + +! /* Setsockoptions(2) level. */ +! #define SOL_SOCKET 1 + +! /* For setsockoptions(2) */ + #define SO_DEBUG 1 + #define SO_REUSEADDR 2 + #define SO_TYPE 3 +*************** +*** 55,71 **** + #define SO_SNDBUF 7 + #define SO_RCVBUF 8 + #define SO_KEEPALIVE 9 +! #define SO_OOBINLINE 10 +! #define SO_NO_CHECK 11 +! #define SO_PRIORITY 12 +! #define SO_LINGER 13 + +! /* the different priorities */ + #define SOPRI_INTERACTIVE 0 + #define SOPRI_NORMAL 1 + #define SOPRI_BACKGROUND 2 + +- /* setsockoptions level */ +- #define SOL_SOCKET 1 +- + #endif /* _LINUX_SOCKET_H */ +--- 47,60 ---- + #define SO_SNDBUF 7 + #define SO_RCVBUF 8 + #define SO_KEEPALIVE 9 +! #define SO_OOBINLINE 10 +! #define SO_NO_CHECK 11 +! #define SO_PRIORITY 12 +! #define SO_LINGER 13 + +! /* The various priorities. */ + #define SOPRI_INTERACTIVE 0 + #define SOPRI_NORMAL 1 + #define SOPRI_BACKGROUND 2 + + #endif /* _LINUX_SOCKET_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/sockios.h /project/LINUX/new/include/linux/sockios.h +*** /project/LINUX/Orig/include/linux/sockios.h +--- /project/LINUX/new/include/linux/sockios.h Sat Apr 24 19:39:36 1993 +*************** +*** 0 **** +--- 1,72 ---- ++ /* ++ * 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 of the socket-level I/O control calls. ++ * ++ * Version: @(#)sockios.h 1.0.2 03/09/93 ++ * ++ * Authors: Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_SOCKIOS_H ++ #define _LINUX_SOCKIOS_H ++ ++ /* This section will go away soon! */ ++ #if 1 /* FIXME: */ ++ #define MAX_IP_NAME 20 ++ #define IP_SET_DEV 0x2401 ++ ++ struct ip_config { ++ char name[MAX_IP_NAME]; ++ unsigned long paddr; ++ unsigned long router; ++ unsigned long net; ++ unsigned long up:1,destroy:1; ++ }; ++ #endif /* FIXME: */ ++ ++ /* Socket-level I/O control calls. */ ++ #define FIOSETOWN 0x8901 ++ #define SIOCSPGRP 0x8902 ++ #define FIOGETOWN 0x8903 ++ #define SIOCGPGRP 0x8904 ++ #define SIOCATMARK 0x8905 ++ ++ /* Socket configuration controls. */ ++ #define SIOCGIFNAME 0x8910 /* get iface name */ ++ #define SIOCSIFLINK 0x8911 /* set iface channel */ ++ #define SIOCGIFCONF 0x8912 /* get iface list */ ++ #define SIOCGIFFLAGS 0x8913 /* get flags */ ++ #define SIOCSIFFLAGS 0x8914 /* set flags */ ++ #define SIOCGIFADDR 0x8915 /* get PA address */ ++ #define SIOCSIFADDR 0x8916 /* set PA address */ ++ #define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ ++ #define SIOCSIFDSTADDR 0x8918 /* set remote PA address */ ++ #define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ ++ #define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ ++ #define SIOCGIFNETMASK 0x891b /* get network PA mask */ ++ #define SIOCSIFNETMASK 0x891c /* set network PA mask */ ++ #define SIOCGIFMETRIC 0x891d /* get metric */ ++ #define SIOCSIFMETRIC 0x891e /* set metric */ ++ #define SIOCGIFMEM 0x891f /* get memory address (BSD) */ ++ #define SIOCSIFMEM 0x8920 /* set memory address (BSD) */ ++ #define SIOCGIFMTU 0x8921 /* get MTU size */ ++ #define SIOCSIFMTU 0x8922 /* set MTU size */ ++ ++ /* Routing table calls. */ ++ #define SIOCADDRT 0x8940 /* add routing table entry */ ++ #define SIOCDELRT 0x8941 /* delete routing table entry */ ++ ++ /* ARP cache control calls. */ ++ #define SIOCDARP 0x8950 /* delete ARP table entry */ ++ #define SIOCGARP 0x8951 /* get ARP table entry */ ++ #define SIOCSARP 0x8952 /* set ARP table entry */ ++ ++ #endif /* _LINUX_SOCKIOS_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/tcp.h /project/LINUX/new/include/linux/tcp.h +*** /project/LINUX/Orig/include/linux/tcp.h +--- /project/LINUX/new/include/linux/tcp.h Wed Apr 28 14:42:37 1993 +*************** +*** 0 **** +--- 1,61 ---- ++ /* ++ * 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 TCP protocol. ++ * ++ * Version: @(#)tcp.h 1.0.2 04/28/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_TCP_H ++ #define _LINUX_TCP_H ++ ++ ++ #define HEADER_SIZE 64 /* maximum header size */ ++ ++ ++ struct tcphdr { ++ unsigned short source; ++ unsigned short dest; ++ unsigned long seq; ++ unsigned long ack_seq; ++ unsigned short res1:4, ++ doff:4, ++ fin:1, ++ syn:1, ++ rst:1, ++ psh:1, ++ ack:1, ++ urg:1, ++ res2:2; ++ unsigned short window; ++ unsigned short check; ++ unsigned short urg_ptr; ++ }; ++ ++ ++ enum { ++ TCP_ESTABLISHED = 1, ++ TCP_SYN_SENT, ++ TCP_SYN_RECV, ++ #if 0 ++ TCP_CLOSING, /* not a valid state, just a seperator so we can use ++ < tcp_closing or > tcp_closing for checks. */ ++ #endif ++ TCP_FIN_WAIT1, ++ TCP_FIN_WAIT2, ++ TCP_TIME_WAIT, ++ TCP_CLOSE, ++ TCP_CLOSE_WAIT, ++ TCP_LAST_ACK, ++ TCP_LISTEN ++ }; ++ ++ #endif /* _LINUX_TCP_H */ +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/tty.h /project/LINUX/new/include/linux/tty.h +*** /project/LINUX/Orig/include/linux/tty.h Thu Apr 22 20:32:21 1993 +--- /project/LINUX/new/include/linux/tty.h Sat Apr 24 19:48:45 1993 +*************** +*** 340,345 **** +--- 340,349 ---- + extern void wait_until_sent(struct tty_struct * tty); + extern void copy_to_cooked(struct tty_struct * tty); + extern int tty_register_ldisc(int disc, struct tty_ldisc *new); ++ extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, ++ int buflen); ++ extern int tty_write_data(struct tty_struct *tty, char *bufp, int buflen, ++ void (*callback)(void * data), void * callarg); + + extern int tty_ioctl(struct inode *, struct file *, unsigned int, unsigned long); + extern int is_orphaned_pgrp(int pgrp); +diff -c --recursive --new-file /project/LINUX/Orig/include/linux/udp.h /project/LINUX/new/include/linux/udp.h +*** /project/LINUX/Orig/include/linux/udp.h +--- /project/LINUX/new/include/linux/udp.h Wed Apr 28 14:42:55 1993 +*************** +*** 0 **** +--- 1,29 ---- ++ /* ++ * 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 UDP protocol. ++ * ++ * Version: @(#)udp.h 1.0.2 04/28/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_UDP_H ++ #define _LINUX_UDP_H ++ ++ ++ struct udphdr { ++ unsigned short source; ++ unsigned short dest; ++ unsigned short len; ++ unsigned short check; ++ }; ++ ++ ++ #endif /* _LINUX_UDP_H */ +diff -c --recursive --new-file /project/LINUX/Orig/kernel/blk_drv/ramdisk.c /project/LINUX/new/kernel/blk_drv/ramdisk.c +*** /project/LINUX/Orig/kernel/blk_drv/ramdisk.c Wed Feb 17 19:25:55 1993 +--- /project/LINUX/new/kernel/blk_drv/ramdisk.c Sat Apr 24 19:39:36 1993 +*************** +*** 2,7 **** +--- 2,10 ---- + * linux/kernel/blk_drv/ramdisk.c + * + * Written by Theodore Ts'o, 12/2/91 ++ * ++ * Modifications by Fred N. van Kempen to allow for bootable root ++ * disks (which are used in LINUX/Pro). Also some cleanups. 03/03/93 + */ + + +*************** +*** 14,22 **** + #include + #include + +! #define MAJOR_NR 1 + #include "blk.h" + + char *rd_start; + int rd_length = 0; + +--- 17,30 ---- + #include + #include + +! #define MAJOR_RAMDISK 1 /* should be in */ +! #define MAJOR_FLOPPY 2 /* should be in */ +! #define MINOR_RAMDISK 1 +! +! #define MAJOR_NR MAJOR_RAMDISK /* weird hack- FvK */ + #include "blk.h" + ++ + char *rd_start; + int rd_length = 0; + +*************** +*** 29,35 **** + INIT_REQUEST; + addr = rd_start + (CURRENT->sector << 9); + len = CURRENT->nr_sectors << 9; +! if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) { + end_request(0); + goto repeat; + } +--- 37,44 ---- + INIT_REQUEST; + addr = rd_start + (CURRENT->sector << 9); + len = CURRENT->nr_sectors << 9; +! if ((MINOR(CURRENT->dev) != MINOR_RAMDISK) || +! (addr+len > rd_start+rd_length)) { + end_request(0); + goto repeat; + } +*************** +*** 42,48 **** + addr, + len); + } else +! panic("unknown ramdisk-command"); + end_request(1); + goto repeat; + } +--- 51,57 ---- + addr, + len); + } else +! panic("RAMDISK: unknown RAM disk command !\n"); + end_request(1); + goto repeat; + } +*************** +*** 67,77 **** + int i; + char *cp; + +! if (register_blkdev(MAJOR_NR,"rd",&rd_fops)) { +! printk("Unable to get major %d for ramdisk\n",MAJOR_NR); + return 0; + } +! blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + rd_start = (char *) mem_start; + rd_length = length; + cp = rd_start; +--- 76,86 ---- + int i; + char *cp; + +! if (register_blkdev(MAJOR_RAMDISK,"rd",&rd_fops)) { +! printk("RAMDISK: Unable to get major %d.\n", MAJOR_RAMDISK); + return 0; + } +! blk_dev[MAJOR_RAMDISK].request_fn = DEVICE_REQUEST; + rd_start = (char *) mem_start; + rd_length = length; + cp = rd_start; +*************** +*** 81,142 **** + } + + /* +! * If the root device is the ram disk, try to load it. + * In order to do this, the root device is originally set to the +! * floppy, and we later change it to be ram disk. + */ + void rd_load(void) + { + struct buffer_head *bh; + struct minix_super_block s; +! int block = 512; /* Start at block 512 */ + int i = 1; + int nblocks; +! char *cp; /* Move pointer */ +! +! if (!rd_length) +! return; +! printk("Ram disk: %d bytes, starting at 0x%x\n", rd_length, +! (int) rd_start); +! if (MAJOR(ROOT_DEV) != 2) +! return; +! bh = breada(ROOT_DEV,block+1,block,block+2,-1); +! if (!bh) { +! printk("Disk error while looking for ramdisk!\n"); +! return; +! } +! *((struct minix_super_block *) &s) = *((struct minix_super_block *) bh->b_data); +! brelse(bh); +! if (s.s_magic != MINIX_SUPER_MAGIC) +! /* No ram disk image present, assume normal floppy boot */ +! return; +! nblocks = s.s_nzones << s.s_log_zone_size; +! if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) { +! printk("Ram disk image too big! (%d blocks, %d avail)\n", +! nblocks, rd_length >> BLOCK_SIZE_BITS); +! return; +! } +! printk("Loading %d bytes into ram disk\n", +! nblocks << BLOCK_SIZE_BITS); +! cp = rd_start; +! while (nblocks) { +! if (nblocks > 2) +! bh = breada(ROOT_DEV, block, block+1, block+2, -1); +! else +! bh = bread(ROOT_DEV, block, BLOCK_SIZE); + if (!bh) { +! printk("I/O error on block %d, aborting load\n", +! block); + return; + } +! (void) memcpy(cp, bh->b_data, BLOCK_SIZE); + brelse(bh); +! if (!(nblocks-- & 15)) +! printk("."); +! cp += BLOCK_SIZE; +! block++; +! i++; + } +- printk("\ndone\n"); +- ROOT_DEV=0x0101; + } +--- 90,172 ---- + } + + /* +! * If the root device is the RAM disk, try to load it. + * In order to do this, the root device is originally set to the +! * floppy, and we later change it to be RAM disk. + */ + void rd_load(void) + { + struct buffer_head *bh; + struct minix_super_block s; +! int block, try; + int i = 1; + int nblocks; +! char *cp; +! +! /* If no RAM disk specified, give up early. */ +! if (!rd_length) return; +! printk("RAMDISK: %d bytes, starting at 0x%x\n", +! rd_length, (int) rd_start); +! +! /* If we are doing a diskette boot, we might have to pre-load it. */ +! if (MAJOR(ROOT_DEV) != MAJOR_FLOPPY) return; +! +! /* +! * Check for a super block on the diskette. +! * The old-style boot/root diskettes had their RAM image +! * starting at block 512 of the boot diskette. LINUX/Pro +! * uses the enire diskette as a file system, so in that +! * case, we have to look at block 0. Be intelligent about +! * this, and check both... - FvK +! */ +! for (try = 0; try < 1000; try += 512) { +! block = try; +! bh = breada(ROOT_DEV,block+1,block,block+2,-1); + if (!bh) { +! printk("RAMDISK: I/O error while looking for super block!\n"); + return; + } +! +! /* This is silly- why do we require it to be a MINIX FS? */ +! *((struct minix_super_block *) &s) = +! *((struct minix_super_block *) bh->b_data); + brelse(bh); +! nblocks = s.s_nzones << s.s_log_zone_size; +! if (s.s_magic != MINIX_SUPER_MAGIC) { +! printk("RAMDISK: trying old-style RAM image.\n"); +! continue; +! } +! +! if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) { +! printk("RAMDISK: image too big! (%d/%d blocks)\n", +! nblocks, rd_length >> BLOCK_SIZE_BITS); +! return; +! } +! printk("RAMDISK: Loading %d blocks into RAM disk", nblocks); +! +! /* We found an image file system. Load it into core! */ +! cp = rd_start; +! while (nblocks) { +! if (nblocks > 2) +! bh = breada(ROOT_DEV, block, block+1, block+2, -1); +! else +! bh = bread(ROOT_DEV, block, BLOCK_SIZE); +! if (!bh) { +! printk("RAMDISK: I/O error on block %d, aborting!\n", +! block); +! return; +! } +! (void) memcpy(cp, bh->b_data, BLOCK_SIZE); +! brelse(bh); +! if (!(nblocks-- & 15)) printk("."); +! cp += BLOCK_SIZE; +! block++; +! i++; +! } +! printk("\ndone\n"); +! +! /* We loaded the file system image. Prepare for mounting it. */ +! ROOT_DEV = ((MAJOR_RAMDISK << 8) | MINOR_RAMDISK); +! return; + } + } +diff -c --recursive --new-file /project/LINUX/Orig/kernel/chr_drv/tty_io.c /project/LINUX/new/kernel/chr_drv/tty_io.c +*** /project/LINUX/Orig/kernel/chr_drv/tty_io.c Thu Apr 22 20:21:02 1993 +--- /project/LINUX/new/kernel/chr_drv/tty_io.c Sat Apr 24 19:39:36 1993 +*************** +*** 1391,1396 **** +--- 1391,1397 ---- + while (count && VLEFT > 0) { + tty->write_q.buf[head++] = *p++; + head &= TTY_BUF_SIZE-1; ++ count--; + } + tty->write_q.head = head; + if (count) { +*************** +*** 1400,1405 **** +--- 1401,1407 ---- + tty->write_data_arg = callarg; + } + __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags)); ++ tty->write(tty); + return count; + } + diff --git a/net/net-2/net-ksrc-revb.tgz b/net/net-2/net-ksrc-revb.tgz new file mode 100644 index 00000000..331a0c79 Binary files /dev/null and b/net/net-2/net-ksrc-revb.tgz differ diff --git a/net/net-2/net-std.tar.z b/net/net-2/net-std.tar.z new file mode 100644 index 00000000..c8ab344e Binary files /dev/null and b/net/net-2/net-std.tar.z differ diff --git a/net/net-2/old/Linus.patch b/net/net-2/old/Linus.patch new file mode 100644 index 00000000..618b0100 --- /dev/null +++ b/net/net-2/old/Linus.patch @@ -0,0 +1,2409 @@ +diff -c --recursive --new-file std/Configure linux/Configure +*** std/Configure Wed Mar 31 16:36:25 1993 +--- linux/Configure Sat Apr 24 19:39:35 1993 +*************** +*** 1,27 **** + #! /bin/sh + # +! # This script is used to configure the linux kernel. +! # It's a fast hack - feel free to do something better. +! CONFIG=.config~ +! CONFIG_H=include/linux/autoconf.h +! > config.new +! echo "#" > $CONFIG +! echo "# Automatically generated make config: don't edit" >> $CONFIG +! echo "#" >> $CONFIG +! +! echo "/*" > $CONFIG_H +! echo " * Automatically generated C config: don't edit" >> $CONFIG_H +! echo " */" >> $CONFIG_H +! +! next="y" +! old="y" + +! while read i +! do + echo $i >> config.new +! echo >> $CONFIG +! echo >> $CONFIG_H +! echo + echo "#" >> $CONFIG + echo "/*" >> $CONFIG_H + echo "**" +--- 1,55 ---- + #! /bin/sh ++ # Configure This script is used to configure the Linux kernel. + # +! # Usage: Configure [-pro] +! # +! # Version; @(#)Configure 1.3 04/05/93 +! # +! # Author: Linus Torvalds, +! # + +! # Set variables to initial state. +! OPTS="" +! CONFIG=.config~ +! CONFIG_H=include/linux/autoconf.h +! next="y" +! old="y" +! +! # Check commandline arguments. +! >config.new +! while [ $# != 0 ] +! do +! case $1 in +! -pro) OPTS="UTS_SYSNAME \"LINUX/Pro\"" +! ;; +! *) echo "Usage: Configure [-pro]" +! exit 1 +! ;; +! esac +! shift +! done +! +! echo "#" > $CONFIG +! echo "# Automatically generated make config: don't edit" >> $CONFIG +! echo "#" >> $CONFIG +! +! echo "/*" > $CONFIG_H +! echo " * Automatically generated C config: don't edit" >> $CONFIG_H +! echo " */" >> $CONFIG_H +! +! # First of all, emit the "special" features to . +! if [ "${OPTS}" ] +! then +! echo "#define ${OPTS}" >> $CONFIG_H +! fi +! +! # Read our standard input (which is the CONFIG.IN file). +! while read i +! do + echo $i >> config.new +! echo >> $CONFIG +! echo >> $CONFIG_H +! echo + echo "#" >> $CONFIG + echo "/*" >> $CONFIG_H + echo "**" +*************** +*** 69,83 **** + then + next="n" + fi +! done +! +! mv config.new config.in + +! echo +! echo "The linux kernel is now hopefully configured for your setup." +! echo "Check the top-level Makefile for additional configuration," +! echo "and do a 'make dep ; make clean' if you want to be sure all" +! echo "the files are correctly re-made" +! echo + +! exit 0 +--- 97,110 ---- + then + next="n" + fi +! done +! mv config.new config.in + +! echo +! echo "The linux kernel is now hopefully configured for your setup." +! echo "Check the top-level Makefile for additional configuration," +! echo "and do a 'make dep ; make clean' if you want to be sure all" +! echo "the files are correctly re-made" +! echo + +! exit 0 +diff -c --recursive --new-file std/Makefile linux/Makefile +*** std/Makefile Thu Apr 22 23:10:11 1993 +--- linux/Makefile Sat Apr 24 22:36:50 1993 +*************** +*** 44,52 **** + # 0x08 - tilde (~) + # 0x10 - dieresis (umlaut) + +! KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0 + # KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x1F +! # KEYBOARD = -DKBD_US -DKBDFLAGS=0 + # KEYBOARD = -DKBD_GR -DKBDFLAGS=0 + # KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x1F + # KEYBOARD = -DKBD_FR -DKBDFLAGS=0 +--- 44,52 ---- + # 0x08 - tilde (~) + # 0x10 - dieresis (umlaut) + +! # KEYBOARD = -DKBD_FINNISH -DKBDFLAGS=0 + # KEYBOARD = -DKBD_FINNISH_LATIN1 -DKBDFLAGS=0x1F +! KEYBOARD = -DKBD_US -DKBDFLAGS=0 + # KEYBOARD = -DKBD_GR -DKBDFLAGS=0 + # KEYBOARD = -DKBD_GR_LATIN1 -DKBDFLAGS=0x1F + # KEYBOARD = -DKBD_FR -DKBDFLAGS=0 +*************** +*** 68,75 **** + # The number is the same as you would ordinarily press at bootup. + # + +! SVGA_MODE= -DSVGA_MODE=3 + + # + # standard CFLAGS + # +--- 68,78 ---- + # The number is the same as you would ordinarily press at bootup. + # + +! SVGA_MODE= -DSVGA_MODE=NORMAL_VGA + ++ # Special options. ++ OPTS = -pro ++ + # + # standard CFLAGS + # +*************** +*** 125,131 **** + /etc/lilo/install + + config: +! sh Configure < config.in + mv .config~ .config + $(MAKE) soundconf + +--- 128,134 ---- + /etc/lilo/install + + config: +! sh Configure $(OPTS) < config.in + mv .config~ .config + $(MAKE) soundconf + +*************** +*** 139,146 **** + + tools/version.h: $(CONFIGURE) Makefile + @./makever.sh +! @echo \#define UTS_RELEASE \"0.99.pl9-`cat .version`\" > tools/version.h +! @echo \#define UTS_VERSION \"`date +%D`\" >> tools/version.h + @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h + @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h + @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h +--- 142,149 ---- + + tools/version.h: $(CONFIGURE) Makefile + @./makever.sh +! @echo \#define UTS_RELEASE \"0.99.9-`cat .version`\" > tools/version.h +! @echo \#define UTS_VERSION \"`date`\" >> tools/version.h + @echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> tools/version.h + @echo \#define LINUX_COMPILE_BY \"`whoami`\" >> tools/version.h + @echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> tools/version.h +diff -c --recursive --new-file std/config.in linux/config.in +*** std/config.in Fri Apr 23 20:41:46 1993 +--- linux/config.in Sat Apr 24 21:04:24 1993 +*************** +*** 1,78 **** + General setup + . + Kernel math emulation +! CONFIG_MATH_EMULATION y/n n + Normal harddisk support + CONFIG_BLK_DEV_HD y/n y + XT harddisk support + CONFIG_BLK_DEV_XD y/n n +! TCP/IP +! CONFIG_TCPIP y/n y + Kernel profiling support + CONFIG_PROFILE y/n n + Limit memory to low 16MB +! CONFIG_MAX_16M y/n n + Use -m486 flag for 486-specific optimizations + CONFIG_M486 y/n y + : + SCSI support + . + SCSI support? +! CONFIG_SCSI y/n n + : + SCSI support type (disk, tape, CDrom) + . + Scsi disk support +! CONFIG_BLK_DEV_SD y/n n + Scsi tape support +! CONFIG_BLK_DEV_ST y/n n + Scsi CDROM support +! CONFIG_BLK_DEV_SR y/n n + . + SCSI low-level drivers + . + Adaptec AHA1542 support +! CONFIG_SCSI_AHA1542 y/n n + Adaptec AHA1740 support +! CONFIG_SCSI_AHA1740 y/n n + Future Domain SCSI support +! CONFIG_SCSI_FUTURE_DOMAIN y/n n + Seagate ST-02 and Future Domain TMC-8xx SCSI support +! CONFIG_SCSI_SEAGATE y/n n + UltraStor SCSI support +! CONFIG_SCSI_ULTRASTOR y/n n + 7000FASST SCSI support +! CONFIG_SCSI_7000FASST y/n n + . + Filesystems + . +- Mount root initially readonly +- CONFIG_ROOT_RDONLY y/n n + Standard (minix) fs support + CONFIG_MINIX_FS y/n y + Extended fs support +! CONFIG_EXT_FS y/n n + Second extended fs support +! CONFIG_EXT2_FS y/n n + xiafs filesystem support +! CONFIG_XIA_FS y/n n + msdos fs support + CONFIG_MSDOS_FS y/n y + /proc filesystem support + CONFIG_PROC_FS y/n y + NFS filesystem support +! CONFIG_NFS_FS y/n n + ISO9660 cdrom filesystem support +! CONFIG_ISO9660_FS y/n n + . + Various character device drivers.. + . + Keyboard meta-key sends ESC-prefix +! CONFIG_KBD_META y/n y + Autoconfigure serial IRQ lines at bootup + CONFIG_AUTO_IRQ y/n n + AST Fourport serial driver support +! CONFIG_AST_FOURPORT y/n n + Accent Async 4 serial support + CONFIG_ACCENT_ASYNC y/n n + Logitech busmouse support +--- 1,78 ---- + General setup + . + Kernel math emulation +! CONFIG_MATH_EMULATION y/n y + Normal harddisk support + CONFIG_BLK_DEV_HD y/n y + XT harddisk support + CONFIG_BLK_DEV_XD y/n n +! TCP/IP version 1 Networking +! CONFIG_TCPIP y/n y +! TCP/IP version 2 Networking +! CONFIG_INET y/n n + Kernel profiling support + CONFIG_PROFILE y/n n + Limit memory to low 16MB +! CONFIG_MAX_16M y/n y + Use -m486 flag for 486-specific optimizations + CONFIG_M486 y/n y + : + SCSI support + . + SCSI support? +! CONFIG_SCSI y/n y + : + SCSI support type (disk, tape, CDrom) + . + Scsi disk support +! CONFIG_BLK_DEV_SD y/n y + Scsi tape support +! CONFIG_BLK_DEV_ST y/n y + Scsi CDROM support +! CONFIG_BLK_DEV_SR y/n y + . + SCSI low-level drivers + . + Adaptec AHA1542 support +! CONFIG_SCSI_AHA1542 y/n y + Adaptec AHA1740 support +! CONFIG_SCSI_AHA1740 y/n y + Future Domain SCSI support +! CONFIG_SCSI_FUTURE_DOMAIN y/n y + Seagate ST-02 and Future Domain TMC-8xx SCSI support +! CONFIG_SCSI_SEAGATE y/n y + UltraStor SCSI support +! CONFIG_SCSI_ULTRASTOR y/n y + 7000FASST SCSI support +! CONFIG_SCSI_7000FASST y/n y + . + Filesystems + . + Standard (minix) fs support + CONFIG_MINIX_FS y/n y + Extended fs support +! CONFIG_EXT_FS y/n y + Second extended fs support +! CONFIG_EXT2_FS y/n y + xiafs filesystem support +! CONFIG_XIA_FS y/n y + msdos fs support + CONFIG_MSDOS_FS y/n y + /proc filesystem support + CONFIG_PROC_FS y/n y + NFS filesystem support +! CONFIG_NFS_FS y/n y + ISO9660 cdrom filesystem support +! CONFIG_ISO9660_FS y/n y + . + Various character device drivers.. + . + Keyboard meta-key sends ESC-prefix +! CONFIG_KBD_META y/n n + Autoconfigure serial IRQ lines at bootup + CONFIG_AUTO_IRQ y/n n + AST Fourport serial driver support +! CONFIG_AST_FOURPORT y/n y + Accent Async 4 serial support + CONFIG_ACCENT_ASYNC y/n n + Logitech busmouse support +diff -c --recursive --new-file std/fs/nfs/proc.c linux/fs/nfs/proc.c +*** std/fs/nfs/proc.c Mon Mar 1 10:16:26 1993 +--- linux/fs/nfs/proc.c Sat Apr 24 23:53:27 1993 +*************** +*** 16,21 **** +--- 16,22 ---- + #define NFS_PROC_DEBUG + #endif + ++ #include + #include + #include + #include +*************** +*** 24,30 **** +--- 25,36 ---- + #include + #include + ++ #ifdef CONFIG_TCPIP + #include ++ #endif ++ #ifdef CONFIG_INET ++ #include ++ #endif + + #ifdef NFS_PROC_DEBUG + static int proc_debug = 0; +diff -c --recursive --new-file std/fs/nfs/sock.c linux/fs/nfs/sock.c +*** std/fs/nfs/sock.c Mon Mar 1 10:16:26 1993 +--- linux/fs/nfs/sock.c Sat Apr 24 21:15:57 1993 +*************** +*** 6,11 **** +--- 6,12 ---- + * low-level nfs remote procedure call interface + */ + ++ #include + #include + #include + #include +*************** +*** 13,21 **** + #include + #include + + #include +- + #include "../../net/kern_sock.h" + + extern struct socket *socki_lookup(struct inode *inode); + +--- 14,28 ---- + #include + #include + ++ #ifdef CONFIG_TCPIP /* FIXME: old-style NET */ + #include + #include "../../net/kern_sock.h" ++ #endif ++ #ifdef CONFIG_INET /* FIXME: new-style NET */ ++ #include ++ #include ++ #endif ++ + + extern struct socket *socki_lookup(struct inode *inode); + +diff -c --recursive --new-file std/fs/proc/Makefile linux/fs/proc/Makefile +*** std/fs/proc/Makefile Fri Dec 25 21:34:36 1992 +--- linux/fs/proc/Makefile Sat Apr 24 19:39:35 1993 +*************** +*** 14,20 **** + .s.o: + $(AS) -o $*.o $< + +! OBJS= inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o + + proc.o: $(OBJS) + $(LD) -r -o proc.o $(OBJS) +--- 14,20 ---- + .s.o: + $(AS) -o $*.o $< + +! OBJS= inode.o root.o base.o mem.o link.o fd.o array.o kmsg.o net.o + + proc.o: $(OBJS) + $(LD) -r -o proc.o $(OBJS) +diff -c --recursive --new-file std/fs/proc/inode.c linux/fs/proc/inode.c +*** std/fs/proc/inode.c Thu Apr 8 06:17:54 1993 +--- linux/fs/proc/inode.c Sat Apr 24 19:39:35 1993 +*************** +*** 100,111 **** + inode->i_op = &proc_root_inode_operations; + return; + } +! if (!pid) { + inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_array_inode_operations; +! if (ino == 5) { +! inode->i_mode = S_IFREG | 0400; +! inode->i_op = &proc_kmsg_inode_operations; + } + return; + } +--- 100,125 ---- + inode->i_op = &proc_root_inode_operations; + return; + } +! if ((ino >= 128) && (ino <= 160)) { /* files within /proc/net */ + inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_net_inode_operations; +! return; +! } +! if (!pid) { +! switch (ino) { +! case 5: +! inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_kmsg_inode_operations; +! break; +! case 8: /* for the net directory */ +! inode->i_mode = S_IFDIR | 0555; +! inode->i_nlink = 2; +! inode->i_op = &proc_net_inode_operations; +! break; +! default: +! inode->i_mode = S_IFREG | 0444; +! inode->i_op = &proc_array_inode_operations; +! break; + } + return; + } +diff -c --recursive --new-file std/fs/proc/net.c linux/fs/proc/net.c +*** std/fs/proc/net.c +--- linux/fs/proc/net.c Sat Apr 24 21:05:18 1993 +*************** +*** 0 **** +--- 1,211 ---- ++ /* ++ * linux/fs/proc/net.c ++ * ++ * Copyright (C) 1991, 1992 Linus Torvalds ++ * ++ * gjh 3/'93 heim@peanuts.informatik.uni-tuebingen.de (Gerald J. Heim) ++ * most of this file is stolen from base.c ++ * it works, but you shouldn't use it as a guideline ++ * for new proc-fs entries. once i'll make it better. ++ * fvk 3/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen) ++ * cleaned up the whole thing, moved "net" specific code to ++ * the NET kernel layer (where it belonged in the first place). ++ * Michael K. Johnson (johnsonm@stolaf.edu) 3/93 ++ * Added support from my previous inet.c. Cleaned things up ++ * quite a bit, modularized the code. ++ * fvk 4/'93 waltje@uwalt.nl.mugnet.org (Fred N. van Kempen) ++ * Renamed "route_get_info()" to "rt_get_info()" for consistency. ++ * ++ * proc net directory handling functions ++ */ ++ #include ++ ++ #include ++ ++ #include ++ #include ++ #include ++ #include ++ ++ /* forward references */ ++ static int proc_readnet(struct inode * inode, struct file * file, ++ char * buf, int count); ++ static int proc_readnetdir(struct inode *, struct file *, ++ struct dirent *, int); ++ static int proc_lookupnet(struct inode *,const char *,int,struct inode **); ++ ++ /* the get_*_info() functions are in the net code, and are configured ++ in via the standard mechanism... */ ++ #ifdef CONFIG_INET ++ extern int unix_get_info(char *); ++ extern int tcp_get_info(char *); ++ extern int udp_get_info(char *); ++ extern int raw_get_info(char *); ++ extern int arp_get_info(char *); ++ extern int dev_get_info(char *); ++ extern int rt_get_info(char *); ++ #endif /* CONFIG_INET */ ++ ++ ++ static struct file_operations proc_net_operations = { ++ NULL, /* lseek - default */ ++ proc_readnet, /* read - bad */ ++ NULL, /* write - bad */ ++ proc_readnetdir, /* readdir */ ++ NULL, /* select - default */ ++ NULL, /* ioctl - default */ ++ NULL, /* mmap */ ++ NULL, /* no special open code */ ++ NULL, /* no special release code */ ++ NULL /* can't fsync */ ++ }; ++ ++ /* ++ * proc directories can do almost nothing.. ++ */ ++ struct inode_operations proc_net_inode_operations = { ++ &proc_net_operations, /* default net directory file-ops */ ++ NULL, /* create */ ++ proc_lookupnet, /* lookup */ ++ NULL, /* link */ ++ NULL, /* unlink */ ++ NULL, /* symlink */ ++ NULL, /* mkdir */ ++ NULL, /* rmdir */ ++ NULL, /* mknod */ ++ NULL, /* rename */ ++ NULL, /* readlink */ ++ NULL, /* follow_link */ ++ NULL, /* bmap */ ++ NULL, /* truncate */ ++ NULL /* permission */ ++ }; ++ ++ static struct proc_dir_entry net_dir[] = { ++ { 1,2,".." }, ++ { 8,1,"." } ++ #ifdef CONFIG_INET ++ ,{ 128,4,"unix" }, ++ { 129,3,"arp" }, ++ { 130,5,"route" }, ++ { 131,3,"dev" }, ++ { 132,3,"raw" }, ++ { 133,3,"tcp" }, ++ { 134,3,"udp" } ++ #endif /* CONFIG_INET */ ++ }; ++ ++ #define NR_NET_DIRENTRY ((sizeof (net_dir))/(sizeof (net_dir[0]))) ++ ++ ++ static int proc_lookupnet(struct inode * dir,const char * name, int len, ++ struct inode ** result) ++ { ++ unsigned int ino; ++ int i; ++ ++ *result = NULL; ++ if (!dir) ++ return -ENOENT; ++ if (!S_ISDIR(dir->i_mode)) { ++ iput(dir); ++ return -ENOENT; ++ } ++ i = NR_NET_DIRENTRY; ++ while (i-- > 0 && !proc_match(len,name,net_dir+i)) ++ /* nothing */; ++ if (i < 0) { ++ iput(dir); ++ return -ENOENT; ++ } ++ ino = net_dir[i].low_ino; ++ if (!(*result = iget(dir->i_sb,ino))) { ++ iput(dir); ++ return -ENOENT; ++ } ++ iput(dir); ++ return 0; ++ } ++ ++ static int proc_readnetdir(struct inode * inode, struct file * filp, ++ struct dirent * dirent, int count) ++ { ++ struct proc_dir_entry * de; ++ unsigned int ino; ++ int i,j; ++ ++ if (!inode || !S_ISDIR(inode->i_mode)) ++ return -EBADF; ++ ino = inode->i_ino; ++ if (((unsigned) filp->f_pos) < NR_NET_DIRENTRY) { ++ de = net_dir + filp->f_pos; ++ filp->f_pos++; ++ i = de->namelen; ++ ino = de->low_ino; ++ put_fs_long(ino, &dirent->d_ino); ++ put_fs_word(i,&dirent->d_reclen); ++ put_fs_byte(0,i+dirent->d_name); ++ j = i; ++ while (i--) ++ put_fs_byte(de->name[i], i+dirent->d_name); ++ return j; ++ } ++ return 0; ++ } ++ ++ ++ static int proc_readnet(struct inode * inode, struct file * file, ++ char * buf, int count) ++ { ++ char * page; ++ int length; ++ int end; ++ unsigned int ino; ++ ++ if (count < 0) ++ return -EINVAL; ++ page = (char *) get_free_page(GFP_KERNEL); ++ if (!page) ++ return -ENOMEM; ++ ino = inode->i_ino; ++ switch (ino) { ++ #ifdef CONFIG_INET ++ case 128: ++ length = unix_get_info(page); ++ break; ++ case 129: ++ length = arp_get_info(page); ++ break; ++ case 130: ++ length = rt_get_info(page); ++ break; ++ case 131: ++ length = dev_get_info(page); ++ break; ++ case 132: ++ length = raw_get_info(page); ++ break; ++ case 133: ++ length = tcp_get_info(page); ++ break; ++ case 134: ++ length = udp_get_info(page); ++ break; ++ #endif /* CONFIG_INET */ ++ default: ++ free_page((unsigned long) page); ++ return -EBADF; ++ } ++ if (file->f_pos >= length) { ++ free_page((unsigned long) page); ++ return 0; ++ } ++ if (count + file->f_pos > length) ++ count = length - file->f_pos; ++ end = count + file->f_pos; ++ memcpy_tofs(buf, page + file->f_pos, count); ++ free_page((unsigned long) page); ++ file->f_pos = end; ++ return count; ++ ++ } +diff -c --recursive --new-file std/fs/proc/root.c linux/fs/proc/root.c +*** std/fs/proc/root.c Sun Feb 28 11:59:43 1993 +--- linux/fs/proc/root.c Sat Apr 24 19:39:35 1993 +*************** +*** 58,64 **** + { 4,7,"meminfo" }, + { 5,4,"kmsg" }, + { 6,7,"version" }, +! { 7,4,"self" } /* will change inode # */ + }; + + #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0]))) +--- 58,65 ---- + { 4,7,"meminfo" }, + { 5,4,"kmsg" }, + { 6,7,"version" }, +! { 7,4,"self" }, /* will change inode # */ +! { 8,3,"net" } + }; + + #define NR_ROOT_DIRENTRY ((sizeof (root_dir))/(sizeof (root_dir[0]))) +diff -c --recursive --new-file std/include/linux/ddi.h linux/include/linux/ddi.h +*** std/include/linux/ddi.h +--- linux/include/linux/ddi.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,79 ---- ++ /* ++ * ddi.h Define the structure for linking in I/O drivers into the ++ * operating system kernel. This method is currently only ++ * used by NET layer drivers, but it will be expanded into ++ * a link methos for ALL kernel-resident device drivers. ++ * ++ * Version: @(#)ddi.h 1.0.2 04/22/93 ++ * ++ * Author: Fred N. van Kempen, ++ */ ++ #ifndef _LINUX_DDI_H ++ #define _LINUX_DDI_H ++ ++ ++ /* DDI control block flags. */ ++ #define DDI_FREADY 0x10000000 /* device is initialized */ ++ #define DDI_FPRESENT 0x20000000 /* device hardware is present */ ++ #define DDI_FBLKDEV 0x00000001 /* device has a BLK spec. file */ ++ #define DDI_FCHRDEV 0x00000002 /* device has a CHR spec. file */ ++ ++ /* Various constants. */ ++ #define DDI_MAXNAME 16 /* length of a DDI ID string */ ++ ++ ++ /* This structure is used to set up a DDI driver. */ ++ struct ddconf { ++ int ioaddr; /* main I/O (port) address */ ++ int ioaux; /* auxiliary I/O (HD, AST) */ ++ int irq; /* IRQ channel */ ++ int dma; /* DMA channel to use */ ++ unsigned long memsize; /* size of onboard memory */ ++ unsigned long memaddr; /* base address of memory */ ++ }; ++ ++ ++ /* The DDI device control block. */ ++ struct ddi_device { ++ char *title; /* title of the driver */ ++ char name[DDI_MAXNAME]; /* unit name of the I/O driver */ ++ short int unit; /* unit number of this driver */ ++ short int nunits; /* number of units in driver */ ++ int (*init)(struct ddi_device *); /* initialization func */ ++ int (*handler)(int, ...); /* command handler */ ++ short int major; /* driver major dev number */ ++ short int minor; /* driver minor dev number */ ++ unsigned long flags; /* various flags */ ++ struct ddconf config; /* driver HW setup */ ++ }; ++ ++ ++ /* This structure is used to set up networking protocols. */ ++ struct ddi_proto { ++ char *name; /* protocol name */ ++ void (*init)(struct ddi_proto *); /* initialization func */ ++ }; ++ ++ ++ /* This structure is used to link a STREAMS interface. */ ++ struct iflink { ++ char id[DDI_MAXNAME]; /* DDI ID string */ ++ char stream[DDI_MAXNAME]; /* STREAMS interface name */ ++ int family; /* address (protocol) family */ ++ unsigned int flags; /* any flags needed (unused) */ ++ }; ++ ++ ++ /* DDI control requests. */ ++ #define DDIOCSDBG 0x9000 /* set DDI debug level */ ++ #define DDIOCGNAME 0x9001 /* get DDI ID name */ ++ #define DDIOCGCONF 0x9002 /* get DDI HW config */ ++ #define DDIOCSCONF 0x9003 /* set DDI HW config */ ++ ++ ++ /* DDI global functions. */ ++ extern void ddi_init(void); ++ extern struct ddi_device *ddi_map(const char *id); ++ ++ ++ #endif /* _LINUX_DDI_H */ +diff -c --recursive --new-file std/include/linux/fs.h linux/include/linux/fs.h +*** std/include/linux/fs.h Thu Apr 22 10:06:20 1993 +--- linux/include/linux/fs.h Sat Apr 24 19:39:35 1993 +*************** +*** 21,31 **** + * recompiled to take full advantage of the new limits.. + */ + #undef NR_OPEN +! #define NR_OPEN 256 /* don't change - fd_set etc depend on this */ + +! #define NR_INODE 256 /* this should be bigger than NR_FILE */ +! #define NR_FILE 128 /* this can well be larger on a larger system */ +! #define NR_SUPER 16 + #define NR_HASH 997 + #define NR_FILE_LOCKS 32 + #define BLOCK_SIZE 1024 +--- 21,31 ---- + * recompiled to take full advantage of the new limits.. + */ + #undef NR_OPEN +! #define NR_OPEN 256 + +! #define NR_INODE 1024 /* changed for LINUX/Pro - FvK */ +! #define NR_FILE 512 /* changed for LINUX/Pro - FvK */ +! #define NR_SUPER 32 /* changed for LINUX/Pro - FvK */ + #define NR_HASH 997 + #define NR_FILE_LOCKS 32 + #define BLOCK_SIZE 1024 +diff -c --recursive --new-file std/include/linux/icmp.h linux/include/linux/icmp.h +*** std/include/linux/icmp.h +--- linux/include/linux/icmp.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,69 ---- ++ /* ++ * 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 ICMP protocol. ++ * ++ * Version: @(#)icmp.h 1.0.1 03/21/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_ICMP_H ++ #define _LINUX_ICMP_H ++ ++ #define ICMP_ECHOREPLY 0 ++ #define ICMP_DEST_UNREACH 3 ++ #define ICMP_SOURCE_QUENCH 4 ++ #define ICMP_REDIRECT 5 ++ #define ICMP_ECHO 8 ++ #define ICMP_TIME_EXCEEDED 11 ++ #define ICMP_PARAMETERPROB 12 ++ #define ICMP_TIMESTAMP 13 ++ #define ICMP_TIMESTAMPREPLY 14 ++ #define ICMP_INFO_REQUEST 15 ++ #define ICMP_INFO_REPLY 16 ++ ++ ++ /* Used by unreachable. */ ++ #define ICMP_NET_UNREACH 0 ++ #define ICMP_HOST_UNREACH 1 ++ #define ICMP_PROT_UNREACH 2 ++ #define ICMP_PORT_UNREACH 3 /* lots of room for confusion. */ ++ #define ICMP_FRAG_NNEDED 4 ++ #define ICMP_SR_FAILED 5 ++ #define ICMP_NET_UNKNOWN 6 ++ #define ICMP_HOST_UNKNOWN 7 ++ #define ICMP_HOST_ISOLATED 8 ++ #define ICMP_NET_ANO 9 ++ #define ICMP_HOST_ANO 10 ++ #define ICMP_NET_UNR_TOS 11 ++ #define ICMP_HOST_UNR_TOS 12 ++ ++ ++ struct icmp_header { ++ unsigned char type; ++ unsigned char code; ++ unsigned short checksum; ++ union { ++ struct { ++ unsigned short id; ++ unsigned short sequence; ++ } echo; ++ unsigned long gateway; ++ } un; ++ }; ++ ++ ++ struct icmp_err { ++ int errno; ++ unsigned fatal:1; ++ }; ++ ++ ++ #endif /* _LINUX_ICMP_H */ +diff -c --recursive --new-file std/include/linux/if.h linux/include/linux/if.h +*** std/include/linux/if.h +--- linux/include/linux/if.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,147 ---- ++ /* ++ * 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 INET interface module. ++ * ++ * Version: @(#)if.h 1.0.2 04/18/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988 ++ * Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_H ++ #define _LINUX_IF_H ++ ++ #include /* for "caddr_t" et al */ ++ #include /* for "struct sockaddr" et al */ ++ ++ ++ /* Structure defining a queue for a network interface. */ ++ struct ifnet { ++ char *if_name; /* name, e.g. ``en'' or ``lo'' */ ++ short if_unit; /* sub-unit for device driver */ ++ short if_mtu; /* maximum transmission unit */ ++ short if_flags; /* up/down, broadcast, etc. */ ++ short if_timer; /* time 'til if_watchdog called */ ++ int if_metric; /* routing metric (not used) */ ++ struct ifaddr *if_addrlist; /* linked list of addrs per if */ ++ struct ifqueue { ++ #ifdef not_yet_in_linux ++ struct mbuf *ifq_head; ++ struct mbuf *ifq_tail; ++ int ifq_len; ++ int ifq_maxlen; ++ int ifq_drops; ++ #endif ++ } if_snd; /* output queue */ ++ ++ /* Procedure handles. */ ++ int (*if_init)(); /* init routine */ ++ int (*if_output)(); /* output routine */ ++ int (*if_ioctl)(); /* ioctl routine */ ++ int (*if_reset)(); /* bus reset routine */ ++ int (*if_watchdog)(); /* timer routine */ ++ ++ /* Generic interface statistics. */ ++ int if_ipackets; /* packets recv'd on interface */ ++ int if_ierrors; /* input errors on interface */ ++ int if_opackets; /* packets sent on interface */ ++ int if_oerrors; /* output errors on interface */ ++ int if_collisions; /* collisions on CSMA i'faces */ ++ ++ /* Linked list: pointer to next interface. */ ++ struct ifnet *if_next; ++ }; ++ ++ /* Standard interface flags. */ ++ #define IFF_UP 0x1 /* interface is up */ ++ #define IFF_BROADCAST 0x2 /* broadcast address valid */ ++ #define IFF_DEBUG 0x4 /* turn on debugging */ ++ #define IFF_LOOPBACK 0x8 /* is a loopback net */ ++ #define IFF_POINTOPOINT 0x10 /* interface is has p-p link */ ++ #define IFF_NOTRAILERS 0x20 /* avoid use of trailers */ ++ #define IFF_RUNNING 0x40 /* resources allocated */ ++ #define IFF_NOARP 0x80 /* no ARP protocol */ ++ ++ /* These are not yet used: */ ++ #define IFF_PROMISC 0x100 /* recve all packets */ ++ #define IFF_ALLMULTI 0x200 /* recve all multicast packets */ ++ ++ ++ /* ++ * The ifaddr structure contains information about one address ++ * of an interface. They are maintained by the different address ++ * families, are allocated and attached when an address is set, ++ * and are linked together so all addresses for an interface can ++ * be located. ++ */ ++ struct ifaddr { ++ struct sockaddr ifa_addr; /* address of interface */ ++ union { ++ struct sockaddr ifu_broadaddr; ++ struct sockaddr ifu_dstaddr; ++ } ifa_ifu; ++ struct iface *ifa_ifp; /* back-pointer to interface */ ++ struct ifaddr *ifa_next; /* next address for interface */ ++ }; ++ #define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */ ++ #define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */ ++ ++ /* ++ * Interface request structure used for socket ++ * ioctl's. All interface ioctl's must have parameter ++ * definitions which begin with ifr_name. The ++ * remainder may be interface specific. ++ */ ++ struct ifreq { ++ #define IFNAMSIZ 16 ++ char ifr_name[IFNAMSIZ]; /* if name, e.g. "en0" */ ++ union { ++ struct sockaddr ifru_addr; ++ struct sockaddr ifru_dstaddr; ++ struct sockaddr ifru_broadaddr; ++ struct sockaddr ifru_netmask; ++ short ifru_flags; ++ int ifru_metric; ++ int ifru_mtu; ++ caddr_t ifru_data; ++ } ifr_ifru; ++ }; ++ #define ifr_addr ifr_ifru.ifru_addr /* address */ ++ #define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */ ++ #define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */ ++ #define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */ ++ #define ifr_flags ifr_ifru.ifru_flags /* flags */ ++ #define ifr_metric ifr_ifru.ifru_metric /* metric */ ++ #define ifr_mtu ifr_ifru.ifru_mtu /* mtu */ ++ #define ifr_data ifr_ifru.ifru_data /* for use by interface */ ++ ++ /* ++ * Structure used in SIOCGIFCONF request. ++ * Used to retrieve interface configuration ++ * for machine (useful for programs which ++ * must know all networks accessible). ++ */ ++ struct ifconf { ++ int ifc_len; /* size of buffer */ ++ union { ++ caddr_t ifcu_buf; ++ struct ifreq *ifcu_req; ++ } ifc_ifcu; ++ }; ++ #define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */ ++ #define ifc_req ifc_ifcu.ifcu_req /* array of structures */ ++ ++ ++ /* BSD UNIX expects to find these here, so here we go: */ ++ #include ++ #include ++ ++ #endif /* _NET_IF_H */ +diff -c --recursive --new-file std/include/linux/if_arp.h linux/include/linux/if_arp.h +*** std/include/linux/if_arp.h +--- linux/include/linux/if_arp.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,83 ---- ++ /* ++ * 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 ARP (RFC 826) protocol. ++ * ++ * Version: @(#)if_arp.h 1.0.1 04/16/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 ++ * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source. ++ * Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_ARP_H ++ #define _LINUX_IF_ARP_H ++ ++ /* ARP protocol HARDWARE identifiers. */ ++ #define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */ ++ #define ARPHRD_ETHER 1 /* Ethernet 10Mbps */ ++ #define ARPHRD_EETHER 2 /* Experimental Ethernet */ ++ #define ARPHRD_AX25 3 /* AX.25 Level 2 */ ++ #define ARPHRD_PRONET 4 /* PROnet token ring */ ++ #define ARPHRD_CHAOS 5 /* Chaosnet */ ++ #define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet- huh? */ ++ #define ARPHRD_ARCNET 7 /* ARCnet */ ++ #define ARPHRD_APPLETLK 8 /* APPLEtalk */ ++ ++ /* ARP protocol opcodes. */ ++ #define ARPOP_REQUEST 1 /* ARP request */ ++ #define ARPOP_REPLY 2 /* ARP reply */ ++ #define ARPOP_RREQUEST 3 /* RARP request */ ++ #define ARPOP_RREPLY 4 /* RARP reply */ ++ ++ ++ /* ++ * Address Resolution Protocol. ++ * ++ * See RFC 826 for protocol description. ARP packets are variable ++ * in size; the arphdr structure defines the fixed-length portion. ++ * Protocol type values are the same as those for 10 Mb/s Ethernet. ++ * It is followed by the variable-sized fields ar_sha, arp_spa, ++ * arp_tha and arp_tpa in that order, according to the lengths ++ * specified. Field names used correspond to RFC 826. ++ */ ++ struct arphdr { ++ unsigned short ar_hrd; /* format of hardware address */ ++ unsigned short ar_pro; /* format of protocol address */ ++ unsigned char ar_hln; /* length of hardware address */ ++ unsigned char ar_pln; /* length of protocol address */ ++ unsigned short ar_op; /* ARP opcode (command) */ ++ ++ /* The rest is variable in size, according to the sizes above. */ ++ #if 0 ++ unsigned char ar_sha[]; /* sender hardware address */ ++ unsigned char ar_spa[]; /* sender protocol address */ ++ unsigned char ar_tha[]; /* target hardware address */ ++ unsigned char ar_tpa[]; /* target protocol address */ ++ #endif /* not actually included! */ ++ }; ++ ++ ++ /* ARP ioctl request. */ ++ struct arpreq { ++ struct sockaddr arp_pa; /* protocol address */ ++ struct sockaddr arp_ha; /* hardware address */ ++ int arp_flags; /* flags */ ++ }; ++ ++ /* ARP Flag values. */ ++ #define ATF_INUSE 0x01 /* entry in use */ ++ #define ATF_COM 0x02 /* completed entry (ha valid) */ ++ #define ATF_PERM 0x04 /* permanent entry */ ++ #define ATF_PUBL 0x08 /* publish entry */ ++ #define ATF_USETRAILERS 0x10 /* has requested trailers */ ++ ++ ++ #endif /* _LINUX_IF_ARP_H */ +diff -c --recursive --new-file std/include/linux/if_ether.h linux/include/linux/if_ether.h +*** std/include/linux/if_ether.h +--- linux/include/linux/if_ether.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,88 ---- ++ /* ++ * 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 Ethernet IEE 802.3 interface. ++ * ++ * Version: @(#)if_ether.h 1.0.1 03/15/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_ETHER_H ++ #define _LINUX_IF_ETHER_H ++ ++ ++ /* IEEE 802.3 Ethernet magic constants. */ ++ #define ETH_ALEN 6 /* #bytes in eth addr */ ++ #define ETH_HLEN 14 /* #bytes in eth header */ ++ #define ETH_ZLEN 64 /* min #bytes in frame */ ++ #define ETH_FLEN 1536 /* max #bytes in frame */ ++ #define ETH_DLEN (ETH_FLEN - ETH_HLEN) /* max #bytes of data */ ++ ++ /* These are the defined Ethernet Protocol ID's. */ ++ #define ETH_P_LOOP 0x0060 /* Ethernet Loopback packet */ ++ #define ETH_P_ECHO 0x0200 /* Ethernet Echo packet */ ++ #define ETH_P_PUP 0x0400 /* Xerox PUP packet */ ++ #define ETH_P_IP 0x0800 /* Internet Protocol packet */ ++ #define ETH_P_ARP 0x0806 /* Address Resolution packet */ ++ #define ETH_P_RARP 0x0835 /* Reverse Addr Res packet */ ++ ++ /* Define the Ethernet Broadcast Address (48 bits set to "1"). */ ++ #define ETH_A_BCAST "\377\377\377\377\377\377" ++ ++ /* This is an Ethernet frame header. */ ++ struct ethhdr { ++ unsigned char h_dest[ETH_ALEN]; /* destination eth addr */ ++ unsigned char h_source[ETH_ALEN]; /* source ether addr */ ++ unsigned short h_proto; /* packet type ID field */ ++ }; ++ ++ /* This is the complete Ethernet frame. */ ++ struct ethframe { ++ struct ethhdr f_hdr; /* frame header */ ++ char f_data[ETH_DLEN]; /* frame data (variable)*/ ++ }; ++ ++ ++ /* Receiver modes */ ++ #define ETH_MODE_MONITOR 1 /* Monitor mode - no receive */ ++ #define ETH_MODE_PHYS 2 /* Physical address receive only */ ++ #define ETH_MODE_BCAST 3 /* Broadcast receive + mode 2 */ ++ #define ETH_MODE_MCAST 4 /* Multicast receive + mode 3 */ ++ #define ETH_MODE_PROMISC 5 /* Promiscuous mode - receive all */ ++ ++ ++ /* Ethernet statistics collection data. */ ++ struct enet_statistics{ ++ int rx_packets; /* total packets received */ ++ int tx_packets; /* total packets transmitted */ ++ int rx_errors; /* bad packets received */ ++ int tx_errors; /* packet transmit problems */ ++ int rx_dropped; /* no space in linux buffers */ ++ int tx_dropped; /* no space available in linux */ ++ int multicast; /* multicast packets received */ ++ int collisions; ++ ++ /* detailed rx_errors: */ ++ int rx_length_errors; ++ int rx_over_errors; /* receiver ring buff overflow */ ++ int rx_crc_errors; /* recved pkt with crc error */ ++ int rx_frame_errors; /* recv'd frame alignment error */ ++ int rx_fifo_errors; /* recv'r fifo overrun */ ++ int rx_missed_errors; /* receiver missed packet */ ++ ++ /* detailed tx_errors */ ++ int tx_aborted_errors; ++ int tx_carrier_errors; ++ int tx_fifo_errors; ++ int tx_heartbeat_errors; ++ int tx_window_errors; ++ }; ++ ++ #endif /* _LINUX_IF_ETHER_H */ +diff -c --recursive --new-file std/include/linux/in.h linux/include/linux/in.h +*** std/include/linux/in.h +--- linux/include/linux/in.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,171 ---- ++ /* ++ * 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 of the Internet Protocol. ++ * ++ * Version: @(#)in.h 1.0.1 04/21/93 ++ * ++ * Authors: Original taken from the GNU Project file. ++ * Fred N. van Kempen, ++ * ++ * 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_IN_H ++ #define _LINUX_IN_H ++ ++ ++ /* Standard well-defined IP protocols. */ ++ enum { ++ IPPROTO_IP = 0, /* Dummy protocol for TCP */ ++ IPPROTO_ICMP = 1, /* Internet Control Message Protocol */ ++ IPPROTO_GGP = 2, /* Gateway Protocol (deprecated) */ ++ IPPROTO_TCP = 6, /* Transmission Control Protocol */ ++ IPPROTO_EGP = 8, /* Exterior Gateway Protocol */ ++ IPPROTO_PUP = 12, /* PUP protocol */ ++ IPPROTO_UDP = 17, /* User Datagram Protocol */ ++ IPPROTO_IDP = 22, /* XNS IDP protocol */ ++ ++ IPPROTO_RAW = 255, /* Raw IP packets */ ++ IPPROTO_MAX ++ }; ++ ++ ++ /* Internet address. */ ++ struct in_addr { ++ unsigned long int s_addr; ++ }; ++ ++ ++ /* Structure describing an Internet (IP) socket address. */ ++ #define __SOCK_SIZE__ 16 /* sizeof(struct sockaddr) */ ++ struct sockaddr_in { ++ short int sin_family; /* Address family */ ++ unsigned short int sin_port; /* Port number */ ++ struct in_addr sin_addr; /* Internet address */ ++ ++ /* Pad to size of `struct sockaddr'. */ ++ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - ++ sizeof(unsigned short int) - sizeof(struct in_addr)]; ++ }; ++ #define sin_zero __pad /* for BSD UNIX comp. -FvK */ ++ ++ ++ /* ++ * Definitions of the bits in an Internet address integer. ++ * On subnets, host and network parts are found according ++ * to the subnet mask, not these masks. ++ */ ++ #define IN_CLASSA(a) ((((long int) (a)) & 0x80000000) == 0) ++ #define IN_CLASSA_NET 0xff000000 ++ #define IN_CLASSA_NSHIFT 24 ++ #define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET) ++ #define IN_CLASSA_MAX 128 ++ ++ #define IN_CLASSB(a) ((((long int) (a)) & 0xc0000000) == 0x80000000) ++ #define IN_CLASSB_NET 0xffff0000 ++ #define IN_CLASSB_NSHIFT 16 ++ #define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET) ++ #define IN_CLASSB_MAX 65536 ++ ++ #define IN_CLASSC(a) ((((long int) (a)) & 0xc0000000) == 0xc0000000) ++ #define IN_CLASSC_NET 0xffffff00 ++ #define IN_CLASSC_NSHIFT 8 ++ #define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET) ++ ++ #define IN_CLASSD(a) ((((long int) (a)) & 0xf0000000) = 0xe0000000) ++ #define IN_MULTICAST(a) IN_CLASSD(a) ++ ++ #define IN_EXPERIMENTAL(a) ((((long int) (a)) & 0xe0000000) = 0xe0000000) ++ #define IN_BADCLASS(a) ((((long int) (a)) & 0xf0000000) = 0xf0000000) ++ ++ /* Address to accept any incoming messages. */ ++ #define INADDR_ANY ((unsigned long int) 0x00000000) ++ ++ /* Address to send to all hosts. */ ++ #define INADDR_BROADCAST ((unsigned long int) 0xffffffff) ++ ++ /* Address indicating an error return. */ ++ #define INADDR_NONE 0xffffffff ++ ++ /* Network number for local host loopback. */ ++ #define IN_LOOPBACKNET 127 ++ ++ /* Address to loopback in software to local host. */ ++ #define INADDR_LOOPBACK 0x7f000001 /* 127.0.0.1 */ ++ ++ ++ /* ++ * Options for use with `getsockopt' and `setsockopt' at ++ * the IP level. LINUX does not yet have the IP_OPTIONS ++ * option (grin), so we undefine it for now.- HJ && FvK ++ */ ++ #if 0 ++ # define IP_OPTIONS 1 /* IP per-packet options */ ++ #endif ++ #define IP_HDRINCL 2 /* raw packet header option */ ++ ++ ++ /* Linux Internet number representation function declarations. */ ++ #undef ntohl ++ #undef ntohs ++ #undef htonl ++ #undef htons ++ ++ extern unsigned long int ntohl(unsigned long int); ++ extern unsigned short int ntohs(unsigned short int); ++ extern unsigned long int htonl(unsigned long int); ++ extern unsigned short int htons(unsigned short int); ++ ++ static __inline__ unsigned long int ++ __ntohl(unsigned long int x) ++ { ++ register unsigned long int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap lower bytes */ ++ "rorl $16,%%eax\n\t" /* swap words */ ++ "xchgb %%al,%%ah\n\t" /* swap higher bytes */ ++ : "=a" (tmp) : "a" (tmp) ); ++ return(tmp); ++ } ++ ++ static __inline__ unsigned short int ++ __ntohs(unsigned short int x) ++ { ++ register unsigned short int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap bytes */ ++ : "=a" (tmp) : "a" (tmp)); ++ return(tmp); ++ } ++ ++ static __inline__ unsigned long int ++ __htonl(unsigned long int x) ++ { ++ register unsigned long int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap lower bytes */ ++ "rorl $16,%%eax\n\t" /* swap words */ ++ "xchgb %%al,%%ah\n\t" /* swap higher bytes */ ++ : "=a" (tmp) : "a" (tmp)); ++ return(tmp); ++ } ++ ++ static __inline__ unsigned short int ++ __htons(unsigned short int x) ++ { ++ register unsigned short int tmp __asm__ ("ax") = x; ++ __asm__ __volatile__ ("xchgb %%al,%%ah\n\t" /* swap bytes */ ++ : "=a" (tmp) : "a" (tmp)); ++ return(tmp); ++ } ++ ++ #ifdef __OPTIMIZE__ ++ # define ntohl(x) __ntohl((x)) ++ # define ntohs(x) __ntohs((x)) ++ # define htonl(x) __htonl((x)) ++ # define htons(x) __htons((x)) ++ #endif ++ ++ #endif /* _LINUX_IN_H */ +diff -c --recursive --new-file std/include/linux/ip.h linux/include/linux/ip.h +*** std/include/linux/ip.h +--- linux/include/linux/ip.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,81 ---- ++ /* ++ * 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 IP protocol. ++ * ++ * Version: @(#)ip.h 1.0.1 03/21/93 ++ * ++ * Authors: Fred N. van Kempen, ++ * ++ * 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_IP_H ++ #define _LINUX_IP_H ++ ++ ++ #define IPOPT_END 0 ++ #define IPOPT_NOOP 1 ++ #define IPOPT_SEC 130 ++ #define IPOPT_LSRR 131 ++ #define IPOPT_SSRR 137 ++ #define IPOPT_RR 7 ++ #define IPOPT_SID 136 ++ #define IPOPT_TIMESTAMP 68 ++ ++ ++ struct timestamp { ++ unsigned char len; ++ unsigned char ptr; ++ union { ++ unsigned char flags:4, ++ overflow:4; ++ unsigned char full_char; ++ } x; ++ unsigned long data[9]; ++ }; ++ ++ ++ #define MAX_ROUTE 16 ++ ++ struct route { ++ char route_size; ++ char pointer; ++ unsigned long route[MAX_ROUTE]; ++ }; ++ ++ ++ struct options { ++ struct route record_route; ++ struct route loose_route; ++ struct route strict_route; ++ struct timestamp tstamp; ++ unsigned short security; ++ unsigned short compartment; ++ unsigned short handling; ++ unsigned short stream; ++ unsigned tcc; ++ }; ++ ++ ++ struct ip_header { ++ unsigned char ihl:4, ++ version:4; ++ unsigned char tos; ++ unsigned short tot_len; ++ unsigned short id; ++ unsigned short frag_off; ++ unsigned char ttl; ++ unsigned char protocol; ++ unsigned short check; ++ unsigned long saddr; ++ unsigned long daddr; ++ /*The options start here. */ ++ }; ++ ++ ++ #endif /* _LINUX_IP_H */ +diff -c --recursive --new-file std/include/linux/net.h linux/include/linux/net.h +*** std/include/linux/net.h +--- linux/include/linux/net.h Sat Apr 24 19:39:35 1993 +*************** +*** 0 **** +--- 1,130 ---- ++ /* ++ * NET An implementation of the SOCKET network access protocol. ++ * This is the master header file for the Linux NET layer, ++ * or, in plain English: the networking handling part of the ++ * kernel. ++ * ++ * Version: @(#)net.h 1.0.1 04/22/93 ++ * ++ * Authors: ??? ++ * Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_NET_H ++ #define _LINUX_NET_H ++ ++ ++ #define NSOCKETS 128 /* should be dynamic, later... */ ++ #define NPROTO 16 /* should be enough for now.. */ ++ #define SOCKET_MAJOR 16 /* Linux VFS major dev number */ ++ ++ ++ #define SYS_SOCKET 1 /* sys_socket(2) */ ++ #define SYS_BIND 2 /* sys_bind(2) */ ++ #define SYS_CONNECT 3 /* sys_connect(2) */ ++ #define SYS_LISTEN 4 /* sys_listen(2) */ ++ #define SYS_ACCEPT 5 /* sys_accept(2) */ ++ #define SYS_GETSOCKNAME 6 /* sys_getsockname(2) */ ++ #define SYS_GETPEERNAME 7 /* sys_getpeername(2) */ ++ #define SYS_SOCKETPAIR 8 /* sys_socketpair(2) */ ++ #define SYS_SEND 9 /* sys_send(2) */ ++ #define SYS_RECV 10 /* sys_recv(2) */ ++ #define SYS_SENDTO 11 /* sys_sendto(2) */ ++ #define SYS_RECVFROM 12 /* sys_recvfrom(2) */ ++ #define SYS_SHUTDOWN 13 /* sys_shutdown(2) */ ++ #define SYS_SETSOCKOPT 14 /* sys_setsockopt(2) */ ++ #define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ ++ ++ ++ typedef enum { ++ SS_FREE = 0, /* not allocated */ ++ SS_UNCONNECTED, /* unconnected to any socket */ ++ SS_CONNECTING, /* in process of connecting */ ++ SS_CONNECTED, /* connected to socket */ ++ SS_DISCONNECTING, /* in process of disconnecting */ ++ } socket_state; ++ ++ #define SO_ACCEPTCON (1<<16) /* performed a listen */ ++ ++ ++ /* ++ * Internel representation of a socket. not all the fields are used by ++ * all configurations: ++ * ++ * server client ++ * conn client connected to server connected to ++ * iconn list of clients -unused- ++ * awaiting connections ++ * wait sleep for clients, sleep for connection, ++ * sleep for i/o sleep for i/o ++ */ ++ struct socket { ++ short type; /* SOCK_STREAM, ... */ ++ socket_state state; ++ long flags; ++ struct proto_ops *ops; /* protocols do most everything */ ++ void *data; /* protocol data */ ++ struct socket *conn; /* server socket connected to */ ++ struct socket *iconn; /* incomplete client conn.s */ ++ struct socket *next; ++ struct wait_queue **wait; /* ptr to place to wait on */ ++ void *dummy; ++ }; ++ ++ #define SOCK_INODE(S) ((struct inode *)(S)->dummy) ++ extern struct socket sockets[NSOCKETS]; ++ #define last_socket (sockets + NSOCKETS - 1) ++ ++ ++ struct proto_ops { ++ int family; ++ ++ int (*create) (struct socket *sock, int protocol); ++ 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); ++ int (*connect) (struct socket *sock, struct sockaddr *uservaddr, ++ int 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); ++ int (*read) (struct socket *sock, char *ubuf, int size, ++ int nonblock); ++ int (*write) (struct socket *sock, char *ubuf, int size, ++ int nonblock); ++ int (*select) (struct socket *sock, int sel_type, ++ select_table *wait); ++ int (*ioctl) (struct socket *sock, unsigned int cmd, ++ unsigned long arg); ++ int (*listen) (struct socket *sock, int len); ++ int (*send) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags); ++ int (*recv) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags); ++ int (*sendto) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags, struct sockaddr *, int addr_len); ++ int (*recvfrom) (struct socket *sock, void *buff, int len, int nonblock, ++ unsigned flags, struct sockaddr *, int *addr_len); ++ int (*shutdown) (struct socket *sock, int flags); ++ int (*setsockopt) (struct socket *sock, int level, int optname, ++ char *optval, int optlen); ++ int (*getsockopt) (struct socket *sock, int level, int optname, ++ char *optval, int *optlen); ++ int (*fcntl) (struct socket *sock, unsigned int cmd, ++ unsigned long arg); ++ }; ++ ++ ++ extern int sock_awaitconn(struct socket *mysock, struct socket *servsock); ++ extern int sock_register(int family, struct proto_ops *ops); ++ ++ ++ #endif /* _LINUX_NET_H */ +diff -c --recursive --new-file std/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h +*** std/include/linux/nfs_fs.h Tue Apr 6 20:57:21 1993 +--- linux/include/linux/nfs_fs.h Sat Apr 24 19:39:35 1993 +*************** +*** 11,17 **** + + #include + +! #include + #include + + /* +--- 11,17 ---- + + #include + +! #include + #include + + /* +diff -c --recursive --new-file std/include/linux/proc_fs.h linux/include/linux/proc_fs.h +*** std/include/linux/proc_fs.h Tue Apr 6 20:57:21 1993 +--- linux/include/linux/proc_fs.h Sat Apr 24 19:39:35 1993 +*************** +*** 25,34 **** +--- 25,36 ---- + + extern struct inode_operations proc_root_inode_operations; + extern struct inode_operations proc_base_inode_operations; ++ extern struct inode_operations proc_net_inode_operations; + extern struct inode_operations proc_mem_inode_operations; + extern struct inode_operations proc_array_inode_operations; + extern struct inode_operations proc_kmsg_inode_operations; + extern struct inode_operations proc_link_inode_operations; + extern struct inode_operations proc_fd_inode_operations; ++ extern struct inode_operations proc_net_inode_operations; + + #endif +diff -c --recursive --new-file std/include/linux/route.h linux/include/linux/route.h +*** std/include/linux/route.h +--- linux/include/linux/route.h Sat Apr 24 19:39:36 1993 +*************** +*** 0 **** +--- 1,49 ---- ++ /* ++ * 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 IP router interface. ++ * ++ * Version: @(#)route.h 1.0.2 04/16/93 ++ * ++ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988 ++ * Fred N. van Kempen, ++ * ++ * 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_ROUTE_H ++ #define _LINUX_ROUTE_H ++ ++ #include ++ ++ ++ /* ++ * This structure gets passed by the SIOCADDRT and SIOCDELRT calls. ++ * It is not exactly identical to the BSD UNIX version of "rtentry", ++ * because BSD used /dev/kmem to figure out interface addresses. We ++ * do it cleaner, using a character array to stuff the name into. ++ * Also, to clean up things, the real IP routing table does not use ++ * the "struct sockaddr" addresses- it uses simple "unsigned long" ++ * fields. Routing is a protocol-dependent thing anyway. -FvK ++ */ ++ struct rtentry { ++ char rt_dev[IFNAMSIZ]; ++ struct sockaddr rt_dst; ++ struct sockaddr rt_gateway; ++ u_char rt_flags; ++ u_char rt_metric; ++ short rt_refcnt; ++ unsigned long rt_use; ++ }; ++ #define RTF_UP 0x0001 /* route useable */ ++ #define RTF_GATEWAY 0x0002 /* destination is a gateway */ ++ #define RTF_HOST 0x0004 /* host entry (net otherwise) */ ++ #define RTF_REINSTATE 0x0008 /* re-instate route after tmout */ ++ #define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */ ++ #define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */ ++ ++ #endif /* _LINUX_ROUTE_H */ +diff -c --recursive --new-file std/include/linux/sock_ioctl.h linux/include/linux/sock_ioctl.h +*** std/include/linux/sock_ioctl.h Sun Feb 28 14:59:14 1993 +--- linux/include/linux/sock_ioctl.h Sat Apr 24 19:39:36 1993 +*************** +*** 1,35 **** +- #ifndef _LINUX_SOCK_IOCTL_H +- #define _LINUX_SOCK_IOCTL_H +- +- #define MAX_IP_NAME 20 +- /* some ioctl. Their values are not special. */ +- #define IP_SET_DEV 0x2401 +- +- struct ip_config +- { +- char name[MAX_IP_NAME]; +- unsigned long paddr; +- unsigned long router; +- unsigned long net; +- unsigned long up:1,destroy:1; +- }; +- +- #define SIOCSARP 0x2501 +- #define SIOCGARP 0x2502 +- #define SIOCDARP 0x2503 +- +- /* +- * ARP ioctl request +- */ +- struct arpreq { +- struct sockaddr arp_pa; /* protocol address */ +- struct sockaddr arp_ha; /* hardware address */ +- int arp_flags; /* flags */ +- }; +- +- #define ATF_COM 0x02 +- #define ATF_PERM 0x04 +- #define ATF_PUBL 0x08 +- #define ATF_USETRAILERS 0x10 +- +- #endif +--- 0 ---- +diff -c --recursive --new-file std/include/linux/socket.h linux/include/linux/socket.h +*** std/include/linux/socket.h Tue Nov 10 12:54:55 1992 +--- linux/include/linux/socket.h Sat Apr 24 19:39:36 1993 +*************** +*** 1,51 **** + #ifndef _LINUX_SOCKET_H + #define _LINUX_SOCKET_H + + struct sockaddr { +! unsigned short sa_family; /* address family, AF_xxx */ +! char sa_data[14]; /* 14 bytes of protocol address */ + }; + +! /* +! * socket types +! */ +! #define SOCK_STREAM 1 /* stream (connection) socket */ +! #define SOCK_DGRAM 2 /* datagram (connectionless) socket */ +! #define SOCK_RAW 3 /* raw socket */ +! #define SOCK_RDM 4 /* reliably-delivered message */ +! #define SOCK_SEQPACKET 5 /* sequential packet socket */ +! #define SOCK_PACKET 10 /* linux specific way of getting +! packets at the dev level. For +! writing rarp and other similiar +! things on the user level. */ +! +! /* +! * supported address families +! */ + #define AF_UNSPEC 0 + #define AF_UNIX 1 + #define AF_INET 2 + +! /* +! * protocol families, same as address families +! */ + #define PF_UNIX AF_UNIX + #define PF_INET AF_INET + +! /* flags we can use with send/ and recv. */ + #define MSG_OOB 1 + #define MSG_PEEK 2 + +! /* ioctl's */ +! #define FIOSETOWN 0x8901 /* the 89 is for uniqueness. +! This should be somewhere else. */ +! #define SIOCSPGRP 0x8902 +! #define FIOGETOWN 0x8903 /* this too. */ +! #define SIOCGPGRP 0x8904 +! #define SIOCATMARK 0x8905 +! + +! /* for setsockoptions */ + #define SO_DEBUG 1 + #define SO_REUSEADDR 2 + #define SO_TYPE 3 +--- 1,43 ---- + #ifndef _LINUX_SOCKET_H + #define _LINUX_SOCKET_H + ++ #include /* the SIOCxxx I/O controls */ ++ ++ + struct sockaddr { +! unsigned short sa_family; /* address family, AF_xxx */ +! char sa_data[14]; /* 14 bytes of protocol address */ + }; + +! /* Socket types. */ +! #define SOCK_STREAM 1 /* stream (connection) socket */ +! #define SOCK_DGRAM 2 /* datagram (conn.less) socket */ +! #define SOCK_RAW 3 /* raw socket */ +! #define SOCK_RDM 4 /* reliably-delivered message */ +! #define SOCK_SEQPACKET 5 /* sequential packet socket */ +! #define SOCK_PACKET 10 /* linux specific way of */ +! /* getting packets at the dev */ +! /* level. For writing rarp and */ +! /* other similiar things on the */ +! /* user level. */ +! +! /* Supported address families. */ + #define AF_UNSPEC 0 + #define AF_UNIX 1 + #define AF_INET 2 + +! /* Protocol families, same as address families. */ + #define PF_UNIX AF_UNIX + #define PF_INET AF_INET + +! /* Flags we can use with send/ and recv. */ + #define MSG_OOB 1 + #define MSG_PEEK 2 + +! /* Setsockoptions(2) level. */ +! #define SOL_SOCKET 1 + +! /* For setsockoptions(2) */ + #define SO_DEBUG 1 + #define SO_REUSEADDR 2 + #define SO_TYPE 3 +*************** +*** 55,71 **** + #define SO_SNDBUF 7 + #define SO_RCVBUF 8 + #define SO_KEEPALIVE 9 +! #define SO_OOBINLINE 10 +! #define SO_NO_CHECK 11 +! #define SO_PRIORITY 12 +! #define SO_LINGER 13 + +! /* the different priorities */ + #define SOPRI_INTERACTIVE 0 + #define SOPRI_NORMAL 1 + #define SOPRI_BACKGROUND 2 + +- /* setsockoptions level */ +- #define SOL_SOCKET 1 +- + #endif /* _LINUX_SOCKET_H */ +--- 47,60 ---- + #define SO_SNDBUF 7 + #define SO_RCVBUF 8 + #define SO_KEEPALIVE 9 +! #define SO_OOBINLINE 10 +! #define SO_NO_CHECK 11 +! #define SO_PRIORITY 12 +! #define SO_LINGER 13 + +! /* The various priorities. */ + #define SOPRI_INTERACTIVE 0 + #define SOPRI_NORMAL 1 + #define SOPRI_BACKGROUND 2 + + #endif /* _LINUX_SOCKET_H */ +diff -c --recursive --new-file std/include/linux/sockios.h linux/include/linux/sockios.h +*** std/include/linux/sockios.h +--- linux/include/linux/sockios.h Sat Apr 24 19:39:36 1993 +*************** +*** 0 **** +--- 1,72 ---- ++ /* ++ * 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 of the socket-level I/O control calls. ++ * ++ * Version: @(#)sockios.h 1.0.2 03/09/93 ++ * ++ * Authors: Ross Biro, ++ * Fred N. van Kempen, ++ * ++ * 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_SOCKIOS_H ++ #define _LINUX_SOCKIOS_H ++ ++ /* This section will go away soon! */ ++ #if 1 /* FIXME: */ ++ #define MAX_IP_NAME 20 ++ #define IP_SET_DEV 0x2401 ++ ++ struct ip_config { ++ char name[MAX_IP_NAME]; ++ unsigned long paddr; ++ unsigned long router; ++ unsigned long net; ++ unsigned long up:1,destroy:1; ++ }; ++ #endif /* FIXME: */ ++ ++ /* Socket-level I/O control calls. */ ++ #define FIOSETOWN 0x8901 ++ #define SIOCSPGRP 0x8902 ++ #define FIOGETOWN 0x8903 ++ #define SIOCGPGRP 0x8904 ++ #define SIOCATMARK 0x8905 ++ ++ /* Socket configuration controls. */ ++ #define SIOCGIFNAME 0x8910 /* get iface name */ ++ #define SIOCSIFLINK 0x8911 /* set iface channel */ ++ #define SIOCGIFCONF 0x8912 /* get iface list */ ++ #define SIOCGIFFLAGS 0x8913 /* get flags */ ++ #define SIOCSIFFLAGS 0x8914 /* set flags */ ++ #define SIOCGIFADDR 0x8915 /* get PA address */ ++ #define SIOCSIFADDR 0x8916 /* set PA address */ ++ #define SIOCGIFDSTADDR 0x8917 /* get remote PA address */ ++ #define SIOCSIFDSTADDR 0x8918 /* set remote PA address */ ++ #define SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */ ++ #define SIOCSIFBRDADDR 0x891a /* set broadcast PA address */ ++ #define SIOCGIFNETMASK 0x891b /* get network PA mask */ ++ #define SIOCSIFNETMASK 0x891c /* set network PA mask */ ++ #define SIOCGIFMETRIC 0x891d /* get metric */ ++ #define SIOCSIFMETRIC 0x891e /* set metric */ ++ #define SIOCGIFMEM 0x891f /* get memory address (BSD) */ ++ #define SIOCSIFMEM 0x8920 /* set memory address (BSD) */ ++ #define SIOCGIFMTU 0x8921 /* get MTU size */ ++ #define SIOCSIFMTU 0x8922 /* set MTU size */ ++ ++ /* Routing table calls. */ ++ #define SIOCADDRT 0x8940 /* add routing table entry */ ++ #define SIOCDELRT 0x8941 /* delete routing table entry */ ++ ++ /* ARP cache control calls. */ ++ #define SIOCDARP 0x8950 /* delete ARP table entry */ ++ #define SIOCGARP 0x8951 /* get ARP table entry */ ++ #define SIOCSARP 0x8952 /* set ARP table entry */ ++ ++ #endif /* _LINUX_SOCKIOS_H */ +diff -c --recursive --new-file std/include/linux/tcp.h linux/include/linux/tcp.h +*** std/include/linux/tcp.h +--- linux/include/linux/tcp.h Sat Apr 24 19:39:36 1993 +*************** +*** 0 **** +--- 1,61 ---- ++ /* ++ * 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 TCP protocol. ++ * ++ * Version: @(#)tcp.h 1.0.1 03/21/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_TCP_H ++ #define _LINUX_TCP_H ++ ++ ++ #define HEADER_SIZE 64 /* maximum header size */ ++ ++ ++ struct tcp_header { ++ unsigned short source; ++ unsigned short dest; ++ unsigned long seq; ++ unsigned long ack_seq; ++ unsigned short res1:4, ++ doff:4, ++ fin:1, ++ syn:1, ++ rst:1, ++ psh:1, ++ ack:1, ++ urg:1, ++ res2:2; ++ unsigned short window; ++ unsigned short check; ++ unsigned short urg_ptr; ++ }; ++ ++ ++ enum { ++ TCP_ESTABLISHED = 1, ++ TCP_SYN_SENT, ++ TCP_SYN_RECV, ++ #if 0 ++ TCP_CLOSING, /* not a valid state, just a seperator so we can use ++ < tcp_closing or > tcp_closing for checks. */ ++ #endif ++ TCP_FIN_WAIT1, ++ TCP_FIN_WAIT2, ++ TCP_TIME_WAIT, ++ TCP_CLOSE, ++ TCP_CLOSE_WAIT, ++ TCP_LAST_ACK, ++ TCP_LISTEN ++ }; ++ ++ #endif /* _LINUX_TCP_H */ +diff -c --recursive --new-file std/include/linux/tty.h linux/include/linux/tty.h +*** std/include/linux/tty.h Thu Apr 22 20:32:21 1993 +--- linux/include/linux/tty.h Sat Apr 24 19:48:45 1993 +*************** +*** 340,345 **** +--- 340,349 ---- + extern void wait_until_sent(struct tty_struct * tty); + extern void copy_to_cooked(struct tty_struct * tty); + extern int tty_register_ldisc(int disc, struct tty_ldisc *new); ++ extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp, ++ int buflen); ++ extern int tty_write_data(struct tty_struct *tty, char *bufp, int buflen, ++ void (*callback)(void * data), void * callarg); + + extern int tty_ioctl(struct inode *, struct file *, unsigned int, unsigned long); + extern int is_orphaned_pgrp(int pgrp); +diff -c --recursive --new-file std/include/linux/udp.h linux/include/linux/udp.h +*** std/include/linux/udp.h +--- linux/include/linux/udp.h Sat Apr 24 19:39:36 1993 +*************** +*** 0 **** +--- 1,29 ---- ++ /* ++ * 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 UDP protocol. ++ * ++ * Version: @(#)udp.h 1.0.1 03/21/93 ++ * ++ * Author: Fred N. van Kempen, ++ * ++ * 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_UDP_H ++ #define _LINUX_UDP_H ++ ++ ++ struct udp_header { ++ unsigned short source; ++ unsigned short dest; ++ unsigned short len; ++ unsigned short check; ++ }; ++ ++ ++ #endif /* _LINUX_UDP_H */ +diff -c --recursive --new-file std/kernel/blk_drv/ramdisk.c linux/kernel/blk_drv/ramdisk.c +*** std/kernel/blk_drv/ramdisk.c Wed Feb 17 19:25:55 1993 +--- linux/kernel/blk_drv/ramdisk.c Sat Apr 24 19:39:36 1993 +*************** +*** 2,7 **** +--- 2,10 ---- + * linux/kernel/blk_drv/ramdisk.c + * + * Written by Theodore Ts'o, 12/2/91 ++ * ++ * Modifications by Fred N. van Kempen to allow for bootable root ++ * disks (which are used in LINUX/Pro). Also some cleanups. 03/03/93 + */ + + +*************** +*** 14,22 **** + #include + #include + +! #define MAJOR_NR 1 + #include "blk.h" + + char *rd_start; + int rd_length = 0; + +--- 17,30 ---- + #include + #include + +! #define MAJOR_RAMDISK 1 /* should be in */ +! #define MAJOR_FLOPPY 2 /* should be in */ +! #define MINOR_RAMDISK 1 +! +! #define MAJOR_NR MAJOR_RAMDISK /* weird hack- FvK */ + #include "blk.h" + ++ + char *rd_start; + int rd_length = 0; + +*************** +*** 29,35 **** + INIT_REQUEST; + addr = rd_start + (CURRENT->sector << 9); + len = CURRENT->nr_sectors << 9; +! if ((MINOR(CURRENT->dev) != 1) || (addr+len > rd_start+rd_length)) { + end_request(0); + goto repeat; + } +--- 37,44 ---- + INIT_REQUEST; + addr = rd_start + (CURRENT->sector << 9); + len = CURRENT->nr_sectors << 9; +! if ((MINOR(CURRENT->dev) != MINOR_RAMDISK) || +! (addr+len > rd_start+rd_length)) { + end_request(0); + goto repeat; + } +*************** +*** 42,48 **** + addr, + len); + } else +! panic("unknown ramdisk-command"); + end_request(1); + goto repeat; + } +--- 51,57 ---- + addr, + len); + } else +! panic("RAMDISK: unknown RAM disk command !\n"); + end_request(1); + goto repeat; + } +*************** +*** 67,77 **** + int i; + char *cp; + +! if (register_blkdev(MAJOR_NR,"rd",&rd_fops)) { +! printk("Unable to get major %d for ramdisk\n",MAJOR_NR); + return 0; + } +! blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + rd_start = (char *) mem_start; + rd_length = length; + cp = rd_start; +--- 76,86 ---- + int i; + char *cp; + +! if (register_blkdev(MAJOR_RAMDISK,"rd",&rd_fops)) { +! printk("RAMDISK: Unable to get major %d.\n", MAJOR_RAMDISK); + return 0; + } +! blk_dev[MAJOR_RAMDISK].request_fn = DEVICE_REQUEST; + rd_start = (char *) mem_start; + rd_length = length; + cp = rd_start; +*************** +*** 81,142 **** + } + + /* +! * If the root device is the ram disk, try to load it. + * In order to do this, the root device is originally set to the +! * floppy, and we later change it to be ram disk. + */ + void rd_load(void) + { + struct buffer_head *bh; + struct minix_super_block s; +! int block = 512; /* Start at block 512 */ + int i = 1; + int nblocks; +! char *cp; /* Move pointer */ +! +! if (!rd_length) +! return; +! printk("Ram disk: %d bytes, starting at 0x%x\n", rd_length, +! (int) rd_start); +! if (MAJOR(ROOT_DEV) != 2) +! return; +! bh = breada(ROOT_DEV,block+1,block,block+2,-1); +! if (!bh) { +! printk("Disk error while looking for ramdisk!\n"); +! return; +! } +! *((struct minix_super_block *) &s) = *((struct minix_super_block *) bh->b_data); +! brelse(bh); +! if (s.s_magic != MINIX_SUPER_MAGIC) +! /* No ram disk image present, assume normal floppy boot */ +! return; +! nblocks = s.s_nzones << s.s_log_zone_size; +! if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) { +! printk("Ram disk image too big! (%d blocks, %d avail)\n", +! nblocks, rd_length >> BLOCK_SIZE_BITS); +! return; +! } +! printk("Loading %d bytes into ram disk\n", +! nblocks << BLOCK_SIZE_BITS); +! cp = rd_start; +! while (nblocks) { +! if (nblocks > 2) +! bh = breada(ROOT_DEV, block, block+1, block+2, -1); +! else +! bh = bread(ROOT_DEV, block, BLOCK_SIZE); + if (!bh) { +! printk("I/O error on block %d, aborting load\n", +! block); + return; + } +! (void) memcpy(cp, bh->b_data, BLOCK_SIZE); + brelse(bh); +! if (!(nblocks-- & 15)) +! printk("."); +! cp += BLOCK_SIZE; +! block++; +! i++; + } +- printk("\ndone\n"); +- ROOT_DEV=0x0101; + } +--- 90,172 ---- + } + + /* +! * If the root device is the RAM disk, try to load it. + * In order to do this, the root device is originally set to the +! * floppy, and we later change it to be RAM disk. + */ + void rd_load(void) + { + struct buffer_head *bh; + struct minix_super_block s; +! int block, try; + int i = 1; + int nblocks; +! char *cp; +! +! /* If no RAM disk specified, give up early. */ +! if (!rd_length) return; +! printk("RAMDISK: %d bytes, starting at 0x%x\n", +! rd_length, (int) rd_start); +! +! /* If we are doing a diskette boot, we might have to pre-load it. */ +! if (MAJOR(ROOT_DEV) != MAJOR_FLOPPY) return; +! +! /* +! * Check for a super block on the diskette. +! * The old-style boot/root diskettes had their RAM image +! * starting at block 512 of the boot diskette. LINUX/Pro +! * uses the enire diskette as a file system, so in that +! * case, we have to look at block 0. Be intelligent about +! * this, and check both... - FvK +! */ +! for (try = 0; try < 1000; try += 512) { +! block = try; +! bh = breada(ROOT_DEV,block+1,block,block+2,-1); + if (!bh) { +! printk("RAMDISK: I/O error while looking for super block!\n"); + return; + } +! +! /* This is silly- why do we require it to be a MINIX FS? */ +! *((struct minix_super_block *) &s) = +! *((struct minix_super_block *) bh->b_data); + brelse(bh); +! nblocks = s.s_nzones << s.s_log_zone_size; +! if (s.s_magic != MINIX_SUPER_MAGIC) { +! printk("RAMDISK: trying old-style RAM image.\n"); +! continue; +! } +! +! if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) { +! printk("RAMDISK: image too big! (%d/%d blocks)\n", +! nblocks, rd_length >> BLOCK_SIZE_BITS); +! return; +! } +! printk("RAMDISK: Loading %d blocks into RAM disk", nblocks); +! +! /* We found an image file system. Load it into core! */ +! cp = rd_start; +! while (nblocks) { +! if (nblocks > 2) +! bh = breada(ROOT_DEV, block, block+1, block+2, -1); +! else +! bh = bread(ROOT_DEV, block, BLOCK_SIZE); +! if (!bh) { +! printk("RAMDISK: I/O error on block %d, aborting!\n", +! block); +! return; +! } +! (void) memcpy(cp, bh->b_data, BLOCK_SIZE); +! brelse(bh); +! if (!(nblocks-- & 15)) printk("."); +! cp += BLOCK_SIZE; +! block++; +! i++; +! } +! printk("\ndone\n"); +! +! /* We loaded the file system image. Prepare for mounting it. */ +! ROOT_DEV = ((MAJOR_RAMDISK << 8) | MINOR_RAMDISK); +! return; + } + } +diff -c --recursive --new-file std/kernel/chr_drv/tty_io.c linux/kernel/chr_drv/tty_io.c +*** std/kernel/chr_drv/tty_io.c Thu Apr 22 20:21:02 1993 +--- linux/kernel/chr_drv/tty_io.c Sat Apr 24 19:39:36 1993 +*************** +*** 1391,1396 **** +--- 1391,1397 ---- + while (count && VLEFT > 0) { + tty->write_q.buf[head++] = *p++; + head &= TTY_BUF_SIZE-1; ++ count--; + } + tty->write_q.head = head; + if (count) { +*************** +*** 1400,1405 **** +--- 1401,1407 ---- + tty->write_data_arg = callarg; + } + __asm__ __volatile__("pushl %0 ; popfl"::"r" (flags)); ++ tty->write(tty); + return count; + } + +diff -c --recursive --new-file std/net/tcp/arp.h linux/net/tcp/arp.h +*** std/net/tcp/arp.h Mon Jan 25 19:26:55 1993 +--- linux/net/tcp/arp.h Sat Apr 24 20:26:41 1993 +*************** +*** 52,57 **** +--- 52,60 ---- + #ifndef _TCP_ARP_H + #define _TCP_ARP_H + ++ #include ++ ++ + struct arp + { + unsigned short hrd; diff --git a/net/net-2/old/linus.tgz b/net/net-2/old/linus.tgz new file mode 100644 index 00000000..b5d5d6a0 Binary files /dev/null and b/net/net-2/old/linus.tgz differ diff --git a/net/net-2/old/net-005.tgz b/net/net-2/old/net-005.tgz new file mode 100644 index 00000000..9266b8de Binary files /dev/null and b/net/net-2/old/net-005.tgz differ diff --git a/net/net-2/old/net2-src.tgz b/net/net-2/old/net2-src.tgz new file mode 100644 index 00000000..153cd01f Binary files /dev/null and b/net/net-2/old/net2-src.tgz differ diff --git a/net/net-2/patches.alpha.z b/net/net-2/patches.alpha.z new file mode 100644 index 00000000..85bcd0b1 Binary files /dev/null and b/net/net-2/patches.alpha.z differ diff --git a/net/net-2/pop3d-1.00.4.tar.gz b/net/net-2/pop3d-1.00.4.tar.gz new file mode 100644 index 00000000..1d87bb79 Binary files /dev/null and b/net/net-2/pop3d-1.00.4.tar.gz differ diff --git a/net/net/READ.ME b/net/net/READ.ME new file mode 100644 index 00000000..5d9f7b43 --- /dev/null +++ b/net/net/READ.ME @@ -0,0 +1,358 @@ +KA9Q TCP is an implementation of TCP/IP for the PC. This is a Unix +port based on a version from mid-1989. Unfortunately the more recent +versions of KA9Q are harder to port to Linux. + +I don't have a manual for this exact version. There's builtin help. +The commands primarily set parameters (the ip and tcp commands), or +start services. In general the same command is used to set and +examine parameters. When you type the command with no value, it shows +the current value. + +To use KA9Q, put startup.net and possibly domain.txt in your home +directory, and run "net". You will probably need to tailor +startup.net for your configuration. See the section at the end of +this document on configuration. Note that you can give an argument to +the "net" command. It will be used as the startup file in place of +startup.net. By default, startup.net and other files are in your home +directory (the value of the environment variable HOME). You can put +them somewhere else by using the environment variable NETHOME. + +If you are using SLIP, note that you must first dial the modem and +establish a SLIP connection. The exact details on doing this are +different at each site. Unfortunately you're probably going to need +help from system or network support staff in order to use SLIP. +Because SLIP effectively connects you to someone's local network, +using it normally requires logging in with a password. I recommend +using kermit's script facility to dial and set up SLIP. It did not +seem work adding a similar facility to KA9Q. + +If your site does not current support SLIP, they will probably have to +do a bit of systems work. For Unix systems, typically this will +involve adding a SLIP device driver, and then enabling routing. (An +appropriate driver is available for the Sun, although I don't know +where. I believe it can be installed without Sun source.) Many +terminal servers will support SLIP directly, so enabling it will +merely involve changing a configuration file. + +Aside from configuration commands (which typically go into +startup.net), the most common commands are probably telnet and ftp. +Both take a host name. Once you are connected, the "escape character" +(initially ^]) lets you do some special things. You type it followed +by another character. Except for the escape character, the characters +are folded, so that c, C, and ^C are equivalent. Here's a list of the +special characters: + + escape character (i.e. two in a row) - send a real escape character + x or ^x - return to command mode + b or ^b - send break + c or ^c - send interrupt process + o or ^c - abort output + t or ^t - are you there? + h or ^h - send telnet erase character + u or ^u - send telnet erase line + ? - print this help message + +Once you return to command mode, the "session" command can be used to +switch between connections. With no arguments, it shows the current +sessions. With a number, it will reconnect you to that session. +There's a disconnect command to kill a session (also some stronger +ways of doing it). + +Telnet normally operates in full duplex, with the other system +echoing. However if that system refuses echoing, or if you use the +command "echo refuse", KA9Q will echo locally. In this case you have +the normal line editing functions. Several control characters have +special functions. Note that in local echo mode, you do not need to +hit the escape character first. + + escape character - return to command mode + ^v - quote the next character + ^b - send break + ^c - send interrupt process + ^o - abort output + ^t - are you there? + +Telnet will pass your TERM environment variable as the terminal type +if the other end asks for it. It will implement flow control locally +if the other end understand the remote flow control option. If the +other end does a "telnet sync" correctly, it will suppress output when +appropriate. E.g. when talking to a Unix system, if you type ^C or ^O +in the middle of a large output, output should stop immediately. +However there may be a pause before getting the next prompt, as some +previously buffered data is probably still going to be transmitted. + +The "ip stat" and "tcp stat" commands are useful to get statistics. +"Ip stat" shows both the IP and SLIP level. If header compression is +being used, it will show how many packets were compressed and how many +were oot. + +FTP is sort of odd. It looks like you are in an interactive +conversation with the FTP server at the other end, with no local +command prompt. Most commands are passed directly to the remote +server, but in fact there is a local command parser, which will +intervene for a few commands: + + cd, dir, list, get, ls, mkdir, nlst, rmdir, put, type + +get and put should be used to transfer files. + +There's very minimal support for X11. If you are running under +X on your Linux system, you can use the command "start x". +This will cause KA9Q to front-end the Linux X11 software, so +that you can run X-based software on other hosts. As usual, +you set a DISPLAY environment variable of the form + + myhost:0.0 + +where myhost is the host name or IP address of your Linux system (i.e. +the address that KA9Q is using). This function is currently very +primitive. There is no access control -- once you've started X, +anyone can connect to your display from anywhere on the network. KA9Q +will put out a message whenever someone connects, so at least you'll +know. If people find this feature useful, I'll put in access control. +With the current implementation, there are still two things you could +do: (1) use xauth, (2) turn on the X server only when you actually +want to start up X software. You can do "stop x". This will not +close down existing X connections. It will just prevent new ones, +until the next "start x". Unfortunately, X involves a lot of network +traffic. Over a 9600 bps line -- which is the primary audience for +this implementation -- it's probably too slow to be useful. + +It's possible to run a server which others can connect to, though I +haven't tried it except for ftp. The command is "start ftp", etc. +For ftp, a login is required. The file ftpusers, in your home +directory, contains a list of users and passwords. + +Here's a list of commands: + + ! - call a recursive shell + arp - set arp parameters + ax25 - configure ham interface + attach - define an interface - must be used for each interface + bootp - request our IP address from a server + connect - for AX25, define call sign for interface + cd + close + disconnect + dir - do a directory on the local system + domain - configure domain name system + eaglestat + echo - refuse or accept - request to disable telnet remote echo + eol - Unix or standard end of line options [standard is recommended, + even for use on Unix systems] + escape - change escape character + etherstat + exit + finger + forward - divert packets from one interface to another + ftp - open an ftp connection + hapnstat + help - print command list + hostname - set/examine host name + kick + log + ip - set/examine IP level parameters + memstat + mbox, mode - AX25 commands + mulport + netrom + nrstat + param - set/examine interafce parameters + ping - send ping to a host + pwd + rdate [offset] [host] - set date/time from UDP time daemon. see below + record + remote + reset - kill connection + route - set up routes + session - see above: move to a different session + shell - call a subshell + smtp - mail handling + start - start server + stop - stop server + tcp - set/examine tcp parameters + telnet - open telnet connection + trace - enable low-level debugging (no arguments - show current status) + trace to - put trace output on file (use "con" for console) + trace [] - trace packets on device + device is typically "sl0" or "loopback" + bits are in hex: + 1 - output, 10 - input (else no tracing) + 100 - dump data in ascii, 200 - hex (else headers only) + trace cmdmode|allmode - show trace just when at command level? + trace telnet [on | off] - show telnet options and urgent data + udp - set/examine udp parameters + upload + wait - control mail select + +The rdate command uses the old-style time protocol (often known as +"rdate"), on UDP port 37, to get the date and time, and then sets the +system clock. Note that the protocol always gives time in GMT. If +your system clock is running on GMT (which is the normal way Unix +should run), this is fine. Otherwise, you'll need to specify the +offset in minutes. For time zones west of GMT, this should be a +negative number. For the Eastern U.S., when not in daylight time, the +offset is -300, because EST is 5 hours (300 minutes) west of GMT. +If no host is specified, a UDP broadcast is used. + +This configuration of KA9Q has been tested only with SLIP. Code is +also included for the KISS device (for ham radio) and Linux generic +Ethernet support using /dev/eth. /dev/eth should either work or come +close to working: it's based on diffs made from a recent version of +KA9Q. I don't know of anyone who has tested KISS. Past experience +suggests that users will prefer Kermit to SLIP unless you use SLIP +with header compression. + +Note that this program depends up non-blocking I/O and the select +system call. In Linux 0.12, these did not work. There are patches, +nonblock.tar.Z and select.patch, on the major distribution machines. +Don't forget: after patching a kernel source file, you must do a make +in each directory where you changed a file. The main make file +doesn't rebuild things all the time when it should. Linux 0.95 +and later has all the necessary patches. + + +CONFIGURATION: + +Here's some advice on preparing a configuration file. I assume you're +planning to use SLIP (dialup IP) or Ethernet. I'm going to explain my +configuration file line by line, as it's likely to be close to what +you need: + + attach asy 0 /dev/tty64 cslip sl0 2048 1500 9600 + +You must include an attach command in every configuration file. It +defines the device. For SLIP, the line above should be about right. +Some variationos: + - /dev/tty64 is the serial line. Obviously you can adjust this + to use a different line. + - cslip specifies SLIP with Van Jacobsen header compression. + If you're using normal slip, use "slip" instead of "cslip". + In my opinion, response on normal SLIP is too slow for it + to be very useful. + - 9600 is the line speed. Use whatever speed you are set for. + If you have a "smart" modem, we recommend turning off + any error correction or compression. These features + introduce enough delay to be objectionable. + +The following attach command could be used for Linux generic +Ethernet (/dev/eth) + attach linux arpa eth0 1500 1.2.3.fa.fb.fc +The last item is your Ethernet hardware address, in hex. It should +be printed when your system boots. E.g. if it prints 01 02 03 04 05 06 +then you put in 1.2.3.4.5.6. Each of the six numbers is in hex, and +may be one or two digits. + + wait 0 + +This should only be needed with older version of the kernel. It +disables the select system call. Instead, runs in a tight loop +continuously testing for input. Unfortunately select has a history of +problems under Linux. It appears to be fine in version 0.96. However +in earlier version, select did not work properly when there was +another program running. (In some cases it works OK unless the other +program uses select. E.g. if you enter emacs in another window, your +FTP comes to a halt.) If you are trying to use KA9Q while another +program is running, and you find that the connection hangs, you might +try "wait 0". Otherwise, you should leave the default setting, which +is "wait 100". The argument to wait is in milliseconds. It's the +amount of time to wait in the main loop. The select will trigger if +input arrives on the serial line, or you hit a key. Otherwise it +waits this amount of time. I don't recommend values larger than 100. +Smaller values might possibly be useful in some siuations. + + route add default sl0 + +This says that all packets should be sent out the SLIP line. Presumably +this is what you want. If you are using Ethernet, of course you'd +use the name of your Ethernet device instead of sl0, e.g. + route add default eth0 + + bootp + +This says that the system will find out its IP address by sending a +BOOTP request out the serial line. Since dialups are normally +in "hunt groups", you will probably get a different line each time +you dial up. Thus your IP address will probably not be the same. +BOOTP is a way of asking the terminal server (or whatever else +you're connected to) to tell you your IP address. If your terminal +server does not support BOOTP, you explicitly set your IP address +using a command of the form + ip address [1.2.3.4] +where 1.2.3.4 is your IP address. You would use this command +instead of the BOOTP command. + + tcp mss 64 + tcp window 256 + +These commands set TCP performance parameters. These control a +tradeoff between overall throughput, jerkiness of output, etc. These +parameters seem to give good performance for interactive connectionos. +For FTP you might want larger values, particularly if you are going +over a long-haul network like the Internet. For FTP the best value +for mss is at least 512, and probably more like 1024, with window +between 2 and 4 times mss. However Linux has fairly small buffers for +the serial line, so you may not be able to get away with parameters +much larger than the ones shown here. If you are using Ethernet, +of course you'll want larger values. I suggest starting with + tcp mss 1460 + tcp window 5840 +This should work for traffic on the local Ethernet. If your +traffic tends to go through routers, a safer set of values is + tcp mss 512 + tcp window 2048 + + domain suffix rutgers.edu + domain add [128.6.4.4] + +These parameters control the domain system. That's the set of servers +you use to look up host names. You'll need to adjust these for your +campus. The suffix is tacked onto all host names you type, unless +they already have a dot in them. This lets you type "athos" instead +of "athos.rutgers.edu". Set it for the domain you most commonly use. +The address 128.6.4.4 should be the address of a domain server on your +campus. All name lookups will be directed to that server. You can +define more than one, by using several "domain add" lines. + +If your campus does not support the domain system, you can use a host +table instead. In that case you would omit the "domain" commands. +The host table is called "domain.txt", in your home directory. It's +in the format of a domain master file. The most important entries +look like + athos.rutgers.edu. IN A 128.6.4.4 +Note that IN and A must be in upper case, and the name must include +the whole suffix, and end in a dot. + +Note that this is a very old domain implementation, and is not up to +the level of the current MS/DOS version. It does not use TTL's. +Every time you type a name, it first looks in domain.txt. If there's +an entry there, it will be used. Otherwise, it will query the domain +server you specified. If it gets an answer, that information will be +added to domain.txt. If a host changes its address, you'll be in +trouble, because you'll continue getting the old information from +domain.txt. Thus it's probably a good idea to remove domain.txt now +and then. + + start finger + start telnet + +These start daemons to respond to incoming finger and telnet +connections. This is optional, but most people will probably find +them useful to help people find you. The finger server uses files +stored in a subdirectory "finger" of your home directory. Files +should have names of the form xxx.txt, where xxx is a user name. +Finger with no arguments will list all users on the system (i.e. it +will look for all files ~/finger/*.txt, and list the names). Finger +with a specific user name will display the text of that file, i.e. +~/finger/xxx.txt. + +The telnet server is really more like a talk link. When someone +telnets to your machine, you'll get a message saying that there is an +incoming telnet connection. At that point you should escape to the +coommand level (using ^] or whatever your escape character is), do +"session" to see the session number of the incoming connection and do +"session NN" to connect to it. At that point you'll be in an +interactive link with the person. There is also a server designed to +allow "real" telnet connections, i.e. connections that create a real +login session. It is activated with the command "start telunix". +However that code is incomplete, and currently does nothing useful. diff --git a/net/net/net-0.3.tar.z b/net/net/net-0.3.tar.z new file mode 100644 index 00000000..2e7e1005 Binary files /dev/null and b/net/net/net-0.3.tar.z differ diff --git a/net/net/nfsd-domain-bug.patch b/net/net/nfsd-domain-bug.patch new file mode 100644 index 00000000..7139e93d --- /dev/null +++ b/net/net/nfsd-domain-bug.patch @@ -0,0 +1,54 @@ +From Thomas.Koenig@ciw.uni-karlsruhe.de Sat Aug 20 11:34:02 EDT 1994 +Article: 2607 of comp.os.linux.announce +Newsgroups: comp.os.linux.announce +Path: bigblue.oit.unc.edu!concert!news-feed-1.peachnet.edu!news.duke.edu!zombie.ncsc.mil!MathWorks.Com!news.kei.com!travelers.mail.cornell.edu!cornell!bounce-bounce +From: ig25@fg70.rz.uni-karlsruhe.de (Thomas Koenig) +Subject: nfsd bug and fix +Message-ID: +Followup-To: comp.os.linux.misc +Keywords: nfs, bug report, patch +Sender: mdw@cs.cornell.edu (Matt Welsh) +Reply-To: Thomas.Koenig@ciw.uni-karlsruhe.de +Organization: University of Karlsruhe, Germany +Date: Sat, 20 Aug 1994 15:50:13 GMT +Approved: linux-announce@tc.cornell.edu (Matt Welsh) +Lines: 36 + +Hi; + +there's a bug in the nfs suite 1.5.10 (for example on + +/sunsite.unc.edu:pub/Linux/system/Network/aris/sources/nfsd/nfsd-1.5.10.tar.gz + +which prevents a directory from being exported to different domains. + +Consider a line in /etc/export: + +/export *.foo.do.main(ro) *.bar.another.domain(ro) + +This would only allow importing the file system /export from +machines from *.bar.another.domain. + +The patch to fix this, one forgotten continue, follows: + +--- nfsd-1.5.10-old/auth_clnt.c Fri Nov 5 04:18:43 1993 ++++ nfsd-1.5.10/auth_clnt.c Wed Aug 17 22:53:12 1994 +@@ -153,6 +153,7 @@ + goto found_it; + } + cpp = &(cp->next); /* the normal iteration */ ++ continue; + } + else if ((hent = gethostbyname(cp->clnt_name)) != NULL) { + cp->clnt_addr = *((struct in_addr *) hent->h_addr); +-- +Thomas Koenig, Thomas.Koenig@ciw.uni-karlsruhe.de, ig25@dkauni2.bitnet. +The joy of engineering is to find a straight line on a double +logarithmic diagram. + + +-- +Send submissions for comp.os.linux.announce to: linux-announce@tc.cornell.edu +Be sure to include Keywords: and a short description of your software. + + diff --git a/net/net/tkppp-1.0.lsm b/net/net/tkppp-1.0.lsm new file mode 100644 index 00000000..fd2c99f8 --- /dev/null +++ b/net/net/tkppp-1.0.lsm @@ -0,0 +1,15 @@ +Begin3 +Title: tkppp +Version: 1.0 +Entered-date: Tue Aug 30 22:06:51 EDT 1994 +Description: A tcl/tk tool for controlling a PPP connection. +Keywords: PPP, tcl, tk +Author: jeschke@cs.indiana.edu (Eric Jeschke) +Maintained-by: jeschke@cs.indiana.edu (Eric Jeschke) +Primary-site: sunsite.unc.edu /pub/Linux/X11/xapps/comm + 3042 tkppp-1.0.tar.gz +Alternate-site: +Original-site: +Platform: tcl/tk +Copying-policy: Public Domain +End diff --git a/net/net/tkppp-1.0.tar.gz b/net/net/tkppp-1.0.tar.gz new file mode 100644 index 00000000..f90f7cf3 Binary files /dev/null and b/net/net/tkppp-1.0.tar.gz differ diff --git a/net/net/wd8003.tar b/net/net/wd8003.tar new file mode 100644 index 00000000..e8f6b5f1 Binary files /dev/null and b/net/net/wd8003.tar differ diff --git a/net/net/xftp-2.2.athena+term.tgz b/net/net/xftp-2.2.athena+term.tgz new file mode 100644 index 00000000..b21e8b57 Binary files /dev/null and b/net/net/xftp-2.2.athena+term.tgz differ diff --git a/net/tcpip/README.hostcvt b/net/tcpip/README.hostcvt new file mode 100644 index 00000000..2134d008 --- /dev/null +++ b/net/tcpip/README.hostcvt @@ -0,0 +1,5 @@ +This is a copy of hostcvt compiled for linux. It helps to convert +from /etc/hosts to named configuration files. + +It may not be used to make money, so I don't think you can charge to +redistribute this. diff --git a/net/tcpip/README.inetd b/net/tcpip/README.inetd new file mode 100644 index 00000000..e4c2775e --- /dev/null +++ b/net/tcpip/README.inetd @@ -0,0 +1,7 @@ +inetd.tar.Z has the following files in it + inetd (put in /usr/etc/inet) + inetd.8 (put in /usr/man/man8) + inetd-diffs + +The diffs only include changes to the *.[ch] files. You will need to +edit the makefile to recompile inetd. diff --git a/net/tcpip/README.named b/net/tcpip/README.named new file mode 100644 index 00000000..55947b64 --- /dev/null +++ b/net/tcpip/README.named @@ -0,0 +1,13 @@ +named-bin.tar.Z consists of the following files: + named (put in /usr/etc/inet) + named-xfer (put in /usr/etc/int) + nsquery (put in /usr/bin or /usr/etc/inet) + nslookup (put in /usr/bin or /usr/etc/inet) + named.8 (put in /usr/man/man8) + nslookup.1 (put in /usr/man/man1) + named-diffs + nslkp.diffs + + The diff files only include changes to the *.[ch] files. You +will need to edit the makefiles yourself and you may need to include +the file res/res_debug.c. diff --git a/net/tcpip/README.tcp98pl5-3 b/net/tcpip/README.tcp98pl5-3 new file mode 100644 index 00000000..b24c950f --- /dev/null +++ b/net/tcpip/README.tcp98pl5-3 @@ -0,0 +1,3 @@ +This is the third tcp patch to 0.98pl5. All three go in without any problem. +This one fixes raw sockets and a few other minor problems. + diff --git a/net/tcpip/README.tcp98pl5-p1 b/net/tcpip/README.tcp98pl5-p1 new file mode 100644 index 00000000..a0148ca1 --- /dev/null +++ b/net/tcpip/README.tcp98pl5-p1 @@ -0,0 +1,6 @@ +This patch was made against pl4 + tcp diffs I sent to Linus. You may need +to apply some of them by hand. + +Ross Biro bir7@leland.stanford.edu +Member League for Programming Freedom (LPF) +mail lpf@uunet.uu.net for information diff --git a/net/tcpip/README.tcp98pl5-p2 b/net/tcpip/README.tcp98pl5-p2 new file mode 100644 index 00000000..ca637109 --- /dev/null +++ b/net/tcpip/README.tcp98pl5-p2 @@ -0,0 +1,7 @@ + +This diff fixes some problems with the first diff, and corrects a few +error returns. Hopefully some of the problems with accept, connect, +and shutdown should have vanished. Again these are not really against +pl5 but against pl4 + some of the pl5 diffs + patch1. You may need to +do these by hand also. + diff --git a/net/tcpip/README.telnetd-buggy b/net/tcpip/README.telnetd-buggy new file mode 100644 index 00000000..da332753 --- /dev/null +++ b/net/tcpip/README.telnetd-buggy @@ -0,0 +1,3 @@ +This is the same BUGGY version of telnetd that was in earlier +releases. It has been recompiled to use a newer library and to +work with .98pl5. We still need a new version. diff --git a/net/tcpip/depca-0.7.README b/net/tcpip/depca-0.7.README new file mode 100644 index 00000000..aedbc3f7 --- /dev/null +++ b/net/tcpip/depca-0.7.README @@ -0,0 +1,11 @@ +From: "pb@cs" <100136.3530@compuserve.com> +To: +Subject: new depca-0.7 for pl13 +Date: 26 Sep 93 18:31:24 EDT + +Find enclosed depca-0.7. This version patches against the limux99pl13 +kernel sources and shoud go where the other depca-driver went (I think +somewhere in Linux/BETA/depca). From the older versions there only the +0.5 version is worth keeping, because it patches against pl10 and 11. + +Gruss PB diff --git a/net/tcpip/depca-0.7.tar.z b/net/tcpip/depca-0.7.tar.z new file mode 100644 index 00000000..f85e4b76 Binary files /dev/null and b/net/tcpip/depca-0.7.tar.z differ diff --git a/net/tcpip/ether-995/3c503.c b/net/tcpip/ether-995/3c503.c new file mode 100644 index 00000000..67ce0d70 --- /dev/null +++ b/net/tcpip/ether-995/3c503.c @@ -0,0 +1,347 @@ +/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with the 3c503 and 3c503/16. It must be used + in shared memory mode. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = "3c503.c:v0.30 1/30/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include + +#include "dev.h" + +#include "8390.h" +#include "3c503reg.h" + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int etherlink2 = 0; + +int el2autoprobe(int ioaddr, struct device *dev); +int el2probe(int ioaddr, struct device *dev); + +static void el2_reset_8390(struct device *dev); +static void el2_init_card(struct device *dev); +static void el2_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static int el2_block_input(struct device *dev, int count, char *buf, + int ring_offset); + + +int +el2autoprobe(int ioaddr, struct device *dev) +{ + int *addr, addrs[] = { 0xddfff, 0xd9fff, 0xcdfff, 0xc9fff, 0}; + int ports[] = {0, 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2a0, 0x2e0, 0}; + + /* Non-autoprobe case first: */ + if (ioaddr > 0) + return el2probe(ioaddr, dev); + + /* We check for a memory-mapped 3c503 board by looking at the + end of boot PROM space (works even if a PROM isn't there). */ + for (addr = addrs; *addr; addr++) { + unsigned int base_bits = *(unsigned char *)*addr, i; + /* Find first set bit. */ + for(i = 8; i; i--, base_bits >>= 1) + if (base_bits & 0x1) + break; + if (base_bits == 1 && el2probe(ports[i], dev)) + return dev->base_addr; + } +#ifdef notdef + /* If it's not memory mapped, we don't care to find it. I haven't + tested the non-memory-mapped code. */ + /* It's not memory mapped -- try all of the locations that aren't + obviously empty. */ + { int *port; + for (port = &ports[1]; *port; port++) + if (inb_p(*port) != 0xff && el2probe(*port, dev)) + return dev->base_addr = *port; + } +#endif + return 0; +} + +/* Probe for the Etherlink II card at I/O port base IOADDR, + returning non-zero on sucess. If found, set the station + address and memory parameters in DEVICE. */ +int +el2probe(int ioaddr, struct device *dev) +{ + int i, found, mem_jumpers; + unsigned char *station_addr = dev->dev_addr; + + /* We verify that it's a 3C503 board by checking the first three octets + of its ethernet address. */ + printk("3c503 probe at %#3x:", ioaddr); + outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */ + outb_p(ECNTRL_THIN, ioaddr + 0x406); + /* Map the station addr PROM into the lower I/O ports. */ + outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406); + for (i = 0; i < ETHER_ADDR_LEN; i++) { + printk(" %2.2X", (station_addr[i] = inb(ioaddr + i))); + } + /* Map the 8390 back into the window. */ + outb(ECNTRL_THIN, ioaddr + 0x406); + found =( station_addr[0] == 0x02 + && station_addr[1] == 0x60 + && station_addr[2] == 0x8c); + if (! found) { + printk(" 3C503 not found.\n"); + return 0; + } + dev->base_addr = ioaddr; + /* Probe for, turn on and clear the board's shared memory. */ + mem_jumpers = inb(ioaddr + 0x404); /* E33G_ROMBASE */ + if (ei_debug > 2) printk(" memory jumpers %2.2x ", mem_jumpers); + outb(EGACFR_IRQOFF, ioaddr + 0x405); /* Enable RAM */ + if ((mem_jumpers & 0xf0) == 0) { + dev->mem_start = 0; + if (ei_debug > 1) printk(" no shared memory "); + } else { + dev->mem_start = ((mem_jumpers & 0xc0) ? 0xD8000 : 0xC8000) + + ((mem_jumpers & 0xA0) ? 0x4000 : 0); + +#define EL2_MEMSIZE (EL2SM_STOP_PG - EL2SM_START_PG)*256 +#ifdef EL2MEMTEST + { /* Check the card's memory. */ + int *mem_base = (int *)dev->mem_start; + int memtest_value = 0xbbadf00d; + mem_base[0] = 0xba5eba5e; + for (i = 1; i < EL2_MEMSIZE/sizeof(mem_base[0]); i++) { + mem_base[i] = memtest_value; + if (mem_base[0] != 0xba5eba5e + || mem_base[i] != memtest_value) { + printk(" memory failure or memory address conflict.\n"); + dev->mem_start = 0; + break; + } + memtest_value += 0x55555555; + mem_base[i] = 0; + } + } +#endif /* EL2MEMTEST */ + /* Divide the on-board memory into a single maximum-sized transmit + (double-sized for ping-pong transmit) buffer at the base, and + use the rest as a receive ring. */ + dev->mem_end = dev->rmem_end = dev->mem_start + EL2_MEMSIZE; + dev->rmem_start = TX_PAGES*256 + dev->mem_start; + } + if (ei_debug > 2) + printk("\n3c503: memory params start=%#5x rstart=%#5x end=%#5x rend=%#5x.\n", + dev->mem_start, dev->rmem_start, dev->mem_end, dev->rmem_end); + + /* Finish setting the board's parameters. */ + etherlink2 = 1; + ei_status.tx_start_page = EL2SM_START_PG; + ei_status.rx_start_page = EL2SM_START_PG + TX_PAGES; + ei_status.stop_page = EL2SM_STOP_PG; + ei_status.reset_8390 = &el2_reset_8390; + ei_status.block_input = &el2_block_input; + ei_status.block_output = &el2_block_output; +/* This should be probed for (or set via an ioctl()) at run-time someday. */ +#if defined(EI8390_THICK) || defined(EL2_AUI) + ei_status.thin_bit = 0; +#else + ei_status.thin_bit = ECNTRL_THIN; +#endif + + if (dev->irq < 2) { + int irqlist[] = {5, 2, 3, 4, 0}; + int *irqp = irqlist; + do { + if (irqaction (dev->irq = *irqp, &ei_sigaction) == 0) { + break; + } + } while (*++irqp); + if (*irqp == 0) { + printk("\n3c503: Unable to find an free IRQ line.\n"); + return 0; + } + } else { + if (dev->irq == 2) + dev->irq = 9; + else if (dev->irq > 5 && dev->irq != 9) { + printk("\n3c503: configured interrupt number %d out of range.\n", + dev->irq); + return 0; + } + if (irqaction (dev->irq, &ei_sigaction)) { + printk ("\n3c503: Unable to get IRQ%d.\n", dev->irq); + return 0; + } + } + + el2_init_card(dev); + + if (dev->mem_start) + printk("3c503 found, memory at %#6x, IRQ %d\n", + dev->mem_start, dev->irq); + else + printk(" 3c503 found, no shared memory, IRQ %d\n", dev->irq); + if (ei_debug > 2) + printk(version); + + return ioaddr; +} + +/* This is called whenever we have a unrecoverable failure: + transmit timeout + Bad ring buffer packet header + */ +static void +el2_reset_8390(struct device *dev) +{ + if (ei_debug > 1) printk("3c503: Resetting the board..."); + outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL); + ei_status.txing = 0; + outb_p(ei_status.thin_bit, E33G_CNTRL); + el2_init_card(dev); + if (ei_debug > 1) printk("done\n"); +} + +/* Initialize the 3c503 GA registers after a reset. */ +static void +el2_init_card(struct device *dev) +{ + /* Unmap the station PROM and select the DIX or BNC connector. */ + outb_p(ei_status.thin_bit, E33G_CNTRL); + + /* Set ASIC copy of rx's first and last+1 buffer pages */ + /* These must be the same as in the 8390. */ + outb(ei_status.rx_start_page, E33G_STARTPG); + outb(ei_status.stop_page, E33G_STOPPG); + + /* Point the vector pointer registers somewhere ?harmless?. */ + outb(0xff, E33G_VP2); /* Point at the ROM restart location 0xffff0 */ + outb(0xff, E33G_VP1); + outb(0x00, E33G_VP0); + /* Turn off all interrupts until we're opened. */ + outb_p(0x00, dev->base_addr + EN0_IMR); + outb_p(EGACFR_IRQOFF, E33G_GACFR); + + /* Set the interrupt line. */ + outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR); + outb_p(8, E33G_DRQCNT); /* Set burst size to 8 */ + outb_p(0x20, E33G_DMAAH); /* Put a valid addr in the GA DMA */ + outb_p(0x00, E33G_DMAAL); + return; /* We always succeed */ +} + +/* Either use the shared memory (if enabled on the board) or put the packet + out through the ASIC FIFO. The latter is probably much slower. */ +static void +el2_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page) +{ + int i; /* Buffer index */ + int boguscount = 0; /* timeout counter */ + if (dev->mem_start) { /* Shared memory transfer */ + void *dest_addr = (void *)(dev->mem_start + + ((start_page - ei_status.tx_start_page) << 8)); + outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM */ + memcpy(dest_addr, buf, count); + if (ei_debug > 2 && memcmp(dest_addr, buf, count)) + printk("3c503: send_packet() bad memory copy @ %#5x.\n", + dest_addr); + else if (ei_debug > 4) + printk("3c503: send_packet() good memory copy @ %#5x.\n", + dest_addr); + return; + } + /* Set up then start the internal memory transfer to Tx Start Page */ + outb(0x00, E33G_DMAAL); + outb(start_page, E33G_DMAAH); + outb(ei_status.thin_bit | ECNTRL_OUTPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. I think it is possible + to output 8 bytes between each check of the status bit. */ + for(i = 0; i < count; i++) { + if (count % 8 == 7) + while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) + if (++boguscount > 32) { + printk(EI_NAME": fifo blocked in el2_block_output.\n"); + return; + } + outb(buf[i], E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + return; +} + +/* Returns the new ring pointer. */ +static int +el2_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int boguscount = 0; + int end_of_ring = dev->rmem_end; + ring_offset -= (EL2SM_START_PG<<8); + + /* Maybe enable shared memory just be to be safe... nahh.*/ + if (dev->mem_start) { /* Use the shared memory. */ + if (dev->mem_start + ring_offset + count > end_of_ring) { + /* We must wrap the input move. */ + int semi_count = end_of_ring - (dev->mem_start + ring_offset); + if (ei_debug > 4) + printk("3c503: block_input() @ %#5x+%x=%5x.\n", + dev->mem_start, ring_offset, + (char *)dev->mem_start + ring_offset); + memcpy(buf, (char *)dev->mem_start + ring_offset, semi_count); + count -= semi_count; + memcpy(buf + semi_count, (char *)dev->rmem_start, count); + return dev->rmem_start + count; + } + if (ei_debug > 4) + printk("3c503: block_input() @ %#5x+%x=%5x.\n", + dev->mem_start, ring_offset, + (char *)dev->mem_start + ring_offset); + memcpy(buf, (char *)dev->mem_start + ring_offset, count); + return ring_offset + count; + } else { /* No shared memory, use the fifo. */ + int i; + outb(ring_offset & 0xff, E33G_DMAAL); + outb((ring_offset >> 8) & 0xff, E33G_DMAAH); + outb(ei_status.thin_bit | ECNTRL_INPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. */ + for(i = 0; i < count; i++) { + if (count % 8 == 7) + while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) + if (++boguscount > 32) { + printk(EI_NAME": fifo blocked in el2_block_input().\n"); + return 0; + } + buf[i] = inb(E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + ring_offset += count; + if (ring_offset >= end_of_ring) + ring_offset = dev->rmem_start + ring_offset - end_of_ring; + return ring_offset; + } +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c 3c503.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/ether-995/3c503reg.h b/net/tcpip/ether-995/3c503reg.h new file mode 100644 index 00000000..da7961d4 --- /dev/null +++ b/net/tcpip/ether-995/3c503reg.h @@ -0,0 +1,59 @@ +/* Definitions for the 3Com 3c503 Etherlink 2. */ +/* This file is part of Donald Becker's 8390 drivers. + This file is distributed under the Linux GPL. + Some of these names and comments are from the Crynwr packet drivers. */ + +#define EL2H (dev->base_addr + 0x400) +#define EL2L (dev->base_addr) + +/* Shared memory management parameters */ + +#define EL2SM_START_PG (0x20) /* First page of TX buffer */ +#define EL2SM_STOP_PG (0x40) /* Last page +1 of RX ring */ + +/* 3Com 3c503 ASIC registers */ +#define E33G_STARTPG (EL2H+0) /* Start page, must match EN0_STARTPG */ +#define E33G_STOPPG (EL2H+1) /* Stop page, must match EN0_STOPPG */ +#define E33G_DRQCNT (EL2H+2) /* DMA burst count */ +#define E33G_IOBASE (EL2H+3) /* Read of I/O base jumpers. */ + /* (non-useful, but it also appears at the end of EPROM space) */ +#define E33G_ROMBASE (EL2H+4) /* Read of memory base jumpers. */ +#define E33G_GACFR (EL2H+5) /* Config/setup bits for the ASIC GA */ +#define E33G_CNTRL (EL2H+6) /* Board's main control register */ +#define E33G_STATUS (EL2H+7) /* Status on completions. */ +#define E33G_IDCFR (EL2H+8) /* Interrupt/DMA config register */ + /* (Which IRQ to assert, DMA chan to use) */ +#define E33G_DMAAH (EL2H+9) /* High byte of DMA address reg */ +#define E33G_DMAAL (EL2H+10) /* Low byte of DMA address reg */ +/* "Vector pointer" - if this address matches a read, the EPROM (rather than + shared RAM) is mapped into memory space. */ +#define E33G_VP2 (EL2H+11) +#define E33G_VP1 (EL2H+12) +#define E33G_VP0 (EL2H+13) +#define E33G_FIFOH (EL2H+14) /* FIFO for programmed I/O moves */ +#define E33G_FIFOL (EL2H+15) /* ... low byte of above. */ + +/* Bits in E33G_CNTRL register: */ + +#define ECNTRL_RESET (0x01) /* Software reset of the ASIC and 8390 */ +#define ECNTRL_THIN (0x02) /* Onboard thin-net xcvr enable */ +#define ECNTRL_SAPROM (0x04) /* Map the station address prom */ +#define ECNTRL_DBLBFR (0x20) /* FIFO configuration bit */ +#define ECNTRL_OUTPUT (0x40) /* PC-to-3C503 direction if 1 */ +#define ECNTRL_INPUT (0x00) /* 3C503-to-PC direction if 0 */ +#define ECNTRL_START (0x80) /* Start the DMA logic */ + +/* Bits in E33G_STATUS register: */ + +#define ESTAT_DPRDY (0x80) /* Data port (of FIFO) ready */ +#define ESTAT_UFLW (0x40) /* Tried to read FIFO when it was empty */ +#define ESTAT_OFLW (0x20) /* Tried to write FIFO when it was full */ +#define ESTAT_DTC (0x10) /* Terminal Count from PC bus DMA logic */ +#define ESTAT_DIP (0x08) /* DMA In Progress */ + +/* Bits in E33G_GACFR register: */ + +#define EGACFR_NORM (0x49) /* Enable 8K shared mem, no DMA TC int */ +#define EGACFR_IRQOFF (0xc9) /* Above, and disable 8390 IRQ line */ + +/* End of 3C503 parameter definitions */ diff --git a/net/tcpip/ether-995/8390.c b/net/tcpip/ether-995/8390.c new file mode 100644 index 00000000..bea13094 --- /dev/null +++ b/net/tcpip/ether-995/8390.c @@ -0,0 +1,731 @@ +/* 8390.c: A general NS8390 ethernet driver core for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with many 8390-based ethernet adaptors. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = + "8390.c:v0.43 2/12/93 for 0.99.5+ Donald Becker (becker@super.org)\n"; +#include +#if !defined(EL2) && !defined(NE2000) && !defined(WD80x3) && !defined(HPLAN) +/* They don't know what they want -- give it all to them! */ +#define EL2 +#define NE2000 +#define WD80x3 +#define HPLAN +#endif + +/* + Braindamage remaining: + + Ethernet devices should use a chr_drv device interface, with ioctl()s to + configure the card, bring the interface up or down, allow access to + statistics, and maybe read() and write() access to raw packets. + This won't be done until after Linux 1.00. + + This driver should support multiple, diverse boards simultaneousely. + This won't be done until after Linux 1.00. + +Sources: + The National Semiconductor LAN Databook, and 3Com databooks, both companies + provided information readily. The NE* info came from the Crynwr packet + driver, and figuring out that the those boards are similar to the NatSemi + evaluation board described in AN-729. Thanks NS, no thanks to Novell/Eagle. + Cabletron provided only info I had already gotten from other sources -- hiss. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "eth.h" +#include "timer.h" +#include "ip.h" +#include "tcp.h" +#include "sock.h" +#include "arp.h" + +#include "8390.h" + +#define ei_reset_8390 (ei_status.reset_8390) +#define ei_block_output (ei_status.block_output) +#define ei_block_input (ei_status.block_input) + +#define EN_CMD (e8390_base) +#define E8390_BASE (e8390_base) + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifdef EI_DEBUG +int ei_debug = EI_DEBUG; +#else +int ei_debug = 2; +#endif + +static int e8390_base; + +static struct device *eifdev; /* For single-board consistency checking. */ +extern int etherlink2; + +struct ei_device ei_status = { EI_NAME, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* The statistics, perhaps these should be in the above structure. */ +static int tx_packets = 0; +static int rx_packets = 0; +static int tx_errors = 0; +static int soft_rx_errors = 0; +static int soft_rx_err_bits = 0; +static int missed_packets = 0; +static int rx_overrun_packets = 0; +/* Max number of packets received at one Intr. */ +/*static int high_water_mark = 0;*/ + +/* Index to functions. */ +/* Put in the device structure. */ +static int ei_open(struct device *dev); +static void ei_send_packet(struct sk_buff *skb, struct device *dev); +/* Dispatch from interrupts. */ +static void ei_interrupt(int reg_ptr); +static void ei_tx_intr(struct device *dev); +static void ei_receive(struct device *dev); +static void ei_rx_overrun(struct device *dev); + +/* Routines generic to NS8390-based boards. */ +void NS8390_init(struct device *dev, int startp); +static void NS8390_trigger_send(struct device *dev, unsigned int length, + int start_page); + +extern int el2autoprobe(int ioaddr, struct device *dev); +extern int el2probe(int ioaddr, struct device *dev); +extern int neprobe(int ioaddr, struct device *dev); +extern int wdprobe(int ioaddr, struct device *dev); +extern int hpprobe(int ioaddr, struct device *dev); + +struct sigaction ei_sigaction = { ei_interrupt, 0, 0, NULL, }; + +/* Open/initialize the board. This routine goes all-out, setting everything + up anew at each open, even though many of these registers should only + need to be set once at boot. + */ +static int +ei_open(struct device *dev) +{ + if ( ! ei_status.exists) { + printk(EI_NAME ": Opening a non-existent physical device\n"); + return 1; /* ENXIO would be more accurate. */ + } + + NS8390_init(dev, 1); + + /* The old local flags... */ + ei_status.txing = 0; + ei_status.in_interrupt = 0; + ei_status.open = 1; + /* ... are now global. */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + return 0; +} + +static int +ei_start_xmit(struct sk_buff *skb, struct device *dev) +{ + if ( ! ei_status.exists) + return 0; /* We should be able to do ENODEV, but nooo. */ + + if (ei_status.txing) { /* Do timeouts, just like the 8003 driver. */ + int txsr = inb(E8390_BASE+EN0_TSR); + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 5 || (tickssofar < 15 && ! (txsr & ENTSR_PTX))) { + return 1; + } + printk(EI_NAME": transmit timed out, TX status %#2x, ISR %#2x.\n", + txsr, inb(E8390_BASE+EN0_ISR)); + /* It's possible to check for an IRQ conflict here. + I may have to do that someday. */ + if ((txsr & ~0x02) == ENTSR_PTX) /* Strip an undefined bit. */ + printk(EI_NAME": Possible IRQ conflict?\n"); + else + printk(EI_NAME": Possible network cable problem?\n"); + /* It futile, but try to restart it anyway. */ + ei_reset_8390(dev); + NS8390_init(dev, 1); + } + + /* This is new: it means some higher layer thinks we've missed an + tx-done interrupt. Caution: dev_tint() handles the cli()/sti() + itself. */ + if (skb == NULL) { +#ifdef pre_995 + /* Alternative is ei_tx_intr(dev); */ + ei_status.txing = 1; + if (dev_tint(NULL, dev) == 0) + ei_status.txing = 0; +#else + dev_tint(dev); +#endif + return 0; + } + /* Fill in the ethernet header. */ + if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + skb->dev = dev; + arp_queue (skb); + return 0; + } + + dev->trans_start = jiffies; + cli(); +#ifdef PINGPONG + ei_tx_intr(dev); +#endif + ei_send_packet(skb, dev); + sti(); + if (skb->free) + kfree_skb (skb, FREE_WRITE); + return 0; +} + +/* The typical workload of the driver: + Handle the ether interface interrupts. */ +static void +ei_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev; + int interrupts, boguscount = 0; + + /* We do the same thing as the 8013 driver, but this is mostly bogus. */ + for (dev = dev_base; dev != NULL; dev = dev->next) { + if (dev->irq == irq) break; + } + dev->interrupt = 1; + ei_status.in_interrupt++; + sti(); /* Allow other interrupts. */ + +#ifdef notneeded + /* If we a getting a reset-complete interrupt the 8390 might not be + mapped in for the 3c503. */ + if (etherlink2) + outb_p(ei_status.thin_bit, E33G_CNTRL), + outb_p(0x00, E33G_STATUS); +#endif + + /* Change to page 0 and read the intr status reg. */ + outb_p(E8390_NODMA+E8390_PAGE0, EN_CMD); + if (ei_debug > 3) + printk(EI_NAME": interrupt(isr=%#2.2x).\n", + inb_p(E8390_BASE + EN0_ISR)); + + if (ei_status.in_interrupt > 1) + printk(EI_NAME ": Reentering the interrupt driver!\n"); + if (dev == NULL) { + printk (EI_NAME ": irq %d for unknown device\n", irq); + ei_status.in_interrupt--; + return; + } else if (ei_debug > 0 && eifdev != dev) { + printk (EI_NAME": device mismatch on irq %d.\n", irq); + dev = eifdev; + } + + /* !!Assumption!! -- we stay in page 0. Don't break this. */ + while ((interrupts = inb_p(E8390_BASE + EN0_ISR)) != 0 + && ++boguscount < 20) { + /* The reset interrupt is the most important... */ + if (interrupts & ENISR_RDC) { + outb_p(ENISR_RDC, E8390_BASE + EN0_ISR); /* Ack intr. */ + } + if (interrupts & ENISR_OVER) { + ei_status.overruns++; + ei_rx_overrun(dev); + } else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) { + /* Got a good (?) packet. */ + ei_receive(dev); + } + /* Push the next to-transmit packet through. */ + if (interrupts & ENISR_TX) { + ei_tx_intr(dev); + } else if (interrupts & ENISR_COUNTERS) { + /* Gotta read the counter to clear the irq, even if we + don't care about their values. */ + inb_p(E8390_BASE + EN0_COUNTER0); + inb_p(E8390_BASE + EN0_COUNTER1); + missed_packets += inb_p(E8390_BASE + EN0_COUNTER2); + outb_p(ENISR_COUNTERS, E8390_BASE + EN0_ISR); /* Ack intr. */ + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + } + + /* Ignore the transmit errs and reset intr for now. */ + if (interrupts & ENISR_TX_ERR) { + outb_p(ENISR_TX_ERR, E8390_BASE + EN0_ISR); /* Ack intr. */ + } + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + } + + if (interrupts && ei_debug) { + printk(EI_NAME ": unknown interrupt %#2x\n", interrupts); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, EN_CMD); + outb_p(0xff, E8390_BASE + EN0_ISR); /* Ack. all intrs. */ + } + ei_status.in_interrupt--; + return; +} + +#ifdef PINGPONG +static int lasttx = 0; +#endif + +/* This is stuffed into the dev struct to be called by dev.c:dev_tint(). + Evenually this should be replaced by the block_output() routines. */ +static void +ei_send_packet(struct sk_buff *skb, struct device *dev) +{ + int length = skb->len; + int send_length = ETHER_MIN_LEN < length ? length : ETHER_MIN_LEN; + + if (length <= 0) + return; + +#ifdef PINGPONG + if (ei_status.tx1 == 0) { /* First buffer empty */ + ei_block_output(dev, length, (void*)(skb+1), + ei_status.tx_start_page); + ei_status.tx1 = send_length; + } else if (ei_status.tx2 == 0) { /* Second buffer empty */ + ei_block_output(dev, length, (void*)(skb+1), + ei_status.tx_start_page+6); + ei_status.tx2 = send_length; + } else { + printk("%s: Internal error, no transmit buffer space tx1=%d tx2=%d lasttx=%d.\n", + ei_status.name, ei_status.tx1, ei_status.tx2, lasttx); + } + ei_status.txqueue++; + /* The following should be merged with ei_tx_intr(). */ + if (lasttx = 0) { + if (ei_status.tx1 > 0) { + NS8390_trigger_send(dev, ei_status.tx1, + ei_status.tx_start_page + 6), + ei_status.tx1 = -1, + lasttx = 1; + } else if (ei_status.tx2 > 0) { + NS8390_trigger_send(dev, ei_status.tx2, + ei_status.tx_start_page + 6), + ei_status.tx2 = -1, + lasttx = 2; + } + } +#else + ei_block_output(dev, length, (void*)(skb+1), ei_status.tx_start_page); + NS8390_trigger_send(dev, send_length, ei_status.tx_start_page); +#endif + return; +} + +/* We have finished a transmit: check for errors and then trigger the next + packet to be sent. */ +static void +ei_tx_intr(struct device *dev) +{ + int status = inb(E8390_BASE + EN0_TSR); + outb_p(ENISR_TX, E8390_BASE + EN0_ISR); /* Ack intr. */ + if ((status & ENTSR_PTX) == 0) + tx_errors++; + else + tx_packets++; + +#ifdef PINGPONG + ei_status.txqueue--; + if (ei_status.tx1 < 0) { + uif (lasttx != 1) + printk("%s: bogus last_tx_buffer %d, tx1=%d.\n", + ei_status.name, lasttx, ei_status.tx1); + ei_status.tx1 = 0; + lasttx = 0; + if (ei_status.tx2 > 0) { + NS8390_trigger_send(dev, ei_status.tx2, + ei_status.tx_start_page + 6), + ei_status.tx2 = -1, + lasttx = 2; + } + } else if (ei_status.tx2 < 0) { + if (lasttx != 2) + printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", + ei_status.name, lasttx, ei_status.tx2); + ei_status.tx2 = 0; + lasttx = 0; + if (ei_status.tx1 > 0) { + NS8390_trigger_send(dev, ei_status.tx1, + ei_status.tx_start_page), + ei_status.tx1 = -1; + lasttx = 1; + } + } /*else + printk(EI_NAME": unexpected TX interrupt.\n");*/ + while ((ei_status.tx1 == 0) || (ei_status.tx2 == 0)) { + dev->tbusy = 0; + dev_tint(dev); + if (dev->tbusy) + return; + else if (lasttx == 0) { + if (ei_status.tx1 == 0 || ei_status.tx2 != 0) + printk(EI_NAME": Unexpected tx buffer busy tx1=%d tx2=%d.\n", + ei_status.tx1, ei_status.tx2); + NS8390_trigger_send(dev, ei_status.tx1, + ei_status.tx_start_page), + ei_status.tx1 = -1; + lasttx = 1; + } + } +#else + ei_status.txing = 0; + dev->tbusy = 0; +#ifdef pre_995 + dev_tint(NULL, dev) +#else + mark_bh (INET_BH); +#endif +#endif +} + +/* We have a good packet(s), get it/them out of the buffers. */ + +static void +ei_receive(struct device *dev) +{ + int rxing_page, this_frame, next_frame, current_offset; + int boguscount = 0; + struct e8390_pkt_hdr rx_frame; + int num_rx_pages = ei_status.stop_page-ei_status.rx_start_page; + + while (++boguscount < 10) { + int size; + + cli(); + outb_p(E8390_NODMA+E8390_PAGE1, EN_CMD); /* Get the rec. page. */ + rxing_page = inb_p(E8390_BASE+EN1_CURPAG);/* (Incoming packet pointer).*/ + outb_p(E8390_NODMA+E8390_PAGE0, EN_CMD); + sti(); + + /* Remove one frame from the ring. Boundary is alway a page behind. */ + this_frame = inb_p(E8390_BASE + EN0_BOUNDARY) + 1; + if (this_frame >= ei_status.stop_page) + this_frame = ei_status.rx_start_page; + + /* Someday we'll omit the previous step, iff we never get this message.*/ + if (ei_debug > 0 && this_frame != ei_status.current_page) + printk(EI_NAME": mismatched read page pointers %2x vs %2x.\n", + this_frame, ei_status.current_page); + + if (this_frame == rxing_page) /* Read all the frames? */ + break; /* Done for now */ + + current_offset = this_frame << 8; + ei_block_input(dev, sizeof(rx_frame), (void *)&rx_frame, + current_offset); + + size = rx_frame.count - sizeof(rx_frame); + + next_frame = this_frame + 1 + ((size+4)>>8); + + /* Check for bogosity warned by 3c503 book: the status byte is never + written. This happened a lot during testing! This code should be + cleaned up someday, and the printk()s should be PRINTK()s. */ + if ( rx_frame.next != next_frame + && rx_frame.next != next_frame + 1 + && rx_frame.next != next_frame - num_rx_pages + && rx_frame.next != next_frame + 1 - num_rx_pages) { +#ifndef EI_DEBUG + ei_status.current_page = rxing_page; + outb(ei_status.current_page-1, E8390_BASE+EN0_BOUNDARY); + continue; +#else + static int last_rx_bogosity = -1; + printk(EI_NAME": bogus packet header, status=%#2x nxpg=%#2x sz=%#x (at %#4x)\n", + rx_frame.status, rx_frame.next, rx_frame.count, current_offset); + + if (rx_packets != last_rx_bogosity) { + /* Maybe we can avoid resetting the chip... empty the packet ring. */ + ei_status.current_page = rxing_page; + printk(EI_NAME": setting next frame to %#2x (nxt=%#2x, rx_frm.nx=%#2x rx_frm.stat=%#2x).\n", + ei_status.current_page, next_frame, + rx_frame.next, rx_frame.status); + last_rx_bogosity = rx_packets; + outb(ei_status.current_page-1, E8390_BASE+EN0_BOUNDARY); + continue; + } else { + /* Oh no Mr Bill! Last ditch error recovery. */ + printk(EI_NAME": multiple sequential lossage, resetting at packet #%d.", + rx_packets); + sti(); + ei_reset_8390(dev); + NS8390_init(dev, 1); + printk("restarting.\n"); + return; + } +#endif /* EI8390_NOCHECK */ + } + + if ((size < 32 || size > 1535) && ei_debug) + printk(EI_NAME": bogus packet size, status=%#2x nxpg=%#2x size=%#x\n", + rx_frame.status, rx_frame.next, rx_frame.count); + if ((rx_frame.status & 0x0F) == ENRSR_RXOK) { + int sksize = sizeof(struct sk_buff) + size; + struct sk_buff *skb; + skb = kmalloc(sksize, GFP_ATOMIC); + if (skb != NULL) { + skb->lock = 0; + skb->mem_len = sksize; + skb->mem_addr = skb; + /* 'skb+1' points to the start of sk_buff data area. */ + ei_block_input(dev, size, (void *)(skb+1), + current_offset + sizeof(rx_frame)); + if(dev_rint((void *)skb, size, IN_SKBUFF, dev)) { + printk(EI_NAME": receive buffers full.\n"); + break; + } + } else if (ei_debug) { + printk(EI_NAME": Couldn't allocate a sk_buff of size %d.\n", sksize); + break; + } + rx_packets++; + } else { + if (ei_debug) + printk(EI_NAME": bogus packet, status=%#2x nxpg=%#2x size=%d\n", + rx_frame.status, rx_frame.next, rx_frame.count); + soft_rx_err_bits |= rx_frame.status, + soft_rx_errors++; + } + next_frame = rx_frame.next; + + /* This should never happen, it's here for debugging. */ + if (next_frame >= ei_status.stop_page) { + printk(EI_NAME": next frame inconsistency, %#2x..", next_frame); + next_frame = ei_status.rx_start_page; + } + ei_status.current_page += 1 + ((size+4)>>8); +#ifdef notdef + if (ei_status.current_page > ei_status.stop_page) + ei_status.current_page -= ei_status.stop_page-ei_status.rx_start_page; + if (ei_status.current_page != next_frame) { + printk(EI_NAME": inconsistency in next_frame %#2x!=%#2x.\n", + this_frame, next_frame); + /* Assume this packet frame is scrogged by the NIC, use magic to + skip to the next frame. Actually we should stop and restart.*/ + next_frame = size > 1535 ? rx_frame.status : rx_frame.next; + ei_status.current_page = next_frame; + break; + } +#endif + + ei_status.current_page = next_frame; + outb(next_frame-1, E8390_BASE+EN0_BOUNDARY); + } + + /* Tell the upper levels we're done. */ + while (dev_rint(NULL, 0, 0, dev) == 1 + && ++boguscount < 20) + ; + /* Bug alert! Reset ENISR_OVER to avoid spurious overruns! */ + outb_p(ENISR_RX+ENISR_RX_ERR+ENISR_OVER, E8390_BASE+EN0_ISR); /* Ack intr. */ + return; +} + +/* We have a receiver overrun: we have to kick the 8390 to get it started + again. Overruns are detected on a per-256byte-page basis. */ +static void +ei_rx_overrun(struct device *dev) +{ + int reset_start_time = jiffies; + + /* We should already be stopped and in page0. Remove after testing. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, EN_CMD); + + if (ei_debug) + printk(EI_NAME ": Receiver overrun.\n"); + + /* The we.c driver does dummy = inb_p( RBCR[01] ); at this point. + It might mean something -- magic to speed up a reset? A 8390 bug?*/ + + /* Wait for reset in case the NIC is doing a tx or rx. This could take up to + 1.5msec, but we have no way of timing something in that range. The 'jiffies' + are just a sanity check. */ + while ((inb_p(E8390_BASE+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 1) { + printk(EI_NAME": reset did not complete at ei_rx_overrun.\n"); + NS8390_init(dev, 1); + return; + }; + + { + int old_rx_packets = rx_packets; + /* Remove packets right away. */ + ei_receive(dev); + rx_overrun_packets += (rx_packets - old_rx_packets); + } + outb_p(0xff, E8390_BASE+EN0_ISR); + /* Generic 8390 insns to start up again, same as in open_8390(). */ + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + outb_p(E8390_TXCONFIG, E8390_BASE + EN0_TXCR); /* xmit on. */ +#ifdef notneeded + outb_p(E8390_RXCONFIG, E8390_BASE + EN0_RXCR); /* rx on, */ +#endif +} + +int +ethif_init(struct device *dev) +{ + int i; + + eifdev = dev; /* Store for debugging. */ + + if (ei_debug > 3) + printk(version); + if (1 +#ifdef WD80x3 + && ! wdprobe(dev->base_addr, dev) +#endif +#ifdef EL2 + && ! el2autoprobe(dev->base_addr, dev) +#endif +#ifdef NE2000 + && ! neprobe(dev->base_addr, dev) +#endif +#ifdef HPLAN + && ! hpprobe(dev->base_addr, dev) +#endif + && 1 ) { + dev->open = &ei_open; + printk("No ethernet device found.\n"); + ei_status.exists = 0; + return 1; /* ENODEV or EAGAIN would be more accurate. */ + } + + e8390_base = dev->base_addr; + + /* Initialize the rest of the device structure. Many of these could + be in Space.c. */ + for (i = 0; i < DEV_NUMBUFFS; i++) + dev->buffs[i] = NULL; + + ei_status.exists = 1; + dev->hard_header = eth_hard_header; + dev->add_arp = eth_add_arp; + dev->queue_xmit = dev_queue_xmit; + dev->rebuild_header = eth_rebuild_header; + dev->type_trans = eth_type_trans; + + dev->send_packet = &ei_send_packet; + dev->open = &ei_open; + dev->hard_start_xmit = &ei_start_xmit; + + dev->type = ETHER_TYPE; + dev->hard_header_len = sizeof (struct enet_header); + dev->mtu = 1500; /* eth_mtu */ + dev->addr_len = ETHER_ADDR_LEN; + for (i = 0; i < dev->addr_len; i++) { + dev->broadcast[i]=0xff; + } + return 0; +} + + +/* This page of functions should be 8390 generic */ +/* Follow National Semi's recommendations for initializing the "NIC". */ +void NS8390_init(struct device *dev, int startp) +{ + int i; + int endcfg = ei_status.word16 ? (0x48 | ENDCFG_WTS) : 0x48; + int e8390_base = dev->base_addr; + + /* Follow National Semi's recommendations for initing the DP83902. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */ + outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ + /* Clear the remote byte count registers. */ + outb_p(0x00, e8390_base + EN0_RCNTLO); + outb_p(0x00, e8390_base + EN0_RCNTHI); + /* Set to monitor and loopback mode -- this is vital!. */ + outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ + /* Set the transmit page and receive ring. */ + outb_p(ei_status.tx_start_page, e8390_base + EN0_TPSR); + ei_status.tx1 = ei_status.tx2 = 0; + outb_p(ei_status.rx_start_page, e8390_base + EN0_STARTPG); + outb_p(ei_status.stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ + ei_status.current_page = ei_status.rx_start_page; /* assert boundary+1 */ + outb_p(ei_status.stop_page, e8390_base + EN0_STOPPG); + /* Clear the pending interrupts and mask. */ + outb_p(0xFF, e8390_base + EN0_ISR); + outb_p(0x00, e8390_base + EN0_IMR); + + /* Copy the station address into the DS8390 registers, + and set the multicast hash bitmap to receive all multicasts. */ + cli(); + outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */ + for(i = 0; i < 6; i++) { + outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i); + } + for(i = 0; i < 8; i++) + outb_p(0xff, e8390_base + EN1_MULT + i); + + outb_p(ei_status.rx_start_page, e8390_base + EN1_CURPAG); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); + sti(); + if (startp) { + outb_p(0xff, e8390_base + EN0_ISR); + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base); + outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ + /* 3c503 TechMan says rxconfig only after the NIC is started. */ + outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ + } + return; +} + +/* Trigger a transmit start, assuming the length is valid. */ +static void NS8390_trigger_send(struct device *dev, unsigned int length, + int start_page) +{ + int e8390_base = dev->base_addr; + + ei_status.txing = 1; + dev->tbusy = 1; + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base); + + if (inb_p(EN_CMD) & E8390_TRANS) { + printk(EI_NAME": trigger_send() called with the transmitter busy.\n"); + return; + } + outb_p(length & 0xff, e8390_base + EN0_TCNTLO); + outb_p(length >> 8, e8390_base + EN0_TCNTHI); + outb_p(start_page, e8390_base + EN0_TPSR); + outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base); + outb_p(ENISR_RDC, e8390_base + EN0_ISR); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -DPINGPONG -I/usr/src/linux/net/tcp -c 8390.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/ether-995/8390.h b/net/tcpip/ether-995/8390.h new file mode 100644 index 00000000..6644ac01 --- /dev/null +++ b/net/tcpip/ether-995/8390.h @@ -0,0 +1,129 @@ +/* Generic NS8390 register definitions. */ +/* This file is part of Donald Becker's 8390 drivers. + This file is distributed under the Linux GPL. + Some of these names and comments are from the Crynwr packet drivers. */ + +#ifndef e8390_h +#define e8390_h +#ifndef EI_NAME +#define EI_NAME "eth_if" +#endif +/*#define PINGPONG*/ +#ifdef PINGPONG +#define TX_PAGES 12 +#else +#define TX_PAGES 6 +#endif + +#define ETHER_ADDR_LEN 6 + +/* From auto_irq.c */ +extern void autoirq_setup(int waittime); +extern int autoirq_report(int waittime); + +/* Most of these entries should be in 'struct device' (or most + things in there should be here!) */ +struct ei_device { /* These should be stored per-board */ + char *name; + int exists:1; /* perhaps in dev->private. */ + int open:1; + int word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */ + void (*reset_8390)(struct device *); + void (*block_output)(struct device *, int, const unsigned char *, int); + int (*block_input)(struct device *, int, char *, int); + unsigned char tx_start_page, rx_start_page, stop_page; + unsigned char current_page; /* Read pointer in buffer */ + unsigned char thin_bit; /* Value to write to the 3c503 E33G_CNTRL */ + unsigned char txing; /* Transmit Active, don't confuse the upper levels. */ + unsigned char txqueue; /* Tx Packet buffer queue length. */ + unsigned char in_interrupt; + short tx1, tx2; /* Packet lengths for ping-pong tx. */ + int overruns; /* Rx overruns. */ +}; + +/* Some generic ethernet register configurations. */ +#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ +#define E8390_RX_IRQ_MASK 0x5 +#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ +#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ +#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ +#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ + +/* Register accessed at EN_CMD, the 8390 base addr. */ +#define E8390_STOP 0x01 /* Stop and reset the chip */ +#define E8390_START 0x02 /* Start the chip, clear reset */ +#define E8390_TRANS 0x04 /* Transmit a frame */ +#define E8390_RREAD 0x08 /* Remote read */ +#define E8390_RWRITE 0x10 /* Remote write */ +#define E8390_NODMA 0x20 /* Remote DMA */ +#define E8390_PAGE0 0x00 /* Select page chip registers */ +#define E8390_PAGE1 0x40 /* using the two high-order bits */ +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ + +/* Page 0 register offsets. */ +#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ +#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ +#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ +#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ +#define EN0_TSR 0x04 /* Transmit status reg RD */ +#define EN0_TPSR 0x04 /* Transmit starting page WR */ +#define EN0_NCR 0x05 /* Number of collision reg RD */ +#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ +#define EN0_FIFO 0x06 /* FIFO RD */ +#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ +#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ +#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ +#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ +#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ +#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ +#define EN0_RSR 0x0c /* rx status reg RD */ +#define EN0_RXCR 0x0c /* RX configuration reg WR */ +#define EN0_TXCR 0x0d /* TX configuration reg WR */ +#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ +#define EN0_DCFG 0x0e /* Data configuration reg WR */ +#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ +#define EN0_IMR 0x0f /* Interrupt mask reg WR */ +#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ + +/* Bits in EN0_ISR - Interrupt status register */ +#define ENISR_RX 0x01 /* Receiver, no error */ +#define ENISR_TX 0x02 /* Transmitter, no error */ +#define ENISR_RX_ERR 0x04 /* Receiver, with error */ +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ +#define ENISR_COUNTERS 0x20 /* Counters need emptying */ +#define ENISR_RDC 0x40 /* remote dma complete */ +#define ENISR_RESET 0x80 /* Reset completed */ +#define ENISR_ALL 0x3f /* Interrupts we will enable */ + +/* Bits in EN0_DCFG - Data config register */ +#define ENDCFG_WTS 0x01 /* word transfer mode selection */ + +/* Page 1 register offsets. */ +#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */ +#define EN1_CURPAG 0x07 /* Current memory page RD WR */ +#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */ + +/* Bits in received packet status byte and EN0_RSR*/ +#define ENRSR_RXOK 0x01 /* Received a good packet */ +#define ENRSR_CRC 0x02 /* CRC error */ +#define ENRSR_FAE 0x04 /* frame alignment error */ +#define ENRSR_FO 0x08 /* FIFO overrun */ +#define ENRSR_MPA 0x10 /* missed pkt */ +#define ENRSR_PHY 0x20 /* physical/multicase address */ +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ +#define ENRSR_DEF 0x80 /* deferring */ + +/* Transmitted packet status, EN0_TSR. */ +#define ENTSR_PTX 0x01 /* Packet transmitted without error */ + +/* The per-packet-header format. */ +struct e8390_pkt_hdr { + unsigned char status; /* status */ + unsigned char next; /* pointer to next packet. */ + unsigned short count; /* header + packet lenght in bytes */ +}; +#endif /* e8390_h */ diff --git a/net/tcpip/ether-995/ChangeLog b/net/tcpip/ether-995/ChangeLog new file mode 100644 index 00000000..c37827b3 --- /dev/null +++ b/net/tcpip/ether-995/ChangeLog @@ -0,0 +1,45 @@ +Fri Feb 12 15:45:13 1993 Donald J. Becker (becker at metropolis) + + * 8390.c: Commented out 'high_water_mark', since it's + never set and results in an 'unused variable' warning. + + * hp.c: Deleted the 'int i;' from hp_block_output() -- + it's unused now that port_write_b() is used instead + of an explicit loop. + +Thu Feb 11 16:04:27 1993 Donald J. Becker (becker at metropolis) + + * ne.c: Added explicit support for D-Link ethercards. + +Sat Jan 30 03:16:30 1993 Donald J. Becker (becker at metropolis) + + * hp.c: Changed the 8-bit output and input loops to use + port_{read,write?_b() instead. Assigned dev->irq before + sigaction() is call to avoid the 3c503 problem (below). + + * 3c503.c: Fixed a wild I/O port write in the probe code that had + been added to mask interrupts during probes. Also assigned dev->irq + before sigaction() is called to correctly handle that spurious + first interrupt. + + * wd.c: Changed the IRQ from the unreliable autoIRQ to reading the + configuation register. I also go a report that it still works + with the 8003 + +Fri Jan 29 11:29:10 1993 Donald J. Becker (becker at metropolis) + + * 3c503: Added EL2_AUI as an alias for EI8390_THICK, and rewrote + the IRQ selection code. It now does assigns the first free IRQ + from the list { 5 2/9 3 4 }. + + * GNUmakefile: Changed the default name from "eth_if" to "eth0" to + be compatible. Also changed the name of EI8390_THICK to EL2_AUI. + + * 8390.c: Omitted incrementing ei_debug during a rx_overrun. + + * ne.c: I put the a ctron check inside of #ifdef EI_8BIT + so that 8-bit Cabletron card are recognized. + Thanks to Eric Wallace, wallace@chezmoto.ai.mit.edu. + + + diff --git a/net/tcpip/ether-995/GNUmakefile b/net/tcpip/ether-995/GNUmakefile new file mode 100644 index 00000000..6603727a --- /dev/null +++ b/net/tcpip/ether-995/GNUmakefile @@ -0,0 +1,36 @@ +# This file must be named 'GNUmakefile'. When it has that name it +# loaded in preference to the regular 'Makefile' (which it include +# right here) so this has the effect of appending lines to the Makefile. + +include Makefile + +# Add a few files to tcpip.a. +newobjs = 8390.o 3c503.o ne.o wd.o hp.o auto_irq.o +OBJS := $(OBJS) $(newobjs) +tcpip.a: $(newobjs) + +# Set the address and IRQ here. The ne.c and 3c503 driver will autoprobe +# if you set the address or IRQ to zero, so we do that by default. +# +# Add -DEI_NAME="eth0" if you want to be exactly compatible with the default +# driver. This will only work if you don't use the distributed 'we' driver! +# +ether_options := -DEI_NAME=\"eth0\" -DEI8390=0 -DEI8390_IRQ=0 +Space.o: Space.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) $(ether_options) -c Space.c -o $@ + +# Change this to define the set of ethercards your kernel will support. +8390.o: 8390.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -DNE2000 -DWD80x3 -DHPLAN -DEL2 -c 8390.c -o $@ + +# Change this to -DEI_8BIT if you have an 8-bit ethercard (NE1000, E10xx). +ne.o: ne.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -UEI_8BIT -c ne.c -o $@ + +# Change this to -DEL2_AUI if you use the AUI port. +3c503.o: 3c503.c 3c503reg.h GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -UEL2_AUI -c 3c503.c -o $@ + +# Change this to -DSHMEM=0xd0000 if you have an old non-EEPROM wd8003 +wd.o: wd.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -UWD_SHMEM -c wd.c -o $@ diff --git a/net/tcpip/ether-995/INSTALL b/net/tcpip/ether-995/INSTALL new file mode 100644 index 00000000..413a4fdb --- /dev/null +++ b/net/tcpip/ether-995/INSTALL @@ -0,0 +1,82 @@ +Installation Directions: + +EMail me (becker@super.org) telling me which version you have gotten. +I need to know how many people have tried, succeeded and +failed before this is released as part of the official Linux. + +Use Linux 0.99.2 or later. Make certain you can make a working kernel +_before_ you install the ethercard driver. + +Put the all of the files into linux/net/tcp/. You'll need all of the +files in this directory. +GNUmakefile 8390.c 8390.h auto_irq.c Space.c wd.c ne.c 3c503.[ch] and hp.c. +Space.c is the only tricky one -- it overwrites the old Space.c. +Stock versions of Space.c leave the "we" driver enabled and will not work. + +Change the GNUmakefile to reflect your configuration. Use the guide at +the end of these instructions and in the README file. + +Make and install your new kernel. + +To actually use this driver you must get the TCP/IP package and edit +your /usr/etc/inet/rc.net file to config whatever you named your +ethernet device. (You can edit the GNUmakefile to use something +besides the "eth0" name. Note that the default name has changed to +the now-standard "eth0" from the old "eth_if"!) + +If you try to 'config' an interface that doesn't exist your kernel +will report "invalid ioctl()" for anthing that tries to use the card. +Note that the ethercard devices aren't (yet) real '/dev/eth_if' devices -- +they only exist in the socket namespace and thus you don't need to +'mknode' them. + +________________ +Important defines + +For Space.c +#define EI8390 0 /* The base address of your ethercard. */ +#define EI8390_IRQ 0 /* and the interrupt you want to use. */ + /* '0' means autoconfigure */ +For 8390.c +#define EI_DEBUG 2 /* Use '0' for no messages. */ +#define EL2 /* For the 3c503 driver. */ +#define NE2000 /* For the NE1000/NE2000/Ctron driver. */ +#define WD80x3 /* For the WD8003/WD8013 driver. */ +#define HPLAN /* For the HP27xxx driver. */ + +For the individual drivers +#undef EI_8BIT /* Define for ne.c iff you have an 8 bit card. */ +#undef EL2_AUI /* Define to use the 3c503 AUI/DIX transceiver. */ + +EI8390 Define (probably in autoconf.h or config.site.h) this to the base + address of your ethernet card. +EI8390_IRQ Define (probably in autoconf.h or config.site.h) this to the + IRQ line of your ethernet card. Most drivers convert a IRQ2 to an + IRQ9 for you, so don't be surprised. +EI_DEBUG Set to the desired numeric debugging level. Use 3 or + greater when actively debugging a problem, '1' for a + casual interest in what's going on, and '0' for normal + use. (Most of the debugging stuff has been taken out recently, + so this won't have much effect.) +EI_PINGPONG + Not included or broken the alpha version. Define this if you want + ping-pong transmit buffers. +EI_8BIT + If you are using the ne.c driver and have an 8-bit card (NE1000 or + E1xxx Cabletron) you must define this. It's not needed for the other + drivers, and I hope to find a way to clean this up in the future. +EL2_AUI + Define for this if you are using the 3c503 and use the AUI/DIX + connector rather than the built-in thin-net transceiver. +WD_SHMEM + Define this to override the shared memory address used by the + WD driver. This should only be necessary for old, jumpered '8003's. + +If you have a Cabletron ethercard you might want to look at ne.c:neprobe() +for info on how to enable more packet buffer space. + +ETHERLINK1_IRQ +ETHERLINK1 Define these to the base address and IRQ of a 3c501 (NOT 3c503) + card. Refer to net/tcp/Space.c. + + diff --git a/net/tcpip/ether-995/README b/net/tcpip/ether-995/README new file mode 100644 index 00000000..c535da49 --- /dev/null +++ b/net/tcpip/ether-995/README @@ -0,0 +1,101 @@ +This is the current version of the 8390 ethercard driver. +The ether-994 drivers are for 0.99.4 and earlier. +The ether-995 drivers are for 0.99.5. + +You should consult the list below for the specific #define for your +ethercard. If you don't have one specific #define the driver will +probe for all supported ethercard types. + +Source Header #define to get Supported cards +8390.c 8390.h EI8390 (generic, needed for all) +3c503.c 3c503reg.h EL2 3c503, 3c503/16 +ne.c NE2000 NE1000, NE2000, NatSemi, Cabletron +wd.c wd.h WD80x3 WD8003, WD8013, SMC elite +hp.c HPLAN HP LAN adaptors + +Notes on each file +INSTALL +The installation directions -- "read this first, uhmmm, second". + +GNUmakefile +The 'GNUmakefile' name is "magic". You just put it into the directory +and it is loaded instead of the regular Makefile (which it thenincludes). +Most people should never need to edit the Makefile, just the GNUmakefile. + +3c503.c +o You'll need to '#define EI8390_THICK' or EL2_AUI if you are using the AUI port + instead of the thinnet connector. Russ Nelson sent me an + run-time method of selecting between the two, but I haven't put it in yet. + This _may_ generate a spurious error message when transmitting the first + packet, I haven't yet tracked down this bug report. +o If you want to check the shared memory, #define EL2MEMTEST. I don't think + the memory check is worth the effort -- it's missed obvious problems. +o You must jumper the board to use shared memory -- I don't test the + non-shared-memory mode and it's probably broken. +o Thanks to Chance Reschke at USRA for providing the + 3c503 and anonymous FTP space. + +ne.c +o You'll need to #define EI_8BIT if you are using an 8-bit ethercard + such as the NE1000 or Cabletron E10xx. I might someday make a run-time + selection between the NE1000 and NE2000 (right now it screws up the + non-default bus-width) but I don't know how to distinguish the Cabletron + ethercards. I'm hoping to find a general way to identify the board's bus + width, but don't hold your breath. + +wd.c +o Thanks to Russ Nelson (nelson@crynwr.com) for loaning me a WD8013. +o The 8013 doesn't work if it's probed by some other driver first: keep + it first in the probe list. + I could reset the board before looking at it to fix the probe problem, but + this involves an outb() which may disturb non-WD8013 devices. +o You _must_ run this board with shared memory enabled. Don't set the + jumper to the no-shared-memory setting. +o The driver now reads the EEPROM setting, so you can use the EEPROM + settings! And there is a new Linux 'wdsetup' program that replaces + MS-DOS 'EZSETUP'! +o You machine may fail to do a soft reboot if the packet buffer shared memory + is mapped in -- the machine might think its a boot PROM (since it + intentionally shares the same memory space as the optional on-board + boot PROM). "Live with it" for now. +o If the packet buffer memory is mapped into a cacheable region it won't work! + It's really easy to this with the map-it-anywhere EEPROM. Check your BIOS + setup. +o If you have an old non-EEPROM wd8003 and need to change the shared memory + address from the default 0xd0000 set WD_SHMEM to the desired address. + +hp.c +o This has only been tested with a 27245A, 27247A, and 27250. It doesn't yet + work with the new 27247B! +o Thanks to Chance Reschke at USRA for loaning me the + 27247A ethercard. + + +BUGS + + The "bogus packet header" is a bug in the 8390. I drop all of + the packets in the ring (usually just one) when this happens. + If you get this more than just occasionally please report it to me. + + I don't yet distinguish between the problems with IRQ conflicts and + problems with the ethernet cable not being connected. If you get + a "transmit timed out" message check both! Your ethercard + probably will NOT work without proper termination. + + A small number of people report continuous "RX transfer address mismatch" + errors with the NE2000. This is a bug in the 8390, and the reason + most designers use shared memory or design their own packet buffer access + circuitry rather than use what's provided by the 8390. An occasional + "mismatch" message (say, once a week) won't impact performance. + + I've fixed most of the spurious "receiver overrun" messages. It + was a bug in the 8390 -- the overrun flag is sometimes set + when the boundary pointer is written. If you still get + isolated overrun errors please send me email. + + The 3c501 driver isn't complete. This card is severely brain-damaged + anyway -- you won't notice the performance difference between working + and non-working versions anyway. If this source code is here, it is + only provided for a few people that wanted to write code for their 3c501 + cards. Don't send me email about it unless it's a bug fix. + diff --git a/net/tcpip/ether-995/Space.c b/net/tcpip/ether-995/Space.c new file mode 100644 index 00000000..ab5781d9 --- /dev/null +++ b/net/tcpip/ether-995/Space.c @@ -0,0 +1,134 @@ +/* Space.c */ +/* Holds initial configuration information for devices. */ +#include "dev.h" +#include +#include + +#define NEXT_DEV NULL + +#ifdef ETHERLINK1 +extern int etherlink_init(struct device *); + +#ifndef ETHERLINK1_IRQ +#define ETHERLINK1_IRQ 9 +#endif + +static struct device el_dev = { + "if3c501", + 0, 0, 0, 0, /* memory rx_end, rx_start, end, start are autoconfiged. */ + ETHERLINK1, ETHERLINK1_IRQ, /* base i/o address, irq. */ + 0,0,0,0,0, + NEXT_DEV, + etherlink_init, 0, {NULL}, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, {0,}, {0,}, 0 + }; +#undef NEXT_DEV +#define NEXT_DEV (&el_dev) + +#endif /* ETHERLINK1 */ + +#if defined(EI8390) || defined(EL2) || defined(NE2000) \ + || defined(WD80x3) || defined(HPLAN) +extern int ethif_init(struct device *); + +#ifndef EI8390_IRQ +#define EI8390_IRQ 0 +#endif + +static struct device ei8390_dev = { +#ifdef EI_NAME + EI_NAME, +#else + "eth_if", +#endif + 0, 0, 0, 0, /* memory rx_end, rx_start, end, start are autoconfiged. */ + EI8390, EI8390_IRQ, 0,0,0,0,0, /* base i/o address, irq, and flags. */ + NEXT_DEV, + ethif_init, 0, {NULL}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, 0, 0, {0,}, {0,}, 0 + }; +#undef NEXT_DEV +#define NEXT_DEV (&ei8390_dev) + +#endif /* The EI8390 drivers. */ + +#ifdef WD8003 +extern int wd8003_init(struct device *); + +static struct device wd8003_dev = +{ + "eth0", + 0xd2000, /* recv memory end. */ + 0xd0600, /* recv memory start. */ + 0xd2000, /* memory end. */ + 0xd0000, /* memory start. */ + 0x280, /* base i/o address. */ + 5, /* irq */ + 0,0,0,0,0, /* flags */ + NEXT_DEV, + wd8003_init, + /* wd8003_init should set up the rest. */ + 0, /* trans start. */ + {NULL}, /* buffs */ + NULL, /* backlog */ + NULL, /* open */ + NULL, /* stop */ + NULL, /* hard_start_xmit */ + NULL, /* hard_header */ + NULL, /* add arp */ + NULL, /* queue xmit */ + NULL, /* rebuild header */ + NULL, /* type_trans */ + NULL, /* send_packet */ + NULL, /* private */ + 0, /* type. */ + 0, /* hard_header_len */ + 0, /* mtu */ + {0,}, /* broadcast address */ + {0,}, /* device address */ + 0 /* addr len */ +}; +#undef NEXT_DEV +#define NEXT_DEV (&wd8003_dev) + +#endif /* WD8003 */ + +extern int loopback_init(struct device *dev); + +static struct device loopback_dev = +{ + "loopback", + -1, /* recv memory end. */ + 0x0, /* recv memory start. */ + -1, /* memory end. */ + 0, /* memory start. */ + 0, /* base i/o address. */ + 0, /* irq */ + 0,0,1,0,0, /* flags */ + NEXT_DEV, /* next device */ + loopback_init, + /* loopback_init should set up the rest. */ + 0, /* trans start. */ + {NULL}, /* buffs */ + NULL, /* backlog */ + NULL, /* open */ + NULL, /* stop */ + NULL, /* hard_start_xmit */ + NULL, /* hard_header */ + NULL, /* add arp */ + NULL, /* queue xmit */ + NULL, /* rebuild header */ + NULL, /* type_trans */ + NULL, /* send_packet */ + NULL, /* private */ + 0, /* type. */ + 0, /* hard_header_len */ + 0, /* mtu */ + {0,}, /* broadcast address */ + {0,}, /* device address */ + 0 /* addr len */ +}; +#undef NEXT_DEV +#define NEXT_DEV (error no next device &loopback_dev) + +struct device *dev_base = &loopback_dev; diff --git a/net/tcpip/ether-995/auto_irq.c b/net/tcpip/ether-995/auto_irq.c new file mode 100644 index 00000000..3acfa9ea --- /dev/null +++ b/net/tcpip/ether-995/auto_irq.c @@ -0,0 +1,100 @@ +/* auto_irq.c: Auto-configure IRQ lines for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + + This code is a general-purpose IRQ line detector for devices with + jumpered IRQ lines. If you can make the device raise an IRQ (and + that IRQ line isn't already being used), these routines will tell + you what IRQ line it's using -- perfect for those oh-so-cool boot-time + device probes! + + To use this, first call autoirq_setup(timeout). TIMEOUT is how many + 'jiffies' (1/18 sec.) to detect other devices that have active IRQ lines, + and can usually be zero at boot. + Next, set up your device to trigger an interrupt. + Finally call autoirq_report(TIMEOUT) to find out which IRQ line was + most recently active. The TIMEOUT should usually be zero, but may + be set to the number of jiffies to wait for an active IRQ. + + The idea of using the setup timeout to filter out bogus IRQs came from + the serial driver. +*/ + + +#ifdef version +static char *version="auto_irq.c:v0.01 1993 Donald Becker (becker@super.org)"; +#endif + +/*#include */ +/*#include */ +#include +#include +#include +/*#include */ + +static volatile int irq_number; /* The latest irq number we actually found. */ +static volatile int irq_bitmap; /* The irqs we actually found. */ +static int irq_handled; /* The irq lines we have a handler on. */ + +static void autoirq_probe(int irq) +{ + irq_number = irq; + set_bit(irq, (void *)&irq_bitmap); + /*irq_bitmap |= 1 << irq;*/ + return; +} +struct sigaction autoirq_sigaction = { autoirq_probe, 0, SA_INTERRUPT, NULL}; + +void autoirq_setup(int waittime) +{ + int i, mask; + int timeout = jiffies+waittime; + + irq_number = 0; + irq_bitmap = 0; + irq_handled = 0; + for (i = 0; i < 16; i++) { + if (!irqaction(i, &autoirq_sigaction)) + set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/ + } + /* Hang out at least jiffies waiting for bogus IRQ hits. */ + while (timeout >= jiffies) + ; + + for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) { + if (irq_bitmap & irq_handled & mask) { + irq_handled &= ~mask; + printk(" Spurious interrupt on IRQ %d\n", i); + free_irq(i); + } + } +} + +int autoirq_report(int waittime) +{ + int i; + int timeout = jiffies+waittime; + + /* Hang out at least jiffies waiting for the IRQ. */ + while (timeout >= jiffies) + if (irq_number) + break; + + /* Retract the irq handlers that we installed. */ + for (i = 0; i < 16; i++) { + if (test_bit(i, (void *)&irq_handled)) + free_irq(i); + } + return irq_number; +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/ether-995/hp.c b/net/tcpip/ether-995/hp.c new file mode 100644 index 00000000..3b179f8b --- /dev/null +++ b/net/tcpip/ether-995/hp.c @@ -0,0 +1,303 @@ +/* hp.c: A HP LAN ethernet driver for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This is a driver for the HP LAN adaptors. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = "hp.c:v0.43 2/12/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define port_read_b(port,buf,nr) \ +__asm__("cld;rep;insb"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write_b(port,buf,nr) \ +__asm__("cld;rep;outsb"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define HP_DATAPORT 0x0c /* "Remote DMA" data port. */ +#define HP_ID 0x07 +#define HP_CONFIGURE 0x08 /* Configuration register. */ +#define HP_RUN 0x01 /* 1 == Run, 0 == reset. */ +#define HP_IRQ 0x0E /* Mask for software-configured IRQ line. */ +#define HP_DATAON 0x10 /* Turn on dataport */ +#define NIC_OFFSET 0x10 /* Offset the 8390 registers. */ + +#define HP_START_PG 0x00 /* First page of TX buffer */ +#define HP_8BSTOP_PG 0x80 /* Last page +1 of RX ring */ +#define HP_16BSTOP_PG 0xFF /* Last page +1 of RX ring */ + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int hpprobe(int ioaddr, struct device *dev); +int hpprobe1(int ioaddr, struct device *dev); + +static void hp_reset_8390(struct device *dev); +static int hp_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void hp_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static void hp_init_card(struct device *dev); + + +/* Probe for an HP LAN adaptor. + Also initialize the card and fill in STATION_ADDR with the station + address. */ + +int hpprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0}; + + if (ioaddr > 0x100) + return hpprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb_p(*port) != 0xff && hpprobe1(*port, dev)) + return dev->base_addr; + return 0; +} + +int hpprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + unsigned char SA_prom[6]; + int tmp; + int hplan; + + printk("HP-LAN ethercard probe at %#3x:", ioaddr); + tmp = inb_p(ioaddr); + if (tmp == 0xFF) { + printk(" not found (nothing there).\n"); + return 0; + } + + for(i = 0; i < sizeof(SA_prom); i++) { + SA_prom[i] = inb(ioaddr + i); + if (i < ETHER_ADDR_LEN && station_addr) { + printk(" %2.2x", SA_prom[i]); + station_addr[i] = SA_prom[i]; + } + } + hplan = (SA_prom[0] == 0x08 && SA_prom[1] == 0x00 && SA_prom[2] == 0x09); + if (hplan == 0) { + printk(" not found (invalid station address prefix).\n"); + return 0; + } + + ei_status.tx_start_page = HP_START_PG; + ei_status.rx_start_page = HP_START_PG + TX_PAGES; + /* Set up the rest of the parameters. */ + if ((tmp = inb_p(HP_ID)) & 0x80) { + ei_status.name = "HP27247"; + ei_status.word16 = 1; + ei_status.stop_page = HP_16BSTOP_PG; /* Safe for now */ + } else { + ei_status.name = "HP27250"; + ei_status.word16 = 0; + ei_status.stop_page = HP_8BSTOP_PG; /* Safe for now */ + } + + /* Set the base address to point to the NIC! */ + dev->base_addr = ioaddr + NIC_OFFSET; + + if (dev->irq == 2) + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + if (dev->irq < 2) { + int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0}; + int irq_8list[] = { 7, 5, 3, 4, 9, 0}; + int *irq = ei_status.word16 ? irq_16list : irq_8list; + for (; *irq; irq++) { + if (irqaction(dev->irq = *irq, &ei_sigaction) == 0) + break; + } + if (*irq == 0) { + printk (" unable to get an IRQ.\n"); + return 0; + } + } + + printk(" %s found, using IRQ %d.\n", ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + + ei_status.reset_8390 = &hp_reset_8390; + ei_status.block_input = &hp_block_input; + ei_status.block_output = &hp_block_output; + hp_init_card(dev); + return dev->base_addr; +} + +static void +hp_reset_8390(struct device *dev) +{ + int hp_base = dev->base_addr - NIC_OFFSET; + int saved_config = inb_p(hp_base + HP_CONFIGURE); + int reset_start_time = jiffies; + + if (ei_debug > 1) printk("resetting the 8390 time=%d...", jiffies); + outb_p(0x00, hp_base + HP_CONFIGURE); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + break; + } + } + + outb_p(saved_config, hp_base + HP_CONFIGURE); + while ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk(EI_NAME": hp_reset_8390() did not complete.\n"); + return; + } + if (ei_debug > 1) printk("8390 reset done.", jiffies); +} + +/* Block input and output, similar to the Crynwr packet driver. If you + porting to a new ethercard look at the packet driver source for hints. + The HP LAN doesn't use shared memory -- we put the packet + out through the "remote DMA" dataport. */ + +static int +hp_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int nic_base = dev->base_addr; + int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); + int xfer_count = count; + + outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base); + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); + outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, nic_base); + if (ei_status.word16) { + port_read(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1); + if (count & 0x01) + buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++; + } else { + port_read_b(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count); + } + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + /* Check only the lower 8 bits so we can ignore ring wrap. */ + if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff)) + printk(EI_NAME": RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n", + ring_offset + xfer_count, addr); + } + outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); + return ring_offset + count; +} + +static void +hp_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page) +{ + int nic_base = dev->base_addr; + int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); + + outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + if (ei_status.word16 && (count & 0x01)) + count++; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base); + +#ifdef ei8390_bug + /* Handle the read-before-write bug the same way as the + Crynwr packet driver -- the NatSemi method doesn't work. */ + outb_p(0x42, nic_base + EN0_RCNTLO); + outb_p(0, nic_base + EN0_RCNTHI); + outb_p(0xff, nic_base + EN0_RSARLO); + outb_p(0x00, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + /* Make certain that the dummy read has occured. */ + inb_p(0x61); + inb_p(0x61); +#endif + + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(0x00, nic_base + EN0_RSARLO); + outb_p(start_page, nic_base + EN0_RSARHI); + + outb_p(E8390_RWRITE+E8390_START, nic_base); + if (ei_status.word16) { + /* Use the 'rep' sequence for 16 bit boards. */ + port_write(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1); + } else { + port_write_b(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count); + } + + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */ + + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + if ((start_page << 8) + count != addr) + printk(EI_NAME": TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n", + (start_page << 8) + count, addr); + } + outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); + return; +} + +/* This function resets the ethercard if something screws up. */ +static void +hp_init_card(struct device *dev) +{ + int irq = dev->irq; + /* default is IRQ5 0 1 2 3 4 5 6 7 8 9 10 11 */ + static char irqval[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0}; + NS8390_init(dev, 0); + outb_p(irqval[irq&0x0f] | HP_RUN, + dev->base_addr - NIC_OFFSET + HP_CONFIGURE); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c hp.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/ether-995/ne.c b/net/tcpip/ether-995/ne.c new file mode 100644 index 00000000..e8f6991c --- /dev/null +++ b/net/tcpip/ether-995/ne.c @@ -0,0 +1,379 @@ +/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with many 8390-based ethernet boards. Currently + it support the NE1000, NE2000 (and clones), and some Cabletron products. + 8-bit ethercard support is enabled with #define EI_8BIT + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +/* Routines for the NatSemi-based designs (NE[12]000). */ + +static char *version = + "ne.c:v0.50 2/19/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define port_read_b(port,buf,nr) \ +__asm__("cld;rep;insb"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write_b(port,buf,nr) \ +__asm__("cld;rep;outsb"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define EN_CMD (dev->base_addr) +#define NE_BASE (dev->base_addr) +#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ +#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ + +#define NE1SM_START_PG 0x20 /* First page of TX buffer */ +#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ +#define NESM_START_PG 0x40 /* First page of TX buffer */ +#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int neprobe(int ioaddr, struct device *dev); +static int neprobe1(int ioaddr, struct device *dev); + +static void ne_reset_8390(struct device *dev); +static int ne_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void ne_block_output(struct device *dev, const int count, + const unsigned char *buf, const int start_page); +static void ne_init_card(struct device *dev); + + +/* Probe for the NE1000 and NE2000. NEx000-like boards have 0x57,0x57 in + bytes 0x0e,0x0f of the SAPROM, but if we read by 16 bit words the NE1000 + appears to have 0x00, 0x42. */ +/* Also initialize the card and fill in STATION_ADDR with the station + address. The station address (and other data) is stored in the + packet buffer memory space, 32 bytes starting at remote DMA address 0. */ + +int neprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x320, 0x340, 0x360, 0}; + + if (ioaddr > 0x100) + return neprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb_p(*port) != 0xff && neprobe1(*port, dev)) + return dev->base_addr = *port; + return 0; +} + +static int neprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + unsigned char SA_prom[32]; + int cmdreg; + int ne2000 = 0, ne1000 = 0, ctron = 0, dlink = 0; + + printk("8390 ethercard probe at %#3x:", ioaddr); + + cmdreg = inb_p(ioaddr); + if (cmdreg == 0xFF) { + printk(" not found (%#2.2x).\n", cmdreg); + return 0; + } + /* Ooops, we must first initialize registers -- we can't just read the PROM + address right away. (Learned the hard way.) */ + /* NS8390_init(eifdev, 0);*/ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr); +#ifdef EI_8BIT + outb_p(0x48, ioaddr + EN0_DCFG); /* Set byte-wide for probe. */ +#else + outb_p(0x49, ioaddr + EN0_DCFG); /* Set word-wide for probe. */ +#endif + /* Even though we'll set them soon, we must clear them! */ + outb_p(0x00, ioaddr + EN0_RCNTLO); + outb_p(0x00, ioaddr + EN0_RCNTHI); + + outb_p(0x00, ioaddr + EN0_IMR); /* Mask completion irq. */ + outb_p(0xFF, ioaddr + EN0_ISR); + + /* Set to monitor and loopback mode. */ + outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, ioaddr + EN0_TXCR); /* 0x02 */ + + +#ifdef EI_8BIT + outb_p(sizeof(SA_prom), ioaddr + EN0_RCNTLO); +#else + /* Double count 0x20 words, the SA PROM is only byte wide. */ + outb_p(2*sizeof(SA_prom), ioaddr + EN0_RCNTLO); +#endif + outb_p(0x00, ioaddr + EN0_RCNTHI); + outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0000. */ + outb_p(0x00, ioaddr + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, ioaddr); + for(i = 0; i < sizeof(SA_prom); i++) { + SA_prom[i] = inb_p(ioaddr + NE_DATAPORT); + if (i < ETHER_ADDR_LEN && station_addr) { + printk(" %2.2x", SA_prom[i]); + station_addr[i] = SA_prom[i]; + } + } +#ifdef EI_8BIT + ne1000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); + ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); + dlink = (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01); +#else + ne2000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); + ne1000 = (SA_prom[14] == 0x00 && SA_prom[15] == 0x42); + ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); + dlink = (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01); +#endif + + /* Set up the rest of the parameters. */ + if (ne1000 || dlink) { + ei_status.name = ne1000 ? "NE1000" : "D-Link"; + ei_status.word16 = 0; + ei_status.tx_start_page = NE1SM_START_PG; + ei_status.rx_start_page = NE1SM_START_PG + TX_PAGES; + ei_status.stop_page = NE1SM_STOP_PG; + } else if (ne2000) { + ei_status.name = "NE2000"; + ei_status.word16 = 1; + ei_status.tx_start_page = NESM_START_PG; + ei_status.rx_start_page = NESM_START_PG + TX_PAGES; + ei_status.stop_page = NESM_STOP_PG; + } else if (ctron) { + /* You'll have to set these yourself, but this info might be useful. + Cabletron packet buffer locations: + E1010 starts at 0x100 and ends at 0x2000. + E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory") + E2010 starts at 0x100 and ends at 0x4000. + E2010-x starts at 0x100 and ends at 0xffff. */ + ei_status.name = "Cabletron"; +#ifdef EI_8BIT + ei_status.word16 = 0; +#else + ei_status.word16 = 1; +#endif + ei_status.tx_start_page = 0x01; + ei_status.rx_start_page = 0x01 + TX_PAGES; +#ifndef CTRON_MEMSIZE +#define CTRON_MEMSIZE 0x20 /* Extra safe... */ +#endif + ei_status.stop_page = CTRON_MEMSIZE; + } else { + printk(" not found.\n"); + return 0; + } + + dev->base_addr = ioaddr; + + if (dev->irq < 2) { + int nic_base = dev->base_addr; + autoirq_setup(0); + outb_p(0x50, nic_base + EN0_IMR); /* Enable one interrupt. */ + outb_p(0x00, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(E8390_RREAD+E8390_START, nic_base); /* Trigger it... */ + outb_p(0x00, nic_base + EN0_IMR); /* Mask it again. */ + dev->irq = autoirq_report(0); + if (ei_debug > 2) + printk(" autoirq is %d", dev->irq); + } else if (dev->irq == 2) + /* Fixup for users that don't know that IRQ 2 is really IRQ 9, + or don't know which one to set. */ + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + { int irqval = irqaction (dev->irq, &ei_sigaction); + if (irqval) { + printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); + return 0; + } + } + + printk(" %s found, using IRQ %d.\n", ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + ei_status.reset_8390 = &ne_reset_8390; + ei_status.block_input = &ne_block_input; + ei_status.block_output = &ne_block_output; + ne_init_card(dev); + return dev->base_addr; +} + +static void +ne_reset_8390(struct device *dev) +{ + int tmp = inb_p(NE_BASE + NE_RESET); + int reset_start_time = jiffies; + + if (ei_debug > 1) printk("resetting the 8390 t=%d...", jiffies); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + outb_p(tmp, NE_BASE + NE_RESET); + return; + } + } + + outb_p(tmp, NE_BASE + NE_RESET); + while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk(EI_NAME": ne_reset_8390() did not complete.\n"); + break; + } +} + +/* Block input and output, similar to the Crynwr packet driver. If you + porting to a new ethercard look at the packet driver source for hints. + The NEx000 doesn't share it on-board packet memory -- you have to put + the packet out through the "remote DMA" dataport using outb. */ + +static int +ne_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int xfer_count = count; + int nic_base = NE_BASE; + + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, EN_CMD); + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); + outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + if (ei_status.word16) { + port_read(NE_BASE + NE_DATAPORT,buf,count>>1); + if (count & 0x01) + buf[count-1] = inb(NE_BASE + NE_DATAPORT), xfer_count++; + } else { + port_read_b(NE_BASE + NE_DATAPORT, buf, count); + } + + /* This was for the ALPHA version only, but enough people have + encountering problems that it is still here. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int addr, tries = 10; + do { + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here + -- it's broken! Check the "DMA" address instead. */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + addr = (high << 8) + low; + if (((ring_offset + xfer_count) & 0xff) == low) + return ring_offset + count; + } while (--tries > 0); + printk(EI_NAME": RX transfer address mismatch, %#4.4x (should be) vs. %#4.4x (actual).\n", + ring_offset + xfer_count, addr); + } + return ring_offset + count; +} + +static void +ne_block_output(struct device *dev, int count, + const unsigned char *buf, const int start_page) +{ + int retries = 0; + int nic_base = NE_BASE; + + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + if (ei_status.word16 && (count & 0x01)) + count++; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, EN_CMD); + + retry: +#if defined(rw_bugfix) + /* Handle the read-before-write bug the same way as the + Crynwr packet driver -- the NatSemi method doesn't work. + Actually this doesn't aways work either, but if you have + problems with your NEx000 this is better than nothing! */ + outb_p(0x42, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(0x42, nic_base + EN0_RSARLO); + outb_p(0x00, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + /* Make certain that the dummy read has occured. */ + SLOW_DOWN_IO; + SLOW_DOWN_IO; + SLOW_DOWN_IO; +#endif /* rw_bugfix */ + + /* Now the normal output. */ + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(0x00, nic_base + EN0_RSARLO); + outb_p(start_page, nic_base + EN0_RSARHI); + + outb_p(E8390_RWRITE+E8390_START, EN_CMD); + if (ei_status.word16) { + port_write(NE_BASE + NE_DATAPORT, buf, count>>1); + } else { + port_write_b(NE_BASE + NE_DATAPORT, buf, count); + } + + /* This was for the ALPHA version only, but enough people have + encountering problems that it is still here. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int addr, tries = 10; + do { + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here + -- it's broken! Check the "DMA" address instead. */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + addr = (high << 8) + low; + if ((start_page << 8) + count == addr) + return; + } while (--tries > 0); + printk(EI_NAME": Packet buffer transfer address mismatch on TX, %#4.4x vs. %#4.4x.\n", + (start_page << 8) + count, addr); + if (retries++ == 0) + goto retry; + } + return; +} + +/* This function resets the ethercard if something screws up. */ +static void +ne_init_card(struct device *dev) +{ + NS8390_init(dev, 0); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/ether-995/wd.c b/net/tcpip/ether-995/wd.c new file mode 100644 index 00000000..b219c68c --- /dev/null +++ b/net/tcpip/ether-995/wd.c @@ -0,0 +1,334 @@ +/* wd.c: A WD80x3 ethernet driver for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This is a driver for the WD8003 and WD8013 ethercards. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + + Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013. +*/ + +static char *version = + "wd.c:v0.30 1/30/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int wdprobe(int ioaddr, struct device *dev); +int wdprobe1(int ioaddr, struct device *dev); + +static void wd_reset_8390(struct device *dev); +static int wd_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void wd_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static int wd_close_card(struct device *dev); + + +#define WD_START_PG 0x00 /* First page of TX buffer */ +#define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */ +#define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */ + +#define WD_CMDREG 0 /* Offset to ASIC command register. */ +#define WD_RESET 0x80 /* Board reset, in WD_CMDREG. */ +#define WD_MEMENB 0x40 /* Enable the shared memory. */ +#define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */ +#define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */ +#define NIC16 0x40 /* Enable 16 bit access from the 8390. */ +#define WD_NIC_OFFSET 16 /* Offset to the 8390 NIC from the base_addr. */ + +/* Probe for the WD8003 and WD8013. These cards have the station + address PROM at I/O ports +8 to +13, with a checksum + following. The routine also initializes the card and fills the + station address field. */ + +int wdprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x280, 0}; + + if (ioaddr > 0x100) + return wdprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb(*port) != 0xff && wdprobe1(*port, dev)) + return *port; + return 0; +} + +int wdprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + int checksum = 0; + int bits16 = 0; + +#if defined(EI_DEBUG) && EI_DEBUG > 2 + printk("WD80x3 ethercard at %#3x:", ioaddr); + for (i = 0; i < 16; i++) { + printk(" %2.2X", inb(ioaddr+i)); + } + printk("\n"); + printk("WD80x3 ethercard at %#3x:", ioaddr+i); + for (;i < 33; i++) { + printk(" %2.2X", inb(ioaddr+i)); + } + printk("\n"); +#endif + printk("WD80x3 ethercard probe at %#3x:", ioaddr); + for (i = 0; i < 8; i++) { + int inval = inb(ioaddr + 8 + i); + checksum += inval; + if (i < 6) + printk(" %2.2X", (station_addr[i] = inval)); + } + + if ((checksum & 0xff) != 0xFF) { + printk(" not found (%#2.2x).\n", checksum); + return 0; + } + + ei_status.name = "WD8003"; + ei_status.word16 = 0; + + /* This method of checking for a 16-bit board is borrowed from the + we.c driver. A simpler method is just to look in ASIC reg. 0x03. + I'm comparing the two method in alpha test to make certain they + return the same result. */ +#ifndef FORCE_8BIT /* Same define as we.c. */ + /* check for 16 bit board - it doesn't have register 0/8 aliasing */ + for (i = 0; i < 8; i++) { + int tmp; + if( inb(ioaddr+8+i) != inb(ioaddr+i) ){ + tmp = inb(ioaddr+1); /* fiddle with 16bit bit */ + outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */ + if ((tmp & 0x01) == (inb( ioaddr+1) & 0x01)) { + int asic_reg5 = inb(ioaddr+WD_CMDREG5); + bits16 = 1; /* use word mode of operation */ + /* Magic to set ASIC to word-wide mode. */ + outb( ISA16 | NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5); + outb(tmp, ioaddr+1); + ei_status.name = "WD8013"; + ei_status.word16 = 1; + break; /* We have a 16bit board here! */ + } + outb(tmp, ioaddr+1); + } + } +#else + bits8 = 1; +#endif /* FORCE_8BIT */ + +#ifndef final_version + if ((inb(ioaddr+1) & 0x01) != (ei_status.word16 & 0x01)) + printk("\nWD80x3: Bus width conflict, %d (probe) != %d (reg report).\n", + ei_status.word16 ? 16:8, (inb(ioaddr+1) & 0x01) ? 16 : 8); +#endif + +#if defined(WD_SHMEM) && WD_SHMEM > 0x80000 + /* Allow an override for alpha testing. */ + dev->mem_start = WD_SHMEM; +#else + if (dev->mem_start == 0) { + dev->mem_start = ((inb(ioaddr)&0x3f) << 13) + + (ei_status.word16 ? (inb(ioaddr+WD_CMDREG5)&0x1f)<<19 : 0x80000); + printk(" address %#x,", dev->mem_start); + } +#endif + + /* The 8390 isn't at the base address -- the ASIC regs are there! */ + dev->base_addr = ioaddr+WD_NIC_OFFSET; + + ei_status.tx_start_page = WD_START_PG; + ei_status.rx_start_page = WD_START_PG + TX_PAGES; + ei_status.stop_page = ei_status.word16 ? WD13_STOP_PG : WD03_STOP_PG; + + dev->rmem_start = dev->mem_start + TX_PAGES*256; + dev->mem_end = dev->rmem_end + = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256; +#if defined(EI_DEBUG) && EI_DEBUG > 3 + memset((void*)dev->mem_start, 0x42052465, + (ei_status.stop_page - WD_START_PG)*256); +#endif + if (dev->irq < 2) { + int irqmap[] = {9,3,5,7,10,11,15,4}; + dev->irq = irqmap[((inb(ioaddr+4) >> 5) & 0x03) + + (inb(ioaddr+1) & 0x04)]; + } else if (dev->irq == 2) + /* Fixup for users that don't know that IRQ 2 is really IRQ 9, + or don't know which one to set. */ + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + { int irqval = irqaction (dev->irq, &ei_sigaction); + if (irqval) { + printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); + return 0; + } + } + + printk(" %s found, using IRQ %d.\n", ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + + if (ei_debug > 2) + printk("%s: Address read from register is %#x, setting address %#x\n", + ei_status.name, + ((inb(ioaddr+WD_CMDREG5)&0x1f)<<19) + ((inb(ioaddr)&0x3f) << 13), + dev->mem_start); + /* Map in the shared memory. This is a little risky, since using + the stuff the user supplied is probably a bad idea. */ + outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), ioaddr); /* WD_CMDREG */ + if (ei_status.word16) + outb( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), ioaddr+WD_CMDREG5); + + ei_status.reset_8390 = &wd_reset_8390; + ei_status.block_input = &wd_block_input; + ei_status.block_output = &wd_block_output; + dev->stop = &wd_close_card; + NS8390_init(dev, 0); + + return dev->base_addr; +} + +static void +wd_reset_8390(struct device *dev) +{ + int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + int reset_start_time = jiffies; + + outb(WD_RESET, wd_cmd_port); + if (ei_debug > 1) printk("resetting the WD80x3 t=%d...", jiffies); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + break; + } + } + + outb(0x00, wd_cmd_port); + while ((inb(dev->base_addr+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk(EI_NAME": wd_reset_8390() did not complete.\n"); + break; + } +#if defined(EI_DEBUG) && EI_DEBUG > 2 + { + int i; + printk("WD80x3 ethercard at %#3x:", wd_cmd_port); + for (i = 0; i < 16; i++) { + printk(" %2.2X", inb(wd_cmd_port+i)); + } + printk("\nWD80x3 ethercard at %#3x:", wd_cmd_port); + for (;i < 33; i++) { + printk(" %2.2X", inb(wd_cmd_port+i)); + } + printk("\n"); + } +#endif + /* Set up the ASIC registers, just in case something changed them. */ + outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port); /* WD_CMDREG */ + if (ei_status.word16) + outb( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5); + +} + +/* Block input and output are easy on shared memory ethercards, and trivial + on the Western digital card where there is no choice of how to do it. */ + +static int +wd_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + void *xfer_start = (void *)(dev->mem_start + ring_offset - (WD_START_PG<<8)); +#ifdef mapout + int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + int mem_val = inb(wd_cmdreg); + /* Map in the shared memory. */ + outb(mem_val|WD_MEMENB, wd_cmdreg); +#endif + if (xfer_start + count > (void*) dev->rmem_end) { + /* We must wrap the input move. */ + int semi_count = (void*)dev->rmem_end - xfer_start; + memcpy(buf, xfer_start, semi_count); + count -= semi_count; + memcpy(buf + semi_count, (char *)dev->rmem_start, count); + return dev->rmem_start + count; + } + memcpy(buf, xfer_start, count); + if (ei_debug > 4) { + unsigned short *board = xfer_start; + printk("wd8013: wd_block_input(cnt=%d offset=%3x addr=%#x) = %2x %2x %2x...\n", + count, ring_offset, xfer_start, board[-1], board[0], board[1]); + } +#ifdef mapout + outb(mem_val & ~WD_MEMENB, wd_cmdreg); /* WD_CMDREG: Map out the shared memory. */ +#endif + return ring_offset + count; +} + +/* This could only be outputting to the transmit buffer. The + ping-pong transmit setup doesn't work with this yet. */ +static void +wd_block_output(struct device *dev, int count, const unsigned char *buf, int start_page) +{ + unsigned char *shmem = (void *)dev->mem_start + ((start_page - WD_START_PG)<<8); +#ifdef mapout + int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + int mem_val = inb(wd_cmdreg); + /* Map in the shared memory. */ + outb(mem_val|WD_MEMENB, wd_cmdreg); +#endif + memcpy(shmem, buf, count); + if (ei_debug > 4) + printk("wd8013: wd_block_output(addr=%#x cnt=%d) -> %2x=%2x %2x=%2x %d...\n", + shmem, count, shmem[23], buf[23], shmem[24], buf[24], memcmp(shmem,buf,count)); +#ifdef mapout + outb(mem_val & ~WD_MEMENB, wd_cmdreg); /* WD_CMDREG: Map out the shared memory. */ +#endif +} + +/* This function resets the ethercard if something screws up. */ +static int +wd_close_card(struct device *dev) +{ + if (ei_debug > 1) + printk("%s: shutting down ethercard.\n", ei_status.name); + NS8390_init(dev, 0); + /* Turn off the shared memory. */ + outb((((dev->mem_start>>13) & 0x3f)), + dev->base_addr-WD_NIC_OFFSET); /* WD_CMDREG */ + return 0; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c wd.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/ftp-rl.taz b/net/tcpip/ftp-rl.taz new file mode 100644 index 00000000..1374a10a Binary files /dev/null and b/net/tcpip/ftp-rl.taz differ diff --git a/net/tcpip/ftpd-dik.taz b/net/tcpip/ftpd-dik.taz new file mode 100644 index 00000000..1d7b02de Binary files /dev/null and b/net/tcpip/ftpd-dik.taz differ diff --git a/net/tcpip/ne2000/111.source b/net/tcpip/ne2000/111.source new file mode 100644 index 00000000..2c408952 --- /dev/null +++ b/net/tcpip/ne2000/111.source @@ -0,0 +1 @@ +stammt von super.org:/pub/linux diff --git a/net/tcpip/ne2000/3c501.c b/net/tcpip/ne2000/3c501.c new file mode 100644 index 00000000..0b378d81 --- /dev/null +++ b/net/tcpip/ne2000/3c501.c @@ -0,0 +1,368 @@ +/* 3c501.c: A 3Com 3c501 ethernet driver for linux. */ +#include +#ifdef ETHERLINK1 +/* + Copyright (C) 1992 Donald Becker + + This is alpha test code. No general redistribution is permitted. + This is a device driver for the 3Com Etherlink 3c501. + Do not purchase this card, even as a joke. It's performance is horrible, + and it breaks in many ways. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +/* + Braindamage remaining: + The 3c501 board. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* This should be checked for necessity after testing. */ +#define REALLY_SLOW_IO +#include +#include +#include +#include + +#include "dev.h" +#include "eth.h" +#include "timer.h" +#include "ip.h" +#include "tcp.h" +#include "sock.h" +#include "arp.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ + +#define port_read_b(port,buf,nr) \ +__asm__("cld;rep;insb"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write_b(port,buf,nr) \ +__asm__("cld;rep;outsb"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define DEBUG 10 /* use 0 for production, 1 for devel., >2 for debug */ + + +/* Index to functions. */ +static void el_interrupt(int reg_ptr); +static void el_send_packet(struct sk_buff *skb, struct device *dev); +static void el_receive(struct device *dev); + +#define EL_NAME "EtherLink 3c501" + +static int el_debug = DEBUG; /* Anything above 5 is wordy death! */ +static int el_base; +static struct device *eldev; /* Only for consistency checking. */ + +/* We could put everything in a struct to be malloc()ed per-board, but + who would want more than one 3c501?. */ +static struct { /* This should be stored per-board */ + char *name; + int exists:1; /* perhaps in dev->private. */ + int open:1; + int txing:1; /* Transmit Active, don't confuse the 8390 */ + int in_interrupt:4; + int overruns, rx_errors, tx_errors; +} el_status = { "Etherlink I", 0, 0, 0, 0, 0, 0, 0 }; + +static int collisions; /* Tx collisions this packet */ +static int tx_pkt_length; /* To reset GP after each collision. */ +static int runt_packets = 0; /* # of runt packets picked up so far. */ +/* static int rx_missed = 0; * # of packets we missed. */ + +static struct sigaction el_sigaction = { el_interrupt, 0, 0, NULL, }; + +#define RX_STATUS (el_base + 0x06) +#define TX_STATUS (el_base + 0x07) +#define GP_LOW (el_base + 0x08) +#define GP_HIGH (el_base + 0x09) +#define RX_LOW (el_base + 0x0A) +#define RX_HIGH (el_base + 0x0B) +#define SAPROM (el_base + 0x0C) +#define AX_STATUS (el_base + 0x0E) +#define DATAPORT (el_base + 0x0F) +#define TX_RDY 0x08 /* In TX_STATUS */ + +/* Writes to the ax command register. */ +#define AX_OFF 0x40 /* Irq off, buffer access on */ +#define AX_SYS 0x41 /* Load the buffer */ +#define AX_XMIT 0x45 /* Transmit a packet */ +#define AX_RX 0x49 /* Receive a packet */ +#define AX_LOOP 0x4D /* Loopback */ + +/* Normal receive mode written to RX_STATUS. We must intr on short packets + to avoid bogus rx lockups. */ +#define RX_NORM 0xA8 +/* TX_STATUS register. */ +#define TX_COLLISION 0x02 + +/* Open/initialize the board. */ +static int +el_open(struct device *dev) +{ + if ( ! el_status.exists) { + printk(EL_NAME ": Opening a non-existent physical device\n"); + return 1; /* We should have a better error return. */ + } + if (el_debug > 2) + printk(EL_NAME ": Doing el_open(%s)...", + dev == eldev ? dev->name : " on unknown dev"); + el_status.txing = 0; + el_status.in_interrupt = 0; + + + outb_p(AX_LOOP, AX_STATUS); /* Aux control, irq and loopback enabled */ + outb_p(0x00, RX_LOW); /* Set rx packet area to 0. */ + outb_p(RX_NORM, RX_STATUS); /* Set Rx commands. */ + outb_p(AX_RX, AX_STATUS); /* Aux control, irq and receive enabled */ + + el_status.open = 1; + if (el_debug > 2) + printk("finished el_open().\n"); + return (0); +} + +int +el_start_xmit(struct sk_buff *skb, struct device *dev) +{ + int axsr; + + if ( ! el_status.exists) + return 0; /* We should have a better error return. */ + if (el_debug > 2) + printk(EL_NAME": Doing el_start_xmit(,%s).\n", skb, + dev == eldev ? "EtherLink" : "unknown dev"); + cli(); + if (el_debug > 4) printk(EL_NAME": interrupts suspended..."); + axsr = inb_p(AX_STATUS); + if (el_status.txing || axsr & 0x01) { + if (jiffies - dev->trans_start < 30) { + sti(); + if (el_debug > 2) + printk(EL_NAME": transmit deferred, no timeout.\n"); + return 1; + } + printk (EL_NAME ": transmit timed out with tx status %#2x.\n", + inb(TX_STATUS)); + } + if (el_debug > 4) printk("doing sti()..."); + sti(); + if (el_debug > 4) printk("filling in hdr..."); + + /* This is new: it means some higher layer thinks we've missed an + tx-done interrupt. */ + if (skb == NULL) { + /* Alternative is ei_tx_intr(dev); */ + el_status.txing = 1; + if (dev_tint(NULL, dev) == 0) + el_status.txing = 0; + return 0; + } + /* Fill in the ethernet header. */ + if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + skb->dev = dev; + arp_queue (skb); + if (el_debug > 1) + printk(" Exiting from xmit_start() via rebuild header?\n"); + return 0; + } + dev->trans_start = jiffies; + el_status.txing = 1; + outb_p(0x0A, TX_STATUS); /* tx irq on done, collision */ + el_send_packet(skb, dev); + if (skb->free) + kfree_skb (skb, FREE_WRITE); + if (el_debug > 3) + printk(EL_NAME": Returning from el_start_xmit().\n"); + return 0; +} + +/* The typical workload of the driver: + Handle the ether interface interrupts. */ +static void +el_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + int axsr; /* Aux. status reg. */ + int txsr; /* Tx. status reg. */ + int rxsr; /* Rx. status reg. */ + + if (eldev->irq != irq) { + printk (EL_NAME ": irq %d for unknown device\n", irq); + return; + } + + el_status.in_interrupt++; + sti(); /* Turn interrupts back on. */ + axsr = inb_p(AX_STATUS); + txsr = inb_p(TX_STATUS); + rxsr = inb_p(RX_STATUS); + if (el_debug > 1) + printk(EL_NAME": in el_interrupt(), axsr=%#2x, txsr=%#2x, rxsr=%#2x.\n", + axsr, txsr, rxsr); + if (el_status.in_interrupt > 1) { + /* We should probably return here -- the 3c501 glitches the + interrupt line when you write to the rx or tx command register. */ + printk(EL_NAME ": Reentering the interrupt driver!\n"); + } + if (rxsr & 0x08) + runt_packets++; /* Just reading rxstatus fixes this. */ + else if (rxsr & 0x20) + el_receive(eldev); + else if (txsr & TX_COLLISION) { + if (++collisions > 16) { + printk(EL_NAME": Transmit failed 16 times, ethernet jammed?\n"); + /* Turn receiving back on. */ + el_status.txing = 0; + outb_p(0x00, RX_LOW); + outb_p(AX_RX, AX_STATUS); + } else { /* Retrigger xmit. */ + int gp_start = 0x800 - tx_pkt_length; + outb_p(gp_start, GP_LOW); + outb_p(gp_start>>8, GP_HIGH); + outb_p(AX_XMIT, AX_STATUS); + } + } else if (txsr & TX_RDY) { + if (dev_tint(NULL, eldev) == 0) + el_status.txing = 0; /* We could turn off the tx... */ + } + el_status.in_interrupt--; + return; +} + +/* This is stuffed into the dev struct to be called by dev.c:dev_tint(). */ +static void +el_send_packet(struct sk_buff *skb, struct device *dev) +{ + tx_pkt_length = skb->len; + collisions = 0; + if (el_debug > 3) printk(" el_send_packet(%d)...", tx_pkt_length); + /* Should we check for tiny (or huge) lengths here? */ + if (tx_pkt_length) { + int gp_start = 0x800 - tx_pkt_length; + unsigned char *buf = (void *)(skb+1); + outb_p(AX_OFF, AX_STATUS); /* irq disabled, rx off */ + outb_p(gp_start, GP_LOW); + outb_p(gp_start>>8, GP_HIGH); + /* After testing use port_write(), defined above. */ + for (; gp_start < 0x800; gp_start++) + outb_p(*buf++, DATAPORT); + outb_p(AX_XMIT, AX_STATUS); /* Trigger xmit. */ + } +} + +/* We have a good packet; well, not really "good", just mostly not broken. + We must check everything to see if it is good. */ +static void +el_receive(struct device *dev) +{ + int state = 0, sksize, length; + struct sk_buff *skb; + + if (el_debug > 2) + printk("in el_receive..."); + /* Painfully read it out of the local memory. */ + outb_p(AX_SYS, AX_STATUS); + length = inb_p(RX_LOW) + (inb_p(RX_HIGH)<<8); + if ((length < 60 || length > 1535)) { + if (el_debug) + printk(EL_NAME": bogus packet, length=%d\n", length); + /* We should reset to receive... */ + return; + } + sksize = sizeof(struct sk_buff) + length; + skb = kmalloc(sksize, GFP_ATOMIC); + outb_p(0x00, GP_LOW); + outb_p(0x00, GP_HIGH); + if (skb != NULL) { + unsigned char *buf = (void *)(skb+1); + skb->mem_len = sksize; + skb->mem_addr = skb; + /* After testing use port_read(), defined above. */ + while (length-- > 0) + *buf++ = inb_p(DATAPORT); + state = dev_rint((void *)skb, length, IN_SKBUFF, dev); + } else if (el_debug) { + printk("Couldn't allocate a sk_buff of size %d.\n", sksize); + } + dev_rint(NULL, 0,0, dev); /* Inform upper level */ + if (el_debug > 2) + printk("done.\n"); + return; +} + +void +etherlink_init(struct device *dev) +{ + int i; + + eldev = dev; /* Store for debugging. */ + el_base = dev->base_addr; + + printk("3c501 probe at %#3.3x: ", el_base); + outb(0x00, GP_HIGH); + for (i = 0; i < 6; i++) { + outb(i, GP_LOW); /* Set station address prom addr */ + dev->dev_addr[i] = inb(SAPROM); /* Read Station address prom */ + printk(" %2.2x", dev->dev_addr[i]); + } + /* Check the first three octets of the S.A. for 3Com's code. */ + if (dev->dev_addr[0] != 0x02 || dev->dev_addr[1] != 0x60 + || dev->dev_addr[2] != 0x8c) { + printk(" Etherlink not found.\n", dev->base_addr); + el_status.exists = 0; + return; + } + el_status.exists = 1; + printk(" Etherlink found.\n"); + + /* Initialize the rest of the device structure. Most of these should + be in Space.c. */ + for (i = 0; i < DEV_NUMBUFFS; i++) + dev->buffs[i] = NULL; + + dev->hard_header = eth_hard_header; + dev->add_arp = eth_add_arp; + dev->queue_xmit = dev_queue_xmit; + dev->rebuild_header = eth_rebuild_header; + dev->type_trans = eth_type_trans; + + dev->send_packet = &el_send_packet; + dev->open = &el_open; + dev->hard_start_xmit = &el_start_xmit; + + dev->type = ETHER_TYPE; + dev->hard_header_len = sizeof (struct enet_header); + dev->mtu = 1500; /* eth_mtu */ + dev->addr_len = ETHER_ADDR_LEN; + for (i = 0; i < dev->addr_len; i++) { + dev->broadcast[i]=0xff; + } + /* Turn off interrupts. */ + + /* Snarf the assigned interrupt. */ + { int irqval = irqaction (dev->irq, &el_sigaction); + if (irqval) { + printk (" unable to get IRQ%d, error=%d.\n", dev->irq, irqval); + return; /* Return failure someday */ + } + } + outb(0x8C, 0x0e); /* setup Aux. control reg. */ + return; +} +#endif /* ETHERLINK1 */ + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -DMAX_16M -I/usr/linux-master/net/tcp -c -o 3c501.o 3c501.c" + * End: + */ diff --git a/net/tcpip/ne2000/3c503.c b/net/tcpip/ne2000/3c503.c new file mode 100644 index 00000000..311c357e --- /dev/null +++ b/net/tcpip/ne2000/3c503.c @@ -0,0 +1,1053 @@ +/* 3c503.c: A general NS8390 ethernet driver for linux. */ +/* + Copyright (C) 1992 Donald Becker + + This is alpha test code. No general redistribution is permitted. + This driver should work with the 3Com Etherlink II 3c503 and + (hardwiring the ne2000 variable) the NE1000, NE2000, and NE2000 clones. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ +#include +#ifdef EI8390 +/* + Braindamage remaining: + + I mostly do full dispatching on cards now, but you might still have to edit + file until all of the probe code is working. Ideally you could have a + subset of the possible cards configured into the kernel and probed for + at boot time. + + We should be able to support multiple, diverse boards + simultaneousely. Pass us 'kmem' at boot time like the drivers in + chr_drv and I'll finish doing the minor bits to put all of the statics + into a structure allocated per-board. Mostly that means putting a few + global statics into an allocated struct, and doing a gensym to get a + new name "ei8390<0-9>". + + When everything is working right, I should make it possible to have a + compile-time configuration of a single ethercard type, and not include + the general code. + +Sources: + The National Semiconductor LAN Databook, and 3Com databooks, both companies + provided information readily. The NE* info came from the Clarkson packet + driver, and figuring out that the those boards are similar to the NatSemi + evaluation board described in AN-729. Thanks NS, no thanks to Novell; buy + a NE2000 _clone_ from someone beside Novell. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* If you are having flakey problems put this back in _before_ . */ +/* #define REALLY_SLOW_IO*/ +#include +#include +#include +#include + +#include "dev.h" +#include "eth.h" +#include "timer.h" +#include "ip.h" +#include "tcp.h" +#include "sock.h" +#include "arp.h" + +#include "3c503reg.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ + +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +static unsigned short inline inw( unsigned short port ) +{ unsigned short _v; + __asm__ volatile ("inw %1,%0" + :"=a" (_v):"d" ((unsigned short) port)); + return _v; +} +static void inline outw( unsigned short value, unsigned short port ) +{ __asm__ volatile ("outw %0,%1" ::"a" ((unsigned short) value), + "d" ((unsigned short) port)); +} + +#define EI_NAME "eth_if" +#define SM_TSTART_PG (ei_status.tx_start_page) +#define SM_RSTART_PG (ei_status.rx_start_page) +#define SM_RSTOP_PG (ei_status.stop_page) +#define ei_reset_8390 (ei_status.reset_8390) +#define ei_block_output (ei_status.block_output) +#define ei_block_input (ei_status.block_input) + +#define NEEI_NAME "NE2000" /* Unused for now. */ +/* These are for the ne1000 and are untested */ +#define NE1SM_TSTART_PG 0x20 /* First page of TX buffer */ +#define NE1SM_RSTART_PG 0x26 /* Starting page of RX ring */ +#define NE1SM_RSTOP_PG 0x40 /* Last page +1 of RX ring */ +#define NESM_TSTART_PG 0x40 /* First page of TX buffer */ +#define NESM_RSTART_PG 0x46 /* Starting page of RX ring */ +#define NESM_RSTOP_PG 0x80 /* Last page +1 of RX ring */ + +#define EL2EI_NAME "3c503" /* Unused for now. */ + +#define EN_CMD (e8390_base) +#define E8390_BASE (e8390_base) + +/* use 0 for production, 1 for devel., >2 for debug */ +#ifdef EI_DEBUG +static int ei_debug = EI_DEBUG; +#else +static int ei_debug = 2; +#endif + +static int e8390_base; + +static struct device *eifdev; /* Only for consistency checking. */ +static int etherlink2 = 0, ne2000 = 0, ne1000 = 0; + +static struct { /* These should be stored per-board */ + char *name; + int exists:1; /* perhaps in dev->private. */ + int open:1; + int txing:1; /* Transmit Active, don't confuse the 8390 */ + int word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */ + int in_interrupt; + int overruns; /* Rx overruns. */ + void (*reset_8390)(struct device *); + void (*block_output)(struct device *, int, const unsigned char *); + int (*block_input)(struct device *, int, char *, int); + int tx_start_page, rx_start_page, stop_page; + int current_page; /* Read pointer in buffer */ + int thin_bit; /* Value to write to the 3c503 E33G_CNTRL */ +} ei_status = { "eth_if", 0, 0, 0, 0, 0, 0, + NULL, NULL, NULL, 0, 0, 0, 0, ECNTRL_THIN}; +/* The statistics, perhaps these should be in the above structure. */ +static int tx_packets = 0; +static int rx_packets = 0; +static int tx_errors = 0; +static int soft_rx_errors = 0; +static int soft_rx_err_bits = 0; + +/* Index to functions. */ +/* Put in the device structure. */ +static int ei_open(struct device *dev); +static void ei_send_packet(struct sk_buff *skb, struct device *dev); +/* Dispatch from interrupts. */ +static void ei_interrupt(int reg_ptr); +static void ei_tx_intr(struct device *dev); +static void ei_receive(struct device *dev); +static void ei_rx_overrun(struct device *dev); + +/* Routines generic to NS8390-based boards. */ +static void NS8390_init(struct device *dev); +static void NS8390_start(); +static void NS8390_trigger_send(unsigned int length); + +static int el2probe(int ioaddr, unsigned char station_addr[ETHER_ADDR_LEN]); +static void el2_reset_8390(struct device *dev); +static void el2_init_card(struct device *dev); +static void el2_block_output(struct device *dev, int count, + const unsigned char *buf); +static int el2_block_input(struct device *dev, int count, char *buf, + int ring_offset); + +static int neprobe(int ioaddr, unsigned char station_addr[ETHER_ADDR_LEN]); +static void ne_reset_8390(struct device *dev); +static int ne_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void ne_block_output(struct device *dev, int count, + const unsigned char *buf); +static void ne_init_card(struct device *dev); + +static struct sigaction ei_sigaction = { ei_interrupt, 0, 0, NULL, }; + +/* Open/initialize the board. This routine goes all-out, setting everything + up anew at each open, even though many of these registers should only + need to be set once at boot. + */ +static int +ei_open(struct device *dev) +{ + if ( ! ei_status.exists) { + printk(EI_NAME ": Opening a non-existent physical device\n"); + return 1; /* We should have a better error return. */ + } + if (etherlink2) { + outb_p(ei_status.thin_bit, E33G_CNTRL); + } else { + ei_reset_8390(dev); + } + + NS8390_init(dev); + + if (etherlink2) { + /* Set ASIC copy of rx's first and last+1 buffer pages */ + /* This must be the same as in the 8390. */ + outb_p(EL2SM_RSTART_PG+1, E33G_STARTPG); + outb_p(EL2SM_RSTOP_PG, E33G_STOPPG); + } + + NS8390_start(); + + ei_status.txing = 0; + ei_status.in_interrupt = 0; + ei_status.open = 1; + if (etherlink2) + outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM (redundent?) */ + return (0); +} + +int +ei_start_xmit(struct sk_buff *skb, struct device *dev) +{ + if ( ! ei_status.exists) + return 0; /* We should have a better error return. */ + + cli(); + if (ei_status.txing) { /* Follow the 8003 driver and do timeouts. */ + if (jiffies - dev->trans_start < 30) { + sti(); + return 1; + } + printk (EI_NAME ": transmit timed out with tx status %#2x.\n", + inb(E8390_BASE+EN0_TSR)); + ei_reset_8390(dev); + } + sti(); + + /* This is new: it means some higher layer thinks we've missed an + tx-done interrupt. */ + if (skb == NULL) { + /* Alternative is ei_tx_intr(dev); */ + ei_status.txing = 1; + if (dev_tint(NULL, dev) == 0) + ei_status.txing = 0; + return 0; + } + /* Fill in the ethernet header. */ + if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + skb->dev = dev; + arp_queue (skb); + return 0; + } + + dev->trans_start = jiffies; + ei_status.txing = 1; + ei_send_packet(skb, dev); + if (skb->free) +#ifdef notdef /* 0.98.5 and beyond use kfree_skb(). */ + free_skb (skb, FREE_WRITE); +#else + kfree_skb (skb, FREE_WRITE); +#endif + return 0; +} + +/* The typical workload of the driver: + Handle the ether interface interrupts. */ +static void +ei_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev; + int interrupts, boguscount = 0; + + /* We do the same thing as the 8013 driver, but this is mostly bogus. */ + for (dev = dev_base; dev != NULL; dev = dev->next) { + if (dev->irq == irq) break; + } + ei_status.in_interrupt++; + sti(); /* Allow other interrupts. */ + + /* If we a getting a reset-complete interrupt the 8390 might not be + mapped in for the 3c503. */ + if (etherlink2) + outb_p(ei_status.thin_bit, E33G_CNTRL), outb_p(0x00, E33G_STATUS); + + /* Change to page 0 and read the intr status reg. */ + outb_p(E8390_NODMA+E8390_PAGE0, EN_CMD); + + if (ei_status.in_interrupt > 1) + printk(EI_NAME ": Reentering the interrupt driver!\n"); + if (dev == NULL) { + printk (EI_NAME ": irq %d for unknown device\n", irq); + ei_status.in_interrupt--; + return; + } + /* !!Assumption!! -- we stay in page 0. Don't break this. */ + while ((interrupts = inb_p(E8390_BASE + EN0_ISR)) != 0 + && ++boguscount < 20) { + /* The reset interrupt is the most important... */ + if (interrupts & ENISR_RDC) { + outb_p(ENISR_RDC, E8390_BASE + EN0_ISR); /* Ack intr. */ + } + if (interrupts & ENISR_OVER) { + ei_status.overruns++; + ei_rx_overrun(dev); + } else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) { + /* Got a good (?) packet. */ + ei_receive(dev); + } + /* Push the next to-transmit packet through. */ + if (interrupts & ENISR_TX) { + ei_tx_intr(dev); + } else if (interrupts & ENISR_COUNTERS) { + /* Gotta read the counter to clear the irq, even if we + don't care about their values. */ + inb_p(E8390_BASE + EN0_COUNTER0); + inb_p(E8390_BASE + EN0_COUNTER1); + inb_p(E8390_BASE + EN0_COUNTER2); + outb_p(ENISR_COUNTERS, E8390_BASE + EN0_ISR); /* Ack intr. */ + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + } + + /* Ignore the transmit errs and reset intr for now. */ + if (interrupts & ENISR_TX_ERR) { + outb_p(ENISR_TX_ERR, E8390_BASE + EN0_ISR); /* Ack intr. */ + } + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + } + + if (interrupts && ei_debug) { + printk(EI_NAME ": unknown interrupt %#2x\n", interrupts); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, EN_CMD); + outb_p(0xff, E8390_BASE + EN0_ISR); /* Ack. all intrs. */ + } + ei_status.in_interrupt--; + return; +} + +/* This is stuffed into the dev struct to be called by dev.c:dev_tint(). */ +static void +ei_send_packet(struct sk_buff *skb, struct device *dev) +{ + int length = skb->len; + + if (length) { + if (etherlink2) + outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM (redundent?) */ + ei_block_output(dev, length, (void*)(skb+1)); + NS8390_trigger_send(ETHER_MIN_LEN < length ? length : ETHER_MIN_LEN); + tx_packets++; + } +} + +/* We have finished a transmit: check for errors and then put the next + packet in the tx buffer. */ +static void +ei_tx_intr(struct device *dev) +{ + int status = inb(E8390_BASE + EN0_TSR); + outb_p(ENISR_TX, E8390_BASE + EN0_ISR); /* Ack intr. */ + if (status & ENTSR_PTX) { + if (dev_tint(NULL, dev) == 0) + ei_status.txing = 0; + } else { /* Bogus! Transmit error */ + tx_errors++; + } +} + +/* We have a good packet(s), get it/them out of the buffers. */ + +static void +ei_receive(struct device *dev) +{ + int rxing_page, this_frame, next_frame, current_offset; + int boguscount = 0; + struct e8390_pkt_hdr rx_frame; + int state = 2; + int num_rx_pages = ei_status.stop_page-ei_status.rx_start_page; + + while (state != 1 && ++boguscount < 10) { + int size; + + cli(); + outb_p(E8390_NODMA+E8390_PAGE1, EN_CMD); /* Get the rec. page. */ + rxing_page = inb_p(E8390_BASE+EN1_CURPAG);/* (Incoming packet pointer).*/ + outb_p(E8390_NODMA+E8390_PAGE0, EN_CMD); + sti(); + + /* Remove one frame from the ring. Boundary is alway a page behind. */ + this_frame = inb_p(E8390_BASE + EN0_BOUNDARY) + 1; + if (this_frame >= ei_status.stop_page) + this_frame = ei_status.rx_start_page; + + /* Someday we'll omit the previous step, iff we never get this message.*/ + if (ei_debug > 0 && this_frame != ei_status.current_page) + printk(EI_NAME": mismatched read page pointers %2x vs %2x.\n", + this_frame, ei_status.current_page); + + if (this_frame == rxing_page) /* Read all the frames? */ + break; /* Done for now */ + + current_offset = this_frame << 8; + ei_block_input(dev, sizeof(rx_frame), (void *)&rx_frame, + current_offset); + + size = rx_frame.count - sizeof(rx_frame); + + next_frame = this_frame + 1 + ((size+4)>>8); + + /* Check for bogosity warned by 3c503 book: the status byte is never + written. This happened a lot during testing! This code should be + cleaned up someday, and the printk()s should be PRINTK()s. */ + if ( rx_frame.next != next_frame + && rx_frame.next != next_frame + 1 + && rx_frame.next != next_frame - num_rx_pages + && rx_frame.next != next_frame + 1 - num_rx_pages) { + + static int last_rx_bogosity = -1; + + printk(EI_NAME": bogus packet header, status=%#2x nxpg=%#2x sz=%#x (at %#2x)\n", + rx_frame.status, rx_frame.next, rx_frame.count, this_frame); + + if (rx_packets != last_rx_bogosity + && ei_status.rx_start_page <= rx_frame.status + && rx_frame.status < ei_status.stop_page) { + /* Maybe we can continue without stopping... */ + ei_status.current_page = rx_frame.status; + printk(EI_NAME": setting next frame to %#2x (nxt=%#2x, rx_frm.nx=%#2x rx_frm.stat=%#2x).\n", + ei_status.current_page, next_frame, + rx_frame.next, rx_frame.status); + last_rx_bogosity = rx_packets; + outb(ei_status.current_page-1, E8390_BASE+EN0_BOUNDARY); + state = 0; + continue; + } else { + /* Oh no Mr Bill! Last ditch error recovery. */ + printk(EI_NAME": multiple sequential lossage, resetting at #%d..", + rx_packets); + ei_reset_8390(dev); + NS8390_init(dev); + NS8390_start(dev); + printk("restarting.\n"); + return; + } + } + + if ((size < 32 || size > 1535) && ei_debug) + printk(EI_NAME": bogus big packet, status=%#2x nxpg=%#2x size=%#x\n", + rx_frame.status, rx_frame.next, rx_frame.count); + if ((rx_frame.status & 0x0F) == ENRSR_RXOK) { + int sksize = sizeof(struct sk_buff) + size; + struct sk_buff *skb; + skb = kmalloc(sksize, GFP_ATOMIC); + if (skb != NULL) { + skb->mem_len = sksize; + skb->mem_addr = skb; + /* 'skb+1' points to the start of sk_buff data area. */ + ei_block_input(dev, size, (void *)(skb+1), + current_offset + sizeof(rx_frame)); + state = dev_rint((void *)skb, size, IN_SKBUFF, dev); + } else if (ei_debug) { + printk("Couldn't allocate a sk_buff of size %d.\n", sksize); + state = 0; + break; + } + if (state < 0) continue; /* Redo packet, dev_rint() screwed up */ + rx_packets++; + } else { + if (ei_debug) + printk(EI_NAME": bogus packet, status=%#2x nxpg=%#2x size=%d\n", + rx_frame.status, rx_frame.next, rx_frame.count); + soft_rx_err_bits |= rx_frame.status, + soft_rx_errors++; + state = 0; + } + next_frame = rx_frame.next; + + /* This should never happen, it's here for debugging. */ + if (next_frame >= ei_status.stop_page) { + printk(EI_NAME": next frame inconsistency, %#2x..", next_frame); + next_frame = ei_status.rx_start_page; + } + ei_status.current_page += 1 + ((size+4)>>8); +#ifdef notdef + if (ei_status.current_page > ei_status.stop_page) + ei_status.current_page -= ei_status.stop_page-ei_status.rx_start_page; + if (ei_status.current_page != next_frame) { + printk(EI_NAME": inconsistency in next_frame %#2x!=%#2x.\n", + this_frame, next_frame); + /* Assume this packet frame is scrogged by the NIC, use magic to + skip to the next frame. Actually we should stop and restart.*/ + next_frame = size > 1535 ? rx_frame.status : rx_frame.next; + ei_status.current_page = next_frame; + break; + } +#endif + + ei_status.current_page = next_frame; + outb(next_frame-1, E8390_BASE+EN0_BOUNDARY); + } + + /* Tell the upper levels we're done. */ + while (state != 1 && ++boguscount < 20) + state = dev_rint(NULL, 0, 0, dev); + outb_p(ENISR_RX+ENISR_RX_ERR, E8390_BASE+EN0_ISR); /* Ack intr. */ + return; +} + +/* We have a receiver overrun: we have to kick the 8390 to get it started + again. Overruns are detected on a per-256byte-page basis. */ +static void +ei_rx_overrun(struct device *dev) +{ + int boguscount = 0; + printk (EI_NAME ": receiver overrun\n"); + /* We should already be stopped and in page0. Remove after testing. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, EN_CMD); + +#ifdef notdef + /* The we.c driver does this. Is it to speed up a reset? */ + { unsigned char dummy; + dummy = inb_p( RBCR0 ); + dummy = inb_p( RBCR1 ); + } +#endif + + /* Acknowledge the RX Interrupt. Maybe we should also do RXOVERRUN? */ + if (inb_p(E8390_BASE+EN0_ISR) & ENISR_RX ) + outb_p(ENISR_RX, E8390_BASE+EN0_ISR); + + /* Wait for reset in case the NIX is doing a tx or rx. */ + while ((inb_p(E8390_BASE+EN0_ISR) & ENISR_RESET) == 0 ) + if (++boguscount > 150000) { + printk(EI_NAME": reset did not complete at ei_rx_overrun.\n"); + NS8390_init(dev); + return; + }; + /* We should clear out at least one received packet here. */ + + outb_p(ENISR_RESET, E8390_BASE+EN0_ISR); /* Ack Reset Intr. */ + /* Generic 8390 insns to start up again, same as in open_8390(). */ + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + outb_p(E8390_TXCONFIG, E8390_BASE + EN0_TXCR); /* xmit on. */ + outb_p(E8390_RXCONFIG, E8390_BASE + EN0_RXCR); /* rx on, */ +} + +void +ethif_init(struct device *dev) +{ + int i; + + eifdev = dev; /* Store for debugging. */ + e8390_base = dev->base_addr; + + + if (el2probe(dev->base_addr, dev->dev_addr)) { + ei_status.exists = 1; + etherlink2 = 1; + ei_status.tx_start_page = EL2SM_TSTART_PG; + ei_status.rx_start_page = EL2SM_RSTART_PG; + ei_status.stop_page = EL2SM_RSTOP_PG; + ei_status.reset_8390 = &el2_reset_8390; + ei_status.block_input = &el2_block_input; + ei_status.block_output = &el2_block_output; + el2_init_card(dev); + } else if (neprobe(dev->base_addr, dev->dev_addr)) { + ei_status.exists = 1; + if (ne1000) { + ne2000 = 0; + ei_status.word16 = 0; + ei_status.tx_start_page = NE1SM_TSTART_PG; + ei_status.rx_start_page = NE1SM_RSTART_PG; + ei_status.stop_page = NE1SM_RSTOP_PG; + } else { + ne2000 = 1; + ei_status.word16 = 1; + ei_status.tx_start_page = NESM_TSTART_PG; + ei_status.rx_start_page = NESM_RSTART_PG; + ei_status.stop_page = NESM_RSTOP_PG; + } + ei_status.reset_8390 = &ne_reset_8390; + ei_status.block_input = &ne_block_input; + ei_status.block_output = &ne_block_output; + ne_init_card(dev); + } else { + /* What should I do here? Erase dev->open? That crashes the kernel. */ + dev->open = &ei_open; + printk("No ethernet device found found.\n"); + return; + } + + /* Initialize the rest of the device structure. Most of these should + be in Space.c. */ + for (i = 0; i < DEV_NUMBUFFS; i++) + dev->buffs[i] = NULL; + + dev->hard_header = eth_hard_header; + dev->add_arp = eth_add_arp; + dev->queue_xmit = dev_queue_xmit; + dev->rebuild_header = eth_rebuild_header; + dev->type_trans = eth_type_trans; + + dev->send_packet = &ei_send_packet; + dev->open = &ei_open; + dev->hard_start_xmit = &ei_start_xmit; + + dev->type = ETHER_TYPE; + dev->hard_header_len = sizeof (struct enet_header); + dev->mtu = 1500; /* eth_mtu */ + dev->addr_len = ETHER_ADDR_LEN; + for (i = 0; i < dev->addr_len; i++) { + dev->broadcast[i]=0xff; + } + return; +} + + + +/* This page of functions should be 8390 generic */ +/* Follow National Semi's recommendations for initializing the "NIC". */ +static void NS8390_init(struct device *dev) +{ + int i; + int endcfg = ei_status.word16 ? (0x48 | ENDCFG_WTS) : 0x48; + + /* Follow National Semi's recommendations for initing the DP83902. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, EN_CMD); /* 0x21 */ + outb_p(endcfg, E8390_BASE + EN0_DCFG); /* 0x48 or 0x49 */ + /* Clear the remote byte count registers. */ + outb_p(0x00, E8390_BASE + EN0_RCNTLO); + outb_p(0x00, E8390_BASE + EN0_RCNTHI); + /* Set to monitor and loopback mode -- this is vital!. */ + outb_p(E8390_RXOFF, E8390_BASE + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, E8390_BASE + EN0_TXCR); /* 0x02 */ + /* Set the transmit page and receive ring. */ + outb_p(SM_TSTART_PG, E8390_BASE + EN0_TPSR); + outb_p(SM_RSTART_PG, E8390_BASE + EN0_STARTPG); + outb_p(SM_RSTOP_PG-1, E8390_BASE + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ + ei_status.current_page = SM_RSTART_PG; /* assert boundary+1 */ + outb_p(SM_RSTOP_PG, E8390_BASE + EN0_STOPPG); + /* Clear the pending interrupts and mask. */ + outb_p(0xFF, E8390_BASE + EN0_ISR); + outb_p(0x00, E8390_BASE + EN0_IMR); + + /* Copy the station address into the DS8390 registers, + and set the multicast hash bitmap to receive all multicasts. */ + outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, EN_CMD); /* 0x61 */ + for(i = 0; i < 6; i++) { + outb_p(dev->dev_addr[i], E8390_BASE + EN1_PHYS + i); + } + for(i = 0; i < 8; i++) + outb_p(0xff, E8390_BASE + EN1_MULT + i); + + outb_p(SM_RSTART_PG, E8390_BASE + EN1_CURPAG); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, EN_CMD); + return; +} +/* Start the NIC: 8390 insns to turn on the xmit, rx, and irqs. */ +static void +NS8390_start() +{ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, EN_CMD); + outb_p(0xff, E8390_BASE + EN0_ISR); + outb_p(ENISR_ALL, E8390_BASE + EN0_IMR); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, EN_CMD); + outb_p(E8390_TXCONFIG, E8390_BASE + EN0_TXCR); /* xmit on. */ + /* 3c503 TechMan says this should only be done after the NIC is started. */ + outb_p(E8390_RXCONFIG, E8390_BASE + EN0_RXCR); /* rx on, */ + return; +} + +/* Trigger a transmit start, assuming the length is valid. */ +static void NS8390_trigger_send(unsigned int length) +{ + struct device *dev = eifdev; + /* Set everything up again, just to be certain. */ + if (etherlink2) + outb_p(0x00, E33G_CNTRL); + outb_p(E8390_NODMA+E8390_PAGE0, EN_CMD); + + if (inb_p(EN_CMD) & E8390_TRANS) { + printk(EI_NAME": NS8390_send_packet() called with the transmitter still busy.\n"); + /* This might be a good place to bump a counter and recover. */ + return; + } + cli(); + outb_p(length & 0xff, E8390_BASE + EN0_TCNTLO); + outb_p(length >> 8, E8390_BASE + EN0_TCNTHI); + outb_p(SM_TSTART_PG, E8390_BASE + EN0_TPSR); + outb_p(E8390_NODMA+E8390_TRANS+E8390_START, EN_CMD); + outb_p(ENISR_RDC, E8390_BASE + EN0_ISR); + sti(); + return; +} + +/* Probe for the Etherlink II card at I/O port base IOADDR, + returning non-zero on sucess. */ +static int +el2probe(int ioaddr, unsigned char station_addr[ETHER_ADDR_LEN]) +{ + int i, found; + + /* We check for a 3C503 board by checking the first three octets + of its ethernet address. */ + printk("3c503 probe at %#3x:", ioaddr); + outb_p(ECNTRL_RESET, ioaddr + 0x406); /* Reset it... */ + outb_p(0, ioaddr + 0x406); + /* Map the station addr PROM into the lower I/O ports. */ + outb(ECNTRL_SAPROM, ioaddr + 0x406); + for (i = 0; i < ETHER_ADDR_LEN; i++) { + printk(" %2.2X", (station_addr[i] = inb(ioaddr + i))); + } + /* Map the 8390 back into the window. */ + outb(0, ioaddr + 0x406); + found =( station_addr[0] == 0x02 + && station_addr[1] == 0x60 + && station_addr[2] == 0x8c); + printk(" 3C503 %sfound.\n", found ? "":"not "); + return found; +} + +/* These functions are somewhat Clarkson packet driver-like. */ +/* Right now this is only called when we have a transmit timeout. */ +static void +el2_reset_8390(struct device *dev) +{ + /* Reset the board. */ + outb_p(ECNTRL_RESET | ei_status.thin_bit, E33G_CNTRL); + outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and irqs */ + outb_p(ei_status.thin_bit, E33G_CNTRL); + ei_status.txing = 0; + /* Doing a 'NS8390_init(dev)' here wouldn't hurt... */ + } + +/* Initialize the card and fill in STATION_ADDR with the station address. + The 3c503 maps the SA PROM into its lower I/O port bank. */ +static void +el2_init_card(struct device *dev) +{ + int i, mem_jumpers; + int pirq; + + /* Unmap the station PROM and turn on the thinnet connector. */ + outb(ei_status.thin_bit, E33G_CNTRL); + /* Point the vector pointer registers somewhere ?harmless?. */ + outb(0xff, E33G_VP2); /* Point at the ROM restart location 0xffff0 */ + outb(0xff, E33G_VP1); + outb(0x00, E33G_VP0); + /* Turn off all interrupts until we're opened. */ + outb_p(0x00, E8390_BASE + EN0_IMR); + outb_p(EGACFR_IRQOFF, E33G_GACFR); + + /* Probe for, turn on and clear the board's shared memory. */ + mem_jumpers = inb(E33G_ROMBASE); + if (mem_jumpers & 0xf0 == 0) { + dev->mem_start = 0; + printk(EI_NAME": no shared memory mapped\n"); + } else { + int *mem_base; + dev->mem_start = ((mem_jumpers & 0xc0) ? 0xD8000 : 0xC8000) + + ((mem_jumpers & 0xA0) ? 0x4000 : 0); + mem_base = (int *)dev->mem_start; + printk(EI_NAME": shared memory at %#6X\n", mem_base); + /* Check the card's memory. */ + for (i = 0; i < (SM_RSTOP_PG - SM_TSTART_PG)*256/sizeof(mem_base[0]); + i++) { + mem_base[i] = 0xAA425542; + if (mem_base[i] != 0xAA425542) { + printk(EI_NAME": memory failure or memory address conflict.\n"); + dev->mem_start = 0; + break; + } + mem_base[i] = 0; + } + /* Divide the on-board memory into a single maximum-sized transmit + (double-sized for ping-pong transmit) buffer at the base, and + use the rest as a receive ring. */ + dev->mem_end = dev->rmem_end = i * sizeof(mem_base[0]); + dev->rmem_start = (SM_RSTART_PG - SM_TSTART_PG) * 256; + } + pirq = (dev->irq == 9 ? 2 : dev->irq); + if (pirq > 5 || pirq < 2) { + printk(EI_NAME": configured interrupt number %d out of range.\n", + dev->irq); + return; /* Return failure someday */ + } else if (irqaction (dev->irq, &ei_sigaction)) { + printk (EI_NAME ": Unable to get IRQ%d.\n", dev->irq); + return; /* Return failure someday */ + } else { + /* We could look for other free interrupts here, or something... */ + } + outb_p((0x04 << pirq), E33G_IDCFR); /* Set the interrupt line. */ + outb_p(8, E33G_NBURST); /* Set burst size to 8 */ + outb_p(0x21, E33G_DMAAH); /* Set up transmit bfr in DMA addr */ + outb_p(0x00, E33G_DMAAL); + return; /* Return success */ +} + +/* Either use the shared memory (if enabled on the board) or put the packet + out through the ASIC FIFO. The latter is probably much slower. */ +static void +el2_block_output(struct device *dev, int count, const unsigned char *buf) +{ + int i; /* Buffer index */ + int boguscount = 0; /* timeout counter */ + if (dev->mem_start) { /* Shared memory transfer */ + outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM */ + memcpy((char *)dev->mem_start, buf, count); + return; + } + /* Set up then start the internal memory transfer to SM_TSTART_PG */ + outb(0x00, E33G_DMAAL); + outb(SM_TSTART_PG, E33G_DMAAH); + outb(ei_status.thin_bit | ECNTRL_OUTPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. I think it is possible + to output 8 bytes between checking the status bit. */ + for(i = 0; i < count; i++) { + while (inb(E33G_STATUS) & ESTAT_DPRDY == 0) + if (++boguscount > 150000) { + printk(EI_NAME": fifo blocked in el2_block_output.\n"); + return; + } + outb(buf[i], E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + return; +} + +/* Returns the new ring pointer. */ +static int +el2_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int boguscount = 0; + int end_of_ring = dev->rmem_end; + /* Maybe enable shared memory just be to be safe... nahh.*/ + if (dev->mem_start) { /* Use the shared memory. */ + if (ring_offset + count >= end_of_ring) { + /* We must wrap the input move. */ + int semi_count = end_of_ring - ring_offset; + memcpy(buf, (char *)dev->mem_start + ring_offset, semi_count); + buf += semi_count, count -= semi_count; + ring_offset = dev->rmem_start; + } + memcpy(buf, (char *)dev->mem_start + ring_offset, count); + return ring_offset + count; + } else { /* No shared memory, use the fifo. */ + int i; + outb(ring_offset & 0xff, E33G_DMAAL); + outb((ring_offset >> 8) & 0xff, E33G_DMAAH); + outb(ei_status.thin_bit | ECNTRL_INPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. */ + for(i = 0; i < count; i++) { + while (inb(E33G_STATUS) & ESTAT_DPRDY == 0) + if (++boguscount > 150000) { + printk(EI_NAME": fifo blocked in el2_block_input().\n"); + return 0; + } + buf[i] = inb(E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + ring_offset += count; + if (ring_offset >= end_of_ring) + ring_offset = dev->rmem_start + ring_offset - end_of_ring; + return ring_offset; + } +} + +/* Routines for the NE2000. */ +#define NE_BASE (e8390_base) +#define NE_DATAPORT 0x10 /* NE2000 Port Window. */ +#define NE_RESET 0x1f /* Issue a read for reset */ + +#define longpause()\ + do { int start_time = jiffies; while(jiffies-start_time < 18) ;\ + } while(0) + +/* Probe for the NE1000 and NE2000. NE2000-like boards have 0x57,0x57 in + bytes 0x0e,0x0f of the SAPROM. I'm not certain yet what to do about + the NE1000! */ +/* Also initialize the card and fill in STATION_ADDR with the station address. + The on-board data is stored where other cards have shared memory, + 32 bytes starting at remote DMA address 0. */ + +static int neprobe(int ioaddr, unsigned char station_addr[ETHER_ADDR_LEN]) +{ + int i; + unsigned char ne_board_data[32]; + int found, cmdreg; + + printk("NE2000 probing at %#3x: ", ioaddr); + cmdreg = inb_p(ioaddr); + if (cmdreg == 0xFF) { + printk(" not found (%#2.2x).\n", cmdreg); + return 0; + } + /* Ooops, we must first initialize registers -- we can't just read the PROM + address right away. (Learned the hard way.) */ + /* NS8390_init(eifdev);*/ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr); + outb_p(0x49, ioaddr + EN0_DCFG); /* Set word-wide for probe. */ + /* Even though we'll set them soon, we must clear them! */ + outb_p(0x00, ioaddr + EN0_RCNTLO); + outb_p(0x00, ioaddr + EN0_RCNTHI); + + outb_p(0x00, ioaddr + EN0_IMR); /* Mask completion irq. */ + outb_p(0xFF, E8390_BASE + EN0_ISR); + + /* Set to monitor and loopback mode. */ + outb_p(E8390_RXOFF, E8390_BASE + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, E8390_BASE + EN0_TXCR); /* 0x02 */ + + + /* Double count 0x20 words, the SA PROM is only byte wide. */ + outb_p(2*sizeof(ne_board_data), ioaddr + EN0_RCNTLO); + outb_p(0x00, ioaddr + EN0_RCNTHI); + outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0000. */ + outb_p(0x00, ioaddr + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, ioaddr); + for(i = 0; i < sizeof(ne_board_data); i++) { + ne_board_data[i] = inb_p(ioaddr + NE_DATAPORT); + if (i < ETHER_ADDR_LEN && station_addr) { + printk(" %#2.2x", ne_board_data[i]); + station_addr[i] = ne_board_data[i]; + } + } + found = ne_board_data[14] == 0x57 && ne_board_data[15] == 0x57; + printk(" %sfound.\n", found ? "" : "not "); + return found; +} + +static void +ne_reset_8390(struct device *dev) +{ + int tmp = inb_p(NE_BASE + NE_RESET); + ei_status.txing = 0; + longpause(); /* We should wait a few jiffies... */ + outb_p(tmp, NE_BASE + NE_RESET); +} + +/* Block input and output, based on the Clarkson packet driver. + The NE2000 doesn't have shared memory on the board -- put the packet + out through the ASIC FIFO. This is probably very slow. */ + +static int +ne_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + + outb_p(E8390_PAGE0+E8390_START, EN_CMD); + outb_p(count & 0xff, E8390_BASE + EN0_RCNTLO); + outb_p(count >> 8, E8390_BASE + EN0_RCNTHI); + outb_p(ring_offset & 0xff, E8390_BASE + EN0_RSARLO); + outb_p(ring_offset >> 8, E8390_BASE + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + if (!ne1000) { + port_read(E8390_BASE + NE_DATAPORT,buf,count>>1); + if (count & 0x01) + buf[count-1] = inb(E8390_BASE + NE_DATAPORT); + } else { + int i; + /* Input the bytes with a slow 8-bit loop. Tune this someday. */ + for(i = 0; i < count; i++) { + buf[i] = inb_p(E8390_BASE + NE_DATAPORT); + } + } + return ring_offset + count; +} + +/* Issues to be resolved for the NE1000: we don't need to round the byte + count up, and the dummy read only needs (count+1), not (count+2). */ +static void +ne_block_output(struct device *dev, int count, const unsigned char *buf) +{ + int i; + int boguscount = 0, tries = 0; + + /* Round the count up. This is for word writes on the NE2000, but do + we need to do it? What effect will an odd byte count have on the + 8390? */ + if (count & 0x01) + count++; + restart: + boguscount = 0; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START, EN_CMD); + + /* This following dummy-read-first sequence is suggested by + NatSemi to avoid a bug in the 8390. */ + outb_p((count+2) & 0xff, NE_BASE + EN0_RCNTLO); + outb_p((count+2) >> 8, NE_BASE + EN0_RCNTHI); + + outb_p(0xfe, NE_BASE + EN0_RSARLO); + outb_p(ei_status.tx_start_page-1, NE_BASE + EN0_RSARHI); + + outb_p(E8390_RREAD+E8390_START, EN_CMD); + + /* Make certain that the dummy read has occured -- strange bugs can + occur otherwise. */ + while (inb_p(NE_BASE + EN0_RSARLO) != 0x00) + if (++boguscount > 10) { + printk(EI_NAME": Failed to write packet (addrlo=%#2x).\n", + inb_p(NE_BASE + EN0_RSARLO)); + if (++tries < 3) + goto restart; /* 8390 burped? */ + return; /* Splat... drop the packet..should reset? */ + } + + outb_p(E8390_RWRITE+E8390_START, EN_CMD); + if (ne1000) { + /* Output the bytes with a slow 8-bit loop. This actually is almost + as fast as possible, but it does tie up the processor. */ + for(i = 0; i < count; i++) + outb_p(buf[i], NE_BASE + NE_DATAPORT); + } else /* NE2000 */ + /* Use the 'rep' sequence for the NE2000. */ + port_write(E8390_BASE + NE_DATAPORT, buf, count>>1); + + while (inb_p(EN0_ISR) & ENISR_RDC == 0) /* DMA done? */ + if (++boguscount > 15000) { + printk(EI_NAME": Timed out doing ne_block_output(%d).\n", count); + return; + } + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int low = inb_p(NE_BASE + EN0_RSARLO); + int high = inb_p(NE_BASE + EN0_RSARHI); + int addr = (high << 8) + low; + if ((ei_status.tx_start_page << 8) + count != addr) + printk(EI_NAME": TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n", + (ei_status.tx_start_page << 8) + count, addr); + } + return; +} + +/* This function resets the ethercard if something screws up. */ +static void +ne_init_card(struct device *dev) +{ + + + NS8390_init(dev); + /* Snarf the interrupt. We could share or wait until open(), but... */ + { int irqval = irqaction (dev->irq, &ei_sigaction); + if (irqval) + printk (EI_NAME": unable to get IRQ%d, error=%d.\n", dev->irq, irqval); + } + return; +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -DEI_DEBUG=3 -I/usr/linux-master/net/tcp -c -o 3c503.o 3c503.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ +#endif /* EI8390 */ diff --git a/net/tcpip/ne2000/3c503reg.h b/net/tcpip/ne2000/3c503reg.h new file mode 100644 index 00000000..7bcaf2d6 --- /dev/null +++ b/net/tcpip/ne2000/3c503reg.h @@ -0,0 +1,55 @@ +/* Definitions for the Etherlink 2. */ +#include "8390.h" +#define EL2H (dev->base_addr + 0x400) +#define EL2L (dev->base_addr) + +/* 3Com 3c503 ASIC registers */ +#define E33G_STARTPG (EL2H+0) /* Start page, must match EN0_STARTPG */ +#define E33G_STOPPG (EL2H+1) /* Stop page, must match EN0_STOPPG */ +#define E33G_NBURST (EL2H+2) /* Size of DMA burst before relinquishing bus */ +#define E33G_IOBASE (EL2H+3) /* Bit coded: where I/O regs are jumpered. */ + /* (Which you have to know already to read it) */ +#define E33G_ROMBASE (EL2H+4) /* Bit coded: Where/whether EEPROM&DPRAM exist */ +#define E33G_GACFR (EL2H+5) /* Config/setup bits for the ASIC GA */ +#define E33G_CNTRL (EL2H+6) /* Board's main control register */ +#define E33G_STATUS (EL2H+7) /* Status on completions. */ +#define E33G_IDCFR (EL2H+8) /* Interrupt/DMA config register */ + /* (Which IRQ to assert, DMA chan to use) */ +#define E33G_DMAAH (EL2H+9) /* High byte of DMA address reg */ +#define E33G_DMAAL (EL2H+10) /* Low byte of DMA address reg */ +#define E33G_VP2 (EL2H+11) /* Vector pointer - for clearing RAM select */ +#define E33G_VP1 (EL2H+12) /* on a system reset, to re-enable EPROM. */ +#define E33G_VP0 (EL2H+13) /* 3Com says set this to Ctrl-Alt-Del handler */ +#define E33G_FIFOH (EL2H+14) /* FIFO for programmed I/O data moves ... */ +#define E33G_FIFOL (EL2H+15) /* .. low byte of above. */ + +/* Bits in E33G_CNTRL register: */ + +#define ECNTRL_RESET (0x01) /* Software reset of the ASIC and 8390 */ +#define ECNTRL_THIN (0x02) /* Onboard thin-net xcvr enable */ +#define ECNTRL_SAPROM (0x04) /* Map the station address prom */ +#define ECNTRL_DBLBFR (0x20) /* FIFO configuration bit */ +#define ECNTRL_OUTPUT (0x40) /* PC-to-3C503 direction if 1 */ +#define ECNTRL_INPUT (0x00) /* 3C503-to-PC direction if 0 */ +#define ECNTRL_START (0x80) /* Start the DMA logic */ + +/* Bits in E33G_STATUS register: */ + +#define ESTAT_DPRDY (0x80) /* Data port (of FIFO) ready */ +#define ESTAT_UFLW (0x40) /* Tried to read FIFO when it was empty */ +#define ESTAT_OFLW (0x20) /* Tried to write FIFO when it was full */ +#define ESTAT_DTC (0x10) /* Terminal Count from PC bus DMA logic */ +#define ESTAT_DIP (0x08) /* DMA In Progress */ + +/* Bits in E33G_GACFR register: */ + +#define EGACFR_NORM (0x49) /* Enable 8K shared mem, no DMA TC int */ +#define EGACFR_IRQOFF (0xc9) /* Above, and disable 8390 IRQ line */ + +/* Shared memory management parameters */ + +#define EL2SM_TSTART_PG (0x20) /* First page of TX buffer */ +#define EL2SM_RSTART_PG (0x26) /* Starting page of RX ring */ +#define EL2SM_RSTOP_PG (0x40) /* Last page +1 of RX ring */ + +/* End of 3C503 parameter definitions */ diff --git a/net/tcpip/ne2000/8390.h b/net/tcpip/ne2000/8390.h new file mode 100644 index 00000000..c92faf8d --- /dev/null +++ b/net/tcpip/ne2000/8390.h @@ -0,0 +1,90 @@ +/* Generic NS8390 register definitions. */ +/* This file was originally written for the 3c503 driver, but should be + usable for most 8390-based network boards. + Some of these names are from the clarkson packet drivers. */ + +/* Some generic ethernet register configurations. */ +#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ +#define E8390_RX_IRQ_MASK 0x5 +#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ +#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ +#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ +#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ + +/* Register accessed at EN_CMD, the 8390 base addr. */ +#define E8390_STOP 0x01 /* Stop the chip, software reset */ +#define E8390_START 0x02 /* Start the chip after stopping */ +#define E8390_TRANS 0x04 /* Transmit a frame */ +#define E8390_RREAD 0x08 /* Remote read */ +#define E8390_RWRITE 0x10 /* Remote write */ +#define E8390_NODMA 0x20 /* No remote DMA used on this card */ +#define E8390_PAGE0 0x00 /* Select page chip registers */ +#define E8390_PAGE1 0x40 /* using the two high-order bits */ +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ + +/* Page 0 register offsets. */ +#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ +#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ +#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ +#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ +#define EN0_TSR 0x04 /* Transmit status reg RD */ +#define EN0_TPSR 0x04 /* Transmit starting page WR */ +#define EN0_NCR 0x05 /* Number of collision reg RD */ +#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ +#define EN0_FIFO 0x06 /* FIFO RD */ +#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ +#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ +#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ +#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ +#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ +#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ +#define EN0_RSR 0x0c /* rx status reg RD */ +#define EN0_RXCR 0x0c /* RX configuration reg WR */ +#define EN0_TXCR 0x0d /* TX configuration reg WR */ +#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ +#define EN0_DCFG 0x0e /* Data configuration reg WR */ +#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ +#define EN0_IMR 0x0f /* Interrupt mask reg WR */ +#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ + +/* Bits in EN0_ISR - Interrupt status register */ +#define ENISR_RX 0x01 /* Receiver, no error */ +#define ENISR_TX 0x02 /* Transmitter, no error */ +#define ENISR_RX_ERR 0x04 /* Receiver, with error */ +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ +#define ENISR_COUNTERS 0x20 /* Counters need emptying */ +#define ENISR_RDC 0x40 /* remote dma complete */ +#define ENISR_RESET 0x80 /* Reset completed */ +#define ENISR_ALL 0x3f /* Interrupts we will enable */ + +/* Bits in EN0_DCFG - Data config register */ +#define ENDCFG_WTS 0x01 /* word transfer mode selection */ + +/* Page 1 register offsets. */ +#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */ +#define EN1_CURPAG 0x07 /* Current memory page RD WR */ +#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */ + +/* Bits in received packet status byte and EN0_RSR*/ +#define ENRSR_RXOK 0x01 /* Received a good packet */ +#define ENRSR_CRC 0x02 /* CRC error */ +#define ENRSR_FAE 0x04 /* frame alignment error */ +#define ENRSR_FO 0x08 /* FIFO overrun */ +#define ENRSR_MPA 0x10 /* missed pkt */ +#define ENRSR_PHY 0x20 /* physical/multicase address */ +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ +#define ENRSR_DEF 0x80 /* deferring */ + +/* Transmitted packet status, EN0_TSR. */ +#define ENTSR_PTX 0x01 /* Packet transmitted without error */ + +/* The per-packet-header format. */ +struct e8390_pkt_hdr { + unsigned char status; /* status */ + unsigned char next; /* pointer to next packet. */ + unsigned short count; /* header + packet lenght in bytes */ +}; diff --git a/net/tcpip/ne2000/README b/net/tcpip/ne2000/README new file mode 100644 index 00000000..377300ea --- /dev/null +++ b/net/tcpip/ne2000/README @@ -0,0 +1,86 @@ + +Directory: ~ftp/pub/linux/ + +WARNING -- read the bugs section at the end of this file before getting + the ethernet board driver!!! + +Files: + README This file, updated Tuesday Nov. 24, 1992 18:34. + 3c501.c The 3c501 ethernet driver source + 3c503.c The 3c503, 3c503/16, NE1000 and NE2000 ethernet driver source. + 3c503reg.h Definitions specific to the 3c503 + 8390.h Generic definitions for the NS8390 chip. + Space.c Added the table entries for the new ethernet drivers. + This file is modified from the 0.98.4 release. + + Image A pre-built Linux 0.98.4 kernel with MathEmu, no SCSI, mount + patch, serial patch, CapsLck mapped to Cntrl, and the + 3c503 and NE2000 ethernet drivers. This kernel usually has + massive ethernet debugging turned on (debugging the kernel + and setting ei_debug = 0 and el_debug = 0 will turn it off) + and this version may not really work. Also the address and + IRQ settings are hard-coded for most ethercards. Making your + own kernel is usually a much better choice. + + linux-0.98.3-E If it exists, the last Image file that worked OK. + + +Directions: + +You might want to rename "3c503.c" to "ne2000.c". + +Put the files (3c503.c, 3c503reg.h, 8390.h, and Space.c) into linux/net/tcp/. +Space.c is the only tricky one -- it overwrites the old Space.c, and +you'll need to edit it to add your IRQ and base address. + +Next add 3c503.o to to linux/net/tcp/Makefile + tcpip.o: ... 3c503.o + +Edit linux/include/linux/config.h and/or config.site.h and insert the following +(see below for other details). +#undef CONFIG_DISTRIBUTION /* Use config.site.h instead. */ +#define EI8390 0x300 /* Then these should be in config.site.h */ +#define EI8390IRQ 5 /* Not used yet, edit Space.c instead. */ +#define EI_DEBUG 2 + +Make and install your new kernel. + +To actually use this driver you must get the TCP/IP package and edit +your /usr/etc/inet/rc.net file to config device "eth_if" instead of +"eth0" (the WD8003). + +BUGS + None know right now. I haven't tested the NS8390 overrun code -- it + worked OK the last time I had other bugs to trigger it, but I've + changed it since. + + Two errors in some versions of the 8390/83901/83902 may not + be handled correctly: the first is a bug where the RX status bytes + is missing from the header -- I try to recover first rather than + resetting the chip (which I do afterwards). + + The second is the 8390 problem with writes to the ethercard + RAM: the first write may be corrupted if you don't do a read + first -- I've never seen this corruption happen, but it may + just be masked by higher level protocols. + I have put in the read-first code, but it's a frequent + source of problems... The timing is really tricky. + + The 3c501 driver isn't complete. This card severely brain-damaged + anyway -- you won't notice the performance diffence when it does work. + +Please send me email if you do try out the drivers, even if you don't +encounter bugs. + +Important defines + +EI_DEBUG Set to the desired numeric debugging level. Use 3 or + greater when actively debugging a problem, '1' for a + casual interest in what's going on, and '0' for normal + use. (Most of the debugging stuff has been taken out recently, + so this won't have much effect.) +EI8390 Define (probably in config.site.h) this to the base address + of your ethernet card. You will also have to set the base + address and irq in net/tcp/Space.c. +ETHERLINK1 Define this to the base address of a 3c501 card. You will + also have to set the base address and irq in net/tcp/Space.c. diff --git a/net/tcpip/ne2000/Space.c b/net/tcpip/ne2000/Space.c new file mode 100644 index 00000000..ec7ba882 --- /dev/null +++ b/net/tcpip/ne2000/Space.c @@ -0,0 +1,113 @@ +/* Space.c */ +/* Holds initial configuration information for devices. */ +#include "dev.h" +#include +#include + +#ifdef ETHERLINK1 +extern void etherlink_init(struct device *); + +static struct device el_dev = { + "if3c501", + 0, 0, 0, 0, /* memory rx_end, rx_start, end, start are autoconfiged. */ + ETHERLINK1, 9, 0,0,0,0,0, /* base i/o address, irq, and flags. */ + NULL, etherlink_init, 0, {NULL}, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, {0,}, {0,}, 0 + }; +#endif + +#ifdef EI8390 +extern void ethif_init(struct device *); + +static struct device el3c503_dev = { + "eth_if", + 0, 0, 0, 0, /* memory rx_end, rx_start, end, start are autoconfiged. */ + 0x300, 5, 0,0,0,0,0, /* base i/o address, irq, and flags. */ +#ifdef ETHERLINK1 + &el_dev, +#else + NULL, +#endif + ethif_init, 0, {NULL}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, 0, 0, {0,}, {0,}, 0 + }; +#endif +extern void wd8003_init(struct device *); + +static struct device wd8003_dev = +{ + "eth0", + 0xd2000, /* recv memory end. */ + 0xd0600, /* recv memory start. */ + 0xd2000, /* memory end. */ + 0xd0000, /* memory start. */ + 0x280, /* base i/o address. */ + 5, /* irq */ + 0,0,0,0,0, /* flags */ +#ifdef EI8390 + &el3c503_dev, /* next device */ +#elif defined(ETHERLINK1) + &el_dev, /* next device */ +#else + NULL, /* next device */ +#endif + wd8003_init, + /* wd8003_init should set up the rest. */ + 0, /* trans start. */ + {NULL}, /* buffs */ + NULL, /* backlog */ + NULL, /* open */ + NULL, /* stop */ + NULL, /* hard_start_xmit */ + NULL, /* hard_header */ + NULL, /* add arp */ + NULL, /* queue xmit */ + NULL, /* rebuild header */ + NULL, /* type_trans */ + NULL, /* send_packet */ + NULL, /* private */ + 0, /* type. */ + 0, /* hard_header_len */ + 0, /* mtu */ + {0,}, /* broadcast address */ + {0,}, /* device address */ + 0 /* addr len */ +}; + +extern void loopback_init(struct device *dev); + +static struct device loopback_dev = +{ + "loopback", + -1, /* recv memory end. */ + 0x0, /* recv memory start. */ + -1, /* memory end. */ + 0, /* memory start. */ + 0, /* base i/o address. */ + 0, /* irq */ + 0,0,1,0,0, /* flags */ + &wd8003_dev, /* next device */ + loopback_init, + /* loopback_init should set up the rest. */ + 0, /* trans start. */ + {NULL}, /* buffs */ + NULL, /* backlog */ + NULL, /* open */ + NULL, /* stop */ + NULL, /* hard_start_xmit */ + NULL, /* hard_header */ + NULL, /* add arp */ + NULL, /* queue xmit */ + NULL, /* rebuild header */ + NULL, /* type_trans */ + NULL, /* send_packet */ + NULL, /* private */ + 0, /* type. */ + 0, /* hard_header_len */ + 0, /* mtu */ + {0,}, /* broadcast address */ + {0,}, /* device address */ + 0 /* addr len */ +}; + +struct device *dev_base = &loopback_dev; diff --git a/net/tcpip/net-0.1.README b/net/tcpip/net-0.1.README new file mode 100644 index 00000000..20cbfd90 --- /dev/null +++ b/net/tcpip/net-0.1.README @@ -0,0 +1,13 @@ +README for net-src-0.1.tar.Z and net-bin-0.1.tar.Z + +Included are ftp, ftpd, telnet, telnetd, inetd, named, nslookup and ping. + +These are libc-4.1 versions of various net programs, both +source and binaries. They are from bsd-net2 with very minimal +changes. The telnet port is based on the one from Pete Chown. + +Yes, this telnet/telnetd really works. I think. This is only +a pre-release. Let me know if there are any problems. + +Rick Sladkey +jrs@world.std.com diff --git a/net/tcpip/net-0.2.README b/net/tcpip/net-0.2.README new file mode 100644 index 00000000..cb7e7001 --- /dev/null +++ b/net/tcpip/net-0.2.README @@ -0,0 +1,98 @@ +This is a compliation of some net sources, mostly from bsd-net2. I +have made an effort to get the programs to compile with few or no +changes except for a new Makefile. This resulted in a bsd include +directory and a bsd library. Take a look at them to see what types of +things are required to get BSD sources to compile correctly without +changes. Some of the tricks are pretty ugly. Please don't laugh... + +Everything should compile straight with the libc-4.2 libraries. Just +type "make" in this directory. You may have to do some surgery on +libbsd/libbsd.a to get things to compile with libc-4.1. + +Notes +===== + +bsd: The directory "bsd" contains include files that, for the most +part, just overload include files of the same name from /usr/include. +It provides some BSD things like "union wait" and others. + +libbsd: The libbsd.a archive is a small library of some functions that +are not in our libc as well as some emulation support functions +referenced in the bsd header files. Notably, it includes a +half-decent transparent sgtty emulation package. + +inetd: Works. Only pathname changes. + +ftp: Works. No changes. + +ftpd: I find that ls with ftpd doesn't work very often. It reports +"Transport endpoint already connected" 9 times out of 10. I think +this is a bug in the kernel which will be fixed in a subsequent +release. There was a memory allocation bug in the original source, +look for "#ifdef linux". Also, the shadow password stuff is not +compiled in as I haven't had a chance to mess with that. + +telnet: Works but see the man page for info about the .telnetrc file +and other new options. This is a really nice telnet with rlogin +emulation and lots of other stuff not present in older telnets. The +original Linux port of telnet/telnetd was done by Pete Chown. + +telnetd: Several people have reported that the 0.1 telnetd sometimes +disconnected before getting to the login prompt. The 0.2 version +omits the vhangup stuff which might have been causing the problem. +Also fixed is the problem with /etc/wtmp not being updated correctly +on logout. It was trying to use /var/adm/wtmp. + +finger: Works. One minor change for POSIX timezone handling. + +fingerd: Works, no changes. + +ping: Works, no changes. Must be suid to root. + +named: Works. A few changes for pathnames and net device +configuration stuff. + +nslookup: Works, but it's fussier than older nslookups about named +being setup correctly. Note the -I option is needed for flex -- that +was a tough one to find. No changes. + +named-xfer: Not tested. + +rcp: Works. Must be suid to root. + +rsh: Works. Must be suid to root. + +rshd: Works. + +rlogin: Works OK but needs more testing. This one depends pretty heavily +on the sgtty emulation in libbsd which is not complete yet. There is +an odd timing bug with select and termio settings. Look for "sleep(1)" +to see what I mean. Must be suid to root. + +rlogind: Works with the URGENT stuff commented out. There was a nasty +bug with shared libraries because environ was redefined. + +talk: Works. This is the new byte-order independent talk, not the old +talk that, e.g., native SunOS uses. The old one wouldn't work with +them anyway. Not the fault of Linux. Includes a one line patch for a +bug in our curses and another for a bug in the original source dealing +with select. + +ntalkd: Works. No changes. + +tftp: Works. No changes. + +tftpd: Works. No changes. + +Sample Entries for inetd.conf +============================= +telnet stream tcp nowait root /usr/etc/inet/telnetd telnetd +ntalk dgram udp wait root /usr/etc/inet/ntalkd ntalkd +ftp stream tcp nowait root /usr/etc/inet/ftpd ftpd -l +finger stream tcp nowait root /usr/etc/inet/fingerd finger +shell stream tcp nowait root /usr/etc/inet/rshd rshd +login stream tcp nowait root /usr/etc/inet/rlogind rlogind +tftp dgram udp wait root /usr/etc/inet/tftpd tftpd + +Rick Sladkey +jrs@world.std.com diff --git a/net/tcpip/newether-pingpong/3c503.c b/net/tcpip/newether-pingpong/3c503.c new file mode 100644 index 00000000..35501bee --- /dev/null +++ b/net/tcpip/newether-pingpong/3c503.c @@ -0,0 +1,377 @@ +/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with the 3c503 and 3c503/16. It must be used + in shared memory mode. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = "3c503.c:v0.67 3/8/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include +#include + +#include "dev.h" + +#include "8390.h" +#include "3c503reg.h" + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; + +int el2autoprobe(int ioaddr, struct device *dev); +int el2probe(int ioaddr, struct device *dev); + +static void el2_reset_8390(struct device *dev); +static void el2_init_card(struct device *dev); +static void el2_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static int el2_block_input(struct device *dev, int count, char *buf, + int ring_offset); + + +int +el2autoprobe(int ioaddr, struct device *dev) +{ + int *addr, addrs[] = { 0xddffe, 0xd9ffe, 0xcdffe, 0xc9ffe, 0}; + int ports[] = {0x300,0x310,0x330,0x350,0x250,0x280,0x2a0,0x2e0,0}; + + /* Non-autoprobe case first: */ + if (ioaddr > 0) + return el2probe(ioaddr, dev); + + /* We check for a memory-mapped 3c503 board by looking at the + port location bitmap at the end of the jumpered boot PROM space. + This works even if a PROM isn't there. */ + for (addr = addrs; *addr; addr++) { + int i; + unsigned int base_bits = *(unsigned char *)*addr; + /* Find first set bit. */ + for(i = 7; i >= 0; i--, base_bits >>= 1) + if (base_bits & 0x1) + break; + if (base_bits == 1 && el2probe(ports[i], dev)) + return dev->base_addr; + } +#ifndef ignore_nonshared_memory + /* It's not memory mapped, bummer. Try all of the locations + that aren't obviously empty. */ + { int i; + for (i = 0; i < 8; i++) + if (inb_p(ports[i] + 0x403) == (0x80 >> i) /* Preliminary check */ + && el2probe(ports[i], dev)) + return dev->base_addr; + } +#endif /* probe_nonshared_memory */ + return 0; +} + +/* Probe for the Etherlink II card at I/O port base IOADDR, + returning non-zero on sucess. If found, set the station + address and memory parameters in DEVICE. */ +int +el2probe(int ioaddr, struct device *dev) +{ + int i, iobase_reg, membase_reg, saved_406; + unsigned char *station_addr = dev->dev_addr; + + /* We verify that it's a 3C503 board by checking the first three octets + of its ethernet address. */ + printk("3c503 probe at %#3x:", ioaddr); + iobase_reg = inb(ioaddr+0x403); + membase_reg = inb(ioaddr+0x404); + /* Verify ASIC register that should be 0 or have a single bit set. */ + if ( (iobase_reg & (iobase_reg - 1)) + || (membase_reg & (membase_reg - 1))) { + printk(" not found.\n"); + return 0; + } + saved_406 = inb_p(ioaddr + 0x406); + outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */ + outb_p(ECNTRL_THIN, ioaddr + 0x406); + /* Map the station addr PROM into the lower I/O ports. */ + outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406); + for (i = 0; i < ETHER_ADDR_LEN; i++) { + printk(" %2.2X", (station_addr[i] = inb(ioaddr + i))); + } + if ( station_addr[0] != 0x02 + || station_addr[1] != 0x60 + || station_addr[2] != 0x8c) { + printk(" 3C503 not found.\n"); + /* Restore the register we frobbed. */ + outb_p(saved_406, ioaddr + 0x406); + return 0; + } + /* Map the 8390 back into the window. */ + outb(ECNTRL_THIN, ioaddr + 0x406); + dev->base_addr = ioaddr; + /* Probe for, turn on and clear the board's shared memory. */ + if (ei_debug > 2) printk(" memory jumpers %2.2x ", membase_reg); + outb(EGACFR_NORM, ioaddr + 0x405); /* Enable RAM */ + if ((membase_reg & 0xf0) == 0) { + dev->mem_start = 0; + } else { + dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) + + ((membase_reg & 0xA0) ? 0x4000 : 0); + +#define EL2_MEMSIZE (EL2SM_STOP_PG - EL2SM_START_PG)*256 +#ifdef EL2MEMTEST + /* This has never found an error, but someone might care. */ + { /* Check the card's memory. */ + int *mem_base = (int *)dev->mem_start; + int memtest_value = 0xbbadf00d; + mem_base[0] = 0xba5eba5e; + for (i = 1; i < EL2_MEMSIZE/sizeof(mem_base[0]); i++) { + mem_base[i] = memtest_value; + if (mem_base[0] != 0xba5eba5e + || mem_base[i] != memtest_value) { + printk(" memory failure or memory address conflict.\n"); + dev->mem_start = 0; + break; + } + memtest_value += 0x55555555; + mem_base[i] = 0; + } + } +#endif /* EL2MEMTEST */ + /* Divide the on-board memory into a single maximum-sized transmit + (double-sized for ping-pong transmit) buffer at the base, and + use the rest as a receive ring. */ + dev->mem_end = dev->rmem_end = dev->mem_start + EL2_MEMSIZE; + dev->rmem_start = TX_PAGES*256 + dev->mem_start; + } + if (ei_debug > 2) + printk("\n3c503: memory params start=%#5x rstart=%#5x end=%#5x rend=%#5x.\n", + dev->mem_start, dev->rmem_start, dev->mem_end, dev->rmem_end); + + /* Finish setting the board's parameters. */ + ei_status.name = "3C503"; + ei_status.tx_start_page = EL2SM_START_PG; + ei_status.rx_start_page = EL2SM_START_PG + TX_PAGES; + ei_status.stop_page = EL2SM_STOP_PG; + ei_status.reset_8390 = &el2_reset_8390; + ei_status.block_input = &el2_block_input; + ei_status.block_output = &el2_block_output; +/* This should be probed for (or set via an ioctl()) at run-time someday. */ +#if defined(EI8390_THICK) || defined(EL2_AUI) + ei_status.thin_bit = 0; +#else + ei_status.thin_bit = ECNTRL_THIN; +#endif + + if (dev->irq < 2) { + int irqlist[] = {5, 9, 3, 4, 0}; + int *irqp = irqlist; + do { + if (request_irq (dev->irq = *irqp, NULL) != -EBUSY) { + /* Twinkle the interrupt, and check if it's seen. */ + autoirq_setup(0); + outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR); + outb_p(0x00, E33G_IDCFR); + if (dev->irq == autoirq_report(0) /* It's a good IRQ line! */ + && request_irq (dev->irq, &ei_interrupt) == 0) { + printk(" got IRQ %d", dev->irq); + break; + } else + printk(" IRQ%d bad..", dev->irq); + } + } while (*++irqp); + if (*irqp == 0) { + printk(" unable to find an free IRQ line.\n"); + return 0; + } + } else { + if (dev->irq == 2) + dev->irq = 9; + else if (dev->irq > 5 && dev->irq != 9) { + printk("\n3c503: configured interrupt number %d out of range.\n", + dev->irq); + return 0; + } + if (request_irq(dev->irq, &ei_interrupt)) { + printk (" unable to get IRQ%d.\n", dev->irq); + return 0; + } + } + + dev->start = 0; + el2_init_card(dev); + + if (dev->mem_start) + printk("\n%s: %s using IRQ %d with shared memory at %#6x-%#6x,\n", + dev->name, ei_status.name, dev->irq, + dev->mem_start, dev->mem_end-1); + else + printk("\n%s: %s using IRQ %d with programmed I/O.\n", + dev->name, ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + + return ioaddr; +} + +/* This is called whenever we have a unrecoverable failure: + transmit timeout + Bad ring buffer packet header + */ +static void +el2_reset_8390(struct device *dev) +{ + if (ei_debug > 1) { + printk("%s: Resetting the 3c503 board...", dev->name); + printk("%#x=%#02x %#x=%#02x %#x=%#02x...", E33G_IDCFR, inb(E33G_IDCFR), + E33G_CNTRL, inb(E33G_CNTRL), E33G_GACFR, inb(E33G_GACFR)); + } + + outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL); + ei_status.txing = 0; + outb_p(ei_status.thin_bit, E33G_CNTRL); + el2_init_card(dev); + if (ei_debug > 1) printk("done\n"); +} + +/* Initialize the 3c503 GA registers after a reset. */ +static void +el2_init_card(struct device *dev) +{ + /* Unmap the station PROM and select the DIX or BNC connector. */ + outb_p(ei_status.thin_bit, E33G_CNTRL); + + /* Set ASIC copy of rx's first and last+1 buffer pages */ + /* These must be the same as in the 8390. */ + outb(ei_status.rx_start_page, E33G_STARTPG); + outb(ei_status.stop_page, E33G_STOPPG); + + /* Point the vector pointer registers somewhere ?harmless?. */ + outb(0xff, E33G_VP2); /* Point at the ROM restart location 0xffff0 */ + outb(0xff, E33G_VP1); + outb(0x00, E33G_VP0); + /* Turn off all interrupts until we're opened. */ + outb_p(0x00, dev->base_addr + EN0_IMR); + /* Enable IRQs iff started. */ + outb(EGACFR_NORM, E33G_GACFR); + + /* Set the interrupt line. */ + outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR); + outb_p(8, E33G_DRQCNT); /* Set burst size to 8 */ + outb_p(0x20, E33G_DMAAH); /* Put a valid addr in the GA DMA */ + outb_p(0x00, E33G_DMAAL); + return; /* We always succeed */ +} + +/* Either use the shared memory (if enabled on the board) or put the packet + out through the ASIC FIFO. The latter is probably much slower. */ +static void +el2_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page) +{ + int i; /* Buffer index */ + int boguscount = 0; /* timeout counter */ + + /* This should really be set with during an open(). */ + outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM and interrupts. */ + + if (dev->mem_start) { /* Shared memory transfer */ + void *dest_addr = (void *)(dev->mem_start + + ((start_page - ei_status.tx_start_page) << 8)); + memcpy(dest_addr, buf, count); + if (ei_debug > 2 && memcmp(dest_addr, buf, count)) + printk("%s: 3c503 send_packet() bad memory copy @ %#5x.\n", + dev->name, dest_addr); + else if (ei_debug > 4) + printk("%s: 3c503 send_packet() good memory copy @ %#5x.\n", + dev->name, dest_addr); + return; + } + /* No shared memory, put the packet out the slow way. */ + /* Set up then start the internal memory transfer to Tx Start Page */ + outb(0x00, E33G_DMAAL); + outb_p(start_page, E33G_DMAAH); + outb_p(ei_status.thin_bit | ECNTRL_OUTPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. I think it is possible + to output 8 bytes between each check of the status bit. */ + for(i = 0; i < count; i++) { + if (i % 8 == 0) + while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) + if (++boguscount > (i<<3) + 32) { + printk("%s: FIFO blocked in el2_block_output (at %d of %d, bc=%d).\n", + dev->name, i, count, boguscount); + return; + } + outb(buf[i], E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + return; +} + +/* Returns the new ring pointer. */ +static int +el2_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int boguscount = 0; + int end_of_ring = dev->rmem_end; + unsigned int i; + + /* Maybe enable shared memory just be to be safe... nahh.*/ + if (dev->mem_start) { /* Use the shared memory. */ + ring_offset -= (EL2SM_START_PG<<8); + if (dev->mem_start + ring_offset + count > end_of_ring) { + /* We must wrap the input move. */ + int semi_count = end_of_ring - (dev->mem_start + ring_offset); + if (ei_debug > 4) + printk("%s: 3c503 block_input() @ %#5x+%x=%5x.\n", + dev->name, dev->mem_start, ring_offset, + (char *)dev->mem_start + ring_offset); + memcpy(buf, (char *)dev->mem_start + ring_offset, semi_count); + count -= semi_count; + memcpy(buf + semi_count, (char *)dev->rmem_start, count); + return dev->rmem_start + count; + } + if (ei_debug > 4) + printk("%s: 3c503 block_input() @ %#5x+%x=%5x.\n", + dev->name, dev->mem_start, ring_offset, + (char *)dev->mem_start + ring_offset); + memcpy(buf, (char *)dev->mem_start + ring_offset, count); + return ring_offset + count; + } + /* No shared memory, use programmed I/O. */ + outb(ring_offset & 0xff, E33G_DMAAL); + outb_p((ring_offset >> 8) & 0xff, E33G_DMAAH); + outb_p(ei_status.thin_bit | ECNTRL_INPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. */ + for(i = 0; i < count; i++) { + if (i % 8 == 0) + while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) + if (++boguscount > (i<<3) + 32) { + printk("%s: FIFO blocked in el2_block_input() (at %d of %d, bc=%d).\n", + dev->name, i, count, boguscount); + boguscount = 0; + break; + } + buf[i] = inb_p(E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + return 0; +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c 3c503.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether-pingpong/3c503reg.h b/net/tcpip/newether-pingpong/3c503reg.h new file mode 100644 index 00000000..da7961d4 --- /dev/null +++ b/net/tcpip/newether-pingpong/3c503reg.h @@ -0,0 +1,59 @@ +/* Definitions for the 3Com 3c503 Etherlink 2. */ +/* This file is part of Donald Becker's 8390 drivers. + This file is distributed under the Linux GPL. + Some of these names and comments are from the Crynwr packet drivers. */ + +#define EL2H (dev->base_addr + 0x400) +#define EL2L (dev->base_addr) + +/* Shared memory management parameters */ + +#define EL2SM_START_PG (0x20) /* First page of TX buffer */ +#define EL2SM_STOP_PG (0x40) /* Last page +1 of RX ring */ + +/* 3Com 3c503 ASIC registers */ +#define E33G_STARTPG (EL2H+0) /* Start page, must match EN0_STARTPG */ +#define E33G_STOPPG (EL2H+1) /* Stop page, must match EN0_STOPPG */ +#define E33G_DRQCNT (EL2H+2) /* DMA burst count */ +#define E33G_IOBASE (EL2H+3) /* Read of I/O base jumpers. */ + /* (non-useful, but it also appears at the end of EPROM space) */ +#define E33G_ROMBASE (EL2H+4) /* Read of memory base jumpers. */ +#define E33G_GACFR (EL2H+5) /* Config/setup bits for the ASIC GA */ +#define E33G_CNTRL (EL2H+6) /* Board's main control register */ +#define E33G_STATUS (EL2H+7) /* Status on completions. */ +#define E33G_IDCFR (EL2H+8) /* Interrupt/DMA config register */ + /* (Which IRQ to assert, DMA chan to use) */ +#define E33G_DMAAH (EL2H+9) /* High byte of DMA address reg */ +#define E33G_DMAAL (EL2H+10) /* Low byte of DMA address reg */ +/* "Vector pointer" - if this address matches a read, the EPROM (rather than + shared RAM) is mapped into memory space. */ +#define E33G_VP2 (EL2H+11) +#define E33G_VP1 (EL2H+12) +#define E33G_VP0 (EL2H+13) +#define E33G_FIFOH (EL2H+14) /* FIFO for programmed I/O moves */ +#define E33G_FIFOL (EL2H+15) /* ... low byte of above. */ + +/* Bits in E33G_CNTRL register: */ + +#define ECNTRL_RESET (0x01) /* Software reset of the ASIC and 8390 */ +#define ECNTRL_THIN (0x02) /* Onboard thin-net xcvr enable */ +#define ECNTRL_SAPROM (0x04) /* Map the station address prom */ +#define ECNTRL_DBLBFR (0x20) /* FIFO configuration bit */ +#define ECNTRL_OUTPUT (0x40) /* PC-to-3C503 direction if 1 */ +#define ECNTRL_INPUT (0x00) /* 3C503-to-PC direction if 0 */ +#define ECNTRL_START (0x80) /* Start the DMA logic */ + +/* Bits in E33G_STATUS register: */ + +#define ESTAT_DPRDY (0x80) /* Data port (of FIFO) ready */ +#define ESTAT_UFLW (0x40) /* Tried to read FIFO when it was empty */ +#define ESTAT_OFLW (0x20) /* Tried to write FIFO when it was full */ +#define ESTAT_DTC (0x10) /* Terminal Count from PC bus DMA logic */ +#define ESTAT_DIP (0x08) /* DMA In Progress */ + +/* Bits in E33G_GACFR register: */ + +#define EGACFR_NORM (0x49) /* Enable 8K shared mem, no DMA TC int */ +#define EGACFR_IRQOFF (0xc9) /* Above, and disable 8390 IRQ line */ + +/* End of 3C503 parameter definitions */ diff --git a/net/tcpip/newether-pingpong/8390.c b/net/tcpip/newether-pingpong/8390.c new file mode 100644 index 00000000..152a98b2 --- /dev/null +++ b/net/tcpip/newether-pingpong/8390.c @@ -0,0 +1,689 @@ +/* 8390.c: A general NS8390 ethernet driver core for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with many 8390-based ethernet adaptors. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = + "8390.c:v0.68 3/9/93 for 0.99.6 Donald Becker (becker@super.org)\n"; +#include +#if !defined(EL2) && !defined(NE2000) && !defined(WD80x3) && !defined(HPLAN) +/* They don't know what they want -- give it all to them! */ +#define EL2 +#define NE2000 +#define WD80x3 +#define HPLAN +#endif + +/* + Braindamage remaining: + + Ethernet devices should use a chr_drv device interface, with ioctl()s to + configure the card, bring the interface up or down, allow access to + statistics, and maybe read() and write() access to raw packets. + This won't be done until after Linux 1.00. + + This driver should support multiple, diverse boards simultaneousely. + This won't be done until after Linux 1.00. + +Sources: + The National Semiconductor LAN Databook, and the 3Com 3c503 databook. + The NE* programming info came from the Crynwr packet driver, and figuring + out that the those boards are similar to the NatSemi evaluation board + described in AN-729. Thanks NS, no thanks to Novell/Eagle. + Cabletron provided only info I had already gotten from other sources -- hiss. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "eth.h" +#include "timer.h" +#include "ip.h" +#include "tcp.h" +#include "sock.h" +#include "arp.h" + +#include "8390.h" + +#define ei_reset_8390 (ei_local->reset_8390) +#define ei_block_output (ei_local->block_output) +#define ei_block_input (ei_local->block_input) + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifdef EI_DEBUG +int ei_debug = EI_DEBUG; +#else +int ei_debug = 2; +#endif + +struct device *irq2dev_map[16] = {0,0,0, /* zeroed...*/}; + +#ifdef PINGPONG +static int lasttx = 0; +#endif + +/* Max number of packets received at one Intr. */ +/*static int high_water_mark = 0;*/ + +/* Index to functions. */ +/* Put in the device structure. */ +static int ei_open(struct device *dev); +/* Dispatch from interrupts. */ +void ei_interrupt(int reg_ptr); +static void ei_tx_intr(struct device *dev); +static void ei_receive(struct device *dev); +static void ei_rx_overrun(struct device *dev); + +int ethdev_init(struct device *dev); +/* Routines generic to NS8390-based boards. */ +void NS8390_init(struct device *dev, int startp); +static void NS8390_trigger_send(struct device *dev, unsigned int length, + int start_page); + +extern int el2autoprobe(int ioaddr, struct device *dev); +extern int el2probe(int ioaddr, struct device *dev); +extern int neprobe(int ioaddr, struct device *dev); +extern int wdprobe(int ioaddr, struct device *dev); +extern int hpprobe(int ioaddr, struct device *dev); + +struct sigaction ei_sigaction = { ei_interrupt, 0, 0, NULL, }; + +/* Open/initialize the board. This routine goes all-out, setting everything + up anew at each open, even though many of these registers should only + need to be set once at boot. + */ +static int +ei_open(struct device *dev) +{ + struct ei_device *ei_local = dev->private; + + if ( ! ei_local) { + printk("%s: Opening a non-existent physical device\n", dev->name); + return 1; /* ENXIO would be more accurate. */ + } + + irq2dev_map[dev->irq] = dev; + NS8390_init(dev, 1); + ei_local->tx1 = ei_local->tx2 = 0; + /* The old local flags... */ + ei_local->txing = 0; + /* ... are now global. */ + dev->tbusy = 0; + dev->interrupt = 0; + dev->start = 1; + return 0; +} + +static int +ei_start_xmit(struct sk_buff *skb, struct device *dev) +{ + int e8390_base = dev->base_addr; + struct ei_device *ei_local = dev->private; + + if (dev->tbusy) { /* Do timeouts, just like the 8003 driver. */ + int txsr = inb(e8390_base+EN0_TSR), isr; + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 5 || (tickssofar < 15 && ! (txsr & ENTSR_PTX))) { + return 1; + } + isr = inb(e8390_base+EN0_ISR); + printk("%s: transmit timed out, TX status %#2x, ISR %#2x.\n", + dev->name, txsr, isr); + /* It's possible to check for an IRQ conflict here. + I may have to do that someday. */ + if (isr) + printk("%s: Possible IRQ conflict on IRQ%d?", dev->name, dev->irq); + else + printk("%s: Possible network cable problem?\n", dev->name); + /* It futile, but try to restart it anyway. */ + ei_reset_8390(dev); + NS8390_init(dev, 1); + printk("\n"); + } + + /* This is new: it means some higher layer thinks we've missed an + tx-done interrupt. Caution: dev_tint() handles the cli()/sti() + itself. */ + if (skb == NULL) { + dev_tint(dev); + return 0; + } + /* Fill in the ethernet header. */ + if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + skb->dev = dev; + arp_queue (skb); + return 0; + } + +#ifdef PINGPONG + { + int length = skb->len; + int output_page; + int send_length = ETHER_MIN_LEN < length ? length : ETHER_MIN_LEN; + if (length <= 0) + return 0; + /* Turn off interrupts so that we can put the packet out safely. */ + outb(0x00, e8390_base + EN0_IMR); + if (ei_local->tx1 == 0) { + output_page = ei_local->tx_start_page; + ei_local->tx1 = send_length; + if (ei_debug && ei_local->tx2 > 0) + printk("%s: idle transmitter tx2=%d, lasttx=%d, txing=%d.\n", + dev->name, ei_local->tx2, lasttx, ei_local->txing); + } else if (ei_local->tx2 == 0) { + output_page = ei_local->tx_start_page + 6; + ei_local->tx2 = send_length; + if (ei_debug && ei_local->tx1 > 0) + printk("%s: idle transmitter, tx1=%d, lasttx=%d, txing=%d.\n", + dev->name, ei_local->tx1, lasttx, ei_local->txing); + } else { + /* We can get to here if we get an rx interrupt and queued + a tx packet just before masking 8390 irqs above. */ + if (ei_debug > 2) + printk("%s: No packet buffer space for ping-pong use.\n", + dev->name); + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + return 1; + } + dev->trans_start = jiffies; + ei_block_output(dev, length, (void*)(skb+1), output_page); + if (! ei_local->txing) { + NS8390_trigger_send(dev, send_length, output_page); + if (output_page == ei_local->tx_start_page) + ei_local->tx1 = -1, lasttx = -1; + else + ei_local->tx2 = -1, lasttx = -2; + ei_local->txing = 1; + } else + ei_local->txqueue++; + if (ei_local->tx1 && ei_local->tx2) + dev->tbusy = 1; + /* Turn 8390 interrupts back on. */ + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + } +#else + { + int length = skb->len; + int send_length = ETHER_MIN_LEN < length ? length : ETHER_MIN_LEN; + if (length <= 0) + return 0; + dev->trans_start = jiffies; + /* Turn off interrupts so that we can put the packet out safely. */ + outb(0x00, e8390_base + EN0_IMR); + ei_block_output(dev, length, (void*)(skb+1), ei_local->tx_start_page); + NS8390_trigger_send(dev, send_length, ei_local->tx_start_page); + dev->tbusy = 1; + /* Turn 8390 interrupts back on. */ + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + } +#endif /* PINGPONG */ + if (skb->free) + kfree_skb (skb, FREE_WRITE); + return 0; +} + +/* The typical workload of the driver: + Handle the ether interface interrupts. */ +void +ei_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev = irq2dev_map[irq]; + int e8390_base; + int interrupts, boguscount = 0; + + if (dev == NULL) { + printk ("net_interrupt(): irq %d for unknown device.\n", irq); + return; + } + dev->interrupt = 1; + sti(); /* Allow other interrupts. */ + + e8390_base = dev->base_addr; + + /* Change to page 0 and read the intr status reg. */ + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); + if (ei_debug > 3) + printk("%s: interrupt(isr=%#2.2x).\n", dev->name, + inb_p(e8390_base + EN0_ISR)); + + /* !!Assumption!! -- we stay in page 0. Don't break this. */ + while ((interrupts = inb_p(e8390_base + EN0_ISR)) != 0 + && ++boguscount < 20) { + if (interrupts & ENISR_RDC) { + /* Ack meaningless DMA complete. */ + outb_p(ENISR_RDC, e8390_base + EN0_ISR); + } + if (interrupts & ENISR_OVER) { + ei_rx_overrun(dev); + } else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) { + /* Got a good (?) packet. */ + ei_receive(dev); + } + /* Push the next to-transmit packet through. */ + if (interrupts & ENISR_TX) { + ei_tx_intr(dev); + } else if (interrupts & ENISR_COUNTERS) { + struct ei_device *ei_local = dev->private; + ei_local->soft_rx_errors += inb_p(e8390_base + EN0_COUNTER0); + ei_local->soft_rx_errors += inb_p(e8390_base + EN0_COUNTER1); + ei_local->missed_packets += inb_p(e8390_base + EN0_COUNTER2); + outb_p(ENISR_COUNTERS, e8390_base + EN0_ISR); /* Ack intr. */ + } + + /* Ignore the transmit errs and reset intr for now. */ + if (interrupts & ENISR_TX_ERR) { + outb_p(ENISR_TX_ERR, e8390_base + EN0_ISR); /* Ack intr. */ + } + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); + } + + if (interrupts && ei_debug) { + printk("%s: unknown interrupt %#2x\n", dev->name, interrupts); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base + E8390_CMD); + outb_p(0xff, e8390_base + EN0_ISR); /* Ack. all intrs. */ + } + dev->interrupt = 0; + return; +} + +/* We have finished a transmit: check for errors and then trigger the next + packet to be sent. */ +static void +ei_tx_intr(struct device *dev) +{ + int e8390_base = dev->base_addr; + int status = inb(e8390_base + EN0_TSR); + struct ei_device *ei_local = dev->private; + + outb_p(ENISR_TX, e8390_base + EN0_ISR); /* Ack intr. */ + if ((status & ENTSR_PTX) == 0) + ei_local->tx_errors++; + else + ei_local->tx_packets++; + +#ifdef PINGPONG + ei_local->txqueue--; + if (ei_local->tx1 < 0) { + if (lasttx != 1 && lasttx != -1) + printk("%s: bogus last_tx_buffer %d, tx1=%d.\n", + ei_local->name, lasttx, ei_local->tx1); + ei_local->tx1 = 0; + dev->tbusy = 0; + if (ei_local->tx2 > 0) { + NS8390_trigger_send(dev, ei_local->tx2, ei_local->tx_start_page + 6); + ei_local->txing = 1; + ei_local->tx2 = -1, + lasttx = 2; + } else + lasttx = 20, ei_local->txing = 0; + } else if (ei_local->tx2 < 0) { + if (lasttx != 2 && lasttx != -2) + printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", + ei_local->name, lasttx, ei_local->tx2); + ei_local->tx2 = 0; + dev->tbusy = 0; + if (ei_local->tx1 > 0) { + NS8390_trigger_send(dev, ei_local->tx1, ei_local->tx_start_page); + ei_local->txing = 1; + ei_local->tx1 = -1; + lasttx = 1; + } else + lasttx = 10, ei_local->txing = 0; + } else + printk("%s: unexpected TX-done interrupt, lasttx=%d.\n", + dev->name, lasttx); +#else + ei_local->txing = 0; + dev->tbusy = 0; +#endif + mark_bh (INET_BH); +} + +/* We have a good packet(s), get it/them out of the buffers. */ + +static void +ei_receive(struct device *dev) +{ + int e8390_base = dev->base_addr; + struct ei_device *ei_local = dev->private; + int rxing_page, this_frame, next_frame, current_offset; + int boguscount = 0; + struct e8390_pkt_hdr rx_frame; + int num_rx_pages = ei_local->stop_page-ei_local->rx_start_page; + + while (++boguscount < 10) { + int size; + + /* Get the rx page (incoming packet pointer). */ + outb_p(E8390_NODMA+E8390_PAGE1, e8390_base + E8390_CMD); + rxing_page = inb_p(e8390_base + EN1_CURPAG); + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base + E8390_CMD); + + /* Remove one frame from the ring. Boundary is alway a page behind. */ + this_frame = inb_p(e8390_base + EN0_BOUNDARY) + 1; + if (this_frame >= ei_local->stop_page) + this_frame = ei_local->rx_start_page; + + /* Someday we'll omit the previous step, iff we never get this message.*/ + if (ei_debug > 0 && this_frame != ei_local->current_page) + printk("%s: mismatched read page pointers %2x vs %2x.\n", + dev->name, this_frame, ei_local->current_page); + + if (this_frame == rxing_page) /* Read all the frames? */ + break; /* Done for now */ + + current_offset = this_frame << 8; + ei_block_input(dev, sizeof(rx_frame), (void *)&rx_frame, + current_offset); + + size = rx_frame.count - sizeof(rx_frame); + + next_frame = this_frame + 1 + ((size+4)>>8); + + /* Check for bogosity warned by 3c503 book: the status byte is never + written. This happened a lot during testing! This code should be + cleaned up someday, and the printk()s should be PRINTK()s. */ + if ( rx_frame.next != next_frame + && rx_frame.next != next_frame + 1 + && rx_frame.next != next_frame - num_rx_pages + && rx_frame.next != next_frame + 1 - num_rx_pages) { +#ifndef EI_DEBUG + ei_local->current_page = rxing_page; + outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY); + continue; +#else + static int last_rx_bogosity = -1; + printk("%s: bogus packet header, status=%#2x nxpg=%#2x sz=%#x (at %#4x)\n", + dev->name, rx_frame.status, rx_frame.next, rx_frame.count, + current_offset); + + if (rx_packets != last_rx_bogosity) { + /* Maybe we can avoid resetting the chip... empty the packet ring. */ + ei_local->current_page = rxing_page; + printk("%s: setting next frame to %#2x (nxt=%#2x, rx_frm.nx=%#2x rx_frm.stat=%#2x).\n", + dev->name, ei_local->current_page, next_frame, + rx_frame.next, rx_frame.status); + last_rx_bogosity = rx_packets; + outb(ei_local->current_page-1, e8390_base+EN0_BOUNDARY); + continue; + } else { + /* Oh no Mr Bill! Last ditch error recovery. */ + printk("%s: recovery failed, resetting at packet #%d..", + dev->name, rx_packets); + sti(); + ei_reset_8390(dev); + NS8390_init(dev, 1); + printk("restarting.\n"); + return; + } +#endif /* EI8390_NOCHECK */ + } + + if ((size < 32 || size > 1535) && ei_debug) + printk("%s: bogus packet size, status=%#2x nxpg=%#2x size=%#x\n", + dev->name, rx_frame.status, rx_frame.next, rx_frame.count); + if ((rx_frame.status & 0x0F) == ENRSR_RXOK) { + int sksize = sizeof(struct sk_buff) + size; + struct sk_buff *skb; + skb = kmalloc(sksize, GFP_ATOMIC); + if (skb != NULL) { + skb->lock = 0; + skb->mem_len = sksize; + skb->mem_addr = skb; + /* 'skb+1' points to the start of sk_buff data area. */ + ei_block_input(dev, size, (void *)(skb+1), + current_offset + sizeof(rx_frame)); + if (dev_rint((void *)skb, size, IN_SKBUFF, dev)) { + printk("%s: receive buffers full.\n", dev->name); + break; + } + } else if (ei_debug) { + printk("%s: Couldn't allocate a sk_buff of size %d.\n", + dev->name, sksize); + break; + } + ei_local->rx_packets++; + } else { + if (ei_debug) + printk("%s: bogus packet, status=%#2x nxpg=%#2x size=%d\n", + dev->name, rx_frame.status, rx_frame.next, rx_frame.count); + ei_local->soft_rx_err_bits |= rx_frame.status, + ei_local->soft_rx_errors++; + } + next_frame = rx_frame.next; + + /* This should never happen, it's here for debugging. */ + if (next_frame >= ei_local->stop_page) { + printk("%s: next frame inconsistency, %#2x..", dev->name, next_frame); + next_frame = ei_local->rx_start_page; + } + ei_local->current_page += 1 + ((size+4)>>8); + ei_local->current_page = next_frame; + outb(next_frame-1, e8390_base+EN0_BOUNDARY); + } + /* If any worth-while packets have been received, dev_rint() + has done a mark_bh(INET_BH) for us and will work on them + when we get to the bottom-half routine. */ + + /* Bug alert! Reset ENISR_OVER to avoid spurious overruns! */ + outb_p(ENISR_RX+ENISR_RX_ERR+ENISR_OVER, e8390_base+EN0_ISR); + return; +} + +/* We have a receiver overrun: we have to kick the 8390 to get it started + again.*/ +static void +ei_rx_overrun(struct device *dev) +{ + int e8390_base = dev->base_addr; + int reset_start_time = jiffies; + struct ei_device *ei_local = dev->private; + + /* We should already be stopped and in page0. Remove after testing. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); + + if (ei_debug) + printk("%s: Receiver overrun.\n", dev->name); + ei_local->rx_overruns++; + + /* The we.c driver does dummy = inb_p( RBCR[01] ); at this point. + It might mean something -- magic to speed up a reset? A 8390 bug?*/ + + /* Wait for reset in case the NIC is doing a tx or rx. This could take up to + 1.5msec, but we have no way of timing something in that range. The 'jiffies' + are just a sanity check. */ + while ((inb_p(e8390_base+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 1) { + printk("%s: reset did not complete at ei_rx_overrun.\n", + dev->name); + NS8390_init(dev, 1); + return; + }; + + { + int old_rx_packets = ei_local->rx_packets; + /* Remove packets right away. */ + ei_receive(dev); + ei_local->rx_overrun_packets += + (ei_local->rx_packets - old_rx_packets); + } + outb_p(0xff, e8390_base+EN0_ISR); + /* Generic 8390 insns to start up again, same as in open_8390(). */ + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, e8390_base + E8390_CMD); + outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ +} + +int +ethif_init(struct device *dev) +{ + if (ei_debug > 1) + printk(version); + + /* The open call may be overridden by the card-specific code. */ + dev->open = &ei_open; + + /* Make up a ei_local structure. */ + dev->private = kmalloc(sizeof(struct ei_device), GFP_KERNEL); + memset(dev->private, 0, sizeof(struct ei_device)); + + if (1 +#ifdef WD80x3 + && ! wdprobe(dev->base_addr, dev) +#endif +#ifdef EL2 + && ! el2autoprobe(dev->base_addr, dev) +#endif +#ifdef NE2000 + && ! neprobe(dev->base_addr, dev) +#endif +#ifdef HPLAN + && ! hpprobe(dev->base_addr, dev) +#endif + && 1 ) { + printk("No ethernet device found.\n"); + kfree(dev->private); + dev->private = NULL; + return 1; /* ENODEV or EAGAIN would be more accurate. */ + } + + return ethdev_init(dev); +} + +/* Initialize the rest of the device structure. */ +int +ethdev_init(struct device *dev) +{ + int i; + + for (i = 0; i < DEV_NUMBUFFS; i++) + dev->buffs[i] = NULL; + + dev->hard_header = eth_hard_header; + dev->add_arp = eth_add_arp; + dev->queue_xmit = dev_queue_xmit; + dev->rebuild_header = eth_rebuild_header; + dev->type_trans = eth_type_trans; + + if (dev->private == NULL) { + dev->private = kmalloc(sizeof(struct ei_device), GFP_KERNEL); + memset(dev->private, 0, sizeof(struct ei_device)); + } + + dev->send_packet = 0; + dev->hard_start_xmit = &ei_start_xmit; + + dev->type = ETHER_TYPE; + dev->hard_header_len = sizeof (struct enet_header); + dev->mtu = 1500; /* eth_mtu */ + dev->addr_len = ETHER_ADDR_LEN; + for (i = 0; i < dev->addr_len; i++) { + dev->broadcast[i]=0xff; + } + return 0; +} + + +/* This page of functions should be 8390 generic */ +/* Follow National Semi's recommendations for initializing the "NIC". */ +void NS8390_init(struct device *dev, int startp) +{ + int e8390_base = dev->base_addr; + struct ei_device *ei_local = dev->private; + int i; + int endcfg = ei_local->word16 ? (0x48 | ENDCFG_WTS) : 0x48; + + /* Follow National Semi's recommendations for initing the DP83902. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */ + outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ + /* Clear the remote byte count registers. */ + outb_p(0x00, e8390_base + EN0_RCNTLO); + outb_p(0x00, e8390_base + EN0_RCNTHI); + /* Set to monitor and loopback mode -- this is vital!. */ + outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ + /* Set the transmit page and receive ring. */ + outb_p(ei_local->tx_start_page, e8390_base + EN0_TPSR); + ei_local->tx1 = ei_local->tx2 = 0; + outb_p(ei_local->rx_start_page, e8390_base + EN0_STARTPG); + outb_p(ei_local->stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ + ei_local->current_page = ei_local->rx_start_page; /* assert boundary+1 */ + outb_p(ei_local->stop_page, e8390_base + EN0_STOPPG); + /* Clear the pending interrupts and mask. */ + outb_p(0xFF, e8390_base + EN0_ISR); + outb_p(0x00, e8390_base + EN0_IMR); + + /* Copy the station address into the DS8390 registers, + and set the multicast hash bitmap to receive all multicasts. */ + cli(); + outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */ + for(i = 0; i < 6; i++) { + outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i); + } + for(i = 0; i < 8; i++) + outb_p(0xff, e8390_base + EN1_MULT + i); + + outb_p(ei_local->rx_start_page, e8390_base + EN1_CURPAG); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); + sti(); + if (startp) { + outb_p(0xff, e8390_base + EN0_ISR); + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base); + outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ + /* 3c503 TechMan says rxconfig only after the NIC is started. */ + outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ + } + return; +} + +/* Trigger a transmit start, assuming the length is valid. */ +static void NS8390_trigger_send(struct device *dev, unsigned int length, + int start_page) +{ + int e8390_base = dev->base_addr; + + ei_status.txing = 1; + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base); + + if (inb_p(e8390_base) & E8390_TRANS) { + printk("%s: trigger_send() called with the transmitter busy.\n", + dev->name); + return; + } + outb_p(length & 0xff, e8390_base + EN0_TCNTLO); + outb_p(length >> 8, e8390_base + EN0_TCNTHI); + outb_p(start_page, e8390_base + EN0_TPSR); + outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -DPINGPONG -I/usr/src/linux/net/tcp -c 8390.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether-pingpong/8390.h b/net/tcpip/newether-pingpong/8390.h new file mode 100644 index 00000000..1a19fe47 --- /dev/null +++ b/net/tcpip/newether-pingpong/8390.h @@ -0,0 +1,148 @@ +/* Generic NS8390 register definitions. */ +/* This file is part of Donald Becker's 8390 drivers. + This file is distributed under the Linux GPL. + Some of these names and comments are from the Crynwr packet drivers. */ + +#ifndef e8390_h +#define e8390_h +#define PINGPONG +#ifdef PINGPONG +#define TX_PAGES 12 +#else +#define TX_PAGES 6 +#endif + +#define ETHER_ADDR_LEN 6 + +/* From 8390.c */ +void ei_interrupt(int reg_ptr); +/* From auto_irq.c */ +extern void autoirq_setup(int waittime); +extern int autoirq_report(int waittime); + +/* Most of these entries should be in 'struct device' (or most of the + things in there should be here!) */ +/* You have one of these per-board */ +struct ei_device { + char *name; + int open:1; + int word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */ + int txing:1; /* Transmit Active */ + void (*reset_8390)(struct device *); + void (*block_output)(struct device *, int, const unsigned char *, int); + int (*block_input)(struct device *, int, char *, int); + unsigned char tx_start_page, rx_start_page, stop_page; + unsigned char current_page; /* Read pointer in buffer */ + unsigned char thin_bit; /* Value to write to the 3c503 E33G_CNTRL */ + unsigned char txqueue; /* Tx Packet buffer queue length. */ + unsigned char in_interrupt; + short tx1, tx2; /* Packet lengths for ping-pong tx. */ + /* The statistics: */ + int tx_packets; + int tx_errors; + int rx_packets; + int soft_rx_errors; + int soft_rx_err_bits; + int missed_packets; + int rx_overruns; + int rx_overrun_packets; +}; + +#define ei_status (*(struct ei_device *)(dev->private)) + +/* Some generic ethernet register configurations. */ +#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ +#define E8390_RX_IRQ_MASK 0x5 +#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ +#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ +#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ +#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ + +/* Register accessed at EN_CMD, the 8390 base addr. */ +#define E8390_STOP 0x01 /* Stop and reset the chip */ +#define E8390_START 0x02 /* Start the chip, clear reset */ +#define E8390_TRANS 0x04 /* Transmit a frame */ +#define E8390_RREAD 0x08 /* Remote read */ +#define E8390_RWRITE 0x10 /* Remote write */ +#define E8390_NODMA 0x20 /* Remote DMA */ +#define E8390_PAGE0 0x00 /* Select page chip registers */ +#define E8390_PAGE1 0x40 /* using the two high-order bits */ +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ + +#define E8390_CMD 0x00 /* The command register (for all pages) */ +/* Page 0 register offsets. */ +#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ +#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ +#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ +#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ +#define EN0_TSR 0x04 /* Transmit status reg RD */ +#define EN0_TPSR 0x04 /* Transmit starting page WR */ +#define EN0_NCR 0x05 /* Number of collision reg RD */ +#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ +#define EN0_FIFO 0x06 /* FIFO RD */ +#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ +#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ +#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ +#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ +#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ +#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ +#define EN0_RSR 0x0c /* rx status reg RD */ +#define EN0_RXCR 0x0c /* RX configuration reg WR */ +#define EN0_TXCR 0x0d /* TX configuration reg WR */ +#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ +#define EN0_DCFG 0x0e /* Data configuration reg WR */ +#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ +#define EN0_IMR 0x0f /* Interrupt mask reg WR */ +#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ + +/* Bits in EN0_ISR - Interrupt status register */ +#define ENISR_RX 0x01 /* Receiver, no error */ +#define ENISR_TX 0x02 /* Transmitter, no error */ +#define ENISR_RX_ERR 0x04 /* Receiver, with error */ +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ +#define ENISR_COUNTERS 0x20 /* Counters need emptying */ +#define ENISR_RDC 0x40 /* remote dma complete */ +#define ENISR_RESET 0x80 /* Reset completed */ +#define ENISR_ALL 0x3f /* Interrupts we will enable */ + +/* Bits in EN0_DCFG - Data config register */ +#define ENDCFG_WTS 0x01 /* word transfer mode selection */ + +/* Page 1 register offsets. */ +#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */ +#define EN1_CURPAG 0x07 /* Current memory page RD WR */ +#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */ + +/* Bits in received packet status byte and EN0_RSR*/ +#define ENRSR_RXOK 0x01 /* Received a good packet */ +#define ENRSR_CRC 0x02 /* CRC error */ +#define ENRSR_FAE 0x04 /* frame alignment error */ +#define ENRSR_FO 0x08 /* FIFO overrun */ +#define ENRSR_MPA 0x10 /* missed pkt */ +#define ENRSR_PHY 0x20 /* physical/multicase address */ +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ +#define ENRSR_DEF 0x80 /* deferring */ + +/* Transmitted packet status, EN0_TSR. */ +#define ENTSR_PTX 0x01 /* Packet transmitted without error */ +/* The other bits in the TX status register mean: + 0x02 The transmit wasn't deferred. + 0x04 The transmit collided at least once. + 0x08 The transmit collided 16 times, and was deferred. + 0x10 The carrier sense was lost (from the ethernet transceiver) + 0x20 A "FIFO underrun" (internal error) occured during transmit. + 0x40 The collision detect "heartbeat" signal was lost. + 0x80 There was an out-of-window collision. + */ + +/* The per-packet-header format. */ +struct e8390_pkt_hdr { + unsigned char status; /* status */ + unsigned char next; /* pointer to next packet. */ + unsigned short count; /* header + packet lenght in bytes */ +}; +#endif /* e8390_h */ diff --git a/net/tcpip/newether-pingpong/Announce b/net/tcpip/newether-pingpong/Announce new file mode 100644 index 00000000..52a6081d --- /dev/null +++ b/net/tcpip/newether-pingpong/Announce @@ -0,0 +1,44 @@ + +Subject: Enhanced Ethercard driver available for alpha test. + +My "8390" Linux ethercard drivers are now available from usra.edu and +super.org in ~ftp/pub/linux/ethercards/*. They'll be at tsx-11 and +sunsite RSN. + +These drivers support all common 8390-based ethernet boards. Currently +"common" is defined as: + + 3Com Products: +* 3Com 3c503 Board loaned by Chance Reschke, USRA.edu (thanks!) + 3Com 3c503/16 and excellent documentation provided by 3Com. + + Clones-n-things + NE1000 Novell and Eagle are useless for documentation, +* NE2000 but copied the designs directly from NatSemi;->. +* Alta Combo(NE2000 clone) + Aritsoft LANtastic AE-2 (NE2000 clone w/ extra memory) + D-Link Ethernet II + + Cabletron products: + E1010 No ID PROM and sketchy info from Ctron means you'll + E1010-x have to compile-in information about your board. + E2010 + E2010-x + + WD/SMC products + WD8003 +* WD8013 Board loaned by Russ Nelson, Crynwr Software. Thanks! + +* I've seen it work myself! + +There is support for the following boards, but since I've only been +able to borrow a thinnet of an HP ethercard I haven't been able to test it: + + HP LAN adaptors +** HP27245 +** HP27247 +** HP27250 + +Thanks are due to the dozens of alpha testers, and special thanks to Chance Reschke <@usra.edu> and Russ Nelson <@crynwr.com> for loaning me ethercards. + + diff --git a/net/tcpip/newether-pingpong/GNUmakefile b/net/tcpip/newether-pingpong/GNUmakefile new file mode 100644 index 00000000..75ebb481 --- /dev/null +++ b/net/tcpip/newether-pingpong/GNUmakefile @@ -0,0 +1,33 @@ +# This file must be named 'GNUmakefile'. When it has that name it +# loaded in preference to the regular 'Makefile' (which it include +# right here) so this has the effect of appending lines to the Makefile. + +include Makefile + +# Add a few files to tcpip.a. +newobjs = 8390.o 3c503.o ne.o wd.o hp.o auto_irq.o +OBJS := $(OBJS) $(newobjs) +tcpip.a: $(newobjs) + +# Set the address and IRQ here. The ne.c and 3c503 driver will autoprobe +# if you set the address or IRQ to zero, so we do that by default. +# +# Add -DEI_NAME="eth0" if you want to be exactly compatible with the default +# driver. This will only work if you don't use the distributed 'we' driver! +# +ether_options := -DEI_NAME=\"eth0\" -DEI8390=0 -DEI8390_IRQ=0 +Space.o: Space.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) $(ether_options) -c Space.c -o $@ + +# Change this to define the set of ethercards your kernel will support. +8390.o: 8390.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -DNE2000 -DWD80x3 -DHPLAN -DEL2 -c 8390.c -o $@ + +# Change this to -DEL2_AUI if you use the AUI port. +3c503.o: 3c503.c 3c503reg.h GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -UEL2_AUI -c 3c503.c -o $@ + +# Change this to -DSHMEM=0xd0000 and -DFORCE_8BIT if you have an old +# (non-EEPROM) wd8003. +wd.o: wd.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -UWD_SHMEM -UFORCE_8BIT -c wd.c -o $@ diff --git a/net/tcpip/newether-pingpong/README b/net/tcpip/newether-pingpong/README new file mode 100644 index 00000000..ca90182e --- /dev/null +++ b/net/tcpip/newether-pingpong/README @@ -0,0 +1,14 @@ +This is a new version of the ethercard drivers. + +The new features are: + + PING-PONG transmit! This can almost double the transmit rate in some + cases. 1MB/sec is now possible!!! + + The 'ne' driver autoselects between the NE1000 and NE2000 modes. + There is a less-intrusive 3c503 probe. + The 3c503 can now be used in non-shared-memory mode. + The HP-LAN non-autoIRQ mode should now work. + The WD driver should now work with some older WD8003 cards, but this + is untested. + \ No newline at end of file diff --git a/net/tcpip/newether-pingpong/auto_irq.c b/net/tcpip/newether-pingpong/auto_irq.c new file mode 100644 index 00000000..c74a9570 --- /dev/null +++ b/net/tcpip/newether-pingpong/auto_irq.c @@ -0,0 +1,110 @@ +/* auto_irq.c: Auto-configure IRQ lines for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + + This code is a general-purpose IRQ line detector for devices with + jumpered IRQ lines. If you can make the device raise an IRQ (and + that IRQ line isn't already being used), these routines will tell + you what IRQ line it's using -- perfect for those oh-so-cool boot-time + device probes! + + To use this, first call autoirq_setup(timeout). TIMEOUT is how many + 'jiffies' (1/18 sec.) to detect other devices that have active IRQ lines, + and can usually be zero at boot. 'autoirq_setup()' returns the bit + vector of nominally-available IRQ lines (lines may be physically in-use, + but not yet registered to a device). + Next, set up your device to trigger an interrupt. + Finally call autoirq_report(TIMEOUT) to find out which IRQ line was + most recently active. The TIMEOUT should usually be zero, but may + be set to the number of jiffies to wait for a slow device to raise an IRQ. + + The idea of using the setup timeout to filter out bogus IRQs came from + the serial driver. +*/ + + +#ifdef version +static char *version="auto_irq.c:v0.01 1993 Donald Becker (becker@super.org)"; +#endif + +/*#include */ +/*#include */ +#include +#include +#include +/*#include */ + +int irqs_busy = 0x01; /* The set of fixed IRQs always enabled */ +int irqs_used = 0x01; /* The set of fixed IRQs sometimes enabled. */ +int irqs_reserved = 0x00; /* An advisory "reserved" table. */ +int irqs_shared = 0x00; /* IRQ lines "shared" among conforming cards.*/ + +static volatile int irq_number; /* The latest irq number we actually found. */ +static volatile int irq_bitmap; /* The irqs we actually found. */ +static int irq_handled; /* The irq lines we have a handler on. */ + +static void autoirq_probe(int irq) +{ + irq_number = irq; + set_bit(irq, (void *)&irq_bitmap); /* irq_bitmap |= 1 << irq; */ + return; +} +struct sigaction autoirq_sigaction = { autoirq_probe, 0, SA_INTERRUPT, NULL}; + +int autoirq_setup(int waittime) +{ + int i, mask; + int timeout = jiffies+waittime; + + irq_number = 0; + irq_bitmap = 0; + irq_handled = 0; + for (i = 0; i < 16; i++) { + if (!irqaction(i, &autoirq_sigaction)) + set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/ + } + /* Update our USED lists. */ + irqs_used |= ~irq_handled; + + /* Hang out at least jiffies waiting for bogus IRQ hits. */ + while (timeout >= jiffies) + ; + + for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) { + if (irq_bitmap & irq_handled & mask) { + irq_handled &= ~mask; + printk(" Spurious interrupt on IRQ %d\n", i); + free_irq(i); + } + } + return irq_handled; +} + +int autoirq_report(int waittime) +{ + int i; + int timeout = jiffies+waittime; + + /* Hang out at least jiffies waiting for the IRQ. */ + while (timeout >= jiffies) + if (irq_number) + break; + + /* Retract the irq handlers that we installed. */ + for (i = 0; i < 16; i++) { + if (test_bit(i, (void *)&irq_handled)) + free_irq(i); + } + return irq_number; +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether-pingpong/hp.c b/net/tcpip/newether-pingpong/hp.c new file mode 100644 index 00000000..531f3f35 --- /dev/null +++ b/net/tcpip/newether-pingpong/hp.c @@ -0,0 +1,319 @@ +/* hp.c: A HP LAN ethernet driver for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This is a driver for the HP LAN adaptors. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = "hp.c:v0.67 3/8/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define port_read_b(port,buf,nr) \ +__asm__("cld;rep;insb"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write_b(port,buf,nr) \ +__asm__("cld;rep;outsb"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define HP_DATAPORT 0x0c /* "Remote DMA" data port. */ +#define HP_ID 0x07 +#define HP_CONFIGURE 0x08 /* Configuration register. */ +#define HP_RUN 0x01 /* 1 == Run, 0 == reset. */ +#define HP_IRQ 0x0E /* Mask for software-configured IRQ line. */ +#define HP_DATAON 0x10 /* Turn on dataport */ +#define NIC_OFFSET 0x10 /* Offset the 8390 registers. */ + +#define HP_START_PG 0x00 /* First page of TX buffer */ +#define HP_8BSTOP_PG 0x80 /* Last page +1 of RX ring */ +#define HP_16BSTOP_PG 0xFF /* Last page +1 of RX ring */ + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; + +int hpprobe(int ioaddr, struct device *dev); +int hpprobe1(int ioaddr, struct device *dev); + +static void hp_reset_8390(struct device *dev); +static int hp_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void hp_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static void hp_init_card(struct device *dev); + +/* The map from IRQ number to HP_CONFIGURE register setting. */ +/* My default is IRQ5 0 1 2 3 4 5 6 7 8 9 10 11 */ +static char irqmap[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0}; + + +/* Probe for an HP LAN adaptor. + Also initialize the card and fill in STATION_ADDR with the station + address. */ + +int hpprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0}; + + if (ioaddr > 0x100) + return hpprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb_p(*port) != 0xff && hpprobe1(*port, dev)) + return dev->base_addr; + return 0; +} + +int hpprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + unsigned char SA_prom[6]; + int tmp; + int hplan; + + printk("HP-LAN ethercard probe at %#3x:", ioaddr); + tmp = inb_p(ioaddr); + if (tmp == 0xFF) { + printk(" not found (nothing there).\n"); + return 0; + } + + for(i = 0; i < sizeof(SA_prom); i++) { + SA_prom[i] = inb(ioaddr + i); + if (i < ETHER_ADDR_LEN && station_addr) { + printk(" %2.2x", SA_prom[i]); + station_addr[i] = SA_prom[i]; + } + } + hplan = (SA_prom[0] == 0x08 && SA_prom[1] == 0x00 && SA_prom[2] == 0x09); + if (hplan == 0) { + printk(" not found (invalid station address prefix).\n"); + return 0; + } + + ei_status.tx_start_page = HP_START_PG; + ei_status.rx_start_page = HP_START_PG + TX_PAGES; + /* Set up the rest of the parameters. */ + if ((tmp = inb_p(HP_ID)) & 0x80) { + ei_status.name = "HP27247"; + ei_status.word16 = 1; + ei_status.stop_page = HP_16BSTOP_PG; /* Safe for now */ + } else { + ei_status.name = "HP27250"; + ei_status.word16 = 0; + ei_status.stop_page = HP_8BSTOP_PG; /* Safe for now */ + } + + /* Set the base address to point to the NIC! */ + dev->base_addr = ioaddr + NIC_OFFSET; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + if (dev->irq < 2) { + int irq_16list[] = { 11, 10, 5, 3, 4, 7, 9, 0}; + int irq_8list[] = { 7, 5, 3, 4, 9, 0}; + int *irqp = ei_status.word16 ? irq_16list : irq_8list; + do { + if (request_irq (dev->irq = *irqp, NULL) != -EBUSY) { + autoirq_setup(0); + /* Twinkle the interrupt, and check if it's seen. */ + outb_p(irqmap[dev->irq] | HP_RUN, ioaddr + HP_CONFIGURE); + outb_p( 0x00 | HP_RUN, ioaddr + HP_CONFIGURE); + if (dev->irq == autoirq_report(0) /* It's a good IRQ line! */ + && request_irq (dev->irq, &ei_interrupt) == 0) { + printk(" got IRQ %d", dev->irq); + break; + } else + printk(" IRQ%d busy..", dev->irq); + } + } while (*++irqp); + if (*irqp == 0) { + printk(" unable to find an free IRQ line.\n"); + return 0; + } + } else { + if (dev->irq == 2) + dev->irq = 9; + if (irqaction(dev->irq, &ei_sigaction)) { + printk (" unable to get IRQ %d.\n", dev->irq); + return 0; + } + } + + printk("\n%s: %s using IRQ %d.\n", dev->name, ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + + ei_status.reset_8390 = &hp_reset_8390; + ei_status.block_input = &hp_block_input; + ei_status.block_output = &hp_block_output; + hp_init_card(dev); + return dev->base_addr; +} + +static void +hp_reset_8390(struct device *dev) +{ + int hp_base = dev->base_addr - NIC_OFFSET; + int saved_config = inb_p(hp_base + HP_CONFIGURE); + int reset_start_time = jiffies; + + if (ei_debug > 1) printk("resetting the 8390 time=%d...", jiffies); + outb_p(0x00, hp_base + HP_CONFIGURE); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + break; + } + } + + outb_p(saved_config, hp_base + HP_CONFIGURE); + while ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk("%s: hp_reset_8390() did not complete.\n", dev->name); + return; + } + if (ei_debug > 1) printk("8390 reset done.", jiffies); +} + +/* Block input and output, similar to the Crynwr packet driver. If you + porting to a new ethercard look at the packet driver source for hints. + The HP LAN doesn't use shared memory -- we put the packet + out through the "remote DMA" dataport. */ + +static int +hp_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int nic_base = dev->base_addr; + int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); + int xfer_count = count; + + outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base); + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); + outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, nic_base); + if (ei_status.word16) { + port_read(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1); + if (count & 0x01) + buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++; + } else { + port_read_b(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count); + } + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + /* Check only the lower 8 bits so we can ignore ring wrap. */ + if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff)) + printk("%s: RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n", + dev->name, ring_offset + xfer_count, addr); + } + outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); + return ring_offset + count; +} + +static void +hp_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page) +{ + int nic_base = dev->base_addr; + int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); + + outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + if (ei_status.word16 && (count & 0x01)) + count++; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base); + +#ifdef ei8390_bug + /* Handle the read-before-write bug the same way as the + Crynwr packet driver -- the NatSemi method doesn't work. */ + outb_p(0x42, nic_base + EN0_RCNTLO); + outb_p(0, nic_base + EN0_RCNTHI); + outb_p(0xff, nic_base + EN0_RSARLO); + outb_p(0x00, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + /* Make certain that the dummy read has occured. */ + inb_p(0x61); + inb_p(0x61); +#endif + + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(0x00, nic_base + EN0_RSARLO); + outb_p(start_page, nic_base + EN0_RSARHI); + + outb_p(E8390_RWRITE+E8390_START, nic_base); + if (ei_status.word16) { + /* Use the 'rep' sequence for 16 bit boards. */ + port_write(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1); + } else { + port_write_b(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count); + } + + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */ + + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + if ((start_page << 8) + count != addr) + printk("%s: TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n", + dev->name, (start_page << 8) + count, addr); + } + outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); + return; +} + +/* This function resets the ethercard if something screws up. */ +static void +hp_init_card(struct device *dev) +{ + int irq = dev->irq; + NS8390_init(dev, 0); + outb_p(irqmap[irq&0x0f] | HP_RUN, + dev->base_addr - NIC_OFFSET + HP_CONFIGURE); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c hp.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether-pingpong/ne.c b/net/tcpip/newether-pingpong/ne.c new file mode 100644 index 00000000..595da7d9 --- /dev/null +++ b/net/tcpip/newether-pingpong/ne.c @@ -0,0 +1,379 @@ +/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with many 8390-based ethernet boards. Currently + it support the NE1000, NE2000 (and clones), and some Cabletron products. + 8-bit ethercard support is enabled with #define EI_8BIT + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +/* Routines for the NatSemi-based designs (NE[12]000). */ + +static char *version = + "ne.c:v0.50 2/19/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define port_read_b(port,buf,nr) \ +__asm__("cld;rep;insb"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write_b(port,buf,nr) \ +__asm__("cld;rep;outsb"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define EN_CMD (dev->base_addr) +#define NE_BASE (dev->base_addr) +#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ +#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ + +#define NE1SM_START_PG 0x20 /* First page of TX buffer */ +#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ +#define NESM_START_PG 0x40 /* First page of TX buffer */ +#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; + +int neprobe(int ioaddr, struct device *dev); +static int neprobe1(int ioaddr, struct device *dev, int verbose); + +static void ne_reset_8390(struct device *dev); +static int ne_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void ne_block_output(struct device *dev, const int count, + const unsigned char *buf, const int start_page); + + +/* Probe for various non-shared-memory ethercards. + + NEx000-clone boards have a Station Address PROM (SAPROM) in the packet + buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of + the SAPROM, while other supposed NE2000 clones must be detected by their + SA prefix. + + Reading the SAPROM from a word-wide card with the 8390 set in byte-wide + mode results in doubled values, which can be detected and compansated for. + + The probe is also responsible for initializing the card and filling + in the 'dev' and 'ei_status' structures. + + We use the minimum memory size for some ethercard product lines, iff we can't + distinguish models. You can increase the packet buffer size by setting + PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are: + E1010 starts at 0x100 and ends at 0x2000. + E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory") + E2010 starts at 0x100 and ends at 0x4000. + E2010-x starts at 0x100 and ends at 0xffff. */ + +int neprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x280, 0x320, 0x340, 0x360, 0}; + + if (ioaddr > 0x100) + return neprobe1(ioaddr, dev, 1); + + for (port = &ports[0]; *port; port++) + if (inb_p(*port) != 0xff && neprobe1(*port, dev, 0)) + return dev->base_addr = *port; + return 0; +} + +static int neprobe1(int ioaddr, struct device *dev, int verbose) +{ + int i; + unsigned char SA_prom[32]; + int wordlength = 2; + int neX000, ctron, dlink; + + + if ( inb_p(ioaddr) == 0xFF) { + if (verbose) printk("8390 ethercard probe at %#3x failed.\n", ioaddr); + return 0; + } + + printk("8390 ethercard probe at %#3x:", ioaddr); + + /* Read the 16 bytes of station address prom, returning 1 for + an eight-bit interface and 2 for a 16-bit interface. + We must first initialize registers, similar to NS8390_init(eifdev, 0). + We can't reliably read the SAPROM address without this. + (I learned the hard way!). */ + { + struct {char value, offset; } program_seq[] = { + {E8390_NODMA+E8390_PAGE0+E8390_STOP, EN_CMD}, /* Select page 0 */ + {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ + {0x00, EN0_RCNTLO}, /* Clear the count regs. */ + {0x00, EN0_RCNTHI}, + {0x00, EN0_IMR}, /* Mask completion irq. */ + {0xFF, EN0_ISR}, + {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ + {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ + {32, EN0_RCNTLO}, + {0x00, EN0_RCNTHI}, + {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ + {0x00, EN0_RSARHI}, + {E8390_RREAD+E8390_START, EN_CMD}, + }; + for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) + outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); + } + for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) { + SA_prom[i] = inb_p(ioaddr + NE_DATAPORT); + SA_prom[i+1] = inb_p(ioaddr + NE_DATAPORT); + if (SA_prom[i] != SA_prom[i+1]) + wordlength = 1; + } + + if (wordlength == 2) { + /* We must set the 8390 for word mode, AND RESET IT. */ + int tmp; + outb_p(0x49, ioaddr + EN0_DCFG); + tmp = inb_p(NE_BASE + NE_RESET); + ei_status.word16 = 1; + outb(tmp, NE_BASE + NE_RESET); + /* Un-double the SA_prom values. */ + for (i = 0; i < 16; i++) + SA_prom[i] = SA_prom[i+i]; + } else + ei_status.word16 = 0; + +#if defined(show_all_SAPROM) + /* If your ethercard isn't detected define this to see the SA_PROM. */ + for(i = 0; i < sizeof(SA_prom); i++) + printk(" %2.2x", SA_prom[i]); +#else + for(i = 0; i < ETHER_ADDR_LEN; i++) { + dev->dev_addr[i] = SA_prom[i]; + printk(" %2.2x", SA_prom[i]); + } +#endif + + neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); + ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); + dlink = (SA_prom[0] == 0x00 && SA_prom[1] == 0xDE && SA_prom[2] == 0x01); + + /* Set up the rest of the parameters. */ + if (neX000 && wordlength == 2) { + ei_status.name = "NE2000"; + ei_status.tx_start_page = NESM_START_PG; + ei_status.stop_page = NESM_STOP_PG; + } else if (neX000 || dlink) { + ei_status.name = neX000 ? "NE1000" : "D-Link"; + ei_status.tx_start_page = NE1SM_START_PG; + ei_status.stop_page = NE1SM_STOP_PG; + } else if (ctron) { + ei_status.name = "Cabletron"; + ei_status.tx_start_page = 0x01; + ei_status.stop_page = (wordlength == 2) ? 0x40 : 0x20; + } else { + printk(" not found.\n"); + return 0; + } + ei_status.rx_start_page = ei_status.tx_start_page + TX_PAGES; +#ifdef PACKETBUF_MEMSIZE + /* Allow the packet buffer size to be overridden by know-it-alls. */ + ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; +#endif + dev->base_addr = ioaddr; + + if (dev->irq < 2) { + int nic_base = dev->base_addr; + autoirq_setup(0); + outb_p(0x50, nic_base + EN0_IMR); /* Enable one interrupt. */ + outb_p(0x00, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(E8390_RREAD+E8390_START, nic_base); /* Trigger it... */ + outb_p(0x00, nic_base + EN0_IMR); /* Mask it again. */ + dev->irq = autoirq_report(0); + if (ei_debug > 2) + printk(" autoirq is %d", dev->irq); + } else if (dev->irq == 2) + /* Fixup for users that don't know that IRQ 2 is really IRQ 9, + or don't know which one to set. */ + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + { int irqval = irqaction (dev->irq, &ei_sigaction); + if (irqval) { + printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); + return 0; + } + } + + printk("\n%s: %s found, using IRQ %d.\n", + dev->name, ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + ei_status.reset_8390 = &ne_reset_8390; + ei_status.block_input = &ne_block_input; + ei_status.block_output = &ne_block_output; + NS8390_init(dev, 0); + return dev->base_addr; +} + +static void +ne_reset_8390(struct device *dev) +{ + int tmp = inb_p(NE_BASE + NE_RESET); + int reset_start_time = jiffies; + + if (ei_debug > 1) printk("resetting the 8390 t=%d...", jiffies); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + outb_p(tmp, NE_BASE + NE_RESET); + return; + } + } + + outb_p(tmp, NE_BASE + NE_RESET); + while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk("%s: ne_reset_8390() did not complete.\n", dev->name); + break; + } +} + +/* Block input and output, similar to the Crynwr packet driver. If you + porting to a new ethercard look at the packet driver source for hints. + The NEx000 doesn't share it on-board packet memory -- you have to put + the packet out through the "remote DMA" dataport using outb. */ + +static int +ne_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int xfer_count = count; + int nic_base = NE_BASE; + + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, EN_CMD); + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); + outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + if (ei_status.word16) { + port_read(NE_BASE + NE_DATAPORT,buf,count>>1); + if (count & 0x01) + buf[count-1] = inb(NE_BASE + NE_DATAPORT), xfer_count++; + } else { + port_read_b(NE_BASE + NE_DATAPORT, buf, count); + } + + /* This was for the ALPHA version only, but enough people have + encountering problems that it is still here. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int addr, tries = 10; + do { + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here + -- it's broken! Check the "DMA" address instead. */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + addr = (high << 8) + low; + if (((ring_offset + xfer_count) & 0xff) == low) + return ring_offset + count; + } while (--tries > 0); + printk("%s: RX transfer address mismatch, %#4.4x (should be) vs. %#4.4x (actual).\n", + dev->name, ring_offset + xfer_count, addr); + } + return ring_offset + count; +} + +static void +ne_block_output(struct device *dev, int count, + const unsigned char *buf, const int start_page) +{ + int retries = 0; + int nic_base = NE_BASE; + + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + if (ei_status.word16 && (count & 0x01)) + count++; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, EN_CMD); + + retry: +#if defined(rw_bugfix) + /* Handle the read-before-write bug the same way as the + Crynwr packet driver -- the NatSemi method doesn't work. + Actually this doesn't aways work either, but if you have + problems with your NEx000 this is better than nothing! */ + outb_p(0x42, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(0x42, nic_base + EN0_RSARLO); + outb_p(0x00, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + /* Make certain that the dummy read has occured. */ + SLOW_DOWN_IO; + SLOW_DOWN_IO; + SLOW_DOWN_IO; +#endif /* rw_bugfix */ + + /* Now the normal output. */ + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(0x00, nic_base + EN0_RSARLO); + outb_p(start_page, nic_base + EN0_RSARHI); + + outb_p(E8390_RWRITE+E8390_START, EN_CMD); + if (ei_status.word16) { + port_write(NE_BASE + NE_DATAPORT, buf, count>>1); + } else { + port_write_b(NE_BASE + NE_DATAPORT, buf, count); + } + + /* This was for the ALPHA version only, but enough people have + encountering problems that it is still here. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int addr, tries = 10; + do { + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here + -- it's broken! Check the "DMA" address instead. */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + addr = (high << 8) + low; + if ((start_page << 8) + count == addr) + return; + } while (--tries > 0); + printk("%s: Packet buffer transfer address mismatch on TX, %#4.4x vs. %#4.4x.\n", + dev->name, (start_page << 8) + count, addr); + if (retries++ == 0) + goto retry; + } + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether-pingpong/wd.c b/net/tcpip/newether-pingpong/wd.c new file mode 100644 index 00000000..614bbe1f --- /dev/null +++ b/net/tcpip/newether-pingpong/wd.c @@ -0,0 +1,334 @@ +/* wd.c: A WD80x3 ethernet driver for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This is a driver for the WD8003 and WD8013 ethercards. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + + Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013. +*/ + +static char *version = + "wd.c:v0.66 3/7/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; + +int wdprobe(int ioaddr, struct device *dev); +int wdprobe1(int ioaddr, struct device *dev); + +static void wd_reset_8390(struct device *dev); +static int wd_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void wd_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static int wd_close_card(struct device *dev); + + +#define WD_START_PG 0x00 /* First page of TX buffer */ +#define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */ +#define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */ + +#define WD_CMDREG 0 /* Offset to ASIC command register. */ +#define WD_RESET 0x80 /* Board reset, in WD_CMDREG. */ +#define WD_MEMENB 0x40 /* Enable the shared memory. */ +#define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */ +#define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */ +#define NIC16 0x40 /* Enable 16 bit access from the 8390. */ +#define WD_NIC_OFFSET 16 /* Offset to the 8390 NIC from the base_addr. */ + +/* Probe for the WD8003 and WD8013. These cards have the station + address PROM at I/O ports +8 to +13, with a checksum + following. The routine also initializes the card and fills the + station address field. */ + +int wdprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x280, 0}; + + if (ioaddr > 0x100) + return wdprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb(*port) != 0xff && wdprobe1(*port, dev)) + return *port; + return 0; +} + +int wdprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + int checksum = 0; + int ancient = 0; /* An old card without config registers. */ + +#if defined(EI_DEBUG) && EI_DEBUG > 2 + printk("WD80x3 ethercard at %#3x:", ioaddr); + for (i = 0; i < 16; i++) { + printk(" %2.2X", inb(ioaddr+i)); + } + printk("\n"); + printk("WD80x3 ethercard at %#3x:", ioaddr+i); + for (;i < 33; i++) { + printk(" %2.2X", inb(ioaddr+i)); + } + printk("\n"); +#endif + printk("WD80x3 ethercard probe at %#3x:", ioaddr); + for (i = 0; i < 8; i++) { + int inval = inb(ioaddr + 8 + i); + checksum += inval; + if (i < 6) + printk(" %2.2X", (station_addr[i] = inval)); + } + + if ((checksum & 0xff) != 0xFF) { + printk(" not found (%#2.2x).\n", checksum); + return 0; + } + + ei_status.name = "WD8003"; + ei_status.word16 = 0; + + /* This method of checking for a 16-bit board is borrowed from the + we.c driver. A simpler method is just to look in ASIC reg. 0x03. + I'm comparing the two method in alpha test to make certain they + return the same result. */ +#ifndef FORCE_8BIT /* Same define as we.c. */ + /* check for 16 bit board - it doesn't have register 0/8 aliasing */ + for (i = 0; i < 8; i++) + if (inb(ioaddr+i) != inb(ioaddr+8+i)) + break; + if (i != 8) { + int tmp = inb(ioaddr+1); /* fiddle with 16bit bit */ + outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */ + if (((inb( ioaddr+1) & 0x01) == 0x01) /* A 16 bit card */ + && (tmp & 0x01) == 0x01 ) { /* In a 16 slot. */ + int asic_reg5 = inb(ioaddr+WD_CMDREG5); + /* Magic to set ASIC to word-wide mode. */ + outb( ISA16 | NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5); + outb(tmp, ioaddr+1); + ei_status.name = "WD8013"; + ei_status.word16 = 1; /* We have a 16bit board here! */ + } + outb(tmp, ioaddr+1); /* Restore original reg1 value. */ + } else + ancient = 1; +#endif /* not FORCE_8BIT */ + +#ifndef final_version + if ( !ancient && (inb(ioaddr+1) & 0x01) != (ei_status.word16 & 0x01)) + printk("\nWD80?3: Bus width conflict, %d (probe) != %d (reg report).", + ei_status.word16 ? 16:8, (inb(ioaddr+1) & 0x01) ? 16 : 8); +#endif + +#if defined(WD_SHMEM) && WD_SHMEM > 0x80000 + /* Allow an override. */ + dev->mem_start = WD_SHMEM; +#else + if (dev->mem_start == 0) { + dev->mem_start = ((inb(ioaddr)&0x3f) << 13) + + (ei_status.word16 ? (inb(ioaddr+WD_CMDREG5)&0x1f)<<19 : 0x80000); + if (dev->mem_start < 0xc0000) /* Sanity and old 8003 check */ + dev->mem_start = 0xd0000; + } +#endif + + /* The 8390 isn't at the base address -- the ASIC regs are there! */ + dev->base_addr = ioaddr+WD_NIC_OFFSET; + + ei_status.tx_start_page = WD_START_PG; + ei_status.rx_start_page = WD_START_PG + TX_PAGES; + ei_status.stop_page = ei_status.word16 ? WD13_STOP_PG : WD03_STOP_PG; + + dev->rmem_start = dev->mem_start + TX_PAGES*256; + dev->mem_end = dev->rmem_end + = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256; +#if defined(EI_DEBUG) && EI_DEBUG > 3 + memset((void*)dev->mem_start, 0x42052465, + (ei_status.stop_page - WD_START_PG)*256); +#endif + if (dev->irq < 2) { + int irqmap[] = {9,3,5,7,10,11,15,4}; + dev->irq = irqmap[((inb(ioaddr+4) >> 5) & 0x03) + + (inb(ioaddr+1) & 0x04)]; + } else if (dev->irq == 2) + /* Fixup for users that don't know that IRQ 2 is really IRQ 9, + or don't know which one to set. */ + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + { int irqval = irqaction (dev->irq, &ei_sigaction); + if (irqval) { + printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); + return 0; + } + } + + printk("\n%s: %s using IRQ %d with shared memory at %#x-%#x.\n", + dev->name, ei_status.name, dev->irq, dev->mem_start, dev->mem_end-1); + if (ei_debug > 1) + printk(version); + + if (ei_debug > 2) + printk("%s: Address read from register is %#x, setting address %#x\n", + ei_status.name, + ((inb(ioaddr+WD_CMDREG5)&0x1f)<<19) + ((inb(ioaddr)&0x3f) << 13), + dev->mem_start); + /* Map in the shared memory. This is a little risky, since using + the stuff the user supplied is probably a bad idea. */ + outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), ioaddr); /* WD_CMDREG */ + if (ei_status.word16) + outb( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), ioaddr+WD_CMDREG5); + + ei_status.reset_8390 = &wd_reset_8390; + ei_status.block_input = &wd_block_input; + ei_status.block_output = &wd_block_output; + dev->stop = &wd_close_card; + NS8390_init(dev, 0); + + return dev->base_addr; +} + +static void +wd_reset_8390(struct device *dev) +{ + int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + int reset_start_time = jiffies; + + outb(WD_RESET, wd_cmd_port); + if (ei_debug > 1) printk("resetting the WD80x3 t=%d...", jiffies); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + break; + } + } + + outb(0x00, wd_cmd_port); + while ((inb(dev->base_addr+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk("%s: wd_reset_8390() did not complete.\n", dev->name); + break; + } +#if defined(EI_DEBUG) && EI_DEBUG > 2 + { + int i; + printk("WD80x3 ethercard at %#3x:", wd_cmd_port); + for (i = 0; i < 16; i++) { + printk(" %2.2X", inb(wd_cmd_port+i)); + } + printk("\nWD80x3 ethercard at %#3x:", wd_cmd_port); + for (;i < 33; i++) { + printk(" %2.2X", inb(wd_cmd_port+i)); + } + printk("\n"); + } +#endif + /* Set up the ASIC registers, just in case something changed them. */ + outb((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port); /* WD_CMDREG */ + if (ei_status.word16) + outb( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5); + +} + +/* Block input and output are easy on shared memory ethercards, and trivial + on the Western digital card where there is no choice of how to do it. */ + +static int +wd_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + void *xfer_start = (void *)(dev->mem_start + ring_offset - (WD_START_PG<<8)); +#ifdef mapout + int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + int mem_val = inb(wd_cmdreg); + /* Map in the shared memory. */ + outb(mem_val|WD_MEMENB, wd_cmdreg); +#endif + if (xfer_start + count > (void*) dev->rmem_end) { + /* We must wrap the input move. */ + int semi_count = (void*)dev->rmem_end - xfer_start; + memcpy(buf, xfer_start, semi_count); + count -= semi_count; + memcpy(buf + semi_count, (char *)dev->rmem_start, count); + return dev->rmem_start + count; + } + memcpy(buf, xfer_start, count); + if (ei_debug > 4) { + unsigned short *board = xfer_start; + printk("%s: wd8013 block_input(cnt=%d offset=%3x addr=%#x) = %2x %2x %2x...\n", + dev->name, count, ring_offset, xfer_start, + board[-1], board[0], board[1]); + } +#ifdef mapout + outb(mem_val & ~WD_MEMENB, wd_cmdreg); /* WD_CMDREG: Map out the shared memory. */ +#endif + return ring_offset + count; +} + +/* This could only be outputting to the transmit buffer. The + ping-pong transmit setup doesn't work with this yet. */ +static void +wd_block_output(struct device *dev, int count, const unsigned char *buf, int start_page) +{ + unsigned char *shmem = (void *)dev->mem_start + ((start_page - WD_START_PG)<<8); +#ifdef mapout + int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + int mem_val = inb(wd_cmdreg); + /* Map in the shared memory. */ + outb(mem_val|WD_MEMENB, wd_cmdreg); +#endif + memcpy(shmem, buf, count); + if (ei_debug > 4) + printk("%s: wd80*3 block_output(addr=%#x cnt=%d) -> %2x=%2x %2x=%2x %d...\n", + shmem, count, shmem[23], buf[23], shmem[24], buf[24], memcmp(shmem,buf,count)); +#ifdef mapout + outb(mem_val & ~WD_MEMENB, wd_cmdreg); /* WD_CMDREG: Map out the shared memory. */ +#endif +} + +/* This function resets the ethercard if something screws up. */ +static int +wd_close_card(struct device *dev) +{ + if (ei_debug > 1) + printk("%s: Shutting down ethercard.\n", dev->name); + NS8390_init(dev, 0); + /* Turn off the shared memory. */ + outb((((dev->mem_start>>13) & 0x3f)), + dev->base_addr-WD_NIC_OFFSET); /* WD_CMDREG */ + return 0; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c wd.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether.taz b/net/tcpip/newether.taz new file mode 100644 index 00000000..86767b07 Binary files /dev/null and b/net/tcpip/newether.taz differ diff --git a/net/tcpip/newether/3c503.c b/net/tcpip/newether/3c503.c new file mode 100644 index 00000000..54a122fd --- /dev/null +++ b/net/tcpip/newether/3c503.c @@ -0,0 +1,340 @@ +/* 3c503.c: A shared-memory NS8390 ethernet driver for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with the 3c503 and 3c503/16. It must be used + in shared memory mode. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = "3c503.c:v0.28 1/28/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include + +#include "dev.h" + +#include "8390.h" +#include "3c503reg.h" +#define EL2AUTOPROBE + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int etherlink2 = 0; + +int el2autoprobe(int ioaddr, struct device *dev); +int el2probe(int ioaddr, struct device *dev); + +static void el2_reset_8390(struct device *dev); +static void el2_init_card(struct device *dev); +static void el2_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static int el2_block_input(struct device *dev, int count, char *buf, + int ring_offset); + + +int +el2autoprobe(int ioaddr, struct device *dev) +{ + int *addr, addrs[] = { 0xddfff, 0xd9fff, 0xcdfff, 0xc9fff, 0}; + int ports[] = {0, 0x300, 0x310, 0x330, 0x350, 0x250, 0x280, 0x2a0, 0x2e0, 0}; + + /* Non-autoprobe case first: */ + if (ioaddr > 0) + if (el2probe(ioaddr, dev)) + return dev->base_addr = ioaddr; + else + return 0; + + /* We check for a memory-mapped 3c503 board by looking at the + end of boot PROM space (works even if a PROM isn't there). */ + for (addr = addrs; *addr; addr++) { + unsigned int base_bits = *(unsigned char *)*addr, i; + /* Find first set bit. */ + for(i = 8; i; i--, base_bits >>= 1) + if (base_bits & 0x1) + break; + if (base_bits == 1 && el2probe(ports[i], dev)) + return dev->base_addr = ports[i]; + } +#ifdef notdef + /* If it's not memory mapped, we don't care to find it. I haven't + tested the non-memory-mapped code. */ + /* It's not memory mapped -- try all of the locations that aren't + obviously empty. */ + { int *port; + for (port = &ports[1]; *port; port++) + if (inb_p(*port) != 0xff && el2probe(*port, dev)) + return dev->base_addr = *port; + } +#endif + return 0; +} + +/* Probe for the Etherlink II card at I/O port base IOADDR, + returning non-zero on sucess. If found, set the station + address and memory parameters in DEVICE. */ +int +el2probe(int ioaddr, struct device *dev) +{ + int i, found, mem_jumpers; + unsigned char *station_addr = dev->dev_addr; + + /* We verify that it's a 3C503 board by checking the first three octets + of its ethernet address. */ + printk("3c503 probe at %#3x:", ioaddr); + outb_p(ECNTRL_RESET|ECNTRL_THIN, ioaddr + 0x406); /* Reset it... */ + outb_p(ECNTRL_THIN, ioaddr + 0x406); + /* Map the station addr PROM into the lower I/O ports. */ + outb(ECNTRL_SAPROM|ECNTRL_THIN, ioaddr + 0x406); + for (i = 0; i < ETHER_ADDR_LEN; i++) { + printk(" %2.2X", (station_addr[i] = inb(ioaddr + i))); + } + /* Map the 8390 back into the window. */ + outb(ECNTRL_THIN, ioaddr + 0x406); + found =( station_addr[0] == 0x02 + && station_addr[1] == 0x60 + && station_addr[2] == 0x8c); + if (! found) { + printk(" 3C503 not found.\n"); + return 0; + } + + /* Probe for, turn on and clear the board's shared memory. */ + mem_jumpers = inb(ioaddr + 0x404); /* E33G_ROMBASE */ + if (ei_debug > 2) printk(" memory jumpers %2.2x ", mem_jumpers); + outb(EGACFR_IRQOFF, E33G_GACFR); /* Enable RAM */ + if ((mem_jumpers & 0xf0) == 0) { + dev->mem_start = 0; + if (ei_debug > 1) printk(" no shared memory "); + } else { + dev->mem_start = ((mem_jumpers & 0xc0) ? 0xD8000 : 0xC8000) + + ((mem_jumpers & 0xA0) ? 0x4000 : 0); + +#define EL2_MEMSIZE (EL2SM_STOP_PG - EL2SM_START_PG)*256 +#ifdef EL2MEMTEST + { /* Check the card's memory. */ + int *mem_base = (int *)dev->mem_start; + int memtest_value = 0xbbadf00d; + mem_base[0] = 0xba5eba5e; + for (i = 1; i < EL2_MEMSIZE/sizeof(mem_base[0]); i++) { + mem_base[i] = memtest_value; + if (mem_base[0] != 0xba5eba5e + || mem_base[i] != memtest_value) { + printk(" memory failure or memory address conflict.\n"); + dev->mem_start = 0; + break; + } + memtest_value += 0x55555555; + mem_base[i] = 0; + } + } +#endif /* EL2MEMTEST */ + /* Divide the on-board memory into a single maximum-sized transmit + (double-sized for ping-pong transmit) buffer at the base, and + use the rest as a receive ring. */ + dev->mem_end = dev->rmem_end = dev->mem_start + EL2_MEMSIZE; + dev->rmem_start = TX_PAGES*256 + dev->mem_start; + } + if (ei_debug > 2) + printk("\n3c503: memory params start=%#5x rstart=%#5x end=%#5x rend=%#5x.\n", + dev->mem_start, dev->rmem_start, dev->mem_end, dev->rmem_end); + + /* Finish setting the board's parameters. */ + etherlink2 = 1; + ei_status.tx_start_page = EL2SM_START_PG; + ei_status.rx_start_page = EL2SM_START_PG + TX_PAGES; + ei_status.stop_page = EL2SM_STOP_PG; + ei_status.reset_8390 = &el2_reset_8390; + ei_status.block_input = &el2_block_input; + ei_status.block_output = &el2_block_output; +/* This should be probed for (or set via an ioctl()) at run-time someday. */ +#ifdef EI8390_THICK + ei_status.thin_bit = 0; +#else + ei_status.thin_bit = ECNTRL_THIN; +#endif + + if (dev->irq <= 0) + dev->irq = 5; /* Autoprobe guess... */ + if (dev->irq == 2) + dev->irq = 9; + else if (dev->irq != 9 && (dev->irq > 5 || dev->irq < 3)) { + printk("\n3c503: configured interrupt number %d out of range.\n", + dev->irq); + return 0; + } + if (irqaction (dev->irq, &ei_sigaction)) { + printk ("\n3c503: Unable to get IRQ%d.\n", dev->irq); + /* We could look for other free interrupts here, or something... */ + return 0; + } + + el2_init_card(dev); + + if (dev->mem_start) + printk("3c503 found, memory at %#6x, IRQ %d\n", + dev->mem_start, dev->irq); + else + printk(" 3c503 found, no shared memory, IRQ %d\n", dev->irq); + if (ei_debug > 2) + printk(version); + + return ioaddr; +} + +/* This is called whenever we have a unrecoverable failure: + transmit timeout + Bad ring buffer packet header + */ +static void +el2_reset_8390(struct device *dev) +{ + if (ei_debug > 1) printk("3c503: Resetting the board..."); + outb_p(ECNTRL_RESET|ECNTRL_THIN, E33G_CNTRL); + ei_status.txing = 0; + outb_p(ei_status.thin_bit, E33G_CNTRL); + el2_init_card(dev); + if (ei_debug > 1) printk("done\n"); +} + +/* Initialize the 3c503 GA registers after a reset. */ +static void +el2_init_card(struct device *dev) +{ + /* Unmap the station PROM and select the DIX or BNC connector. */ + outb_p(ei_status.thin_bit, E33G_CNTRL); + + /* Set ASIC copy of rx's first and last+1 buffer pages */ + /* These must be the same as in the 8390. */ + outb(ei_status.rx_start_page, E33G_STARTPG); + outb(ei_status.stop_page, E33G_STOPPG); + + /* Point the vector pointer registers somewhere ?harmless?. */ + outb(0xff, E33G_VP2); /* Point at the ROM restart location 0xffff0 */ + outb(0xff, E33G_VP1); + outb(0x00, E33G_VP0); + /* Turn off all interrupts until we're opened. */ + outb_p(0x00, dev->base_addr + EN0_IMR); + outb_p(EGACFR_IRQOFF, E33G_GACFR); + + /* Set the interrupt line. */ + outb_p((0x04 << (dev->irq == 9 ? 2 : dev->irq)), E33G_IDCFR); + outb_p(8, E33G_DRQCNT); /* Set burst size to 8 */ + outb_p(0x20, E33G_DMAAH); /* Put a valid addr in the GA DMA */ + outb_p(0x00, E33G_DMAAL); + return; /* We always succeed */ +} + +/* Either use the shared memory (if enabled on the board) or put the packet + out through the ASIC FIFO. The latter is probably much slower. */ +static void +el2_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page) +{ + int i; /* Buffer index */ + int boguscount = 0; /* timeout counter */ + if (dev->mem_start) { /* Shared memory transfer */ + void *dest_addr = (void *)(dev->mem_start + + ((start_page - ei_status.tx_start_page) << 8)); + outb(EGACFR_NORM, E33G_GACFR); /* Enable RAM */ + memcpy(dest_addr, buf, count); + if (ei_debug > 2 && memcmp(dest_addr, buf, count)) + printk("3c503: send_packet() bad memory copy @ %#5x.\n", + dest_addr); + else if (ei_debug > 4) + printk("3c503: send_packet() good memory copy @ %#5x.\n", + dest_addr); + return; + } + /* Set up then start the internal memory transfer to Tx Start Page */ + outb(0x00, E33G_DMAAL); + outb(start_page, E33G_DMAAH); + outb(ei_status.thin_bit | ECNTRL_OUTPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. I think it is possible + to output 8 bytes between each check of the status bit. */ + for(i = 0; i < count; i++) { + if (count % 8 == 7) + while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) + if (++boguscount > 32) { + printk(EI_NAME": fifo blocked in el2_block_output.\n"); + return; + } + outb(buf[i], E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + return; +} + +/* Returns the new ring pointer. */ +static int +el2_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int boguscount = 0; + int end_of_ring = dev->rmem_end; + ring_offset -= (EL2SM_START_PG<<8); + + /* Maybe enable shared memory just be to be safe... nahh.*/ + if (dev->mem_start) { /* Use the shared memory. */ + if (dev->mem_start + ring_offset + count > end_of_ring) { + /* We must wrap the input move. */ + int semi_count = end_of_ring - (dev->mem_start + ring_offset); + if (ei_debug > 4) + printk("3c503: block_input() @ %#5x+%x=%5x.\n", + dev->mem_start, ring_offset, + (char *)dev->mem_start + ring_offset); + memcpy(buf, (char *)dev->mem_start + ring_offset, semi_count); + count -= semi_count; + memcpy(buf + semi_count, (char *)dev->rmem_start, count); + return dev->rmem_start + count; + } + if (ei_debug > 4) + printk("3c503: block_input() @ %#5x+%x=%5x.\n", + dev->mem_start, ring_offset, + (char *)dev->mem_start + ring_offset); + memcpy(buf, (char *)dev->mem_start + ring_offset, count); + return ring_offset + count; + } else { /* No shared memory, use the fifo. */ + int i; + outb(ring_offset & 0xff, E33G_DMAAL); + outb((ring_offset >> 8) & 0xff, E33G_DMAAH); + outb(ei_status.thin_bit | ECNTRL_INPUT | ECNTRL_START, E33G_CNTRL); + + /* This is the byte copy loop: it should probably be tuned for + for speed once everything is working. */ + for(i = 0; i < count; i++) { + if (count % 8 == 7) + while ((inb(E33G_STATUS) & ESTAT_DPRDY) == 0) + if (++boguscount > 32) { + printk(EI_NAME": fifo blocked in el2_block_input().\n"); + return 0; + } + buf[i] = inb(E33G_FIFOH); + } + outb(ei_status.thin_bit, E33G_CNTRL); + ring_offset += count; + if (ring_offset >= end_of_ring) + ring_offset = dev->rmem_start + ring_offset - end_of_ring; + return ring_offset; + } +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c 3c503.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether/3c503reg.h b/net/tcpip/newether/3c503reg.h new file mode 100644 index 00000000..da7961d4 --- /dev/null +++ b/net/tcpip/newether/3c503reg.h @@ -0,0 +1,59 @@ +/* Definitions for the 3Com 3c503 Etherlink 2. */ +/* This file is part of Donald Becker's 8390 drivers. + This file is distributed under the Linux GPL. + Some of these names and comments are from the Crynwr packet drivers. */ + +#define EL2H (dev->base_addr + 0x400) +#define EL2L (dev->base_addr) + +/* Shared memory management parameters */ + +#define EL2SM_START_PG (0x20) /* First page of TX buffer */ +#define EL2SM_STOP_PG (0x40) /* Last page +1 of RX ring */ + +/* 3Com 3c503 ASIC registers */ +#define E33G_STARTPG (EL2H+0) /* Start page, must match EN0_STARTPG */ +#define E33G_STOPPG (EL2H+1) /* Stop page, must match EN0_STOPPG */ +#define E33G_DRQCNT (EL2H+2) /* DMA burst count */ +#define E33G_IOBASE (EL2H+3) /* Read of I/O base jumpers. */ + /* (non-useful, but it also appears at the end of EPROM space) */ +#define E33G_ROMBASE (EL2H+4) /* Read of memory base jumpers. */ +#define E33G_GACFR (EL2H+5) /* Config/setup bits for the ASIC GA */ +#define E33G_CNTRL (EL2H+6) /* Board's main control register */ +#define E33G_STATUS (EL2H+7) /* Status on completions. */ +#define E33G_IDCFR (EL2H+8) /* Interrupt/DMA config register */ + /* (Which IRQ to assert, DMA chan to use) */ +#define E33G_DMAAH (EL2H+9) /* High byte of DMA address reg */ +#define E33G_DMAAL (EL2H+10) /* Low byte of DMA address reg */ +/* "Vector pointer" - if this address matches a read, the EPROM (rather than + shared RAM) is mapped into memory space. */ +#define E33G_VP2 (EL2H+11) +#define E33G_VP1 (EL2H+12) +#define E33G_VP0 (EL2H+13) +#define E33G_FIFOH (EL2H+14) /* FIFO for programmed I/O moves */ +#define E33G_FIFOL (EL2H+15) /* ... low byte of above. */ + +/* Bits in E33G_CNTRL register: */ + +#define ECNTRL_RESET (0x01) /* Software reset of the ASIC and 8390 */ +#define ECNTRL_THIN (0x02) /* Onboard thin-net xcvr enable */ +#define ECNTRL_SAPROM (0x04) /* Map the station address prom */ +#define ECNTRL_DBLBFR (0x20) /* FIFO configuration bit */ +#define ECNTRL_OUTPUT (0x40) /* PC-to-3C503 direction if 1 */ +#define ECNTRL_INPUT (0x00) /* 3C503-to-PC direction if 0 */ +#define ECNTRL_START (0x80) /* Start the DMA logic */ + +/* Bits in E33G_STATUS register: */ + +#define ESTAT_DPRDY (0x80) /* Data port (of FIFO) ready */ +#define ESTAT_UFLW (0x40) /* Tried to read FIFO when it was empty */ +#define ESTAT_OFLW (0x20) /* Tried to write FIFO when it was full */ +#define ESTAT_DTC (0x10) /* Terminal Count from PC bus DMA logic */ +#define ESTAT_DIP (0x08) /* DMA In Progress */ + +/* Bits in E33G_GACFR register: */ + +#define EGACFR_NORM (0x49) /* Enable 8K shared mem, no DMA TC int */ +#define EGACFR_IRQOFF (0xc9) /* Above, and disable 8390 IRQ line */ + +/* End of 3C503 parameter definitions */ diff --git a/net/tcpip/newether/8390.c b/net/tcpip/newether/8390.c new file mode 100644 index 00000000..a4cf8629 --- /dev/null +++ b/net/tcpip/newether/8390.c @@ -0,0 +1,712 @@ +/* 8390.c: A general NS8390 ethernet driver core for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with many 8390-based ethernet adaptors. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = + "8390.c:v0.27 1/27/93 Donald Becker (becker@super.org)\n"; +#include +#if !defined(EL2) && !defined(NE2000) && !defined(WD80x3) && !defined(HPLAN) +/* They don't know what they want -- give it all to them! */ +#define EL2 +#define NE2000 +#define WD80x3 +#define HPLAN +#endif + +/* + Braindamage remaining: + + Ethernet devices should use a chr_drv device interface, with ioctl()s to + configure the card, bring the interface up or down, allow access to + statistics, and maybe read() and write() access to raw packets. + This won't be done until after Linux 1.00. + + This driver should support multiple, diverse boards simultaneousely. + This won't be done until after Linux 1.00. + +Sources: + The National Semiconductor LAN Databook, and 3Com databooks, both companies + provided information readily. The NE* info came from the Crynwr packet + driver, and figuring out that the those boards are similar to the NatSemi + evaluation board described in AN-729. Thanks NS, no thanks to Novell/Eagle. + Cabletron provided only info I had already gotten from other sources -- hiss. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "eth.h" +#include "timer.h" +#include "ip.h" +#include "tcp.h" +#include "sock.h" +#include "arp.h" + +#include "8390.h" + +#define ei_reset_8390 (ei_status.reset_8390) +#define ei_block_output (ei_status.block_output) +#define ei_block_input (ei_status.block_input) + +#define EN_CMD (e8390_base) +#define E8390_BASE (e8390_base) + +/* use 0 for production, 1 for verification, >2 for debug */ +#ifdef EI_DEBUG +int ei_debug = EI_DEBUG; +#else +int ei_debug = 2; +#endif + +static int e8390_base; + +static struct device *eifdev; /* For single-board consistency checking. */ +extern int etherlink2; + +struct ei_device ei_status = { EI_NAME, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* The statistics, perhaps these should be in the above structure. */ +static int tx_packets = 0; +static int rx_packets = 0; +static int tx_errors = 0; +static int soft_rx_errors = 0; +static int soft_rx_err_bits = 0; +static int missed_packets = 0; + +/* Index to functions. */ +/* Put in the device structure. */ +static int ei_open(struct device *dev); +static void ei_send_packet(struct sk_buff *skb, struct device *dev); +/* Dispatch from interrupts. */ +static void ei_interrupt(int reg_ptr); +static void ei_tx_intr(struct device *dev); +static void ei_receive(struct device *dev); +static void ei_rx_overrun(struct device *dev); + +/* Routines generic to NS8390-based boards. */ +void NS8390_init(struct device *dev, int startp); +static void NS8390_trigger_send(struct device *dev, unsigned int length, + int start_page); + +extern int el2autoprobe(int ioaddr, struct device *dev); +extern int el2probe(int ioaddr, struct device *dev); +extern int neprobe(int ioaddr, struct device *dev); +extern int wdprobe(int ioaddr, struct device *dev); +extern int hpprobe(int ioaddr, struct device *dev); + +struct sigaction ei_sigaction = { ei_interrupt, 0, 0, NULL, }; + +/* Open/initialize the board. This routine goes all-out, setting everything + up anew at each open, even though many of these registers should only + need to be set once at boot. + */ +static int +ei_open(struct device *dev) +{ + if ( ! ei_status.exists) { + printk(EI_NAME ": Opening a non-existent physical device\n"); + return 1; /* ENXIO would be more accurate. */ + } + + NS8390_init(dev, 1); + + ei_status.txing = 0; + ei_status.in_interrupt = 0; + ei_status.open = 1; + return 0; +} + +static int +ei_start_xmit(struct sk_buff *skb, struct device *dev) +{ + if ( ! ei_status.exists) + return 0; /* We should be able to do ENODEV, but nooo. */ + + if (ei_status.txing) { /* Do timeouts, just like the 8003 driver. */ + int txsr = inb(E8390_BASE+EN0_TSR); + int tickssofar = jiffies - dev->trans_start; + if (tickssofar < 5 || (tickssofar < 15 && ! (txsr & ENTSR_PTX))) { + return 1; + } + printk(EI_NAME": transmit timed out, TX status %#2x, ISR %#2x.\n", + txsr, inb(E8390_BASE+EN0_ISR)); + /* It's possible to check for an IRQ conflict here. + I may have to do that someday. */ + if ((txsr & ~0x02) == ENTSR_PTX) /* Strip an undefined bit. */ + printk(EI_NAME": Possible IRQ conflict?\n"); + else + printk(EI_NAME": Possible network cable problem?\n"); + /* It futile, but try to restart it anyway. */ + ei_reset_8390(dev); + NS8390_init(dev, 1); + } + + /* This is new: it means some higher layer thinks we've missed an + tx-done interrupt. Caution: dev_tint() handles the cli()/sti() + itself. */ + if (skb == NULL) { + /* Alternative is ei_tx_intr(dev); */ + ei_status.txing = 1; + if (dev_tint(NULL, dev) == 0) + ei_status.txing = 0; + return 0; + } + /* Fill in the ethernet header. */ + if (!skb->arp && dev->rebuild_header(skb+1, dev)) { + skb->dev = dev; + arp_queue (skb); + return 0; + } + + dev->trans_start = jiffies; + cli(); + ei_status.txing = 1; +#ifdef PINGPONG + ei_tx_intr(dev); +#endif + ei_send_packet(skb, dev); + sti(); + if (skb->free) +#ifdef notdef /* 0.98.5 and beyond use kfree_skb(). */ + free_skb (skb, FREE_WRITE); +#else + kfree_skb (skb, FREE_WRITE); +#endif + return 0; +} + +/* The typical workload of the driver: + Handle the ether interface interrupts. */ +static void +ei_interrupt(int reg_ptr) +{ + int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2); + struct device *dev; + int interrupts, boguscount = 0; + + /* We do the same thing as the 8013 driver, but this is mostly bogus. */ + for (dev = dev_base; dev != NULL; dev = dev->next) { + if (dev->irq == irq) break; + } + ei_status.in_interrupt++; + sti(); /* Allow other interrupts. */ + +#ifdef notneeded + /* If we a getting a reset-complete interrupt the 8390 might not be + mapped in for the 3c503. */ + if (etherlink2) + outb_p(ei_status.thin_bit, E33G_CNTRL), + outb_p(0x00, E33G_STATUS); +#endif + + /* Change to page 0 and read the intr status reg. */ + outb_p(E8390_NODMA+E8390_PAGE0, EN_CMD); + if (ei_debug > 3) + printk(EI_NAME": interrupt(isr=%#2.2x).\n", + inb_p(E8390_BASE + EN0_ISR)); + + if (ei_status.in_interrupt > 1) + printk(EI_NAME ": Reentering the interrupt driver!\n"); + if (dev == NULL) { + printk (EI_NAME ": irq %d for unknown device\n", irq); + ei_status.in_interrupt--; + return; + } else if (ei_debug > 0 && eifdev != dev) { + printk (EI_NAME": device mismatch on irq %d.\n", irq); + dev = eifdev; + } + + /* !!Assumption!! -- we stay in page 0. Don't break this. */ + while ((interrupts = inb_p(E8390_BASE + EN0_ISR)) != 0 + && ++boguscount < 20) { + /* The reset interrupt is the most important... */ + if (interrupts & ENISR_RDC) { + outb_p(ENISR_RDC, E8390_BASE + EN0_ISR); /* Ack intr. */ + } + if (interrupts & ENISR_OVER) { + ei_status.overruns++; + ei_rx_overrun(dev); + } else if (interrupts & (ENISR_RX+ENISR_RX_ERR)) { + /* Got a good (?) packet. */ + ei_receive(dev); + } + /* Push the next to-transmit packet through. */ + if (interrupts & ENISR_TX) { + ei_tx_intr(dev); + } else if (interrupts & ENISR_COUNTERS) { + /* Gotta read the counter to clear the irq, even if we + don't care about their values. */ + inb_p(E8390_BASE + EN0_COUNTER0); + inb_p(E8390_BASE + EN0_COUNTER1); + missed_packets += inb_p(E8390_BASE + EN0_COUNTER2); + outb_p(ENISR_COUNTERS, E8390_BASE + EN0_ISR); /* Ack intr. */ + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + } + + /* Ignore the transmit errs and reset intr for now. */ + if (interrupts & ENISR_TX_ERR) { + outb_p(ENISR_TX_ERR, E8390_BASE + EN0_ISR); /* Ack intr. */ + } + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + } + + if (interrupts && ei_debug) { + printk(EI_NAME ": unknown interrupt %#2x\n", interrupts); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, EN_CMD); + outb_p(0xff, E8390_BASE + EN0_ISR); /* Ack. all intrs. */ + } + ei_status.in_interrupt--; + return; +} + +#ifdef PINGPONG +static int lasttx = 0; +#endif + +/* This is stuffed into the dev struct to be called by dev.c:dev_tint(). + Evenually this should be replaced by the block_output() routines. */ +static void +ei_send_packet(struct sk_buff *skb, struct device *dev) +{ + int length = skb->len; + int send_length = ETHER_MIN_LEN < length ? length : ETHER_MIN_LEN; + + if (length <= 0) + return; + +#ifdef PINGPONG + if (ei_status.tx1 == 0) { /* First buffer empty */ + ei_block_output(dev, length, (void*)(skb+1), + ei_status.tx_start_page); + ei_status.tx1 = send_length; + } else if (ei_status.tx2 == 0) { /* Second buffer empty */ + ei_block_output(dev, length, (void*)(skb+1), + ei_status.tx_start_page+6); + ei_status.tx2 = send_length; + } else { + printk("%s: Internal error, no transmit buffer space tx1=%d tx2=%d lasttx=%d.\n", + ei_status.name, ei_status.tx1, ei_status.tx2, lasttx); + } + ei_status.txqueue++; + /* The following should be merged with ei_tx_intr(). */ + if (lasttx = 0) { + if (ei_status.tx1 > 0) { + NS8390_trigger_send(dev, ei_status.tx1, + ei_status.tx_start_page + 6), + ei_status.tx1 = -1, + lasttx = 1; + } else if (ei_status.tx2 > 0) { + NS8390_trigger_send(dev, ei_status.tx2, + ei_status.tx_start_page + 6), + ei_status.tx2 = -1, + lasttx = 2; + } + } +#else + ei_block_output(dev, length, (void*)(skb+1), ei_status.tx_start_page); + NS8390_trigger_send(dev, send_length, ei_status.tx_start_page); +#endif + return; +} + +/* We have finished a transmit: check for errors and then trigger the next + packet to be sent. */ +static void +ei_tx_intr(struct device *dev) +{ + int status = inb(E8390_BASE + EN0_TSR); + outb_p(ENISR_TX, E8390_BASE + EN0_ISR); /* Ack intr. */ + if ((status & ENTSR_PTX) == 0) + tx_errors++; + else + tx_packets++; + +#ifdef PINGPONG + { + ei_status.txqueue--; + if (ei_status.tx1 < 0) { + if (lasttx != 1) + printk("%s: bogus last_tx_buffer %d, tx1=%d.\n", + ei_status.name, lasttx, ei_status.tx1); + ei_status.tx1 = 0; + lasttx = 0; + if (ei_status.tx2 > 0) { + NS8390_trigger_send(dev, ei_status.tx2, + ei_status.tx_start_page + 6), + ei_status.tx2 = -1, + lasttx = 2; + } + } else if (ei_status.tx2 < 0) { + if (lasttx != 2) + printk("%s: bogus last_tx_buffer %d, tx2=%d.\n", + ei_status.name, lasttx, ei_status.tx2); + ei_status.tx2 = 0; + lasttx = 0; + if (ei_status.tx1 > 0) { + NS8390_trigger_send(dev, ei_status.tx1, + ei_status.tx_start_page), + ei_status.tx1 = -1; + lasttx = 1; + } + } /*else + printk(EI_NAME": unexpected TX interrupt.\n");*/ + while ((ei_status.tx1 == 0) || (ei_status.tx2 == 0)) + if (dev_tint(NULL, dev) == 0) { + ei_status.txing = 0; + return; + } else if (lasttx == 0) { + if (ei_status.tx1 == 0 || ei_status.tx2 != 0) + printk(EI_NAME": Unexpected tx buffer busy tx1=%d tx2=%d.\n", + ei_status.tx1, ei_status.tx2); + NS8390_trigger_send(dev, ei_status.tx1, + ei_status.tx_start_page), + ei_status.tx1 = -1; + lasttx = 1; + } + } +#else + if (dev_tint(NULL, dev) == 0) + ei_status.txing = 0; +#endif +} + +/* We have a good packet(s), get it/them out of the buffers. */ + +static void +ei_receive(struct device *dev) +{ + int rxing_page, this_frame, next_frame, current_offset; + int boguscount = 0; + struct e8390_pkt_hdr rx_frame; + int num_rx_pages = ei_status.stop_page-ei_status.rx_start_page; + + while (++boguscount < 10) { + int size; + + cli(); + outb_p(E8390_NODMA+E8390_PAGE1, EN_CMD); /* Get the rec. page. */ + rxing_page = inb_p(E8390_BASE+EN1_CURPAG);/* (Incoming packet pointer).*/ + outb_p(E8390_NODMA+E8390_PAGE0, EN_CMD); + sti(); + + /* Remove one frame from the ring. Boundary is alway a page behind. */ + this_frame = inb_p(E8390_BASE + EN0_BOUNDARY) + 1; + if (this_frame >= ei_status.stop_page) + this_frame = ei_status.rx_start_page; + + /* Someday we'll omit the previous step, iff we never get this message.*/ + if (ei_debug > 0 && this_frame != ei_status.current_page) + printk(EI_NAME": mismatched read page pointers %2x vs %2x.\n", + this_frame, ei_status.current_page); + + if (this_frame == rxing_page) /* Read all the frames? */ + break; /* Done for now */ + + current_offset = this_frame << 8; + ei_block_input(dev, sizeof(rx_frame), (void *)&rx_frame, + current_offset); + + size = rx_frame.count - sizeof(rx_frame); + + next_frame = this_frame + 1 + ((size+4)>>8); + + /* Check for bogosity warned by 3c503 book: the status byte is never + written. This happened a lot during testing! This code should be + cleaned up someday, and the printk()s should be PRINTK()s. */ + if ( rx_frame.next != next_frame + && rx_frame.next != next_frame + 1 + && rx_frame.next != next_frame - num_rx_pages + && rx_frame.next != next_frame + 1 - num_rx_pages) { +#ifndef EI_DEBUG + ei_status.current_page = rxing_page; + outb(ei_status.current_page-1, E8390_BASE+EN0_BOUNDARY); + continue; +#else + static int last_rx_bogosity = -1; + printk(EI_NAME": bogus packet header, status=%#2x nxpg=%#2x sz=%#x (at %#4x)\n", + rx_frame.status, rx_frame.next, rx_frame.count, current_offset); + + if (rx_packets != last_rx_bogosity) { + /* Maybe we can avoid resetting the chip... empty the packet ring. */ + ei_status.current_page = rxing_page; + printk(EI_NAME": setting next frame to %#2x (nxt=%#2x, rx_frm.nx=%#2x rx_frm.stat=%#2x).\n", + ei_status.current_page, next_frame, + rx_frame.next, rx_frame.status); + last_rx_bogosity = rx_packets; + outb(ei_status.current_page-1, E8390_BASE+EN0_BOUNDARY); + continue; + } else { + /* Oh no Mr Bill! Last ditch error recovery. */ + printk(EI_NAME": multiple sequential lossage, resetting at packet #%d.", + rx_packets); + sti(); + ei_reset_8390(dev); + NS8390_init(dev, 1); + printk("restarting.\n"); + return; + } +#endif /* EI8390_NOCHECK */ + } + + if ((size < 32 || size > 1535) && ei_debug) + printk(EI_NAME": bogus big packet, status=%#2x nxpg=%#2x size=%#x\n", + rx_frame.status, rx_frame.next, rx_frame.count); + if ((rx_frame.status & 0x0F) == ENRSR_RXOK) { + int sksize = sizeof(struct sk_buff) + size; + struct sk_buff *skb; + skb = kmalloc(sksize, GFP_ATOMIC); + if (skb != NULL) { + skb->lock = 0; + skb->mem_len = sksize; + skb->mem_addr = skb; + /* 'skb+1' points to the start of sk_buff data area. */ + ei_block_input(dev, size, (void *)(skb+1), + current_offset + sizeof(rx_frame)); + if(dev_rint((void *)skb, size, IN_SKBUFF, dev)) { + printk(EI_NAME": receive buffers full.\n"); + break; + } + } else if (ei_debug) { + printk(EI_NAME": Couldn't allocate a sk_buff of size %d.\n", sksize); + break; + } + rx_packets++; + } else { + if (ei_debug) + printk(EI_NAME": bogus packet, status=%#2x nxpg=%#2x size=%d\n", + rx_frame.status, rx_frame.next, rx_frame.count); + soft_rx_err_bits |= rx_frame.status, + soft_rx_errors++; + } + next_frame = rx_frame.next; + + /* This should never happen, it's here for debugging. */ + if (next_frame >= ei_status.stop_page) { + printk(EI_NAME": next frame inconsistency, %#2x..", next_frame); + next_frame = ei_status.rx_start_page; + } + ei_status.current_page += 1 + ((size+4)>>8); +#ifdef notdef + if (ei_status.current_page > ei_status.stop_page) + ei_status.current_page -= ei_status.stop_page-ei_status.rx_start_page; + if (ei_status.current_page != next_frame) { + printk(EI_NAME": inconsistency in next_frame %#2x!=%#2x.\n", + this_frame, next_frame); + /* Assume this packet frame is scrogged by the NIC, use magic to + skip to the next frame. Actually we should stop and restart.*/ + next_frame = size > 1535 ? rx_frame.status : rx_frame.next; + ei_status.current_page = next_frame; + break; + } +#endif + + ei_status.current_page = next_frame; + outb(next_frame-1, E8390_BASE+EN0_BOUNDARY); + } + + /* Tell the upper levels we're done. */ + while (dev_rint(NULL, 0, 0, dev) == 1 + && ++boguscount < 20) + ; + /* Bug alert! Reset ENISR_OVER to avoid spurious overruns! */ + outb_p(ENISR_RX+ENISR_RX_ERR+ENISR_OVER, E8390_BASE+EN0_ISR); /* Ack intr. */ + return; +} + +/* We have a receiver overrun: we have to kick the 8390 to get it started + again. Overruns are detected on a per-256byte-page basis. */ +static void +ei_rx_overrun(struct device *dev) +{ + int reset_start_time = jiffies; + + /* We should already be stopped and in page0. Remove after testing. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, EN_CMD); + + if (ei_debug) + printk(EI_NAME ": Receiver overrun.\n"); + + /* The we.c driver does dummy = inb_p( RBCR[01] ); at this point. + It might mean something -- magic to speed up a reset? A 8390 bug?*/ + + /* Wait for reset in case the NIC is doing a tx or rx. This could take up to + 1.5msec, but we have no way of timing something in that range. The 'jiffies' + are just a sanity check. */ + while ((inb_p(E8390_BASE+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 1) { + printk(EI_NAME": reset did not complete at ei_rx_overrun.\n"); + NS8390_init(dev, 1); + return; + }; + + /* Remove packets right away. */ + ei_debug += 5; + ei_receive(dev); + ei_debug -= 5; + outb_p(0xff, E8390_BASE+EN0_ISR); + /* Generic 8390 insns to start up again, same as in open_8390(). */ + outb_p(E8390_NODMA + E8390_PAGE0 + E8390_START, EN_CMD); + outb_p(E8390_TXCONFIG, E8390_BASE + EN0_TXCR); /* xmit on. */ +#ifdef notneeded + outb_p(E8390_RXCONFIG, E8390_BASE + EN0_RXCR); /* rx on, */ +#endif +} + +int +ethif_init(struct device *dev) +{ + int i; + + eifdev = dev; /* Store for debugging. */ + + if (ei_debug > 3) + printk(version); + if (1 +#ifdef WD80x3 + && ! wdprobe(dev->base_addr, dev) +#endif +#ifdef EL2 + && ! el2autoprobe(dev->base_addr, dev) +#endif +#ifdef NE2000 + && ! neprobe(dev->base_addr, dev) +#endif +#ifdef HPLAN + && ! hpprobe(dev->base_addr, dev) +#endif + && 1 ) { + dev->open = &ei_open; + printk("No ethernet device found.\n"); + ei_status.exists = 0; + return 1; /* ENODEV or EAGAIN would be more accurate. */ + } + + e8390_base = dev->base_addr; + + /* Initialize the rest of the device structure. Many of these could + be in Space.c. */ + for (i = 0; i < DEV_NUMBUFFS; i++) + dev->buffs[i] = NULL; + + ei_status.exists = 1; + dev->hard_header = eth_hard_header; + dev->add_arp = eth_add_arp; + dev->queue_xmit = dev_queue_xmit; + dev->rebuild_header = eth_rebuild_header; + dev->type_trans = eth_type_trans; + + dev->send_packet = &ei_send_packet; + dev->open = &ei_open; + dev->hard_start_xmit = &ei_start_xmit; + + dev->type = ETHER_TYPE; + dev->hard_header_len = sizeof (struct enet_header); + dev->mtu = 1500; /* eth_mtu */ + dev->addr_len = ETHER_ADDR_LEN; + for (i = 0; i < dev->addr_len; i++) { + dev->broadcast[i]=0xff; + } + return 0; +} + + +/* This page of functions should be 8390 generic */ +/* Follow National Semi's recommendations for initializing the "NIC". */ +void NS8390_init(struct device *dev, int startp) +{ + int i; + int endcfg = ei_status.word16 ? (0x48 | ENDCFG_WTS) : 0x48; + int e8390_base = dev->base_addr; + + /* Follow National Semi's recommendations for initing the DP83902. */ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); /* 0x21 */ + outb_p(endcfg, e8390_base + EN0_DCFG); /* 0x48 or 0x49 */ + /* Clear the remote byte count registers. */ + outb_p(0x00, e8390_base + EN0_RCNTLO); + outb_p(0x00, e8390_base + EN0_RCNTHI); + /* Set to monitor and loopback mode -- this is vital!. */ + outb_p(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ + /* Set the transmit page and receive ring. */ + outb_p(ei_status.tx_start_page, e8390_base + EN0_TPSR); + ei_status.tx1 = ei_status.tx2 = 0; + outb_p(ei_status.rx_start_page, e8390_base + EN0_STARTPG); + outb_p(ei_status.stop_page-1, e8390_base + EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ + ei_status.current_page = ei_status.rx_start_page; /* assert boundary+1 */ + outb_p(ei_status.stop_page, e8390_base + EN0_STOPPG); + /* Clear the pending interrupts and mask. */ + outb_p(0xFF, e8390_base + EN0_ISR); + outb_p(0x00, e8390_base + EN0_IMR); + + /* Copy the station address into the DS8390 registers, + and set the multicast hash bitmap to receive all multicasts. */ + cli(); + outb_p(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base); /* 0x61 */ + for(i = 0; i < 6; i++) { + outb_p(dev->dev_addr[i], e8390_base + EN1_PHYS + i); + } + for(i = 0; i < 8; i++) + outb_p(0xff, e8390_base + EN1_MULT + i); + + outb_p(ei_status.rx_start_page, e8390_base + EN1_CURPAG); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base); + sti(); + if (startp) { + outb_p(0xff, e8390_base + EN0_ISR); + outb_p(ENISR_ALL, e8390_base + EN0_IMR); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base); + outb_p(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ + /* 3c503 TechMan says rxconfig only after the NIC is started. */ + outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ + } + return; +} + +/* Trigger a transmit start, assuming the length is valid. */ +static void NS8390_trigger_send(struct device *dev, unsigned int length, + int start_page) +{ + int e8390_base = dev->base_addr; + outb_p(E8390_NODMA+E8390_PAGE0, e8390_base); + + if (inb_p(EN_CMD) & E8390_TRANS) { + printk(EI_NAME": trigger_send() called with the transmitter busy.\n"); + return; + } + outb_p(length & 0xff, e8390_base + EN0_TCNTLO); + outb_p(length >> 8, e8390_base + EN0_TCNTHI); + outb_p(start_page, e8390_base + EN0_TPSR); + outb_p(E8390_NODMA+E8390_TRANS+E8390_START, e8390_base); + outb_p(ENISR_RDC, e8390_base + EN0_ISR); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -DPINGPONG -I/usr/src/linux/net/tcp -c 8390.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether/8390.h b/net/tcpip/newether/8390.h new file mode 100644 index 00000000..6644ac01 --- /dev/null +++ b/net/tcpip/newether/8390.h @@ -0,0 +1,129 @@ +/* Generic NS8390 register definitions. */ +/* This file is part of Donald Becker's 8390 drivers. + This file is distributed under the Linux GPL. + Some of these names and comments are from the Crynwr packet drivers. */ + +#ifndef e8390_h +#define e8390_h +#ifndef EI_NAME +#define EI_NAME "eth_if" +#endif +/*#define PINGPONG*/ +#ifdef PINGPONG +#define TX_PAGES 12 +#else +#define TX_PAGES 6 +#endif + +#define ETHER_ADDR_LEN 6 + +/* From auto_irq.c */ +extern void autoirq_setup(int waittime); +extern int autoirq_report(int waittime); + +/* Most of these entries should be in 'struct device' (or most + things in there should be here!) */ +struct ei_device { /* These should be stored per-board */ + char *name; + int exists:1; /* perhaps in dev->private. */ + int open:1; + int word16:1; /* We have the 16-bit (vs 8-bit) version of the card. */ + void (*reset_8390)(struct device *); + void (*block_output)(struct device *, int, const unsigned char *, int); + int (*block_input)(struct device *, int, char *, int); + unsigned char tx_start_page, rx_start_page, stop_page; + unsigned char current_page; /* Read pointer in buffer */ + unsigned char thin_bit; /* Value to write to the 3c503 E33G_CNTRL */ + unsigned char txing; /* Transmit Active, don't confuse the upper levels. */ + unsigned char txqueue; /* Tx Packet buffer queue length. */ + unsigned char in_interrupt; + short tx1, tx2; /* Packet lengths for ping-pong tx. */ + int overruns; /* Rx overruns. */ +}; + +/* Some generic ethernet register configurations. */ +#define E8390_TX_IRQ_MASK 0xa /* For register EN0_ISR */ +#define E8390_RX_IRQ_MASK 0x5 +#define E8390_RXCONFIG 0x4 /* EN0_RXCR: broadcasts, no multicast,errors */ +#define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ +#define E8390_TXCONFIG 0x00 /* EN0_TXCR: Normal transmit mode */ +#define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ + +/* Register accessed at EN_CMD, the 8390 base addr. */ +#define E8390_STOP 0x01 /* Stop and reset the chip */ +#define E8390_START 0x02 /* Start the chip, clear reset */ +#define E8390_TRANS 0x04 /* Transmit a frame */ +#define E8390_RREAD 0x08 /* Remote read */ +#define E8390_RWRITE 0x10 /* Remote write */ +#define E8390_NODMA 0x20 /* Remote DMA */ +#define E8390_PAGE0 0x00 /* Select page chip registers */ +#define E8390_PAGE1 0x40 /* using the two high-order bits */ +#define E8390_PAGE2 0x80 /* Page 3 is invalid. */ + +/* Page 0 register offsets. */ +#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ +#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ +#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ +#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ +#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ +#define EN0_TSR 0x04 /* Transmit status reg RD */ +#define EN0_TPSR 0x04 /* Transmit starting page WR */ +#define EN0_NCR 0x05 /* Number of collision reg RD */ +#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ +#define EN0_FIFO 0x06 /* FIFO RD */ +#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ +#define EN0_ISR 0x07 /* Interrupt status reg RD WR */ +#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ +#define EN0_RSARLO 0x08 /* Remote start address reg 0 */ +#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ +#define EN0_RSARHI 0x09 /* Remote start address reg 1 */ +#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ +#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ +#define EN0_RSR 0x0c /* rx status reg RD */ +#define EN0_RXCR 0x0c /* RX configuration reg WR */ +#define EN0_TXCR 0x0d /* TX configuration reg WR */ +#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ +#define EN0_DCFG 0x0e /* Data configuration reg WR */ +#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ +#define EN0_IMR 0x0f /* Interrupt mask reg WR */ +#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ + +/* Bits in EN0_ISR - Interrupt status register */ +#define ENISR_RX 0x01 /* Receiver, no error */ +#define ENISR_TX 0x02 /* Transmitter, no error */ +#define ENISR_RX_ERR 0x04 /* Receiver, with error */ +#define ENISR_TX_ERR 0x08 /* Transmitter, with error */ +#define ENISR_OVER 0x10 /* Receiver overwrote the ring */ +#define ENISR_COUNTERS 0x20 /* Counters need emptying */ +#define ENISR_RDC 0x40 /* remote dma complete */ +#define ENISR_RESET 0x80 /* Reset completed */ +#define ENISR_ALL 0x3f /* Interrupts we will enable */ + +/* Bits in EN0_DCFG - Data config register */ +#define ENDCFG_WTS 0x01 /* word transfer mode selection */ + +/* Page 1 register offsets. */ +#define EN1_PHYS 0x01 /* This board's physical enet addr RD WR */ +#define EN1_CURPAG 0x07 /* Current memory page RD WR */ +#define EN1_MULT 0x08 /* Multicast filter mask array (8 bytes) RD WR */ + +/* Bits in received packet status byte and EN0_RSR*/ +#define ENRSR_RXOK 0x01 /* Received a good packet */ +#define ENRSR_CRC 0x02 /* CRC error */ +#define ENRSR_FAE 0x04 /* frame alignment error */ +#define ENRSR_FO 0x08 /* FIFO overrun */ +#define ENRSR_MPA 0x10 /* missed pkt */ +#define ENRSR_PHY 0x20 /* physical/multicase address */ +#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */ +#define ENRSR_DEF 0x80 /* deferring */ + +/* Transmitted packet status, EN0_TSR. */ +#define ENTSR_PTX 0x01 /* Packet transmitted without error */ + +/* The per-packet-header format. */ +struct e8390_pkt_hdr { + unsigned char status; /* status */ + unsigned char next; /* pointer to next packet. */ + unsigned short count; /* header + packet lenght in bytes */ +}; +#endif /* e8390_h */ diff --git a/net/tcpip/newether/GNUmakefile b/net/tcpip/newether/GNUmakefile new file mode 100644 index 00000000..075cf46d --- /dev/null +++ b/net/tcpip/newether/GNUmakefile @@ -0,0 +1,27 @@ +# This has the effect of appending lines to the Makefile. +include Makefile + +# Add a few files to tcpip.a. +newobjs = 8390.o 3c503.o ne.o wd.o hp.o auto_irq.o +OBJS := $(OBJS) $(newobjs) +tcpip.a: $(newobjs) + +# Set the address and IRQ here. The ne.c and 3c503 driver will autoprobe +# if you set the address or IRQ to zero, so we do that by default. +# +# Add -DEI_NAME=eth0 if you want to be exactly compatible with the default +# driver. This will only work if you don't use the distributed 'we' driver! +# +Space.o: Space.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -DEI8390=0 -DEI8390_IRQ=0 -c Space.c -o $@ + +# Change this to define the set of ethercards your kernel will support. +8390.o: 8390.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -DNE2000 -DWD80x3 -DHPLAN -DEL2 -c 8390.c -o $@ + +# And set any special compile-time options here. +ne.o: ne.c GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -UEI_8BIT -c ne.c -o $@ + +3c503.o: 3c503.c 3c503reg.h GNUmakefile + $(CC) $(CPPFLAGS) $(CFLAGS) -UEI8390_THICK -c 3c503.c -o $@ diff --git a/net/tcpip/newether/INSTALL b/net/tcpip/newether/INSTALL new file mode 100644 index 00000000..f3892edc --- /dev/null +++ b/net/tcpip/newether/INSTALL @@ -0,0 +1,77 @@ +Installation Directions: + +EMail me (becker@super.org) telling me you've gotten the "experimental +drivers". I need to know how many people have tried, succeeded and +failed before this is released as part of the official Linux. + +Use Linux 0.99.2 or later. Make certain you can make a working kernel +_before_ you install the ethercard driver. + +Put the all of the files into linux/net/tcp/. You'll need +GNUmakefile 8390.c 8390.h Space.c wd.c ne.c 3c503.c 3c503reg.h and hp.c. +Space.c is the only tricky one -- it overwrites the old Space.c. +Stock versions of Space.c leave the "we" driver enabled and will not work. + +Change the GNUmakefile to reflect your configuration. Use the guide at +the end of these instructions. + +Make and install your new kernel. + +To actually use this driver you must get the TCP/IP package and edit +your /usr/etc/inet/rc.net file to config "eth_if" instead of +"eth0" (the WD8003). (Alternately you can edit the GNUmakefile to use the +"eth0" name.) + +If you try to 'config' an interface that doesn't exist your kernel +will report "invalid ioctl()" for anthing that tries to use the card. +Note that the ethercard devices aren't (yet) real '/dev/eth_if' devices -- +they only exist in the socket namespace and thus you don't need to +'mknode' them. + +________________ +Important defines + +For Space.c +#define EI8390 0x300 /* The base address of your ethercard. */ +#define EI8390_IRQ 5 /* and the interrupt you want to use. */ + +For 8390.c +#define EI_DEBUG 2 /* Use '0' for no messages. */ +#define EL2 /* For the 3c503 driver. */ +#define NE2000 /* For the NE1000/NE2000/Ctron driver. */ +#define WD80x3 /* For the WD8003/WD8013 driver. */ +#define HPLAN /* For the HP27xxx driver. */ + +For the individual drivers +#undef EI_8BIT /* Define for ne.c iff you have an 8 bit card.*/ +#undef EI8390_THICK /* Define for 3c503 AUI/DIX transceiver.*/ + +EI8390 Define (probably in autoconf.h or config.site.h) this to the base + address of your ethernet card. +EI8390_IRQ Define (probably in autoconf.h or config.site.h) this to the + IRQ line of your ethernet card. Most drivers convert a IRQ2 to an + IRQ9 for you, so don't be surprised. +EI_DEBUG Set to the desired numeric debugging level. Use 3 or + greater when actively debugging a problem, '1' for a + casual interest in what's going on, and '0' for normal + use. (Most of the debugging stuff has been taken out recently, + so this won't have much effect.) +EI_PINGPONG + Not included or broken the alpha version. Define this if you want + ping-pong transmit buffers. +EI_8BIT + If you are using the ne.c driver and have an 8-bit card (NE1000 or + E1xxx Cabletron) you must define this. It's not needed for the other + drivers, and I hope to find a way to clean this up in the future. +EI8390_THICK + Define for this if you are using the 3c503 and use the AUI/DIX + connector rather than the built-in thin-net transceiver. + +If you have a Cabletron ethercard you might want to look at ne.c:neprobe() +for info on how to enable more packet buffer space. + +ETHERLINK1_IRQ +ETHERLINK1 Define these to the base address and IRQ of a 3c501 (NOT 3c503) + card. Refer to net/tcp/Space.c. + + diff --git a/net/tcpip/newether/README b/net/tcpip/newether/README new file mode 100644 index 00000000..8940f3a5 --- /dev/null +++ b/net/tcpip/newether/README @@ -0,0 +1,80 @@ +This is the experimental version of the 8390 ethercard driver. + +You should consult the list below for the specific #define for your +ethercard. If you don't have one specific #define the driver will +probe for all supported ethercard types. + +Source Header #define to get Supported cards +8390.c 8390.h EI8390 (generic, needed for all) +3c503.c 3c503reg.h EL2 3c503, 3c503/16 +ne.c NE2000 NE1000, NE2000, NatSemi, Cabletron +wd.c wd.h WD80x3 WD8003, WD8013, SMC elite +hp.c HPLAN HP LAN adaptors + +Notes on each package + +3c503.c +o You'll need to #define EI8390_THICK if you are using the AUI port instead + of the thinnet connector. Russ Nelson sent me an + run-time method of selecting between the two, but I haven't put it in yet. + This _may_ generate a spurious error message when transmitting the first + packet, I haven't yet tracked down this bug report. +o If you want to check the shared memory, #define EL2MEMTEST. I don't think + the memory check is worth the effort -- it's missed obvious problems. +o You must jumper the board to use shared memory -- I don't test the + non-shared-memory mode and it's probably broken. +o Thanks to Chance Reschke at USRA for providing the + 3c503 and anonymous FTP space. + +ne.c +o You'll need to #define EI_8BIT if you are using an 8-bit ethercard + such as the NE1000 or Cabletron E10xx. I might someday make a run-time + selection between the NE1000 and NE2000 (right now it screws up the + non-default bus-width) but I don't know how to distinguish the Cabletron + ethercards. I'm hoping to find a general way to identify the board's bus + width, but don't hold your breath. + +wd.c +o Thanks to Russ Nelson (nelson@crynwr.com) for loaning me a WD8013. +o The 8013 doesn't work if it's probed by some other driver first. + Make it either first in the probe list or the only driver you compile in. + Maybe I should reset the board before looking at it to fix the probe problem. +o You machine may fail to do a soft reboot if the packet buffer shared memory is + mapped in -- the machine might think its a boot PROM (since it intentionally + shares the same memory space as the optional on-board boot PROM). + +hp.c +o This has only been tested with a 27245A, 27247A, and 27250. It doesn't yet + work with the new 27247B! +o Thanks to Chance Reschke at USRA for loaning me the + 27247A ethercard. + + +BUGS + + The "bogus packet header" is a bug in the 8390. I drop all of + the packets in the ring (usually just one) when this happens. + If you get this more than just occasionally please report it to me. + + I don't yet distinguish between the problems with IRQ conflicts and + problems with the ethernet cable not being connected. If you get + a "transmit timed out" message check both! Your ethercard + probably will NOT work without proper termination. + + A small number of people report continuous "RX transfer address mismatch" + errors with the NE2000. This is a bug in the 8390, and the reason + most designers use shared memory or design their own packet buffer access + circuitry rather than use what's provided by the 8390. An occasional + "mismatch" message (say, once a week) won't impact performance. + + I've fixed most of the spurious "receiver overrun" messages. It + was a bug in the 8390 -- the overrun flag is sometimes set + when the boundary pointer is written. If you still get + isolated overrun errors please send me email. + + The 3c501 driver isn't complete. This card is severely brain-damaged + anyway -- you won't notice the performance difference between working + and non-working versions anyway. If this source code is here, it is + only provided for a few people that wanted to write code for their 3c501 + cards. Don't send me email about it unless it's a bug fix. + diff --git a/net/tcpip/newether/Space.c b/net/tcpip/newether/Space.c new file mode 100644 index 00000000..ab5781d9 --- /dev/null +++ b/net/tcpip/newether/Space.c @@ -0,0 +1,134 @@ +/* Space.c */ +/* Holds initial configuration information for devices. */ +#include "dev.h" +#include +#include + +#define NEXT_DEV NULL + +#ifdef ETHERLINK1 +extern int etherlink_init(struct device *); + +#ifndef ETHERLINK1_IRQ +#define ETHERLINK1_IRQ 9 +#endif + +static struct device el_dev = { + "if3c501", + 0, 0, 0, 0, /* memory rx_end, rx_start, end, start are autoconfiged. */ + ETHERLINK1, ETHERLINK1_IRQ, /* base i/o address, irq. */ + 0,0,0,0,0, + NEXT_DEV, + etherlink_init, 0, {NULL}, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, {0,}, {0,}, 0 + }; +#undef NEXT_DEV +#define NEXT_DEV (&el_dev) + +#endif /* ETHERLINK1 */ + +#if defined(EI8390) || defined(EL2) || defined(NE2000) \ + || defined(WD80x3) || defined(HPLAN) +extern int ethif_init(struct device *); + +#ifndef EI8390_IRQ +#define EI8390_IRQ 0 +#endif + +static struct device ei8390_dev = { +#ifdef EI_NAME + EI_NAME, +#else + "eth_if", +#endif + 0, 0, 0, 0, /* memory rx_end, rx_start, end, start are autoconfiged. */ + EI8390, EI8390_IRQ, 0,0,0,0,0, /* base i/o address, irq, and flags. */ + NEXT_DEV, + ethif_init, 0, {NULL}, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, 0, 0, 0, {0,}, {0,}, 0 + }; +#undef NEXT_DEV +#define NEXT_DEV (&ei8390_dev) + +#endif /* The EI8390 drivers. */ + +#ifdef WD8003 +extern int wd8003_init(struct device *); + +static struct device wd8003_dev = +{ + "eth0", + 0xd2000, /* recv memory end. */ + 0xd0600, /* recv memory start. */ + 0xd2000, /* memory end. */ + 0xd0000, /* memory start. */ + 0x280, /* base i/o address. */ + 5, /* irq */ + 0,0,0,0,0, /* flags */ + NEXT_DEV, + wd8003_init, + /* wd8003_init should set up the rest. */ + 0, /* trans start. */ + {NULL}, /* buffs */ + NULL, /* backlog */ + NULL, /* open */ + NULL, /* stop */ + NULL, /* hard_start_xmit */ + NULL, /* hard_header */ + NULL, /* add arp */ + NULL, /* queue xmit */ + NULL, /* rebuild header */ + NULL, /* type_trans */ + NULL, /* send_packet */ + NULL, /* private */ + 0, /* type. */ + 0, /* hard_header_len */ + 0, /* mtu */ + {0,}, /* broadcast address */ + {0,}, /* device address */ + 0 /* addr len */ +}; +#undef NEXT_DEV +#define NEXT_DEV (&wd8003_dev) + +#endif /* WD8003 */ + +extern int loopback_init(struct device *dev); + +static struct device loopback_dev = +{ + "loopback", + -1, /* recv memory end. */ + 0x0, /* recv memory start. */ + -1, /* memory end. */ + 0, /* memory start. */ + 0, /* base i/o address. */ + 0, /* irq */ + 0,0,1,0,0, /* flags */ + NEXT_DEV, /* next device */ + loopback_init, + /* loopback_init should set up the rest. */ + 0, /* trans start. */ + {NULL}, /* buffs */ + NULL, /* backlog */ + NULL, /* open */ + NULL, /* stop */ + NULL, /* hard_start_xmit */ + NULL, /* hard_header */ + NULL, /* add arp */ + NULL, /* queue xmit */ + NULL, /* rebuild header */ + NULL, /* type_trans */ + NULL, /* send_packet */ + NULL, /* private */ + 0, /* type. */ + 0, /* hard_header_len */ + 0, /* mtu */ + {0,}, /* broadcast address */ + {0,}, /* device address */ + 0 /* addr len */ +}; +#undef NEXT_DEV +#define NEXT_DEV (error no next device &loopback_dev) + +struct device *dev_base = &loopback_dev; diff --git a/net/tcpip/newether/auto_irq.c b/net/tcpip/newether/auto_irq.c new file mode 100644 index 00000000..3acfa9ea --- /dev/null +++ b/net/tcpip/newether/auto_irq.c @@ -0,0 +1,100 @@ +/* auto_irq.c: Auto-configure IRQ lines for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + + This code is a general-purpose IRQ line detector for devices with + jumpered IRQ lines. If you can make the device raise an IRQ (and + that IRQ line isn't already being used), these routines will tell + you what IRQ line it's using -- perfect for those oh-so-cool boot-time + device probes! + + To use this, first call autoirq_setup(timeout). TIMEOUT is how many + 'jiffies' (1/18 sec.) to detect other devices that have active IRQ lines, + and can usually be zero at boot. + Next, set up your device to trigger an interrupt. + Finally call autoirq_report(TIMEOUT) to find out which IRQ line was + most recently active. The TIMEOUT should usually be zero, but may + be set to the number of jiffies to wait for an active IRQ. + + The idea of using the setup timeout to filter out bogus IRQs came from + the serial driver. +*/ + + +#ifdef version +static char *version="auto_irq.c:v0.01 1993 Donald Becker (becker@super.org)"; +#endif + +/*#include */ +/*#include */ +#include +#include +#include +/*#include */ + +static volatile int irq_number; /* The latest irq number we actually found. */ +static volatile int irq_bitmap; /* The irqs we actually found. */ +static int irq_handled; /* The irq lines we have a handler on. */ + +static void autoirq_probe(int irq) +{ + irq_number = irq; + set_bit(irq, (void *)&irq_bitmap); + /*irq_bitmap |= 1 << irq;*/ + return; +} +struct sigaction autoirq_sigaction = { autoirq_probe, 0, SA_INTERRUPT, NULL}; + +void autoirq_setup(int waittime) +{ + int i, mask; + int timeout = jiffies+waittime; + + irq_number = 0; + irq_bitmap = 0; + irq_handled = 0; + for (i = 0; i < 16; i++) { + if (!irqaction(i, &autoirq_sigaction)) + set_bit(i, (void *)&irq_handled); /* irq_handled |= 1 << i;*/ + } + /* Hang out at least jiffies waiting for bogus IRQ hits. */ + while (timeout >= jiffies) + ; + + for (i = 0, mask = 0x01; i < 16; i++, mask <<= 1) { + if (irq_bitmap & irq_handled & mask) { + irq_handled &= ~mask; + printk(" Spurious interrupt on IRQ %d\n", i); + free_irq(i); + } + } +} + +int autoirq_report(int waittime) +{ + int i; + int timeout = jiffies+waittime; + + /* Hang out at least jiffies waiting for the IRQ. */ + while (timeout >= jiffies) + if (irq_number) + break; + + /* Retract the irq handlers that we installed. */ + for (i = 0; i < 16; i++) { + if (test_bit(i, (void *)&irq_handled)) + free_irq(i); + } + return irq_number; +} + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c auto_irq.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether/hp.c b/net/tcpip/newether/hp.c new file mode 100644 index 00000000..7d412518 --- /dev/null +++ b/net/tcpip/newether/hp.c @@ -0,0 +1,312 @@ +/* hp.c: A HP LAN ethernet driver for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This is a driver for the HP LAN adaptors. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +static char *version = "hp.c:v0.28 1/28/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define port_read_b(port,buf,nr) \ +__asm__("cld;rep;insb"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write_b(port,buf,nr) \ +__asm__("cld;rep;outsb"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define HP_DATAPORT 0x0c /* "Remote DMA" data port. */ +#define HP_ID 0x07 +#define HP_CONFIGURE 0x08 /* Configuration register. */ +#define HP_RUN 0x01 /* 1 == Run, 0 == reset. */ +#define HP_IRQ 0x0E /* Mask for software-configured IRQ line. */ +#define HP_DATAON 0x10 /* Turn on dataport */ +#define NIC_OFFSET 0x10 /* Offset the 8390 registers. */ + +#define HP_START_PG 0x00 /* First page of TX buffer */ +#define HP_8BSTOP_PG 0x80 /* Last page +1 of RX ring */ +#define HP_16BSTOP_PG 0xFF /* Last page +1 of RX ring */ + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int hpprobe(int ioaddr, struct device *dev); +int hpprobe1(int ioaddr, struct device *dev); + +static void hp_reset_8390(struct device *dev); +static int hp_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void hp_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static void hp_init_card(struct device *dev); + + +/* Probe for an HP LAN adaptor. + Also initialize the card and fill in STATION_ADDR with the station + address. */ + +int hpprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x320, 0x340, 0x280, 0x2C0, 0x200, 0x240, 0}; + + if (ioaddr > 0x100) + return hpprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb_p(*port) != 0xff && hpprobe1(*port, dev)) + return dev->base_addr; + return 0; +} + +int hpprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + unsigned char SA_prom[6]; + int tmp; + int hplan; + + printk("HP-LAN ethercard probe at %#3x:", ioaddr); + tmp = inb_p(ioaddr); + if (tmp == 0xFF) { + printk(" not found (nothing there).\n"); + return 0; + } + + for(i = 0; i < sizeof(SA_prom); i++) { + SA_prom[i] = inb(ioaddr + i); + if (i < ETHER_ADDR_LEN && station_addr) { + printk(" %2.2x", SA_prom[i]); + station_addr[i] = SA_prom[i]; + } + } + hplan = (SA_prom[0] == 0x08 && SA_prom[1] == 0x00 && SA_prom[2] == 0x09); + if (hplan == 0) { + printk(" not found (invalid station address prefix).\n"); + return 0; + } + + ei_status.tx_start_page = HP_START_PG; + ei_status.rx_start_page = HP_START_PG + TX_PAGES; + /* Set up the rest of the parameters. */ + if ((tmp = inb_p(HP_ID)) & 0x80) { + ei_status.name = "HP27247"; + ei_status.word16 = 1; + ei_status.stop_page = HP_16BSTOP_PG; /* Safe for now */ + } else { + ei_status.name = "HP27250"; + ei_status.word16 = 0; + ei_status.stop_page = HP_8BSTOP_PG; /* Safe for now */ + } + + /* Set the base address to point to the NIC! */ + dev->base_addr = ioaddr + NIC_OFFSET; + + if (dev->irq == 2) + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + if (dev->irq < 2) { + int *irq, irq_list[] = { 11, 10, 5, 3, 4, 7, 9, 0}; + for (irq = irq_list; *irq; irq++) { + if (irqaction(*irq, &ei_sigaction) == 0) + break; + } + if (*irq == 0) { + printk (" unable to get an IRQ.\n"); + return 0; + } + dev->irq = *irq; + } + + printk(" %s found, using IRQ %d.\n", ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + + ei_status.reset_8390 = &hp_reset_8390; + ei_status.block_input = &hp_block_input; + ei_status.block_output = &hp_block_output; + hp_init_card(dev); + return dev->base_addr; +} + +static void +hp_reset_8390(struct device *dev) +{ + int hp_base = dev->base_addr - NIC_OFFSET; + int saved_config = inb_p(hp_base + HP_CONFIGURE); + int reset_start_time = jiffies; + + if (ei_debug > 1) printk("resetting the 8390 time=%d...", jiffies); + outb_p(0x00, hp_base + HP_CONFIGURE); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + break; + } + } + + outb_p(saved_config, hp_base + HP_CONFIGURE); + while ((inb_p(hp_base+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk(EI_NAME": hp_reset_8390() did not complete.\n"); + return; + } + if (ei_debug > 1) printk("8390 reset done.", jiffies); +} + +/* Block input and output, similar to the Crynwr packet driver. If you + porting to a new ethercard look at the packet driver source for hints. + The HP LAN doesn't use shared memory -- we put the packet + out through the "remote DMA" dataport. */ + +static int +hp_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int nic_base = dev->base_addr; + int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); + int xfer_count = count; + + outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base); + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); + outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, nic_base); + if (ei_status.word16) { + port_read(nic_base - NIC_OFFSET + HP_DATAPORT,buf,count>>1); + if (count & 0x01) + buf[count-1] = inb(nic_base - NIC_OFFSET + HP_DATAPORT), xfer_count++; + } else { + /* Input the bytes with a slow 8-bit loop. Someday change this to: + port_read_b(nic_base - NIC_OFFSET + HP_DATA_PORT,buf, count); */ + int i; + for(i = 0; i < count; i++) { + buf[i] = inb_p(nic_base - NIC_OFFSET + HP_DATAPORT); + } + } + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + /* Check only the lower 8 bits so we can ignore ring wrap. */ + if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff)) + printk(EI_NAME": RX transfer address mismatch, %#4.4x vs. %#4.4x (actual).\n", + ring_offset + xfer_count, addr); + } + outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); + return ring_offset + count; +} + +static void +hp_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page) +{ + int nic_base = dev->base_addr; + int saved_config = inb_p(nic_base - NIC_OFFSET + HP_CONFIGURE); + int i; + + outb_p(saved_config | HP_DATAON, nic_base - NIC_OFFSET + HP_CONFIGURE); + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + if (ei_status.word16 && (count & 0x01)) + count++; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base); + +#ifdef notdef + /* Handle the read-before-write bug the same way as the + Crynwr packet driver -- the NatSemi method doesn't work. */ + outb_p(0x42, nic_base + EN0_RCNTLO); + outb_p(0, nic_base + EN0_RCNTHI); + outb_p(0xff, nic_base + EN0_RSARLO); + outb_p(0x00, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + /* Make certain that the dummy read has occured. */ + inb_p(0x61); + inb_p(0x61); +#endif + + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(0x00, nic_base + EN0_RSARLO); + outb_p(start_page, nic_base + EN0_RSARHI); + + outb_p(E8390_RWRITE+E8390_START, nic_base); + if (ei_status.word16) { + /* Use the 'rep' sequence for 16 bit boards. */ + port_write(nic_base - NIC_OFFSET + HP_DATAPORT, buf, count>>1); + } else { + /* Output the bytes with a slow 8-bit loop. This actually is almost + as fast as possible, but it does tie up the processor. We could + also use a 'rep' sequnce here. */ + for(i = 0; i < count; i++) + outb_p(buf[i], nic_base - NIC_OFFSET + HP_DATAPORT); + } + + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */ + + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + if ((start_page << 8) + count != addr) + printk(EI_NAME": TX Transfer address mismatch, %#4.4x vs. %#4.4x.\n", + (start_page << 8) + count, addr); + } + outb_p(saved_config & (~HP_DATAON), nic_base - NIC_OFFSET + HP_CONFIGURE); + return; +} + +/* This function resets the ethercard if something screws up. */ +static void +hp_init_card(struct device *dev) +{ + int irq = dev->irq; + /* default is IRQ5 0 1 2 3 4 5 6 7 8 9 10 11 */ + static char irqval[16] = { 0, 0, 4, 6, 8,10, 0,14, 0, 4, 2,12,0,0,0,0}; + NS8390_init(dev, 0); + outb_p(irqval[irq&0x0f] | HP_RUN, + dev->base_addr - NIC_OFFSET + HP_CONFIGURE); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c hp.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether/ne.c b/net/tcpip/newether/ne.c new file mode 100644 index 00000000..f718cb8b --- /dev/null +++ b/net/tcpip/newether/ne.c @@ -0,0 +1,372 @@ +/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */ +/* + Written 1992,1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This driver should work with many 8390-based ethernet boards. Currently + it support the NE1000, NE2000 (and clones), and some Cabletron products. + 8-bit ethercard support is enabled with #define EI_8BIT + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 +*/ + +/* Routines for the NatSemi-based designs (NE[12]000). */ + +static char *version = + "ne.c:v0.27 1/27/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + +/* These should be in someday, borrowed from blk_drv/hd.c. */ +#define port_read(port,buf,nr) \ +__asm__("cld;rep;insw"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write(port,buf,nr) \ +__asm__("cld;rep;outsw"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define port_read_b(port,buf,nr) \ +__asm__("cld;rep;insb"::"d" (port),"D" (buf),"c" (nr):"cx","di") +#define port_write_b(port,buf,nr) \ +__asm__("cld;rep;outsb"::"d" (port),"S" (buf),"c" (nr):"cx","si") + +#define EN_CMD (dev->base_addr) +#define NE_BASE (dev->base_addr) +#define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ +#define NE_RESET 0x1f /* Issue a read to reset, a write to clear. */ + +#define NE1SM_START_PG 0x20 /* First page of TX buffer */ +#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ +#define NESM_START_PG 0x40 /* First page of TX buffer */ +#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int neprobe(int ioaddr, struct device *dev); +static int neprobe1(int ioaddr, struct device *dev); + +static void ne_reset_8390(struct device *dev); +static int ne_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void ne_block_output(struct device *dev, const int count, + const unsigned char *buf, const int start_page); +static void ne_init_card(struct device *dev); + + +/* Probe for the NE1000 and NE2000. NEx000-like boards have 0x57,0x57 in + bytes 0x0e,0x0f of the SAPROM, but if we read by 16 bit words the NE1000 + appears to have 0x00, 0x42. */ +/* Also initialize the card and fill in STATION_ADDR with the station + address. The station address (and other data) is stored in the + packet buffer memory space, 32 bytes starting at remote DMA address 0. */ + +int neprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x320, 0x340, 0x360, 0}; + + if (ioaddr > 0x100) + return neprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb_p(*port) != 0xff && neprobe1(*port, dev)) + return dev->base_addr = *port; + return 0; +} + +static int neprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + unsigned char SA_prom[32]; + int cmdreg; + int ne2000 = 0, ne1000 = 0, ctron = 0; + + printk("8390 ethercard probe at %#3x:", ioaddr); + + cmdreg = inb_p(ioaddr); + if (cmdreg == 0xFF) { + printk(" not found (%#2.2x).\n", cmdreg); + return 0; + } + /* Ooops, we must first initialize registers -- we can't just read the PROM + address right away. (Learned the hard way.) */ + /* NS8390_init(eifdev, 0);*/ + outb_p(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr); +#ifdef EI_8BIT + outb_p(0x48, ioaddr + EN0_DCFG); /* Set byte-wide for probe. */ +#else + outb_p(0x49, ioaddr + EN0_DCFG); /* Set word-wide for probe. */ +#endif + /* Even though we'll set them soon, we must clear them! */ + outb_p(0x00, ioaddr + EN0_RCNTLO); + outb_p(0x00, ioaddr + EN0_RCNTHI); + + outb_p(0x00, ioaddr + EN0_IMR); /* Mask completion irq. */ + outb_p(0xFF, ioaddr + EN0_ISR); + + /* Set to monitor and loopback mode. */ + outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* 0x20 */ + outb_p(E8390_TXOFF, ioaddr + EN0_TXCR); /* 0x02 */ + + +#ifdef EI_8BIT + outb_p(sizeof(SA_prom), ioaddr + EN0_RCNTLO); +#else + /* Double count 0x20 words, the SA PROM is only byte wide. */ + outb_p(2*sizeof(SA_prom), ioaddr + EN0_RCNTLO); +#endif + outb_p(0x00, ioaddr + EN0_RCNTHI); + outb_p(0x00, ioaddr + EN0_RSARLO); /* DMA starting at 0x0000. */ + outb_p(0x00, ioaddr + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, ioaddr); + for(i = 0; i < sizeof(SA_prom); i++) { + SA_prom[i] = inb_p(ioaddr + NE_DATAPORT); + if (i < ETHER_ADDR_LEN && station_addr) { + printk(" %2.2x", SA_prom[i]); + station_addr[i] = SA_prom[i]; + } + } +#ifdef EI_8BIT + ne1000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); +#else + ne2000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); + ne1000 = (SA_prom[14] == 0x00 && SA_prom[15] == 0x42); + ctron = (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d); +#endif + + /* Set up the rest of the parameters. */ + if (ne1000) { + ei_status.name = "NE1000"; + ei_status.word16 = 0; + ei_status.tx_start_page = NE1SM_START_PG; + ei_status.rx_start_page = NE1SM_START_PG + TX_PAGES; + ei_status.stop_page = NE1SM_STOP_PG; + } else if (ne2000) { + ei_status.name = "NE2000"; + ei_status.word16 = 1; + ei_status.tx_start_page = NESM_START_PG; + ei_status.rx_start_page = NESM_START_PG + TX_PAGES; + ei_status.stop_page = NESM_STOP_PG; + } else if (ctron) { + /* You'll have to set these yourself, but this info might be useful. + Cabletron packet buffer locations: + E1010 starts at 0x100 and ends at 0x2000. + E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory") + E2010 starts at 0x100 and ends at 0x4000. + E2010-x starts at 0x100 and ends at 0xffff. */ + ei_status.name = "Cabletron"; + ei_status.word16 = 1; + ei_status.tx_start_page = 0x01; + ei_status.rx_start_page = 0x01 + TX_PAGES; +#ifndef CTRON_MEMSIZE +#define CTRON_MEMSIZE 0x20 /* Extra safe... */ +#endif + ei_status.stop_page = CTRON_MEMSIZE; + } else { + printk(" not found.\n"); + return 0; + } + + dev->base_addr = ioaddr; + + if (dev->irq < 2) { + int nic_base = dev->base_addr; + autoirq_setup(0); + outb_p(0x50, nic_base + EN0_IMR); /* Enable one interrupt. */ + outb_p(0x00, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(E8390_RREAD+E8390_START, nic_base); /* Trigger it... */ + outb_p(0x00, nic_base + EN0_IMR); /* Mask it again. */ + dev->irq = autoirq_report(0); + if (ei_debug > 2) + printk(" autoirq is %d", dev->irq); + } else if (dev->irq == 2) + /* Fixup for users that don't know that IRQ 2 is really IRQ 9, + or don't know which one to set. */ + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + { int irqval = irqaction (dev->irq, &ei_sigaction); + if (irqval) { + printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); + return 0; + } + } + + printk(" %s found, using IRQ %d.\n", ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + ei_status.reset_8390 = &ne_reset_8390; + ei_status.block_input = &ne_block_input; + ei_status.block_output = &ne_block_output; + ne_init_card(dev); + return dev->base_addr; +} + +static void +ne_reset_8390(struct device *dev) +{ + int tmp = inb_p(NE_BASE + NE_RESET); + int reset_start_time = jiffies; + + if (ei_debug > 1) printk("resetting the 8390 t=%d...", jiffies); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + break; + } + } + + outb_p(tmp, NE_BASE + NE_RESET); + while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk(EI_NAME": ne_reset_8390() did not complete.\n"); + break; + } +} + +/* Block input and output, similar to the Crynwr packet driver. If you + porting to a new ethercard look at the packet driver source for hints. + The NEx000 doesn't have shared memory on the board -- put the packet + out through the "remote DMA" dataport. */ + +static int +ne_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + int xfer_count = count; + int nic_base = NE_BASE; + + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, EN_CMD); + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); + outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + if (ei_status.word16) { + port_read(NE_BASE + NE_DATAPORT,buf,count>>1); + if (count & 0x01) + buf[count-1] = inb(NE_BASE + NE_DATAPORT), xfer_count++; + } else { + /* Input the bytes with a slow 8-bit loop. Someday change this to: + port_read_b(NE_BASE + NE_DATAPORT, buf, count); */ + int i; + /* Input the bytes with a slow 8-bit loop. Tune this someday. */ + for(i = 0; i < count; i++) { + buf[i] = inb_p(NE_BASE + NE_DATAPORT); + } + } + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + /* Check only the lower 8 bits so we can ignore ring wrap. */ + if (((ring_offset + xfer_count) & 0xff) != (addr & 0xff)) + printk(EI_NAME": RX transfer address mismatch, %#4.4x (should be) vs. %#4.4x (actual).\n", + ring_offset + xfer_count, addr); + } + return ring_offset + count; +} + +static void +ne_block_output(struct device *dev, int count, + const unsigned char *buf, const int start_page) +{ + int i, retries = 0; + int nic_base = NE_BASE; + + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + if (ei_status.word16 && (count & 0x01)) + count++; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, EN_CMD); + + retry: +#if !defined(no_rw_bugfix) && 0 + /* Handle the read-before-write bug the same way as the + Crynwr packet driver -- the NatSemi method doesn't work. + Actually this doesn't aways work either, but if you have + problems with your NEx000 this is better than nothing! */ + outb_p(0x42, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(0x42, nic_base + EN0_RSARLO); + outb_p(0x00, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, EN_CMD); + /* Make certain that the dummy read has occured. */ + SLOW_DOWN_IO; + SLOW_DOWN_IO; + SLOW_DOWN_IO; +#endif /* no_rw_bugfix */ + + /* Now the normal output. */ + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(0x00, nic_base + EN0_RSARLO); + outb_p(start_page, nic_base + EN0_RSARHI); + + outb_p(E8390_RWRITE+E8390_START, EN_CMD); + if (ei_status.word16) { + /* Use the 'rep' sequence for 16 bit boards. */ + port_write(NE_BASE + NE_DATAPORT, buf, count>>1); + } else { + /* Output the bytes with a slow 8-bit loop. Someday change this to: + port_write_b(NE_BASE + NE_DATAPORT, buf, count); */ + /* Output the bytes with a slow 8-bit loop. This actually is almost + as fast as possible, but it does tie up the processor. We could + also use a 'rep' sequnce here. */ + for(i = 0; i < count; i++) + outb_p(buf[i], NE_BASE + NE_DATAPORT); + } + + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here -- it's broken! */ + + /* This is for the ALPHA version only, remove for later releases. */ + if (ei_debug > 0) { /* DMA termination address check... */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + int addr = (high << 8) + low; + if ((start_page << 8) + count != addr) + printk(EI_NAME": Packet buffer transfer address mismatch on TX, %#4.4x vs. %#4.4x.\n", + (start_page << 8) + count, addr); + if (retries++ == 0) + goto retry; + } + return; +} + +/* This function resets the ethercard if something screws up. */ +static void +ne_init_card(struct device *dev) +{ + NS8390_init(dev, 0); + return; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/newether/wd.c b/net/tcpip/newether/wd.c new file mode 100644 index 00000000..44da7963 --- /dev/null +++ b/net/tcpip/newether/wd.c @@ -0,0 +1,352 @@ +/* wd.c: A WD80x3 ethernet driver for linux. */ +/* + Written 1993 by Donald Becker. This is alpha test code. + This is a extension to the Linux operating system, and is covered by + same Gnu Public License that covers that work. + + This is a driver for the WD8003 and WD8013 ethercards. + + The Author may be reached as becker@super.org or + C/O Supercomputing Research Ctr., 17100 Science Dr., Bowie MD 20715 + + Thanks to Russ Nelson (nelson@crnwyr.com) for loaning me a WD8013. +*/ + +static char *version = + "wd.c:v0.28a 1/28/93 Donald Becker (becker@super.org)\n"; + +#include +#include +#include +#include +#include +#include + +#include "dev.h" +#include "8390.h" + + +extern void NS8390_init(struct device *dev, int startp); +extern int ei_debug; +extern struct sigaction ei_sigaction; +extern struct ei_device ei_status; + +int wdprobe(int ioaddr, struct device *dev); +int wdprobe1(int ioaddr, struct device *dev); + +static void wd_reset_8390(struct device *dev); +static int wd_block_input(struct device *dev, int count, + char *buf, int ring_offset); +static void wd_block_output(struct device *dev, int count, + const unsigned char *buf, const start_page); +static int wd_close_card(struct device *dev); + + +/* The stop page doesn't use the whole packet buffer RAM for the + 16 bit versions. This could be changed for the final version. */ +#define WD_START_PG 0x00 /* First page of TX buffer */ +#define WD_STOP_PG 0x40 /* Last page +1 of RX ring */ + +#define WD_CMDREG 0 /* Offset to ASIC command register. */ +#define WD_RESET 0x80 /* Board reset, in WD_CMDREG. */ +#define WD_MEMENB 0x40 /* Enable the shared memory. */ +#define WD_CMDREG5 5 /* Offset to 16-bit-only ASIC register 5. */ +#define ISA16 0x80 /* Enable 16 bit access from the ISA bus. */ +#define NIC16 0x40 /* Enable 16 bit access from the 8390. */ +#define WD_NIC_OFFSET 16 /* Offset to the 8390 NIC from the base_addr. */ + +/* Probe for the WD8003 and WD8013. These cards have the station + address PROM at I/O ports +8 to +13, with a checksum + following. The routine also initializes the card and fills the + station address field. */ + +int wdprobe(int ioaddr, struct device *dev) +{ + int *port, ports[] = {0x300, 0x280, 0}; + + if (ioaddr > 0x100) + return wdprobe1(ioaddr, dev); + + for (port = &ports[0]; *port; port++) + if (inb_p(*port) != 0xff && wdprobe1(*port, dev)) + return dev->base_addr; + return 0; +} + +int wdprobe1(int ioaddr, struct device *dev) +{ + int i; + unsigned char *station_addr = dev->dev_addr; + int checksum = 0; + int bits16 = 0; + +#if defined(EI_DEBUG) && EI_DEBUG > 2 + printk("WD80x3 ethercard at %#3x:", ioaddr); + for (i = 0; i < 16; i++) { + printk(" %2.2X", inb(ioaddr+i)); + } + printk("\n"); + printk("WD80x3 ethercard at %#3x:", ioaddr+i); + for (;i < 33; i++) { + printk(" %2.2X", inb(ioaddr+i)); + } + printk("\n"); +#endif + printk("WD80x3 ethercard probe at %#3x:", ioaddr); + for (i = 0; i < 8; i++) { + int inval = inb(ioaddr + 8 + i); + checksum += inval; + if (i < 6) + printk(" %2.2X", (station_addr[i] = inval)); + } + + if ((checksum & 0xff) != 0xFF) { + printk(" not found (%#2.2x).\n", checksum); + return 0; + } + + ei_status.name = "WD8003"; + ei_status.word16 = 0; + + + /* This method of checking for a 16-bit board is borrowed from the + we.c driver. A simpler method is just to look in ASIC reg. 0x03. + I'm comparing the two method in alpha test to make certain they + return the same result. */ +#ifndef FORCE_8BIT /* Same define as we.c. */ + /* check for 16 bit board - it doesn't have register 0/8 aliasing */ + for (i = 0; i < 8; i++) { + int tmp; + if( inb_p(ioaddr+8+i) != inb_p(ioaddr+i) ){ + tmp = inb_p(ioaddr+1); /* fiddle with 16bit bit */ + outb( tmp ^ 0x01, ioaddr+1 ); /* attempt to clear 16bit bit */ + if ((tmp & 0x01) == (inb_p( ioaddr+1) & 0x01)) { + int asic_reg5 = inb(ioaddr+WD_CMDREG5); + bits16 = 1; /* use word mode of operation */ + /* Magic to set ASIC to word-wide mode. */ + outb( ISA16 | NIC16 | (asic_reg5&0x1f), ioaddr+WD_CMDREG5); + outb(tmp, ioaddr+1); + ei_status.name = "WD8013"; + ei_status.word16 = 1; + break; /* We have a 16bit board here! */ + } + outb(tmp, ioaddr+1); + } + } +#else + bits8 = 1; +#endif /* FORCE_8BIT */ + +#ifndef final_version + if ((inb(ioaddr+1) & 0x01) != (ei_status.word16 & 0x01)) + printk("\nWD80x3: Bus width conflict, %d (probe) != %d (reg report).\n", + ei_status.word16 ? 16:8, (inb(ioaddr+1) & 0x01) ? 16 : 8); +#endif + + ei_status.tx_start_page = WD_START_PG; + ei_status.rx_start_page = WD_START_PG + TX_PAGES; + ei_status.stop_page = WD_STOP_PG; + +#if defined(WD_SHMEM) && WD_SHMEM > 0x80000 + /* Allow an override for alpha testing. */ + dev->mem_start = WD_SHMEM; +#else + if (dev->mem_start == 0) { + dev->mem_start = ((inb(ioaddr)&0x3f) << 13) + + (ei_status.word16 ? (inb(ioaddr+WD_CMDREG5)&0x1f)<<19 : 0x80000); + printk(" address %#x,", dev->mem_start); + } +#endif + + dev->rmem_start = dev->mem_start + TX_PAGES*256; + dev->mem_end = dev->rmem_end + = dev->mem_start + (WD_STOP_PG - WD_START_PG)*256; +#if defined(EI_DEBUG) && EI_DEBUG > 3 + memset((void*)dev->mem_start, 0x42424242, (WD_STOP_PG - WD_START_PG)*256); +#endif + + /* The 8390 isn't at the base address -- the ASIC regs are there! */ + dev->base_addr = ioaddr+WD_NIC_OFFSET; + + if (dev->irq < 2) { + int nic_base = dev->base_addr; + outb(WD_RESET, ioaddr); + autoirq_setup(1); + outb_p((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), ioaddr); /* WD_CMDREG */ + if (ei_status.word16) + outb_p( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), ioaddr+WD_CMDREG5); + /* This doesn't reliably generate an interrupt! */ + outb_p(0xff, nic_base + EN0_ISR); /* Ack. all intrs. */ + outb_p(0x50, nic_base + EN0_IMR); /* Enable "DMA complete" interrupt. */ + outb_p(0x00, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(E8390_RREAD+E8390_START, nic_base); /* Trigger it... */ + outb_p(E8390_RWRITE+E8390_START, nic_base); /* Trigger it again... */ + dev->irq = autoirq_report(1); + outb_p(0x00, nic_base + EN0_IMR); /* Mask it again. */ + if (ei_debug > 2) + printk(" autoIRQ %d", dev->irq); + if (dev->irq == 0) { + printk(" autoIRQ failed, isr=%02x", inb(nic_base + EN0_ISR)); + dev->irq = 10; + } + } else if (dev->irq == 2) + /* Fixup for users that don't know that IRQ 2 is really IRQ 9, + or don't know which one to set. */ + dev->irq = 9; + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + { int irqval = irqaction (dev->irq, &ei_sigaction); + if (irqval) { + printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval); + return 0; + } + } + + printk(" %s found, using IRQ %d.\n", ei_status.name, dev->irq); + if (ei_debug > 1) + printk(version); + + if (ei_debug > 1) + printk("%s: Address read from register is %#x, setting address %#x\n", + ei_status.name, + ((inb(ioaddr+WD_CMDREG5)&0x1f)<<19) + ((inb(ioaddr)&0x3f) << 13), + dev->mem_start); + /* Map in the shared memory. This is a little risky, since using + the stuff the user supplied is probably a bad idea. */ + outb_p((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), ioaddr); /* WD_CMDREG */ + if (ei_status.word16) + outb_p( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), ioaddr+WD_CMDREG5); + + ei_status.reset_8390 = &wd_reset_8390; + ei_status.block_input = &wd_block_input; + ei_status.block_output = &wd_block_output; + dev->stop = &wd_close_card; + NS8390_init(dev, 0); + + return dev->base_addr; +} + +static void +wd_reset_8390(struct device *dev) +{ + int wd_cmd_port = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + int reset_start_time = jiffies; + + outb(WD_RESET, wd_cmd_port); + if (ei_debug > 1) printk("resetting the WD80x3 t=%d...", jiffies); + ei_status.txing = 0; + + sti(); + /* We shouldn't use the boguscount for timing, but this hasn't been + checked yet, and you could hang your machine if jiffies break... */ + { + int boguscount = 150000; + while(jiffies - reset_start_time < 2) + if (boguscount-- < 0) { + printk("jiffy failure (t=%d)...", jiffies); + break; + } + } + + outb(0x00, wd_cmd_port); + while ((inb_p(dev->base_addr+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2) { + printk(EI_NAME": wd_reset_8390() did not complete.\n"); + break; + } +#if defined(EI_DEBUG) && EI_DEBUG > 2 + { + int i; + printk("WD80x3 ethercard at %#3x:", wd_cmd_port); + for (i = 0; i < 16; i++) { + printk(" %2.2X", inb(wd_cmd_port+i)); + } + printk("\nWD80x3 ethercard at %#3x:", wd_cmd_port); + for (;i < 33; i++) { + printk(" %2.2X", inb(wd_cmd_port+i)); + } + printk("\n"); + } +#endif + /* Set up the ASIC registers, just in case something changed them. */ + outb_p((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmd_port); /* WD_CMDREG */ + if (ei_status.word16) + outb_p( ISA16 | NIC16 | ((dev->mem_start>>19) & 0x1f), wd_cmd_port+WD_CMDREG5); + +} + +/* Block input and output are easy on shared memory ethercards, and trivial + on the Western digital card where there is no choice of how to do it. */ + +static int +wd_block_input(struct device *dev, int count, char *buf, int ring_offset) +{ + void *xfer_start = (void *)(dev->mem_start + ring_offset - (WD_START_PG<<8)); +#ifdef mapout + int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + /* Map in the shared memory. */ + outb_p((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmdreg); +#endif + if (xfer_start + count > (void*) dev->rmem_end) { + /* We must wrap the input move. */ + int semi_count = (void*)dev->rmem_end - xfer_start; + memcpy(buf, xfer_start, semi_count); + count -= semi_count; + memcpy(buf + semi_count, (char *)dev->rmem_start, count); + return dev->rmem_start + count; + } + memcpy(buf, xfer_start, count); + if (ei_debug > 4) { + unsigned short *board = xfer_start; + printk("wd8013: wd_block_input(cnt=%d offset=%3x addr=%#x) = %2x %2x %2x...\n", + count, ring_offset, xfer_start, board[-1], board[0], board[1]); + } +#ifdef mapout + outb(0, wd_cmdreg); /* WD_CMDREG: Map out the shared memory. */ +#endif + return ring_offset + count; +} + +/* This could only be outputting to the transmit buffer. The + ping-pong transmit setup doesn't work with this yet. */ +static void +wd_block_output(struct device *dev, int count, const unsigned char *buf, int start_page) +{ + unsigned char *shmem = (void *)dev->mem_start + ((start_page - WD_START_PG)<<8); +#ifdef mapout + int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */ + /* Map in the shared memory. */ + outb_p((((dev->mem_start>>13) & 0x3f)|WD_MEMENB), wd_cmdreg); +#endif + memcpy(shmem, buf, count); + if (ei_debug > 4) + printk("wd8013: wd_block_output(addr=%#x cnt=%d) -> %2x=%2x %2x=%2x %d...\n", + shmem, count, shmem[23], buf[23], shmem[24], buf[24], memcmp(shmem,buf,count)); +#ifdef mapout + outb(0, wd_cmdreg); /* WD_CMDREG: Map out the shared memory. */ +#endif +} + +/* This function resets the ethercard if something screws up. */ +static int +wd_close_card(struct device *dev) +{ + if (ei_debug > 1) + printk("%s: shutting down ethercard.\n", ei_status.name); + NS8390_init(dev, 0); + /* Turn off the shared memory. */ + outb_p((((dev->mem_start>>13) & 0x3f)), + dev->base_addr-WD_NIC_OFFSET); /* WD_CMDREG */ + return 0; +} + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c wd.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/net/tcpip/ping.README b/net/tcpip/ping.README new file mode 100644 index 00000000..b872aefd --- /dev/null +++ b/net/tcpip/ping.README @@ -0,0 +1,5 @@ +This is a ping binary for Linux .98pl5 + the 3 tcp patches. It should also +work with any kernel > .98pl5. It needs to be installed suid root. + +The source has a message saying it's public domain, but it also claims +to be Copyright by Berkeley with the standard Berkeley license. \ No newline at end of file diff --git a/net/tcpip/tcp5.diff b/net/tcpip/tcp5.diff new file mode 100644 index 00000000..ede7990d --- /dev/null +++ b/net/tcpip/tcp5.diff @@ -0,0 +1,116 @@ +From owner-linux-activists@joker.cs.hut.fi Wed Aug 5 03:51:40 1992 +Received: from funet.fi by lazy.qt.IPA.FhG.de with SMTP + (5.61+/IDA-1.2.8/gandalf.2) id AA03065; Wed, 5 Aug 92 03:51:37 +0200 +Received: from santra.hut.fi by funet.fi with SMTP (PP) id <02221-0@funet.fi>; + Wed, 5 Aug 1992 04:50:24 +0300 +Received: from joker.cs.hut.fi by santra.hut.fi (5.65c/8.0/TeKoLa) id AA17553; + Wed, 5 Aug 1992 04:50:12 +0300 +Received: by joker.cs.hut.fi (5.65b/6.8/S-TeKoLa) id AA13438; + Wed, 5 Aug 92 04:49:56 +0259 +Received: from sunlight.Stanford.EDU by joker.cs.hut.fi (5.65b/6.8/S-TeKoLa) + id AA13417; Wed, 5 Aug 92 04:49:12 +0300 +Received: from elaine12.Stanford.EDU by sunlight.Stanford.EDU (4.1/AIR-1.0) + id AA18390; Tue, 4 Aug 92 18:49:17 PDT +From: bir7@leland.stanford.edu +Message-Id: <9208050149.AA18390@sunlight.Stanford.EDU> +Subject: Re: tcp/ip diffs +Sender: owner-linux-activists@niksula.hut.fi +To: linux-activists@niksula.hut.fi +X-Note1: Remember to put 'X-Mn-Key: normal' to your mail body or header +Date: Tue, 4 Aug 92 18:49:17 PDT +Cc: linux-activists@joker.cs.hut.fi (Linux Activists), arl@cs.hut.fi +In-Reply-To: <9208050130.AA02024@klaava.Helsinki.FI>; from "Linus Torvalds" at Aug 5, 92 4:30 am +X-Mailer: ELM [version 2.3 PL11] + +X-Mn-Key: NET +> +> bir7@leland.stanford.edu: "tcp/ip diffs" (Aug 4, 16:44): +> > Here are diffs against .97 (+ profile patches) that are required for +> > all the tcp/ip code. It includes 4 files, one for vhangup, one for +> > the tty's, one for fcntl, and one for the net directory. I would +> > appretiate it if you would include all these diffs in the next +> > release. +> +> Your next message indicated there were problems with the patch, so I +> won't put it in yet. Other than that, I think I'm ready for the tcp/ip +> code. + Some diffs to fix the problem are at the end of the message. +For the net/tcp directory, you should probably get it from nic.funet.fi +Linux/testing/beta/NET, as it's very big. +> +> One thing I've been wondering about: does the tcp/ip code use 386bsd +> code heavily? I've had a few people asking about it, as they don't like +> the USL suit against BSDI. I'd rather be NET/2 free (which the current +> kernel should be), although I personally think the USL suit will fail +> (but it may take some time) +> + All the clients and servers are from BIND. The only kernel +code that is remotely related to anything is the wd8003 driver. I used +the 386bsd driver as an example when I wrote the code. But basically +everything is different. The basic tcp/ip code was written completely +by me. The only thing I've gotten from anyone else is some icmp code +which is probably not from net2, as it has to interface with everything +I did which is not remotely like anything in net2 (Actually I don't know +this since I haven't look at the net2 code, but the way the tcp/ip code +evolved it couldn't be like anything else.) + +Everyone Please note at the end of this message are some diffs which must +be applied for unix domain sockets to work (after applying my sock.diff +which screws them up.) + +[Ari, Please add them to the ftp site either in the tar file or next to it.] + +Ross Biro bir7@leland.stanford.edu +Member League for Programming Freedom (LPF) +mail league@prep.ai.mit.edu for information + +ps. I'm using X right now, so the diffs work. +---- important diffs ----- +*** ../linux/net/unix.c Tue Aug 4 12:26:38 1992 +--- linux/net/unix.c Tue Aug 4 17:30:29 1992 +*************** +*** 431,441 **** + { + struct socket *clientsock; + + PRINTK("unix_proto_accept: socket 0x%x accepted via socket 0x%x\n", + sock, newsock); +- unix_data_ref(UN_DATA(newsock->conn)); + + /* + * if there aren't any sockets awaiting connection, then wait for + * one, unless nonblocking + */ +--- 431,440 ---- +*************** +*** 446,456 **** + if (current->signal & ~current->blocked) { + PRINTK("sys_accept: sleep was interrupted\n"); + return -ERESTARTSYS; + } + } +- UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn); + + /* + * great. finish the connection relative to server and client, + * wake up the client and return the new fd to the server + */ +--- 445,454 ---- +*************** +*** 459,468 **** +--- 457,470 ---- + newsock->conn = clientsock; + clientsock->conn = newsock; + clientsock->state = SS_CONNECTED; + newsock->state = SS_CONNECTED; + wake_up(clientsock->wait); ++ ++ unix_data_ref (UN_DATA(newsock->conn)); ++ UN_DATA(newsock)->peerupd = UN_DATA(newsock->conn); ++ + return 0; + } + + /* + * gets the current name or the name of the connected socket. + diff --git a/net/tcpip/tcp5.patch b/net/tcpip/tcp5.patch new file mode 100644 index 00000000..d353a6db --- /dev/null +++ b/net/tcpip/tcp5.patch @@ -0,0 +1,82 @@ +From owner-linux-activists@joker.cs.hut.fi Wed Aug 5 19:54:00 1992 +Received: from funet.fi by lazy.qt.IPA.FhG.de with SMTP + (5.61+/IDA-1.2.8/gandalf.2) id AA03798; Wed, 5 Aug 92 19:53:55 +0200 +Received: from santra.hut.fi by funet.fi with SMTP (PP) id <12734-0@funet.fi>; + Wed, 5 Aug 1992 20:44:54 +0300 +Received: from joker.cs.hut.fi by santra.hut.fi (5.65c/8.0/TeKoLa) id AA23193; + Wed, 5 Aug 1992 20:44:44 +0300 +Received: by joker.cs.hut.fi (5.65b/6.8/S-TeKoLa) id AA23011; + Wed, 5 Aug 92 20:44:27 +0300 +Received: from sunlight.Stanford.EDU by joker.cs.hut.fi (5.65b/6.8/S-TeKoLa) + id AA23002; Wed, 5 Aug 92 20:43:45 +0300 +Received: from elaine29.Stanford.EDU by sunlight.Stanford.EDU (4.1/AIR-1.0) + id AA23764; Wed, 5 Aug 92 10:43:45 PDT +From: bir7@leland.stanford.edu +Message-Id: <9208051743.AA23764@sunlight.Stanford.EDU> +Subject: Re: No Problem with tcpip diffs - alpha 5 +Sender: owner-linux-activists@niksula.hut.fi +To: linux-activists@niksula.hut.fi +X-Note1: Remember to put 'X-Mn-Key: normal' to your mail body or header +Date: Wed, 5 Aug 92 10:43:45 PDT +Cc: linux-activists@joker.cs.hut.fi (Linux Activists), + torvalds@kruuna.helsinki.fi (Linus Torvalds) +In-Reply-To: <9208051731.AA11359@sparta.com>; from "Robert T. Harris" at Aug 5, 92 1:31 pm +X-Mailer: ELM [version 2.3 PL11] + +X-Mn-Key: NET + +> When you are wrong - you are wrong - I was wrong - sorry! +> +> I posted a message describing problems with the tcpip alpha 5 release diffs, +> my problem turned out to be trying to patch using the alpha 4 release diffs. I +> left the old alpha release stuff in /usr/src/inet and thought that it had come +> from alpha 5 - I wondered why I had a duplicate set of diffs at /usr/src! +> + + Actually I think there may be problems with the diffs (Coming from +me you should expect that.) They may have part of the profiling code in +them. It seems that they are against a stock .97 kernel without the +profiling code, but the "new" kernel had the profiling code in. If +something strange happens, it might be do to that. Now on to the bugs. + + First You will only be able to connect via the loopback interface +for 2 reasons. + + 1) in line 107 of sock.h in the definition of struct sock: + unsigned long retransmits should be long retransmits + (connect sets it to negative to give more time to make the + connection.) + + 2) ip.c: ip_compute_csum + unsigned short sum = 0; +should be + unsigned long sum = 0; + + (around line 604) + shrl $16, %%eax + adcw %%ax, %%bx + adcw $0, %%bx + should be + shrl $16, %%eax + addw %%ax, %%bx <- changed the 'c' to a 'd' + adcw $0, %%bx + + + And (this one shouldn't matter.) + (around line 622) + lodsb + movb $0,%%al + should be + lodsb + movb $0, %%ah <-- change the 'l' to a 'h' + +With this I can connect using other than the loopback interface. +(It's what I get for rushing and only testing it with itself when +I've made some major changes.) + +I'm sorry for the inconvenience. + +Ross Biro bir7@leland.stanford.edu +Member League for Programming Freedom (LPF) +mail league@prep.ai.mit.edu for information + diff --git a/net/tcpip/tcp8p1.tar.Z.uue b/net/tcpip/tcp8p1.tar.Z.uue new file mode 100644 index 00000000..3370092e Binary files /dev/null and b/net/tcpip/tcp8p1.tar.Z.uue differ diff --git a/net/tcpip/tcp8p2-against-0.98p2.uue b/net/tcpip/tcp8p2-against-0.98p2.uue new file mode 100644 index 00000000..c7be3974 Binary files /dev/null and b/net/tcpip/tcp8p2-against-0.98p2.uue differ diff --git a/net/tcpip/tcp98pl5-p3.README b/net/tcpip/tcp98pl5-p3.README new file mode 100644 index 00000000..0f2a57b8 --- /dev/null +++ b/net/tcpip/tcp98pl5-p3.README @@ -0,0 +1,2 @@ +This is the third tcp patch to 0.98pl5. All three go in without any problem. +This one fixes raw sockets and a few other minor problems. diff --git a/net/tcpip/tcpip.README b/net/tcpip/tcpip.README new file mode 100644 index 00000000..0ad64918 --- /dev/null +++ b/net/tcpip/tcpip.README @@ -0,0 +1,4 @@ +tcpip.tar.Z contains a working config (and source) as well as +services protocols and the install script. Get the Linux TCP/IP +FAQ for more information on how to set things up. + diff --git a/net/tcpip/tcpip.iafa b/net/tcpip/tcpip.iafa new file mode 100644 index 00000000..4e2797d4 --- /dev/null +++ b/net/tcpip/tcpip.iafa @@ -0,0 +1,23 @@ +Package-Name: tcpip.8.tar.Z + +Title: Linux tcpip configuration and support programs + +Version: 1.0 + +Description: configuration program for Inet sockets for Linux + +Author: Ross Biro bir7@leland.stanford.edu + +Maintained-by: Author + +Maintained-at: Check tsx-11.mit.edu and nic.funet.fi + +Platforms: Linux .98pl5+(4 meg of ram may be needed.) + +Copying-Policy: Copyrighted Liscensed under GPL + +Keywords: tcp ip tcp/ip network ethernet sockets internet + + + + diff --git a/net/tcpip/tcpip.tar.Z.A5 b/net/tcpip/tcpip.tar.Z.A5 new file mode 100644 index 00000000..c02e3c65 Binary files /dev/null and b/net/tcpip/tcpip.tar.Z.A5 differ diff --git a/net/tcpip/tcpip.tar.Z.A6 b/net/tcpip/tcpip.tar.Z.A6 new file mode 100644 index 00000000..be336fda Binary files /dev/null and b/net/tcpip/tcpip.tar.Z.A6 differ diff --git a/net/tcpip/tcpip.tar.Z.A7 b/net/tcpip/tcpip.tar.Z.A7 new file mode 100644 index 00000000..694f9a83 Binary files /dev/null and b/net/tcpip/tcpip.tar.Z.A7 differ diff --git a/net/tcpip/tcpip082-udp_rcv-patch b/net/tcpip/tcpip082-udp_rcv-patch new file mode 100644 index 00000000..c0dcb290 Binary files /dev/null and b/net/tcpip/tcpip082-udp_rcv-patch differ