diff options
author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2005-04-02 17:17:22 +0000 |
---|---|---|
committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2005-04-02 17:17:22 +0000 |
commit | e3cc2d553a453dcd7776a8ce366bd0df245d8816 (patch) | |
tree | baf9dbc2d2071e12281c8a70fa00011e9b1d5c47 /openwrt/package | |
parent | 65b2fb12e2427c02047ca4d96179f5fca1d36181 (diff) |
add usb isdn and serial driver fixes
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@524 3c298f89-4303-0410-b956-a3cf2f4a3e73
Diffstat (limited to 'openwrt/package')
3 files changed, 23648 insertions, 0 deletions
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 index 0000000000..c9833e2a30 --- /dev/null +++ b/openwrt/package/linux/kernel-patches/400-i4l-cvs-2-4-29 @@ -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 index 0000000000..4ef20fa8ba --- /dev/null +++ b/openwrt/package/linux/kernel-patches/401-hfc-usb-backport-i4l-cvs @@ -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 index 0000000000..8577499b0d --- /dev/null +++ b/openwrt/package/linux/kernel-patches/402-pl2303-backport-2-4-29 @@ -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 ++ |