]> git.neil.brown.name Git - history.git/commitdiff
Import 2.0.26 2.0.26
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:23 +0000 (15:11 -0500)
committerAlan Cox <alan@lxorguk.ukuu.org.uk>
Fri, 23 Nov 2007 20:11:23 +0000 (15:11 -0500)
66 files changed:
CREDITS
Documentation/Changes
Documentation/Configure.help
Documentation/isdn/INTERFACE
Documentation/unicode.txt
MAINTAINERS
Makefile
arch/alpha/kernel/bios32.c
arch/alpha/kernel/entry.S
arch/i386/kernel/ksyms.c
arch/i386/kernel/time.c
arch/i386/mm/init.c
drivers/block/ide-tape.c
drivers/block/ide.c
drivers/cdrom/mcd.c
drivers/isdn/icn/icn.c
drivers/isdn/icn/icn.h
drivers/isdn/isdn_cards.c
drivers/isdn/isdn_common.c
drivers/isdn/isdn_net.c
drivers/isdn/isdn_ppp.c
drivers/isdn/isdn_ppp.h
drivers/isdn/isdn_tty.c
drivers/isdn/pcbit/drv.c
drivers/isdn/teles/callc.c
drivers/isdn/teles/card.c
drivers/isdn/teles/isdnl3.c
drivers/isdn/teles/l3_1TR6.c
drivers/isdn/teles/l3_1TR6.h
drivers/isdn/teles/llglue.c
drivers/isdn/teles/q931.c
drivers/net/README.multicast
drivers/net/de4x5.c
drivers/net/depca.c
drivers/net/ewrk3.c
drivers/net/loopback.c
drivers/net/tulip.c
drivers/pci/pci.c
drivers/scsi/Config.in
drivers/scsi/advansys.c
drivers/scsi/eata.c
drivers/scsi/eata.h
drivers/scsi/g_NCR5380.c
drivers/scsi/ppa.c
drivers/scsi/scsi.c
drivers/scsi/u14-34f.c
drivers/scsi/u14-34f.h
include/asm-alpha/unistd.h
include/linux/igmp.h
include/linux/isdn.h
include/linux/isdnif.h
include/linux/major.h
include/linux/pci.h
include/net/protocol.h
include/net/tcp.h
include/net/udp.h
net/appletalk/ddp.c
net/ax25/af_ax25.c
net/ipv4/icmp.c
net/ipv4/igmp.c
net/ipv4/ip_fragment.c
net/ipv4/ipmr.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/unix/af_unix.c

diff --git a/CREDITS b/CREDITS
index df5e734fd3835583889bb4288cdd5559e7c9566c..252120ab27e064ec335a7a8f9e64ff2e374ca34f 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -68,7 +68,7 @@ D: Wrote SYS V IPC (part of standard kernel since 0.99.10)
 N: Dario Ballabio
 E: dario@milano.europe.dg.com
 D: Author and maintainer of the Ultrastor 14F/34F SCSI driver
-D: Author and maintainer of the EATA ISA/EISA SCSI driver
+D: Author and maintainer of the EATA ISA/EISA/PCI SCSI driver
 S: Data General Corporation
 S: Milano
 S: Italy
@@ -371,6 +371,14 @@ S: Myrstuguv. 83
 S: S-143 32 VARBY
 S: Sweden
 
+N: Fritz Elfert
+E: fritz@wuemaus.franken.de
+D: ISDN subsystem
+D: ICN ISDN driver
+S: Grombuehlstr. 11r
+S: 97080 Wuerzburg
+S: Germany
+
 N: Paal-Kristian Engstad
 E: engstad@funcom.com
 D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
index 63c6dc1290c4125db834c2fd1d2fcd16d2806051..9ccdff91c85db8a6a5c48efda95eccf606e6c937 100644 (file)
@@ -34,7 +34,10 @@ http://www.datanet.hu/generations/linux/Changes.html (English version).
 bunshou no nihongo ban wa
 http://jf.gee.kyoto-u.ac.jp/JF/v2.0/Changes-2.0.html ni arimasu.
 
-Last updated: October 12, 1996.
+   Voyez le site http://www.linux-kheops.com/traduc/kernels/ pour la
+traduction francais (merci, David Bourgin).  (French translation)
+
+Last updated: November 5, 1996.
 Current Author: Chris Ricker (gt1355b@prism.gatech.edu).
 
 Current Releases
@@ -43,16 +46,16 @@ Current Releases
 - Kernel modules        2.0.0
 - PPP daemon            2.2.0f
 - Dynamic linker (ld.so) 1.7.14
-- GNU CC                2.7.2
+- GNU CC                2.7.2.1
 - Binutils              2.7.0.3
-- Linux C Library       Stable:  5.2.18, Beta:  5.3.12 / 5.4.7
-- Linux C++ Library     2.7.1.4
+- Linux C Library       Stable:  5.2.18, Beta:  5.4.10
+- Linux C++ Library     2.7.2.1
 - Termcap               2.0.8
 - Procps                1.01
 - Gpm                   1.10
 - SysVinit              2.64
 - Util-linux            2.5
-- Mount                  2.5k
+- Mount                  2.5p
 - Net-tools              1.32-alpha
 - Kbd                    0.91
 
@@ -69,11 +72,11 @@ daemons to quit working), look for a line like `route add -net
 127.0.0.1' in your network configuration files and change it to `route
 add -net 127.0.0.0'.
 
-   This error is present in all Red Hat distributions (and derivative
-distributions like Caldera).  If you're running one of these, edit
-/etc/sysconfig/network-scripts/ifup-lo, changing the line `route add
--net $(IPADDR)' to `route add -net 127.0.0.0' and you should be fine.
-The new Red Hat 4.0 (Colgate) distribution does not have this problem.
+   This error is present in all Red Hat distributions through Red Hat
+3.03 (and derivative distributions like Caldera).  If you're running
+one of these, edit /etc/sysconfig/network-scripts/ifup-lo, changing the
+line `route add -net $(IPADDR)' to `route add -net 127.0.0.0' and you
+should be fine.
 
    People have also reported problems due to the naming of the dummy
 network interface driver.  If the dummy driver is compiled into the
@@ -134,9 +137,8 @@ binary is at the end of this file).
 
    Also, the libc-5.3.x line has a known security hole relating to
 rlogin.  Libc-5.3.12 fixes this, so if you're going to run an
-experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.7 is
-currently available as well, but it has a few problems of its own (a
-few missing symbols, for example, that will break existing apps).
+experimental libc, be sure to upgrade to 5.3.12.  Libc-5.4.10 is
+currently available as well, but it may have problems, so caveat emptor.
 
    If you're getting an error message that is something to the effect of
 
@@ -271,7 +273,7 @@ allowed.  For example, a file cannot be simultaneously locked with
 details.  Among the programs this has impacted are older sendmails.  If
 you get a message that sendmail cannot lock aliases.dir (or other
 files), you'll need to upgrade to at least 8.7.x. The latest sendmail
-is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.7.5.tar.gz.
+is at ftp://ftp.cs.berkeley.edu/ucb/src/sendmail/sendmail.8.8.2.tar.gz.
 
 Uugetty
 =======
@@ -293,7 +295,7 @@ Mount
 currently at release 2.5.  Some may find, especially when using the
 loop or xiafs file system, NFS, or automounting, that they need to
 upgrade to the latest release of mount, available from
-ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5k.tar.gz.
+ftp://ftp.win.tue.nl/pub/linux/util/mount-2.5p.tar.gz.
 
 Console
 =======
@@ -504,7 +506,7 @@ ftp://tsx-11.mit.edu/pub/linux/BETA/ibcs2/ibcs-2.0-960610.tar.gz
 
    For a version of Dosemu that works (well, at least as well as DOS
 ever works ;-), get
-ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/Development/dosemu-0.63.1.55.tgz
+ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/Development/dosemu-0.64.0.3.tgz
 or check out http://www.ednet.ns.ca/auto/rddc. Be sure to follow the
 instructions in README.newkernels about patching your include files, or
 it will not compile.
@@ -584,7 +586,8 @@ How to know the version of the installed programs
 *************************************************
 
    There are some simple methods useful to know the version of the
-installed programs and libraries.
+installed programs and libraries.  The SysVinit version display
+requires that you be logged in as root.
 
 GNU CC: gcc -v and gcc --version
 PPP: pppd -h (wrong but it show the version)
@@ -595,6 +598,8 @@ ldd: ldd -v and ldd -V
 termcap: ls -l /lib/libtermcap.so.*
 modules: insmod -V
 procps: ps --version
+SysVinit: cat /proc/`cat /var/run/syslog.pid`/environ|strings|awk '$1 ~
+/INIT_VERSION/ {print}'
 
 Where to get the files
 **********************
@@ -602,16 +607,16 @@ Where to get the files
 Binutils
 ========
 
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.7.0.3.bin.tar.gz
+ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/binutils-2.7.0.3.bin.tar.gz
 Installation notes:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.7.0.3
+ftp://tsx-11.mit.edu:/pub/linux/packages/GCC/release.binutils-2.7.0.3
 
 GNU CC
 ======
 
-ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.bin.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/gcc-2.7.2.1.bin.tar.gz
 Installation notes:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.gcc-2.7.2.1
 
 Linux C Library
 ===============
@@ -621,10 +626,10 @@ ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.2.18.bin.tar.gz
 Installation notes for 5.2.18:
 ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.2.18
 
-The latest 5.3.12 release:
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.3.12.bin.tar.gz
-Installation notes for 5.3.12:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.3.12
+The latest 5.4.10 release:
+ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.10.bin.tar.gz
+Installation notes for 5.4.10:
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.10
 
 Patched make sources:
 ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74.patched.tar.gz
@@ -634,12 +639,9 @@ ftp://sunsite.unc.edu/pub/Linux/devel/make/make-3.74-direntfix-elf.tgz
 Linux C++ Library
 =================
 
-ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.4.bin.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.1.3.bin.tar.gz
+ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.1.bin.tar.gz
 Installation notes:
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.4
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.1.3
-Use 2.7.13 with libc 5.2.18 and 2.7.14 with libc 5.3.12.
+ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.1
 
 Dynamic Linker
 ==============
@@ -712,11 +714,9 @@ mirrors.
    For others, David Bourgin has put together a package of everything
 necessary to quickly and easily upgrade to 2.0.x.  See
 ftp://ftp.wsc.com/pub/freeware/linux/update.linux/ for more information
-and the files.  This package also includes many bug-fixes, including
-one for a recently discovered bug in sendmail-8.7.5 (just look at
-/pub/freeware/linux/update.linux/updat2-0.addon1/sendmail-8.7.5a.tar.gz
-if you only need the bug fix).  There's also an alternate lightweight
-termcap in the same directory that works well for many people.
+and the files.  This package also includes many bug-fixes, such as the
+latest sendmail. There's also an alternate lightweight termcap in the
+same directory that works well for many people.
 
 Please send info about any other packages that 2.0.x "broke" or about
 any new features of 2.0.x that require extra or new packages for use to
index bda2615581dbf51446d525e5143bd2a3e6c01cac..8891a5c2a6d31fd1fc5d9806aa14235cdbae0c89 100644 (file)
@@ -1381,14 +1381,14 @@ CONFIG_SCSI_EATA_PIO
 
 UltraStor 14F/34F support
 CONFIG_SCSI_U14_34F
-  This is support for the UltraStor 14F, 24F and 34F SCSI-2 host
-  adaptor family. The source at drivers/scsi/u14-34f.c contains some
-  information about this hardware. If the driver doesn't work out of
-  the box, you may have to change some settings in
-  drivers/scsi/u14-34f.h. Read the SCSI-HOWTO, available via ftp
-  (user: anonymous) at sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note
-  that there is also another driver for the same hardware: "UltraStor
-  SCSI support", below. You should only enable one of them. This
+  This is support for the UltraStor 14F and 34F SCSI-2 host adapters.
+  The source at drivers/scsi/u14-34f.c contains some information about 
+  this hardware. If the driver doesn't work out of the box, you may have 
+  to change some settings in drivers/scsi/u14-34f.c.
+  Read the SCSI-HOWTO, available via ftp (user: anonymous) at 
+  sunsite.unc.edu:/pub/Linux/docs/HOWTO. Note that there is also another
+  driver for the same hardware: "UltraStor SCSI support", below.
+  You should enable both only if you want 24F support as well. This
   driver is also available as a module ( = code which can be inserted
   in and removed from the running kernel whenever you want). If you
   want to compile it as a module, say M here and read
@@ -1626,9 +1626,8 @@ CONFIG_SCSI_ULTRASTOR
   drivers/scsi/ultrastor.h. If you want to compile this as a module (
   = code which can be inserted in and removed from the running kernel
   whenever you want), say M here and read Documentation/modules.txt.
-  Note that there is also another driver for the same hardware:
-  "UltraStor 14F/34F support", above. You should only enable one of
-  them.
+  Note that there is also another driver for UltraStor hardware:
+  "UltraStor 14F/34F support", above.
  
 7000FASST SCSI support
 CONFIG_SCSI_7000FASST
@@ -1639,12 +1638,16 @@ CONFIG_SCSI_7000FASST
   want to compile it as a module, say M here and read
   Documentation/modules.txt.
 
-EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support
+EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support
 CONFIG_SCSI_EATA
-  This driver supports all the DPT SCSI host adapters, such as
-  PM2011B/9X, PM2021A/9X, PM2012A, PM1012B, PM2022A/9X, PM2122A/9X and
-  PM2322A/9X. Note that the PM2001 is not supported by this
-  driver. You want to read the start of drivers/scsi/eata.c and the
+  This driver supports all the EATA/DMA-compliant SCSI host adapters
+  and does not need any BIOS32 or PCI BIOS service.
+  Only ISA (0x1F0, 0x170, 0x230, 0x330) and EISA (0x1C88 through 0xFC88)
+  addresses are probed. In order to detect a generic EATA PCI board you
+  can force on it any unused EISA address.
+  Note that there is also another driver for the same hardware:
+  "EATA-DMA support". You should enable only one of them.
+  You want to read the start of drivers/scsi/eata.c and the
   SCSI-HOWTO, available via ftp (user: anonymous) at
   sunsite.unc.edu:/pub/Linux/docs/HOWTO.  If you want to compile this
   as a module ( = code which can be inserted in and removed from the
index 6ba401123adc43ad04393c50c9115a4e4bf34b84..fe2a4440cd808abf8d757f1572de4d775746fd6c 100644 (file)
@@ -1,4 +1,4 @@
-$Id: INTERFACE,v 1.3 1996/06/25 17:52:41 fritz Exp $
+$Id: INTERFACE,v 1.5 1996/11/06 17:40:47 keil Exp $
 
 Description of the Interface between Linklevel and Hardwarelevel
   of isdn4linux:
@@ -497,6 +497,12 @@ Description of the Interface between Linklevel and Hardwarelevel
       num         = ASCII-String in the following format:
                     "%s,%d,%d,%s",CallerNumber,ServiceIndicator,AddInfo,
                     CalledNumber.
+    Return:
+      0           = No device matching this call.
+      1           = At least one device matching this call (RING on ttyI).
+                    HL-driver may send ALERTING on the D-channel in this case.
+      2           = Call will be rejected.
+      -1          = An error happened. (Invalid parameters for example.)
 
   ISDN_STAT_RUN:
 
index ce2397cbfb4b55c6be789b5f94437c93400b3f68..b9f44a6eb58555fff3df5b49299cd7627df3e06d 100644 (file)
@@ -20,18 +20,20 @@ loaded.
 
 In accordance with the Unicode standard/ISO 10646 the range U+F000 to
 U+F8FF has been reserved for OS-wide allocation (the Unicode Standard
-refers to this as a "Corporate Zone").  U+F000 was picked as the
-starting point since it lets the direct-mapping area start on a large
-power of two (in case 1024- or 2048-character fonts ever become
-necessary).  This leaves U+E000 to U+EFFF as End User Zone.
+refers to this as a "Corporate Zone", since this is inaccurate for
+Linux we call it the "Linux Zone").  U+F000 was picked as the starting
+point since it lets the direct-mapping area start on a large power of
+two (in case 1024- or 2048-character fonts ever become necessary).
+This leaves U+E000 to U+EFFF as End User Zone.
 
 The Unicodes in the range U+F000 to U+F1FF have been hard-coded to map
 directly to the loaded font, bypassing the translation table.  The
 user-defined map now defaults to U+F000 to U+F1FF, emulating the
-previous behaviour.
+previous behaviour.  This range may expand in the future should it be
+warranted.
 
-Actual characters assigned in the Corporate Zone
-------------------------------------------------
+Actual characters assigned in the Linux Zone
+--------------------------------------------
 
 In addition, the following characters not present in Unicode 1.1.4 (at
 least, I have not found them!) have been defined; these are used by
@@ -58,7 +60,7 @@ also political reasons (the Japanese, for example, are not too happy
 about the whole 16-bit concept to begin with.)  However, with Linux
 being a hacker-driven OS it seems this is a brilliant linguistic hack
 worth supporting.  Hence I have chosen to add it to the list in the
-Linux "Corporate" Zone.
+Linux Zone.
 
 Several glyph forms for the Klingon alphabet has been proposed.
 However, since the set of symbols appear to be consistent throughout,
@@ -122,5 +124,16 @@ U+F8F7     KLINGON DIGIT SEVEN
 U+F8F8 KLINGON DIGIT EIGHT
 U+F8F9 KLINGON DIGIT NINE
 
+Other Fictional and Artificial Scripts
+--------------------------------------
 
-       H. Peter Anvin <hpa@storm.net>
+Since the assignment of the Klingon Linux Unicode block, a registry of
+fictional and artificial scripts has been established by John Cowan,
+<cowan@ccil.org>.  The ConScript Unicode Registry is accessible at
+http://locke.ccil.org/~cowan/csur/; the ranges used fall at the bottom
+of the End User Zone and can hence not be normatively assigned, but it
+is recommended that people who wish to encode fictional scripts use
+these codes, in the interest of interoperability.  For Klingon, CSUR
+has adopted the Linux encoding.
+
+       H. Peter Anvin <hpa@zytor.com>
index f80fedd7316c1407e78d2bbc7d79e8f2cba6d4b4..889c8d60deed6ff02a427198ca3342f918748eb1 100644 (file)
@@ -135,16 +135,16 @@ M:        Marcio Saito <marcio@cyclades.com>
 W:     http://www.cyclades.com/
 S:     Supported
 
-EATA ISA/EISA SCSI DRIVER
+EATA ISA/EISA/PCI SCSI DRIVER
 P:     Dario Ballabio
 M:     dario@milano.europe.dg.com
-L:     linux-kernel@vger.rutgers.edu
+L:     linux-scsi@vger.rutgers.edu
 S:     Maintained
 
 U14-34F SCSI DRIVER
 P:     Dario Ballabio
 M:     dario@milano.europe.dg.com
-L:     linux-kernel@vger.rutgers.edu
+L:     linux-scsi@vger.rutgers.edu
 S:     Maintained
 
 EATA-DMA SCSI DRIVER
index a0d0784d661a88927cb3bcbbb9f915e9ab245020..992cdd6fe684f0db864bbe8be25caf62f6ecc01a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 0
-SUBLEVEL = 25
+SUBLEVEL = 26
 
 ARCH = i386
 
index 1e0a5050dd20b76b238e76d1ac9e3200646520d3..37f03b3549c80617788628bfae95cfe2b88b0573 100644 (file)
@@ -37,6 +37,14 @@ int pcibios_present(void)
 {
         return 0;
 }
+asmlinkage int sys_pciconfig_read()
+{
+        return 0;
+}
+asmlinkage int sys_pciconfig_write()
+{
+        return 0;
+}
 
 #else /* CONFIG_PCI */
 
@@ -48,6 +56,7 @@ int pcibios_present(void)
 
 #include <asm/hwrpb.h>
 #include <asm/io.h>
+#include <asm/segment.h>
 
 
 #define KB             1024
@@ -1193,4 +1202,81 @@ const char *pcibios_strerror (int error)
         }
 }
 
+asmlinkage int sys_pciconfig_read(
+       unsigned long bus,
+       unsigned long dfn,
+       unsigned long off,
+       unsigned long len,
+       unsigned char *buf)
+{
+        unsigned char ubyte;
+        unsigned short ushort;
+        unsigned int uint;
+       long err = 0;
+
+       switch (len) {
+           case 1:
+               err = pcibios_read_config_byte(bus, dfn, off, &ubyte);
+               if (err != PCIBIOS_SUCCESSFUL)
+                   ubyte = 0xff;
+               put_user(ubyte, buf);
+               break;
+           case 2:
+               err = pcibios_read_config_word(bus, dfn, off, &ushort);
+               if (err != PCIBIOS_SUCCESSFUL)
+                   ushort = 0xffff;
+               put_user(ushort, (unsigned short *)buf);
+               break;
+           case 4:
+               err = pcibios_read_config_dword(bus, dfn, off, &uint);
+               if (err != PCIBIOS_SUCCESSFUL)
+                   uint = 0xffffffff;
+               put_user(uint, (unsigned int *)buf);
+               break;
+           default:
+               err = -EINVAL;
+               break;
+       }
+        return err;
+}
+asmlinkage int sys_pciconfig_write(
+       unsigned long bus,
+       unsigned long dfn,
+       unsigned long off,
+       unsigned long len,
+       unsigned char *buf)
+{
+        unsigned char ubyte;
+        unsigned short ushort;
+        unsigned int uint;
+        long err = 0;
+
+       switch (len) {
+           case 1:
+                ubyte = get_user(buf);
+                err = pcibios_write_config_byte(bus, dfn, off, ubyte);
+                if (err != PCIBIOS_SUCCESSFUL) {
+                       err = -EFAULT;
+               }
+               break;
+           case 2:
+                ushort = get_user((unsigned short *)buf);
+                err = pcibios_write_config_word(bus, dfn, off, ushort);
+                if (err != PCIBIOS_SUCCESSFUL) {
+                       err = -EFAULT;
+               }
+               break;
+           case 4:
+                uint = get_user((unsigned int *)buf);
+                err = pcibios_write_config_dword(bus, dfn, off, uint);
+                if (err != PCIBIOS_SUCCESSFUL) {
+                       err = -EFAULT;
+               }
+               break;
+           default:
+               err = -EINVAL;
+               break;
+       }
+        return err;
+}
 #endif /* CONFIG_PCI */
index 0ff8ff726463f1280a1c96d2eb8f5d4ef8d02776..b7a64848655a718e7995ef3516a76862c8fd0bf8 100644 (file)
@@ -758,4 +758,4 @@ sys_call_table:
        .quad sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler, sys_sched_yield
        .quad sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, do_entSys /* sys_afs_syscall */, sys_newuname
        .quad sys_nanosleep, sys_mremap, do_entSys, do_entSys, do_entSys
-       .quad do_entSys, do_entSys, do_entSys, do_entSys, do_entSys
+       .quad sys_pciconfig_read, sys_pciconfig_write, do_entSys, do_entSys, do_entSys
index ea39097f358cbe2208f84807b56a2cea00689782..86925d31491a26cb8c2d6b2b23913fe478be4a18 100644 (file)
@@ -19,6 +19,10 @@ static struct symbol_table arch_symbol_table = {
        X(apic_reg),            /* Needed internally for the I386 inlines */
        X(cpu_data),
        X(syscall_count),
+       X(kernel_flag),
+       X(kernel_counter),
+       X(active_kernel_processor),
+       X(smp_invalidate_needed),
 #endif
 #include <linux/symtab_end.h>
 };
index 827d86c341c2282ecdafca33f44ff984e2973a77..31166a545d9b811fc5fa8e583c1611cf80c91113 100644 (file)
@@ -471,9 +471,9 @@ void time_init(void)
                                if( x86_model == 0 ) {
                                        /* turn on cycle counters during power down */
                                        __asm__ __volatile__ (" movl $0x83, %%ecx \n \
-                                                               rdmsr \n \
+                                                               .byte 0x0f,0x32 \n \
                                                                orl $1,%%eax \n \
-                                                               wrmsr \n " 
+                                                               .byte 0x0f,0x30 \n " 
                                                                 : : : "ax", "cx", "dx" );
                                        udelay(500);
                                }
index 9fbfd3c09d24fb5cba2598e388e7ccbb7dcef77f..edcb6b0fbd70fdde153305deabc8bf7a813685de 100644 (file)
 #include <asm/pgtable.h>
 #include <asm/dma.h>
 
+#if 0
 /*
  * The SMP kernel can't handle the 4MB page table optimizations yet
  */
 #ifdef __SMP__
 #undef USE_PENTIUM_MM
 #endif
+#endif
 
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
index d397a17eb7cb0c1d3c5a45eee4a61100aac69d51..dbb718319a1a513368ade8efca43f175729c414e 100644 (file)
@@ -3717,7 +3717,7 @@ int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int
        ide_drive_t *drive=idetape_chrdev.drive;
        idetape_tape_t *tape=&(drive->tape);
        char *buf_ptr=buf;
-       int bytes_read,temp,actually_read=0, original_count = count;
+       int bytes_read,temp,actually_read=0;
 
 #if IDETAPE_DEBUG_LOG
        printk ("Reached idetape_chrdev_read\n");
@@ -3777,7 +3777,7 @@ int idetape_chrdev_read (struct inode *inode, struct file *file, char *buf, int
                tape->merge_buffer_size=bytes_read-temp;
        }
 finish:
-       if (actually_read < original_count && tape->filemark)
+       if (!actually_read && tape->filemark)
                idetape_space_over_filemarks (drive, MTFSF, 1);
        return (actually_read);
 }
index ddd80004942ebd2d56fa42a3d3f18ef374c9823b..a9803ba37390f1dbe93cdc2e363a10f1ed88218f 100644 (file)
@@ -2279,7 +2279,7 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
        ide_input_data(drive, id, SECTOR_WORDS);/* read 512 bytes of id info */
        sti();
 
-#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO)
+#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
        /*
         * EATA SCSI controllers do a hardware ATA emulation:  
         * Ignore them if there is a driver for them available.
index e529c070d01a7a54d651f277efd2d65739412a1c..155ed92d54a99a7fbad0407a46d2e2b1fc285edf 100644 (file)
        07 July 1995 Modifications by Andrew J. Kroll
 
        Bjorn Ekwall <bj0rn@blox.se> added unregister_blkdev to mcd_init()
+
+       Michael K. Johnson <johnsonm@redhat.com> added retries on open
+       for slow drives which take a while to recognize that they contain
+       a CD.
 */
 
 #include <linux/module.h>
@@ -1095,6 +1099,7 @@ int
 mcd_open(struct inode *ip, struct file *fp)
 {
        int st;
+       int count = 0;
 
        if (mcdPresent == 0)
                return -ENXIO;                  /* no hardware */
@@ -1106,9 +1111,16 @@ mcd_open(struct inode *ip, struct file *fp)
 
        mcd_invalidate_buffers();
 
-       st = statusCmd();                       /* check drive status */
-       if (st == -1)
-               return -EIO;                    /* drive doesn't respond */
+       do {
+               st = statusCmd();               /* check drive status */
+               if (st == -1)
+                       return -EIO;            /* drive doesn't respond */
+               if ((st & MST_READY) == 0) {    /* no disk? wait a sec... */
+                       current->state = TASK_INTERRUPTIBLE;
+                       current->timeout = jiffies + HZ;
+                       schedule();
+               }
+       } while (((st & MST_READY) == 0) && count++ < MCD_RETRY_ATTEMPTS);
 
        if ((st & MST_READY) == 0)              /* no disk in drive */
        {
index 65723fef99c9a45df81d2565dd3f79905c9237cb..f65becc50d5e8700c47d99de8ea0d896d5d5b2dd 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: icn.c,v 1.29 1996/08/29 20:34:54 fritz Exp $
+/* $Id: icn.c,v 1.31 1996/11/13 02:36:25 fritz Exp $
  *
  * ISDN low-level module for the ICN active ISDN-Card.
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: icn.c,v $
+ * Revision 1.31  1996/11/13 02:36:25  fritz
+ * Fixed a race condition in writecmd.
+ * Some optimizations and cleanup.
+ *
+ * Revision 1.30  1996/10/22 23:14:09  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
  * Revision 1.29  1996/08/29 20:34:54  fritz
  * Bugfix in send queue management:
  * sndcount was not updated correctly.
 #undef MAP_DEBUG
 
 static char
-*revision = "$Revision: 1.29 $";
+*revision = "$Revision: 1.31 $";
 
 static int icn_addcard(int, char *, char *);
 
@@ -153,13 +160,9 @@ static int icn_addcard(int, char *, char *);
 static void icn_free_queue(struct sk_buff_head *queue)
 {
         struct sk_buff *skb;
-        unsigned long flags;
-        
-        save_flags(flags);
-        cli();
+
         while ((skb = skb_dequeue(queue)))
                 dev_kfree_skb(skb, FREE_WRITE);
-        restore_flags(flags);
 }
 
 /* Put a value into a shift-register, highest bit first.
@@ -262,7 +265,7 @@ static inline void icn_release_channel(void)
 #endif
         save_flags(flags);
         cli();
-        if (dev.chanlock)
+        if (dev.chanlock > 0)
                 dev.chanlock--;
         restore_flags(flags);
 }
@@ -275,12 +278,12 @@ static inline int icn_trymaplock_channel(icn_card *card, int channel)
 {
         ulong flags;
 
-        save_flags(flags);
-        cli();
 #ifdef MAP_DEBUG
         printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel,
                dev.chanlock);
 #endif
+        save_flags(flags);
+        cli();
         if ((!dev.chanlock) ||
             ((dev.channel == channel) && (dev.mcard == card))) {
                 dev.chanlock++;
@@ -306,12 +309,12 @@ static inline void icn_maprelease_channel(icn_card *card, int channel)
 {
         ulong flags;
 
-        save_flags(flags);
-        cli();
 #ifdef MAP_DEBUG
         printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock);
 #endif
-        if (dev.chanlock)
+        save_flags(flags);
+        cli();
+        if (dev.chanlock > 0)
                 dev.chanlock--;
         if (!dev.chanlock)
                 icn_map_channel(card,channel);
@@ -381,10 +384,12 @@ static void icn_pollbchan_send(int channel, icn_card *card)
         struct sk_buff *skb;
         isdn_ctrl cmd;
 
-        if (!card->sndcount[channel])
+        if (!(card->sndcount[channel] ||
+             skb_queue_len(&card->spqueue[channel])))
                 return;
         if (icn_trymaplock_channel(card,mch)) {
-                while (sbfree && card->sndcount[channel]) {
+                while (sbfree && (card->sndcount[channel] ||
+                                  skb_queue_len(&card->spqueue[channel]))) {
                         save_flags(flags);
                         cli();
                         if (card->xmit_lock[channel]) {
@@ -567,6 +572,22 @@ static int icn_parse_status(u_char *status, int channel, icn_card *card)
         return dflag;
 }
 
+static void icn_putmsg(icn_card *card, unsigned char c)
+{
+        ulong flags;
+
+        save_flags(flags);
+        cli();
+        *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
+        if (card->msg_buf_write == card->msg_buf_read) {
+                if (++card->msg_buf_read > card->msg_buf_end)
+                card->msg_buf_read = card->msg_buf;
+        }
+        if (card->msg_buf_write > card->msg_buf_end)
+                card->msg_buf_write = card->msg_buf;
+        restore_flags(flags);
+}
+
 static void icn_polldchan(unsigned long data)
 {
         icn_card *card = (icn_card *)data;
@@ -585,16 +606,7 @@ static void icn_polldchan(unsigned long data)
                 avail = msg_avail;
                 for (left = avail, i = readb(&msg_o); left > 0; i++, left--) {
                         c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]);
-                        save_flags(flags);
-                        cli();
-                        *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
-                        if (card->msg_buf_write == card->msg_buf_read) {
-                                if (++card->msg_buf_read > card->msg_buf_end)
-                                        card->msg_buf_read = card->msg_buf;
-                        }
-                        if (card->msg_buf_write > card->msg_buf_end)
-                                card->msg_buf_write = card->msg_buf;
-                        restore_flags(flags);
+                        icn_putmsg(card, c);
                         if (c == 0xff) {
                                 card->imsg[card->iptr] = 0;
                                 card->iptr = 0;
@@ -833,28 +845,28 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
         printk(KERN_DEBUG "shmem=%08lx\n", (ulong) dev.shmem);
 #endif
         SLEEP(1);
-        save_flags(flags);
-        cli();
 #ifdef BOOT_DEBUG
         printk(KERN_DEBUG "Map Bank 0\n");
 #endif
+        save_flags(flags);
+        cli();
         icn_map_channel(card,0);                                   /* Select Bank 0    */
         icn_lock_channel(card,0);                                  /* Lock Bank 0      */
         restore_flags(flags);
         SLEEP(1);
-        memcpy_fromfs(codebuf, buffer, ICN_CODE_STAGE1);
+        copy_from_user(codebuf, buffer, ICN_CODE_STAGE1);
         memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1);           /* Copy code        */
 #ifdef BOOT_DEBUG
         printk(KERN_DEBUG "Bootloader transfered\n");
 #endif
         if (card->doubleS0) {
                 SLEEP(1);
-                save_flags(flags);
-                cli();
-                icn_release_channel();
 #ifdef BOOT_DEBUG
                 printk(KERN_DEBUG "Map Bank 8\n");
 #endif
+                save_flags(flags);
+                cli();
+                icn_release_channel();
                 icn_map_channel(card,2);                           /* Select Bank 8   */
                 icn_lock_channel(card,2);                          /* Lock Bank 8     */
                 restore_flags(flags);
@@ -872,11 +884,11 @@ static int icn_loadboot(u_char * buffer, icn_card * card)
         if (!card->doubleS0)
                 return 0;
         /* reached only, if we have a Double-S0-Card */
-        save_flags(flags);
-        cli();
 #ifdef BOOT_DEBUG
         printk(KERN_DEBUG "Map Bank 0\n");
 #endif
+        save_flags(flags);
+        cli();
         icn_map_channel(card,0);                                   /* Select Bank 0   */
         icn_lock_channel(card,0);                                  /* Lock Bank 0     */
         restore_flags(flags);
@@ -913,7 +925,7 @@ static int icn_loadproto(u_char * buffer, icn_card * card)
         while (left) {
                 if (sbfree) {                           /* If there is a free buffer...  */
                         cnt = MIN(256, left);
-                        memcpy_fromfs(codebuf, p, cnt);
+                        copy_from_user(codebuf, p, cnt);
                         memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data                     */ 
                         sbnext;                         /* switch to next buffer         */
                         p += cnt;
@@ -957,12 +969,12 @@ static int icn_loadproto(u_char * buffer, icn_card * card)
                         schedule();
                 } else {
                         if ((card->secondhalf) || (!card->doubleS0)) {
-                                save_flags(flags);
-                                cli();
 #ifdef BOOT_DEBUG
                                 printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n",
                                        card->secondhalf);
 #endif
+                                save_flags(flags);
+                                cli();
                                 init_timer(&card->st_timer);
                                 card->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
                                 card->st_timer.function = icn_polldchan;
@@ -995,7 +1007,7 @@ static int icn_readstatus(u_char * buf, int len, int user, icn_card * card)
                 if (card->msg_buf_read == card->msg_buf_write)
                         return count;
                 if (user)
-                        put_fs_byte(*card->msg_buf_read++, p);
+                        put_user(*card->msg_buf_read++, p);
                 else
                         *p = *card->msg_buf_read++;
                 if (card->msg_buf_read > card->msg_buf_end)
@@ -1005,64 +1017,70 @@ static int icn_readstatus(u_char * buf, int len, int user, icn_card * card)
 }
 
 /* Put command-strings into the command-queue of the Interface */
-static int icn_writecmd(const u_char * buf, int len, int user, icn_card * card, int waitflg)
+static int icn_writecmd(const u_char * buf, int len, int user, icn_card * card)
 {
-        int mch = card->secondhalf ? 2 : 0;
+       int mch = card->secondhalf ? 2 : 0;
         int avail;
         int pp;
         int i;
         int count;
+        int xcount;
         int ocount;
+        int loop;
         unsigned long flags;
+        int lastmap_channel;
+        struct icn_card *lastmap_card;
         u_char *p;
         isdn_ctrl cmd;
         u_char msg[0x100];
 
-        while (1) {
-                if (icn_trymaplock_channel(card, mch)) {
-                        avail = cmd_free;
-                        count = MIN(avail, len);
-                        if (user)
-                                memcpy_fromfs(msg, buf, count);
-                        else
-                                memcpy(msg, buf, count);
-                        save_flags(flags);
-                        cli();
-                        ocount = 1;
-                        *card->msg_buf_write++ = '>';
-                        if (card->msg_buf_write > card->msg_buf_end)
-                                card->msg_buf_write = card->msg_buf;
-                        for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp++) {
-                                writeb((*p == '\n') ? 0xff : *p,
-                                       &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]);
-                                *card->msg_buf_write++ = *p;
-                                if ((*p == '\n') && (i > 1)) {
-                                        *card->msg_buf_write++ = '>';
-                                        if (card->msg_buf_write > card->msg_buf_end)
-                                                card->msg_buf_write = card->msg_buf;
-                                        ocount++;
-                                }
-                                /* No checks for buffer overflow of raw-status-device */
-                                if (card->msg_buf_write > card->msg_buf_end)
-                                        card->msg_buf_write = card->msg_buf;
+        ocount = 1;
+        xcount = loop = 0;
+        while (len) {
+                save_flags(flags);
+                cli();
+                lastmap_card = dev.mcard;
+                lastmap_channel = dev.channel;
+                icn_map_channel(card, mch);
+               
+                avail = cmd_free;
+                count = MIN(avail, len);
+                if (user)
+                        copy_from_user(msg, buf, count);
+                else
+                        memcpy(msg, buf, count);
+                icn_putmsg(card, '>');
+                for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp
+                            ++) {
+                        writeb((*p == '\n') ? 0xff : *p,
+                               &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]);
+                        len--;
+                        xcount++;
+                        icn_putmsg(card, *p);
+                        if ((*p == '\n') && (i > 1)) {
+                                icn_putmsg(card, '>');
                                 ocount++;
                         }
-                        restore_flags(flags);
-                        cmd.command = ISDN_STAT_STAVAIL;
-                        cmd.driver = card->myid;
-                        cmd.arg = ocount;
-                        card->interface.statcallb(&cmd);
-                        writeb((readb(&cmd_i) + count) & 0xff, &cmd_i);
-                        icn_release_channel();
-                        waitflg = 0;
+                        ocount++;
+                }
+                writeb((readb(&cmd_i) + count) & 0xff, &cmd_i);
+                if (lastmap_card)
+                        icn_map_channel(lastmap_card, lastmap_channel);
+                restore_flags(flags);
+                if (len) {
+                        udelay(1000);
+                        if (loop++ > 20)
+                                break;
                 } else
-                        count = 0;
-                if (!waitflg)
                         break;
-                current->timeout = jiffies + 10;
-                schedule();
         }
-        return count;
+        if (len && (!user))
+                printk(KERN_WARNING "icn: writemsg incomplete!\n");
+        cmd.command = ISDN_STAT_STAVAIL;
+        cmd.driver = card->myid;
+        cmd.arg = ocount;
+        card->interface.statcallb(&cmd);
+        return xcount;
 }
 
 /*
@@ -1175,12 +1193,12 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                                     (void *) a,
                                                     sizeof(ulong) * 2)))
                                         return i;
-                                memcpy_tofs((char *)a,
+                                copy_from_user((char *)a,
                                             (char *)&card, sizeof(ulong));
                                a += sizeof(ulong);
                                {
                                         ulong l = (ulong)&dev;
-                                        memcpy_tofs((char *)a,
+                                        copy_from_user((char *)a,
                                                     (char *)&l, sizeof(ulong));
                                 }
                                 return 0;
@@ -1198,7 +1216,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                         case ICN_IOCTL_ADDCARD:
                                 if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(icn_cdef))))
                                         return i;
-                                memcpy_fromfs((char *)&cdef, (char *)a, sizeof(cdef));
+                                copy_from_user((char *)&cdef, (char *)a, sizeof(cdef));
                                 return (icn_addcard(cdef.port, cdef.id1, cdef.id2));
                                 break;
                         case ICN_IOCTL_LEASEDCFG:
@@ -1212,7 +1230,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                                 current->timeout = jiffies + ICN_BOOT_TIMEOUT1;
                                                 schedule();
                                                 sprintf(cbuf, "00;FV2ON\n01;EAZ1\n");
-                                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                                                 printk(KERN_INFO
                                                        "icn: (%s) Leased-line mode enabled\n",
                                                        CID);
@@ -1225,7 +1243,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                         if (card->leased) {
                                                 card->leased = 0;
                                                 sprintf(cbuf, "00;FV2OFF\n");
-                                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                                                 printk(KERN_INFO
                                                        "icn: (%s) Leased-line mode disabled\n",
                                                        CID);
@@ -1275,7 +1293,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                 *p2 = '\0';
                                 sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), dcode, dial, si1,
                                         si2, p);
-                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                         }
                         break;
                 case ISDN_CMD_ACCEPTD:
@@ -1292,10 +1310,10 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                                         sprintf(cbuf, "%02d;BTRA\n", (int) a);
                                                         break;
                                         }
-                                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                        i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                                 }
                                 sprintf(cbuf, "%02d;DCON_R\n", (int) a);
-                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                         }
                         break;
                 case ISDN_CMD_ACCEPTB:
@@ -1314,7 +1332,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                         }
                                 else
                                         sprintf(cbuf, "%02d;BCON_R\n", (int) a);
-                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                         }
                         break;
                 case ISDN_CMD_HANGUP:
@@ -1323,7 +1341,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                         if (c->arg < ICN_BCH) {
                                 a = c->arg + 1;
                                 sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
-                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                         }
                         break;
                 case ISDN_CMD_SETEAZ:
@@ -1339,7 +1357,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                 } else
                                         sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
                                                 c->num[0] ? c->num : "0123456789");
-                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                         }
                         break;
                 case ISDN_CMD_CLREAZ:
@@ -1353,7 +1371,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                         sprintf(cbuf, "%02d;MSNC\n", (int) a);
                                 else
                                         sprintf(cbuf, "%02d;EAZC\n", (int) a);
-                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                         }
                         break;
                 case ISDN_CMD_SETL2:
@@ -1371,7 +1389,7 @@ static int icn_command(isdn_ctrl * c, icn_card * card)
                                         default:
                                                 return -EINVAL;
                                 }
-                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card, 1);
+                                i = icn_writecmd(cbuf, strlen(cbuf), 0, card);
                                 card->l2_proto[a & 255] = (a >> 8);
                         }
                         break;
@@ -1455,7 +1473,7 @@ static int if_writecmd(const u_char * buf, int len, int user, int id, int channe
         if (card) {
                 if (!card->flags & ICN_FLAGS_RUNNING)
                         return -ENODEV;
-                return (icn_writecmd(buf, len, user, card, 0));
+                return (icn_writecmd(buf, len, user, card));
         }
         printk(KERN_ERR
                "icn: if_writecmd called with invalid driverId!\n");
index acbc113a260bb15c5608e35655a2318f8bb523d9..7ce78b434b6159bbe70d47f19a2eebac3178737c 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: icn.h,v 1.21 1996/08/29 20:35:57 fritz Exp $
+/* $Id: icn.h,v 1.22 1996/11/13 02:37:33 fritz Exp $
  *
  * ISDN lowlevel-module for the ICN active ISDN-Card.
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: icn.h,v $
+ * Revision 1.22  1996/11/13 02:37:33  fritz
+ * Added delay include.
+ *
  * Revision 1.21  1996/08/29 20:35:57  fritz
  * Speed up B-Channel polling interval.
  *
@@ -135,6 +138,7 @@ typedef struct icn_cdef {
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
+#include <linux/delay.h>
 #include <linux/isdnif.h>
 
 #endif /* __KERNEL__ */
index 7a3083799f2f15302d74b8b3413a4131367fda75..a70d6992ec33546ac2b098ce3326bd6d4c3d0f70 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_cards.c,v 1.1 1996/04/20 16:04:36 fritz Exp $
+/* $Id: isdn_cards.c,v 1.2 1996/10/13 19:52:17 keil Exp $
  *
  * Linux ISDN subsystem, initialization for non-modularized drivers.
  *
@@ -19,6 +19,9 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_cards.c,v $
+ * Revision 1.2  1996/10/13 19:52:17  keil
+ * HiSax support
+ *
  * Revision 1.1  1996/04/20 16:04:36  fritz
  * Initial revision
  *
 #include <linux/config.h>
 
 #ifdef CONFIG_ISDN_DRV_ICN
-extern int icn_init(void);
+extern void icn_init(void);
 #endif
 
 #ifdef CONFIG_ISDN_DRV_TELES
-extern int teles_init(void);
+extern void teles_init(void);
+#endif
+
+#ifdef CONFIG_ISDN_DRV_HISAX
+extern void HiSax_init(void);
 #endif
 
 #ifdef CONFIG_ISDN_DRV_PCBIT
-extern int pcbit_init(void);
+extern void pcbit_init(void);
 #endif
 
 void isdn_cards_init(void)
@@ -46,6 +53,9 @@ void isdn_cards_init(void)
 #if CONFIG_ISDN_DRV_TELES
         teles_init();
 #endif
+#ifdef CONFIG_ISDN_DRV_HISAX
+       HiSax_init();
+#endif
 #if CONFIG_ISDN_DRV_PCBIT
         pcbit_init();
 #endif
index 12d243110e9e5055328e1a819fa7abe0262fb7ca..532cdda41f0aba44e30c9acdc80789eea9abf595 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.23 1996/06/25 18:35:38 fritz Exp $
+/* $Id: isdn_common.c,v 1.28 1996/11/13 02:33:19 fritz Exp $
  *
  * Linux ISDN subsystem, common used functions (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_common.c,v $
+ * Revision 1.28  1996/11/13 02:33:19  fritz
+ * Fixed a race condition.
+ *
+ * Revision 1.27  1996/10/27 22:02:41  keil
+ * return codes for ISDN_STAT_ICALL
+ *
+ * Revision 1.26  1996/10/23 11:59:40  fritz
+ * More compatibility changes.
+ *
+ * Revision 1.25  1996/10/22 23:13:54  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
+ * Revision 1.24  1996/10/11 14:02:03  fritz
+ * Bugfix: call to isdn_ppp_timer_timeout() never compiled, because of
+ *         typo in #ifdef.
+ *
  * Revision 1.23  1996/06/25 18:35:38  fritz
  * Fixed bogus memory access in isdn_set_allcfg().
  *
 isdn_dev *dev = (isdn_dev *) 0;
 
 static int  has_exported = 0;
-static char *isdn_revision      = "$Revision: 1.23 $";
+static char *isdn_revision      = "$Revision: 1.28 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -231,7 +247,7 @@ static void isdn_timer_funct(ulong dummy)
                                 isdn_net_autohup();
                         if (tf & ISDN_TIMER_MODEMRING)
                                 isdn_tty_modem_ring();
-#if (defined CONFIG_ISDN_PPP ) && (defined ISDN_CONFIG_MPP)
+#if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP)
                         if (tf & ISDN_TIMER_IPPP)
                                 isdn_ppp_timer_timeout();
 #endif
@@ -407,6 +423,7 @@ static int isdn_status_callback(isdn_ctrl * c)
        ulong flags;
        int i;
        int r;
+       int retval=0;
         modem_info *info;
        isdn_ctrl cmd;
 
@@ -469,12 +486,13 @@ static int isdn_status_callback(isdn_ctrl * c)
                                                 info->msr |= UART_MSR_RI;
                                                 isdn_tty_modem_result(2, info);
                                                 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
-                                                return 0;
+                                                return 1;
                                         } else if (dev->drv[di]->reject_bus) {
                                                 cmd.driver = di;
                                                 cmd.arg = c->arg;
                                                 cmd.command = ISDN_CMD_HANGUP;
                                                 dev->drv[di]->interface->command(&cmd);
+                                                retval=2;
                                         }
                                         break;
                                 case 1:
@@ -484,10 +502,11 @@ static int isdn_status_callback(isdn_ctrl * c)
                                         cmd.arg = c->arg;
                                         cmd.command = ISDN_CMD_ACCEPTD;
                                         dev->drv[di]->interface->command(&cmd);
-                                        return 0;
+                                        return 1;
                                         break;
                                 case 2:        /* For calling back, first reject incoming call ... */
                                 case 3:        /* Interface found, but down, reject call actively  */
+                                       retval=2;
                                         printk(KERN_INFO "isdn: Rejecting Call\n");
                                         cmd.driver = di;
                                         cmd.arg = c->arg;
@@ -499,13 +518,13 @@ static int isdn_status_callback(isdn_ctrl * c)
                                 case 4:
                                         /* ... then start callback. */
                                         isdn_net_dial();
-                                        return 0;
+                                        return 2;
                        }
                         cmd.driver = di;
                         cmd.arg = c->arg;
                         cmd.command = ISDN_CMD_UNLOCK;
                         dev->drv[di]->interface->command(&cmd);
-                        return 0;
+                        return retval;
                         break;
                 case ISDN_STAT_CINF:
                        if (i<0)
@@ -766,13 +785,13 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
                         while ((count_pull < skb->len) && (left-- > 0)) {
                                 if (dev->drv[di]->DLEflag & DLEmask) {
                                         if (user)
-                                                put_fs_byte(DLE,cp++);
+                                                put_user(DLE,cp++);
                                         else
                                                 *cp++ = DLE;
                                         dev->drv[di]->DLEflag &= ~DLEmask;
                                 } else {
                                         if (user)
-                                                put_fs_byte(*p,cp++);
+                                                put_user(*p,cp++);
                                         else
                                                 *cp++ = *p;
                                         if (*p == DLE) {
@@ -795,7 +814,7 @@ int isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int
                         }
                         count_put = count_pull;
                         if (user)
-                                memcpy_tofs(cp, skb->data, count_put);
+                                copy_to_user(cp, skb->data, count_put);
                         else
                                 memcpy(cp, skb->data, count_put);
                         cp += count_put;
@@ -905,7 +924,7 @@ void isdn_info_update(void)
        wake_up_interruptible(&(dev->info_waitq));
 }
 
-static int isdn_read(struct inode *inode, struct file *file, char *buf, int count)
+static RWTYPE isdn_read(struct inode *inode, struct file *file, char *buf, RWARG count)
 {
        uint minor = MINOR(inode->i_rdev);
        int len = 0;
@@ -923,7 +942,7 @@ static int isdn_read(struct inode *inode, struct file *file, char *buf, int coun
                p = isdn_statstr();
                file->private_data = 0;
                if ((len = strlen(p)) <= count) {
-                       memcpy_tofs(buf, p, len);
+                       copy_to_user(buf, p, len);
                        file->f_pos += len;
                        return len;
                }
@@ -977,12 +996,12 @@ static int isdn_read(struct inode *inode, struct file *file, char *buf, int coun
        return -ENODEV;
 }
 
-static int isdn_lseek(struct inode *inode, struct file *file, off_t offset, int orig)
+static LSTYPE isdn_lseek(struct inode *inode, struct file *file, LSARG offset, int orig)
 {
        return -ESPIPE;
 }
 
-static int isdn_write(struct inode *inode, struct file *file, const char *buf, int count)
+static RWTYPE isdn_write(struct inode *inode, struct file *file, const char *buf, RWARG count)
 {
        uint minor = MINOR(inode->i_rdev);
        int drvidx;
@@ -1076,7 +1095,7 @@ static int isdn_set_allcfg(char *src)
                restore_flags(flags);
                return ret;
        }
-       memcpy_fromfs((char *) &i, src, sizeof(int));
+       copy_from_user((char *) &i, src, sizeof(int));
         src += sizeof(int);
        while (i) {
                char *c;
@@ -1086,7 +1105,7 @@ static int isdn_set_allcfg(char *src)
                        restore_flags(flags);
                        return ret;
                }
-               memcpy_fromfs((char *) &cfg, src, sizeof(cfg));
+               copy_from_user((char *) &cfg, src, sizeof(cfg));
                src += sizeof(cfg);
                if (!isdn_net_new(cfg.name, NULL)) {
                        restore_flags(flags);
@@ -1100,7 +1119,7 @@ static int isdn_set_allcfg(char *src)
                        restore_flags(flags);
                        return ret;
                }
-               memcpy_fromfs(buf, src, sizeof(buf));
+               copy_from_user(buf, src, sizeof(buf));
                src += sizeof(buf);
                c = buf;
                while (*c) {
@@ -1122,7 +1141,7 @@ static int isdn_set_allcfg(char *src)
                        restore_flags(flags);
                        return ret;
                }
-               memcpy_fromfs(buf, src, sizeof(buf));
+               copy_from_user(buf, src, sizeof(buf));
                src += sizeof(buf);
                c = buf;
                while (*c) {
@@ -1179,9 +1198,9 @@ static int isdn_get_allcfg(char *dest)
                cfg.callback = (p->local.flags & ISDN_NET_CALLBACK) ? 1 : 0;
                cfg.chargehup = (p->local.hupflags & 4) ? 1 : 0;
                cfg.ihup = (p->local.hupflags & 8) ? 1 : 0;
-               memcpy_tofs(dest, p->local.name, 10);
+               copy_to_user(dest, p->local.name, 10);
                dest += 10;
-               memcpy_tofs(dest, (char *) &cfg, sizeof(cfg));
+               copy_to_user(dest, (char *) &cfg, sizeof(cfg));
                dest += sizeof(cfg);
                strcpy(phone.name, p->local.name);
                phone.outgoing = 0;
@@ -1231,8 +1250,8 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                                sizeof(ulong)*ISDN_MAX_CHANNELS*2)))
                                                 return ret;
                                         for (i = 0;i<ISDN_MAX_CHANNELS;i++) {
-                                                put_fs_long(dev->ibytes[i],p++);
-                                                put_fs_long(dev->obytes[i],p++);
+                                                put_user(dev->ibytes[i],p++);
+                                                put_user(dev->obytes[i],p++);
                                         }
                                         return 0;
                                 } else
@@ -1261,14 +1280,14 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         s = name;
                                 } else
                                         s = NULL;
                                 if ((s = isdn_net_new(s, NULL))) {
                                         if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
                                                 return ret;
-                                        memcpy_tofs((char *) arg, s, strlen(s) + 1);
+                                        copy_to_user((char *) arg, s, strlen(s) + 1);
                                         return 0;
                                 } else
                                         return -ENODEV;
@@ -1277,13 +1296,13 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(bname))))
                                                 return ret;
-                                        memcpy_fromfs(bname, (char *) arg, sizeof(bname));
+                                        copy_from_user(bname, (char *) arg, sizeof(bname));
                                 } else
                                         return -EINVAL;
                                 if ((s = isdn_net_newslave(bname))) {
                                         if ((ret = verify_area(VERIFY_WRITE, (void *) arg, strlen(s) + 1)))
                                                 return ret;
-                                        memcpy_tofs((char *) arg, s, strlen(s) + 1);
+                                        copy_to_user((char *) arg, s, strlen(s) + 1);
                                         return 0;
                                 } else
                                         return -ENODEV;
@@ -1292,7 +1311,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         return isdn_net_rm(name);
                                 } else
                                         return -EINVAL;
@@ -1301,7 +1320,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &cfg, (char *) arg, sizeof(cfg));
+                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
                                         return isdn_net_setcfg(&cfg);
                                 } else
                                         return -EINVAL;
@@ -1310,11 +1329,11 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(cfg))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &cfg, (char *) arg, sizeof(cfg));
+                                        copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg));
                                         if (!(ret = isdn_net_getcfg(&cfg))) {
                                                 if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(cfg))))
                                                         return ret;
-                                                memcpy_tofs((char *) arg, (char *) &cfg, sizeof(cfg));
+                                                copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg));
                                         }
                                         return ret;
                                 } else
@@ -1324,7 +1343,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
+                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
                                         return isdn_net_addphone(&phone);
                                 } else
                                         return -EINVAL;
@@ -1333,7 +1352,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
+                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
                                         return isdn_net_getphones(&phone, (char *) arg);
                                 } else
                                         return -EINVAL;
@@ -1342,7 +1361,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(phone))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &phone, (char *) arg, sizeof(phone));
+                                        copy_from_user((char *) &phone, (char *) arg, sizeof(phone));
                                         return isdn_net_delphone(&phone);
                                 } else
                                         return -EINVAL;
@@ -1351,7 +1370,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         return isdn_net_force_dial(name);
                                 } else
                                         return -EINVAL;
@@ -1364,7 +1383,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                 return ret;
                                 } else
                                         return -EINVAL;
-                                memcpy_fromfs(name,(char*)arg,sizeof(name));
+                                copy_from_user(name,(char*)arg,sizeof(name));
                                 return isdn_ppp_dial_slave(name);
                         case IIOCNETDLN:
                                 if(arg) {
@@ -1374,7 +1393,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                 return ret;
                                 } else
                                         return -EINVAL;
-                                memcpy_fromfs(name,(char*)arg,sizeof(name));
+                                copy_from_user(name,(char*)arg,sizeof(name));
                                 return isdn_ppp_hangup_slave(name);
 #endif
                         case IIOCNETHUP:
@@ -1382,7 +1401,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg, sizeof(name))))
                                                 return ret;
-                                        memcpy_fromfs(name, (char *) arg, sizeof(name));
+                                        copy_from_user(name, (char *) arg, sizeof(name));
                                         return isdn_net_force_hangup(name);
                                 } else
                                         return -EINVAL;
@@ -1408,7 +1427,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg,
                                                                sizeof(isdn_ioctl_struct))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &iocts, (char *) arg,
+                                        copy_from_user((char *) &iocts, (char *) arg,
                                                       sizeof(isdn_ioctl_struct));
                                         if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
@@ -1457,10 +1476,10 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                 return ret;
                                         
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                memcpy_tofs(p, dev->mdm.info[i].emu.profile,
+                                                copy_to_user(p, dev->mdm.info[i].emu.profile,
                                                             ISDN_MODEM_ANZREG);
                                                 p += ISDN_MODEM_ANZREG;
-                                                memcpy_tofs(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN);
+                                                copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN);
                                                 p += ISDN_MSNLEN;
                                         }
                                         return (ISDN_MODEM_ANZREG + ISDN_MSNLEN) * ISDN_MAX_CHANNELS;
@@ -1479,10 +1498,10 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                 return ret;
                                         
                                         for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-                                                memcpy_fromfs(dev->mdm.info[i].emu.profile, p,
+                                                copy_from_user(dev->mdm.info[i].emu.profile, p,
                                                               ISDN_MODEM_ANZREG);
                                                 p += ISDN_MODEM_ANZREG;
-                                                memcpy_fromfs(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN);
+                                                copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN);
                                                 p += ISDN_MSNLEN;
                                         }
                                         return 0;
@@ -1500,7 +1519,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg,
                                                                sizeof(isdn_ioctl_struct))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
                                         if (strlen(iocts.drvid)) {
                                                 drvidx = -1;
                                                 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
@@ -1515,7 +1534,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         if (cmd == IIOCSETMAP) {
                                                 if ((ret = verify_area(VERIFY_READ, (void *) iocts.arg, 255)))
                                                         return ret;
-                                                memcpy_fromfs(nstring, (char *) iocts.arg, 255);
+                                                copy_from_user(nstring, (char *) iocts.arg, 255);
                                                 memset(dev->drv[drvidx]->msn2eaz, 0,
                                                        sizeof(dev->drv[drvidx]->msn2eaz));
                                                 p = strtok(nstring, ",");
@@ -1534,7 +1553,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                                 if ((ret = verify_area(VERIFY_WRITE, (void *) iocts.arg,
                                                                        strlen(nstring) + 1)))
                                                         return ret;
-                                                memcpy_tofs((char *) iocts.arg, nstring, strlen(nstring) + 1);
+                                                copy_to_user((char *) iocts.arg, nstring, strlen(nstring) + 1);
                                         }
                                         return 0;
                                 } else
@@ -1543,7 +1562,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                 if (arg) {
                                         if ((ret = verify_area(VERIFY_WRITE, (void *) arg, sizeof(ulong))))
                                                 return ret;
-                                        memcpy_tofs((char *) arg, (char *) &dev, sizeof(ulong));
+                                        copy_to_user((char *) arg, (char *) &dev, sizeof(ulong));
                                         return 0;
                                 } else
                                         return -EINVAL;
@@ -1559,7 +1578,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         if ((ret = verify_area(VERIFY_READ, (void *) arg,
                                                                sizeof(isdn_ioctl_struct))))
                                                 return ret;
-                                        memcpy_fromfs((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
+                                        copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct));
                                         if (strlen(iocts.drvid)) {
                                                 if ((p = strchr(iocts.drvid, ',')))
                                                         *p = 0;
@@ -1582,7 +1601,7 @@ static int isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong ar
                                         memcpy(c.num, (char *) &iocts.arg, sizeof(ulong));
                                         ret = dev->drv[drvidx]->interface->command(&c);
                                         memcpy((char *) &iocts.arg, c.num, sizeof(ulong));
-                                        memcpy_tofs((char *) arg, &iocts, sizeof(isdn_ioctl_struct));
+                                        copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct));
                                         return ret;
                                 } else
                                         return -EINVAL;
@@ -1816,8 +1835,8 @@ void isdn_free_channel(int di, int ch, int usage)
                         cmd.driver = di;
                         cmd.arg = ch;
                         cmd.command = ISDN_CMD_UNLOCK;
-                        (void) dev->drv[di]->interface->command(&cmd);
                         restore_flags(flags);
+                        (void) dev->drv[di]->interface->command(&cmd);
                        return;
                }
        restore_flags(flags);
@@ -1891,7 +1910,7 @@ int isdn_writebuf_stub(int drvidx, int chan, const u_char *buf, int len,
                 skb->free = 1;
 
                 if (user)
-                        memcpy_fromfs(skb_put(skb, len), buf, len);
+                        copy_from_user(skb_put(skb, len), buf, len);
                 else
                         memcpy(skb_put(skb, len), buf, len);
 
index 0774f53196c1827291be5c455873dbca8d44e9ba..e1da45bf34d4ba4c2711163edfe4717a30244c97 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.20 1996/08/29 20:06:03 fritz Exp $
+/* $Id: isdn_net.c,v 1.29 1996/11/13 02:31:38 fritz Exp $
  *
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.29  1996/11/13 02:31:38  fritz
+ * Minor cleanup.
+ *
+ * Revision 1.28  1996/10/27 20:49:06  keil
+ * bugfix to compile without MPP
+ *
+ * Revision 1.27  1996/10/25 18:46:01  fritz
+ * Another bugfix in isdn_net_autohup()
+ *
+ * Revision 1.26  1996/10/23 23:05:36  fritz
+ * Bugfix: Divide by zero in isdn_net_autohup()
+ *
+ * Revision 1.25  1996/10/22 23:13:58  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
+ * Revision 1.24  1996/10/11 13:57:40  fritz
+ * Bugfix: Error in BogoCPS calculation.
+ *
+ * Revision 1.23  1996/09/23 01:58:08  fritz
+ * Fix: With syncPPP encapsulation, discard LCP packets
+ *      when calculating hangup timeout.
+ *
+ * Revision 1.22  1996/09/23 00:03:37  fritz
+ * Fix: did not compile without CONFIG_ISDN_PPP
+ *
+ * Revision 1.21  1996/09/07 12:44:50  hipp
+ * (hopefully) fixed callback problem with syncPPP
+ * syncPPP network devices now show PPP link encap
+ *
  * Revision 1.20  1996/08/29 20:06:03  fritz
  * Bugfix: Transmission timeout had been much to low.
  *
@@ -130,7 +159,7 @@ static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
  
 extern void dev_purge_queues(struct device *dev);      /* move this to net/core/dev.c */
 
-char *isdn_net_revision = "$Revision: 1.20 $";
+char *isdn_net_revision = "$Revision: 1.29 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -237,19 +266,21 @@ isdn_net_unbind_channel(isdn_net_local * lp)
  * Since this function is called every second, simply reset the
  * byte-counter of the interface after copying it to the cps-variable.
  */
+unsigned long last_jiffies = -HZ;
+
 void
 isdn_net_autohup()
 {
        isdn_net_dev *p = dev->netdev;
         int anymore;
-       ulong flags;
 
-       save_flags(flags);
-       cli();
         anymore = 0;
        while (p) {
                isdn_net_local *l = (isdn_net_local *) & (p->local);
-               l->cps = l->transcount;
+               if ((jiffies - last_jiffies) == 0)
+                       l->cps = 0;
+               else
+                       l->cps = l->transcount / (jiffies - last_jiffies);
                l->transcount = 0;
                if (dev->net_verbose > 3)
                        printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps);
@@ -270,8 +301,8 @@ isdn_net_autohup()
                }
                p = (isdn_net_dev *) p->next;
        }
+       last_jiffies = jiffies;
         isdn_timer_ctrl(ISDN_TIMER_NETHANGUP,anymore);
-       restore_flags(flags);
 }
 
 /*
@@ -902,8 +933,8 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
                                                 restore_flags(flags);
                                                return 0;       /* STN (skb to nirvana) ;) */
                                        }
-                                       isdn_net_dial();        /* Initiate dialing */
                                        restore_flags(flags);
+                                       isdn_net_dial();        /* Initiate dialing */
                                        return 1;       /* let upper layer requeue skb packet */
                                }
 #endif
@@ -917,9 +948,9 @@ isdn_net_start_xmit(struct sk_buff *skb, struct device *ndev)
                                 }
                                 lp->first_skb = skb;
                                /* Initiate dialing */
-                               isdn_net_dial();
                                 ndev->tbusy = 0;
                                restore_flags(flags);
+                               isdn_net_dial();
                                 return 0;
                        } else {
                                 /*
@@ -1053,11 +1084,20 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
        isdn_net_local *lp = (isdn_net_local *) ndev->priv;
 #ifdef CONFIG_ISDN_PPP
         isdn_net_local *olp = lp;  /* original 'lp' */
+        int proto = PPP_PROTOCOL(skb->data);
 #endif
 
        lp->transcount += skb->len;
        lp->stats.rx_packets++;
-       lp->huptimer = 0;
+#ifdef CONFIG_ISDN_PPP
+        /*
+         * If encapsulation is syncppp, don't reset
+         * huptimer on LCP packets.
+         */
+        if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP ||
+            (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP))
+#endif
+               lp->huptimer = 0;
 
        if (lp->master) {
                /* Bundling: If device is a slave-device, deliver to master, also
@@ -1066,7 +1106,15 @@ isdn_net_receive(struct device *ndev, struct sk_buff *skb)
                ndev = lp->master;
                lp = (isdn_net_local *) ndev->priv;
                lp->stats.rx_packets++;
-               lp->huptimer = 0;
+#ifdef CONFIG_ISDN_PPP
+                /*
+                 * If encapsulation is syncppp, don't reset
+                 * huptimer on LCP packets.
+                 */
+                if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP ||
+                    (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && proto != PPP_LCP))
+#endif
+                        lp->huptimer = 0;
        }
 
        skb->dev = ndev;
@@ -1716,9 +1764,14 @@ isdn_net_find_icall(int di, int ch, int idx, char *num)
                                               eaz);
                                        /* if this interface is dialing, it does it probably on a different
                                           device, so free this device */
-                                       if ((p->local.dialstate == 4) || (p->local.dialstate == 12))
+                                       if ((p->local.dialstate == 4) || (p->local.dialstate == 12)) {
+#ifdef CONFIG_ISDN_PPP
+                                                if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
+                                                        isdn_ppp_free(lp);
+#endif
                                                isdn_free_channel(p->local.isdn_device, p->local.isdn_channel,
                                                         ISDN_USAGE_NET);
+                                        }
                                        dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
                                        dev->usage[idx] |= ISDN_USAGE_NET;
                                        strcpy(dev->num[idx], nr);
@@ -1808,8 +1861,8 @@ int isdn_net_force_dial_lp(isdn_net_local * lp)
                                }
 #endif
                        /* Initiate dialing */
-                       isdn_net_dial();
                        restore_flags(flags);
+                       isdn_net_dial();
                        return 0;
                } else
                        return -EINVAL;
@@ -1899,6 +1952,8 @@ isdn_net_new(char *name, struct device *master)
        netdev->local.exclusive = -1;
        netdev->local.ppp_slot = -1;
        netdev->local.pppbind = -1;
+        netdev->local.sav_skb = NULL;
+        netdev->local.first_skb = NULL;
        netdev->local.l2_proto = ISDN_PROTO_L2_X75I;
        netdev->local.l3_proto = ISDN_PROTO_L3_TRANS;
        netdev->local.slavedelay = 10 * HZ;
@@ -1972,13 +2027,16 @@ int isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
                                        p->local.name);
                                 return -EBUSY;
                         }
-#ifndef CONFIG_ISDN_PPP
                 if (cfg->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
-                        printk(KERN_WARNING "%s: SyncPPP not configured\n",
+#ifndef CONFIG_ISDN_PPP
+                        printk(KERN_WARNING "%s: SyncPPP support not configured\n",
                                p->local.name);
                         return -EINVAL;
-                }
+#else
+                        p->dev.type = ARPHRD_PPP; /* change ARP type */
+                        p->dev.addr_len = 0;
 #endif
+                }
                if (strlen(cfg->drvid)) {
                        /* A bind has been requested ... */
                        char *c,*e;
@@ -2188,19 +2246,19 @@ int isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
        inout &= 1;
         for (n = p->local.phone[inout]; n; n = n->next) {
                if (more) {
-                       put_fs_byte(' ', phones++);
+                       put_user(' ', phones++);
                        count++;
                }
                if ((ret = verify_area(VERIFY_WRITE, (void *) phones, strlen(n->num) + 1))) {
                        restore_flags(flags);
                        return ret;
                }
-               memcpy_tofs(phones, n->num, strlen(n->num) + 1);
+               copy_to_user(phones, n->num, strlen(n->num) + 1);
                phones += strlen(n->num);
                count += strlen(n->num);
                more = 1;
        }
-        put_fs_byte(0,phones);
+        put_user(0,phones);
         count++;
        restore_flags(flags);
        return count;
@@ -2268,16 +2326,11 @@ static int isdn_net_rmallphone(isdn_net_dev * p)
 int isdn_net_force_hangup(char *name)
 {
        isdn_net_dev *p = isdn_net_findif(name);
-       int flags;
        struct device *q;
 
        if (p) {
-               save_flags(flags);
-               cli();
-               if (p->local.isdn_device < 0) {
-                       restore_flags(flags);
+               if (p->local.isdn_device < 0)
                        return 1;
-               }
                isdn_net_hangup(&p->dev);
                q = p->local.slave;
                /* If this interface has slaves, do a hangup for them also. */
@@ -2285,7 +2338,6 @@ int isdn_net_force_hangup(char *name)
                        isdn_net_hangup(q);
                        q = (((isdn_net_local *) q->priv)->slave);
                }
-               restore_flags(flags);
                return 0;
        }
        return -ENODEV;
@@ -2347,7 +2399,7 @@ static int isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
                isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
        restore_flags(flags);
 
-#ifdef CONFIG_ISDN_PPP
+#ifdef CONFIG_ISDN_MPP
        isdn_ppp_free_mpqueue(p);       /* still necessary? */
 #endif
        kfree(p);
@@ -2417,14 +2469,3 @@ void dev_purge_queues(struct device *dev)
         }
        
 }
-
-
-
-
-
-
-
-
-
-
-
index 1c31b272e3fd213a6691769ad3708c97ac609d0f..f7ec2e7d4fc3638c9deab582cfab9bc8dd4a0db9 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.14 1996/08/12 16:26:47 hipp Exp $
+/* $Id: isdn_ppp.c,v 1.20 1996/10/30 12:21:58 fritz Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.20  1996/10/30 12:21:58  fritz
+ * Cosmetic fix: Compiler warning when compiling without MPP.
+ *
+ * Revision 1.19  1996/10/25 19:03:21  hipp
+ * changed/added some defines to (re)allow compilation without MP/VJ
+ *
+ * Revision 1.18  1996/10/22 23:14:00  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
+ * Revision 1.17  1996/10/22 09:39:49  hipp
+ * a few MP changes and bugfixes
+ *
+ * Revision 1.16  1996/09/23 01:58:10  fritz
+ * Fix: With syncPPP encapsulation, discard LCP packets
+ *      when calculating hangup timeout.
+ *
+ * Revision 1.15  1996/09/07 12:50:12  hipp
+ * bugfixes (unknown device after failed dial attempt, minor bugs)
+ *
  * Revision 1.14  1996/08/12 16:26:47  hipp
  * code cleanup
  * changed connection management from minors to slots
@@ -73,6 +92,8 @@
 
 /* TODO: right tbusy handling when using MP */
 
+#undef ISDN_SYNCPPP_READDRESS
+
 #include <linux/config.h>
 #define __NO_VERSION__
 #include <linux/module.h>
 #ifndef PPP_IPX
 #define PPP_IPX 0x002b 
 #endif
+
+/* set this if you use dynamic addressing */
  
 /* Prototypes */
 static int isdn_ppp_fill_rq(unsigned char *buf, int len,int proto, int slot);
@@ -95,23 +118,45 @@ static int isdn_ppp_if_get_unit(char *namebuf);
 #ifdef CONFIG_ISDN_MPP
 static int isdn_ppp_bundle(struct ippp_struct *, int unit);
 static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask);
-static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min);
+static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min);
+static void isdn_ppp_cleanup_sqqueue(isdn_net_dev * dev,isdn_net_local *, long min);
 static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb,
-               int BEbyte, int *sqno, int min_sqno);
+               int BEbyte, long *sqno, int min_sqno);
 #endif
 
-char *isdn_ppp_revision              = "$Revision: 1.14 $";
+char *isdn_ppp_revision              = "$Revision: 1.20 $";
+
 struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 
 extern int isdn_net_force_dial_lp(isdn_net_local *);
 
+/*
+ * frame log (debug)
+ */
+static void isdn_ppp_frame_log(char *info,char *data,int len,int maxlen)
+{
+       int cnt,j,i;
+       char buf[80];
+
+       if(len < maxlen)
+               maxlen = len;
+       
+       for(i=0,cnt=0;cnt<maxlen;i++) {
+               for(j=0;j<16 && cnt<maxlen;j++,cnt++)
+                       sprintf(buf+j*3,"%02x ",(unsigned char) data[cnt]);
+               printk(KERN_DEBUG "%s[%d]: %s\n",info,i,buf);
+       }
+}
+
 /*
  * unbind isdn_net_local <=> ippp-device 
  * note: it can happen, that we hangup/free the master before the slaves
  */
 int isdn_ppp_free(isdn_net_local *lp)
 {
+#ifdef CONFIG_ISDN_MPP
        isdn_net_local *master_lp=lp;
+#endif
        unsigned long flags;
        struct ippp_struct *is;
 
@@ -131,7 +176,7 @@ int isdn_ppp_free(isdn_net_local *lp)
        if(master_lp->netdev->queue == lp) {
                master_lp->netdev->queue = lp->next;
                if(lp->next == lp) {    /* last link in queue? */
-                               master_lp->netdev->ib.bundled = 0;
+                       master_lp->netdev->ib.bundled = 0;
                        isdn_ppp_free_mpqueue(master_lp->netdev);
                        isdn_ppp_free_sqqueue(master_lp->netdev);
                }
@@ -139,12 +184,20 @@ int isdn_ppp_free(isdn_net_local *lp)
        lp->next = lp->last = lp;       /* (re)set own pointers */
 #endif
 
-       isdn_ppp_closewait(lp->ppp_slot);       /* force wakeup on ippp device */
+       if( (is->state & IPPP_CONNECT) )
+               isdn_ppp_closewait(lp->ppp_slot);       /* force wakeup on ippp device */
+       else if(is->state & IPPP_ASSIGNED)
+               is->state = IPPP_OPEN;  /* fallback to 'OPEN but not ASSIGEND' staet */
+               
 
        if(is->debug & 0x1)
                printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp,(long) is->lp);
 
        is->lp = NULL;  /* link is down .. set lp to NULL */
+#ifdef ISDN_SYNCPPP_READDRESS
+       is->old_pa_addr = 0x0;
+       is->old_pa_dstaddr = 0x0;
+#endif
        lp->ppp_slot = -1;                      /* is this OK ?? */
        restore_flags(flags);
 
@@ -209,7 +262,7 @@ int isdn_ppp_bind(isdn_net_local * lp)
        is = ippp_table[i];
        is->lp = lp;
        is->unit = unit;
-       is->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+       is->state = IPPP_OPEN | IPPP_ASSIGNED;  /* assigned to a netdevice but not connected */
 
        restore_flags(flags);
 
@@ -223,6 +276,11 @@ int isdn_ppp_bind(isdn_net_local * lp)
 
 void isdn_ppp_wakeup_daemon(isdn_net_local *lp)
 {
+       if(lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS)
+               return;
+
+       ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+
        if (ippp_table[lp->ppp_slot]->wq)
                wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
 }
@@ -270,6 +328,9 @@ int isdn_ppp_open(int min, struct file *file)
        int slot;
        struct ippp_struct *is;
 
+       if(min < 0 || min > ISDN_MAX_CHANNELS)
+               return -ENODEV;
+
        slot = isdn_ppp_get_slot();
        if(slot < 0) {
                return -EBUSY;
@@ -322,11 +383,15 @@ void isdn_ppp_release(int min, struct file *file)
                printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
 
        if (is->lp) {   /* a lp address says: this link is still up */
-               isdn_net_dev *p = dev->netdev;
-               p = is->lp->netdev;
-               is->lp->ppp_slot = -1;
-               isdn_net_hangup(&p->dev); /* lp->ppp_slot==-1 => no calling of isdn_ppp_closewait() */
-               is->lp = NULL;
+               isdn_net_dev *p = is->lp->netdev;
+               
+               is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
+               /* 
+                * isdn_net_hangup() calls isdn_ppp_free()
+                * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
+                * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
+                */
+               isdn_net_hangup(&p->dev);
        }
        for (i = 0; i < NUM_RCV_BUFFS; i++) {
                if (is->rq[i].buf) {
@@ -348,24 +413,33 @@ void isdn_ppp_release(int min, struct file *file)
 /*
  * get_arg .. ioctl helper
  */
-static int get_arg(void *b, unsigned long *val)
+static int get_arg(void *b,void *val,int len)
 {
        int r;
-       if ((r = verify_area(VERIFY_READ, (void *) b, sizeof(unsigned long))))
+       if(len <= 0)
+               len = sizeof(unsigned long); 
+       if ((r = verify_area(VERIFY_READ, (void *) b, len )))
                 return r;
-       memcpy_fromfs((void *) val, b, sizeof(unsigned long));
+       copy_from_user((void *) val, b, len );
        return 0;
 }
 
 /*
  * set arg .. ioctl helper
  */
-static int set_arg(void *b, unsigned long val)
+static int set_arg(void *b, unsigned long val,void *str)
 {
        int r;
-       if ((r = verify_area(VERIFY_WRITE, b, sizeof(unsigned long))))
-                return r;
-       memcpy_tofs(b, (void *) &val, sizeof(unsigned long));
+       if(!str) {
+               if ((r = verify_area(VERIFY_WRITE, b, 4 )))
+                        return r;
+               copy_to_user(b, (void *) &val, 4 );
+       }
+       else {
+               if ((r = verify_area(VERIFY_WRITE, b,val)))
+                       return r;
+               copy_to_user(b,str,val);
+       }
        return 0;
 }
 
@@ -389,7 +463,9 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
        switch (cmd) {
        case PPPIOCBUNDLE:
 #ifdef CONFIG_ISDN_MPP
-               if ((r = get_arg((void *) arg, &val)))
+               if( !(is->state & IPPP_CONNECT) )
+                       return -EINVAL;
+               if ((r = get_arg((void *) arg, &val,0)))
                        return r;
                printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
                         (int) min, (int) is->unit, (int) val);
@@ -399,41 +475,50 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
 #endif
                break;
        case PPPIOCGUNIT:       /* get ppp/isdn unit number */
-               if ((r = set_arg((void *) arg, is->unit)))
+               if ((r = set_arg((void *) arg, is->unit,NULL)))
                        return r;
                break;
        case PPPIOCGMPFLAGS:    /* get configuration flags */
-               if ((r = set_arg((void *) arg, is->mpppcfg)))
+               if ((r = set_arg((void *) arg, is->mpppcfg,NULL)))
                        return r;
                break;
        case PPPIOCSMPFLAGS:    /* set configuration flags */
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_arg((void *) arg, &val,0)))
                        return r;
                is->mpppcfg = val;
                break;
        case PPPIOCGFLAGS:      /* get configuration flags */
-               if ((r = set_arg((void *) arg, is->pppcfg)))
+               if ((r = set_arg((void *) arg, is->pppcfg,NULL)))
                        return r;
                break;
        case PPPIOCSFLAGS:      /* set configuration flags */
-               if ((r = get_arg((void *) arg, &val))) {
+               if ((r = get_arg((void *) arg, &val,0))) {
                        return r;
                }
-               if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP)) {
+               if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT) ) {
                        isdn_net_local *lp = is->lp;
-                       lp->netdev->dev.tbusy = 0;
-                       mark_bh(NET_BH); /* OK .. we are ready to send buffers */
+                       if(lp) {
+                               lp->netdev->dev.tbusy = 0;
+                               mark_bh(NET_BH); /* OK .. we are ready to send buffers */
+                       }
                }
                is->pppcfg = val;
                break;
 #if 0
        case PPPIOCGSTAT:       /* read PPP statistic information */
                break;
-       case PPPIOCGTIME:       /* read time delta information */
-               break;
 #endif
+       case PPPIOCGIDLE:       /* get idle time information */
+               if(is->lp)
+               {
+                       struct ppp_idle pidle;
+                       pidle.xmit_idle = pidle.recv_idle = is->lp->huptimer;
+                       if((r = set_arg((void *) arg,sizeof(struct ppp_idle),&pidle)))
+                               return r;       
+               }
+               break;
        case PPPIOCSMRU:        /* set receive unit size for PPP */
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_arg((void *) arg, &val,0)))
                        return r;
                is->mru = val;
                break;
@@ -442,7 +527,7 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
        case PPPIOCSMPMTU:
                break;
        case PPPIOCSMAXCID:     /* set the maximum compression slot id */
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_arg((void *) arg, &val,0)))
                        return r;
                val++;
                if(is->maxcid != val) {
@@ -465,14 +550,25 @@ int isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long a
                }
                break;
        case PPPIOCGDEBUG:
-               if ((r = set_arg((void *) arg, is->debug)))
+               if ((r = set_arg((void *) arg, is->debug,0)))
                        return r;
                break;
        case PPPIOCSDEBUG:
-               if ((r = get_arg((void *) arg, &val)))
+               if ((r = get_arg((void *) arg, &val,0)))
                        return r;
                is->debug = val;
                break;
+       case PPPIOCSCOMPRESS:
+#if 0
+               {
+                       struct ppp_option_data pod;
+                       r = get_arg((void *) arg,&pod,sizeof(struct ppp_option_data));
+                       if(r)
+                               return r;
+                       ippp_set_compression(is,&pod);
+               }
+#endif
+               break;
        default:
                break;
        }
@@ -607,7 +703,7 @@ int isdn_ppp_read(int min, struct file *file, char *buf, int count)
        }
        if (b->len < count)
                count = b->len;
-       memcpy_tofs(buf, b->buf, count);
+       copy_to_user(buf, b->buf, count);
        kfree(b->buf);
        b->buf = NULL;
        is->first = b;
@@ -624,6 +720,8 @@ int isdn_ppp_write(int min, struct file *file,  const char *buf, int count)
 {
        isdn_net_local *lp;
        struct ippp_struct *is;
+       int proto;
+       unsigned char protobuf[4];
 
        is = file->private_data;
 
@@ -637,12 +735,21 @@ int isdn_ppp_write(int min, struct file *file,  const char *buf, int count)
        if (!lp)
                printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
        else {
-               lp->huptimer = 0;
+                /*
+                 * Don't reset huptimer for
+                 * LCP packets. (Echo requests).
+                 */
+                copy_from_user(protobuf, buf, 4);
+                proto = PPP_PROTOCOL(protobuf);
+                if (proto != PPP_LCP)
+                       lp->huptimer = 0;
+               
                if (lp->isdn_device < 0 || lp->isdn_channel < 0)
                        return 0;
 
                if (dev->drv[lp->isdn_device]->running && lp->dialstate == 0 &&
                    (lp->flags & ISDN_NET_CONNECTED)) {
+                       int cnt;
                        struct sk_buff *skb;
                        skb = dev_alloc_skb(count);
                        if(!skb) {
@@ -650,17 +757,22 @@ int isdn_ppp_write(int min, struct file *file,  const char *buf, int count)
                                return count;
                        }
                        skb->free = 1;
-                       memcpy_fromfs(skb_put(skb, count), buf, count);
-                       if(isdn_writebuf_skb_stub(lp->isdn_device,lp->isdn_channel,skb) != count) {
+                       copy_from_user(skb_put(skb, count), buf, count);
+                       if(is->debug & 0x40) {
+                               printk(KERN_DEBUG "ppp xmit: len %ld\n",skb->len);
+                               isdn_ppp_frame_log("xmit",skb->data,skb->len,32);
+                       }
+                       if( (cnt=isdn_writebuf_skb_stub(lp->isdn_device,lp->isdn_channel,skb)) != count) {
                                if(lp->sav_skb) {
                                        dev_kfree_skb(lp->sav_skb,FREE_WRITE);
-                                       printk(KERN_INFO "isdn_ppp_write: freeing sav_skb!\n");
+                                       printk(KERN_INFO "isdn_ppp_write: freeing sav_skb (%d,%d)!\n",cnt,count);
                                }
+                               else
+                                       printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n",cnt,count);
                                lp->sav_skb = skb;
                        }
                }
        }
-
        return count;
 }
 
@@ -706,14 +818,15 @@ void isdn_ppp_cleanup(void)
 /*
  * handler for incoming packets on a syncPPP interface
  */
-
 void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
 {
        struct ippp_struct *is;
        is = ippp_table[lp->ppp_slot];
 
-       if(is->debug & 0x4)
-               printk(KERN_DEBUG "recv skb, len: %ld\n",skb->len);
+       if(is->debug & 0x4) {
+               printk(KERN_DEBUG "ippp_receive: len: %ld\n",skb->len);
+               isdn_ppp_frame_log("receive",skb->data,skb->len,32);
+       }
 
        if(net_dev->local.master) {
                printk(KERN_WARNING "isdn_ppp_receice: net_dev != master\n");
@@ -741,7 +854,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
                }
                if (proto == PPP_MP) {
                        isdn_net_local *lpq;
-                       int sqno, min_sqno, tseq;
+                       long sqno, min_sqno, tseq;
                        u_char BEbyte = skb->data[0];
                        if(is->debug & 0x8)
                                printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto ,
@@ -758,7 +871,7 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
                        if ((tseq = is->last_link_seqno) >= sqno) {
                                int range = is->range;
                                if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */
-                                       printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %d, last: %d !!!\n", sqno, tseq);
+                                       printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n", sqno, tseq);
                                else {
                                        sqno += range;
                                        is->last_link_seqno = sqno;
@@ -766,16 +879,19 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
                        } else
                                is->last_link_seqno = sqno;
 
-                       for (min_sqno = 0, lpq = net_dev->queue;;) {
-                               if (ippp_table[lpq->ppp_slot]->last_link_seqno > min_sqno)
-                                       min_sqno = ippp_table[lpq->ppp_slot]->last_link_seqno;
+                       for (min_sqno = LONG_MAX, lpq = net_dev->queue;;) {
+                               long lls = ippp_table[lpq->ppp_slot]->last_link_seqno;
+                               if (lls >= 0 && lls < min_sqno)
+                                       min_sqno = lls;
                                lpq = lpq->next;
                                if (lpq == net_dev->queue)
                                        break;
                        }
                        if (min_sqno >= ippp_table[lpq->ppp_slot]->range) {     /* OK, every link overflowed */
                                int mask = ippp_table[lpq->ppp_slot]->range - 1;        /* range is a power of 2 */
+#if 0
                                isdn_ppp_cleanup_queue(net_dev, min_sqno);
+#endif
                                isdn_ppp_mask_queue(net_dev, mask);
                                net_dev->ib.next_num &= mask;
                                {
@@ -795,11 +911,18 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
                        }
                        if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) {
                                printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot);
-                               if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0)
+                               if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb , BEbyte, &sqno, min_sqno)) < 0) {
+                                       net_dev->ib.modify = 1; /* block timeout-timer */
+                                       isdn_ppp_cleanup_sqqueue(net_dev,lp,min_sqno); 
+                                       net_dev->ib.modify = 0;
                                        return;         /* no packet complete */
+                               }
                        } else
                                sqno_end = sqno;
 
+                       if(is->debug & 0x40)
+                               printk(KERN_DEBUG "min_sqno: %ld sqno_end %d next: %ld\n",min_sqno,sqno_end,net_dev->ib.next_num );
+
                        /*
                         * MP buffer management .. reorders incoming packets ..
                         * lotsa mem-copies and not heavily tested.
@@ -842,27 +965,14 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
                                                ql->next = q;
                                        }
                                }
-                               net_dev->ib.modify = 0;
-                               return;
                        } else {
                                /* 
                                 * packet was 'in order' .. push it higher
                                 */
-                               struct sqqueue *q;
-
                                net_dev->ib.next_num = sqno_end + 1;
                                isdn_ppp_push_higher(net_dev, lp, skb, -1);
-
-                                /*
-                                 * check queue, whether we have still buffered the next packet(s)
-                                 */
-                               while ((q = net_dev->ib.sq) && q->sqno_start == net_dev->ib.next_num) {
-                                       isdn_ppp_push_higher(net_dev, lp, q->skb, -1);
-                                       net_dev->ib.sq = q->next;
-                                       net_dev->ib.next_num = q->sqno_end + 1;
-                                       kfree(q);
-                               }
                        }
+                       isdn_ppp_cleanup_sqqueue(net_dev,lp,min_sqno);
                        net_dev->ib.modify = 0;
 
                } else
@@ -872,7 +982,6 @@ void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buf
                isdn_ppp_push_higher(net_dev, lp, skb , -1);
 }
 
-
 /*
  * push frame to higher layers
  * note: net_dev has to be master net_dev
@@ -892,13 +1001,15 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
                }
        }
 
-       if(is->debug & 0x10)
+       if(is->debug & 0x10) {
                printk(KERN_DEBUG "push, skb %ld %04x\n",skb->len,proto);
+               isdn_ppp_frame_log("rpush",skb->data,skb->len,32);
+       }
 
        switch (proto) {
        case PPP_IPX: /* untested */
                if(is->debug & 0x20)
-                       printk(KERN_DEBUG "isdn_ppp: _IPX\n");
+                       printk(KERN_DEBUG "isdn_ppp: IPX\n");
                skb->dev = dev;
                skb->mac.raw = skb->data;
                skb->protocol = htons(ETH_P_IPX);
@@ -971,7 +1082,7 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
        }
 
        netif_rx(skb);
-       net_dev->local.stats.rx_packets++;
+/* net_dev->local.stats.rx_packets++; */ /* done in isdn_net.c */
        /* Reset hangup-timer */
        lp->huptimer = 0;
 
@@ -986,7 +1097,7 @@ static void isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, stru
  * skb isn't allowed!! 
  */
 
-static void isdn_ppp_skb_destructor(struct sk_buff *skb)
+static void isdn_ppp_skb_destructor(struct sk_buff *skb)       /* debug function */
 {
        char outstr[80],*outpnt=outstr;
        int i;
@@ -1009,22 +1120,55 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
 
        if(mdev)
                mlp = (isdn_net_local *) (mdev->priv); 
-       else
+       else {
+               mdev = dev;
                mlp = (isdn_net_local *) (dev->priv);
+       }
        nd = mlp->netdev;       /* get master lp */
        ipts = ippp_table[mlp->ppp_slot];
 
        if (!(ipts->pppcfg & SC_ENABLE_IP)) {    /* PPP connected ? */
+#ifdef ISDN_SYNCPPP_READDRESS
+               if(!ipts->old_pa_addr)
+                       ipts->old_pa_addr = mdev->pa_addr;
+               if(!ipts->old_pa_dstaddr)
+                       ipts->old_pa_dstaddr = mdev->pa_dstaddr;
+#endif
                if(ipts->debug & 0x1) {
                        printk(KERN_INFO "%s: IP frame delayed.\n",dev->name);
                        skb->destructor = isdn_ppp_skb_destructor;
                }
                return 1;
-        }
+       }
 
        skb->destructor = NULL;
 
+       switch(ntohs(skb->protocol)) {
+               case ETH_P_IP:
+                       proto = PPP_IP;
+#ifdef ISDN_SYNCPPP_READDRESS
+                       if(ipts->old_pa_addr != mdev->pa_addr)
+                       {
+                               struct iphdr *ipfr;
+                               ipfr = (struct iphdr *) skb->data;
+printk(KERN_DEBUG "IF-address changed from %lx to %lx\n",ipts->old_pa_addr,mdev->pa_addr);
+                               if(ipfr->version == 4) {
+                                       if(ipfr->saddr == ipts->old_pa_addr) {
+printk(KERN_DEBUG "readdressing %lx to %lx\n",ipfr->saddr,mdev->pa_addr);
+                                               ipfr->saddr = mdev->pa_addr;
+                                       }
+                               }
+                       }
+                       /* dstaddr change not so improtant */
+#endif
+                       break;
+               case ETH_P_IPX:
+                       proto = PPP_IPX;        /* untested */
+                       break;
+       }
+
        lp = nd->queue;         /* get lp on top of queue */
+
        if(lp->sav_skb) {       /* find a non-busy device */
                isdn_net_local *nlp = lp->next;
                while(lp->sav_skb) {
@@ -1046,7 +1190,7 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
                printk(KERN_DEBUG  "xmit skb, len %ld\n",skb->len);
 
 #ifdef CONFIG_ISDN_PPP_VJ
-       if (ipts->pppcfg & SC_COMP_TCP) {       /* ipts here? probably yes .. but this check again */
+       if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) {    /* ipts here? probably yes .. but this check again */
                struct sk_buff *new_skb;
 
                new_skb = dev_alloc_skb(skb->len);
@@ -1118,6 +1262,12 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
        skb->data[3] = proto & 0xff;
 
         /* tx-stats are now updated via BSENT-callback */
+
+       if(ipts->debug & 0x40) {
+               printk(KERN_DEBUG "skb xmit: len: %ld\n",skb->len);
+               isdn_ppp_frame_log("xmit",skb->data,skb->len,32);
+       }
+
        if(isdn_net_send_skb(dev , lp , skb)) { 
                if(lp->sav_skb) {       /* whole sav_skb processing with disabled IRQs ?? */
                        printk(KERN_ERR "%s: whoops .. there is another stored skb!\n",dev->name);
@@ -1129,6 +1279,8 @@ int isdn_ppp_xmit(struct sk_buff *skb, struct device *dev)
        return 0;
 }
 
+#ifdef CONFIG_ISDN_MPP
+
 void isdn_ppp_free_sqqueue(isdn_net_dev * p) 
 {
        struct sqqueue *q = p->ib.sq;
@@ -1158,8 +1310,6 @@ void isdn_ppp_free_mpqueue(isdn_net_dev * p)
        }
 }
 
-#ifdef CONFIG_ISDN_MPP
-
 static int isdn_ppp_bundle(struct ippp_struct *is, int unit)
 {
        char ifn[IFNAMSIZ + 1];
@@ -1215,8 +1365,7 @@ static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask)
        }
 }
 
-
-static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, int *sqnop, int min_sqno)
+static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int BEbyte, long *sqnop, int min_sqno)
 {
        struct mpqueue *qe, *q1, *q;
        long cnt, flags;
@@ -1228,7 +1377,7 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int
                printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n");
                save_flags(flags);
                cli();
-               isdn_ppp_cleanup_queue(dev, min_sqno);
+               isdn_ppp_cleanup_mpqueue(dev, min_sqno);
                restore_flags(flags);
                return -1;
        }
@@ -1244,7 +1393,7 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int
                dev->mp_last = q1;
                q1->next = NULL;
                q1->last = NULL;
-               isdn_ppp_cleanup_queue(dev, min_sqno);  /* not necessary */
+               isdn_ppp_cleanup_mpqueue(dev, min_sqno);        /* not necessary */
                restore_flags(flags);
                return -1;
        }
@@ -1278,7 +1427,7 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int
        while (!(q->BEbyte & MP_END_FRAG)) {
                cnt++;
                if (!(q->next) || q->next->sqno != cnt) {
-                       isdn_ppp_cleanup_queue(dev, min_sqno);
+                       isdn_ppp_cleanup_mpqueue(dev, min_sqno);
                        restore_flags(flags);
                        return -1;
                }
@@ -1293,7 +1442,7 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int
        while (!(q->BEbyte & MP_BEGIN_FRAG)) {
                cnt--;
                if (!(q->last) || q->last->sqno != cnt) {
-                       isdn_ppp_cleanup_queue(dev, min_sqno);
+                       isdn_ppp_cleanup_mpqueue(dev, min_sqno);
                        restore_flags(flags);
                        return -1;
                }
@@ -1313,7 +1462,7 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int
        sqno_end = qe->sqno;
        *sqnop = q->sqno;
 
-       isdn_ppp_cleanup_queue(dev, min_sqno);
+       isdn_ppp_cleanup_mpqueue(dev, min_sqno);
        restore_flags(flags);
 
        *skb = dev_alloc_skb(pktlen + 40); /* not needed: +40 for VJ compression .. */
@@ -1344,10 +1493,32 @@ static int isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff ** skb, int
 }
 
 /*
- * remove stale packets from list
+ * check sq-queue, whether we have still buffered the next packet(s)
+ * or packets with a sqno less or equal to min_sqno
+ * net_dev: master netdevice , lp: 'real' local connection
  */
+static void isdn_ppp_cleanup_sqqueue(isdn_net_dev *net_dev, isdn_net_local *lp,long min_sqno)
+{
+       struct sqqueue *q;
 
-static void isdn_ppp_cleanup_queue(isdn_net_dev * dev, long min_sqno)
+       while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno) ) {
+               if(q->sqno_start != net_dev->ib.next_num) {
+                       printk(KERN_DEBUG "ippp: MP, stepping over missing frame: %ld\n",net_dev->ib.next_num);
+#ifdef CONFIG_ISDN_PPP_VJ
+                       slhc_toss(ippp_table[net_dev->local.ppp_slot]->slcomp);
+#endif
+               }
+               isdn_ppp_push_higher(net_dev, lp, q->skb, -1);
+               net_dev->ib.sq = q->next;
+               net_dev->ib.next_num = q->sqno_end + 1;
+               kfree(q);
+    }
+}
+
+/*
+ * remove stale packets from list
+ */
+static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno)
 {
 #ifdef CONFIG_ISDN_PPP_VJ
        int toss = 0;
@@ -1404,9 +1575,9 @@ void isdn_ppp_timer_timeout(void)
        while (net_dev) {
                isdn_net_local *lp = &net_dev->local;
                if (net_dev->ib.modify || lp->master)   {       /* interface locked or slave?*/
-                        net_dev = net_dev->next;
+                       net_dev = net_dev->next;
                        continue;
-                }
+               }
 
                q = net_dev->ib.sq;
                while (q) {
@@ -1475,7 +1646,7 @@ static int isdn_ppp_dev_ioctl_stats(int slot,struct ifreq *ifr,struct device *de
                }
 #endif
        }
-       memcpy_tofs (res, &t, sizeof (struct ppp_stats));
+       copy_to_user (res, &t, sizeof (struct ppp_stats));
        return 0;
 
 }
@@ -1500,7 +1671,7 @@ int isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
                        len = strlen(PPP_VERSION) + 1;
                        error = verify_area(VERIFY_WRITE, r, len);
                        if (!error)
-                               memcpy_tofs(r, PPP_VERSION, len);
+                               copy_to_user(r, PPP_VERSION, len);
                        break;
                case SIOCGPPPSTATS:
                        error = isdn_ppp_dev_ioctl_stats (lp->ppp_slot, ifr, dev);
@@ -1597,3 +1768,13 @@ int isdn_ppp_hangup_slave(char *name)
 #endif
 }
 
+#if 0
+static struct symbol_table isdn_ppp_syms = {
+#include <linux/symtab_begin.h>
+    X(isdn_ppp_register_compressor),
+    X(isdn_ppp_unregister_compressor),
+#include <linux/symtab_end.h>
+};
+#endif
+
+
index 70de759505c254ae9578f714deb2e22652db3185..4568f8d2b1fe0187d41ad4bd560e0281b46f1182 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.h,v 1.4 1996/05/06 11:34:56 hipp Exp $
+/* $Id: isdn_ppp.h,v 1.6 1996/09/23 01:58:11 fritz Exp $
  *
  * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_ppp.h,v $
+ * Revision 1.6  1996/09/23 01:58:11  fritz
+ * Fix: With syncPPP encapsulation, discard LCP packets
+ *      when calculating hangup timeout.
+ *
+ * Revision 1.5  1996/09/07 12:51:34  hipp
+ * *** empty log message ***
+ *
  * Revision 1.4  1996/05/06 11:34:56  hipp
  * fixed a few bugs
  *
@@ -34,6 +41,7 @@
  *
  */
 
+#include <linux/ppp_defs.h> /* for PPP_PROTOCOL */
 extern void isdn_ppp_timer_timeout(void);
 extern int  isdn_ppp_read(int , struct file *, char *, int);
 extern int  isdn_ppp_write(int , struct file *, const char *, int);
@@ -54,3 +62,10 @@ extern int  isdn_ppp_dial_slave(char *);
 extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
 
 extern struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
+
+#define IPPP_OPEN      0x01
+#define IPPP_CONNECT   0x02
+#define IPPP_CLOSEWAIT 0x04
+#define IPPP_NOBLOCK   0x08
+#define IPPP_ASSIGNED  0x10
+
index e53b0548f0f9f2f63b2f1eb3e2beedb6b5c8bb9f..3a0b7ab0e557b55fda23fed99372fa0696fdc0bf 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.21 1996/06/24 17:40:28 fritz Exp $
+/* $Id: isdn_tty.c,v 1.23 1996/10/22 23:14:02 fritz Exp $
  *
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.23  1996/10/22 23:14:02  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
+ * Revision 1.22  1996/10/19 18:56:43  fritz
+ * ATZ did not change the xmitbuf size.
+ *
  * Revision 1.21  1996/06/24 17:40:28  fritz
  * Bugfix: Did not compile without CONFIG_ISDN_AUDIO
  *
 
 static int  isdn_tty_edit_at(const char *, int, modem_info *, int);
 static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int);
-static void isdn_tty_modem_reset_regs(atemu *, int);
+static void isdn_tty_modem_reset_regs(modem_info *, int);
 static void isdn_tty_cmd_ATA(modem_info *);
 static void isdn_tty_at_cout(char *, modem_info *);
 static void isdn_tty_flush_buffer(struct tty_struct *);
@@ -139,7 +145,7 @@ static char *isdn_ttyname_cui  = "cui";
 static int bit2si[8] = {1,5,7,7,7,7,7,7};
 static int si2bit[8] = {4,1,4,4,4,4,4,4};
                                 
-char *isdn_tty_revision        = "$Revision: 1.21 $";
+char *isdn_tty_revision        = "$Revision: 1.23 $";
 
 #define DLE 0x10
 #define ETX 0x03
@@ -375,7 +381,7 @@ static int isdn_tty_end_vrx(const char *buf, int c, int from_user)
                 return 1;
         }
        if (from_user) {
-               memcpy_fromfs(tmpbuf, buf, c);
+               copy_from_user(tmpbuf, buf, c);
                 p = tmpbuf;
         } else
                 p = (char *)buf;
@@ -710,7 +716,7 @@ static void isdn_tty_change_speed(modem_info * info)
 #endif
                         if (info->online)
                                 info->ncarrier = 1;
-                        isdn_tty_modem_reset_regs(&info->emu, 0);
+                        isdn_tty_modem_reset_regs(info, 0);
                         isdn_tty_modem_hup(info);
                 }
                 return;
@@ -785,7 +791,7 @@ static void isdn_tty_shutdown(modem_info * info)
        if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
                info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
                 if (info->emu.mdmreg[13] & 4) {
-                        isdn_tty_modem_reset_regs(&info->emu, 0);
+                        isdn_tty_modem_reset_regs(info, 0);
 #ifdef ISDN_DEBUG_MODEM_HUP
                         printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
 #endif
@@ -836,7 +842,7 @@ static int isdn_tty_write(struct tty_struct *tty, int from_user, const u_char *
                                                    &(m->lastplus),
                                                    from_user);
                         if (from_user)
-                                memcpy_fromfs(&(info->xmit_buf[info->xmit_count]), buf, c);
+                                copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c);
                         else
                                 memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
 #ifdef CONFIG_ISDN_AUDIO
@@ -1041,9 +1047,10 @@ static int isdn_tty_get_modem_info(modem_info * info, uint * value)
 
 static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
 {
-       uint arg = get_user((uint *) value);
+       uint arg;
         int pre_dtr;
 
+    GET_USER(arg, (uint *)value);
        switch (cmd) {
                 case TIOCMBIS:
 #ifdef ISDN_DEBUG_MODEM_IOCTL
@@ -1067,7 +1074,7 @@ static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
                         if (arg & TIOCM_DTR) {
                                 info->mcr &= ~UART_MCR_DTR;
                                 if (info->emu.mdmreg[13] & 4) {
-                                        isdn_tty_modem_reset_regs(&info->emu, 0);
+                                        isdn_tty_modem_reset_regs(info, 0);
 #ifdef ISDN_DEBUG_MODEM_HUP
                                         printk(KERN_DEBUG "Mhup in TIOCMBIC\n");
 #endif
@@ -1088,7 +1095,7 @@ static int isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value)
                         if (pre_dtr |= (info->mcr & UART_MCR_DTR)) {
                                 if (!(info->mcr & UART_MCR_DTR)) {
                                         if (info->emu.mdmreg[13] & 4) {
-                                                isdn_tty_modem_reset_regs(&info->emu, 0);
+                                                isdn_tty_modem_reset_regs(info, 0);
 #ifdef ISDN_DEBUG_MODEM_HUP
                                                 printk(KERN_DEBUG "Mhup in TIOCMSET\n");
 #endif
@@ -1152,7 +1159,7 @@ static int isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
                         error = verify_area(VERIFY_READ, (void *) arg, sizeof(long));
                         if (error)
                                 return error;
-                        arg = get_user((ulong *) arg);
+                        GET_USER(arg, (ulong *) arg);
                         tty->termios->c_cflag =
                                 ((tty->termios->c_cflag & ~CLOCAL) |
                                  (arg ? CLOCAL : 0));
@@ -1546,11 +1553,13 @@ static void isdn_tty_modem_reset_vpar(atemu *m)
         m->vpar[3] = 2;  /* Compression type        (1 = ADPCM-2   ) */
 }
 
-static void isdn_tty_modem_reset_regs(atemu * m, int force)
+static void isdn_tty_modem_reset_regs(modem_info *info, int force)
 {
+        atemu *m = &info->emu;
        if ((m->mdmreg[12] & 32) || force) {
                memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
                memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
+                info->xmit_size = m->mdmreg[16] * 16;
        }
         isdn_tty_modem_reset_vpar(m);
        m->mdmcmdl = 0;
@@ -1622,7 +1631,7 @@ int isdn_tty_modem_init(void)
        for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
                info = &m->info[i];
                isdn_tty_reset_profile(&info->emu);
-               isdn_tty_modem_reset_regs(&info->emu, 1);
+               isdn_tty_modem_reset_regs(info, 1);
                info->magic = ISDN_ASYNC_MAGIC;
                info->line = i;
                info->tty = 0;
@@ -1840,7 +1849,7 @@ static void isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pl
                *pluscount = 0;
        }
        if (from_user) {
-               memcpy_fromfs(cbuf, p, count);
+               copy_from_user(cbuf, p, count);
                p = cbuf;
        }
        while (count > 0) {
@@ -2054,7 +2063,7 @@ static int isdn_tty_cmd_ATand(char **p, modem_info * info)
                         /* &F -Set Factory-Defaults */
                         p[0]++;
                         isdn_tty_reset_profile(m);
-                        isdn_tty_modem_reset_regs(m, 1);
+                        isdn_tty_modem_reset_regs(info, 1);
                         break;
                 case 'S':
                         /* &S - Set Windowsize */
@@ -2612,7 +2621,7 @@ static void isdn_tty_parse_at(modem_info * info)
                         case 'Z':
                                 /* Z - Load Registers from Profile */
                                 p++;
-                                isdn_tty_modem_reset_regs(m, 1);
+                                isdn_tty_modem_reset_regs(info, 1);
                                 break;
 #ifdef CONFIG_ISDN_AUDIO
                         case '+':
@@ -2670,7 +2679,7 @@ static int isdn_tty_edit_at(const char *p, int count, modem_info * info, int use
 
        for (cnt = count; cnt > 0; p++, cnt--) {
                if (user)
-                       c = get_user(p);
+                       GET_USER(c, p);
                else
                        c = *p;
                total++;
index 806a27a2f535321dae2b03d16efe2a20436fd3a4..dc386a13387207c8fab30ac98c9f4950304d2a44 100644 (file)
@@ -428,7 +428,7 @@ int pcbit_writecmd(const u_char* buf, int len, int user, int driver, int channel
                {
                        u_char cbuf[1024];
 
-                       memcpy_fromfs(cbuf, buf, len);
+                       copy_from_user(cbuf, buf, len);
                        for (i=0; i<len; i++)
                                writeb(cbuf[i], dev->sh_mem + i);
                }
@@ -446,7 +446,7 @@ int pcbit_writecmd(const u_char* buf, int len, int user, int driver, int channel
                        /* get it into kernel space */
                        if ((ptr = kmalloc(len, GFP_KERNEL))==NULL)
                                return -ENOMEM;
-                       memcpy_fromfs(ptr, buf, len);
+                       copy_from_user(ptr, buf, len);
                        loadbuf = ptr;
                }
                else
@@ -761,8 +761,13 @@ static int stat_st = 0;
 static int stat_end = 0;
 
 
-#define memcpy_to_COND(flag, d, s, len) \
-(flag ? memcpy_tofs(d, s, len) : memcpy(d, s, len))
+static __inline void
+memcpy_to_COND(int flag, char *d, const char *s, int len) {
+       if (flag)
+               copy_to_user(d, s, len);
+       else
+               memcpy(d, s, len);
+}
 
 
 int pcbit_stat(u_char* buf, int len, int user, int driver, int channel)
index d46c283632f3abd7c66810e5d027471f55fd4ccf..7333fdcc3e322584d1881ff5b1f3abd4750a87dd 100644 (file)
@@ -1,6 +1,9 @@
-/* $Id: callc.c,v 1.13 1996/06/24 17:15:55 fritz Exp $
+/* $Id: callc.c,v 1.14 1996/10/22 23:14:14 fritz Exp $
  *
  * $Log: callc.c,v $
+ * Revision 1.14  1996/10/22 23:14:14  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
  * Revision 1.13  1996/06/24 17:15:55  fritz
  * corrected return code of teles_writebuf()
  *
@@ -1451,7 +1454,7 @@ teles_writebuf(int id, int chan, const u_char * buf, int count, int user)
         ptr += i;
 
         if (user)
-                memcpy_fromfs(ptr, buf, count);
+                copy_from_user(ptr, buf, count);
         else
                 memcpy(ptr, buf, count);
         ibh->datasize = count + i;
index c90bcd00bc5ae0d120711c362b6d09fd86da085a..2ada8a29d399a66f38b1bc7794ec50fff279e181 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: card.c,v 1.13 1996/07/18 11:21:24 jdenoud Exp $
+/* $Id: card.c,v 1.16 1996/10/22 23:14:16 fritz Exp $
  *
  * card.c     low level stuff for the Teles S0 isdn card
  * 
@@ -7,6 +7,15 @@
  * Beat Doebeli         log all D channel traffic
  * 
  * $Log: card.c,v $
+ * Revision 1.16  1996/10/22 23:14:16  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
+ * Revision 1.15  1996/09/29 19:41:56  fritz
+ * Bugfix: ignore unknown frames.
+ *
+ * Revision 1.14  1996/09/23 01:53:49  fritz
+ * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6).
+ *
  * Revision 1.13  1996/07/18 11:21:24  jdenoud
  * Use small buffers for incoming audio data
  *
@@ -59,6 +68,7 @@
 
 #define __NO_VERSION__
 #include "teles.h"
+#include "proto.h"
 
 #define INCLUDE_INLINE_FUNCS
 #include <linux/tqueue.h>
@@ -77,7 +87,7 @@ extern int      nrcards;
 static inline   byte
 readisac_0(byte * cardm, byte offset)
 {
-       return *(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
+       return readb(cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
 }
 
 static inline   byte
@@ -92,7 +102,7 @@ readisac_3(int iobase, byte offset)
 static inline void
 writeisac_0(byte * cardm, byte offset, byte value)
 {
-       *(byte *) (cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset) = value;
+       writeb(value, cardm + 0x100 + ((offset & 1) ? 0x1ff : 0) + offset);
 }
 
 static inline void
@@ -119,7 +129,7 @@ writeisac_s(int iobase, byte offset, byte * src, int count)
 static inline   byte
 readhscx_0(byte * base, byte hscx, byte offset)
 {
-       return *(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
+       return readb(base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
                          ((hscx & 1) ? 0x40 : 0) + offset);
 }
 
@@ -135,8 +145,8 @@ readhscx_3(int iobase, byte hscx, byte offset)
 static inline void
 writehscx_0(byte * base, byte hscx, byte offset, byte data)
 {
-       *(byte *) (base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
-                  ((hscx & 1) ? 0x40 : 0) + offset) = data;
+       writeb(data, base + 0x180 + ((offset & 1) ? 0x1FF : 0) +
+                  ((hscx & 1) ? 0x40 : 0) + offset);
 }
 
 static inline void
@@ -1253,12 +1263,12 @@ checkcard(int cardnr)
         if (card->membase) {
                 cli();
                 timout = jiffies + (HZ / 5) + 1;
-                *(byte *) (card->membase + 0x80) = 0;
+                writeb(0, card->membase + 0x80);
                 sti();
                 while (jiffies <= timout);
                 
                 cli();
-                *(byte *) (card->membase + 0x80) = 1;
+                writeb(1, card->membase + 0x80);
                 timout = jiffies + (HZ / 5) + 1;
                 sti();
                 while (jiffies <= timout);
index 411dc4ad435d89fae02f774f6c7223e421bb0ac1..31f616fa016f23fcdb775778942459701594cfe5 100644 (file)
@@ -1,6 +1,12 @@
-/* $Id: isdnl3.c,v 1.9 1996/06/06 14:22:27 fritz Exp $
+/* $Id: isdnl3.c,v 1.11 1996/09/29 19:41:58 fritz Exp $
  *
  * $Log: isdnl3.c,v $
+ * Revision 1.11  1996/09/29 19:41:58  fritz
+ * Bugfix: ignore unknown frames.
+ *
+ * Revision 1.10  1996/09/25 18:32:43  keil
+ * response for STATUS_ENQ message added
+ *
  * Revision 1.9  1996/06/06 14:22:27  fritz
  * Changed level of "non-digital call..." message, since
  * with audio support, this is quite normal.
@@ -391,6 +397,42 @@ l3s20(struct PStack *st, byte pr,
        newl3state(st, 7);
 }
 
+static void
+l3s21(struct PStack *st, byte pr, void *arg)
+{
+       struct BufHeader *dibh=arg;
+       byte           *p;
+       int             size;
+
+       BufPoolRelease(dibh);
+       
+       BufPoolGet(&dibh, st->l1.sbufpool, GFP_ATOMIC, (void *) st, 20);
+       p = DATAPTR(dibh);
+       p += st->l2.ihsize;
+       size = st->l2.ihsize;
+
+       *p++ = 0x8;
+       *p++ = 0x1;
+       *p++ = st->l3.callref;
+       *p++ = MT_STATUS;
+       size += 4;
+
+       *p++ = IE_CAUSE;
+       *p++ = 0x2;
+       *p++ = 0x80;
+       *p++ = 0x9E; /* answer status enquire */
+       size += 4;
+
+       *p++ = 0x14; /* CallState */
+       *p++ = 0x1;
+       *p++ = st->l3.state & 0x3f; /* ISO L3 CallState */
+       size += 3;
+
+       dibh->datasize = size;
+       i_down(st, dibh);
+
+}
+
 struct stateentry {
        int             state;
        byte            primitive;
@@ -432,34 +474,44 @@ sizeof(struct stateentry);
 
 static struct stateentry datastatelist[] =
 {
+        {0,MT_STATUS_ENQUIRY,l3s21},
         {0,MT_SETUP,l3s12},
+        {1,MT_STATUS_ENQUIRY,l3s21},
         {1,MT_CALL_PROCEEDING,l3s6},
         {1,MT_SETUP_ACKNOWLEDGE,l3s6},
         {1,MT_RELEASE_COMPLETE,l3s4},
         {1,MT_RELEASE,l3s19},
         {1,MT_DISCONNECT,l3s7},
+        {3,MT_STATUS_ENQUIRY,l3s21},
         {3,MT_DISCONNECT,l3s7},
         {3,MT_CONNECT,l3s8},
         {3,MT_ALERTING,l3s11},
         {3,MT_RELEASE,l3s19},
         {3,MT_RELEASE_COMPLETE,l3s4},
+        {4,MT_STATUS_ENQUIRY,l3s21},
         {4,MT_CONNECT,l3s8},
         {4,MT_DISCONNECT,l3s7},
         {4,MT_RELEASE,l3s19},
         {4,MT_RELEASE_COMPLETE,l3s4},
+        {8,MT_STATUS_ENQUIRY,l3s21},
         {6,MT_SETUP,l3s12},
+        {8,MT_STATUS_ENQUIRY,l3s21},
         {7,MT_RELEASE,l3s19},
         {7,MT_RELEASE_COMPLETE,l3s4_1},
         {7,MT_DISCONNECT,l3s7},
+        {8,MT_STATUS_ENQUIRY,l3s21},
         {8,MT_RELEASE,l3s19},
         {8,MT_CONNECT_ACKNOWLEDGE,l3s17},
         {8,MT_DISCONNECT,l3s7},
         {8,MT_RELEASE_COMPLETE,l3s4_1},
+        {10,MT_STATUS_ENQUIRY,l3s21},
         {10,MT_DISCONNECT,l3s7},
         {10,MT_RELEASE,l3s19},
         {10,MT_RELEASE_COMPLETE,l3s4_1},
+        {11,MT_STATUS_ENQUIRY,l3s21},
         {11,MT_RELEASE,l3s19},
         {11,MT_RELEASE_COMPLETE,l3s4},
+        {19,MT_STATUS_ENQUIRY,l3s21},
         {19,MT_RELEASE_COMPLETE,l3s4},
 };
 
@@ -502,7 +554,7 @@ l3up(struct PStack *st,
                                  datastatelist_1tr6t[i].rout(st, pr, ibh);
                          break;
 #endif
-                 default:      /* E-DSS1 */
+                 case PROTO_EURO:      /* E-DSS1 */
                          for (i = 0; i < datasllen; i++)
                                  if ((st->l3.state == datastatelist[i].state) &&
                                      (mt == datastatelist[i].primitive))
@@ -514,6 +566,10 @@ l3up(struct PStack *st,
                                                st->l3.state, mt);
                          } else
                                  datastatelist[i].rout(st, pr, ibh);
+                         break;
+                 default:
+                         BufPoolRelease(ibh);
+                         break;
                }
        } else if (pr == DL_UNIT_DATA) {
                ptr = DATAPTR(ibh);
@@ -540,7 +596,7 @@ l3up(struct PStack *st,
                                  datastatelist_1tr6t[i].rout(st, pr, ibh);
                          break;
 #endif
-                 default:      /* E-DSS1 */
+                 case PROTO_EURO:      /* E-DSS1 */
                          for (i = 0; i < datasllen; i++)
                                  if ((st->l3.state == datastatelist[i].state) &&
                                      (mt == datastatelist[i].primitive))
@@ -552,6 +608,10 @@ l3up(struct PStack *st,
                                                st->l3.state, mt);
                          } else
                                  datastatelist[i].rout(st, pr, ibh);
+                         break;
+                 default:
+                         BufPoolRelease(ibh);
+                         break;
                }
        }
 }
index e3716769c9a42606e6e44cb4080e7fc9a62911af..1e237e1527524fe7b2aa61370b6b141b85c43226 100644 (file)
@@ -1,6 +1,12 @@
-/* $Id: l3_1TR6.c,v 1.4 1996/06/06 14:22:28 fritz Exp $
+/* $Id: l3_1TR6.c,v 1.6 1996/09/25 18:34:57 keil Exp $
  *
  * $Log: l3_1TR6.c,v $
+ * Revision 1.6  1996/09/25 18:34:57  keil
+ * missing states in 1TR6 Statemachine added
+ *
+ * Revision 1.5  1996/09/23 01:53:51  fritz
+ * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6).
+ *
  * Revision 1.4  1996/06/06 14:22:28  fritz
  * Changed level of "non-digital call..." message, since
  * with audio support, this is quite normal.
@@ -19,6 +25,8 @@
  *
  */
 
+#include       "proto.h"
+
 static void
 l3_1TR6_message(struct PStack *st, int mt, int pd)
 {
@@ -404,7 +412,7 @@ l3_1tr6_conn(struct PStack *st, byte pr,
 }
 
 static void
-l3_1tr6_ignore(struct PStack *st, byte pr, void *arg)
+l3_1tr6_reset(struct PStack *st, byte pr, void *arg)
 {
        newl3state(st, 0);
 }
@@ -453,16 +461,36 @@ l3_1tr6_rel_req(struct PStack *st, byte pr, void *arg)
 static struct stateentry downstatelist_1tr6t[] =
 {
        {0, CC_SETUP_REQ, l3_1tr6_setup},
+       {1, CC_DISCONNECT_REQ, l3_1tr6_disconn_req},
+       {1, CC_RELEASE_REQ, l3_1tr6_rel_req},
+        {1, CC_DLRL, l3_1tr6_reset},
+       {2, CC_DISCONNECT_REQ, l3_1tr6_disconn_req},
+       {2, CC_RELEASE_REQ, l3_1tr6_rel_req},
+        {2, CC_DLRL, l3_1tr6_reset},
+       {3, CC_DISCONNECT_REQ, l3_1tr6_disconn_req},
+       {3, CC_RELEASE_REQ, l3_1tr6_rel_req},
+        {3, CC_DLRL, l3_1tr6_reset},
        {4, CC_DISCONNECT_REQ, l3_1tr6_disconn_req},
-       {6, CC_REJECT_REQ, l3_1tr6_ignore},
+       {4, CC_RELEASE_REQ, l3_1tr6_rel_req},
+        {4, CC_DLRL, l3_1tr6_reset},
+       {6, CC_REJECT_REQ, l3_1tr6_reset},
+       {6, CC_RELEASE_REQ, l3_1tr6_rel_req},
        {6, CC_SETUP_RSP, l3_1tr6_conn},
        {6, CC_ALERTING_REQ, l3_1tr6_alert},
+        {6, CC_DLRL, l3_1tr6_reset},
        {7, CC_SETUP_RSP, l3_1tr6_conn},
+       {7, CC_RELEASE_REQ, l3_1tr6_rel_req},
        {7, CC_DISCONNECT_REQ, l3_1tr6_disconn_req},
-        {7, CC_DLRL, l3_1tr6_disconn_req},
+        {7, CC_DLRL, l3_1tr6_reset},
        {8, CC_DISCONNECT_REQ, l3_1tr6_disconn_req},
+       {8, CC_RELEASE_REQ, l3_1tr6_rel_req},
+        {8, CC_DLRL, l3_1tr6_reset},
        {10, CC_DISCONNECT_REQ, l3_1tr6_disconn_req},
-       {12, CC_RELEASE_REQ, l3_1tr6_rel_req}
+       {10, CC_RELEASE_REQ, l3_1tr6_rel_req},
+        {10, CC_DLRL, l3_1tr6_reset},
+       {12, CC_RELEASE_REQ, l3_1tr6_rel_req},
+        {12, CC_DLRL, l3_1tr6_reset},
+        {19, CC_DLRL, l3_1tr6_reset},
 };
 
 static int      downsl_1tr6t_len = sizeof(downstatelist_1tr6t) /
index a3502fb36dc4d5f33d7f9ae4163b09ffc458875c..e3b538e260e9433c78665fb5ec96689514ed63c0 100644 (file)
@@ -1,6 +1,9 @@
-/* $Id: l3_1TR6.h,v 1.3 1996/04/30 21:53:48 isdn4dev Exp $
+/* $Id: l3_1TR6.h,v 1.4 1996/09/23 01:53:52 fritz Exp $
  *
  * $Log: l3_1TR6.h,v $
+ * Revision 1.4  1996/09/23 01:53:52  fritz
+ * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6).
+ *
  * Revision 1.3  1996/04/30 21:53:48  isdn4dev
  * Bugs, SPV, Logging in q931.c  Karsten Keil
  *
@@ -12,9 +15,6 @@
 #ifndef l3_1TR6
 #define l3_1TR6
 
-#define PROTO_DIS_N0 0x40
-#define PROTO_DIS_N1 0x41
-
 /*
  * MsgType N0
  */
index ce022f7a0e06714e57c3811093dff673de6f24c2..7e32c2f4f43b6e9ba020565d3b995055e43993c2 100644 (file)
@@ -1,6 +1,9 @@
-/* $Id: llglue.c,v 1.6 1996/06/03 20:03:39 fritz Exp $
+/* $Id: llglue.c,v 1.7 1996/10/22 23:14:17 fritz Exp $
  *
  * $Log: llglue.c,v $
+ * Revision 1.7  1996/10/22 23:14:17  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
  * Revision 1.6  1996/06/03 20:03:39  fritz
  * Fixed typos.
  *
@@ -47,7 +50,7 @@ teles_readstatus(byte * buf, int len, int user, int id, int channel)
 
        for (p = buf, count = 0; count < len; p++, count++) {
                if (user)
-                       put_fs_byte(*teles_status_read++, p);
+                       put_user(*teles_status_read++, p);
                else
                        *p++ = *teles_status_read++;
                if (teles_status_read > teles_status_end)
index 0b93388cfd59fa6eabb9a0d286e72ad6cf938238..c9f5fa6922e5ca4b25e382aaf5068955c441a96f 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: q931.c,v 1.5 1996/06/03 20:03:40 fritz Exp $
+/* $Id: q931.c,v 1.6 1996/09/23 01:53:53 fritz Exp $
  *
  * q931.c               code to decode ITU Q.931 call control messages
  * 
@@ -14,6 +14,9 @@
  *
  * 
  * $Log: q931.c,v $
+ * Revision 1.6  1996/09/23 01:53:53  fritz
+ * Bugfix: discard unknown frames (non-EDSS1 and non-1TR6).
+ *
  * Revision 1.5  1996/06/03 20:03:40  fritz
  * Fixed typos.
  *
@@ -35,6 +38,7 @@
 
 #define __NO_VERSION__
 #include "teles.h"
+#include "proto.h"
 #include "l3_1TR6.h"
 
 byte           *
@@ -1083,7 +1087,7 @@ dlogframe(struct IsdnCardState *sp, byte * buf, int size, char *comment) {
                        }
                        buf += buf[1] + 2;
                }
-       } else {        /* EURO */
+       } else if (buf[0]==PROTO_EURO) {        /* EURO */
                /* locate message type */
                for (i = 0; i < MTSIZE; i++)
                        if (mtlist[i].nr == buf[3])
@@ -1144,6 +1148,8 @@ dlogframe(struct IsdnCardState *sp, byte * buf, int size, char *comment) {
                        buf += buf[1] + 2;
                }
        }
+       else dp += sprintf(dp,"Unnown frame type %.2x, ignored\n",buf[0]);
+
        dp += sprintf(dp, "\n");
        teles_putstatus(sp->dlogspace);
 }
index 73ad973bedb440469545ed4dd8cecd5406ba61d0..38cd658a81a7e8f381667655e4869107c0fb99b4 100644 (file)
@@ -19,6 +19,7 @@ Board         Multicast       AllMulti        Promisc         Filter
 3c505          YES             NO              YES             Hardware
 3c507          NO              NO              NO              N/A
 3c509          YES             YES             YES             Software
+3c59x          YES             YES             YES             Software
 ac3200         YES             YES             YES             Software(#)
 apricot                YES             PROMISC         YES             Hardware
 arcnet         NO              NO              NO              N/A
index de8e26140a89efd7215cc38a5d0f2c219fb8c1eb..2c56bf7213a2eaff885b333ce3f46076c3b25f70 100644 (file)
@@ -29,8 +29,7 @@
     measurement. Their error is +/-20k on a quiet (private) network and also
     depend on what load the CPU has.
 
-    The author may    be reached  at  davies@wanton.lkg.dec.com  or  Digital
-    Equipment Corporation, 550 King Street, Littleton MA 01460.
+    The author may be reached at davies@maniac.ultranet.com.
 
     =========================================================================
     This driver has been written  substantially  from scratch, although  its
                          and <michael@compurex.com>
       0.441   9-Sep-96    Change dc21041_autoconf() to probe quiet BNC media
                            with a loopback packet.
+      0.442   9-Sep-96    Include AUI in dc21041 media printout. Bug reported
+                           by <bhat@mundook.cs.mu.OZ.AU>
 
     =========================================================================
 */
 
-static const char *version = "de4x5.c:v0.441 96/9/9 davies@wanton.lkg.dec.com\n";
+static const char *version = "de4x5.c:v0.442 96/11/7 davies@maniac.ultranet.com\n";
 
 #include <linux/module.h>
 
@@ -915,7 +916,7 @@ de4x5_hw_init(struct device *dev, u_long iobase)
 
     }
     
-    if (de4x5_debug > 0) {
+    if (de4x5_debug > 1) {
        printk(version);
     }
     
@@ -3760,10 +3761,11 @@ de4x5_dbg_media(struct device *dev)
                        (lp->media == TP  ? "TP." :
                         (lp->media == ANS ? "TP/Nway." :
                          (lp->media == BNC ? "BNC." : 
-                          (lp->media == BNC_AUI ? "BNC/AUI." : 
-                           (lp->media == EXT_SIA ? "EXT SIA." : 
-                            "???."
-                            )))))));
+                          (lp->media == AUI ? "AUI." : 
+                           (lp->media == BNC_AUI ? "BNC/AUI." : 
+                            (lp->media == EXT_SIA ? "EXT SIA." : 
+                             "???."
+                             ))))))));
            } else {
                printk("%s: mode is %s\n", dev->name,
                    (lp->media == NC ? "link down or incompatible connection.":
index 3e194f4be3e901de818776a93e5ad2700c0a7ee6..0eef451ff8123b2c35292a7fc8e933aebf7be39d 100644 (file)
@@ -37,9 +37,7 @@
     I have benchmarked the driver with a  DE100 at 595kB/s to (542kB/s from)
     a DECstation 5000/200.
 
-    The   author   may    be   reached  at    davies@wanton.lkg.dec.com   or
-    davies@maniac.ultranet.com  or Digital  Equipment Corporation, 550  King
-    Street, Littleton MA 01460.
+    The author may be reached at davies@maniac.ultranet.com
 
     =========================================================================
 
     =========================================================================
 */
 
-static const char *version = "depca.c:v0.43 96/8/16 davies@wanton.lkg.dec.com\n";
+static const char *version = "depca.c:v0.43 96/8/16 davies@maniac.ultranet.com\n";
 
 #include <linux/module.h>
 
@@ -650,7 +648,7 @@ depca_hw_init(struct device *dev, u_long ioaddr)
       status = -ENXIO;
     }
     if (!status) {
-      if (depca_debug > 0) {
+      if (depca_debug > 1) {
        printk(version);
       }
 
index df006b3555202c0b4b4c4da3e882d85ff163226f..fc7b5a04ecfe7b649615557c79ec6bf69cc966b8 100644 (file)
@@ -18,9 +18,7 @@
     card and benchmarked with 'ttcp': it transferred 16M  of data at 975kB/s
     (7.8Mb/s) to a DECstation 5000/200.
 
-    The     author  may  be    reached    at  davies@wanton.lkg.dec.com   or
-    davies@maniac.ultranet.com or  Digital  Equipment Corporation,  550 King
-    Street, Littleton MA 01460.
+    The author may be reached at davies@maniac.ultranet.com.
 
     =========================================================================
     This driver has been written  substantially  from scratch, although  its
     =========================================================================
 */
 
-static const char *version = "ewrk3.c:v0.43 96/8/16 davies@wanton.lkg.dec.com\n";
+static const char *version = "ewrk3.c:v0.43 96/8/16 davies@maniac.ultranet.com\n";
 
 #include <linux/module.h>
 
@@ -590,7 +588,7 @@ ewrk3_hw_init(struct device *dev, u_long iobase)
     }
 
     if (!status) {
-      if (ewrk3_debug > 0) {
+      if (ewrk3_debug > 1) {
        printk(version);
       }
       
index 7c3e1cad4a2087b2914438aadf81ee9f54d4aedc..f8766c68824c882b4b7ab43fdec9ed0e8c72ce62 100644 (file)
@@ -20,6 +20,8 @@
  *              Michael Griffith:       Don't bother computing the checksums
  *                                      on packets received on the loopback
  *                                      interface.
+ *             Alexey Kuznetsov:       Potential hang under some extreme
+ *                                     cases removed.
  *
  *             This program is free software; you can redistribute it and/or
  *             modify it under the terms of the GNU General Public License
@@ -73,9 +75,9 @@ static int loopback_xmit(struct sk_buff *skb, struct device *dev)
        {
                struct sk_buff *skb2=skb;
                skb=skb_clone(skb, GFP_ATOMIC);         /* Clone the buffer */
-               if(skb==NULL)
-                       return 1;
                dev_kfree_skb(skb2, FREE_WRITE);
+               if(skb==NULL)
+                       return 0;
                unlock=0;
        }
        else if(skb->sk)
index 7eb8adbe83d03e2c86bdf56c3de8e16bd8a01515..ad0c83af5fde4bdf8298fac18b2c472214588497 100644 (file)
@@ -17,7 +17,8 @@
 static char *version =
 "tulip.c:v0.10 8/11/95 becker@cesdis.gsfc.nasa.gov\n"
 "        +0.72 4/17/96 "
-"http://www.dsl.tutics.tut.ac.jp/~linux/tulip\n";
+"http://www.dsl.tutics.tut.ac.jp/~linux/tulip\n"
+"        +0.01 10/24/96 mjacob@feral.com (2.1.7)\n";
 
 /* A few user-configurable values. */
 
@@ -334,6 +335,7 @@ struct tulip_private {
        int setup_frame[48];    /* Pseudo-Tx frame to init address table. */
        void (*port_select)(struct device *dev);
        int (*port_fail)(struct device *dev);
+       struct device *next_module;
        char *signature;
        unsigned int cur_rx, cur_tx;            /* The next free ring entry */
        unsigned int dirty_rx, dirty_tx;        /* The ring entries to be free()ed. */
@@ -367,7 +369,6 @@ static int tulip_rx(struct device *dev);
 static void tulip_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 static int tulip_close(struct device *dev);
 static struct enet_statistics *tulip_get_stats(struct device *dev);
-static struct device *tulip_alloc(struct device *dev);
 static void set_multicast_list(struct device *dev);
 
 #define        generic21140_fail       NULL
@@ -379,6 +380,11 @@ static void cogent21140_select(struct device *dev);
 static int generic21040_fail(struct device *dev);
 static int generic21041_fail(struct device *dev);
 
+#ifdef MODULE
+/* A list of all installed Tulip devices, for removing the driver module. */
+static struct device *root_tulip_dev = NULL;
+#endif
+
 static struct {
        void (*port_select)(struct device *dev);
        int (*port_fail)(struct device *dev);
@@ -436,7 +442,6 @@ static struct {
 
 #ifdef MODULE
 static int if_port=TULIP_AUTO_PORT;
-static size_t alloc_size;
 #ifdef TULIP_FULL_DUPLEX
 static int full_duplex=1;
 #else
@@ -997,7 +1002,8 @@ tulip_rx(struct device *dev)
                        if (status & TRING_RxFIFO) lp->stats.rx_fifo_errors++;
                } else {
                        /* Malloc up new buffer, compatible with net-2e. */
-                       short pkt_len = lp->rx_ring[entry].status >> 16;
+                       /* Omit the four octet CRC from the length. */
+                       short pkt_len = (lp->rx_ring[entry].status >> 16) - 4;
                        struct sk_buff *skb;
 
                        skb = dev_alloc_skb(pkt_len + 2);
@@ -1132,6 +1138,7 @@ static void set_multicast_list(struct device *dev)
                        *setup_frm++ = eaddrs[2];
                } while (++i < 15);
 
+#ifndef        __alpha__
                /* Now add this frame to the Tx list. */
                {
                        unsigned long flags;
@@ -1152,46 +1159,8 @@ static void set_multicast_list(struct device *dev)
                        /* Trigger an immediate transmit demand. */
                        tio_write(TPOLL_TRIGGER, CSR1);
                }
-       }
-}
-
-static struct device *tulip_alloc(struct device *dev)
-{
-       struct tulip_private *tp;
-       char *buff;
-#ifndef        MODULE
-       size_t alloc_size;
 #endif
-       if (!dev || dev->priv) {
-               struct device *olddev = dev;
-
-               alloc_size = sizeof(struct device)
-                       + sizeof(struct tulip_private)
-                       + ETHNAMSIZ;
-               alloc_size = ROUND_UP(alloc_size, 8);
-
-               buff = (char *)kmalloc(alloc_size, GFP_KERNEL);
-               dev = (struct device *)buff;
-               if (dev == NULL) {
-                       printk("tulip_alloc: kmalloc failed.\n");
-                       return(NULL);
-               }
-               tp = (struct tulip_private *)(buff + sizeof(struct device));
-               memset(buff, 0, alloc_size);
-               dev->priv = (void *)tp;
-               dev->name = (char *)(buff + sizeof(struct device)
-                                                        + sizeof(struct tulip_private));
-               if (olddev) {
-                       dev->next = olddev->next;
-                       olddev->next = dev;
-               }
-       } else {
-               alloc_size = ROUND_UP(sizeof(struct tulip_private), 8);
-               tp = (struct tulip_private *)kmalloc(alloc_size, GFP_KERNEL);
-               memset((void *)tp, 0, alloc_size);
-               dev->priv = (void *)tp;
        }
-       return(dev);
 }
 
 int
@@ -1200,6 +1169,7 @@ tulip_hwinit(struct device *dev, int ioaddr,
 {
        /* See note below on the Znyx 315 etherarray. */
        static unsigned char last_phys_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
+       static int last_irq;
        char detect_mesg[80], *mesgp=detect_mesg;
        struct tulip_private *tp = (struct tulip_private *)dev->priv;
        int i;
@@ -1269,11 +1239,13 @@ tulip_hwinit(struct device *dev, int ioaddr,
                for (i = 0; i < ETH_ALEN - 1; i++)
                        dev->dev_addr[i] = last_phys_addr[i];
                dev->dev_addr[i] = last_phys_addr[i] + 1;
+               irq = last_irq;
        }
        for (i = 0; i < ETH_ALEN - 1; i++)
                mesgp += sprintf(mesgp, "%2.2x:", dev->dev_addr[i]);
        mesgp += sprintf(mesgp, "%2.2x, IRQ %d\n",
                                         last_phys_addr[i] = dev->dev_addr[i], irq);
+       last_irq = irq;
 
        /* copy ethernet address */
        if (card_type(tp, device_id,
@@ -1295,21 +1267,20 @@ tulip_hwinit(struct device *dev, int ioaddr,
        dev->set_multicast_list = &set_multicast_list;
 
 #ifdef MODULE
-    ether_setup(dev);
        if (if_port == TULIP_AUTO_PORT)
                if_port = TULIP_PORT;
        else
                tp->port_fix = 1;
        dev->if_port = if_port;
        tp->full_duplex = full_duplex;
+       tp->next_module = root_tulip_dev;
+       root_tulip_dev = dev;
 #else
 #ifdef TULIP_FULL_DUPLEX
        tp->full_duplex = 1;
 #endif
-    init_etherdev(dev, 0);
        dev->if_port = TULIP_PORT;
 #endif
-
 #ifdef TULIP_FIX_PORT
        tp->port_fix = 1;
 #endif
@@ -1340,14 +1311,13 @@ int tulip_probe(struct device *dev)
 
     if (!pcibios_present()) return(-ENODEV);
 
-       for (pci_index = 0; pci_index < 8; pci_index++) {
+       for (pci_index = 0; pci_index < 0xff; pci_index++) {
                /* Search for the PCI_DEVICE_ID_DEV_TULIP* chips */
-               for (cno = 0; pci_chips[cno] != PCI_DEVICE_ID_NONE; cno ++)
+               for (cno = 0; pci_chips[cno] != PCI_DEVICE_ID_NONE; cno++) {
                        if (pcibios_find_device(PCI_VENDOR_ID_DEC,
                                                                        pci_chips[cno],
                                                                        pci_index, &pci_bus,
                                                                        &pci_device_fn) == 0) {
-                               struct device *dp;
 
                                /* get IO address */
                                pcibios_read_config_dword(pci_bus, pci_device_fn,
@@ -1355,19 +1325,14 @@ int tulip_probe(struct device *dev)
                                                                                  &pci_ioaddr);
                                /* Remove I/O space marker in bit 0. */
                                pci_ioaddr &= ~3;
-                               for (dp = tulip_head; dp != NULL; dp = dp->next)
-                                       if (dp->base_addr == pci_ioaddr) break;
-                               if (dp) continue;
                                /* get IRQ */
-                               pcibios_read_config_byte(pci_bus, pci_device_fn,
-                                                                                PCI_INTERRUPT_LINE, &pci_irq);
-#ifdef MODULE
-                               /* compare requested IRQ/IO address */
-                               if (dev && dev->base_addr &&
-                                       dev->base_addr != pci_ioaddr) continue;
-#else
-                               if ((dev = tulip_alloc(dev)) == NULL) break;
-#endif
+                               pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pci_irq);
+                               dev = init_etherdev(NULL, 
+                                       ROUND_UP(sizeof(struct device) +
+                                               sizeof (struct tulip_private) +
+                                               ETHNAMSIZ, 8));
+
+                               if (dev == NULL) break;
                                if (!tulip_head) {
                                        printk(version);
                                        tulip_head = dev;
@@ -1394,56 +1359,48 @@ int tulip_probe(struct device *dev)
                                                                                          PCI_LATENCY_TIMER, 100);
                                }
                                if (tulip_hwinit(dev, pci_ioaddr, pci_irq,
-                                                                pci_chips[cno]) < 0) continue;
-                               num ++;
-#ifdef MODULE
-                               return(0);
-#endif
+                                                                pci_chips[cno]) < 0) {
+                                       continue;
+                               }
+                               num++;
 #ifdef TULIP_MAX_CARDS
                                if (num >= TULIP_MAX_CARDS) return(0);
 #endif
                }
        }
+       }
        return(num > 0 ? 0: -ENODEV);
 }
 
 #ifdef MODULE
-#ifdef __alpha__
-#if 1
-static int io = 0xb000;
-#else
-static int io = 0x10400;
-#endif
-#else
-static int io = 0xfc80;
-#endif
 
-static struct device *mod_dev;
+/* The parameters that may be passed in... */
+/* This driver does nothing with options yet.  It will later be used to
+   pass the full-duplex flag, etc. */
+int debug = -1;
 
-int init_module(void)
+int
+init_module(void)
 {
-       if ((mod_dev = tulip_alloc(0)) == NULL) return(-EIO);
-
-       mod_dev->base_addr = io;
-       mod_dev->irq = 0;
-       mod_dev->init = &tulip_probe;
-
-       if (register_netdev(mod_dev)) {
-               printk("tulip: register_netdev() returned non-zero.\n");
-               kfree_s(mod_dev, alloc_size);
-               return -EIO;
-       }
-       return(0);
+       root_tulip_dev = NULL;
+       return tulip_probe(NULL);
 }
 
 void
 cleanup_module(void)
 {
-       release_region(mod_dev->base_addr, TULIP_TOTAL_SIZE);
-       unregister_netdev(mod_dev);
-       kfree_s(mod_dev, alloc_size);
+       struct device *next_dev;
+
+       /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+       while (root_tulip_dev) {
+               next_dev =
+                  ((struct tulip_private *) root_tulip_dev->priv)->next_module;
+               unregister_netdev(root_tulip_dev);
+               release_region(root_tulip_dev->base_addr, TULIP_TOTAL_SIZE);
+               kfree(root_tulip_dev);
+               root_tulip_dev = next_dev;
+       }
 }
-
 #endif /* MODULE */
 
 \f
index 723c34b31513690cc5525140ba716fc028a62054..149be377582134fe9a8a6ee0fc56a6e83e1276a4 100644 (file)
@@ -69,8 +69,8 @@ struct pci_dev_info dev_info[] = {
        DEVICE( DEC,            DEC_TULIP_FAST, "DC21140"),
        DEVICE( DEC,            DEC_FDDI,       "DEFPA"),
        DEVICE( DEC,            DEC_TULIP_PLUS, "DC21041"),
-       DEVICE( DEC,            DEC_21052_AB,   "DC21052-AB"),
-       DEVICE( DEC,            DEC_21152_AA,   "DC21152-AA"),
+       DEVICE( DEC,            DEC_21052,      "DC21052"),
+       DEVICE( DEC,            DEC_21152,      "DC21152"),
        DEVICE( CIRRUS,         CIRRUS_5430,    "GD 5430"),
        DEVICE( CIRRUS,         CIRRUS_5434_4,  "GD 5434"),
        DEVICE( CIRRUS,         CIRRUS_5434_8,  "GD 5434"),
@@ -87,7 +87,7 @@ struct pci_dev_info dev_info[] = {
        DEVICE( TRIDENT,        TRIDENT_9660,   "TG 9660"),
        DEVICE( AI,             AI_M1435,       "M1435"),
        DEVICE( MATROX,         MATROX_MGA_2,   "Atlas PX2085"),
-       DEVICE( MATROX,         MATROX_MIL     ,"Millenium"),
+       DEVICE( MATROX,         MATROX_MIL     ,"Millennium"),
        DEVICE( MATROX,         MATROX_MGA_IMP, "MGA Impression"),
        DEVICE( CT,             CT_65545,       "65545"),
        DEVICE( CT,             CT_65548,       "65548"),
@@ -210,7 +210,10 @@ struct pci_dev_info dev_info[] = {
        DEVICE( 3DLABS,         3DLABS_300SX,   "GLINT 300SX"),
        DEVICE( AVANCE,         AVANCE_2302,    "ALG-2302"),
        DEVICE( S3,             S3_ViRGE,       "ViRGE"),
-       DEVICE( S3,             S3_811,         "Trio32/Trio64"),
+       DEVICE( S3,             S3_TRIO,        "Trio32/Trio64"),
+       DEVICE( S3,             S3_AURORA64VP,  "Aurora64V+"),
+       DEVICE( S3,             S3_TRIO64UVP,   "Trio64UV+"),
+       DEVICE( S3,             S3_ViRGE_VX,    "ViRGE/VX"),
        DEVICE( S3,             S3_868, "Vision 868"),
        DEVICE( S3,             S3_928,         "Vision 928-P"),
        DEVICE( S3,             S3_864_1,       "Vision 864-P"),
index 424c73987a8595dda99d74d1d53415985144ebb8..3d78a4207e30de7d5f8f758be2e9aceb0b0ff23c 100644 (file)
@@ -26,7 +26,7 @@ dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
 dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI
 dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
 dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
-dep_tristate 'EATA ISA/EISA (DPT PM2011/021/012/022/122/322) support' CONFIG_SCSI_EATA $CONFIG_SCSI
+dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI
 dep_tristate 'Future Domain 16xx SCSI support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
 dep_tristate 'Generic NCR5380/53c400 SCSI support' CONFIG_SCSI_GENERIC_NCR5380 $CONFIG_SCSI
 if [ "$CONFIG_SCSI_GENERIC_NCR5380" != "n" ]; then
index c7f037b8d36211e8abce7dbe979325ce8c10e174..3659d6a2519e88a680b4cb457cea28f79be8ffe3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: advansys.c,v 1.20 1996/09/26 00:47:54 bobf Exp bobf $ */
+/* $Id: advansys.c,v 1.29 1996/11/15 00:45:07 bobf Exp bobf $ */
 /*
  * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters
  * 
  */
 
 /*
- * The driver has been run with the v1.2.13, v1.3.57, and v2.0.21 kernels.
+ * The driver has been used in the following kernels:
+ *  v1.2.13, v1.3.57, v2.0.25, v2.1.9
  */
-#define ASC_VERSION "1.7"    /* AdvanSys Driver Version */
+#define ASC_VERSION "2.0"    /* AdvanSys Driver Version */
 
 /*
 
 
      Connectivity Products:
         ABP510/5150 - Bus-Master ISA (240 CDB) (Footnote 1)
-        ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1)
-        ABP5142 - Bus-Master ISA PnP with floppy (16 CDB)
+        ABP5140 - Bus-Master ISA PnP (16 CDB) (Footnote 1, 3)
+        ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) (Footnote 4)
         ABP920 - Bus-Master PCI (16 CDB)
-        ABP930 - Bus-Master PCI (16 CDB)
+        ABP930 - Bus-Master PCI (16 CDB) (Footnote 5)
         ABP930U - Bus-Master PCI Ultra (16 CDB)
         ABP960 - Bus-Master PCI MAC/PC (16 CDB) (Footnote 2)
         ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB)
        1. This board has been shipped by HP with the 4020i CD-R drive.
           The board has no BIOS so it cannot control a boot device, but
           it can control any secondary SCSI device.
-   
        2. This board has been sold by Iomega as a Jaz Jet PCI adapter.
-  
+       3. This board has been sold by SIIG as the i540 SpeedMaster.
+       4. This board has been sold by SIIG as the i542 SpeedMaster.
+       5. This board has been sold by SIIG as the Fast SCSI Pro PCI.
+
   B. Linux v1.2.X - Directions for Adding the AdvanSys Driver
 
      These directions apply to v1.2.13. For versions that follow v1.2.13.
          5. Remove the request timeout issue form the driver issues list.
          6. Miscellaneous documentation additions and changes.
 
+     1.8 (10/4/96):
+         1. Make changes to handle the new v2.1.0 kernel memory mapping
+            in which a kernel virtual address may not be equivalent to its
+            bus or DMA memory address.
+         2. Change abort and reset request handling to make it yet even
+            more robust.
+         3. Try to mitigate request starvation by sending ordered requests
+            to heavily loaded, tag queuing enabled devices.
+         4. Maintain statistics on request response time.
+         5. Add request response time statistics and other information to
+            the adapter /proc file: /proc/scsi/advansys[0...].
+
+     1.9 (10/21/96):
+         1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to
+            make use of mid-level SCSI driver device queue depth flow
+            control mechanism. This will eliminate aborts caused by a
+            device being unable to keep up with requests and eliminate
+            repeat busy or QUEUE FULL status returned by a device.
+         2. Incorporate miscellaneous Asc Library bug fixes.
+         3. To allow the driver to work in kernels with broken module
+            support set 'cmd_per_lun' if the driver is compile as a
+            module. This change affects kernels v1.3.89 to present.
+         4. Remove PCI BIOS address from the driver banner. The PCI BIOS
+            is relocated by the motherboard BIOS and its new address can
+            not be determined by the driver.
+         5. Add mid-level SCSI queue depth information to the adapter
+            /proc file: /proc/scsi/advansys[0...].
+
+     2.0 (11/14/96):
+         1. Change allocation of global structures used for device
+            initialization to guarantee they are in DMA-able memory.
+            Previously when the driver was loaded as a module these
+            structures might not have been in DMA-able memory, causing
+            device initialization to fail.
+
   I. Known Problems or Issues
 
-         None
+         1. Remove conditional constants (ASC_QUEUE_FLOW_CONTROL) around
+            the queue depth flow control code when mid-level SCSI changes
+            are included in Linux.
 
   J. Credits
 
 
 #define ASC_LIB_VERSION_MAJOR  1
 #define ASC_LIB_VERSION_MINOR  22
-#define ASC_LIB_SERIAL_NUMBER  89
+#define ASC_LIB_SERIAL_NUMBER  91
 
 typedef unsigned char uchar;
 
@@ -615,7 +655,6 @@ typedef unsigned char uchar;
 #define ASC_PCI_ID2FUNC( id )   (((id) >> 8) & 0x7)
 #define ASC_PCI_MKID( bus, dev, func ) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF))
 
-#define  Asc_DvcLib_Status   int
 #define  ASC_DVCLIB_CALL_DONE     (1)
 #define  ASC_DVCLIB_CALL_FAILED   (0)
 #define  ASC_DVCLIB_CALL_ERROR    (-1)
@@ -823,7 +862,7 @@ AscMemWordCopyToLram(iop_base, s_addr, outbuf, words)
 #define SCSI_SENKEY_MEDIUM_ERR    0x03
 #define SCSI_SENKEY_HW_ERR        0x04
 #define SCSI_SENKEY_ILLEGAL       0x05
-#define SCSI_SENKEY_ATTENSION     0x06
+#define SCSI_SENKEY_ATTENTION     0x06
 #define SCSI_SENKEY_PROTECTED     0x07
 #define SCSI_SENKEY_BLANK         0x08
 #define SCSI_SENKEY_V_UNIQUE      0x09
@@ -1349,7 +1388,6 @@ typedef struct asc_risc_sg_list_q {
 #define ASC_IERR_SCAM                 0x0800
 #define ASC_IERR_SET_SDTR             0x1000
 #define ASC_IERR_RW_LRAM              0x8000
-#define ASC_DVCLIB_STATUS             0x00
 #define ASC_DEF_IRQ_NO  10
 #define ASC_MAX_IRQ_NO  15
 #define ASC_MIN_IRQ_NO  10
@@ -2108,7 +2146,7 @@ int                 AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SA
 #define ASC_INFO_SIZE                  128                     /* advansys_info() line size */
 
 /* /proc/scsi/advansys/[0...] related definitions */
-#define ASC_PRTBUF_SIZE                        1024
+#define ASC_PRTBUF_SIZE                        2048
 #define ASC_PRTLINE_SIZE               160
 
 #define ASC_PRT_NEXT() \
@@ -2137,15 +2175,52 @@ int                 AscRestoreNewMicroCode(ASC_DVC_VAR asc_ptr_type *, ASC_MC_SA
 #define DRIVER_BYTE(byte)      ((byte) << 24)
 
 /*
- * REQ and REQP are the generic name for a SCSI request block and pointer.
- * REQPTID(reqp) returns reqp's target id.
- * REQPNEXT(reqp) returns reqp's next pointer.
- * REQPNEXTP(reqp) returns a pointer to reqp's next pointer.
+ * The following definitions and macros are OS independent interfaces to
+ * the queue functions:
+ *  REQ - SCSI request structure
+ *  REQP - pointer to SCSI request structure
+ *  REQPTID(reqp) - reqp's target id
+ *  REQPNEXT(reqp) - reqp's next pointer
+ *  REQPNEXTP(reqp) - pointer to reqp's next pointer
+ *  REQPTIME(reqp) - reqp's time stamp value
+ *  REQTIMESTAMP() - system time stamp value
  */
 typedef Scsi_Cmnd                      REQ, *REQP;
 #define REQPNEXT(reqp)         ((REQP) ((reqp)->host_scribble))
 #define REQPNEXTP(reqp)                ((REQP *) &((reqp)->host_scribble))
 #define REQPTID(reqp)          ((reqp)->target)
+#define REQPTIME(reqp)         ((reqp)->SCp.this_residual)
+#define REQTIMESTAMP()         (jiffies)
+
+#define REQTIMESTAT(function, ascq, reqp, tid) \
+{ \
+       /*
+        * If the request time stamp is less than the system time stamp, then \
+        * maybe the system time stamp wrapped. Set the request time to zero.\
+        */ \
+       if (REQPTIME(reqp) <= REQTIMESTAMP()) { \
+               REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \
+       } else { \
+               /* Indicate an error occurred with the assertion. */ \
+               ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \
+               REQPTIME(reqp) = 0; \
+       } \
+       /* Handle first minimum time case without external initialization. */ \
+       if (((ascq)->q_tot_cnt[tid] == 1) ||  \
+               (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \
+                       (ascq)->q_min_tim[tid] = REQPTIME(reqp); \
+                       ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \
+                               (function), (tid), (ascq)->q_min_tim[tid]); \
+               } \
+       if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \
+               (ascq)->q_max_tim[tid] = REQPTIME(reqp); \
+               ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \
+                       (function), tid, (ascq)->q_max_tim[tid]); \
+       } \
+       (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \
+       /* Reset the time stamp field. */ \
+       REQPTIME(reqp) = 0; \
+}
 
 /* asc_enqueue() flags */
 #define ASC_FRONT              1
@@ -2243,7 +2318,11 @@ typedef Scsi_Cmnd                        REQ, *REQP;
 #endif /* ADVANSYS_STATS */
 
 #define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit))
-#define ASC_TENTHS(num, den) ((((num) * 10)/(den)) - (10 * ((num)/(den))))
+
+/* If the result wraps when calculating tenths, return 0. */
+#define ASC_TENTHS(num, den) \
+       (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \
+       0 : ((((num) * 10)/(den)) - (10 * ((num)/(den)))))
 
 /*
  * Display a message to the console.
@@ -2287,8 +2366,7 @@ typedef Scsi_Cmnd                 REQ, *REQP;
 #define        ASC_DBG3(lvl, s, a1, a2, a3)
 #define        ASC_DBG4(lvl, s, a1, a2, a3, a4)
 #define        ASC_DBG_PRT_SCSI_HOST(lvl, s)
-#define        ASC_DBG_PRT_DVC_VAR(lvl, v)
-#define        ASC_DBG_PRT_DVC_CFG(lvl, c)
+#define        ASC_DBG_PRT_SCSI_CMND(lvl, s)
 #define        ASC_DBG_PRT_SCSI_Q(lvl, scsiqp)
 #define        ASC_DBG_PRT_QDONE_INFO(lvl, qdone)
 #define        ASC_DBG_PRT_HEX(lvl, name, start, length)
@@ -2348,17 +2426,10 @@ typedef Scsi_Cmnd                       REQ, *REQP;
                } \
        }
 
-#define        ASC_DBG_PRT_DVC_VAR(lvl, v) \
+#define        ASC_DBG_PRT_SCSI_CMND(lvl, s) \
        { \
                if (asc_dbglvl >= (lvl)) { \
-                       asc_prt_dvc_var(v); \
-               } \
-       }
-
-#define        ASC_DBG_PRT_DVC_CFG(lvl, c) \
-       { \
-               if (asc_dbglvl >= (lvl)) { \
-                       asc_prt_dvc_cfg(c); \
+                       asc_prt_scsi_cmnd(s); \
                } \
        }
 
@@ -2431,9 +2502,6 @@ struct asc_stats {
        ulong   sg_cnt;                 /* # scatter-gather I/O requests received */
        ulong   sg_elem;                /* # scatter-gather elements */
        ulong   sg_xfer;                /* # scatter-gather transfer 512-bytes */
-       /* Device SCSI Command Queuing Statistics */
-       ASC_SCSI_BIT_ID_TYPE queue_full;
-       ushort  queue_full_cnt[ASC_MAX_TID+1];
 };
 #endif /* ADVANSYS_STATS */
 
@@ -2447,6 +2515,10 @@ typedef struct asc_queue {
 #ifdef ADVANSYS_STATS
        short                                   q_cur_cnt[ASC_MAX_TID+1]; /* current queue count */
        short                                   q_max_cnt[ASC_MAX_TID+1]; /* maximum queue count */
+       ulong                                   q_tot_cnt[ASC_MAX_TID+1]; /* total enqueue count */
+       ulong                                   q_tot_tim[ASC_MAX_TID+1]; /* total time queued */
+       ushort                                  q_max_tim[ASC_MAX_TID+1]; /* maximum time queued */
+       ushort                                  q_min_tim[ASC_MAX_TID+1]; /* minimum time queued */
 #endif /* ADVANSYS_STATS */
 } asc_queue_t;
 
@@ -2464,10 +2536,21 @@ typedef struct asc_board {
        ASC_DVC_CFG                      asc_dvc_cfg;           /* Device configuration */
        asc_queue_t                      active;                        /* Active command queue */
        asc_queue_t                      waiting;                       /* Waiting command queue */
+       asc_queue_t                      done;                          /* Done command queue */
        ASC_SCSI_BIT_ID_TYPE init_tidmask;              /* Target initialized mask */
+       /* The following three structures must be in DMA-able memory. */
+       ASC_SCSI_REQ_Q           scsireqq;
+       ASC_CAP_INFO             cap_info;
+       ASC_SCSI_INQUIRY         inquiry;
+       Scsi_Device                      *device[ASC_MAX_TID+1]; /* Mid-Level Scsi Device */
+       ushort                           reqcnt[ASC_MAX_TID+1]; /* Starvation request count */
+#if ASC_QUEUE_FLOW_CONTROL
+       ushort                           nerrcnt[ASC_MAX_TID+1]; /* No error request count */
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+       ASC_SCSI_BIT_ID_TYPE queue_full;                /* Queue full mask */
+       ushort  queue_full_cnt[ASC_MAX_TID+1];  /* Queue full count */
        ASCEEP_CONFIG            eep_config;            /* EEPROM configuration */
-       asc_queue_t                      scsi_done_q;           /* Completion command queue */
-       ulong                            reset_jiffies;         /* Saved time of last reset */
+       ulong                            last_reset;            /* Saved time of last reset */
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
        /* /proc/scsi/advansys/[0...] */
        char                             *prtbuf;                       /* Statistics Print Buffer */
@@ -2551,13 +2634,6 @@ STATIC struct Scsi_Host  *asc_host[ASC_NUM_BOARD_SUPPORTED] = { 0 };
 /* Overrun buffer shared between all boards. */
 STATIC uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 };
 
-/*
- * Global structures used for device initialization.
- */
-STATIC ASC_SCSI_REQ_Q   asc_scsireqq = { { 0 } };
-STATIC ASC_CAP_INFO             asc_cap_info = { 0 };
-STATIC ASC_SCSI_INQUIRY         asc_inquiry = { { 0 } };
-
 /*
  * Global structures required to issue a command.
  */
@@ -2646,6 +2722,7 @@ STATIC int                        asc_prt_board_stats(struct Scsi_Host *, char *, int);
 #endif /* ADVANSYS_STATS */
 #ifdef ADVANSYS_DEBUG
 STATIC void            asc_prt_scsi_host(struct Scsi_Host *);
+STATIC void            asc_prt_scsi_cmnd(Scsi_Cmnd *);
 STATIC void            asc_prt_dvc_cfg(ASC_DVC_CFG *);
 STATIC void            asc_prt_dvc_var(ASC_DVC_VAR *);
 STATIC void            asc_prt_scsi_q(ASC_SCSI_Q *);
@@ -3059,6 +3136,7 @@ advansys_detect(Scsi_Host_Template *tpnt)
                        memset(boardp, 0, sizeof(asc_board_t));
                        boardp->id = asc_board_count - 1;
                        asc_dvc_varp = &boardp->asc_dvc_var;
+                       asc_dvc_varp->drv_ptr = (ulong) boardp;
                        asc_dvc_varp->cfg = &boardp->asc_dvc_cfg;
                        asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0];
                        asc_dvc_varp->iop_base = iop;
@@ -3114,9 +3192,9 @@ advansys_detect(Scsi_Host_Template *tpnt)
                        /*
                         * Get the board configuration.
                         *
-                        * AscInitGetConfig() may change the board's bus_type value.
-                        * The asc_bus[bus] value should no longer be used. If the
-                        * bus_type field must be referenced only use the bit-wise
+                        * NOTE: AscInitGetConfig() may change the board's bus_type
+                        * value. The asc_bus[bus] value should no longer be used. If
+                        * the bus_type field must be referenced only use the bit-wise
                         * AND operator "&".
                         */
                        ASC_DBG(2, "advansys_detect: AscInitGetConfig()\n");
@@ -3247,7 +3325,7 @@ advansys_detect(Scsi_Host_Template *tpnt)
                         */
 
                        /* AscInitSetConfig() will set the IRQ for non-PCI boards. */
-                       if (asc_dvc_varp->bus_type != ASC_IS_PCI) {
+                       if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) {
                                shp->irq = asc_dvc_varp->irq_no;
                        }
 
@@ -3286,16 +3364,33 @@ advansys_detect(Scsi_Host_Template *tpnt)
                         */
                        shp->select_queue_depths = advansys_select_queue_depths;
 
-                       shp->cmd_per_lun = 0; /* 'cmd_per_lun' is no longer used. */
+#ifdef MODULE
+                       /*
+                        * Following v1.3.89, 'cmd_per_lun' is no longer needed
+                        * and should be set to zero. But because of a bug introduced
+                        * in v1.3.89 if the driver is compiled as a module and
+                        * 'cmd_per_lun' is zero, the Mid-Level SCSI function
+                        * 'allocate_device' will panic. To allow the driver to
+                        * work as a module in these kernels set 'cmd_per_lun' to 1.
+                        */
+                       shp->cmd_per_lun = 1;
+#else /* MODULE */
+                       shp->cmd_per_lun = 0;
+#endif /* MODULE */
 #endif /* version >= v1.3.89 */
 
                        /*
-                        * Maximum number of scatter-gather elements adapter can handle.
-                        *
-                        * Set a conservative 'sg_tablesize' value to prevent memory
-                        * allocation failures.
+                        * Set the maximum number of scatter-gather elements adapter
+                        * can handle.
                         */
+
 #ifdef MODULE
+                       /*
+                        * If the driver is compiled as a module, set a conservative
+                        * 'sg_tablesize' value to prevent memory allocation failures.
+                        * Memory allocation errors are more likely to occur at module
+                        * load time, then at driver initialization time.
+                        */
                        shp->sg_tablesize = 8;
 #else /* MODULE */
                        /*
@@ -3474,25 +3569,28 @@ advansys_info(struct Scsi_Host *shp)
                        ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
                        (unsigned) shp->base, shp->io_port,
                        shp->io_port + (shp->n_io_port - 1), shp->irq, shp->dma_channel);
+       } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
+               if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
+                       == ASC_IS_PCI_ULTRA) {
+                       busname = "PCI Ultra";
+               } else {
+                       busname = "PCI";
+               }
+               sprintf(info,
+                       "AdvanSys SCSI %s: %s %u CDB: IO %X-%X, IRQ %u",
+                       ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
+                       shp->io_port, shp->io_port + (shp->n_io_port - 1), shp->irq);
        } else {
                if (asc_dvc_varp->bus_type & ASC_IS_VL) {
                        busname = "VL";
                } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) {
                        busname = "EISA";
-               } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) {
-                       if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA)
-                               == ASC_IS_PCI_ULTRA) {
-                               busname = "PCI Ultra";
-                       } else {
-                               busname = "PCI";
-                       }
                } else {
                        busname = "?";
                        ASC_PRINT2(
 "advansys_info: board %d: unknown bus type %d\n",
                                boardp->id, asc_dvc_varp->bus_type);
                }
-               /* No DMA channel for non-ISA busses. */
                sprintf(info,
                        "AdvanSys SCSI %s: %s %u CDB: BIOS %X, IO %X-%X, IRQ %u",
                        ASC_VERSION, busname, boardp->asc_dvc_var.max_total_qng,
@@ -3512,7 +3610,9 @@ advansys_info(struct Scsi_Host *shp)
  * Polled-I/O. Apparently host drivers shouldn't return until
  * command is finished.
  *
- * XXX - Can host drivers block here instead of spinning on command status?
+ * Note: This is an old interface that is no longer used by the SCSI
+ * mid-level driver. The new interface, advansys_queuecommand(),
+ * currently handles all requests.
  */
 int
 advansys_command(Scsi_Cmnd *scp)
@@ -3521,6 +3621,10 @@ advansys_command(Scsi_Cmnd *scp)
        ASC_STATS(scp->host, command);
        scp->SCp.Status = 0; /* Set to a known state */
        advansys_queuecommand(scp, advansys_command_done);
+       /*
+        * XXX - Can host drivers block here instead of spinning on
+        * command status?
+        */
        while (scp->SCp.Status == 0) {
                continue;
        }
@@ -3571,11 +3675,11 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
                }
 
                /*
-                * Add blocked requests to the board's 'scsi_done_q'. The queued
+                * Add blocked requests to the board's 'done' queue. The queued
                 * requests will be completed at the end of the abort or reset
                 * handling.
                 */
-               asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+               asc_enqueue(&boardp->done, scp, ASC_BACK);
                restore_flags(flags);
                return 0;
        }
@@ -3601,7 +3705,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
         * target waiting list.
         * 
         * If an error occurred, the request will have been placed on the
-        * board's 'scsi_done_q' and must be completed before returning.
+        * board's 'done' queue and must be completed before returning.
         */
        scp->scsi_done = done;
        switch (asc_execute_scsi_cmnd(scp)) {
@@ -3612,7 +3716,7 @@ advansys_queuecommand(Scsi_Cmnd *scp, void (*done)(Scsi_Cmnd *))
                break;
        case ASC_ERROR:
        default:
-               done_scp = asc_dequeue_list(&boardp->scsi_done_q, NULL, ASC_TID_ALL);
+               done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
                /* Interrupts could be enabled here. */
                asc_scsi_done_list(done_scp);
                break;
@@ -3634,42 +3738,63 @@ advansys_abort(Scsi_Cmnd *scp)
        asc_board_t                     *boardp;
        ASC_DVC_VAR                     *asc_dvc_varp;
        int                                     flags;
-       int                                     status = ASC_FALSE;
-       int                                     abort_do_done = ASC_FALSE;
-       Scsi_Cmnd                       *done_scp;
-       int                                     ret = ASC_ERROR;
-
-       ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
+       int                                     do_scsi_done;
+       int                                     scp_found;
+       Scsi_Cmnd                       *done_scp = NULL;
+       int                                     ret;
 
        /* Save current flags and disable interrupts. */
        save_flags(flags);
        cli();
 
+       ASC_DBG1(1, "advansys_abort: scp %x\n", (unsigned) scp);
+
 #ifdef ADVANSYS_STATS
        if (scp->host != NULL) {
                ASC_STATS(scp->host, abort);
        }       
 #endif /* ADVANSYS_STATS */
 
+#ifdef ADVVANSYS_DEBUG
+       do_scsi_done = ASC_ERROR;
+       scp_found = ASC_ERROR;
+       ret = ASC_ERROR;
+#endif /* ADVANSYS_DEBUG */
+
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
        if (scp->serial_number != scp->serial_number_at_timeout) {
+               ASC_PRINT1(
+"advansys_abort: timeout serial number changed for request %x\n",
+                       (unsigned) scp);
+               do_scsi_done = ASC_FALSE;
+               scp_found = ASC_FALSE;
                ret = SCSI_ABORT_NOT_RUNNING;
        } else
 #endif /* version >= v1.3.89 */
        if ((shp = scp->host) == NULL) {
                scp->result = HOST_BYTE(DID_ERROR);
+               do_scsi_done = ASC_TRUE;
+               scp_found = ASC_FALSE;
                ret = SCSI_ABORT_ERROR;
        } else if ((boardp = ASC_BOARDP(shp))->flags & 
                                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
                ASC_PRINT2(
 "advansys_abort: board %d: Nested host reset or abort, flags 0x%x\n",
                        boardp->id, boardp->flags);
+               do_scsi_done = ASC_TRUE;
+               if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+                   (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
+               }
                scp->result = HOST_BYTE(DID_ERROR);
                ret = SCSI_ABORT_ERROR;
        } else {
                /* Set abort flag to avoid nested reset or abort requests. */
                boardp->flags |= ASC_HOST_IN_ABORT;
 
+               do_scsi_done = ASC_TRUE;
                if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
                        /*
                         * If asc_rmqueue() found the command on the waiting
@@ -3678,6 +3803,7 @@ advansys_abort(Scsi_Cmnd *scp)
                         */
                        ASC_DBG1(1, "advansys_abort: scp %x found on waiting queue\n",
                                (unsigned) scp);
+                       scp_found = ASC_TRUE;
                        scp->result = HOST_BYTE(DID_ABORT);
                        ret = SCSI_ABORT_SUCCESS;
                } else if (asc_isqueued(&boardp->active, scp) == ASC_TRUE) {
@@ -3693,7 +3819,7 @@ advansys_abort(Scsi_Cmnd *scp)
                        sti(); /* Enable interrupts for AscAbortSRB(). */
                        ASC_DBG1(1, "advansys_abort: before AscAbortSRB(), scp %x\n",
                                (unsigned) scp);
-                       switch (status = AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
+                       switch (AscAbortSRB(asc_dvc_varp, (ulong) scp)) {
                        case ASC_TRUE:
                                /* asc_isr_callback() will be called */
                                ASC_DBG(1, "advansys_abort: AscAbortSRB() TRUE\n");
@@ -3713,20 +3839,23 @@ advansys_abort(Scsi_Cmnd *scp)
                        cli();
 
                        /*
-                        * If the abort failed, remove the request from the
-                        * active list and complete it.
+                        * The request will either still be on the active queue
+                        * or have been added to the board's done queue.
                         */
-                       if (status != ASC_TRUE) {
-                               if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
-                                       scp->result = HOST_BYTE(DID_ABORT);
-                                       abort_do_done = ASC_TRUE;
-                               }
+                       if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
+                               scp->result = HOST_BYTE(DID_ABORT);
+                               scp_found = ASC_TRUE;
+                       } else {
+                               scp_found = asc_rmqueue(&boardp->done, scp);
+                               ASC_ASSERT(scp_found == ASC_TRUE);
                        }
 
                } else {
                        /*
                         * The command was not found on the active or waiting queues.
                         */
+                       do_scsi_done = ASC_TRUE;
+                       scp_found = ASC_FALSE;
                        ret = SCSI_ABORT_NOT_RUNNING;
                }
 
@@ -3736,11 +3865,11 @@ advansys_abort(Scsi_Cmnd *scp)
                /*
                 * Because the ASC_HOST_IN_ABORT flag causes both
                 * 'advansys_interrupt' and 'asc_isr_callback' to
-                * queue requests to the board's 'scsi_done_q' and
+                * queue requests to the board's 'done' queue and
                 * prevents waiting commands from being executed,
                 * these queued requests must be handled here.
                 */
-               done_scp = asc_dequeue_list(&boardp->scsi_done_q, NULL, ASC_TID_ALL);
+               done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL);
 
                /*
                 * Start any waiting commands for the board.
@@ -3749,22 +3878,39 @@ advansys_abort(Scsi_Cmnd *scp)
                        ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
                        asc_execute_queue(&boardp->waiting);
                }
+       }
 
-               /* Interrupts could be enabled here. */
+       /* Interrupts could be enabled here. */
 
-               /*
-                * If needed, complete the aborted request.
-                */
-               if (abort_do_done == ASC_TRUE) {
+       /*
+        * Complete the request to be aborted, unless it has been
+        * restarted as detected above, even if it was not found on
+        * the device active or waiting queues.
+        */
+       ASC_ASSERT(do_scsi_done != ASC_ERROR);
+       ASC_ASSERT(scp_found != ASC_ERROR);
+       if (do_scsi_done == ASC_TRUE) {
+               if (scp->scsi_done == NULL) {
+                       ASC_PRINT1(
+"advansys_abort: aborted request scsi_done() is NULL, %x\n",
+                               (unsigned) scp);
+               } else {
+                       if (scp_found == ASC_FALSE) {
+                               ASC_PRINT1(
+"advansys_abort: abort request not active or waiting, completing anyway %x\n",
+                                       (unsigned) scp);
+                       }
                        ASC_STATS(scp->host, done);
                        scp->scsi_done(scp);
                }
+       }
 
-               /*
-                * It is possible for the request done function to re-enable
-                * interrupts without confusing the driver. But here interrupts
-                * aren't enabled until all requests have been completed.
-                */
+       /*
+        * It is possible for the request done function to re-enable
+        * interrupts without confusing the driver. But here interrupts
+        * aren't enabled until all requests have been completed.
+        */
+       if (done_scp != NULL) {
                asc_scsi_done_list(done_scp);
        }
 
@@ -3795,18 +3941,18 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
        int                                     flags;
        Scsi_Cmnd                       *done_scp = NULL, *last_scp = NULL;
        Scsi_Cmnd                       *tscp, *new_last_scp;
-       int                                     scp_found = ASC_FALSE;
-       int                             device_reset = ASC_FALSE;
+       int                                     do_scsi_done;
+       int                                     scp_found;
        int                                     status;
        int                                     target;
-       int                                     ret = ASC_ERROR;
-
-       ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
+       int                                     ret;
 
        /* Save current flags and disable interrupts. */
        save_flags(flags);
        cli();
 
+       ASC_DBG1(1, "advansys_reset: %x\n", (unsigned) scp);
+
 #ifdef ADVANSYS_STATS
        if (scp->host != NULL) {
                ASC_STATS(scp->host, reset);
@@ -3815,21 +3961,35 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
 
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
        if (scp->serial_number != scp->serial_number_at_timeout) {
+               ASC_PRINT1(
+"advansys_reset: timeout serial number changed for request %x\n",
+                       (unsigned) scp);
+               do_scsi_done = ASC_FALSE;
+               scp_found = ASC_FALSE;
                ret = SCSI_RESET_NOT_RUNNING;
        } else
 #endif /* version >= v1.3.89 */
        if ((shp = scp->host) == NULL) {
                scp->result = HOST_BYTE(DID_ERROR);
+               do_scsi_done = ASC_TRUE;
+               scp_found = ASC_FALSE;
                ret = SCSI_RESET_ERROR;
        } else if ((boardp = ASC_BOARDP(shp))->flags & 
                                (ASC_HOST_IN_RESET | ASC_HOST_IN_ABORT)) {
                ASC_PRINT2(
 "advansys_reset: board %d: Nested host reset or abort, flags 0x%x\n",
                        boardp->id, boardp->flags);
+               do_scsi_done = ASC_TRUE;
+               if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+                   (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
+               }
                scp->result = HOST_BYTE(DID_ERROR);
                ret = SCSI_RESET_ERROR;
-       } else if (jiffies >= boardp->reset_jiffies &&
-                          jiffies < (boardp->reset_jiffies + (10 * HZ))) {
+       } else if (jiffies >= boardp->last_reset &&
+                          jiffies < (boardp->last_reset + (10 * HZ))) {
                /*
                 * Don't allow a reset to be attempted within 10 seconds
                 * of the last reset.
@@ -3840,15 +4000,27 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                 */
                ASC_DBG(1,
                        "advansys_reset: reset within 10 sec of last reset ignored\n");
+               do_scsi_done = ASC_TRUE;
+               if ((asc_rmqueue(&boardp->active, scp) == ASC_TRUE) ||
+                   (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE)) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
+               }
                scp->result = HOST_BYTE(DID_ERROR);
                ret = SCSI_RESET_ERROR;
        } else {
+               int device_reset = ASC_FALSE;
+
+               do_scsi_done = ASC_TRUE;
+
                /* Set reset flag to avoid nested reset or abort requests. */
                boardp->flags |= ASC_HOST_IN_RESET;
 
                /*
-                * If the request is on the target waiting or active queue,
-                * note that it was found and remove it from its queue.
+                * If the request is on the target waiting or active queue
+                * or the board done queue, then remove it and note that it
+                * was found.
                 */
                if (asc_rmqueue(&boardp->active, scp) == ASC_TRUE) {
                        ASC_DBG(1, "advansys_reset: active scp_found = TRUE\n");
@@ -3856,6 +4028,10 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                } else if (asc_rmqueue(&boardp->waiting, scp) == ASC_TRUE) {
                        ASC_DBG(1, "advansys_reset: waiting scp_found = TRUE\n");
                        scp_found = ASC_TRUE;
+               } else if (asc_rmqueue(&boardp->done, scp) == ASC_TRUE) {
+                       scp_found = ASC_TRUE;
+               } else {
+                       scp_found = ASC_FALSE;
                }
 
                /*
@@ -3939,11 +4115,11 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                /*
                 * Because the ASC_HOST_IN_RESET flag causes both
                 * 'advansys_interrupt' and 'asc_isr_callback' to
-                * queue requests to the board's 'scsi_done_q' and
+                * queue requests to the board's 'done' queue and
                 * prevents waiting commands from being executed,
                 * these queued requests must be handled here.
                 */
-               done_scp = asc_dequeue_list(&boardp->scsi_done_q, &last_scp,
+               done_scp = asc_dequeue_list(&boardp->done, &last_scp,
                                                                        ASC_TID_ALL);
 
                /*
@@ -4006,7 +4182,7 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                }
 
                /* Save the time of the most recently completed reset. */
-               boardp->reset_jiffies = jiffies;
+               boardp->last_reset = jiffies;
 
                /* Clear reset flag. */
                boardp->flags &= ~ASC_HOST_IN_RESET;
@@ -4018,34 +4194,35 @@ advansys_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
                        ASC_DBG(1, "advansys_interrupt: before asc_execute_queue()\n");
                        asc_execute_queue(&boardp->waiting);
                }
+               ret = SCSI_RESET_SUCCESS;
+       }
 
-               /* Interrupts could be enabled here. */
+       /* Interrupts could be enabled here. */
 
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
-               /*
-                * If the command was found on the active or waiting request
-                * queues or if the the SCSI_RESET_SYNCHRONOUS flag is set,
-                * then done the command now.
-                */
-               if (scp_found == ASC_TRUE || (reset_flags & SCSI_RESET_SYNCHRONOUS)) {
-                       scp->result = HOST_BYTE(DID_RESET);
-                       ASC_STATS(scp->host, done);
-                       scp->scsi_done(scp);
-               }
-#else /* version >= v1.3.89 */
-               if (scp_found == ASC_TRUE) {
-                       scp->result = HOST_BYTE(DID_RESET);
+       ASC_ASSERT(do_scsi_done != ASC_ERROR);
+       ASC_ASSERT(scp_found != ASC_ERROR);
+       if (do_scsi_done == ASC_TRUE) {
+               if (scp->scsi_done == NULL) {
+                       ASC_PRINT1(
+"advansys_reset: reset request scsi_done() is NULL, %x\n",
+                               (unsigned) scp);
+               } else {
+                       if (scp_found == ASC_FALSE) {
+                               ASC_PRINT1(
+"advansys_reset: reset request not active or waiting, completing anyway %x\n",
+                                       (unsigned) scp);
+                       }
                        ASC_STATS(scp->host, done);
                        scp->scsi_done(scp);
                }
-#endif /* version >= v1.3.89 */
-               ret = SCSI_RESET_SUCCESS;
+       }
 
-               /*
-                * It is possible for the request done function to re-enable
-                * interrupts without confusing the driver. But here interrupts
-                * aren't enabled until requests have been completed.
-                */
+       /*
+        * It is possible for the request done function to re-enable
+        * interrupts without confusing the driver. But here interrupts
+        * aren't enabled until requests have been completed.
+        */
+       if (done_scp != NULL) {
                asc_scsi_done_list(done_scp);
        }
 
@@ -4239,11 +4416,11 @@ advansys_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                         * Add to the list of requests that must be completed.
                         */
                        if (done_scp == NULL) {
-                               done_scp = asc_dequeue_list(&boardp->scsi_done_q, &last_scp,
+                               done_scp = asc_dequeue_list(&boardp->done, &last_scp,
                                        ASC_TID_ALL);
                        } else {
                                ASC_ASSERT(last_scp != NULL);
-                               REQPNEXT(last_scp) = asc_dequeue_list(&boardp->scsi_done_q,
+                               REQPNEXT(last_scp) = asc_dequeue_list(&boardp->done,
                                        &new_last_scp, ASC_TID_ALL);
                                if (new_last_scp != NULL) {
                                        ASC_ASSERT(REQPNEXT(last_scp) != NULL);
@@ -4285,6 +4462,11 @@ advansys_select_queue_depths(struct Scsi_Host *shp, Scsi_Device *devicelist)
                if (device->host != shp) {
                        continue;
                }
+               /*
+                * Save a pointer to the device and set its initial/maximum
+                * queue depth.
+                */
+               boardp->device[device->id] = device;
                device->queue_depth = boardp->asc_dvc_var.max_dvc_qng[device->id];
                ASC_DBG3(1, "advansys_select_queue_depths: shp %x, id %d, depth %d\n",
                        (unsigned) shp, device->id, device->queue_depth);
@@ -4318,6 +4500,7 @@ asc_scsi_done_list(Scsi_Cmnd *scp)
                tscp = REQPNEXT(scp);
                REQPNEXT(scp) = NULL;
                ASC_STATS(scp->host, done);
+               ASC_ASSERT(scp->scsi_done != NULL);
                scp->scsi_done(scp);
                scp = tscp;
        }
@@ -4360,7 +4543,7 @@ asc_scsi_done_list(Scsi_Cmnd *scp)
  *     host_scribble - used for pointer to another Scsi_Cmnd
  *
  * If this function returns ASC_NOERROR or ASC_ERROR the request
- * has been enqueued on the board's 'scsi_done_q' and must be
+ * has been enqueued on the board's 'done' queue and must be
  * completed by the caller.
  *
  * If ASC_BUSY is returned the request must be enqueued by the
@@ -4371,6 +4554,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 {
        asc_board_t             *boardp;
        ASC_DVC_VAR             *asc_dvc_varp;
+       Scsi_Device             *device;
        int                             ret;
 
        ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
@@ -4379,6 +4563,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 
        boardp = ASC_BOARDP(scp->host);
        asc_dvc_varp = &boardp->asc_dvc_var;
+       device = boardp->device[scp->target];
 
        /*
         * If this is the first command, then initialize the device. If
@@ -4387,7 +4572,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
        if ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(scp->target)) == 0) {
                if (asc_init_dev(asc_dvc_varp, scp) == ASC_FALSE) {
                        scp->result = HOST_BYTE(DID_BAD_TARGET);
-                       asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+                       asc_enqueue(&boardp->done, scp, ASC_BACK);
                        return ASC_ERROR;
                }
                boardp->init_tidmask |= ASC_TIX_TO_TARGET_ID(scp->target);
@@ -4412,9 +4597,30 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
        asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
        asc_scsi_q.q1.target_lun = scp->lun;
        asc_scsi_q.q2.target_ix = ASC_TIDLUN_TO_IX(scp->target, scp->lun);
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
        asc_scsi_q.q1.sense_addr = (ulong) &scp->sense_buffer[0];
+#else /* version >= v2.0.0 */
+       asc_scsi_q.q1.sense_addr = virt_to_bus(&scp->sense_buffer[0]);
+#endif /* version >= v2.0.0 */
        asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer);
-       asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
+
+       /*
+        * If there are any outstanding requests for the current target,
+        * then every 255th request send an ORDERED request. This heuristic
+        * tries to retain the benefit of request sorting while preventing
+        * request starvation. 255 is the max number of tags or pending commands
+        * a device may have outstanding.
+        *
+        * The request count is incremented below for every successfully
+        * started request.
+        * 
+        */
+       if ((asc_dvc_varp->cur_dvc_qng[scp->target] > 0) &&
+           (boardp->reqcnt[scp->target] % 255) == 0) {
+               asc_scsi_q.q2.tag_code = M2_QTAG_MSG_ORDERED;
+       } else {
+               asc_scsi_q.q2.tag_code = M2_QTAG_MSG_SIMPLE;
+       }
 
        /*
         * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather
@@ -4425,8 +4631,11 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                 * CDB request of single contiguous buffer.
                 */
                ASC_STATS(scp->host, cont_cnt);
-               /* request_buffer is already a real address. */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
                asc_scsi_q.q1.data_addr = (ulong) scp->request_buffer;
+#else /* version >= v2.0.0 */
+               asc_scsi_q.q1.data_addr = virt_to_bus(scp->request_buffer);
+#endif /* version >= v2.0.0 */
                asc_scsi_q.q1.data_cnt = scp->request_bufflen;
                ASC_STATS_ADD(scp->host, cont_xfer,
                                          ASC_CEILING(scp->request_bufflen, 512));
@@ -4444,7 +4653,7 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
 "asc_execute_scsi_cmnd: board %d: use_sg %d > sg_tablesize %d\n",
                                boardp->id, scp->use_sg, scp->host->sg_tablesize);
                        scp->result = HOST_BYTE(DID_ERROR);
-                       asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+                       asc_enqueue(&boardp->done, scp, ASC_BACK);
                        return ASC_ERROR;
                }
 
@@ -4468,7 +4677,11 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
                 */
                slp = (struct scatterlist *) scp->request_buffer;
                for (sgcnt = 0; sgcnt < scp->use_sg; sgcnt++, slp++) {
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
                        asc_sg_head.sg_list[sgcnt].addr = (ulong) slp->address;
+#else /* version >= v2.0.0 */
+                       asc_sg_head.sg_list[sgcnt].addr = virt_to_bus(slp->address);
+#endif /* version >= v2.0.0 */
                        asc_sg_head.sg_list[sgcnt].bytes = slp->length;
                        ASC_STATS_ADD(scp->host, sg_xfer, ASC_CEILING(slp->length, 512));
                }
@@ -4484,28 +4697,71 @@ asc_execute_scsi_cmnd(Scsi_Cmnd *scp)
        switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) {
        case ASC_NOERROR:
                ASC_STATS(scp->host, asc_noerror);
+               /*
+                * Increment monotonically increasing per device successful
+                * request counter. Wrapping doesn't matter.
+                */
+               boardp->reqcnt[scp->target]++;
+
+#if ASC_QUEUE_FLOW_CONTROL
+               /*
+                * Conditionally increment the device queue depth.
+                *
+                * If no error occurred and there have been 100 consecutive
+                * successfull requests and the current queue depth is less
+                * than the maximum queue depth, then increment the current
+                * queue depth.
+                */
+               if (boardp->nerrcnt[scp->target]++ > 100) {
+                       boardp->nerrcnt[scp->target] = 0;
+                       if ((device->queue_curr_depth < device->queue_depth) &&
+                           (!(boardp->queue_full & ASC_TIX_TO_TARGET_ID(scp->target)) ||
+                                (boardp->queue_full_cnt[scp->target] >
+                                 device->queue_curr_depth))) {
+                               device->queue_curr_depth++;
+                       }
+               }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                asc_enqueue(&boardp->active, scp, ASC_BACK);
                ASC_DBG(1, "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n");
                break;
        case ASC_BUSY:
                /* Caller must enqueue request and retry later. */
                ASC_STATS(scp->host, asc_busy);
+#if ASC_QUEUE_FLOW_CONTROL
+               /*
+                * Clear consecutive no error counter and if possbile decrement
+                * queue depth.
+                */
+               boardp->nerrcnt[scp->target] = 0;
+               if (device->queue_curr_depth > 1) {
+                       device->queue_curr_depth--;
+               }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                break;
        case ASC_ERROR:
                ASC_PRINT2(
 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code %x\n",
                        boardp->id, asc_dvc_varp->err_code);
                ASC_STATS(scp->host, asc_error);
+#if ASC_QUEUE_FLOW_CONTROL
+               /* Clear consecutive no error counter. */
+               boardp->nerrcnt[scp->target] = 0;
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                scp->result = HOST_BYTE(DID_ERROR);
-               asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+               asc_enqueue(&boardp->done, scp, ASC_BACK);
                break;
        default:
                ASC_PRINT2(
 "asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code %x\n",
                        boardp->id, asc_dvc_varp->err_code);
                ASC_STATS(scp->host, asc_unknown);
+#if ASC_QUEUE_FLOW_CONTROL
+               /* Clear consecutive no error counter. */
+               boardp->nerrcnt[scp->target] = 0;
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                scp->result = HOST_BYTE(DID_ERROR);
-               asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+               asc_enqueue(&boardp->done, scp, ASC_BACK);
                break;
        }
 
@@ -4645,7 +4901,7 @@ asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep)
         * The done function for the command will be called from
         * advansys_interrupt().
         */
-       asc_enqueue(&boardp->scsi_done_q, scp, ASC_BACK);
+       asc_enqueue(&boardp->done, scp, ASC_BACK);
 
        return;
 }
@@ -4659,6 +4915,9 @@ STATIC int
 asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
 {
        asc_board_t                             *boardp;
+       ASC_SCSI_REQ_Q                  *scsireqq;
+       ASC_CAP_INFO                    *cap_info;
+       ASC_SCSI_INQUIRY                *inquiry;
        int                                             found;
        ASC_SCSI_BIT_ID_TYPE    save_use_tagged_qng;
        ASC_SCSI_BIT_ID_TYPE    save_can_tagged_qng;
@@ -4675,9 +4934,11 @@ asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
        boardp = ASC_BOARDP(scp->host);
 
        /* Set-up AscInitPollTarget() arguments. */
-       memset(&asc_scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
-       memset(&asc_cap_info, 0, sizeof(ASC_CAP_INFO));
-       memset(&asc_inquiry, 0, sizeof(ASC_SCSI_INQUIRY));
+       scsireqq = &boardp->scsireqq;
+       memset(scsireqq, 0, sizeof(ASC_SCSI_REQ_Q));
+       cap_info = &boardp->cap_info;
+       memset(cap_info, 0, sizeof(ASC_CAP_INFO));
+       inquiry = &boardp->inquiry;
 
        /*
         * XXX - AscInitPollBegin() re-initializes these fields to
@@ -4695,24 +4956,24 @@ asc_init_dev(ASC_DVC_VAR *asc_dvc_varp, Scsi_Cmnd *scp)
                return ASC_FALSE;
        }
 
-       asc_scsireqq.sense_ptr = &asc_scsireqq.sense[0];
-       asc_scsireqq.r1.sense_len = ASC_MIN_SENSE_LEN;
-       asc_scsireqq.r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
-       asc_scsireqq.r1.target_lun = 0;
-       asc_scsireqq.r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
+       scsireqq->sense_ptr = &scsireqq->sense[0];
+       scsireqq->r1.sense_len = ASC_MIN_SENSE_LEN;
+       scsireqq->r1.target_id = ASC_TID_TO_TARGET_ID(scp->target);
+       scsireqq->r1.target_lun = 0;
+       scsireqq->r2.target_ix = ASC_TIDLUN_TO_IX(scp->target, 0);
 
        found = ASC_FALSE;
        ASC_DBG(2, "asc_init_dev: AscInitPollTarget()\n");
-       switch (ret = AscInitPollTarget(asc_dvc_varp, &asc_scsireqq,
-               &asc_inquiry, &asc_cap_info)) {
+       switch (ret = AscInitPollTarget(asc_dvc_varp, scsireqq, inquiry,
+               cap_info)) {
        case ASC_TRUE:
                found = ASC_TRUE;
 #ifdef ADVANSYS_DEBUG
                tidmask = ASC_TIX_TO_TARGET_ID(scp->target);
                ASC_DBG2(1, "asc_init_dev: lba %lu, blk_size %lu\n",
-                       asc_cap_info.lba, asc_cap_info.blk_size);
+                       cap_info->lba, cap_info->blk_size);
                ASC_DBG1(1, "asc_init_dev: peri_dvc_type %x\n",
-                       asc_inquiry.byte0.peri_dvc_type);
+                       inquiry->byte0.peri_dvc_type);
                if (asc_dvc_varp->use_tagged_qng & tidmask) {
                        ASC_DBG1(1, "asc_init_dev: command queuing enabled: %d\n",
                                asc_dvc_varp->max_dvc_qng[scp->target]);
@@ -5188,12 +5449,14 @@ asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag)
        ascq->q_tidmask |= ASC_TIX_TO_TARGET_ID(tid);
 #ifdef ADVANSYS_STATS
        /* Maintain request queue statistics. */
+       ascq->q_tot_cnt[tid]++;
        ascq->q_cur_cnt[tid]++;
        if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) {
                ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid];
                ASC_DBG2(1, "asc_enqueue: new q_max_cnt[%d] %d\n",
                        tid, ascq->q_max_cnt[tid]);
        }
+       REQPTIME(reqp) = REQTIMESTAMP();
 #endif /* ADVANSYS_STATS */
        ASC_DBG1(1, "asc_enqueue: reqp %x\n", (unsigned) reqp);
        return;
@@ -5227,6 +5490,7 @@ asc_dequeue(asc_queue_t *ascq, int tid)
                /* Maintain request queue statistics. */
                ascq->q_cur_cnt[tid]--;
                ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
+               REQTIMESTAT("asc_dequeue", ascq, reqp, tid);
 #endif /* ADVANSYS_STATS */
        }
        ASC_DBG1(1, "asc_dequeue: reqp %x\n", (unsigned) reqp);
@@ -5249,6 +5513,9 @@ asc_dequeue(asc_queue_t *ascq, int tid)
  * (or the function return value) is not NULL, i.e. use a temporary
  * variable for 'lastpp' and check its value after the function return
  * before assigning it to the list last pointer.
+ *
+ * Unfortunately collecting queuing time statistics adds overhead to
+ * the function that isn't inherent to the function's algorithm.
  */
 REQP
 asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
@@ -5268,7 +5535,7 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
        if (tid != ASC_TID_ALL) {
                /* Return all requests for the specified 'tid'. */
                if ((ascq->q_tidmask & ASC_TIX_TO_TARGET_ID(tid)) == 0) {
-                       /* List is empty set first and last return pointers to NULL. */
+                       /* List is empty; Set first and last return pointers to NULL. */
                        firstp = lastp = NULL;
                } else {
                        firstp = ascq->q_first[tid];
@@ -5276,7 +5543,13 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
                        ascq->q_first[tid] = ascq->q_last[tid] = NULL;
                        ascq->q_tidmask &= ~ASC_TIX_TO_TARGET_ID(tid);
 #ifdef ADVANSYS_STATS
-                       ascq->q_cur_cnt[tid] = 0;
+                       {
+                               REQP reqp;
+                               ascq->q_cur_cnt[tid] = 0;
+                               for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
+                                       REQTIMESTAT("asc_dequeue_list", ascq, reqp, tid);
+                               }
+                       }
 #endif /* ADVANSYS_STATS */
                }
        } else {
@@ -5299,6 +5572,14 @@ asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid)
 #endif /* ADVANSYS_STATS */
                        }
                }
+#ifdef ADVANSYS_STATS
+               {
+                       REQP reqp;
+                       for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) {
+                               REQTIMESTAT("asc_dequeue_list", ascq, reqp, reqp->target);
+                       }
+               }
+#endif /* ADVANSYS_STATS */
        }
        if (lastpp) {
                *lastpp = lastp;
@@ -5324,7 +5605,7 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp)
        int                     tid;
        int                     ret = ASC_FALSE;
 
-       ASC_DBG2(1, "asc_rmqueue: ascq %x, reqp %d\n",
+       ASC_DBG2(1, "asc_rmqueue: ascq %x, reqp %x\n",
                (unsigned) ascq, (unsigned) reqp);
        ASC_ASSERT(interrupts_enabled() == ASC_FALSE);
        ASC_ASSERT(reqp != NULL);
@@ -5373,6 +5654,7 @@ asc_rmqueue(asc_queue_t *ascq, REQP reqp)
        /* Maintain request queue statistics. */
        if (ret == ASC_TRUE) {
                ascq->q_cur_cnt[tid]--;
+               REQTIMESTAT("asc_rmqueue", ascq, reqp, tid);
        }
        ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0);
 #endif /* ADVANSYS_STATS */
@@ -5406,6 +5688,7 @@ asc_isqueued(asc_queue_t *ascq, REQP reqp)
                        break;
                }
        }
+       ASC_DBG1(1, "asc_isqueued: ret %x\n", ret);
        return ret;
 }
 
@@ -5478,7 +5761,7 @@ asc_prt_board_devices(struct Scsi_Host *shp, char *cp, int cplen)
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if (boardp->asc_dvc_cfg.chip_scsi_id == i) {
                        continue;
-               } else if (boardp->init_tidmask & (1 << i)) {
+               } else if (boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) {
                        len = asc_prt_line(cp, leftlen, " %d,", i);
                        ASC_PRT_NEXT();
                }
@@ -5534,7 +5817,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->disc_enable & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->disc_enable & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5545,7 +5828,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->use_cmd_qng & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->use_cmd_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5556,7 +5839,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->start_motor & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->start_motor & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5567,7 +5850,7 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (ep->init_sdtr & (1 << i)) ? 'Y' : 'N');
+                       i, (ep->init_sdtr & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5595,9 +5878,15 @@ asc_prt_board_eeprom(struct Scsi_Host *shp, char *cp, int cplen)
 STATIC int
 asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
 {
+       asc_board_t                     *boardp;
        int                                     leftlen;
        int                                     totlen;
        int                                     len;
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+       int                                     i;
+#endif /* version >= v1.3.89 */
+
+       boardp = ASC_BOARDP(shp);
 
        leftlen = cplen;
        totlen = len = 0;
@@ -5608,42 +5897,91 @@ asc_prt_driver_conf(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
 
        len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+" host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
+               shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
+#else /* version >= v1.3.89 */
 " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n",
                shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun,
                shp->max_channel);
-#else /* version >= v1.3.89 */
-" host_busy %u, last_reset %u, max_id %u, max_lun %u\n",
-               shp->host_busy, shp->last_reset, shp->max_id, shp->max_lun);
 #endif /* version >= v1.3.89 */
        ASC_PRT_NEXT();
        
        len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,57)
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
+" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
+               shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
+#else /* version >= v1.3.57 */
 " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
                shp->unique_id, shp->can_queue, shp->this_id, shp->sg_tablesize,
                shp->cmd_per_lun);
-#else /* version >= v1.3.57 */
-" can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n",
-               shp->can_queue, shp->this_id, shp->sg_tablesize, shp->cmd_per_lun);
 #endif /* version >= v1.3.57 */
        ASC_PRT_NEXT();
 
        len = asc_prt_line(cp, leftlen,
-#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,57)
-" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
-               shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
-#else /* version >= v1.3.57 */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,57)
 " unchecked_isa_dma %d, loaded_as_module %d\n",
                shp->unchecked_isa_dma, shp->loaded_as_module);
+#else /* version >= v1.3.57 */
+" unchecked_isa_dma %d, use_clustering %d, loaded_as_module %d\n",
+               shp->unchecked_isa_dma, shp->use_clustering, shp->loaded_as_module);
 #endif /* version >= v1.3.57 */
        ASC_PRT_NEXT();
 
        len = asc_prt_line(cp, leftlen,
-" flags %x, reset_jiffies %x, jiffies %x\n",
-               ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->reset_jiffies, jiffies);
+" flags %x, last_reset %x, jiffies %x\n",
+               ASC_BOARDP(shp)->flags, ASC_BOARDP(shp)->last_reset, jiffies);
+       ASC_PRT_NEXT();
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,89)
+       len = asc_prt_line(cp, leftlen,
+" queue_depth:     ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %d:%d",
+                       i, boardp->device[i]->queue_depth);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
+#endif /* version >= v1.3.89 */
+
+#if ASC_QUEUE_FLOW_CONTROL
+       len = asc_prt_line(cp, leftlen,
+" queue_curr_depth:");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %d:%d",
+                       i, boardp->device[i]->queue_curr_depth);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
        ASC_PRT_NEXT();
 
+       len = asc_prt_line(cp, leftlen,
+" queue_count:     ");
+       ASC_PRT_NEXT();
+       for (i = 0; i <= ASC_MAX_TID; i++) {
+               if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
+                       continue;
+               }
+               len = asc_prt_line(cp, leftlen, " %d:%d",
+                       i, boardp->device[i]->queue_count);
+               ASC_PRT_NEXT();
+       }
+       len = asc_prt_line(cp, leftlen, "\n");
+       ASC_PRT_NEXT();
+#endif /* ASC_QUEUE_FLOW_CONTROL */
+
        return totlen;
 }
 
@@ -5668,9 +6006,6 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_DVC_VAR                     *v;
        ASC_DVC_CFG                     *c;
        int                                     i;
-#ifdef ADVANSYS_STATS
-       struct asc_stats        *s;
-#endif /* ADVANSYS_STATS */
 
        boardp = ASC_BOARDP(shp);
        v = &boardp->asc_dvc_var;
@@ -5704,11 +6039,11 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (v->sdtr_done & (1 << i)) ? 'Y' : 'N');
+                       i, (v->sdtr_done & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5719,11 +6054,11 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%c",
-                       i, (v->use_tagged_qng & (1 << i)) ? 'Y' : 'N');
+                       i, (v->use_tagged_qng & ASC_TIX_TO_TARGET_ID(i)) ? 'Y' : 'N');
                ASC_PRT_NEXT();
        }
        len = asc_prt_line(cp, leftlen, "\n");
@@ -5735,7 +6070,7 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%u", i, v->cur_dvc_qng[i]);
@@ -5750,7 +6085,7 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
                len = asc_prt_line(cp, leftlen, " %d:%u", i, v->max_dvc_qng[i]);
@@ -5759,21 +6094,18 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        len = asc_prt_line(cp, leftlen, "\n");
        ASC_PRT_NEXT();
 
-#ifdef ADVANSYS_STATS
-       s = &boardp->asc_stats;
-
        /* Indicate whether the device has returned queue full status. */
        len = asc_prt_line(cp, leftlen,
 " Command Queue Full:      ");
        ASC_PRT_NEXT();
        for (i = 0; i <= ASC_MAX_TID; i++) {
                if ((boardp->asc_dvc_cfg.chip_scsi_id == i) ||
-                   ((boardp->init_tidmask & (1 << i)) == 0)) {
+                   ((boardp->init_tidmask & ASC_TIX_TO_TARGET_ID(i)) == 0)) {
                        continue;
                }
-               if (s->queue_full & (1 << i)) {
+               if (boardp->queue_full & ASC_TIX_TO_TARGET_ID(i)) {
                        len = asc_prt_line(cp, leftlen, " %d:Y-%d",
-                               i, s->queue_full_cnt[i]);
+                               i, boardp->queue_full_cnt[i]);
                } else {
                        len = asc_prt_line(cp, leftlen, " %d:N", i);
                }
@@ -5781,7 +6113,6 @@ asc_prt_board_info(struct Scsi_Host *shp, char *cp, int cplen)
        }
        len = asc_prt_line(cp, leftlen, "\n");
        ASC_PRT_NEXT();
-#endif /* ADVANSYS_STATS */
 
        return totlen;
 }
@@ -5897,18 +6228,19 @@ DvcLeaveCritical(int flags)
 }
 
 /*
- * Convert a virtual address to a virtual address.
- *
- * Apparently Linux is loaded V=R (virtual equals real). Just return
- * the virtual address.
+ * Convert a virtual address to a bus address.
  */
 ulong
 DvcGetPhyAddr(uchar *buf_addr, ulong buf_len)
 {
-       ulong phys_addr;
+       ulong bus_addr;
 
-       phys_addr = (ulong) buf_addr;
-       return phys_addr;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+       bus_addr = (ulong) buf_addr;
+#else /* version >= v2.0.0 */
+       bus_addr = virt_to_bus(buf_addr);
+#endif /* version >= v2.0.0 */
+       return bus_addr;
 }
 
 ulong
@@ -5919,7 +6251,11 @@ DvcGetSGList(ASC_DVC_VAR *asc_dvc_sg, uchar *buf_addr, ulong buf_len,
 
        buf_size = buf_len;
        asc_sg_head_ptr->entry_cnt = 1;
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
        asc_sg_head_ptr->sg_list[0].addr = (ulong) buf_addr;
+#else /* version >= v2.0.0 */
+       asc_sg_head_ptr->sg_list[0].addr = virt_to_bus(buf_addr);
+#endif /* version >= v2.0.0 */
        asc_sg_head_ptr->sg_list[0].bytes = buf_size;
        return buf_size;
 }
@@ -6076,8 +6412,6 @@ DvcWritePCIConfigByte(
 /*
  * Return the BIOS address of the adapter at the specified
  * I/O port and with the specified bus type.
- *
- * This function was formerly supplied by the library.
  */
 ushort
 AscGetChipBiosAddress(
@@ -6088,13 +6422,15 @@ AscGetChipBiosAddress(
     ushort  cfg_lsw ;
     ushort  bios_addr ;
 
-    /*
-     *   We can't get the BIOS address for PCI
-     */
-    if ( bus_type & ASC_IS_PCI )
-    {
-        return( 0 );
-    }
+       /*
+        * The PCI BIOS is re-located by the motherboard BIOS. Because
+        * of this the driver can not determine where a PCI BIOS is
+        * loaded and executes.
+        */
+       if ( bus_type & ASC_IS_PCI )
+       {
+               return( 0 );
+       }
 
     if( ( bus_type & ASC_IS_EISA ) != 0 )
     {
@@ -6169,25 +6505,6 @@ asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
                s->asc_noerror, s->asc_busy, s->asc_error, s->asc_unknown);
        ASC_PRT_NEXT();
 
-       /*
-        * Display request queuing statistics.
-        */
-       len = asc_prt_line(cp, leftlen,
-" Active and Pending Request Queues:\n");
-       ASC_PRT_NEXT();
-
-       active = &ASC_BOARDP(shp)->active;
-       waiting = &ASC_BOARDP(shp)->waiting;
-       for (i = 0; i < ASC_MAX_TID + 1; i++) {
-               if (active->q_max_cnt[i] > 0 || waiting->q_max_cnt[i] > 0) {
-                       len = asc_prt_line(cp, leftlen,
-"  target %d: active [cur %d, max %d], waiting [cur %d, max %d]\n",
-                               i, active->q_cur_cnt[i], active->q_max_cnt[i],
-                               waiting->q_cur_cnt[i], waiting->q_max_cnt[i]);
-                       ASC_PRT_NEXT();
-               }
-       }
-
        /*
         * Display data transfer statistics.
         */
@@ -6235,6 +6552,44 @@ asc_prt_board_stats(struct Scsi_Host *shp, char *cp, int cplen)
                ASC_PRT_NEXT();
        }
 
+       /*
+        * Display request queuing statistics.
+        */
+       len = asc_prt_line(cp, leftlen,
+" Active and Waiting Request Queues (time unit: %d HZ):\n", HZ);
+       ASC_PRT_NEXT();
+
+       active = &ASC_BOARDP(shp)->active;
+       waiting = &ASC_BOARDP(shp)->waiting;
+       for (i = 0; i < ASC_MAX_TID + 1; i++) {
+               if (active->q_tot_cnt[i] > 0 || waiting->q_tot_cnt[i] > 0) {
+                       len = asc_prt_line(cp, leftlen, " target %d\n", i);
+                       ASC_PRT_NEXT();
+
+                       len = asc_prt_line(cp, leftlen,
+"   active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n",
+                               active->q_cur_cnt[i], active->q_max_cnt[i],
+                               active->q_tot_cnt[i],
+                               active->q_min_tim[i], active->q_max_tim[i],
+                               (active->q_tot_cnt[i] == 0) ? 0 :
+                               (active->q_tot_tim[i]/active->q_tot_cnt[i]),
+                               (active->q_tot_cnt[i] == 0) ? 0 :
+                               ASC_TENTHS(active->q_tot_tim[i], active->q_tot_cnt[i]));
+                       ASC_PRT_NEXT();
+
+                       len = asc_prt_line(cp, leftlen,
+"   waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n",
+                               waiting->q_cur_cnt[i], waiting->q_max_cnt[i],
+                               waiting->q_tot_cnt[i],
+                               waiting->q_min_tim[i], waiting->q_max_tim[i],
+                               (waiting->q_tot_cnt[i] == 0) ? 0 :
+                               (waiting->q_tot_tim[i]/waiting->q_tot_cnt[i]),
+                               (waiting->q_tot_cnt[i] == 0) ? 0 :
+                               ASC_TENTHS(waiting->q_tot_tim[i], waiting->q_tot_cnt[i]));
+                       ASC_PRT_NEXT();
+               }
+       }
+
        return totlen;
 }
 #endif /* ADVANSYS_STATS */
@@ -6274,6 +6629,60 @@ asc_prt_scsi_host(struct Scsi_Host *s)
        asc_prt_dvc_cfg(&ASC_BOARDP(s)->asc_dvc_cfg);
 }
 
+/*
+ * asc_prt_scsi_cmnd()
+ */
+STATIC void 
+asc_prt_scsi_cmnd(Scsi_Cmnd *s)
+{
+       printk("Scsi_Cmnd at addr %x\n", (unsigned) s);
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,0)
+       printk(
+" host %x, device %x, target %u, lun %u\n",
+               (unsigned) s->host, (unsigned) s->device, s->target, s->lun);
+#else /* version >= v1.3.0 */
+       printk(
+" host %x, device %x, target %u, lun %u, channel %u,\n",
+               (unsigned) s->host, (unsigned) s->device, s->target, s->lun,
+               s->channel);
+#endif /* version >= v1.3.0 */
+
+       asc_prt_hex(" CDB", s->cmnd, s->cmd_len);
+
+       printk(
+" use_sg %u, sglist_len %u, abort_reason %x\n",
+               s->use_sg, s->sglist_len, s->abort_reason);
+
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(1,3,89)
+       printk(
+" retries %d, allowed %d\n",
+                s->retries, s->allowed);
+#else /* version >= v1.3.89 */
+       printk(
+" serial_number %x, serial_number_at_timeout %x, retries %d, allowed %d\n",
+               (unsigned) s->serial_number, (unsigned) s->serial_number_at_timeout,
+                s->retries, s->allowed);
+#endif /* version >= v1.3.89 */
+
+       printk(
+" timeout_per_command %d, timeout_total %d, timeout %d\n",
+               s->timeout_per_command, s->timeout_total, s->timeout);
+
+       printk(
+" internal_timeout %u, flags %u, this_count %d\n",
+               s->internal_timeout, s->flags, s->this_count);
+
+       printk(
+" scsi_done %x, done %x, host_scribble %x, result %x\n",
+               (unsigned) s->scsi_done, (unsigned) s->done,
+               (unsigned) s->host_scribble, s->result);
+
+       printk(
+" tag %u, pid %u\n",
+               (unsigned) s->tag, (unsigned) s->pid);
+}
+
 /*
  * asc_prt_dvc_var()
  */
@@ -6896,6 +7305,8 @@ AscIsrChipHalted(
                                                asc_dvc->sdtr_done |= target_id;
                                                asc_dvc->init_sdtr |= target_id;
                                                asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+                                               sdtr_data = AscCalSDTRData(asc_dvc,
+                                                       sdtr_xmsg.xfer_period, sdtr_xmsg.req_ack_offset);
                                                AscSetChipSDTR(iop_base, sdtr_data, tid_no);
                                        } else {
                                                q_cntl |= QC_MSG_OUT;
@@ -6903,6 +7314,8 @@ AscIsrChipHalted(
                                                                          sdtr_xmsg.xfer_period,
                                                                          sdtr_xmsg.req_ack_offset);
                                                asc_dvc->pci_fix_asyn_xfer &= ~target_id;
+                                               sdtr_data = AscCalSDTRData(asc_dvc,
+                                                       sdtr_xmsg.xfer_period, sdtr_xmsg.req_ack_offset);
                                                AscSetChipSDTR(iop_base, sdtr_data, tid_no);
                                                asc_dvc->sdtr_done |= target_id;
                                                asc_dvc->init_sdtr |= target_id;
@@ -6996,24 +7409,23 @@ AscIsrChipHalted(
                                                                         (ushort) ((ushort) ASCV_MAX_DVC_QNG_BEG + (ushort) tid_no),
                                                                         cur_dvc_qng);
                                }
-#ifdef ADVANSYS_STATS
                                {
-                                       asc_board_t             *boardp;
-                                       int                             i;
-                                       for (i = 0; i < ASC_NUM_BOARD_SUPPORTED; i++) {
-                                               if (asc_host[i] == NULL) {
-                                                       continue;
-                                               }
-                                               boardp = ASC_BOARDP(asc_host[i]);
-                                               if (&boardp->asc_dvc_var == asc_dvc) {
-                                                       boardp->asc_stats.queue_full |= target_id;
-                                                       boardp->asc_stats.queue_full_cnt[tid_no] =
-                                                         cur_dvc_qng;
-                                                       break;
-                                               }
-                                       }
+                               asc_board_t             *boardp;
+                               boardp = (asc_board_t *) asc_dvc->drv_ptr;
+
+                               /*
+                                * Set the device queue depth to the number of
+                                * active requests when the QUEUE FULL condition
+                                * was encountered.
+                                */
+                               boardp->queue_full |= target_id;
+                               boardp->queue_full_cnt[tid_no] = cur_dvc_qng;
+#if ASC_QUEUE_FLOW_CONTROL
+                               if (boardp->device[tid_no]->queue_curr_depth > cur_dvc_qng) {
+                                       boardp->device[tid_no]->queue_curr_depth = cur_dvc_qng;
+                               }
+#endif /* ASC_QUEUE_FLOW_CONTROL */
                                }
-#endif
                        }
                }
                AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0);
@@ -7331,8 +7743,10 @@ AscScsiSetupCmdQ(
        scsiq->r3.host_stat = 0;
        scsiq->r3.done_stat = 0;
        scsiq->r2.vm_id = 0;
-       scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
        scsiq->r1.data_cnt = buf_len;
+       scsiq->cdbptr = (uchar dosfar *) scsiq->cdb;
+       scsiq->sense_ptr = (uchar dosfar *) scsiq->sense ;
+       scsiq->r1.sense_len = ASC_MIN_SENSE_LEN ;
        scsiq->r2.tag_code = (uchar) M2_QTAG_MSG_SIMPLE;
        scsiq->r2.flag = (uchar) ASC_FLAG_SCSIQ_REQ;
        scsiq->r2.srb_ptr = (ulong) scsiq;
@@ -7345,6 +7759,12 @@ AscScsiSetupCmdQ(
                }
                scsiq->r1.data_addr = phy_addr;
        }
+       if ((phy_addr = AscGetOnePhyAddr(asc_dvc,
+                       (uchar dosfar *) scsiq->sense_ptr,
+                       (ulong) scsiq->r1.sense_len )) == 0L) {
+               return (ERR);
+       }
+       scsiq->r1.sense_addr = phy_addr ;
        return (0);
 }
 
@@ -8441,21 +8861,22 @@ AscGetSynPeriodIndex(
 {
        ruchar             *period_table;
        int                 max_index;
+       int                 min_index;
        int                 i;
        period_table = asc_dvc->sdtr_period_tbl;
        max_index = (int) asc_dvc->max_sdtr_index;
+       min_index = ( int )asc_dvc->host_init_sdtr_index ;
        if (
-                  (syn_time >= period_table[0])
-                  && (syn_time <= period_table[max_index])
+                  (syn_time <= period_table[max_index])
          ) {
-               for (i = 0; i < (max_index - 1); i++) {
+               for (i = min_index; i < (max_index - 1); i++) {
                        if (syn_time <= period_table[i]) {
-                               return (i);
+                               return ((uchar) i);
                        }
                }
-               return (max_index);
+               return ((uchar) max_index);
        } else {
-               return (max_index + 1);
+               return ((uchar) (max_index + 1));
        }
 }
 
@@ -9260,20 +9681,20 @@ AscInitAscDvcVar(
        asc_dvc->no_scam = 0;
        asc_dvc->unit_not_ready = 0;
        asc_dvc->queue_full_or_busy = 0;
+       asc_dvc->redo_scam = 0 ;
+       asc_dvc->res2 = 0 ;
+       asc_dvc->host_init_sdtr_index = 0 ;
+       asc_dvc->res7 = 0 ;
+       asc_dvc->res8 = 0 ;
+       asc_dvc->cfg->can_tagged_qng = 0 ;
+       asc_dvc->cfg->cmd_qng_enabled = 0;
        asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL;
        asc_dvc->init_sdtr = ASC_SCSI_WIDTH_BIT_SET;
        asc_dvc->max_total_qng = ASC_DEF_MAX_TOTAL_QNG;
        asc_dvc->scsi_reset_wait = 3;
        asc_dvc->start_motor = ASC_SCSI_WIDTH_BIT_SET;
        asc_dvc->max_dma_count = AscGetMaxDmaCount(asc_dvc->bus_type);
-       asc_dvc->redo_scam = 0;
-       asc_dvc->res2 = 0;
-       asc_dvc->host_init_sdtr_index = 0;
-       asc_dvc->res7 = 0;
-       asc_dvc->res8 = 0;
        asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET;
-       asc_dvc->cfg->can_tagged_qng = 0;
-       asc_dvc->cfg->cmd_qng_enabled = 0;
        asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID;
        asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER;
        asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) |
@@ -9562,6 +9983,9 @@ AscInitPollIsrCallBack(
                scsiq_req->r3.host_stat = scsi_done_q->d3.host_stat;
                scsiq_req->r3.scsi_stat = scsi_done_q->d3.scsi_stat;
                scsiq_req->r3.scsi_msg = scsi_done_q->d3.scsi_msg;
+               ASC_DBG4(1, "AscInitPollIsrCallBack: done_stat %x, host_stat %x, scsi_stat %x, scsi_msg %x\n",
+                       scsi_done_q->d3.done_stat, scsi_done_q->d3.host_stat,
+                       scsi_done_q->d3.scsi_stat, scsi_done_q->d3.scsi_msg);
                if ((scsi_done_q->d3.scsi_stat == SS_CHK_CONDITION) &&
                        (scsi_done_q->d3.host_stat == 0)) {
                        cp_sen_len = (uchar) ASC_MIN_SENSE_LEN;
@@ -9893,20 +10317,11 @@ AscInitPollTarget(
        int                 support_read_cap;
        int                 tmp_disable_init_sdtr;
        int                 sta;
-       ulong               phy_addr;
        dvc_found = 0;
        tmp_disable_init_sdtr = FALSE;
        tid_bits = scsiq->r1.target_id;
        lun = scsiq->r1.target_lun;
        tid_no = ASC_TIX_TO_TID(scsiq->r2.target_ix);
-       if (
-                  (phy_addr = AscGetOnePhyAddr(asc_dvc,
-                                                                               (uchar dosfar *) scsiq->sense_ptr,
-                                                                               (ulong) scsiq->r1.sense_len)) == 0L
-         ) {
-               return (ERR);
-       }
-       scsiq->r1.sense_addr = phy_addr;
        if (
                   ((asc_dvc->init_sdtr & tid_bits) != 0)
                   && ((asc_dvc->sdtr_done & tid_bits) == 0)
@@ -10024,7 +10439,7 @@ PollQueueDone(
        int                 status;
        int                 retry = 0;
 
-       ASC_DBG1(1, "PollQueueDone: timeout_sec %d", timeout_sec);
+       ASC_DBG1(1, "PollQueueDone: timeout_sec %d\n", timeout_sec);
        do {
                ASC_DBG(1, "PollQueueDone: before AscExeScsiQueue\n");
                if ((status = AscExeScsiQueue(asc_dvc,
@@ -10032,6 +10447,7 @@ PollQueueDone(
                        ASC_DBG(1, "PollQueueDone: before AscPollQDone\n");
                        if ((status = AscPollQDone(asc_dvc, scsiq,
                                                                           timeout_sec)) != 1) {
+                               ASC_DBG1(1, "PollQueueDone: status %x\n", status);
                                if (status == 0x80) {
                                        if (retry++ > ASC_MAX_INIT_BUSY_RETRY) {
                                                break;
@@ -10047,14 +10463,18 @@ PollQueueDone(
                                scsiq->r3.host_stat = 0;
                                scsiq->r3.scsi_stat = 0;
                                scsiq->r3.scsi_msg = 0;
+                               ASC_DBG(1, "PollQueueDone: before AscAbortSRB()\n");
                                AscAbortSRB(asc_dvc, (ulong) scsiq);
                        }
+                       ASC_DBG1(1, "PollQueueDone: status %x\n", status);
                        ASC_DBG1(1, "PollQueueDone: done_stat %x\n", scsiq->r3.done_stat);
                        return (scsiq->r3.done_stat);
                }
+               ASC_DBG1(1, "PollQueueDone: status %x\n", status);
                DvcSleepMilliSecond(5);
        } while (((status == 0) || (status == 0x80)) &&
                          retry++ < ASC_MAX_INIT_BUSY_RETRY);
+       ASC_DBG1(1, "PollQueueDone: status %x\n", status);
        ASC_DBG(1, "PollQueueDone: done_stat QD_WITH_ERROR\n");
        return (scsiq->r3.done_stat = QD_WITH_ERROR);
 }
@@ -10153,12 +10573,12 @@ InitTestUnitReady(
        ASC_REQ_SENSE dosfar *sen;
        retry = 0;
        tid_bits = scsiq->r1.target_id;
-       while (retry++ < 2) {
+       while (retry++ < 4) {
                PollScsiTestUnitReady(asc_dvc, scsiq);
                if (scsiq->r3.done_stat == 0x01) {
                        return (1);
                } else if (scsiq->r3.done_stat == QD_WITH_ERROR) {
-                       DvcSleepMilliSecond(100);
+                       DvcSleepMilliSecond(200);
                        sen = (ASC_REQ_SENSE dosfar *) scsiq->sense_ptr;
                        if ((scsiq->r3.scsi_stat == SS_CHK_CONDITION) &&
                                ((sen->err_code & 0x70) != 0)) {
@@ -10174,9 +10594,10 @@ InitTestUnitReady(
                                        } else {
                                                DvcSleepMilliSecond(5000);
                                        }
-                               } else if (sen->sense_key == SCSI_SENKEY_ATTENSION) {
-                                       DvcSleepMilliSecond(500);
+                               } else if (sen->sense_key == SCSI_SENKEY_ATTENTION) {
+                                       DvcSleepMilliSecond( ( ulong )( 500L*retry ) ) ;
                                } else {
+                                       DvcSleepMilliSecond( 500 ) ;
                                        break;
                                }
                        } else {
@@ -10208,6 +10629,7 @@ AscPollQDone(
        while (TRUE) {
                if (asc_dvc->err_code != 0) {
                        scsiq->r3.done_stat = QD_WITH_ERROR;
+                       ASC_DBG1(1, "AscPollQDone: err_code %x\n", asc_dvc->err_code);
                        sta = ERR;
                        break;
                }
@@ -10220,10 +10642,12 @@ AscPollQDone(
                }
                DvcSleepMilliSecond(10);
                if (loop++ > loop_end) {
+                       ASC_DBG(1, "AscPollQDone: loop finished\n");
                        sta = 0;
                        break;
                }
                if (AscIsChipHalted(iop_base)) {
+                       ASC_DBG(1, "AscPollQDone: AscIsChipHalted()\n");
 #if !CC_ASCISR_CHECK_INT_PENDING
                        AscAckInterrupt(iop_base);
 #endif
@@ -10231,6 +10655,7 @@ AscPollQDone(
                        loop = 0;
                } else {
                        if (AscIsIntPending(iop_base)) {
+                               ASC_DBG(1, "AscPollQDone: AscIsIntPending()\n");
 #if !CC_ASCISR_CHECK_INT_PENDING
                                AscAckInterrupt(iop_base);
 #endif
index 258be2a5f51f5b81f828342eef0d5d3dd7dc261b..83806bdb3800d2b255da044b55cae754e72a294a 100644 (file)
@@ -1,6 +1,13 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25
+ *          Added support for EATA 2.0C, PCI, multichannel and wide SCSI.
+ *
+ *      27 Sep 1996 rev. 2.12 for linux 2.1.0
+ *          Portability cleanups (virtual/bus addressing, little/big endian
+ *          support).
+ *
  *      09 Jul 1996 rev. 2.11 for linux 2.0.4
  *          Number of internal retries is now limited.
  *
@@ -78,7 +85,8 @@
  *
  *  Here is a brief description of the DPT SCSI host adapters.
  *  All these boards provide an EATA/DMA compatible programming interface
- *  and are fully supported by this driver:
+ *  and are fully supported by this driver in any configuration, including
+ *  multiple SCSI channels:
  *
  *  PM2011B/9X -  Entry Level ISA
  *  PM2021A/9X -  High Performance ISA
  *  PM2022A/9X -  Entry Level EISA
  *  PM2122A/9X -  High Performance EISA
  *  PM2322A/9X -  Extra High Performance EISA
+ *  PM3021     -  SmartRAID Adapter for ISA
+ *  PM3222     -  SmartRAID Adapter for EISA (PM3222W is 16-bit wide SCSI)
+ *  PM3224     -  SmartRAID Adapter for PCI  (PM3224W is 16-bit wide SCSI)
  *
  *  The DPT PM2001 provides only the EATA/PIO interface and hence is not
  *  supported by this driver.
  *
  *  This code has been tested with up to 3 Distributed Processing Technology 
  *  PM2122A/9X (DPT SCSI BIOS v002.D1, firmware v05E.0) eisa controllers,
- *  no on board cache and no RAID option. 
- *  BIOS must be enabled on the first board and must be disabled for all other 
- *  boards. 
- *  Support is provided for any number of DPT PM2122 eisa boards.
- *  All boards should be configured at the same IRQ level.
- *  Multiple IRQ configurations are supported too.
- *  Boards can be located in any eisa slot (1-15) and are named EATA0, 
- *  EATA1,... in increasing eisa slot number. ISA boards are detected
- *  after the eisa slot probes.
+ *  in any combination of private and shared IRQ.
+ *  PCI support has been tested using a DPT PM3224W (firmware v07G.0).
+ *
+ *  Multiple ISA, EISA and PCI boards can be configured in the same system.
+ *  It is suggested to put all the EISA boards on the same IRQ level, all
+ *  the PCI  boards on another IRQ level, while ISA boards cannot share 
+ *  interrupts.
  *
- *  The IRQ for EISA boards should be _level_ triggered (not _edge_ triggered).
- *  This is a requirement in order to support multiple boards on the same IRQ.
+ *  If you configure multiple boards on the same IRQ, the interrupt must
+ *  be _level_ triggered (not _edge_ triggered).
  *
- *  Other eisa configuration parameters are:
+ *  This driver detects EATA boards by probes at fixed port addresses,
+ *  so no BIOS32 or PCI BIOS support is used or required.
+ *  The suggested way to detect a generic EATA PCI board is to force on it
+ *  any unused EISA address, even if there are other controllers on the EISA
+ *  bus, or even if you system has no EISA bus at all.
+ *  Do not force any ISA address on EATA PCI boards.
  *
- *  COMMAND QUEUING   : ENABLED
- *  COMMAND TIMEOUT   : ENABLED
- *  CACHE             : DISABLED
+ *  The sequence of detection probes is:
+ *  - ISA 0x1F0; 
+ *  - EISA/PCI 0x1C88 through 0xFC88 (corresponding to EISA slots 1 to 15);
+ *  - ISA  0x170, 0x230, 0x330.
+ *
+ *  The boards are named EATA0, EATA1,... according to the detection order.
  *
  *  In order to support multiple ISA boards in a reliable way,
  *  the driver sets host->wish_block = TRUE for all ISA boards.
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/byteorder.h>
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -154,11 +172,14 @@ struct proc_dir_entry proc_scsi_eata2x = {
 #undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
 
-#define MAX_TARGET 8
+#define MAX_CHANNEL 4
+#define MAX_LUN 32
+#define MAX_TARGET 32
 #define MAX_IRQ 16
 #define MAX_BOARDS 18
 #define MAX_MAILBOXES 64
 #define MAX_SGLIST 64
+#define MAX_LARGE_SGLIST 252
 #define MAX_INTERNAL_RETRIES 64
 #define MAX_CMD_PER_LUN 2
 
@@ -184,7 +205,7 @@ struct proc_dir_entry proc_scsi_eata2x = {
 #define REG_MID         4
 #define REG_MSB         5
 #define REGION_SIZE     9
-#define EISA_RANGE      0xf000
+#define EISA_RANGE      0x1000
 #define BSY_ASSERTED      0x80
 #define DRQ_ASSERTED      0x08
 #define ABSY_ASSERTED     0x01
@@ -209,6 +230,7 @@ struct proc_dir_entry proc_scsi_eata2x = {
 /* Number of valid bytes in the board config structure for EATA 2.0x */
 #define EATA_2_0A_SIZE 28
 #define EATA_2_0B_SIZE 30
+#define EATA_2_0C_SIZE 34
 
 /* Board info structure */
 struct eata_info {
@@ -224,8 +246,7 @@ struct eata_info {
              ata:1,    /* This is an ATA device */
           haaval:1;    /* Host Adapter Address Valid */
    ushort cp_pad_len;   /* Number of pad bytes after cp_len */
-   unchar host_addr[3]; /* Host Adapter SCSI ID for channels 2, 1, 0 */
-   unchar reserved;
+   unchar host_addr[4]; /* Host Adapter SCSI ID for channels 3, 2, 1, 0 */
    ulong  cp_len;       /* Number of valid bytes in cp */
    ulong  sp_len;       /* Number of valid bytes in sp */
    ushort queue_size;   /* Max number of cp that can be queued */
@@ -241,10 +262,14 @@ struct eata_info {
    unchar  isaena:1,    /* ISA i/o addressing is disabled/enabled */
         forcaddr:1,    /* Port address has been forced */
                 :6;
-   unchar  max_id:5,    /* Max number of SCSI target IDs */
+   unchar  max_id:5,    /* Max SCSI target ID number */
         max_chan:3;    /* Max SCSI channel number on this board */
 
-   ushort ipad[249];
+   /* Structure extension defined in EATA 2.0C */
+   unchar   max_lun;    /* Max SCSI LUN number */
+   unchar   notused[3];
+
+   ushort ipad[247];
    };
 
 /* Board config structure */
@@ -283,9 +308,9 @@ struct mscp {
    unchar unused[4];
    unchar phsunit:1,     /* Send to Target Physical Unit (bypass RAID) */
          notused:7;
-   unchar target;        /* SCSI Target ID */
-   unchar     lun:3,     /* LUN */
-                :2,
+   unchar  target:5,     /* SCSI target ID */
+          channel:3;     /* SCSI channel number */
+   unchar     lun:5,     /* SCSI logical unit number */
           luntar:1,     /* This cp is for Target (not LUN) */
           dispri:1,     /* Disconnect Privilege granted */
              one:1;     /* 1 */
@@ -315,26 +340,31 @@ struct hostdata {
    char board_name[16];                 /* Name of this board */
    char board_id[256];                  /* data from INQUIRY on this board */
    int in_reset;                        /* True if board is doing a reset */
-   int target_time_out[MAX_TARGET];     /* N. of timeout errors on target */
-   int target_reset[MAX_TARGET];        /* If TRUE redo operation on target */
+   int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */
+   int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */
    unsigned int retries;                /* Number of internal retries */
    unsigned long last_retried_pid;      /* Pid of last retried command */
-   unsigned char subversion;            /* Bus type, either ISA or ESA */
+   unsigned char subversion;            /* Bus type, either ISA or EISA/PCI */
    unsigned char protocol_rev;          /* EATA 2.0 rev., 'A' or 'B' or 'C' */
    struct mssp sp[MAX_MAILBOXES];       /* Returned status for this board */
    };
 
-static struct Scsi_Host * sh[MAX_BOARDS + 1];
-static const chardriver_name = "EATA";
+static struct Scsi_Host *sh[MAX_BOARDS + 1];
+static const char *driver_name = "EATA";
 static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
 
 #define HD(board) ((struct hostdata *) &sh[board]->hostdata)
 #define BN(board) (HD(board)->board_name)
 
+#define H2DEV(x) htonl(x)
+#define DEV2H(x) H2DEV(x)
+#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
+#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
+
 static void eata2x_interrupt_handler(int, void *, struct pt_regs *);
 static int do_trace = FALSE;
 
-static inline unchar wait_on_busy(ushort iobase) {
+static inline int wait_on_busy(unsigned int iobase) {
    unsigned int loop = MAXLOOP;
 
    while (inb(iobase + REG_AUX_STATUS) & ABSY_ASSERTED)
@@ -343,22 +373,22 @@ static inline unchar wait_on_busy(ushort iobase) {
    return FALSE;
 }
 
-static inline unchar do_dma (ushort iobase, unsigned int addr, unchar cmd) {
+static inline int do_dma(unsigned int iobase, unsigned int addr, unchar cmd) {
 
    if (wait_on_busy(iobase)) return TRUE;
 
-   if (addr) {
-      outb((char)  addr,        iobase + REG_LOW);
-      outb((char) (addr >> 8),  iobase + REG_LM);
-      outb((char) (addr >> 16), iobase + REG_MID);
-      outb((char) (addr >> 24), iobase + REG_MSB);
+   if ((addr = V2DEV(addr))) {
+      outb((char) (addr >> 24), iobase + REG_LOW);
+      outb((char) (addr >> 16), iobase + REG_LM);
+      outb((char) (addr >> 8),  iobase + REG_MID);
+      outb((char)  addr,        iobase + REG_MSB);
       }
 
    outb(cmd, iobase + REG_CMD);
    return FALSE;
 }
 
-static inline unchar read_pio (ushort iobase, ushort *start, ushort *end) {
+static inline int read_pio(unsigned int iobase, ushort *start, ushort *end) {
    unsigned int loop = MAXLOOP;
    ushort *p;
 
@@ -374,12 +404,11 @@ static inline unchar read_pio (ushort iobase, ushort *start, ushort *end) {
    return FALSE;
 }
 
-static inline int port_detect(ushort *port_base, unsigned int j, 
-                             Scsi_Host_Template * tpnt) {
-   unsigned char irq, dma_channel, subversion;
+static inline int port_detect(unsigned int *port_base, unsigned int j, 
+                             Scsi_Host_Template *tpnt) {
+   unsigned char irq, dma_channel, subversion, c;
    unsigned char protocol_rev;
    struct eata_info info;
-   const char *board_status;
 
    /* Allowed DMA channels for ISA (0 indicates reserved) */
    unsigned char dma_channel_table[4] = { 5, 6, 7, 0 };
@@ -403,27 +432,24 @@ static inline int port_detect(ushort *port_base, unsigned int j,
    /* Check the controller "EATA" signature */
    if (info.sign != EATA_SIGNATURE) return FALSE;
 
-   if (ntohl(info.data_len) < EATA_2_0A_SIZE) {
+   if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
       printk("%s: config structure size (%ld bytes) too short, detaching.\n", 
-            name, ntohl(info.data_len));
+            name, DEV2H(info.data_len));
       return FALSE;
       }
-   else if (ntohl(info.data_len) == EATA_2_0A_SIZE)
+   else if (DEV2H(info.data_len) == EATA_2_0A_SIZE)
       protocol_rev = 'A';
-   else if (ntohl(info.data_len) == EATA_2_0B_SIZE)
+   else if (DEV2H(info.data_len) == EATA_2_0B_SIZE)
       protocol_rev = 'B';
    else
       protocol_rev = 'C';
 
-   if (protocol_rev != 'A' && info.max_chan > 0)
-      printk("%s: warning, only scsi channel 0 is supported.\n", name);
-
    irq = info.irq;
 
-   if (*port_base & EISA_RANGE) {
+   if (*port_base >= EISA_RANGE) {
 
       if (!info.haaval || info.ata || info.drqvld) {
-        printk("%s: unusable EISA board found (%d%d%d), detaching.\n", 
+        printk("%s: unusable EISA/PCI board found (%d%d%d), detaching.\n", 
                name, info.haaval, info.ata, info.drqvld);
         return FALSE;
         }
@@ -450,11 +476,6 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       printk("%s: warning, LEVEL triggering is suggested for IRQ %u.\n",
             name, irq);
 
-   if (info.second)
-      board_status = "Sec.";
-   else
-      board_status = "Prim.";
-
    /* Board detected, allocate its IRQ if not already done */
    if ((irq >= MAX_IRQ) || ((irqlist[irq] == NO_IRQ) && request_irq
        (irq, eata2x_interrupt_handler, SA_INTERRUPT, driver_name, NULL))) {
@@ -498,6 +519,7 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       }
 
    sh[j]->io_port = *port_base;
+   sh[j]->unique_id = *port_base;
    sh[j]->n_io_port = REGION_SIZE;
    sh[j]->dma_channel = dma_channel;
    sh[j]->irq = irq;
@@ -526,11 +548,20 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       enable_dma(dma_channel);
       }
 
+   if (protocol_rev != 'A' && info.max_chan > 0 && info.max_chan < MAX_CHANNEL)
+      sh[j]->max_channel = info.max_chan;
+
+   if (protocol_rev != 'A' && info.max_id > 7 && info.max_id < MAX_TARGET)
+      sh[j]->max_id = info.max_id + 1;
+
+   if (protocol_rev == 'C' && info.max_lun > 7 && info.max_lun < MAX_LUN)
+      sh[j]->max_lun = info.max_lun + 1;
+
    strcpy(BN(j), name);
 
-   printk("%s: 2.0%c, %s, ID %d, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\
-         "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev, board_status, 
-          sh[j]->this_id, sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel,
+   printk("%s: rev. 2.0%c, PORT 0x%03x, IRQ %u, DMA %u, SG %d, "\
+         "Mbox %d, CmdLun %d.\n", BN(j), HD(j)->protocol_rev,
+          sh[j]->io_port, sh[j]->irq, sh[j]->dma_channel,
           sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun);
 
    /* DPT PM2012 does not allow to detect sg_tablesize correctly */
@@ -545,30 +576,38 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       sh[j]->can_queue = MAX_MAILBOXES;
       }
 
+   if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
+      printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
+             BN(j), sh[j]->max_id, sh[j]->max_lun);
+
+   for (c = 0; c <= sh[j]->max_channel; c++)
+      printk("%s: SCSI channel %u enabled, host target ID %u.\n",
+             BN(j), c, info.host_addr[3 - c]);
+
 #if defined (DEBUG_DETECT)
    if (protocol_rev != 'A')
       printk("%s: EATA 2.0%c, isaena %u, forcaddr %u, max_id %u,"\
-            " max_chan %u.\n", name, protocol_rev, info.isaena, 
-            info.forcaddr, info.max_id, info.max_chan);
+            " max_chan %u, max_lun %u.\n", name, protocol_rev, info.isaena, 
+            info.forcaddr, info.max_id, info.max_chan, info.max_lun);
 
-   printk("%s: Version 0x%x, SYNC 0x%x, infol %ld, cpl %ld spl %ld.\n", 
-         name, info.version, info.sync, ntohl(info.data_len), 
-         ntohl(info.cp_len), ntohl(info.sp_len));
+   printk("%s: Vers. 0x%x, SYNC 0x%x, sec. %u, infol %ld, cpl %ld spl %ld.\n", 
+         name, info.version, info.sync, info.second, DEV2H(info.data_len), 
+         DEV2H(info.cp_len), DEV2H(info.sp_len));
 #endif
 
    return TRUE;
 }
 
-int eata2x_detect (Scsi_Host_Template * tpnt) {
+int eata2x_detect(Scsi_Host_Template *tpnt) {
    unsigned int j = 0, k, flags;
 
-   ushort io_port[] = { 
-      0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88, 0x8c88,
-      0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, 
-      0x1f0,  0x170,  0x330,  0x230,  0x0
+   unsigned int io_port[] = { 
+      0x1f0,  0x1c88, 0x2c88, 0x3c88, 0x4c88, 0x5c88, 0x6c88, 0x7c88,
+      0x8c88, 0x9c88, 0xac88, 0xbc88, 0xcc88, 0xdc88, 0xec88, 0xfc88, 
+      0x170,  0x230,  0x330,  0x0
       };
 
-   ushort *port_base = io_port;
+   unsigned int *port_base = io_port;
 
    tpnt->proc_dir = &proc_scsi_eata2x;
 
@@ -598,20 +637,20 @@ int eata2x_detect (Scsi_Host_Template * tpnt) {
 
 static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
    unsigned int k;
-   struct scatterlist * sgpnt;
+   struct scatterlist *sgpnt;
 
    sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 
    for (k = 0; k < SCpnt->use_sg; k++) {
-      cpp->sglist[k].address = htonl((unsigned int) sgpnt[k].address);
-      cpp->sglist[k].num_bytes = htonl((unsigned int) sgpnt[k].length);
+      cpp->sglist[k].address = V2DEV(sgpnt[k].address);
+      cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
       }
 
-   cpp->data_address = htonl((unsigned int) cpp->sglist);
-   cpp->data_len = htonl((SCpnt->use_sg * sizeof(struct sg_list)));
+   cpp->data_address = V2DEV(cpp->sglist);
+   cpp->data_len = H2DEV((SCpnt->use_sg * sizeof(struct sg_list)));
 }
 
-int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
+int eata2x_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    unsigned int i, j, k, flags;
    struct mscp *cpp;
    struct mssp *spp;
@@ -670,15 +709,16 @@ int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
 
    memset(spp, 0, sizeof(struct mssp));
 
-   /* The EATA protocol uses Big Endian format, while Intel is Little Endian */
-   cpp->sp_addr = htonl((unsigned int) spp);
+   /* The EATA protocol uses Big Endian format */
+   cpp->sp_addr = V2DEV(spp);
 
    SCpnt->scsi_done = done;
    cpp->index = i;
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
-   if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n",
-                       BN(j), i, SCpnt->target, SCpnt->pid);
+   if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
+                       BN(j), i, SCpnt->channel, SCpnt->target,
+                        SCpnt->lun, SCpnt->pid);
 
    for (k = 0; k < ARRAY_SIZE(data_out_cmds); k++)
      if (SCpnt->cmnd[0] == data_out_cmds[k]) {
@@ -690,10 +730,11 @@ int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    cpp->reqsen = TRUE;
    cpp->dispri = TRUE;
    cpp->one = TRUE;
+   cpp->channel = SCpnt->channel;
    cpp->target = SCpnt->target;
    cpp->lun = SCpnt->lun;  
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = htonl((unsigned int) SCpnt->sense_buffer); 
+   cpp->sense_addr = V2DEV(SCpnt->sense_buffer); 
    cpp->sense_len = sizeof SCpnt->sense_buffer;
 
    if (SCpnt->use_sg) {
@@ -701,8 +742,8 @@ int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
       build_sg_list(cpp, SCpnt);
       }
    else {
-      cpp->data_address = htonl((unsigned int) SCpnt->request_buffer);
-      cpp->data_len = htonl(SCpnt->request_bufflen);
+      cpp->data_address = V2DEV(SCpnt->request_buffer);
+      cpp->data_len = H2DEV(SCpnt->request_bufflen);
       }
 
    memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len);
@@ -711,8 +752,9 @@ int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    if (do_dma(sh[j]->io_port, (unsigned int) cpp, SEND_CP_DMA)) {
       SCpnt->result = DID_ERROR << 16; 
       SCpnt->host_scribble = NULL;
-      printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n", 
-            BN(j), SCpnt->target, SCpnt->pid);
+      printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\
+             " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
+             SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);    
       return 0;
@@ -723,7 +765,7 @@ int eata2x_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    return 0;
 }
 
-int eata2x_abort (Scsi_Cmnd *SCarg) {
+int eata2x_abort(Scsi_Cmnd *SCarg) {
    unsigned int i, j, flags;
 
    save_flags(flags);
@@ -731,15 +773,15 @@ int eata2x_abort (Scsi_Cmnd *SCarg) {
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
 
    if (SCarg->host_scribble == NULL) {
-      printk("%s: abort, target %d, pid %ld inactive.\n",
-            BN(j), SCarg->target, SCarg->pid);
+      printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
+            BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
-   printk("%s: abort, mbox %d, target %d, pid %ld.\n", 
-         BN(j), i, SCarg->target, SCarg->pid);
+   printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n", 
+         BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -782,16 +824,17 @@ int eata2x_abort (Scsi_Cmnd *SCarg) {
    panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
 
-int eata2x_reset (Scsi_Cmnd *SCarg, unsigned int reset_flags) {
-   unsigned int i, j, flags, time, k, limit = 0;
+int eata2x_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
+   unsigned int i, j, flags, time, k, c, limit = 0;
    int arg_done = FALSE;
    Scsi_Cmnd *SCpnt;
 
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d, pid %ld, reset_flags %u.\n", 
-         BN(j), SCarg->target, SCarg->pid, reset_flags);
+   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
+         BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+          reset_flags);
 
    if (SCarg->host_scribble == NULL)
       printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
@@ -810,9 +853,11 @@ int eata2x_reset (Scsi_Cmnd *SCarg, unsigned int reset_flags) {
 
    HD(j)->retries = 0;
 
-   for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE;
-
-   for (k = 0; k < MAX_TARGET; k++) HD(j)->target_time_out[k] = 0;
+   for (c = 0; c <= sh[j]->max_channel; c++)
+      for (k = 0; k < sh[j]->max_id; k++) {
+         HD(j)->target_redo[k][c] = TRUE;
+         HD(j)->target_to[k][c] = 0;
+         }
 
    for (i = 0; i < sh[j]->can_queue; i++) {
 
@@ -896,9 +941,10 @@ int eata2x_reset (Scsi_Cmnd *SCarg, unsigned int reset_flags) {
       }
 }
 
-static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) {
+static void eata2x_interrupt_handler(int irq, void *dev_id,
+                                     struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0;
+   unsigned int i, j, k, c, flags, status, tstatus, loops, total_loops = 0;
    struct mssp *spp;
    struct mscp *cpp;
 
@@ -991,9 +1037,8 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * reg
                     status = DID_ERROR << 16;
    
                  /* If there was a bus reset, redo operation on each target */
-                 else if (tstatus != GOOD
-                          && SCpnt->device->type == TYPE_DISK
-                          && HD(j)->target_reset[SCpnt->target])
+                 else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                          && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
                     status = DID_BUS_BUSY << 16;
    
                  /* Works around a flaw in scsi.c */
@@ -1006,15 +1051,16 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * reg
                     status = DID_OK << 16;
    
                  if (tstatus == GOOD)
-                    HD(j)->target_reset[SCpnt->target] = FALSE;
+                    HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
    
                  if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-                    printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\
-                           "0x%x, sense key 0x%x.\n", BN(j), 
-                           SCpnt->target, SCpnt->lun, SCpnt->pid,
-                           spp->target_status, SCpnt->sense_buffer[2]);
+                    printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                            "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                           SCpnt->channel, SCpnt->target, SCpnt->lun, 
+                            SCpnt->pid, spp->target_status, 
+                            SCpnt->sense_buffer[2]);
    
-                 HD(j)->target_time_out[SCpnt->target] = 0;
+                 HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
    
                   if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
 
@@ -1022,11 +1068,11 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * reg
               case ASST:     /* Selection Time Out */
               case 0x02:     /* Command Time Out   */
    
-                 if (HD(j)->target_time_out[SCpnt->target] > 1)
+                 if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
                     status = DID_ERROR << 16;
                  else {
                     status = DID_TIME_OUT << 16;
-                    HD(j)->target_time_out[SCpnt->target]++;
+                    HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
                     }
    
                  break;
@@ -1035,8 +1081,9 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * reg
               case 0x03:     /* SCSI Bus Reset Received */
               case 0x04:     /* Initial Controller Power-up */
    
-                 for (k = 0; k < MAX_TARGET; k++) 
-                    HD(j)->target_reset[k] = TRUE;
+                 for (c = 0; c <= sh[j]->max_channel; c++) 
+                    for (k = 0; k < sh[j]->max_id; k++) 
+                       HD(j)->target_redo[k][c] = TRUE;
    
                  if (SCpnt->device->type != TYPE_TAPE
                       && HD(j)->retries < MAX_INTERNAL_RETRIES) {
@@ -1075,9 +1122,10 @@ static void eata2x_interrupt_handler(int irq, void *dev_id, struct pt_regs * reg
                do_trace)
 #endif
               printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-                     " target %d:%d, pid %ld, count %d.\n",
+                     " target %d.%d:%d, pid %ld, count %d.\n",
                      BN(j), i, spp->adapter_status, spp->target_status,
-                     SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount);
+                     SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+                      HD(j)->iocount);
    
            /* Set the command state to inactive */
            SCpnt->host_scribble = NULL;
index 00486c97f97d264eaf4d5cc25aea29f13586e4df..0edcb31d4c5ba94ec53e5f4ecf3700b687ece74a 100644 (file)
@@ -11,7 +11,7 @@ int eata2x_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
 int eata2x_abort(Scsi_Cmnd *);
 int eata2x_reset(Scsi_Cmnd *, unsigned int);
 
-#define EATA_VERSION "2.11.00"
+#define EATA_VERSION "2.20.00"
 
 
 #define EATA {                                                 \
index 223edd692fed47a4a883e29cef452d1fe25499b1..df9cb1b02ee20118f4d011618af92dd5def13de2 100644 (file)
@@ -386,14 +386,15 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
        blocks--;
     }
 
+    if (blocks) {
 #if (NDEBUG & NDEBUG_C400_PREAD)
-    printk("53C400r: EXTRA: Waiting for buffer\n");
+       printk("53C400r: EXTRA: Waiting for buffer\n");
 #endif
-    while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
-       ;
+       while (NCR5380_read(C400_CONTROL_STATUS_REG) & CSR_HOST_BUF_NOT_RDY)
+           ;
 
 #if (NDEBUG & NDEBUG_C400_PREAD)
-    printk("53C400r: Transferring EXTRA 128 bytes\n");
+       printk("53C400r: Transferring EXTRA 128 bytes\n");
 #endif
 #ifdef CONFIG_SCSI_G_NCR5380_PORT
        for (i=0; i<128; i++)
@@ -402,8 +403,13 @@ static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst,
        /* implies CONFIG_SCSI_G_NCR5380_MEM */
        memmove(dst+start,NCR53C400_host_buffer+NCR5380_map_name,128);
 #endif
-    start+=128;
-    blocks--;
+       start+=128;
+       blocks--;
+    }
+#if (NDEBUG & NDEBUG_C400_PREAD)
+    else
+       printk("53C400r: No EXTRA required\n");
+#endif
 
 #if (NDEBUG & NDEBUG_C400_PREAD)
     printk("53C400r: Final values: blocks=%d   start=%d\n", blocks, start);
index 82a4d979412378b152efaacb0f32715ce6e6c8fd..1793de1145bac8ca33e6a037feab0971e6818b3a 100644 (file)
@@ -46,7 +46,7 @@ static int      ppa_nybble     = 0;      /* don't force nybble mode  */
 #define   PPA_SPIN_TMO          5000000 /* ppa_wait loop limiter */
 #define   PPA_SECTOR_SIZE       512     /* for a performance hack only */
 
-#include  <unistd.h>
+#include  <linux/stddef.h>
 #include  <linux/module.h>
 #include  <linux/kernel.h>
 #include  <linux/tqueue.h>
index 6f00a24436180f11e7163c4fd3e7acf769e40e8b..2be3dc3df74088b6b82a0b0ca250f0d30a6e8724 100644 (file)
@@ -311,7 +311,7 @@ static int get_device_flags(unsigned char * response_data){
 
 void scsi_make_blocked_list(void)  {
     int block_count = 0, index;
-    unsigned int flags;
+    unsigned long flags;
     struct Scsi_Host * sh[128], * shpnt;
     
     /*
@@ -1025,7 +1025,7 @@ Scsi_Cmnd * allocate_device (struct request ** reqp, Scsi_Device * device,
     kdev_t dev;
     struct request * req = NULL;
     int tablesize;
-    unsigned int flags;
+    unsigned long flags;
     struct buffer_head * bh, *bhp;
     struct Scsi_Host * host;
     Scsi_Cmnd * SCpnt = NULL;
@@ -1293,7 +1293,7 @@ inline void internal_cmnd (Scsi_Cmnd * SCpnt)
 
 static void scsi_request_sense (Scsi_Cmnd * SCpnt)
 {
-    unsigned int flags;
+    unsigned long flags;
     
     save_flags(flags);
     cli();
index ffd39202a3bc73eeee218b7746118a26f881c714..60a7b8b166fff70f095b2cd58687208898d726f3 100644 (file)
@@ -1,6 +1,13 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
+ *      16 Nov 1996 rev. 2.20 for linux 2.1.10 and 2.0.25
+ *          Added multichannel support.
+ *
+ *      27 Sep 1996 rev. 2.12 for linux 2.1.0
+ *          Portability cleanups (virtual/bus addressing, little/big endian
+ *          support).
+ *
  *      09 Jul 1996 rev. 2.11 for linux 2.0.4
  *          "Data over/under-run" no longer implies a redo on all targets.
  *          Number of internal retries is now limited.
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <asm/system.h>
+#include <asm/byteorder.h>
 #include <linux/proc_fs.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -197,6 +205,8 @@ struct proc_dir_entry proc_scsi_u14_34f = {
 #undef  DEBUG_STATISTICS
 #undef  DEBUG_RESET
 
+#define MAX_CHANNEL 1
+#define MAX_LUN 8
 #define MAX_TARGET 8
 #define MAX_IRQ 16
 #define MAX_BOARDS 4
@@ -248,9 +258,9 @@ struct mscp {
    unsigned char dcn: 1;                /* disable disconnect */
    unsigned char ca: 1;                 /* use cache (if available) */
    unsigned char sg: 1;                 /* scatter/gather operation */
-   unsigned char target: 3;             /* target SCSI id */
-   unsigned char ch_no: 2;              /* SCSI channel (always 0 for 14f) */
-   unsigned char lun: 3;                /* logical unit number */
+   unsigned char target: 3;             /* SCSI target id */
+   unsigned char channel: 2;            /* SCSI channel number */
+   unsigned char lun: 3;                /* SCSI logical unit number */
    unsigned int data_address PACKED;    /* transfer data pointer */
    unsigned int data_len PACKED;        /* length in bytes */
    unsigned int command_link PACKED;    /* for linking command chains */
@@ -266,8 +276,8 @@ struct mscp {
    Scsi_Cmnd *SCpnt;
 
    struct sg_list {
-      unsigned int address;     /* Segment Address */
-      unsigned int num_bytes;   /* Segment Length */
+      unsigned int address;             /* Segment Address */
+      unsigned int num_bytes;           /* Segment Length */
       } sglist[MAX_SGLIST];
 
    unsigned int index;   /* cp index */
@@ -283,8 +293,8 @@ struct hostdata {
    char board_name[16];                 /* Name of this board */
    char board_id[256];                  /* data from INQUIRY on this board */
    int in_reset;                        /* True if board is doing a reset */
-   int target_time_out[MAX_TARGET];     /* N. of timeout errors on target */
-   int target_reset[MAX_TARGET];        /* If TRUE redo operation on target */
+   int target_to[MAX_TARGET][MAX_CHANNEL]; /* N. of timeout errors on target */
+   int target_redo[MAX_TARGET][MAX_CHANNEL]; /* If TRUE redo i/o on target */
    unsigned int retries;                /* Number of internal retries */
    unsigned long last_retried_pid;      /* Pid of last retried command */
    unsigned char subversion;            /* Bus type, either ISA or ESA */
@@ -295,17 +305,31 @@ struct hostdata {
    unsigned char slot;
    };
 
-static struct Scsi_Host * sh[MAX_BOARDS + 1];
-static const chardriver_name = "Ux4F";
+static struct Scsi_Host *sh[MAX_BOARDS + 1];
+static const char *driver_name = "Ux4F";
 static unsigned int irqlist[MAX_IRQ], calls[MAX_IRQ];
 
 #define HD(board) ((struct hostdata *) &sh[board]->hostdata)
 #define BN(board) (HD(board)->board_name)
 
+#if defined(__BIG_ENDIAN)
+#define H2DEV(x) ((unsigned long)( \
+       (((unsigned long)(x) & 0x000000ffU) << 24) | \
+       (((unsigned long)(x) & 0x0000ff00U) <<  8) | \
+       (((unsigned long)(x) & 0x00ff0000U) >>  8) | \
+       (((unsigned long)(x) & 0xff000000U) >> 24)))
+#else
+#define H2DEV(x) (x)
+#endif
+
+#define DEV2H(x) H2DEV(x)
+#define V2DEV(addr) ((addr) ? H2DEV(virt_to_bus((void *)addr)) : 0)
+#define DEV2V(addr) ((addr) ? DEV2H(bus_to_virt((unsigned long)addr)) : 0)
+
 static void u14_34f_interrupt_handler(int, void *, struct pt_regs *);
 static int do_trace = FALSE;
 
-static inline unchar wait_on_busy(ushort iobase) {
+static inline int wait_on_busy(unsigned int iobase) {
    unsigned int loop = MAXLOOP;
 
    while (inb(iobase + REG_LCL_INTR) & BSY_ASSERTED)
@@ -322,8 +346,8 @@ static int board_inquiry(unsigned int j) {
    memset(cpp, 0, sizeof(struct mscp));
    cpp->opcode = OP_HOST_ADAPTER;
    cpp->xdir = DTD_IN;
-   cpp->data_address = (unsigned int) HD(j)->board_id;
-   cpp->data_len = sizeof(HD(j)->board_id);
+   cpp->data_address = V2DEV(HD(j)->board_id);
+   cpp->data_len = H2DEV(sizeof(HD(j)->board_id));
    cpp->scsi_cdbs_len = 6;
    cpp->scsi_cdbs[0] = HA_CMD_INQUIRY;
 
@@ -338,7 +362,7 @@ static int board_inquiry(unsigned int j) {
    outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
 
    /* Store pointer in OGM address bytes */
-   outl((unsigned int)cpp, sh[j]->io_port + REG_OGM);
+   outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
 
    /* Issue OGM interrupt */
    outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
@@ -357,9 +381,9 @@ static int board_inquiry(unsigned int j) {
    return FALSE;
 }
 
-static inline int port_detect(ushort *port_base, unsigned int j, 
-                             Scsi_Host_Template * tpnt) {
-   unsigned char irq, dma_channel, subversion;
+static inline int port_detect(unsigned int *port_base, unsigned int j, 
+                             Scsi_Host_Template *tpnt) {
+   unsigned char irq, dma_channel, subversion, c;
    unsigned char in_byte;
 
    /* Allowed BIOS base addresses (NULL indicates reserved) */
@@ -447,6 +471,7 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       }
 
    sh[j]->io_port = *port_base;
+   sh[j]->unique_id = *port_base;
    sh[j]->n_io_port = REGION_SIZE;
    sh[j]->base = bios_segment_table[config_1.bios_segment];
    sh[j]->irq = irq;
@@ -505,6 +530,10 @@ static inline int port_detect(ushort *port_base, unsigned int j,
       enable_dma(dma_channel);
       }
 
+   sh[j]->max_channel = MAX_CHANNEL - 1;
+   sh[j]->max_id = MAX_TARGET;
+   sh[j]->max_lun = MAX_LUN;
+
    if (HD(j)->subversion == ISA && !board_inquiry(j)) {
       HD(j)->board_id[40] = 0;
 
@@ -519,21 +548,29 @@ static inline int port_detect(ushort *port_base, unsigned int j,
 
    printk("%s: PORT 0x%03x, BIOS 0x%05x, IRQ %u, DMA %u, SG %d, "\
          "Mbox %d, CmdLun %d, C%d.\n", BN(j), sh[j]->io_port, 
-         (int)sh[j]->base, sh[j]->irq, 
-         sh[j]->dma_channel, sh[j]->sg_tablesize, 
-         sh[j]->can_queue, sh[j]->cmd_per_lun,
+         (int)sh[j]->base, sh[j]->irq, sh[j]->dma_channel,
+          sh[j]->sg_tablesize, sh[j]->can_queue, sh[j]->cmd_per_lun,
          sh[j]->hostt->use_clustering);
+
+   if (sh[j]->max_id > 8 || sh[j]->max_lun > 8)
+      printk("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n",
+             BN(j), sh[j]->max_id, sh[j]->max_lun);
+
+   for (c = 0; c <= sh[j]->max_channel; c++)
+      printk("%s: SCSI channel %u enabled, host target ID %u.\n",
+             BN(j), c, sh[j]->this_id);
+
    return TRUE;
 }
 
-int u14_34f_detect (Scsi_Host_Template * tpnt) {
+int u14_34f_detect(Scsi_Host_Template *tpnt) {
    unsigned int j = 0, k, flags;
 
-   ushort io_port[] = {
+   unsigned int io_port[] = {
       0x330, 0x340, 0x230, 0x240, 0x210, 0x130, 0x140, 0x0
       };
 
-   ushort *port_base = io_port;
+   unsigned int *port_base = io_port;
 
    tpnt->proc_dir = &proc_scsi_u14_34f;
 
@@ -563,19 +600,19 @@ int u14_34f_detect (Scsi_Host_Template * tpnt) {
 
 static inline void build_sg_list(struct mscp *cpp, Scsi_Cmnd *SCpnt) {
    unsigned int k, data_len = 0;
-   struct scatterlist * sgpnt;
+   struct scatterlist *sgpnt;
 
    sgpnt = (struct scatterlist *) SCpnt->request_buffer;
 
    for (k = 0; k < SCpnt->use_sg; k++) {
-      cpp->sglist[k].address = (unsigned int) sgpnt[k].address;
-      cpp->sglist[k].num_bytes = sgpnt[k].length;
+      cpp->sglist[k].address = V2DEV(sgpnt[k].address);
+      cpp->sglist[k].num_bytes = H2DEV(sgpnt[k].length);
       data_len += sgpnt[k].length;
       }
 
    cpp->use_sg = SCpnt->use_sg;
-   cpp->data_address = (unsigned int) cpp->sglist;
-   cpp->data_len = data_len;
+   cpp->data_address = V2DEV(cpp->sglist);
+   cpp->data_len = H2DEV(data_len);
 }
 
 int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
@@ -634,8 +671,9 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    cpp->index = i;
    SCpnt->host_scribble = (unsigned char *) &cpp->index;
 
-   if (do_trace) printk("%s: qcomm, mbox %d, target %d, pid %ld.\n",
-                       BN(j), i, SCpnt->target, SCpnt->pid);
+   if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n",
+                       BN(j), i, SCpnt->channel, SCpnt->target, 
+                        SCpnt->lun, SCpnt->pid);
 
    cpp->xdir = DTD_IN;
 
@@ -646,10 +684,11 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
        }
 
    cpp->opcode = OP_SCSI;
+   cpp->channel = SCpnt->channel;
    cpp->target = SCpnt->target;
    cpp->lun = SCpnt->lun;
    cpp->SCpnt = SCpnt;
-   cpp->sense_addr = (unsigned int) SCpnt->sense_buffer;
+   cpp->sense_addr = V2DEV(SCpnt->sense_buffer);
    cpp->sense_len = sizeof SCpnt->sense_buffer;
 
    if (SCpnt->use_sg) {
@@ -657,8 +696,8 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
       build_sg_list(cpp, SCpnt);
       }
    else {
-      cpp->data_address = (unsigned int)SCpnt->request_buffer;
-      cpp->data_len = SCpnt->request_bufflen;
+      cpp->data_address = V2DEV(SCpnt->request_buffer);
+      cpp->data_len = H2DEV(SCpnt->request_bufflen);
       }
 
    cpp->scsi_cdbs_len = SCpnt->cmd_len;
@@ -667,15 +706,16 @@ int u14_34f_queuecommand(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) {
    if (wait_on_busy(sh[j]->io_port)) {
       SCpnt->result = DID_ERROR << 16;
       SCpnt->host_scribble = NULL;
-      printk("%s: qcomm, target %d, pid %ld, adapter busy, DID_ERROR, done.\n", 
-            BN(j), SCpnt->target, SCpnt->pid);
+      printk("%s: qcomm, target %d.%d:%d, pid %ld, adapter busy, DID_ERROR,"\
+             " done.\n", BN(j), SCpnt->channel, SCpnt->target, SCpnt->lun,
+             SCpnt->pid);
       restore_flags(flags);
       done(SCpnt);
       return 0;
       }
 
    /* Store pointer in OGM address bytes */
-   outl((unsigned int)cpp, sh[j]->io_port + REG_OGM);
+   outl(V2DEV(cpp), sh[j]->io_port + REG_OGM);
 
    /* Issue OGM interrupt */
    outb(CMD_OGM_INTR, sh[j]->io_port + REG_LCL_INTR);
@@ -693,15 +733,15 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
 
    if (SCarg->host_scribble == NULL) {
-      printk("%s: abort, target %d, pid %ld inactive.\n",
-            BN(j), SCarg->target, SCarg->pid);
+      printk("%s: abort, target %d.%d:%d, pid %ld inactive.\n",
+            BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
       restore_flags(flags);
       return SCSI_ABORT_NOT_RUNNING;
       }
 
    i = *(unsigned int *)SCarg->host_scribble;
-   printk("%s: abort, mbox %d, target %d, pid %ld.\n",
-         BN(j), i, SCarg->target, SCarg->pid);
+   printk("%s: abort, mbox %d, target %d.%d:%d, pid %ld.\n",
+         BN(j), i, SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid);
 
    if (i >= sh[j]->can_queue)
       panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j));
@@ -744,16 +784,17 @@ int u14_34f_abort(Scsi_Cmnd *SCarg) {
    panic("%s: abort, mbox %d, invalid cp_stat.\n", BN(j), i);
 }
 
-int u14_34f_reset(Scsi_Cmnd * SCarg, unsigned int reset_flags) {
-   unsigned int i, j, flags, time, k, limit = 0;
+int u14_34f_reset(Scsi_Cmnd *SCarg, unsigned int reset_flags) {
+   unsigned int i, j, flags, time, k, c, limit = 0;
    int arg_done = FALSE;
    Scsi_Cmnd *SCpnt;
 
    save_flags(flags);
    cli();
    j = ((struct hostdata *) SCarg->host->hostdata)->board_number;
-   printk("%s: reset, enter, target %d, pid %ld, reset_flags %u.\n", 
-         BN(j), SCarg->target, SCarg->pid, reset_flags);
+   printk("%s: reset, enter, target %d.%d:%d, pid %ld, reset_flags %u.\n", 
+         BN(j), SCarg->channel, SCarg->target, SCarg->lun, SCarg->pid,
+          reset_flags);
 
    if (SCarg->host_scribble == NULL)
       printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid);
@@ -772,9 +813,11 @@ int u14_34f_reset(Scsi_Cmnd * SCarg, unsigned int reset_flags) {
 
    HD(j)->retries = 0;
 
-   for (k = 0; k < MAX_TARGET; k++) HD(j)->target_reset[k] = TRUE;
-
-   for (k = 0; k < MAX_TARGET; k++) HD(j)->target_time_out[k] = 0;
+   for (c = 0; c <= sh[j]->max_channel; c++)
+      for (k = 0; k < sh[j]->max_id; k++) {
+         HD(j)->target_redo[k][c] = TRUE;
+         HD(j)->target_to[k][c] = 0;
+         }
 
    for (i = 0; i < sh[j]->can_queue; i++) {
 
@@ -859,7 +902,7 @@ int u14_34f_reset(Scsi_Cmnd * SCarg, unsigned int reset_flags) {
       }
 }
 
-int u14_34f_biosparam(Disk * disk, kdev_t dev, int * dkinfo) {
+int u14_34f_biosparam(Disk *disk, kdev_t dev, int *dkinfo) {
    unsigned int j = 0;
    int size = disk->capacity;
 
@@ -869,9 +912,10 @@ int u14_34f_biosparam(Disk * disk, kdev_t dev, int * dkinfo) {
    return 0;
 }
 
-static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * regs) {
+static void u14_34f_interrupt_handler(int irq, void *dev_id,
+                                      struct pt_regs *regs) {
    Scsi_Cmnd *SCpnt;
-   unsigned int i, j, k, flags, status, tstatus, loops, total_loops = 0;
+   unsigned int i, j, k, c, flags, status, tstatus, loops, total_loops = 0;
    struct mscp *spp;
 
    save_flags(flags);
@@ -901,7 +945,7 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * re
         if (do_trace) printk("%s: ihdlr, start service, count %d.\n",
                              BN(j), HD(j)->iocount);
 
-        spp = (struct mscp *)inl(sh[j]->io_port + REG_ICM);
+        spp = (struct mscp *)DEV2V(inl(sh[j]->io_port + REG_ICM));
 
         /* Clear interrupt pending flag */
         outb(CMD_CLR_INTR, sh[j]->io_port + REG_SYS_INTR);
@@ -956,9 +1000,8 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * re
                  status = DID_ERROR << 16;
 
               /* If there was a bus reset, redo operation on each target */
-              else if (tstatus != GOOD
-                       && SCpnt->device->type == TYPE_DISK
-                       && HD(j)->target_reset[SCpnt->target])
+              else if (tstatus != GOOD && SCpnt->device->type == TYPE_DISK
+                       && HD(j)->target_redo[SCpnt->target][SCpnt->channel])
                  status = DID_BUS_BUSY << 16;
 
               /* Works around a flaw in scsi.c */
@@ -971,26 +1014,27 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * re
                  status = DID_OK << 16;
 
               if (tstatus == GOOD)
-                 HD(j)->target_reset[SCpnt->target] = FALSE;
+                 HD(j)->target_redo[SCpnt->target][SCpnt->channel] = FALSE;
 
               if (spp->target_status && SCpnt->device->type == TYPE_DISK)
-                 printk("%s: ihdlr, target %d:%d, pid %ld, target_status "\
-                        "0x%x, sense key 0x%x.\n", BN(j), 
-                        SCpnt->target, SCpnt->lun, SCpnt->pid,
-                        spp->target_status, SCpnt->sense_buffer[2]);
+                 printk("%s: ihdlr, target %d.%d:%d, pid %ld, "\
+                         "target_status 0x%x, sense key 0x%x.\n", BN(j), 
+                        SCpnt->channel, SCpnt->target, SCpnt->lun,
+                         SCpnt->pid, spp->target_status,
+                         SCpnt->sense_buffer[2]);
 
-              HD(j)->target_time_out[SCpnt->target] = 0;
+              HD(j)->target_to[SCpnt->target][SCpnt->channel] = 0;
 
                if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0;
 
               break;
            case ASST:     /* Selection Time Out */
 
-              if (HD(j)->target_time_out[SCpnt->target] > 1)
+              if (HD(j)->target_to[SCpnt->target][SCpnt->channel] > 1)
                  status = DID_ERROR << 16;
               else {
                  status = DID_TIME_OUT << 16;
-                 HD(j)->target_time_out[SCpnt->target]++;
+                 HD(j)->target_to[SCpnt->target][SCpnt->channel]++;
                  }
 
               break;
@@ -1001,8 +1045,10 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * re
            case 0x96:     /* Illegal SCSI command */
            case 0xa3:     /* SCSI bus reset error */
 
-              for (k = 0; k < MAX_TARGET; k++) 
-                 HD(j)->target_reset[k] = TRUE;
+              for (c = 0; c <= sh[j]->max_channel; c++) 
+                 for (k = 0; k < sh[j]->max_id; k++) 
+                    HD(j)->target_redo[k][c] = TRUE;
+   
 
            case 0x92:     /* Data over/under-run */
 
@@ -1042,9 +1088,10 @@ static void u14_34f_interrupt_handler(int irq, void *dev_id, struct pt_regs * re
             do_trace)
 #endif
            printk("%s: ihdlr, mbox %2d, err 0x%x:%x,"\
-                  " target %d:%d, pid %ld, count %d.\n",
+                  " target %d.%d:%d, pid %ld, count %d.\n",
                   BN(j), i, spp->adapter_status, spp->target_status,
-                  SCpnt->target, SCpnt->lun, SCpnt->pid, HD(j)->iocount);
+                  SCpnt->channel, SCpnt->target, SCpnt->lun, SCpnt->pid,
+                   HD(j)->iocount);
 
         /* Set the command state to inactive */
         SCpnt->host_scribble = NULL;
index a4dc31e850b5fc86a5fdf3afedeb5441a7d76310..f301f48ae629c72ffcb55f09afc117b36fefb635 100644 (file)
@@ -10,7 +10,7 @@ int u14_34f_abort(Scsi_Cmnd *);
 int u14_34f_reset(Scsi_Cmnd *, unsigned int);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "2.11.00"
+#define U14_34F_VERSION "2.20.00"
 
 #define ULTRASTOR_14_34F {                                            \
                NULL, /* Ptr for modules */                           \
index 768bae850f7b0ef4c77b3fbf7f2f3e3480614357..03f74548188d673d57facd431b31ba165a7c6aa8 100644 (file)
 #define __NR_nanosleep                 340
 #define __NR_mremap                    341
 #define __NR_nfsctl                    342
+#define __NR_setresuid                 343
+#define __NR_getresuid                 344
+#define __NR_pciconfig_read            345
+#define __NR_pciconfig_write           346
 
 #if defined(__LIBRARY__) && defined(__GNUC__)
 
index 272be68948bf0428751cba86370e168cc3d10099..82569a65353afd29db701878581285210a0fe26b 100644 (file)
@@ -36,6 +36,7 @@ struct igmphdr
 #define IGMP_HOST_MEMBERSHIP_REPORT    0x12    /* Ditto */
 #define IGMP_DVMRP                     0x13    /* DVMRP routing */
 #define IGMP_PIM                       0x14    /* PIM routing */
+#define IGMP_TRACE                     0x15    /* CISCO trace */
 #define IGMP_HOST_NEW_MEMBERSHIP_REPORT 0x16   /* New version of 0x11 */
 #define IGMP_HOST_LEAVE_MESSAGE        0x17    /* An extra BSD seems to send */
 
@@ -90,7 +91,8 @@ struct ip_mc_list
        unsigned long multiaddr;
        struct ip_mc_list *next;
        struct timer_list timer;
-       int tm_running;
+       short tm_running;
+       short reporter;
        int users;
 };
 
index 1408407d9388a1df7ff63dceea6b7bece378af5d..cf6a8bf6ae2ed99e8dd3d8e3e3ab6fa3289aebf0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.16 1996/08/12 16:20:56 hipp Exp $
+/* $Id: isdn.h,v 1.18 1996/11/06 17:37:50 keil Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn.h,v $
+ * Revision 1.18  1996/11/06 17:37:50  keil
+ * more changes for 2.1.X
+ *
+ * Revision 1.17  1996/09/07 12:53:57  hipp
+ * moved a few isdn_ppp.c specific defines to drives/isdn/isdn_ppp.h
+ *
  * Revision 1.16  1996/08/12 16:20:56  hipp
  * renamed ppp_minor to ppp_slot
  *
@@ -212,7 +218,6 @@ typedef struct {
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/malloc.h>
-#include <linux/mm.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/tty.h>
@@ -504,11 +509,6 @@ typedef struct {
 #define NUM_RCV_BUFFS     64
 #define PPP_HARD_HDR_LEN 4
 
-#define IPPP_OPEN        0x1
-#define IPPP_CONNECT     0x2
-#define IPPP_CLOSEWAIT   0x4
-#define IPPP_NOBLOCK     0x8
-
 #ifdef CONFIG_ISDN_PPP
 
 struct sqqueue {
index 113099edf42e5de292472bf712daa8dfc0d63eb1..76837784710eece5fff4775085644f90dfa5be68 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: isdnif.h,v 1.9 1996/06/06 21:24:24 fritz Exp $
+/* $Id: isdnif.h,v 1.13 1996/11/13 02:39:59 fritz Exp $
  *
  * Linux ISDN subsystem
  *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdnif.h,v $
+ * Revision 1.13  1996/11/13 02:39:59  fritz
+ * More compatibility changes.
+ *
+ * Revision 1.12  1996/11/06 17:38:48  keil
+ * more changes for 2.1.X
+ *
+ * Revision 1.11  1996/10/23 11:59:42  fritz
+ * More compatibility changes.
+ *
+ * Revision 1.10  1996/10/22 23:14:19  fritz
+ * Changes for compatibility to 2.0.X and 2.1.X kernels.
+ *
  * Revision 1.9  1996/06/06 21:24:24  fritz
  * Started adding support for suspend/resume.
  *
@@ -302,6 +314,30 @@ typedef struct {
  */
 extern int register_isdn(isdn_if*);
 
+/* Compatibility Linux-2.0.X <-> Linux-2.1.X */
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+#if (LINUX_VERSION_CODE < 0x020100)
+#include <linux/mm.h>
+#define copy_from_user memcpy_fromfs
+#define copy_to_user memcpy_tofs
+#define GET_USER(x, addr) ( x = get_user(addr) )
+#define RWTYPE int
+#define LSTYPE int
+#define RWARG int
+#define LSARG off_t
+#else
+#include <asm/uaccess.h>
+#define GET_USER get_user
+#define PUT_USER put_user
+#define RWTYPE long
+#define LSTYPE long long
+#define RWARG unsigned long
+#define LSARG long long
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* isdnif_h */
 
index 584189f65a20cd428f28cca7d4b8189cc8b849e6..c7f6382d621efbb914c8cf8a7ef22fed68465cc6 100644 (file)
@@ -8,8 +8,8 @@
 
 /* limits */
 
-#define MAX_CHRDEV 64
-#define MAX_BLKDEV 64
+#define MAX_CHRDEV 128
+#define MAX_BLKDEV 128
 
 #define UNNAMED_MAJOR  0
 #define MEM_MAJOR      1
index fb6eea7e15822635c49fb8ab969f43d4c76bc06e..4118dfdc01f7041c251490f367c3041c7f4c8cec 100644 (file)
 #define PCI_DEVICE_ID_DEC_TULIP_FAST   0x0009
 #define PCI_DEVICE_ID_DEC_FDDI         0x000F
 #define PCI_DEVICE_ID_DEC_TULIP_PLUS   0x0014
-#define PCI_DEVICE_ID_DEC_21052_AB     0x0021
-#define PCI_DEVICE_ID_DEC_21152_AA     0x0024
+#define PCI_DEVICE_ID_DEC_21052                0x0021
+#define PCI_DEVICE_ID_DEC_21152                0x0024
 
 #define PCI_VENDOR_ID_CIRRUS           0x1013
 #define PCI_DEVICE_ID_CIRRUS_5430      0x00a0
 
 #define PCI_VENDOR_ID_S3               0x5333
 #define PCI_DEVICE_ID_S3_ViRGE         0x5631
-#define PCI_DEVICE_ID_S3_811           0x8811
+#define PCI_DEVICE_ID_S3_TRIO          0x8811
+#define PCI_DEVICE_ID_S3_AURORA64VP    0x8812
+#define PCI_DEVICE_ID_S3_TRIO64UVP     0x8814
+#define PCI_DEVICE_ID_S3_ViRGE_VX      0x883d
 #define PCI_DEVICE_ID_S3_868           0x8880
 #define PCI_DEVICE_ID_S3_928           0x88b0
 #define PCI_DEVICE_ID_S3_864_1         0x88c0
index ae328b6982eb19b653863e727c4132cf6b7e8b0c..c21f845aaeddd4fbc316d9c55dbe12a4284c13da 100644 (file)
@@ -35,7 +35,7 @@ struct inet_protocol {
   void                 (*err_handler)(int type, int code, unsigned char *buff,
                                       __u32 daddr,
                                       __u32 saddr,
-                                      struct inet_protocol *protocol);
+                                      struct inet_protocol *protocol, int len);
   struct inet_protocol *next;
   unsigned char                protocol;
   unsigned char                copy:1;
index 82714831f8ef6af5f47c0c0af5501577123e77b1..36bb61270a9f853cf1a2f401dc45b9ecf7aada41 100644 (file)
@@ -129,7 +129,7 @@ extern struct proto tcp_prot;
 extern struct tcp_mib tcp_statistics;
 
 extern void    tcp_err(int type, int code, unsigned char *header, __u32 daddr,
-                       __u32, struct inet_protocol *protocol);
+                       __u32, struct inet_protocol *protocol, int len);
 extern void    tcp_shutdown (struct sock *sk, int how);
 extern int     tcp_rcv(struct sk_buff *skb, struct device *dev,
                        struct options *opt, __u32 daddr,
index fe4723a78c68efe54739517597395eb6ec85b406..404f64a956b34e729135c3ff1df12888091e9c81 100644 (file)
@@ -32,7 +32,7 @@ extern struct proto udp_prot;
 
 
 extern void    udp_err(int type, int code, unsigned char *header, __u32 daddr,
-                       __u32 saddr, struct inet_protocol *protocol);
+                       __u32 saddr, struct inet_protocol *protocol, int len);
 extern void    udp_send_check(struct udphdr *uh, __u32 saddr, 
                        __u32 daddr, int len, struct sock *sk);
 extern int     udp_recvfrom(struct sock *sk, unsigned char *to,
index f212a182c2e0cc66c317d895fbdfd36796fc5a9a..296fb99b91b5759d2e071e0a2288ff19d7fdf6e5 100644 (file)
@@ -1085,7 +1085,7 @@ static int atalk_getsockopt(struct socket *sock, int level, int optname,
        err=verify_area(VERIFY_WRITE,optval,sizeof(int));
        if (err) 
                return err;
-       put_user(val,optval);
+       put_user(val,(int *)optval);
        return(0);
 }
 
index ece3534f461baf8a51b7c5e0e0ab3e238cc74ea8..b1872f532fb8a652506f75eac230df0380ceb6d5 100644 (file)
@@ -1034,7 +1034,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname,
        if ((err = verify_area(VERIFY_WRITE, optval, sizeof(int))) != 0)
                return err;
 
-       put_user(val, optval);
+       put_user(val, (int *)optval);
 
        return 0;
 }
index 1aeea41f8d61f9e108dce1ecb36ada2108548631..7aa28f4e3bdb2952be386f469a2c780388398d91 100644 (file)
@@ -642,8 +642,15 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct devi
        unsigned char *dp;      
        int match_addr=0;
        
+       if(len<sizeof(struct iphdr))
+               goto flush_it;
+               
        iph = (struct iphdr *) (icmph + 1);
        
+       len-=iph->ihl<<2;
+       if(len<0)
+               goto flush_it;
+       
        dp= ((unsigned char *)iph)+(iph->ihl<<2);
        
        if(icmph->type==ICMP_DEST_UNREACH)
@@ -784,12 +791,13 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, struct devi
                        if (iph->protocol == ipprot->protocol && ipprot->err_handler) 
                        {
                                ipprot->err_handler(icmph->type, icmph->code, dp,
-                                           iph->daddr, iph->saddr, ipprot);
+                                           iph->daddr, iph->saddr, ipprot, len);
                        }
 
                        ipprot = nextip;
                }
        }
+flush_it:
        kfree_skb(skb, FREE_READ);
 }
 
@@ -806,6 +814,9 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct dev
        /*
         *      Get the copied header of the packet that caused the redirect
         */
+       
+       if(len<=sizeof(struct iphdr))
+               goto flush_it;
         
        iph = (struct iphdr *) (icmph + 1);
        ip = iph->daddr;
@@ -861,7 +872,7 @@ static void icmp_redirect(struct icmphdr *icmph, struct sk_buff *skb, struct dev
        /*
         *      Discard the original packet
         */
-        
+flush_it:
        kfree_skb(skb, FREE_READ);
 }
 
index d703e8e77b5638b20c956ca86f89a415a4a0fc8b..a116f46e8380d7d4347f800f791ee952ffb236cb 100644 (file)
@@ -61,6 +61,9 @@
  *                                     miscalculation fixed in igmp_heard_query
  *                                     and random() made to return unsigned to
  *                                     prevent negative expiry times.
+ *             Alexey Kuznetsov:       Wrong group leaving behaviour, backport
+ *                                     fix from pending 2.1.x patches.
+ *             Alan Cox:               Forget to enable FDDI support earlier.
  */
 
 
@@ -278,6 +281,7 @@ static void igmp_timer_expire(unsigned long data)
                igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_NEW_MEMBERSHIP_REPORT);
        else
                igmp_send_report(im->interface, im->multiaddr, IGMP_HOST_MEMBERSHIP_REPORT);
+       im->reporter=1;
 }
 
 static void igmp_init_timer(struct ip_mc_list *im)
@@ -289,17 +293,24 @@ static void igmp_init_timer(struct ip_mc_list *im)
 }
 
 
-static void igmp_heard_report(struct device *dev, unsigned long address)
+static void igmp_heard_report(struct device *dev, __u32 address, __u32 src)
 {
        struct ip_mc_list *im;
 
-       if ((address & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP) {
-         /* Timers are only set for non-local groups */
-         for(im=dev->ip_mc_list;im!=NULL;im=im->next) {
-           if(im->multiaddr==address && im->tm_running) {
-             igmp_stop_timer(im);
-           }
-         }
+       if ((address & IGMP_LOCAL_GROUP_MASK) != IGMP_LOCAL_GROUP) 
+       {
+               /* Timers are only set for non-local groups */
+               for(im=dev->ip_mc_list;im!=NULL;im=im->next) 
+               {
+                       if(im->multiaddr==address)
+                       {
+                               if(im->tm_running) 
+                                       igmp_stop_timer(im);
+                               if(src!=dev->pa_addr)
+                                       im->reporter=0;
+                               return;
+                       }
+               }
        }
 }
 
@@ -391,8 +402,8 @@ extern __inline__ void ip_mc_map(unsigned long addr, char *buf)
 void ip_mc_filter_add(struct device *dev, unsigned long addr)
 {
        char buf[6];
-       if(dev->type!=ARPHRD_ETHER)
-               return; /* Only do ethernet now */
+       if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_FDDI)
+               return; /* Only do ethernet or FDDI for now */
        ip_mc_map(addr,buf);
        dev_mc_add(dev,buf,ETH_ALEN,0);
 }
@@ -404,8 +415,8 @@ void ip_mc_filter_add(struct device *dev, unsigned long addr)
 void ip_mc_filter_del(struct device *dev, unsigned long addr)
 {
        char buf[6];
-       if(dev->type!=ARPHRD_ETHER)
-               return; /* Only do ethernet now */
+       if(dev->type!=ARPHRD_ETHER && dev->type!=ARPHRD_FDDI)
+               return; /* Only do ethernet or FDDI for now */
        ip_mc_map(addr,buf);
        dev_mc_delete(dev,buf,ETH_ALEN,0);
 }
@@ -473,9 +484,9 @@ int igmp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
        if(ih->type==IGMP_HOST_MEMBERSHIP_QUERY && daddr==IGMP_ALL_HOSTS)
                igmp_heard_query(dev,ih->code);
        if(ih->type==IGMP_HOST_MEMBERSHIP_REPORT && daddr==ih->group)
-               igmp_heard_report(dev,ih->group);
+               igmp_heard_report(dev,ih->group, saddr);
        if(ih->type==IGMP_HOST_NEW_MEMBERSHIP_REPORT && daddr==ih->group)
-               igmp_heard_report(dev,ih->group);
+               igmp_heard_report(dev,ih->group, saddr);
        kfree_skb(skb, FREE_READ);
        return 0;
 }
index b45ad5656d572828ec1b5c165f885b248bb87e62..e557c39c7b82c04cc7cb48100ee57dedd9160b55 100644 (file)
@@ -10,6 +10,8 @@
  *
  * Fixes:
  *             Alan Cox        :       Split from ip.c , see ip_input.c for history.
+ *             Alan Cox        :       Handling oversized frames
+ *             Uriel Maimon    :       Accounting errors in two fringe cases.
  */
 
 #include <linux/types.h>
@@ -486,7 +488,7 @@ struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device
        {
                skb->sk = NULL;
                printk("Oversized packet received from %s\n",in_ntoa(iph->saddr));
-               frag_kfree_skb(skb, FREE_READ);
+               kfree_skb(skb, FREE_READ);
                ip_statistics.IpReasmFails++;
                return NULL;
        }       
@@ -554,6 +556,9 @@ struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device
                /*
                 *      If we get a frag size of <= 0, remove it and the packet
                 *      that it goes with.
+                *
+                *      We never throw the new frag away, so the frag being
+                *      dumped has always been charged for.
                 */
                if (tmp->len <= 0)
                {
@@ -580,15 +585,21 @@ struct sk_buff *ip_defrag(struct iphdr *iph, struct sk_buff *skb, struct device
        tfp = ip_frag_create(offset, end, skb, ptr);
 
        /*
-        *      No memory to save the fragment - so throw the lot
+        *      No memory to save the fragment - so throw the lot. If we
+        *      failed the frag_create we haven't charged the queue.
         */
 
        if (!tfp)
        {
                skb->sk = NULL;
-               frag_kfree_skb(skb, FREE_READ);
+               kfree_skb(skb, FREE_READ);
                return NULL;
        }
+       
+       /*
+        *      From now on our buffer is charged to the queues.
+        */
+        
        tfp->prev = prev;
        tfp->next = next;
        if (prev != NULL)
index 54660a26683f722401c0d562e2f70f49613c51e3..a45b083637b05c94b3546462ed6fd95b4f3c9750 100644 (file)
@@ -542,7 +542,7 @@ int ip_mroute_setsockopt(struct sock *sk,int optname,char *optval,int optlen)
                                return -EINVAL;
                        if((err=verify_area(VERIFY_READ, optval,sizeof(int)))<0)
                                return err;
-                       mroute_do_pim= (optval)?1:0;
+                       mroute_do_pim= get_user((int *)optval)?1:0;
                        return 0;
                /*
                 *      Spurious command, or MRT_VERSION which you cannot
index e6f1fde3864bce684bf413642c971bba53d53c02..b1438ec7c38643fb975c3b055962b899e2a37f2b 100644 (file)
@@ -502,7 +502,7 @@ void tcp_time_wait(struct sock *sk)
  */
 
 void tcp_err(int type, int code, unsigned char *header, __u32 daddr,
-       __u32 saddr, struct inet_protocol *protocol)
+       __u32 saddr, struct inet_protocol *protocol, int len)
 {
        struct tcphdr *th = (struct tcphdr *)header;
        struct sock *sk;
@@ -514,6 +514,10 @@ void tcp_err(int type, int code, unsigned char *header, __u32 daddr,
        struct iphdr *iph=(struct iphdr *)(header-sizeof(struct iphdr));
 #endif
        th =(struct tcphdr *)header;
+       
+       if(len<sizeof(struct tcphdr))
+               return;
+               
        sk = get_sock(&tcp_prot, th->source, daddr, th->dest, saddr, 0, 0);
 
        if (sk == NULL)
@@ -1420,6 +1424,8 @@ static int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
                        if (copied)
                                break;
                        copied = -ERESTARTSYS;
+                       if (nonblock)
+                               copied = -EAGAIN;
                        break;
                }
 
index 9634f3941d98c746ed28a814f372aabf1e47423c..f0c1b0fa874e3a22bc1a657b0238deec7a8d5cd8 100644 (file)
@@ -202,7 +202,7 @@ static void bad_tcp_sequence(struct sock *sk, struct tcphdr *th, u32 end_seq,
         
        if (sk->state==TCP_SYN_SENT || sk->state==TCP_SYN_RECV) 
        {
-               tcp_send_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev, sk->ip_tos,sk->ip_ttl);
+               tcp_send_reset(sk->saddr,sk->daddr,th,sk->prot,NULL,dev,0,255);
                return;
        }
 
@@ -248,11 +248,18 @@ static int tcp_reset(struct sock *sk, struct sk_buff *skb)
        /*
         *      We want the right error as BSD sees it (and indeed as we do).
         */
-       sk->err = ECONNRESET;
-       if (sk->state == TCP_SYN_SENT)
+       switch (sk->state) {
+       case TCP_TIME_WAIT:
+               break;
+       case TCP_SYN_SENT:
                sk->err = ECONNREFUSED;
-       if (sk->state == TCP_CLOSE_WAIT)
+               break;
+       case TCP_CLOSE_WAIT:
                sk->err = EPIPE;
+               break;
+       default:
+               sk->err = ECONNRESET;
+       }
 #ifdef CONFIG_TCP_RFC1337
        /*
         *      Time wait assassination protection [RFC1337]
@@ -368,7 +375,7 @@ static void tcp_conn_request(struct sock *sk, struct sk_buff *skb,
        {
                if(sk->debug)
                        printk("Reset on %p: Connect on dead socket.\n",sk);
-               tcp_send_reset(daddr, saddr, th, sk->prot, opt, dev, sk->ip_tos,sk->ip_ttl);
+               tcp_send_reset(daddr, saddr, th, sk->prot, opt, dev, 0,255);
                tcp_statistics.TcpAttemptFails++;
                kfree_skb(skb, FREE_READ);
                return;
@@ -1558,7 +1565,7 @@ static int tcp_data(struct sk_buff *skb, struct sock *sk,
                                {
                                        sk->acked_seq = new_seq + th->fin;
                                        tcp_send_reset(sk->saddr, sk->daddr, skb->h.th,
-                                               sk->prot, NULL, skb->dev, sk->ip_tos, sk->ip_ttl);
+                                               sk->prot, NULL, skb->dev, 0, 255);
                                        tcp_statistics.TcpEstabResets++;
                                        sk->err = EPIPE;
                                        sk->error_report(sk);
@@ -1863,7 +1870,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                if(sk->state==TCP_LISTEN)
                {
                        if(th->ack)     /* These use the socket TOS.. might want to be the received TOS */
-                               tcp_send_reset(daddr,saddr,th,sk->prot,opt,dev,sk->ip_tos, sk->ip_ttl);
+                               tcp_send_reset(daddr,saddr,th,sk->prot,opt,dev,0, 255);
 
                        /*
                         *      We don't care for RST, and non SYN are absorbed (old segments)
@@ -1944,7 +1951,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                                           different connection  [ th->rst is checked in tcp_send_reset()] */
                                        tcp_statistics.TcpAttemptFails++;
                                        tcp_send_reset(daddr, saddr, th,
-                                               sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl);
+                                               sk->prot, opt,dev,0,255);
                                        kfree_skb(skb, FREE_READ);
                                        return(0);
                                }
@@ -1956,7 +1963,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                                           start. Shouldn't happen but cover it */
                                        tcp_statistics.TcpAttemptFails++;
                                        tcp_send_reset(daddr, saddr, th,
-                                               sk->prot, opt,dev,sk->ip_tos,sk->ip_ttl);
+                                               sk->prot, opt,dev,0,255);
                                        kfree_skb(skb, FREE_READ);
                                        return 0;
                                }
@@ -2103,7 +2110,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
         
        if(th->syn && skb->seq!=sk->syn_seq)
        {
-               tcp_send_reset(daddr,saddr,th, &tcp_prot, opt, dev, skb->ip_hdr->tos, 255);
+               tcp_send_reset(daddr,saddr,th, &tcp_prot, opt, dev,0, 255);
                return tcp_reset(sk,skb);       
        }
 
@@ -2120,7 +2127,7 @@ int tcp_rcv(struct sk_buff *skb, struct device *dev, struct options *opt,
                 
                if(sk->state==TCP_SYN_RECV)
                {
-                       tcp_send_reset(daddr, saddr, th,sk->prot, opt, dev,sk->ip_tos,sk->ip_ttl);
+                       tcp_send_reset(daddr, saddr, th,sk->prot, opt, dev,0,255);
                }
                kfree_skb(skb, FREE_READ);
                return 0;
@@ -2164,7 +2171,7 @@ no_tcp_socket:
        /*
         *      No such TCB. If th->rst is 0 send a reset (checked in tcp_send_reset)
         */
-       tcp_send_reset(daddr, saddr, th, &tcp_prot, opt,dev,skb->ip_hdr->tos,255);
+       tcp_send_reset(daddr, saddr, th, &tcp_prot, opt,dev,0,255);
 
 discard_it:
        /*
index 07e2a4a77222f09235ab132c183196ed36f84cc9..432bb10f82d4509af8c1589300f53e60025e0276 100644 (file)
@@ -151,7 +151,7 @@ void udp_cache_zap(void)
  */
 
 void udp_err(int type, int code, unsigned char *header, __u32 daddr,
-       __u32 saddr, struct inet_protocol *protocol)
+       __u32 saddr, struct inet_protocol *protocol, int len)
 {
        struct udphdr *uh;
        struct sock *sk;
@@ -159,6 +159,9 @@ void udp_err(int type, int code, unsigned char *header, __u32 daddr,
        /*
         *      Find the 8 bytes of post IP header ICMP included for us
         */  
+        
+       if(len<sizeof(struct udphdr))
+               return;
        
        uh = (struct udphdr *)header;  
    
index 37cf7acb575c7624deb5f6adfda0bb183969c9d3..01f4ccd1f6270ec33321558e0165288ab4660966 100644 (file)
@@ -679,7 +679,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_
  *     Support routines for struct cmsghdr handling
  */
  
-static struct cmsghdr *unix_copyrights(void *userp, int len)
+static struct cmsghdr *unix_copyrights(void *userp, int len) /* AT&T ? */
 {
        struct cmsghdr *cm;
 
@@ -724,9 +724,6 @@ static int unix_fd_copy(struct sock *sk, struct cmsghdr *cmsg, struct file **fp)
                int fd;
                
                fd = fdp[i];    
-#if 0
-               printk("testing  fd %d\n", fd);
-#endif
                if (fd < 0 || fd >= NR_OPEN)
                        return -EBADF;
                if (current->files->fd[fd]==NULL)
@@ -1106,9 +1103,9 @@ static int unix_recvmsg(struct socket *sock, struct msghdr *msg, int size, int n
                                        return copied;
                                if(noblock)
                                        return -EAGAIN;
+                               unix_data_wait(sk);
                                if(current->signal & ~current->blocked)
                                        return -ERESTARTSYS;
-                               unix_data_wait(sk);
                                down(&sk->protinfo.af_unix.readsem);
                                continue;
                        }
@@ -1297,7 +1294,7 @@ struct proto_ops unix_proto_ops = {
 
 void unix_proto_init(struct net_proto *pro)
 {
-       printk(KERN_INFO "NET3: Unix domain sockets 0.12 for Linux NET3.035.\n");
+       printk(KERN_INFO "NET3: Unix domain sockets 0.13 for Linux NET3.035.\n");
        sock_register(unix_proto_ops.family, &unix_proto_ops);
 #ifdef CONFIG_PROC_FS
        proc_net_register(&(struct proc_dir_entry) {