--- a/Documentation/isdn/CREDITS +++ b/Documentation/isdn/CREDITS @@ -37,7 +37,7 @@ Michael Knigge (knick@cove.han.de) 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) --- a/Documentation/isdn/HiSax.cert +++ b/Documentation/isdn/HiSax.cert @@ -68,6 +68,8 @@ drivers/isdn/hisax/cert.c 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. --- a/Documentation/isdn/INTERFACE +++ b/Documentation/isdn/INTERFACE @@ -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 @@ Description of the Interface between Lin 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 @@ Description of the Interface between Lin 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) + --- a/Documentation/isdn/INTERFACE.fax +++ b/Documentation/isdn/INTERFACE.fax @@ -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 --- a/Documentation/isdn/README +++ b/Documentation/isdn/README @@ -278,6 +278,12 @@ README for the ISDN-subsystem 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. --- a/Documentation/isdn/README.HiSax +++ b/Documentation/isdn/README.HiSax @@ -41,10 +41,9 @@ ELSA Quickstep 3000 (same settings as QS 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 Card (Speed Win, Teledat 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 @@ Gazel ISDN cards 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 @@ There is also some config needed before 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 @@ Card types: 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 @@ Examples for module loading (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 @@ type 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 ------------------ --- a/Documentation/isdn/README.act2000 +++ b/Documentation/isdn/README.act2000 @@ -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. --- a/Documentation/isdn/README.audio +++ b/Documentation/isdn/README.audio @@ -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. --- a/Documentation/isdn/README.eicon +++ b/Documentation/isdn/README.eicon @@ -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) --- a/Documentation/isdn/README.hysdn +++ b/Documentation/isdn/README.hysdn @@ -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 --- a/Documentation/isdn/README.icn +++ b/Documentation/isdn/README.icn @@ -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: --- a/Documentation/isdn/README.pcbit +++ b/Documentation/isdn/README.pcbit @@ -37,4 +37,4 @@ mailing list (isdn4linux@listserv.isdn4l regards, Pedro. - + --- /dev/null +++ b/Documentation/isdn/abcext_kernel.help @@ -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 + --- a/drivers/isdn/Config.in +++ b/drivers/isdn/Config.in @@ -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 @@ if [ "$CONFIG_X25" != "n" ]; then 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 @@ mainmenu_option next_comment 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 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; 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 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; 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 --- a/drivers/isdn/Makefile +++ b/drivers/isdn/Makefile @@ -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 @@ obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_ # 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 --- a/drivers/isdn/act2000/act2000.h +++ b/drivers/isdn/act2000/act2000.h @@ -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 @@ typedef struct act2000_card { 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); --- a/drivers/isdn/act2000/act2000_isa.c +++ b/drivers/isdn/act2000/act2000_isa.c @@ -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 @@ act2000_isa_config_port(act2000_card * c 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 @@ act2000_isa_send(act2000_card * card) 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 @@ act2000_isa_send(act2000_card * card) } else dev_kfree_skb(skb); card->sbuf = NULL; +#if 0 + printk(KERN_DEBUG "act2000_isa_send: %d bytes\n", l); +#endif } } --- a/drivers/isdn/act2000/act2000_isa.h +++ b/drivers/isdn/act2000/act2000_isa.h @@ -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). * --- a/drivers/isdn/act2000/capi.c +++ b/drivers/isdn/act2000/capi.c @@ -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 @@ static actcapi_msgdsc valid_msg[] = { {{ 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}, }; --- a/drivers/isdn/act2000/capi.h +++ b/drivers/isdn/act2000/capi.h @@ -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 @@ typedef struct actcapi_msg { __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 @@ typedef struct actcapi_msg { __u8 controller; __u16 info __attribute__ ((packed)); } listen_conf; +#endif struct data_b3_req { __u16 fakencci; __u16 datalen; @@ -330,7 +344,7 @@ typedef struct actcapi_msg { } msg; } actcapi_msg; -static inline unsigned short +extern __inline__ unsigned short actcapi_nextsmsg(act2000_card *card) { unsigned long flags; --- a/drivers/isdn/act2000/module.c +++ b/drivers/isdn/act2000/module.c @@ -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 @@ act2000_alloccard(int bus, int port, int 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 @@ static void __exit act2000_exit(void) } 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); --- a/drivers/isdn/avmb1/avm_cs.c +++ b/drivers/isdn/avmb1/avm_cs.c @@ -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 * --- a/drivers/isdn/avmb1/avmcard.h +++ b/drivers/isdn/avmb1/avmcard.h @@ -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 * --- a/drivers/isdn/avmb1/b1.c +++ b/drivers/isdn/avmb1/b1.c @@ -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 #include #include +#include #include #include #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 $"; /* ------------------------------------------------------------- */ --- a/drivers/isdn/avmb1/b1dma.c +++ b/drivers/isdn/avmb1/b1dma.c @@ -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 #include #include +#include #include #include #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 @@ int b1dmactl_read_proc(char *page, char __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 @@ int b1dmactl_read_proc(char *page, char 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); --- a/drivers/isdn/avmb1/b1isa.c +++ b/drivers/isdn/avmb1/b1isa.c @@ -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 #include #include +#include #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 $"; /* ------------------------------------------------------------- */ --- a/drivers/isdn/avmb1/b1pci.c +++ b/drivers/isdn/avmb1/b1pci.c @@ -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 #include #include +#include #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 @@ static int add_card(struct pci_dev *dev) } 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 @@ static int add_card(struct pci_dev *dev) } } 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", --- a/drivers/isdn/avmb1/b1pcmcia.c +++ b/drivers/isdn/avmb1/b1pcmcia.c @@ -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 $"; /* ------------------------------------------------------------- */ --- a/drivers/isdn/avmb1/c4.c +++ b/drivers/isdn/avmb1/c4.c @@ -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 #include #include +#include #include #include #include @@ -30,7 +31,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 @@ -39,6 +40,7 @@ static char *revision = "$Revision: 1.1. 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 }, @@ -46,6 +48,7 @@ static struct pci_device_id c4_pci_tbl[] }; MODULE_DEVICE_TABLE(pci, c4_pci_tbl); +#endif MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -1332,9 +1335,9 @@ static int __init search_cards(struct ca } 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", --- a/drivers/isdn/avmb1/capi.c +++ b/drivers/isdn/avmb1/capi.c @@ -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 #include #include +#include #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE #include #ifdef CONFIG_PPP @@ -30,6 +31,9 @@ #include #include #undef CAPI_PPP_ON_RAW_DEVICE +#ifdef CAPI_PPP_ON_RAW_DEVICE +#include +#endif /* CAPI_PPP_ON_RAW_DEVICE */ #endif /* CONFIG_PPP */ #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ #include @@ -38,14 +42,16 @@ #include #include #include +#ifdef HAVE_DEVFS_FS #include +#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 capiminor { 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 @@ struct capiminor { /* 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 capincci { 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 capidev *capidev_openlist 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 @@ static int capincci_add_ack(struct capim 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 @@ static int capiminor_del_ack(struct capi 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 @@ static int capiminor_del_ack(struct capi 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 @@ static void capiminor_del_all_ack(struct 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 @@ static void capiminor_del_all_ack(struct /* -------- 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 @@ static struct capiminor *capiminor_alloc return mp; } -static void capiminor_free(struct capiminor *mp) +void capiminor_free(struct capiminor *mp) { struct capiminor **pp; @@ -271,7 +301,11 @@ static void capiminor_free(struct capimi 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 void capiminor_free(struct capimi } } -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 @@ static struct capiminor *capiminor_find( /* -------- 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 @@ static struct capincci *capincci_alloc(s 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 @@ static struct capincci *capincci_alloc(s 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 @@ static void capincci_free(struct capidev } } #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 void capincci_free(struct capidev } } -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 @@ static struct capidev *capidev_alloc(str 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 @@ static void capidev_free(struct capidev 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 @@ static struct capidev *capidev_find(u16 #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 @@ gen_data_b3_resp_for(struct capiminor *m 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 @@ static int handle_recv_skb(struct capimi 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 @@ static int handle_recv_skb(struct capimi 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 void handle_minor_recv(struct cap } } -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 @@ static int handle_minor_send(struct capi 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 @@ static int handle_minor_send(struct capi 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 @@ static int handle_minor_send(struct capi #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 @@ static void capi_signal(u16 applid, void #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 @@ capi_write(struct file *file, const char 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 @@ capi_ioctl(struct inode *inode, struct f 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 @@ capi_ioctl(struct inode *inode, struct f 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 @@ capi_release(struct inode *inode, struct 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 @@ capinc_raw_ioctl(struct inode *inode, st 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 @@ capinc_raw_release(struct inode *inode, 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 @@ static struct file_operations capinc_raw /* -------- 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 @@ static int capinc_tty_open(struct tty_st 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 @@ static void capinc_tty_close(struct tty_ #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 @@ static int capinc_tty_write(struct tty_s 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_put_char(struct t } } -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 @@ static void capinc_tty_flush_chars(struc (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 @@ static int capinc_tty_write_room(struct 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 @@ static int capinc_tty_chars_in_buffer(st 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 @@ static int capinc_tty_ioctl(struct tty_s 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 @@ static void capinc_tty_throttle(struct t 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_unthrottle(struct } } -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_stop(struct tty_s } } -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_start(struct tty_ } } -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 tty_struct *capinc_tty_tab 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 @@ static int capinc_tty_init(void) 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 @@ static void __exit proc_exit(void) /* -------- 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 @@ static int __init alloc_init(void) #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 @@ static int __init capi_init(void) 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 @@ static int __init capi_init(void) #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 @@ static int __init capi_init(void) } #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 @@ static int __init capi_init(void) 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 int __init capi_init(void) 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); } --- a/drivers/isdn/avmb1/capicmd.h +++ b/drivers/isdn/avmb1/capicmd.h @@ -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 * --- a/drivers/isdn/avmb1/capidev.h +++ b/drivers/isdn/avmb1/capidev.h @@ -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 * --- a/drivers/isdn/avmb1/capidrv.c +++ b/drivers/isdn/avmb1/capidrv.c @@ -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 @@ struct capidrv_contr { int oldstate; /* */ __u16 datahandle; - spinlock_t lock; struct ncci_datahandle_queue { struct ncci_datahandle_queue *next; __u16 datahandle; @@ -423,7 +422,6 @@ static inline capidrv_ncci *new_ncci(cap 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 @@ static int capidrv_add_ack(struct capidr __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 @@ static int capidrv_add_ack(struct capidr 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 int capidrv_del_ack(struct capidr 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 @@ static int if_sendbuf(int id, int channe (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 @@ static void enable_dchannel_trace(capidr 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 @@ static int capidrv_delcontr(__u16 contr) 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; --- a/drivers/isdn/avmb1/capidrv.h +++ b/drivers/isdn/avmb1/capidrv.h @@ -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) * --- a/drivers/isdn/avmb1/capifs.c +++ b/drivers/isdn/avmb1/capifs.c @@ -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 * @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -32,7 +33,7 @@ MODULE_DESCRIPTION("CAPI4Linux: /dev/cap 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 inline struct capifs_sb_info *SBI 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 @@ static int capifs_root_readdir(struct fi 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 @@ static int capifs_root_readdir(struct fi 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 @@ static struct dentry *capifs_root_lookup 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 @@ static void capifs_put_super(struct supe 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 @@ static void capifs_put_super(struct supe 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 super_block *capifs_read_super(st 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 @@ struct super_block *capifs_read_super(st /* * 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 @@ struct super_block *capifs_read_super(st 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 @@ struct super_block *capifs_read_super(st 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 @@ static int capifs_statfs(struct super_bl 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 @@ static struct inode *capifs_new_inode(st } 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 @@ void capifs_new_ncci(char type, unsigned 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 } } } --- a/drivers/isdn/avmb1/capifs.h +++ b/drivers/isdn/avmb1/capifs.h @@ -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 * --- a/drivers/isdn/avmb1/capilli.h +++ b/drivers/isdn/avmb1/capilli.h @@ -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 * --- a/drivers/isdn/avmb1/capiutil.c +++ b/drivers/isdn/avmb1/capiutil.c @@ -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 #include #include +#include #include "capiutil.h" MODULE_DESCRIPTION("CAPI4Linux: CAPI message conversion support"); --- a/drivers/isdn/avmb1/capiutil.h +++ b/drivers/isdn/avmb1/capiutil.h @@ -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 * --- a/drivers/isdn/avmb1/kcapi.c +++ b/drivers/isdn/avmb1/kcapi.c @@ -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 #include #include +#include #include #include #include @@ -33,7 +34,7 @@ #include #endif -static char *revision = "$Revision: 1.1.4.1 $"; +static char *revision = "$Revision: 1.28 $"; /* ------------------------------------------------------------- */ @@ -64,7 +65,6 @@ struct capi_ncci { __u32 ncci; __u32 winsize; int nmsg; - spinlock_t lock; struct msgidqueue *msgidqueue; struct msgidqueue *msgidlast; struct msgidqueue *msgidfree; @@ -104,14 +104,14 @@ static char capi_manufakturer[64] = "AVM #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 @@ static int notify_push(unsigned int cmd, * 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 int notify_push(unsigned int cmd, 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 @@ static void notify_handler(void *dummy) kfree(np); MOD_DEC_USE_COUNT; } +#ifdef COMPAT_HAS_SCHEDULE_TASK MOD_DEC_USE_COUNT; +#endif } /* -------- NCCI Handling ------------------------------------- */ @@ -647,7 +647,6 @@ static void notify_handler(void *dummy) 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 void mq_init(struct capi_n 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 @@ static inline int mq_enqueue(struct capi 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 @@ static inline int mq_dequeue(struct capi 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 @@ static void controllercb_appl_released(s 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 @@ error: 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); --- a/drivers/isdn/avmb1/t1isa.c +++ b/drivers/isdn/avmb1/t1isa.c @@ -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 #include #include +#include #include #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 $"; /* ------------------------------------------------------------- */ --- a/drivers/isdn/avmb1/t1pci.c +++ b/drivers/isdn/avmb1/t1pci.c @@ -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 #include #include +#include #include #include #include @@ -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 @@ static int __init t1pci_init(void) } 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", --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -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 #include #include +#ifndef COMPAT_USE_MODCOUNT_LOCK #include +#endif #ifdef CONFIG_PROC_FS #include #else #include #endif #include +#include #include "isdn_divert.h" /*********************************/ @@ -80,7 +83,6 @@ static ssize_t 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 @@ isdn_divert_read(struct file *file, char 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 @@ isdn_divert_open(struct inode *ino, stru { 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 @@ isdn_divert_close(struct inode *ino, str 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 @@ isdn_divert_close(struct inode *ino, str 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 @@ static struct file_operations isdn_fops 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 @@ divert_dev_init(void) 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); --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -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 @@ static void deflect_timer_expire(ulong a 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 @@ int isdn_divert_icall(isdn_ctrl *ic) 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 @@ int isdn_divert_icall(isdn_ctrl *ic) 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 @@ int prot_stat_callback(isdn_ctrl *ic) } +#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: --- a/drivers/isdn/divert/isdn_divert.h +++ b/drivers/isdn/divert/isdn_divert.h @@ -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 @@ typedef struct 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 */ --- a/drivers/isdn/eicon/Divas_mod.c +++ b/drivers/isdn/eicon/Divas_mod.c @@ -20,6 +20,7 @@ #include "adapter.h" #include "uxio.h" +#include MODULE_DESCRIPTION("ISDN4Linux: Driver for Eicon Diva Server cards"); MODULE_AUTHOR("Armin Schindler"); --- a/drivers/isdn/eicon/common.c +++ b/drivers/isdn/eicon/common.c @@ -808,9 +808,7 @@ void DivasDoDpc(void *pData) while(i--) { - if (card->state == DIA_RUNNING) - DivaDoCardDpc(card); - card++; + DivaDoCardDpc(card++); } } --- a/drivers/isdn/eicon/eicon.h +++ b/drivers/isdn/eicon/eicon.h @@ -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. * @@ -347,19 +347,19 @@ typedef struct eicon_card { 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); --- a/drivers/isdn/eicon/eicon_dsp.h +++ b/drivers/isdn/eicon/eicon_dsp.h @@ -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 --- a/drivers/isdn/eicon/eicon_idi.c +++ b/drivers/isdn/eicon/eicon_idi.c @@ -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 @@ idi_faxdata_rcv(eicon_card *ccard, eicon 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 @@ idi_faxdata_send(eicon_card *ccard, eico 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 @@ idi_handle_ind(eicon_card *ccard, struct } 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) { --- a/drivers/isdn/eicon/eicon_idi.h +++ b/drivers/isdn/eicon/eicon_idi.h @@ -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 --- a/drivers/isdn/eicon/eicon_io.c +++ b/drivers/isdn/eicon/eicon_io.c @@ -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. --- a/drivers/isdn/eicon/eicon_isa.c +++ b/drivers/isdn/eicon/eicon_isa.c @@ -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 int eicon_isa_valid_irq[] = { 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 @@ eicon_isa_find_card(int Mem, int Irq, ch 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 @@ eicon_isa_find_card(int Mem, int Irq, ch 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 @@ eicon_isa_bootload(eicon_isa_card *card, 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 @@ eicon_isa_bootload(eicon_isa_card *card, } 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 --- a/drivers/isdn/eicon/eicon_isa.h +++ b/drivers/isdn/eicon/eicon_isa.h @@ -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. * --- a/drivers/isdn/eicon/eicon_mod.c +++ b/drivers/isdn/eicon/eicon_mod.c @@ -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 @@ if_command(isdn_ctrl * c) 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 @@ if_readstatus(u_char * buf, int len, int 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 @@ eicon_exit(void) #ifndef MODULE +#ifdef COMPAT_HAS_NEW_SETUP static int __init eicon_setup(char *line) { @@ -1467,6 +1477,12 @@ eicon_setup(char *line) 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 @@ eicon_setup(char *line) #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 */ --- a/drivers/isdn/eicon/eicon_pci.c +++ b/drivers/isdn/eicon/eicon_pci.c @@ -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 --- a/drivers/isdn/eicon/eicon_pci.h +++ b/drivers/isdn/eicon/eicon_pci.h @@ -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). * --- a/drivers/isdn/eicon/fourbri.c +++ b/drivers/isdn/eicon/fourbri.c @@ -337,8 +337,7 @@ static int diva_server_4bri_load(card_t 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")); --- a/drivers/isdn/eicon/kprintf.c +++ b/drivers/isdn/eicon/kprintf.c @@ -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 @@ void DivasPrintf(char *fmt, ...) /* 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); --- a/drivers/isdn/eicon/lincfg.c +++ b/drivers/isdn/eicon/lincfg.c @@ -26,6 +26,9 @@ #include "uxio.h" #include +#ifndef COMPAT_HAS_2_2_PCI +#include +#endif #include #include --- a/drivers/isdn/eicon/linchr.c +++ b/drivers/isdn/eicon/linchr.c @@ -154,17 +154,17 @@ ssize_t do_read(struct file *pFile, char 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); } --- a/drivers/isdn/eicon/linio.c +++ b/drivers/isdn/eicon/linio.c @@ -15,6 +15,7 @@ #include #include #include +#include #undef N_DATA #include "uxio.h" --- a/drivers/isdn/hisax/Makefile +++ b/drivers/isdn/hisax/Makefile @@ -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_AVM_A1_PCMCIA) 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_NETJET_U) += n 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_BKM_A4T) += bk 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 @@ hisax-objs += $(sort $(hisax-objs-y)) 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) --- /dev/null +++ b/drivers/isdn/hisax/amd7930.c @@ -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 + * + * 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 + +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); +} --- a/drivers/isdn/hisax/arcofi.c +++ b/drivers/isdn/hisax/arcofi.c @@ -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 * --- a/drivers/isdn/hisax/arcofi.h +++ b/drivers/isdn/hisax/arcofi.h @@ -1,4 +1,4 @@ -/* $Id: arcofi.h,v 1.1.4.1 2001/11/20 14:19:35 kai Exp $ +/* $Id$ * * Ansteuerung ARCOFI 2165 * --- a/drivers/isdn/hisax/asuscom.c +++ b/drivers/isdn/hisax/asuscom.c @@ -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 -#include #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 @@ Asus_card_msg(struct IsdnCardState *cs, 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 @@ setup_asuscom(struct IsdnCard *card) 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]; --- a/drivers/isdn/hisax/avm_a1.c +++ b/drivers/isdn/hisax/avm_a1.c @@ -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 --- a/drivers/isdn/hisax/avm_a1p.c +++ b/drivers/isdn/hisax/avm_a1p.c @@ -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) --- a/drivers/isdn/hisax/avm_pci.c +++ b/drivers/isdn/hisax/avm_pci.c @@ -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 -#include +#include #include 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 @@ hdlc_empty_fifo(struct BCState *bcs, int 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 @@ hdlc_fill_fifo(struct BCState *bcs) } 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 @@ AVM_card_msg(struct IsdnCardState *cs, i } 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 @@ setup_avm_pcipnp(struct IsdnCard *card) 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 @@ setup_avm_pcipnp(struct IsdnCard *card) } 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 @@ setup_avm_pcipnp(struct IsdnCard *card) 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 --- a/drivers/isdn/hisax/bkm_a4t.c +++ b/drivers/isdn/hisax/bkm_a4t.c @@ -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 +#include #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 @@ setup_bkm_a4t(struct IsdnCard *card) 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; } --- a/drivers/isdn/hisax/bkm_a8.c +++ b/drivers/isdn/hisax/bkm_a8.c @@ -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 +#include #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 @@ setup_sct_quadro(struct IsdnCard *card) 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 @@ setup_sct_quadro(struct IsdnCard *card) 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 */ } --- a/drivers/isdn/hisax/bkm_ax.h +++ b/drivers/isdn/hisax/bkm_ax.h @@ -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) * --- a/drivers/isdn/hisax/callc.c +++ b/drivers/isdn/hisax/callc.c @@ -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 @@ -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 @@ enum { 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 @@ static char *strEvent[] = "EV_PROCEED", "EV_ALERT", "EV_REDIR", + "EV_ALERTING", + "EV_PROCEEDING", }; @@ -286,6 +290,22 @@ lli_prep_dialout(struct FsmInst *fi, int } 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 @@ static struct FsmNode fnlist[] __initdat {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 @@ static void stat_redir_result(struct Isd 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 @@ dchan_l3l4(struct PStack *st, int pr, vo 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; --- a/drivers/isdn/hisax/cert.c +++ b/drivers/isdn/hisax/cert.c @@ -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 --- a/drivers/isdn/hisax/config.c +++ b/drivers/isdn/hisax/config.c @@ -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 @@ -24,6 +24,11 @@ #include #include #include + +#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 @@ const char *CardType[] = { "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 @@ EXPORT_SYMBOL(HiSax_closecard); 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 @@ static int io[HISAX_MAX_CARDS] __devinit #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 @@ void __init HiSaxVersion(void) } #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 @@ static int __init HiSax_setup(char *line 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 @@ static int __init HiSax_setup(char *line } 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_hfcs(struct IsdnCard *c 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_w6692(struct IsdnCard * 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 @@ static int __devinit init_card(struct Is 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 @@ static int __devinit checkcard(int cardn 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 @@ static int __devinit checkcard(int cardn 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 @@ static int __devinit checkcard(int cardn 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 @@ int __devinit HiSax_inithardware(int *bu 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 @@ void HiSax_reportcard(int cardnr, int se #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 @@ static int __init HiSax_init(void) 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 @@ static int __init HiSax_init(void) } 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 @@ static int __init HiSax_init(void) 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 @@ int elsa_init_pcmcia(void *pcm_iob, int 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 @@ int elsa_init_pcmcia(void *pcm_iob, int 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 @@ int hfc_init_pcmcia(void *pcm_iob, int p 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 @@ int hfc_init_pcmcia(void *pcm_iob, int p 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 @@ int sedl_init_pcmcia(void *pcm_iob, int 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 @@ int sedl_init_pcmcia(void *pcm_iob, int 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 @@ int avm_a1_init_pcmcia(void *pcm_iob, in 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 @@ int avm_a1_init_pcmcia(void *pcm_iob, in 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 @@ int __devinit hisax_init_pcmcia(void *pc 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 @@ int hisax_register(struct hisax_d_if *hi 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 @@ static struct pci_device_id hisax_pci_tb {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_DEVICE_TABLE(pci, hisax_pci_tbl); 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); --- a/drivers/isdn/hisax/diva.c +++ b/drivers/isdn/hisax/diva.c @@ -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 -#include +#include 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 @@ const char *Diva_revision = "$Revision: #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 @@ const char *Diva_revision = "$Revision: #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 @@ MemWriteHSCX(struct IsdnCardState *cs, i 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 @@ Memhscx_int_main(struct IsdnCardState *c 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 @@ Memhscx_int_main(struct IsdnCardState *c 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 @@ Memhscx_int_main(struct IsdnCardState *c } 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 @@ Start_IPACPCI: 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 @@ reset_diva(struct IsdnCardState *cs) 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 @@ diva_led_handler(struct IsdnCardState *c { 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 @@ Diva_card_msg(struct IsdnCardState *cs, 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 @@ Diva_card_msg(struct IsdnCardState *cs, } 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 @@ Diva_card_msg(struct IsdnCardState *cs, 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 @@ setup_diva(struct IsdnCard *card) 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 @@ setup_diva(struct IsdnCard *card) 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 @@ setup_diva(struct IsdnCard *card) 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 @@ setup_diva(struct IsdnCard *card) 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 @@ setup_diva(struct IsdnCard *card) 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 @@ ready: 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; --- a/drivers/isdn/hisax/elsa.c +++ b/drivers/isdn/hisax/elsa.c @@ -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 -#include +#include #include #include 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 @@ probe_elsa(struct IsdnCardState *cs) 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 @@ setup_elsa(struct IsdnCard *card) 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 @@ setup_elsa(struct IsdnCard *card) 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 @@ setup_elsa(struct IsdnCard *card) 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 @@ setup_elsa(struct IsdnCard *card) break; case ELSA_PCFPRO: case ELSA_PCF: - case ELSA_QS3000: case ELSA_QS3000PCI: bytecnt = 16; break; --- a/drivers/isdn/hisax/elsa_cs.c +++ b/drivers/isdn/hisax/elsa_cs.c @@ -72,7 +72,7 @@ static int pc_debug = PCMCIA_DEBUG; 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 --- a/drivers/isdn/hisax/elsa_ser.c +++ b/drivers/isdn/hisax/elsa_ser.c @@ -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 @@ static inline void transmit_chars(struct } } +#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) { --- a/drivers/isdn/hisax/fsm.c +++ b/drivers/isdn/hisax/fsm.c @@ -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) { --- a/drivers/isdn/hisax/fsm.h +++ b/drivers/isdn/hisax/fsm.h @@ -1,4 +1,4 @@ -/* $Id: fsm.h,v 1.1.2.1 2001/11/20 14:19:35 kai Exp $ +/* $Id$ * * Finite state machine * --- a/drivers/isdn/hisax/gazel.c +++ b/drivers/isdn/hisax/gazel.c @@ -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 +#include 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 @@ setup_gazelpci(struct IsdnCardState *cs) 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) --- a/drivers/isdn/hisax/hfc_2bds0.c +++ b/drivers/isdn/hisax/hfc_2bds0.c @@ -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 @@ hfcd_bh(struct IsdnCardState *cs) */ 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 @@ HFCD_l1hw(struct PStack *st, int pr, voi 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 @@ setstack_hfcd(struct PStack *st, struct 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 --- a/drivers/isdn/hisax/hfc_2bds0.h +++ b/drivers/isdn/hisax/hfc_2bds0.h @@ -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 * --- a/drivers/isdn/hisax/hfc_2bs0.c +++ b/drivers/isdn/hisax/hfc_2bs0.c @@ -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 * --- a/drivers/isdn/hisax/hfc_2bs0.h +++ b/drivers/isdn/hisax/hfc_2bs0.h @@ -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 * --- a/drivers/isdn/hisax/hfc_pci.c +++ b/drivers/isdn/hisax/hfc_pci.c @@ -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 +#include #include 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 @@ release_io_hfcpci(struct IsdnCardState * { 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 @@ release_io_hfcpci(struct IsdnCardState * 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 @@ hfcpci_fill_fifo(struct BCState *bcs) 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 @@ hfcpci_interrupt(int intno, void *dev_id 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 @@ hfcpci_bh(struct IsdnCardState *cs) */ 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 @@ setup_hfcpci(struct IsdnCard *card) 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 @@ setup_hfcpci(struct IsdnCard *card) 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 @@ setup_hfcpci(struct IsdnCard *card) 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, --- a/drivers/isdn/hisax/hfc_pci.h +++ b/drivers/isdn/hisax/hfc_pci.h @@ -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 * --- a/drivers/isdn/hisax/hfc_sx.c +++ b/drivers/isdn/hisax/hfc_sx.c @@ -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 -#include 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 @@ hfcsx_interrupt(int intno, void *dev_id, 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 @@ hfcsx_bh(struct IsdnCardState *cs) */ 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 @@ hfcsx_card_msg(struct IsdnCardState *cs, 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 @@ setup_hfcsx(struct IsdnCard *card) 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 @@ setup_hfcsx(struct IsdnCard *card) cs->auxcmd = &hfcsx_auxcmd; return (1); } + + + + --- a/drivers/isdn/hisax/hfc_sx.h +++ b/drivers/isdn/hisax/hfc_sx.h @@ -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 * --- /dev/null +++ b/drivers/isdn/hisax/hfc_usb.c @@ -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 +#include +#include +#include +#include +#include +#include "hisax.h" +#include +#include +#include +#include +#include +#include +#include +#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); --- /dev/null +++ b/drivers/isdn/hisax/hfc_usbr.c @@ -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 +#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 */ +} --- a/drivers/isdn/hisax/hfcscard.c +++ b/drivers/isdn/hisax/hfcscard.c @@ -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 -#include #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 @@ hfcs_card_msg(struct IsdnCardState *cs, 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 @@ setup_hfcs(struct IsdnCard *card) 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; --- a/drivers/isdn/hisax/hisax.h +++ b/drivers/isdn/hisax/hisax.h @@ -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 #include #include +#ifndef COMPAT_NO_SOFTNET #include +#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 @@ struct amd7930_hw { #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 hfcPCI_hw { 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 @@ struct w6692_chip { 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 IsdnCardState { 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 IsdnCardState { 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 @@ struct IsdnCardState { #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 @@ struct IsdnCardState { #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 @@ struct IsdnCardState { #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 */ --- a/drivers/isdn/hisax/hisax_debug.h +++ b/drivers/isdn/hisax/hisax_debug.h @@ -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) \ --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -20,22 +20,19 @@ * * o POWER PC * o clean up debugging - * o tx_skb at PH_DEACTIVATE time */ #include #include #include #include -#include +#include "hisax_isapnp.h" #include #include #include #include - -#include - #include "hisax_fcpcipnp.h" +#include "hisax_isac.h" // debugging cruft #define __debug_variable debug @@ -46,10 +43,14 @@ static int debug = 0; MODULE_PARM(debug, "i"); #endif -MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); +MODULE_AUTHOR("Kai Germaschewski "); 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 @@ static struct pci_device_id fcpci_ids[] }; 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 @@ MODULE_DEVICE_TABLE(isapnp, fcpnp_ids); static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); -MODULE_LICENSE("GPL"); + +static LIST_HEAD(adapter_list); // ---------------------------------------------------------------------- @@ -147,7 +149,7 @@ static unsigned char fcpci_read_isac(str 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 @@ static void fcpci_write_isac(struct isac 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 @@ static unsigned char fcpci2_read_isac(st 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 @@ static void fcpci2_write_isac(struct isa 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 @@ static void hdlc_fill_fifo(struct fritz_ DBG(0x40, "hdlc_fill_fifo"); + if (!skb) + BUG(); + if (skb->len == 0) BUG(); @@ -515,7 +520,6 @@ static inline void hdlc_xdu_irq(struct f } 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 @@ static inline void hdlc_xpr_irq(struct f 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 void hdlc_irq_one(struct fritz_bc } } -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 @@ static inline void hdlc_irq(struct fritz 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 @@ static void modehdlc(struct fritz_bcs *b 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 @@ static void fcpci2_irq(int intno, void * 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 @@ static void fcpci_irq(int intno, void *d 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 @@ static inline void fcpci_init(struct fri { 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 inline void fcpci_init(struct fri 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 @@ static int __devinit fcpcipnp_setup(stru 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 int __devinit fcpcipnp_setup(stru 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 @@ new_adapter(struct pci_dev *pdev) 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 @@ new_adapter(struct pci_dev *pdev) 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 @@ new_adapter(struct pci_dev *pdev) 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 @@ static int __devinit fcpci_probe(struct 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 @@ static int __devinit fcpci_probe(struct 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 @@ static int __devinit fcpnp_probe(struct 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 @@ static int __devinit fcpnp_probe(struct 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 @@ static int __devinit fcpnp_probe(struct 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 @@ static int __init hisax_fcpcipnp_init(vo 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 @@ static int __init hisax_fcpcipnp_init(vo 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 --- a/drivers/isdn/hisax/hisax_fcpcipnp.h +++ b/drivers/isdn/hisax/hisax_fcpcipnp.h @@ -43,10 +43,12 @@ struct fritz_bcs { }; 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]; --- a/drivers/isdn/hisax/hisax_isac.c +++ b/drivers/isdn/hisax/hisax_isac.c @@ -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 @@ static char *ISACVer[] = { }; #endif -MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); -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 @@ static void l1m_debug(struct FsmInst *fi va_end(args); } -static void isac_version(struct isac *cs) +static void __devinit isac_version(struct isac *cs) { int val; @@ -602,7 +598,7 @@ static inline void isac_exi_interrupt(st } } -void isac_irq(struct isac *isac) +void isac_interrupt(struct isac *isac) { unsigned char val; @@ -635,8 +631,6 @@ void isac_irq(struct isac *isac) 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 @@ static inline void isacsx_icd_interrupt( } } -void isacsx_irq(struct isac *isac) +void isacsx_interrupt(struct isac *isac) { unsigned char val; @@ -755,7 +749,7 @@ void isacsx_irq(struct isac *isac) 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 @@ void isac_init(struct isac *isac) 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 @@ void isac_setup(struct isac *isac) 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 @@ void isac_setup(struct isac *isac) 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_init); 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); --- a/drivers/isdn/hisax/hisax_isac.h +++ b/drivers/isdn/hisax/hisax_isac.h @@ -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_init(struct isac *isac); 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 --- /dev/null +++ b/drivers/isdn/hisax/hisax_isapnp.c @@ -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; + } + } +} + --- /dev/null +++ b/drivers/isdn/hisax/hisax_isapnp.h @@ -0,0 +1,33 @@ +#ifndef __HISAX_ISAPNP_H__ +#define __HISAX_ISAPNP_H__ + +#include + +#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 --- /dev/null +++ b/drivers/isdn/hisax/hisax_loadable.h @@ -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 +#include + +/***************************************/ +/* 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); --- a/drivers/isdn/hisax/hscx.c +++ b/drivers/isdn/hisax/hscx.c @@ -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 * --- a/drivers/isdn/hisax/hscx.h +++ b/drivers/isdn/hisax/hscx.h @@ -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 * --- a/drivers/isdn/hisax/hscx_irq.c +++ b/drivers/isdn/hisax/hscx_irq.c @@ -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 * --- a/drivers/isdn/hisax/icc.c +++ b/drivers/isdn/hisax/icc.c @@ -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 * --- a/drivers/isdn/hisax/icc.h +++ b/drivers/isdn/hisax/icc.h @@ -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 * --- a/drivers/isdn/hisax/ipac.h +++ b/drivers/isdn/hisax/ipac.h @@ -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 * --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -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 * --- a/drivers/isdn/hisax/isac.h +++ b/drivers/isdn/hisax/isac.h @@ -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 * --- a/drivers/isdn/hisax/isar.c +++ b/drivers/isdn/hisax/isar.c @@ -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 @@ get_irq_infos(struct IsdnCardState *cs, 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 @@ isar_load_firmware(struct IsdnCardState } cs->debug = debug; isar_setup(cs); - ret = 0; reterrflg: restore_flags(flags); @@ -428,21 +425,6 @@ reterror: 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 @@ isar_rcv_frame(struct IsdnCardState *cs, 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 @@ isar_rcv_frame(struct IsdnCardState *cs, } } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; } @@ -633,9 +617,8 @@ isar_rcv_frame(struct IsdnCardState *cs, 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 @@ isar_rcv_frame(struct IsdnCardState *cs, 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_rcv_frame(struct IsdnCardState *cs, 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 @@ isar_rcv_frame(struct IsdnCardState *cs, 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 @@ isar_pump_statev_modem(struct BCState *b } } +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 @@ isar_pump_statev_fax(struct BCState *bcs 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_int_main(struct IsdnCardState *cs) 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 @@ ftimer_handler(struct BCState *bcs) { 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 @@ setup_pump(struct BCState *bcs) { } 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 @@ setup_pump(struct BCState *bcs) { } 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 @@ setup_sart(struct BCState *bcs) { "\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 @@ setup_sart(struct BCState *bcs) { 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 @@ isar_pump_cmd(struct BCState *bcs, u_cha 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 @@ isar_pump_cmd(struct BCState *bcs, u_cha } 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 @@ isar_pump_cmd(struct BCState *bcs, u_cha } 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 @@ isar_pump_cmd(struct BCState *bcs, u_cha } 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 @@ isar_pump_cmd(struct BCState *bcs, u_cha 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 @@ isar_l2l1(struct PStack *st, int pr, voi 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 @@ isar_auxcmd(struct IsdnCardState *cs, is 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 @@ isar_auxcmd(struct IsdnCardState *cs, is cs->iif.statcallb(ic); return(0); } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { - char *p = ic->parm.aux.para; - for(i=0;iparm.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;iparm.aux.para[0]) break; - if ((i < FAXMODCNT) && ((1< i) && test_bit(BC_FLG_INIT, &bcs->Flag)) { isar_pump_cmd(bcs, ic->parm.aux.cmd, @@ -1850,7 +1762,7 @@ isar_auxcmd(struct IsdnCardState *cs, is 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 @@ isar_auxcmd(struct IsdnCardState *cs, is 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); --- a/drivers/isdn/hisax/isar.h +++ b/drivers/isdn/hisax/isar.h @@ -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); --- a/drivers/isdn/hisax/isdnl1.c +++ b/drivers/isdn/hisax/isdnl1.c @@ -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 --- a/drivers/isdn/hisax/isdnl1.h +++ b/drivers/isdn/hisax/isdnl1.h @@ -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 * --- a/drivers/isdn/hisax/isdnl2.c +++ b/drivers/isdn/hisax/isdnl2.c @@ -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 @@ l2_st5_tei_remove(struct FsmInst *fi, in 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 --- a/drivers/isdn/hisax/isdnl2.h +++ b/drivers/isdn/hisax/isdnl2.h @@ -1,4 +1,4 @@ -/* $Id: isdnl2.h,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $ +/* $Id$ * * Layer 2 defines * --- a/drivers/isdn/hisax/isdnl3.c +++ b/drivers/isdn/hisax/isdnl3.c @@ -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 -const char *l3_revision = "$Revision: 1.1.4.1 $"; +const char *l3_revision = "$Revision: 2.22 $"; static struct Fsm l3fsm; --- a/drivers/isdn/hisax/isdnl3.h +++ b/drivers/isdn/hisax/isdnl3.h @@ -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. --- a/drivers/isdn/hisax/isurf.c +++ b/drivers/isdn/hisax/isurf.c @@ -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 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 @@ void 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 @@ isurf_auxcmd(struct IsdnCardState *cs, i 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 @@ setup_isurf(struct IsdnCard *card) 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 @@ setup_isurf(struct IsdnCard *card) } 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 @@ setup_isurf(struct IsdnCard *card) 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, --- a/drivers/isdn/hisax/ix1_micro.c +++ b/drivers/isdn/hisax/ix1_micro.c @@ -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 -#include #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 @@ ix1_card_msg(struct IsdnCardState *cs, i 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 @@ setup_ix1micro(struct IsdnCard *card) 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; --- a/drivers/isdn/hisax/jade.c +++ b/drivers/isdn/hisax/jade.c @@ -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) * --- a/drivers/isdn/hisax/jade.h +++ b/drivers/isdn/hisax/jade.h @@ -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 * --- a/drivers/isdn/hisax/jade_irq.c +++ b/drivers/isdn/hisax/jade_irq.c @@ -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) * --- a/drivers/isdn/hisax/l3_1tr6.c +++ b/drivers/isdn/hisax/l3_1tr6.c @@ -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 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; \ --- a/drivers/isdn/hisax/l3_1tr6.h +++ b/drivers/isdn/hisax/l3_1tr6.h @@ -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 * --- a/drivers/isdn/hisax/l3dss1.c +++ b/drivers/isdn/hisax/l3dss1.c @@ -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 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 --- a/drivers/isdn/hisax/l3dss1.h +++ b/drivers/isdn/hisax/l3dss1.h @@ -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 * --- a/drivers/isdn/hisax/l3ni1.c +++ b/drivers/isdn/hisax/l3ni1.c @@ -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 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 --- a/drivers/isdn/hisax/l3ni1.h +++ b/drivers/isdn/hisax/l3ni1.h @@ -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 * --- a/drivers/isdn/hisax/lmgr.c +++ b/drivers/isdn/hisax/lmgr.c @@ -1,4 +1,4 @@ -/* $Id: lmgr.c,v 1.1.4.1 2001/11/20 14:19:36 kai Exp $ +/* $Id$ * * Layermanagement module * --- a/drivers/isdn/hisax/md5sums.asc +++ b/drivers/isdn/hisax/md5sums.asc @@ -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----- --- a/drivers/isdn/hisax/mic.c +++ b/drivers/isdn/hisax/mic.c @@ -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) --- a/drivers/isdn/hisax/netjet.c +++ b/drivers/isdn/hisax/netjet.c @@ -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 #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 @@ void 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 @@ mode_tiger(struct BCState *bcs, int mode 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 @@ mode_tiger(struct BCState *bcs, int mode 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 @@ tiger_l2l1(struct PStack *st, int pr, vo 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): --- a/drivers/isdn/hisax/netjet.h +++ b/drivers/isdn/hisax/netjet.h @@ -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 * --- a/drivers/isdn/hisax/niccy.c +++ b/drivers/isdn/hisax/niccy.c @@ -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 -#include +#include 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 @@ niccy_card_msg(struct IsdnCardState *cs, } 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 @@ setup_niccy(struct IsdnCard *card) 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 @@ setup_niccy(struct IsdnCard *card) 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); --- a/drivers/isdn/hisax/nj_s.c +++ b/drivers/isdn/hisax/nj_s.c @@ -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 +#include #include #include #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 @@ NETjet_S_card_msg(struct IsdnCardState * 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 @@ setup_netjet_s(struct IsdnCard *card) 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 @@ setup_netjet_s(struct IsdnCard *card) } 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; --- a/drivers/isdn/hisax/nj_u.c +++ b/drivers/isdn/hisax/nj_u.c @@ -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 +#include #include #include #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 @@ setup_netjet_u(struct IsdnCard *card) 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); --- a/drivers/isdn/hisax/q931.c +++ b/drivers/isdn/hisax/q931.c @@ -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 @@ struct MessageType mt_n1[] = #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) --- /dev/null +++ b/drivers/isdn/hisax/rawhdlc.c @@ -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 + * by Brent Baccala + * + * 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> + * 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 +#endif + +#include +#include +#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>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 --- /dev/null +++ b/drivers/isdn/hisax/rawhdlc.h @@ -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 + * + * 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 --- a/drivers/isdn/hisax/s0box.c +++ b/drivers/isdn/hisax/s0box.c @@ -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) { --- a/drivers/isdn/hisax/saphir.c +++ b/drivers/isdn/hisax/saphir.c @@ -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) --- a/drivers/isdn/hisax/sedlbauer.c +++ b/drivers/isdn/hisax/sedlbauer.c @@ -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 -#include +#include 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 @@ const char *Sedlbauer_Types[] = #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 @@ Sedl_card_msg(struct IsdnCardState *cs, 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 @@ setup_sedlbauer(struct IsdnCard *card) 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 @@ setup_sedlbauer(struct IsdnCard *card) 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 @@ setup_sedlbauer(struct IsdnCard *card) } 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 @@ setup_sedlbauer(struct IsdnCard *card) 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 @@ setup_sedlbauer(struct IsdnCard *card) 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. --- a/drivers/isdn/hisax/sportster.c +++ b/drivers/isdn/hisax/sportster.c @@ -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) --- /dev/null +++ b/drivers/isdn/hisax/st5481-debug.h @@ -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 + + + --- a/drivers/isdn/hisax/st5481.h +++ b/drivers/isdn/hisax/st5481.h @@ -219,15 +219,15 @@ enum { #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 @@ -236,7 +236,7 @@ printk(KERN_INFO "%s:%s: " format "\n" , * FIFO handling */ -/* Generic FIFO structure */ +/* Generic FIFO structure */ struct fifo { u_char r,w,count,size; spinlock_t lock; @@ -270,7 +270,7 @@ static inline int fifo_add(struct fifo * 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 @@ static inline int fifo_remove(struct fif 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 @@ static inline int fifo_remove(struct fif 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_intr { }; 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_d_out { }; 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_b_out { }; 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 @@ extern int st5481_debug; 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; --- a/drivers/isdn/hisax/st5481_b.c +++ b/drivers/isdn/hisax/st5481_b.c @@ -67,28 +67,24 @@ static void usb_b_out(struct st5481_bcs 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 @@ static void usb_b_out(struct st5481_bcs 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 @@ static void st5481B_mode(struct st5481_b 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 @@ static int __devinit st5481_setup_b_out( 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 @@ int __devinit st5481_setup_b(struct st54 /* * 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,""); --- a/drivers/isdn/hisax/st5481_d.c +++ b/drivers/isdn/hisax/st5481_d.c @@ -162,8 +162,8 @@ static struct FsmNode L1FnList[] __initd {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 @@ static void usb_d_out(struct st5481_adap 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 @@ static void usb_d_out(struct st5481_adap 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 @@ static void dout_start_xmit(struct FsmIn 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 @@ static void dout_start_xmit(struct FsmIn 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 @@ static int __devinit st5481_setup_d_out( 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 @@ int __devinit st5481_setup_d(struct st54 return retval; } -void st5481_release_d(struct st5481_adapter *adapter) +void __devexit st5481_release_d(struct st5481_adapter *adapter) { DBG(2,""); --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -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 @@ MODULE_DEVICE_TABLE (usb, st5481_ids); 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, }; --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c @@ -41,9 +41,9 @@ static void usb_next_ctrl_msg(struct urb (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 @@ void usb_ctrl_msg(struct st5481_adapter } 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 @@ static void usb_ctrl_complete(struct urb 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 @@ int __devinit st5481_setup_usb(struct st 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 @@ int __devinit st5481_setup_usb(struct st * 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 @@ st5481_setup_isocpipes(struct urb* urb[2 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 @@ static void usb_in_complete(struct urb * 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 @@ int __devinit st5481_setup_in(struct st5 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 @@ void st5481_release_in(struct st5481_in */ 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 @@ void st5481_in_mode(struct st5481_in *in 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); --- a/drivers/isdn/hisax/tei.c +++ b/drivers/isdn/hisax/tei.c @@ -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 #include -const char *tei_revision = "$Revision: 1.1.4.1 $"; +const char *tei_revision = "$Revision: 2.20 $"; #define ID_REQUEST 1 #define ID_ASSIGNED 2 --- a/drivers/isdn/hisax/teleint.c +++ b/drivers/isdn/hisax/teleint.c @@ -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) --- a/drivers/isdn/hisax/teles0.c +++ b/drivers/isdn/hisax/teles0.c @@ -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 @@ release_io_teles0(struct IsdnCardState * { 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 @@ setup_teles0(struct IsdnCard *card) /* 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 @@ setup_teles0(struct IsdnCard *card) } 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, --- a/drivers/isdn/hisax/teles3.c +++ b/drivers/isdn/hisax/teles3.c @@ -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 -#include #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 @@ Teles_card_msg(struct IsdnCardState *cs, 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 @@ setup_teles3(struct IsdnCard *card) && (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) { --- a/drivers/isdn/hisax/telespci.c +++ b/drivers/isdn/hisax/telespci.c @@ -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 +#include 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 @@ setup_telespci(struct IsdnCard *card) 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); --- a/drivers/isdn/hisax/w6692.c +++ b/drivers/isdn/hisax/w6692.c @@ -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 #include +#include /* table entry in the PCI devices list */ typedef struct { @@ -29,20 +30,14 @@ typedef struct { 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 @@ setstack_W6692(struct PStack *st, struct 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 @@ setstack_w6692(struct PStack *st, struct 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 @@ w6692_card_msg(struct IsdnCardState *cs, { 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 @@ setup_w6692(struct IsdnCard *card) if (dev_w6692) { if (pci_enable_device(dev_w6692)) continue; - cs->subtyp = id_idx; break; } id_idx++; @@ -1023,14 +1015,7 @@ setup_w6692(struct IsdnCard *card) 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 @@ setup_w6692(struct IsdnCard *card) } 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 @@ setup_w6692(struct IsdnCard *card) 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; --- a/drivers/isdn/hisax/w6692.h +++ b/drivers/isdn/hisax/w6692.h @@ -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 * --- a/drivers/isdn/hysdn/boardergo.c +++ b/drivers/isdn/hysdn/boardergo.c @@ -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 -#include +#include +#include +#include #include #include #include #include #include -#include #include "hysdn_defs.h" #include "boardergo.h" @@ -45,11 +59,10 @@ ergo_interrupt(int intno, void *dev_id, 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 @@ ergo_interrupt(int intno, void *dev_id, 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 @@ ergo_irq_bh(hysdn_card * card) 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 @@ ergo_irq_bh(hysdn_card * card) 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 @@ ergo_stopcard(hysdn_card * card) #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 @@ ergo_stopcard(hysdn_card * card) 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 @@ ergo_set_errlog_state(hysdn_card * card, 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 @@ ergo_writebootimg(struct HYSDN_CARD *car 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 @@ ergo_writebootseq(struct HYSDN_CARD *car 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 @@ ergo_waitpofready(struct HYSDN_CARD *car 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 @@ ergo_waitpofready(struct HYSDN_CARD *car 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 @@ ergo_waitpofready(struct HYSDN_CARD *car #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 */ --- a/drivers/isdn/hysdn/boardergo.h +++ b/drivers/isdn/hysdn/boardergo.h @@ -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 /************************************************/ /* defines for the dual port memory of the card */ --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -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 -static char hycapi_revision[]="$Revision: 1.1.4.1 $"; +static char hycapi_revision[]="$Revision$"; unsigned int hycapi_enable = 0xffffffff; MODULE_PARM(hycapi_enable, "i"); --- a/drivers/isdn/hysdn/hysdn_boot.c +++ b/drivers/isdn/hysdn/hysdn_boot.c @@ -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 @@ pof_handle_data(hysdn_card * card, int d (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) --- a/drivers/isdn/hysdn/hysdn_defs.h +++ b/drivers/isdn/hysdn/hysdn_defs.h @@ -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 #include #include +#include +#include + +#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 @@ typedef struct HYSDN_CARD { 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 */ --- a/drivers/isdn/hysdn/hysdn_init.c +++ b/drivers/isdn/hysdn/hysdn_init.c @@ -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 @@ static struct pci_device_id hysdn_pci_tb { } /* 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 @@ search_cards(void) 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 */ --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -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 @@ unsigned int hynet_enable = 0xffffffff; 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 @@ struct net_local { /* 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 @@ struct net_local { int sk_count; /* number of buffers currently in ring */ int is_open; /* flag controlling module locking */ +#endif }; /* net_local */ @@ -83,11 +88,19 @@ net_open(struct net_device *dev) 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 @@ net_open(struct net_device *dev) 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 @@ flush_tx_buffers(struct net_local *nl) nl->sk_count--; } } /* flush_tx_buffers */ +#endif /*********************************************************************/ @@ -129,6 +144,15 @@ static int 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 @@ net_close(struct net_device *dev) ((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 @@ net_send_packet(struct sk_buff *skb, str return (0); /* success */ } /* net_send_packet */ +#endif /***********************************************************************/ @@ -190,6 +258,15 @@ hysdn_tx_netack(hysdn_card * card) 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 @@ hysdn_tx_netack(hysdn_card * card) 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 @@ hysdn_tx_netget(hysdn_card * card) 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 @@ hysdn_net_create(hysdn_card * card) } 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 @@ hysdn_net_release(hysdn_card * card) 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 */ --- a/drivers/isdn/hysdn/hysdn_pof.h +++ b/drivers/isdn/hysdn/hysdn_pof.h @@ -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. * --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -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 #include #include +#ifndef COMPAT_USE_MODCOUNT_LOCK #include +#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 @@ hysdn_conf_write(struct file *file, cons 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 @@ hysdn_conf_open(struct inode *ino, struc 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 @@ hysdn_conf_open(struct inode *ino, struc 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 @@ hysdn_conf_open(struct inode *ino, struc /* 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 @@ hysdn_conf_open(struct inode *ino, struc /* 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 @@ hysdn_conf_open(struct inode *ino, struc *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 @@ hysdn_conf_close(struct inode *ino, stru 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 @@ hysdn_conf_close(struct inode *ino, stru 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 @@ hysdn_conf_close(struct inode *ino, stru 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 @@ static struct file_operations conf_fops 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 @@ hysdn_procconf_init(void) 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 */ --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -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 #include #include +#ifndef COMPAT_USE_MODCOUNT_LOCK #include +#endif #include "hysdn_defs.h" @@ -115,8 +117,7 @@ put_log_buffer(hysdn_card * card, char * 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 @@ put_log_buffer(hysdn_card * card, char * 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 @@ hysdn_log_read(struct file *file, char * 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 @@ hysdn_log_read(struct file *file, char * 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 @@ hysdn_log_open(struct inode *ino, struct 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 @@ hysdn_log_open(struct inode *ino, struct 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 @@ hysdn_log_open(struct inode *ino, struct } 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 @@ hysdn_log_close(struct inode *ino, struc 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 @@ hysdn_log_close(struct inode *ino, struc /* 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 @@ hysdn_log_close(struct inode *ino, struc 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 @@ hysdn_log_close(struct inode *ino, struc 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 @@ static struct file_operations log_fops = 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 @@ hysdn_proclog_init(hysdn_card * card) 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)); --- a/drivers/isdn/hysdn/hysdn_sched.c +++ b/drivers/isdn/hysdn/hysdn_sched.c @@ -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 -#include #include #include #include -#include #include #include "hysdn_defs.h" @@ -151,22 +149,19 @@ hysdn_tx_cfgline(hysdn_card * card, ucha 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 @@ hysdn_tx_cfgline(hysdn_card * card, ucha /* 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"); --- a/drivers/isdn/icn/icn.c +++ b/drivers/isdn/icn/icn.c @@ -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 @@ MODULE_PARM_DESC(icn_id2, "ID-String of #undef MAP_DEBUG static char -*revision = "$Revision: 1.1.4.1 $"; +*revision = "$Revision$"; static int icn_addcard(int, char *, char *); @@ -1634,6 +1634,7 @@ icn_addcard(int port, char *id1, char *i } #ifndef MODULE +#ifdef COMPAT_HAS_NEW_SETUP static int __init icn_setup(char *line) { @@ -1643,6 +1644,14 @@ icn_setup(char *line) 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_setup(char *line) icn_id2 = sid2; } } +#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("icn=", icn_setup); +#else +} +#endif #endif /* MODULE */ static int __init icn_init(void) --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -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. * --- a/drivers/isdn/isdn_audio.c +++ b/drivers/isdn/isdn_audio.c @@ -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 @@ static char isdn_audio_ulaw_to_alaw[] = 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 @@ isdn_audio_tlookup(const u_char *table, : "memory", "ax"); #else while (n--) - *buff = table[*(unsigned char *)buff], buff++; + *buff++ = table[*(unsigned char *)buff]; #endif } @@ -479,18 +499,6 @@ isdn_audio_goertzel(int *sample, modem_i 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 @@ isdn_audio_eval_dtmf(modem_info * info) 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 != '.')) { --- a/drivers/isdn/isdn_audio.h +++ b/drivers/isdn/isdn_audio.h @@ -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 adpcm_state { typedef struct dtmf_state { char last; - char llast; int idx; int buf[DTMF_NPOINTS]; } dtmf_state; --- a/drivers/isdn/isdn_bsdcomp.c +++ b/drivers/isdn/isdn_bsdcomp.c @@ -105,6 +105,14 @@ MODULE_LICENSE("Dual BSD/GPL"); #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 @@ static void bsd_free (void *state) * Release the dictionary */ if (db->dict) { - vfree (db->dict); + BSD_C_FREE (db->dict); db->dict = NULL; } @@ -293,7 +301,7 @@ static void bsd_free (void *state) * Release the string buffer */ if (db->lens) { - vfree (db->lens); + BSD_C_FREE (db->lens); db->lens = NULL; } @@ -350,14 +358,19 @@ static void *bsd_alloc (struct isdn_ppp_ * 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 @@ static void *bsd_alloc (struct isdn_ppp_ 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 @@ static int bsd_compress (void *state, st 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 @@ static int bsd_compress (void *state, st 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 @@ static int bsd_compress (void *state, st /* 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 @@ static int bsd_compress (void *state, st 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 @@ static int bsd_decompress (void *state, 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 @@ static int bsd_decompress (void *state, 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 @@ static int bsd_decompress (void *state, 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 @@ static int bsd_decompress (void *state, } } *--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 @@ static int bsd_decompress (void *state, /* 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 @@ static int bsd_decompress (void *state, 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; } --- a/drivers/isdn/isdn_common.c +++ b/drivers/isdn/isdn_common.c @@ -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 #include #include +#include #include "isdn_common.h" #include "isdn_tty.h" #include "isdn_net.h" @@ -33,7 +34,9 @@ #include #endif /* CONFIG_ISDN_DIVERSION */ #include "isdn_v110.h" +#ifdef HAVE_DEVFS_FS #include +#endif /* HAVE_DEVFS_FS */ /* Debugflags */ #undef ISDN_DEBUG_STATCALLB @@ -44,7 +47,7 @@ MODULE_LICENSE("GPL"); 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 isdn_divert_if *divert_if; /* = N 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 @@ isdn_unlock_drivers(void) { 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_unlock_drivers(void) isdn_command(&cmd); dev->drv[i]->locks--; } - } } void @@ -473,6 +472,7 @@ isdn_status_callback(isdn_ctrl * c) 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 @@ isdn_status_callback(isdn_ctrl * c) 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 @@ isdn_status_callback(isdn_ctrl * c) 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 @@ isdn_minor2chan(int minor) 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 @@ isdn_read(struct file *file, char *buf, 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 @@ isdn_read(struct file *file, char *buf, 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 @@ isdn_read(struct file *file, char *buf, } 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; @@ -1065,6 +1220,9 @@ isdn_read(struct file *file, char *buf, } else { len = 0; } +#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT + } +#endif save_flags(flags); cli(); if (len) @@ -1072,7 +1230,7 @@ isdn_read(struct file *file, char *buf, else dev->drv[drvidx]->stavail = 0; restore_flags(flags); - *off = pos + len; + *off += len; retval = len; goto out; } @@ -1084,7 +1242,9 @@ isdn_read(struct file *file, char *buf, #endif retval = -ENODEV; out: +#ifndef COMPAT_HAVE_READ_LOCK_KERNEL unlock_kernel(); +#endif return retval; } @@ -1096,15 +1256,18 @@ isdn_write(struct file *file, const char 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); @@ -1149,7 +1312,9 @@ isdn_write(struct file *file, const char #endif retval = -ENODEV; out: +#ifndef COMPAT_HAVE_WRITE_LOCK_KERNEL unlock_kernel(); +#endif return retval; } @@ -1160,15 +1325,12 @@ isdn_poll(struct file *file, poll_table 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 */ @@ -1190,7 +1352,9 @@ isdn_poll(struct file *file, poll_table #endif mask = POLLERR; out: +#ifndef COMPAT_HAVE_POLL_LOCK_KERNEL unlock_kernel(); +#endif return mask; } @@ -1220,42 +1384,9 @@ isdn_ioctl(struct inode *inode, struct f #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) { @@ -1277,11 +1408,34 @@ isdn_ioctl(struct inode *inode, struct f */ 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 */ @@ -1657,22 +1811,12 @@ isdn_open(struct inode *ino, struct file 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; @@ -1695,6 +1839,9 @@ isdn_open(struct inode *ino, struct file 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; } @@ -1707,6 +1854,10 @@ isdn_open(struct inode *ino, struct file } #endif out: +#ifdef COMPAT_USE_MODCOUNT_LOCK + if (retval) + MOD_DEC_USE_COUNT; +#endif return retval; } @@ -1715,25 +1866,11 @@ isdn_close(struct inode *ino, struct fil { 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) @@ -1741,6 +1878,12 @@ isdn_close(struct inode *ino, struct fil 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 @@ -1749,13 +1892,19 @@ isdn_close(struct inode *ino, struct fil #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, @@ -1808,6 +1957,15 @@ isdn_get_free_channel(int usage, int l2_ 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; @@ -1826,7 +1984,11 @@ isdn_get_free_channel(int usage, int l2_ 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(); @@ -2013,7 +2175,7 @@ isdn_add_channels(driver *d, int drvidx, 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; } @@ -2021,7 +2183,7 @@ isdn_add_channels(driver *d, int drvidx, 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; @@ -2033,7 +2195,8 @@ isdn_add_channels(driver *d, int drvidx, 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); @@ -2047,7 +2210,8 @@ isdn_add_channels(driver *d, int drvidx, 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) { @@ -2071,7 +2235,9 @@ isdn_add_channels(driver *d, int drvidx, 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); @@ -2135,6 +2301,7 @@ int DIVERT_REG_NAME(isdn_divert_if *i_di 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); @@ -2172,7 +2339,7 @@ register_isdn(isdn_if * i) 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; } @@ -2232,6 +2399,7 @@ isdn_getrev(const char *revision) return rev; } +#ifdef HAVE_DEVFS_FS #ifdef CONFIG_DEVFS_FS static devfs_handle_t devfs_handle; @@ -2321,6 +2489,7 @@ static void isdn_cleanup_devfs(void) } #endif /* CONFIG_DEVFS_FS */ +#endif /* HAVE_DEVFS_FS */ /* * Allocate and initialize all data, register modem-devices @@ -2338,7 +2507,6 @@ static int __init isdn_init(void) 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; @@ -2352,7 +2520,9 @@ static int __init isdn_init(void) 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) @@ -2360,7 +2530,9 @@ static int __init isdn_init(void) 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; } @@ -2371,7 +2543,9 @@ static int __init isdn_init(void) 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; @@ -2397,6 +2571,9 @@ static int __init isdn_init(void) printk("\n"); #endif isdn_info_update(); +#ifdef CONFIG_ISDN_WITH_ABC + isdn_dw_abc_init_func(); +#endif return 0; } @@ -2405,7 +2582,7 @@ static int __init isdn_init(void) */ static void __exit isdn_exit(void) { - unsigned long flags; + int flags; int i; #ifdef CONFIG_ISDN_PPP @@ -2439,13 +2616,18 @@ static void __exit isdn_exit(void) 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); --- a/drivers/isdn/isdn_common.h +++ b/drivers/isdn/isdn_common.h @@ -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); --- a/drivers/isdn/isdn_concap.c +++ b/drivers/isdn/isdn_concap.c @@ -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 * --- a/drivers/isdn/isdn_concap.h +++ b/drivers/isdn/isdn_concap.h @@ -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 * --- /dev/null +++ b/drivers/isdn/isdn_dwabc.c @@ -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 + * + * 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 +#define __NO_VERSION__ + +#ifdef CONFIG_ISDN_WITH_ABC + +static char *dwabcrevison = "$Revision: 1.27 $"; + +#include +#define CONFIG_ISDN_WITH_ABC_NEED_DWSJIFFIES 1 +#include +#include +#include "isdn_common.h" +#include "isdn_net.h" + +#include + +#include +#include +#include + + +#if CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS && CONFIG_ISDN_PPP +#include +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 \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 \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 --- a/drivers/isdn/isdn_net.c +++ b/drivers/isdn/isdn_net.c @@ -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 * 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 +#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 @@ static __inline__ int isdn_net_device_st dev = lp->master; else dev = &n->dev; +#ifdef COMPAT_NO_SOFTNET + return dev->start; +#else return netif_running(dev); +#endif } /* @@ -143,6 +143,10 @@ static __inline__ void isdn_net_inc_fram 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 @@ static __inline__ void isdn_net_dec_fram 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 @@ static __inline__ void isdn_net_zero_fra * 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 @@ isdn_net_unbind_channel(isdn_net_local * 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 @@ isdn_net_autohup() 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 @@ isdn_net_stat_callback(int idx, isdn_ctr 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 @@ isdn_net_stat_callback(int idx, isdn_ctr } } 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 @@ isdn_net_dial(void) int i; unsigned long flags; isdn_ctrl cmd; - u_char *phone_number; while (p) { isdn_net_local *lp = p->local; @@ -597,6 +749,47 @@ isdn_net_dial(void) */ 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 @@ isdn_net_dial(void) 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 @@ isdn_net_dial(void) 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 @@ isdn_net_dial(void) } } 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 @@ isdn_net_dial(void) 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_net_hangup(struct net_device *d) 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 @@ typedef struct { 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 @@ isdn_net_log_skb(struct sk_buff * skb, i 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 @@ isdn_net_log_skb(struct sk_buff * skb, i 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 @@ void isdn_net_write_super(isdn_net_local } 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 @@ void isdn_net_writebuf_skb(isdn_net_loca 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 @@ void isdn_net_writebuf_skb(isdn_net_loca 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 @@ isdn_net_xmit(struct net_device *ndev, s /* 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 @@ isdn_net_xmit(struct net_device *ndev, s 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 @@ isdn_net_adjust_hdr(struct sk_buff *skb, } +#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 @@ void isdn_net_tx_timeout(struct net_devi 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 @@ isdn_net_start_xmit(struct sk_buff *skb, } 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 @@ isdn_net_start_xmit(struct sk_buff *skb, } 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 @@ isdn_net_start_xmit(struct sk_buff *skb, 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 @@ isdn_net_start_xmit(struct sk_buff *skb, 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 @@ isdn_net_start_xmit(struct sk_buff *skb, 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 @@ isdn_net_start_xmit(struct sk_buff *skb, } } return 1; +#endif } /* @@ -1356,6 +2027,9 @@ isdn_net_close(struct net_device *dev) 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 @@ isdn_net_ciscohdlck_receive(isdn_net_loc } 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 @@ isdn_net_ciscohdlck_receive(isdn_net_loc "\"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_receive(struct net_device *ndev { 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 @@ isdn_net_receive(struct net_device *ndev 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 @@ isdn_net_receive(struct net_device *ndev /* 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 @@ isdn_net_receive(struct net_device *ndev 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 @@ isdn_net_receive(struct net_device *ndev 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 @@ isdn_net_receive(struct net_device *ndev 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,7 +2915,10 @@ isdn_net_find_icall(int di, int ch, int isdn_net_phone *n; ulong flags; char nr[ISDN_MSNLEN]; - 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); @@ -2182,17 +2940,15 @@ isdn_net_find_icall(int di, int ch, int 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, @@ -2212,25 +2968,8 @@ p = dev->netdev; 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; @@ -2238,17 +2977,122 @@ p = dev->netdev; 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)) { @@ -2377,6 +3221,12 @@ p = dev->netdev; 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; /* @@ -2429,6 +3279,47 @@ p = dev->netdev; 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 @@ -2518,7 +3409,11 @@ isdn_net_force_dial_lp(isdn_net_local * 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); @@ -2601,7 +3496,11 @@ isdn_net_new(char *name, struct net_devi 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; @@ -2619,11 +3518,13 @@ isdn_net_new(char *name, struct net_devi ((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); @@ -2660,6 +3561,9 @@ isdn_net_new(char *name, struct net_devi 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 */ @@ -2833,7 +3737,6 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg /* 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) { @@ -2862,6 +3765,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg 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; @@ -2935,6 +3841,9 @@ isdn_net_setcfg(isdn_net_ioctl_cfg * cfg } } lp->p_encap = cfg->p_encap; +#ifdef CONFIG_ISDN_WITH_ABC + isdn_dw_abc_reset_interface(lp,0); +#endif return 0; } return -ENODEV; @@ -3011,6 +3920,9 @@ isdn_net_addphone(isdn_net_ioctl_phone * n->num[sizeof(n->num) - 1] = 0; 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; @@ -3104,6 +4016,9 @@ isdn_net_delphone(isdn_net_ioctl_phone * 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; } @@ -3139,6 +4054,9 @@ isdn_net_rmallphone(isdn_net_dev * p) 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; } @@ -3222,6 +4140,10 @@ isdn_net_realrm(isdn_net_dev * p, isdn_n /* 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); --- a/drivers/isdn/isdn_net.h +++ b/drivers/isdn/isdn_net.h @@ -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 @@ static __inline__ void isdn_net_add_to_b 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 @@ static __inline__ void isdn_net_rm_from_ 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); } --- a/drivers/isdn/isdn_ppp.c +++ b/drivers/isdn/isdn_ppp.c @@ -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 #include #include -#ifdef CONFIG_IPPP_FILTER -#include -#endif #include "isdn_common.h" #include "isdn_ppp.h" @@ -72,11 +69,19 @@ static void isdn_ppp_mp_cleanup( isdn_ne 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 @@ isdn_ppp_free(isdn_net_local * lp) 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 @@ isdn_ppp_free(isdn_net_local * lp) 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 @@ isdn_ppp_bind(isdn_net_local * lp) void isdn_ppp_wakeup_daemon(isdn_net_local * lp) { - if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) { - 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 @@ isdn_ppp_closewait(int slot) { 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 @@ isdn_ppp_open(int min, struct file *file 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 @@ isdn_ppp_open(int min, struct file *file */ 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 @@ isdn_ppp_release(int min, struct file *f 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 @@ isdn_ppp_release(int min, struct file *f 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 @@ isdn_ppp_ioctl(int min, struct file *fil 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 @@ isdn_ppp_ioctl(int min, struct file *fil } 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 @@ isdn_ppp_fill_rq(unsigned char *buf, int 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 @@ void isdn_ppp_receive(isdn_net_dev * net 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 @@ isdn_ppp_push_higher(isdn_net_dev * net_ { 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 @@ isdn_ppp_push_higher(isdn_net_dev * net_ 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 @@ isdn_ppp_push_higher(isdn_net_dev * net_ } 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 @@ isdn_ppp_push_higher(isdn_net_dev * net_ 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 @@ static unsigned char *isdn_ppp_skb_push( 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_ppp_xmit(struct sk_buff *skb, struc 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 @@ isdn_ppp_xmit(struct sk_buff *skb, struc 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 @@ isdn_ppp_xmit(struct sk_buff *skb, struc */ 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 @@ isdn_ppp_xmit(struct sk_buff *skb, struc 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 ippp_bundle * isdn_ppp_mp_bundle_ 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 @@ static void isdn_ppp_mp_receive(isdn_net 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 @@ static void isdn_ppp_mp_receive(isdn_net 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 @@ void isdn_ppp_mp_reassembly( isdn_net_de 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 @@ isdn_ppp_dev_ioctl_stats(int slot, struc 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 @@ isdn_ppp_dev_ioctl(struct net_device *de 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; @@ -2432,7 +2250,7 @@ static void isdn_ppp_ccp_reset_trans(str 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; @@ -2583,7 +2401,13 @@ static struct sk_buff *isdn_ppp_compress } 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) { @@ -2631,31 +2455,18 @@ static struct sk_buff *isdn_ppp_compress 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]) { @@ -2807,18 +2618,13 @@ static void isdn_ppp_receive_ccp(isdn_ne 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) { @@ -2834,17 +2640,12 @@ static void isdn_ppp_send_ccp(isdn_net_d 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]) { --- a/drivers/isdn/isdn_ppp.h +++ b/drivers/isdn/isdn_ppp.h @@ -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 int isdn_ppp_init(void); 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); --- a/drivers/isdn/isdn_tty.c +++ b/drivers/isdn/isdn_tty.c @@ -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 bit2si[8] = 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 @@ isdn_tty_tint(modem_info * info) 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 @@ isdn_tty_write(struct tty_struct *tty, i /* 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 @@ isdn_tty_write(struct tty_struct *tty, i } } } else +#ifdef ISDN_TTY_FCLASS1 if (TTY_IS_FCLASS1(info)) { int cc = isdn_tty_handleDLEdown(info, m, c); @@ -1252,6 +1259,7 @@ isdn_tty_write(struct tty_struct *tty, i info->xmit_count += cc; } else #endif +#endif info->xmit_count += c; } else { info->msr |= UART_MSR_CTS; @@ -1329,7 +1337,10 @@ isdn_tty_flush_buffer(struct tty_struct 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_close(struct tty_struct *tty, s 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_stat_callback(int i, isdn_ctrl 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 @@ isdn_tty_modem_result(int code, modem_in 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 @@ isdn_tty_modem_result(int code, modem_in 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 @@ isdn_tty_cmd_PLUSF(char **p, modem_info #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 @@ isdn_tty_cmd_PLUSF(char **p, modem_info 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 @@ isdn_tty_cmd_PLUSF(char **p, modem_info info->xmit_size = m->mdmreg[REG_PSIZE] * 16; break; +#endif case '2': p[0]++; if (!(dev->global_features & @@ -3348,9 +3381,11 @@ isdn_tty_cmd_PLUSF(char **p, modem_info 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,"); --- a/drivers/isdn/isdn_tty.h +++ b/drivers/isdn/isdn_tty.h @@ -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)) --- a/drivers/isdn/isdn_ttyfax.c +++ b/drivers/isdn/isdn_ttyfax.c @@ -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 @@ isdn_tty_fax_modem_result(int code, mode } } +#ifdef ISDN_TTY_FCLASS1 int isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c) { @@ -186,6 +187,7 @@ isdn_tty_fax_command1(modem_info * info, } return (0); } +#endif int isdn_tty_fax_command(modem_info * info, isdn_ctrl * c) @@ -193,8 +195,10 @@ isdn_tty_fax_command(modem_info * info, 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 @@ isdn_tty_fax_bitorder(modem_info * info, } } +#ifdef ISDN_TTY_FCLASS1 /* * Parse AT+F.. FAX class 1 commands */ @@ -403,6 +408,7 @@ isdn_tty_cmd_FCLASS1(char **p, modem_inf } return 1; } +#endif /* * Parse AT+F.. FAX class 2 commands @@ -970,6 +976,70 @@ isdn_tty_cmd_FCLASS2(char **p, modem_inf } 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 @@ isdn_tty_cmd_FCLASS2(char **p, modem_inf } 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_cmd_FCLASS2(char **p, modem_inf 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 @@ isdn_tty_cmd_PLUSF_FAX(char **p, modem_i { 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; } --- a/drivers/isdn/isdn_ttyfax.h +++ b/drivers/isdn/isdn_ttyfax.h @@ -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). * --- a/drivers/isdn/isdn_v110.c +++ b/drivers/isdn/isdn_v110.c @@ -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 @@ isdn_v110_close(isdn_v110_stream * v) 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); --- a/drivers/isdn/isdn_v110.h +++ b/drivers/isdn/isdn_v110.h @@ -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). * --- a/drivers/isdn/isdn_x25iface.c +++ b/drivers/isdn/isdn_x25iface.c @@ -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 * --- a/drivers/isdn/isdn_x25iface.h +++ b/drivers/isdn/isdn_x25iface.h @@ -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 * --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -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 #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_AUTHOR("Fritz Elfert"); 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 @@ isdnloop_init(void) } 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 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -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. * --- a/drivers/isdn/pcbit/callbacks.c +++ b/drivers/isdn/pcbit/callbacks.c @@ -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. --- a/drivers/isdn/pcbit/callbacks.h +++ b/drivers/isdn/pcbit/callbacks.h @@ -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. --- a/drivers/isdn/pcbit/capi.c +++ b/drivers/isdn/pcbit/capi.c @@ -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. --- a/drivers/isdn/pcbit/capi.h +++ b/drivers/isdn/pcbit/capi.h @@ -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_disc_resp(struct pcbit_c 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; --- a/drivers/isdn/pcbit/drv.c +++ b/drivers/isdn/pcbit/drv.c @@ -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 #include #include +#ifdef COMPAT_HAS_ISA_IOREMAP #include +#endif #include "pcbit.h" #include "edss1.h" @@ -89,6 +91,7 @@ int pcbit_init_dev(int board, int mem_ba 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 @@ int pcbit_init_dev(int board, int mem_ba 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 @@ int pcbit_init_dev(int board, int mem_ba 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 @@ int pcbit_init_dev(int board, int mem_ba 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 @@ int pcbit_init_dev(int board, int mem_ba { 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 @@ int pcbit_init_dev(int board, int mem_ba 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 @@ int pcbit_init_dev(int board, int mem_ba 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 @@ void pcbit_terminate(int board) 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 @@ int pcbit_writecmd(const u_char* buf, in 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 @@ void pcbit_l3_receive(struct pcbit_dev * 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 @@ void pcbit_l3_receive(struct pcbit_dev * 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); --- a/drivers/isdn/pcbit/edss1.c +++ b/drivers/isdn/pcbit/edss1.c @@ -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. --- a/drivers/isdn/pcbit/edss1.h +++ b/drivers/isdn/pcbit/edss1.h @@ -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. --- a/drivers/isdn/pcbit/layer2.c +++ b/drivers/isdn/pcbit/layer2.c @@ -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 @@ pcbit_receive(struct pcbit_dev *dev) 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 @@ pcbit_receive(struct pcbit_dev *dev) 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; } --- a/drivers/isdn/pcbit/layer2.h +++ b/drivers/isdn/pcbit/layer2.h @@ -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. --- a/drivers/isdn/pcbit/module.c +++ b/drivers/isdn/pcbit/module.c @@ -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 @@ static void __exit pcbit_exit(void) } #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 @@ static int __init pcbit_setup(char *line 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 @@ static int __init pcbit_setup(char *line i++; } +#ifdef COMPAT_HAS_NEW_SETUP return(1); } __setup("pcbit=", pcbit_setup); +#else +} +#endif #endif module_init(pcbit_init); --- a/drivers/isdn/pcbit/pcbit.h +++ b/drivers/isdn/pcbit/pcbit.h @@ -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. --- a/drivers/isdn/sc/card.h +++ b/drivers/isdn/sc/card.h @@ -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 * --- a/drivers/isdn/sc/command.c +++ b/drivers/isdn/sc/command.c @@ -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 @@ int get_card_from_id(int driver) if(adapter[i]->driverId == driver) return i; } - return -ENODEV; + return -NODEV; } /* --- a/drivers/isdn/sc/debug.c +++ b/drivers/isdn/sc/debug.c @@ -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. * --- a/drivers/isdn/sc/debug.h +++ b/drivers/isdn/sc/debug.h @@ -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. * --- a/drivers/isdn/sc/event.c +++ b/drivers/isdn/sc/event.c @@ -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. * --- a/drivers/isdn/sc/init.c +++ b/drivers/isdn/sc/init.c @@ -514,6 +514,15 @@ int identify_board(unsigned long rambase 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 @@ int identify_board(unsigned long rambase 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; --- a/drivers/isdn/sc/interrupt.c +++ b/drivers/isdn/sc/interrupt.c @@ -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. * --- a/drivers/isdn/sc/ioctl.c +++ b/drivers/isdn/sc/ioctl.c @@ -23,6 +23,9 @@ extern int send_and_receive(int, unsigne extern board *adapter[]; +#if 0 +static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" }; +#endif int GetStatus(int card, boardInfo *); --- a/drivers/isdn/sc/message.c +++ b/drivers/isdn/sc/message.c @@ -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 * --- a/drivers/isdn/sc/message.h +++ b/drivers/isdn/sc/message.h @@ -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. * --- a/drivers/isdn/sc/packet.c +++ b/drivers/isdn/sc/packet.c @@ -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. * --- a/drivers/isdn/sc/shmem.c +++ b/drivers/isdn/sc/shmem.c @@ -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. * --- a/drivers/isdn/sc/timer.c +++ b/drivers/isdn/sc/timer.c @@ -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. * --- a/drivers/isdn/tpam/tpam.h +++ b/drivers/isdn/tpam/tpam.h @@ -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) * --- a/drivers/isdn/tpam/tpam_commands.c +++ b/drivers/isdn/tpam/tpam_commands.c @@ -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) * --- a/drivers/isdn/tpam/tpam_crcpc.c +++ b/drivers/isdn/tpam/tpam_crcpc.c @@ -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) * --- a/drivers/isdn/tpam/tpam_hdlc.c +++ b/drivers/isdn/tpam/tpam_hdlc.c @@ -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) * --- a/drivers/isdn/tpam/tpam_main.c +++ b/drivers/isdn/tpam/tpam_main.c @@ -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 @@ static struct pci_driver tpam_driver = { name: "tpam", id_table: tpam_pci_tbl, probe: tpam_probe, - remove: __devexit_p(tpam_remove), + remove: tpam_remove, }; static int __init tpam_init(void) { --- a/drivers/isdn/tpam/tpam_memory.c +++ b/drivers/isdn/tpam/tpam_memory.c @@ -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) * --- a/drivers/isdn/tpam/tpam_nco.c +++ b/drivers/isdn/tpam/tpam_nco.c @@ -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) --- a/drivers/isdn/tpam/tpam_queues.c +++ b/drivers/isdn/tpam/tpam_queues.c @@ -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 @@ void tpam_irq(int irq, void *dev_id, str 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"); --- a/include/linux/b1lli.h +++ b/include/linux/b1lli.h @@ -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. * --- a/include/linux/b1pcmcia.h +++ b/include/linux/b1pcmcia.h @@ -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. --- a/include/linux/capi.h +++ b/include/linux/capi.h @@ -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 * --- a/include/linux/concap.h +++ b/include/linux/concap.h @@ -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 * @@ -11,6 +11,7 @@ #ifdef __KERNEL__ #include #include +#include /* Stuff to support encapsulation protocols genericly. The encapsulation protocol is processed at the uppermost layer of the network interface. --- a/include/linux/hysdn_if.h +++ b/include/linux/hysdn_if.h @@ -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. --- a/include/linux/isdn/tpam.h +++ b/include/linux/isdn/tpam.h @@ -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) * --- a/include/linux/isdn.h +++ b/include/linux/isdn.h @@ -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 #include #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 @@ typedef struct { #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 + + +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 @@ typedef struct { # include #endif +#ifdef HAVE_DEVFS_FS #ifdef CONFIG_DEVFS_FS # include #endif +#endif /* HAVE_DEVFS_FS */ #include @@ -272,6 +336,12 @@ typedef struct { #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 @@ typedef struct isdn_net_local_s { 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 @@ typedef struct isdn_devt { 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 @@ typedef struct isdn_devt { 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 @@ typedef struct isdn_devt { 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__ */ --- /dev/null +++ b/include/linux/isdn_compat.h @@ -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 + +#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 +#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 + +/* + * 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 */ --- a/include/linux/isdn_divertif.h +++ b/include/linux/isdn_divertif.h @@ -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 @@ typedef struct 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; /*********************/ --- /dev/null +++ b/include/linux/isdn_dwabc.h @@ -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 + * + * 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 +#include +#include +#include +#include +#include + + +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 +#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 --- a/include/linux/isdn_lzscomp.h +++ b/include/linux/isdn_lzscomp.h @@ -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 --- a/include/linux/isdn_ppp.h +++ b/include/linux/isdn_ppp.h @@ -8,6 +8,7 @@ #ifndef _LINUX_ISDN_PPP_H #define _LINUX_ISDN_PPP_H +#include #define CALLTYPE_INCOMING 0x1 #define CALLTYPE_OUTGOING 0x2 @@ -33,6 +34,11 @@ struct pppcallinfo #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 @@ struct isdn_ppp_comp_data { #include -#ifdef CONFIG_IPPP_FILTER -#include -#endif #define DECOMP_ERR_NOMEM (-10) @@ -226,10 +229,6 @@ struct ippp_struct { 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; --- a/include/linux/isdnif.h +++ b/include/linux/isdnif.h @@ -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 /* * Values for general protocol-selection @@ -213,6 +214,8 @@ typedef struct #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 --- a/include/linux/kernelcapi.h +++ b/include/linux/kernelcapi.h @@ -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__