add usb isdn and serial driver fixes
authorFelix Fietkau <nbd@openwrt.org>
Sat, 2 Apr 2005 17:17:22 +0000 (17:17 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Sat, 2 Apr 2005 17:17:22 +0000 (17:17 +0000)
SVN-Revision: 524

openwrt/package/linux/kernel-patches/400-i4l-cvs-2-4-29 [new file with mode: 0644]
openwrt/package/linux/kernel-patches/401-hfc-usb-backport-i4l-cvs [new file with mode: 0644]
openwrt/package/linux/kernel-patches/402-pl2303-backport-2-4-29 [new file with mode: 0644]

diff --git a/openwrt/package/linux/kernel-patches/400-i4l-cvs-2-4-29 b/openwrt/package/linux/kernel-patches/400-i4l-cvs-2-4-29
new file mode 100644 (file)
index 0000000..c9833e2
--- /dev/null
@@ -0,0 +1,20247 @@
+diff -rNu linux-2.4.29.old/Documentation/isdn/CREDITS linux-2.4.29/Documentation/isdn/CREDITS
+--- linux-2.4.29.old/Documentation/isdn/CREDITS        2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/CREDITS    2005-03-22 15:06:50.246454160 +0100
+@@ -37,7 +37,7 @@
+ Andreas Kool (akool@Kool.f.EUnet.de)
+   For contribution of the isdnlog/isdnrep-tool
+-Pedro Roque Marques (pedro_m@yahoo.com)
++Pedro Roque Marques (roque@di.fc.ul.pt)
+   For lot of new ideas and the pcbit driver.
+ Eberhard Moenkeberg (emoenke@gwdg.de)
+diff -rNu linux-2.4.29.old/Documentation/isdn/HiSax.cert linux-2.4.29/Documentation/isdn/HiSax.cert
+--- linux-2.4.29.old/Documentation/isdn/HiSax.cert     2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/HiSax.cert 2005-03-22 15:06:50.264451424 +0100
+@@ -68,6 +68,8 @@
+ drivers/isdn/hisax/elsa.c
+ drivers/isdn/hisax/diva.c
+ drivers/isdn/hisax/hfc_pci.c
++drivers/isdn/hisax/hfc_usbr.c
++drivers/isdn/hisax/hfc_usb.c
+ Please send any changes, bugfixes and patches to me rather than implementing
+ them directly into the HiSax sources.
+diff -rNu linux-2.4.29.old/Documentation/isdn/INTERFACE linux-2.4.29/Documentation/isdn/INTERFACE
+--- linux-2.4.29.old/Documentation/isdn/INTERFACE      2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/INTERFACE  2005-03-22 15:06:50.288447776 +0100
+@@ -1,4 +1,4 @@
+-$Id: INTERFACE,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: INTERFACE,v 1.17 2002/01/31 13:26:35 keil Exp $
+ Description of the Interface between Linklevel and Hardwarelevel
+   of isdn4linux:
+@@ -399,7 +399,7 @@
+                     protocol-Id is one of the constants ISDN_PROTO_L3...
+       parm.fax    = Pointer to T30_s fax struct. (fax usage only)
+-  ISDN_CMD_GETL2: (currently unused)
++  ISDN_CMD_GETL3: (currently unused)
+     With this command, the HL-driver is told to return the current
+     setting of the Layer-3-protocol.
+@@ -781,3 +781,22 @@
+       arg         = channel-number, locally to the driver. (starting with 0)
+       parm        = unused.
++  ISDN_STAT_ALERT:
++
++    With this call, the HL-driver signals the receive of an ALERTING message to the LL.
++
++    Parameter:
++      driver      = driver-Id
++      command     = ISDN_STAT_ALERT
++      arg         = channel-number, locally to the driver. (starting with 0)
++
++  ISDN_STAT_PROCEED:
++
++    With this call, the HL-driver signals the receive of an CALL PROCEEDING message
++    to the LL.
++
++    Parameter:
++      driver      = driver-Id
++      command     = ISDN_STAT_PROCEED
++      arg         = channel-number, locally to the driver. (starting with 0)
++
+diff -rNu linux-2.4.29.old/Documentation/isdn/INTERFACE.fax linux-2.4.29/Documentation/isdn/INTERFACE.fax
+--- linux-2.4.29.old/Documentation/isdn/INTERFACE.fax  2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/INTERFACE.fax      2005-03-22 15:06:50.312444128 +0100
+@@ -1,4 +1,4 @@
+-$Id: INTERFACE.fax,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: INTERFACE.fax,v 1.2 2000/08/06 09:22:50 armin Exp $
+ Description of the fax-subinterface between linklevel and hardwarelevel of 
+diff -rNu linux-2.4.29.old/Documentation/isdn/README linux-2.4.29/Documentation/isdn/README
+--- linux-2.4.29.old/Documentation/isdn/README 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README     2005-03-22 15:06:50.340439872 +0100
+@@ -278,6 +278,12 @@
+                                       1 = Add CPN to FCON message on
+                             Bit 2:    0 = Add CDN to RING/FCON message off
+                                       1 = Add CDN to RING/FCON message on
++                            Bit 3:    0 = Do not signal RINGING
++                                      1 = Signal RINGING if ALERT was received
++                            Bit 4:    0 = Do not signal PROCEEDING
++                                      1 = Signal PROCEEDING if CALL PROCEEDING
++                                          was received
++
+   Last but not least a (at the moment fairly primitive) device to request
+   the line-status (/dev/isdninfo) is made available.
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.HiSax linux-2.4.29/Documentation/isdn/README.HiSax
+--- linux-2.4.29.old/Documentation/isdn/README.HiSax   2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.HiSax       2005-03-22 15:06:50.372435008 +0100
+@@ -41,10 +41,9 @@
+ ELSA Quickstep 3000PCI
+ ELSA PCMCIA
+ ITK ix1-micro Rev.2
+-Eicon Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
+-Eicon Diva 2.01 ISA and PCI
+-Eicon Diva 2.02 PCI
+-Eicon Diva Piccola
++Eicon.Diehl Diva 2.0 ISA and PCI (S0 and U interface, no PRO version)
++Eicon.Diehl Diva 2.01 ISA and PCI
++Eicon.Diehl Diva Piccola
+ ASUSCOM NETWORK INC. ISDNLink 128K PC adapter (order code I-IN100-ST-D)
+ Dynalink IS64PH (OEM version of ASUSCOM NETWORK INC. ISDNLink 128K adapter)
+ PCBIT-DP (OEM version of ASUSCOM NETWORK INC. ISDNLink)
+@@ -53,7 +52,6 @@
+ Sedlbauer Speed Star/Speed Star2 (PCMCIA)
+ Sedlbauer ISDN-Controller PC/104
+ USR Sportster internal TA (compatible Stollmann tina-pp V3)
+-USR internal TA PCI
+ ith Kommunikationstechnik GmbH MIC 16 ISA card
+ Traverse Technologie NETjet PCI S0 card and NETspider U card
+ Ovislink ISDN sc100-p card (NETjet driver)
+@@ -68,14 +66,14 @@
+ HFC-PCI based cards
+ Winbond W6692 based cards
+ HFC-S+, HFC-SP/PCMCIA cards
+-formula-n enternow
+-Gerdes Power ISDN
++HFC-USB ISDN TAs
+ Note: PCF, PCF-Pro: up to now, only the ISDN part is supported
+       PCC-8: not tested yet
+       Eicon.Diehl Diva U interface not tested
+ If you know other passive cards with the Siemens chipset, please let me know.
++To use the PNP cards you need the isapnptools.
+ You can combine any card, if there is no conflict between the resources
+ (io, mem, irq).
+@@ -91,15 +89,8 @@
+ modules. It is included in the normal "make [menu]config" target at the
+ kernel. Don't forget it, especially to select the right D-channel protocol.
+-Please note: In older versions of the HiSax driver, all PnP cards
+-needed to be configured with isapnp and worked only with the HiSax
+-driver used as a module.
+-
+-In the current version, HiSax will automatically use the in-kernel
+-ISAPnP support, provided you selected it during kernel configuration
+-(CONFIG_ISAPNP), if you don't give the io=, irq= command line parameters.
+-
+-The affected card types are: 4,7,12,14,19,27-30
++Please note: All PnP cards need to be configured with isapnp and will work
++only with the HiSax driver used as a module.
+ a) when built as a module
+ -------------------------
+@@ -200,8 +191,6 @@
+    37 HFC 2BDS0 S+, SP         irq,io 
+    38 NETspider U PCI card     none
+    39 HFC 2BDS0 SP/PCMCIA      irq,io (set with cardmgr)
+-   40   hotplug interface
+-   41   Formula-n enter:now PCI  none
+ At the moment IRQ sharing is only possible with PCI cards. Please make sure
+ that your IRQ is free and enabled for ISA use.
+@@ -227,13 +216,6 @@
+                    (IO 1 (BASE 0x0180))
+    modprobe hisax type=4 protocol=2 irq=10 io0=0x580 io1=0x180
+-   In the current version of HiSax, you can instead simply use
+-
+-   modprobe hisax type=4 protocol=2
+-
+-   if you configured your kernel for ISAPnP. Don't run isapnp in
+-   this case!
+-
+ 6. Teles 16.3, Euro ISDN, I/O base 280 hex, IRQ 12 and
+    Teles 16.0, 1TR6, IRQ 5, Memory d0000 hex
+    modprobe hisax type=3,1 protocol=2,1 io=0x280 mem=0,0xd0000
+@@ -314,9 +296,7 @@
+    36 W6692 based PCI cards   none
+    37 HFC 2BDS0 S+,SP/PCMCIA  ONLY WORKS AS A MODULE !
+    38 NETspider U PCI card    none
+-   39 HFC 2BDS0 SP/PCMCIA     ONLY WORKS AS A MODULE !
+-   40   hotplug interface     ONLY WORKS AS A MODULE !
+-   41   Formula-n enter:now PCI none
++
+ Running the driver
+ ------------------
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.act2000 linux-2.4.29/Documentation/isdn/README.act2000
+--- linux-2.4.29.old/Documentation/isdn/README.act2000 2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.act2000     2005-03-22 15:06:50.388432576 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.act2000,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.act2000,v 1.3 2000/08/06 09:22:51 armin Exp $
+ This document describes the ACT2000 driver for the
+ IBM Active 2000 ISDN card.
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.audio linux-2.4.29/Documentation/isdn/README.audio
+--- linux-2.4.29.old/Documentation/isdn/README.audio   2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.audio       2005-03-22 15:06:50.404430144 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.audio,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.audio,v 1.8 1999/07/11 17:17:29 armin Exp $
+ ISDN subsystem for Linux.
+   Description of audio mode.
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.eicon linux-2.4.29/Documentation/isdn/README.eicon
+--- linux-2.4.29.old/Documentation/isdn/README.eicon   2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.eicon       2005-03-22 15:06:50.479418744 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.eicon,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.eicon,v 1.10 2000/08/13 12:19:15 armin Exp $
+ (c) 1999,2000 Armin Schindler (mac@melware.de)
+ (c) 1999,2000 Cytronics & Melware (info@melware.de)
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.hysdn linux-2.4.29/Documentation/isdn/README.hysdn
+--- linux-2.4.29.old/Documentation/isdn/README.hysdn   2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.hysdn       2005-03-22 15:06:50.522412208 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.hysdn,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.hysdn,v 1.3.6.1 2001/02/10 14:41:19 kai Exp $
+ The hysdn driver has been written by
+ by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) 
+ for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.icn linux-2.4.29/Documentation/isdn/README.icn
+--- linux-2.4.29.old/Documentation/isdn/README.icn     2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.icn 2005-03-22 15:06:50.550407952 +0100
+@@ -1,4 +1,4 @@
+-$Id: README.icn,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++$Id: README.icn,v 1.7 2000/08/06 09:22:51 armin Exp $
+ You can get the ICN-ISDN-card from:
+diff -rNu linux-2.4.29.old/Documentation/isdn/README.pcbit linux-2.4.29/Documentation/isdn/README.pcbit
+--- linux-2.4.29.old/Documentation/isdn/README.pcbit   2005-03-22 14:48:26.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/README.pcbit       2005-03-22 15:06:50.567405368 +0100
+@@ -37,4 +37,4 @@
+ regards,
+   Pedro.
+               
+-<pedro_m@yahoo.com>
++<roque@di.fc.ul.pt>
+diff -rNu linux-2.4.29.old/Documentation/isdn/abcext_kernel.help linux-2.4.29/Documentation/isdn/abcext_kernel.help
+--- linux-2.4.29.old/Documentation/isdn/abcext_kernel.help     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/Documentation/isdn/abcext_kernel.help 2005-03-22 15:06:50.600400352 +0100
+@@ -0,0 +1,166 @@
++ 
++ISDN-ABC-DW Extension
++CONFIG_ISDN_WITH_ABC
++   These are many brand new Options and Features for the
++   ISDN SUBSYSTEM. Including Logical Device bindings,
++   Compression and other good stuff for Optimizing your
++   ISDN System.
++
++   To Use this Extensions you MUST HAVE THE NEWEST
++   ISDN4K-UTILS. You must have Version 3.1-Beta6 or
++   higher. Elsewhere you can not configure this Extensions.
++
++   WARNING ! THIS STUF IS NOT PRODUCTION RELEASE THE
++   FUNCTION ARE UNDER DEVELOPMENT. This ist BETA-CODE.
++   You can use it at you Own Risk.
++
++   For more Information on these Extensions take a look at
++   "linux/Documentation/isdn/dw-abc-extension-howto.txt or
++   Online at the Web "http://www.mediatronix.de/i4l/index.html"
++
++   Please Report Bugs to "mario@mediatronix.de" or
++   "delefw@isdn4linux.de"
++
++D-Channel-Callback with Channel in use check
++CONFIG_ISDN_WITH_ABC_CALLB
++   When a Interface is declared as an Callback Interface,
++   the Interface is checking that the other Side is not
++   Calling on the same time before the Interface is Dialing.
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++
++   In most case answer with "Yes" when you have Callback devices,
++   otherwise leave it "No"
++
++Outgoing-EAZ-Support
++CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++   Enables the Feature to Define an other EAZ or MSN for
++   Outgoing calls on an Interface.
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++
++Least Cost Router Support
++CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++   This is the final Kernel Code for configuring an Least
++   Cost Router Softwarebased. The other Job is to do the
++   action in ISDNLOG. You need the ISDNLOG to use this 
++   function. Currently the ISDNLOG have not the Support for
++   this Option.
++   So in most situations let the Option off.
++
++TCP keepalive detect and response
++CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE
++   This Option works only with the TCP/IP V4. It enables
++   the Function that ISDN Devices are Answering TCP_KEEPALIVE Pakets
++   localy. So that TCP KEEPALIVE Pakets not longer takes the Line
++   open.
++
++Drop frames Sourceadresse is not Interfaceadress
++CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR
++   This Option works only with the TCP/IP V4. It will allow only
++   the Transmitt of Pakets where the Sourceadresse is the Interface
++   adress. It is usefull when you have Lines with Dynamic IP.
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++
++Receive do not reset the Hanguptimer
++CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++   When you activate this option than the reiceive of pakets do
++   not reset the Hanguptimer. It is very usefull because if the
++   Paket vor your Network your Network generate an Response and
++   the Transmit is reseting the HUPTIMER. But when the Paket is
++   Rejected at your firewall your network generate no Response
++   and no Sendtraffic is generated. So in this case there is no 
++   need to Reset the Huptimer because you have only received Data.
++   With that option only Transmitted Data/Pakets will reset the
++   HUPTIMER.
++
++Support of (device-channel) and Binding Groups
++CONFIG_ISDN_WITH_ABC_ICALL_BIND
++   This Option enables the Feature to Bind logical ISDN Interfaces
++   to an prefered ISDN Card or ISDN Card plus Channel. So you have
++   the Chance to keep Channels exclusively for one (or more) 
++   Connection. Very usefull when you have more channels and Use 
++   Calling Line Identification, because you can organize that your
++   call is going out over the Line with the right EAZ for the CLI.
++
++Skip channel if used external (Dial Only)
++CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++   When you have more than One ISDN Card in your System and you
++   will Dialout with an Interface you can become the Situation
++   that an External Device such a Telephone or Fax is Using the
++   B-Channels. Normaly ISDN4Linux does not detect this Situation
++   and dial everytime of the "External Busy" line out. With this
++   Option Enabled the I4L will detect that he can not dialout on
++   This Card and dial over the next Card out.
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++
++Interface autodisable if Config error
++CONFIG_ISDN_WITH_ABC_CONN_ERROR
++   This Option will detect an Device which generate Telephone
++   Cost but does not Function correctly because there are
++   Configerrors on one of the Site. In this Situation the
++   Interface will be marked as Unsuably for some time to do
++   not call every time this Site.
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++
++UDP-Info-Support
++CONFIG_ISDN_WITH_ABC_UDP_CHECK
++   This is the Mainoption to Enable or Disable the UDP
++   Info Support. An Option to Controll ISDN-Interfaces
++   Remotely. For this very Complex thing take a look at
++
++   "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information.
++
++UDP Hangup Support
++CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++
++   Sorry no more Information!
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++   
++UDP Dial Support
++CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++
++   Sorry no more Information!
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++   
++Limit on the line frames to two
++CONFIG_ISDN_WITH_ABC_FRAME_LIMIT
++
++   This Option enables support for sending only 2 Pakets on
++   the Fly to the ISDN Driver. It is very usefull when you
++   will use the new RAW-IP Compression. Because of sending
++   Only 2 Pakets on the Fly makes the risk of overflowing
++   the ISDN Driver very smaller.
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++
++Compression with RAWIP and X75I
++CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++
++   With this Option you have the ability to make Datacompression
++   on RAW-IP Lines. It is function on HDLC and X75I Connection,
++   but the Prefered L2-Protocol for Compression is X75I because
++   the HDLC Protocol have no Errorcorrection.
++
++   To Use this Option YOU MUST HAVE ENABLED THE OPTION:
++   Support synchronous PPP
++   and must load after loading the main isdndrivers the
++   Modul "isdn_bsdcomp".
++
++   See "linux/Documentation/isdn/dw-abc-extension-howto.txt" 
++   for more Information
++
+diff -rNu linux-2.4.29.old/drivers/isdn/Config.in linux-2.4.29/drivers/isdn/Config.in
+--- linux-2.4.29.old/drivers/isdn/Config.in    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/Config.in        2005-03-22 15:06:44.259364336 +0100
+@@ -4,11 +4,9 @@
+ # only included if CONFIG_ISDN != n
+-define_bool CONFIG_ISDN_BOOL y
+ if [ "$CONFIG_INET" != "n" ]; then
+    bool '  Support synchronous PPP' CONFIG_ISDN_PPP
+    if [ "$CONFIG_ISDN_PPP" != "n" ]; then
+-      dep_bool     '    PPP filtering for ISDN' CONFIG_IPPP_FILTER $CONFIG_FILTER
+       bool         '    Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
+       bool         '    Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
+       dep_tristate '    Support BSD compression' CONFIG_ISDN_PPP_BSDCOMP $CONFIG_ISDN
+@@ -23,6 +21,30 @@
+ fi
+ mainmenu_option next_comment
++comment 'ISDN abc-dw-extension'
++bool 'Enable isdn-abc-dw-extension' CONFIG_ISDN_WITH_ABC
++if [ "$CONFIG_ISDN_WITH_ABC" != "n" ]; then
++      bool '  Use D-Channel-Callback with Channel in use check' CONFIG_ISDN_WITH_ABC_CALLB
++      bool '  Enable Outgoing-EAZ-Support' CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++      bool '  Enable LCR-Support (need isdnlog)' CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++      bool '  RX dont reset hanguptimeout' CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++      if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
++              bool '  Enable UDP-Info-Support' CONFIG_ISDN_WITH_ABC_UDP_CHECK
++              if [ "$CONFIG_ISDN_WITH_ABC_UDP_CHECK" != "n" ]; then
++                      bool '    Enable Hangup-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++                      bool '    Enable Dial-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++              fi
++      fi
++
++      bool '  Skip channel if used external (dial only)' CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++      bool '  Support interface-auto-disable if config-error' CONFIG_ISDN_WITH_ABC_CONN_ERROR
++      if [ "$CONFIG_ISDN_PPP" != "n" ]; then
++              bool '  Enable Compression with rawip and x75i' CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++      fi
++fi
++endmenu
++
++mainmenu_option next_comment
+ comment 'ISDN feature submodules'
+    dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
+    dep_tristate 'Support isdn diversion services' CONFIG_ISDN_DIVERSION $CONFIG_ISDN
+@@ -34,7 +56,6 @@
+ comment 'Passive ISDN cards'
+ dep_tristate 'HiSax SiemensChipSet driver support' CONFIG_ISDN_DRV_HISAX $CONFIG_ISDN
+ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
+-   define_bool CONFIG_ISDN_HISAX y
+    comment '  D-channel protocol features'
+    bool '  HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO
+    if [ "$CONFIG_HISAX_EURO" != "n" ]; then
+@@ -45,31 +66,28 @@
+    fi
+    bool '  HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
+    bool '  HiSax Support for US NI1' CONFIG_HISAX_NI1
+-   int  '  Maximum number of cards supported by HiSax' CONFIG_HISAX_MAX_CARDS 8
+    comment '  HiSax supported cards'
+-   if [ "$CONFIG_ISA" != "n" ]; then
+-      bool '  Teles 16.0/8.0' CONFIG_HISAX_16_0
+-      bool '  Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+-      bool '  AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+-      bool '  ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+-      bool '  ASUSCOM ISA cards' CONFIG_HISAX_ASUSCOM
+-      bool '  TELEINT cards' CONFIG_HISAX_TELEINT
+-      bool '  HFC-S based cards' CONFIG_HISAX_HFCS
+-      bool '  USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
+-      bool '  MIC card' CONFIG_HISAX_MIC
+-      bool '  Siemens I-Surf card' CONFIG_HISAX_ISURF
+-      bool '  HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+-   fi
++   bool '  Teles 16.0/8.0' CONFIG_HISAX_16_0
++   bool '  Teles 16.3 or PNP or PCMCIA' CONFIG_HISAX_16_3
+    bool '  Teles PCI' CONFIG_HISAX_TELESPCI 
+    bool '  Teles S0Box' CONFIG_HISAX_S0BOX 
++   bool '  AVM A1 (Fritz)' CONFIG_HISAX_AVM_A1
+    bool '  AVM PnP/PCI (Fritz!PnP/PCI)' CONFIG_HISAX_FRITZPCI
+    bool '  AVM A1 PCMCIA (Fritz)' CONFIG_HISAX_AVM_A1_PCMCIA
+    bool '  Elsa cards' CONFIG_HISAX_ELSA
++   bool '  ITK ix1-micro Revision 2' CONFIG_HISAX_IX1MICROR2
+    bool '  Eicon.Diehl Diva cards' CONFIG_HISAX_DIEHLDIVA
++   bool '  ASUSCOM ISA cards' CONFIG_HISAX_ASUSCOM
++   bool '  TELEINT cards' CONFIG_HISAX_TELEINT
++   bool '  HFC-S based cards' CONFIG_HISAX_HFCS
+    bool '  Sedlbauer cards' CONFIG_HISAX_SEDLBAUER
++   bool '  USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
++   bool '  MIC card' CONFIG_HISAX_MIC
+    bool '  NETjet card' CONFIG_HISAX_NETJET
+    bool '  NETspider U card' CONFIG_HISAX_NETJET_U
+    bool '  Niccy PnP/PCI card' CONFIG_HISAX_NICCY
++   bool '  Siemens I-Surf card' CONFIG_HISAX_ISURF
++   bool '  HST Saphir card' CONFIG_HISAX_HSTSAPHIR
+    bool '  Telekom A4T card' CONFIG_HISAX_BKM_A4T
+    bool '  Scitel Quadro card' CONFIG_HISAX_SCT_QUADRO
+    bool '  Gazel cards' CONFIG_HISAX_GAZEL
+@@ -78,20 +96,27 @@
+    bool '  HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
+    if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+ #      bool '  TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU
+-      bool '  Formula-n enter:now PCI card' CONFIG_HISAX_ENTERNOW_PCI
+       if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then
+        bool '  Am7930' CONFIG_HISAX_AMD7930
+       fi
+    fi
+    bool '  HiSax debugging' CONFIG_HISAX_DEBUG
+-   dep_tristate 'Sedlbauer PCMCIA cards'                              CONFIG_HISAX_SEDLBAUER_CS  $CONFIG_ISDN_DRV_HISAX $CONFIG_PCMCIA
+-   dep_tristate 'ELSA PCMCIA MicroLink cards'                         CONFIG_HISAX_ELSA_CS       $CONFIG_ISDN_DRV_HISAX $CONFIG_PCMCIA
+-   dep_tristate 'AVM A1 PCMCIA cards'                                 CONFIG_HISAX_AVM_A1_CS     $CONFIG_ISDN_DRV_HISAX $CONFIG_PCMCIA $CONFIG_HISAX_AVM_A1_PCMCIA
+-   dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)'                CONFIG_HISAX_ST5481        $CONFIG_ISDN_DRV_HISAX    $CONFIG_EXPERIMENTAL
+-   dep_tristate 'AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP  $CONFIG_ISDN_DRV_HISAX                $CONFIG_EXPERIMENTAL
+-   dep_tristate 'Auerswald devices ISDN support'                      CONFIG_USB_AUERISDN        $CONFIG_ISDN_DRV_HISAX
++   dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
++   dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
++   dep_tristate 'Colognechip HFC-USB support' CONFIG_HISAX_HFC_USB_CS $CONFIG_HISAX $CONFIG_USB
++   dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
++   dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
++   if [ "$CONFIG_HISAX_SEDLBAUER_CS" != "n" ]; then
++      define_bool CONFIG_HISAX_SEDLBAUER y
++   fi
++   if [ "$CONFIG_HISAX_ELSA_CS" != "n" ]; then
++      define_bool CONFIG_HISAX_ELSA y
++   fi
++   if [ "$CONFIG_HISAX_HFC_USB_CS" != "n" ]; then
++      define_bool CONFIG_HISAX_HFC_USB y
++   fi
+ fi
+ endmenu
+diff -rNu linux-2.4.29.old/drivers/isdn/Makefile linux-2.4.29/drivers/isdn/Makefile
+--- linux-2.4.29.old/drivers/isdn/Makefile     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/Makefile 2005-03-22 15:06:44.277361600 +0100
+@@ -2,7 +2,7 @@
+ # The target object and module list name.
+-O_TARGET      := vmlinux-obj.o
++O_TARGET      := isdn.a
+ # Objects that export symbols.
+@@ -32,9 +32,9 @@
+ # Object files in subdirectories
+-mod-subdirs                           := avmb1 eicon hisax
++mod-subdirs                           := avmb1 eicon
+ subdir-$(CONFIG_ISDN_DIVERSION)               += divert
+-subdir-$(CONFIG_ISDN_HISAX)           += hisax
++subdir-$(CONFIG_ISDN_DRV_HISAX)               += hisax
+ subdir-$(CONFIG_ISDN_DRV_ICN)         += icn
+ subdir-$(CONFIG_ISDN_DRV_PCBIT)               += pcbit
+ subdir-$(CONFIG_ISDN_DRV_SC)          += sc
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/act2000.h linux-2.4.29/drivers/isdn/act2000/act2000.h
+--- linux-2.4.29.old/drivers/isdn/act2000/act2000.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/act2000.h        2005-03-22 15:06:44.103388048 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: act2000.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+  *
+@@ -178,19 +178,19 @@
+         char regname[35];                /* Name used for request_region     */
+ } act2000_card;
+-static inline void act2000_schedule_tx(act2000_card *card)
++extern __inline__ void act2000_schedule_tx(act2000_card *card)
+ {
+         queue_task(&card->snd_tq, &tq_immediate);
+         mark_bh(IMMEDIATE_BH);
+ }
+-static inline void act2000_schedule_rx(act2000_card *card)
++extern __inline__ void act2000_schedule_rx(act2000_card *card)
+ {
+         queue_task(&card->rcv_tq, &tq_immediate);
+         mark_bh(IMMEDIATE_BH);
+ }
+-static inline void act2000_schedule_poll(act2000_card *card)
++extern __inline__ void act2000_schedule_poll(act2000_card *card)
+ {
+         queue_task(&card->poll_tq, &tq_immediate);
+         mark_bh(IMMEDIATE_BH);
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.c linux-2.4.29/drivers/isdn/act2000/act2000_isa.c
+--- linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/act2000_isa.c    2005-03-22 15:06:44.135383184 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: act2000_isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
+  *
+@@ -178,8 +178,7 @@
+                 card->flags &= ~ACT2000_FLAGS_PVALID;
+         }
+         if (!check_region(portbase, ISA_REGION)) {
+-                if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
+-                      return -EIO;
++                request_region(portbase, ACT2000_PORTLEN, card->regname);
+                 card->port = portbase;
+                 card->flags |= ACT2000_FLAGS_PVALID;
+                 return 0;
+@@ -341,6 +340,9 @@
+               while (skb->len) {
+                       if (act2000_isa_writeb(card, *(skb->data))) {
+                               /* Fifo is full, but more data to send */
++#if 0
++                              printk(KERN_DEBUG "act2000_isa_send: %d bytes\n", l);
++#endif
+                               test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
+                               /* Schedule myself */
+                               act2000_schedule_tx(card);
+@@ -363,6 +365,9 @@
+               } else
+                       dev_kfree_skb(skb);
+               card->sbuf = NULL;
++#if 0
++              printk(KERN_DEBUG "act2000_isa_send: %d bytes\n", l);
++#endif
+       }
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.h linux-2.4.29/drivers/isdn/act2000/act2000_isa.h
+--- linux-2.4.29.old/drivers/isdn/act2000/act2000_isa.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/act2000_isa.h    2005-03-22 15:06:44.152380600 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: act2000_isa.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/capi.c linux-2.4.29/drivers/isdn/act2000/capi.c
+--- linux-2.4.29.old/drivers/isdn/act2000/capi.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/capi.c   2005-03-22 15:06:44.172377560 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+  * CAPI encoder/decoder
+@@ -76,6 +76,10 @@
+       {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"},
+       {{ 0x86, 0x03}, "DATA_B3_RESP"},
+       {{ 0xff, 0x03}, "MANUFACTURER_RESP"},
++#if 0
++/* CAPI 2.0 */
++      {{ 0x05, 0x80}, "LISTEN_REQ (CAPI 2.0)"},
++#endif
+ #endif
+       {{ 0x00, 0x00}, NULL},
+ };
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/capi.h linux-2.4.29/drivers/isdn/act2000/capi.h
+--- linux-2.4.29.old/drivers/isdn/act2000/capi.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/capi.h   2005-03-22 15:06:44.187375280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+  *
+@@ -294,6 +294,19 @@
+                       __u16 plci;
+                       __u16 info;
+               } select_b3_protocol_conf;
++#if 0
++              struct listen_req {
++                      __u32 controller;
++                      __u32 infomask;  
++                      __u32 cipmask;
++                      __u32 cipmask2;
++                      __u16 dummy; /* 2 Length-bytes of 2 Structs MUST always be 0!!! */
++              } listen_req;
++              struct listen_conf {
++                      __u32  controller;
++                      __u16 info;
++              } listen_conf;
++#else
+               struct listen_req {
+                       __u8  controller;
+                       __u32 infomask __attribute__ ((packed));  
+@@ -304,6 +317,7 @@
+                       __u8  controller;
+                       __u16 info __attribute__ ((packed));
+               } listen_conf;
++#endif
+               struct data_b3_req {
+                       __u16 fakencci;
+                       __u16 datalen;
+@@ -330,7 +344,7 @@
+       } msg;
+ } actcapi_msg;
+-static inline unsigned short
++extern __inline__ unsigned short
+ actcapi_nextsmsg(act2000_card *card)
+ {
+       unsigned long flags;
+diff -rNu linux-2.4.29.old/drivers/isdn/act2000/module.c linux-2.4.29/drivers/isdn/act2000/module.c
+--- linux-2.4.29.old/drivers/isdn/act2000/module.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/act2000/module.c 2005-03-22 15:06:44.202373000 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: module.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
+  *
+@@ -630,6 +630,10 @@
+         card->interface.features =
+               ISDN_FEATURE_L2_X75I |
+               ISDN_FEATURE_L2_HDLC |
++#if 0
++/* Not yet! New Firmware is on the way ... */
++              ISDN_FEATURE_L2_TRANS |
++#endif
+               ISDN_FEATURE_L3_TRANS |
+               ISDN_FEATURE_P_UNKNOWN;
+         card->interface.hl_hdrlen = 20;
+@@ -843,6 +847,39 @@
+         }
+         printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
+ }
++#if 0
++#ifndef MODULE
++void
++act2000_setup(char *str, int *ints)
++{
++        int i, j, argc, port, irq, bus;
++      
++        argc = ints[0];
++        i = 1;
++        if (argc)
++                while (argc) {
++                        port = irq = -1;
++                      bus = 0;
++                        if (argc) {
++                                bus = ints[i];
++                                i++;
++                                argc--;
++                        }
++                        if (argc) {
++                                port = ints[i];
++                                i++;
++                                argc--;
++                        }
++                        if (argc) {
++                                irq = ints[i];
++                                i++;
++                                argc--;
++                        }
++                      act2000_addcard(bus, port, irq, act_id);
++              }
++}
++#endif
++#endif
+ module_init(act2000_init);
+ module_exit(act2000_exit);
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/avm_cs.c linux-2.4.29/drivers/isdn/avmb1/avm_cs.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/avm_cs.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/avm_cs.c   2005-03-22 15:06:44.696297912 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_cs.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: avm_cs.c,v 1.6 2001/09/24 13:22:44 kai Exp $
+  *
+  * A PCMCIA client driver for AVM B1/M1/M2
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/avmcard.h linux-2.4.29/drivers/isdn/avmb1/avmcard.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/avmcard.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/avmcard.h  2005-03-22 15:06:44.711295632 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avmcard.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: avmcard.h,v 1.12 2001/09/24 13:22:44 kai Exp $
+  *
+  * Copyright 1999 by Carsten Paeth <calle@calle.de>
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1.c linux-2.4.29/drivers/isdn/avmb1/b1.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1.c       2005-03-22 15:06:44.733292288 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1.c,v 1.26 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Common module for AVM B1 cards.
+  * 
+@@ -20,6 +20,7 @@
+ #include <linux/kernelcapi.h>
+ #include <asm/io.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include <asm/uaccess.h>
+ #include <linux/netdevice.h>
+ #include "capilli.h"
+@@ -27,7 +28,7 @@
+ #include "capicmd.h"
+ #include "capiutil.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.26 $";
+ /* ------------------------------------------------------------- */
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1dma.c linux-2.4.29/drivers/isdn/avmb1/b1dma.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1dma.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1dma.c    2005-03-22 15:06:44.750289704 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1dma.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1dma.c,v 1.18 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Common module for AVM B1 cards that support dma with AMCC
+  * 
+@@ -21,6 +21,7 @@
+ #include <linux/kernelcapi.h>
+ #include <asm/io.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include <asm/uaccess.h>
+ #include <linux/netdevice.h>
+ #include "capilli.h"
+@@ -28,7 +29,11 @@
+ #include "capicmd.h"
+ #include "capiutil.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++#if BITS_PER_LONG != 32
++#error FIXME: driver requires 32-bit platform
++#endif
++
++static char *revision = "$Revision: 1.18 $";
+ /* ------------------------------------------------------------- */
+@@ -851,7 +856,7 @@
+       __u8 flag;
+       int len = 0;
+       char *s;
+-      u_long txaddr, txlen, rxaddr, rxlen, csr;
++      __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);
+@@ -907,12 +912,12 @@
+       save_flags(flags);
+       cli();
+-      txaddr = (u_long)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
+-      txaddr -= (u_long)card->dma->sendbuf;
++      txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c));
++      txaddr -= (__u32)card->dma->sendbuf;
+       txlen  = b1dmainmeml(card->mbase+0x30);
+-      rxaddr = (u_long)phys_to_virt(b1dmainmeml(card->mbase+0x24));
+-      rxaddr -= (u_long)card->dma->recvbuf;
++      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);
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1isa.c linux-2.4.29/drivers/isdn/avmb1/b1isa.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1isa.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1isa.c    2005-03-22 15:06:44.766287272 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1isa.c,v 1.14 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Module for AVM B1 ISA-card.
+  * 
+@@ -19,12 +19,13 @@
+ #include <linux/capi.h>
+ #include <linux/init.h>
+ #include <asm/io.h>
++#include <linux/isdn_compat.h>
+ #include "capicmd.h"
+ #include "capiutil.h"
+ #include "capilli.h"
+ #include "avmcard.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.14 $";
+ /* ------------------------------------------------------------- */
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1pci.c linux-2.4.29/drivers/isdn/avmb1/b1pci.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1pci.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1pci.c    2005-03-22 15:06:44.781284992 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1pci.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1pci.c,v 1.40 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Module for AVM B1 PCI-card.
+  * 
+@@ -21,21 +21,24 @@
+ #include <linux/capi.h>
+ #include <asm/io.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include "capicmd.h"
+ #include "capiutil.h"
+ #include "capilli.h"
+ #include "avmcard.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.40 $";
+ /* ------------------------------------------------------------- */
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id b1pci_pci_tbl[] __initdata = {
+       { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
+       { }                             /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card");
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+@@ -416,14 +419,14 @@
+       }
+       param.irq = dev->irq;
+-      if (pci_resource_start(dev, 2)) { /* B1 PCI V4 */
++      if (pci_resource_start_io(dev, 2)) { /* B1 PCI V4 */
+ #ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
+               driver = &b1pciv4_driver;
+               pci_set_master(dev);
+ #endif
+-              param.membase = pci_resource_start(dev, 0);
+-              param.port = pci_resource_start(dev, 2);
++              param.membase = pci_resource_start_mem(dev, 0);
++              param.port = pci_resource_start_io(dev, 2);
+               printk(KERN_INFO
+               "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
+@@ -440,7 +443,7 @@
+               }
+       } else {
+               param.membase = 0;
+-              param.port = pci_resource_start(dev, 1);
++              param.port = pci_resource_start_io(dev, 1);
+               printk(KERN_INFO
+               "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/b1pcmcia.c linux-2.4.29/drivers/isdn/avmb1/b1pcmcia.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/b1pcmcia.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/b1pcmcia.c 2005-03-22 15:06:44.796282712 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1pcmcia.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: b1pcmcia.c,v 1.17 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Module for AVM B1/M1/M2 PCMCIA-card.
+  * 
+@@ -25,7 +25,7 @@
+ #include "capilli.h"
+ #include "avmcard.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.17 $";
+ /* ------------------------------------------------------------- */
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/c4.c linux-2.4.29/drivers/isdn/avmb1/c4.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/c4.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/c4.c       2005-03-22 15:06:44.812280280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: c4.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: c4.c,v 1.38 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Module for AVM C4 & C2 card.
+  * 
+@@ -18,6 +18,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/ioport.h>
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/init.h>
+@@ -29,7 +30,7 @@
+ #include "capilli.h"
+ #include "avmcard.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.38 $";
+ #undef CONFIG_C4_DEBUG
+ #undef CONFIG_C4_POLLDEBUG
+@@ -38,6 +39,7 @@
+ static int suppress_pollack;
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id c4_pci_tbl[] __initdata = {
+       { PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4 },
+       { PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2 },
+@@ -45,6 +47,7 @@
+ };
+ MODULE_DEVICE_TABLE(pci, c4_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards");
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+@@ -1328,9 +1331,9 @@
+               }
+               pci_set_master(dev);
+-              param.port = pci_resource_start(dev, 1);
++              param.port = pci_resource_start_io(dev, 1);
+               param.irq = dev->irq;
+-              param.membase = pci_resource_start(dev, 0);
++              param.membase = pci_resource_start_mem(dev, 0);
+   
+               printk(KERN_INFO
+                       "%s: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capi.c linux-2.4.29/drivers/isdn/avmb1/capi.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capi.c     2005-03-22 15:06:44.849274656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.c,v 1.1.4.2 2001/12/09 18:45:13 kai Exp $
++/* $Id: capi.c,v 1.59 2001/11/07 22:35:48 kai Exp $
+  *
+  * CAPI 2.0 Interface for Linux
+  *
+@@ -23,6 +23,7 @@
+ #include <linux/smp_lock.h>
+ #include <linux/timer.h>
+ #include <linux/wait.h>
++#include <linux/isdn_compat.h>
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ #include <linux/tty.h>
+ #ifdef CONFIG_PPP
+@@ -30,6 +31,9 @@
+ #include <linux/ppp_defs.h>
+ #include <linux/if_ppp.h>
+ #undef CAPI_PPP_ON_RAW_DEVICE
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++#include <linux/ppp_channel.h>
++#endif /* CAPI_PPP_ON_RAW_DEVICE */
+ #endif /* CONFIG_PPP */
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ #include <linux/skbuff.h>
+@@ -38,14 +42,16 @@
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/init.h>
++#ifdef HAVE_DEVFS_FS
+ #include <linux/devfs_fs_kernel.h>
++#endif /* HAVE_DEVFS_FS */
+ #include "capiutil.h"
+ #include "capicmd.h"
+ #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
+ #include "capifs.h"
+ #endif
+-static char *revision = "$Revision: 1.1.4.2 $";
++static char *revision = "$Revision: 1.59 $";
+ MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
+ MODULE_AUTHOR("Carsten Paeth");
+@@ -87,10 +93,10 @@
+       struct capincci  *nccip;
+       unsigned int      minor;
+-      u16              applid;
+-      u32              ncci;
+-      u16              datahandle;
+-      u16              msgid;
++      __u16            applid;
++      __u32            ncci;
++      __u16            datahandle;
++      __u16            msgid;
+       struct file      *file;
+       struct tty_struct *tty;
+@@ -112,16 +118,22 @@
+       /* transmit path */
+       struct datahandle_queue {
+                   struct datahandle_queue *next;
+-                  u16                      datahandle;
++                  __u16                    datahandle;
+       } *ackqueue;
+       int nack;
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++      /* interface to generic ppp layer */
++      struct ppp_channel      chan;
++      int                     chan_connected;
++      int                     chan_index;
++#endif
+ };
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ struct capincci {
+       struct capincci *next;
+-      u32              ncci;
++      __u32            ncci;
+       struct capidev  *cdev;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+       struct capiminor *minorp;
+@@ -131,8 +143,8 @@
+ struct capidev {
+       struct capidev *next;
+       struct file    *file;
+-      u16             applid;
+-      u16             errcode;
++      __u16           applid;
++      __u16           errcode;
+       unsigned int    minor;
+       unsigned        userflags;
+@@ -156,22 +168,28 @@
+ static struct capiminor *minors = 0;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef COMPAT_HAS_kmem_cache
+ static kmem_cache_t *capidev_cachep = 0;
+ static kmem_cache_t *capincci_cachep = 0;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ static kmem_cache_t *capiminor_cachep = 0;
+ static kmem_cache_t *capidh_cachep = 0;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#endif
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ /* -------- datahandles --------------------------------------------- */
+-static int capincci_add_ack(struct capiminor *mp, u16 datahandle)
++int capincci_add_ack(struct capiminor *mp, __u16 datahandle)
+ {
+       struct datahandle_queue *n, **pp;
+       n = (struct datahandle_queue *)
++#ifdef COMPAT_HAS_kmem_cache
+       kmem_cache_alloc(capidh_cachep, GFP_ATOMIC);
++#else
++      kmalloc(sizeof(struct datahandle_queue), GFP_ATOMIC);
++#endif
+       if (!n) {
+          printk(KERN_ERR "capi: alloc datahandle failed\n");
+          return -1;
+@@ -184,7 +202,7 @@
+       return 0;
+ }
+-static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
++int capiminor_del_ack(struct capiminor *mp, __u16 datahandle)
+ {
+       struct datahandle_queue **pp, *p;
+@@ -192,7 +210,11 @@
+               if ((*pp)->datahandle == datahandle) {
+                       p = *pp;
+                       *pp = (*pp)->next;
++#ifdef COMPAT_HAS_kmem_cache
+                       kmem_cache_free(capidh_cachep, p);
++#else
++                      kfree(p);
++#endif
+                       mp->nack--;
+                       return 0;
+               }
+@@ -200,7 +222,7 @@
+       return -1;
+ }
+-static void capiminor_del_all_ack(struct capiminor *mp)
++void capiminor_del_all_ack(struct capiminor *mp)
+ {
+       struct datahandle_queue **pp, *p;
+@@ -208,7 +230,11 @@
+       while (*pp) {
+               p = *pp;
+               *pp = (*pp)->next;
++#ifdef COMPAT_HAS_kmem_cache
+               kmem_cache_free(capidh_cachep, p);
++#else
++              kfree(p);
++#endif
+               mp->nack--;
+       }
+ }
+@@ -216,13 +242,17 @@
+ /* -------- struct capiminor ---------------------------------------- */
+-static struct capiminor *capiminor_alloc(u16 applid, u32 ncci)
++struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci)
+ {
+       struct capiminor *mp, **pp;
+         unsigned int minor = 0;
+       MOD_INC_USE_COUNT;
++#ifdef COMPAT_HAS_kmem_cache
+       mp = (struct capiminor *)kmem_cache_alloc(capiminor_cachep, GFP_ATOMIC);
++#else
++      mp = (struct capiminor *)kmalloc(sizeof(struct capiminor), GFP_ATOMIC);
++#endif
+       if (!mp) {
+               MOD_DEC_USE_COUNT;
+               printk(KERN_ERR "capi: can't alloc capiminor\n");
+@@ -257,7 +287,7 @@
+       return mp;
+ }
+-static void capiminor_free(struct capiminor *mp)
++void capiminor_free(struct capiminor *mp)
+ {
+       struct capiminor **pp;
+@@ -271,7 +301,11 @@
+                       skb_queue_purge(&mp->inqueue);
+                       skb_queue_purge(&mp->outqueue);
+                       capiminor_del_all_ack(mp);
++#ifdef COMPAT_HAS_kmem_cache
+                       kmem_cache_free(capiminor_cachep, mp);
++#else
++                      kfree(mp);
++#endif
+                       MOD_DEC_USE_COUNT;
+ #ifdef _DEBUG_REFCOUNT
+                       printk(KERN_DEBUG "capiminor_free %d\n", GET_USE_COUNT(THIS_MODULE));
+@@ -283,7 +317,7 @@
+       }
+ }
+-static struct capiminor *capiminor_find(unsigned int minor)
++struct capiminor *capiminor_find(unsigned int minor)
+ {
+       struct capiminor *p;
+       for (p = minors; p && p->minor != minor; p = p->next)
+@@ -294,7 +328,7 @@
+ /* -------- struct capincci ----------------------------------------- */
+-static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
++static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci)
+ {
+       struct capincci *np, **pp;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+@@ -302,7 +336,11 @@
+       kdev_t kdev;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef COMPAT_HAS_kmem_cache
+       np = (struct capincci *)kmem_cache_alloc(capincci_cachep, GFP_ATOMIC);
++#else
++      np = (struct capincci *)kmalloc(sizeof(struct capincci), GFP_ATOMIC);
++#endif
+       if (!np)
+               return 0;
+       memset(np, 0, sizeof(struct capincci));
+@@ -331,7 +369,7 @@
+         return np;
+ }
+-static void capincci_free(struct capidev *cdev, u32 ncci)
++static void capincci_free(struct capidev *cdev, __u32 ncci)
+ {
+       struct capincci *np, **pp;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+@@ -367,7 +405,11 @@
+                               }
+                       }
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef COMPAT_HAS_kmem_cache
+                       kmem_cache_free(capincci_cachep, np);
++#else
++                      kfree(np);
++#endif
+                       if (*pp == 0) return;
+               } else {
+                       pp = &(*pp)->next;
+@@ -375,7 +417,7 @@
+       }
+ }
+-static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
++struct capincci *capincci_find(struct capidev *cdev, __u32 ncci)
+ {
+       struct capincci *p;
+@@ -393,7 +435,11 @@
+       struct capidev *cdev;
+       struct capidev **pp;
++#ifdef COMPAT_HAS_kmem_cache
+       cdev = (struct capidev *)kmem_cache_alloc(capidev_cachep, GFP_KERNEL);
++#else
++      cdev = (struct capidev *)kmalloc(sizeof(struct capidev), GFP_KERNEL);
++#endif
+       if (!cdev)
+               return 0;
+       memset(cdev, 0, sizeof(struct capidev));
+@@ -423,10 +469,14 @@
+       if (*pp)
+               *pp = cdev->next;
++#ifdef COMPAT_HAS_kmem_cache
+       kmem_cache_free(capidev_cachep, cdev);
++#else
++      kfree(cdev);
++#endif
+ }
+-static struct capidev *capidev_find(u16 applid)
++static struct capidev *capidev_find(__u16 applid)
+ {
+       struct capidev *p;
+       for (p=capidev_openlist; p; p = p->next) {
+@@ -439,13 +489,13 @@
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+ /* -------- handle data queue --------------------------------------- */
+-static struct sk_buff *
++struct sk_buff *
+ gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
+ {
+       struct sk_buff *nskb;
+       nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_ATOMIC);
+       if (nskb) {
+-              u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
++              __u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
+               unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
+               capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
+               capimsg_setu16(s, 2, mp->applid);
+@@ -458,11 +508,11 @@
+       return nskb;
+ }
+-static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
++int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
+ {
+       struct sk_buff *nskb;
+       unsigned int datalen;
+-      u16 errcode, datahandle;
++      __u16 errcode, datahandle;
+       datalen = skb->len - CAPIMSG_LEN(skb->data);
+       if (mp->tty) {
+@@ -504,6 +554,28 @@
+               kfree_skb(skb);
+               return 0;
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++      } else if (mp->chan_connected) {
++              if ((nskb = gen_data_b3_resp_for(mp, skb)) == 0) {
++                      printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
++                      return -1;
++              }
++              datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4);
++              errcode = (*capifuncs->capi_put_message)(mp->applid, nskb);
++              if (errcode != CAPI_NOERROR) {
++                      printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
++                                      errcode);
++                      kfree_skb(nskb);
++                      return -1;
++              }
++              (void)skb_pull(skb, CAPIMSG_LEN(skb->data));
++#ifdef _DEBUG_DATAFLOW
++              printk(KERN_DEBUG "capi: DATA_B3_RESP %u len=%d => ppp\n",
++                                      datahandle, skb->len);
++#endif
++              ppp_input(&mp->chan, skb);
++              return 0;
++#endif
+       } else if (mp->file) {
+               if (skb_queue_len(&mp->recvqueue) > CAPINC_MAX_RECVQUEUE) {
+ #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
+@@ -538,7 +610,7 @@
+       return -1;
+ }
+-static void handle_minor_recv(struct capiminor *mp)
++void handle_minor_recv(struct capiminor *mp)
+ {
+       struct sk_buff *skb;
+       while ((skb = skb_dequeue(&mp->inqueue)) != 0) {
+@@ -552,13 +624,13 @@
+       }
+ }
+-static int handle_minor_send(struct capiminor *mp)
++int handle_minor_send(struct capiminor *mp)
+ {
+       struct sk_buff *skb;
+-      u16 len;
++      __u16 len;
+       int count = 0;
+-      u16 errcode;
+-      u16 datahandle;
++      __u16 errcode;
++      __u16 datahandle;
+       if (mp->tty && mp->ttyoutstop) {
+ #if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS)
+@@ -569,7 +641,7 @@
+       while ((skb = skb_dequeue(&mp->outqueue)) != 0) {
+               datahandle = mp->datahandle;
+-              len = (u16)skb->len;
++              len = (__u16)skb->len;
+               skb_push(skb, CAPI_DATA_B3_REQ_LEN);
+               memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
+               capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
+@@ -578,7 +650,7 @@
+               capimsg_setu8 (skb->data, 5, CAPI_REQ);
+               capimsg_setu16(skb->data, 6, mp->msgid++);
+               capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
+-              capimsg_setu32(skb->data, 12, (u32) skb->data); /* Data32 */
++              capimsg_setu32(skb->data, 12, (__u32) skb->data); /* Data32 */
+               capimsg_setu16(skb->data, 16, len);     /* Data length */
+               capimsg_setu16(skb->data, 18, datahandle);
+               capimsg_setu16(skb->data, 20, 0);       /* Flags */
+@@ -620,16 +692,16 @@
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+ /* -------- function called by lower level -------------------------- */
+-static void capi_signal(u16 applid, void *param)
++static void capi_signal(__u16 applid, void *param)
+ {
+       struct capidev *cdev = (struct capidev *)param;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+       struct capiminor *mp;
+-      u16 datahandle;
++      __u16 datahandle;
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+       struct capincci *np;
+       struct sk_buff *skb = 0;
+-      u32 ncci;
++      __u32 ncci;
+       (void) (*capifuncs->capi_get_message) (applid, &skb);
+       if (!skb) {
+@@ -683,6 +755,12 @@
+ #endif
+               kfree_skb(skb);
+               (void)capiminor_del_ack(mp, datahandle);
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++              if (mp->chan_connected) {
++                      ppp_output_wakeup(&mp->chan);
++                      return;
++              }
++#endif
+               if (mp->tty) {
+                       if (mp->tty->ldisc.write_wakeup)
+                               mp->tty->ldisc.write_wakeup(mp->tty);
+@@ -758,7 +836,7 @@
+       struct capidev *cdev = (struct capidev *)file->private_data;
+       struct sk_buff *skb;
+       int retval;
+-      u16 mlen;
++      __u16 mlen;
+         if (ppos != &file->f_pos)
+               return -ESPIPE;
+@@ -998,7 +1076,7 @@
+                                               sizeof(ncci));
+                       if (retval)
+                               return -EFAULT;
+-                      nccip = capincci_find(cdev, (u32) ncci);
++                      nccip = capincci_find(cdev, (__u32) ncci);
+                       if (!nccip)
+                               return 0;
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+@@ -1023,7 +1101,7 @@
+                                               sizeof(ncci));
+                       if (retval)
+                               return -EFAULT;
+-                      nccip = capincci_find(cdev, (u32) ncci);
++                      nccip = capincci_find(cdev, (__u32) ncci);
+                       if (!nccip || (mp = nccip->minorp) == 0)
+                               return -ESRCH;
+                       return mp->minor;
+@@ -1070,7 +1148,9 @@
+ static struct file_operations capi_fops =
+ {
++#ifdef COMPAT_HAS_FILEOP_OWNER
+       owner:          THIS_MODULE,
++#endif
+       llseek:         no_llseek,
+       read:           capi_read,
+       write:          capi_write,
+@@ -1233,6 +1313,45 @@
+               return -EINVAL;
+       switch (cmd) {
++#ifdef CAPI_PPP_ON_RAW_DEVICE
++      case PPPIOCATTACH:
++              {
++                      int retval, val;
++                      if (get_user(val, (int *) arg))
++                              break;
++                      if (mp->chan_connected)
++                              return -EALREADY;
++                      mp->chan.private = mp;
++#if 1
++                      return -EINVAL;
++#else
++                      mp->chan.ops = &ppp_ops;
++#endif
++
++                      retval = ppp_register_channel(&mp->chan, val);
++                      if (retval)
++                              return retval;
++                      mp->chan_connected = 1;
++                      mp->chan_index = val;
++              }
++              return 0;
++      case PPPIOCDETACH:
++              {
++                      if (!mp->chan_connected)
++                              return -ENXIO;
++                      ppp_unregister_channel(&mp->chan);
++                      mp->chan_connected = 0;
++              }
++              return 0;
++      case PPPIOCGUNIT:
++              {
++                      if (!mp->chan_connected)
++                              return -ENXIO;
++                      if (put_user(mp->chan_index, (int *) arg))
++                              return -EFAULT;
++              }
++              return 0;
++#endif
+       }
+       return -EINVAL;
+ }
+@@ -1260,7 +1379,9 @@
+ static struct file_operations capinc_raw_fops =
+ {
++#ifdef COMPAT_HAS_FILEOP_OWNER
+       owner:          THIS_MODULE,
++#endif
+       llseek:         no_llseek,
+       read:           capinc_raw_read,
+       write:          capinc_raw_write,
+@@ -1272,7 +1393,7 @@
+ /* -------- tty_operations for capincci ----------------------------- */
+-static int capinc_tty_open(struct tty_struct * tty, struct file * file)
++int capinc_tty_open(struct tty_struct * tty, struct file * file)
+ {
+       struct capiminor *mp;
+@@ -1300,7 +1421,7 @@
+       return 0;
+ }
+-static void capinc_tty_close(struct tty_struct * tty, struct file * file)
++void capinc_tty_close(struct tty_struct * tty, struct file * file)
+ {
+       struct capiminor *mp;
+@@ -1325,8 +1446,8 @@
+ #endif
+ }
+-static int capinc_tty_write(struct tty_struct * tty, int from_user,
+-                          const unsigned char *buf, int count)
++int capinc_tty_write(struct tty_struct * tty, int from_user,
++                    const unsigned char *buf, int count)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+       struct sk_buff *skb;
+@@ -1377,7 +1498,7 @@
+       return count;
+ }
+-static void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
++void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+       struct sk_buff *skb;
+@@ -1414,7 +1535,7 @@
+       }
+ }
+-static void capinc_tty_flush_chars(struct tty_struct *tty)
++void capinc_tty_flush_chars(struct tty_struct *tty)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+       struct sk_buff *skb;
+@@ -1440,7 +1561,7 @@
+       (void)handle_minor_recv(mp);
+ }
+-static int capinc_tty_write_room(struct tty_struct *tty)
++int capinc_tty_write_room(struct tty_struct *tty)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+       int room;
+@@ -1458,7 +1579,7 @@
+       return room;
+ }
+-static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
++int capinc_tty_chars_in_buffer(struct tty_struct *tty)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+       if (!mp || !mp->nccip) {
+@@ -1476,7 +1597,7 @@
+       return mp->outbytes;
+ }
+-static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
++int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
+                   unsigned int cmd, unsigned long arg)
+ {
+       int error = 0;
+@@ -1488,14 +1609,14 @@
+       return error;
+ }
+-static void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
++void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+       printk(KERN_DEBUG "capinc_tty_set_termios\n");
+ #endif
+ }
+-static void capinc_tty_throttle(struct tty_struct * tty)
++void capinc_tty_throttle(struct tty_struct * tty)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1505,7 +1626,7 @@
+               mp->ttyinstop = 1;
+ }
+-static void capinc_tty_unthrottle(struct tty_struct * tty)
++void capinc_tty_unthrottle(struct tty_struct * tty)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1517,7 +1638,7 @@
+       }
+ }
+-static void capinc_tty_stop(struct tty_struct *tty)
++void capinc_tty_stop(struct tty_struct *tty)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1528,7 +1649,7 @@
+       }
+ }
+-static void capinc_tty_start(struct tty_struct *tty)
++void capinc_tty_start(struct tty_struct *tty)
+ {
+       struct capiminor *mp = (struct capiminor *)tty->driver_data;
+ #ifdef _DEBUG_TTYFUNCS
+@@ -1540,43 +1661,49 @@
+       }
+ }
+-static void capinc_tty_hangup(struct tty_struct *tty)
++void capinc_tty_hangup(struct tty_struct *tty)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+       printk(KERN_DEBUG "capinc_tty_hangup\n");
+ #endif
+ }
+-static void capinc_tty_break_ctl(struct tty_struct *tty, int state)
++void capinc_tty_break_ctl(struct tty_struct *tty, int state)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+       printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
+ #endif
+ }
+-static void capinc_tty_flush_buffer(struct tty_struct *tty)
++void capinc_tty_flush_buffer(struct tty_struct *tty)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+       printk(KERN_DEBUG "capinc_tty_flush_buffer\n");
+ #endif
+ }
+-static void capinc_tty_set_ldisc(struct tty_struct *tty)
++void capinc_tty_set_ldisc(struct tty_struct *tty)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+       printk(KERN_DEBUG "capinc_tty_set_ldisc\n");
+ #endif
+ }
+-static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
++void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
+ {
+ #ifdef _DEBUG_TTYFUNCS
+       printk(KERN_DEBUG "capinc_tty_send_xchar(%d)\n", ch);
+ #endif
+ }
+-static int capinc_tty_read_proc(char *page, char **start, off_t off,
+-                              int count, int *eof, void *data)
++int capinc_tty_read_proc(char *page, char **start, off_t off,
++                        int count, int *eof, void *data)
++{
++      return 0;
++}
++
++int capinc_write_proc(struct file *file, const char *buffer,
++                        unsigned long count, void *data)
+ {
+       return 0;
+ }
+@@ -1588,7 +1715,7 @@
+ static struct termios *capinc_tty_termios[CAPINC_NR_PORTS];
+ static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS];
+-static int capinc_tty_init(void)
++int capinc_tty_init(void)
+ {
+       struct tty_driver *drv = &capinc_tty_driver;
+@@ -1646,7 +1773,7 @@
+       return 0;
+ }
+-static void capinc_tty_exit(void)
++void capinc_tty_exit(void)
+ {
+       struct tty_driver *drv = &capinc_tty_driver;
+       int retval;
+@@ -1771,8 +1898,9 @@
+ /* -------- init function and module interface ---------------------- */
++#ifdef COMPAT_HAS_kmem_cache
+-static void alloc_exit(void)
++static void __exit alloc_exit(void)
+ {
+       if (capidev_cachep) {
+               (void)kmem_cache_destroy(capidev_cachep);
+@@ -1837,8 +1965,9 @@
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+       return 0;
+ }
++#endif
+-static void lower_callback(unsigned int cmd, u32 contr, void *data)
++static void lower_callback(unsigned int cmd, __u32 contr, void *data)
+ {
+       struct capi_ncciinfo *np;
+       struct capidev *cdev;
+@@ -1900,15 +2029,19 @@
+               MOD_DEC_USE_COUNT;
+               return -EIO;
+       }
++#ifdef HAVE_DEVFS_FS
+         devfs_register_series (NULL, "capi/r%u", CAPINC_NR_PORTS,
+                             DEVFS_FL_DEFAULT,
+                               capi_rawmajor, 0,
+                               S_IFCHR | S_IRUSR | S_IWUSR,
+                               &capinc_raw_fops, NULL);
++#endif
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef HAVE_DEVFS_FS
+       devfs_register (NULL, "isdn/capi20", DEVFS_FL_DEFAULT,
+                       capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR,
+                       &capi_fops, NULL);
++#endif
+       printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major);
+       if ((capifuncs = attach_capi_interface(&cuser)) == 0) {
+@@ -1918,9 +2051,11 @@
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+               devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef HAVE_DEVFS_FS
+               devfs_unregister(devfs_find_handle(NULL, "capi20",
+                                                  capi_major, 0,
+                                                  DEVFS_SPECIAL_CHR, 0));
++#endif
+               return -EIO;
+       }
+@@ -1934,8 +2069,10 @@
+       }
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
++#ifdef COMPAT_HAS_kmem_cache
+       if (alloc_init() < 0) {
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
++#ifdef HAVE_DEVFS_FS
+               unsigned int j;
+               devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
+               for (j = 0; j < CAPINC_NR_PORTS; j++) {
+@@ -1943,16 +2080,20 @@
+                       sprintf(devname, "capi/r%u", j);
+                       devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));
+               }
++#endif
+               capinc_tty_exit();
+ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
+               (void) detach_capi_interface(&cuser);
+               devfs_unregister_chrdev(capi_major, "capi20");
++#ifdef HAVE_DEVFS_FS
+               devfs_unregister(devfs_find_handle(NULL, "capi20",
+                                                  capi_major, 0,
+                                                  DEVFS_SPECIAL_CHR, 0));
++#endif
+               MOD_DEC_USE_COUNT;
+               return -ENOMEM;
+       }
++#endif /* COMPAT_HAS_kmem_cache */
+       (void)proc_init();
+@@ -1975,23 +2116,31 @@
+ static void __exit capi_exit(void)
+ {
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
++#ifdef HAVE_DEVFS_FS
+       unsigned int j;
+ #endif
++#endif
++#ifdef COMPAT_HAS_kmem_cache
+       alloc_exit();
++#endif
+       (void)proc_exit();
+       devfs_unregister_chrdev(capi_major, "capi20");
++#ifdef HAVE_DEVFS_FS
+       devfs_unregister(devfs_find_handle(NULL, "isdn/capi20", capi_major, 0, DEVFS_SPECIAL_CHR, 0));
++#endif
+ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
+       capinc_tty_exit();
+       devfs_unregister_chrdev(capi_rawmajor, "capi/r%d");
++#ifdef HAVE_DEVFS_FS
+       for (j = 0; j < CAPINC_NR_PORTS; j++) {
+               char devname[32];
+               sprintf(devname, "capi/r%u", j);
+               devfs_unregister(devfs_find_handle(NULL, devname, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0));
+       }
+ #endif
++#endif
+       (void) detach_capi_interface(&cuser);
+       printk(KERN_NOTICE "capi: Rev %s: unloaded\n", rev);
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capicmd.h linux-2.4.29/drivers/isdn/avmb1/capicmd.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capicmd.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capicmd.h  2005-03-22 15:06:44.865272224 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capicmd.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capicmd.h,v 1.4 2001/09/24 13:22:44 kai Exp $
+  * 
+  * CAPI 2.0 Interface for Linux
+  * 
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capidev.h linux-2.4.29/drivers/isdn/avmb1/capidev.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capidev.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capidev.h  2005-03-22 15:06:44.880269944 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capidev.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capidev.h,v 1.8 2001/09/24 13:22:44 kai Exp $
+  *
+  * CAPI 2.0 Interface for Linux
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capidrv.c linux-2.4.29/drivers/isdn/avmb1/capidrv.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capidrv.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capidrv.c  2005-03-22 15:06:44.918264168 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capidrv.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capidrv.c,v 1.45 2001/09/24 13:22:44 kai Exp $
+  *
+  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
+  *
+@@ -35,7 +35,7 @@
+ #include "capicmd.h"
+ #include "capidrv.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.45 $";
+ static int debugmode = 0;
+ MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
+@@ -105,7 +105,6 @@
+                               int oldstate;
+                               /* */
+                               __u16 datahandle;
+-                                spinlock_t lock;
+                               struct ncci_datahandle_queue {
+                                   struct ncci_datahandle_queue *next;
+                                   __u16                         datahandle;
+@@ -423,7 +422,6 @@
+       nccip->plcip = plcip;
+       nccip->chan = plcip->chan;
+       nccip->datahandle = 0;
+-        nccip->lock = SPIN_LOCK_UNLOCKED;
+       nccip->next = plcip->ncci_list;
+       plcip->ncci_list = nccip;
+@@ -480,7 +478,6 @@
+                          __u16 datahandle, int len)
+ {
+       struct ncci_datahandle_queue *n, **pp;
+-      unsigned long flags;
+       n = (struct ncci_datahandle_queue *)
+               kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
+@@ -491,31 +488,25 @@
+       n->next = 0;
+       n->datahandle = datahandle;
+       n->len = len;
+-      spin_lock_irqsave(&nccip->lock, flags);
+       for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ;
+       *pp = n;
+-      spin_unlock_irqrestore(&nccip->lock, flags);
+       return 0;
+ }
+ static int capidrv_del_ack(struct capidrv_ncci *nccip, __u16 datahandle)
+ {
+       struct ncci_datahandle_queue **pp, *p;
+-      unsigned long flags;
+       int len;
+-      spin_lock_irqsave(&nccip->lock, flags);
+       for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) {
+               if ((*pp)->datahandle == datahandle) {
+                       p = *pp;
+                       len = p->len;
+                       *pp = (*pp)->next;
+-                      spin_unlock_irqrestore(&nccip->lock, flags);
+                       kfree(p);
+                       return len;
+               }
+       }
+-        spin_unlock_irqrestore(&nccip->lock, flags);
+       return -1;
+ }
+@@ -523,25 +514,13 @@
+ static void send_message(capidrv_contr * card, _cmsg * cmsg)
+ {
+-      struct sk_buff  *skb;
+-      size_t          len;
+-      u16             err;
+-
++      struct sk_buff *skb;
++      size_t len;
+       capi_cmsg2message(cmsg, cmsg->buf);
+       len = CAPIMSG_LEN(cmsg->buf);
+       skb = alloc_skb(len, GFP_ATOMIC);
+-      if(!skb) {
+-              printk(KERN_ERR "no skb len(%d) memory\n", len);
+-              return;
+-      }
+       memcpy(skb_put(skb, len), cmsg->buf, len);
+-      err = (*capifuncs->capi_put_message) (global.appid, skb);
+-      if (err) {
+-              printk(KERN_WARNING "%s: capi_put_message error: %04x\n",
+-                      __FUNCTION__, err);
+-              kfree_skb(skb);
+-              return;
+-      }
++      (*capifuncs->capi_put_message) (global.appid, skb);
+       global.nsentctlpkt++;
+ }
+@@ -1932,8 +1911,10 @@
+                       (void)capidrv_del_ack(nccip, datahandle);
+                       return 0;
+               }
++#if 1
+               printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
+                      card->contrnr, skb_headroom(skb), msglen);
++#endif
+               memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
+               errcode = (*capifuncs->capi_put_message) (global.appid, nskb);
+               if (errcode == CAPI_NOERROR) {
+@@ -2035,6 +2016,52 @@
+       send_message(card, &cmdcmsg);
+ }
++#if 0
++static void disable_dchannel_trace(capidrv_contr *card)
++{
++        __u8 manufacturer[CAPI_MANUFACTURER_LEN];
++        capi_version version;
++      __u16 contr = card->contrnr;
++      __u16 errcode;
++      __u16 avmversion[3];
++
++        errcode = (*capifuncs->capi_get_manufacturer)(contr, manufacturer);
++        if (errcode != CAPI_NOERROR) {
++         printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
++                      card->name, errcode);
++         return;
++      }
++      if (strstr(manufacturer, "AVM") == 0) {
++         printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
++                      card->name, manufacturer);
++         return;
++      }
++        errcode = (*capifuncs->capi_get_version)(contr, &version);
++        if (errcode != CAPI_NOERROR) {
++         printk(KERN_ERR "%s: can't get version (0x%x)\n",
++                      card->name, errcode);
++         return;
++      }
++      avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
++      avmversion[1] = (version.majormanuversion << 4) & 0xf0;
++      avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
++      avmversion[2] |= version.minormanuversion & 0x0f;
++
++        if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
++              printk(KERN_INFO "%s: D2 trace disabled\n", card->name);
++      } else {
++              printk(KERN_INFO "%s: D3 trace disabled\n", card->name);
++      }
++      capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid,
++                                 card->msgid++,
++                                 contr,
++                                 0x214D5641,  /* ManuID */
++                                 0,           /* Class */
++                                 1,           /* Function */
++                                 (_cstruct)"\004\000\000\000\000");
++      send_message(card, &cmdcmsg);
++}
++#endif
+ static void send_listen(capidrv_contr *card)
+ {
+@@ -2200,10 +2227,10 @@
+                       free_ncci(card, card->bchans[card->nbchan-1].nccip);
+               if (card->bchans[card->nbchan-1].plcip)
+                       free_plci(card, card->bchans[card->nbchan-1].plcip);
++              if (card->plci_list)
++                      printk(KERN_ERR "capidrv: bug in free_plci()\n");
+               card->nbchan--;
+       }
+-      if (card->plci_list)
+-              printk(KERN_ERR "capidrv: bug in free_plci()\n");
+       kfree(card->bchans);
+       card->bchans = 0;
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capidrv.h linux-2.4.29/drivers/isdn/avmb1/capidrv.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capidrv.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capidrv.h  2005-03-22 15:06:44.935261584 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capidrv.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capidrv.h,v 1.4 2001/09/24 13:22:44 kai Exp $
+  *
+  * ISDN4Linux Driver, using capi20 interface (kernelcapi)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capifs.c linux-2.4.29/drivers/isdn/avmb1/capifs.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capifs.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capifs.c   2005-03-22 15:06:44.950259304 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capifs.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capifs.c,v 1.22 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Copyright 2000 by Carsten Paeth <calle@calle.de>
+  *
+@@ -25,6 +25,7 @@
+ #include <linux/major.h>
+ #include <linux/slab.h>
+ #include <linux/ctype.h>
++#include <linux/isdn_compat.h>
+ #include <asm/bitops.h>
+ #include <asm/uaccess.h>
+@@ -32,7 +33,7 @@
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.22 $";
+ struct capifs_ncci {
+       struct inode *inode;
+@@ -69,14 +70,21 @@
+ static int capifs_root_readdir(struct file *,void *,filldir_t);
+ static struct dentry *capifs_root_lookup(struct inode *,struct dentry *);
+ static int capifs_revalidate(struct dentry *, int);
++#ifdef COMPAT_VFS_2_4
+ static struct inode *capifs_new_inode(struct super_block *sb);
++#endif
+ static struct file_operations capifs_root_operations = {
++#ifdef COMPAT_VFS_2_4
+       read:           generic_read_dir,
++#endif
+       readdir:        capifs_root_readdir,
+ };
+ struct inode_operations capifs_root_inode_operations = {
++#ifndef COMPAT_VFS_2_4
++      default_file_ops: &capifs_root_operations, /* file operations */
++#endif
+       lookup: capifs_root_lookup,
+ };
+@@ -101,12 +109,20 @@
+       switch(nr)
+       {
+       case 0:
++#ifdef COMPAT_VFS_2_4
+               if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
++#else
++              if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
++#endif
+                       return 0;
+               filp->f_pos = ++nr;
+               /* fall through */
+       case 1:
++#ifdef COMPAT_VFS_2_4
+               if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
++#else
++              if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
++#endif
+                       return 0;
+               filp->f_pos = ++nr;
+               /* fall through */
+@@ -118,7 +134,11 @@
+                               char *p = numbuf;
+                               if (np->type) *p++ = np->type;
+                               sprintf(p, "%u", np->num);
++#ifdef COMPAT_VFS_2_4
+                               if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_UNKNOWN) < 0 )
++#else
++                              if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
++#endif
+                                       return 0;
+                       }
+                       filp->f_pos = ++nr;
+@@ -180,7 +200,7 @@
+       dentry->d_inode = np->inode;
+       if ( dentry->d_inode )
+-              atomic_inc(&dentry->d_inode->i_count);
++              i_count_inc(dentry->d_inode->i_count);
+       
+       d_add(dentry, dentry->d_inode);
+@@ -199,9 +219,9 @@
+       for ( i = 0 ; i < sbi->max_ncci ; i++ ) {
+               if ( (inode = sbi->nccis[i].inode) ) {
+-                      if (atomic_read(&inode->i_count) != 1 )
++                      if (i_count_read(inode->i_count) != 1 )
+                               printk("capifs_put_super: badness: entry %d count %d\n",
+-                                     i, (unsigned)atomic_read(&inode->i_count));
++                                     i, (unsigned)i_count_read(inode->i_count));
+                       inode->i_nlink--;
+                       iput(inode);
+               }
+@@ -213,11 +233,24 @@
+       kfree(sbi->nccis);
+       kfree(sbi);
++#ifndef COMPAT_VFS_2_4
++      MOD_DEC_USE_COUNT;
++#endif
+ }
++#ifdef COMPAT_VFS_2_4
+ static int capifs_statfs(struct super_block *sb, struct statfs *buf);
++#else
++static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
++static void capifs_write_inode(struct inode *inode) { };
++static void capifs_read_inode(struct inode *inode);
++#endif
+ static struct super_operations capifs_sops = {
++#ifndef COMPAT_VFS_2_4
++      read_inode:     capifs_read_inode,
++      write_inode:    capifs_write_inode,
++#endif
+       put_super:      capifs_put_super,
+       statfs:         capifs_statfs,
+ };
+@@ -288,6 +321,10 @@
+       struct dentry * root;
+       struct capifs_sb_info *sbi;
++#ifndef COMPAT_VFS_2_4
++      MOD_INC_USE_COUNT;
++      lock_super(s);
++#endif
+       /* Super block already completed? */
+       if (s->s_root)
+               goto out;
+@@ -322,6 +359,7 @@
+       /*
+        * Get the root inode and dentry, but defer checking for errors.
+        */
++#ifdef COMPAT_VFS_2_4
+       root_inode = capifs_new_inode(s);
+       if (root_inode) {
+               root_inode->i_ino = 1;
+@@ -331,6 +369,10 @@
+               root_inode->i_nlink = 2;
+       } 
+       root = d_alloc_root(root_inode);
++#else
++      root_inode = iget(s, 1); /* inode 1 == root directory */
++      root = d_alloc_root(root_inode, NULL);
++#endif
+       /*
+        * Check whether somebody else completed the super block.
+@@ -370,11 +412,34 @@
+       mounts = s;
+ out:  /* Success ... somebody else completed the super block for us. */ 
++#ifndef COMPAT_VFS_2_4
++      unlock_super(s);
++#endif
+       return s;
+ fail:
++#ifndef COMPAT_VFS_2_4
++      unlock_super(s);
++      MOD_DEC_USE_COUNT;
++#endif
+       return NULL;
+ }
++#ifndef COMPAT_VFS_2_4
++static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
++{
++      struct statfs tmp;
++
++      tmp.f_type = CAPIFS_SUPER_MAGIC;
++      tmp.f_bsize = 1024;
++      tmp.f_blocks = 0;
++      tmp.f_bfree = 0;
++      tmp.f_bavail = 0;
++      tmp.f_files = 0;
++      tmp.f_ffree = 0;
++      tmp.f_namelen = NAME_MAX;
++      return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
++}
++#else
+ static int capifs_statfs(struct super_block *sb, struct statfs *buf)
+ {
+       buf->f_type = CAPIFS_SUPER_MAGIC;
+@@ -387,7 +452,9 @@
+       buf->f_namelen = NAME_MAX;
+       return 0;
+ }
++#endif
++#ifdef COMPAT_VFS_2_4
+ static struct inode *capifs_new_inode(struct super_block *sb)
+ {
+       struct inode *inode = new_inode(sb);
+@@ -399,8 +466,51 @@
+       }
+       return inode;
+ }
++#else
++static void capifs_read_inode(struct inode *inode)
++{
++      ino_t ino = inode->i_ino;
++      struct capifs_sb_info *sbi = SBI(inode->i_sb);
++
++      inode->i_mode = 0;
++      inode->i_nlink = 0;
++      inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
++      inode->i_blocks = 0;
++      inode->i_blksize = 1024;
++      inode->i_uid = inode->i_gid = 0;
++
++      if ( ino == 1 ) {
++              inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
++              inode->i_op = &capifs_root_inode_operations;
++              inode->i_nlink = 2;
++              return;
++      } 
++      ino -= 2;
++      if ( ino >= sbi->max_ncci )
++              return;         /* Bogus */
++      
++#ifdef COMPAT_VFS_2_4
++      init_special_inode(inode, S_IFCHR, 0);
++#else
++      inode->i_mode = S_IFCHR;
++      inode->i_op = &chrdev_inode_operations;
++#endif
++
++      return;
++}
++#endif
++
++#ifndef COMPAT_VFS_2_4
++static struct file_system_type capifs_fs_type = {
++      "capifs",
++      0,
++      capifs_read_super,
++      NULL
++};
++#else
+ static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
++#endif
+ void capifs_new_ncci(char type, unsigned int num, kdev_t device)
+ {
+@@ -421,16 +531,26 @@
+                               break;
+                       }
+               }
++#ifdef COMPAT_VFS_2_4
+               if ( ino >= sbi->max_ncci )
+                       continue;
+               if ((np->inode = capifs_new_inode(sb)) != NULL) {
++#else
++              if ((np->inode = iget(sb, ino+2)) != NULL) {
++#endif
+                       struct inode *inode = np->inode;
+                       inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
+                       inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
++#ifdef COMPAT_VFS_2_4
+                       inode->i_nlink = 1;
+                       inode->i_ino = ino + 2;
+                       init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
++#else
++                      inode->i_mode = sbi->mode | S_IFCHR;
++                      inode->i_rdev = np->kdev;
++                      inode->i_nlink++;
++#endif
+               }
+       }
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capifs.h linux-2.4.29/drivers/isdn/avmb1/capifs.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capifs.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capifs.h   2005-03-22 15:06:44.965257024 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capifs.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capifs.h,v 1.4 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Copyright 2000 by Carsten Paeth <calle@calle.de>
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capilli.h linux-2.4.29/drivers/isdn/avmb1/capilli.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capilli.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capilli.h  2005-03-22 15:06:44.980254744 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capilli.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capilli.h,v 1.5 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Kernel CAPI 2.0 Driver Interface for Linux
+  * 
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capiutil.c linux-2.4.29/drivers/isdn/avmb1/capiutil.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/capiutil.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capiutil.c 2005-03-22 15:06:44.997252160 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capiutil.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capiutil.c,v 1.16 2001/09/24 13:22:44 kai Exp $
+  *
+  * CAPI 2.0 convert capi message to capi message struct
+  *
+@@ -19,6 +19,7 @@
+ #include <linux/init.h>
+ #include <asm/segment.h>
+ #include <linux/config.h>
++#include <linux/isdn_compat.h>
+ #include "capiutil.h"
+ MODULE_DESCRIPTION("CAPI4Linux: CAPI message conversion support");
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/capiutil.h linux-2.4.29/drivers/isdn/avmb1/capiutil.h
+--- linux-2.4.29.old/drivers/isdn/avmb1/capiutil.h     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/capiutil.h 2005-03-22 15:06:45.040245624 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capiutil.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: capiutil.h,v 1.7 2001/09/24 13:22:44 kai Exp $
+  *
+  * CAPI 2.0 defines & types
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/kcapi.c linux-2.4.29/drivers/isdn/avmb1/kcapi.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/kcapi.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/kcapi.c    2005-03-22 15:06:45.062242280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: kcapi.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: kcapi.c,v 1.28 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Kernel CAPI 2.0 Module
+  * 
+@@ -21,6 +21,7 @@
+ #include <linux/proc_fs.h>
+ #include <linux/skbuff.h>
+ #include <linux/tqueue.h>
++#include <linux/isdn_compat.h>
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/locks.h>
+@@ -33,7 +34,7 @@
+ #include <linux/b1lli.h>
+ #endif
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.28 $";
+ /* ------------------------------------------------------------- */
+@@ -64,7 +65,6 @@
+       __u32 ncci;
+       __u32 winsize;
+       int   nmsg;
+-        spinlock_t lock;
+       struct msgidqueue *msgidqueue;
+       struct msgidqueue *msgidlast;
+       struct msgidqueue *msgidfree;
+@@ -104,14 +104,14 @@
+ #define APPL(a)                  (&applications[(a)-1])
+ #define       VALID_APPLID(a)    ((a) && (a) <= CAPI_MAXAPPL && APPL(a)->applid == a)
+ #define APPL_IS_FREE(a)    (APPL(a)->applid == 0)
+-#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0)
+-#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0)
++#define APPL_MARK_FREE(a)  do{ APPL(a)->applid=0; MOD_DEC_USE_COUNT; }while(0);
++#define APPL_MARK_USED(a)  do{ APPL(a)->applid=(a); MOD_INC_USE_COUNT; }while(0);
+ #define NCCI2CTRL(ncci)    (((ncci) >> 24) & 0x7f)
+ #define VALID_CARD(c)    ((c) > 0 && (c) <= CAPI_MAXCONTR)
+ #define CARD(c)                  (&cards[(c)-1])
+-#define CARDNR(cp)       ((((cp)-cards)+1) & 0xff)
++#define CARDNR(cp)       (((cp)-cards)+1)
+ static struct capi_appl applications[CAPI_MAXAPPL];
+ static struct capi_ctr cards[CAPI_MAXCONTR];
+@@ -535,9 +535,13 @@
+        * of devices. Devices can only removed in
+        * user process, not in bh.
+        */
++#ifdef COMPAT_HAS_SCHEDULE_TASK
+       MOD_INC_USE_COUNT;
+       if (schedule_task(&tq_state_notify) == 0)
+               MOD_DEC_USE_COUNT;
++#else
++      queue_task(&tq_state_notify, &tq_scheduler);
++#endif
+       return 0;
+ }
+@@ -546,13 +550,7 @@
+ static void notify_up(__u32 contr)
+ {
+       struct capi_interface_user *p;
+-      __u16 appl;
+-      for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
+-              if (!VALID_APPLID(appl)) continue;
+-              if (APPL(appl)->releasing) continue;
+-              CARD(contr)->driver->register_appl(CARD(contr), appl, &APPL(appl)->rparam);
+-      }
+         printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
+       spin_lock(&capi_users_lock);
+       for (p = capi_users; p; p = p->next) {
+@@ -639,7 +637,9 @@
+               kfree(np);
+               MOD_DEC_USE_COUNT;
+       }
++#ifdef COMPAT_HAS_SCHEDULE_TASK
+       MOD_DEC_USE_COUNT;
++#endif
+ }
+       
+ /* -------- NCCI Handling ------------------------------------- */
+@@ -647,7 +647,6 @@
+ static inline void mq_init(struct capi_ncci * np)
+ {
+       int i;
+-        np->lock = SPIN_LOCK_UNLOCKED;
+       np->msgidqueue = 0;
+       np->msgidlast = 0;
+       np->nmsg = 0;
+@@ -662,11 +661,8 @@
+ static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid)
+ {
+       struct msgidqueue *mq;
+-      spin_lock_bh(&np->lock);
+-      if ((mq = np->msgidfree) == 0) {
+-              spin_unlock_bh(&np->lock);
++      if ((mq = np->msgidfree) == 0)
+               return 0;
+-      }
+       np->msgidfree = mq->next;
+       mq->msgid = msgid;
+       mq->next = 0;
+@@ -676,14 +672,12 @@
+       if (!np->msgidqueue)
+               np->msgidqueue = mq;
+       np->nmsg++;
+-      spin_unlock_bh(&np->lock);
+       return 1;
+ }
+ static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid)
+ {
+       struct msgidqueue **pp;
+-      spin_lock_bh(&np->lock);
+       for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) {
+               if ((*pp)->msgid == msgid) {
+                       struct msgidqueue *mq = *pp;
+@@ -693,11 +687,9 @@
+                       mq->next = np->msgidfree;
+                       np->msgidfree = mq;
+                       np->nmsg--;
+-                      spin_unlock_bh(&np->lock);
+                       return 1;
+               }
+       }
+-      spin_unlock_bh(&np->lock);
+       return 0;
+ }
+@@ -720,16 +712,12 @@
+                       nextpp = &(*pp)->next;
+               }
+       }
+-      if (APPL(appl)->releasing) { /* only release if the application was marked for release */
+-              printk(KERN_DEBUG "kcapi: appl %d releasing(%d)\n", appl, APPL(appl)->releasing);
+-              APPL(appl)->releasing--;
+-              if (APPL(appl)->releasing <= 0) {
+-                      APPL(appl)->signal = 0;
+-                      APPL_MARK_FREE(appl);
+-                      printk(KERN_INFO "kcapi: appl %d down\n", appl);
+-              }
+-      } else
+-              printk(KERN_WARNING "kcapi: appl %d card%d released without request\n", appl, card->cnr);
++      APPL(appl)->releasing--;
++      if (APPL(appl)->releasing <= 0) {
++              APPL(appl)->signal = 0;
++              APPL_MARK_FREE(appl);
++              printk(KERN_INFO "kcapi: appl %d down\n", appl);
++      }
+ }
+ /*
+  * ncci management
+@@ -882,7 +870,16 @@
+ static void controllercb_ready(struct capi_ctr * card)
+ {
++      __u16 appl;
++
+       card->cardstate = CARD_RUNNING;
++
++      for (appl = 1; appl <= CAPI_MAXAPPL; appl++) {
++              if (!VALID_APPLID(appl)) continue;
++              if (APPL(appl)->releasing) continue;
++              card->driver->register_appl(card, appl, &APPL(appl)->rparam);
++      }
++
+         printk(KERN_NOTICE "kcapi: card %d \"%s\" ready.\n",
+               CARDNR(card), card->name);
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/t1isa.c linux-2.4.29/drivers/isdn/avmb1/t1isa.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/t1isa.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/t1isa.c    2005-03-22 15:06:45.078239848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: t1isa.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: t1isa.c,v 1.22 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Module for AVM T1 HEMA-card.
+  * 
+@@ -19,13 +19,14 @@
+ #include <linux/capi.h>
+ #include <linux/kernelcapi.h>
+ #include <linux/init.h>
++#include <linux/isdn_compat.h>
+ #include <asm/io.h>
+ #include "capicmd.h"
+ #include "capiutil.h"
+ #include "capilli.h"
+ #include "avmcard.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.22 $";
+ /* ------------------------------------------------------------- */
+diff -rNu linux-2.4.29.old/drivers/isdn/avmb1/t1pci.c linux-2.4.29/drivers/isdn/avmb1/t1pci.c
+--- linux-2.4.29.old/drivers/isdn/avmb1/t1pci.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/avmb1/t1pci.c    2005-03-22 15:06:45.094237416 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: t1pci.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: t1pci.c,v 1.25 2001/09/24 13:22:44 kai Exp $
+  * 
+  * Module for AVM T1 PCI-card.
+  * 
+@@ -18,6 +18,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/ioport.h>
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/capi.h>
+ #include <linux/init.h>
+ #include <asm/io.h>
+@@ -26,19 +27,21 @@
+ #include "capilli.h"
+ #include "avmcard.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision: 1.25 $";
+ #undef CONFIG_T1PCI_DEBUG
+ #undef CONFIG_T1PCI_POLLDEBUG
+ /* ------------------------------------------------------------- */
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id t1pci_pci_tbl[] __initdata = {
+       { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
+       { }                             /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card");
+ MODULE_AUTHOR("Carsten Paeth");
+ MODULE_LICENSE("GPL");
+@@ -264,9 +267,9 @@
+               }
+               pci_set_master(dev);
+-              param.port = pci_resource_start(dev, 1);
++              param.port = pci_resource_start_io(dev, 1);
+               param.irq = dev->irq;
+-              param.membase = pci_resource_start(dev, 0);
++              param.membase = pci_resource_start_mem(dev, 0);
+               printk(KERN_INFO
+                       "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
+diff -rNu linux-2.4.29.old/drivers/isdn/divert/divert_procfs.c linux-2.4.29/drivers/isdn/divert/divert_procfs.c
+--- linux-2.4.29.old/drivers/isdn/divert/divert_procfs.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/divert/divert_procfs.c   2005-03-22 15:06:45.158227688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: divert_procfs.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * Filesystem handling for the diversion supplementary services.
+  *
+@@ -14,13 +14,16 @@
+ #include <linux/module.h>
+ #include <linux/version.h>
+ #include <linux/poll.h>
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ #include <linux/smp_lock.h>
++#endif
+ #ifdef CONFIG_PROC_FS
+ #include <linux/proc_fs.h>
+ #else
+ #include <linux/fs.h>
+ #endif
+ #include <linux/isdnif.h>
++#include <linux/isdn_compat.h>
+ #include "isdn_divert.h"
+ /*********************************/
+@@ -80,7 +83,6 @@
+ isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off)
+ {
+       struct divert_info *inf;
+-      loff_t pos = *off;
+       int len;
+       if (!*((struct divert_info **) file->private_data)) {
+@@ -92,11 +94,11 @@
+               return (0);
+       inf->usage_cnt--;       /* new usage count */
+-      file->private_data = &inf->next;        /* next structure */
++      (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;
+-              *off = pos + len;
++              file->f_pos += len;
+               return (len);
+       }
+       return (0);
+@@ -136,17 +138,23 @@
+ {
+       unsigned long flags;
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_INC_USE_COUNT;
++#else
+       lock_kernel();
++#endif
+       save_flags(flags);
+       cli();
+       if_used++;
+       if (divert_info_head)
+-              filep->private_data = &(divert_info_tail->next);
++              (struct divert_info **) filep->private_data = &(divert_info_tail->next);
+       else
+-              filep->private_data = &divert_info_head;
++              (struct divert_info **) filep->private_data = &divert_info_head;
+       restore_flags(flags);
+       /*  start_divert(); */
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+       unlock_kernel();
++#endif
+       return (0);
+ }                             /* isdn_divert_open */
+@@ -159,7 +167,9 @@
+       struct divert_info *inf;
+       unsigned long flags;
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+       lock_kernel();
++#endif
+       save_flags(flags);
+       cli();
+       if_used--;
+@@ -175,7 +185,11 @@
+                       divert_info_head = divert_info_head->next;
+                       kfree(inf);
+               }
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_DEC_USE_COUNT;
++#else
+       unlock_kernel();
++#endif
+       return (0);
+ }                             /* isdn_divert_close */
+@@ -276,6 +290,9 @@
+       open:           isdn_divert_open,
+       release:        isdn_divert_close,                                      
+ };
++#ifdef COMPAT_NO_SOFTNET
++struct inode_operations divert_file_inode_operations;
++#endif
+ /****************************/
+ /* isdn subdir in /proc/net */
+@@ -302,8 +319,16 @@
+               remove_proc_entry("isdn", proc_net);
+               return (-1);
+       }
++#ifdef COMPAT_NO_SOFTNET
++      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;
++#else
+       isdn_divert_entry->proc_fops = &isdn_fops; 
++#ifdef COMPAT_HAS_FILEOP_OWNER
+       isdn_divert_entry->owner = THIS_MODULE; 
++#endif
++#endif  /* COMPAT_NO_SOFTNET */
+ #endif        /* CONFIG_PROC_FS */
+       return (0);
+diff -rNu linux-2.4.29.old/drivers/isdn/divert/isdn_divert.c linux-2.4.29/drivers/isdn/divert/isdn_divert.c
+--- linux-2.4.29.old/drivers/isdn/divert/isdn_divert.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/divert/isdn_divert.c     2005-03-22 15:06:45.173225408 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_divert.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * DSS1 main diversion supplementary handling for i4l.
+  *
+@@ -84,6 +84,9 @@
+        restore_flags(flags); 
+        break;
++     case NETWORK_DIAL:
++       divert_if.dial_net_name(cs->deflect_dest);  
++
+      case DEFLECT_AUTODEL:
+      default:
+        save_flags(flags);
+@@ -452,6 +455,7 @@
+          case DEFLECT_PROCEED:
+          case DEFLECT_REPORT:
+          case DEFLECT_REJECT:
++         case NETWORK_DIAL:
+            if (dv->rule.action == DEFLECT_PROCEED)
+           if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) 
+               return(0); /* no external deflection needed */  
+@@ -495,6 +499,11 @@
+            else
+              { cs->deflect_dest[0] = '\0';
+              retval = 4; /* only proceed */
++             if (cs->akt_state == NETWORK_DIAL) {
++               strcpy(cs->deflect_dest,dv->rule.to_nr);
++               cs->timer.expires = jiffies + 10;
++               retval = 0;
++             }
+              }  
+            sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
+                    cs->akt_state,
+@@ -739,6 +748,18 @@
+                       } 
++#if 0
++  sprintf(st, "0x%lx 0x%lx",ic->arg, ic->parm.dss1_io.ll_id);
++  p = st + strlen(st);
++  p1 = ic->parm.dss1_io.data;
++  i = ic->parm.dss1_io.datalen;
++  while ((i > 0) && (p - st < 530))
++   { p += sprintf(p," %02x",(*p1++) & 0xFF);
++     i--;
++   }
++  sprintf(p, "\n");
++  put_info_buffer(st);
++#endif
+                    break;
+  
+                  default:
+diff -rNu linux-2.4.29.old/drivers/isdn/divert/isdn_divert.h linux-2.4.29/drivers/isdn/divert/isdn_divert.h
+--- linux-2.4.29.old/drivers/isdn/divert/isdn_divert.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/divert/isdn_divert.h     2005-03-22 15:06:45.189222976 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_divert.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * Header for the diversion supplementary ioctl interface.
+  *
+@@ -36,9 +36,10 @@
+ #define DEFLECT_PROCEED   2  /* deflect when externally triggered */
+ #define DEFLECT_ALERT     3  /* alert and deflect after delay */ 
+ #define DEFLECT_REJECT    4  /* reject immediately */
+-#define DIVERT_ACTIVATE   5  /* diversion activate */
+-#define DIVERT_DEACTIVATE 6  /* diversion deactivate */
+-#define DIVERT_REPORT     7  /* interrogation result */ 
++#define NETWORK_DIAL      5  /* dial a network interface */
++#define DIVERT_ACTIVATE   16 /* diversion activate */
++#define DIVERT_DEACTIVATE 17 /* diversion deactivate */
++#define DIVERT_REPORT     18 /* interrogation result */ 
+ #define DEFLECT_AUTODEL 255  /* only for internal use */ 
+ #define DEFLECT_ALL_IDS   0xFFFFFFFF /* all drivers selected */
+@@ -60,6 +61,7 @@
+                        2 = report call, send proceed, wait max waittime secs
+                        3 = report call, alert and deflect after waittime 
+                        4 = report call, reject immediately  
++                       5 = dial net interface specified in to_nr  
+                        actions 1-2 only take place if interface is opened 
+                   */
+    u_char waittime; /* maximum wait time for proceeding */ 
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/Divas_mod.c linux-2.4.29/drivers/isdn/eicon/Divas_mod.c
+--- linux-2.4.29.old/drivers/isdn/eicon/Divas_mod.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/Divas_mod.c        2005-03-22 15:06:45.229216896 +0100
+@@ -20,6 +20,7 @@
+ #include "adapter.h"
+ #include "uxio.h"
++#include <linux/isdn_compat.h>
+ MODULE_DESCRIPTION("ISDN4Linux: Driver for Eicon Diva Server cards");
+ MODULE_AUTHOR("Armin Schindler");
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/common.c linux-2.4.29/drivers/isdn/eicon/common.c
+--- linux-2.4.29.old/drivers/isdn/eicon/common.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/common.c   2005-03-22 15:06:45.301205952 +0100
+@@ -808,9 +808,7 @@
+       
+       while(i--)
+       {
+-            if (card->state == DIA_RUNNING)
+-              DivaDoCardDpc(card);
+-            card++;
++              DivaDoCardDpc(card++);
+       }
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon.h linux-2.4.29/drivers/isdn/eicon/eicon.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon.h    2005-03-22 15:06:45.371195312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon.h,v 1.26 2001/09/24 13:22:47 kai Exp $
+  *
+  * ISDN low-level module for Eicon active ISDN-Cards.
+  *
+@@ -348,19 +348,19 @@
+ extern char *eicon_ctype_name[];
+-static inline void eicon_schedule_tx(eicon_card *card)
++extern __inline__ void eicon_schedule_tx(eicon_card *card)
+ {
+         queue_task(&card->snd_tq, &tq_immediate);
+         mark_bh(IMMEDIATE_BH);
+ }
+-static inline void eicon_schedule_rx(eicon_card *card)
++extern __inline__ void eicon_schedule_rx(eicon_card *card)
+ {
+         queue_task(&card->rcv_tq, &tq_immediate);
+         mark_bh(IMMEDIATE_BH);
+ }
+-static inline void eicon_schedule_ack(eicon_card *card)
++extern __inline__ void eicon_schedule_ack(eicon_card *card)
+ {
+         queue_task(&card->ack_tq, &tq_immediate);
+         mark_bh(IMMEDIATE_BH);
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_dsp.h linux-2.4.29/drivers/isdn/eicon/eicon_dsp.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_dsp.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_dsp.h        2005-03-22 15:06:45.386193032 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_dsp.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_dsp.h,v 1.8 2001/09/24 13:22:47 kai Exp $
+  *
+  * ISDN lowlevel-module for Eicon active cards.
+  * DSP definitions
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.c linux-2.4.29/drivers/isdn/eicon/eicon_idi.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_idi.c        2005-03-22 15:06:45.421187712 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_idi.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_idi.c,v 1.45 2001/11/07 22:35:48 kai Exp $
+  *
+  * ISDN lowlevel-module for Eicon active cards.
+  * IDI interface 
+@@ -25,7 +25,7 @@
+ #undef EICON_FULL_SERVICE_OKTETT
+-char *eicon_idi_revision = "$Revision: 1.1.4.1 $";
++char *eicon_idi_revision = "$Revision: 1.45 $";
+ eicon_manifbuf *manbuf;
+@@ -1583,6 +1583,37 @@
+               return;
+       }
++#if 0 
++      eicon_sff_dochead *doc = (eicon_sff_dochead *)skb->data;
++      eicon_sff_pagehead *page = (eicon_sff_pagehead *)skb->data + sizeof(eicon_sff_dochead);
++
++      printk(KERN_DEBUG"SFF: doc %d / page %d (skb : %d)\n", 
++              sizeof(eicon_sff_dochead), 
++              sizeof(eicon_sff_pagehead), skb->len);
++
++      if (skb->len >= sizeof(eicon_sff_dochead)) {
++              printk(KERN_DEBUG"SFF: id = 0x%x\n", doc->id);
++              printk(KERN_DEBUG"SFF: version = 0x%x\n", doc->version);
++              printk(KERN_DEBUG"SFF: reserved1 = 0x%x\n", doc->reserved1);
++              printk(KERN_DEBUG"SFF: userinfo = 0x%x\n", doc->userinfo);
++              printk(KERN_DEBUG"SFF: pagecount = 0x%x\n", doc->pagecount);
++              printk(KERN_DEBUG"SFF: off1pagehead = 0x%x\n", doc->off1pagehead);
++              printk(KERN_DEBUG"SFF: offnpagehead = 0x%x\n", doc->offnpagehead);
++              printk(KERN_DEBUG"SFF: offdocend = 0x%x\n", doc->offdocend);
++      }
++      if (skb->len >= (sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead))) {
++              printk(KERN_DEBUG"SFFp: id = 0x%x\n", page->pageheadid);
++              printk(KERN_DEBUG"SFFp: len = 0x%x\n", page->pageheadlen);
++              printk(KERN_DEBUG"SFFp: resvert = 0x%x\n", page->resvert);
++              printk(KERN_DEBUG"SFFp: reshoriz = 0x%x\n", page->reshoriz);
++              printk(KERN_DEBUG"SFFp: coding = 0x%x\n", page->coding);
++              printk(KERN_DEBUG"SFFp: reserved2 = 0x%x\n", page->reserved2);
++              printk(KERN_DEBUG"SFFp: linelength = 0x%x\n", page->linelength);
++              printk(KERN_DEBUG"SFFp: pagelength = 0x%x\n", page->pagelength);
++              printk(KERN_DEBUG"SFFp: offprevpage = 0x%x\n", page->offprevpage);
++              printk(KERN_DEBUG"SFFp: offnextpage = 0x%x\n", page->offnextpage);
++      }
++#endif
+       
+       if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) {
+@@ -2054,8 +2085,7 @@
+                               OutBuf.Len++;
+                       } else {
+                               *OutBuf.Next++ = 0;
+-                              *(__u16 *) OutBuf.Next = (__u16) LineBuf.Len;
+-                              OutBuf.Next += sizeof(__u16);
++                              *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len;
+                               OutBuf.Len += 3;
+                       }
+                       memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len);
+@@ -2385,6 +2415,12 @@
+                               } else {
+                                       if (chan->e.B2Id)
+                                               idi_do_req(ccard, chan, REMOVE, 1);
++#if 0
++                                      if (chan->e.D3Id) {
++                                              idi_do_req(ccard, chan, REMOVE, 0);
++                                              idi_do_req(ccard, chan, ASSIGN, 0);
++                                      }
++#endif
+                                       chan->statectrl &= ~WAITING_FOR_HANGUP;
+                                       chan->statectrl &= ~IN_HOLD;
+                                       if (chan->statectrl & HAVE_CONN_REQ) {
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.h linux-2.4.29/drivers/isdn/eicon/eicon_idi.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_idi.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_idi.h        2005-03-22 15:06:45.437185280 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_idi.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_idi.h,v 1.12 2001/09/24 13:22:47 kai Exp $
+  *
+  * ISDN lowlevel-module for the Eicon active cards.
+  * IDI-Interface
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_io.c linux-2.4.29/drivers/isdn/eicon/eicon_io.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_io.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_io.c 2005-03-22 15:06:45.453182848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_io.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_io.c,v 1.15 2001/09/24 13:22:47 kai Exp $
+  *
+  * ISDN low-level module for Eicon active ISDN-Cards.
+  * Code for communicating with hardware.
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.c linux-2.4.29/drivers/isdn/eicon/eicon_isa.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_isa.c        2005-03-22 15:06:45.469180416 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_isa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_isa.c,v 1.18 2001/11/07 22:35:48 kai Exp $
+  *
+  * ISDN low-level module for Eicon active ISDN-Cards.
+  * Hardware-specific code for old ISA cards.
+@@ -20,7 +20,7 @@
+ #define release_shmem release_region
+ #define request_shmem request_region
+-char *eicon_isa_revision = "$Revision: 1.1.4.1 $";
++char *eicon_isa_revision = "$Revision: 1.18 $";
+ #undef EICON_MCA_DEBUG
+@@ -38,8 +38,12 @@
+ static void
+ eicon_isa_release_shmem(eicon_isa_card *card) {
+       if (card->mvalid) {
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap(card->shmem);
+               release_mem_region(card->physmem, card->ramsize);
++#else
++              release_shmem((unsigned long)card->shmem, card->ramsize);
++#endif
+       }
+       card->mvalid = 0;
+ }
+@@ -94,12 +98,20 @@
+                        Mem, Id);
+               return -1;
+       }
++#ifdef COMPAT_HAS_ISA_IOREMAP
+       if (check_mem_region(Mem, RAMSIZE)) {
++#else
++      if (check_shmem(Mem, RAMSIZE)) {
++#endif
+               printk(KERN_WARNING "eicon_isa_boot: memory at 0x%x already in use.\n", Mem);
+               return -1;
+       }
++#ifdef COMPAT_HAS_ISA_IOREMAP
+       amem = (unsigned long) ioremap(Mem, RAMSIZE);
++#else
++      amem = (unsigned long) Mem;
++#endif
+         writew(0x55aa, amem + 0x402);
+         if (readw(amem + 0x402) != 0x55aa) primary = 0;
+       writew(0, amem + 0x402);
+@@ -109,12 +121,16 @@
+       if (primary) {
+               printk(KERN_INFO "Eicon: assuming pri card at 0x%x\n", Mem);
+               writeb(0, amem + 0x3ffe);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char *)amem);
++#endif
+               return EICON_CTYPE_ISAPRI;
+       } else {
+               printk(KERN_INFO "Eicon: assuming bri card at 0x%x\n", Mem);
+               writeb(0, amem + 0x400);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char *)amem);
++#endif
+               return EICON_CTYPE_ISABRI;
+       }
+       return -1;
+@@ -151,6 +167,7 @@
+       else
+               card->ramsize  = RAMSIZE;
++#ifdef COMPAT_HAS_ISA_IOREMAP
+       if (check_mem_region(card->physmem, card->ramsize)) {
+               printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n",
+                       card->physmem);
+@@ -159,6 +176,16 @@
+       }
+       request_mem_region(card->physmem, card->ramsize, "Eicon ISA ISDN");
+       card->shmem = (eicon_isa_shmem *) ioremap(card->physmem, card->ramsize);
++#else
++      /* Register shmem */
++      if (check_shmem((unsigned long)card->shmem, card->ramsize)) {
++              printk(KERN_WARNING "eicon_isa_boot: memory at 0x%lx already in use.\n",
++                      (unsigned long)card->shmem);
++              kfree(code);
++              return -EBUSY;
++      }
++      request_shmem((unsigned long)card->shmem, card->ramsize, "Eicon ISA ISDN");
++#endif
+ #ifdef EICON_MCA_DEBUG
+       printk(KERN_INFO "eicon_isa_boot: card->ramsize = %d.\n", card->ramsize);
+ #endif
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.h linux-2.4.29/drivers/isdn/eicon/eicon_isa.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_isa.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_isa.h        2005-03-22 15:06:45.485177984 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_isa.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_isa.h,v 1.11 2001/09/24 13:22:47 kai Exp $
+  *
+  * ISDN low-level module for Eicon active ISDN-Cards.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_mod.c linux-2.4.29/drivers/isdn/eicon/eicon_mod.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_mod.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_mod.c        2005-03-22 15:06:45.505174944 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_mod.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_mod.c,v 1.44 2001/11/20 09:48:25 armin Exp $
+  *
+  * ISDN lowlevel-module for Eicon active cards.
+  * 
+@@ -44,7 +44,7 @@
+ static eicon_card *cards = (eicon_card *) NULL;   /* glob. var , contains
+                                                      start of card-list   */
+-static char *eicon_revision = "$Revision: 1.1.4.1 $";
++static char *eicon_revision = "$Revision: 1.44 $";
+ extern char *eicon_pci_revision;
+ extern char *eicon_isa_revision;
+@@ -639,6 +639,18 @@
+ static int
+ if_writecmd(const u_char * buf, int len, int user, int id, int channel)
+ {
++#if 0
++      /* Not yet used */
++        eicon_card *card = eicon_findcard(id);
++
++        if (card) {
++                if (!card->flags & EICON_FLAGS_RUNNING)
++                        return (len);
++                return (len);
++        }
++        printk(KERN_ERR
++               "eicon: if_writecmd called with invalid driverId!\n");
++#endif
+         return (len);
+ }
+@@ -665,11 +677,8 @@
+                       else
+                               cnt = skb->len;
+-                      if (user) {
+-                              spin_unlock_irqrestore(&eicon_lock, flags);
++                      if (user)
+                               copy_to_user(p, skb->data, cnt);
+-                              spin_lock_irqsave(&eicon_lock, flags);
+-                      }
+                       else
+                               memcpy(p, skb->data, cnt);
+@@ -1459,6 +1468,7 @@
+ #ifndef MODULE
++#ifdef COMPAT_HAS_NEW_SETUP
+ static int __init
+ eicon_setup(char *line)
+ {
+@@ -1467,6 +1477,12 @@
+       char *str;
+       str = get_options(line, 4, ints);
++#else
++void
++eicon_setup(char *str, int *ints)
++{
++        int i, argc;
++#endif
+         argc = ints[0];
+         i = 1;
+@@ -1494,9 +1510,13 @@
+ #else
+       printk(KERN_INFO "Eicon ISDN active driver setup\n");
+ #endif
++#ifdef COMPAT_HAS_NEW_SETUP
+       return(1);
+ }
+ __setup("eicon=", eicon_setup);
++#else
++}
++#endif
+ #endif /* MODULE */
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.c linux-2.4.29/drivers/isdn/eicon/eicon_pci.c
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_pci.c        2005-03-22 15:06:45.522172360 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_pci.c,v 1.18 2001/09/24 13:22:47 kai Exp $
+  *
+  * ISDN low-level module for Eicon active ISDN-Cards.
+  * Hardware-specific code for PCI cards.
+@@ -24,7 +24,7 @@
+ #include "adapter.h"
+ #include "uxio.h"
+-char *eicon_pci_revision = "$Revision: 1.1.4.1 $";
++char *eicon_pci_revision = "$Revision: 1.18 $";
+ #if CONFIG_PCI                 /* intire stuff is only for PCI */
+ #ifdef CONFIG_ISDN_DRV_EICON_PCI
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.h linux-2.4.29/drivers/isdn/eicon/eicon_pci.h
+--- linux-2.4.29.old/drivers/isdn/eicon/eicon_pci.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/eicon_pci.h        2005-03-22 15:06:45.538169928 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: eicon_pci.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: eicon_pci.h,v 1.7 2001/09/24 13:22:47 kai Exp $
+  *
+  * ISDN low-level module for Eicon active ISDN-Cards (PCI part).
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/fourbri.c linux-2.4.29/drivers/isdn/eicon/fourbri.c
+--- linux-2.4.29.old/drivers/isdn/eicon/fourbri.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/fourbri.c  2005-03-22 15:06:45.553167648 +0100
+@@ -337,8 +337,7 @@
+ static int diva_server_4bri_start(card_t *card, byte *channels)
+ {
+       byte *ctl;
+-      byte *shared;
+-      int i;
++      byte *shared, i;
+       int adapter_num;
+       DPRINTF(("divas: start Diva Server 4BRI"));
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/kprintf.c linux-2.4.29/drivers/isdn/eicon/kprintf.c
+--- linux-2.4.29.old/drivers/isdn/eicon/kprintf.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/kprintf.c  2005-03-22 15:06:45.601160352 +0100
+@@ -18,6 +18,468 @@
+ #include "divalog.h"
+ #include "uxio.h"
++/*
++ * Implementation of printf and sprintf for kernel
++ */
++
++#define MAX_BUFF    (80)        /* limit size of temporary buffers */
++
++#define WRITE_CHAR(BUFFER, SIZE, C) \
++  if (--(SIZE) < 0) { (BUFFER)--; *(BUFFER) = '\0'; return; } *(BUFFER)++ = (C)
++
++
++/*
++ * convert a number to decimal ASCII
++ */
++
++static
++void    do_decimal( char            *temp,
++                    int             temp_len,
++                    unsigned int    value,
++                    char            *s)
++
++{
++    int     i;
++
++    temp[0] = '\0';
++
++    for (i = 1; i < temp_len; i++)
++    {
++        temp[i] = (char) ((value % 10) + (int) '0');
++        value /= 10;
++    }
++
++    for (i = (temp_len - 1); temp[i] == '0'; i--)
++    {
++        ;
++    }
++
++    if (i == 0)
++    {
++        i++;
++    }
++
++    while (i >= 0)
++    {
++        *s++ = temp[i--];
++    }
++
++    return;
++}
++
++/*
++ * convert a number to octal ASCII
++ */
++
++static
++void    do_octal(   char            *temp,
++                    unsigned int    value,
++                    char            *s)
++
++{
++    int     i;
++
++    temp[0] = '\0';
++
++    for (i = 1; i <= 11; i++)
++    {
++        temp[i] = (char) ((value & 07) + (int) '0');
++        value >>= 3;
++    }
++    temp[11] &= '3';
++
++    for (i = 11; temp[i] == '0'; i--)
++    {
++        ;
++    }
++
++    if (i == 0)
++    {
++        i++;
++    }
++
++    while (i >= 0)
++    {
++        *s++ = temp[i--];
++    }
++
++    return;
++}
++
++/*
++ * convert a number to hex ASCII
++ */
++
++static
++void    do_hex( char            *temp,
++                unsigned int    value,
++                char            *s)
++
++{
++    int     i;
++    static
++    char    *dec_to_hex = "0123456789abcdef";
++
++    temp[0] = '\0';
++
++    for (i = 1; i <= 8; i++)
++    {
++        temp[i] = dec_to_hex[value & 0x0f];
++        value >>= 4;
++    }
++
++    for (i = 8; temp[i] == '0'; i--)
++    {
++        ;
++    }
++
++    if (i == 0)
++    {
++        i++;
++    }
++
++    while (i >= 0)
++    {
++        *s++ = temp[i--];
++    }
++
++    return;
++}
++
++/*
++ * convert a buffer to ASCII HEX
++ */
++
++static
++void    do_buffer(  char    *buffer,
++                    int     length,
++                    char    *s)
++
++{
++    static
++    char    hex_char [] = "0123456789abcdef";
++    char    *b = buffer;
++    int     hex_byte;
++    int     nybble;
++
++    length = (length >= ((MAX_BUFF / 3) + 1)) ? (MAX_BUFF / 3) : length;
++
++    while (length)
++    {
++        hex_byte = (int) *b++;
++        nybble = (hex_byte >> 4) & 0xf;
++        *s++ = hex_char[nybble];
++        nybble = hex_byte & 0xf;
++        *s++ = hex_char[nybble];
++        *s++ = ' ';
++        length--;
++    }
++    *s = '\0';
++
++    return;
++}
++
++/*
++ * Body of sprintf function: behaves just like standard sprintf, except we
++ * have an extra argument (buffer size) which we use to ensure we don't
++ * overflow
++ */
++
++void    Divas_vsprintf(   char    *buffer,
++                    int     size,
++                    char    *fmt,
++                    va_list argptr)
++
++{
++    char        c;          /* single character buffer */
++    int         i;          /* handy scratch counter */
++    int         f;          /* format character (after %) */
++    char        *str;       /* pointer into string */
++    char        temp[20];   /* temp buffer used in printing numbers */
++    char        string[MAX_BUFF]; /* output from number conversion */
++    int         length;     /* length of string "str" */
++    char        fill;       /* fill character ' ' or '0' */
++    boolean_t   leftjust;   /* TRUE if left justified, else right justified */
++    int         fmax, fmin; /* field specifiers % MIN . MAX s */
++    int         leading;    /* number of leading/trailing fill characters */
++    char        sign;       /* set to '-' for negative decimals */
++    int         number;     /* numeric argument */
++
++    char        *buff_ptr;  /* pointer to user's buffer of hex data */
++    int         buff_len;   /* length of hex data */
++
++    /* make sure we have somthing to write into */
++
++    if ((!buffer) || (size <= 0))
++    {
++        return;
++    }
++
++    while (TRUE)
++    {
++        /* echo characters until end or '%' encountered */
++
++        while ((c = *fmt++) != '%')
++        {
++            if (!c)
++            {
++                *buffer = '\0';
++                return;
++            }
++            WRITE_CHAR(buffer, size, c);
++        }
++
++        /* echo %% as % */
++
++        if (*fmt == '%')
++        {
++            WRITE_CHAR(buffer, size, *fmt);
++            continue;
++        }
++
++        /* %- turns on left-justify */
++
++        if ((leftjust = (boolean_t) ((*fmt == '-') ? TRUE : FALSE)))
++        {
++            fmt++;
++        }
++
++        /* %0 turns on zero filling */
++
++        if (*fmt == '0')
++        {
++            fill = '0';
++        }
++        else
++        {
++            fill = ' ';
++        }
++
++        /* minium field width specifier for %d, u, x, c, s */
++
++        fmin = 0;
++
++        if (*fmt == '*')
++        {
++            fmin = va_arg(argptr, int);
++            fmt++;
++        }
++        else
++        {
++            while ('0' <= *fmt && *fmt <= '9')
++            {
++                fmin = (fmin * 10) + (*fmt++ - '0');
++            }
++        }
++
++        /* maximum string width specifier for %s */
++
++        fmax = 0;
++
++        if (*fmt == '.')
++        {
++            if (*(++fmt) == '*')
++            {
++                fmax = va_arg(argptr, int);
++                fmt++;
++            }
++            else
++            {
++                while ('0' <= *fmt && *fmt <= '9')
++                {
++                    fmax = (fmax * 10) + (*fmt++ - '0');
++                }
++            }
++        }
++
++        /* skip over 'l' option (ints are assumed same size as longs) */
++
++        if (*fmt == 'l')
++        {
++            fmt++;
++        }
++
++        /* get the format chacater */
++
++        if (!(f = *fmt++))
++        {
++            WRITE_CHAR(buffer, size, '%');
++            *buffer = '\0';
++            return;
++        }
++
++        sign = '\0';        /* sign == '-' for negative decimal */
++
++        str = string;
++
++        switch (f)
++        {
++        case 'c' :
++            string[0] = (char) va_arg(argptr, int);
++            string[1] = '\0';
++            fmax = 0;
++            fill = ' ';
++            break;
++
++        case 's' :
++            str = va_arg(argptr, char *);
++            fill = ' ';
++            break;
++
++        case 'D' :
++        case 'd' :
++            number = va_arg(argptr, int);
++            if (number < 0)
++            {
++                sign = '-';
++                number = -number;
++            }
++            do_decimal(temp, DIM(temp), (unsigned int) number, str);
++            fmax = 0;
++            break;
++
++        case 'U' :
++        case 'u' :
++            number = va_arg(argptr, int);
++            do_decimal(temp, DIM(temp), (unsigned int) number, str);
++            fmax = 0;
++            break;
++
++        case 'O' :
++        case 'o' :
++            number = va_arg(argptr, int);
++            do_octal(temp, (unsigned int) number, str);
++            fmax = 0;
++            break;
++
++        case 'X' :
++        case 'x' :
++            number = va_arg(argptr, int);
++            do_hex(temp, (unsigned int) number, str);
++            fmax = 0;
++            break;
++
++        case 'H' :
++        case 'h' :
++            buff_ptr = va_arg(argptr, char *);
++            buff_len = va_arg(argptr, int);
++            do_buffer(buff_ptr, buff_len, str);
++            fmax = 0;
++            break;
++
++        default :
++            WRITE_CHAR(buffer, size, ((char) f));
++            break;
++        }
++
++        /* get the length of the string */
++
++        length = 0;
++        while (str[length])
++        {
++            length++;
++        }
++
++        /* make sure we have fmax and fmin values that are O.K. */
++
++        if (fmin > DIM(string) || fmin < 0)
++        {
++            fmin = 0;
++        }
++
++        if (fmax > DIM(string) || fmax < 0)
++        {
++            fmax = 0;
++        }
++
++        /* figure out how many leading characters thare are */
++
++        leading = 0;
++
++        if (fmax || fmin)
++        {
++            if (fmax)
++            {
++                if (length > fmax)
++                {
++                    length = fmax;
++                }
++            }
++
++            if (fmin)
++            {
++                leading = fmin - length;
++            }
++
++            if (sign == '-')
++            {
++                leading--;
++            }
++        }
++
++        /* output sign now, if fill is numeric */
++
++        if (sign == '-' && fill == '0')
++        {
++            WRITE_CHAR(buffer, size, '-');
++        }
++
++        /* if right justified, output fill characters */
++
++        if (!leftjust)
++        {
++            for (i = 0; i < leading; i++)
++            {
++                WRITE_CHAR(buffer, size, fill);
++            }
++        }
++
++        /* output sign now, if fill is spaces */
++
++        if (sign == '-' && fill == ' ')
++        {
++            WRITE_CHAR(buffer, size, '-');
++        }
++
++        /* now the actual value */
++
++        for (i = 0; i < length; i++)
++        {
++            WRITE_CHAR(buffer, size, str[i]);
++        }
++
++        /* if left justified, fill out with the fill character */
++
++        if (leftjust)
++        {
++            for (i = 0; i < leading; i++)
++            {
++                WRITE_CHAR(buffer, size, fill);
++            }
++        }
++    }
++}
++
++/*
++ * sprintf for kernel
++ *
++ * call our vsprintf assuming user has a big buffer....
++ */
++
++void    DivasSprintf(char *buffer, char *fmt, ...)
++
++{
++    va_list     argptr;         /* pointer to additional args */
++
++    va_start(argptr, fmt);
++
++    Divas_vsprintf(buffer, 1024, fmt, argptr);
++
++    va_end(argptr);
++
++    return;
++}
++
+ void    DivasPrintf(char  *fmt, ...)
+ {
+@@ -40,7 +502,7 @@
+     /* call vsprintf to format the user's information */
+-    vsnprintf(log.buffer, DIM(log.buffer), fmt, argptr);
++    Divas_vsprintf(log.buffer, DIM(log.buffer), fmt, argptr);
+     va_end(argptr);
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/lincfg.c linux-2.4.29/drivers/isdn/eicon/lincfg.c
+--- linux-2.4.29.old/drivers/isdn/eicon/lincfg.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/lincfg.c   2005-03-22 15:06:45.620157464 +0100
+@@ -26,6 +26,9 @@
+ #include "uxio.h"
+ #include <linux/pci.h>
++#ifndef COMPAT_HAS_2_2_PCI
++#include <linux/pci_ids.h>
++#endif
+ #include <linux/kernel.h>
+ #include <linux/ioport.h>
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/linchr.c linux-2.4.29/drivers/isdn/eicon/linchr.c
+--- linux-2.4.29.old/drivers/isdn/eicon/linchr.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/linchr.c   2005-03-22 15:06:45.635155184 +0100
+@@ -154,17 +154,17 @@
+       klog_t *pHeadItem;
+       if (BufferSize < sizeof(klog_t))
++      {
++              printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
++                      BufferSize, sizeof(klog_t));
+               return -EIO;
++      }
+       pHeadItem = (klog_t *) DivasLogFifoRead();
+       if (pHeadItem)
+       {
+-              if(copy_to_user(pClientLogBuffer, pHeadItem, sizeof(klog_t)))
+-              {
+-                      kfree(pHeadItem);
+-                      return -EFAULT;
+-              }
++              memcpy(pClientLogBuffer, pHeadItem, sizeof(klog_t));
+               kfree(pHeadItem);
+               return sizeof(klog_t);
+       }
+diff -rNu linux-2.4.29.old/drivers/isdn/eicon/linio.c linux-2.4.29/drivers/isdn/eicon/linio.c
+--- linux-2.4.29.old/drivers/isdn/eicon/linio.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/eicon/linio.c    2005-03-22 15:06:45.651152752 +0100
+@@ -15,6 +15,7 @@
+ #include <linux/slab.h>
+ #include <linux/pci.h>
+ #include <linux/delay.h>
++#include <linux/isdn_compat.h>
+ #undef N_DATA
+ #include "uxio.h"
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/Makefile linux-2.4.29/drivers/isdn/hisax/Makefile
+--- linux-2.4.29.old/drivers/isdn/hisax/Makefile       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/Makefile   2005-03-22 15:06:45.819127216 +0100
+@@ -4,20 +4,17 @@
+ O_TARGET        := vmlinux-obj.o
+-# Define maximum number of cards
+-
+-EXTRA_CFLAGS      += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+-
+ # Objects that export symbols.
+-export-objs     := config.o hisax_isac.o isdnhdlc.o
++export-objs     := config.o fsm.o hisax_isac.o
+ # Multipart objects.
+ list-multi      := hisax.o hisax_st5481.o
+ hisax-objs      := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
+                    lmgr.o q931.o callc.o fsm.o cert.o
+-hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o
++hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o \
++                   st5481_hdlc.o
+ # Optional parts of multipart objects.
+ hisax-objs-$(CONFIG_HISAX_EURO) += l3dss1.o
+@@ -33,7 +30,7 @@
+ hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o
+ hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o
+-hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o
++hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
+ hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o
+@@ -44,6 +41,7 @@
+ hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o
+ hisax-objs-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o
+ hisax-objs-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o
++hisax-objs-$(CONFIG_HISAX_HFC_USB) += hfc_usbr.o
+ hisax-objs-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o
+ hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o
+@@ -51,7 +49,6 @@
+ hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o
+ hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o
+-hisax-objs-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o
+ #hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o
+ hisax-objs += $(sort $(hisax-objs-y))
+@@ -61,10 +58,9 @@
+ obj-$(CONFIG_ISDN_DRV_HISAX)          += hisax.o
+ obj-$(CONFIG_HISAX_SEDLBAUER_CS)      += sedlbauer_cs.o
+ obj-$(CONFIG_HISAX_ELSA_CS)           += elsa_cs.o
+-obj-$(CONFIG_HISAX_AVM_A1_CS)         += avma1_cs.o
+-obj-$(CONFIG_HISAX_ST5481)            += hisax_st5481.o isdnhdlc.o
+-obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_isac.o hisax_fcpcipnp.o
+-obj-$(CONFIG_USB_AUERISDN)            += isdnhdlc.o
++obj-$(CONFIG_HISAX_HFC_USB_CS)                += hfc_usb.o
++obj-$(CONFIG_HISAX_ST5481)            += hisax_st5481.o
++obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_fcpcipnp.o hisax_isac.o
+ CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
+ CFLAGS_cert.o := -DCERTIFICATION=$(CERT)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/amd7930.c linux-2.4.29/drivers/isdn/hisax/amd7930.c
+--- linux-2.4.29.old/drivers/isdn/hisax/amd7930.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/amd7930.c  2005-03-22 15:06:45.837124480 +0100
+@@ -0,0 +1,755 @@
++/* $Id: amd7930.c,v 1.8 2001/09/24 13:22:55 kai Exp $
++ *
++ * HiSax ISDN driver - chip specific routines for AMD 7930
++ *
++ * Author       Brent Baccala
++ * Copyright    by Brent Baccala <baccala@FreeSoft.org>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ *    - Existing ISDN HiSax driver provides all the smarts
++ *    - it compiles, runs, talks to an isolated phone switch, connects
++ *      to a Cisco, pings go through
++ *    - AMD 7930 support only (no DBRI yet)
++ *    - no US NI-1 support (may not work on US phone system - untested)
++ *    - periodic packet loss, apparently due to lost interrupts
++ *    - ISDN sometimes freezes, requiring reboot before it will work again
++ *
++ * The code is unreliable enough to be consider alpha
++ *
++ * This file is (c) under GNU General Public License
++ *
++ * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
++ * SparcStation 1+.  The chip provides microphone and speaker interfaces
++ * which provide mono-channel audio at 8K samples per second via either
++ * 8-bit A-law or 8-bit mu-law encoding.  Also, the chip features an
++ * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
++ * which performs basic D channel LAPD processing and provides raw
++ * B channel data.  The digital audio channel, the two ISDN B channels,
++ * and two 64 Kbps channels to the microprocessor are all interconnected
++ * via a multiplexer.
++ *
++ * This driver interfaces to the Linux HiSax ISDN driver, which performs
++ * all high-level Q.921 and Q.931 ISDN functions.  The file is not
++ * itself a hardware driver; rather it uses functions exported by
++ * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
++ * allowing the chip to be simultaneously used for both audio and ISDN data.
++ * The hardware driver does _no_ buffering, but provides several callbacks
++ * which are called during interrupt service and should therefore run quickly.
++ *
++ * D channel transmission is performed by passing the hardware driver the
++ * address and size of an skb's data area, then waiting for a callback
++ * to signal successful transmission of the packet.  A task is then
++ * queued to notify the HiSax driver that another packet may be transmitted.
++ *
++ * D channel reception is quite simple, mainly because of:
++ *   1) the slow speed of the D channel - 16 kbps, and
++ *   2) the presence of an 8- or 32-byte (depending on chip version) FIFO
++ *      to buffer the D channel data on the chip
++ * Worst case scenario of back-to-back packets with the 8 byte buffer
++ * at 16 kbps yields an service time of 4 ms - long enough to preclude
++ * the need for fancy buffering.  We queue a background task that copies
++ * data out of the receive buffer into an skb, and the hardware driver
++ * simply does nothing until we're done with the receive buffer and
++ * reset it for a new packet.
++ *
++ * B channel processing is more complex, because of:
++ *   1) the faster speed - 64 kbps,
++ *   2) the lack of any on-chip buffering (it interrupts for every byte), and
++ *   3) the lack of any chip support for HDLC encapsulation
++ *
++ * The HiSax driver can put each B channel into one of three modes -
++ * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
++ * and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
++ * L1_MODE_HDLC is the most common, used for almost all "pure" digital
++ * data sessions.  L1_MODE_TRANS is used for ISDN audio.
++ *
++ * HDLC B channel transmission is performed via a large buffer into
++ * which the skb is copied while performing HDLC bit-stuffing.  A CRC
++ * is computed and attached to the end of the buffer, which is then
++ * passed to the low-level routines for raw transmission.  Once
++ * transmission is complete, the hardware driver is set to enter HDLC
++ * idle by successive transmission of mark (all 1) bytes, waiting for
++ * the ISDN driver to prepare another packet for transmission and
++ * deliver it.
++ *
++ * HDLC B channel reception is performed via an X-byte ring buffer
++ * divided into N sections of X/N bytes each.  Defaults: X=256 bytes, N=4.
++ * As the hardware driver notifies us that each section is full, we
++ * hand it the next section and schedule a background task to peruse
++ * the received section, bit-by-bit, with an HDLC decoder.  As
++ * packets are detected, they are copied into a large buffer while
++ * decoding HDLC bit-stuffing.  The ending CRC is verified, and if
++ * it is correct, we alloc a new skb of the correct length (which we
++ * now know), copy the packet into it, and hand it to the upper layers.
++ * Optimization: for large packets, we hand the buffer (which also
++ * happens to be an skb) directly to the upper layer after an skb_trim,
++ * and alloc a new large buffer for future packets, thus avoiding a copy.
++ * Then we return to HDLC processing; state is saved between calls.
++ * 
++ */
++
++#define __NO_VERSION__
++#include "hisax.h"
++#include "../../sbus/audio/amd7930.h"
++#include "isac.h"
++#include "isdnl1.h"
++#include "rawhdlc.h"
++#include <linux/interrupt.h>
++
++static const char *amd7930_revision = "$Revision: 1.8 $";
++
++#define RCV_BUFSIZE   1024    /* Size of raw receive buffer in bytes */
++#define RCV_BUFBLKS   4       /* Number of blocks to divide buffer into
++                               * (must divide RCV_BUFSIZE) */
++
++static void Bchan_fill_fifo(struct BCState *, struct sk_buff *);
++
++static void
++Bchan_xmt_bh(struct BCState *bcs)
++{
++      struct sk_buff *skb;
++
++      if (bcs->hw.amd7930.tx_skb != NULL) {
++              dev_kfree_skb(bcs->hw.amd7930.tx_skb);
++              bcs->hw.amd7930.tx_skb = NULL;
++      }
++
++      if ((skb = skb_dequeue(&bcs->squeue))) {
++              Bchan_fill_fifo(bcs, skb);
++      } else {
++              clear_bit(BC_FLG_BUSY, &bcs->Flag);
++              bcs->event |= 1 << B_XMTBUFREADY;
++              queue_task(&bcs->tqueue, &tq_immediate);
++              mark_bh(IMMEDIATE_BH);
++      }
++}
++
++static void
++Bchan_xmit_callback(struct BCState *bcs)
++{
++      queue_task(&bcs->hw.amd7930.tq_xmt, &tq_immediate);
++      mark_bh(IMMEDIATE_BH);
++}
++
++/* B channel transmission: two modes (three, if you count L1_MODE_NULL)
++ *
++ * L1_MODE_HDLC - We need to do HDLC encapsulation before transmiting
++ * the packet (i.e. make_raw_hdlc_data).  Since this can be a
++ * time-consuming operation, our completion callback just schedules
++ * a bottom half to do encapsulation for the next packet.  In between,
++ * the link will just idle
++ *
++ * L1_MODE_TRANS - Data goes through, well, transparent.  No HDLC encap,
++ * and we can't just let the link idle, so the "bottom half" actually
++ * gets called during the top half (it's our callback routine in this case),
++ * but it's a lot faster now since we don't call make_raw_hdlc_data
++ */
++
++static void
++Bchan_fill_fifo(struct BCState *bcs, struct sk_buff *skb)
++{
++      struct IsdnCardState *cs = bcs->cs;
++      int len;
++
++      if ((cs->debug & L1_DEB_HSCX) || (cs->debug & L1_DEB_HSCX_FIFO)) {
++              char tmp[1024];
++              char *t = tmp;
++
++              t += sprintf(t, "amd7930_fill_fifo %c cnt %d",
++                           bcs->channel ? 'B' : 'A', skb->len);
++              if (cs->debug & L1_DEB_HSCX_FIFO)
++                      QuickHex(t, skb->data, skb->len);
++              debugl1(cs, tmp);
++      }
++
++      if (bcs->mode == L1_MODE_HDLC) {
++              len = make_raw_hdlc_data(skb->data, skb->len,
++                                       bcs->hw.amd7930.tx_buff, RAW_BUFMAX);
++              if (len > 0)
++                      amd7930_bxmit(0, bcs->channel,
++                                    bcs->hw.amd7930.tx_buff, len,
++                                    (void *) &Bchan_xmit_callback,
++                                    (void *) bcs);
++              dev_kfree_skb(skb);
++      } else if (bcs->mode == L1_MODE_TRANS) {
++              amd7930_bxmit(0, bcs->channel,
++                            bcs->hw.amd7930.tx_buff, skb->len,
++                            (void *) &Bchan_xmt_bh,
++                            (void *) bcs);
++              bcs->hw.amd7930.tx_skb = skb;
++      } else {
++              dev_kfree_skb(skb);
++      }
++}
++
++static void
++Bchan_mode(struct BCState *bcs, int mode, int bc)
++{
++      struct IsdnCardState *cs = bcs->cs;
++
++      if (cs->debug & L1_DEB_HSCX) {
++              char tmp[40];
++              sprintf(tmp, "AMD 7930 mode %d bchan %d/%d",
++                      mode, bc, bcs->channel);
++              debugl1(cs, tmp);
++      }
++      bcs->mode = mode;
++}
++
++/* Bchan_l2l1 is the entry point for upper layer routines that want to
++ * transmit on the B channel.  PH_DATA_REQ is a normal packet that
++ * we either start transmitting (if idle) or queue (if busy).
++ * PH_PULL_REQ can be called to request a callback message (PH_PULL_CNF)
++ * once the link is idle.  After a "pull" callback, the upper layer
++ * routines can use PH_PULL_IND to send data.
++ */
++
++static void
++Bchan_l2l1(struct PStack *st, int pr, void *arg)
++{
++      struct sk_buff *skb = arg;
++
++      switch (pr) {
++              case (PH_DATA_REQ):
++                      if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
++                              skb_queue_tail(&st->l1.bcs->squeue, skb);
++                      } else {
++                              test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
++                              Bchan_fill_fifo(st->l1.bcs, skb);
++                      }
++                      break;
++              case (PH_PULL_IND):
++                      if (test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
++                              printk(KERN_WARNING "amd7930: this shouldn't happen\n");
++                              break;
++                      }
++                      test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
++                      Bchan_fill_fifo(st->l1.bcs, skb);
++                      break;
++              case (PH_PULL_REQ):
++                      if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag)) {
++                              clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++                              st->l1.l1l2(st, PH_PULL_CNF, NULL);
++                      } else
++                              set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++                      break;
++      }
++}
++
++/* Receiver callback and bottom half - decodes HDLC at leisure (if
++ * L1_MODE_HDLC) and passes newly received skb on via bcs->rqueue.  If
++ * a large packet is received, stick rv_skb (the buffer that the
++ * packet has been decoded into) on the receive queue and alloc a new
++ * (large) skb to act as buffer for future receives.  If a small
++ * packet is received, leave rv_skb alone, alloc a new skb of the
++ * correct size, and copy the packet into it
++ */
++
++static void
++Bchan_recv_callback(struct BCState *bcs)
++{
++      struct amd7930_hw *hw = &bcs->hw.amd7930;
++
++      hw->rv_buff_in += RCV_BUFSIZE/RCV_BUFBLKS;
++      hw->rv_buff_in %= RCV_BUFSIZE;
++
++      if (hw->rv_buff_in != hw->rv_buff_out) {
++              amd7930_brecv(0, bcs->channel,
++                            hw->rv_buff + hw->rv_buff_in,
++                            RCV_BUFSIZE/RCV_BUFBLKS,
++                            (void *) &Bchan_recv_callback, (void *) bcs);
++      }
++
++      queue_task(&hw->tq_rcv, &tq_immediate);
++      mark_bh(IMMEDIATE_BH);
++}
++
++static void
++Bchan_rcv_bh(struct BCState *bcs)
++{
++      struct IsdnCardState *cs = bcs->cs;
++      struct amd7930_hw *hw = &bcs->hw.amd7930;
++      struct sk_buff *skb;
++      int len;
++
++      if (cs->debug & L1_DEB_HSCX) {
++              char tmp[1024];
++
++              sprintf(tmp, "amd7930_Bchan_rcv (%d/%d)",
++                      hw->rv_buff_in, hw->rv_buff_out);
++              debugl1(cs, tmp);
++              QuickHex(tmp, hw->rv_buff + hw->rv_buff_out,
++                       RCV_BUFSIZE/RCV_BUFBLKS);
++              debugl1(cs, tmp);
++      }
++
++      do {
++              if (bcs->mode == L1_MODE_HDLC) {
++                      while ((len = read_raw_hdlc_data(hw->hdlc_state,
++                                                       hw->rv_buff + hw->rv_buff_out, RCV_BUFSIZE/RCV_BUFBLKS,
++                                                       hw->rv_skb->tail, HSCX_BUFMAX))) {
++                              if (len > 0 && (cs->debug & L1_DEB_HSCX_FIFO)) {
++                                      char tmp[1024];
++                                      char *t = tmp;
++
++                                      t += sprintf(t, "amd7930_Bchan_rcv %c cnt %d", bcs->channel ? 'B' : 'A', len);
++                                      QuickHex(t, hw->rv_skb->tail, len);
++                                      debugl1(cs, tmp);
++                              }
++
++                              if (len > HSCX_BUFMAX/2) {
++                                      /* Large packet received */
++
++                                      if (!(skb = dev_alloc_skb(HSCX_BUFMAX))) {
++                                              printk(KERN_WARNING "amd7930: receive out of memory");
++                                      } else {
++                                              skb_put(hw->rv_skb, len);
++                                              skb_queue_tail(&bcs->rqueue, hw->rv_skb);
++                                              hw->rv_skb = skb;
++                                              bcs->event |= 1 << B_RCVBUFREADY;
++                                              queue_task(&bcs->tqueue, &tq_immediate);
++                                      }
++                              } else if (len > 0) {
++                                      /* Small packet received */
++
++                                      if (!(skb = dev_alloc_skb(len))) {
++                                              printk(KERN_WARNING "amd7930: receive out of memory\n");
++                                      } else {
++                                              memcpy(skb_put(skb, len), hw->rv_skb->tail, len);
++                                              skb_queue_tail(&bcs->rqueue, skb);
++                                              bcs->event |= 1 << B_RCVBUFREADY;
++                                              queue_task(&bcs->tqueue, &tq_immediate);
++                                              mark_bh(IMMEDIATE_BH);
++                                      }
++                              } else {
++                                      /* Reception Error */
++                                      /* printk("amd7930: B channel receive error\n"); */
++                              }
++                      }
++              } else if (bcs->mode == L1_MODE_TRANS) {
++                      if (!(skb = dev_alloc_skb(RCV_BUFSIZE/RCV_BUFBLKS))) {
++                              printk(KERN_WARNING "amd7930: receive out of memory\n");
++                      } else {
++                              memcpy(skb_put(skb, RCV_BUFSIZE/RCV_BUFBLKS),
++                                     hw->rv_buff + hw->rv_buff_out,
++                                     RCV_BUFSIZE/RCV_BUFBLKS);
++                              skb_queue_tail(&bcs->rqueue, skb);
++                              bcs->event |= 1 << B_RCVBUFREADY;
++                              queue_task(&bcs->tqueue, &tq_immediate);
++                              mark_bh(IMMEDIATE_BH);
++                      }
++              }
++
++              if (hw->rv_buff_in == hw->rv_buff_out) {
++                      /* Buffer was filled up - need to restart receiver */
++                      amd7930_brecv(0, bcs->channel,
++                                    hw->rv_buff + hw->rv_buff_in,
++                                    RCV_BUFSIZE/RCV_BUFBLKS,
++                                    (void *) &Bchan_recv_callback,
++                                    (void *) bcs);
++              }
++
++              hw->rv_buff_out += RCV_BUFSIZE/RCV_BUFBLKS;
++              hw->rv_buff_out %= RCV_BUFSIZE;
++
++      } while (hw->rv_buff_in != hw->rv_buff_out);
++}
++
++static void
++Bchan_close(struct BCState *bcs)
++{
++      struct sk_buff *skb;
++
++      Bchan_mode(bcs, 0, 0);
++      amd7930_bclose(0, bcs->channel);
++
++      if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
++              skb_queue_purge(&bcs->rqueue);
++              skb_queue_purge(&bcs->squeue);
++      }
++      test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
++}
++
++static int
++Bchan_open(struct BCState *bcs)
++{
++      struct amd7930_hw *hw = &bcs->hw.amd7930;
++
++      if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
++              skb_queue_head_init(&bcs->rqueue);
++              skb_queue_head_init(&bcs->squeue);
++      }
++      test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
++
++      amd7930_bopen(0, bcs->channel, 0xff);
++      hw->rv_buff_in = 0;
++      hw->rv_buff_out = 0;
++      hw->tx_skb = NULL;
++      init_hdlc_state(hw->hdlc_state, 0);
++      amd7930_brecv(0, bcs->channel,
++                    hw->rv_buff + hw->rv_buff_in, RCV_BUFSIZE/RCV_BUFBLKS,
++                    (void *) &Bchan_recv_callback, (void *) bcs);
++
++      bcs->event = 0;
++      bcs->tx_cnt = 0;
++      return (0);
++}
++
++static void
++Bchan_init(struct BCState *bcs)
++{
++      if (!(bcs->hw.amd7930.tx_buff = kmalloc(RAW_BUFMAX, GFP_ATOMIC))) {
++              printk(KERN_WARNING
++                     "HiSax: No memory for amd7930.tx_buff\n");
++              return;
++      }
++      if (!(bcs->hw.amd7930.rv_buff = kmalloc(RCV_BUFSIZE, GFP_ATOMIC))) {
++              printk(KERN_WARNING
++                     "HiSax: No memory for amd7930.rv_buff\n");
++              return;
++      }
++      if (!(bcs->hw.amd7930.rv_skb = dev_alloc_skb(HSCX_BUFMAX))) {
++              printk(KERN_WARNING
++                     "HiSax: No memory for amd7930.rv_skb\n");
++              return;
++      }
++      if (!(bcs->hw.amd7930.hdlc_state = kmalloc(sizeof(struct hdlc_state),
++                                                 GFP_ATOMIC))) {
++              printk(KERN_WARNING
++                     "HiSax: No memory for amd7930.hdlc_state\n");
++              return;
++      }
++
++      bcs->hw.amd7930.tq_rcv.sync = 0;
++      bcs->hw.amd7930.tq_rcv.routine = (void (*)(void *)) &Bchan_rcv_bh;
++      bcs->hw.amd7930.tq_rcv.data = (void *) bcs;
++
++      bcs->hw.amd7930.tq_xmt.sync = 0;
++      bcs->hw.amd7930.tq_xmt.routine = (void (*)(void *)) &Bchan_xmt_bh;
++      bcs->hw.amd7930.tq_xmt.data = (void *) bcs;
++}
++
++static void
++Bchan_manl1(struct PStack *st, int pr,
++        void *arg)
++{
++      switch (pr) {
++              case (PH_ACTIVATE_REQ):
++                      test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
++                      Bchan_mode(st->l1.bcs, st->l1.mode, st->l1.bc);
++                      st->l1.l1man(st, PH_ACTIVATE_CNF, NULL);
++                      break;
++              case (PH_DEACTIVATE_REQ):
++                      if (!test_bit(BC_FLG_BUSY, &st->l1.bcs->Flag))
++                              Bchan_mode(st->l1.bcs, 0, 0);
++                      test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
++                      break;
++      }
++}
++
++int
++setstack_amd7930(struct PStack *st, struct BCState *bcs)
++{
++      if (Bchan_open(bcs))
++              return (-1);
++      st->l1.bcs = bcs;
++      st->l2.l2l1 = Bchan_l2l1;
++      st->ma.manl1 = Bchan_manl1;
++      setstack_manager(st);
++      bcs->st = st;
++      return (0);
++}
++
++
++static void
++amd7930_drecv_callback(void *arg, int error, unsigned int count)
++{
++      struct IsdnCardState *cs = (struct IsdnCardState *) arg;
++      static struct tq_struct task;
++      struct sk_buff *skb;
++
++        /* NOTE: This function is called directly from an interrupt handler */
++
++      if (1) {
++              if (!(skb = alloc_skb(count, GFP_ATOMIC)))
++                      printk(KERN_WARNING "HiSax: D receive out of memory\n");
++              else {
++                      memcpy(skb_put(skb, count), cs->rcvbuf, count);
++                      skb_queue_tail(&cs->rq, skb);
++              }
++
++              task.routine = (void *) DChannel_proc_rcv;
++              task.data = (void *) cs;
++              queue_task(&task, &tq_immediate);
++              mark_bh(IMMEDIATE_BH);
++      }
++
++      if (cs->debug & L1_DEB_ISAC_FIFO) {
++              char tmp[128];
++              char *t = tmp;
++
++              t += sprintf(t, "amd7930 Drecv cnt %d", count);
++              if (error) t += sprintf(t, " ERR %x", error);
++              QuickHex(t, cs->rcvbuf, count);
++              debugl1(cs, tmp);
++      }
++
++      amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
++                    &amd7930_drecv_callback, cs);
++}
++
++static void
++amd7930_dxmit_callback(void *arg, int error)
++{
++      struct IsdnCardState *cs = (struct IsdnCardState *) arg;
++      static struct tq_struct task;
++
++        /* NOTE: This function is called directly from an interrupt handler */
++
++      /* may wish to do retransmission here, if error indicates collision */
++
++      if (cs->debug & L1_DEB_ISAC_FIFO) {
++              char tmp[128];
++              char *t = tmp;
++
++              t += sprintf(t, "amd7930 Dxmit cnt %d", cs->tx_skb->len);
++              if (error) t += sprintf(t, " ERR %x", error);
++              QuickHex(t, cs->tx_skb->data, cs->tx_skb->len);
++              debugl1(cs, tmp);
++      }
++
++      cs->tx_skb = NULL;
++
++      task.routine = (void *) DChannel_proc_xmt;
++      task.data = (void *) cs;
++      queue_task(&task, &tq_immediate);
++      mark_bh(IMMEDIATE_BH);
++}
++
++static void
++amd7930_Dchan_l2l1(struct PStack *st, int pr, void *arg)
++{
++      struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
++      struct sk_buff *skb = arg;
++      char str[64];
++
++      switch (pr) {
++              case (PH_DATA_REQ):
++                      if (cs->tx_skb) {
++                              skb_queue_tail(&cs->sq, skb);
++#ifdef L2FRAME_DEBUG          /* psa */
++                              if (cs->debug & L1_DEB_LAPD)
++                                      Logl2Frame(cs, skb, "PH_DATA Queued", 0);
++#endif
++                      } else {
++                              if ((cs->dlogflag) && (!(skb->data[2] & 1))) {
++                                      /* I-FRAME */
++                                      LogFrame(cs, skb->data, skb->len);
++                                      sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
++                                      dlogframe(cs, skb->data+4, skb->len-4,
++                                                str);
++                              }
++                              cs->tx_skb = skb;
++                              cs->tx_cnt = 0;
++#ifdef L2FRAME_DEBUG          /* psa */
++                              if (cs->debug & L1_DEB_LAPD)
++                                      Logl2Frame(cs, skb, "PH_DATA", 0);
++#endif
++                              amd7930_dxmit(0, skb->data, skb->len,
++                                            &amd7930_dxmit_callback, cs);
++                      }
++                      break;
++              case (PH_PULL_IND):
++                      if (cs->tx_skb) {
++                              if (cs->debug & L1_DEB_WARN)
++                                      debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
++                              skb_queue_tail(&cs->sq, skb);
++                              break;
++                      }
++                      if ((cs->dlogflag) && (!(skb->data[2] & 1))) {  /* I-FRAME */
++                              LogFrame(cs, skb->data, skb->len);
++                              sprintf(str, "Q.931 frame user->network tei %d", st->l2.tei);
++                              dlogframe(cs, skb->data + 4, skb->len - 4,
++                                        str);
++                      }
++                      cs->tx_skb = skb;
++                      cs->tx_cnt = 0;
++#ifdef L2FRAME_DEBUG          /* psa */
++                      if (cs->debug & L1_DEB_LAPD)
++                              Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
++#endif
++                      amd7930_dxmit(0, cs->tx_skb->data, cs->tx_skb->len,
++                                    &amd7930_dxmit_callback, cs);
++                      break;
++              case (PH_PULL_REQ):
++#ifdef L2FRAME_DEBUG          /* psa */
++                      if (cs->debug & L1_DEB_LAPD)
++                              debugl1(cs, "-> PH_REQUEST_PULL");
++#endif
++                      if (!cs->tx_skb) {
++                              test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++                              st->l1.l1l2(st, PH_PULL_CNF, NULL);
++                      } else
++                              test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
++                      break;
++      }
++}
++
++int
++setDstack_amd7930(struct PStack *st, struct IsdnCardState *cs)
++{
++      st->l2.l2l1 = amd7930_Dchan_l2l1;
++      if (! cs->rcvbuf) {
++              printk("setDstack_amd7930: No cs->rcvbuf!\n");
++      } else {
++              amd7930_drecv(0, cs->rcvbuf, MAX_DFRAME_LEN,
++                            &amd7930_drecv_callback, cs);
++      }
++      return (0);
++}
++
++static void
++manl1_msg(struct IsdnCardState *cs, int msg, void *arg) {
++      struct PStack *st;
++
++      st = cs->stlist;
++      while (st) {
++              st->ma.manl1(st, msg, arg);
++              st = st->next;
++      }
++}
++
++static void
++amd7930_new_ph(struct IsdnCardState *cs)
++{
++      switch (amd7930_get_liu_state(0)) {
++              case 3:
++                      manl1_msg(cs, PH_POWERUP_CNF, NULL);
++                        break;
++
++              case 7:
++                      manl1_msg(cs, PH_I4_P8_IND, NULL);
++                      break;
++
++              case 8:
++                      manl1_msg(cs, PH_RSYNC_IND, NULL);
++                      break;
++      }
++}
++
++/* amd7930 LIU state change callback */
++
++static void
++amd7930_liu_callback(struct IsdnCardState *cs)
++{
++      static struct tq_struct task;
++
++      if (!cs)
++              return;
++
++      if (cs->debug & L1_DEB_ISAC) {
++              char tmp[32];
++              sprintf(tmp, "amd7930_liu state %d", amd7930_get_liu_state(0));
++              debugl1(cs, tmp);
++      }
++
++      task.sync = 0;
++      task.routine = (void *) &amd7930_new_ph;
++      task.data = (void *) cs;
++      queue_task(&task, &tq_immediate);
++      mark_bh(IMMEDIATE_BH);
++}
++
++void
++amd7930_l1cmd(struct IsdnCardState *cs, int msg, void *arg)
++{
++      u_char val;
++      char tmp[32];
++      
++      if (cs->debug & L1_DEB_ISAC) {
++              char tmp[32];
++              sprintf(tmp, "amd7930_l1cmd msg %x", msg);
++              debugl1(cs, tmp);
++      }
++
++      switch(msg) {
++              case PH_RESET_REQ:
++                      if (amd7930_get_liu_state(0) <= 3)
++                              amd7930_liu_activate(0,0);
++                      else
++                              amd7930_liu_deactivate(0);
++                      break;
++              case PH_ENABLE_REQ:
++                      break;
++              case PH_INFO3_REQ:
++                      amd7930_liu_activate(0,0);
++                      break;
++              case PH_TESTLOOP_REQ:
++                      break;
++              default:
++                      if (cs->debug & L1_DEB_WARN) {
++                              sprintf(tmp, "amd7930_l1cmd unknown %4x", msg);
++                              debugl1(cs, tmp);
++                      }
++                      break;
++      }
++}
++
++static void init_amd7930(struct IsdnCardState *cs)
++{
++      Bchan_init(&cs->bcs[0]);
++      Bchan_init(&cs->bcs[1]);
++      cs->bcs[0].BC_SetStack = setstack_amd7930;
++      cs->bcs[1].BC_SetStack = setstack_amd7930;
++      cs->bcs[0].BC_Close = Bchan_close;
++      cs->bcs[1].BC_Close = Bchan_close;
++      Bchan_mode(cs->bcs, 0, 0);
++      Bchan_mode(cs->bcs + 1, 0, 0);
++}
++
++void
++release_amd7930(struct IsdnCardState *cs)
++{
++}
++
++static int
++amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg)
++{
++      switch (mt) {
++              case CARD_RESET:
++                      return(0);
++              case CARD_RELEASE:
++                      release_amd7930(cs);
++                      return(0);
++              case CARD_INIT:
++                      cs->l1cmd = amd7930_l1cmd;
++                      amd7930_liu_init(0, &amd7930_liu_callback, (void *)cs);
++                      init_amd7930(cs);
++                      return(0);
++              case CARD_TEST:
++                      return(0);
++      }
++      return(0);
++}
++
++int __init
++setup_amd7930(struct IsdnCard *card)
++{
++      struct IsdnCardState *cs = card->cs;
++      char tmp[64];
++
++      strcpy(tmp, amd7930_revision);
++      printk(KERN_INFO "HiSax: AMD7930 driver Rev. %s\n", HiSax_getrev(tmp));
++      if (cs->typ != ISDN_CTYPE_AMD7930)
++              return (0);
++
++        cs->irq = amd7930_get_irqnum(0);
++        if (cs->irq == 0)
++              return (0);
++
++      cs->cardmsg = &amd7930_card_msg;
++
++      return (1);
++}
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/arcofi.c linux-2.4.29/drivers/isdn/hisax/arcofi.c
+--- linux-2.4.29.old/drivers/isdn/hisax/arcofi.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/arcofi.c   2005-03-22 15:06:45.852122200 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: arcofi.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: arcofi.c,v 1.14 2001/09/24 13:22:55 kai Exp $
+  *
+  * Ansteuerung ARCOFI 2165
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/arcofi.h linux-2.4.29/drivers/isdn/hisax/arcofi.h
+--- linux-2.4.29.old/drivers/isdn/hisax/arcofi.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/arcofi.h   2005-03-22 15:06:45.872119160 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: arcofi.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * Ansteuerung ARCOFI 2165
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/asuscom.c linux-2.4.29/drivers/isdn/hisax/asuscom.c
+--- linux-2.4.29.old/drivers/isdn/hisax/asuscom.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/asuscom.c  2005-03-22 15:06:45.889116576 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: asuscom.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: asuscom.c,v 1.14 2001/09/24 13:22:55 kai Exp $
+  *
+  * low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
+  *
+@@ -14,7 +14,6 @@
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "isac.h"
+ #include "ipac.h"
+@@ -23,7 +22,7 @@
+ extern const char *CardType[];
+-const char *Asuscom_revision = "$Revision: 1.1.4.1 $";
++const char *Asuscom_revision = "$Revision: 1.14 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -310,27 +309,6 @@
+       return(0);
+ }
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id asus_ids[] __initdata = {
+-      { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688),
+-        ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1688), 
+-        (unsigned long) "Asus1688 PnP" },
+-      { ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690),
+-        ISAPNP_VENDOR('A', 'S', 'U'), ISAPNP_FUNCTION(0x1690), 
+-        (unsigned long) "Asus1690 PnP" },
+-      { ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020),
+-        ISAPNP_VENDOR('S', 'I', 'E'), ISAPNP_FUNCTION(0x0020), 
+-        (unsigned long) "Isurf2 PnP" },
+-      { ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000),
+-        ISAPNP_VENDOR('E', 'L', 'F'), ISAPNP_FUNCTION(0x0000), 
+-        (unsigned long) "Iscas TE320" },
+-      { 0, }
+-};
+-
+-static struct isapnp_device_id *adev = &asus_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_asuscom(struct IsdnCard *card)
+ {
+@@ -343,45 +321,7 @@
+       printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp));
+       if (cs->typ != ISDN_CTYPE_ASUSCOM)
+               return (0);
+-#ifdef __ISAPNP__
+-      if (!card->para[1] && isapnp_present()) {
+-              struct pci_bus *pb;
+-              struct pci_dev *pd;
+-
+-              while(adev->card_vendor) {
+-                      if ((pb = isapnp_find_card(adev->card_vendor,
+-                              adev->card_device, pnp_c))) {
+-                              pnp_c = pb;
+-                              pd = NULL;
+-                              if ((pd = isapnp_find_dev(pnp_c,
+-                                      adev->vendor, adev->function, pd))) {
+-                                      printk(KERN_INFO "HiSax: %s detected\n",
+-                                              (char *)adev->driver_data);
+-                                      pd->prepare(pd);
+-                                      pd->deactivate(pd);
+-                                      pd->activate(pd);
+-                                      card->para[1] = pd->resource[0].start;
+-                                      card->para[0] = pd->irq_resource[0].start;
+-                                      if (!card->para[0] || !card->para[1]) {
+-                                              printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n",
+-                                              card->para[0], card->para[1]);
+-                                              pd->deactivate(pd);
+-                                              return(0);
+-                                      }
+-                                      break;
+-                              } else {
+-                                      printk(KERN_ERR "AsusPnP: PnP error card found, no device\n");
+-                              }
+-                      }
+-                      adev++;
+-                      pnp_c=NULL;
+-              } 
+-              if (!adev->card_vendor) {
+-                      printk(KERN_INFO "AsusPnP: no ISAPnP card found\n");
+-                      return(0);
+-              }
+-      }
+-#endif
++
+       bytecnt = 8;
+       cs->hw.asus.cfg_reg = card->para[1];
+       cs->irq = card->para[0];
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/avm_a1.c linux-2.4.29/drivers/isdn/hisax/avm_a1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/avm_a1.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/avm_a1.c   2005-03-22 15:06:45.904114296 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_a1.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: avm_a1.c,v 2.15 2001/09/24 13:22:55 kai Exp $
+  *
+  * low level stuff for AVM A1 (Fritz) isdn cards
+  *
+@@ -18,7 +18,7 @@
+ #include "isdnl1.h"
+ extern const char *CardType[];
+-static const char *avm_revision = "$Revision: 1.1.4.1 $";
++static const char *avm_revision = "$Revision: 2.15 $";
+ #define        AVM_A1_STAT_ISAC       0x01
+ #define        AVM_A1_STAT_HSCX       0x02
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/avm_a1p.c linux-2.4.29/drivers/isdn/hisax/avm_a1p.c
+--- linux-2.4.29.old/drivers/isdn/hisax/avm_a1p.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/avm_a1p.c  2005-03-22 15:06:45.919112016 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_a1p.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: avm_a1p.c,v 2.9 2001/09/24 13:22:55 kai Exp $
+  *
+  * low level stuff for the following AVM cards:
+  * A1 PCMCIA
+@@ -57,7 +57,7 @@
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+-static const char *avm_revision = "$Revision: 1.1.4.1 $";
++static const char *avm_revision = "$Revision: 2.9 $";
+ static inline u_char
+ ReadISAC(struct IsdnCardState *cs, u_char offset)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/avm_pci.c linux-2.4.29/drivers/isdn/hisax/avm_pci.c
+--- linux-2.4.29.old/drivers/isdn/hisax/avm_pci.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/avm_pci.c  2005-03-22 15:06:45.945108064 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: avm_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: avm_pci.c,v 1.29 2001/09/24 13:22:55 kai Exp $
+  *
+  * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards
+  *
+@@ -19,11 +19,11 @@
+ #include "isac.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+ extern const char *CardType[];
+-static const char *avm_pci_rev = "$Revision: 1.1.4.1 $";
++static const char *avm_pci_rev = "$Revision: 1.29 $";
+ #define  AVM_FRITZ_PCI                1
+ #define  AVM_FRITZ_PNP                2
+@@ -291,8 +291,7 @@
+                       debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
+               return;
+       }
+-      p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+-      ptr = (u_int *)p;
++      ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+       bcs->hw.hdlc.rcvidx += count;
+       if (cs->subtyp == AVM_FRITZ_PCI) {
+               outl(idx, cs->hw.avm.cfg_reg + 4);
+@@ -353,8 +352,7 @@
+       }
+       if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
+               debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
+-      p = bcs->tx_skb->data;
+-      ptr = (u_int *)p;
++      ptr = (u_int *) p = bcs->tx_skb->data;
+       skb_pull(bcs->tx_skb, count);
+       bcs->tx_cnt -= count;
+       bcs->hw.hdlc.count += count;
+@@ -766,10 +764,6 @@
+ }
+ static struct pci_dev *dev_avm __initdata = NULL;
+-#ifdef __ISAPNP__
+-static struct pci_bus *bus_avm __initdata = NULL;
+-static struct pci_dev *pnp_avm __initdata = NULL;
+-#endif
+ int __init
+ setup_avm_pcipnp(struct IsdnCard *card)
+@@ -783,47 +777,10 @@
+       if (cs->typ != ISDN_CTYPE_FRITZPCI)
+               return (0);
+       if (card->para[1]) {
+-              /* old manual method */
+               cs->hw.avm.cfg_reg = card->para[1];
+               cs->irq = card->para[0];
+               cs->subtyp = AVM_FRITZ_PNP;
+       } else {
+-#ifdef __ISAPNP__
+-              if (isapnp_present()) {
+-                      struct pci_bus *ba;
+-                      if ((ba = isapnp_find_card(
+-                              ISAPNP_VENDOR('A', 'V', 'M'),
+-                              ISAPNP_FUNCTION(0x0900), bus_avm))) {
+-                              bus_avm = ba;
+-                              pnp_avm = NULL;
+-                              if ((pnp_avm = isapnp_find_dev(bus_avm,
+-                                      ISAPNP_VENDOR('A', 'V', 'M'),
+-                                      ISAPNP_FUNCTION(0x0900), pnp_avm))) {
+-                                      pnp_avm->prepare(pnp_avm);
+-                                      pnp_avm->deactivate(pnp_avm);
+-                                      pnp_avm->activate(pnp_avm);
+-                                      cs->hw.avm.cfg_reg =
+-                                              pnp_avm->resource[0].start;
+-                                      cs->irq = 
+-                                              pnp_avm->irq_resource[0].start;
+-                                      if (!cs->irq) {
+-                                              printk(KERN_ERR "FritzPnP:No IRQ\n");
+-                                              pnp_avm->deactivate(pnp_avm);
+-                                              return(0);
+-                                      }
+-                                      if (!cs->hw.avm.cfg_reg) {
+-                                              printk(KERN_ERR "FritzPnP:No IO address\n");
+-                                              pnp_avm->deactivate(pnp_avm);
+-                                              return(0);
+-                                      }
+-                                      cs->subtyp = AVM_FRITZ_PNP;
+-                                      goto ready;
+-                              }
+-                      }
+-              } else {
+-                      printk(KERN_INFO "FritzPnP: no ISA PnP present\n");
+-              }
+-#endif
+ #if CONFIG_PCI
+               if (!pci_present()) {
+                       printk(KERN_ERR "FritzPCI: no PCI bus present\n");
+@@ -838,7 +795,7 @@
+                       }
+                       if (pci_enable_device(dev_avm))
+                               return(0);
+-                      cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1);
++                      cs->hw.avm.cfg_reg = pci_resource_start_io(dev_avm, 1);
+                       if (!cs->hw.avm.cfg_reg) {
+                               printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n");
+                               return(0);
+@@ -854,7 +811,6 @@
+               return (0);
+ #endif /* CONFIG_PCI */
+       }
+-ready:
+       cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10;
+       if (check_region((cs->hw.avm.cfg_reg), 32)) {
+               printk(KERN_WARNING
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/bkm_a4t.c linux-2.4.29/drivers/isdn/hisax/bkm_a4t.c
+--- linux-2.4.29.old/drivers/isdn/hisax/bkm_a4t.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/bkm_a4t.c  2005-03-22 15:06:45.962105480 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: bkm_a4t.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: bkm_a4t.c,v 1.22 2001/09/24 13:22:55 kai Exp $
+  *
+  * low level stuff for T-Berkom A4T
+  *
+@@ -20,11 +20,12 @@
+ #include "jade.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include "bkm_ax.h"
+ extern const char *CardType[];
+-const char *bkm_a4t_revision = "$Revision: 1.1.4.1 $";
++const char *bkm_a4t_revision = "$Revision: 1.22 $";
+ static inline u_char
+@@ -293,13 +294,13 @@
+               u16 sub_sys;
+               u16 sub_vendor;
+-              sub_vendor = dev_a4t->subsystem_vendor;
+-              sub_sys = dev_a4t->subsystem_device;
++              pci_get_sub_vendor(dev_a4t,sub_vendor);
++              pci_get_sub_system(dev_a4t,sub_sys);
+               if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) {
+                       if (pci_enable_device(dev_a4t))
+                               return(0);
+                       found = 1;
+-                      pci_memaddr = pci_resource_start(dev_a4t, 0);
++                      pci_memaddr = pci_resource_start_mem(dev_a4t, 0);
+                       cs->irq = dev_a4t->irq;
+                       break;
+               }
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/bkm_a8.c linux-2.4.29/drivers/isdn/hisax/bkm_a8.c
+--- linux-2.4.29.old/drivers/isdn/hisax/bkm_a8.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/bkm_a8.c   2005-03-22 15:06:45.982102440 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: bkm_a8.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: bkm_a8.c,v 1.22 2001/09/24 13:22:55 kai Exp $
+  *
+  * low level stuff for Scitel Quadro (4*S0, passive)
+  *
+@@ -20,6 +20,7 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include "bkm_ax.h"
+ #if CONFIG_PCI
+@@ -28,7 +29,7 @@
+ extern const char *CardType[];
+-const char sct_quadro_revision[] = "$Revision: 1.1.4.1 $";
++const char sct_quadro_revision[] = "$Revision: 1.22 $";
+ static const char *sct_quadro_subtypes[] =
+ {
+@@ -329,13 +330,13 @@
+               while ((dev_a8 = pci_find_device(PCI_VENDOR_ID_PLX,
+                       PCI_DEVICE_ID_PLX_9050, dev_a8))) {
+                       
+-                      sub_vendor_id = dev_a8->subsystem_vendor;
+-                      sub_sys_id = dev_a8->subsystem_device;
++                      pci_get_sub_vendor(dev_a8,sub_vendor_id);
++                      pci_get_sub_system(dev_a8,sub_sys_id);
+                       if ((sub_sys_id == PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO) &&
+                               (sub_vendor_id == PCI_VENDOR_ID_BERKOM)) {
+                               if (pci_enable_device(dev_a8))
+                                       return(0);
+-                              pci_ioaddr1 = pci_resource_start(dev_a8, 1);
++                              pci_ioaddr1 = pci_resource_start_io(dev_a8, 1);
+                               pci_irq = dev_a8->irq;
+                               pci_bus = dev_a8->bus->number;
+                               pci_device_fn = dev_a8->devfn;
+@@ -365,7 +366,7 @@
+                       pci_ioaddr1 &= PCI_BASE_ADDRESS_IO_MASK;
+                       pcibios_write_config_dword(pci_bus, pci_device_fn,
+                               PCI_BASE_ADDRESS_1, pci_ioaddr1);
+-                      dev_a8->resource[ 1].start = pci_ioaddr1;
++                      get_pcibase(dev_a8, 1) = pci_ioaddr1;
+               }
+ #endif /* End HACK */
+       }
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/bkm_ax.h linux-2.4.29/drivers/isdn/hisax/bkm_ax.h
+--- linux-2.4.29.old/drivers/isdn/hisax/bkm_ax.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/bkm_ax.h   2005-03-22 15:06:46.010098184 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: bkm_ax.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * low level decls for T-Berkom cards A4T and Scitel Quadro (4*S0, passive)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/callc.c linux-2.4.29/drivers/isdn/hisax/callc.c
+--- linux-2.4.29.old/drivers/isdn/hisax/callc.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/callc.c    2005-03-22 15:06:46.027095600 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: callc.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: callc.c,v 2.59 2002/02/09 21:19:11 keil Exp $
+  *
+  * Author       Karsten Keil
+  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
+@@ -26,7 +26,7 @@
+ #define MOD_USE_COUNT ( GET_USE_COUNT (&__this_module))
+ #endif        /* MODULE */
+-const char *lli_revision = "$Revision: 1.1.4.1 $";
++const char *lli_revision = "$Revision: 2.59 $";
+ extern struct IsdnCard cards[];
+ extern int nrcards;
+@@ -145,9 +145,11 @@
+       EV_PROCEED,             /* 20 */
+       EV_ALERT,               /* 21 */ 
+       EV_REDIR,               /* 22 */ 
++      EV_ALERTING,            /* 23 */
++      EV_PROCEEDING,          /* 24 */
+ };
+-#define EVENT_COUNT (EV_REDIR + 1)
++#define EVENT_COUNT (EV_PROCEEDING + 1)
+ static char *strEvent[] =
+ {
+@@ -174,6 +176,8 @@
+       "EV_PROCEED",
+       "EV_ALERT",
+       "EV_REDIR",
++      "EV_ALERTING",
++      "EV_PROCEEDING",
+ };
+@@ -286,6 +290,22 @@
+ }
+ static void
++lli_alerting(struct FsmInst *fi, int event, void *arg)
++{
++      struct Channel *chanp = fi->userdata;
++      
++      HL_LL(chanp, ISDN_STAT_ALERT);
++}
++
++static void
++lli_proceeding(struct FsmInst *fi, int event, void *arg)
++{
++      struct Channel *chanp = fi->userdata;
++      
++      HL_LL(chanp, ISDN_STAT_PROCEED);
++}
++
++static void
+ lli_resume(struct FsmInst *fi, int event, void *arg)
+ {
+       struct Channel *chanp = fi->userdata;
+@@ -784,6 +804,8 @@
+         {ST_OUT_DIAL,           EV_DISCONNECT_IND,      lli_release_req},
+         {ST_OUT_DIAL,           EV_RELEASE,             lli_dhup_close},
+         {ST_OUT_DIAL,           EV_NOSETUP_RSP,         lli_no_setup_rsp},
++        {ST_OUT_DIAL,           EV_PROCEEDING,                lli_proceeding},
++        {ST_OUT_DIAL,           EV_ALERTING,          lli_alerting},
+         {ST_OUT_DIAL,           EV_SETUP_ERR,           lli_error},
+         {ST_IN_WAIT_LL,         EV_LEASED_REL,          lli_failure_l},
+         {ST_IN_WAIT_LL,         EV_ACCEPTD,             lli_setup_rsp},
+@@ -925,7 +947,7 @@
+       ic.driver = cs->myid;
+       ic.command = ISDN_STAT_REDIR;
+       ic.arg = chan; 
+-      ic.parm.num[0] = result;
++      (ulong)(ic.parm.num[0]) = result;
+       cs->iif.statcallb(&ic);
+ } /* stat_redir_result */
+@@ -997,8 +1019,13 @@
+                       FsmEvent(&chanp->fi, EV_RELEASE, NULL);
+                       break;
+               case (CC_PROCEED_SEND | INDICATION):
++                      break;
+               case (CC_PROCEEDING | INDICATION):
++                      FsmEvent(&chanp->fi, EV_PROCEEDING, NULL);
++                      break;
+               case (CC_ALERTING | INDICATION):
++                      FsmEvent(&chanp->fi, EV_ALERTING, NULL);
++                      break;
+               case (CC_PROGRESS | INDICATION):
+               case (CC_NOTIFY | INDICATION):
+                       break;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/cert.c linux-2.4.29/drivers/isdn/hisax/cert.c
+--- linux-2.4.29.old/drivers/isdn/hisax/cert.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/cert.c     2005-03-22 15:06:46.042093320 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: cert.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: cert.c,v 2.6 2001/09/24 13:22:56 kai Exp $
+  *
+  * Author       Karsten Keil
+  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/config.c linux-2.4.29/drivers/isdn/hisax/config.c
+--- linux-2.4.29.old/drivers/isdn/hisax/config.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/config.c   2005-03-22 15:06:46.077088000 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: config.c,v 1.1.4.5 2001/12/09 19:19:26 kai Exp $
++/* $Id: config.c,v 2.84 2002/08/13 09:55:29 keil Exp $
+  *
+  * Author       Karsten Keil
+  * Copyright    by Karsten Keil      <keil@isdn4linux.de>
+@@ -24,6 +24,11 @@
+ #include <linux/kernel_stat.h>
+ #include <linux/tqueue.h>
+ #include <linux/interrupt.h>
++
++#ifdef CONFIG_HISAX_HFC_USB
++#include "hisax_loadable.h"
++#endif
++
+ #define HISAX_STATUS_BUFSIZE 4096
+ #define INCLUDE_INLINE_FUNCS
+@@ -75,8 +80,7 @@
+  *   37 HFC 2BDS0 S+/SP         p0=irq p1=iobase
+  *   38 Travers Technologies NETspider-U PCI card
+  *   39 HFC 2BDS0-SP PCMCIA     p0=irq p1=iobase
+- *   40 hotplug interface
+- *   41 Formula-n enter:now ISDN PCI a/b   none
++ *   40 HFC-S USB               none
+  *
+  * protocol can be either ISDN_PTYPE_EURO or ISDN_PTYPE_1TR6 or ISDN_PTYPE_NI1
+  *
+@@ -95,11 +99,17 @@
+       "Siemens I-Surf", "Acer P10", "HST Saphir", "Telekom A4T",
+       "Scitel Quadro", "Gazel", "HFC 2BDS0 PCI", "Winbond 6692",
+       "HFC 2BDS0 SX", "NETspider-U", "HFC-2BDS0-SP PCMCIA",
+-      "Hotplug", "Formula-n enter:now PCI a/b", 
++      "HFC-S USB",
+ };
+ void HiSax_closecard(int cardnr);
++#ifdef CONFIG_HISAX_HFC_USB
++#define DEFAULT_CARD ISDN_CTYPE_HFC_USB
++#define DEFAULT_CFG {0,0,0,0}
++EXPORT_SYMBOL(hisax_register_hfcusb);
++#endif
++
+ #ifdef CONFIG_HISAX_ELSA
+ #define DEFAULT_CARD ISDN_CTYPE_ELSA
+ #define DEFAULT_CFG {0,0,0,0}
+@@ -339,19 +349,27 @@
+       NULL, \
+ }
+-struct IsdnCard cards[HISAX_MAX_CARDS] = {
++#define EMPTY_CARD    {0, DEFAULT_PROTO, {0, 0, 0, 0}, NULL}
++
++struct IsdnCard cards[] = {
+       FIRST_CARD,
++      EMPTY_CARD,
++      EMPTY_CARD,
++      EMPTY_CARD,
++      EMPTY_CARD,
++      EMPTY_CARD,
++      EMPTY_CARD,
++      EMPTY_CARD,
+ };
+-#define HISAX_IDSIZE (HISAX_MAX_CARDS*8)
+-static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, };
++static char HiSaxID[64] __devinitdata = { 0, };
+ char *HiSax_id __devinitdata = HiSaxID;
+ #ifdef MODULE
+ /* Variables for insmod */
+-static int type[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int io[HISAX_MAX_CARDS] __devinitdata = { 0, };
++static int type[8] __devinitdata = { 0, };
++static int protocol[8] __devinitdata = { 0, };
++static int io[8] __devinitdata = { 0, };
+ #undef IO0_IO1
+ #ifdef CONFIG_HISAX_16_3
+ #define IO0_IO1
+@@ -361,27 +379,23 @@
+ #define IO0_IO1
+ #endif
+ #ifdef IO0_IO1
+-static int io0[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int io1[HISAX_MAX_CARDS] __devinitdata = { 0, };
++static int io0[8] __devinitdata = { 0, };
++static int io1[8] __devinitdata = { 0, };
+ #endif
+-static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, };
+-static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, };
++static int irq[8] __devinitdata = { 0, };
++static int mem[8] __devinitdata = { 0, };
+ static char *id __devinitdata = HiSaxID;
+-#define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i"
+-
+-MODULE_DESCRIPTION("ISDN4Linux: Driver for passive ISDN cards");
+ MODULE_AUTHOR("Karsten Keil");
+-MODULE_LICENSE("GPL");
+-MODULE_PARM(type, PARM_PARA);
+-MODULE_PARM(protocol, PARM_PARA);
+-MODULE_PARM(io, PARM_PARA);
+-MODULE_PARM(irq, PARM_PARA);
+-MODULE_PARM(mem, PARM_PARA);
++MODULE_PARM(type, "1-8i");
++MODULE_PARM(protocol, "1-8i");
++MODULE_PARM(io, "1-8i");
++MODULE_PARM(irq, "1-8i");
++MODULE_PARM(mem, "1-8i");
+ MODULE_PARM(id, "s");
+ #ifdef IO0_IO1
+-MODULE_PARM(io0, PARM_PARA);
+-MODULE_PARM(io1, PARM_PARA);
++MODULE_PARM(io0, "1-8i");
++MODULE_PARM(io1, "1-8i");
+ #endif
+ #endif /* MODULE */
+@@ -432,6 +446,7 @@
+ }
+ #ifndef MODULE
++#ifdef COMPAT_HAS_NEW_SETUP
+ #define MAX_ARG       (HISAX_MAX_CARDS*5)
+ static int __init HiSax_setup(char *line)
+ {
+@@ -440,12 +455,16 @@
+       char *str;
+       str = get_options(line, MAX_ARG, ints);
++#else
++void __init HiSax_setup(char *str, int *ints)
++{
++      int i, j, argc;
++#endif
+       argc = ints[0];
+       printk(KERN_DEBUG "HiSax_setup: argc(%d) str(%s)\n", argc, str);
+       i = 0;
+       j = 1;
+       while (argc && (i < HISAX_MAX_CARDS)) {
+-              cards[i].protocol = DEFAULT_PROTO;
+               if (argc) {
+                       cards[i].typ = ints[j];
+                       j++;
+@@ -473,19 +492,21 @@
+               }
+               i++;
+       }
+-      if (str && *str) {
+-              if (strlen(str) < HISAX_IDSIZE)
+-                      strcpy(HiSaxID, str);
+-              else
+-                      printk(KERN_WARNING "HiSax: ID too long!");
+-      } else
++      if (str && *str) {
++              strcpy(HiSaxID, str);
++              HiSax_id = HiSaxID;
++      } else {
+               strcpy(HiSaxID, "HiSax");
+-
+-      HiSax_id = HiSaxID;
++              HiSax_id = HiSaxID;
++      }
++#ifdef COMPAT_HAS_NEW_SETUP
+       return 1;
+ }
+ __setup("hisax=", HiSax_setup);
++#else
++}
++#endif /* COMPAT_HAS_NEW_SETUP */
+ #endif /* MODULES */
+ #if CARD_TELES0
+@@ -560,6 +581,10 @@
+ extern int setup_hfcpci(struct IsdnCard *card);
+ #endif
++#if CONFIG_HISAX_HFC_USB
++extern int setup_hfc_usb(struct IsdnCard *card);
++#endif
++
+ #if CARD_HFC_SX
+ extern int setup_hfcsx(struct IsdnCard *card);
+ #endif
+@@ -604,10 +629,6 @@
+ extern int setup_netjet_u(struct IsdnCard *card);
+ #endif
+-#if CARD_FN_ENTERNOW_PCI
+-extern int setup_enternow_pci(struct IsdnCard *card);
+-#endif
+-
+ /*
+  * Find card with given driverId
+  */
+@@ -899,7 +920,8 @@
+       return 3;
+ }
+-static int __devinit checkcard(int cardnr, char *id, int *busy_flag)
++static int __devinit checkcard(int cardnr, char *id, int *busy_flag,
++                             void *load_drv)
+ {
+       long flags;
+       int ret = 0;
+@@ -1093,6 +1115,12 @@
+               ret = setup_hfcsx(card);
+               break;
+ #endif
++#if CONFIG_HISAX_HFC_USB
++      case ISDN_CTYPE_HFC_USB:
++              cs->hw.hfcusb.drv = load_drv;
++              ret = setup_hfc_usb(card);
++              break;
++#endif
+ #if CARD_NICCY
+       case ISDN_CTYPE_NICCY:
+               ret = setup_niccy(card);
+@@ -1143,11 +1171,6 @@
+               ret = setup_netjet_u(card);
+               break;
+ #endif
+-#if CARD_FN_ENTERNOW_PCI
+-      case ISDN_CTYPE_ENTERNOW:
+-              ret = setup_enternow_pci(card);
+-              break;
+-#endif
+       case ISDN_CTYPE_DYNAMIC:
+               ret = 2;
+               break;
+@@ -1186,6 +1209,9 @@
+       case ISDN_CTYPE_DYNAMIC:
+               ret = 0;
+               break;
++      case ISDN_CTYPE_HFC_USB:
++              ret = cs->cardmsg(cs, CARD_INIT, NULL);
++              break;
+       default:
+               ret = init_card(cs);
+               break;
+@@ -1257,16 +1283,13 @@
+                       else
+                               sprintf(ids, "%s%d", id, i);
+               }
+-              if (checkcard(i, ids, busy_flag)) {
++              if (checkcard(i, ids, busy_flag, NULL)) {
+                       foundcards++;
+                       i++;
+               } else {
+-                      /* make sure we don't oops the module */
+-                      if (cards[i].typ > 0 && cards[i].typ <= ISDN_CTYPE_COUNT) {
+-                              printk(KERN_WARNING
+-                                      "HiSax: Card %s not installed !\n",
+-                                      CardType[cards[i].typ]);
+-                      }
++                      printk(KERN_WARNING
++                             "HiSax: Card %s not installed !\n",
++                             CardType[cards[i].typ]);
+                       HiSax_shiftcards(i);
+                       nrcards--;
+               }
+@@ -1342,6 +1365,49 @@
+ #endif
+ }
++#ifdef CONFIG_HISAX_HFC_USB
++int
++hisax_register_hfcusb(struct hisax_drvreg *l1drv)
++{
++      int i;
++      char ids[30];
++
++      if (l1drv->version != HISAX_LOAD_VERSION)
++              return 1;
++
++      switch (l1drv->cmd) {
++      case HISAX_LOAD_CHKVER:
++              break;  /* success */
++
++      case HISAX_LOAD_REGISTER:
++              for (i = 0; i < HISAX_MAX_CARDS; i++) {
++                      if (!cards[i].typ)
++                              break;
++              }
++              if (i >= HISAX_MAX_CARDS)
++                      return 1;       /* no space */
++              cards[i].typ = ISDN_CTYPE_HFC_USB;      /* setup type */
++              cards[i].protocol = DEFAULT_PROTO;
++              sprintf(ids, "%s%d", l1drv->drvname, i);
++              if (checkcard(i, ids, NULL, (void *) l1drv)) {
++                      nrcards++;
++                      return 0;
++              }
++              if (cards[i].cs)
++                      kfree((void *) cards[i].cs);
++              cards[i].cs = NULL;
++              cards[i].typ = 0;       /* no card present */
++              return 1;
++              break;
++
++      default:
++              return 1;       /* unknown command */
++      }
++
++      return 0;
++}                             /* hisax_register_hfcusb */
++#endif
++
+ static int __init HiSax_init(void)
+ {
+       int i, retval;
+@@ -1408,8 +1474,6 @@
+               if (protocol[i]) {
+                       cards[j].protocol = protocol[i];
+                       nzproto++;
+-              } else {
+-                      cards[j].protocol = DEFAULT_PROTO;
+               }
+               switch (type[i]) {
+               case ISDN_CTYPE_16_0:
+@@ -1487,22 +1551,15 @@
+                       } else {
+                               /* QUADRO is a 4 BRI card */
+                               cards[j++].para[0] = 1;
+-                              /* we need to check if further cards can be added */
+-                              if (j < HISAX_MAX_CARDS) {
+-                                      cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+-                                      cards[j].protocol = protocol[i];
+-                                      cards[j++].para[0] = 2;
+-                              }
+-                              if (j < HISAX_MAX_CARDS) {
+-                                      cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+-                                      cards[j].protocol = protocol[i];
+-                                      cards[j++].para[0] = 3;
+-                              }
+-                              if (j < HISAX_MAX_CARDS) {
+-                                      cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
+-                                      cards[j].protocol = protocol[i];
+-                                      cards[j].para[0] = 4;
+-                              }
++                              cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
++                              cards[j].protocol = protocol[i];
++                              cards[j++].para[0] = 2;
++                              cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
++                              cards[j].protocol = protocol[i];
++                              cards[j++].para[0] = 3;
++                              cards[j].typ = ISDN_CTYPE_SCT_QUADRO;
++                              cards[j].protocol = protocol[i];
++                              cards[j].para[0] = 4;
+                       }
+                       break;
+               }
+@@ -1526,10 +1583,15 @@
+              nrcards, (nrcards > 1) ? "s" : "");
+       /* Install only, if at least one card found */
+-      if (!HiSax_inithardware(NULL))
+-              return -ENODEV;
++      if (!HiSax_inithardware(NULL)) {
++              retval = -EIO;
++              goto out_isdnl1;
++      }
++
+       return 0;
++ out_isdnl1:
++      Isdnl1Free();
+  out_tei:
+       TeiFree();
+  out_isdnl2:
+@@ -1576,8 +1638,6 @@
+               cards[i].typ = type[i];
+               if (protocol[i]) {
+                       cards[i].protocol = protocol[i];
+-              } else {
+-                      cards[i].protocol = DEFAULT_PROTO;
+               }
+       }
+       cards[0].para[0] = pcm_irq;
+@@ -1595,8 +1655,7 @@
+       printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+              nrcards, (nrcards > 1) ? "s" : "");
+-      if (!HiSax_inithardware(busy_flag))
+-              return -ENODEV;
++      HiSax_inithardware(busy_flag);
+       printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+       return 0;
+@@ -1619,8 +1678,6 @@
+               cards[i].typ = type[i];
+               if (protocol[i]) {
+                       cards[i].protocol = protocol[i];
+-              } else {
+-                      cards[i].protocol = DEFAULT_PROTO;
+               }
+       }
+       cards[0].para[0] = pcm_irq;
+@@ -1638,8 +1695,7 @@
+       printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+              nrcards, (nrcards > 1) ? "s" : "");
+-      if (!HiSax_inithardware(busy_flag))
+-              return -ENODEV;
++      HiSax_inithardware(busy_flag);
+       printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+       return 0;
+@@ -1662,8 +1718,6 @@
+               cards[i].typ = type[i];
+               if (protocol[i]) {
+                       cards[i].protocol = protocol[i];
+-              } else {
+-                      cards[i].protocol = DEFAULT_PROTO;
+               }
+       }
+       cards[0].para[0] = pcm_irq;
+@@ -1681,8 +1735,7 @@
+       printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+              nrcards, (nrcards > 1) ? "s" : "");
+-      if (!HiSax_inithardware(busy_flag))
+-              return -ENODEV;
++      HiSax_inithardware(busy_flag);
+       printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+       return 0;
+@@ -1705,8 +1758,6 @@
+               cards[i].typ = type[i];
+               if (protocol[i]) {
+                       cards[i].protocol = protocol[i];
+-              } else {
+-                      cards[i].protocol = DEFAULT_PROTO;
+               }
+       }
+       cards[0].para[0] = pcm_irq;
+@@ -1724,8 +1775,7 @@
+       printk(KERN_DEBUG "HiSax: Total %d card%s defined\n",
+              nrcards, (nrcards > 1) ? "s" : "");
+-      if (!HiSax_inithardware(busy_flag))
+-              return -ENODEV;
++      HiSax_inithardware(busy_flag);
+       printk(KERN_NOTICE "HiSax: module installed\n");
+ #endif
+       return 0;
+@@ -1743,7 +1793,7 @@
+               sprintf(ids, "HiSax%d", nrcards);
+       else
+               sprintf(ids, "HiSax");
+-      if (!checkcard(nrcards, ids, busy_flag)) {
++      if (!checkcard(nrcards, ids, busy_flag, NULL)) {
+               return -1;
+       }
+       ret = nrcards;
+@@ -1785,7 +1835,7 @@
+       cards[i].protocol = protocol;
+       sprintf(id, "%s%d", name, i);
+       nrcards++;
+-      retval = checkcard(i, id, 0);
++      retval = checkcard(i, id, 0, NULL);
+       if (retval == 0) { // yuck
+               cards[i].typ = 0;
+               nrcards--;
+@@ -2117,9 +2167,6 @@
+       {PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA20,     PCI_ANY_ID, PCI_ANY_ID},
+       {PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA20_U,   PCI_ANY_ID, PCI_ANY_ID},
+       {PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA201,    PCI_ANY_ID, PCI_ANY_ID},
+-//#########################################################################################   
+-      {PCI_VENDOR_ID_EICON,    PCI_DEVICE_ID_EICON_DIVA202,    PCI_ANY_ID, PCI_ANY_ID},
+-//#########################################################################################   
+ #endif
+ #ifdef CONFIG_HISAX_ELSA
+       {PCI_VENDOR_ID_ELSA,     PCI_DEVICE_ID_ELSA_MICROLINK,   PCI_ANY_ID, PCI_ANY_ID},
+@@ -2178,11 +2225,3 @@
+ module_init(HiSax_init);
+ module_exit(HiSax_exit);
+-
+-EXPORT_SYMBOL(FsmNew);
+-EXPORT_SYMBOL(FsmFree);
+-EXPORT_SYMBOL(FsmEvent);
+-EXPORT_SYMBOL(FsmChangeState);
+-EXPORT_SYMBOL(FsmInitTimer);
+-EXPORT_SYMBOL(FsmDelTimer);
+-EXPORT_SYMBOL(FsmRestartTimer);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/diva.c linux-2.4.29/drivers/isdn/hisax/diva.c
+--- linux-2.4.29.old/drivers/isdn/hisax/diva.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/diva.c     2005-03-22 15:06:46.106083592 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: diva.c,v 1.1.4.2 2002/08/30 11:21:00 keil Exp $
++/* $Id: diva.c,v 1.33 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for Eicon.Diehl Diva Family ISDN cards
+  *
+@@ -22,14 +22,13 @@
+ #include "isac.h"
+ #include "hscx.h"
+ #include "ipac.h"
+-#include "ipacx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+ extern const char *CardType[];
+-const char *Diva_revision = "$Revision: 1.1.4.2 $";
++const char *Diva_revision = "$Revision: 1.33 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -51,7 +50,6 @@
+ #define DIVA_PCI      2
+ #define DIVA_IPAC_ISA 3
+ #define DIVA_IPAC_PCI 4
+-#define DIVA_IPACX_PCI        5
+ /* CTRL (Read) */
+ #define DIVA_IRQ_STAT 0x01
+@@ -71,12 +69,10 @@
+ #define PITA_MISC_REG         0x1c
+ #ifdef __BIG_ENDIAN
+ #define PITA_PARA_SOFTRESET   0x00000001
+-#define PITA_SER_SOFTRESET    0x00000002
+ #define PITA_PARA_MPX_MODE    0x00000004
+ #define PITA_INT0_ENABLE      0x00000200
+ #else
+ #define PITA_PARA_SOFTRESET   0x01000000
+-#define PITA_SER_SOFTRESET    0x02000000
+ #define PITA_PARA_MPX_MODE    0x04000000
+ #define PITA_INT0_ENABLE      0x00020000
+ #endif
+@@ -244,47 +240,6 @@
+       memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value);
+ }
+-/* IO-Functions for IPACX type cards */
+-static u_char
+-MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset)
+-{
+-      return (memreadreg(cs->hw.diva.cfg_reg, offset));
+-}
+-
+-static void
+-MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value)
+-{
+-      memwritereg(cs->hw.diva.cfg_reg, offset, value);
+-}
+-
+-static void
+-MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
+-{
+-      while(size--)
+-              *data++ = memreadreg(cs->hw.diva.cfg_reg, 0);
+-}
+-
+-static void
+-MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size)
+-{
+-      while(size--)
+-              memwritereg(cs->hw.diva.cfg_reg, 0, *data++);
+-}
+-
+-static u_char
+-MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset)
+-{
+-      return(memreadreg(cs->hw.diva.cfg_reg, offset + 
+-                    (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1)));
+-}
+-
+-static void
+-MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value)
+-{
+-      memwritereg(cs->hw.diva.cfg_reg, offset + 
+-              (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value);
+-}
+-
+ /*
+  * fast interrupt HSCX stuff goes here
+  */
+@@ -595,7 +550,7 @@
+       u_char exval;
+       struct BCState *bcs;
+-      if (val & 0x01) { // EXB
++      if (val & 0x01) {
+               bcs = cs->bcs + 1;
+               exval = MemReadHSCX(cs, 1, HSCX_EXIR);
+               if (exval & 0x40) {
+@@ -622,7 +577,7 @@
+                       debugl1(cs, "HSCX B interrupt %x", val);
+               Memhscx_interrupt(cs, val, 1);
+       }
+-      if (val & 0x02) {       // EXA
++      if (val & 0x02) {
+               bcs = cs->bcs;
+               exval = MemReadHSCX(cs, 0, HSCX_EXIR);
+               if (exval & 0x40) {
+@@ -644,7 +599,7 @@
+               } else if (cs->debug & L1_DEB_HSCX)
+                       debugl1(cs, "HSCX A EXIR %x", exval);
+       }
+-      if (val & 0x04) {       // ICA
++      if (val & 0x04) {
+               exval = MemReadHSCX(cs, 0, HSCX_ISTA);
+               if (cs->debug & L1_DEB_HSCX)
+                       debugl1(cs, "HSCX A interrupt %x", exval);
+@@ -705,31 +660,12 @@
+       memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0);
+ }
+-static void
+-diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs)
+-{
+-      struct IsdnCardState *cs = dev_id;
+-      u_char val;
+-      u_char *cfg;
+-
+-      if (!cs) {
+-              printk(KERN_WARNING "Diva: Spurious interrupt!\n");
+-              return;
+-      }
+-      cfg = (u_char *) cs->hw.diva.pci_cfg;
+-      val = *cfg;
+-      if (!(val &PITA_INT0_STATUS)) return; // other shared IRQ
+-  interrupt_ipacx(cs);      // handler for chip
+-      *cfg = PITA_INT0_STATUS;  // Reset PLX interrupt
+-}
+-
+ void
+ release_io_diva(struct IsdnCardState *cs)
+ {
+       int bytecnt;
+-      if ((cs->subtyp == DIVA_IPAC_PCI) || 
+-          (cs->subtyp == DIVA_IPACX_PCI)   ) {
++      if (cs->subtyp == DIVA_IPAC_PCI) {
+               u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg;
+               *cfg = 0; /* disable INT0/1 */ 
+@@ -776,16 +712,6 @@
+               set_current_state(TASK_UNINTERRUPTIBLE);
+               schedule_timeout((10*HZ)/1000);
+               memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0);
+-      } else if (cs->subtyp == DIVA_IPACX_PCI) {
+-              unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg +
+-                                      PITA_MISC_REG);
+-              *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE;
+-              set_current_state(TASK_UNINTERRUPTIBLE);
+-              schedule_timeout((10*HZ)/1000);
+-              *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET;
+-              set_current_state(TASK_UNINTERRUPTIBLE);
+-              schedule_timeout((10*HZ)/1000);
+-              MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off
+       } else { /* DIVA 2.0 */
+               cs->hw.diva.ctrl_reg = 0;        /* Reset On */
+               byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg);
+@@ -814,9 +740,7 @@
+ {
+       int blink = 0;
+-      if ((cs->subtyp == DIVA_IPAC_ISA) ||
+-          (cs->subtyp == DIVA_IPAC_PCI) ||
+-          (cs->subtyp == DIVA_IPACX_PCI)   )
++      if ((cs->subtyp == DIVA_IPAC_ISA) || (cs->subtyp == DIVA_IPAC_PCI))
+               return;
+       del_timer(&cs->hw.diva.tl);
+       if (cs->hw.diva.status & DIVA_ASSIGN)
+@@ -859,12 +783,6 @@
+                       release_io_diva(cs);
+                       return(0);
+               case CARD_INIT:
+-                      if (cs->subtyp == DIVA_IPACX_PCI) {
+-                              ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+-                              *ireg = PITA_INT0_ENABLE;
+-                        init_ipacx(cs, 3); // init chip and enable interrupts
+-        return (0);
+-                      }
+                       if (cs->subtyp == DIVA_IPAC_PCI) {
+                               ireg = (unsigned int *)cs->hw.diva.pci_cfg;
+                               *ireg = PITA_INT0_ENABLE;
+@@ -901,9 +819,7 @@
+                       }
+                       break;
+       }
+-      if ((cs->subtyp != DIVA_IPAC_ISA) && 
+-          (cs->subtyp != DIVA_IPAC_PCI) &&
+-          (cs->subtyp != DIVA_IPACX_PCI)   )
++      if ((cs->subtyp != DIVA_IPAC_ISA) && (cs->subtyp != DIVA_IPAC_PCI))
+               diva_led_handler(cs);
+       return(0);
+ }
+@@ -911,40 +827,11 @@
+ static struct pci_dev *dev_diva __initdata = NULL;
+ static struct pci_dev *dev_diva_u __initdata = NULL;
+ static struct pci_dev *dev_diva201 __initdata = NULL;
+-static struct pci_dev *dev_diva202 __initdata = NULL;
+-
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id diva_ids[] __initdata = {
+-      { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
+-        ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), 
+-        (unsigned long) "Diva picola" },
+-      { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51),
+-        ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x51), 
+-        (unsigned long) "Diva picola" },
+-      { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
+-        ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71), 
+-        (unsigned long) "Diva 2.0" },
+-      { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x71),
+-        ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0x71), 
+-        (unsigned long) "Diva 2.0" },
+-      { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
+-        ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1), 
+-        (unsigned long) "Diva 2.01" },
+-      { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0xA1),
+-        ISAPNP_VENDOR('E', 'I', 'C'), ISAPNP_FUNCTION(0xA1), 
+-        (unsigned long) "Diva 2.01" },
+-      { 0, }
+-};
+-
+-static struct isapnp_device_id *pdev = &diva_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_diva(struct IsdnCard *card)
+ {
+-      int bytecnt = 8;
++      int bytecnt;
+       u_char val;
+       struct IsdnCardState *cs = card->cs;
+       char tmp[64];
+@@ -977,75 +864,8 @@
+                       cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR;
+               }
+               cs->irq = card->para[0];
++              bytecnt = 8;
+       } else {
+-#ifdef __ISAPNP__
+-              if (isapnp_present()) {
+-                      struct pci_bus *pb;
+-                      struct pci_dev *pd;
+-
+-                      while(pdev->card_vendor) {
+-                              if ((pb = isapnp_find_card(pdev->card_vendor,
+-                                      pdev->card_device, pnp_c))) {
+-                                      pnp_c = pb;
+-                                      pd = NULL;
+-                                      if ((pd = isapnp_find_dev(pnp_c,
+-                                              pdev->vendor, pdev->function, pd))) {
+-                                              printk(KERN_INFO "HiSax: %s detected\n",
+-                                                      (char *)pdev->driver_data);
+-                                              pd->prepare(pd);
+-                                              pd->deactivate(pd);
+-                                              pd->activate(pd);
+-                                              card->para[1] =
+-                                                      pd->resource[0].start;
+-                                              card->para[0] =
+-                                                      pd->irq_resource[0].start;
+-                                              if (!card->para[0] || !card->para[1]) {
+-                                                      printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n",
+-                                                              card->para[0], card->para[1]);
+-                                                      pd->deactivate(pd);
+-                                                      return(0);
+-                                              }
+-                                              cs->hw.diva.cfg_reg  = card->para[1];
+-                                              cs->irq = card->para[0];
+-                                              if (pdev->function == ISAPNP_FUNCTION(0xA1)) {
+-                                                      cs->subtyp = DIVA_IPAC_ISA;
+-                                                      cs->hw.diva.ctrl = 0;
+-                                                      cs->hw.diva.isac =
+-                                                              card->para[1] + DIVA_IPAC_DATA;
+-                                                      cs->hw.diva.hscx =
+-                                                              card->para[1] + DIVA_IPAC_DATA;
+-                                                      cs->hw.diva.isac_adr =
+-                                                              card->para[1] + DIVA_IPAC_ADR;
+-                                                      cs->hw.diva.hscx_adr =
+-                                                              card->para[1] + DIVA_IPAC_ADR;
+-                                                      test_and_set_bit(HW_IPAC, &cs->HW_Flags);
+-                                              } else {
+-                                                      cs->subtyp = DIVA_ISA;
+-                                                      cs->hw.diva.ctrl =
+-                                                              card->para[1] + DIVA_ISA_CTRL;
+-                                                      cs->hw.diva.isac =
+-                                                              card->para[1] + DIVA_ISA_ISAC_DATA;
+-                                                      cs->hw.diva.hscx =
+-                                                              card->para[1] + DIVA_HSCX_DATA;
+-                                                      cs->hw.diva.isac_adr =
+-                                                              card->para[1] + DIVA_ISA_ISAC_ADR;
+-                                                      cs->hw.diva.hscx_adr =
+-                                                              card->para[1] + DIVA_HSCX_ADR;
+-                                              }
+-                                              goto ready;
+-                                      } else {
+-                                              printk(KERN_ERR "Diva PnP: PnP error card found, no device\n");
+-                                              return(0);
+-                                      }
+-                              }
+-                              pdev++;
+-                              pnp_c=NULL;
+-                      } 
+-                      if (!pdev->card_vendor) {
+-                              printk(KERN_INFO "Diva PnP: no ISAPnP card found\n");
+-                      }
+-              }
+-#endif
+ #if CONFIG_PCI
+               if (!pci_present()) {
+                       printk(KERN_ERR "Diva: no PCI bus present\n");
+@@ -1059,14 +879,14 @@
+                               return(0);
+                       cs->subtyp = DIVA_PCI;
+                       cs->irq = dev_diva->irq;
+-                      cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2);
++                      cs->hw.diva.cfg_reg = pci_resource_start_io(dev_diva, 2);
+               } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON,
+                       PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) {
+                       if (pci_enable_device(dev_diva_u))
+                               return(0);
+                       cs->subtyp = DIVA_PCI;
+                       cs->irq = dev_diva_u->irq;
+-                      cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2);
++                      cs->hw.diva.cfg_reg = pci_resource_start_io(dev_diva_u, 2);
+               } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON,
+                       PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) {
+                       if (pci_enable_device(dev_diva201))
+@@ -1074,19 +894,9 @@
+                       cs->subtyp = DIVA_IPAC_PCI;
+                       cs->irq = dev_diva201->irq;
+                       cs->hw.diva.pci_cfg =
+-                              (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096);
++                              (ulong) ioremap(pci_resource_start_mem(dev_diva201, 0), 4096);
+                       cs->hw.diva.cfg_reg =
+-                              (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096);
+-              } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON,
+-                      PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) {
+-                      if (pci_enable_device(dev_diva202))
+-                              return(0);
+-                      cs->subtyp = DIVA_IPACX_PCI;
+-                      cs->irq = dev_diva202->irq;
+-                      cs->hw.diva.pci_cfg =
+-                              (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096);
+-                      cs->hw.diva.cfg_reg =
+-                              (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096);
++                              (ulong) ioremap(pci_resource_start_mem(dev_diva201, 1), 4096);
+               } else {
+                       printk(KERN_WARNING "Diva: No PCI card found\n");
+                       return(0);
+@@ -1107,8 +917,7 @@
+               printk(KERN_WARNING "Diva: unable to config DIVA PCI\n");
+               return (0);
+ #endif /* CONFIG_PCI */
+-              if ((cs->subtyp == DIVA_IPAC_PCI) ||
+-                  (cs->subtyp == DIVA_IPACX_PCI)   ) {
++              if (cs->subtyp == DIVA_IPAC_PCI) {
+                       cs->hw.diva.ctrl = 0;
+                       cs->hw.diva.isac = 0;
+                       cs->hw.diva.hscx = 0;
+@@ -1125,23 +934,18 @@
+                       bytecnt = 32;
+               }
+       }
+-ready:
++
+       printk(KERN_INFO
+               "Diva: %s card configured at %#lx IRQ %d\n",
+               (cs->subtyp == DIVA_PCI) ? "PCI" :
+               (cs->subtyp == DIVA_ISA) ? "ISA" : 
+-              (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" :
+-              (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
++              (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : "IPAC PCI",
+               cs->hw.diva.cfg_reg, cs->irq);
+-      if ((cs->subtyp == DIVA_IPAC_PCI)  || 
+-          (cs->subtyp == DIVA_IPACX_PCI) || 
+-          (cs->subtyp == DIVA_PCI)         )
+-              printk(KERN_INFO "Diva: %s space at %#lx\n",
+-                      (cs->subtyp == DIVA_PCI) ? "PCI" :
+-                      (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI",
++      if ((cs->subtyp == DIVA_IPAC_PCI) || (cs->subtyp == DIVA_PCI))
++              printk(KERN_INFO "Diva: %s PCI space at %#lx\n",
++                      (cs->subtyp == DIVA_PCI) ? "PCI" : "IPAC PCI",
+                       cs->hw.diva.pci_cfg);
+-      if ((cs->subtyp != DIVA_IPAC_PCI) &&
+-          (cs->subtyp != DIVA_IPACX_PCI)   ) {
++      if (cs->subtyp != DIVA_IPAC_PCI) {
+               if (check_region(cs->hw.diva.cfg_reg, bytecnt)) {
+                       printk(KERN_WARNING
+                              "HiSax: %s config port %lx-%lx already in use\n",
+@@ -1177,17 +981,6 @@
+               cs->irq_func = &diva_irq_ipac_pci;
+               val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID);
+               printk(KERN_INFO "Diva: IPAC version %x\n", val);
+-      } else if (cs->subtyp == DIVA_IPACX_PCI) {
+-              cs->readisac  = &MemReadISAC_IPACX;
+-              cs->writeisac = &MemWriteISAC_IPACX;
+-              cs->readisacfifo  = &MemReadISACfifo_IPACX;
+-              cs->writeisacfifo = &MemWriteISACfifo_IPACX;
+-              cs->BC_Read_Reg  = &MemReadHSCX_IPACX;
+-              cs->BC_Write_Reg = &MemWriteHSCX_IPACX;
+-              cs->BC_Send_Data = 0; // function located in ipacx module
+-              cs->irq_func = &diva_irq_ipacx_pci;
+-              printk(KERN_INFO "Diva: IPACX Design Id: %x\n", 
+-            MemReadISAC_IPACX(cs, IPACX_ID) &0x3F);
+       } else { /* DIVA 2.0 */
+               cs->hw.diva.tl.function = (void *) diva_led_handler;
+               cs->hw.diva.tl.data = (long) cs;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/elsa.c linux-2.4.29/drivers/isdn/hisax/elsa.c
+--- linux-2.4.29.old/drivers/isdn/hisax/elsa.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/elsa.c     2005-03-22 15:06:46.123081008 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: elsa.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: elsa.c,v 2.32 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for Elsa isdn cards
+  *
+@@ -28,13 +28,13 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+ #include <linux/serial.h>
+ #include <linux/serial_reg.h>
+ extern const char *CardType[];
+-const char *Elsa_revision = "$Revision: 1.1.4.1 $";
++const char *Elsa_revision = "$Revision: 2.32 $";
+ const char *Elsa_Types[] =
+ {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro",
+  "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", 
+@@ -864,21 +864,6 @@
+ static        struct pci_dev *dev_qs1000 __devinitdata = NULL;
+ static        struct pci_dev *dev_qs3000 __devinitdata = NULL;
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id elsa_ids[] __initdata = {
+-      { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133),
+-        ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0133), 
+-        (unsigned long) "Elsa QS1000" },
+-      { ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134),
+-        ISAPNP_VENDOR('E', 'L', 'S'), ISAPNP_FUNCTION(0x0134), 
+-        (unsigned long) "Elsa QS3000" },
+-      { 0, }
+-};
+-
+-static struct isapnp_device_id *pdev = &elsa_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __devinit
+ setup_elsa(struct IsdnCard *card)
+ {
+@@ -893,7 +878,6 @@
+       cs->hw.elsa.ctrl_reg = 0;
+       cs->hw.elsa.status = 0;
+       cs->hw.elsa.MFlag = 0;
+-      cs->subtyp = 0;
+       if (cs->typ == ISDN_CTYPE_ELSA) {
+               cs->hw.elsa.base = card->para[0];
+               printk(KERN_INFO "Elsa: Microlink IO probing\n");
+@@ -955,60 +939,9 @@
+                       return (0);
+               }
+       } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) {
+-#ifdef __ISAPNP__
+-              if (!card->para[1] && isapnp_present()) {
+-                      struct pci_bus *pb;
+-                      struct pci_dev *pd;
+-
+-                      while(pdev->card_vendor) {
+-                              if ((pb = isapnp_find_card(pdev->card_vendor,
+-                                      pdev->card_device, pnp_c))) {
+-                                      pnp_c = pb;
+-                                      pd = NULL;
+-                                      if ((pd = isapnp_find_dev(pnp_c,
+-                                              pdev->vendor, pdev->function, pd))) {
+-                                              printk(KERN_INFO "HiSax: %s detected\n",
+-                                                      (char *)pdev->driver_data);
+-                                              pd->prepare(pd);
+-                                              pd->deactivate(pd);
+-                                              pd->activate(pd);
+-                                              card->para[1] =
+-                                                      pd->resource[0].start;
+-                                              card->para[0] =
+-                                                      pd->irq_resource[0].start;
+-                                              if (!card->para[0] || !card->para[1]) {
+-                                                      printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n",
+-                                                              card->para[0], card->para[1]);
+-                                                      pd->deactivate(pd);
+-                                                      return(0);
+-                                              }
+-                                              if (pdev->function == ISAPNP_FUNCTION(0x133))
+-                                                      cs->subtyp = ELSA_QS1000;
+-                                              else
+-                                                      cs->subtyp = ELSA_QS3000;
+-                                              break;
+-                                      } else {
+-                                              printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n");
+-                                              return(0);
+-                                      }
+-                              }
+-                              pdev++;
+-                              pnp_c=NULL;
+-                      } 
+-                      if (!pdev->card_vendor) {
+-                              printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n");
+-                              return(0);
+-                      }
+-              }
+-#endif
+-              if (card->para[1] && card->para[0]) { 
+-                      cs->hw.elsa.base = card->para[1];
+-                      cs->irq = card->para[0];
+-                      if (!cs->subtyp)
+-                              cs->subtyp = ELSA_QS1000;
+-              } else {
+-                      printk(KERN_ERR "Elsa PnP: no parameter\n");
+-              }
++              cs->hw.elsa.base = card->para[1];
++              cs->irq = card->para[0];
++              cs->subtyp = ELSA_QS1000;
+               cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG;
+               cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE;
+               cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC;
+@@ -1058,16 +991,16 @@
+                               return(0);
+                       cs->subtyp = ELSA_QS1000PCI;
+                       cs->irq = dev_qs1000->irq;
+-                      cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1);
+-                      cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3);
++                      cs->hw.elsa.cfg = pci_resource_start_io(dev_qs1000, 1);
++                      cs->hw.elsa.base = pci_resource_start_io(dev_qs1000, 3);
+               } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA,
+                       PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) {
+                       if (pci_enable_device(dev_qs3000))
+                               return(0);
+                       cs->subtyp = ELSA_QS3000PCI;
+                       cs->irq = dev_qs3000->irq;
+-                      cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1);
+-                      cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3);
++                      cs->hw.elsa.cfg = pci_resource_start_io(dev_qs3000, 1);
++                      cs->hw.elsa.base = pci_resource_start_io(dev_qs3000, 3);
+               } else {
+                       printk(KERN_WARNING "Elsa: No PCI card found\n");
+                       return(0);
+@@ -1123,7 +1056,6 @@
+                       break;
+               case ELSA_PCFPRO:
+               case ELSA_PCF:
+-              case ELSA_QS3000:
+               case ELSA_QS3000PCI:
+                       bytecnt = 16;
+                       break;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/elsa_cs.c linux-2.4.29/drivers/isdn/hisax/elsa_cs.c
+--- linux-2.4.29.old/drivers/isdn/hisax/elsa_cs.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/elsa_cs.c  2005-03-22 15:06:46.138078728 +0100
+@@ -72,7 +72,7 @@
+ MODULE_PARM(pc_debug, "i");
+ #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
+ static char *version =
+-"elsa_cs.c $Revision: 1.1.4.1 $ $Date: 2001/11/20 14:19:35 $ (K.Lichtenwalder)";
++"elsa_cs.c $Revision: 1.2 $ $Date: 2001/09/24 13:22:56 $ (K.Lichtenwalder)";
+ #else
+ #define DEBUG(n, args...)
+ #endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/elsa_ser.c linux-2.4.29/drivers/isdn/hisax/elsa_ser.c
+--- linux-2.4.29.old/drivers/isdn/hisax/elsa_ser.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/elsa_ser.c 2005-03-22 15:06:46.158075688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: elsa_ser.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: elsa_ser.c,v 2.14 2001/09/24 13:22:56 kai Exp $
+  *
+  * stuff for the serial modem on ELSA cards
+  *
+@@ -396,6 +396,74 @@
+       }
+ }
++#if 0
++static inline void check_modem_status(struct IsdnCardState *cs)
++{
++      int     status;
++      struct async_struct *info = cs->hw.elsa.info;
++      struct  async_icount *icount;
++      
++      status = serial_inp(info, UART_MSR);
++
++      if (status & UART_MSR_ANY_DELTA) {
++              icount = &info->state->icount;
++              /* update input line counters */
++              if (status & UART_MSR_TERI)
++                      icount->rng++;
++              if (status & UART_MSR_DDSR)
++                      icount->dsr++;
++              if (status & UART_MSR_DDCD) {
++                      icount->dcd++;
++              }
++              if (status & UART_MSR_DCTS)
++                      icount->cts++;
++//            wake_up(&info->delta_msr_wait);
++      }
++
++      if ((info->flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
++#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
++              printk("ttys%d CD now %s...", info->line,
++                     (status & UART_MSR_DCD) ? "on" : "off");
++#endif                
++              if (status & UART_MSR_DCD)
++//                    wake_up(&info->open_wait);
++;
++              else if (!((info->flags & ASYNC_CALLOUT_ACTIVE) &&
++                         (info->flags & ASYNC_CALLOUT_NOHUP))) {
++#ifdef SERIAL_DEBUG_OPEN
++                      printk("doing serial hangup...");
++#endif
++                      if (info->tty)
++                              tty_hangup(info->tty);
++              }
++      }
++#if 0
++      if (info->flags & ASYNC_CTS_FLOW) {
++              if (info->tty->hw_stopped) {
++                      if (status & UART_MSR_CTS) {
++#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
++                              printk("CTS tx start...");
++#endif
++                              info->tty->hw_stopped = 0;
++                              info->IER |= UART_IER_THRI;
++                              serial_outp(info, UART_IER, info->IER);
++//                            rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
++                              return;
++                      }
++              } else {
++                      if (!(status & UART_MSR_CTS)) {
++#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
++                              printk("CTS tx stop...");
++#endif
++                              info->tty->hw_stopped = 1;
++                              info->IER &= ~UART_IER_THRI;
++                              serial_outp(info, UART_IER, info->IER);
++                      }
++              }
++      }
++#endif 0
++}
++#endif
+ static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs)
+ {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/fsm.c linux-2.4.29/drivers/isdn/hisax/fsm.c
+--- linux-2.4.29.old/drivers/isdn/hisax/fsm.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/fsm.c      2005-03-22 15:06:46.174073256 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: fsm.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * Finite state machine
+  *
+@@ -21,6 +21,14 @@
+ #define FSM_TIMER_DEBUG 0
++EXPORT_SYMBOL(FsmNew);
++EXPORT_SYMBOL(FsmFree);
++EXPORT_SYMBOL(FsmEvent);
++EXPORT_SYMBOL(FsmChangeState);
++EXPORT_SYMBOL(FsmInitTimer);
++EXPORT_SYMBOL(FsmDelTimer);
++EXPORT_SYMBOL(FsmRestartTimer);
++
+ int __init
+ FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount)
+ {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/fsm.h linux-2.4.29/drivers/isdn/hisax/fsm.h
+--- linux-2.4.29.old/drivers/isdn/hisax/fsm.h  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/fsm.h      2005-03-22 15:06:46.189070976 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: fsm.h,v 1.1.2.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * Finite state machine
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/gazel.c linux-2.4.29/drivers/isdn/hisax/gazel.c
+--- linux-2.4.29.old/drivers/isdn/hisax/gazel.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/gazel.c    2005-03-22 15:06:46.205068544 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: gazel.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: gazel.c,v 2.19 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for Gazel isdn cards
+  *
+@@ -20,9 +20,10 @@
+ #include "isdnl1.h"
+ #include "ipac.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ extern const char *CardType[];
+-const char *gazel_revision = "$Revision: 1.1.4.1 $";
++const char *gazel_revision = "$Revision: 2.19 $";
+ #define R647      1
+ #define R685      2
+@@ -563,8 +564,8 @@
+                       if (pci_enable_device(dev_tel))
+                               return 1;
+                       pci_irq = dev_tel->irq;
+-                      pci_ioaddr0 = pci_resource_start(dev_tel, 1);
+-                      pci_ioaddr1 = pci_resource_start(dev_tel, 2);
++                      pci_ioaddr0 = pci_resource_start_io(dev_tel, 1);
++                      pci_ioaddr1 = pci_resource_start_io(dev_tel, 2);
+                       found = 1;
+               }
+               if (found)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.c linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.c        2005-03-22 15:06:46.221066112 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bds0.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bds0.c,v 1.18 2001/09/24 13:22:56 kai Exp $
+  *
+  * specific routines for CCD's HFC 2BDS0
+  *
+@@ -616,6 +616,17 @@
+ */
+       if (!cs)
+               return;
++#if 0 
++      if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
++              if (cs->debug)
++                      debugl1(cs, "D-Channel Busy cleared");
++              stptr = cs->stlist;
++              while (stptr != NULL) {
++                      stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
++                      stptr = stptr->next;
++              }
++      }
++#endif
+       if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+               switch (cs->dc.hfcd.ph_state) {
+                       case (0):
+@@ -1090,6 +1101,32 @@
+                       cs->hw.hfcD.mst_m |= HFCD_MASTER;
+                       cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m);
+                       break;
++#if 0
++              case (HW_TESTLOOP | REQUEST):
++                      u_char val = 0;
++                      if (1 & (int) arg)
++                              val |= 0x0c;
++                      if (2 & (int) arg)
++                              val |= 0x3;
++                      if (test_bit(HW_IOM1, &cs->HW_Flags)) {
++                              /* IOM 1 Mode */
++                              if (!val) {
++                                      cs->writeisac(cs, ISAC_SPCR, 0xa);
++                                      cs->writeisac(cs, ISAC_ADF1, 0x2);
++                              } else {
++                                      cs->writeisac(cs, ISAC_SPCR, val);
++                                      cs->writeisac(cs, ISAC_ADF1, 0xa);
++                              }
++                      } else {
++                              /* IOM 2 Mode */
++                              cs->writeisac(cs, ISAC_SPCR, val);
++                              if (val)
++                                      cs->writeisac(cs, ISAC_ADF1, 0x8);
++                              else
++                                      cs->writeisac(cs, ISAC_ADF1, 0x0);
++                      }
++                      break;
++#endif
+               default:
+                       if (cs->debug & L1_DEB_WARN)
+                               debugl1(cs, "hfcd_l1hw unknown pr %4x", pr);
+@@ -1106,6 +1143,20 @@
+ static void
+ hfc_dbusy_timer(struct IsdnCardState *cs)
+ {
++#if 0
++      struct PStack *stptr;
++      if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
++              if (cs->debug)
++                      debugl1(cs, "D-Channel Busy");
++              test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
++              stptr = cs->stlist;
++              
++              while (stptr != NULL) {
++                      stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
++                      stptr = stptr->next;
++              }
++      }
++#endif
+ }
+ unsigned int __init
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.h linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bds0.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bds0.h        2005-03-22 15:06:46.236063832 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bds0.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bds0.h,v 1.6 2001/09/24 13:22:56 kai Exp $
+  *
+  * specific defines for CCD's HFC 2BDS0
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.c linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.c 2005-03-22 15:06:46.272058360 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bs0.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bs0.c,v 1.20 2001/09/24 13:22:56 kai Exp $
+  *
+  * specific routines for CCD's HFC 2BS0
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.h linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_2bs0.h     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_2bs0.h 2005-03-22 15:06:46.288055928 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_2bs0.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_2bs0.h,v 1.5 2001/09/24 13:22:56 kai Exp $
+  *
+  * specific defines for CCD's HFC 2BS0
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.c linux-2.4.29/drivers/isdn/hisax/hfc_pci.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_pci.c  2005-03-22 15:06:46.305053344 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_pci.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_pci.c,v 1.48 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level driver for CCD´s hfc-pci based cards
+  *
+@@ -22,11 +22,12 @@
+ #include "hfc_pci.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+ extern const char *CardType[];
+-static const char *hfcpci_revision = "$Revision: 1.1.4.1 $";
++static const char *hfcpci_revision = "$Revision: 1.48 $";
+ /* table entry in the PCI devices list */
+ typedef struct {
+@@ -76,8 +77,6 @@
+ {
+       unsigned long flags;
+-      printk(KERN_INFO "HiSax: release hfcpci at %p\n",
+-              cs->hw.hfcpci.pci_io);
+       save_flags(flags);
+       cli();
+       cs->hw.hfcpci.int_m2 = 0;       /* interrupt output off ! */
+@@ -88,11 +87,13 @@
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_timeout((30 * HZ) / 1000);     /* Timeout 30ms */
+       Write_hfc(cs, HFCPCI_CIRM, 0);  /* Reset Off */
++#if CONFIG_PCI
+       pcibios_write_config_word(cs->hw.hfcpci.pci_bus, cs->hw.hfcpci.pci_device_fn, PCI_COMMAND, 0);  /* disable memory mapped ports + busmaster */
++#endif                                /* CONFIG_PCI */
+       del_timer(&cs->hw.hfcpci.timer);
+       kfree(cs->hw.hfcpci.share_start);
+       cs->hw.hfcpci.share_start = NULL;
+-      iounmap((void *)cs->hw.hfcpci.pci_io);
++      vfree(cs->hw.hfcpci.pci_io);
+ }
+ /********************************************************************************/
+@@ -687,10 +688,6 @@
+                               debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
+                                       bcs->channel, bcs->tx_skb->len);
+-                      if (bcs->st->lli.l1writewakeup &&
+-                           (PACKET_NOACK != bcs->tx_skb->pkt_type))
+-                              bcs->st->lli.l1writewakeup(bcs->st, bcs->tx_skb->len);
+-
+                       dev_kfree_skb_any(bcs->tx_skb);
+                       cli();
+                       bcs->tx_skb = skb_dequeue(&bcs->squeue);        /* fetch next data */
+@@ -1146,6 +1143,20 @@
+ static void
+ hfcpci_dbusy_timer(struct IsdnCardState *cs)
+ {
++#if 0
++      struct PStack *stptr;
++      if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
++              if (cs->debug)
++                      debugl1(cs, "D-Channel Busy");
++              test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
++              stptr = cs->stlist;
++
++              while (stptr != NULL) {
++                      stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
++                      stptr = stptr->next;
++              }
++      }
++#endif
+ }
+ /*************************************/
+@@ -1550,6 +1561,17 @@
+  */
+       if (!cs)
+               return;
++#if 0
++      if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
++              if (cs->debug)
++                      debugl1(cs, "D-Channel Busy cleared");
++              stptr = cs->stlist;
++              while (stptr != NULL) {
++                      stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
++                      stptr = stptr->next;
++              }
++      }
++#endif
+       if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+               if (!cs->hw.hfcpci.nt_mode)
+                       switch (cs->dc.hfcpci.ph_state) {
+@@ -1712,7 +1734,7 @@
+                               if (pci_enable_device(tmp_hfcpci))
+                                       continue;
+                               pci_set_master(tmp_hfcpci);
+-                              if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK)))
++                              if ((card->para[0]) && (card->para[0] != (get_pcibase(tmp_hfcpci, 0) & PCI_BASE_ADDRESS_IO_MASK)))
+                                       continue;
+                               else
+                                       break;
+@@ -1729,7 +1751,7 @@
+                               printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
+                               return (0);
+                       }
+-                      cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start;
++                      cs->hw.hfcpci.pci_io = (char *) get_pcibase(dev_hfcpci, 1);
+                       printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
+               } else {
+                       printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
+@@ -1746,7 +1768,7 @@
+                       printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
+                       return 0;
+               }
+-              cs->hw.hfcpci.fifos = (void *)
++              (ulong) cs->hw.hfcpci.fifos =
+                   (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
+               pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
+                                      cs->hw.hfcpci.pci_device_fn, 0x80,
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.h linux-2.4.29/drivers/isdn/hisax/hfc_pci.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_pci.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_pci.h  2005-03-22 15:06:46.320051064 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_pci.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_pci.h,v 1.10 2001/09/24 13:22:56 kai Exp $
+  *
+  * specific defines for CCD's HFC 2BDS0 PCI chips
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.c linux-2.4.29/drivers/isdn/hisax/hfc_sx.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_sx.c   2005-03-22 15:06:46.350046504 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_sx.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfc_sx.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+  *
+  * level driver for CCD´s hfc-s+/sp based cards
+  *
+@@ -17,11 +17,10 @@
+ #include "hfc_sx.h"
+ #include "isdnl1.h"
+ #include <linux/interrupt.h>
+-#include <linux/isapnp.h>
+ extern const char *CardType[];
+-static const char *hfcsx_revision = "$Revision: 1.1.4.1 $";
++static const char *hfcsx_revision = "$Revision: 1.12 $";
+ /***************************************/
+ /* IRQ-table for CCDs demo board       */
+@@ -940,6 +939,20 @@
+ static void
+ hfcsx_dbusy_timer(struct IsdnCardState *cs)
+ {
++#if 0
++      struct PStack *stptr;
++      if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) {
++              if (cs->debug)
++                      debugl1(cs, "D-Channel Busy");
++              test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags);
++              stptr = cs->stlist;
++
++              while (stptr != NULL) {
++                      stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL);
++                      stptr = stptr->next;
++              }
++      }
++#endif
+ }
+ /*************************************/
+@@ -1333,6 +1346,17 @@
+  */
+       if (!cs)
+               return;
++#if 0
++      if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) {
++              if (cs->debug)
++                      debugl1(cs, "D-Channel Busy cleared");
++              stptr = cs->stlist;
++              while (stptr != NULL) {
++                      stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL);
++                      stptr = stptr->next;
++              }
++      }
++#endif
+       if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
+               if (!cs->hw.hfcsx.nt_mode)
+                       switch (cs->dc.hfcsx.ph_state) {
+@@ -1461,17 +1485,7 @@
+       return (0);
+ }
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id hfc_ids[] __initdata = {
+-      { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620),
+-        ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2620), 
+-        (unsigned long) "Teles 16.3c2" },
+-      { 0, }
+-};
+-static struct isapnp_device_id *hdev = &hfc_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+ int __devinit
+ setup_hfcsx(struct IsdnCard *card)
+@@ -1482,45 +1496,6 @@
+       strcpy(tmp, hfcsx_revision);
+       printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp));
+-#ifdef __ISAPNP__
+-      if (!card->para[1] && isapnp_present()) {
+-              struct pci_bus *pb;
+-              struct pci_dev *pd;
+-
+-              while(hdev->card_vendor) {
+-                      if ((pb = isapnp_find_card(hdev->card_vendor,
+-                              hdev->card_device, pnp_c))) {
+-                              pnp_c = pb;
+-                              pd = NULL;
+-                              if ((pd = isapnp_find_dev(pnp_c,
+-                                      hdev->vendor, hdev->function, pd))) {
+-                                      printk(KERN_INFO "HiSax: %s detected\n",
+-                                              (char *)hdev->driver_data);
+-                                      pd->prepare(pd);
+-                                      pd->deactivate(pd);
+-                                      pd->activate(pd);
+-                                      card->para[1] = pd->resource[0].start;
+-                                      card->para[0] = pd->irq_resource[0].start;
+-                                      if (!card->para[0] || !card->para[1]) {
+-                                              printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
+-                                              card->para[0], card->para[1]);
+-                                              pd->deactivate(pd);
+-                                              return(0);
+-                                      }
+-                                      break;
+-                              } else {
+-                                      printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
+-                              }
+-                      }
+-                      hdev++;
+-                      pnp_c=NULL;
+-              } 
+-              if (!hdev->card_vendor) {
+-                      printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
+-                      return(0);
+-              }
+-      }
+-#endif
+       cs->hw.hfcsx.base = card->para[1] & 0xfffe;
+       cs->irq = card->para[0];
+       cs->hw.hfcsx.int_s1 = 0;
+@@ -1603,3 +1578,7 @@
+       cs->auxcmd = &hfcsx_auxcmd;
+       return (1);
+ }
++
++
++
++
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.h linux-2.4.29/drivers/isdn/hisax/hfc_sx.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_sx.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_sx.h   2005-03-22 15:06:46.365044224 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfc_sx.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id$
+  *
+  * specific defines for CCD's HFC 2BDS0 S+,SP chips
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c linux-2.4.29/drivers/isdn/hisax/hfc_usb.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_usb.c  2005-03-22 15:06:46.381041792 +0100
+@@ -0,0 +1,1189 @@
++/* $Id: hfc_usb.c,v 2.3 2001/07/06 21:30:11 werner Exp $
++ *
++ *
++ *
++ * Author       (C) 2001 Werner Cornelius (werner@isdn-development.de)
++ *              modular driver for Colognechip HFC-USB chip
++ *              as plugin for HiSax isdn driver
++ *              type approval valid for HFC-S USB based TAs
++ *
++ * Copyright 2001  by Werner Cornelius (werner@isdn-development.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)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * 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.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/stddef.h>
++#include <linux/timer.h>
++#include <linux/config.h>
++#include <linux/isdn_compat.h>
++#include <linux/init.h>
++#include "hisax.h"
++#include <linux/module.h>
++#include <linux/kernel_stat.h>
++#include <linux/tqueue.h>
++#include <linux/usb.h>
++#include <linux/kernel.h>
++#include <linux/smp_lock.h>
++#include <linux/sched.h>
++#include "hisax_loadable.h"
++
++#define INCLUDE_INLINE_FUNCS
++
++/***********/
++/* defines */
++/***********/
++#define HFC_CTRL_TIMEOUT 5    /* 5ms timeout writing/reading regs */
++#define HFC_TIMER_T3     7000 /* timeout for l1 activation timer */
++
++#define HFCUSB_L1_STATECHANGE   0     /* L1 state changed */
++#define HFCUSB_L1_DRX           1     /* D-frame received */
++#define HFCUSB_L1_ERX           2     /* E-frame received */
++#define HFCUSB_L1_DTX           4     /* D-frames completed */
++
++#define MAX_BCH_SIZE        2048      /* allowed B-channel packet size */
++
++#define HFCUSB_RX_THRESHOLD 64        /* threshold for fifo report bit rx */
++#define HFCUSB_TX_THRESHOLD 64        /* threshold for fifo report bit tx */
++
++#define HFCUSB_CHIP_ID    0x16        /* Chip ID register index */
++#define HFCUSB_CIRM       0x00        /* cirm register index */
++#define HFCUSB_USB_SIZE   0x07        /* int length register */
++#define HFCUSB_USB_SIZE_I 0x06        /* iso length register */
++#define HFCUSB_F_CROSS    0x0b        /* bit order register */
++#define HFCUSB_CLKDEL     0x37        /* bit delay register */
++#define HFCUSB_CON_HDLC   0xfa        /* channel connect register */
++#define HFCUSB_HDLC_PAR   0xfb
++#define HFCUSB_SCTRL      0x31        /* S-bus control register (tx) */
++#define HFCUSB_SCTRL_E    0x32        /* same for E and special funcs */
++#define HFCUSB_SCTRL_R    0x33        /* S-bus control register (rx) */
++#define HFCUSB_F_THRES    0x0c        /* threshold register */
++#define HFCUSB_FIFO       0x0f        /* fifo select register */
++#define HFCUSB_F_USAGE    0x1a        /* fifo usage register */
++#define HFCUSB_MST_MODE0  0x14
++#define HFCUSB_MST_MODE1  0x15
++#define HFCUSB_P_DATA     0x1f
++#define HFCUSB_INC_RES_F  0x0e
++#define HFCUSB_STATES     0x30
++
++#define HFCUSB_CHIPID 0x40    /* ID value of HFC-USB */
++
++/******************/
++/* fifo registers */
++/******************/
++#define HFCUSB_NUM_FIFOS   8  /* maximum number of fifos */
++#define HFCUSB_B1_TX       0  /* index for B1 transmit bulk/int */
++#define HFCUSB_B1_RX       1  /* index for B1 receive bulk/int */
++#define HFCUSB_B2_TX       2
++#define HFCUSB_B2_RX       3
++#define HFCUSB_D_TX        4
++#define HFCUSB_D_RX        5
++#define HFCUSB_PCM_TX      6
++#define HFCUSB_PCM_RX      7
++
++/************/
++/* LED mask */
++/************/
++#define LED_DRIVER         0x1
++#define LED_L1             0x2
++#define LED_BCH            0x4
++
++/**********/
++/* macros */
++/**********/
++#define Write_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
++#define Read_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
++
++#ifdef COMPAT_HAS_USB_IDTAB
++/****************************************/
++/* data defining the devices to be used */
++/****************************************/
++static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
++      {USB_DEVICE(0x959, 0x2bd0)},    /* Colognechip ROM */
++      {USB_DEVICE(0x7b0, 0x0006)},    /* USB TA 128 */
++      {}                      /* end with an all-zeroes entry */
++};
++#endif
++
++/*************************************************/
++/* entry and size of output/input control buffer */
++/*************************************************/
++#define HFC_CTRL_BUFSIZE 32
++typedef struct {
++      __u8 hfc_reg;           /* register number */
++      __u8 reg_val;           /* value to be written (or read) */
++} ctrl_buft;
++
++/***************************************************************/
++/* structure defining input+output fifos (interrupt/bulk mode) */
++/***************************************************************/
++struct hfcusb_data;           /* forward definition */
++typedef struct {
++      int fifonum;            /* fifo index attached to this structure */
++      __u8 fifo_mask;         /* mask for this fifo */
++      int active;             /* fifo is currently active */
++      struct hfcusb_data *hfc;        /* pointer to main structure */
++      int pipe;               /* address of endpoint */
++      __u8 usb_maxlen;        /* maximum length for usb transfer */
++      int max_size;           /* maximum size of receive/send packet */
++      int transmode;          /* transparent mode selected */
++      int framenum;           /* number of frame when last tx completed */
++      int rx_offset;          /* offset inside rx buffer */
++      int next_complete;      /* complete marker */
++      __u8 *act_ptr;          /* pointer to next data */
++      __u8 intervall;         /* interrupt interval */
++      struct sk_buff *buff;   /* actual used buffer */
++      urb_t urb;              /* transfer structure for usb routines */
++      __u8 buffer[128];       /* buffer incoming/outgoing data */
++} usb_fifo;
++
++/*********************************************/
++/* structure holding all data for one device */
++/*********************************************/
++typedef struct hfcusb_data {
++      struct hisax_drvreg regd;       /* register data and callbacks */
++      struct usb_device *dev; /* our device */
++      int if_used;            /* used interface number */
++      int alt_used;           /* used alternate config */
++      int ctrl_paksize;       /* control pipe packet size */
++      int ctrl_in_pipe, ctrl_out_pipe;        /* handles for control pipe */
++
++      /* control pipe background handling */
++      ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE];  /* buffer holding queued data */
++      volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt;       /* input/output pointer + count */
++      urb_t ctrl_urb;         /* transfer structure for control channel */
++      devrequest ctrl_write;  /* buffer for control write request */
++      devrequest ctrl_read;   /* same for read request */
++
++      volatile __u8 dfifo_fill;       /* value read from tx d-fifo */
++      volatile __u8 active_fifos;     /* fifos currently active as bit mask */
++      volatile __u8 threshold_mask;   /* threshold actually reported */
++      volatile __u8 service_request;  /* fifo needs service from task */
++      volatile __u8 ctrl_fifo;        /* last selected fifo */
++      volatile __u8 bch_enables;      /* or mask for sctrl_r and sctrl register values */
++        volatile __u8 led_req;          /* request status of adapters leds */ 
++        volatile __u8 led_act;          /* active status of adapters leds */ 
++      usb_fifo fifos[HFCUSB_NUM_FIFOS];       /* structure holding all fifo data */
++
++      /* layer 1 activation/deactivation handling */
++      volatile __u8 l1_state; /* actual l1 state */
++      volatile ulong l1_event;        /* event mask */
++      struct tq_struct l1_tq; /* l1 bh structure */
++      struct timer_list t3_timer;     /* timer for activation/deactivation */
++      struct timer_list t4_timer;     /* timer for activation/deactivation */
++} hfcusb_data;
++
++#if 0
++static void
++usb_dump_urb(purb_t purb)
++{
++      printk("urb                   :%p\n", purb);
++      printk("next                  :%p\n", purb->next);
++      printk("dev                   :%p\n", purb->dev);
++      printk("pipe                  :%08X\n", purb->pipe);
++      printk("status                :%d\n", purb->status);
++      printk("transfer_flags        :%08X\n", purb->transfer_flags);
++      printk("transfer_buffer       :%p\n", purb->transfer_buffer);
++      printk("transfer_buffer_length:%d\n",
++             purb->transfer_buffer_length);
++      printk("actual_length         :%d\n", purb->actual_length);
++      printk("setup_packet          :%p\n", purb->setup_packet);
++      printk("start_frame           :%d\n", purb->start_frame);
++      printk("number_of_packets     :%d\n", purb->number_of_packets);
++      printk("interval              :%d\n", purb->interval);
++      printk("error_count           :%d\n", purb->error_count);
++      printk("context               :%p\n", purb->context);
++      printk("complete              :%p\n", purb->complete);
++}
++#endif
++
++/*************************************************************************/
++/* bottom half handler for L1 activation/deactiavtaion + D-chan + E-chan */
++/*************************************************************************/
++static void
++usb_l1d_bh(hfcusb_data * hfc)
++{
++
++      while (hfc->l1_event) {
++              if (test_and_clear_bit
++                  (HFCUSB_L1_STATECHANGE, &hfc->l1_event)) {
++                      if (hfc->l1_state == 7)
++                          hfc->led_req |= LED_L1;
++                      else
++                          hfc->led_req &= ~LED_L1;
++                      if ((hfc->l1_state == 7) ||
++                          (hfc->l1_state == 3))
++                          hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++                                             (hfc->l1_state ==
++                                              7) ? (PH_ACTIVATE |
++                                                    INDICATION)
++                                             : (PH_DEACTIVATE | INDICATION),
++                                             NULL);
++              }
++              if (test_and_clear_bit(HFCUSB_L1_DRX, &hfc->l1_event)) {
++                      hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++                                         PH_DATA | INDICATION,
++                                         (void *) 0);
++              }
++              if (test_and_clear_bit(HFCUSB_L1_ERX, &hfc->l1_event)) {
++                      hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++                                         PH_DATA | INDICATION,
++                                         (void *) 1);
++              }
++              if (test_and_clear_bit(HFCUSB_L1_DTX, &hfc->l1_event)) {
++                      hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++                                         PH_DATA | CONFIRM, NULL);
++              }
++      }                       /* while */
++}                             /* usb_l1d_bh */
++
++/******************************************************/
++/* start next background transfer for control channel */
++/******************************************************/
++static void
++ctrl_start_transfer(hfcusb_data * hfc)
++{
++
++      if (hfc->ctrl_cnt) {
++              switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
++                      case HFCUSB_F_USAGE:
++                              hfc->ctrl_urb.pipe = hfc->ctrl_in_pipe;
++                              hfc->ctrl_urb.setup_packet =
++                                  (u_char *) & hfc->ctrl_read;
++                              hfc->ctrl_urb.transfer_buffer_length = 1;
++                              hfc->ctrl_read.index =
++                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
++                                  hfc_reg;
++                              hfc->ctrl_urb.transfer_buffer =
++                                  (char *) &hfc->dfifo_fill;
++                              break;
++
++                      default:        /* write register */
++                              hfc->ctrl_urb.pipe = hfc->ctrl_out_pipe;
++                              hfc->ctrl_urb.setup_packet =
++                                  (u_char *) & hfc->ctrl_write;
++                              hfc->ctrl_urb.transfer_buffer = NULL;
++                              hfc->ctrl_urb.transfer_buffer_length = 0;
++                              hfc->ctrl_write.index =
++                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
++                                  hfc_reg;
++                              hfc->ctrl_write.value =
++                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
++                                  reg_val;
++                              break;
++              }
++              usb_submit_urb(&hfc->ctrl_urb); /* start transfer */
++      }
++}                             /* ctrl_start_transfer */
++
++/************************************/
++/* queue a control transfer request */
++/* return 0 on success.             */
++/************************************/
++static int
++queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val)
++{
++      ctrl_buft *buf;
++
++      if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)
++              return (1);     /* no space left */
++      buf = hfc->ctrl_buff + hfc->ctrl_in_idx;        /* pointer to new index */
++      buf->hfc_reg = reg;
++      buf->reg_val = val;
++      if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
++              hfc->ctrl_in_idx = 0;   /* pointer wrap */
++      if (++hfc->ctrl_cnt == 1)
++              ctrl_start_transfer(hfc);
++      return (0);
++}                             /* queue_control_request */
++
++/**************************************/
++/* called when timer t3 or t4 expires */
++/**************************************/
++static void
++l1_timer_expire(hfcusb_data * hfc)
++{
++    if (timer_pending(&hfc->t4_timer))
++      del_timer(&hfc->t4_timer);
++    queue_control_request(hfc, HFCUSB_STATES, 0x40);
++    test_and_set_bit(HFCUSB_L1_STATECHANGE,
++                   &hfc->l1_event);
++    queue_task(&hfc->l1_tq, &tq_immediate);
++    mark_bh(IMMEDIATE_BH);
++} /* l1_timer_expire */
++
++/**************************************************/
++/* (re)fills a tx-fifo urb. Queuing is done later */
++/**************************************************/
++static void
++fill_tx_urb(usb_fifo * fifo)
++{
++      struct sk_buff *skb;
++      long flags;
++      int i, ii = 0;
++
++      fifo->urb.dev = fifo->hfc->dev;
++      if ((fifo->buff)
++          && (fifo->urb.transfer_buffer_length < fifo->usb_maxlen)) {
++              switch (fifo->fifonum) {
++                      case HFCUSB_B1_TX:
++                      case HFCUSB_B2_TX:
++                              skb = fifo->buff;
++                              fifo->buff = NULL;
++                              fifo->hfc->regd.bch_l1l2(fifo->hfc->regd.
++                                                       arg_hisax,
++                                                       (fifo->fifonum ==
++                                                        HFCUSB_B1_TX) ? 0
++                                                       : 1,
++                                                       (PH_DATA |
++                                                        CONFIRM),
++                                                       (void *) skb);
++                              fifo->hfc->service_request |=
++                                  fifo->fifo_mask;
++                              return;
++                      case HFCUSB_D_TX:
++                              dev_kfree_skb_any(fifo->buff);
++                              fifo->buff = NULL;
++                              save_flags(flags);
++                              cli();
++                              fifo->hfc->dfifo_fill = 0xff;   /* currently invalid data */
++                              queue_control_request(fifo->hfc,
++                                                    HFCUSB_FIFO,
++                                                    HFCUSB_D_TX);
++                              queue_control_request(fifo->hfc,
++                                                    HFCUSB_F_USAGE, 0);
++                              restore_flags(flags);
++                              return;
++                      default:
++                              return; /* error, invalid fifo */
++              }
++      }
++
++      /* check if new buffer needed */
++      if (!fifo->buff) {
++              switch (fifo->fifonum) {
++                      case HFCUSB_B1_TX:
++                              if (fifo->hfc->regd.bsk[0])
++                                      fifo->buff = *fifo->hfc->regd.bsk[0];   /* B1-channel tx buffer */
++                              break;
++                      case HFCUSB_B2_TX:
++                              if (fifo->hfc->regd.bsk[1])
++                                      fifo->buff = *fifo->hfc->regd.bsk[1];   /* B2-channel tx buffer */
++                              break;
++                      case HFCUSB_D_TX:
++                              if (fifo->hfc->regd.dsq)
++                                      fifo->buff = skb_dequeue(fifo->hfc->regd.dsq);  /* D-channel tx queue */
++                              break;
++                      default:
++                              return; /* error, invalid fifo */
++              }
++              if (!fifo->buff) {
++                      fifo->active = 0;       /* we are inactive now */
++                      fifo->hfc->active_fifos &= ~fifo->fifo_mask;
++                      if (fifo->fifonum == HFCUSB_D_TX) {
++                              test_and_set_bit(HFCUSB_L1_DTX,
++                                               &fifo->hfc->l1_event);
++                              queue_task(&fifo->hfc->l1_tq,
++                                         &tq_immediate);
++                              mark_bh(IMMEDIATE_BH);
++                      }
++                      return;
++              }
++              fifo->act_ptr = fifo->buff->data;       /* start of data */
++              fifo->active = 1;
++              ii = 1;
++              fifo->hfc->active_fifos |= fifo->fifo_mask;
++              fifo->hfc->service_request &= ~fifo->fifo_mask;
++      }
++      /* fillup the send buffer */
++      i = fifo->buff->len - (fifo->act_ptr - fifo->buff->data);       /* remaining length */
++      fifo->buffer[0] = !fifo->transmode;     /* not eof */
++      if (i > (fifo->usb_maxlen - ii)) {
++              i = fifo->usb_maxlen - ii;
++      }
++      if (i)
++              memcpy(fifo->buffer + ii, fifo->act_ptr, i);
++      fifo->urb.transfer_buffer_length = i + ii;
++        fifo->rx_offset = ii;
++}                             /* fill_tx_urb */
++
++/************************************************/
++/* transmit completion routine for all tx fifos */
++/************************************************/
++static void
++tx_complete(purb_t urb)
++{
++      usb_fifo *fifo = (usb_fifo *) urb->context;     /* pointer to our fifo */
++
++      fifo->hfc->service_request &= ~fifo->fifo_mask; /* no further handling */
++      fifo->framenum = usb_get_current_frame_number(fifo->hfc->dev);
++
++      /* check for deactivation or error */
++      if ((!fifo->active) || (urb->status)) {
++              fifo->hfc->active_fifos &= ~fifo->fifo_mask;    /* we are inactive */
++              fifo->active = 0;
++              if ((fifo->buff) && (fifo->fifonum == HFCUSB_D_TX)) {
++                      dev_kfree_skb_any(fifo->buff);
++              }
++              fifo->buff = NULL;
++              return;
++      }
++      fifo->act_ptr += (urb->transfer_buffer_length - fifo->rx_offset);       /* adjust pointer */
++      fill_tx_urb(fifo);      /* refill the urb */
++      fifo->hfc->threshold_mask |= fifo->fifo_mask;   /* assume threshold reached */
++      if (fifo->buff)
++              fifo->hfc->service_request |= fifo->fifo_mask;  /* need to restart */
++}                             /* tx_complete */
++
++/***********************************************/
++/* receive completion routine for all rx fifos */
++/***********************************************/
++static void
++rx_complete(purb_t urb)
++{
++      usb_fifo *fifo = (usb_fifo *) urb->context;     /* pointer to our fifo */
++      hfcusb_data *hfc = fifo->hfc;
++      usb_fifo *txfifo;
++      __u8 last_state;
++      int i, ii, currcnt, hdlci;
++      struct sk_buff *skb;
++
++      urb->dev = hfc->dev; /* security init */
++      if ((!fifo->active) || (urb->status)) {
++              hfc->service_request &= ~fifo->fifo_mask;       /* no further handling */
++              hfc->active_fifos &= ~fifo->fifo_mask;  /* we are inactive */
++              fifo->urb.interval = 0; /* cancel automatic rescheduling */
++              if (fifo->buff) {
++                      dev_kfree_skb_any(fifo->buff);
++                      fifo->buff = NULL;
++              }
++              return;
++      }
++
++      /* first check for any status changes */
++      if ((urb->actual_length < fifo->rx_offset)
++          || (urb->actual_length > fifo->usb_maxlen))
++              return;         /* error condition */
++
++      if (fifo->rx_offset) {
++              hfc->threshold_mask = fifo->buffer[1];  /* update threshold status */
++              fifo->next_complete = fifo->buffer[0] & 1;
++              if ((fifo->fifonum == HFCUSB_D_RX) &&
++                  (hfc->led_req != hfc->led_act))
++                  queue_control_request(hfc, HFCUSB_P_DATA, hfc->led_req);
++
++              /* check if rescheduling needed */
++              if ((i =
++                   hfc->service_request & hfc->active_fifos & ~hfc->
++                   threshold_mask)) {
++                      currcnt =
++                          usb_get_current_frame_number(hfc->dev);
++                      txfifo = hfc->fifos + HFCUSB_B1_TX;
++                      ii = 3;
++                      while (ii--) {
++                              if ((i & txfifo->fifo_mask)
++                                  && (currcnt != txfifo->framenum)) {
++                                      hfc->service_request &=
++                                          ~txfifo->fifo_mask;
++                                      if (!txfifo->buff)
++                                              fill_tx_urb(txfifo);
++                                      if (txfifo->buff)
++                                              usb_submit_urb(&txfifo->
++                                                             urb);
++                              }
++                              txfifo += 2;
++                      }
++              }
++
++              /* handle l1 events */
++              if ((fifo->buffer[0] >> 4) != hfc->l1_state) {
++                      last_state = hfc->l1_state;
++                      hfc->l1_state = fifo->buffer[0] >> 4;   /* update status */
++                      if (timer_pending(&hfc->t4_timer))
++                          del_timer(&hfc->t4_timer);
++                      if (((hfc->l1_state == 3) && 
++                           ((last_state == 7) || 
++                            (last_state == 8))) || 
++                          ((timer_pending(&hfc->t3_timer) &&
++                          (hfc->l1_state == 8)))) {
++                          hfc->t4_timer.expires = jiffies + 2;
++                          add_timer(&hfc->t4_timer);
++                      } else { 
++                              if (timer_pending(&hfc->t3_timer)
++                                  && (hfc->l1_state == 7))
++                                      del_timer(&hfc->t3_timer);      /* no longer needed */
++                              test_and_set_bit(HFCUSB_L1_STATECHANGE,
++                                               &hfc->l1_event);
++                              queue_task(&hfc->l1_tq, &tq_immediate);
++                              mark_bh(IMMEDIATE_BH);
++                      }
++              }
++      }
++
++      /* check the length for data and move if present */
++      if (fifo->next_complete || (urb->actual_length > fifo->rx_offset)) {
++              i = fifo->buff->len + urb->actual_length - fifo->rx_offset;     /* new total length */
++              hdlci = (fifo->transmode) ? 0 : 3;
++              if (i <= (fifo->max_size + hdlci)) {
++                      memcpy(fifo->act_ptr,
++                             fifo->buffer + fifo->rx_offset,
++                             urb->actual_length - fifo->rx_offset);
++                      fifo->act_ptr +=
++                          (urb->actual_length - fifo->rx_offset);
++                      fifo->buff->len +=
++                          (urb->actual_length - fifo->rx_offset);
++              } else
++                      fifo->buff->len = fifo->max_size + 4;   /* mark frame as to long */
++              if (fifo->next_complete && (urb->actual_length < fifo->usb_maxlen)) {
++                  /* the frame is complete */
++                  fifo->next_complete = 0;
++                  if (((!*(fifo->act_ptr - 1)) || fifo->transmode) &&
++                      (fifo->buff->len >= (hdlci + 1))
++                      && (fifo->buff->len <=
++                          (fifo->max_size + hdlci)) &&
++                      ((skb = dev_alloc_skb(fifo->max_size + hdlci)) != NULL)) {
++                      fifo->buff->len -= hdlci;       /* adjust size */
++                      switch (fifo->fifonum) {
++                          case HFCUSB_D_RX:
++                              skb_queue_tail(hfc->regd.
++                                             drq,
++                                             fifo->buff);
++                              test_and_set_bit
++                                  (HFCUSB_L1_DRX,
++                                   &hfc->l1_event);
++                              queue_task(&hfc->l1_tq,
++                                         &tq_immediate);
++                              mark_bh(IMMEDIATE_BH);
++                              break;
++
++                          case HFCUSB_B1_RX:
++                              if (hfc->regd.brq[0]) {
++                                  skb_queue_tail
++                                      (hfc->regd.
++                                       brq[0],
++                                       fifo->buff);
++                                  hfc->regd.
++                                      bch_l1l2(hfc->
++                                               regd.
++                                               arg_hisax,
++                                               0,
++                                               PH_DATA
++                                               |
++                                               INDICATION,
++                                               (void *)
++                                               fifo->
++                                               buff);
++                              } else
++                                  dev_kfree_skb_any
++                                      (fifo->buff);
++                              break;
++                              
++                          case HFCUSB_B2_RX:
++                              if (hfc->regd.brq[1]) {
++                                  skb_queue_tail
++                                      (hfc->regd.
++                                       brq[1],
++                                       fifo->buff);
++                                  hfc->regd.
++                                      bch_l1l2(hfc->
++                                               regd.
++                                               arg_hisax,
++                                               1,
++                                               PH_DATA
++                                               |
++                                               INDICATION,
++                                               (void
++                                                *)
++                                               fifo->
++                                               buff);
++                              } else
++                                  dev_kfree_skb_any
++                                      (fifo->buff);
++                              break;
++
++                          case HFCUSB_PCM_RX:
++                              skb_queue_tail(&hfc->regd.
++                                             erq,
++                                             fifo->buff);
++                              test_and_set_bit
++                                  (HFCUSB_L1_ERX,
++                                   &hfc->l1_event);
++                              queue_task(&hfc->l1_tq,
++                                         &tq_immediate);
++                              mark_bh(IMMEDIATE_BH);
++                              break;
++
++                          default:
++                              dev_kfree_skb_any(fifo->
++                                                buff);
++                              break;
++                      }
++                      fifo->buff = skb;
++                  } 
++                  fifo->buff->len = 0;        /* reset counter */
++                  fifo->act_ptr = fifo->buff->data;   /* and pointer */
++              }
++      }
++      fifo->rx_offset = (urb->actual_length < fifo->usb_maxlen) ? 2 : 0;
++}                             /* rx_complete */
++
++/***************************************************/
++/* start the interrupt transfer for the given fifo */
++/***************************************************/
++static void
++start_rx_fifo(usb_fifo * fifo)
++{
++      if (fifo->buff)
++              return;         /* still active */
++      if (!
++          (fifo->buff =
++           dev_alloc_skb(fifo->max_size + (fifo->transmode ? 0 : 3))))
++              return;
++      fifo->act_ptr = fifo->buff->data;
++      FILL_INT_URB(&fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
++                   fifo->usb_maxlen, rx_complete, fifo, fifo->intervall);
++      fifo->next_complete = 0;
++      fifo->rx_offset = 2;
++      fifo->active = 1;       /* must be marked active */
++      fifo->hfc->active_fifos |= fifo->fifo_mask;
++      if (usb_submit_urb(&fifo->urb)) {
++              fifo->active = 0;
++              fifo->hfc->active_fifos &= ~fifo->fifo_mask;
++              dev_kfree_skb_any(fifo->buff);
++              fifo->buff = NULL;
++      }
++}                             /* start_rx_fifo */
++
++/***************************************************************/
++/* control completion routine handling background control cmds */
++/***************************************************************/
++static void
++ctrl_complete(purb_t urb)
++{
++      hfcusb_data *hfc = (hfcusb_data *) urb->context;
++
++      urb->dev = hfc->dev;
++      if (hfc->ctrl_cnt) {
++              switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
++                      case HFCUSB_FIFO:
++                              hfc->ctrl_fifo =
++                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
++                                  reg_val;
++                              break;
++                      case HFCUSB_F_USAGE:
++                              if (!hfc->dfifo_fill) {
++                                      fill_tx_urb(hfc->fifos +
++                                                  HFCUSB_D_TX);
++                                      if (hfc->fifos[HFCUSB_D_TX].buff)
++                                              usb_submit_urb(&hfc->
++                                                             fifos
++                                                             [HFCUSB_D_TX].
++                                                             urb);
++                              } else {
++                                      queue_control_request(hfc,
++                                                            HFCUSB_FIFO,
++                                                            HFCUSB_D_TX);
++                                      queue_control_request(hfc,
++                                                            HFCUSB_F_USAGE,
++                                                            0);
++                              }
++                              break;
++                      case HFCUSB_SCTRL_R:
++                              switch (hfc->ctrl_fifo) {
++                                      case HFCUSB_B1_RX:
++                                              if (hfc->bch_enables & 1)
++                                                      start_rx_fifo(hfc->
++                                                                    fifos
++                                                                    +
++                                                                    HFCUSB_B1_RX);
++                                              break;
++                                      case HFCUSB_B2_RX:
++                                              if (hfc->bch_enables & 2)
++                                                      start_rx_fifo(hfc->
++                                                                    fifos
++                                                                    +
++                                                                    HFCUSB_B2_RX);
++                                              break;
++                              }
++                              if (hfc->bch_enables & 3)
++                                  hfc->led_req |= LED_BCH;
++                              else
++                                  hfc->led_req &= ~LED_BCH;
++                              break;
++                      case HFCUSB_P_DATA:
++                              hfc->led_act =
++                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
++                                  reg_val;
++                              break;
++              }
++              hfc->ctrl_cnt--;        /* decrement actual count */
++              if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
++                      hfc->ctrl_out_idx = 0;  /* pointer wrap */
++              ctrl_start_transfer(hfc);       /* start next transfer */
++      }
++}                             /* ctrl_complete */
++
++/*****************************************/
++/* Layer 1 + D channel access from HiSax */
++/*****************************************/
++static void
++hfcusb_l1_access(void *drvarg, int pr, void *arg)
++{
++      hfcusb_data *hfc = (hfcusb_data *) drvarg;
++
++      switch (pr) {
++              case (PH_DATA | REQUEST):
++              case (PH_PULL | INDICATION):
++                      skb_queue_tail(hfc->regd.dsq,
++                                     (struct sk_buff *) arg);
++                      if (!hfc->fifos[HFCUSB_D_TX].active
++                          && !hfc->dfifo_fill) {
++                              fill_tx_urb(hfc->fifos + HFCUSB_D_TX);
++                              hfc->active_fifos |=
++                                  hfc->fifos[HFCUSB_D_TX].fifo_mask;
++                              usb_submit_urb(&hfc->fifos[HFCUSB_D_TX].
++                                             urb);
++                      }
++                      break;
++              case (PH_ACTIVATE | REQUEST):
++                  switch (hfc->l1_state) {
++                      case 6:
++                      case 8:
++                              hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++                                                 (PH_DEACTIVATE |
++                                                 INDICATION), NULL);
++
++                              break;
++                      case 7:
++                              hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
++                                                 (PH_ACTIVATE |
++                                                 INDICATION), NULL);
++
++                              break;
++                      default:
++                              queue_control_request(hfc, HFCUSB_STATES, 0x60);        /* start activation */
++                              hfc->t3_timer.expires =
++                                  jiffies + (HFC_TIMER_T3 * HZ) / 1000;
++                              if (!timer_pending(&hfc->t3_timer))
++                                      add_timer(&hfc->t3_timer);
++                              break;
++                  }
++                  break;
++
++              case (PH_DEACTIVATE | REQUEST):
++                      queue_control_request(hfc, HFCUSB_STATES, 0x40);        /* start deactivation */
++                      break;
++              default:
++                      printk(KERN_INFO "unknown hfcusb l1_access 0x%x\n",
++                             pr);
++                      break;
++      }
++}                             /* hfcusb_l1_access */
++
++/*******************************/
++/* B channel access from HiSax */
++/*******************************/
++static void
++hfcusb_bch_access(void *drvarg, int chan, int pr, void *arg)
++{
++      hfcusb_data *hfc = (hfcusb_data *) drvarg;
++      usb_fifo *fifo = hfc->fifos + (chan ? HFCUSB_B2_TX : HFCUSB_B1_TX);
++      long flags;
++
++      switch (pr) {
++              case (PH_DATA | REQUEST):
++              case (PH_PULL | INDICATION):
++                      save_flags(flags);
++                      cli();
++                      if (!fifo->active) {
++                              fill_tx_urb(fifo);
++                              hfc->active_fifos |= fifo->fifo_mask;
++                              usb_submit_urb(&fifo->urb);
++                      }
++                      restore_flags(flags);
++                      break;
++              case (PH_ACTIVATE | REQUEST):
++                      if (!((int) arg)) {
++                              hfc->bch_enables &= ~(1 << chan);
++                              if (fifo->active) {
++                                      fifo->active = 0;
++                                      usb_unlink_urb(&fifo->urb);
++                              }
++                              save_flags(flags);
++                              cli();
++                              queue_control_request(hfc, HFCUSB_FIFO,
++                                                    fifo->fifonum);
++                              queue_control_request(hfc,
++                                                    HFCUSB_INC_RES_F, 2);
++                              queue_control_request(hfc, HFCUSB_CON_HDLC,
++                                                    9);
++                              queue_control_request(hfc, HFCUSB_SCTRL,
++                                                    0x40 +
++                                                    hfc->bch_enables);
++                              queue_control_request(hfc, HFCUSB_SCTRL_R,
++                                                    hfc->bch_enables);
++                              restore_flags(flags);
++                              fifo++;
++                              if (fifo->active) {
++                                      fifo->active = 0;
++                                      usb_unlink_urb(&fifo->urb);
++                              }
++                              return; /* fifo deactivated */
++                      }
++                      fifo->transmode = ((int) arg == L1_MODE_TRANS);
++                      fifo->max_size =
++                          ((fifo->transmode) ? fifo->
++                           usb_maxlen : MAX_BCH_SIZE);
++                      (fifo + 1)->transmode = fifo->transmode;
++                      (fifo + 1)->max_size = fifo->max_size;
++                      hfc->bch_enables |= (1 << chan);
++                      save_flags(flags);
++                      cli();
++                      queue_control_request(hfc, HFCUSB_FIFO,
++                                            fifo->fifonum);
++                      queue_control_request(hfc, HFCUSB_CON_HDLC,
++                                            ((!fifo->
++                                              transmode) ? 9 : 11));
++                      queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
++                      queue_control_request(hfc, HFCUSB_SCTRL,
++                                            0x40 + hfc->bch_enables);
++                      if ((int) arg == L1_MODE_HDLC)
++                              queue_control_request(hfc, HFCUSB_CON_HDLC,
++                                                    8);
++                      queue_control_request(hfc, HFCUSB_FIFO,
++                                            fifo->fifonum + 1);
++                      queue_control_request(hfc, HFCUSB_CON_HDLC,
++                                            ((!fifo->
++                                              transmode) ? 8 : 10));
++                      queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
++                      queue_control_request(hfc, HFCUSB_SCTRL_R,
++                                            hfc->bch_enables);
++                      restore_flags(flags);
++
++                      break;
++
++              default:
++                      printk(KERN_INFO
++                             "unknown hfcusb bch_access chan %d 0x%x\n",
++                             chan, pr);
++                      break;
++      }
++}                             /* hfcusb_bch_access */
++
++/***************************************************************************/
++/* usb_init is called once when a new matching device is detected to setup */
++/* main parmeters. It registers the driver at the main hisax module.       */
++/* on success 0 is returned.                                               */
++/***************************************************************************/
++static int
++usb_init(hfcusb_data * hfc)
++{
++      usb_fifo *fifo;
++      int i;
++      u_char b;
++
++      /* check the chip id */
++      if ((Read_hfc(hfc, HFCUSB_CHIP_ID, &b) != 1) ||
++          (b != HFCUSB_CHIPID)) {
++              printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);
++              return (1);
++      }
++
++      /* first set the needed config, interface and alternate */
++      usb_set_configuration(hfc->dev, 1);
++      usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
++
++        /* init the led state request */
++      hfc->led_req = LED_DRIVER;
++
++      /* now we initialise the chip */
++      Write_hfc(hfc, HFCUSB_CIRM, 0x10);      /* aux = output, reset off */
++      Write_hfc(hfc, HFCUSB_P_DATA, 0);       /* leds = off */
++      Write_hfc(hfc, HFCUSB_USB_SIZE,
++                (hfc->fifos[HFCUSB_B1_TX].usb_maxlen >> 3) |
++                ((hfc->fifos[HFCUSB_B1_RX].usb_maxlen >> 3) << 4));
++
++      /* enable PCM/GCI master mode */
++      Write_hfc(hfc, HFCUSB_MST_MODE1, 0);    /* set default values */
++      Write_hfc(hfc, HFCUSB_MST_MODE0, 1);    /* enable master mode */
++
++      /* init the fifos */
++      Write_hfc(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD >> 3) |
++                ((HFCUSB_RX_THRESHOLD >> 3) << 4));
++
++      for (i = 0, fifo = hfc->fifos + i; i < HFCUSB_NUM_FIFOS;
++           i++, fifo++) {
++              Write_hfc(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
++
++              fifo->transmode = 0;    /* hdlc mode selected */
++              fifo->buff = NULL;      /* init buffer pointer */
++              fifo->max_size =
++                  (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
++              Write_hfc(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); /* data length */
++              Write_hfc(hfc, HFCUSB_CON_HDLC, ((i & 1) ? 0x08 : 0x09));       /* rx hdlc, tx fill 1 */
++              Write_hfc(hfc, HFCUSB_INC_RES_F, 2);    /* reset the fifo */
++      }
++
++      Write_hfc(hfc, HFCUSB_CLKDEL, 0x0f);    /* clock delay value */
++      Write_hfc(hfc, HFCUSB_STATES, 3 | 0x10);        /* set deactivated mode */
++      Write_hfc(hfc, HFCUSB_STATES, 3);       /* enable state machine */
++
++      Write_hfc(hfc, HFCUSB_SCTRL_R, 0);      /* disable both B receivers */
++      Write_hfc(hfc, HFCUSB_SCTRL, 0x40);     /* disable B transmitters + cap mode */
++
++      /* init the l1 timer */
++      init_timer(&hfc->t3_timer);
++      hfc->t3_timer.data = (long) hfc;
++      hfc->t3_timer.function = (void *) l1_timer_expire;
++      hfc->t4_timer.data = (long) hfc;
++      hfc->t4_timer.function = (void *) l1_timer_expire;
++      hfc->l1_tq.routine = (void *) (void *) usb_l1d_bh;
++      hfc->l1_tq.sync = 0;
++      hfc->l1_tq.data = hfc;
++
++      /* init the background control machinery */
++      hfc->ctrl_read.requesttype = 0xc0;
++      hfc->ctrl_read.request = 1;
++      hfc->ctrl_read.length = 1;
++      hfc->ctrl_write.requesttype = 0x40;
++      hfc->ctrl_write.request = 0;
++      hfc->ctrl_write.length = 0;
++      FILL_CONTROL_URB(&hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,
++                       (u_char *) & hfc->ctrl_write, NULL, 0,
++                       ctrl_complete, hfc);
++
++      /* init the TX-urbs */
++      fifo = hfc->fifos + HFCUSB_D_TX;
++      FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
++                    (u_char *) fifo->buffer, 0, tx_complete, fifo);
++      fifo = hfc->fifos + HFCUSB_B1_TX;
++      FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
++                    (u_char *) fifo->buffer, 0, tx_complete, fifo);
++      fifo = hfc->fifos + HFCUSB_B2_TX;
++      FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
++                    (u_char *) fifo->buffer, 0, tx_complete, fifo);
++
++      /* init the E-buffer */
++      skb_queue_head_init(&hfc->regd.erq);
++
++      /* now register ourself at hisax */
++      hfc->regd.version = HISAX_LOAD_VERSION; /* set our version */
++      hfc->regd.cmd = HISAX_LOAD_REGISTER;    /* register command */
++      hfc->regd.argl1 = (void *) hfc; /* argument for our local routine */
++      hfc->regd.dch_l2l1 = hfcusb_l1_access;
++      hfc->regd.bch_l2l1 = hfcusb_bch_access;
++      hfc->regd.drvname = "hfc_usb";
++      if (hisax_register_hfcusb(&hfc->regd)) {
++              printk(KERN_INFO "HFC-USB failed to register at hisax\n");
++              Write_hfc(hfc, HFCUSB_CIRM, 0x08);      /* aux = input, reset on */
++              return (1);
++      }
++
++      /* startup the D- and E-channel fifos */
++      start_rx_fifo(hfc->fifos + HFCUSB_D_RX);        /* D-fifo */
++      if (hfc->fifos[HFCUSB_PCM_RX].pipe)
++              start_rx_fifo(hfc->fifos + HFCUSB_PCM_RX);      /* E-fifo */
++
++      return (0);
++}                             /* usb_init */
++
++/*************************************************/
++/* function called to probe a new plugged device */
++/*************************************************/
++static void *
++hfc_usb_probe(struct usb_device *dev, unsigned int interface
++#ifdef COMPAT_HAS_USB_IDTAB
++            , const struct usb_device_id *id_table)
++#else
++    )
++#endif
++{
++      hfcusb_data *context;
++      struct usb_interface *ifp = dev->actconfig->interface + interface;
++      struct usb_interface_descriptor *ifdp =
++          ifp->altsetting + ifp->act_altsetting;
++      struct usb_endpoint_descriptor *epd;
++      int i, idx, ep_msk;
++
++#ifdef COMPAT_HAS_USB_IDTAB
++      if (id_table && (dev->descriptor.idVendor == id_table->idVendor) &&
++          (dev->descriptor.idProduct == id_table->idProduct) &&
++#else
++      if ((((dev->descriptor.idVendor == 0x959) &&
++          (dev->descriptor.idProduct == 0x2bd0)) ||
++          ((dev->descriptor.idVendor == 0x7b0) &&
++          (dev->descriptor.idProduct == 0x0006))) &&
++#endif
++          (ifdp->bNumEndpoints >= 6) && (ifdp->bNumEndpoints <= 16)) {
++              if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) {
++                      return (NULL);  /* got no mem */
++              };
++              memset(context, 0, sizeof(hfcusb_data));        /* clear the structure */
++              i = ifdp->bNumEndpoints;        /* get number of endpoints */
++              ep_msk = 0;     /* none found */
++              epd = ifdp->endpoint;   /* first endpoint descriptor */
++              while (i-- && ((ep_msk & 0xcf) != 0xcf)) {
++
++                      idx = (((epd->bEndpointAddress & 0x7f) - 1) << 1);      /* get endpoint base */
++                      if (idx < 7) {
++                              switch (epd->bmAttributes) {
++                                      case USB_ENDPOINT_XFER_INT:
++                                              if (!
++                                                  (epd->
++                                                   bEndpointAddress &
++                                                   0x80))
++                                                      break;  /* only interrupt in allowed */
++                                              idx++;  /* input index is odd */
++                                              context->fifos[idx].pipe =
++                                                  usb_rcvintpipe(dev,
++                                                                 epd->
++                                                                 bEndpointAddress);
++                                              break;
++
++                                      case USB_ENDPOINT_XFER_BULK:
++                                              if (epd->
++                                                  bEndpointAddress &
++                                                  0x80)
++                                                      break;  /* only bulk out allowed */
++                                              context->fifos[idx].pipe =
++                                                  usb_sndbulkpipe(dev,
++                                                                  epd->
++                                                                  bEndpointAddress);
++                                              break;
++                                      default:
++                                              context->fifos[idx].pipe = 0;   /* reset data */
++                              }       /* switch attribute */
++
++                              if (context->fifos[idx].pipe) {
++                                      context->fifos[idx].fifonum = idx;
++                                      context->fifos[idx].fifo_mask =
++                                          1 << idx;
++                                      context->fifos[idx].hfc = context;
++                                      context->fifos[idx].usb_maxlen =
++                                          epd->wMaxPacketSize;
++                                      context->fifos[idx].intervall =
++                                          epd->bInterval;
++                                      ep_msk |= (1 << idx);
++                              } else
++                                      ep_msk &= ~(1 << idx);
++                      }       /* idx < 7 */
++                      epd++;
++              }
++
++              if ((ep_msk & 0x3f) != 0x3f) {
++                      kfree(context);
++                      return (NULL);
++              }
++              MOD_INC_USE_COUNT;      /* lock our module */
++              context->dev = dev;     /* save device */
++              context->if_used = interface;   /* save used interface */
++              context->alt_used = ifp->act_altsetting;        /* and alternate config */
++              context->ctrl_paksize = dev->descriptor.bMaxPacketSize0;        /* control size */
++
++              /* create the control pipes needed for register access */
++              context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
++              context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
++
++              /* init the chip and register the driver */
++              if (usb_init(context)) {
++                      kfree(context);
++                      MOD_DEC_USE_COUNT;
++                      return (NULL);
++              }
++
++              printk(KERN_INFO
++                     "HFC-USB: New device if=%d alt=%d registered\n",
++                     context->if_used, context->alt_used);
++              return (context);
++      }
++
++      return (NULL);          /* no matching entry */
++}                             /* hfc_usb_probe */
++
++/****************************************************/
++/* function called when an active device is removed */
++/****************************************************/
++static void
++hfc_usb_disconnect(struct usb_device *usbdev, void *drv_context)
++{
++      hfcusb_data *context = drv_context;
++      int i;
++      struct sk_buff *skb;
++
++      /* tell all fifos to terminate */
++      for (i = 0; i < HFCUSB_NUM_FIFOS; i++)
++              if (context->fifos[i].active) {
++                      context->fifos[i].active = 0;
++                      usb_unlink_urb(&context->fifos[i].urb);
++              }
++      while (context->active_fifos) {
++              set_current_state(TASK_INTERRUPTIBLE);
++              /* Timeout 10ms */
++              schedule_timeout((10 * HZ) / 1000);
++      }
++      if (timer_pending(&context->t3_timer))
++              del_timer(&context->t3_timer);
++      context->regd.release_driver(context->regd.arg_hisax);
++      while ((skb = skb_dequeue(&context->regd.erq)) != NULL)
++              dev_kfree_skb_any(skb);
++
++      kfree(context);         /* free our structure again */
++      MOD_DEC_USE_COUNT;      /* and decrement the usage counter */
++}                             /* hfc_usb_disconnect */
++
++/************************************/
++/* our driver information structure */
++/************************************/
++static struct usb_driver hfc_drv = {
++      name:"hfc_usb",
++#ifdef COMPAT_HAS_USB_IDTAB
++      id_table:hfc_usb_idtab,
++#endif
++      probe:hfc_usb_probe,
++      disconnect:hfc_usb_disconnect,
++};
++
++static void __exit
++hfc_usb_exit(void)
++{
++
++      usb_deregister(&hfc_drv);       /* release our driver */
++      printk(KERN_INFO "HFC-USB module removed\n");
++}
++
++static int __init
++hfc_usb_init(void)
++{
++      struct hisax_drvreg drv;
++
++      drv.version = HISAX_LOAD_VERSION;       /* set our version */
++      drv.cmd = HISAX_LOAD_CHKVER;    /* check command only */
++      if (hisax_register_hfcusb(&drv)) {
++              printk(KERN_INFO "HFC-USB <-> hisax version conflict\n");
++              return (-1);    /* unable to register */
++      }
++      if (usb_register(&hfc_drv)) {
++              printk(KERN_INFO
++                     "Unable to register HFC-USB module at usb stack\n");
++              return (-1);    /* unable to register */
++      }
++
++      printk(KERN_INFO "HFC-USB module loaded\n");
++      return (0);
++}
++
++module_init(hfc_usb_init);
++module_exit(hfc_usb_exit);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_usbr.c linux-2.4.29/drivers/isdn/hisax/hfc_usbr.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_usbr.c     1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_usbr.c 2005-03-22 15:06:46.397039360 +0100
+@@ -0,0 +1,471 @@
++/* $Id: hfc_usbr.c,v 2.5 2001/07/06 21:30:11 werner Exp $
++
++ * hfc_usb.c  low level driver for CCD´s hfc-usb single chip controllers
++ *            type approval valid for HFC-S USB based TAs
++ *
++ * Author     Werner Cornelius (werner@isdn-development.de)
++ *
++ * Copyright 2001  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)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * 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.
++ *
++ */
++
++#define __NO_VERSION__
++#include <linux/init.h>
++#include "hisax.h"
++#include "isdnl1.h"
++#include "hisax_loadable.h"
++
++extern const char *CardType[];
++
++static const char *hfcusb_revision = "$Revision: 2.5 $";
++
++/*********************************/
++/* schedule a new b_channel task */
++/*********************************/
++static void
++hfcusb_sched_event(struct BCState *bcs, int event)
++{
++      bcs->event |= 1 << event;
++      queue_task(&bcs->tqueue, &tq_immediate);
++      mark_bh(IMMEDIATE_BH);
++}
++
++/************************************************/
++/* select a b-channel entry matching and active */
++/************************************************/
++static
++struct BCState *
++Sel_BCS(struct IsdnCardState *cs, int channel)
++{
++      if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
++              return (&cs->bcs[0]);
++      else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
++              return (&cs->bcs[1]);
++      else
++              return (NULL);
++}
++
++/**********************************************/
++/* transfer function (D-channel from l2 to l1 */
++/**********************************************/
++static void
++hfcusb_d_l2l1(struct PStack *st, int pr, void *arg)
++{
++      struct IsdnCardState *cs = st->l1.hardware;
++      struct hisax_drvreg *drv = cs->hw.hfcusb.drv;
++
++      if (drv) {
++              switch (pr) {
++                      case (PH_DATA | REQUEST):
++                      case (PH_PULL | INDICATION):
++                              cs->hw.hfcusb.dch_tx_busy = 1;
++                              break;
++                      case (PH_PULL | REQUEST):
++                              if (!cs->hw.hfcusb.dch_tx_busy) {
++                                      test_and_clear_bit(FLG_L1_PULL_REQ,
++                                                         &st->l1.Flags);
++                                      st->l1.l1l2(st, PH_PULL | CONFIRM,
++                                                  NULL);
++                              } else
++                                      test_and_set_bit(FLG_L1_PULL_REQ,
++                                                       &st->l1.Flags);
++                              return;
++              }
++              drv->dch_l2l1(drv, pr, arg);
++      } else
++              debugl1(cs, "hfcusb l2l1 called without existing driver");
++}                             /* hfcusb_d_l2l1 */
++
++/*****************************/
++/* E-channel receive routine */
++/*****************************/
++static void
++EChannel_proc_rcv(struct IsdnCardState *cs)
++{
++      u_char *ptr;
++      struct sk_buff *skb;
++      struct hisax_drvreg *usbdrv =
++          (struct hisax_drvreg *) cs->hw.hfcusb.drv;
++
++
++      while ((skb = skb_dequeue(&usbdrv->erq)) != NULL) {
++              if (cs->debug & DEB_DLOG_HEX) {
++                      ptr = cs->dlog;
++                      if ((skb->len) < MAX_DLOG_SPACE / 3 - 10) {
++                              *ptr++ = 'E';
++                              *ptr++ = 'C';
++                              *ptr++ = 'H';
++                              *ptr++ = 'O';
++                              *ptr++ = ':';
++                              ptr += QuickHex(ptr, skb->data, skb->len);
++                              ptr--;
++                              *ptr++ = '\n';
++                              *ptr = 0;
++                              HiSax_putstatus(cs, NULL, cs->dlog);
++                      } else
++                              HiSax_putstatus(cs, "LogEcho: ",
++                                              "warning Frame too big (%d)",
++                                              skb->len);
++              }
++              dev_kfree_skb_any(skb);
++      }
++}
++
++/******************************************/
++/* transfer function called from L1 to L2 */
++/******************************************/
++static void
++hfcusb_d_l1l2(void *cs1, int pr, void *arg)
++{
++      struct IsdnCardState *cs = (struct IsdnCardState *) cs1;
++
++      switch (pr) {
++              case (PH_DATA | INDICATION):
++                      if (!((int) arg))
++                              DChannel_proc_rcv(cs);
++                      else
++                              EChannel_proc_rcv(cs);
++                      break;
++
++              case (PH_DATA | CONFIRM):
++                      cs->hw.hfcusb.dch_tx_busy = 0;
++                      DChannel_proc_xmt(cs);
++                      break;
++
++              case (PH_ACTIVATE | INDICATION):
++              case (PH_ACTIVATE | CONFIRM):
++                      cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++                      if (cs->debug & L1_DEB_ISAC)
++                              debugl1(cs, "layer 1 activated");
++                      break;
++
++              case (PH_DEACTIVATE | INDICATION):
++              case (PH_DEACTIVATE | CONFIRM):
++                      cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++                      if (cs->debug & L1_DEB_ISAC)
++                              debugl1(cs, "layer 1 deactivated");
++                      break;
++
++              default:
++                      debugl1(cs, "unknown l1 msg 0x%x ", pr);
++      }
++}                             /* hfcusb_d_l1l2 */
++
++
++/******************************************/
++/* transfer function called from L1 to L2 */
++/******************************************/
++static void
++hfcusb_b_l1l2(void *cs1, int chan, int pr, void *arg)
++{
++      struct IsdnCardState *cs = (struct IsdnCardState *) cs1;
++      struct BCState *bcs = Sel_BCS(cs, chan);
++
++      switch (pr) {
++              case (PH_DATA | INDICATION):
++                      if (!bcs)
++                              return;
++                      hfcusb_sched_event(bcs, B_RCVBUFREADY);
++                      break;
++
++              case (PH_DATA | CONFIRM):
++                      if (!bcs)
++                              return;
++                      bcs->tx_cnt -= bcs->tx_skb->len;
++                      if (bcs->st->lli.l1writewakeup &&
++                          (PACKET_NOACK != bcs->tx_skb->pkt_type))
++                              bcs->st->lli.l1writewakeup(bcs->st,
++                                                         bcs->tx_skb->
++                                                         len);
++                      dev_kfree_skb_any(bcs->tx_skb);
++                      bcs->tx_skb = skb_dequeue(&bcs->squeue);
++                      break;
++
++              case (PH_ACTIVATE | INDICATION):
++              case (PH_ACTIVATE | CONFIRM):
++                      cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++                      if (cs->debug & L1_DEB_ISAC)
++                              debugl1(cs, "layer 1 activated");
++                      break;
++
++              case (PH_DEACTIVATE | INDICATION):
++              case (PH_DEACTIVATE | CONFIRM):
++                      cs->stlist->l1.l1l2(cs->stlist, pr, arg);
++                      if (cs->debug & L1_DEB_ISAC)
++                              debugl1(cs, "layer 1 deactivated");
++                      break;
++
++              default:
++                      debugl1(cs, "unknown l1 b msg 0x%x ", pr);
++      }
++}                             /* hfcusb_b_l1l2 */
++
++
++/***********************************************/
++/* called during init setting l1 stack pointer */
++/***********************************************/
++void
++setstack_hfcusb(struct PStack *st, struct IsdnCardState *cs)
++{
++      st->l2.l2l1 = hfcusb_d_l2l1;
++}
++
++/**************************************/
++/* send B-channel data if not blocked */
++/**************************************/
++static void
++hfcusb_send_data(struct BCState *bcs)
++{
++      struct IsdnCardState *cs = bcs->cs;
++      struct hisax_drvreg *drv =
++          (struct hisax_drvreg *) cs->hw.hfcusb.drv;
++
++      if (!drv)
++              return;
++      drv->bch_l2l1(drv->argl1, bcs->channel, PH_DATA | REQUEST,
++                    bcs->tx_skb);
++}
++
++/***************************************************************/
++/* activate/deactivate hardware for selected channels and mode */
++/***************************************************************/
++void
++mode_hfcusb(struct BCState *bcs, int mode, int bc)
++{
++      struct IsdnCardState *cs = bcs->cs;
++      struct hisax_drvreg *drv = cs->hw.hfcusb.drv;
++
++      if (!drv)
++              return;
++      if (cs->debug & L1_DEB_HSCX)
++              debugl1(cs, "HFCUSB bchannel mode %d bchan %d/%d",
++                      mode, bc, bcs->channel);
++      bcs->mode = mode;
++      bcs->channel = bc;
++      if (mode) {
++              drv->bsk[bc] = &bcs->tx_skb;
++              drv->brq[bc] = &bcs->rqueue;
++      }
++      drv->bch_l2l1(drv->argl1, bc, PH_ACTIVATE | REQUEST,
++                    (void *) mode);
++      if (!mode) {
++              drv->bsk[bc] = NULL;
++              drv->brq[bc] = NULL;
++      }
++}
++
++/******************************/
++/* Layer2 -> Layer 1 Transfer */
++/******************************/
++static void
++hfcusb_b_l2l1(struct PStack *st, int pr, void *arg)
++{
++      struct sk_buff *skb = arg;
++      struct hisax_drvreg *drv = st->l1.bcs->cs->hw.hfcusb.drv;
++      long flags;
++
++      switch (pr) {
++              case (PH_DATA | REQUEST):
++                      save_flags(flags);
++                      cli();
++                      if (st->l1.bcs->tx_skb) {
++                              skb_queue_tail(&st->l1.bcs->squeue, skb);
++                              restore_flags(flags);
++                      } else {
++                              st->l1.bcs->tx_skb = skb;
++                              st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
++                              restore_flags(flags);
++                      }
++                      break;
++              case (PH_PULL | INDICATION):
++                      if (st->l1.bcs->tx_skb) {
++                              printk(KERN_WARNING
++                                     "hfc_l2l1: this shouldn't happen\n");
++                              break;
++                      }
++                      save_flags(flags);
++                      cli();
++                      st->l1.bcs->tx_skb = skb;
++                      st->l1.bcs->cs->BC_Send_Data(st->l1.bcs);
++                      restore_flags(flags);
++                      break;
++              case (PH_PULL | REQUEST):
++                      if (!st->l1.bcs->tx_skb) {
++                              test_and_clear_bit(FLG_L1_PULL_REQ,
++                                                 &st->l1.Flags);
++                              st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
++                      } else
++                              test_and_set_bit(FLG_L1_PULL_REQ,
++                                               &st->l1.Flags);
++                      break;
++              case (PH_ACTIVATE | REQUEST):
++                      if (drv) {
++                              test_and_set_bit(BC_FLG_ACTIV,
++                                               &st->l1.bcs->Flag);
++                              mode_hfcusb(st->l1.bcs, st->l1.mode,
++                                          st->l1.bc);
++                              l1_msg_b(st, pr, arg);
++                      }
++                      break;
++              case (PH_DEACTIVATE | REQUEST):
++                      l1_msg_b(st, pr, arg);
++                      break;
++              case (PH_DEACTIVATE | CONFIRM):
++                      test_and_clear_bit(BC_FLG_ACTIV,
++                                         &st->l1.bcs->Flag);
++                      test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
++                      mode_hfcusb(st->l1.bcs, 0, st->l1.bc);
++                      st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
++                      break;
++      }
++}
++
++/******************************************/
++/* deactivate B-channel access and queues */
++/******************************************/
++static void
++close_hfcusb(struct BCState *bcs)
++{
++      mode_hfcusb(bcs, 0, bcs->channel);
++      if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
++              skb_queue_purge(&bcs->rqueue);
++              skb_queue_purge(&bcs->squeue);
++              if (bcs->tx_skb) {
++                      dev_kfree_skb_any(bcs->tx_skb);
++                      bcs->tx_skb = NULL;
++                      test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
++              }
++      }
++}
++
++/*************************************/
++/* init B-channel queues and control */
++/*************************************/
++static int
++open_hfcusbstate(struct IsdnCardState *cs, struct BCState *bcs)
++{
++      if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
++              skb_queue_head_init(&bcs->rqueue);
++              skb_queue_head_init(&bcs->squeue);
++      }
++      bcs->tx_skb = NULL;
++      test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
++      bcs->event = 0;
++      bcs->tx_cnt = 0;
++      return (0);
++}
++
++/*********************************/
++/* inits the stack for B-channel */
++/*********************************/
++static int
++setstack_2b(struct PStack *st, struct BCState *bcs)
++{
++      bcs->channel = st->l1.bc;
++      if (open_hfcusbstate(st->l1.hardware, bcs))
++              return (-1);
++      st->l1.bcs = bcs;
++      st->l2.l2l1 = hfcusb_b_l2l1;
++      setstack_manager(st);
++      bcs->st = st;
++      setstack_l1_B(st);
++      return (0);
++}
++
++/********************************/
++/* called for card init message */
++/********************************/
++void __devinit
++inithfcusb(struct IsdnCardState *cs)
++{
++      cs->setstack_d = setstack_hfcusb;
++      cs->BC_Send_Data = &hfcusb_send_data;
++      cs->bcs[0].BC_SetStack = setstack_2b;
++      cs->bcs[1].BC_SetStack = setstack_2b;
++      cs->bcs[0].BC_Close = close_hfcusb;
++      cs->bcs[1].BC_Close = close_hfcusb;
++      mode_hfcusb(cs->bcs, 0, 0);
++      mode_hfcusb(cs->bcs + 1, 0, 1);
++}
++
++
++
++/*******************************************/
++/* handle card messages from control layer */
++/*******************************************/
++static int
++hfcusb_card_msg(struct IsdnCardState *cs, int mt, void *arg)
++{
++      if (cs->debug & L1_DEB_ISAC)
++              debugl1(cs, "HFCUSB: card_msg %x", mt);
++      switch (mt) {
++              case CARD_INIT:
++                      inithfcusb(cs);
++                      return (0);
++              case CARD_RELEASE:
++              case CARD_RESET:
++              case CARD_TEST:
++                      return (0);
++      }
++      return (0);
++}
++
++
++extern void
++ HiSax_closecard(int cardnr);
++/*****************************/
++/* release a driver instance */
++/* called when hardware is   */
++/* no longer present.        */
++/*****************************/
++static void
++release_hfcdrv(void *arg)
++{
++      struct IsdnCardState *cs = (struct IsdnCardState *) arg;
++
++      cs->hw.hfcusb.drv = NULL;       /* disable any further use of driver */
++      HiSax_closecard(cs->cardnr);
++}                             /* release_hfcdrv */
++
++/*********************************************/
++/* called once when a new device is detected */
++/* initialises local data                    */
++/*********************************************/
++int
++setup_hfc_usb(struct IsdnCard *card)
++{
++      struct IsdnCardState *cs = card->cs;
++      char tmp[64];
++      struct hisax_drvreg *usbdrv =
++          (struct hisax_drvreg *) cs->hw.hfcusb.drv;
++
++      if (!usbdrv)
++              return (0);     /* no driver data present */
++
++      strcpy(tmp, hfcusb_revision);
++      printk(KERN_INFO "HiSax: HFC-USB driver Rev. %s\n",
++             HiSax_getrev(tmp));
++
++      usbdrv->release_driver = &release_hfcdrv;       /* release routine */
++      usbdrv->arg_hisax = (void *) cs;        /* parameter for calling */
++      usbdrv->dch_l1l2 = &hfcusb_d_l1l2;      /* access from L1 to HiSax */
++      usbdrv->bch_l1l2 = &hfcusb_b_l1l2;
++      usbdrv->drq = &cs->rq;
++      usbdrv->dsq = &cs->sq;
++      cs->cardmsg = &hfcusb_card_msg;
++      return (1);             /* success */
++}
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfcscard.c linux-2.4.29/drivers/isdn/hisax/hfcscard.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfcscard.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfcscard.c 2005-03-22 15:06:46.412037080 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hfcscard.c,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $
++/* $Id: hfcscard.c,v 1.10 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for hfcs based cards (Teles3c, ACER P10)
+  *
+@@ -12,14 +12,13 @@
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "hfc_2bds0.h"
+ #include "isdnl1.h"
+ extern const char *CardType[];
+-static const char *hfcs_revision = "$Revision: 1.1.4.1 $";
++static const char *hfcs_revision = "$Revision: 1.10 $";
+ static void
+ hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+@@ -140,36 +139,6 @@
+       return(0);
+ }
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id hfc_ids[] __initdata = {
+-      { ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114),
+-        ISAPNP_VENDOR('A', 'N', 'X'), ISAPNP_FUNCTION(0x1114), 
+-        (unsigned long) "Acer P10" },
+-      { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002),
+-        ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0002), 
+-        (unsigned long) "Billion 2" },
+-      { ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001),
+-        ISAPNP_VENDOR('B', 'I', 'L'), ISAPNP_FUNCTION(0x0001), 
+-        (unsigned long) "Billion 1" },
+-      { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410),
+-        ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x7410), 
+-        (unsigned long) "IStar PnP" },
+-      { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610),
+-        ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2610), 
+-        (unsigned long) "Teles 16.3c" },
+-      { ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001),
+-        ISAPNP_VENDOR('S', 'F', 'M'), ISAPNP_FUNCTION(0x0001), 
+-        (unsigned long) "Tornado Tipa C" },
+-      { ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001),
+-        ISAPNP_VENDOR('K', 'Y', 'E'), ISAPNP_FUNCTION(0x0001), 
+-        (unsigned long) "Genius Speed Surfer" },
+-      { 0, }
+-};
+-
+-static struct isapnp_device_id *hdev = &hfc_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_hfcs(struct IsdnCard *card)
+ {
+@@ -178,46 +147,6 @@
+       strcpy(tmp, hfcs_revision);
+       printk(KERN_INFO "HiSax: HFC-S driver Rev. %s\n", HiSax_getrev(tmp));
+-
+-#ifdef __ISAPNP__
+-      if (!card->para[1] && isapnp_present()) {
+-              struct pci_bus *pb;
+-              struct pci_dev *pd;
+-
+-              while(hdev->card_vendor) {
+-                      if ((pb = isapnp_find_card(hdev->card_vendor,
+-                              hdev->card_device, pnp_c))) {
+-                              pnp_c = pb;
+-                              pd = NULL;
+-                              if ((pd = isapnp_find_dev(pnp_c,
+-                                      hdev->vendor, hdev->function, pd))) {
+-                                      printk(KERN_INFO "HiSax: %s detected\n",
+-                                              (char *)hdev->driver_data);
+-                                      pd->prepare(pd);
+-                                      pd->deactivate(pd);
+-                                      pd->activate(pd);
+-                                      card->para[1] = pd->resource[0].start;
+-                                      card->para[0] = pd->irq_resource[0].start;
+-                                      if (!card->para[0] || !card->para[1]) {
+-                                              printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n",
+-                                              card->para[0], card->para[1]);
+-                                              pd->deactivate(pd);
+-                                              return(0);
+-                                      }
+-                                      break;
+-                              } else {
+-                                      printk(KERN_ERR "HFC PnP: PnP error card found, no device\n");
+-                              }
+-                      }
+-                      hdev++;
+-                      pnp_c=NULL;
+-              } 
+-              if (!hdev->card_vendor) {
+-                      printk(KERN_INFO "HFC PnP: no ISAPnP card found\n");
+-                      return(0);
+-              }
+-      }
+-#endif
+       cs->hw.hfcD.addr = card->para[1] & 0xfffe;
+       cs->irq = card->para[0];
+       cs->hw.hfcD.cip = 0;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax.h linux-2.4.29/drivers/isdn/hisax/hisax.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax.h    2005-03-22 15:06:46.431034192 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hisax.h,v 1.1.4.2 2001/12/09 19:15:28 kai Exp $
++/* $Id: hisax.h,v 2.64 2001/09/24 13:22:56 kai Exp $
+  *
+  * Basic declarations, defines and prototypes
+  *
+@@ -24,7 +24,9 @@
+ #include <linux/isdnif.h>
+ #include <linux/tty.h>
+ #include <linux/serial_reg.h>
++#ifndef COMPAT_NO_SOFTNET
+ #include <linux/netdevice.h>
++#endif
+ #define ERROR_STATISTIC
+@@ -68,9 +70,6 @@
+ #define DL_DATA               0x0220
+ #define DL_FLUSH      0x0224
+ #define DL_UNIT_DATA  0x0230
+-
+-#define MDL_BC_RELEASE  0x0278  // Formula-n enter:now
+-#define MDL_BC_ASSIGN   0x027C  // Formula-n enter:now
+ #define MDL_ASSIGN    0x0280
+ #define MDL_REMOVE    0x0284
+ #define MDL_ERROR     0x0288
+@@ -472,8 +471,6 @@
+ #define BC_FLG_FTI_RUN        13
+ #define BC_FLG_LL_OK  14
+ #define BC_FLG_LL_CONN        15
+-#define BC_FLG_FTI_FTS        16
+-#define BC_FLG_FRH_WAIT       17
+ #define L1_MODE_NULL  0
+ #define L1_MODE_TRANS 1
+@@ -695,6 +692,13 @@
+       struct timer_list timer;
+ };
++#ifdef CONFIG_HISAX_HFC_USB
++struct hfcUSB_hw {  
++        void *drv; /* pointer to driver structure */
++        int dch_tx_busy;
++};
++#endif
++
+ struct hfcSX_hw {
+         unsigned long base;
+       unsigned char cirm;
+@@ -838,17 +842,6 @@
+       int ph_state;
+ };
+-struct amd7930_chip {
+-      u_char lmr1;
+-      u_char ph_state;
+-      u_char old_state;
+-      u_char flg_t3;
+-      unsigned int tx_xmtlen;
+-      struct timer_list timer3;
+-      void (*ph_command) (struct IsdnCardState *, u_char, char *);
+-      void (*setIrqMask) (struct IsdnCardState *, u_char);
+-};
+-
+ struct icc_chip {
+       int ph_state;
+       u_char *mon_tx;
+@@ -902,6 +895,9 @@
+               struct njet_hw njet;
+               struct hfcD_hw hfcD;
+               struct hfcPCI_hw hfcpci;
++#ifdef CONFIG_HISAX_HFC_USB
++              struct hfcUSB_hw hfcusb;
++#endif
+               struct hfcSX_hw hfcsx;
+               struct ix1_hw niccy;
+               struct isurf_hw isurf;
+@@ -945,7 +941,6 @@
+               struct hfcpci_chip hfcpci;
+               struct hfcsx_chip hfcsx;
+               struct w6692_chip w6692;
+-              struct amd7930_chip amd7930;
+               struct icc_chip icc;
+       } dc;
+       u_char *rcvbuf;
+@@ -967,6 +962,8 @@
+ #define  MON0_TX      4
+ #define  MON1_TX      8
++#define        HISAX_MAX_CARDS        8
++
+ #define  ISDN_CTYPE_16_0      1
+ #define  ISDN_CTYPE_8_0               2
+ #define  ISDN_CTYPE_16_3      3
+@@ -1006,8 +1003,8 @@
+ #define  ISDN_CTYPE_HFC_SX      37
+ #define  ISDN_CTYPE_NETJET_U  38
+ #define  ISDN_CTYPE_HFC_SP_PCMCIA      39
+-#define  ISDN_CTYPE_DYNAMIC     40
+-#define  ISDN_CTYPE_ENTERNOW  41
++#define  ISDN_CTYPE_HFC_USB     40
++#define  ISDN_CTYPE_DYNAMIC     41
+ #define  ISDN_CTYPE_COUNT     41
+@@ -1267,10 +1264,6 @@
+ #define CARD_NETJET_U 0
+ #endif
+-#ifdef CONFIG_HISAX_ENTERNOW_PCI
+-#define CARD_FN_ENTERNOW_PCI 1
+-#endif
+-
+ #define TEI_PER_CARD 1
+ /* L1 Debug */
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_debug.h linux-2.4.29/drivers/isdn/hisax/hisax_debug.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_debug.h  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_debug.h      2005-03-22 15:06:46.452031000 +0100
+@@ -28,7 +28,7 @@
+ #define DBG(level, format, arg...) do { \
+ if (level & __debug_variable) \
+-printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \
++printk(KERN_DEBUG __FUNCTION__ ": " format "\n" , ## arg); \
+ } while (0)
+ #define DBG_PACKET(level,data,count) \
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.c linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.c   2005-03-22 15:06:46.468028568 +0100
+@@ -20,22 +20,19 @@
+  *
+  * o POWER PC
+  * o clean up debugging
+- * o tx_skb at PH_DEACTIVATE time
+  */
+ #include <linux/version.h>
+ #include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include "hisax_isapnp.h"
+ #include <linux/kmod.h>
+ #include <linux/slab.h>
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
+-
+-#include <asm/io.h>
+-
+ #include "hisax_fcpcipnp.h"
++#include "hisax_isac.h"
+ // debugging cruft
+ #define __debug_variable debug
+@@ -46,10 +43,14 @@
+ MODULE_PARM(debug, "i");
+ #endif
+-MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
++MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>");
+ MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
+-static struct pci_device_id fcpci_ids[] __devinitdata = {
++#ifndef PCI_DEVICE_ID_AVM_A1_V2
++#define PCI_DEVICE_ID_AVM_A1_V2 0x0e00
++#endif
++
++static struct pci_device_id fcpci_ids[] __initdata = {
+       { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1   , PCI_ANY_ID, PCI_ANY_ID,
+         0, 0, (unsigned long) "Fritz!Card PCI" },
+       { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1_V2, PCI_ANY_ID, PCI_ANY_ID,
+@@ -58,7 +59,7 @@
+ };
+ MODULE_DEVICE_TABLE(pci, fcpci_ids);
+-static struct isapnp_device_id fcpnp_ids[] __devinitdata = {
++static struct isapnp_device_id fcpnp_ids[] __initdata = {
+       { ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900),
+         ISAPNP_VENDOR('A', 'V', 'M'), ISAPNP_FUNCTION(0x0900), 
+         (unsigned long) "Fritz!Card PnP" },
+@@ -68,7 +69,8 @@
+ static int protocol = 2;       /* EURO-ISDN Default */
+ MODULE_PARM(protocol, "i");
+-MODULE_LICENSE("GPL");
++
++static LIST_HEAD(adapter_list);
+ // ----------------------------------------------------------------------
+@@ -147,7 +149,7 @@
+       outb(idx, adapter->io + AVM_INDEX);
+       val = inb(adapter->io + AVM_DATA + (offset & 0xf));
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+-      DBG(0x1000, " port %#x, value %#x",
++      DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+           offset, val);
+       return val;
+ }
+@@ -160,7 +162,7 @@
+               AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
+       unsigned long flags;
+-      DBG(0x1000, " port %#x, value %#x",
++      DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+           offset, value);
+       spin_lock_irqsave(&adapter->hw_lock, flags);
+       outb(idx, adapter->io + AVM_INDEX);
+@@ -240,7 +242,7 @@
+       outl(offset, adapter->io + AVM_ISACSX_INDEX);
+       val = inl(adapter->io + AVM_ISACSX_DATA);
+       spin_unlock_irqrestore(&adapter->hw_lock, flags);
+-      DBG(0x1000, " port %#x, value %#x",
++      DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+           offset, val);
+       return val;
+@@ -252,7 +254,7 @@
+       struct fritz_adapter *adapter = isac->priv;
+       unsigned long flags;
+-      DBG(0x1000, " port %#x, value %#x",
++      DBG(0x1000, __FUNCTION__ " port %#x, value %#x",
+           offset, value);
+       spin_lock_irqsave(&adapter->hw_lock, flags);
+       outl(offset, adapter->io + AVM_ISACSX_INDEX);
+@@ -375,6 +377,9 @@
+       DBG(0x40, "hdlc_fill_fifo");
++      if (!skb)
++              BUG();
++
+       if (skb->len == 0)
+               BUG();
+@@ -515,7 +520,6 @@
+       }
+       skb_push(bcs->tx_skb, bcs->tx_cnt);
+       bcs->tx_cnt = 0;
+-      hdlc_fill_fifo(bcs);
+ }
+ static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
+@@ -536,7 +540,7 @@
+       dev_kfree_skb_irq(skb);
+ }
+-static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
++static void hdlc_irq(struct fritz_bcs *bcs, u32 stat)
+ {
+       DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
+       if (stat & HDLC_INT_RPR) {
+@@ -553,7 +557,7 @@
+       }
+ }
+-static inline void hdlc_irq(struct fritz_adapter *adapter)
++static inline void hdlc_interrupt(struct fritz_adapter *adapter)
+ {
+       int nr;
+       u32 stat;
+@@ -562,7 +566,7 @@
+               stat = adapter->read_hdlc_status(adapter, nr);
+               DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
+               if (stat & HDLC_INT_MASK)
+-                      hdlc_irq_one(&adapter->bcs[nr], stat);
++                      hdlc_irq(&adapter->bcs[nr], stat);
+       }
+ }
+@@ -584,14 +588,14 @@
+               adapter->write_ctrl(bcs, 5);
+               break;
+       case L1_MODE_TRANS:
++              bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
++              adapter->write_ctrl(bcs, 5);
++              bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
++              adapter->write_ctrl(bcs, 1);
++              bcs->ctrl.sr.cmd = 0;
++              break;
+       case L1_MODE_HDLC:
+-              bcs->rcvidx = 0;
+-              bcs->tx_cnt = 0;
+-              bcs->tx_skb = NULL;
+-              if (mode == L1_MODE_TRANS)
+-                      bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
+-              else
+-                      bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
++              bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
+               adapter->write_ctrl(bcs, 5);
+               bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
+               adapter->write_ctrl(bcs, 1);
+@@ -645,10 +649,10 @@
+               return;
+       DBG(2, "STATUS0 %#x", val);
+       if (val & AVM_STATUS0_IRQ_ISAC)
+-              isacsx_irq(&adapter->isac);
++              isacsx_interrupt(&adapter->isac);
+       if (val & AVM_STATUS0_IRQ_HDLC)
+-              hdlc_irq(adapter);
++              hdlc_interrupt(adapter);
+ }
+ static void fcpci_irq(int intno, void *dev, struct pt_regs *regs)
+@@ -662,10 +666,10 @@
+               return;
+       DBG(2, "sval %#x", sval);
+       if (!(sval & AVM_STATUS0_IRQ_ISAC))
+-              isac_irq(&adapter->isac);
++              isac_interrupt(&adapter->isac);
+       if (!(sval & AVM_STATUS0_IRQ_HDLC))
+-              hdlc_irq(adapter);
++              hdlc_interrupt(adapter);
+ }
+ // ----------------------------------------------------------------------
+@@ -681,11 +685,6 @@
+ {
+       outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | 
+            AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
+-
+-      outb(AVM_STATUS1_ENA_IOM | adapter->irq, 
+-           adapter->io + AVM_STATUS1);
+-      set_current_state(TASK_UNINTERRUPTIBLE);
+-      schedule_timeout(50*HZ / 1000); /* Timeout 50ms */
+ }
+ // ----------------------------------------------------------------------
+@@ -693,6 +692,7 @@
+ static int __devinit fcpcipnp_setup(struct fritz_adapter *adapter)
+ {
+       u32 val = 0;
++      struct pci_dev *pdev = adapter->pci_dev;
+       int retval;
+       DBG(1,"");
+@@ -700,21 +700,21 @@
+       isac_init(&adapter->isac); // FIXME is this okay now
+       retval = -EBUSY;
+-      if (!request_region(adapter->io, 32, "fcpcipnp"))
++      if (!request_region(adapter->io, 32, "hisax_fcpcipnp"))
+               goto err;
+       switch (adapter->type) {
+       case AVM_FRITZ_PCIV2:
+-              retval = request_irq(adapter->irq, fcpci2_irq, SA_SHIRQ, 
+-                                   "fcpcipnp", adapter);
++              retval = request_irq(pdev->irq, fcpci2_irq, SA_SHIRQ, 
++                                   "hisax_fcpcipnp", adapter);
+               break;
+       case AVM_FRITZ_PCI:
+-              retval = request_irq(adapter->irq, fcpci_irq, SA_SHIRQ,
+-                                   "fcpcipnp", adapter);
++              retval = request_irq(pdev->irq, fcpci_irq, SA_SHIRQ,
++                                   "hisax_fcpcipnp", adapter);
+               break;
+       case AVM_FRITZ_PNP:
+-              retval = request_irq(adapter->irq, fcpci_irq, 0,
+-                                   "fcpcipnp", adapter);
++              retval = request_irq(pdev->irq, fcpci_irq, 0,
++                                   "hisax_fcpcipnp", adapter);
+               break;
+       }
+       if (retval)
+@@ -808,11 +808,23 @@
+ static void __devexit fcpcipnp_release(struct fritz_adapter *adapter)
+ {
++      struct pci_dev *pdev = adapter->pci_dev;
++
+       DBG(1,"");
+       outb(0, adapter->io + AVM_STATUS0);
+-      free_irq(adapter->irq, adapter);
++      free_irq(pdev->irq, adapter);
+       release_region(adapter->io, 32);
++
++      switch (adapter->type) {
++      case AVM_FRITZ_PCI:
++      case AVM_FRITZ_PCIV2:
++              pci_disable_device(pdev);
++              break;
++      case AVM_FRITZ_PNP:
++              pdev->deactivate(pdev);
++              break;
++      }
+ }
+ // ----------------------------------------------------------------------
+@@ -830,6 +842,8 @@
+       memset(adapter, 0, sizeof(struct fritz_adapter));
++      adapter->pci_dev = pdev;
++
+       SET_MODULE_OWNER(&adapter->isac.hisax_d_if);
+       adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
+       adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
+@@ -840,6 +854,7 @@
+               adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
+               adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
+       }
++      list_add(&adapter->list, &adapter_list);
+       pci_set_drvdata(pdev, adapter);
+@@ -854,6 +869,7 @@
+ static void delete_adapter(struct fritz_adapter *adapter)
+ {
+       hisax_unregister(&adapter->isac.hisax_d_if);
++      list_del(&adapter->list);
+       kfree(adapter);
+ }
+@@ -863,12 +879,15 @@
+       struct fritz_adapter *adapter;
+       int retval;
++      printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
++             (char *) ent->driver_data, pdev->slot_name);
++
+       retval = -ENOMEM;
+       adapter = new_adapter(pdev);
+       if (!adapter)
+               goto err;
+-      if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) 
++      if (pdev->device == 0x0e00) 
+               adapter->type = AVM_FRITZ_PCIV2;
+       else
+               adapter->type = AVM_FRITZ_PCI;
+@@ -876,12 +895,7 @@
+       retval = pci_enable_device(pdev);
+       if (retval)
+               goto err_free;
+-
+       adapter->io = pci_resource_start(pdev, 1);
+-      adapter->irq = pdev->irq;
+-
+-      printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
+-             (char *) ent->driver_data, pdev->slot_name);
+       retval = fcpcipnp_setup(adapter);
+       if (retval)
+@@ -901,6 +915,9 @@
+       struct fritz_adapter *adapter;
+       int retval;
++      printk(KERN_INFO "hisax_fcpcipnp: found adapter %s\n",
++             (char *) ent->driver_data);
++
+       retval = -ENOMEM;
+       adapter = new_adapter(pdev);
+       if (!adapter)
+@@ -912,11 +929,8 @@
+       pdev->deactivate(pdev); // why?
+       pdev->activate(pdev);
+       adapter->io = pdev->resource[0].start;
+-      adapter->irq = pdev->irq_resource[0].start;
+-
+-      printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
+-             (char *) ent->driver_data, adapter->io, adapter->irq);
+-
++      pdev->irq = pdev->irq_resource[0].start;
++      
+       retval = fcpcipnp_setup(adapter);
+       if (retval)
+               goto err_free;
+@@ -929,43 +943,35 @@
+       return retval;
+ }
+-static void __devexit fcpci_remove(struct pci_dev *pdev)
+-{
+-      struct fritz_adapter *adapter = pci_get_drvdata(pdev);
+-
+-      fcpcipnp_release(adapter);
+-      pci_disable_device(pdev);
+-      delete_adapter(adapter);
+-}
+-
+-static void __devexit fcpnp_remove(struct pci_dev *pdev)
++static void __devexit fcpcipnp_remove(struct pci_dev *pdev)
+ {
+       struct fritz_adapter *adapter = pci_get_drvdata(pdev);
+       fcpcipnp_release(adapter);
+-      pdev->deactivate(pdev);
+       delete_adapter(adapter);
+ }
+ static struct pci_driver fcpci_driver = {
+-      name:     "fcpci",
+-      probe:    fcpci_probe,
+-      remove:   __devexit_p(fcpci_remove),
++      name: "fcpci",
++      probe: fcpci_probe,
++      remove: fcpcipnp_remove,
+       id_table: fcpci_ids,
+ };
+ static struct isapnp_driver fcpnp_driver = {
+-      name:     "fcpnp",
+-      probe:    fcpnp_probe,
+-      remove:   __devexit_p(fcpnp_remove),
++      name: "fcpnp",
++      probe: fcpnp_probe,
++      remove: fcpcipnp_remove,
+       id_table: fcpnp_ids,
+ };
+-static int __init hisax_fcpcipnp_init(void)
++static LIST_HEAD(isapnp_drivers);
++
++static int __init hisax_fcpci_init(void)
+ {
+       int retval, pci_nr_found;
+-      printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
++      printk(KERN_INFO "hisax_fcpcipnp: Fritz!PCI/PnP ISDN driver v0.0.1\n");
+       retval = pci_register_driver(&fcpci_driver);
+       if (retval < 0)
+@@ -976,15 +982,14 @@
+       if (retval < 0)
+               goto out_unregister_pci;
+-#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
++#if !defined(CONFIG_HOTPLUG) && defined(MODULE)
+       if (pci_nr_found + retval == 0) {
+               retval = -ENODEV;
+               goto out_unregister_isapnp;
+-      }
+ #endif
+       return 0;
+-#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
++#if !defined(CONFIG_HOTPLUG) && defined(MODULE)
+  out_unregister_isapnp:
+       isapnp_unregister_driver(&fcpnp_driver);
+ #endif
+@@ -994,11 +999,15 @@
+       return retval;
+ }
+-static void __exit hisax_fcpcipnp_exit(void)
++static void __exit hisax_fcpci_exit(void)
+ {
+       isapnp_unregister_driver(&fcpnp_driver);
+       pci_unregister_driver(&fcpci_driver);
+ }
+-module_init(hisax_fcpcipnp_init);
+-module_exit(hisax_fcpcipnp_exit);
++module_init(hisax_fcpci_init);
++module_exit(hisax_fcpci_exit);
++
++#ifdef __ISAPNP__
++#include "hisax_isapnp.c"
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.h linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_fcpcipnp.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_fcpcipnp.h   2005-03-22 15:06:46.484026136 +0100
+@@ -43,10 +43,12 @@
+ };
+ struct fritz_adapter {
++      struct list_head list;
++      struct pci_dev *pci_dev;
++
+       int type;
+       spinlock_t hw_lock;
+       unsigned int io;
+-      unsigned int irq;
+       struct isac isac;
+       struct fritz_bcs bcs[2];
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.c linux-2.4.29/drivers/isdn/hisax/hisax_isac.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isac.c       2005-03-22 15:06:46.543017168 +0100
+@@ -34,7 +34,7 @@
+ static int debug = 1;
+ MODULE_PARM(debug, "i");
+-static char *ISACVer[] = {
++static char *ISACVer[] __devinitdata = {
+   "2086/2186 V1.1", 
+   "2085 B1", 
+   "2085 B2",
+@@ -42,10 +42,6 @@
+ };
+ #endif
+-MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
+-MODULE_DESCRIPTION("ISAC/ISAC-SX driver");
+-MODULE_LICENSE("GPL");
+-
+ #define DBG_WARN      0x0001
+ #define DBG_IRQ       0x0002
+ #define DBG_L1M       0x0004
+@@ -438,7 +434,7 @@
+       va_end(args);
+ }
+-static void isac_version(struct isac *cs)
++static void __devinit isac_version(struct isac *cs)
+ {
+       int val;
+@@ -602,7 +598,7 @@
+       }
+ }
+-void isac_irq(struct isac *isac)
++void isac_interrupt(struct isac *isac)
+ {
+       unsigned char val;
+@@ -635,8 +631,6 @@
+       if (val & ISAC_ISTA_SIN) {
+               DBG(DBG_WARN, "SIN");
+       }
+-      isac->write_isac(isac, ISAC_MASK, 0xff);
+-      isac->write_isac(isac, ISAC_MASK, 0x00);
+ }
+ // ======================================================================
+@@ -742,7 +736,7 @@
+       }
+ }
+-void isacsx_irq(struct isac *isac)
++void isacsx_interrupt(struct isac *isac)
+ {
+       unsigned char val;
+@@ -755,7 +749,7 @@
+               isacsx_cic_interrupt(isac);
+ }
+-void isac_init(struct isac *isac)
++void __devinit isac_init(struct isac *isac)
+ {
+       isac->tx_skb = NULL;
+       isac->l1m.fsm = &l1fsm;
+@@ -770,7 +764,7 @@
+       FsmInitTimer(&isac->l1m, &isac->timer);
+ }
+-void isac_setup(struct isac *isac)
++void __devinit isac_setup(struct isac *isac)
+ {
+       int val, eval;
+@@ -781,7 +775,7 @@
+       isac->write_isac(isac, ISAC_MASK, 0xff);
+       isac->mocr = 0xaa;
+-      if (test_bit(ISAC_IOM1, &isac->flags)) {
++      if (test_bit(HW_IOM1, &isac->flags)) {
+               /* IOM 1 Mode */
+               isac->write_isac(isac, ISAC_ADF2, 0x0);
+               isac->write_isac(isac, ISAC_SPCR, 0xa);
+@@ -817,7 +811,7 @@
+       FsmEvent(&isac->l1m, (val >> 2) & 0xf, NULL);
+       isac->write_isac(isac, ISAC_MASK, 0x0);
+-      // RESET Receiver and Transmitter
++      /* RESET Receiver and Transmitter */
+       isac->write_isac(isac, ISAC_CMDR, ISAC_CMDR_XRES | ISAC_CMDR_RRES);
+ }
+@@ -888,10 +882,10 @@
+ EXPORT_SYMBOL(isac_d_l2l1);
+ EXPORT_SYMBOL(isacsx_setup);
+-EXPORT_SYMBOL(isacsx_irq);
++EXPORT_SYMBOL(isacsx_interrupt);
+ EXPORT_SYMBOL(isac_setup);
+-EXPORT_SYMBOL(isac_irq);
++EXPORT_SYMBOL(isac_interrupt);
+ module_init(hisax_isac_init);
+ module_exit(hisax_isac_exit);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.h linux-2.4.29/drivers/isdn/hisax/hisax_isac.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isac.h   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isac.h       2005-03-22 15:06:46.559014736 +0100
+@@ -8,7 +8,7 @@
+ #define TIMER3_VALUE 7000
+ #define MAX_DFRAME_LEN_L1 300
+-#define ISAC_IOM1     0
++#define HW_IOM1       0
+ struct isac {
+       void *priv;
+@@ -37,9 +37,9 @@
+ void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg);
+ void isac_setup(struct isac *isac);
+-void isac_irq(struct isac *isac);
++void isac_interrupt(struct isac *isac);
+ void isacsx_setup(struct isac *isac);
+-void isacsx_irq(struct isac *isac);
++void isacsx_interrupt(struct isac *isac);
+ #endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.c linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.c     2005-03-22 15:06:46.576012152 +0100
+@@ -0,0 +1,105 @@
++// FIXME copied
++static const struct isapnp_device_id *
++isapnp_match_device(const struct isapnp_device_id *ids, struct pci_dev *dev)
++{
++      DBG(1,"");
++
++      while (ids->card_vendor || ids->card_device) {
++              if ((ids->card_vendor == ISAPNP_ANY_ID || ids->card_vendor == dev->bus->vendor) &&
++                  (ids->card_device == ISAPNP_ANY_ID || ids->card_device == dev->bus->device) &&
++                    (ids->vendor == ISAPNP_ANY_ID || ids->vendor == dev->vendor) &&
++                    (ids->function == ISAPNP_ANY_ID || ids->function == dev->device))
++                      return ids;
++              ids++;
++      }
++      return NULL;
++}
++
++/**
++ * pci_dev_driver - get the pci_driver of a device
++ * @dev: the device to query
++ *
++ * Returns the appropriate pci_driver structure or %NULL if there is no 
++ * registered driver for the device.
++ */
++struct pci_driver *isapnp_dev_driver(const struct pci_dev *dev)
++{
++      return dev->driver;
++}
++
++static int isapnp_announce_device(struct isapnp_driver *drv, struct pci_dev *dev)
++{
++      const struct isapnp_device_id *id;
++      int ret = 0;
++
++      DBG(1,"");
++
++      if (drv->id_table) {
++              id = isapnp_match_device(drv->id_table, dev);
++              if (!id) {
++                      ret = 0;
++                      goto out;
++              }
++      } else
++              id = NULL;
++
++//    dev_probe_lock();
++      if (drv->probe(dev, id) >= 0) {
++              dev->driver = (struct pci_driver *) drv;
++              ret = 1;
++      }
++//    dev_probe_unlock();
++out:
++      return ret;
++}
++
++/**
++ * FIXME pci_register_driver - register a new pci driver
++ * @drv: the driver structure to register
++ * 
++ * Adds the driver structure to the list of registered drivers
++ * Returns the number of pci devices which were claimed by the driver
++ * during registration.  The driver remains registered even if the
++ * return value is zero.
++ */
++int isapnp_register_driver(struct isapnp_driver *drv)
++{
++      struct pci_dev *dev;
++      int count = 0;
++
++      DBG(1,"");
++
++      list_add_tail(&drv->node, &isapnp_drivers);
++      isapnp_for_each_dev(dev) {
++              if (!isapnp_dev_driver(dev))
++                      count += isapnp_announce_device(drv, dev);
++      }
++      return count;
++}
++
++/**
++ * pci_unregister_driver - unregister a pci driver
++ * @drv: the driver structure to unregister
++ * 
++ * Deletes the driver structure from the list of registered PCI drivers,
++ * gives it a chance to clean up by calling its remove() function for
++ * each device it was responsible for, and marks those devices as
++ * driverless.
++ */
++
++void isapnp_unregister_driver(struct isapnp_driver *drv)
++{
++      struct pci_dev *dev;
++
++      DBG(1,"");
++
++      list_del(&drv->node);
++      isapnp_for_each_dev(dev) {
++              if (dev->driver == (struct pci_driver *) drv) {
++                      if (drv->remove)
++                              drv->remove(dev);
++                      dev->driver = NULL;
++              }
++      }
++}
++
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.h linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_isapnp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_isapnp.h     2005-03-22 15:06:46.590010024 +0100
+@@ -0,0 +1,33 @@
++#ifndef __HISAX_ISAPNP_H__
++#define __HISAX_ISAPNP_H__
++
++#include <linux/isapnp.h>
++
++#ifdef COMPAT_NEED_ISAPNP_DRIVER
++struct isapnp_driver {
++      struct list_head node;
++      char *name;
++      const struct isapnp_device_id *id_table;        /* NULL if wants all devices */
++      int  (*probe)  (struct pci_dev *dev, const struct isapnp_device_id *id);        /* New device inserted */
++      void (*remove) (struct pci_dev *dev);   /* Device removed (NULL if not a hot-plug capable driver) */
++};
++#endif
++#ifdef __ISAPNP__
++
++int isapnp_register_driver(struct isapnp_driver *drv);
++void isapnp_unregister_driver(struct isapnp_driver *drv);
++
++#else
++
++static inline int isapnp_register_driver(struct isapnp_driver *drv) 
++{ 
++      return 0;
++}
++
++static inline void isapnp_unregister_driver(struct isapnp_driver *drv) 
++{ 
++}
++
++#endif
++
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hisax_loadable.h linux-2.4.29/drivers/isdn/hisax/hisax_loadable.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hisax_loadable.h       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hisax_loadable.h   2005-03-22 15:06:46.606007592 +0100
+@@ -0,0 +1,74 @@
++/* $Id: hisax_loadable.h,v 2.1 2001/06/08 22:19:16 werner Exp $
++ *
++ *
++ * Author       (C) 2001 Werner Cornelius (werner@isdn-development.de)
++ *              modular driver for Colognechip HFC-USB chip
++ *              as plugin for HiSax isdn driver
++ *
++ * Copyright 2001  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)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * 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.
++ *
++ */
++
++#include <linux/types.h>
++#include <linux/skbuff.h>
++
++/***************************************/
++/* additional defines for l1 constants */
++/***************************************/
++#define B1_DATA       0x1f0
++#define B1_SETMODE    0x1f4
++#define B2_DATA       0x1f8
++#define B2_SETMODE    0x1fc
++
++
++/********************************************************/
++/* structure used for register and release of L1 driver */
++/********************************************************/
++struct hisax_drvreg {
++      int version;            /* actual version for check */
++      int cmd;                /* command code */
++
++      /* function pointers set by hisax during register call */
++      void (*release_driver) (void *arg_hisax);       /* set by hisax, release function for driver */
++      void (*dch_l1l2) (void *arg_hisax, int pr, void *arg);  /* set by hisax, notify dch+l1 events */
++      void (*bch_l1l2) (void *arg_hisax, int chan, int pr, void *arg);        /* set by hisax, notify bch events */
++      void *arg_hisax;        /* argument when calling hisax main */
++      struct sk_buff_head *drq;       /* pointer to D-receive queue */
++      struct sk_buff_head *dsq;       /* pointer to D-send queue */
++      struct sk_buff_head erq;        /* E-receive queue */
++      struct sk_buff_head *brq[2];    /* pointer to B-receive queues */
++      struct sk_buff **bsk[2];        /* pointer to B-transmit buffer */
++
++      /* function pointers set by l1 driver before calling the register function */
++      void (*dch_l2l1) (void *argl1, int pr, void *arg);      /* function dch+l1 from hisax -> l1 */
++      void (*bch_l2l1) (void *argl1, int chan, int pr, void *arg);    /* function bch from hisax -> l1 */
++      void *argl1;            /* pointer to l1 data structure when calling l1 */
++
++      char *drvname;          /* driver name for hisax usage */
++};
++
++/**************************/
++/* constants and commands */
++/**************************/
++#define HISAX_LOAD_VERSION  4 /* change when interface changes */
++#define HISAX_LOAD_CHKVER   0 /* check version command (returns 0 on success) */
++#define HISAX_LOAD_REGISTER 1 /* register the L1 driver and return 0 on success */
++
++/***************************************/
++/* definition of the register function */
++/***************************************/
++extern int hisax_register_hfcusb(struct hisax_drvreg *l1drv);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hscx.c linux-2.4.29/drivers/isdn/hisax/hscx.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hscx.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hscx.c     2005-03-22 15:06:46.621005312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hscx.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: hscx.c,v 1.24 2001/09/24 13:22:56 kai Exp $
+  *
+  * HSCX specific routines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hscx.h linux-2.4.29/drivers/isdn/hisax/hscx.h
+--- linux-2.4.29.old/drivers/isdn/hisax/hscx.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hscx.h     2005-03-22 15:06:46.640002424 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hscx.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: hscx.h,v 1.8 2001/09/24 13:22:56 kai Exp $
+  *
+  * HSCX specific defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hscx_irq.c linux-2.4.29/drivers/isdn/hisax/hscx_irq.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hscx_irq.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hscx_irq.c 2005-03-22 15:06:46.655999992 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hscx_irq.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: hscx_irq.c,v 1.18 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level b-channel stuff for Siemens HSCX
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/icc.c linux-2.4.29/drivers/isdn/hisax/icc.c
+--- linux-2.4.29.old/drivers/isdn/hisax/icc.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/icc.c      2005-03-22 15:06:46.672997408 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icc.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: icc.c,v 1.8 2001/09/24 13:22:56 kai Exp $
+  *
+  * ICC specific routines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/icc.h linux-2.4.29/drivers/isdn/hisax/icc.h
+--- linux-2.4.29.old/drivers/isdn/hisax/icc.h  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/icc.h      2005-03-22 15:06:46.687995128 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icc.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: icc.h,v 1.4 2001/09/24 13:22:56 kai Exp $
+  *
+  * ICC specific routines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/ipac.h linux-2.4.29/drivers/isdn/hisax/ipac.h
+--- linux-2.4.29.old/drivers/isdn/hisax/ipac.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/ipac.h     2005-03-22 15:06:46.702992848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: ipac.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: ipac.h,v 1.7 2001/09/24 13:22:56 kai Exp $
+  *
+  * IPAC specific defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isac.c linux-2.4.29/drivers/isdn/hisax/isac.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isac.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isac.c     2005-03-22 15:06:46.844971264 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isac.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isac.c,v 1.31 2001/09/24 13:22:56 kai Exp $
+  *
+  * ISAC specific routines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isac.h linux-2.4.29/drivers/isdn/hisax/isac.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isac.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isac.h     2005-03-22 15:06:47.111930680 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isac.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isac.h,v 1.9 2001/09/24 13:22:56 kai Exp $
+  *
+  * ISAC specific defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isar.c linux-2.4.29/drivers/isdn/hisax/isar.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isar.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isar.c     2005-03-22 15:06:47.302901648 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isar.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isar.c,v 1.22 2001/09/23 12:00:05 keil Exp $
+  *
+  * isar.c   ISAR (Siemens PSB 7110) specific routines
+  *
+@@ -21,12 +21,10 @@
+ #define DLE   0x10
+ #define ETX   0x03
+-#define FAXMODCNT     13
+-const u_char  faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146};
+-static        u_int   modmask = 0x1fff;
+-static        int     frm_extra_delay = 2;
+-static        int     para_TOA = 6;
+-const   u_char  *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" };
++
++const u_char faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; 
++const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; 
++#define FAXMODCNT 13
+ void isar_setup(struct IsdnCardState *cs);
+ static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para);
+@@ -127,7 +125,7 @@
+       ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L);
+ #if DUMP_MBOXFRAME
+       if (cs->debug & L1_DEB_HSCX)
+-              debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
++              debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb,
+                       ireg->clsb);
+ #endif
+ }
+@@ -414,7 +412,6 @@
+       }
+       cs->debug = debug;
+       isar_setup(cs);
+-
+       ret = 0;
+ reterrflg:
+       restore_flags(flags);
+@@ -428,21 +425,6 @@
+       return(ret);
+ }
+-static inline void
+-ll_deliver_faxstat(struct BCState *bcs, u_char status)
+-{
+-        isdn_ctrl ic;
+-      struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
+- 
+-      if (bcs->cs->debug & L1_DEB_HSCX)
+-              debugl1(bcs->cs, "HL->LL FAXIND %x", status);
+-      ic.driver = bcs->cs->myid;
+-      ic.command = ISDN_STAT_FAXIND;
+-      ic.arg = chanp->chan;
+-      ic.parm.aux.cmd = status;
+-      bcs->cs->iif.statcallb(&ic);
+-}
+-
+ extern void BChannel_bh(struct BCState *);
+ #define B_LL_NOCARRIER        8
+ #define B_LL_CONNECT  9
+@@ -599,6 +581,7 @@
+                               if (ireg->cmsb & SART_NMD) { /* ABORT */
+                                       if (cs->debug & L1_DEB_WARN)
+                                               debugl1(cs, "isar_rcv_frame: no more data");
++                                      cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+                                       bcs->hw.isar.rcvidx = 0;
+                                       send_DLE_ETX(bcs);
+                                       sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
+@@ -609,6 +592,7 @@
+                               }
+                       } else {
+                               printk(KERN_WARNING "HiSax: skb out of memory\n");
++                              cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+                       }
+                       break;
+               }
+@@ -633,9 +617,8 @@
+                       bcs->hw.isar.rcvidx = 0;
+                       cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+               } else {
+-                      if (ireg->cmsb & HDLC_FSD) {
++                      if (ireg->cmsb & HDLC_FSD)
+                               bcs->hw.isar.rcvidx = 0;
+-                      }
+                       ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx;
+                       bcs->hw.isar.rcvidx += ireg->clsb;
+                       rcv_mbox(cs, ireg, ptr);
+@@ -646,8 +629,6 @@
+                                       if (cs->debug & L1_DEB_WARN)
+                                               debugl1(cs, "isar frame to short %d",
+                                                       bcs->hw.isar.rcvidx);
+-                                      printk(KERN_WARNING "ISAR: frame to short %d\n",
+-                                              bcs->hw.isar.rcvidx);
+                               } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) {
+                                       printk(KERN_WARNING "ISAR: receive out of memory\n");
+                               } else {
+@@ -658,7 +639,6 @@
+                                       isar_sched_event(bcs, B_RCVBUFREADY);
+                                       send_DLE_ETX(bcs);
+                                       isar_sched_event(bcs, B_LL_OK);
+-                                      test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+                               }
+                               bcs->hw.isar.rcvidx = 0;
+                       }
+@@ -666,14 +646,13 @@
+               if (ireg->cmsb & SART_NMD) { /* ABORT */
+                       if (cs->debug & L1_DEB_WARN)
+                               debugl1(cs, "isar_rcv_frame: no more data");
++                      cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0);
+                       bcs->hw.isar.rcvidx = 0;
++                      send_DLE_ETX(bcs);
+                       sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) |
+                               ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL);
+                       bcs->hw.isar.state = STFAX_ESCAPE;
+-                      if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) {
+-                              send_DLE_ETX(bcs);
+-                              isar_sched_event(bcs, B_LL_NOCARRIER);
+-                      }
++                      isar_sched_event(bcs, B_LL_NOCARRIER);
+               }
+               break;
+       default:
+@@ -977,6 +956,21 @@
+       }
+ }
++static inline void
++ll_deliver_faxstat(struct BCState *bcs, u_char status)
++{
++        isdn_ctrl ic;
++      struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata;
++ 
++      if (bcs->cs->debug & L1_DEB_HSCX)
++              debugl1(bcs->cs, "HL->LL FAXIND %x", status);
++      ic.driver = bcs->cs->myid;
++      ic.command = ISDN_STAT_FAXIND;
++      ic.arg = chanp->chan;
++      ic.parm.aux.cmd = status;
++      bcs->cs->iif.statcallb(&ic);
++}
++
+ static void
+ isar_pump_statev_fax(struct BCState *bcs, u_char devt) {
+       struct IsdnCardState *cs = bcs->cs;
+@@ -1081,22 +1075,19 @@
+                       if (cs->debug & L1_DEB_HSCX)
+                               debugl1(cs, "pump stev RSP_DISC");
+                       if (bcs->hw.isar.state == STFAX_ESCAPE) {
+-                              p1 = 5;
+                               switch(bcs->hw.isar.newcmd) {
+                                       case 0:
+                                               bcs->hw.isar.state = STFAX_READY;
+                                               break;
+-                                      case PCTRL_CMD_FTM:
+-                                              p1 = 2;
+                                       case PCTRL_CMD_FTH:
++                                      case PCTRL_CMD_FTM:
++                                              p1 = 10;
+                                               sendmsg(cs, dps | ISAR_HIS_PUMPCTRL,
+                                                       PCTRL_CMD_SILON, 1, &p1);
+                                               bcs->hw.isar.state = STFAX_SILDET;
+                                               break;
+-                                      case PCTRL_CMD_FRM:
+-                                              if (frm_extra_delay)
+-                                                      mdelay(frm_extra_delay);
+                                       case PCTRL_CMD_FRH:
++                                      case PCTRL_CMD_FRM:
+                                               p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod;
+                                               bcs->hw.isar.newmod = 0;
+                                               bcs->hw.isar.cmd = bcs->hw.isar.newcmd;
+@@ -1215,9 +1206,6 @@
+                                       isar_pump_statev_modem(bcs, ireg->cmsb);
+                               } else if (bcs->mode == L1_MODE_FAX) {
+                                       isar_pump_statev_fax(bcs, ireg->cmsb);
+-                              } else if (ireg->cmsb == PSEV_10MS_TIMER) {
+-                                      if (cs->debug & L1_DEB_HSCX)
+-                                              debugl1(cs, "pump stev TIMER");
+                               } else {
+                                       if (cs->debug & L1_DEB_WARN)
+                                               debugl1(cs, "isar IIS_PSTEV pmode %d stat %x",
+@@ -1278,9 +1266,6 @@
+       if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) {
+               isar_sched_event(bcs, B_LL_CONNECT);
+       }
+-      if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) {
+-              isar_sched_event(bcs, B_LL_OK);
+-      }
+ }
+ static void
+@@ -1303,7 +1288,7 @@
+                       } else {
+                               param[5] = PV32P6_ATN;
+                       }
+-                      param[0] = para_TOA; /* 6 db */
++                      param[0] = 6; /* 6 db */
+                       param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B |
+                                  PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; 
+                       param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B;
+@@ -1319,7 +1304,7 @@
+                       } else {
+                               param[1] = PFAXP2_ATN;
+                       }
+-                      param[0] = para_TOA; /* 6 db */
++                      param[0] = 6; /* 6 db */
+                       sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param);
+                       bcs->hw.isar.state = STFAX_NULL;
+                       bcs->hw.isar.newcmd = 0;
+@@ -1348,6 +1333,7 @@
+                               "\0\0");
+                       break;
+               case L1_MODE_HDLC:
++              case L1_MODE_FAX:
+                       param[0] = 0;
+                       sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1,
+                               param);
+@@ -1359,9 +1345,6 @@
+                       sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2,
+                               param);
+                       break;
+-              case L1_MODE_FAX:
+-                      /* SART must not configured with FAX */
+-                      break;
+       }
+       udelay(1000);
+       sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL);
+@@ -1465,7 +1448,6 @@
+       switch(cmd) {
+               case ISDN_FAX_CLASS1_FTM:
+-                      test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+                       if (bcs->hw.isar.state == STFAX_READY) {
+                               p1 = para;
+                               ctrl = PCTRL_CMD_FTM;
+@@ -1489,7 +1471,6 @@
+                       }
+                       break;
+               case ISDN_FAX_CLASS1_FTH:
+-                      test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+                       if (bcs->hw.isar.state == STFAX_READY) {
+                               p1 = para;
+                               ctrl = PCTRL_CMD_FTH;
+@@ -1513,7 +1494,6 @@
+                       }
+                       break;
+               case ISDN_FAX_CLASS1_FRM:
+-                      test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+                       if (bcs->hw.isar.state == STFAX_READY) {
+                               p1 = para;
+                               ctrl = PCTRL_CMD_FRM;
+@@ -1537,7 +1517,6 @@
+                       }
+                       break;
+               case ISDN_FAX_CLASS1_FRH:
+-                      test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag);
+                       if (bcs->hw.isar.state == STFAX_READY) {
+                               p1 = para;
+                               ctrl = PCTRL_CMD_FRH;
+@@ -1560,11 +1539,6 @@
+                               bcs->hw.isar.state = STFAX_ESCAPE; 
+                       }
+                       break;
+-              case ISDN_FAXPUMP_HALT:
+-                      bcs->hw.isar.state = STFAX_NULL;
+-                      nom = 0;
+-                      ctrl = PCTRL_CMD_HALT;
+-                      break;
+       }
+       if (ctrl)
+               sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1);
+@@ -1658,15 +1632,6 @@
+                       l1_msg_b(st, pr, arg);
+                       break;
+               case (PH_DEACTIVATE | CONFIRM):
+-                      switch(st->l1.mode) {
+-                              case L1_MODE_TRANS:
+-                              case L1_MODE_HDLC:
+-                              case L1_MODE_V32:
+-                                      break;
+-                              case L1_MODE_FAX:
+-                                      isar_pump_cmd(st->l1.bcs, ISDN_FAXPUMP_HALT, 0);
+-                                      break;
+-                      }
+                       test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+                       test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag);
+                       if (st->l1.bcs->cs->debug & L1_DEB_HSCX)
+@@ -1758,51 +1723,6 @@
+                                               test_and_set_bit(BC_FLG_DLEETX,
+                                                       &bcs->Flag);
+                                       break;
+-                              case ISDN_FAX_CLASS1_FTS:
+-                                      if (ic->parm.aux.subcmd == AT_QUERY) {
+-                                              ic->command = ISDN_STAT_FAXIND;
+-                                              ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
+-                                              cs->iif.statcallb(ic);
+-                                              return(0);
+-                                      } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
+-                                              strcpy(ic->parm.aux.para, "0-255");
+-                                              ic->command = ISDN_STAT_FAXIND;
+-                                              ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+-                                              cs->iif.statcallb(ic);
+-                                              return(0);
+-                                      } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+-                                              if (cs->debug & L1_DEB_HSCX)
+-                                                      debugl1(cs, "isar_auxcmd %s=%d",
+-                                                              FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
+-                                              if (bcs->hw.isar.state == STFAX_READY) {
+-                                                      if (! ic->parm.aux.para[0]) {
+-                                                              ic->command = ISDN_STAT_FAXIND;
+-                                                              ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK;
+-                                                              cs->iif.statcallb(ic);
+-                                                              return(0);
+-                                                      }
+-                                                      if (! test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) {
+-                                                              /* n*10 ms */
+-                                                              bcs->hw.isar.ftimer.expires =
+-                                                                      jiffies + ((ic->parm.aux.para[0] * 10 * HZ)/1000);
+-                                                              test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag);
+-                                                              add_timer(&bcs->hw.isar.ftimer);
+-                                                              return(0);
+-                                                      } else {
+-                                                              if (cs->debug)
+-                                                                      debugl1(cs, "isar FTS=%d and FTI busy",
+-                                                                              ic->parm.aux.para[0]);
+-                                                      }
+-                                              } else {
+-                                                      if (cs->debug)
+-                                                              debugl1(cs, "isar FTS=%d and isar.state not ready(%x)",
+-                                                                      ic->parm.aux.para[0],bcs->hw.isar.state);
+-                                              }
+-                                              ic->command = ISDN_STAT_FAXIND;
+-                                              ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR;
+-                                              cs->iif.statcallb(ic);
+-                                      }
+-                                      break;
+                               case ISDN_FAX_CLASS1_FRM:
+                               case ISDN_FAX_CLASS1_FRH:
+                               case ISDN_FAX_CLASS1_FTM:
+@@ -1815,24 +1735,16 @@
+                                               cs->iif.statcallb(ic);
+                                               return(0);
+                                       } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) {
+-                                              char *p = ic->parm.aux.para;
+-                                              for(i=0;i<FAXMODCNT;i++)
+-                                                      if ((1<<i) & modmask)
+-                                                              p += sprintf(p, "%d,", faxmodulation[i]);
+-                                              p--;
+-                                              *p=0;
++                                              strcpy(ic->parm.aux.para, faxmodulation_s);
+                                               ic->command = ISDN_STAT_FAXIND;
+                                               ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY;
+                                               cs->iif.statcallb(ic);
+                                               return(0);
+                                       } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) {
+-                                              if (cs->debug & L1_DEB_HSCX)
+-                                                      debugl1(cs, "isar_auxcmd %s=%d",
+-                                                              FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]);
+                                               for(i=0;i<FAXMODCNT;i++)
+                                                       if (faxmodulation[i]==ic->parm.aux.para[0])
+                                                               break;
+-                                              if ((i < FAXMODCNT) && ((1<<i) & modmask) && 
++                                              if ((FAXMODCNT > i) && 
+                                                       test_bit(BC_FLG_INIT, &bcs->Flag)) {
+                                                       isar_pump_cmd(bcs,
+                                                               ic->parm.aux.cmd,
+@@ -1850,7 +1762,7 @@
+                       break;
+               case (ISDN_CMD_IOCTL):
+                       switch (ic->arg) {
+-                              case 9: /* load firmware */
++                              case (9): /* load firmware */
+                                       features = ISDN_FEATURE_L2_MODEM |
+                                               ISDN_FEATURE_L2_FAX |
+                                               ISDN_FEATURE_L3_FCLASS1;
+@@ -1860,26 +1772,6 @@
+                                       else 
+                                               ll_run(cs, features);
+                                       break;
+-                              case 20:
+-                                      features = *(unsigned int *) ic->parm.num;
+-                                      printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n",
+-                                              modmask, features);
+-                                      modmask = features;
+-                                      break;
+-                              case 21:
+-                                      features = *(unsigned int *) ic->parm.num;
+-                                      printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n",
+-                                              frm_extra_delay, features);
+-                                      if (features >= 0)
+-                                              frm_extra_delay = features;
+-                                      break;
+-                              case 22:
+-                                      features = *(unsigned int *) ic->parm.num;
+-                                      printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n",
+-                                              para_TOA, features);
+-                                      if (features >= 0 && features < 32)
+-                                              para_TOA = features;
+-                                      break;
+                               default:
+                                       printk(KERN_DEBUG "HiSax: invalid ioctl %d\n",
+                                              (int) ic->arg);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isar.h linux-2.4.29/drivers/isdn/hisax/isar.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isar.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isar.h     2005-03-22 15:06:47.457878088 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isar.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isar.h,v 1.11 2001/09/24 13:22:56 kai Exp $
+  *
+  * ISAR (Siemens PSB 7110) specific defines
+  *
+@@ -28,8 +28,6 @@
+ #define ISAR_HIS_FIRM         0x1e
+ #define ISAR_HIS_STDSP                0x08
+ #define ISAR_HIS_DIAG         0x05
+-#define ISAR_HIS_WAITSTATE    0x27
+-#define ISAR_HIS_TIMERIRQ     0x25
+ #define ISAR_HIS_P0CFG                0x3c
+ #define ISAR_HIS_P12CFG               0x24
+ #define ISAR_HIS_SARTCFG      0x25    
+@@ -45,10 +43,6 @@
+ #define ISAR_HIS_DPS2         0x80
+ #define SET_DPS(x)            ((x<<6) & 0xc0)
+-#define ISAR_CMD_TIMERIRQ_OFF 0x20
+-#define ISAR_CMD_TIMERIRQ_ON  0x21
+-
+-
+ #define ISAR_IIS_MSCMSD               0x3f
+ #define ISAR_IIS_VNR          0x15
+ #define ISAR_IIS_DKEY         0x03
+@@ -213,8 +207,6 @@
+ #define STFAX_ESCAPE  5
+ #define STFAX_SILDET  6
+-#define ISDN_FAXPUMP_HALT     100
+-
+ extern int ISARVersion(struct IsdnCardState *cs, char *s);
+ extern void isar_int_main(struct IsdnCardState *cs);
+ extern void initisar(struct IsdnCardState *cs);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl1.c linux-2.4.29/drivers/isdn/hisax/isdnl1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl1.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl1.c   2005-03-22 15:06:47.582859088 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl1.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl1.c,v 2.46 2001/09/24 13:22:56 kai Exp $
+  *
+  * common low level stuff for Siemens Chipsetbased isdn cards
+  *
+@@ -18,7 +18,7 @@
+  *
+  */
+-const char *l1_revision = "$Revision: 1.1.4.1 $";
++const char *l1_revision = "$Revision: 2.46 $";
+ #define __NO_VERSION__
+ #include <linux/init.h>
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl1.h linux-2.4.29/drivers/isdn/hisax/isdnl1.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl1.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl1.h   2005-03-22 15:06:47.615854072 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl1.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl1.h,v 2.12 2001/09/24 13:22:56 kai Exp $
+  *
+  * Layer 1 defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl2.c linux-2.4.29/drivers/isdn/hisax/isdnl2.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl2.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl2.c   2005-03-22 15:06:47.631851640 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl2.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl2.c,v 2.30 2001/09/24 13:22:56 kai Exp $
+  *
+  * Author       Karsten Keil
+  *              based on the teles driver from Jan den Ouden
+@@ -20,7 +20,7 @@
+ #include "hisax.h"
+ #include "isdnl2.h"
+-const char *l2_revision = "$Revision: 1.1.4.1 $";
++const char *l2_revision = "$Revision: 2.30 $";
+ static void l2m_debug(struct FsmInst *fi, char *fmt, ...);
+@@ -1418,8 +1418,8 @@
+       freewin(st);
+       st->l2.tei = -1;
+       stop_t200(st, 17);
+-      st5_dl_release_l2l3(st);
+       FsmChangeState(fi, ST_L2_1);
++      st5_dl_release_l2l3(st);
+ }
+ static void
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl2.h linux-2.4.29/drivers/isdn/hisax/isdnl2.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl2.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl2.h   2005-03-22 15:06:47.647849208 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl2.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+  *
+  * Layer 2 defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl3.c linux-2.4.29/drivers/isdn/hisax/isdnl3.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl3.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl3.c   2005-03-22 15:06:47.663846776 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl3.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isdnl3.c,v 2.22 2001/09/24 13:22:56 kai Exp $
+  *
+  * Author       Karsten Keil
+  *              based on the teles driver from Jan den Ouden
+@@ -21,7 +21,7 @@
+ #include "isdnl3.h"
+ #include <linux/config.h>
+-const char *l3_revision = "$Revision: 1.1.4.1 $";
++const char *l3_revision = "$Revision: 2.22 $";
+ static struct Fsm l3fsm;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isdnl3.h linux-2.4.29/drivers/isdn/hisax/isdnl3.h
+--- linux-2.4.29.old/drivers/isdn/hisax/isdnl3.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isdnl3.h   2005-03-22 15:06:47.679844344 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnl3.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/isurf.c linux-2.4.29/drivers/isdn/hisax/isurf.c
+--- linux-2.4.29.old/drivers/isdn/hisax/isurf.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/isurf.c    2005-03-22 15:06:47.699841304 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isurf.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: isurf.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for Siemens I-Surf/I-Talk cards
+  *
+@@ -16,11 +16,10 @@
+ #include "isac.h"
+ #include "isar.h"
+ #include "isdnl1.h"
+-#include <linux/isapnp.h>
+ extern const char *CardType[];
+-static const char *ISurf_revision = "$Revision: 1.1.4.1 $";
++static const char *ISurf_revision = "$Revision: 1.12 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -128,8 +127,10 @@
+ release_io_isurf(struct IsdnCardState *cs)
+ {
+       release_region(cs->hw.isurf.reset, 1);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+       iounmap((unsigned char *)cs->hw.isurf.isar);
+       release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
++#endif
+ }
+ static void
+@@ -194,10 +195,6 @@
+       return(isar_auxcmd(cs, ic));
+ }
+-#ifdef __ISAPNP__
+-static struct pci_bus *pnp_surf __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_isurf(struct IsdnCard *card)
+ {
+@@ -215,58 +212,9 @@
+               cs->hw.isurf.phymem = card->para[2];
+               cs->irq = card->para[0];
+       } else {
+-#ifdef __ISAPNP__
+-              struct pci_bus *pb;
+-              struct pci_dev *pd;
+-
+-              if (isapnp_present()) {
+-                      cs->subtyp = 0;
+-                      if ((pb = isapnp_find_card(
+-                              ISAPNP_VENDOR('S', 'I', 'E'),
+-                              ISAPNP_FUNCTION(0x0010), pnp_surf))) {
+-                              pnp_surf = pb;
+-                              pd = NULL;
+-                              if (!(pd = isapnp_find_dev(pnp_surf,
+-                                      ISAPNP_VENDOR('S', 'I', 'E'),
+-                                      ISAPNP_FUNCTION(0x0010), pd))) {
+-                                      printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n");
+-                                      return (0);
+-                              }
+-                              pd->prepare(pd);
+-                              pd->deactivate(pd);
+-                              pd->activate(pd);
+-                              /* The ISA-PnP logic apparently
+-                               * expects upper limit address to be
+-                               * set. Since the isa-pnp module
+-                               * doesn't do this, so we have to make
+-                               * up for it.
+-                               */
+-                              isapnp_cfg_begin(pd->bus->number, pd->devfn);
+-                              isapnp_write_word(ISAPNP_CFG_MEM+3, 
+-                                      pd->resource[8].end >> 8);
+-                              isapnp_cfg_end();
+-                              cs->hw.isurf.reset = pd->resource[0].start;
+-                              cs->hw.isurf.phymem = pd->resource[8].start;
+-                              cs->irq = pd->irq_resource[0].start;
+-                              if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) {
+-                                      printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n",
+-                                              cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem);
+-                                      pd->deactivate(pd);
+-                                      return(0);
+-                              }
+-                      } else {
+-                              printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n");
+-                              return(0);
+-                      }
+-              } else {
+-                      printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n");
+-                      return(0);
+-              }
+-#else
+               printk(KERN_WARNING "HiSax: %s port/mem not set\n",
+                       CardType[card->typ]);
+               return (0);
+-#endif
+       }
+       if (check_region(cs->hw.isurf.reset, 1)) {
+               printk(KERN_WARNING
+@@ -277,6 +225,7 @@
+       } else {
+               request_region(cs->hw.isurf.reset, 1, "isurf isdn");
+       }
++#ifdef COMPAT_HAS_ISA_IOREMAP
+       if (check_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE)) {
+               printk(KERN_WARNING
+                       "HiSax: %s memory region %lx-%lx already in use\n",
+@@ -292,6 +241,10 @@
+       cs->hw.isurf.isar =
+               (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE);
+       cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET;
++#else
++      cs->hw.isurf.isar = cs->hw.isurf.phymem + ISURF_ISAR_OFFSET;
++      cs->hw.isurf.isac = cs->hw.isurf.phymem + ISURF_ISAC_OFFSET;
++#endif
+       printk(KERN_INFO
+              "ISurf: defined at 0x%x 0x%lx IRQ %d\n",
+              cs->hw.isurf.reset,
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/ix1_micro.c linux-2.4.29/drivers/isdn/hisax/ix1_micro.c
+--- linux-2.4.29.old/drivers/isdn/hisax/ix1_micro.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/ix1_micro.c        2005-03-22 15:06:47.714839024 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: ix1_micro.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: ix1_micro.c,v 2.12 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for ITK ix1-micro Rev.2 isdn cards
+  * derived from the original file teles3.c from Karsten Keil
+@@ -19,14 +19,13 @@
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "isac.h"
+ #include "hscx.h"
+ #include "isdnl1.h"
+ extern const char *CardType[];
+-const char *ix1_revision = "$Revision: 1.1.4.1 $";
++const char *ix1_revision = "$Revision: 2.12 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -219,21 +218,6 @@
+       return(0);
+ }
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id itk_ids[] __initdata = {
+-      { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25),
+-        ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x25), 
+-        (unsigned long) "ITK micro 2" },
+-      { ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29),
+-        ISAPNP_VENDOR('I', 'T', 'K'), ISAPNP_FUNCTION(0x29), 
+-        (unsigned long) "ITK micro 2." },
+-      { 0, }
+-};
+-
+-static struct isapnp_device_id *idev = &itk_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __init
+ setup_ix1micro(struct IsdnCard *card)
+@@ -246,45 +230,6 @@
+       if (cs->typ != ISDN_CTYPE_IX1MICROR2)
+               return (0);
+-#ifdef __ISAPNP__
+-      if (!card->para[1] && isapnp_present()) {
+-              struct pci_bus *pb;
+-              struct pci_dev *pd;
+-
+-              while(idev->card_vendor) {
+-                      if ((pb = isapnp_find_card(idev->card_vendor,
+-                              idev->card_device, pnp_c))) {
+-                              pnp_c = pb;
+-                              pd = NULL;
+-                              if ((pd = isapnp_find_dev(pnp_c,
+-                                      idev->vendor, idev->function, pd))) {
+-                                      printk(KERN_INFO "HiSax: %s detected\n",
+-                                              (char *)idev->driver_data);
+-                                      pd->prepare(pd);
+-                                      pd->deactivate(pd);
+-                                      pd->activate(pd);
+-                                      card->para[1] = pd->resource[0].start;
+-                                      card->para[0] = pd->irq_resource[0].start;
+-                                      if (!card->para[0] || !card->para[1]) {
+-                                              printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n",
+-                                              card->para[0], card->para[1]);
+-                                              pd->deactivate(pd);
+-                                              return(0);
+-                                      }
+-                                      break;
+-                              } else {
+-                                      printk(KERN_ERR "ITK PnP: PnP error card found, no device\n");
+-                              }
+-                      }
+-                      idev++;
+-                      pnp_c=NULL;
+-              } 
+-              if (!idev->card_vendor) {
+-                      printk(KERN_INFO "ITK PnP: no ISAPnP card found\n");
+-                      return(0);
+-              }
+-      }
+-#endif
+       /* IO-Ports */
+       cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET;
+       cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/jade.c linux-2.4.29/drivers/isdn/hisax/jade.c
+--- linux-2.4.29.old/drivers/isdn/hisax/jade.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/jade.c     2005-03-22 15:06:47.729836744 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: jade.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: jade.c,v 1.9 2001/09/24 13:22:56 kai Exp $
+  *
+  * JADE stuff (derived from original hscx.c)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/jade.h linux-2.4.29/drivers/isdn/hisax/jade.h
+--- linux-2.4.29.old/drivers/isdn/hisax/jade.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/jade.h     2005-03-22 15:06:47.745834312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: jade.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: jade.h,v 1.5 2001/09/24 13:22:56 kai Exp $
+  *
+  * JADE specific defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/jade_irq.c linux-2.4.29/drivers/isdn/hisax/jade_irq.c
+--- linux-2.4.29.old/drivers/isdn/hisax/jade_irq.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/jade_irq.c 2005-03-22 15:06:47.760832032 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: jade_irq.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: jade_irq.c,v 1.7 2001/09/24 13:22:56 kai Exp $
+  *
+  * Low level JADE IRQ stuff (derived from original hscx_irq.c)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.c linux-2.4.29/drivers/isdn/hisax/l3_1tr6.c
+--- linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3_1tr6.c  2005-03-22 15:06:47.777829448 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3_1tr6.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: l3_1tr6.c,v 2.15 2001/09/24 13:22:56 kai Exp $
+  *
+  * German 1TR6 D-channel protocol
+  *
+@@ -20,7 +20,7 @@
+ #include <linux/ctype.h>
+ extern char *HiSax_getrev(const char *revision);
+-const char *l3_1tr6_revision = "$Revision: 1.1.4.1 $";
++const char *l3_1tr6_revision = "$Revision: 2.15 $";
+ #define MsgHead(ptr, cref, mty, dis) \
+       *ptr++ = dis; \
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.h linux-2.4.29/drivers/isdn/hisax/l3_1tr6.h
+--- linux-2.4.29.old/drivers/isdn/hisax/l3_1tr6.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3_1tr6.h  2005-03-22 15:06:47.796826560 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3_1tr6.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+  *
+  * German 1TR6 D-channel protocol defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3dss1.c linux-2.4.29/drivers/isdn/hisax/l3dss1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/l3dss1.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3dss1.c   2005-03-22 15:06:47.822822608 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3dss1.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: l3dss1.c,v 2.32 2001/09/24 13:22:56 kai Exp $
+  *
+  * EURO/DSS1 D-channel protocol
+  *
+@@ -27,7 +27,7 @@
+ #include <linux/config.h>
+ extern char *HiSax_getrev(const char *revision);
+-const char *dss1_revision = "$Revision: 1.1.4.1 $";
++const char *dss1_revision = "$Revision: 2.32 $";
+ #define EXT_BEARER_CAPS 1
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3dss1.h linux-2.4.29/drivers/isdn/hisax/l3dss1.h
+--- linux-2.4.29.old/drivers/isdn/hisax/l3dss1.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3dss1.h   2005-03-22 15:06:47.842819568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3dss1.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+  *
+  * DSS1 (Euro) D-channel protocol defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3ni1.c linux-2.4.29/drivers/isdn/hisax/l3ni1.c
+--- linux-2.4.29.old/drivers/isdn/hisax/l3ni1.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3ni1.c    2005-03-22 15:06:47.859816984 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3ni1.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: l3ni1.c,v 2.8 2001/09/24 13:22:56 kai Exp $
+  *
+  * NI1 D-channel protocol
+  *
+@@ -25,7 +25,7 @@
+ #include <linux/ctype.h>
+ extern char *HiSax_getrev(const char *revision);
+-const char *ni1_revision = "$Revision: 1.1.4.1 $";
++const char *ni1_revision = "$Revision: 2.8 $";
+ #define EXT_BEARER_CAPS 1
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/l3ni1.h linux-2.4.29/drivers/isdn/hisax/l3ni1.h
+--- linux-2.4.29.old/drivers/isdn/hisax/l3ni1.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/l3ni1.h    2005-03-22 15:06:47.877814248 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: l3ni1.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+  *
+  * NI1 D-channel protocol
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/lmgr.c linux-2.4.29/drivers/isdn/hisax/lmgr.c
+--- linux-2.4.29.old/drivers/isdn/hisax/lmgr.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/lmgr.c     2005-03-22 15:06:47.895811512 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: lmgr.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id$
+  *
+  * Layermanagement module
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/md5sums.asc linux-2.4.29/drivers/isdn/hisax/md5sums.asc
+--- linux-2.4.29.old/drivers/isdn/hisax/md5sums.asc    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/md5sums.asc        2005-03-22 15:06:47.910809232 +0100
+@@ -1,33 +1,22 @@
+------BEGIN PGP SIGNED MESSAGE-----
+-Hash: SHA1
+-
+ # This are valid md5sums for certificated HiSax driver.
+ # The certification is valid only if the md5sums of all files match.
+ # The certification is valid only for ELSA Microlink PCI,
+-# Eicon Technology Diva 2.01 PCI, Sedlbauer SpeedFax+,
+-# HFC-S PCI A based cards and HFC-S USB based ISDN
+-# terminal adapters in the moment.
++# Eicon Technology Diva 2.01 PCI, Sedlbauer SpeedFax+, 
++# HFC-S PCI A based cards and HFC-S USB based isdn tas 
++# in the moment.
+ # Read ../../../Documentation/isdn/HiSax.cert for more informations.
+ # 
+-cd4a9917e1147039d5dfc66440d42054  isac.c
+-211840e78b56c9d4753be9c85da21a50  isdnl1.c
+-5ce9b1fff42a02f9c2eb4fb81c701b1f  isdnl2.c
+-6948de0c43513dd23c6706feb5fc2209  isdnl3.c
+-3730780b69368218d756024165efea79  tei.c
+-16e72710eb58da01415b877490f5d2ac  callc.c
+-6abc55c77e0f3149ae9334f3257a1a1a  cert.c
+-27bdb2800d4590e00da20eff241edc47  l3dss1.c
+-df8bb877b854c4302d396b554e4e84ef  l3_1tr6.c
+-9d8b4bed15370063d1b16e47080f50e1  elsa.c
+-210f4a3f1eebca70229d786b15cf3e90  diva.c
+-4ddf21079dd77e892380f789bae250a7  sedlbauer.c
+-8200d818771e3cbdef2a3c3e818d25ac  hfc_pci.c
++6f9433a8b696076562562d090e3c420f  isac.c
++13c3eed869f5139f44c563e3a8fea1f5  isdnl1.c
++addcff863b0ff1e366c0f2ae9fa6e81e  isdnl2.c
++7076deb94a363945c21ea27aca4a720a  isdnl3.c
++51c603829b6cc4f8421f744ad657ceff  tei.c
++669050ab5079f02887ed0239d86e5474  callc.c
++ecacd146b8f8881ef9349935dab3df4a  cert.c
++fadeb3b85bb23bc1ac48470c0848d6fa  l3dss1.c
++cf7dec9fac6283716904d26b99188476  l3_1tr6.c
++2f75c8765e1be13d114d5f4433cf364b  elsa.c
++b4cf8a4dceed9ea6dcba65a85b4eecc7  diva.c
++dee3f8f40c6fe78a4b57729804b7e6cd  sedlbauer.c
++0d79fe6dfc5bfaa4826970c41a6d273d  hfc_pci.c
+ # end of md5sums
+------BEGIN PGP SIGNATURE-----
+-Version: GnuPG v1.0.6 (GNU/Linux)
+-Comment: For info see http://www.gnupg.org
+-
+-iD8DBQE9rE91DiY0VZsg4ukRAkKfAJ4xWUfqjc0hW+V+JPue5yr7mrt+RwCdGdSf
+-GIKgAEdRLzERmpt/bCCwAbY=
+-=FaHw
+------END PGP SIGNATURE-----
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/mic.c linux-2.4.29/drivers/isdn/hisax/mic.c
+--- linux-2.4.29.old/drivers/isdn/hisax/mic.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/mic.c      2005-03-22 15:06:47.926806800 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: mic.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: mic.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for mic cards
+  *
+@@ -19,7 +19,7 @@
+ extern const char *CardType[];
+-const char *mic_revision = "$Revision: 1.1.4.1 $";
++const char *mic_revision = "$Revision: 1.12 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/netjet.c linux-2.4.29/drivers/isdn/hisax/netjet.c
+--- linux-2.4.29.old/drivers/isdn/hisax/netjet.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/netjet.c   2005-03-22 15:06:47.941804520 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: netjet.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: netjet.c,v 1.29 2001/09/24 13:22:56 kai Exp $
+  *
+  * low level stuff for Traverse Technologie NETJet ISDN cards
+  *
+@@ -8,9 +8,7 @@
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License, incorporated herein by reference.
+  *
+- * Thanks to Traverse Technologies Australia for documents and information
+- *
+- * 16-Apr-2002 - led code added - Guy Ellis (guy@traverse.com.au)
++ * Thanks to Traverse Technologie Australia for documents and information
+  *
+  */
+@@ -26,7 +24,7 @@
+ #include <asm/io.h>
+ #include "netjet.h"
+-const char *NETjet_revision = "$Revision: 1.1.4.1 $";
++const char *NETjet_revision = "$Revision: 1.29 $";
+ /* Interface functions */
+@@ -135,7 +133,6 @@
+ mode_tiger(struct BCState *bcs, int mode, int bc)
+ {
+       struct IsdnCardState *cs = bcs->cs;
+-        u_char led;
+       if (cs->debug & L1_DEB_HSCX)
+               debugl1(cs, "Tiger mode %d bchan %d/%d",
+@@ -157,15 +154,6 @@
+                                       cs->hw.njet.dmactrl);
+                               byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0);
+                       }
+-                        if (cs->typ == ISDN_CTYPE_NETJET_S)
+-                        {
+-                                // led off
+-                                led = bc & 0x01;
+-                                led = 0x01 << (6 + led); // convert to mask
+-                                led = ~led;
+-                                cs->hw.njet.auxd &= led;
+-                                byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+-                        }
+                       break;
+               case (L1_MODE_TRANS):
+                       break;
+@@ -191,14 +179,6 @@
+                       bcs->hw.tiger.sendp = bcs->hw.tiger.send;
+                       bcs->hw.tiger.free = NETJET_DMA_TXSIZE;
+                       test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag);
+-                        if (cs->typ == ISDN_CTYPE_NETJET_S)
+-                        {
+-                                // led on
+-                                led = bc & 0x01;
+-                                led = 0x01 << (6 + led); // convert to mask
+-                                cs->hw.njet.auxd |= led;
+-                                byteout(cs->hw.njet.auxa, cs->hw.njet.auxd);
+-                        }
+                       break;
+       }
+       if (cs->debug & L1_DEB_HSCX)
+@@ -874,13 +854,9 @@
+               case (PH_ACTIVATE | REQUEST):
+                       test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag);
+                       mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc);
+-                      /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
+-                      st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc));
+                       l1_msg_b(st, pr, arg);
+                       break;
+               case (PH_DEACTIVATE | REQUEST):
+-                      /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */
+-                      st->l1.bcs->cs->cardmsg(st->l1.bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc));
+                       l1_msg_b(st, pr, arg);
+                       break;
+               case (PH_DEACTIVATE | CONFIRM):
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/netjet.h linux-2.4.29/drivers/isdn/hisax/netjet.h
+--- linux-2.4.29.old/drivers/isdn/hisax/netjet.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/netjet.h   2005-03-22 15:06:47.956802240 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: netjet.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: netjet.h,v 2.8 2001/09/24 13:22:56 kai Exp $
+  *
+  * NETjet common header file
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/niccy.c linux-2.4.29/drivers/isdn/hisax/niccy.c
+--- linux-2.4.29.old/drivers/isdn/hisax/niccy.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/niccy.c    2005-03-22 15:06:47.977799048 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: niccy.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: niccy.c,v 1.21 2001/10/20 22:05:00 kai Exp $
+  *
+  * low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and
+  * compatible (SAGEM cybermodem)
+@@ -22,10 +22,10 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+ extern const char *CardType[];
+-const char *niccy_revision = "$Revision: 1.1.4.1 $";
++const char *niccy_revision = "$Revision: 1.21 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -239,9 +239,6 @@
+ }
+ static struct pci_dev *niccy_dev __initdata = NULL;
+-#ifdef __ISAPNP__
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+ int __init
+ setup_niccy(struct IsdnCard *card)
+@@ -253,39 +250,7 @@
+       printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp));
+       if (cs->typ != ISDN_CTYPE_NICCY)
+               return (0);
+-#ifdef __ISAPNP__
+-      if (!card->para[1] && isapnp_present()) {
+-              struct pci_bus *pb;
+-              struct pci_dev *pd;
+-
+-              if ((pb = isapnp_find_card(
+-                      ISAPNP_VENDOR('S', 'D', 'A'),
+-                      ISAPNP_FUNCTION(0x0150), pnp_c))) {
+-                      pnp_c = pb;
+-                      pd = NULL;
+-                      if (!(pd = isapnp_find_dev(pnp_c,
+-                              ISAPNP_VENDOR('S', 'D', 'A'),
+-                              ISAPNP_FUNCTION(0x0150), pd))) {
+-                              printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n");
+-                              return (0);
+-                      }
+-                      pd->prepare(pd);
+-                      pd->deactivate(pd);
+-                      pd->activate(pd);
+-                      card->para[1] = pd->resource[0].start;
+-                      card->para[2] = pd->resource[1].start;
+-                      card->para[0] = pd->irq_resource[0].start;
+-                      if (!card->para[0] || !card->para[1] || !card->para[2]) {
+-                              printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n",
+-                                      card->para[0], card->para[1], card->para[2]);
+-                              pd->deactivate(pd);
+-                              return(0);
+-                      }
+-              } else {
+-                      printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n");
+-              }
+-      }
+-#endif
++
+       if (card->para[1]) {
+               cs->hw.niccy.isac = card->para[1] + ISAC_PNP;
+               cs->hw.niccy.hscx = card->para[1] + HSCX_PNP;
+@@ -331,12 +296,12 @@
+                               return(0);
+                       }
+                       cs->irq = niccy_dev->irq;
+-                      cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0);
++                      cs->hw.niccy.cfg_reg = pci_resource_start_io(niccy_dev, 0);
+                       if (!cs->hw.niccy.cfg_reg) {
+                               printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n");
+                               return(0);
+                       }
+-                      pci_ioaddr = pci_resource_start(niccy_dev, 1);
++                      pci_ioaddr = pci_resource_start_io(niccy_dev, 1);
+                       if (!pci_ioaddr) {
+                               printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n");
+                               return(0);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/nj_s.c linux-2.4.29/drivers/isdn/hisax/nj_s.c
+--- linux-2.4.29.old/drivers/isdn/hisax/nj_s.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/nj_s.c     2005-03-22 15:06:47.993796616 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: nj_s.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: nj_s.c,v 2.13 2001/09/24 13:22:56 kai Exp $
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License, incorporated herein by reference.
+@@ -12,11 +12,12 @@
+ #include "isac.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+ #include <linux/ppp_defs.h>
+ #include "netjet.h"
+-const char *NETjet_S_revision = "$Revision: 1.1.4.1 $";
++const char *NETjet_S_revision = "$Revision: 2.13 $";
+ static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
+ {
+@@ -130,7 +131,6 @@
+                       release_io_netjet(cs);
+                       return(0);
+               case CARD_INIT:
+-                      reset_netjet_s(cs);
+                       inittiger(cs);
+                       clear_pending_isac_ints(cs);
+                       initisac(cs);
+@@ -180,19 +180,11 @@
+                               printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
+                               return(0);
+                       }
+-                      cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
++                      cs->hw.njet.base = pci_resource_start_io(dev_netjet, 0);
+                       if (!cs->hw.njet.base) {
+                               printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n");
+                               return(0);
+                       }
+-                      /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */
+-                      if ((dev_netjet->subsystem_vendor == 0x55) &&
+-                              (dev_netjet->subsystem_device == 0x02)) {
+-                              printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n");
+-                              printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n");
+-                              return(0);
+-                      }
+-                      /* end new code */
+               } else {
+                       printk(KERN_WARNING "NETjet-S: No PCI card found\n");
+                       return(0);
+@@ -263,6 +255,7 @@
+       } else {
+               request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn");
+       }
++      reset_netjet_s(cs);
+       cs->readisac  = &NETjet_ReadIC;
+       cs->writeisac = &NETjet_WriteIC;
+       cs->readisacfifo  = &NETjet_ReadICfifo;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/nj_u.c linux-2.4.29/drivers/isdn/hisax/nj_u.c
+--- linux-2.4.29.old/drivers/isdn/hisax/nj_u.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/nj_u.c     2005-03-22 15:06:48.008794336 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: nj_u.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $ 
++/* $Id: nj_u.c,v 2.14 2001/09/24 13:22:56 kai Exp $ 
+  *
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License, incorporated herein by reference.
+@@ -12,11 +12,12 @@
+ #include "icc.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ #include <linux/interrupt.h>
+ #include <linux/ppp_defs.h>
+ #include "netjet.h"
+-const char *NETjet_U_revision = "$Revision: 1.1.4.1 $";
++const char *NETjet_U_revision = "$Revision: 2.14 $";
+ static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
+ {
+@@ -181,7 +182,7 @@
+                               printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
+                               return(0);
+                       }
+-                      cs->hw.njet.base = pci_resource_start(dev_netjet, 0);
++                      cs->hw.njet.base = pci_resource_start_io(dev_netjet, 0);
+                       if (!cs->hw.njet.base) {
+                               printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n");
+                               return(0);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/q931.c linux-2.4.29/drivers/isdn/hisax/q931.c
+--- linux-2.4.29.old/drivers/isdn/hisax/q931.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/q931.c     2005-03-22 15:06:48.032790688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: q931.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: q931.c,v 1.12 2001/09/24 13:22:56 kai Exp $
+  *
+  * code to decode ITU Q.931 call control messages
+  *
+@@ -197,6 +197,31 @@
+ #define MT_N1_LEN (sizeof(mt_n1) / sizeof(struct MessageType))
++#if 0
++static struct MessageType fac_1tr6[] =
++{
++      {FAC_Sperre, "Sperre"},
++      {FAC_Forward1, "Forward 1"},
++      {FAC_Forward2, "Forward 2"},
++      {FAC_Konferenz, "Konferenz"},
++      {FAC_GrabBchan, "Grab Bchannel"},
++      {FAC_Reactivate, "Reactivate"},
++      {FAC_Konferenz3, "Dreier Konferenz"},
++      {FAC_Dienstwechsel1, "Einseitiger Dienstwechsel"},
++      {FAC_Dienstwechsel2, "Zweiseitiger Dienstwechsel"},
++      {FAC_NummernIdent, "Rufnummer-Identifizierung"},
++      {FAC_GBG, "GBG"},
++      {FAC_DisplayUebergeben, "Display Uebergeben"},
++      {FAC_DisplayUmgeleitet, "Display Umgeleitet"},
++      {FAC_Unterdruecke, "Unterdruecke Rufnummer"},
++      {FAC_Deactivate, "Deactivate"},
++      {FAC_Activate, "Activate"},
++      {FAC_SPV, "SPV"},
++      {FAC_Rueckwechsel, "Rueckwechsel"},
++      {FAC_Umleitung, "Umleitung"}
++};
++#define FAC_1TR6_LEN (sizeof(fac_1tr6) / sizeof(struct MessageType))
++#endif
+ static int
+ prbits(char *dest, u_char b, int start, int len)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.c linux-2.4.29/drivers/isdn/hisax/rawhdlc.c
+--- linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.c      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/rawhdlc.c  2005-03-22 15:06:48.047788408 +0100
+@@ -0,0 +1,543 @@
++/* $Id: rawhdlc.c,v 1.7 2001/09/24 13:22:57 kai Exp $
++ *
++ * support routines for cards that don't support HDLC
++ *
++ * Author     Brent Baccala
++ * Copyright  by Karsten Keil <keil@isdn4linux.de>
++ *            by Brent Baccala <baccala@FreeSoft.org>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ *
++ * Some passive ISDN cards, such as the Traverse NETJet and the AMD 7930,
++ * don't perform HDLC encapsulation over the B channel.  Drivers for
++ * such cards use support routines in this file to perform B channel HDLC.
++ *
++ * Bit-synchronous HDLC encapsulation is a means of encapsulating packets
++ * over a continuously transmitting serial communications link.
++ * It looks like this:
++ *
++ *      11111111101111110...........0111111011111111111
++ *      iiiiiiiiiffffffffdddddddddddffffffffiiiiiiiiiii
++ *
++ *      i = idle     f = flag     d = data
++ *
++ * When idle, the channel sends a continuous string of ones (mark
++ * idle; illustrated), or a continuous string of flag characters (flag
++ * idle).  The beginning of a data frame is marked by a flag character
++ * (01111110), then comes the actual data, followed by another flag
++ * character, after which another frame may be sent immediately (a
++ * single flag may serve as both the end of one frame and the start of
++ * the next), or the link may return to idle.  Obviously, the flag
++ * character can not appear anywhere in the data (or a false
++ * end-of-frame would occur), so the transmitter performs
++ * "bit-stuffing" - inserting a zero bit after every five one bits,
++ * irregardless of the original bit after the five ones.  Byte
++ * ordering is irrelevent at this point - the data is treated as a
++ * string of bits, not bytes.  Since no more than 5 ones may now occur
++ * in a row, the flag sequence, with its 6 ones, is unique.
++ *
++ * Upon reception, a zero bit that occur after 5 one bits is simply
++ * discarded.  A series of 6 one bits is end-of-frame, and a series of
++ * 7 one bits is an abort.  Once bit-stuffing has been corrected for,
++ * an integer number of bytes should now be present.  The last two
++ * of these bytes form the Frame Check Sequence, a CRC that is verified
++ * and then discarded.  Note that bit-stuffing is performed on the FCS
++ * just as if it were regular data.
++ *
++ *
++ *
++ * int make_raw_hdlc_data(u_char *src, u_int slen,
++ *                        u_char *dst, u_int dsize)
++ *
++ *   Used for transmission.  Copies slen bytes from src to dst, performing
++ *   HDLC encapsulation (flag bytes, bit-stuffing, CRC) in the process.
++ *   dsize is size of destination buffer, and should be at least
++ *   ((6*slen)/5)+5 bytes to ensure adequate space will be available.
++ *   Function returns length (in bytes) of valid destination buffer, or
++ *   0 upon destination overflow.
++ *
++ * void init_hdlc_state(struct hdlc_state *stateptr, int mode)
++ *
++ *   Initializes hdlc_state structure before first call to read_raw_hdlc_data
++ *
++ *   mode = 0: Sane mode
++ *   mode = 1/2: 
++ *             Insane mode; NETJet use a shared unsigned int memory block (
++ *           with busmaster DMA), the bit pattern of every word is 
++ *           <8 B1> <8 B2> <8 Mon> <2 D> <4 C/I> <MX> <MR>
++ *           according to Siemens IOM-2 interface, so we have to handle
++ *             the src buffer as unsigned int and have to shift/mask the
++ *             B-channel bytes.
++ *             mode 1 -> B1  mode 2  -> B2 data is used
++ *
++ * int read_raw_hdlc_data(struct hdlc_state *saved_state,
++ *                        u_char *src, u_int slen,
++ *                        u_char *dst, u_int dsize)
++ *
++ *   Used for reception.  Scans source buffer bit-by-bit looking for
++ *   valid HDLC frames, which are copied to destination buffer.  HDLC
++ *   state information is stored in a structure, which allows this
++ *   function to process frames spread across several blocks of raw
++ *   HDLC data.  Part of the state information is bit offsets into
++ *   the source and destination buffers.
++ *
++ *   A return value >0 indicates the length of a valid frame, now
++ *   stored in the destination buffer.  In this case, the source
++ *   buffer might not be completely processed, so this function should
++ *   be called again with the same source buffer, possibly with a
++ *   different destination buffer.
++ *
++ *   A return value of zero indicates that the source buffer was
++ *   completely processed without finding a valid end-of-packet;
++ *   however, we might be in the middle of packet reception, so
++ *   the function should be called again with the next block of
++ *   raw HDLC data and the same destination buffer.  It is NOT
++ *   permitted to change the destination buffer in this case,
++ *   since data may already have begun to be stored there.
++ *
++ *   A return value of -1 indicates some kind of error - destination
++ *   buffer overflow, CRC check failed, frame not a multiple of 8
++ *   bits.  Destination buffer probably contains invalid data, which
++ *   should be discarded.  Call function again with same source buffer
++ *   and a new (or same) destination buffer.
++ *
++ *   Suggested calling sequence:
++ *
++ *      init_hdlc_state(...);
++ *      for (EACH_RAW_DATA_BLOCK) {
++ *         while (len = read_raw_hdlc_data(...)) {
++ *             if (len == -1) DISCARD_FRAME;
++ *             else PROCESS_FRAME;
++ *         }
++ *      }
++ *
++ *
++ * Test the code in this file as follows:
++ *    gcc -DDEBUGME -o rawhdlctest rawhdlc.c
++ *    ./rawhdlctest < rawdata
++ *
++ * The file "rawdata" can be easily generated from a HISAX B-channel
++ * hex dump (CF CF CF 02 ...) using the following perl script:
++ *
++ * while(<>) {
++ *     @hexlist = split ' ';
++ *     while ($hexstr = shift(@hexlist)) {
++ *         printf "%c", hex($hexstr);
++ *     }
++ * }
++ *
++ */
++
++#ifdef DEBUGME
++#include <stdio.h>
++#endif
++
++#include <linux/types.h>
++#include <linux/ppp_defs.h>
++#include "rawhdlc.h"
++
++/* There's actually an identical copy of this table in the PPP code
++ * (ppp_crc16_table), but I don't want this code dependent on PPP
++ */
++
++// static 
++__u16 fcstab[256] =
++{
++      0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
++      0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
++      0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
++      0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
++      0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
++      0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
++      0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
++      0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
++      0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
++      0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
++      0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
++      0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
++      0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
++      0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
++      0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
++      0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
++      0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
++      0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
++      0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
++      0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
++      0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
++      0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
++      0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
++      0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
++      0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
++      0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
++      0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
++      0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
++      0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
++      0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
++      0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
++      0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
++};
++
++#define HDLC_ZERO_SEARCH 0
++#define HDLC_FLAG_SEARCH 1
++#define HDLC_FLAG_FOUND  2
++#define HDLC_FRAME_FOUND 3
++#define HDLC_NULL 4
++#define HDLC_PART 5
++#define HDLC_FULL 6
++
++#define HDLC_FLAG_VALUE       0x7e
++
++
++#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \
++                      bitcnt++;\
++                      out_val >>= 1;\
++                      if (val & 1) {\
++                              s_one++;\
++                              out_val |= 0x80;\
++                      } else {\
++                              s_one = 0;\
++                              out_val &= 0x7f;\
++                      }\
++                      if (bitcnt==8) {\
++                              if (d_cnt == dsize) return 0;\
++                              dst[d_cnt++] = out_val;\
++                              bitcnt = 0;\
++                      }\
++                      if (s_one == 5) {\
++                              out_val >>= 1;\
++                              out_val &= 0x7f;\
++                              bitcnt++;\
++                              s_one = 0;\
++                      }\
++                      if (bitcnt==8) {\
++                              if (d_cnt == dsize) return 0;\
++                              dst[d_cnt++] = out_val;\
++                              bitcnt = 0;\
++                      }\
++                      val >>= 1;\
++              }
++
++/* Optimization suggestion: If needed, this function could be
++ * dramatically sped up using a state machine.  Each state would
++ * correspond to having seen N one bits, and being offset M bits into
++ * the current output byte.  N ranges from 0 to 4, M from 0 to 7, so
++ * we need 5*8 = 35 states.  Each state would have a table with 256
++ * entries, one for each input character.  Each entry would contain
++ * three output characters, an output state, an a byte increment
++ * that's either 1 or 2.  All this could fit in four bytes; so we need
++ * 4 bytes * 256 characters = 1 KB for each state (35 KB total).  Zero
++ * the output buffer before you start.  For each character in your
++ * input, you look it up in the current state's table and get three
++ * bytes to be or'ed into the output at the current byte offset, and
++ * an byte increment to move your pointer forward.  A simple Perl
++ * script could generate the tables.  Given HDLC semantics, probably
++ * would be better to set output to all 1s, then use ands instead of ors.
++ * A smaller state machine could operate on nibbles instead of bytes.
++ * A state machine for 32-bit architectures could use word offsets
++ * instead of byte offsets, requiring 5*32 = 160 states; probably
++ * best to work on nibbles in such a case.
++ */
++
++
++int make_raw_hdlc_data(u_char *src, u_int slen, u_char *dst, u_int dsize)
++{
++      register u_int i,d_cnt=0;
++      register u_char j;
++      register u_char val;
++      register u_char s_one = 0;
++      register u_char out_val = 0;
++      register u_char bitcnt = 0;
++      u_int fcs;
++      
++      
++      dst[d_cnt++] = HDLC_FLAG_VALUE;
++      fcs = PPP_INITFCS;
++      for (i=0; i<slen; i++) {
++              val = src[i];
++              fcs = PPP_FCS (fcs, val);
++              MAKE_RAW_BYTE;
++      }
++      fcs ^= 0xffff;
++      val = fcs & 0xff;
++      MAKE_RAW_BYTE;
++      val = (fcs>>8) & 0xff;
++      MAKE_RAW_BYTE;
++      val = HDLC_FLAG_VALUE;
++      for (j=0; j<8; j++) { 
++              bitcnt++;
++              out_val >>= 1;
++              if (val & 1)
++                      out_val |= 0x80;
++              else
++                      out_val &= 0x7f;
++              if (bitcnt==8) {
++                      if (d_cnt == dsize) return 0;
++                      dst[d_cnt++] = out_val;
++                      bitcnt = 0;
++              }
++              val >>= 1;
++      }
++      if (bitcnt) {
++              while (8>bitcnt++) {
++                      out_val >>= 1;
++                      out_val |= 0x80;
++              }
++              if (d_cnt == dsize) return 0;
++              dst[d_cnt++] = out_val;
++      }
++
++      return d_cnt;
++}
++
++void init_hdlc_state(struct hdlc_state *stateptr, int mode)
++{
++      stateptr->state = HDLC_ZERO_SEARCH;
++      stateptr->r_one = 0;
++      stateptr->r_val = 0;
++      stateptr->o_bitcnt = 0;
++      stateptr->i_bitcnt = 0;
++      stateptr->insane_mode = mode;
++}
++
++/* Optimization suggestion: A similar state machine could surely
++ * be developed for this function as well.
++ */
++
++int read_raw_hdlc_data(struct hdlc_state *saved_state,
++                       u_char *src, u_int slen, u_char *dst, u_int dsize)
++{
++      int retval=0;
++      register u_char val;
++      register u_char state = saved_state->state;
++      register u_char r_one = saved_state->r_one;
++      register u_char r_val = saved_state->r_val;
++      register u_int o_bitcnt = saved_state->o_bitcnt;
++      register u_int i_bitcnt = saved_state->i_bitcnt;
++      register u_int fcs    = saved_state->fcs;
++      register u_int *isrc = (u_int *) src;
++        
++      /* Use i_bitcnt (bit offset into source buffer) to reload "val"
++       * in case we're starting up again partway through a source buffer
++       */
++
++      if ((i_bitcnt >> 3) < slen) {
++              if (saved_state->insane_mode==1) {
++                      val = isrc[(i_bitcnt >> 3)] & 0xff;
++              } else if (saved_state->insane_mode==2) {
++                      val = (isrc[i_bitcnt >> 3] >>8) & 0xff;
++              } else {
++                      val = src[i_bitcnt >> 3];
++              }
++              val >>= i_bitcnt & 7;
++      }
++
++      /* One bit per loop.  Keep going until we've got something to
++       * report (retval != 0), or we exhaust the source buffer
++       */
++
++      while ((retval == 0) && ((i_bitcnt >> 3) < slen)) {
++              if ((i_bitcnt & 7) == 0) {
++                      if (saved_state->insane_mode==1) {
++                              val = isrc[(i_bitcnt >> 3)] & 0xff;
++                      } else if (saved_state->insane_mode==2) {
++                              val = (isrc[i_bitcnt >> 3] >>8) & 0xff;
++                      } else {
++                              val = src[i_bitcnt >> 3];
++                      }
++#ifdef DEBUGME
++                      printf("Input byte %d: 0x%2x\n", i_bitcnt>>3, val);
++#endif
++                      if (val == 0xff) {
++                              state = HDLC_ZERO_SEARCH;
++                              o_bitcnt = 0;
++                              r_one = 0;
++                              i_bitcnt += 8;
++                              continue;
++                      }
++              }
++
++#ifdef DEBUGME
++              /* printf("Data bit=%d (%d/%d)\n", val&1, i_bitcnt>>3, i_bitcnt&7);*/
++#endif
++
++              if (state == HDLC_ZERO_SEARCH) {
++                      if (val & 1) {
++                              r_one++;
++                      } else {
++                              r_one=0;
++                              state= HDLC_FLAG_SEARCH;
++                      }
++              } else if (state == HDLC_FLAG_SEARCH) { 
++                      if (val & 1) {
++                              r_one++;
++                              if (r_one>6) {
++                                      state=HDLC_ZERO_SEARCH;
++                              }
++                      } else {
++                              if (r_one==6) {
++                                      o_bitcnt=0;
++                                      r_val=0;
++                                      state=HDLC_FLAG_FOUND;
++                              }
++                              r_one=0;
++                      }
++              } else if (state ==  HDLC_FLAG_FOUND) {
++                      if (val & 1) {
++                              r_one++;
++                              if (r_one>6) {
++                                      state=HDLC_ZERO_SEARCH;
++                              } else {
++                                      r_val >>= 1;
++                                      r_val |= 0x80;
++                                      o_bitcnt++;
++                              }
++                      } else {
++                              if (r_one==6) {
++                                      o_bitcnt=0;
++                                      r_val=0;
++                                      r_one=0;
++                                      i_bitcnt++;
++                                      val >>= 1;
++                                      continue;
++                              } else if (r_one!=5) {
++                                      r_val >>= 1;
++                                      r_val &= 0x7f;
++                                      o_bitcnt++;
++                              }
++                              r_one=0;        
++                      }
++                      if ((state != HDLC_ZERO_SEARCH) &&
++                              !(o_bitcnt & 7)) {
++#ifdef DEBUGME
++                              printf("HDLC_FRAME_FOUND at i_bitcnt:%d\n",i_bitcnt);
++#endif
++                              state=HDLC_FRAME_FOUND;
++                              fcs = PPP_INITFCS;
++                              dst[0] = r_val;
++                              fcs = PPP_FCS (fcs, r_val);
++                      }
++              } else if (state ==  HDLC_FRAME_FOUND) {
++                      if (val & 1) {
++                              r_one++;
++                              if (r_one>6) {
++                                      state=HDLC_ZERO_SEARCH;
++                                      o_bitcnt=0;
++                              } else {
++                                      r_val >>= 1;
++                                      r_val |= 0x80;
++                                      o_bitcnt++;
++                              }
++                      } else {
++                              if (r_one==6) {
++                                      r_val=0; 
++                                      r_one=0;
++                                      o_bitcnt++;
++                                      if (o_bitcnt & 7) {
++                                              /* Alignment error */
++#ifdef DEBUGME
++                                              printf("Alignment error\n");
++#endif
++                                              state=HDLC_FLAG_SEARCH;
++                                              retval = -1;
++                                      } else if (fcs==PPP_GOODFCS) {
++                                              /* Valid frame */
++                                              state=HDLC_FLAG_FOUND;
++                                              retval = (o_bitcnt>>3)-3;
++                                      } else {
++                                              /* CRC error */
++#ifdef DEBUGME
++                                              printf("CRC error; fcs was 0x%x, should have been 0x%x\n", fcs, PPP_GOODFCS);
++#endif
++                                              state=HDLC_FLAG_FOUND;
++                                              retval = -1;
++                                      }
++                              } else if (r_one==5) {
++                                      r_one=0;
++                                      i_bitcnt++;
++                                      val >>= 1;
++                                      continue;
++                              } else {
++                                      r_val >>= 1;
++                                      r_val &= 0x7f;
++                                      o_bitcnt++;
++                              }
++                              r_one=0;        
++                      }
++                      if ((state == HDLC_FRAME_FOUND) &&
++                              !(o_bitcnt & 7)) {
++                              if ((o_bitcnt>>3)>=dsize) {
++                                      /* Buffer overflow error */
++#ifdef DEBUGME
++                                      printf("Buffer overflow error\n");
++#endif
++                                      r_val=0; 
++                                      state=HDLC_FLAG_SEARCH;
++                                      retval = -1;
++                              } else {
++                                      dst[(o_bitcnt>>3)-1] = r_val;
++                                      fcs = PPP_FCS (fcs, r_val);
++#ifdef DEBUGME
++                                      printf("Output byte %d: 0x%02x; FCS 0x%04x\n", (o_bitcnt>>3)-1, r_val, fcs);
++#endif
++                              }
++                      }
++              }
++              i_bitcnt ++;
++              val >>= 1;
++      }
++
++      /* We exhausted the source buffer before anything else happened
++       * (retval==0).  Reset i_bitcnt in expectation of a new source
++       * buffer.  Other, we either had an error or a valid frame, so
++       * reset o_bitcnt in expectation of a new destination buffer.
++       */
++
++      if (retval == 0) {
++              i_bitcnt = 0;
++      } else {
++              o_bitcnt = 0;
++      }
++
++      saved_state->state = state;
++      saved_state->r_one = r_one;
++      saved_state->r_val = r_val;
++      saved_state->fcs = fcs;
++      saved_state->o_bitcnt = o_bitcnt;
++      saved_state->i_bitcnt = i_bitcnt;
++
++      return (retval);
++}
++
++
++
++#ifdef DEBUGME
++
++char buffer[1024];
++char obuffer[1024];
++
++main()
++{
++  int buflen=0;
++  int len;
++  struct hdlc_state hdlc_state;
++
++  while((buffer[buflen] = getc(stdin)) != EOF && buflen<1024) buflen++;
++
++  printf("buflen = %d\n", buflen);
++
++  init_hdlc_state(&hdlc_state, 0);
++
++  while (len = read_raw_hdlc_data(&hdlc_state,buffer,buflen,obuffer,1024)) {
++    if (len == -1) printf("Error @ byte %d/bit %d\n",
++                        hdlc_state.i_bitcnt>>3, hdlc_state.i_bitcnt & 7);
++    else {
++      printf("Frame received: len %d\n", len);
++    }
++  }
++
++  printf("Done\n");
++}
++
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.h linux-2.4.29/drivers/isdn/hisax/rawhdlc.h
+--- linux-2.4.29.old/drivers/isdn/hisax/rawhdlc.h      1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/rawhdlc.h  2005-03-22 15:06:48.076784000 +0100
+@@ -0,0 +1,28 @@
++/* $Id: rawhdlc.h,v 1.5 2001/09/24 13:22:57 kai Exp $
++ *
++ * Author     Brent Baccala
++ * Copyright  by Brent Baccala <baccala@FreeSoft.org>
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ */
++
++#ifndef RAWHDLC_H
++struct hdlc_state {
++      char insane_mode;
++      u_char state;
++      u_char r_one;
++      u_char r_val;
++      u_int o_bitcnt;
++      u_int i_bitcnt;
++      u_int fcs;
++};
++
++
++int make_raw_hdlc_data(u_char *src, u_int slen, u_char *dst, u_int dsize);
++void init_hdlc_state(struct hdlc_state *stateptr, int mode);
++int read_raw_hdlc_data(struct hdlc_state *saved_state,
++                       u_char *src, u_int slen, u_char *dst, u_int dsize);
++#define RAWHDLC_H
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/s0box.c linux-2.4.29/drivers/isdn/hisax/s0box.c
+--- linux-2.4.29.old/drivers/isdn/hisax/s0box.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/s0box.c    2005-03-22 15:06:48.092781568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: s0box.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: s0box.c,v 2.6 2001/09/24 13:22:57 kai Exp $
+  *
+  * low level stuff for Creatix S0BOX
+  *
+@@ -18,7 +18,7 @@
+ #include "isdnl1.h"
+ extern const char *CardType[];
+-const char *s0box_revision = "$Revision: 1.1.4.1 $";
++const char *s0box_revision = "$Revision: 2.6 $";
+ static inline void
+ writereg(unsigned int padr, signed int addr, u_char off, u_char val) {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/saphir.c linux-2.4.29/drivers/isdn/hisax/saphir.c
+--- linux-2.4.29.old/drivers/isdn/hisax/saphir.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/saphir.c   2005-03-22 15:06:48.107779288 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: saphir.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: saphir.c,v 1.10 2001/09/24 13:22:57 kai Exp $
+  *
+  * low level stuff for HST Saphir 1
+  *
+@@ -20,7 +20,7 @@
+ #include "isdnl1.h"
+ extern const char *CardType[];
+-static char *saphir_rev = "$Revision: 1.1.4.1 $";
++static char *saphir_rev = "$Revision: 1.10 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/sedlbauer.c linux-2.4.29/drivers/isdn/hisax/sedlbauer.c
+--- linux-2.4.29.old/drivers/isdn/hisax/sedlbauer.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/sedlbauer.c        2005-03-22 15:06:48.123776856 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: sedlbauer.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: sedlbauer.c,v 1.34 2002/02/09 21:00:57 keil Exp $
+  *
+  * low level stuff for Sedlbauer cards
+  * includes support for the Sedlbauer speed star (speed star II),
+@@ -48,18 +48,19 @@
+ #include "isar.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
+-#include <linux/isapnp.h>
++#include <linux/isdn_compat.h>
+ extern const char *CardType[];
+-const char *Sedlbauer_revision = "$Revision: 1.1.4.1 $";
++const char *Sedlbauer_revision = "$Revision: 1.34 $";
+ const char *Sedlbauer_Types[] =
+       {"None", "speed card/win", "speed star", "speed fax+",
+       "speed win II / ISDN PC/104", "speed star II", "speed pci",
+-      "speed fax+ pyramid", "speed fax+ pci"};
++      "speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"};
+ #define PCI_SUBVENDOR_SPEEDFAX_PYRAMID        0x51
++#define PCI_SUBVENDOR_HST_SAPHIR3     0x52
+ #define PCI_SUBVENDOR_SEDLBAUER_PCI   0x53
+ #define PCI_SUBVENDOR_SPEEDFAX_PCI    0x54
+ #define PCI_SUB_ID_SEDLBAUER          0x01
+@@ -72,6 +73,7 @@
+ #define SEDL_SPEED_PCI        6
+ #define SEDL_SPEEDFAX_PYRAMID 7
+ #define SEDL_SPEEDFAX_PCI     8
++#define HST_SAPHIR3           9
+ #define SEDL_CHIP_TEST                0
+ #define SEDL_CHIP_ISAC_HSCX   1
+@@ -531,21 +533,6 @@
+ static struct pci_dev *dev_sedl __devinitdata = NULL;
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id sedl_ids[] __initdata = {
+-      { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01),
+-        ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x01), 
+-        (unsigned long) "Speed win" },
+-      { ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02),
+-        ISAPNP_VENDOR('S', 'A', 'G'), ISAPNP_FUNCTION(0x02), 
+-        (unsigned long) "Speed Fax+" },
+-      { 0, }
+-};
+-
+-static struct isapnp_device_id *pdev = &sedl_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __devinit
+ setup_sedlbauer(struct IsdnCard *card)
+ {
+@@ -581,57 +568,6 @@
+                       bytecnt = 16;
+               }
+       } else {
+-#ifdef __ISAPNP__
+-              if (isapnp_present()) {
+-                      struct pci_bus *pb;
+-                      struct pci_dev *pd;
+-
+-                      while(pdev->card_vendor) {
+-                              if ((pb = isapnp_find_card(pdev->card_vendor,
+-                                      pdev->card_device, pnp_c))) {
+-                                      pnp_c = pb;
+-                                      pd = NULL;
+-                                      if ((pd = isapnp_find_dev(pnp_c,
+-                                              pdev->vendor, pdev->function, pd))) {
+-                                              printk(KERN_INFO "HiSax: %s detected\n",
+-                                                      (char *)pdev->driver_data);
+-                                              pd->prepare(pd);
+-                                              pd->deactivate(pd);
+-                                              pd->activate(pd);
+-                                              card->para[1] =
+-                                                      pd->resource[0].start;
+-                                              card->para[0] =
+-                                                      pd->irq_resource[0].start;
+-                                              if (!card->para[0] || !card->para[1]) {
+-                                                      printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n",
+-                                                              card->para[0], card->para[1]);
+-                                                      pd->deactivate(pd);
+-                                                      return(0);
+-                                              }
+-                                              cs->hw.sedl.cfg_reg = card->para[1];
+-                                              cs->irq = card->para[0];
+-                                              if (pdev->function == ISAPNP_FUNCTION(0x2)) {
+-                                                      cs->subtyp = SEDL_SPEED_FAX;
+-                                                      cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+-                                                      bytecnt = 16;
+-                                              } else {
+-                                                      cs->subtyp = SEDL_SPEED_CARD_WIN;
+-                                                      cs->hw.sedl.chip = SEDL_CHIP_TEST;
+-                                              }
+-                                              goto ready;
+-                                      } else {
+-                                              printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n");
+-                                              return(0);
+-                                      }
+-                              }
+-                              pdev++;
+-                              pnp_c=NULL;
+-                      } 
+-                      if (!pdev->card_vendor) {
+-                              printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n");
+-                      }
+-              }
+-#endif
+ /* Probe for Sedlbauer speed pci */
+ #if CONFIG_PCI
+               if (!pci_present()) {
+@@ -647,15 +583,15 @@
+                               printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n");
+                               return(0);
+                       }
+-                      cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0);
++                      cs->hw.sedl.cfg_reg = pci_resource_start_io(dev_sedl, 0);
+               } else {
+                       printk(KERN_WARNING "Sedlbauer: No PCI card found\n");
+                       return(0);
+               }
+               cs->irq_flags |= SA_SHIRQ;
+               cs->hw.sedl.bus = SEDL_BUS_PCI;
+-              sub_vendor_id = dev_sedl->subsystem_vendor;
+-              sub_id = dev_sedl->subsystem_device;
++              pci_get_sub_vendor(dev_sedl,sub_vendor_id);
++              pci_get_sub_system(dev_sedl,sub_id);
+               printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n",
+                       sub_vendor_id, sub_id);
+               printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n",
+@@ -670,6 +606,9 @@
+               } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) {
+                       cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR;
+                       cs->subtyp = SEDL_SPEEDFAX_PCI;
++              } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) {
++                      cs->hw.sedl.chip = SEDL_CHIP_IPAC;
++                      cs->subtyp = HST_SAPHIR3;
+               } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) {
+                       cs->hw.sedl.chip = SEDL_CHIP_IPAC;
+                       cs->subtyp = SEDL_SPEED_PCI;
+@@ -683,8 +622,8 @@
+               cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF;
+               byteout(cs->hw.sedl.cfg_reg, 0xff);
+               byteout(cs->hw.sedl.cfg_reg, 0x00);
+-              byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd);
+-              byteout(cs->hw.sedl.cfg_reg+ 5, 0x02);
++              byteout(cs->hw.sedl.cfg_reg +2, 0xdd);
++              byteout(cs->hw.sedl.cfg_reg +5, 0x02);
+               byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on);
+               save_flags(flags);
+               sti();
+@@ -697,7 +636,7 @@
+               return (0);
+ #endif /* CONFIG_PCI */
+       }       
+-ready:        
++      
+       /* In case of the sedlbauer pcmcia card, this region is in use,
+        * reserved for us by the card manager. So we do not check it
+        * here, it would fail.
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/sportster.c linux-2.4.29/drivers/isdn/hisax/sportster.c
+--- linux-2.4.29.old/drivers/isdn/hisax/sportster.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/sportster.c        2005-03-22 15:06:48.169769864 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: sportster.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: sportster.c,v 1.16 2001/09/24 13:22:57 kai Exp $
+  *
+  * low level stuff for USR Sportster internal TA
+  *
+@@ -20,7 +20,7 @@
+ #include "isdnl1.h"
+ extern const char *CardType[];
+-const char *sportster_revision = "$Revision: 1.1.4.1 $";
++const char *sportster_revision = "$Revision: 1.16 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481-debug.h linux-2.4.29/drivers/isdn/hisax/st5481-debug.h
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481-debug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481-debug.h     2005-03-22 15:06:48.184767584 +0100
+@@ -0,0 +1,103 @@
++#define ST5481_DEBUG 0x0
++
++#if ST5481_DEBUG
++
++
++/*
++  DEBUG flags. Set compile option  ST5481_DEBUG with the following bits set to trace
++  the given subsections:
++
++  0x01:  USB
++  0x02:  D
++  0x04:  B
++  0x08:  PH
++  0x10:  PACKET_DUMP D out
++  0x20:  ISO_DUMP D out
++  0x40:  PACKET_DUMP D in
++  0x80:  ISO_DUMP in
++  0x100: PACKET_DUMP B out
++  0x200: ISO_DUMP B out
++  0x400: PACKET_DUMP B in
++*/
++
++#define DBG(level, format, arg...) \
++if (level &  ST5481_DEBUG) \
++printk(KERN_DEBUG __FUNCTION__ ": " format "\n" , ## arg) \
++
++static inline void 
++dump_packet(const char *name,const u_char *data,int pkt_len)
++{
++#define DUMP_HDR_SIZE 200
++#define DUMP_TLR_SIZE 8
++      if (pkt_len) {
++              int i,len1,len2;
++
++              printk(KERN_DEBUG "%s: length=%d,data=",name,pkt_len);
++
++              if (pkt_len >  DUMP_HDR_SIZE+ DUMP_TLR_SIZE) {
++                      len1 = DUMP_HDR_SIZE;
++                      len2 = DUMP_TLR_SIZE;
++              } else {
++                      len1 = pkt_len > DUMP_HDR_SIZE ? DUMP_HDR_SIZE : pkt_len;
++                      len2 = 0;                       
++              }
++              for (i = 0; i < len1; ++i) {
++                      printk ("%.2x", data[i]);
++              }
++              if (len2) {
++                      printk ("..");
++                      for (i = pkt_len-DUMP_TLR_SIZE; i < pkt_len; ++i) {
++                              printk ("%.2x", data[i]);
++                      }
++              }
++              printk ("\n");
++      }
++#undef DUMP_HDR_SIZE
++#undef DUMP_TLR_SIZE
++}
++
++static inline void 
++dump_iso_packet(const char *name,urb_t *urb)
++{
++      int i,j;
++      int len,ofs;
++      u_char *data;
++
++      printk(KERN_DEBUG "%s: packets=%d,errors=%d\n",
++             name,urb->number_of_packets,urb->error_count);
++      for (i = 0; i  < urb->number_of_packets; ++i) {
++              if (urb->pipe & USB_DIR_IN) {
++                      len = urb->iso_frame_desc[i].actual_length;
++              } else {
++                      len = urb->iso_frame_desc[i].length;
++              }
++              ofs = urb->iso_frame_desc[i].offset;
++              printk(KERN_DEBUG "len=%.2d,ofs=%.3d ",len,ofs);
++              if (len) {
++                      data = urb->transfer_buffer+ofs;
++                      for (j=0; j < len; j++) {
++                              printk ("%.2x", data[j]);
++                      }
++              }
++              printk("\n");
++      }
++}
++
++#define DUMP_PACKET(level,data,count) \
++  if (level & ST5481_DEBUG) dump_packet(__FUNCTION__,data,count)
++#define DUMP_SKB(level,skb) \
++  if ((level & ST5481_DEBUG) && skb) dump_packet(__FUNCTION__,skb->data,skb->len)
++#define DUMP_ISO_PACKET(level,urb) \
++  if (level & ST5481_DEBUG) dump_iso_packet(__FUNCTION__,urb)
++
++#else
++
++#define DBG(level,format, arg...) do {} while (0)
++#define DUMP_PACKET(level,data,count) do {} while (0)
++#define DUMP_SKB(level,skb) do {} while (0)
++#define DUMP_ISO_PACKET(level,urb) do {} while (0)
++
++#endif
++
++
++
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481.h linux-2.4.29/drivers/isdn/hisax/st5481.h
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481.h   2005-03-22 15:06:48.201765000 +0100
+@@ -219,15 +219,15 @@
+ #define L1_EVENT_COUNT (EV_TIMER3 + 1)
+ #define ERR(format, arg...) \
+-printk(KERN_ERR "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
++printk(KERN_ERR __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+ #define WARN(format, arg...) \
+-printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
++printk(KERN_WARNING __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+ #define INFO(format, arg...) \
+-printk(KERN_INFO "%s:%s: " format "\n" , __FILE__,  __FUNCTION__ , ## arg)
++printk(KERN_INFO __FILE__ ": " __FUNCTION__ ": " format "\n" , ## arg)
+-#include "isdnhdlc.h"
++#include "st5481_hdlc.h"
+ #include "fsm.h"
+ #include "hisax_if.h"
+ #include <linux/skbuff.h>
+@@ -236,7 +236,7 @@
+  * FIFO handling
+  */
+-/* Generic FIFO structure */
++/* Generic FIFO structure */ 
+ struct fifo {
+       u_char r,w,count,size;
+       spinlock_t lock;
+@@ -270,7 +270,7 @@
+               index = -1;
+       } else {
+               // Return index where to get the next data to add to the FIFO
+-              index = fifo->w++ & (fifo->size-1);
++              index = fifo->w++ & (fifo->size-1); 
+               fifo->count++;
+       }
+       spin_unlock_irqrestore(&fifo->lock, flags);
+@@ -289,13 +289,13 @@
+               return -1;
+       }
+-      spin_lock_irqsave(&fifo->lock, flags);
++      spin_lock_irqsave(&fifo->lock, flags);          
+       if (!fifo->count) {
+               // FIFO empty
+               index = -1;
+       } else {
+               // Return index where to get the next data from the FIFO
+-              index = fifo->r++ & (fifo->size-1);
++              index = fifo->r++ & (fifo->size-1); 
+               fifo->count--;
+       }
+       spin_unlock_irqrestore(&fifo->lock, flags);
+@@ -309,7 +309,7 @@
+ typedef void (*ctrl_complete_t)(void *);
+ typedef struct ctrl_msg {
+-      struct usb_ctrlrequest dr;
++      devrequest dr;
+       ctrl_complete_t complete;
+       void *context;
+ } ctrl_msg; 
+@@ -336,7 +336,7 @@
+ };
+ struct st5481_d_out {
+-      struct isdnhdlc_vars hdlc_state;
++      struct hdlc_vars hdlc_state;
+       struct urb *urb[2]; /* double buffering */
+       unsigned long busy;
+       struct sk_buff *tx_skb;
+@@ -344,7 +344,7 @@
+ };
+ struct st5481_b_out {
+-      struct isdnhdlc_vars hdlc_state;
++      struct hdlc_vars hdlc_state;
+       struct urb *urb[2]; /* double buffering */
+       u_char flow_event;
+       u_long busy;
+@@ -352,7 +352,7 @@
+ };
+ struct st5481_in {
+-      struct isdnhdlc_vars hdlc_state;
++      struct hdlc_vars hdlc_state;
+       struct urb *urb[2]; /* double buffering */
+       int mode;
+       int bufsize;
+@@ -478,7 +478,7 @@
+   if (level & __debug_variable) dump_iso_packet(__FUNCTION__,urb)
+ static void __attribute__((unused))
+-dump_iso_packet(const char *name,struct urb *urb)
++dump_iso_packet(const char *name,urb_t *urb)
+ {
+       int i,j;
+       int len,ofs;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_b.c linux-2.4.29/drivers/isdn/hisax/st5481_b.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_b.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_b.c 2005-03-22 15:06:48.216762720 +0100
+@@ -67,28 +67,24 @@
+                               bytes_sent = buf_size - len;
+                               if (skb->len < bytes_sent)
+                                       bytes_sent = skb->len;
+-                              {       /* swap tx bytes to get hearable audio data */
+-                                      register unsigned char *src  = skb->data;
+-                                      register unsigned char *dest = urb->transfer_buffer+len;
+-                                      register unsigned int count;
+-                                      for (count = 0; count < bytes_sent; count++)
+-                                              *dest++ = isdnhdlc_bit_rev_tab[*src++];
+-                              }
++
++                              memcpy(urb->transfer_buffer+len, skb->data, bytes_sent);
++                              
+                               len += bytes_sent;
+                       } else {
+-                              len += isdnhdlc_encode(&b_out->hdlc_state,
+-                                                     skb->data, skb->len, &bytes_sent,
+-                                                     urb->transfer_buffer+len, buf_size-len);
++                              len += hdlc_encode(&b_out->hdlc_state, 
++                                                 skb->data, skb->len, &bytes_sent,
++                                                 urb->transfer_buffer+len, buf_size-len);
+                       }
+                       skb_pull(skb, bytes_sent);
+-
++                      
+                       if (!skb->len) {
+                               // Frame sent
+                               b_out->tx_skb = NULL;
+                               B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize);
+                               dev_kfree_skb_any(skb);
+-
++                              
+ /*                            if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */
+ /*                                    st5481B_sched_event(bcs, B_XMTBUFREADY); */
+ /*                            } */
+@@ -99,9 +95,9 @@
+                               len = buf_size;
+                       } else {
+                               // Send flags
+-                              len += isdnhdlc_encode(&b_out->hdlc_state,
+-                                                     NULL, 0, &bytes_sent,
+-                                                     urb->transfer_buffer+len, buf_size-len);
++                              len += hdlc_encode(&b_out->hdlc_state, 
++                                                 NULL, 0, &bytes_sent,
++                                                 urb->transfer_buffer+len, buf_size-len);
+                       }
+               }       
+       }
+@@ -213,7 +209,7 @@
+       if (bcs->mode != L1_MODE_NULL) {
+               // Open the B channel
+               if (bcs->mode != L1_MODE_TRANS) {
+-                      isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
++                      hdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K);
+               }
+               st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL);
+       
+@@ -279,7 +275,7 @@
+                                     usb_b_out_complete, bcs);
+ }
+-static void st5481_release_b_out(struct st5481_bcs *bcs)
++static void __devexit st5481_release_b_out(struct st5481_bcs *bcs)
+ {
+       struct st5481_b_out *b_out = &bcs->b_out;
+@@ -320,7 +316,7 @@
+ /*
+  * Release buffers and URBs for the B channels
+  */
+-void st5481_release_b(struct st5481_bcs *bcs)
++void __devexit st5481_release_b(struct st5481_bcs *bcs)
+ {
+       DBG(4,"");
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_d.c linux-2.4.29/drivers/isdn/hisax/st5481_d.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_d.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_d.c 2005-03-22 15:06:48.231760440 +0100
+@@ -162,8 +162,8 @@
+       {ST_L1_F8, EV_TIMER3,            l1_timer3},
+       {ST_L1_F8, EV_IND_DP,            l1_go_f3},
+       {ST_L1_F8, EV_IND_AP,            l1_go_f6},
+-      {ST_L1_F8, EV_IND_AI8,           l1_go_f7},
+-      {ST_L1_F8, EV_IND_AI10,          l1_go_f7},
++      {ST_L1_F8, EV_IND_AI8,           l1_go_f8},
++      {ST_L1_F8, EV_IND_AI10,          l1_go_f8},
+       {ST_L1_F8, EV_IND_RSY,           l1_ignore},
+ };
+@@ -297,7 +297,7 @@
+       unsigned int num_packets, packet_offset;
+       int len, buf_size, bytes_sent;
+       struct sk_buff *skb;
+-      struct iso_packet_descriptor *desc;
++      iso_packet_descriptor_t *desc;
+       if (d_out->fsm.state != ST_DOUT_NORMAL)
+               return;
+@@ -313,15 +313,15 @@
+       buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT;
+       
+       if (skb) {
+-              len = isdnhdlc_encode(&d_out->hdlc_state,
+-                                    skb->data, skb->len, &bytes_sent,
+-                                    urb->transfer_buffer, buf_size);
++              len = hdlc_encode(&d_out->hdlc_state, 
++                                skb->data, skb->len, &bytes_sent,
++                                urb->transfer_buffer, buf_size);
+               skb_pull(skb,bytes_sent);
+       } else {
+               // Send flags or idle
+-              len = isdnhdlc_encode(&d_out->hdlc_state,
+-                                    NULL, 0, &bytes_sent,
+-                                    urb->transfer_buffer, buf_size);
++              len = hdlc_encode(&d_out->hdlc_state, 
++                                NULL, 0, &bytes_sent,
++                                urb->transfer_buffer, buf_size);
+       }
+       
+       if (len < buf_size) {
+@@ -413,7 +413,7 @@
+       DBG(2,"len=%d",skb->len);
+-      isdnhdlc_out_init(&d_out->hdlc_state, 1, 0);
++      hdlc_out_init(&d_out->hdlc_state, 1, 0);
+       if (test_and_set_bit(buf_nr, &d_out->busy)) {
+               WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy);
+@@ -422,9 +422,9 @@
+       urb = d_out->urb[buf_nr];
+       DBG_SKB(0x10, skb);
+-      len = isdnhdlc_encode(&d_out->hdlc_state,
+-                            skb->data, skb->len, &bytes_sent,
+-                            urb->transfer_buffer, 16);
++      len = hdlc_encode(&d_out->hdlc_state, 
++                        skb->data, skb->len, &bytes_sent,
++                        urb->transfer_buffer, 16);
+       skb_pull(skb, bytes_sent);
+       if(len < 16)
+@@ -673,7 +673,7 @@
+                                     usb_d_out_complete, adapter);
+ }
+-static void st5481_release_d_out(struct st5481_adapter *adapter)
++static void __devexit st5481_release_d_out(struct st5481_adapter *adapter)
+ {
+       struct st5481_d_out *d_out = &adapter->d_out;
+@@ -723,7 +723,7 @@
+       return retval;
+ }
+-void st5481_release_d(struct st5481_adapter *adapter)
++void __devexit st5481_release_d(struct st5481_adapter *adapter)
+ {
+       DBG(2,"");
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_init.c linux-2.4.29/drivers/isdn/hisax/st5481_init.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_init.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_init.c      2005-03-22 15:06:48.268754816 +0100
+@@ -14,6 +14,7 @@
+  * TODO:
+  *
+  * b layer1 delay?
++ * hdlc as module
+  * hotplug / unregister issues
+  * mod_inc/dec_use_count
+  * unify parts of d/b channel usb handling
+@@ -177,7 +178,7 @@
+ static struct usb_driver st5481_usb_driver = {
+       name: "st5481_usb",
+       probe: probe_st5481,
+-      disconnect: __devexit_p(disconnect_st5481),
++      disconnect: disconnect_st5481,
+       id_table: st5481_ids,
+ };
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/st5481_usb.c linux-2.4.29/drivers/isdn/hisax/st5481_usb.c
+--- linux-2.4.29.old/drivers/isdn/hisax/st5481_usb.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/st5481_usb.c       2005-03-22 15:06:48.284752384 +0100
+@@ -41,9 +41,9 @@
+               (unsigned char *)&ctrl->msg_fifo.data[r_index];
+       
+       DBG(1,"request=0x%02x,value=0x%04x,index=%x",
+-          ((struct ctrl_msg *)urb->setup_packet)->dr.bRequest,
+-          ((struct ctrl_msg *)urb->setup_packet)->dr.wValue,
+-          ((struct ctrl_msg *)urb->setup_packet)->dr.wIndex);
++          ((struct ctrl_msg *)urb->setup_packet)->dr.request,
++          ((struct ctrl_msg *)urb->setup_packet)->dr.value,
++          ((struct ctrl_msg *)urb->setup_packet)->dr.index);
+       // Prepare the URB
+       urb->dev = adapter->usb_dev;
+@@ -69,11 +69,11 @@
+       }
+       ctrl_msg = &ctrl->msg_fifo.data[w_index]; 
+    
+-      ctrl_msg->dr.bRequestType = requesttype;
+-      ctrl_msg->dr.bRequest = request;
+-      ctrl_msg->dr.wValue = cpu_to_le16p(&value);
+-      ctrl_msg->dr.wIndex = cpu_to_le16p(&index);
+-      ctrl_msg->dr.wLength = 0;
++      ctrl_msg->dr.requesttype = requesttype;
++      ctrl_msg->dr.request = request;
++      ctrl_msg->dr.value = cpu_to_le16p(&value);
++      ctrl_msg->dr.index = cpu_to_le16p(&index);
++      ctrl_msg->dr.length = 0;
+       ctrl_msg->complete = complete;
+       ctrl_msg->context = context;
+@@ -140,17 +140,17 @@
+       ctrl_msg = (struct ctrl_msg *)urb->setup_packet;
+       
+-      if (ctrl_msg->dr.bRequest == USB_REQ_CLEAR_FEATURE) {
++      if (ctrl_msg->dr.request == USB_REQ_CLEAR_FEATURE) {
+               /* Special case handling for pipe reset */
+-              le16_to_cpus(&ctrl_msg->dr.wIndex);
++              le16_to_cpus(&ctrl_msg->dr.index);
+               usb_endpoint_running(adapter->usb_dev,
+-                                   ctrl_msg->dr.wIndex & ~USB_DIR_IN, 
+-                                   (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0);
++                                   ctrl_msg->dr.index & ~USB_DIR_IN, 
++                                   (ctrl_msg->dr.index & USB_DIR_IN) == 0);
+               /* toggle is reset on clear */
+               usb_settoggle(adapter->usb_dev, 
+-                            ctrl_msg->dr.wIndex & ~USB_DIR_IN, 
+-                            (ctrl_msg->dr.wIndex & USB_DIR_IN) == 0,
++                            ctrl_msg->dr.index & ~USB_DIR_IN, 
++                            (ctrl_msg->dr.index & USB_DIR_IN) == 0,
+                             0);
+@@ -235,7 +235,7 @@
+       struct usb_interface_descriptor *altsetting;
+       struct usb_endpoint_descriptor *endpoint;
+       int status;
+-      struct urb *urb;
++      urb_t *urb;
+       u_char *buf;
+       
+       DBG(1,"");
+@@ -307,7 +307,7 @@
+  * Release buffers and URBs for the interrupt and control
+  * endpoint.
+  */
+-void st5481_release_usb(struct st5481_adapter *adapter)
++void __devexit st5481_release_usb(struct st5481_adapter *adapter)
+ {
+       struct st5481_intr *intr = &adapter->intr;
+       struct st5481_ctrl *ctrl = &adapter->ctrl;
+@@ -443,7 +443,7 @@
+       return retval;
+ }
+-void st5481_release_isocpipes(struct urb* urb[2])
++void __devexit st5481_release_isocpipes(struct urb* urb[2])
+ {
+       int j;
+@@ -484,18 +484,16 @@
+       ptr = urb->transfer_buffer;
+       while (len > 0) {
+               if (in->mode == L1_MODE_TRANS) {
+-                      /* swap rx bytes to get hearable audio */
+-                      register unsigned char *dest = in->rcvbuf;
++                      memcpy(in->rcvbuf, ptr, len);
+                       status = len;
+-                      for (; len; len--)
+-                              *dest++ = isdnhdlc_bit_rev_tab[*ptr++];
++                      len = 0;
+               } else {
+-                      status = isdnhdlc_decode(&in->hdlc_state, ptr, len, &count,
+-                                               in->rcvbuf, in->bufsize);
++                      status = hdlc_decode(&in->hdlc_state, ptr, len, &count,
++                                           in->rcvbuf, in->bufsize);
+                       ptr += count;
+                       len -= count;
+               }
+-
++              
+               if (status > 0) {
+                       // Good frame received
+                       DBG(4,"count=%d",status);
+@@ -549,7 +547,7 @@
+       return retval;
+ }
+-void st5481_release_in(struct st5481_in *in)
++void __devexit st5481_release_in(struct st5481_in *in)
+ {
+       DBG(2,"");
+@@ -562,8 +560,7 @@
+  */
+ int st5481_isoc_flatten(struct urb *urb)
+ {
+-      struct iso_packet_descriptor *pipd;
+-      struct iso_packet_descriptor *pend;
++      piso_packet_descriptor_t pipd,pend;
+       unsigned char *src,*dst;
+       unsigned int len;
+       
+@@ -624,10 +621,15 @@
+       if (in->mode != L1_MODE_NULL) {
+               if (in->mode != L1_MODE_TRANS)
+-                      isdnhdlc_rcv_init(&in->hdlc_state,
+-                                        in->mode == L1_MODE_HDLC_56K);
++                      hdlc_rcv_init(&in->hdlc_state,
++                                    in->mode == L1_MODE_HDLC_56K);
+               
+               st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL);
++#if 0
++              st5481_usb_device_ctrl_msg(in->adapter, in->counter,
++                                         in->packet_size,
++                                         st5481_start_rcv, in);
++#endif
+               st5481_usb_device_ctrl_msg(in->adapter, in->counter,
+                                          in->packet_size,
+                                          NULL, NULL);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/tei.c linux-2.4.29/drivers/isdn/hisax/tei.c
+--- linux-2.4.29.old/drivers/isdn/hisax/tei.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/tei.c      2005-03-22 15:06:48.316747520 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tei.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: tei.c,v 2.20 2001/09/24 13:22:57 kai Exp $
+  *
+  * Author       Karsten Keil
+  *              based on the teles driver from Jan den Ouden
+@@ -21,7 +21,7 @@
+ #include <linux/init.h>
+ #include <linux/random.h>
+-const char *tei_revision = "$Revision: 1.1.4.1 $";
++const char *tei_revision = "$Revision: 2.20 $";
+ #define ID_REQUEST    1
+ #define ID_ASSIGNED   2
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/teleint.c linux-2.4.29/drivers/isdn/hisax/teleint.c
+--- linux-2.4.29.old/drivers/isdn/hisax/teleint.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/teleint.c  2005-03-22 15:06:48.330745392 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: teleint.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: teleint.c,v 1.16 2001/09/24 13:22:57 kai Exp $
+  *
+  * low level stuff for TeleInt isdn cards
+  *
+@@ -19,7 +19,7 @@
+ extern const char *CardType[];
+-const char *TeleInt_revision = "$Revision: 1.1.4.1 $";
++const char *TeleInt_revision = "$Revision: 1.16 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/teles0.c linux-2.4.29/drivers/isdn/hisax/teles0.c
+--- linux-2.4.29.old/drivers/isdn/hisax/teles0.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/teles0.c   2005-03-22 15:06:48.348742656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: teles0.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: teles0.c,v 2.15 2001/09/24 13:22:57 kai Exp $
+  *
+  * low level stuff for Teles Memory IO isdn cards
+  *
+@@ -24,7 +24,7 @@
+ extern const char *CardType[];
+-const char *teles0_revision = "$Revision: 1.1.4.1 $";
++const char *teles0_revision = "$Revision: 2.15 $";
+ #define TELES_IOMEM_SIZE      0x400
+ #define byteout(addr,val) outb(val,addr)
+@@ -189,8 +189,10 @@
+ {
+       if (cs->hw.teles0.cfg_reg)
+               release_region(cs->hw.teles0.cfg_reg, 8);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+       iounmap((unsigned char *)cs->hw.teles0.membase);
+       release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
++#endif
+ }
+ static int
+@@ -327,6 +329,7 @@
+       /* 16.0 and 8.0 designed for IOM1 */
+       test_and_set_bit(HW_IOM1, &cs->HW_Flags);
+       cs->hw.teles0.phymem = card->para[1];
++#ifdef COMPAT_HAS_ISA_IOREMAP
+       if (check_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE)) {
+               printk(KERN_WARNING
+                       "HiSax: %s memory region %lx-%lx already in use\n",
+@@ -342,6 +345,9 @@
+       }
+       cs->hw.teles0.membase =
+               (unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE);
++#else
++      cs->hw.teles0.membase = cs->hw.teles0.phymem;
++#endif
+       printk(KERN_INFO
+              "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n",
+              CardType[cs->typ], cs->irq,
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/teles3.c linux-2.4.29/drivers/isdn/hisax/teles3.c
+--- linux-2.4.29.old/drivers/isdn/hisax/teles3.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/teles3.c   2005-03-22 15:06:48.367739768 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: teles3.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: teles3.c,v 2.19 2001/09/24 13:22:57 kai Exp $
+  *
+  * low level stuff for Teles 16.3 & PNP isdn cards
+  *
+@@ -15,14 +15,13 @@
+  */
+ #define __NO_VERSION__
+ #include <linux/init.h>
+-#include <linux/isapnp.h>
+ #include "hisax.h"
+ #include "isac.h"
+ #include "hscx.h"
+ #include "isdnl1.h"
+ extern const char *CardType[];
+-const char *teles3_revision = "$Revision: 1.1.4.1 $";
++const char *teles3_revision = "$Revision: 2.19 $";
+ #define byteout(addr,val) outb(val,addr)
+ #define bytein(addr) inb(addr)
+@@ -255,24 +254,6 @@
+       return(0);
+ }
+-#ifdef __ISAPNP__
+-static struct isapnp_device_id teles_ids[] __initdata = {
+-      { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110),
+-        ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), 
+-        (unsigned long) "Teles 16.3 PnP" },
+-      { ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0),
+-        ISAPNP_VENDOR('C', 'T', 'X'), ISAPNP_FUNCTION(0x0), 
+-        (unsigned long) "Creatix 16.3 PnP" },
+-      { ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002),
+-        ISAPNP_VENDOR('C', 'P', 'Q'), ISAPNP_FUNCTION(0x1002), 
+-        (unsigned long) "Compaq ISDN S0" },
+-      { 0, }
+-};
+-
+-static struct isapnp_device_id *tdev = &teles_ids[0];
+-static struct pci_bus *pnp_c __devinitdata = NULL;
+-#endif
+-
+ int __devinit
+ setup_teles3(struct IsdnCard *card)
+ {
+@@ -286,47 +267,6 @@
+           && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA))
+               return (0);
+-#ifdef __ISAPNP__
+-      if (!card->para[1] && isapnp_present()) {
+-              struct pci_bus *pb;
+-              struct pci_dev *pd;
+-
+-              while(tdev->card_vendor) {
+-                      if ((pb = isapnp_find_card(tdev->card_vendor,
+-                              tdev->card_device, pnp_c))) {
+-                              pnp_c = pb;
+-                              pd = NULL;
+-                              if ((pd = isapnp_find_dev(pnp_c,
+-                                      tdev->vendor, tdev->function, pd))) {
+-                                      printk(KERN_INFO "HiSax: %s detected\n",
+-                                              (char *)tdev->driver_data);
+-                                      pd->prepare(pd);
+-                                      pd->deactivate(pd);
+-                                      pd->activate(pd);
+-                                      card->para[3] = pd->resource[2].start;
+-                                      card->para[2] = pd->resource[1].start;
+-                                      card->para[1] = pd->resource[0].start;
+-                                      card->para[0] = pd->irq_resource[0].start;
+-                                      if (!card->para[0] || !card->para[1] || !card->para[2]) {
+-                                              printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n",
+-                                              card->para[0], card->para[1], card->para[2]);
+-                                              pd->deactivate(pd);
+-                                              return(0);
+-                                      }
+-                                      break;
+-                              } else {
+-                                      printk(KERN_ERR "Teles PnP: PnP error card found, no device\n");
+-                              }
+-                      }
+-                      tdev++;
+-                      pnp_c=NULL;
+-              } 
+-              if (!tdev->card_vendor) {
+-                      printk(KERN_INFO "Teles PnP: no ISAPnP card found\n");
+-                      return(0);
+-              }
+-      }
+-#endif
+       if (cs->typ == ISDN_CTYPE_16_3) {
+               cs->hw.teles3.cfg_reg = card->para[1];
+               switch (cs->hw.teles3.cfg_reg) {
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/telespci.c linux-2.4.29/drivers/isdn/hisax/telespci.c
+--- linux-2.4.29.old/drivers/isdn/hisax/telespci.c     2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/telespci.c 2005-03-22 15:06:48.382737488 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: telespci.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: telespci.c,v 2.23 2001/09/24 13:22:57 kai Exp $
+  *
+  * low level stuff for Teles PCI isdn cards
+  *
+@@ -20,9 +20,10 @@
+ #include "hscx.h"
+ #include "isdnl1.h"
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ extern const char *CardType[];
+-const char *telespci_revision = "$Revision: 1.1.4.1 $";
++const char *telespci_revision = "$Revision: 2.23 $";
+ #define ZORAN_PO_RQ_PEN       0x02000000
+ #define ZORAN_PO_WR   0x00800000
+@@ -307,10 +308,10 @@
+                       printk(KERN_WARNING "Teles: No IRQ for PCI card found\n");
+                       return(0);
+               }
+-              cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0),
++              cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start_mem(dev_tel, 0),
+                       PAGE_SIZE);
+               printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n",
+-                      pci_resource_start(dev_tel, 0), dev_tel->irq);
++                      pci_resource_start_mem(dev_tel, 0), dev_tel->irq);
+       } else {
+               printk(KERN_WARNING "TelesPCI: No PCI card found\n");
+               return(0);
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/w6692.c linux-2.4.29/drivers/isdn/hisax/w6692.c
+--- linux-2.4.29.old/drivers/isdn/hisax/w6692.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/w6692.c    2005-03-22 15:06:48.398735056 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: w6692.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: w6692.c,v 1.18 2001/09/24 13:22:57 kai Exp $
+  *
+  * Winbond W6692 specific routines
+  *
+@@ -18,6 +18,7 @@
+ #include "isdnl1.h"
+ #include <linux/interrupt.h>
+ #include <linux/pci.h>
++#include <linux/isdn_compat.h>
+ /* table entry in the PCI devices list */
+ typedef struct {
+@@ -29,20 +30,14 @@
+ static const PCI_ENTRY id_list[] =
+ {
+-      {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
+       {PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
+-      {0, 0, "U.S.Robotics", "ISDN PCI Card TA"}
++      {PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
++      {0, 0, NULL, NULL}
+ };
+-#define W6692_SV_USR   0x16ec
+-#define W6692_SD_USR   0x3409
+-#define W6692_WINBOND  0
+-#define W6692_DYNALINK 1
+-#define W6692_USR      2
+-
+ extern const char *CardType[];
+-const char *w6692_revision = "$Revision: 1.1.4.1 $";
++const char *w6692_revision = "$Revision: 1.18 $";
+ #define DBUSY_TIMER_VALUE 80
+@@ -675,6 +670,16 @@
+ static void
+ DC_Close_W6692(struct IsdnCardState *cs)
+ {
++#if 0
++      if (cs->dc.w6692.mon_rx) {
++              kfree(cs->dc.w6692.mon_rx);
++              cs->dc.w6692.mon_rx = NULL;
++      }
++      if (cs->dc.w6692.mon_tx) {
++              kfree(cs->dc.w6692.mon_tx);
++              cs->dc.w6692.mon_tx = NULL;
++      }
++#endif
+ }
+ static void
+@@ -865,38 +870,31 @@
+       return (0);
+ }
+-void resetW6692(struct IsdnCardState *cs)
+-{
+-      cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
+-      schedule_timeout((10*HZ)/1000);
+-      cs->writeW6692(cs, W_D_CTL, 0x00);
+-      schedule_timeout((10*HZ)/1000);
+-      cs->writeW6692(cs, W_IMASK, 0xff);
+-      cs->writeW6692(cs, W_D_SAM, 0xff);
+-      cs->writeW6692(cs, W_D_TAM, 0xff);
+-      cs->writeW6692(cs, W_D_EXIM, 0x00);
+-      cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
+-      cs->writeW6692(cs, W_IMASK, 0x18);
+-      if (cs->subtyp == W6692_USR) {
+-              /* seems that USR implemented some power control features
+-               * Pin 79 is connected to the oscilator circuit so we
+-               * have to handle it here
+-               */
+-              cs->writeW6692(cs, W_PCTL, 0x80);
+-              cs->writeW6692(cs, W_XDATA, 0x00);
+-      }
+-}
+-
+ void __init initW6692(struct IsdnCardState *cs, int part)
+ {
+       if (part & 1) {
+               cs->tqueue.routine = (void *) (void *) W6692_bh;
+               cs->setstack_d = setstack_W6692;
+               cs->DC_Close = DC_Close_W6692;
++#if 0
++              cs->dc.w6692.mon_tx = NULL;
++              cs->dc.w6692.mon_rx = NULL;
++#endif
+               cs->dbusytimer.function = (void *) dbusy_timer_handler;
+               cs->dbusytimer.data = (long) cs;
+               init_timer(&cs->dbusytimer);
+-              resetW6692(cs);
++
++              cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST);
++              cs->writeW6692(cs, W_D_CTL, 0x00);
++              cs->writeW6692(cs, W_IMASK, 0xff);
++#if 0
++              cs->dc.w6692.mocr = 0xaa;
++#endif
++              cs->writeW6692(cs, W_D_SAM, 0xff);
++              cs->writeW6692(cs, W_D_TAM, 0xff);
++              cs->writeW6692(cs, W_D_EXIM, 0x00);
++              cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT);
++              cs->writeW6692(cs, W_IMASK, 0x18);
+               ph_command(cs, W_L1CMD_RST);
+               cs->dc.w6692.ph_state = W_L1CMD_RST;
+               W6692_new_ph(cs);
+@@ -963,14 +961,9 @@
+ {
+       switch (mt) {
+               case CARD_RESET:
+-                      resetW6692(cs);
+                       return (0);
+               case CARD_RELEASE:
+-                      cs->writeW6692(cs, W_IMASK, 0xff);
+                       release_region(cs->hw.w6692.iobase, 256);
+-                      if (cs->subtyp == W6692_USR) {
+-                              cs->writeW6692(cs, W_XDATA, 0x04);
+-                      }
+                       return (0);
+               case CARD_INIT:
+                       initW6692(cs, 3);
+@@ -1013,7 +1006,6 @@
+               if (dev_w6692) {
+                       if (pci_enable_device(dev_w6692))
+                               continue;
+-                      cs->subtyp = id_idx;
+                       break;
+               }
+               id_idx++;
+@@ -1023,14 +1015,7 @@
+               pci_irq = dev_w6692->irq;
+               /* I think address 0 is allways the configuration area */
+               /* and address 1 is the real IO space KKe 03.09.99 */
+-              pci_ioaddr = pci_resource_start(dev_w6692, 1);
+-              /* USR ISDN PCI card TA need some special handling */
+-              if (cs->subtyp == W6692_WINBOND) {
+-                      if ((W6692_SV_USR == dev_w6692->subsystem_vendor) &&
+-                          (W6692_SD_USR == dev_w6692->subsystem_device)) {
+-                              cs->subtyp = W6692_USR;
+-                      }
+-              }
++              pci_ioaddr = pci_resource_start_io(dev_w6692, 1);
+       }
+       if (!found) {
+               printk(KERN_WARNING "W6692: No PCI card found\n");
+@@ -1047,18 +1032,18 @@
+       }
+       cs->hw.w6692.iobase = pci_ioaddr;
+       printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n",
+-             id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name,
+-             pci_ioaddr, pci_irq);
++             id_list[id_idx].vendor_name, id_list[id_idx].card_name,
++             pci_ioaddr, dev_w6692->irq);
+       if (check_region((cs->hw.w6692.iobase), 256)) {
+               printk(KERN_WARNING
+                      "HiSax: %s I/O ports %x-%x already in use\n",
+-                     id_list[cs->subtyp].card_name,
++                     id_list[id_idx].card_name,
+                      cs->hw.w6692.iobase,
+                      cs->hw.w6692.iobase + 255);
+               return (0);
+       } else {
+               request_region(cs->hw.w6692.iobase, 256,
+-                             id_list[cs->subtyp].card_name);
++                             id_list[id_idx].card_name);
+       }
+ #else
+       printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n");
+@@ -1068,7 +1053,7 @@
+       printk(KERN_INFO
+              "HiSax: %s config irq:%d I/O:%x\n",
+-             id_list[cs->subtyp].card_name, cs->irq,
++             id_list[id_idx].card_name, cs->irq,
+              cs->hw.w6692.iobase);
+       cs->readW6692 = &ReadW6692;
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/w6692.h linux-2.4.29/drivers/isdn/hisax/w6692.h
+--- linux-2.4.29.old/drivers/isdn/hisax/w6692.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hisax/w6692.h    2005-03-22 15:06:48.414732624 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: w6692.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $
++/* $Id: w6692.h,v 1.4 2001/09/24 13:22:57 kai Exp $
+  *
+  * Winbond W6692 specific defines
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/boardergo.c linux-2.4.29/drivers/isdn/hysdn/boardergo.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/boardergo.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/boardergo.c        2005-03-22 15:06:48.468724416 +0100
+@@ -1,27 +1,41 @@
+-/* $Id: boardergo.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
+- *
++/* $Id: boardergo.c,v 1.9 2001/07/19 20:39:51 kai Exp $
++
+  * Linux driver for HYSDN cards, specific routines for ergo type boards.
+  *
+- * Author    Werner Cornelius (werner@titro.de) for Hypercope GmbH
+- * Copyright 1999 by Werner Cornelius (werner@titro.de)
+- *
+- * This software may be used and distributed according to the terms
+- * of the GNU General Public License, incorporated herein by reference.
+- *
+  * As all Linux supported cards Champ2, Ergo and Metro2/4 use the same
+  * DPRAM interface and layout with only minor differences all related
+  * stuff is done here, not in separate modules.
+  *
++ * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH
++ *
++ * Copyright 1999  by Werner Cornelius (werner@titro.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)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * 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.
++ *
+  */
++#define __NO_VERSION__
+ #include <linux/config.h>
+-#include <linux/sched.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <asm/io.h>
+ #include <linux/signal.h>
+ #include <linux/kernel.h>
+ #include <linux/ioport.h>
+ #include <linux/interrupt.h>
+ #include <linux/vmalloc.h>
+-#include <asm/io.h>
+ #include "hysdn_defs.h"
+ #include "boardergo.h"
+@@ -45,11 +59,10 @@
+       if (!card->irq_enabled)
+               return;         /* other device interrupting or irq switched off */
+-      save_flags(flags);
+-      cli();                  /* no further irqs allowed */
++      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) {
+-              restore_flags(flags);   /* restore old state */
++              HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+               return;         /* no interrupt requested by E1 */
+       }
+       /* clear any pending ints on the board */
+@@ -63,7 +76,7 @@
+               queue_task(&card->irq_queue, &tq_immediate);
+               mark_bh(IMMEDIATE_BH);
+       }
+-      restore_flags(flags);
++      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ }                             /* ergo_interrupt */
+ /******************************************************************************/
+@@ -83,17 +96,15 @@
+               return;         /* invalid call */
+       dpr = card->dpram;      /* point to DPRAM */
++      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+-      save_flags(flags);
+-      cli();
+       if (card->hw_lock) {
+-              restore_flags(flags);   /* hardware currently unavailable */
++              HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+               return;
+       }
+       card->hw_lock = 1;      /* we now lock the hardware */
+       do {
+-              sti();          /* reenable other ints */
+               again = 0;      /* assume loop not to be repeated */
+               if (!dpr->ToHyFlag) {
+@@ -113,15 +124,13 @@
+                               again = 1;      /* restart loop */
+                       }
+               }               /* a message has arrived for us */
+-              cli();          /* no further ints */
+               if (again) {
+                       dpr->ToHyInt = 1;
+                       dpr->ToPcInt = 1;       /* interrupt to E1 for all cards */
+               } else
+                       card->hw_lock = 0;      /* free hardware again */
+       } while (again);        /* until nothing more to do */
+-
+-      restore_flags(flags);
++      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ }                             /* ergo_irq_bh */
+@@ -138,8 +147,7 @@
+ #ifdef CONFIG_HYSDN_CAPI
+       hycapi_capi_stop(card);
+ #endif /* CONFIG_HYSDN_CAPI */
+-      save_flags(flags);
+-      cli();
++      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       val = bytein(card->iobase + PCI9050_INTR_REG);  /* get actual value */
+       val &= ~(PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1);        /* mask irq */
+       byteout(card->iobase + PCI9050_INTR_REG, val);
+@@ -147,8 +155,7 @@
+       byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RESET);      /* reset E1 processor */
+       card->state = CARD_STATE_UNUSED;
+       card->err_log_state = ERRLOG_STATE_OFF;         /* currently no log active */
+-
+-      restore_flags(flags);
++      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+ }                             /* ergo_stopcard */
+ /**************************************************************************/
+@@ -163,20 +170,17 @@
+               card->err_log_state = ERRLOG_STATE_OFF;         /* must be off */
+               return;
+       }
+-      save_flags(flags);
+-      cli();
+-
++      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) ||
+           ((card->err_log_state == ERRLOG_STATE_ON) && on)) {
+-              restore_flags(flags);
++              HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+               return;         /* nothing to do */
+       }
+       if (on)
+               card->err_log_state = ERRLOG_STATE_START;       /* request start */
+       else
+               card->err_log_state = ERRLOG_STATE_STOP;        /* request stop */
+-
+-      restore_flags(flags);
++      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+       queue_task(&card->irq_queue, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+ }                             /* ergo_set_errlog_state */
+@@ -245,9 +249,6 @@
+               while (!dpram->ToHyNoDpramErrLog);      /* reread volatile register to flush PCI */
+               byteout(card->iobase + PCI9050_USER_IO, PCI9050_E1_RUN);        /* start E1 processor */
+-              /* the interrupts are still masked */
+-
+-              sti();
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout((20 * HZ) / 1000);     /* Timeout 20ms */
+@@ -282,7 +283,6 @@
+       dst = sp->Data;         /* point to data in spool structure */
+       buflen = sp->Len;       /* maximum len of spooled data */
+       wr_mirror = sp->WrPtr;  /* only once read */
+-      sti();
+       /* try until all bytes written or error */
+       i = 0x1000;             /* timeout value */
+@@ -358,9 +358,7 @@
+                       if (card->debug_flags & LOG_POF_RECORD)
+                               hysdn_addlog(card, "ERGO: pof boot success");
+-                      save_flags(flags);
+-                      cli();
+-
++                      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+                       card->state = CARD_STATE_RUN;   /* now card is running */
+                       /* enable the cards interrupt */
+                       byteout(card->iobase + PCI9050_INTR_REG,
+@@ -371,8 +369,7 @@
+                       dpr->ToPcFlag = 0;      /* reset data indicator */
+                       dpr->ToHyInt = 1;
+                       dpr->ToPcInt = 1;       /* interrupt to E1 for all cards */
+-
+-                      restore_flags(flags);
++                      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+                       if ((hynet_enable & (1 << card->myid)) 
+                           && (i = hysdn_net_create(card))) 
+                       {
+@@ -387,7 +384,6 @@
+ #endif /* CONFIG_HYSDN_CAPI */
+                       return (0);     /* success */
+               }               /* data has arrived */
+-              sti();
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout((50 * HZ) / 1000);     /* Timeout 50ms */
+       }                       /* wait until timeout */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/boardergo.h linux-2.4.29/drivers/isdn/hysdn/boardergo.h
+--- linux-2.4.29.old/drivers/isdn/hysdn/boardergo.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/boardergo.h        2005-03-22 15:06:48.485721832 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: boardergo.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..).
+  *
+@@ -10,6 +10,7 @@
+  *
+  */
++#include <linux/isdn_compat.h>
+ /************************************************/
+ /* defines for the dual port memory of the card */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hycapi.c linux-2.4.29/drivers/isdn/hysdn/hycapi.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hycapi.c       2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hycapi.c   2005-03-22 15:06:48.500719552 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hycapi.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards, CAPI2.0-Interface.
+  *
+@@ -29,7 +29,7 @@
+ #include "hysdn_defs.h"
+ #include <linux/kernelcapi.h>
+-static char hycapi_revision[]="$Revision: 1.1.4.1 $";
++static char hycapi_revision[]="$Revision$";
+ unsigned int hycapi_enable = 0xffffffff; 
+ MODULE_PARM(hycapi_enable, "i");
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_boot.c linux-2.4.29/drivers/isdn/hysdn/hysdn_boot.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_boot.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_boot.c       2005-03-22 15:06:48.516717120 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_boot.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards
+  * specific routines for booting and pof handling
+@@ -143,7 +143,7 @@
+                                            (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA",
+                                            datlen, boot->pof_recoffset);
+-                      if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen)) < 0)
++                      if ((boot->last_error = card->writebootseq(card, boot->buf.BootBuf, datlen) < 0))
+                               return (boot->last_error);      /* error writing data */
+                       if (boot->pof_recoffset + datlen >= boot->pof_reclen)
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_defs.h linux-2.4.29/drivers/isdn/hysdn/hysdn_defs.h
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_defs.h   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_defs.h       2005-03-22 15:06:48.533714536 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_defs.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: hysdn_defs.h,v 1.10 2001/09/24 13:23:03 kai Exp $
+  *
+  * Linux driver for HYSDN cards
+  * global definitions and exported vars and functions.
+@@ -19,6 +19,11 @@
+ #include <linux/interrupt.h>
+ #include <linux/tqueue.h>
+ #include <linux/skbuff.h>
++#include <linux/isdn_compat.h>
++#include <linux/spinlock.h>
++
++#define HYSDN_SPIN_LOCK(a,b) spin_lock(a)
++#define HYSDN_SPIN_UNLOCK(a,b) spin_unlock(a)
+ /****************************/
+ /* storage type definitions */
+@@ -176,6 +181,7 @@
+       struct tq_struct irq_queue;     /* interrupt task queue */
+       uchar volatile irq_enabled;     /* interrupt enabled if != 0 */
+       uchar volatile hw_lock; /* hardware is currently locked -> no access */
++      spinlock_t irq_lock;
+       /* boot process */
+       void *boot;             /* pointer to boot private data */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_init.c linux-2.4.29/drivers/isdn/hysdn/hysdn_init.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_init.c   2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_init.c       2005-03-22 15:06:48.551711800 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_init.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards, init functions.
+  *
+@@ -21,6 +21,7 @@
+ #include "hysdn_defs.h"
++#ifndef COMPAT_HAS_2_2_PCI
+ static struct pci_device_id hysdn_pci_tbl[] __initdata = {
+       {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO},
+       {PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2},
+@@ -29,11 +30,12 @@
+       { }                             /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl);
++#endif
+ MODULE_DESCRIPTION("ISDN4Linux: Driver for HYSDN cards");
+ MODULE_AUTHOR("Werner Cornelius");
+ MODULE_LICENSE("GPL");
+-static char *hysdn_init_revision = "$Revision: 1.1.4.1 $";
++static char *hysdn_init_revision = "$Revision$";
+ int cardmax;                  /* number of found cards */
+ hysdn_card *card_root = NULL; /* pointer to first card */
+@@ -91,11 +93,11 @@
+               card->myid = cardmax;   /* set own id */
+               card->bus = akt_pcidev->bus->number;
+               card->devfn = akt_pcidev->devfn;        /* slot + function */
+-              card->subsysid = akt_pcidev->subsystem_device;
++              pci_get_sub_system(akt_pcidev,card->subsysid);
+               card->irq = akt_pcidev->irq;
+-              card->iobase = pci_resource_start(akt_pcidev, PCI_REG_PLX_IO_BASE);
+-              card->plxbase = pci_resource_start(akt_pcidev, PCI_REG_PLX_MEM_BASE);
+-              card->membase = pci_resource_start(akt_pcidev, PCI_REG_MEMORY_BASE);
++              card->iobase = pci_resource_start_io(akt_pcidev, PCI_REG_PLX_IO_BASE);
++              card->plxbase = pci_resource_start_mem(akt_pcidev, PCI_REG_PLX_MEM_BASE);
++              card->membase = pci_resource_start_mem(akt_pcidev, PCI_REG_MEMORY_BASE);
+               card->brdtype = BD_NONE;        /* unknown */
+               card->debug_flags = DEF_DEB_FLAGS;      /* set default debug */
+               card->faxchans = 0;     /* default no fax channels */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_net.c linux-2.4.29/drivers/isdn/hysdn/hysdn_net.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_net.c    2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_net.c        2005-03-22 15:06:48.567709368 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_net.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards, net (ethernet type) handling routines.
+  *
+@@ -29,7 +29,7 @@
+ MODULE_PARM(hynet_enable, "i");
+ /* store the actual version for log reporting */
+-char *hysdn_net_revision = "$Revision: 1.1.4.1 $";
++char *hysdn_net_revision = "$Revision$";
+ #define MAX_SKB_BUFFERS 20    /* number of buffers for keeping TX-data */
+@@ -45,6 +45,10 @@
+       /* additional vars may be added here */
+       char dev_name[9];       /* our own device name */
++#ifdef COMPAT_NO_SOFTNET
++      struct sk_buff *tx_skb; /* buffer for tx operation */
++
++#else
+       /* Tx control lock.  This protects the transmit buffer ring
+        * state along with the "tx full" state of the driver.  This
+        * means all netif_queue flow control actions are protected
+@@ -56,6 +60,7 @@
+       int sk_count;           /* number of buffers currently in ring */
+       int is_open;            /* flag controlling module locking */
++#endif
+ };                            /* net_local */
+@@ -83,11 +88,19 @@
+       hysdn_card *card = dev->priv;
+       int i;
++#ifdef COMPAT_NO_SOFTNET
++      dev->tbusy = 0;         /* non busy state */
++      dev->interrupt = 0;
++      if (!dev->start)
++              MOD_INC_USE_COUNT;      /* increment only if device is down */
++      dev->start = 1;         /* and started */
++#else
+       if (!((struct net_local *) dev)->is_open)
+               MOD_INC_USE_COUNT;      /* increment only if interface is actually down */
+       ((struct net_local *) dev)->is_open = 1;        /* device actually open */
+       netif_start_queue(dev); /* start tx-queueing */
++#endif
+       /* Fill in the MAC-level header (if not already set) */
+       if (!card->mac_addr[0]) {
+@@ -104,6 +117,7 @@
+       return (0);
+ }                             /* net_open */
++#ifndef COMPAT_NO_SOFTNET
+ /*******************************************/
+ /* flush the currently occupied tx-buffers */
+ /* must only be called when device closed  */
+@@ -119,6 +133,7 @@
+               nl->sk_count--;
+       }
+ }                             /* flush_tx_buffers */
++#endif
+ /*********************************************************************/
+@@ -129,6 +144,15 @@
+ net_close(struct net_device *dev)
+ {
++#ifdef COMPAT_NO_SOFTNET
++      dev->tbusy = 1;         /* we are busy */
++
++      if (dev->start)
++              MOD_DEC_USE_COUNT;      /* dec only if device has been active */
++
++      dev->start = 0;         /* and not started */
++
++#else
+       netif_stop_queue(dev);  /* disable queueing */
+       if (((struct net_local *) dev)->is_open)
+@@ -136,9 +160,52 @@
+       ((struct net_local *) dev)->is_open = 0;
+       flush_tx_buffers((struct net_local *) dev);
++#endif
+       return (0);             /* success */
+ }                             /* net_close */
++#ifdef COMPAT_NO_SOFTNET
++/************************************/
++/* send a packet on this interface. */
++/* only for kernel versions < 2.3.33 */
++/************************************/
++static int
++net_send_packet(struct sk_buff *skb, struct net_device *dev)
++{
++      struct net_local *lp = (struct net_local *) dev;
++
++      if (dev->tbusy) {
++              /*
++               * If we get here, some higher level has decided we are broken.
++               * There should really be a "kick me" function call instead.
++               * As ISDN may have higher timeouts than real ethernet 10s timeout
++               */
++              int tickssofar = jiffies - dev->trans_start;
++              if (tickssofar < (10000 * HZ) / 1000)
++                      return 1;
++              printk(KERN_WARNING "%s: transmit timed out. \n", dev->name);
++              dev->tbusy = 0;
++              dev->trans_start = jiffies;
++      }
++      /*
++       * Block a timer-based transmit from overlapping. This could better be
++       * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
++       */
++      if (test_and_set_bit(0, (void *) &dev->tbusy) != 0)
++              printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
++
++      else {
++              lp->stats.tx_bytes += skb->len;
++              dev->trans_start = jiffies;
++              lp->tx_skb = skb;       /* remember skb pointer */
++              queue_task(&((hysdn_card *) dev->priv)->irq_queue, &tq_immediate);
++              mark_bh(IMMEDIATE_BH);
++      }
++
++      return (0);             /* success */
++}                             /* net_send_packet */
++
++#else
+ /************************************/
+ /* send a packet on this interface. */
+ /* new style for kernel >= 2.3.33   */
+@@ -176,6 +243,7 @@
+       return (0);             /* success */
+ }                             /* net_send_packet */
++#endif
+ /***********************************************************************/
+@@ -190,6 +258,15 @@
+       if (!lp)
+               return;         /* non existing device */
++#ifdef COMPAT_NO_SOFTNET
++      if (lp->tx_skb)
++              dev_kfree_skb(lp->tx_skb);      /* free tx pointer */
++      lp->tx_skb = NULL;      /* reset pointer */
++
++      lp->stats.tx_packets++;
++      lp->netdev.tbusy = 0;
++      mark_bh(NET_BH);        /* Inform upper layers. */
++#else
+       if (!lp->sk_count)
+               return;         /* error condition */
+@@ -203,6 +280,7 @@
+       if (lp->sk_count-- == MAX_SKB_BUFFERS)  /* dec usage count */
+               netif_start_queue((struct net_device *) lp);
++#endif
+ }                             /* hysdn_tx_netack */
+ /*****************************************************/
+@@ -250,10 +328,15 @@
+       if (!lp)
+               return (NULL);  /* non existing device */
++#ifdef COMPAT_NO_SOFTNET
++      return (lp->tx_skb);    /* return packet pointer */
++
++#else
+       if (!lp->sk_count)
+               return (NULL);  /* nothing available */
+       return (lp->skbs[lp->out_idx]);         /* next packet to send */
++#endif
+ }                             /* hysdn_tx_netget */
+@@ -296,15 +379,21 @@
+       }
+       memset(dev, 0, sizeof(struct net_local));       /* clean the structure */
++#ifndef COMPAT_NO_SOFTNET
+       spin_lock_init(&((struct net_local *) dev)->lock);
++#endif
+       /* initialise necessary or informing fields */
+       dev->base_addr = card->iobase;  /* IO address */
+       dev->irq = card->irq;   /* irq */
+       dev->init = net_init;   /* the init function of the device */
++#ifdef COMPAT_NO_SOFTNET
++      dev->name = ((struct net_local *) dev)->dev_name;       /* device name */
++#else
+       if(dev->name) {
+               strcpy(dev->name, ((struct net_local *) dev)->dev_name);
+       } 
++#endif
+       if ((i = register_netdev(dev))) {
+               printk(KERN_WARNING "HYSDN: unable to create network device\n");
+               kfree(dev);
+@@ -333,7 +422,9 @@
+       card->netif = NULL;     /* clear out pointer */
+       dev->stop(dev);         /* close the device */
++#ifndef COMPAT_NO_SOFTNET
+       flush_tx_buffers((struct net_local *) dev);     /* empty buffers */
++#endif
+       unregister_netdev(dev); /* release the device */
+       kfree(dev);             /* release the memory allocated */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_pof.h linux-2.4.29/drivers/isdn/hysdn/hysdn_pof.h
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_pof.h    2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_pof.h        2005-03-22 15:06:48.583706936 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_pof.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards, definitions used for handling pof-files.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_procconf.c linux-2.4.29/drivers/isdn/hysdn/hysdn_procconf.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_procconf.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_procconf.c   2005-03-22 15:06:48.598704656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_procconf.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions.
+  *
+@@ -17,11 +17,13 @@
+ #include <linux/poll.h>
+ #include <linux/proc_fs.h>
+ #include <linux/pci.h>
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ #include <linux/smp_lock.h>
++#endif
+ #include "hysdn_defs.h"
+-static char *hysdn_procconf_revision = "$Revision: 1.1.4.1 $";
++static char *hysdn_procconf_revision = "$Revision$";
+ #define INFO_OUT_LEN 80               /* length of info line including lf */
+@@ -212,32 +214,29 @@
+ static ssize_t
+ hysdn_conf_read(struct file *file, char *buf, size_t count, loff_t * off)
+ {
+-      loff_t pos = *off;
+       char *cp;
+       int i;
+       if (off != &file->f_pos)        /* fs error check */
+               return -ESPIPE;
+-      if (!(file->f_mode & FMODE_READ))
+-              return -EPERM;
+-
+-      if (!(cp = file->private_data))
+-              return (-EFAULT);       /* should never happen */
+-
+-      i = strlen(cp); /* get total string length */
+-
+-      if (pos != (unsigned)pos || pos >= i)
+-              return 0;
+-
+-      /* still bytes to transfer */
+-      cp += pos;      /* point to desired data offset */
+-      i -= pos;       /* remaining length */
+-      if (i > count)
+-              i = count;      /* limit length to transfer */
+-      if (copy_to_user(buf, cp, i))
+-              return (-EFAULT);       /* copy error */
+-      *off = pos + i; /* adjust offset */
++      if (file->f_mode & FMODE_READ) {
++              if (!(cp = file->private_data))
++                      return (-EFAULT);       /* should never happen */
++              i = strlen(cp); /* get total string length */
++              if (*off < i) {
++                      /* still bytes to transfer */
++                      cp += *off;     /* point to desired data offset */
++                      i -= *off;      /* remaining length */
++                      if (i > count)
++                              i = count;      /* limit length to transfer */
++                      if (copy_to_user(buf, cp, i))
++                              return (-EFAULT);       /* copy error */
++                      *off += i;      /* adjust offset */
++              } else
++                      return (0);
++      } else
++              return (-EPERM);        /* no permission to read */
+       return (i);
+ }                             /* hysdn_conf_read */
+@@ -254,7 +253,11 @@
+       char *cp, *tmp;
+       /* now search the addressed card */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_INC_USE_COUNT;
++#else
+       lock_kernel();
++#endif
+       card = card_root;
+       while (card) {
+               pd = card->procconf;
+@@ -263,7 +266,11 @@
+               card = card->next;      /* search next entry */
+       }
+       if (!card) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++              MOD_DEC_USE_COUNT;
++#else
+               unlock_kernel();
++#endif
+               return (-ENODEV);       /* device is unknown/invalid */
+       }
+       if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
+@@ -274,7 +281,11 @@
+               /* write only access -> write boot file or conf line */
+               if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++                      MOD_DEC_USE_COUNT;
++#else
+                       unlock_kernel();
++#endif
+                       return (-EFAULT);
+               }
+               cnf->card = card;
+@@ -286,7 +297,11 @@
+               /* read access -> output card info data */
+               if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++                      MOD_DEC_USE_COUNT;
++#else
+                       unlock_kernel();
++#endif
+                       return (-EFAULT);       /* out of memory */
+               }
+               filep->private_data = tmp;      /* start of string */
+@@ -320,10 +335,16 @@
+               *cp++ = '\n';
+               *cp = 0;        /* end of string */
+       } else {                /* simultaneous read/write access forbidden ! */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++              MOD_DEC_USE_COUNT;
++#else
+               unlock_kernel();
++#endif
+               return (-EPERM);        /* no permission this time */
+       }
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+       unlock_kernel();
++#endif
+       return (0);
+ }                             /* hysdn_conf_open */
+@@ -338,7 +359,9 @@
+       int retval = 0;
+       struct proc_dir_entry *pd;
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+       lock_kernel();
++#endif
+       /* search the addressed card */
+       card = card_root;
+       while (card) {
+@@ -348,7 +371,9 @@
+               card = card->next;      /* search next entry */
+       }
+       if (!card) {
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+               unlock_kernel();
++#endif
+               return (-ENODEV);       /* device is unknown/invalid */
+       }
+       if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL))
+@@ -371,7 +396,11 @@
+               if (filep->private_data)
+                       kfree(filep->private_data);     /* release memory */
+       }
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_DEC_USE_COUNT;
++#else
+       unlock_kernel();
++#endif
+       return (retval);
+ }                             /* hysdn_conf_close */
+@@ -387,6 +416,9 @@
+       release:        hysdn_conf_close,                                       
+ };
++#ifdef COMPAT_NO_SOFTNET
++static struct inode_operations conf_inode_operations;
++#endif
+ /*****************************/
+ /* hysdn subdir in /proc/net */
+ /*****************************/
+@@ -415,8 +447,17 @@
+               if ((card->procconf = (void *) create_proc_entry(conf_name,
+                                            S_IFREG | S_IRUGO | S_IWUSR,
+                                           hysdn_proc_entry)) != NULL) {
++#ifdef COMPAT_NO_SOFTNET
++                      memset(&conf_inode_operations, 0, sizeof(struct inode_operations));
++                      conf_inode_operations.default_file_ops = &conf_fops;
++
++                      ((struct proc_dir_entry *) card->procconf)->ops = &conf_inode_operations;
++#else
+                       ((struct proc_dir_entry *) card->procconf)->proc_fops = &conf_fops;
++#ifdef COMPAT_HAS_FILEOP_OWNER
+                       ((struct proc_dir_entry *) card->procconf)->owner = THIS_MODULE;
++#endif
++#endif
+                       hysdn_proclog_init(card);       /* init the log file entry */
+               }
+               card = card->next;      /* next entry */
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_proclog.c linux-2.4.29/drivers/isdn/hysdn/hysdn_proclog.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_proclog.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_proclog.c    2005-03-22 15:06:48.613702376 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_proclog.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards, /proc/net filesystem log functions.
+  *
+@@ -16,7 +16,9 @@
+ #include <linux/poll.h>
+ #include <linux/proc_fs.h>
+ #include <linux/pci.h>
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+ #include <linux/smp_lock.h>
++#endif
+ #include "hysdn_defs.h"
+@@ -115,8 +117,7 @@
+       strcpy(ib->log_start, cp);      /* set output string */
+       ib->next = NULL;
+       ib->proc_ctrl = pd;     /* point to own control structure */
+-      save_flags(flags);
+-      cli();
++      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       ib->usage_cnt = pd->if_used;
+       if (!pd->log_head)
+               pd->log_head = ib;      /* new head */
+@@ -124,7 +125,7 @@
+               pd->log_tail->next = ib;        /* follows existing messages */
+       pd->log_tail = ib;      /* new tail */
+       i = pd->del_lock++;     /* get lock state */
+-      restore_flags(flags);
++      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+       /* delete old entrys */
+       if (!i)
+@@ -210,7 +211,6 @@
+       word ino;
+       struct procdata *pd = NULL;
+       hysdn_card *card;
+-      loff_t pos = *off;
+       if (!*((struct log_data **) file->private_data)) {
+               if (file->f_flags & O_NONBLOCK)
+@@ -235,11 +235,11 @@
+               return (0);
+       inf->usage_cnt--;       /* new usage count */
+-      file->private_data = &inf->next;        /* next structure */
++      (struct log_data **) file->private_data = &inf->next;   /* next structure */
+       if ((len = strlen(inf->log_start)) <= count) {
+               if (copy_to_user(buf, inf->log_start, len))
+                       return -EFAULT;
+-              *off = pos + len;
++              file->f_pos += len;
+               return (len);
+       }
+       return (0);
+@@ -255,7 +255,11 @@
+       struct procdata *pd = NULL;
+       ulong flags;
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_INC_USE_COUNT;
++#else
+       lock_kernel();
++#endif
+       card = card_root;
+       while (card) {
+               pd = card->proclog;
+@@ -264,7 +268,11 @@
+               card = card->next;      /* search next entry */
+       }
+       if (!card) {
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++              MOD_DEC_USE_COUNT;
++#else
+               unlock_kernel();
++#endif
+               return (-ENODEV);       /* device is unknown/invalid */
+       }
+       filep->private_data = card;     /* remember our own card */
+@@ -274,19 +282,24 @@
+       } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
+               /* read access -> log/debug read */
+-              save_flags(flags);
+-              cli();
++              HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+               pd->if_used++;
+               if (pd->log_head)
+-                      filep->private_data = &(pd->log_tail->next);
++                      (struct log_data **) filep->private_data = &(pd->log_tail->next);
+               else
+-                      filep->private_data = &(pd->log_head);
+-              restore_flags(flags);
++                      (struct log_data **) filep->private_data = &(pd->log_head);
++              HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+       } else {                /* simultaneous read/write access forbidden ! */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++              MOD_DEC_USE_COUNT;
++#else
+               unlock_kernel();
++#endif
+               return (-EPERM);        /* no permission this time */
+       }
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+       unlock_kernel();
++#endif
+       return (0);
+ }                             /* hysdn_log_open */
+@@ -306,7 +319,9 @@
+       int flags, retval = 0;
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+       lock_kernel();
++#endif
+       if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) {
+               /* write only access -> write debug level written */
+               retval = 0;     /* success */
+@@ -314,8 +329,7 @@
+               /* read access -> log/debug read, mark one further file as closed */
+               pd = NULL;
+-              save_flags(flags);
+-              cli();
++              HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+               inf = *((struct log_data **) filep->private_data);      /* get first log entry */
+               if (inf)
+                       pd = (struct procdata *) inf->proc_ctrl;        /* still entries there */
+@@ -338,7 +352,7 @@
+                       inf->usage_cnt--;       /* decrement usage count for buffers */
+                       inf = inf->next;
+               }
+-              restore_flags(flags);
++              HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+               if (pd)
+                       if (pd->if_used <= 0)   /* delete buffers if last file closed */
+@@ -348,7 +362,11 @@
+                                       kfree(inf);
+                               }
+       }                       /* read access */
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_DEC_USE_COUNT;
++#else
+       unlock_kernel();
++#endif
+       return (retval);
+ }                             /* hysdn_log_close */
+@@ -400,6 +418,9 @@
+       release:        hysdn_log_close,                                        
+ };
++#ifdef COMPAT_NO_SOFTNET
++struct inode_operations log_inode_operations;
++#endif
+ /***********************************************************************************/
+ /* hysdn_proclog_init is called when the module is loaded after creating the cards */
+@@ -414,10 +435,20 @@
+       if ((pd = (struct procdata *) kmalloc(sizeof(struct procdata), GFP_KERNEL)) != NULL) {
+               memset(pd, 0, sizeof(struct procdata));
++#ifdef COMPAT_NO_SOFTNET
++              memset(&log_inode_operations, 0, sizeof(struct inode_operations));
++              log_inode_operations.default_file_ops = &log_fops;
++#endif
+               sprintf(pd->log_name, "%s%d", PROC_LOG_BASENAME, card->myid);
+               if ((pd->log = create_proc_entry(pd->log_name, S_IFREG | S_IRUGO | S_IWUSR, hysdn_proc_entry)) != NULL) {
++#ifdef COMPAT_NO_SOFTNET
++                      pd->log->ops = &log_inode_operations;   /* set new operations table */
++#else
+                       pd->log->proc_fops = &log_fops; 
++#ifdef COMPAT_HAS_FILEOP_OWNER
+                       pd->log->owner = THIS_MODULE;
++#endif
++#endif
+               }
+               init_waitqueue_head(&(pd->rd_queue));
+diff -rNu linux-2.4.29.old/drivers/isdn/hysdn/hysdn_sched.c linux-2.4.29/drivers/isdn/hysdn/hysdn_sched.c
+--- linux-2.4.29.old/drivers/isdn/hysdn/hysdn_sched.c  2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/hysdn/hysdn_sched.c      2005-03-22 15:06:48.630699792 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_sched.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: hysdn_sched.c,v 1.9 2001/09/24 13:23:03 kai Exp $
+  *
+  * Linux driver for HYSDN cards
+  * scheduler routines for handling exchange card <-> pc.
+@@ -12,11 +12,9 @@
+  */
+ #include <linux/config.h>
+-#include <linux/sched.h>
+ #include <linux/signal.h>
+ #include <linux/kernel.h>
+ #include <linux/ioport.h>
+-#include <linux/interrupt.h>
+ #include <asm/io.h>
+ #include "hysdn_defs.h"
+@@ -151,22 +149,19 @@
+       if (card->debug_flags & LOG_SCHED_ASYN)
+               hysdn_addlog(card, "async tx-cfg chan=%d len=%d", chan, strlen(line) + 1);
+-
+-      save_flags(flags);
+-      cli();
++      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       while (card->async_busy) {
+-              sti();
+-
++              HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+               if (card->debug_flags & LOG_SCHED_ASYN)
+                       hysdn_addlog(card, "async tx-cfg delayed");
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout((20 * HZ) / 1000);     /* Timeout 20ms */
+               if (!--cnt) {
+-                      restore_flags(flags);
++                      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+                       return (-ERR_ASYNC_TIME);       /* timed out */
+               }
+-              cli();
++              HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       }                       /* wait for buffer to become free */
+       strcpy(card->async_data, line);
+@@ -177,31 +172,26 @@
+       /* now queue the task */
+       queue_task(&card->irq_queue, &tq_immediate);
+       mark_bh(IMMEDIATE_BH);
+-      sti();
+-
++      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+       if (card->debug_flags & LOG_SCHED_ASYN)
+               hysdn_addlog(card, "async tx-cfg data queued");
+       cnt++;                  /* short delay */
+-      cli();
+-
++      HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       while (card->async_busy) {
+-              sti();
+-
++              HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+               if (card->debug_flags & LOG_SCHED_ASYN)
+                       hysdn_addlog(card, "async tx-cfg waiting for tx-ready");
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout((20 * HZ) / 1000);     /* Timeout 20ms */
+               if (!--cnt) {
+-                      restore_flags(flags);
++                      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+                       return (-ERR_ASYNC_TIME);       /* timed out */
+               }
+-              cli();
++              HYSDN_SPIN_LOCK(&card->irq_lock, flags);
+       }                       /* wait for buffer to become free again */
+-
+-      restore_flags(flags);
+-
++      HYSDN_SPIN_UNLOCK(&card->irq_lock, flags);
+       if (card->debug_flags & LOG_SCHED_ASYN)
+               hysdn_addlog(card, "async tx-cfg data send");
+diff -rNu linux-2.4.29.old/drivers/isdn/icn/icn.c linux-2.4.29/drivers/isdn/icn/icn.c
+--- linux-2.4.29.old/drivers/isdn/icn/icn.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/icn/icn.c        2005-03-22 15:06:48.722685808 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icn.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * ISDN low-level module for the ICN active ISDN-Card.
+  *
+@@ -41,7 +41,7 @@
+ #undef MAP_DEBUG
+ static char
+-*revision = "$Revision: 1.1.4.1 $";
++*revision = "$Revision$";
+ static int icn_addcard(int, char *, char *);
+@@ -1634,6 +1634,7 @@
+ }
+ #ifndef MODULE
++#ifdef COMPAT_HAS_NEW_SETUP
+ static int __init
+ icn_setup(char *line)
+ {
+@@ -1643,6 +1644,14 @@
+       static char sid2[20];
+       str = get_options(line, 2, ints);
++#else
++void
++icn_setup(char *str, int *ints)
++{
++      char *p;
++      static char sid[20];
++      static char sid2[20];
++#endif
+       if (ints[0])
+               portbase = ints[1];
+       if (ints[0] > 1)
+@@ -1656,9 +1665,13 @@
+                       icn_id2 = sid2;
+               }
+       }
++#ifdef COMPAT_HAS_NEW_SETUP
+       return(1);
+ }
+ __setup("icn=", icn_setup);
++#else
++}
++#endif
+ #endif /* MODULE */
+ static int __init icn_init(void)
+diff -rNu linux-2.4.29.old/drivers/isdn/icn/icn.h linux-2.4.29/drivers/isdn/icn/icn.h
+--- linux-2.4.29.old/drivers/isdn/icn/icn.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/icn/icn.h        2005-03-22 15:06:48.752681248 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: icn.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for the ICN active ISDN-Card.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_audio.c linux-2.4.29/drivers/isdn/isdn_audio.c
+--- linux-2.4.29.old/drivers/isdn/isdn_audio.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_audio.c     2005-03-22 15:06:44.306357192 +0100
+@@ -1,9 +1,9 @@
+-/* $Id: isdn_audio.c,v 1.1.4.1 2001/11/20 14:19:33 kai Exp $
++/* $Id: isdn_audio.c,v 1.24 2002/08/13 09:57:26 keil Exp $
+  *
+  * Linux ISDN subsystem, audio conversion and compression (linklevel).
+  *
+  * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
+- * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
++ * DTMF code (c) 1996 by Christian Mock (cm@tahina.priv.at)
+  * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de)
+  *
+  * This software may be used and distributed according to the terms
+@@ -15,7 +15,7 @@
+ #include "isdn_audio.h"
+ #include "isdn_common.h"
+-char *isdn_audio_revision = "$Revision: 1.1.4.1 $";
++char *isdn_audio_revision = "$Revision: 1.24 $";
+ /*
+  * Misc. lookup-tables.
+@@ -169,19 +169,39 @@
+       0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
+ };
+-#define NCOEFF            8     /* number of frequencies to be analyzed       */
+-#define DTMF_TRESH     4000     /* above this is dtmf                         */
++#define NCOEFF           16     /* number of frequencies to be analyzed       */
++#define DTMF_TRESH    25000     /* above this is dtmf                         */
+ #define SILENCE_TRESH   200     /* below this is silence                      */
++#define H2_TRESH      20000     /* 2nd harmonic                               */
+ #define AMP_BITS          9     /* bits per sample, reduced to avoid overflow */
+ #define LOGRP             0
+ #define HIGRP             1
++typedef struct {
++      int grp;                /* low/high group     */
++      int k;                  /* k                  */
++      int k2;                 /* k fuer 2. harmonic */
++} dtmf_t;
++
+ /* For DTMF recognition:
+  * 2 * cos(2 * PI * k / N) precalculated for all k
+  */
+ static int cos2pik[NCOEFF] =
+ {
+-      55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
++      55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517,
++      38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279
++};
++
++static dtmf_t dtmf_tones[8] =
++{
++      {LOGRP, 0, 1},          /*  697 Hz */
++      {LOGRP, 2, 3},          /*  770 Hz */
++      {LOGRP, 4, 5},          /*  852 Hz */
++      {LOGRP, 6, 7},          /*  941 Hz */
++      {HIGRP, 8, 9},          /* 1209 Hz */
++      {HIGRP, 10, 11},        /* 1336 Hz */
++      {HIGRP, 12, 13},        /* 1477 Hz */
++      {HIGRP, 14, 15}         /* 1633 Hz */
+ };
+ static char dtmf_matrix[4][4] =
+@@ -208,7 +228,7 @@
+       :       "memory", "ax");
+ #else
+       while (n--)
+-              *buff = table[*(unsigned char *)buff], buff++;
++              *buff++ = table[*(unsigned char *)buff];
+ #endif
+ }
+@@ -479,18 +499,6 @@
+                       sk2 = sk1;
+                       sk1 = sk;
+               }
+-              /* Avoid overflows */
+-              sk >>= 1;
+-              sk2 >>= 1;
+-              /* compute |X(k)|**2 */
+-              /* report overflows. This should not happen. */
+-              /* Comment this out if desired */
+-              if (sk < -32768 || sk > 32767)
+-                      printk(KERN_DEBUG
+-                             "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
+-              if (sk2 < -32768 || sk2 > 32767)
+-                      printk(KERN_DEBUG
+-                             "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
+               result[k] =
+                   ((sk * sk) >> AMP_BITS) -
+                   ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
+@@ -514,58 +522,28 @@
+       int grp[2];
+       char what;
+       char *p;
+-      int thresh;
+       while ((skb = skb_dequeue(&info->dtmf_queue))) {
+               result = (int *) skb->data;
+               s = info->dtmf_state;
+-              grp[LOGRP] = grp[HIGRP] = -1;
++              grp[LOGRP] = grp[HIGRP] = -2;
+               silence = 0;
+-              thresh = 0;
+-              for (i = 0; i < NCOEFF; i++) {
+-                      if (result[i] > DTMF_TRESH) {
+-                              if (result[i] > thresh)
+-                                      thresh = result[i];
+-                      }
+-                      else if (result[i] < SILENCE_TRESH)
++              for (i = 0; i < 8; i++) {
++                      if ((result[dtmf_tones[i].k] > DTMF_TRESH) &&
++                          (result[dtmf_tones[i].k2] < H2_TRESH))
++                              grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1;
++                      else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) &&
++                            (result[dtmf_tones[i].k2] < SILENCE_TRESH))
+                               silence++;
+               }
+-              if (silence == NCOEFF)
++              if (silence == 8)
+                       what = ' ';
+               else {
+-                      if (thresh > 0) {
+-                              thresh = thresh >> 4;  /* touchtones must match within 12 dB */
+-                              for (i = 0; i < NCOEFF; i++) {
+-                                      if (result[i] < thresh)
+-                                              continue;  /* ignore */
+-                                      /* good level found. This is allowed only one time per group */
+-                                      if (i < NCOEFF / 2) {
+-                                              /* lowgroup*/
+-                                              if (grp[LOGRP] >= 0) {
+-                                                      // Bad. Another tone found. */
+-                                                      grp[LOGRP] = -1;
+-                                                      break;
+-                                              }
+-                                              else
+-                                                      grp[LOGRP] = i;
+-                                      }
+-                                      else { /* higroup */
+-                                              if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
+-                                                      grp[HIGRP] = -1;
+-                                                      break;
+-                                              }
+-                                              else
+-                                                      grp[HIGRP] = i - NCOEFF/2;
+-                                      }
+-                              }
+-                              if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
+-                                      what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
+-                                      if (s->last != ' ' && s->last != '.')
+-                                              s->last = what; /* min. 1 non-DTMF between DTMF */
+-                              } else
+-                                      what = '.';
+-                      }
+-                      else
++                      if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
++                              what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4];
++                              if (s->last != ' ' && s->last != '.')
++                                      s->last = what; /* min. 1 non-DTMF between DTMF */
++                      } else
+                               what = '.';
+               }
+               if ((what != s->last) && (what != ' ') && (what != '.')) {
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_audio.h linux-2.4.29/drivers/isdn/isdn_audio.h
+--- linux-2.4.29.old/drivers/isdn/isdn_audio.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_audio.h     2005-03-22 15:06:44.321354912 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_audio.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_audio.h,v 1.10 2001/09/24 13:22:42 kai Exp $
+  *
+  * Linux ISDN subsystem, audio conversion and compression (linklevel).
+  *
+@@ -20,7 +20,6 @@
+ typedef struct dtmf_state {
+       char last;
+-      char llast;
+       int idx;
+       int buf[DTMF_NPOINTS];
+ } dtmf_state;
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_bsdcomp.c linux-2.4.29/drivers/isdn/isdn_bsdcomp.c
+--- linux-2.4.29.old/drivers/isdn/isdn_bsdcomp.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_bsdcomp.c   2005-03-22 15:06:44.339352176 +0100
+@@ -105,6 +105,14 @@
+ #define DEBUG 1
++#ifdef CONFIG_ISDN_WITH_ABC
++#define BSD_C_MALLOC(x)     kmalloc((x),GFP_ATOMIC)
++#define BSD_C_FREE(x)       kfree(x)
++#else
++#define BSD_C_MALLOC(x)     vmalloc(x)
++#define BSD_C_FREE(x)       vfree(x)
++#endif
++
+ /*
+  * A dictionary for doing BSD compress.
+  */
+@@ -285,7 +293,7 @@
+                * Release the dictionary
+                */
+               if (db->dict) {
+-                      vfree (db->dict);
++                      BSD_C_FREE (db->dict);
+                       db->dict = NULL;
+               }
+@@ -293,7 +301,7 @@
+                * Release the string buffer
+                */
+               if (db->lens) {
+-                      vfree (db->lens);
++                      BSD_C_FREE (db->lens);
+                       db->lens = NULL;
+               }
+@@ -350,14 +358,19 @@
+        * Allocate space for the dictionary. This may be more than one page in
+        * length.
+        */
+-      db->dict = (struct bsd_dict *) vmalloc (hsize * sizeof (struct bsd_dict));
++      db->dict = (struct bsd_dict *) BSD_C_MALLOC (hsize * sizeof (struct bsd_dict));
++
++      MOD_INC_USE_COUNT;
++      /*
++      ** MOD_INC_USE_COUNT must be before bsd_free
++      ** bsd_free make MOD_DEC_USE_COUNT if db != NULL
++      */
++
+       if (!db->dict) {
+               bsd_free (db);
+               return NULL;
+       }
+-      MOD_INC_USE_COUNT;
+-
+       /*
+        * If this is the compression buffer then there is no length data.
+        * For decompression, the length information is needed as well.
+@@ -365,7 +378,7 @@
+       if (!decomp)
+               db->lens = NULL;
+       else {
+-              db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) *
++              db->lens = (unsigned short *) BSD_C_MALLOC ((maxmaxcode + 1) *
+                       sizeof (db->lens[0]));
+               if (!db->lens) {
+                       bsd_free (db); /* calls MOD_DEC_USE_COUNT; */
+@@ -478,7 +491,11 @@
+       int hval,disp,ilen,mxcode;
+       unsigned char *rptr = skb_in->data;
+       int isize = skb_in->len;
++#ifdef CONFIG_ISDN_WITH_ABC
++      long secure = 0;
++#endif
++#ifndef CONFIG_ISDN_WITH_ABC
+ #define OUTPUT(ent)                   \
+   {                                   \
+     bitno -= n_bits;                  \
+@@ -490,17 +507,45 @@
+       bitno += 8;                     \
+     } while (bitno <= 24);            \
+   }
++#else
++#define OUTPUT(ent)                   \
++  {                                   \
++      secure = 0;                                     \
++    bitno -= n_bits;                  \
++    accm |= ((ent) << bitno);         \
++    do        {                               \
++        if(skb_out && skb_tailroom(skb_out) > 0)      \
++                      *(skb_put(skb_out,1)) = (unsigned char) (accm>>24); \
++      accm <<= 8;                     \
++      bitno += 8;                     \
++      } while (bitno <= 24 && ++secure < 10000);              \
++      if(secure >= 10000) {                                                   \
++              printk(KERN_DEBUG "BSD in OUTPUT secure counter reached\n");    \
++              return 0;                                                                       \
++      }                                                                                               \
++  }
++#endif
+       /*
+        * If the protocol is not in the range we're interested in,
+        * just return without compressing the packet.  If it is,
+        * the protocol becomes the first byte to compress.
+        */
++#ifdef CONFIG_ISDN_WITH_ABC
++      ent = proto;
++
++      if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) ) {
++
++              printk(KERN_DEBUG "bsd_compress called with %x\n",proto);
++              return 0;
++      }
++#else
+       printk(KERN_DEBUG "bsd_compress called with %x\n",proto);
+       
+       ent = proto;
+       if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) )
+               return 0;
++#endif
+       db      = (struct bsd_db *) state;
+       hshift  = db->hshift;
+@@ -538,6 +583,9 @@
+       
+               /* continue probing until a match or invalid entry */
+               disp = (hval == 0) ? 1 : hval;
++#ifdef CONFIG_ISDN_WITH_ABC
++              secure = 0;
++#endif
+               do {
+                       hval += disp;
+@@ -546,7 +594,15 @@
+                       dictp = dict_ptr (db, hval);
+                       if (dictp->codem1 >= max_ent)
+                               goto nomatch;
++#ifndef CONFIG_ISDN_WITH_ABC
+               } while (dictp->fcode != fcode);
++#else
++              } while (dictp->fcode != fcode && ++secure < 100000);
++              if(secure >= 100000) {
++                      printk(KERN_DEBUG "BSD: compress while dictp->fcode != fcode secure-counter reached\n");
++                      return 0;
++              }
++#endif
+               ent = dictp->codem1 + 1;        /* finally found (prefix,suffix) */
+               continue;
+@@ -669,6 +725,9 @@
+       int ilen;
+       int codelen;
+       int extra;
++#ifdef CONFIG_ISDN_WITH_ABC
++      unsigned long secure = 0;
++#endif
+       db       = (struct bsd_db *) state;
+       max_ent  = db->max_ent;
+@@ -677,7 +736,9 @@
+       n_bits   = db->n_bits;
+       tgtbitno = 32 - n_bits; /* bitno when we have a code */
++#ifndef CONFIG_ISDN_WITH_ABC
+       printk(KERN_DEBUG "bsd_decompress called\n");
++#endif
+       if(!skb_in || !skb_out) {
+               printk(KERN_ERR "bsd_decompress called with NULL parameter\n");
+@@ -795,7 +856,11 @@
+               p     = skb_put(skb_out,codelen);
+               p += codelen;
++#ifdef CONFIG_ISDN_WITH_ABC
++              for(secure = 0; finchar > LAST && secure < 50000;secure++) {
++#else
+               while (finchar > LAST) {
++#endif
+                       struct bsd_dict *dictp2 = dict_ptr (db, finchar);
+           
+                       dictp = dict_ptr (db, dictp2->cptr);
+@@ -822,6 +887,12 @@
+                       }
+               }
+               *--p = finchar;
++#ifdef CONFIG_ISDN_WITH_ABC
++              if(secure >= 50000) {
++                      printk(KERN_DEBUG "BSD: decompress secure-counter reached\n");
++                      return DECOMP_FATALERROR;
++              }
++#endif
+       
+ #ifdef DEBUG
+               if (--codelen != 0)
+@@ -851,12 +922,23 @@
+                       /* look for a free hash table entry */
+                       if (dictp->codem1 < max_ent) {
+                               disp = (hval == 0) ? 1 : hval;
++#ifdef CONFIG_ISDN_WITH_ABC
++                              secure = 0;
++#endif
+                               do {
+                                       hval += disp;
+                                       if (hval >= db->hsize)
+                                               hval -= db->hsize;
+                                       dictp = dict_ptr (db, hval);
++#ifndef CONFIG_ISDN_WITH_ABC
+                               } while (dictp->codem1 < max_ent);
++#else
++                              } while (dictp->codem1 < max_ent && ++secure < 50000);
++                              if(secure >= 50000) {
++                                      printk(KERN_DEBUG "BSD: decomp while (dictp->codem1 < max_ent) secure-counter reached\n");
++                                      return DECOMP_FATALERROR;
++                              }
++#endif
+                       }
+           
+                       /*
+@@ -895,11 +977,21 @@
+       db->comp_bytes   += skb_in->len - BSD_OVHD;
+       db->uncomp_bytes += skb_out->len;
++#ifdef CONFIG_ISDN_WITH_ABC
++      /*
++      ** bsd_check will call bsd_clear 
++      ** and so on the internal tables will be cleared.
++      **
++      ** I think that's not what we will at this point ?????
++      ** For me at works without bsd_check.
++      */
++#else
+       if (bsd_check(db)) {
+               if (db->debug)
+                       printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",
+                               db->unit, db->seqno - 1);
+       }
++#endif
+       return skb_out->len;
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_common.c linux-2.4.29/drivers/isdn/isdn_common.c
+--- linux-2.4.29.old/drivers/isdn/isdn_common.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_common.c    2005-03-22 15:06:44.359349136 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_common.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_common.c,v 1.137 2002/02/09 21:19:11 keil Exp $
+  *
+  * Linux ISDN subsystem, common used functions (linklevel).
+  *
+@@ -19,6 +19,7 @@
+ #include <linux/vmalloc.h>
+ #include <linux/isdn.h>
+ #include <linux/smp_lock.h>
++#include <linux/list.h>
+ #include "isdn_common.h"
+ #include "isdn_tty.h"
+ #include "isdn_net.h"
+@@ -33,7 +34,9 @@
+ #include <linux/isdn_divertif.h>
+ #endif /* CONFIG_ISDN_DIVERSION */
+ #include "isdn_v110.h"
++#ifdef HAVE_DEVFS_FS
+ #include <linux/devfs_fs_kernel.h>
++#endif /* HAVE_DEVFS_FS */
+ /* Debugflags */
+ #undef ISDN_DEBUG_STATCALLB
+@@ -44,7 +47,7 @@
+ isdn_dev *dev;
+-static char *isdn_revision = "$Revision: 1.1.4.1 $";
++static char *isdn_revision = "$Revision: 1.137 $";
+ extern char *isdn_net_revision;
+ extern char *isdn_tty_revision;
+@@ -67,19 +70,19 @@
+ static int isdn_writebuf_stub(int, int, const u_char *, int, int);
+ static void set_global_features(void);
++#ifdef HAVE_DEVFS_FS
+ static void isdn_register_devfs(int);
+ static void isdn_unregister_devfs(int);
++#endif /* HAVE_DEVFS_FS */
+ static int isdn_wildmat(char *s, char *p);
+ void
+ isdn_lock_drivers(void)
+ {
+       int i;
+-      isdn_ctrl cmd;
+-      for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+-              if (!dev->drv[i])
+-                      continue;
++      for (i = 0; i < dev->drivers; i++) {
++              isdn_ctrl cmd;
+               cmd.driver = i;
+               cmd.arg = 0;
+@@ -101,10 +104,7 @@
+ {
+       int i;
+-      for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+-              if (!dev->drv[i])
+-                      continue;
+-
++      for (i = 0; i < dev->drivers; i++)
+               if (dev->drv[i]->locks > 0) {
+                       isdn_ctrl cmd;
+@@ -114,7 +114,6 @@
+                       isdn_command(&cmd);
+                       dev->drv[i]->locks--;
+               }
+-      }
+ }
+ void
+@@ -473,6 +472,7 @@
+                       dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
+                       break;
+               case ISDN_STAT_ICALL:
++              case ISDN_STAT_ICALLW:
+                       if (i < 0)
+                               return -1;
+ #ifdef ISDN_DEBUG_STATCALLB
+@@ -718,7 +718,9 @@
+                                       dev->drvmap[i] = -1;
+                                       dev->chanmap[i] = -1;
+                                       dev->usage[i] &= ~ISDN_USAGE_DISABLED;
++#ifdef HAVE_DEVFS_FS
+                                       isdn_unregister_devfs(i);
++#endif /* HAVE_DEVFS_FS */
+                               }
+                       dev->drivers--;
+                       dev->channels -= dev->drv[di]->channels;
+@@ -755,6 +757,10 @@
+                         if (divert_if)
+                           return(divert_if->stat_callback(c));
+ #endif /* CONFIG_ISDN_DIVERSION */
++              case ISDN_STAT_ALERT:
++              case ISDN_STAT_PROCEED:
++                      isdn_tty_stat_callback(i, c);
++                      break;
+               default:
+                       return -1;
+       }
+@@ -900,72 +906,239 @@
+       return (dev->chanmap[minor]);
+ }
+-static char *
+-isdn_statstr(void)
++// ----------------------------------------------------------------------
++// /dev/isdninfo
++// 
++// This device has somewhat insane semantics, but we need to support
++// them for the sake of compatibility.
++//
++// After opening, the first read will succeed and return the current state
++// Then, unless O_NONBLOCK is set, it will block until a state change happens
++// and then return the new state.
++// Also, if the buffer size for the read is too small, we'll just return
++// EOF
++
++struct isdnstatus_dev {
++      struct list_head list;
++      int update;
++};
++
++static DECLARE_WAIT_QUEUE_HEAD(isdnstatus_waitq);
++static LIST_HEAD(isdnstatus_devs);
++static spinlock_t isdnstatus_devs_lock = SPIN_LOCK_UNLOCKED;
++
++void
++isdn_info_update(void)
++{
++      struct list_head *p;
++      struct isdnstatus_dev *idev;
++
++      spin_lock(&isdnstatus_devs_lock);
++      list_for_each(p, &isdnstatus_devs) {
++              idev = list_entry(p, struct isdnstatus_dev, list);
++              idev->update = 1;
++      }
++      spin_unlock(&isdnstatus_devs_lock);
++      wake_up_interruptible(&isdnstatus_waitq);
++}
++
++static int
++isdnstatus_open(struct inode *ino, struct file *filep)
++{
++      struct isdnstatus_dev *p;
++
++      p = kmalloc(sizeof(struct isdnstatus_dev), GFP_USER);
++      if (!p)
++              return -ENOMEM;
++
++      /* At opening time we allow a single update */
++      p->update = 1;
++      spin_lock(&isdnstatus_devs_lock);
++      list_add(&p->list, &isdnstatus_devs);
++      spin_unlock(&isdnstatus_devs_lock);
++      filep->private_data = p;
++
++      return 0;
++}
++
++static void
++isdnstatus_close(struct inode *ino, struct file *filep)
++{
++      struct isdnstatus_dev *p = filep->private_data;
++
++      spin_lock(&isdnstatus_devs_lock);
++      list_del(&p->list);
++      spin_unlock(&isdnstatus_devs_lock);
++      kfree(p);
++}
++
++// FIXME we don't lock against the state changing whilst being
++// printed
++
++void
++isdn_statstr(char *buf)
+ {
+-      static char istatbuf[2048];
+       char *p;
+       int i;
+-      sprintf(istatbuf, "idmap:\t");
+-      p = istatbuf + strlen(istatbuf);
++      p = buf;
++      p += sprintf(p, "idmap:\t");
+       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+-              sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
+-              p = istatbuf + strlen(istatbuf);
++              p += sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
+       }
+-      sprintf(p, "\nchmap:\t");
+-      p = istatbuf + strlen(istatbuf);
++      p += sprintf(p, "\nchmap:\t");
+       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+-              sprintf(p, "%d ", dev->chanmap[i]);
+-              p = istatbuf + strlen(istatbuf);
++              p += sprintf(p, "%d ", dev->chanmap[i]);
+       }
+-      sprintf(p, "\ndrmap:\t");
+-      p = istatbuf + strlen(istatbuf);
++      p += sprintf(p, "\ndrmap:\t");
+       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+-              sprintf(p, "%d ", dev->drvmap[i]);
+-              p = istatbuf + strlen(istatbuf);
++              p += sprintf(p, "%d ", dev->drvmap[i]);
+       }
+-      sprintf(p, "\nusage:\t");
+-      p = istatbuf + strlen(istatbuf);
++      p += sprintf(p, "\nusage:\t");
+       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+-              sprintf(p, "%d ", dev->usage[i]);
+-              p = istatbuf + strlen(istatbuf);
++              p += sprintf(p, "%d ", dev->usage[i]);
+       }
+-      sprintf(p, "\nflags:\t");
+-      p = istatbuf + strlen(istatbuf);
++      p += sprintf(p, "\nflags:\t");
+       for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
+               if (dev->drv[i]) {
+-                      sprintf(p, "%ld ", dev->drv[i]->online);
+-                      p = istatbuf + strlen(istatbuf);
++                      p += sprintf(p, "%ld ", dev->drv[i]->online);
+               } else {
+-                      sprintf(p, "? ");
+-                      p = istatbuf + strlen(istatbuf);
++                      p += sprintf(p, "? ");
+               }
+       }
+-      sprintf(p, "\nphone:\t");
+-      p = istatbuf + strlen(istatbuf);
++      p += sprintf(p, "\nphone:\t");
+       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+-              sprintf(p, "%s ", dev->num[i]);
+-              p = istatbuf + strlen(istatbuf);
++              p += sprintf(p, "%s ", dev->num[i]);
+       }
+-      sprintf(p, "\n");
+-      return istatbuf;
++      p += sprintf(p, "\n");
+ }
+-/* Module interface-code */
++static ssize_t
++isdnstatus_read(struct file *file, char *buf, size_t count, loff_t * off)
++{
++      static DECLARE_MUTEX(istatbuf_mutex);
++      static char istatbuf[2048];
+-void
+-isdn_info_update(void)
++        DECLARE_WAITQUEUE(wait, current);
++      struct isdnstatus_dev *idev;
++      int retval = 0;
++      unsigned int len;
++
++      idev = file->private_data;
++
++      if (off != &file->f_pos)
++              return -ESPIPE;
++
++        add_wait_queue(&isdnstatus_waitq, &wait);
++        for (;;) {
++                set_current_state(TASK_INTERRUPTIBLE);
++                
++              if (idev->update)
++                        break;
++
++                retval = -EAGAIN;
++                if (file->f_flags & O_NONBLOCK)
++                        break;
++
++                retval = -ERESTARTSYS;
++                if (signal_pending(current))
++                        break;
++
++                schedule();
++        }
++        __set_current_state(TASK_RUNNING);
++        remove_wait_queue(&isdnstatus_waitq, &wait);
++
++      if (!idev->update)
++              goto out;
++
++      idev->update = 0;
++      down(&istatbuf_mutex);
++      isdn_statstr(istatbuf);
++      len = strlen(istatbuf);
++      if (len > count) {
++              retval = 0;
++              goto out_unlock;
++      }
++      if (copy_to_user(buf, istatbuf, len)) {
++              retval = -EFAULT;
++              goto out_unlock;
++      }
++      *off += len;
++      retval = len;
++
++ out_unlock:
++      up(&istatbuf_mutex);
++ out:
++      return retval;
++}
++
++static ssize_t
++isdnstatus_write(struct file *file, const char *buf, size_t count, loff_t * off)
+ {
+-      infostruct *p = dev->infochain;
++      return -EINVAL;
++}
++
++static unsigned int
++isdnstatus_poll(struct file *file, poll_table * wait)
++{
++      struct isdnstatus_dev *idev;
++      unsigned int mask = 0;
++
++      idev = file->private_data;
+-      while (p) {
+-              *(p->private) = 1;
+-              p = (infostruct *) p->next;
++      poll_wait(file, &isdnstatus_waitq, wait);
++      if (idev->update) {
++              mask |= POLLIN | POLLRDNORM;
+       }
+-      wake_up_interruptible(&(dev->info_waitq));
++      return mask;
+ }
++static int
++isdnstatus_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
++{
++      int retval;
++      isdn_net_ioctl_phone phone;
++
++      switch (cmd) {
++      case IIOCGETDVR:
++              return (TTY_DV +
++                      (NET_DV << 8) +
++                      (INF_DV << 16));
++      case IIOCGETCPS:
++              if (arg) {
++                      ulong *p = (ulong *) arg;
++                      int i;
++                      if ((retval = verify_area(VERIFY_WRITE, (void *) arg,
++                                             sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
++                              return retval;
++                      for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
++                              put_user(dev->ibytes[i], p++);
++                              put_user(dev->obytes[i], p++);
++                      }
++                      return 0;
++              } else
++                      return -EINVAL;
++              break;
++#ifdef CONFIG_NETDEVICES
++      case IIOCNETGPN:
++              /* Get peer phone number of a connected 
++               * isdn network interface */
++              if (arg) {
++                      if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
++                              return -EFAULT;
++                      return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
++              } else
++                      return -EINVAL;
++#endif
++      default:
++              return -EINVAL;
++      }
++}
++
++// ----------------------------------------------------------------------
++
++
+ static ssize_t
+ isdn_read(struct file *file, char *buf, size_t count, loff_t * off)
+ {
+@@ -976,37 +1149,16 @@
+       int chidx;
+       int retval;
+       char *p;
+-      loff_t pos = *off;
+       if (off != &file->f_pos)
+               return -ESPIPE;
+-      if (pos != (unsigned) pos)
+-              return -EINVAL;
+-
++#ifndef COMPAT_HAVE_READ_LOCK_KERNEL
+       lock_kernel();
+-      if (minor == ISDN_MINOR_STATUS) {
+-              if (!file->private_data) {
+-                      if (file->f_flags & O_NONBLOCK) {
+-                              retval = -EAGAIN;
+-                              goto out;
+-                      }
+-                      interruptible_sleep_on(&(dev->info_waitq));
+-              }
+-              p = isdn_statstr();
+-              file->private_data = 0;
+-              if ((len = strlen(p)) <= count) {
+-                      if (copy_to_user(buf, p, len)) {
+-                              retval = -EFAULT;
+-                              goto out;
+-                      }
+-                      *off = pos + len;
+-                      retval = len;
+-                      goto out;
+-              }
+-              retval = 0;
+-              goto out;
+-      }
++#endif
++      if (minor == ISDN_MINOR_STATUS)
++              return isdnstatus_read(file, buf, count, off);
++        
+       if (!dev->drivers) {
+               retval = -ENODEV;
+               goto out;
+@@ -1031,7 +1183,7 @@
+               cli();
+               len = isdn_readbchan(drvidx, chidx, p, 0, count,
+                                    &dev->drv[drvidx]->rcv_waitq[chidx]);
+-              *off = pos + len;
++              *off += len;
+               restore_flags(flags);
+               if (copy_to_user(buf,p,len)) 
+                       len = -EFAULT;
+@@ -1052,6 +1204,9 @@
+                       }
+                       interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
+               }
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++              if(drvidx || (len = isdn_dw_abc_lcr_readstat(buf,count)) < 1) {
++#endif
+               if (dev->drv[drvidx]->interface->readstat) {
+                       if (count > dev->drv[drvidx]->stavail)
+                               count = dev->drv[drvidx]->stavail;
+@@ -1061,6 +1216,9 @@
+               } else {
+                       len = 0;
+               }
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++              }
++#endif
+               save_flags(flags);
+               cli();
+               if (len)
+@@ -1068,7 +1226,7 @@
+               else
+                       dev->drv[drvidx]->stavail = 0;
+               restore_flags(flags);
+-              *off = pos + len;
++              *off += len;
+               retval = len;
+               goto out;
+       }
+@@ -1080,7 +1238,9 @@
+ #endif
+       retval = -ENODEV;
+  out:
++#ifndef COMPAT_HAVE_READ_LOCK_KERNEL
+       unlock_kernel();
++#endif
+       return retval;
+ }
+@@ -1092,15 +1252,18 @@
+       int chidx;
+       int retval;
++      if (minor == ISDN_MINOR_STATUS)
++              return isdnstatus_write(file, buf, count, off);
++
+       if (off != &file->f_pos)
+               return -ESPIPE;
+-      if (minor == ISDN_MINOR_STATUS)
+-              return -EPERM;
+       if (!dev->drivers)
+               return -ENODEV;
++#ifndef COMPAT_HAVE_WRITE_LOCK_KERNEL
+       lock_kernel();
++#endif
+       if (minor <= ISDN_MINOR_BMAX) {
+               printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
+               drvidx = isdn_minor2drv(minor);
+@@ -1145,7 +1308,9 @@
+ #endif
+       retval = -ENODEV;
+  out:
++#ifndef COMPAT_HAVE_WRITE_LOCK_KERNEL
+       unlock_kernel();
++#endif
+       return retval;
+ }
+@@ -1156,15 +1321,12 @@
+       unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+       int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
++#ifndef COMPAT_HAVE_POLL_LOCK_KERNEL
+       lock_kernel();
+-      if (minor == ISDN_MINOR_STATUS) {
+-              poll_wait(file, &(dev->info_waitq), wait);
+-              /* mask = POLLOUT | POLLWRNORM; */
+-              if (file->private_data) {
+-                      mask |= POLLIN | POLLRDNORM;
+-              }
+-              goto out;
+-      }
++#endif
++      if (minor == ISDN_MINOR_STATUS)
++              return isdnstatus_poll(file, wait);
++
+       if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
+               if (drvidx < 0) {
+                       /* driver deregistered while file open */
+@@ -1186,7 +1348,9 @@
+ #endif
+       mask = POLLERR;
+  out:
++#ifndef COMPAT_HAVE_POLL_LOCK_KERNEL
+       unlock_kernel();
++#endif
+       return mask;
+ }
+@@ -1216,42 +1380,9 @@
+ #define phone iocpar.phone
+ #define cfg   iocpar.cfg
+-      if (minor == ISDN_MINOR_STATUS) {
+-              switch (cmd) {
+-                      case IIOCGETDVR:
+-                              return (TTY_DV +
+-                                      (NET_DV << 8) +
+-                                      (INF_DV << 16));
+-                      case IIOCGETCPS:
+-                              if (arg) {
+-                                      ulong *p = (ulong *) arg;
+-                                      int i;
+-                                      if ((ret = verify_area(VERIFY_WRITE, (void *) arg,
+-                                                             sizeof(ulong) * ISDN_MAX_CHANNELS * 2)))
+-                                              return ret;
+-                                      for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+-                                              put_user(dev->ibytes[i], p++);
+-                                              put_user(dev->obytes[i], p++);
+-                                      }
+-                                      return 0;
+-                              } else
+-                                      return -EINVAL;
+-                              break;
+-#ifdef CONFIG_NETDEVICES
+-                      case IIOCNETGPN:
+-                              /* Get peer phone number of a connected 
+-                               * isdn network interface */
+-                              if (arg) {
+-                                      if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+-                                              return -EFAULT;
+-                                      return isdn_net_getpeer(&phone, (isdn_net_ioctl_phone *) arg);
+-                              } else
+-                                      return -EINVAL;
+-#endif
+-                      default:
+-                              return -EINVAL;
+-              }
+-      }
++      if (minor == ISDN_MINOR_STATUS)
++              return isdnstatus_ioctl(inode, file, cmd, arg);
++
+       if (!dev->drivers)
+               return -ENODEV;
+       if (minor <= ISDN_MINOR_BMAX) {
+@@ -1273,11 +1404,34 @@
+  */
+               switch (cmd) {
+                       case IIOCNETDWRSET:
++#ifdef CONFIG_ISDN_WITH_ABC
++                              if (arg) {
++
++                                      if (copy_from_user(name, (char *) arg, sizeof(name))) {
++
++                                              return(-EFAULT);
++
++                                      } else {
++
++                                              isdn_net_dev *p = isdn_net_findif(name);
++
++                                              if(p == NULL)
++                                                      return(-EINVAL);
++
++                                              return(isdn_dw_abc_reset_interface(p->local,1));
++                                      }
++                              } 
++#else
+                               printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
++#endif
+                               return(-EINVAL);
+                       case IIOCNETLCR:
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++                              return(isdn_dw_abc_lcr_ioctl(arg));
++#else
+                               printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
+                               return -ENODEV;
++#endif
+ #ifdef CONFIG_NETDEVICES
+                       case IIOCNETAIF:
+                               /* Add a network-interface */
+@@ -1650,22 +1804,12 @@
+       int chidx;
+       int retval = -ENODEV;
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_INC_USE_COUNT;
++#endif
+       if (minor == ISDN_MINOR_STATUS) {
+-              infostruct *p;
+-
+-              if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
+-                      p->next = (char *) dev->infochain;
+-                      p->private = (char *) &(filep->private_data);
+-                      dev->infochain = p;
+-                      /* At opening we allow a single update */
+-                      filep->private_data = (char *) 1;
+-                      retval = 0;
+-                      goto out;
+-              } else {
+-                      retval = -ENOMEM;
+-                      goto out;
+-              }
++              return isdnstatus_open(ino, filep);
+       }
+       if (!dev->channels)
+               goto out;
+@@ -1688,6 +1832,9 @@
+               if (drvidx < 0)
+                       goto out;
+               isdn_lock_drivers();
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++              if(!drvidx) isdn_dw_abc_lcr_open();
++#endif
+               retval = 0;
+               goto out;
+       }
+@@ -1700,6 +1847,10 @@
+       }
+ #endif
+  out:
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      if (retval)
++              MOD_DEC_USE_COUNT;
++#endif
+       return retval;
+ }
+@@ -1708,25 +1859,11 @@
+ {
+       uint minor = MINOR(ino->i_rdev);
++#ifndef COMPAT_USE_MODCOUNT_LOCK
+       lock_kernel();
++#endif
+       if (minor == ISDN_MINOR_STATUS) {
+-              infostruct *p = dev->infochain;
+-              infostruct *q = NULL;
+-
+-              while (p) {
+-                      if (p->private == (char *) &(filep->private_data)) {
+-                              if (q)
+-                                      q->next = p->next;
+-                              else
+-                                      dev->infochain = (infostruct *) (p->next);
+-                              kfree(p);
+-                              goto out;
+-                      }
+-                      q = p;
+-                      p = (infostruct *) (p->next);
+-              }
+-              printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
+-              goto out;
++              isdnstatus_close(ino, filep);
+       }
+       isdn_unlock_drivers();
+       if (minor <= ISDN_MINOR_BMAX)
+@@ -1734,6 +1871,12 @@
+       if (minor <= ISDN_MINOR_CTRLMAX) {
+               if (dev->profd == current)
+                       dev->profd = NULL;
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++              {
++                      int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
++                      if(!drvidx) isdn_dw_abc_lcr_close();
++              }
++#endif
+               goto out;
+       }
+ #ifdef CONFIG_ISDN_PPP
+@@ -1742,13 +1885,19 @@
+ #endif
+  out:
++#ifdef COMPAT_USE_MODCOUNT_LOCK
++      MOD_DEC_USE_COUNT;
++#else
+       unlock_kernel();
++#endif
+       return 0;
+ }
+ static struct file_operations isdn_fops =
+ {
++#ifdef COMPAT_HAS_FILEOP_OWNER
+       owner:          THIS_MODULE,
++#endif
+       llseek:         no_llseek,
+       read:           isdn_read,
+       write:          isdn_write,
+@@ -1801,6 +1950,15 @@
+               if (USG_NONE(dev->usage[i]) &&
+                   (dev->drvmap[i] != -1)) {
+                       int d = dev->drvmap[i];
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++                      if(jiffies < dev->dwabc_chan_external_inuse[i]) {
++
++                              if((dev->dwabc_chan_external_inuse[i] - jiffies) > (HZ * 120))
++                                      dev->dwabc_chan_external_inuse[i] = 0;
++                              else 
++                                      continue;
++                      }
++#endif
+                       if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
+                       ((pre_dev != d) || (pre_chan != dev->chanmap[i])))
+                               continue;
+@@ -1819,7 +1977,11 @@
+                                               restore_flags(flags);
+                                               return i;
+                                       } else {
++#ifdef CONFIG_ISDN_WITH_ABC
++                                              if ((pre_dev == d) && ((pre_chan == dev->chanmap[i]) || pre_chan > 1000)) {
++#else
+                                               if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
++#endif
+                                                       dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
+                                                       dev->usage[i] |= usage;
+                                                       isdn_info_update();
+@@ -2006,7 +2168,7 @@
+       if ((adding) && (d->rcverr))
+               kfree(d->rcverr);
+-      if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
++      if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+               printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
+               return -1;
+       }
+@@ -2014,7 +2176,7 @@
+       if ((adding) && (d->rcvcount))
+               kfree(d->rcvcount);
+-      if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_KERNEL))) {
++      if (!(d->rcvcount = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) {
+               printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
+               if (!adding) kfree(d->rcverr);
+               return -1;
+@@ -2026,7 +2188,8 @@
+                       skb_queue_purge(&d->rpqueue[j]);
+               kfree(d->rpqueue);
+       }
+-      if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
++      if (!(d->rpqueue =
++            (struct sk_buff_head *) kmalloc(sizeof(struct sk_buff_head) * m, GFP_KERNEL))) {
+               printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
+               if (!adding) {
+                       kfree(d->rcvcount);
+@@ -2040,7 +2203,8 @@
+       if ((adding) && (d->rcv_waitq))
+               kfree(d->rcv_waitq);
+-      d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
++      d->rcv_waitq = (wait_queue_head_t *)
++              kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL);
+       if (!d->rcv_waitq) {
+               printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
+               if (!adding) {
+@@ -2064,7 +2228,9 @@
+                       if (dev->chanmap[k] < 0) {
+                               dev->chanmap[k] = j;
+                               dev->drvmap[k] = drvidx;
++#ifdef HAVE_DEVFS_FS
+                               isdn_register_devfs(k);
++#endif /* HAVE_DEVFS_FS */
+                               break;
+                       }
+       restore_flags(flags);
+@@ -2128,6 +2294,7 @@
+         i_div->ll_cmd = isdn_command; /* set command function */
+         i_div->drv_to_name = map_drvname; 
+         i_div->name_to_drv = map_namedrv; 
++        i_div->dial_net_name = isdn_net_force_dial; 
+         MOD_INC_USE_COUNT;
+         divert_if = i_div; /* remember interface */
+         return(DIVERT_NO_ERR);
+@@ -2165,7 +2332,7 @@
+               printk(KERN_WARNING "register_isdn: No write routine given.\n");
+               return 0;
+       }
+-      if (!(d = kmalloc(sizeof(driver), GFP_KERNEL))) {
++      if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) {
+               printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
+               return 0;
+       }
+@@ -2225,6 +2392,7 @@
+       return rev;
+ }
++#ifdef HAVE_DEVFS_FS
+ #ifdef CONFIG_DEVFS_FS
+ static devfs_handle_t devfs_handle;
+@@ -2314,6 +2482,7 @@
+ }
+ #endif  /* CONFIG_DEVFS_FS */
++#endif /* HAVE_DEVFS_FS */
+ /*
+  * Allocate and initialize all data, register modem-devices
+@@ -2331,7 +2500,6 @@
+       init_timer(&dev->timer);
+       dev->timer.function = isdn_timer_funct;
+       init_MUTEX(&dev->sem);
+-      init_waitqueue_head(&dev->info_waitq);
+       for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
+               dev->drvmap[i] = -1;
+               dev->chanmap[i] = -1;
+@@ -2345,7 +2513,9 @@
+               vfree(dev);
+               return -EIO;
+       }
++#ifdef HAVE_DEVFS_FS
+       isdn_init_devfs();
++#endif /* HAVE_DEVFS_FS */
+       if ((i = isdn_tty_modem_init()) < 0) {
+               printk(KERN_WARNING "isdn: Could not register tty devices\n");
+               if (i == -3)
+@@ -2353,7 +2523,9 @@
+               if (i <= -2)
+                       tty_unregister_driver(&dev->mdm.tty_modem);
+               vfree(dev);
++#ifdef HAVE_DEVFS_FS
+               isdn_cleanup_devfs();
++#endif /* HAVE_DEVFS_FS */
+               devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
+               return -EIO;
+       }
+@@ -2364,7 +2536,9 @@
+               tty_unregister_driver(&dev->mdm.cua_modem);
+               for (i = 0; i < ISDN_MAX_CHANNELS; i++)
+                       kfree(dev->mdm.info[i].xmit_buf - 4);
++#ifdef HAVE_DEVFS_FS
+               isdn_cleanup_devfs();
++#endif /* HAVE_DEVFS_FS */
+               devfs_unregister_chrdev(ISDN_MAJOR, "isdn");
+               vfree(dev);
+               return -EIO;
+@@ -2390,6 +2564,9 @@
+       printk("\n");
+ #endif
+       isdn_info_update();
++#ifdef CONFIG_ISDN_WITH_ABC
++      isdn_dw_abc_init_func();
++#endif
+       return 0;
+ }
+@@ -2398,7 +2575,7 @@
+  */
+ static void __exit isdn_exit(void)
+ {
+-      unsigned long flags;
++      int flags;
+       int i;
+ #ifdef CONFIG_ISDN_PPP
+@@ -2432,13 +2609,18 @@
+               printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n");
+               restore_flags(flags);
+       } else {
++#ifdef HAVE_DEVFS_FS
+               isdn_cleanup_devfs();
++#endif /* HAVE_DEVFS_FS */
+               del_timer(&dev->timer);
+               restore_flags(flags);
+               /* call vfree with interrupts enabled, else it will hang */
+               vfree(dev);
+               printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
+       }
++#ifdef CONFIG_ISDN_WITH_ABC
++      isdn_dw_abc_release_func();
++#endif
+ }
+ module_init(isdn_init);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_common.h linux-2.4.29/drivers/isdn/isdn_common.h
+--- linux-2.4.29.old/drivers/isdn/isdn_common.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_common.h    2005-03-22 15:06:44.374346856 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_common.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_common.h,v 1.22 2001/09/24 13:22:42 kai Exp $
+  *
+  * header for Linux ISDN subsystem
+  * common used functions and debugging-switches (linklevel).
+@@ -24,6 +24,9 @@
+ #undef  ISDN_DEBUG_NET_DIAL
+ #undef  ISDN_DEBUG_NET_ICALL
++#ifdef CONFIG_ISDN_WITH_ABC
++int isdn_net_force_dial_lp(isdn_net_local *);
++#endif
+ /* Prototypes */
+ extern void isdn_MOD_INC_USE_COUNT(void);
+ extern void isdn_MOD_DEC_USE_COUNT(void);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_concap.c linux-2.4.29/drivers/isdn/isdn_concap.c
+--- linux-2.4.29.old/drivers/isdn/isdn_concap.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_concap.c    2005-03-22 15:06:44.389344576 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_concap.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_concap.c,v 1.9 2001/09/24 13:22:42 kai Exp $
+  * 
+  * Linux ISDN subsystem, protocol encapsulation
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_concap.h linux-2.4.29/drivers/isdn/isdn_concap.h
+--- linux-2.4.29.old/drivers/isdn/isdn_concap.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_concap.h    2005-03-22 15:06:44.405342144 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_concap.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_concap.h,v 1.4 2001/09/24 13:22:42 kai Exp $
+  *
+  * Linux ISDN subsystem, protocol encapsulation
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_dwabc.c linux-2.4.29/drivers/isdn/isdn_dwabc.c
+--- linux-2.4.29.old/drivers/isdn/isdn_dwabc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_dwabc.c     2005-03-22 15:06:44.421339712 +0100
+@@ -0,0 +1,1053 @@
++
++/* $Id: isdn_dwabc.c,v 1.27 2001/12/01 23:18:21 detabc Exp $
++
++ * Linux ISDN subsystem, abc-extension releated funktions.
++ *
++ * Copyright           by abc GmbH
++ *                     written by Detlef Wengorz <detlefw@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)
++ * any later version.
++ *
++ */
++
++#include <linux/config.h>
++#define __NO_VERSION__
++
++#ifdef CONFIG_ISDN_WITH_ABC
++
++static char *dwabcrevison = "$Revision: 1.27 $";
++
++#include <asm/semaphore.h>
++#define CONFIG_ISDN_WITH_ABC_NEED_DWSJIFFIES  1
++#include <linux/list.h>
++#include <linux/isdn.h>
++#include "isdn_common.h"
++#include "isdn_net.h"
++
++#include <linux/skbuff.h>
++
++#include <net/udp.h>
++#include <net/checksum.h>
++#include <linux/isdn_dwabc.h>
++
++
++#if CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS && CONFIG_ISDN_PPP
++#include <linux/isdn_ppp.h>
++extern struct isdn_ppp_compressor *isdn_ippp_comp_head;
++#define ipc_head isdn_ippp_comp_head
++#ifndef CI_BSD_COMPRESS
++#define CI_BSD_COMPRESS 21
++#endif
++#endif
++
++#define NBYTEORDER_30BYTES      0x1e00 
++#define DWABC_TMRES (HZ / 10)
++
++#define VERBLEVEL (dev->net_verbose > 2)
++
++static struct timer_list dw_abc_timer;
++
++
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++static ISDN_DWSPINLOCK lcr_spin = ISDN_DWSPIN_UNLOCKED;
++#define LCR_LOCK() isdn_dwspin_trylock(&lcr_spin)
++#define LCR_ULOCK() isdn_dwspin_unlock(&lcr_spin)
++
++typedef struct ISDN_DW_ABC_LCR {
++
++      struct list_head dll;
++      char lcr_printbuf[64 + ISDN_MSNLEN + ISDN_MSNLEN];
++      char *lcr_poin;
++      char *lcr_epoin;
++
++} ISDN_DW_ABC_LCR;
++
++static LIST_HEAD(lcr_dll);
++static atomic_t lcr_open_count                =       ATOMIC_INIT(0);
++static volatile  ulong lcr_call_counter       = 0;
++
++
++static int myjiftime(char *p,u_long nj)
++{
++      sprintf(p,"%02ld:%02ld.%02ld",
++              ((nj / 100) / 60) % 100, (nj / 100) % 60,nj % 100);
++
++      return(8);
++}
++
++
++static void dw_lcr_clear_all(void)
++{
++      struct list_head *lh;
++
++      if(!LCR_LOCK()) {
++
++              while((lh = lcr_dll.next) != &lcr_dll) {
++
++                      ISDN_DW_ABC_LCR *p = list_entry(lh,ISDN_DW_ABC_LCR,dll);
++                      list_del(&p->dll);
++                      kfree(p);
++              }
++
++              LCR_ULOCK();
++      }
++}
++
++void isdn_dw_abc_lcr_open(void) 
++{ atomic_inc(&lcr_open_count); }
++
++void isdn_dw_abc_lcr_close(void) 
++{ 
++      if(atomic_dec_and_test(&lcr_open_count))
++              dw_lcr_clear_all();
++}
++
++int isdn_dw_abc_lcr_lock(void) 
++{ return(LCR_LOCK()); }
++
++void isdn_dw_abc_lcr_ulock(void) 
++{ LCR_ULOCK(); }
++
++
++size_t isdn_dw_abc_lcr_readstat(char *buf,size_t count) 
++{
++      size_t  retw = 0;
++
++      while(buf != NULL && count > 0) {
++
++              struct list_head *lh = NULL;
++              ISDN_DW_ABC_LCR *p = NULL;
++              char *dp = NULL;
++              size_t  n;
++
++              if((n = LCR_LOCK())) {
++
++                      if(!retw)
++                              retw = n;
++
++                      break;
++              }
++
++
++              while((lh = lcr_dll.next) != &lcr_dll) {
++
++                      p = list_entry(lh,ISDN_DW_ABC_LCR,dll);
++
++                      if(p->lcr_poin >= p->lcr_epoin) {
++
++                              list_del(&p->dll);
++                              kfree(p);
++                              p = NULL;
++
++                      } else break;
++              }
++
++              if(p == NULL) {
++                              
++                      LCR_ULOCK();
++                      break;
++              }
++
++              n = p->lcr_epoin - p->lcr_poin;
++
++              if(n > count)
++                      n = count;
++
++              dp = p->lcr_poin;
++              p->lcr_poin += n;
++              retw += n;
++              LCR_ULOCK();
++              copy_to_user(buf,dp,n);
++              buf += n;
++      }
++
++      return(retw);
++}
++
++
++static void isdn_dw_abc_lcr_clear_helper(isdn_net_local *lp)
++{
++      if(lp != NULL) {
++
++              void *a,*b;
++
++              a = lp->dw_abc_lcr_cmd;  
++              b = lp->dw_abc_lcr_io;
++              lp->dw_abc_lcr_io = NULL;
++              lp->dw_abc_lcr_cmd = NULL;
++              lp->dw_abc_lcr_callid = 
++              lp->dw_abc_lcr_start_request =
++              lp->dw_abc_lcr_end_request = 0;
++              
++              if(a) kfree(a);
++              if(b) kfree(b);
++      }
++}
++
++void isdn_dw_abc_lcr_clear(isdn_net_local *lp)
++{
++      if(!LCR_LOCK()) {
++              isdn_dw_abc_lcr_clear_helper(lp);
++              LCR_ULOCK();
++      }
++}
++
++
++u_long isdn_dw_abc_lcr_call_number( isdn_net_local *lp,isdn_ctrl *call_cmd)
++{
++      u_long mid = 0;
++
++      if(LCR_LOCK())
++              return(0);
++
++      isdn_dw_abc_lcr_clear_helper(lp);
++
++      if( atomic_read(&lcr_open_count) > 0 && 
++              lp != NULL                                              && 
++              call_cmd != NULL) {
++
++              ISDN_DW_ABC_LCR  *lc = NULL;
++              int ab = 0;
++
++              if((lp->dw_abc_lcr_cmd = 
++                      ( isdn_ctrl *)kmalloc(sizeof(isdn_ctrl),GFP_ATOMIC)) == NULL) {
++
++no_mem_out:;
++                      isdn_dw_abc_lcr_clear_helper(lp);
++                      LCR_ULOCK();
++                      printk(KERN_DEBUG "%s %d : LCR no memory\n",__FILE__,__LINE__);
++                      return(0);
++              }
++
++              memcpy(lp->dw_abc_lcr_cmd,call_cmd,sizeof(*call_cmd));
++              while(!(lp->dw_abc_lcr_callid = mid = lcr_call_counter++));
++              
++              lp->dw_abc_lcr_end_request = lp->dw_abc_lcr_start_request = jiffies;
++              lp->dw_abc_lcr_end_request += HZ * 3;
++
++              if((lc = (ISDN_DW_ABC_LCR  *)kmalloc(sizeof(*lc),GFP_KERNEL)) == NULL)
++                      goto no_mem_out;
++
++              lc->lcr_poin = lc->lcr_epoin = lc->lcr_printbuf;
++              lc->lcr_epoin += myjiftime(lc->lcr_epoin,jiffies);
++
++              sprintf(lc->lcr_epoin," DW_ABC_LCR\t%lu\t%.*s\t%.*s\n",
++                      mid,
++                      (int)ISDN_MSNLEN,
++                      call_cmd->parm.setup.eazmsn,
++                      (int)ISDN_MSNLEN,
++                      call_cmd->parm.setup.phone);
++
++              lc->lcr_epoin += strlen(lc->lcr_epoin);
++              ab = lc->lcr_epoin - lc->lcr_poin;
++
++              list_add_tail(&lc->dll,&lcr_dll);
++              LCR_ULOCK();
++
++              if(ab > 0) {
++
++                      if(dev->drv[0] != NULL ) {
++
++                              dev->drv[0]->stavail += ab;
++                              wake_up_interruptible(&dev->drv[0]->st_waitq);
++                      }
++              }
++
++      } else LCR_ULOCK();
++
++      return(mid);
++}
++
++
++int isdn_dw_abc_lcr_ioctl(u_long arg)
++{
++      struct ISDN_DWABC_LCR_IOCTL     i;
++      int need = sizeof(struct ISDN_DWABC_LCR_IOCTL); 
++      isdn_net_dev *p; 
++
++      memset(&i,0,sizeof(struct ISDN_DWABC_LCR_IOCTL));
++      copy_from_user(&i,(char *)arg,sizeof(int));
++
++      if(i.lcr_ioctl_sizeof < need)
++              need = i.lcr_ioctl_sizeof;
++
++      if(need > 0) 
++              copy_from_user(&i,(char *)arg,need);
++
++       if(LCR_LOCK())
++              return(-EAGAIN);
++
++       p = dev->netdev; 
++
++       for(;p ; p = p->next) {
++
++              isdn_net_local *lp = p->local;
++
++              if(     lp->dw_abc_lcr_callid != i.lcr_ioctl_callid)
++                      continue;
++
++              if(lp->dw_abc_lcr_cmd == NULL) 
++                      continue;
++
++              if(lp->dw_abc_lcr_io == NULL)
++                      lp->dw_abc_lcr_io = (struct ISDN_DWABC_LCR_IOCTL *)
++                              kmalloc(sizeof(struct ISDN_DWABC_LCR_IOCTL),GFP_ATOMIC);
++
++              if(lp->dw_abc_lcr_io == NULL) {
++
++                      printk(KERN_DEBUG "%s %d : no memory\n",__FILE__,__LINE__);
++                      continue;
++              }
++
++              memcpy(lp->dw_abc_lcr_io,&i,sizeof(struct ISDN_DWABC_LCR_IOCTL));
++
++              if(i.lcr_ioctl_flags & DWABC_LCR_FLG_NEWNUMBER) {
++
++                      char *xx = i.lcr_ioctl_nr;
++                      char *exx = xx + sizeof(i.lcr_ioctl_nr);
++                      char *d = lp->dw_abc_lcr_cmd->parm.setup.phone;
++                      char *ed = d + sizeof(lp->dw_abc_lcr_cmd->parm.setup.phone) - 1;
++
++                      while(d < ed && xx < exx && *xx) *(d++) = *(xx++);
++                      while(d < ed) *(d++) = 0;
++                      *d = 0;
++              }
++       }
++
++       LCR_ULOCK();
++       return(0);
++}
++
++#endif
++
++
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++int dw_abc_udp_test(struct sk_buff *skb,struct net_device *ndev)
++{
++      if(ndev != NULL && skb != NULL && skb->protocol == htons(ETH_P_IP)) {
++
++              struct iphdr *iph = (struct iphdr *)skb->data;
++              isdn_net_local *lp = (isdn_net_local *) ndev->priv;
++              int rklen = skb->len;
++
++              if (skb->nh.raw > skb->data && skb->nh.raw < skb->tail) {
++
++                      rklen -= (char *)skb->nh.raw - (char *)skb->data;
++                      iph = (struct iphdr *)skb->nh.raw;
++              }
++
++              if(rklen >= 20 && iph->version == 4 && 
++                      !(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_UDP_CHECK)) {
++
++                      if(     iph->tot_len == NBYTEORDER_30BYTES      && 
++                              iph->protocol == IPPROTO_UDP) {
++
++                              struct udphdr *udp = 
++                                      (struct udphdr *)((char *)iph + (iph->ihl << 2));
++
++                              ushort usrc = ntohs(udp->source);
++
++                              if(     udp->dest == htons(25001) && 
++                                      usrc >= 20000 && usrc < 25000) {
++
++                                      char *p = (char *)(udp + 1);
++
++                                      if(p[0] == p[1]) {
++
++                                              char mc = 0;
++
++                                              switch(*p) {
++                                              case 0x30:
++
++                                                      mc = *p;
++
++                                                      if((lp->flags & ISDN_NET_CONNECTED) && (!lp->dialstate))
++                                                              mc++;
++
++                                                      break;
++
++                                              case 0x32:
++
++                                                      mc = *p;
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++                                                      if((lp->flags & ISDN_NET_CONNECTED) && (!lp->dialstate)) {
++
++                                                              mc++;
++                                                              break;
++                                                      }
++
++                                                      if(!isdn_net_force_dial_lp(lp)) mc++;
++#endif
++                                                      break;
++
++                                              case 0x11:
++                                                      mc = *p + 1;
++                                                      isdn_dw_abc_reset_interface(lp,1);
++                                                      break;
++
++                                              case 0x28:      mc = *p + 1;    break;
++                                              case 0x2a:
++                                              case 0x2c:
++
++                                                      mc = *p;
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++                                                      if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_UDP_HANGUP)) {
++
++                                                              if(lp->isdn_device >= 0) {
++
++                                                                      isdn_net_hangup(ndev);
++                                                                      mc = *p + 1;
++                                                              }
++                                                      }
++#endif
++                                                      break;
++                                              }
++
++                                              if(mc) {
++
++                                                      struct sk_buff *nskb;
++                                                      int need = 2+sizeof(struct iphdr)+sizeof(struct udphdr);
++                                                      int hneed = need + ndev->hard_header_len;
++
++                                                      if((nskb = (struct sk_buff *)dev_alloc_skb(hneed)) != NULL) {
++
++                                                              ushort n = sizeof(struct udphdr) + 2;
++                                                              struct iphdr *niph;
++                                                              struct udphdr *nup;
++                                                              skb_reserve(nskb,ndev->hard_header_len);
++
++                                                              if((niph = (struct iphdr *)skb_put(nskb,need))==NULL){
++
++                                                                      printk(KERN_DEBUG "%s: skb_put failt (%d bytes)\n", lp->name,hneed);
++                                                                      dev_kfree_skb(nskb);
++                                                                      return(0);
++                                                              }
++
++                                                              nup = (struct udphdr *)(niph + 1);
++                                                              ((char *)(nup + 1))[0] = mc;
++                                                              ((char *)(nup + 1))[1] = mc;
++                                                              nup->source=udp->dest;
++                                                              nup->dest=udp->source;
++                                                              nup->len=htons(n);
++                                                              nup->check=0; /* dont need checksum */
++                                                              memset((void *)niph,0,sizeof(*niph));
++                                                              niph->version=4;
++                                                              niph->ihl=5;
++                                                              niph->tot_len=NBYTEORDER_30BYTES;
++                                                              niph->ttl = 32;
++                                                              niph->protocol = IPPROTO_UDP;
++                                                              niph->saddr=iph->daddr;
++                                                              niph->daddr=iph->saddr;
++                                                              niph->id=iph->id;
++                                                              niph->check=ip_fast_csum((unsigned char *)niph,niph->ihl);
++                                                              nskb->dev = ndev;
++                                                              nskb->pkt_type = PACKET_HOST;
++                                                              nskb->protocol = htons(ETH_P_IP);
++                                                              nskb->mac.raw = nskb->data;
++                                                              netif_rx(nskb);
++                                                      }
++
++                                                      return(1);
++                                              }
++                                      }
++                              }
++                      }
++              }
++      }
++
++      return(0);
++}
++#endif
++
++
++void isdn_dw_clear_if(ulong pm,isdn_net_local *lp)
++{
++      if(lp != NULL) {
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++              isdn_dw_abc_lcr_clear(lp);
++#endif
++      }
++}
++
++
++
++static void dw_abc_timer_func(u_long dont_need_yet)
++{
++      register u_long t;
++
++      if(!((t = ++isdn_dwabc_jiffies.msec_100) & 1))
++              if(isdn_dwabc_jiffies.msec_200++ & 1)
++                      isdn_dwabc_jiffies.msec_400++;
++      
++      if(!(t % 5)) 
++              if(isdn_dwabc_jiffies.msec_500++ & 1)
++                      isdn_dwabc_jiffies.msec_1000++;
++
++      dw_abc_timer.expires = jiffies + DWABC_TMRES;
++      add_timer(&dw_abc_timer);
++}
++
++
++void isdn_dw_abc_init_func(void)
++{
++
++      init_timer(&dw_abc_timer);
++      dw_abc_timer.function = dw_abc_timer_func;
++
++
++      printk( KERN_INFO
++              "abc-extension %s Kernel 0x%06X\n"
++              "written by\nDetlef Wengorz <detlefw@isdn4linux.de>\n"
++              "Installed options:\n"
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++              "CONFIG_ISDN_WITH_ABC_CALLB\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++              "CONFIG_ISDN_WITH_ABC_UDP_CHECK\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++              "CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++              "CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++              "CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++              "CONFIG_ISDN_WITH_ABC_LCR_SUPPORT\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++              "CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++              "CONFIG_ISDN_WITH_ABC_CH_EXTINUSE\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++              "CONFIG_ISDN_WITH_ABC_CONN_ERROR\n"
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++              "CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS\n"
++#endif
++              "loaded\n",
++              dwabcrevison,LINUX_VERSION_CODE);
++              dwsjiffies = 0;
++              dw_abc_timer.expires = jiffies + DWABC_TMRES;
++              add_timer(&dw_abc_timer);
++}
++
++void isdn_dw_abc_release_func(void)
++{
++      del_timer(&dw_abc_timer);
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++      dw_lcr_clear_all();
++#endif
++      printk( KERN_INFO
++              "abc-extension %s  Kernel 0x%06X\n"
++              "written by\n"
++              "Detlef Wengorz <detlefw@isdn4linux.de>\n"
++              "unloaded\n",
++              dwabcrevison,LINUX_VERSION_CODE);
++}
++
++
++void isdn_dwabc_test_phone(isdn_net_local *lp) 
++{
++      if(lp != NULL) {
++
++              isdn_net_phone *h = lp->phone[0];
++              ulong oflags = lp->dw_abc_flags;
++              int secure = 0;
++
++              lp->dw_abc_flags = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++              *lp->dw_out_msn = 0;
++#endif
++
++              for(;h != NULL && secure < 1000;secure++,h = h->next) {
++
++                      char *p         =       h->num;
++                      char *ep        =       p + ISDN_MSNLEN;
++
++                      for(;p < ep && *p && (*p <= ' ' || *p == '"' || *p == '\'');p++);
++
++                      if(p >= ep)
++                              continue;
++
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                      if(*p == '>') {
++
++                              if(++p < ep && *p != '<' && *p != '>') {
++
++                                      char *d = lp->dw_out_msn;
++
++                                      for(;*p && (p < ep) && (*p == ' ' || *p == '\t');p++);
++                                      for(ep--;*p && (p < ep);) *(d++) = *(p++);
++                                      *d = 0;
++                                      continue;
++                              }
++                      }
++#endif
++
++                      if(*p == '~') {
++
++                              /* abc switch's */
++
++                              for(p++;p < ep && *p;p++) switch(*p) {
++                              case 'u':       lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_UDP_CHECK;                      break;
++                              case 'h':       lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_UDP_HANGUP;                     break;
++                              case 'd':       lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_UDP_DIAL;                       break;
++                              case 'c':       lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE;            break;
++                              case 'e':   lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_CONN_ERROR;                 break;
++                              case 'l':   lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_LCR;                                break;
++
++                              case 'x':
++                              case 'X':       lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER;           break;
++
++                              case 'B':       lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_BSD_COMPRESS;                      break;
++                              case 'L':       lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_LEASED_LINE;                       break;
++
++                              case '"':
++                              case ' ':
++                              case '\t':
++                              case '\'':      break;
++
++                              default:        
++                                      printk(KERN_DEBUG"isdn_net: %s abc-switch <~%c> unknown\n",lp->name,*p);
++                                      break;
++                              }
++                      }
++              }
++
++              if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_LEASED_LINE) {
++
++                      lp->dw_abc_flags |= 
++                                      ISDN_DW_ABC_FLAG_NO_UDP_CHECK           |
++                                      ISDN_DW_ABC_FLAG_NO_UDP_HANGUP          |
++                                      ISDN_DW_ABC_FLAG_NO_UDP_DIAL            |
++                                      ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE         |
++                                      ISDN_DW_ABC_FLAG_NO_CONN_ERROR          |
++                                      ISDN_DW_ABC_FLAG_NO_LCR;
++              }
++
++              if(dev->net_verbose  && (lp->dw_abc_flags != oflags || dev->net_verbose > 4))
++                      printk(KERN_DEBUG "isdn_net %s abc-flags 0x%lx\n",lp->name,lp->dw_abc_flags);
++
++      }
++}
++
++
++int isdn_dw_abc_reset_interface(isdn_net_local *lp,int with_message)
++{
++      int r = -EINVAL;
++
++      if(lp != NULL) {
++
++              r = 0;
++
++              lp->dw_abc_bchan_last_connect = 0;
++              lp->dw_abc_dialstart = 0;
++              lp->dw_abc_inuse_secure = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++              lp->dw_abc_bchan_errcnt = 0;
++#endif
++
++              if(with_message && dev->net_verbose > 0)
++                      printk(KERN_INFO
++                              "%s: NOTE: reset (clear) abc-interface-secure-counter\n",
++                              lp->name);
++      }
++
++      return(r);
++}
++
++      
++#if CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS && CONFIG_ISDN_PPP
++
++#define DWBSD_PKT_FIRST_LEN 16
++#define DWBSD_PKT_SWITCH      165
++#define DWBSD_PKT_BSD         189
++
++#define DWBSD_VERSION                 0x2
++
++void dwabc_bsd_first_gen(isdn_net_local *lp)
++{
++      if(lp != NULL && lp->p_encap == ISDN_NET_ENCAP_RAWIP && 
++              (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS)) { 
++              
++              struct sk_buff *skb = NULL;
++              char *p = NULL;
++              char *ep = NULL;
++
++              if((skb =(struct sk_buff *)dev_alloc_skb(128)) == NULL) {
++
++                      printk(KERN_INFO "%s: dwabc: alloc-skb failed for 128 bytes\n",lp->name);
++                      return;
++              }
++
++              skb_reserve(skb,64);
++              p = skb_put(skb,DWBSD_PKT_FIRST_LEN);
++              ep = p + DWBSD_PKT_FIRST_LEN;
++
++              *(p++) = DWBSD_PKT_SWITCH;
++              *(p++) = DWBSD_VERSION;
++              for(;p < ep;p++)        *(p++) = 0;
++
++              isdn_net_write_super(lp, skb);
++
++              if(dev->net_verbose > 2)
++                      printk(KERN_INFO "%s: dwabc: sending comm-header version 0x%x\n",lp->name,DWBSD_VERSION);
++      }
++}
++
++
++void dwabc_bsd_free(isdn_net_local *lp)
++{
++      if(lp != NULL) {
++
++              if(lp->dw_abc_bsd_stat_rx || lp->dw_abc_bsd_stat_tx) {
++
++                      struct isdn_ppp_compressor *c = NULL;
++
++                      if(!(c = (struct isdn_ppp_compressor *)lp->dw_abc_bsd_compressor)) {
++
++                              printk(KERN_WARNING
++                              "%s: PANIC: freeing bsd compressmemory without compressor\n",
++                                      lp->name);
++
++                      } else {
++
++                              if(lp->dw_abc_bsd_stat_rx) (*c->free)(lp->dw_abc_bsd_stat_rx);
++                              if(lp->dw_abc_bsd_stat_tx) (*c->free)(lp->dw_abc_bsd_stat_tx);
++
++                              if(dev->net_verbose > 2)
++                                      printk(KERN_INFO
++                                              "%s: free bsd compress-memory\n",
++                                              lp->name);
++                      }
++              }
++
++              lp->dw_abc_bsd_compressor = NULL;
++              lp->dw_abc_bsd_stat_rx = NULL;
++              lp->dw_abc_bsd_stat_tx = NULL;
++              lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_BSDAKTIV;
++
++              if(dev->net_verbose > 0) {
++
++                      if(lp->dw_abc_bsd_rcv != lp->dw_abc_bsd_bsd_rcv) {
++
++                              printk(KERN_INFO "%s: Receive %lu<-%lu kb\n",lp->name,
++                                      lp->dw_abc_bsd_rcv >> 10 , lp->dw_abc_bsd_bsd_rcv >> 10);
++                      }
++
++
++                      if(lp->dw_abc_bsd_snd != lp->dw_abc_bsd_bsd_snd) {
++
++                              printk(KERN_INFO "%s: Send  %lu->%lu kb\n",lp->name,
++                                      lp->dw_abc_bsd_snd >> 10 , lp->dw_abc_bsd_bsd_snd >> 10);
++                      }
++              }
++
++              lp->dw_abc_bsd_rcv              =
++              lp->dw_abc_bsd_bsd_rcv  =
++              lp->dw_abc_bsd_snd              =
++              lp->dw_abc_bsd_bsd_snd  = 0;
++      }
++}
++
++
++int dwabc_bsd_init(isdn_net_local *lp)
++{
++      int r = 1;
++
++      if(lp != NULL) {
++
++              dwabc_bsd_free(lp);
++
++              if(lp->p_encap == ISDN_NET_ENCAP_RAWIP) {
++
++                      void *rx = NULL;
++                      void *tx = NULL;
++                      struct isdn_ppp_comp_data *cp = NULL;
++                      struct isdn_ppp_compressor *c = NULL;
++
++                      if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS) do {
++
++                              for(c = ipc_head ;
++                                      c != NULL && c->num != CI_BSD_COMPRESS; c = c->next);
++
++                              if(c == NULL) {
++
++                                      printk(KERN_INFO
++                                              "%s: Module isdn_bsdcompress not loaded\n",
++                                              lp->name);
++
++                                      break;
++                              }
++
++                              cp = (struct isdn_ppp_comp_data *)
++                                      kmalloc(sizeof(struct isdn_ppp_comp_data),GFP_ATOMIC);
++
++                              if(cp == NULL) {
++
++                                      printk(KERN_INFO
++                                              "%s: allocation of isdn_ppp_comp_data failed\n",
++                                              lp->name);
++
++                                      break;
++                              }
++
++                              memset(cp,0,sizeof(*cp));
++                              cp->num = CI_BSD_COMPRESS;
++                              cp->optlen = 1;
++                                      
++                              /*
++                              ** set BSD_VERSION 1 and 12 bits compressmode
++                              */
++                              *cp->options = (1 << 5) | 12;
++
++                              if((rx = (*c->alloc)(cp)) == NULL) {
++
++                                      printk(KERN_INFO
++                                              "%s: allocation of bsd rx-memory failed\n",
++                                              lp->name);
++
++                                      break;
++                              }
++                                      
++                              if(!(*c->init)(rx,cp,0,1)) {
++
++                                      printk(KERN_INFO 
++                                              "%s: init of bsd rx-stream  failed\n",lp->name);
++
++                                      break;
++                              }
++
++                              cp->flags = IPPP_COMP_FLAG_XMIT;
++                                              
++                              if((tx = (*c->alloc)(cp)) == NULL) {
++
++                                      printk(KERN_INFO
++                                              "%s: allocation of bsd tx-memory failed\n",
++                                              lp->name);
++
++                                      break;
++                              }
++
++                              if(!(*c->init)(tx,cp,0,1)) {
++
++                                      printk(KERN_INFO
++                                              "%s: init of bsd tx-stream  failed\n",
++                                              lp->name);
++
++                                      break;
++                              }
++
++                              lp->dw_abc_bsd_compressor = (void *)c;
++                              lp->dw_abc_bsd_stat_rx = rx;
++                              lp->dw_abc_bsd_stat_tx = tx;
++                              rx = tx = NULL;
++                              r = 0;
++
++                              if(dev->net_verbose > 2)
++                                      printk(KERN_INFO
++                                              "%s: bsd compress-memory and init ok\n",
++                                              lp->name);
++
++                      } while(0);
++
++                      if(cp != NULL)
++                              kfree(cp);
++
++                      if(c != NULL) {
++
++                              if(tx != NULL) (*c->free)(tx);
++                              if(rx != NULL) (*c->free)(rx);
++                      }
++
++              } else if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS) {
++              
++                      printk(KERN_INFO
++                              "%s: bsd-compress only with encapsulation rawip allowed\n",
++                              lp->name);
++              }
++      }
++
++      return(r);
++}
++
++struct sk_buff *dwabc_bsd_compress(   isdn_net_local *lp,
++                                                                      struct sk_buff *skb,
++                                                                      struct net_device *ndev)
++{
++      if(lp != NULL && lp->p_encap == ISDN_NET_ENCAP_RAWIP    && 
++              (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS)      &&
++              (lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_BSDAKTIV)) {
++
++              if(lp->dw_abc_bsd_stat_tx != NULL && lp->dw_abc_bsd_compressor) {
++
++                      struct isdn_ppp_compressor *cp = 
++                              (struct isdn_ppp_compressor *)lp->dw_abc_bsd_compressor;
++
++                      struct sk_buff *nskb = (struct sk_buff *)
++                              dev_alloc_skb(skb->len * 2 + ndev->hard_header_len);
++
++                      int l = 0;
++
++                      if(nskb == NULL) {
++
++                              (void)(*cp->reset)(lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++                              printk(KERN_INFO "%s: dwabc-compress no memory\n",lp->name);
++
++                      } else {
++
++                              skb_reserve(nskb,ndev->hard_header_len);
++                              *(unsigned char *)skb_put(nskb,1) = DWBSD_PKT_BSD;
++                              l = (*cp->compress)(lp->dw_abc_bsd_stat_tx,skb,nskb,0x21);
++
++                              if(l < 1 || l > skb->len) {
++
++                                      (void)(*cp->reset)(lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++                                      dev_kfree_skb(nskb);
++
++                              } else {
++
++                                      u_short sqnr;
++
++                                      dev_kfree_skb(skb);
++                                      skb = nskb;
++                                      sqnr = ((*(u_char *)skb->data) << 8) + 
++                                                      ((u_char)skb->data[1]);
++
++                                      if(sqnr > 65500)
++                                              (void)(*cp->reset)
++                                                      (lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++                              }
++                      }
++              }
++      }
++
++      return(skb);
++}
++
++struct sk_buff *dwabc_bsd_rx_pkt(     isdn_net_local *lp,
++                                                                      struct sk_buff *skb,
++                                                                      struct net_device *ndev)
++{
++      struct sk_buff *r = skb;
++
++      if(lp != NULL && lp->p_encap == ISDN_NET_ENCAP_RAWIP && 
++              (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS)) { 
++
++              unsigned char *p = (unsigned char *)skb->data;
++              struct isdn_ppp_compressor *cp = 
++                      (struct isdn_ppp_compressor *)lp->dw_abc_bsd_compressor;
++
++              if(*p == DWBSD_PKT_SWITCH) {
++
++                      if(skb->len == DWBSD_PKT_FIRST_LEN) {
++
++                              if((lp->dw_abc_remote_version = p[1]) < 0x2) {
++
++                                      printk(KERN_INFO 
++                                              "%s: I can't really talk with remote version 0x%x\n"
++                                              "Please upgrade remote or disable rawip-compression\n",
++                                              lp->name,
++                                              p[1]);
++                              }
++
++                              lp->dw_abc_if_flags |= ISDN_DW_ABC_IFFLAG_BSDAKTIV;
++                              dev_kfree_skb(skb);
++
++                              if(cp && lp->dw_abc_bsd_stat_tx) 
++                                      (void)(*cp->reset)(lp->dw_abc_bsd_stat_tx,0,0,NULL,0,NULL);
++
++                              if(dev->net_verbose > 2)
++                                      printk(KERN_INFO 
++                                              "%s: receive comm-header rem-version 0x%02x\n",
++                                              lp->name,
++                                              lp->dw_abc_remote_version);
++
++                              return(NULL);
++                      }
++
++              } else if(*p == DWBSD_PKT_BSD && lp->dw_abc_bsd_stat_rx != NULL && cp) {
++
++                      struct sk_buff *nskb = NULL;
++
++                      if(test_and_set_bit(ISDN_DW_ABC_BITLOCK_RECEIVE,
++                              &lp->dw_abc_bitlocks)) {
++
++                              printk(KERN_INFO "%s: bsd-decomp called recursivly\n",lp->name);
++                              dev_kfree_skb(skb);
++                              dwabc_bsd_first_gen(lp);
++                              return(NULL);
++                      } 
++                      
++                      nskb = (struct sk_buff *)
++                              dev_alloc_skb(2048 + ndev->hard_header_len);
++
++                      if(nskb != NULL) {
++
++                              int l = 0;
++                              u_short sqnr;
++
++                              skb_reserve(nskb,ndev->hard_header_len);
++                              skb_pull(skb, 1);
++                              sqnr = ((*(u_char *)skb->data) << 8) | ((u_char)skb->data[1]);
++
++                              if(!sqnr && cp && lp->dw_abc_bsd_stat_rx)
++                                      (void)(*cp->reset)(lp->dw_abc_bsd_stat_rx,0,0,NULL,0,NULL);
++
++                              if((l = (*cp->decompress)
++                                      (lp->dw_abc_bsd_stat_rx,skb,nskb,NULL)) < 1 || l>8000) {
++
++                                      printk(KERN_INFO "%s: abc-decomp failed\n",lp->name);
++                                      dev_kfree_skb(nskb);
++                                      dev_kfree_skb(skb);
++                                      nskb = NULL;
++                                      dwabc_bsd_first_gen(lp);
++
++                              } else {
++
++                                      if (nskb->data[0] & 0x1)
++                                              skb_pull(nskb, 1);   /* protocol ID is only 8 bit */
++                                      else
++                                              skb_pull(nskb, 2);
++
++                                      nskb->dev = skb->dev;
++                                      nskb->pkt_type = skb->pkt_type;
++                                      nskb->mac.raw = nskb->data;
++                                      dev_kfree_skb(skb);
++                              }
++
++                      } else {
++
++                              printk(KERN_INFO "%s: PANIC abc-decomp no memory\n",lp->name);
++                              dev_kfree_skb(skb);
++                              dwabc_bsd_first_gen(lp);
++                      }
++
++                      clear_bit(ISDN_DW_ABC_BITLOCK_RECEIVE,&lp->dw_abc_bitlocks);
++                      r = nskb;
++              }
++      }
++
++      return(r);
++}
++
++#else
++int dwabc_bsd_init(isdn_net_local *lp) { return(1); }
++void dwabc_bsd_free(isdn_net_local *lp) { return; }
++void dwabc_bsd_first_gen(isdn_net_local *lp) { return ; }
++
++struct sk_buff *dwabc_bsd_compress(isdn_net_local *lp,struct sk_buff *skb,struct net_device *ndev)
++{ return(skb); }
++
++struct sk_buff *dwabc_bsd_rx_pkt(isdn_net_local *lp,struct sk_buff *skb,struct net_device *ndev)
++{ return(skb); }
++#endif
++#endif
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_net.c linux-2.4.29/drivers/isdn/isdn_net.c
+--- linux-2.4.29.old/drivers/isdn/isdn_net.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_net.c       2005-03-22 15:06:44.447335760 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_net.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_net.c,v 1.153 2002/08/17 18:35:23 detabc Exp $
+  *
+  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
+  *
+@@ -9,14 +9,6 @@
+  * This software may be used and distributed according to the terms
+  * of the GNU General Public License, incorporated herein by reference.
+  *
+- * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02 
+- *                                       guy@traverse.com.au
+- * Outgoing calls - looks for a 'V' in first char of dialed number
+- * Incoming calls - checks first character of eaz as follows:
+- *   Numeric - accept DATA only - original functionality
+- *   'V'     - accept VOICE (DOV) only
+- *   'B'     - accept BOTH DATA and DOV types
+- *
+  * Jan 2001: fix CISCO HDLC      Bjoern A. Zeeb <i4l@zabbadoz.net>
+  *           for info on the protocol, see 
+  *           http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
+@@ -38,6 +30,10 @@
+ #include "isdn_concap.h"
+ #endif
++#ifdef CONFIG_ISDN_WITH_ABC
++#include <linux/isdn_dwabc.h>
++#define isdn_net_log_skb(skb,lp) isdn_net_log_skb_dwabc(skb,lp,NULL)
++#endif
+ /*
+  * Outline of new tbusy handling: 
+@@ -79,7 +75,11 @@
+               dev = lp->master;
+       else
+               dev = &n->dev;
++#ifdef COMPAT_NO_SOFTNET
++      return dev->start;
++#else
+       return netif_running(dev);
++#endif
+ }
+ /*
+@@ -143,6 +143,10 @@
+       atomic_inc(&lp->frame_cnt);
+       if (isdn_net_device_busy(lp))
+               isdn_net_device_stop_queue(lp);
++#if 0
++      printk(KERN_DEBUG "%s: inc_frame_cnt now %d\n", lp->name, 
++            atomic_read(&lp->frame_cnt));
++#endif
+ }
+ static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
+@@ -157,11 +161,19 @@
+                       isdn_net_device_wake_queue(lp);
+               }
+        }                                                                      
++#if 0
++      printk(KERN_DEBUG "%s: dec_frame_cnt now %d\n", lp->name, 
++             atomic_read(&lp->frame_cnt));
++#endif
+ }
+ static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
+ {
+       atomic_set(&lp->frame_cnt, 0);
++#if 0
++      printk(KERN_DEBUG "%s: zero_frame_cnt now %d\n", lp->name,
++             atomic_read(&lp->frame_cnt));
++#endif
+ }
+ /* For 2.2.x we leave the transmitter busy timeout at 2 secs, just 
+@@ -173,23 +185,101 @@
+  * which might rely on the tx timeout. If so, we'll find out this way...
+  */
++#ifdef COMPAT_NO_SOFTNET
++#define ISDN_NET_TX_TIMEOUT (2*HZ)
++#else
+ #define ISDN_NET_TX_TIMEOUT (20*HZ) 
++#endif
+ /* Prototypes */
++#ifndef CONFIG_ISDN_WITH_ABC
+ int isdn_net_force_dial_lp(isdn_net_local *);
++#endif
+ static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
+ static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
+ static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
+-char *isdn_net_revision = "$Revision: 1.1.4.1 $";
++char *isdn_net_revision = "$Revision: 1.153 $";
+  /*
+   * Code for raw-networking over ISDN
+   */
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++static int isdn_dwabc_encap_with_conerr(isdn_net_local *lp)
++{
++      if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CONN_ERROR)
++              return(0);
++
++      return( 
++              lp->p_encap == ISDN_NET_ENCAP_SYNCPPP                   ||
++              lp->p_encap == ISDN_NET_ENCAP_RAWIP                     ||
++              lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK                ||
++              lp->p_encap == ISDN_NET_ENCAP_UIHDLC                    );
++}
++
++static int isdn_dwabc_conerr_ippktok(struct sk_buff *skb)
++{
++              struct iphdr *iph = (struct iphdr *)skb->data;
++              return(iph->version == 6 || (skb->len >= 20 && iph->version == 4));
++}
++
++#endif
++
++static int isdn_dwabc_is_interface_disabled(isdn_net_local *lp)
++{
++      if(lp == NULL)
++              return(0);
++
++      lp->dw_abc_inuse_secure = 0;
++      lp->dw_abc_dialstart = 0;
++
++      /*
++      ** check for jiffies overflow
++      */
++      if(lp->dw_abc_bchan_last_connect > jiffies) {
++
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++              lp->dw_abc_bchan_errcnt = 0;
++#endif
++              lp->dw_abc_bchan_last_connect = 0;
++      }
++
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++      if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CONN_ERROR) && isdn_dwabc_encap_with_conerr(lp)) {
++
++              if(lp->dw_abc_bchan_errcnt > 3 && !(lp->dw_abc_bchan_errcnt & 3)) {
++                      ulong nj = jiffies;
++                      ulong delay =   lp->dw_abc_bchan_errcnt * 
++                                                      lp->dw_abc_bchan_errcnt * 
++                                                      lp->dw_abc_bchan_errcnt;
++
++                      if(delay > 86400) delay = 86400;
++                      delay = (lp->dw_abc_bchan_last_connect + delay * HZ);
++
++                      if(delay > nj) {
++
++                              printk(KERN_INFO 
++                                      "%s: interface auto-disabled (bchannel connect-error %lu seconds left)\n",
++                                      lp->name,(delay - nj) / HZ);
++
++                              return(1);
++                      }
++              }
++      }
++#endif
++      return(0);
++}
++#endif
++
++#ifdef CONFIG_ISDN_WITH_ABC
++void
++#else
+ static void
++#endif
+ isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
+ {
+       if(skb) {
+@@ -297,6 +387,12 @@
+       save_flags(flags);
+       cli();
++#ifdef CONFIG_ISDN_WITH_ABC
++      isdn_dw_clear_if(0l,lp);
++      lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_NODCHAN;
++      lp->dw_abc_inuse_secure = 0;
++      dwabc_bsd_free(lp);
++#endif
+       skb_queue_purge(&lp->super_tx_queue);
+       if (!lp->master) {      /* reset only master device */
+@@ -351,6 +447,26 @@
+               if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
+                       anymore = 1;
+                       l->huptimer++;
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++                      if(     isdn_dwabc_encap_with_conerr(l) && l->dw_abc_bchan_errcnt > 0) {
++
++                              int n = 180;
++
++                              if(l->dw_abc_bchan_errcnt > 3) n = 120;
++                              if(l->dw_abc_bchan_errcnt > 6) n = 90;
++                              if(l->dw_abc_bchan_errcnt > 9) n = 60;
++
++                              if(l->huptimer > n) {
++
++                                      printk(KERN_INFO "%s: bchan conf-error auto-secure-hangup\n",l->name);
++                                      isdn_net_hangup(&p->dev);
++                                      p = (isdn_net_dev *) p->next;
++                                      continue;
++                              }
++                      }
++#endif
++#endif
+                       /*
+                        * if there is some dialmode where timeout-hangup
+                        * should _not_ be done, check for that here
+@@ -465,8 +581,32 @@
+                                       printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
+                                              lp->charge);
+                                       isdn_net_unbind_channel(lp);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++                                      if(lp->dw_abc_bchan_errcnt) {
++
++                                              printk(KERN_INFO
++                                                      "%s: Note: bchannel-error-counter is %hd\n",
++                                                      lp->name,
++                                                      lp->dw_abc_bchan_errcnt);
++                                      }
++#endif
+                                       return 1;
+                               }
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++                              if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE)) {
++                                      if((lp->dialstate == 4 || lp->dialstate == 12) && 
++                                              lp->dw_abc_dialstart && (idx < ISDN_MAX_CHANNELS)) {
++                                      
++                                              if((jiffies - lp->dw_abc_dialstart) < (HZ >>2)) {
++
++                                                      lp->dw_abc_if_flags |= ISDN_DW_ABC_IFFLAG_NODCHAN;
++                                                      lp->dialstate = 1;
++                                                      dev->dwabc_chan_external_inuse[idx] = jiffies + HZ * 30;
++                                                      printk(KERN_INFO "%s: Channel %d look like external in use\n",lp->name,idx);
++                                              }
++                                      }
++                              }
++#endif
+                               break;
+ #ifdef CONFIG_ISDN_X25
+                       case ISDN_STAT_BHUP:
+@@ -507,6 +647,19 @@
+                                                       }
+                                               }
+                                               printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
++#ifdef CONFIG_ISDN_WITH_ABC
++                                              if(!dwabc_bsd_init(lp)) dwabc_bsd_first_gen(lp);
++                                              lp->dw_abc_bchan_last_connect = jiffies;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++                                              if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CONN_ERROR)) {
++
++                                                      lp->dw_abc_bchan_errcnt += isdn_dwabc_encap_with_conerr(lp);
++                                                      
++                                                      if(lp->dw_abc_bchan_errcnt > 32000)
++                                                              lp->dw_abc_bchan_errcnt = 32000;
++                                              }
++#endif
++#endif
+                                               /* If first Chargeinfo comes before B-Channel connect,
+                                                * we correct the timestamp here.
+                                                */
+@@ -578,7 +731,6 @@
+       int i;
+       unsigned long flags;
+       isdn_ctrl cmd;
+-        u_char *phone_number;
+       while (p) {
+               isdn_net_local *lp = p->local;
+@@ -597,6 +749,47 @@
+                                */
+                               save_flags(flags);
+                               cli();
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++                              if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE) &&
++                                      (lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_NODCHAN)) {
++
++                                      int chi = 0;
++                                      short lsecure = 0;
++
++                                      lsecure = lp->dw_abc_inuse_secure;
++                                      isdn_net_unbind_channel(lp);
++                                      lp->dw_abc_inuse_secure = lsecure + 1;
++
++                                      /* Grab a free ISDN-Channel */
++                                      if ((lsecure >= ISDN_MAX_CHANNELS ) || (chi = 
++                                              isdn_get_free_channel(
++                                                      ISDN_USAGE_NET,
++                                                      lp->l2_proto,
++                                                      lp->l3_proto,
++                                                      lp->pre_device,
++                                                      lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                                                      (*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn)
++#else
++                                                      lp->msn)
++#endif
++                                                      ) < 0) {
++
++                                              restore_flags(flags);
++                                              isdn_net_unreachable(&p->dev, NULL,
++                                                      "DWABC: redial-external-inuse NO FREE CHANNEL\n");
++                                              isdn_net_hangup(&p->dev);
++                                              break;
++                                      }
++
++                                      isdn_net_bind_channel(lp, chi);
++                                      lp->dialstate = 1;
++                                      lp->dialstarted = 0;
++                                      lp->dialwait_timer = 0;
++                              }
++
++                              lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_NODCHAN;
++#endif
+                               lp->dial = lp->phone[1];
+                               restore_flags(flags);
+                               if (!lp->dial) {
+@@ -621,18 +814,69 @@
+                               cmd.arg = lp->isdn_channel;
+                               cmd.command = ISDN_CMD_CLREAZ;
+                               isdn_command(&cmd);
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                              sprintf(cmd.parm.num, "%s",
++                                      isdn_map_eaz2msn((*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn, cmd.driver));
++#else
+                               sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
++#endif
+                               cmd.command = ISDN_CMD_SETEAZ;
+                               isdn_command(&cmd);
+                               lp->dialretry = 0;
+                               anymore = 1;
+                               lp->dialstate++;
++#ifdef CONFIG_ISDN_WITH_ABC
++                              lp->onhtime = lp->dw_abc_old_onhtime;
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++                              isdn_dw_abc_lcr_clear(lp);
++#endif
++#endif
+                               /* Fall through */
+                       case 3:
+                               /* Setup interface, dial current phone-number, switch to next number.
+                                * If list of phone-numbers is exhausted, increment
+                                * retry-counter.
+                                */
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++                              if(!isdn_dw_abc_lcr_lock()) {
++
++                                      if(     lp->dw_abc_lcr_cmd != NULL              &&
++                                              lp->dw_abc_lcr_start_request    != 
++                                              lp->dw_abc_lcr_end_request) {
++
++                                              if(     lp->dw_abc_lcr_io == NULL                               && 
++                                                      lp->dw_abc_lcr_start_request <= jiffies &&
++                                                      lp->dw_abc_lcr_end_request > jiffies) {
++                                                      
++                                                      isdn_dw_abc_lcr_ulock();
++                                                      anymore = 1;
++                                                      break;
++                                              }
++
++                                              if(lp->dw_abc_lcr_io != NULL) {
++
++                                                      if(lp->dw_abc_lcr_io->lcr_ioctl_flags & 
++                                                              DWABC_LCR_FLG_DISABLE) {
++
++                                                              isdn_dw_abc_lcr_ulock();
++                                                              isdn_net_hangup(&p->dev);
++                                                              break;
++                                                      }
++
++                                                      if(lp->dw_abc_lcr_io->lcr_ioctl_flags & 
++                                                              DWABC_LCR_FLG_NEWHUPTIME) {
++                                                              lp->onhtime = lp->dw_abc_lcr_io->lcr_ioctl_onhtime;
++                                                      }
++                                              }
++
++                                              memcpy(&cmd,lp->dw_abc_lcr_cmd,sizeof(cmd));
++                                              isdn_dw_abc_lcr_ulock();
++                                              goto dw_abc_lcr_next_click;
++                                      }
++
++                                      isdn_dw_abc_lcr_ulock();
++                              }
++#endif
+                               if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
+                                       char *s;
+                                       if (dev->global_flags & ISDN_GLOBAL_STOPPED)
+@@ -677,20 +921,7 @@
+                                                       break;
+                                               }
+-                                      cmd.driver = lp->isdn_device;
+-                                      cmd.command = ISDN_CMD_DIAL;
+-                                      cmd.parm.setup.si2 = 0;
+-
+-                                        /* check for DOV */
+-                                        phone_number = lp->dial->num;
+-                                        if ((*phone_number == 'v') ||
+-                                          (*phone_number == 'V')) { /* DOV call */
+-                                                cmd.parm.setup.si1 = 1;
+-                                        } else { /* DATA call */
+-                                                cmd.parm.setup.si1 = 7;
+-                                      }
+-
+-                                      strcpy(cmd.parm.setup.phone, phone_number);
++                                      sprintf(cmd.parm.setup.phone, "%s", lp->dial->num);
+                                       /*
+                                        * Switch to next number or back to start if at end of list.
+                                        */
+@@ -710,17 +941,70 @@
+                                               }
+                                       }
+                                       restore_flags(flags);
++                                      cmd.driver = lp->isdn_device;
++                                      cmd.command = ISDN_CMD_DIAL;
++                                      cmd.parm.setup.si1 = 7;
++                                      cmd.parm.setup.si2 = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ 
++                                      sprintf(cmd.parm.setup.eazmsn, "%s",
++                                              isdn_map_eaz2msn((*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn, cmd.driver));
++#else
+                                       sprintf(cmd.parm.setup.eazmsn, "%s",
+                                               isdn_map_eaz2msn(lp->msn, cmd.driver));
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++                                      /*
++                                      ** if callback-out we dont need 
++                                      ** low-cost-routing LCR
++                                      */
++                                  if(!(lp->flags & ISDN_NET_CBOUT) &&
++                                              !(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_LCR)) {
++
++                                              isdn_dw_abc_lcr_call_number(lp,&cmd);
++                                              
++                                              if(lp->dw_abc_lcr_start_request != lp->dw_abc_lcr_end_request) {
++
++                                                      if(dev->net_verbose > 2) {
++
++                                                              printk(KERN_INFO 
++                                      "%s: Waiting for LCR-response from isdnlog %s -> %s...\n",
++                                                                      lp->name,
++                                                                      cmd.parm.setup.eazmsn,
++                                                                      cmd.parm.setup.phone);
++                                                      }
++                                                              
++                                                      anymore = 1;
++                                                      break;
++                                              }
++                                      } 
++
++dw_abc_lcr_next_click:;
++                                      isdn_dw_abc_lcr_clear(lp);
++#endif
+                                       i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
+                                       if (i >= 0) {
+                                               strcpy(dev->num[i], cmd.parm.setup.phone);
+                                               dev->usage[i] |= ISDN_USAGE_OUTGOING;
+                                               isdn_info_update();
+                                       }
+-                                      printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name,
+-                                             lp->dialretry, cmd.parm.setup.phone,
+-                                             (cmd.parm.setup.si1 == 1) ? "DOV" : "");
++#ifdef CONFIG_ISDN_WITH_ABC
++                                      printk(KERN_INFO "%s: dialing %d %s -> %s...\n", lp->name,
++                                             lp->dialretry, 
++                                                 cmd.parm.setup.eazmsn,
++                                                 cmd.parm.setup.phone);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++                                      if(lp->dw_abc_bchan_errcnt) {
++
++                                              printk(KERN_INFO
++                                                      "%s: Note: bchannel-error-counter is %hd\n",
++                                                      lp->name,
++                                                      lp->dw_abc_bchan_errcnt);
++                                      }
++#endif
++#else
++                                      printk(KERN_INFO "%s: dialing %d %s...\n", lp->name,
++                                             lp->dialretry, cmd.parm.setup.phone);
++#endif
+                                       lp->dtimer = 0;
+ #ifdef ISDN_DEBUG_NET_DIAL
+                                       printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
+@@ -741,6 +1025,10 @@
+                               lp->dialstate =
+                                   (lp->cbdelay &&
+                                    (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
++#ifdef CONFIG_ISDN_WITH_ABC
++                              lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_NODCHAN;
++                              lp->dw_abc_dialstart = jiffies;
++#endif
+                               break;
+                       case 4:
+                               /* Wait for D-Channel-connect.
+@@ -890,6 +1178,15 @@
+               isdn_command(&cmd);
+               printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
+               isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++              if(lp->dw_abc_bchan_errcnt) {
++
++                      printk(KERN_INFO
++                              "%s: Note: bchannel-error-counter is %hd\n",
++                              lp->name,
++                              lp->dw_abc_bchan_errcnt);
++              }
++#endif
+       }
+       isdn_net_unbind_channel(lp);
+ }
+@@ -899,8 +1196,13 @@
+       unsigned short dest;
+ } ip_ports;
++#ifdef CONFIG_ISDN_WITH_ABC
++void
++isdn_net_log_skb_dwabc(struct sk_buff * skb, isdn_net_local * lp,char *reason)
++#else
+ static void
+ isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
++#endif
+ {
+       u_char *p = skb->nh.raw; /* hopefully, this was set correctly */
+       unsigned short proto = ntohs(skb->protocol);
+@@ -972,7 +1274,13 @@
+                                       break;
+                       }
+                       printk(KERN_INFO
++#ifdef CONFIG_ISDN_WITH_ABC
++                              "%s %s: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
++                              (reason == NULL) ? "OPEN" : reason,
++                              (lp != NULL) ? lp->name : "",
++#else
+                               "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
++#endif
+                              p[12], p[13], p[14], p[15],
+                              p[16], p[17], p[18], p[19],
+@@ -980,7 +1288,13 @@
+                       break;
+               case ETH_P_ARP:
+                       printk(KERN_INFO
++#ifdef CONFIG_ISDN_WITH_ABC
++                              "%s %s: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
++                              (reason == NULL) ? "OPEN" : reason,
++                              (lp != NULL) ? lp->name : "",
++#else
+                               "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
++#endif
+                              p[14], p[15], p[16], p[17],
+                              p[24], p[25], p[26], p[27]);
+                       break;
+@@ -1004,11 +1318,22 @@
+       }
+       spin_lock_bh(&lp->xmit_lock);
++
+       if (!isdn_net_lp_busy(lp)) {
++#ifdef CONFIG_ISDN_WITH_ABC
++              if(!skb_queue_empty(&lp->super_tx_queue)) {
++                      /*
++                      ** don't reverse the frame flow
++                      ** compression need frames in order and maybe other's too
++                      */
++                      skb_queue_tail(&lp->super_tx_queue, skb); 
++                      skb = skb_dequeue(&lp->super_tx_queue);
++              }
++#endif
+               isdn_net_writebuf_skb(lp, skb);
+-      } else {
+-              skb_queue_tail(&lp->super_tx_queue, skb);
+-      }
++
++      } else skb_queue_tail(&lp->super_tx_queue, skb);
++
+       spin_unlock_bh(&lp->xmit_lock);
+ }
+@@ -1056,7 +1381,6 @@
+               printk(KERN_WARNING "%s: HL driver queue full\n", lp->name);
+               goto error;
+       }
+-      
+       lp->transcount += len;
+       isdn_net_inc_frame_cnt(lp);
+       return;
+@@ -1064,9 +1388,19 @@
+  error:
+       dev_kfree_skb(skb);
+       lp->stats.tx_errors++;
+-
+ }
++#if 0
++int isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp,struct sk_buff *skb)
++{
++      if (isdn_net_lp_busy(lp)) {
++              printk(KERN_WARNING "isdn_net_send_skb: HL channel busy\n");
++              return 1;
++      }
++      isdn_net_writebuf_skb(lp, skb);
++      return 0;
++}
++#endif
+ /*
+  *  Helper function for isdn_net_start_xmit.
+@@ -1109,7 +1443,54 @@
+       /* Reset hangup-timeout */
+       lp->huptimer = 0; // FIXME?
++#ifdef CONFIG_ISDN_WITH_ABC
++
++      if(test_and_set_bit(ISDN_DW_ABC_BITLOCK_SEND,&lp->dw_abc_bitlocks)) {
++
++              if(dev->net_verbose > 2)
++                      printk(KERN_INFO "%s: isdn_net_xmit  called recursivly\n",lp->name);
++
++              spin_unlock_bh(&lp->xmit_lock);
++              return(1);
++      }
++
++      if(skb != NULL) {
++
++              int l = skb->len;
++              int nl = l;
++
++              if(     lp->p_encap == ISDN_NET_ENCAP_RAWIP &&
++                              (lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_BSDAKTIV)) {
++
++                      if((skb = dwabc_bsd_compress(lp,skb,ndev)) != NULL) {
++
++                              int r = 0;
++                              nl = skb->len;
++                              skb_queue_tail(&lp->super_tx_queue,skb);
++
++                              if(l != nl && (r = isdn_dc2minor(lp->isdn_device,lp->isdn_channel)) >= 0) {
++
++                                      dev->obytes[r] += l - nl;
++                                      lp->stats.tx_bytes += l - nl;
++                              }
++                      }
++
++              } else skb_queue_tail(&lp->super_tx_queue,skb);
++
++              if(lp->p_encap == ISDN_NET_ENCAP_RAWIP) {
++
++                      lp->dw_abc_bsd_snd += l;
++                      lp->dw_abc_bsd_bsd_snd += nl;
++              }
++      }
++      clear_bit(ISDN_DW_ABC_BITLOCK_SEND,&lp->dw_abc_bitlocks);
++
++      while(!isdn_net_lp_busy(lp) && (skb = skb_dequeue(&lp->super_tx_queue)))
++              isdn_net_writebuf_skb(lp, skb);
++
++#else
+       isdn_net_writebuf_skb(lp, skb);
++#endif
+       spin_unlock_bh(&lp->xmit_lock);
+       /* the following stuff is here for backwards compatibility.
+@@ -1143,6 +1524,69 @@
+       return retv;
++#if 0
++      if (lp->cps > lp->triggercps) {
++              /* Device overloaded */
++
++              /*
++               * Packet-delivery via round-robin over master
++               * and all connected slaves.
++               */
++              if (lp->master) {
++                      /* Slaves always deliver themselves */
++                      spin_lock_bh(&lp->xmit_lock);
++                      if (!isdn_net_lp_busy(lp)) {
++                              isdn_net_writebuf_skb(lp, skb);
++                              ret = 0;
++                      } else {
++                              isdn_net_device_stop_queue(lp);
++                              ret = 1;
++                      }
++                      ret = isdn_net_send_skb(ndev, lp, skb);
++                      spin_unlock_bh(&lp->xmit_lock);
++              } else {
++                      isdn_net_local *slp = (isdn_net_local *) (lp->srobin->priv);
++                      /* Master delivers via srobin and maintains srobin */
++                      if (lp->srobin == ndev) {
++                              spin_lock_bh(&lp->xmit_lock);
++                              ret = isdn_net_send_skb(ndev, lp, skb);
++                              spin_unlock_bh(&lp->xmit_lock);
++                      } else {
++                              ret = isdn_net_start_xmit(skb, lp->srobin);
++                      }
++                      lp->srobin = (slp->slave) ? slp->slave : ndev;
++                      slp = (isdn_net_local *) (lp->srobin->priv);
++                      if (!((slp->flags & ISDN_NET_CONNECTED) && (slp->dialstate == 0)))
++                              lp->srobin = ndev;
++              }
++              /* Slave-startup using delay-variable */
++              if (lp->slave) {
++                      if (!lp->sqfull) {
++                              /* First time overload: set timestamp only */
++                              lp->sqfull = 1;
++                              lp->sqfull_stamp = jiffies;
++                      } else {
++                              /* subsequent overload: if slavedelay exceeded, start dialing */
++                              if ((jiffies - lp->sqfull_stamp) > lp->slavedelay)
++                                      isdn_net_force_dial_lp((isdn_net_local *) lp->slave->priv);
++                      }
++              }
++      } else {
++              /* Not overloaded, deliver locally */
++              spin_lock_bh(&lp->xmit_lock);
++              if (!isdn_net_lp_busy(lp)) {
++                      isdn_net_writebuf_skb(lp, skb);
++                      ret = 0;
++              } else {
++                      isdn_net_device_stop_queue(lp);
++                      ret = 1;
++              }
++              spin_unlock_bh(&lp->xmit_lock);
++              if (lp->sqfull && ((jiffies - lp->sqfull_stamp) > (lp->slavedelay + (10 * HZ))))
++                      lp->sqfull = 0;
++      }
++      return ret;
++#endif
+ }
+ static void
+@@ -1161,6 +1605,7 @@
+ }
++#ifndef COMPAT_NO_SOFTNET
+ void isdn_net_tx_timeout(struct net_device * ndev)
+ {
+       isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+@@ -1188,19 +1633,206 @@
+       ndev->trans_start = jiffies;
+       netif_wake_queue(ndev);
+ }
++#endif
+ /*
+  * Try sending a packet.
+  * If this interface isn't connected to a ISDN-Channel, find a free channel,
+  * and start dialing.
+  */
++#ifdef CONFIG_ISDN_WITH_ABC
++static int dwabc_isdn_net_start_xmit(struct sk_buff *,struct net_device *);
++
++static int isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++{
++      if(skb == NULL || ndev == NULL)
++              return(dwabc_isdn_net_start_xmit(skb,ndev));
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++      if(!(((isdn_net_local *)ndev->priv)->dw_abc_flags & 
++              ISDN_DW_ABC_FLAG_NO_UDP_CHECK)) {
++
++              if(dw_abc_udp_test(skb,ndev)) {
++                      dev_kfree_skb(skb);
++                      return(0);
++              }
++      }
++#endif
++      return(dwabc_isdn_net_start_xmit(skb,ndev));
++}
++
++
++#ifdef CONFIG_ISDN_WITH_ABC
++int isdn_auto_dial_helper(    isdn_net_local *lp,
++                                                      struct sk_buff *skb,
++                                                      int dm_manual_allowed)
++/**********************************************************************
++      return's:
++              -1              dial not allowed or impossible
++              0               interface is connected
++              1               dial is started
++***********************************************************************/
++{
++      int retw = -1;
++      int chi;
++      ulong flags;
++      char *errmsg = NULL;
++
++#ifdef ISDN_DEBUG_NET_DUMP
++      {
++              char *buf = skb->data;
++              isdn_dumppkt("S:", buf, skb->len, 40);
++      }
++#endif
++      if (lp->flags & ISDN_NET_CONNECTED) 
++              return(0);
++
++      save_flags(flags);
++      cli();
++
++      do {
++
++              /* Log packet, which triggered dialing */
++              if (dev->net_verbose)
++                      isdn_net_log_skb(skb, lp);
++              /* only do autodial if allowed by config */
++              if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
++                      errmsg = "dial rejected: interface not in dialmode `auto'";
++
++                      if(dm_manual_allowed &&
++                              !(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_MANUAL)) {
++
++                              errmsg = 
++                              "dial rejected: interface not in dialmode `auto or manual'";
++                      }
++                      break;
++              }
++
++              if (!lp->phone[1]) {
++
++                      errmsg = "No phone number";
++                      break;
++              }
++
++              if(lp->dialwait_timer <= 0) {
++
++                      if(     lp->dialstarted > 0 &&
++                              lp->dialtimeout > 0 && 
++                              jiffies < (lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
++
++                              lp->dialwait_timer = 
++                                      lp->dialstarted + lp->dialtimeout + lp->dialwait;
++                      }
++              }
++
++              if(lp->dialwait_timer > 0) {
++
++                      if(jiffies < lp->dialwait_timer) {
++
++                              errmsg = "dial rejected: retry-time not reached";
++                              break;
++
++                      } else lp->dialwait_timer = 0;
++              }
++#ifdef CONFIG_ISDN_WITH_ABC
++              if(isdn_dwabc_is_interface_disabled(lp))
++                      break;
++#endif
++              /* Grab a free ISDN-Channel */
++              if (((chi =
++                              isdn_get_free_channel(
++                                      ISDN_USAGE_NET,
++                                      lp->l2_proto,
++                                      lp->l3_proto,
++                                      lp->pre_device,
++                                      lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                                      (*lp->dw_out_msn) ? lp->dw_out_msn :
++#endif
++                                      lp->msn)
++                      ) < 0) &&
++                      ((chi =
++                              isdn_get_free_channel(
++                                      ISDN_USAGE_NET,
++                                      lp->l2_proto,
++                                      lp->l3_proto,
++                                      lp->pre_device,
++                                      lp->pre_channel^1,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                                      (*lp->dw_out_msn) ? lp->dw_out_msn :
++#endif
++                                      lp->msn)
++                      ) < 0)) {
++
++                              errmsg = "No channel";
++                              break;
++              }
++
++              lp->dialstate = 1;
++              /* Connect interface with channel */
++              isdn_net_bind_channel(lp, chi);
++#ifdef CONFIG_ISDN_PPP
++              if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
++                      /* no 'first_skb' handling for syncPPP */
++                      if (isdn_ppp_bind(lp) < 0) {
++                              isdn_net_unbind_channel(lp);
++                              break;
++                      }
++
++                      isdn_net_dial();        /* Initiate dialing */
++                      netif_stop_queue(&lp->netdev->dev);
++                      retw = 1;
++                      break;
++                      /* let upper layer requeue skb packet */
++              }
++#endif
++              /* Initiate dialing */
++              isdn_net_dial();
++              isdn_net_device_stop_queue(lp);
++              retw = 1;
++
++      } while(0);
++
++      if(retw < 0 && errmsg != NULL)
++              isdn_net_unreachable(&lp->netdev->dev, skb, errmsg);
++
++      restore_flags(flags);
++      return(retw);
++}
++#endif
++
++
++
++static int
++dwabc_isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++#else
+ static int
+ isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
++#endif
+ {
+       isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+ #ifdef CONFIG_ISDN_X25
+       struct concap_proto * cprot = lp -> netdev -> cprot;
+ #endif
++#ifdef COMPAT_NO_SOFTNET 
++      /* 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 < ISDN_NET_TX_TIMEOUT)
++                      return 1;
++              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;
++              netif_wake_queue(ndev);
++      }
++#endif
+ #ifdef CONFIG_ISDN_X25
+ /* At this point hard_start_xmit() passes control to the encapsulation
+    protocol (if present).
+@@ -1220,6 +1852,40 @@
+       } else
+ #endif
+       /* auto-dialing xmit function */
++#ifdef CONFIG_ISDN_WITH_ABC
++      {
++              int r;
++
++              isdn_net_adjust_hdr(skb, ndev);
++
++              if(!(r = isdn_auto_dial_helper(lp,skb,0))) {
++
++                      /* 
++                      ** Device is connected to an ISDN channel
++                      */ 
++                      ndev->trans_start = jiffies;
++
++                      if (!lp->dialstate) {
++
++                              /* 
++                              ** ISDN connection is established, try sending 
++                              */
++                              r = isdn_net_xmit(ndev, skb);
++
++                      } else r = 1;
++
++                      if(r)
++                              netif_stop_queue(ndev);
++
++              } else if(r < 0) {
++
++                      dev_kfree_skb(skb);
++                      r = 0;
++              }
++
++              return(r);
++      }
++#else
+       {
+ #ifdef ISDN_DEBUG_NET_DUMP
+               u_char *buf;
+@@ -1256,6 +1922,14 @@
+                                       } else
+                                               lp->dialwait_timer = 0;
+                               }
++#ifdef CONFIG_ISDN_WITH_ABC
++                              if(isdn_dwabc_is_interface_disabled(lp)) {
++
++                                      dev_kfree_skb(skb);
++                                      restore_flags(flags);
++                                      return(0);
++                              }
++#endif
+                               /* Grab a free ISDN-Channel */
+                               if (((chi =
+                                    isdn_get_free_channel(
+@@ -1264,6 +1938,9 @@
+                                                       lp->l3_proto,
+                                                       lp->pre_device,
+                                                       lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                                                      (*lp->dw_out_msn) ? lp->dw_out_msn : 
++#endif
+                                                       lp->msn)
+                                                       ) < 0) &&
+                                       ((chi =
+@@ -1273,6 +1950,9 @@
+                                                       lp->l3_proto,
+                                                       lp->pre_device,
+                                                       lp->pre_channel^1,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                                                      (*lp->dw_out_msn) ? lp->dw_out_msn :
++#endif
+                                                       lp->msn)
+                                                       ) < 0)) {
+                                       restore_flags(flags);
+@@ -1296,16 +1976,6 @@
+                                               restore_flags(flags);
+                                               return 0;       /* STN (skb to nirvana) ;) */
+                                       }
+-#ifdef CONFIG_IPPP_FILTER
+-                                      if (isdn_ppp_autodial_filter(skb, lp)) {
+-                                              isdn_ppp_free(lp);
+-                                              isdn_net_unbind_channel(lp);
+-                                              restore_flags(flags);
+-                                              isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
+-                                              dev_kfree_skb(skb);
+-                                              return 0;
+-                                      }
+-#endif
+                                       restore_flags(flags);
+                                       isdn_net_dial();        /* Initiate dialing */
+                                       netif_stop_queue(ndev);
+@@ -1337,6 +2007,7 @@
+               }
+       }
+       return 1;
++#endif
+ }
+ /*
+@@ -1356,6 +2027,9 @@
+       if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
+ #endif
+       netif_stop_queue(dev);
++#ifdef COMPAT_NO_SOFTNET
++      dev->start = 0;
++#endif
+       if ((p = (((isdn_net_local *) dev->priv)->slave))) {
+               /* If this interface has slaves, stop them also */
+               while (p) {
+@@ -1776,6 +2450,10 @@
+       }
+       switch (type) {
++      case CISCO_TYPE_INET:
++              skb->protocol = htons(ETH_P_IP);
++              netif_rx(skb);
++              break;
+       case CISCO_TYPE_SLARP:
+               isdn_net_ciscohdlck_slarp_in(lp, skb);
+               goto out_free;
+@@ -1785,11 +2463,11 @@
+                               "\"no cdp enable\" on cisco.\n", lp->name);
+               goto out_free;
+       default:
+-              /* no special cisco protocol */
+-              skb->protocol = htons(type);
+-              netif_rx(skb);
+-              return;
++              printk(KERN_WARNING "%s: Unknown Cisco type 0x%04x\n",
++                     lp->name, type);
++              goto out_free;
+       }
++      return;
+  out_free:
+       kfree_skb(skb);
+@@ -1803,9 +2481,19 @@
+ {
+       isdn_net_local *lp = (isdn_net_local *) ndev->priv;
+       isdn_net_local *olp = lp;       /* original 'lp' */
++#ifdef CONFIG_ISDN_PPP
++      int proto = PPP_PROTOCOL(skb->data);
++#endif
+ #ifdef CONFIG_ISDN_X25
+       struct concap_proto *cprot = lp -> netdev -> cprot;
+ #endif
++#ifdef CONFIG_ISDN_WITH_ABC
++      struct net_device *ondev = ndev;
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++      ulong lp_huptimer  = 0;
++      ulong olp_huptimer = 0;
++#endif
++#endif
+       lp->transcount += skb->len;
+       lp->stats.rx_packets++;
+@@ -1819,6 +2507,10 @@
+               lp->stats.rx_packets++;
+               lp->stats.rx_bytes += skb->len;
+       }
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++      lp_huptimer  = lp->huptimer;
++      olp_huptimer = olp->huptimer;
++#endif
+       skb->dev = ndev;
+       skb->pkt_type = PACKET_HOST;
+       skb->mac.raw = skb->data;
+@@ -1840,9 +2532,40 @@
+                       /* Fall through */
+               case ISDN_NET_ENCAP_RAWIP:
+                       /* RAW-IP without MAC-Header */
++#ifdef CONFIG_ISDN_WITH_ABC
++                      if(olp->p_encap == ISDN_NET_ENCAP_RAWIP) {
++
++                              ushort l = skb->len;
++                              short r = 0;
++
++                              olp->dw_abc_bsd_bsd_rcv += l;
++
++                              if((skb = dwabc_bsd_rx_pkt(olp,skb,ondev)) == NULL) {
++
++                                      olp->dw_abc_bsd_rcv += l;
++                                      return;
++                              }
++
++                              olp->dw_abc_bsd_rcv += skb->len;
++
++                              if(     l != skb->len && 
++                                      (r=isdn_dc2minor(olp->isdn_device,olp->isdn_channel))>=0) {
++
++                                      dev->ibytes[r] += skb->len - l;
++                                      olp->stats.rx_bytes += skb->len - l;
++
++                                      if(olp != lp)
++                                              lp->stats.rx_bytes += skb->len - l;
++                              }
++                      }
++#endif
+                       olp->huptimer = 0;
+                       lp->huptimer = 0;
+                       skb->protocol = htons(ETH_P_IP);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++                      if(isdn_dwabc_conerr_ippktok(skb))
++                              lp->dw_abc_bchan_errcnt = 0;
++#endif
+                       break;
+               case ISDN_NET_ENCAP_CISCOHDLCK:
+                       isdn_net_ciscohdlck_receive(lp, skb);
+@@ -1862,8 +2585,22 @@
+                       break;
+ #ifdef CONFIG_ISDN_PPP
+               case ISDN_NET_ENCAP_SYNCPPP:
+-                      /* huptimer is done in isdn_ppp_push_higher */
++                      /*
++                       * If encapsulation is syncppp, don't reset
++                       * huptimer on LCP packets.
++                       */
++                      if (proto != PPP_LCP) {
++                              olp->huptimer = 0;
++                              lp->huptimer = 0;
++                      }
+                       isdn_ppp_receive(lp->netdev, olp, skb);
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++                      if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) {
++
++                              lp->huptimer = lp_huptimer + 1;
++                              olp->huptimer = olp_huptimer+ 1;
++                      }
++#endif
+                       return;
+ #endif
+@@ -1873,6 +2610,15 @@
+                       if(cprot) if(cprot -> pops)
+                               if( cprot -> pops -> data_ind){
+                                       cprot -> pops -> data_ind(cprot,skb);
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++                                      lp->dw_abc_bchan_errcnt = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++                                      if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) {
++                                              lp->huptimer = lp_huptimer;
++                                              olp->huptimer = olp_huptimer;
++                                      }
++#endif
++#endif
+                                       return;
+                               };
+ #endif /* CONFIG_ISDN_X25 */
+@@ -1882,6 +2628,15 @@
+                       return;
+       }
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++      if(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER) {
++
++              lp->huptimer = lp_huptimer;
++              olp->huptimer = olp_huptimer;
++      }
++#endif
++#endif
+       netif_rx(skb);
+       return;
+ }
+@@ -2160,8 +2915,10 @@
+       isdn_net_phone *n;
+       ulong flags;
+       char nr[32];
+-      char *my_eaz;
+-
++#ifdef CONFIG_ISDN_WITH_ABC
++      if(dev->net_verbose > 2)
++              printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=0x%04X\n", di, ch, idx,dev->usage[idx]);
++#endif
+       /* Search name in netdev-chain */
+       save_flags(flags);
+       cli();
+@@ -2180,17 +2937,15 @@
+               eaz = setup->eazmsn;
+       if (dev->net_verbose > 1)
+               printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
+-        /* Accept DATA and VOICE calls at this stage
+-        local eaz is checked later for allowed call types */
+-        if ((si1 != 7) && (si1 != 1)) {
+-                restore_flags(flags);
+-                if (dev->net_verbose > 1)
+-                        printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
+-                return 0;
+-        }
+-
+-n = (isdn_net_phone *) 0;
+-p = dev->netdev;
++      /* Accept only calls with Si1 = 7 (Data-Transmission) */
++      if (si1 != 7) {
++              restore_flags(flags);
++              if (dev->net_verbose > 1)
++                      printk(KERN_INFO "isdn_net: Service-Indicator not 7, ignored\n");
++              return 0;
++      }
++      n = (isdn_net_phone *) 0;
++      p = dev->netdev;
+       ematch = wret = swapped = 0;
+ #ifdef ISDN_DEBUG_NET_ICALL
+       printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
+@@ -2210,25 +2965,8 @@
+                               break;
+               }
+               swapped = 0;
+-                /* check acceptable call types for DOV */
+-                my_eaz = isdn_map_eaz2msn(lp->msn, di);
+-                if (si1 == 1) { /* it's a DOV call, check if we allow it */
+-                        if (*my_eaz == 'v' || *my_eaz == 'V' ||
+-                          *my_eaz == 'b' || *my_eaz == 'B')
+-                                my_eaz++; /* skip to allow a match */
+-                        else
+-                                my_eaz = 0; /* force non match */
+-                } else { /* it's a DATA call, check if we allow it */
+-                        if (*my_eaz == 'b' || *my_eaz == 'B')
+-                                my_eaz++; /* skip to allow a match */
+-                }
+-                if (my_eaz)
+-                        matchret = isdn_msncmp(eaz, my_eaz);
+-                else
+-                        matchret = 1;
+-                if (!matchret)
+-                        ematch = 1;
+-
++              if (!(matchret = isdn_msncmp(eaz, isdn_map_eaz2msn(lp->msn, di))))
++                      ematch = 1;
+               /* Remember if more numbers eventually can match */
+               if (matchret > wret)
+                       wret = matchret;
+@@ -2236,17 +2974,122 @@
+               printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
+                      lp->name, lp->msn, lp->flags, lp->dialstate);
+ #endif
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++              if ((!matchret) &&                                        /* EAZ is matching   */
++                  (((!(lp->flags & ISDN_NET_CONNECTED)) &&              /* but not connected */
++                    (USG_NONE(dev->usage[idx]))) ||                     /* and ch. unused or */
++                   (lp->dialstate == 4) || (lp->dialstate == 12) ||           /* if dialing        */
++                        ((lp->flags & ISDN_NET_CBOUT) != 0 &&                         /* init a callback      */
++                        lp->outgoing != 0 )))
++
++              /*
++              ** we dont stop call's anymore (both sides call's syncron)
++              ** it will be problem in any case.
++              ** both sides will make the same.
++              ** i try later to make a switch (check the phon-numbers)
++              ** to detect with side must be stop the call.
++              */
++#else
+               if ((!matchret) &&                                        /* EAZ is matching   */
+                   (((!(lp->flags & ISDN_NET_CONNECTED)) &&              /* but not connected */
+                     (USG_NONE(dev->usage[idx]))) ||                     /* and ch. unused or */
+                    ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing        */
+                      (!(lp->flags & ISDN_NET_CALLBACK)))                /* but no callback   */
+                    )))
++#endif
+                        {
+ #ifdef ISDN_DEBUG_NET_ICALL
+                       printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
+                              lp->pre_device, lp->pre_channel);
+ #endif
++#ifdef CONFIG_ISDN_WITH_ABC
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++                      {
++                              int use_this_call = 0;
++
++                              if(!(lp->flags & ISDN_NET_CBOUT) && ((lp->dialstate == 4) || (lp->dialstate == 12))) {
++
++                                      /*
++                                      ** searching for a diff. in the calling-number and the EAZ
++                                      ** the remote will make the same
++                                      */
++
++                                      char *pnr = nr;
++                                      char *pea = eaz;
++
++                                      for(;*pnr;pnr++);
++                                      for(;*pea;pea++);
++                                      for(pnr--,pea--;pnr >= nr && pea >= eaz && *pea != *pnr;pnr--,pea--);
++
++                                      if(pnr < nr || pea < eaz || *pea > *pnr) {
++
++                                              p = (isdn_net_dev *) p->next;
++                                              continue;
++                                      }
++
++                                      use_this_call = 1;
++                              }
++                              
++                              if( use_this_call || 
++                                      ((lp->flags & ISDN_NET_CBOUT) && (lp->flags & ISDN_NET_CONNECTED))) {
++
++                                      /*
++                                      ** the incoming call was to quick.
++                                      ** the callback-delay-time ist not reached.
++                                      ** in that case we can stop the call
++                                      */
++
++                                      if(lp->isdn_device > -1 && lp->isdn_channel > -1) {
++
++                                              int minor = isdn_dc2minor(lp->isdn_device,lp->isdn_channel);
++
++                                              if(lp->isdn_device != di || lp->isdn_channel != ch) {
++
++                                                      isdn_ctrl cmd;
++
++                                                      memset((void *)&cmd,0,sizeof(cmd));
++                                                      cmd.driver = lp->isdn_device;
++                                                      cmd.command = ISDN_CMD_HANGUP;
++                                                      cmd.arg = lp->isdn_channel;
++                                                      (void) dev->drv[cmd.driver]->interface->command(&cmd);
++                                                      isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
++
++                                                      if(dev->net_verbose > 1) {
++
++                                                              printk(KERN_INFO 
++                              "%s: found outgoing call hangup old call on di %d ch %d\n",
++                                                                      lp->name,lp->isdn_device,lp->isdn_channel);
++                                                      }
++
++                                              } else if (dev->net_verbose > 1) {
++
++                                                      printk(KERN_INFO "%s: found outgoing call on same di %d ch %d\n",
++                                                              lp->name,lp->isdn_device,lp->isdn_channel);
++                                              }
++
++                                              if(minor >= 0) {
++
++                                                      dev->rx_netdev[minor] = NULL;
++                                                      dev->st_netdev[minor] = NULL;
++                                              }
++
++                                              isdn_free_channel(lp->isdn_device,
++                                                      lp->isdn_channel, ISDN_USAGE_NET);
++
++                                      } else if (dev->net_verbose > 1) {
++
++                                              printk(KERN_INFO "%s: found outgoing call reset callstate \n",lp->name);
++                                      }
++
++                                      lp->flags &= ~ISDN_NET_CONNECTED;
++                                      lp->isdn_device = -1;
++                                      lp->isdn_channel = -1;
++                                      lp->dtimer = 0;
++                                      lp->dialstate = 0;
++                              }
++                      }
++#endif
++#endif
+                       if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
+                               if ((lp->pre_channel != ch) ||
+                                   (lp->pre_device != di)) {
+@@ -2375,6 +3218,12 @@
+                                               continue;
+                                       }
+                               } 
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++                              if(isdn_dwabc_is_interface_disabled(lp)) {
++                                      restore_flags(flags);
++                                      return 3;
++                              }
++#endif
+                               if (lp->flags & ISDN_NET_CALLBACK) {
+                                       int chi;
+                                       /*
+@@ -2427,6 +3276,47 @@
+                                       restore_flags(flags);
+                                       return 0;
+                               } else {
++#ifdef CONFIG_ISDN_WITH_ABC_CALLB
++                                      {
++                                      /*
++                                      ** this is a sanity-check.
++                                      ** check for double use (device and channel)
++                                      ** will be very near to a kernel-crash in that case
++                                      */
++                                      isdn_net_dev *sp = dev->netdev;
++                                      int s_shl;
++                                      isdn_net_local *ml;
++
++                                      for(s_shl=0; s_shl < 2048 && sp != NULL; sp = (isdn_net_dev *)sp->next, s_shl++) {
++
++                                              if(sp == p || (ml = sp->local) == NULL)
++                                                      continue;
++
++                                              if(ml->isdn_device != di || ml->isdn_channel != ch)
++                                                      continue;
++
++                                              if(ml->dialstate != 4 && ml->dialstate != 12) {
++
++                                                      /*
++                                                      ** wrong situation
++                                                      */
++                                                      break;
++                                              }
++
++                                              isdn_net_unbind_channel(ml);
++                                      }
++
++                                      if(sp != NULL) {
++
++                                              printk(KERN_DEBUG
++"%s: call from %s -> %s (drv %d chan %d duplicated with %s) \n",
++                                                      lp->name, nr, eaz,di,ch,
++                                                      sp->local->name );
++
++                                              restore_flags(flags);
++                                              return 3;
++                                      }}
++#endif
+                                       printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
+                                              eaz);
+                                       /* if this interface is dialing, it does it probably on a different
+@@ -2516,7 +3406,11 @@
+                                                       lp->l3_proto,
+                                                       lp->pre_device,
+                                                       lp->pre_channel,
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++                                                      (*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn)
++#else
+                                                       lp->msn)
++#endif
+                                                       ) < 0) {
+                               printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
+                               restore_flags(flags);
+@@ -2599,7 +3493,11 @@
+               strcpy(netdev->local->name, "         ");
+       else
+               strcpy(netdev->local->name, name);
++#ifdef COMPAT_NO_SOFTNET
++      netdev->dev.name = netdev->local->name;
++#else
+       strcpy(netdev->dev.name, netdev->local->name);
++#endif
+       netdev->dev.priv = netdev->local;
+       netdev->dev.init = isdn_net_init;
+       netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP;
+@@ -2617,11 +3515,13 @@
+               ((isdn_net_local *) q->priv)->slave = &(netdev->dev);
+       } else {
+               /* Device shall be a master */
++#ifndef COMPAT_NO_SOFTNET
+               /*
+                * Watchdog timer (currently) for master only.
+                */
+               netdev->dev.tx_timeout = isdn_net_tx_timeout;
+               netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
++#endif
+               if (register_netdev(&netdev->dev) != 0) {
+                       printk(KERN_WARNING "isdn_net: Could not register net-device\n");
+                       kfree(netdev->local);
+@@ -2658,6 +3558,9 @@
+       netdev->local->hupflags = ISDN_INHUP;   /* Do hangup even on incoming calls */
+       netdev->local->onhtime = 10;    /* Default hangup-time for saving costs
+          of those who forget configuring this */
++#ifdef CONFIG_ISDN_WITH_ABC 
++      netdev->local->dw_abc_old_onhtime = netdev->local->onhtime;
++#endif
+       netdev->local->dialmax = 1;
+       netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;     /* Hangup before Callback, manual dial */
+       netdev->local->cbdelay = 25;    /* Wait 5 secs before Callback */
+@@ -2831,7 +3734,6 @@
+                       /* If binding is exclusive, try to grab the channel */
+                       save_flags(flags);
+-                      cli();
+                       if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
+                               lp->l2_proto, lp->l3_proto, drvidx,
+                               chidx, lp->msn)) < 0) {
+@@ -2859,6 +3761,9 @@
+               lp->pre_device = drvidx;
+               lp->pre_channel = chidx;
+               lp->onhtime = cfg->onhtime;
++#ifdef CONFIG_ISDN_WITH_ABC 
++              lp->dw_abc_old_onhtime = lp->onhtime;
++#endif
+               lp->charge = cfg->charge;
+               lp->l2_proto = cfg->l2_proto;
+               lp->l3_proto = cfg->l3_proto;
+@@ -2932,6 +3837,9 @@
+                       }
+               }
+               lp->p_encap = cfg->p_encap;
++#ifdef CONFIG_ISDN_WITH_ABC 
++              isdn_dw_abc_reset_interface(lp,0);
++#endif
+               return 0;
+       }
+       return -ENODEV;
+@@ -3007,6 +3915,9 @@
+               strcpy(n->num, phone->phone);
+               n->next = p->local->phone[phone->outgoing & 1];
+               p->local->phone[phone->outgoing & 1] = n;
++#ifdef CONFIG_ISDN_WITH_ABC
++              isdn_dwabc_test_phone(p->local);
++#endif
+               return 0;
+       }
+       return -ENODEV;
+@@ -3100,6 +4011,9 @@
+                               else
+                                       p->local->phone[inout] = n->next;
+                               kfree(n);
++#ifdef CONFIG_ISDN_WITH_ABC
++                              isdn_dwabc_test_phone(p->local);
++#endif
+                               restore_flags(flags);
+                               return 0;
+                       }
+@@ -3135,6 +4049,9 @@
+               p->local->phone[i] = NULL;
+       }
+       p->local->dial = NULL;
++#ifdef CONFIG_ISDN_WITH_ABC
++      isdn_dwabc_test_phone(p->local);
++#endif
+       restore_flags(flags);
+       return 0;
+ }
+@@ -3218,6 +4135,10 @@
+       /* If no more net-devices remain, disable auto-hangup timer */
+       if (dev->netdev == NULL)
+               isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
++#ifdef CONFIG_ISDN_WITH_ABC
++      isdn_dw_clear_if(~0l,p->local);
++      dwabc_bsd_free(p->local);
++#endif
+       restore_flags(flags);
+       kfree(p->local);
+       kfree(p);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_net.h linux-2.4.29/drivers/isdn/isdn_net.h
+--- linux-2.4.29.old/drivers/isdn/isdn_net.h   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_net.h       2005-03-22 15:06:44.463333328 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_net.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_net.h,v 1.23 2001/11/07 22:35:48 kai Exp $
+  *
+  * header for Linux ISDN subsystem, network related functions (linklevel).
+  *
+@@ -26,6 +26,7 @@
+ #define CISCO_ADDR_BROADCAST  0x8f
+ #define CISCO_CTRL            0x00
+ #define CISCO_TYPE_CDP        0x2000
++#define CISCO_TYPE_INET       0x0800
+ #define CISCO_TYPE_SLARP      0x8035
+ #define CISCO_SLARP_REQUEST   0
+ #define CISCO_SLARP_REPLY     1
+@@ -106,8 +107,6 @@
+       spin_lock_irqsave(&nd->queue_lock, flags);
+       lp = nd->queue;
+-//    printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) nlp:%s(%p) last(%p)\n",
+-//            lp->name, lp, nlp->name, nlp, lp->last); 
+       nlp->last = lp->last;
+       lp->last->next = nlp;
+       lp->last = nlp;
+@@ -127,20 +126,12 @@
+       if (lp->master)
+               master_lp = (isdn_net_local *) lp->master->priv;
+-//    printk(KERN_DEBUG __FUNCTION__": lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n",
+-//            lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue); 
+       spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
+       lp->last->next = lp->next;
+       lp->next->last = lp->last;
+-      if (master_lp->netdev->queue == lp) {
++      if (master_lp->netdev->queue == lp)
+               master_lp->netdev->queue = lp->next;
+-              if (lp->next == lp) { /* last in queue */
+-                      master_lp->netdev->queue = master_lp->netdev->local;
+-              }
+-      }
+       lp->next = lp->last = lp;       /* (re)set own pointers */
+-//    printk(KERN_DEBUG __FUNCTION__": mndq(%p)\n",
+-//            master_lp->netdev->queue); 
+       spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ppp.c linux-2.4.29/drivers/isdn/isdn_ppp.c
+--- linux-2.4.29.old/drivers/isdn/isdn_ppp.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ppp.c       2005-03-22 15:06:44.481330592 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ppp.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ppp.c,v 1.94 2001/11/07 22:35:48 kai Exp $
+  *
+  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
+  *
+@@ -13,9 +13,6 @@
+ #include <linux/isdn.h>
+ #include <linux/poll.h>
+ #include <linux/ppp-comp.h>
+-#ifdef CONFIG_IPPP_FILTER
+-#include <linux/filter.h>
+-#endif
+ #include "isdn_common.h"
+ #include "isdn_ppp.h"
+@@ -72,11 +69,19 @@
+ static int isdn_ppp_bundle(struct ippp_struct *, int unit);
+ #endif        /* CONFIG_ISDN_MPP */
+   
+-char *isdn_ppp_revision = "$Revision: 1.1.4.1 $";
++char *isdn_ppp_revision = "$Revision: 1.94 $";
+ static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
++#ifndef CONFIG_ISDN_WITH_ABC
+ static struct isdn_ppp_compressor *ipc_head = NULL;
++#else
++      /*
++      ** make compressor's common usable
++      */
++struct isdn_ppp_compressor *isdn_ippp_comp_head = NULL;
++#define ipc_head isdn_ippp_comp_head
++#endif
+ /*
+  * frame log (debug)
+@@ -110,11 +115,8 @@
+       unsigned long flags;
+       struct ippp_struct *is;
+-      if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+-                      __FUNCTION__, lp->ppp_slot);
++      if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS)
+               return 0;
+-      }
+       save_flags(flags);
+       cli();
+@@ -130,12 +132,7 @@
+       lp->netdev->pb->ref_ct--;
+       spin_unlock(&lp->netdev->pb->lock);
+ #endif /* CONFIG_ISDN_MPP */
+-      if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
+-                      __FUNCTION__, lp->ppp_slot);
+-              restore_flags(flags);
+-              return 0;
+-      }
++
+       is = ippp_table[lp->ppp_slot];
+       if ((is->state & IPPP_CONNECT))
+               isdn_ppp_closewait(lp->ppp_slot);       /* force wakeup on ippp device */
+@@ -231,13 +228,12 @@
+ void
+ isdn_ppp_wakeup_daemon(isdn_net_local * lp)
+ {
+-      if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
+-                      __FUNCTION__, lp->ppp_slot);
++      if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS)
+               return;
+-      }
++
+       ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
+-      wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
++
++              wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
+ }
+ /*
+@@ -250,14 +246,13 @@
+ {
+       struct ippp_struct *is;
+-      if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: slot(%d) out of range\n",
+-                      __FUNCTION__, slot);
++      if (slot < 0 || slot >= ISDN_MAX_CHANNELS)
+               return 0;
+-      }
+       is = ippp_table[slot];
++
+       if (is->state)
+               wake_up_interruptible(&is->wq);
++
+       is->state = IPPP_CLOSEWAIT;
+       return 1;
+ }
+@@ -295,9 +290,11 @@
+               return -EBUSY;
+       }
+       is = file->private_data = ippp_table[slot];
+-      
+-      printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
+-             slot, min, is->state);
++
++#if 0
++      if (is->debug & 0x1)
++#endif
++              printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n", slot, min, is->state);
+       /* compression stuff */
+       is->link_compressor   = is->compressor = NULL;
+@@ -327,10 +324,7 @@
+        */
+       is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
+ #endif
+-#ifdef CONFIG_IPPP_FILTER
+-      is->pass_filter.filter = NULL;
+-      is->active_filter.filter = NULL;
+-#endif
++
+       is->state = IPPP_OPEN;
+       return 0;
+@@ -349,20 +343,12 @@
+               return;
+       is = file->private_data;
+-      if (!is) {
+-              printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__);
+-              return;
+-      }
+       if (is->debug & 0x1)
+               printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
+       if (is->lp) {           /* a lp address says: this link is still up */
+               isdn_net_dev *p = is->lp->netdev;
+-              if (!p) {
+-                      printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__);
+-                      return;
+-              }
+               is->state &= ~IPPP_CONNECT;     /* -> effect: no call of wakeup */
+               /*
+                * isdn_net_hangup() calls isdn_ppp_free()
+@@ -385,18 +371,8 @@
+       slhc_free(is->slcomp);
+       is->slcomp = NULL;
+ #endif
+-#ifdef CONFIG_IPPP_FILTER
+-      if (is->pass_filter.filter) {
+-              kfree(is->pass_filter.filter);
+-              is->pass_filter.filter = NULL;
+-      }
+-      if (is->active_filter.filter) {
+-              kfree(is->active_filter.filter);
+-              is->active_filter.filter = NULL;
+-      }
+-#endif
+-/* TODO: if this was the previous master: link the stuff to the new master */
++/* TODO: if this was the previous master: link the the stuff to the new master */
+       if(is->comp_stat)
+               is->compressor->free(is->comp_stat);
+       if(is->link_comp_stat)
+@@ -509,13 +485,15 @@
+                       if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
+                               if (lp) {
+                                       /* OK .. we are ready to send buffers */
+-                                      is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
+                                       netif_wake_queue(&lp->netdev->dev);
+-                                      break;
+                               }
+                       }
+                       is->pppcfg = val;
+                       break;
++#if 0
++              case PPPIOCGSTAT:       /* read PPP statistic information */
++                      break;
++#endif
+               case PPPIOCGIDLE:       /* get idle time information */
+                       if (lp) {
+                               struct ppp_idle pidle;
+@@ -604,39 +582,6 @@
+                               }
+                               return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo));
+                       }
+-#ifdef CONFIG_IPPP_FILTER
+-              case PPPIOCSPASS:
+-              case PPPIOCSACTIVE:
+-                      {
+-                              struct sock_fprog uprog, *filtp;
+-                              struct sock_filter *code = NULL;
+-                              int len, err;
+-
+-                              if (copy_from_user(&uprog, (void *) arg, sizeof(uprog)))
+-                                      return -EFAULT;
+-                              if (uprog.len > 0 && uprog.len < 65536) {
+-                                      len = uprog.len * sizeof(struct sock_filter);
+-                                      code = kmalloc(len, GFP_KERNEL);
+-                                      if (code == NULL)
+-                                              return -ENOMEM;
+-                                      if (copy_from_user(code, uprog.filter, len)) {
+-                                              kfree(code);
+-                                              return -EFAULT;
+-                                      }
+-                                      err = sk_chk_filter(code, uprog.len);
+-                                      if (err) {
+-                                              kfree(code);
+-                                              return err;
+-                                      }
+-                              }
+-                              filtp = (cmd == PPPIOCSPASS) ? &is->pass_filter : &is->active_filter;
+-                              if (filtp->filter)
+-                                      kfree(filtp->filter);
+-                              filtp->filter = code;
+-                              filtp->len = uprog.len;
+-                              break;
+-                      }
+-#endif /* CONFIG_IPPP_FILTER */
+               default:
+                       break;
+       }
+@@ -699,7 +644,7 @@
+       struct ippp_struct *is;
+       if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
+-              printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
++              printk(KERN_WARNING "ippp: illegal slot.\n");
+               return 0;
+       }
+       is = ippp_table[slot];
+@@ -976,8 +921,7 @@
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
+-                      lp->ppp_slot);
++              printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+               kfree_skb(skb);
+               return;
+       }
+@@ -1026,23 +970,19 @@
+ {
+       struct net_device *dev = &net_dev->dev;
+       struct ippp_struct *is, *mis;
+-      isdn_net_local *mlp = NULL;
+       int slot;
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
+-                      lp->ppp_slot);
++              printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot %d\n", lp->ppp_slot);
+               goto drop_packet;
+       }
+       is = ippp_table[slot];
+       
+       if (lp->master) { // FIXME?
+-              mlp = (isdn_net_local *) lp->master->priv;
+-              slot = mlp->ppp_slot;
++              slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+               if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-                      printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
+-                              lp->ppp_slot);
++                      printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot %d\n", lp->ppp_slot);
+                       goto drop_packet;
+               }
+       }
+@@ -1076,11 +1016,6 @@
+               case PPP_VJC_UNCOMP:
+                       if (is->debug & 0x20)
+                               printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
+-                      if (net_dev->local->ppp_slot < 0) {
+-                              printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+-                                      __FUNCTION__, net_dev->local->ppp_slot);
+-                              goto drop_packet;
+-                      }
+                       if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
+                               printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
+                               goto drop_packet;
+@@ -1102,11 +1037,6 @@
+                               }
+                               skb_put(skb, skb_old->len + 128);
+                               memcpy(skb->data, skb_old->data, skb_old->len);
+-                              if (net_dev->local->ppp_slot < 0) {
+-                                      printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
+-                                              __FUNCTION__, net_dev->local->ppp_slot);
+-                                      goto drop_packet;
+-                              }
+                               pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
+                                               skb->data, skb_old->len);
+                               kfree_skb(skb_old);
+@@ -1133,36 +1063,12 @@
+                       return;
+       }
+-#ifdef CONFIG_IPPP_FILTER
+-      /* check if the packet passes the pass and active filters
+-       * the filter instructions are constructed assuming
+-       * a four-byte PPP header on each packet (which is still present) */
+-      skb_push(skb, 4);
+-      skb->data[0] = 0;       /* indicate inbound */
+-
+-      if (is->pass_filter.filter
+-          && sk_run_filter(skb, is->pass_filter.filter,
+-                          is->pass_filter.len) == 0) {
+-              if (is->debug & 0x2)
+-                      printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
+-              kfree_skb(skb);
+-              return;
+-      }
+-      if (!(is->active_filter.filter
+-            && sk_run_filter(skb, is->active_filter.filter,
+-                             is->active_filter.len) == 0)) {
+-              if (is->debug & 0x2)
+-                      printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+-              lp->huptimer = 0;
+-              if (mlp)
+-                      mlp->huptimer = 0;
+-      }
+-      skb_pull(skb, 4);
+-#else /* CONFIG_IPPP_FILTER */
+-      lp->huptimer = 0;
+-      if (mlp)
+-              mlp->huptimer = 0;
+-#endif /* CONFIG_IPPP_FILTER */
++      /* Reset hangup-timer */
++      lp->huptimer = 0;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++      lp->dw_abc_bchan_errcnt = 0;
++#endif
++
+       skb->dev = dev;
+       skb->mac.raw = skb->data;
+       netif_rx(skb);
+@@ -1199,6 +1105,7 @@
+       return skb_push(skb,len);
+ }
++
+ /*
+  * send ppp frame .. we expect a PIDCOMPressable proto --
+  *  (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
+@@ -1214,25 +1121,23 @@
+       isdn_net_dev *nd;
+       unsigned int proto = PPP_IP;     /* 0x21 */
+       struct ippp_struct *ipt,*ipts;
+-      int slot, retval = 0;
++      int slot;
+       mlp = (isdn_net_local *) (netdev->priv);
+       nd = mlp->netdev;       /* get master lp */
+       slot = mlp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+-                      mlp->ppp_slot);
++              printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", mlp->ppp_slot);
+               kfree_skb(skb);
+-              goto out;
++              return 0;
+       }
+       ipts = ippp_table[slot];
+       if (!(ipts->pppcfg & SC_ENABLE_IP)) {   /* PPP connected ? */
+               if (ipts->debug & 0x1)
+                       printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
+-              retval = 1;
+-              goto out;
++              return 1;
+       }
+       switch (ntohs(skb->protocol)) {
+@@ -1246,25 +1151,24 @@
+                       printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n", 
+                              skb->protocol);
+                       dev_kfree_skb(skb);
+-                      goto out;
++                      return 0;
+       }
+       lp = isdn_net_get_locked_lp(nd);
+       if (!lp) {
+               printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
+-              retval = 1;
+-              goto out;
++              return 1;
+       }
+       /* we have our lp locked from now on */
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
+-                      lp->ppp_slot);
++              printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot %d\n", lp->ppp_slot);
+               kfree_skb(skb);
+-              goto unlock;
++              return 0;
+       }
+       ipt = ippp_table[slot];
++      lp->huptimer = 0;
+       /*
+        * after this line .. requeueing in the device queue is no longer allowed!!!
+@@ -1275,34 +1179,6 @@
+        */
+       skb_pull(skb,IPPP_MAX_HEADER);
+-#ifdef CONFIG_IPPP_FILTER
+-      /* check if we should pass this packet
+-       * the filter instructions are constructed assuming
+-       * a four-byte PPP header on each packet */
+-      skb_push(skb, 4);
+-      skb->data[0] = 1;       /* indicate outbound */
+-      *(u_int16_t *)(skb->data + 2) = htons(proto);
+-
+-      if (ipt->pass_filter.filter 
+-          && sk_run_filter(skb, ipt->pass_filter.filter,
+-                           ipt->pass_filter.len) == 0) {
+-              if (ipt->debug & 0x4)
+-                      printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
+-              kfree_skb(skb);
+-              goto unlock;
+-      }
+-      if (!(ipt->active_filter.filter
+-            && sk_run_filter(skb, ipt->active_filter.filter,
+-                             ipt->active_filter.len) == 0)) {
+-              if (ipt->debug & 0x4)
+-                      printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
+-              lp->huptimer = 0;
+-      }
+-      skb_pull(skb, 4);
+-#else /* CONFIG_IPPP_FILTER */
+-      lp->huptimer = 0;
+-#endif /* CONFIG_IPPP_FILTER */
+-
+       if (ipt->debug & 0x4)
+               printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
+         if (ipts->debug & 0x40)
+@@ -1440,54 +1316,9 @@
+  unlock:
+       spin_unlock_bh(&lp->xmit_lock);
+- out:
+-      return retval;
++      return 0;
+ }
+-#ifdef CONFIG_IPPP_FILTER
+-/*
+- * check if this packet may trigger auto-dial.
+- */
+-
+-int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
+-{
+-      struct ippp_struct *is = ippp_table[lp->ppp_slot];
+-      u_int16_t proto;
+-      int drop = 0;
+-
+-      switch (ntohs(skb->protocol)) {
+-      case ETH_P_IP:
+-              proto = PPP_IP;
+-              break;
+-      case ETH_P_IPX:
+-              proto = PPP_IPX;
+-              break;
+-      default:
+-              printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
+-                     skb->protocol);
+-              return 1;
+-      }
+-
+-      /* the filter instructions are constructed assuming
+-       * a four-byte PPP header on each packet. we have to
+-       * temporarily remove part of the fake header stuck on
+-       * earlier.
+-       */
+-      skb_pull(skb, IPPP_MAX_HEADER - 4);
+-      skb->data[0] = 1;       /* indicate outbound */
+-      *(u_int16_t *)(skb->data + 2) = htons(proto);
+-      
+-      drop |= is->pass_filter.filter
+-              && sk_run_filter(skb, is->pass_filter.filter,
+-                               is->pass_filter.len) == 0;
+-      drop |= is->active_filter.filter
+-              && sk_run_filter(skb, is->active_filter.filter,
+-                               is->active_filter.len) == 0;
+-      
+-      skb_push(skb, IPPP_MAX_HEADER - 4);
+-      return drop;
+-}
+-#endif
+ #ifdef CONFIG_ISDN_MPP
+ /* this is _not_ rfc1990 header, but something we convert both short and long
+@@ -1537,15 +1368,8 @@
+ static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
+ {
+-      struct ippp_struct * is;
+-
+-      if (lp->ppp_slot < 0) {
+-              printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+-                      __FUNCTION__, lp->ppp_slot);
+-              return(-EINVAL);
+-      }
+-
+-      is = ippp_table[lp->ppp_slot];
++      struct ippp_struct * is = ippp_table[lp->ppp_slot];
++   
+       if (add_to) {
+               if( lp->netdev->pb )
+                       lp->netdev->pb->ref_ct--;
+@@ -1591,8 +1415,7 @@
+         stats = &mp->stats;
+       slot = lp->ppp_slot;
+       if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
+-                      __FUNCTION__, lp->ppp_slot);
++              printk(KERN_ERR "isdn_ppp_mp_receive: lp->ppp_slot %d\n", lp->ppp_slot);
+               stats->frame_drops++;
+               dev_kfree_skb(skb);
+               spin_unlock_irqrestore(&mp->lock, flags);
+@@ -1628,8 +1451,7 @@
+       for (lpq = net_dev->queue;;) {
+               slot = lpq->ppp_slot;
+               if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-                      printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
+-                              __FUNCTION__, lpq->ppp_slot);
++                      printk(KERN_ERR "isdn_ppp_mp_receive: lpq->ppp_slot %d\n", lpq->ppp_slot);
+               } else {
+                       u32 lls = ippp_table[slot]->last_link_seqno;
+                       if (MP_LT(lls, minseq))
+@@ -1861,14 +1683,9 @@
+       struct sk_buff * skb;
+       unsigned int tot_len;
+-      if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+-                      __FUNCTION__, lp->ppp_slot);
+-              return;
+-      }
+       if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
+               if( ippp_table[lp->ppp_slot]->debug & 0x40 )
+-                      printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
++                      printk(KERN_DEBUG"isdn_mppp: reassembly: frame %d, "
+                                       "len %d\n", MP_SEQ(from), from->len );
+               skb = from;
+               skb_pull(skb, MP_HEADER_LEN);
+@@ -1987,10 +1804,8 @@
+       memset(&t, 0, sizeof(struct ppp_stats));
+       if (dev->flags & IFF_UP) {
+               t.p.ppp_ipackets = lp->stats.rx_packets;
+-              t.p.ppp_ibytes = lp->stats.rx_bytes;
+               t.p.ppp_ierrors = lp->stats.rx_errors;
+               t.p.ppp_opackets = lp->stats.tx_packets;
+-              t.p.ppp_obytes = lp->stats.tx_bytes;
+               t.p.ppp_oerrors = lp->stats.tx_errors;
+ #ifdef CONFIG_ISDN_PPP_VJ
+               if (slot >= 0 && ippp_table[slot]->slcomp) {
+@@ -2018,6 +1833,9 @@
+       int len;
+       isdn_net_local *lp = (isdn_net_local *) dev->priv;
++#if 0
++      printk(KERN_DEBUG "ippp, dev_ioctl: cmd %#08x , %d \n", cmd, lp->ppp_slot);
++#endif
+       if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
+               return -EINVAL;
+@@ -2431,7 +2249,7 @@
+                               return;
+                       }
+                       rs->state = CCPResetSentReq;
+-                      /* We always expect an Ack if the decompressor doesn't
++                      /* We always expect an Ack if the decompressor doesnt
+                          know better */
+                       rs->expra = 1;
+                       rs->dlen = 0;
+@@ -2582,7 +2400,13 @@
+     }
+       if(type) { /* type=1 => Link compression */
++#if 0
++              compressor = is->link_compressor;
++              stat = is->link_comp_stat;
++              new_proto = PPP_LINK_COMP;
++#else
+               return skb_in;
++#endif
+       }
+       else {
+               if(!master) {
+@@ -2630,31 +2454,18 @@
+ static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
+        struct sk_buff *skb,int proto)
+ {
+-      struct ippp_struct *is;
++      struct ippp_struct *is = ippp_table[lp->ppp_slot];
+       struct ippp_struct *mis;
+       int len;
+       struct isdn_ppp_resetparams rsparm;
+       unsigned char rsdata[IPPP_RESET_MAXDATABYTES];  
+-      printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
+-              lp->ppp_slot);
+-      if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+-                      __FUNCTION__, lp->ppp_slot);
+-              return;
+-      }
+-      is = ippp_table[lp->ppp_slot];
++      printk(KERN_DEBUG "Received CCP frame from peer\n");
+       isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+-      if(lp->master) {
+-              int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+-              if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-                      printk(KERN_ERR "%s: slot(%d) out of range\n",
+-                              __FUNCTION__, slot);
+-                      return;
+-              }       
+-              mis = ippp_table[slot];
+-      } else
++      if(lp->master)
++              mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
++      else
+               mis = is;
+       switch(skb->data[0]) {
+@@ -2806,18 +2617,13 @@
+ static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
+ {
+-      struct ippp_struct *mis,*is;
+-      int proto, slot = lp->ppp_slot;
++      struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot];
++      int proto;
+       unsigned char *data;
+       if(!skb || skb->len < 3)
+               return;
+-      if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-              printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
+-                      __FUNCTION__, slot);
+-              return;
+-      }       
+-      is = ippp_table[slot];
++
+       /* Daemon may send with or without address and control field comp */
+       data = skb->data;
+       if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
+@@ -2833,17 +2639,12 @@
+       printk(KERN_DEBUG "Received CCP frame from daemon:\n");
+       isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
+-      if (lp->master) {
+-              slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
+-              if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
+-                      printk(KERN_ERR "%s: slot(%d) out of range\n",
+-                              __FUNCTION__, slot);
+-                      return;
+-              }       
+-              mis = ippp_table[slot];
+-      } else
+-              mis = is;
+-      if (mis != is)
++        if(lp->master)
++                mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot];
++        else
++                mis = is;
++      
++      if(mis != is)
+               printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
+       
+         switch(data[2]) {
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ppp.h linux-2.4.29/drivers/isdn/isdn_ppp.h
+--- linux-2.4.29.old/drivers/isdn/isdn_ppp.h   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ppp.h       2005-03-22 15:06:44.497328160 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ppp.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ppp.h,v 1.18 2001/09/24 13:22:42 kai Exp $
+  *
+  * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
+  *
+@@ -19,7 +19,6 @@
+ extern void isdn_ppp_cleanup(void);
+ extern int isdn_ppp_free(isdn_net_local *);
+ extern int isdn_ppp_bind(isdn_net_local *);
+-extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *);
+ extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
+ extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
+ extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_tty.c linux-2.4.29/drivers/isdn/isdn_tty.c
+--- linux-2.4.29.old/drivers/isdn/isdn_tty.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_tty.c       2005-03-22 15:06:44.524324056 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_tty.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_tty.c,v 1.104 2002/02/09 21:19:11 keil Exp $
+  *
+  * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
+  *
+@@ -53,7 +53,7 @@
+ static int si2bit[8] =
+ {4, 1, 4, 4, 4, 4, 4, 4};
+-char *isdn_tty_revision = "$Revision: 1.1.4.1 $";
++char *isdn_tty_revision = "$Revision: 1.104 $";
+ /* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
+@@ -321,7 +321,10 @@
+               info->send_outstanding++;
+               info->msr &= ~UART_MSR_CTS;
+               info->lsr &= ~UART_LSR_TEMT;
+-              tty_wakeup(tty);
++              if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++                  tty->ldisc.write_wakeup)
++                      (tty->ldisc.write_wakeup) (tty);
++              wake_up_interruptible(&tty->write_wait);
+               return;
+       }
+       if (slen < 0) {
+@@ -1211,7 +1214,10 @@
+                                               /* If DLE decoding results in zero-transmit, but
+                                                * c originally was non-zero, do a wakeup.
+                                                */
+-                                              tty_wakeup(tty);
++                                              if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++                                               tty->ldisc.write_wakeup)
++                                                      (tty->ldisc.write_wakeup) (tty);
++                                              wake_up_interruptible(&tty->write_wait);
+                                               info->msr |= UART_MSR_CTS;
+                                               info->lsr |= UART_LSR_TEMT;
+                                       }
+@@ -1232,6 +1238,7 @@
+                                       }
+                               }
+                       } else
++#ifdef ISDN_TTY_FCLASS1
+                       if (TTY_IS_FCLASS1(info)) {
+                               int cc = isdn_tty_handleDLEdown(info, m, c);
+                               
+@@ -1252,6 +1259,7 @@
+                               info->xmit_count += cc;
+                       } else
+ #endif
++#endif
+                               info->xmit_count += c;
+               } else {
+                       info->msr |= UART_MSR_CTS;
+@@ -1329,7 +1337,10 @@
+       isdn_tty_cleanup_xmit(info);
+       info->xmit_count = 0;
+       restore_flags(flags);
+-      tty_wakeup(tty);
++      wake_up_interruptible(&tty->write_wait);
++      if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
++          tty->ldisc.write_wakeup)
++              (tty->ldisc.write_wakeup) (tty);
+ }
+ static void
+@@ -1858,7 +1869,8 @@
+       isdn_tty_shutdown(info);
+       if (tty->driver.flush_buffer)
+               tty->driver.flush_buffer(tty);
+-      tty_ldisc_flush(tty);
++      if (tty->ldisc.flush_buffer)
++              tty->ldisc.flush_buffer(tty);
+       info->tty = 0;
+       info->ncarrier = 0;
+       tty->closing = 0;
+@@ -2306,6 +2318,22 @@
+                                 isdn_tty_at_cout("\r\n", info);
+                               }
+                               return 1;
++                      case ISDN_STAT_ALERT:
++#ifdef ISDN_TTY_STAT_DEBUG
++                              printk(KERN_DEBUG "tty_STAT_ALERT ttyI%d\n", info->line);
++#endif
++                              /* Signal RINGING to tty-device if requested */
++                              if (info->emu.mdmreg[REG_ALERT] & BIT_ALERT)
++                                      isdn_tty_modem_result(RESULT_RINGING, info);
++                              return 1;
++                      case ISDN_STAT_PROCEED:
++#ifdef ISDN_TTY_STAT_DEBUG
++                              printk(KERN_DEBUG "tty_STAT_PROCEED ttyI%d\n", info->line);
++#endif
++                              /* Signal PROCEEDING to tty-device if requested */
++                              if (info->emu.mdmreg[REG_PROCEED] & BIT_PROCEED)
++                                      isdn_tty_modem_result(RESULT_PROCEEDING, info);
++                              return 1;
+                       case ISDN_STAT_DCONN:
+ #ifdef ISDN_TTY_STAT_DEBUG
+                               printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
+@@ -2618,7 +2646,7 @@
+       static char *msg[] =
+       {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
+        "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
+-       "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
++       "RINGING", "NO MSN/EAZ", "VCON", "RUNG", "PROCEEDING"};
+       ulong flags;
+       char s[ISDN_MSNLEN+10];
+@@ -2781,7 +2809,8 @@
+                       restore_flags(flags);
+                       return;
+               }
+-              tty_ldisc_flush(info->tty);
++              if (info->tty->ldisc.flush_buffer)
++                      info->tty->ldisc.flush_buffer(info->tty);
+               if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
+                   (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
+                      (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
+@@ -3296,9 +3325,11 @@
+ #ifdef CONFIG_ISDN_TTY_FAX
+                               if (TTY_IS_FCLASS2(info))
+                                               sprintf(rs, "\r\n2");
++#ifdef ISDN_TTY_FCLASS1
+                               else if (TTY_IS_FCLASS1(info))
+                                               sprintf(rs, "\r\n1");
+ #endif
++#endif
+                               isdn_tty_at_cout(rs, info);
+                               break;
+                       case '=':
+@@ -3313,6 +3344,7 @@
+                                                   m->mdmreg[REG_PSIZE] * 16;
+                                               break;
+ #ifdef CONFIG_ISDN_TTY_FAX
++#ifdef ISDN_TTY_FCLASS1
+                                       case '1':
+                                               p[0]++;
+                                               if (!(dev->global_features &
+@@ -3324,6 +3356,7 @@
+                                               info->xmit_size =
+                                                   m->mdmreg[REG_PSIZE] * 16;
+                                               break;
++#endif
+                                       case '2':
+                                               p[0]++;
+                                               if (!(dev->global_features &
+@@ -3348,9 +3381,11 @@
+                                               p[0]++;
+                                               strcpy(rs, "\r\n0,");
+ #ifdef CONFIG_ISDN_TTY_FAX
++#ifdef ISDN_TTY_FCLASS1
+                                               if (dev->global_features &
+                                                       ISDN_FEATURE_L3_FCLASS1)
+                                                       strcat(rs, "1,");
++#endif
+                                               if (dev->global_features &
+                                                       ISDN_FEATURE_L3_FCLASS2)
+                                                       strcat(rs, "2,");
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_tty.h linux-2.4.29/drivers/isdn/isdn_tty.h
+--- linux-2.4.29.old/drivers/isdn/isdn_tty.h   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_tty.h       2005-03-22 15:06:44.545320864 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_tty.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_tty.h,v 1.25 2002/02/09 21:19:11 keil Exp $
+  *
+  * header for Linux ISDN subsystem, tty related functions (linklevel).
+  *
+@@ -78,6 +78,10 @@
+ #define BIT_CPNFCON   2
+ #define REG_CDN      23
+ #define BIT_CDN       4
++#define REG_ALERT    23
++#define BIT_ALERT     8
++#define REG_PROCEED  23
++#define BIT_PROCEED  16
+ /* defines for result codes */
+ #define RESULT_OK             0
+@@ -93,10 +97,13 @@
+ #define RESULT_NO_MSN_EAZ     10
+ #define RESULT_VCON           11
+ #define RESULT_RUNG           12
++#define RESULT_PROCEEDING     13
++#ifdef ISDN_TTY_FCLASS1
+ #define TTY_IS_FCLASS1(info) \
+       ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+        (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
++#endif
+ #define TTY_IS_FCLASS2(info) \
+       ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
+        (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ttyfax.c linux-2.4.29/drivers/isdn/isdn_ttyfax.c
+--- linux-2.4.29.old/drivers/isdn/isdn_ttyfax.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ttyfax.c    2005-03-22 15:06:44.561318432 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ttyfax.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ttyfax.c,v 1.9 2001/09/24 13:22:43 kai Exp $
+  *
+  * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
+  *
+@@ -20,7 +20,7 @@
+ #include "isdn_ttyfax.h"
+-static char *isdn_tty_fax_revision = "$Revision: 1.1.4.1 $";
++static char *isdn_tty_fax_revision = "$Revision: 1.9 $";
+ #define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
+@@ -148,6 +148,7 @@
+       }
+ }
++#ifdef ISDN_TTY_FCLASS1
+ int
+ isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c)
+ {
+@@ -186,6 +187,7 @@
+       }
+       return (0);
+ }
++#endif
+ int
+ isdn_tty_fax_command(modem_info * info, isdn_ctrl * c)
+@@ -193,8 +195,10 @@
+       T30_s *f = info->fax;
+       char rs[10];
++#ifdef ISDN_TTY_FCLASS1
+       if (TTY_IS_FCLASS1(info))
+               return (isdn_tty_fax_command1(info, c));
++#endif
+ #ifdef ISDN_TTY_FAX_CMD_DEBUG
+       printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
+@@ -312,6 +316,7 @@
+       }
+ }
++#ifdef ISDN_TTY_FCLASS1
+ /*
+  * Parse AT+F.. FAX class 1 commands
+  */
+@@ -403,6 +408,7 @@
+       }
+       return 1;
+ }
++#endif
+ /*
+  * Parse AT+F.. FAX class 2 commands
+@@ -970,6 +976,70 @@
+               }
+               return 0;
+       }
++#if 0
++      /* LO=n - Flow control opts */
++      if (!strncmp(p[0], "LO", 2)) {  /* TODO */
++              p[0] += 2;
++              switch (*p[0]) {
++                      case '?':
++                              p[0]++;
++                              sprintf(rs, "\r\n%d", f->lo);
++                              isdn_tty_at_cout(rs, info);
++                              break;
++                      case '=':
++                              p[0]++;
++                              if (*p[0] == '?') {
++                                      p[0]++;
++                                      sprintf(rs, "\r\n0,1,2");
++                                      isdn_tty_at_cout(rs, info);
++                              } else {
++                                      par = isdn_getnum(p);
++                                      if ((par < 0) || (par > 2))
++                                              PARSE_ERROR1;
++                                      f->lo = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++                                      printk(KERN_DEBUG "isdn_tty: Fax FLO=%d\n", par);
++#endif
++                              }
++                              break;
++                      default:
++                              PARSE_ERROR1;
++              }
++              return 0;
++      }
++#endif
++#if 0
++      /* LPL=n - Doc for polling cmd  */
++      if (!strncmp(p[0], "LPL", 3)) {         /* TODO */
++              p[0] += 3;
++              switch (*p[0]) {
++                      case '?':
++                              p[0]++;
++                              sprintf(rs, "\r\n%d", f->lpl);
++                              isdn_tty_at_cout(rs, info);
++                              break;
++                      case '=':
++                              p[0]++;
++                              if (*p[0] == '?') {
++                                      p[0]++;
++                                      sprintf(rs, "\r\n0,1");
++                                      isdn_tty_at_cout(rs, info);
++                              } else {
++                                      par = isdn_getnum(p);
++                                      if ((par < 0) || (par > 1))
++                                              PARSE_ERROR1;
++                                      f->lpl = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++                                      printk(KERN_DEBUG "isdn_tty: Fax FLPL=%d\n", par);
++#endif
++                              }
++                              break;
++                      default:
++                              PARSE_ERROR1;
++              }
++              return 0;
++      }
++#endif
+       /* MDL? - DCE Model       */
+       if (!strncmp(p[0], "MDL?", 4)) {
+@@ -1049,6 +1119,38 @@
+               }
+               return 0;
+       }
++#if 0
++      /* PTS=n - Page transfer status       */
++      if (!strncmp(p[0], "PTS", 3)) {         /* TODO */
++              p[0] += 3;
++              switch (*p[0]) {
++                      case '?':
++                              p[0]++;
++                              sprintf(rs, "\r\n%d", f->pts);
++                              isdn_tty_at_cout(rs, info);
++                              break;
++                      case '=':
++                              p[0]++;
++                              if (*p[0] == '?') {
++                                      p[0]++;
++                                      sprintf(rs, "\r\n0-5");
++                                      isdn_tty_at_cout(rs, info);
++                              } else {
++                                      par = isdn_getnum(p);
++                                      if ((par < 0) || (par > 5))
++                                              PARSE_ERROR1;
++                                      f->pts = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++                                      printk(KERN_DEBUG "isdn_tty: Fax FPTS=%d\n", par);
++#endif
++                              }
++                              break;
++                      default:
++                              PARSE_ERROR1;
++              }
++              return 0;
++      }
++#endif
+       /* REL=n - Phase C received EOL alignment */
+       if (!strncmp(p[0], "REL", 3)) {
+@@ -1091,6 +1193,38 @@
+               isdn_tty_at_cout(rs, info);
+               return 0;
+       }
++#if 0
++      /* SPL=n - Enable polling */
++      if (!strncmp(p[0], "SPL", 3)) {         /* TODO */
++              p[0] += 3;
++              switch (*p[0]) {
++                      case '?':
++                              p[0]++;
++                              sprintf(rs, "\r\n%d", f->spl);
++                              isdn_tty_at_cout(rs, info);
++                              break;
++                      case '=':
++                              p[0]++;
++                              if (*p[0] == '?') {
++                                      p[0]++;
++                                      sprintf(rs, "\r\n0,1");
++                                      isdn_tty_at_cout(rs, info);
++                              } else {
++                                      par = isdn_getnum(p);
++                                      if ((par < 0) || (par > 1))
++                                              PARSE_ERROR1;
++                                      f->spl = par;
++#ifdef ISDN_TTY_FAX_STAT_DEBUG
++                                      printk(KERN_DEBUG "isdn_tty: Fax FSPL=%d\n", par);
++#endif
++                              }
++                              break;
++                      default:
++                              PARSE_ERROR1;
++              }
++              return 0;
++      }
++#endif
+       /* Phase C Transmit Data Block Size */
+       if (!strncmp(p[0], "TBC=", 4)) {        /* dummy, not used */
+@@ -1116,7 +1250,9 @@
+ {
+       if (TTY_IS_FCLASS2(info))
+               return (isdn_tty_cmd_FCLASS2(p, info));
++#ifdef ISDN_TTY_FCLASS1
+       else if (TTY_IS_FCLASS1(info))
+               return (isdn_tty_cmd_FCLASS1(p, info));
++#endif
+       PARSE_ERROR1;
+ }
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_ttyfax.h linux-2.4.29/drivers/isdn/isdn_ttyfax.h
+--- linux-2.4.29.old/drivers/isdn/isdn_ttyfax.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_ttyfax.h    2005-03-22 15:06:44.576316152 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_ttyfax.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_ttyfax.h,v 1.3 2001/09/24 13:22:43 kai Exp $
+  *
+  * header for Linux ISDN subsystem, tty_fax related functions (linklevel).
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_v110.c linux-2.4.29/drivers/isdn/isdn_v110.c
+--- linux-2.4.29.old/drivers/isdn/isdn_v110.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_v110.c      2005-03-22 15:06:44.593313568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_v110.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_v110.c,v 1.8 2001/09/24 13:22:43 kai Exp $
+  *
+  * Linux ISDN subsystem, V.110 related functions (linklevel).
+  *
+@@ -19,7 +19,7 @@
+ #undef ISDN_V110_DEBUG
+-char *isdn_v110_revision = "$Revision: 1.1.4.1 $";
++char *isdn_v110_revision = "$Revision: 1.8 $";
+ #define V110_38400 255
+ #define V110_19200  15
+@@ -138,6 +138,14 @@
+               return;
+ #ifdef ISDN_V110_DEBUG
+       printk(KERN_DEBUG "v110 close\n");
++#if 0
++      printk(KERN_DEBUG "isdn_v110_close: nbytes=%d\n", v->nbytes);
++      printk(KERN_DEBUG "isdn_v110_close: nbits=%d\n", v->nbits);
++      printk(KERN_DEBUG "isdn_v110_close: key=%d\n", v->key);
++      printk(KERN_DEBUG "isdn_v110_close: SyncInit=%d\n", v->SyncInit);
++      printk(KERN_DEBUG "isdn_v110:close: decodelen=%d\n", v->decodelen);
++      printk(KERN_DEBUG "isdn_v110_close: framelen=%d\n", v->framelen);
++#endif
+ #endif
+       kfree(v->encodebuf);
+       kfree(v);
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_v110.h linux-2.4.29/drivers/isdn/isdn_v110.h
+--- linux-2.4.29.old/drivers/isdn/isdn_v110.h  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_v110.h      2005-03-22 15:06:44.608311288 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_v110.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_v110.h,v 1.5 2001/09/24 13:22:43 kai Exp $
+  *
+  * Linux ISDN subsystem, V.110 related functions (linklevel).
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_x25iface.c linux-2.4.29/drivers/isdn/isdn_x25iface.c
+--- linux-2.4.29.old/drivers/isdn/isdn_x25iface.c      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_x25iface.c  2005-03-22 15:06:44.626308552 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_x25iface.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_x25iface.c,v 1.10 2001/09/24 13:22:43 kai Exp $
+  *
+  * Linux ISDN subsystem, X.25 related functions
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdn_x25iface.h linux-2.4.29/drivers/isdn/isdn_x25iface.h
+--- linux-2.4.29.old/drivers/isdn/isdn_x25iface.h      2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdn_x25iface.h  2005-03-22 15:06:44.645305664 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_x25iface.h,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
++/* $Id: isdn_x25iface.h,v 1.4 2001/09/24 13:22:43 kai Exp $
+  *
+  * header for Linux ISDN subsystem, x.25 related functions
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.c linux-2.4.29/drivers/isdn/isdnloop/isdnloop.c
+--- linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdnloop/isdnloop.c      2005-03-22 15:06:48.813671976 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnloop.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: isdnloop.c,v 1.17 2001/08/30 10:45:42 kai Exp $
+  *
+  * ISDN low-level module implementing a dummy loop driver.
+  *
+@@ -14,7 +14,7 @@
+ #include <linux/init.h>
+ #include "isdnloop.h"
+-static char *revision = "$Revision: 1.1.4.1 $";
++static char *revision = "$Revision$";
+ static char *isdnloop_id;
+ MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
+@@ -22,8 +22,8 @@
+ MODULE_LICENSE("GPL");
+ MODULE_PARM(isdnloop_id, "s");
+ MODULE_PARM_DESC(isdnloop_id, "ID-String of first card");
+-
+-static int isdnloop_addcard(char *);
++  
++  static int isdnloop_addcard(char *);
+ /*
+  * Free queue completely.
+@@ -1542,11 +1542,7 @@
+       } else
+               strcpy(rev, " ??? ");
+       printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev);
+-
+-      if (isdnloop_id)
+-              return (isdnloop_addcard(isdnloop_id));
+-
+-      return 0;
++      return (isdnloop_addcard(isdnloop_id));
+ }
+ static void __exit
+diff -rNu linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.h linux-2.4.29/drivers/isdn/isdnloop/isdnloop.h
+--- linux-2.4.29.old/drivers/isdn/isdnloop/isdnloop.h  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/isdnloop/isdnloop.h      2005-03-22 15:06:48.834668784 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnloop.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Loopback lowlevel module for testing of linklevel.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/callbacks.c linux-2.4.29/drivers/isdn/pcbit/callbacks.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/callbacks.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/callbacks.c        2005-03-22 15:06:48.909657384 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/callbacks.h linux-2.4.29/drivers/isdn/pcbit/callbacks.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/callbacks.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/callbacks.h        2005-03-22 15:06:48.953650696 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/capi.c linux-2.4.29/drivers/isdn/pcbit/capi.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/capi.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/capi.c     2005-03-22 15:06:49.042637168 +0100
+@@ -4,7 +4,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/capi.h linux-2.4.29/drivers/isdn/pcbit/capi.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/capi.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/capi.h     2005-03-22 15:06:49.071632760 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+@@ -63,7 +63,8 @@
+ extern int capi_decode_debug_188(u_char *hdr, ushort hdrlen);
+ #endif
+-static inline struct pcbit_chan * 
++extern __inline__ 
++struct pcbit_chan * 
+ capi_channel(struct pcbit_dev *dev, struct sk_buff *skb)
+ {
+       ushort callref;
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/drv.c linux-2.4.29/drivers/isdn/pcbit/drv.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/drv.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/drv.c      2005-03-22 15:06:49.091629720 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+@@ -35,7 +35,9 @@
+ #include <linux/isdnif.h>
+ #include <asm/string.h>
+ #include <asm/io.h>
++#ifdef COMPAT_HAS_ISA_IOREMAP
+ #include <linux/ioport.h>
++#endif
+ #include "pcbit.h"
+ #include "edss1.h"
+@@ -89,6 +91,7 @@
+       if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) {
+               dev->ph_mem = mem_base;
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               if (check_mem_region(dev->ph_mem, 4096)) {
+                       printk(KERN_WARNING
+                               "PCBIT: memory region %lx-%lx already in use\n",
+@@ -100,6 +103,9 @@
+                       request_mem_region(dev->ph_mem, 4096, "PCBIT mem");
+               }
+               dev->sh_mem = (unsigned char*)ioremap(dev->ph_mem, 4096);
++#else
++              dev->sh_mem = (unsigned char*) mem_base;
++#endif
+       }
+       else 
+       {
+@@ -112,8 +118,10 @@
+       dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL);
+       if (!dev->b1) {
+               printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char*)dev->sh_mem);
+               release_mem_region(dev->ph_mem, 4096);
++#endif
+               kfree(dev);
+               return -ENOMEM;
+       }
+@@ -122,8 +130,10 @@
+       if (!dev->b2) {
+               printk("pcbit_init: couldn't malloc pcbit_chan struct\n");
+               kfree(dev->b1);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char*)dev->sh_mem);
+               release_mem_region(dev->ph_mem, 4096);
++#endif
+               kfree(dev);
+               return -ENOMEM;
+       }
+@@ -144,8 +154,10 @@
+       {
+               kfree(dev->b1);
+               kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char*)dev->sh_mem);
+               release_mem_region(dev->ph_mem, 4096);
++#endif
+               kfree(dev);
+               dev_pcbit[board] = NULL;
+               return -EIO;
+@@ -166,8 +178,10 @@
+               free_irq(irq, dev);
+               kfree(dev->b1);
+               kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char*)dev->sh_mem);
+               release_mem_region(dev->ph_mem, 4096);
++#endif
+               kfree(dev);
+               dev_pcbit[board] = NULL;
+               return -EIO;
+@@ -197,8 +211,10 @@
+               free_irq(irq, dev);
+               kfree(dev->b1);
+               kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char*)dev->sh_mem);
+               release_mem_region(dev->ph_mem, 4096);
++#endif
+               kfree(dev);
+               dev_pcbit[board] = NULL;
+               return -EIO;
+@@ -235,8 +251,10 @@
+                       del_timer(&dev->b2->fsm_timer);
+               kfree(dev->b1);
+               kfree(dev->b2);
++#ifdef COMPAT_HAS_ISA_IOREMAP
+               iounmap((unsigned char*)dev->sh_mem);
+               release_mem_region(dev->ph_mem, 4096);
++#endif
+               kfree(dev);
+       }
+ }
+@@ -430,7 +448,7 @@
+       switch(dev->l2_state) {
+       case L2_LWMODE:
+               /* check (size <= rdp_size); write buf into board */
+-              if (len < 0 || len > BANK4 + 1)
++              if (len > BANK4 + 1)
+               {
+                       printk("pcbit_writecmd: invalid length %d\n", len);
+                       return -EINVAL;
+@@ -609,6 +627,20 @@
+                      dev->b1->s_refnum, 
+                      dev->b2->s_refnum);
+ #endif
++#if 0 
++              if (dev->b1->s_refnum == refnum)
++                      chan = dev->b1;
++              else { 
++                 
++                      if (dev->b2->s_refnum == refnum)
++                              chan = dev->b2;
++                      else {
++                              chan = NULL;
++                              printk(KERN_WARNING "Connection Confirm - refnum doesn't match chan\n");
++                              break;
++                      }
++              }
++#else
+               /* We just try to find a channel in the right state */
+               if (dev->b1->fsm_state == ST_CALL_INIT)
+@@ -622,6 +654,7 @@
+                               break;
+                       }
+               }
++#endif
+               if (capi_decode_conn_conf(chan, skb, &complete)) {
+                       printk(KERN_DEBUG "conn_conf indicates error\n");
+                       pcbit_fsm_event(dev, chan, EV_ERROR, NULL);
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/edss1.c linux-2.4.29/drivers/isdn/pcbit/edss1.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/edss1.c        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/edss1.c    2005-03-22 15:06:49.119625464 +0100
+@@ -4,7 +4,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/edss1.h linux-2.4.29/drivers/isdn/pcbit/edss1.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/edss1.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/edss1.h    2005-03-22 15:06:49.161619080 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/layer2.c linux-2.4.29/drivers/isdn/pcbit/layer2.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/layer2.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/layer2.c   2005-03-22 15:06:49.195613912 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  *
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of
+  * the GNU General Public License, incorporated herein by reference.
+@@ -369,11 +369,16 @@
+               if (dev->read_frame) {
+                       printk(KERN_DEBUG "pcbit_receive: Type 0 frame and read_frame != NULL\n");
++#if 0
++                      pcbit_l2_error(dev);
++                      return;
++#else
+                       /* discard previous queued frame */
+                       if (dev->read_frame->skb)
+                               kfree_skb(dev->read_frame->skb);
+                       kfree(dev->read_frame);
+                       dev->read_frame = NULL;
++#endif
+               }
+               frame = kmalloc(sizeof(struct frame_buf), GFP_ATOMIC);
+@@ -449,10 +454,14 @@
+               if (!(frame = dev->read_frame)) {
+                       printk("Type 1 frame and no frame queued\n");
++#if 1
+                       /* usually after an error: toss frame */
+                       dev->readptr += tt;
+                       if (dev->readptr > dev->sh_mem + BANK2 + BANKLEN)
+                               dev->readptr -= BANKLEN;
++#else
++                      pcbit_l2_error(dev);
++#endif
+                       return;
+               }
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/layer2.h linux-2.4.29/drivers/isdn/pcbit/layer2.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/layer2.h       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/layer2.h   2005-03-22 15:06:49.228608896 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/module.c linux-2.4.29/drivers/isdn/pcbit/module.c
+--- linux-2.4.29.old/drivers/isdn/pcbit/module.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/module.c   2005-03-22 15:06:49.251605400 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+@@ -92,6 +92,7 @@
+ }
+ #ifndef MODULE
++#ifdef COMPAT_HAS_NEW_SETUP
+ #define MAX_PARA      (MAX_PCBIT_CARDS * 2)
+ static int __init pcbit_setup(char *line)
+ {
+@@ -100,6 +101,11 @@
+       int ints[MAX_PARA+1];
+       str = get_options(line, MAX_PARA, ints);
++#else
++void pcbit_setup(char *str, int *ints)
++{
++      int i, j, argc;
++#endif
+       argc = ints[0];
+       i = 0;
+       j = 1;
+@@ -118,9 +124,13 @@
+               i++;
+       }
++#ifdef COMPAT_HAS_NEW_SETUP
+       return(1);
+ }
+ __setup("pcbit=", pcbit_setup);
++#else
++}
++#endif
+ #endif
+ module_init(pcbit_init);
+diff -rNu linux-2.4.29.old/drivers/isdn/pcbit/pcbit.h linux-2.4.29/drivers/isdn/pcbit/pcbit.h
+--- linux-2.4.29.old/drivers/isdn/pcbit/pcbit.h        2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/pcbit/pcbit.h    2005-03-22 15:06:49.284600384 +0100
+@@ -3,7 +3,7 @@
+  *
+  * Copyright (C) 1996 Universidade de Lisboa
+  * 
+- * Written by Pedro Roque Marques (pedro_m@yahoo.com)
++ * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
+  *
+  * This software may be used and distributed according to the terms of 
+  * the GNU General Public License, incorporated herein by reference.
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/card.h linux-2.4.29/drivers/isdn/sc/card.h
+--- linux-2.4.29.old/drivers/isdn/sc/card.h    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/card.h        2005-03-22 15:06:49.333592936 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: card.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Driver parameters for SpellCaster ISA ISDN adapters
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/command.c linux-2.4.29/drivers/isdn/sc/command.c
+--- linux-2.4.29.old/drivers/isdn/sc/command.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/command.c     2005-03-22 15:06:49.348590656 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: command.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+@@ -95,7 +95,7 @@
+               if(adapter[i]->driverId == driver)
+                       return i;
+       }
+-      return -ENODEV;
++      return -NODEV;
+ }
+ /* 
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/debug.c linux-2.4.29/drivers/isdn/sc/debug.c
+--- linux-2.4.29.old/drivers/isdn/sc/debug.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/debug.c       2005-03-22 15:06:49.363588376 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: debug.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/debug.h linux-2.4.29/drivers/isdn/sc/debug.h
+--- linux-2.4.29.old/drivers/isdn/sc/debug.h   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/debug.h       2005-03-22 15:06:49.378586096 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: debug.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/event.c linux-2.4.29/drivers/isdn/sc/event.c
+--- linux-2.4.29.old/drivers/isdn/sc/event.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/event.c       2005-03-22 15:06:49.394583664 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: event.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/init.c linux-2.4.29/drivers/isdn/sc/init.c
+--- linux-2.4.29.old/drivers/isdn/sc/init.c    2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/init.c        2005-03-22 15:06:49.432577888 +0100
+@@ -514,6 +514,15 @@
+       schedule_timeout(HZ);
+       sig = readl(rambase + SIG_OFFSET);
+       pr_debug("Looking for a signature, got 0x%x\n", sig);
++#if 0
++/*
++ * For Gary: 
++ * If it's a timing problem, it should be gone with the above schedule()
++ * Another possible reason may be the missing volatile in the original
++ * code. readl() does this for us.
++ */
++      printk("");     /* Hack! Doesn't work without this !!!??? */
++#endif
+       if(sig == SIGNATURE)
+               return PRI_BOARD;
+@@ -525,6 +534,9 @@
+       schedule_timeout(HZ);
+       sig = readl(rambase + SIG_OFFSET);
+       pr_debug("Looking for a signature, got 0x%x\n", sig);
++#if 0
++      printk("");     /* Hack! Doesn't work without this !!!??? */
++#endif
+       if(sig == SIGNATURE)
+               return BRI_BOARD;
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/interrupt.c linux-2.4.29/drivers/isdn/sc/interrupt.c
+--- linux-2.4.29.old/drivers/isdn/sc/interrupt.c       2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/interrupt.c   2005-03-22 15:06:49.447575608 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: interrupt.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/ioctl.c linux-2.4.29/drivers/isdn/sc/ioctl.c
+--- linux-2.4.29.old/drivers/isdn/sc/ioctl.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/ioctl.c       2005-03-22 15:06:49.463573176 +0100
+@@ -23,6 +23,9 @@
+ extern board *adapter[];
++#if 0
++static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" };
++#endif
+ int GetStatus(int card, boardInfo *);
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/message.c linux-2.4.29/drivers/isdn/sc/message.c
+--- linux-2.4.29.old/drivers/isdn/sc/message.c 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/message.c     2005-03-22 15:06:49.478570896 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: message.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * functions for sending and receiving control messages
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/message.h linux-2.4.29/drivers/isdn/sc/message.h
+--- linux-2.4.29.old/drivers/isdn/sc/message.h 2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/message.h     2005-03-22 15:06:49.495568312 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: message.h,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/packet.c linux-2.4.29/drivers/isdn/sc/packet.c
+--- linux-2.4.29.old/drivers/isdn/sc/packet.c  2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/packet.c      2005-03-22 15:06:49.514565424 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: packet.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/shmem.c linux-2.4.29/drivers/isdn/sc/shmem.c
+--- linux-2.4.29.old/drivers/isdn/sc/shmem.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/shmem.c       2005-03-22 15:06:49.560558432 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: shmem.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/sc/timer.c linux-2.4.29/drivers/isdn/sc/timer.c
+--- linux-2.4.29.old/drivers/isdn/sc/timer.c   2005-03-22 14:47:56.000000000 +0100
++++ linux-2.4.29/drivers/isdn/sc/timer.c       2005-03-22 15:06:49.575556152 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: timer.c,v 1.1.4.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam.h linux-2.4.29/drivers/isdn/tpam/tpam.h
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam.h  2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam.h      2005-03-22 15:06:49.648545056 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam.h,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: tpam.h,v 1.3 2001/09/24 13:23:12 kai Exp $
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_commands.c linux-2.4.29/drivers/isdn/tpam/tpam_commands.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_commands.c 2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_commands.c     2005-03-22 15:06:49.664542624 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_commands.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: tpam_commands.c,v 1.3 2001/09/24 13:23:12 kai Exp $
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_crcpc.c linux-2.4.29/drivers/isdn/tpam/tpam_crcpc.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_crcpc.c    2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_crcpc.c        2005-03-22 15:06:49.681540040 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_crcpc.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_hdlc.c linux-2.4.29/drivers/isdn/tpam/tpam_hdlc.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_hdlc.c     2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_hdlc.c 2005-03-22 15:06:49.702536848 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_hdlc.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id: tpam_hdlc.c,v 1.3 2001/09/24 13:23:12 kai Exp $
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_main.c linux-2.4.29/drivers/isdn/tpam/tpam_main.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_main.c     2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_main.c 2005-03-22 15:06:49.717534568 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_main.c,v 1.1.2.2 2001/12/09 18:45:14 kai Exp $
++/* $Id$
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver - main routines)
+  *
+@@ -254,7 +254,7 @@
+       name:           "tpam",
+       id_table:       tpam_pci_tbl,
+       probe:          tpam_probe,
+-      remove:         __devexit_p(tpam_remove),
++      remove:         tpam_remove,
+ };
+ static int __init tpam_init(void) {
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_memory.c linux-2.4.29/drivers/isdn/tpam/tpam_memory.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_memory.c   2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_memory.c       2005-03-22 15:06:49.734531984 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_memory.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver - Board Memory Access)
+  *
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_nco.c linux-2.4.29/drivers/isdn/tpam/tpam_nco.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_nco.c      2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_nco.c  2005-03-22 15:06:49.749529704 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_nco.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Turbo PAM ISDN driver for Linux. 
+  * (Kernel Driver - Low Level NCO Manipulation)
+diff -rNu linux-2.4.29.old/drivers/isdn/tpam/tpam_queues.c linux-2.4.29/drivers/isdn/tpam/tpam_queues.c
+--- linux-2.4.29.old/drivers/isdn/tpam/tpam_queues.c   2005-03-22 14:47:57.000000000 +0100
++++ linux-2.4.29/drivers/isdn/tpam/tpam_queues.c       2005-03-22 15:06:49.764527424 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam_queues.c,v 1.1.2.1 2001/11/20 14:19:37 kai Exp $
++/* $Id$
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+  *
+@@ -146,7 +146,6 @@
+               do {
+                       hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
+                       if (waiting_too_long++ > 0xfffffff) {
+-                              kfree_skb(skb); 
+                               spin_unlock(&card->lock);
+                               printk(KERN_ERR "TurboPAM(tpam_irq): "
+                                               "waiting too long...\n");
+diff -rNu linux-2.4.29.old/include/linux/b1lli.h linux-2.4.29/include/linux/b1lli.h
+--- linux-2.4.29.old/include/linux/b1lli.h     2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/b1lli.h 2005-03-22 15:06:49.881509640 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1lli.h,v 1.8.8.3 2001/09/23 22:25:05 kai Exp $
++/* $Id$
+  *
+  * ISDN lowlevel-module for AVM B1-card.
+  *
+diff -rNu linux-2.4.29.old/include/linux/b1pcmcia.h linux-2.4.29/include/linux/b1pcmcia.h
+--- linux-2.4.29.old/include/linux/b1pcmcia.h  2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/b1pcmcia.h      2005-03-22 15:06:49.862512528 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: b1pcmcia.h,v 1.1.8.2 2001/09/23 22:25:05 kai Exp $
++/* $Id$
+  *
+  * Exported functions of module b1pcmcia to be called by
+  * avm_cs card services module.
+diff -rNu linux-2.4.29.old/include/linux/capi.h linux-2.4.29/include/linux/capi.h
+--- linux-2.4.29.old/include/linux/capi.h      2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/capi.h  2005-03-22 15:06:49.922503408 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: capi.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+  * 
+  * CAPI 2.0 Interface for Linux
+  * 
+diff -rNu linux-2.4.29.old/include/linux/concap.h linux-2.4.29/include/linux/concap.h
+--- linux-2.4.29.old/include/linux/concap.h    2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/concap.h        2005-03-22 15:06:49.906505840 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: concap.h,v 1.2.8.1 2001/09/23 22:25:05 kai Exp $
++/* $Id: concap.h,v 1.3 2001/09/24 13:23:13 kai Exp $
+  *
+  * Copyright 1997 by Henner Eisen <eis@baty.hanse.de>
+  *
+@@ -11,6 +11,7 @@
+ #ifdef __KERNEL__
+ #include <linux/skbuff.h>
+ #include <linux/netdevice.h>
++#include <linux/isdn_compat.h>
+ /* Stuff to support encapsulation protocols genericly. The encapsulation
+    protocol is processed at the uppermost layer of the network interface.
+diff -rNu linux-2.4.29.old/include/linux/hysdn_if.h linux-2.4.29/include/linux/hysdn_if.h
+--- linux-2.4.29.old/include/linux/hysdn_if.h  2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/hysdn_if.h      2005-03-22 15:06:49.974495504 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: hysdn_if.h,v 1.1.8.3 2001/09/23 22:25:05 kai Exp $
++/* $Id$
+  *
+  * Linux driver for HYSDN cards
+  * ioctl definitions shared by hynetmgr and driver.
+diff -rNu linux-2.4.29.old/include/linux/isdn/tpam.h linux-2.4.29/include/linux/isdn/tpam.h
+--- linux-2.4.29.old/include/linux/isdn/tpam.h 2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/isdn/tpam.h     2005-03-22 15:06:49.947499608 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: tpam.h,v 1.1.2.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+  *
+  * Turbo PAM ISDN driver for Linux. (Kernel Driver)
+  *
+diff -rNu linux-2.4.29.old/include/linux/isdn.h linux-2.4.29/include/linux/isdn.h
+--- linux-2.4.29.old/include/linux/isdn.h      2005-03-22 14:47:31.000000000 +0100
++++ linux-2.4.29/include/linux/isdn.h  2005-03-22 15:06:50.001491400 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id: isdn.h,v 1.125 2001/12/01 23:18:21 detabc Exp $
+  *
+  * Main header for the Linux ISDN subsystem (linklevel).
+  *
+@@ -14,6 +14,7 @@
+ #ifndef __ISDN_H__
+ #define __ISDN_H__
++#include <linux/isdn_compat.h>
+ #include <linux/ioctl.h>
+ #ifdef CONFIG_COBALT_MICRO_SERVER
+@@ -93,9 +94,15 @@
+ #define ISDN_LMSNLEN         255 /* Length of tty's Listen-MSN string */
+ #define ISDN_CMSGLEN       50  /* Length of CONNECT-Message to add for Modem */
++#ifdef BIG_PHONE_NUMBERS
+ #define ISDN_MSNLEN          32
+ #define NET_DV 0x06  /* Data version for isdn_net_ioctl_cfg   */
+ #define TTY_DV 0x06  /* Data version for iprofd etc.          */
++#else
++#define ISDN_MSNLEN          20
++#define NET_DV 0x05  /* Data version for isdn_net_ioctl_cfg   */
++#define TTY_DV 0x05  /* Data version for iprofd etc.          */
++#endif
+ #define INF_DV 0x01  /* Data version for /dev/isdninfo        */
+@@ -187,6 +194,61 @@
+ #define ISDN_MINOR_PPPMAX   (128 + (ISDN_MAX_CHANNELS-1))
+ #define ISDN_MINOR_STATUS   255
++#ifndef CONFIG_ISDN_WITH_ABC
++#undef CONFIG_ISDN_WITH_ABC_CALLB
++#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
++#undef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
++#undef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++#undef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
++#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++#else /* CONFIG_ISDN_WITH_ABC */
++#include <linux/isdn_dwabc.h>
++
++
++typedef struct DWABCJIFFIES {
++
++      u_long  msec_1000;
++      u_long  msec_500;
++      u_long  msec_400;
++      u_long  msec_200;
++      u_long  msec_100;
++
++} DWABCJIFFIES;
++
++
++#ifdef CONFIG_ISDN_WITH_ABC_NEED_DWSJIFFIES
++DWABCJIFFIES isdn_dwabc_jiffies;
++#else
++extern DWABCJIFFIES isdn_dwabc_jiffies;
++#endif
++#define dwsjiffies (isdn_dwabc_jiffies.msec_1000)
++
++#define ISDN_DW_ABC_FLAG_UNUSED00001          0x00000001L
++#define ISDN_DW_ABC_FLAG_NO_UDP_CHECK         0x00000002L
++#define ISDN_DW_ABC_FLAG_NO_UDP_HANGUP                0x00000004L
++#define ISDN_DW_ABC_FLAG_NO_UDP_DIAL          0x00000008L
++#define ISDN_DW_ABC_FLAG_UNUSED00010          0x00000010L
++#define ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER      0x00000020L
++#define ISDN_DW_ABC_FLAG_NO_CH_EXTINUSE               0x00000040L
++#define ISDN_DW_ABC_FLAG_NO_CONN_ERROR                0x00000080L
++#define ISDN_DW_ABC_FLAG_BSD_COMPRESS         0x00000100L
++#define ISDN_DW_ABC_FLAG_NO_LCR                               0x00000200L
++#define ISDN_DW_ABC_FLAG_LEASED_LINE          0x00001000L
++
++#define ISDN_DW_ABC_IFFLAG_NODCHAN                    0x00000001L
++#define ISDN_DW_ABC_IFFLAG_BSDAKTIV                   0x00000002L
++
++#define ISDN_DW_ABC_BITLOCK_SEND                      0
++#define ISDN_DW_ABC_BITLOCK_RECEIVE                   1
++
++#endif /* CONFIG_ISDN_WITH_ABC */
++
++
++
+ #ifdef CONFIG_ISDN_PPP
+ #ifdef CONFIG_ISDN_PPP_VJ
+@@ -204,9 +266,11 @@
+ #  include <linux/concap.h>
+ #endif
++#ifdef HAVE_DEVFS_FS
+ #ifdef CONFIG_DEVFS_FS
+ #  include <linux/devfs_fs_kernel.h>
+ #endif
++#endif /* HAVE_DEVFS_FS */
+ #include <linux/isdnif.h>
+@@ -272,6 +336,12 @@
+ #define ISDN_NET_CALLBACK   0x04       /* activate callback                 */
+ #define ISDN_NET_CBHUP      0x08       /* hangup before callback            */
+ #define ISDN_NET_CBOUT      0x10       /* remote machine does callback      */
++#if 0
++/* Unused??? */
++#define ISDN_NET_CLONE      0x08       /* clone a tmp interface when called */
++#define ISDN_NET_TMP        0x10       /* tmp interface until getting an IP */
++#define ISDN_NET_DYNAMIC    0x20       /* this link is dynamically allocated */
++#endif
+ #define ISDN_NET_MAGIC      0x49344C02 /* for paranoia-checking             */
+@@ -386,6 +456,38 @@
+   char cisco_debserint;                       /* debugging flag of cisco hdlc with slarp */
+   struct timer_list cisco_timer;
+   struct tq_struct tqueue;
++#ifdef CONFIG_ISDN_WITH_ABC
++  ulong       dw_abc_flags;
++  ulong       dw_abc_if_flags;
++  int         dw_abc_inuse_secure;
++  ulong       dw_abc_dialstart;
++  int         dw_abc_old_onhtime;
++  int                 dw_abc_remote_version;
++  int         dw_abc_bitlocks;
++#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
++  char        dw_out_msn[ISDN_MSNLEN]; /* eaz for outgoing call if *out_msn != 0 */
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++  ulong                               dw_abc_lcr_callid;
++  ulong                               dw_abc_lcr_start_request;
++  ulong                               dw_abc_lcr_end_request;
++  isdn_ctrl                   *dw_abc_lcr_cmd;
++  struct ISDN_DWABC_LCR_IOCTL *dw_abc_lcr_io;
++#endif
++  ulong dw_abc_bchan_last_connect;
++#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR
++  short dw_abc_bchan_errcnt;
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
++  void *dw_abc_bsd_compressor;
++  void *dw_abc_bsd_stat_rx;
++  void *dw_abc_bsd_stat_tx;
++#endif
++  ulong       dw_abc_bsd_snd;
++  ulong       dw_abc_bsd_bsd_snd;
++  ulong       dw_abc_bsd_rcv;
++  ulong       dw_abc_bsd_bsd_rcv;
++#endif
+ } isdn_net_local;
+ /* the interface itself */
+@@ -608,12 +710,13 @@
+       int               tflags;                    /* Timer-Flags:               */
+       /*  see ISDN_TIMER_..defines  */
+       int               global_flags;
+-      infostruct        *infochain;                /* List of open info-devs.    */
+-      wait_queue_head_t info_waitq;               /* Wait-Queue for isdninfo    */
+       struct timer_list timer;                       /* Misc.-function Timer       */
+       int               chanmap[ISDN_MAX_CHANNELS];/* Map minor->device-channel  */
+       int               drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index    */
+       int               usage[ISDN_MAX_CHANNELS];  /* Used by tty/ip/voice       */
++#ifdef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
++      ulong                     dwabc_chan_external_inuse[ISDN_MAX_CHANNELS];
++#endif
+       char              num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
+       /* Remote number of active ch.*/
+       int               m_idx[ISDN_MAX_CHANNELS];  /* Index for mdm....          */
+@@ -631,6 +734,7 @@
+       isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
+       struct semaphore  sem;                       /* serialize list access*/
+       unsigned long     global_features;
++#ifdef HAVE_DEVFS_FS
+ #ifdef CONFIG_DEVFS_FS
+       devfs_handle_t devfs_handle_isdninfo;
+       devfs_handle_t devfs_handle_isdnctrl;
+@@ -640,10 +744,41 @@
+       devfs_handle_t devfs_handle_ipppX[ISDN_MAX_CHANNELS];
+ #endif
+ #endif /* CONFIG_DEVFS_FS */
++#endif /* HAVE_DEVFS_FS */
+ } isdn_dev;
+ extern isdn_dev *dev;
++#ifdef CONFIG_ISDN_WITH_ABC
++extern int isdn_auto_dial_helper(isdn_net_local *,struct sk_buff *,int);
++extern void dwisdn_nfw_send(isdn_net_local *lp,int drop_only);
++extern void isdn_net_unreachable(struct net_device *,struct sk_buff *,char *);
++extern void isdn_net_log_skb_dwabc(struct sk_buff *,isdn_net_local *,char *);
++extern void isdn_net_hangup(struct net_device *d);
++extern void isdn_dw_clear_if(ulong pm,isdn_net_local *);
++extern void isdn_dwabc_test_phone(isdn_net_local *);
++extern void isdn_dw_abc_init_func(void);
++extern void isdn_dw_abc_release_func(void);
++extern int isdn_dw_abc_reset_interface(isdn_net_local *,int);
++extern int dwabc_bsd_init(isdn_net_local *lp);
++extern void dwabc_bsd_free(isdn_net_local *lp);
++extern struct sk_buff *dwabc_bsd_compress(isdn_net_local *,struct sk_buff *,struct net_device *);
++extern void dwabc_bsd_first_gen(isdn_net_local *);
++extern struct sk_buff *dwabc_bsd_rx_pkt(isdn_net_local *,struct sk_buff *,struct net_device *);
++#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
++extern size_t isdn_dw_abc_lcr_readstat(char *,size_t);
++extern ulong isdn_dw_abc_lcr_call_number(isdn_net_local *,isdn_ctrl *);
++extern void isdn_dw_abc_lcr_open(void);
++extern void isdn_dw_abc_lcr_close(void);
++extern int isdn_dw_abc_lcr_ioctl(ulong);
++extern void isdn_dw_abc_lcr_clear(isdn_net_local *);
++extern int isdn_dw_abc_lcr_lock(void);
++extern void isdn_dw_abc_lcr_ulock(void);
++#endif
++#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK
++extern int dw_abc_udp_test(struct sk_buff *skb,struct net_device *ndev); 
++#endif
++#endif
+ #endif /* __KERNEL__ */
+diff -rNu linux-2.4.29.old/include/linux/isdn_compat.h linux-2.4.29/include/linux/isdn_compat.h
+--- linux-2.4.29.old/include/linux/isdn_compat.h       1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_compat.h   2005-03-22 15:06:50.017488968 +0100
+@@ -0,0 +1,261 @@
++/* $Id: isdn_compat.h,v 1.53 2001/09/24 13:23:13 kai Exp $
++ *
++ * Linux ISDN subsystem
++ * Compatibility for various Linux kernel versions
++ *
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ */
++
++#ifndef _LINUX_ISDN_COMPAT_H
++#define _LINUX_ISDN_COMPAT_H
++
++#ifdef __KERNEL__
++
++#ifndef ISDN_COMPAT_NOT_GENERIC
++/* when using std2kern -u, this part is left out and instead provided
++   by the .ctrl files */
++
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,18)
++
++#define set_current_state(sta) (current->state = sta)
++#define module_init(x)        int init_module(void) { return x(); }
++#define module_exit(x)        void cleanup_module(void) { x(); }
++#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); *(int *)0 = 0; } while (0)
++#define init_MUTEX(x)                         *(x)=MUTEX
++#define init_MUTEX_LOCKED(x)                  *(x)=MUTEX_LOCKED
++#define __devinit
++#define __devinitdata
++
++#else /* 2.2.18 and later */
++
++#define COMPAT_HAS_NEW_SETUP
++#define COMPAT_HAS_NEW_WAITQ
++
++#endif
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
++
++#define dev_kfree_skb_irq(a) dev_kfree_skb(a)
++#define dev_kfree_skb_any(a) dev_kfree_skb(a)
++#define COMPAT_HAS_2_2_PCI
++#define get_pcibase(ps, nr) ps->base_address[nr]
++#define pci_resource_start_io(pdev, nr) ((pdev)->base_address[nr] & PCI_BASE_ADDRESS_IO_MASK)
++#define pci_resource_start_mem(pdev, nr) ((pdev)->base_address[nr] & PCI_BASE_ADDRESS_MEM_MASK)
++#define pci_get_sub_vendor(pdev, id)  pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &id)
++#define pci_get_sub_system(pdev, id)  pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &id)
++
++#define __exit
++#define __devinit
++#define __devinitdata
++
++#define net_device device
++#define COMPAT_NO_SOFTNET
++#define netif_running(d) test_bit(LINK_STATE_START, &d->state)
++#define COMPAT_NEED_MPPP_DEFS
++#define spin_lock_bh(lock)
++#define spin_unlock_bh(lock)
++#define COMPAT_NEED_SPIN_LOCK_BH
++#define i_count_read(ic) ic
++#define i_count_inc(ic)  ic++
++#define COMPAT_USE_MODCOUNT_LOCK
++#define devfs_register_chrdev(m,n,f) register_chrdev(m,n,f)
++#define devfs_unregister_chrdev(m,n) unregister_chrdev(m,n)
++#define COMPAT_NEED_PCI_IDS
++#define in_irq() (local_irq_count[smp_processor_id()] != 0)
++
++#else /* 2.4.0 and later */
++
++#define pci_resource_start_io(pdev, nr) pci_resource_start(pdev, nr)
++#define pci_resource_start_mem(pdev, nr) pci_resource_start(pdev, nr)
++#define get_pcibase(ps, nr) ps->resource[nr].start
++#define pci_get_sub_system(pdev, id)  id = pdev->subsystem_device
++#define pci_get_sub_vendor(pdev, id)  id = pdev->subsystem_vendor
++
++#define BIG_PHONE_NUMBERS
++#define COMPAT_HAS_ISA_IOREMAP
++#define i_count_read(ic) atomic_read(&ic)
++#define i_count_inc(ic)  atomic_inc(&ic)
++#define COMPAT_HAS_FILEOP_OWNER
++#define COMPAT_HAVE_NEW_FILLDIR
++#define COMPAT_has_fileops_in_inode
++#define COMPAT_HAS_init_special_inode
++#define COMPAT_d_alloc_root_one_parameter
++#define HAVE_DEVFS_FS
++#define COMPAT_HAS_SCHEDULE_TASK
++#define COMPAT_HAS_USB_IDTAB
++
++#endif
++
++#endif /* ISDN_COMPAT_GENERIC */
++
++#ifdef COMPAT_HAS_2_2_PCI 
++#include <linux/pci.h>
++#ifdef __powerpc__
++static inline int pci_enable_device(struct pci_dev *dev)
++{
++      u16 cmd;
++      pci_read_config_word(dev, PCI_COMMAND, &cmd);
++      cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_SERR;
++      cmd &= ~PCI_COMMAND_FAST_BACK;
++      pci_write_config_word(dev, PCI_COMMAND, cmd);
++      return(0);
++}
++#else
++static inline int pci_enable_device(struct pci_dev *dev)
++{
++      return 0;
++}
++#endif /* __powerpc__ */
++
++#define PCI_ANY_ID (~0)
++
++/* as this is included multiple times, we make it inline */
++
++static inline struct pci_dev * pci_find_subsys(unsigned int vendor, unsigned int device,
++                                      unsigned int ss_vendor, unsigned int ss_device,
++                                      struct pci_dev *from)
++{
++      unsigned short subsystem_vendor, subsystem_device;
++
++      while ((from = pci_find_device(vendor, device, from))) {
++              pci_read_config_word(from, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
++              pci_read_config_word(from, PCI_SUBSYSTEM_ID, &subsystem_device);
++              if ((ss_vendor == PCI_ANY_ID || subsystem_vendor == ss_vendor) &&
++                  (ss_device == PCI_ANY_ID || subsystem_device == ss_device))
++                      return from;
++      }
++      return NULL;
++}
++#endif
++
++#ifdef COMPAT_NO_SOFTNET
++#include <linux/netdevice.h>
++
++/*
++ * Tell upper layers that the network device is ready to xmit more frames.
++ */
++static void __inline__ netif_wake_queue(struct net_device * dev)
++{
++      dev->tbusy = 0;
++      mark_bh(NET_BH);
++}
++
++/*
++ * called during net_device open()
++ */
++static void __inline__ netif_start_queue(struct net_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 net_device * dev)
++{
++      dev->tbusy = 1;
++}
++
++#endif /* COMPAT_NO_SOFTNET */
++
++#ifndef COMPAT_HAS_NEW_WAITQ
++typedef struct wait_queue wait_queue_t;
++typedef struct wait_queue *wait_queue_head_t;
++
++#define DECLARE_WAITQUEUE(wait, current)      struct wait_queue wait = { current, NULL }
++#define DECLARE_WAIT_QUEUE_HEAD(wait)         wait_queue_head_t wait
++#define init_waitqueue_head(x)                        *(x)=NULL
++#define init_waitqueue_entry(q,p)             ((q)->task)=(p)
++#endif /* COMPAT_HAS_NEW_WAITQ */
++
++#ifdef COMPAT_NEED_PCI_IDS
++
++#define PCI_ANY_ID (~0)
++
++#define PCI_VENDOR_ID_DYNALINK          0x0675
++#define PCI_DEVICE_ID_DYNALINK_IS64PH   0x1702
++
++#define PCI_DEVICE_ID_WINBOND2_6692   0x6692
++
++#define PCI_DEVICE_ID_PLX_R685                0x1030
++#define PCI_DEVICE_ID_PLX_DJINN_ITOO    0x1151
++#define PCI_DEVICE_ID_PLX_R753          0x1152
++
++#define PCI_VENDOR_ID_ELSA            0x1048
++#define PCI_DEVICE_ID_ELSA_MICROLINK  0x1000
++#define PCI_DEVICE_ID_ELSA_QS3000     0x3000
++
++#define PCI_VENDOR_ID_EICON           0x1133
++#define PCI_DEVICE_ID_EICON_DIVA20PRO 0xe001
++#define PCI_DEVICE_ID_EICON_DIVA20    0xe002
++#define PCI_DEVICE_ID_EICON_DIVA20PRO_U       0xe003
++#define PCI_DEVICE_ID_EICON_DIVA20_U  0xe004
++#define PCI_DEVICE_ID_EICON_DIVA201   0xe005
++#define PCI_DEVICE_ID_EICON_MAESTRA   0xe010
++#define PCI_DEVICE_ID_EICON_MAESTRAQ  0xe012
++#define PCI_DEVICE_ID_EICON_MAESTRAQ_U        0xe013
++#define PCI_DEVICE_ID_EICON_MAESTRAP  0xe014
++ 
++#define PCI_VENDOR_ID_CCD             0x1397
++#define PCI_DEVICE_ID_CCD_2BD0                0x2BD0
++#define PCI_DEVICE_ID_CCD_B000                0xB000
++#define PCI_DEVICE_ID_CCD_B006                0xB006
++#define PCI_DEVICE_ID_CCD_B007                0xB007
++#define PCI_DEVICE_ID_CCD_B008                0xB008
++#define PCI_DEVICE_ID_CCD_B009                0xB009
++#define PCI_DEVICE_ID_CCD_B00A                0xB00A
++#define PCI_DEVICE_ID_CCD_B00B                0xB00B
++#define PCI_DEVICE_ID_CCD_B00C                0xB00C
++#define PCI_DEVICE_ID_CCD_B100                0xB100
++
++#define PCI_VENDOR_ID_ASUSTEK           0x1043   
++#define PCI_DEVICE_ID_ASUSTEK_0675      0x0675
++
++#define PCI_VENDOR_ID_BERKOM                  0x0871
++#define PCI_DEVICE_ID_BERKOM_A1T              0xFFA1
++#define PCI_DEVICE_ID_BERKOM_T_CONCEPT          0xFFA2
++#define PCI_DEVICE_ID_BERKOM_A4T              0xFFA4
++#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO      0xFFA8
++
++#define PCI_DEVICE_ID_SATSAGEM_NICCY  0x1016
++
++#define PCI_DEVICE_ID_TIGERJET_100    0x0002
++
++#define PCI_VENDOR_ID_ANIGMA          0x1051
++#define PCI_DEVICE_ID_ANIGMA_MC145575 0x0100
++
++#define PCI_VENDOR_ID_ZOLTRIX         0x15b0
++#define PCI_DEVICE_ID_ZOLTRIX_2BD0    0x2BD0
++
++#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E        0x0070
++#define PCI_DEVICE_ID_DIGI_DF_M_E     0x0071
++#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A        0x0072
++#define PCI_DEVICE_ID_DIGI_DF_M_A     0x0073
++
++#define PCI_DEVICE_ID_AVM_B1          0x0700
++#define PCI_DEVICE_ID_AVM_C4          0x0800
++#define PCI_DEVICE_ID_AVM_C2          0x1100
++#define PCI_DEVICE_ID_AVM_T1          0x1200
++
++#define PCI_VENDOR_ID_HYPERCOPE               0x1365
++#define PCI_DEVICE_ID_HYPERCOPE_PLX   0x9050
++#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO     0x0104
++#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO         0x0106
++#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO        0x0107
++#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2       0x0108
++#define PCI_SUBDEVICE_ID_HYPERCOPE_PLEXUS       0x0109
++
++#define PCI_VENDOR_ID_ABOCOM            0x13D1
++#define PCI_DEVICE_ID_ABOCOM_2BD1       0x2BD1
++
++#endif /* COMPAT_NEED_PCI_IDS */
++
++#endif /* __KERNEL__ */
++#endif /* _LINUX_ISDN_COMPAT_H */
+diff -rNu linux-2.4.29.old/include/linux/isdn_divertif.h linux-2.4.29/include/linux/isdn_divertif.h
+--- linux-2.4.29.old/include/linux/isdn_divertif.h     2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_divertif.h 2005-03-22 15:06:50.032486688 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_divertif.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+  *
+  * Header for the diversion supplementary interface for i4l.
+  *
+@@ -14,7 +14,7 @@
+ /***********************************************************/
+ /* magic value is also used to control version information */
+ /***********************************************************/
+-#define DIVERT_IF_MAGIC 0x25873401
++#define DIVERT_IF_MAGIC 0x25873402
+ #define DIVERT_CMD_REG  0x00  /* register command */
+ #define DIVERT_CMD_REL  0x01  /* release command */
+ #define DIVERT_NO_ERR   0x00  /* return value no error */
+@@ -34,6 +34,7 @@
+     int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */
+     char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */
+     int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */
++    int (*dial_net_name)(char *); /* force dial of a ll net interface  */
+   } isdn_divert_if;
+ /*********************/
+diff -rNu linux-2.4.29.old/include/linux/isdn_dwabc.h linux-2.4.29/include/linux/isdn_dwabc.h
+--- linux-2.4.29.old/include/linux/isdn_dwabc.h        1970-01-01 01:00:00.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_dwabc.h    2005-03-22 15:06:50.048484256 +0100
+@@ -0,0 +1,84 @@
++/* $Id: isdn_dwabc.h,v 1.9 2001/09/26 20:32:08 detabc Exp $
++ *
++ * Header for the Linux ISDN abc-extension.
++ *
++ * Copyright           by abc GmbH
++ *                     written by Detlef Wengorz <detlefw@isdn4linux.de>
++ * 
++ * This software may be used and distributed according to the terms
++ * of the GNU General Public License, incorporated herein by reference.
++ *
++ */
++
++#ifndef ISDN_DWABC_H
++#define ISDN_DWABC_H
++
++#ifdef __KERNEL__
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/spinlock.h>
++#include <linux/errno.h>
++
++
++typedef struct ISDN_DWSPINLOCK {
++
++      spinlock_t      spin;
++      short           owner;
++      short           my_flags;
++      ulong           irq_flags;
++
++} ISDN_DWSPINLOCK;
++
++#define ISDN_DWSPIN_UNLOCKED                          \
++      (ISDN_DWSPINLOCK) {                                             \
++              spin:           SPIN_LOCK_UNLOCKED,             \
++              owner:          -1,                                             \
++              my_flags:       0,                                              \
++              irq_flags:      0,                                              \
++      }
++
++#define ISDN_DWSPIN_INIT(x)                   \
++                      do { *(x) = ISDN_DWSPIN_UNLOCKED; } while(0);
++
++static __inline__ int isdn_dwspin_trylock(ISDN_DWSPINLOCK *spin)
++{
++      if(!spin_trylock(&spin->spin)) {
++
++              if(spin->owner == smp_processor_id())
++                      return(-EAGAIN);
++
++              spin_lock(&spin->spin);
++      }
++
++      spin->owner = smp_processor_id();
++      return(0);
++}
++
++static __inline__ void isdn_dwspin_unlock(ISDN_DWSPINLOCK *spin)
++{
++      spin->owner = -1;
++      spin_unlock(&spin->spin);
++}
++
++
++#else
++#include <sys/types.h>
++#endif
++
++#define DWABC_LCR_FLG_NEWNUMBER               0x00000001L
++#define DWABC_LCR_FLG_DISABLE         0x00000002L
++#define DWABC_LCR_FLG_NEWHUPTIME      0x00000004L
++
++
++struct ISDN_DWABC_LCR_IOCTL {
++
++      int     lcr_ioctl_sizeof;       /* mustbe sizeof(ISDN_DWABC_LCR_IOCTL)  */
++      u_short lcr_ioctl_onhtime;      /* new hanguptime                                               */
++      u_long  lcr_ioctl_callid;       /* callid from lcr-subsystem                    */
++      u_long  lcr_ioctl_flags;        /* see above                                                    */
++      char    lcr_ioctl_nr[32];       /* new destination phonenumber                  */
++};
++
++#endif
+diff -rNu linux-2.4.29.old/include/linux/isdn_lzscomp.h linux-2.4.29/include/linux/isdn_lzscomp.h
+--- linux-2.4.29.old/include/linux/isdn_lzscomp.h      2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_lzscomp.h  2005-03-22 15:06:50.089478024 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdn_lzscomp.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id$
+  *
+  * Header for isdn_lzscomp.c
+  * Concentrated here to not mess up half a dozen kernel headers with code
+diff -rNu linux-2.4.29.old/include/linux/isdn_ppp.h linux-2.4.29/include/linux/isdn_ppp.h
+--- linux-2.4.29.old/include/linux/isdn_ppp.h  2005-03-22 14:47:31.000000000 +0100
++++ linux-2.4.29/include/linux/isdn_ppp.h      2005-03-22 15:06:50.116473920 +0100
+@@ -8,6 +8,7 @@
+ #ifndef _LINUX_ISDN_PPP_H
+ #define _LINUX_ISDN_PPP_H
++#include <linux/isdn_compat.h>
+ #define CALLTYPE_INCOMING 0x1
+ #define CALLTYPE_OUTGOING 0x2
+@@ -33,6 +34,11 @@
+ #define PPPIOCSCOMPRESSOR _IOW('t',135,int)
+ #define PPPIOCGIFNAME      _IOR('t',136, char [IFNAMSIZ] )
++#ifdef COMPAT_NEED_MPPP_DEFS
++#define PPP_MP          0x003d
++#define PPP_COMPFRAG    0x00fb
++#define PPP_CCPFRAG     0x80fb
++#endif
+ #define SC_MP_PROT       0x00000200
+ #define SC_REJ_MP_PROT   0x00000400
+@@ -65,9 +71,6 @@
+ #include <linux/config.h>
+-#ifdef CONFIG_IPPP_FILTER
+-#include <linux/filter.h>
+-#endif
+ #define DECOMP_ERR_NOMEM      (-10)
+@@ -226,10 +229,6 @@
+   unsigned char *cbuf;
+   struct slcompress *slcomp;
+ #endif
+-#ifdef CONFIG_IPPP_FILTER
+-  struct sock_fprog pass_filter;      /* filter for packets to pass */
+-  struct sock_fprog active_filter;    /* filter for pkts to reset idle */
+-#endif
+   unsigned long debug;
+   struct isdn_ppp_compressor *compressor,*decompressor;
+   struct isdn_ppp_compressor *link_compressor,*link_decompressor;
+diff -rNu linux-2.4.29.old/include/linux/isdnif.h linux-2.4.29/include/linux/isdnif.h
+--- linux-2.4.29.old/include/linux/isdnif.h    2005-03-22 14:47:31.000000000 +0100
++++ linux-2.4.29/include/linux/isdnif.h        2005-03-22 15:06:50.132471488 +0100
+@@ -1,4 +1,4 @@
+-/* $Id: isdnif.h,v 1.1.4.1 2001/11/20 14:19:38 kai Exp $
++/* $Id: isdnif.h,v 1.43 2002/02/09 21:19:11 keil Exp $
+  *
+  * Linux ISDN subsystem
+  * Definition of the interface between the subsystem and its low-level drivers.
+@@ -14,6 +14,7 @@
+ #ifndef __ISDNIF_H__
+ #define __ISDNIF_H__
++#include <linux/isdn_compat.h>
+ /*
+  * Values for general protocol-selection
+@@ -213,6 +214,8 @@
+ #define ISDN_STAT_FAXIND  276    /* FAX indications from HL-driver        */
+ #define ISDN_STAT_AUDIO   277    /* DTMF, DSP indications                 */
+ #define ISDN_STAT_DISCH   278    /* Disable/Enable channel usage          */
++#define ISDN_STAT_ALERT   279    /* Signal alerting                       */
++#define ISDN_STAT_PROCEED 280    /* Signal proceeding                     */
+ /*
+  * Audio commands
+diff -rNu linux-2.4.29.old/include/linux/kernelcapi.h linux-2.4.29/include/linux/kernelcapi.h
+--- linux-2.4.29.old/include/linux/kernelcapi.h        2005-03-22 14:47:32.000000000 +0100
++++ linux-2.4.29/include/linux/kernelcapi.h    2005-03-22 15:06:50.147469208 +0100
+@@ -1,12 +1,10 @@
+-/* $Id: kernelcapi.h,v 1.1.4.2 2002/01/28 18:25:10 kai Exp $
++/*
++ * $Id: kernelcapi.h,v 1.9 2000/11/28 09:34:02 kai Exp $
+  * 
+  * Kernel CAPI 2.0 Interface for Linux
+  * 
+  * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
+  * 
+- * This software may be used and distributed according to the terms
+- * of the GNU General Public License, incorporated herein by reference.
+- *
+  */
+ #ifndef __KERNELCAPI_H__
diff --git a/openwrt/package/linux/kernel-patches/401-hfc-usb-backport-i4l-cvs b/openwrt/package/linux/kernel-patches/401-hfc-usb-backport-i4l-cvs
new file mode 100644 (file)
index 0000000..4ef20fa
--- /dev/null
@@ -0,0 +1,2663 @@
+diff -rNu linux-2.4.29.old/drivers/Makefile linux-2.4.29/drivers/Makefile
+--- linux-2.4.29.old/drivers/Makefile  2005-03-22 14:47:41.000000000 +0100
++++ linux-2.4.29/drivers/Makefile      2005-03-22 15:15:20.012957872 +0100
+@@ -38,7 +38,7 @@
+ subdir-$(CONFIG_MD)           += md
+ subdir-$(CONFIG_IEEE1394)     += ieee1394
+ subdir-$(CONFIG_PNP)          += pnp
+-subdir-$(CONFIG_ISDN_BOOL)    += isdn
++subdir-$(CONFIG_ISDN)         += isdn
+ subdir-$(CONFIG_ATM)          += atm
+ subdir-$(CONFIG_FC4)          += fc4
+diff -rNu linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c linux-2.4.29/drivers/isdn/hisax/hfc_usb.c
+--- linux-2.4.29.old/drivers/isdn/hisax/hfc_usb.c      2005-03-22 15:13:58.233390256 +0100
++++ linux-2.4.29/drivers/isdn/hisax/hfc_usb.c  2005-03-22 15:14:57.475384104 +0100
+@@ -1,13 +1,11 @@
+-/* $Id: hfc_usb.c,v 2.3 2001/07/06 21:30:11 werner Exp $
++/*
++ * hfc_usb.c
+  *
++ * modular HiSax ISDN driver for Colognechip HFC-USB chip
+  *
+- *
+- * Author       (C) 2001 Werner Cornelius (werner@isdn-development.de)
+- *              modular driver for Colognechip HFC-USB chip
+- *              as plugin for HiSax isdn driver
+- *              type approval valid for HFC-S USB based TAs
+- *
+- * Copyright 2001  by Werner Cornelius (werner@isdn-development.de)
++ * Authors : Peter Sprenger  (sprenger@moving-byters.de)
++ *           Martin Bachem   (info@colognechip.com)
++ *           based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.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
+@@ -23,70 +21,90 @@
+  * along with this program; if not, write to the Free Software
+  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
+- */
++ * 2005_Mar_16 grsch
++ *      ported 2.6.8 hfc_usb.c to 2.4.20 format
++ *      Gregor Schaffrath <gschaff@ran-dom.org>
++*/
++
+ #include <linux/types.h>
+ #include <linux/stddef.h>
+ #include <linux/timer.h>
+ #include <linux/config.h>
+-#include <linux/isdn_compat.h>
+ #include <linux/init.h>
+ #include "hisax.h"
+ #include <linux/module.h>
+ #include <linux/kernel_stat.h>
+-#include <linux/tqueue.h>
+ #include <linux/usb.h>
+ #include <linux/kernel.h>
+ #include <linux/smp_lock.h>
+ #include <linux/sched.h>
++#include "hisax_if.h"
+ #include "hisax_loadable.h"
++static const char *hfcusb_revision = "4.0";
++
++/*
++      to enable much mire debug messages in this driver, define
++                      VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG
++      below
++*/
++
++#define VERBOSE_USB_DEBUG 
++#define VERBOSE_ISDN_DEBUG 
++
+ #define INCLUDE_INLINE_FUNCS
++#define TRUE  1
++#define FALSE 0
++
++
+ /***********/
+ /* defines */
+ /***********/
+-#define HFC_CTRL_TIMEOUT 5    /* 5ms timeout writing/reading regs */
+-#define HFC_TIMER_T3     7000 /* timeout for l1 activation timer */
+-
+-#define HFCUSB_L1_STATECHANGE   0     /* L1 state changed */
+-#define HFCUSB_L1_DRX           1     /* D-frame received */
+-#define HFCUSB_L1_ERX           2     /* E-frame received */
+-#define HFCUSB_L1_DTX           4     /* D-frames completed */
+-
+-#define MAX_BCH_SIZE        2048      /* allowed B-channel packet size */
+-
+-#define HFCUSB_RX_THRESHOLD 64        /* threshold for fifo report bit rx */
+-#define HFCUSB_TX_THRESHOLD 64        /* threshold for fifo report bit tx */
+-
+-#define HFCUSB_CHIP_ID    0x16        /* Chip ID register index */
+-#define HFCUSB_CIRM       0x00        /* cirm register index */
+-#define HFCUSB_USB_SIZE   0x07        /* int length register */
+-#define HFCUSB_USB_SIZE_I 0x06        /* iso length register */
+-#define HFCUSB_F_CROSS    0x0b        /* bit order register */
+-#define HFCUSB_CLKDEL     0x37        /* bit delay register */
+-#define HFCUSB_CON_HDLC   0xfa        /* channel connect register */
++#define HFC_CTRL_TIMEOUT      20  //(HZ * USB_CTRL_GET_TIMEOUT)
++/* 5ms timeout writing/reading regs */
++#define HFC_TIMER_T3     8000      /* timeout for l1 activation timer */
++#define HFC_TIMER_T4     500       /* time for state change interval */
++
++#define HFCUSB_L1_STATECHANGE   0  /* L1 state changed */
++#define HFCUSB_L1_DRX           1  /* D-frame received */
++#define HFCUSB_L1_ERX           2  /* E-frame received */
++#define HFCUSB_L1_DTX           4  /* D-frames completed */
++
++#define MAX_BCH_SIZE        2048   /* allowed B-channel packet size */
++
++#define HFCUSB_RX_THRESHOLD 64     /* threshold for fifo report bit rx */
++#define HFCUSB_TX_THRESHOLD 64     /* threshold for fifo report bit tx */
++
++#define HFCUSB_CHIP_ID    0x16     /* Chip ID register index */
++#define HFCUSB_CIRM       0x00     /* cirm register index */
++#define HFCUSB_USB_SIZE   0x07     /* int length register */
++#define HFCUSB_USB_SIZE_I 0x06     /* iso length register */
++#define HFCUSB_F_CROSS    0x0b     /* bit order register */
++#define HFCUSB_CLKDEL     0x37     /* bit delay register */
++#define HFCUSB_CON_HDLC   0xfa     /* channel connect register */
+ #define HFCUSB_HDLC_PAR   0xfb
+-#define HFCUSB_SCTRL      0x31        /* S-bus control register (tx) */
+-#define HFCUSB_SCTRL_E    0x32        /* same for E and special funcs */
+-#define HFCUSB_SCTRL_R    0x33        /* S-bus control register (rx) */
+-#define HFCUSB_F_THRES    0x0c        /* threshold register */
+-#define HFCUSB_FIFO       0x0f        /* fifo select register */
+-#define HFCUSB_F_USAGE    0x1a        /* fifo usage register */
++#define HFCUSB_SCTRL      0x31     /* S-bus control register (tx) */
++#define HFCUSB_SCTRL_E    0x32     /* same for E and special funcs */
++#define HFCUSB_SCTRL_R    0x33     /* S-bus control register (rx) */
++#define HFCUSB_F_THRES    0x0c     /* threshold register */
++#define HFCUSB_FIFO       0x0f     /* fifo select register */
++#define HFCUSB_F_USAGE    0x1a     /* fifo usage register */
+ #define HFCUSB_MST_MODE0  0x14
+ #define HFCUSB_MST_MODE1  0x15
+ #define HFCUSB_P_DATA     0x1f
+ #define HFCUSB_INC_RES_F  0x0e
+ #define HFCUSB_STATES     0x30
+-#define HFCUSB_CHIPID 0x40    /* ID value of HFC-USB */
++#define HFCUSB_CHIPID 0x40         /* ID value of HFC-USB */
+ /******************/
+ /* fifo registers */
+ /******************/
+-#define HFCUSB_NUM_FIFOS   8  /* maximum number of fifos */
+-#define HFCUSB_B1_TX       0  /* index for B1 transmit bulk/int */
+-#define HFCUSB_B1_RX       1  /* index for B1 receive bulk/int */
++#define HFCUSB_NUM_FIFOS   8       /* maximum number of fifos */
++#define HFCUSB_B1_TX       0       /* index for B1 transmit bulk/int */
++#define HFCUSB_B1_RX       1       /* index for B1 receive bulk/int */
+ #define HFCUSB_B2_TX       2
+ #define HFCUSB_B2_RX       3
+ #define HFCUSB_D_TX        4
+@@ -94,198 +112,162 @@
+ #define HFCUSB_PCM_TX      6
+ #define HFCUSB_PCM_RX      7
+-/************/
+-/* LED mask */
+-/************/
+-#define LED_DRIVER         0x1
+-#define LED_L1             0x2
+-#define LED_BCH            0x4
++/*
++* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
++* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
++*/
++#define USB_INT               0
++#define USB_BULK      1
++#define USB_ISOC      2
++
++#define ISOC_PACKETS_D        8
++#define ISOC_PACKETS_B        8
++#define ISO_BUFFER_SIZE       128
++
++// ISO send definitions
++#define SINK_MAX      68
++#define SINK_MIN      48
++#define SINK_DMIN     12
++#define SINK_DMAX     18
++#define BITLINE_INF   (-64*8)
++
++
++
+ /**********/
+ /* macros */
+ /**********/
+-#define Write_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
+-#define Read_hfc(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
+-
+-#ifdef COMPAT_HAS_USB_IDTAB
+-/****************************************/
+-/* data defining the devices to be used */
+-/****************************************/
+-static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
+-      {USB_DEVICE(0x959, 0x2bd0)},    /* Colognechip ROM */
+-      {USB_DEVICE(0x7b0, 0x0006)},    /* USB TA 128 */
+-      {}                      /* end with an all-zeroes entry */
+-};
+-#endif
++#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT)
++#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
+ /*************************************************/
+ /* entry and size of output/input control buffer */
+ /*************************************************/
+ #define HFC_CTRL_BUFSIZE 32
+-typedef struct {
++typedef struct
++{
+       __u8 hfc_reg;           /* register number */
+       __u8 reg_val;           /* value to be written (or read) */
++      int action;         /* data for action handler */
++
+ } ctrl_buft;
++typedef struct
++{
++      int vendor;         // vendor id
++      int prod_id;        // product id
++      char *vend_name;    // vendor string
++      __u8 led_scheme;    // led display scheme
++      __u8 led_invert;    // invert led aux port settings
++      __u8 led_bits[8];   // array of 8 possible LED bitmask settings
++
++} vendor_data;
++
+ /***************************************************************/
+ /* structure defining input+output fifos (interrupt/bulk mode) */
+ /***************************************************************/
+-struct hfcusb_data;           /* forward definition */
+-typedef struct {
+-      int fifonum;            /* fifo index attached to this structure */
+-      __u8 fifo_mask;         /* mask for this fifo */
+-      int active;             /* fifo is currently active */
++
++struct usb_fifo;                      /* forward definition */
++typedef struct iso_urb_struct
++{
++      struct urb *purb;
++      __u8 buffer[ISO_BUFFER_SIZE];   /* buffer incoming/outgoing data */
++      struct usb_fifo *owner_fifo;    // pointer to owner fifo
++} iso_urb_struct;
++
++
++struct hfcusb_data;                   /* forward definition */
++typedef struct usb_fifo
++{
++      int fifonum;                    /* fifo index attached to this structure */
++      int active;                     /* fifo is currently active */
+       struct hfcusb_data *hfc;        /* pointer to main structure */
+-      int pipe;               /* address of endpoint */
+-      __u8 usb_maxlen;        /* maximum length for usb transfer */
+-      int max_size;           /* maximum size of receive/send packet */
+-      int transmode;          /* transparent mode selected */
+-      int framenum;           /* number of frame when last tx completed */
+-      int rx_offset;          /* offset inside rx buffer */
+-      int next_complete;      /* complete marker */
+-      __u8 *act_ptr;          /* pointer to next data */
+-      __u8 intervall;         /* interrupt interval */
+-      struct sk_buff *buff;   /* actual used buffer */
+-      urb_t urb;              /* transfer structure for usb routines */
+-      __u8 buffer[128];       /* buffer incoming/outgoing data */
++      int pipe;                       /* address of endpoint */
++      __u8 usb_packet_maxlen;         /* maximum length for usb transfer */
++      unsigned int max_size;          /* maximum size of receive/send packet */
++      __u8 intervall;                 /* interrupt interval */
++      struct sk_buff *skbuff;         /* actual used buffer */
++      struct urb *urb;                /* transfer structure for usb routines */
++      __u8 buffer[128];               /* buffer incoming/outgoing data */
++      int bit_line;                   /* how much bits are in the fifo? */
++
++      volatile __u8 usb_transfer_mode;/* switched between ISO and INT */
++      iso_urb_struct iso[2];          /* need two urbs to have one always for pending */
++      struct hisax_if *hif;           /* hisax interface */
++      int delete_flg;                 /* only delete skbuff once */
++      int last_urblen;                /* remember length of last packet */
++
+ } usb_fifo;
++
+ /*********************************************/
+ /* structure holding all data for one device */
+ /*********************************************/
+-typedef struct hfcusb_data {
+-      struct hisax_drvreg regd;       /* register data and callbacks */
+-      struct usb_device *dev; /* our device */
+-      int if_used;            /* used interface number */
+-      int alt_used;           /* used alternate config */
+-      int ctrl_paksize;       /* control pipe packet size */
++typedef struct hfcusb_data
++{
++      // HiSax Interface for loadable Layer1 drivers
++      struct hisax_d_if d_if;                 /* see hisax_if.h */
++      struct hisax_b_if b_if[2];              /* see hisax_if.h */
++      int protocol;
++      
++      struct usb_device *dev;                 /* our device */
++      int if_used;                            /* used interface number */
++      int alt_used;                           /* used alternate config */
++      int ctrl_paksize;                       /* control pipe packet size */
+       int ctrl_in_pipe, ctrl_out_pipe;        /* handles for control pipe */
++      int cfg_used;                           /* configuration index used */
++      int vend_idx;                           // vendor found
++
++      int b_mode[2];                          // B-channel mode
++
++      int l1_activated;                       // layer 1 activated
++
++      int packet_size,iso_packet_size;        
+       /* control pipe background handling */
+       ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE];  /* buffer holding queued data */
+-      volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt;       /* input/output pointer + count */
+-      urb_t ctrl_urb;         /* transfer structure for control channel */
+-      devrequest ctrl_write;  /* buffer for control write request */
+-      devrequest ctrl_read;   /* same for read request */
+-
+-      volatile __u8 dfifo_fill;       /* value read from tx d-fifo */
+-      volatile __u8 active_fifos;     /* fifos currently active as bit mask */
+-      volatile __u8 threshold_mask;   /* threshold actually reported */
+-      volatile __u8 service_request;  /* fifo needs service from task */
+-      volatile __u8 ctrl_fifo;        /* last selected fifo */
+-      volatile __u8 bch_enables;      /* or mask for sctrl_r and sctrl register values */
+-        volatile __u8 led_req;          /* request status of adapters leds */ 
+-        volatile __u8 led_act;          /* active status of adapters leds */ 
++      volatile int ctrl_in_idx, ctrl_out_idx,
++              ctrl_cnt;                       /* input/output pointer + count */
++      struct urb *ctrl_urb;                   /* transfer structure for control channel */
++
++      struct usb_ctrlrequest ctrl_write;      /* buffer for control write request */
++      struct usb_ctrlrequest ctrl_read;       /* same for read request */
++
++      __u8 led_state,led_new_data,led_b_active;
++
++      volatile __u8 threshold_mask;           /* threshold actually reported */
++      volatile __u8 bch_enables;              /* or mask for sctrl_r and sctrl register values */
++
+       usb_fifo fifos[HFCUSB_NUM_FIFOS];       /* structure holding all fifo data */
+-      /* layer 1 activation/deactivation handling */
+-      volatile __u8 l1_state; /* actual l1 state */
+-      volatile ulong l1_event;        /* event mask */
+-      struct tq_struct l1_tq; /* l1 bh structure */
+-      struct timer_list t3_timer;     /* timer for activation/deactivation */
+-      struct timer_list t4_timer;     /* timer for activation/deactivation */
++      volatile __u8 l1_state;                 /* actual l1 state */
++      struct timer_list t3_timer;             /* timer 3 for activation/deactivation */
++      struct timer_list t4_timer;             /* timer 4 for activation/deactivation */
++      struct timer_list led_timer;            /* timer flashing leds */
++
+ } hfcusb_data;
+-#if 0
+-static void
+-usb_dump_urb(purb_t purb)
+-{
+-      printk("urb                   :%p\n", purb);
+-      printk("next                  :%p\n", purb->next);
+-      printk("dev                   :%p\n", purb->dev);
+-      printk("pipe                  :%08X\n", purb->pipe);
+-      printk("status                :%d\n", purb->status);
+-      printk("transfer_flags        :%08X\n", purb->transfer_flags);
+-      printk("transfer_buffer       :%p\n", purb->transfer_buffer);
+-      printk("transfer_buffer_length:%d\n",
+-             purb->transfer_buffer_length);
+-      printk("actual_length         :%d\n", purb->actual_length);
+-      printk("setup_packet          :%p\n", purb->setup_packet);
+-      printk("start_frame           :%d\n", purb->start_frame);
+-      printk("number_of_packets     :%d\n", purb->number_of_packets);
+-      printk("interval              :%d\n", purb->interval);
+-      printk("error_count           :%d\n", purb->error_count);
+-      printk("context               :%p\n", purb->context);
+-      printk("complete              :%p\n", purb->complete);
+-}
+-#endif
+-/*************************************************************************/
+-/* bottom half handler for L1 activation/deactiavtaion + D-chan + E-chan */
+-/*************************************************************************/
+-static void
+-usb_l1d_bh(hfcusb_data * hfc)
+-{
++static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish);
++
+-      while (hfc->l1_event) {
+-              if (test_and_clear_bit
+-                  (HFCUSB_L1_STATECHANGE, &hfc->l1_event)) {
+-                      if (hfc->l1_state == 7)
+-                          hfc->led_req |= LED_L1;
+-                      else
+-                          hfc->led_req &= ~LED_L1;
+-                      if ((hfc->l1_state == 7) ||
+-                          (hfc->l1_state == 3))
+-                          hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+-                                             (hfc->l1_state ==
+-                                              7) ? (PH_ACTIVATE |
+-                                                    INDICATION)
+-                                             : (PH_DEACTIVATE | INDICATION),
+-                                             NULL);
+-              }
+-              if (test_and_clear_bit(HFCUSB_L1_DRX, &hfc->l1_event)) {
+-                      hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+-                                         PH_DATA | INDICATION,
+-                                         (void *) 0);
+-              }
+-              if (test_and_clear_bit(HFCUSB_L1_ERX, &hfc->l1_event)) {
+-                      hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+-                                         PH_DATA | INDICATION,
+-                                         (void *) 1);
+-              }
+-              if (test_and_clear_bit(HFCUSB_L1_DTX, &hfc->l1_event)) {
+-                      hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+-                                         PH_DATA | CONFIRM, NULL);
+-              }
+-      }                       /* while */
+-}                             /* usb_l1d_bh */
+ /******************************************************/
+ /* start next background transfer for control channel */
+ /******************************************************/
+-static void
+-ctrl_start_transfer(hfcusb_data * hfc)
++static void ctrl_start_transfer(hfcusb_data * hfc)
+ {
+-
+-      if (hfc->ctrl_cnt) {
+-              switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
+-                      case HFCUSB_F_USAGE:
+-                              hfc->ctrl_urb.pipe = hfc->ctrl_in_pipe;
+-                              hfc->ctrl_urb.setup_packet =
+-                                  (u_char *) & hfc->ctrl_read;
+-                              hfc->ctrl_urb.transfer_buffer_length = 1;
+-                              hfc->ctrl_read.index =
+-                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
+-                                  hfc_reg;
+-                              hfc->ctrl_urb.transfer_buffer =
+-                                  (char *) &hfc->dfifo_fill;
+-                              break;
+-
+-                      default:        /* write register */
+-                              hfc->ctrl_urb.pipe = hfc->ctrl_out_pipe;
+-                              hfc->ctrl_urb.setup_packet =
+-                                  (u_char *) & hfc->ctrl_write;
+-                              hfc->ctrl_urb.transfer_buffer = NULL;
+-                              hfc->ctrl_urb.transfer_buffer_length = 0;
+-                              hfc->ctrl_write.index =
+-                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
+-                                  hfc_reg;
+-                              hfc->ctrl_write.value =
+-                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
+-                                  reg_val;
+-                              break;
+-              }
+-              usb_submit_urb(&hfc->ctrl_urb); /* start transfer */
++      int err;
++      if(hfc->ctrl_cnt)
++      {
++              hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe;
++              hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write;
++              hfc->ctrl_urb->transfer_buffer = NULL;
++              hfc->ctrl_urb->transfer_buffer_length = 0;
++              hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
++              hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
++              err = usb_submit_urb(hfc->ctrl_urb);    /* start transfer */
++              printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err);
+       }
+ }                             /* ctrl_start_transfer */
+@@ -293,897 +275,1418 @@
+ /* queue a control transfer request */
+ /* return 0 on success.             */
+ /************************************/
+-static int
+-queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val)
++static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val,int action)
+ {
+       ctrl_buft *buf;
+-      if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+-              return (1);     /* no space left */
+-      buf = hfc->ctrl_buff + hfc->ctrl_in_idx;        /* pointer to new index */
++#ifdef VERBOSE_USB_DEBUG
++      printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val);
++#endif
++
++      if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)  return(1);          /* no space left */
++      buf = &hfc->ctrl_buff[hfc->ctrl_in_idx];        /* pointer to new index */
+       buf->hfc_reg = reg;
+       buf->reg_val = val;
++      buf->action=action;
+       if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
+               hfc->ctrl_in_idx = 0;   /* pointer wrap */
+       if (++hfc->ctrl_cnt == 1)
+               ctrl_start_transfer(hfc);
+-      return (0);
+-}                             /* queue_control_request */
++      return(0);
++}             /* queue_control_request */
+-/**************************************/
+-/* called when timer t3 or t4 expires */
+-/**************************************/
+-static void
+-l1_timer_expire(hfcusb_data * hfc)
+-{
+-    if (timer_pending(&hfc->t4_timer))
+-      del_timer(&hfc->t4_timer);
+-    queue_control_request(hfc, HFCUSB_STATES, 0x40);
+-    test_and_set_bit(HFCUSB_L1_STATECHANGE,
+-                   &hfc->l1_event);
+-    queue_task(&hfc->l1_tq, &tq_immediate);
+-    mark_bh(IMMEDIATE_BH);
+-} /* l1_timer_expire */
+-
+-/**************************************************/
+-/* (re)fills a tx-fifo urb. Queuing is done later */
+-/**************************************************/
+-static void
+-fill_tx_urb(usb_fifo * fifo)
+-{
+-      struct sk_buff *skb;
+-      long flags;
+-      int i, ii = 0;
+-
+-      fifo->urb.dev = fifo->hfc->dev;
+-      if ((fifo->buff)
+-          && (fifo->urb.transfer_buffer_length < fifo->usb_maxlen)) {
+-              switch (fifo->fifonum) {
+-                      case HFCUSB_B1_TX:
+-                      case HFCUSB_B2_TX:
+-                              skb = fifo->buff;
+-                              fifo->buff = NULL;
+-                              fifo->hfc->regd.bch_l1l2(fifo->hfc->regd.
+-                                                       arg_hisax,
+-                                                       (fifo->fifonum ==
+-                                                        HFCUSB_B1_TX) ? 0
+-                                                       : 1,
+-                                                       (PH_DATA |
+-                                                        CONFIRM),
+-                                                       (void *) skb);
+-                              fifo->hfc->service_request |=
+-                                  fifo->fifo_mask;
+-                              return;
+-                      case HFCUSB_D_TX:
+-                              dev_kfree_skb_any(fifo->buff);
+-                              fifo->buff = NULL;
+-                              save_flags(flags);
+-                              cli();
+-                              fifo->hfc->dfifo_fill = 0xff;   /* currently invalid data */
+-                              queue_control_request(fifo->hfc,
+-                                                    HFCUSB_FIFO,
+-                                                    HFCUSB_D_TX);
+-                              queue_control_request(fifo->hfc,
+-                                                    HFCUSB_F_USAGE, 0);
+-                              restore_flags(flags);
+-                              return;
+-                      default:
+-                              return; /* error, invalid fifo */
+-              }
++
++static int control_action_handler(hfcusb_data *hfc,int reg,int val,int action)
++{
++      if(!action) return(1);  // no action defined
++
++      return(0);
++}
++
++
++/***************************************************************/
++/* control completion routine handling background control cmds */
++/***************************************************************/
++static void ctrl_complete(struct urb *urb)
++{
++      hfcusb_data *hfc = (hfcusb_data *) urb->context;
++      ctrl_buft *buf;
++
++      printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt);
++      urb->dev = hfc->dev;
++      if(hfc->ctrl_cnt)
++      {
++              buf=&hfc->ctrl_buff[hfc->ctrl_out_idx];
++              control_action_handler(hfc,buf->hfc_reg,buf->reg_val,buf->action);
++
++              hfc->ctrl_cnt--;        /* decrement actual count */
++              if(++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0;      /* pointer wrap */
++
++              ctrl_start_transfer(hfc);       /* start next transfer */
++      }
++}                             /* ctrl_complete */
++
++
++
++#define LED_OFF      0   // no LED support
++#define LED_SCHEME1  1         // LED standard scheme
++#define LED_SCHEME2  2         // not used yet...
++
++#define LED_POWER_ON  1
++#define LED_POWER_OFF 2
++#define LED_S0_ON             3
++#define LED_S0_OFF            4
++#define LED_B1_ON             5
++#define LED_B1_OFF            6
++#define LED_B1_DATA           7
++#define LED_B2_ON             8
++#define LED_B2_OFF            9
++#define LED_B2_DATA      10
++
++#define LED_NORMAL   0         // LEDs are normal
++#define LED_INVERTED 1   // LEDs are inverted
++
++// time for LED flashing
++#define LED_TIME      250
++
++vendor_data vdata[]=
++{
++    {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}},     /* CologneChip Eval TA */
++      {0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1,  LED_INVERTED, {8,0x40,0x20,0x10}},  /* Billion TA */
++      {0x742, 0x2008, "Stollmann USB TA",             LED_SCHEME1,  LED_NORMAL,   {4,0,2,1}},           /* Stollmann TA */
++      {0x8e3, 0x0301, "Olitec USB RNIS",              LED_SCHEME1,  LED_NORMAL,   {2,0,1,4}},           /* Olitec TA  */
++      {0x675, 0x1688, "DrayTec USB ISDN TA",          LED_SCHEME1,  LED_NORMAL,   {4,0,2,1}},           /* Draytec TA */
++      {0x7fa, 0x0846, "Bewan Modem RNIS USB",         LED_SCHEME1,  LED_INVERTED, {8,0x40,0x20,0x10}},  /* Bewan TA   */
++      {0}                        // EOL element
++};
++                                                                              
++/***************************************************/
++/* write led data to auxport & invert if necessary */
++/***************************************************/
++static void write_led(hfcusb_data * hfc,__u8 led_state)
++{
++      if(led_state!=hfc->led_state)
++      {
++              hfc->led_state=led_state;
++              queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1);
++      }
++}
++
++/******************************************/
++/* invert B-channel LEDs if data is sent  */
++/******************************************/
++static void led_timer(hfcusb_data * hfc)
++{
++      static int cnt=0;
++      __u8 led_state=hfc->led_state;
++
++      if(cnt)
++      {
++              if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2];
++              if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3];
++      }
++      else
++      {
++              if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2];
++              if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3];
+       }
+-      /* check if new buffer needed */
+-      if (!fifo->buff) {
+-              switch (fifo->fifonum) {
+-                      case HFCUSB_B1_TX:
+-                              if (fifo->hfc->regd.bsk[0])
+-                                      fifo->buff = *fifo->hfc->regd.bsk[0];   /* B1-channel tx buffer */
++      write_led(hfc,led_state);
++      hfc->led_new_data=0;
++
++      cnt=!cnt;
++      // restart 4 hz timer
++      hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
++      if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
++}
++
++/**************************/
++/* handle LED requests    */
++/**************************/
++static void handle_led(hfcusb_data * hfc,int event)
++{
++      __u8 led_state=hfc->led_state;
++
++      // if no scheme -> no LED action
++      if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return;
++
++      switch(event)
++      {
++              case LED_POWER_ON:
++                                 led_state|=vdata[hfc->vend_idx].led_bits[0];
++                              break;
++              case LED_POWER_OFF: // no Power off handling
++                              break;
++              case LED_S0_ON:
++                                 led_state|=vdata[hfc->vend_idx].led_bits[1];
++                              break;
++              case LED_S0_OFF:
++                                 led_state&=~vdata[hfc->vend_idx].led_bits[1];
+                               break;
+-                      case HFCUSB_B2_TX:
+-                              if (fifo->hfc->regd.bsk[1])
+-                                      fifo->buff = *fifo->hfc->regd.bsk[1];   /* B2-channel tx buffer */
++              case LED_B1_ON:
++                                      hfc->led_b_active|=1;
+                               break;
+-                      case HFCUSB_D_TX:
+-                              if (fifo->hfc->regd.dsq)
+-                                      fifo->buff = skb_dequeue(fifo->hfc->regd.dsq);  /* D-channel tx queue */
++              case LED_B1_OFF:
++                                      hfc->led_b_active&=~1;
+                               break;
+-                      default:
+-                              return; /* error, invalid fifo */
++              case LED_B1_DATA:
++                                 hfc->led_new_data|=1;
++                              break;
++              case LED_B2_ON:
++                                 hfc->led_b_active|=2;
++                              break;
++              case LED_B2_OFF:
++                                      hfc->led_b_active&=~2;
++                              break;
++              case LED_B2_DATA:
++                                 hfc->led_new_data|=2;
++                              break;
++      }
++      
++      write_led(hfc,led_state);
++}
++
++/********************************/
++/* called when timer t3 expires */
++/********************************/
++static void l1_timer_expire_t3(hfcusb_data * hfc)
++{
++    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n");
++
++      hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
++#ifdef VERBOSE_USB_DEBUG
++      printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
++#endif
++      hfc->l1_activated=FALSE;
++      handle_led(hfc,LED_S0_OFF);
++}
++
++/********************************/
++/* called when timer t4 expires */
++/********************************/
++static void l1_timer_expire_t4(hfcusb_data * hfc)
++{
++    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n");
++
++      hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
++#ifdef VERBOSE_USB_DEBUG
++      printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
++#endif
++      hfc->l1_activated=FALSE;
++      handle_led(hfc,LED_S0_OFF);
++}
++
++/*****************************/
++/* handle S0 state changes   */
++/*****************************/
++static void state_handler(hfcusb_data * hfc,__u8 state)
++{
++      __u8 old_state;
++
++      old_state=hfc->l1_state;
++
++      // range check
++      if(state==old_state || state<1 || state>8) return;
++
++#ifdef VERBOSE_ISDN_DEBUG
++      printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state);
++#endif
++
++      if(state<4 || state==7 || state==8)
++      {
++        if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer);
++              //printk(KERN_INFO "HFC-USB: T3 deactivated\n");
++      }
++
++      if(state>=7)
++      {
++        if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer);
++              //printk(KERN_INFO "HFC-USB: T4 deactivated\n");
++      }
++
++      if(state==7 && !hfc->l1_activated)
++      {
++              hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL);
++              //printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n");
++              hfc->l1_activated=TRUE;
++              handle_led(hfc,LED_S0_ON);
++      }
++      else
++      if(state<=3 /* && activated*/)
++      {
++              if(old_state==7 || old_state==8)
++              {
++                      //printk(KERN_INFO "HFC-USB: T4 activated\n");
++                      hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000;
++                      if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer);
+               }
+-              if (!fifo->buff) {
+-                      fifo->active = 0;       /* we are inactive now */
+-                      fifo->hfc->active_fifos &= ~fifo->fifo_mask;
+-                      if (fifo->fifonum == HFCUSB_D_TX) {
+-                              test_and_set_bit(HFCUSB_L1_DTX,
+-                                               &fifo->hfc->l1_event);
+-                              queue_task(&fifo->hfc->l1_tq,
+-                                         &tq_immediate);
+-                              mark_bh(IMMEDIATE_BH);
+-                      }
+-                      return;
++              else
++              {
++                      hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
++                      //printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n");
++                      hfc->l1_activated=FALSE;
++                      handle_led(hfc,LED_S0_OFF);
+               }
+-              fifo->act_ptr = fifo->buff->data;       /* start of data */
+-              fifo->active = 1;
+-              ii = 1;
+-              fifo->hfc->active_fifos |= fifo->fifo_mask;
+-              fifo->hfc->service_request &= ~fifo->fifo_mask;
+-      }
+-      /* fillup the send buffer */
+-      i = fifo->buff->len - (fifo->act_ptr - fifo->buff->data);       /* remaining length */
+-      fifo->buffer[0] = !fifo->transmode;     /* not eof */
+-      if (i > (fifo->usb_maxlen - ii)) {
+-              i = fifo->usb_maxlen - ii;
+-      }
+-      if (i)
+-              memcpy(fifo->buffer + ii, fifo->act_ptr, i);
+-      fifo->urb.transfer_buffer_length = i + ii;
+-        fifo->rx_offset = ii;
+-}                             /* fill_tx_urb */
+-
+-/************************************************/
+-/* transmit completion routine for all tx fifos */
+-/************************************************/
+-static void
+-tx_complete(purb_t urb)
++      }
++
++      hfc->l1_state=state;
++}
++
++
++/* prepare iso urb */
++static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf,
++      int num_packets, int packet_size, int interval, usb_complete_t complete, void *context)
+ {
+-      usb_fifo *fifo = (usb_fifo *) urb->context;     /* pointer to our fifo */
++      int k;
+-      fifo->hfc->service_request &= ~fifo->fifo_mask; /* no further handling */
+-      fifo->framenum = usb_get_current_frame_number(fifo->hfc->dev);
++      spin_lock_init(&urb->lock);     // do we really need spin_lock_init ?
++      urb->dev = dev;
++      urb->pipe = pipe;
++      urb->complete = complete;
++      urb->number_of_packets = num_packets;
++      urb->transfer_buffer_length = packet_size * num_packets;
++      urb->context = context;
++      urb->transfer_buffer = buf;
++      urb->transfer_flags = 0;
++      urb->transfer_flags = USB_ISO_ASAP;
++      urb->actual_length = 0;
++      urb->interval = interval;
++      for (k = 0; k < num_packets; k++) {
++              urb->iso_frame_desc[k].offset = packet_size * k;
++              urb->iso_frame_desc[k].length = packet_size;
++              urb->iso_frame_desc[k].actual_length = 0;
++      }
++}
+-      /* check for deactivation or error */
+-      if ((!fifo->active) || (urb->status)) {
+-              fifo->hfc->active_fifos &= ~fifo->fifo_mask;    /* we are inactive */
+-              fifo->active = 0;
+-              if ((fifo->buff) && (fifo->fifonum == HFCUSB_D_TX)) {
+-                      dev_kfree_skb_any(fifo->buff);
++/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */
++static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size)
++{
++      int i, k, errcode;
++
++#ifdef VERBOSE_USB_DEBUG
++      printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n",  fifo->fifonum);
++#endif
++
++
++      // allocate Memory for Iso out Urbs
++      for (i = 0; i < 2; i++) {
++              if (!(fifo->iso[i].purb)) {
++                      fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb);
++                      fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
++
++                      // Init the first iso
++                      if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb))
++                      {
++
++                              fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer,
++                                      num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall,
++                                      complete, &fifo->iso[i]);
++
++                              memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer));
++
++                              // defining packet delimeters in fifo->buffer
++                              for(k = 0; k < num_packets_per_urb; k++)
++                              {
++                                      fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size;
++                                      fifo->iso[i].purb->iso_frame_desc[k].length = packet_size;
++                              }
++                      }
+               }
+-              fifo->buff = NULL;
+-              return;
++
++              fifo->bit_line = BITLINE_INF;
++
++              errcode = usb_submit_urb(fifo->iso[i].purb);
++              fifo->active = (errcode >= 0) ? 1 : 0;
++              if(errcode < 0)
++              {
++                      printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n",  errcode, i);
++              };
++
+       }
+-      fifo->act_ptr += (urb->transfer_buffer_length - fifo->rx_offset);       /* adjust pointer */
+-      fill_tx_urb(fifo);      /* refill the urb */
+-      fifo->hfc->threshold_mask |= fifo->fifo_mask;   /* assume threshold reached */
+-      if (fifo->buff)
+-              fifo->hfc->service_request |= fifo->fifo_mask;  /* need to restart */
+-}                             /* tx_complete */
+-/***********************************************/
+-/* receive completion routine for all rx fifos */
+-/***********************************************/
+-static void
+-rx_complete(purb_t urb)
++      // errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL));
++      return(fifo->active);
++}
++
++/* stops running iso chain and frees their pending urbs */
++static void stop_isoc_chain(usb_fifo * fifo)
+ {
+-      usb_fifo *fifo = (usb_fifo *) urb->context;     /* pointer to our fifo */
+-      hfcusb_data *hfc = fifo->hfc;
+-      usb_fifo *txfifo;
+-      __u8 last_state;
+-      int i, ii, currcnt, hdlci;
+-      struct sk_buff *skb;
+-
+-      urb->dev = hfc->dev; /* security init */
+-      if ((!fifo->active) || (urb->status)) {
+-              hfc->service_request &= ~fifo->fifo_mask;       /* no further handling */
+-              hfc->active_fifos &= ~fifo->fifo_mask;  /* we are inactive */
+-              fifo->urb.interval = 0; /* cancel automatic rescheduling */
+-              if (fifo->buff) {
+-                      dev_kfree_skb_any(fifo->buff);
+-                      fifo->buff = NULL;
++      int i;
++
++      for(i = 0; i < 2; i++)
++      {
++              if(fifo->iso[i].purb)
++              {
++#ifdef VERBOSE_USB_DEBUG
++                      printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i);
++#endif
++                      usb_unlink_urb(fifo->iso[i].purb);
++                      usb_free_urb(fifo->iso[i].purb);
++                      fifo->iso[i].purb = NULL;
+               }
+-              return;
+       }
++      if (fifo->urb) {
++              usb_unlink_urb(fifo->urb);
++              usb_free_urb(fifo->urb);
++              fifo->urb = NULL;
++      }
++      fifo->active = 0;
++}
+-      /* first check for any status changes */
+-      if ((urb->actual_length < fifo->rx_offset)
+-          || (urb->actual_length > fifo->usb_maxlen))
+-              return;         /* error condition */
+-
+-      if (fifo->rx_offset) {
+-              hfc->threshold_mask = fifo->buffer[1];  /* update threshold status */
+-              fifo->next_complete = fifo->buffer[0] & 1;
+-              if ((fifo->fifonum == HFCUSB_D_RX) &&
+-                  (hfc->led_req != hfc->led_act))
+-                  queue_control_request(hfc, HFCUSB_P_DATA, hfc->led_req);
+-
+-              /* check if rescheduling needed */
+-              if ((i =
+-                   hfc->service_request & hfc->active_fifos & ~hfc->
+-                   threshold_mask)) {
+-                      currcnt =
+-                          usb_get_current_frame_number(hfc->dev);
+-                      txfifo = hfc->fifos + HFCUSB_B1_TX;
+-                      ii = 3;
+-                      while (ii--) {
+-                              if ((i & txfifo->fifo_mask)
+-                                  && (currcnt != txfifo->framenum)) {
+-                                      hfc->service_request &=
+-                                          ~txfifo->fifo_mask;
+-                                      if (!txfifo->buff)
+-                                              fill_tx_urb(txfifo);
+-                                      if (txfifo->buff)
+-                                              usb_submit_urb(&txfifo->
+-                                                             urb);
++// defines how much ISO packets are handled in one URB
++static int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,
++                             ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D};
++
++/*****************************************************/
++/* transmit completion routine for all ISO tx fifos */
++/*****************************************************/
++static void tx_iso_complete(struct urb *urb)
++{
++      iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
++      usb_fifo *fifo = context_iso_urb->owner_fifo;
++      hfcusb_data *hfc = fifo->hfc;
++      int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon;
++      __u8 threshbit;
++      __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
++
++      fifon=fifo->fifonum;
++      tx_offset=0;
++      // very weird error code when using ohci drivers, for now : ignore this error ...  (MB)
++      if(urb->status == -EOVERFLOW)
++      {
++              urb->status = 0;
++#ifdef VERBOSE_USB_DEBUG
++              printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);
++#endif
++      }
++
++      if(fifo->active && !urb->status)
++      {
++              transp_mode=0;
++              if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
++
++              threshbit = threshtable[fifon] & hfc->threshold_mask;   // is threshold set for our channel?
++              num_isoc_packets=iso_packets[fifon];
++
++              if(fifon >= HFCUSB_D_TX)
++              {
++                      sink = (threshbit) ? SINK_DMIN : SINK_DMAX;     // how much bit go to the sink for D-channel?
++              }
++              else
++              {
++                      sink = (threshbit) ? SINK_MIN : SINK_MAX;       // how much bit go to the sink for B-channel?
++              }
++
++              // prepare ISO Urb
++              fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
++                      fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context);
++              memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer));
++
++              frame_complete=FALSE;
++
++              // Generate Iso Packets
++              for(k = 0; k < num_isoc_packets; ++k)
++              {
++                      if(fifo->skbuff)
++                      {
++                              len = fifo->skbuff->len;        // remaining length
++
++                              fifo->bit_line -= sink; // we lower data margin every msec
++                              current_len = (0 - fifo->bit_line) / 8;
++                              if(current_len > 14) current_len = 14;  // maximum 15 byte for every ISO packet makes our life easier
++                              current_len = (len <= current_len) ? len : current_len;
++                              fifo->bit_line += current_len * 8;      // how much bit do we put on the line?
++
++                              context_iso_urb->buffer[tx_offset] = 0;
++                              if(current_len == len)
++                              {
++                                      if(!transp_mode)
++                                      {
++                                              context_iso_urb->buffer[tx_offset] = 1; // here frame completion
++                                              fifo->bit_line += 32;   // add 2 byte flags and 16bit CRC at end of ISDN frame
++                                      }
++                                      frame_complete = TRUE;
++                              }
++
++                              // copy bytes from buffer into ISO_URB
++                              memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len);
++                              skb_pull(fifo->skbuff,current_len);
++
++                              // define packet delimeters within the URB buffer
++                              urb->iso_frame_desc[k].offset = tx_offset;
++                              urb->iso_frame_desc[k].length = current_len + 1;
++
++                              tx_offset += (current_len + 1);
++                              // printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask);
++                              if(!transp_mode)
++                              {
++                                      if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA);
++                                      if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA);
++                              }
++                      }
++                      else
++                      {
++                              // we have no more data - generate 1 byte ISO packets
++                              urb->iso_frame_desc[k].offset = tx_offset++;
++
++                              urb->iso_frame_desc[k].length = 1;
++                              fifo->bit_line -= sink; // we lower data margin every msec
++
++                              if(fifo->bit_line < BITLINE_INF)
++                              {
++                                      fifo->bit_line = BITLINE_INF;
++                                      //printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n");
+                               }
+-                              txfifo += 2;
+                       }
+-              }
+-              /* handle l1 events */
+-              if ((fifo->buffer[0] >> 4) != hfc->l1_state) {
+-                      last_state = hfc->l1_state;
+-                      hfc->l1_state = fifo->buffer[0] >> 4;   /* update status */
+-                      if (timer_pending(&hfc->t4_timer))
+-                          del_timer(&hfc->t4_timer);
+-                      if (((hfc->l1_state == 3) && 
+-                           ((last_state == 7) || 
+-                            (last_state == 8))) || 
+-                          ((timer_pending(&hfc->t3_timer) &&
+-                          (hfc->l1_state == 8)))) {
+-                          hfc->t4_timer.expires = jiffies + 2;
+-                          add_timer(&hfc->t4_timer);
+-                      } else { 
+-                              if (timer_pending(&hfc->t3_timer)
+-                                  && (hfc->l1_state == 7))
+-                                      del_timer(&hfc->t3_timer);      /* no longer needed */
+-                              test_and_set_bit(HFCUSB_L1_STATECHANGE,
+-                                               &hfc->l1_event);
+-                              queue_task(&hfc->l1_tq, &tq_immediate);
+-                              mark_bh(IMMEDIATE_BH);
++                      if(frame_complete)
++                      {
++                              // delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST
++                              fifo->delete_flg=TRUE;
++
++                              fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize);
++
++                              if(fifo->skbuff && fifo->delete_flg)
++                              {
++                                      dev_kfree_skb_any(fifo->skbuff);
++                                      //printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum);
++                                      fifo->skbuff = NULL;
++                                      fifo->delete_flg=FALSE;
++                              }
++
++                              frame_complete=FALSE;
+                       }
++        }
++
++              errcode = usb_submit_urb(urb);
++              if(errcode < 0)
++              {
++                      printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);
++              }
++      }
++      else
++      {
++              if(urb->status)
++              {
++                      printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);
+               }
+       }
+-      /* check the length for data and move if present */
+-      if (fifo->next_complete || (urb->actual_length > fifo->rx_offset)) {
+-              i = fifo->buff->len + urb->actual_length - fifo->rx_offset;     /* new total length */
+-              hdlci = (fifo->transmode) ? 0 : 3;
+-              if (i <= (fifo->max_size + hdlci)) {
+-                      memcpy(fifo->act_ptr,
+-                             fifo->buffer + fifo->rx_offset,
+-                             urb->actual_length - fifo->rx_offset);
+-                      fifo->act_ptr +=
+-                          (urb->actual_length - fifo->rx_offset);
+-                      fifo->buff->len +=
+-                          (urb->actual_length - fifo->rx_offset);
+-              } else
+-                      fifo->buff->len = fifo->max_size + 4;   /* mark frame as to long */
+-              if (fifo->next_complete && (urb->actual_length < fifo->usb_maxlen)) {
+-                  /* the frame is complete */
+-                  fifo->next_complete = 0;
+-                  if (((!*(fifo->act_ptr - 1)) || fifo->transmode) &&
+-                      (fifo->buff->len >= (hdlci + 1))
+-                      && (fifo->buff->len <=
+-                          (fifo->max_size + hdlci)) &&
+-                      ((skb = dev_alloc_skb(fifo->max_size + hdlci)) != NULL)) {
+-                      fifo->buff->len -= hdlci;       /* adjust size */
+-                      switch (fifo->fifonum) {
+-                          case HFCUSB_D_RX:
+-                              skb_queue_tail(hfc->regd.
+-                                             drq,
+-                                             fifo->buff);
+-                              test_and_set_bit
+-                                  (HFCUSB_L1_DRX,
+-                                   &hfc->l1_event);
+-                              queue_task(&hfc->l1_tq,
+-                                         &tq_immediate);
+-                              mark_bh(IMMEDIATE_BH);
+-                              break;
++}                             /* tx_iso_complete */
+-                          case HFCUSB_B1_RX:
+-                              if (hfc->regd.brq[0]) {
+-                                  skb_queue_tail
+-                                      (hfc->regd.
+-                                       brq[0],
+-                                       fifo->buff);
+-                                  hfc->regd.
+-                                      bch_l1l2(hfc->
+-                                               regd.
+-                                               arg_hisax,
+-                                               0,
+-                                               PH_DATA
+-                                               |
+-                                               INDICATION,
+-                                               (void *)
+-                                               fifo->
+-                                               buff);
+-                              } else
+-                                  dev_kfree_skb_any
+-                                      (fifo->buff);
+-                              break;
+-                              
+-                          case HFCUSB_B2_RX:
+-                              if (hfc->regd.brq[1]) {
+-                                  skb_queue_tail
+-                                      (hfc->regd.
+-                                       brq[1],
+-                                       fifo->buff);
+-                                  hfc->regd.
+-                                      bch_l1l2(hfc->
+-                                               regd.
+-                                               arg_hisax,
+-                                               1,
+-                                               PH_DATA
+-                                               |
+-                                               INDICATION,
+-                                               (void
+-                                                *)
+-                                               fifo->
+-                                               buff);
+-                              } else
+-                                  dev_kfree_skb_any
+-                                      (fifo->buff);
+-                              break;
++/*****************************************************/
++/* receive completion routine for all ISO tx fifos   */
++/*****************************************************/
++static void rx_iso_complete(struct urb *urb)
++{
++      iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
++      usb_fifo *fifo = context_iso_urb->owner_fifo;
++      hfcusb_data *hfc = fifo->hfc;
++      int k, len, errcode, offset, num_isoc_packets,fifon;
++      __u8 *buf;
+-                          case HFCUSB_PCM_RX:
+-                              skb_queue_tail(&hfc->regd.
+-                                             erq,
+-                                             fifo->buff);
+-                              test_and_set_bit
+-                                  (HFCUSB_L1_ERX,
+-                                   &hfc->l1_event);
+-                              queue_task(&hfc->l1_tq,
+-                                         &tq_immediate);
+-                              mark_bh(IMMEDIATE_BH);
+-                              break;
++      fifon=fifo->fifonum;
++      // very weird error code when using ohci drivers, for now : ignore this error ...  (MB)
++      if(urb->status == -EOVERFLOW)
++      {
++              urb->status = 0;
++#ifdef VERBOSE_USB_DEBUG
++              printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);
++#endif
++      }
+-                          default:
+-                              dev_kfree_skb_any(fifo->
+-                                                buff);
+-                              break;
++      if(fifo->active && !urb->status)
++      {
++              num_isoc_packets=iso_packets[fifon];
++
++              // Generate D-Channel Iso Packets
++              for(k = 0; k < num_isoc_packets; ++k)
++              {
++                      len=urb->iso_frame_desc[k].actual_length;
++                      offset=urb->iso_frame_desc[k].offset;
++                      buf=context_iso_urb->buffer+offset;
++
++                      if(fifo->last_urblen!=fifo->usb_packet_maxlen)
++                      {
++                              // the threshold mask is in the 2nd status byte
++                              hfc->threshold_mask=buf[1];
++                              // the S0 state is in the upper half of the 1st status byte
++                              state_handler(hfc,buf[0] >> 4);
++                              // if we have more than the 2 status bytes -> collect data
++                              if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1);
+                       }
+-                      fifo->buff = skb;
+-                  } 
+-                  fifo->buff->len = 0;        /* reset counter */
+-                  fifo->act_ptr = fifo->buff->data;   /* and pointer */
++                      else collect_rx_frame(fifo,buf,len,0);
++
++                      fifo->last_urblen=len;
++
++        }
++
++              // prepare ISO Urb
++              fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
++                      fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context);
++
++              errcode = usb_submit_urb(urb);
++              if(errcode < 0)
++              {
++                      printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);
++              }
++      }
++      else
++      {
++              if(urb->status)
++              {
++                      printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);
++              }
++      }
++}                             /* rx_iso_complete */
++
++
++/*****************************************************/
++/* collect data from interrupt or isochron in        */
++/*****************************************************/
++static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish)
++{
++      hfcusb_data *hfc = fifo->hfc;
++      int transp_mode,fifon;
++
++      fifon=fifo->fifonum;
++      transp_mode=0;
++      if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
++
++      //printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon);
++      if(!fifo->skbuff)
++      {
++              // allocate sk buffer
++              fifo->skbuff=dev_alloc_skb(fifo->max_size + 3);
++              if(!fifo->skbuff)
++              {
++                      printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon);
++                      return;
++              }
++              
++      }
++
++      if(len && fifo->skbuff->len+len<fifo->max_size)
++      {
++              memcpy(skb_put(fifo->skbuff,len),data,len);
++      }
++      else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size);
++
++      // give transparent data up, when 128 byte are available
++      if(transp_mode && fifo->skbuff->len>=128)
++      {
++              fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
++              fifo->skbuff = NULL;  // buffer was freed from upper layer
++              return;
++      }
++
++      // we have a complete hdlc packet
++      if(finish)
++      {
++              if(!fifo->skbuff->data[fifo->skbuff->len-1])
++              {
++                      skb_trim(fifo->skbuff,fifo->skbuff->len-3);  // remove CRC & status
++
++                      //printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon);
++
++                      if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff);
++                      else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
++
++                      fifo->skbuff = NULL;  // buffer was freed from upper layer
++              }
++              else
++              {
++                      printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len);
++
++                      skb_trim(fifo->skbuff,0);  // clear whole buffer
++              }
++      }
++
++      // LED flashing only in HDLC mode
++      if(!transp_mode)
++      {
++              if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA);
++              if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA);
++      }
++}
++
++/***********************************************/
++/* receive completion routine for all rx fifos */
++/***********************************************/
++static void rx_complete(struct urb *urb)
++{
++      int len;
++      __u8 *buf;
++      usb_fifo *fifo = (usb_fifo *) urb->context;     /* pointer to our fifo */
++      hfcusb_data *hfc = fifo->hfc;
++
++      urb->dev = hfc->dev;    /* security init */
++
++      if((!fifo->active) || (urb->status)) {
++#ifdef VERBOSE_USB_DEBUG
++              printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status);
++#endif
++              fifo->urb->interval = 0;        /* cancel automatic rescheduling */
++              if(fifo->skbuff) {
++                      dev_kfree_skb_any(fifo->skbuff);
++                      fifo->skbuff = NULL;
+               }
++              return;
+       }
+-      fifo->rx_offset = (urb->actual_length < fifo->usb_maxlen) ? 2 : 0;
+-}                             /* rx_complete */
++
++      len=urb->actual_length;
++      buf=fifo->buffer;
++
++      if(fifo->last_urblen!=fifo->usb_packet_maxlen) {
++              // the threshold mask is in the 2nd status byte
++              hfc->threshold_mask=buf[1];
++              // the S0 state is in the upper half of the 1st status byte
++              state_handler(hfc,buf[0] >> 4);
++              // if we have more than the 2 status bytes -> collect data
++              if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1);
++      } else
++              collect_rx_frame(fifo,buf,urb->actual_length,0);
++
++      fifo->last_urblen=urb->actual_length;
++
++
++}     /* rx_complete */
++
++
+ /***************************************************/
+ /* start the interrupt transfer for the given fifo */
+ /***************************************************/
+-static void
+-start_rx_fifo(usb_fifo * fifo)
++static void start_int_fifo(usb_fifo * fifo)
+ {
+-      if (fifo->buff)
+-              return;         /* still active */
+-      if (!
+-          (fifo->buff =
+-           dev_alloc_skb(fifo->max_size + (fifo->transmode ? 0 : 3))))
+-              return;
+-      fifo->act_ptr = fifo->buff->data;
+-      FILL_INT_URB(&fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
+-                   fifo->usb_maxlen, rx_complete, fifo, fifo->intervall);
+-      fifo->next_complete = 0;
+-      fifo->rx_offset = 2;
+-      fifo->active = 1;       /* must be marked active */
+-      fifo->hfc->active_fifos |= fifo->fifo_mask;
+-      if (usb_submit_urb(&fifo->urb)) {
++      int errcode;
++
++#ifdef VERBOSE_USB_DEBUG
++      printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum);
++#endif
++      if (!fifo->urb) {
++              fifo->urb = usb_alloc_urb(0);
++              if (!fifo->urb)
++                      return;
++      }
++      usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
++                               fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall);
++      fifo->active = 1;               /* must be marked active */
++      errcode = usb_submit_urb(fifo->urb);
++
++      if(errcode)
++      {
++              printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n",   errcode);
+               fifo->active = 0;
+-              fifo->hfc->active_fifos &= ~fifo->fifo_mask;
+-              dev_kfree_skb_any(fifo->buff);
+-              fifo->buff = NULL;
++              fifo->skbuff = NULL;
+       }
+-}                             /* start_rx_fifo */
++} /* start_int_fifo */
+-/***************************************************************/
+-/* control completion routine handling background control cmds */
+-/***************************************************************/
+-static void
+-ctrl_complete(purb_t urb)
++/*****************************/
++/* set the B-channel mode    */
++/*****************************/
++static void set_hfcmode(hfcusb_data *hfc,int channel,int mode)
+ {
+-      hfcusb_data *hfc = (hfcusb_data *) urb->context;
++      __u8 val,idx_table[2]={0,2};
+-      urb->dev = hfc->dev;
+-      if (hfc->ctrl_cnt) {
+-              switch (hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg) {
+-                      case HFCUSB_FIFO:
+-                              hfc->ctrl_fifo =
+-                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
+-                                  reg_val;
+-                              break;
+-                      case HFCUSB_F_USAGE:
+-                              if (!hfc->dfifo_fill) {
+-                                      fill_tx_urb(hfc->fifos +
+-                                                  HFCUSB_D_TX);
+-                                      if (hfc->fifos[HFCUSB_D_TX].buff)
+-                                              usb_submit_urb(&hfc->
+-                                                             fifos
+-                                                             [HFCUSB_D_TX].
+-                                                             urb);
+-                              } else {
+-                                      queue_control_request(hfc,
+-                                                            HFCUSB_FIFO,
+-                                                            HFCUSB_D_TX);
+-                                      queue_control_request(hfc,
+-                                                            HFCUSB_F_USAGE,
+-                                                            0);
+-                              }
+-                              break;
+-                      case HFCUSB_SCTRL_R:
+-                              switch (hfc->ctrl_fifo) {
+-                                      case HFCUSB_B1_RX:
+-                                              if (hfc->bch_enables & 1)
+-                                                      start_rx_fifo(hfc->
+-                                                                    fifos
+-                                                                    +
+-                                                                    HFCUSB_B1_RX);
+-                                              break;
+-                                      case HFCUSB_B2_RX:
+-                                              if (hfc->bch_enables & 2)
+-                                                      start_rx_fifo(hfc->
+-                                                                    fifos
+-                                                                    +
+-                                                                    HFCUSB_B2_RX);
+-                                              break;
+-                              }
+-                              if (hfc->bch_enables & 3)
+-                                  hfc->led_req |= LED_BCH;
+-                              else
+-                                  hfc->led_req &= ~LED_BCH;
+-                              break;
+-                      case HFCUSB_P_DATA:
+-                              hfc->led_act =
+-                                  hfc->ctrl_buff[hfc->ctrl_out_idx].
+-                                  reg_val;
+-                              break;
+-              }
+-              hfc->ctrl_cnt--;        /* decrement actual count */
+-              if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
+-                      hfc->ctrl_out_idx = 0;  /* pointer wrap */
+-              ctrl_start_transfer(hfc);       /* start next transfer */
++#ifdef VERBOSE_ISDN_DEBUG
++  printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode);
++#endif
++
++      hfc->b_mode[channel]=mode;
++
++      // setup CON_HDLC
++      val=0;
++      if(mode!=L1_MODE_NULL) val=8;    // enable fifo?
++      if(mode==L1_MODE_TRANS) val|=2;  // set transparent bit
++
++      queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register
++      queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
++      queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo
++
++      queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register
++      queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
++      queue_control_request(hfc,HFCUSB_INC_RES_F,2,1);  // reset fifo
++
++      val=0x40;
++      if(hfc->b_mode[0]) val|=1;
++      if(hfc->b_mode[1]) val|=2;
++      queue_control_request(hfc,HFCUSB_SCTRL,val,1);
++
++      val=0;
++      if(hfc->b_mode[0]) val|=1;
++      if(hfc->b_mode[1]) val|=2;
++      queue_control_request(hfc,HFCUSB_SCTRL_R,val,1);
++
++      if(mode==L1_MODE_NULL)
++      {
++              if(channel) handle_led(hfc,LED_B2_OFF);
++              else handle_led(hfc,LED_B1_OFF);
+       }
+-}                             /* ctrl_complete */
++      else
++      {
++              if(channel) handle_led(hfc,LED_B2_ON);
++              else handle_led(hfc,LED_B1_ON);
++      }
++}
+-/*****************************************/
+-/* Layer 1 + D channel access from HiSax */
+-/*****************************************/
+-static void
+-hfcusb_l1_access(void *drvarg, int pr, void *arg)
+-{
+-      hfcusb_data *hfc = (hfcusb_data *) drvarg;
+-
+-      switch (pr) {
+-              case (PH_DATA | REQUEST):
+-              case (PH_PULL | INDICATION):
+-                      skb_queue_tail(hfc->regd.dsq,
+-                                     (struct sk_buff *) arg);
+-                      if (!hfc->fifos[HFCUSB_D_TX].active
+-                          && !hfc->dfifo_fill) {
+-                              fill_tx_urb(hfc->fifos + HFCUSB_D_TX);
+-                              hfc->active_fifos |=
+-                                  hfc->fifos[HFCUSB_D_TX].fifo_mask;
+-                              usb_submit_urb(&hfc->fifos[HFCUSB_D_TX].
+-                                             urb);
+-                      }
+-                      break;
+-              case (PH_ACTIVATE | REQUEST):
+-                  switch (hfc->l1_state) {
+-                      case 6:
+-                      case 8:
+-                              hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+-                                                 (PH_DEACTIVATE |
+-                                                 INDICATION), NULL);
++/*
++   --------------------------------------------------------------------------------------
++   from here : hisax_if callback routines :
++     - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) {
+-                              break;
+-                      case 7:
+-                              hfc->regd.dch_l1l2(hfc->regd.arg_hisax,
+-                                                 (PH_ACTIVATE |
+-                                                 INDICATION), NULL);
++   l1 to l2 routines :
++     - static void hfc_usb_l1l2(hfcusb_data * hfc)
+-                              break;
+-                      default:
+-                              queue_control_request(hfc, HFCUSB_STATES, 0x60);        /* start activation */
+-                              hfc->t3_timer.expires =
+-                                  jiffies + (HFC_TIMER_T3 * HZ) / 1000;
+-                              if (!timer_pending(&hfc->t3_timer))
+-                                      add_timer(&hfc->t3_timer);
+-                              break;
+-                  }
+-                  break;
++*/
+-              case (PH_DEACTIVATE | REQUEST):
+-                      queue_control_request(hfc, HFCUSB_STATES, 0x40);        /* start deactivation */
+-                      break;
+-              default:
+-                      printk(KERN_INFO "unknown hfcusb l1_access 0x%x\n",
+-                             pr);
+-                      break;
+-      }
+-}                             /* hfcusb_l1_access */
+-
+-/*******************************/
+-/* B channel access from HiSax */
+-/*******************************/
+-static void
+-hfcusb_bch_access(void *drvarg, int chan, int pr, void *arg)
+-{
+-      hfcusb_data *hfc = (hfcusb_data *) drvarg;
+-      usb_fifo *fifo = hfc->fifos + (chan ? HFCUSB_B2_TX : HFCUSB_B1_TX);
+-      long flags;
+-
+-      switch (pr) {
+-              case (PH_DATA | REQUEST):
+-              case (PH_PULL | INDICATION):
+-                      save_flags(flags);
+-                      cli();
+-                      if (!fifo->active) {
+-                              fill_tx_urb(fifo);
+-                              hfc->active_fifos |= fifo->fifo_mask;
+-                              usb_submit_urb(&fifo->urb);
+-                      }
+-                      restore_flags(flags);
+-                      break;
+-              case (PH_ACTIVATE | REQUEST):
+-                      if (!((int) arg)) {
+-                              hfc->bch_enables &= ~(1 << chan);
+-                              if (fifo->active) {
+-                                      fifo->active = 0;
+-                                      usb_unlink_urb(&fifo->urb);
++void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
++{
++    usb_fifo *fifo = my_hisax_if->priv;
++      hfcusb_data *hfc = fifo->hfc;
++
++    switch (pr) {
++              case PH_ACTIVATE | REQUEST:
++                              if(fifo->fifonum==HFCUSB_D_TX)
++                              {
++#ifdef VERBOSE_ISDN_DEBUG
++                                      printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n");
++#endif
++                                      queue_control_request(hfc, HFCUSB_STATES,0x60,1);       /* make activation */
++                                      hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000;
++                                      if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer);
+                               }
+-                              save_flags(flags);
+-                              cli();
+-                              queue_control_request(hfc, HFCUSB_FIFO,
+-                                                    fifo->fifonum);
+-                              queue_control_request(hfc,
+-                                                    HFCUSB_INC_RES_F, 2);
+-                              queue_control_request(hfc, HFCUSB_CON_HDLC,
+-                                                    9);
+-                              queue_control_request(hfc, HFCUSB_SCTRL,
+-                                                    0x40 +
+-                                                    hfc->bch_enables);
+-                              queue_control_request(hfc, HFCUSB_SCTRL_R,
+-                                                    hfc->bch_enables);
+-                              restore_flags(flags);
+-                              fifo++;
+-                              if (fifo->active) {
+-                                      fifo->active = 0;
+-                                      usb_unlink_urb(&fifo->urb);
++                              else
++                              {
++#ifdef VERBOSE_ISDN_DEBUG
++                                      printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n");
++#endif
++                                      set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg);
++                                      fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL);
+                               }
+-                              return; /* fifo deactivated */
+-                      }
+-                      fifo->transmode = ((int) arg == L1_MODE_TRANS);
+-                      fifo->max_size =
+-                          ((fifo->transmode) ? fifo->
+-                           usb_maxlen : MAX_BCH_SIZE);
+-                      (fifo + 1)->transmode = fifo->transmode;
+-                      (fifo + 1)->max_size = fifo->max_size;
+-                      hfc->bch_enables |= (1 << chan);
+-                      save_flags(flags);
+-                      cli();
+-                      queue_control_request(hfc, HFCUSB_FIFO,
+-                                            fifo->fifonum);
+-                      queue_control_request(hfc, HFCUSB_CON_HDLC,
+-                                            ((!fifo->
+-                                              transmode) ? 9 : 11));
+-                      queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
+-                      queue_control_request(hfc, HFCUSB_SCTRL,
+-                                            0x40 + hfc->bch_enables);
+-                      if ((int) arg == L1_MODE_HDLC)
+-                              queue_control_request(hfc, HFCUSB_CON_HDLC,
+-                                                    8);
+-                      queue_control_request(hfc, HFCUSB_FIFO,
+-                                            fifo->fifonum + 1);
+-                      queue_control_request(hfc, HFCUSB_CON_HDLC,
+-                                            ((!fifo->
+-                                              transmode) ? 8 : 10));
+-                      queue_control_request(hfc, HFCUSB_INC_RES_F, 2);
+-                      queue_control_request(hfc, HFCUSB_SCTRL_R,
+-                                            hfc->bch_enables);
+-                      restore_flags(flags);
+-
+-                      break;
+-
+-              default:
+-                      printk(KERN_INFO
+-                             "unknown hfcusb bch_access chan %d 0x%x\n",
+-                             chan, pr);
+-                      break;
+-      }
+-}                             /* hfcusb_bch_access */
++                break;
++        case PH_DEACTIVATE | REQUEST:
++                              if(fifo->fifonum==HFCUSB_D_TX)
++                              {
++#ifdef VERBOSE_ISDN_DEBUG
++                                      printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n");
++#endif
++                                      printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n");
++                              }
++                              else
++                              {
++#ifdef VERBOSE_ISDN_DEBUG
++                                      printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n");
++#endif
++                                      set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL);
++                                      fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL);
++                              }
++                break;
++              case PH_DATA | REQUEST:
++                              if(fifo->skbuff && fifo->delete_flg)
++                              {
++                                      dev_kfree_skb_any(fifo->skbuff);
++                                      //printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum);
++                                      fifo->skbuff = NULL;
++                                      fifo->delete_flg=FALSE;
++                              }
++
++                              fifo->skbuff=arg; // we have a new buffer
++
++                              //if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n");
++                              //else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n");
++                break;
++        default:
++                printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr);
++                break;
++    }
++}
++
++// valid configurations
++#define CNF_4INT3ISO  1      // 4 INT IN, 3 ISO OUT
++#define CNF_3INT3ISO  2      // 3 INT IN, 3 ISO OUT
++#define CNF_4ISO3ISO  3      // 4 ISO IN, 3 ISO OUT
++#define CNF_3ISO3ISO  4        // 3 ISO IN, 3 ISO OUT
++
++
++/*
++   --------------------------------------------------------------------------------------
++   From here on USB initialization and deactivation related routines are implemented :
++
++   - hfc_usb_init :
++      is the main Entry Point for the USB Subsystem when the device get plugged
++      in. This function calls usb_register with usb_driver as parameter.
++      Here, further entry points for probing (hfc_usb_probe) and disconnecting
++      the device (hfc_usb_disconnect) are published, as the id_table
++
++   - hfc_usb_probe
++      this function is called by the usb subsystem, and steps through the alternate
++      settings of the currently plugged in device to detect all Endpoints needed to
++      run an ISDN TA.
++      Needed EndPoints are
++      3 (+1) IntIn EndPoints   (D-in,  E-in, B1-in, B2-in, (E-in)) or
++      3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints
++      The currently used transfer mode of on the Out-Endpoints will be stored in
++      hfc->usb_transfer_mode and is either USB_INT or USB_ISO
++      When a valid alternate setting could be found, the usb_init (see blow)
++      function is called
++
++   - usb_init
++      Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive
++      Data to/from the several EndPoints are initialized:
++       The E- and D-Channel Int-In chain gets started
++       The IsoChain for the Iso-Out traffic get started
++
++   - hfc_usb_disconnect
++      this function is called by the usb subsystem and has to free all resources
++      and stop all usb traffic to allow a proper hotplugging disconnect.
++
++*/
+ /***************************************************************************/
+ /* usb_init is called once when a new matching device is detected to setup */
+-/* main parmeters. It registers the driver at the main hisax module.       */
++/* main parameters. It registers the driver at the main hisax module.       */
+ /* on success 0 is returned.                                               */
+ /***************************************************************************/
+-static int
+-usb_init(hfcusb_data * hfc)
++static int usb_init(hfcusb_data * hfc)
+ {
+       usb_fifo *fifo;
+-      int i;
++      int i, err;
+       u_char b;
+-
++      struct hisax_b_if *p_b_if[2];
++      
+       /* check the chip id */
+-      if ((Read_hfc(hfc, HFCUSB_CHIP_ID, &b) != 1) ||
+-          (b != HFCUSB_CHIPID)) {
++      printk(KERN_INFO "HFCUSB_CHIP_ID begin\n");
++      if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {
++              printk(KERN_INFO "HFC-USB: cannot read chip id\n");
++              return(1); 
++      }
++      printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b);
++      if (b != HFCUSB_CHIPID) {
+               printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);
+-              return (1);
++              return(1);
+       }
+       /* first set the needed config, interface and alternate */
+-      usb_set_configuration(hfc->dev, 1);
+-      usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
++      printk(KERN_INFO "usb_init 1\n");
++//    usb_set_configuration(hfc->dev, 1);
++      printk(KERN_INFO "usb_init 2\n");
++      err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
++      printk(KERN_INFO "usb_init usb_set_interface return %d\n", err);
++      /* now we initialize the chip */
++      write_usb(hfc, HFCUSB_CIRM, 8);     // do reset
++      write_usb(hfc, HFCUSB_CIRM, 0x10);      // aux = output, reset off
+-        /* init the led state request */
+-      hfc->led_req = LED_DRIVER;
++      // set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers
++      write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4));
+-      /* now we initialise the chip */
+-      Write_hfc(hfc, HFCUSB_CIRM, 0x10);      /* aux = output, reset off */
+-      Write_hfc(hfc, HFCUSB_P_DATA, 0);       /* leds = off */
+-      Write_hfc(hfc, HFCUSB_USB_SIZE,
+-                (hfc->fifos[HFCUSB_B1_TX].usb_maxlen >> 3) |
+-                ((hfc->fifos[HFCUSB_B1_RX].usb_maxlen >> 3) << 4));
++      // set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers
++      write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);
+       /* enable PCM/GCI master mode */
+-      Write_hfc(hfc, HFCUSB_MST_MODE1, 0);    /* set default values */
+-      Write_hfc(hfc, HFCUSB_MST_MODE0, 1);    /* enable master mode */
++      write_usb(hfc, HFCUSB_MST_MODE1, 0);    /* set default values */
++      write_usb(hfc, HFCUSB_MST_MODE0, 1);    /* enable master mode */
+       /* init the fifos */
+-      Write_hfc(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD >> 3) |
+-                ((HFCUSB_RX_THRESHOLD >> 3) << 4));
++      write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4));
+-      for (i = 0, fifo = hfc->fifos + i; i < HFCUSB_NUM_FIFOS;
+-           i++, fifo++) {
+-              Write_hfc(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
+-
+-              fifo->transmode = 0;    /* hdlc mode selected */
+-              fifo->buff = NULL;      /* init buffer pointer */
+-              fifo->max_size =
+-                  (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
+-              Write_hfc(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); /* data length */
+-              Write_hfc(hfc, HFCUSB_CON_HDLC, ((i & 1) ? 0x08 : 0x09));       /* rx hdlc, tx fill 1 */
+-              Write_hfc(hfc, HFCUSB_INC_RES_F, 2);    /* reset the fifo */
+-      }
+-
+-      Write_hfc(hfc, HFCUSB_CLKDEL, 0x0f);    /* clock delay value */
+-      Write_hfc(hfc, HFCUSB_STATES, 3 | 0x10);        /* set deactivated mode */
+-      Write_hfc(hfc, HFCUSB_STATES, 3);       /* enable state machine */
++      fifo = hfc->fifos;
++      for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
++      {
++              write_usb(hfc, HFCUSB_FIFO, i); /* select the desired fifo */
++              fifo[i].skbuff = NULL;  /* init buffer pointer */
++              fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
++              fifo[i].last_urblen=0;
++              write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2));     // set 2 bit for D- & E-channel
++              write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08));      // rx hdlc, enable IFF for D-channel
++              write_usb(hfc, HFCUSB_INC_RES_F, 2);    /* reset the fifo */
++      }
+-      Write_hfc(hfc, HFCUSB_SCTRL_R, 0);      /* disable both B receivers */
+-      Write_hfc(hfc, HFCUSB_SCTRL, 0x40);     /* disable B transmitters + cap mode */
++      write_usb(hfc, HFCUSB_CLKDEL, 0x0f);     /* clock delay value */
++      write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
++      write_usb(hfc, HFCUSB_STATES, 3);            /* enable state machine */
++
++      write_usb(hfc, HFCUSB_SCTRL_R, 0);           /* disable both B receivers */
++      write_usb(hfc, HFCUSB_SCTRL, 0x40);          /* disable B transmitters + capacitive mode */
++
++      // set both B-channel to not connected
++      hfc->b_mode[0]=L1_MODE_NULL;
++      hfc->b_mode[1]=L1_MODE_NULL;
++
++      hfc->l1_activated=FALSE;
++      hfc->led_state=0;
++      hfc->led_new_data=0;
+-      /* init the l1 timer */
++      /* init the t3 timer */
+       init_timer(&hfc->t3_timer);
+       hfc->t3_timer.data = (long) hfc;
+-      hfc->t3_timer.function = (void *) l1_timer_expire;
++      hfc->t3_timer.function = (void *) l1_timer_expire_t3;
++      /* init the t4 timer */
++      init_timer(&hfc->t4_timer);
+       hfc->t4_timer.data = (long) hfc;
+-      hfc->t4_timer.function = (void *) l1_timer_expire;
+-      hfc->l1_tq.routine = (void *) (void *) usb_l1d_bh;
+-      hfc->l1_tq.sync = 0;
+-      hfc->l1_tq.data = hfc;
+-
+-      /* init the background control machinery */
+-      hfc->ctrl_read.requesttype = 0xc0;
+-      hfc->ctrl_read.request = 1;
+-      hfc->ctrl_read.length = 1;
+-      hfc->ctrl_write.requesttype = 0x40;
+-      hfc->ctrl_write.request = 0;
+-      hfc->ctrl_write.length = 0;
+-      FILL_CONTROL_URB(&hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,
+-                       (u_char *) & hfc->ctrl_write, NULL, 0,
+-                       ctrl_complete, hfc);
+-
+-      /* init the TX-urbs */
+-      fifo = hfc->fifos + HFCUSB_D_TX;
+-      FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
+-                    (u_char *) fifo->buffer, 0, tx_complete, fifo);
+-      fifo = hfc->fifos + HFCUSB_B1_TX;
+-      FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
+-                    (u_char *) fifo->buffer, 0, tx_complete, fifo);
+-      fifo = hfc->fifos + HFCUSB_B2_TX;
+-      FILL_BULK_URB(&fifo->urb, hfc->dev, fifo->pipe,
+-                    (u_char *) fifo->buffer, 0, tx_complete, fifo);
+-
+-      /* init the E-buffer */
+-      skb_queue_head_init(&hfc->regd.erq);
+-
+-      /* now register ourself at hisax */
+-      hfc->regd.version = HISAX_LOAD_VERSION; /* set our version */
+-      hfc->regd.cmd = HISAX_LOAD_REGISTER;    /* register command */
+-      hfc->regd.argl1 = (void *) hfc; /* argument for our local routine */
+-      hfc->regd.dch_l2l1 = hfcusb_l1_access;
+-      hfc->regd.bch_l2l1 = hfcusb_bch_access;
+-      hfc->regd.drvname = "hfc_usb";
+-      if (hisax_register_hfcusb(&hfc->regd)) {
+-              printk(KERN_INFO "HFC-USB failed to register at hisax\n");
+-              Write_hfc(hfc, HFCUSB_CIRM, 0x08);      /* aux = input, reset on */
+-              return (1);
+-      }
+-
+-      /* startup the D- and E-channel fifos */
+-      start_rx_fifo(hfc->fifos + HFCUSB_D_RX);        /* D-fifo */
+-      if (hfc->fifos[HFCUSB_PCM_RX].pipe)
+-              start_rx_fifo(hfc->fifos + HFCUSB_PCM_RX);      /* E-fifo */
++      hfc->t4_timer.function = (void *) l1_timer_expire_t4;
++      /* init the led timer */
++      init_timer(&hfc->led_timer);
++      hfc->led_timer.data = (long) hfc;
++      hfc->led_timer.function = (void *) led_timer;
++      // trigger 4 hz led timer
++      hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
++      if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
++
++      // init the background machinery for control requests
++      hfc->ctrl_read.bRequestType = 0xc0;
++      hfc->ctrl_read.bRequest = 1;
++      hfc->ctrl_read.wLength = 1;
++      hfc->ctrl_write.bRequestType = 0x40;
++      hfc->ctrl_write.bRequest = 0;
++      hfc->ctrl_write.wLength = 0;
++      usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc);
++                                      
++      /* Init All Fifos */
++      for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
++      {
++              hfc->fifos[i].iso[0].purb = NULL;
++              hfc->fifos[i].iso[1].purb = NULL;
++              hfc->fifos[i].active = 0;
++      }
++
++      // register like Germaschewski :
++      hfc->d_if.owner = THIS_MODULE;
++      hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];
++      hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;
++
++      for (i=0; i<2; i++)
++      {
++              hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2];
++              hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;
++              p_b_if[i] = &hfc->b_if[i];
++      }
++      
++      hfc->protocol = 2;  /* default EURO ISDN, should be a module_param */
++      hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
++      
++      for (i=0; i<4; i++)
++              hfc->fifos[i].hif=&p_b_if[i/2]->ifc;
++      for (i=4; i<8; i++)
++              hfc->fifos[i].hif=&hfc->d_if.ifc;
++
++      // 3 (+1) INT IN + 3 ISO OUT
++      if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO)
++      {
++              start_int_fifo(hfc->fifos + HFCUSB_D_RX);       // Int IN D-fifo
++              if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX);  // E-fifo
++              start_int_fifo(hfc->fifos + HFCUSB_B1_RX);      // Int IN B1-fifo
++              start_int_fifo(hfc->fifos + HFCUSB_B2_RX);      // Int IN B2-fifo
++      }
++
++      // 3 (+1) ISO IN + 3 ISO OUT
++      if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO)
++      {
++              start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16);
++              if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16);
++              start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16);
++              start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16);
++      }
++
++      start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1);
++      start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1);
++      start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1);
++
++      handle_led(hfc,LED_POWER_ON);
++
++      return(0);
++}     /* usb_init */
++
++
++/****************************************/
++/* data defining the devices to be used */
++/****************************************/
++// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
++static struct usb_device_id hfc_usb_idtab[] = {
++      {USB_DEVICE(0x7b0, 0x0007)},    /* Billion USB TA 2 */
++      {USB_DEVICE(0x742, 0x2008)},    /* Stollmann USB TA */
++      {USB_DEVICE(0x959, 0x2bd0)},    /* Colognechip USB eval TA */
++      {USB_DEVICE(0x8e3, 0x0301)},    /* OliTec ISDN USB */
++      {USB_DEVICE(0x675, 0x1688)},    /* DrayTec ISDN USB */
++      {USB_DEVICE(0x7fa, 0x0846)},    /* Bewan ISDN USB TA */
++      {}                              /* end with an all-zeroes entry */
++};
++
++MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)");
++MODULE_DESCRIPTION("HFC I4L USB driver");
++MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
++MODULE_LICENSE("GPL");
++
++#define EP_NUL 1    // Endpoint at this position not allowed
++#define EP_NOP 2      // all type of endpoints allowed at this position
++#define EP_ISO 3      // Isochron endpoint mandatory at this position
++#define EP_BLK 4      // Bulk endpoint mandatory at this position
++#define EP_INT 5      // Interrupt endpoint mandatory at this position
++
++// this array represents all endpoints possible in the HCF-USB
++// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints
++int validconf[][18]=
++{
++      // INT in, ISO out config
++      {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2},
++      {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2},
++      // ISO in, ISO out config
++      {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2},
++      {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2},
++      {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}       // EOL element
++};
++
++// string description of chosen config
++char *conf_str[]=
++{
++      "4 Interrupt IN + 3 Isochron OUT",
++      "3 Interrupt IN + 3 Isochron OUT",
++      "4 Isochron IN + 3 Isochron OUT",
++      "3 Isochron IN + 3 Isochron OUT"
++};
+-      return (0);
+-}                             /* usb_init */
+ /*************************************************/
+ /* function called to probe a new plugged device */
+ /*************************************************/
+-static void *
+-hfc_usb_probe(struct usb_device *dev, unsigned int interface
+-#ifdef COMPAT_HAS_USB_IDTAB
+-            , const struct usb_device_id *id_table)
+-#else
+-    )
+-#endif
++//static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
++static void* hfc_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
+ {
++        //struct usb_device *dev= interface_to_usbdev(intf);
++      struct usb_interface* intf = dev->actconfig->interface + ifnum;
+       hfcusb_data *context;
+-      struct usb_interface *ifp = dev->actconfig->interface + interface;
+-      struct usb_interface_descriptor *ifdp =
+-          ifp->altsetting + ifp->act_altsetting;
+-      struct usb_endpoint_descriptor *epd;
+-      int i, idx, ep_msk;
+-
+-#ifdef COMPAT_HAS_USB_IDTAB
+-      if (id_table && (dev->descriptor.idVendor == id_table->idVendor) &&
+-          (dev->descriptor.idProduct == id_table->idProduct) &&
+-#else
+-      if ((((dev->descriptor.idVendor == 0x959) &&
+-          (dev->descriptor.idProduct == 0x2bd0)) ||
+-          ((dev->descriptor.idVendor == 0x7b0) &&
+-          (dev->descriptor.idProduct == 0x0006))) &&
+-#endif
+-          (ifdp->bNumEndpoints >= 6) && (ifdp->bNumEndpoints <= 16)) {
+-              if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) {
+-                      return (NULL);  /* got no mem */
+-              };
+-              memset(context, 0, sizeof(hfcusb_data));        /* clear the structure */
+-              i = ifdp->bNumEndpoints;        /* get number of endpoints */
+-              ep_msk = 0;     /* none found */
+-              epd = ifdp->endpoint;   /* first endpoint descriptor */
+-              while (i-- && ((ep_msk & 0xcf) != 0xcf)) {
+-
+-                      idx = (((epd->bEndpointAddress & 0x7f) - 1) << 1);      /* get endpoint base */
+-                      if (idx < 7) {
+-                              switch (epd->bmAttributes) {
+-                                      case USB_ENDPOINT_XFER_INT:
+-                                              if (!
+-                                                  (epd->
+-                                                   bEndpointAddress &
+-                                                   0x80))
+-                                                      break;  /* only interrupt in allowed */
+-                                              idx++;  /* input index is odd */
+-                                              context->fifos[idx].pipe =
+-                                                  usb_rcvintpipe(dev,
+-                                                                 epd->
+-                                                                 bEndpointAddress);
+-                                              break;
+-
+-                                      case USB_ENDPOINT_XFER_BULK:
+-                                              if (epd->
+-                                                  bEndpointAddress &
+-                                                  0x80)
+-                                                      break;  /* only bulk out allowed */
+-                                              context->fifos[idx].pipe =
+-                                                  usb_sndbulkpipe(dev,
+-                                                                  epd->
+-                                                                  bEndpointAddress);
+-                                              break;
+-                                      default:
+-                                              context->fifos[idx].pipe = 0;   /* reset data */
+-                              }       /* switch attribute */
+-
+-                              if (context->fifos[idx].pipe) {
+-                                      context->fifos[idx].fifonum = idx;
+-                                      context->fifos[idx].fifo_mask =
+-                                          1 << idx;
+-                                      context->fifos[idx].hfc = context;
+-                                      context->fifos[idx].usb_maxlen =
+-                                          epd->wMaxPacketSize;
+-                                      context->fifos[idx].intervall =
+-                                          epd->bInterval;
+-                                      ep_msk |= (1 << idx);
+-                              } else
+-                                      ep_msk &= ~(1 << idx);
+-                      }       /* idx < 7 */
+-                      epd++;
+-              }
++      //struct usb_host_interface *iface = intf->cur_altsetting;
++      //struct usb_host_interface *iface_used = NULL;
++      //struct usb_host_endpoint *ep;
++      struct usb_endpoint_descriptor* ep;
++      //int ifnum = iface->desc.bInterfaceNumber;
++      struct usb_interface_descriptor* intfdesc = intf->altsetting + intf->act_altsetting;
++      struct usb_interface_descriptor* intfdesc_used = NULL;
++      int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
++      int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;
++
++//        usb_show_device(dev);
++//    usb_show_device_descriptor(&dev->descriptor);
++//    usb_show_interface_descriptor(&iface->desc);
++      vend_idx=0xffff;
++      for(i=0;vdata[i].vendor;i++)
++      {
++              if(dev->descriptor.idVendor==vdata[i].vendor && dev->descriptor.idProduct==vdata[i].prod_id) vend_idx=i;
++      }
++      
+-              if ((ep_msk & 0x3f) != 0x3f) {
+-                      kfree(context);
+-                      return (NULL);
+-              }
+-              MOD_INC_USE_COUNT;      /* lock our module */
+-              context->dev = dev;     /* save device */
+-              context->if_used = interface;   /* save used interface */
+-              context->alt_used = ifp->act_altsetting;        /* and alternate config */
+-              context->ctrl_paksize = dev->descriptor.bMaxPacketSize0;        /* control size */
+-
+-              /* create the control pipes needed for register access */
+-              context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
+-              context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
+-
+-              /* init the chip and register the driver */
+-              if (usb_init(context)) {
+-                      kfree(context);
+-                      MOD_DEC_USE_COUNT;
+-                      return (NULL);
+-              }
++#ifdef VERBOSE_USB_DEBUG      
++      printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d)\n",
++              ifnum, intfdesc->bAlternateSetting); 
++      /*      printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",
++              ifnum, intfdesc->bAlternateSetting, intf->driver->minor); */
++#endif
+-              printk(KERN_INFO
+-                     "HFC-USB: New device if=%d alt=%d registered\n",
+-                     context->if_used, context->alt_used);
+-              return (context);
+-      }
++      if (vend_idx != 0xffff) {
++#ifdef VERBOSE_USB_DEBUG
++              printk(KERN_INFO "HFC-USB: found vendor idx:%d  name:%s\n",vend_idx,vdata[vend_idx].vend_name);
++#endif
++              /* if vendor and product ID is OK, start probing a matching alternate setting ... */
++              alt_idx = 0;
++              small_match=0xffff;
++              // default settings
++              iso_packet_size=16;
++              packet_size=64;
++
++              while (alt_idx < intf->num_altsetting) {
++                      //iface = intf->altsetting + alt_idx;
++                      intfdesc = intf->altsetting + alt_idx;
++                      probe_alt_setting = intfdesc->bAlternateSetting;
++                      cfg_used=0;
+-      return (NULL);          /* no matching entry */
+-}                             /* hfc_usb_probe */
++#ifdef VERBOSE_USB_DEBUG
++                      printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting);
++#endif
++                      // check for config EOL element
++                      while (validconf[cfg_used][0]) {
++                              cfg_found=TRUE;
++                              vcf=validconf[cfg_used];
++                              ep = intfdesc->endpoint;        /* first endpoint descriptor */
++
++#ifdef VERBOSE_USB_DEBUG
++                              printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",
++                                      ifnum, probe_alt_setting, cfg_used);
++#endif
++                              // copy table
++                              memcpy(cmptbl,vcf,16*sizeof(int));
++
++                              // check for all endpoints in this alternate setting
++                              for (i=0; i < intfdesc->bNumEndpoints; i++) {
++                                      ep_addr = ep->bEndpointAddress;
++                                      idx = ((ep_addr & 0x7f)-1)*2;   /* get endpoint base */
++                                      if (ep_addr & 0x80)
++                                              idx++;
++                                      attr = ep->bmAttributes;
++
++                                      if (cmptbl[idx] == EP_NUL) {
++                                              printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d  attr:%d  cmptbl[%d]:%d\n",
++                                                      idx, attr, idx, cmptbl[idx]);
++                                              cfg_found = FALSE;
++                                      }
++
++                                      if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT)
++                                              cmptbl[idx] = EP_NUL;
++                                      if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK)
++                                              cmptbl[idx] = EP_NUL;
++                                      if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO)
++                                              cmptbl[idx] = EP_NUL;
++
++                                      // check if all INT endpoints match minimum interval
++                                      if (attr == USB_ENDPOINT_XFER_INT && ep->bInterval < vcf[17]) {
++#ifdef VERBOSE_USB_DEBUG
++                                              if (cfg_found)
++                                                      printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n",
++                                                              vcf[17]);
++#endif
++                                              cfg_found = FALSE;
++                                      }
++
++                                      ep++;
++                              }
++
++                              for (i = 0; i < 16; i++) {
++                                      // printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]);
++
++                                      // all entries must be EP_NOP or EP_NUL for a valid config
++                                      if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL)
++                                              cfg_found = FALSE;
++                              }
++
++                              // we check for smallest match, to provide configuration priority
++                              // configurations with smaller index have higher priority
++                              if (cfg_found) {
++                                      if (cfg_used < small_match) {
++                                              small_match = cfg_used;
++                                              alt_used = probe_alt_setting;
++                                              //iface_used = iface;
++                                              intfdesc_used = intfdesc;
++                                      }
++#ifdef VERBOSE_USB_DEBUG
++                                      printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);
++#endif
++                              }
++
++                              cfg_used++;
++                      }
++
++                      alt_idx++;
++              }               /* (alt_idx < intf->num_altsetting) */
++#ifdef VERBOSE_USB_DEBUG
++              printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);
++#endif
++              // yiipiee, we found a valid config
++              if (small_match != 0xffff) {
++                      //iface = iface_used;
++                      intfdesc = intfdesc_used;
++
++                      if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
++                              return(NULL);  /* got no mem */
++                      memset(context, 0, sizeof(hfcusb_data));        /* clear the structure */
++
++                      ep = intfdesc->endpoint;        /* first endpoint descriptor */
++                      vcf = validconf[small_match];
++
++                      for (i = 0; i < intfdesc->bNumEndpoints; i++) {
++                              ep_addr = ep->bEndpointAddress;
++                              idx = ((ep_addr & 0x7f)-1)*2;   /* get endpoint base */
++                              if (ep_addr & 0x80)
++                                      idx++;
++                              cidx = idx & 7;
++                              attr = ep->bmAttributes;
++
++                              // only initialize used endpoints
++                              if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) {
++                                      switch (attr) {
++                                              case USB_ENDPOINT_XFER_INT:
++                                                      context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->bEndpointAddress);
++                                                      context->fifos[cidx].usb_transfer_mode = USB_INT;
++                                                      packet_size = ep->wMaxPacketSize; // remember max packet size
++#ifdef VERBOSE_USB_DEBUG
++                                                      printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n",
++                                                              ep->bInterval, idx, cidx);
++#endif
++                                                      break;
++                                              case USB_ENDPOINT_XFER_BULK:
++                                                      if (ep_addr & 0x80)
++                                                              context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->bEndpointAddress);
++                                                      else
++                                                              context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->bEndpointAddress);
++                                                      context->fifos[cidx].usb_transfer_mode = USB_BULK;
++                                                      packet_size = ep->wMaxPacketSize; // remember max packet size
++#ifdef VERBOSE_USB_DEBUG
++                                                      printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n",
++                                                              idx, cidx);
++#endif
++                                                      break;
++                                              case USB_ENDPOINT_XFER_ISOC:
++                                                      if (ep_addr & 0x80)
++                                                              context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->bEndpointAddress);
++                                                      else
++                                                              context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->bEndpointAddress);
++                                                      context->fifos[cidx].usb_transfer_mode = USB_ISOC;
++                                                      iso_packet_size = ep->wMaxPacketSize; // remember max packet size
++#ifdef VERBOSE_USB_DEBUG
++                                                      printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n",
++                                                              idx, cidx);
++#endif
++                                                      break;
++                                              default:
++                                                      context->fifos[cidx].pipe = 0;  /* reset data */
++                                      }       /* switch attribute */
++
++                                      if (context->fifos[cidx].pipe) {
++                                              context->fifos[cidx].fifonum = cidx;
++                                              context->fifos[cidx].hfc = context;
++                                              context->fifos[cidx].usb_packet_maxlen = ep->wMaxPacketSize;
++                                              context->fifos[cidx].intervall = ep->bInterval;
++                                              context->fifos[cidx].skbuff = NULL;
++#ifdef VERBOSE_USB_DEBUG
++                                              printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n",
++                                                      context->fifos[cidx].fifonum,
++                                                      context->fifos[cidx].usb_packet_maxlen,
++                                                      context->fifos[cidx].intervall);
++#endif
++                                      }
++                              }
++
++                              ep++;
++                      }
++
++                      // now share our luck
++                      context->dev = dev;                                             /* save device */
++                      context->if_used = ifnum;                                       /* save used interface */
++                      context->alt_used = alt_used;                                   /* and alternate config */
++                      context->ctrl_paksize = dev->descriptor.bMaxPacketSize0;        /* control size */
++                      context->cfg_used=vcf[16];                                      // store used config
++                      context->vend_idx=vend_idx;                                     // store found vendor
++                      context->packet_size=packet_size;
++                      context->iso_packet_size=iso_packet_size;
++
++                      /* create the control pipes needed for register access */
++                      context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
++                      context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
++                      context->ctrl_urb = usb_alloc_urb(0);
++
++                      printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n",
++                              vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used);
++
++                      /* init the chip and register the driver */
++                      if (usb_init(context))
++                      {
++                              if (context->ctrl_urb) {
++                                      usb_unlink_urb(context->ctrl_urb);
++                                      usb_free_urb(context->ctrl_urb);
++                                      context->ctrl_urb = NULL;
++                              }
++                              kfree(context);
++                              return(NULL);
++                      }
++                      //usb_set_intfdata(intf, context);
++                      //intf->private_data = context;
++                      return(context);
++              } 
++      }
++      return(NULL);
++}
+ /****************************************************/
+ /* function called when an active device is removed */
+ /****************************************************/
+-static void
+-hfc_usb_disconnect(struct usb_device *usbdev, void *drv_context)
++//static void hfc_usb_disconnect(struct usb_interface *intf)
++static void hfc_usb_disconnect(struct usb_device *usbdev, void* drv_context)
+ {
+-      hfcusb_data *context = drv_context;
++        //hfcusb_data *context = intf->private_data;
++        hfcusb_data* context = drv_context;
+       int i;
+-      struct sk_buff *skb;
+-      /* tell all fifos to terminate */
+-      for (i = 0; i < HFCUSB_NUM_FIFOS; i++)
+-              if (context->fifos[i].active) {
+-                      context->fifos[i].active = 0;
+-                      usb_unlink_urb(&context->fifos[i].urb);
+-              }
+-      while (context->active_fifos) {
+-              set_current_state(TASK_INTERRUPTIBLE);
+-              /* Timeout 10ms */
+-              schedule_timeout((10 * HZ) / 1000);
+-      }
++      printk(KERN_INFO "HFC-USB: device disconnect\n");
++      
++      //intf->private_data = NULL;
++      if (!context)
++              return;
+       if (timer_pending(&context->t3_timer))
+               del_timer(&context->t3_timer);
+-      context->regd.release_driver(context->regd.arg_hisax);
+-      while ((skb = skb_dequeue(&context->regd.erq)) != NULL)
+-              dev_kfree_skb_any(skb);
++      if (timer_pending(&context->t4_timer))
++              del_timer(&context->t4_timer);
++      if (timer_pending(&context->led_timer))
++              del_timer(&context->led_timer);
++
++      hisax_unregister(&context->d_if);
++      /* tell all fifos to terminate */
++      for(i = 0; i < HFCUSB_NUM_FIFOS; i++) {
++              if(context->fifos[i].usb_transfer_mode == USB_ISOC) {
++                      if(context->fifos[i].active > 0) {
++                              stop_isoc_chain(&context->fifos[i]);
++#ifdef VERBOSE_USB_DEBUG
++                              printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i);
++#endif
++                      }
++              } else {
++                      if(context->fifos[i].active > 0) {
++                              context->fifos[i].active = 0;
++#ifdef VERBOSE_USB_DEBUG
++                              printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i);
++#endif
++                      }
++                      if (context->fifos[i].urb) {
++                              usb_unlink_urb(context->fifos[i].urb);
++                              usb_free_urb(context->fifos[i].urb);
++                              context->fifos[i].urb = NULL;
++                      }
++              }
++              context->fifos[i].active = 0;
++      }
++      if (context->ctrl_urb) {
++              usb_unlink_urb(context->ctrl_urb);
++              usb_free_urb(context->ctrl_urb);
++              context->ctrl_urb = NULL;
++      }
+       kfree(context);         /* free our structure again */
+-      MOD_DEC_USE_COUNT;      /* and decrement the usage counter */
+ }                             /* hfc_usb_disconnect */
++
+ /************************************/
+ /* our driver information structure */
+ /************************************/
+ static struct usb_driver hfc_drv = {
+       name:"hfc_usb",
+-#ifdef COMPAT_HAS_USB_IDTAB
+       id_table:hfc_usb_idtab,
+-#endif
+       probe:hfc_usb_probe,
+       disconnect:hfc_usb_disconnect,
+ };
+-static void __exit
+-hfc_usb_exit(void)
+-{
++static void __exit hfc_usb_exit(void)
++{
++#ifdef VERBOSE_USB_DEBUG
++      printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n");
++#endif
+       usb_deregister(&hfc_drv);       /* release our driver */
+       printk(KERN_INFO "HFC-USB module removed\n");
+ }
+-static int __init
+-hfc_usb_init(void)
++static int __init hfc_usb_init(void)
+ {
+-      struct hisax_drvreg drv;
++      printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision);
+-      drv.version = HISAX_LOAD_VERSION;       /* set our version */
+-      drv.cmd = HISAX_LOAD_CHKVER;    /* check command only */
+-      if (hisax_register_hfcusb(&drv)) {
+-              printk(KERN_INFO "HFC-USB <-> hisax version conflict\n");
+-              return (-1);    /* unable to register */
+-      }
+-      if (usb_register(&hfc_drv)) {
+-              printk(KERN_INFO
+-                     "Unable to register HFC-USB module at usb stack\n");
+-              return (-1);    /* unable to register */
++      if(usb_register(&hfc_drv))
++      {
++              printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n");
++              return(-1);                /* unable to register */
+       }
+-
+-      printk(KERN_INFO "HFC-USB module loaded\n");
+-      return (0);
++      return(0);
+ }
++
++
++
++
+ module_init(hfc_usb_init);
+ module_exit(hfc_usb_exit);
++
diff --git a/openwrt/package/linux/kernel-patches/402-pl2303-backport-2-4-29 b/openwrt/package/linux/kernel-patches/402-pl2303-backport-2-4-29
new file mode 100644 (file)
index 0000000..8577499
--- /dev/null
@@ -0,0 +1,738 @@
+diff -rNu linux-2.4.29.old/drivers/usb/serial/pl2303.c linux-2.4.29/drivers/usb/serial/pl2303.c
+--- linux-2.4.29.old/drivers/usb/serial/pl2303.c       2005-03-22 14:48:04.000000000 +0100
++++ linux-2.4.29/drivers/usb/serial/pl2303.c   2005-03-22 15:33:05.735943352 +0100
+@@ -1,7 +1,7 @@
+ /*
+  * Prolific PL2303 USB to serial adaptor driver
+  *
+- * Copyright (C) 2001-2003 Greg Kroah-Hartman (greg@kroah.com)
++ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+  * Copyright (C) 2003 IBM Corp.
+  *
+  * Original driver for 2.2.x by anonymous
+@@ -12,8 +12,16 @@
+  *    (at your option) any later version.
+  *
+  * See Documentation/usb/usb-serial.txt for more information on using this driver
+- * 2003_Apr_24 gkh
+- *    Added line error reporting support.  Hopefully it is correct...
++ *
++ *
++ * 2005_Mar_05 grsch
++ *      ported 2.6.8 pl2303.c to 2.4.20 format
++ *      (HX model works fine now, ID table should be brought up to date)
++ *      Gregor Schaffrath <gschaff@ran-dom.org>
++ * 
++ * 2002_Mar_26 gkh
++ *    allowed driver to work properly if there is no tty assigned to a port
++ *    (this happens for serial console devices.)
+  *
+  * 2001_Oct_06 gkh
+  *    Added RTS and DTR line control.  Thanks to joe@bndlg.de for parts of it.
+@@ -33,6 +41,9 @@
+  * 
+  */
++static int debug;
++
++
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -46,43 +57,44 @@
+ #include <linux/spinlock.h>
+ #include <asm/uaccess.h>
+ #include <linux/usb.h>
+-
+-#ifdef CONFIG_USB_SERIAL_DEBUG
+-      static int debug = 1;
+-#else
+-      static int debug;
+-#endif
+-
+ #include "usb-serial.h"
+ #include "pl2303.h"
+ /*
+  * Version Information
+  */
+-#define DRIVER_VERSION "v0.10"
++#define DRIVER_VERSION "v0.11"
+ #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver"
+-
+-
+ static struct usb_device_id id_table [] = {
+       { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) },
+       { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) },
+       { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
+       { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID) },
+-      { USB_DEVICE(ATEN_VENDOR_ID2, ATEN_PRODUCT_ID) },
+       { USB_DEVICE(ELCOM_VENDOR_ID, ELCOM_PRODUCT_ID) },
+       { USB_DEVICE(ITEGNO_VENDOR_ID, ITEGNO_PRODUCT_ID) },
+       { USB_DEVICE(MA620_VENDOR_ID, MA620_PRODUCT_ID) },
+-      { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
+-      { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
+-      { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
+-      { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
+-      { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
++        { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID) },
++        { USB_DEVICE(TRIPP_VENDOR_ID, TRIPP_PRODUCT_ID) },
++        { USB_DEVICE(RADIOSHACK_VENDOR_ID, RADIOSHACK_PRODUCT_ID) },
++        { USB_DEVICE(DCU10_VENDOR_ID, DCU10_PRODUCT_ID) },
++        { USB_DEVICE(SITECOM_VENDOR_ID, SITECOM_PRODUCT_ID) },
++        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_ID) },
++        { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_ID) },
+       { }                                     /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE (usb, id_table);
++/*
++static struct usb_driver pl2303_driver = {
++      .owner =        THIS_MODULE,
++      .name =         "pl2303",
++      .probe =        usb_serial_probe,
++      .disconnect =   usb_serial_disconnect,
++      .id_table =     id_table,
++};
++*/
+ #define SET_LINE_REQUEST_TYPE         0x21
+ #define SET_LINE_REQUEST              0x20
+@@ -130,6 +142,9 @@
+ static int pl2303_write (struct usb_serial_port *port, int from_user,
+                        const unsigned char *buf, int count);
+ static void pl2303_break_ctl(struct usb_serial_port *port,int break_state);
++static int pl2303_tiocmget (struct usb_serial_port *port, struct file *file);
++static int pl2303_tiocmset (struct usb_serial_port *port, struct file *file,
++                          unsigned int set, unsigned int clear);
+ static int pl2303_startup (struct usb_serial *serial);
+ static void pl2303_shutdown (struct usb_serial *serial);
+@@ -149,27 +164,48 @@
+       .ioctl =                pl2303_ioctl,
+       .break_ctl =            pl2303_break_ctl,
+       .set_termios =          pl2303_set_termios,
++      //.tiocmget =           pl2303_tiocmget,
++      //.tiocmset =           pl2303_tiocmset,
+       .read_bulk_callback =   pl2303_read_bulk_callback,
+       .read_int_callback =    pl2303_read_int_callback,
+       .write_bulk_callback =  pl2303_write_bulk_callback,
++      //.attach =             pl2303_startup,
+       .startup =              pl2303_startup,
+       .shutdown =             pl2303_shutdown,
+ };
++enum pl2303_type {
++      type_0,         /* don't know the difference between type 0 and */
++      type_1,         /* type 1, until someone from prolific tells us... */
++      HX,             /* HX version of the pl2303 chip */
++};
++
+ struct pl2303_private {
+       spinlock_t lock;
+       wait_queue_head_t delta_msr_wait;
+       u8 line_control;
+       u8 line_status;
+       u8 termios_initialized;
++      enum pl2303_type type;
+ };
+ static int pl2303_startup (struct usb_serial *serial)
+ {
+       struct pl2303_private *priv;
++      enum pl2303_type type = type_0;
+       int i;
++      if (serial->dev->descriptor.bDeviceClass == 0x02)
++              type = type_0;
++      else if (serial->dev->descriptor.bMaxPacketSize0 == 0x40)
++              type = HX;
++      else if (serial->dev->descriptor.bDeviceClass == 0x00)
++              type = type_1;
++      else if (serial->dev->descriptor.bDeviceClass == 0xFF)
++              type = type_1;
++      dbg("device type: %d", type);
++
+       for (i = 0; i < serial->num_ports; ++i) {
+               priv = kmalloc (sizeof (struct pl2303_private), GFP_KERNEL);
+               if (!priv)
+@@ -177,7 +213,8 @@
+               memset (priv, 0x00, sizeof (struct pl2303_private));
+               spin_lock_init(&priv->lock);
+               init_waitqueue_head(&priv->delta_msr_wait);
+-              usb_set_serial_port_data(&serial->port[i], priv);
++              priv->type = type;
++              serial->port[i].private = priv;
+       }
+       return 0;
+ }
+@@ -215,13 +252,13 @@
+               memcpy (port->write_urb->transfer_buffer, buf, count);
+       }
+       
+-      usb_serial_debug_data (__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
++      usb_serial_debug_data(__FILE__, __FUNCTION__, count, port->write_urb->transfer_buffer);
+       port->write_urb->transfer_buffer_length = count;
+       port->write_urb->dev = port->serial->dev;
+       result = usb_submit_urb (port->write_urb);
+       if (result)
+-              err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
++              err("%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
+       else
+               result = count;
+@@ -233,7 +270,7 @@
+ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *old_termios)
+ {
+       struct usb_serial *serial = port->serial;
+-      struct pl2303_private *priv = usb_get_serial_port_data(port);
++      struct pl2303_private *priv = port->private;
+       unsigned long flags;
+       unsigned int cflag;
+       unsigned char *buf;
+@@ -241,8 +278,7 @@
+       int i;
+       u8 control;
+-      dbg("%s -  port %d, initialized = %d", __FUNCTION__, port->number, 
+-           priv->termios_initialized);
++      dbg("%s -  port %d", __FUNCTION__, port->number);
+       if ((!port->tty) || (!port->tty->termios)) {
+               dbg("%s - no tty structures", __FUNCTION__);
+@@ -269,7 +305,7 @@
+       buf = kmalloc (7, GFP_KERNEL);
+       if (!buf) {
+-              err("%s - out of memory.", __FUNCTION__);
++              err("%s - out of memory.\n", __FUNCTION__);
+               return;
+       }
+       memset (buf, 0x00, 0x07);
+@@ -311,7 +347,7 @@
+               case B230400:   baud = 230400;  break;
+               case B460800:   baud = 460800;  break;
+               default:
+-                      err ("pl2303 driver does not support the baudrate requested (fix it)");
++                      err("pl2303 driver does not support the baudrate requested (fix it)\n");
+                       break;
+       }
+       dbg("%s - baud = %d", __FUNCTION__, baud);
+@@ -380,26 +416,30 @@
+            buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]);
+       if (cflag & CRTSCTS) {
+-              i = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
+-                                   VENDOR_WRITE_REQUEST, VENDOR_WRITE_REQUEST_TYPE,
+-                                   0x0, 0x41, NULL, 0, 100);
+-              dbg ("0x40:0x1:0x0:0x41  %d", i);
++              __u16 index;
++              if (priv->type == HX)
++                      index = 0x61;
++              else
++                      index = 0x41;
++              i = usb_control_msg(serial->dev, 
++                                  usb_sndctrlpipe(serial->dev, 0),
++                                  VENDOR_WRITE_REQUEST,
++                                  VENDOR_WRITE_REQUEST_TYPE,
++                                  0x0, index, NULL, 0, 100);
++              dbg ("0x40:0x1:0x0:0x%x  %d", index, i);
+       }
+       kfree (buf);
+-}       
+-
++} 
+ static int pl2303_open (struct usb_serial_port *port, struct file *filp)
+ {
+       struct termios tmp_termios;
+       struct usb_serial *serial = port->serial;
++      struct pl2303_private *priv = port->private;
+       unsigned char *buf;
+       int result;
+-      if (port_paranoia_check (port, __FUNCTION__))
+-              return -ENODEV;
+-              
+       dbg("%s -  port %d", __FUNCTION__, port->number);
+       usb_clear_halt(serial->dev, port->write_urb->pipe);
+@@ -427,6 +467,18 @@
+       SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0x0404, 1);
+       FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0);
+       FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0);
++      SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 0, 1);
++      SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 1, 0);
++ 
++      if (priv->type == HX) {
++              /* HX chip */
++              SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x44);
++              /* reset upstream data pipes */
++              SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 8, 0);
++              SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 9, 0);
++      } else {
++              SOUP (VENDOR_WRITE_REQUEST_TYPE, VENDOR_WRITE_REQUEST, 2, 0x24);
++      }
+       kfree(buf);
+@@ -441,7 +493,7 @@
+       port->read_urb->dev = serial->dev;
+       result = usb_submit_urb (port->read_urb);
+       if (result) {
+-              err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
++              err("%s - failed submitting read urb, error %d\n", __FUNCTION__, result);
+               pl2303_close (port, NULL);
+               return -EPROTO;
+       }
+@@ -450,7 +502,7 @@
+       port->interrupt_in_urb->dev = serial->dev;
+       result = usb_submit_urb (port->interrupt_in_urb);
+       if (result) {
+-              err("%s - failed submitting interrupt urb, error %d", __FUNCTION__, result);
++              err("%s - failed submitting interrupt urb, error %d\n", __FUNCTION__, result);
+               pl2303_close (port, NULL);
+               return -EPROTO;
+       }
+@@ -460,125 +512,103 @@
+ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
+ {
+-      struct usb_serial *serial;
+       struct pl2303_private *priv;
+       unsigned long flags;
+       unsigned int c_cflag;
+       int result;
+-      if (port_paranoia_check (port, __FUNCTION__))
+-              return;
+-      serial = get_usb_serial (port, __FUNCTION__);
+-      if (!serial)
+-              return;
+-      
+       dbg("%s - port %d", __FUNCTION__, port->number);
+-      if (serial->dev) {
+-              if (port->tty) {
+-                      c_cflag = port->tty->termios->c_cflag;
+-                      if (c_cflag & HUPCL) {
+-                              /* drop DTR and RTS */
+-                              priv = usb_get_serial_port_data(port);
+-                              spin_lock_irqsave(&priv->lock, flags);
+-                              priv->line_control = 0;
+-                              spin_unlock_irqrestore (&priv->lock, flags);
+-                              set_control_lines (port->serial->dev, 0);
+-                      }
+-              }
++      /* shutdown our urbs */
++      dbg("%s - shutting down urbs", __FUNCTION__);
++      result = usb_unlink_urb (port->write_urb);
++      if (result)
++              dbg("%s - usb_unlink_urb (write_urb)"
++                  " failed with reason: %d", __FUNCTION__,
++                   result);
+-              /* shutdown our urbs */
+-              dbg("%s - shutting down urbs", __FUNCTION__);
+-              result = usb_unlink_urb (port->write_urb);
+-              if (result)
+-                      dbg("%s - usb_unlink_urb (write_urb)"
+-                          " failed with reason: %d", __FUNCTION__,
+-                           result);
++      result = usb_unlink_urb (port->read_urb);
++      if (result)
++              dbg("%s - usb_unlink_urb (read_urb) "
++                  "failed with reason: %d", __FUNCTION__,
++                   result);
+-              result = usb_unlink_urb (port->read_urb);
+-              if (result)
+-                      dbg("%s - usb_unlink_urb (read_urb) "
+-                          "failed with reason: %d", __FUNCTION__,
+-                           result);
++      result = usb_unlink_urb (port->interrupt_in_urb);
++      if (result)
++              dbg("%s - usb_unlink_urb (interrupt_in_urb)"
++                  " failed with reason: %d", __FUNCTION__,
++                   result);
+-              result = usb_unlink_urb (port->interrupt_in_urb);
+-              if (result)
+-                      dbg("%s - usb_unlink_urb (interrupt_in_urb)"
+-                          " failed with reason: %d", __FUNCTION__,
+-                           result);
++      if (port->tty) {
++              c_cflag = port->tty->termios->c_cflag;
++              if (c_cflag & HUPCL) {
++                      /* drop DTR and RTS */
++                      priv = port->private;
++                      spin_lock_irqsave(&priv->lock, flags);
++                      priv->line_control = 0;
++                      spin_unlock_irqrestore (&priv->lock, flags);
++                      set_control_lines (port->serial->dev, 0);
++              }
+       }
++
+ }
++/* taken from 2.4.20 driver */
+ static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value)
+ {
+-      struct pl2303_private *priv = usb_get_serial_port_data(port);
+-      unsigned long flags;
+-      unsigned int arg;
+-      u8 control;
+-
+-      if (copy_from_user(&arg, value, sizeof(int)))
+-              return -EFAULT;
+-
+-      spin_lock_irqsave (&priv->lock, flags);
+-      switch (cmd) {
+-              case TIOCMBIS:
+-                      if (arg & TIOCM_RTS)
+-                              priv->line_control |= CONTROL_RTS;
+-                      if (arg & TIOCM_DTR)
+-                              priv->line_control |= CONTROL_DTR;
+-                      break;
+-
+-              case TIOCMBIC:
+-                      if (arg & TIOCM_RTS)
+-                              priv->line_control &= ~CONTROL_RTS;
+-                      if (arg & TIOCM_DTR)
+-                              priv->line_control &= ~CONTROL_DTR;
+-                      break;
++  struct pl2303_private *priv = port->private;
++  unsigned int arg;
+-              case TIOCMSET:
+-                      /* turn off RTS and DTR and then only turn
+-                         on what was asked to */
+-                      priv->line_control &= ~(CONTROL_RTS | CONTROL_DTR);
+-                      priv->line_control |= ((arg & TIOCM_RTS) ? CONTROL_RTS : 0);
+-                      priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
+-                      break;
+-      }
+-      control = priv->line_control;
+-      spin_unlock_irqrestore (&priv->lock, flags);
+-
+-      return set_control_lines (port->serial->dev, control);
++  if (copy_from_user(&arg, value, sizeof(int)))
++    return -EFAULT;
++  
++  switch (cmd) {
++  case TIOCMBIS:
++    if (arg & TIOCM_RTS)
++      priv->line_control |= CONTROL_RTS;
++    if (arg & TIOCM_DTR)
++      priv->line_control |= CONTROL_DTR;
++    break;
++    
++  case TIOCMBIC:
++    if (arg & TIOCM_RTS)
++      priv->line_control &= ~CONTROL_RTS;
++    if (arg & TIOCM_DTR)
++      priv->line_control &= ~CONTROL_DTR;
++    break;
++    
++  case TIOCMSET:
++    /* turn off RTS and DTR and then only turn
++       on what was asked to */
++    priv->line_control &= ~(CONTROL_RTS | CONTROL_DTR);
++    priv->line_control |= ((arg & TIOCM_RTS) ? CONTROL_RTS : 0);
++    priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
++    break;
++  }
++  
++  return set_control_lines (port->serial->dev, priv->line_control);
+ }
+ static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
+ {
+-      struct pl2303_private *priv = usb_get_serial_port_data(port);
+-      unsigned long flags;
+-      unsigned int mcr;
+-      unsigned int status;
+-      unsigned int result;
+-
+-      spin_lock_irqsave (&priv->lock, flags);
+-      mcr = priv->line_control;
+-      status = priv->line_status;
+-      spin_unlock_irqrestore (&priv->lock, flags);
+-
+-      result = ((mcr & CONTROL_DTR)           ? TIOCM_DTR : 0)
+-                | ((mcr & CONTROL_RTS)        ? TIOCM_RTS : 0)
+-                | ((status & UART_CTS)        ? TIOCM_CTS : 0)
+-                | ((status & UART_DSR)        ? TIOCM_DSR : 0)
+-                | ((status & UART_RING)       ? TIOCM_RI  : 0)
+-                | ((status & UART_DCD)        ? TIOCM_CD  : 0);
+-
+-      dbg("%s - result = %x", __FUNCTION__, result);
+-
+-      if (copy_to_user(value, &result, sizeof(int)))
+-              return -EFAULT;
+-      return 0;
++  struct pl2303_private *priv = port->private;
++  unsigned int mcr = priv->line_control;
++  unsigned int result;
++  
++  result = ((mcr & CONTROL_DTR)           ? TIOCM_DTR : 0)
++    | ((mcr & CONTROL_RTS)        ? TIOCM_RTS : 0);
++  
++  dbg("%s - result = %x", __FUNCTION__, result);
++  
++  if (copy_to_user(value, &result, sizeof(int)))
++    return -EFAULT;
++  return 0;
+ }
++/* end of 2.4.20 kernel part - grsch */
+ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
+ {
+-      struct pl2303_private *priv = usb_get_serial_port_data(port);
++      struct pl2303_private *priv = port->private;
+       unsigned long flags;
+       unsigned int prevstatus;
+       unsigned int status;
+@@ -617,21 +647,10 @@
+       dbg("%s (%d) cmd = 0x%04x", __FUNCTION__, port->number, cmd);
+       switch (cmd) {
+-              
+-              case TIOCMGET:
+-                      dbg("%s (%d) TIOCMGET", __FUNCTION__, port->number);
+-                      return get_modem_info (port, (unsigned int *)arg);
+-
+-              case TIOCMBIS:
+-              case TIOCMBIC:
+-              case TIOCMSET:
+-                      dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", __FUNCTION__,  port->number);
+-                      return set_modem_info(port, cmd, (unsigned int *) arg);
+-
+               case TIOCMIWAIT:
+                       dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
+                       return wait_modem_info(port, arg);
+-              
++
+               default:
+                       dbg("%s not supported = 0x%04x", __FUNCTION__, cmd);
+                       break;
+@@ -652,7 +671,7 @@
+               state = BREAK_OFF;
+       else
+               state = BREAK_ON;
+-      dbg("%s - turning break %s", __FUNCTION__, state==BREAK_OFF ? "off" : "on");
++      dbg("%s - turning break %s", state==BREAK_OFF ? "off" : "on", __FUNCTION__);
+       result = usb_control_msg (serial->dev, usb_sndctrlpipe (serial->dev, 0),
+                                 BREAK_REQUEST, BREAK_REQUEST_TYPE, state, 
+@@ -669,8 +688,8 @@
+       dbg("%s", __FUNCTION__);
+       for (i = 0; i < serial->num_ports; ++i) {
+-              kfree (usb_get_serial_port_data(&serial->port[i]));
+-              usb_set_serial_port_data(&serial->port[i], NULL);
++              kfree (serial->port[i].private);
++              serial->port[i].private = NULL;
+       }               
+ }
+@@ -678,16 +697,14 @@
+ static void pl2303_read_int_callback (struct urb *urb)
+ {
+       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+-      struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+-      struct pl2303_private *priv = usb_get_serial_port_data(port);
++      struct pl2303_private *priv = port->private;
+       unsigned char *data = urb->transfer_buffer;
+       unsigned long flags;
++      int status;
+       u8 uart_state;
+       dbg("%s (%d)", __FUNCTION__, port->number);
+-      /* ints auto restart... */
+-
+       switch (urb->status) {
+       case 0:
+               /* success */
+@@ -700,17 +717,14 @@
+               return;
+       default:
+               dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+-              return;
++              goto exit;
+       }
+-      if (!serial) {
+-              return;
+-      }
+-      usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
++      usb_serial_debug_data(__FILE__, __FUNCTION__, urb->actual_length, urb->transfer_buffer);
+       if (urb->actual_length < UART_STATE)
+-              return;
++              goto exit;
+       /* Save off the uart status for others to look at */
+       uart_state = data[UART_STATE];
+@@ -718,17 +732,19 @@
+       uart_state |= (priv->line_status & UART_STATE_TRANSIENT_MASK);
+       priv->line_status = uart_state;
+       spin_unlock_irqrestore(&priv->lock, flags);
+-      wake_up_interruptible (&priv->delta_msr_wait);
+-
+-      return;
++              
++exit:
++      status = usb_submit_urb (urb);
++      if (status)
++              err("%s - usb_submit_urb failed with result %d\n",
++                      __FUNCTION__, status);
+ }
+ static void pl2303_read_bulk_callback (struct urb *urb)
+ {
+       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+-      struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
+-      struct pl2303_private *priv = usb_get_serial_port_data(port);
++      struct pl2303_private *priv = port->private;
+       struct tty_struct *tty;
+       unsigned char *data = urb->transfer_buffer;
+       unsigned long flags;
+@@ -737,16 +753,8 @@
+       u8 status;
+       char tty_flag;
+-      if (port_paranoia_check (port, __FUNCTION__))
+-              return;
+-
+       dbg("%s - port %d", __FUNCTION__, port->number);
+-      if (!serial) {
+-              dbg("%s - bad serial pointer, exiting", __FUNCTION__);
+-              return;
+-      }
+-
+       if (urb->status) {
+               dbg("%s - urb->status = %d", __FUNCTION__, urb->status);
+               if (!port->open_count) {
+@@ -757,17 +765,17 @@
+                       /* PL2303 mysteriously fails with -EPROTO reschedule the read */
+                       dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__);
+                       urb->status = 0;
+-                      urb->dev = serial->dev;
++                      urb->dev = port->serial->dev;
+                       result = usb_submit_urb(urb);
+                       if (result)
+-                              err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++                              err("%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+                       return;
+               }
+               dbg("%s - unable to handle the error, exiting.", __FUNCTION__);
+               return;
+       }
+-      usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);
++      usb_serial_debug_data(__FILE__, __FUNCTION__, urb->actual_length, data);
+       /* get tty_flag from status */
+       tty_flag = TTY_NORMAL;
+@@ -776,7 +784,7 @@
+       status = priv->line_status;
+       priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
+       spin_unlock_irqrestore(&priv->lock, flags);
+-      wake_up_interruptible (&priv->delta_msr_wait); //AF from 2.6
++      wake_up_interruptible (&priv->delta_msr_wait);
+       /* break takes precedence over parity, */
+       /* which takes precedence over framing errors */
+@@ -805,10 +813,10 @@
+       /* Schedule the next read _if_ we are still open */
+       if (port->open_count) {
+-              urb->dev = serial->dev;
++              urb->dev = port->serial->dev;
+               result = usb_submit_urb(urb);
+               if (result)
+-                      err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
++                      err("%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result);
+       }
+       return;
+@@ -821,44 +829,32 @@
+       struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
+       int result;
+-      if (port_paranoia_check (port, __FUNCTION__))
+-              return;
+-      
+       dbg("%s - port %d", __FUNCTION__, port->number);
+       
+       if (urb->status) {
+               /* error in the urb, so we have to resubmit it */
+-              if (serial_paranoia_check (port->serial, __FUNCTION__)) {
+-                      return;
+-              }
+               dbg("%s - Overflow in write", __FUNCTION__);
+               dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status);
+               port->write_urb->transfer_buffer_length = 1;
+               port->write_urb->dev = port->serial->dev;
+               result = usb_submit_urb (port->write_urb);
+               if (result)
+-                      err("%s - failed resubmitting write urb, error %d", __FUNCTION__, result);
++                      err("%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result);
+               return;
+       }
+-      queue_task(&port->tqueue, &tq_immediate);
+-      mark_bh(IMMEDIATE_BH);
+-      return;
++        queue_task(&port->tqueue, &tq_immediate);
++        mark_bh(IMMEDIATE_BH);
+ }
+ static int __init pl2303_init (void)
+ {
+-      int retval;
+-      retval = usb_serial_register(&pl2303_device);
+-      if (retval)
+-              goto failed_usb_serial_register;
++      usb_serial_register(&pl2303_device);
+       info(DRIVER_DESC " " DRIVER_VERSION);
+       return 0;
+-failed_usb_serial_register:
+-      return retval;
+ }
+@@ -877,3 +873,4 @@
+ MODULE_PARM(debug, "i");
+ MODULE_PARM_DESC(debug, "Debug enabled or not");
++//this is an error
+diff -rNu linux-2.4.29.old/drivers/usb/serial/pl2303.h linux-2.4.29/drivers/usb/serial/pl2303.h
+--- linux-2.4.29.old/drivers/usb/serial/pl2303.h       2005-03-22 14:48:04.000000000 +0100
++++ linux-2.4.29/drivers/usb/serial/pl2303.h   2005-03-22 15:33:05.758939856 +0100
+@@ -41,3 +41,12 @@
+ #define SITECOM_VENDOR_ID     0x6189
+ #define SITECOM_PRODUCT_ID    0x2068
++
++/* Alcatel OT535/735 USB cable */
++#define ALCATEL_VENDOR_ID     0x11f7
++#define ALCATEL_PRODUCT_ID    0x02df
++
++/* Samsung I330 phone cradle */
++#define SAMSUNG_VENDOR_ID       0x04e8
++#define SAMSUNG_PRODUCT_ID      0x8001
++