## Automatically generated incremental diff
## From:   linux-2.2.15-pre14
## To:     linux-2.2.15-pre15
## Robot:  $Id: make-incremental-diff,v 1.7 2001/12/04 05:19:54 hpa Exp $

diff -urN linux-2.2.15-pre14/CREDITS linux/CREDITS
--- linux-2.2.15-pre14/CREDITS	Mon Dec  3 22:01:22 2001
+++ linux/CREDITS	Mon Dec  3 22:01:28 2001
@@ -867,7 +867,8 @@
 S: United Kingdom
 
 N: Ron Holt
-E: ron@sovereign.org
+E: ron@holt.org
+E: rholt@netcom.com
 W: http://www.holt.org/
 P: 1024/1FD44539 DF 4B EB 9F 5B 68 38 9A  40 E3 FB 71 D1 C8 0B 56
 D: Kernel development
diff -urN linux-2.2.15-pre14/Documentation/Configure.help linux/Documentation/Configure.help
--- linux-2.2.15-pre14/Documentation/Configure.help	Mon Dec  3 22:01:22 2001
+++ linux/Documentation/Configure.help	Mon Dec  3 22:01:28 2001
@@ -9977,6 +9977,19 @@
   the radio tuner. This is supported in the video4linux
   radio-miropcm20 driver.
 
+Micronas Intermetall MSP 3400 support
+CONFIG_VIDEO_MSP3400
+  This option enables the driver for the Micronas Intermetall MSP 3400 
+  series sound decoder/mixer chips often found on BT848-style TV cards.
+
+  Say Y here if your sound card has a MSP 3400 series sound decoder or 
+  mixer chip.
+
+  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
+  Documentation/modules.txt. The module will be called msp3400.o.
+
 SB32/AWE support
 CONFIG_AWE32_SYNTH
   Say Y here if you have a Sound Blaster SB32, AWE32-PnP, SB AWE64 or
@@ -10610,6 +10623,10 @@
 CONFIG_ISDN_DRV_AVMB1_B1PCI
   Enable support for the PCI version of the AVM B1 card.
 
+AVM B1 PCI V4 support
+CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+  Enable support for the V4 version of AVM B1 PCI card.
+
 AVM T1/T1-B ISA support
 CONFIG_ISDN_DRV_AVMB1_T1ISA
   Enable support for the AVM T1 T1B card.
@@ -10623,6 +10640,11 @@
 CONFIG_ISDN_DRV_AVMB1_T1PCI
   Enable support for the AVM T1 T1B card.
   Note: This is a PRI card and handle 30 B-channels.
+
+AVM C4 support
+CONFIG_ISDN_DRV_AVMB1_C4
+  Enable support for the AVM C4 PCI card.
+  This card handle 4 BRI ISDN lines (8 channels).
 
 Verbose reason code reporting (kernel size +=7K)
 CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
diff -urN linux-2.2.15-pre14/Documentation/isdn/CREDITS linux/Documentation/isdn/CREDITS
--- linux-2.2.15-pre14/Documentation/isdn/CREDITS	Tue Oct 26 17:53:39 1999
+++ linux/Documentation/isdn/CREDITS	Mon Dec  3 22:01:28 2001
@@ -58,9 +58,13 @@
 Max Riegel (riegel@max.franken.de)
   For making the ICN hardware-documentation and test-equipment available.
 
+Armin Schindler (mac@melware.de)
+  For the eicon active card driver.
+
 Gerhard 'Fido' Schneider (fido@wuff.mayn.de)
   For heavy-duty-beta-testing with his BBS ;)
 
 Thomas Uhl (uhl@think.de)
   For distributing the cards.
   For pushing me to work ;-)
+
diff -urN linux-2.2.15-pre14/Documentation/isdn/README linux/Documentation/isdn/README
--- linux-2.2.15-pre14/Documentation/isdn/README	Tue Jan  4 10:12:10 2000
+++ linux/Documentation/isdn/README	Mon Dec  3 22:01:28 2001
@@ -80,8 +80,7 @@
    The functionality is almost the same as that of a serial device
    (the line-discs are handled by the kernel), which lets you run
    SLIP, CSLIP and asynchronous PPP through the devices. We have tested
-   Seyon, minicom, CSLIP (uri-dip) PPP and mgetty (compiled with NO_FAX),
-   XCept.
+   Seyon, minicom, CSLIP (uri-dip) PPP, mgetty, XCept and Hylafax. 
 
    The modem-emulation supports the following:
            1.3.1 Commands:
@@ -124,6 +123,10 @@
                AT&D3    Same as AT&D2 but also resets all registers.
                AT&Ex    Set the EAZ/MSN for this channel to x.
                AT&F     Reset all registers and profile to "factory-defaults"
+               AT&Lx    Set list of phone numbers to listen on.  x is a
+                        list of wildcard patterns separated by semicolon.
+                        If this is set, it has precedence over the MSN set
+                        by AT&E.
                AT&Rx    Select V.110 bitrate adaption.
                         This command enables V.110 protocol with 9600 baud
                         (x=9600), 19200 baud (x=19200) or 38400 baud
@@ -238,7 +241,8 @@
              15   0         Layer-3 protocol:
                                       0 = transparent
                                       1 = transparent with audio features (e.g. DSP)
-                                      2 = Fax G3 (S14 has to be set to 11)
+                                      2 = Fax G3 Class 2 commands (S14 has to be set to 11)
+                                      2 = Fax G3 Class 1 commands (S14 has to be set to 11)
              16   250       Send-Packet-size/16
              17   8         Window-size (not yet implemented)
              18   4         Bit coded register, Service-Octet-1 to accept,
@@ -309,8 +313,6 @@
   If an incoming call matches one network interface, it gets connected to it.
   If another incoming call for the same EAZ arrives, which does not match
   a network interface, the first tty gets a "RING" and so on.
-  As soon as voice gets supported (with the availability of the Diehl-driver),
-  the service-identifier will be evaluated in addition.
 
 2 System prerequisites:
 
diff -urN linux-2.2.15-pre14/Documentation/isdn/README.eicon linux/Documentation/isdn/README.eicon
--- linux-2.2.15-pre14/Documentation/isdn/README.eicon	Tue Jan  4 10:12:10 2000
+++ linux/Documentation/isdn/README.eicon	Mon Dec  3 22:01:28 2001
@@ -1,9 +1,10 @@
-$Id: README.eicon,v 1.5 1999/10/11 18:13:25 armin Exp $
+$Id: README.eicon,v 1.6 2000/01/27 09:54:44 armin Exp $
 
-(c) 1999 Cytronics & Melware (info@melware.de)
+(c) 1999,2000 Armin Schindler (mac@melware.de)
+(c) 1999,2000 Cytronics & Melware (info@melware.de)
 
 This document describes the eicon driver for the
-Eicon.Diehl active ISDN cards.
+Eicon active ISDN cards.
 
 It is meant to be used with isdn4linux, an ISDN link-level module for Linux.
 
@@ -50,7 +51,8 @@
 
 - ETSI (Euro-DSS1) 
 - 1TR6 (German ISDN) *not testet*
-
+- other protocols exist for the range of DIVA Server cards,
+  but they are not fully testet yet.
 
 
 You can load the module simply by using the insmod or modprobe function :
@@ -58,7 +60,7 @@
   insmod eicon [id=driverid] [membase=<membase>] [irq=<irq>]
 
 
-The module will automatically probe the PCI-cards. If the id-options
+The module will automatically probe the PCI-cards. If the id-option
 is omitted, the driver will assume 'eicon0' for the first pci card and
 increases the digit with each further card. With a given driver-id
 the module appends a number starting with '0'.
@@ -84,6 +86,14 @@
 
 Details about using the eiconctrl utility are in 'man eiconctrl'
 or will be printed by starting eiconctrl without any parameters.
+
+ISDNLOG:
+With eicon driver version 1.77 or newer and the eiconctrl utility
+of version 1.1 or better, you can use the isdnlog user program
+with your DIVA Server BRI card.
+Just use "eiconctrl isdnlog on" and the driver will generate
+the necessary D-Channel traces for isdnlog.
+
 
 Thanks to 
 	Deutsche Mailbox Saar-Lor-Lux GmbH
diff -urN linux-2.2.15-pre14/Documentation/isdn/README.x25 linux/Documentation/isdn/README.x25
--- linux-2.2.15-pre14/Documentation/isdn/README.x25	Mon Aug  9 12:04:38 1999
+++ linux/Documentation/isdn/README.x25	Mon Dec  3 22:01:28 2001
@@ -61,7 +61,21 @@
 
 - You might want to access a public X.25 data network from your Linux box.
   You can use i4l if you were physically connected to the X.25 switch
-  by an ISDN line (leased line as well as dial up connection should work)
+  by an ISDN B-channel (leased line as well as dial up connection should
+  work).
+
+  This corresponds to ITU-T recommendation X.31 Case A (circuit-mode
+  access to PSPDN [packet switched public data network]).
+
+  NOTE: X.31 also covers a Case B (access to PSPDN via virtual
+  circuit / packet mode service). The latter mode (which in theory
+  also allows using the D-channel) is not supported by isdn4linux.
+  It should however be possible to establish such packet mode connections
+  with certain active isdn cards provided that the firmware supports X.31
+  and the driver exports this functionality to the user. Currently, 
+  the AVM B1 driver is the only driver which does so. (It should be
+  possible to access D-channel X.31 with active AVM cards using the
+  CAPI interface of the AVM-B1 driver).
 
 - Or you might want to operate certain ISDN teleservices on your linux
   box. A lot of those teleservices run on top of the ISO-8208
diff -urN linux-2.2.15-pre14/Makefile linux/Makefile
--- linux-2.2.15-pre14/Makefile	Mon Dec  3 22:01:22 2001
+++ linux/Makefile	Mon Dec  3 22:01:28 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 2
 SUBLEVEL = 15
-EXTRAVERSION = pre14
+EXTRAVERSION = pre15
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
@@ -282,8 +282,8 @@
 	@echo -n \#define UTS_VERSION \"\#`cat .version` > .ver
 	@if [ -n "$(CONFIG_SMP)" ] ; then echo -n " SMP" >> .ver; fi
 	@if [ -f .name ]; then  echo -n \-`cat .name` >> .ver; fi
-	@echo ' '`date`'"' >> .ver
-	@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> .ver
+	@echo ' '`LANG=C date`'"' >> .ver
+	@echo \#define LINUX_COMPILE_TIME \"`LANG=C date +%T`\" >> .ver
 	@echo \#define LINUX_COMPILE_BY \"`whoami`\" >> .ver
 	@echo \#define LINUX_COMPILE_HOST \"`hostname`\" >> .ver
 	@if [ -x /bin/dnsdomainname ]; then \
diff -urN linux-2.2.15-pre14/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- linux-2.2.15-pre14/arch/sparc/kernel/irq.c	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc/kernel/irq.c	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.93 1999/04/21 06:15:45 anton Exp $
+/*  $Id: irq.c,v 1.93.2.1 2000/02/17 18:05:29 davem Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
diff -urN linux-2.2.15-pre14/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- linux-2.2.15-pre14/arch/sparc/mm/srmmu.c	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc/mm/srmmu.c	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.187.2.8 1999/12/23 01:58:38 davem Exp $
+/* $Id: srmmu.c,v 1.187.2.9 2000/03/05 17:39:18 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/arch/sparc/mm/swift.S linux/arch/sparc/mm/swift.S
--- linux-2.2.15-pre14/arch/sparc/mm/swift.S	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc/mm/swift.S	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/* $Id: swift.S,v 1.1.2.3 1999/10/14 01:00:17 davem Exp $
+/* $Id: swift.S,v 1.1.2.4 2000/03/05 17:39:17 davem Exp $
  * swift.S: MicroSparc-II mmu/cache operations.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
diff -urN linux-2.2.15-pre14/arch/sparc64/kernel/entry.S linux/arch/sparc64/kernel/entry.S
--- linux-2.2.15-pre14/arch/sparc64/kernel/entry.S	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc64/kernel/entry.S	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/* $Id: entry.S,v 1.103.2.4 1999/10/24 17:29:13 davem Exp $
+/* $Id: entry.S,v 1.103.2.5 2000/03/06 22:30:22 davem Exp $
  * arch/sparc64/kernel/entry.S:  Sparc64 trap low-level entry points.
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/arch/sparc64/kernel/head.S linux/arch/sparc64/kernel/head.S
--- linux-2.2.15-pre14/arch/sparc64/kernel/head.S	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc64/kernel/head.S	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.60.2.4 1999/11/12 15:45:47 davem Exp $
+/* $Id: head.S,v 1.60.2.5 2000/03/06 22:30:25 davem Exp $
  * head.S: Initial boot code for the Sparc64 port of Linux.
  *
  * Copyright (C) 1996,1997 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- linux-2.2.15-pre14/arch/sparc64/kernel/setup.c	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc64/kernel/setup.c	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.43.2.2 1999/10/24 17:29:20 davem Exp $
+/*  $Id: setup.c,v 1.43.2.3 2000/03/03 23:50:37 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/arch/sparc64/lib/blockops.S linux/arch/sparc64/lib/blockops.S
--- linux-2.2.15-pre14/arch/sparc64/lib/blockops.S	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc64/lib/blockops.S	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/* $Id: blockops.S,v 1.16.2.1 1999/10/07 20:48:14 davem Exp $
+/* $Id: blockops.S,v 1.16.2.2 2000/03/03 23:50:32 davem Exp $
  * blockops.S: UltraSparc block zero optimized routines.
  *
  * Copyright (C) 1996,1998 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- linux-2.2.15-pre14/arch/sparc64/mm/init.c	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc64/mm/init.c	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.127.2.6 1999/12/05 07:24:42 davem Exp $
+/*  $Id: init.c,v 1.127.2.8 2000/03/03 23:50:41 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/arch/sparc64/mm/ultra.S linux/arch/sparc64/mm/ultra.S
--- linux-2.2.15-pre14/arch/sparc64/mm/ultra.S	Mon Dec  3 22:01:22 2001
+++ linux/arch/sparc64/mm/ultra.S	Mon Dec  3 22:01:28 2001
@@ -1,4 +1,4 @@
-/* $Id: ultra.S,v 1.32.2.1 1999/10/24 17:29:34 davem Exp $
+/* $Id: ultra.S,v 1.32.2.3 2000/03/03 23:50:46 davem Exp $
  * ultra.S: Don't expand these all over the place...
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/drivers/char/Config.in linux/drivers/char/Config.in
--- linux-2.2.15-pre14/drivers/char/Config.in	Mon Dec  3 22:01:22 2001
+++ linux/drivers/char/Config.in	Mon Dec  3 22:01:28 2001
@@ -149,6 +149,10 @@
   fi
   if [ "$CONFIG_PCI" != "n" ]; then
     dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+    if [ "$CONFIG_VIDEO_BT848" != "n" ]; then
+      comment '  MSP3400 sound decoder support is in the section "additional'
+      comment '  low level sound drivers". You may need to enable it there.'
+    fi
   fi
   if [ "$CONFIG_PARPORT" != "n" ]; then
     dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
diff -urN linux-2.2.15-pre14/drivers/isdn/Config.in linux/drivers/isdn/Config.in
--- linux-2.2.15-pre14/drivers/isdn/Config.in	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/Config.in	Mon Dec  3 22:01:29 2001
@@ -89,10 +89,17 @@
 if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
    bool '  AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
    bool '  AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
+   if [ "$CONFIG_ISDN_DRV_AVMB1_B1PCI" != "n" ]; then
+      if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+         bool '  AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+      fi
+   fi
    bool '  AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA
    bool '  AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA
    bool '  AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI
-   bool '  AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4
+   if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+      bool '  AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4
+   fi
    bool '  Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
 fi
 endmenu
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/Makefile linux/drivers/isdn/avmb1/Makefile
--- linux-2.2.15-pre14/drivers/isdn/avmb1/Makefile	Tue Oct 26 17:53:40 1999
+++ linux/drivers/isdn/avmb1/Makefile	Mon Dec  3 22:01:29 2001
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile,v 1.7 1999/09/15 08:16:03 calle Exp $
+# $Id: Makefile,v 1.8 2000/01/25 14:33:38 calle Exp $
 #
 # Makefile for the CAPI and AVM-B1 device drivers.
 #
@@ -11,6 +11,11 @@
 # parent makes..
 #
 # $Log: Makefile,v $
+# Revision 1.8  2000/01/25 14:33:38  calle
+# - Added Support AVM B1 PCI V4.0 (tested with prototype)
+#   - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+#   - support for revision register
+#
 # Revision 1.7  1999/09/15 08:16:03  calle
 # Implementation of 64Bit extention complete.
 #
@@ -99,7 +104,7 @@
   ifdef CONFIG_ISDN_DRV_AVMB1_C4
   O_OBJS   += c4.o
   endif
-  OX_OBJS  += capiutil.o capidrv.o b1.o
+  OX_OBJS  += capiutil.o capidrv.o b1.o b1dma.o
 else
   ifeq ($(CONFIG_ISDN_DRV_AVMB1),m)
   O_TARGET += kernelcapi.o
@@ -123,7 +128,7 @@
   ifdef CONFIG_ISDN_DRV_AVMB1_C4
   M_OBJS   += c4.o
   endif
-  MX_OBJS  += capiutil.o capidrv.o b1.o
+  MX_OBJS  += capiutil.o capidrv.o b1.o b1dma.o
   endif
 endif
 
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/avmcard.h linux/drivers/isdn/avmb1/avmcard.h
--- linux-2.2.15-pre14/drivers/isdn/avmb1/avmcard.h	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/avmcard.h	Mon Dec  3 22:01:29 2001
@@ -1,9 +1,14 @@
 /*
- * $Id: avmcard.h,v 1.6 1999/11/05 16:38:01 calle Exp $
+ * $Id: avmcard.h,v 1.7 2000/01/25 14:33:38 calle Exp $
  *
  * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: avmcard.h,v $
+ * Revision 1.7  2000/01/25 14:33:38  calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ *   - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ *   - support for revision register
+ *
  * Revision 1.6  1999/11/05 16:38:01  calle
  * Cleanups before kernel 2.4:
  * - Changed all messages to use card->name or driver->name instead of
@@ -92,6 +97,8 @@
 	unsigned irq;
 	unsigned long membase;
 	enum avmcardtype cardtype;
+	unsigned char revision;
+	unsigned char class;
 	int cardnr; /* for t1isa */
 
 	char msgbuf[128];	/* capimsg msg part */
@@ -228,8 +235,9 @@
 #define B1_WRITE		0x01
 #define B1_INSTAT		0x02
 #define B1_OUTSTAT		0x03
-#define B1_RESET		0x10
 #define B1_ANALYSE		0x04
+#define B1_REVISION		0x05
+#define B1_RESET		0x10
 
 
 #define B1_STAT0(cardtype)  ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l)
@@ -561,10 +569,13 @@
 	 }
 }
 
+/* b1.c */
 int b1_detect(unsigned int base, enum avmcardtype cardtype);
+void b1_getrevision(avmcard *card);
 int b1_load_t4file(avmcard *card, capiloaddatapart * t4file);
 int b1_load_config(avmcard *card, capiloaddatapart * config);
 int b1_loaded(avmcard *card);
+
 int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
 void b1_reset_ctr(struct capi_ctr *ctrl);
 void b1_register_appl(struct capi_ctr *ctrl, __u16 appl,
@@ -577,5 +588,21 @@
 int b1ctl_read_proc(char *page, char **start, off_t off,
         		int count, int *eof, struct capi_ctr *ctrl);
 
+/* b1dma.c */
+int b1pciv4_detect(avmcard *card);
+int t1pci_detect(avmcard *card);
+void b1dma_reset(avmcard *card);
+void b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs);
+
+int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
+void b1dma_reset_ctr(struct capi_ctr *ctrl);
+void b1dma_remove_ctr(struct capi_ctr *ctrl);
+void b1dma_register_appl(struct capi_ctr *ctrl,
+				__u16 appl,
+				capi_register_params *rp);
+void b1dma_release_appl(struct capi_ctr *ctrl, __u16 appl);
+void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
+int b1dmactl_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, struct capi_ctr *ctrl);
 
 #endif /* _AVMCARD_H_ */
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/b1.c linux/drivers/isdn/avmb1/b1.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/b1.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/b1.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,16 @@
 /*
- * $Id: b1.c,v 1.12 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1.c,v 1.13 2000/01/25 14:33:38 calle Exp $
  * 
  * Common module for AVM B1 cards.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1.c,v $
+ * Revision 1.13  2000/01/25 14:33:38  calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ *   - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ *   - support for revision register
+ *
  * Revision 1.12  1999/11/05 16:38:01  calle
  * Cleanups before kernel 2.4:
  * - Changed all messages to use card->name or driver->name instead of
@@ -86,7 +91,7 @@
 #include "capicmd.h"
 #include "capiutil.h"
 
-static char *revision = "$Revision: 1.12 $";
+static char *revision = "$Revision: 1.13 $";
 
 /* ------------------------------------------------------------- */
 
@@ -158,6 +163,12 @@
 	return 0;
 }
 
+void b1_getrevision(avmcard *card)
+{
+    card->class = inb(card->port + B1_ANALYSE);
+    card->revision = inb(card->port + B1_REVISION);
+}
+
 int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
 {
 	unsigned char buf[256];
@@ -688,6 +699,7 @@
 EXPORT_SYMBOL(b1_irq_table);
 
 EXPORT_SYMBOL(b1_detect);
+EXPORT_SYMBOL(b1_getrevision);
 EXPORT_SYMBOL(b1_load_t4file);
 EXPORT_SYMBOL(b1_load_config);
 EXPORT_SYMBOL(b1_loaded);
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/b1dma.c linux/drivers/isdn/avmb1/b1dma.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/b1dma.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/isdn/avmb1/b1dma.c	Mon Dec  3 22:01:29 2001
@@ -0,0 +1,987 @@
+/*
+ * $Id: b1dma.c,v 1.3 2000/02/26 01:00:53 keil Exp $
+ * 
+ * Common module for AVM B1 cards that support dma with AMCC
+ * 
+ * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de)
+ * 
+ * $Log: b1dma.c,v $
+ * Revision 1.3  2000/02/26 01:00:53  keil
+ * changes from 2.3.47
+ *
+ * Revision 1.2  2000/01/25 14:44:47  calle
+ * typo in b1pciv4_detect().
+ *
+ * Revision 1.1  2000/01/25 14:36:43  calle
+ * common function for  T1 PCI and B1 PCI V4.
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/capi.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "capilli.h"
+#include "avmcard.h"
+#include "capicmd.h"
+#include "capiutil.h"
+
+static char *revision = "$Revision: 1.3 $";
+
+/* ------------------------------------------------------------- */
+
+MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
+
+int suppress_pollack = 0;
+MODULE_PARM(suppress_pollack, "0-1i");
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_dispatch_tx(avmcard *card);
+
+/* ------------------------------------------------------------- */
+
+/* S5933 */
+
+#define	AMCC_RXPTR	0x24
+#define	AMCC_RXLEN	0x28
+#define	AMCC_TXPTR	0x2c
+#define	AMCC_TXLEN	0x30
+
+#define	AMCC_INTCSR	0x38
+#	define EN_READ_TC_INT		0x00008000L
+#	define EN_WRITE_TC_INT		0x00004000L
+#	define EN_TX_TC_INT		EN_READ_TC_INT
+#	define EN_RX_TC_INT		EN_WRITE_TC_INT
+#	define AVM_FLAG			0x30000000L
+
+#	define ANY_S5933_INT		0x00800000L
+#	define	READ_TC_INT		0x00080000L
+#	define WRITE_TC_INT		0x00040000L
+#	define	TX_TC_INT		READ_TC_INT
+#	define	RX_TC_INT		WRITE_TC_INT
+#	define MASTER_ABORT_INT		0x00100000L
+#	define TARGET_ABORT_INT		0x00200000L
+#	define BUS_MASTER_INT		0x00200000L
+#	define ALL_INT			0x000C0000L
+
+#define	AMCC_MCSR	0x3c
+#	define A2P_HI_PRIORITY		0x00000100L
+#	define EN_A2P_TRANSFERS		0x00000400L
+#	define P2A_HI_PRIORITY		0x00001000L
+#	define EN_P2A_TRANSFERS		0x00004000L
+#	define RESET_A2P_FLAGS		0x04000000L
+#	define RESET_P2A_FLAGS		0x02000000L
+
+/* ------------------------------------------------------------- */
+
+#define b1dmaoutmeml(addr, value)	writel(value, addr)
+#define b1dmainmeml(addr)	readl(addr)
+#define b1dmaoutmemw(addr, value)	writew(value, addr)
+#define b1dmainmemw(addr)	readw(addr)
+#define b1dmaoutmemb(addr, value)	writeb(value, addr)
+#define b1dmainmemb(addr)	readb(addr)
+
+/* ------------------------------------------------------------- */
+
+static inline int b1dma_tx_empty(unsigned int port)
+{
+	return inb(port + 0x03) & 0x1;
+}
+
+static inline int b1dma_rx_full(unsigned int port)
+{
+	return inb(port + 0x02) & 0x1;
+}
+
+static int b1dma_tolink(avmcard *card, void *buf, unsigned int len)
+{
+	unsigned long stop = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
+	unsigned char *s = (unsigned char *)buf;
+	while (len--) {
+		while (   !b1dma_tx_empty(card->port)
+		       && time_before(jiffies, stop));
+		if (!b1dma_tx_empty(card->port)) 
+			return -1;
+	        t1outp(card->port, 0x01, *s++);
+	}
+	return 0;
+}
+
+static int b1dma_fromlink(avmcard *card, void *buf, unsigned int len)
+{
+	unsigned long stop = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
+	unsigned char *s = (unsigned char *)buf;
+	while (len--) {
+		while (   !b1dma_rx_full(card->port)
+		       && time_before(jiffies, stop));
+		if (!b1dma_rx_full(card->port)) 
+			return -1;
+	        *s++ = t1inp(card->port, 0x00);
+	}
+	return 0;
+}
+
+static int WriteReg(avmcard *card, __u32 reg, __u8 val)
+{
+	__u8 cmd = 0x00;
+	if (   b1dma_tolink(card, &cmd, 1) == 0
+	    && b1dma_tolink(card, &reg, 4) == 0) {
+		__u32 tmp = val;
+		return b1dma_tolink(card, &tmp, 4);
+	}
+	return -1;
+}
+
+static __u8 ReadReg(avmcard *card, __u32 reg)
+{
+	__u8 cmd = 0x01;
+	if (   b1dma_tolink(card, &cmd, 1) == 0
+	    && b1dma_tolink(card, &reg, 4) == 0) {
+		__u32 tmp;
+		if (b1dma_fromlink(card, &tmp, 4) == 0)
+			return (__u8)tmp;
+	}
+	return 0xff;
+}
+
+/* ------------------------------------------------------------- */
+
+static inline void _put_byte(void **pp, __u8 val)
+{
+	__u8 *s = *pp;
+	*s++ = val;
+	*pp = s;
+}
+
+static inline void _put_word(void **pp, __u32 val)
+{
+	__u8 *s = *pp;
+	*s++ = val & 0xff;
+	*s++ = (val >> 8) & 0xff;
+	*s++ = (val >> 16) & 0xff;
+	*s++ = (val >> 24) & 0xff;
+	*pp = s;
+}
+
+static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len)
+{
+	unsigned i = len;
+	_put_word(pp, i);
+	while (i-- > 0)
+		_put_byte(pp, *dp++);
+}
+
+static inline __u8 _get_byte(void **pp)
+{
+	__u8 *s = *pp;
+	__u8 val;
+	val = *s++;
+	*pp = s;
+	return val;
+}
+
+static inline __u32 _get_word(void **pp)
+{
+	__u8 *s = *pp;
+	__u32 val;
+	val = *s++;
+	val |= (*s++ << 8);
+	val |= (*s++ << 16);
+	val |= (*s++ << 24);
+	*pp = s;
+	return val;
+}
+
+static inline __u32 _get_slice(void **pp, unsigned char *dp)
+{
+	unsigned int len, i;
+
+	len = i = _get_word(pp);
+	while (i-- > 0) *dp++ = _get_byte(pp);
+	return len;
+}
+
+/* ------------------------------------------------------------- */
+
+void b1dma_reset(avmcard *card)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	card->csr = 0x0;
+	b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+	b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+	b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0);
+	b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0);
+
+	t1outp(card->port, 0x10, 0x00);
+	t1outp(card->port, 0x07, 0x00);
+
+	restore_flags(flags);
+
+	b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+	udelay(10 * 1000);
+	b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
+	udelay(10 * 1000);
+	b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+	if (card->cardtype == avm_t1pci)
+		udelay(42 * 1000);
+	else
+		udelay(10 * 1000);
+}
+
+/* ------------------------------------------------------------- */
+
+int b1dma_detect(avmcard *card)
+{
+	b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+	udelay(10 * 1000);
+	b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
+	udelay(10 * 1000);
+	b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
+	udelay(42 * 1000);
+
+	b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0);
+	b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0);
+	card->csr = 0x0;
+	b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+
+	if (b1dmainmeml(card->mbase+AMCC_MCSR) != 0x000000E6)
+		return 1;
+
+	b1dmaoutmeml(card->mbase+AMCC_RXPTR, 0xffffffff);
+	b1dmaoutmeml(card->mbase+AMCC_TXPTR, 0xffffffff);
+	if (   b1dmainmeml(card->mbase+AMCC_RXPTR) != 0xfffffffc
+	    || b1dmainmeml(card->mbase+AMCC_TXPTR) != 0xfffffffc)
+		return 2;
+
+	b1dmaoutmeml(card->mbase+AMCC_RXPTR, 0x0);
+	b1dmaoutmeml(card->mbase+AMCC_TXPTR, 0x0);
+	if (   b1dmainmeml(card->mbase+AMCC_RXPTR) != 0x0
+	    || b1dmainmeml(card->mbase+AMCC_TXPTR) != 0x0)
+		return 3;
+
+	t1outp(card->port, 0x10, 0x00);
+	t1outp(card->port, 0x07, 0x00);
+	
+	t1outp(card->port, 0x02, 0x02);
+	t1outp(card->port, 0x03, 0x02);
+
+	if (   (t1inp(card->port, 0x02) & 0xFE) != 0x02
+	    || t1inp(card->port, 0x3) != 0x03)
+		return 4;
+
+	t1outp(card->port, 0x02, 0x00);
+	t1outp(card->port, 0x03, 0x00);
+
+	if (   (t1inp(card->port, 0x02) & 0xFE) != 0x00
+	    || t1inp(card->port, 0x3) != 0x01)
+		return 5;
+
+	return 0;
+}
+
+int t1pci_detect(avmcard *card)
+{
+	int ret;
+
+	if ((ret = b1dma_detect(card)) != 0)
+		return ret;
+	
+	/* Transputer test */
+	
+	if (   WriteReg(card, 0x80001000, 0x11) != 0
+	    || WriteReg(card, 0x80101000, 0x22) != 0
+	    || WriteReg(card, 0x80201000, 0x33) != 0
+	    || WriteReg(card, 0x80301000, 0x44) != 0)
+		return 6;
+
+	if (   ReadReg(card, 0x80001000) != 0x11
+	    || ReadReg(card, 0x80101000) != 0x22
+	    || ReadReg(card, 0x80201000) != 0x33
+	    || ReadReg(card, 0x80301000) != 0x44)
+		return 7;
+
+	if (   WriteReg(card, 0x80001000, 0x55) != 0
+	    || WriteReg(card, 0x80101000, 0x66) != 0
+	    || WriteReg(card, 0x80201000, 0x77) != 0
+	    || WriteReg(card, 0x80301000, 0x88) != 0)
+		return 8;
+
+	if (   ReadReg(card, 0x80001000) != 0x55
+	    || ReadReg(card, 0x80101000) != 0x66
+	    || ReadReg(card, 0x80201000) != 0x77
+	    || ReadReg(card, 0x80301000) != 0x88)
+		return 9;
+
+	return 0;
+}
+
+int b1pciv4_detect(avmcard *card)
+{
+	int ret, i;
+
+	if ((ret = b1dma_detect(card)) != 0)
+		return ret;
+	
+	for (i=0; i < 5 ; i++) {
+		if (WriteReg(card, 0x80A00000, 0x21) != 0)
+			return 6;
+		if ((ReadReg(card, 0x80A00000) & 0x01) != 0x01)
+			return 7;
+	}
+	for (i=0; i < 5 ; i++) {
+		if (WriteReg(card, 0x80A00000, 0x20) != 0)
+			return 8;
+		if ((ReadReg(card, 0x80A00000) & 0x01) != 0x00)
+			return 9;
+	}
+	
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_dispatch_tx(avmcard *card)
+{
+	avmcard_dmainfo *dma = card->dma;
+	unsigned long flags;
+	struct sk_buff *skb;
+	__u8 cmd, subcmd;
+	__u16 len;
+	__u32 txlen;
+	int inint;
+	void *p;
+	
+	save_flags(flags);
+	cli();
+
+	inint = card->interrupt;
+
+	if (card->csr & EN_TX_TC_INT) { /* tx busy */
+	        restore_flags(flags);
+		return;
+	}
+
+	skb = skb_dequeue(&dma->send_queue);
+	if (!skb) {
+#ifdef CONFIG_B1DMA_DEBUG
+		printk(KERN_DEBUG "tx(%d): underrun\n", inint);
+#endif
+	        restore_flags(flags);
+		return;
+	}
+
+	len = CAPIMSG_LEN(skb->data);
+
+	if (len) {
+		cmd = CAPIMSG_COMMAND(skb->data);
+		subcmd = CAPIMSG_SUBCOMMAND(skb->data);
+
+		p = dma->sendbuf;
+
+		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
+			__u16 dlen = CAPIMSG_DATALEN(skb->data);
+			_put_byte(&p, SEND_DATA_B3_REQ);
+			_put_slice(&p, skb->data, len);
+			_put_slice(&p, skb->data + len, dlen);
+		} else {
+			_put_byte(&p, SEND_MESSAGE);
+			_put_slice(&p, skb->data, len);
+		}
+		txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
+#ifdef CONFIG_B1DMA_DEBUG
+		printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
+				inint, txlen);
+#endif
+	} else {
+		txlen = skb->len-2;
+#ifdef CONFIG_B1DMA_POLLDEBUG
+		if (skb->data[2] == SEND_POLLACK)
+			printk(KERN_INFO "%s: send ack\n", card->name);
+#endif
+#ifdef CONFIG_B1DMA_DEBUG
+		printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
+				inint, skb->data[2], txlen);
+#endif
+		memcpy(dma->sendbuf, skb->data+2, skb->len-2);
+	}
+	txlen = (txlen + 3) & ~3;
+
+	b1dmaoutmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
+	b1dmaoutmeml(card->mbase+AMCC_TXLEN, txlen);
+
+	card->csr |= EN_TX_TC_INT;
+
+	if (!inint)
+		b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+
+	restore_flags(flags);
+	dev_kfree_skb(skb);
+}
+
+/* ------------------------------------------------------------- */
+
+static void queue_pollack(avmcard *card)
+{
+	struct sk_buff *skb;
+	void *p;
+
+	skb = alloc_skb(3, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_CRIT "%s: no memory, lost poll ack\n",
+					card->name);
+		return;
+	}
+	p = skb->data;
+	_put_byte(&p, 0);
+	_put_byte(&p, 0);
+	_put_byte(&p, SEND_POLLACK);
+	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+	skb_queue_tail(&card->dma->send_queue, skb);
+	b1dma_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_handle_rx(avmcard *card)
+{
+	avmctrl_info *cinfo = &card->ctrlinfo[0];
+	avmcard_dmainfo *dma = card->dma;
+	struct capi_ctr *ctrl = cinfo->capi_ctrl;
+	struct sk_buff *skb;
+	void *p = dma->recvbuf+4;
+	__u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
+	__u8 b1cmd =  _get_byte(&p);
+
+#ifdef CONFIG_B1DMA_DEBUG
+	printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen);
+#endif
+	
+	switch (b1cmd) {
+	case RECEIVE_DATA_B3_IND:
+
+		ApplId = (unsigned) _get_word(&p);
+		MsgLen = _get_slice(&p, card->msgbuf);
+		DataB3Len = _get_slice(&p, card->databuf);
+
+		if (MsgLen < 30) { /* not CAPI 64Bit */
+			memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
+			MsgLen = 30;
+			CAPIMSG_SETLEN(card->msgbuf, 30);
+		}
+		if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
+			printk(KERN_ERR "%s: incoming packet dropped\n",
+					card->name);
+		} else {
+			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+			memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
+			ctrl->handle_capimsg(ctrl, ApplId, skb);
+		}
+		break;
+
+	case RECEIVE_MESSAGE:
+
+		ApplId = (unsigned) _get_word(&p);
+		MsgLen = _get_slice(&p, card->msgbuf);
+		if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
+			printk(KERN_ERR "%s: incoming packet dropped\n",
+					card->name);
+		} else {
+			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
+			ctrl->handle_capimsg(ctrl, ApplId, skb);
+		}
+		break;
+
+	case RECEIVE_NEW_NCCI:
+
+		ApplId = _get_word(&p);
+		NCCI = _get_word(&p);
+		WindowSize = _get_word(&p);
+
+		ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
+
+		break;
+
+	case RECEIVE_FREE_NCCI:
+
+		ApplId = _get_word(&p);
+		NCCI = _get_word(&p);
+
+		if (NCCI != 0xffffffff)
+			ctrl->free_ncci(ctrl, ApplId, NCCI);
+		else ctrl->appl_released(ctrl, ApplId);
+		break;
+
+	case RECEIVE_START:
+#ifdef CONFIG_B1DMA_POLLDEBUG
+		printk(KERN_INFO "%s: receive poll\n", card->name);
+#endif
+		if (!suppress_pollack)
+			queue_pollack(card);
+		ctrl->resume_output(ctrl);
+		break;
+
+	case RECEIVE_STOP:
+		ctrl->suspend_output(ctrl);
+		break;
+
+	case RECEIVE_INIT:
+
+		cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
+		b1_parse_version(cinfo);
+		printk(KERN_INFO "%s: %s-card (%s) now active\n",
+		       card->name,
+		       cinfo->version[VER_CARDTYPE],
+		       cinfo->version[VER_DRIVER]);
+		ctrl->ready(ctrl);
+		break;
+
+	case RECEIVE_TASK_READY:
+		ApplId = (unsigned) _get_word(&p);
+		MsgLen = _get_slice(&p, card->msgbuf);
+		card->msgbuf[MsgLen--] = 0;
+		while (    MsgLen >= 0
+		       && (   card->msgbuf[MsgLen] == '\n'
+			   || card->msgbuf[MsgLen] == '\r'))
+			card->msgbuf[MsgLen--] = 0;
+		printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
+				card->name, ApplId, card->msgbuf);
+		break;
+
+	case RECEIVE_DEBUGMSG:
+		MsgLen = _get_slice(&p, card->msgbuf);
+		card->msgbuf[MsgLen--] = 0;
+		while (    MsgLen >= 0
+		       && (   card->msgbuf[MsgLen] == '\n'
+			   || card->msgbuf[MsgLen] == '\r'))
+			card->msgbuf[MsgLen--] = 0;
+		printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
+		break;
+
+	default:
+		printk(KERN_ERR "%s: b1dma_interrupt: 0x%x ???\n",
+				card->name, b1cmd);
+		return;
+	}
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_handle_interrupt(avmcard *card)
+{
+	__u32 status = b1dmainmeml(card->mbase+AMCC_INTCSR);
+	__u32 newcsr;
+
+	if ((status & ANY_S5933_INT) == 0) 
+		return;
+
+        newcsr = card->csr | (status & ALL_INT);
+	if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
+	if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
+	b1dmaoutmeml(card->mbase+AMCC_INTCSR, newcsr);
+
+	if ((status & RX_TC_INT) != 0) {
+		__u8 *recvbuf = card->dma->recvbuf;
+		__u32 rxlen;
+	   	if (card->dma->recvlen == 0) {
+			card->dma->recvlen = *((__u32 *)recvbuf);
+			rxlen = (card->dma->recvlen + 3) & ~3;
+			b1dmaoutmeml(card->mbase+AMCC_RXPTR,
+					virt_to_phys(recvbuf+4));
+			b1dmaoutmeml(card->mbase+AMCC_RXLEN, rxlen);
+		} else {
+			b1dma_handle_rx(card);
+	   		card->dma->recvlen = 0;
+			b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf));
+			b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
+		}
+	}
+
+	if ((status & TX_TC_INT) != 0) {
+		card->csr &= ~EN_TX_TC_INT;
+	        b1dma_dispatch_tx(card);
+	} else if (card->csr & EN_TX_TC_INT) {
+		if (b1dmainmeml(card->mbase+AMCC_TXLEN) == 0) {
+			card->csr &= ~EN_TX_TC_INT;
+			b1dma_dispatch_tx(card);
+		}
+	}
+	b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+}
+
+void b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
+{
+	avmcard *card;
+
+	card = (avmcard *) devptr;
+
+	if (!card) {
+		printk(KERN_WARNING "b1dma: interrupt: wrong device\n");
+		return;
+	}
+	if (card->interrupt) {
+		printk(KERN_ERR "%s: reentering interrupt hander\n", card->name);
+		return;
+	}
+
+	card->interrupt = 1;
+
+	b1dma_handle_interrupt(card);
+
+	card->interrupt = 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1dma_loaded(avmcard *card)
+{
+	unsigned long stop;
+	unsigned char ans;
+	unsigned long tout = 2;
+	unsigned int base = card->port;
+
+	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+		if (b1_tx_empty(base))
+			break;
+	}
+	if (!b1_tx_empty(base)) {
+		printk(KERN_ERR "%s: b1dma_loaded: tx err, corrupted t4 file ?\n",
+				card->name);
+		return 0;
+	}
+	b1_put_byte(base, SEND_POLLACK);
+	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
+		if (b1_rx_full(base)) {
+			if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) {
+				return 1;
+			}
+			printk(KERN_ERR "%s: b1dma_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans);
+			return 0;
+		}
+	}
+	printk(KERN_ERR "%s: b1dma_loaded: firmware not running\n", card->name);
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+static void b1dma_send_init(avmcard *card)
+{
+	struct sk_buff *skb;
+	void *p;
+
+	skb = alloc_skb(15, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_CRIT "%s: no memory, lost register appl.\n",
+					card->name);
+		return;
+	}
+	p = skb->data;
+	_put_byte(&p, 0);
+	_put_byte(&p, 0);
+	_put_byte(&p, SEND_INIT);
+	_put_word(&p, AVM_NAPPS);
+	_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
+	_put_word(&p, card->cardnr - 1);
+	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+	skb_queue_tail(&card->dma->send_queue, skb);
+	b1dma_dispatch_tx(card);
+}
+
+int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	unsigned long flags;
+	int retval;
+
+	b1dma_reset(card);
+
+	if ((retval = b1_load_t4file(card, &data->firmware))) {
+		b1dma_reset(card);
+		printk(KERN_ERR "%s: failed to load t4file!!\n",
+					card->name);
+		return retval;
+	}
+
+	if (data->configuration.len > 0 && data->configuration.data) {
+		if ((retval = b1_load_config(card, &data->configuration))) {
+			b1dma_reset(card);
+			printk(KERN_ERR "%s: failed to load config!!\n",
+					card->name);
+			return retval;
+		}
+	}
+
+	if (!b1dma_loaded(card)) {
+		b1dma_reset(card);
+		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
+		return -EIO;
+	}
+
+	save_flags(flags);
+	cli();
+
+	card->csr = AVM_FLAG;
+	b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+	b1dmaoutmeml(card->mbase+AMCC_MCSR,
+		EN_A2P_TRANSFERS|EN_P2A_TRANSFERS
+		|A2P_HI_PRIORITY|P2A_HI_PRIORITY
+		|RESET_A2P_FLAGS|RESET_P2A_FLAGS);
+	t1outp(card->port, 0x07, 0x30);
+	t1outp(card->port, 0x10, 0xF0);
+
+	card->dma->recvlen = 0;
+	b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf));
+	b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4);
+	card->csr |= EN_RX_TC_INT;
+	b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
+	restore_flags(flags);
+
+        b1dma_send_init(card);
+
+	return 0;
+}
+
+void b1dma_reset_ctr(struct capi_ctr *ctrl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+
+ 	b1dma_reset(card);
+
+	memset(cinfo->version, 0, sizeof(cinfo->version));
+	ctrl->reseted(ctrl);
+}
+
+
+/* ------------------------------------------------------------- */
+
+
+void b1dma_register_appl(struct capi_ctr *ctrl,
+				__u16 appl,
+				capi_register_params *rp)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	struct sk_buff *skb;
+	int want = rp->level3cnt;
+	int nconn;
+	void *p;
+
+	if (want > 0) nconn = want;
+	else nconn = ctrl->profile.nbchannel * -want;
+	if (nconn == 0) nconn = ctrl->profile.nbchannel;
+
+	skb = alloc_skb(23, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_CRIT "%s: no memory, lost register appl.\n",
+					card->name);
+		return;
+	}
+	p = skb->data;
+	_put_byte(&p, 0);
+	_put_byte(&p, 0);
+	_put_byte(&p, SEND_REGISTER);
+	_put_word(&p, appl);
+	_put_word(&p, 1024 * (nconn+1));
+	_put_word(&p, nconn);
+	_put_word(&p, rp->datablkcnt);
+	_put_word(&p, rp->datablklen);
+	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+
+	skb_queue_tail(&card->dma->send_queue, skb);
+	b1dma_dispatch_tx(card);
+
+	ctrl->appl_registered(ctrl, appl);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1dma_release_appl(struct capi_ctr *ctrl, __u16 appl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	struct sk_buff *skb;
+	void *p;
+
+	skb = alloc_skb(7, GFP_ATOMIC);
+	if (!skb) {
+		printk(KERN_CRIT "%s: no memory, lost release appl.\n",
+					card->name);
+		return;
+	}
+	p = skb->data;
+	_put_byte(&p, 0);
+	_put_byte(&p, 0);
+	_put_byte(&p, SEND_RELEASE);
+	_put_word(&p, appl);
+
+	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
+	skb_queue_tail(&card->dma->send_queue, skb);
+	b1dma_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	skb_queue_tail(&card->dma->send_queue, skb);
+	b1dma_dispatch_tx(card);
+}
+
+/* ------------------------------------------------------------- */
+
+int b1dmactl_read_proc(char *page, char **start, off_t off,
+        		int count, int *eof, struct capi_ctr *ctrl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+	unsigned long flags;
+	__u8 flag;
+	int len = 0;
+	char *s;
+	__u32 txaddr, txlen, rxaddr, rxlen, csr;
+
+	len += sprintf(page+len, "%-16s %s\n", "name", card->name);
+	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
+	len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
+	len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
+	switch (card->cardtype) {
+	case avm_b1isa: s = "B1 ISA"; break;
+	case avm_b1pci: s = "B1 PCI"; break;
+	case avm_b1pcmcia: s = "B1 PCMCIA"; break;
+	case avm_m1: s = "M1"; break;
+	case avm_m2: s = "M2"; break;
+	case avm_t1isa: s = "T1 ISA (HEMA)"; break;
+	case avm_t1pci: s = "T1 PCI"; break;
+	case avm_c4: s = "C4"; break;
+	default: s = "???"; break;
+	}
+	len += sprintf(page+len, "%-16s %s\n", "type", s);
+	if ((s = cinfo->version[VER_DRIVER]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
+	if ((s = cinfo->version[VER_CARDTYPE]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
+	if ((s = cinfo->version[VER_SERIAL]) != 0)
+	   len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
+
+	if (card->cardtype != avm_m1) {
+        	flag = ((__u8 *)(ctrl->profile.manu))[3];
+        	if (flag)
+			len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
+			"protocol",
+			(flag & 0x01) ? " DSS1" : "",
+			(flag & 0x02) ? " CT1" : "",
+			(flag & 0x04) ? " VN3" : "",
+			(flag & 0x08) ? " NI1" : "",
+			(flag & 0x10) ? " AUSTEL" : "",
+			(flag & 0x20) ? " ESS" : "",
+			(flag & 0x40) ? " 1TR6" : ""
+			);
+	}
+	if (card->cardtype != avm_m1) {
+        	flag = ((__u8 *)(ctrl->profile.manu))[5];
+		if (flag)
+			len += sprintf(page+len, "%-16s%s%s%s%s\n",
+			"linetype",
+			(flag & 0x01) ? " point to point" : "",
+			(flag & 0x02) ? " point to multipoint" : "",
+			(flag & 0x08) ? " leased line without D-channel" : "",
+			(flag & 0x04) ? " leased line with D-channel" : ""
+			);
+	}
+	len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
+
+	save_flags(flags);
+	cli();
+
+	txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
+	txaddr -= (__u32)card->dma->sendbuf;
+	txlen  = b1dmainmeml(card->mbase+0x30);
+
+	rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24));
+	rxaddr -= (__u32)card->dma->recvbuf;
+	rxlen  = b1dmainmeml(card->mbase+0x28);
+
+	csr  = b1dmainmeml(card->mbase+AMCC_INTCSR);
+
+	restore_flags(flags);
+
+        len += sprintf(page+len, "%-16s 0x%lx\n",
+				"csr (cached)", (unsigned long)card->csr);
+        len += sprintf(page+len, "%-16s 0x%lx\n",
+				"csr", (unsigned long)csr);
+        len += sprintf(page+len, "%-16s %lu\n",
+				"txoff", (unsigned long)txaddr);
+        len += sprintf(page+len, "%-16s %lu\n",
+				"txlen", (unsigned long)txlen);
+        len += sprintf(page+len, "%-16s %lu\n",
+				"rxoff", (unsigned long)rxaddr);
+        len += sprintf(page+len, "%-16s %lu\n",
+				"rxlen", (unsigned long)rxlen);
+
+	if (off+count >= len)
+	   *eof = 1;
+	if (len < off)
+           return 0;
+	*start = page + off;
+	return ((count < len-off) ? count : len-off);
+}
+
+/* ------------------------------------------------------------- */
+
+EXPORT_SYMBOL(b1dma_reset);
+EXPORT_SYMBOL(t1pci_detect);
+EXPORT_SYMBOL(b1pciv4_detect);
+EXPORT_SYMBOL(b1dma_interrupt);
+
+EXPORT_SYMBOL(b1dma_load_firmware);
+EXPORT_SYMBOL(b1dma_reset_ctr);
+EXPORT_SYMBOL(b1dma_register_appl);
+EXPORT_SYMBOL(b1dma_release_appl);
+EXPORT_SYMBOL(b1dma_send_message);
+EXPORT_SYMBOL(b1dmactl_read_proc);
+
+#ifdef MODULE
+#define b1dma_init init_module
+void cleanup_module(void);
+#endif
+
+int b1dma_init(void)
+{
+	char *p;
+	char rev[10];
+
+	if ((p = strchr(revision, ':'))) {
+		strncpy(rev, p + 1, sizeof(rev));
+		p = strchr(rev, '$');
+		*p = 0;
+	} else
+		strcpy(rev, "1.0");
+
+	printk(KERN_INFO "b1dma: revision %s\n", rev);
+
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+}
+#endif
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/b1isa.c linux/drivers/isdn/avmb1/b1isa.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/b1isa.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/b1isa.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,19 @@
 /*
- * $Id: b1isa.c,v 1.5 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1isa.c,v 1.7 2000/02/02 18:36:03 calle Exp $
  * 
  * Module for AVM B1 ISA-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1isa.c,v $
+ * Revision 1.7  2000/02/02 18:36:03  calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.6  2000/01/25 14:37:39  calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
  * Revision 1.5  1999/11/05 16:38:01  calle
  * Cleanups before kernel 2.4:
  * - Changed all messages to use card->name or driver->name instead of
@@ -61,7 +69,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.5 $";
+static char *revision = "$Revision: 1.7 $";
 
 /* ------------------------------------------------------------- */
 
@@ -69,10 +77,6 @@
 
 /* ------------------------------------------------------------- */
 
-static struct capi_driver_interface *di;
-
-/* ------------------------------------------------------------- */
-
 static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
 {
 	avmcard *card;
@@ -96,6 +100,10 @@
 }
 /* ------------------------------------------------------------- */
 
+static struct capi_driver_interface *di;
+
+/* ------------------------------------------------------------- */
+
 static void b1isa_remove_ctr(struct capi_ctr *ctrl)
 {
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
@@ -122,10 +130,13 @@
 	avmcard *card;
 	int retval;
 
+	MOD_INC_USE_COUNT;
+
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
 		printk(KERN_WARNING "b1isa: no memory.\n");
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
@@ -133,6 +144,7 @@
 	if (!cinfo) {
 		printk(KERN_WARNING "b1isa: no memory.\n");
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(cinfo, 0, sizeof(avmctrl_info));
@@ -149,12 +161,14 @@
 		       card->port, card->port + AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 	if (b1_irq_table[card->irq & 0xf] == 0) {
 		printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EINVAL;
 	}
 	if (   card->port != 0x150 && card->port != 0x250
@@ -162,6 +176,7 @@
 		printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EINVAL;
 	}
 	b1_reset(card->port);
@@ -170,9 +185,11 @@
 					card->port, retval);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 	b1_reset(card->port);
+	b1_getrevision(card);
 
 	request_region(p->port, AVMB1_PORTLEN, card->name);
 
@@ -182,6 +199,7 @@
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
@@ -192,10 +210,14 @@
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
-	MOD_INC_USE_COUNT;
+	printk(KERN_INFO
+		"%s: AVM B1 ISA at i/o %#x, irq %d, revision %d\n",
+		driver->name, card->port, card->irq, card->revision);
+
 	return 0;
 }
 
@@ -205,11 +227,12 @@
 
 	if (!cinfo)
 		return "";
-	sprintf(cinfo->infobuf, "%s %s 0x%x %d",
+	sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
 		cinfo->cardname[0] ? cinfo->cardname : "-",
 		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
 		cinfo->card ? cinfo->card->port : 0x0,
-		cinfo->card ? cinfo->card->irq : 0
+		cinfo->card ? cinfo->card->irq : 0,
+		cinfo->card ? cinfo->card->revision : 0
 		);
 	return cinfo->infobuf;
 }
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/b1pci.c linux/drivers/isdn/avmb1/b1pci.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/b1pci.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/b1pci.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,20 @@
 /*
- * $Id: b1pci.c,v 1.18 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1pci.c,v 1.20 2000/02/02 18:36:03 calle Exp $
  * 
  * Module for AVM B1 PCI-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1pci.c,v $
+ * Revision 1.20  2000/02/02 18:36:03  calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.19  2000/01/25 14:33:38  calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ *   - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ *   - support for revision register
+ *
  * Revision 1.18  1999/11/05 16:38:01  calle
  * Cleanups before kernel 2.4:
  * - Changed all messages to use card->name or driver->name instead of
@@ -66,7 +75,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.18 $";
+static char *revision = "$Revision: 1.20 $";
 
 /* ------------------------------------------------------------- */
 
@@ -138,11 +147,12 @@
 
 	if (!cinfo)
 		return "";
-	sprintf(cinfo->infobuf, "%s %s 0x%x %d",
+	sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
 		cinfo->cardname[0] ? cinfo->cardname : "-",
 		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
 		cinfo->card ? cinfo->card->port : 0x0,
-		cinfo->card ? cinfo->card->irq : 0
+		cinfo->card ? cinfo->card->irq : 0,
+		cinfo->card ? cinfo->card->revision : 0
 		);
 	return cinfo->infobuf;
 }
@@ -155,10 +165,13 @@
 	avmctrl_info *cinfo;
 	int retval;
 
+	MOD_INC_USE_COUNT;
+
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
@@ -166,6 +179,7 @@
 	if (!cinfo) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(cinfo, 0, sizeof(avmctrl_info));
@@ -182,6 +196,7 @@
 		       driver->name, card->port, card->port + AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 	b1_reset(card->port);
@@ -190,9 +205,11 @@
 					driver->name, card->port, retval);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 	b1_reset(card->port);
+	b1_getrevision(card);
 
 	request_region(p->port, AVMB1_PORTLEN, card->name);
 
@@ -203,6 +220,7 @@
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
@@ -214,10 +232,19 @@
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
-	MOD_INC_USE_COUNT;
+	if (card->revision >= 4) {
+		printk(KERN_INFO
+			"%s: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n",
+			driver->name, card->port, card->irq, card->revision);
+	} else {
+		printk(KERN_INFO
+			"%s: AVM B1 PCI at i/o %#x, irq %d, revision %d\n",
+			driver->name, card->port, card->irq, card->revision);
+	}
 
 	return 0;
 }
@@ -241,6 +268,187 @@
     0, /* no add_card function */
 };
 
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+/* ------------------------------------------------------------- */
+
+static struct capi_driver_interface *div4;
+
+/* ------------------------------------------------------------- */
+
+static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+	avmcard *card = cinfo->card;
+
+ 	b1dma_reset(card);
+
+	div4->detach_ctr(ctrl);
+	free_irq(card->irq, card);
+	iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+	release_region(card->port, AVMB1_PORTLEN);
+	ctrl->driverdata = 0;
+	kfree(card->ctrlinfo);
+	kfree(card->dma);
+	kfree(card);
+
+	MOD_DEC_USE_COUNT;
+}
+
+static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+	if (!cinfo)
+		return "";
+	sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx r%d",
+		cinfo->cardname[0] ? cinfo->cardname : "-",
+		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
+		cinfo->card ? cinfo->card->port : 0x0,
+		cinfo->card ? cinfo->card->irq : 0,
+		cinfo->card ? cinfo->card->membase : 0,
+		cinfo->card ? cinfo->card->revision : 0
+		);
+	return cinfo->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
+static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p)
+{
+	unsigned long base, page_offset;
+	avmcard *card;
+	avmctrl_info *cinfo;
+	int retval;
+
+	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
+
+	if (!card) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		return -ENOMEM;
+	}
+	memset(card, 0, sizeof(avmcard));
+	card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC);
+	if (!card->dma) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(card->dma, 0, sizeof(avmcard_dmainfo));
+        cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC);
+	if (!cinfo) {
+		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+		kfree(card->dma);
+		kfree(card);
+		return -ENOMEM;
+	}
+	memset(cinfo, 0, sizeof(avmctrl_info));
+	card->ctrlinfo = cinfo;
+	cinfo->card = card;
+	sprintf(card->name, "b1pciv4-%x", p->port);
+	card->port = p->port;
+	card->irq = p->irq;
+	card->membase = p->membase;
+	card->cardtype = avm_b1pci;
+
+	if (check_region(card->port, AVMB1_PORTLEN)) {
+		printk(KERN_WARNING
+		       "%s: ports 0x%03x-0x%03x in use.\n",
+		       driver->name, card->port, card->port + AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	base = card->membase & PAGE_MASK;
+	page_offset = card->membase - base;
+	card->mbase = ioremap_nocache(base, page_offset + 64);
+	if (card->mbase) {
+		card->mbase += page_offset;
+	} else {
+		printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
+					driver->name, card->membase);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EIO;
+	}
+
+	b1dma_reset(card);
+
+	if ((retval = b1pciv4_detect(card)) != 0) {
+		printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
+					driver->name, card->port, retval);
+                iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EIO;
+	}
+	b1dma_reset(card);
+	b1_getrevision(card);
+
+	request_region(p->port, AVMB1_PORTLEN, card->name);
+
+	retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
+	if (retval) {
+		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
+				driver->name, card->irq);
+                iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EBUSY;
+	}
+
+	cinfo->capi_ctrl = div4->attach_ctr(driver, card->name, cinfo);
+	if (!cinfo->capi_ctrl) {
+		printk(KERN_ERR "%s: attach controller failed.\n", driver->name);
+                iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
+		free_irq(card->irq, card);
+		release_region(card->port, AVMB1_PORTLEN);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+		return -EBUSY;
+	}
+	card->cardnr = cinfo->capi_ctrl->cnr;
+
+	skb_queue_head_init(&card->dma->send_queue);
+
+	printk(KERN_INFO
+		"%s: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n",
+		driver->name, card->port, card->irq,
+		card->membase, card->revision);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/* ------------------------------------------------------------- */
+
+
+static struct capi_driver b1pciv4_driver = {
+    "b1pciv4",
+    "0.0",
+    b1dma_load_firmware,
+    b1dma_reset_ctr,
+    b1pciv4_remove_ctr,
+    b1dma_register_appl,
+    b1dma_release_appl,
+    b1dma_send_message,
+
+    b1pciv4_procinfo,
+    b1dmactl_read_proc,
+    0,	/* use standard driver_read_proc */
+
+    0, /* no add_card function */
+};
+
+#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */
+
 #ifdef MODULE
 #define b1pci_init init_module
 void cleanup_module(void);
@@ -248,9 +456,55 @@
 
 static int ncards = 0;
 
+static int add_card(struct pci_dev *dev)
+{
+	struct capi_driver *driver = &b1pci_driver;
+	struct capicardparams param;
+	int retval;
+
+	if (dev->base_address[ 2] & PCI_BASE_ADDRESS_IO_MASK) { /* B1 PCI V4 */
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+		driver = &b1pciv4_driver;
+#endif
+		param.membase = dev->base_address[ 0] & PCI_BASE_ADDRESS_MEM_MASK;
+		param.port = dev->base_address[ 2] & PCI_BASE_ADDRESS_IO_MASK;
+		param.irq = dev->irq;
+		printk(KERN_INFO
+		"%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
+		driver->name, param.port, param.irq, param.membase);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+		retval = b1pciv4_add_card(driver, &param);
+#else
+		retval = b1pci_add_card(driver, &param);
+#endif
+		if (retval != 0) {
+		        printk(KERN_ERR
+			"%s: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n",
+			driver->name, param.port, param.irq, param.membase);
+		}
+	} else {
+		param.membase = 0;
+		param.port = dev->base_address[ 1] & PCI_BASE_ADDRESS_IO_MASK;
+		param.irq = dev->irq;
+		printk(KERN_INFO
+		"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
+		driver->name, param.port, param.irq);
+		retval = b1pci_add_card(driver, &param);
+		if (retval != 0) {
+		        printk(KERN_ERR
+			"%s: no AVM-B1 at i/o %#x, irq %d detected\n",
+			driver->name, param.port, param.irq);
+		}
+	}
+	return retval;
+}
+
 int b1pci_init(void)
 {
 	struct capi_driver *driver = &b1pci_driver;
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+	struct capi_driver *driverv4 = &b1pciv4_driver;
+#endif
 	struct pci_dev *dev = NULL;
 	char *p;
 	int retval;
@@ -271,26 +525,32 @@
 		return -EIO;
 	}
 
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+	printk(KERN_INFO "%s: revision %s\n", driverv4->name, driverv4->revision);
+
+        div4 = attach_capi_driver(driverv4);
+
+	if (!div4) {
+    		detach_capi_driver(driver);
+		printk(KERN_ERR "%s: failed to attach capi_driver\n",
+				driverv4->name);
+		return -EIO;
+	}
+#endif
+
 #ifdef CONFIG_PCI
 	if (!pci_present()) {
 		printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
     		detach_capi_driver(driver);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+    		detach_capi_driver(driverv4);
+#endif
 		return -EIO;
 	}
 
 	while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) {
-		struct capicardparams param;
-
-		param.port = dev->base_address[ 1] & PCI_BASE_ADDRESS_IO_MASK;
-		param.irq = dev->irq;
-		printk(KERN_INFO
-			"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
-			driver->name, param.port, param.irq);
-		retval = b1pci_add_card(driver, &param);
+		retval = add_card(dev);
 		if (retval != 0) {
-		        printk(KERN_ERR
-			"%s: no AVM-B1 at i/o %#x, irq %d detected\n",
-			driver->name, param.port, param.irq);
 #ifdef MODULE
 			cleanup_module();
 #endif
@@ -315,5 +575,8 @@
 void cleanup_module(void)
 {
     detach_capi_driver(&b1pci_driver);
+#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+    detach_capi_driver(&b1pciv4_driver);
+#endif
 }
 #endif
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/b1pcmcia.c linux/drivers/isdn/avmb1/b1pcmcia.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/b1pcmcia.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/b1pcmcia.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,19 @@
 /*
- * $Id: b1pcmcia.c,v 1.5 1999/11/05 16:38:01 calle Exp $
+ * $Id: b1pcmcia.c,v 1.7 2000/02/02 18:36:03 calle Exp $
  * 
  * Module for AVM B1/M1/M2 PCMCIA-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: b1pcmcia.c,v $
+ * Revision 1.7  2000/02/02 18:36:03  calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.6  2000/01/25 14:37:39  calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
  * Revision 1.5  1999/11/05 16:38:01  calle
  * Cleanups before kernel 2.4:
  * - Changed all messages to use card->name or driver->name instead of
@@ -62,7 +70,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.5 $";
+static char *revision = "$Revision: 1.7 $";
 
 /* ------------------------------------------------------------- */
 
@@ -126,12 +134,16 @@
 {
 	avmctrl_info *cinfo;
 	avmcard *card;
+	char *cardname;
 	int retval;
 
+	MOD_INC_USE_COUNT;
+
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
@@ -139,6 +151,7 @@
 	if (!cinfo) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(cinfo, 0, sizeof(avmctrl_info));
@@ -159,9 +172,11 @@
 					driver->name, card->port, retval);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 	b1_reset(card->port);
+	b1_getrevision(card);
 
 	retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card);
 	if (retval) {
@@ -169,6 +184,7 @@
 				driver->name, card->irq);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
@@ -179,10 +195,19 @@
 		free_irq(card->irq, card);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
+	switch (cardtype) {
+		case avm_m1: cardname = "M1"; break;
+		case avm_m2: cardname = "M2"; break;
+		default    : cardname = "B1 PCMCIA"; break;
+	}
+
+	printk(KERN_INFO
+		"%s: AVM %s at i/o %#x, irq %d, revision %d\n",
+		driver->name, cardname, card->port, card->irq, card->revision);
 
-	MOD_INC_USE_COUNT;
 	return cinfo->capi_ctrl->cnr;
 }
 
@@ -194,11 +219,12 @@
 
 	if (!cinfo)
 		return "";
-	sprintf(cinfo->infobuf, "%s %s 0x%x %d",
+	sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d",
 		cinfo->cardname[0] ? cinfo->cardname : "-",
 		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
 		cinfo->card ? cinfo->card->port : 0x0,
-		cinfo->card ? cinfo->card->irq : 0
+		cinfo->card ? cinfo->card->irq : 0,
+		cinfo->card ? cinfo->card->revision : 0
 		);
 	return cinfo->infobuf;
 }
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/c4.c linux/drivers/isdn/avmb1/c4.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/c4.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/avmb1/c4.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,22 @@
 /*
- * $Id: c4.c,v 1.2 2000/01/21 20:52:58 keil Exp $
+ * $Id: c4.c,v 1.5 2000/03/16 15:21:03 calle Exp $
  * 
  * Module for AVM C4 card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: c4.c,v $
+ * Revision 1.5  2000/03/16 15:21:03  calle
+ * Bugfix in c4_remove: loop 5 times instead of 4 :-(
+ *
+ * Revision 1.4  2000/02/02 18:36:03  calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.3  2000/01/25 14:37:39  calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
  * Revision 1.2  2000/01/21 20:52:58  keil
  * pci_find_subsys as local function for 2.2.X kernel
  *
@@ -32,7 +43,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.2 $";
+static char *revision = "$Revision: 1.5 $";
 
 #undef CONFIG_C4_DEBUG
 #undef CONFIG_C4_POLLDEBUG
@@ -896,7 +907,7 @@
 
  	c4_reset(card);
 
-        for (i=0; i <= 4; i++) {
+        for (i=0; i < 4; i++) {
 		cinfo = &card->ctrlinfo[i];
 		if (cinfo->capi_ctrl)
 			di->detach_ctr(cinfo->capi_ctrl);
@@ -1085,16 +1096,19 @@
 
 static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
 {
-	unsigned long page_offset, base;
+	unsigned long base, page_offset;
 	avmctrl_info *cinfo;
 	avmcard *card;
 	int retval;
 	int i;
 
+	MOD_INC_USE_COUNT;
+
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
@@ -1102,6 +1116,7 @@
 	if (!card->dma) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card->dma, 0, sizeof(avmcard_dmainfo));
@@ -1111,6 +1126,7 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(cinfo, 0, sizeof(avmctrl_info)*4);
@@ -1132,12 +1148,24 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
-        base = card->membase & PAGE_MASK;
+	base = card->membase & PAGE_MASK;
 	page_offset = card->membase - base;
-	card->mbase = ioremap_nocache(base, page_offset + 64);
+	card->mbase = ioremap_nocache(base, page_offset + 128);
+	if (card->mbase) {
+		card->mbase += page_offset;
+	} else {
+		printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
+					driver->name, card->membase);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+	        MOD_DEC_USE_COUNT;
+		return -EIO;
+	}
 
 	if ((retval = c4_detect(card)) != 0) {
 		printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
@@ -1146,6 +1174,7 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 	c4_reset(card);
@@ -1161,6 +1190,7 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
@@ -1181,6 +1211,7 @@
 	        	kfree(card->dma);
 	        	kfree(card->ctrlinfo);
 			kfree(card);
+	        	MOD_DEC_USE_COUNT;
 			return -EBUSY;
 		}
 		if (i == 0)
@@ -1189,7 +1220,9 @@
 
 	skb_queue_head_init(&card->dma->send_queue);
 
-	MOD_INC_USE_COUNT;
+	printk(KERN_INFO
+		"%s: AVM C4 at i/o %#x, irq %d, mem %#lx\n",
+		driver->name, card->port, card->irq, card->membase);
 
 	return 0;
 }
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/capi.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/capi.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,14 @@
 /*
- * $Id: capi.c,v 1.22 1999/11/13 21:27:16 keil Exp $
+ * $Id: capi.c,v 1.23 2000/02/26 01:00:53 keil Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capi.c,v $
+ * Revision 1.23  2000/02/26 01:00:53  keil
+ * changes from 2.3.47
+ *
  * Revision 1.22  1999/11/13 21:27:16  keil
  * remove KERNELVERSION
  *
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/kcapi.c linux/drivers/isdn/avmb1/kcapi.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/kcapi.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/kcapi.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,15 @@
 /*
- * $Id: kcapi.c,v 1.11 1999/11/23 13:29:29 calle Exp $
+ * $Id: kcapi.c,v 1.12 2000/01/28 16:45:39 calle Exp $
  * 
  * Kernel CAPI 2.0 Module
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: kcapi.c,v $
+ * Revision 1.12  2000/01/28 16:45:39  calle
+ * new manufacturer command KCAPI_CMD_ADDCARD (generic addcard),
+ * will search named driver and call the add_card function if one exist.
+ *
  * Revision 1.11  1999/11/23 13:29:29  calle
  * Bugfix: incoming capi message were never traced.
  *
@@ -82,7 +86,7 @@
 #include <linux/b1lli.h>
 #endif
 
-static char *revision = "$Revision: 1.11 $";
+static char *revision = "$Revision: 1.12 $";
 
 /* ------------------------------------------------------------- */
 
@@ -157,10 +161,6 @@
 static struct sk_buff_head recv_queue;
 static struct capi_interface_user *capi_users = 0;
 static struct capi_driver *drivers;
-#ifdef CONFIG_AVMB1_COMPAT
-static struct capi_driver *b1isa_driver;
-static struct capi_driver *t1isa_driver;
-#endif
 static long notify_up_set = 0;
 static long notify_down_set = 0;
 
@@ -956,12 +956,6 @@
 	driver->next = 0;
 	*pp = driver;
 	printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name);
-#ifdef CONFIG_AVMB1_COMPAT
-        if (strcmp(driver->name, "b1isa") == 0 && driver->add_card)
-		b1isa_driver = driver;
-        if (strcmp(driver->name, "t1isa") == 0 && driver->add_card)
-		t1isa_driver = driver;
-#endif
 	sprintf(driver->procfn, "capi/drivers/%s", driver->name);
 	driver->procent = create_proc_entry(driver->procfn, 0, 0);
 	if (driver->procent) {
@@ -983,10 +977,6 @@
 	for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ;
 	if (*pp) {
 		*pp = (*pp)->next;
-#ifdef CONFIG_AVMB1_COMPAT
-		if (driver == b1isa_driver) b1isa_driver = 0;
-		if (driver == t1isa_driver) t1isa_driver = 0;
-#endif
 		printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name);
 	} else {
 		printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name);
@@ -1201,6 +1191,15 @@
 	return CAPI_NOERROR;
 }
 
+static struct capi_driver *find_driver(char *name)
+{
+	struct capi_driver *dp;
+	for (dp = drivers; dp; dp = dp->next)
+		if (strcmp(dp->name, name) == 0)
+			return dp;
+	return 0;
+}
+
 #ifdef CONFIG_AVMB1_COMPAT
 static int old_capi_manufacturer(unsigned int cmd, void *data)
 {
@@ -1232,9 +1231,15 @@
 		cparams.cardnr = cdef.cardnr;
 
                 switch (cdef.cardtype) {
-			case AVM_CARDTYPE_B1: driver = b1isa_driver; break;
-			case AVM_CARDTYPE_T1: driver = t1isa_driver; break;
-			default: driver = 0;
+			case AVM_CARDTYPE_B1:
+				driver = find_driver("b1isa");
+				break;
+			case AVM_CARDTYPE_T1:
+				driver = find_driver("t1isa");
+				break;
+			default:
+				driver = 0;
+				break;
 		}
 		if (!driver) {
 			printk(KERN_ERR "kcapi: driver not loaded.\n");
@@ -1346,9 +1351,7 @@
 			return -ESRCH;
 
 		gdef.cardstate = card->cardstate;
-		if (card->driver == b1isa_driver)
-			gdef.cardtype = AVM_CARDTYPE_B1;
-		else if (card->driver == t1isa_driver)
+		if (card->driver == find_driver("t1isa"))
 			gdef.cardtype = AVM_CARDTYPE_T1;
 		else gdef.cardtype = AVM_CARDTYPE_B1;
 
@@ -1392,7 +1395,6 @@
 static int capi_manufacturer(unsigned int cmd, void *data)
 {
         struct capi_ctr *card;
-	kcapi_flagdef fdef;
 	int retval;
 
 	switch (cmd) {
@@ -1407,6 +1409,9 @@
 		return old_capi_manufacturer(cmd, data);
 #endif
 	case KCAPI_CMD_TRACE:
+	{
+		kcapi_flagdef fdef;
+
 		if ((retval = copy_from_user((void *) &fdef, data,
 					 sizeof(kcapi_flagdef))))
 			return retval;
@@ -1420,6 +1425,44 @@
 		printk(KERN_INFO "kcapi: contr %d set trace=%d\n",
 			card->cnr, card->traceflag);
 		return 0;
+	}
+
+	case KCAPI_CMD_ADDCARD:
+	{
+		struct capi_driver *driver;
+		capicardparams cparams;
+		kcapi_carddef cdef;
+
+		if ((retval = copy_from_user((void *) &cdef, data,
+							sizeof(cdef))))
+			return retval;
+
+		cparams.port = cdef.port;
+		cparams.irq = cdef.irq;
+		cparams.membase = cdef.membase;
+		cparams.cardnr = cdef.cardnr;
+		cparams.cardtype = 0;
+		cdef.driver[sizeof(cdef.driver)-1] = 0;
+
+		if ((driver = find_driver(cdef.driver)) == 0) {
+			printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n",
+					cdef.driver);
+			return -ESRCH;
+		}
+
+		if (!driver->add_card) {
+			printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver);
+			return -EIO;
+		}
+
+		return driver->add_card(driver, &cparams);
+	}
+
+	default:
+		printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n",
+					cmd);
+		break;
+
 	}
 	return -EINVAL;
 }
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/t1isa.c linux/drivers/isdn/avmb1/t1isa.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/t1isa.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/avmb1/t1isa.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,19 @@
 /*
- * $Id: t1isa.c,v 1.8 1999/11/05 16:38:01 calle Exp $
+ * $Id: t1isa.c,v 1.10 2000/02/02 18:36:04 calle Exp $
  * 
  * Module for AVM T1 HEMA-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: t1isa.c,v $
+ * Revision 1.10  2000/02/02 18:36:04  calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.9  2000/01/25 14:37:39  calle
+ * new message after successfull detection including card revision and
+ * used resources.
+ *
  * Revision 1.8  1999/11/05 16:38:01  calle
  * Cleanups before kernel 2.4:
  * - Changed all messages to use card->name or driver->name instead of
@@ -73,7 +81,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.8 $";
+static char *revision = "$Revision: 1.10 $";
 
 /* ------------------------------------------------------------- */
 
@@ -413,10 +421,13 @@
 	avmcard *card;
 	int retval;
 
+	MOD_INC_USE_COUNT;
+
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
@@ -424,6 +435,7 @@
 	if (!cinfo) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(cinfo, 0, sizeof(avmctrl_info));
@@ -440,6 +452,7 @@
 				driver->name, card->port);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EINVAL;
         }
 
@@ -449,6 +462,7 @@
 		       driver->name, card->port, card->port + AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 	if (hema_irq_table[card->irq & 0xf] == 0) {
@@ -456,6 +470,7 @@
 				driver->name, card->irq);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EINVAL;
 	}
 	for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) {
@@ -465,6 +480,7 @@
 					driver->name, card->cardnr, cardp->port);
 	                kfree(card->ctrlinfo);
 			kfree(card);
+	        	MOD_DEC_USE_COUNT;
 			return -EBUSY;
 		}
 	}
@@ -473,6 +489,7 @@
 					driver->name, card->port, retval);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+		MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
 	t1_disable_irq(card->port);
@@ -487,6 +504,7 @@
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+		MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
@@ -498,10 +516,14 @@
 		release_region(card->port, AVMB1_PORTLEN);
 	        kfree(card->ctrlinfo);
 		kfree(card);
+		MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
-	MOD_INC_USE_COUNT;
+	printk(KERN_INFO
+		"%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n",
+		driver->name, card->port, card->irq, card->cardnr);
+
 	return 0;
 }
 
diff -urN linux-2.2.15-pre14/drivers/isdn/avmb1/t1pci.c linux/drivers/isdn/avmb1/t1pci.c
--- linux-2.2.15-pre14/drivers/isdn/avmb1/t1pci.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/avmb1/t1pci.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,20 @@
 /*
- * $Id: t1pci.c,v 1.3 1999/11/13 21:27:16 keil Exp $
+ * $Id: t1pci.c,v 1.5 2000/02/02 18:36:04 calle Exp $
  * 
  * Module for AVM T1 PCI-card.
  * 
  * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: t1pci.c,v $
+ * Revision 1.5  2000/02/02 18:36:04  calle
+ * - Modules are now locked while init_module is running
+ * - fixed problem with memory mapping if address is not aligned
+ *
+ * Revision 1.4  2000/01/25 14:33:38  calle
+ * - Added Support AVM B1 PCI V4.0 (tested with prototype)
+ *   - splitted up t1pci.c into b1dma.c for common function with b1pciv4
+ *   - support for revision register
+ *
  * Revision 1.3  1999/11/13 21:27:16  keil
  * remove KERNELVERSION
  *
@@ -38,7 +47,7 @@
 #include "capilli.h"
 #include "avmcard.h"
 
-static char *revision = "$Revision: 1.3 $";
+static char *revision = "$Revision: 1.5 $";
 
 #undef CONFIG_T1PCI_DEBUG
 #undef CONFIG_T1PCI_POLLDEBUG
@@ -55,712 +64,20 @@
 
 /* ------------------------------------------------------------- */
 
-static int suppress_pollack = 0;
-
 MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
 
-MODULE_PARM(suppress_pollack, "0-1i");
-
-
 /* ------------------------------------------------------------- */
 
 static struct capi_driver_interface *di;
 
 /* ------------------------------------------------------------- */
 
-static void t1pci_dispatch_tx(avmcard *card);
-
-/* ------------------------------------------------------------- */
-
-/* S5933 */
-
-#define	AMCC_RXPTR	0x24
-#define	AMCC_RXLEN	0x28
-#define	AMCC_TXPTR	0x2c
-#define	AMCC_TXLEN	0x30
-
-#define	AMCC_INTCSR	0x38
-#	define EN_READ_TC_INT		0x00008000L
-#	define EN_WRITE_TC_INT		0x00004000L
-#	define EN_TX_TC_INT		EN_READ_TC_INT
-#	define EN_RX_TC_INT		EN_WRITE_TC_INT
-#	define AVM_FLAG			0x30000000L
-
-#	define ANY_S5933_INT		0x00800000L
-#	define	READ_TC_INT		0x00080000L
-#	define WRITE_TC_INT		0x00040000L
-#	define	TX_TC_INT		READ_TC_INT
-#	define	RX_TC_INT		WRITE_TC_INT
-#	define MASTER_ABORT_INT		0x00100000L
-#	define TARGET_ABORT_INT		0x00200000L
-#	define BUS_MASTER_INT		0x00200000L
-#	define ALL_INT			0x000C0000L
-
-#define	AMCC_MCSR	0x3c
-#	define A2P_HI_PRIORITY		0x00000100L
-#	define EN_A2P_TRANSFERS		0x00000400L
-#	define P2A_HI_PRIORITY		0x00001000L
-#	define EN_P2A_TRANSFERS		0x00004000L
-#	define RESET_A2P_FLAGS		0x04000000L
-#	define RESET_P2A_FLAGS		0x02000000L
-
-/* ------------------------------------------------------------- */
-
-#define t1outmeml(addr, value)	writel(value, addr)
-#define t1inmeml(addr)	readl(addr)
-#define t1outmemw(addr, value)	writew(value, addr)
-#define t1inmemw(addr)	readw(addr)
-#define t1outmemb(addr, value)	writeb(value, addr)
-#define t1inmemb(addr)	readb(addr)
-
-/* ------------------------------------------------------------- */
-
-static inline int t1pci_tx_empty(unsigned int port)
-{
-	return inb(port + 0x03) & 0x1;
-}
-
-static inline int t1pci_rx_full(unsigned int port)
-{
-	return inb(port + 0x02) & 0x1;
-}
-
-static int t1pci_tolink(avmcard *card, void *buf, unsigned int len)
-{
-	unsigned long stop = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
-	unsigned char *s = (unsigned char *)buf;
-	while (len--) {
-		while (   !t1pci_tx_empty(card->port)
-		       && time_before(jiffies, stop));
-		if (!t1pci_tx_empty(card->port)) 
-			return -1;
-	        t1outp(card->port, 0x01, *s++);
-	}
-	return 0;
-}
-
-static int t1pci_fromlink(avmcard *card, void *buf, unsigned int len)
-{
-	unsigned long stop = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
-	unsigned char *s = (unsigned char *)buf;
-	while (len--) {
-		while (   !t1pci_rx_full(card->port)
-		       && time_before(jiffies, stop));
-		if (!t1pci_rx_full(card->port)) 
-			return -1;
-	        *s++ = t1inp(card->port, 0x00);
-	}
-	return 0;
-}
-
-static int WriteReg(avmcard *card, __u32 reg, __u8 val)
-{
-	__u8 cmd = 0x00;
-	if (   t1pci_tolink(card, &cmd, 1) == 0
-	    && t1pci_tolink(card, &reg, 4) == 0) {
-		__u32 tmp = val;
-		return t1pci_tolink(card, &tmp, 4);
-	}
-	return -1;
-}
-
-static __u8 ReadReg(avmcard *card, __u32 reg)
-{
-	__u8 cmd = 0x01;
-	if (   t1pci_tolink(card, &cmd, 1) == 0
-	    && t1pci_tolink(card, &reg, 4) == 0) {
-		__u32 tmp;
-		if (t1pci_fromlink(card, &tmp, 4) == 0)
-			return (__u8)tmp;
-	}
-	return 0xff;
-}
-
-/* ------------------------------------------------------------- */
-
-static inline void _put_byte(void **pp, __u8 val)
-{
-	__u8 *s = *pp;
-	*s++ = val;
-	*pp = s;
-}
-
-static inline void _put_word(void **pp, __u32 val)
-{
-	__u8 *s = *pp;
-	*s++ = val & 0xff;
-	*s++ = (val >> 8) & 0xff;
-	*s++ = (val >> 16) & 0xff;
-	*s++ = (val >> 24) & 0xff;
-	*pp = s;
-}
-
-static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len)
-{
-	unsigned i = len;
-	_put_word(pp, i);
-	while (i-- > 0)
-		_put_byte(pp, *dp++);
-}
-
-static inline __u8 _get_byte(void **pp)
-{
-	__u8 *s = *pp;
-	__u8 val;
-	val = *s++;
-	*pp = s;
-	return val;
-}
-
-static inline __u32 _get_word(void **pp)
-{
-	__u8 *s = *pp;
-	__u32 val;
-	val = *s++;
-	val |= (*s++ << 8);
-	val |= (*s++ << 16);
-	val |= (*s++ << 24);
-	*pp = s;
-	return val;
-}
-
-static inline __u32 _get_slice(void **pp, unsigned char *dp)
-{
-	unsigned int len, i;
-
-	len = i = _get_word(pp);
-	while (i-- > 0) *dp++ = _get_byte(pp);
-	return len;
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_reset(avmcard *card)
-{
-	unsigned long flags;
-
-	save_flags(flags);
-	cli();
-	card->csr = 0x0;
-	t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-	t1outmeml(card->mbase+AMCC_MCSR, 0);
-	t1outmeml(card->mbase+AMCC_RXLEN, 0);
-	t1outmeml(card->mbase+AMCC_TXLEN, 0);
-
-	t1outp(card->port, T1_RESETLINK, 0x00);
-	t1outp(card->port, 0x07, 0x00);
-
-	restore_flags(flags);
-
-	t1outmeml(card->mbase+AMCC_MCSR, 0);
-	udelay(10 * 1000);
-	t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
-	udelay(10 * 1000);
-	t1outmeml(card->mbase+AMCC_MCSR, 0);
-	udelay(42 * 1000);
-
-}
-
-/* ------------------------------------------------------------- */
-
-static int t1pci_detect(avmcard *card)
-{
-	t1outmeml(card->mbase+AMCC_MCSR, 0);
-	udelay(10 * 1000);
-	t1outmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
-	udelay(10 * 1000);
-	t1outmeml(card->mbase+AMCC_MCSR, 0);
-	udelay(42 * 1000);
-
-	t1outmeml(card->mbase+AMCC_RXLEN, 0);
-	t1outmeml(card->mbase+AMCC_TXLEN, 0);
-	card->csr = 0x0;
-	t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-
-	if (t1inmeml(card->mbase+AMCC_MCSR) != 0x000000E6)
-		return 1;
-
-	t1outmeml(card->mbase+AMCC_RXPTR, 0xffffffff);
-	t1outmeml(card->mbase+AMCC_TXPTR, 0xffffffff);
-	if (   t1inmeml(card->mbase+AMCC_RXPTR) != 0xfffffffc
-	    || t1inmeml(card->mbase+AMCC_TXPTR) != 0xfffffffc)
-		return 2;
-
-	t1outmeml(card->mbase+AMCC_RXPTR, 0x0);
-	t1outmeml(card->mbase+AMCC_TXPTR, 0x0);
-	if (   t1inmeml(card->mbase+AMCC_RXPTR) != 0x0
-	    || t1inmeml(card->mbase+AMCC_TXPTR) != 0x0)
-		return 3;
-
-	t1outp(card->port, T1_RESETLINK, 0x00);
-	t1outp(card->port, 0x07, 0x00);
-	
-	t1outp(card->port, 0x02, 0x02);
-	t1outp(card->port, 0x03, 0x02);
-
-	if (   (t1inp(card->port, 0x02) & 0xFE) != 0x02
-	    || t1inp(card->port, 0x3) != 0x03)
-		return 4;
-
-	t1outp(card->port, 0x02, 0x00);
-	t1outp(card->port, 0x03, 0x00);
-
-	if (   (t1inp(card->port, 0x02) & 0xFE) != 0x00
-	    || t1inp(card->port, 0x3) != 0x01)
-		return 5;
-
-	/* Transputer test */
-	
-	if (   WriteReg(card, 0x80001000, 0x11) != 0
-	    || WriteReg(card, 0x80101000, 0x22) != 0
-	    || WriteReg(card, 0x80201000, 0x33) != 0
-	    || WriteReg(card, 0x80301000, 0x44) != 0)
-		return 6;
-
-	if (   ReadReg(card, 0x80001000) != 0x11
-	    || ReadReg(card, 0x80101000) != 0x22
-	    || ReadReg(card, 0x80201000) != 0x33
-	    || ReadReg(card, 0x80301000) != 0x44)
-		return 7;
-
-	if (   WriteReg(card, 0x80001000, 0x55) != 0
-	    || WriteReg(card, 0x80101000, 0x66) != 0
-	    || WriteReg(card, 0x80201000, 0x77) != 0
-	    || WriteReg(card, 0x80301000, 0x88) != 0)
-		return 8;
-
-	if (   ReadReg(card, 0x80001000) != 0x55
-	    || ReadReg(card, 0x80101000) != 0x66
-	    || ReadReg(card, 0x80201000) != 0x77
-	    || ReadReg(card, 0x80301000) != 0x88)
-		return 9;
-
-	return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_dispatch_tx(avmcard *card)
-{
-	avmcard_dmainfo *dma = card->dma;
-	unsigned long flags;
-	struct sk_buff *skb;
-	__u8 cmd, subcmd;
-	__u16 len;
-	__u32 txlen;
-	int inint;
-	void *p;
-	
-	save_flags(flags);
-	cli();
-
-	inint = card->interrupt;
-
-	if (card->csr & EN_TX_TC_INT) { /* tx busy */
-	        restore_flags(flags);
-		return;
-	}
-
-	skb = skb_dequeue(&dma->send_queue);
-	if (!skb) {
-#ifdef CONFIG_T1PCI_DEBUG
-		printk(KERN_DEBUG "tx(%d): underrun\n", inint);
-#endif
-	        restore_flags(flags);
-		return;
-	}
-
-	len = CAPIMSG_LEN(skb->data);
-
-	if (len) {
-		cmd = CAPIMSG_COMMAND(skb->data);
-		subcmd = CAPIMSG_SUBCOMMAND(skb->data);
-
-		p = dma->sendbuf;
-
-		if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
-			__u16 dlen = CAPIMSG_DATALEN(skb->data);
-			_put_byte(&p, SEND_DATA_B3_REQ);
-			_put_slice(&p, skb->data, len);
-			_put_slice(&p, skb->data + len, dlen);
-		} else {
-			_put_byte(&p, SEND_MESSAGE);
-			_put_slice(&p, skb->data, len);
-		}
-		txlen = (__u8 *)p - (__u8 *)dma->sendbuf;
-#ifdef CONFIG_T1PCI_DEBUG
-		printk(KERN_DEBUG "tx(%d): put msg len=%d\n",
-				inint, txlen);
-#endif
-	} else {
-		txlen = skb->len-2;
-#ifdef CONFIG_T1PCI_POLLDEBUG
-		if (skb->data[2] == SEND_POLLACK)
-			printk(KERN_INFO "%s: ack to t1\n", card->name);
-#endif
-#ifdef CONFIG_T1PCI_DEBUG
-		printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n",
-				inint, skb->data[2], txlen);
-#endif
-		memcpy(dma->sendbuf, skb->data+2, skb->len-2);
-	}
-	txlen = (txlen + 3) & ~3;
-
-	t1outmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf));
-	t1outmeml(card->mbase+AMCC_TXLEN, txlen);
-
-	card->csr |= EN_TX_TC_INT;
-
-	if (!inint)
-		t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-
-	restore_flags(flags);
-	dev_kfree_skb(skb);
-}
-
-/* ------------------------------------------------------------- */
-
-static void queue_pollack(avmcard *card)
-{
-	struct sk_buff *skb;
-	void *p;
-
-	skb = alloc_skb(3, GFP_ATOMIC);
-	if (!skb) {
-		printk(KERN_CRIT "%s: no memory, lost poll ack\n",
-					card->name);
-		return;
-	}
-	p = skb->data;
-	_put_byte(&p, 0);
-	_put_byte(&p, 0);
-	_put_byte(&p, SEND_POLLACK);
-	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
-
-	skb_queue_tail(&card->dma->send_queue, skb);
-	t1pci_dispatch_tx(card);
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_handle_rx(avmcard *card)
-{
-	avmctrl_info *cinfo = &card->ctrlinfo[0];
-	avmcard_dmainfo *dma = card->dma;
-	struct capi_ctr *ctrl = cinfo->capi_ctrl;
-	struct sk_buff *skb;
-	void *p = dma->recvbuf+4;
-	__u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize;
-	__u8 b1cmd =  _get_byte(&p);
-
-#ifdef CONFIG_T1PCI_DEBUG
-	printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen);
-#endif
-	
-	switch (b1cmd) {
-	case RECEIVE_DATA_B3_IND:
-
-		ApplId = (unsigned) _get_word(&p);
-		MsgLen = _get_slice(&p, card->msgbuf);
-		DataB3Len = _get_slice(&p, card->databuf);
-
-		if (MsgLen < 30) { /* not CAPI 64Bit */
-			memset(card->msgbuf+MsgLen, 0, 30-MsgLen);
-			MsgLen = 30;
-			CAPIMSG_SETLEN(card->msgbuf, 30);
-		}
-		if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) {
-			printk(KERN_ERR "%s: incoming packet dropped\n",
-					card->name);
-		} else {
-			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
-			memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len);
-			ctrl->handle_capimsg(ctrl, ApplId, skb);
-		}
-		break;
-
-	case RECEIVE_MESSAGE:
-
-		ApplId = (unsigned) _get_word(&p);
-		MsgLen = _get_slice(&p, card->msgbuf);
-		if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
-			printk(KERN_ERR "%s: incoming packet dropped\n",
-					card->name);
-		} else {
-			memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen);
-			ctrl->handle_capimsg(ctrl, ApplId, skb);
-		}
-		break;
-
-	case RECEIVE_NEW_NCCI:
-
-		ApplId = _get_word(&p);
-		NCCI = _get_word(&p);
-		WindowSize = _get_word(&p);
-
-		ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
-
-		break;
-
-	case RECEIVE_FREE_NCCI:
-
-		ApplId = _get_word(&p);
-		NCCI = _get_word(&p);
-
-		if (NCCI != 0xffffffff)
-			ctrl->free_ncci(ctrl, ApplId, NCCI);
-		else ctrl->appl_released(ctrl, ApplId);
-		break;
-
-	case RECEIVE_START:
-#ifdef CONFIG_T1PCI_POLLDEBUG
-		printk(KERN_INFO "%s: poll from t1\n", card->name);
-#endif
-		if (!suppress_pollack)
-			queue_pollack(card);
-		ctrl->resume_output(ctrl);
-		break;
-
-	case RECEIVE_STOP:
-		ctrl->suspend_output(ctrl);
-		break;
-
-	case RECEIVE_INIT:
-
-		cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
-		b1_parse_version(cinfo);
-		printk(KERN_INFO "%s: %s-card (%s) now active\n",
-		       card->name,
-		       cinfo->version[VER_CARDTYPE],
-		       cinfo->version[VER_DRIVER]);
-		ctrl->ready(ctrl);
-		break;
-
-	case RECEIVE_TASK_READY:
-		ApplId = (unsigned) _get_word(&p);
-		MsgLen = _get_slice(&p, card->msgbuf);
-		card->msgbuf[MsgLen--] = 0;
-		while (    MsgLen >= 0
-		       && (   card->msgbuf[MsgLen] == '\n'
-			   || card->msgbuf[MsgLen] == '\r'))
-			card->msgbuf[MsgLen--] = 0;
-		printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
-				card->name, ApplId, card->msgbuf);
-		break;
-
-	case RECEIVE_DEBUGMSG:
-		MsgLen = _get_slice(&p, card->msgbuf);
-		card->msgbuf[MsgLen--] = 0;
-		while (    MsgLen >= 0
-		       && (   card->msgbuf[MsgLen] == '\n'
-			   || card->msgbuf[MsgLen] == '\r'))
-			card->msgbuf[MsgLen--] = 0;
-		printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
-		break;
-
-	default:
-		printk(KERN_ERR "%s: t1pci_interrupt: 0x%x ???\n",
-				card->name, b1cmd);
-		return;
-	}
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_handle_interrupt(avmcard *card)
-{
-	__u32 status = t1inmeml(card->mbase+AMCC_INTCSR);
-	__u32 newcsr;
-
-	if ((status & ANY_S5933_INT) == 0) 
-		return;
-
-        newcsr = card->csr | (status & ALL_INT);
-	if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
-	if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
-	t1outmeml(card->mbase+AMCC_INTCSR, newcsr);
-
-	if ((status & RX_TC_INT) != 0) {
-		__u8 *recvbuf = card->dma->recvbuf;
-		__u32 rxlen;
-	   	if (card->dma->recvlen == 0) {
-			card->dma->recvlen = *((__u32 *)recvbuf);
-			rxlen = (card->dma->recvlen + 3) & ~3;
-			t1outmeml(card->mbase+AMCC_RXPTR,
-					virt_to_phys(recvbuf+4));
-			t1outmeml(card->mbase+AMCC_RXLEN, rxlen);
-		} else {
-			t1pci_handle_rx(card);
-	   		card->dma->recvlen = 0;
-			t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf));
-			t1outmeml(card->mbase+AMCC_RXLEN, 4);
-		}
-	}
-
-	if ((status & TX_TC_INT) != 0) {
-		card->csr &= ~EN_TX_TC_INT;
-	        t1pci_dispatch_tx(card);
-	} else if (card->csr & EN_TX_TC_INT) {
-		if (t1inmeml(card->mbase+AMCC_TXLEN) == 0) {
-			card->csr &= ~EN_TX_TC_INT;
-			t1pci_dispatch_tx(card);
-		}
-	}
-	t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-}
-
-static void t1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs)
-{
-	avmcard *card;
-
-	card = (avmcard *) devptr;
-
-	if (!card) {
-		printk(KERN_WARNING "t1pci: interrupt: wrong device\n");
-		return;
-	}
-	if (card->interrupt) {
-		printk(KERN_ERR "%s: reentering interrupt hander\n", card->name);
-		return;
-	}
-
-	card->interrupt = 1;
-
-	t1pci_handle_interrupt(card);
-
-	card->interrupt = 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static int t1pci_loaded(avmcard *card)
-{
-	unsigned long stop;
-	unsigned char ans;
-	unsigned long tout = 2;
-	unsigned int base = card->port;
-
-	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
-		if (b1_tx_empty(base))
-			break;
-	}
-	if (!b1_tx_empty(base)) {
-		printk(KERN_ERR "%s: t1pci_loaded: tx err, corrupted t4 file ?\n",
-				card->name);
-		return 0;
-	}
-	b1_put_byte(base, SEND_POLLACK);
-	for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
-		if (b1_rx_full(base)) {
-			if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) {
-				return 1;
-			}
-			printk(KERN_ERR "%s: t1pci_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans);
-			return 0;
-		}
-	}
-	printk(KERN_ERR "%s: t1pci_loaded: firmware not running\n", card->name);
-	return 0;
-}
-
-/* ------------------------------------------------------------- */
-
-static void t1pci_send_init(avmcard *card)
-{
-	struct sk_buff *skb;
-	void *p;
-
-	skb = alloc_skb(15, GFP_ATOMIC);
-	if (!skb) {
-		printk(KERN_CRIT "%s: no memory, lost register appl.\n",
-					card->name);
-		return;
-	}
-	p = skb->data;
-	_put_byte(&p, 0);
-	_put_byte(&p, 0);
-	_put_byte(&p, SEND_INIT);
-	_put_word(&p, AVM_NAPPS);
-	_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
-	_put_word(&p, card->cardnr - 1);
-	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
-
-	skb_queue_tail(&card->dma->send_queue, skb);
-	t1pci_dispatch_tx(card);
-}
-
-static int t1pci_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
-{
-	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
-	avmcard *card = cinfo->card;
-	unsigned long flags;
-	int retval;
-
-	t1pci_reset(card);
-
-	if ((retval = b1_load_t4file(card, &data->firmware))) {
-		t1pci_reset(card);
-		printk(KERN_ERR "%s: failed to load t4file!!\n",
-					card->name);
-		return retval;
-	}
-
-	if (data->configuration.len > 0 && data->configuration.data) {
-		if ((retval = b1_load_config(card, &data->configuration))) {
-			t1pci_reset(card);
-			printk(KERN_ERR "%s: failed to load config!!\n",
-					card->name);
-			return retval;
-		}
-	}
-
-	if (!t1pci_loaded(card)) {
-		t1pci_reset(card);
-		printk(KERN_ERR "%s: failed to load t4file.\n", card->name);
-		return -EIO;
-	}
-
-	save_flags(flags);
-	cli();
-
-	card->csr = AVM_FLAG;
-	t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-	t1outmeml(card->mbase+AMCC_MCSR,
-		EN_A2P_TRANSFERS|EN_P2A_TRANSFERS
-		|A2P_HI_PRIORITY|P2A_HI_PRIORITY
-		|RESET_A2P_FLAGS|RESET_P2A_FLAGS);
-	t1outp(card->port, 0x07, 0x30);
-	t1outp(card->port, 0x10, 0xF0);
-
-	card->dma->recvlen = 0;
-	t1outmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf));
-	t1outmeml(card->mbase+AMCC_RXLEN, 4);
-	card->csr |= EN_RX_TC_INT;
-	t1outmeml(card->mbase+AMCC_INTCSR, card->csr);
-	restore_flags(flags);
-
-        t1pci_send_init(card);
-
-	return 0;
-}
-
-void t1pci_reset_ctr(struct capi_ctr *ctrl)
-{
-	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
-	avmcard *card = cinfo->card;
-
- 	t1pci_reset(card);
-
-	memset(cinfo->version, 0, sizeof(cinfo->version));
-	ctrl->reseted(ctrl);
-}
-
 static void t1pci_remove_ctr(struct capi_ctr *ctrl)
 {
 	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
 	avmcard *card = cinfo->card;
 
- 	t1pci_reset(card);
+ 	b1dma_reset(card);
 
 	di->detach_ctr(ctrl);
 	free_irq(card->irq, card);
@@ -776,210 +93,20 @@
 
 /* ------------------------------------------------------------- */
 
-
-void t1pci_register_appl(struct capi_ctr *ctrl,
-				__u16 appl,
-				capi_register_params *rp)
-{
-	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
-	avmcard *card = cinfo->card;
-	struct sk_buff *skb;
-	int want = rp->level3cnt;
-	int nconn;
-	void *p;
-
-	if (want > 0) nconn = want;
-	else nconn = ctrl->profile.nbchannel * -want;
-	if (nconn == 0) nconn = ctrl->profile.nbchannel;
-
-	skb = alloc_skb(23, GFP_ATOMIC);
-	if (!skb) {
-		printk(KERN_CRIT "%s: no memory, lost register appl.\n",
-					card->name);
-		return;
-	}
-	p = skb->data;
-	_put_byte(&p, 0);
-	_put_byte(&p, 0);
-	_put_byte(&p, SEND_REGISTER);
-	_put_word(&p, appl);
-	_put_word(&p, 1024 * (nconn+1));
-	_put_word(&p, nconn);
-	_put_word(&p, rp->datablkcnt);
-	_put_word(&p, rp->datablklen);
-	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
-
-	skb_queue_tail(&card->dma->send_queue, skb);
-	t1pci_dispatch_tx(card);
-
-	ctrl->appl_registered(ctrl, appl);
-}
-
-/* ------------------------------------------------------------- */
-
-void t1pci_release_appl(struct capi_ctr *ctrl, __u16 appl)
-{
-	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
-	avmcard *card = cinfo->card;
-	struct sk_buff *skb;
-	void *p;
-
-	skb = alloc_skb(7, GFP_ATOMIC);
-	if (!skb) {
-		printk(KERN_CRIT "%s: no memory, lost release appl.\n",
-					card->name);
-		return;
-	}
-	p = skb->data;
-	_put_byte(&p, 0);
-	_put_byte(&p, 0);
-	_put_byte(&p, SEND_RELEASE);
-	_put_word(&p, appl);
-
-	skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
-	skb_queue_tail(&card->dma->send_queue, skb);
-	t1pci_dispatch_tx(card);
-}
-
-/* ------------------------------------------------------------- */
-
-
-static void t1pci_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
-{
-	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
-	avmcard *card = cinfo->card;
-	skb_queue_tail(&card->dma->send_queue, skb);
-	t1pci_dispatch_tx(card);
-}
-
-/* ------------------------------------------------------------- */
-
-static char *t1pci_procinfo(struct capi_ctr *ctrl)
-{
-	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
-
-	if (!cinfo)
-		return "";
-	sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx",
-		cinfo->cardname[0] ? cinfo->cardname : "-",
-		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
-		cinfo->card ? cinfo->card->port : 0x0,
-		cinfo->card ? cinfo->card->irq : 0,
-		cinfo->card ? cinfo->card->membase : 0
-		);
-	return cinfo->infobuf;
-}
-
-static int t1pci_read_proc(char *page, char **start, off_t off,
-        		int count, int *eof, struct capi_ctr *ctrl)
-{
-	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
-	avmcard *card = cinfo->card;
-	unsigned long flags;
-	__u8 flag;
-	int len = 0;
-	char *s;
-	__u32 txaddr, txlen, rxaddr, rxlen, csr;
-
-	len += sprintf(page+len, "%-16s %s\n", "name", card->name);
-	len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port);
-	len += sprintf(page+len, "%-16s %d\n", "irq", card->irq);
-	len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase);
-	switch (card->cardtype) {
-	case avm_b1isa: s = "B1 ISA"; break;
-	case avm_b1pci: s = "B1 PCI"; break;
-	case avm_b1pcmcia: s = "B1 PCMCIA"; break;
-	case avm_m1: s = "M1"; break;
-	case avm_m2: s = "M2"; break;
-	case avm_t1isa: s = "T1 ISA (HEMA)"; break;
-	case avm_t1pci: s = "T1 PCI"; break;
-	case avm_c4: s = "C4"; break;
-	default: s = "???"; break;
-	}
-	len += sprintf(page+len, "%-16s %s\n", "type", s);
-	if ((s = cinfo->version[VER_DRIVER]) != 0)
-	   len += sprintf(page+len, "%-16s %s\n", "ver_driver", s);
-	if ((s = cinfo->version[VER_CARDTYPE]) != 0)
-	   len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s);
-	if ((s = cinfo->version[VER_SERIAL]) != 0)
-	   len += sprintf(page+len, "%-16s %s\n", "ver_serial", s);
-
-	if (card->cardtype != avm_m1) {
-        	flag = ((__u8 *)(ctrl->profile.manu))[3];
-        	if (flag)
-			len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n",
-			"protocol",
-			(flag & 0x01) ? " DSS1" : "",
-			(flag & 0x02) ? " CT1" : "",
-			(flag & 0x04) ? " VN3" : "",
-			(flag & 0x08) ? " NI1" : "",
-			(flag & 0x10) ? " AUSTEL" : "",
-			(flag & 0x20) ? " ESS" : "",
-			(flag & 0x40) ? " 1TR6" : ""
-			);
-	}
-	if (card->cardtype != avm_m1) {
-        	flag = ((__u8 *)(ctrl->profile.manu))[5];
-		if (flag)
-			len += sprintf(page+len, "%-16s%s%s%s%s\n",
-			"linetype",
-			(flag & 0x01) ? " point to point" : "",
-			(flag & 0x02) ? " point to multipoint" : "",
-			(flag & 0x08) ? " leased line without D-channel" : "",
-			(flag & 0x04) ? " leased line with D-channel" : ""
-			);
-	}
-	len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname);
-
-	save_flags(flags);
-	cli();
-
-	txaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x2c));
-	txaddr -= (__u32)card->dma->sendbuf;
-	txlen  = t1inmeml(card->mbase+0x30);
-
-	rxaddr = (__u32)phys_to_virt(t1inmeml(card->mbase+0x24));
-	rxaddr -= (__u32)card->dma->recvbuf;
-	rxlen  = t1inmeml(card->mbase+0x28);
-
-	csr  = t1inmeml(card->mbase+AMCC_INTCSR);
-
-	restore_flags(flags);
-
-        len += sprintf(page+len, "%-16s 0x%lx\n",
-				"csr (cached)", (unsigned long)card->csr);
-        len += sprintf(page+len, "%-16s 0x%lx\n",
-				"csr", (unsigned long)csr);
-        len += sprintf(page+len, "%-16s %lu\n",
-				"txoff", (unsigned long)txaddr);
-        len += sprintf(page+len, "%-16s %lu\n",
-				"txlen", (unsigned long)txlen);
-        len += sprintf(page+len, "%-16s %lu\n",
-				"rxoff", (unsigned long)rxaddr);
-        len += sprintf(page+len, "%-16s %lu\n",
-				"rxlen", (unsigned long)rxlen);
-
-	if (off+count >= len)
-	   *eof = 1;
-	if (len < off)
-           return 0;
-	*start = page + off;
-	return ((count < len-off) ? count : len-off);
-}
-
-/* ------------------------------------------------------------- */
-
 static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
 {
-	unsigned long page_offset, base;
+	unsigned long base, page_offset;
 	avmcard *card;
 	avmctrl_info *cinfo;
 	int retval;
 
+	MOD_INC_USE_COUNT;
+
 	card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC);
 
 	if (!card) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card, 0, sizeof(avmcard));
@@ -987,6 +114,7 @@
 	if (!card->dma) {
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(card->dma, 0, sizeof(avmcard_dmainfo));
@@ -995,6 +123,7 @@
 		printk(KERN_WARNING "%s: no memory.\n", driver->name);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -ENOMEM;
 	}
 	memset(cinfo, 0, sizeof(avmctrl_info));
@@ -1013,14 +142,26 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
-        base = card->membase & PAGE_MASK;
+	base = card->membase & PAGE_MASK;
 	page_offset = card->membase - base;
 	card->mbase = ioremap_nocache(base, page_offset + 64);
+	if (card->mbase) {
+		card->mbase += page_offset;
+	} else {
+		printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
+					driver->name, card->membase);
+	        kfree(card->ctrlinfo);
+		kfree(card->dma);
+		kfree(card);
+	        MOD_DEC_USE_COUNT;
+		return -EIO;
+	}
 
-	t1pci_reset(card);
+	b1dma_reset(card);
 
 	if ((retval = t1pci_detect(card)) != 0) {
 		printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
@@ -1029,13 +170,14 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EIO;
 	}
-	t1pci_reset(card);
+	b1dma_reset(card);
 
 	request_region(p->port, AVMB1_PORTLEN, card->name);
 
-	retval = request_irq(card->irq, t1pci_interrupt, SA_SHIRQ, card->name, card);
+	retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card);
 	if (retval) {
 		printk(KERN_ERR "%s: unable to get IRQ %d.\n",
 				driver->name, card->irq);
@@ -1044,6 +186,7 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 
@@ -1056,31 +199,52 @@
 	        kfree(card->ctrlinfo);
 		kfree(card->dma);
 		kfree(card);
+	        MOD_DEC_USE_COUNT;
 		return -EBUSY;
 	}
 	card->cardnr = cinfo->capi_ctrl->cnr;
 
 	skb_queue_head_init(&card->dma->send_queue);
 
-	MOD_INC_USE_COUNT;
+	printk(KERN_INFO
+		"%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n",
+		driver->name, card->port, card->irq, card->membase);
 
 	return 0;
 }
 
 /* ------------------------------------------------------------- */
 
+static char *t1pci_procinfo(struct capi_ctr *ctrl)
+{
+	avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
+
+	if (!cinfo)
+		return "";
+	sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx",
+		cinfo->cardname[0] ? cinfo->cardname : "-",
+		cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-",
+		cinfo->card ? cinfo->card->port : 0x0,
+		cinfo->card ? cinfo->card->irq : 0,
+		cinfo->card ? cinfo->card->membase : 0
+		);
+	return cinfo->infobuf;
+}
+
+/* ------------------------------------------------------------- */
+
 static struct capi_driver t1pci_driver = {
     "t1pci",
     "0.0",
-    t1pci_load_firmware,
-    t1pci_reset_ctr,
+    b1dma_load_firmware,
+    b1dma_reset_ctr,
     t1pci_remove_ctr,
-    t1pci_register_appl,
-    t1pci_release_appl,
-    t1pci_send_message,
+    b1dma_register_appl,
+    b1dma_release_appl,
+    b1dma_send_message,
 
     t1pci_procinfo,
-    t1pci_read_proc,
+    b1dmactl_read_proc,
     0,	/* use standard driver_read_proc */
 
     0, /* no add_card function */
diff -urN linux-2.2.15-pre14/drivers/isdn/divert/divert_procfs.c linux/drivers/isdn/divert/divert_procfs.c
--- linux-2.2.15-pre14/drivers/isdn/divert/divert_procfs.c	Tue Oct 26 17:53:40 1999
+++ linux/drivers/isdn/divert/divert_procfs.c	Mon Dec  3 22:01:29 2001
@@ -1,10 +1,10 @@
-/* 
- * $Id: divert_procfs.c,v 1.5 1999/09/14 20:31:01 werner Exp $
+/*
+ * $Id: divert_procfs.c,v 1.6 2000/02/14 19:23:03 werner Exp $
  *
  * Filesystem handling for the diversion supplementary services.
  *
  * Copyright 1998       by Werner Cornelius (werner@isdn4linux.de)
- * 
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
@@ -17,9 +17,13 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: divert_procfs.c,v $
+ * Revision 1.6  2000/02/14 19:23:03  werner
+ *
+ * Changed handling of proc filesystem tables to a more portable version
+ *
  * Revision 1.5  1999/09/14 20:31:01  werner
  *
  * Removed obsoleted functions for proc fs and synced with new ones.
@@ -44,9 +48,9 @@
 #include <linux/version.h>
 #include <linux/poll.h>
 #ifdef CONFIG_PROC_FS
-  #include <linux/proc_fs.h>
+#include <linux/proc_fs.h>
 #else
-  #include <linux/fs.h>
+#include <linux/fs.h>
 #endif
 #include <linux/isdnif.h>
 #include "isdn_divert.h"
@@ -54,220 +58,239 @@
 /*********************************/
 /* Variables for interface queue */
 /*********************************/
-ulong if_used = 0; /* number of interface users */
-static struct divert_info *divert_info_head = NULL; /* head of queue */
-static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
-static struct wait_queue *rd_queue = 0; /* Queue IO */
+ulong if_used = 0;		/* number of interface users */
+static struct divert_info *divert_info_head = NULL;	/* head of queue */
+static struct divert_info *divert_info_tail = NULL;	/* pointer to last entry */
+static struct wait_queue *rd_queue = 0;		/* Queue IO */
 
 /*********************************/
 /* put an info buffer into queue */
 /*********************************/
-void put_info_buffer(char *cp)
-{ struct divert_info *ib;
-  int flags; 
-  
-  if (if_used <= 0) return;
-  if (!cp) return;
-  if (!*cp) return; 
-  if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info)+strlen(cp), GFP_ATOMIC))) return; /* no memory */
-  strcpy(ib->info_start,cp); /* set output string */
-  ib->next = NULL;
-  save_flags(flags);
-  cli();
-  ib->usage_cnt = if_used; 
-  if (!divert_info_head) 
-    divert_info_head = ib; /* new head */
-  else
-    divert_info_tail->next = ib; /* follows existing messages */
-  divert_info_tail = ib; /* new tail */   
-  restore_flags(flags);
-
-  /* delete old entrys */
-  while (divert_info_head->next)
-   { if ((divert_info_head->usage_cnt <= 0) &&
-         (divert_info_head->next->usage_cnt <= 0))
-       { ib = divert_info_head;
-         divert_info_head = divert_info_head->next;
-         kfree(ib);
-       }
-     else break;
-   } /* divert_info_head->next */  
-  wake_up_interruptible(&(rd_queue));
-} /* put_info_buffer */
+void
+put_info_buffer(char *cp)
+{
+	struct divert_info *ib;
+	int flags;
+
+	if (if_used <= 0)
+		return;
+	if (!cp)
+		return;
+	if (!*cp)
+		return;
+	if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
+		 return;	/* no memory */
+	strcpy(ib->info_start, cp);	/* set output string */
+	ib->next = NULL;
+	save_flags(flags);
+	cli();
+	ib->usage_cnt = if_used;
+	if (!divert_info_head)
+		divert_info_head = ib;	/* new head */
+	else
+		divert_info_tail->next = ib;	/* follows existing messages */
+	divert_info_tail = ib;	/* new tail */
+	restore_flags(flags);
+
+	/* delete old entrys */
+	while (divert_info_head->next) {
+		if ((divert_info_head->usage_cnt <= 0) &&
+		    (divert_info_head->next->usage_cnt <= 0)) {
+			ib = divert_info_head;
+			divert_info_head = divert_info_head->next;
+			kfree(ib);
+		} else
+			break;
+	}			/* divert_info_head->next */
+	wake_up_interruptible(&(rd_queue));
+}				/* put_info_buffer */
 
 /**********************************/
 /* deflection device read routine */
 /**********************************/
-static ssize_t isdn_divert_read(struct file *file, char *buf, size_t count, loff_t *off)
-{ struct divert_info *inf;
-  int len;
-	
-  if (!*((struct divert_info **)file->private_data))
-    { if (file->f_flags & O_NONBLOCK)
-	return -EAGAIN;
-      interruptible_sleep_on(&(rd_queue));
-    }
-  if (!(inf = *((struct divert_info **)file->private_data))) return(0);
-  
-  inf->usage_cnt--; /* new usage count */
-  (struct divert_info **)file->private_data = &inf->next; /* next structure */
-  if ((len = strlen(inf->info_start)) <= count) 
-    { if (copy_to_user(buf, inf->info_start, len))
-	return -EFAULT;
-      file->f_pos += len;
-      return(len);
-    }
-  return(0);
-} /* isdn_divert_read */
+static ssize_t
+isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off)
+{
+	struct divert_info *inf;
+	int len;
+
+	if (!*((struct divert_info **) file->private_data)) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		interruptible_sleep_on(&(rd_queue));
+	}
+	if (!(inf = *((struct divert_info **) file->private_data)))
+		return (0);
+
+	inf->usage_cnt--;	/* new usage count */
+	(struct divert_info **) file->private_data = &inf->next;	/* next structure */
+	if ((len = strlen(inf->info_start)) <= count) {
+		if (copy_to_user(buf, inf->info_start, len))
+			return -EFAULT;
+		file->f_pos += len;
+		return (len);
+	}
+	return (0);
+}				/* isdn_divert_read */
 
 /**********************************/
 /* deflection device write routine */
 /**********************************/
-static ssize_t isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t *off)
+static ssize_t
+isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t * off)
 {
-  return(-ENODEV);
-} /* isdn_divert_write */
+	return (-ENODEV);
+}				/* isdn_divert_write */
 
 
 /***************************************/
 /* select routines for various kernels */
 /***************************************/
-static unsigned int isdn_divert_poll(struct file *file, poll_table * wait)
-{ unsigned int mask = 0;
+static unsigned int
+isdn_divert_poll(struct file *file, poll_table * wait)
+{
+	unsigned int mask = 0;
 
-  poll_wait(file, &(rd_queue), wait);
-  /* mask = POLLOUT | POLLWRNORM; */
-  if (*((struct divert_info **)file->private_data)) 
-    { mask |= POLLIN | POLLRDNORM;
-    }
-  return mask;
-} /* isdn_divert_poll */
+	poll_wait(file, &(rd_queue), wait);
+	/* mask = POLLOUT | POLLWRNORM; */
+	if (*((struct divert_info **) file->private_data)) {
+		mask |= POLLIN | POLLRDNORM;
+	}
+	return mask;
+}				/* isdn_divert_poll */
 
 /****************/
 /* Open routine */
 /****************/
-static int isdn_divert_open(struct inode *ino, struct file *filep)
-{ int flags;
+static int
+isdn_divert_open(struct inode *ino, struct file *filep)
+{
+	int flags;
 
-  MOD_INC_USE_COUNT;
-  save_flags(flags);
-  cli();
-  if_used++;
-  if (divert_info_head)
-    (struct divert_info **)filep->private_data = &(divert_info_tail->next);
-   else
-    (struct divert_info **)filep->private_data = &divert_info_head; 
-  restore_flags(flags);
-  /*  start_divert(); */
-  return(0);
-} /* isdn_divert_open */
+	MOD_INC_USE_COUNT;
+	save_flags(flags);
+	cli();
+	if_used++;
+	if (divert_info_head)
+		(struct divert_info **) filep->private_data = &(divert_info_tail->next);
+	else
+		(struct divert_info **) filep->private_data = &divert_info_head;
+	restore_flags(flags);
+	/*  start_divert(); */
+	return (0);
+}				/* isdn_divert_open */
 
 /*******************/
 /* close routine   */
 /*******************/
-static int isdn_divert_close(struct inode *ino, struct file *filep)
-{ struct divert_info *inf; 
-  int flags;
-
-  save_flags(flags);
-  cli();
-  if_used--;
-  inf = *((struct divert_info **)filep->private_data);
-  while (inf)
-   { inf->usage_cnt--;
-     inf = inf->next;
-   } 
-  restore_flags(flags);
-  if (if_used <= 0)
-   while (divert_info_head)
-    { inf = divert_info_head;
-      divert_info_head = divert_info_head->next;
-      kfree(inf);
-    }
-  MOD_DEC_USE_COUNT;
-  return(0);
-} /* isdn_divert_close */
+static int
+isdn_divert_close(struct inode *ino, struct file *filep)
+{
+	struct divert_info *inf;
+	int flags;
+
+	save_flags(flags);
+	cli();
+	if_used--;
+	inf = *((struct divert_info **) filep->private_data);
+	while (inf) {
+		inf->usage_cnt--;
+		inf = inf->next;
+	}
+	restore_flags(flags);
+	if (if_used <= 0)
+		while (divert_info_head) {
+			inf = divert_info_head;
+			divert_info_head = divert_info_head->next;
+			kfree(inf);
+		}
+	MOD_DEC_USE_COUNT;
+	return (0);
+}				/* isdn_divert_close */
 
 /*********/
 /* IOCTL */
 /*********/
-static int isdn_divert_ioctl(struct inode *inode, struct file *file, 
-                             uint cmd, ulong arg)
-{ divert_ioctl dioctl;
-  int i, flags;
-  divert_rule *rulep;
-  char *cp;
-
-  if ((i = copy_from_user(&dioctl,(char *) arg, sizeof(dioctl))))
-    return(i); 
- 
-  switch (cmd)
-   { 
-     case IIOCGETVER:
-       dioctl.drv_version = DIVERT_IIOC_VERSION ; /* set version */
-       break;
-
-     case IIOCGETDRV:
-       if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
-         return(-EINVAL);  
-       break;
-
-     case IIOCGETNAM:
-       cp = divert_if.drv_to_name(dioctl.getid.drvid);
-       if (!cp) return(-EINVAL);
-       if (!*cp) return(-EINVAL);
-       strcpy(dioctl.getid.drvnam,cp);  
-       break;
-
-     case IIOCGETRULE:
-       if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
-         return(-EINVAL);  
-       dioctl.getsetrule.rule = *rulep; /* copy data */
-       break;
-
-     case IIOCMODRULE:
-       if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
-         return(-EINVAL);  
-       save_flags(flags);
-       cli();
-       *rulep = dioctl.getsetrule.rule; /* copy data */
-       restore_flags(flags);
-       return(0); /* no copy required */
-       break;
-
-     case IIOCINSRULE:
-       return(insertrule(dioctl.getsetrule.ruleidx,&dioctl.getsetrule.rule));
-       break;
-
-     case IIOCDELRULE:
-       return(deleterule(dioctl.getsetrule.ruleidx));
-       break;
-
-     case IIOCDODFACT:
-       return(deflect_extern_action(dioctl.fwd_ctrl.subcmd,
-                                    dioctl.fwd_ctrl.callid,
-                                    dioctl.fwd_ctrl.to_nr)); 
-
-     case  IIOCDOCFACT:
-     case  IIOCDOCFDIS:
-     case  IIOCDOCFINT:
-       if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) 
-         return(-EINVAL); /* invalid driver */
-       if ((i = cf_command(dioctl.cf_ctrl.drvid,
-                          (cmd == IIOCDOCFACT) ? 1: (cmd == IIOCDOCFDIS) ? 0:2,
-                          dioctl.cf_ctrl.cfproc,
-                          dioctl.cf_ctrl.msn,  
-                          dioctl.cf_ctrl.service,
-                          dioctl.cf_ctrl.fwd_nr,
-                          &dioctl.cf_ctrl.procid)))
-         return(i);    
-       break;
-   
-     default: 
-       return(-EINVAL);
-   } /* switch cmd */
-  return(copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */
-} /* isdn_divert_ioctl */
+static int
+isdn_divert_ioctl(struct inode *inode, struct file *file,
+		  uint cmd, ulong arg)
+{
+	divert_ioctl dioctl;
+	int i, flags;
+	divert_rule *rulep;
+	char *cp;
+
+	if ((i = copy_from_user(&dioctl, (char *) arg, sizeof(dioctl))))
+		return (i);
+
+	switch (cmd) {
+		case IIOCGETVER:
+			dioctl.drv_version = DIVERT_IIOC_VERSION;	/* set version */
+			break;
+
+		case IIOCGETDRV:
+			if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
+				return (-EINVAL);
+			break;
+
+		case IIOCGETNAM:
+			cp = divert_if.drv_to_name(dioctl.getid.drvid);
+			if (!cp)
+				return (-EINVAL);
+			if (!*cp)
+				return (-EINVAL);
+			strcpy(dioctl.getid.drvnam, cp);
+			break;
+
+		case IIOCGETRULE:
+			if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+				return (-EINVAL);
+			dioctl.getsetrule.rule = *rulep;	/* copy data */
+			break;
+
+		case IIOCMODRULE:
+			if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
+				return (-EINVAL);
+			save_flags(flags);
+			cli();
+			*rulep = dioctl.getsetrule.rule;	/* copy data */
+			restore_flags(flags);
+			return (0);	/* no copy required */
+			break;
+
+		case IIOCINSRULE:
+			return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule));
+			break;
+
+		case IIOCDELRULE:
+			return (deleterule(dioctl.getsetrule.ruleidx));
+			break;
+
+		case IIOCDODFACT:
+			return (deflect_extern_action(dioctl.fwd_ctrl.subcmd,
+						  dioctl.fwd_ctrl.callid,
+						 dioctl.fwd_ctrl.to_nr));
+
+		case IIOCDOCFACT:
+		case IIOCDOCFDIS:
+		case IIOCDOCFINT:
+			if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
+				return (-EINVAL);	/* invalid driver */
+			if ((i = cf_command(dioctl.cf_ctrl.drvid,
+					    (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
+					    dioctl.cf_ctrl.cfproc,
+					    dioctl.cf_ctrl.msn,
+					    dioctl.cf_ctrl.service,
+					    dioctl.cf_ctrl.fwd_nr,
+					    &dioctl.cf_ctrl.procid)))
+				return (i);
+			break;
+
+		default:
+			return (-EINVAL);
+	}			/* switch cmd */
+	return (copy_to_user((char *) arg, &dioctl, sizeof(dioctl)));	/* success */
+}				/* isdn_divert_ioctl */
 
 
 #ifdef CONFIG_PROC_FS
@@ -282,79 +305,62 @@
 	isdn_divert_lseek,
 	isdn_divert_read,
 	isdn_divert_write,
-	NULL,                          /* isdn_readdir */
-	isdn_divert_poll,              /* isdn_poll */
-	isdn_divert_ioctl,             /* isdn_ioctl */
-	NULL,                          /* isdn_mmap */
+	NULL,			/* isdn_readdir */
+	isdn_divert_poll,	/* isdn_poll */
+	isdn_divert_ioctl,	/* isdn_ioctl */
+	NULL,			/* isdn_mmap */
 	isdn_divert_open,
-	NULL,                          /* flush */ 
+	NULL,			/* flush */
 	isdn_divert_close,
-	NULL                           /* fsync */
-};
-
-struct inode_operations divert_file_inode_operations = {
-    &isdn_fops,  /* default proc file-ops */
-    NULL,	 /* create	*/
-    NULL,	 /* lookup	*/
-    NULL,	 /* link		*/
-    NULL,	 /* unlink	*/
-    NULL,	 /* symlink	*/
-    NULL,	 /* mkdir	*/
-    NULL,	 /* rmdir	   */
-    NULL,	 /* mknod	   */
-    NULL,	    /* rename	   */
-    NULL,	    /* readlink	   */
-    NULL,	    /* follow_link */
-    NULL,	    /* readpage	   */
-    NULL,	    /* writepage   */
-    NULL,	    /* bmap	   */
-    NULL,	    /* truncate	   */
-    NULL	    /* permission  */
+	NULL			/* fsync */
 };
 
+struct inode_operations divert_file_inode_operations;
 
 /****************************/
 /* isdn subdir in /proc/net */
 /****************************/
 static struct proc_dir_entry *isdn_proc_entry = NULL;
 static struct proc_dir_entry *isdn_divert_entry = NULL;
-#endif CONFIG_PROC_FS
+#endif	/* CONFIG_PROC_FS */
 
 /***************************************************************************/
 /* divert_dev_init must be called before the proc filesystem may be used   */
 /***************************************************************************/
-int divert_dev_init(void)
-{ int i;
+int
+divert_dev_init(void)
+{
 
 
 #ifdef CONFIG_PROC_FS
-  isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO ,proc_net);
-  if (!isdn_proc_entry) 
-    return(-1);
-  isdn_divert_entry = create_proc_entry("divert",S_IFREG | S_IRUGO,isdn_proc_entry); 
-  if (!isdn_divert_entry) 
-   {
-     remove_proc_entry("isdn",proc_net);
-     return(-1);
-   }
-  isdn_divert_entry->ops = &divert_file_inode_operations;
-#endif CONFIG_PROC_FS
+	isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO, proc_net);
+	if (!isdn_proc_entry)
+		return (-1);
+	isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry);
+	if (!isdn_divert_entry) {
+		remove_proc_entry("isdn", proc_net);
+		return (-1);
+	}
+	memset(&divert_file_inode_operations, 0, sizeof(struct inode_operations));
+	divert_file_inode_operations.default_file_ops = &isdn_fops;
+	isdn_divert_entry->ops = &divert_file_inode_operations;
+#endif	/* CONFIG_PROC_FS */
 
-  return(0);
-} /* divert_dev_init */
+	return (0);
+}				/* divert_dev_init */
 
 /***************************************************************************/
 /* divert_dev_deinit must be called before leaving isdn when included as   */
 /* a module.                                                               */
 /***************************************************************************/
-int divert_dev_deinit(void)
-{ int i;
+int
+divert_dev_deinit(void)
+{
 
 #ifdef CONFIG_PROC_FS
-  remove_proc_entry("divert",isdn_proc_entry);
-  remove_proc_entry("isdn",proc_net);
-#endif CONFIG_PROC_FS
-
-  return(0);
-} /* divert_dev_deinit */
+	remove_proc_entry("divert", isdn_proc_entry);
+	remove_proc_entry("isdn", proc_net);
+#endif	/* CONFIG_PROC_FS */
 
+	return (0);
+}				/* divert_dev_deinit */
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon.h	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/eicon/eicon.h	Mon Dec  3 22:01:29 2001
@@ -1,10 +1,10 @@
-/* $Id: eicon.h,v 1.18 1999/11/25 11:43:27 armin Exp $
+/* $Id: eicon.h,v 1.19 2000/01/23 21:21:23 armin Exp $
  *
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
  *
  * Copyright 1998    by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de) 
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000  by Armin Schindler (mac@melware.de) 
+ * Copyright 1999,2000  Cytronics & Melware (info@melware.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon.h,v $
+ * Revision 1.19  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.18  1999/11/25 11:43:27  armin
  * Fixed statectrl and connect message.
  * X.75 fix and HDLC/transparent with autoconnect.
@@ -263,7 +267,7 @@
 
 /* Macro for delay via schedule() */
 #define SLEEP(j) {                     \
-  current->state = TASK_INTERRUPTIBLE; \
+  current->state = TASK_UNINTERRUPTIBLE; \
   schedule_timeout(j);                 \
 }
 
@@ -282,6 +286,8 @@
 #define XLOG_ERR_UNKNOWN        (18)
 #define XLOG_OK                  (0)
 
+#define TRACE_OK                 (1)
+
 typedef struct {
   __u8 Id	__attribute__ ((packed));
   __u8 uX	__attribute__ ((packed));
@@ -697,6 +703,7 @@
 
 extern ulong DebugVar;
 extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
+extern void eicon_putstatus(eicon_card * card, char * buf);
 
 #endif  /* __KERNEL__ */
 
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_dsp.h linux/drivers/isdn/eicon/eicon_dsp.h
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_dsp.h	Wed Aug 25 17:29:47 1999
+++ linux/drivers/isdn/eicon/eicon_dsp.h	Mon Dec  3 22:01:29 2001
@@ -1,10 +1,10 @@
-/* $Id: eicon_dsp.h,v 1.4 1999/07/25 15:12:02 armin Exp $
+/* $Id: eicon_dsp.h,v 1.5 2000/01/23 21:21:23 armin Exp $
  *
- * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * ISDN lowlevel-module for Eicon active cards.
  *        DSP definitions
  *
- * Copyright 1999    by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1999,2000  by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000  Cytronics & Melware (info@melware.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: eicon_dsp.h,v $
+ * Revision 1.5  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.4  1999/07/25 15:12:02  armin
  * fix of some debug logs.
  * enabled ISA-cards option.
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_idi.c linux/drivers/isdn/eicon/eicon_idi.c
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_idi.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/eicon/eicon_idi.c	Mon Dec  3 22:01:29 2001
@@ -1,10 +1,10 @@
-/* $Id: eicon_idi.c,v 1.28 2000/01/20 19:55:34 keil Exp $
+/* $Id: eicon_idi.c,v 1.33 2000/03/06 15:45:17 armin Exp $
  *
- * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * ISDN lowlevel-module for Eicon active cards.
  *        IDI interface 
  *
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000  by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000  Cytronics & Melware (info@melware.de)
  *
  * Thanks to	Deutsche Mailbox Saar-Lor-Lux GmbH
  *		for sponsoring and testing fax
@@ -26,6 +26,25 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.c,v $
+ * Revision 1.33  2000/03/06 15:45:17  armin
+ * Fixed incomplete number handling with BRI PtP connection.
+ *
+ * Revision 1.32  2000/03/04 17:04:21  armin
+ * Fix of statemachine, B-connect before D-connect,
+ * thanks to Helmut Adams <adams@ipcon.de>
+ * Minor change in send-data packet handling.
+ *
+ * Revision 1.31  2000/02/22 16:26:40  armin
+ * Fixed membase error message.
+ * Fixed missing log buffer struct.
+ *
+ * Revision 1.30  2000/02/16 16:08:46  armin
+ * Fixed virtual channel handling of IDI.
+ *
+ * Revision 1.29  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.28  2000/01/20 19:55:34  keil
  * Add FAX Class 1 support
  *
@@ -145,7 +164,7 @@
 
 #undef EICON_FULL_SERVICE_OKTETT
 
-char *eicon_idi_revision = "$Revision: 1.28 $";
+char *eicon_idi_revision = "$Revision: 1.33 $";
 
 eicon_manifbuf *manbuf;
 
@@ -251,10 +270,10 @@
 }
 
 int
-idi_put_req(eicon_REQ *reqbuf, int rq, int signet)
+idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch)
 {
 	reqbuf->Req = rq;
-	reqbuf->ReqCh = 0;
+	reqbuf->ReqCh = Ch;
 	reqbuf->ReqId = 1;
 	reqbuf->XBuffer.length = 1;
 	reqbuf->XBuffer.P[0] = 0;
@@ -364,34 +383,34 @@
 			break;
 		case REMOVE:
 		case REMOVE|0x700:
-			idi_put_req(reqbuf, REMOVE, layer);
+			idi_put_req(reqbuf, REMOVE, layer, 0);
 			break;
 		case INDICATE_REQ:
-			idi_put_req(reqbuf, INDICATE_REQ, 0);
+			idi_put_req(reqbuf, INDICATE_REQ, 0, 0);
 			break;
 		case HANGUP:
-			idi_put_req(reqbuf, HANGUP, 0);
+			idi_put_req(reqbuf, HANGUP, 0, 0);
 			break;
 		case REJECT:
-			idi_put_req(reqbuf, REJECT, 0);
+			idi_put_req(reqbuf, REJECT, 0 ,0);
 			break;
 		case CALL_ALERT:
-			idi_put_req(reqbuf, CALL_ALERT, 0);
+			idi_put_req(reqbuf, CALL_ALERT, 0, 0);
 			break;
 		case CALL_RES:
 			idi_call_res_req(reqbuf, chan);
 			break;
 		case IDI_N_CONNECT|0x700:
-			idi_put_req(reqbuf, IDI_N_CONNECT, 1);
+			idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
 			break;
 		case IDI_N_CONNECT_ACK|0x700:
-			idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1);
+			idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
 			break;
 		case IDI_N_DISC|0x700:
-			idi_put_req(reqbuf, IDI_N_DISC, 1);
+			idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
 			break;
 		case IDI_N_DISC_ACK|0x700:
-			idi_put_req(reqbuf, IDI_N_DISC_ACK, 1);
+			idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
 			break;
 		default:
 			eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
@@ -809,6 +828,11 @@
 					message->osa[i] = buffer[pos++];
 				eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa);
 				break;
+			case CAD:
+				pos += wlen;
+				eicon_log(ccard, 2, "idi_inf: Ch%d: Connected Address in ind, len:%x\n", 
+					chan->No, wlen);
+				break;
 			case BC:
 				if (wlen > sizeof(message->bc)) {
 					pos += wlen;
@@ -1202,7 +1226,7 @@
 	reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
 
 	reqbuf->Req = IDI_N_EDATA;
-	reqbuf->ReqCh = 0;
+	reqbuf->ReqCh = chan->e.IndCh;
 	reqbuf->ReqId = 1;
 
 	reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P);
@@ -2201,7 +2225,7 @@
 	reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
 
 	reqbuf->Req = IDI_N_UDATA;
-	reqbuf->ReqCh = 0;
+	reqbuf->ReqCh = chan->e.IndCh;
 	reqbuf->ReqId = 1;
 
 	reqbuf->XBuffer.length = len + 1;
@@ -2306,6 +2330,51 @@
 }
 
 void
+eicon_parse_trace(eicon_card *ccard, unsigned char *buffer, int len)
+{
+	int i,j,n;
+	int buflen = len * 3 + 30;
+	char *p;
+	struct trace_s {
+		unsigned long time;
+		unsigned short size;
+		unsigned short code;
+		unsigned char data[1];
+	} *q;
+
+	if (!(p = kmalloc(buflen, GFP_ATOMIC))) {
+		eicon_log(ccard, 1, "idi_err: Ch??: could not allocate trace buffer\n");
+		return;
+	}
+	memset(p, 0, buflen);
+	q = (struct trace_s *)buffer;
+
+	if (DebugVar & 512) {
+		if ((q->code == 3) || (q->code == 4)) {
+			n = (short) *(q->data);
+			if (n) {
+				j = sprintf(p, "DTRC:");
+				for (i = 0; i < n; i++) {
+					j += sprintf(p + j, "%02x ", q->data[i+2]);
+				}
+				j += sprintf(p + j, "\n");
+			}
+		}
+	} else {
+		j = sprintf(p, "XLOG: %lx %04x %04x ",
+			q->time, q->size, q->code);
+
+		for (i = 0; i < q->size; i++) {
+			j += sprintf(p + j, "%02x ", q->data[i]);
+		}
+		j += sprintf(p + j, "\n");
+	}
+	if (strlen(p))
+		eicon_putstatus(ccard, p);
+	kfree(p);
+}
+
+void
 idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
 {
 	int tmp;
@@ -2331,12 +2400,12 @@
 		return;
 	}
 	
-	if (ind->Ind != 8)
+	if ((ind->Ind != 8) && (ind->Ind != 0xc))
 		dlev = 144;
 	else
 		dlev = 128;
 
-       	eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", chan->No,
+       	eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%x Id=%x Ch=%x MInd=%x MLen=%x Len=%x\n", chan->No,
 	        ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
 
 	free_buff = 1;
@@ -2454,15 +2523,7 @@
 						break;
 					case 3: /* incomplete number */
 						eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No);
-					        switch(ccard->type) {
-					                case EICON_CTYPE_MAESTRAP:
-					                case EICON_CTYPE_S2M:
-								/* TODO (other protocols) */
-								chan->fsm_state = EICON_STATE_ICALLW;
-								break;
-							default:
-								idi_do_req(ccard, chan, HANGUP, 0);
-						}
+						chan->fsm_state = EICON_STATE_ICALLW;
 						break;
 				}
 				break;
@@ -2499,8 +2560,10 @@
 							/* On most incoming calls we use automatic connect */
 							/* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
 					}
-				} else
-					idi_hangup(ccard, chan);
+				} else {
+					if (chan->fsm_state != EICON_STATE_ACTIVE)
+						idi_hangup(ccard, chan);
+				}
 				break;
 			case CALL_CON:
 				eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
@@ -2541,8 +2604,12 @@
 
 		if (chan->No == ccard->nchannels) {
 			/* Management Indication */
-			idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
-			chan->fsm_state = 1;
+			if (ind->Ind == 0x04) { /* Trace_Ind */
+				eicon_parse_trace(ccard, ind->RBuffer.P, ind->RBuffer.length);
+			} else {
+				idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length);
+				chan->fsm_state = 1;
+			}
 		} 
 		else
 		switch(ind->Ind) {
@@ -2581,6 +2648,7 @@
 				break; 
 			case IDI_N_CONNECT:
 				eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No);
+				chan->e.IndCh = ind->IndCh;
 				if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1);
 				if (chan->l2prot == ISDN_PROTO_L2_FAX) {
 					break;
@@ -2611,6 +2679,7 @@
 					idi_fax_hangup(ccard, chan);
 				}
 #endif
+				chan->e.IndCh = 0;
 				save_flags(flags);
 				cli();
 				chan->queued = 0;
@@ -2640,7 +2709,7 @@
 #endif
 				break; 
 			case IDI_N_DATA_ACK:
-				eicon_log(ccard, 16, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
+				eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
 				break;
 			case IDI_N_DATA:
 				skb_pull(skb, sizeof(eicon_IND) - 1);
@@ -2690,7 +2759,7 @@
 	/* Management Interface */	
 	if (chan->No == ccard->nchannels) {
 		/* Managementinterface: changing state */
-		if (chan->e.Req == 0x04)
+		if (chan->e.Req != 0x02)
 			chan->fsm_state = 1;
 	}
 
@@ -2721,6 +2790,11 @@
 	} else {
 	/* Network layer */
 		switch(chan->e.Req & 0x0f) {
+			case IDI_N_CONNECT:
+				chan->e.IndCh = ack->RcCh;
+				eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
+					ack->RcId, ack->RcCh, ack->Reference);
+				break;
 			case IDI_N_MDATA:
 			case IDI_N_DATA:
 				if ((chan->e.Req & 0x0f) == IDI_N_DATA) {
@@ -2857,11 +2931,14 @@
 						dCh, ack->Rc, ack->RcId, ack->RcCh);
 					break;
 				default:
-					eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
-						dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
+					if (dCh != ccard->nchannels)
+						eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
+							dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
 			}
 			if (dCh == ccard->nchannels) { /* Management */
 				chan->fsm_state = 2;
+				eicon_log(ccard, 8, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n",
+					dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req);
 			} else if (dCh >= 0) {
 					/* any other channel */
 					/* card reports error: we hangup */
@@ -2937,13 +3014,15 @@
 
 	        reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
 		if (((len - offset) > 270) &&
+			(chan->l2prot != ISDN_PROTO_L2_MODEM) &&
+			(chan->l2prot != ISDN_PROTO_L2_FAX) &&
 			(chan->l2prot != ISDN_PROTO_L2_TRANS)) {
 		        reqbuf->Req = IDI_N_MDATA;
 		} else {
 		        reqbuf->Req = IDI_N_DATA;
-			if (ack) reqbuf->Req |= N_D_BIT;
+			/* if (ack) reqbuf->Req |= N_D_BIT; */
 		}	
-        	reqbuf->ReqCh = 0;
+        	reqbuf->ReqCh = chan->e.IndCh;
 	        reqbuf->ReqId = 1;
 		memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen);
 		reqbuf->XBuffer.length = plen;
@@ -3061,38 +3140,36 @@
 
         chan = &(card->bch[card->nchannels]);
 
-	if (chan->e.D3Id)
-		return -EBUSY;
-	chan->e.D3Id = 1;
-	while((skb2 = skb_dequeue(&chan->e.X)))
-		dev_kfree_skb(skb2);
-	chan->e.busy = 0;
+	if (!(chan->e.D3Id)) {
+		chan->e.D3Id = 1;
+		while((skb2 = skb_dequeue(&chan->e.X)))
+			dev_kfree_skb(skb2);
+		chan->e.busy = 0;
  
-	if ((ret = eicon_idi_manage_assign(card))) {
-		chan->e.D3Id = 0;
-		return(ret); 
-	}
+		if ((ret = eicon_idi_manage_assign(card))) {
+			chan->e.D3Id = 0;
+			return(ret); 
+		}
 
-        timeout = jiffies + 50;
-        while (timeout > jiffies) {
-                if (chan->e.B2Id) break;
-                SLEEP(10);
-        }
-        if (!chan->e.B2Id) {
-		chan->e.D3Id = 0;
-		return -EIO;
+	        timeout = jiffies + 50;
+        	while (timeout > jiffies) {
+	                if (chan->e.B2Id) break;
+        	        SLEEP(10);
+	        }
+	        if (!chan->e.B2Id) {
+			chan->e.D3Id = 0;
+			return -EIO;
+		}
 	}
 
 	chan->fsm_state = 0;
 
 	if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) {
                	eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n");
-		chan->e.D3Id = 0;
 		return -ENOMEM;
 	}
 	if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) {
 		kfree(manbuf);
-		chan->e.D3Id = 0;
 		return -EFAULT;
 	}
 
@@ -3106,7 +3183,6 @@
 		if (skb2) 
 			dev_kfree_skb(skb2);
 		kfree(manbuf);
-		chan->e.D3Id = 0;
                 return -ENOMEM;
         }
 
@@ -3143,25 +3219,14 @@
                 SLEEP(10);
         }
         if ((!chan->fsm_state) || (chan->fsm_state == 2)) {
-		eicon_idi_manage_remove(card);
 		kfree(manbuf);
-		chan->e.D3Id = 0;
 		return -EIO;
 	}
-
-	if ((ret = eicon_idi_manage_remove(card))) {
-		kfree(manbuf);
-		chan->e.D3Id = 0;
-		return(ret);
-	}
-
 	if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) {
 		kfree(manbuf);
-		chan->e.D3Id = 0;
 		return -EFAULT;
 	}
 
 	kfree(manbuf);
-	chan->e.D3Id = 0;
   return(0);
 }
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_idi.h linux/drivers/isdn/eicon/eicon_idi.h
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_idi.h	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/eicon/eicon_idi.h	Mon Dec  3 22:01:29 2001
@@ -1,10 +1,10 @@
-/* $Id: eicon_idi.h,v 1.8 1999/11/25 11:43:27 armin Exp $
+/* $Id: eicon_idi.h,v 1.9 2000/01/23 21:21:23 armin Exp $
  *
- * ISDN lowlevel-module for the Eicon.Diehl active cards.
+ * ISDN lowlevel-module for the Eicon active cards.
  * IDI-Interface
  *
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000  by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000  Cytronics & Melware (info@melware.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_idi.h,v $
+ * Revision 1.9  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.8  1999/11/25 11:43:27  armin
  * Fixed statectrl and connect message.
  * X.75 fix and HDLC/transparent with autoconnect.
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_io.c linux/drivers/isdn/eicon/eicon_io.c
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_io.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/eicon/eicon_io.c	Mon Dec  3 22:01:29 2001
@@ -1,12 +1,12 @@
-/* $Id: eicon_io.c,v 1.9 1999/11/18 20:55:25 armin Exp $
+/* $Id: eicon_io.c,v 1.10 2000/01/23 21:21:23 armin Exp $
  *
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
  * Code for communicating with hardware.
  *
- * Copyright 1999    by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1999,2000  by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000  Cytronics & Melware (info@melware.de)
  *
- * Thanks to	Eicon Technology Diehl GmbH & Co. oHG for 
+ * Thanks to	Eicon Technology GmbH & Co. oHG for 
  *		documents, informations and hardware. 
  *
  * This program is free software; you can redistribute it and/or modify
@@ -24,6 +24,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_io.c,v $
+ * Revision 1.10  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.9  1999/11/18 20:55:25  armin
  * Ready_Int fix of ISA cards.
  *
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_isa.c linux/drivers/isdn/eicon/eicon_isa.c
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_isa.c	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/eicon/eicon_isa.c	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,11 @@
-/* $Id: eicon_isa.c,v 1.12 1999/11/27 12:56:19 armin Exp $
+/* $Id: eicon_isa.c,v 1.14 2000/02/22 16:26:40 armin Exp $
  *
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
  * Hardware-specific code for old ISA cards.
  *
- * Copyright 1998    by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1998      by Fritz Elfert (fritz@isdn4linux.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,6 +22,14 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_isa.c,v $
+ * Revision 1.14  2000/02/22 16:26:40  armin
+ * Fixed membase error message.
+ * Fixed missing log buffer struct.
+ *
+ * Revision 1.13  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.12  1999/11/27 12:56:19  armin
  * Forgot some iomem changes for last ioremap compat.
  *
@@ -79,7 +87,7 @@
 #define release_shmem release_region
 #define request_shmem request_region
 
-char *eicon_isa_revision = "$Revision: 1.12 $";
+char *eicon_isa_revision = "$Revision: 1.14 $";
 
 #undef EICON_MCA_DEBUG
 
@@ -139,6 +147,9 @@
 	unsigned long amem;
 
 	if (!strlen(Id))
+		return -1;
+
+	if (Mem == -1)
 		return -1;
 
 	/* Check for valid membase address */
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_isa.h linux/drivers/isdn/eicon/eicon_isa.h
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_isa.h	Tue Jan  4 10:12:15 2000
+++ linux/drivers/isdn/eicon/eicon_isa.h	Mon Dec  3 22:01:29 2001
@@ -1,10 +1,10 @@
-/* $Id: eicon_isa.h,v 1.7 1999/11/18 21:14:30 armin Exp $
+/* $Id: eicon_isa.h,v 1.8 2000/01/23 21:21:23 armin Exp $
  *
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
  *
- * Copyright 1998    by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1998      by Fritz Elfert (fritz@isdn4linux.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_isa.h,v $
+ * Revision 1.8  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.7  1999/11/18 21:14:30  armin
  * New ISA memory mapped IO
  *
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_mod.c linux/drivers/isdn/eicon/eicon_mod.c
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_mod.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/eicon/eicon_mod.c	Mon Dec  3 22:01:29 2001
@@ -1,12 +1,12 @@
-/* $Id: eicon_mod.c,v 1.23 2000/01/20 19:55:34 keil Exp $
+/* $Id: eicon_mod.c,v 1.25 2000/02/22 16:26:40 armin Exp $
  *
- * ISDN lowlevel-module for Eicon.Diehl active cards.
+ * ISDN lowlevel-module for Eicon active cards.
  * 
- * Copyright 1997    by Fritz Elfert (fritz@isdn4linux.de)
- * Copyright 1998,99 by Armin Schindler (mac@melware.de) 
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1997      by Fritz Elfert (fritz@isdn4linux.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de) 
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
  * 
- * Thanks to    Eicon Technology Diehl GmbH & Co. oHG for
+ * Thanks to    Eicon Technology GmbH & Co. oHG for
  *              documents, informations and hardware.
  *
  *              Deutsche Telekom AG for S2M support.
@@ -31,6 +31,14 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_mod.c,v $
+ * Revision 1.25  2000/02/22 16:26:40  armin
+ * Fixed membase error message.
+ * Fixed missing log buffer struct.
+ *
+ * Revision 1.24  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.23  2000/01/20 19:55:34  keil
  * Add FAX Class 1 support
  *
@@ -136,7 +144,7 @@
 static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
                                                      start of card-list   */
 
-static char *eicon_revision = "$Revision: 1.23 $";
+static char *eicon_revision = "$Revision: 1.25 $";
 
 extern char *eicon_pci_revision;
 extern char *eicon_isa_revision;
@@ -157,7 +165,7 @@
 #endif
 static char *id           = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 
-MODULE_DESCRIPTION(             "Driver for Eicon.Diehl active ISDN cards");
+MODULE_DESCRIPTION(             "Driver for Eicon active ISDN cards");
 MODULE_AUTHOR(                  "Armin Schindler");
 MODULE_SUPPORTED_DEVICE(        "ISDN subsystem");
 MODULE_PARM_DESC(id,   		"ID-String of first card");
@@ -882,8 +890,10 @@
 	u_char *p;
 	struct sk_buff *skb;
 
-	if (!card)
-		return;
+	if (!card) {
+		if (!(card = cards))
+			return;
+	}
 
 	save_flags(flags);
 	cli();
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_pci.c linux/drivers/isdn/eicon/eicon_pci.c
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_pci.c	Tue Oct 26 17:53:40 1999
+++ linux/drivers/isdn/eicon/eicon_pci.c	Mon Dec  3 22:01:29 2001
@@ -1,12 +1,12 @@
-/* $Id: eicon_pci.c,v 1.10 1999/08/22 20:26:49 calle Exp $
+/* $Id: eicon_pci.c,v 1.11 2000/01/23 21:21:23 armin Exp $
  *
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards.
+ * ISDN low-level module for Eicon active ISDN-Cards.
  * Hardware-specific code for PCI cards.
  *
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
  *
- * Thanks to	Eicon Technology Diehl GmbH & Co. oHG for 
+ * Thanks to	Eicon Technology GmbH & Co. oHG for 
  *		documents, informations and hardware. 
  *
  *		Deutsche Telekom AG for S2M support.
@@ -26,6 +26,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_pci.c,v $
+ * Revision 1.11  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.10  1999/08/22 20:26:49  calle
  * backported changes from kernel 2.3.14:
  * - several #include "config.h" gone, others come.
@@ -77,7 +81,7 @@
 #include "eicon_pci.h"
 
 
-char *eicon_pci_revision = "$Revision: 1.10 $";
+char *eicon_pci_revision = "$Revision: 1.11 $";
 
 #if CONFIG_PCI	         /* intire stuff is only for PCI */
 
diff -urN linux-2.2.15-pre14/drivers/isdn/eicon/eicon_pci.h linux/drivers/isdn/eicon/eicon_pci.h
--- linux-2.2.15-pre14/drivers/isdn/eicon/eicon_pci.h	Mon Aug  9 12:04:39 1999
+++ linux/drivers/isdn/eicon/eicon_pci.h	Mon Dec  3 22:01:29 2001
@@ -1,9 +1,9 @@
-/* $Id: eicon_pci.h,v 1.3 1999/03/29 11:19:51 armin Exp $
+/* $Id: eicon_pci.h,v 1.4 2000/01/23 21:21:23 armin Exp $
  *
- * ISDN low-level module for Eicon.Diehl active ISDN-Cards (PCI part).
+ * ISDN low-level module for Eicon active ISDN-Cards (PCI part).
  *
- * Copyright 1998,99 by Armin Schindler (mac@melware.de)
- * Copyright 1999    Cytronics & Melware (info@melware.de)
+ * Copyright 1998-2000 by Armin Schindler (mac@melware.de)
+ * Copyright 1999,2000 Cytronics & Melware (info@melware.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,6 +20,10 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: eicon_pci.h,v $
+ * Revision 1.4  2000/01/23 21:21:23  armin
+ * Added new trace capability and some updates.
+ * DIVA Server BRI now supports data for ISDNLOG.
+ *
  * Revision 1.3  1999/03/29 11:19:51  armin
  * I/O stuff now in seperate file (eicon_io.c)
  * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented.
diff -urN linux-2.2.15-pre14/drivers/isdn/hisax/config.c linux/drivers/isdn/hisax/config.c
--- linux-2.2.15-pre14/drivers/isdn/hisax/config.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/hisax/config.c	Mon Dec  3 22:01:29 2001
@@ -1,10 +1,13 @@
-/* $Id: config.c,v 2.43 2000/01/20 19:49:36 keil Exp $
+/* $Id: config.c,v 2.44 2000/02/26 00:35:12 keil Exp $
 
  * Author       Karsten Keil (keil@isdn4linux.de)
  *              based on the teles driver from Jan den Ouden
  *
  *
  * $Log: config.c,v $
+ * Revision 2.44  2000/02/26 00:35:12  keil
+ * Fix skb freeing in interrupt context
+ *
  * Revision 2.43  2000/01/20 19:49:36  keil
  * Support teles 13.3c vendor version 2.1
  *
@@ -548,9 +551,9 @@
 
 	printk(KERN_INFO "HiSax: Linux Driver for passive ISDN cards\n");
 #ifdef MODULE
-	printk(KERN_INFO "HiSax: Version 3.3d (module)\n");
+	printk(KERN_INFO "HiSax: Version 3.3e (module)\n");
 #else
-	printk(KERN_INFO "HiSax: Version 3.3d (kernel)\n");
+	printk(KERN_INFO "HiSax: Version 3.3e (kernel)\n");
 #endif
 	strcpy(tmp, l1_revision);
 	printk(KERN_INFO "HiSax: Layer1 Revision %s\n", HiSax_getrev(tmp));
diff -urN linux-2.2.15-pre14/drivers/isdn/hisax/hfc_pci.c linux/drivers/isdn/hisax/hfc_pci.c
--- linux-2.2.15-pre14/drivers/isdn/hisax/hfc_pci.c	Tue Jan  4 10:12:16 2000
+++ linux/drivers/isdn/hisax/hfc_pci.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: hfc_pci.c,v 1.25 1999/12/19 13:09:42 keil Exp $
+/* $Id: hfc_pci.c,v 1.27 2000/02/26 00:35:12 keil Exp $
 
  * hfc_pci.c     low level driver for CCD´s hfc-pci based cards
  *
@@ -23,6 +23,13 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: hfc_pci.c,v $
+ * Revision 1.27  2000/02/26 00:35:12  keil
+ * Fix skb freeing in interrupt context
+ *
+ * Revision 1.26  2000/02/09 20:22:55  werner
+ *
+ * Updated PCI-ID table
+ *
  * Revision 1.25  1999/12/19 13:09:42  keil
  * changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
  * signal proof delays
@@ -122,7 +129,7 @@
 
 extern const char *CardType[];
 
-static const char *hfcpci_revision = "$Revision: 1.25 $";
+static const char *hfcpci_revision = "$Revision: 1.27 $";
 
 /* table entry in the PCI devices list */
 typedef struct {
@@ -151,6 +158,7 @@
 	{0x1051, 0x0100, "Motorola MC145575", "MC145575"},
 	{0x1397, 0xB100, "Seyeon", "B100"},
 	{0x15B0, 0x2BD0, "Zoltrix", "2BD0"},
+	{0x114f, 0x71,   "Digi intl.","Digicom"}, 
 	{0, 0, NULL, NULL},
 };
 
diff -urN linux-2.2.15-pre14/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- linux-2.2.15-pre14/drivers/isdn/hisax/hisax.h	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/hisax/hisax.h	Mon Dec  3 22:01:29 2001
@@ -1,8 +1,11 @@
-/* $Id: hisax.h,v 2.40 2000/01/20 19:51:46 keil Exp $
+/* $Id: hisax.h,v 2.41 2000/02/26 00:35:13 keil Exp $
 
  *   Basic declarations, defines and prototypes
  *
  * $Log: hisax.h,v $
+ * Revision 2.41  2000/02/26 00:35:13  keil
+ * Fix skb freeing in interrupt context
+ *
  * Revision 2.40  2000/01/20 19:51:46  keil
  * Fix AddTimer message
  * Change CONFIG defines
@@ -158,7 +161,7 @@
 #include <linux/tty.h>
 #include <linux/serial_reg.h>
 
-#undef ERROR_STATISTIC
+#define ERROR_STATISTIC
 
 #define REQUEST		0
 #define CONFIRM		1
diff -urN linux-2.2.15-pre14/drivers/isdn/hisax/l3dss1.c linux/drivers/isdn/hisax/l3dss1.c
--- linux-2.2.15-pre14/drivers/isdn/hisax/l3dss1.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/hisax/l3dss1.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: l3dss1.c,v 2.22 2000/01/20 19:44:20 keil Exp $
+/* $Id: l3dss1.c,v 2.23 2000/02/26 01:38:14 keil Exp $
 
  * EURO/DSS1 D-channel protocol
  *
@@ -13,6 +13,9 @@
  *              Fritz Elfert
  *
  * $Log: l3dss1.c,v $
+ * Revision 2.23  2000/02/26 01:38:14  keil
+ * Fixes for V.110 encoding LLC from Jens Jakobsen
+ *
  * Revision 2.22  2000/01/20 19:44:20  keil
  * Fixed uninitialiesed location
  * Fixed redirecting number IE in Setup
@@ -104,7 +107,7 @@
 #include <linux/config.h>
 
 extern char *HiSax_getrev(const char *revision);
-const char *dss1_revision = "$Revision: 2.22 $";
+const char *dss1_revision = "$Revision: 2.23 $";
 
 #define EXT_BEARER_CAPS 1
 
@@ -1045,7 +1048,8 @@
 EncodeASyncParams(u_char * p, u_char si2)
 {				// 7c 06 88  90 21 42 00 bb
 
-	p[0] = p[1] = 0;
+	p[0] = 0;
+	p[1] = 0x40;		// Intermediate rate: 16 kbit/s jj 2000.02.19
 	p[2] = 0x80;
 	if (si2 & 32)		// 7 data bits
 
@@ -1059,7 +1063,7 @@
 		p[2] += 96;
 	else			// 1 stop bit
 
-		p[2] = 32;
+		p[2] += 32;
 
 	if (si2 & 8)		// even parity
 
diff -urN linux-2.2.15-pre14/drivers/isdn/hisax/md5sums.asc linux/drivers/isdn/hisax/md5sums.asc
--- linux-2.2.15-pre14/drivers/isdn/hisax/md5sums.asc	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/hisax/md5sums.asc	Mon Dec  3 22:01:29 2001
@@ -13,7 +13,7 @@
 a23fbf8879c1432b04640b8b04bdf419  tei.c
 ce248e56c2e1326012d0b25f92bbf99b  callc.c
 bf9605b36429898f7be6630034e83230  cert.c
-233960fa9fc46aaffcaa883b5b59cf4e  l3dss1.c
+6ce0a184127be1a44747e2017ed24ad9  l3dss1.c
 a3a570781f828b6d59e6b231653133de  l3_1tr6.c
 8188deeb4a1b34c574cd51638cd214d0  elsa.c
 a3c2b8e9d2c623658888b5f1d4317c2a  diva.c
@@ -23,9 +23,9 @@
 Version: 2.6.3i
 Charset: noconv
 
-iQCVAwUBOIdqVzpxHvX/mS9tAQGaWQP+Pj0oVxbhusXnlNOQ+FV6YOGj1HGMXPsO
-C/9555qSbvcKg64OO8VdU1LWq/RCsAwBkJ3eSizF5LbWD8lhCHUpkNlzEv4fIaHe
-fAA9zLnC8Vk4h/YLwUNfZxezYvf22NGSydXGZH4VvLAigF0OGRlKaewsR61KZ/Fh
-4GnVqcxYaH8=
-=eINS
+iQCVAwUBONEHHTpxHvX/mS9tAQG/pAP/UyLx23V9mOgiYaId1Gm6xthyM8TP4bfE
+ov4cNmUHQtHINLXtkAP+eacw/kCiiYhdxBIrNaUC+KQkyiFPOs8frx6espxTfDte
+VZDhKDY5NYch2n3OKPLX26pNNJeu7DELMpFR6vvGByokv1RRYVs2wBk0Q5dnfPaq
+WsW0HeL/vBA=
+=fSCb
 -----END PGP SIGNATURE-----
diff -urN linux-2.2.15-pre14/drivers/isdn/hisax/teles3.c linux/drivers/isdn/hisax/teles3.c
--- linux-2.2.15-pre14/drivers/isdn/hisax/teles3.c	Tue Jan  4 10:12:16 2000
+++ linux/drivers/isdn/hisax/teles3.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: teles3.c,v 2.14 1999/12/23 15:09:32 keil Exp $
+/* $Id: teles3.c,v 2.15 2000/02/03 16:40:10 keil Exp $
 
  * teles3.c     low level stuff for Teles 16.3 & PNP isdn cards
  *
@@ -11,6 +11,9 @@
  *              Beat Doebeli
  *
  * $Log: teles3.c,v $
+ * Revision 2.15  2000/02/03 16:40:10  keil
+ * Fix teles pcmcia
+ *
  * Revision 2.14  1999/12/23 15:09:32  keil
  * change email
  *
@@ -91,7 +94,7 @@
 #include "isdnl1.h"
 
 extern const char *CardType[];
-const char *teles3_revision = "$Revision: 2.14 $";
+const char *teles3_revision = "$Revision: 2.15 $";
 
 #define byteout(addr,val) outb(val,addr)
 #define bytein(addr) inb(addr)
@@ -228,7 +231,7 @@
 release_io_teles3(struct IsdnCardState *cs)
 {
 	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		release_region(cs->hw.teles3.hscx[0], 97);
+		release_region(cs->hw.teles3.hscx[1], 96);
 	} else {
 		if (cs->hw.teles3.cfg_reg) {
 			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
@@ -370,15 +373,15 @@
 	cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e;
 	cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e;
 	if (cs->typ == ISDN_CTYPE_TELESPCMCIA) {
-		if (check_region((cs->hw.teles3.hscx[0]), 97)) {
+		if (check_region((cs->hw.teles3.hscx[1]), 96 )) {
 			printk(KERN_WARNING
 			       "HiSax: %s ports %x-%x already in use\n",
 			       CardType[cs->typ],
-			       cs->hw.teles3.hscx[0],
-			       cs->hw.teles3.hscx[0] + 96);
+			       cs->hw.teles3.hscx[1],
+			       cs->hw.teles3.hscx[1] + 96);
 			return (0);
 		} else
-			request_region(cs->hw.teles3.hscx[0], 97, "HiSax Teles PCMCIA");
+			request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA");
 	} else {
 		if (cs->hw.teles3.cfg_reg) {
 			if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) {
diff -urN linux-2.2.15-pre14/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- linux-2.2.15-pre14/drivers/isdn/isdn_common.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/isdn_common.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.97 2000/01/23 18:45:37 keil Exp $
+/* $Id: isdn_common.c,v 1.100 2000/03/03 16:37:11 kai Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -21,6 +21,16 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_common.c,v $
+ * Revision 1.100  2000/03/03 16:37:11  kai
+ * incorporated some cosmetic changes from the official kernel tree back
+ * into CVS
+ *
+ * Revision 1.99  2000/02/26 01:00:52  keil
+ * changes from 2.3.47
+ *
+ * Revision 1.98  2000/02/16 14:56:27  paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers
+ *
  * Revision 1.97  2000/01/23 18:45:37  keil
  * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
  *
@@ -442,7 +452,7 @@
 
 isdn_dev *dev = (isdn_dev *) 0;
 
-static char *isdn_revision = "$Revision: 1.97 $";
+static char *isdn_revision = "$Revision: 1.100 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -1792,15 +1802,15 @@
 					int i;
 
 					if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
-					(ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN)
+					(ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
 						   * ISDN_MAX_CHANNELS)))
 						return ret;
 
 					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 						if (copy_to_user(p, dev->mdm.info[i].emu.profile,
-						      ISDN_MODEM_ANZREG))
+						      ISDN_MODEM_NUMREG))
 							return -EFAULT;
-						p += ISDN_MODEM_ANZREG;
+						p += ISDN_MODEM_NUMREG;
 						if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
 							return -EFAULT;
 						p += ISDN_MSNLEN;
@@ -1808,7 +1818,7 @@
 							return -EFAULT;
 						p += ISDN_LMSNLEN;
 					}
-					return (ISDN_MODEM_ANZREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
+					return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
 				} else
 					return -EINVAL;
 				break;
@@ -1819,15 +1829,15 @@
 					int i;
 
 					if ((ret = verify_area(VERIFY_READ, (void *) arg,
-					(ISDN_MODEM_ANZREG + ISDN_MSNLEN)
+					(ISDN_MODEM_NUMREG + ISDN_MSNLEN)
 						   * ISDN_MAX_CHANNELS)))
 						return ret;
 
 					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 						if (copy_from_user(dev->mdm.info[i].emu.profile, p,
-						     ISDN_MODEM_ANZREG))
+						     ISDN_MODEM_NUMREG))
 							return -EFAULT;
-						p += ISDN_MODEM_ANZREG;
+						p += ISDN_MODEM_NUMREG;
 						if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
 							return -EFAULT;
 						p += ISDN_MSNLEN;
@@ -2061,17 +2071,13 @@
 
 static struct file_operations isdn_fops =
 {
-	isdn_lseek,
-	isdn_read,
-	isdn_write,
-	NULL,                   /* isdn_readdir */
-	isdn_poll,              /* isdn_poll */
-	isdn_ioctl,             /* isdn_ioctl */
-	NULL,                   /* isdn_mmap */
-	isdn_open,
-	NULL,			/* flush */
-	isdn_close,
-	NULL                    /* fsync */
+	llseek:		isdn_lseek,
+	read:		isdn_read,
+	write:		isdn_write,
+	poll:		isdn_poll,
+	ioctl:		isdn_ioctl,
+	open:		isdn_open,
+	release:	isdn_close,
 };
 
 char *
@@ -2569,6 +2575,7 @@
 		rev = "???";
 	return rev;
 }
+
 
 /*
  * Allocate and initialize all data, register modem-devices
diff -urN linux-2.2.15-pre14/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- linux-2.2.15-pre14/drivers/isdn/isdn_net.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/isdn_net.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.103 2000/01/23 18:45:37 keil Exp $
+/* $Id: isdn_net.c,v 1.114 2000/03/16 16:37:41 kai Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -21,6 +21,51 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_net.c,v $
+ * Revision 1.114  2000/03/16 16:37:41  kai
+ * Allow phone numbers starting with "*" as outgoing numbers for
+ * networking interface. Some PBX's need this to allow dialing internal
+ * numbers (mine, for example ;-)
+ *
+ * Revision 1.113  2000/03/16 15:46:37  kai
+ * a little bugfix and cosmetic changes
+ *
+ * Revision 1.112  2000/03/04 16:20:42  detabc
+ * copy frames before rewriting frame's saddr
+ *
+ * Revision 1.111  2000/02/28 22:28:24  he
+ * moved tx_timeout warning messages in old (2.2.x) branch where it really only
+ * indicates problems.
+ *
+ * Revision 1.110  2000/02/26 01:00:53  keil
+ * changes from 2.3.47
+ *
+ * Revision 1.109  2000/02/25 11:29:17  paul
+ * changed chargetime to ulong from int (after about 20 days the "chargetime of
+ * ipppX is now 1234" message displays a negative number on alpha).
+ *
+ * Revision 1.108  2000/02/15 12:54:01  kai
+ * set TX timeout back to 2 secs for 2.2.x, just to be safe
+ *
+ * Revision 1.107  2000/02/13 09:52:05  kai
+ * increased TX_TIMEOUT to 20sec
+ *
+ * Revision 1.106  2000/02/12 19:26:55  kai
+ * adopted to latest 2.3 softnet changes.
+ *
+ * tested with PPP and MPPP, it works here.
+ * can somebody check raw-ip?
+ *
+ * also changed std2kern, stddiff for bash-1 compatibility,
+ * hope this doesn't break anything.
+ *
+ * Revision 1.105  2000/02/12 11:43:26  he
+ * SOFTNET related changes, first try. Compatible with linux 2.2.x, but
+ * not tested for kernels with softnet (>= 2.3.43) yet.
+ *
+ * Revision 1.104  2000/02/06 21:49:59  detabc
+ * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections.
+ * Include checksum-recompute of ip- and udp-header's.
+ *
  * Revision 1.103  2000/01/23 18:45:37  keil
  * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
  *
@@ -433,10 +478,6 @@
 #endif
 
 
-#ifndef ISDN_NEW_TBUSY
-#define ISDN_NEW_TBUSY
-#endif
-#ifdef ISDN_NEW_TBUSY
 /*
  * Outline of new tbusy handling: 
  *
@@ -453,29 +494,55 @@
  */
 
 /*
- * Tell upper layers that the network device is ready to xmit more frames.
+ * About SOFTNET:
+ * Most of the changes were pretty obvious and basically done by HE already.
+ *
+ * One problem of the isdn net device code is that is uses struct net_device
+ * for masters and slaves. However, only master interface are registered to 
+ * the network layer, and therefore, it only makes sense to call netif_* 
+ * functions on them.
+ *
+ * --KG
  */
-static void __inline__ isdn_net_dev_xon(struct device * dev)
-{
-	dev->tbusy = 0;
-	mark_bh(NET_BH);
-}
 
-static void __inline__ isdn_net_lp_xon(isdn_net_local * lp)
+/* 
+ * Find out if the netdevice has been ifup-ed yet.
+ * For slaves, look at the corresponding master.
+ */
+static int __inline__ isdn_net_started(isdn_net_dev *n)
 {
-	lp->netdev->dev.tbusy = 0;
-	if(lp->master) lp->master->tbusy = 0;
-	mark_bh(NET_BH);
+	isdn_net_local *lp = n->local;
+	struct device *dev;
+	
+	if (lp->master) 
+		dev = lp->master;
+	else
+		dev = &n->dev;
+	return dev->start;
 }
 
 /*
- * Ask upper layers to temporarily cease passing us more xmit frames.
+ * wake up the network -> net_device queue.
+ * For slaves, wake the corresponding master interface.
  */
-static void __inline__ isdn_net_dev_xoff(struct device * dev)
+static void __inline__ isdn_net_lp_xon(isdn_net_local * lp)
 {
-	dev->tbusy = 1;
+	if (lp->master) 
+		netif_wake_queue(lp->master);
+	else
+		netif_wake_queue(&lp->netdev->dev);
 }
-#endif
+
+/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just 
+ * to be safe.
+ * For 2.3.x we push it up to 20 secs, because call establishment
+ * (in particular callback) may take such a long time, and we 
+ * don't want confusing messages in the log. However, there is a slight
+ * possibility that this large timeout will break other things like MPPP,
+ * which might rely on the tx timeout. If so, we'll find out this way...
+ */
+
+#define ISDN_NET_TX_TIMEOUT (2*HZ)
 
 /* Prototypes */
 
@@ -483,7 +550,7 @@
 static int isdn_net_start_xmit(struct sk_buff *, struct device *);
 static int isdn_net_xmit(struct device *, isdn_net_local *, struct sk_buff *);
 
-char *isdn_net_revision = "$Revision: 1.103 $";
+char *isdn_net_revision = "$Revision: 1.114 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -522,14 +589,9 @@
 #endif
 	ulong flags;
 
+	/* not sure if the cli() is needed at all --KG */
 	save_flags(flags);
 	cli();                  /* Avoid glitch on writes to CMD regs */
-	dev->interrupt = 0;
-#ifdef ISDN_NEW_TBUSY
-	isdn_net_dev_xon(dev);
-#else
-	dev->tbusy = 0;
-#endif
 #ifdef CONFIG_ISDN_X25
 	if( cprot && cprot -> pops && dops )
 		cprot -> pops -> restart ( cprot, dev, dops );
@@ -545,8 +607,12 @@
 	struct device *p;
 	struct in_device *in_dev;
 
+	/* moved here from isdn_net_reset, because only the master has an
+	   interface associated which is supposed to be started. BTW:
+	   we need to call netif_start_queue, not netif_wake_queue here */
+	netif_start_queue(dev);
+
 	isdn_net_reset(dev);
-	dev->start = 1;
 	/* Fill in the MAC-level header (not needed, but for compatibility... */
 	for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
 		dev->dev_addr[i] = 0xfc;
@@ -564,7 +630,6 @@
 	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
 		while (p) {
 			isdn_net_reset(p);
-			p->start = 1;
 			p = (((isdn_net_local *) p->priv)->slave);
 		}
 	}
@@ -682,7 +747,7 @@
 							isdn_net_hangup(&p->dev);
 						} else if (jiffies - l->chargetime > l->chargeint) {
 							printk(KERN_DEBUG
-							       "isdn_net: %s: chtime = %d, chint = %d\n",
+							       "isdn_net: %s: chtime = %lu, chint = %d\n",
 							       l->name, l->chargetime, l->chargeint);
 							isdn_net_hangup(&p->dev);
 						}
@@ -743,19 +808,11 @@
 							mdev = &lp->netdev->dev;
 						if (!isdn_net_send_skb(mdev, lp, lp->sav_skb)) {
 							lp->sav_skb = NULL;
-#ifndef ISDN_NEW_TBUSY
-							mark_bh(NET_BH);
-#endif
 						} else {
 							return 1;
 						}
 					}
-#ifdef ISDN_NEW_TBUSY
 					isdn_net_lp_xon(lp);
-#else
-					if (test_and_clear_bit(0, (void *) &(p->dev.tbusy)))
-						mark_bh(NET_BH);
-#endif
 				}
 				return 1;
 			case ISDN_STAT_DCONN:
@@ -831,7 +888,7 @@
 						 * we correct the timestamp here.
 						 */
 						lp->chargetime = jiffies;
-						printk(KERN_DEBUG "isdn_net: chargetime of %s now %d\n",
+						printk(KERN_DEBUG "isdn_net: chargetime of %s now %lu\n",
 						lp->name, lp->chargetime);
 
 						/* reset dial-timeout */
@@ -854,18 +911,7 @@
 							if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
 								lp->first_skb = NULL;
 						}
-#ifdef ISDN_NEW_TBUSY
 						if(! lp->first_skb) isdn_net_lp_xon(lp);
-#else
-						else {
-							/*
-							 * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
-							 * With an empty lp->first_skb, we need to do this ourselves
-							 */
-							lp->netdev->dev.tbusy = 0;
-							mark_bh(NET_BH);
-						}
-#endif /* ISDN_NEW_TBUSY */
 						return 1;
 				}
 				break;
@@ -889,7 +935,7 @@
 				if (lp->hupflags & ISDN_WAITCHARGE)
 					lp->hupflags |= ISDN_HAVECHARGE;
 				lp->chargetime = jiffies;
-				printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %d\n",
+				printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
 				       lp->name, lp->chargetime);
 				return 1;
 		}
@@ -898,20 +944,6 @@
 }
 
 /*
- * Check, if a number contains wildcard-characters, in which case it
- * is for incoming purposes only.
- */
-static int
-isdn_net_checkwild(char *num)
-{
-	return ((strchr(num, '?')) ||
-		(strchr(num, '*')) ||
-		(strchr(num, '[')) ||
-		(strchr(num, ']')) ||
-		(strchr(num, '^')));
-}
-
-/*
  * Perform dialout for net-interfaces and timeout-handling for
  * D-Channel-up and B-Channel-up Messages.
  * This function is initially called from within isdn_net_start_xmit() or
@@ -1322,13 +1354,7 @@
  *
  * Return: 0 on success, !0 on failure.
  */
-#ifndef ISDN_NEW_TBUSY
-/*
- * Side-effects: ndev->tbusy is cleared on success.
- */
-#endif
-int
-isdn_net_send_skb
+int isdn_net_send_skb
 		(struct device *ndev, isdn_net_local * lp,struct sk_buff *skb)
 {
 	int ret;
@@ -1337,17 +1363,11 @@
 	ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
 	if (ret == len) {
 		lp->transcount += len;
-#ifndef ISDN_NEW_TBUSY
-		clear_bit(0, (void *) &(ndev->tbusy));
-#endif
 		return 0;
 	}
 	if (ret < 0) {
 		dev_kfree_skb(skb);
 		lp->stats.tx_errors++;
-#ifndef ISDN_NEW_TBUSY
-		clear_bit(0, (void *) &(ndev->tbusy));
-#endif
 		return 0;
 	}
 	return 1;
@@ -1393,11 +1413,7 @@
 			if (lp->srobin == ndev)
 				ret = isdn_net_send_skb(ndev, lp, skb);
 			else
-#ifdef ISDN_NEW_TBUSY
 				ret = isdn_net_start_xmit(skb, lp->srobin);
-#else
-				ret = ndev->tbusy = isdn_net_start_xmit(skb, lp->srobin);
-#endif
 			lp->srobin = (slp->slave) ? slp->slave : ndev;
 			slp = (isdn_net_local *) (lp->srobin->priv);
 			if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0)))
@@ -1439,6 +1455,8 @@
 	}
 }
 
+
+
 /*
  * Try sending a packet.
  * If this interface isn't connected to a ISDN-Channel, find a free channel,
@@ -1451,19 +1469,24 @@
 #ifdef CONFIG_ISDN_X25
 	struct concap_proto * cprot = lp -> netdev -> cprot;
 #endif
+	/* some comment as with the softnet TX timeout
+	   when this happens, it's a bug in the HL card driver
+	   and should be fixed there, so we can supposedly get rid of 
+	   this here at all. 
+	   I added a debugging message to find out if it ever occurs --KG
+	*/
+
 	if (ndev->tbusy) {
-		if (jiffies - ndev->trans_start < (2 * HZ))
+		if (jiffies - ndev->trans_start < ISDN_NET_TX_TIMEOUT)
 			return 1;
-		if (!lp->dialstate)
+		if (!lp->dialstate){
 			lp->stats.tx_errors++;
+			printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n",
+				ndev->name, lp->dialstate);
+		}
 		ndev->trans_start = jiffies;
-#ifdef ISDN_NEW_TBUSY
-		isdn_net_dev_xon(ndev);
-#endif
+		netif_wake_queue(ndev);
 	}
-#ifndef ISDN_NEW_TBUSY
-	ndev->tbusy = 1; /* left instead of obsolete test_and_set_bit() */
-#endif
 #ifdef CONFIG_ISDN_X25
 /* At this point hard_start_xmit() passes control to the encapsulation
    protocol (if present).
@@ -1478,9 +1501,7 @@
 */
 	if( cprot ) {
 		int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
-#ifdef ISDN_NEW_TBUSY
-		if(ret) isdn_net_dev_xoff(ndev);
-#endif
+		if(ret) netif_stop_queue(ndev);
 		return ret;
 	} else
 #endif
@@ -1500,9 +1521,6 @@
 			if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
 				isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
 				dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
-				ndev->tbusy = 0;
-#endif
 				return 0;
 			}
 			if (lp->phone[1]) {
@@ -1518,9 +1536,6 @@
 					if(jiffies < lp->dialwait_timer) {
 						isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
 						dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
-						ndev->tbusy = 0;
-#endif
 						restore_flags(flags);
 						return 0;
 					} else
@@ -1549,9 +1564,6 @@
 					isdn_net_unreachable(ndev, skb,
 							   "No channel");
 					dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
-					ndev->tbusy = 0;
-#endif
 					return 0;
 				}
 				/* Log packet, which triggered dialing */
@@ -1571,9 +1583,7 @@
 					}
 					restore_flags(flags);
 					isdn_net_dial();	/* Initiate dialing */
-#ifdef ISDN_NEW_TBUSY
-					isdn_net_dev_xoff(ndev);
-#endif
+					netif_stop_queue(ndev);
 					return 1;	/* let upper layer requeue skb packet */
 				}
 #endif
@@ -1587,9 +1597,6 @@
 				}
 				lp->first_skb = skb;
 				/* Initiate dialing */
-#ifndef ISDN_NEW_TBUSY
-				ndev->tbusy = 0;
-#endif
 				restore_flags(flags);
 				isdn_net_dial();
 				return 0;
@@ -1597,9 +1604,6 @@
 				isdn_net_unreachable(ndev, skb,
 						     "No phone number");
 				dev_kfree_skb(skb);
-#ifndef ISDN_NEW_TBUSY
-				ndev->tbusy = 0;
-#endif
 				return 0;
 			}
 		} else {
@@ -1610,24 +1614,16 @@
 				int ret;
 				if (lp->first_skb) {
 					if (isdn_net_xmit(ndev, lp, lp->first_skb)){
-#ifdef ISDN_NEW_TBUSY
-						isdn_net_dev_xoff(ndev);
-#endif
+						netif_stop_queue(ndev);
 						return 1;
 }
 					lp->first_skb = NULL;
 				}
 				ret = (isdn_net_xmit(ndev, lp, skb));
-#ifdef ISDN_NEW_TBUSY
-				if(ret) isdn_net_dev_xoff(ndev);
-#endif
+				if(ret) netif_stop_queue(ndev);
 				return ret;
 			} else
-#ifdef ISDN_NEW_TBUSY
-				isdn_net_dev_xoff(ndev);
-#else
-				ndev->tbusy = 1;
-#endif
+				netif_stop_queue(ndev);
 		}
 	}
 	return 1;
@@ -1649,7 +1645,7 @@
 #ifdef CONFIG_ISDN_X25
 	if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
 #endif
-	dev->tbusy = 1;
+	netif_stop_queue(dev);
 	dev->start = 0;
 	if ((p = (((isdn_net_local *) dev->priv)->slave))) {
 		/* If this interface has slaves, stop them also */
@@ -1661,8 +1657,6 @@
 				cprot -> pops -> close( cprot );
 #endif
 			isdn_net_hangup(p);
-			p->tbusy = 1;
-			p->start = 0;
 			p = (((isdn_net_local *) p->priv)->slave);
 		}
 	}
@@ -2403,7 +2397,7 @@
 				 * Is the interface up?
 				 * If not, reject the call actively.
 				 */
-				if (!p->dev.start) {
+				if (!isdn_net_started(p)) {
 					restore_flags(flags);
 					printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
 					       lp->name);
@@ -2671,9 +2665,6 @@
 			p = (((isdn_net_local *) p->priv)->slave);
 		}
 		((isdn_net_local *) q->priv)->slave = &(netdev->dev);
-		q->interrupt = 0;
-		q->tbusy = 0;
-		q->start = master->start;
 	} else {
 		/* Device shall be a master */
 		if (register_netdev(&netdev->dev) != 0) {
@@ -2746,7 +2737,7 @@
 		if (n->local->master)
 			return NULL;
 		/* Master must not be started yet */
-		if (n->dev.start)
+		if (isdn_net_started(n)) 
 			return NULL;
 		return (isdn_net_new(newname, &(n->dev)));
 	}
@@ -2789,9 +2780,8 @@
 #ifdef CONFIG_ISDN_X25
 			struct concap_proto * cprot = p -> cprot;
 #endif
-			if (p->dev.start) {
-				printk(KERN_WARNING
-				"%s: cannot change encap when if is up\n",
+			if (isdn_net_started(p)) {
+				printk(KERN_WARNING "%s: cannot change encap when if is up\n",
 				       lp->name);
 				return -EBUSY;
 			}
@@ -3051,8 +3041,6 @@
 	isdn_net_dev *p = isdn_net_findif(phone->name);
 	isdn_net_phone *n;
 
-	if (isdn_net_checkwild(phone->phone) && (phone->outgoing & 1))
-		return -EINVAL;
 	if (p) {
 		if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
 			return -ENOMEM;
@@ -3225,14 +3213,8 @@
 
 	save_flags(flags);
 	cli();
-	if (p->local->master) {
-		/* If it's a slave, it may be removed even if it is busy. However
-		 * it has to be hung up first.
-		 */
-		isdn_net_hangup(&p->dev);
-		p->dev.start = 0;
-	}
-	if (p->dev.start) {
+
+	if (isdn_net_started(p)) {
 		restore_flags(flags);
 		return -EBUSY;
 	}
diff -urN linux-2.2.15-pre14/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- linux-2.2.15-pre14/drivers/isdn/isdn_ppp.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/isdn_ppp.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.61 1999/11/20 22:14:14 detabc Exp $
+/* $Id: isdn_ppp.c,v 1.63 2000/03/16 15:46:37 kai Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -19,6 +19,18 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_ppp.c,v $
+ * Revision 1.63  2000/03/16 15:46:37  kai
+ * a little bugfix and cosmetic changes
+ *
+ * Revision 1.62  2000/02/12 19:26:55  kai
+ * adopted to latest 2.3 softnet changes.
+ *
+ * tested with PPP and MPPP, it works here.
+ * can somebody check raw-ip?
+ *
+ * also changed std2kern, stddiff for bash-1 compatibility,
+ * hope this doesn't break anything.
+ *
  * Revision 1.61  1999/11/20 22:14:14  detabc
  * added channel dial-skip in case of external use
  * (isdn phone or another isdn device) on the same NTBA.
@@ -322,7 +334,7 @@
 static void isdn_ppp_free_mpqueue(isdn_net_dev *);
 #endif
 
-char *isdn_ppp_revision = "$Revision: 1.61 $";
+char *isdn_ppp_revision = "$Revision: 1.63 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 
@@ -716,7 +728,7 @@
 		case PPPIOCGIFNAME:
 			if(!lp)
 				return -EINVAL;
-			if ((r = set_arg((void *) arg, lp->name,strlen(lp->name))))
+			if ((r = set_arg((void *) arg, lp->name, strlen(lp->name))))
 				return r;
 			break;
 		case PPPIOCGMPFLAGS:	/* get configuration flags */
@@ -738,8 +750,8 @@
 			}
 			if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
 				if (lp) {
-					lp->netdev->dev.tbusy = 0;
-					mark_bh(NET_BH);	/* OK .. we are ready to send buffers */
+					/* OK .. we are ready to send buffers */
+					netif_wake_queue(&lp->netdev->dev);
 				}
 			}
 			is->pppcfg = val;
@@ -1508,7 +1520,7 @@
 			break;
 		default:
 			dev_kfree_skb(skb);
-			printk(KERN_ERR "isdn_ppp: skipped frame with unsupported protocoll: %#x.\n", skb->protocol);
+			printk(KERN_ERR "isdn_ppp: skipped frame with unsupported protocol: %#x.\n", skb->protocol);
 			return 0;
 	}
 
@@ -1516,7 +1528,7 @@
 
 	if (lp->sav_skb) {      /* find a non-busy device */
 		isdn_net_local *nlp = lp->next;
-		while (lp->sav_skb) {
+		while (nlp->sav_skb) {
 			if (lp == nlp)
 				return 1;
 			nlp = nd->queue = nd->queue->next;
@@ -1942,12 +1954,14 @@
 #ifdef CONFIG_ISDN_PPP_VJ
 	int toss = 0;
 #endif
-/* z.z einfaches aussortieren gammeliger pakete. Fuer die Zukunft:
-   eventuell, solange vorne kein B-paket ist und sqno<=min_sqno: auch rauswerfen
-   wenn sqno<min_sqno und Luecken vorhanden sind: auch weg (die koennen nicht mehr gefuellt werden)
-   bei paketen groesser min_sqno: ueber mp_mrru: wenn summe ueber pktlen der rumhaengenden Pakete
-   groesser als mrru ist: raus damit , Pakete muessen allerdings zusammenhaengen sonst koennte
-   ja ein Paket mit B und eins mit E dazwischenpassen */
+	/* currently we just discard ancient packets. 
+	   To do: 
+	   Maybe, as long as there's no B-packet in front and sqno <= min_sqno: discard.
+	   If sqno < min_sqno and there are gaps: discard (the gaps won't be filled anyway).
+	   Packets with sqno > min_sqno: Larger than mp_mrru: If sum of all pktlen of pending
+	   packets large than mrru: discard - packets need to be consecutive, though, if not 
+	   there could be an B and an E-packet in between.
+	*/
 
 	struct mpqueue *ql,
 	*q = dev->mp_last;
diff -urN linux-2.2.15-pre14/drivers/isdn/isdn_tty.c linux/drivers/isdn/isdn_tty.c
--- linux-2.2.15-pre14/drivers/isdn/isdn_tty.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/isdn_tty.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.c,v 1.82 2000/01/23 18:45:37 keil Exp $
+/* $Id: isdn_tty.c,v 1.84 2000/02/16 15:10:14 paul Exp $
 
  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
  *
@@ -20,6 +20,15 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.c,v $
+ * Revision 1.84  2000/02/16 15:10:14  paul
+ * If a ttyI has no open FDs, don't connect incoming calls to it.
+ * (Hangup on close of last FD is still to be done.)
+ *
+ * Revision 1.83  2000/02/16 14:59:33  paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers;
+ * used defines for result codes;
+ * fixed RING ... RUNG problem (no empty lines in between).
+ *
  * Revision 1.82  2000/01/23 18:45:37  keil
  * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN)
  *
@@ -379,7 +388,7 @@
 static int si2bit[8] =
 {4, 1, 4, 4, 4, 4, 4, 4};
 
-char *isdn_tty_revision = "$Revision: 1.82 $";
+char *isdn_tty_revision = "$Revision: 1.84 $";
 
 
 /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
@@ -901,7 +910,7 @@
 isdn_tty_modem_do_ncarrier(unsigned long data)
 {
 	modem_info *info = (modem_info *) data;
-	isdn_tty_modem_result(3, info);
+	isdn_tty_modem_result(RESULT_NO_CARRIER, info);
 }
 
 /* Next routine is called, whenever the DTR-signal is raised.
@@ -986,7 +995,7 @@
 	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
 	if (i < 0) {
 		restore_flags(flags);
-		isdn_tty_modem_result(6, info);
+		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
 	} else {
 		info->isdn_driver = dev->drvmap[i];
 		info->isdn_channel = dev->chanmap[i];
@@ -1056,8 +1065,7 @@
 	if (info->online) {
 		info->last_lhup = local;
 		info->online = 0;
-		/* NO CARRIER message */
-		isdn_tty_modem_result(3, info);
+		isdn_tty_modem_result(RESULT_NO_CARRIER, info);
 	}
 #ifdef CONFIG_ISDN_AUDIO
 	info->vonline = 0;
@@ -1086,7 +1094,7 @@
 #endif
 	if ((info->msr & UART_MSR_RI) &&
 		(info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
-		isdn_tty_modem_result(12, info);
+		isdn_tty_modem_result(RESULT_RUNG, info);
 	info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
 	info->lsr |= UART_LSR_TEMT;
 	if (info->isdn_driver >= 0) {
@@ -1197,7 +1205,7 @@
 	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
 	if (i < 0) {
 		restore_flags(flags);
-		isdn_tty_modem_result(6, info);
+		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
 	} else {
 		info->isdn_driver = dev->drvmap[i];
 		info->isdn_channel = dev->chanmap[i];
@@ -1265,7 +1273,7 @@
 
 	l = strlen(msg);
 	if (!l) {
-		isdn_tty_modem_result(4, info);
+		isdn_tty_modem_result(RESULT_ERROR, info);
 		return;
 	}
 	for (j = 7; j >= 0; j--)
@@ -1291,7 +1299,7 @@
 	i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
 	if (i < 0) {
 		restore_flags(flags);
-		isdn_tty_modem_result(6, info);
+		isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
 	} else {
 		info->isdn_driver = dev->drvmap[i];
 		info->isdn_channel = dev->chanmap[i];
@@ -1589,7 +1597,7 @@
 #ifdef ISDN_DEBUG_MODEM_HUP
 				printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
 #endif
-				isdn_tty_modem_result(3, info);
+				isdn_tty_modem_result(RESULT_NO_CARRIER, info);
 				isdn_tty_modem_hup(info, 1);
 			} else
 				c = isdn_tty_edit_at(buf, c, info, from_user);
@@ -2322,7 +2330,7 @@
 {
 	atemu *m = &info->emu;
 	if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
-		memcpy(m->mdmreg, m->profile, ISDN_MODEM_ANZREG);
+		memcpy(m->mdmreg, m->profile, ISDN_MODEM_NUMREG);
 		memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
 		memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
 		info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
@@ -2339,7 +2347,7 @@
 static void
 modem_write_profile(atemu * m)
 {
-	memcpy(m->profile, m->mdmreg, ISDN_MODEM_ANZREG);
+	memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
 	memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
 	memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
 	if (dev->profd)
@@ -2448,6 +2456,13 @@
 	return 0;
 }
 
+
+/*
+ * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
+ *      match the MSN against the MSNs (glob patterns) defined for tty_emulator,
+ *      and return 0 for match, 1 for no match, 2 if MSN could match if longer.
+ */
+
 static int
 isdn_tty_match_icall(char *cid, atemu *emu, int di)
 {
@@ -2513,15 +2528,14 @@
 	int idx;
 	int si1;
 	int si2;
-	char nr[32];
+	char *nr;
 	ulong flags;
 
 	if (!setup.phone[0]) {
-		nr[0] = '0';
-		nr[1] = '\0';
+		nr = "0";
 		printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
 	} else
-		strcpy(nr, setup.phone);
+		nr = setup.phone;
 	si1 = (int) setup.si1;
 	si2 = (int) setup.si2;
 	if (!setup.eazmsn[0]) {
@@ -2538,6 +2552,8 @@
 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
 		modem_info *info = &dev->mdm.info[i];
 
+                if (info->count == 0)
+                    continue;
 		if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) &&  /* SI1 is matching */
 		    (info->emu.mdmreg[REG_SI2] == si2))	{         /* SI2 is matching */
 			idx = isdn_dc2minor(di, ch);
@@ -2575,7 +2591,7 @@
 					printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
 					       info->line);
 					info->msr |= UART_MSR_RI;
-					isdn_tty_modem_result(2, info);
+					isdn_tty_modem_result(RESULT_RING, info);
 					isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
 					return 1;
 				}
@@ -2661,9 +2677,9 @@
 #endif
 				if (TTY_IS_ACTIVE(info)) {
 					if (info->dialing == 1) 
-						isdn_tty_modem_result(7, info);
+						isdn_tty_modem_result(RESULT_BUSY, info);
 					if (info->dialing > 1) 
-						isdn_tty_modem_result(3, info);
+						isdn_tty_modem_result(RESULT_NO_CARRIER, info);
 					info->dialing = 0;
 #ifdef ISDN_DEBUG_MODEM_HUP
 					printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
@@ -2692,12 +2708,12 @@
 					if (USG_MODEM(dev->usage[i])) {
 						if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
 							strcpy(info->emu.connmsg, c->parm.num);
-							isdn_tty_modem_result(1, info);
+							isdn_tty_modem_result(RESULT_CONNECT, info);
 						} else
-							isdn_tty_modem_result(5, info);
+							isdn_tty_modem_result(RESULT_CONNECT64000, info);
 					}
 					if (USG_VOICE(dev->usage[i]))
-						isdn_tty_modem_result(11, info);
+						isdn_tty_modem_result(RESULT_VCON, info);
 					return 1;
 				}
 				break;
@@ -2723,7 +2739,7 @@
 						info->last_l2 = -1;
 						info->last_si = 0;
 						sprintf(info->last_cause, "0000");
-						isdn_tty_modem_result(6, info);
+						isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
 					}
 					isdn_tty_modem_hup(info, 0);
 					return 1;
@@ -2938,6 +2954,7 @@
  * For CONNECT-messages also switch to online-mode.
  * For RING-message handle auto-ATA if register 0 != 0
  */
+
 static void
 isdn_tty_modem_result(int code, modem_info * info)
 {
@@ -2950,14 +2967,13 @@
 	char s[ISDN_MSNLEN+10];
 
 	switch (code) {
-		case 2:
-			m->mdmreg[REG_RINGCNT]++;	/* RING */
+		case RESULT_RING:
+			m->mdmreg[REG_RINGCNT]++;
 			if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])
 				/* Automatically accept incoming call */
 				isdn_tty_cmd_ATA(info);
 			break;
-		case 3:
-			/* NO CARRIER */
+		case RESULT_NO_CARRIER:
 #ifdef ISDN_DEBUG_MODEM_HUP
 			printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
 			       (info->flags & ISDN_ASYNC_CLOSING),
@@ -2992,13 +3008,13 @@
 			}
 #endif
 			break;
-		case 1:
-		case 5:
+		case RESULT_CONNECT:
+		case RESULT_CONNECT64000:
 			sprintf(info->last_cause, "0000");
 			if (!info->online)
 				info->online = 2;
 			break;
-		case 11:
+		case RESULT_VCON:
 #ifdef ISDN_DEBUG_MODEM_VOICE
 			printk(KERN_DEBUG "res3: send VCON on ttyI%d\n",
 			       info->line);
@@ -3007,27 +3023,30 @@
 			if (!info->online)
 				info->online = 1;
 			break;
-	}
+	} /* switch(code) */
+
 	if (m->mdmreg[REG_RESP] & BIT_RESP) {
 		/* Show results */
-		isdn_tty_at_cout("\r\n", info);
 		if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) {
-			/* Show numeric results */
-			sprintf(s, "%d", code);
+			/* Show numeric results only */
+			sprintf(s, "\r\n%d\r\n", code);
 			isdn_tty_at_cout(s, info);
 		} else {
-			if ((code == 2) &&
-				(m->mdmreg[REG_RUNG] & BIT_RUNG) &&
-				(m->mdmreg[REG_RINGCNT] > 1))
-				return;
-			if ((code == 2) && (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE))) {
-				isdn_tty_at_cout("CALLER NUMBER: ", info);
-				isdn_tty_at_cout(dev->num[info->drv_index], info);
-				isdn_tty_at_cout("\r\n", info);
+			if (code == RESULT_RING) {
+			    /* return if "show RUNG" and ringcounter>1 */
+			    if ((m->mdmreg[REG_RUNG] & BIT_RUNG) &&
+				    (m->mdmreg[REG_RINGCNT] > 1))
+						return;
+			    /* print CID, _before_ _every_ ring */
+			    if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
+				    isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
+				    isdn_tty_at_cout(dev->num[info->drv_index], info);
+			    }
 			}
+			isdn_tty_at_cout("\r\n", info);
 			isdn_tty_at_cout(msg[code], info);
 			switch (code) {
-				case 1:
+				case RESULT_CONNECT:
 					switch (m->mdmreg[REG_L2PROT]) {
 						case ISDN_PROTO_L2_MODEM:
 							isdn_tty_at_cout(" ", info);
@@ -3035,13 +3054,13 @@
 							break;
 					}
 					break;
-				case 2:
+				case RESULT_RING:
 					/* Append CPN, if enabled */
 					if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
 						sprintf(s, "/%s", m->cpn);
 						isdn_tty_at_cout(s, info);
 					}
-					/* Print CID only once, _after_ 1.st RING */
+					/* Print CID only once, _after_ 1st RING */
 					if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
 					    (m->mdmreg[REG_RINGCNT] == 1)) {
 						isdn_tty_at_cout("\r\n", info);
@@ -3049,10 +3068,10 @@
 						isdn_tty_at_cout(dev->num[info->drv_index], info);
 					}
 					break;
-				case 3:
-				case 6:
-				case 7:
-				case 8:
+				case RESULT_NO_CARRIER:
+				case RESULT_NO_DIALTONE:
+				case RESULT_BUSY:
+				case RESULT_NO_ANSWER:
 					m->mdmreg[REG_RINGCNT] = 0;
 					/* Append Cause-Message if enabled */
 					if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) {
@@ -3060,7 +3079,7 @@
 						isdn_tty_at_cout(s, info);
 					}
 					break;
-				case 5:
+				case RESULT_CONNECT64000:
 					/* Append Protocol to CONNECT message */
 					switch (m->mdmreg[REG_L2PROT]) {
 						case ISDN_PROTO_L2_X75I:
@@ -3088,10 +3107,10 @@
 					}
 					break;
 			}
+			isdn_tty_at_cout("\r\n", info);
 		}
-		isdn_tty_at_cout("\r\n", info);
 	}
-	if (code == 3) {
+	if (code == RESULT_NO_CARRIER) {
 		save_flags(flags);
 		cli();
 		if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
@@ -3109,6 +3128,7 @@
 	}
 }
 
+
 /*
  * Display a modem-register-value.
  */
@@ -3161,8 +3181,8 @@
 	*q = 0;
 }
 
-#define PARSE_ERROR { isdn_tty_modem_result(4, info); return; }
-#define PARSE_ERROR1 { isdn_tty_modem_result(4, info); return 1; }
+#define PARSE_ERROR { isdn_tty_modem_result(RESULT_ERROR, info); return; }
+#define PARSE_ERROR1 { isdn_tty_modem_result(RESULT_ERROR, info); return 1; }
 
 static void
 isdn_tty_report(modem_info * info)
@@ -3330,8 +3350,8 @@
 			/* &L -Set Numbers to listen on */
 			p[0]++;
 			i = 0;
-			while ((strchr("0123456789,-*[]?;", *p[0])) &&
-			       (i < ISDN_LMSNLEN) && *p[0])
+			while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
+			       (i < ISDN_LMSNLEN))
 				m->lmsn[i++] = *p[0]++;
 			m->lmsn[i] = '\0';
 			break;
@@ -3382,7 +3402,7 @@
 			/* &V - Show registers */
 			p[0]++;
 			isdn_tty_at_cout("\r\n", info);
-			for (i = 0; i < ISDN_MODEM_ANZREG; i++) {
+			for (i = 0; i < ISDN_MODEM_NUMREG; i++) {
 				sprintf(rb, "S%02d=%03d%s", i,
 					m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n");
 				isdn_tty_at_cout(rb, info);
@@ -3487,7 +3507,7 @@
 	int bval;
 
 	mreg = isdn_getnum(p);
-	if (mreg < 0 || mreg >= ISDN_MODEM_ANZREG)
+	if (mreg < 0 || mreg >= ISDN_MODEM_NUMREG)
 		PARSE_ERROR1;
 	switch (*p[0]) {
 		case '=':
@@ -3590,7 +3610,7 @@
 		isdn_command(&cmd);
 		isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
 	} else
-		isdn_tty_modem_result(8, info);
+		isdn_tty_modem_result(RESULT_NO_ANSWER, info);
 }
 
 #ifdef CONFIG_ISDN_AUDIO
@@ -3780,7 +3800,7 @@
 			if (!m->vpar[0])
 				PARSE_ERROR1;
 			if (info->online != 1) {
-				isdn_tty_modem_result(8, info);
+				isdn_tty_modem_result(RESULT_NO_ANSWER, info);
 				return 1;
 			}
 			info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
@@ -3804,7 +3824,7 @@
 			printk(KERN_DEBUG "AT: +VRX\n");
 #endif
 			info->vonline |= 1;
-			isdn_tty_modem_result(1, info);
+			isdn_tty_modem_result(RESULT_CONNECT, info);
 			return 0;
 			break;
 		case 4:
@@ -3894,7 +3914,7 @@
 			if (!m->vpar[0])
 				PARSE_ERROR1;
 			if (info->online != 1) {
-				isdn_tty_modem_result(8, info);
+				isdn_tty_modem_result(RESULT_NO_ANSWER, info);
 				return 1;
 			}
 			info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
@@ -3914,7 +3934,7 @@
 #endif
 			m->lastDLE = 0;
 			info->vonline |= 2;
-			isdn_tty_modem_result(1, info);
+			isdn_tty_modem_result(RESULT_CONNECT, info);
 			return 0;
 			break;
 		case 7:
@@ -3999,13 +4019,13 @@
 				if (info->msr & UART_MSR_DCD)
 					PARSE_ERROR;
 				if (info->msr & UART_MSR_RI) {
-					isdn_tty_modem_result(3, info);
+					isdn_tty_modem_result(RESULT_NO_CARRIER, info);
 					return;
 				}
 				isdn_tty_getdial(++p, ds, sizeof ds);
 				p += strlen(p);
 				if (!strlen(m->msn))
-					isdn_tty_modem_result(10, info);
+					isdn_tty_modem_result(RESULT_NO_MSN_EAZ, info);
 				else if (strlen(ds))
 					isdn_tty_dial(ds, info, m);
 				else
@@ -4077,9 +4097,9 @@
 				p++;
 				if (info->msr & UART_MSR_DCD)
 					/* if B-Channel is up */
-					isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? 1:5, info);
+					isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? RESULT_CONNECT:RESULT_CONNECT64000, info);
 				else
-					isdn_tty_modem_result(3, info);
+					isdn_tty_modem_result(RESULT_NO_CARRIER, info);
 				return;
 			case 'Q':
 				/* Q - Turn Emulator messages on/off */
@@ -4172,7 +4192,7 @@
 #ifdef CONFIG_ISDN_AUDIO
 	if (!info->vonline)
 #endif
-		isdn_tty_modem_result(0, info);
+		isdn_tty_modem_result(RESULT_OK, info);
 }
 
 /* Need own toupper() because standard-toupper is not available
@@ -4283,7 +4303,7 @@
 					    ((jiffies - info->emu.lastplus) > PLUSWAIT2)) {
 						info->emu.pluscount = 0;
 						info->online = 0;
-						isdn_tty_modem_result(0, info);
+						isdn_tty_modem_result(RESULT_OK, info);
 					}
 				}
 			}
@@ -4305,7 +4325,7 @@
 		modem_info *info = &dev->mdm.info[i];
 		if (info->msr & UART_MSR_RI) {
 			ton = 1;
-			isdn_tty_modem_result(2, info);
+			isdn_tty_modem_result(RESULT_RING, info);
 		}
 	}
 	isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
@@ -4347,7 +4367,7 @@
 		if (info->dialing) {
 			if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
 				info->dialing = 0;
-				isdn_tty_modem_result(3, info);
+				isdn_tty_modem_result(RESULT_NO_CARRIER, info);
 				isdn_tty_modem_hup(info, 1);
 			}
 			else
diff -urN linux-2.2.15-pre14/drivers/isdn/isdn_tty.h linux/drivers/isdn/isdn_tty.h
--- linux-2.2.15-pre14/drivers/isdn/isdn_tty.h	Mon Dec  3 22:01:22 2001
+++ linux/drivers/isdn/isdn_tty.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_tty.h,v 1.18 2000/01/20 19:55:33 keil Exp $
+/* $Id: isdn_tty.h,v 1.19 2000/02/16 14:59:33 paul Exp $
 
  * header for Linux ISDN subsystem, tty related functions (linklevel).
  *
@@ -20,6 +20,11 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_tty.h,v $
+ * Revision 1.19  2000/02/16 14:59:33  paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers;
+ * used defines for result codes;
+ * fixed RING ... RUNG problem (no empty lines in between).
+ *
  * Revision 1.18  2000/01/20 19:55:33  keil
  * Add FAX Class 1 support
  *
@@ -110,7 +115,7 @@
  * Definition of some special Registers of AT-Emulator
  */
 #define REG_RINGATA   0
-#define REG_RINGCNT   1
+#define REG_RINGCNT   1  /* ring counter register */
 #define REG_ESC       2
 #define REG_CR        3
 #define REG_LF        4
@@ -118,10 +123,10 @@
 
 #define REG_WAITC     7
 
-#define REG_RESP     12
-#define BIT_RESP      1
-#define REG_RESPNUM  12
-#define BIT_RESPNUM   2
+#define REG_RESP     12  /* show response messages register */
+#define BIT_RESP      1  /* show response messages bit      */
+#define REG_RESPNUM  12  /* show numeric responses register */
+#define BIT_RESPNUM   2  /* show numeric responses bit      */
 #define REG_ECHO     12
 #define BIT_ECHO      4
 #define REG_DCD      12
@@ -144,8 +149,8 @@
 #define BIT_RESPXT    8
 #define REG_CIDONCE  13
 #define BIT_CIDONCE  16
-#define REG_RUNG     13
-#define BIT_RUNG     64
+#define REG_RUNG     13  /* show RUNG message register      */
+#define BIT_RUNG     64  /* show RUNG message bit           */
 #define REG_DISPLAY  13
 #define BIT_DISPLAY 128
 
@@ -162,6 +167,21 @@
 #define REG_CPN      23
 #define BIT_CPN       1
 #define BIT_CPNFCON   2
+
+/* defines for result codes */
+#define RESULT_OK		0
+#define RESULT_CONNECT		1
+#define RESULT_RING		2
+#define RESULT_NO_CARRIER	3
+#define RESULT_ERROR		4
+#define RESULT_CONNECT64000	5
+#define RESULT_NO_DIALTONE	6
+#define RESULT_BUSY		7
+#define RESULT_NO_ANSWER	8
+#define RESULT_RINGING		9
+#define RESULT_NO_MSN_EAZ	10
+#define RESULT_VCON		11
+#define RESULT_RUNG		12
 
 #define TTY_IS_FCLASS1(info) \
 	((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
diff -urN linux-2.2.15-pre14/drivers/isdn/isdn_v110.c linux/drivers/isdn/isdn_v110.c
--- linux-2.2.15-pre14/drivers/isdn/isdn_v110.c	Tue Jan  4 10:12:17 2000
+++ linux/drivers/isdn/isdn_v110.c	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_v110.c,v 1.3 1999/10/30 09:49:28 keil Exp $
+/* $Id: isdn_v110.c,v 1.4 2000/03/16 16:34:12 kai Exp $
 
  * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
@@ -19,6 +19,11 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_v110.c,v $
+ * Revision 1.4  2000/03/16 16:34:12  kai
+ * some translation work
+ *
+ * there shouldn't be any German comments lurking around anymore ;-)
+ *
  * Revision 1.3  1999/10/30 09:49:28  keil
  * Reinit of v110 structs
  *
@@ -39,14 +44,15 @@
 
 #undef ISDN_V110_DEBUG
 
-char *isdn_v110_revision = "$Revision: 1.3 $";
+char *isdn_v110_revision = "$Revision: 1.4 $";
 
 #define V110_38400 255
 #define V110_19200  15
 #define V110_9600    3
 
-/* Die folgenden Daten sind fertig kodierte Matrizen, jeweils
-   als online und offline matrix für 9600, 19200 und 38400
+/* 
+ * The following data are precoded matrices, online and offline matrix 
+ * for 9600, 19200 und 38400, respectively
  */
 static unsigned char V110_OnMatrix_9600[] =
 {0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
@@ -74,13 +80,12 @@
 static unsigned char V110_OffMatrix_38400[] =
 {0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff};
 
-
-/* FlipBits dreht die Reihenfolge von jeweils keylen bits in einem byte um.
-   Aus der Bitreihenfolge 76543210 werden bei keylen=4 die bits 45670123,
-   bei keylen=2 die bits 67452301. Dies ist notwendig, weil die reihenfolge
-   auf der isdn-leitung falsch herum ist.
+/* 
+ * FlipBits reorders sequences of keylen bits in one byte.
+ * E.g. source order 7654321 will be converted to 45670123 when keylen = 4,
+ * and to 67452301 when keylen = 2. This is necessary because ordering on
+ * the isdn line is the the other way.
  */
-
 static __inline unsigned char
 FlipBits(unsigned char c, int keylen)
 {
@@ -164,8 +169,9 @@
 }
 
 
-/* ValidHeaderBytes prüft, wieviele bytes in v->decodebuf gültig sind */
-
+/* 
+ * ValidHeaderBytes return the number of valid bytes in v->decodebuf 
+ */
 static int
 ValidHeaderBytes(isdn_v110_stream * v)
 {
@@ -176,8 +182,9 @@
 	return i;
 }
 
-/* SyncHeader schiebt den decodebuf pointer auf den nächsten gültigen header */
-
+/* 
+ * SyncHeader moves the decodebuf ptr to the next valid header 
+ */
 static void
 SyncHeader(isdn_v110_stream * v)
 {
@@ -214,68 +221,60 @@
 	int dbit = v->dbit;
 	unsigned char b = v->b;
 
-	while (line < len) {    /* sind schon alle matrizenzeilen abgearbeitet? */
-		if ((line % 10) == 0) {	/* die 0. zeile der matrix ist immer null ! */
-			if (m[line] != 0x00) {	/* nicht 0 ? dann fehler! */
+	while (line < len) {    /* Are we done with all lines of the matrix? */
+		if ((line % 10) == 0) {	/* the 0. line of the matrix is always 0 ! */
+			if (m[line] != 0x00) {	/* not 0 ? -> error! */
 #ifdef ISDN_V110_DEBUG
 				printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad Header\n");
+				/* returning now is not the right thing, though :-( */
 #endif
-
-/*
-  dann einen return zu machen, ist auch irgendwie nicht das richtige! :-(
-  v->introducer = 0; v->dbit = 1; v->b = 0;
-  return buflen;                                                                                                     anzahl schon erzeugter daten zurückgeben!
-  */
-			}
-			line++; /* sonst die nächste matrixzeile nehmen */
+			} 
+			line++; /* next line of matrix */
 			continue;
-		} else if ((line % 10) == 5) {	/* in zeile 5 stehen nur e-bits ! */
-			if ((m[line] & 0x70) != 0x30) {	/* 011 muß am anfang stehen! */
+		} else if ((line % 10) == 5) {	/* in line 5 there's only e-bits ! */
+			if ((m[line] & 0x70) != 0x30) {	/* 011 has to be at the beginning! */
 #ifdef ISDN_V110_DEBUG
 				printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad 5th line\n");
+				/* returning now is not the right thing, though :-( */
 #endif
-/* dann einen return zu machen, ist auch irgendwie nicht das richtige! :-(
-   v->introducer = 0; v->dbit = 1; v->b = 0;
-   return buflen;
- */
 			}
-			line++; /* alles klar, nächste zeile */
+			line++; /* next line */
 			continue;
 		} else if (!introducer) {	/* every byte starts with 10 (stopbit, startbit) */
-			introducer = (m[line] & mbit) ? 0 : 1;	/* aktuelles bit der matrix */
+			introducer = (m[line] & mbit) ? 0 : 1;	/* current bit of the matrix */
 		      next_byte:
-			if (mbit > 2) {	/* war es das letzte bit dieser matrixzeile ? */
-				mbit >>= 1;	/* nein, nimm das nächste in dieser zeile */
+			if (mbit > 2) {	/* was it the last bit in this line ? */
+				mbit >>= 1;	/* no -> take next */
 				continue;
-			}       /* sonst links in der nächsten zeile anfangen */
+			}       /* otherwise start with leftmost bit in the next line */
 			mbit = 64;
 			line++;
 			continue;
-		} else {        /* sonst müssen wir ein datenbit setzen */
-			if (m[line] & mbit)	/* war das bit in der matrix gesetzt ? */
-				b |= dbit;	/* ja, dann setz es auch im datenbyte  */
+		} else {        /* otherwise we need to set a data bit */
+			if (m[line] & mbit)	/* was that bit set in the matrix ? */
+				b |= dbit;	/* yes -> set it in the data byte */
 			else
-				b &= dbit - 1;	/* nein, lösch bit im datenbyte */
-			if (dbit < 128)	/* haben wir schon ein ganzes byte voll ? */
-				dbit <<= 1;	/* nein, auf zum nächsten datenbit */
-			else {  /* ein ganzes datenbyte ist voll */
-				buf[buflen++] = b;	/* byte in den output buffer kopieren */
-				introducer = b = 0;	/* Init der Introsequenz und des datenbytes */
-				dbit = 1;	/* als nächstes suchen wir das nullte bit */
+				b &= dbit - 1;	/* no -> clear it in the data byte */
+			if (dbit < 128)	/* is that data byte done ? */
+				dbit <<= 1;	/* no, got the next bit */
+			else {  /* data byte is done */
+				buf[buflen++] = b;	/* copy byte into the output buffer */
+				introducer = b = 0;	/* init of the intro sequence and of the data byte */
+				dbit = 1;	/* next we look for the 0th bit */
 			}
-			goto next_byte;	/* suche das nächste bit in der matrix */
+			goto next_byte;	/* look for next bit in the matrix */
 		}
 	}
 	v->introducer = introducer;
 	v->dbit = dbit;
 	v->b = b;
-	return buflen;          /* return anzahl der bytes im output buffer */
+	return buflen;          /* return number of bytes in the output buffer */
 }
 
-/* DecodeStream erhält vom input stream V110 kodierte Daten, die zu den
-   V110 frames zusammengepackt werden müssen. Die Daten können an diese
-   Schnittstelle so übergeben werden, wie sie von der Leitung kommen, ohne
-   darauf achten zu müssen, das frames usw. eingehalten werden.
+/* 
+ * DecodeStream receives V.110 coded data from the input stream. It recovers the 
+ * original frames.
+ * The input stream doesn't need to be framed
  */
 struct sk_buff *
 isdn_v110_decode(isdn_v110_stream * v, struct sk_buff *skb)
@@ -314,8 +313,8 @@
 		dev_kfree_skb(skb);
 		return NULL;    /* no, try later      */
 	}
-	if (ValidHeaderBytes(v) != v->nbytes) {	/* ist es ein ungültiger header ? */
-		SyncHeader(v);  /* nein, such einen header */
+	if (ValidHeaderBytes(v) != v->nbytes) {	/* is that a valid header? */
+		SyncHeader(v);  /* no -> look for header */
 		goto ReSync;
 	}
 	len = (v->decodelen - (v->decodelen % (10 * v->nbytes))) / v->nbytes;
@@ -357,15 +356,15 @@
 	int introducer = 3;
 	int ibit[] = {0, 1, 1};
 
-	while ((i < len) && (line < mlen)) {	/* solange noch input da ist */
-		switch (line % 10) {	/* in welcher matrixzeile sind wir ? */
+	while ((i < len) && (line < mlen)) {	/* while we still have input data */
+		switch (line % 10) {	/* in which line of the matrix are we? */
 			case 0:
-				m[line++] = 0x00;	/* zeile 0 ist immer 0 */
-				mbit = 128;	/* und es geht mit dem 7. bit weiter */
+				m[line++] = 0x00;	/* line 0 is always 0 */
+				mbit = 128;	/* go on with the 7th bit */
 				break;
 			case 5:
-				m[line++] = 0xbf;	/* zeile 5 ist immer 10111111 */
-				mbit = 128;	/* und es geht mit dem 7. bit weiter */
+				m[line++] = 0xbf;	/* line 5 is always 10111111 */
+				mbit = 128;	/* go on with the 7th bit */
 				break;
 		}
 		if (line >= mlen) {
@@ -373,41 +372,41 @@
 			return line;
 		}
 	next_bit:
-		switch (mbit) { /* ganz linkes oder rechtes bit ? */
+		switch (mbit) { /* leftmost or rightmost bit ? */
 			case 1:
-				line++;	/* ganz rechts ! dann in die nächste */
+				line++;	/* rightmost -> go to next line */
 				if (line >= mlen) {
 					printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
 					return line;
 				}
 			case 128:
-				m[line] = 128;	/* ganz links byte auf 1000000 setzen */
-				mbit = 64;	/* aktuelles bit in der matrixzeile */
+				m[line] = 128;	/* leftmost -> set byte to 1000000 */
+				mbit = 64;	/* current bit in the matrix line */
 				continue;
 		}
-		if (introducer) {	/* 110 sequenz setzen ? */
-			introducer--;	/* ein digit weniger setzen */
-			m[line] |= ibit[introducer] ? mbit : 0;	/* entsprechendes bit setzen */
-			mbit >>= 1;	/* bit der matrixzeile >> 1 */
-			goto next_bit;	/* und dort weiter machen */
-		}               /* else datenbits in die matrix packen! */
-		m[line] |= (buf[i] & dbit) ? mbit : 0;	/* datenbit in matrix setzen */
-		if (dbit == 128) {	/* war es das letzte datenbit ? */
-			dbit = 1;	/* dann mach beim nächsten weiter */
-			i++;    /* nächste datenbyte des input buffers */
-			if (i < len)	/* war es schon das letzte ? */
-				introducer = 3;	/* nein, schreib den introducer 110 */
-			else {  /* war das letzte datenbyte ! */
-				m[line] |= (mbit - 1) & 0xfe;	/* setz restliche bits der zeile auf 1 */
+		if (introducer) {	/* set 110 sequence ? */
+			introducer--;	/* set on digit less */
+			m[line] |= ibit[introducer] ? mbit : 0;	/* set corresponding bit */
+			mbit >>= 1;	/* bit of matrix line  >> 1 */
+			goto next_bit;	/* and go on there */
+		}               /* else push data bits into the matrix! */
+		m[line] |= (buf[i] & dbit) ? mbit : 0;	/* set data bit in matrix */
+		if (dbit == 128) {	/* was it the last one? */
+			dbit = 1;	/* then go on with first bit of  */
+			i++;            /* next byte in input buffer */
+			if (i < len)	/* input buffer done ? */
+				introducer = 3;	/* no, write introducer 110 */
+			else {  /* input buffer done ! */
+				m[line] |= (mbit - 1) & 0xfe;	/* set remaining bits in line to 1 */
 				break;
 			}
-		} else          /* nicht das letzte datenbit */
-			dbit <<= 1;	/* dann gehe zum nächsten datenbit */
-		mbit >>= 1;     /* und setz bit der matrix weiter */
+		} else          /* not the last data bit */
+			dbit <<= 1;	/* then go to next data bit */
+		mbit >>= 1;     /* go to next bit of matrix */
 		goto next_bit;
 
 	}
-	/* evtl. noch restliche zeilen in der matrix generieren... */
+	/* if necessary, generate remaining lines of the matrix... */
 	if ((line) && ((line + 10) < mlen))
 		switch (++line % 10) {
 			case 1:
@@ -429,7 +428,7 @@
 			case 9:
 				m[line++] = 0xfe;
 		}
-	return line;            /* soviele matrixzeilen sind es */
+	return line;            /* that's how many lines we have */
 }
 
 /*
@@ -517,7 +516,7 @@
 		return nskb;
 	}
 	mlen = EncodeMatrix(skb->data, rlen, v110buf, size);
-	/* jetzt noch jeweils 2 oder 4 bits auf den output stream verteilen! */
+	/* now distribute 2 or 4 bits each to the output stream! */
 	rbuf = skb_put(nskb, size);
 	olen = 0;
 	sval1 = 8 - v->nbits;
diff -urN linux-2.2.15-pre14/drivers/isdn/isdn_v110.h linux/drivers/isdn/isdn_v110.h
--- linux-2.2.15-pre14/drivers/isdn/isdn_v110.h	Tue Jan  4 10:12:17 2000
+++ linux/drivers/isdn/isdn_v110.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_v110.h,v 1.2 1999/10/30 09:49:28 keil Exp $
+/* $Id: isdn_v110.h,v 1.3 2000/03/16 16:34:12 kai Exp $
 
  * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
@@ -19,6 +19,11 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
  * $Log: isdn_v110.h,v $
+ * Revision 1.3  2000/03/16 16:34:12  kai
+ * some translation work
+ *
+ * there shouldn't be any German comments lurking around anymore ;-)
+ *
  * Revision 1.2  1999/10/30 09:49:28  keil
  * Reinit of v110 structs
  *
@@ -29,17 +34,14 @@
 #ifndef _isdn_v110_h_
 #define _isdn_v110_h_
 
-/* isdn_v110_encode erhält len Nettodaten in buf, kodiert diese und liefert
-   das Ergebnis wieder in buf. Wieviele Bytes kodiert wurden wird als
-   return zurück gegeben. Diese Daten können dann 1:1 auf die Leitung
-   gegeben werden.
-*/
+/* 
+ * isdn_v110_encode will take raw data and encode it using V.110 
+ */
 extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
 
-/* isdn_v110_decode erhält vom input stream V110 kodierte Daten, die zu den
-   V110 frames zusammengepackt werden müssen. Die Daten können an diese
-   Schnittstelle so übergeben werden, wie sie von der Leitung kommen, ohne
-   darauf achten zu müssen, das frames usw. eingehalten werden.
+/* 
+ * isdn_v110_decode receives V.110 coded data from the stream and rebuilds
+ * frames from them. The source stream doesn't need to be framed.
  */
 extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
 
diff -urN linux-2.2.15-pre14/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- linux-2.2.15-pre14/drivers/net/dmfe.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/net/dmfe.c	Mon Dec  3 22:01:29 2001
@@ -346,8 +346,8 @@
 			continue;
 
 		/* read PCI IO base address and IRQ to check */
-		pci_read_config_dword(net_dev, PCI_BASE_ADDRESS_0, &pci_iobase);
-		pci_read_config_byte(net_dev, PCI_INTERRUPT_LINE, &pci_irqline);
+		pci_iobase = net_dev->base_address[0];
+		pci_irqline = net_dev->irq;
 		pci_iobase &= ~0x7f;	/* mask off bit0~6 */
 
 		/* Enable Master/IO access, Disable memory access */
@@ -360,7 +360,7 @@
 		pci_write_config_byte(net_dev, PCI_LATENCY_TIMER, 0x80);
 
 		/* Read Chip revesion */
-		pci_read_config_dword(net_dev, 8, &dev_rev);
+		pci_read_config_dword(net_dev, PCI_REVISION_ID, &dev_rev);
 
 		/* IO range check */
 		if (check_region(pci_iobase, CHK_IO_SIZE(pci_id, dev_rev))) {
@@ -570,9 +570,8 @@
 	}
 	/* No Tx resource check, it never happen normally */
 	if (db->tx_queue_cnt >= TX_FREE_DESC_CNT) {
-		dev_kfree_skb(skb);
 		dev->tbusy = 1;
-		return -EBUSY;
+		return 1;
 	}
 	/* transmit this packet */
 	txptr = db->tx_insert_ptr;
diff -urN linux-2.2.15-pre14/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- linux-2.2.15-pre14/drivers/net/irda/irport.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/net/irda/irport.c	Mon Dec  3 22:01:29 2001
@@ -6,7 +6,7 @@
  * Status:	  Experimental.
  * Author:	  Dag Brattli <dagb@cs.uit.no>
  * Created at:	  Sun Aug  3 13:49:59 1997
- * Modified at:   Fri Jan 14 21:07:20 2000
+ * Modified at:   Sat Mar 11 07:41:54 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:	  serial.c by Linus Torvalds 
  * 
@@ -943,10 +943,14 @@
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irda_task_execute(self, __irport_change_speed, NULL, NULL, 
 				  (void *) irq->ifr_baudrate);
 		break;
 	case SIOCSDONGLE: /* Set dongle */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		/* Initialize dongle */
 		dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
 		if (!dongle)
@@ -967,12 +971,16 @@
 				  NULL);	
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
 		irq->ifr_receiving = irport_is_receiving(self);
 		break;
 	case SIOCSDTRRTS:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irport_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
 		break;
 	default:
diff -urN linux-2.2.15-pre14/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- linux-2.2.15-pre14/drivers/net/irda/irtty.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/net/irda/irtty.c	Mon Dec  3 22:01:29 2001
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Fri Jan 14 21:02:27 2000
+ * Modified at:   Sat Mar 11 07:43:30 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
  *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
@@ -34,6 +34,7 @@
 
 #include <asm/segment.h>
 #include <asm/uaccess.h>
+#include <asm/termios.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irtty.h>
@@ -325,7 +326,7 @@
 {
 	struct termios old_termios;
 	int cflag;
-
+	
 	old_termios = *(self->tty->termios);
 	cflag = self->tty->termios->c_cflag;
 	
@@ -562,6 +563,8 @@
 {
 	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
 
+	IRDA_DEBUG(2, __FUNCTION__ "(%ld)\n", jiffies);
+
 	if (!self || !self->netdev) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), not ready yet!\n");
 		return;
@@ -711,8 +714,6 @@
 
 		self->tx_buff.data += actual;
 		self->tx_buff.len  -= actual;
-
-		self->stats.tx_packets++;		      
 	} else {		
 		/* 
 		 *  Now serial buffer is almost free & we can start 
@@ -734,6 +735,7 @@
 			/* Tell network layer that we want more frames */
 			mark_bh(NET_BH);
 		}
+		self->stats.tx_packets++;
 	}
 }
 
@@ -972,10 +974,14 @@
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irda_task_execute(self, irtty_change_speed, NULL, NULL, 
 				  (void *) irq->ifr_baudrate);
 		break;
 	case SIOCSDONGLE: /* Set dongle */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		/* Initialize dongle */
 		dongle = irda_device_dongle_init(dev, irq->ifr_dongle);
 		if (!dongle)
@@ -996,15 +1002,21 @@
 				  NULL);	
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
 		irq->ifr_receiving = irtty_is_receiving(self);
 		break;
 	case SIOCSDTRRTS:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irtty_set_dtr_rts(dev, irq->ifr_dtr, irq->ifr_rts);
 		break;
 	case SIOCSMODE:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irtty_set_mode(dev, irq->ifr_mode);
 		break;
 	default:
diff -urN linux-2.2.15-pre14/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c
--- linux-2.2.15-pre14/drivers/net/irda/nsc-ircc.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/net/irda/nsc-ircc.c	Mon Dec  3 22:01:29 2001
@@ -6,7 +6,7 @@
  * Status:        Stable.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Wed Jan 26 13:00:29 2000
+ * Modified at:   Fri Mar 10 11:53:26 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -1969,9 +1969,13 @@
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		nsc_ircc_change_speed(self, irq->ifr_baudrate);
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
diff -urN linux-2.2.15-pre14/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- linux-2.2.15-pre14/drivers/net/irda/toshoboe.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/net/irda/toshoboe.c	Mon Dec  3 22:01:29 2001
@@ -612,11 +612,15 @@
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		/* toshoboe_setbaud(self, irq->ifr_baudrate); */
                 /* Just change speed once - inserted by Paul Bristow */
 	        self->new_speed = irq->ifr_baudrate;
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
diff -urN linux-2.2.15-pre14/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- linux-2.2.15-pre14/drivers/net/irda/w83977af_ir.c	Mon Dec  3 22:01:22 2001
+++ linux/drivers/net/irda/w83977af_ir.c	Mon Dec  3 22:01:29 2001
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Paul VanderSpek
  * Created at:    Wed Nov  4 11:46:16 1998
- * Modified at:   Tue Jan 11 13:09:48 2000
+ * Modified at:   Fri Mar 10 11:53:53 2000
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -1348,9 +1348,13 @@
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		w83977af_change_speed(self, irq->ifr_baudrate);
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
diff -urN linux-2.2.15-pre14/drivers/net/olympic.c linux/drivers/net/olympic.c
--- linux-2.2.15-pre14/drivers/net/olympic.c	Mon Dec  3 22:01:23 2001
+++ linux/drivers/net/olympic.c	Mon Dec  3 22:01:29 2001
@@ -22,12 +22,11 @@
  *
  *  6/8/99  - Official Release 0.2.0   
  *            Merged into the kernel code 
- *  
- *  1/10/00 - Added Spinlocks for smp.
  *
+ *  3/10/00 - Enabled FDX and fixed bugs produced thereafter.
+ *  	      Put in smp code 
  *  To Do:
- *	IPv6 Multicast 
- *	
+ *
  *  If Problems do Occur
  *  Most problems can be rectified by either closing and opening the interface
  *  (ifconfig down and up) or rmmod and insmod'ing the driver (a bit difficult
@@ -85,7 +84,7 @@
  */
 
 static char *version = 
-"Olympic.c v0.2.1 1/10/00 - Peter De Schrijver & Mike Phillips" ; 
+"Olympic.c v0.4.0 3/10/00 - Peter De Schrijver & Mike Phillips" ; 
 
 static char *open_maj_error[]  = {"No error", "Lobe Media Test", "Physical Insertion",
 				   "Address Verification", "Neighbor Notification (Ring Poll)",
@@ -397,7 +396,7 @@
 #if OLYMPIC_NETWORK_MONITOR
 		writew(ntohs(OPEN_ADAPTER_ENABLE_FDX | OPEN_ADAPTER_PASS_ADC_MAC | OPEN_ADAPTER_PASS_ATT_MAC | OPEN_ADAPTER_PASS_BEACON),init_srb+8);
 #else
-		writew(OPEN_ADAPTER_ENABLE_FDX,init_srb+8);
+		writew(ntohs(OPEN_ADAPTER_ENABLE_FDX),init_srb+8);
 #endif		
 
 		if (olympic_priv->olympic_laa[0]) {
@@ -755,7 +754,7 @@
 	if (!(sisr & SISR_MI)) /* Interrupt isn't for us */ 
 		return ;
 
-	spin_lock(&olympic_priv->olympic_lock) ; 
+	spin_lock(&olympic_priv->olympic_lock);
 
 	if (dev->interrupt) 
 		printk(KERN_WARNING "%s: Re-entering interrupt \n",dev->name) ; 
@@ -835,7 +834,9 @@
 	dev->interrupt = 0 ;  
 
 	writel(SISR_MI,olympic_mmio+SISR_MASK_SUM);
+
 	spin_unlock(&olympic_priv->olympic_lock) ; 
+
 }	
 
 static int olympic_xmit(struct sk_buff *skb, struct device *dev) 
@@ -844,13 +845,12 @@
 	__u8 *olympic_mmio=olympic_priv->olympic_mmio;
 	unsigned long flags ; 
 
-	spin_lock_irqsave(&olympic_priv->olympic_lock, flags) ; 
-
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
-		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ; 
 		return 1;
 	}
 
+	spin_lock_irqsave(&olympic_priv->olympic_lock, flags) ; 
+
 	if(olympic_priv->free_tx_ring_entries) {
 		olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].buffer=virt_to_bus(skb->data);
 		olympic_priv->olympic_tx_ring[olympic_priv->tx_ring_free].status_length=skb->len | (0x80000000);
@@ -864,13 +864,12 @@
 		writew((((readw(olympic_mmio+TXENQ_1)) & 0x8000) ^ 0x8000) | 1,olympic_mmio+TXENQ_1);
 
 		dev->tbusy=0;		
-		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ; 
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock, flags) ; 
 		return 0;
 	} else {
-		spin_unlock_irqrestore(&olympic_priv->olympic_lock,flags) ; 
+		spin_unlock_irqrestore(&olympic_priv->olympic_lock, flags) ; 
 		return 1;
-	} 
-
+	}	
 }
 	
 
@@ -951,9 +950,9 @@
 	options = olympic_priv->olympic_copy_all_options; 
 
 	if (dev->flags&IFF_PROMISC)  
-		options |= (3<<5) ; /* All LLC and MAC frames, all through the main rx channel */  
+		options |= 0x61 ; 
 	else
-		options &= ~(3<<5) ; 
+		options &= ~0x61 ; 
 
 	if (dev->mc_count) {  
 		set_mc_list = 1 ; 
@@ -1228,7 +1227,7 @@
 	__u16 lan_status = 0, lan_status_diff  ; /* Initialize to stop compiler warning */
 	__u8 fdx_prot_error ; 
 	__u16 next_ptr;
-
+	int i ; 
 #if OLYMPIC_NETWORK_MONITOR
 	struct trh_hdr *mac_hdr ; 
 #endif
@@ -1288,7 +1287,7 @@
 
 		/* Is the ASB free ? */ 	
 		
-		if (!(readl(olympic_priv->olympic_mmio + SISR) & SISR_ASB_FREE)) {
+		if (readb(asb_block + 2) != 0xff) { 
 			olympic_priv->asb_queued = 1 ; 
 			writel(LISR_ASB_FREE_REQ,olympic_priv->olympic_mmio+LISR_SUM); 
 			return ; 	
@@ -1307,7 +1306,7 @@
 		return ; 	
 		
 	} else if (readb(arb_block) == ARB_LAN_CHANGE_STATUS) { /* Lan.change.status */
-		lan_status = readw(arb_block+6);
+		lan_status = ntohs(readw(arb_block+6)) ;
 		fdx_prot_error = readb(arb_block+8) ; 
 		
 		/* Issue ARB Free */
@@ -1335,11 +1334,20 @@
 			dev->tbusy = 1 ;
 			dev->interrupt = 1 ; 
 			dev->start = 0 ; 
+	
 			olympic_priv->srb = readw(olympic_priv->olympic_lap + LAPWWO) ; 
+			olympic_priv->rx_status_last_received++;
+			olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+			for(i=0;i<OLYMPIC_RX_RING_SIZE;i++) {
+				dev_kfree_skb(olympic_priv->rx_ring_skb[olympic_priv->rx_status_last_received]);
+				olympic_priv->rx_status_last_received++;
+				olympic_priv->rx_status_last_received&=OLYMPIC_RX_RING_SIZE-1;
+			}
+
 			free_irq(dev->irq,dev);
 			
 			printk(KERN_WARNING "%s: Adapter has been closed \n", dev->name) ; 
-	
+			MOD_DEC_USE_COUNT ; 
 		} /* If serious error */
 		
 		if (olympic_priv->olympic_message_level) { 
diff -urN linux-2.2.15-pre14/drivers/net/olympic.h linux/drivers/net/olympic.h
--- linux-2.2.15-pre14/drivers/net/olympic.h	Mon Dec  3 22:01:23 2001
+++ linux/drivers/net/olympic.h	Mon Dec  3 22:01:29 2001
@@ -244,7 +244,7 @@
 	__u8 *olympic_mmio;
 	__u8 *olympic_lap;
 
-	spinlock_t	olympic_lock ; 
+	spinlock_t olympic_lock ; 
 
 	volatile int srb_queued;    /* True if an SRB is still posted */	
 	struct wait_queue *srb_wait;
@@ -282,7 +282,7 @@
 	
 	__u8  phys_addr[4] ; 
 	__u8  up_node_addr[6] ; 
-	__u8  up_phys_addr[6] ; 
+	__u8  up_phys_addr[4] ; 
 	__u8  poll_addr[6] ; 
 	__u16 reserved ; 
 	__u16 acc_priority ; 
diff -urN linux-2.2.15-pre14/drivers/net/sktr.c linux/drivers/net/sktr.c
--- linux-2.2.15-pre14/drivers/net/sktr.c	Mon Dec  3 22:01:23 2001
+++ linux/drivers/net/sktr.c	Mon Dec  3 22:01:29 2001
@@ -131,9 +131,7 @@
 
 static int AdapterNum = 0;
 
-#ifdef MODULE
 static int rate[SKTR_MAX_ADAPTERS] 	= { SPEED_16,  };
-#endif
 
 /* Use 0 for production, 1 for verification, 2 for debug, and
  * 3 for very verbose debug.
diff -urN linux-2.2.15-pre14/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- linux-2.2.15-pre14/drivers/scsi/hosts.h	Mon Dec  3 22:01:23 2001
+++ linux/drivers/scsi/hosts.h	Mon Dec  3 22:01:29 2001
@@ -484,10 +484,10 @@
 #ifdef CONFIG_SCSI_PLUTO_MODULE
 #define SD_EXTRA_DEVS 40
 #else
-#define SD_EXTRA_DEVS 16
+#define SD_EXTRA_DEVS 21
 #endif
-#define ST_EXTRA_DEVS 2
-#define SR_EXTRA_DEVS 4
+#define ST_EXTRA_DEVS 3
+#define SR_EXTRA_DEVS 8
 #define SG_EXTRA_DEVS (SD_EXTRA_DEVS + SR_EXTRA_DEVS + ST_EXTRA_DEVS)
 
 #endif
diff -urN linux-2.2.15-pre14/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- linux-2.2.15-pre14/drivers/scsi/megaraid.c	Mon Dec  3 22:01:23 2001
+++ linux/drivers/scsi/megaraid.c	Mon Dec  3 22:01:29 2001
@@ -2,14 +2,14 @@
  *
  *                    Linux MegaRAID device driver
  *
- * Copyright 1998 American Megatrends Inc.
+ * Copyright 1999 American Megatrends Inc.
  *
  *              This program is free software; you can redistribute it and/or
  *              modify it under the terms of the GNU General Public License
  *              as published by the Free Software Foundation; either version
  *              2 of the License, or (at your option) any later version.
  *
- * Version : 1.04
+ * Version : 1.07b
  * 
  * Description: Linux device driver for AMI MegaRAID controller
  *
@@ -111,6 +111,24 @@
  *    The addtional 32 bit field for 64bit address in the newly defined
  *      mailbox64 structure is set to 0 at this point.
  *
+ * Version 1.05
+ *    Changed the queing implementation for handling SCBs and completed
+ *      commands.
+ *    Added spinlocks in the interrupt service routine to enable the dirver
+ *      function in the SMP environment.
+ *    Fixed the problem of unnecessary aborts in the abort entry point, which
+ *      also enables the driver to handle large amount of I/O requests for
+ *      long duration of time.
+ *
+ * Version 1.07
+ *    Removed the usage of uaccess.h file for kernel versions less than
+ *    2.0.36, as this file is not present in those versions.
+ *
+ * Version 1.07b
+ *    The MegaRAID 466 cards with 3.00 firmware lockup and seem to very
+ *    occasionally hang. We check such cards and report them. You can
+ *    get firmware upgrades to flash the board to 3.10 for free.
+ *
  * BUGS:
  *     Some older 2.1 kernels (eg. 2.1.90) have a bug in pci.c that
  *     fails to detect the controller as a pci device on the system.
@@ -125,7 +143,8 @@
 #define CRLFSTR "\n"
 #define IOCTL_CMD_NEW  0x81
 
-#define MEGARAID_VERSION "v1.04 (August 16, 1999)"
+#define MEGARAID_VERSION "v107 (December 22, 1999)"
+
 
 #include <linux/config.h>
 #include <linux/version.h>
@@ -145,8 +164,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/malloc.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
@@ -169,7 +186,9 @@
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#if LINUX_VERSION_CODE > 0x020024
 #include <asm/uaccess.h>
+#endif
 
 #include "sd.h"
 #include "scsi.h"
@@ -209,31 +228,6 @@
 #define MAX_SERBUF 160
 #define COM_BASE 0x2f8
 
-#define ENQUEUE(obj,type,list,next) \
-{ type **node; long cpuflag; \
-  spin_lock_irqsave(&mega_lock,cpuflag);\
-  for(node=&(list); *node; node=(type **)&(*node)->##next); \
-  (*node) = obj; \
-  (*node)->##next = NULL; \
-  spin_unlock_irqrestore(&mega_lock,cpuflag);\
-}
-
-/* a non-locking version (if we already have the lock) */
-#define ENQUEUE_NL(obj,type,list,next) \
-{ type **node; \
-  for(node=&(list); *node; node=(type **)&(*node)->##next); \
-  (*node) = obj; \
-  (*node)->##next = NULL; \
-}
-
-#define DEQUEUE(obj,type,list,next) \
-{ long cpuflag; \
-  spin_lock_irqsave(&mega_lock,cpuflag);\
-  if ((obj=list) != NULL) {\
-    list = (type *)(list)->##next; \
-  } \
-  spin_unlock_irqrestore(&mega_lock,cpuflag);\
-};
 
 u32 RDINDOOR (mega_host_config * megaCfg)
 {
@@ -265,19 +259,67 @@
 			 u_char * mboxData,
 			 mega_scb * scb,
 			 int intr);
-static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
 			 u32 * buffer, u32 * length);
 
 static int mega_busyWaitMbox(mega_host_config *);
 static void mega_runpendq (mega_host_config *);
-static void mega_rundoneq (void);
+static void mega_rundoneq (mega_host_config *);
 static void mega_cmd_done (mega_host_config *, mega_scb *, int);
 static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt);
-static inline void freeSgList(mega_host_config *megaCfg);
+static inline void mega_freeSgList(mega_host_config *megaCfg);
 static void mega_Convert8ldTo40ld(  mega_RAIDINQ  *inquiry,
                                     mega_Enquiry3 *enquiry3,
                                     megaRaidProductInfo *productInfo );
 
+
+
+
+#if LINUX_VERSION_CODE > 0x020100
+#  include <asm/spinlock.h>
+#  include <linux/smp.h>
+#  define cpuid smp_processor_id()
+#  if LINUX_VERSION_CODE < 0x020195
+#    define DRIVER_LOCK_T unsigned long cpu_flags = 0;
+#    define DRIVER_LOCK_INIT(p) \
+       spin_lock_init(&p->mega_lock);
+#    define DRIVER_LOCK(p) \
+       if(!p->cpu_lock_count[cpuid]) { \
+         spin_lock_irqsave(&p->mega_lock, cpu_flags); \
+         p->cpu_lock_count[cpuid]++; \
+       } else { \
+         p->cpu_lock_count[cpuid]++; \
+       }
+#    define DRIVER_UNLOCK(p) \
+       if(--p->cpu_lock_count[cpuid] == 0) \
+         spin_unlock_irqrestore(&p->mega_lock, cpu_flags);
+#    define IO_LOCK(p)   spin_lock_irqsave(&io_request_lock,cpu_flags);
+#    define IO_UNLOCK(p) spin_unlock_irqrestore(&io_request_lock,cpu_flags);
+#  else
+#    define DRIVER_LOCK_T
+#    define DRIVER_LOCK_INIT(p)
+#    define DRIVER_LOCK(p)
+#    define DRIVER_UNLOCK(p)
+#    define IO_LOCK_T unsigned long io_flags = 0;
+#    define IO_LOCK spin_lock_irqsave(&io_request_lock,io_flags);
+#    define IO_UNLOCK spin_unlock_irqrestore(&io_request_lock,io_flags);
+#  endif
+#else
+#  define cpuid 0
+#  define DRIVER_LOCK_T long cpu_flags;
+#  define DRIVER_LOCK_INIT(p)
+#  define DRIVER_LOCK(p) \
+       save_flags(cpu_flags); \
+       cli();
+#  define DRIVER_UNLOCK(p) \
+       restore_flags(cpu_flags);
+#  define IO_LOCK_T unsigned long io_flags = 0;
+#  define IO_LOCK(p)   DRIVER_LOCK(p)
+#  define IO_UNLOCK(p) DRIVER_UNLOCK(p)
+#  define le32_to_cpu(x) (x)
+#  define cpu_to_le32(x) (x)
+#endif
+
 /* set SERDEBUG to 1 to enable serial debugging */
 #define SERDEBUG 0
 #if SERDEBUG
@@ -297,6 +339,7 @@
 /*  Use "megaraid=skipXX" as LILO option to prohibit driver from scanning
     XX scsi id on each channel.  Used for Madrona motherboard, where SAF_TE
     processor id cannot be scanned */
+
 static char *megaraid;
 #if LINUX_VERSION_CODE > 0x20100
 #ifdef MODULE
@@ -314,13 +357,10 @@
 
 static mega_scb *pLastScb = NULL;
 
-/* Queue of pending/completed SCBs */
-static Scsi_Cmnd *qCompleted = NULL;
 
 #if SERDEBUG
 volatile static spinlock_t serial_lock;
 #endif
-volatile static spinlock_t mega_lock;
 
 struct proc_dir_entry proc_scsi_megaraid =
 {
@@ -386,7 +426,7 @@
 #define TRACE(A)
 #endif
 
-void callDone (Scsi_Cmnd * SCpnt)
+static void callDone (Scsi_Cmnd * SCpnt)
 {
   if (SCpnt->result) {
     TRACE (("*** %.08lx %.02x <%d.%d.%d> = %x\n", SCpnt->serial_number,
@@ -406,37 +446,66 @@
  * Free a SCB structure
  *=======================
  */
-static void freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
+static void mega_freeSCB (mega_host_config *megaCfg, mega_scb * pScb)
 {
-  mega_scb **ppScb;
+
+  mega_scb *pScbtmp;
+
+  if ((pScb == NULL) || (pScb->idx >= 0xFE)) {
+    return ;
+  }
 
   /* Unlink from pending queue */
-  for(ppScb=&megaCfg->qPending; *ppScb; ppScb=&(*ppScb)->next) {
-    if (*ppScb == pScb) {
-	*ppScb = pScb->next;
+
+  if(pScb == megaCfg->qPendingH) {
+    if(megaCfg->qPendingH == megaCfg->qPendingT ) 
+      megaCfg->qPendingH = megaCfg->qPendingT = NULL;
+    else {
+      megaCfg->qPendingH = megaCfg->qPendingH->next;
+    }
+    megaCfg->qPcnt--;
+  }
+  else {
+    for(pScbtmp=megaCfg->qPendingH; pScbtmp; pScbtmp=pScbtmp->next) {
+      if (pScbtmp->next == pScb) {
+        pScbtmp->next = pScb->next;
+        if(pScb == megaCfg->qPendingT) {
+          megaCfg->qPendingT = pScbtmp;
+        }
+        megaCfg->qPcnt--;
 	break;
     }
   }
+  }
 
-  /* Link back into list */
+  /* Link back into free list */
   pScb->state = SCB_FREE;
   pScb->SCpnt = NULL;
 
-  pScb->next     = megaCfg->qFree;
-  megaCfg->qFree = pScb;
+  if(megaCfg->qFreeH == (mega_scb *) NULL ) {
+    megaCfg->qFreeH = megaCfg->qFreeT = pScb;
+  }
+  else {
+    megaCfg->qFreeT->next  = pScb;
+    megaCfg->qFreeT = pScb;
+  }
+  megaCfg->qFreeT->next = NULL;
+  megaCfg->qFcnt++;
+
 }
 
 /*===========================
  * Allocate a SCB structure
  *===========================
  */
-static mega_scb * allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
+static mega_scb * mega_allocateSCB (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt)
 {
   mega_scb *pScb;
 
   /* Unlink command from Free List */
-  if ((pScb = megaCfg->qFree) != NULL) {
-    megaCfg->qFree = pScb->next;
+  if ((pScb = megaCfg->qFreeH) != NULL) {
+    megaCfg->qFreeH = pScb->next;
+    megaCfg->qFcnt--;
     
     pScb->isrcount = jiffies;
     pScb->next  = NULL;
@@ -455,62 +524,72 @@
  * Initialize SCB structures
  *================================================
  */
-static int initSCB (mega_host_config * megaCfg)
+static int mega_initSCB (mega_host_config * megaCfg)
 {
   int idx;
 
-  megaCfg->qFree = NULL;
+  megaCfg->qFreeH = NULL;
+  megaCfg->qFcnt = 0;
+#if DEBUG
+if(megaCfg->max_cmds >= MAX_COMMANDS) {
+printk("megaraid:ctlr max cmds = %x : MAX_CMDS = %x", megaCfg->max_cmds, MAX_COMMANDS);
+}
+#endif
+
   for (idx = megaCfg->max_cmds-1; idx >= 0; idx--) {
     megaCfg->scbList[idx].idx    = idx;
     megaCfg->scbList[idx].sgList = kmalloc(sizeof(mega_sglist) * MAX_SGLIST,
 					   GFP_ATOMIC | GFP_DMA);
     if (megaCfg->scbList[idx].sgList == NULL) {
       printk(KERN_WARNING "Can't allocate sglist for id %d\n",idx);
-      freeSgList(megaCfg);
+      mega_freeSgList(megaCfg);
       return -1;
     }
     
     if (idx < MAX_COMMANDS) {
       /* Link to free list */
-      freeSCB(megaCfg, &megaCfg->scbList[idx]);
+      mega_freeSCB(megaCfg, &megaCfg->scbList[idx]);
     }
   }
   return 0;
 }
 
 /* Run through the list of completed requests */
-static void mega_rundoneq ()
+static void mega_rundoneq (mega_host_config *megaCfg)
 {
   Scsi_Cmnd *SCpnt;
 
-  while (1) {
-    DEQUEUE (SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
-    if (SCpnt == NULL)
-      return;
+  while ((SCpnt = megaCfg->qCompletedH) != NULL) {
+    megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
+    megaCfg->qCcnt--;
 
+    SCpnt->host_scribble = (unsigned char *) NULL ; // XC : sep 14
     /* Callback */
     callDone (SCpnt);
   }
+  megaCfg->qCompletedH = megaCfg->qCompletedT = NULL;
 }
 
 /*
-  Runs through the list of pending requests
-  Assumes that mega_lock spin_lock has been acquired.
-*/
+ * Runs through the list of pending requests
+ * Assumes that mega_lock spin_lock has been acquired.
+ */
 static void mega_runpendq(mega_host_config *megaCfg)
 {
   mega_scb *pScb;
 
   /* Issue any pending commands to the card */
-  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
     if (pScb->state == SCB_ACTIVE) {
-      megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1);
+      if(megaIssueCmd(megaCfg, pScb->mboxData, pScb, 1))
+	return;
     }
   }
 }
 
 /* Add command to the list of completed requests */
-static void mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
+static void
+mega_cmd_done (mega_host_config * megaCfg, mega_scb * pScb, 
 			   int status)
 {
   int islogical;
@@ -524,7 +603,6 @@
   }
 
   SCpnt = pScb->SCpnt;
-  /*freeSCB(megaCfg, pScb);*/ /*delay this to the end of this func.*/
   pthru = &pScb->pthru;
   mbox = (mega_mailbox *) &pScb->mboxData;
 
@@ -533,7 +611,7 @@
 	TRACE(("pScb->idx = ",pScb->idx));
 	TRACE(("pScb->state = ",pScb->state));
 	TRACE(("pScb->state = ",pScb->state));
-	printk("Problem...!\n");
+	printk("megaraid:Problem...!\n");
 	while(1);
   }
 
@@ -588,10 +666,18 @@
   /* not IOCTL_CMD_NEW SCB, freeSCB()*/
   /* For IOCTL_CMD_NEW SCB, delay freeSCB() in megaraid_queue()
    * after copy data back to user space*/
-     freeSCB(megaCfg, pScb);
+     mega_freeSCB(megaCfg, pScb);
 
   /* Add Scsi_Command to end of completed queue */
-  ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    if( megaCfg->qCompletedH == NULL ) {
+      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+    }
+    else {
+      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+      megaCfg->qCompletedT = SCpnt;
+   }
+   megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+   megaCfg->qCcnt++;
 }
 
 /*-------------------------------------------------------------------
@@ -631,13 +717,11 @@
 
   if ( islogical ) {
 	lun = (SCpnt->target * 8) + lun;
-#if 1
         if ( lun > FC_MAX_LOGICAL_DRIVES ){
             SCpnt->result = (DID_BAD_TARGET << 16);
             callDone (SCpnt);
             return NULL;
         }
-#endif
   }
   /*-----------------------------------------------------
    *
@@ -661,7 +745,7 @@
     case READ_CAPACITY:
     case INQUIRY:
       /* Allocate a SCB and initialize passthru */
-      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
 	callDone (SCpnt);
 	return NULL;
@@ -692,7 +776,7 @@
     case READ_10:
     case WRITE_10:
       /* Allocate a SCB and initialize mailbox */
-      if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+      if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
 	SCpnt->result = (DID_ERROR << 16);
 	callDone (SCpnt);
 	return NULL;
@@ -728,7 +812,7 @@
       }
 
       /* Calculate Scatter-Gather info */
-      mbox->numsgelements = build_sglist (megaCfg, pScb,
+      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
 					  (u32 *) & mbox->xferaddr,
 					  (u32 *) & seg);
 
@@ -747,7 +831,7 @@
    *-----------------------------------------------------*/
   else {
     /* Allocate a SCB and initialize passthru */
-    if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+    if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
       SCpnt->result = (DID_ERROR << 16);
       callDone (SCpnt);
       return NULL;
@@ -768,7 +852,7 @@
     pthru->cdblen = SCpnt->cmd_len;
     memcpy (pthru->cdb, SCpnt->cmnd, SCpnt->cmd_len);
 
-    pthru->numsgelements = build_sglist (megaCfg, pScb,
+    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
 					 (u32 *) & pthru->dataxferaddr,
 					 (u32 *) & pthru->dataxferlen);
 
@@ -795,20 +879,12 @@
   unsigned char *data = (unsigned char *)SCpnt->request_buffer;
   int i;
 
-  if ((pScb = allocateSCB (megaCfg, SCpnt)) == NULL) {
+  if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {
     SCpnt->result = (DID_ERROR << 16);
     callDone (SCpnt);
     return NULL;
   }
 
-#if 0
-  printk("\nBUF: ");
-  for (i=0;i<18;i++) {
-     printk(" %x",data[i]);
-  }
-  printk("......\n");
-#endif
-
   mboxdata = (u8 *) & pScb->mboxData;
   mbox = (mega_ioctl_mbox *) & pScb->mboxData;
   mailbox = (mega_mailbox *) & pScb->mboxData;
@@ -831,7 +907,7 @@
     mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;
     mailbox->xferaddr = virt_to_bus (pthru);
 
-    pthru->numsgelements = build_sglist (megaCfg, pScb,
+    pthru->numsgelements = mega_build_sglist (megaCfg, pScb,
 					 (u32 *) & pthru->dataxferaddr,
 					 (u32 *) & pthru->dataxferlen);
 
@@ -843,6 +919,14 @@
   }
   /* else normal (nonpassthru) command */
 
+#if LINUX_VERSION_CODE > 0x020024
+/*
+ * usage of the function copy from user is used in case of data more than
+ * 4KB.  This is used only with adapters which supports more than 8 logical
+ * drives.  This feature is disabled on kernels earlier or same as 2.0.36
+ * as the uaccess.h file is not available with those kernels.
+ */
+
   if (SCpnt->cmnd[0] == IOCTL_CMD_NEW) { 
             /* use external data area for large xfers  */
      /* If cmnd[0] is set to IOCTL_CMD_NEW then *
@@ -868,6 +952,7 @@
       copy_from_user(kern_area,user_area,xfer_size);
       pScb->kern_area = kern_area;
   }
+#endif
 
   mbox->cmd = data[0];
   mbox->channel = data[1];
@@ -890,7 +975,7 @@
   } 
   else {
 
-      mbox->numsgelements = build_sglist (megaCfg, pScb,
+      mbox->numsgelements = mega_build_sglist (megaCfg, pScb,
 				      (u32 *) & mbox->xferaddr,
 				      (u32 *) & seg);
 
@@ -918,32 +1003,36 @@
 }
 #endif
 
+#if DEBUG
+static unsigned int cum_time = 0;
+static unsigned int cum_time_cnt = 0;
+#endif
+
 /*--------------------------------------------------------------------
  * Interrupt service routine
  *--------------------------------------------------------------------*/
 static void megaraid_isr (int irq, void *devp, struct pt_regs *regs)
 {
+#if LINUX_VERSION_CODE >= 0x20100
+  IO_LOCK_T
+#endif
   mega_host_config    *megaCfg;
   u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];
-  u32 dword;
+  u32 dword=0;
   mega_mailbox *mbox;
   mega_scb *pScb;
-  long flags;
-  int qCnt, qStatus;
+  u_char qCnt, qStatus;
+  u_char            completed[MAX_FIRMWARE_STATUS];
+  Scsi_Cmnd *SCpnt;
 
   megaCfg = (mega_host_config *) devp;
   mbox = (mega_mailbox *)tmpBox;
 
-#if LINUX_VERSION_CODE >= 0x20100
-  spin_lock_irqsave (&io_request_lock, flags);
-#endif
-
-  while (megaCfg->host->irq == irq) {
-
-    spin_lock_irqsave (&mega_lock, flags);
+  if (megaCfg->host->irq == irq) {
 
     if (megaCfg->flag & IN_ISR) {
       TRACE (("ISR called reentrantly!!\n"));
+      printk ("ISR called reentrantly!!\n");
     }
 
     megaCfg->flag |= IN_ISR;
@@ -952,48 +1041,67 @@
 	printk(KERN_WARNING "Error: mailbox busy in isr!\n");
     }
 
-
     /* Check if a valid interrupt is pending */
     if (megaCfg->flag & BOARD_QUARTZ) {
       dword = RDOUTDOOR (megaCfg);
       if (dword != 0x10001234) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-	spin_unlock_irqrestore (&mega_lock, flags);
-	break;
+	return;
       }
-      WROUTDOOR (megaCfg, dword);
-
-      /* Copy to temp location */
-      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
-
-      /* Acknowledge interrupt */
-      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
-      while (RDINDOOR (megaCfg) & 0x02);
     }
     else {
       byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);
       if ((byte & VALID_INTR_BYTE) == 0) {
 	/* Spurious interrupt */
 	megaCfg->flag &= ~IN_ISR;
-	spin_unlock_irqrestore (&mega_lock, flags);
-	break;
+	return;
       }
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
+    }
+
+    for(idx=0;idx<MAX_FIRMWARE_STATUS;idx++ ) completed[idx] = 0;
+
+#if LINUX_VERSION_CODE >= 0x20100
+    IO_LOCK;
+#endif
+
+    qCnt = 0xff;
+    while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) 
+      ;
+
+    qStatus = 0xff;
+    while ((qStatus = megaCfg->mbox->status) == 0xFF)
+      ;
 
-      /* Copy to temp location */
-      memcpy(tmpBox, (mega_mailbox *)megaCfg->mbox, MAILBOX_SIZE);
+    /* Get list of completed requests */
+    for (idx = 0; idx<qCnt; idx++) {
+      while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {
+	printk("p");
+      }
+      completed[idx] = sIdx;
+      sIdx = 0xFF;
+    }
 
+    if (megaCfg->flag & BOARD_QUARTZ) {
+      WROUTDOOR (megaCfg, dword);
       /* Acknowledge interrupt */
+      WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);
+      while (RDINDOOR (megaCfg) & 0x02);
+    }
+    else {
       CLEAR_INTR (megaCfg->host->io_port);
     }
 
-    qCnt = mbox->numstatus;
-    qStatus = mbox->status;
+#if DEBUG
+    if(qCnt >= MAX_FIRMWARE_STATUS) {
+      printk("megaraid_isr: cmplt=%d ", qCnt);
+    }
+#endif
 
     for (idx = 0; idx < qCnt; idx++) {
-      sIdx = mbox->completed[idx];
-      if (sIdx > 0) {
+      sIdx = completed[idx];
+      if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {
 	pScb = &megaCfg->scbList[sIdx - 1];
 
 	/* ASSERT(pScb->state == SCB_ISSUED); */
@@ -1001,12 +1109,30 @@
 #if DEBUG
 	if (((jiffies) - pScb->isrcount) > maxCmdTime) {
 	  maxCmdTime = (jiffies) - pScb->isrcount;
-	  printk("cmd time = %u\n", maxCmdTime);
+	  printk("megaraid_isr : cmd time = %u\n", maxCmdTime);
 	}
 #endif
-
+/*
+ * Assuming that the scsi command, for which an abort request was received
+ * earlier has completed.
+ */
 	if (pScb->state == SCB_ABORTED) {
-	  printk("Received aborted SCB! %u\n", (int)((jiffies)-pScb->isrcount));
+          SCpnt = pScb->SCpnt;
+	}
+	if (pScb->state == SCB_RESET) {
+          SCpnt = pScb->SCpnt;
+	  mega_freeSCB (megaCfg, pScb);
+	  SCpnt->result = (DID_RESET << 16) ;
+          if( megaCfg->qCompletedH == NULL ) {
+            megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+          }
+          else {
+            megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+            megaCfg->qCompletedT = SCpnt;
+          }
+          megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+          megaCfg->qCcnt++;
+          continue;
 	}
 
         if (*(pScb->SCpnt->cmnd)==IOCTL_CMD_NEW) 
@@ -1017,24 +1143,23 @@
 	mega_cmd_done(megaCfg, pScb, qStatus);
 
       }
-
+      else {
+        printk("megaraid: wrong cmd id completed from firmware:id=%x\n",sIdx);
+	for(;;);
+      }
     }
-    spin_unlock_irqrestore (&mega_lock, flags);
-
-    megaCfg->flag &= ~IN_ISR;
 
-    mega_rundoneq();
+    mega_rundoneq(megaCfg);
 
+    megaCfg->flag &= ~IN_ISR;
     /* Loop through any pending requests */
-    spin_lock_irqsave(&mega_lock, flags);
     mega_runpendq(megaCfg);
-    spin_unlock_irqrestore(&mega_lock,flags);
+#if LINUX_VERSION_CODE >= 0x20100
+    IO_UNLOCK;
+#endif
 
   }
 
-#if LINUX_VERSION_CODE >= 0x20100
-  spin_unlock_irqrestore (&io_request_lock, flags);
-#endif
 }
 
 /*==================================================*/
@@ -1078,7 +1203,6 @@
   mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;
   u_char byte;
   u32 cmdDone;
-  Scsi_Cmnd *SCpnt;
   u32 phys_mbox;
   u8 retval=-1;
 
@@ -1087,18 +1211,12 @@
 
   phys_mbox = virt_to_bus (megaCfg->mbox);
 
-#if 0
-  if (intr && mbox->busy) {
-    return 0;
-  }
-#endif
-
 #if DEBUG
   showMbox(pScb);
 #endif
 
   /* Wait until mailbox is free */
-  while (mega_busyWaitMbox (megaCfg)) {
+  if (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox......!!\n");
     udelay(1000);
 
@@ -1108,14 +1226,10 @@
     
     /* Abort command */
     if (pScb == NULL) {
-	printk("NULL pScb in megaIssue\n");
 	TRACE(("NULL pScb in megaIssue\n"));
+	printk("NULL pScb in megaIssue\n");
     }
-    SCpnt = pScb->SCpnt;
-    freeSCB(megaCfg, pScb);
-
-    SCpnt->result = (DID_ABORT << 16);
-    callDone(SCpnt);
+    mega_cmd_done (megaCfg, pScb, 0x08);
     return -1;
   }
 
@@ -1154,7 +1268,6 @@
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-	mega_rundoneq ();
       }
 
       WRINDOOR (megaCfg, phys_mbox | 0x2);
@@ -1168,26 +1281,25 @@
       while (!((byte = READ_PORT (megaCfg->host->io_port, INTR_PORT)) & INTR_VALID));
       WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);
 
-
       ENABLE_INTR (megaCfg->host->io_port);
       CLEAR_INTR (megaCfg->host->io_port);
 
       if (pScb) {
 	mega_cmd_done (megaCfg, pScb, mbox->status);
-	mega_rundoneq ();
       }
       else {
 	TRACE (("Error: NULL pScb!\n"));
       }
-
     }
     enable_irq(megaCfg->host->irq);
     retval=mbox->status;
   }
+#if DEBUG
   while (mega_busyWaitMbox (megaCfg)) {
     printk("Blocked mailbox on exit......!\n");
     udelay(1000);
   }
+#endif
 
   return retval;
 }
@@ -1195,7 +1307,7 @@
 /*-------------------------------------------------------------------
  * Copies data to SGLIST
  *-------------------------------------------------------------------*/
-static int build_sglist (mega_host_config * megaCfg, mega_scb * scb,
+static int mega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,
 	      u32 * buffer, u32 * length)
 {
   struct scatterlist *sgList;
@@ -1254,9 +1366,7 @@
   paddr = (paddr + 4 + 16) & 0xfffffff0;
 
   /* Register mailbox area with the firmware */
-  if (megaCfg->flag & BOARD_QUARTZ) {
-  }
-  else {
+  if (!(megaCfg->flag & BOARD_QUARTZ)) {
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT0, paddr & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT1, (paddr >> 8) & 0xFF);
     WRITE_PORT (megaCfg->host->io_port, MBOX_PORT2, (paddr >> 16) & 0xFF);
@@ -1314,8 +1424,6 @@
   u32 paddr;
   u8 retval;
 
-  spin_lock_init (&mega_lock);
-
   /* Initialize adapter inquiry mailbox*/
   paddr = virt_to_bus (megaCfg->mega_buffer);
   mbox = (mega_mailbox *) mboxData;
@@ -1375,28 +1483,17 @@
     /*(megaCfg->flag & BOARD_40LD)?FC_MAX_TARGETS_PER_CHANNEL:MAX_TARGET+1;*/ 
   megaCfg->host->max_lun =              /* max lun */
     (megaCfg->flag & BOARD_40LD) ? FC_MAX_LOGICAL_DRIVES : MAX_LOGICAL_DRIVES; 
+  megaCfg->host->cmd_per_lun = MAX_CMD_PER_LUN;
 
   megaCfg->numldrv = enquiry3Pnt->numLDrv;
   megaCfg->max_cmds = megaCfg->productInfo.MaxConcCmds;
+  if(megaCfg->max_cmds > MAX_COMMANDS) megaCfg->max_cmds = MAX_COMMANDS - 1;
 
-#if 0 
-  int i;
-  printk (KERN_DEBUG "---- Logical drive info from enquiry3 struct----\n");
-  for (i = 0; i < megaCfg->numldrv; i++) {
-    printk ("%d: size: %d prop: %x state: %x\n", i,
-	    enquiry3Pnt->lDrvSize[i],
-	    enquiry3Pnt->lDrvProp[i],
-	    enquiry3Pnt->lDrvState[i]);
-  }
+  megaCfg->host->can_queue   = megaCfg->max_cmds;
 
-  printk (KERN_DEBUG "---- Physical drive info ----\n");
-  for (i = 0; i < FC_MAX_PHYSICAL_DEVICES; i++) {
-    if (i && !(i % 8))
-      printk ("\n");
-    printk ("%d: %x   ", i, enquiry3Pnt->pDrvState[i]);
+  if (megaCfg->host->can_queue >= MAX_COMMANDS) {
+    megaCfg->host->can_queue = MAX_COMMANDS-1;
   }
-  printk ("\n");
-#endif
 
 #ifdef HP			/* use HP firmware and bios version encoding */
   sprintf (megaCfg->fwVer, "%c%d%d.%d%d",
@@ -1443,7 +1540,7 @@
   return 0;
 }
 
-int findCard (Scsi_Host_Template * pHostTmpl,
+int mega_findCard (Scsi_Host_Template * pHostTmpl,
 	  u16 pciVendor, u16 pciDev,
 	  long flag)
 {
@@ -1456,10 +1553,6 @@
 
 #if LINUX_VERSION_CODE < 0x20100
   while (!pcibios_find_device (pciVendor, pciDev, pciIdx, &pciBus, &pciDevFun)) {
-
-#if 0
-  } /* keep auto-indenters happy */
-#endif
 #else
   
   struct pci_dev *pdev = pci_devices;
@@ -1470,10 +1563,14 @@
 #endif
     if ((flag & BOARD_QUARTZ) && (skip_id == -1)) {
       u16 magic;
+#if LINUX_VERSION_CODE < 0x20100
       pcibios_read_config_word (pciBus, pciDevFun,
 				PCI_CONF_AMISIG,
 				&magic);
-      if (magic != AMI_SIGNATURE) {
+#else
+      pci_read_config_word (pdev, PCI_CONF_AMISIG, &magic);
+#endif
+      if ((magic != AMI_SIGNATURE) && (magic != AMI_SIGNATURE_471) ){
         pciIdx++;
 	continue;		/* not an AMI board */
       }
@@ -1518,8 +1615,15 @@
 	    host->host_no, (u_int) megaBase, megaIrq);
 
     /* Copy resource info into structure */
-    megaCfg->qPending = NULL;
-    megaCfg->qFree    = NULL;
+    megaCfg->qCompletedH = NULL;
+    megaCfg->qCompletedT = NULL;
+    megaCfg->qPendingH = NULL;
+    megaCfg->qPendingT = NULL;
+    megaCfg->qFreeH    = NULL;
+    megaCfg->qFreeT    = NULL;
+    megaCfg->qFcnt = 0;
+    megaCfg->qPcnt = 0;
+    megaCfg->qCcnt = 0;
     megaCfg->flag = flag;
     megaCfg->host = host;
     megaCfg->base = megaBase;
@@ -1549,10 +1653,43 @@
 
     mega_register_mailbox (megaCfg, virt_to_bus ((void *) &megaCfg->mailbox64));
     mega_i_query_adapter (megaCfg);
-    
+   
+    if (flag == BOARD_QUARTZ) {
+      /* Check to see if this is a Dell PERC RAID controller model 466 */
+      u16 subsysid, subsysvid;
+#if LINUX_VERSION_CODE < 0x20100
+      pcibios_read_config_word (pciBus, pciDevFun,
+				PCI_SUBSYSTEM_VENDOR_ID,
+				&subsysvid);
+      pcibios_read_config_word (pciBus, pciDevFun,
+				PCI_SUBSYSTEM_ID,
+				&subsysid);
+#else
+      pci_read_config_word (pdev, PCI_SUBSYSTEM_VENDOR_ID, &subsysvid);
+      pci_read_config_word (pdev, PCI_SUBSYSTEM_ID, &subsysid);
+#endif
+      if ( (subsysid == 0x1111) && (subsysvid == 0x1111) &&
+           (!strcmp(megaCfg->fwVer,"3.00") || !strcmp(megaCfg->fwVer,"3.01"))) {
+	printk(KERN_WARNING
+"megaraid: Your card is a Dell PERC 2/SC RAID controller with firmware\n"
+"megaraid: 3.00 or 3.01.  This driver is known to have corruption issues\n"
+"megaraid: with those firmware versions on this specific card.  In order\n"
+"megaraid: to protect your data, please upgrade your firmware to version\n"
+"megaraid: 3.10 or later, available from the Dell Technical Support web\n"
+"megaraid: site at\n"
+"http://support.dell.com/us/en/filelib/download/index.asp?fileid=2489\n");
+	megaraid_release (host);
+#ifdef MODULE	
+	continue;
+#else
+	while(1) schedule_timeout(1 * HZ);
+#endif	
+      }
+    }
+
     /* Initialize SCBs */
-    if (initSCB (megaCfg)) {
-      scsi_unregister (host);
+    if (mega_initSCB (megaCfg)) {
+      megaraid_release (host);
       continue;
     }
 
@@ -1589,9 +1726,9 @@
 
   printk ("megaraid: " MEGARAID_VERSION CRLFSTR);
 
-  count += findCard (pHostTmpl, 0x101E, 0x9010, 0);
-  count += findCard (pHostTmpl, 0x101E, 0x9060, 0);
-  count += findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+  count += mega_findCard (pHostTmpl, 0x101E, 0x9010, 0);
+  count += mega_findCard (pHostTmpl, 0x101E, 0x9060, 0);
+  count += mega_findCard (pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
 
   return count;
 }
@@ -1626,13 +1763,13 @@
     release_region (megaCfg->host->io_port, 16);
   }
 
-  freeSgList(megaCfg);
+  mega_freeSgList(megaCfg);
   scsi_unregister (pSHost);
 
   return 0;
 }
 
-static inline void freeSgList(mega_host_config *megaCfg)
+static inline void mega_freeSgList(mega_host_config *megaCfg)
 {
   int i;
 
@@ -1678,13 +1815,12 @@
  *-----------------------------------------------------------------*/
 int megaraid_queue (Scsi_Cmnd * SCpnt, void (*pktComp) (Scsi_Cmnd *))
 {
+  DRIVER_LOCK_T
   mega_host_config *megaCfg;
   mega_scb *pScb;
-  long flags;
-
-  spin_lock_irqsave(&mega_lock,flags);
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
+  DRIVER_LOCK(megaCfg);
 
   if (!(megaCfg->flag & (1L << SCpnt->channel))) {
     if (SCpnt->channel < SCpnt->host->max_channel)
@@ -1702,33 +1838,56 @@
   /* If driver in abort or reset.. cancel this command */
   if (megaCfg->flag & IN_ABORT) {
     SCpnt->result = (DID_ABORT << 16);
-    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    /* Add Scsi_Command to end of completed queue */
+    if( megaCfg->qCompletedH == NULL ) {
+      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+    }
+    else {
+      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+      megaCfg->qCompletedT = SCpnt;
+    }
+    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+    megaCfg->qCcnt++;
 
-    spin_unlock_irqrestore(&mega_lock,flags);
+    DRIVER_UNLOCK(megaCfg);
     return 0;
   }
   else if (megaCfg->flag & IN_RESET) {
     SCpnt->result = (DID_RESET << 16);
-    ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+    /* Add Scsi_Command to end of completed queue */
+    if( megaCfg->qCompletedH == NULL ) {
+      megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+    }
+    else {
+      megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+      megaCfg->qCompletedT = SCpnt;
+    }
+    megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+    megaCfg->qCcnt++;
 
-    spin_unlock_irqrestore(&mega_lock,flags);
+    DRIVER_UNLOCK(megaCfg);
     return 0;
   }
 
+  megaCfg->flag |= IN_QUEUE;
   /* Allocate and build a SCB request */
   if ((pScb = mega_build_cmd (megaCfg, SCpnt)) != NULL) {
               /*build SCpnt for IOCTL_CMD_NEW cmd in mega_ioctl()*/
     /* Add SCB to the head of the pending queue */
-    ENQUEUE_NL (pScb, mega_scb, megaCfg->qPending, next);
-
-    /* Issue any pending command to the card if not in ISR */
-    if (!(megaCfg->flag & IN_ISR)) {
-      mega_runpendq(megaCfg);
+    /* Add SCB to the head of the pending queue */
+    if( megaCfg->qPendingH == NULL ) {
+      megaCfg->qPendingH = megaCfg->qPendingT = pScb;
     }
     else {
-      printk("IRQ pend...\n");
+      megaCfg->qPendingT->next = pScb;
+      megaCfg->qPendingT = pScb;
     }
+    megaCfg->qPendingT->next = NULL;
+    megaCfg->qPcnt++;
+
+      mega_runpendq(megaCfg);
 
+#if LINUX_VERSION_CODE > 0x020024
     if ( SCpnt->cmnd[0]==IOCTL_CMD_NEW )
     {  /* user data from external user buffer */
           char *user_area;
@@ -1744,12 +1903,13 @@
 
           kfree(pScb->kern_area);
 
-          freeSCB(megaCfg, pScb);
+          mega_freeSCB(megaCfg, pScb);
     }
-
+#endif
   }
 
-  spin_unlock_irqrestore(&mega_lock,flags);
+  megaCfg->flag &= ~IN_QUEUE;
+  DRIVER_UNLOCK(megaCfg);
 
   return 0;
 }
@@ -1787,78 +1947,92 @@
 /*---------------------------------------------------------------------
  * Abort a previous SCSI request
  *---------------------------------------------------------------------*/
-int megaraid_abort (Scsi_Cmnd * SCpnt)
+int
+megaraid_abort (Scsi_Cmnd * SCpnt)
 {
   mega_host_config *megaCfg;
-  int   rc, idx;
-  long  flags;
+  int   rc; //, idx;
   mega_scb *pScb;
 
-  rc = SCSI_ABORT_SUCCESS;
-
-  spin_lock_irqsave (&mega_lock, flags);
+  rc = SCSI_ABORT_NOT_RUNNING;
 
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_ABORT;
 
-  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
+  for(pScb=megaCfg->qPendingH; pScb; pScb=pScb->next) {
     if (pScb->SCpnt == SCpnt) {
       /* Found an aborting command */
 #if DEBUG
       showMbox(pScb);
 #endif
 
-      printk("Abort: %d %u\n", 
-	     SCpnt->timeout_per_command,
-	     (uint)((jiffies) - pScb->isrcount));
+/*
+ * If the command is queued to be issued to the firmware, abort the scsi cmd,
+ * If the command is already aborted in a previous call to the _abort entry
+ *  point, return SCSI_ABORT_SNOOZE, suggesting a reset.
+ * If the command is issued to the firmware, which might complete after
+ *  some time, we will mark the scb as aborted, and return to the mid layer, 
+ *  that abort could not be done.
+ *  In the ISR, when this command actually completes, we will perform a normal
+ *  completion.
+ *
+ * Oct 27, 1999
+ */
 
       switch(pScb->state) {
       case SCB_ABORTED: /* Already aborted */
 	rc = SCSI_ABORT_SNOOZE;
 	break;
       case SCB_ISSUED: /* Waiting on ISR result */
-	rc = SCSI_ABORT_PENDING;
+	rc = SCSI_ABORT_NOT_RUNNING;
 	pScb->state = SCB_ABORTED;
 	break;
+      case SCB_ACTIVE: /* still on the pending queue */
+	mega_freeSCB (megaCfg, pScb);
+	SCpnt->result = (DID_ABORT << 16) ;
+        if( megaCfg->qCompletedH == NULL ) {
+          megaCfg->qCompletedH = megaCfg->qCompletedT = SCpnt;
+        }
+        else {
+          megaCfg->qCompletedT->host_scribble = (unsigned char *) SCpnt;
+          megaCfg->qCompletedT = SCpnt;
+        }
+        megaCfg->qCompletedT->host_scribble = (unsigned char *) NULL;
+        megaCfg->qCcnt++;
+	rc = SCSI_ABORT_SUCCESS;
+        break;
+      default:
+        printk("megaraid_abort: unknown command state!!\n");
+        rc = SCSI_ABORT_NOT_RUNNING;
+	break;
       }
+      break;
     }
   }
 
-#if 0
-  TRACE (("ABORT!!! %.08lx %.02x <%d.%d.%d>\n",
-	  SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
-	  SCpnt->lun));
-  for(pScb=megaCfg->qPending; pScb; pScb=pScb->next) {
-    if (pScb->SCpnt == SCpnt) { 
-      ser_printk("** %d<%x>  %c\n", pScb->SCpnt->pid, pScb->idx+1,
-		 pScb->state == SCB_ACTIVE ? 'A' : 'I');
+  megaCfg->flag &= ~IN_ABORT;
+
 #if DEBUG
-      showMbox(pScb);
-#endif
-    }
-  }
+if(megaCfg->flag & IN_QUEUE)  printk("ma:flag is in queue\n");
+if(megaCfg->qCompletedH == NULL) printk("ma:qchead == null\n");
 #endif
-
-  /*
-   * Walk list of SCBs for any that are still outstanding
-   */
-  for (idx = 0; idx < megaCfg->max_cmds; idx++) {
-    if (megaCfg->scbList[idx].state != SCB_FREE) {
-      if (megaCfg->scbList[idx].SCpnt == SCpnt) {
-	freeSCB (megaCfg, &megaCfg->scbList[idx]);
-
-	SCpnt->result = (DID_ABORT << 16) | (SUGGEST_RETRY << 24);
-	ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
-      }
-    }
-  }
   
-  megaCfg->flag &= ~IN_ABORT;
-
-  spin_unlock_irqrestore (&mega_lock, flags);
-
-  mega_rundoneq();
+/*
+ * This is required here to complete any completed requests to be communicated
+ * over to the mid layer.
+ * Calling just mega_rundoneq() did not work.
+ */
+if(megaCfg->qCompletedH) {
+  SCpnt = megaCfg->qCompletedH;
+  megaCfg->qCompletedH = (Scsi_Cmnd *)SCpnt->host_scribble;
+  megaCfg->qCcnt--;
+
+  SCpnt->host_scribble = (unsigned char *) NULL ;
+  /* Callback */
+  callDone (SCpnt);
+}
+  mega_rundoneq(megaCfg);
 
   return rc;
 }
@@ -1870,14 +2044,18 @@
 {
   mega_host_config *megaCfg;
   int idx;
-  long flags;
-
-  spin_lock_irqsave (&mega_lock, flags);
+  int rc;
+  mega_scb *pScb;
 
+  rc = SCSI_RESET_NOT_RUNNING;
   megaCfg = (mega_host_config *) SCpnt->host->hostdata;
 
   megaCfg->flag |= IN_RESET;
 
+  printk ("megaraid_RESET: %.08lx cmd=%.02x <c=%d.t=%d.l=%d>, flag = %x\n",
+	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
+	  SCpnt->lun, rstflags);
+
   TRACE (("RESET: %.08lx %.02x <%d.%d.%d>\n",
 	SCpnt->serial_number, SCpnt->cmnd[0], SCpnt->channel, SCpnt->target,
 	  SCpnt->lun));
@@ -1888,20 +2066,18 @@
   for (idx = 0; idx < megaCfg->max_cmds; idx++) {
     if (megaCfg->scbList[idx].state != SCB_FREE) {
       SCpnt = megaCfg->scbList[idx].SCpnt;
+      pScb = &megaCfg->scbList[idx];
       if (SCpnt != NULL) {
-	freeSCB (megaCfg, &megaCfg->scbList[idx]);
-	SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY << 24);
-	ENQUEUE_NL(SCpnt, Scsi_Cmnd, qCompleted, host_scribble);
+        pScb->state = SCB_RESET;
+        break;
       }
     }
   }
 
   megaCfg->flag &= ~IN_RESET;
 
-  spin_unlock_irqrestore (&mega_lock, flags);
-
-  mega_rundoneq();
-  return SCSI_RESET_PUNT;
+  mega_rundoneq(megaCfg);
+  return rc;
 }
 
 /*-------------------------------------------------------------
@@ -1947,4 +2123,3 @@
 
 #include "scsi_module.c"
 #endif
-
diff -urN linux-2.2.15-pre14/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- linux-2.2.15-pre14/drivers/scsi/megaraid.h	Mon Dec  3 22:01:23 2001
+++ linux/drivers/scsi/megaraid.h	Mon Dec  3 22:01:29 2001
@@ -8,6 +8,7 @@
 #define IN_ISR                  0x80000000L
 #define IN_ABORT                0x40000000L
 #define IN_RESET                0x20000000L
+#define IN_QUEUE                0x10000000L
 #define BOARD_QUARTZ            0x08000000L
 #define BOARD_40LD              0x04000000L
 
@@ -21,9 +22,15 @@
 
 #define MEGA_CMD_TIMEOUT        10
 
-#define MAX_SGLIST              17
-#define MAX_COMMANDS            250
+/* Feel free to fiddle with these.. max values are:
+   SGLIST     0..26
+   COMMANDS   0..253
+   CMDPERLUN  0..63
+*/
+#define MAX_SGLIST              0x1A
+#define MAX_COMMANDS            127
 #define MAX_CMD_PER_LUN         63
+#define MAX_FIRMWARE_STATUS     46
 
 #define MAX_LOGICAL_DRIVES      8
 #define MAX_CHANNEL             5
@@ -100,6 +107,7 @@
 #define PCI_CONF_IRQ_OFFSET        0x3c
 #define PCI_CONF_AMISIG            0xa0
 #define AMI_SIGNATURE              0x3344
+#define AMI_SIGNATURE_471          0xCCCC
 
 #if LINUX_VERSION_CODE < 0x20100
 #define MEGARAID \
@@ -505,7 +513,7 @@
     u32 dataxferlen;
 } mega_passthru;
 
-typedef struct _mega_mailbox {
+struct _mega_mailbox {
     /* 0x0 */ u8 cmd;
     /* 0x1 */ u8 cmdid;
     /* 0x2 */ u16 numsectors;
@@ -520,8 +528,9 @@
     /* 0x12 */ u8 completed[46];
     u8 mraid_poll;
     u8 mraid_ack;
-    u8 pad[16];
-} mega_mailbox;
+    u8 pad[16]; /* for alignment purposes */
+}__attribute__((packed));
+typedef struct _mega_mailbox mega_mailbox;
 
 typedef struct {
     u32 xferSegment;      /* for 64-bit controllers */
@@ -575,8 +584,16 @@
     u32 flag;
     u32 base;
  
-    mega_scb *qFree;
-    mega_scb *qPending;
+    mega_scb *qFreeH;
+    mega_scb *qFreeT;
+    mega_scb *qPendingH;
+    mega_scb *qPendingT;
+    
+    Scsi_Cmnd *qCompletedH;
+    Scsi_Cmnd *qCompletedT;
+    u32 qFcnt;
+    u32 qPcnt;
+    u32 qCcnt;
 
     u32 nReads[FC_MAX_LOGICAL_DRIVES];
     u32 nWrites[FC_MAX_LOGICAL_DRIVES];
diff -urN linux-2.2.15-pre14/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- linux-2.2.15-pre14/drivers/scsi/scsi.c	Mon Dec  3 22:01:23 2001
+++ linux/drivers/scsi/scsi.c	Mon Dec  3 22:01:29 2001
@@ -270,6 +270,7 @@
 						 * SCSI code to reset bus.*/
 {"QUANTUM","LPS525S","3110", BLIST_NOLUN},      /* Locks sometimes if polled for lun != 0 */
 {"QUANTUM","PD1225S","3110", BLIST_NOLUN},      /* Locks sometimes if polled for lun != 0 */
+{"QUANTUM","FIREBALL ST4.3S","0F0C",BLIST_NOLUN},/* Locks sometimes if polled for lun != 0 */
 {"MEDIAVIS","CDR-H93MV","1.31", BLIST_NOLUN},   /* Locks up if polled for lun != 0 */
 {"SANKYO", "CP525","6.64", BLIST_NOLUN},        /* causes failed REQ SENSE, extra reset */
 {"HP", "C1750A", "3226", BLIST_NOLUN},          /* scanjet iic */
@@ -281,6 +282,7 @@
 {"YAMAHA","CRW6416S","1.0c", BLIST_NOLUN},	/* Locks up if polled for lun != 0 */
 {"MITSUMI", "CD-R CR-2201CS", "6119", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
 {"RELISYS", "Scorpio", "*", BLIST_NOLUN},	/* responds to all LUN */
+{"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all LUN */
 
 /*
  * Other types of devices that have special flags.
diff -urN linux-2.2.15-pre14/fs/dquot.c linux/fs/dquot.c
--- linux-2.2.15-pre14/fs/dquot.c	Mon Dec  3 22:01:23 2001
+++ linux/fs/dquot.c	Mon Dec  3 22:01:29 2001
@@ -539,7 +539,6 @@
 struct dquot *get_empty_dquot(void)
 {
 	struct dquot *dquot;
-	int count;
 
 repeat:
 	dquot = find_best_free();
@@ -569,10 +568,9 @@
 	/*
 	 * Try pruning the dcache to free up some dquots ...
 	 */
-//	printk(KERN_DEBUG "get_empty_dquot: pruning %d\n", count);
 	if (prune_dcache(0, 128))
 	{
-		free_inode_memory(count);
+		free_inode_memory(10);
 		goto repeat;
 	}
 
@@ -1584,7 +1582,7 @@
 			break;
 		case Q_GETQUOTA:
 			if (((type == USRQUOTA && current->euid != id) ||
-			     (type == GRPQUOTA && in_group_p(id))) &&
+			     (type == GRPQUOTA && !in_egroup_p(id))) &&
 			    !capable(CAP_SYS_RESOURCE))
 				goto out;
 			break;
diff -urN linux-2.2.15-pre14/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- linux-2.2.15-pre14/fs/nfsd/nfsfh.c	Mon Dec  3 22:01:23 2001
+++ linux/fs/nfsd/nfsfh.c	Mon Dec  3 22:01:29 2001
@@ -690,6 +690,15 @@
 		return 1;
 	}
 
+	/* if nfsd_server is zero, NFSD_MAXFH will be zero too, so
+	 * find_fhe() will NEVER find the file handle NOR an empty space,
+	 * and expire_slot will not be able to expire any file handle,
+	 * because NFSD_MAXFH is zero ... */
+
+	if (nfsd_nservers <= 0) {
+		return 0;
+	}
+
 	expire_slot(cache);
 	goto repeat;
 }
diff -urN linux-2.2.15-pre14/include/asm-sparc/asm_offsets.h linux/include/asm-sparc/asm_offsets.h
--- linux-2.2.15-pre14/include/asm-sparc/asm_offsets.h	Tue Jan  4 10:12:24 2000
+++ linux/include/asm-sparc/asm_offsets.h	Mon Dec  3 22:01:29 2001
@@ -186,6 +186,8 @@
 #define ASIZ_task_parent_exec_id	0x00000004
 #define AOFF_task_self_exec_id	0x000005a0
 #define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_oom_kill_try	0x000005a4
+#define ASIZ_task_oom_kill_try	0x00000004
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
 #define AOFF_mm_mmap_avl	0x00000004
@@ -446,25 +448,27 @@
 #define AOFF_task_mm	0x00000668
 #define ASIZ_task_mm	0x00000004
 #define AOFF_task_sigmask_lock	0x0000066c
-#define ASIZ_task_sigmask_lock	0x00000008
-#define AOFF_task_sig	0x00000674
+#define ASIZ_task_sigmask_lock	0x00000001
+#define AOFF_task_sig	0x00000670
 #define ASIZ_task_sig	0x00000004
-#define AOFF_task_signal	0x00000678
+#define AOFF_task_signal	0x00000674
 #define ASIZ_task_signal	0x00000008
-#define AOFF_task_blocked	0x00000680
+#define AOFF_task_blocked	0x0000067c
 #define ASIZ_task_blocked	0x00000008
-#define AOFF_task_sigqueue	0x00000688
+#define AOFF_task_sigqueue	0x00000684
 #define ASIZ_task_sigqueue	0x00000004
-#define AOFF_task_sigqueue_tail	0x0000068c
+#define AOFF_task_sigqueue_tail	0x00000688
 #define ASIZ_task_sigqueue_tail	0x00000004
-#define AOFF_task_sas_ss_sp	0x00000690
+#define AOFF_task_sas_ss_sp	0x0000068c
 #define ASIZ_task_sas_ss_sp	0x00000004
-#define AOFF_task_sas_ss_size	0x00000694
+#define AOFF_task_sas_ss_size	0x00000690
 #define ASIZ_task_sas_ss_size	0x00000004
-#define AOFF_task_parent_exec_id	0x00000698
+#define AOFF_task_parent_exec_id	0x00000694
 #define ASIZ_task_parent_exec_id	0x00000004
-#define AOFF_task_self_exec_id	0x0000069c
+#define AOFF_task_self_exec_id	0x00000698
 #define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_oom_kill_try	0x0000069c
+#define ASIZ_task_oom_kill_try	0x00000004
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000004
 #define AOFF_mm_mmap_avl	0x00000004
diff -urN linux-2.2.15-pre14/include/asm-sparc/pgtable.h linux/include/asm-sparc/pgtable.h
--- linux-2.2.15-pre14/include/asm-sparc/pgtable.h	Mon Dec  3 22:01:23 2001
+++ linux/include/asm-sparc/pgtable.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.78.2.1 1999/08/07 10:52:48 davem Exp $ */
+/* $Id: pgtable.h,v 1.78.2.2 2000/02/27 04:44:44 davem Exp $ */
 #ifndef _SPARC_PGTABLE_H
 #define _SPARC_PGTABLE_H
 
diff -urN linux-2.2.15-pre14/include/asm-sparc/spinlock.h linux/include/asm-sparc/spinlock.h
--- linux-2.2.15-pre14/include/asm-sparc/spinlock.h	Sun Jun 13 19:42:01 1999
+++ linux/include/asm-sparc/spinlock.h	Mon Dec  3 22:01:29 2001
@@ -57,8 +57,13 @@
 
 #include <asm/psr.h>
 
-/* Define this to use the verbose/debugging versions in arch/sparc/lib/debuglocks.c */
-#define SPIN_LOCK_DEBUG
+/*
+ * Define this to use the verbose/debugging versions in
+ * arch/sparc/lib/debuglocks.c
+ *
+ * Be sure to make check_asm whenever changing this option.
+ */
+#undef SPIN_LOCK_DEBUG
 
 #ifdef SPIN_LOCK_DEBUG
 struct _spinlock_debug {
@@ -141,9 +146,13 @@
 typedef unsigned char spinlock_t;
 #define SPIN_LOCK_UNLOCKED	0
 
-#define spin_lock_init(lock)	(*(lock) = 0)
+#define spin_lock_init(lock)   (*((unsigned char *)(lock)) = 0)
 #define spin_is_locked(lock)    (*((volatile unsigned char *)(lock)) != 0)
-#define spin_unlock_wait(lock)	do { barrier(); } while(*(volatile unsigned char *)lock)
+
+#define spin_unlock_wait(lock) \
+do { \
+	barrier(); \
+} while(*((volatile unsigned char *)lock))
 
 extern __inline__ void spin_lock(spinlock_t *lock)
 {
@@ -152,7 +161,7 @@
 	orcc	%%g2, 0x0, %%g0
 	bne,a	2f
 	 ldub	[%0], %%g2
-	.text	2
+	.subsection	2
 2:	orcc	%%g2, 0x0, %%g0
 	bne,a	2b
 	 ldub	[%0], %%g2
@@ -178,77 +187,13 @@
 	__asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
 }
 
-extern __inline__ void spin_lock_irq(spinlock_t *lock)
-{
-	__asm__ __volatile__("
-	rd	%%psr, %%g2
-	or	%%g2, %0, %%g2
-	wr	%%g2, 0x0, %%psr
-	nop; nop; nop;
-1:	ldstub	[%1], %%g2
-	orcc	%%g2, 0x0, %%g0
-	bne,a	2f
-	 ldub	[%1], %%g2
-	.text	2
-2:	orcc	%%g2, 0x0, %%g0
-	bne,a	2b
-	 ldub	[%1], %%g2
-	b,a	1b
-	.previous
-"	: /* No outputs */
-	: "i" (PSR_PIL), "r" (lock)
-	: "g2", "memory", "cc");
-}
-
-extern __inline__ void spin_unlock_irq(spinlock_t *lock)
-{
-	__asm__ __volatile__("
-	rd	%%psr, %%g2
-	andn	%%g2, %1, %%g2
-	stb	%%g0, [%0]
-	wr	%%g2, 0x0, %%psr
-	nop; nop; nop;
-"	: /* No outputs. */
-	: "r" (lock), "i" (PSR_PIL)
-	: "g2", "memory");
-}
+#define spin_lock_irqsave(lock, flags) \
+	do { __save_and_cli(flags); spin_lock(lock); } while (0)
+#define spin_unlock_irqrestore(lock, flags) \
+	do { spin_unlock(lock); __restore_flags(flags); } while (0)
 
-#define spin_lock_irqsave(__lock, flags)	\
-do {						\
-	register spinlock_t *__lp asm("g1");	\
-	__lp = (__lock);			\
-	__asm__ __volatile__(			\
-	"rd	%%psr, %0\n\t"			\
-	"or	%0, %1, %%g2\n\t"		\
-	"wr	%%g2, 0x0, %%psr\n\t"		\
-	"nop; nop; nop;\n"			\
-	"1:\n\t"				\
-	"ldstub	[%2], %%g2\n\t"			\
-	"orcc	%%g2, 0x0, %%g0\n\t"		\
-	"bne,a	2f\n\t"				\
-	" ldub	[%2], %%g2\n\t"			\
-	".text	2\n"				\
-	"2:\n\t"				\
-	"orcc	%%g2, 0x0, %%g0\n\t"		\
-	"bne,a	2b\n\t"				\
-	" ldub	[%2], %%g2\n\t"			\
-	"b,a	1b\n\t"				\
-	".previous\n"				\
-	: "=r" (flags)				\
-	: "i" (PSR_PIL), "r" (__lp)		\
-	: "g2", "memory", "cc");		\
-} while(0)
-
-extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
-{
-	__asm__ __volatile__("
-	stb	%%g0, [%0]
-	wr	%1, 0x0, %%psr
-	nop; nop; nop;
-"	: /* No outputs. */
-	: "r" (lock), "r" (flags)
-	: "memory", "cc");
-}
+#define spin_lock_irq(lock)	do { __cli(); spin_lock(lock); } while (0)
+#define spin_unlock_irq(lock)	do { spin_unlock(lock); __sti(); } while (0)
 
 /* Read-write spinlocks, allowing multiple readers
  * but only one writer.
@@ -290,7 +235,7 @@
 	 ldstub	[%%g1 + 3], %%g2
 "	: /* no outputs */
 	: "r" (lp)
-	: "g2", "g4", "g7", "memory", "cc");
+	: "g2", "g4", "memory", "cc");
 }
 
 #define read_lock(lock) \
@@ -310,7 +255,7 @@
 	 ldstub	[%%g1 + 3], %%g2
 "	: /* no outputs */
 	: "r" (lp)
-	: "g2", "g4", "g7", "memory", "cc");
+	: "g2", "g4", "memory", "cc");
 }
 
 #define read_unlock(lock) \
@@ -330,7 +275,7 @@
 	 ldstub	[%%g1 + 3], %%g2
 "	: /* no outputs */
 	: "r" (lp)
-	: "g2", "g4", "g7", "memory", "cc");
+	: "g2", "g4", "memory", "cc");
 }
 
 #define write_unlock(rw)	do { (rw)->lock = 0; } while(0)
diff -urN linux-2.2.15-pre14/include/asm-sparc/vaddrs.h linux/include/asm-sparc/vaddrs.h
--- linux-2.2.15-pre14/include/asm-sparc/vaddrs.h	Mon Dec  3 22:01:23 2001
+++ linux/include/asm-sparc/vaddrs.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: vaddrs.h,v 1.22 1999/04/20 13:22:55 anton Exp $ */
+/* $Id: vaddrs.h,v 1.22.2.1 2000/03/05 19:26:24 davem Exp $ */
 #ifndef _SPARC_VADDRS_H
 #define _SPARC_VADDRS_H
 
diff -urN linux-2.2.15-pre14/include/asm-sparc64/asm_offsets.h linux/include/asm-sparc64/asm_offsets.h
--- linux-2.2.15-pre14/include/asm-sparc64/asm_offsets.h	Tue Jan  4 10:12:24 2000
+++ linux/include/asm-sparc64/asm_offsets.h	Mon Dec  3 22:01:29 2001
@@ -186,7 +186,9 @@
 #define ASIZ_task_parent_exec_id	0x00000004
 #define AOFF_task_self_exec_id	0x0000082c
 #define ASIZ_task_self_exec_id	0x00000004
-#define ASIZ_task	0x00000830
+#define AOFF_task_oom_kill_try	0x00000830
+#define ASIZ_task_oom_kill_try	0x00000004
+#define ASIZ_task	0x00000840
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -476,7 +478,9 @@
 #define ASIZ_task_parent_exec_id	0x00000004
 #define AOFF_task_self_exec_id	0x00000a1c
 #define ASIZ_task_self_exec_id	0x00000004
-#define ASIZ_task	0x00000a20
+#define AOFF_task_oom_kill_try	0x00000a20
+#define ASIZ_task_oom_kill_try	0x00000004
+#define ASIZ_task	0x00000a30
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
 #define AOFF_mm_mmap_avl	0x00000008
@@ -764,6 +768,8 @@
 #define ASIZ_task_parent_exec_id	0x00000004
 #define AOFF_task_self_exec_id	0x00000a24
 #define ASIZ_task_self_exec_id	0x00000004
+#define AOFF_task_oom_kill_try	0x00000a28
+#define ASIZ_task_oom_kill_try	0x00000004
 #define ASIZ_task	0x00000a30
 #define AOFF_mm_mmap	0x00000000
 #define ASIZ_mm_mmap	0x00000008
diff -urN linux-2.2.15-pre14/include/asm-sparc64/floppy.h linux/include/asm-sparc64/floppy.h
--- linux-2.2.15-pre14/include/asm-sparc64/floppy.h	Mon Dec  3 22:01:23 2001
+++ linux/include/asm-sparc64/floppy.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.18.2.3 2000/01/09 18:29:32 ecd Exp $
+/* $Id: floppy.h,v 1.18.2.4 2000/02/27 04:44:47 davem Exp $
  * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- linux-2.2.15-pre14/include/asm-sparc64/pgtable.h	Mon Dec  3 22:01:23 2001
+++ linux/include/asm-sparc64/pgtable.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: pgtable.h,v 1.103.2.2 1999/12/05 07:24:45 davem Exp $
+/* $Id: pgtable.h,v 1.103.2.3 2000/02/27 04:44:47 davem Exp $
  * pgtable.h: SpitFire page table operations.
  *
  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
diff -urN linux-2.2.15-pre14/include/asm-sparc64/system.h linux/include/asm-sparc64/system.h
--- linux-2.2.15-pre14/include/asm-sparc64/system.h	Mon Dec  3 22:01:23 2001
+++ linux/include/asm-sparc64/system.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: system.h,v 1.50 1999/05/08 03:03:22 davem Exp $ */
+/* $Id: system.h,v 1.50.2.1 2000/03/06 22:30:28 davem Exp $ */
 #ifndef __SPARC64_SYSTEM_H
 #define __SPARC64_SYSTEM_H
 
diff -urN linux-2.2.15-pre14/include/linux/isdn.h linux/include/linux/isdn.h
--- linux-2.2.15-pre14/include/linux/isdn.h	Mon Dec  3 22:01:23 2001
+++ linux/include/linux/isdn.h	Mon Dec  3 22:01:29 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.88 2000/01/20 19:59:43 keil Exp $
+/* $Id: isdn.h,v 1.95 2000/03/04 16:20:42 detabc Exp $
  *
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -21,6 +21,31 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  *
  * $Log: isdn.h,v $
+ * Revision 1.95  2000/03/04 16:20:42  detabc
+ * copy frames before rewriting frame's saddr
+ *
+ * Revision 1.94  2000/02/26 00:29:40  keil
+ * more softnet changes
+ *
+ * Revision 1.93  2000/02/25 11:29:17  paul
+ * changed chargetime to ulong from int (after about 20 days the "chargetime of
+ * ipppX is now 1234" message displays a negative number on alpha).
+ *
+ * Revision 1.92  2000/02/17 13:15:56  keil
+ * fix backward compatibility for 2.2
+ *
+ * Revision 1.91  2000/02/16 14:56:27  paul
+ * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers
+ *
+ * Revision 1.90  2000/02/06 21:50:00  detabc
+ * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections.
+ * Include checksum-recompute of ip- and udp-header's.
+ *
+ * Revision 1.89  2000/02/05 22:11:33  detabc
+ * Add rewriting of socket's and frame's saddr adressfield for
+ * dynip-connections.  Only for tcp/ipv4 and switchable per interface.
+ * Include checksum-recompute of ip- and tcp-header's.
+ *
  * Revision 1.88  2000/01/20 19:59:43  keil
  * Add FAX Class 1 support
  *
@@ -374,6 +399,8 @@
 #undef CONFIG_ISDN_WITH_ABC_CONN_ERROR
 #undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
 #undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
+#undef CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR 
+#undef CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR 
 
 
 /* New ioctl-codes */
@@ -433,7 +460,7 @@
 #define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */
 #define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing  */
 
-#define ISDN_MODEM_ANZREG    24        /* Number of Modem-Registers        */
+#define ISDN_MODEM_NUMREG    24        /* Number of Modem-Registers        */
 #define ISDN_LMSNLEN         255 /* Length of tty's Listen-MSN string */
 #define ISDN_CMSGLEN	     50	 /* Length of CONNECT-Message to add for Modem */
 
@@ -536,6 +563,7 @@
 #  include <linux/concap.h>
 #endif
 
+
 #include <linux/isdnif.h>
 
 #define ISDN_DRVIOCTL_MASK       0x7f  /* Mask for Device-ioctl */
@@ -657,7 +685,7 @@
                                        /*   0 = Transparent                */
   int                    huptimer;     /* Timeout-counter for auto-hangup  */
   int                    charge;       /* Counter for charging units       */
-  int                    chargetime;   /* Timer for Charging info          */
+  ulong                  chargetime;   /* Timer for Charging info          */
   int                    hupflags;     /* Flags for charge-unit-hangup:    */
 				       /* bit0: chargeint is invalid       */
 				       /* bit1: Getting charge-interval    */
@@ -762,8 +790,8 @@
 
 /* Private data of AT-command-interpreter */
 typedef struct atemu {
-	u_char       profile[ISDN_MODEM_ANZREG]; /* Modem-Regs. Profile 0              */
-	u_char       mdmreg[ISDN_MODEM_ANZREG];  /* Modem-Registers                    */
+	u_char       profile[ISDN_MODEM_NUMREG]; /* Modem-Regs. Profile 0              */
+	u_char       mdmreg[ISDN_MODEM_NUMREG];  /* Modem-Registers                    */
 	char         pmsn[ISDN_MSNLEN];          /* EAZ/MSNs Profile 0                 */
 	char         msn[ISDN_MSNLEN];           /* EAZ/MSN                            */
 	char         plmsn[ISDN_LMSNLEN];        /* Listening MSNs Profile 0           */
@@ -975,5 +1003,32 @@
 /* Utility-Macros */
 #define MIN(a,b) ((a<b)?a:b)
 #define MAX(a,b) ((a>b)?a:b)
+/*
+ * Tell upper layers that the network device is ready to xmit more frames.
+ */
+static void __inline__ netif_wake_queue(struct device * dev)
+{
+	dev->tbusy = 0;
+	mark_bh(NET_BH);
+}
+
+/*
+ * called during net_device open()
+ */
+static void __inline__ netif_start_queue(struct device * dev)
+{
+	dev->tbusy = 0;
+	/* actually, we never use the interrupt flag at all */
+	dev->interrupt = 0;
+	dev->start = 1;
+}
+
+/*
+ * Ask upper layers to temporarily cease passing us more xmit frames.
+ */
+static void __inline__ netif_stop_queue(struct device * dev)
+{
+	dev->tbusy = 1;
+}
 #endif /* __KERNEL__ */
 #endif /* isdn_h */
diff -urN linux-2.2.15-pre14/include/linux/kernelcapi.h linux/include/linux/kernelcapi.h
--- linux-2.2.15-pre14/include/linux/kernelcapi.h	Tue Oct 26 17:53:42 1999
+++ linux/include/linux/kernelcapi.h	Mon Dec  3 22:01:29 2001
@@ -1,11 +1,15 @@
 /*
- * $Id: kernelcapi.h,v 1.4 1999/09/10 17:24:19 calle Exp $
+ * $Id: kernelcapi.h,v 1.5 2000/01/28 16:45:40 calle Exp $
  * 
  * Kernel CAPI 2.0 Interface for Linux
  * 
  * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
  * 
  * $Log: kernelcapi.h,v $
+ * Revision 1.5  2000/01/28 16:45:40  calle
+ * new manufacturer command KCAPI_CMD_ADDCARD (generic addcard),
+ * will search named driver and call the add_card function if one exist.
+ *
  * Revision 1.4  1999/09/10 17:24:19  calle
  * Changes for proposed standard for CAPI2.0:
  * - AK148 "Linux Exention"
@@ -57,8 +61,17 @@
 	int flag;
 } kcapi_flagdef;
 
+typedef struct kcapi_carddef {
+	char		driver[32];
+	unsigned int	port;
+	unsigned	irq;
+	unsigned int	membase;
+	int		cardnr;
+} kcapi_carddef;
+
 /* new ioctls >= 10 */
 #define KCAPI_CMD_TRACE		10
+#define KCAPI_CMD_ADDCARD	11	/* add card to named driver */
 
 /* 
  * flag > 2 => trace also data
diff -urN linux-2.2.15-pre14/ipc/sem.c linux/ipc/sem.c
--- linux-2.2.15-pre14/ipc/sem.c	Mon Dec  3 22:01:23 2001
+++ linux/ipc/sem.c	Mon Dec  3 22:01:29 2001
@@ -521,16 +521,14 @@
 		break;
 	case IPC_SET:
 		buf = arg.buf;
-		err = copy_from_user (&tbuf, buf, sizeof (*buf));
-		if (err)
-			err = -EFAULT;
+		err = -EFAULT;
+		if(copy_from_user (&tbuf, buf, sizeof (*buf)))
+			goto out;
 		break;
 	}
 
 	err = -EIDRM;
-	if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
-		goto out;
-	if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+	if ((sma != semary[id]) || (sma->sem_perm.seq != (unsigned int) semid / SEMMNI))
 		goto out;
 
 	switch (cmd) {
@@ -540,8 +538,9 @@
 			goto out;
 		for (i = 0; i < sma->sem_nsems; i++)
 			sem_io[i] = sma->sem_base[i].semval;
+		err = -EFAULT;
 		if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
-			err = -EFAULT;
+			goto out;
 		break;
 	case SETVAL:
 		err = -EACCES;
@@ -575,8 +574,9 @@
 		tbuf.sem_otime  = sma->sem_otime;
 		tbuf.sem_ctime  = sma->sem_ctime;
 		tbuf.sem_nsems  = sma->sem_nsems;
+		err = -EFAULT;
 		if (copy_to_user (buf, &tbuf, sizeof(*buf)))
-			err = -EFAULT;
+			goto out;
 		break;
 	case SETALL:
 		err = -EACCES;
@@ -601,6 +601,25 @@
 	return err;
 }
 
+
+static struct sem_undo* freeundos(struct sem_undo* un)
+{
+	struct sem_undo* u;
+	struct sem_undo** up;
+
+	for (up = &current->semundo;(u=*up);up=&u->proc_next) {
+		if(un==u) {
+			un=u->proc_next;
+			*up=un;
+			kfree(u);
+			return un;
+		}
+	}
+	printk ("freeundos undo list error id=%d\n", un->semid);
+	return un->proc_next;
+}
+
+
 asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
 {
 	int id, size, error = -EINVAL;
@@ -647,9 +666,15 @@
 		/* Make sure we have an undo structure
 		 * for this process and this semaphore set.
 		 */
-		for (un = current->semundo; un; un = un->proc_next)
-			if (un->semid == semid)
+		un = current->semundo;
+		while(un != NULL) {
+			if(un->semid==semid)
 				break;
+			if(un->semid==-1)
+				un=freeundos(un);
+			else
+			un=un->proc_next;
+		}
 		if (!un) {
 			size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
 			un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
diff -urN linux-2.2.15-pre14/net/x25/af_x25.c linux/net/x25/af_x25.c
--- linux-2.2.15-pre14/net/x25/af_x25.c	Thu Aug 27 19:33:09 1998
+++ linux/net/x25/af_x25.c	Mon Dec  3 22:01:30 2001
@@ -16,6 +16,7 @@
  *	X.25 001	Jonathan Naylor	Started coding.
  *	X.25 002	Jonathan Naylor	Centralised disconnect handling.
  *					New timer architecture.
+ *	2000-11-03	Henner Eisen	MSG_EOR handling more POSIX compliant.
  */
 
 #include <linux/config.h>
@@ -854,7 +855,7 @@
 	unsigned char *asmptr;
 	int size, qbit = 0;
 
-	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_OOB))
+	if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_OOB | MSG_EOR))
 		return -EINVAL;
 
 	if (sk->zapped)
@@ -1035,6 +1036,9 @@
 		copied = size;
 		msg->msg_flags |= MSG_TRUNC;
 	}
+
+	/* Currently, each datagram always contains a complete record */ 
+	msg->msg_flags |= MSG_EOR;
 
 	skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
 
diff -urN linux-2.2.15-pre14/net/x25/x25_link.c linux/net/x25/x25_link.c
--- linux-2.2.15-pre14/net/x25/x25_link.c	Mon Dec  3 22:01:23 2001
+++ linux/net/x25/x25_link.c	Mon Dec  3 22:01:30 2001
@@ -85,13 +85,14 @@
 void x25_link_control(struct sk_buff *skb, struct x25_neigh *neigh, unsigned short frametype)
 {
 	struct sk_buff *skbn;
+	int confirm;
 
 	switch (frametype) {
 		case X25_RESTART_REQUEST:
+			confirm = !x25_t20timer_pending(neigh);
 			x25_stop_t20timer(neigh);
-			if (!x25_t20timer_pending(neigh))
-				x25_transmit_restart_confirmation(neigh);
 			neigh->state = X25_LINK_STATE_3;
+			if (confirm) x25_transmit_restart_confirmation(neigh);
 			break;
 
 		case X25_RESTART_CONFIRMATION:
