diff --git a/.config b/.config deleted file mode 100644 index 01ae3ff4..00000000 --- a/.config +++ /dev/null @@ -1,8 +0,0 @@ -# -# defines for standalone build -# -# WARNING, You can NOT override FEATURES which are disabled in the -# kernel configuration here, only add Drivers here. -# -CONFIG_ISDN_DRV_LOOP=m -CONFIG_ISDN_DRV_ACT2000=m diff --git a/Documentation/Configure.help.diff b/Documentation/Configure.help.diff deleted file mode 100644 index 279b1ebe..00000000 --- a/Documentation/Configure.help.diff +++ /dev/null @@ -1,132 +0,0 @@ ---- linux-2.0.29.org/Documentation/Configure.help Tue Mar 25 23:24:33 1997 -+++ /usr/src/linux/Documentation/Configure.help Tue Mar 25 22:52:13 1997 -@@ -1671,6 +1671,15 @@ - available via ftp (user: anonymous) at - sunsite.unc.edu:/pub/Linux/docs/HOWTO, is for you. - -+GDT SCSI Disk Array Controller support -+CONFIG_SCSI_GDTH -+ This is a driver for all SCSI Disk Array Controllers (EISA/ISA/PCI) -+ manufactured by ICP vortex. It is documented in the kernel source in -+ drivers/scsi/gdth.c and drivers/scsi/gdth.h. This driver is also -+ available as a module ( = code which can be inserted in and removed -+ from the running kernel whenever you want). If you want to compile -+ it as a module, say M here and read Documentation/modules.txt. -+ - IOMEGA Parallel Port ZIP drive SCSI support - CONFIG_SCSI_PPA - This driver supports the parallel port version of IOMEGA's ZIP drive -@@ -2734,6 +2743,14 @@ - change a setting in the file include/linux/gscd.h before compiling - the kernel. - -+MicroSolutions backup CDROM support -+CONFIG_BPCD -+ MicroSolutions' backup CDROM is an external drive that connects to -+ the parallel port. Say Y if you have one of these, and read the -+ file linux/Documentation/cdrom/bpcd. If you have several different -+ devices that will share a common parallel port, say M and build them -+ as modules. -+ - Philips/LMS CM206 CDROM support - CONFIG_CM206 - If you have a Philips/LMS CDROM drive cm206 in combination with a -@@ -3258,6 +3275,7 @@ - module load time. - - -+ - Mouse Support (not serial mice) - CONFIG_MOUSE - This is for machines with a bus mouse or a PS/2 mouse as opposed to -@@ -3775,6 +3793,90 @@ - Documentation/isdn/README on how to configure it using 16.3, a - different D-channel protocol, or non-standard irq/port/shmem - settings. -+ -+HiSax SiemensChipSet driver support -+CONFIG_ISDN_DRV_HISAX -+ This is an alternative driver supporting the Siemens chipset on -+ various ISDN-cards (like AVM A1, Elsa ISDN cards, Teles S0-16.0, -+ Teles S0-16.3, Teles S0-8, Teles/Creatix PnP, ITK micro ix1 and -+ many compatibles).It's a complete rewrite of the original Teles -+ driver. So you either say M or Y here and N in the above Teles -+ section. -+ See Documentation/isdn/README.HiSax for further informations on -+ using this driver. -+ -+HiSax Support for Teles 16.0/8.0 -+CONFIG_HISAX_16_0 -+ This enables HiSax support for the Teles ISDN-cards S0-16.0, -+ S0-8 and many compatibles. -+ See Documentation/isdn/README.HiSax on how to configure it -+ using the different cards, a different D-channel protocol, or -+ non-standard irq/port/shmem settings. -+ -+HiSax Support for Teles 16.3 or PNP or PCMCIA -+CONFIG_HISAX_16_3 -+ This enables HiSax support for the Teles ISDN-cards S0-16.3 -+ the Teles/Creatix PnP and the Teles PCMCIA. -+ See Documentation/isdn/README.HiSax on how to configure it -+ using the different cards, a different D-channel protocol, or -+ non-standard irq/port/shmem settings. -+ -+HiSax Support for AVM A1 (Fritz) -+CONFIG_HISAX_AVM_A1 -+ This enables HiSax support for the AVM A1 (aka "Fritz"). -+ See Documentation/isdn/README.HiSax on how to configure it -+ using the different cards, a different D-channel protocol, or -+ non-standard irq/port/shmem settings. -+ -+HiSax Support for Elsa ISA cards -+CONFIG_HISAX_ELSA_PCC -+ This enables HiSax support for the Elsa Mircolink cards and -+ for the Elsa Quickstep series cards for the ISA bus. -+ You don't have to select "HiSax Support for Elsa PCMCIA card" -+ at the same time. -+ See Documentation/isdn/README.HiSax on how to configure it -+ using the different cards, a different D-channel protocol, or -+ non-standard irq/port/shmem settings. -+ -+HiSax Support for Elsa PCMCIA card -+CONFIG_HISAX_ELSA_PCMCIA -+ This enables HiSax support for the Elsa PCMCIA card. -+ You don't have to select "HiSax Support for Elsa ISA cards" at -+ the same time. -+ See Documentation/isdn/README.HiSax on how to configure it -+ using the different cards, a different D-channel protocol, or -+ non-standard irq/port/shmem settings. -+ -+HiSax Support for ITK ix1-micro Revision 2 -+CONFIG_HISAX_IX1MICROR2 -+ This enables HiSax support for the ITK ix1-micro Revision 2 card. -+ See Documentation/isdn/README.HiSax on how to configure it -+ using the different cards, a different D-channel protocol, or -+ non-standard irq/port/shmem settings. -+ -+HiSax Support for EURO/DSS1 -+CONFIG_HISAX_EURO -+ You should choose your D-channel protocol your local -+ telephone service provider uses here by saying Y or N. -+ NOTE: This is mutually exclusive with HiSax Support for -+ german 1TR6 and US/NI-1 if you have only one ISDN card -+ installed. -+ -+HiSax Support for US/NI-1 -+CONFIG_HISAX_NI1 -+ You should choose your D-channel protocol your local -+ telephone service provider uses here by saying Y or N. -+ NOTE: This is mutually exclusive with HiSax Support for -+ german 1TR6 and EURO/DSS1 if you have only one ISDN card -+ installed. -+ -+HiSax Support for german 1TR6 -+CONFIG_HISAX_1TR6 -+ You should choose your D-channel protocol your local -+ telephone service provider uses here by saying Y or N. -+ NOTE: This is mutually exclusive with HiSax Support for -+ EURO/DSS1 and US/NI-1 if you have only one ISDN card -+ installed. - - PCBIT-D support - CONFIG_ISDN_DRV_PCBIT diff --git a/Documentation/Configure.help.divert.diff b/Documentation/Configure.help.divert.diff deleted file mode 100644 index 660135e8..00000000 --- a/Documentation/Configure.help.divert.diff +++ /dev/null @@ -1,32 +0,0 @@ ---- Configure.org Sat May 1 19:59:05 1999 -+++ Configure.help Sat May 1 20:08:56 1999 -@@ -4541,6 +4541,20 @@ - driver is the only voice-supporting drivers. See - Documentation/isdn/README.audio for more information. - -+ISDN diversion services support -+CONFIG_ISDN_DIVERSION -+ This option allows you to use some supplementary diversion -+ services in conjunction with the HiSax driver on an EURO/DSS1 -+ line. Supported options are CD (call deflection), CFU (Call -+ forward unconditional), CFB (Call forward when busy) and CFNR -+ (call forward not reachable). -+ Additionally the actual CFU, CFB and CFNR state may be -+ interrogated. The use of CFU, CFB, CFNR and interrogation may -+ be limited to some countries. The keypad protocol is still not -+ implemented. -+ CD should work in all countries if this service has been sub- -+ scribed. -+ -+HiSax driver for HFC-S+, HFC-SP and HFC-PCMCIA cards -+CONFIG_HISAX_HFC_SX -+ This option allows you to add support for for ISDN-cards supplied -+ with CCDs HFC-S+, HFC-SP and HFC-PCMCIA-cards with the SP chip. -+ Drivers for the very old HFC-S chip and the new busmaster HFC-PCI -+ are separate selectable drivers and not covered by this option. -+ Due to problems with cards only equipped with 8K of RAM this driver -+ only supports cards equipped with 32K RAM like CCD recommends. -+ - ICN 2B and 4B support - CONFIG_ISDN_DRV_ICN - This enables support for two kinds of ISDN-cards made by a German diff --git a/Documentation/Configure.help.dwabc.diff b/Documentation/Configure.help.dwabc.diff deleted file mode 100644 index 4aa44138..00000000 --- a/Documentation/Configure.help.dwabc.diff +++ /dev/null @@ -1,175 +0,0 @@ ---- Configure.help.orig Wed Dec 15 20:35:10 1999 -+++ Configure.help Wed Dec 15 20:35:33 1999 -@@ -11317,6 +11317,172 @@ - - Please read the file Documentation/isdn/README.diversion. - -+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://i4l.mediatronix.de" -+ -+ 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 -+ -+ - ICN 2B and 4B support - CONFIG_ISDN_DRV_ICN - This enables support for two kinds of ISDN-cards made by a German diff --git a/Documentation/Configure.help.eicon.diff b/Documentation/Configure.help.eicon.diff deleted file mode 100644 index edbc92c3..00000000 --- a/Documentation/Configure.help.eicon.diff +++ /dev/null @@ -1,33 +0,0 @@ ---- Configure.org Sat Jul 31 14:01:20 1999 -+++ Configure.help Sat Jul 31 14:17:49 1999 -@@ -9820,6 +9820,30 @@ - you need to have access to a machine on the Internet that has a - program like lynx or netscape). - -+Eicon.Diehl active card support -+CONFIG_ISDN_DRV_EICON -+ Say Y here if you have an Eicon active ISDN card. In order to use -+ this card, additional firmware is necessary, which has to be loaded -+ into the card using the eiconctrl utility which is part of the latest -+ isdn4k-utils package. Please read the file -+ Documentation/isdn/README.eicon for more information. -+ -+Eicon old-type card support -+CONFIG_ISDN_DRV_EICON_ISA -+ Say Y here if you have an old-type Eicon active ISDN card. In order to -+ use this card, additional firmware is necessary, which has to be loaded -+ into the card using the eiconctrl utility which is part of the latest -+ isdn4k-utils package. Please read the file -+ Documentation/isdn/README.eicon for more information. -+ -+Support AT-Fax Class 2 commands -+CONFIG_ISDN_TTY_FAX -+ If you say Y here, the modem-emulator will support a subset of the -+ Fax Class 2 commands. Using a getty with fax-support -+ (mgetty+sendfax, hylafax), you will be able to use your Linux box -+ as an ISDN-fax-machine. This must be supported by the lowlevel driver -+ also. See Documentation/isdn/README.fax for more information. -+ - AVM-B1 with CAPI2.0 support - CONFIG_ISDN_DRV_AVMB1 - This enables support for the AVM B1 ISDN networking cards. In diff --git a/Documentation/isdn/00-INDEX b/Documentation/isdn/00-INDEX deleted file mode 100644 index b2e73cbc..00000000 --- a/Documentation/isdn/00-INDEX +++ /dev/null @@ -1,43 +0,0 @@ -00-INDEX - - this file (info on ISDN implementation for Linux) -CREDITS - - list of the kind folks that brought you this stuff. -INTERFACE - - description of Linklevel and Hardwarelevel ISDN interface. -README - - general info on what you need and what to do for Linux ISDN. -README.FAQ - - general info for FAQ. -README.audio - - info for running audio over ISDN. -README.fax - - info for using Fax over ISDN. -README.icn - - info on the ICN-ISDN-card and its driver. -README.HiSax - - info on the HiSax driver which replaces the old teles. -README.hfc-pci - - info on hfc-pci based cards. -README.pcbit - - info on the PCBIT-D ISDN adapter and driver. -README.syncppp - - info on running Sync PPP over ISDN. -syncPPP.FAQ - - frequently asked questions about running PPP over ISDN. -README.avmb1 - - info on driver for AVM-B1 ISDN card. -README.act2000 - - info on driver for IBM ACT-2000 card. -README.eicon - - info on driver for Eicon active cards. -README.concap - - info on "CONCAP" ecapsulation protocol interface used for X.25. -README.diversion - - info on module for isdn diversion services. -README.sc - - info on driver for Spellcaster cards. -README.x25 - _ info for running X.25 over ISDN. -README.hysdn - - info on driver for Hypercope active HYSDN cards - \ No newline at end of file diff --git a/Documentation/isdn/CREDITS b/Documentation/isdn/CREDITS deleted file mode 100644 index e1b3023e..00000000 --- a/Documentation/isdn/CREDITS +++ /dev/null @@ -1,70 +0,0 @@ - -I want to thank all who contributed to this project and especially to: -(in alphabetical order) - -Thomas Bogendörfer (tsbogend@bigbug.franken.de) - Tester, lots of bugfixes and hints. - -Alan Cox (alan@redhat.com) - For help getting into standard-kernel. - -Henner Eisen (eis@baty.hanse.de) - For X.25 implementation. - -Volker Götz (volker@oops.franken.de) - For contribution of man-pages, the imontty-tool and a perfect - maintaining of the mailing-list at hub-wue. - -Matthias Hessler (hessler@isdn4linux.de) - For creating and maintaining the FAQ. - -Bernhard Hailer (Bernhard.Hailer@lrz.uni-muenchen.de) - For creating the FAQ, and the leafsite HOWTO. - -Michael 'Ghandi' Herold (michael@abadonna.franken.de) - For contribution of the vbox answering machine. - -Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - For his Sync-PPP-code. - -Karsten Keil (keil@isdn4linux.de) - For adding 1TR6-support to the Teles-driver. - For the HiSax-driver. - -Michael Knigge (knick@cove.han.de) - For contributing the imon-tool - -Andreas Kool (akool@Kool.f.EUnet.de) - For contribution of the isdnlog/isdnrep-tool - -Pedro Roque Marques (roque@di.fc.ul.pt) - For lot of new ideas and the pcbit driver. - -Eberhard Moenkeberg (emoenke@gwdg.de) - For testing and help to get into kernel. - -Thomas Neumann (tn@ruhr.de) - For help with Cisco-SLARP and keepalive - -Jan den Ouden (denouden@groovin.xs4all.nl) - For contribution of the original teles-driver - -Carsten Paeth (calle@calle.in-berlin.de) - For the AVM-B1-CAPI2.0 driver - -Thomas Pfeiffer (pfeiffer@pds.de) - For V.110, extended T.70 and Hylafax extensions in isdn_tty.c - -Max Riegel (riegel@max.franken.de) - For making the ICN hardware-documentation and test-equipment available. - -Armin Schindler (mac@melware.de) - For the eicon active card driver. - -Gerhard 'Fido' Schneider (fido@wuff.mayn.de) - For heavy-duty-beta-testing with his BBS ;) - -Thomas Uhl (uhl@think.de) - For distributing the cards. - For pushing me to work ;-) - diff --git a/Documentation/isdn/HiSax.cert b/Documentation/isdn/HiSax.cert deleted file mode 100644 index af128daa..00000000 --- a/Documentation/isdn/HiSax.cert +++ /dev/null @@ -1,78 +0,0 @@ ------BEGIN PGP SIGNED MESSAGE----- - -First: - - HiSax is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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. - -However, if you wish to modify the HiSax sources, please note the following: - -HiSax has passed the ITU approval test suite with ELSA Quickstep ISDN cards -and Eicon Technology Diva 2.01 PCI card. -The certification is only valid for the combination of the tested software -version and the tested hardware. Any changes to the HiSax source code may -therefore affect the certification. - -If you change the main files of the HiSax ISDN stack, the certification will -become invalid. Because in most countries it is illegal to connect -unapproved ISDN equipment to the public network, I have to guarantee that -changes in HiSax do not affect the certification. - -In order to make a valid certification apparent to the user, I have built in -some validation checks that are made during the make process. The HiSax main -files are protected by md5 checksums and the md5sum file is pgp signed by -myself: - -KeyID 1024/FF992F6D 1997/01/16 Karsten Keil -Key fingerprint = 92 6B F7 58 EE 86 28 C8 C4 1A E6 DC 39 89 F2 AA - -Only if the checksums are OK, and the signature of the file -"drivers/isdn/hisax/md5sums.asc" match, is the certification valid; a -message confirming this is then displayed during the hisax init process. - -The affected files are: - -drivers/isdn/hisax/isac.c -drivers/isdn/hisax/isdnl1.c -drivers/isdn/hisax/isdnl2.c -drivers/isdn/hisax/isdnl3.c -drivers/isdn/hisax/tei.c -drivers/isdn/hisax/callc.c -drivers/isdn/hisax/l3dss1.c -drivers/isdn/hisax/l3_1tr6.c -drivers/isdn/hisax/cert.c -drivers/isdn/hisax/elsa.c -drivers/isdn/hisax/diva.c - -Please send any changes, bugfixes and patches to me rather than implementing -them directly into the HiSax sources. - -This does not reduce your rights granted by the GNU General Public License. -If you wish to change the sources, go ahead; but note that then the -certification is invalid even if you use one of the approved cards. - -Here are the certification registration numbers for ELSA Quickstep cards: -German D133361J CETECOM ICT Services GmbH 0682 -European D133362J CETECOM ICT Services GmbH 0682 - - -Karsten Keil -keil@isdn4linux.de - ------BEGIN PGP SIGNATURE----- -Version: 2.6.3i -Charset: noconv - -iQCVAwUBOFAwqTpxHvX/mS9tAQFI2QP9GLDK2iy/KBhwReE3F7LeO+tVhffTVZ3a -20q5/z/WcIg/pnH0uTkl2UgDXBFXYl45zJyDGNpAposIFmT+Edd14o7Vj1w/BBdn -Y+5rBmJf+gyBu61da5d6bv0lpymwRa/um+ri+ilYnZ/XPfg5JKhdjGSBCJuJAElM -d2jFbTrsMYw= -=LNf9 ------END PGP SIGNATURE----- diff --git a/Documentation/isdn/INTERFACE b/Documentation/isdn/INTERFACE deleted file mode 100644 index 9e4cf5f1..00000000 --- a/Documentation/isdn/INTERFACE +++ /dev/null @@ -1,783 +0,0 @@ -$Id$ - -Description of the Interface between Linklevel and Hardwarelevel - of isdn4linux: - - - The Communication between Linklevel (LL) and Hardwarelevel (HL) - is based on the struct isdn_if (defined in isdnif.h). - - An HL-driver can register itself at LL by calling the function - register_isdn() with a pointer to that struct. Prior to that, it has - to preset some of the fields of isdn_if. The LL sets the rest of - the fields. All further communication is done via callbacks using - the function-pointers defined in isdn_if. - - Changes/Version numbering: - - During development of the ISDN subsystem, several changes have been - made to the interface. Before it went into kernel, the package - had a unique version number. The last version, distributed separately - was 0.7.4. When the subsystem went into kernel, every functional unit - got a separate version number. These numbers are shown at initialization, - separated by slashes: - - c.c/t.t/n.n/p.p/a.a/v.v - - where - - c.c is the revision of the common code. - t.t is the revision of the tty related code. - n.n is the revision of the network related code. - p.p is the revision of the ppp related code. - a.a is the revision of the audio related code. - v.v is the revision of the V.110 related code. - - Changes in this document are marked with '***CHANGEx' where x representing - the version number. If that number starts with 0, it refers to the old, - separately distributed package. If it starts with one of the letters - above, it refers to the revision of the corresponding module. - ***CHANGEIx refers to the revision number of the isdnif.h - -1. Description of the fields of isdn_if: - - int channels; - - This field has to be set by the HL-driver to the number of channels - supported prior to calling register_isdn(). Upon return of the call, - the LL puts an id there, which has to be used by the HL-driver when - invoking the other callbacks. - - int maxbufsize; - - ***CHANGE0.6: New since this version. - - Also to be preset by the HL-driver. With this value the HL-driver - tells the LL the maximum size of a data-packet it will accept. - - unsigned long features; - - To be preset by the HL-driver. Using this field, the HL-driver - announces the features supported. At the moment this is limited to - report the supported layer2 and layer3-protocols. For setting this - field the constants ISDN_FEATURE..., declared in isdnif.h have to be - used. - - ***CHANGE0.7.1: The line type (1TR6, EDSS1) has to be set. - - unsigned short hl_hdrlen; - - ***CHANGE0.7.4: New field. - - To be preset by the HL-driver, if it supports sk_buff's. The driver - should put here the amount of additional space needed in sk_buff's for - its internal purposes. Drivers not supporting sk_buff's should - initialize this field to 0. - - void (*rcvcallb_skb)(int, int, struct sk_buff *) - - ***CHANGE0.7.4: New field. - - This field will be set by LL. The HL-driver delivers received data- - packets by calling this function. Upon calling, the HL-driver must - already have its private data pulled off the head of the sk_buff. - - Parameter: - int driver-Id - int Channel-number locally to the driver. (starting with 0) - struct sk_buff * Pointer to sk_buff, containing received data. - - int (*statcallb)(isdn_ctrl*); - - This field will be set by LL. This function has to be called by the - HL-driver for signaling status-changes or other events to the LL. - - Parameter: - isdn_ctrl* - - The struct isdn_ctrl also defined in isdn_if. The exact meanings of its - fields are described together with the descriptions of the possible - events. Here is only a short description of the fields: - - driver = driver Id. - command = event-type. (one of the constants ISDN_STAT_...) - arg = depends on event-type. - num = depends on event-type. - - Returnvalue: - 0 on success, else -1 - - int (*command)(isdn_ctrl*); - - This field has to be preset by the HL-driver. It points to a function, - to be called by LL to perform functions like dialing, B-channel - setup, etc. The exact meaning of the parameters is described with the - descriptions of the possible commands. - - Parameter: - isdn_ctrl* - driver = driver-Id - command = command to perform. (one of the constants ISDN_CMD_...) - arg = depends on command. - num = depends on command. - - Returnvalue: - >=0 on success, else error-code (-ENODEV etc.) - - int (*writebuf_skb)(int, int, int, struct sk_buff *) - - ***CHANGE0.7.4: New field. - ***CHANGEI.1.21: New field. - - This field has to be preset by the HL-driver. The given function will - be called by the LL for delivering data to be send via B-Channel. - - - Parameter: - int driver-Id ***CHANGE0.7.4: New parameter. - int channel-number locally to the HL-driver. (starts with 0) - int ack ***ChangeI1.21: New parameter - If this is !0, the driver has to signal the delivery - by sending an ISDN_STAT_BSENT. If this is 0, the driver - MUST NOT send an ISDN_STAT_BSENT. - struct sk_buff * Pointer to sk_buff containing data to be send via - B-channel. - - Returnvalue: - Length of data accepted on success, else error-code (-EINVAL on - oversized packets etc.) - - int (*writecmd)(u_char*, int, int, int, int); - - This field has to be preset by the HL-driver. The given function will be - called to perform write-requests on /dev/isdnctrl (i.e. sending commands - to the card) The data-format is hardware-specific. This function is - intended for debugging only. It is not necessary for normal operation - and never will be called by the tty-emulation- or network-code. If - this function is not supported, the driver has to set NULL here. - - Parameter: - u_char* pointer to data. - int length of data. - int flag: 0 = call from within kernel-space. (HL-driver must use - memcpy, may NOT use schedule()) - 1 = call from user-space. (HL-driver must use - memcpy_fromfs, use of schedule() allowed) - int driver-Id. - int channel-number locally to the HL-driver. (starts with 0) - -***CHANGEI1.14: The driver-Id and channel-number are new since this revision. - - Returnvalue: - Length of data accepted on success, else error-code (-EINVAL etc.) - - int (*readstat)(u_char*, int, int, int, int); - - This field has to be preset by the HL-driver. The given function will be - called to perform read-requests on /dev/isdnctrl (i.e. reading replies - from the card) The data-format is hardware-specific. This function is - intended for debugging only. It is not necessary for normal operation - and never will be called by the tty-emulation- or network-code. If - this function is not supported, the driver has to set NULL here. - - Parameter: - u_char* pointer to data. - int length of data. - int flag: 0 = call from within kernel-space. (HL-driver must use - memcpy, may NOT use schedule()) - 1 = call from user-space. (HL-driver must use - memcpy_fromfs, use of schedule() allowed) - int driver-Id. - int channel-number locally to the HL-driver. (starts with 0) - -***CHANGEI1.14: The driver-Id and channel-number are new since this revision. - - Returnvalue: - Length of data on success, else error-code (-EINVAL etc.) - - char id[20]; - ***CHANGE0.7: New since this version. - - This string has to be preset by the HL-driver. Its purpose is for - identification of the driver by the user. Eg.: it is shown in the - status-info of /dev/isdninfo. Furthermore it is used as Id for binding - net-interfaces to a specific channel. If a string of length zero is - given, upon return, isdn4linux will replace it by a generic name. (line0, - line1 etc.) It is recommended to make this string configurable during - module-load-time. (copy a global variable to this string.) For doing that, - modules 1.2.8 or newer are necessary. - -2. Description of the commands, a HL-driver has to support: - - All commands will be performed by calling the function command() described - above from within the LL. The field command of the struct-parameter will - contain the desired command, the field driver is always set to the - appropriate driver-Id. - - Until now, the following commands are defined: - -***CHANGEI1.34: The parameter "num" has been replaced by a union "parm" containing - the old "num" and a new setup_type struct used for ISDN_CMD_DIAL - and ISDN_STAT_ICALL callback. - - ISDN_CMD_IOCTL: - - This command is intended for performing ioctl-calls for configuring - hardware or similar purposes (setting port-addresses, loading firmware - etc.) For this purpose, in the LL all ioctl-calls with an argument - >= IIOCDRVCTL (0x100) will be handed transparently to this - function after subtracting 0x100 and placing the result in arg. - Example: - If a userlevel-program calls ioctl(0x101,...) the function gets - called with the field command set to 1. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_IOCTL - arg = Original ioctl-cmd - IIOCDRVCTL - parm.num = first bytes filled with (unsigned long)arg - - Returnvalue: - Depending on driver. - - - ISDN_CMD_DIAL: - - This command is used to tell the HL-driver it should dial a given - number. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_DIAL - arg = channel-number locally to the driver. (starting with 0) - - parm.setup.phone = An ASCII-String containing the number to dial. - parm.setup.eazmsn = An ASCII-Sting containing the own EAZ or MSN. - parm.setup.si1 = The Service-Indicator. - parm.setup.si2 = Additional Service-Indicator. - - If the Line has been designed as SPV (a special german - feature, meaning semi-leased-line) the phone has to - start with an "S". - ***CHANGE0.6: In previous versions the EAZ has been given in the - highbyte of arg. - ***CHANGE0.7.1: New since this version: ServiceIndicator and AddInfo. - - ISDN_CMD_ACCEPTD: - - With this command, the HL-driver is told to accept a D-Channel-setup. - (Response to an incoming call) - - Parameter: - driver = driver-Id. - command = ISDN_CMD_ACCEPTD - arg = channel-number locally to the driver. (starting with 0) - parm = unused. - - ISDN_CMD_ACCEPTB: - - With this command, the HL-driver is told to perform a B-Channel-setup. - (after establishing D-Channel-Connection) - - Parameter: - driver = driver-Id. - command = ISDN_CMD_ACCEPTB - arg = channel-number locally to the driver. (starting with 0) - parm = unused. - - ISDN_CMD_HANGUP: - - With this command, the HL-driver is told to hangup (B-Channel if - established first, then D-Channel). This command is also used for - actively rejecting an incoming call. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_HANGUP - arg = channel-number locally to the driver. (starting with 0) - parm = unused. - - ISDN_CMD_CLREAZ: - - With this command, the HL-driver is told not to signal incoming - calls to the LL. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_CLREAZ - arg = channel-number locally to the driver. (starting with 0) - parm = unused. - - ISDN_CMD_SETEAZ: - - With this command, the HL-driver is told to signal incoming calls for - the given EAZs/MSNs to the LL. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_SETEAZ - arg = channel-number locally to the driver. (starting with 0) - parm.num = ASCII-String, containing the desired EAZ's/MSN's - (comma-separated). If an empty String is given, the - HL-driver should respond to ALL incoming calls, - regardless of the destination-address. - ***CHANGE0.6: New since this version the "empty-string"-feature. - - ISDN_CMD_GETEAZ: (currently unused) - - With this command, the HL-driver is told to report the current setting - given with ISDN_CMD_SETEAZ. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_GETEAZ - arg = channel-number locally to the driver. (starting with 0) - parm.num = ASCII-String, containing the current EAZ's/MSN's - - ISDN_CMD_SETSIL: (currently unused) - - With this command, the HL-driver is told to signal only incoming - calls with the given Service-Indicators. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_SETSIL - arg = channel-number locally to the driver. (starting with 0) - parm.num = ASCII-String, containing the desired Service-Indicators. - - ISDN_CMD_GETSIL: (currently unused) - - With this command, the HL-driver is told to return the current - Service-Indicators it will respond to. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_SETSIL - arg = channel-number locally to the driver. (starting with 0) - parm.num = ASCII-String, containing the current Service-Indicators. - - ISDN_CMD_SETL2: - - With this command, the HL-driver is told to select the given Layer-2- - protocol. This command is issued by the LL prior to ISDN_CMD_DIAL or - ISDN_CMD_ACCEPTD. - - - Parameter: - driver = driver-Id. - command = ISDN_CMD_SETL2 - arg = channel-number locally to the driver. (starting with 0) - logical or'ed with (protocol-Id << 8) - protocol-Id is one of the constants ISDN_PROTO_L2... - parm = unused. - - ISDN_CMD_GETL2: (currently unused) - - With this command, the HL-driver is told to return the current - setting of the Layer-2-protocol. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_GETL2 - arg = channel-number locally to the driver. (starting with 0) - parm = unused. - Returnvalue: - current protocol-Id (one of the constants ISDN_L2_PROTO) - - ISDN_CMD_SETL3: - - With this command, the HL-driver is told to select the given Layer-3- - protocol. This command is issued by the LL prior to ISDN_CMD_DIAL or - ISDN_CMD_ACCEPTD. - - - Parameter: - driver = driver-Id. - command = ISDN_CMD_SETL3 - arg = channel-number locally to the driver. (starting with 0) - logical or'ed with (protocol-Id << 8) - 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) - - With this command, the HL-driver is told to return the current - setting of the Layer-3-protocol. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_GETL3 - arg = channel-number locally to the driver. (starting with 0) - parm = unused. - Returnvalue: - current protocol-Id (one of the constants ISDN_L3_PROTO) - - ISDN_CMD_LOCK: - - With this command the HL-driver is told, that it will be used by the - LL and therefore may not be unloaded. The HL-driver should use - MOD_INC_USE_COUNT to tell that to the kernel. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_LOCK - arg = unused. - parm = unused. - - ISDN_CMD_UNLOCK: - - With this command the HL-driver is told, that it is no more used by the - LL and therefore may be unloaded. The HL-driver should use - DEC_INC_USE_COUNT to tell that to the kernel. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_UNLOCK - arg = unused. - parm = unused. - - ISDN_CMD_PROCEED: - - With this command, the HL-driver is told to proceed with a incoming call. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_PROCEED - arg = channel-number locally to the driver. (starting with 0) - setup.eazmsn= empty string or string send as uus1 in DSS1 with - PROCEED message - - ISDN_CMD_ALERT: - - With this command, the HL-driver is told to alert a proceeding call. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_ALERT - arg = channel-number locally to the driver. (starting with 0) - setup.eazmsn= empty string or string send as uus1 in DSS1 with - ALERT message - - ISDN_CMD_REDIR: - - With this command, the HL-driver is told to redirect a call in proceeding - or alerting state. - - Parameter: - driver = driver-Id. - command = ISDN_CMD_REDIR - arg = channel-number locally to the driver. (starting with 0) - setup.eazmsn= empty string or string send as uus1 in DSS1 protocol - setup.screen= screening indicator - setup.phone = redirected to party number - - ISDN_CMD_PROT_IO: - - With this call, the LL-driver invokes protocol specific features through - the LL. - The call is not implicitely bound to a connection. - - Parameter: - driver = driver-Id - command = ISDN_CMD_PROT_IO - arg = The lower 8 Bits define the adressed protocol as defined - in ISDN_PTYPE..., the upper bits are used to differenciate - the protocol specific CMD. - - para = protocol and function specific. See isdnif.h for detail. - - - ISDN_CMD_FAXCMD: - - With this command the HL-driver receives a fax sub-command. - For details refer to INTERFACE.fax - - Parameter: - driver = driver-Id. - command = ISDN_CMD_FAXCMD - arg = channel-number locally to the driver. (starting with 0) - parm = unused. - - -3. Description of the events to be signaled by the HL-driver to the LL. - - All status-changes are signaled via calling the previously described - function statcallb(). The field command of the struct isdn_cmd has - to be set by the HL-driver with the appropriate Status-Id (event-number). - The field arg has to be set to the channel-number (locally to the driver, - starting with 0) to which this event applies. (Exception: STAVAIL-event) - - Until now, the following Status-Ids are defined: - - ISDN_STAT_AVAIL: - - With this call, the HL-driver signals the availability of new data - for readstat(). Used only for debugging-purposes, see description - of readstat(). - - Parameter: - driver = driver-Id - command = ISDN_STAT_STAVAIL - arg = length of available data. - parm = unused. - - ISDN_STAT_ICALL: - ISDN_STAT_ICALLW: - - With this call, the HL-driver signals an incoming call to the LL. - If ICALLW is signalled the incoming call is a waiting call without - a available B-chan. - - Parameter: - driver = driver-Id - command = ISDN_STAT_ICALL - arg = channel-number, locally to the driver. (starting with 0) - para.setup.phone = Callernumber. - para.setup.eazmsn = CalledNumber. - para.setup.si1 = Service Indicator. - para.setup.si2 = Additional Service Indicator. - para.setup.plan = octet 3 from Calling party number Information Element. - para.setup.screen = octet 3a from Calling party number Information Element. - - Return: - 0 = No device matching this call. - 1 = At least one device matching this call (RING on ttyI). - HL-driver may send ALERTING on the D-channel in this case. - 2 = Call will be rejected. - 3 = Incoming called party number is currently incomplete. - Additional digits are required. - Used for signalling with PtP connections. - 4 = Call will be held in a proceeding state - (HL driver sends PROCEEDING) - Used when a user space prog needs time to interpret a call - para.setup.eazmsn may be filled with an uus1 message of - 30 octets maximum. Empty string if no uus. - 5 = Call will be actively deflected to another party - Only available in DSS1/EURO protocol - para.setup.phone must be set to destination party number - para.setup.eazmsn may be filled with an uus1 message of - 30 octets maximum. Empty string if no uus. - -1 = An error happened. (Invalid parameters for example.) - The keypad support now is included in the dial command. - - - ISDN_STAT_RUN: - - With this call, the HL-driver signals availability of the ISDN-card. - (after initializing, loading firmware) - - Parameter: - driver = driver-Id - command = ISDN_STAT_RUN - arg = unused. - parm = unused. - - ISDN_STAT_STOP: - - With this call, the HL-driver signals unavailability of the ISDN-card. - (before unloading, while resetting/reconfiguring the card) - - Parameter: - driver = driver-Id - command = ISDN_STAT_STOP - arg = unused. - parm = unused. - - ISDN_STAT_DCONN: - - With this call, the HL-driver signals the successful establishment of - a D-Channel-connection. (Response to ISDN_CMD_ACCEPTD or ISDN_CMD_DIAL) - - Parameter: - driver = driver-Id - command = ISDN_STAT_DCONN - arg = channel-number, locally to the driver. (starting with 0) - parm = unused. - - ISDN_STAT_BCONN: - - With this call, the HL-driver signals the successful establishment of - a B-Channel-connection. (Response to ISDN_CMD_ACCEPTB or because the - remote-station has initiated establishment) - - The HL driver should call this when the logical l2/l3 protocol - connection on top of the physical B-channel is established. - - Parameter: - driver = driver-Id - command = ISDN_STAT_BCONN - arg = channel-number, locally to the driver. (starting with 0) - parm.num = ASCII-String, containing type of connection (for analog - modem only). This will be appended to the CONNECT message - e.g. 14400/V.32bis - - ISDN_STAT_DHUP: - - With this call, the HL-driver signals the shutdown of a - D-Channel-connection. This could be a response to a prior ISDN_CMD_HANGUP, - or caused by a remote-hangup or if the remote-station has actively - rejected a call. - - Parameter: - driver = driver-Id - command = ISDN_STAT_DHUP - arg = channel-number, locally to the driver. (starting with 0) - parm = unused. - - ISDN_STAT_BHUP: - - With this call, the HL-driver signals the shutdown of a - B-Channel-connection. This could be a response to a prior ISDN_CMD_HANGUP, - or caused by a remote-hangup. - - The HL driver should call this as soon as the logical l2/l3 protocol - connection on top of the physical B-channel is released. - - Parameter: - driver = driver-Id - command = ISDN_STAT_BHUP - arg = channel-number, locally to the driver. (starting with 0) - parm = unused. - - ISDN_STAT_CINF: - - With this call, the HL-driver delivers charge-unit information to the - LL. - - Parameter: - driver = driver-Id - command = ISDN_STAT_CINF - arg = channel-number, locally to the driver. (starting with 0) - parm.num = ASCII string containing charge-units (digits only). - - ISDN_STAT_LOAD: (currently unused) - - ISDN_STAT_UNLOAD: - - With this call, the HL-driver signals that it will be unloaded now. This - tells the LL to release all corresponding data-structures. - - Parameter: - driver = driver-Id - command = ISDN_STAT_UNLOAD - arg = unused. - parm = unused. - - ISDN_STAT_BSENT: - - With this call the HL-driver signals the delivery of a data-packet. - This callback is used by the network-interfaces only, tty-Emulation - does not need this call. - - Parameter: - driver = driver-Id - command = ISDN_STAT_BSENT - arg = channel-number, locally to the driver. (starting with 0) - parm.length = ***CHANGEI.1.21: New field. - the driver has to set this to the original length - of the skb at the time of receiving it from the linklevel. - - ISDN_STAT_NODCH: - - With this call, the driver has to respond to a prior ISDN_CMD_DIAL, if - no D-Channel is available. - - Parameter: - driver = driver-Id - command = ISDN_STAT_NODCH - arg = channel-number, locally to the driver. (starting with 0) - parm = unused. - - ISDN_STAT_ADDCH: - - This call is for HL-drivers, which are unable to check card-type - or numbers of supported channels before they have loaded any firmware - using ioctl. Those HL-driver simply set the channel-parameter to a - minimum channel-number when registering, and later if they know - the real amount, perform this call, allocating additional channels. - - Parameter: - driver = driver-Id - command = ISDN_STAT_ADDCH - arg = number of channels to be added. - parm = unused. - - ISDN_STAT_CAUSE: - - With this call, the HL-driver delivers CAUSE-messages to the LL. - Currently the LL does not use this messages. Their contents is simply - logged via kernel-messages. Therefore, currently the format of the - messages is completely free. However they should be printable. - - Parameter: - driver = driver-Id - command = ISDN_STAT_NODCH - arg = channel-number, locally to the driver. (starting with 0) - parm.num = ASCII string containing CAUSE-message. - - ISDN_STAT_DISPLAY: - - With this call, the HL-driver delivers DISPLAY-messages to the LL. - Currently the LL does not use this messages. - - Parameter: - driver = driver-Id - command = ISDN_STAT_DISPLAY - arg = channel-number, locally to the driver. (starting with 0) - para.display= string containing DISPLAY-message. - - ISDN_STAT_PROT: - - With this call, the HL-driver delivers protocol specific infos to the LL. - The call is not implicitely bound to a connection. - - Parameter: - driver = driver-Id - command = ISDN_STAT_PROT - arg = The lower 8 Bits define the adressed protocol as defined - in ISDN_PTYPE..., the upper bits are used to differenciate - the protocol specific STAT. - - para = protocol and function specific. See isdnif.h for detail. - - ISDN_STAT_DISCH: - - With this call, the HL-driver signals the LL to disable or enable the - use of supplied channel and driver. - The call may be used to reduce the available number of B-channels after - loading the driver. The LL has to ignore a disabled channel when searching - for free channels. The HL driver itself never delivers STAT callbacks for - disabled channels. - The LL returns a nonzero code if the operation was not successfull or the - selected channel is actually regarded as busy. - - Parameter: - driver = driver-Id - command = ISDN_STAT_DISCH - arg = channel-number, locally to the driver. (starting with 0) - parm.num[0] = 0 if channel shall be disabled, else enabled. - - ISDN_STAT_L1ERR: - - ***CHANGEI1.21 new status message. - A signal can be sent to the linklevel if an Layer1-error results in - packet-loss on receive or send. The field errcode of the cmd.parm - union describes the error more precisely. - - Parameter: - driver = driver-Id - command = ISDN_STAT_L1ERR - arg = channel-number, locally to the driver. (starting with 0) - parm.errcode= ISDN_STAT_L1ERR_SEND: Packet lost while sending. - ISDN_STAT_L1ERR_RECV: Packet lost while receiving. - ISDN_STAT_FAXIND: - - With this call the HL-driver signals a fax sub-command to the LL. - For details refer to INTERFACE.fax - - Parameter: - driver = driver-Id. - command = ISDN_STAT_FAXIND - arg = channel-number, locally to the driver. (starting with 0) - parm = unused. - diff --git a/Documentation/isdn/INTERFACE.fax b/Documentation/isdn/INTERFACE.fax deleted file mode 100644 index 1f47b654..00000000 --- a/Documentation/isdn/INTERFACE.fax +++ /dev/null @@ -1,163 +0,0 @@ -$Id$ - - -Description of the fax-subinterface between linklevel and hardwarelevel of - isdn4linux. - - The communication between linklevel (LL) and harwarelevel (HL) for fax - is based on the struct T30_s (defined in isdnif.h). - This struct is allocated in the LL. - In order to use fax, the LL provides the pointer to this struct with the - command ISDN_CMD_SETL3 (parm.fax). This pointer expires in case of hangup - and when a new channel to a new connection is assigned. - - -Data handling: - In send-mode the HL-driver has to handle the codes and the bit-order - conversion by itself. - In receive-mode the LL-driver takes care of the bit-order conversion - (specified by +FBOR) - -Structure T30_s description: - - This structure stores the values (set by AT-commands), the remote- - capability-values and the command-codes between LL and HL. - - If the HL-driver receives ISDN_CMD_FAXCMD, all needed information - is in this struct set by the LL. - To signal information to the LL, the HL-driver has to set the - the parameters and use ISDN_STAT_FAXIND. - (Please refer to INTERFACE) - -Structure T30_s: - - All members are 8-bit unsigned (__u8) - - - resolution - - rate - - width - - length - - compression - - ecm - - binary - - scantime - - id[] - Local faxmachine's parameters, set by +FDIS, +FDCS, +FLID, ... - - - r_resolution - - r_rate - - r_width - - r_length - - r_compression - - r_ecm - - r_binary - - r_scantime - - r_id[] - Remote faxmachine's parameters. To be set by HL-driver. - - - phase - Defines the actual state of fax connection. Set by HL or LL - depending on progress and type of connection. - If the phase changes because of an AT command, the LL driver - changes this value. Otherwise the HL-driver takes care of it, but - only neccessary on call establishment (from IDLE to PHASE_A). - (one of the constants ISDN_FAX_PHASE_[IDLE,A,B,C,D,E]) - - - direction - Defines outgoing/send or incoming/receive connection. - (ISDN_TTY_FAX_CONN_[IN,OUT]) - - - code - Commands from LL to HL; possible constants : - ISDN_TTY_FAX_DR signals +FDR command to HL - - ISDN_TTY_FAX_DT signals +FDT command to HL - - ISDN_TTY_FAX_ET signals +FET command to HL - - - Other than that the "code" is set with the hangup-code value at - the end of connection for the +FHNG message. - - - r_code - Commands from HL to LL; possible constants : - ISDN_TTY_FAX_CFR output of +FCFR message. - - ISDN_TTY_FAX_RID output of remote ID set in r_id[] - (+FCSI/+FTSI on send/receive) - - ISDN_TTY_FAX_DCS output of +FDCS and CONNECT message, - switching to phase C. - - ISDN_TTY_FAX_ET signals end of data, - switching to phase D. - - ISDN_TTY_FAX_FCON signals the established, outgoing connection, - switching to phase B. - - ISDN_TTY_FAX_FCON_I signals the established, incoming connection, - switching to phase B. - - ISDN_TTY_FAX_DIS output of +FDIS message and values. - - ISDN_TTY_FAX_SENT signals that all data has been sent - and is acknowledged, - OK message will be sent. - - ISDN_TTY_FAX_PTS signals a msg-confirmation (page sent successful), - depending on fet value: - 0: output OK message (more pages follow) - 1: switching to phase B (next document) - - ISDN_TTY_FAX_TRAIN_OK output of +FDCS and OK message (for receive mode). - - ISDN_TTY_FAX_EOP signals end of data in receive mode, - switching to phase D. - - ISDN_TTY_FAX_HNG output of the +FHNG and value set by code and - OK message, switching to phase E. - - - - badlin - Value of +FBADLIN - - - badmul - Value of +FBADMUL - - - bor - Value of +FBOR - - - fet - Value of +FET command in send-mode. - Set by HL in receive-mode for +FET message. - - - pollid[] - ID-string, set by +FCIG - - - cq - Value of +FCQ - - - cr - Value of +FCR - - - ctcrty - Value of +FCTCRTY - - - minsp - Value of +FMINSP - - - phcto - Value of +FPHCTO - - - rel - Value of +FREL - - - nbc - Value of +FNBC (0,1) - (+FNBC is not a known class 2 fax command, I added this to change the - automatic "best capabilities" connection in the eicon HL-driver) - - -Armin -mac@melware.de - diff --git a/Documentation/isdn/README b/Documentation/isdn/README deleted file mode 100644 index afd9f45a..00000000 --- a/Documentation/isdn/README +++ /dev/null @@ -1,597 +0,0 @@ -README for the ISDN-subsystem - -1. Preface - - 1.1 Introduction - - This README describes how to set up and how to use the different parts - of the ISDN-subsystem. - - For using the ISDN-subsystem, some additional userlevel programs are - necessary. Those programs and some contributed utilities are available - at - - ftp.isdn4linux.de - - /pub/isdn4linux/isdn4k-utils-.tar.gz - - - We also have set up a mailing-list: - - The isdn4linux-project originates in Germany, and therefore by historical - reasons, the mailing-list's primary language is german. However mails - written in english have been welcome all the time. - - to subscribe: write a email to majordomo@listserv.isdn4linux.de, - Subject irrelevant, in the message body: - subscribe isdn4linux - - To write to the mailing-list, write to isdn4linux@listserv.isdn4linux.de - - This mailinglist is bidirectionally gated to the newsgroup - - de.alt.comm.isdn4linux - - There is also a well maintained FAQ in English available at - http://www.mhessler.de/i4lfaq/ - It can be viewed online, or downloaded in sgml/text/html format. - The FAQ can also be viewed online at - http://www.isdn4inux.de/faq/ - or downloaded from - ftp://ftp.isdn4linux.de/pub/isdn4linux/FAQ/ - - 1.1 Technical details - - In the following Text, the terms MSN and EAZ are used. - - MSN is the abbreviation for (M)ultiple(S)ubscriber(N)umber, and applies - to Euro(EDSS1)-type lines. Usually it is simply the phone number. - - EAZ is the abbreviation of (E)ndgeraete(A)uswahl(Z)iffer and - applies to German 1TR6-type lines. This is a one-digit string, - simply appended to the base phone number - - The internal handling is nearly identical, so replace the appropriate - term to that one, which applies to your local ISDN-environment. - - When the link-level-module isdn.o is loaded, it supports up to 16 - low-level-modules with up to 64 channels. (The number 64 is arbitrarily - chosen and can be configured at compile-time --ISDN_MAX in isdn.h). - A low-level-driver can register itself through an interface (which is - defined in isdnif.h) and gets assigned a slot. - The following char-devices are made available for each channel: - - A raw-control-device with the following functions: - write: raw D-channel-messages (format: depends on driver). - read: raw D-channel-messages (format: depends on driver). - ioctl: depends on driver, i.e. for the ICN-driver, the base-address of - the ports and the shared memory on the card can be set and read - also the boot-code and the protocol software can be loaded into - the card. - - O N L Y !!! for debugging (no locking against other devices): - One raw-data-device with the following functions: - write: data to B-channel. - read: data from B-channel. - - In addition the following devices are made available: - - 128 tty-devices (64 cuix and 64 ttyIx) with integrated modem-emulator: - The functionality is almost the same as that of a serial device - (the line-discs are handled by the kernel), which lets you run - SLIP, CSLIP and asynchronous PPP through the devices. We have tested - Seyon, minicom, CSLIP (uri-dip) PPP, mgetty, XCept and Hylafax. - - The modem-emulation supports the following: - 1.3.1 Commands: - - ATA Answer incoming call. - ATD Dial, the number may contain: - [0-9] and [,#.*WPT-S] - the latter are ignored until 'S'. - The 'S' must precede the number, if - the line is a SPV (German 1TR6). - ATE0 Echo off. - ATE1 Echo on (default). - ATH Hang-up. - ATH1 Off hook (ignored). - ATH0 Hang-up. - ATI Return "ISDN for Linux...". - ATI0 " - ATI1 " - ATI2 Report of last connection. - ATO On line (data mode). - ATQ0 Enable result codes (default). - ATQ1 Disable result codes (default). - ATSx=y Set register x to y. - ATSx? Show contents of register x. - ATV0 Numeric responses. - ATV1 English responses (default). - ATZ Load registers and EAZ/MSN from Profile. - AT&Bx Set Send-Packet-size to x (max. 4000) - The real packet-size may be limited by the - low-level-driver used. e.g. the HiSax-Module- - limit is 2000. You will get NO Error-Message, - if you set it to higher values, because at the - time of giving this command the corresponding - driver may not be selected (see "Automatic - Assignment") however the size of outgoing packets - will be limited correctly. - AT&D0 Ignore DTR - AT&D2 DTR-low-edge: Hang up and return to - command mode (default). - AT&D3 Same as AT&D2 but also resets all registers. - AT&Ex Set the EAZ/MSN for this channel to x. - AT&F Reset all registers and profile to "factory-defaults" - AT&Lx Set list of phone numbers to listen on. x is a - list of wildcard patterns separated by semicolon. - If this is set, it has precedence over the MSN set - by AT&E. - AT&Rx Select V.110 bitrate adaption. - This command enables V.110 protocol with 9600 baud - (x=9600), 19200 baud (x=19200) or 38400 baud - (x=38400). A value of x=0 disables V.110 switching - back to default X.75. This command sets the following - Registers: - Reg 14 (Layer-2 protocol): - x = 0: 0 - x = 9600: 7 - x = 19200: 8 - x = 38400: 9 - Reg 18.2 = 1 - Reg 19 (Additional Service Indicator): - x = 0: 0 - x = 9600: 197 - x = 19200: 199 - x = 38400: 198 - Note on value in Reg 19: - There is _NO_ common convention for 38400 baud. - The value 198 is choosen arbitrarily. Users - _MUST_ negotiate this value before establishing - a connection. - AT&Sx Set window-size (x = 1..8) (not yet implemented) - AT&V Show all settings. - AT&W0 Write registers and EAZ/MSN to profile. See also - iprofd (5.c in this README). - AT&X0 BTX-mode and T.70-mode off (default) - AT&X1 BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0) - AT&X2 T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0) - AT+Rx Resume a suspended call with CallID x (x = 1,2,3...) - AT+Sx Suspend a call with CallID x (x = 1,2,3...) - - For voice-mode commands refer to README.audio - - 1.3.2 Escape sequence: - During a connection, the emulation reacts just like - a normal modem to the escape sequence +++. - (The escape character - default '+' - can be set in the - register 2). - The DELAY must at least be 1.5 seconds long and delay - between the escape characters must not exceed 0.5 seconds. - - 1.3.3 Registers: - - Nr. Default Description - 0 0 Answer on ring number. - (no auto-answer if S0=0). - 1 0 Count of rings. - 2 43 Escape character. - (a value >= 128 disables the escape sequence). - 3 13 Carriage return character (ASCII). - 4 10 Line feed character (ASCII). - 5 8 Backspace character (ASCII). - 6 3 Delay in seconds before dialing. - 7 60 Wait for carrier. - 8 2 Pause time for comma (ignored) - 9 6 Carrier detect time (ignored) - 10 7 Carrier loss to disconnect time (ignored). - 11 70 Touch tone timing (ignored). - 12 69 Bit coded register: - Bit 0: 0 = Suppress response messages. - 1 = Show response messages. - Bit 1: 0 = English response messages. - 1 = Numeric response messages. - Bit 2: 0 = Echo off. - 1 = Echo on. - Bit 3 0 = DCD always on. - 1 = DCD follows carrier. - Bit 4 0 = CTS follows RTS - 1 = Ignore RTS, CTS always on. - Bit 5 0 = return to command mode on DTR low. - 1 = Same as 0 but also resets all - registers. - See also register 13, bit 2 - Bit 6 0 = DSR always on. - 1 = DSR only on if channel is available. - Bit 7 0 = Cisco-PPP-flag-hack off (default). - 1 = Cisco-PPP-flag-hack on. - 13 0 Bit coded register: - Bit 0: 0 = Use delayed tty-send-algorithm - 1 = Direct tty-send. - Bit 1: 0 = T.70 protocol (Only for BTX!) off - 1 = T.70 protocol (Only for BTX!) on - Bit 2: 0 = Don't hangup on DTR low. - 1 = Hangup on DTR low. - Bit 3: 0 = Standard response messages - 1 = Extended response messages - Bit 4: 0 = CALLER NUMBER before every RING. - 1 = CALLER NUMBER after first RING. - Bit 5: 0 = T.70 extended protocol off - 1 = T.70 extended protocol on - Bit 6: 0 = Special RUNG Message off - 1 = Special RUNG Message on - "RUNG" is delivered on a ttyI, if - an incoming call happened (RING) and - the remote party hung up before any - local ATA was given. - Bit 7: 0 = Don't show display messages from net - 1 = Show display messages from net - (S12 Bit 1 must be 0 too) - 14 0 Layer-2 protocol: - 0 = X75/LAPB with I-frames - 1 = X75/LAPB with UI-frames - 2 = X75/LAPB with BUI-frames - 3 = HDLC - 4 = Transparent (audio) - 7 = V.110, 9600 baud - 8 = V.110, 19200 baud - 9 = V.110, 38400 baud - 10 = Analog Modem (only if hardware supports this) - 11 = Fax G3 (only if hardware supports this) - 15 0 Layer-3 protocol: - 0 = transparent - 1 = transparent with audio features (e.g. DSP) - 2 = Fax G3 Class 2 commands (S14 has to be set to 11) - 2 = Fax G3 Class 1 commands (S14 has to be set to 11) - 16 250 Send-Packet-size/16 - 17 8 Window-size (not yet implemented) - 18 4 Bit coded register, Service-Octet-1 to accept, - or to be used on dialout: - Bit 0: Service 1 (audio) when set. - Bit 1: Service 5 (BTX) when set. - Bit 2: Service 7 (data) when set. - Note: It is possible to set more than one - bit. In this case, on incoming calls - the selected services are accepted, - and if the service is "audio", the - Layer-2-protocol is automatically - changed to 4 regardless of the setting - of register 14. On outgoing calls, - the most significant 1-bit is chosen to - select the outgoing service octet. - 19 0 Service-Octet-2 - 20 0 Bit coded register (readonly) - Service-Octet-1 of last call. - Bit mapping is the same as register 18 - 21 0 Bit coded register (readonly) - Set on incoming call (during RING) to - octet 3 of calling party number IE (Numbering plan) - See section 4.5.10 of ITU Q.931 - 22 0 Bit coded register (readonly) - Set on incoming call (during RING) to - octet 3a of calling party number IE (Screening info) - See section 4.5.10 of ITU Q.931 - 23 0 Bit coded register: - Bit 0: 0 = Add CPN to RING message off - 1 = Add CPN to RING message on - Bit 1: 0 = Add CPN to FCON message off - 1 = Add CPN to FCON message on - - Last but not least a (at the moment fairly primitive) device to request - the line-status (/dev/isdninfo) is made available. - - Automatic assignment of devices to lines: - - All inactive physical lines are listening to all EAZs for incoming - calls and are NOT assigned to a specific tty or network interface. - When an incoming call is detected, the driver looks first for a network - interface and then for an opened tty which: - - 1. is configured for the same EAZ. - 2. has the same protocol settings for the B-channel. - 3. (only for network interfaces if the security flag is set) - contains the caller number in its access list. - 4. Either the channel is not bound exclusively to another Net-interface, or - it is bound AND the other checks apply to exactly this interface. - (For usage of the bind-features, refer to the isdnctrl-man-page) - - Only when a matching interface or tty is found is the call accepted - and the "connection" between the low-level-layer and the link-level-layer - is established and kept until the end of the connection. - In all other cases no connection is established. Isdn4linux can be - configured to either do NOTHING in this case (which is useful, if - other, external devices with the same EAZ/MSN are connected to the bus) - or to reject the call actively. (isdnctrl busreject ...) - - For an outgoing call, the inactive physical lines are searched. - The call is placed on the first physical line, which supports the - requested protocols for the B-channel. If a net-interface, however - is pre-bound to a channel, this channel is used directly. - - This makes it possible to configure several network interfaces and ttys - for one EAZ, if the network interfaces are set to secure operation. - If an incoming call matches one network interface, it gets connected to it. - If another incoming call for the same EAZ arrives, which does not match - a network interface, the first tty gets a "RING" and so on. - -2 System prerequisites: - - ATTENTION! - - Always use the latest module utilities. The current version is - named in Documentation/Changes. Some old versions of insmod - are not capable of setting the driver-Ids correctly. - -3. Lowlevel-driver configuration. - - Configuration depends on how the drivers are built. See the - README. for information on driver-specific setup. - -4. Device-inodes - - The major and minor numbers and their names are described in - Documentation/devices.txt. The major numbers are: - - 43 for the ISDN-tty's. - 44 for the ISDN-callout-tty's. - 45 for control/info/debug devices. - -5. Application - - a) For some card-types, firmware has to be loaded into the cards, before - proceeding with device-independent setup. See README. - for how to do that. - - b) If you only intend to use ttys, you are nearly ready now. - - c) If you want to have really permanent "Modem"-settings on disk, you - can start the daemon iprofd. Give it a path to a file at the command- - line. It will store the profile-settings in this file every time - an AT&W0 is performed on any ISDN-tty. If the file already exists, - all profiles are initialized from this file. If you want to unload - any of the modules, kill iprofd first. - - d) For networking, continue: Create an interface: - isdnctrl addif isdn0 - - e) Set the EAZ (or MSN for Euro-ISDN): - isdnctrl eaz isdn0 2 - - (For 1TR6 a single digit is allowed, for Euro-ISDN the number is your - real MSN e.g.: Phone-Number) - - f) Set the number for outgoing calls on the interface: - isdnctrl addphone isdn0 out 1234567 - ... (this can be executed more than once, all assigned numbers are - tried in order) - and the number(s) for incoming calls: - isdnctrl addphone isdn0 in 1234567 - - g) Set the timeout for hang-up: - isdnctrl huptimeout isdn0 - - h) additionally you may activate charge-hang-up (= Hang up before - next charge-info, this only works, if your isdn-provider transmits - the charge-info during and after the connection): - isdnctrl chargehup isdn0 on - - i) Set the dial mode of the interface: - isdnctrl dialmode isdn0 auto - "off" means that you (or the system) cannot make any connection - (neither incoming or outgoing connections are possible). Use - this if you want to be sure that no connections will be made. - "auto" means that the interface is in auto-dial mode, and will - attempt to make a connection whenever a network data packet needs - the interface's link. Note that this can cause unexpected dialouts, - and lead to a high phone bill! Some daemons or other pc's that use - this interface can cause this. - Incoming connections are also possible. - "manual" is a dial mode created to prevent the unexpected dialouts. - In this mode, the interface will never make any connections on its - own. You must explicitly initiate a connection with "isdnctrl dial - isdn0". However, after an idle time of no traffic as configured for - the huptimeout value with isdnctrl, the connection _will_ be ended. - If you don't want any automatic hangup, set the huptimeout value to 0. - "manual" is the default. - - j) Setup the interface with ifconfig as usual, and set a route to it. - - k) (optional) If you run X11 and have Tcl/Tk-wish version 4.0, you can use - the script tools/tcltk/isdnmon. You can add actions for line-status - changes. See the comments at the beginning of the script for how to - do that. There are other tty-based tools in the tools-subdirectory - contributed by Michael Knigge (imon), Volker Götz (imontty) and - Andreas Kool (isdnmon). - - l) For initial testing, you can set the verbose-level to 2 (default: 0). - Then all incoming calls are logged, even if they are not addressed - to one of the configured net-interfaces: - isdnctrl verbose 2 - - Now you are ready! A ping to the set address should now result in an - automatic dial-out (look at syslog kernel-messages). - The phone numbers and EAZs can be assigned at any time with isdnctrl. - You can add as many interfaces as you like with addif following the - directions above. Of course, there may be some limitations. But we have - tested as many as 20 interfaces without any problem. However, if you - don't give an interface name to addif, the kernel will assign a name - which starts with "eth". The number of "eth"-interfaces is limited by - the kernel. - -5. Additional options for isdnctrl: - - "isdnctrl secure on" - Only incoming calls, for which the caller-id is listed in the access - list of the interface are accepted. You can add caller-id's With the - command "isdnctrl addphone in " - Euro-ISDN does not transmit the leading '0' of the caller-id for an - incoming call, therefore you should configure it accordingly. - If the real number for the dialout e.g. is "09311234567" the number - to configure here is "9311234567". The pattern-match function - works similar to the shell mechanism. - - ? one arbitrary digit - * zero or arbitrary many digits - [123] one of the digits in the list - [1-5] one digit between '1' and '5' - a '^' as the first character in a list inverts the list - - - "isdnctrl secure off" - Switch off secure operation (default). - - "isdnctrl ihup [on|off]" - Switch the hang-up-timer for incoming calls on or off. - - "isdnctrl eaz " - Returns the EAZ of an interface. - - "isdnctrl delphone in|out " - Deletes a number from one of the access-lists of the interface. - - "isdnctrl delif " - Removes the interface (and possible slaves) from the kernel. - (You have to unregister it with "ifconfig down" before). - - "isdnctrl callback [on|off]" - Switches an interface to callback-mode. In this mode, an incoming call - will be rejected and after this the remote-station will be called. If - you test this feature by using ping, some routers will re-dial very - quickly, so that the callback from isdn4linux may not be recognized. - In this case use ping with the option -i to increase the interval - between echo-packets. - - "isdnctrl cbdelay [seconds]" - Sets the delay (default 5 sec) between an incoming call and start of - dialing when callback is enabled. - - "isdnctrl cbhup [on|off]" - This enables (default) or disables an active hangup (reject) when getting an - incoming call for an interface which is configured for callback. - - "isdnctrl encap " - Selects the type of packet-encapsulation. The encapsulation can be changed - only while an interface is down. - - At the moment the following values are supported: - - rawip (Default) Selects raw-IP-encapsulation. This means, MAC-headers - are stripped off. - ip IP with type-field. Same as IP but the type-field of the MAC-header - is preserved. - x25iface X.25 interface encapsulation (first byte semantics as defined in - ../networking/x25-iface.txt). Use this for running the linux - X.25 network protocol stack (AF_X25 sockets) on top of isdn. - cisco-h A special-mode for communicating with a Cisco, which is configured - to do "hdlc" - ethernet No stripping. Packets are sent with full MAC-header. - The Ethernet-address of the interface is faked, from its - IP-address: fc:fc:i1:i2:i3:i4, where i1-4 are the IP-addr.-values. - syncppp Synchronous PPP - - uihdlc HDLC with UI-frame-header (for use with DOS ISPA, option -h1) - - - NOTE: x25iface encapsulation is currently experimental. Please - read README.x25 for further details - - - Watching packets, using standard-tcpdump will fail for all encapsulations - except ethernet because tcpdump does not know how to handle packets - without MAC-header. A patch for tcpdump is included in the utility-package - mentioned above. - - "isdnctrl l2_prot " - Selects a layer-2-protocol. - (With the ICN-driver and the HiSax-driver, "x75i" and "hdlc" is available. - With other drivers, "x75ui", "x75bui", "x25dte", "x25dce" may be - possible too. See README.x25 for x25 related l2 protocols.) - - isdnctrl l3_prot - The same for layer-3. (At the moment only "trans" is allowed) - - "isdnctrl list " - Shows all parameters of an interface and the charge-info. - Try "all" as the interface name. - - "isdnctrl hangup " - Forces hangup of an interface. - - "isdnctrl bind , [exclusive]" - If you are using more than one ISDN card, it is sometimes necessary to - dial out using a specific card or even preserve a specific channel for - dialout of a specific net-interface. This can be done with the above - command. Replace by whatever you assigned while loading the - module. The is counted from zero. The upper limit - depends on the card used. At the moment no card supports more than - 2 channels, so the upper limit is one. - - "isdnctrl unbind " - unbinds a previously bound interface. - - "isdnctrl busreject on|off" - If switched on, isdn4linux replies a REJECT to incoming calls, it - cannot match to any configured interface. - If switched off, nothing happens in this case. - You normally should NOT enable this feature, if the ISDN adapter is not - the only device connected to the S0-bus. Otherwise it could happen that - isdn4linux rejects an incoming call, which belongs to another device on - the bus. - - "isdnctrl addslave - Creates a slave interface for channel-bundling. Slave interfaces are - not seen by the kernel, but their ISDN-part can be configured with - isdnctrl as usual. (Phone numbers, EAZ/MSN, timeouts etc.) If more - than two channels are to be bundled, feel free to create as many as you - want. InterfaceName must be a real interface, NOT a slave. Slave interfaces - start dialing, if the master interface resp. the previous slave interface - has a load of more than 7000 cps. They hangup if the load goes under 7000 - cps, according to their "huptimeout"-parameter. - - "isdnctrl sdelay secs." - This sets the minimum time an Interface has to be fully loaded, until - it sends a dial-request to its slave. - - "isdnctrl dial " - Forces an interface to start dialing even if no packets are to be - transferred. - - "isdnctrl mapping MSN0,MSN1,MSN2,...MSN9" - This installs a mapping table for EAZ<->MSN-mapping for a single line. - Missing MSN's have to be given as "-" or can be omitted, if at the end - of the commandline. - With this command, it's now possible to have an interface listening to - mixed 1TR6- and Euro-Type lines. In this case, the interface has to be - configured to a 1TR6-type EAZ (one digit). The mapping is also valid - for tty-emulation. Seen from the interface/tty-level the mapping - CAN be used, however it's possible to use single tty's/interfaces with - real MSN's (more digits) also, in which case the mapping will be ignored. - Here is an example: - - You have a 1TR6-type line with base-nr. 1234567 and a Euro-line with - MSN's 987654, 987655 and 987656. The DriverId for the Euro-line is "EURO". - - isdnctrl mapping EURO -,987654,987655,987656,-,987655 - ... - isdnctrl eaz isdn0 1 # listen on 12345671(1tr6) and 987654(euro) - ... - isdnctrl eaz isdn1 4 # listen on 12345674(1tr6) only. - ... - isdnctrl eaz isdn2 987654 # listen on 987654(euro) only. - - Same scheme is used with AT&E... at the tty's. - -6. If you want to write a new low-level-driver, you are welcome. - The interface to the link-level-module is described in the file INTERFACE. - If the interface should be expanded for any reason, don't do it - on your own, send me a mail containing the proposed changes and - some reasoning about them. - If other drivers will not be affected, I will include the changes - in the next release. - For developers only, there is a second mailing-list. Write to me - (fritz@isdn4linux.de), if you want to join that list. - -Have fun! - - -Fritz - diff --git a/Documentation/isdn/README.FAQ b/Documentation/isdn/README.FAQ deleted file mode 100644 index 356f7944..00000000 --- a/Documentation/isdn/README.FAQ +++ /dev/null @@ -1,26 +0,0 @@ - -The FAQ for isdn4linux -====================== - -Please note that there is a big FAQ available in the isdn4k-utils. -You find it in: - isdn4k-utils/FAQ/i4lfaq.sgml - -In case you just want to see the FAQ online, or download the newest version, -you can have a look at my website: -http://www.mhessler.de/i4lfaq/ (view + download) -or: -http://www.isdn4linux.de/faq/ (view) - -As the extension tells, the FAQ is in SGML format, and you can convert it -into text/html/... format by using the sgml2txt/sgml2html/... tools. -Alternatively, you can also do a 'configure; make all' in the FAQ directory. - - -Please have a look at the FAQ before posting anything in the Mailinglist, -or the newsgroup! - - -Matthias Hessler -hessler@isdn4linux.de - diff --git a/Documentation/isdn/README.HiSax b/Documentation/isdn/README.HiSax deleted file mode 100644 index 04167822..00000000 --- a/Documentation/isdn/README.HiSax +++ /dev/null @@ -1,633 +0,0 @@ -HiSax is a Linux hardware-level driver for passive ISDN cards with Siemens -chipset (ISAC_S 2085/2086/2186, HSCX SAB 82525). It is based on the Teles -driver from Jan den Ouden. -It is meant to be used with isdn4linux, an ISDN link-level module for Linux -written by Fritz Elfert. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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. - - -Supported cards ---------------- - -Teles 8.0/16.0/16.3 and compatible ones -Teles 16.3c -Teles S0/PCMCIA -Teles PCI -Teles S0Box -Creatix S0Box -Creatix PnP S0 -Compaq ISDN S0 ISA card -AVM A1 (Fritz, Teledat 150) -AVM Fritz PCMCIA -AVM Fritz PnP -AVM Fritz PCI -ELSA Microlink PCC-16, PCF, PCF-Pro, PCC-8 -ELSA Quickstep 1000 -ELSA Quickstep 1000PCI -ELSA Quickstep 3000 (same settings as QS1000) -ELSA Quickstep 3000PCI -ELSA PCMCIA -ITK ix1-micro Rev.2 -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) -HFC-2BS0 based cards (TeleInt SA1) -Sedlbauer Speed Card (Speed Win, Teledat 100, PCI, Fax+) -Sedlbauer Speed Star/Speed Star2 (PCMCIA) -Sedlbauer ISDN-Controller PC/104 -USR Sportster internal TA (compatible Stollmann tina-pp V3) -ith Kommunikationstechnik GmbH MIC 16 ISA card -Traverse Technologie NETjet PCI S0 card -Dr. Neuhaus Niccy PnP/PCI -Siemens I-Surf 1.0 -Siemens I-Surf 2.0 (with IPAC, try type 12 asuscom) -ACER P10 -HST Saphir -Berkom Telekom A4T -Scitel Quadro -Gazel ISDN cards -HFC-PCI based cards -Winbond W6692 based cards -HFC-S+, HFC-SP/PCMCIA cards - -Note: PCF, PCF-Pro: up to now, only the ISDN part is supported - PCC-8: not tested yet - Teles PCMCIA is EXPERIMENTAL - Teles 16.3c is EXPERIMENTAL - Teles PCI is EXPERIMENTAL - Teles S0Box is EXPERIMENTAL - Eicon.Diehl Diva U interface not tested - HFC-S+, HFC-SP/PCMCIA are experimental - -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 ressources -(io, mem, irq). - - -Configuring the driver ----------------------- - -The HiSax driver can either be built directly into the kernel or as a module. -It can be configured using the command line feature while loading the kernel -with LILO or LOADLIN or, if built as a module, using insmod/modprobe with -parameters. -There is also some config needed before you compile the kernel and/or -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: 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 -------------------------- - -insmod/modprobe hisax.o \ - io=iobase irq=IRQ mem=membase type=card_type \ - protocol=D_channel_protocol id=idstring - -or, if several cards are installed: - -insmod/modprobe hisax.o \ - io=iobase1,iobase2,... irq=IRQ1,IRQ2,... mem=membase1,membase2,... \ - type=card_type1,card_type2,... \ - protocol=D_channel_protocol1,D_channel_protocol2,... \ - id=idstring1%idstring2 ... - -where "iobaseN" represents the I/O base address of the Nth card, "membaseN" -the memory base address of the Nth card, etc. - -The reason for the delimiter "%" being used in the idstrings is that "," -won't work with the current modules package. - -The parameters may be specified in any order. For example, the "io" -parameter may precede the "irq" parameter, or vice versa. If several -cards are installed, the ordering within the comma separated parameter -lists must of course be consistent. - -Only parameters applicable to the card type need to be specified. For -example, the Teles 16.3 card is not memory-mapped, so the "mem" -parameter may be omitted for this card. Sometimes it may be necessary -to specify a dummy parameter, however. This is the case when there is -a card of a different type later in the list that needs a parameter -which the preceding card does not. For instance, if a Teles 16.0 card -is listed after a Teles 16.3 card, a dummy memory base parameter of 0 -must be specified for the 16.3. Instead of a dummy value, the parameter -can also be skipped by simply omitting the value. For example: -mem=,0xd0000. See example 6 below. - -The parameter for the D-Channel protocol may be omitted if you selected the -correct one during kernel config. Valid values are "1" for German 1TR6, -"2" for EDSS1 (Euro ISDN) and "3" for leased lines (no D-Channel). - -The Creatix/Teles PnP cards use io1= and io2= instead of io= for specifying -the I/O addresses of the ISAC and HSCX chips, respectively. - -Card types: - - Type Required parameters (in addition to type and protocol) - - 1 Teles 16.0 irq, mem, io - 2 Teles 8.0 irq, mem - 3 Teles 16.3 (non PnP) irq, io - 4 Creatix/Teles PnP irq, io0 (ISAC), io1 (HSCX) - 5 AVM A1 (Fritz) irq, io - 6 ELSA PCC/PCF cards io or nothing for autodetect (the iobase is - required only if you have more than one ELSA - card in your PC) - 7 ELSA Quickstep 1000 irq, io (from isapnp setup) - 8 Teles 16.3 PCMCIA irq, io - 9 ITK ix1-micro Rev.2 irq, io - 10 ELSA PCMCIA irq, io (set with card manager) - 11 Eicon.Diehl Diva ISA PnP irq, io - 11 Eicon.Diehl Diva PCI no parameter - 12 ASUS COM ISDNLink irq, io (from isapnp setup) - 13 HFC-2BS0 based cards irq, io - 14 Teles 16.3c PnP irq, io - 15 Sedlbauer Speed Card irq, io - 15 Sedlbauer PC/104 irq, io - 15 Sedlbauer Speed PCI no parameter - 16 USR Sportster internal irq, io - 17 MIC card irq, io - 18 ELSA Quickstep 1000PCI no parameter - 19 Compaq ISDN S0 ISA card irq, io0, io1, io (from isapnp setup io=IO2) - 20 NETjet PCI card no parameter - 21 Teles PCI no parameter - 22 Sedlbauer Speed Star (PCMCIA) irq, io (set with card manager) - 24 Dr. Neuhaus Niccy PnP irq, io0, io1 (from isapnp setup) - 24 Dr. Neuhaus Niccy PCI no parameter - 25 Teles S0Box irq, io (of the used lpt port) - 26 AVM A1 PCMCIA (Fritz!) irq, io (set with card manager) - 27 AVM PnP (Fritz!PnP) irq, io (from isapnp setup) - 27 AVM PCI (Fritz!PCI) no parameter - 28 Sedlbauer Speed Fax+ irq, io (from isapnp setup) - 29 Siemens I-Surf 1.0 irq, io, memory (from isapnp setup) - 30 ACER P10 irq, io (from isapnp setup) - 31 HST Saphir irq, io - 32 Telekom A4T none - 33 Scitel Quadro subcontroller (4*S0, subctrl 1...4) - 34 Gazel ISDN cards (ISA) irq,io - 34 Gazel ISDN cards (PCI) none - 35 HFC 2BDS0 PCI none - 36 W6692 based PCI cards none - 37 HFC 2BDS0 S+, SP/PCMCIA irq,io (pcmcia must be set with cardmgr) - - -At the moment IRQ sharing is only possible with PCI cards. Please make sure -that your IRQ is free and enabled for ISA use. - - -Examples for module loading - -1. Teles 16.3, Euro ISDN, I/O base 280 hex, IRQ 10 - modprobe hisax type=3 protocol=2 io=0x280 irq=10 - -2. Teles 16.0, 1TR6 ISDN, I/O base d80 hex, IRQ 5, Memory d0000 hex - modprobe hisax protocol=1 type=1 io=0xd80 mem=0xd0000 irq=5 - -3. Fritzcard, Euro ISDN, I/O base 340 hex, IRQ 10 and ELSA PCF, Euro ISDN - modprobe hisax type=5,6 protocol=2,2 io=0x340 irq=10 id=Fritz%Elsa - -4. Any ELSA PCC/PCF card, Euro ISDN - modprobe hisax type=6 protocol=2 - -5. Teles 16.3 PnP, Euro ISDN, with isapnp configured - isapnp config: (INT 0 (IRQ 10 (MODE +E))) - (IO 0 (BASE 0x0580)) - (IO 1 (BASE 0x0180)) - modprobe hisax type=4 protocol=2 irq=10 io0=0x580 io1=0x180 - -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 - - Please note the dummy 0 memory address for the Teles 16.3, used as a - placeholder as described above, in the last example. - -7. Teles PCMCIA, Euro ISDN, I/O base 180 hex, IRQ 15 (default values) - modprobe hisax type=8 protocol=2 io=0x180 irq=15 - - -b) using LILO/LOADLIN, with the driver compiled directly into the kernel ------------------------------------------------------------------------- - -hisax=typ1,dp1,pa_1,pb_1,pc_1[,typ2,dp2,pa_2 ... \ - typn,dpn,pa_n,pb_n,pc_n][,idstring1[,idstring2,...,idstringn]] - -where - typ1 = type of 1st card (default depends on kernel settings) - dp1 = D-Channel protocol of 1st card. 1=1TR6, 2=EDSS1, 3=leased - pa_1 = 1st parameter (depending on the type of the card) - pb_1 = 2nd parameter ( " " " " " " " ) - pc_1 = 3rd parameter ( " " " " " " " ) - - typ2,dp2,pa_2,pb_2,pc_2 = Parameters of the second card (defaults: none) - typn,dpn,pa_n,pb_n,pc_n = Parameters of the n'th card (up to 16 cards are - supported) - - idstring = Driver ID for accessing the particular card with utility - programs and for identification when using a line monitor - (default: "HiSax") - - Note: the ID string must start with an alphabetical character! - -Card types: - -type - 1 Teles 16.0 pa=irq pb=membase pc=iobase - 2 Teles 8.0 pa=irq pb=membase - 3 Teles 16.3 pa=irq pb=iobase - 4 Creatix/Teles PNP ONLY WORKS AS A MODULE ! - 5 AVM A1 (Fritz) pa=irq pb=iobase - 6 ELSA PCC/PCF cards pa=iobase or nothing for autodetect - 7 ELSA Quickstep 1000 ONLY WORKS AS A MODULE ! - 8 Teles S0 PCMCIA pa=irq pb=iobase - 9 ITK ix1-micro Rev.2 pa=irq pb=iobase - 10 ELSA PCMCIA pa=irq, pb=io (set with card manager) - 11 Eicon.Diehl Diva ISAPnP ONLY WORKS AS A MODULE ! - 11 Eicon.Diehl Diva PCI no parameter - 12 ASUS COM ISDNLink ONLY WORKS AS A MODULE ! - 13 HFC-2BS0 based cards pa=irq pb=io - 14 Teles 16.3c PnP ONLY WORKS AS A MODULE ! - 15 Sedlbauer Speed Card pa=irq pb=io (Speed Win only as module !) - 15 Sedlbauer PC/104 pa=irq pb=io - 15 Sedlbauer Speed PCI no parameter - 16 USR Sportster internal pa=irq pb=io - 17 MIC card pa=irq pb=io - 18 ELSA Quickstep 1000PCI no parameter - 19 Compaq ISDN S0 ISA card ONLY WORKS AS A MODULE ! - 20 NETjet PCI card no parameter - 21 Teles PCI no parameter - 22 Sedlbauer Speed Star (PCMCIA) pa=irq, pb=io (set with card manager) - 24 Dr. Neuhaus Niccy PnP ONLY WORKS AS A MODULE ! - 24 Dr. Neuhaus Niccy PCI no parameter - 25 Teles S0Box pa=irq, pb=io (of the used lpt port) - 26 AVM A1 PCMCIA (Fritz!) pa=irq, pb=io (set with card manager) - 27 AVM PnP (Fritz!PnP) ONLY WORKS AS A MODULE ! - 27 AVM PCI (Fritz!PCI) no parameter - 28 Sedlbauer Speed Fax+ ONLY WORKS AS A MODULE ! - 29 Siemens I-Surf 1.0 ONLY WORKS AS A MODULE ! - 30 ACER P10 ONLY WORKS AS A MODULE ! - 31 HST Saphir pa=irq, pb=io - 32 Telekom A4T no parameter - 33 Scitel Quadro subcontroller (4*S0, subctrl 1...4) - 34 Gazel ISDN cards (ISA) pa=irq, pb=io - 34 Gazel ISDN cards (PCI) no parameter - 35 HFC 2BDS0 PCI no parameter - 36 W6692 based PCI cards none - 37 HFC 2BDS0 S+,SP/PCMCIA pa=irq, pb=io - -Running the driver ------------------- - -When you insmod isdn.o and hisax.o (or with the in-kernel version, during -boot time), a few lines should appear in your syslog. Look for something like: - -Apr 13 21:01:59 kke01 kernel: HiSax: Driver for Siemens chip set ISDN cards -Apr 13 21:01:59 kke01 kernel: HiSax: Version 2.9 -Apr 13 21:01:59 kke01 kernel: HiSax: Revisions 1.14/1.9/1.10/1.25/1.8 -Apr 13 21:01:59 kke01 kernel: HiSax: Total 1 card defined -Apr 13 21:01:59 kke01 kernel: HiSax: Card 1 Protocol EDSS1 Id=HiSax1 (0) -Apr 13 21:01:59 kke01 kernel: HiSax: Elsa driver Rev. 1.13 -... -Apr 13 21:01:59 kke01 kernel: Elsa: PCF-Pro found at 0x360 Rev.:C IRQ 10 -Apr 13 21:01:59 kke01 kernel: Elsa: timer OK; resetting card -Apr 13 21:01:59 kke01 kernel: Elsa: HSCX version A: V2.1 B: V2.1 -Apr 13 21:01:59 kke01 kernel: Elsa: ISAC 2086/2186 V1.1 -... -Apr 13 21:01:59 kke01 kernel: HiSax: DSS1 Rev. 1.14 -Apr 13 21:01:59 kke01 kernel: HiSax: 2 channels added - -This means that the card is ready for use. -Cabling problems or line-downs are not detected, and only some ELSA cards can -detect the S0 power. - -Remember that, according to the new strategy for accessing low-level drivers -from within isdn4linux, you should also define a driver ID while doing -insmod: Simply append hisax_id= to the insmod command line. This -string MUST NOT start with a digit or a small 'x'! - -At this point you can run a 'cat /dev/isdnctrl0' and view debugging messages. - -At the moment, debugging messages are enabled with the hisaxctrl tool: - - hisaxctrl DebugCmd - - default is HiSax, if you didn't specify one. - -DebugCmd is 1 for generic debugging - 11 for layer 1 development debugging - 13 for layer 3 development debugging - -where is the integer sum of the following debugging -options you wish enabled: - -With DebugCmd set to 1: - - 0x0001 Link-level <--> hardware-level communication - 0x0002 Top state machine - 0x0004 D-Channel Frames for isdnlog - 0x0008 D-Channel Q.921 - 0x0010 B-Channel X.75 - 0x0020 D-Channel l2 - 0x0040 B-Channel l2 - 0x0080 D-Channel link state debugging - 0x0100 B-Channel link state debugging - 0x0200 TEI debug - 0x0400 LOCK debug in callc.c - 0x0800 More paranoid debug in callc.c (not for normal use) - 0x1000 D-Channel l1 state debugging - 0x2000 B-Channel l1 state debugging - -With DebugCmd set to 11: - - 0x0001 Warnings (default: on) - 0x0002 IRQ status - 0x0004 ISAC - 0x0008 ISAC FIFO - 0x0010 HSCX - 0x0020 HSCX FIFO (attention: full B-Channel output!) - 0x0040 D-Channel LAPD frame types - 0x0080 IPAC debug - 0x0100 HFC receive debug - 0x0200 ISAC monitor debug - 0x0400 D-Channel frames for isdnlog (set with 1 0x4 too) - 0x0800 D-Channel message verbose - -With DebugCmd set to 13: - - 1 Warnings (default: on) - 2 l3 protocol descriptor errors - 4 l3 state machine - 8 charge info debugging (1TR6) - -For example, 'hisaxctrl HiSax 1 0x3ff' enables full generic debugging. - -Because of some obscure problems with some switch equipment, the delay -between the CONNECT message and sending the first data on the B-channel is now -configurable with - -hisaxctrl 2 - in ms Value between 50 and 800 ms is recommended. - -Downloading Firmware --------------------- -At the moment, the Sedlbauer speed fax+ is the only card, which -needs to download firmware. -The firmware is downloaded with the hisaxctrl tool: - - hisaxctrl 9 - - default is HiSax, if you didn't specify one, - -where is the filename of the firmware file. - -For example, 'hisaxctrl HiSax 9 ISAR.BIN' downloads the firmware for -ISAR based cards (like the Sedlbauer speed fax+). - -Warning -------- -HiSax is a work in progress and may crash your machine. -For certification look at HiSax.cert file. - -Limitations ------------ -At this time, HiSax only works on Euro ISDN lines and German 1TR6 lines. -For leased lines see appendix. - -Bugs ----- -If you find any, please let me know. - - -Thanks ------- -Special thanks to: - - Emil Stephan for the name HiSax which is a mix of HSCX and ISAC. - - Fritz Elfert, Jan den Ouden, Michael Hipp, Michael Wein, - Andreas Kool, Pekka Sarnila, Sim Yskes, Johan Myrre'en, - Klaus-Peter Nischke (ITK AG), Christof Petig, Werner Fehn (ELSA GmbH), - Volker Schmidt - Edgar Toernig and Marcus Niemann for the Sedlbauer driver - Stephan von Krawczynski - Juergen Quade for the Leased Line part - Klaus Lichtenwalder (Klaus.Lichtenwalder@WebForum.DE), for ELSA PCMCIA support - Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff - Ton van Rosmalen for Teles PCI - Petr Novak for Winbond W6692 support - and more people who are hunting bugs. (If I forgot somebody, please - send me a mail). - - Firma ELSA GmbH - Firma Eicon.Diehl GmbH - Firma Dynalink NL - Firma ASUSCOM NETWORK INC. Taiwan - Firma S.u.S.E - Firma ith Kommunikationstechnik GmbH - Firma Traverse Technologie Australia - Firma Medusa GmbH (www.medusa.de). - Firma Quant-X Austria for sponsoring a DEC Alpha board+CPU - Firma Cologne Chip Designs GmbH - - My girl friend and partner in life Ute for her patience with me. - - -Enjoy, - -Karsten Keil -keil@isdn4linux.de - - -Appendix: Teles PCMCIA driver ------------------------------ - -See - http://www.stud.uni-wuppertal.de/~ea0141/pcmcia.html -for instructions. - -Appendix: Linux and ISDN-leased lines -------------------------------------- - -Original from Juergen Quade, new version KKe. - -Attention NEW VERSION, the old leased line syntax won't work !!! - -You can use HiSax to connect your Linux-Box via an ISDN leased line -to e.g. the Internet: - -1. Build a kernel which includes the HiSax driver either as a module - or as part of the kernel. - cd /usr/src/linux - make menuconfig - - make clean; make dep; make zImage; make modules; make modules_install -2. Install the new kernel - cp /usr/src/linux/arch/i386/boot/zImage /etc/kernel/linux.isdn - vi /etc/lilo.conf - - lilo -3. in case the hisax driver is a "fixed" part of the kernel, configure - the driver with lilo: - vi /etc/lilo.conf - - lilo - Your lilo.conf _might_ look like the following: - - # LILO configuration-file - # global section - # teles 16.0 on IRQ=5, MEM=0xd8000, PORT=0xd80 - append="hisax=1,3,5,0xd8000,0xd80,HiSax" - # teles 16.3 (non pnp) on IRQ=15, PORT=0xd80 - # append="hisax=3,3,5,0xd8000,0xd80,HiSax" - boot=/dev/sda - compact # faster, but won't work on all systems. - linear - read-only - prompt - timeout=100 - vga = normal # force sane state - # Linux bootable partition config begins - image = /etc/kernel/linux.isdn - root = /dev/sda1 - label = linux.isdn - # - image = /etc/kernel/linux-2.0.30 - root = /dev/sda1 - label = linux.secure - - In the line starting with "append" you have to adapt the parameters - according to your card (see above in this file) - -3. boot the new linux.isdn kernel -4. start the ISDN subsystem: - a) load - if necessary - the modules (depends, whether you compiled - the ISDN driver as module or not) - According to the type of card you have to specify the necessary - driver parameter (irq, io, mem, type, protocol). - For the leased line the protocol is "3". See the table above for - the parameters, which you have to specify depending on your card. - b) configure i4l - /sbin/isdnctrl addif isdn0 - # EAZ 1 -- B1 channel 2 --B2 channel - /sbin/isdnctrl eaz isdn0 1 - /sbin/isdnctrl secure isdn0 on - /sbin/isdnctrl huptimeout isdn0 0 - /sbin/isdnctrl l2_prot isdn0 hdlc - # Attention you must not set an outgoing number !!! This won't work !!! - # The incomming number is LEASED0 for the first card, LEASED1 for the - # second and so on. - /sbin/isdnctrl addphone isdn0 in LEASED0 - # Here is no need to bind the channel. - c) in case the remote partner is a CISCO: - /sbin/isdnctrl encap isdn0 cisco-h - d) configure the interface - /sbin/ifconfig isdn0 ${LOCAL_IP} pointopoint ${REMOTE_IP} - e) set the routes - /sbin/route add -host ${REMOTE_IP} isdn0 - /sbin/route add default gw ${REMOTE_IP} - f) switch the card into leased mode for each used B-channel - /sbin/hisaxctrl HiSax 5 1 - -Remarks: -a) Use state of the art isdn4k-utils - -Here an example script: -#!/bin/sh -# Start/Stop ISDN lesaed line connection - -I4L_AS_MODULE=yes -I4L_REMOTE_IS_CISCO=no -I4L_MODULE_PARAMS="type=16 io=0x268 irq=7 " -I4L_DEBUG=no -I4L_LEASED_128K=yes -LOCAL_IP=192.168.1.1 -REMOTE_IP=192.168.2.1 - -case "$1" in - start) - echo "Starting ISDN ..." - if [ ${I4L_AS_MODULE} = "yes" ]; then - echo "loading modules..." - /sbin/modprobe hisax ${I4L_MODULE_PARAMS} - fi - # configure interface - /sbin/isdnctrl addif isdn0 - /sbin/isdnctrl secure isdn0 on - if [ ${I4L_DEBUG} = "yes" ]; then - /sbin/isdnctrl verbose 7 - /sbin/hisaxctrl HiSax 1 0xffff - /sbin/hisaxctrl HiSax 11 0xff - cat /dev/isdnctrl >/tmp/lea.log & - fi - if [ ${I4L_REMOTE_IS_CISCO} = "yes" ]; then - /sbin/isdnctrl encap isdn0 cisco-h - fi - /sbin/isdnctrl huptimeout isdn0 0 - # B-CHANNEL 1 - /sbin/isdnctrl eaz isdn0 1 - /sbin/isdnctrl l2_prot isdn0 hdlc - # 1. card - /sbin/isdnctrl addphone isdn0 in LEASED0 - if [ ${I4L_LEASED_128K} = "yes" ]; then - /sbin/isdnctrl addslave isdn0 isdn0s - /sbin/isdnctrl secure isdn0s on - /sbin/isdnctrl huptimeout isdn0s 0 - # B-CHANNEL 2 - /sbin/isdnctrl eaz isdn0s 2 - /sbin/isdnctrl l2_prot isdn0s hdlc - # 1. card - /sbin/isdnctrl addphone isdn0s in LEASED0 - if [ ${I4L_REMOTE_IS_CISCO} = "yes" ]; then - /sbin/isdnctrl encap isdn0s cisco-h - fi - fi - /sbin/isdnctrl dialmode isdn0 manual - # configure tcp/ip - /sbin/ifconfig isdn0 ${LOCAL_IP} pointopoint ${REMOTE_IP} - /sbin/route add -host ${REMOTE_IP} isdn0 - /sbin/route add default gw ${REMOTE_IP} - # switch to leased mode - # B-CHANNEL 1 - /sbin/hisaxctrl HiSax 5 1 - if [ ${I4L_LEASED_128K} = "yes" ]; then - # B-CHANNEL 2 - sleep 10; /* Wait for master */ - /sbin/hisaxctrl HiSax 5 2 - fi - ;; - stop) - /sbin/ifconfig isdn0 down - /sbin/isdnctrl delif isdn0 - if [ ${I4L_DEBUG} = "yes" ]; then - killall cat - fi - if [ ${I4L_AS_MODULE} = "yes" ]; then - /sbin/rmmod hisax - /sbin/rmmod isdn - /sbin/rmmod ppp - /sbin/rmmod slhc - fi - ;; - *) - echo "Usage: $0 {start|stop}" - exit 1 -esac -exit 0 diff --git a/Documentation/isdn/README.act2000 b/Documentation/isdn/README.act2000 deleted file mode 100644 index e5618f2b..00000000 --- a/Documentation/isdn/README.act2000 +++ /dev/null @@ -1,104 +0,0 @@ -$Id$ - -This document describes the ACT2000 driver for the -IBM Active 2000 ISDN card. - -There are 3 Types of this card available. A ISA-, MCA-, and PCMCIA-Bus -Version. Currently, only the ISA-Bus version of the card is supported. -However MCA and PCMCIA will follow soon. - -The ISA-Bus Version uses 8 IO-ports. The base port adress has to be set -manually using the DIP switches. - -Setting up the DIP switches for the IBM Active 2000 ISDN card: - - Note: S5 and S6 always set off! - - S1 S2 S3 S4 Base-port - on on on on 0x0200 (Factory default) - off on on on 0x0240 - on off on on 0x0280 - off off on on 0x02c0 - on on off on 0x0300 - off on off on 0x0340 - on off off on 0x0380 - on on on off 0xcfe0 - off on on off 0xcfa0 - on off on off 0xcf60 - off off on off 0xcf20 - on on off off 0xcee0 - off on off off 0xcea0 - on off off off 0xce60 - off off off off Card disabled - -IRQ is configured by software. Possible values are: - - 3, 5, 7, 10, 11, 12, 15 and none (polled mode) - - -The ACT2000 driver may either be built into the kernel or as a module. -Initialization depends on how the driver is built: - -Driver built into the kernel: - - The ACT2000 driver can be configured using the commandline-feature while - loading the kernel with LILO or LOADLIN. It accepts the following syntax: - - act2000=b,p,i[,idstring] - - where - - b = Bus-Type (1=ISA, 2=MCA, 3=PCMCIA) - p = portbase (-1 means autoprobe) - i = Interrupt (-1 means use next free IRQ, 0 means polled mode) - - The idstring is an arbitrary string used for referencing the card - by the actctrl tool later. - - Defaults used, when no parameters given at all: - - 1,-1,-1,"" - - which means: Autoprobe for an ISA card, use next free IRQ, let the - ISDN linklevel fill the IdString (usually "line0" for the first card). - - If you like to use more than one card, you can use the program - "actctrl" from the utility-package to configure additional cards. - - Using the "actctrl"-utility, portbase and irq can also be changed - during runtime. The D-channel protocol is configured by the "dproto" - option of the "actctrl"-utility after loading the firmware into the - card's memory using the "actctrl"-utility. - -Driver built as module: - - The module act2000.o can be configured during modprobe (insmod) by - appending its parameters to the modprobe resp. insmod commandline. - The following syntax is accepted: - - act_bus=b act_port=p act_irq=i act_id=idstring - - where b, p, i and idstring have the same meanings as the parameters - described for the builtin version above. - - Using the "actctrl"-utility, the same features apply to the modularized - version as to the kernel-builtin one. (i.e. loading of firmware and - configuring the D-channel protocol) - -Loading the firmware into the card: - - The firmware is supplied together with the isdn4k-utils package. It - can be found in the subdirectory act2000/firmware/ - - Assuming you have installed the utility-package correctly, the firmware - will be downloaded into the card using the following command: - - actctrl -d idstring load /etc/isdn/bip11.btl - - where idstring is the Name of the card, given during insmod-time or - (for kernel-builtin driver) on the kernel commandline. If only one - ISDN card is used, the -d isdstrin may be omitted. - - For further documentation (adding more IBM Active 2000 cards), refer to - the manpage actctrl.8 which is included in the isdn4k-utils package. - diff --git a/Documentation/isdn/README.audio b/Documentation/isdn/README.audio deleted file mode 100644 index 32c19cd2..00000000 --- a/Documentation/isdn/README.audio +++ /dev/null @@ -1,138 +0,0 @@ -$Id$ - -ISDN subsystem for Linux. - Description of audio mode. - -When enabled during kernel configuration, the tty emulator of the ISDN -subsystem is capable of a reduced set of commands to support audio. -This document describes the commands supported and the format of -audio data. - -Commands for enabling/disabling audio mode: - - AT+FCLASS=8 Enable audio mode. - This affects the following registers: - S18: Bits 0 and 2 are set. - S16: Set to 48 and any further change to - larger values is blocked. - AT+FCLASS=0 Disable audio mode. - Register 18 is set to 4. - AT+FCLASS=? Show possible modes. - AT+FCLASS? Report current mode (0 or 8). - -Commands supported in audio mode: - -All audio mode commands have one of the following forms: - - AT+Vxx? Show current setting. - AT+Vxx=? Show possible settings. - AT+Vxx=v Set simple parameter. - AT+Vxx=v,v ... Set complex parameter. - -where xx is a two-character code and v are alphanumerical parameters. -The following commands are supported: - - AT+VNH=x Auto hangup setting. NO EFFECT, supported - for compatibility only. - AT+VNH? Always reporting "1" - AT+VNH=? Always reporting "1" - - AT+VIP Reset all audio parameters. - - AT+VLS=x Line select. x is one of the following: - 0 = No device. - 2 = Phone line. - AT+VLS=? Always reporting "0,2" - AT+VLS? Show current line. - - AT+VRX Start recording. Emulator responds with - CONNECT and starts sending audio data to - the application. See below for data format - - AT+VSD=x,y Set silence-detection parameters. - Possible parameters: - x = 0 ... 31 sensitivity threshold level. - (default 0 , deactivated) - y = 0 ... 255 range of interval in units - of 0.1 second. (default 70) - AT+VSD=? Report possible parameters. - AT+VSD? Show current parameters. - - AT+VDD=x,y Set DTMF-detection parameters. - Only possible if online and during this connection. - Possible parameters: - x = 0 ... 15 sensitivity threshold level. - (default 0 , I4L soft-decode) - (1-15 soft-decode off, hardware on) - y = 0 ... 255 tone duration in units of 5ms. - Not for I4L soft decode (default 8, 40ms) - AT+VDD=? Report possible parameters. - AT+VDD? Show current parameters. - - AT+VSM=x Select audio data format. - Possible parameters: - 2 = ADPCM-2 - 3 = ADPCM-3 - 4 = ADPCM-4 - 5 = aLAW - 6 = uLAW - AT+VSM=? Show possible audio formats. - - AT+VTX Start audio playback. Emulator responds - with CONNECT and starts sending audio data - received from the application via phone line. -General behavior and description of data formats/protocol. - when a connection is made: - - On incoming calls, if the application responds to a RING - with ATA, depending on the calling service, the emulator - responds with either CONNECT (data call) or VCON (voice call). - - On outgoing voice calls, the emulator responds with VCON - upon connection setup. - - Audio recording. - - When receiving audio data, a kind of bisync protocol is used. - Upon AT+VRX command, the emulator responds with CONNECT, and - starts sending audio data to the application. There are several - escape sequences defined, all using DLE (0x10) as Escape char: - - End of audio data. (i.e. caused by a - hangup of the remote side) Emulator stops - recording, responding with VCON. - Abort recording, (send by appl.) Emulator - stops recording, sends DLE,ETX. - Escape sequence for DLE in data stream. - 0 Touchtone "0" received. - ... - 9 Touchtone "9" received. - # Touchtone "#" received. - * Touchtone "*" received. - A Touchtone "A" received. - B Touchtone "B" received. - C Touchtone "C" received. - D Touchtone "D" received. - - q quiet. Silence detected after non-silence. - s silence. Silence detected from the - start of recording. - - Currently unsupported DLE sequences: - - c FAX calling tone received. - b busy tone received. - - Audio playback. - - When sending audio data, upon AT+VTX command, emulator responds with - CONNECT, and starts transferring data from application to the phone line. - The same DLE sequences apply to this mode. - - Full-Duplex-Audio: - - When _both_ commands for recording and playback are given in _one_ - AT-command-line (i.e.: "AT+VTX+VRX"), full-duplex-mode is selected. - In this mode, the only way to stop recording is sending - and the only way to stop playback is to send . - diff --git a/Documentation/isdn/README.avmb1 b/Documentation/isdn/README.avmb1 deleted file mode 100644 index 6fa9406d..00000000 --- a/Documentation/isdn/README.avmb1 +++ /dev/null @@ -1,187 +0,0 @@ -Driver for active AVM Controller. - -The driver provides a kernel capi2.0 Interface (kernelcapi) and -on top of this a User-Level-CAPI2.0-interface (capi) -and a driver to connect isdn4linux with CAPI2.0 (capidrv). -The lowlevel interface can be used to implement a CAPI2.0 -also for passive cards since July 1999. - -The author can be reached at calle@calle.in-berlin.de. -The command avmcapictrl is part of the isdn4k-utils. -t4-files can be found at ftp://ftp.avm.de/cardware/b1/linux/firmware - -Currently supported cards: - B1 ISA (all versions) - B1 PCI - T1/T1B (HEMA card) - M1 - M2 - B1 PCMCIA - -Installing ----------- - -You need at least /dev/capi20 to load the firmware. - -mknod /dev/capi20 c 68 0 -mknod /dev/capi20.00 c 68 1 -mknod /dev/capi20.01 c 68 2 -. -. -. -mknod /dev/capi20.19 c 68 20 - -Running -------- - -To use the card you need the t4-files to download the firmware. -AVM GmbH provides several t4-files for the different D-channel -protocols (b1.t4 for Euro-ISDN). Install these file in /lib/isdn. - -if you configure as modules load the modules this way: - -insmod /lib/modules/current/misc/capiutil.o -insmod /lib/modules/current/misc/b1.o -insmod /lib/modules/current/misc/kernelcapi.o -insmod /lib/modules/current/misc/capidrv.o -insmod /lib/modules/current/misc/capi.o - -if you have an B1-PCI card load the module b1pci.o -insmod /lib/modules/current/misc/b1pci.o -and load the firmware with -avmcapictrl load /lib/isdn/b1.t4 1 - -if you have an B1-ISA card load the module b1isa.o -and add the card by calling -avmcapictrl add 0x150 15 -and load the firmware by calling -avmcapictrl load /lib/isdn/b1.t4 1 - -if you have an T1-ISA card load the module t1isa.o -and add the card by calling -avmcapictrl add 0x450 15 T1 0 -and load the firmware by calling -avmcapictrl load /lib/isdn/t1.t4 1 - -if you have an PCMCIA card (B1/M1/M2) load the module b1pcmcia.o -before you insert the card. - -Leased Lines with B1 --------------------- -Init card and load firmware. -For an D64S use "FV: 1" as phone number -For an D64S2 use "FV: 1" and "FV: 2" for multilink -or "FV: 1,2" to use CAPI channel bundling. - -/proc-Interface ------------------ - -/proc/capi: - dr-xr-xr-x 2 root root 0 Jul 1 14:03 . - dr-xr-xr-x 82 root root 0 Jun 30 19:08 .. - -r--r--r-- 1 root root 0 Jul 1 14:03 applications - -r--r--r-- 1 root root 0 Jul 1 14:03 applstats - -r--r--r-- 1 root root 0 Jul 1 14:03 capi20 - -r--r--r-- 1 root root 0 Jul 1 14:03 capidrv - -r--r--r-- 1 root root 0 Jul 1 14:03 controller - -r--r--r-- 1 root root 0 Jul 1 14:03 contrstats - -r--r--r-- 1 root root 0 Jul 1 14:03 driver - -r--r--r-- 1 root root 0 Jul 1 14:03 ncci - -r--r--r-- 1 root root 0 Jul 1 14:03 users - -/proc/capi/applications: - applid level3cnt datablkcnt datablklen ncci-cnt recvqueuelen - level3cnt: capi_register parameter - datablkcnt: capi_register parameter - ncci-cnt: current number of nccis (connections) - recvqueuelen: number of messages on receive queue - for example: -1 -2 16 2048 1 0 -2 2 7 2048 1 0 - -/proc/capi/applstats: - applid recvctlmsg nrecvdatamsg nsentctlmsg nsentdatamsg - recvctlmsg: capi messages received without DATA_B3_IND - recvdatamsg: capi DATA_B3_IND received - sentctlmsg: capi messages sent without DATA_B3_REQ - sentdatamsg: capi DATA_B3_REQ sent - for example: -1 2057 1699 1721 1699 - -/proc/capi/capi20: statistics of capi.o (/dev/capi20) - minor nopen nrecvdropmsg nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - minor: minor device number of capi device - nopen: number of calls to devices open - nrecvdropmsg: capi messages dropped (messages in recvqueue in close) - nrecvctlmsg: capi messages received without DATA_B3_IND - nrecvdatamsg: capi DATA_B3_IND received - nsentctlmsg: capi messages sent without DATA_B3_REQ - nsentdatamsg: capi DATA_B3_REQ sent - - for example: -1 2 18 0 16 2 - -/proc/capi/capidrv: statistics of capidrv.o (capi messages) - nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: capi messages received without DATA_B3_IND - nrecvdatamsg: capi DATA_B3_IND received - nsentctlmsg: capi messages sent without DATA_B3_REQ - nsentdatamsg: capi DATA_B3_REQ sent - for example: -2780 2226 2256 2226 - -/proc/capi/controller: - controller drivername state cardname controllerinfo - for example: -1 b1pci running b1pci-e000 B1 3.07-01 0xe000 19 -2 t1isa running t1isa-450 B1 3.07-01 0x450 11 0 -3 b1pcmcia running m2-150 B1 3.07-01 0x150 5 - -/proc/capi/contrstats: - controller nrecvctlmsg nrecvdatamsg sentctlmsg sentdatamsg - nrecvctlmsg: capi messages received without DATA_B3_IND - nrecvdatamsg: capi DATA_B3_IND received - nsentctlmsg: capi messages sent without DATA_B3_REQ - nsentdatamsg: capi DATA_B3_REQ sent - for example: -1 2845 2272 2310 2274 -2 2 0 2 0 -3 2 0 2 0 - -/proc/capi/driver: - drivername ncontroller - for example: -b1pci 1 -t1isa 1 -b1pcmcia 1 -b1isa 0 - -/proc/capi/ncci: - apllid ncci winsize sendwindow - for example: -1 0x10101 8 0 - -/proc/capi/users: kernelmodules that use the kernelcapi. - name - for example: -capidrv -capi20 - -Questions ---------- -Check out the FAQ (ftp.isdn4linux.de) or subscribe to the -linux-avmb1@calle.in-berlin.de mailing list by sending -a mail to majordomo@calle.in-berlin.de with -subscribe linux-avmb1 -in the body. - -German documentaion and several scripts can be found at -ftp://ftp.avm.de/cardware/b1/linux/ - -Bugs ----- -If you find any please let me know. - -Enjoy, - -Carsten Paeth (calle@calle.in-berlin.de) diff --git a/Documentation/isdn/README.concap b/Documentation/isdn/README.concap deleted file mode 100644 index a934fe34..00000000 --- a/Documentation/isdn/README.concap +++ /dev/null @@ -1,259 +0,0 @@ -Description of the "concap" encapsulation protocol interface -============================================================ - -The "concap" interface is intended to be used by network device -drivers that need to process an encapsulation protocol. -It is assumed that the protocol interacts with a linux network device by -- data transmission -- connection control (establish, release) -Thus, the mnemonic: "CONnection CONtrolling eNCAPsulation Protocol". - -This is currently only used inside the isdn subsystem. But it might -also be useful to other kinds of network devices. Thus, if you want -to suggest changes that improve usability or performance of the -interface, please let me know. I'm willing to include them in future -releases (even if I needed to adapt the current isdn code to the -changed interface). - - -Why is this useful? -=================== - -The encapsulation protocol used on top of WAN connections or permanent -point-to-point links are frequently chosen upon bilateral agreement. -Thus, a device driver for a certain type of hardware must support -several different encapsulation protocols at once. - -The isdn device driver did already support several different -encapsulation protocols. The encapsulation protocol is configured by a -user space utility (isdnctrl). The isdn network interface code then -uses several case statements which select appropriate actions -depending on the currently configured encapsulation protocol. - -In contrast, LAN network interfaces always used a single encapsulation -protocol which is unique to the hardware type of the interface. The LAN -encapsulation is usually done by just sticking a header on the data. Thus, -traditional linux network device drivers used to process the -encapsulation protocol directly (usually by just providing a hard_header() -method in the device structure) using some hardware type specific support -functions. This is simple, direct and efficient. But it doesn't fit all -the requirements for complex WAN encapsulations. - - - The configurability of the encapsulation protocol to be used - makes isdn network interfaces more flexible, but also much more - complex than traditional lan network interfaces. - - -Many Encapsulation protocols used on top of WAN connections will not just -stick a header on the data. They also might need to set up or release -the WAN connection. They also might want to send other data for their -private purpose over the wire, e.g. ppp does a lot of link level -negotiation before the first piece of user data can be transmitted. -Such encapsulation protocols for WAN devices are typically more complex -than encapsulation protocols for lan devices. Thus, network interface -code for typical WAN devices also tends to be more complex. - - -In order to support Linux' x25 PLP implementation on top of -isdn network interfaces I could have introduced yet another branch to -the various case statements inside drivers/isdn/isdn_net.c. -This eventually made isdn_net.c even more complex. In addition, it made -isdn_net.c harder to maintain. Thus, by identifying an abstract -interface between the network interface code and the encapsulation -protocol, complexity could be reduced and maintainability could be -increased. - - -Likewise, a similar encapsulation protocol will frequently be needed by -several different interfaces of even different hardware type, e.g. the -synchronous ppp implementation used by the isdn driver and the -asyncronous ppp implementation used by the ppp driver have a lot of -similar code in them. By cleanly separating the encapsulation protocol -from the hardware specific interface stuff such code could be shared -better in future. - - -When operating over dial-up-connections (e.g. telephone lines via modem, -non-permanent virtual circuits of wide area networks, ISDN) many -encapsulation protocols will need to control the connection. Therefore, -some basic connection control primitives are supported. The type and -semantics of the connection (i.e the ISO layer where connection service -is provided) is outside our scope and might be different depending on -the encapsulation protocol used, e.g. for a ppp module using our service -on top of a modem connection a connect_request will result in dialing -a (somewhere else configured) remote phone number. For an X25-interface -module (LAPB semantics, as defined in Documentation/networking/x25-iface.txt) -a connect_request will ask for establishing a reliable lapb -datalink connection. - - -The encapsulation protocol currently provides the following -service primitives to the network device. - -- create a new encapsulation protocol instance -- delete encapsulation protocol instance and free all its resources -- initialize (open) the encapsulation protocol instance for use. -- deactivate (close) an encapsulation protocol instance. -- process (xmit) data handed down by upper protocol layer -- receive data from lower (hardware) layer -- process connect indication from lower (hardware) layer -- process disconnect indication from lower (hardware) layer - - -The network interface driver accesses those primitives via callbacks -provided by the encapsulation protocol instance within a -struct concap_proto_ops. - -struct concap_proto_ops{ - - /* create a new encapsulation protocol instance of same type */ - struct concap_proto * (*proto_new) (void); - - /* delete encapsulation protocol instance and free all its resources. - cprot may no loger be referenced after calling this */ - void (*proto_del)(struct concap_proto *cprot); - - /* initialize the protocol's data. To be called at interface startup - or when the device driver resets the interface. All services of the - encapsulation protocol may be used after this*/ - int (*restart)(struct concap_proto *cprot, - struct net_device *ndev, - struct concap_device_ops *dops); - - /* deactivate an encapsulation protocol instance. The encapsulation - protocol may not call any *dops methods after this. */ - int (*close)(struct concap_proto *cprot); - - /* process a frame handed down to us by upper layer */ - int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb); - - /* to be called for each data entity received from lower layer*/ - int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb); - - /* to be called when a connection was set up/down. - Protocols that don't process these primitives might fill in - dummy methods here */ - int (*connect_ind)(struct concap_proto *cprot); - int (*disconn_ind)(struct concap_proto *cprot); -}; - - -The data structures are defined in the header file include/linux/concap.h. - - -A Network interface using encapsulation protocols must also provide -some service primitives to the encapsulation protocol: - -- request data being submitted by lower layer (device hardware) -- request a connection being set up by lower layer -- request a connection being released by lower layer - -The encapsulation protocol accesses those primitives via callbacks -provided by the network interface within a struct concap_device_ops. - -struct concap_device_ops{ - - /* to request data be submitted by device */ - int (*data_req)(struct concap_proto *, struct sk_buff *); - - /* Control methods must be set to NULL by devices which do not - support connection control. */ - /* to request a connection be set up */ - int (*connect_req)(struct concap_proto *); - - /* to request a connection be released */ - int (*disconn_req)(struct concap_proto *); -}; - -The network interface does not explicitly provide a receive service -because the encapsulation protocol directly calls netif_rx(). - - - - -An encapsulation protocol itself is actually the -struct concap_proto{ - struct net_device *net_dev; /* net device using our service */ - struct concap_device_ops *dops; /* callbacks provided by device */ - struct concap_proto_ops *pops; /* callbacks provided by us */ - int flags; - void *proto_data; /* protocol specific private data, to - be accessed via *pops methods only*/ - /* - : - whatever - : - */ -}; - -Most of this is filled in when the device requests the protocol to -be reset (opend). The network interface must provide the net_dev and -dops pointers. Other concap_proto members should be considered private -data that are only accessed by the pops callback functions. Likewise, -a concap proto should access the network device's private data -only by means of the callbacks referred to by the dops pointer. - - -A possible extended device structure which uses the connection controlling -encapsulation services could look like this: - -struct concap_device{ - struct net_device net_dev; - struct my_priv /* device->local stuff */ - /* the my_priv struct might contain a - struct concap_device_ops *dops; - to provide the device specific callbacks - */ - struct concap_proto *cprot; /* callbacks provided by protocol */ -}; - - - -Misc Thoughts -============= - -The concept of the concap proto might help to reuse protocol code and -reduce the complexity of certain network interface implementations. -The trade off is that it introduces yet another procedure call layer -when processing the protocol. This has of course some impact on -performance. However, typically the concap interface will be used by -devices attached to slow lines (like telephone, isdn, leased synchronous -lines). For such slow lines, the overhead is probably negligible. -This might no longer hold for certain high speed WAN links (like -ATM). - - -If general linux network interfaces explicitly supported concap -protocols (e.g. by a member struct concap_proto* in struct net_device) -then the interface of the service function could be changed -by passing a pointer of type (struct net_device*) instead of -type (struct concap_proto*). Doing so would make many of the service -functions compatible to network device support functions. - -e.g. instead of the concap protocol's service function - - int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb); - -we could have - - int (*encap_and_xmit)(struct net_device *ndev, struct sk_buff *skb); - -As this is compatible to the dev->hard_start_xmit() method, the device -driver could directly register the concap protocol's encap_and_xmit() -function as its hard_start_xmit() method. This would eliminate one -procedure call layer. - - -The device's data request function could also be defined as - - int (*data_req)(struct net_device *ndev, struct sk_buff *skb); - -This might even allow for some protocol stacking. And the network -interface might even register the same data_req() function directly -as its hard_start_xmit() method when a zero layer encapsulation -protocol is configured. Thus, eliminating the performance penalty -of the concap interface when a trivial concap protocol is used. -Nevertheless, the device remains able to support encapsulation -protocol configuration. - diff --git a/Documentation/isdn/README.diversion b/Documentation/isdn/README.diversion deleted file mode 100644 index 8e1d7a01..00000000 --- a/Documentation/isdn/README.diversion +++ /dev/null @@ -1,127 +0,0 @@ -The isdn diversion services are a supporting module working together with -the isdn4linux and the HiSax module for passive cards. -Active cards, TAs and cards using a own or other driver than the HiSax -module need to be adapted to the HL<->LL interface described in a separate -document. The diversion services may be used with all cards supported by -the HiSax driver. -The diversion kernel interface and controlling tool divertctrl were written -by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) under the -GNU Public License. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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. - -Table of contents -================= - -1. Features of the i4l diversion services - (Or what can the i4l diversion services do for me) - -2. Required hard- and software - -3. Compiling, installing and loading/unloading the module - Tracing calling and diversion information - -4. Tracing calling and diversion information - -5. Format of the divert device ASCII output - - -1. Features of the i4l diversion services - (Or what can the i4l diversion services do for me) - - The i4l diversion services offers call forwarding and logging normally - only supported by isdn phones. Incoming calls may be diverted - unconditionally (CFU), when not reachable (CFNR) or on busy condition - (CFB). - The diversions may be invoked statically in the providers exchange - as normally done by isdn phones. In this case all incoming calls - with a special (or all) service identifiers are forwarded if the - forwarding reason is met. Activated static services may also be - interrogated (queried). - The i4l diversion services additionally offers a dynamic version of - call forwarding which is not preprogrammed inside the providers exchange - but dynamically activated by i4l. - In this case all incoming calls are checked by rules that may be - compared to the mechanism of ipfwadm or ipchains. If a given rule matches - the checking process is finished and the rule matching will be applied - to the call. - The rules include primary and secondary service indentifiers, called - number and subaddress, callers number and subaddress and whether the rule - matches to all filtered calls or only those when all B-channel resources - are exhausted. - Actions that may be invoked by a rule are ignore, proceed, reject, - direct divert or delayed divert of a call. - All incoming calls matching a rule except the ignore rule a reported and - logged as ASCII via the proc filesystem (/proc/net/isdn/divert). If proceed - is selected the call will be held in a proceeding state (without ringing) - for a certain amount of time to let an external program or client decide - how to handle the call. - - -2. Required hard- and software - - For using the i4l diversion services the isdn line must be of a EURO/DSS1 - type. Additionally the i4l services only work together with the HiSax - driver for passive isdn cards. All HiSax supported cards may be used for - the diversion purposes. - The static diversion services require the provider having static services - CFU, CFNR, CFB activated on an MSN-line. The static services may not be - used on a point-to-point connection. Further the static services are only - available in some countries (for example germany). Countries requiring the - keypad protocol for activating static diversions (like the netherlands) are - not supported but may use the tty devices for this purpose. - The dynamic diversion servives may be used in all countries if the provider - enables the feature CF (call forwarding). This should work on both MSN- and - point-to-point lines. - To add and delete rules the additional divertctrl program is needed. This - program is part of the isdn4kutils package. - -3. Compiling, installing and loading/unloading the module - Tracing calling and diversion information - - - To compile the i4l code with diversion support you need to say yes to the - DSS1 diversion services when selecting the i4l options in the kernel - config (menuconfig or config). - After having properly activated a make modules and make modules_install all - required modules will be correctly installed in the needed modules dirs. - As the diversion services are currently not included in the scripts of most - standard distributions you will have to add a "insmod dss1_divert" after - having loaded the global isdn module. - The module can be loaded without any command line parameters. - If the module is actually loaded and active may be checked with a - "cat /proc/modules" or "ls /proc/net/isdn/divert". The divert file is - dynamically created by the diversion module and removed when the module is - unloaded. - - -4. Tracing calling and diversion information - - You also may put a "cat /proc/net/isdn/divert" in the background with the - output redirected to a file. Then all actions of the module are logged. - The divert file in the proc system may be opened more than once, so in - conjunction with inetd and a small remote client on other machines inside - your network incoming calls and reactions by the module may be shown on - every listening machine. - If a call is reported as proceeding an external program or client may - specify during a certain amount of time (normally 4 to 10 seconds) what - to do with that call. - To unload the module all open files to the device in the proc system must - be closed. Otherwise the module (and isdn.o) may not be unloaded. - -5. Format of the divert device ASCII output - - To be done later - diff --git a/Documentation/isdn/README.eicon b/Documentation/isdn/README.eicon deleted file mode 100644 index 5fdb2c8f..00000000 --- a/Documentation/isdn/README.eicon +++ /dev/null @@ -1,115 +0,0 @@ -$Id$ - -(c) 1999,2000 Armin Schindler (mac@melware.de) -(c) 1999,2000 Cytronics & Melware (info@melware.de) - -This document describes the eicon driver for the -Eicon active ISDN cards. - -It is meant to be used with isdn4linux, an ISDN link-level module for Linux. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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. - - - -Supported Cards -=============== - -Old ISA type ------------- -- S-Card ISA -- SX-Card ISA -- SXn-Card ISA -- SCOM-Card ISA -- Quadro-Card ISA -- S2M-Card ISA - -DIVA Server family ------------------- -- DIVA Server BRI/PCI 2M -- DIVA Server PRI/PCI 2M (9M 23M 30M) - supported functions of onboard DSPs: - - analog modem - - fax group 2/3 (Fax Class 2 commands) - - DTMF detection - - -ISDN D-Channel Protocols ------------------------- - -- ETSI (Euro-DSS1) -- 1TR6 (German ISDN) *not testet* -- other protocols exist for the range of DIVA Server cards, - but they are not fully testet yet. - - -You can load the module simply by using the insmod or modprobe function : - - insmod eicon [id=driverid] [membase=] [irq=] - - -The module will automatically probe the PCI-cards. If the id-option -is omitted, the driver will assume 'eicon0' for the first pci card and -increases the digit with each further card. With a given driver-id -the module appends a number starting with '0'. - -For ISA-cards you have to specify membase, irq and id. If id or -membase is missing/invalid, the driver will not be loaded except -PCI-cards were found. Additional ISA-cards and irq/membase changes -can be done with the eiconctrl utility. - -After loading the module, you have to download the protocol and -dsp-code by using the eiconctrl utility of isdn4k-utils. - - -Example for loading and starting a BRI card with E-DSS1 Protocol. - - eiconctrl [-d DriverId] load etsi - -Example for a BRI card with E-DSS1 Protocol with PtP configuration. - - eiconctrl [-d DriverId] load etsi -n -t0 -s1 - - -Example for loading and starting a PRI card with E-DSS1 Protocol. - - eiconctrl [-d DriverId] load etsi -s2 -n - - -Details about using the eiconctrl utility are in 'man eiconctrl' -or will be printed by starting eiconctrl without any parameters. - -ISDNLOG: -With eicon driver version 1.77 or newer and the eiconctrl utility -of version 1.1 or better, you can use the isdnlog user program -with your DIVA Server BRI card. -Just use "eiconctrl isdnlog on" and the driver will generate -the necessary D-Channel traces for isdnlog. - - -Thanks to - Deutsche Mailbox Saar-Lor-Lux GmbH - for sponsoring and testing fax - capabilities with Diva Server cards. - - -Any reports about bugs, errors and even wishes are welcome. - - -Have fun ! - -Armin Schindler -mac@melware.de -http://www.melware.de diff --git a/Documentation/isdn/README.fax b/Documentation/isdn/README.fax deleted file mode 100644 index eeff9ce9..00000000 --- a/Documentation/isdn/README.fax +++ /dev/null @@ -1,42 +0,0 @@ - -Fax with isdn4linux -=================== - -When enabled during kernel configuration, the tty emulator -of the ISDN subsystem is capable of the Fax Class 2 commands. - -This only makes sense under the following conditions : - -- You need the commands as dummy, because you are using - hylafax (with patch) for AVM capi. -- You want to use the fax capabilities of your isdn-card. - (supported cards are listed below) - - -NOTE: This implementation does *not* support fax with passive - ISDN-cards (known as softfax). The low-level driver of - the ISDN-card and/or the card itself must support this. - - -Supported ISDN-Cards --------------------- - -Eicon DIVA Server BRI/PCI - - full support with both B-channels. - -Eicon DIVA Server PRI/PCI - - full support on amount of B-channels - depending on DSPs on board. - - - -The command set is known as Class 2 (not Class 2.0) and -can be activated by AT+FCLASS=2 - - -The interface between the link-level-module and the hardware-level driver -is described in the files INTERFACE.fax and INTERFACE. - -Armin -mac@melware.de - diff --git a/Documentation/isdn/README.hfc-pci b/Documentation/isdn/README.hfc-pci deleted file mode 100644 index 6cc311e3..00000000 --- a/Documentation/isdn/README.hfc-pci +++ /dev/null @@ -1,41 +0,0 @@ -The driver for the HFC-PCI and HFC-PCI-A chips from CCD may be used -for many OEM cards using this chips. -Additionally the driver has a special feature which makes it possible -to read the echo-channel of the isdn bus. So all frames in both directions -may be logged. -When the echo logging feature is used the number of available B-channels -for a HFC-PCI card is reduced to 1. Of course this is only relevant to -the card, not to the isdn line. -To activate the echo mode the following ioctls must be entered: - -hisaxctrl 10 1 - -This reduces the available channels to 1. There must not be open connections -through this card when entering the command. -And then: - -hisaxctrl 12 1 - -This enables the echo mode. If Hex logging is activated the isdnctrlx -devices show a output with a line beginning of HEX: for the providers -exchange and ECHO: for isdn devices sending to the provider. - -If more than one HFC-PCI cards are installed, a specific card may be selected -at the hisax module load command line. Supply the load command with the desired -IO-address of the desired card. -Example: -There tree cards installed in your machine at IO-base addresses 0xd000, 0xd400 -and 0xdc00 -If you want to use the card at 0xd400 standalone you should supply the insmod -or depmod with type=35 io=0xd400. -If you want to use all three cards, but the order needs to be at 0xdc00,0xd400, -0xd000 you may give the parameters type=35,35,35 io=0xdc00,0xd400,0xd00 -Then the desired card will be the initialised in the desired order. -If the io parameter is used the io addresses of all used cards should be -supplied else the parameter is assumed 0 and a auto search for a free card is -invoked which may not give the wanted result. - -Comments and reports to werner@isdn4linux.de or werner@titro.de . - - - diff --git a/Documentation/isdn/README.hysdn b/Documentation/isdn/README.hysdn deleted file mode 100644 index bfc94fe8..00000000 --- a/Documentation/isdn/README.hysdn +++ /dev/null @@ -1,177 +0,0 @@ -$Id$ -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 -under the GNU Public License. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - 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. - -Table of contents -================= - -1. About the driver - -2. Loading/Unloading the driver - -3. Entries in the /proc filesystem - -4. The /proc/net/hysdn/cardconfX file - -5. The /proc/net/hysdn/cardlogX file - -6. Where to get additional info and help - - -1. About the driver - - The drivers/isdn/hysdn subdir contains a driver for HYPERCOPEs active - PCI isdn cards Champ, Ergo and Metro. To enable support for this cards - enable ISDN support in the kernel config and support for HYSDN cards in - the active cards submenu. The driver may only be compiled and used if - support for loadable modules and the process filesystem have been enabled. - No other ISDN options need to be enabled for these cards. - - Up to now these cards do not use or require the standard isdn interface - module (isdn.o), but registers itself as an ethernet card. All necessary - handlers for various protocols like ppp and others as well as config info - and firmware may be fetched from Hypercopes WWW-Site www.hypercope.de. - The driver has been included in the i4l tree as a CAPI compliant module - is under development and will be connected to the standard i4l modules - additionally. - -2. Loading/Unloading the driver - - The module has no command line parameters and auto detects up to 10 cards - in the id-range 0-9. - If a loaded driver shall be unloaded all open files in the /proc/net/hysdn - subdir need to be closed and all ethernet interfaces allocated by this - driver must be shut down. Otherwise the module counter will avoid a module - unload. - -3. Entries in the /proc filesystem - - When the module has been loaded it adds the directory hysdn in the - /proc/net tree. This directory contains exactly 2 file entries for each - card. One is called cardconfX and the other cardlogX, where X is the - card id number from 0 to 9. - The cards are numbered in the order found in the PCI config data. - -4. The /proc/net/hysdn/cardconfX file - - This file may be read to get by everyone to get info about the cards type, - actual state, available features and used resources. - The first 3 entries (id, bus and slot) are PCI info fields, the following - type field gives the information about the cards type: - - 4 -> Ergo card (server card with 2 b-chans) - 5 -> Metro card (server card with 4 or 8 b-chans) - 6 -> Champ card (client card with 2 b-chans) - - The following 3 fields show the hardware assignments for irq, iobase and the - dual ported memory (dp-mem). - The fields b-chans and fax-chans announce the available card resources of - this types for the user. - The state variable indicates the actual drivers state for this card with the - following assignments. - - 0 -> card has not been booted since driver load - 1 -> card booting is actually in progess - 2 -> card is in an error state due to a previous boot failure - 3 -> card is booted and active - - And the last field (device) shows the name of the ethernet device assigned - to this card. Up to the first successfull boot this field only shows a - - to tell that no net device has been allocated up to now. Once a net device - has been allocated it remains assigned to this card, even if a card is - rebooted and an boot error occurs. - - Writing to the cardconfX file boots the card or transfers config lines to - the cards firmware. The type of data is automatically detected when the - first data is written. Only root has write access to this file. - The firmware boot files are normally called hyclient.pof for client cards - and hyserver.pof for server cards. - After successfully writing the boot file, complete config files or single - config lines may be copied to this file. - If an error occurs the return value given to the writing process has the - following additional codes (decimal): - - 1000 Another process is currently bootng the card - 1001 Invalid firmware header - 1002 Boards dual-port RAM test failed - 1003 Internal firmware handler error - 1004 Boot image size invalid - 1005 First boot stage (bootstrap loader) failed - 1006 Second boot stage failure - 1007 Timeout waiting for card ready during boot - 1008 Operation only allowed in booted state - 1009 Config line to long - 1010 Invalid channel number - 1011 Timeout sending config data - - Additional info about error reasons may be fetched from the log output. - -5. The /proc/net/hysdn/cardlogX file - - The cardlogX file entry may be opened multiple for reading by everyone to - get the cards and drivers log data. Card messages always start with the - keyword LOG. All other lines are output from the driver. - The driver log data may be redirected to the syslog by selecting the - approriate bitmask. The cards log messages will always be send to this - interface but never to the syslog. - - A root user may write a decimal or hex (with 0x) value t this file to select - desired output options. As mentioned above the cards log dat is always - written to the cardlog file independant of the following options only used - to check and debug the driver itself: - - For example: - echo "0x34560078" > /proc/net/hysdn/cardlog0 - to output the hex log mask 34560078 for card 0. - - The written value is regarded as an unsigned 32-Bit value, bit ored for - desired output. The following bits are already assigned: - - 0x80000000 All driver log data is alternatively via syslog - 0x00000001 Log memory allocation errors - 0x00000010 Firmware load start and close are logged - 0x00000020 Log firmware record parser - 0x00000040 Log every firmware write actions - 0x00000080 Log all card related boot messages - 0x00000100 Output all config data sent for debugging purposes - 0x00000200 Only non comment config lines are shown wth channel - 0x00000400 Additional conf log output - 0x00001000 Log the asynchronous scheduler actions (config and log) - 0x00100000 Log all open and close actions to /proc/net/hysdn/card files - 0x00200000 Log all actions from /proc file entries - 0x00010000 Log network interface init and deinit - -6. Where to get additional info and help - - If you have any problems concerning the driver or configuration contact - the Hypercope support team (www.hypercope.de) and or the author - Werner Cornelius (werner@isdn4linux or cornelius@titro.de) - - - - - - - - - - - - - diff --git a/Documentation/isdn/README.icn b/Documentation/isdn/README.icn deleted file mode 100644 index 6f8d386b..00000000 --- a/Documentation/isdn/README.icn +++ /dev/null @@ -1,148 +0,0 @@ -$Id$ - -You can get the ICN-ISDN-card from: - -Thinking Objects Software GmbH -Versbacher Röthe 159 -97078 Würzburg -Tel: +49 931 2877950 -Fax: +49 931 2877951 - -email info@think.de -WWW http:/www.think.de - - -The card communicates with the PC by two interfaces: - 1. A range of 4 successive port-addresses, whose base address can be - configured with the switches. - 2. A memory window with 16KB-256KB size, which can be setup in 16k steps - over the whole range of 16MB. Isdn4linux only uses a 16k window. - The base address of the window can be configured when loading - the lowlevel-module (see README). If using more than one card, - all cards are mapped to the same window and activated as needed. - -Setting up the IO-address dipswitches for the ICN-ISDN-card: - - Two types of cards exist, one with dip-switches and one with - hook-switches. - - 1. Setting for the card with hook-switches: - - (0 = switch closed, 1 = switch open) - - S3 S2 S1 Base-address - 0 0 0 0x300 - 0 0 1 0x310 - 0 1 0 0x320 (Default for isdn4linux) - 0 1 1 0x330 - 1 0 0 0x340 - 1 0 1 0x350 - 1 1 0 0x360 - 1 1 1 NOT ALLOWED! - - 2. Setting for the card with dip-switches: - - (0 = switch closed, 1 = switch open) - - S1 S2 S3 S4 Base-Address - 0 0 0 0 0x300 - 0 0 0 1 0x310 - 0 0 1 0 0x320 (Default for isdn4linux) - 0 0 1 1 0x330 - 0 1 0 0 0x340 - 0 1 0 1 0x350 - 0 1 1 0 0x360 - 0 1 1 1 NOT ALLOWED! - 1 0 0 0 0x308 - 1 0 0 1 0x318 - 1 0 1 0 0x328 - 1 0 1 1 0x338 - 1 1 0 0 0x348 - 1 1 0 1 0x358 - 1 1 1 0 0x368 - 1 1 1 1 NOT ALLOWED! - -The ICN driver may be built into the kernel or as a module. Initialization -depends on how the driver is built: - -Driver built into the kernel: - - The ICN driver can be configured using the commandline-feature while - loading the kernel with LILO or LOADLIN. It accepts the following syntax: - - icn=p,m[,idstring1[,idstring2]] - - where - - p = portbase (default: 0x320) - m = shared memory (default: 0xd0000) - - When using the ICN double card (4B), you MUST define TWO idstrings. - idstring must start with a character! There is no way for the driver - to distinguish between a 2B and 4B type card. Therefore, by supplying - TWO idstrings, you tell the driver that you have a 4B installed. - - If you like to use more than one card, you can use the program - "icnctrl" from the utility-package to configure additional cards. - You need to configure shared memory only once, since the icn-driver - maps all cards into the same address-space. - - Using the "icnctrl"-utility, portbase and shared memory can also be - changed during runtime. - - The D-channel protocol is configured by loading different firmware - into the card's memory using the "icnctrl"-utility. - - -Driver built as module: - - The module icn.o can be configured during "insmod'ing" it by - appending its parameters to the insmod-commandline. The following - syntax is accepted: - - portbase=p membase=m icn_id=idstring [icn_id2=idstring2] - - where p, m, idstring1 and idstring2 have the same meanings as the - parameters described for the kernel-version above. - - When using the ICN double card (4B), you MUST define TWO idstrings. - idstring must start with a character! There is no way for the driver - to distinguish between a 2B and 4B type card. Therefore, by supplying - TWO idstrings, you tell the driver that you have a 4B installed. - - Using the "icnctrl"-utility, the same features apply to the modularized - version like to the kernel-builtin one. - - The D-channel protocol is configured by loading different firmware - into the card's memory using the "icnctrl"-utility. - -Loading the firmware into the card: - - The firmware is supplied together with the isdn4k-utils package. It - can be found in the subdirectory icnctrl/firmware/ - - There are 3 files: - - loadpg.bin - Image of the bootstrap loader. - pc_1t_ca.bin - Image of firmware for german 1TR6 protocol. - pc_eu_ca.bin - Image if firmware for EDSS1 (Euro-ISDN) protocol. - - Assuming you have installed the utility-package correctly, the firmware - will be downloaded into the 2B-card using the following command: - - icnctrl -d Idstring load /etc/isdn/loadpg.bin /etc/isdn/pc_XX_ca.bin - - where XX is either "1t" or "eu", depending on the D-Channel protocol - used on your S0-bus and Idstring is the Name of the card, given during - insmod-time or (for kernel-builtin driver) on the kernel commandline. - - To load a 4B-card, the same command is used, except a second firmware - file is appended to the commandline of icnctrl. - - -> After dowloading firmware, the two LEDs at the back cover of the card - (ICN-4B: 4 LEDs) must be blinking intermittently now. If a connection - is up, the corresponding led is lit continuously. - - For further documentation (adding more ICN-cards), refer to the manpage - icnctrl.8 which is included in the isdn4k-utils package. - diff --git a/Documentation/isdn/README.pcbit b/Documentation/isdn/README.pcbit deleted file mode 100644 index 51250022..00000000 --- a/Documentation/isdn/README.pcbit +++ /dev/null @@ -1,40 +0,0 @@ ------------------------------------------------------------------------------- - README file for the PCBIT-D Device Driver. ------------------------------------------------------------------------------- - -The PCBIT is a Euro ISDN adapter manufactured in Portugal by Octal and -developed in cooperation with Portugal Telecom and Inesc. -The driver interfaces with the standard kernel isdn facilities -originally developed by Fritz Elfert in the isdn4linux project. - -The common versions of the pcbit board require a firmware that is -distributed (and copyrighted) by the manufacturer. To load this -firmware you need "pcbitctl" available on the standard isdn4k-utils -package or in the pcbit package available in: - -ftp://ftp.di.fc.ul.pt/pub/systems/Linux/isdn - -Known Limitations: - -- The board reset procedure is at the moment incorrect and will only -allow you to load the firmware after a hard reset. - -- Only HDLC in B-channels is supported at the moment. There is no -current support for X.25 in B or D channels nor LAPD in B -channels. The main reason is that these two other protocol modes have, -to my knowledge, very little use. If you want to see them implemented -*do* send me a mail. - -- The driver often triggers errors in the board that I and the -manufacturer believe to be caused by bugs in the firmware. The current -version includes several procedures for error recovery that should -allow normal operation. Plans for the future include cooperation with -the manufacturer in order to solve this problem. - -Information/hints/help can be obtained in the linux isdn -mailing list (isdn4linux@listserv.isdn4linux.de) or directly from me. - -regards, - Pedro. - - diff --git a/Documentation/isdn/README.syncppp b/Documentation/isdn/README.syncppp deleted file mode 100644 index 27d26009..00000000 --- a/Documentation/isdn/README.syncppp +++ /dev/null @@ -1,58 +0,0 @@ -Some additional information for setting up a syncPPP -connection using network interfaces. ---------------------------------------------------------------- - -You need one thing beside the isdn4linux package: - - a patched pppd .. (I called it ipppd to show the difference) - -Compiling isdn4linux with sync PPP: ------------------------------------ -To compile isdn4linux with the sync PPP part, you have -to answer the appropriate question when doing a "make config" -Don't forget to load the slhc.o -module before the isdn.o module, if VJ-compression support -is not compiled into your kernel. (e.g if you have no PPP or -CSLIP in the kernel) - -Using isdn4linux with sync PPP: -------------------------------- -Sync PPP is just another encapsulation for isdn4linux. The -name to enable sync PPP encapsulation is 'syncppp' .. e.g: - - /sbin/isdnctrl encap ippp0 syncppp - -The name of the interface is here 'ippp0'. You need -one interface with the name 'ippp0' to saturate the -ipppd, which checks the ppp version via this interface. -Currently, all devices must have the name ipppX where -'X' is a decimal value. - -To set up a PPP connection you need the ipppd .. You must start -the ipppd once after installing the modules. The ipppd -communicates with the isdn4linux link-level driver using the -/dev/ippp0 to /dev/ippp15 devices. One ipppd can handle -all devices at once. If you want to use two PPP connections -at the same time, you have to connect the ipppd to two -devices .. and so on. -I've implemented one additional option for the ipppd: - 'useifip' will get (if set to not 0.0.0.0) the IP address - for the negotiation from the attached network-interface. -(also: ipppd will try to negotiate pointopoint IP as remote IP) -You must disable BSD-compression, this implementation can't -handle compressed packets. - -Check the etc/rc.isdn.syncppp in the isdn4kernel-util package -for an example setup script. - -To use the MPPP stuff, you must configure a slave device -with isdn4linux. Now call the ipppd with the '+mp' option. -To increase the number of links, you must use the -'addlink' option of the isdnctrl tool. (rc.isdn.syncppp.MPPP is -an example script) - -enjoy it, - michael - - - diff --git a/Documentation/isdn/README.x25 b/Documentation/isdn/README.x25 deleted file mode 100644 index e561a77c..00000000 --- a/Documentation/isdn/README.x25 +++ /dev/null @@ -1,184 +0,0 @@ - -X.25 support within isdn4linux -============================== - -This is alpha/beta test code. Use it completely at your own risk. -As new versions appear, the stuff described here might suddenly change -or become invalid without notice. - -Keep in mind: - -You are using several new parts of the 2.2.x kernel series which -have not been tested in a large scale. Therefore, you might encounter -more bugs as usual. - -- If you connect to an X.25 neighbour not operated by yourself, ASK the - other side first. Be prepared that bugs in the protocol implementation - might result in problems. - -- This implementation has never wiped out my whole hard disk yet. But as - this is experimental code, don't blame me if that happened to you. - Backing up important data will never harm. - -- Monitor your isdn connections while using this software. This should - prevent you from undesired phone bills in case of driver problems. - - - - -How to configure the kernel -=========================== - -The ITU-T (former CCITT) X.25 network protocol layer has been implemented -in the Linux source tree since version 2.1.16. The isdn subsystem might be -useful to run X.25 on top of ISDN. If you want to try it, select - - "CCITT X.25 Packet Layer" - -from the networking options as well as - - "ISDN Support" and "X.25 PLP on Top of ISDN" - -from the ISDN subsystem options when you configure your kernel for -compilation. You currently also need to enable -"Prompt for development and/or incomplete code/drivers" from the -"Code maturity level options" menu. For the x25trace utility to work -you also need to enable "Packet socket". - -For local testing it is also recommended to enable the isdnloop driver -from the isdn subsystem's configuration menu. - -For testing, it is recommended that all isdn drivers and the X.25 PLP -protocol are compiled as loadable modules. Like this, you can recover -from certain errors by simply unloading and reloading the modules. - - - -What's it for? How to use it? -============================= - -X.25 on top of isdn might be useful with two different scenarios: - -- You might want to access a public X.25 data network from your Linux box. - You can use i4l if you were physically connected to the X.25 switch - by an ISDN B-channel (leased line as well as dial up connection should - work). - - This corresponds to ITU-T recommendation X.31 Case A (circuit-mode - access to PSPDN [packet switched public data network]). - - NOTE: X.31 also covers a Case B (access to PSPDN via virtual - circuit / packet mode service). The latter mode (which in theory - also allows using the D-channel) is not supported by isdn4linux. - It should however be possible to establish such packet mode connections - with certain active isdn cards provided that the firmware supports X.31 - and the driver exports this functionality to the user. Currently, - the AVM B1 driver is the only driver which does so. (It should be - possible to access D-channel X.31 with active AVM cards using the - CAPI interface of the AVM-B1 driver). - -- Or you might want to operate certain ISDN teleservices on your linux - box. A lot of those teleservices run on top of the ISO-8208 - (DTE-DTE mode) network layer protocol. ISO-8208 is essentially the - same as ITU-T X.25. - - Popular candidates of such teleservices are EUROfile transfer or any - teleservice applying ITU-T recommendation T.90. - -To use the X.25 protocol on top of isdn, just create an isdn network -interface as usual, configure your own and/or peer's ISDN numbers, -and choose x25iface encapsulation by - - isdnctrl encap x25iface. - -Once encap is set like this, the device can be used by the X.25 packet layer. - -All the stuff needed for X.25 is implemented inside the isdn link -level (mainly isdn_net.c and some new source files). Thus, it should -work with every existing HL driver. I was able to successfully open X.25 -connections on top of the isdnloop driver and the hisax driver. -"x25iface"-encapsulation bypasses demand dialing. Dialing will be -initiated when the upper (X.25 packet) layer requests the lapb datalink to -be established. But hangup timeout is still active. Whenever a hangup -occurs, all existing X.25 connections on that link will be cleared -It is recommended to use sufficiently large hangup-timeouts for the -isdn interfaces. - - -In order to set up a conforming protocol stack you also need to -specify the proper l2_prot parameter: - -To operate in ISO-8208 X.25 DTE-DTE mode, use - - isdnctrl l2_prot x75i - -To access an X.25 network switch via isdn (your linux box is the DTE), use - - isdnctrl l2_prot x25dte - -To mimic an X.25 network switch (DCE side of the connection), use - - isdnctrl l2_prot x25dce - -However, x25dte or x25dce is currently not supported by any real HL -level driver. The main difference between x75i and x25dte/dce is that -x25d[tc]e uses fixed lap_b addresses. With x75i, the side which -initiates the isdn connection uses the DTE's lap_b address while the -called side used the DCE's lap_b address. Thus, l2_prot x75i might -probably work if you access a public X.25 network as long as the -corresponding isdn connection is set up by you. At least one test -was successful to connect via isdn4linux to an X.25 switch using this -trick. At the switch side, a terminal adapter X.21 was used to connect -it to the isdn. - - -How to set up a test installation? -================================== - -To test X.25 on top of isdn, you need to get - -- a recent version of the "isdnctrl" program that supports setting the new - X.25 specific parameters. - -- the x25-utils-2.X package from - ftp://ftp.hes.iki.fi/pub/ham/linux/ax25/x25utils-* - (don't confuse the x25-utils with the ax25-utils) - -- an application program that uses linux PF_X25 sockets (some are - contained in the x25-util package). - -Before compiling the user level utilities make sure that the compiler/ -preprocessor will fetch the proper kernel header files of this kernel -source tree. Either make /usr/include/linux a symbolic link pointing to -this kernel's include/linux directory or set the appropriate compiler flags. - -When all drivers and interfaces are loaded and configured you need to -ifconfig the network interfaces up and add X.25-routes to them. Use -the usual ifconfig tool. - -ifconfig up - -But a special x25route tool (distributed with the x25-util package) -is needed to set up X.25 routes. I.e. - -x25route add 01 - -will cause all x.25 connections to the destination X.25-address -"01" to be routed to your created isdn network interface. - -There are currently no real X.25 applications available. However, for -tests, the x25-utils package contains a modified version of telnet -and telnetd that uses X.25 sockets instead of tcp/ip sockets. You can -use those for your first tests. Furthermore, you might check -ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/ which contains some -alpha-test implementation ("eftp4linux") of the EUROfile transfer -protocol. - -The scripts distributed with the eftp4linux test releases might also -provide useful examples for setting up X.25 on top of isdn. - -The x25-utility package also contains an x25trace tool that can be -used to monitor X.25 packets received by the network interfaces. -The /proc/net/x25* files also contain useful information. - -- Henner diff --git a/Documentation/isdn/abcext_kernel.help b/Documentation/isdn/abcext_kernel.help deleted file mode 100644 index 18d6d6a1..00000000 --- a/Documentation/isdn/abcext_kernel.help +++ /dev/null @@ -1,166 +0,0 @@ - -ISDN-ABC-DW Extension -CONFIG_ISDN_WITH_ABC - These are many brand new Options and Features for the - ISDN SUBSYSTEM. Including Logical Device bindings, - Compression and other good stuff for Optimizing your - ISDN System. - - To Use this Extensions you MUST HAVE THE NEWEST - ISDN4K-UTILS. You must have Version 3.1-Beta6 or - higher. Elsewhere you can not configure this Extensions. - - WARNING ! THIS STUF IS NOT PRODUCTION RELEASE THE - FUNCTION ARE UNDER DEVELOPMENT. This ist BETA-CODE. - You can use it at you Own Risk. - - For more Information on these Extensions take a look at - "linux/Documentation/isdn/dw-abc-extension-howto.txt or - Online at the Web "http://www.mediatronix.de/i4l/index.html" - - Please Report Bugs to "mario@mediatronix.de" or - "delefw@isdn4linux.de" - -D-Channel-Callback with Channel in use check -CONFIG_ISDN_WITH_ABC_CALLB - When a Interface is declared as an Callback Interface, - the Interface is checking that the other Side is not - Calling on the same time before the Interface is Dialing. - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - - In most case answer with "Yes" when you have Callback devices, - otherwise leave it "No" - -Outgoing-EAZ-Support -CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ - Enables the Feature to Define an other EAZ or MSN for - Outgoing calls on an Interface. - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - -Least Cost Router Support -CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - This is the final Kernel Code for configuring an Least - Cost Router Softwarebased. The other Job is to do the - action in ISDNLOG. You need the ISDNLOG to use this - function. Currently the ISDNLOG have not the Support for - this Option. - So in most situations let the Option off. - -TCP keepalive detect and response -CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - This Option works only with the TCP/IP V4. It enables - the Function that ISDN Devices are Answering TCP_KEEPALIVE Pakets - localy. So that TCP KEEPALIVE Pakets not longer takes the Line - open. - -Drop frames Sourceadresse is not Interfaceadress -CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR - This Option works only with the TCP/IP V4. It will allow only - the Transmitt of Pakets where the Sourceadresse is the Interface - adress. It is usefull when you have Lines with Dynamic IP. - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - -Receive do not reset the Hanguptimer -CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - When you activate this option than the reiceive of pakets do - not reset the Hanguptimer. It is very usefull because if the - Paket vor your Network your Network generate an Response and - the Transmit is reseting the HUPTIMER. But when the Paket is - Rejected at your firewall your network generate no Response - and no Sendtraffic is generated. So in this case there is no - need to Reset the Huptimer because you have only received Data. - With that option only Transmitted Data/Pakets will reset the - HUPTIMER. - -Support of (device-channel) and Binding Groups -CONFIG_ISDN_WITH_ABC_ICALL_BIND - This Option enables the Feature to Bind logical ISDN Interfaces - to an prefered ISDN Card or ISDN Card plus Channel. So you have - the Chance to keep Channels exclusively for one (or more) - Connection. Very usefull when you have more channels and Use - Calling Line Identification, because you can organize that your - call is going out over the Line with the right EAZ for the CLI. - -Skip channel if used external (Dial Only) -CONFIG_ISDN_WITH_ABC_CH_EXTINUSE - When you have more than One ISDN Card in your System and you - will Dialout with an Interface you can become the Situation - that an External Device such a Telephone or Fax is Using the - B-Channels. Normaly ISDN4Linux does not detect this Situation - and dial everytime of the "External Busy" line out. With this - Option Enabled the I4L will detect that he can not dialout on - This Card and dial over the next Card out. - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - -Interface autodisable if Config error -CONFIG_ISDN_WITH_ABC_CONN_ERROR - This Option will detect an Device which generate Telephone - Cost but does not Function correctly because there are - Configerrors on one of the Site. In this Situation the - Interface will be marked as Unsuably for some time to do - not call every time this Site. - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - -UDP-Info-Support -CONFIG_ISDN_WITH_ABC_UDP_CHECK - This is the Mainoption to Enable or Disable the UDP - Info Support. An Option to Controll ISDN-Interfaces - Remotely. For this very Complex thing take a look at - - "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information. - -UDP Hangup Support -CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP - - Sorry no more Information! - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - -UDP Dial Support -CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL - - Sorry no more Information! - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - -Limit on the line frames to two -CONFIG_ISDN_WITH_ABC_FRAME_LIMIT - - This Option enables support for sending only 2 Pakets on - the Fly to the ISDN Driver. It is very usefull when you - will use the new RAW-IP Compression. Because of sending - Only 2 Pakets on the Fly makes the risk of overflowing - the ISDN Driver very smaller. - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - -Compression with RAWIP and X75I -CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS - - With this Option you have the ability to make Datacompression - on RAW-IP Lines. It is function on HDLC and X75I Connection, - but the Prefered L2-Protocol for Compression is X75I because - the HDLC Protocol have no Errorcorrection. - - To Use this Option YOU MUST HAVE ENABLED THE OPTION: - Support synchronous PPP - and must load after loading the main isdndrivers the - Modul "isdn_bsdcomp". - - See "linux/Documentation/isdn/dw-abc-extension-howto.txt" - for more Information - diff --git a/Documentation/isdn/syncPPP.FAQ b/Documentation/isdn/syncPPP.FAQ deleted file mode 100644 index 3257a4bc..00000000 --- a/Documentation/isdn/syncPPP.FAQ +++ /dev/null @@ -1,224 +0,0 @@ -simple isdn4linux PPP FAQ .. to be continued .. not 'debugged' -------------------------------------------------------------------- - -Q01: what's pppd, ipppd, syncPPP, asyncPPP ?? -Q02: error message "this system lacks PPP support" -Q03: strange information using 'ifconfig' -Q04: MPPP?? What's that and how can I use it ... -Q05: I tried MPPP but it doesn't work -Q06: can I use asynchronous PPP encapsulation with network devices -Q07: A SunISDN machine can't connect to my i4l system -Q08: I wanna talk to several machines, which need different configs -Q09: Starting the ipppd, I get only error messages from i4l -Q10: I wanna use dynamic IP address assignment -Q11: I can't connect. How can I check where the problem is. -Q12: How can I reduce login delay? - -------------------------------------------------------------------- - -Q01: pppd, ipppd, syncPPP, asyncPPP .. what is that ? - what should I use? -A: The pppd is for asynchronous PPP .. asynchronous means - here, the framing is character based. (e.g when - using ttyI* or tty* devices) - - The ipppd handles PPP packets coming in HDLC - frames (bit based protocol) ... The PPP driver - in isdn4linux pushes all IP packets direct - to the network layer and all PPP protocol - frames to the /dev/ippp* device. - So, the ipppd is a simple external network - protocol handler. - - If you login into a remote machine using the - /dev/ttyI* devices and then enable PPP on the - remote terminal server -> use the 'old' pppd - - If your remote side immediately starts to send - frames ... you probably connect to a - syncPPP machine .. use the network device part - of isdn4linux with the 'syncppp' encapsulation - and make sure, that the ipppd is running and - connected to at least one /dev/ippp*. Check the - isdn4linux manual on how to configure a network device. - --- - -Q02: when I start the ipppd .. I only get the - error message "this system lacks PPP support" -A: check that at least the device 'ippp0' exists. - (you can check this e.g with the program 'ifconfig') - The ipppd NEEDS this device under THIS name .. - If this device doesn't exists, use: - isdnctrl addif ippp0 - isdnctrl encap ippp0 syncppp - ... (see isdn4linux doc for more) ... -A: Maybe you have compiled the ipppd with another - kernel source tree than the kernel you currently - run ... - --- - -Q03: when I list the netdevices with ifconfig I see, that - my ISDN interface has a HWaddr and IRQ=0 and Base - address = 0 -A: The device is a fake ethernet device .. ignore IRQ and baseaddr - You need the HWaddr only for ethernet encapsulation. - --- - -Q04: MPPP?? What's that and how can I use it ... - -A: MPPP or MP or MPP (Warning: MP is also an - acronym for 'Multi Processor') stands for - Multi Point to Point and means bundling - of several channels to one logical stream. - To enable MPPP negotiation you must call the - ipppd with the '+mp' option. - You must also configure a slave device for - every additional channel. (see the i4l manual - for more) - To use channel bundling you must first activate - the 'master' or initial call. Now you can add - the slave channels with the command: - isdnctrl addlink - e.g: - isdnctrl addlink ippp0 - This is different from other encapsulations of - isdn4linux! With syncPPP, there is no automatic - activation of slave devices. - --- - -Q05: I tried MPPP but it doesn't work .. the ipppd - writes in the debug log something like: - .. rcvd [0][proto=0x3d] c0 00 00 00 80 fd 01 01 00 0a ... - .. sent [0][LCP ProtRej id=0x2 00 3d c0 00 00 00 80 fd 01 ... - -A: you forgot to compile MPPP/RFC1717 support into the - ISDN Subsystem. Recompile with this option enabled. - --- - -Q06: can I use asynchronous PPP encapsulation - over the network interface of isdn4linux .. - -A: No .. that's not possible .. Use the standard - PPP package over the /dev/ttyI* devices. You - must not use the ipppd for this. - --- - -Q07: A SunISDN machine tries to connect my i4l system, - which doesn't work. - Checking the debug log I just saw garbage like: -!![ ... fill in the line ... ]!! - -A: The Sun tries to talk asynchronous PPP ... i4l - can't understand this ... try to use the ttyI* - devices with the standard PPP/pppd package - -A: (from Alexanter Strauss: ) -!![ ... fill in mail ]!! - --- - -Q08: I wanna talk to remote machines, which need - a different configuration. The only way - I found to do this is to kill the ipppd and - start a new one with another config to connect - to the second machine. - -A: you must bind a network interface explicitly to - an ippp device, where you can connect a (for this - interface) individually configured ipppd. - --- - -Q09: When I start the ipppd I only get error messages - from the i4l driver .. - -A: When starting, the ipppd calls functions which may - trigger a network packet. (e.g gethostbyname()). - Without the ipppd (at this moment, it is not - fully started) we can't handle this network request. - Try to configure hostnames necessary for the ipppd - in your local /etc/hosts file or in a way, that - your system can resolve it without using an - isdn/ippp network-interface. - --- - -Q10: I wanna use dynamic IP address assignment ... How - must I configure the network device. - -A: At least you must have a route which forwards - a packet to the ippp network-interface to trigger - the dial-on-demand. - A default route to the ippp-interface will work. - Now you must choose a dummy IP address for your - interface. - If for some reason you can't set the default - route to the ippp interface, you may take any - address of the subnet from which you expect your - dynamic IP number and set a 'network route' for - this subnet to the ippp interface. - To allow overriding of the dummy address you - must call the ipppd with the 'ipcp-accept-local' option. - -A: You must know, how the ipppd gets the addresses it wanna - configure. If you don't give any option, the ipppd - tries to negotiate the local host address! - With the option 'noipdefault' it requests an address - from the remote machine. With 'useifip' it gets the - addresses from the net interface. Or you set the address - on the option line with the option. - Note: the IP address of the remote machine must be configured - locally or the remote machine must send it in an IPCP request. - If your side doesn't know the IP address after negotiation, it - closes the connection! - You must allow overriding of address with the 'ipcp-accept-*' - options, if you have set your own or the remote address - explicitly. - -A: Maybe you try these options .. e.g: - - /sbin/ipppd :$REMOTE noipdefault /dev/ippp0 - - where REMOTE must be the address of the remote machine (the - machine, which gives you your address) - --- - -Q11: I can't connect. How can I check where the problem is. - -A: A good help log is the debug output from the ipppd... - Check whether you can find there: - - only a few LCP-conf-req SENT messages (less then 10) - and then a Term-REQ: - -> check whether your ISDN card is well configured - it seems, that your machine doesn't dial - (IRQ,IO,Proto, etc problems) - Configure your ISDN card to print debug messages and - check the /dev/isdnctrl output next time. There - you can see, whether there is activity on the card/line. - - there are at least a few RECV messages in the log: - -> fine: your card is dialing and your remote machine - tries to talk with you. Maybe only a missing - authentication. Check your ipppd configuration again. - - the ipppd exits for some reason: - -> not good ... check /var/adm/syslog and /var/adm/daemon. - Could be a bug in the ipppd. - --- - -Q12: How can I reduce login delay? - -A: Log a login session ('debug' log) and check which options - your remote side rejects. Next time configure your ipppd - to not negotiate these options. Another 'side effect' is, that - this increases redundancy. (e.g your remote side is buggy and - rejects options in a wrong way). - - - diff --git a/Makefile b/Makefile deleted file mode 100644 index 88c45b27..00000000 --- a/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -I4LVERSION=2.1.88 - -KERNELDIR = /usr/src/linux - -######### NOTHING TO CHANGE BELOW ################ -.EXPORT_ALL_VARIABLES: - -CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ - else if [ -x /bin/bash ]; then echo /bin/bash; \ - else echo sh; fi ; fi) -KCONFIG = $(KERNELDIR)/.config - -TOPDIR := $(shell if [ "$$PWD" != "" ]; then echo $$PWD; else pwd; fi) -ISDNINC := $(ISDNTOP)/include - -# -# Get VERSION, PATCHLEVEL, SUBLEVEL, ARCH, SMP and SMP_PROF from Kerneltree -# -VERSION = $(shell head -9 $(KERNELDIR)/Makefile |grep VERSION |awk '{print $$3}') -PATCHLEVEL = $(shell head -9 $(KERNELDIR)/Makefile |grep PATCHLEVEL |awk '{print $$3}') -SUBLEVEL = $(shell head -9 $(KERNELDIR)/Makefile |grep SUBLEVEL |awk '{print $$3}') -ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) -ifneq ("$(shell egrep '^ *SMP *=.*' $(KERNELDIR)/Makefile)","") - SMP = 1 -endif -ifneq ("$(shell egrep '^ *SMP_PROF *=.*' $(KERNELDIR)/Makefile)","") - SMP_PROF = 1 -endif -ARCHMAKE := $(KERNELDIR)/arch/$(ARCH)/Makefile -MODDEST =/lib/modules/$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)/misc -HPATH =$(KERNELDIR)/include -HOSTCC =gcc -I$(HPATH) -I$(ISDNINC) -HOSTCFLAGS =-O2 -fomit-frame-pointer -CROSS_COMPILE = -AS =$(CROSS_COMPILE)as -LD =$(CROSS_COMPILE)ld -CC =$(CROSS_COMPILE)gcc -g -D__KERNEL__ -I$(HPATH) -CPP =$(CC) -E -AR =$(CROSS_COMPILE)ar -NM =$(CROSS_COMPILE)nm -STRIP =$(CROSS_COMPILE)strip -MAKE =make - -ifeq ($(KCONFIG),$(wildcard $(KCONFIG))) -include $(KCONFIG) -ifeq ($(CONFIG_ISDN),m) -include .config -do-it-all: modules -else -do-it-all: modconf-error -endif -else -do-it-all: unconf-error -endif - -CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce - -ifdef CONFIG_CPP -CFLAGS := $(CFLAGS) -x c++ -endif - -ifdef SMP -CFLAGS += -D__SMP__ -AFLAGS += -D__SMP__ - -ifdef SMP_PROF -CFLAGS += -D__SMP_PROF__ -AFLAGS += -D__SMP_PROF__ -endif -endif - -include $(ARCHMAKE) - -SUBDIRS := drivers/isdn - -MODFLAGS = -DMODULE -ifdef CONFIG_MODVERSIONS -MODFLAGS += -DMODVERSIONS -include $(HPATH)/linux/modversions.h -endif - -all: do-it-all - -unconf-error: - @echo "" - @echo "Cannot find configured kernel." - @echo "Make sure, you have our kernel configured, and" - @echo "the definition of KERNELDIR points to the proper location." - @echo "" - -modconf-error: - @echo "" - @echo "Your have disbled CONFIG_MODULES in your kernel configuration." - @echo "Without that option, this package cannot compile." - @echo "Reconfigure your kernel, then come back here and start again." - @echo "" - -$(KERNELDIR)/linux/version.h: $(KERNELDIR)/Makefile - @cd $(KERNELDIR) - $(MAKE) include/linux/version.h - -modules: $(KERNELDIR)/include/linux/version.h - @set -e; \ - for i in $(SUBDIRS); do \ - $(MAKE) -C $$i CFLAGS="$(CFLAGS) $(MODFLAGS)" MAKING_MODULES=1 modules; \ - done - -rootperm: - @echo 'main(int argc,char**argv){unlink(argv[0]);return(getuid()==0);}'>g - @if gcc -x c -o G g && rm -f g && ./G ; then \ - echo -e "\n\n Need root permission for installation!\n\n"; \ - exit 1; \ - fi - -modules_install: rootperm - @set -e; \ - for i in $(SUBDIRS); do \ - $(MAKE) -C $$i modules_install; \ - done - depmod -a $(VERSION).$(PATCHLEVEL).$(SUBLEVEL) - -clean: - rm -f `find . -name '*.[iso]' -print` - rm -f `find . -type f -name '*~' -print` - rm -f core `find . -type f -name 'core' -print` - -include Rules.make diff --git a/README.preparser b/README.preparser deleted file mode 100644 index d3f95e58..00000000 --- a/README.preparser +++ /dev/null @@ -1,61 +0,0 @@ -"preparser" is a little tool to resolve special macros and conditional -preprocessor code in C files. - -The special marcro and conditions are given in a control file. - -The control file use the same syntax like the C preprocessor directives -"#define" and "#undef" plus a "#delete" command. -You can also use C-Comments in it. -Here are 2 implicit conditional defines in "preparser" for "#if 0" -and "#if 1" code segments. - -Control file syntax: - -#delete -#define -#undef - - maybe also a function. - -/* example control file */ -#delete #include -#define GET_USER get_user -#define PUT_USER put_user -#define idev_kfree_skb(a,b) dev_kfree_skb(a) -#define COMPAT_HAS_NEW_SYMTAB -#undef COMPAT_HAS_NEW_SETUP -/* end of example control file */ - -What does the Programm ? -1. It copies a input file into a output file (or stdout) -2. While copying it deletes all items given in #delete (exact string - matching). -3. While copying it resolve the marcros given in the control file. -4. It resolve any "#ifdef" "#ifndef" "#if" related to the marcros given in - the control file. Note: in the moment it don't calculate a value after - an "#if" directive, if here is a "#define" in the control file for - the string after "#if" and the value of that "#define" is empty, "#if" is - handled as false, if a value is given it is handled as true. -5. All items inside "strings" or C comments are not modified. - -Usage - - ./preparser [options] [output file] - - Valid options are: - - -d increase debug level - -c,-C Use control file - -? Usage ; printout this information - - -"preparser" was written to write Linux portable Linux kernel code (portable -in the sense "portable between various kernel versions") and to remove -experimental code from C files. This avoid that contructs based on -KERNELVERSION are going into standard kernel. - - -Karsten Keil -keil@isdn4linux.de - -PS: If you like to get the source, request it by mail. diff --git a/Rules.make b/Rules.make deleted file mode 100644 index 4dff63f5..00000000 --- a/Rules.make +++ /dev/null @@ -1,189 +0,0 @@ -# -# This file contains rules which are shared between multiple Makefiles. -# - -# -# False targets. -# -.PHONY: dummy - -# -# Special variables which should not be exported -# -unexport EXTRA_ASFLAGS -unexport EXTRA_CFLAGS -unexport EXTRA_LDFLAGS -unexport EXTRA_ARFLAGS -unexport SUBDIRS -unexport SUB_DIRS -unexport ALL_SUB_DIRS -unexport MOD_SUB_DIRS -unexport O_TARGET -unexport O_OBJS -unexport L_OBJS -unexport M_OBJS -unexport ALL_MOBJS -# objects that export symbol tables -unexport OX_OBJS -unexport LX_OBJS -unexport MX_OBJS -unexport SYMTAB_OBJS - -unexport MOD_LIST_NAME - -# -# Get things started. -# -first_rule: sub_dirs - $(MAKE) all_targets - -# -# Common rules -# - -%.s: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -S $< -o $@ - -%.o: %.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< - -%.o: %.s - $(AS) $(ASFLAGS) $(EXTRA_CFLAGS) -o $@ $< - -# -# -# -all_targets: $(O_TARGET) $(L_TARGET) - -# -# Rule to compile a set of .o files into one .o file -# -ifdef O_TARGET -ALL_O = $(OX_OBJS) $(O_OBJS) -$(O_TARGET): $(ALL_O) $(KERNELDIR)/include/linux/config.h - rm -f $@ -ifneq "$(strip $(ALL_O))" "" - $(LD) $(EXTRA_LDFLAGS) -r -o $@ $(ALL_O) -else - $(AR) rcs $@ -endif -endif - -# -# Rule to compile a set of .o files into one .a file -# -ifdef L_TARGET -$(L_TARGET): $(LX_OBJS) $(L_OBJS) $(KERNELDIR)/include/linux/config.h - rm -f $@ - $(AR) $(EXTRA_ARFLAGS) rcs $@ $(LX_OBJS) $(L_OBJS) -endif - -# -# This make dependencies quickly -# -fastdep: dummy - if [ -n "$(wildcard *.[chS])" ]; then \ - $(TOPDIR)/scripts/mkdep *.[chS] > .depend; fi -ifdef ALL_SUB_DIRS - set -e; for i in $(ALL_SUB_DIRS); do $(MAKE) -C $$i fastdep; done -endif - -# -# A rule to make subdirectories -# -sub_dirs: dummy -ifdef SUB_DIRS - set -e; for i in $(SUB_DIRS); do $(MAKE) -C $$i; done -endif - -# -# A rule to make modules -# -ALL_MOBJS = $(MX_OBJS) $(M_OBJS) -modules: $(ALL_MOBJS) dummy -ifdef MOD_SUB_DIRS - set -e; for i in $(MOD_SUB_DIRS); do $(MAKE) -C $$i modules; done -endif - -modules_install: $(ALL_MOBJS) dummy -ifdef MOD_SUB_DIRS - set -e; for i in $(MOD_SUB_DIRS); do $(MAKE) -C $$i modules_install; done -endif -ifneq "$(strip $(ALL_MOBJS))" "" - mkdir -p $(MODDEST) - cp -p $(ALL_MOBJS) $(MODDEST) -endif - -# -# A rule to do nothing -# -dummy: - -# -# This is useful for testing -# -script: - $(SCRIPT) - -# -# This sets version suffixes on exported symbols -# Uses SYMTAB_OBJS -# Separate the object into "normal" objects and "exporting" objects -# Exporting objects are: all objects that define symbol tables -# -ifdef CONFIG_MODVERSIONS -SYMTAB_OBJS = $(LX_OBJS) $(OX_OBJS) $(MX_OBJS) -ifneq "$(strip $(SYMTAB_OBJS))" "" - -MODINCL = $(KERNELDIR)/include/linux/modules - -# The -w option (enable warnings) for /bin/genksyms will return here in 2.1 -$(MODINCL)/%.ver: %.c - @if [ ! -x /sbin/genksyms ]; then echo "Please read: Documentation/modules.txt"; fi - $(CC) $(CFLAGS) -E -D__GENKSYMS__ $< | /sbin/genksyms $(MODINCL) - -$(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)): $(KERNELDIR)/include/linux/autoconf.h - -$(KERNELDIR)/include/linux/modversions.h: $(addprefix $(MODINCL)/,$(SYMTAB_OBJS:.o=.ver)) - @echo updating $(KERNELDIR)/include/linux/modversions.h - @(echo "#ifdef MODVERSIONS";\ - echo "#undef CONFIG_MODVERSIONS";\ - echo "#define CONFIG_MODVERSIONS";\ - echo "#ifndef _set_ver";\ - echo "#define _set_ver(sym,vers) sym ## _R ## vers";\ - echo "#endif";\ - cd $(KERNELDIR)/include/linux/modules; for f in *.ver;\ - do echo "#include "; done; \ - echo "#undef CONFIG_MODVERSIONS";\ - echo "#endif") \ - > $(KERNELDIR)/include/linux/modversions.h - -$(MX_OBJS): $(KERNELDIR)/include/linux/modversions.h - $(CC) $(CFLAGS) -DEXPORT_SYMTAB -c $(@:.o=.c) - -$(LX_OBJS) $(OX_OBJS): $(KERNELDIR)/include/linux/modversions.h - $(CC) $(CFLAGS) -DMODVERSIONS -DEXPORT_SYMTAB -c $(@:.o=.c) - -dep fastdep: $(KERNELDIR)/include/linux/modversions.h - -endif -$(M_OBJS): $(KERNELDIR)/include/linux/modversions.h -ifdef MAKING_MODULES -$(O_OBJS) $(L_OBJS): $(KERNELDIR)/include/linux/modversions.h -endif -# This is needed to ensure proper dependency for multipart modules such as -# fs/ext.o. (Otherwise, not all subobjects will be recompiled when -# version information changes.) - -endif - -# -# include dependency files they exist -# -ifeq (.depend,$(wildcard .depend)) -include .depend -endif - -ifeq ($(KERNELDIR)/.hdepend,$(wildcard $(KERNELDIR)/.hdepend)) -include $(KERNELDIR)/.hdepend -endif diff --git a/do_indent b/do_indent deleted file mode 100755 index 74e39c40..00000000 --- a/do_indent +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh -INDENT=`which indent` -SED=`which sed` -if test "$INDENT" = "" ; then - echo programm indent missing - exit -fi -if test "$SED" = "" ; then - echo programm sed missing - exit -fi -BACKUP=false -CHECK=false -case "$1" in - -b) - BACKUP=true - shift - ;; - -c) - CHECK=true - BACKUP=false - shift - ;; -esac - -formatiere() { - if $CHECK ; then - OUT=$1.idout - else - OUT=$1 - fi - cp $1 $1\~ - cat $1\~ | $INDENT -kr -i8 -cli8 -psl -lp | \ - $SED -e 's/^ / /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/^\( \+\) /\1 /g' \ - -e 's/[ ]\+$//g' > $OUT - if $CHECK ; then - diff -u $1\~ $OUT - rm $OUT - fi - if ! $BACKUP ; then - rm $1\~ - fi -} - -for f in $* ; do - formatiere $f -done - diff --git a/drivers/isdn/Config.in b/drivers/isdn/Config.in deleted file mode 100644 index 4cd73e47..00000000 --- a/drivers/isdn/Config.in +++ /dev/null @@ -1,147 +0,0 @@ -# -# ISDN device configuration -# -if [ "$CONFIG_INET" != "n" ]; then - bool ' Support synchronous PPP' CONFIG_ISDN_PPP - if [ "$CONFIG_ISDN_PPP" != "n" ]; then - bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ - bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP - fi -fi -bool ' Support audio via ISDN' CONFIG_ISDN_AUDIO -if [ "$CONFIG_ISDN_AUDIO" != "n" ]; then - bool ' Support AT-Fax Class 2 commands' CONFIG_ISDN_TTY_FAX -fi -if [ "$CONFIG_X25" != "n" ]; then - bool ' X.25 PLP on top of ISDN' CONFIG_ISDN_X25 -fi - -if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - 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 ' TCP keepalive detect and response (ip4 only)' CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - bool ' Drop frames s_addr != iface_addr (ip4 only)' CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR - if [ "$CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR" != "n" ]; then - bool ' Rewrite socket and frame saddr-field (tcp-ip4 only and very experimental)' CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR - bool ' Rewrite socket and frame saddr-field (udp-ip4 only and very experimental)' CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR - fi - bool ' RX dont reset hanguptimeout' CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - bool ' Support (device-channel)<->(bind-groups)' CONFIG_ISDN_WITH_ABC_ICALL_BIND - bool ' Skip channel if used external (dial only)' CONFIG_ISDN_WITH_ABC_CH_EXTINUSE - bool ' Support interface-auto-disble if config-error' CONFIG_ISDN_WITH_ABC_CONN_ERROR - 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 - bool ' Limit on the line frames to 2' CONFIG_ISDN_WITH_ABC_FRAME_LIMIT - if [ "$CONFIG_ISDN_PPP" != "n" ]; then - bool ' Enable Compression with rawip and x75i' CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS - fi - fi - endmenu -fi - -mainmenu_option next_comment -comment 'ISDN feature submodules' - dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN - bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION -endmenu - -comment 'low-level hardware drivers' - -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 - comment ' D-channel protocol features' - bool ' HiSax Support for EURO/DSS1' CONFIG_HISAX_EURO - if [ "$CONFIG_HISAX_EURO" != "n" ]; then - bool ' Support for german chargeinfo' CONFIG_DE_AOC - bool ' Disable sending complete' CONFIG_HISAX_NO_SENDCOMPLETE - bool ' Disable sending low layer compatibility' CONFIG_HISAX_NO_LLC - bool ' Disable keypad protocol option' CONFIG_HISAX_NO_KEYPAD - fi - bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6 - comment ' HiSax supported cards' - 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 ' 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 - bool ' HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI - bool ' Winbond W6692 based cards' CONFIG_HISAX_W6692 - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX -# bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU - if [ "$ARCH" = "sparc" -o "$ARCH" = "sparc64" ]; then - bool ' Am7930' CONFIG_HISAX_AMD7930 - fi - fi -fi -endmenu - -mainmenu_option next_comment -comment 'Active ISDN cards' -dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN -dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN -if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - dep_tristate 'Spellcaster support (EXPERIMENTAL)' CONFIG_ISDN_DRV_SC $CONFIG_ISDN - dep_tristate 'IBM Active 2000 support (EXPERIMENTAL)' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN -fi -dep_tristate 'Eicon active card support' CONFIG_ISDN_DRV_EICON $CONFIG_ISDN -if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then - bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA -fi -dep_tristate 'CAPI2.0 support' CONFIG_ISDN_CAPI $CONFIG_ISDN -if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - bool 'CAPI2.0 Middleware support' CONFIG_ISDN_CAPI_MIDDLEWARE - if [ "$CONFIG_ISDN_CAPI_MIDDLEWARE" != "n" ]; then - bool 'CAPI2.0 filesystem support' CONFIG_ISDN_CAPIFS - fi -fi -if [ "$CONFIG_ISDN_CAPI" != "n" ]; then - bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA - bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI - if [ "$CONFIG_ISDN_DRV_AVMB1_B1PCI" != "n" ]; then - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - bool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - fi - fi - bool ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA - bool ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - bool ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI - if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then - bool ' AVM C4 support' CONFIG_ISDN_DRV_AVMB1_C4 - fi - bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON -fi -if [ "$CONFIG_PROC_FS" != "n" ]; then -if [ "$CONFIG_MODULES" != "n" ]; then - bool 'Hypercope HYSDN cards (Champ, Ergo, Metro) support (module)' CONFIG_HYSDN -fi -fi -endmenu diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile deleted file mode 100644 index eaabb8e0..00000000 --- a/drivers/isdn/Makefile +++ /dev/null @@ -1,151 +0,0 @@ -SUB_DIRS := -MOD_SUB_DIRS := -ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon divert hysdn - -L_OBJS := -LX_OBJS := -M_OBJS := -MX_OBJS := -O_OBJS := -OX_OBJS := -L_TARGET := -O_TARGET := - -ifeq ($(CONFIG_ISDN),y) - L_TARGET := isdn.a - L_OBJS += isdn_net.o isdn_tty.o isdn_cards.o isdn_v110.o - LX_OBJS += isdn_common.o - ifdef CONFIG_ISDN_PPP - L_OBJS += isdn_ppp.o - endif - ifdef CONFIG_ISDN_X25 - L_OBJS += isdn_x25iface.o - L_OBJS += isdn_concap.o - endif - ifdef CONFIG_ISDN_AUDIO - L_OBJS += isdn_audio.o - ifdef CONFIG_ISDN_TTY_FAX - L_OBJS += isdn_ttyfax.o - endif - endif - ifdef CONFIG_ISDN_WITH_ABC - L_OBJS += isdn_dwabc.o - endif -else - ifeq ($(CONFIG_ISDN),m) - M_OBJS += isdn.o - O_TARGET += isdn.o - O_OBJS += isdn_net.o isdn_tty.o isdn_v110.o - OX_OBJS += isdn_common.o - ifdef CONFIG_ISDN_PPP - O_OBJS += isdn_ppp.o - M_OBJS += isdn_bsdcomp.o - endif - ifdef CONFIG_ISDN_X25 - O_OBJS += isdn_x25iface.o - O_OBJS += isdn_concap.o - endif - ifdef CONFIG_ISDN_AUDIO - O_OBJS += isdn_audio.o - ifdef CONFIG_ISDN_TTY_FAX - O_OBJS += isdn_ttyfax.o - endif - endif - ifdef CONFIG_ISDN_WITH_ABC - O_OBJS += isdn_dwabc.o - endif - endif -endif - -ifeq ($(CONFIG_ISDN_DIVERSION),y) - ifeq ($(CONFIG_MODULES),y) - MOD_SUB_DIRS += divert - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_HISAX),y) - L_OBJS += hisax/hisax.o - SUB_DIRS += hisax - MOD_SUB_DIRS += hisax -else - ifeq ($(CONFIG_ISDN_DRV_HISAX),m) - MOD_SUB_DIRS += hisax - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_ICN),y) - L_OBJS += icn/icn_obj.o - SUB_DIRS += icn - MOD_SUB_DIRS += icn -else - ifeq ($(CONFIG_ISDN_DRV_ICN),m) - MOD_SUB_DIRS += icn - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_PCBIT),y) - L_OBJS += pcbit/pcbit.o - SUB_DIRS += pcbit - MOD_SUB_DIRS += pcbit -else - ifeq ($(CONFIG_ISDN_DRV_PCBIT),m) - MOD_SUB_DIRS += pcbit - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_SC),y) - L_OBJS += sc/sc.o - SUB_DIRS += sc - MOD_SUB_DIRS += sc -else - ifeq ($(CONFIG_ISDN_DRV_SC),m) - MOD_SUB_DIRS += sc - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_AVMB1),y) - L_OBJS += avmb1/avmb1.o - SUB_DIRS += avmb1 - MOD_SUB_DIRS += avmb1 -else - ifeq ($(CONFIG_ISDN_DRV_AVMB1),m) - MOD_SUB_DIRS += avmb1 - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_LOOP),y) - L_OBJS += isdnloop/isdnloop.o - SUB_DIRS += isdnloop - MOD_SUB_DIRS += isdnloop -else - ifeq ($(CONFIG_ISDN_DRV_LOOP),m) - MOD_SUB_DIRS += isdnloop - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_ACT2000),y) - L_OBJS += act2000/act2000.o - SUB_DIRS += act2000 - MOD_SUB_DIRS += act2000 -else - ifeq ($(CONFIG_ISDN_DRV_ACT2000),m) - MOD_SUB_DIRS += act2000 - endif -endif - -ifeq ($(CONFIG_ISDN_DRV_EICON),y) - L_OBJS += eicon/eicon.o - SUB_DIRS += eicon - MOD_SUB_DIRS += eicon -else - ifeq ($(CONFIG_ISDN_DRV_EICON),m) - MOD_SUB_DIRS += eicon - endif -endif - -ifeq ($(CONFIG_HYSDN),y) - MOD_SUB_DIRS += hysdn -endif - -include $(TOPDIR)/Rules.make - diff --git a/drivers/isdn/act2000/Makefile b/drivers/isdn/act2000/Makefile deleted file mode 100644 index 0e3c4a7e..00000000 --- a/drivers/isdn/act2000/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -L_OBJS := -M_OBJS := -O_OBJS := module.o capi.o act2000_isa.o - -O_TARGET := -ifeq ($(CONFIG_ISDN_DRV_ACT2000),y) - O_TARGET += act2000.o -else - ifeq ($(CONFIG_ISDN_DRV_ACT2000),m) - O_TARGET += act2000.o - M_OBJS = act2000.o - endif -endif - -include $(TOPDIR)/Rules.make diff --git a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h deleted file mode 100644 index ad10825b..00000000 --- a/drivers/isdn/act2000/act2000.h +++ /dev/null @@ -1,240 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Thanks to Friedemann Baitinger and IBM Germany - * - * 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. - * - * $Log$ - * Revision 1.6 1998/11/05 22:12:38 fritz - * Changed mail-address. - * - * Revision 1.5 1997/10/09 22:22:59 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.4 1997/09/25 17:25:37 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.3 1997/09/24 23:11:43 fritz - * Optimized IRQ load and polling-mode. - * - * Revision 1.2 1997/09/24 19:44:12 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.1 1997/09/23 18:00:05 fritz - * New driver for IBM Active 2000. - * - */ - -#ifndef act2000_h -#define act2000_h - -#ifdef __KERNEL__ -/* Kernel includes */ - -#include -#include -#endif - -#define ACT2000_IOCTL_SETPORT 1 -#define ACT2000_IOCTL_GETPORT 2 -#define ACT2000_IOCTL_SETIRQ 3 -#define ACT2000_IOCTL_GETIRQ 4 -#define ACT2000_IOCTL_SETBUS 5 -#define ACT2000_IOCTL_GETBUS 6 -#define ACT2000_IOCTL_SETPROTO 7 -#define ACT2000_IOCTL_GETPROTO 8 -#define ACT2000_IOCTL_SETMSN 9 -#define ACT2000_IOCTL_GETMSN 10 -#define ACT2000_IOCTL_LOADBOOT 11 -#define ACT2000_IOCTL_ADDCARD 12 - -#define ACT2000_IOCTL_TEST 98 -#define ACT2000_IOCTL_DEBUGVAR 99 - -#define ACT2000_BUS_ISA 1 -#define ACT2000_BUS_MCA 2 -#define ACT2000_BUS_PCMCIA 3 - -/* Struct for adding new cards */ -typedef struct act2000_cdef { - int bus; - int port; - int irq; - char id[10]; -} act2000_cdef; - -/* Struct for downloading firmware */ -typedef struct act2000_ddef { - int length; /* Length of code */ - char *buffer; /* Ptr. to code */ -} act2000_ddef; - -typedef struct act2000_fwid { - char isdn[4]; - char revlen[2]; - char revision[504]; -} act2000_fwid; - -#if defined(__KERNEL__) || defined(__DEBUGVAR__) - -#ifdef __KERNEL__ -/* Kernel includes */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif /* __KERNEL__ */ - -#define ACT2000_PORTLEN 8 - -#define ACT2000_FLAGS_RUNNING 1 /* Cards driver activated */ -#define ACT2000_FLAGS_PVALID 2 /* Cards port is valid */ -#define ACT2000_FLAGS_IVALID 4 /* Cards irq is valid */ -#define ACT2000_FLAGS_LOADED 8 /* Firmware loaded */ - -#define ACT2000_BCH 2 /* # of channels per card */ - -/* D-Channel states */ -#define ACT2000_STATE_NULL 0 -#define ACT2000_STATE_ICALL 1 -#define ACT2000_STATE_OCALL 2 -#define ACT2000_STATE_IWAIT 3 -#define ACT2000_STATE_OWAIT 4 -#define ACT2000_STATE_IBWAIT 5 -#define ACT2000_STATE_OBWAIT 6 -#define ACT2000_STATE_BWAIT 7 -#define ACT2000_STATE_BHWAIT 8 -#define ACT2000_STATE_BHWAIT2 9 -#define ACT2000_STATE_DHWAIT 10 -#define ACT2000_STATE_DHWAIT2 11 -#define ACT2000_STATE_BSETUP 12 -#define ACT2000_STATE_ACTIVE 13 - -#define ACT2000_MAX_QUEUED 8000 /* 2 * maxbuff */ - -#define ACT2000_LOCK_TX 0 -#define ACT2000_LOCK_RX 1 - -typedef struct act2000_chan { - unsigned short callref; /* Call Reference */ - unsigned short fsm_state; /* Current D-Channel state */ - unsigned short eazmask; /* EAZ-Mask for this Channel */ - short queued; /* User-Data Bytes in TX queue */ - unsigned short plci; - unsigned short ncci; - unsigned char l2prot; /* Layer 2 protocol */ - unsigned char l3prot; /* Layer 3 protocol */ -} act2000_chan; - -typedef struct msn_entry { - char eaz; - char msn[16]; - struct msn_entry * next; -} msn_entry; - -typedef struct irq_data_isa { - __u8 *rcvptr; - __u16 rcvidx; - __u16 rcvlen; - struct sk_buff *rcvskb; - __u8 rcvignore; - __u8 rcvhdr[8]; -} irq_data_isa; - -typedef union irq_data { - irq_data_isa isa; -} irq_data; - -/* - * Per card driver data - */ -typedef struct act2000_card { - unsigned short port; /* Base-port-address */ - unsigned short irq; /* Interrupt */ - u_char ptype; /* Protocol type (1TR6 or Euro) */ - u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */ - struct act2000_card *next; /* Pointer to next device struct */ - int myid; /* Driver-Nr. assigned by linklevel */ - unsigned long flags; /* Statusflags */ - unsigned long ilock; /* Semaphores for IRQ-Routines */ - struct sk_buff_head rcvq; /* Receive-Message queue */ - struct sk_buff_head sndq; /* Send-Message queue */ - struct sk_buff_head ackq; /* Data-Ack-Message queue */ - u_char *ack_msg; /* Ptr to User Data in User skb */ - __u16 need_b3ack; /* Flag: Need ACK for current skb */ - struct sk_buff *sbuf; /* skb which is currently sent */ - struct timer_list ptimer; /* Poll timer */ - struct tq_struct snd_tq; /* Task struct for xmit bh */ - struct tq_struct rcv_tq; /* Task struct for rcv bh */ - struct tq_struct poll_tq; /* Task struct for polled rcv bh */ - msn_entry *msn_list; - unsigned short msgnum; /* Message number fur sending */ - act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */ - char status_buf[256]; /* Buffer for status messages */ - char *status_buf_read; - char *status_buf_write; - char *status_buf_end; - irq_data idat; /* Data used for IRQ handler */ - isdn_if interface; /* Interface to upper layer */ - char regname[35]; /* Name used for request_region */ -} act2000_card; - -extern __inline__ void act2000_schedule_tx(act2000_card *card) -{ - queue_task(&card->snd_tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -extern __inline__ void act2000_schedule_rx(act2000_card *card) -{ - queue_task(&card->rcv_tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -extern __inline__ void act2000_schedule_poll(act2000_card *card) -{ - queue_task(&card->poll_tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -extern char *act2000_find_eaz(act2000_card *, char); - -#endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */ -#endif /* act2000_h */ diff --git a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c deleted file mode 100644 index 5923e858..00000000 --- a/drivers/isdn/act2000/act2000_isa.c +++ /dev/null @@ -1,538 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Thanks to Friedemann Baitinger and IBM Germany - * - * 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. - * - * $Log$ - * Revision 1.9 1999/09/04 06:20:04 keil - * Changes from kernel set_current_state() - * - * Revision 1.8 1999/01/05 18:29:25 he - * merged remaining schedule_timeout() changes from 2.1.127 - * - * Revision 1.7 1998/11/05 22:12:41 fritz - * Changed mail-address. - * - * Revision 1.6 1998/06/17 19:51:09 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.5 1998/02/12 23:06:47 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.4 1997/10/09 22:23:00 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.3 1997/09/25 17:25:38 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.2 1997/09/24 23:11:44 fritz - * Optimized IRQ load and polling-mode. - * - * Revision 1.1 1997/09/23 18:00:05 fritz - * New driver for IBM Active 2000. - * - */ - -#define __NO_VERSION__ -#include "act2000.h" -#include "act2000_isa.h" -#include "capi.h" - -static act2000_card *irq2card_map[16] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static int act2000_isa_irqs[] = -{ - 3, 5, 7, 10, 11, 12, 15 -}; -#define ISA_NRIRQS (sizeof(act2000_isa_irqs)/sizeof(int)) - -static void -act2000_isa_delay(long t) -{ - sti(); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(t); - sti(); -} - -/* - * Reset Controller, then try to read the Card's signature. - + Return: - * 1 = Signature found. - * 0 = Signature not found. - */ -static int -act2000_isa_reset(unsigned short portbase) -{ - unsigned char reg; - int i; - int found; - int serial = 0; - - found = 0; - if ((reg = inb(portbase + ISA_COR)) != 0xff) { - outb(reg | ISA_COR_RESET, portbase + ISA_COR); - mdelay(10); - outb(reg, portbase + ISA_COR); - mdelay(10); - - for (i = 0; i < 16; i++) { - if (inb(portbase + ISA_ISR) & ISA_ISR_SERIAL) - serial |= 0x10000; - serial >>= 1; - } - if (serial == ISA_SER_ID) - found++; - } - return found; -} - -int -act2000_isa_detect(unsigned short portbase) -{ - int ret = 0; - unsigned long flags; - - save_flags(flags); - cli(); - if (!check_region(portbase, ISA_REGION)) - ret = act2000_isa_reset(portbase); - restore_flags(flags); - return ret; -} - -static void -act2000_isa_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - act2000_card *card = irq2card_map[irq]; - u_char istatus; - - if (!card) { - printk(KERN_WARNING - "act2000: Spurious interrupt!\n"); - return; - } - istatus = (inb(ISA_PORT_ISR) & 0x07); - if (istatus & ISA_ISR_OUT) { - /* RX fifo has data */ - istatus &= ISA_ISR_OUT_MASK; - outb(0, ISA_PORT_SIS); - act2000_isa_receive(card); - outb(ISA_SIS_INT, ISA_PORT_SIS); - } - if (istatus & ISA_ISR_ERR) { - /* Error Interrupt */ - istatus &= ISA_ISR_ERR_MASK; - printk(KERN_WARNING "act2000: errIRQ\n"); - } - if (istatus) - printk(KERN_DEBUG "act2000: ?IRQ %d %02x\n", irq, istatus); -} - -static void -act2000_isa_select_irq(act2000_card * card) -{ - unsigned char reg; - - reg = (inb(ISA_PORT_COR) & ~ISA_COR_IRQOFF) | ISA_COR_PERR; - switch (card->irq) { - case 3: - reg = ISA_COR_IRQ03; - break; - case 5: - reg = ISA_COR_IRQ05; - break; - case 7: - reg = ISA_COR_IRQ07; - break; - case 10: - reg = ISA_COR_IRQ10; - break; - case 11: - reg = ISA_COR_IRQ11; - break; - case 12: - reg = ISA_COR_IRQ12; - break; - case 15: - reg = ISA_COR_IRQ15; - break; - } - outb(reg, ISA_PORT_COR); -} - -static void -act2000_isa_enable_irq(act2000_card * card) -{ - act2000_isa_select_irq(card); - /* Enable READ irq */ - outb(ISA_SIS_INT, ISA_PORT_SIS); -} - -/* - * Install interrupt handler, enable irq on card. - * If irq is -1, choose next free irq, else irq is given explicitely. - */ -int -act2000_isa_config_irq(act2000_card * card, short irq) -{ - int i; - unsigned long flags; - - if (card->flags & ACT2000_FLAGS_IVALID) { - free_irq(card->irq, NULL); - irq2card_map[card->irq] = NULL; - } - card->flags &= ~ACT2000_FLAGS_IVALID; - outb(ISA_COR_IRQOFF, ISA_PORT_COR); - if (!irq) - return 0; - save_flags(flags); - cli(); - if (irq == -1) { - /* Auto select */ - for (i = 0; i < ISA_NRIRQS; i++) { - if (!request_irq(act2000_isa_irqs[i], &act2000_isa_interrupt, 0, card->regname, NULL)) { - card->irq = act2000_isa_irqs[i]; - irq2card_map[card->irq] = card; - card->flags |= ACT2000_FLAGS_IVALID; - break; - } - } - } else { - /* Fixed irq */ - if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) { - card->irq = irq; - irq2card_map[card->irq] = card; - card->flags |= ACT2000_FLAGS_IVALID; - } - } - restore_flags(flags); - if (!card->flags & ACT2000_FLAGS_IVALID) { - printk(KERN_WARNING - "act2000: Could not request irq\n"); - return -EBUSY; - } else { - act2000_isa_select_irq(card); - /* Disable READ and WRITE irq */ - outb(0, ISA_PORT_SIS); - outb(0, ISA_PORT_SOS); - } - return 0; -} - -int -act2000_isa_config_port(act2000_card * card, unsigned short portbase) -{ - if (card->flags & ACT2000_FLAGS_PVALID) { - release_region(card->port, ISA_REGION); - card->flags &= ~ACT2000_FLAGS_PVALID; - } - if (!check_region(portbase, ISA_REGION)) { - request_region(portbase, ACT2000_PORTLEN, card->regname); - card->port = portbase; - card->flags |= ACT2000_FLAGS_PVALID; - return 0; - } - return -EBUSY; -} - -/* - * Release ressources, used by an adaptor. - */ -void -act2000_isa_release(act2000_card * card) -{ - unsigned long flags; - - save_flags(flags); - cli(); - if (card->flags & ACT2000_FLAGS_IVALID) { - free_irq(card->irq, NULL); - irq2card_map[card->irq] = NULL; - } - card->flags &= ~ACT2000_FLAGS_IVALID; - if (card->flags & ACT2000_FLAGS_PVALID) - release_region(card->port, ISA_REGION); - card->flags &= ~ACT2000_FLAGS_PVALID; - restore_flags(flags); -} - -static int -act2000_isa_writeb(act2000_card * card, u_char data) -{ - u_char timeout = 40; - - while (timeout) { - if (inb(ISA_PORT_SOS) & ISA_SOS_READY) { - outb(data, ISA_PORT_SDO); - return 0; - } else { - timeout--; - udelay(10); - } - } - return 1; -} - -static int -act2000_isa_readb(act2000_card * card, u_char * data) -{ - u_char timeout = 40; - - while (timeout) { - if (inb(ISA_PORT_SIS) & ISA_SIS_READY) { - *data = inb(ISA_PORT_SDI); - return 0; - } else { - timeout--; - udelay(10); - } - } - return 1; -} - -void -act2000_isa_receive(act2000_card *card) -{ - u_char c; - - if (test_and_set_bit(ACT2000_LOCK_RX, (void *) &card->ilock) != 0) - return; - while (!act2000_isa_readb(card, &c)) { - if (card->idat.isa.rcvidx < 8) { - card->idat.isa.rcvhdr[card->idat.isa.rcvidx++] = c; - if (card->idat.isa.rcvidx == 8) { - int valid = actcapi_chkhdr(card, (actcapi_msghdr *)&card->idat.isa.rcvhdr); - - if (valid) { - card->idat.isa.rcvlen = ((actcapi_msghdr *)&card->idat.isa.rcvhdr)->len; - card->idat.isa.rcvskb = dev_alloc_skb(card->idat.isa.rcvlen); - if (card->idat.isa.rcvskb == NULL) { - card->idat.isa.rcvignore = 1; - printk(KERN_WARNING - "act2000_isa_receive: no memory\n"); - test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock); - return; - } - memcpy(skb_put(card->idat.isa.rcvskb, 8), card->idat.isa.rcvhdr, 8); - card->idat.isa.rcvptr = skb_put(card->idat.isa.rcvskb, card->idat.isa.rcvlen - 8); - } else { - card->idat.isa.rcvidx = 0; - printk(KERN_WARNING - "act2000_isa_receive: Invalid CAPI msg\n"); - { - int i; __u8 *p; __u8 *c; __u8 tmp[30]; - for (i = 0, p = (__u8 *)&card->idat.isa.rcvhdr, c = tmp; i < 8; i++) - c += sprintf(c, "%02x ", *(p++)); - printk(KERN_WARNING "act2000_isa_receive: %s\n", tmp); - } - } - } - } else { - if (!card->idat.isa.rcvignore) - *card->idat.isa.rcvptr++ = c; - if (++card->idat.isa.rcvidx >= card->idat.isa.rcvlen) { - if (!card->idat.isa.rcvignore) { - skb_queue_tail(&card->rcvq, card->idat.isa.rcvskb); - act2000_schedule_rx(card); - } - card->idat.isa.rcvidx = 0; - card->idat.isa.rcvlen = 8; - card->idat.isa.rcvignore = 0; - card->idat.isa.rcvskb = NULL; - card->idat.isa.rcvptr = card->idat.isa.rcvhdr; - } - } - } - if (!(card->flags & ACT2000_FLAGS_IVALID)) { - /* In polling mode, schedule myself */ - if ((card->idat.isa.rcvidx) && - (card->idat.isa.rcvignore || - (card->idat.isa.rcvidx < card->idat.isa.rcvlen))) - act2000_schedule_poll(card); - } - test_and_clear_bit(ACT2000_LOCK_RX, (void *) &card->ilock); -} - -void -act2000_isa_send(act2000_card * card) -{ - unsigned long flags; - struct sk_buff *skb; - actcapi_msg *msg; - int l; - - if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0) - return; - while (1) { - save_flags(flags); - cli(); - if (!(card->sbuf)) { - if ((card->sbuf = skb_dequeue(&card->sndq))) { - card->ack_msg = card->sbuf->data; - msg = (actcapi_msg *)card->sbuf->data; - if ((msg->hdr.cmd.cmd == 0x86) && - (msg->hdr.cmd.subcmd == 0) ) { - /* Save flags in message */ - card->need_b3ack = msg->msg.data_b3_req.flags; - msg->msg.data_b3_req.flags = 0; - } - } - } - restore_flags(flags); - if (!(card->sbuf)) { - /* No more data to send */ - test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock); - return; - } - skb = card->sbuf; - l = 0; - 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); - return; - } - skb_pull(skb, 1); - l++; - } - msg = (actcapi_msg *)card->ack_msg; - if ((msg->hdr.cmd.cmd == 0x86) && - (msg->hdr.cmd.subcmd == 0) ) { - /* - * If it's user data, reset data-ptr - * and put skb into ackq. - */ - skb->data = card->ack_msg; - /* Restore flags in message */ - msg->msg.data_b3_req.flags = card->need_b3ack; - skb_queue_tail(&card->ackq, skb); - } else - dev_kfree_skb(skb); - card->sbuf = NULL; -#if 0 - printk(KERN_DEBUG "act2000_isa_send: %d bytes\n", l); -#endif - } -} - -/* - * Get firmware ID, check for 'ISDN' signature. - */ -static int -act2000_isa_getid(act2000_card * card) -{ - - act2000_fwid fid; - u_char *p = (u_char *) & fid; - int count = 0; - - while (1) { - if (count > 510) - return -EPROTO; - if (act2000_isa_readb(card, p++)) - break; - count++; - } - if (count <= 20) { - printk(KERN_WARNING "act2000: No Firmware-ID!\n"); - return -ETIME; - } - *p = '\0'; - fid.revlen[0] = '\0'; - if (strcmp(fid.isdn, "ISDN")) { - printk(KERN_WARNING "act2000: Wrong Firmware-ID!\n"); - return -EPROTO; - } - if ((p = strchr(fid.revision, '\n'))) - *p = '\0'; - printk(KERN_INFO "act2000: Firmware-ID: %s\n", fid.revision); - if (card->flags & ACT2000_FLAGS_IVALID) { - printk(KERN_DEBUG "Enabling Interrupts ...\n"); - act2000_isa_enable_irq(card); - } - return 0; -} - -/* - * Download microcode into card, check Firmware signature. - */ -int -act2000_isa_download(act2000_card * card, act2000_ddef * cb) -{ - int length; - int ret; - int l; - int c; - long timeout; - u_char *b; - u_char *p; - u_char *buf; - act2000_ddef cblock; - - if (!act2000_isa_reset(card->port)) - return -ENXIO; - act2000_isa_delay(HZ / 2); - if ((ret = verify_area(VERIFY_READ, (void *) cb, sizeof(cblock)))) - return ret; - copy_from_user(&cblock, (char *) cb, sizeof(cblock)); - length = cblock.length; - p = cblock.buffer; - if ((ret = verify_area(VERIFY_READ, (void *) p, length))) - return ret; - buf = (u_char *) kmalloc(1024, GFP_KERNEL); - if (!buf) - return -ENOMEM; - timeout = 0; - while (length) { - l = (length > 1024) ? 1024 : length; - c = 0; - b = buf; - copy_from_user(buf, p, l); - while (c < l) { - if (act2000_isa_writeb(card, *b++)) { - printk(KERN_WARNING - "act2000: loader timed out" - " len=%d c=%d\n", length, c); - kfree(buf); - return -ETIME; - } - c++; - } - length -= l; - p += l; - } - kfree(buf); - act2000_isa_delay(HZ / 2); - return (act2000_isa_getid(card)); -} diff --git a/drivers/isdn/act2000/act2000_isa.h b/drivers/isdn/act2000/act2000_isa.h deleted file mode 100644 index e4fd9144..00000000 --- a/drivers/isdn/act2000/act2000_isa.h +++ /dev/null @@ -1,152 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version). - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Thanks to Friedemann Baitinger and IBM Germany - * - * 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. - * - * $Log$ - * Revision 1.2 1998/11/05 22:12:43 fritz - * Changed mail-address. - * - * Revision 1.1 1997/09/23 18:00:07 fritz - * New driver for IBM Active 2000. - * - */ - -#ifndef act2000_isa_h -#define act2000_isa_h - -#define ISA_POLL_LOOP 40 /* Try to read-write before give up */ - -typedef enum { - INT_NO_CHANGE = 0, /* Do not change the Mask */ - INT_ON = 1, /* Set to Enable */ - INT_OFF = 2, /* Set to Disable */ -} ISA_INT_T; - -/**************************************************************************/ -/* Configuration Register COR (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* Soft Res| IRQM | IRQ Select | N/A | WAIT |Proc err */ -/**************************************************************************/ -#define ISA_COR 0 /* Offset for ISA config register */ -#define ISA_COR_PERR 0x01 /* Processor Error Enabled */ -#define ISA_COR_WS 0x02 /* Insert Wait State if 1 */ -#define ISA_COR_IRQOFF 0x38 /* No Interrupt */ -#define ISA_COR_IRQ07 0x30 /* IRQ 7 Enable */ -#define ISA_COR_IRQ05 0x28 /* IRQ 5 Enable */ -#define ISA_COR_IRQ03 0x20 /* IRQ 3 Enable */ -#define ISA_COR_IRQ10 0x18 /* IRQ 10 Enable */ -#define ISA_COR_IRQ11 0x10 /* IRQ 11 Enable */ -#define ISA_COR_IRQ12 0x08 /* IRQ 12 Enable */ -#define ISA_COR_IRQ15 0x00 /* IRQ 15 Enable */ -#define ISA_COR_IRQPULSE 0x40 /* 0 = Level 1 = Pulse Interrupt */ -#define ISA_COR_RESET 0x80 /* Soft Reset for Transputer */ - -/**************************************************************************/ -/* Interrupt Source Register ISR (RO) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A |Err sig |Ser ID |IN Intr |Out Intr| Error */ -/**************************************************************************/ -#define ISA_ISR 1 /* Offset for Interrupt Register */ -#define ISA_ISR_ERR 0x01 /* Error Interrupt */ -#define ISA_ISR_OUT 0x02 /* Output Interrupt */ -#define ISA_ISR_INP 0x04 /* Input Interrupt */ -#define ISA_ISR_SERIAL 0x08 /* Read out Serial ID after Reset */ -#define ISA_ISR_ERRSIG 0x10 /* Error Signal Input */ -#define ISA_ISR_ERR_MASK 0xfe /* Mask Error Interrupt */ -#define ISA_ISR_OUT_MASK 0xfd /* Mask Output Interrupt */ -#define ISA_ISR_INP_MASK 0xfb /* Mask Input Interrupt */ - -/* Signature delivered after Reset at ISA_ISR_SERIAL (LSB first) */ -#define ISA_SER_ID 0x0201 /* ID for ISA Card */ - -/**************************************************************************/ -/* EEPROM Register EPR (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A |ROM Hold| ROM CS |ROM CLK | ROM IN |ROM Out */ -/**************************************************************************/ -#define ISA_EPR 2 /* Offset for this Register */ -#define ISA_EPR_OUT 0x01 /* Rome Register Out (RO) */ -#define ISA_EPR_IN 0x02 /* Rom Register In (WR) */ -#define ISA_EPR_CLK 0x04 /* Rom Clock (WR) */ -#define ISA_EPR_CS 0x08 /* Rom Cip Select (WR) */ -#define ISA_EPR_HOLD 0x10 /* Rom Hold Signal (WR) */ - -/**************************************************************************/ -/* EEPROM enable Register EER (unused) */ -/**************************************************************************/ -#define ISA_EER 3 /* Offset for this Register */ - -/**************************************************************************/ -/* SLC Data Input SDI (RO) */ -/**************************************************************************/ -#define ISA_SDI 4 /* Offset for this Register */ - -/**************************************************************************/ -/* SLC Data Output SDO (WO) */ -/**************************************************************************/ -#define ISA_SDO 5 /* Offset for this Register */ - -/**************************************************************************/ -/* IMS C011 Mode 2 Input Status Register for INMOS CPU SIS (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A | N/A | N/A | N/A |Int Ena |Data Pre */ -/**************************************************************************/ -#define ISA_SIS 6 /* Offset for this Register */ -#define ISA_SIS_READY 0x01 /* If 1 : data is available */ -#define ISA_SIS_INT 0x02 /* Enable Interrupt for READ */ - -/**************************************************************************/ -/* IMS C011 Mode 2 Output Status Register from INMOS CPU SOS (RW) */ -/**************************************************************************/ -/* 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 */ -/* N/A | N/A | N/A | N/A | N/A | N/A |Int Ena |Out Rdy */ -/**************************************************************************/ -#define ISA_SOS 7 /* Offset for this Register */ -#define ISA_SOS_READY 0x01 /* If 1 : we can write Data */ -#define ISA_SOS_INT 0x02 /* Enable Interrupt for WRITE */ - -#define ISA_REGION 8 /* Number of Registers */ - - -/* Macros for accessing ports */ -#define ISA_PORT_COR (card->port+ISA_COR) -#define ISA_PORT_ISR (card->port+ISA_ISR) -#define ISA_PORT_EPR (card->port+ISA_EPR) -#define ISA_PORT_EER (card->port+ISA_EER) -#define ISA_PORT_SDI (card->port+ISA_SDI) -#define ISA_PORT_SDO (card->port+ISA_SDO) -#define ISA_PORT_SIS (card->port+ISA_SIS) -#define ISA_PORT_SOS (card->port+ISA_SOS) - -/* Prototypes */ - -extern int act2000_isa_detect(unsigned short portbase); -extern int act2000_isa_config_irq(act2000_card * card, short irq); -extern int act2000_isa_config_port(act2000_card * card, unsigned short portbase); -extern int act2000_isa_download(act2000_card * card, act2000_ddef * cb); -extern void act2000_isa_release(act2000_card * card); -extern void act2000_isa_receive(act2000_card *card); -extern void act2000_isa_send(act2000_card *card); - -#endif /* act2000_isa_h */ diff --git a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c deleted file mode 100644 index 272c0294..00000000 --- a/drivers/isdn/act2000/capi.c +++ /dev/null @@ -1,1218 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * CAPI encoder/decoder - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Thanks to Friedemann Baitinger and IBM Germany - * - * 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. - * - * $Log$ - * Revision 1.7 1998/02/23 23:35:41 fritz - * Eliminated some compiler warnings. - * - * Revision 1.6 1998/02/12 23:06:50 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.5 1997/10/09 22:23:02 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.4 1997/09/25 17:25:39 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.3 1997/09/24 19:44:14 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.2 1997/09/23 19:41:24 fritz - * Disabled Logging of DATA_B3_IND/RESP/REQ/CONF Messages. - * - * Revision 1.1 1997/09/23 18:00:08 fritz - * New driver for IBM Active 2000. - * - */ - -#define __NO_VERSION__ -#include "act2000.h" -#include "capi.h" - -static actcapi_msgdsc valid_msg[] = { - {{ 0x86, 0x02}, "DATA_B3_IND"}, /* DATA_B3_IND/CONF must be first because of speed!!! */ - {{ 0x86, 0x01}, "DATA_B3_CONF"}, - {{ 0x02, 0x01}, "CONNECT_CONF"}, - {{ 0x02, 0x02}, "CONNECT_IND"}, - {{ 0x09, 0x01}, "CONNECT_INFO_CONF"}, - {{ 0x03, 0x02}, "CONNECT_ACTIVE_IND"}, - {{ 0x04, 0x01}, "DISCONNECT_CONF"}, - {{ 0x04, 0x02}, "DISCONNECT_IND"}, - {{ 0x05, 0x01}, "LISTEN_CONF"}, - {{ 0x06, 0x01}, "GET_PARAMS_CONF"}, - {{ 0x07, 0x01}, "INFO_CONF"}, - {{ 0x07, 0x02}, "INFO_IND"}, - {{ 0x08, 0x01}, "DATA_CONF"}, - {{ 0x08, 0x02}, "DATA_IND"}, - {{ 0x40, 0x01}, "SELECT_B2_PROTOCOL_CONF"}, - {{ 0x80, 0x01}, "SELECT_B3_PROTOCOL_CONF"}, - {{ 0x81, 0x01}, "LISTEN_B3_CONF"}, - {{ 0x82, 0x01}, "CONNECT_B3_CONF"}, - {{ 0x82, 0x02}, "CONNECT_B3_IND"}, - {{ 0x83, 0x02}, "CONNECT_B3_ACTIVE_IND"}, - {{ 0x84, 0x01}, "DISCONNECT_B3_CONF"}, - {{ 0x84, 0x02}, "DISCONNECT_B3_IND"}, - {{ 0x85, 0x01}, "GET_B3_PARAMS_CONF"}, - {{ 0x01, 0x01}, "RESET_B3_CONF"}, - {{ 0x01, 0x02}, "RESET_B3_IND"}, - /* {{ 0x87, 0x02, "HANDSET_IND"}, not implemented */ - {{ 0xff, 0x01}, "MANUFACTURER_CONF"}, - {{ 0xff, 0x02}, "MANUFACTURER_IND"}, -#ifdef DEBUG_MSG - /* Requests */ - {{ 0x01, 0x00}, "RESET_B3_REQ"}, - {{ 0x02, 0x00}, "CONNECT_REQ"}, - {{ 0x04, 0x00}, "DISCONNECT_REQ"}, - {{ 0x05, 0x00}, "LISTEN_REQ"}, - {{ 0x06, 0x00}, "GET_PARAMS_REQ"}, - {{ 0x07, 0x00}, "INFO_REQ"}, - {{ 0x08, 0x00}, "DATA_REQ"}, - {{ 0x09, 0x00}, "CONNECT_INFO_REQ"}, - {{ 0x40, 0x00}, "SELECT_B2_PROTOCOL_REQ"}, - {{ 0x80, 0x00}, "SELECT_B3_PROTOCOL_REQ"}, - {{ 0x81, 0x00}, "LISTEN_B3_REQ"}, - {{ 0x82, 0x00}, "CONNECT_B3_REQ"}, - {{ 0x84, 0x00}, "DISCONNECT_B3_REQ"}, - {{ 0x85, 0x00}, "GET_B3_PARAMS_REQ"}, - {{ 0x86, 0x00}, "DATA_B3_REQ"}, - {{ 0xff, 0x00}, "MANUFACTURER_REQ"}, - /* Responses */ - {{ 0x01, 0x03}, "RESET_B3_RESP"}, - {{ 0x02, 0x03}, "CONNECT_RESP"}, - {{ 0x03, 0x03}, "CONNECT_ACTIVE_RESP"}, - {{ 0x04, 0x03}, "DISCONNECT_RESP"}, - {{ 0x07, 0x03}, "INFO_RESP"}, - {{ 0x08, 0x03}, "DATA_RESP"}, - {{ 0x82, 0x03}, "CONNECT_B3_RESP"}, - {{ 0x83, 0x03}, "CONNECT_B3_ACTIVE_RESP"}, - {{ 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}, -}; -#define num_valid_msg (sizeof(valid_msg)/sizeof(actcapi_msgdsc)) -#define num_valid_imsg 27 /* MANUFACTURER_IND */ - -/* - * Check for a valid incoming CAPI message. - * Return: - * 0 = Invalid message - * 1 = Valid message, no B-Channel-data - * 2 = Valid message, B-Channel-data - */ -int -actcapi_chkhdr(act2000_card * card, actcapi_msghdr *hdr) -{ - int i; - - if (hdr->applicationID != 1) - return 0; - if (hdr->len < 9) - return 0; - for (i = 0; i < num_valid_imsg; i++) - if ((hdr->cmd.cmd == valid_msg[i].cmd.cmd) && - (hdr->cmd.subcmd == valid_msg[i].cmd.subcmd)) { - return (i?1:2); - } - return 0; -} - -#define ACTCAPI_MKHDR(l, c, s) { \ - skb = alloc_skb(l + 8, GFP_ATOMIC); \ - if (skb) { \ - m = (actcapi_msg *)skb_put(skb, l + 8); \ - m->hdr.len = l + 8; \ - m->hdr.applicationID = 1; \ - m->hdr.cmd.cmd = c; \ - m->hdr.cmd.subcmd = s; \ - m->hdr.msgnum = actcapi_nextsmsg(card); \ - } \ -} - -#define ACTCAPI_CHKSKB if (!skb) { \ - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); \ - return; \ -} - -#define ACTCAPI_QUEUE_TX { \ - actcapi_debug_msg(skb, 1); \ - skb_queue_tail(&card->sndq, skb); \ - act2000_schedule_tx(card); \ -} - -int -actcapi_listen_req(act2000_card *card) -{ - __u16 eazmask = 0; - int i; - actcapi_msg *m; - struct sk_buff *skb; - - for (i = 0; i < ACT2000_BCH; i++) - eazmask |= card->bch[i].eazmask; - ACTCAPI_MKHDR(9, 0x05, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.listen_req.controller = 0; - m->msg.listen_req.infomask = 0x3f; /* All information */ - m->msg.listen_req.eazmask = eazmask; - m->msg.listen_req.simask = (eazmask)?0x86:0; /* All SI's */ - ACTCAPI_QUEUE_TX; - return 0; -} - -int -actcapi_connect_req(act2000_card *card, act2000_chan *chan, char *phone, - char eaz, int si1, int si2) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR((11 + strlen(phone)), 0x02, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - chan->fsm_state = ACT2000_STATE_NULL; - return -ENOMEM; - } - m->msg.connect_req.controller = 0; - m->msg.connect_req.bchan = 0x83; - m->msg.connect_req.infomask = 0x3f; - m->msg.connect_req.si1 = si1; - m->msg.connect_req.si2 = si2; - m->msg.connect_req.eaz = eaz?eaz:'0'; - m->msg.connect_req.addr.len = strlen(phone) + 1; - m->msg.connect_req.addr.tnp = 0x81; - memcpy(m->msg.connect_req.addr.num, phone, strlen(phone)); - chan->callref = m->hdr.msgnum; - ACTCAPI_QUEUE_TX; - return 0; -} - -static void -actcapi_connect_b3_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(17, 0x82, 0x00); - ACTCAPI_CHKSKB; - m->msg.connect_b3_req.plci = chan->plci; - memset(&m->msg.connect_b3_req.ncpi, 0, - sizeof(m->msg.connect_b3_req.ncpi)); - m->msg.connect_b3_req.ncpi.len = 13; - m->msg.connect_b3_req.ncpi.modulo = 8; - ACTCAPI_QUEUE_TX; -} - -/* - * Set net type (1TR6) or (EDSS1) - */ -int -actcapi_manufacturer_req_net(act2000_card *card) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(5, 0xff, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_net.manuf_msg = 0x11; - m->msg.manufacturer_req_net.controller = 1; - m->msg.manufacturer_req_net.nettype = (card->ptype == ISDN_PTYPE_EURO)?1:0; - ACTCAPI_QUEUE_TX; - printk(KERN_INFO "act2000 %s: D-channel protocol now %s\n", - card->interface.id, (card->ptype == ISDN_PTYPE_EURO)?"euro":"1tr6"); - card->interface.features &= - ~(ISDN_FEATURE_P_UNKNOWN | ISDN_FEATURE_P_EURO | ISDN_FEATURE_P_1TR6); - card->interface.features |= - ((card->ptype == ISDN_PTYPE_EURO)?ISDN_FEATURE_P_EURO:ISDN_FEATURE_P_1TR6); - return 0; -} - -/* - * Switch V.42 on or off - */ -int -actcapi_manufacturer_req_v42(act2000_card *card, ulong arg) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(8, 0xff, 0x00); - if (!skb) { - - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_v42.manuf_msg = 0x10; - m->msg.manufacturer_req_v42.controller = 0; - m->msg.manufacturer_req_v42.v42control = (arg?1:0); - ACTCAPI_QUEUE_TX; - return 0; -} - -/* - * Set error-handler - */ -int -actcapi_manufacturer_req_errh(act2000_card *card) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(4, 0xff, 0x00); - if (!skb) { - - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_err.manuf_msg = 0x03; - m->msg.manufacturer_req_err.controller = 0; - ACTCAPI_QUEUE_TX; - return 0; -} - -/* - * Set MSN-Mapping. - */ -int -actcapi_manufacturer_req_msn(act2000_card *card) -{ - msn_entry *p = card->msn_list; - actcapi_msg *m; - struct sk_buff *skb; - int len; - - while (p) { - int i; - - len = strlen(p->msn); - for (i = 0; i < 2; i++) { - ACTCAPI_MKHDR(6 + len, 0xff, 0x00); - if (!skb) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return -ENOMEM; - } - m->msg.manufacturer_req_msn.manuf_msg = 0x13 + i; - m->msg.manufacturer_req_msn.controller = 0; - m->msg.manufacturer_req_msn.msnmap.eaz = p->eaz; - m->msg.manufacturer_req_msn.msnmap.len = len; - memcpy(m->msg.manufacturer_req_msn.msnmap.msn, p->msn, len); - ACTCAPI_QUEUE_TX; - } - p = p->next; - } - return 0; -} - -void -actcapi_select_b2_protocol_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(10, 0x40, 0x00); - ACTCAPI_CHKSKB; - m->msg.select_b2_protocol_req.plci = chan->plci; - memset(&m->msg.select_b2_protocol_req.dlpd, 0, - sizeof(m->msg.select_b2_protocol_req.dlpd)); - m->msg.select_b2_protocol_req.dlpd.len = 6; - switch (chan->l2prot) { - case ISDN_PROTO_L2_TRANS: - m->msg.select_b2_protocol_req.protocol = 0x03; - m->msg.select_b2_protocol_req.dlpd.dlen = 4000; - break; - case ISDN_PROTO_L2_HDLC: - m->msg.select_b2_protocol_req.protocol = 0x02; - m->msg.select_b2_protocol_req.dlpd.dlen = 4000; - break; - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - m->msg.select_b2_protocol_req.protocol = 0x01; - m->msg.select_b2_protocol_req.dlpd.dlen = 4000; - m->msg.select_b2_protocol_req.dlpd.laa = 3; - m->msg.select_b2_protocol_req.dlpd.lab = 1; - m->msg.select_b2_protocol_req.dlpd.win = 7; - m->msg.select_b2_protocol_req.dlpd.modulo = 8; - break; - } - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_select_b3_protocol_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(17, 0x80, 0x00); - ACTCAPI_CHKSKB; - m->msg.select_b3_protocol_req.plci = chan->plci; - memset(&m->msg.select_b3_protocol_req.ncpd, 0, - sizeof(m->msg.select_b3_protocol_req.ncpd)); - switch (chan->l3prot) { - case ISDN_PROTO_L3_TRANS: - m->msg.select_b3_protocol_req.protocol = 0x04; - m->msg.select_b3_protocol_req.ncpd.len = 13; - m->msg.select_b3_protocol_req.ncpd.modulo = 8; - break; - } - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_listen_b3_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x81, 0x00); - ACTCAPI_CHKSKB; - m->msg.listen_b3_req.plci = chan->plci; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_disconnect_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(3, 0x04, 0x00); - ACTCAPI_CHKSKB; - m->msg.disconnect_req.plci = chan->plci; - m->msg.disconnect_req.cause = 0; - ACTCAPI_QUEUE_TX; -} - -void -actcapi_disconnect_b3_req(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(17, 0x84, 0x00); - ACTCAPI_CHKSKB; - m->msg.disconnect_b3_req.ncci = chan->ncci; - memset(&m->msg.disconnect_b3_req.ncpi, 0, - sizeof(m->msg.disconnect_b3_req.ncpi)); - m->msg.disconnect_b3_req.ncpi.len = 13; - m->msg.disconnect_b3_req.ncpi.modulo = 8; - chan->fsm_state = ACT2000_STATE_BHWAIT; - ACTCAPI_QUEUE_TX; -} - -void -actcapi_connect_resp(act2000_card *card, act2000_chan *chan, __u8 cause) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(3, 0x02, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_resp.plci = chan->plci; - m->msg.connect_resp.rejectcause = cause; - if (cause) { - chan->fsm_state = ACT2000_STATE_NULL; - chan->plci = 0x8000; - } else - chan->fsm_state = ACT2000_STATE_IWAIT; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_connect_active_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x03, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_resp.plci = chan->plci; - if (chan->fsm_state == ACT2000_STATE_IWAIT) - chan->fsm_state = ACT2000_STATE_IBWAIT; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_connect_b3_resp(act2000_card *card, act2000_chan *chan, __u8 rejectcause) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR((rejectcause?3:17), 0x82, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_b3_resp.ncci = chan->ncci; - m->msg.connect_b3_resp.rejectcause = rejectcause; - if (!rejectcause) { - memset(&m->msg.connect_b3_resp.ncpi, 0, - sizeof(m->msg.connect_b3_resp.ncpi)); - m->msg.connect_b3_resp.ncpi.len = 13; - m->msg.connect_b3_resp.ncpi.modulo = 8; - chan->fsm_state = ACT2000_STATE_BWAIT; - } - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_connect_b3_active_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x83, 0x03); - ACTCAPI_CHKSKB; - m->msg.connect_b3_active_resp.ncci = chan->ncci; - chan->fsm_state = ACT2000_STATE_ACTIVE; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_info_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x07, 0x03); - ACTCAPI_CHKSKB; - m->msg.info_resp.plci = chan->plci; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_disconnect_b3_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x84, 0x03); - ACTCAPI_CHKSKB; - m->msg.disconnect_b3_resp.ncci = chan->ncci; - chan->ncci = 0x8000; - chan->queued = 0; - ACTCAPI_QUEUE_TX; -} - -static void -actcapi_disconnect_resp(act2000_card *card, act2000_chan *chan) -{ - actcapi_msg *m; - struct sk_buff *skb; - - ACTCAPI_MKHDR(2, 0x04, 0x03); - ACTCAPI_CHKSKB; - m->msg.disconnect_resp.plci = chan->plci; - chan->plci = 0x8000; - ACTCAPI_QUEUE_TX; -} - -static int -new_plci(act2000_card *card, __u16 plci) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if (card->bch[i].plci == 0x8000) { - card->bch[i].plci = plci; - return i; - } - return -1; -} - -static int -find_plci(act2000_card *card, __u16 plci) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if (card->bch[i].plci == plci) - return i; - return -1; -} - -static int -find_ncci(act2000_card *card, __u16 ncci) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if (card->bch[i].ncci == ncci) - return i; - return -1; -} - -static int -find_dialing(act2000_card *card, __u16 callref) -{ - int i; - for (i = 0; i < ACT2000_BCH; i++) - if ((card->bch[i].callref == callref) && - (card->bch[i].fsm_state == ACT2000_STATE_OCALL)) - return i; - return -1; -} - -static int -actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) { - __u16 plci; - __u16 ncci; - __u16 controller; - __u8 blocknr; - int chan; - actcapi_msg *msg = (actcapi_msg *)skb->data; - - EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci); - chan = find_ncci(card, ncci); - if (chan < 0) - return 0; - if (card->bch[chan].fsm_state != ACT2000_STATE_ACTIVE) - return 0; - if (card->bch[chan].plci != plci) - return 0; - blocknr = msg->msg.data_b3_ind.blocknr; - skb_pull(skb, 19); - card->interface.rcvcallb_skb(card->myid, chan, skb); - if (!(skb = alloc_skb(11, GFP_ATOMIC))) { - printk(KERN_WARNING "actcapi: alloc_skb failed\n"); - return 1; - } - msg = (actcapi_msg *)skb_put(skb, 11); - msg->hdr.len = 11; - msg->hdr.applicationID = 1; - msg->hdr.cmd.cmd = 0x86; - msg->hdr.cmd.subcmd = 0x03; - msg->hdr.msgnum = actcapi_nextsmsg(card); - msg->msg.data_b3_resp.ncci = ncci; - msg->msg.data_b3_resp.blocknr = blocknr; - ACTCAPI_QUEUE_TX; - return 1; -} - -/* - * Walk over ackq, unlink DATA_B3_REQ from it, if - * ncci and blocknr are matching. - * Decrement queued-bytes counter. - */ -static int -handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) { - unsigned long flags; - struct sk_buff *skb; - struct sk_buff *tmp; - struct actcapi_msg *m; - int ret = 0; - - save_flags(flags); - cli(); - skb = skb_peek(&card->ackq); - restore_flags(flags); - if (!skb) { - printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); - return 0; - } - tmp = skb; - while (1) { - m = (actcapi_msg *)tmp->data; - if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) && - (m->msg.data_b3_req.blocknr == blocknr)) { - /* found corresponding DATA_B3_REQ */ - skb_unlink(tmp); - chan->queued -= m->msg.data_b3_req.datalen; - if (m->msg.data_b3_req.flags) - ret = m->msg.data_b3_req.datalen; - dev_kfree_skb(tmp); - if (chan->queued < 0) - chan->queued = 0; - return ret; - } - save_flags(flags); - cli(); - tmp = skb_peek((struct sk_buff_head *)tmp); - restore_flags(flags); - if ((tmp == skb) || (tmp == NULL)) { - /* reached end of queue */ - printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); - return 0; - } - } -} - -void -actcapi_dispatch(act2000_card *card) -{ - struct sk_buff *skb; - actcapi_msg *msg; - __u16 ccmd; - int chan; - int len; - act2000_chan *ctmp; - isdn_ctrl cmd; - char tmp[170]; - - while ((skb = skb_dequeue(&card->rcvq))) { - actcapi_debug_msg(skb, 0); - msg = (actcapi_msg *)skb->data; - ccmd = ((msg->hdr.cmd.cmd << 8) | msg->hdr.cmd.subcmd); - switch (ccmd) { - case 0x8602: - /* DATA_B3_IND */ - if (actcapi_data_b3_ind(card, skb)) - return; - break; - case 0x8601: - /* DATA_B3_CONF */ - chan = find_ncci(card, msg->msg.data_b3_conf.ncci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_ACTIVE)) { - if (msg->msg.data_b3_conf.info != 0) - printk(KERN_WARNING "act2000: DATA_B3_CONF: %04x\n", - msg->msg.data_b3_conf.info); - len = handle_ack(card, &card->bch[chan], - msg->msg.data_b3_conf.blocknr); - if (len) { - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BSENT; - cmd.arg = chan; - cmd.parm.length = len; - card->interface.statcallb(&cmd); - } - } - break; - case 0x0201: - /* CONNECT_CONF */ - chan = find_dialing(card, msg->hdr.msgnum); - if (chan >= 0) { - if (msg->msg.connect_conf.info) { - card->bch[chan].fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - card->bch[chan].fsm_state = ACT2000_STATE_OWAIT; - card->bch[chan].plci = msg->msg.connect_conf.plci; - } - } - break; - case 0x0202: - /* CONNECT_IND */ - chan = new_plci(card, msg->msg.connect_ind.plci); - if (chan < 0) { - ctmp = (act2000_chan *)tmp; - ctmp->plci = msg->msg.connect_ind.plci; - actcapi_connect_resp(card, ctmp, 0x11); /* All Card-Cannels busy */ - } else { - card->bch[chan].fsm_state = ACT2000_STATE_ICALL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_ICALL; - cmd.arg = chan; - cmd.parm.setup.si1 = msg->msg.connect_ind.si1; - cmd.parm.setup.si2 = msg->msg.connect_ind.si2; - if (card->ptype == ISDN_PTYPE_EURO) - strcpy(cmd.parm.setup.eazmsn, - act2000_find_eaz(card, msg->msg.connect_ind.eaz)); - else { - cmd.parm.setup.eazmsn[0] = msg->msg.connect_ind.eaz; - cmd.parm.setup.eazmsn[1] = 0; - } - memset(cmd.parm.setup.phone, 0, sizeof(cmd.parm.setup.phone)); - memcpy(cmd.parm.setup.phone, msg->msg.connect_ind.addr.num, - msg->msg.connect_ind.addr.len - 1); - cmd.parm.setup.plan = msg->msg.connect_ind.addr.tnp; - cmd.parm.setup.screen = 0; - if (card->interface.statcallb(&cmd) == 2) - actcapi_connect_resp(card, &card->bch[chan], 0x15); /* Reject Call */ - } - break; - case 0x0302: - /* CONNECT_ACTIVE_IND */ - chan = find_plci(card, msg->msg.connect_active_ind.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_IWAIT: - actcapi_connect_active_resp(card, &card->bch[chan]); - break; - case ACT2000_STATE_OWAIT: - actcapi_connect_active_resp(card, &card->bch[chan]); - actcapi_select_b2_protocol_req(card, &card->bch[chan]); - break; - } - break; - case 0x8202: - /* CONNECT_B3_IND */ - chan = find_plci(card, msg->msg.connect_b3_ind.plci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_IBWAIT)) { - card->bch[chan].ncci = msg->msg.connect_b3_ind.ncci; - actcapi_connect_b3_resp(card, &card->bch[chan], 0); - } else { - ctmp = (act2000_chan *)tmp; - ctmp->ncci = msg->msg.connect_b3_ind.ncci; - actcapi_connect_b3_resp(card, ctmp, 0x11); /* All Card-Cannels busy */ - } - break; - case 0x8302: - /* CONNECT_B3_ACTIVE_IND */ - chan = find_ncci(card, msg->msg.connect_b3_active_ind.ncci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BWAIT)) { - actcapi_connect_b3_active_resp(card, &card->bch[chan]); - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - case 0x8402: - /* DISCONNECT_B3_IND */ - chan = find_ncci(card, msg->msg.disconnect_b3_ind.ncci); - if (chan >= 0) { - ctmp = &card->bch[chan]; - actcapi_disconnect_b3_resp(card, ctmp); - switch (ctmp->fsm_state) { - case ACT2000_STATE_ACTIVE: - ctmp->fsm_state = ACT2000_STATE_DHWAIT2; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - break; - case ACT2000_STATE_BHWAIT2: - actcapi_disconnect_req(card, ctmp); - ctmp->fsm_state = ACT2000_STATE_DHWAIT; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_BHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - break; - } - } - break; - case 0x0402: - /* DISCONNECT_IND */ - chan = find_plci(card, msg->msg.disconnect_ind.plci); - if (chan >= 0) { - ctmp = &card->bch[chan]; - actcapi_disconnect_resp(card, ctmp); - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - ctmp = (act2000_chan *)tmp; - ctmp->plci = msg->msg.disconnect_ind.plci; - actcapi_disconnect_resp(card, ctmp); - } - break; - case 0x4001: - /* SELECT_B2_PROTOCOL_CONF */ - chan = find_plci(card, msg->msg.select_b2_protocol_conf.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_ICALL: - case ACT2000_STATE_OWAIT: - ctmp = &card->bch[chan]; - if (msg->msg.select_b2_protocol_conf.info == 0) - actcapi_select_b3_protocol_req(card, ctmp); - else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - } - break; - case 0x8001: - /* SELECT_B3_PROTOCOL_CONF */ - chan = find_plci(card, msg->msg.select_b3_protocol_conf.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_ICALL: - case ACT2000_STATE_OWAIT: - ctmp = &card->bch[chan]; - if (msg->msg.select_b3_protocol_conf.info == 0) - actcapi_listen_b3_req(card, ctmp); - else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - } - break; - case 0x8101: - /* LISTEN_B3_CONF */ - chan = find_plci(card, msg->msg.listen_b3_conf.plci); - if (chan >= 0) - switch (card->bch[chan].fsm_state) { - case ACT2000_STATE_ICALL: - ctmp = &card->bch[chan]; - if (msg->msg.listen_b3_conf.info == 0) - actcapi_connect_resp(card, ctmp, 0); - else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - case ACT2000_STATE_OWAIT: - ctmp = &card->bch[chan]; - if (msg->msg.listen_b3_conf.info == 0) { - actcapi_connect_b3_req(card, ctmp); - ctmp->fsm_state = ACT2000_STATE_OBWAIT; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DCONN; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } - break; - } - break; - case 0x8201: - /* CONNECT_B3_CONF */ - chan = find_plci(card, msg->msg.connect_b3_conf.plci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_OBWAIT)) { - ctmp = &card->bch[chan]; - if (msg->msg.connect_b3_conf.info) { - ctmp->fsm_state = ACT2000_STATE_NULL; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan; - card->interface.statcallb(&cmd); - } else { - ctmp->ncci = msg->msg.connect_b3_conf.ncci; - ctmp->fsm_state = ACT2000_STATE_BWAIT; - } - } - break; - case 0x8401: - /* DISCONNECT_B3_CONF */ - chan = find_ncci(card, msg->msg.disconnect_b3_conf.ncci); - if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BHWAIT)) - card->bch[chan].fsm_state = ACT2000_STATE_BHWAIT2; - break; - case 0x0702: - /* INFO_IND */ - chan = find_plci(card, msg->msg.info_ind.plci); - if (chan >= 0) - /* TODO: Eval Charging info / cause */ - actcapi_info_resp(card, &card->bch[chan]); - break; - case 0x0401: - /* LISTEN_CONF */ - case 0x0501: - /* LISTEN_CONF */ - case 0xff01: - /* MANUFACTURER_CONF */ - break; - case 0xff02: - /* MANUFACTURER_IND */ - if (msg->msg.manuf_msg == 3) { - memset(tmp, 0, sizeof(tmp)); - strncpy(tmp, - &msg->msg.manufacturer_ind_err.errstring, - msg->hdr.len - 16); - if (msg->msg.manufacturer_ind_err.errcode) - printk(KERN_WARNING "act2000: %s\n", tmp); - else { - printk(KERN_DEBUG "act2000: %s\n", tmp); - if ((!strncmp(tmp, "INFO: Trace buffer con", 22)) || - (!strncmp(tmp, "INFO: Compile Date/Tim", 22))) { - card->flags |= ACT2000_FLAGS_RUNNING; - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - actcapi_manufacturer_req_net(card); - actcapi_manufacturer_req_msn(card); - actcapi_listen_req(card); - card->interface.statcallb(&cmd); - } - } - } - break; - default: - printk(KERN_WARNING "act2000: UNHANDLED Message %04x\n", ccmd); - break; - } - dev_kfree_skb(skb); - } -} - -#ifdef DEBUG_MSG -static void -actcapi_debug_caddr(actcapi_addr *addr) -{ - char tmp[30]; - - printk(KERN_DEBUG " Alen = %d\n", addr->len); - if (addr->len > 0) - printk(KERN_DEBUG " Atnp = 0x%02x\n", addr->tnp); - if (addr->len > 1) { - memset(tmp, 0, 30); - memcpy(tmp, addr->num, addr->len - 1); - printk(KERN_DEBUG " Anum = '%s'\n", tmp); - } -} - -static void -actcapi_debug_ncpi(actcapi_ncpi *ncpi) -{ - printk(KERN_DEBUG " ncpi.len = %d\n", ncpi->len); - if (ncpi->len >= 2) - printk(KERN_DEBUG " ncpi.lic = 0x%04x\n", ncpi->lic); - if (ncpi->len >= 4) - printk(KERN_DEBUG " ncpi.hic = 0x%04x\n", ncpi->hic); - if (ncpi->len >= 6) - printk(KERN_DEBUG " ncpi.ltc = 0x%04x\n", ncpi->ltc); - if (ncpi->len >= 8) - printk(KERN_DEBUG " ncpi.htc = 0x%04x\n", ncpi->htc); - if (ncpi->len >= 10) - printk(KERN_DEBUG " ncpi.loc = 0x%04x\n", ncpi->loc); - if (ncpi->len >= 12) - printk(KERN_DEBUG " ncpi.hoc = 0x%04x\n", ncpi->hoc); - if (ncpi->len >= 13) - printk(KERN_DEBUG " ncpi.mod = %d\n", ncpi->modulo); -} - -static void -actcapi_debug_dlpd(actcapi_dlpd *dlpd) -{ - printk(KERN_DEBUG " dlpd.len = %d\n", dlpd->len); - if (dlpd->len >= 2) - printk(KERN_DEBUG " dlpd.dlen = 0x%04x\n", dlpd->dlen); - if (dlpd->len >= 3) - printk(KERN_DEBUG " dlpd.laa = 0x%02x\n", dlpd->laa); - if (dlpd->len >= 4) - printk(KERN_DEBUG " dlpd.lab = 0x%02x\n", dlpd->lab); - if (dlpd->len >= 5) - printk(KERN_DEBUG " dlpd.modulo = %d\n", dlpd->modulo); - if (dlpd->len >= 6) - printk(KERN_DEBUG " dlpd.win = %d\n", dlpd->win); -} - -#ifdef DEBUG_DUMP_SKB -static void dump_skb(struct sk_buff *skb) { - char tmp[80]; - char *p = skb->data; - char *t = tmp; - int i; - - for (i = 0; i < skb->len; i++) { - t += sprintf(t, "%02x ", *p++ & 0xff); - if ((i & 0x0f) == 8) { - printk(KERN_DEBUG "dump: %s\n", tmp); - t = tmp; - } - } - if (i & 0x07) - printk(KERN_DEBUG "dump: %s\n", tmp); -} -#endif - -void -actcapi_debug_msg(struct sk_buff *skb, int direction) -{ - actcapi_msg *msg = (actcapi_msg *)skb->data; - char *descr; - int i; - char tmp[170]; - -#ifndef DEBUG_DATA_MSG - if (msg->hdr.cmd.cmd == 0x86) - return; -#endif - descr = "INVALID"; -#ifdef DEBUG_DUMP_SKB - dump_skb(skb); -#endif - for (i = 0; i < num_valid_msg; i++) - if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) && - (msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) { - descr = valid_msg[i].description; - break; - } - printk(KERN_DEBUG "%s %s msg\n", direction?"Outgoing":"Incoming", descr); - printk(KERN_DEBUG " ApplID = %d\n", msg->hdr.applicationID); - printk(KERN_DEBUG " Len = %d\n", msg->hdr.len); - printk(KERN_DEBUG " MsgNum = 0x%04x\n", msg->hdr.msgnum); - printk(KERN_DEBUG " Cmd = 0x%02x\n", msg->hdr.cmd.cmd); - printk(KERN_DEBUG " SubCmd = 0x%02x\n", msg->hdr.cmd.subcmd); - switch (i) { - case 0: - /* DATA B3 IND */ - printk(KERN_DEBUG " BLOCK = 0x%02x\n", - msg->msg.data_b3_ind.blocknr); - break; - case 2: - /* CONNECT CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.connect_conf.info); - break; - case 3: - /* CONNECT IND */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_ind.plci); - printk(KERN_DEBUG " Contr = %d\n", - msg->msg.connect_ind.controller); - printk(KERN_DEBUG " SI1 = %d\n", - msg->msg.connect_ind.si1); - printk(KERN_DEBUG " SI2 = %d\n", - msg->msg.connect_ind.si2); - printk(KERN_DEBUG " EAZ = '%c'\n", - msg->msg.connect_ind.eaz); - actcapi_debug_caddr(&msg->msg.connect_ind.addr); - break; - case 5: - /* CONNECT ACTIVE IND */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_active_ind.plci); - actcapi_debug_caddr(&msg->msg.connect_active_ind.addr); - break; - case 8: - /* LISTEN CONF */ - printk(KERN_DEBUG " Contr = %d\n", - msg->msg.listen_conf.controller); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.listen_conf.info); - break; - case 11: - /* INFO IND */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.info_ind.plci); - printk(KERN_DEBUG " Imsk = 0x%04x\n", - msg->msg.info_ind.nr.mask); - if (msg->hdr.len > 12) { - int l = msg->hdr.len - 12; - int j; - char *p = tmp; - for (j = 0; j < l ; j++) - p += sprintf(p, "%02x ", msg->msg.info_ind.el.display[j]); - printk(KERN_DEBUG " D = '%s'\n", tmp); - } - break; - case 14: - /* SELECT B2 PROTOCOL CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.select_b2_protocol_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.select_b2_protocol_conf.info); - break; - case 15: - /* SELECT B3 PROTOCOL CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.select_b3_protocol_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.select_b3_protocol_conf.info); - break; - case 16: - /* LISTEN B3 CONF */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.listen_b3_conf.plci); - printk(KERN_DEBUG " Info = 0x%04x\n", - msg->msg.listen_b3_conf.info); - break; - case 18: - /* CONNECT B3 IND */ - printk(KERN_DEBUG " NCCI = 0x%04x\n", - msg->msg.connect_b3_ind.ncci); - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_b3_ind.plci); - actcapi_debug_ncpi(&msg->msg.connect_b3_ind.ncpi); - break; - case 19: - /* CONNECT B3 ACTIVE IND */ - printk(KERN_DEBUG " NCCI = 0x%04x\n", - msg->msg.connect_b3_active_ind.ncci); - actcapi_debug_ncpi(&msg->msg.connect_b3_active_ind.ncpi); - break; - case 26: - /* MANUFACTURER IND */ - printk(KERN_DEBUG " Mmsg = 0x%02x\n", - msg->msg.manufacturer_ind_err.manuf_msg); - switch (msg->msg.manufacturer_ind_err.manuf_msg) { - case 3: - printk(KERN_DEBUG " Contr = %d\n", - msg->msg.manufacturer_ind_err.controller); - printk(KERN_DEBUG " Code = 0x%08x\n", - msg->msg.manufacturer_ind_err.errcode); - memset(tmp, 0, sizeof(tmp)); - strncpy(tmp, &msg->msg.manufacturer_ind_err.errstring, - msg->hdr.len - 16); - printk(KERN_DEBUG " Emsg = '%s'\n", tmp); - break; - } - break; - case 30: - /* LISTEN REQ */ - printk(KERN_DEBUG " Imsk = 0x%08x\n", - msg->msg.listen_req.infomask); - printk(KERN_DEBUG " Emsk = 0x%04x\n", - msg->msg.listen_req.eazmask); - printk(KERN_DEBUG " Smsk = 0x%04x\n", - msg->msg.listen_req.simask); - break; - case 35: - /* SELECT_B2_PROTOCOL_REQ */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.select_b2_protocol_req.plci); - printk(KERN_DEBUG " prot = 0x%02x\n", - msg->msg.select_b2_protocol_req.protocol); - if (msg->hdr.len >= 11) - printk(KERN_DEBUG "No dlpd\n"); - else - actcapi_debug_dlpd(&msg->msg.select_b2_protocol_req.dlpd); - break; - case 44: - /* CONNECT RESP */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_resp.plci); - printk(KERN_DEBUG " CAUSE = 0x%02x\n", - msg->msg.connect_resp.rejectcause); - break; - case 45: - /* CONNECT ACTIVE RESP */ - printk(KERN_DEBUG " PLCI = 0x%04x\n", - msg->msg.connect_active_resp.plci); - break; - } -} -#endif diff --git a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h deleted file mode 100644 index 42c0afc2..00000000 --- a/drivers/isdn/act2000/capi.h +++ /dev/null @@ -1,406 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Thanks to Friedemann Baitinger and IBM Germany - * - * 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. - * - * $Log$ - * Revision 1.4 1997/10/01 09:21:04 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.3 1997/09/25 17:25:41 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.2 1997/09/24 19:44:15 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.1 1997/09/23 18:00:10 fritz - * New driver for IBM Active 2000. - * - */ - -#ifndef CAPI_H -#define CAPI_H - -/* Command-part of a CAPI message */ -typedef struct actcapi_msgcmd { - __u8 cmd; - __u8 subcmd; -} actcapi_msgcmd; - -/* CAPI message header */ -typedef struct actcapi_msghdr { - __u16 len; - __u16 applicationID; - actcapi_msgcmd cmd; - __u16 msgnum; -} actcapi_msghdr; - -/* CAPI message description (for debugging) */ -typedef struct actcapi_msgdsc { - actcapi_msgcmd cmd; - char *description; -} actcapi_msgdsc; - -/* CAPI Adress */ -typedef struct actcapi_addr { - __u8 len; /* Length of element */ - __u8 tnp; /* Type/Numbering Plan */ - __u8 num[20]; /* Caller ID */ -} actcapi_addr; - -/* CAPI INFO element mask */ -typedef union actcapi_infonr { /* info number */ - __u16 mask; /* info-mask field */ - struct bmask { /* bit definitions */ - unsigned codes : 3; /* code set */ - unsigned rsvd : 5; /* reserved */ - unsigned svind : 1; /* single, variable length ind. */ - unsigned wtype : 7; /* W-element type */ - } bmask; -} actcapi_infonr; - -/* CAPI INFO element */ -typedef union actcapi_infoel { /* info element */ - __u8 len; /* length of info element */ - __u8 display[40]; /* display contents */ - __u8 uuinfo[40]; /* User-user info field */ - struct cause { /* Cause information */ - unsigned ext2 : 1; /* extension */ - unsigned cod : 2; /* coding standard */ - unsigned spare : 1; /* spare */ - unsigned loc : 4; /* location */ - unsigned ext1 : 1; /* extension */ - unsigned cval : 7; /* Cause value */ - } cause; - struct charge { /* Charging information */ - __u8 toc; /* type of charging info */ - __u8 unit[10]; /* charging units */ - } charge; - __u8 date[20]; /* date fields */ - __u8 stat; /* state of remote party */ -} actcapi_infoel; - -/* Message for EAZ<->MSN Mapping */ -typedef struct actcapi_msn { - __u8 eaz; - __u8 len; /* Length of MSN */ - __u8 msn[15] __attribute__ ((packed)); -} actcapi_msn; - -typedef struct actcapi_dlpd { - __u8 len; /* Length of structure */ - __u16 dlen __attribute__ ((packed)); /* Data Length */ - __u8 laa __attribute__ ((packed)); /* Link Address A */ - __u8 lab; /* Link Address B */ - __u8 modulo; /* Modulo Mode */ - __u8 win; /* Window size */ - __u8 xid[100]; /* XID Information */ -} actcapi_dlpd; - -typedef struct actcapi_ncpd { - __u8 len; /* Length of structure */ - __u16 lic __attribute__ ((packed)); - __u16 hic __attribute__ ((packed)); - __u16 ltc __attribute__ ((packed)); - __u16 htc __attribute__ ((packed)); - __u16 loc __attribute__ ((packed)); - __u16 hoc __attribute__ ((packed)); - __u8 modulo __attribute__ ((packed)); -} actcapi_ncpd; -#define actcapi_ncpi actcapi_ncpd - -/* - * Layout of NCCI field in a B3 DATA CAPI message is different from - * standard at act2000: - * - * Bit 0-4 = PLCI - * Bit 5-7 = Controller - * Bit 8-15 = NCCI - */ -#define MAKE_NCCI(plci,contr,ncci) \ - ((plci & 0x1f) | ((contr & 0x7) << 5) | ((ncci & 0xff) << 8)) - -#define EVAL_NCCI(fakencci,plci,contr,ncci) { \ - plci = fakencci & 0x1f; \ - contr = (fakencci >> 5) & 0x7; \ - ncci = (fakencci >> 8) & 0xff; \ -} - -/* - * Layout of PLCI field in a B3 DATA CAPI message is different from - * standard at act2000: - * - * Bit 0-4 = PLCI - * Bit 5-7 = Controller - * Bit 8-15 = reserved (must be 0) - */ -#define MAKE_PLCI(plci,contr) \ - ((plci & 0x1f) | ((contr & 0x7) << 5)) - -#define EVAL_PLCI(fakeplci,plci,contr) { \ - plci = fakeplci & 0x1f; \ - contr = (fakeplci >> 5) & 0x7; \ -} - -typedef struct actcapi_msg { - actcapi_msghdr hdr; - union msg { - __u16 manuf_msg; - struct manufacturer_req_net { - __u16 manuf_msg; - __u16 controller; - __u8 nettype; - } manufacturer_req_net; - struct manufacturer_req_v42 { - __u16 manuf_msg; - __u16 controller; - __u32 v42control; - } manufacturer_req_v42; - struct manufacturer_conf_v42 { - __u16 manuf_msg; - __u16 controller; - } manufacturer_conf_v42; - struct manufacturer_req_err { - __u16 manuf_msg; - __u16 controller; - } manufacturer_req_err; - struct manufacturer_ind_err { - __u16 manuf_msg; - __u16 controller; - __u32 errcode; - __u8 errstring; /* actually up to 160 */ - } manufacturer_ind_err; - struct manufacturer_req_msn { - __u16 manuf_msg; - __u16 controller; - actcapi_msn msnmap; - } manufacturer_req_msn; - /* TODO: TraceInit-req/conf/ind/resp and - * TraceDump-req/conf/ind/resp - */ - struct connect_req { - __u8 controller; - __u8 bchan; - __u32 infomask __attribute__ ((packed)); - __u8 si1; - __u8 si2; - __u8 eaz; - actcapi_addr addr; - } connect_req; - struct connect_conf { - __u16 plci; - __u16 info; - } connect_conf; - struct connect_ind { - __u16 plci; - __u8 controller; - __u8 si1; - __u8 si2; - __u8 eaz; - actcapi_addr addr; - } connect_ind; - struct connect_resp { - __u16 plci; - __u8 rejectcause; - } connect_resp; - struct connect_active_ind { - __u16 plci; - actcapi_addr addr; - } connect_active_ind; - struct connect_active_resp { - __u16 plci; - } connect_active_resp; - struct connect_b3_req { - __u16 plci; - actcapi_ncpi ncpi; - } connect_b3_req; - struct connect_b3_conf { - __u16 plci; - __u16 ncci; - __u16 info; - } connect_b3_conf; - struct connect_b3_ind { - __u16 ncci; - __u16 plci; - actcapi_ncpi ncpi; - } connect_b3_ind; - struct connect_b3_resp { - __u16 ncci; - __u8 rejectcause; - actcapi_ncpi ncpi __attribute__ ((packed)); - } connect_b3_resp; - struct disconnect_req { - __u16 plci; - __u8 cause; - } disconnect_req; - struct disconnect_conf { - __u16 plci; - __u16 info; - } disconnect_conf; - struct disconnect_ind { - __u16 plci; - __u16 info; - } disconnect_ind; - struct disconnect_resp { - __u16 plci; - } disconnect_resp; - struct connect_b3_active_ind { - __u16 ncci; - actcapi_ncpi ncpi; - } connect_b3_active_ind; - struct connect_b3_active_resp { - __u16 ncci; - } connect_b3_active_resp; - struct disconnect_b3_req { - __u16 ncci; - actcapi_ncpi ncpi; - } disconnect_b3_req; - struct disconnect_b3_conf { - __u16 ncci; - __u16 info; - } disconnect_b3_conf; - struct disconnect_b3_ind { - __u16 ncci; - __u16 info; - actcapi_ncpi ncpi; - } disconnect_b3_ind; - struct disconnect_b3_resp { - __u16 ncci; - } disconnect_b3_resp; - struct info_ind { - __u16 plci; - actcapi_infonr nr; - actcapi_infoel el; - } info_ind; - struct info_resp { - __u16 plci; - } info_resp; - struct listen_b3_req { - __u16 plci; - } listen_b3_req; - struct listen_b3_conf { - __u16 plci; - __u16 info; - } listen_b3_conf; - struct select_b2_protocol_req { - __u16 plci; - __u8 protocol; - actcapi_dlpd dlpd __attribute__ ((packed)); - } select_b2_protocol_req; - struct select_b2_protocol_conf { - __u16 plci; - __u16 info; - } select_b2_protocol_conf; - struct select_b3_protocol_req { - __u16 plci; - __u8 protocol; - actcapi_ncpd ncpd __attribute__ ((packed)); - } select_b3_protocol_req; - struct select_b3_protocol_conf { - __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)); - __u16 eazmask __attribute__ ((packed)); - __u16 simask __attribute__ ((packed)); - } listen_req; - struct listen_conf { - __u8 controller; - __u16 info __attribute__ ((packed)); - } listen_conf; -#endif - struct data_b3_req { - __u16 fakencci; - __u16 datalen; - __u32 unused; - __u8 blocknr; - __u16 flags __attribute__ ((packed)); - } data_b3_req; - struct data_b3_ind { - __u16 fakencci; - __u16 datalen; - __u32 unused; - __u8 blocknr; - __u16 flags __attribute__ ((packed)); - } data_b3_ind; - struct data_b3_resp { - __u16 ncci; - __u8 blocknr; - } data_b3_resp; - struct data_b3_conf { - __u16 ncci; - __u8 blocknr; - __u16 info __attribute__ ((packed)); - } data_b3_conf; - } msg; -} actcapi_msg; - -extern __inline__ unsigned short -actcapi_nextsmsg(act2000_card *card) -{ - unsigned long flags; - unsigned short n; - - save_flags(flags); - cli(); - n = card->msgnum; - card->msgnum++; - card->msgnum &= 0x7fff; - restore_flags(flags); - return n; -} -#define DEBUG_MSG -#undef DEBUG_DATA_MSG -#undef DEBUG_DUMP_SKB - -extern int actcapi_chkhdr(act2000_card *, actcapi_msghdr *); -extern int actcapi_listen_req(act2000_card *); -extern int actcapi_manufacturer_req_net(act2000_card *); -extern int actcapi_manufacturer_req_v42(act2000_card *, ulong); -extern int actcapi_manufacturer_req_errh(act2000_card *); -extern int actcapi_manufacturer_req_msn(act2000_card *); -extern int actcapi_connect_req(act2000_card *, act2000_chan *, char *, char, int, int); -extern void actcapi_select_b2_protocol_req(act2000_card *, act2000_chan *); -extern void actcapi_disconnect_b3_req(act2000_card *, act2000_chan *); -extern void actcapi_connect_resp(act2000_card *, act2000_chan *, __u8); -extern void actcapi_dispatch(act2000_card *); -#ifdef DEBUG_MSG -extern void actcapi_debug_msg(struct sk_buff *skb, int); -#else -#define actcapi_debug_msg(skb, len) -#endif -#endif diff --git a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c deleted file mode 100644 index ea482f79..00000000 --- a/drivers/isdn/act2000/module.c +++ /dev/null @@ -1,963 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000. - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Thanks to Friedemann Baitinger and IBM Germany - * - * 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. - * - * $Log$ - * Revision 1.10 1999/10/24 18:46:05 fritz - * Changed isa_ prefix to act2000_isa_ to prevent name-clash in latest - * kernels. - * - * Revision 1.9 1999/04/12 13:13:56 fritz - * Made cards pointer static to avoid name-clash. - * - * Revision 1.8 1998/11/05 22:12:51 fritz - * Changed mail-address. - * - * Revision 1.7 1998/02/12 23:06:52 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.6 1998/01/31 22:10:42 keil - * changes for 2.1.82 - * - * Revision 1.5 1997/10/09 22:23:04 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.4 1997/09/25 17:25:43 fritz - * Support for adding cards at runtime. - * Support for new Firmware. - * - * Revision 1.3 1997/09/24 23:11:45 fritz - * Optimized IRQ load and polling-mode. - * - * Revision 1.2 1997/09/24 19:44:17 fritz - * Added MSN mapping support, some cleanup. - * - * Revision 1.1 1997/09/23 18:00:13 fritz - * New driver for IBM Active 2000. - * - */ - -#include "act2000.h" -#include "act2000_isa.h" -#include "capi.h" - -static unsigned short act2000_isa_ports[] = -{ - 0x0200, 0x0240, 0x0280, 0x02c0, 0x0300, 0x0340, 0x0380, - 0xcfe0, 0xcfa0, 0xcf60, 0xcf20, 0xcee0, 0xcea0, 0xce60, -}; -#define ISA_NRPORTS (sizeof(act2000_isa_ports)/sizeof(unsigned short)) - -static act2000_card *cards = (act2000_card *) NULL; - -/* Parameters to be set by insmod */ -static int act_bus = 0; -static int act_port = -1; /* -1 = Autoprobe */ -static int act_irq = -1; /* -1 = Autoselect */ -static char *act_id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - -MODULE_DESCRIPTION( "Driver for IBM Active 2000 ISDN card"); -MODULE_AUTHOR( "Fritz Elfert"); -MODULE_SUPPORTED_DEVICE( "ISDN subsystem"); -MODULE_PARM_DESC(act_bus, "BusType of first card, 1=ISA, 2=MCA, 3=PCMCIA, currently only ISA"); -MODULE_PARM_DESC(membase, "Base port address of first card"); -MODULE_PARM_DESC(act_irq, "IRQ of first card (-1 = grab next free IRQ)"); -MODULE_PARM_DESC(act_id, "ID-String of first card"); -MODULE_PARM(act_bus, "i"); -MODULE_PARM(act_port, "i"); -MODULE_PARM(act_irq, "i"); -MODULE_PARM(act_id, "s"); - -static int act2000_addcard(int, int, int, char *); - -static act2000_chan * -find_channel(act2000_card *card, int channel) -{ - if ((channel >= 0) && (channel < ACT2000_BCH)) - return &(card->bch[channel]); - printk(KERN_WARNING "act2000: Invalid channel %d\n", channel); - return NULL; -} - -/* - * Free MSN list - */ -static void -act2000_clear_msn(act2000_card *card) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q; - unsigned long flags; - - save_flags(flags); - cli(); - card->msn_list = NULL; - restore_flags(flags); - while (p) { - q = p->next; - kfree(p); - p = q; - } -} - -/* - * Find an MSN entry in the list. - * If ia5 != 0, return IA5-encoded EAZ, else - * return a bitmask with corresponding bit set. - */ -static __u16 -act2000_find_msn(act2000_card *card, char *msn, int ia5) -{ - struct msn_entry *p = card->msn_list; - __u8 eaz = '0'; - - while (p) { - if (!strcmp(p->msn, msn)) { - eaz = p->eaz; - break; - } - p = p->next; - } - if (!ia5) - return (1 << (eaz - '0')); - else - return eaz; -} - -/* - * Find an EAZ entry in the list. - * return a string with corresponding msn. - */ -char * -act2000_find_eaz(act2000_card *card, char eaz) -{ - struct msn_entry *p = card->msn_list; - - while (p) { - if (p->eaz == eaz) - return(p->msn); - p = p->next; - } - return("\0"); -} - -/* - * Add or delete an MSN to the MSN list - * - * First character of msneaz is EAZ, rest is MSN. - * If length of eazmsn is 1, delete that entry. - */ -static int -act2000_set_msn(act2000_card *card, char *eazmsn) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q = NULL; - unsigned long flags; - int i; - - if (!strlen(eazmsn)) - return 0; - if (strlen(eazmsn) > 16) - return -EINVAL; - for (i = 0; i < strlen(eazmsn); i++) - if (!isdigit(eazmsn[i])) - return -EINVAL; - if (strlen(eazmsn) == 1) { - /* Delete a single MSN */ - while (p) { - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - if (q) - q->next = p->next; - else - card->msn_list = p->next; - restore_flags(flags); - kfree(p); - printk(KERN_DEBUG - "Mapping for EAZ %c deleted\n", - eazmsn[0]); - return 0; - } - q = p; - p = p->next; - } - return 0; - } - /* Add a single MSN */ - while (p) { - /* Found in list, replace MSN */ - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - strcpy(p->msn, &eazmsn[1]); - restore_flags(flags); - printk(KERN_DEBUG - "Mapping for EAZ %c changed to %s\n", - eazmsn[0], - &eazmsn[1]); - return 0; - } - p = p->next; - } - /* Not found in list, add new entry */ - p = kmalloc(sizeof(msn_entry), GFP_KERNEL); - if (!p) - return -ENOMEM; - p->eaz = eazmsn[0]; - strcpy(p->msn, &eazmsn[1]); - p->next = card->msn_list; - save_flags(flags); - cli(); - card->msn_list = p; - restore_flags(flags); - printk(KERN_DEBUG - "Mapping %c -> %s added\n", - eazmsn[0], - &eazmsn[1]); - return 0; -} - -static void -act2000_transmit(struct act2000_card *card) -{ - switch (card->bus) { - case ACT2000_BUS_ISA: - act2000_isa_send(card); - break; - case ACT2000_BUS_PCMCIA: - case ACT2000_BUS_MCA: - default: - printk(KERN_WARNING - "act2000_transmit: Illegal bustype %d\n", card->bus); - } -} - -static void -act2000_receive(struct act2000_card *card) -{ - switch (card->bus) { - case ACT2000_BUS_ISA: - act2000_isa_receive(card); - break; - case ACT2000_BUS_PCMCIA: - case ACT2000_BUS_MCA: - default: - printk(KERN_WARNING - "act2000_receive: Illegal bustype %d\n", card->bus); - } -} - -static void -act2000_poll(unsigned long data) -{ - act2000_card * card = (act2000_card *)data; - unsigned long flags; - - act2000_receive(card); - save_flags(flags); - cli(); - del_timer(&card->ptimer); - card->ptimer.expires = jiffies + 3; - add_timer(&card->ptimer); - restore_flags(flags); -} - -static int -act2000_command(act2000_card * card, isdn_ctrl * c) -{ - ulong a; - act2000_chan *chan; - act2000_cdef cdef; - isdn_ctrl cmd; - char tmp[17]; - int ret; - unsigned long flags; - - switch (c->command) { - case ISDN_CMD_IOCTL: - memcpy(&a, c->parm.num, sizeof(ulong)); - switch (c->arg) { - case ACT2000_IOCTL_LOADBOOT: - switch (card->bus) { - case ACT2000_BUS_ISA: - ret = act2000_isa_download(card, - (act2000_ddef *)a); - if (!ret) { - card->flags |= ACT2000_FLAGS_LOADED; - if (!(card->flags & ACT2000_FLAGS_IVALID)) { - card->ptimer.expires = jiffies + 3; - card->ptimer.function = act2000_poll; - card->ptimer.data = (unsigned long)card; - add_timer(&card->ptimer); - } - actcapi_manufacturer_req_errh(card); - } - break; - default: - printk(KERN_WARNING - "act2000: Illegal BUS type %d\n", - card->bus); - ret = -EIO; - } - return ret; - case ACT2000_IOCTL_SETPROTO: - card->ptype = a?ISDN_PTYPE_EURO:ISDN_PTYPE_1TR6; - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return 0; - actcapi_manufacturer_req_net(card); - return 0; - case ACT2000_IOCTL_SETMSN: - if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp)))) - return ret; - if ((ret = act2000_set_msn(card, tmp))) - return ret; - if (card->flags & ACT2000_FLAGS_RUNNING) - return(actcapi_manufacturer_req_msn(card)); - return 0; - case ACT2000_IOCTL_ADDCARD: - if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef)))) - return ret; - if (act2000_addcard(cdef.bus, cdef.port, cdef.irq, cdef.id)) - return -EIO; - return 0; - case ACT2000_IOCTL_TEST: - if (!(card->flags & ACT2000_FLAGS_RUNNING)) - return -ENODEV; - return 0; - default: - return -EINVAL; - } - break; - case ISDN_CMD_DIAL: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - save_flags(flags); - cli(); - if (chan->fsm_state != ACT2000_STATE_NULL) { - restore_flags(flags); - printk(KERN_WARNING "Dial on channel with state %d\n", - chan->fsm_state); - return -EBUSY; - } - if (card->ptype == ISDN_PTYPE_EURO) - tmp[0] = act2000_find_msn(card, c->parm.setup.eazmsn, 1); - else - tmp[0] = c->parm.setup.eazmsn[0]; - chan->fsm_state = ACT2000_STATE_OCALL; - chan->callref = 0xffff; - restore_flags(flags); - ret = actcapi_connect_req(card, chan, c->parm.setup.phone, - tmp[0], c->parm.setup.si1, - c->parm.setup.si2); - if (ret) { - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg &= 0x0f; - card->interface.statcallb(&cmd); - } - return ret; - case ISDN_CMD_ACCEPTD: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - if (chan->fsm_state == ACT2000_STATE_ICALL) - actcapi_select_b2_protocol_req(card, chan); - return 0; - case ISDN_CMD_ACCEPTB: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - return 0; - case ISDN_CMD_HANGUP: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - switch (chan->fsm_state) { - case ACT2000_STATE_ICALL: - case ACT2000_STATE_BSETUP: - actcapi_connect_resp(card, chan, 0x15); - break; - case ACT2000_STATE_ACTIVE: - actcapi_disconnect_b3_req(card, chan); - break; - } - return 0; - case ISDN_CMD_SETEAZ: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - if (strlen(c->parm.num)) { - if (card->ptype == ISDN_PTYPE_EURO) { - chan->eazmask = act2000_find_msn(card, c->parm.num, 0); - } - if (card->ptype == ISDN_PTYPE_1TR6) { - int i; - chan->eazmask = 0; - for (i = 0; i < strlen(c->parm.num); i++) - if (isdigit(c->parm.num[i])) - chan->eazmask |= (1 << (c->parm.num[i] - '0')); - } - } else - chan->eazmask = 0x3ff; - actcapi_listen_req(card); - return 0; - case ISDN_CMD_CLREAZ: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - chan->eazmask = 0; - actcapi_listen_req(card); - return 0; - case ISDN_CMD_SETL2: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - chan->l2prot = (c->arg >> 8); - return 0; - case ISDN_CMD_GETL2: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - return chan->l2prot; - case ISDN_CMD_SETL3: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg >> 8) != ISDN_PROTO_L3_TRANS) { - printk(KERN_WARNING "L3 protocol unknown\n"); - return -1; - } - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - chan->l3prot = (c->arg >> 8); - return 0; - case ISDN_CMD_GETL3: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x0f))) - break; - return chan->l3prot; - case ISDN_CMD_GETEAZ: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - printk(KERN_DEBUG "act2000 CMD_GETEAZ not implemented\n"); - return 0; - case ISDN_CMD_SETSIL: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - printk(KERN_DEBUG "act2000 CMD_SETSIL not implemented\n"); - return 0; - case ISDN_CMD_GETSIL: - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - printk(KERN_DEBUG "act2000 CMD_GETSIL not implemented\n"); - return 0; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - return 0; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - return 0; - } - - return -EINVAL; -} - -static int -act2000_sendbuf(act2000_card *card, int channel, int ack, struct sk_buff *skb) -{ - struct sk_buff *xmit_skb; - int len; - act2000_chan *chan; - actcapi_msg *msg; - - if (!(chan = find_channel(card, channel))) - return -1; - if (chan->fsm_state != ACT2000_STATE_ACTIVE) - return -1; - len = skb->len; - if ((chan->queued + len) >= ACT2000_MAX_QUEUED) - return 0; - if (!len) - return 0; - if (skb_headroom(skb) < 19) { - printk(KERN_WARNING "act2000_sendbuf: Headroom only %d\n", - skb_headroom(skb)); - xmit_skb = alloc_skb(len + 19, GFP_ATOMIC); - if (!xmit_skb) { - printk(KERN_WARNING "act2000_sendbuf: Out of memory\n"); - return 0; - } - skb_reserve(xmit_skb, 19); - memcpy(skb_put(xmit_skb, len), skb->data, len); - } else { - xmit_skb = skb_clone(skb, GFP_ATOMIC); - if (!xmit_skb) { - printk(KERN_WARNING "act2000_sendbuf: Out of memory\n"); - return 0; - } - } - dev_kfree_skb(skb); - msg = (actcapi_msg *)skb_push(xmit_skb, 19); - msg->hdr.len = 19 + len; - msg->hdr.applicationID = 1; - msg->hdr.cmd.cmd = 0x86; - msg->hdr.cmd.subcmd = 0x00; - msg->hdr.msgnum = actcapi_nextsmsg(card); - msg->msg.data_b3_req.datalen = len; - msg->msg.data_b3_req.blocknr = (msg->hdr.msgnum & 0xff); - msg->msg.data_b3_req.fakencci = MAKE_NCCI(chan->plci, 0, chan->ncci); - msg->msg.data_b3_req.flags = ack; /* Will be set to 0 on actual sending */ - actcapi_debug_msg(xmit_skb, 1); - chan->queued += len; - skb_queue_tail(&card->sndq, xmit_skb); - act2000_schedule_tx(card); - return len; -} - - -/* Read the Status-replies from the Interface */ -static int -act2000_readstatus(u_char * buf, int len, int user, act2000_card * card) -{ - int count; - u_char *p; - - for (p = buf, count = 0; count < len; p++, count++) { - if (card->status_buf_read == card->status_buf_write) - return count; - if (user) - put_user(*card->status_buf_read++, p); - else - *p = *card->status_buf_read++; - if (card->status_buf_read > card->status_buf_end) - card->status_buf_read = card->status_buf; - } - return count; -} - -static void -act2000_putmsg(act2000_card *card, char c) -{ - ulong flags; - - save_flags(flags); - cli(); - *card->status_buf_write++ = c; - if (card->status_buf_write == card->status_buf_read) { - if (++card->status_buf_read > card->status_buf_end) - card->status_buf_read = card->status_buf; - } - if (card->status_buf_write > card->status_buf_end) - card->status_buf_write = card->status_buf; - restore_flags(flags); -} - -static void -act2000_logstat(struct act2000_card *card, char *str) -{ - char *p = str; - isdn_ctrl c; - - while (*p) - act2000_putmsg(card, *p++); - c.command = ISDN_STAT_STAVAIL; - c.driver = card->myid; - c.arg = strlen(str); - card->interface.statcallb(&c); -} - -/* - * Find card with given driverId - */ -static inline act2000_card * -act2000_findcard(int driverid) -{ - act2000_card *p = cards; - - while (p) { - if (p->myid == driverid) - return p; - p = p->next; - } - return (act2000_card *) 0; -} - -/* - * Wrapper functions for interface to linklevel - */ -static int -if_command(isdn_ctrl * c) -{ - act2000_card *card = act2000_findcard(c->driver); - - if (card) - return (act2000_command(card, c)); - printk(KERN_ERR - "act2000: if_command %d called with invalid driverId %d!\n", - c->command, c->driver); - return -ENODEV; -} - -static int -if_writecmd(const u_char * buf, int len, int user, int id, int channel) -{ - act2000_card *card = act2000_findcard(id); - - if (card) { - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - return (len); - } - printk(KERN_ERR - "act2000: if_writecmd called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_readstatus(u_char * buf, int len, int user, int id, int channel) -{ - act2000_card *card = act2000_findcard(id); - - if (card) { - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - return (act2000_readstatus(buf, len, user, card)); - } - printk(KERN_ERR - "act2000: if_readstatus called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) -{ - act2000_card *card = act2000_findcard(id); - - if (card) { - if (!card->flags & ACT2000_FLAGS_RUNNING) - return -ENODEV; - return (act2000_sendbuf(card, channel, ack, skb)); - } - printk(KERN_ERR - "act2000: if_sendbuf called with invalid driverId!\n"); - return -ENODEV; -} - - -/* - * Allocate a new card-struct, initialize it - * link it into cards-list. - */ -static void -act2000_alloccard(int bus, int port, int irq, char *id) -{ - int i; - act2000_card *card; - if (!(card = (act2000_card *) kmalloc(sizeof(act2000_card), GFP_KERNEL))) { - printk(KERN_WARNING - "act2000: (%s) Could not allocate card-struct.\n", id); - return; - } - memset((char *) card, 0, sizeof(act2000_card)); - skb_queue_head_init(&card->sndq); - skb_queue_head_init(&card->rcvq); - skb_queue_head_init(&card->ackq); - card->snd_tq.routine = (void *) (void *) act2000_transmit; - card->snd_tq.data = card; - card->rcv_tq.routine = (void *) (void *) actcapi_dispatch; - card->rcv_tq.data = card; - card->poll_tq.routine = (void *) (void *) act2000_receive; - card->poll_tq.data = card; - init_timer(&card->ptimer); - card->interface.channels = ACT2000_BCH; - card->interface.maxbufsize = 4000; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = if_writecmd; - card->interface.readstat = if_readstatus; - 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; - card->ptype = ISDN_PTYPE_EURO; - strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); - for (i=0; ibch[i].plci = 0x8000; - card->bch[i].ncci = 0x8000; - card->bch[i].l2prot = ISDN_PROTO_L2_X75I; - card->bch[i].l3prot = ISDN_PROTO_L3_TRANS; - } - card->myid = -1; - card->bus = bus; - card->port = port; - card->irq = irq; - card->next = cards; - cards = card; -} - -/* - * register card at linklevel - */ -static int -act2000_registercard(act2000_card * card) -{ - switch (card->bus) { - case ACT2000_BUS_ISA: - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: Illegal BUS type %d\n", - card->bus); - return -1; - } - if (!register_isdn(&card->interface)) { - printk(KERN_WARNING - "act2000: Unable to register %s\n", - card->interface.id); - return -1; - } - card->myid = card->interface.channels; - sprintf(card->regname, "act2000-isdn (%s)", card->interface.id); - return 0; -} - -static void -unregister_card(act2000_card * card) -{ - isdn_ctrl cmd; - - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - switch (card->bus) { - case ACT2000_BUS_ISA: - act2000_isa_release(card); - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: Invalid BUS type %d\n", - card->bus); - break; - } -} - -static int -act2000_addcard(int bus, int port, int irq, char *id) -{ - act2000_card *p; - act2000_card *q = NULL; - int initialized; - int added = 0; - int failed = 0; - int i; - - if (!bus) - bus = ACT2000_BUS_ISA; - if (port != -1) { - /* Port defined, do fixed setup */ - act2000_alloccard(bus, port, irq, id); - } else { - /* No port defined, perform autoprobing. - * This may result in more than one card detected. - */ - switch (bus) { - case ACT2000_BUS_ISA: - for (i = 0; i < ISA_NRPORTS; i++) - if (act2000_isa_detect(act2000_isa_ports[i])) { - printk(KERN_INFO - "act2000: Detected ISA card at port 0x%x\n", - act2000_isa_ports[i]); - act2000_alloccard(bus, act2000_isa_ports[i], irq, id); - } - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: addcard: Invalid BUS type %d\n", - bus); - } - } - if (!cards) - return 1; - p = cards; - while (p) { - initialized = 0; - if (!p->interface.statcallb) { - /* Not yet registered. - * Try to register and activate it. - */ - added++; - switch (p->bus) { - case ACT2000_BUS_ISA: - if (act2000_isa_detect(p->port)) { - if (act2000_registercard(p)) - break; - if (act2000_isa_config_port(p, p->port)) { - printk(KERN_WARNING - "act2000: Could not request port 0x%04x\n", - p->port); - unregister_card(p); - p->interface.statcallb = NULL; - break; - } - if (act2000_isa_config_irq(p, p->irq)) { - printk(KERN_INFO - "act2000: No IRQ available, fallback to polling\n"); - /* Fall back to polled operation */ - p->irq = 0; - } - printk(KERN_INFO - "act2000: ISA" - "-type card at port " - "0x%04x ", - p->port); - if (p->irq) - printk("irq %d\n", p->irq); - else - printk("polled\n"); - initialized = 1; - } - break; - case ACT2000_BUS_MCA: - case ACT2000_BUS_PCMCIA: - default: - printk(KERN_WARNING - "act2000: addcard: Invalid BUS type %d\n", - p->bus); - } - } else - /* Card already initialized */ - initialized = 1; - if (initialized) { - /* Init OK, next card ... */ - q = p; - p = p->next; - } else { - /* Init failed, remove card from list, free memory */ - printk(KERN_WARNING - "act2000: Initialization of %s failed\n", - p->interface.id); - if (q) { - q->next = p->next; - kfree(p); - p = q->next; - } else { - cards = p->next; - kfree(p); - p = cards; - } - failed++; - } - } - return (added - failed); -} - -#define DRIVERNAME "IBM Active 2000 ISDN driver" - -#ifdef MODULE -#define act2000_init init_module -#endif - -int -act2000_init(void) -{ - printk(KERN_INFO "%s\n", DRIVERNAME); - if (!cards) - act2000_addcard(act_bus, act_port, act_irq, act_id); - if (!cards) - printk(KERN_INFO "act2000: No cards defined yet\n"); - /* No symbols to export, hide all symbols */ - EXPORT_NO_SYMBOLS; - return 0; -} - -#ifdef MODULE -void -cleanup_module(void) -{ - act2000_card *card = cards; - act2000_card *last; - while (card) { - unregister_card(card); - del_timer(&card->ptimer); - card = card->next; - } - card = cards; - while (card) { - last = card; - card = card->next; - act2000_clear_msn(last); - kfree(last); - } - printk(KERN_INFO "%s unloaded\n", DRIVERNAME); -} - -#else -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 diff --git a/drivers/isdn/avmb1/Makefile b/drivers/isdn/avmb1/Makefile deleted file mode 100644 index 324cd769..00000000 --- a/drivers/isdn/avmb1/Makefile +++ /dev/null @@ -1,175 +0,0 @@ -# -# $Id$ -# -# Makefile for the CAPI and AVM-B1 device drivers. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definitions are now inherited from the -# parent makes.. -# -# $Log$ -# Revision 1.13 2000/03/08 17:06:33 calle -# - changes for devfs and 2.3.49 -# - capifs now configurable (no need with devfs) -# - New Middleware ioctl CAPI_NCCI_GETUNIT -# - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) -# -# Revision 1.12 2000/03/06 18:00:23 calle -# - Middleware extention now working with 2.3.49 (capifs). -# - Fixed typos in debug section of capi.c -# - Bugfix: Makefile corrected for b1pcmcia.c -# -# Revision 1.11 2000/03/06 09:17:07 calle -# - capifs: fileoperations now in inode (change for 2.3.49) -# - Config.in: Middleware extention not a tristate, uups. -# -# Revision 1.10 2000/03/03 16:48:38 calle -# - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) -# It is now possible to create a connection with a CAPI2.0 applikation -# and than to handle the data connection from /dev/capi/ (capifs) and also -# using async or sync PPP on this connection. -# The two major device number 190 and 191 are not confirmed yet, -# but I want to save the code in cvs, before I go on. -# -# Revision 1.9 2000/03/03 15:50:42 calle -# - kernel CAPI: -# - Changed parameter "param" in capi_signal from __u32 to void *. -# - rewrote notifier handling in kcapi.c -# - new notifier NCCI_UP and NCCI_DOWN -# - User CAPI: -# - /dev/capi20 is now a cloning device. -# - middleware extentions prepared. -# - capidrv.c -# - locking of list operations and module count updates. -# -# Revision 1.8 2000/01/25 14:33:38 calle -# - Added Support AVM B1 PCI V4.0 (tested with prototype) -# - splitted up t1pci.c into b1dma.c for common function with b1pciv4 -# - support for revision register -# -# Revision 1.7 1999/09/15 08:16:03 calle -# Implementation of 64Bit extention complete. -# -# Revision 1.6 1999/07/20 06:41:44 calle -# Bugfix: After the redesign of the AVM B1 driver, the driver didn't even -# compile, if not selected as modules. -# -# Revision 1.5 1999/07/01 15:26:20 calle -# complete new version (I love it): -# + new hardware independed "capi_driver" interface that will make it easy to: -# - support other controllers with CAPI-2.0 (i.e. USB Controller) -# - write a CAPI-2.0 for the passive cards -# - support serial link CAPI-2.0 boxes. -# + wrote "capi_driver" for all supported cards. -# + "capi_driver" (supported cards) now have to be configured with -# make menuconfig, in the past all supported cards where included -# at once. -# + new and better informations in /proc/capi/ -# + new ioctl to switch trace of capi messages per controller -# using "avmcapictrl trace [contr] on|off|...." -# + complete testcircle with all supported cards and also the -# PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. -# -# Revision 1.4 1997/03/30 17:10:40 calle -# added support for AVM-B1-PCI card. -# -# Revision 1.3 1997/03/22 02:00:57 fritz -# -Reworked toplevel Makefile. From now on, no different Makefiles -# for standalone- and in-kernel-compilation are needed any more. -# -Added local Rules.make for above reason. -# -Experimental changes in teles3.c for enhanced IRQ-checking with -# 2.1.X and SMP kernels. -# -Removed diffstd-script, same functionality is in stddiff -r. -# -Enhanced scripts std2kern and stddiff. -# -# Revision 1.1 1997/03/05 21:26:14 fritz -# Renamed, according naming conventions in CVS tree. -# -# Revision 1.1 1997/03/04 21:50:26 calle -# Frirst version in isdn4linux -# -# Revision 2.2 1997/02/12 09:31:39 calle -# -# Revision 1.1 1997/01/31 10:32:20 calle -# Initial revision -# -# - -# -# Objects that don't export a symtab -# -L_OBJS := # used as component of an L_TARGET -O_OBJS := # used as component of an O_TARGET -M_OBJS := # used as module -# -# Objects that do export a symtab -# -LX_OBJS := # used as component of an L_TARGET -OX_OBJS := # used as component of an O_TARGET -MX_OBJS := # used as module -# -# Targets, created by linking others -# -O_TARGET := # used for .o targets (from O and OX objects) -L_TARGET := # used for .a targets (from L and LX objects) - -ifeq ($(CONFIG_ISDN_CAPI),y) - O_TARGET += avmb1.o - OX_OBJS += kcapi.o - O_OBJS += capi.o - ifdef CONFIG_ISDN_CAPIFS - OX_OBJS += capifs.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - O_OBJS += b1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - O_OBJS += b1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - O_OBJS += t1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - OX_OBJS += b1pcmcia.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - O_OBJS += t1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_C4 - O_OBJS += c4.o - endif - OX_OBJS += capiutil.o capidrv.o b1.o b1dma.o -else - ifeq ($(CONFIG_ISDN_CAPI),m) - O_TARGET += kernelcapi.o - OX_OBJS += kcapi.o - M_OBJS += capi.o kernelcapi.o - ifdef CONFIG_ISDN_CAPIFS - MX_OBJS += capifs.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - M_OBJS += b1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - M_OBJS += b1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - M_OBJS += t1isa.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - MX_OBJS += b1pcmcia.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - M_OBJS += t1pci.o - endif - ifdef CONFIG_ISDN_DRV_AVMB1_C4 - M_OBJS += c4.o - endif - MX_OBJS += capiutil.o capidrv.o b1.o b1dma.o - endif -endif - -include $(TOPDIR)/Rules.make diff --git a/drivers/isdn/avmb1/avmcard.h b/drivers/isdn/avmb1/avmcard.h deleted file mode 100644 index 7288fe80..00000000 --- a/drivers/isdn/avmb1/avmcard.h +++ /dev/null @@ -1,603 +0,0 @@ -/* - * $Id$ - * - * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.6 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.5 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.4 1999/08/04 10:10:08 calle - * Bugfix: corrected /proc functions, added structure for new AVM cards. - * - * Revision 1.3 1999/07/23 08:41:47 calle - * prepared for new AVM cards. - * - * Revision 1.2 1999/07/05 15:09:45 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:22 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - */ - -#ifndef _AVMCARD_H_ -#define _AVMCARD_H_ - -#define AVMB1_PORTLEN 0x1f -#define AVM_MAXVERSION 8 -#define AVM_NAPPS 30 -#define AVM_NCCI_PER_CHANNEL 4 - -/* - * Versions - */ - -#define VER_DRIVER 0 -#define VER_CARDTYPE 1 -#define VER_HWID 2 -#define VER_SERIAL 3 -#define VER_OPTION 4 -#define VER_PROTO 5 -#define VER_PROFILE 6 -#define VER_CAPI 7 - -enum avmcardtype { - avm_b1isa, - avm_b1pci, - avm_b1pcmcia, - avm_m1, - avm_m2, - avm_t1isa, - avm_t1pci, - avm_c4 -}; - -typedef struct avmcard_dmainfo { - __u32 recvlen; - __u8 recvbuf[128+2048]; - struct sk_buff_head send_queue; - __u8 sendbuf[128+2048]; -} avmcard_dmainfo; - - -typedef struct avmcard { - char name[32]; - unsigned int port; - unsigned irq; - unsigned long membase; - enum avmcardtype cardtype; - unsigned char revision; - unsigned char class; - int cardnr; /* for t1isa */ - - char msgbuf[128]; /* capimsg msg part */ - char databuf[2048]; /* capimsg data part */ - - int interrupt; - - void *mbase; - volatile __u32 csr; - avmcard_dmainfo *dma; - - struct avmctrl_info { - char cardname[32]; - - int versionlen; - char versionbuf[1024]; - char *version[AVM_MAXVERSION]; - - char infobuf[128]; /* for function procinfo */ - - struct avmcard *card; - struct capi_ctr *capi_ctrl; - - } *ctrlinfo; - - int nlogcontr; -} avmcard; - -typedef struct avmctrl_info avmctrl_info; - -extern int b1_irq_table[16]; - -/* - * LLI Messages to the ISDN-ControllerISDN Controller - */ - -#define SEND_POLL 0x72 /* - * after load <- RECEIVE_POLL - */ -#define SEND_INIT 0x11 /* - * first message <- RECEIVE_INIT - * int32 NumApplications int32 - * NumNCCIs int32 BoardNumber - */ -#define SEND_REGISTER 0x12 /* - * register an application int32 - * ApplIDId int32 NumMessages - * int32 NumB3Connections int32 - * NumB3Blocks int32 B3Size - * - * AnzB3Connection != 0 && - * AnzB3Blocks >= 1 && B3Size >= 1 - */ -#define SEND_RELEASE 0x14 /* - * deregister an application int32 - * ApplID - */ -#define SEND_MESSAGE 0x15 /* - * send capi-message int32 length - * capi-data ... - */ -#define SEND_DATA_B3_REQ 0x13 /* - * send capi-data-message int32 - * MsgLength capi-data ... int32 - * B3Length data .... - */ - -#define SEND_CONFIG 0x21 /* - */ - -#define SEND_POLLACK 0x73 /* T1 Watchdog */ - -/* - * LLI Messages from the ISDN-ControllerISDN Controller - */ - -#define RECEIVE_POLL 0x32 /* - * <- after SEND_POLL - */ -#define RECEIVE_INIT 0x27 /* - * <- after SEND_INIT int32 length - * byte total length b1struct board - * driver revision b1struct card - * type b1struct reserved b1struct - * serial number b1struct driver - * capability b1struct d-channel - * protocol b1struct CAPI-2.0 - * profile b1struct capi version - */ -#define RECEIVE_MESSAGE 0x21 /* - * <- after SEND_MESSAGE int32 - * AppllID int32 Length capi-data - * .... - */ -#define RECEIVE_DATA_B3_IND 0x22 /* - * received data int32 AppllID - * int32 Length capi-data ... - * int32 B3Length data ... - */ -#define RECEIVE_START 0x23 /* - * Handshake - */ -#define RECEIVE_STOP 0x24 /* - * Handshake - */ -#define RECEIVE_NEW_NCCI 0x25 /* - * int32 AppllID int32 NCCI int32 - * WindowSize - */ -#define RECEIVE_FREE_NCCI 0x26 /* - * int32 AppllID int32 NCCI - */ -#define RECEIVE_RELEASE 0x26 /* - * int32 AppllID int32 0xffffffff - */ -#define RECEIVE_TASK_READY 0x31 /* - * int32 tasknr - * int32 Length Taskname ... - */ -#define RECEIVE_DEBUGMSG 0x71 /* - * int32 Length message - * - */ -#define RECEIVE_POLLDWORD 0x75 /* t1pci in dword mode */ - -#define WRITE_REGISTER 0x00 -#define READ_REGISTER 0x01 - -/* - * port offsets - */ - -#define B1_READ 0x00 -#define B1_WRITE 0x01 -#define B1_INSTAT 0x02 -#define B1_OUTSTAT 0x03 -#define B1_ANALYSE 0x04 -#define B1_REVISION 0x05 -#define B1_RESET 0x10 - - -#define B1_STAT0(cardtype) ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l) -#define B1_STAT1(cardtype) (0x80E00000l) - -/* ---------------------------------------------------------------- */ - -static inline unsigned char b1outp(unsigned int base, - unsigned short offset, - unsigned char value) -{ - outb(value, base + offset); - return inb(base + B1_ANALYSE); -} - - -static inline int b1_rx_full(unsigned int base) -{ - return inb(base + B1_INSTAT) & 0x1; -} - -static inline unsigned char b1_get_byte(unsigned int base) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - while (!b1_rx_full(base) && time_before(jiffies, stop)); - if (b1_rx_full(base)) - return inb(base + B1_READ); - printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base); - return 0; -} - -static inline unsigned int b1_get_word(unsigned int base) -{ - unsigned int val = 0; - val |= b1_get_byte(base); - val |= (b1_get_byte(base) << 8); - val |= (b1_get_byte(base) << 16); - val |= (b1_get_byte(base) << 24); - return val; -} - -static inline int b1_tx_empty(unsigned int base) -{ - return inb(base + B1_OUTSTAT) & 0x1; -} - -static inline void b1_put_byte(unsigned int base, unsigned char val) -{ - while (!b1_tx_empty(base)); - b1outp(base, B1_WRITE, val); -} - -static inline int b1_save_put_byte(unsigned int base, unsigned char val) -{ - unsigned long stop = jiffies + 2 * HZ; - while (!b1_tx_empty(base) && time_before(jiffies,stop)); - if (!b1_tx_empty(base)) return -1; - b1outp(base, B1_WRITE, val); - return 0; -} - -static inline void b1_put_word(unsigned int base, unsigned int val) -{ - b1_put_byte(base, val & 0xff); - b1_put_byte(base, (val >> 8) & 0xff); - b1_put_byte(base, (val >> 16) & 0xff); - b1_put_byte(base, (val >> 24) & 0xff); -} - -static inline unsigned int b1_get_slice(unsigned int base, - unsigned char *dp) -{ - unsigned int len, i; - - len = i = b1_get_word(base); - while (i-- > 0) *dp++ = b1_get_byte(base); - return len; -} - -static inline void b1_put_slice(unsigned int base, - unsigned char *dp, unsigned int len) -{ - unsigned i = len; - b1_put_word(base, i); - while (i-- > 0) - b1_put_byte(base, *dp++); -} - -static void b1_wr_reg(unsigned int base, - unsigned int reg, - unsigned int value) -{ - b1_put_byte(base, WRITE_REGISTER); - b1_put_word(base, reg); - b1_put_word(base, value); -} - -static inline unsigned int b1_rd_reg(unsigned int base, - unsigned int reg) -{ - b1_put_byte(base, READ_REGISTER); - b1_put_word(base, reg); - return b1_get_word(base); - -} - -static inline void b1_reset(unsigned int base) -{ - b1outp(base, B1_RESET, 0); - udelay(55 * 2 * 1000); /* 2 TIC's */ - - b1outp(base, B1_RESET, 1); - udelay(55 * 2 * 1000); /* 2 TIC's */ - - b1outp(base, B1_RESET, 0); - udelay(55 * 2 * 1000); /* 2 TIC's */ -} - -static inline unsigned char b1_disable_irq(unsigned int base) -{ - return b1outp(base, B1_INSTAT, 0x00); -} - -/* ---------------------------------------------------------------- */ - -static inline void b1_set_test_bit(unsigned int base, - enum avmcardtype cardtype, - int onoff) -{ - b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20); -} - -static inline int b1_get_test_bit(unsigned int base, - enum avmcardtype cardtype) -{ - return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0; -} - -/* ---------------------------------------------------------------- */ - -#define T1_FASTLINK 0x00 -#define T1_SLOWLINK 0x08 - -#define T1_READ B1_READ -#define T1_WRITE B1_WRITE -#define T1_INSTAT B1_INSTAT -#define T1_OUTSTAT B1_OUTSTAT -#define T1_IRQENABLE 0x05 -#define T1_FIFOSTAT 0x06 -#define T1_RESETLINK 0x10 -#define T1_ANALYSE 0x11 -#define T1_IRQMASTER 0x12 -#define T1_IDENT 0x17 -#define T1_RESETBOARD 0x1f - -#define T1F_IREADY 0x01 -#define T1F_IHALF 0x02 -#define T1F_IFULL 0x04 -#define T1F_IEMPTY 0x08 -#define T1F_IFLAGS 0xF0 - -#define T1F_OREADY 0x10 -#define T1F_OHALF 0x20 -#define T1F_OEMPTY 0x40 -#define T1F_OFULL 0x80 -#define T1F_OFLAGS 0xF0 - -/* there are HEMA cards with 1k and 4k FIFO out */ -#define FIFO_OUTBSIZE 256 -#define FIFO_INPBSIZE 512 - -#define HEMA_VERSION_ID 0 -#define HEMA_PAL_ID 0 - -static inline void t1outp(unsigned int base, - unsigned short offset, - unsigned char value) -{ - outb(value, base + offset); -} - -static inline unsigned char t1inp(unsigned int base, - unsigned short offset) -{ - return inb(base + offset); -} - -static inline int t1_isfastlink(unsigned int base) -{ - return (inb(base + T1_IDENT) & ~0x82) == 1; -} - -static inline unsigned char t1_fifostatus(unsigned int base) -{ - return inb(base + T1_FIFOSTAT); -} - -static inline unsigned int t1_get_slice(unsigned int base, - unsigned char *dp) -{ - unsigned int len, i; -#ifdef FASTLINK_DEBUG - unsigned wcnt = 0, bcnt = 0; -#endif - - len = i = b1_get_word(base); - if (t1_isfastlink(base)) { - int status; - while (i > 0) { - status = t1_fifostatus(base) & (T1F_IREADY|T1F_IHALF); - if (i >= FIFO_INPBSIZE) status |= T1F_IFULL; - - switch (status) { - case T1F_IREADY|T1F_IHALF|T1F_IFULL: - insb(base+B1_READ, dp, FIFO_INPBSIZE); - dp += FIFO_INPBSIZE; - i -= FIFO_INPBSIZE; -#ifdef FASTLINK_DEBUG - wcnt += FIFO_INPBSIZE; -#endif - break; - case T1F_IREADY|T1F_IHALF: - insb(base+B1_READ,dp, i); -#ifdef FASTLINK_DEBUG - wcnt += i; -#endif - dp += i; - i = 0; - if (i == 0) - break; - /* fall through */ - default: - *dp++ = b1_get_byte(base); - i--; -#ifdef FASTLINK_DEBUG - bcnt++; -#endif - break; - } - } -#ifdef FASTLINK_DEBUG - if (wcnt) - printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n", - base, len, wcnt, bcnt); -#endif - } else { - while (i-- > 0) - *dp++ = b1_get_byte(base); - } - return len; -} - -static inline void t1_put_slice(unsigned int base, - unsigned char *dp, unsigned int len) -{ - unsigned i = len; - b1_put_word(base, i); - if (t1_isfastlink(base)) { - int status; - while (i > 0) { - status = t1_fifostatus(base) & (T1F_OREADY|T1F_OHALF); - if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY; - switch (status) { - case T1F_OREADY|T1F_OHALF|T1F_OEMPTY: - outsb(base+B1_WRITE, dp, FIFO_OUTBSIZE); - dp += FIFO_OUTBSIZE; - i -= FIFO_OUTBSIZE; - break; - case T1F_OREADY|T1F_OHALF: - outsb(base+B1_WRITE, dp, i); - dp += i; - i = 0; - break; - default: - b1_put_byte(base, *dp++); - i--; - break; - } - } - } else { - while (i-- > 0) - b1_put_byte(base, *dp++); - } -} - -static inline void t1_disable_irq(unsigned int base) -{ - t1outp(base, T1_IRQMASTER, 0x00); -} - -static inline void t1_reset(unsigned int base) -{ - /* reset T1 Controller */ - b1_reset(base); - /* disable irq on HEMA */ - t1outp(base, B1_INSTAT, 0x00); - t1outp(base, B1_OUTSTAT, 0x00); - t1outp(base, T1_IRQMASTER, 0x00); - /* reset HEMA board configuration */ - t1outp(base, T1_RESETBOARD, 0xf); -} - -static inline void b1_setinterrupt(unsigned int base, unsigned irq, - enum avmcardtype cardtype) -{ - switch (cardtype) { - case avm_t1isa: - t1outp(base, B1_INSTAT, 0x00); - t1outp(base, B1_INSTAT, 0x02); - t1outp(base, T1_IRQMASTER, 0x08); - break; - case avm_b1isa: - b1outp(base, B1_INSTAT, 0x00); - b1outp(base, B1_RESET, b1_irq_table[irq]); - b1outp(base, B1_INSTAT, 0x02); - break; - default: - case avm_m1: - case avm_m2: - case avm_b1pci: - b1outp(base, B1_INSTAT, 0x00); - b1outp(base, B1_RESET, 0xf0); - b1outp(base, B1_INSTAT, 0x02); - break; - case avm_c4: - case avm_t1pci: - b1outp(base, B1_RESET, 0xf0); - break; - } -} - -/* b1.c */ -int b1_detect(unsigned int base, enum avmcardtype cardtype); -void b1_getrevision(avmcard *card); -int b1_load_t4file(avmcard *card, capiloaddatapart * t4file); -int b1_load_config(avmcard *card, capiloaddatapart * config); -int b1_loaded(avmcard *card); - -int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); -void b1_reset_ctr(struct capi_ctr *ctrl); -void b1_register_appl(struct capi_ctr *ctrl, __u16 appl, - capi_register_params *rp); -void b1_release_appl(struct capi_ctr *ctrl, __u16 appl); -void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -void b1_parse_version(avmctrl_info *card); -void b1_handle_interrupt(avmcard * card); - -int b1ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl); - -/* b1dma.c */ -int b1pciv4_detect(avmcard *card); -int t1pci_detect(avmcard *card); -void b1dma_reset(avmcard *card); -void b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs); - -int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data); -void b1dma_reset_ctr(struct capi_ctr *ctrl); -void b1dma_remove_ctr(struct capi_ctr *ctrl); -void b1dma_register_appl(struct capi_ctr *ctrl, - __u16 appl, - capi_register_params *rp); -void b1dma_release_appl(struct capi_ctr *ctrl, __u16 appl); -void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); -int b1dmactl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl); - -#endif /* _AVMCARD_H_ */ diff --git a/drivers/isdn/avmb1/b1.c b/drivers/isdn/avmb1/b1.c deleted file mode 100644 index 67de070b..00000000 --- a/drivers/isdn/avmb1/b1.c +++ /dev/null @@ -1,741 +0,0 @@ -/* - * $Id$ - * - * Common module for AVM B1 cards. - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.12 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.11 1999/10/11 22:04:12 keil - * COMPAT_NEED_UACCESS (no include in isdn_compat.h) - * - * Revision 1.10 1999/09/15 08:16:03 calle - * Implementation of 64Bit extention complete. - * - * Revision 1.9 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.8 1999/08/22 20:26:22 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.7 1999/08/04 10:10:09 calle - * Bugfix: corrected /proc functions, added structure for new AVM cards. - * - * Revision 1.6 1999/07/23 08:51:04 calle - * small fix and typo in checkin before. - * - * Revision 1.5 1999/07/23 08:41:48 calle - * prepared for new AVM cards. - * - * Revision 1.4 1999/07/09 15:05:38 keil - * compat.h is now isdn_compat.h - * - * Revision 1.3 1999/07/06 07:41:59 calle - * - changes in /proc interface - * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. - * - * Revision 1.2 1999/07/05 15:09:47 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:23 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef COMPAT_NEED_UACCESS -#include -#endif -#include "capilli.h" -#include "avmcard.h" -#include "capicmd.h" -#include "capiutil.h" - -static char *revision = "$Revision$"; - -/* ------------------------------------------------------------- */ - -MODULE_AUTHOR("Carsten Paeth "); - -/* ------------------------------------------------------------- */ - -int b1_irq_table[16] = -{0, - 0, - 0, - 192, /* irq 3 */ - 32, /* irq 4 */ - 160, /* irq 5 */ - 96, /* irq 6 */ - 224, /* irq 7 */ - 0, - 64, /* irq 9 */ - 80, /* irq 10 */ - 208, /* irq 11 */ - 48, /* irq 12 */ - 0, - 0, - 112, /* irq 15 */ -}; - -/* ------------------------------------------------------------- */ - -int b1_detect(unsigned int base, enum avmcardtype cardtype) -{ - int onoff, i; - - /* - * Statusregister 0000 00xx - */ - if ((inb(base + B1_INSTAT) & 0xfc) - || (inb(base + B1_OUTSTAT) & 0xfc)) - return 1; - /* - * Statusregister 0000 001x - */ - b1outp(base, B1_INSTAT, 0x2); /* enable irq */ - /* b1outp(base, B1_OUTSTAT, 0x2); */ - if ((inb(base + B1_INSTAT) & 0xfe) != 0x2 - /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */) - return 2; - /* - * Statusregister 0000 000x - */ - b1outp(base, B1_INSTAT, 0x0); /* disable irq */ - b1outp(base, B1_OUTSTAT, 0x0); - if ((inb(base + B1_INSTAT) & 0xfe) - || (inb(base + B1_OUTSTAT) & 0xfe)) - return 3; - - for (onoff = !0, i= 0; i < 10 ; i++) { - b1_set_test_bit(base, cardtype, onoff); - if (b1_get_test_bit(base, cardtype) != onoff) - return 4; - onoff = !onoff; - } - - if (cardtype == avm_m1) - return 0; - - if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01) - return 5; - - return 0; -} - -void b1_getrevision(avmcard *card) -{ - card->class = inb(card->port + B1_ANALYSE); - card->revision = inb(card->port + B1_REVISION); -} - -int b1_load_t4file(avmcard *card, capiloaddatapart * t4file) -{ - unsigned char buf[256]; - unsigned char *dp; - int i, left, retval; - unsigned int base = card->port; - - dp = t4file->data; - left = t4file->len; - while (left > sizeof(buf)) { - if (t4file->user) { - retval = copy_from_user(buf, dp, sizeof(buf)); - if (retval) - return -EFAULT; - } else { - memcpy(buf, dp, sizeof(buf)); - } - for (i = 0; i < sizeof(buf); i++) - if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - left -= sizeof(buf); - dp += sizeof(buf); - } - if (left) { - if (t4file->user) { - retval = copy_from_user(buf, dp, left); - if (retval) - return -EFAULT; - } else { - memcpy(buf, dp, left); - } - for (i = 0; i < left; i++) - if (b1_save_put_byte(base, buf[i]) < 0) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - } - return 0; -} - -int b1_load_config(avmcard *card, capiloaddatapart * config) -{ - unsigned char buf[256]; - unsigned char *dp; - unsigned int base = card->port; - int i, j, left, retval; - - dp = config->data; - left = config->len; - if (left) { - b1_put_byte(base, SEND_CONFIG); - b1_put_word(base, 1); - b1_put_byte(base, SEND_CONFIG); - b1_put_word(base, left); - } - while (left > sizeof(buf)) { - if (config->user) { - retval = copy_from_user(buf, dp, sizeof(buf)); - if (retval) - return -EFAULT; - } else { - memcpy(buf, dp, sizeof(buf)); - } - for (i = 0; i < sizeof(buf); ) { - b1_put_byte(base, SEND_CONFIG); - for (j=0; j < 4; j++) { - b1_put_byte(base, buf[i++]); - } - } - left -= sizeof(buf); - dp += sizeof(buf); - } - if (left) { - if (config->user) { - retval = copy_from_user(buf, dp, left); - if (retval) - return -EFAULT; - } else { - memcpy(buf, dp, left); - } - for (i = 0; i < left; ) { - b1_put_byte(base, SEND_CONFIG); - for (j=0; j < 4; j++) { - if (i < left) - b1_put_byte(base, buf[i++]); - else - b1_put_byte(base, 0); - } - } - } - return 0; -} - -int b1_loaded(avmcard *card) -{ - unsigned int base = card->port; - unsigned long stop; - unsigned char ans; - unsigned long tout = 2; - - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_tx_empty(base)) - break; - } - if (!b1_tx_empty(base)) { - printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?\n", - card->name); - return 0; - } - b1_put_byte(base, SEND_POLL); - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_rx_full(base)) { - if ((ans = b1_get_byte(base)) == RECEIVE_POLL) { - return 1; - } - printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not running\n", - card->name, ans); - return 0; - } - } - printk(KERN_ERR "%s: b1_loaded: firmware not running\n", card->name); - return 0; -} - -/* ------------------------------------------------------------- */ - -int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int retval; - - b1_reset(port); - - if ((retval = b1_load_t4file(card, &data->firmware))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - b1_disable_irq(port); - - if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(card, &data->configuration))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1_loaded(card)) { - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - save_flags(flags); - cli(); - b1_setinterrupt(port, card->irq, card->cardtype); - b1_put_byte(port, SEND_INIT); - b1_put_word(port, AVM_NAPPS); - b1_put_word(port, AVM_NCCI_PER_CHANNEL*2); - b1_put_word(port, ctrl->cnr - 1); - restore_flags(flags); - - return 0; -} - -void b1_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - ctrl->reseted(ctrl); -} - -void b1_register_appl(struct capi_ctr *ctrl, - __u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int nconn, want = rp->level3cnt; - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel; - - save_flags(flags); - cli(); - b1_put_byte(port, SEND_REGISTER); - b1_put_word(port, appl); - b1_put_word(port, 1024 * (nconn+1)); - b1_put_word(port, nconn); - b1_put_word(port, rp->datablkcnt); - b1_put_word(port, rp->datablklen); - restore_flags(flags); - - ctrl->appl_registered(ctrl, appl); -} - -void b1_release_appl(struct capi_ctr *ctrl, __u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - - save_flags(flags); - cli(); - b1_put_byte(port, SEND_RELEASE); - b1_put_word(port, appl); - restore_flags(flags); -} - -void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - __u16 len = CAPIMSG_LEN(skb->data); - __u8 cmd = CAPIMSG_COMMAND(skb->data); - __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - save_flags(flags); - cli(); - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - __u16 dlen = CAPIMSG_DATALEN(skb->data); - b1_put_byte(port, SEND_DATA_B3_REQ); - b1_put_slice(port, skb->data, len); - b1_put_slice(port, skb->data + len, dlen); - } else { - b1_put_byte(port, SEND_MESSAGE); - b1_put_slice(port, skb->data, len); - } - restore_flags(flags); - dev_kfree_skb(skb); -} - -/* ------------------------------------------------------------- */ - -void b1_parse_version(avmctrl_info *cinfo) -{ - struct capi_ctr *ctrl = cinfo->capi_ctrl; - avmcard *card = cinfo->card; - capi_profile *profp; - __u8 *dversion; - __u8 flag; - int i, j; - - for (j = 0; j < AVM_MAXVERSION; j++) - cinfo->version[j] = "\0\0" + 1; - for (i = 0, j = 0; - j < AVM_MAXVERSION && i < cinfo->versionlen; - j++, i += cinfo->versionbuf[i] + 1) - cinfo->version[j] = &cinfo->versionbuf[i + 1]; - - strncpy(ctrl->serial, cinfo->version[VER_SERIAL], CAPI_SERIAL_LEN); - memcpy(&ctrl->profile, cinfo->version[VER_PROFILE],sizeof(capi_profile)); - strncpy(ctrl->manu, "AVM GmbH", CAPI_MANUFACTURER_LEN); - dversion = cinfo->version[VER_DRIVER]; - ctrl->version.majorversion = 2; - ctrl->version.minorversion = 0; - ctrl->version.majormanuversion = (((dversion[0] - '0') & 0xf) << 4); - ctrl->version.majormanuversion |= ((dversion[2] - '0') & 0xf); - ctrl->version.minormanuversion = (dversion[3] - '0') << 4; - ctrl->version.minormanuversion |= - (dversion[5] - '0') * 10 + ((dversion[6] - '0') & 0xf); - - profp = &ctrl->profile; - - flag = ((__u8 *)(profp->manu))[1]; - switch (flag) { - case 0: if (cinfo->version[VER_CARDTYPE]) - strcpy(cinfo->cardname, cinfo->version[VER_CARDTYPE]); - else strcpy(cinfo->cardname, "B1"); - break; - case 3: strcpy(cinfo->cardname,"PCMCIA B"); break; - case 4: strcpy(cinfo->cardname,"PCMCIA M1"); break; - case 5: strcpy(cinfo->cardname,"PCMCIA M2"); break; - case 6: strcpy(cinfo->cardname,"B1 V3.0"); break; - case 7: strcpy(cinfo->cardname,"B1 PCI"); break; - default: sprintf(cinfo->cardname, "AVM?%u", (unsigned int)flag); break; - } - printk(KERN_NOTICE "%s: card %d \"%s\" ready.\n", - card->name, ctrl->cnr, cinfo->cardname); - - flag = ((__u8 *)(profp->manu))[3]; - if (flag) - printk(KERN_NOTICE "%s: card %d Protocol:%s%s%s%s%s%s%s\n", - card->name, - ctrl->cnr, - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - - flag = ((__u8 *)(profp->manu))[5]; - if (flag) - printk(KERN_NOTICE "%s: card %d Linetype:%s%s%s%s\n", - card->name, - ctrl->cnr, - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); -} - -/* ------------------------------------------------------------- */ - -void b1_handle_interrupt(avmcard * card) -{ - avmctrl_info *cinfo = &card->ctrlinfo[0]; - struct capi_ctr *ctrl = cinfo->capi_ctrl; - unsigned char b1cmd; - struct sk_buff *skb; - - unsigned ApplId; - unsigned MsgLen; - unsigned DataB3Len; - unsigned NCCI; - unsigned WindowSize; - - if (!b1_rx_full(card->port)) - return; - - b1cmd = b1_get_byte(card->port); - - switch (b1cmd) { - - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - DataB3Len = b1_get_slice(card->port, card->databuf); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf+MsgLen, 0, 30-MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len + MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - WindowSize = b1_get_word(card->port); - - ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); - - break; - - case RECEIVE_FREE_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - - if (NCCI != 0xffffffff) - ctrl->free_ncci(ctrl, ApplId, NCCI); - else ctrl->appl_released(ctrl, ApplId); - break; - - case RECEIVE_START: - /* b1_put_byte(card->port, SEND_POLLACK); */ - ctrl->resume_output(ctrl); - break; - - case RECEIVE_STOP: - ctrl->suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - ctrl->ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = b1_get_slice(card->port, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = b1_get_slice(card->port, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - case 0xff: - printk(KERN_ERR "%s: card removed ?\n", card->name); - return; - default: - printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } -} - -/* ------------------------------------------------------------- */ -int b1ctl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - __u8 flag; - int len = 0; - char *s; - - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - default: s = "???"; break; - } - len += sprintf(page+len, "%-16s %s\n", "type", s); - if (card->cardtype == avm_t1isa) - len += sprintf(page+len, "%-16s %d\n", "cardnr", card->cardnr); - if ((s = cinfo->version[VER_DRIVER]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((__u8 *)(ctrl->profile.manu))[3]; - if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((__u8 *)(ctrl->profile.manu))[5]; - if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); -} - -/* ------------------------------------------------------------- */ - -EXPORT_SYMBOL(b1_irq_table); - -EXPORT_SYMBOL(b1_detect); -EXPORT_SYMBOL(b1_getrevision); -EXPORT_SYMBOL(b1_load_t4file); -EXPORT_SYMBOL(b1_load_config); -EXPORT_SYMBOL(b1_loaded); -EXPORT_SYMBOL(b1_load_firmware); -EXPORT_SYMBOL(b1_reset_ctr); -EXPORT_SYMBOL(b1_register_appl); -EXPORT_SYMBOL(b1_release_appl); -EXPORT_SYMBOL(b1_send_message); - -EXPORT_SYMBOL(b1_parse_version); -EXPORT_SYMBOL(b1_handle_interrupt); - -EXPORT_SYMBOL(b1ctl_read_proc); - -#ifdef MODULE -#define b1_init init_module -void cleanup_module(void); -#endif - -int b1_init(void) -{ - char *p; - char rev[10]; - - if ((p = strchr(revision, ':'))) { - strncpy(rev, p + 1, sizeof(rev)); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, "1.0"); - - printk(KERN_INFO "b1: revision %s\n", rev); - - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ -} -#endif diff --git a/drivers/isdn/avmb1/b1dma.c b/drivers/isdn/avmb1/b1dma.c deleted file mode 100644 index 4e4d35a3..00000000 --- a/drivers/isdn/avmb1/b1dma.c +++ /dev/null @@ -1,989 +0,0 @@ -/* - * $Id$ - * - * Common module for AVM B1 cards that support dma with AMCC - * - * (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.2 2000/01/25 14:44:47 calle - * typo in b1pciv4_detect(). - * - * Revision 1.1 2000/01/25 14:36:43 calle - * common function for T1 PCI and B1 PCI V4. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef COMPAT_NEED_UACCESS -#include -#endif -#include "capilli.h" -#include "avmcard.h" -#include "capicmd.h" -#include "capiutil.h" - -static char *revision = "$Revision$"; - -/* ------------------------------------------------------------- */ - -MODULE_AUTHOR("Carsten Paeth "); - -int suppress_pollack = 0; -MODULE_PARM(suppress_pollack, "0-1i"); - -/* ------------------------------------------------------------- */ - -static void b1dma_dispatch_tx(avmcard *card); - -/* ------------------------------------------------------------- */ - -/* S5933 */ - -#define AMCC_RXPTR 0x24 -#define AMCC_RXLEN 0x28 -#define AMCC_TXPTR 0x2c -#define AMCC_TXLEN 0x30 - -#define AMCC_INTCSR 0x38 -# define EN_READ_TC_INT 0x00008000L -# define EN_WRITE_TC_INT 0x00004000L -# define EN_TX_TC_INT EN_READ_TC_INT -# define EN_RX_TC_INT EN_WRITE_TC_INT -# define AVM_FLAG 0x30000000L - -# define ANY_S5933_INT 0x00800000L -# define READ_TC_INT 0x00080000L -# define WRITE_TC_INT 0x00040000L -# define TX_TC_INT READ_TC_INT -# define RX_TC_INT WRITE_TC_INT -# define MASTER_ABORT_INT 0x00100000L -# define TARGET_ABORT_INT 0x00200000L -# define BUS_MASTER_INT 0x00200000L -# define ALL_INT 0x000C0000L - -#define AMCC_MCSR 0x3c -# define A2P_HI_PRIORITY 0x00000100L -# define EN_A2P_TRANSFERS 0x00000400L -# define P2A_HI_PRIORITY 0x00001000L -# define EN_P2A_TRANSFERS 0x00004000L -# define RESET_A2P_FLAGS 0x04000000L -# define RESET_P2A_FLAGS 0x02000000L - -/* ------------------------------------------------------------- */ - -#define b1dmaoutmeml(addr, value) writel(value, addr) -#define b1dmainmeml(addr) readl(addr) -#define b1dmaoutmemw(addr, value) writew(value, addr) -#define b1dmainmemw(addr) readw(addr) -#define b1dmaoutmemb(addr, value) writeb(value, addr) -#define b1dmainmemb(addr) readb(addr) - -/* ------------------------------------------------------------- */ - -static inline int b1dma_tx_empty(unsigned int port) -{ - return inb(port + 0x03) & 0x1; -} - -static inline int b1dma_rx_full(unsigned int port) -{ - return inb(port + 0x02) & 0x1; -} - -static int b1dma_tolink(avmcard *card, void *buf, unsigned int len) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - unsigned char *s = (unsigned char *)buf; - while (len--) { - while ( !b1dma_tx_empty(card->port) - && time_before(jiffies, stop)); - if (!b1dma_tx_empty(card->port)) - return -1; - t1outp(card->port, 0x01, *s++); - } - return 0; -} - -static int b1dma_fromlink(avmcard *card, void *buf, unsigned int len) -{ - unsigned long stop = jiffies + 1 * HZ; /* maximum wait time 1 sec */ - unsigned char *s = (unsigned char *)buf; - while (len--) { - while ( !b1dma_rx_full(card->port) - && time_before(jiffies, stop)); - if (!b1dma_rx_full(card->port)) - return -1; - *s++ = t1inp(card->port, 0x00); - } - return 0; -} - -static int WriteReg(avmcard *card, __u32 reg, __u8 val) -{ - __u8 cmd = 0x00; - if ( b1dma_tolink(card, &cmd, 1) == 0 - && b1dma_tolink(card, ®, 4) == 0) { - __u32 tmp = val; - return b1dma_tolink(card, &tmp, 4); - } - return -1; -} - -static __u8 ReadReg(avmcard *card, __u32 reg) -{ - __u8 cmd = 0x01; - if ( b1dma_tolink(card, &cmd, 1) == 0 - && b1dma_tolink(card, ®, 4) == 0) { - __u32 tmp; - if (b1dma_fromlink(card, &tmp, 4) == 0) - return (__u8)tmp; - } - return 0xff; -} - -/* ------------------------------------------------------------- */ - -static inline void _put_byte(void **pp, __u8 val) -{ - __u8 *s = *pp; - *s++ = val; - *pp = s; -} - -static inline void _put_word(void **pp, __u32 val) -{ - __u8 *s = *pp; - *s++ = val & 0xff; - *s++ = (val >> 8) & 0xff; - *s++ = (val >> 16) & 0xff; - *s++ = (val >> 24) & 0xff; - *pp = s; -} - -static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) -{ - unsigned i = len; - _put_word(pp, i); - while (i-- > 0) - _put_byte(pp, *dp++); -} - -static inline __u8 _get_byte(void **pp) -{ - __u8 *s = *pp; - __u8 val; - val = *s++; - *pp = s; - return val; -} - -static inline __u32 _get_word(void **pp) -{ - __u8 *s = *pp; - __u32 val; - val = *s++; - val |= (*s++ << 8); - val |= (*s++ << 16); - val |= (*s++ << 24); - *pp = s; - return val; -} - -static inline __u32 _get_slice(void **pp, unsigned char *dp) -{ - unsigned int len, i; - - len = i = _get_word(pp); - while (i-- > 0) *dp++ = _get_byte(pp); - return len; -} - -/* ------------------------------------------------------------- */ - -void b1dma_reset(avmcard *card) -{ - unsigned long flags; - - save_flags(flags); - cli(); - card->csr = 0x0; - b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); - b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0); - b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0); - - t1outp(card->port, 0x10, 0x00); - t1outp(card->port, 0x07, 0x00); - - restore_flags(flags); - - b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - udelay(10 * 1000); - b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ - udelay(10 * 1000); - b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - if (card->cardtype == avm_t1pci) - udelay(42 * 1000); - else - udelay(10 * 1000); -} - -/* ------------------------------------------------------------- */ - -int b1dma_detect(avmcard *card) -{ - b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - udelay(10 * 1000); - b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */ - udelay(10 * 1000); - b1dmaoutmeml(card->mbase+AMCC_MCSR, 0); - udelay(42 * 1000); - - b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0); - b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0); - card->csr = 0x0; - b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); - - if (b1dmainmeml(card->mbase+AMCC_MCSR) != 0x000000E6) - return 1; - - b1dmaoutmeml(card->mbase+AMCC_RXPTR, 0xffffffff); - b1dmaoutmeml(card->mbase+AMCC_TXPTR, 0xffffffff); - if ( b1dmainmeml(card->mbase+AMCC_RXPTR) != 0xfffffffc - || b1dmainmeml(card->mbase+AMCC_TXPTR) != 0xfffffffc) - return 2; - - b1dmaoutmeml(card->mbase+AMCC_RXPTR, 0x0); - b1dmaoutmeml(card->mbase+AMCC_TXPTR, 0x0); - if ( b1dmainmeml(card->mbase+AMCC_RXPTR) != 0x0 - || b1dmainmeml(card->mbase+AMCC_TXPTR) != 0x0) - return 3; - - t1outp(card->port, 0x10, 0x00); - t1outp(card->port, 0x07, 0x00); - - t1outp(card->port, 0x02, 0x02); - t1outp(card->port, 0x03, 0x02); - - if ( (t1inp(card->port, 0x02) & 0xFE) != 0x02 - || t1inp(card->port, 0x3) != 0x03) - return 4; - - t1outp(card->port, 0x02, 0x00); - t1outp(card->port, 0x03, 0x00); - - if ( (t1inp(card->port, 0x02) & 0xFE) != 0x00 - || t1inp(card->port, 0x3) != 0x01) - return 5; - - return 0; -} - -int t1pci_detect(avmcard *card) -{ - int ret; - - if ((ret = b1dma_detect(card)) != 0) - return ret; - - /* Transputer test */ - - if ( WriteReg(card, 0x80001000, 0x11) != 0 - || WriteReg(card, 0x80101000, 0x22) != 0 - || WriteReg(card, 0x80201000, 0x33) != 0 - || WriteReg(card, 0x80301000, 0x44) != 0) - return 6; - - if ( ReadReg(card, 0x80001000) != 0x11 - || ReadReg(card, 0x80101000) != 0x22 - || ReadReg(card, 0x80201000) != 0x33 - || ReadReg(card, 0x80301000) != 0x44) - return 7; - - if ( WriteReg(card, 0x80001000, 0x55) != 0 - || WriteReg(card, 0x80101000, 0x66) != 0 - || WriteReg(card, 0x80201000, 0x77) != 0 - || WriteReg(card, 0x80301000, 0x88) != 0) - return 8; - - if ( ReadReg(card, 0x80001000) != 0x55 - || ReadReg(card, 0x80101000) != 0x66 - || ReadReg(card, 0x80201000) != 0x77 - || ReadReg(card, 0x80301000) != 0x88) - return 9; - - return 0; -} - -int b1pciv4_detect(avmcard *card) -{ - int ret, i; - - if ((ret = b1dma_detect(card)) != 0) - return ret; - - for (i=0; i < 5 ; i++) { - if (WriteReg(card, 0x80A00000, 0x21) != 0) - return 6; - if ((ReadReg(card, 0x80A00000) & 0x01) != 0x01) - return 7; - } - for (i=0; i < 5 ; i++) { - if (WriteReg(card, 0x80A00000, 0x20) != 0) - return 8; - if ((ReadReg(card, 0x80A00000) & 0x01) != 0x00) - return 9; - } - - return 0; -} - -/* ------------------------------------------------------------- */ - -static void b1dma_dispatch_tx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - unsigned long flags; - struct sk_buff *skb; - __u8 cmd, subcmd; - __u16 len; - __u32 txlen; - int inint; - void *p; - - save_flags(flags); - cli(); - - inint = card->interrupt; - - if (card->csr & EN_TX_TC_INT) { /* tx busy */ - restore_flags(flags); - return; - } - - skb = skb_dequeue(&dma->send_queue); - if (!skb) { -#ifdef CONFIG_B1DMA_DEBUG - printk(KERN_DEBUG "tx(%d): underrun\n", inint); -#endif - restore_flags(flags); - return; - } - - len = CAPIMSG_LEN(skb->data); - - if (len) { - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - p = dma->sendbuf; - - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - __u16 dlen = CAPIMSG_DATALEN(skb->data); - _put_byte(&p, SEND_DATA_B3_REQ); - _put_slice(&p, skb->data, len); - _put_slice(&p, skb->data + len, dlen); - } else { - _put_byte(&p, SEND_MESSAGE); - _put_slice(&p, skb->data, len); - } - txlen = (__u8 *)p - (__u8 *)dma->sendbuf; -#ifdef CONFIG_B1DMA_DEBUG - printk(KERN_DEBUG "tx(%d): put msg len=%d\n", - inint, txlen); -#endif - } else { - txlen = skb->len-2; -#ifdef CONFIG_B1DMA_POLLDEBUG - if (skb->data[2] == SEND_POLLACK) - printk(KERN_INFO "%s: send ack\n", card->name); -#endif -#ifdef CONFIG_B1DMA_DEBUG - printk(KERN_DEBUG "tx(%d): put 0x%x len=%d\n", - inint, skb->data[2], txlen); -#endif - memcpy(dma->sendbuf, skb->data+2, skb->len-2); - } - txlen = (txlen + 3) & ~3; - - b1dmaoutmeml(card->mbase+AMCC_TXPTR, virt_to_phys(dma->sendbuf)); - b1dmaoutmeml(card->mbase+AMCC_TXLEN, txlen); - - card->csr |= EN_TX_TC_INT; - - if (!inint) - b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); - - restore_flags(flags); - dev_kfree_skb(skb); -} - -/* ------------------------------------------------------------- */ - -static void queue_pollack(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(3, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost poll ack\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_POLLACK); - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - b1dma_dispatch_tx(card); -} - -/* ------------------------------------------------------------- */ - -static void b1dma_handle_rx(avmcard *card) -{ - avmctrl_info *cinfo = &card->ctrlinfo[0]; - avmcard_dmainfo *dma = card->dma; - struct capi_ctr *ctrl = cinfo->capi_ctrl; - struct sk_buff *skb; - void *p = dma->recvbuf+4; - __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; - __u8 b1cmd = _get_byte(&p); - -#ifdef CONFIG_B1DMA_DEBUG - printk(KERN_DEBUG "rx: 0x%x %lu\n", b1cmd, (unsigned long)dma->recvlen); -#endif - - switch (b1cmd) { - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - DataB3Len = _get_slice(&p, card->databuf); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf+MsgLen, 0, 30-MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - WindowSize = _get_word(&p); - - ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); - - break; - - case RECEIVE_FREE_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - - if (NCCI != 0xffffffff) - ctrl->free_ncci(ctrl, ApplId, NCCI); - else ctrl->appl_released(ctrl, ApplId); - break; - - case RECEIVE_START: -#ifdef CONFIG_B1DMA_POLLDEBUG - printk(KERN_INFO "%s: receive poll\n", card->name); -#endif - if (!suppress_pollack) - queue_pollack(card); - ctrl->resume_output(ctrl); - break; - - case RECEIVE_STOP: - ctrl->suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - ctrl->ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - default: - printk(KERN_ERR "%s: b1dma_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } -} - -/* ------------------------------------------------------------- */ - -static void b1dma_handle_interrupt(avmcard *card) -{ - __u32 status = b1dmainmeml(card->mbase+AMCC_INTCSR); - __u32 newcsr; - - if ((status & ANY_S5933_INT) == 0) - return; - - newcsr = card->csr | (status & ALL_INT); - if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; - if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT; - b1dmaoutmeml(card->mbase+AMCC_INTCSR, newcsr); - - if ((status & RX_TC_INT) != 0) { - __u8 *recvbuf = card->dma->recvbuf; - __u32 rxlen; - if (card->dma->recvlen == 0) { - card->dma->recvlen = *((__u32 *)recvbuf); - rxlen = (card->dma->recvlen + 3) & ~3; - b1dmaoutmeml(card->mbase+AMCC_RXPTR, - virt_to_phys(recvbuf+4)); - b1dmaoutmeml(card->mbase+AMCC_RXLEN, rxlen); - } else { - b1dma_handle_rx(card); - card->dma->recvlen = 0; - b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(recvbuf)); - b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4); - } - } - - if ((status & TX_TC_INT) != 0) { - card->csr &= ~EN_TX_TC_INT; - b1dma_dispatch_tx(card); -#if 1 - } else if (card->csr & EN_TX_TC_INT) { - if (b1dmainmeml(card->mbase+AMCC_TXLEN) == 0) { - card->csr &= ~EN_TX_TC_INT; - b1dma_dispatch_tx(card); - } -#endif - } - b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); -} - -void b1dma_interrupt(int interrupt, void *devptr, struct pt_regs *regs) -{ - avmcard *card; - - card = (avmcard *) devptr; - - if (!card) { - printk(KERN_WARNING "b1dma: interrupt: wrong device\n"); - return; - } - if (card->interrupt) { - printk(KERN_ERR "%s: reentering interrupt hander\n", card->name); - return; - } - - card->interrupt = 1; - - b1dma_handle_interrupt(card); - - card->interrupt = 0; -} - -/* ------------------------------------------------------------- */ - -static int b1dma_loaded(avmcard *card) -{ - unsigned long stop; - unsigned char ans; - unsigned long tout = 2; - unsigned int base = card->port; - - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_tx_empty(base)) - break; - } - if (!b1_tx_empty(base)) { - printk(KERN_ERR "%s: b1dma_loaded: tx err, corrupted t4 file ?\n", - card->name); - return 0; - } - b1_put_byte(base, SEND_POLLACK); - for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) { - if (b1_rx_full(base)) { - if ((ans = b1_get_byte(base)) == RECEIVE_POLLDWORD) { - return 1; - } - printk(KERN_ERR "%s: b1dma_loaded: got 0x%x, firmware not running in dword mode\n", card->name, ans); - return 0; - } - } - printk(KERN_ERR "%s: b1dma_loaded: firmware not running\n", card->name); - return 0; -} - -/* ------------------------------------------------------------- */ - -static void b1dma_send_init(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(15, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_INIT); - _put_word(&p, AVM_NAPPS); - _put_word(&p, AVM_NCCI_PER_CHANNEL*30); - _put_word(&p, card->cardnr - 1); - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - b1dma_dispatch_tx(card); -} - -int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned long flags; - int retval; - - b1dma_reset(card); - - if ((retval = b1_load_t4file(card, &data->firmware))) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(card, &data->configuration))) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1dma_loaded(card)) { - b1dma_reset(card); - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - save_flags(flags); - cli(); - - card->csr = AVM_FLAG; - b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); - b1dmaoutmeml(card->mbase+AMCC_MCSR, - EN_A2P_TRANSFERS|EN_P2A_TRANSFERS - |A2P_HI_PRIORITY|P2A_HI_PRIORITY - |RESET_A2P_FLAGS|RESET_P2A_FLAGS); - t1outp(card->port, 0x07, 0x30); - t1outp(card->port, 0x10, 0xF0); - - card->dma->recvlen = 0; - b1dmaoutmeml(card->mbase+AMCC_RXPTR, virt_to_phys(card->dma->recvbuf)); - b1dmaoutmeml(card->mbase+AMCC_RXLEN, 4); - card->csr |= EN_RX_TC_INT; - b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr); - restore_flags(flags); - - b1dma_send_init(card); - - return 0; -} - -void b1dma_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - - b1dma_reset(card); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - ctrl->reseted(ctrl); -} - - -/* ------------------------------------------------------------- */ - - -void b1dma_register_appl(struct capi_ctr *ctrl, - __u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - int want = rp->level3cnt; - int nconn; - void *p; - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel; - - skb = alloc_skb(23, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_REGISTER); - _put_word(&p, appl); - _put_word(&p, 1024 * (nconn+1)); - _put_word(&p, nconn); - _put_word(&p, rp->datablkcnt); - _put_word(&p, rp->datablklen); - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - b1dma_dispatch_tx(card); - - ctrl->appl_registered(ctrl, appl); -} - -/* ------------------------------------------------------------- */ - -void b1dma_release_appl(struct capi_ctr *ctrl, __u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - void *p; - - skb = alloc_skb(7, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost release appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_RELEASE); - _put_word(&p, appl); - - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - skb_queue_tail(&card->dma->send_queue, skb); - b1dma_dispatch_tx(card); -} - -/* ------------------------------------------------------------- */ - -void b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - skb_queue_tail(&card->dma->send_queue, skb); - b1dma_dispatch_tx(card); -} - -/* ------------------------------------------------------------- */ - -int b1dmactl_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned long flags; - __u8 flag; - int len = 0; - char *s; - __u32 txaddr, txlen, rxaddr, rxlen, csr; - - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - default: s = "???"; break; - } - len += sprintf(page+len, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((__u8 *)(ctrl->profile.manu))[3]; - if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((__u8 *)(ctrl->profile.manu))[5]; - if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); - - save_flags(flags); - cli(); - - txaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x2c)); - txaddr -= (__u32)card->dma->sendbuf; - txlen = b1dmainmeml(card->mbase+0x30); - - rxaddr = (__u32)phys_to_virt(b1dmainmeml(card->mbase+0x24)); - rxaddr -= (__u32)card->dma->recvbuf; - rxlen = b1dmainmeml(card->mbase+0x28); - - csr = b1dmainmeml(card->mbase+AMCC_INTCSR); - - restore_flags(flags); - - len += sprintf(page+len, "%-16s 0x%lx\n", - "csr (cached)", (unsigned long)card->csr); - len += sprintf(page+len, "%-16s 0x%lx\n", - "csr", (unsigned long)csr); - len += sprintf(page+len, "%-16s %lu\n", - "txoff", (unsigned long)txaddr); - len += sprintf(page+len, "%-16s %lu\n", - "txlen", (unsigned long)txlen); - len += sprintf(page+len, "%-16s %lu\n", - "rxoff", (unsigned long)rxaddr); - len += sprintf(page+len, "%-16s %lu\n", - "rxlen", (unsigned long)rxlen); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); -} - -/* ------------------------------------------------------------- */ - -EXPORT_SYMBOL(b1dma_reset); -EXPORT_SYMBOL(t1pci_detect); -EXPORT_SYMBOL(b1pciv4_detect); -EXPORT_SYMBOL(b1dma_interrupt); - -EXPORT_SYMBOL(b1dma_load_firmware); -EXPORT_SYMBOL(b1dma_reset_ctr); -EXPORT_SYMBOL(b1dma_register_appl); -EXPORT_SYMBOL(b1dma_release_appl); -EXPORT_SYMBOL(b1dma_send_message); -EXPORT_SYMBOL(b1dmactl_read_proc); - -#ifdef MODULE -#define b1dma_init init_module -void cleanup_module(void); -#endif - -int b1dma_init(void) -{ - char *p; - char rev[10]; - - if ((p = strchr(revision, ':'))) { - strncpy(rev, p + 1, sizeof(rev)); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, "1.0"); - - printk(KERN_INFO "b1dma: revision %s\n", rev); - - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ -} -#endif diff --git a/drivers/isdn/avmb1/b1isa.c b/drivers/isdn/avmb1/b1isa.c deleted file mode 100644 index 4416d0bd..00000000 --- a/drivers/isdn/avmb1/b1isa.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * $Id$ - * - * Module for AVM B1 ISA-card. - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.6 2000/01/25 14:37:39 calle - * new message after successfull detection including card revision and - * used resources. - * - * Revision 1.5 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.4 1999/08/22 20:26:24 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.3 1999/07/09 15:05:40 keil - * compat.h is now isdn_compat.h - * - * Revision 1.2 1999/07/05 15:09:49 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:27 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "capicmd.h" -#include "capiutil.h" -#include "capilli.h" -#include "avmcard.h" - -static char *revision = "$Revision$"; - -/* ------------------------------------------------------------- */ - -MODULE_AUTHOR("Carsten Paeth "); - -/* ------------------------------------------------------------- */ - -static void b1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) -{ - avmcard *card; - - card = (avmcard *) devptr; - - if (!card) { - printk(KERN_WARNING "b1_interrupt: wrong device\n"); - return; - } - if (card->interrupt) { - printk(KERN_ERR "b1_interrupt: reentering interrupt hander (%s)\n", card->name); - return; - } - - card->interrupt = 1; - - b1_handle_interrupt(card); - - card->interrupt = 0; -} -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface *di; - -/* ------------------------------------------------------------- */ - -static void b1isa_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - di->detach_ctr(ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - - MOD_DEC_USE_COUNT; -} - -/* ------------------------------------------------------------- */ - -static int b1isa_add_card(struct capi_driver *driver, struct capicardparams *p) -{ - avmctrl_info *cinfo; - avmcard *card; - int retval; - - MOD_INC_USE_COUNT; - - card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); - - if (!card) { - printk(KERN_WARNING "b1isa: no memory.\n"); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card, 0, sizeof(avmcard)); - cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "b1isa: no memory.\n"); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(cinfo, 0, sizeof(avmctrl_info)); - card->ctrlinfo = cinfo; - cinfo->card = card; - sprintf(card->name, "b1isa-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->cardtype = avm_b1isa; - - if (check_region(card->port, AVMB1_PORTLEN)) { - printk(KERN_WARNING - "b1isa: ports 0x%03x-0x%03x in use.\n", - card->port, card->port + AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - if (b1_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "b1isa: irq %d not valid.\n", card->irq); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EINVAL; - } - if ( card->port != 0x150 && card->port != 0x250 - && card->port != 0x300 && card->port != 0x340) { - printk(KERN_WARNING "b1isa: illegal port 0x%x.\n", card->port); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EINVAL; - } - b1_reset(card->port); - if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "b1isa: NO card at 0x%x (%d)\n", - card->port, retval); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - b1_reset(card->port); - b1_getrevision(card); - - request_region(p->port, AVMB1_PORTLEN, card->name); - - retval = request_irq(card->irq, b1isa_interrupt, 0, card->name, card); - if (retval) { - printk(KERN_ERR "b1isa: unable to get IRQ %d.\n", card->irq); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); - if (!cinfo->capi_ctrl) { - printk(KERN_ERR "b1isa: attach controller failed.\n"); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - printk(KERN_INFO - "%s: AVM B1 ISA at i/o %#x, irq %d, revision %d\n", - driver->name, card->port, card->irq, card->revision); - - return 0; -} - -static char *b1isa_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static struct capi_driver b1isa_driver = { - "b1isa", - "0.0", - b1_load_firmware, - b1_reset_ctr, - b1isa_remove_ctr, - b1_register_appl, - b1_release_appl, - b1_send_message, - - b1isa_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ - - b1isa_add_card, -}; - -#ifdef MODULE -#define b1isa_init init_module -void cleanup_module(void); -#endif - -int b1isa_init(void) -{ - struct capi_driver *driver = &b1isa_driver; - char *p; - - if ((p = strchr(revision, ':'))) { - strncpy(driver->revision, p + 1, sizeof(driver->revision)); - p = strchr(driver->revision, '$'); - *p = 0; - } - - printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); - - di = attach_capi_driver(driver); - - if (!di) { - printk(KERN_ERR "%s: failed to attach capi_driver\n", - driver->name); - return -EIO; - } - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - detach_capi_driver(&b1isa_driver); -} -#endif diff --git a/drivers/isdn/avmb1/b1pci.c b/drivers/isdn/avmb1/b1pci.c deleted file mode 100644 index a74e6402..00000000 --- a/drivers/isdn/avmb1/b1pci.c +++ /dev/null @@ -1,579 +0,0 @@ -/* - * $Id$ - * - * Module for AVM B1 PCI-card. - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.19 2000/01/25 14:33:38 calle - * - Added Support AVM B1 PCI V4.0 (tested with prototype) - * - splitted up t1pci.c into b1dma.c for common function with b1pciv4 - * - support for revision register - * - * Revision 1.18 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.17 1999/10/05 06:50:07 calle - * Forgot SA_SHIRQ as argument to request_irq. - * - * Revision 1.16 1999/08/11 21:01:07 keil - * new PCI codefix - * - * Revision 1.15 1999/08/10 16:02:27 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.14 1999/07/09 15:05:41 keil - * compat.h is now isdn_compat.h - * - * Revision 1.13 1999/07/05 15:09:50 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.12 1999/07/01 15:26:29 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "capicmd.h" -#include "capiutil.h" -#include "capilli.h" -#include "avmcard.h" - -static char *revision = "$Revision$"; - -/* ------------------------------------------------------------- */ - -#ifndef PCI_VENDOR_ID_AVM -#define PCI_VENDOR_ID_AVM 0x1244 -#endif - -#ifndef PCI_DEVICE_ID_AVM_B1 -#define PCI_DEVICE_ID_AVM_B1 0x700 -#endif - -/* ------------------------------------------------------------- */ - -MODULE_AUTHOR("Carsten Paeth "); - -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface *di; - -/* ------------------------------------------------------------- */ - -static void b1pci_interrupt(int interrupt, void *devptr, struct pt_regs *regs) -{ - avmcard *card; - - card = (avmcard *) devptr; - - if (!card) { - printk(KERN_WARNING "b1pci: interrupt: wrong device\n"); - return; - } - if (card->interrupt) { - printk(KERN_ERR "%s: reentering interrupt hander.\n", card->name); - return; - } - - card->interrupt = 1; - - b1_handle_interrupt(card); - - card->interrupt = 0; -} -/* ------------------------------------------------------------- */ - -static void b1pci_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - di->detach_ctr(ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - ctrl->driverdata = 0; - kfree(card->ctrlinfo); - kfree(card); - - MOD_DEC_USE_COUNT; -} - -/* ------------------------------------------------------------- */ - -static char *b1pci_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p) -{ - avmcard *card; - avmctrl_info *cinfo; - int retval; - - MOD_INC_USE_COUNT; - - card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); - - if (!card) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card, 0, sizeof(avmcard)); - cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(cinfo, 0, sizeof(avmctrl_info)); - card->ctrlinfo = cinfo; - cinfo->card = card; - sprintf(card->name, "b1pci-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->cardtype = avm_b1pci; - - if (check_region(card->port, AVMB1_PORTLEN)) { - printk(KERN_WARNING - "%s: ports 0x%03x-0x%03x in use.\n", - driver->name, card->port, card->port + AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - b1_reset(card->port); - if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", - driver->name, card->port, retval); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - b1_reset(card->port); - b1_getrevision(card); - - request_region(p->port, AVMB1_PORTLEN, card->name); - - retval = request_irq(card->irq, b1pci_interrupt, SA_SHIRQ, card->name, card); - if (retval) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", - driver->name, card->irq); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); - if (!cinfo->capi_ctrl) { - printk(KERN_ERR "%s: attach controller failed.\n", - driver->name); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - if (card->revision >= 4) { - printk(KERN_INFO - "%s: AVM B1 PCI V4 at i/o %#x, irq %d, revision %d (no dma)\n", - driver->name, card->port, card->irq, card->revision); - } else { - printk(KERN_INFO - "%s: AVM B1 PCI at i/o %#x, irq %d, revision %d\n", - driver->name, card->port, card->irq, card->revision); - } - - return 0; -} - -/* ------------------------------------------------------------- */ - -static struct capi_driver b1pci_driver = { - "b1pci", - "0.0", - b1_load_firmware, - b1_reset_ctr, - b1pci_remove_ctr, - b1_register_appl, - b1_release_appl, - b1_send_message, - - b1pci_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ - - 0, /* no add_card function */ -}; - -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface *div4; - -/* ------------------------------------------------------------- */ - -static void b1pciv4_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - - b1dma_reset(card); - - div4->detach_ctr(ctrl); - free_irq(card->irq, card); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - release_region(card->port, AVMB1_PORTLEN); - ctrl->driverdata = 0; - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - - MOD_DEC_USE_COUNT; -} - -static char *b1pciv4_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p) -{ - unsigned long base, page_offset; - avmcard *card; - avmctrl_info *cinfo; - int retval; - - card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); - - if (!card) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - return -ENOMEM; - } - memset(card, 0, sizeof(avmcard)); - card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC); - if (!card->dma) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card); - return -ENOMEM; - } - memset(card->dma, 0, sizeof(avmcard_dmainfo)); - cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card->dma); - kfree(card); - return -ENOMEM; - } - memset(cinfo, 0, sizeof(avmctrl_info)); - card->ctrlinfo = cinfo; - cinfo->card = card; - sprintf(card->name, "b1pciv4-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = avm_b1pci; - - if (check_region(card->port, AVMB1_PORTLEN)) { - printk(KERN_WARNING - "%s: ports 0x%03x-0x%03x in use.\n", - driver->name, card->port, card->port + AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - return -EBUSY; - } - - base = card->membase & PAGE_MASK; - page_offset = card->membase - base; - card->mbase = ioremap_nocache(base, page_offset + 64); - if (card->mbase) { - card->mbase += page_offset; - } else { - printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n", - driver->name, card->membase); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - return -EIO; - } - - b1dma_reset(card); - - if ((retval = b1pciv4_detect(card)) != 0) { - printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", - driver->name, card->port, retval); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - return -EIO; - } - b1dma_reset(card); - b1_getrevision(card); - - request_region(p->port, AVMB1_PORTLEN, card->name); - - retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card); - if (retval) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", - driver->name, card->irq); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - return -EBUSY; - } - - cinfo->capi_ctrl = div4->attach_ctr(driver, card->name, cinfo); - if (!cinfo->capi_ctrl) { - printk(KERN_ERR "%s: attach controller failed.\n", driver->name); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - return -EBUSY; - } - card->cardnr = cinfo->capi_ctrl->cnr; - - skb_queue_head_init(&card->dma->send_queue); - - printk(KERN_INFO - "%s: AVM B1 PCI V4 at i/o %#x, irq %d, mem %#lx, revision %d (dma)\n", - driver->name, card->port, card->irq, - card->membase, card->revision); - - MOD_INC_USE_COUNT; - - return 0; -} - -/* ------------------------------------------------------------- */ - - -static struct capi_driver b1pciv4_driver = { - "b1pciv4", - "0.0", - b1dma_load_firmware, - b1dma_reset_ctr, - b1pciv4_remove_ctr, - b1dma_register_appl, - b1dma_release_appl, - b1dma_send_message, - - b1pciv4_procinfo, - b1dmactl_read_proc, - 0, /* use standard driver_read_proc */ - - 0, /* no add_card function */ -}; - -#endif /* CONFIG_ISDN_DRV_AVMB1_B1PCIV4 */ - -#ifdef MODULE -#define b1pci_init init_module -void cleanup_module(void); -#endif - -static int ncards = 0; - -static int add_card(struct pci_dev *dev) -{ - struct capi_driver *driver = &b1pci_driver; - struct capicardparams param; - int retval; - - if (get_pcibase(dev, 2) & PCI_BASE_ADDRESS_IO_MASK) { /* B1 PCI V4 */ -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - driver = &b1pciv4_driver; -#endif - param.membase = get_pcibase(dev, 0) & PCI_BASE_ADDRESS_MEM_MASK; - param.port = get_pcibase(dev, 2) & PCI_BASE_ADDRESS_IO_MASK; - param.irq = dev->irq; - printk(KERN_INFO - "%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n", - driver->name, param.port, param.irq, param.membase); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - retval = b1pciv4_add_card(driver, ¶m); -#else - retval = b1pci_add_card(driver, ¶m); -#endif - if (retval != 0) { - printk(KERN_ERR - "%s: no AVM-B1 V4 at i/o %#x, irq %d, mem %#x detected\n", - driver->name, param.port, param.irq, param.membase); - } - } else { - param.membase = 0; - param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK; - param.irq = dev->irq; - printk(KERN_INFO - "%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n", - driver->name, param.port, param.irq); - retval = b1pci_add_card(driver, ¶m); - if (retval != 0) { - printk(KERN_ERR - "%s: no AVM-B1 at i/o %#x, irq %d detected\n", - driver->name, param.port, param.irq); - } - } - return retval; -} - -int b1pci_init(void) -{ - struct capi_driver *driver = &b1pci_driver; -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - struct capi_driver *driverv4 = &b1pciv4_driver; -#endif - struct pci_dev *dev = NULL; - char *p; - int retval; - - if ((p = strchr(revision, ':'))) { - strncpy(driver->revision, p + 1, sizeof(driver->revision)); - p = strchr(driver->revision, '$'); - *p = 0; - } - - printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); - - di = attach_capi_driver(driver); - - if (!di) { - printk(KERN_ERR "%s: failed to attach capi_driver\n", - driver->name); - return -EIO; - } - -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - printk(KERN_INFO "%s: revision %s\n", driverv4->name, driverv4->revision); - - div4 = attach_capi_driver(driverv4); - - if (!div4) { - detach_capi_driver(driver); - printk(KERN_ERR "%s: failed to attach capi_driver\n", - driverv4->name); - return -EIO; - } -#endif - -#ifdef CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "%s: no PCI bus present\n", driver->name); - detach_capi_driver(driver); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - detach_capi_driver(driverv4); -#endif - return -EIO; - } - - while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, dev))) { - retval = add_card(dev); - if (retval != 0) { -#ifdef MODULE - cleanup_module(); -#endif - return retval; - } - ncards++; - } - if (ncards) { - printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n", - driver->name, ncards); - return 0; - } - printk(KERN_ERR "%s: NO B1-PCI card detected\n", driver->name); - return -ESRCH; -#else - printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name); - return -EIO; -#endif -} - -#ifdef MODULE -void cleanup_module(void) -{ - detach_capi_driver(&b1pci_driver); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 - detach_capi_driver(&b1pciv4_driver); -#endif -} -#endif diff --git a/drivers/isdn/avmb1/b1pcmcia.c b/drivers/isdn/avmb1/b1pcmcia.c deleted file mode 100644 index 147b231b..00000000 --- a/drivers/isdn/avmb1/b1pcmcia.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * $Id$ - * - * Module for AVM B1/M1/M2 PCMCIA-card. - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.8 2000/03/06 18:00:23 calle - * - Middleware extention now working with 2.3.49 (capifs). - * - Fixed typos in debug section of capi.c - * - Bugfix: Makefile corrected for b1pcmcia.c - * - * Revision 1.7 2000/02/02 18:36:03 calle - * - Modules are now locked while init_module is running - * - fixed problem with memory mapping if address is not aligned - * - * Revision 1.6 2000/01/25 14:37:39 calle - * new message after successfull detection including card revision and - * used resources. - * - * Revision 1.5 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.4 1999/08/22 20:26:26 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.3 1999/07/09 15:05:41 keil - * compat.h is now isdn_compat.h - * - * Revision 1.2 1999/07/05 15:09:51 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:30 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "capicmd.h" -#include "capiutil.h" -#include "capilli.h" -#include "avmcard.h" - -static char *revision = "$Revision$"; - -/* ------------------------------------------------------------- */ - -MODULE_AUTHOR("Carsten Paeth "); - -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface *di; - -/* ------------------------------------------------------------- */ - -static void b1pcmcia_interrupt(int interrupt, void *devptr, struct pt_regs *regs) -{ - avmcard *card; - - card = (avmcard *) devptr; - - if (!card) { - printk(KERN_WARNING "b1pcmcia: interrupt: wrong device\n"); - return; - } - if (card->interrupt) { - printk(KERN_ERR "%s: reentering interrupt hander.\n", - card->name); - return; - } - - card->interrupt = 1; - - b1_handle_interrupt(card); - - card->interrupt = 0; -} -/* ------------------------------------------------------------- */ - -static void b1pcmcia_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - b1_reset(port); - b1_reset(port); - - di->detach_ctr(ctrl); - free_irq(card->irq, card); - /* io addrsses managent by CardServices - * release_region(card->port, AVMB1_PORTLEN); - */ - kfree(card); - - MOD_DEC_USE_COUNT; -} - -/* ------------------------------------------------------------- */ - -static int b1pcmcia_add_card(struct capi_driver *driver, - unsigned int port, - unsigned irq, - enum avmcardtype cardtype) -{ - avmctrl_info *cinfo; - avmcard *card; - char *cardname; - int retval; - - MOD_INC_USE_COUNT; - - card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); - - if (!card) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card, 0, sizeof(avmcard)); - cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(cinfo, 0, sizeof(avmctrl_info)); - card->ctrlinfo = cinfo; - cinfo->card = card; - switch (cardtype) { - case avm_m1: sprintf(card->name, "m1-%x", port); break; - case avm_m2: sprintf(card->name, "m2-%x", port); break; - default: sprintf(card->name, "b1pcmcia-%x", port); break; - } - card->port = port; - card->irq = irq; - card->cardtype = cardtype; - - b1_reset(card->port); - if ((retval = b1_detect(card->port, card->cardtype)) != 0) { - printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", - driver->name, card->port, retval); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - b1_reset(card->port); - b1_getrevision(card); - - retval = request_irq(card->irq, b1pcmcia_interrupt, 0, card->name, card); - if (retval) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", - driver->name, card->irq); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); - if (!cinfo->capi_ctrl) { - printk(KERN_ERR "%s: attach controller failed.\n", - driver->name); - free_irq(card->irq, card); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - switch (cardtype) { - case avm_m1: cardname = "M1"; break; - case avm_m2: cardname = "M2"; break; - default : cardname = "B1 PCMCIA"; break; - } - - printk(KERN_INFO - "%s: AVM %s at i/o %#x, irq %d, revision %d\n", - driver->name, cardname, card->port, card->irq, card->revision); - - return cinfo->capi_ctrl->cnr; -} - -/* ------------------------------------------------------------- */ - -static char *b1pcmcia_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d r%d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->revision : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static struct capi_driver b1pcmcia_driver = { - "b1pcmcia", - "0.0", - b1_load_firmware, - b1_reset_ctr, - b1pcmcia_remove_ctr, - b1_register_appl, - b1_release_appl, - b1_send_message, - - b1pcmcia_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ - - 0, -}; - -/* ------------------------------------------------------------- */ - -int b1pcmcia_addcard_b1(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_b1pcmcia); -} - -int b1pcmcia_addcard_m1(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m1); -} - -int b1pcmcia_addcard_m2(unsigned int port, unsigned irq) -{ - return b1pcmcia_add_card(&b1pcmcia_driver, port, irq, avm_m2); -} - -int b1pcmcia_delcard(unsigned int port, unsigned irq) -{ - struct capi_ctr *ctrl; - avmcard *card; - - for (ctrl = b1pcmcia_driver.controller; ctrl; ctrl = ctrl->next) { - card = ((avmctrl_info *)(ctrl->driverdata))->card; - if (card->port == port && card->irq == irq) { - b1pcmcia_remove_ctr(ctrl); - return 0; - } - } - return -ESRCH; -} - -EXPORT_SYMBOL(b1pcmcia_addcard_b1); -EXPORT_SYMBOL(b1pcmcia_addcard_m1); -EXPORT_SYMBOL(b1pcmcia_addcard_m2); -EXPORT_SYMBOL(b1pcmcia_delcard); - -/* ------------------------------------------------------------- */ - -#ifdef MODULE -#define b1pcmcia_init init_module -void cleanup_module(void); -#endif - -int b1pcmcia_init(void) -{ - struct capi_driver *driver = &b1pcmcia_driver; - char *p; - - if ((p = strchr(revision, ':'))) { - strncpy(driver->revision, p + 1, sizeof(driver->revision)); - p = strchr(driver->revision, '$'); - *p = 0; - } - - printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); - - di = attach_capi_driver(driver); - - if (!di) { - printk(KERN_ERR "%s: failed to attach capi_driver\n", - driver->name); - return -EIO; - } - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - detach_capi_driver(&b1pcmcia_driver); -} -#endif diff --git a/drivers/isdn/avmb1/c4.c b/drivers/isdn/avmb1/c4.c deleted file mode 100644 index be2e052e..00000000 --- a/drivers/isdn/avmb1/c4.c +++ /dev/null @@ -1,1344 +0,0 @@ -/* - * $Id$ - * - * Module for AVM C4 card. - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.3 2000/01/25 14:37:39 calle - * new message after successfull detection including card revision and - * used resources. - * - * Revision 1.2 2000/01/21 20:52:58 keil - * pci_find_subsys as local function for 2.2.X kernel - * - * Revision 1.1 2000/01/20 10:51:37 calle - * Added driver for C4. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "capicmd.h" -#include "capiutil.h" -#include "capilli.h" -#include "avmcard.h" - -static char *revision = "$Revision$"; - -#undef CONFIG_C4_DEBUG -#undef CONFIG_C4_POLLDEBUG - -/* ------------------------------------------------------------- */ - -#ifndef PCI_VENDOR_ID_DEC -#define PCI_VENDOR_ID_DEC 0x1011 -#endif - -#ifndef PCI_DEVICE_ID_DEC_21285 -#define PCI_DEVICE_ID_DEC_21285 0x1065 -#endif - -#ifndef PCI_VENDOR_ID_AVM -#define PCI_VENDOR_ID_AVM 0x1244 -#endif - -#ifndef PCI_DEVICE_ID_AVM_C4 -#define PCI_DEVICE_ID_AVM_C4 0x0800 -#endif - -/* ------------------------------------------------------------- */ - -int suppress_pollack = 0; - -MODULE_AUTHOR("Carsten Paeth "); - -MODULE_PARM(suppress_pollack, "0-1i"); - -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface *di; - -/* ------------------------------------------------------------- */ - -static void c4_dispatch_tx(avmcard *card); - -/* ------------------------------------------------------------- */ - -#define DC21285_DRAM_A0MR 0x40000000 -#define DC21285_DRAM_A1MR 0x40004000 -#define DC21285_DRAM_A2MR 0x40008000 -#define DC21285_DRAM_A3MR 0x4000C000 - -#define CAS_OFFSET 0x88 - -#define DC21285_ARMCSR_BASE 0x42000000 - -#define PCI_OUT_INT_STATUS 0x30 -#define PCI_OUT_INT_MASK 0x34 -#define MAILBOX_0 0x50 -#define MAILBOX_1 0x54 -#define MAILBOX_2 0x58 -#define MAILBOX_3 0x5C -#define DOORBELL 0x60 -#define DOORBELL_SETUP 0x64 - -#define CHAN_1_CONTROL 0x90 -#define CHAN_2_CONTROL 0xB0 -#define DRAM_TIMING 0x10C -#define DRAM_ADDR_SIZE_0 0x110 -#define DRAM_ADDR_SIZE_1 0x114 -#define DRAM_ADDR_SIZE_2 0x118 -#define DRAM_ADDR_SIZE_3 0x11C -#define SA_CONTROL 0x13C -#define XBUS_CYCLE 0x148 -#define XBUS_STROBE 0x14C -#define DBELL_PCI_MASK 0x150 -#define DBELL_SA_MASK 0x154 - -#define SDRAM_SIZE 0x1000000 - -/* ------------------------------------------------------------- */ - -#define MBOX_PEEK_POKE MAILBOX_0 - -#define DBELL_ADDR 0x01 -#define DBELL_DATA 0x02 -#define DBELL_RNWR 0x40 -#define DBELL_INIT 0x80 - -/* ------------------------------------------------------------- */ - -#define MBOX_UP_ADDR MAILBOX_0 -#define MBOX_UP_LEN MAILBOX_1 -#define MBOX_DOWN_ADDR MAILBOX_2 -#define MBOX_DOWN_LEN MAILBOX_3 - -#define DBELL_UP_HOST 0x00000100 -#define DBELL_UP_ARM 0x00000200 -#define DBELL_DOWN_HOST 0x00000400 -#define DBELL_DOWN_ARM 0x00000800 -#define DBELL_RESET_HOST 0x40000000 -#define DBELL_RESET_ARM 0x80000000 - -/* ------------------------------------------------------------- */ - -#define DRAM_TIMING_DEF 0x001A01A5 -#define DRAM_AD_SZ_DEF0 0x00000045 -#define DRAM_AD_SZ_NULL 0x00000000 - -#define SA_CTL_ALLRIGHT 0x64AA0271 - -#define INIT_XBUS_CYCLE 0x100016DB -#define INIT_XBUS_STROBE 0xF1F1F1F1 - -/* ------------------------------------------------------------- */ - -#define RESET_TIMEOUT (15*HZ) /* 15 sec */ -#define PEEK_POKE_TIMEOUT (HZ/10) /* 0.1 sec */ - -/* ------------------------------------------------------------- */ - -#define c4outmeml(addr, value) writel(value, addr) -#define c4inmeml(addr) readl(addr) -#define c4outmemw(addr, value) writew(value, addr) -#define c4inmemw(addr) readw(addr) -#define c4outmemb(addr, value) writeb(value, addr) -#define c4inmemb(addr) readb(addr) - -/* ------------------------------------------------------------- */ - -static inline int wait_for_doorbell(avmcard *card, unsigned long t) -{ - unsigned long stop; - - stop = jiffies + t; - while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return -1; - } - return 0; -} - -static int c4_poke(avmcard *card, unsigned long off, unsigned long value) -{ - - if (wait_for_doorbell(card, HZ/10) < 0) - return -1; - - c4outmeml(card->mbase+MBOX_PEEK_POKE, off); - c4outmeml(card->mbase+DOORBELL, DBELL_ADDR); - - if (wait_for_doorbell(card, HZ/10) < 0) - return -1; - - c4outmeml(card->mbase+MBOX_PEEK_POKE, value); - c4outmeml(card->mbase+DOORBELL, DBELL_DATA | DBELL_ADDR); - - return 0; -} - -static int c4_peek(avmcard *card, unsigned long off, unsigned long *valuep) -{ - if (wait_for_doorbell(card, HZ/10) < 0) - return -1; - - c4outmeml(card->mbase+MBOX_PEEK_POKE, off); - c4outmeml(card->mbase+DOORBELL, DBELL_RNWR | DBELL_ADDR); - - if (wait_for_doorbell(card, HZ/10) < 0) - return -1; - - *valuep = c4inmeml(card->mbase+MBOX_PEEK_POKE); - - return 0; -} - -/* ------------------------------------------------------------- */ - -static int c4_load_t4file(avmcard *card, capiloaddatapart * t4file) -{ - __u32 val; - unsigned char *dp; - int left, retval; - __u32 loadoff = 0; - - dp = t4file->data; - left = t4file->len; - while (left >= sizeof(__u32)) { - if (t4file->user) { - retval = copy_from_user(&val, dp, sizeof(val)); - if (retval) - return -EFAULT; - } else { - memcpy(&val, dp, sizeof(val)); - } - if (c4_poke(card, loadoff, val)) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - left -= sizeof(__u32); - dp += sizeof(__u32); - loadoff += sizeof(__u32); - } - if (left) { - val = 0; - if (t4file->user) { - retval = copy_from_user(&val, dp, left); - if (retval) - return -EFAULT; - } else { - memcpy(&val, dp, left); - } - if (c4_poke(card, loadoff, val)) { - printk(KERN_ERR "%s: corrupted firmware file ?\n", - card->name); - return -EIO; - } - } - return 0; -} - -/* ------------------------------------------------------------- */ - -static inline void _put_byte(void **pp, __u8 val) -{ - __u8 *s = *pp; - *s++ = val; - *pp = s; -} - -static inline void _put_word(void **pp, __u32 val) -{ - __u8 *s = *pp; - *s++ = val & 0xff; - *s++ = (val >> 8) & 0xff; - *s++ = (val >> 16) & 0xff; - *s++ = (val >> 24) & 0xff; - *pp = s; -} - -static inline void _put_slice(void **pp, unsigned char *dp, unsigned int len) -{ - unsigned i = len; - _put_word(pp, i); - while (i-- > 0) - _put_byte(pp, *dp++); -} - -static inline __u8 _get_byte(void **pp) -{ - __u8 *s = *pp; - __u8 val; - val = *s++; - *pp = s; - return val; -} - -static inline __u32 _get_word(void **pp) -{ - __u8 *s = *pp; - __u32 val; - val = *s++; - val |= (*s++ << 8); - val |= (*s++ << 16); - val |= (*s++ << 24); - *pp = s; - return val; -} - -static inline __u32 _get_slice(void **pp, unsigned char *dp) -{ - unsigned int len, i; - - len = i = _get_word(pp); - while (i-- > 0) *dp++ = _get_byte(pp); - return len; -} - -/* ------------------------------------------------------------- */ - -static void c4_reset(avmcard *card) -{ - unsigned long stop; - - c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM); - - stop = jiffies + HZ*10; - while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return; - c4outmeml(card->mbase+DOORBELL, DBELL_ADDR); - } - - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0); -} - -/* ------------------------------------------------------------- */ - -static int c4_detect(avmcard *card) -{ - unsigned long stop, dummy; - - c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); - if (c4inmeml(card->mbase+PCI_OUT_INT_MASK) != 0x0c) - return 1; - - c4outmeml(card->mbase+DOORBELL, DBELL_RESET_ARM); - - stop = jiffies + HZ*10; - while (c4inmeml(card->mbase+DOORBELL) != 0xffffffff) { - if (!time_before(jiffies, stop)) - return 2; - c4outmeml(card->mbase+DOORBELL, DBELL_ADDR); - } - - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_1_CONTROL, 0); - c4_poke(card, DC21285_ARMCSR_BASE + CHAN_2_CONTROL, 0); - - c4outmeml(card->mbase+MAILBOX_0, 0x55aa55aa); - if (c4inmeml(card->mbase+MAILBOX_0) != 0x55aa55aa) return 3; - - c4outmeml(card->mbase+MAILBOX_0, 0xaa55aa55); - if (c4inmeml(card->mbase+MAILBOX_0) != 0xaa55aa55) return 4; - - if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_SA_MASK, 0)) return 5; - if (c4_poke(card, DC21285_ARMCSR_BASE+DBELL_PCI_MASK, 0)) return 6; - if (c4_poke(card, DC21285_ARMCSR_BASE+SA_CONTROL, SA_CTL_ALLRIGHT)) - return 7; - if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_CYCLE, INIT_XBUS_CYCLE)) - return 8; - if (c4_poke(card, DC21285_ARMCSR_BASE+XBUS_STROBE, INIT_XBUS_STROBE)) - return 8; - if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9; - - udelay(1000); - - if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10; - if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11; - if (c4_peek(card, DC21285_DRAM_A2MR, &dummy)) return 12; - if (c4_peek(card, DC21285_DRAM_A3MR, &dummy)) return 13; - - if (c4_poke(card, DC21285_DRAM_A0MR+CAS_OFFSET, 0)) return 14; - if (c4_poke(card, DC21285_DRAM_A1MR+CAS_OFFSET, 0)) return 15; - if (c4_poke(card, DC21285_DRAM_A2MR+CAS_OFFSET, 0)) return 16; - if (c4_poke(card, DC21285_DRAM_A3MR+CAS_OFFSET, 0)) return 17; - - udelay(1000); - - if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF)) - return 18; - - if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_0,DRAM_AD_SZ_DEF0)) - return 19; - if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_1,DRAM_AD_SZ_NULL)) - return 20; - if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_2,DRAM_AD_SZ_NULL)) - return 21; - if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_ADDR_SIZE_3,DRAM_AD_SZ_NULL)) - return 22; - - /* Transputer test */ - - if ( c4_poke(card, 0x000000, 0x11111111) - || c4_poke(card, 0x400000, 0x22222222) - || c4_poke(card, 0x800000, 0x33333333) - || c4_poke(card, 0xC00000, 0x44444444)) - return 23; - - if ( c4_peek(card, 0x000000, &dummy) || dummy != 0x11111111 - || c4_peek(card, 0x400000, &dummy) || dummy != 0x22222222 - || c4_peek(card, 0x800000, &dummy) || dummy != 0x33333333 - || c4_peek(card, 0xC00000, &dummy) || dummy != 0x44444444) - return 24; - - if ( c4_poke(card, 0x000000, 0x55555555) - || c4_poke(card, 0x400000, 0x66666666) - || c4_poke(card, 0x800000, 0x77777777) - || c4_poke(card, 0xC00000, 0x88888888)) - return 25; - - if ( c4_peek(card, 0x000000, &dummy) || dummy != 0x55555555 - || c4_peek(card, 0x400000, &dummy) || dummy != 0x66666666 - || c4_peek(card, 0x800000, &dummy) || dummy != 0x77777777 - || c4_peek(card, 0xC00000, &dummy) || dummy != 0x88888888) - return 26; - - return 0; -} - -/* ------------------------------------------------------------- */ - -static void c4_dispatch_tx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - unsigned long flags; - struct sk_buff *skb; - __u8 cmd, subcmd; - __u16 len; - __u32 txlen; - void *p; - - save_flags(flags); - cli(); - - if (card->csr & DBELL_DOWN_ARM) { /* tx busy */ - restore_flags(flags); - return; - } - - skb = skb_dequeue(&dma->send_queue); - if (!skb) { -#ifdef CONFIG_C4_DEBUG - printk(KERN_DEBUG "%s: tx underrun\n", card->name); -#endif - restore_flags(flags); - return; - } - - len = CAPIMSG_LEN(skb->data); - - if (len) { - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - p = dma->sendbuf; - - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - __u16 dlen = CAPIMSG_DATALEN(skb->data); - _put_byte(&p, SEND_DATA_B3_REQ); - _put_slice(&p, skb->data, len); - _put_slice(&p, skb->data + len, dlen); - } else { - _put_byte(&p, SEND_MESSAGE); - _put_slice(&p, skb->data, len); - } - txlen = (__u8 *)p - (__u8 *)dma->sendbuf; -#ifdef CONFIG_C4_DEBUG - printk(KERN_DEBUG "%s: tx put msg len=%d\n", card->name, txlen); -#endif - } else { - txlen = skb->len-2; -#ifdef CONFIG_C4_POLLDEBUG - if (skb->data[2] == SEND_POLLACK) - printk(KERN_INFO "%s: ack to c4\n", card->name); -#endif -#ifdef CONFIG_C4_DEBUG - printk(KERN_DEBUG "%s: tx put 0x%x len=%d\n", - card->name, skb->data[2], txlen); -#endif - memcpy(dma->sendbuf, skb->data+2, skb->len-2); - } - txlen = (txlen + 3) & ~3; - - c4outmeml(card->mbase+MBOX_DOWN_ADDR, virt_to_phys(dma->sendbuf)); - c4outmeml(card->mbase+MBOX_DOWN_LEN, txlen); - - card->csr |= DBELL_DOWN_ARM; - - c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM); - - restore_flags(flags); - dev_kfree_skb(skb); -} - -/* ------------------------------------------------------------- */ - -static void queue_pollack(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(3, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost poll ack\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_POLLACK); - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); -} - -/* ------------------------------------------------------------- */ - -static void c4_handle_rx(avmcard *card) -{ - avmcard_dmainfo *dma = card->dma; - struct capi_ctr *ctrl; - avmctrl_info *cinfo; - struct sk_buff *skb; - void *p = dma->recvbuf; - __u32 ApplId, MsgLen, DataB3Len, NCCI, WindowSize; - __u8 b1cmd = _get_byte(&p); - __u32 cidx; - - -#ifdef CONFIG_C4_DEBUG - printk(KERN_DEBUG "%s: rx 0x%x len=%lu\n", card->name, - b1cmd, (unsigned long)dma->recvlen); -#endif - - switch (b1cmd) { - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - DataB3Len = _get_slice(&p, card->databuf); - cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; - if (cidx > 3) cidx = 0; - ctrl = card->ctrlinfo[cidx].capi_ctrl; - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf+MsgLen, 0, 30-MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr; - if (cidx > 3) cidx = 0; - ctrl = card->ctrlinfo[cidx].capi_ctrl; - - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - WindowSize = _get_word(&p); - cidx = (NCCI&0x7f) - card->cardnr; - if (cidx > 3) cidx = 0; - ctrl = card->ctrlinfo[cidx].capi_ctrl; - - ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); - - break; - - case RECEIVE_FREE_NCCI: - - ApplId = _get_word(&p); - NCCI = _get_word(&p); - - if (NCCI != 0xffffffff) { - cidx = (NCCI&0x7f) - card->cardnr; - if (cidx > 3) cidx = 0; - ctrl = card->ctrlinfo[cidx].capi_ctrl; - ctrl->free_ncci(ctrl, ApplId, NCCI); - } else { - for (cidx=0; cidx < 4; cidx++) { - ctrl = card->ctrlinfo[cidx].capi_ctrl; - ctrl->appl_released(ctrl, ApplId); - } - } - break; - - case RECEIVE_START: -#ifdef CONFIG_C4_POLLDEBUG - printk(KERN_INFO "%s: poll from c4\n", card->name); -#endif - if (!suppress_pollack) - queue_pollack(card); - for (cidx=0; cidx < 4; cidx++) { - ctrl = card->ctrlinfo[cidx].capi_ctrl; - ctrl->resume_output(ctrl); - } - break; - - case RECEIVE_STOP: - for (cidx=0; cidx < 4; cidx++) { - ctrl = card->ctrlinfo[cidx].capi_ctrl; - ctrl->suspend_output(ctrl); - } - break; - - case RECEIVE_INIT: - - cidx = card->nlogcontr++; - cinfo = &card->ctrlinfo[cidx]; - ctrl = cinfo->capi_ctrl; - cinfo->versionlen = _get_slice(&p, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - ctrl->ready(cinfo->capi_ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) _get_word(&p); - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = _get_slice(&p, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - default: - printk(KERN_ERR "%s: c4_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } -} - -/* ------------------------------------------------------------- */ - -static void c4_handle_interrupt(avmcard *card) -{ - __u32 status = c4inmeml(card->mbase+DOORBELL); - - if (status & DBELL_RESET_HOST) { - int i; - c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); - printk(KERN_ERR "%s: unexpected reset\n", card->name); - for (i=0; i < 4; i++) { - avmctrl_info *cinfo = &card->ctrlinfo[i]; - memset(cinfo->version, 0, sizeof(cinfo->version)); - if (cinfo->capi_ctrl) - cinfo->capi_ctrl->reseted(cinfo->capi_ctrl); - } - return; - } - - status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); - if (!status) - return; - c4outmeml(card->mbase+DOORBELL, status); - - if ((status & DBELL_UP_HOST) != 0) { - card->dma->recvlen = c4inmeml(card->mbase+MBOX_UP_LEN); - c4outmeml(card->mbase+MBOX_UP_LEN, 0); - c4_handle_rx(card); - card->dma->recvlen = 0; - c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf)); - c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM); - } - - if ((status & DBELL_DOWN_HOST) != 0) { - card->csr &= ~DBELL_DOWN_ARM; - c4_dispatch_tx(card); - } else if (card->csr & DBELL_DOWN_HOST) { - if (c4inmeml(card->mbase+MBOX_DOWN_LEN) == 0) { - card->csr &= ~DBELL_DOWN_ARM; - c4_dispatch_tx(card); - } - } -} - -static void c4_interrupt(int interrupt, void *devptr, struct pt_regs *regs) -{ - avmcard *card; - - card = (avmcard *) devptr; - - if (!card) { - printk(KERN_WARNING "%s: interrupt: wrong device\n", card->name); - return; - } - if (card->interrupt) { - printk(KERN_ERR "%s: reentering interrupt hander\n", - card->name); - return; - } - - card->interrupt = 1; - - c4_handle_interrupt(card); - - card->interrupt = 0; -} - -/* ------------------------------------------------------------- */ - -static void c4_send_init(avmcard *card) -{ - struct sk_buff *skb; - void *p; - - skb = alloc_skb(15, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_INIT); - _put_word(&p, AVM_NAPPS); - _put_word(&p, AVM_NCCI_PER_CHANNEL*30); - _put_word(&p, card->cardnr - 1); - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); -} - -static int c4_send_config(avmcard *card, capiloaddatapart * config) -{ - struct sk_buff *skb; - __u8 val[sizeof(__u32)]; - void *p; - unsigned char *dp; - int left, retval; - - skb = alloc_skb(12 + ((config->len+3)/4)*5, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, can't send config.\n", - card->name); - return -ENOMEM; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_CONFIG); - _put_word(&p, 1); - _put_byte(&p, SEND_CONFIG); - _put_word(&p, config->len); /* 12 */ - - dp = config->data; - left = config->len; - while (left >= sizeof(__u32)) { - if (config->user) { - retval = copy_from_user(val, dp, sizeof(val)); - if (retval) { - dev_kfree_skb(skb); - return -EFAULT; - } - } else { - memcpy(val, dp, sizeof(val)); - } - _put_byte(&p, SEND_CONFIG); - _put_byte(&p, val[0]); - _put_byte(&p, val[1]); - _put_byte(&p, val[2]); - _put_byte(&p, val[3]); - left -= sizeof(val); - dp += sizeof(val); - } - if (left) { - memset(val, 0, sizeof(val)); - if (config->user) { - retval = copy_from_user(&val, dp, left); - if (retval) { - dev_kfree_skb(skb); - return -EFAULT; - } - } else { - memcpy(&val, dp, left); - } - _put_byte(&p, SEND_CONFIG); - _put_byte(&p, val[0]); - _put_byte(&p, val[1]); - _put_byte(&p, val[2]); - _put_byte(&p, val[3]); - } - - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); - - return 0; -} - -static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned long flags; - int retval; - - if ((retval = c4_load_t4file(card, &data->firmware))) { - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - c4_reset(card); - return retval; - } - - save_flags(flags); - cli(); - - card->csr = 0; - c4outmeml(card->mbase+MBOX_UP_LEN, 0); - c4outmeml(card->mbase+MBOX_DOWN_LEN, 0); - c4outmeml(card->mbase+DOORBELL, DBELL_INIT); - udelay(1000); - c4outmeml(card->mbase+DOORBELL, - DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST); - - c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x08); - - card->dma->recvlen = 0; - c4outmeml(card->mbase+MBOX_UP_ADDR, virt_to_phys(card->dma->recvbuf)); - c4outmeml(card->mbase+MBOX_UP_LEN, sizeof(card->dma->recvbuf)); - c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM); - restore_flags(flags); - - if (data->configuration.len > 0 && data->configuration.data) - c4_send_config(card, &data->configuration); - - c4_send_init(card); - - return 0; -} - - -void c4_reset_ctr(struct capi_ctr *ctrl) -{ - avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; - avmctrl_info *cinfo; - int i; - - c4_reset(card); - - for (i=0; i < 4; i++) { - cinfo = &card->ctrlinfo[i]; - memset(cinfo->version, 0, sizeof(cinfo->version)); - if (cinfo->capi_ctrl) - cinfo->capi_ctrl->reseted(cinfo->capi_ctrl); - } -} - -static void c4_remove_ctr(struct capi_ctr *ctrl) -{ - avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; - avmctrl_info *cinfo; - int i; - - c4_reset(card); - - for (i=0; i <= 4; i++) { - cinfo = &card->ctrlinfo[i]; - if (cinfo->capi_ctrl) - di->detach_ctr(cinfo->capi_ctrl); - } - - free_irq(card->irq, card); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - release_region(card->port, AVMB1_PORTLEN); - ctrl->driverdata = 0; - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - - MOD_DEC_USE_COUNT; -} - -/* ------------------------------------------------------------- */ - - -void c4_register_appl(struct capi_ctr *ctrl, - __u16 appl, - capi_register_params *rp) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - int want = rp->level3cnt; - int nconn; - void *p; - - if (ctrl->cnr == card->cardnr) { - - if (want > 0) nconn = want; - else nconn = ctrl->profile.nbchannel * 4 * -want; - if (nconn == 0) nconn = ctrl->profile.nbchannel * 4; - - skb = alloc_skb(23, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost register appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_REGISTER); - _put_word(&p, appl); - _put_word(&p, 1024 * (nconn+1)); - _put_word(&p, nconn); - _put_word(&p, rp->datablkcnt); - _put_word(&p, rp->datablklen); - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); - } - - ctrl->appl_registered(ctrl, appl); -} - -/* ------------------------------------------------------------- */ - -void c4_release_appl(struct capi_ctr *ctrl, __u16 appl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - struct sk_buff *skb; - void *p; - - if (ctrl->cnr == card->cardnr) { - skb = alloc_skb(7, GFP_ATOMIC); - if (!skb) { - printk(KERN_CRIT "%s: no memory, lost release appl.\n", - card->name); - return; - } - p = skb->data; - _put_byte(&p, 0); - _put_byte(&p, 0); - _put_byte(&p, SEND_RELEASE); - _put_word(&p, appl); - - skb_put(skb, (__u8 *)p - (__u8 *)skb->data); - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); - } -} - -/* ------------------------------------------------------------- */ - - -static void c4_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - skb_queue_tail(&card->dma->send_queue, skb); - c4_dispatch_tx(card); -} - -/* ------------------------------------------------------------- */ - -static char *c4_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0 - ); - return cinfo->infobuf; -} - -static int c4_read_proc(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - __u8 flag; - int len = 0; - char *s; - - len += sprintf(page+len, "%-16s %s\n", "name", card->name); - len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); - len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); - len += sprintf(page+len, "%-16s 0x%lx\n", "membase", card->membase); - switch (card->cardtype) { - case avm_b1isa: s = "B1 ISA"; break; - case avm_b1pci: s = "B1 PCI"; break; - case avm_b1pcmcia: s = "B1 PCMCIA"; break; - case avm_m1: s = "M1"; break; - case avm_m2: s = "M2"; break; - case avm_t1isa: s = "T1 ISA (HEMA)"; break; - case avm_t1pci: s = "T1 PCI"; break; - case avm_c4: s = "C4"; break; - default: s = "???"; break; - } - len += sprintf(page+len, "%-16s %s\n", "type", s); - if ((s = cinfo->version[VER_DRIVER]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); - if ((s = cinfo->version[VER_CARDTYPE]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); - if ((s = cinfo->version[VER_SERIAL]) != 0) - len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); - - if (card->cardtype != avm_m1) { - flag = ((__u8 *)(ctrl->profile.manu))[3]; - if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s%s%s%s\n", - "protocol", - (flag & 0x01) ? " DSS1" : "", - (flag & 0x02) ? " CT1" : "", - (flag & 0x04) ? " VN3" : "", - (flag & 0x08) ? " NI1" : "", - (flag & 0x10) ? " AUSTEL" : "", - (flag & 0x20) ? " ESS" : "", - (flag & 0x40) ? " 1TR6" : "" - ); - } - if (card->cardtype != avm_m1) { - flag = ((__u8 *)(ctrl->profile.manu))[5]; - if (flag) - len += sprintf(page+len, "%-16s%s%s%s%s\n", - "linetype", - (flag & 0x01) ? " point to point" : "", - (flag & 0x02) ? " point to multipoint" : "", - (flag & 0x08) ? " leased line without D-channel" : "", - (flag & 0x04) ? " leased line with D-channel" : "" - ); - } - len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); - - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); -} - -/* ------------------------------------------------------------- */ - -static int c4_add_card(struct capi_driver *driver, struct capicardparams *p) -{ - unsigned long base, page_offset; - avmctrl_info *cinfo; - avmcard *card; - int retval; - int i; - - MOD_INC_USE_COUNT; - - card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); - - if (!card) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card, 0, sizeof(avmcard)); - card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC); - if (!card->dma) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card->dma, 0, sizeof(avmcard_dmainfo)); - cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info)*4, GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(cinfo, 0, sizeof(avmctrl_info)*4); - card->ctrlinfo = cinfo; - for (i=0; i < 4; i++) { - cinfo = &card->ctrlinfo[i]; - cinfo->card = card; - } - sprintf(card->name, "c4-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = avm_c4; - - if (check_region(card->port, AVMB1_PORTLEN)) { - printk(KERN_WARNING - "%s: ports 0x%03x-0x%03x in use.\n", - driver->name, card->port, card->port + AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - base = card->membase & PAGE_MASK; - page_offset = card->membase - base; - card->mbase = ioremap_nocache(base, page_offset + 128); - if (card->mbase) { - card->mbase += page_offset; - } else { - printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n", - driver->name, card->membase); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - - if ((retval = c4_detect(card)) != 0) { - printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", - driver->name, card->port, retval); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - c4_reset(card); - - request_region(p->port, AVMB1_PORTLEN, card->name); - - retval = request_irq(card->irq, c4_interrupt, SA_SHIRQ, card->name, card); - if (retval) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", - driver->name, card->irq); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - for (i=0; i < 4; i++) { - cinfo = &card->ctrlinfo[i]; - cinfo->card = card; - cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); - if (!cinfo->capi_ctrl) { - printk(KERN_ERR "%s: attach controller failed (%d).\n", - driver->name, i); - for (i--; i >= 0; i--) { - cinfo = &card->ctrlinfo[i]; - di->detach_ctr(cinfo->capi_ctrl); - } - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->dma); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - if (i == 0) - card->cardnr = cinfo->capi_ctrl->cnr; - } - - skb_queue_head_init(&card->dma->send_queue); - - printk(KERN_INFO - "%s: AVM C4 at i/o %#x, irq %d, mem %#lx\n", - driver->name, card->port, card->irq, card->membase); - - return 0; -} - -/* ------------------------------------------------------------- */ - -static struct capi_driver c4_driver = { - "c4", - "0.0", - c4_load_firmware, - c4_reset_ctr, - c4_remove_ctr, - c4_register_appl, - c4_release_appl, - c4_send_message, - - c4_procinfo, - c4_read_proc, - 0, /* use standard driver_read_proc */ - - 0, /* no add_card function */ -}; - -#ifdef MODULE -#define c4_init init_module -void cleanup_module(void); -#endif - -#ifndef COMPAT_HAS_pci_find_subsys -#ifndef PCI_ANY_ID -#define PCI_ANY_ID (~0) -#endif - -static 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 - -static int ncards = 0; - -int c4_init(void) -{ - struct capi_driver *driver = &c4_driver; - struct pci_dev *dev = NULL; - char *p; - int retval; - - if ((p = strchr(revision, ':'))) { - strncpy(driver->revision, p + 1, sizeof(driver->revision)); - p = strchr(driver->revision, '$'); - *p = 0; - } - - printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); - - di = attach_capi_driver(driver); - - if (!di) { - printk(KERN_ERR "%s: failed to attach capi_driver\n", - driver->name); - return -EIO; - } - -#ifdef CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "%s: no PCI bus present\n", driver->name); - detach_capi_driver(driver); - return -EIO; - } - - while ((dev = pci_find_subsys( - PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, - PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, dev))) { - struct capicardparams param; - - param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK; - param.irq = dev->irq; - param.membase = get_pcibase(dev, 0) & PCI_BASE_ADDRESS_MEM_MASK; - - printk(KERN_INFO - "%s: PCI BIOS reports AVM-C4 at i/o %#x, irq %d, mem %#x\n", - driver->name, param.port, param.irq, param.membase); - retval = c4_add_card(driver, ¶m); - if (retval != 0) { - printk(KERN_ERR - "%s: no AVM-C4 at i/o %#x, irq %d detected, mem %#x\n", - driver->name, param.port, param.irq, param.membase); -#ifdef MODULE - cleanup_module(); -#endif - return retval; - } - ncards++; - } - if (ncards) { - printk(KERN_INFO "%s: %d C4 card(s) detected\n", - driver->name, ncards); - return 0; - } - printk(KERN_ERR "%s: NO C4 card detected\n", driver->name); - return -ESRCH; -#else - printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name); - return -EIO; -#endif -} - -#ifdef MODULE -void cleanup_module(void) -{ - detach_capi_driver(&c4_driver); -} -#endif diff --git a/drivers/isdn/avmb1/capi.c b/drivers/isdn/avmb1/capi.c deleted file mode 100644 index dda26c24..00000000 --- a/drivers/isdn/avmb1/capi.c +++ /dev/null @@ -1,2291 +0,0 @@ -/* - * $Id$ - * - * CAPI 2.0 Interface for Linux - * - * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.28 2000/03/08 17:06:33 calle - * - changes for devfs and 2.3.49 - * - capifs now configurable (no need with devfs) - * - New Middleware ioctl CAPI_NCCI_GETUNIT - * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) - * - * Revision 1.27 2000/03/06 18:00:23 calle - * - Middleware extention now working with 2.3.49 (capifs). - * - Fixed typos in debug section of capi.c - * - Bugfix: Makefile corrected for b1pcmcia.c - * - * Revision 1.26 2000/03/03 16:48:38 calle - * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) - * It is now possible to create a connection with a CAPI2.0 applikation - * and than to handle the data connection from /dev/capi/ (capifs) and also - * using async or sync PPP on this connection. - * The two major device number 190 and 191 are not confirmed yet, - * but I want to save the code in cvs, before I go on. - * - * Revision 1.25 2000/03/03 16:37:11 kai - * incorporated some cosmetic changes from the official kernel tree back - * into CVS - * - * Revision 1.24 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.23 2000/02/26 01:00:53 keil - * changes from 2.3.47 - * - * Revision 1.22 1999/11/13 21:27:16 keil - * remove KERNELVERSION - * - * Revision 1.21 1999/09/10 17:24:18 calle - * Changes for proposed standard for CAPI2.0: - * - AK148 "Linux Exention" - * - * Revision 1.20 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.19 1999/07/09 15:05:42 keil - * compat.h is now isdn_compat.h - * - * Revision 1.18 1999/07/06 07:42:01 calle - * - changes in /proc interface - * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. - * - * Revision 1.17 1999/07/01 15:26:30 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * Revision 1.16 1999/07/01 08:22:57 keil - * compatibility macros now in - * - * Revision 1.15 1999/06/21 15:24:11 calle - * extend information in /proc. - * - * Revision 1.14 1999/06/10 16:51:03 calle - * Bugfix: open/release of control device was not handled correct. - * - * Revision 1.13 1998/08/28 04:32:25 calle - * Added patch send by Michael.Mueller4@post.rwth-aachen.de, to get AVM B1 - * driver running with 2.1.118. - * - * Revision 1.12 1998/05/26 22:39:34 he - * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) - * concap typo - * cleared dev.tbusy in isdn_net BCONN status callback - * - * Revision 1.11 1998/03/09 17:46:37 he - * merged in 2.1.89 changes - * - * Revision 1.10 1998/02/13 07:09:13 calle - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.9 1998/01/31 11:14:44 calle - * merged changes to 2.0 tree, prepare 2.1.82 to work. - * - * Revision 1.8 1997/11/04 06:12:08 calle - * capi.c: new read/write in file_ops since 2.1.60 - * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware. - * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON) - * compat.h: added #define LinuxVersionCode - * - * Revision 1.7 1997/10/11 10:29:34 calle - * llseek() parameters changed in 2.1.56. - * - * Revision 1.6 1997/10/01 09:21:15 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.5 1997/08/21 23:11:55 fritz - * Added changes for kernels >= 2.1.45 - * - * Revision 1.4 1997/05/27 15:17:50 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.3 1997/05/18 09:24:14 calle - * added verbose disconnect reason reporting to avmb1. - * some fixes in capi20 interface. - * changed info messages for B1-PCI - * - * Revision 1.2 1997/03/05 21:17:59 fritz - * Added capi_poll for compiling under 2.1.27 - * - * Revision 1.1 1997/03/04 21:50:29 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -#include -#ifdef CONFIG_PPP -#include -#include -#include -#ifdef PPPIOCATTACH -#include -#endif /* PPPIOCATTACH */ -#endif /* CONFIG_PPP */ -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -#include -#include -#include -#include -#include -#ifdef HAVE_DEVFS_FS -#include -#endif /* HAVE_DEVFS_FS */ -#include -#include "capiutil.h" -#include "capicmd.h" -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -#include "capifs.h" -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -#ifdef COMPAT_HAS_kmem_cache -#include -#endif - -static char *revision = "$Revision$"; - -MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)"); - -#undef _DEBUG_REFCOUNT /* alloc/free and open/close debug */ -#undef _DEBUG_TTYFUNCS /* call to tty_driver */ -#undef _DEBUG_DATAFLOW /* data flow */ - -/* -------- driver information -------------------------------------- */ - -int capi_major = 68; /* allocated */ -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -int capi_rawmajor = 190; -int capi_ttymajor = 191; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - -MODULE_PARM(capi_major, "i"); -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -MODULE_PARM(capi_rawmajor, "i"); -MODULE_PARM(capi_ttymajor, "i"); -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - -/* -------- defines ------------------------------------------------- */ - -#define CAPINC_MAX_RECVQUEUE 10 -#define CAPINC_MAX_SENDQUEUE 10 -#define CAPI_MAX_BLKSIZE 2048 - -/* -------- data structures ----------------------------------------- */ - -struct capidev; -struct capincci; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -struct capiminor; - -struct capiminor { - struct capiminor *next; - struct capincci *nccip; - unsigned int minor; - - __u16 applid; - __u32 ncci; - __u16 datahandle; - __u16 msgid; - - struct file *file; - struct tty_struct *tty; - int ttyinstop; - int ttyoutstop; - struct sk_buff *ttyskb; - atomic_t ttyopencount; - - struct sk_buff_head inqueue; - int inbytes; - struct sk_buff_head outqueue; - int outbytes; - - /* for raw device */ - struct sk_buff_head recvqueue; -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t recvwait; - wait_queue_head_t sendwait; -#else - struct wait_queue *recvwait; - struct wait_queue *sendwait; -#endif - - /* transmit path */ - struct datahandle_queue { - struct datahandle_queue *next; - __u16 datahandle; - } *ackqueue; - int nack; - -#ifdef PPPIOCATTACH - /* 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; - struct capidev *cdev; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *minorp; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -}; - -struct capidev { - struct capidev *next; - struct file *file; - __u16 applid; - __u16 errcode; - unsigned int minor; - unsigned userflags; - - struct sk_buff_head recvqueue; -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t recvwait; -#else - struct wait_queue *recvwait; -#endif - - /* Statistic */ - unsigned long nrecvctlpkt; - unsigned long nrecvdatapkt; - unsigned long nsentctlpkt; - unsigned long nsentdatapkt; - - struct capincci *nccis; -}; - -/* -------- global variables ---------------------------------------- */ - -static struct capi_interface *capifuncs = 0; -static struct capidev *capidev_openlist = 0; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -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 --------------------------------------------- */ - -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; - } - n->next = 0; - n->datahandle = datahandle; - for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) ; - *pp = n; - mp->nack++; - return 0; -} - -int capiminor_del_ack(struct capiminor *mp, __u16 datahandle) -{ - struct datahandle_queue **pp, *p; - - for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { - 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; - } - } - return -1; -} - -void capiminor_del_all_ack(struct capiminor *mp) -{ - struct datahandle_queue **pp, *p; - - for (pp = &mp->ackqueue; *pp; pp = &(*pp)->next) { - p = *pp; - *pp = (*pp)->next; -#ifdef COMPAT_HAS_kmem_cache - kmem_cache_free(capidh_cachep, p); -#else - kfree(p); -#endif - mp->nack--; - } -} - - -/* -------- struct capiminor ---------------------------------------- */ - -struct capiminor *capiminor_alloc(__u16 applid, __u32 ncci) -{ - struct capiminor *mp, **pp; - unsigned int minor = 0; - -#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) { - printk(KERN_ERR "capi: can't alloc capiminor\n"); - return 0; - } - MOD_INC_USE_COUNT; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capiminor_alloc %d\n", GET_USE_COUNT(THIS_MODULE)); -#endif - memset(mp, 0, sizeof(struct capiminor)); - mp->applid = applid; - mp->ncci = ncci; - mp->msgid = 0; - atomic_set(&mp->ttyopencount,0); - - skb_queue_head_init(&mp->inqueue); - skb_queue_head_init(&mp->outqueue); - - skb_queue_head_init(&mp->recvqueue); -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&mp->recvwait); - init_waitqueue_head(&mp->sendwait); -#endif - - for (pp = &minors; *pp; pp = &(*pp)->next) { - if ((*pp)->minor < minor) - continue; - if ((*pp)->minor > minor) - break; - minor++; - } - mp->minor = minor; - mp->next = *pp; - *pp = mp; - return mp; -} - -void capiminor_free(struct capiminor *mp) -{ - struct capiminor **pp; - struct sk_buff *skb; - - pp = &minors; - while (*pp) { - if (*pp == mp) { - *pp = (*pp)->next; - if (mp->ttyskb) kfree_skb(mp->ttyskb); - mp->ttyskb = 0; - while ((skb = skb_dequeue(&mp->recvqueue)) != 0) - kfree_skb(skb); - while ((skb = skb_dequeue(&mp->inqueue)) != 0) - kfree_skb(skb); - while ((skb = skb_dequeue(&mp->outqueue)) != 0) - kfree_skb(skb); - 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)); -#endif - return; - } else { - pp = &(*pp)->next; - } - } -} - -struct capiminor *capiminor_find(unsigned int minor) -{ - struct capiminor *p; - for (p = minors; p && p->minor != minor; p = p->next) - ; - return p; -} -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - -/* -------- struct capincci ----------------------------------------- */ - -static struct capincci *capincci_alloc(struct capidev *cdev, __u32 ncci) -{ - struct capincci *np, **pp; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp = 0; - 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)); - np->ncci = ncci; - np->cdev = cdev; - for (pp=&cdev->nccis; *pp; pp = &(*pp)->next) - ; - *pp = np; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - mp = 0; - if (cdev->userflags & CAPIFLAG_HIGHJACKING) - mp = np->minorp = capiminor_alloc(cdev->applid, ncci); - if (mp) { - mp->nccip = np; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "set mp->nccip\n"); -#endif -#ifdef CONFIG_ISDN_CAPIFS - kdev = MKDEV(capi_rawmajor, mp->minor); - capifs_new_ncci('r', mp->minor, kdev); - kdev = MKDEV(capi_ttymajor, mp->minor); - capifs_new_ncci(0, mp->minor, kdev); -#endif - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - return np; -} - -static void capincci_free(struct capidev *cdev, __u32 ncci) -{ - struct capincci *np, **pp; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - - pp=&cdev->nccis; - while (*pp) { - np = *pp; - if (ncci == 0xffffffff || np->ncci == ncci) { - *pp = (*pp)->next; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if ((mp = np->minorp) != 0) { -#ifdef CONFIG_ISDN_CAPIFS - capifs_free_ncci('r', mp->minor); - capifs_free_ncci(0, mp->minor); -#endif - if (mp->tty) { - mp->nccip = 0; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "reset mp->nccip\n"); -#endif - tty_hangup(mp->tty); - } else if (mp->file) { - mp->nccip = 0; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "reset mp->nccip\n"); -#endif - wake_up_interruptible(&mp->recvwait); - wake_up_interruptible(&mp->sendwait); - } else { - capiminor_free(mp); - } - } -#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; - } - } -} - -struct capincci *capincci_find(struct capidev *cdev, __u32 ncci) -{ - struct capincci *p; - - for (p=cdev->nccis; p ; p = p->next) { - if (p->ncci == ncci) - break; - } - return p; -} - -/* -------- struct capidev ------------------------------------------ */ - -static struct capidev *capidev_alloc(struct file *file) -{ - 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)); - cdev->file = file; - cdev->minor = MINOR_PART(file); - - skb_queue_head_init(&cdev->recvqueue); -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&cdev->recvwait); -#endif - pp=&capidev_openlist; - while (*pp) pp = &(*pp)->next; - *pp = cdev; - return cdev; -} - -static void capidev_free(struct capidev *cdev) -{ - struct capidev **pp; - struct sk_buff *skb; - - if (cdev->applid) - (*capifuncs->capi_release) (cdev->applid); - cdev->applid = 0; - - while ((skb = skb_dequeue(&cdev->recvqueue)) != 0) { - kfree_skb(skb); - } - - pp=&capidev_openlist; - while (*pp && *pp != cdev) pp = &(*pp)->next; - 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) -{ - struct capidev *p; - for (p=capidev_openlist; p; p = p->next) { - if (p->applid == applid) - break; - } - return p; -} - -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -/* -------- handle data queue --------------------------------------- */ - -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); - 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); - capimsg_setu8 (s, 4, CAPI_DATA_B3); - capimsg_setu8 (s, 5, CAPI_RESP); - capimsg_setu16(s, 6, mp->msgid++); - capimsg_setu32(s, 8, mp->ncci); - capimsg_setu16(s, 12, datahandle); - } - return nskb; -} - -int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb) -{ - struct sk_buff *nskb; - unsigned int datalen; - __u16 errcode, datahandle; - - datalen = skb->len - CAPIMSG_LEN(skb->data); - if (mp->tty) { - if (mp->tty->ldisc.receive_buf == 0) { - printk(KERN_ERR "capi: ldisc has no receive_buf function\n"); - return -1; - } - if (mp->ttyinstop) { -#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: recv tty throttled\n"); -#endif - return -1; - } - if (mp->tty->ldisc.receive_room && - mp->tty->ldisc.receive_room(mp->tty) < datalen) { -#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: no room in tty\n"); -#endif - return -1; - } - 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 => ldisc\n", - datahandle, skb->len); -#endif - mp->tty->ldisc.receive_buf(mp->tty, skb->data, 0, skb->len); - return 0; - -#ifdef PPPIOCATTACH - } 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) - printk(KERN_DEBUG "capi: no room in raw queue\n"); -#endif - return -1; - } - 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 => raw\n", - datahandle, skb->len); -#endif - skb_queue_tail(&mp->recvqueue, skb); - wake_up_interruptible(&mp->recvwait); - return 0; - } -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: currently no receiver\n"); -#endif - return -1; -} - -void handle_minor_recv(struct capiminor *mp) -{ - struct sk_buff *skb; - while ((skb = skb_dequeue(&mp->inqueue)) != 0) { - unsigned int len = skb->len; - mp->inbytes -= len; - if (handle_recv_skb(mp, skb) < 0) { - skb_queue_head(&mp->inqueue, skb); - mp->inbytes += len; - return; - } - } -} - -int handle_minor_send(struct capiminor *mp) -{ - struct sk_buff *skb; - __u16 len; - int count = 0; - __u16 errcode; - __u16 datahandle; - - if (mp->tty && mp->ttyoutstop) { -#if defined(_DEBUG_DATAFLOW) || defined(_DEBUG_TTYFUNCS) - printk(KERN_DEBUG "capi: send: tty stopped\n"); -#endif - return 0; - } - - while ((skb = skb_dequeue(&mp->outqueue)) != 0) { - datahandle = mp->datahandle; - 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); - capimsg_setu16(skb->data, 2, mp->applid); - capimsg_setu8 (skb->data, 4, CAPI_DATA_B3); - 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_setu16(skb->data, 16, len); /* Data length */ - capimsg_setu16(skb->data, 18, datahandle); - capimsg_setu16(skb->data, 20, 0); /* Flags */ - - if (capincci_add_ack(mp, datahandle) < 0) { - skb_pull(skb, CAPI_DATA_B3_REQ_LEN); - skb_queue_head(&mp->outqueue, skb); - return count; - } - errcode = (*capifuncs->capi_put_message) (mp->applid, skb); - if (errcode == CAPI_NOERROR) { - mp->datahandle++; - count++; - mp->outbytes -= len; -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi: DATA_B3_REQ %u len=%u\n", - datahandle, len); -#endif - continue; - } - capiminor_del_ack(mp, datahandle); - - if (errcode == CAPI_SENDQUEUEFULL) { - skb_pull(skb, CAPI_DATA_B3_REQ_LEN); - skb_queue_head(&mp->outqueue, skb); - break; - } - - /* ups, drop packet */ - printk(KERN_ERR "capi: put_message = %x\n", errcode); - mp->outbytes -= len; - kfree_skb(skb); - } - if (count) - wake_up_interruptible(&mp->sendwait); - return count; -} - -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -/* -------- function called by lower level -------------------------- */ - -static void capi_signal(__u16 applid, void *param) -{ - struct capidev *cdev = (struct capidev *)param; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp; - __u16 datahandle; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - struct capincci *np; - struct sk_buff *skb = 0; - __u32 ncci; - - (void) (*capifuncs->capi_get_message) (applid, &skb); - if (!skb) { - printk(KERN_ERR "BUG: capi_signal: no skb\n"); - return; - } - - if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) { - skb_queue_tail(&cdev->recvqueue, skb); - wake_up_interruptible(&cdev->recvwait); - return; - } - ncci = CAPIMSG_CONTROL(skb->data); - for (np = cdev->nccis; np && np->ncci != ncci; np = np->next) - ; - if (!np) { - printk(KERN_ERR "BUG: capi_signal: ncci not found\n"); - skb_queue_tail(&cdev->recvqueue, skb); - wake_up_interruptible(&cdev->recvwait); - return; - } -#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE - skb_queue_tail(&cdev->recvqueue, skb); - wake_up_interruptible(&cdev->recvwait); -#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - mp = np->minorp; - if (!mp) { - skb_queue_tail(&cdev->recvqueue, skb); - wake_up_interruptible(&cdev->recvwait); - return; - } - - - if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { - - datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi_signal: DATA_B3_IND %u len=%d\n", - datahandle, skb->len-CAPIMSG_LEN(skb->data)); -#endif - skb_queue_tail(&mp->inqueue, skb); - mp->inbytes += skb->len; - handle_minor_recv(mp); - - } else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) { - - datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4); -#ifdef _DEBUG_DATAFLOW - printk(KERN_DEBUG "capi_signal: DATA_B3_CONF %u 0x%x\n", - datahandle, - CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2)); -#endif - kfree_skb(skb); - (void)capiminor_del_ack(mp, datahandle); -#ifdef PPPIOCATTACH - 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); - } else { - wake_up_interruptible(&mp->sendwait); - } - (void)handle_minor_send(mp); - - } else { - /* ups, let capi application handle it :-) */ - skb_queue_tail(&cdev->recvqueue, skb); - wake_up_interruptible(&cdev->recvwait); - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -} - -/* -------- file_operations for capidev ----------------------------- */ - -static long long capi_llseek(struct file *file, - long long offset, int origin) -{ - return -ESPIPE; -} - -static ssize_t capi_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - struct capidev *cdev = (struct capidev *)file->private_data; - struct sk_buff *skb; - int retval; - size_t copied; - - if (ppos != &file->f_pos) - return -ESPIPE; - - if (!cdev->applid) - return -ENODEV; - - if ((skb = skb_dequeue(&cdev->recvqueue)) == 0) { - - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - for (;;) { - interruptible_sleep_on(&cdev->recvwait); - if ((skb = skb_dequeue(&cdev->recvqueue)) != 0) - break; - if (signal_pending(current)) - break; - } - if (skb == 0) - return -ERESTARTNOHAND; - } - if (skb->len > count) { - skb_queue_head(&cdev->recvqueue, skb); - return -EMSGSIZE; - } - retval = copy_to_user(buf, skb->data, skb->len); - if (retval) { - skb_queue_head(&cdev->recvqueue, skb); - return retval; - } - copied = skb->len; - - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND) { - cdev->nrecvdatapkt++; - } else { - cdev->nrecvctlpkt++; - } - - kfree_skb(skb); - - return copied; -} - -static ssize_t capi_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct capidev *cdev = (struct capidev *)file->private_data; - struct sk_buff *skb; - int retval; - __u16 mlen; - - if (ppos != &file->f_pos) - return -ESPIPE; - - if (!cdev->applid) - return -ENODEV; - - skb = alloc_skb(count, GFP_USER); - - if ((retval = copy_from_user(skb_put(skb, count), buf, count))) { - kfree_skb(skb); - return retval; - } - mlen = CAPIMSG_LEN(skb->data); - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - if (mlen + CAPIMSG_DATALEN(skb->data) != count) { - kfree_skb(skb); - return -EINVAL; - } - } else { - if (mlen != count) { - kfree_skb(skb); - return -EINVAL; - } - } - CAPIMSG_SETAPPID(skb->data, cdev->applid); - - cdev->errcode = (*capifuncs->capi_put_message) (cdev->applid, skb); - - if (cdev->errcode) { - kfree_skb(skb); - return -EIO; - } - if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { - cdev->nsentdatapkt++; - } else { - cdev->nsentctlpkt++; - } - return count; -} - -static unsigned int -capi_poll(struct file *file, poll_table * wait) -{ - struct capidev *cdev = (struct capidev *)file->private_data; - unsigned int mask = 0; - - if (!cdev->applid) - return POLLERR; - - poll_wait(file, &(cdev->recvwait), wait); - mask = POLLOUT | POLLWRNORM; - if (!skb_queue_empty(&cdev->recvqueue)) - mask |= POLLIN | POLLRDNORM; - return mask; -} - -static int capi_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct capidev *cdev = (struct capidev *)file->private_data; - capi_ioctl_struct data; - int retval = -EINVAL; - - switch (cmd) { - case CAPI_REGISTER: - { - retval = copy_from_user((void *) &data.rparams, - (void *) arg, sizeof(struct capi_register_params)); - if (retval) - return -EFAULT; - if (cdev->applid) - return -EEXIST; - cdev->errcode = (*capifuncs->capi_register) (&data.rparams, - &cdev->applid); - if (cdev->errcode) { - cdev->applid = 0; - return -EIO; - } - (void) (*capifuncs->capi_set_signal) (cdev->applid, capi_signal, cdev); - } - return (int)cdev->applid; - - case CAPI_GET_VERSION: - { - retval = copy_from_user((void *) &data.contr, - (void *) arg, - sizeof(data.contr)); - if (retval) - return -EFAULT; - cdev->errcode = (*capifuncs->capi_get_version) (data.contr, &data.version); - if (cdev->errcode) - return -EIO; - retval = copy_to_user((void *) arg, - (void *) &data.version, - sizeof(data.version)); - if (retval) - return -EFAULT; - } - return 0; - - case CAPI_GET_SERIAL: - { - retval = copy_from_user((void *) &data.contr, - (void *) arg, - sizeof(data.contr)); - if (retval) - return -EFAULT; - cdev->errcode = (*capifuncs->capi_get_serial) (data.contr, data.serial); - if (cdev->errcode) - return -EIO; - retval = copy_to_user((void *) arg, - (void *) data.serial, - sizeof(data.serial)); - if (retval) - return -EFAULT; - } - return 0; - case CAPI_GET_PROFILE: - { - retval = copy_from_user((void *) &data.contr, - (void *) arg, - sizeof(data.contr)); - if (retval) - return -EFAULT; - - if (data.contr == 0) { - cdev->errcode = (*capifuncs->capi_get_profile) (data.contr, &data.profile); - if (cdev->errcode) - return -EIO; - - retval = copy_to_user((void *) arg, - (void *) &data.profile.ncontroller, - sizeof(data.profile.ncontroller)); - - } else { - cdev->errcode = (*capifuncs->capi_get_profile) (data.contr, &data.profile); - if (cdev->errcode) - return -EIO; - - retval = copy_to_user((void *) arg, - (void *) &data.profile, - sizeof(data.profile)); - } - if (retval) - return -EFAULT; - } - return 0; - - case CAPI_GET_MANUFACTURER: - { - retval = copy_from_user((void *) &data.contr, - (void *) arg, - sizeof(data.contr)); - if (retval) - return -EFAULT; - cdev->errcode = (*capifuncs->capi_get_manufacturer) (data.contr, data.manufacturer); - if (cdev->errcode) - return -EIO; - - retval = copy_to_user((void *) arg, (void *) data.manufacturer, - sizeof(data.manufacturer)); - if (retval) - return -EFAULT; - - } - return 0; - case CAPI_GET_ERRCODE: - data.errcode = cdev->errcode; - cdev->errcode = CAPI_NOERROR; - if (arg) { - retval = copy_to_user((void *) arg, - (void *) &data.errcode, - sizeof(data.errcode)); - if (retval) - return -EFAULT; - } - return data.errcode; - - case CAPI_INSTALLED: - if ((*capifuncs->capi_isinstalled)() == CAPI_NOERROR) - return 0; - return -ENXIO; - - case CAPI_MANUFACTURER_CMD: - { - struct capi_manufacturer_cmd mcmd; - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - retval = copy_from_user((void *) &mcmd, (void *) arg, - sizeof(mcmd)); - if (retval) - return -EFAULT; - return (*capifuncs->capi_manufacturer) (mcmd.cmd, mcmd.data); - } - return 0; - - case CAPI_SET_FLAGS: - case CAPI_CLR_FLAGS: - { - unsigned userflags; - retval = copy_from_user((void *) &userflags, - (void *) arg, - sizeof(userflags)); - if (retval) - return -EFAULT; - if (cmd == CAPI_SET_FLAGS) - cdev->userflags |= userflags; - else - cdev->userflags &= ~userflags; - } - return 0; - - case CAPI_GET_FLAGS: - { - retval = copy_to_user((void *) arg, - (void *) &cdev->userflags, - sizeof(cdev->userflags)); - if (retval) - return -EFAULT; - } - return 0; - - case CAPI_NCCI_OPENCOUNT: - { - struct capincci *nccip; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - struct capiminor *mp; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - unsigned ncci; - int count = 0; - retval = copy_from_user((void *) &ncci, - (void *) arg, - sizeof(ncci)); - if (retval) - return -EFAULT; - nccip = capincci_find(cdev, (__u32) ncci); - if (!nccip) - return 0; -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if ((mp = nccip->minorp) != 0) { - count += atomic_read(&mp->ttyopencount); - if (mp->file) - count++; - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - return count; - } - return 0; - -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - case CAPI_NCCI_GETUNIT: - { - struct capincci *nccip; - struct capiminor *mp; - unsigned ncci; - retval = copy_from_user((void *) &ncci, - (void *) arg, - sizeof(ncci)); - if (retval) - return -EFAULT; - nccip = capincci_find(cdev, (__u32) ncci); - if (!nccip || (mp = nccip->minorp) == 0) - return -ESRCH; - return mp->minor; - } - return 0; -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - } - return -EINVAL; -} - -static int capi_open(struct inode *inode, struct file *file) -{ - if (file->private_data) - return -EEXIST; - - if ((file->private_data = capidev_alloc(file)) == 0) - return -ENOMEM; - - MOD_INC_USE_COUNT; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capi_open %d\n", GET_USE_COUNT(THIS_MODULE)); -#endif - return 0; -} - -static int capi_release(struct inode *inode, struct file *file) -{ - struct capidev *cdev = (struct capidev *)file->private_data; - - capincci_free(cdev, 0xffffffff); - capidev_free(cdev); - - MOD_DEC_USE_COUNT; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE)); -#endif - return 0; -} - -static struct file_operations capi_fops = -{ - llseek: capi_llseek, - read: capi_read, - write: capi_write, - poll: capi_poll, - ioctl: capi_ioctl, - open: capi_open, - release: capi_release, -}; - -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE -/* -------- file_operations for capincci ---------------------------- */ - -int capinc_raw_open(struct inode *inode, struct file *file) -{ - struct capiminor *mp; - - if (file->private_data) - return -EEXIST; - if ((mp = capiminor_find(MINOR_PART(file))) == 0) - return -ENXIO; - if (mp->nccip == 0) - return -ENXIO; - if (mp->file) - return -EBUSY; - -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capi_raw_open %d\n", GET_USE_COUNT(THIS_MODULE)); -#endif - - mp->datahandle = 0; - mp->file = file; - file->private_data = (void *)mp; - handle_minor_recv(mp); - return 0; -} - -long long capinc_raw_llseek(struct file *file, - long long offset, int origin) -{ - return -ESPIPE; -} - -ssize_t capinc_raw_read(struct file *file, char *buf, - size_t count, loff_t *ppos) -{ - struct capiminor *mp = (struct capiminor *)file->private_data; - struct sk_buff *skb; - int retval; - size_t copied = 0; - - if (ppos != &file->f_pos) - return -ESPIPE; - - if (!mp || !mp->nccip) - return -EINVAL; - - if ((skb = skb_dequeue(&mp->recvqueue)) == 0) { - - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - for (;;) { - interruptible_sleep_on(&mp->recvwait); - if (mp->nccip == 0) - return 0; - if ((skb = skb_dequeue(&mp->recvqueue)) != 0) - break; - if (signal_pending(current)) - break; - } - if (skb == 0) - return -ERESTARTNOHAND; - } - do { - if (count < skb->len) { - retval = copy_to_user(buf, skb->data, count); - if (retval) { - skb_queue_head(&mp->recvqueue, skb); - return retval; - } - skb_pull(skb, count); - skb_queue_head(&mp->recvqueue, skb); - copied += count; - return copied; - } else { - retval = copy_to_user(buf, skb->data, skb->len); - if (retval) { - skb_queue_head(&mp->recvqueue, skb); - return copied; - } - copied += skb->len; - count -= skb->len; - buf += skb->len; - kfree_skb(skb); - } - } while ((skb = skb_dequeue(&mp->recvqueue)) != 0); - - return copied; -} - -ssize_t capinc_raw_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) -{ - struct capiminor *mp = (struct capiminor *)file->private_data; - struct sk_buff *skb; - int retval; - - if (ppos != &file->f_pos) - return -ESPIPE; - - if (!mp || !mp->nccip) - return -EINVAL; - - skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_USER); - - skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); - if ((retval = copy_from_user(skb_put(skb, count), buf, count))) { - kfree_skb(skb); - return retval; - } - - while (skb_queue_len(&mp->outqueue) > CAPINC_MAX_SENDQUEUE) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - interruptible_sleep_on(&mp->sendwait); - if (mp->nccip == 0) { - kfree_skb(skb); - return -EIO; - } - if (signal_pending(current)) - return -ERESTARTNOHAND; - } - skb_queue_tail(&mp->outqueue, skb); - mp->outbytes += skb->len; - (void)handle_minor_send(mp); - return count; -} - -unsigned int -capinc_raw_poll(struct file *file, poll_table * wait) -{ - struct capiminor *mp = (struct capiminor *)file->private_data; - unsigned int mask = 0; - - if (!mp || !mp->nccip) - return POLLERR|POLLHUP; - - poll_wait(file, &(mp->recvwait), wait); - if (!skb_queue_empty(&mp->recvqueue)) - mask |= POLLIN | POLLRDNORM; - poll_wait(file, &(mp->sendwait), wait); - if (skb_queue_len(&mp->outqueue) > CAPINC_MAX_SENDQUEUE) - mask = POLLOUT | POLLWRNORM; - return mask; -} - -int capinc_raw_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct capiminor *mp = (struct capiminor *)file->private_data; - if (!mp || !mp->nccip) - return -EINVAL; - - switch (cmd) { -#ifdef PPPIOCATTACH - 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; -} - -int -capinc_raw_release(struct inode *inode, struct file *file) -{ - struct capiminor *mp = (struct capiminor *)file->private_data; - - if (mp) { - mp->file = 0; - if (mp->nccip == 0) - capiminor_free(mp); - } - -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_raw_release %d\n", GET_USE_COUNT(THIS_MODULE)); -#endif - return 0; -} - -struct file_operations capinc_raw_fops = -{ - capinc_raw_llseek, - capinc_raw_read, - capinc_raw_write, - NULL, /* capi_readdir */ - capinc_raw_poll, - capinc_raw_ioctl, - NULL, /* capi_mmap */ - capinc_raw_open, -#ifdef FILEOP_HAS_FLUSH - NULL, /* capi_flush */ -#endif - capinc_raw_release, - NULL, /* capi_fsync */ - NULL, /* capi_fasync */ -}; - -/* -------- tty_operations for capincci ----------------------------- */ - -int capinc_tty_open(struct tty_struct * tty, struct file * file) -{ - struct capiminor *mp; - - if ((mp = capiminor_find(MINOR_PART(file))) == 0) - return -ENXIO; - if (mp->nccip == 0) - return -ENXIO; - if (mp->file) - return -EBUSY; - - skb_queue_head_init(&mp->recvqueue); -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&mp->recvwait); - init_waitqueue_head(&mp->sendwait); -#endif - tty->driver_data = (void *)mp; -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capi_tty_open %d\n", GET_USE_COUNT(THIS_MODULE)); -#endif - if (atomic_read(&mp->ttyopencount) == 0) - mp->tty = tty; - atomic_inc(&mp->ttyopencount); -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount)); -#endif - handle_minor_recv(mp); - return 0; -} - -void capinc_tty_close(struct tty_struct * tty, struct file * file) -{ - struct capiminor *mp; - - mp = (struct capiminor *)tty->driver_data; - if (mp) { - if (atomic_dec_and_test(&mp->ttyopencount)) { -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close lastclose\n"); -#endif - tty->driver_data = (void *)0; - mp->tty = 0; - } -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount)); -#endif - if (mp->nccip == 0) - capiminor_free(mp); - } - -#ifdef _DEBUG_REFCOUNT - printk(KERN_DEBUG "capinc_tty_close\n"); -#endif -} - -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; - int retval; - -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write(from_user=%d,count=%d)\n", - from_user, count); -#endif - - if (!mp || !mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n"); -#endif - return 0; - } - - skb = mp->ttyskb; - if (skb) { - mp->ttyskb = 0; - skb_queue_tail(&mp->outqueue, skb); - mp->outbytes += skb->len; - } - - skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC); - if (!skb) { - printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n"); - return -ENOMEM; - } - - skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); - if (from_user) { - if ((retval = copy_from_user(skb_put(skb, count), buf, count))) { - kfree_skb(skb); -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write: copy_from_user=%d\n", retval); -#endif - return retval; - } - } else { - memcpy(skb_put(skb, count), buf, count); - } - - skb_queue_tail(&mp->outqueue, skb); - mp->outbytes += skb->len; - (void)handle_minor_send(mp); - (void)handle_minor_recv(mp); - return count; -} - -void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; - struct sk_buff *skb; - -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_put_char(%u)\n", ch); -#endif - - if (!mp || !mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n"); -#endif - return; - } - - skb = mp->ttyskb; - if (skb) { - if (skb_tailroom(skb) > 0) { - *(skb_put(skb, 1)) = ch; - return; - } - mp->ttyskb = 0; - skb_queue_tail(&mp->outqueue, skb); - mp->outbytes += skb->len; - (void)handle_minor_send(mp); - } - skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC); - if (skb) { - skb_reserve(skb, CAPI_DATA_B3_REQ_LEN); - *(skb_put(skb, 1)) = ch; - mp->ttyskb = skb; - } else { - printk(KERN_ERR "capinc_put_char: char %u lost\n", ch); - } -} - -void capinc_tty_flush_chars(struct tty_struct *tty) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; - struct sk_buff *skb; - -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_flush_chars\n"); -#endif - - if (!mp || !mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n"); -#endif - return; - } - - skb = mp->ttyskb; - if (skb) { - mp->ttyskb = 0; - skb_queue_tail(&mp->outqueue, skb); - mp->outbytes += skb->len; - (void)handle_minor_send(mp); - } - (void)handle_minor_recv(mp); -} - -int capinc_tty_write_room(struct tty_struct *tty) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; - int room; - if (!mp || !mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write_room: mp or mp->ncci NULL\n"); -#endif - return 0; - } - room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue); - room *= CAPI_MAX_BLKSIZE; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_write_room = %d\n", room); -#endif - return room; -} - -int capinc_tty_chars_in_buffer(struct tty_struct *tty) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; - if (!mp || !mp->nccip) { -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_chars_in_buffer: mp or mp->ncci NULL\n"); -#endif - return 0; - } -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n", - mp->outbytes, mp->nack, - skb_queue_len(&mp->outqueue), - skb_queue_len(&mp->inqueue)); -#endif - return mp->outbytes; -} - -int capinc_tty_ioctl(struct tty_struct *tty, struct file * file, - unsigned int cmd, unsigned long arg) -{ - return -ENOIOCTLCMD; -} - -void capinc_tty_set_termios(struct tty_struct *tty, struct termios * old) -{ -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_set_termios\n"); -#endif -} - -void capinc_tty_throttle(struct tty_struct * tty) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_throttle\n"); -#endif - if (mp) - mp->ttyinstop = 1; -} - -void capinc_tty_unthrottle(struct tty_struct * tty) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_unthrottle\n"); -#endif - if (mp) { - mp->ttyinstop = 0; - handle_minor_recv(mp); - } -} - -void capinc_tty_stop(struct tty_struct *tty) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_stop\n"); -#endif - if (mp) { - mp->ttyoutstop = 1; - } -} - -void capinc_tty_start(struct tty_struct *tty) -{ - struct capiminor *mp = (struct capiminor *)tty->driver_data; -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_start\n"); -#endif - if (mp) { - mp->ttyoutstop = 0; - (void)handle_minor_send(mp); - } -} - -void capinc_tty_hangup(struct tty_struct *tty) -{ -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_hangup\n"); -#endif -} - -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 -} - -void capinc_tty_flush_buffer(struct tty_struct *tty) -{ -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_flush_buffer\n"); -#endif -} - -void capinc_tty_set_ldisc(struct tty_struct *tty) -{ -#ifdef _DEBUG_TTYFUNCS - printk(KERN_DEBUG "capinc_tty_set_ldisc\n"); -#endif -} - -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 -} - -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; -} - -#define CAPINC_NR_PORTS 256 -static struct tty_driver capinc_tty_driver; -static int capinc_tty_refcount; -static struct tty_struct *capinc_tty_table[CAPINC_NR_PORTS]; -static struct termios *capinc_tty_termios[CAPINC_NR_PORTS]; -static struct termios *capinc_tty_termios_locked[CAPINC_NR_PORTS]; - -int capinc_tty_init(void) -{ - struct tty_driver *drv = &capinc_tty_driver; - - /* Initialize the tty_driver structure */ - - memset(drv, 0, sizeof(struct tty_driver)); - drv->magic = TTY_DRIVER_MAGIC; -#if (LINUX_VERSION_CODE > 0x20100) - drv->driver_name = "capi_nc"; -#endif - drv->name = "capi/%d"; - drv->major = capi_ttymajor; - drv->minor_start = 0; - drv->num = CAPINC_NR_PORTS; - drv->type = TTY_DRIVER_TYPE_SERIAL; - drv->subtype = SERIAL_TYPE_NORMAL; - drv->init_termios = tty_std_termios; - drv->init_termios.c_iflag = ICRNL; - drv->init_termios.c_oflag = OPOST | ONLCR; - drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - drv->init_termios.c_lflag = 0; - drv->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_RESET_TERMIOS; - drv->refcount = &capinc_tty_refcount; - drv->table = capinc_tty_table; - drv->termios = capinc_tty_termios; - drv->termios_locked = capinc_tty_termios_locked; - - drv->open = capinc_tty_open; - drv->close = capinc_tty_close; - drv->write = capinc_tty_write; - drv->put_char = capinc_tty_put_char; - drv->flush_chars = capinc_tty_flush_chars; - drv->write_room = capinc_tty_write_room; - drv->chars_in_buffer = capinc_tty_chars_in_buffer; - drv->ioctl = capinc_tty_ioctl; - drv->set_termios = capinc_tty_set_termios; - drv->throttle = capinc_tty_throttle; - drv->unthrottle = capinc_tty_unthrottle; - drv->stop = capinc_tty_stop; - drv->start = capinc_tty_start; - drv->hangup = capinc_tty_hangup; -#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */ - drv->break_ctl = capinc_tty_break_ctl; -#endif - drv->flush_buffer = capinc_tty_flush_buffer; - drv->set_ldisc = capinc_tty_set_ldisc; -#if (LINUX_VERSION_CODE >= 131343) - drv->send_xchar = capinc_tty_send_xchar; - drv->read_proc = capinc_tty_read_proc; -#endif - if (tty_register_driver(drv)) { - printk(KERN_ERR "Couldn't register capi_nc driver\n"); - return -1; - } - return 0; -} - -void capinc_tty_exit(void) -{ - struct tty_driver *drv = &capinc_tty_driver; - int retval; - if ((retval = tty_unregister_driver(drv))) - printk(KERN_ERR "capi: failed to unregister capi_nc driver (%d)\n", retval); -} - -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - -/* -------- /proc functions ----------------------------------------- */ - -/* - * /proc/capi/capi20: - * minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt - */ -static int proc_capidev_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capidev *cdev; - int len = 0; - off_t begin = 0; - - for (cdev=capidev_openlist; cdev; cdev = cdev->next) { - len += sprintf(page+len, "%d %d %lu %lu %lu %lu\n", - cdev->minor, - cdev->applid, - cdev->nrecvctlpkt, - cdev->nrecvdatapkt, - cdev->nsentctlpkt, - cdev->nsentdatapkt); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } -endloop: - if (cdev == 0) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * /proc/capi/capi20ncci: - * applid ncci - */ -static int proc_capincci_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capidev *cdev; - struct capincci *np; - int len = 0; - off_t begin = 0; - - for (cdev=capidev_openlist; cdev; cdev = cdev->next) { - for (np=cdev->nccis; np; np = np->next) { - len += sprintf(page+len, "%d 0x%x%s\n", - cdev->applid, - np->ncci, -#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE - ""); -#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - np->minorp && np->minorp->file ? " open" : ""); -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } - } -endloop: - if (cdev == 0) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -static struct procfsentries { - char *name; - mode_t mode; - int (*read_proc)(char *page, char **start, off_t off, - int count, int *eof, void *data); - struct proc_dir_entry *procent; -} procfsentries[] = { - /* { "capi", S_IFDIR, 0 }, */ - { "capi/capi20", 0 , proc_capidev_read_proc }, - { "capi/capi20ncci", 0 , proc_capincci_read_proc }, -}; - -static void proc_init(void) -{ - int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); - int i; - - for (i=0; i < nelem; i++) { - struct procfsentries *p = procfsentries + i; - p->procent = create_proc_entry(p->name, p->mode, 0); - if (p->procent) p->procent->read_proc = p->read_proc; - } -} - -static void proc_exit(void) -{ - int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); - int i; - - for (i=nelem-1; i >= 0; i--) { - struct procfsentries *p = procfsentries + i; - if (p->procent) { - remove_proc_entry(p->name, 0); - p->procent = 0; - } - } -} - -/* -------- init function and module interface ---------------------- */ - -#ifdef COMPAT_HAS_kmem_cache - -static void alloc_exit(void) -{ - if (capidev_cachep) { - (void)kmem_cache_destroy(capidev_cachep); - capidev_cachep = 0; - } - if (capincci_cachep) { - (void)kmem_cache_destroy(capincci_cachep); - capincci_cachep = 0; - } -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if (capidh_cachep) { - (void)kmem_cache_destroy(capidh_cachep); - capidh_cachep = 0; - } - if (capiminor_cachep) { - (void)kmem_cache_destroy(capiminor_cachep); - capiminor_cachep = 0; - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -} - -static int alloc_init(void) -{ - capidev_cachep = kmem_cache_create("capi20_dev", - sizeof(struct capidev), - 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!capidev_cachep) { - alloc_exit(); - return -ENOMEM; - } - - capincci_cachep = kmem_cache_create("capi20_ncci", - sizeof(struct capincci), - 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!capincci_cachep) { - alloc_exit(); - return -ENOMEM; - } -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - capidh_cachep = kmem_cache_create("capi20_dh", - sizeof(struct datahandle_queue), - 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!capidh_cachep) { - alloc_exit(); - return -ENOMEM; - } - capiminor_cachep = kmem_cache_create("capi20_minor", - sizeof(struct capiminor), - 0, - SLAB_HWCACHE_ALIGN, - NULL, NULL); - if (!capiminor_cachep) { - alloc_exit(); - return -ENOMEM; - } -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ - return 0; -} -#endif - -static void lower_callback(unsigned int cmd, __u32 contr, void *data) -{ - struct capi_ncciinfo *np; - struct capidev *cdev; - - switch (cmd) { - case KCI_CONTRUP: - printk(KERN_INFO "capi: controller %hu up\n", contr); - break; - case KCI_CONTRDOWN: - printk(KERN_INFO "capi: controller %hu down\n", contr); - break; - case KCI_NCCIUP: - np = (struct capi_ncciinfo *)data; - if ((cdev = capidev_find(np->applid)) == 0) - return; - (void)capincci_alloc(cdev, np->ncci); - break; - case KCI_NCCIDOWN: - np = (struct capi_ncciinfo *)data; - if ((cdev = capidev_find(np->applid)) == 0) - return; - (void)capincci_free(cdev, np->ncci); - break; - } -} - -#ifdef MODULE -#define capi_init init_module -#endif - -static struct capi_interface_user cuser = { - "capi20", - lower_callback, -}; - -static char rev[10]; - -int capi_init(void) -{ - char *p; - - MOD_INC_USE_COUNT; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 2); - p = strchr(rev, '$'); - *(p-1) = 0; - } else - strcpy(rev, "???"); - - if (devfs_register_chrdev(capi_major, "capi20", &capi_fops)) { - printk(KERN_ERR "capi20: unable to get major %d\n", capi_major); - MOD_DEC_USE_COUNT; - return -EIO; - } - -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if (devfs_register_chrdev(capi_rawmajor, "capi/r%d", &capinc_raw_fops)) { - devfs_unregister_chrdev(capi_major, "capi20"); - printk(KERN_ERR "capi20: unable to get major %d\n", capi_rawmajor); - 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, 0, 0, - &capinc_raw_fops, NULL); -#endif -#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ -#ifdef HAVE_DEVFS_FS - devfs_register (NULL, "isdn/capi20", 0, DEVFS_FL_DEFAULT, - capi_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, 0, 0, - &capi_fops, NULL); -#endif - printk(KERN_NOTICE "capi20: started up with major %d\n", capi_major); - - if ((capifuncs = attach_capi_interface(&cuser)) == 0) { - - MOD_DEC_USE_COUNT; - devfs_unregister_chrdev(capi_major, "capi20"); -#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", 0, - capi_major, 0, - DEVFS_SPECIAL_CHR, 0)); -#endif - return -EIO; - } - -#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE - if (capinc_tty_init() < 0) { - (void) detach_capi_interface(&cuser); - devfs_unregister_chrdev(capi_major, "capi20"); - devfs_unregister_chrdev(capi_rawmajor, "capi/r%d"); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } -#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++) { - char devname[32]; - sprintf(devname, "capi/r%u", j); - devfs_unregister(devfs_find_handle(NULL, devname, 0, 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", 0, - capi_major, 0, - DEVFS_SPECIAL_CHR, 0)); -#endif - MOD_DEC_USE_COUNT; - return -ENOMEM; - } -#endif /* COMPAT_HAS_kmem_cache */ - - (void)proc_init(); - - printk(KERN_NOTICE "capi20: Rev%s: started up with major %d\n", - rev, capi_major); - - MOD_DEC_USE_COUNT; - return 0; -} - -#ifdef MODULE -void cleanup_module(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", 0, 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++) { - devfs_handle_t handle; - char devname[32]; - sprintf(devname, "capi/r%u", j); - devfs_unregister(devfs_find_handle(NULL, devname, 0, capi_rawmajor, j, DEVFS_SPECIAL_CHR, 0)); - } -#endif -#endif - (void) detach_capi_interface(&cuser); - printk(KERN_NOTICE "capi: Rev%s: unloaded\n", rev); -} - -#endif diff --git a/drivers/isdn/avmb1/capicmd.h b/drivers/isdn/avmb1/capicmd.h deleted file mode 100644 index c7a1a18a..00000000 --- a/drivers/isdn/avmb1/capicmd.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * $Id$ - * - * CAPI 2.0 Interface for Linux - * - * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.2 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.1 1997/03/04 21:50:30 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - * - */ -#ifndef __CAPICMD_H__ -#define __CAPICMD_H__ - -#define CAPI_MSG_BASELEN 8 -#define CAPI_DATA_B3_REQ_LEN (CAPI_MSG_BASELEN+4+4+2+2+2) -#define CAPI_DATA_B3_RESP_LEN (CAPI_MSG_BASELEN+4+2) - -/*----- CAPI commands -----*/ -#define CAPI_ALERT 0x01 -#define CAPI_CONNECT 0x02 -#define CAPI_CONNECT_ACTIVE 0x03 -#define CAPI_CONNECT_B3_ACTIVE 0x83 -#define CAPI_CONNECT_B3 0x82 -#define CAPI_CONNECT_B3_T90_ACTIVE 0x88 -#define CAPI_DATA_B3 0x86 -#define CAPI_DISCONNECT_B3 0x84 -#define CAPI_DISCONNECT 0x04 -#define CAPI_FACILITY 0x80 -#define CAPI_INFO 0x08 -#define CAPI_LISTEN 0x05 -#define CAPI_MANUFACTURER 0xff -#define CAPI_RESET_B3 0x87 -#define CAPI_SELECT_B_PROTOCOL 0x41 - -/*----- CAPI subcommands -----*/ - -#define CAPI_REQ 0x80 -#define CAPI_CONF 0x81 -#define CAPI_IND 0x82 -#define CAPI_RESP 0x83 - -/*----- CAPI combined commands -----*/ - -#define CAPICMD(cmd,subcmd) (((cmd)<<8)|(subcmd)) - -#define CAPI_DISCONNECT_REQ CAPICMD(CAPI_DISCONNECT,CAPI_REQ) -#define CAPI_DISCONNECT_CONF CAPICMD(CAPI_DISCONNECT,CAPI_CONF) -#define CAPI_DISCONNECT_IND CAPICMD(CAPI_DISCONNECT,CAPI_IND) -#define CAPI_DISCONNECT_RESP CAPICMD(CAPI_DISCONNECT,CAPI_RESP) - -#define CAPI_ALERT_REQ CAPICMD(CAPI_ALERT,CAPI_REQ) -#define CAPI_ALERT_CONF CAPICMD(CAPI_ALERT,CAPI_CONF) - -#define CAPI_CONNECT_REQ CAPICMD(CAPI_CONNECT,CAPI_REQ) -#define CAPI_CONNECT_CONF CAPICMD(CAPI_CONNECT,CAPI_CONF) -#define CAPI_CONNECT_IND CAPICMD(CAPI_CONNECT,CAPI_IND) -#define CAPI_CONNECT_RESP CAPICMD(CAPI_CONNECT,CAPI_RESP) - -#define CAPI_CONNECT_ACTIVE_REQ CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_REQ) -#define CAPI_CONNECT_ACTIVE_CONF CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_CONF) -#define CAPI_CONNECT_ACTIVE_IND CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_IND) -#define CAPI_CONNECT_ACTIVE_RESP CAPICMD(CAPI_CONNECT_ACTIVE,CAPI_RESP) - -#define CAPI_SELECT_B_PROTOCOL_REQ CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_REQ) -#define CAPI_SELECT_B_PROTOCOL_CONF CAPICMD(CAPI_SELECT_B_PROTOCOL,CAPI_CONF) - -#define CAPI_CONNECT_B3_ACTIVE_REQ CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_REQ) -#define CAPI_CONNECT_B3_ACTIVE_CONF CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_CONF) -#define CAPI_CONNECT_B3_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_IND) -#define CAPI_CONNECT_B3_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_ACTIVE,CAPI_RESP) - -#define CAPI_CONNECT_B3_REQ CAPICMD(CAPI_CONNECT_B3,CAPI_REQ) -#define CAPI_CONNECT_B3_CONF CAPICMD(CAPI_CONNECT_B3,CAPI_CONF) -#define CAPI_CONNECT_B3_IND CAPICMD(CAPI_CONNECT_B3,CAPI_IND) -#define CAPI_CONNECT_B3_RESP CAPICMD(CAPI_CONNECT_B3,CAPI_RESP) - - -#define CAPI_CONNECT_B3_T90_ACTIVE_IND CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_IND) -#define CAPI_CONNECT_B3_T90_ACTIVE_RESP CAPICMD(CAPI_CONNECT_B3_T90_ACTIVE,CAPI_RESP) - -#define CAPI_DATA_B3_REQ CAPICMD(CAPI_DATA_B3,CAPI_REQ) -#define CAPI_DATA_B3_CONF CAPICMD(CAPI_DATA_B3,CAPI_CONF) -#define CAPI_DATA_B3_IND CAPICMD(CAPI_DATA_B3,CAPI_IND) -#define CAPI_DATA_B3_RESP CAPICMD(CAPI_DATA_B3,CAPI_RESP) - -#define CAPI_DISCONNECT_B3_REQ CAPICMD(CAPI_DISCONNECT_B3,CAPI_REQ) -#define CAPI_DISCONNECT_B3_CONF CAPICMD(CAPI_DISCONNECT_B3,CAPI_CONF) -#define CAPI_DISCONNECT_B3_IND CAPICMD(CAPI_DISCONNECT_B3,CAPI_IND) -#define CAPI_DISCONNECT_B3_RESP CAPICMD(CAPI_DISCONNECT_B3,CAPI_RESP) - -#define CAPI_RESET_B3_REQ CAPICMD(CAPI_RESET_B3,CAPI_REQ) -#define CAPI_RESET_B3_CONF CAPICMD(CAPI_RESET_B3,CAPI_CONF) -#define CAPI_RESET_B3_IND CAPICMD(CAPI_RESET_B3,CAPI_IND) -#define CAPI_RESET_B3_RESP CAPICMD(CAPI_RESET_B3,CAPI_RESP) - -#define CAPI_LISTEN_REQ CAPICMD(CAPI_LISTEN,CAPI_REQ) -#define CAPI_LISTEN_CONF CAPICMD(CAPI_LISTEN,CAPI_CONF) - -#define CAPI_MANUFACTURER_REQ CAPICMD(CAPI_MANUFACTURER,CAPI_REQ) -#define CAPI_MANUFACTURER_CONF CAPICMD(CAPI_MANUFACTURER,CAPI_CONF) -#define CAPI_MANUFACTURER_IND CAPICMD(CAPI_MANUFACTURER,CAPI_IND) -#define CAPI_MANUFACTURER_RESP CAPICMD(CAPI_MANUFACTURER,CAPI_RESP) - -#define CAPI_FACILITY_REQ CAPICMD(CAPI_FACILITY,CAPI_REQ) -#define CAPI_FACILITY_CONF CAPICMD(CAPI_FACILITY,CAPI_CONF) -#define CAPI_FACILITY_IND CAPICMD(CAPI_FACILITY,CAPI_IND) -#define CAPI_FACILITY_RESP CAPICMD(CAPI_FACILITY,CAPI_RESP) - -#define CAPI_INFO_REQ CAPICMD(CAPI_INFO,CAPI_REQ) -#define CAPI_INFO_CONF CAPICMD(CAPI_INFO,CAPI_CONF) -#define CAPI_INFO_IND CAPICMD(CAPI_INFO,CAPI_IND) -#define CAPI_INFO_RESP CAPICMD(CAPI_INFO,CAPI_RESP) - -#endif /* __CAPICMD_H__ */ diff --git a/drivers/isdn/avmb1/capidev.h b/drivers/isdn/avmb1/capidev.h deleted file mode 100644 index 04f8f451..00000000 --- a/drivers/isdn/avmb1/capidev.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * $Id$ - * - * CAPI 2.0 Interface for Linux - * - * (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.5 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.4 1999/07/01 15:26:32 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * Revision 1.3 1999/07/01 08:22:58 keil - * compatibility macros now in - * - * Revision 1.2 1999/06/21 15:24:13 calle - * extend information in /proc. - * - * Revision 1.1 1997/03/04 21:50:30 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - */ - -struct capidev { - struct capidev *next; - struct file *file; - __u16 applid; - __u16 errcode; - unsigned int minor; - - struct sk_buff_head recv_queue; -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t recv_wait; -#else - struct wait_queue *recv_wait; -#endif - - /* Statistic */ - unsigned long nrecvctlpkt; - unsigned long nrecvdatapkt; - unsigned long nsentctlpkt; - unsigned long nsentdatapkt; -}; diff --git a/drivers/isdn/avmb1/capidrv.c b/drivers/isdn/avmb1/capidrv.c deleted file mode 100644 index 1b735493..00000000 --- a/drivers/isdn/avmb1/capidrv.c +++ /dev/null @@ -1,2585 +0,0 @@ -/* - * $Id$ - * - * ISDN4Linux Driver, using capi20 interface (kernelcapi) - * - * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.29.2.1 2000/03/03 17:14:12 kai - * Merged changes from the main tree - * - * Revision 1.30 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.29 1999/12/06 17:13:06 calle - * Added controller watchdog. - * - * Revision 1.28 1999/11/05 16:22:37 calle - * Bugfix: Missing break in switch on ISDN_CMD_HANGUP. - * - * Revision 1.27 1999/09/16 15:13:04 calle - * forgot to change paramter type of contr for lower_callback ... - * - * Revision 1.26 1999/08/06 07:41:16 calle - * Added the "vbox patch". if (si1 == 1) si2 = 0; - * - * Revision 1.25 1999/08/04 10:10:11 calle - * Bugfix: corrected /proc functions, added structure for new AVM cards. - * - * Revision 1.24 1999/07/20 06:48:02 calle - * Bugfix: firmware version check for D2 trace was too restrictiv. - * - * Revision 1.23 1999/07/09 15:05:44 keil - * compat.h is now isdn_compat.h - * - * Revision 1.22 1999/07/06 07:24:14 calle - * Bugfix: call to kfree_skb in capidrv_signal was too early, - * thanks to Lars Heete . - * - * Revision 1.21 1999/07/01 15:26:34 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * Revision 1.20 1999/07/01 08:22:59 keil - * compatibility macros now in - * - * Revision 1.19 1999/06/29 16:16:54 calle - * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again. - * Also right unlocking (ISDN_CMD_UNLOCK) is done now. - * isdnlog should check returncode of read(2) calls. - * - * Revision 1.18 1999/06/21 15:24:15 calle - * extend information in /proc. - * - * Revision 1.17 1999/06/10 16:53:55 calle - * Removing of module b1pci will now remove card from lower level. - * - * Revision 1.16 1999/05/31 11:50:33 calle - * Bugfix: In if_sendbuf, skb_push'ed DATA_B3 header was not skb_pull'ed - * on failure, result in data block with DATA_B3 header transmitted - * - * Revision 1.15 1999/05/25 21:26:16 calle - * Include CAPI-Channelallocation (leased lines) from the 2.0 tree. - * - * Revision 1.14 1999/05/22 07:55:06 calle - * Added *V110* to AVM B1 driver. - * - * Revision 1.13 1998/06/26 15:12:55 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.12 1998/03/29 16:06:03 calle - * changes from 2.0 tree merged. - * - * Revision 1.3.2.10 1998/03/20 14:38:24 calle - * capidrv: prepared state machines for suspend/resume/hold - * capidrv: fix bug in state machine if B1/T1 is out of nccis - * b1capi: changed some errno returns. - * b1capi: detect if you try to add same T1 to different io address. - * b1capi: change number of nccis depending on number of channels. - * b1lli: cosmetics - * - * Revision 1.3.2.9 1998/03/20 09:01:12 calle - * Changes capi_register handling to get full support for 30 bchannels. - * - * Revision 1.3.2.8 1998/03/18 17:51:28 calle - * added controller number to error messages - * - * Revision 1.3.2.7 1998/02/27 15:40:47 calle - * T1 running with slow link. bugfix in capi_release. - * - * Revision 1.11 1998/02/13 07:09:15 calle - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.10 1998/02/02 19:52:23 calle - * Fixed vbox (audio) acceptb. - * - * Revision 1.9 1998/01/31 11:14:45 calle - * merged changes to 2.0 tree, prepare 2.1.82 to work. - * - * Revision 1.8 1997/11/04 06:12:09 calle - * capi.c: new read/write in file_ops since 2.1.60 - * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware. - * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON) - * compat.h: added #define LinuxVersionCode - * - * Revision 1.7 1997/10/11 10:36:34 calle - * Added isdnlog support. patch to isdnlog needed. - * - * Revision 1.6 1997/10/11 10:25:55 calle - * New interface for lowlevel drivers. BSENT with nr. of bytes sent, - * allow sending without ACK. - * - * Revision 1.5 1997/10/01 09:21:16 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.4 1997/07/13 12:22:43 calle - * bug fix for more than one controller in connect_req. - * debugoutput now with contrnr. - * - * Revision 1.3 1997/05/18 09:24:15 calle - * added verbose disconnect reason reporting to avmb1. - * some fixes in capi20 interface. - * changed info messages for B1-PCI - * - * Revision 1.2 1997/03/05 21:19:59 fritz - * Removed include of config.h (mkdep stated this is unneded). - * - * Revision 1.1 1997/03/04 21:50:31 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "capiutil.h" -#include "capicmd.h" -#include "capidrv.h" - -static char *revision = "$Revision$"; -int debugmode = 0; - -MODULE_AUTHOR("Carsten Paeth "); -MODULE_PARM(debugmode, "i"); - -/* -------- type definitions ----------------------------------------- */ - - -struct capidrv_contr { - - struct capidrv_contr *next; - - __u32 contrnr; - char name[20]; - - /* - * for isdn4linux - */ - isdn_if interface; - int myid; - - /* - * LISTEN state - */ - int state; - __u32 cipmask; - __u32 cipmask2; - struct timer_list listentimer; - - /* - * ID of capi message sent - */ - __u16 msgid; - - /* - * B-Channels - */ - int nbchan; - struct capidrv_bchan { - struct capidrv_contr *contr; - __u8 msn[ISDN_MSNLEN]; - int l2; - int l3; - __u8 num[ISDN_MSNLEN]; - __u8 mynum[ISDN_MSNLEN]; - int si1; - int si2; - int incoming; - int disconnecting; - struct capidrv_plci { - struct capidrv_plci *next; - __u32 plci; - __u32 ncci; /* ncci for CONNECT_ACTIVE_IND */ - __u16 msgid; /* to identfy CONNECT_CONF */ - int chan; - int state; - int leasedline; - struct capidrv_ncci { - struct capidrv_ncci *next; - struct capidrv_plci *plcip; - __u32 ncci; - __u16 msgid; /* to identfy CONNECT_B3_CONF */ - int chan; - int state; - int oldstate; - /* */ - __u16 datahandle; - struct ncci_datahandle_queue { - struct ncci_datahandle_queue *next; - __u16 datahandle; - int len; - } *ackqueue; - } *ncci_list; - } *plcip; - struct capidrv_ncci *nccip; - } *bchans; - - struct capidrv_plci *plci_list; - - /* for q931 data */ - __u8 q931_buf[4096]; - __u8 *q931_read; - __u8 *q931_write; - __u8 *q931_end; -}; - - -struct capidrv_data { - __u16 appid; - int ncontr; - struct capidrv_contr *contr_list; - - /* statistic */ - unsigned long nrecvctlpkt; - unsigned long nrecvdatapkt; - unsigned long nsentctlpkt; - unsigned long nsentdatapkt; -}; - -typedef struct capidrv_plci capidrv_plci; -typedef struct capidrv_ncci capidrv_ncci; -typedef struct capidrv_contr capidrv_contr; -typedef struct capidrv_data capidrv_data; -typedef struct capidrv_bchan capidrv_bchan; - -/* -------- data definitions ----------------------------------------- */ - -static capidrv_data global; -static struct capi_interface *capifuncs; - -static void handle_dtrace_data(capidrv_contr *card, - int send, int level2, __u8 *data, __u16 len); - -/* -------- convert functions ---------------------------------------- */ - -static inline __u32 b1prot(int l2, int l3) -{ - switch (l2) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - return 0; - case ISDN_PROTO_L2_HDLC: - default: - return 0; - case ISDN_PROTO_L2_TRANS: - return 1; - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - return 2; - case ISDN_PROTO_L2_FAX: - return 4; - } -} - -static inline __u32 b2prot(int l2, int l3) -{ - switch (l2) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - default: - return 0; - case ISDN_PROTO_L2_HDLC: - case ISDN_PROTO_L2_TRANS: - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - return 1; - case ISDN_PROTO_L2_FAX: - return 4; - } -} - -static inline __u32 b3prot(int l2, int l3) -{ - switch (l2) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - case ISDN_PROTO_L2_HDLC: - case ISDN_PROTO_L2_TRANS: - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - default: - return 0; - case ISDN_PROTO_L2_FAX: - return 4; - } -} - -static _cstruct b1config_sync_v110(__u16 rate) -{ - /* CAPI-Spec "B1 Configuration" */ - static unsigned char buf[9]; - buf[0] = 8; /* len */ - /* maximum bitrate */ - buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff; - buf[3] = buf[4] = 0; /* reserved, bits per character */ - buf[5] = buf[6] = 0; /* reserved, parity */ - buf[7] = buf[9] = 0; /* reserved, stop bits */ - return buf; -} - -static _cstruct b1config(int l2, int l3) -{ - switch (l2) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - case ISDN_PROTO_L2_HDLC: - case ISDN_PROTO_L2_TRANS: - default: - return 0; - case ISDN_PROTO_L2_V11096: - return b1config_sync_v110(9600); - case ISDN_PROTO_L2_V11019: - return b1config_sync_v110(19200); - case ISDN_PROTO_L2_V11038: - return b1config_sync_v110(38400); - } -} - -static inline __u16 si2cip(__u8 si1, __u8 si2) -{ - static const __u8 cip[17][5] = - { - /* 0 1 2 3 4 */ - {0, 0, 0, 0, 0}, /*0 */ - {16, 16, 4, 26, 16}, /*1 */ - {17, 17, 17, 4, 4}, /*2 */ - {2, 2, 2, 2, 2}, /*3 */ - {18, 18, 18, 18, 18}, /*4 */ - {2, 2, 2, 2, 2}, /*5 */ - {0, 0, 0, 0, 0}, /*6 */ - {2, 2, 2, 2, 2}, /*7 */ - {2, 2, 2, 2, 2}, /*8 */ - {21, 21, 21, 21, 21}, /*9 */ - {19, 19, 19, 19, 19}, /*10 */ - {0, 0, 0, 0, 0}, /*11 */ - {0, 0, 0, 0, 0}, /*12 */ - {0, 0, 0, 0, 0}, /*13 */ - {0, 0, 0, 0, 0}, /*14 */ - {22, 22, 22, 22, 22}, /*15 */ - {27, 27, 27, 28, 27} /*16 */ - }; - if (si1 > 16) - si1 = 0; - if (si2 > 4) - si2 = 0; - - return (__u16) cip[si1][si2]; -} - -static inline __u8 cip2si1(__u16 cipval) -{ - static const __u8 si[32] = - {7, 1, 7, 7, 1, 1, 7, 7, /*0-7 */ - 7, 1, 0, 0, 0, 0, 0, 0, /*8-15 */ - 1, 2, 4, 10, 9, 9, 15, 7, /*16-23 */ - 7, 7, 1, 16, 16, 0, 0, 0}; /*24-31 */ - - if (cipval > 31) - cipval = 0; /* .... */ - return si[cipval]; -} - -static inline __u8 cip2si2(__u16 cipval) -{ - static const __u8 si[32] = - {0, 0, 0, 0, 2, 3, 0, 0, /*0-7 */ - 0, 3, 0, 0, 0, 0, 0, 0, /*8-15 */ - 1, 2, 0, 0, 9, 0, 0, 0, /*16-23 */ - 0, 0, 3, 2, 3, 0, 0, 0}; /*24-31 */ - - if (cipval > 31) - cipval = 0; /* .... */ - return si[cipval]; -} - - -/* -------- controller managment ------------------------------------- */ - -static inline capidrv_contr *findcontrbydriverid(int driverid) -{ - capidrv_contr *p = global.contr_list; - long flags; - - save_flags(flags); - cli(); - while (p) { - if (p->myid == driverid) - break; - p = p->next; - } - restore_flags(flags); - return p; -} - -static capidrv_contr *findcontrbynumber(__u32 contr) -{ - capidrv_contr *p = global.contr_list; - long flags; - - save_flags(flags); - cli(); - while (p) { - if (p->contrnr == contr) - break; - p = p->next; - } - restore_flags(flags); - return p; -} - - -/* -------- plci management ------------------------------------------ */ - -static capidrv_plci *new_plci(capidrv_contr * card, int chan) -{ - capidrv_plci *plcip; - - plcip = (capidrv_plci *) kmalloc(sizeof(capidrv_plci), GFP_ATOMIC); - - if (plcip == 0) - return 0; - - memset(plcip, 0, sizeof(capidrv_plci)); - plcip->state = ST_PLCI_NONE; - plcip->plci = 0; - plcip->msgid = 0; - plcip->chan = chan; - plcip->next = card->plci_list; - card->plci_list = plcip; - card->bchans[chan].plcip = plcip; - - return plcip; -} - -static capidrv_plci *find_plci_by_plci(capidrv_contr * card, __u32 plci) -{ - capidrv_plci *p; - for (p = card->plci_list; p; p = p->next) - if (p->plci == plci) - return p; - return 0; -} - -static capidrv_plci *find_plci_by_msgid(capidrv_contr * card, __u16 msgid) -{ - capidrv_plci *p; - for (p = card->plci_list; p; p = p->next) - if (p->msgid == msgid) - return p; - return 0; -} - -static capidrv_plci *find_plci_by_ncci(capidrv_contr * card, __u32 ncci) -{ - capidrv_plci *p; - for (p = card->plci_list; p; p = p->next) - if (p->plci == (ncci & 0xffff)) - return p; - return 0; -} - -static void free_plci(capidrv_contr * card, capidrv_plci * plcip) -{ - capidrv_plci **pp; - - for (pp = &card->plci_list; *pp; pp = &(*pp)->next) { - if (*pp == plcip) { - *pp = (*pp)->next; - card->bchans[plcip->chan].plcip = 0; - card->bchans[plcip->chan].disconnecting = 0; - card->bchans[plcip->chan].incoming = 0; - kfree(plcip); - return; - } - } - printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n", - card->contrnr, plcip, plcip->plci); -} - -/* -------- ncci management ------------------------------------------ */ - -static inline capidrv_ncci *new_ncci(capidrv_contr * card, - capidrv_plci * plcip, - __u32 ncci) -{ - capidrv_ncci *nccip; - - nccip = (capidrv_ncci *) kmalloc(sizeof(capidrv_ncci), GFP_ATOMIC); - - if (nccip == 0) - return 0; - - memset(nccip, 0, sizeof(capidrv_ncci)); - nccip->ncci = ncci; - nccip->state = ST_NCCI_NONE; - nccip->plcip = plcip; - nccip->chan = plcip->chan; - nccip->datahandle = 0; - - nccip->next = plcip->ncci_list; - plcip->ncci_list = nccip; - - card->bchans[plcip->chan].nccip = nccip; - - return nccip; -} - -static inline capidrv_ncci *find_ncci(capidrv_contr * card, __u32 ncci) -{ - capidrv_plci *plcip; - capidrv_ncci *p; - - if ((plcip = find_plci_by_ncci(card, ncci)) == 0) - return 0; - - for (p = plcip->ncci_list; p; p = p->next) - if (p->ncci == ncci) - return p; - return 0; -} - -static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr * card, - __u32 ncci, __u16 msgid) -{ - capidrv_plci *plcip; - capidrv_ncci *p; - - if ((plcip = find_plci_by_ncci(card, ncci)) == 0) - return 0; - - for (p = plcip->ncci_list; p; p = p->next) - if (p->msgid == msgid) - return p; - return 0; -} - -static void free_ncci(capidrv_contr * card, struct capidrv_ncci *nccip) -{ - struct capidrv_ncci **pp; - - for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) { - if (*pp == nccip) { - *pp = (*pp)->next; - break; - } - } - card->bchans[nccip->chan].nccip = 0; - kfree(nccip); -} - -static int capidrv_add_ack(struct capidrv_ncci *nccip, - __u16 datahandle, int len) -{ - struct ncci_datahandle_queue *n, **pp; - - n = (struct ncci_datahandle_queue *) - kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC); - if (!n) { - printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n"); - return -1; - } - n->next = 0; - n->datahandle = datahandle; - n->len = len; - for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) ; - *pp = n; - return 0; -} - -static int capidrv_del_ack(struct capidrv_ncci *nccip, __u16 datahandle) -{ - struct ncci_datahandle_queue **pp, *p; - int len; - - for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) { - if ((*pp)->datahandle == datahandle) { - p = *pp; - len = p->len; - *pp = (*pp)->next; - kfree(p); - return len; - } - } - return -1; -} - -/* -------- convert and send capi message ---------------------------- */ - -static void send_message(capidrv_contr * card, _cmsg * cmsg) -{ - struct sk_buff *skb; - size_t len; - capi_cmsg2message(cmsg, cmsg->buf); - len = CAPIMSG_LEN(cmsg->buf); - skb = alloc_skb(len, GFP_ATOMIC); - memcpy(skb_put(skb, len), cmsg->buf, len); - (*capifuncs->capi_put_message) (global.appid, skb); - global.nsentctlpkt++; -} - -/* -------- state machine -------------------------------------------- */ - -struct listenstatechange { - int actstate; - int nextstate; - int event; -}; - -static struct listenstatechange listentable[] = -{ - {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ}, - {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ}, - {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR}, - {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR}, - {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, - {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY}, - {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, - {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK}, - {}, -}; - -static void listen_change_state(capidrv_contr * card, int event) -{ - struct listenstatechange *p = listentable; - while (p->event) { - if (card->state == p->actstate && p->event == event) { - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n", - card->contrnr, card->state, p->nextstate); - card->state = p->nextstate; - return; - } - p++; - } - printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n", - card->contrnr, card->state, event); - -} - -/* ------------------------------------------------------------------ */ - -static void p0(capidrv_contr * card, capidrv_plci * plci) -{ - isdn_ctrl cmd; - - card->bchans[plci->chan].contr = 0; - cmd.command = ISDN_STAT_DHUP; - cmd.driver = card->myid; - cmd.arg = plci->chan; - card->interface.statcallb(&cmd); - free_plci(card, plci); -} - -/* ------------------------------------------------------------------ */ - -struct plcistatechange { - int actstate; - int nextstate; - int event; - void (*changefunc) (capidrv_contr * card, capidrv_plci * plci); -}; - -static struct plcistatechange plcitable[] = -{ - /* P-0 */ - {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, 0}, - {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, 0}, - {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, 0}, - {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, 0}, - /* P-0.1 */ - {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0}, - {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, 0}, - /* P-1 */ - {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, - {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, - /* P-ACT */ - {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, - {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, 0}, - {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, 0}, - /* P-2 */ - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, - {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, 0}, - {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, 0}, - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, - {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, 0}, - /* P-3 */ - {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, 0}, - {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, 0}, - {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, - /* P-4 */ - {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, 0}, - {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, 0}, - {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, 0}, - {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, - /* P-5 */ - {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, 0}, - /* P-6 */ - {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0}, - /* P-0.Res */ - {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0}, - {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, 0}, - /* P-RES */ - {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, 0}, - /* P-HELD */ - {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, 0}, - {}, -}; - -static void plci_change_state(capidrv_contr * card, capidrv_plci * plci, int event) -{ - struct plcistatechange *p = plcitable; - while (p->event) { - if (plci->state == p->actstate && p->event == event) { - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n", - card->contrnr, plci->plci, plci->state, p->nextstate); - plci->state = p->nextstate; - if (p->changefunc) - p->changefunc(card, plci); - return; - } - p++; - } - printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n", - card->contrnr, plci->plci, plci->state, event); -} - -/* ------------------------------------------------------------------ */ - -static _cmsg cmsg; - -static void n0(capidrv_contr * card, capidrv_ncci * ncci) -{ - isdn_ctrl cmd; - - capi_fill_DISCONNECT_REQ(&cmsg, - global.appid, - card->msgid++, - ncci->plcip->plci, - 0, /* BChannelinformation */ - 0, /* Keypadfacility */ - 0, /* Useruserdata */ /* $$$$ */ - 0 /* Facilitydataarray */ - ); - send_message(card, &cmsg); - plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ); - - cmd.command = ISDN_STAT_BHUP; - cmd.driver = card->myid; - cmd.arg = ncci->chan; - card->interface.statcallb(&cmd); - free_ncci(card, ncci); -} - -/* ------------------------------------------------------------------ */ - -struct nccistatechange { - int actstate; - int nextstate; - int event; - void (*changefunc) (capidrv_contr * card, capidrv_ncci * ncci); -}; - -static struct nccistatechange nccitable[] = -{ - /* N-0 */ - {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, 0}, - {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, 0}, - /* N-0.1 */ - {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, 0}, - {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0}, - /* N-1 */ - {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, 0}, - {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, 0}, - {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, - /* N-2 */ - {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, 0}, - {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, - /* N-ACT */ - {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0}, - {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, 0}, - {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, - /* N-3 */ - {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, 0}, - {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, 0}, - /* N-4 */ - {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, 0}, - {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR,0}, - /* N-5 */ - {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0}, - {}, -}; - -static void ncci_change_state(capidrv_contr * card, capidrv_ncci * ncci, int event) -{ - struct nccistatechange *p = nccitable; - while (p->event) { - if (ncci->state == p->actstate && p->event == event) { - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n", - card->contrnr, ncci->ncci, ncci->state, p->nextstate); - if (p->nextstate == ST_NCCI_PREVIOUS) { - ncci->state = ncci->oldstate; - ncci->oldstate = p->actstate; - } else { - ncci->oldstate = p->actstate; - ncci->state = p->nextstate; - } - if (p->changefunc) - p->changefunc(card, ncci); - return; - } - p++; - } - printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n", - card->contrnr, ncci->ncci, ncci->state, event); -} - -/* ------------------------------------------------------------------- */ - -static inline int new_bchan(capidrv_contr * card) -{ - int i; - for (i = 0; i < card->nbchan; i++) { - if (card->bchans[i].plcip == 0) { - card->bchans[i].disconnecting = 0; - return i; - } - } - return -1; -} - -/* ------------------------------------------------------------------- */ - -static void handle_controller(_cmsg * cmsg) -{ - capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); - - if (!card) { - printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController & 0x7f); - return; - } - switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) { - - case CAPI_LISTEN_CONF: /* Controller */ - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n", - card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask); - if (cmsg->Info) { - listen_change_state(card, EV_LISTEN_CONF_ERROR); - } else if (card->cipmask == 0) { - listen_change_state(card, EV_LISTEN_CONF_EMPTY); - } else { - listen_change_state(card, EV_LISTEN_CONF_OK); - } - break; - - case CAPI_MANUFACTURER_IND: /* Controller */ - if ( cmsg->ManuID == 0x214D5641 - && cmsg->Class == 0 - && cmsg->Function == 1) { - __u8 *data = cmsg->ManuData+3; - __u16 len = cmsg->ManuData[0]; - __u16 layer; - int direction; - if (len == 255) { - len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8)); - data += 2; - } - len -= 2; - layer = ((*(data-1)) << 8) | *(data-2); - if (layer & 0x300) - direction = (layer & 0x200) ? 0 : 1; - else direction = (layer & 0x800) ? 0 : 1; - if (layer & 0x0C00) { - if ((layer & 0xff) == 0x80) { - handle_dtrace_data(card, direction, 1, data, len); - break; - } - } else if ((layer & 0xff) < 0x80) { - handle_dtrace_data(card, direction, 0, data, len); - break; - } - printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController, layer); - break; - } - goto ignored; - case CAPI_MANUFACTURER_CONF: /* Controller */ - if (cmsg->ManuID == 0x214D5641) { - char *s = 0; - switch (cmsg->Class) { - case 0: break; - case 1: s = "unknown class"; break; - case 2: s = "unknown function"; break; - default: s = "unkown error"; break; - } - if (s) - printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController, - cmsg->Function, s); - break; - } - goto ignored; - case CAPI_FACILITY_IND: /* Controller/plci/ncci */ - goto ignored; - case CAPI_FACILITY_CONF: /* Controller/plci/ncci */ - goto ignored; - case CAPI_INFO_IND: /* Controller/plci */ - goto ignored; - case CAPI_INFO_CONF: /* Controller/plci */ - goto ignored; - - default: - printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController); - } - return; - - ignored: - printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController); -} - -static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg) -{ - capidrv_plci *plcip; - capidrv_bchan *bchan; - isdn_ctrl cmd; - int chan; - - if ((chan = new_bchan(card)) == -1) { - printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr); - return; - } - bchan = &card->bchans[chan]; - if ((plcip = new_plci(card, chan)) == 0) { - printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr); - return; - } - bchan->incoming = 1; - plcip->plci = cmsg->adr.adrPLCI; - plci_change_state(card, plcip, EV_PLCI_CONNECT_IND); - - cmd.command = ISDN_STAT_ICALL; - cmd.driver = card->myid; - cmd.arg = chan; - memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup)); - strncpy(cmd.parm.setup.phone, - cmsg->CallingPartyNumber + 3, - cmsg->CallingPartyNumber[0] - 2); - strncpy(cmd.parm.setup.eazmsn, - cmsg->CalledPartyNumber + 2, - cmsg->CalledPartyNumber[0] - 1); - cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue); - cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue); - cmd.parm.setup.plan = cmsg->CallingPartyNumber[1]; - cmd.parm.setup.screen = cmsg->CallingPartyNumber[2]; - - printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n", - card->contrnr, - cmd.parm.setup.phone, - cmd.parm.setup.si1, - cmd.parm.setup.si2, - cmd.parm.setup.eazmsn); - - if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) { - printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOX\n", - card->contrnr, - cmd.parm.setup.si2); - cmd.parm.setup.si2 = 0; - } - - switch (card->interface.statcallb(&cmd)) { - case 0: - case 3: - /* No device matching this call. - * and isdn_common.c has send a HANGUP command - * which is ignored in state ST_PLCI_INCOMING, - * so we send RESP to ignore the call - */ - capi_cmsg_answer(cmsg); - cmsg->Reject = 1; /* ignore */ - send_message(card, cmsg); - plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); - printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n", - card->contrnr, - cmd.parm.setup.phone, - cmd.parm.setup.si1, - cmd.parm.setup.si2, - cmd.parm.setup.eazmsn); - break; - case 1: - /* At least one device matching this call (RING on ttyI) - * HL-driver may send ALERTING on the D-channel in this - * case. - * really means: RING on ttyI or a net interface - * accepted this call already. - * - * If the call was accepted, state has already changed, - * and CONNECT_RESP already sent. - */ - if (plcip->state == ST_PLCI_INCOMING) { - printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n", - card->contrnr, - cmd.parm.setup.phone, - cmd.parm.setup.si1, - cmd.parm.setup.si2, - cmd.parm.setup.eazmsn); - capi_fill_ALERT_REQ(cmsg, - global.appid, - card->msgid++, - plcip->plci, /* adr */ - 0, /* BChannelinformation */ - 0, /* Keypadfacility */ - 0, /* Useruserdata */ - 0 /* Facilitydataarray */ - ); - plcip->msgid = cmsg->Messagenumber; - send_message(card, cmsg); - } else { - printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n", - card->contrnr, - cmd.parm.setup.phone, - cmd.parm.setup.si1, - cmd.parm.setup.si2, - cmd.parm.setup.eazmsn); - } - break; - - case 2: /* Call will be rejected. */ - capi_cmsg_answer(cmsg); - cmsg->Reject = 2; /* reject call, normal call clearing */ - send_message(card, cmsg); - plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); - break; - - default: - /* An error happened. (Invalid parameters for example.) */ - capi_cmsg_answer(cmsg); - cmsg->Reject = 8; /* reject call, - destination out of order */ - send_message(card, cmsg); - plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); - break; - } - return; -} - -static void handle_plci(_cmsg * cmsg) -{ - capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); - capidrv_plci *plcip; - isdn_ctrl cmd; - - if (!card) { - printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController & 0x7f); - return; - } - switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) { - - case CAPI_DISCONNECT_IND: /* plci */ - if (cmsg->Reason) { - printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI); - } - if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) { - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - goto notfound; - } - card->bchans[plcip->chan].disconnecting = 1; - plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND); - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP); - break; - - case CAPI_DISCONNECT_CONF: /* plci */ - if (cmsg->Info) { - printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->Info, capi_info2str(cmsg->Info), - cmsg->adr.adrPLCI); - } - if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) - goto notfound; - - card->bchans[plcip->chan].disconnecting = 1; - break; - - case CAPI_ALERT_CONF: /* plci */ - if (cmsg->Info) { - printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->Info, capi_info2str(cmsg->Info), - cmsg->adr.adrPLCI); - } - break; - - case CAPI_CONNECT_IND: /* plci */ - handle_incoming_call(card, cmsg); - break; - - case CAPI_CONNECT_CONF: /* plci */ - if (cmsg->Info) { - printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->Info, capi_info2str(cmsg->Info), - cmsg->adr.adrPLCI); - } - if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber))) - goto notfound; - - plcip->plci = cmsg->adr.adrPLCI; - if (cmsg->Info) { - plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR); - } else { - plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK); - } - break; - - case CAPI_CONNECT_ACTIVE_IND: /* plci */ - - if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) - goto notfound; - - if (card->bchans[plcip->chan].incoming) { - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND); - } else { - capidrv_ncci *nccip; - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - - nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI); - - if (!nccip) { - printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr); - break; /* $$$$ */ - } - capi_fill_CONNECT_B3_REQ(cmsg, - global.appid, - card->msgid++, - plcip->plci, /* adr */ - 0 /* NCPI */ - ); - nccip->msgid = cmsg->Messagenumber; - send_message(card, cmsg); - cmd.command = ISDN_STAT_DCONN; - cmd.driver = card->myid; - cmd.arg = plcip->chan; - card->interface.statcallb(&cmd); - plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND); - ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ); - } - break; - - case CAPI_INFO_IND: /* Controller/plci */ - - if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) - goto notfound; - - if (cmsg->InfoNumber == 0x4000) { - if (cmsg->InfoElement[0] == 4) { - cmd.command = ISDN_STAT_CINF; - cmd.driver = card->myid; - cmd.arg = plcip->chan; - sprintf(cmd.parm.num, "%lu", - (unsigned long) - ((__u32) cmsg->InfoElement[1] - | ((__u32) (cmsg->InfoElement[2]) << 8) - | ((__u32) (cmsg->InfoElement[3]) << 16) - | ((__u32) (cmsg->InfoElement[4]) << 24))); - card->interface.statcallb(&cmd); - break; - } - } - printk(KERN_ERR "capidrv-%d: %s\n", - card->contrnr, capi_cmsg2str(cmsg)); - break; - - case CAPI_CONNECT_ACTIVE_CONF: /* plci */ - goto ignored; - case CAPI_SELECT_B_PROTOCOL_CONF: /* plci */ - goto ignored; - case CAPI_FACILITY_IND: /* Controller/plci/ncci */ - goto ignored; - case CAPI_FACILITY_CONF: /* Controller/plci/ncci */ - goto ignored; - - case CAPI_INFO_CONF: /* Controller/plci */ - goto ignored; - - default: - printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrPLCI); - } - return; - ignored: - printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrPLCI); - return; - notfound: - printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrPLCI); - return; -} - -static void handle_ncci(_cmsg * cmsg) -{ - capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); - capidrv_plci *plcip; - capidrv_ncci *nccip; - isdn_ctrl cmd; - int len; - - if (!card) { - printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController & 0x7f); - return; - } - switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) { - - case CAPI_CONNECT_B3_ACTIVE_IND: /* ncci */ - if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) - goto notfound; - - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND); - - cmd.command = ISDN_STAT_BCONN; - cmd.driver = card->myid; - cmd.arg = nccip->chan; - card->interface.statcallb(&cmd); - - printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n", - card->contrnr, nccip->chan, nccip->ncci); - break; - - case CAPI_CONNECT_B3_ACTIVE_CONF: /* ncci */ - goto ignored; - - case CAPI_CONNECT_B3_IND: /* ncci */ - - plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI); - if (plcip) { - nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI); - if (nccip) { - ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND); - capi_fill_CONNECT_B3_RESP(cmsg, - global.appid, - card->msgid++, - nccip->ncci, /* adr */ - 0, /* Reject */ - 0 /* NCPI */ - ); - send_message(card, cmsg); - ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP); - break; - } - printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr); - } else { - printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrNCCI); - } - capi_fill_CONNECT_B3_RESP(cmsg, - global.appid, - card->msgid++, - cmsg->adr.adrNCCI, - 2, /* Reject */ - 0 /* NCPI */ - ); - send_message(card, cmsg); - break; - - case CAPI_CONNECT_B3_CONF: /* ncci */ - - if (!(nccip = find_ncci_by_msgid(card, - cmsg->adr.adrNCCI, - cmsg->Messagenumber))) - goto notfound; - - nccip->ncci = cmsg->adr.adrNCCI; - if (cmsg->Info) { - printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->Info, capi_info2str(cmsg->Info), - cmsg->adr.adrNCCI); - } - - if (cmsg->Info) - ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR); - else - ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK); - break; - - case CAPI_CONNECT_B3_T90_ACTIVE_IND: /* ncci */ - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - break; - - case CAPI_DATA_B3_IND: /* ncci */ - /* handled in handle_data() */ - goto ignored; - - case CAPI_DATA_B3_CONF: /* ncci */ - if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) - goto notfound; - - len = capidrv_del_ack(nccip, cmsg->DataHandle); - if (len < 0) - break; - cmd.command = ISDN_STAT_BSENT; - cmd.driver = card->myid; - cmd.arg = nccip->chan; - cmd.parm.length = len; - card->interface.statcallb(&cmd); - break; - - case CAPI_DISCONNECT_B3_IND: /* ncci */ - if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) - goto notfound; - - card->bchans[nccip->chan].disconnecting = 1; - ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND); - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP); - break; - - case CAPI_DISCONNECT_B3_CONF: /* ncci */ - if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) - goto notfound; - if (cmsg->Info) { - printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->Info, capi_info2str(cmsg->Info), - cmsg->adr.adrNCCI); - ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR); - } - break; - - case CAPI_RESET_B3_IND: /* ncci */ - if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) - goto notfound; - ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND); - capi_cmsg_answer(cmsg); - send_message(card, cmsg); - break; - - case CAPI_RESET_B3_CONF: /* ncci */ - goto ignored; /* $$$$ */ - - case CAPI_FACILITY_IND: /* Controller/plci/ncci */ - goto ignored; - case CAPI_FACILITY_CONF: /* Controller/plci/ncci */ - goto ignored; - - default: - printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrNCCI); - } - return; - ignored: - printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrNCCI); - return; - notfound: - printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrNCCI); -} - - -static void handle_data(_cmsg * cmsg, struct sk_buff *skb) -{ - capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f); - capidrv_ncci *nccip; - - if (!card) { - printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n", - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrController & 0x7f); - kfree_skb(skb); - return; - } - if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) { - printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n", - card->contrnr, - capi_cmd2str(cmsg->Command, cmsg->Subcommand), - cmsg->adr.adrNCCI); - kfree_skb(skb); - return; - } - (void) skb_pull(skb, CAPIMSG_LEN(skb->data)); - card->interface.rcvcallb_skb(card->myid, nccip->chan, skb); - capi_cmsg_answer(cmsg); - send_message(card, cmsg); -} - -static _cmsg s_cmsg; - -static void capidrv_signal(__u16 applid, void *dummy) -{ - struct sk_buff *skb = 0; - - while ((*capifuncs->capi_get_message) (global.appid, &skb) == CAPI_NOERROR) { - capi_message2cmsg(&s_cmsg, skb->data); - if (debugmode > 2) - printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", - applid, capi_cmsg2str(&s_cmsg)); - - if (s_cmsg.Command == CAPI_DATA_B3 - && s_cmsg.Subcommand == CAPI_IND) { - handle_data(&s_cmsg, skb); - global.nrecvdatapkt++; - continue; - } - if ((s_cmsg.adr.adrController & 0xffffff00) == 0) - handle_controller(&s_cmsg); - else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0) - handle_plci(&s_cmsg); - else - handle_ncci(&s_cmsg); - /* - * data of skb used in s_cmsg, - * free data when s_cmsg is not used again - * thanks to Lars Heete - */ - kfree_skb(skb); - global.nrecvctlpkt++; - } -} - -/* ------------------------------------------------------------------- */ - -#define PUTBYTE_TO_STATUS(card, byte) \ - do { \ - *(card)->q931_write++ = (byte); \ - if ((card)->q931_write > (card)->q931_end) \ - (card)->q931_write = (card)->q931_buf; \ - } while (0) - -static void handle_dtrace_data(capidrv_contr *card, - int send, int level2, __u8 *data, __u16 len) -{ - long flags; - __u8 *p, *end; - isdn_ctrl cmd; - - if (!len) { - printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n", - card->contrnr, len); - return; - } - - save_flags(flags); - cli(); - - if (level2) { - PUTBYTE_TO_STATUS(card, 'D'); - PUTBYTE_TO_STATUS(card, '2'); - PUTBYTE_TO_STATUS(card, send ? '>' : '<'); - PUTBYTE_TO_STATUS(card, ':'); - } else { - PUTBYTE_TO_STATUS(card, 'D'); - PUTBYTE_TO_STATUS(card, '3'); - PUTBYTE_TO_STATUS(card, send ? '>' : '<'); - PUTBYTE_TO_STATUS(card, ':'); - } - - for (p = data, end = data+len; p < end; p++) { - __u8 w; - PUTBYTE_TO_STATUS(card, ' '); - w = (*p >> 4) & 0xf; - PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w); - w = *p & 0xf; - PUTBYTE_TO_STATUS(card, (w < 10) ? '0'+w : 'A'-10+w); - } - PUTBYTE_TO_STATUS(card, '\n'); - - restore_flags(flags); - - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = len*3+5; - card->interface.statcallb(&cmd); -} - -/* ------------------------------------------------------------------- */ - -static _cmsg cmdcmsg; - -static int capidrv_ioctl(isdn_ctrl * c, capidrv_contr * card) -{ - switch (c->arg) { - case 1: - debugmode = (int)(*((unsigned int *)c->parm.num)); - printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n", - card->contrnr, debugmode); - return 0; - default: - printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n", - card->contrnr, c->arg); - return -EINVAL; - } - return -EINVAL; -} - -/* - * Handle leased lines (CAPI-Bundling) - */ - -struct internal_bchannelinfo { - unsigned short channelalloc; - unsigned short operation; - unsigned char cmask[31]; -}; - -static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep) -{ - unsigned long bmask = 0; - int active = !0; - char *s; - int i; - - if (strncmp(teln, "FV:", 3) != 0) - return 1; - s = teln + 3; - while (*s && *s == ' ') s++; - if (!*s) return -2; - if (*s == 'p' || *s == 'P') { - active = 0; - s++; - } - if (*s == 'a' || *s == 'A') { - active = !0; - s++; - } - while (*s) { - int digit1 = 0; - int digit2 = 0; - if (!isdigit(*s)) return -3; - while (isdigit(*s)) { digit1 = digit1*10 + (*s - '0'); s++; } - if (digit1 <= 0 && digit1 > 30) return -4; - if (*s == 0 || *s == ',' || *s == ' ') { - bmask |= (1 << digit1); - digit1 = 0; - if (*s) s++; - continue; - } - if (*s != '-') return -5; - s++; - if (!isdigit(*s)) return -3; - while (isdigit(*s)) { digit2 = digit2*10 + (*s - '0'); s++; } - if (digit2 <= 0 && digit2 > 30) return -4; - if (*s == 0 || *s == ',' || *s == ' ') { - if (digit1 > digit2) - for (i = digit2; i <= digit1 ; i++) - bmask |= (1 << i); - else - for (i = digit1; i <= digit2 ; i++) - bmask |= (1 << i); - digit1 = digit2 = 0; - if (*s) s++; - continue; - } - return -6; - } - if (activep) *activep = active; - if (bmaskp) *bmaskp = bmask; - return 0; -} - -static int FVteln2capi20(char *teln, __u8 AdditionalInfo[1+2+2+31]) -{ - unsigned long bmask; - int active; - int rc, i; - - rc = decodeFVteln(teln, &bmask, &active); - if (rc) return rc; - /* Length */ - AdditionalInfo[0] = 2+2+31; - /* Channel: 3 => use channel allocation */ - AdditionalInfo[1] = 3; AdditionalInfo[2] = 0; - /* Operation: 0 => DTE mode, 1 => DCE mode */ - if (active) { - AdditionalInfo[3] = 0; AdditionalInfo[4] = 0; - } else { - AdditionalInfo[3] = 1; AdditionalInfo[4] = 0; - } - /* Channel mask array */ - AdditionalInfo[5] = 0; /* no D-Channel */ - for (i=1; i <= 30; i++) - AdditionalInfo[5+i] = (bmask & (1 << i)) ? 0xff : 0; - return 0; -} - -static int capidrv_command(isdn_ctrl * c, capidrv_contr * card) -{ - isdn_ctrl cmd; - struct capidrv_bchan *bchan; - struct capidrv_plci *plcip; - __u8 AdditionalInfo[1+2+2+31]; - int rc, isleasedline = 0; - - if (c->command == ISDN_CMD_IOCTL) - return capidrv_ioctl(c, card); - - switch (c->command) { - case ISDN_CMD_DIAL:{ - __u8 calling[ISDN_MSNLEN + 3]; - __u8 called[ISDN_MSNLEN + 2]; - - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n", - card->contrnr, - c->arg, - c->parm.setup.phone, - c->parm.setup.si1, - c->parm.setup.si2, - c->parm.setup.eazmsn); - - bchan = &card->bchans[c->arg % card->nbchan]; - - if (bchan->plcip) { - printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n", - card->contrnr, - c->arg, - c->parm.setup.phone, - c->parm.setup.si1, - c->parm.setup.si2, - c->parm.setup.eazmsn, - bchan->plcip->plci); - return 0; - } - bchan->si1 = c->parm.setup.si1; - bchan->si2 = c->parm.setup.si2; - - strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num)); - strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum)); - rc = FVteln2capi20(bchan->num, AdditionalInfo); - isleasedline = (rc == 0); - if (rc < 0) - printk(KERN_ERR "capidrv-%d: WARNING: illegal leased linedefinition \"%s\"\n", card->contrnr, bchan->num); - - if (isleasedline) { - calling[0] = 0; - called[0] = 0; - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr); - } else { - calling[0] = strlen(bchan->mynum) + 2; - calling[1] = 0; - calling[2] = 0x80; - strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN); - called[0] = strlen(bchan->num) + 1; - called[1] = 0x80; - strncpy(called + 2, bchan->num, ISDN_MSNLEN); - } - - capi_fill_CONNECT_REQ(&cmdcmsg, - global.appid, - card->msgid++, - card->contrnr, /* adr */ - si2cip(bchan->si1, bchan->si2), /* cipvalue */ - called, /* CalledPartyNumber */ - calling, /* CallingPartyNumber */ - 0, /* CalledPartySubaddress */ - 0, /* CallingPartySubaddress */ - b1prot(bchan->l2, bchan->l3), /* B1protocol */ - b2prot(bchan->l2, bchan->l3), /* B2protocol */ - b3prot(bchan->l2, bchan->l3), /* B3protocol */ - b1config(bchan->l2, bchan->l3), /* B1configuration */ - 0, /* B2configuration */ - 0, /* B3configuration */ - 0, /* BC */ - 0, /* LLC */ - 0, /* HLC */ - /* BChannelinformation */ - isleasedline ? AdditionalInfo : 0, - 0, /* Keypadfacility */ - 0, /* Useruserdata */ - 0 /* Facilitydataarray */ - ); - if ((plcip = new_plci(card, (c->arg % card->nbchan))) == 0) { - cmd.command = ISDN_STAT_DHUP; - cmd.driver = card->myid; - cmd.arg = (c->arg % card->nbchan); - card->interface.statcallb(&cmd); - return -1; - } - plcip->msgid = cmdcmsg.Messagenumber; - plcip->leasedline = isleasedline; - plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ); - send_message(card, &cmdcmsg); - return 0; - } - - case ISDN_CMD_ACCEPTD: - - bchan = &card->bchans[c->arg % card->nbchan]; - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n", - card->contrnr, - c->arg, bchan->l2, bchan->l3); - - capi_fill_CONNECT_RESP(&cmdcmsg, - global.appid, - card->msgid++, - bchan->plcip->plci, /* adr */ - 0, /* Reject */ - b1prot(bchan->l2, bchan->l3), /* B1protocol */ - b2prot(bchan->l2, bchan->l3), /* B2protocol */ - b3prot(bchan->l2, bchan->l3), /* B3protocol */ - b1config(bchan->l2, bchan->l3), /* B1configuration */ - 0, /* B2configuration */ - 0, /* B3configuration */ - 0, /* ConnectedNumber */ - 0, /* ConnectedSubaddress */ - 0, /* LLC */ - 0, /* BChannelinformation */ - 0, /* Keypadfacility */ - 0, /* Useruserdata */ - 0 /* Facilitydataarray */ - ); - capi_cmsg2message(&cmdcmsg, cmdcmsg.buf); - plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP); - send_message(card, &cmdcmsg); - return 0; - - case ISDN_CMD_ACCEPTB: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n", - card->contrnr, - c->arg); - return -ENOSYS; - - case ISDN_CMD_HANGUP: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n", - card->contrnr, - c->arg); - bchan = &card->bchans[c->arg % card->nbchan]; - - if (bchan->disconnecting) { - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n", - card->contrnr, - c->arg); - return 0; - } - if (bchan->nccip) { - bchan->disconnecting = 1; - capi_fill_DISCONNECT_B3_REQ(&cmdcmsg, - global.appid, - card->msgid++, - bchan->nccip->ncci, - 0 /* NCPI */ - ); - ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ); - send_message(card, &cmdcmsg); - return 0; - } else if (bchan->plcip) { - if (bchan->plcip->state == ST_PLCI_INCOMING) { - /* - * just ignore, we a called from - * isdn_status_callback(), - * which will return 0 or 2, this is handled - * by the CONNECT_IND handler - */ - bchan->disconnecting = 1; - return 0; - } else if (bchan->plcip->plci) { - bchan->disconnecting = 1; - capi_fill_DISCONNECT_REQ(&cmdcmsg, - global.appid, - card->msgid++, - bchan->plcip->plci, - 0, /* BChannelinformation */ - 0, /* Keypadfacility */ - 0, /* Useruserdata */ - 0 /* Facilitydataarray */ - ); - plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ); - send_message(card, &cmdcmsg); - return 0; - } else { - printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n", - card->contrnr, - c->arg); - return -EINVAL; - } - } - printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n", - card->contrnr, - c->arg); - return -EINVAL; -/* ready */ - - case ISDN_CMD_SETL2: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n", - card->contrnr, - (c->arg & 0xff), (c->arg >> 8)); - bchan = &card->bchans[(c->arg & 0xff) % card->nbchan]; - bchan->l2 = (c->arg >> 8); - return 0; - - case ISDN_CMD_SETL3: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n", - card->contrnr, - (c->arg & 0xff), (c->arg >> 8)); - bchan = &card->bchans[(c->arg & 0xff) % card->nbchan]; - bchan->l3 = (c->arg >> 8); - return 0; - - case ISDN_CMD_SETEAZ: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n", - card->contrnr, - c->parm.num, c->arg); - bchan = &card->bchans[c->arg % card->nbchan]; - strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN); - return 0; - - case ISDN_CMD_CLREAZ: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n", - card->contrnr, c->arg); - bchan = &card->bchans[c->arg % card->nbchan]; - bchan->msn[0] = 0; - return 0; - - case ISDN_CMD_LOCK: - if (debugmode > 1) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_LOCK (%ld)\n", card->contrnr, c->arg); - MOD_INC_USE_COUNT; - break; - - case ISDN_CMD_UNLOCK: - if (debugmode > 1) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_UNLOCK (%ld)\n", - card->contrnr, c->arg); - MOD_DEC_USE_COUNT; - break; - -/* never called */ - case ISDN_CMD_GETL2: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL2\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_GETL3: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETL3\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_GETEAZ: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETEAZ\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_SETSIL: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_SETSIL\n", - card->contrnr); - return -ENODEV; - case ISDN_CMD_GETSIL: - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_GETSIL\n", - card->contrnr); - return -ENODEV; - default: - printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n", - card->contrnr, c->command); - return -EINVAL; - } - return 0; -} - -static int if_command(isdn_ctrl * c) -{ - capidrv_contr *card = findcontrbydriverid(c->driver); - - if (card) - return capidrv_command(c, card); - - printk(KERN_ERR - "capidrv-%d: if_command %d called with invalid driverId %d!\n", - card->contrnr, c->command, c->driver); - return -ENODEV; -} - -static _cmsg sendcmsg; - -static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb) -{ - capidrv_contr *card = findcontrbydriverid(id); - capidrv_bchan *bchan; - capidrv_ncci *nccip; - int len = skb->len; - size_t msglen; - __u16 errcode; - __u16 datahandle; - - if (!card) { - printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n", - card->contrnr, id); - return 0; - } - if (debugmode > 1) - printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n", - card->contrnr, len, skb, doack); - bchan = &card->bchans[channel % card->nbchan]; - nccip = bchan->nccip; - if (!nccip || nccip->state != ST_NCCI_ACTIVE) { - printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n", - card->contrnr, card->name, channel); - return 0; - } - datahandle = nccip->datahandle; - capi_fill_DATA_B3_REQ(&sendcmsg, global.appid, card->msgid++, - nccip->ncci, /* adr */ - (__u32) skb->data, /* Data */ - skb->len, /* DataLength */ - datahandle, /* DataHandle */ - 0 /* Flags */ - ); - - if (capidrv_add_ack(nccip, datahandle, doack ? skb->len : -1) < 0) - return 0; - - capi_cmsg2message(&sendcmsg, sendcmsg.buf); - msglen = CAPIMSG_LEN(sendcmsg.buf); - if (skb_headroom(skb) < msglen) { - struct sk_buff *nskb = skb_realloc_headroom(skb, msglen); - if (!nskb) { - printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n", - card->contrnr); - (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) { - dev_kfree_skb(skb); - nccip->datahandle++; - global.nsentdatapkt++; - return len; - } - (void)capidrv_del_ack(nccip, datahandle); - dev_kfree_skb(nskb); - return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; - } else { - memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen); - errcode = (*capifuncs->capi_put_message) (global.appid, skb); - if (errcode == CAPI_NOERROR) { - nccip->datahandle++; - global.nsentdatapkt++; - return len; - } - skb_pull(skb, msglen); - (void)capidrv_del_ack(nccip, datahandle); - return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; - } -} - -static int if_readstat(__u8 *buf, int len, int user, int id, int channel) -{ - capidrv_contr *card = findcontrbydriverid(id); - int count; - __u8 *p; - - if (!card) { - printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n", - card->contrnr, id); - return -ENODEV; - } - - for (p=buf, count=0; count < len; p++, count++) { - if (user) - put_user(*card->q931_read++, p); - else - *p = *card->q931_read++; - if (card->q931_read > card->q931_end) - card->q931_read = card->q931_buf; - } - return count; - -} - -static void enable_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 enabled\n", card->name); - capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid, - card->msgid++, - contr, - 0x214D5641, /* ManuID */ - 0, /* Class */ - 1, /* Function */ - (_cstruct)"\004\200\014\000\000"); - } else { - printk(KERN_INFO "%s: D3 trace enabled\n", card->name); - capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.appid, - card->msgid++, - contr, - 0x214D5641, /* ManuID */ - 0, /* Class */ - 1, /* Function */ - (_cstruct)"\004\002\003\000\000"); - } - send_message(card, &cmdcmsg); -} - -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); -} - -static void send_listen(capidrv_contr *card) -{ - capi_fill_LISTEN_REQ(&cmdcmsg, global.appid, - card->msgid++, - card->contrnr, /* controller */ - 1 << 6, /* Infomask */ - card->cipmask, - card->cipmask2, - 0, 0); - send_message(card, &cmdcmsg); - listen_change_state(card, EV_LISTEN_REQ); -} - -static void listentimerfunc(unsigned long x) -{ - capidrv_contr *card = (capidrv_contr *)x; - if (card->state != ST_LISTEN_NONE && card->state != ST_LISTEN_ACTIVE) - printk(KERN_ERR "%s: controller dead ??\n", card->name); - send_listen(card); - mod_timer(&card->listentimer, jiffies + 60*HZ); -} - - -static int capidrv_addcontr(__u16 contr, struct capi_profile *profp) -{ - capidrv_contr *card; - long flags; - isdn_ctrl cmd; - char id[20]; - int i; - - MOD_INC_USE_COUNT; - - sprintf(id, "capidrv-%d", contr); - if (!(card = (capidrv_contr *) kmalloc(sizeof(capidrv_contr), GFP_ATOMIC))) { - printk(KERN_WARNING - "capidrv: (%s) Could not allocate contr-struct.\n", id); - MOD_DEC_USE_COUNT; - return -1; - } - memset(card, 0, sizeof(capidrv_contr)); - init_timer(&card->listentimer); - strcpy(card->name, id); - card->contrnr = contr; - card->nbchan = profp->nbchannel; - card->bchans = (capidrv_bchan *) kmalloc(sizeof(capidrv_bchan) * card->nbchan, GFP_ATOMIC); - if (!card->bchans) { - printk(KERN_WARNING - "capidrv: (%s) Could not allocate bchan-structs.\n", id); - kfree(card); - MOD_DEC_USE_COUNT; - return -1; - } - card->interface.channels = profp->nbchannel; - card->interface.maxbufsize = 2048; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = 0; - card->interface.readstat = if_readstat; - card->interface.features = ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_X75UI | - ISDN_FEATURE_L2_X75BUI | - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L2_TRANS | - ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_L2_V11096 | - ISDN_FEATURE_L2_V11019 | - ISDN_FEATURE_L2_V11038 | -#if 0 - ISDN_FEATURE_L2_FAX | - ISDN_FEATURE_L3_FAX | -#endif - ISDN_FEATURE_P_UNKNOWN; - card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */ - strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); - - - card->q931_read = card->q931_buf; - card->q931_write = card->q931_buf; - card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1; - - if (!register_isdn(&card->interface)) { - printk(KERN_ERR "capidrv: Unable to register contr %s\n", id); - kfree(card->bchans); - kfree(card); - MOD_DEC_USE_COUNT; - return -1; - } - card->myid = card->interface.channels; - - save_flags(flags); - cli(); - card->next = global.contr_list; - global.contr_list = card; - global.ncontr++; - restore_flags(flags); - - memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan); - for (i = 0; i < card->nbchan; i++) { - card->bchans[i].contr = card; - } - - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - - card->cipmask = 0x1FFF03FF; /* any */ - card->cipmask2 = 0; - - send_listen(card); - - card->listentimer.data = (unsigned long)card; - card->listentimer.function = listentimerfunc; - mod_timer(&card->listentimer, jiffies + 60*HZ); - - printk(KERN_INFO "%s: now up (%d B channels)\n", - card->name, card->nbchan); - - enable_dchannel_trace(card); - - return 0; -} - -static int capidrv_delcontr(__u16 contr) -{ - capidrv_contr **pp, *card; - isdn_ctrl cmd; - long flags; - int i; - - save_flags(flags); - cli(); - for (pp = &global.contr_list; *pp; pp = &(*pp)->next) { - if ((*pp)->contrnr == contr) - break; - } - if (!*pp) { - restore_flags(flags); - printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr); - return -1; - } - card = *pp; - *pp = (*pp)->next; - global.ncontr--; - restore_flags(flags); - - if (debugmode) - printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n", - card->contrnr, card->myid); - - cmd.command = ISDN_STAT_STOP; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - - for (i = 0; i < card->nbchan; i++) { - - cmd.command = ISDN_STAT_DISCH; - cmd.driver = card->myid; - cmd.arg = i; - cmd.parm.num[0] = 0; - card->interface.statcallb(&cmd); - - if (card->bchans[i].nccip) - free_ncci(card, card->bchans[i].nccip); - if (card->bchans[i].plcip) - free_plci(card, card->bchans[i].plcip); - if (card->plci_list) - printk(KERN_ERR "capidrv: bug in free_plci()\n"); - } - kfree(card->bchans); - del_timer(&card->listentimer); - - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - - kfree(card); - - printk(KERN_INFO "%s: now down.\n", card->name); - - MOD_DEC_USE_COUNT; - - return 0; -} - - -static void lower_callback(unsigned int cmd, __u32 contr, void *data) -{ - - switch (cmd) { - case KCI_CONTRUP: - printk(KERN_INFO "capidrv: controller %hu up\n", contr); - (void) capidrv_addcontr(contr, (capi_profile *) data); - break; - case KCI_CONTRDOWN: - printk(KERN_INFO "capidrv: controller %hu down\n", contr); - (void) capidrv_delcontr(contr); - break; - } -} - -/* - * /proc/capi/capidrv: - * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt - */ -static int proc_capidrv_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - int len = 0; - - len += sprintf(page+len, "%lu %lu %lu %lu\n", - global.nrecvctlpkt, - global.nrecvdatapkt, - global.nsentctlpkt, - global.nsentdatapkt); - if (off+count >= len) - *eof = 1; - if (len < off) - return 0; - *start = page + off; - return ((count < len-off) ? count : len-off); -} - -static struct procfsentries { - char *name; - mode_t mode; - int (*read_proc)(char *page, char **start, off_t off, - int count, int *eof, void *data); - struct proc_dir_entry *procent; -} procfsentries[] = { - /* { "capi", S_IFDIR, 0 }, */ - { "capi/capidrv", 0 , proc_capidrv_read_proc }, -}; - -static void proc_init(void) -{ - int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); - int i; - - for (i=0; i < nelem; i++) { - struct procfsentries *p = procfsentries + i; - p->procent = create_proc_entry(p->name, p->mode, 0); - if (p->procent) p->procent->read_proc = p->read_proc; - } -} - -static void proc_exit(void) -{ - int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); - int i; - - for (i=nelem-1; i >= 0; i--) { - struct procfsentries *p = procfsentries + i; - if (p->procent) { - remove_proc_entry(p->name, 0); - p->procent = 0; - } - } -} - -static struct capi_interface_user cuser = { - "capidrv", - lower_callback -}; - -#ifdef MODULE -#define capidrv_init init_module -#endif - -int capidrv_init(void) -{ - struct capi_register_params rparam; - capi_profile profile; - char rev[10]; - char *p; - __u32 ncontr, contr; - __u16 errcode; - - MOD_INC_USE_COUNT; - - capifuncs = attach_capi_interface(&cuser); - - if (!capifuncs) { - MOD_DEC_USE_COUNT; - return -EIO; - } - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, " ??? "); - - rparam.level3cnt = -2; /* number of bchannels twice */ - rparam.datablkcnt = 16; - rparam.datablklen = 2048; - errcode = (*capifuncs->capi_register) (&rparam, &global.appid); - if (errcode) { - detach_capi_interface(&cuser); - MOD_DEC_USE_COUNT; - return -EIO; - } - - errcode = (*capifuncs->capi_get_profile) (0, &profile); - if (errcode != CAPI_NOERROR) { - (void) (*capifuncs->capi_release) (global.appid); - detach_capi_interface(&cuser); - MOD_DEC_USE_COUNT; - return -EIO; - } - - (void) (*capifuncs->capi_set_signal) (global.appid, capidrv_signal, 0); - - ncontr = profile.ncontroller; - for (contr = 1; contr <= ncontr; contr++) { - errcode = (*capifuncs->capi_get_profile) (contr, &profile); - if (errcode != CAPI_NOERROR) - continue; - (void) capidrv_addcontr(contr, &profile); - } - proc_init(); - - printk(KERN_NOTICE "capidrv: Rev%s: loaded\n", rev); - MOD_DEC_USE_COUNT; - - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - capidrv_contr *card, *next; - long flags; - char rev[10]; - char *p; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else { - strcpy(rev, " ??? "); - } - - for (card = global.contr_list; card; card = next) { - next = card->next; - disable_dchannel_trace(card); - } - - save_flags(flags); - cli(); - for (card = global.contr_list; card; card = next) { - next = card->next; - capidrv_delcontr(card->contrnr); - } - restore_flags(flags); - - (void) (*capifuncs->capi_release) (global.appid); - detach_capi_interface(&cuser); - proc_exit(); - - printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev); -} - -#endif diff --git a/drivers/isdn/avmb1/capidrv.h b/drivers/isdn/avmb1/capidrv.h deleted file mode 100644 index 1ee0539a..00000000 --- a/drivers/isdn/avmb1/capidrv.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * $Id$ - * - * ISDN4Linux Driver, using capi20 interface (kernelcapi) - * - * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.1.2.1 1998/03/20 14:38:28 calle - * capidrv: prepared state machines for suspend/resume/hold - * capidrv: fix bug in state machine if B1/T1 is out of nccis - * b1capi: changed some errno returns. - * b1capi: detect if you try to add same T1 to different io address. - * b1capi: change number of nccis depending on number of channels. - * b1lli: cosmetics - * - * Revision 1.1 1997/03/04 21:50:33 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - */ -#ifndef __CAPIDRV_H__ -#define __CAPIDRV_H__ - -/* - * LISTEN state machine - */ -#define ST_LISTEN_NONE 0 /* L-0 */ -#define ST_LISTEN_WAIT_CONF 1 /* L-0.1 */ -#define ST_LISTEN_ACTIVE 2 /* L-1 */ -#define ST_LISTEN_ACTIVE_WAIT_CONF 3 /* L-1.1 */ - - -#define EV_LISTEN_REQ 1 /* L-0 -> L-0.1 - L-1 -> L-1.1 */ -#define EV_LISTEN_CONF_ERROR 2 /* L-0.1 -> L-0 - L-1.1 -> L-1 */ -#define EV_LISTEN_CONF_EMPTY 3 /* L-0.1 -> L-0 - L-1.1 -> L-0 */ -#define EV_LISTEN_CONF_OK 4 /* L-0.1 -> L-1 - L-1.1 -> L.1 */ - -/* - * per plci state machine - */ -#define ST_PLCI_NONE 0 /* P-0 */ -#define ST_PLCI_OUTGOING 1 /* P-0.1 */ -#define ST_PLCI_ALLOCATED 2 /* P-1 */ -#define ST_PLCI_ACTIVE 3 /* P-ACT */ -#define ST_PLCI_INCOMING 4 /* P-2 */ -#define ST_PLCI_FACILITY_IND 5 /* P-3 */ -#define ST_PLCI_ACCEPTING 6 /* P-4 */ -#define ST_PLCI_DISCONNECTING 7 /* P-5 */ -#define ST_PLCI_DISCONNECTED 8 /* P-6 */ -#define ST_PLCI_RESUMEING 9 /* P-0.Res */ -#define ST_PLCI_RESUME 10 /* P-Res */ -#define ST_PLCI_HELD 11 /* P-HELD */ - -#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1 - */ -#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0 - */ -#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1 - */ -#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1 - */ -#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2 - */ -#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT - */ -#define EV_PLCI_CONNECT_REJECT 7 /* P-2 -> P-5 - P-3 -> P-5 - */ -#define EV_PLCI_DISCONNECT_REQ 8 /* P-1 -> P-5 - P-2 -> P-5 - P-3 -> P-5 - P-4 -> P-5 - P-ACT -> P-5 - P-Res -> P-5 (*) - P-HELD -> P-5 (*) - */ -#define EV_PLCI_DISCONNECT_IND 9 /* P-1 -> P-6 - P-2 -> P-6 - P-3 -> P-6 - P-4 -> P-6 - P-5 -> P-6 - P-ACT -> P-6 - P-Res -> P-6 (*) - P-HELD -> P-6 (*) - */ -#define EV_PLCI_FACILITY_IND_DOWN 10 /* P-0.1 -> P-5 - P-1 -> P-5 - P-ACT -> P-5 - P-2 -> P-5 - P-3 -> P-5 - P-4 -> P-5 - */ -#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0 - */ -#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0 - */ - -#define EV_PLCI_RESUME_REQ 13 /* P-0 -> P-0.Res - */ -#define EV_PLCI_RESUME_CONF_OK 14 /* P-0.Res -> P-Res - */ -#define EV_PLCI_RESUME_CONF_ERROR 15 /* P-0.Res -> P-0 - */ -#define EV_PLCI_RESUME_IND 16 /* P-Res -> P-ACT - */ -#define EV_PLCI_HOLD_IND 17 /* P-ACT -> P-HELD - */ -#define EV_PLCI_RETRIEVE_IND 18 /* P-HELD -> P-ACT - */ -#define EV_PLCI_SUSPEND_IND 19 /* P-ACT -> P-5 - */ -#define EV_PLCI_CD_IND 20 /* P-2 -> P-5 - */ - -/* - * per ncci state machine - */ -#define ST_NCCI_PREVIOUS -1 -#define ST_NCCI_NONE 0 /* N-0 */ -#define ST_NCCI_OUTGOING 1 /* N-0.1 */ -#define ST_NCCI_INCOMING 2 /* N-1 */ -#define ST_NCCI_ALLOCATED 3 /* N-2 */ -#define ST_NCCI_ACTIVE 4 /* N-ACT */ -#define ST_NCCI_RESETING 5 /* N-3 */ -#define ST_NCCI_DISCONNECTING 6 /* N-4 */ -#define ST_NCCI_DISCONNECTED 7 /* N-5 */ - -#define EV_NCCI_CONNECT_B3_REQ 1 /* N-0 -> N-0.1 */ -#define EV_NCCI_CONNECT_B3_IND 2 /* N-0 -> N.1 */ -#define EV_NCCI_CONNECT_B3_CONF_OK 3 /* N-0.1 -> N.2 */ -#define EV_NCCI_CONNECT_B3_CONF_ERROR 4 /* N-0.1 -> N.0 */ -#define EV_NCCI_CONNECT_B3_REJECT 5 /* N-1 -> N-4 */ -#define EV_NCCI_CONNECT_B3_RESP 6 /* N-1 -> N-2 */ -#define EV_NCCI_CONNECT_B3_ACTIVE_IND 7 /* N-2 -> N-ACT */ -#define EV_NCCI_RESET_B3_REQ 8 /* N-ACT -> N-3 */ -#define EV_NCCI_RESET_B3_IND 9 /* N-3 -> N-ACT */ -#define EV_NCCI_DISCONNECT_B3_IND 10 /* N-4 -> N.5 */ -#define EV_NCCI_DISCONNECT_B3_CONF_ERROR 11 /* N-4 -> previous */ -#define EV_NCCI_DISCONNECT_B3_REQ 12 /* N-1 -> N-4 - N-2 -> N-4 - N-3 -> N-4 - N-ACT -> N-4 */ -#define EV_NCCI_DISCONNECT_B3_RESP 13 /* N-5 -> N-0 */ - -#endif /* __CAPIDRV_H__ */ diff --git a/drivers/isdn/avmb1/capifs.c b/drivers/isdn/avmb1/capifs.c deleted file mode 100644 index 07a81005..00000000 --- a/drivers/isdn/avmb1/capifs.c +++ /dev/null @@ -1,603 +0,0 @@ -/* - * $Id$ - * - * (c) Copyright 2000 by Carsten Paeth (calle@calle.de) - * - * Heavily based on devpts filesystem from H. Peter Anvin - * - * $Log$ - * Revision 1.4 2000/03/08 17:06:33 calle - * - changes for devfs and 2.3.49 - * - capifs now configurable (no need with devfs) - * - New Middleware ioctl CAPI_NCCI_GETUNIT - * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) - * - * Revision 1.3 2000/03/06 18:00:23 calle - * - Middleware extention now working with 2.3.49 (capifs). - * - Fixed typos in debug section of capi.c - * - Bugfix: Makefile corrected for b1pcmcia.c - * - * Revision 1.2 2000/03/06 09:17:07 calle - * - capifs: fileoperations now in inode (change for 2.3.49) - * - Config.in: Middleware extention not a tristate, uups. - * - * Revision 1.1 2000/03/03 16:48:38 calle - * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) - * It is now possible to create a connection with a CAPI2.0 applikation - * and than to handle the data connection from /dev/capi/ (capifs) and also - * using async or sync PPP on this connection. - * The two major device number 190 and 191 are not confirmed yet, - * but I want to save the code in cvs, before I go on. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Carsten Paeth "); - -static char *revision = "$Revision$"; - -struct capifs_ncci { - struct inode *inode; - char used; - char type; - unsigned int num; - kdev_t kdev; -}; - -struct capifs_sb_info { - u32 magic; - struct super_block *next; - struct super_block **back; - int setuid; - int setgid; - uid_t uid; - gid_t gid; - umode_t mode; - - unsigned int max_ncci; - struct capifs_ncci *nccis; -}; - -#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') -#define CAPIFS_SBI_MAGIC (('C'<<24)|('A'<<16)|('P'<<8)|'I') - -static inline struct capifs_sb_info *SBI(struct super_block *sb) -{ - return (struct capifs_sb_info *)(sb->u.generic_sbp); -} - -/* ------------------------------------------------------------------ */ - -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); - -static struct file_operations capifs_root_operations = { -#ifdef COMPAT_has_generic_read_dir - read: generic_read_dir, -#endif - readdir: capifs_root_readdir, -}; - -struct inode_operations capifs_root_inode_operations = { -#ifndef COMPAT_has_fileops_in_inode - &capifs_root_operations, /* file operations */ -#endif - lookup: capifs_root_lookup, -}; - -struct inode_operations capifs_inode_operations; - -static struct dentry_operations capifs_dentry_operations = { - capifs_revalidate, /* d_revalidate */ - NULL, /* d_hash */ - NULL, /* d_compare */ -}; - -/* - * /dev/capi/%d - * /dev/capi/r%d - */ - -static int capifs_root_readdir(struct file *filp, void *dirent, filldir_t filldir) -{ - struct inode * inode = filp->f_dentry->d_inode; - struct capifs_sb_info * sbi = SBI(filp->f_dentry->d_inode->i_sb); - off_t nr; - char numbuf[32]; - - nr = filp->f_pos; - - switch(nr) - { - case 0: - if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0) - return 0; - filp->f_pos = ++nr; - /* fall through */ - case 1: - if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0) - return 0; - filp->f_pos = ++nr; - /* fall through */ - default: - while (nr < sbi->max_ncci) { - int n = nr - 2; - struct capifs_ncci *np = &sbi->nccis[n]; - if (np->inode && np->used) { - char *p = numbuf; - if (np->type) *p++ = np->type; - sprintf(p, "%u", np->num); - if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 ) - return 0; - } - filp->f_pos = ++nr; - } - break; - } - - return 0; -} - -/* - * Revalidate is called on every cache lookup. We use it to check that - * the ncci really does still exist. Never revalidate negative dentries; - * for simplicity (fix later?) - */ -static int capifs_revalidate(struct dentry * dentry, int flags) -{ - struct capifs_sb_info *sbi; - - if ( !dentry->d_inode ) - return 0; - - sbi = SBI(dentry->d_inode->i_sb); - - return ( sbi->nccis[dentry->d_inode->i_ino - 2].inode == dentry->d_inode ); -} - -static struct dentry *capifs_root_lookup(struct inode * dir, struct dentry * dentry) -{ - struct capifs_sb_info *sbi = SBI(dir->i_sb); - struct capifs_ncci *np; - unsigned int i; - char numbuf[32]; - char *p, *tmp; - unsigned int num; - char type = 0; - - dentry->d_inode = NULL; /* Assume failure */ - dentry->d_op = &capifs_dentry_operations; - - if (dentry->d_name.len >= sizeof(numbuf) ) - return NULL; - strncpy(numbuf, dentry->d_name.name, dentry->d_name.len); - numbuf[dentry->d_name.len] = 0; - p = numbuf; - if (!isdigit(*p)) type = *p++; - tmp = p; - num = (unsigned int)simple_strtoul(p, &tmp, 10); - if (tmp == p || *tmp) - return NULL; - - for (i = 0, np = sbi->nccis ; i < sbi->max_ncci; i++, np++) { - if (np->used && np->num == num && np->type == type) - break; - } - - if ( i >= sbi->max_ncci ) - return NULL; - - dentry->d_inode = np->inode; - if ( dentry->d_inode ) - dentry->d_inode->i_count++; - - d_add(dentry, dentry->d_inode); - - return NULL; -} - -/* ------------------------------------------------------------------ */ - -static struct super_block *mounts = NULL; - -static void capifs_put_super(struct super_block *sb) -{ - struct capifs_sb_info *sbi = SBI(sb); - struct inode *inode; - int i; - - for ( i = 0 ; i < sbi->max_ncci ; i++ ) { - if ( (inode = sbi->nccis[i].inode) ) { - if ( inode->i_count != 1 ) - printk("capifs_put_super: badness: entry %d count %d\n", - i, inode->i_count); - inode->i_nlink--; - iput(inode); - } - } - - *sbi->back = sbi->next; - if ( sbi->next ) - SBI(sbi->next)->back = sbi->back; - - kfree(sbi->nccis); - kfree(sbi); - - MOD_DEC_USE_COUNT; -} - -static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz); -static void capifs_read_inode(struct inode *inode); -static void capifs_write_inode(struct inode *inode); - -static struct super_operations capifs_sops = { - read_inode: capifs_read_inode, - write_inode: capifs_write_inode, - put_super: capifs_put_super, - statfs: capifs_statfs, -}; - -static int capifs_parse_options(char *options, struct capifs_sb_info *sbi) -{ - int setuid = 0; - int setgid = 0; - uid_t uid = 0; - gid_t gid = 0; - umode_t mode = 0600; - unsigned int maxncci = 512; - char *this_char, *value; - - this_char = NULL; - if ( options ) - this_char = strtok(options,","); - for ( ; this_char; this_char = strtok(NULL,",")) { - if ((value = strchr(this_char,'=')) != NULL) - *value++ = 0; - if (!strcmp(this_char,"uid")) { - if (!value || !*value) - return 1; - uid = simple_strtoul(value,&value,0); - if (*value) - return 1; - setuid = 1; - } - else if (!strcmp(this_char,"gid")) { - if (!value || !*value) - return 1; - gid = simple_strtoul(value,&value,0); - if (*value) - return 1; - setgid = 1; - } - else if (!strcmp(this_char,"mode")) { - if (!value || !*value) - return 1; - mode = simple_strtoul(value,&value,8); - if (*value) - return 1; - } - else if (!strcmp(this_char,"maxncci")) { - if (!value || !*value) - return 1; - maxncci = simple_strtoul(value,&value,8); - if (*value) - return 1; - } - else - return 1; - } - sbi->setuid = setuid; - sbi->setgid = setgid; - sbi->uid = uid; - sbi->gid = gid; - sbi->mode = mode & ~S_IFMT; - sbi->max_ncci = maxncci; - - return 0; -} - -struct super_block *capifs_read_super(struct super_block *s, void *data, - int silent) -{ - struct inode * root_inode; - struct dentry * root; - struct capifs_sb_info *sbi; - - MOD_INC_USE_COUNT; - - lock_super(s); - /* Super block already completed? */ - if (s->s_root) { - unlock_super(s); - goto out; - } - - sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL); - if ( !sbi ) { - unlock_super(s); - goto fail; - } - - memset(sbi, 0, sizeof(struct capifs_sb_info)); - sbi->magic = CAPIFS_SBI_MAGIC; - - /* Can this call block? (It shouldn't) */ - if ( capifs_parse_options(data,sbi) ) { - kfree(sbi); - unlock_super(s); - printk("capifs: called with bogus options\n"); - goto fail; - } - - sbi->nccis = kmalloc(sizeof(struct capifs_ncci) * sbi->max_ncci, GFP_KERNEL); - if ( !sbi->nccis ) { - kfree(sbi); - unlock_super(s); - goto fail; - } - memset(sbi->nccis, 0, sizeof(struct capifs_ncci) * sbi->max_ncci); - - s->u.generic_sbp = (void *) sbi; - s->s_blocksize = 1024; - s->s_blocksize_bits = 10; - s->s_magic = CAPIFS_SUPER_MAGIC; - s->s_op = &capifs_sops; - s->s_root = NULL; - unlock_super(s); /* shouldn't we keep it locked a while longer? */ - - /* - * Get the root inode and dentry, but defer checking for errors. - */ - root_inode = iget(s, 1); /* inode 1 == root directory */ -#ifdef COMPAT_d_alloc_root_one_parameter - root = d_alloc_root(root_inode); -#else - root = d_alloc_root(root_inode, NULL); -#endif - - /* - * Check whether somebody else completed the super block. - */ - if (s->s_root) { - if (root) dput(root); - else iput(root_inode); - goto out; - } - - if (!root) { - printk("capifs: get root dentry failed\n"); - /* - * iput() can block, so we clear the super block first. - */ - s->s_dev = 0; - iput(root_inode); - kfree(sbi->nccis); - kfree(sbi); - goto fail; - } - - /* - * Check whether somebody else completed the super block. - */ - if (s->s_root) - goto out; - - /* - * Success! Install the root dentry now to indicate completion. - */ - lock_super(s); - s->s_root = root; - - sbi->next = mounts; - if ( sbi->next ) - SBI(sbi->next)->back = &(sbi->next); - sbi->back = &mounts; - mounts = s; - - unlock_super(s); - return s; - - /* - * Success ... somebody else completed the super block for us. - */ -out: - MOD_DEC_USE_COUNT; - return s; -fail: - s->s_dev = 0; - MOD_DEC_USE_COUNT; - return NULL; -} - -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; -} - -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_op = NULL; - inode->i_mode = 0; - inode->i_nlink = 0; - inode->i_size = 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; -#ifdef COMPAT_has_fileops_in_inode - inode->i_fop = &capifs_root_operations; -#endif - inode->i_nlink = 2; - return; - } - -#ifdef COMPAT_has_fileops_in_inode - /* need dummy inode operations .... */ - inode->i_op = &capifs_inode_operations; -#endif - - ino -= 2; - if ( ino >= sbi->max_ncci ) - return; /* Bogus */ - -#ifdef COMPAT_HAS_init_special_inode - init_special_inode(inode, S_IFCHR, 0); -#else - inode->i_mode = S_IFCHR; - inode->i_op = &chrdev_inode_operations; -#endif - - return; -} - -static void capifs_write_inode(struct inode *inode) -{ -} - -static struct file_system_type capifs_fs_type = { - "capifs", - 0, - capifs_read_super, - NULL -}; - -void capifs_new_ncci(char type, unsigned int num, kdev_t device) -{ - struct super_block *sb; - struct capifs_sb_info *sbi; - struct capifs_ncci *np; - ino_t ino; - - for ( sb = mounts ; sb ; sb = sbi->next ) { - sbi = SBI(sb); - - for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) { - if (np->used == 0) { - np->used = 1; - np->type = type; - np->num = num; - np->kdev = device; - break; - } - } - - if ((np->inode = iget(sb, ino+2)) != 0) { - struct inode *inode = np->inode; - inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid; - inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid; - inode->i_mode = sbi->mode | S_IFCHR; - inode->i_rdev = np->kdev; - inode->i_nlink++; - } - } -} - -void capifs_free_ncci(char type, unsigned int num) -{ - struct super_block *sb; - struct capifs_sb_info *sbi; - struct inode *inode; - struct capifs_ncci *np; - ino_t ino; - - for ( sb = mounts ; sb ; sb = sbi->next ) { - sbi = SBI(sb); - - for (ino = 0, np = sbi->nccis ; ino < sbi->max_ncci; ino++, np++) { - if (!np->used || np->type != type || np->num != num) - continue; - if (np->inode) { - inode = np->inode; - np->used = 0; - inode->i_nlink--; - iput(inode); - break; - } - } - } -} - -int __init capifs_init(void) -{ - char rev[10]; - char *p; - int err; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, "1.0"); - - err = register_filesystem(&capifs_fs_type); - if (err) - return err; -#ifdef MODULE - printk(KERN_NOTICE "capifs: Rev%s: loaded\n", rev); -#else - printk(KERN_NOTICE "capifs: Rev%s: started\n", rev); -#endif - return 0; -} - -void capifs_exit(void) -{ - unregister_filesystem(&capifs_fs_type); -} - -EXPORT_SYMBOL(capifs_new_ncci); -EXPORT_SYMBOL(capifs_free_ncci); - -#ifdef MODULE - -int init_module(void) -{ - return capifs_init(); -} - -void cleanup_module(void) -{ - capifs_exit(); -} - -#endif diff --git a/drivers/isdn/avmb1/capifs.h b/drivers/isdn/avmb1/capifs.h deleted file mode 100644 index 0e8dd780..00000000 --- a/drivers/isdn/avmb1/capifs.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * $Id$ - * - * (c) Copyright 2000 by Carsten Paeth (calle@calle.de) - * - * $Log$ - * Revision 1.2 2000/03/08 17:06:33 calle - * - changes for devfs and 2.3.49 - * - capifs now configurable (no need with devfs) - * - New Middleware ioctl CAPI_NCCI_GETUNIT - * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) - * - * Revision 1.1 2000/03/03 16:48:38 calle - * - Added CAPI2.0 Middleware support (CONFIG_ISDN_CAPI) - * It is now possible to create a connection with a CAPI2.0 applikation - * and than to handle the data connection from /dev/capi/ (capifs) and also - * using async or sync PPP on this connection. - * The two major device number 190 and 191 are not confirmed yet, - * but I want to save the code in cvs, before I go on. - * - * - */ - -void capifs_new_ncci(char type, unsigned int num, kdev_t device); -void capifs_free_ncci(char type, unsigned int num); diff --git a/drivers/isdn/avmb1/capilli.h b/drivers/isdn/avmb1/capilli.h deleted file mode 100644 index 9765b1ef..00000000 --- a/drivers/isdn/avmb1/capilli.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * $Id$ - * - * Kernel CAPI 2.0 Driver Interface for Linux - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - */ -#ifndef __CAPILLI_H__ -#define __CAPILLI_H__ - -typedef struct capiloaddatapart { - int user; /* data in userspace ? */ - int len; - unsigned char *data; -} capiloaddatapart; - -typedef struct capiloaddata { - capiloaddatapart firmware; - capiloaddatapart configuration; -} capiloaddata; - -typedef struct capicardparams { - unsigned int port; - unsigned irq; - int cardtype; - int cardnr; - unsigned int membase; -} capicardparams; - -struct capi_driver; - -struct capi_ctr { - struct capi_ctr *next; /* next ctr of same driver */ - struct capi_driver *driver; - int cnr; /* controller number */ - char name[32]; /* name of controller */ - volatile unsigned short cardstate; /* controller state */ - volatile int blocked; /* output blocked */ - int traceflag; /* capi trace */ - - void *driverdata; /* driver specific */ - - /* filled before calling ready callback */ - __u8 manu[CAPI_MANUFACTURER_LEN]; /* CAPI_GET_MANUFACTURER */ - capi_version version; /* CAPI_GET_VERSION */ - capi_profile profile; /* CAPI_GET_PROFILE */ - __u8 serial[CAPI_SERIAL_LEN]; /* CAPI_GET_SERIAL */ - - /* functions */ - void (*ready)(struct capi_ctr * card); - void (*reseted)(struct capi_ctr * card); - void (*suspend_output)(struct capi_ctr * card); - void (*resume_output)(struct capi_ctr * card); - void (*handle_capimsg)(struct capi_ctr * card, - __u16 appl, struct sk_buff *skb); - void (*appl_registered)(struct capi_ctr * card, __u16 appl); - void (*appl_released)(struct capi_ctr * card, __u16 appl); - - void (*new_ncci)(struct capi_ctr * card, - __u16 appl, __u32 ncci, __u32 winsize); - void (*free_ncci)(struct capi_ctr * card, __u16 appl, __u32 ncci); - - /* management information for kcapi */ - - unsigned long nrecvctlpkt; - unsigned long nrecvdatapkt; - unsigned long nsentctlpkt; - unsigned long nsentdatapkt; - - struct proc_dir_entry *procent; - char procfn[128]; -}; - -struct capi_driver_interface { - struct capi_ctr *(*attach_ctr)(struct capi_driver *driver, char *name, void *data); - int (*detach_ctr)(struct capi_ctr *); -}; - -struct capi_driver { - char name[32]; /* driver name */ - char revision[32]; - int (*load_firmware)(struct capi_ctr *, capiloaddata *); - void (*reset_ctr)(struct capi_ctr *); - void (*remove_ctr)(struct capi_ctr *); - void (*register_appl)(struct capi_ctr *, __u16 appl, - capi_register_params *); - void (*release_appl)(struct capi_ctr *, __u16 appl); - void (*send_message)(struct capi_ctr *, struct sk_buff *skb); - - char *(*procinfo)(struct capi_ctr *); - int (*ctr_read_proc)(char *page, char **start, off_t off, - int count, int *eof, struct capi_ctr *card); - int (*driver_read_proc)(char *page, char **start, off_t off, - int count, int *eof, struct capi_driver *driver); - - int (*add_card)(struct capi_driver *driver, capicardparams *data); - - /* intitialized by kcapi */ - struct capi_ctr *controller; /* list of controllers */ - struct capi_driver *next; - int ncontroller; - struct proc_dir_entry *procent; - char procfn[128]; -}; - -struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver); -void detach_capi_driver(struct capi_driver *driver); - -#endif /* __CAPILLI_H__ */ diff --git a/drivers/isdn/avmb1/capiutil.c b/drivers/isdn/avmb1/capiutil.c deleted file mode 100644 index ee15aae2..00000000 --- a/drivers/isdn/avmb1/capiutil.c +++ /dev/null @@ -1,1002 +0,0 @@ -/* - * $Id$ - * - * CAPI 2.0 convert capi message to capi message struct - * - * From CAPI 2.0 Development Kit AVM 1995 (msg.c) - * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.11 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.10 1999/08/31 11:19:54 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.9 1999/07/09 15:05:46 keil - * compat.h is now isdn_compat.h - * - * Revision 1.8 1999/07/01 15:26:37 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * Revision 1.7 1999/07/01 08:23:01 keil - * compatibility macros now in - * - * Revision 1.6 1997/11/04 06:12:12 calle - * capi.c: new read/write in file_ops since 2.1.60 - * capidrv.c: prepared isdnlog interface for d2-trace in newer firmware. - * capiutil.c: needs config.h (CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON) - * compat.h: added #define LinuxVersionCode - * - * Revision 1.5 1997/10/01 09:21:19 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.4 1997/08/10 07:43:55 calle - * forgot to export symbol capi_info2str for 2.1.x - * - * Revision 1.3 1997/05/18 09:24:18 calle - * added verbose disconnect reason reporting to avmb1. - * some fixes in capi20 interface. - * changed info messages for B1-PCI - * - * Revision 1.2 1997/03/05 21:22:13 fritz - * Fix: Symbols have to be exported unconditionally. - * - * Revision 1.1 1997/03/04 21:50:34 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "capiutil.h" - -/* from CAPI2.0 DDK AVM Berlin GmbH */ - -#ifndef CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON -char *capi_info2str(__u16 reason) -{ - return ".."; -} -#else -char *capi_info2str(__u16 reason) -{ - switch (reason) { - -/*-- informative values (corresponding message was processed) -----*/ - case 0x0001: - return "NCPI not supported by current protocol, NCPI ignored"; - case 0x0002: - return "Flags not supported by current protocol, flags ignored"; - case 0x0003: - return "Alert already sent by another application"; - -/*-- error information concerning CAPI_REGISTER -----*/ - case 0x1001: - return "Too many applications"; - case 0x1002: - return "Logical block size too small, must be at least 128 Bytes"; - case 0x1003: - return "Buffer exceeds 64 kByte"; - case 0x1004: - return "Message buffer size too small, must be at least 1024 Bytes"; - case 0x1005: - return "Max. number of logical connections not supported"; - case 0x1006: - return "Reserved"; - case 0x1007: - return "The message could not be accepted because of an internal busy condition"; - case 0x1008: - return "OS resource error (no memory ?)"; - case 0x1009: - return "CAPI not installed"; - case 0x100A: - return "Controller does not support external equipment"; - case 0x100B: - return "Controller does only support external equipment"; - -/*-- error information concerning message exchange functions -----*/ - case 0x1101: - return "Illegal application number"; - case 0x1102: - return "Illegal command or subcommand or message length less than 12 bytes"; - case 0x1103: - return "The message could not be accepted because of a queue full condition !! The error code does not imply that CAPI cannot receive messages directed to another controller, PLCI or NCCI"; - case 0x1104: - return "Queue is empty"; - case 0x1105: - return "Queue overflow, a message was lost !! This indicates a configuration error. The only recovery from this error is to perform a CAPI_RELEASE"; - case 0x1106: - return "Unknown notification parameter"; - case 0x1107: - return "The Message could not be accepted because of an internal busy condition"; - case 0x1108: - return "OS Resource error (no memory ?)"; - case 0x1109: - return "CAPI not installed"; - case 0x110A: - return "Controller does not support external equipment"; - case 0x110B: - return "Controller does only support external equipment"; - -/*-- error information concerning resource / coding problems -----*/ - case 0x2001: - return "Message not supported in current state"; - case 0x2002: - return "Illegal Controller / PLCI / NCCI"; - case 0x2003: - return "Out of PLCI"; - case 0x2004: - return "Out of NCCI"; - case 0x2005: - return "Out of LISTEN"; - case 0x2006: - return "Out of FAX resources (protocol T.30)"; - case 0x2007: - return "Illegal message parameter coding"; - -/*-- error information concerning requested services -----*/ - case 0x3001: - return "B1 protocol not supported"; - case 0x3002: - return "B2 protocol not supported"; - case 0x3003: - return "B3 protocol not supported"; - case 0x3004: - return "B1 protocol parameter not supported"; - case 0x3005: - return "B2 protocol parameter not supported"; - case 0x3006: - return "B3 protocol parameter not supported"; - case 0x3007: - return "B protocol combination not supported"; - case 0x3008: - return "NCPI not supported"; - case 0x3009: - return "CIP Value unknown"; - case 0x300A: - return "Flags not supported (reserved bits)"; - case 0x300B: - return "Facility not supported"; - case 0x300C: - return "Data length not supported by current protocol"; - case 0x300D: - return "Reset procedure not supported by current protocol"; - -/*-- informations about the clearing of a physical connection -----*/ - case 0x3301: - return "Protocol error layer 1 (broken line or B-channel removed by signalling protocol)"; - case 0x3302: - return "Protocol error layer 2"; - case 0x3303: - return "Protocol error layer 3"; - case 0x3304: - return "Another application got that call"; -/*-- T.30 specific reasons -----*/ - case 0x3311: - return "Connecting not successful (remote station is no FAX G3 machine)"; - case 0x3312: - return "Connecting not successful (training error)"; - case 0x3313: - return "Disconnected before transfer (remote station does not support transfer mode, e.g. resolution)"; - case 0x3314: - return "Disconnected during transfer (remote abort)"; - case 0x3315: - return "Disconnected during transfer (remote procedure error, e.g. unsuccessful repetition of T.30 commands)"; - case 0x3316: - return "Disconnected during transfer (local tx data underrun)"; - case 0x3317: - return "Disconnected during transfer (local rx data overflow)"; - case 0x3318: - return "Disconnected during transfer (local abort)"; - case 0x3319: - return "Illegal parameter coding (e.g. SFF coding error)"; - -/*-- disconnect causes from the network according to ETS 300 102-1/Q.931 -----*/ - case 0x3481: return "Unallocated (unassigned) number"; - case 0x3482: return "No route to specified transit network"; - case 0x3483: return "No route to destination"; - case 0x3486: return "Channel unacceptable"; - case 0x3487: - return "Call awarded and being delivered in an established channel"; - case 0x3490: return "Normal call clearing"; - case 0x3491: return "User busy"; - case 0x3492: return "No user responding"; - case 0x3493: return "No answer from user (user alerted)"; - case 0x3495: return "Call rejected"; - case 0x3496: return "Number changed"; - case 0x349A: return "Non-selected user clearing"; - case 0x349B: return "Destination out of order"; - case 0x349C: return "Invalid number format"; - case 0x349D: return "Facility rejected"; - case 0x349E: return "Response to STATUS ENQUIRY"; - case 0x349F: return "Normal, unspecified"; - case 0x34A2: return "No circuit / channel available"; - case 0x34A6: return "Network out of order"; - case 0x34A9: return "Temporary failure"; - case 0x34AA: return "Switching equipment congestion"; - case 0x34AB: return "Access information discarded"; - case 0x34AC: return "Requested circuit / channel not available"; - case 0x34AF: return "Resources unavailable, unspecified"; - case 0x34B1: return "Quality of service unavailable"; - case 0x34B2: return "Requested facility not subscribed"; - case 0x34B9: return "Bearer capability not authorized"; - case 0x34BA: return "Bearer capability not presently available"; - case 0x34BF: return "Service or option not available, unspecified"; - case 0x34C1: return "Bearer capability not implemented"; - case 0x34C2: return "Channel type not implemented"; - case 0x34C5: return "Requested facility not implemented"; - case 0x34C6: return "Only restricted digital information bearer capability is available"; - case 0x34CF: return "Service or option not implemented, unspecified"; - case 0x34D1: return "Invalid call reference value"; - case 0x34D2: return "Identified channel does not exist"; - case 0x34D3: return "A suspended call exists, but this call identity does not"; - case 0x34D4: return "Call identity in use"; - case 0x34D5: return "No call suspended"; - case 0x34D6: return "Call having the requested call identity has been cleared"; - case 0x34D8: return "Incompatible destination"; - case 0x34DB: return "Invalid transit network selection"; - case 0x34DF: return "Invalid message, unspecified"; - case 0x34E0: return "Mandatory information element is missing"; - case 0x34E1: return "Message type non-existent or not implemented"; - case 0x34E2: return "Message not compatible with call state or message type non-existent or not implemented"; - case 0x34E3: return "Information element non-existent or not implemented"; - case 0x34E4: return "Invalid information element contents"; - case 0x34E5: return "Message not compatible with call state"; - case 0x34E6: return "Recovery on timer expiry"; - case 0x34EF: return "Protocol error, unspecified"; - case 0x34FF: return "Interworking, unspecified"; - - default: return "No additional information"; - } -} -#endif - -typedef struct { - int typ; - size_t off; -} _cdef; - -#define _CBYTE 1 -#define _CWORD 2 -#define _CDWORD 3 -#define _CSTRUCT 4 -#define _CMSTRUCT 5 -#define _CEND 6 - -static _cdef cdef[] = -{ - /*00 */ - {_CEND}, - /*01 */ - {_CEND}, - /*02 */ - {_CEND}, - /*03 */ - {_CDWORD, offsetof(_cmsg, adr.adrController)}, - /*04 */ - {_CMSTRUCT, offsetof(_cmsg, AdditionalInfo)}, - /*05 */ - {_CSTRUCT, offsetof(_cmsg, B1configuration)}, - /*06 */ - {_CWORD, offsetof(_cmsg, B1protocol)}, - /*07 */ - {_CSTRUCT, offsetof(_cmsg, B2configuration)}, - /*08 */ - {_CWORD, offsetof(_cmsg, B2protocol)}, - /*09 */ - {_CSTRUCT, offsetof(_cmsg, B3configuration)}, - /*0a */ - {_CWORD, offsetof(_cmsg, B3protocol)}, - /*0b */ - {_CSTRUCT, offsetof(_cmsg, BC)}, - /*0c */ - {_CSTRUCT, offsetof(_cmsg, BChannelinformation)}, - /*0d */ - {_CMSTRUCT, offsetof(_cmsg, BProtocol)}, - /*0e */ - {_CSTRUCT, offsetof(_cmsg, CalledPartyNumber)}, - /*0f */ - {_CSTRUCT, offsetof(_cmsg, CalledPartySubaddress)}, - /*10 */ - {_CSTRUCT, offsetof(_cmsg, CallingPartyNumber)}, - /*11 */ - {_CSTRUCT, offsetof(_cmsg, CallingPartySubaddress)}, - /*12 */ - {_CDWORD, offsetof(_cmsg, CIPmask)}, - /*13 */ - {_CDWORD, offsetof(_cmsg, CIPmask2)}, - /*14 */ - {_CWORD, offsetof(_cmsg, CIPValue)}, - /*15 */ - {_CDWORD, offsetof(_cmsg, Class)}, - /*16 */ - {_CSTRUCT, offsetof(_cmsg, ConnectedNumber)}, - /*17 */ - {_CSTRUCT, offsetof(_cmsg, ConnectedSubaddress)}, - /*18 */ - {_CDWORD, offsetof(_cmsg, Data)}, - /*19 */ - {_CWORD, offsetof(_cmsg, DataHandle)}, - /*1a */ - {_CWORD, offsetof(_cmsg, DataLength)}, - /*1b */ - {_CSTRUCT, offsetof(_cmsg, FacilityConfirmationParameter)}, - /*1c */ - {_CSTRUCT, offsetof(_cmsg, Facilitydataarray)}, - /*1d */ - {_CSTRUCT, offsetof(_cmsg, FacilityIndicationParameter)}, - /*1e */ - {_CSTRUCT, offsetof(_cmsg, FacilityRequestParameter)}, - /*1f */ - {_CWORD, offsetof(_cmsg, FacilitySelector)}, - /*20 */ - {_CWORD, offsetof(_cmsg, Flags)}, - /*21 */ - {_CDWORD, offsetof(_cmsg, Function)}, - /*22 */ - {_CSTRUCT, offsetof(_cmsg, HLC)}, - /*23 */ - {_CWORD, offsetof(_cmsg, Info)}, - /*24 */ - {_CSTRUCT, offsetof(_cmsg, InfoElement)}, - /*25 */ - {_CDWORD, offsetof(_cmsg, InfoMask)}, - /*26 */ - {_CWORD, offsetof(_cmsg, InfoNumber)}, - /*27 */ - {_CSTRUCT, offsetof(_cmsg, Keypadfacility)}, - /*28 */ - {_CSTRUCT, offsetof(_cmsg, LLC)}, - /*29 */ - {_CSTRUCT, offsetof(_cmsg, ManuData)}, - /*2a */ - {_CDWORD, offsetof(_cmsg, ManuID)}, - /*2b */ - {_CSTRUCT, offsetof(_cmsg, NCPI)}, - /*2c */ - {_CWORD, offsetof(_cmsg, Reason)}, - /*2d */ - {_CWORD, offsetof(_cmsg, Reason_B3)}, - /*2e */ - {_CWORD, offsetof(_cmsg, Reject)}, - /*2f */ - {_CSTRUCT, offsetof(_cmsg, Useruserdata)} -}; - -static unsigned char *cpars[] = -{ - /*00 */ 0, - /*01 ALERT_REQ */ (unsigned char *) "\x03\x04\x0c\x27\x2f\x1c\x01\x01", - /*02 CONNECT_REQ */ (unsigned char *) "\x03\x14\x0e\x10\x0f\x11\x0d\x06\x08\x0a\x05\x07\x09\x01\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01", - /*03 */ 0, - /*04 DISCONNECT_REQ */ (unsigned char *) "\x03\x04\x0c\x27\x2f\x1c\x01\x01", - /*05 LISTEN_REQ */ (unsigned char *) "\x03\x25\x12\x13\x10\x11\x01", - /*06 */ 0, - /*07 */ 0, - /*08 INFO_REQ */ (unsigned char *) "\x03\x0e\x04\x0c\x27\x2f\x1c\x01\x01", - /*09 FACILITY_REQ */ (unsigned char *) "\x03\x1f\x1e\x01", - /*0a SELECT_B_PROTOCOL_REQ */ (unsigned char *) "\x03\x0d\x06\x08\x0a\x05\x07\x09\x01\x01", - /*0b CONNECT_B3_REQ */ (unsigned char *) "\x03\x2b\x01", - /*0c */ 0, - /*0d DISCONNECT_B3_REQ */ (unsigned char *) "\x03\x2b\x01", - /*0e */ 0, - /*0f DATA_B3_REQ */ (unsigned char *) "\x03\x18\x1a\x19\x20\x01", - /*10 RESET_B3_REQ */ (unsigned char *) "\x03\x2b\x01", - /*11 */ 0, - /*12 */ 0, - /*13 ALERT_CONF */ (unsigned char *) "\x03\x23\x01", - /*14 CONNECT_CONF */ (unsigned char *) "\x03\x23\x01", - /*15 */ 0, - /*16 DISCONNECT_CONF */ (unsigned char *) "\x03\x23\x01", - /*17 LISTEN_CONF */ (unsigned char *) "\x03\x23\x01", - /*18 MANUFACTURER_REQ */ (unsigned char *) "\x03\x2a\x15\x21\x29\x01", - /*19 */ 0, - /*1a INFO_CONF */ (unsigned char *) "\x03\x23\x01", - /*1b FACILITY_CONF */ (unsigned char *) "\x03\x23\x1f\x1b\x01", - /*1c SELECT_B_PROTOCOL_CONF */ (unsigned char *) "\x03\x23\x01", - /*1d CONNECT_B3_CONF */ (unsigned char *) "\x03\x23\x01", - /*1e */ 0, - /*1f DISCONNECT_B3_CONF */ (unsigned char *) "\x03\x23\x01", - /*20 */ 0, - /*21 DATA_B3_CONF */ (unsigned char *) "\x03\x19\x23\x01", - /*22 RESET_B3_CONF */ (unsigned char *) "\x03\x23\x01", - /*23 */ 0, - /*24 */ 0, - /*25 */ 0, - /*26 CONNECT_IND */ (unsigned char *) "\x03\x14\x0e\x10\x0f\x11\x0b\x28\x22\x04\x0c\x27\x2f\x1c\x01\x01", - /*27 CONNECT_ACTIVE_IND */ (unsigned char *) "\x03\x16\x17\x28\x01", - /*28 DISCONNECT_IND */ (unsigned char *) "\x03\x2c\x01", - /*29 */ 0, - /*2a MANUFACTURER_CONF */ (unsigned char *) "\x03\x2a\x15\x21\x29\x01", - /*2b */ 0, - /*2c INFO_IND */ (unsigned char *) "\x03\x26\x24\x01", - /*2d FACILITY_IND */ (unsigned char *) "\x03\x1f\x1d\x01", - /*2e */ 0, - /*2f CONNECT_B3_IND */ (unsigned char *) "\x03\x2b\x01", - /*30 CONNECT_B3_ACTIVE_IND */ (unsigned char *) "\x03\x2b\x01", - /*31 DISCONNECT_B3_IND */ (unsigned char *) "\x03\x2d\x2b\x01", - /*32 */ 0, - /*33 DATA_B3_IND */ (unsigned char *) "\x03\x18\x1a\x19\x20\x01", - /*34 RESET_B3_IND */ (unsigned char *) "\x03\x2b\x01", - /*35 CONNECT_B3_T90_ACTIVE_IND */ (unsigned char *) "\x03\x2b\x01", - /*36 */ 0, - /*37 */ 0, - /*38 CONNECT_RESP */ (unsigned char *) "\x03\x2e\x0d\x06\x08\x0a\x05\x07\x09\x01\x16\x17\x28\x04\x0c\x27\x2f\x1c\x01\x01", - /*39 CONNECT_ACTIVE_RESP */ (unsigned char *) "\x03\x01", - /*3a DISCONNECT_RESP */ (unsigned char *) "\x03\x01", - /*3b */ 0, - /*3c MANUFACTURER_IND */ (unsigned char *) "\x03\x2a\x15\x21\x29\x01", - /*3d */ 0, - /*3e INFO_RESP */ (unsigned char *) "\x03\x01", - /*3f FACILITY_RESP */ (unsigned char *) "\x03\x1f\x01", - /*40 */ 0, - /*41 CONNECT_B3_RESP */ (unsigned char *) "\x03\x2e\x2b\x01", - /*42 CONNECT_B3_ACTIVE_RESP */ (unsigned char *) "\x03\x01", - /*43 DISCONNECT_B3_RESP */ (unsigned char *) "\x03\x01", - /*44 */ 0, - /*45 DATA_B3_RESP */ (unsigned char *) "\x03\x19\x01", - /*46 RESET_B3_RESP */ (unsigned char *) "\x03\x01", - /*47 CONNECT_B3_T90_ACTIVE_RESP */ (unsigned char *) "\x03\x01", - /*48 */ 0, - /*49 */ 0, - /*4a */ 0, - /*4b */ 0, - /*4c */ 0, - /*4d */ 0, - /*4e MANUFACTURER_RESP */ (unsigned char *) "\x03\x2a\x15\x21\x29\x01", -}; - -/*-------------------------------------------------------*/ - -#define byteTLcpy(x,y) *(__u8 *)(x)=*(__u8 *)(y); -#define wordTLcpy(x,y) *(__u16 *)(x)=*(__u16 *)(y); -#define dwordTLcpy(x,y) memcpy(x,y,4); -#define structTLcpy(x,y,l) memcpy (x,y,l) -#define structTLcpyovl(x,y,l) memmove (x,y,l) - -#define byteTRcpy(x,y) *(__u8 *)(y)=*(__u8 *)(x); -#define wordTRcpy(x,y) *(__u16 *)(y)=*(__u16 *)(x); -#define dwordTRcpy(x,y) memcpy(y,x,4); -#define structTRcpy(x,y,l) memcpy (y,x,l) -#define structTRcpyovl(x,y,l) memmove (y,x,l) - -/*-------------------------------------------------------*/ -static unsigned command_2_index(unsigned c, unsigned sc) -{ - if (c & 0x80) - c = 0x9 + (c & 0x0f); - else if (c <= 0x0f); - else if (c == 0x41) - c = 0x9 + 0x1; - else if (c == 0xff) - c = 0x00; - return (sc & 3) * (0x9 + 0x9) + c; -} - -/*-------------------------------------------------------*/ -#define TYP (cdef[cmsg->par[cmsg->p]].typ) -#define OFF (((__u8 *)cmsg)+cdef[cmsg->par[cmsg->p]].off) - -static void jumpcstruct(_cmsg * cmsg) -{ - unsigned layer; - for (cmsg->p++, layer = 1; layer;) { - /* $$$$$ assert (cmsg->p); */ - cmsg->p++; - switch (TYP) { - case _CMSTRUCT: - layer++; - break; - case _CEND: - layer--; - break; - } - } -} -/*-------------------------------------------------------*/ -static void pars_2_message(_cmsg * cmsg) -{ - - for (; TYP != _CEND; cmsg->p++) { - switch (TYP) { - case _CBYTE: - byteTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTLcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - if (*(__u8 **) OFF == 0) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - } else if (**(_cstruct *) OFF != 0xff) { - structTLcpy(cmsg->m + cmsg->l, *(_cstruct *) OFF, 1 + **(_cstruct *) OFF); - cmsg->l += 1 + **(_cstruct *) OFF; - } else { - _cstruct s = *(_cstruct *) OFF; - structTLcpy(cmsg->m + cmsg->l, s, 3 + *(__u16 *) (s + 1)); - cmsg->l += 3 + *(__u16 *) (s + 1); - } - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (*(_cmstruct *) OFF == CAPI_DEFAULT) { - *(cmsg->m + cmsg->l) = '\0'; - cmsg->l++; - jumpcstruct(cmsg); - } -/*----- Metastruktur wird composed -----*/ - else { - unsigned _l = cmsg->l; - unsigned _ls; - cmsg->l++; - cmsg->p++; - pars_2_message(cmsg); - _ls = cmsg->l - _l - 1; - if (_ls < 255) - (cmsg->m + _l)[0] = (__u8) _ls; - else { - structTLcpyovl(cmsg->m + _l + 3, cmsg->m + _l + 1, _ls); - (cmsg->m + _l)[0] = 0xff; - wordTLcpy(cmsg->m + _l + 1, &_ls); - } - } - break; - } - } -} - -/*-------------------------------------------------------*/ -unsigned capi_cmsg2message(_cmsg * cmsg, __u8 * msg) -{ - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)]; - - pars_2_message(cmsg); - - wordTLcpy(msg + 0, &cmsg->l); - byteTLcpy(cmsg->m + 4, &cmsg->Command); - byteTLcpy(cmsg->m + 5, &cmsg->Subcommand); - wordTLcpy(cmsg->m + 2, &cmsg->ApplId); - wordTLcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/*-------------------------------------------------------*/ -static void message_2_pars(_cmsg * cmsg) -{ - for (; TYP != _CEND; cmsg->p++) { - - switch (TYP) { - case _CBYTE: - byteTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l++; - break; - case _CWORD: - wordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 2; - break; - case _CDWORD: - dwordTRcpy(cmsg->m + cmsg->l, OFF); - cmsg->l += 4; - break; - case _CSTRUCT: - *(__u8 **) OFF = cmsg->m + cmsg->l; - - if (cmsg->m[cmsg->l] != 0xff) - cmsg->l += 1 + cmsg->m[cmsg->l]; - else - cmsg->l += 3 + *(__u16 *) (cmsg->m + cmsg->l + 1); - break; - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (cmsg->m[cmsg->l] == '\0') { - *(_cmstruct *) OFF = CAPI_DEFAULT; - cmsg->l++; - jumpcstruct(cmsg); - } else { - unsigned _l = cmsg->l; - *(_cmstruct *) OFF = CAPI_COMPOSE; - cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; - cmsg->p++; - message_2_pars(cmsg); - } - break; - } - } -} - -/*-------------------------------------------------------*/ -unsigned capi_message2cmsg(_cmsg * cmsg, __u8 * msg) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->m = msg; - cmsg->l = 8; - cmsg->p = 0; - byteTRcpy(cmsg->m + 4, &cmsg->Command); - byteTRcpy(cmsg->m + 5, &cmsg->Subcommand); - cmsg->par = cpars[command_2_index(cmsg->Command, cmsg->Subcommand)]; - - message_2_pars(cmsg); - - wordTRcpy(msg + 0, &cmsg->l); - wordTRcpy(cmsg->m + 2, &cmsg->ApplId); - wordTRcpy(cmsg->m + 6, &cmsg->Messagenumber); - - return 0; -} - -/*-------------------------------------------------------*/ -unsigned capi_cmsg_header(_cmsg * cmsg, __u16 _ApplId, - __u8 _Command, __u8 _Subcommand, - __u16 _Messagenumber, __u32 _Controller) -{ - memset(cmsg, 0, sizeof(_cmsg)); - cmsg->ApplId = _ApplId; - cmsg->Command = _Command; - cmsg->Subcommand = _Subcommand; - cmsg->Messagenumber = _Messagenumber; - cmsg->adr.adrController = _Controller; - return 0; -} - -/*-------------------------------------------------------*/ - -static char *mnames[] = -{ - 0, - "ALERT_REQ", - "CONNECT_REQ", - 0, - "DISCONNECT_REQ", - "LISTEN_REQ", - 0, - 0, - "INFO_REQ", - "FACILITY_REQ", - "SELECT_B_PROTOCOL_REQ", - "CONNECT_B3_REQ", - 0, - "DISCONNECT_B3_REQ", - 0, - "DATA_B3_REQ", - "RESET_B3_REQ", - 0, - 0, - "ALERT_CONF", - "CONNECT_CONF", - 0, - "DISCONNECT_CONF", - "LISTEN_CONF", - "MANUFACTURER_REQ", - 0, - "INFO_CONF", - "FACILITY_CONF", - "SELECT_B_PROTOCOL_CONF", - "CONNECT_B3_CONF", - 0, - "DISCONNECT_B3_CONF", - 0, - "DATA_B3_CONF", - "RESET_B3_CONF", - 0, - 0, - 0, - "CONNECT_IND", - "CONNECT_ACTIVE_IND", - "DISCONNECT_IND", - 0, - "MANUFACTURER_CONF", - 0, - "INFO_IND", - "FACILITY_IND", - 0, - "CONNECT_B3_IND", - "CONNECT_B3_ACTIVE_IND", - "DISCONNECT_B3_IND", - 0, - "DATA_B3_IND", - "RESET_B3_IND", - "CONNECT_B3_T90_ACTIVE_IND", - 0, - 0, - "CONNECT_RESP", - "CONNECT_ACTIVE_RESP", - "DISCONNECT_RESP", - 0, - "MANUFACTURER_IND", - 0, - "INFO_RESP", - "FACILITY_RESP", - 0, - "CONNECT_B3_RESP", - "CONNECT_B3_ACTIVE_RESP", - "DISCONNECT_B3_RESP", - 0, - "DATA_B3_RESP", - "RESET_B3_RESP", - "CONNECT_B3_T90_ACTIVE_RESP", - 0, - 0, - 0, - 0, - 0, - 0, - "MANUFACTURER_RESP" -}; - -char *capi_cmd2str(__u8 cmd, __u8 subcmd) -{ - return mnames[command_2_index(cmd, subcmd)]; -} - - -/*-------------------------------------------------------*/ -/*-------------------------------------------------------*/ - -static char *pnames[] = -{ - /*00 */ 0, - /*01 */ 0, - /*02 */ 0, - /*03 */ "Controller/PLCI/NCCI", - /*04 */ "AdditionalInfo", - /*05 */ "B1configuration", - /*06 */ "B1protocol", - /*07 */ "B2configuration", - /*08 */ "B2protocol", - /*09 */ "B3configuration", - /*0a */ "B3protocol", - /*0b */ "BC", - /*0c */ "BChannelinformation", - /*0d */ "BProtocol", - /*0e */ "CalledPartyNumber", - /*0f */ "CalledPartySubaddress", - /*10 */ "CallingPartyNumber", - /*11 */ "CallingPartySubaddress", - /*12 */ "CIPmask", - /*13 */ "CIPmask2", - /*14 */ "CIPValue", - /*15 */ "Class", - /*16 */ "ConnectedNumber", - /*17 */ "ConnectedSubaddress", - /*18 */ "Data32", - /*19 */ "DataHandle", - /*1a */ "DataLength", - /*1b */ "FacilityConfirmationParameter", - /*1c */ "Facilitydataarray", - /*1d */ "FacilityIndicationParameter", - /*1e */ "FacilityRequestParameter", - /*1f */ "FacilitySelector", - /*20 */ "Flags", - /*21 */ "Function", - /*22 */ "HLC", - /*23 */ "Info", - /*24 */ "InfoElement", - /*25 */ "InfoMask", - /*26 */ "InfoNumber", - /*27 */ "Keypadfacility", - /*28 */ "LLC", - /*29 */ "ManuData", - /*2a */ "ManuID", - /*2b */ "NCPI", - /*2c */ "Reason", - /*2d */ "Reason_B3", - /*2e */ "Reject", - /*2f */ "Useruserdata" -}; - - -static char buf[8192]; -static char *p = 0; - -#include - -/*-------------------------------------------------------*/ -static void bufprint(char *fmt,...) -{ - va_list f; - va_start(f, fmt); - vsprintf(p, fmt, f); - va_end(f); - p += strlen(p); -} - -static void printstructlen(__u8 * m, unsigned len) -{ - unsigned hex = 0; - for (; len; len--, m++) - if (isalnum(*m) || *m == ' ') { - if (hex) - bufprint(">"); - bufprint("%c", *m); - hex = 0; - } else { - if (!hex) - bufprint("<%02x", *m); - else - bufprint(" %02x", *m); - hex = 1; - } - if (hex) - bufprint(">"); -} - -static void printstruct(__u8 * m) -{ - unsigned len; - if (m[0] != 0xff) { - len = m[0]; - m += 1; - } else { - len = ((__u16 *) (m + 1))[0]; - m += 3; - } - printstructlen(m, len); -} - -/*-------------------------------------------------------*/ -#define NAME (pnames[cmsg->par[cmsg->p]]) - -static void protocol_message_2_pars(_cmsg * cmsg, int level) -{ - for (; TYP != _CEND; cmsg->p++) { - int slen = 29 + 3 - level; - int i; - - bufprint(" "); - for (i = 0; i < level - 1; i++) - bufprint(" "); - - switch (TYP) { - case _CBYTE: - bufprint("%-*s = 0x%x\n", slen, NAME, *(__u8 *) (cmsg->m + cmsg->l)); - cmsg->l++; - break; - case _CWORD: - bufprint("%-*s = 0x%x\n", slen, NAME, *(__u16 *) (cmsg->m + cmsg->l)); - cmsg->l += 2; - break; - case _CDWORD: - bufprint("%-*s = 0x%lx\n", slen, NAME, *(__u32 *) (cmsg->m + cmsg->l)); - cmsg->l += 4; - break; - case _CSTRUCT: - bufprint("%-*s = ", slen, NAME); - if (cmsg->m[cmsg->l] == '\0') - bufprint("default"); - else - printstruct(cmsg->m + cmsg->l); - bufprint("\n"); - if (cmsg->m[cmsg->l] != 0xff) - cmsg->l += 1 + cmsg->m[cmsg->l]; - else - cmsg->l += 3 + *(__u16 *) (cmsg->m + cmsg->l + 1); - - break; - - case _CMSTRUCT: -/*----- Metastruktur 0 -----*/ - if (cmsg->m[cmsg->l] == '\0') { - bufprint("%-*s = default\n", slen, NAME); - cmsg->l++; - jumpcstruct(cmsg); - } else { - char *name = NAME; - unsigned _l = cmsg->l; - bufprint("%-*s\n", slen, name); - cmsg->l = (cmsg->m + _l)[0] == 255 ? cmsg->l + 3 : cmsg->l + 1; - cmsg->p++; - protocol_message_2_pars(cmsg, level + 1); - } - break; - } - } -} -/*-------------------------------------------------------*/ -char *capi_message2str(__u8 * msg) -{ - - _cmsg cmsg; - p = buf; - p[0] = 0; - - cmsg.m = msg; - cmsg.l = 8; - cmsg.p = 0; - byteTRcpy(cmsg.m + 4, &cmsg.Command); - byteTRcpy(cmsg.m + 5, &cmsg.Subcommand); - cmsg.par = cpars[command_2_index(cmsg.Command, cmsg.Subcommand)]; - - bufprint("%-26s ID=%03d #0x%04x LEN=%04d\n", - mnames[command_2_index(cmsg.Command, cmsg.Subcommand)], - ((unsigned short *) msg)[1], - ((unsigned short *) msg)[3], - ((unsigned short *) msg)[0]); - - protocol_message_2_pars(&cmsg, 1); - return buf; -} - -char *capi_cmsg2str(_cmsg * cmsg) -{ - p = buf; - p[0] = 0; - cmsg->l = 8; - cmsg->p = 0; - bufprint("%s ID=%03d #0x%04x LEN=%04d\n", - mnames[command_2_index(cmsg->Command, cmsg->Subcommand)], - ((__u16 *) cmsg->m)[1], - ((__u16 *) cmsg->m)[3], - ((__u16 *) cmsg->m)[0]); - protocol_message_2_pars(cmsg, 1); - return buf; -} - - -EXPORT_SYMBOL(capi_cmsg2message); -EXPORT_SYMBOL(capi_message2cmsg); -EXPORT_SYMBOL(capi_cmsg_header); -EXPORT_SYMBOL(capi_cmd2str); -EXPORT_SYMBOL(capi_cmsg2str); -EXPORT_SYMBOL(capi_message2str); -EXPORT_SYMBOL(capi_info2str); - -#ifdef MODULE - -int init_module(void) -{ - return 0; -} - -void cleanup_module(void) -{ -} - -#endif diff --git a/drivers/isdn/avmb1/capiutil.h b/drivers/isdn/avmb1/capiutil.h deleted file mode 100644 index fb4ca8b9..00000000 --- a/drivers/isdn/avmb1/capiutil.h +++ /dev/null @@ -1,537 +0,0 @@ -/* - * $Id$ - * - * CAPI 2.0 defines & types - * - * From CAPI 2.0 Development Kit AVM 1995 (capi20.h) - * Rewritten for Linux 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.5 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.4 1999/09/15 08:16:03 calle - * Implementation of 64Bit extention complete. - * - * Revision 1.3 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.2 1997/05/18 09:24:19 calle - * added verbose disconnect reason reporting to avmb1. - * some fixes in capi20 interface. - * changed info messages for B1-PCI - * - * Revision 1.1 1997/03/04 21:50:35 calle - * Frirst version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - * - */ -#ifndef __CAPIUTIL_H__ -#define __CAPIUTIL_H__ - -#include - -#define CAPIMSG_BASELEN 8 -#define CAPIMSG_U8(m, off) (m[off]) -#define CAPIMSG_U16(m, off) (m[off]|(m[(off)+1]<<8)) -#define CAPIMSG_U32(m, off) (m[off]|(m[(off)+1]<<8)|(m[(off)+2]<<16)|(m[(off)+3]<<24)) -#define CAPIMSG_LEN(m) CAPIMSG_U16(m,0) -#define CAPIMSG_APPID(m) CAPIMSG_U16(m,2) -#define CAPIMSG_COMMAND(m) CAPIMSG_U8(m,4) -#define CAPIMSG_SUBCOMMAND(m) CAPIMSG_U8(m,5) -#define CAPIMSG_CMD(m) (((m[4])<<8)|(m[5])) -#define CAPIMSG_MSGID(m) CAPIMSG_U16(m,6) -#define CAPIMSG_CONTROLLER(m) (m[8] & 0x7f) -#define CAPIMSG_CONTROL(m) CAPIMSG_U32(m, 8) -#define CAPIMSG_NCCI(m) CAPIMSG_CONTROL(m) -#define CAPIMSG_DATALEN(m) CAPIMSG_U16(m,16) /* DATA_B3_REQ */ - -static inline void capimsg_setu8(void *m, int off, __u8 val) -{ - ((__u8 *)m)[off] = val; -} - -static inline void capimsg_setu16(void *m, int off, __u16 val) -{ - ((__u8 *)m)[off] = val & 0xff; - ((__u8 *)m)[off+1] = (val >> 8) & 0xff; -} - -static inline void capimsg_setu32(void *m, int off, __u32 val) -{ - ((__u8 *)m)[off] = val & 0xff; - ((__u8 *)m)[off+1] = (val >> 8) & 0xff; - ((__u8 *)m)[off+2] = (val >> 16) & 0xff; - ((__u8 *)m)[off+3] = (val >> 24) & 0xff; -} - -#define CAPIMSG_SETLEN(m, len) capimsg_setu16(m, 0, len) -#define CAPIMSG_SETAPPID(m, applid) capimsg_setu16(m, 2, applid) -#define CAPIMSG_SETCOMMAND(m,cmd) capimsg_setu8(m, 4, cmd) -#define CAPIMSG_SETSUBCOMMAND(m, cmd) capimsg_setu8(m, 5, cmd) -#define CAPIMSG_SETMSGID(m, msgid) capimsg_setu16(m, 6, msgid) -#define CAPIMSG_SETCONTROL(m, contr) capimsg_setu32(m, 8, contr) -#define CAPIMSG_SETDATALEN(m, len) capimsg_setu16(m, 16, len) - -/*----- basic-type definitions -----*/ - -typedef __u8 *_cstruct; - -typedef enum { - CAPI_COMPOSE, - CAPI_DEFAULT -} _cmstruct; - -/* - The _cmsg structure contains all possible CAPI 2.0 parameter. - All parameters are stored here first. The function CAPI_CMSG_2_MESSAGE - assembles the parameter and builds CAPI2.0 conform messages. - CAPI_MESSAGE_2_CMSG disassembles CAPI 2.0 messages and stores the - parameter in the _cmsg structure - */ - -typedef struct { - /* Header */ - __u16 ApplId; - __u8 Command; - __u8 Subcommand; - __u16 Messagenumber; - - /* Parameter */ - union { - __u32 adrController; - __u32 adrPLCI; - __u32 adrNCCI; - } adr; - - _cmstruct AdditionalInfo; - _cstruct B1configuration; - __u16 B1protocol; - _cstruct B2configuration; - __u16 B2protocol; - _cstruct B3configuration; - __u16 B3protocol; - _cstruct BC; - _cstruct BChannelinformation; - _cmstruct BProtocol; - _cstruct CalledPartyNumber; - _cstruct CalledPartySubaddress; - _cstruct CallingPartyNumber; - _cstruct CallingPartySubaddress; - __u32 CIPmask; - __u32 CIPmask2; - __u16 CIPValue; - __u32 Class; - _cstruct ConnectedNumber; - _cstruct ConnectedSubaddress; - __u32 Data; - __u16 DataHandle; - __u16 DataLength; - _cstruct FacilityConfirmationParameter; - _cstruct Facilitydataarray; - _cstruct FacilityIndicationParameter; - _cstruct FacilityRequestParameter; - __u16 FacilitySelector; - __u16 Flags; - __u32 Function; - _cstruct HLC; - __u16 Info; - _cstruct InfoElement; - __u32 InfoMask; - __u16 InfoNumber; - _cstruct Keypadfacility; - _cstruct LLC; - _cstruct ManuData; - __u32 ManuID; - _cstruct NCPI; - __u16 Reason; - __u16 Reason_B3; - __u16 Reject; - _cstruct Useruserdata; - - /* intern */ - unsigned l, p; - unsigned char *par; - __u8 *m; - - /* buffer to construct message */ - __u8 buf[180]; - -} _cmsg; - -/* - * capi_cmsg2message() assembles the parameter from _cmsg to a CAPI 2.0 - * conform message - */ -unsigned capi_cmsg2message(_cmsg * cmsg, __u8 * msg); - -/* - * capi_message2cmsg disassembles a CAPI message an writes the parameter - * into _cmsg for easy access - */ -unsigned capi_message2cmsg(_cmsg * cmsg, __u8 * msg); - -/* - * capi_cmsg_header() fills the _cmsg structure with default values, so only - * parameter with non default values must be changed before sending the - * message. - */ -unsigned capi_cmsg_header(_cmsg * cmsg, __u16 _ApplId, - __u8 _Command, __u8 _Subcommand, - __u16 _Messagenumber, __u32 _Controller); - -/* - * capi_info2str generated a readable string for Capi2.0 reasons. - */ -char *capi_info2str(__u16 reason); - -/*-----------------------------------------------------------------------*/ - -/* - * Debugging / Tracing functions - */ -char *capi_cmd2str(__u8 cmd, __u8 subcmd); -char *capi_cmsg2str(_cmsg * cmsg); -char *capi_message2str(__u8 * msg); - -/*-----------------------------------------------------------------------*/ - -static inline void capi_cmsg_answer(_cmsg * cmsg) -{ - cmsg->Subcommand |= 0x01; -} - -/*-----------------------------------------------------------------------*/ - -static inline void capi_fill_CONNECT_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - capi_cmsg_header(cmsg, ApplId, 0x82, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_FACILITY_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 FacilitySelector, - _cstruct FacilityRequestParameter) -{ - capi_cmsg_header(cmsg, ApplId, 0x80, 0x80, Messagenumber, adr); - cmsg->FacilitySelector = FacilitySelector; - cmsg->FacilityRequestParameter = FacilityRequestParameter; -} - -static inline void capi_fill_INFO_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct CalledPartyNumber, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x08, 0x80, Messagenumber, adr); - cmsg->CalledPartyNumber = CalledPartyNumber; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_LISTEN_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 InfoMask, - __u32 CIPmask, - __u32 CIPmask2, - _cstruct CallingPartyNumber, - _cstruct CallingPartySubaddress) -{ - capi_cmsg_header(cmsg, ApplId, 0x05, 0x80, Messagenumber, adr); - cmsg->InfoMask = InfoMask; - cmsg->CIPmask = CIPmask; - cmsg->CIPmask2 = CIPmask2; - cmsg->CallingPartyNumber = CallingPartyNumber; - cmsg->CallingPartySubaddress = CallingPartySubaddress; -} - -static inline void capi_fill_ALERT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x01, 0x80, Messagenumber, adr); - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_CONNECT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 CIPValue, - _cstruct CalledPartyNumber, - _cstruct CallingPartyNumber, - _cstruct CalledPartySubaddress, - _cstruct CallingPartySubaddress, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration, - _cstruct BC, - _cstruct LLC, - _cstruct HLC, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - - capi_cmsg_header(cmsg, ApplId, 0x02, 0x80, Messagenumber, adr); - cmsg->CIPValue = CIPValue; - cmsg->CalledPartyNumber = CalledPartyNumber; - cmsg->CallingPartyNumber = CallingPartyNumber; - cmsg->CalledPartySubaddress = CalledPartySubaddress; - cmsg->CallingPartySubaddress = CallingPartySubaddress; - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; - cmsg->BC = BC; - cmsg->LLC = LLC; - cmsg->HLC = HLC; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_DATA_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 Data, - __u16 DataLength, - __u16 DataHandle, - __u16 Flags) -{ - - capi_cmsg_header(cmsg, ApplId, 0x86, 0x80, Messagenumber, adr); - cmsg->Data = Data; - cmsg->DataLength = DataLength; - cmsg->DataHandle = DataHandle; - cmsg->Flags = Flags; -} - -static inline void capi_fill_DISCONNECT_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - - capi_cmsg_header(cmsg, ApplId, 0x04, 0x80, Messagenumber, adr); - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_DISCONNECT_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - - capi_cmsg_header(cmsg, ApplId, 0x84, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_MANUFACTURER_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 ManuID, - __u32 Class, - __u32 Function, - _cstruct ManuData) -{ - - capi_cmsg_header(cmsg, ApplId, 0xff, 0x80, Messagenumber, adr); - cmsg->ManuID = ManuID; - cmsg->Class = Class; - cmsg->Function = Function; - cmsg->ManuData = ManuData; -} - -static inline void capi_fill_RESET_B3_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - _cstruct NCPI) -{ - - capi_cmsg_header(cmsg, ApplId, 0x87, 0x80, Messagenumber, adr); - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_SELECT_B_PROTOCOL_REQ(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration) -{ - - capi_cmsg_header(cmsg, ApplId, 0x41, 0x80, Messagenumber, adr); - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; -} - -static inline void capi_fill_CONNECT_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 Reject, - __u16 B1protocol, - __u16 B2protocol, - __u16 B3protocol, - _cstruct B1configuration, - _cstruct B2configuration, - _cstruct B3configuration, - _cstruct ConnectedNumber, - _cstruct ConnectedSubaddress, - _cstruct LLC, - _cstruct BChannelinformation, - _cstruct Keypadfacility, - _cstruct Useruserdata, - _cstruct Facilitydataarray) -{ - capi_cmsg_header(cmsg, ApplId, 0x02, 0x83, Messagenumber, adr); - cmsg->Reject = Reject; - cmsg->B1protocol = B1protocol; - cmsg->B2protocol = B2protocol; - cmsg->B3protocol = B3protocol; - cmsg->B1configuration = B1configuration; - cmsg->B2configuration = B2configuration; - cmsg->B3configuration = B3configuration; - cmsg->ConnectedNumber = ConnectedNumber; - cmsg->ConnectedSubaddress = ConnectedSubaddress; - cmsg->LLC = LLC; - cmsg->BChannelinformation = BChannelinformation; - cmsg->Keypadfacility = Keypadfacility; - cmsg->Useruserdata = Useruserdata; - cmsg->Facilitydataarray = Facilitydataarray; -} - -static inline void capi_fill_CONNECT_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x03, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_CONNECT_B3_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x83, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_CONNECT_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 Reject, - _cstruct NCPI) -{ - capi_cmsg_header(cmsg, ApplId, 0x82, 0x83, Messagenumber, adr); - cmsg->Reject = Reject; - cmsg->NCPI = NCPI; -} - -static inline void capi_fill_CONNECT_B3_T90_ACTIVE_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x88, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_DATA_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 DataHandle) -{ - - capi_cmsg_header(cmsg, ApplId, 0x86, 0x83, Messagenumber, adr); - cmsg->DataHandle = DataHandle; -} - -static inline void capi_fill_DISCONNECT_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x84, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_DISCONNECT_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x04, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_FACILITY_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u16 FacilitySelector) -{ - - capi_cmsg_header(cmsg, ApplId, 0x80, 0x83, Messagenumber, adr); - cmsg->FacilitySelector = FacilitySelector; -} - -static inline void capi_fill_INFO_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x08, 0x83, Messagenumber, adr); -} - -static inline void capi_fill_MANUFACTURER_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr, - __u32 ManuID, - __u32 Class, - __u32 Function, - _cstruct ManuData) -{ - - capi_cmsg_header(cmsg, ApplId, 0xff, 0x83, Messagenumber, adr); - cmsg->ManuID = ManuID; - cmsg->Class = Class; - cmsg->Function = Function; - cmsg->ManuData = ManuData; -} - -static inline void capi_fill_RESET_B3_RESP(_cmsg * cmsg, __u16 ApplId, __u16 Messagenumber, - __u32 adr) -{ - - capi_cmsg_header(cmsg, ApplId, 0x87, 0x83, Messagenumber, adr); -} - -#endif /* __CAPIUTIL_H__ */ diff --git a/drivers/isdn/avmb1/kcapi.c b/drivers/isdn/avmb1/kcapi.c deleted file mode 100644 index d1084a34..00000000 --- a/drivers/isdn/avmb1/kcapi.c +++ /dev/null @@ -1,1799 +0,0 @@ -/* - * $Id$ - * - * Kernel CAPI 2.0 Module - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.13 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.12 2000/01/28 16:45:39 calle - * new manufacturer command KCAPI_CMD_ADDCARD (generic addcard), - * will search named driver and call the add_card function if one exist. - * - * Revision 1.11 1999/11/23 13:29:29 calle - * Bugfix: incoming capi message were never traced. - * - * Revision 1.10 1999/10/26 15:30:32 calle - * Generate error message if user want to add card, but driver module is - * not loaded. - * - * Revision 1.9 1999/10/11 22:04:12 keil - * COMPAT_NEED_UACCESS (no include in isdn_compat.h) - * - * Revision 1.8 1999/09/10 17:24:18 calle - * Changes for proposed standard for CAPI2.0: - * - AK148 "Linux Exention" - * - * Revision 1.7 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 1.6 1999/07/20 06:41:49 calle - * Bugfix: After the redesign of the AVM B1 driver, the driver didn't even - * compile, if not selected as modules. - * - * Revision 1.5 1999/07/09 15:05:48 keil - * compat.h is now isdn_compat.h - * - * Revision 1.4 1999/07/08 14:15:17 calle - * Forgot to count down ncards in drivercb_detach_ctr. - * - * Revision 1.3 1999/07/06 07:42:02 calle - * - changes in /proc interface - * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. - * - * Revision 1.2 1999/07/05 15:09:52 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:42 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - */ -#define CONFIG_AVMB1_COMPAT - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef COMPAT_NEED_UACCESS -#include -#endif -#include "capicmd.h" -#include "capiutil.h" -#include "capilli.h" -#ifdef CONFIG_AVMB1_COMPAT -#include -#endif - -static char *revision = "$Revision$"; - -/* ------------------------------------------------------------- */ - -#define CARD_FREE 0 -#define CARD_DETECTED 1 -#define CARD_LOADING 2 -#define CARD_RUNNING 3 - -/* ------------------------------------------------------------- */ - -int showcapimsgs = 0; - -MODULE_AUTHOR("Carsten Paeth "); -MODULE_PARM(showcapimsgs, "0-4i"); - -/* ------------------------------------------------------------- */ - -struct msgidqueue { - struct msgidqueue *next; - __u16 msgid; -}; - -struct capi_ncci { - struct capi_ncci *next; - __u16 applid; - __u32 ncci; - __u32 winsize; - int nmsg; - struct msgidqueue *msgidqueue; - struct msgidqueue *msgidlast; - struct msgidqueue *msgidfree; - struct msgidqueue msgidpool[CAPI_MAXDATAWINDOW]; -}; - -struct capi_appl { - __u16 applid; - capi_register_params rparam; - int releasing; - void *param; - void (*signal) (__u16 applid, void *param); - struct sk_buff_head recv_queue; - int nncci; - struct capi_ncci *nccilist; - - unsigned long nrecvctlpkt; - unsigned long nrecvdatapkt; - unsigned long nsentctlpkt; - unsigned long nsentdatapkt; -}; - -struct capi_notifier { - struct capi_notifier *next; - unsigned int cmd; - __u32 controller; - __u16 applid; - __u32 ncci; -}; - -/* ------------------------------------------------------------- */ - -static struct capi_version driver_version = {2, 0, 1, 1<<4}; -static char driver_serial[CAPI_SERIAL_LEN] = "0004711"; -static char capi_manufakturer[64] = "AVM Berlin"; - -#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 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) - -static struct capi_appl applications[CAPI_MAXAPPL]; -static struct capi_ctr cards[CAPI_MAXCONTR]; -static int ncards = 0; -static struct sk_buff_head recv_queue; -static struct capi_interface_user *capi_users = 0; -static spinlock_t capi_users_lock = SPIN_LOCK_UNLOCKED; -static struct capi_driver *drivers; -static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; - -static struct tq_struct tq_state_notify; -static struct tq_struct tq_recv_notify; - -/* -------- util functions ------------------------------------ */ - -static char *cardstate2str(unsigned short cardstate) -{ - switch (cardstate) { - default: - case CARD_FREE: return "free"; - case CARD_DETECTED: return "detected"; - case CARD_LOADING: return "loading"; - case CARD_RUNNING: return "running"; - } -} - -static inline int capi_cmd_valid(__u8 cmd) -{ - switch (cmd) { - case CAPI_ALERT: - case CAPI_CONNECT: - case CAPI_CONNECT_ACTIVE: - case CAPI_CONNECT_B3_ACTIVE: - case CAPI_CONNECT_B3: - case CAPI_CONNECT_B3_T90_ACTIVE: - case CAPI_DATA_B3: - case CAPI_DISCONNECT_B3: - case CAPI_DISCONNECT: - case CAPI_FACILITY: - case CAPI_INFO: - case CAPI_LISTEN: - case CAPI_MANUFACTURER: - case CAPI_RESET_B3: - case CAPI_SELECT_B_PROTOCOL: - return 1; - } - return 0; -} - -static inline int capi_subcmd_valid(__u8 subcmd) -{ - switch (subcmd) { - case CAPI_REQ: - case CAPI_CONF: - case CAPI_IND: - case CAPI_RESP: - return 1; - } - return 0; -} - -/* -------- /proc functions ----------------------------------- */ -/* - * /proc/capi/applications: - * applid l3cnt dblkcnt dblklen #ncci recvqueuelen - */ -static int proc_applications_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_appl *ap; - int i; - int len = 0; - off_t begin = 0; - - for (i=0; i < CAPI_MAXAPPL; i++) { - ap = &applications[i]; - if (ap->applid == 0) continue; - len += sprintf(page+len, "%u %d %d %d %d %d\n", - ap->applid, - ap->rparam.level3cnt, - ap->rparam.datablkcnt, - ap->rparam.datablklen, - ap->nncci, - skb_queue_len(&ap->recv_queue)); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } -endloop: - if (i >= CAPI_MAXAPPL) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * /proc/capi/ncci: - * applid ncci winsize nblk - */ -static int proc_ncci_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_appl *ap; - struct capi_ncci *np; - int i; - int len = 0; - off_t begin = 0; - - for (i=0; i < CAPI_MAXAPPL; i++) { - ap = &applications[i]; - if (ap->applid == 0) continue; - for (np = ap->nccilist; np; np = np->next) { - len += sprintf(page+len, "%d 0x%x %d %d\n", - np->applid, - np->ncci, - np->winsize, - np->nmsg); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } - } -endloop: - if (i >= CAPI_MAXAPPL) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * /proc/capi/driver: - * driver ncontroller - */ -static int proc_driver_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_driver *driver; - int len = 0; - off_t begin = 0; - - spin_lock(&drivers_lock); - for (driver = drivers; driver; driver = driver->next) { - len += sprintf(page+len, "%-32s %d %s\n", - driver->name, - driver->ncontroller, - driver->revision); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } -endloop: - spin_unlock(&drivers_lock); - if (!driver) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * /proc/capi/users: - * name - */ -static int proc_users_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_interface_user *cp; - int len = 0; - off_t begin = 0; - - spin_lock(&capi_users_lock); - for (cp = capi_users; cp ; cp = cp->next) { - len += sprintf(page+len, "%s\n", cp->name); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } -endloop: - spin_unlock(&capi_users_lock); - if (cp == 0) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * /proc/capi/controller: - * cnr driver cardstate name driverinfo - */ -static int proc_controller_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_ctr *cp; - int i; - int len = 0; - off_t begin = 0; - - for (i=0; i < CAPI_MAXCONTR; i++) { - cp = &cards[i]; - if (cp->cardstate == CARD_FREE) continue; - len += sprintf(page+len, "%d %-10s %-8s %-16s %s\n", - cp->cnr, cp->driver->name, - cardstate2str(cp->cardstate), - cp->name, - cp->driver->procinfo ? cp->driver->procinfo(cp) : "" - ); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } -endloop: - if (i >= CAPI_MAXCONTR) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * /proc/capi/applstats: - * applid nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt - */ -static int proc_applstats_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_appl *ap; - int i; - int len = 0; - off_t begin = 0; - - for (i=0; i < CAPI_MAXAPPL; i++) { - ap = &applications[i]; - if (ap->applid == 0) continue; - len += sprintf(page+len, "%u %lu %lu %lu %lu\n", - ap->applid, - ap->nrecvctlpkt, - ap->nrecvdatapkt, - ap->nsentctlpkt, - ap->nsentdatapkt); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } -endloop: - if (i >= CAPI_MAXAPPL) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -/* - * /proc/capi/contrstats: - * cnr nrecvctlpkt nrecvdatapkt nsentctlpkt nsentdatapkt - */ -static int proc_contrstats_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_ctr *cp; - int i; - int len = 0; - off_t begin = 0; - - for (i=0; i < CAPI_MAXCONTR; i++) { - cp = &cards[i]; - if (cp->cardstate == CARD_FREE) continue; - len += sprintf(page+len, "%d %lu %lu %lu %lu\n", - cp->cnr, - cp->nrecvctlpkt, - cp->nrecvdatapkt, - cp->nsentctlpkt, - cp->nsentdatapkt); - if (len+begin > off+count) - goto endloop; - if (len+begin < off) { - begin += len; - len = 0; - } - } -endloop: - if (i >= CAPI_MAXCONTR) - *eof = 1; - if (off >= len+begin) - return 0; - *start = page + (begin-off); - return ((count < begin+len-off) ? count : begin+len-off); -} - -static struct procfsentries { - char *name; - mode_t mode; - int (*read_proc)(char *page, char **start, off_t off, - int count, int *eof, void *data); - struct proc_dir_entry *procent; -} procfsentries[] = { - { "capi", S_IFDIR, 0 }, - { "capi/applications", 0 , proc_applications_read_proc }, - { "capi/ncci", 0 , proc_ncci_read_proc }, - { "capi/driver", 0 , proc_driver_read_proc }, - { "capi/users", 0 , proc_users_read_proc }, - { "capi/controller", 0 , proc_controller_read_proc }, - { "capi/applstats", 0 , proc_applstats_read_proc }, - { "capi/contrstats", 0 , proc_contrstats_read_proc }, - { "capi/drivers", S_IFDIR, 0 }, - { "capi/controllers", S_IFDIR, 0 }, -}; - -static void proc_capi_init(void) -{ - int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); - int i; - - for (i=0; i < nelem; i++) { - struct procfsentries *p = procfsentries + i; - p->procent = create_proc_entry(p->name, p->mode, 0); - if (p->procent) p->procent->read_proc = p->read_proc; - } -} - -static void proc_capi_exit(void) -{ - int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]); - int i; - - for (i=nelem-1; i >= 0; i--) { - struct procfsentries *p = procfsentries + i; - if (p->procent) { - remove_proc_entry(p->name, 0); - p->procent = 0; - } - } -} - -/* -------- Notifier handling --------------------------------- */ - -static struct capi_notifier_list{ - struct capi_notifier *head; - struct capi_notifier *tail; -} notifier_list; - -static inline void notify_enqueue(struct capi_notifier *np) -{ - struct capi_notifier_list *q = ¬ifier_list; - unsigned long flags; - - save_flags(flags); - cli(); - if (q->tail) { - q->tail->next = np; - q->tail = np; - } else { - q->head = q->tail = np; - } - restore_flags(flags); -} - -static inline struct capi_notifier *notify_dequeue(void) -{ - struct capi_notifier_list *q = ¬ifier_list; - struct capi_notifier *np = 0; - unsigned long flags; - - save_flags(flags); - cli(); - if (q->head) { - np = q->head; - if ((q->head = np->next) == 0) - q->tail = 0; - np->next = 0; - } - restore_flags(flags); - return np; -} - -static int notify_push(unsigned int cmd, __u32 controller, - __u16 applid, __u32 ncci) -{ - struct capi_notifier *np; - - np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC); - if (!np) - return -1; - memset(np, 0, sizeof(struct capi_notifier)); - np->cmd = cmd; - np->controller = controller; - np->applid = applid; - np->ncci = ncci; - notify_enqueue(np); - MOD_INC_USE_COUNT; - queue_task(&tq_state_notify, &tq_immediate); - mark_bh(IMMEDIATE_BH); - return 0; -} - -/* -------- KCI_CONTRUP --------------------------------------- */ - -static void notify_up(__u32 contr) -{ - struct capi_interface_user *p; - - printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr); - spin_lock(&capi_users_lock); - for (p = capi_users; p; p = p->next) { - if (!p->callback) continue; - (*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile); - } - spin_unlock(&capi_users_lock); -} - -/* -------- KCI_CONTRDOWN ------------------------------------- */ - -static void notify_down(__u32 contr) -{ - struct capi_interface_user *p; - printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr); - spin_lock(&capi_users_lock); - for (p = capi_users; p; p = p->next) { - if (!p->callback) continue; - (*p->callback) (KCI_CONTRDOWN, contr, 0); - } - spin_unlock(&capi_users_lock); -} - -/* -------- KCI_NCCIUP ---------------------------------------- */ - -static void notify_ncciup(__u32 contr, __u16 applid, __u32 ncci) -{ - struct capi_interface_user *p; - struct capi_ncciinfo n; - n.applid = applid; - n.ncci = ncci; - /*printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);*/ - spin_lock(&capi_users_lock); - for (p = capi_users; p; p = p->next) { - if (!p->callback) continue; - (*p->callback) (KCI_NCCIUP, contr, &n); - } - spin_unlock(&capi_users_lock); -}; - -/* -------- KCI_NCCIDOWN -------------------------------------- */ - -static void notify_nccidown(__u32 contr, __u16 applid, __u32 ncci) -{ - struct capi_interface_user *p; - struct capi_ncciinfo n; - n.applid = applid; - n.ncci = ncci; - /*printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);*/ - spin_lock(&capi_users_lock); - for (p = capi_users; p; p = p->next) { - if (!p->callback) continue; - (*p->callback) (KCI_NCCIDOWN, contr, &n); - } - spin_unlock(&capi_users_lock); -}; - -/* ------------------------------------------------------------ */ - -static void inline notify_doit(struct capi_notifier *np) -{ - switch (np->cmd) { - case KCI_CONTRUP: - notify_up(np->controller); - break; - case KCI_CONTRDOWN: - notify_down(np->controller); - break; - case KCI_NCCIUP: - notify_ncciup(np->controller, np->applid, np->ncci); - break; - case KCI_NCCIDOWN: - notify_nccidown(np->controller, np->applid, np->ncci); - break; - } -} - -static void notify_handler(void *dummy) -{ - struct capi_notifier *np; - - while ((np = notify_dequeue()) != 0) { - notify_doit(np); - kfree(np); - MOD_DEC_USE_COUNT; - } -} - -/* -------- NCCI Handling ------------------------------------- */ - -static inline void mq_init(struct capi_ncci * np) -{ - int i; - np->msgidqueue = 0; - np->msgidlast = 0; - np->nmsg = 0; - memset(np->msgidpool, 0, sizeof(np->msgidpool)); - np->msgidfree = &np->msgidpool[0]; - for (i = 1; i < np->winsize; i++) { - np->msgidpool[i].next = np->msgidfree; - np->msgidfree = &np->msgidpool[i]; - } -} - -static inline int mq_enqueue(struct capi_ncci * np, __u16 msgid) -{ - struct msgidqueue *mq; - if ((mq = np->msgidfree) == 0) - return 0; - np->msgidfree = mq->next; - mq->msgid = msgid; - mq->next = 0; - if (np->msgidlast) - np->msgidlast->next = mq; - np->msgidlast = mq; - if (!np->msgidqueue) - np->msgidqueue = mq; - np->nmsg++; - return 1; -} - -static inline int mq_dequeue(struct capi_ncci * np, __u16 msgid) -{ - struct msgidqueue **pp; - for (pp = &np->msgidqueue; *pp; pp = &(*pp)->next) { - if ((*pp)->msgid == msgid) { - struct msgidqueue *mq = *pp; - *pp = mq->next; - if (mq == np->msgidlast) - np->msgidlast = 0; - mq->next = np->msgidfree; - np->msgidfree = mq; - np->nmsg--; - return 1; - } - } - return 0; -} - -static void controllercb_appl_registered(struct capi_ctr * card, __u16 appl) -{ -} - -static void controllercb_appl_released(struct capi_ctr * card, __u16 appl) -{ - struct capi_ncci **pp, **nextpp; - for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) { - if (NCCI2CTRL((*pp)->ncci) == card->cnr) { - struct capi_ncci *np = *pp; - *pp = np->next; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x down!\n", appl, np->ncci); - kfree(np); - APPL(appl)->nncci--; - nextpp = pp; - } else { - nextpp = &(*pp)->next; - } - } - 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 managment - */ - -static void controllercb_new_ncci(struct capi_ctr * card, - __u16 appl, __u32 ncci, __u32 winsize) -{ - struct capi_ncci *np; - if (!VALID_APPLID(appl)) { - printk(KERN_ERR "avmb1_handle_new_ncci: illegal appl %d\n", appl); - return; - } - if ((np = (struct capi_ncci *) kmalloc(sizeof(struct capi_ncci), GFP_ATOMIC)) == 0) { - printk(KERN_ERR "capi_new_ncci: alloc failed ncci 0x%x\n", ncci); - return; - } - if (winsize > CAPI_MAXDATAWINDOW) { - printk(KERN_ERR "capi_new_ncci: winsize %d too big, set to %d\n", - winsize, CAPI_MAXDATAWINDOW); - winsize = CAPI_MAXDATAWINDOW; - } - np->applid = appl; - np->ncci = ncci; - np->winsize = winsize; - mq_init(np); - np->next = APPL(appl)->nccilist; - APPL(appl)->nccilist = np; - APPL(appl)->nncci++; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x up\n", appl, ncci); - - notify_push(KCI_NCCIUP, CARDNR(card), appl, ncci); -} - -static void controllercb_free_ncci(struct capi_ctr * card, - __u16 appl, __u32 ncci) -{ - struct capi_ncci **pp; - if (!VALID_APPLID(appl)) { - printk(KERN_ERR "free_ncci: illegal appl %d\n", appl); - return; - } - for (pp = &APPL(appl)->nccilist; *pp; pp = &(*pp)->next) { - if ((*pp)->ncci == ncci) { - struct capi_ncci *np = *pp; - *pp = np->next; - kfree(np); - APPL(appl)->nncci--; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x down\n", appl, ncci); - notify_push(KCI_NCCIDOWN, CARDNR(card), appl, ncci); - return; - } - } - printk(KERN_ERR "free_ncci: ncci 0x%x not found\n", ncci); -} - - -static struct capi_ncci *find_ncci(struct capi_appl * app, __u32 ncci) -{ - struct capi_ncci *np; - for (np = app->nccilist; np; np = np->next) { - if (np->ncci == ncci) - return np; - } - return 0; -} - -/* -------- Receiver ------------------------------------------ */ - -static void recv_handler(void *dummy) -{ - struct sk_buff *skb; - - while ((skb = skb_dequeue(&recv_queue)) != 0) { - __u16 appl = CAPIMSG_APPID(skb->data); - struct capi_ncci *np; - if (!VALID_APPLID(appl)) { - printk(KERN_ERR "kcapi: recv_handler: applid %d ? (%s)\n", - appl, capi_message2str(skb->data)); - kfree_skb(skb); - continue; - } - if (APPL(appl)->signal == 0) { - printk(KERN_ERR "kcapi: recv_handler: applid %d has no signal function\n", - appl); - kfree_skb(skb); - continue; - } - if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF - && (np = find_ncci(APPL(appl), CAPIMSG_NCCI(skb->data))) != 0 - && mq_dequeue(np, CAPIMSG_MSGID(skb->data)) == 0) { - printk(KERN_ERR "kcapi: msgid %hu ncci 0x%x not on queue\n", - CAPIMSG_MSGID(skb->data), np->ncci); - } - if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { - APPL(appl)->nrecvdatapkt++; - } else { - APPL(appl)->nrecvctlpkt++; - } - skb_queue_tail(&APPL(appl)->recv_queue, skb); - (APPL(appl)->signal) (APPL(appl)->applid, APPL(appl)->param); - } -} - -static void controllercb_handle_capimsg(struct capi_ctr * card, - __u16 appl, struct sk_buff *skb) -{ - int showctl = 0; - __u8 cmd, subcmd; - - if (card->cardstate != CARD_RUNNING) { - printk(KERN_INFO "kcapi: controller %d not active, got: %s", - card->cnr, capi_message2str(skb->data)); - goto error; - } - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - if (cmd == CAPI_DATA_B3 && subcmd == CAPI_IND) { - card->nrecvdatapkt++; - if (card->traceflag > 2) showctl |= 2; - } else { - card->nrecvctlpkt++; - if (card->traceflag) showctl |= 2; - } - showctl |= (card->traceflag & 1); - if (showctl & 2) { - if (showctl & 1) { - printk(KERN_DEBUG "kcapi: got [0x%lx] id#%d %s len=%u\n", - (unsigned long) card->cnr, - CAPIMSG_APPID(skb->data), - capi_cmd2str(cmd, subcmd), - CAPIMSG_LEN(skb->data)); - } else { - printk(KERN_DEBUG "kcapi: got [0x%lx] %s\n", - (unsigned long) card->cnr, - capi_message2str(skb->data)); - } - - } - skb_queue_tail(&recv_queue, skb); - queue_task(&tq_recv_notify, &tq_immediate); - mark_bh(IMMEDIATE_BH); - return; - -error: - kfree_skb(skb); -} - -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); - - notify_push(KCI_CONTRUP, CARDNR(card), 0, 0); -} - -static void controllercb_reseted(struct capi_ctr * card) -{ - __u16 appl; - - if (card->cardstate == CARD_FREE) - return; - if (card->cardstate == CARD_DETECTED) - return; - - card->cardstate = CARD_DETECTED; - - memset(card->manu, 0, sizeof(card->manu)); - memset(&card->version, 0, sizeof(card->version)); - memset(&card->profile, 0, sizeof(card->profile)); - memset(card->serial, 0, sizeof(card->serial)); - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - struct capi_ncci **pp, **nextpp; - for (pp = &APPL(appl)->nccilist; *pp; pp = nextpp) { - if (NCCI2CTRL((*pp)->ncci) == card->cnr) { - struct capi_ncci *np = *pp; - *pp = np->next; - printk(KERN_INFO "kcapi: appl %d ncci 0x%x forced down!\n", appl, np->ncci); - notify_push(KCI_NCCIDOWN, CARDNR(card), appl, np->ncci); - kfree(np); - nextpp = pp; - } else { - nextpp = &(*pp)->next; - } - } - } - - printk(KERN_NOTICE "kcapi: card %d down.\n", CARDNR(card)); - - notify_push(KCI_CONTRDOWN, CARDNR(card), 0, 0); -} - -static void controllercb_suspend_output(struct capi_ctr *card) -{ - if (!card->blocked) { - printk(KERN_DEBUG "kcapi: card %d suspend\n", CARDNR(card)); - card->blocked = 1; - } -} - -static void controllercb_resume_output(struct capi_ctr *card) -{ - if (card->blocked) { - printk(KERN_DEBUG "kcapi: card %d resume\n", CARDNR(card)); - card->blocked = 0; - } -} - -/* ------------------------------------------------------------- */ - - -struct capi_ctr * -drivercb_attach_ctr(struct capi_driver *driver, char *name, void *driverdata) -{ - struct capi_ctr *card, **pp; - int i; - - for (i=0; i < CAPI_MAXCONTR && cards[i].cardstate != CARD_FREE; i++) ; - - if (i == CAPI_MAXCONTR) { - printk(KERN_ERR "kcapi: out of controller slots\n"); - return 0; - } - card = &cards[i]; - memset(card, 0, sizeof(struct capi_ctr)); - card->driver = driver; - card->cnr = CARDNR(card); - strncpy(card->name, name, sizeof(card->name)); - card->cardstate = CARD_DETECTED; - card->blocked = 0; - card->driverdata = driverdata; - card->traceflag = showcapimsgs; - - card->ready = controllercb_ready; - card->reseted = controllercb_reseted; - card->suspend_output = controllercb_suspend_output; - card->resume_output = controllercb_resume_output; - card->handle_capimsg = controllercb_handle_capimsg; - card->appl_registered = controllercb_appl_registered; - card->appl_released = controllercb_appl_released; - card->new_ncci = controllercb_new_ncci; - card->free_ncci = controllercb_free_ncci; - - for (pp = &driver->controller; *pp; pp = &(*pp)->next) ; - card->next = 0; - *pp = card; - driver->ncontroller++; - sprintf(card->procfn, "capi/controllers/%d", card->cnr); - card->procent = create_proc_entry(card->procfn, 0, 0); - if (card->procent) { - card->procent->read_proc = - (int (*)(char *,char **,off_t,int,int *,void *)) - driver->ctr_read_proc; - card->procent->data = card; - } - - ncards++; - printk(KERN_NOTICE "kcapi: Controller %d: %s attached\n", - card->cnr, card->name); - return card; -} - -static int drivercb_detach_ctr(struct capi_ctr *card) -{ - struct capi_driver *driver = card->driver; - struct capi_ctr **pp; - - if (card->cardstate == CARD_FREE) - return 0; - if (card->cardstate != CARD_DETECTED) - controllercb_reseted(card); - for (pp = &driver->controller; *pp ; pp = &(*pp)->next) { - if (*pp == card) { - *pp = card->next; - driver->ncontroller--; - ncards--; - break; - } - } - if (card->procent) { - remove_proc_entry(card->procfn, 0); - card->procent = 0; - } - card->cardstate = CARD_FREE; - printk(KERN_NOTICE "kcapi: Controller %d: %s unregistered\n", - card->cnr, card->name); - return 0; -} - -/* ------------------------------------------------------------- */ - -/* fallback if no driver read_proc function defined by driver */ - -static int driver_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct capi_driver *driver = (struct capi_driver *)data; - int len = 0; - - len += sprintf(page+len, "%-16s %s\n", "name", driver->name); - len += sprintf(page+len, "%-16s %s\n", "revision", driver->revision); - - if (len < off) - return 0; - *eof = 1; - *start = page - off; - return ((count < len-off) ? count : len-off); -} - -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface di = { - drivercb_attach_ctr, - drivercb_detach_ctr, -}; - -struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver) -{ - struct capi_driver **pp; - - MOD_INC_USE_COUNT; - spin_lock(&drivers_lock); - for (pp = &drivers; *pp; pp = &(*pp)->next) ; - driver->next = 0; - *pp = driver; - spin_unlock(&drivers_lock); - printk(KERN_NOTICE "kcapi: driver %s attached\n", driver->name); - sprintf(driver->procfn, "capi/drivers/%s", driver->name); - driver->procent = create_proc_entry(driver->procfn, 0, 0); - if (driver->procent) { - if (driver->driver_read_proc) { - driver->procent->read_proc = - (int (*)(char *,char **,off_t,int,int *,void *)) - driver->driver_read_proc; - } else { - driver->procent->read_proc = driver_read_proc; - } - driver->procent->data = driver; - } - return &di; -} - -void detach_capi_driver(struct capi_driver *driver) -{ - struct capi_driver **pp; - spin_lock(&drivers_lock); - for (pp = &drivers; *pp && *pp != driver; pp = &(*pp)->next) ; - if (*pp) { - *pp = (*pp)->next; - printk(KERN_NOTICE "kcapi: driver %s detached\n", driver->name); - } else { - printk(KERN_ERR "kcapi: driver %s double detach ?\n", driver->name); - } - spin_unlock(&drivers_lock); - if (driver->procent) { - remove_proc_entry(driver->procfn, 0); - driver->procent = 0; - } - MOD_DEC_USE_COUNT; -} - -/* ------------------------------------------------------------- */ -/* -------- CAPI2.0 Interface ---------------------------------- */ -/* ------------------------------------------------------------- */ - -static __u16 capi_isinstalled(void) -{ - int i; - for (i = 0; i < CAPI_MAXCONTR; i++) { - if (cards[i].cardstate == CARD_RUNNING) - return CAPI_NOERROR; - } - return CAPI_REGNOTINSTALLED; -} - -static __u16 capi_register(capi_register_params * rparam, __u16 * applidp) -{ - int appl; - int i; - - if (rparam->datablklen < 128) - return CAPI_LOGBLKSIZETOSMALL; - - for (appl = 1; appl <= CAPI_MAXAPPL; appl++) { - if (APPL_IS_FREE(appl)) - break; - } - if (appl > CAPI_MAXAPPL) - return CAPI_TOOMANYAPPLS; - - APPL_MARK_USED(appl); - skb_queue_head_init(&APPL(appl)->recv_queue); - APPL(appl)->nncci = 0; - - memcpy(&APPL(appl)->rparam, rparam, sizeof(capi_register_params)); - - for (i = 0; i < CAPI_MAXCONTR; i++) { - if (cards[i].cardstate != CARD_RUNNING) - continue; - cards[i].driver->register_appl(&cards[i], appl, - &APPL(appl)->rparam); - } - *applidp = appl; - printk(KERN_INFO "kcapi: appl %d up\n", appl); - - return CAPI_NOERROR; -} - -static __u16 capi_release(__u16 applid) -{ - struct sk_buff *skb; - int i; - - if (!VALID_APPLID(applid) || APPL(applid)->releasing) - return CAPI_ILLAPPNR; - APPL(applid)->releasing++; - while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0) - kfree_skb(skb); - for (i = 0; i < CAPI_MAXCONTR; i++) { - if (cards[i].cardstate != CARD_RUNNING) - continue; - APPL(applid)->releasing++; - cards[i].driver->release_appl(&cards[i], applid); - } - APPL(applid)->releasing--; - if (APPL(applid)->releasing <= 0) { - APPL(applid)->signal = 0; - APPL_MARK_FREE(applid); - printk(KERN_INFO "kcapi: appl %d down\n", applid); - } - return CAPI_NOERROR; -} - -static __u16 capi_put_message(__u16 applid, struct sk_buff *skb) -{ - struct capi_ncci *np; - __u32 contr; - int showctl = 0; - __u8 cmd, subcmd; - - if (ncards == 0) - return CAPI_REGNOTINSTALLED; - if (!VALID_APPLID(applid)) - return CAPI_ILLAPPNR; - if (skb->len < 12 - || !capi_cmd_valid(CAPIMSG_COMMAND(skb->data)) - || !capi_subcmd_valid(CAPIMSG_SUBCOMMAND(skb->data))) - return CAPI_ILLCMDORSUBCMDORMSGTOSMALL; - contr = CAPIMSG_CONTROLLER(skb->data); - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) { - contr = 1; - if (CARD(contr)->cardstate != CARD_RUNNING) - return CAPI_REGNOTINSTALLED; - } - if (CARD(contr)->blocked) - return CAPI_SENDQUEUEFULL; - - cmd = CAPIMSG_COMMAND(skb->data); - subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - if (cmd == CAPI_DATA_B3 && subcmd== CAPI_REQ) { - if ((np = find_ncci(APPL(applid), CAPIMSG_NCCI(skb->data))) != 0 - && mq_enqueue(np, CAPIMSG_MSGID(skb->data)) == 0) - return CAPI_SENDQUEUEFULL; - CARD(contr)->nsentdatapkt++; - APPL(applid)->nsentdatapkt++; - if (CARD(contr)->traceflag > 2) showctl |= 2; - } else { - CARD(contr)->nsentctlpkt++; - APPL(applid)->nsentctlpkt++; - if (CARD(contr)->traceflag) showctl |= 2; - } - showctl |= (CARD(contr)->traceflag & 1); - if (showctl & 2) { - if (showctl & 1) { - printk(KERN_DEBUG "kcapi: put [0x%lx] id#%d %s len=%u\n", - (unsigned long) contr, - CAPIMSG_APPID(skb->data), - capi_cmd2str(cmd, subcmd), - CAPIMSG_LEN(skb->data)); - } else { - printk(KERN_DEBUG "kcapi: put [0x%lx] %s\n", - (unsigned long) contr, - capi_message2str(skb->data)); - } - - } - CARD(contr)->driver->send_message(CARD(contr), skb); - return CAPI_NOERROR; -} - -static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp) -{ - struct sk_buff *skb; - - if (!VALID_APPLID(applid)) - return CAPI_ILLAPPNR; - if ((skb = skb_dequeue(&APPL(applid)->recv_queue)) == 0) - return CAPI_RECEIVEQUEUEEMPTY; - *msgp = skb; - return CAPI_NOERROR; -} - -static __u16 capi_set_signal(__u16 applid, - void (*signal) (__u16 applid, void *param), - void *param) -{ - if (!VALID_APPLID(applid)) - return CAPI_ILLAPPNR; - APPL(applid)->signal = signal; - APPL(applid)->param = param; - return CAPI_NOERROR; -} - -static __u16 capi_get_manufacturer(__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN]) -{ - if (contr == 0) { - strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return CAPI_REGNOTINSTALLED; - - strncpy(buf, CARD(contr)->manu, CAPI_MANUFACTURER_LEN); - return CAPI_NOERROR; -} - -static __u16 capi_get_version(__u32 contr, struct capi_version *verp) -{ - if (contr == 0) { - *verp = driver_version; - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return CAPI_REGNOTINSTALLED; - - memcpy((void *) verp, &CARD(contr)->version, sizeof(capi_version)); - return CAPI_NOERROR; -} - -static __u16 capi_get_serial(__u32 contr, __u8 serial[CAPI_SERIAL_LEN]) -{ - if (contr == 0) { - strncpy(serial, driver_serial, CAPI_SERIAL_LEN); - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return CAPI_REGNOTINSTALLED; - - strncpy((void *) serial, CARD(contr)->serial, CAPI_SERIAL_LEN); - return CAPI_NOERROR; -} - -static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp) -{ - if (contr == 0) { - profp->ncontroller = ncards; - return CAPI_NOERROR; - } - if (!VALID_CARD(contr) || CARD(contr)->cardstate != CARD_RUNNING) - return CAPI_REGNOTINSTALLED; - - memcpy((void *) profp, &CARD(contr)->profile, - sizeof(struct capi_profile)); - return CAPI_NOERROR; -} - -static struct capi_driver *find_driver(char *name) -{ - struct capi_driver *dp; - spin_lock(&drivers_lock); - for (dp = drivers; dp; dp = dp->next) - if (strcmp(dp->name, name) == 0) - break; - spin_unlock(&drivers_lock); - return dp; -} - -#ifdef CONFIG_AVMB1_COMPAT -static int old_capi_manufacturer(unsigned int cmd, void *data) -{ - avmb1_loadandconfigdef ldef; - avmb1_extcarddef cdef; - avmb1_resetdef rdef; - avmb1_getdef gdef; - struct capi_driver *driver; - struct capi_ctr *card; - capicardparams cparams; - capiloaddata ldata; - int retval; - - switch (cmd) { - case AVMB1_ADDCARD: - case AVMB1_ADDCARD_WITH_TYPE: - if (cmd == AVMB1_ADDCARD) { - if ((retval = copy_from_user((void *) &cdef, data, - sizeof(avmb1_carddef)))) - return retval; - cdef.cardtype = AVM_CARDTYPE_B1; - } else { - if ((retval = copy_from_user((void *) &cdef, data, - sizeof(avmb1_extcarddef)))) - return retval; - } - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.cardnr = cdef.cardnr; - - switch (cdef.cardtype) { - case AVM_CARDTYPE_B1: - driver = find_driver("b1isa"); - break; - case AVM_CARDTYPE_T1: - driver = find_driver("t1isa"); - break; - default: - driver = 0; - break; - } - if (!driver) { - printk(KERN_ERR "kcapi: driver not loaded.\n"); - return -EIO; - } - if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver has no add card function.\n"); - return -EIO; - } - - return driver->add_card(driver, &cparams); - - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - - if (cmd == AVMB1_LOAD) { - if ((retval = copy_from_user((void *) &ldef, data, - sizeof(avmb1_loaddef)))) - return retval; - ldef.t4config.len = 0; - ldef.t4config.data = 0; - } else { - if ((retval = copy_from_user((void *) &ldef, data, - sizeof(avmb1_loadandconfigdef)))) - return retval; - } - if (!VALID_CARD(ldef.contr)) - return -ESRCH; - - card = CARD(ldef.contr); - if (card->cardstate == CARD_FREE) - return -ESRCH; - if (card->driver->load_firmware == 0) { - printk(KERN_DEBUG "kcapi: load: driver \%s\" has no load function\n", card->driver->name); - return -ESRCH; - } - - if (ldef.t4file.len <= 0) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: length of t4file is %d ?\n", ldef.t4file.len); - return -EINVAL; - } - if (ldef.t4file.data == 0) { - printk(KERN_DEBUG "kcapi: load: invalid parameter: dataptr is 0\n"); - return -EINVAL; - } - - ldata.firmware.user = 1; - ldata.firmware.data = ldef.t4file.data; - ldata.firmware.len = ldef.t4file.len; - ldata.configuration.user = 1; - ldata.configuration.data = ldef.t4config.data; - ldata.configuration.len = ldef.t4config.len; - - if (card->cardstate != CARD_DETECTED) { - printk(KERN_INFO "kcapi: load: contr=%d not in detect state\n", ldef.contr); - return -EBUSY; - } - card->cardstate = CARD_LOADING; - - retval = card->driver->load_firmware(card, &ldata); - - if (retval) { - card->cardstate = CARD_DETECTED; - return retval; - } - - while (card->cardstate != CARD_RUNNING) { - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); /* 0.1 sec */ - - if (signal_pending(current)) - return -EINTR; - } - return 0; - - case AVMB1_RESETCARD: - if ((retval = copy_from_user((void *) &rdef, data, - sizeof(avmb1_resetdef)))) - return retval; - if (!VALID_CARD(rdef.contr)) - return -ESRCH; - card = CARD(rdef.contr); - - if (card->cardstate == CARD_FREE) - return -ESRCH; - if (card->cardstate == CARD_DETECTED) - return 0; - - card->driver->reset_ctr(card); - - while (card->cardstate > CARD_DETECTED) { - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); /* 0.1 sec */ - - if (signal_pending(current)) - return -EINTR; - } - return 0; - - case AVMB1_GET_CARDINFO: - if ((retval = copy_from_user((void *) &gdef, data, - sizeof(avmb1_getdef)))) - return retval; - - if (!VALID_CARD(gdef.contr)) - return -ESRCH; - - card = CARD(gdef.contr); - - if (card->cardstate == CARD_FREE) - return -ESRCH; - - gdef.cardstate = card->cardstate; - if (card->driver == find_driver("t1isa")) - gdef.cardtype = AVM_CARDTYPE_T1; - else gdef.cardtype = AVM_CARDTYPE_B1; - - if ((retval = copy_to_user(data, (void *) &gdef, - sizeof(avmb1_getdef)))) - return retval; - - return 0; - - case AVMB1_REMOVECARD: - if ((retval = copy_from_user((void *) &rdef, data, - sizeof(avmb1_resetdef)))) - return retval; - - if (!VALID_CARD(rdef.contr)) - return -ESRCH; - card = CARD(rdef.contr); - - if (card->cardstate == CARD_FREE) - return -ESRCH; - - if (card->cardstate != CARD_DETECTED) - return -EBUSY; - - card->driver->remove_ctr(card); - - while (card->cardstate != CARD_FREE) { - - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ/10); /* 0.1 sec */ - - if (signal_pending(current)) - return -EINTR; - } - return 0; - } - return -EINVAL; -} -#endif - -static int capi_manufacturer(unsigned int cmd, void *data) -{ - struct capi_ctr *card; - int retval; - - switch (cmd) { -#ifdef CONFIG_AVMB1_COMPAT - case AVMB1_ADDCARD: - case AVMB1_ADDCARD_WITH_TYPE: - case AVMB1_LOAD: - case AVMB1_LOAD_AND_CONFIG: - case AVMB1_RESETCARD: - case AVMB1_GET_CARDINFO: - case AVMB1_REMOVECARD: - return old_capi_manufacturer(cmd, data); -#endif - case KCAPI_CMD_TRACE: - { - kcapi_flagdef fdef; - - if ((retval = copy_from_user((void *) &fdef, data, - sizeof(kcapi_flagdef)))) - return retval; - - if (!VALID_CARD(fdef.contr)) - return -ESRCH; - card = CARD(fdef.contr); - if (card->cardstate == CARD_FREE) - return -ESRCH; - card->traceflag = fdef.flag; - printk(KERN_INFO "kcapi: contr %d set trace=%d\n", - card->cnr, card->traceflag); - return 0; - } - - case KCAPI_CMD_ADDCARD: - { - struct capi_driver *driver; - capicardparams cparams; - kcapi_carddef cdef; - - if ((retval = copy_from_user((void *) &cdef, data, - sizeof(cdef)))) - return retval; - - cparams.port = cdef.port; - cparams.irq = cdef.irq; - cparams.membase = cdef.membase; - cparams.cardnr = cdef.cardnr; - cparams.cardtype = 0; - cdef.driver[sizeof(cdef.driver)-1] = 0; - - if ((driver = find_driver(cdef.driver)) == 0) { - printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", - cdef.driver); - return -ESRCH; - } - - if (!driver->add_card) { - printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); - return -EIO; - } - - return driver->add_card(driver, &cparams); - } - - default: - printk(KERN_ERR "kcapi: manufacturer command %d unknown.\n", - cmd); - break; - - } - return -EINVAL; -} - -struct capi_interface avmb1_interface = -{ - capi_isinstalled, - capi_register, - capi_release, - capi_put_message, - capi_get_message, - capi_set_signal, - capi_get_manufacturer, - capi_get_version, - capi_get_serial, - capi_get_profile, - capi_manufacturer -}; - -/* ------------------------------------------------------------- */ -/* -------- Exported Functions --------------------------------- */ -/* ------------------------------------------------------------- */ - -struct capi_interface *attach_capi_interface(struct capi_interface_user *userp) -{ - struct capi_interface_user *p; - - MOD_INC_USE_COUNT; - spin_lock(&capi_users_lock); - for (p = capi_users; p; p = p->next) { - if (p == userp) { - spin_unlock(&capi_users_lock); - printk(KERN_ERR "kcapi: double attach from %s\n", - userp->name); - MOD_DEC_USE_COUNT; - return 0; - } - } - userp->next = capi_users; - capi_users = userp; - spin_unlock(&capi_users_lock); - printk(KERN_NOTICE "kcapi: %s attached\n", userp->name); - - return &avmb1_interface; -} - -int detach_capi_interface(struct capi_interface_user *userp) -{ - struct capi_interface_user **pp; - - spin_lock(&capi_users_lock); - for (pp = &capi_users; *pp; pp = &(*pp)->next) { - if (*pp == userp) { - *pp = userp->next; - spin_unlock(&capi_users_lock); - userp->next = 0; - printk(KERN_NOTICE "kcapi: %s detached\n", userp->name); - MOD_DEC_USE_COUNT; - return 0; - } - } - spin_unlock(&capi_users_lock); - printk(KERN_ERR "kcapi: double detach from %s\n", userp->name); - return -1; -} - -/* ------------------------------------------------------------- */ -/* -------- Init & Cleanup ------------------------------------- */ -/* ------------------------------------------------------------- */ - -EXPORT_SYMBOL(attach_capi_interface); -EXPORT_SYMBOL(detach_capi_interface); -EXPORT_SYMBOL(attach_capi_driver); -EXPORT_SYMBOL(detach_capi_driver); - -#ifndef MODULE -#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA -extern int b1isa_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI -extern int b1pci_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA -extern int t1isa_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA -extern int b1pcmcia_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI -extern int t1pci_init(void); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_C4 -extern int c4_init(void); -#endif -#endif - -/* - * init / exit functions - */ - -#ifdef MODULE -#define kcapi_init init_module -#endif - -int kcapi_init(void) -{ - char *p; - char rev[10]; - - skb_queue_head_init(&recv_queue); - /* init_bh(CAPI_BH, do_capi_bh); */ - - tq_state_notify.routine = notify_handler; - tq_state_notify.data = 0; - - tq_recv_notify.routine = recv_handler; - tq_recv_notify.data = 0; - - proc_capi_init(); - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, "1.0"); - -#ifdef MODULE - printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev); -#else - printk(KERN_NOTICE "CAPI-driver Rev%s: started\n", rev); -#ifdef CONFIG_ISDN_DRV_AVMB1_B1ISA - (void)b1isa_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCI - (void)b1pci_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1ISA - (void)t1isa_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCMCIA - (void)b1pcmcia_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_T1PCI - (void)t1pci_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1_C4 - (void)c4_init(); -#endif -#endif - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - char rev[10]; - char *p; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else { - strcpy(rev, "1.0"); - } - - proc_capi_exit(); - printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev); -} -#endif diff --git a/drivers/isdn/avmb1/t1isa.c b/drivers/isdn/avmb1/t1isa.c deleted file mode 100644 index ee8721b7..00000000 --- a/drivers/isdn/avmb1/t1isa.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * $Id$ - * - * Module for AVM T1 HEMA-card. - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.9 2000/01/25 14:37:39 calle - * new message after successfull detection including card revision and - * used resources. - * - * Revision 1.8 1999/11/05 16:38:01 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.7 1999/09/15 08:16:03 calle - * Implementation of 64Bit extention complete. - * - * Revision 1.6 1999/09/07 09:02:53 calle - * SETDATA removed. Now inside the kernel the datapart of DATA_B3_REQ and - * DATA_B3_IND is always directly after the CAPI message. The "Data" member - * ist never used inside the kernel. - * - * Revision 1.5 1999/08/22 20:26:28 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.4 1999/07/09 15:05:50 keil - * compat.h is now isdn_compat.h - * - * Revision 1.3 1999/07/06 07:42:04 calle - * - changes in /proc interface - * - check and changed calls to [dev_]kfree_skb and [dev_]alloc_skb. - * - * Revision 1.2 1999/07/05 15:09:54 calle - * - renamed "appl_release" to "appl_released". - * - version und profile data now cleared on controller reset - * - extended /proc interface, to allow driver and controller specific - * informations to include by driver hackers. - * - * Revision 1.1 1999/07/01 15:26:44 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "capicmd.h" -#include "capiutil.h" -#include "capilli.h" -#include "avmcard.h" - -static char *revision = "$Revision$"; - -/* ------------------------------------------------------------- */ - -MODULE_AUTHOR("Carsten Paeth "); - -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface *di; - -/* ------------------------------------------------------------- */ - -static int hema_irq_table[16] = -{0, - 0, - 0, - 0x80, /* irq 3 */ - 0, - 0x90, /* irq 5 */ - 0, - 0xA0, /* irq 7 */ - 0, - 0xB0, /* irq 9 */ - 0xC0, /* irq 10 */ - 0xD0, /* irq 11 */ - 0xE0, /* irq 12 */ - 0, - 0, - 0xF0, /* irq 15 */ -}; - -static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr) -{ - unsigned char cregs[8]; - unsigned char reverse_cardnr; - unsigned long flags; - unsigned char dummy; - int i; - - reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1) - | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3); - cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf); - cregs[1] = 0x00; /* fast & slow link connected to CON1 */ - cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */ - cregs[3] = 0; - cregs[4] = 0x11; /* zero wait state */ - cregs[5] = hema_irq_table[irq & 0xf]; - cregs[6] = 0; - cregs[7] = 0; - - save_flags(flags); - cli(); - /* board reset */ - t1outp(base, T1_RESETBOARD, 0xf); - udelay(100 * 1000); - dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */ - - /* write config */ - dummy = (base >> 4) & 0xff; - for (i=1;i<=0xf;i++) t1outp(base, i, dummy); - t1outp(base, HEMA_PAL_ID & 0xf, dummy); - t1outp(base, HEMA_PAL_ID >> 4, cregs[0]); - for(i=1;i<7;i++) t1outp(base, 0, cregs[i]); - t1outp(base, ((base >> 4)) & 0x3, cregs[7]); - restore_flags(flags); - - udelay(100 * 1000); - t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); - t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); - udelay(10 * 1000); - t1outp(base, T1_FASTLINK+T1_RESETLINK, 1); - t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1); - udelay(100 * 1000); - t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); - t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); - udelay(10 * 1000); - t1outp(base, T1_FASTLINK+T1_ANALYSE, 0); - udelay(5 * 1000); - t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0); - - if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */ - return 1; - if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */ - return 2; - if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0) - return 3; - if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70) - return 4; - if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0) - return 5; - if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1) - return 6; - if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */ - return 7; - if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0) - return 8; - if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0) - return 9; - return 0; -} - -static void t1_handle_interrupt(avmcard * card) -{ - avmctrl_info *cinfo = &card->ctrlinfo[0]; - struct capi_ctr *ctrl = cinfo->capi_ctrl; - unsigned char b1cmd; - struct sk_buff *skb; - - unsigned ApplId; - unsigned MsgLen; - unsigned DataB3Len; - unsigned NCCI; - unsigned WindowSize; - - while (b1_rx_full(card->port)) { - - b1cmd = b1_get_byte(card->port); - - switch (b1cmd) { - - case RECEIVE_DATA_B3_IND: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - DataB3Len = t1_get_slice(card->port, card->databuf); - - if (MsgLen < 30) { /* not CAPI 64Bit */ - memset(card->msgbuf+MsgLen, 0, 30-MsgLen); - MsgLen = 30; - CAPIMSG_SETLEN(card->msgbuf, 30); - } - if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_MESSAGE: - - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { - printk(KERN_ERR "%s: incoming packet dropped\n", - card->name); - } else { - memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); - ctrl->handle_capimsg(ctrl, ApplId, skb); - } - break; - - case RECEIVE_NEW_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - WindowSize = b1_get_word(card->port); - - ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize); - - break; - - case RECEIVE_FREE_NCCI: - - ApplId = b1_get_word(card->port); - NCCI = b1_get_word(card->port); - - if (NCCI != 0xffffffff) - ctrl->free_ncci(ctrl, ApplId, NCCI); - else ctrl->appl_released(ctrl, ApplId); - break; - - case RECEIVE_START: - b1_put_byte(card->port, SEND_POLLACK); - ctrl->resume_output(ctrl); - break; - - case RECEIVE_STOP: - ctrl->suspend_output(ctrl); - break; - - case RECEIVE_INIT: - - cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); - b1_parse_version(cinfo); - printk(KERN_INFO "%s: %s-card (%s) now active\n", - card->name, - cinfo->version[VER_CARDTYPE], - cinfo->version[VER_DRIVER]); - ctrl->ready(ctrl); - break; - - case RECEIVE_TASK_READY: - ApplId = (unsigned) b1_get_word(card->port); - MsgLen = t1_get_slice(card->port, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: task %d \"%s\" ready.\n", - card->name, ApplId, card->msgbuf); - break; - - case RECEIVE_DEBUGMSG: - MsgLen = t1_get_slice(card->port, card->msgbuf); - card->msgbuf[MsgLen--] = 0; - while ( MsgLen >= 0 - && ( card->msgbuf[MsgLen] == '\n' - || card->msgbuf[MsgLen] == '\r')) - card->msgbuf[MsgLen--] = 0; - printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); - break; - - case 0xff: - printk(KERN_ERR "%s: card reseted ?\n", card->name); - return; - default: - printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", - card->name, b1cmd); - return; - } - } -} - -/* ------------------------------------------------------------- */ - -static void t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs) -{ - avmcard *card; - - card = (avmcard *) devptr; - - if (!card) { - printk(KERN_WARNING "t1isa: interrupt: wrong device\n"); - return; - } - if (card->interrupt) { - printk(KERN_ERR "%s: reentering interrupt hander.\n", - card->name); - return; - } - - card->interrupt = 1; - - t1_handle_interrupt(card); - - card->interrupt = 0; -} -/* ------------------------------------------------------------- */ - -static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - int retval; - - t1_disable_irq(port); - b1_reset(port); - - if ((retval = b1_load_t4file(card, &data->firmware))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load t4file!!\n", - card->name); - return retval; - } - - if (data->configuration.len > 0 && data->configuration.data) { - if ((retval = b1_load_config(card, &data->configuration))) { - b1_reset(port); - printk(KERN_ERR "%s: failed to load config!!\n", - card->name); - return retval; - } - } - - if (!b1_loaded(card)) { - printk(KERN_ERR "%s: failed to load t4file.\n", card->name); - return -EIO; - } - - save_flags(flags); - cli(); - b1_setinterrupt(port, card->irq, card->cardtype); - b1_put_byte(port, SEND_INIT); - b1_put_word(port, AVM_NAPPS); - b1_put_word(port, AVM_NCCI_PER_CHANNEL*30); - b1_put_word(port, ctrl->cnr - 1); - restore_flags(flags); - - return 0; -} - -void t1isa_reset_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - t1_disable_irq(port); - b1_reset(port); - b1_reset(port); - - memset(cinfo->version, 0, sizeof(cinfo->version)); - ctrl->reseted(ctrl); -} - -static void t1isa_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - - t1_disable_irq(port); - b1_reset(port); - b1_reset(port); - t1_reset(port); - - di->detach_ctr(ctrl); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - - MOD_DEC_USE_COUNT; -} - -/* ------------------------------------------------------------- */ - -static int t1isa_add_card(struct capi_driver *driver, struct capicardparams *p) -{ - struct capi_ctr *ctrl; - avmctrl_info *cinfo; - avmcard *card; - int retval; - - MOD_INC_USE_COUNT; - - card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); - - if (!card) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card, 0, sizeof(avmcard)); - cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(cinfo, 0, sizeof(avmctrl_info)); - card->ctrlinfo = cinfo; - cinfo->card = card; - sprintf(card->name, "t1isa-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->cardtype = avm_t1isa; - card->cardnr = p->cardnr; - - if (!(((card->port & 0x7) == 0) && ((card->port & 0x30) != 0x30))) { - printk(KERN_WARNING "%s: illegal port 0x%x.\n", - driver->name, card->port); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EINVAL; - } - - if (check_region(card->port, AVMB1_PORTLEN)) { - printk(KERN_WARNING - "%s: ports 0x%03x-0x%03x in use.\n", - driver->name, card->port, card->port + AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - if (hema_irq_table[card->irq & 0xf] == 0) { - printk(KERN_WARNING "%s: irq %d not valid.\n", - driver->name, card->irq); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EINVAL; - } - for (ctrl = driver->controller; ctrl; ctrl = ctrl->next) { - avmcard *cardp = ((avmctrl_info *)(ctrl->driverdata))->card; - if (cardp->cardnr == card->cardnr) { - printk(KERN_WARNING "%s: card with number %d already installed at 0x%x.\n", - driver->name, card->cardnr, cardp->port); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - } - if ((retval = t1_detectandinit(card->port, card->irq, card->cardnr)) != 0) { - printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", - driver->name, card->port, retval); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - t1_disable_irq(card->port); - b1_reset(card->port); - - request_region(p->port, AVMB1_PORTLEN, card->name); - - retval = request_irq(card->irq, t1isa_interrupt, 0, card->name, card); - if (retval) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", - driver->name, card->irq); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); - if (!cinfo->capi_ctrl) { - printk(KERN_ERR "%s: attach controller failed.\n", - driver->name); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - printk(KERN_INFO - "%s: AVM T1 ISA at i/o %#x, irq %d, card %d\n", - driver->name, card->port, card->irq, card->cardnr); - - return 0; -} - -static void t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - unsigned int port = card->port; - unsigned long flags; - __u16 len = CAPIMSG_LEN(skb->data); - __u8 cmd = CAPIMSG_COMMAND(skb->data); - __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data); - - save_flags(flags); - cli(); - if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) { - __u16 dlen = CAPIMSG_DATALEN(skb->data); - b1_put_byte(port, SEND_DATA_B3_REQ); - t1_put_slice(port, skb->data, len); - t1_put_slice(port, skb->data + len, dlen); - } else { - b1_put_byte(port, SEND_MESSAGE); - t1_put_slice(port, skb->data, len); - } - restore_flags(flags); - dev_kfree_skb(skb); -} -/* ------------------------------------------------------------- */ - -static char *t1isa_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d %d", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->cardnr : 0 - ); - return cinfo->infobuf; -} - - -/* ------------------------------------------------------------- */ - -static struct capi_driver t1isa_driver = { - "t1isa", - "0.0", - t1isa_load_firmware, - t1isa_reset_ctr, - t1isa_remove_ctr, - b1_register_appl, - b1_release_appl, - t1isa_send_message, - - t1isa_procinfo, - b1ctl_read_proc, - 0, /* use standard driver_read_proc */ - - t1isa_add_card, -}; - -#ifdef MODULE -#define t1isa_init init_module -void cleanup_module(void); -#endif - -int t1isa_init(void) -{ - struct capi_driver *driver = &t1isa_driver; - char *p; - - if ((p = strchr(revision, ':'))) { - strncpy(driver->revision, p + 1, sizeof(driver->revision)); - p = strchr(driver->revision, '$'); - *p = 0; - } - - printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); - - di = attach_capi_driver(driver); - - if (!di) { - printk(KERN_ERR "%s: failed to attach capi_driver\n", - driver->name); - return -EIO; - } - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - detach_capi_driver(&t1isa_driver); -} -#endif diff --git a/drivers/isdn/avmb1/t1pci.c b/drivers/isdn/avmb1/t1pci.c deleted file mode 100644 index 20542035..00000000 --- a/drivers/isdn/avmb1/t1pci.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * $Id$ - * - * Module for AVM T1 PCI-card. - * - * (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.4 2000/01/25 14:33:38 calle - * - Added Support AVM B1 PCI V4.0 (tested with prototype) - * - splitted up t1pci.c into b1dma.c for common function with b1pciv4 - * - support for revision register - * - * Revision 1.3 1999/11/13 21:27:16 keil - * remove KERNELVERSION - * - * Revision 1.2 1999/11/05 16:38:02 calle - * Cleanups before kernel 2.4: - * - Changed all messages to use card->name or driver->name instead of - * constant string. - * - Moved some data from struct avmcard into new struct avmctrl_info. - * Changed all lowlevel capi driver to match the new structur. - * - * Revision 1.1 1999/10/26 15:31:42 calle - * Added driver for T1-PCI card. - * - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "capicmd.h" -#include "capiutil.h" -#include "capilli.h" -#include "avmcard.h" - -static char *revision = "$Revision$"; - -#undef CONFIG_T1PCI_DEBUG -#undef CONFIG_T1PCI_POLLDEBUG - -/* ------------------------------------------------------------- */ - -#ifndef PCI_VENDOR_ID_AVM -#define PCI_VENDOR_ID_AVM 0x1244 -#endif - -#ifndef PCI_DEVICE_ID_AVM_T1 -#define PCI_DEVICE_ID_AVM_T1 0x1200 -#endif - -/* ------------------------------------------------------------- */ - -MODULE_AUTHOR("Carsten Paeth "); - -/* ------------------------------------------------------------- */ - -static struct capi_driver_interface *di; - -/* ------------------------------------------------------------- */ - -static void t1pci_remove_ctr(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - avmcard *card = cinfo->card; - - b1dma_reset(card); - - di->detach_ctr(ctrl); - free_irq(card->irq, card); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - release_region(card->port, AVMB1_PORTLEN); - ctrl->driverdata = 0; - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - - MOD_DEC_USE_COUNT; -} - -/* ------------------------------------------------------------- */ - -static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p) -{ - unsigned long base, page_offset; - avmcard *card; - avmctrl_info *cinfo; - int retval; - - MOD_INC_USE_COUNT; - - card = (avmcard *) kmalloc(sizeof(avmcard), GFP_ATOMIC); - - if (!card) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card, 0, sizeof(avmcard)); - card->dma = (avmcard_dmainfo *) kmalloc(sizeof(avmcard_dmainfo), GFP_ATOMIC); - if (!card->dma) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(card->dma, 0, sizeof(avmcard_dmainfo)); - cinfo = (avmctrl_info *) kmalloc(sizeof(avmctrl_info), GFP_ATOMIC); - if (!cinfo) { - printk(KERN_WARNING "%s: no memory.\n", driver->name); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -ENOMEM; - } - memset(cinfo, 0, sizeof(avmctrl_info)); - card->ctrlinfo = cinfo; - cinfo->card = card; - sprintf(card->name, "t1pci-%x", p->port); - card->port = p->port; - card->irq = p->irq; - card->membase = p->membase; - card->cardtype = avm_t1pci; - - if (check_region(card->port, AVMB1_PORTLEN)) { - printk(KERN_WARNING - "%s: ports 0x%03x-0x%03x in use.\n", - driver->name, card->port, card->port + AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - base = card->membase & PAGE_MASK; - page_offset = card->membase - base; - card->mbase = ioremap_nocache(base, page_offset + 64); - if (card->mbase) { - card->mbase += page_offset; - } else { - printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n", - driver->name, card->membase); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - - b1dma_reset(card); - - if ((retval = t1pci_detect(card)) != 0) { - printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n", - driver->name, card->port, retval); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EIO; - } - b1dma_reset(card); - - request_region(p->port, AVMB1_PORTLEN, card->name); - - retval = request_irq(card->irq, b1dma_interrupt, SA_SHIRQ, card->name, card); - if (retval) { - printk(KERN_ERR "%s: unable to get IRQ %d.\n", - driver->name, card->irq); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - - cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo); - if (!cinfo->capi_ctrl) { - printk(KERN_ERR "%s: attach controller failed.\n", driver->name); - iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK)); - free_irq(card->irq, card); - release_region(card->port, AVMB1_PORTLEN); - kfree(card->ctrlinfo); - kfree(card->dma); - kfree(card); - MOD_DEC_USE_COUNT; - return -EBUSY; - } - card->cardnr = cinfo->capi_ctrl->cnr; - - skb_queue_head_init(&card->dma->send_queue); - - printk(KERN_INFO - "%s: AVM T1 PCI at i/o %#x, irq %d, mem %#lx\n", - driver->name, card->port, card->irq, card->membase); - - return 0; -} - -/* ------------------------------------------------------------- */ - -static char *t1pci_procinfo(struct capi_ctr *ctrl) -{ - avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); - - if (!cinfo) - return ""; - sprintf(cinfo->infobuf, "%s %s 0x%x %d 0x%lx", - cinfo->cardname[0] ? cinfo->cardname : "-", - cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", - cinfo->card ? cinfo->card->port : 0x0, - cinfo->card ? cinfo->card->irq : 0, - cinfo->card ? cinfo->card->membase : 0 - ); - return cinfo->infobuf; -} - -/* ------------------------------------------------------------- */ - -static struct capi_driver t1pci_driver = { - "t1pci", - "0.0", - b1dma_load_firmware, - b1dma_reset_ctr, - t1pci_remove_ctr, - b1dma_register_appl, - b1dma_release_appl, - b1dma_send_message, - - t1pci_procinfo, - b1dmactl_read_proc, - 0, /* use standard driver_read_proc */ - - 0, /* no add_card function */ -}; - -#ifdef MODULE -#define t1pci_init init_module -void cleanup_module(void); -#endif - -static int ncards = 0; - -int t1pci_init(void) -{ - struct capi_driver *driver = &t1pci_driver; - struct pci_dev *dev = NULL; - char *p; - int retval; - - if ((p = strchr(revision, ':'))) { - strncpy(driver->revision, p + 1, sizeof(driver->revision)); - p = strchr(driver->revision, '$'); - *p = 0; - } - - printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision); - - di = attach_capi_driver(driver); - - if (!di) { - printk(KERN_ERR "%s: failed to attach capi_driver\n", - driver->name); - return -EIO; - } - -#ifdef CONFIG_PCI - if (!pci_present()) { - printk(KERN_ERR "%s: no PCI bus present\n", driver->name); - detach_capi_driver(driver); - return -EIO; - } - - while ((dev = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, dev))) { - struct capicardparams param; - - param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK; - param.irq = dev->irq; - param.membase = get_pcibase(dev, 0) & PCI_BASE_ADDRESS_MEM_MASK; - - printk(KERN_INFO - "%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n", - driver->name, param.port, param.irq, param.membase); - retval = t1pci_add_card(driver, ¶m); - if (retval != 0) { - printk(KERN_ERR - "%s: no AVM-T1-PCI at i/o %#x, irq %d detected, mem %#x\n", - driver->name, param.port, param.irq, param.membase); -#ifdef MODULE - cleanup_module(); -#endif - return retval; - } - ncards++; - } - if (ncards) { - printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n", - driver->name, ncards); - return 0; - } - printk(KERN_ERR "%s: NO T1-PCI card detected\n", driver->name); - return -ESRCH; -#else - printk(KERN_ERR "%s: kernel not compiled with PCI.\n", driver->name); - return -EIO; -#endif -} - -#ifdef MODULE -void cleanup_module(void) -{ - detach_capi_driver(&t1pci_driver); -} -#endif diff --git a/drivers/isdn/debugvar.c b/drivers/isdn/debugvar.c deleted file mode 100644 index 5a66d2df..00000000 --- a/drivers/isdn/debugvar.c +++ /dev/null @@ -1,328 +0,0 @@ -/* $Id$ - - * Variable-debugging for isdn4linux. - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995 Thinking Objects Software GmbH Wuerzburg - * - * This file is part of Isdn4Linux. - * - * 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. - * - * $Log$ - * Revision 1.6 1999/04/12 12:33:07 fritz - * Changes from 2.0 tree. - * - * Revision 1.5 1997/02/03 23:34:51 fritz - * Reformatted - * - * Revision 1.4 1996/04/30 07:55:50 fritz - * Disabled mmap. - * - * Revision 1.3 1996/04/28 15:19:23 fritz - * adapted to new ioctl names. - * - * Revision 1.2 1996/01/04 02:46:16 fritz - * Changed copying policy to GPL. - * - * Revision 1.1 1995/12/18 18:22:52 fritz - * Initial revision - * - */ - -#include -#include -/* #include */ -#include -#include -#include -#include - -#include -#include - -typedef unsigned char uchar; -int mem_fd; - -#if 0 /* Weiss der Teufel, warum das nicht mit mmap geht */ -uchar -* mapmem(ulong location, long size) -{ - ulong mmseg; - ulong mmsize; - ulong addr; - ulong offset; - - mmseg = location & 0xffffe000L; - mmsize = (location - mmseg + size) + 0x1000; - offset = location - mmseg; - addr = (ulong) mmap(0, mmsize, PROT_READ, MAP_SHARED, mem_fd, mmseg); - if ((int) addr == -1) { - perror("mmap"); - exit(1); - } - printf("mmap: loc=%08lx siz=%08lx mseg=%08lx msiz=%08lx ofs=%08lx adr=%08lx\n", location, size, mmseg, mmsize, offset, addr); - return ((uchar *) (addr + offset)); -} -#else -uchar -* mapmem(ulong location, long size) -{ - uchar *buffer; - - if ((buffer = malloc(size))) { - lseek(mem_fd, location, SEEK_SET); - read(mem_fd, buffer, size); - } else { - perror("malloc"); - exit(1); - } - return buffer; -} -#endif - -char * -dumpIntArray(int *arr, int count) -{ - static char buf[1024]; - char *p = buf; - int i; - - for (i = 0; i < count; i++) - p += sprintf(p, "%d%s", arr[i], (i < (count - 1)) ? ", " : "\0"); - return (buf); -} - -char * -dumpCharArray(char *arr, int count) -{ - static char buf[1024]; - char *p = buf; - int i; - - for (i = 0; i < count; i++) - p += sprintf(p, "%02x%s", (uchar) arr[i], (i < (count - 1)) ? ", " : "\0"); - return (buf); -} - -char * -dumpStringArray(char *arr, int count, int len) -{ - static char buf[1024]; - char *p = buf; - char *s = arr; - int i; - - for (i = 0; i < count; s += len, i++) - p += sprintf(p, "\"%s\"%s", s, (i < (count - 1)) ? ", " : "\0"); - return (buf); -} - -void -dumpDriver(ulong drvaddr) -{ - driver *drv = (driver *) mapmem(drvaddr, sizeof(driver)); - isdn_if *ifc = (isdn_if *) mapmem((ulong) drv->interface, sizeof(isdn_if)); - - printf(" online = %08lx\n", drv->online); - printf(" channels = %d\n", drv->channels); - printf(" locks = %d\n", drv->locks); - printf(" reject_bus = %d\n", drv->flags & DRV_FLAG_REJBUS); - printf(" running = %d\n", drv->flags & DRV_FLAG_RUNNING); - printf(" loaded = %d\n", drv->flags & DRV_FLAG_LOADED); - printf(" maxbufsize = %d\n", drv->maxbufsize); - printf(" pktcount = %ld\n", drv->pktcount); - printf(" stavail = %d\n", drv->stavail); - printf(" Interface @%08lx:\n", (ulong) drv->interface); - printf(" Id(ch) = %d\n", ifc->channels); - printf(" maxbufsize = %d\n", ifc->maxbufsize); - printf(" features = %08lx\n", ifc->features); -} - -void -dumpModem(modem mdm) -{ - int i; - atemu *atm; - modem_info *info; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - printf("mdm [%02d]\n", i); - printf(" msr = %08x\n", mdm.msr[i]); - printf(" mlr = %08x\n", mdm.mlr[i]); - printf(" refcount = %d\n", mdm.refcount); - printf(" online = %d\n", mdm.online[i]); - printf(" dialing = %d\n", mdm.dialing[i]); - printf(" rcvsched = %d\n", mdm.rcvsched[i]); - printf(" ncarrier = %d\n", mdm.ncarrier[i]); - printf(" atmodem:\n"); - atm = &mdm.atmodem[i]; - printf(" profile = \n %s\n", dumpCharArray(atm->mdmreg, ISDN_MODEM_NUMREG)); - printf(" mdmreg = \n %s\n", dumpCharArray(atm->mdmreg, ISDN_MODEM_NUMREG)); - printf(" msn = \"%s\"\n", atm->msn); - printf(" mdmcmdl = %d\n", atm->mdmcmdl); - printf(" pluscount = %d\n", atm->pluscount); - printf(" lastplus = %08x\n", atm->lastplus); - printf(" mdmcmd = \"%s\"\n", atm->mdmcmd); - printf(" info:\n"); - info = &mdm.info[i]; - printf(" magic = %08x\n", info->magic); - printf(" flags = %08x\n", info->flags); - printf(" type = %d\n", info->type); - printf(" x_char = %02x\n", info->x_char); - printf(" close_delay = %d\n", info->close_delay); - printf(" MCR = %08x\n", info->MCR); - printf(" line = %d\n", info->line); - printf(" count = %d\n", info->count); - printf(" blocked_open = %d\n", info->blocked_open); - printf(" session = %08lx\n", info->session); - printf(" pgrp = %08lx\n", info->pgrp); - printf(" isdn_driver = %d\n", info->isdn_driver); - printf(" isdn_channel = %d\n", info->isdn_channel); - printf(" drv_index = %d\n", info->drv_index); - printf(" xmit_size = %d\n", info->xmit_size); - printf(" xmit_count = %d\n", info->xmit_count); - } -} - -void -dumpNetPhone(ulong paddr) -{ - ulong pa = paddr; - isdn_net_phone *phone; - - while (pa) { - phone = (isdn_net_phone *) mapmem(pa, sizeof(isdn_net_phone)); - printf(" @%08lx: \"%s\"\n", pa, phone->num); - pa = (ulong) (phone->next); - } -} - -void -dumpNetDev(ulong devaddr) -{ - ulong nda = devaddr; - isdn_net_dev *ndev; - - while (nda) { - ndev = (isdn_net_dev *) mapmem(nda, sizeof(isdn_net_dev)); - printf("Net-Device @%08lx:\n", nda); - printf("dev. :\n"); - printf(" start = %d\n", ndev->dev.start); - printf(" tbusy = %ld\n", ndev->dev.tbusy); - printf(" interrupt = %d\n", ndev->dev.interrupt); - printf("local. :\n"); - printf(" name = \"%s\"\n", ndev->local.name); - printf(" isdn_device = %d\n", ndev->local.isdn_device); - printf(" isdn_channel = %d\n", ndev->local.isdn_channel); - printf(" ppp_minor = %d\n", ndev->local.ppp_minor); - printf(" pre_device = %d\n", ndev->local.pre_device); - printf(" pre_channel = %d\n", ndev->local.pre_channel); - printf(" exclusive = %d\n", ndev->local.exclusive); - printf(" flags = %d\n", ndev->local.flags); - printf(" dialstate = %d\n", ndev->local.dialstate); - printf(" dialretry = %d\n", ndev->local.dialretry); - printf(" dialmax = %d\n", ndev->local.dialmax); - printf(" msn = \"%s\"\n", ndev->local.msn); - printf(" dtimer = %d\n", ndev->local.dtimer); - printf(" p_encap = %d\n", ndev->local.p_encap); - printf(" l2_proto = %d\n", ndev->local.l2_proto); - printf(" l3_proto = %d\n", ndev->local.l3_proto); - printf(" huptimer = %d\n", ndev->local.huptimer); - printf(" charge = %d\n", ndev->local.charge); - printf(" chargetime = %08x\n", ndev->local.chargetime); - printf(" hupflags = %d\n", ndev->local.hupflags); - printf(" outgoing = %d\n", ndev->local.outgoing); - printf(" onhtime = %d\n", ndev->local.onhtime); - printf(" chargeint = %d\n", ndev->local.chargeint); - printf(" onum = %d\n", ndev->local.onum); - printf(" sqfull = %08x\n", ndev->local.sqfull); - printf(" sqfull_stamp = %08lx\n", ndev->local.sqfull_stamp); - printf(" master = -> %08x\n", (unsigned int) ndev->local.master); - printf(" slave = -> %08x\n", (unsigned int) ndev->local.slave); - if (ndev->local.phone[0]) { - printf(" phone[in]:\n"); - dumpNetPhone((ulong) ndev->local.phone[0]); - } else - printf(" phone[in] = NULL\n"); - if (ndev->local.phone[1]) { - printf(" phone[out]:\n"); - dumpNetPhone((ulong) ndev->local.phone[1]); - } else - printf(" phone[out] = NULL\n"); - printf(" dial = @%08lx\n", (ulong) ndev->local.dial); - nda = (ulong) (ndev->next); - } -} - -void -main(int argc, char *argv[], char *envp[]) -{ - int f; - int i; - static isdn_dev *my_isdndev; - ulong kaddr; - - printf("\nDebugger for isdn and icn Modules\n"); - f = open("/dev/isdnctrl", O_RDONLY); - if (ioctl(f, IIOCDBGVAR, &kaddr)) { - perror("ioctl IIOCDBGVAR"); - exit(-1); - } - close(f); - if ((mem_fd = open("/dev/kmem", O_RDWR)) < 0) { - perror("open /dev/kmem"); - exit(1); - } - printf("isdn-main-struct at %08lx (%d):\n", kaddr, sizeof(isdn_dev)); - my_isdndev = (isdn_dev *) mapmem(kaddr, sizeof(isdn_dev)); - printf("isdndev.flags = %d\n", my_isdndev->flags); - printf("isdndev.drivers = %d\n", my_isdndev->drivers); - printf("isdndev.channels = %d\n", my_isdndev->channels); - printf("isdndev.net_verbose = %d\n", my_isdndev->net_verbose); - printf("isdndev.modempoll = %d\n", my_isdndev->modempoll); - printf("isdndev.tflags = %d\n", my_isdndev->tflags); - printf("isdndev.global_flags = %d\n", my_isdndev->global_flags); - if (my_isdndev->infochain) { - printf("isdndev.infochain = @%08lx:\n", (ulong) my_isdndev->infochain); - } else - printf("isdndev.infochain = NULL\n"); - if (my_isdndev->info_waitq) { - printf("isdndev.info_waitq = @%08lx:\n", (ulong) my_isdndev->info_waitq); - } else - printf("isdndev.info_waitq = NULL\n"); - printf("isdndev.chanmap = %s\n", - dumpIntArray(my_isdndev->chanmap, ISDN_MAX_CHANNELS)); - printf("isdndev.drvmap = %s\n", - dumpIntArray(my_isdndev->drvmap, ISDN_MAX_CHANNELS)); - printf("isdndev.usage = %s\n", - dumpIntArray(my_isdndev->usage, ISDN_MAX_CHANNELS)); - printf("isdndev.num = %s\n", - dumpStringArray(my_isdndev->num[0], ISDN_MAX_CHANNELS, 20)); - printf("isdndev.m_idx = %s\n", - dumpIntArray(my_isdndev->m_idx, ISDN_MAX_CHANNELS)); - dumpModem(my_isdndev->mdm); - for (i = 0; i < ISDN_MAX_DRIVERS; i++) - if (my_isdndev->drv[i]) { - printf("isdndev.drv[%02d] = @%08lx:\n", i, (ulong) my_isdndev->drv[i]); - dumpDriver((ulong) (my_isdndev->drv[i])); - } - if (my_isdndev->netdev) { - printf("isdndev.netdev = @%08lx:\n", (ulong) my_isdndev->netdev); - dumpNetDev((ulong) my_isdndev->netdev); - } else - printf("isdndev.netdev = NULL\n"); - close(mem_fd); -} diff --git a/drivers/isdn/divert/Makefile b/drivers/isdn/divert/Makefile deleted file mode 100644 index 109c900d..00000000 --- a/drivers/isdn/divert/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -L_OBJS := -LX_OBJS := -M_OBJS := -MX_OBJS := -O_OBJS := -OX_OBJS := -L_TARGET := -O_TARGET := - -O_OBJS += isdn_divert.o divert_procfs.o -O_TARGET := dss1_divert.o -M_OBJS += dss1_divert.o -OX_OBJS += divert_init.o - -include $(TOPDIR)/Rules.make - - - - - - diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c deleted file mode 100644 index a82afa8f..00000000 --- a/drivers/isdn/divert/divert_init.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * $Id$ - * - * Module init for DSS1 diversion services for i4l. - * - * Copyright 1999 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. - * - * $Log$ - * Revision 1.3 1999/07/05 20:21:39 werner - * changes to use diversion sources for all kernel versions. - * removed static device, only proc filesystem used - * - * Revision 1.2 1999/07/04 21:37:30 werner - * Ported from kernel version 2.0 - * - * - * - */ - -#include -#include -#include "isdn_divert.h" - -/********************/ -/* needed externals */ -/********************/ -extern int printk(const char *fmt,...); - -/****************************************/ -/* structure containing interface to hl */ -/****************************************/ -isdn_divert_if divert_if = - { DIVERT_IF_MAGIC, /* magic value */ - DIVERT_CMD_REG, /* register cmd */ - ll_callback, /* callback routine from ll */ - NULL, /* command still not specified */ - NULL, /* drv_to_name */ - NULL, /* name_to_drv */ - }; - -/*************************/ -/* Module interface code */ -/* no cmd line parms */ -/*************************/ -int init_module(void) -{ int i; - - if (divert_dev_init()) - { printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n"); - return(-EIO); - } - if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) - { divert_dev_deinit(); - printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n",i); - return(-EIO); - } -#if (LINUX_VERSION_CODE < 0x020111) - register_symtab(0); -#endif - printk(KERN_INFO "dss1_divert module successfully installed\n"); - return(0); -} /* init_module */ - -/**********************/ -/* Module deinit code */ -/**********************/ -void cleanup_module(void) -{ int flags; - int i; - - save_flags(flags); - cli(); - divert_if.cmd = DIVERT_CMD_REL; /* release */ - if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) - { printk(KERN_WARNING "dss1_divert: error %d releasing module\n",i); - restore_flags(flags); - return; - } - if (divert_dev_deinit()) - { printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n"); - restore_flags(flags); - return; - } - restore_flags(flags); - deleterule(-1); /* delete all rules and free mem */ - deleteprocs(); - printk(KERN_INFO "dss1_divert module successfully removed \n"); -} /* cleanup_module */ - - diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c deleted file mode 100644 index 7f28ae9d..00000000 --- a/drivers/isdn/divert/divert_procfs.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * $Id$ - * - * Filesystem handling for the diversion supplementary services. - * - * Copyright 1998 by Werner Cornelius (werner@isdn4linux.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * 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. - * - * $Log$ - * Revision 1.6 2000/02/14 19:23:03 werner - * - * Changed handling of proc filesystem tables to a more portable version - * - * Revision 1.5 1999/09/14 20:31:01 werner - * - * Removed obsoleted functions for proc fs and synced with new ones. - * - * Revision 1.4 1999/08/06 07:42:48 calle - * Added COMPAT_HAS_NEW_WAITQ for rd_queue for newer kernels. - * - * Revision 1.3 1999/07/05 20:21:41 werner - * changes to use diversion sources for all kernel versions. - * removed static device, only proc filesystem used - * - * Revision 1.2 1999/07/04 21:37:31 werner - * Ported from kernel version 2.0 - * - * - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#ifdef CONFIG_PROC_FS -#include -#else -#include -#endif -#include -#include -#include "isdn_divert.h" - -/*********************************/ -/* Variables for interface queue */ -/*********************************/ -ulong if_used = 0; /* number of interface users */ -static struct divert_info *divert_info_head = NULL; /* head of queue */ -static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */ -#ifdef COMPAT_HAS_NEW_WAITQ -static wait_queue_head_t rd_queue; -#else -static struct wait_queue *rd_queue = 0; /* Queue IO */ -#endif - -/*********************************/ -/* put an info buffer into queue */ -/*********************************/ -void -put_info_buffer(char *cp) -{ - struct divert_info *ib; - int flags; - - if (if_used <= 0) - return; - if (!cp) - return; - if (!*cp) - return; - if (!(ib = (struct divert_info *) kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC))) - return; /* no memory */ - strcpy(ib->info_start, cp); /* set output string */ - ib->next = NULL; - save_flags(flags); - cli(); - ib->usage_cnt = if_used; - if (!divert_info_head) - divert_info_head = ib; /* new head */ - else - divert_info_tail->next = ib; /* follows existing messages */ - divert_info_tail = ib; /* new tail */ - restore_flags(flags); - - /* delete old entrys */ - while (divert_info_head->next) { - if ((divert_info_head->usage_cnt <= 0) && - (divert_info_head->next->usage_cnt <= 0)) { - ib = divert_info_head; - divert_info_head = divert_info_head->next; - kfree(ib); - } else - break; - } /* divert_info_head->next */ - wake_up_interruptible(&(rd_queue)); -} /* put_info_buffer */ - -/**********************************/ -/* deflection device read routine */ -/**********************************/ -static ssize_t -isdn_divert_read(struct file *file, char *buf, size_t count, loff_t * off) -{ - struct divert_info *inf; - int len; - - if (!*((struct divert_info **) file->private_data)) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - interruptible_sleep_on(&(rd_queue)); - } - if (!(inf = *((struct divert_info **) file->private_data))) - return (0); - - inf->usage_cnt--; /* new usage count */ - (struct divert_info **) file->private_data = &inf->next; /* next structure */ - if ((len = strlen(inf->info_start)) <= count) { - if (copy_to_user(buf, inf->info_start, len)) - return -EFAULT; - file->f_pos += len; - return (len); - } - return (0); -} /* isdn_divert_read */ - -/**********************************/ -/* deflection device write routine */ -/**********************************/ -static ssize_t -isdn_divert_write(struct file *file, const char *buf, size_t count, loff_t * off) -{ - return (-ENODEV); -} /* isdn_divert_write */ - - -/***************************************/ -/* select routines for various kernels */ -/***************************************/ -static unsigned int -isdn_divert_poll(struct file *file, poll_table * wait) -{ - unsigned int mask = 0; - - poll_wait(file, &(rd_queue), wait); - /* mask = POLLOUT | POLLWRNORM; */ - if (*((struct divert_info **) file->private_data)) { - mask |= POLLIN | POLLRDNORM; - } - return mask; -} /* isdn_divert_poll */ - -/****************/ -/* Open routine */ -/****************/ -static int -isdn_divert_open(struct inode *ino, struct file *filep) -{ - int flags; - - MOD_INC_USE_COUNT; - save_flags(flags); - cli(); - if_used++; - if (divert_info_head) - (struct divert_info **) filep->private_data = &(divert_info_tail->next); - else - (struct divert_info **) filep->private_data = &divert_info_head; - restore_flags(flags); - /* start_divert(); */ - return (0); -} /* isdn_divert_open */ - -/*******************/ -/* close routine */ -/*******************/ -static int -isdn_divert_close(struct inode *ino, struct file *filep) -{ - struct divert_info *inf; - int flags; - - save_flags(flags); - cli(); - if_used--; - inf = *((struct divert_info **) filep->private_data); - while (inf) { - inf->usage_cnt--; - inf = inf->next; - } - restore_flags(flags); - if (if_used <= 0) - while (divert_info_head) { - inf = divert_info_head; - divert_info_head = divert_info_head->next; - kfree(inf); - } - MOD_DEC_USE_COUNT; - return (0); -} /* isdn_divert_close */ - -/*********/ -/* IOCTL */ -/*********/ -static int -isdn_divert_ioctl(struct inode *inode, struct file *file, - uint cmd, ulong arg) -{ - divert_ioctl dioctl; - int i, flags; - divert_rule *rulep; - char *cp; - - if ((i = copy_from_user(&dioctl, (char *) arg, sizeof(dioctl)))) - return (i); - - switch (cmd) { - case IIOCGETVER: - dioctl.drv_version = DIVERT_IIOC_VERSION; /* set version */ - break; - - case IIOCGETDRV: - if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0) - return (-EINVAL); - break; - - case IIOCGETNAM: - cp = divert_if.drv_to_name(dioctl.getid.drvid); - if (!cp) - return (-EINVAL); - if (!*cp) - return (-EINVAL); - strcpy(dioctl.getid.drvnam, cp); - break; - - case IIOCGETRULE: - if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) - return (-EINVAL); - dioctl.getsetrule.rule = *rulep; /* copy data */ - break; - - case IIOCMODRULE: - if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx))) - return (-EINVAL); - save_flags(flags); - cli(); - *rulep = dioctl.getsetrule.rule; /* copy data */ - restore_flags(flags); - return (0); /* no copy required */ - break; - - case IIOCINSRULE: - return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule)); - break; - - case IIOCDELRULE: - return (deleterule(dioctl.getsetrule.ruleidx)); - break; - - case IIOCDODFACT: - return (deflect_extern_action(dioctl.fwd_ctrl.subcmd, - dioctl.fwd_ctrl.callid, - dioctl.fwd_ctrl.to_nr)); - - case IIOCDOCFACT: - case IIOCDOCFDIS: - case IIOCDOCFINT: - if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid)) - return (-EINVAL); /* invalid driver */ - if ((i = cf_command(dioctl.cf_ctrl.drvid, - (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2, - dioctl.cf_ctrl.cfproc, - dioctl.cf_ctrl.msn, - dioctl.cf_ctrl.service, - dioctl.cf_ctrl.fwd_nr, - &dioctl.cf_ctrl.procid))) - return (i); - break; - - default: - return (-EINVAL); - } /* switch cmd */ - return (copy_to_user((char *) arg, &dioctl, sizeof(dioctl))); /* success */ -} /* isdn_divert_ioctl */ - - -#ifdef CONFIG_PROC_FS -static loff_t -isdn_divert_lseek(struct file *file, loff_t offset, int orig) -{ - return -ESPIPE; -} - -static struct file_operations isdn_fops = -{ - isdn_divert_lseek, - isdn_divert_read, - isdn_divert_write, - NULL, /* isdn_readdir */ - isdn_divert_poll, /* isdn_poll */ - isdn_divert_ioctl, /* isdn_ioctl */ - NULL, /* isdn_mmap */ - isdn_divert_open, - NULL, /* flush */ - isdn_divert_close, - NULL /* fsync */ -}; - -#ifdef COMPAT_NO_SOFTNET -struct inode_operations divert_file_inode_operations; -#endif - -/****************************/ -/* isdn subdir in /proc/net */ -/****************************/ -static struct proc_dir_entry *isdn_proc_entry = NULL; -static struct proc_dir_entry *isdn_divert_entry = NULL; -#endif /* CONFIG_PROC_FS */ - -/***************************************************************************/ -/* divert_dev_init must be called before the proc filesystem may be used */ -/***************************************************************************/ -int -divert_dev_init(void) -{ - -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&rd_queue); -#endif - -#ifdef CONFIG_PROC_FS - isdn_proc_entry = create_proc_entry("isdn", S_IFDIR | S_IRUGO | S_IXUGO, proc_net); - if (!isdn_proc_entry) - return (-1); - isdn_divert_entry = create_proc_entry("divert", S_IFREG | S_IRUGO, isdn_proc_entry); - if (!isdn_divert_entry) { - remove_proc_entry("isdn", proc_net); - return (-1); - } -#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; -#endif - -#endif /* CONFIG_PROC_FS */ - - return (0); -} /* divert_dev_init */ - -/***************************************************************************/ -/* divert_dev_deinit must be called before leaving isdn when included as */ -/* a module. */ -/***************************************************************************/ -int -divert_dev_deinit(void) -{ - -#ifdef CONFIG_PROC_FS - remove_proc_entry("divert", isdn_proc_entry); - remove_proc_entry("isdn", proc_net); -#endif /* CONFIG_PROC_FS */ - - return (0); -} /* divert_dev_deinit */ diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c deleted file mode 100644 index 9073696d..00000000 --- a/drivers/isdn/divert/isdn_divert.c +++ /dev/null @@ -1,911 +0,0 @@ -/* - * $Id$ - * - * DSS1 main diversion supplementary handling for i4l. - * - * Copyright 1999 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. - * - * $Log$ - * Revision 1.4 1999/08/25 20:02:21 werner - * Changed return values for stat_icall(w) from 3->4 and 4->5 because of conflicts - * with existing software definitions. (PtP incomplete called party number) - * - * Revision 1.3 1999/08/22 20:26:35 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.2 1999/07/04 21:37:32 werner - * Ported from kernel version 2.0 - * - * - * - */ - - - -#define __NO_VERSION__ -#include -#include -#include -#include "isdn_divert.h" - -/**********************************/ -/* structure keeping calling info */ -/**********************************/ -struct call_struc - { isdn_ctrl ics; /* delivered setup + driver parameters */ - ulong divert_id; /* Id delivered to user */ - unsigned char akt_state; /* actual state */ - char deflect_dest[35]; /* deflection destination */ - struct timer_list timer; /* timer control structure */ - char info[90]; /* device info output */ - struct call_struc *next; /* pointer to next entry */ - struct call_struc *prev; - }; - - -/********************************************/ -/* structure keeping deflection table entry */ -/********************************************/ -struct deflect_struc - { struct deflect_struc *next,*prev; - divert_rule rule; /* used rule */ - }; - - -/*****************************************/ -/* variables for main diversion services */ -/*****************************************/ -/* diversion/deflection processes */ -static struct call_struc *divert_head = NULL; /* head of remembered entrys */ -static ulong next_id = 1; /* next info id */ -static struct deflect_struc *table_head = NULL; -static struct deflect_struc *table_tail = NULL; -static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */ - -/***************************/ -/* timer callback function */ -/***************************/ -static void deflect_timer_expire(ulong arg) -{ int flags; - struct call_struc *cs = (struct call_struc *) arg; - - save_flags(flags); - cli(); - del_timer(&cs->timer); /* delete active timer */ - restore_flags(flags); - - switch(cs->akt_state) - { case DEFLECT_PROCEED: - cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */ - divert_if.ll_cmd(&cs->ics); - save_flags(flags); - cli(); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - restore_flags(flags); - break; - - case DEFLECT_ALERT: - cs->ics.command = ISDN_CMD_REDIR; /* protocol */ - strcpy(cs->ics.parm.setup.phone,cs->deflect_dest); - strcpy(cs->ics.parm.setup.eazmsn,"Testtext delayed"); - divert_if.ll_cmd(&cs->ics); - save_flags(flags); - cli(); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - restore_flags(flags); - break; - - case DEFLECT_AUTODEL: - default: - save_flags(flags); - cli(); - if (cs->prev) - cs->prev->next = cs->next; /* forward link */ - else - divert_head = cs->next; - if (cs->next) - cs->next->prev = cs->prev; /* back link */ - restore_flags(flags); - kfree(cs); - return; - - } /* switch */ -} /* deflect_timer_func */ - - -/*****************************************/ -/* handle call forwarding de/activations */ -/* 0 = deact, 1 = act, 2 = interrogate */ -/*****************************************/ -int cf_command(int drvid, int mode, - u_char proc, char *msn, - u_char service, char *fwd_nr, ulong *procid) -{ int retval,msnlen,flags; - int fwd_len; - char *p,*ielenp,tmp[60]; - struct call_struc *cs; - - if (strchr(msn,'.')) return(-EINVAL); /* subaddress not allowed in msn */ - if ((proc & 0x7F) > 2) return(-EINVAL); - proc &= 3; - p = tmp; - *p++ = 0x30; /* enumeration */ - ielenp = p++; /* remember total length position */ - *p++ = 0xa; /* proc tag */ - *p++ = 1; /* length */ - *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */ - *p++ = 0xa; /* service tag */ - *p++ = 1; /* length */ - *p++ = service; /* service to handle */ - - if (mode == 1) - { if (!*fwd_nr) return(-EINVAL); /* destination missing */ - if (strchr(fwd_nr,'.')) return(-EINVAL); /* subaddress not allowed */ - fwd_len = strlen(fwd_nr); - *p++ = 0x30; /* number enumeration */ - *p++ = fwd_len + 2; /* complete forward to len */ - *p++ = 0x80; /* fwd to nr */ - *p++ = fwd_len; /* length of number */ - strcpy(p,fwd_nr); /* copy number */ - p += fwd_len; /* pointer beyond fwd */ - } /* activate */ - - msnlen = strlen(msn); - *p++ = 0x80; /* msn number */ - if (msnlen > 1) - { *p++ = msnlen; /* length */ - strcpy(p,msn); - p += msnlen; - } - else *p++ = 0; - - *ielenp = p - ielenp - 1; /* set total IE length */ - - /* allocate mem for information struct */ - if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) - return(-ENOMEM); /* no memory */ - init_timer(&cs->timer); - cs->info[0] = '\0'; - cs->timer.function = deflect_timer_expire; - cs->timer.data = (ulong) cs; /* pointer to own structure */ - cs->ics.driver = drvid; - cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */ - cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */ - cs->ics.parm.dss1_io.proc = (mode == 1) ? 7: (mode == 2) ? 11:8; /* operation */ - cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */ - cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */ - cs->ics.parm.dss1_io.data = tmp; /* start of buffer */ - - save_flags(flags); - cli(); - cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */ - restore_flags(flags); - *procid = cs->ics.parm.dss1_io.ll_id; - - sprintf(cs->info,"%d 0x%lx %s%s 0 %s %0x %d%s%s\n", - (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT, - cs->ics.parm.dss1_io.ll_id, - (mode != 2) ? "" : "0 ", - divert_if.drv_to_name(cs->ics.driver), - msn, - service & 0xFF, - proc, - (mode != 1) ? "" : " 0 ", - (mode != 1) ? "" : fwd_nr); - - retval = divert_if.ll_cmd(&cs->ics); /* excute command */ - - if (!retval) - { cs->prev = NULL; - save_flags(flags); - cli(); - cs->next = divert_head; - divert_head = cs; - restore_flags(flags); - } - else - kfree(cs); - return(retval); -} /* cf_command */ - - -/****************************************/ -/* handle a external deflection command */ -/****************************************/ -int deflect_extern_action(u_char cmd, ulong callid, char *to_nr) -{ struct call_struc *cs; - isdn_ctrl ic; - int flags; - int i; - - if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */ - cs = divert_head; /* start of parameter list */ - while (cs) - { if (cs->divert_id == callid) break; /* found */ - cs = cs->next; - } /* search entry */ - if (!cs) return(-EINVAL); /* invalid callid */ - - ic.driver = cs->ics.driver; - ic.arg = cs->ics.arg; - i = -EINVAL; - if (cs->akt_state == DEFLECT_AUTODEL) return(i); /* no valid call */ - switch (cmd & 0x7F) - { case 0: /* hangup */ - del_timer(&cs->timer); - ic.command = ISDN_CMD_HANGUP; - i = divert_if.ll_cmd(&ic); - save_flags(flags); - cli(); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - restore_flags(flags); - break; - - case 1: /* alert */ - if (cs->akt_state == DEFLECT_ALERT) return(0); - cmd &= 0x7F; /* never wait */ - del_timer(&cs->timer); - ic.command = ISDN_CMD_ALERT; - if ((i = divert_if.ll_cmd(&ic))) - { save_flags(flags); - cli(); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - restore_flags(flags); - } - else - cs->akt_state = DEFLECT_ALERT; - break; - - case 2: /* redir */ - del_timer(&cs->timer); - strcpy(cs->ics.parm.setup.phone, to_nr); - strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual"); - ic.command = ISDN_CMD_REDIR; - if ((i = divert_if.ll_cmd(&ic))) - { save_flags(flags); - cli(); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - add_timer(&cs->timer); - restore_flags(flags); - } - else - cs->akt_state = DEFLECT_ALERT; - break; - - } /* switch */ - return(i); -} /* deflect_extern_action */ - -/********************************/ -/* insert a new rule before idx */ -/********************************/ -int insertrule(int idx, divert_rule *newrule) -{ struct deflect_struc *ds,*ds1; - int flags; - - if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc), - GFP_KERNEL))) - return(-ENOMEM); /* no memory */ - - ds->rule = *newrule; /* set rule */ - - save_flags(flags); - cli(); - - if (idx >= 0) - { ds1 = table_head; - while ((ds1) && (idx > 0)) - { idx--; - ds1 = ds1->next; - } - if (!ds1) idx = -1; - } - - if (idx < 0) - { ds->prev = table_tail; /* previous entry */ - ds->next = NULL; /* end of chain */ - if (ds->prev) - ds->prev->next = ds; /* last forward */ - else - table_head = ds; /* is first entry */ - table_tail = ds; /* end of queue */ - } - else - { ds->next = ds1; /* next entry */ - ds->prev = ds1->prev; /* prev entry */ - ds1->prev = ds; /* backward chain old element */ - if (!ds->prev) - table_head = ds; /* first element */ - } - - restore_flags(flags); - return(0); -} /* insertrule */ - -/***********************************/ -/* delete the rule at position idx */ -/***********************************/ -int deleterule(int idx) -{ struct deflect_struc *ds,*ds1; - int flags; - - if (idx < 0) - { save_flags(flags); - cli(); - ds = table_head; - table_head = NULL; - table_tail = NULL; - restore_flags(flags); - while (ds) - { ds1 = ds; - ds = ds->next; - kfree(ds1); - } - return(0); - } - - save_flags(flags); - cli(); - ds = table_head; - - while ((ds) && (idx > 0)) - { idx--; - ds = ds->next; - } - - if (!ds) - { restore_flags(flags); - return(-EINVAL); - } - - if (ds->next) - ds->next->prev = ds->prev; /* backward chain */ - else - table_tail = ds->prev; /* end of chain */ - - if (ds->prev) - ds->prev->next = ds->next; /* forward chain */ - else - table_head = ds->next; /* start of chain */ - - restore_flags(flags); - kfree(ds); - return(0); -} /* deleterule */ - -/*******************************************/ -/* get a pointer to a specific rule number */ -/*******************************************/ -divert_rule *getruleptr(int idx) -{ struct deflect_struc *ds = table_head; - - if (idx < 0) return(NULL); - while ((ds) && (idx >= 0)) - { if (!(idx--)) - { return(&ds->rule); - break; - } - ds = ds->next; - } - return(NULL); -} /* getruleptr */ - -/*************************************************/ -/* called from common module on an incoming call */ -/*************************************************/ -int isdn_divert_icall(isdn_ctrl *ic) -{ int retval = 0; - int flags; - struct call_struc *cs = NULL; - struct deflect_struc *dv; - char *p,*p1; - u_char accept; - - /* first check the internal deflection table */ - for (dv = table_head; dv ; dv = dv->next ) - { /* scan table */ - if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) || - ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL))) - continue; /* call option check */ - if (!(dv->rule.drvid & (1L << ic->driver))) - continue; /* driver not matching */ - if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1)) - continue; /* si1 not matching */ - if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2)) - continue; /* si2 not matching */ - - p = dv->rule.my_msn; - p1 = ic->parm.setup.eazmsn; - accept = 0; - while (*p) - { /* complete compare */ - if (*p == '-') - { accept = 1; /* call accepted */ - break; - } - if (*p++ != *p1++) - break; /* not accepted */ - if ((!*p) && (!*p1)) - accept = 1; - } /* complete compare */ - if (!accept) continue; /* not accepted */ - - if ((strcmp(dv->rule.caller,"0")) || (ic->parm.setup.phone[0])) - { p = dv->rule.caller; - p1 = ic->parm.setup.phone; - accept = 0; - while (*p) - { /* complete compare */ - if (*p == '-') - { accept = 1; /* call accepted */ - break; - } - if (*p++ != *p1++) - break; /* not accepted */ - if ((!*p) && (!*p1)) - accept = 1; - } /* complete compare */ - if (!accept) continue; /* not accepted */ - } - - switch (dv->rule.action) - { case DEFLECT_IGNORE: - return(0); - break; - - case DEFLECT_ALERT: - case DEFLECT_PROCEED: - case DEFLECT_REPORT: - case DEFLECT_REJECT: - if (dv->rule.action == DEFLECT_PROCEED) - if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime))) - return(0); /* no external deflection needed */ - if (!(cs = (struct call_struc *) kmalloc(sizeof(struct call_struc), GFP_ATOMIC))) - return(0); /* no memory */ - init_timer(&cs->timer); - cs->info[0] = '\0'; - cs->timer.function = deflect_timer_expire; - cs->timer.data = (ulong) cs; /* pointer to own structure */ - - cs->ics = *ic; /* copy incoming data */ - if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone,"0"); - if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn,"0"); - cs->ics.parm.setup.screen = dv->rule.screen; - if (dv->rule.waittime) - cs->timer.expires = jiffies + (HZ * dv->rule.waittime); - else - if (dv->rule.action == DEFLECT_PROCEED) - cs->timer.expires = jiffies + (HZ * extern_wait_max); - else - cs->timer.expires = 0; - cs->akt_state = dv->rule.action; - save_flags(flags); - cli(); - cs->divert_id = next_id++; /* new sequence number */ - restore_flags(flags); - cs->prev = NULL; - if (cs->akt_state == DEFLECT_ALERT) - { strcpy(cs->deflect_dest,dv->rule.to_nr); - if (!cs->timer.expires) - { strcpy(ic->parm.setup.eazmsn,"Testtext direct"); - ic->parm.setup.screen = dv->rule.screen; - strcpy(ic->parm.setup.phone,dv->rule.to_nr); - cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */ - cs->timer.expires = jiffies + (HZ * AUTODEL_TIME); - retval = 5; - } - else - retval = 1; /* alerting */ - } - else - { cs->deflect_dest[0] = '\0'; - retval = 4; /* only proceed */ - } - sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n", - cs->akt_state, - cs->divert_id, - divert_if.drv_to_name(cs->ics.driver), - (ic->command == ISDN_STAT_ICALLW) ? "1":"0", - cs->ics.parm.setup.phone, - cs->ics.parm.setup.eazmsn, - cs->ics.parm.setup.si1, - cs->ics.parm.setup.si2, - cs->ics.parm.setup.screen, - dv->rule.waittime, - cs->deflect_dest); - if ((dv->rule.action == DEFLECT_REPORT) || - (dv->rule.action == DEFLECT_REJECT)) - { put_info_buffer(cs->info); - kfree(cs); /* remove */ - return((dv->rule.action == DEFLECT_REPORT) ? 0:2); /* nothing to do */ - } - break; - - default: - return(0); /* ignore call */ - break; - } /* switch action */ - break; - } /* scan_table */ - - if (cs) - { cs->prev = NULL; - save_flags(flags); - cli(); - cs->next = divert_head; - divert_head = cs; - if (cs->timer.expires) add_timer(&cs->timer); - restore_flags(flags); - - put_info_buffer(cs->info); - return(retval); - } - else - return(0); -} /* isdn_divert_icall */ - - -void deleteprocs(void) -{ struct call_struc *cs, *cs1; - int flags; - - save_flags(flags); - cli(); - cs = divert_head; - divert_head = NULL; - while (cs) - { del_timer(&cs->timer); - cs1 = cs; - cs = cs->next; - kfree(cs1); - } - restore_flags(flags); -} /* deleteprocs */ - -/****************************************************/ -/* put a address including address type into buffer */ -/****************************************************/ -int put_address(char *st, u_char *p, int len) -{ u_char retval = 0; - u_char adr_typ = 0; /* network standard */ - - if (len < 2) return(retval); - if (*p == 0xA1) - { retval = *(++p) + 2; /* total length */ - if (retval > len) return(0); /* too short */ - len = retval - 2; /* remaining length */ - if (len < 3) return(0); - if ((*(++p) != 0x0A) || (*(++p) != 1)) return(0); - adr_typ = *(++p); - len -= 3; - p++; - if (len < 2) return(0); - if (*p++ != 0x12) return(0); - if (*p > len) return(0); /* check number length */ - len = *p++; - } - else - if (*p == 0x80) - { retval = *(++p) + 2; /* total length */ - if (retval > len) return(0); - len = retval - 2; - p++; - } - else - return(0); /* invalid address information */ - - sprintf(st,"%d ",adr_typ); - st += strlen(st); - if (!len) - *st++ = '-'; - else - while (len--) - *st++ = *p++; - *st = '\0'; - return(retval); -} /* put_address */ - -/*************************************/ -/* report a succesfull interrogation */ -/*************************************/ -int interrogate_success(isdn_ctrl *ic, struct call_struc *cs) -{ char *src = ic->parm.dss1_io.data; - int restlen = ic->parm.dss1_io.datalen; - int cnt = 1; - u_char n,n1; - char st[90], *p, *stp; - - if (restlen < 2) return(-100); /* frame too short */ - if (*src++ != 0x30) return(-101); - if ((n = *src++) > 0x81) return(-102); /* invalid length field */ - restlen -= 2; /* remaining bytes */ - if (n == 0x80) - { if (restlen < 2) return(-103); - if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-104); - restlen -= 2; - } - else - if ( n == 0x81) - { n = *src++; - restlen--; - if (n > restlen) return(-105); - restlen = n; - } - else - if (n > restlen) return(-106); - else - restlen = n; /* standard format */ - if (restlen < 3) return(-107); /* no procedure */ - if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return(-108); - restlen -= 3; - if (restlen < 2) return(-109); /* list missing */ - if (*src == 0x31) - { src++; - if ((n = *src++) > 0x81) return(-110); /* invalid length field */ - restlen -= 2; /* remaining bytes */ - if (n == 0x80) - { if (restlen < 2) return(-111); - if ((*(src+restlen-1)) || (*(src+restlen-2))) return(-112); - restlen -= 2; - } - else - if ( n == 0x81) - { n = *src++; - restlen--; - if (n > restlen) return(-113); - restlen = n; - } - else - if (n > restlen) return(-114); - else - restlen = n; /* standard format */ - } /* result list header */ - - while (restlen >= 2) - { stp = st; - sprintf(stp,"%d 0x%lx %d %s ",DIVERT_REPORT, ic->parm.dss1_io.ll_id, - cnt++,divert_if.drv_to_name(ic->driver)); - stp += strlen(stp); - if (*src++ != 0x30) return(-115); /* invalid enum */ - n = *src++; - restlen -= 2; - if (n > restlen) return(-116); /* enum length wrong */ - restlen -= n; - p = src; /* one entry */ - src += n; - if (!(n1 = put_address(stp,p,n & 0xFF))) continue; - stp += strlen(stp); - p += n1; - n -= n1; - if (n < 6) continue; /* no service and proc */ - if ((*p++ != 0x0A) || (*p++ != 1)) continue; - sprintf(stp," 0x%02x ",(*p++) & 0xFF); - stp += strlen(stp); - if ((*p++ != 0x0A) || (*p++ != 1)) continue; - sprintf(stp,"%d ",(*p++) & 0xFF); - stp += strlen(stp); - n -= 6; - if (n > 2) - { if (*p++ != 0x30) continue; - if (*p > (n-2)) continue; - n = *p++; - if (!(n1 = put_address(stp,p,n & 0xFF))) continue; - stp += strlen(stp); - } - sprintf(stp,"\n"); - put_info_buffer(st); - } /* while restlen */ - if (restlen) return(-117); - return(0); -} /* interrogate_success */ - -/*********************************************/ -/* callback for protocol specific extensions */ -/*********************************************/ -int prot_stat_callback(isdn_ctrl *ic) -{ struct call_struc *cs, *cs1; - int i,flags; - - cs = divert_head; /* start of list */ - cs1 = NULL; - while (cs) - { if (ic->driver == cs->ics.driver) - { switch (cs->ics.arg) - { case DSS1_CMD_INVOKE: - if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) && - (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) - { switch (ic->arg) - { case DSS1_STAT_INVOKE_ERR: - sprintf(cs->info,"128 0x%lx 0x%x\n", - ic->parm.dss1_io.ll_id, - ic->parm.dss1_io.timeout); - put_info_buffer(cs->info); - break; - - case DSS1_STAT_INVOKE_RES: - switch (cs->ics.parm.dss1_io.proc) - { case 7: - case 8: - put_info_buffer(cs->info); - break; - - case 11: - i = interrogate_success(ic,cs); - if (i) - sprintf(cs->info,"%d 0x%lx %d\n",DIVERT_REPORT, - ic->parm.dss1_io.ll_id,i); - put_info_buffer(cs->info); - break; - - default: - printk(KERN_WARNING "dss1_divert: unknown proc %d\n",cs->ics.parm.dss1_io.proc); - break; - } - - -#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: - printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n",ic->arg); - break; - } - cs1 = cs; /* remember structure */ - cs = NULL; - continue; /* abort search */ - } /* id found */ - break; - - case DSS1_CMD_INVOKE_ABORT: - printk(KERN_WARNING "dss1_divert unhandled invoke abort\n"); - break; - - default: - printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n",cs->ics.arg); - break; - } /* switch ics.arg */ - cs = cs->next; - } /* driver ok */ - } - - if (!cs1) - { printk(KERN_WARNING "dss1_divert unhandled process\n"); - return(0); - } - - if (cs1->ics.driver == -1) - { save_flags(flags); - cli(); - del_timer(&cs1->timer); - if (cs1->prev) - cs1->prev->next = cs1->next; /* forward link */ - else - divert_head = cs1->next; - if (cs1->next) - cs1->next->prev = cs1->prev; /* back link */ - restore_flags(flags); - kfree(cs1); - } - - return(0); -} /* prot_stat_callback */ - - -/***************************/ -/* status callback from HL */ -/***************************/ -int isdn_divert_stat_callback(isdn_ctrl *ic) -{ struct call_struc *cs, *cs1; - int flags, retval; - - retval = -1; - cs = divert_head; /* start of list */ - while (cs) - { if ((ic->driver == cs->ics.driver) && (ic->arg == cs->ics.arg)) - { switch (ic->command) - { case ISDN_STAT_DHUP: - sprintf(cs->info,"129 0x%lx\n",cs->divert_id); - del_timer(&cs->timer); - cs->ics.driver = -1; - break; - - case ISDN_STAT_CAUSE: - sprintf(cs->info,"130 0x%lx %s\n",cs->divert_id,ic->parm.num); - break; - - case ISDN_STAT_REDIR: - sprintf(cs->info,"131 0x%lx\n",cs->divert_id); - del_timer(&cs->timer); - cs->ics.driver = -1; - break; - - default: - sprintf(cs->info,"999 0x%lx 0x%x\n",cs->divert_id,(int)(ic->command)); - break; - } - put_info_buffer(cs->info); - retval = 0; - } - cs1 = cs; - cs = cs->next; - if (cs1->ics.driver == -1) - { - save_flags(flags); - cli(); - if (cs1->prev) - cs1->prev->next = cs1->next; /* forward link */ - else - divert_head = cs1->next; - if (cs1->next) - cs1->next->prev = cs1->prev; /* back link */ - restore_flags(flags); - kfree(cs1); - } - } - return(retval); /* not found */ -} /* isdn_divert_stat_callback */ - - -/********************/ -/* callback from ll */ -/********************/ -int ll_callback(isdn_ctrl *ic) -{ - switch (ic->command) - { case ISDN_STAT_ICALL: - case ISDN_STAT_ICALLW: - return(isdn_divert_icall(ic)); - break; - - case ISDN_STAT_PROT: - if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) - { if (ic->arg != DSS1_STAT_INVOKE_BRD) - return(prot_stat_callback(ic)); - else - return(0); /* DSS1 invoke broadcast */ - } - else - return(-1); /* protocol not euro */ - - default: - return(isdn_divert_stat_callback(ic)); - } -} /* ll_callback */ - diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h deleted file mode 100644 index f71815ba..00000000 --- a/drivers/isdn/divert/isdn_divert.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * $Id$ - * - * Header for the diversion supplementary ioctl interface. - * - * Copyright 1998 by Werner Cornelius (werner@ikt.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. - * - * $Log$ - * Revision 1.3 1999/08/22 20:26:37 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.2 1999/07/04 21:37:33 werner - * Ported from kernel version 2.0 - * - */ - - -#include -#include - -/******************************************/ -/* IOCTL codes for interface to user prog */ -/******************************************/ -#define DIVERT_IIOC_VERSION 0x01 /* actual version */ -#define IIOCGETVER _IO('I', 1) /* get version of interface */ -#define IIOCGETDRV _IO('I', 2) /* get driver number */ -#define IIOCGETNAM _IO('I', 3) /* get driver name */ -#define IIOCGETRULE _IO('I', 4) /* read one rule */ -#define IIOCMODRULE _IO('I', 5) /* modify/replace a rule */ -#define IIOCINSRULE _IO('I', 6) /* insert/append one rule */ -#define IIOCDELRULE _IO('I', 7) /* delete a rule */ -#define IIOCDODFACT _IO('I', 8) /* hangup/reject/alert/immediately deflect a call */ -#define IIOCDOCFACT _IO('I', 9) /* activate control forwarding in PBX */ -#define IIOCDOCFDIS _IO('I',10) /* deactivate control forwarding in PBX */ -#define IIOCDOCFINT _IO('I',11) /* interrogate control forwarding in PBX */ - -/*************************************/ -/* states reported through interface */ -/*************************************/ -#define DEFLECT_IGNORE 0 /* ignore incoming call */ -#define DEFLECT_REPORT 1 /* only report */ -#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 DEFLECT_AUTODEL 255 /* only for internal use */ - -#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */ - -typedef struct - { ulong drvid; /* driver ids, bit mapped */ - char my_msn[35]; /* desired msn, subaddr allowed */ - char caller[35]; /* caller id, partial string with * + subaddr allowed */ - char to_nr[35]; /* deflected to number incl. subaddress */ - u_char si1,si2; /* service indicators, si1=bitmask, si1+2 0 = all */ - u_char screen; /* screening: 0 = no info, 1 = info, 2 = nfo with nr */ - u_char callopt; /* option for call handling: - 0 = all calls - 1 = only non waiting calls - 2 = only waiting calls */ - u_char action; /* desired action: - 0 = don't report call -> ignore - 1 = report call, do not allow/proceed for deflection - 2 = report call, send proceed, wait max waittime secs - 3 = report call, alert and deflect after waittime - 4 = report call, reject immediately - actions 1-2 only take place if interface is opened - */ - u_char waittime; /* maximum wait time for proceeding */ - } divert_rule; - -typedef union - { int drv_version; /* return of driver version */ - struct - { int drvid; /* id of driver */ - char drvnam[30]; /* name of driver */ - } getid; - struct - { int ruleidx; /* index of rule */ - divert_rule rule; /* rule parms */ - } getsetrule; - struct - { u_char subcmd; /* 0 = hangup/reject, - 1 = alert, - 2 = deflect */ - ulong callid; /* id of call delivered by ascii output */ - char to_nr[35]; /* destination when deflect, - else uus1 string (maxlen 31), - data from rule used if empty */ - } fwd_ctrl; - struct - { int drvid; /* id of driver */ - u_char cfproc; /* cfu = 0, cfb = 1, cfnr = 2 */ - ulong procid; /* process id returned when no error */ - u_char service; /* basically coded service, 0 = all */ - char msn[25]; /* desired msn, empty = all */ - char fwd_nr[35];/* forwarded to number + subaddress */ - } cf_ctrl; - } divert_ioctl; - -#ifdef __KERNEL__ - -#include -#include - -#define AUTODEL_TIME 30 /* timeout in s to delete internal entries */ - -/**************************************************/ -/* structure keeping ascii info for device output */ -/**************************************************/ -struct divert_info - { struct divert_info *next; - ulong usage_cnt; /* number of files still to work */ - char info_start[2]; /* info string start */ - }; - - -/**************/ -/* Prototypes */ -/**************/ -extern ulong if_used; /* number of interface users */ -extern int divert_dev_deinit(void); -extern int divert_dev_init(void); -extern void put_info_buffer(char *); -extern int ll_callback(isdn_ctrl *); -extern isdn_divert_if divert_if; -extern divert_rule *getruleptr(int); -extern int insertrule(int, divert_rule *); -extern int deleterule(int); -extern void deleteprocs(void); -extern int deflect_extern_action(u_char, ulong, char *); -extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *); - -#endif /* __KERNEL__ */ diff --git a/drivers/isdn/eicon/Makefile b/drivers/isdn/eicon/Makefile deleted file mode 100644 index 306aac0e..00000000 --- a/drivers/isdn/eicon/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -L_OBJS := -M_OBJS := -O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o - -O_TARGET := -ifeq ($(CONFIG_ISDN_DRV_EICON),y) - O_TARGET += eicon.o -else - O_TARGET += eicon.o - M_OBJS = eicon.o -endif - -include $(TOPDIR)/Rules.make diff --git a/drivers/isdn/eicon/eicon.h b/drivers/isdn/eicon/eicon.h deleted file mode 100644 index ef157b86..00000000 --- a/drivers/isdn/eicon/eicon.h +++ /dev/null @@ -1,707 +0,0 @@ -/* $Id$ - * - * ISDN low-level module for Eicon active ISDN-Cards. - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * 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. - * - * $Log$ - * Revision 1.18 1999/11/25 11:43:27 armin - * Fixed statectrl and connect message. - * X.75 fix and HDLC/transparent with autoconnect. - * Minor cleanup. - * - * Revision 1.17 1999/10/26 21:15:33 armin - * using define for checking phone number len to avoid buffer overflow. - * - * Revision 1.16 1999/10/08 22:09:33 armin - * Some fixes of cards interface handling. - * Bugfix of NULL pointer occurence. - * Changed a few log outputs. - * - * Revision 1.15 1999/09/26 14:17:53 armin - * Improved debug and log via readstat() - * - * Revision 1.14 1999/09/08 20:17:31 armin - * Added microchannel patch from Erik Weber. - * - * Revision 1.13 1999/09/06 07:29:35 fritz - * Changed my mail-address. - * - * Revision 1.12 1999/09/04 06:20:05 keil - * Changes from kernel set_current_state() - * - * Revision 1.11 1999/08/29 17:23:44 armin - * New setup compat. - * Bugfix if compile as not module. - * - * Revision 1.10 1999/08/22 20:26:41 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.9 1999/08/18 20:16:57 armin - * Added XLOG function for all cards. - * Bugfix of alloc_skb NULL pointer. - * - * Revision 1.8 1999/07/25 15:12:01 armin - * fix of some debug logs. - * enabled ISA-cards option. - * - * Revision 1.7 1999/07/11 17:16:23 armin - * Bugfixes in queue handling. - * Added DSP-DTMF decoder functions. - * Reorganized ack_handler. - * - * Revision 1.6 1999/06/09 19:31:24 armin - * Wrong PLX size for request_region() corrected. - * Added first MCA code from Erik Weber. - * - * Revision 1.5 1999/03/29 11:19:41 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.4 1999/03/02 12:37:42 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.3 1999/01/24 20:14:07 armin - * Changed and added debug stuff. - * Better data sending. (still problems with tty's flip buffer) - * - * Revision 1.2 1999/01/10 18:46:04 armin - * Bug with wrong values in HLC fixed. - * Bytes to send are counted and limited now. - * - * Revision 1.1 1999/01/01 18:09:41 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - - -#ifndef eicon_h -#define eicon_h - -#define EICON_IOCTL_SETMMIO 0 -#define EICON_IOCTL_GETMMIO 1 -#define EICON_IOCTL_SETIRQ 2 -#define EICON_IOCTL_GETIRQ 3 -#define EICON_IOCTL_LOADBOOT 4 -#define EICON_IOCTL_ADDCARD 5 -#define EICON_IOCTL_GETTYPE 6 -#define EICON_IOCTL_LOADPCI 7 -#define EICON_IOCTL_LOADISA 8 -#define EICON_IOCTL_GETVER 9 -#define EICON_IOCTL_GETXLOG 10 - -#define EICON_IOCTL_MANIF 90 - -#define EICON_IOCTL_FREEIT 97 -#define EICON_IOCTL_TEST 98 -#define EICON_IOCTL_DEBUGVAR 99 - -/* Bus types */ -#define EICON_BUS_ISA 1 -#define EICON_BUS_MCA 2 -#define EICON_BUS_PCI 3 - -/* Constants for describing Card-Type */ -#define EICON_CTYPE_S 0 -#define EICON_CTYPE_SX 1 -#define EICON_CTYPE_SCOM 2 -#define EICON_CTYPE_QUADRO 3 -#define EICON_CTYPE_S2M 4 -#define EICON_CTYPE_MAESTRA 5 -#define EICON_CTYPE_MAESTRAQ 6 -#define EICON_CTYPE_MAESTRAQ_U 7 -#define EICON_CTYPE_MAESTRAP 8 -#define EICON_CTYPE_ISABRI 0x10 -#define EICON_CTYPE_ISAPRI 0x20 -#define EICON_CTYPE_MASK 0x0f -#define EICON_CTYPE_QUADRO_NR(n) (n<<4) - -#define MAX_HEADER_LEN 10 - -#define MAX_STATUS_BUFFER 150 - -/* Struct for adding new cards */ -typedef struct eicon_cdef { - int membase; - int irq; - char id[10]; -} eicon_cdef; - -#define EICON_ISA_BOOT_MEMCHK 1 -#define EICON_ISA_BOOT_NORMAL 2 - -/* Struct for downloading protocol via ioctl for ISA cards */ -/* same struct for downloading protocol via ioctl for MCA cards */ -typedef struct { - /* start-up parameters */ - unsigned char tei; - unsigned char nt2; - unsigned char skip1; - unsigned char WatchDog; - unsigned char Permanent; - unsigned char XInterface; - unsigned char StableL2; - unsigned char NoOrderCheck; - unsigned char HandsetType; - unsigned char skip2; - unsigned char LowChannel; - unsigned char ProtVersion; - unsigned char Crc4; - unsigned char Loopback; - unsigned char oad[32]; - unsigned char osa[32]; - unsigned char spid[32]; - unsigned char boot_opt; - unsigned long bootstrap_len; - unsigned long firmware_len; - unsigned char code[1]; /* Rest (bootstrap- and firmware code) will be allocated */ -} eicon_isa_codebuf; - -/* Struct for downloading protocol via ioctl for PCI cards */ -typedef struct { - /* start-up parameters */ - unsigned char tei; - unsigned char nt2; - unsigned char WatchDog; - unsigned char Permanent; - unsigned char XInterface; - unsigned char StableL2; - unsigned char NoOrderCheck; - unsigned char HandsetType; - unsigned char LowChannel; - unsigned char ProtVersion; - unsigned char Crc4; - unsigned char NoHscx30Mode; /* switch PRI into No HSCX30 test mode */ - unsigned char Loopback; /* switch card into Loopback mode */ - struct q931_link_s - { - unsigned char oad[32]; - unsigned char osa[32]; - unsigned char spid[32]; - } l[2]; - unsigned long protocol_len; - unsigned int dsp_code_num; - unsigned long dsp_code_len[9]; - unsigned char code[1]; /* Rest (protocol- and dsp code) will be allocated */ -} eicon_pci_codebuf; - -/* Data for downloading protocol via ioctl */ -typedef union { - eicon_isa_codebuf isa; - eicon_isa_codebuf mca; - eicon_pci_codebuf pci; -} eicon_codebuf; - -/* Data for Management interface */ -typedef struct { - int count; - int pos; - int length[50]; - unsigned char data[700]; -} eicon_manifbuf; - - -#ifdef __KERNEL__ - -/* Kernel includes */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -typedef struct { - __u16 length __attribute__ ((packed)); /* length of data/parameter field */ - __u8 P[1]; /* data/parameter field */ -} eicon_PBUFFER; - -#include "eicon_isa.h" - -/* Macro for delay via schedule() */ -#define SLEEP(j) { \ - set_current_state(TASK_UNINTERRUPTIBLE); \ - schedule_timeout(j); \ -} - -#endif /* KERNEL */ - -#define DIVAS_SHARED_OFFSET (0x1000) - -#define MIPS_BUFFER_SZ 128 -#define MIPS_MAINT_OFFS 0xff00 - -#define XLOG_ERR_CARD_NUM (13) -#define XLOG_ERR_DONE (14) -#define XLOG_ERR_CMD (15) -#define XLOG_ERR_TIMEOUT (16) -#define XLOG_ERR_CARD_STATE (17) -#define XLOG_ERR_UNKNOWN (18) -#define XLOG_OK (0) - -#define TRACE_OK (1) - -typedef struct { - __u8 Id __attribute__ ((packed)); - __u8 uX __attribute__ ((packed)); - __u8 listen __attribute__ ((packed)); - __u8 active __attribute__ ((packed)); - __u8 sin[3] __attribute__ ((packed)); - __u8 bc[6] __attribute__ ((packed)); - __u8 llc[6] __attribute__ ((packed)); - __u8 hlc[6] __attribute__ ((packed)); - __u8 oad[20] __attribute__ ((packed)); -}DSigStruc; - -typedef struct { - __u32 cx_b1 __attribute__ ((packed)); - __u32 cx_b2 __attribute__ ((packed)); - __u32 cr_b1 __attribute__ ((packed)); - __u32 cr_b2 __attribute__ ((packed)); - __u32 px_b1 __attribute__ ((packed)); - __u32 px_b2 __attribute__ ((packed)); - __u32 pr_b1 __attribute__ ((packed)); - __u32 pr_b2 __attribute__ ((packed)); - __u16 er_b1 __attribute__ ((packed)); - __u16 er_b2 __attribute__ ((packed)); -}BL1Struc; - -typedef struct { - __u32 XTotal __attribute__ ((packed)); - __u32 RTotal __attribute__ ((packed)); - __u16 XError __attribute__ ((packed)); - __u16 RError __attribute__ ((packed)); -}L2Struc; - -typedef struct { - __u16 free_n; -}OSStruc; - -typedef union -{ - DSigStruc DSigStats; - BL1Struc BL1Stats; - L2Struc L2Stats; - OSStruc OSStats; - __u8 b[MIPS_BUFFER_SZ]; - __u16 w[MIPS_BUFFER_SZ>>1]; - __u16 l[MIPS_BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */ - __u32 d[MIPS_BUFFER_SZ>>2]; -} MIPS_BUFFER; - -typedef struct -{ - __u8 req __attribute__ ((packed)); - __u8 rc __attribute__ ((packed)); - __u8 reserved[2] __attribute__ ((packed)); /* R3000 alignment ... */ - __u8 *mem __attribute__ ((packed)); - __u16 length __attribute__ ((packed)); /* used to be short */ - __u16 port __attribute__ ((packed)); - __u8 fill[4] __attribute__ ((packed)); /* data at offset 16 */ - MIPS_BUFFER data __attribute__ ((packed)); -} mi_pc_maint_t; - -typedef struct -{ - __u16 command; - mi_pc_maint_t pcm; -}xlogreq_t; - -typedef struct{ - __u16 code __attribute__ ((packed)); /* used to be short */ - __u16 timeh __attribute__ ((packed)); - __u16 timel __attribute__ ((packed)); - char buffer[MIPS_BUFFER_SZ - 6]; -}xlog_entry_t; - - -#define DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE 48 -#define DSP_COMBIFILE_FORMAT_VERSION_BCD 0x0100 - -#define DSP_FILE_FORMAT_IDENTIFICATION_SIZE 48 -#define DSP_FILE_FORMAT_VERSION_BCD 0x0100 - -typedef struct tag_dsp_combifile_header -{ - char format_identification[DSP_COMBIFILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed)); - __u16 format_version_bcd __attribute__ ((packed)); - __u16 header_size __attribute__ ((packed)); - __u16 combifile_description_size __attribute__ ((packed)); - __u16 directory_entries __attribute__ ((packed)); - __u16 directory_size __attribute__ ((packed)); - __u16 download_count __attribute__ ((packed)); - __u16 usage_mask_size __attribute__ ((packed)); -} t_dsp_combifile_header; - -typedef struct tag_dsp_combifile_directory_entry -{ - __u16 card_type_number __attribute__ ((packed)); - __u16 file_set_number __attribute__ ((packed)); -} t_dsp_combifile_directory_entry; - -typedef struct tag_dsp_file_header -{ - char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE] __attribute__ ((packed)); - __u16 format_version_bcd __attribute__ ((packed)); - __u16 download_id __attribute__ ((packed)); - __u16 download_flags __attribute__ ((packed)); - __u16 required_processing_power __attribute__ ((packed)); - __u16 interface_channel_count __attribute__ ((packed)); - __u16 header_size __attribute__ ((packed)); - __u16 download_description_size __attribute__ ((packed)); - __u16 memory_block_table_size __attribute__ ((packed)); - __u16 memory_block_count __attribute__ ((packed)); - __u16 segment_table_size __attribute__ ((packed)); - __u16 segment_count __attribute__ ((packed)); - __u16 symbol_table_size __attribute__ ((packed)); - __u16 symbol_count __attribute__ ((packed)); - __u16 total_data_size_dm __attribute__ ((packed)); - __u16 data_block_count_dm __attribute__ ((packed)); - __u16 total_data_size_pm __attribute__ ((packed)); - __u16 data_block_count_pm __attribute__ ((packed)); -} t_dsp_file_header; - -typedef struct tag_dsp_memory_block_desc -{ - __u16 alias_memory_block; - __u16 memory_type; - __u16 address; - __u16 size; /* DSP words */ -} t_dsp_memory_block_desc; - -typedef struct tag_dsp_segment_desc -{ - __u16 memory_block; - __u16 attributes; - __u16 base; - __u16 size; - __u16 alignment; /* ==0 -> no other legal start address than base */ -} t_dsp_segment_desc; - -typedef struct tag_dsp_symbol_desc -{ - __u16 symbol_id; - __u16 segment; - __u16 offset; - __u16 size; /* DSP words */ -} t_dsp_symbol_desc; - -typedef struct tag_dsp_data_block_header -{ - __u16 attributes; - __u16 segment; - __u16 offset; - __u16 size; /* DSP words */ -} t_dsp_data_block_header; - -typedef struct tag_dsp_download_desc /* be sure to keep native alignment for MAESTRA's */ -{ - __u16 download_id; - __u16 download_flags; - __u16 required_processing_power; - __u16 interface_channel_count; - __u16 excess_header_size; - __u16 memory_block_count; - __u16 segment_count; - __u16 symbol_count; - __u16 data_block_count_dm; - __u16 data_block_count_pm; - __u8 * p_excess_header_data __attribute__ ((packed)); - char * p_download_description __attribute__ ((packed)); - t_dsp_memory_block_desc *p_memory_block_table __attribute__ ((packed)); - t_dsp_segment_desc *p_segment_table __attribute__ ((packed)); - t_dsp_symbol_desc *p_symbol_table __attribute__ ((packed)); - __u16 * p_data_blocks_dm __attribute__ ((packed)); - __u16 * p_data_blocks_pm __attribute__ ((packed)); -} t_dsp_download_desc; - - -#ifdef __KERNEL__ - -typedef struct { - __u8 Req; /* pending request */ - __u8 Rc; /* return code received */ - __u8 Ind; /* indication received */ - __u8 ReqCh; /* channel of current Req */ - __u8 RcCh; /* channel of current Rc */ - __u8 IndCh; /* channel of current Ind */ - __u8 D3Id; /* ID used by this entity */ - __u8 B2Id; /* ID used by this entity */ - __u8 GlobalId; /* reserved field */ - __u8 XNum; /* number of X-buffers */ - __u8 RNum; /* number of R-buffers */ - struct sk_buff_head X; /* X-buffer queue */ - struct sk_buff_head R; /* R-buffer queue */ - __u8 RNR; /* receive not ready flag */ - __u8 complete; /* receive complete status */ - __u8 busy; /* busy flag */ - __u16 ref; /* saved reference */ -} entity; - -#define FAX_MAX_SCANLINE 256 - -typedef struct { - __u8 PrevObject; - __u8 NextObject; - __u8 abLine[FAX_MAX_SCANLINE]; - __u8 abFrame[FAX_MAX_SCANLINE]; - unsigned int LineLen; - unsigned int LineDataLen; - __u32 LineData; - unsigned int NullBytesPos; - __u8 NullByteExist; - int PageCount; - __u8 Dle; - __u8 Eop; -} eicon_ch_fax_buf; - -typedef struct { - int No; /* Channel Number */ - unsigned short fsm_state; /* Current D-Channel state */ - unsigned short statectrl; /* State controling bits */ - unsigned short eazmask; /* EAZ-Mask for this Channel */ - int queued; /* User-Data Bytes in TX queue */ - int waitq; /* User-Data Bytes in wait queue */ - int waitpq; /* User-Data Bytes in packet queue */ - struct sk_buff *tskb1; /* temp skb 1 */ - struct sk_buff *tskb2; /* temp skb 2 */ - unsigned char l2prot; /* Layer 2 protocol */ - unsigned char l3prot; /* Layer 3 protocol */ -#ifdef CONFIG_ISDN_TTY_FAX - T30_s *fax; /* pointer to fax data in LL */ - eicon_ch_fax_buf fax2; /* fax related struct */ -#endif - entity e; /* Entity */ - char cpn[32]; /* remember cpn */ - char oad[32]; /* remember oad */ - char dsa[32]; /* remember dsa */ - char osa[32]; /* remember osa */ - unsigned char cause[2]; /* Last Cause */ - unsigned char si1; - unsigned char si2; - unsigned char plan; - unsigned char screen; -} eicon_chan; - -typedef struct { - eicon_chan *ptr; -} eicon_chan_ptr; - -#include "eicon_pci.h" - -#define EICON_FLAGS_RUNNING 1 /* Cards driver activated */ -#define EICON_FLAGS_PVALID 2 /* Cards port is valid */ -#define EICON_FLAGS_IVALID 4 /* Cards irq is valid */ -#define EICON_FLAGS_MVALID 8 /* Cards membase is valid */ -#define EICON_FLAGS_LOADED 8 /* Firmware loaded */ - -#define EICON_BCH 2 /* # of channels per card */ - -/* D-Channel states */ -#define EICON_STATE_NULL 0 -#define EICON_STATE_ICALL 1 -#define EICON_STATE_OCALL 2 -#define EICON_STATE_IWAIT 3 -#define EICON_STATE_OWAIT 4 -#define EICON_STATE_IBWAIT 5 -#define EICON_STATE_OBWAIT 6 -#define EICON_STATE_BWAIT 7 -#define EICON_STATE_BHWAIT 8 -#define EICON_STATE_BHWAIT2 9 -#define EICON_STATE_DHWAIT 10 -#define EICON_STATE_DHWAIT2 11 -#define EICON_STATE_BSETUP 12 -#define EICON_STATE_ACTIVE 13 -#define EICON_STATE_ICALLW 14 -#define EICON_STATE_LISTEN 15 -#define EICON_STATE_WMCONN 16 - -#define EICON_MAX_QUEUE 2138 - -#define EICON_LOCK_TX 0 -#define EICON_LOCK_RX 1 - -typedef union { - eicon_isa_card isa; - eicon_pci_card pci; - eicon_isa_card mca; -} eicon_hwif; - -typedef struct { - __u8 ret; - __u8 id; - __u8 ch; -} eicon_ack; - -typedef struct { - __u8 code; - __u8 id; - __u8 ch; -} eicon_req; - -typedef struct { - __u8 ret; - __u8 id; - __u8 ch; - __u8 more; -} eicon_indhdr; - -typedef struct msn_entry { - char eaz; - char msn[16]; - struct msn_entry * next; -} msn_entry; - -/* - * Per card driver data - */ -typedef struct eicon_card { - eicon_hwif hwif; /* Hardware dependant interface */ - u_char ptype; /* Protocol type (1TR6 or Euro) */ - u_char bus; /* Bustype (ISA, MCA, PCI) */ - u_char type; /* Cardtype (EICON_CTYPE_...) */ - struct eicon_card *qnext; /* Pointer to next quadro adapter */ - int Feature; /* Protocol Feature Value */ - struct eicon_card *next; /* Pointer to next device struct */ - int myid; /* Driver-Nr. assigned by linklevel */ - unsigned long flags; /* Statusflags */ - struct sk_buff_head rcvq; /* Receive-Message queue */ - struct sk_buff_head sndq; /* Send-Message queue */ - struct sk_buff_head rackq; /* Req-Ack-Message queue */ - struct sk_buff_head sackq; /* Data-Ack-Message queue */ - struct sk_buff_head statq; /* Status-Message queue */ - int statq_entries; - struct tq_struct snd_tq; /* Task struct for xmit bh */ - struct tq_struct rcv_tq; /* Task struct for rcv bh */ - struct tq_struct ack_tq; /* Task struct for ack bh */ - msn_entry *msn_list; - eicon_chan* IdTable[256]; /* Table to find entity */ - __u16 ref_in; - __u16 ref_out; - int nchannels; /* Number of B-Channels */ - int ReadyInt; /* Ready Interrupt */ - eicon_chan *bch; /* B-Channel status/control */ - char status_buf[256]; /* Buffer for status messages */ - char *status_buf_read; - char *status_buf_write; - char *status_buf_end; - isdn_if interface; /* Interface to upper layer */ - char regname[35]; /* Name used for request_region */ -#ifdef CONFIG_MCA - int mca_slot; /* # of cards MCA slot */ - int mca_io; /* MCA cards IO port */ -#endif /* CONFIG_MCA */ -} eicon_card; - -/* -----------------------------------------------------------** -** The PROTOCOL_FEATURE_STRING ** -** defines capabilities and ** -** features of the actual protocol code. It's used as a bit ** -** mask. ** -** The following Bits are defined: ** -** -----------------------------------------------------------*/ -#define PROTCAP_TELINDUS 0x0001 /* Telindus Variant of protocol code */ -#define PROTCAP_MANIF 0x0002 /* Management interface implemented */ -#define PROTCAP_V_42 0x0004 /* V42 implemented */ -#define PROTCAP_V90D 0x0008 /* V.90D (implies up to 384k DSP code) */ -#define PROTCAP_EXTD_FAX 0x0010 /* Extended FAX (ECM, 2D, T6, Polling) */ -#define PROTCAP_FREE4 0x0020 /* not used */ -#define PROTCAP_FREE5 0x0040 /* not used */ -#define PROTCAP_FREE6 0x0080 /* not used */ -#define PROTCAP_FREE7 0x0100 /* not used */ -#define PROTCAP_FREE8 0x0200 /* not used */ -#define PROTCAP_FREE9 0x0400 /* not used */ -#define PROTCAP_FREE10 0x0800 /* not used */ -#define PROTCAP_FREE11 0x1000 /* not used */ -#define PROTCAP_FREE12 0x2000 /* not used */ -#define PROTCAP_FREE13 0x4000 /* not used */ -#define PROTCAP_EXTENSION 0x8000 /* used for future extentions */ - -#include "eicon_idi.h" - -extern eicon_card *cards; -extern char *eicon_ctype_name[]; - - -extern __inline__ void eicon_schedule_tx(eicon_card *card) -{ - queue_task(&card->snd_tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -extern __inline__ void eicon_schedule_rx(eicon_card *card) -{ - queue_task(&card->rcv_tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -extern __inline__ void eicon_schedule_ack(eicon_card *card) -{ - queue_task(&card->ack_tq, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -extern char *eicon_find_eaz(eicon_card *, char); -extern int eicon_addcard(int, int, int, char *); -extern void eicon_io_transmit(eicon_card *card); -extern void eicon_irq(int irq, void *dev_id, struct pt_regs *regs); -extern void eicon_io_rcv_dispatch(eicon_card *ccard); -extern void eicon_io_ack_dispatch(eicon_card *ccard); -extern int eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq); -#ifdef CONFIG_MCA -extern int eicon_mca_find_card(int, int, int, char *); -extern int eicon_mca_probe(int, int, int, int, char *); -extern int eicon_info(char *, int , void *); -#endif /* CONFIG_MCA */ - -extern ulong DebugVar; -extern void eicon_log(eicon_card * card, int level, const char *fmt, ...); -extern void eicon_putstatus(eicon_card * card, char * buf); - -#endif /* __KERNEL__ */ - -#endif /* eicon_h */ diff --git a/drivers/isdn/eicon/eicon_dsp.h b/drivers/isdn/eicon/eicon_dsp.h deleted file mode 100644 index e0abf37e..00000000 --- a/drivers/isdn/eicon/eicon_dsp.h +++ /dev/null @@ -1,419 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for Eicon active cards. - * DSP definitions - * - * Copyright 1999,2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * 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. - * - * $Log$ - * Revision 1.4 1999/07/25 15:12:02 armin - * fix of some debug logs. - * enabled ISA-cards option. - * - * Revision 1.3 1999/07/11 17:16:24 armin - * Bugfixes in queue handling. - * Added DSP-DTMF decoder functions. - * Reorganized ack_handler. - * - * Revision 1.2 1999/03/29 11:19:42 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.1 1999/03/02 12:18:54 armin - * First checkin of DSP defines for audio features. - * - * - */ - -#ifndef DSP_H -#define DSP_H - -#define DSP_UDATA_REQUEST_RECONFIGURE 0 -/* -parameters: - reconfigure delay (in 8kHz samples) - reconfigure code - reconfigure hdlc preamble flags -*/ - -#define DSP_RECONFIGURE_TX_FLAG 0x8000 -#define DSP_RECONFIGURE_SHORT_TRAIN_FLAG 0x4000 -#define DSP_RECONFIGURE_ECHO_PROTECT_FLAG 0x2000 -#define DSP_RECONFIGURE_HDLC_FLAG 0x1000 -#define DSP_RECONFIGURE_SYNC_FLAG 0x0800 -#define DSP_RECONFIGURE_PROTOCOL_MASK 0x00ff -#define DSP_RECONFIGURE_IDLE 0 -#define DSP_RECONFIGURE_V25 1 -#define DSP_RECONFIGURE_V21_CH2 2 -#define DSP_RECONFIGURE_V27_2400 3 -#define DSP_RECONFIGURE_V27_4800 4 -#define DSP_RECONFIGURE_V29_7200 5 -#define DSP_RECONFIGURE_V29_9600 6 -#define DSP_RECONFIGURE_V33_12000 7 -#define DSP_RECONFIGURE_V33_14400 8 -#define DSP_RECONFIGURE_V17_7200 9 -#define DSP_RECONFIGURE_V17_9600 10 -#define DSP_RECONFIGURE_V17_12000 11 -#define DSP_RECONFIGURE_V17_14400 12 - -/* -data indications if transparent framer - data 0 - data 1 - ... - -data indications if HDLC framer - data 0 - data 1 - ... - CRC 0 - CRC 1 - preamble flags -*/ - -#define DSP_UDATA_REQUEST_SWITCH_FRAMER 1 -/* -parameters: - transmit framer type - receive framer type -*/ - -#define DSP_REQUEST_SWITCH_FRAMER_HDLC 0 -#define DSP_REQUEST_SWITCH_FRAMER_TRANSPARENT 1 -#define DSP_REQUEST_SWITCH_FRAMER_ASYNC 2 - - -#define DSP_UDATA_REQUEST_CLEARDOWN 2 -/* -parameters: - - none - -*/ - - -#define DSP_UDATA_REQUEST_TX_CONFIRMATION_ON 3 -/* -parameters: - - none - -*/ - - -#define DSP_UDATA_REQUEST_TX_CONFIRMATION_OFF 4 -/* -parameters: - - none - -*/ - - -#define DSP_UDATA_INDICATION_SYNC 0 -/* -returns: - time of sync (sampled from counter at 8kHz) -*/ - -#define DSP_UDATA_INDICATION_DCD_OFF 1 -/* -returns: - time of DCD off (sampled from counter at 8kHz) -*/ - -#define DSP_UDATA_INDICATION_DCD_ON 2 -/* -returns: - time of DCD on (sampled from counter at 8kHz) - connected norm - connected options - connected speed (bit/s, max of tx and rx speed) - roundtrip delay (ms) - connected speed tx (bit/s) - connected speed rx (bit/s) -*/ - -#define DSP_UDATA_INDICATION_CTS_OFF 3 -/* -returns: - time of CTS off (sampled from counter at 8kHz) -*/ - -#define DSP_UDATA_INDICATION_CTS_ON 4 -/* -returns: - time of CTS on (sampled from counter at 8kHz) - connected norm - connected options - connected speed (bit/s, max of tx and rx speed) - roundtrip delay (ms) - connected speed tx (bit/s) - connected speed rx (bit/s) -*/ - -typedef struct eicon_dsp_ind { - __u16 time __attribute__ ((packed)); - __u8 norm __attribute__ ((packed)); - __u16 options __attribute__ ((packed)); - __u32 speed __attribute__ ((packed)); - __u16 delay __attribute__ ((packed)); - __u32 txspeed __attribute__ ((packed)); - __u32 rxspeed __attribute__ ((packed)); -} eicon_dsp_ind; - -#define DSP_CONNECTED_NORM_UNSPECIFIED 0 -#define DSP_CONNECTED_NORM_V21 1 -#define DSP_CONNECTED_NORM_V23 2 -#define DSP_CONNECTED_NORM_V22 3 -#define DSP_CONNECTED_NORM_V22_BIS 4 -#define DSP_CONNECTED_NORM_V32_BIS 5 -#define DSP_CONNECTED_NORM_V34 6 -#define DSP_CONNECTED_NORM_V8 7 -#define DSP_CONNECTED_NORM_BELL_212A 8 -#define DSP_CONNECTED_NORM_BELL_103 9 -#define DSP_CONNECTED_NORM_V29_LEASED_LINE 10 -#define DSP_CONNECTED_NORM_V33_LEASED_LINE 11 -#define DSP_CONNECTED_NORM_V90 12 -#define DSP_CONNECTED_NORM_V21_CH2 13 -#define DSP_CONNECTED_NORM_V27_TER 14 -#define DSP_CONNECTED_NORM_V29 15 -#define DSP_CONNECTED_NORM_V33 16 -#define DSP_CONNECTED_NORM_V17 17 - -#define DSP_CONNECTED_OPTION_TRELLIS 0x0001 -#define DSP_CONNECTED_OPTION_V42_TRANS 0x0002 -#define DSP_CONNECTED_OPTION_V42_LAPM 0x0004 -#define DSP_CONNECTED_OPTION_SHORT_TRAIN 0x0008 -#define DSP_CONNECTED_OPTION_TALKER_ECHO_PROTECT 0x0010 - - -#define DSP_UDATA_INDICATION_DISCONNECT 5 -/* -returns: - cause -*/ - -#define DSP_DISCONNECT_CAUSE_NONE 0x00 -#define DSP_DISCONNECT_CAUSE_BUSY_TONE 0x01 -#define DSP_DISCONNECT_CAUSE_CONGESTION_TONE 0x02 -#define DSP_DISCONNECT_CAUSE_INCOMPATIBILITY 0x03 -#define DSP_DISCONNECT_CAUSE_CLEARDOWN 0x04 -#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT 0x05 - - -#define DSP_UDATA_INDICATION_TX_CONFIRMATION 6 -/* -returns: - confirmation number -*/ - - -#define DSP_UDATA_REQUEST_SEND_DTMF_DIGITS 16 -/* -parameters: - tone duration (ms) - gap duration (ms) - digit 0 tone code - ... - digit n tone code -*/ - -#define DSP_SEND_DTMF_DIGITS_HEADER_LENGTH 5 - -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_697_HZ 0x00 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_770_HZ 0x01 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_852_HZ 0x02 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_941_HZ 0x03 -#define DSP_DTMF_DIGIT_TONE_LOW_GROUP_MASK 0x03 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1209_HZ 0x00 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1336_HZ 0x04 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1477_HZ 0x08 -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_1633_HZ 0x0c -#define DSP_DTMF_DIGIT_TONE_HIGH_GROUP_MASK 0x0c - -#define DSP_DTMF_DIGIT_TONE_CODE_0 0x07 -#define DSP_DTMF_DIGIT_TONE_CODE_1 0x00 -#define DSP_DTMF_DIGIT_TONE_CODE_2 0x04 -#define DSP_DTMF_DIGIT_TONE_CODE_3 0x08 -#define DSP_DTMF_DIGIT_TONE_CODE_4 0x01 -#define DSP_DTMF_DIGIT_TONE_CODE_5 0x05 -#define DSP_DTMF_DIGIT_TONE_CODE_6 0x09 -#define DSP_DTMF_DIGIT_TONE_CODE_7 0x02 -#define DSP_DTMF_DIGIT_TONE_CODE_8 0x06 -#define DSP_DTMF_DIGIT_TONE_CODE_9 0x0a -#define DSP_DTMF_DIGIT_TONE_CODE_STAR 0x03 -#define DSP_DTMF_DIGIT_TONE_CODE_HASHMARK 0x0b -#define DSP_DTMF_DIGIT_TONE_CODE_A 0x0c -#define DSP_DTMF_DIGIT_TONE_CODE_B 0x0d -#define DSP_DTMF_DIGIT_TONE_CODE_C 0x0e -#define DSP_DTMF_DIGIT_TONE_CODE_D 0x0f - - -#define DSP_UDATA_INDICATION_DTMF_DIGITS_SENT 16 -/* -returns: - - none - - One indication will be sent for every request. -*/ - - -#define DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER 17 -/* -parameters: - tone duration (ms) - gap duration (ms) -*/ -typedef struct enable_dtmf_s { - __u16 tone; - __u16 gap; -} enable_dtmf_s; - -#define DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER 18 -/* -parameters: - - none - -*/ - -#define DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED 17 -/* -returns: - digit 0 tone code - ... - digit n tone code -*/ - -#define DSP_DTMF_DIGITS_RECEIVED_HEADER_LENGTH 1 - - -#define DSP_UDATA_INDICATION_MODEM_CALLING_TONE 18 -/* -returns: - - none - -*/ - -#define DSP_UDATA_INDICATION_FAX_CALLING_TONE 19 -/* -returns: - - none - -*/ - -#define DSP_UDATA_INDICATION_ANSWER_TONE 20 -/* -returns: - - none - -*/ - -/* ============= FAX ================ */ - -#define EICON_FAXID_LEN 20 - -typedef struct eicon_t30_s { - __u8 code; - __u8 rate; - __u8 resolution; - __u8 format; - __u8 pages_low; - __u8 pages_high; - __u8 atf; - __u8 control_bits_low; - __u8 control_bits_high; - __u8 feature_bits_low; - __u8 feature_bits_high; - __u8 universal_5; - __u8 universal_6; - __u8 universal_7; - __u8 station_id_len; - __u8 head_line_len; - __u8 station_id[EICON_FAXID_LEN]; -/* __u8 head_line[]; */ -} eicon_t30_s; - - /* EDATA transmit messages */ -#define EDATA_T30_DIS 0x01 -#define EDATA_T30_FTT 0x02 -#define EDATA_T30_MCF 0x03 - - /* EDATA receive messages */ -#define EDATA_T30_DCS 0x81 -#define EDATA_T30_TRAIN_OK 0x82 -#define EDATA_T30_EOP 0x83 -#define EDATA_T30_MPS 0x84 -#define EDATA_T30_EOM 0x85 -#define EDATA_T30_DTC 0x86 - -#define T30_FORMAT_SFF 0 -#define T30_FORMAT_ASCII 1 -#define T30_FORMAT_COUNT 2 - -#define T30_CONTROL_BIT_DISABLE_FINE 0x0001 -#define T30_CONTROL_BIT_ENABLE_ECM 0x0002 -#define T30_CONTROL_BIT_ECM_64_BYTES 0x0004 -#define T30_CONTROL_BIT_ENABLE_2D_CODING 0x0008 -#define T30_CONTROL_BIT_ENABLE_T6_CODING 0x0010 -#define T30_CONTROL_BIT_ENABLE_UNCOMPR 0x0020 -#define T30_CONTROL_BIT_ACCEPT_POLLING 0x0040 -#define T30_CONTROL_BIT_REQUEST_POLLING 0x0080 -#define T30_CONTROL_BIT_MORE_DOCUMENTS 0x0100 - -#define T30_CONTROL_BIT_ALL_FEATURES\ - (T30_CONTROL_BIT_ENABLE_ECM | T30_CONTROL_BIT_ENABLE_2D_CODING |\ - T30_CONTROL_BIT_ENABLE_T6_CODING | T30_CONTROL_BIT_ENABLE_UNCOMPR) - -#define T30_FEATURE_BIT_FINE 0x0001 -#define T30_FEATURE_BIT_ECM 0x0002 -#define T30_FEATURE_BIT_ECM_64_BYTES 0x0004 -#define T30_FEATURE_BIT_2D_CODING 0x0008 -#define T30_FEATURE_BIT_T6_CODING 0x0010 -#define T30_FEATURE_BIT_UNCOMPR_ENABLED 0x0020 -#define T30_FEATURE_BIT_POLLING 0x0040 - -#define FAX_OBJECT_DOCU 1 -#define FAX_OBJECT_PAGE 2 -#define FAX_OBJECT_LINE 3 - -#define T4_EOL 0x800 -#define T4_EOL_BITSIZE 12 -#define T4_EOL_DWORD (T4_EOL << (32 - T4_EOL_BITSIZE)) -#define T4_EOL_MASK_DWORD ((__u32) -1 << (32 - T4_EOL_BITSIZE)) - -#define SFF_LEN_FLD_SIZE 3 - -#define _DLE_ 0x10 -#define _ETX_ 0x03 - -typedef struct eicon_sff_dochead { - __u32 id __attribute__ ((packed)); - __u8 version __attribute__ ((packed)); - __u8 reserved1 __attribute__ ((packed)); - __u16 userinfo __attribute__ ((packed)); - __u16 pagecount __attribute__ ((packed)); - __u16 off1pagehead __attribute__ ((packed)); - __u32 offnpagehead __attribute__ ((packed)); - __u32 offdocend __attribute__ ((packed)); -} eicon_sff_dochead; - -typedef struct eicon_sff_pagehead { - __u8 pageheadid __attribute__ ((packed)); - __u8 pageheadlen __attribute__ ((packed)); - __u8 resvert __attribute__ ((packed)); - __u8 reshoriz __attribute__ ((packed)); - __u8 coding __attribute__ ((packed)); - __u8 reserved2 __attribute__ ((packed)); - __u16 linelength __attribute__ ((packed)); - __u16 pagelength __attribute__ ((packed)); - __u32 offprevpage __attribute__ ((packed)); - __u32 offnextpage __attribute__ ((packed)); -} eicon_sff_pagehead; - -#endif /* DSP_H */ - diff --git a/drivers/isdn/eicon/eicon_idi.c b/drivers/isdn/eicon/eicon_idi.c deleted file mode 100644 index 9cfd056b..00000000 --- a/drivers/isdn/eicon/eicon_idi.c +++ /dev/null @@ -1,3266 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for Eicon active cards. - * IDI interface - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * Thanks to Deutsche Mailbox Saar-Lor-Lux GmbH - * for sponsoring and testing fax - * capabilities with Diva Server cards. - * (dor@deutschemailbox.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. - * - * $Log$ - * Revision 1.31.2.1 2000/03/04 17:24:16 armin - * Fix of statemachine, B-connect before D-connect, - * thanks to Helmut Adams - * Minor change in send-data packet handling. - * - * Revision 1.31 2000/02/22 16:26:40 armin - * Fixed membase error message. - * Fixed missing log buffer struct. - * - * Revision 1.30 2000/02/16 16:08:46 armin - * Fixed virtual channel handling of IDI. - * - * Revision 1.29 2000/01/23 21:21:23 armin - * Added new trace capability and some updates. - * DIVA Server BRI now supports data for ISDNLOG. - * - * Revision 1.28 2000/01/20 19:55:34 keil - * Add FAX Class 1 support - * - * Revision 1.27 1999/11/29 13:12:03 armin - * Autoconnect on L2_TRANS doesn't work with link_level correctly, - * changed back to former mode. - * - * Revision 1.26 1999/11/25 11:43:27 armin - * Fixed statectrl and connect message. - * X.75 fix and HDLC/transparent with autoconnect. - * Minor cleanup. - * - * Revision 1.25 1999/11/18 20:30:55 armin - * removed old workaround for ISA cards. - * - * Revision 1.24 1999/10/26 21:15:33 armin - * using define for checking phone number len to avoid buffer overflow. - * - * Revision 1.23 1999/10/11 18:13:25 armin - * Added fax capabilities for Eicon Diva Server cards. - * - * Revision 1.22 1999/10/08 22:09:33 armin - * Some fixes of cards interface handling. - * Bugfix of NULL pointer occurence. - * Changed a few log outputs. - * - * Revision 1.21 1999/09/26 14:17:53 armin - * Improved debug and log via readstat() - * - * Revision 1.20 1999/09/21 20:35:43 armin - * added more error checking. - * - * Revision 1.19 1999/09/21 20:06:40 armin - * Added pointer checks. - * - * Revision 1.18 1999/09/07 12:48:05 armin - * Prepared for sub-address usage. - * - * Revision 1.17 1999/09/07 12:35:39 armin - * Better checking and channel Id handling. - * - * Revision 1.16 1999/09/04 13:44:19 armin - * Fix of V.42 analog Modem negotiation handling. - * - * Revision 1.15 1999/08/28 21:32:50 armin - * Prepared for fax related functions. - * Now compilable without errors/warnings. - * - * Revision 1.14 1999/08/28 20:24:40 armin - * Corrected octet 3/3a in CPN/OAD information element. - * Thanks to John Simpson - * - * Revision 1.13 1999/08/22 20:26:44 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.12 1999/08/18 20:16:59 armin - * Added XLOG function for all cards. - * Bugfix of alloc_skb NULL pointer. - * - * Revision 1.11 1999/07/25 15:12:03 armin - * fix of some debug logs. - * enabled ISA-cards option. - * - * Revision 1.10 1999/07/11 17:16:24 armin - * Bugfixes in queue handling. - * Added DSP-DTMF decoder functions. - * Reorganized ack_handler. - * - * Revision 1.9 1999/03/29 11:19:42 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.8 1999/03/02 12:37:43 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.7 1999/02/03 18:34:35 armin - * Channel selection for outgoing calls w/o CHI. - * Added channel # in debug messages. - * L2 Transparent should work with 800 byte/packet now. - * - * Revision 1.6 1999/01/26 07:18:59 armin - * Bug with wrong added CPN fixed. - * - * Revision 1.5 1999/01/24 20:14:11 armin - * Changed and added debug stuff. - * Better data sending. (still problems with tty's flip buffer) - * - * Revision 1.4 1999/01/10 18:46:05 armin - * Bug with wrong values in HLC fixed. - * Bytes to send are counted and limited now. - * - * Revision 1.3 1999/01/05 14:49:34 armin - * Added experimental usage of full BC and HLC for - * speech, 3.1kHz audio, fax gr.2/3 - * - * Revision 1.2 1999/01/04 13:19:29 armin - * Channel status with listen-request wrong - fixed. - * - * Revision 1.1 1999/01/01 18:09:41 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - -#include -#define __NO_VERSION__ -#include "eicon.h" -#include "eicon_idi.h" -#include "eicon_dsp.h" - -#undef EICON_FULL_SERVICE_OKTETT - -char *eicon_idi_revision = "$Revision$"; - -eicon_manifbuf *manbuf; - -static char BC_Speech[3] = { 0x80, 0x90, 0xa3 }; -static char BC_31khz[3] = { 0x90, 0x90, 0xa3 }; -static char BC_64k[2] = { 0x88, 0x90 }; -static char BC_video[3] = { 0x91, 0x90, 0xa5 }; - -#ifdef EICON_FULL_SERVICE_OKTETT -/* -static char HLC_telephony[2] = { 0x91, 0x81 }; -*/ -static char HLC_faxg3[2] = { 0x91, 0x84 }; -#endif - -int eicon_idi_manage_assign(eicon_card *card); -int eicon_idi_manage_remove(eicon_card *card); -int idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer); - -int -idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan) -{ - int l = 0; - int tmp; - - tmp = 0; - if (!signet) { - /* Signal Layer */ - reqbuf->XBuffer.P[l++] = CAI; - reqbuf->XBuffer.P[l++] = 1; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = KEY; - reqbuf->XBuffer.P[l++] = 3; - reqbuf->XBuffer.P[l++] = 'I'; - reqbuf->XBuffer.P[l++] = '4'; - reqbuf->XBuffer.P[l++] = 'L'; - reqbuf->XBuffer.P[l++] = SHIFT|6; - reqbuf->XBuffer.P[l++] = SIN; - reqbuf->XBuffer.P[l++] = 2; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; /* end */ - reqbuf->Req = ASSIGN; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 0; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 0; /* Sig Entity */ - } - else { - /* Network Layer */ - reqbuf->XBuffer.P[l++] = CAI; - reqbuf->XBuffer.P[l++] = 1; - reqbuf->XBuffer.P[l++] = chan->e.D3Id; - reqbuf->XBuffer.P[l++] = LLC; - reqbuf->XBuffer.P[l++] = 2; - switch(chan->l2prot) { - case ISDN_PROTO_L2_TRANS: - reqbuf->XBuffer.P[l++] = 2; /* transparent */ - break; - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - reqbuf->XBuffer.P[l++] = 5; /* X.75 */ - break; - case ISDN_PROTO_L2_MODEM: - if (chan->fsm_state == EICON_STATE_IWAIT) - reqbuf->XBuffer.P[l++] = 9; /* V.42 incoming */ - else - reqbuf->XBuffer.P[l++] = 10; /* V.42 */ - break; - case ISDN_PROTO_L2_HDLC: - case ISDN_PROTO_L2_FAX: - if (chan->fsm_state == EICON_STATE_IWAIT) - reqbuf->XBuffer.P[l++] = 3; /* autoconnect on incoming */ - else - reqbuf->XBuffer.P[l++] = 2; /* transparent */ - break; - default: - reqbuf->XBuffer.P[l++] = 1; - } - switch(chan->l3prot) { - case ISDN_PROTO_L3_FCLASS2: -#ifdef CONFIG_ISDN_TTY_FAX - reqbuf->XBuffer.P[l++] = 6; - reqbuf->XBuffer.P[l++] = NLC; - tmp = idi_fill_in_T30(chan, &reqbuf->XBuffer.P[l+1]); - reqbuf->XBuffer.P[l++] = tmp; - l += tmp; - break; -#endif - case ISDN_PROTO_L3_TRANS: - default: - reqbuf->XBuffer.P[l++] = 4; - } - reqbuf->XBuffer.P[l++] = 0; /* end */ - reqbuf->Req = ASSIGN; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 0x20; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 1; /* Net Entity */ - } - return(0); -} - -int -idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch) -{ - reqbuf->Req = rq; - reqbuf->ReqCh = Ch; - reqbuf->ReqId = 1; - reqbuf->XBuffer.length = 1; - reqbuf->XBuffer.P[0] = 0; - reqbuf->Reference = signet; - return(0); -} - -int -idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan) -{ - int l = 9; - reqbuf->Req = CALL_RES; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 1; - reqbuf->XBuffer.P[0] = CAI; - reqbuf->XBuffer.P[1] = 6; - reqbuf->XBuffer.P[2] = 9; - reqbuf->XBuffer.P[3] = 0; - reqbuf->XBuffer.P[4] = 0; - reqbuf->XBuffer.P[5] = 0; - reqbuf->XBuffer.P[6] = 32; - reqbuf->XBuffer.P[7] = 3; - switch(chan->l2prot) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - case ISDN_PROTO_L2_HDLC: - reqbuf->XBuffer.P[1] = 1; - reqbuf->XBuffer.P[2] = 0x05; - l = 4; - break; - case ISDN_PROTO_L2_V11096: - reqbuf->XBuffer.P[2] = 0x0d; - reqbuf->XBuffer.P[3] = 5; - reqbuf->XBuffer.P[4] = 0; - break; - case ISDN_PROTO_L2_V11019: - reqbuf->XBuffer.P[2] = 0x0d; - reqbuf->XBuffer.P[3] = 6; - reqbuf->XBuffer.P[4] = 0; - break; - case ISDN_PROTO_L2_V11038: - reqbuf->XBuffer.P[2] = 0x0d; - reqbuf->XBuffer.P[3] = 7; - reqbuf->XBuffer.P[4] = 0; - break; - case ISDN_PROTO_L2_MODEM: - reqbuf->XBuffer.P[2] = 0x11; - reqbuf->XBuffer.P[3] = 7; - reqbuf->XBuffer.P[4] = 0; - reqbuf->XBuffer.P[5] = 0; - reqbuf->XBuffer.P[6] = 128; - reqbuf->XBuffer.P[7] = 0; - break; - case ISDN_PROTO_L2_FAX: - reqbuf->XBuffer.P[2] = 0x10; - reqbuf->XBuffer.P[3] = 0; - reqbuf->XBuffer.P[4] = 0; - reqbuf->XBuffer.P[5] = 0; - reqbuf->XBuffer.P[6] = 128; - reqbuf->XBuffer.P[7] = 0; - break; - case ISDN_PROTO_L2_TRANS: - switch(chan->l3prot) { - case ISDN_PROTO_L3_TRANSDSP: - reqbuf->XBuffer.P[2] = 22; /* DTMF, audio events on */ - } - break; - } - reqbuf->XBuffer.P[8] = 0; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 0; /* Sig Entity */ - eicon_log(NULL, 8, "idi_req: Ch%d: Call_Res\n", chan->No); - return(0); -} - -int -idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in do_req()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - eicon_log(card, 8, "idi_req: Ch%d: req %x (%s)\n", chan->No, cmd, (layer)?"Net":"Sig"); - if (layer) cmd |= 0x700; - switch(cmd) { - case ASSIGN: - case ASSIGN|0x700: - idi_assign_req(reqbuf, layer, chan); - break; - case REMOVE: - case REMOVE|0x700: - idi_put_req(reqbuf, REMOVE, layer, 0); - break; - case INDICATE_REQ: - idi_put_req(reqbuf, INDICATE_REQ, 0, 0); - break; - case HANGUP: - idi_put_req(reqbuf, HANGUP, 0, 0); - break; - case REJECT: - idi_put_req(reqbuf, REJECT, 0 ,0); - break; - case CALL_ALERT: - idi_put_req(reqbuf, CALL_ALERT, 0, 0); - break; - case CALL_RES: - idi_call_res_req(reqbuf, chan); - break; - case IDI_N_CONNECT|0x700: - idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0); - break; - case IDI_N_CONNECT_ACK|0x700: - idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0); - break; - case IDI_N_DISC|0x700: - idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh); - break; - case IDI_N_DISC_ACK|0x700: - idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh); - break; - default: - eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No); - dev_kfree_skb(skb); - dev_kfree_skb(skb2); - return(-1); - } - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_schedule_tx(card); - return(0); -} - -int -eicon_idi_listen_req(eicon_card *card, eicon_chan *chan) -{ - if ((!card) || (!chan)) - return 1; - - eicon_log(card, 16, "idi_req: Ch%d: Listen_Req eazmask=0x%x\n",chan->No, chan->eazmask); - if (!chan->e.D3Id) { - idi_do_req(card, chan, ASSIGN, 0); - } - if (chan->fsm_state == EICON_STATE_NULL) { - if (!(chan->statectrl & HAVE_CONN_REQ)) { - idi_do_req(card, chan, INDICATE_REQ, 0); - chan->fsm_state = EICON_STATE_LISTEN; - } - } - return(0); -} - -unsigned char -idi_si2bc(int si1, int si2, char *bc, char *hlc) -{ - hlc[0] = 0; - switch(si1) { - case 1: - bc[0] = 0x90; /* 3,1 kHz audio */ - bc[1] = 0x90; /* 64 kbit/s */ - bc[2] = 0xa3; /* G.711 A-law */ -#ifdef EICON_FULL_SERVICE_OKTETT - if (si2 == 1) { - bc[0] = 0x80; /* Speech */ - hlc[0] = 0x02; /* hlc len */ - hlc[1] = 0x91; /* first hic */ - hlc[2] = 0x81; /* Telephony */ - } -#endif - return(3); - case 2: - bc[0] = 0x90; /* 3,1 kHz audio */ - bc[1] = 0x90; /* 64 kbit/s */ - bc[2] = 0xa3; /* G.711 A-law */ -#ifdef EICON_FULL_SERVICE_OKTETT - if (si2 == 2) { - hlc[0] = 0x02; /* hlc len */ - hlc[1] = 0x91; /* first hic */ - hlc[2] = 0x84; /* Fax Gr.2/3 */ - } -#endif - return(3); - case 5: - case 7: - default: - bc[0] = 0x88; - bc[1] = 0x90; - return(2); - } - return (0); -} - -int -idi_hangup(eicon_card *card, eicon_chan *chan) -{ - if ((!card) || (!chan)) - return 1; - - if ((chan->fsm_state == EICON_STATE_ACTIVE) || - (chan->fsm_state == EICON_STATE_WMCONN)) { - if (chan->e.B2Id) idi_do_req(card, chan, IDI_N_DISC, 1); - } - if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1); - if (chan->fsm_state != EICON_STATE_NULL) { - chan->statectrl |= WAITING_FOR_HANGUP; - idi_do_req(card, chan, HANGUP, 0); - chan->fsm_state = EICON_STATE_NULL; - } - eicon_log(card, 8, "idi_req: Ch%d: Hangup\n", chan->No); -#ifdef CONFIG_ISDN_TTY_FAX - chan->fax = 0; -#endif - return(0); -} - -int -idi_connect_res(eicon_card *card, eicon_chan *chan) -{ - if ((!card) || (!chan)) - return 1; - - chan->fsm_state = EICON_STATE_IWAIT; - - /* check if old NetID has been removed */ - if (chan->e.B2Id) { - eicon_log(card, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n", - chan->No, chan->e.B2Id); - idi_do_req(card, chan, REMOVE, 1); - } - - idi_do_req(card, chan, ASSIGN, 1); - idi_do_req(card, chan, CALL_RES, 0); - return(0); -} - -int -idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, - char *eazmsn, int si1, int si2) -{ - int l = 0; - int i; - unsigned char tmp; - unsigned char *sub, *sp; - unsigned char bc[5]; - unsigned char hlc[5]; - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - if ((!card) || (!chan)) - return 1; - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in connect_req()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - reqbuf->Req = CALL_REQ; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 1; - - sub = NULL; - sp = phone; - while (*sp) { - if (*sp == '.') { - sub = sp + 1; - *sp = 0; - } else - sp++; - } - reqbuf->XBuffer.P[l++] = CPN; - reqbuf->XBuffer.P[l++] = strlen(phone) + 1; - reqbuf->XBuffer.P[l++] = 0x81; - for(i=0; iXBuffer.P[l++] = phone[i] & 0x7f; - if (sub) { - reqbuf->XBuffer.P[l++] = DSA; - reqbuf->XBuffer.P[l++] = strlen(sub) + 2; - reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */ - reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */ - while (*sub) - reqbuf->XBuffer.P[l++] = *sub++ & 0x7f; - } - - sub = NULL; - sp = eazmsn; - while (*sp) { - if (*sp == '.') { - sub = sp + 1; - *sp = 0; - } else - sp++; - } - reqbuf->XBuffer.P[l++] = OAD; - reqbuf->XBuffer.P[l++] = strlen(eazmsn) + 2; - reqbuf->XBuffer.P[l++] = 0x01; - reqbuf->XBuffer.P[l++] = 0x80; - for(i=0; iXBuffer.P[l++] = eazmsn[i] & 0x7f; - if (sub) { - reqbuf->XBuffer.P[l++] = OSA; - reqbuf->XBuffer.P[l++] = strlen(sub) + 2; - reqbuf->XBuffer.P[l++] = 0x80; /* NSAP coded */ - reqbuf->XBuffer.P[l++] = 0x50; /* local IDI format */ - while (*sub) - reqbuf->XBuffer.P[l++] = *sub++ & 0x7f; - } - - if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) { - reqbuf->XBuffer.P[l++] = BC; - reqbuf->XBuffer.P[l++] = tmp; - for(i=0; iXBuffer.P[l++] = bc[i]; - if ((tmp=hlc[0])) { - reqbuf->XBuffer.P[l++] = HLC; - reqbuf->XBuffer.P[l++] = tmp; - for(i=1; i<=tmp;i++) - reqbuf->XBuffer.P[l++] = hlc[i]; - } - } - - reqbuf->XBuffer.P[l++] = CAI; - reqbuf->XBuffer.P[l++] = 6; - reqbuf->XBuffer.P[l++] = 0x09; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 0; - reqbuf->XBuffer.P[l++] = 32; - reqbuf->XBuffer.P[l++] = 3; - switch(chan->l2prot) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - case ISDN_PROTO_L2_HDLC: - reqbuf->XBuffer.P[l-6] = 5; - reqbuf->XBuffer.P[l-7] = 1; - l -= 5; - break; - case ISDN_PROTO_L2_V11096: - reqbuf->XBuffer.P[l-7] = 3; - reqbuf->XBuffer.P[l-6] = 0x0d; - reqbuf->XBuffer.P[l-5] = 5; - reqbuf->XBuffer.P[l-4] = 0; - l -= 3; - break; - case ISDN_PROTO_L2_V11019: - reqbuf->XBuffer.P[l-7] = 3; - reqbuf->XBuffer.P[l-6] = 0x0d; - reqbuf->XBuffer.P[l-5] = 6; - reqbuf->XBuffer.P[l-4] = 0; - l -= 3; - break; - case ISDN_PROTO_L2_V11038: - reqbuf->XBuffer.P[l-7] = 3; - reqbuf->XBuffer.P[l-6] = 0x0d; - reqbuf->XBuffer.P[l-5] = 7; - reqbuf->XBuffer.P[l-4] = 0; - l -= 3; - break; - case ISDN_PROTO_L2_MODEM: - reqbuf->XBuffer.P[l-6] = 0x11; - reqbuf->XBuffer.P[l-5] = 7; - reqbuf->XBuffer.P[l-4] = 0; - reqbuf->XBuffer.P[l-3] = 0; - reqbuf->XBuffer.P[l-2] = 128; - reqbuf->XBuffer.P[l-1] = 0; - break; - case ISDN_PROTO_L2_FAX: - reqbuf->XBuffer.P[l-6] = 0x10; - reqbuf->XBuffer.P[l-5] = 0; - reqbuf->XBuffer.P[l-4] = 0; - reqbuf->XBuffer.P[l-3] = 0; - reqbuf->XBuffer.P[l-2] = 128; - reqbuf->XBuffer.P[l-1] = 0; - break; - case ISDN_PROTO_L2_TRANS: - switch(chan->l3prot) { - case ISDN_PROTO_L3_TRANSDSP: - reqbuf->XBuffer.P[l-6] = 22; /* DTMF, audio events on */ - } - break; - } - - reqbuf->XBuffer.P[l++] = 0; /* end */ - reqbuf->XBuffer.length = l; - reqbuf->Reference = 0; /* Sig Entity */ - - if (chan->statectrl & WAITING_FOR_HANGUP) { - /* If the line did not disconnect yet, - we have to delay this command */ - eicon_log(card, 32, "idi_req: Ch%d: delaying conn_req\n", chan->No); - chan->statectrl |= HAVE_CONN_REQ; - chan->tskb1 = skb; - chan->tskb2 = skb2; - } else { - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_schedule_tx(card); - } - - eicon_log(card, 8, "idi_req: Ch%d: Conn_Req %s -> %s\n",chan->No, eazmsn, phone); - return(0); -} - - -void -idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsigned char *buffer, int len) -{ - int i,j; - int pos = 0; - int codeset = 0; - int wlen = 0; - int lock = 0; - __u8 w; - __u16 code; - isdn_ctrl cmd; - - memset(message, 0, sizeof(idi_ind_message)); - - if ((!len) || (!buffer[pos])) return; - - while(pos <= len) { - w = buffer[pos++]; - if (!w) return; - if (w & 0x80) { - wlen = 0; - } - else { - wlen = buffer[pos++]; - } - - if (pos > len) return; - - if (lock & 0x80) lock &= 0x7f; - else codeset = lock; - - if((w&0xf0) == SHIFT) { - codeset = w; - if(!(codeset & 0x08)) lock = codeset & 7; - codeset &= 7; - lock |= 0x80; - } - else { - if (w==ESC && wlen >=2) { - code = buffer[pos++]|0x800; - wlen--; - } - else code = w; - code |= (codeset<<8); - - if (pos + wlen > len) { - eicon_log(ccard, 1, "idi_err: Ch%d: IElen %d of %x exceeds Ind_Length (+%d)\n", chan->No, - wlen, code, (pos + wlen) - len); - return; - } - - switch(code) { - case OAD: - if (wlen > sizeof(message->oad)) { - pos += wlen; - break; - } - j = 1; - if (wlen) { - message->plan = buffer[pos++]; - if (message->plan &0x80) - message->screen = 0; - else { - message->screen = buffer[pos++]; - j = 2; - } - } - for(i=0; i < wlen-j; i++) - message->oad[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: OAD=(0x%02x,0x%02x) %s\n", chan->No, - message->plan, message->screen, message->oad); - break; - case RDN: - if (wlen > sizeof(message->rdn)) { - pos += wlen; - break; - } - j = 1; - if (wlen) { - if (!(buffer[pos++] & 0x80)) { - pos++; - j = 2; - } - } - for(i=0; i < wlen-j; i++) - message->rdn[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: RDN= %s\n", chan->No, - message->rdn); - break; - case CPN: - if (wlen > sizeof(message->cpn)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->cpn[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: CPN=(0x%02x) %s\n", chan->No, - (__u8)message->cpn[0], message->cpn + 1); - break; - case DSA: - if (wlen > sizeof(message->dsa)) { - pos += wlen; - break; - } - pos += 2; - for(i=0; i < wlen-2; i++) - message->dsa[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: DSA=%s\n", chan->No, message->dsa); - break; - case OSA: - if (wlen > sizeof(message->osa)) { - pos += wlen; - break; - } - pos += 2; - for(i=0; i < wlen-2; i++) - message->osa[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: OSA=%s\n", chan->No, message->osa); - break; - case CAD: - pos += wlen; - eicon_log(ccard, 2, "idi_inf: Ch%d: Connected Address in ind, len:%x\n", - chan->No, wlen); - break; - case BC: - if (wlen > sizeof(message->bc)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->bc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: BC = 0x%02x 0x%02x 0x%02x\n", chan->No, - message->bc[0],message->bc[1],message->bc[2]); - break; - case 0x800|BC: - if (wlen > sizeof(message->e_bc)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->e_bc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/BC=%d\n", chan->No, message->bc[0]); - break; - case LLC: - if (wlen > sizeof(message->llc)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->llc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: LLC=%d %d %d %d\n", chan->No, message->llc[0], - message->llc[1],message->llc[2],message->llc[3]); - break; - case HLC: - if (wlen > sizeof(message->hlc)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->hlc[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: HLC=%x %x %x %x %x\n", chan->No, - message->hlc[0], message->hlc[1], - message->hlc[2], message->hlc[3], message->hlc[4]); - break; - case DSP: - case 0x600|DSP: - if (wlen > sizeof(message->display)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->display[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: Display: %s\n", chan->No, - message->display); - break; - case 0x600|KEY: - if (wlen > sizeof(message->keypad)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->keypad[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: Keypad: %s\n", chan->No, - message->keypad); - break; - case NI: - case 0x600|NI: - if (wlen) { - switch(buffer[pos] & 127) { - case 0: - eicon_log(ccard, 4, "idi_inf: Ch%d: User suspended.\n", chan->No); - break; - case 1: - eicon_log(ccard, 4, "idi_inf: Ch%d: User resumed.\n", chan->No); - break; - case 2: - eicon_log(ccard, 4, "idi_inf: Ch%d: Bearer service change.\n", chan->No); - break; - default: - eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Notification %x.\n", - chan->No, buffer[pos] & 127); - } - pos += wlen; - } - break; - case PI: - case 0x600|PI: - if (wlen > 1) { - switch(buffer[pos+1] & 127) { - case 1: - eicon_log(ccard, 4, "idi_inf: Ch%d: Call is not end-to-end ISDN.\n", chan->No); - break; - case 2: - eicon_log(ccard, 4, "idi_inf: Ch%d: Destination address is non ISDN.\n", chan->No); - break; - case 3: - eicon_log(ccard, 4, "idi_inf: Ch%d: Origination address is non ISDN.\n", chan->No); - break; - case 4: - eicon_log(ccard, 4, "idi_inf: Ch%d: Call has returned to the ISDN.\n", chan->No); - break; - case 5: - eicon_log(ccard, 4, "idi_inf: Ch%d: Interworking has occurred.\n", chan->No); - break; - case 8: - eicon_log(ccard, 4, "idi_inf: Ch%d: In-band information available.\n", chan->No); - break; - default: - eicon_log(ccard, 4, "idi_inf: Ch%d: Unknown Progress %x.\n", - chan->No, buffer[pos+1] & 127); - } - } - pos += wlen; - break; - case CAU: - if (wlen > sizeof(message->cau)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->cau[i] = buffer[pos++]; - memcpy(&chan->cause, &message->cau, 2); - eicon_log(ccard, 4, "idi_inf: Ch%d: CAU=%d %d\n", chan->No, - message->cau[0],message->cau[1]); - break; - case 0x800|CAU: - if (wlen > sizeof(message->e_cau)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->e_cau[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: ECAU=%d %d\n", chan->No, - message->e_cau[0],message->e_cau[1]); - break; - case 0x800|CHI: - if (wlen > sizeof(message->e_chi)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->e_chi[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: ESC/CHI=%d\n", chan->No, - message->e_cau[0]); - break; - case 0x800|0x7a: - pos ++; - message->e_mt=buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: EMT=0x%x\n", chan->No, message->e_mt); - break; - case DT: - if (wlen > sizeof(message->dt)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->dt[i] = buffer[pos++]; - eicon_log(ccard, 4, "idi_inf: Ch%d: DT: %02d.%02d.%02d %02d:%02d:%02d\n", chan->No, - message->dt[2], message->dt[1], message->dt[0], - message->dt[3], message->dt[4], message->dt[5]); - break; - case 0x600|SIN: - if (wlen > sizeof(message->sin)) { - pos += wlen; - break; - } - for(i=0; i < wlen; i++) - message->sin[i] = buffer[pos++]; - eicon_log(ccard, 2, "idi_inf: Ch%d: SIN=%d %d\n", chan->No, - message->sin[0],message->sin[1]); - break; - case 0x600|CPS: - eicon_log(ccard, 2, "idi_inf: Ch%d: Called Party Status in ind\n", chan->No); - pos += wlen; - break; - case 0x600|CIF: - for (i = 0; i < wlen; i++) - if (buffer[pos + i] != '0') break; - memcpy(&cmd.parm.num, &buffer[pos + i], wlen - i); - cmd.parm.num[wlen - i] = 0; - eicon_log(ccard, 2, "idi_inf: Ch%d: CIF=%s\n", chan->No, cmd.parm.num); - pos += wlen; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_CINF; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - break; - case 0x600|DATE: - eicon_log(ccard, 2, "idi_inf: Ch%d: Date in ind\n", chan->No); - pos += wlen; - break; - case 0xa1: - eicon_log(ccard, 2, "idi_inf: Ch%d: Sending Complete in ind.\n", chan->No); - pos += wlen; - break; - case 0xe08: - case 0xe7a: - case 0xe04: - case 0xe00: - /* *** TODO *** */ - case CHA: - /* Charge advice */ - case FTY: - case 0x600|FTY: - case CHI: - case 0x800: - /* Not yet interested in this */ - pos += wlen; - break; - case 0x880: - /* Managment Information Element */ - if (!manbuf) { - eicon_log(ccard, 1, "idi_err: manbuf not allocated\n"); - } - else { - memcpy(&manbuf->data[manbuf->pos], &buffer[pos], wlen); - manbuf->length[manbuf->count] = wlen; - manbuf->count++; - manbuf->pos += wlen; - } - pos += wlen; - break; - default: - pos += wlen; - eicon_log(ccard, 6, "idi_inf: Ch%d: unknown information element 0x%x in ind, len:%x\n", - chan->No, code, wlen); - } - } - } -} - -void -idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2) -{ - si1[0] = 0; - si2[0] = 0; - if (memcmp(bc, BC_Speech, 3) == 0) { /* Speech */ - si1[0] = 1; -#ifdef EICON_FULL_SERVICE_OKTETT - si2[0] = 1; -#endif - } - if (memcmp(bc, BC_31khz, 3) == 0) { /* 3.1kHz audio */ - si1[0] = 1; -#ifdef EICON_FULL_SERVICE_OKTETT - si2[0] = 2; - if (memcmp(hlc, HLC_faxg3, 2) == 0) { /* Fax Gr.2/3 */ - si1[0] = 2; - } -#endif - } - if (memcmp(bc, BC_64k, 2) == 0) { /* unrestricted 64 kbits */ - si1[0] = 7; - } - if (memcmp(bc, BC_video, 3) == 0) { /* video */ - si1[0] = 4; - } -} - -/********************* FAX stuff ***************************/ - -#ifdef CONFIG_ISDN_TTY_FAX - -int -idi_fill_in_T30(eicon_chan *chan, unsigned char *buffer) -{ - eicon_t30_s *t30 = (eicon_t30_s *) buffer; - - if (!chan->fax) { - eicon_log(NULL, 1,"idi_T30: fill_in with NULL fax struct, ERROR\n"); - return 0; - } - memset(t30, 0, sizeof(eicon_t30_s)); - t30->station_id_len = EICON_FAXID_LEN; - memcpy(&t30->station_id[0], &chan->fax->id[0], EICON_FAXID_LEN); - t30->resolution = chan->fax->resolution; - t30->rate = chan->fax->rate + 1; /* eicon rate starts with 1 */ - t30->format = T30_FORMAT_SFF; - t30->pages_low = 0; - t30->pages_high = 0; - t30->atf = 1; /* optimised for AT+F command set */ - t30->code = 0; - t30->feature_bits_low = 0; - t30->feature_bits_high = 0; - t30->control_bits_low = 0; - t30->control_bits_high = 0; - - if (chan->fax->nbc) { - /* set compression by DCC value */ - switch(chan->fax->compression) { - case (0): /* 1-D modified */ - break; - case (1): /* 2-D modified Read */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - break; - case (2): /* 2-D uncompressed */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - break; - case (3): /* 2-D modified Read */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; - t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; - t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - break; - } - } else { - /* set compression to best */ - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_T6_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_UNCOMPR; - t30->feature_bits_low |= T30_FEATURE_BIT_UNCOMPR_ENABLED; - t30->feature_bits_low |= T30_FEATURE_BIT_T6_CODING; - t30->feature_bits_low |= T30_FEATURE_BIT_2D_CODING; - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - } - switch(chan->fax->ecm) { - case (0): /* disable ECM */ - break; - case (1): - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->control_bits_low |= T30_CONTROL_BIT_ECM_64_BYTES; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM_64_BYTES; - break; - case (2): - t30->control_bits_low |= T30_CONTROL_BIT_ENABLE_ECM; - t30->feature_bits_low |= T30_FEATURE_BIT_ECM; - break; - } - - if (DebugVar & 128) { - char st[40]; - eicon_log(NULL, 128, "sT30:code = %x\n", t30->code); - eicon_log(NULL, 128, "sT30:rate = %x\n", t30->rate); - eicon_log(NULL, 128, "sT30:res = %x\n", t30->resolution); - eicon_log(NULL, 128, "sT30:format = %x\n", t30->format); - eicon_log(NULL, 128, "sT30:pages_low = %x\n", t30->pages_low); - eicon_log(NULL, 128, "sT30:pages_high = %x\n", t30->pages_high); - eicon_log(NULL, 128, "sT30:atf = %x\n", t30->atf); - eicon_log(NULL, 128, "sT30:control_bits_low = %x\n", t30->control_bits_low); - eicon_log(NULL, 128, "sT30:control_bits_high = %x\n", t30->control_bits_high); - eicon_log(NULL, 128, "sT30:feature_bits_low = %x\n", t30->feature_bits_low); - eicon_log(NULL, 128, "sT30:feature_bits_high = %x\n", t30->feature_bits_high); - //eicon_log(NULL, 128, "sT30:universal_5 = %x\n", t30->universal_5); - //eicon_log(NULL, 128, "sT30:universal_6 = %x\n", t30->universal_6); - //eicon_log(NULL, 128, "sT30:universal_7 = %x\n", t30->universal_7); - eicon_log(NULL, 128, "sT30:station_id_len = %x\n", t30->station_id_len); - eicon_log(NULL, 128, "sT30:head_line_len = %x\n", t30->head_line_len); - strncpy(st, t30->station_id, t30->station_id_len); - st[t30->station_id_len] = 0; - eicon_log(NULL, 128, "sT30:station_id = <%s>\n", st); - } - return(sizeof(eicon_t30_s)); -} - -/* send fax struct */ -int -idi_send_edata(eicon_card *card, eicon_chan *chan) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { - eicon_log(card, 1, "idi_snd: Ch%d: send edata on state %d !\n", chan->No, chan->fsm_state); - return -ENODEV; - } - eicon_log(card, 128, "idi_snd: Ch%d: edata (fax)\n", chan->No); - - skb = alloc_skb(sizeof(eicon_REQ) + sizeof(eicon_t30_s), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_edata()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ)); - - reqbuf->Req = IDI_N_EDATA; - reqbuf->ReqCh = chan->e.IndCh; - reqbuf->ReqId = 1; - - reqbuf->XBuffer.length = idi_fill_in_T30(chan, reqbuf->XBuffer.P); - reqbuf->Reference = 1; /* Net Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_schedule_tx(card); - return (0); -} - -void -idi_parse_edata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len) -{ - eicon_t30_s *p = (eicon_t30_s *)buffer; - int i; - - if (DebugVar & 128) { - char st[40]; - eicon_log(ccard, 128, "rT30:len %d , size %d\n", len, sizeof(eicon_t30_s)); - eicon_log(ccard, 128, "rT30:code = %x\n", p->code); - eicon_log(ccard, 128, "rT30:rate = %x\n", p->rate); - eicon_log(ccard, 128, "rT30:res = %x\n", p->resolution); - eicon_log(ccard, 128, "rT30:format = %x\n", p->format); - eicon_log(ccard, 128, "rT30:pages_low = %x\n", p->pages_low); - eicon_log(ccard, 128, "rT30:pages_high = %x\n", p->pages_high); - eicon_log(ccard, 128, "rT30:atf = %x\n", p->atf); - eicon_log(ccard, 128, "rT30:control_bits_low = %x\n", p->control_bits_low); - eicon_log(ccard, 128, "rT30:control_bits_high = %x\n", p->control_bits_high); - eicon_log(ccard, 128, "rT30:feature_bits_low = %x\n", p->feature_bits_low); - eicon_log(ccard, 128, "rT30:feature_bits_high = %x\n", p->feature_bits_high); - //eicon_log(ccard, 128, "rT30:universal_5 = %x\n", p->universal_5); - //eicon_log(ccard, 128, "rT30:universal_6 = %x\n", p->universal_6); - //eicon_log(ccard, 128, "rT30:universal_7 = %x\n", p->universal_7); - eicon_log(ccard, 128, "rT30:station_id_len = %x\n", p->station_id_len); - eicon_log(ccard, 128, "rT30:head_line_len = %x\n", p->head_line_len); - strncpy(st, p->station_id, p->station_id_len); - st[p->station_id_len] = 0; - eicon_log(ccard, 128, "rT30:station_id = <%s>\n", st); - } - if (!chan->fax) { - eicon_log(ccard, 1, "idi_edata: parse to NULL fax struct, ERROR\n"); - return; - } - chan->fax->code = p->code; - i = (p->station_id_len < FAXIDLEN) ? p->station_id_len : (FAXIDLEN - 1); - memcpy(chan->fax->r_id, p->station_id, i); - chan->fax->r_id[i] = 0; - chan->fax->r_resolution = p->resolution; - chan->fax->r_rate = p->rate - 1; - chan->fax->r_binary = 0; /* no binary support */ - chan->fax->r_width = 0; - chan->fax->r_length = 2; - chan->fax->r_scantime = 0; - chan->fax->r_compression = 0; - chan->fax->r_ecm = 0; - if (p->feature_bits_low & T30_FEATURE_BIT_2D_CODING) { - chan->fax->r_compression = 1; - if (p->feature_bits_low & T30_FEATURE_BIT_UNCOMPR_ENABLED) { - chan->fax->r_compression = 2; - } - } - if (p->feature_bits_low & T30_FEATURE_BIT_T6_CODING) { - chan->fax->r_compression = 3; - } - - if (p->feature_bits_low & T30_FEATURE_BIT_ECM) { - chan->fax->r_ecm = 2; - if (p->feature_bits_low & T30_FEATURE_BIT_ECM_64_BYTES) - chan->fax->r_ecm = 1; - } -} - -void -idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header) -{ - static __u16 wd2sff[] = { - 1728, 2048, 2432, 1216, 864 - }; - static __u16 ln2sff[2][3] = { - { 1143, 1401, 0 } , { 2287, 2802, 0 } - }; - struct sk_buff *skb; - eicon_sff_dochead *doc; - eicon_sff_pagehead *page; - u_char *docp; - - if (!chan->fax) { - eicon_log(card, 1, "idi_fax: send head with NULL fax struct, ERROR\n"); - return; - } - if (header == 2) { /* DocHeader + PageHeader */ - skb = alloc_skb(sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead), GFP_ATOMIC); - } else { - skb = alloc_skb(sizeof(eicon_sff_pagehead), GFP_ATOMIC); - } - if (!skb) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_header()\n", chan->No); - return; - } - - if (header == 2) { /* DocHeader + PageHeader */ - docp = skb_put(skb, sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); - doc = (eicon_sff_dochead *) docp; - page = (eicon_sff_pagehead *) (docp + sizeof(eicon_sff_dochead)); - memset(docp, 0,sizeof(eicon_sff_dochead) + sizeof(eicon_sff_pagehead)); - doc->id = 0x66666653; - doc->version = 0x01; - doc->off1pagehead = sizeof(eicon_sff_dochead); - } else { - page = (eicon_sff_pagehead *)skb_put(skb, sizeof(eicon_sff_pagehead)); - memset(page, 0, sizeof(eicon_sff_pagehead)); - } - - switch(header) { - case 1: /* PageHeaderEnd */ - page->pageheadid = 254; - page->pageheadlen = 0; - break; - case 0: /* PageHeader */ - case 2: /* DocHeader + PageHeader */ - page->pageheadid = 254; - page->pageheadlen = sizeof(eicon_sff_pagehead) - 2; - page->resvert = chan->fax->resolution; - page->reshoriz = 0; /* always 203 dpi */ - page->coding = 0; /* always 1D */ - page->linelength = wd2sff[chan->fax->width]; - page->pagelength = ln2sff[chan->fax->resolution][chan->fax->length]; - eicon_log(card, 128, "sSFF-Head: linelength = %d\n", page->linelength); - eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength); - break; - } - idi_send_data(card, chan, 0, skb, 0); -} - -void -idi_fax_cmd(eicon_card *card, eicon_chan *chan) -{ - isdn_ctrl cmd; - - if ((!card) || (!chan)) - return; - - if (!chan->fax) { - eicon_log(card, 1, "idi_fax: cmd with NULL fax struct, ERROR\n"); - return; - } - switch (chan->fax->code) { - case ISDN_TTY_FAX_DT: - if (chan->fax->phase == ISDN_FAX_PHASE_B) { - idi_send_edata(card, chan); - break; - } - if (chan->fax->phase == ISDN_FAX_PHASE_D) { - idi_send_edata(card, chan); - break; - } - break; - - case ISDN_TTY_FAX_DR: - if (chan->fax->phase == ISDN_FAX_PHASE_B) { - idi_send_edata(card, chan); - - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_CFR; - card->interface.statcallb(&cmd); - - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_RID; - card->interface.statcallb(&cmd); - - /* telling 1-D compression */ - chan->fax->r_compression = 0; - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DCS; - card->interface.statcallb(&cmd); - - chan->fax2.NextObject = FAX_OBJECT_DOCU; - chan->fax2.PrevObject = FAX_OBJECT_DOCU; - - break; - } - if (chan->fax->phase == ISDN_FAX_PHASE_D) { - idi_send_edata(card, chan); - break; - } - break; - - case ISDN_TTY_FAX_ET: - switch(chan->fax->fet) { - case 0: - case 1: - idi_fax_send_header(card, chan, 0); - break; - case 2: - idi_fax_send_header(card, chan, 1); - break; - } - break; - } -} - -void -idi_edata_rcveop(eicon_card *card, eicon_chan *chan) -{ - isdn_ctrl cmd; - - if (!chan->fax) { - eicon_log(card, 1, "idi_edata: rcveop with NULL fax struct, ERROR\n"); - return; - } - cmd.driver = card->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_ET; - card->interface.statcallb(&cmd); -} - -void -idi_reset_fax_stat(eicon_chan *chan) -{ - chan->fax2.LineLen = 0; - chan->fax2.LineData = 0; - chan->fax2.LineDataLen = 0; - chan->fax2.NullByteExist = 0; - chan->fax2.Dle = 0; - chan->fax2.PageCount = 0; - chan->fax2.Eop = 0; -} - -void -idi_edata_action(eicon_card *ccard, eicon_chan *chan, char *buffer, int len) -{ - isdn_ctrl cmd; - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_edata: action with NULL fax struct, ERROR\n"); - return; - } - if (chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) { - idi_parse_edata(ccard, chan, buffer, len); - - if (chan->fax->phase == ISDN_FAX_PHASE_A) { - idi_reset_fax_stat(chan); - - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, ""); - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_FCON; - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_RID; - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DIS; - ccard->interface.statcallb(&cmd); - - if (chan->fax->r_compression != 0) { - /* telling fake compression in second DIS message */ - chan->fax->r_compression = 0; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DIS; - ccard->interface.statcallb(&cmd); - } - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_SENT; /* OK message */ - ccard->interface.statcallb(&cmd); - } else - if (chan->fax->phase == ISDN_FAX_PHASE_D) { - - if ((chan->fax->code == EDATA_T30_MCF) && - (chan->fax->fet != 2)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_PTS; - ccard->interface.statcallb(&cmd); - } - - switch(chan->fax->fet) { - case 0: /* new page */ - /* stay in phase D , wait on cmd +FDT */ - break; - case 1: /* new document */ - /* link-level switch to phase B */ - break; - case 2: /* session end */ - default: - /* send_edata produces error on some */ - /* fax-machines here, so we don't */ - /* idi_send_edata(ccard, chan); */ - break; - } - } - } - - if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { - idi_parse_edata(ccard, chan, buffer, len); - - if ((chan->fax->code == EDATA_T30_DCS) && - (chan->fax->phase == ISDN_FAX_PHASE_A)) { - idi_reset_fax_stat(chan); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, ""); - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_FCON_I; - ccard->interface.statcallb(&cmd); - } else - if ((chan->fax->code == EDATA_T30_TRAIN_OK) && - (chan->fax->phase == ISDN_FAX_PHASE_A)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_RID; - ccard->interface.statcallb(&cmd); - - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; - ccard->interface.statcallb(&cmd); - } else - if ((chan->fax->code == EDATA_T30_TRAIN_OK) && - (chan->fax->phase == ISDN_FAX_PHASE_B)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_TRAIN_OK; - ccard->interface.statcallb(&cmd); - } else - if (chan->fax->phase == ISDN_FAX_PHASE_C) { - switch(chan->fax->code) { - case EDATA_T30_TRAIN_OK: - idi_send_edata(ccard, chan); - break; - case EDATA_T30_MPS: - chan->fax->fet = 0; - idi_edata_rcveop(ccard, chan); - break; - case EDATA_T30_EOM: - chan->fax->fet = 1; - idi_edata_rcveop(ccard, chan); - break; - case EDATA_T30_EOP: - chan->fax->fet = 2; - idi_edata_rcveop(ccard, chan); - break; - } - } - } -} - -void -fax_put_rcv(eicon_card *ccard, eicon_chan *chan, u_char *Data, int len) -{ - struct sk_buff *skb; - - skb = alloc_skb(len + MAX_HEADER_LEN, GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_put_rcv()\n", chan->No); - return; - } - skb_reserve(skb, MAX_HEADER_LEN); - memcpy(skb_put(skb, len), Data, len); - ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb); -} - -void -idi_faxdata_rcv(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) -{ - eicon_OBJBUFFER InBuf; - eicon_OBJBUFFER LineBuf; - unsigned int Length = 0; - unsigned int aLength = 0; - unsigned int ObjectSize = 0; - unsigned int ObjHeadLen = 0; - unsigned int ObjDataLen = 0; - __u8 Recordtype; - __u8 PageHeaderLen; - __u8 Event; - eicon_sff_pagehead *ob_page; - - __u16 Cl2Eol = 0x8000; - -# define EVENT_NONE 0 -# define EVENT_NEEDDATA 1 - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_fax: rcvdata with NULL fax struct, ERROR\n"); - 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) { - InBuf.Data = skb->data; - InBuf.Size = skb->len; - InBuf.Len = 0; - InBuf.Next = InBuf.Data; - LineBuf.Data = chan->fax2.abLine; - LineBuf.Size = sizeof(chan->fax2.abLine); - LineBuf.Len = chan->fax2.LineLen; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - - Event = EVENT_NONE; - while (Event == EVENT_NONE) { - switch(chan->fax2.NextObject) { - case FAX_OBJECT_DOCU: - Length = LineBuf.Len + (InBuf.Size - InBuf.Len); - if (Length < sizeof(eicon_sff_dochead)) { - Event = EVENT_NEEDDATA; - break; - } - ObjectSize = sizeof(eicon_sff_dochead); - Length = ObjectSize; - if (LineBuf.Len < Length) { - Length -= LineBuf.Len; - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - InBuf.Len += Length; - InBuf.Next += Length; - } else { - LineBuf.Len -= Length; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); - } - chan->fax2.PrevObject = FAX_OBJECT_DOCU; - chan->fax2.NextObject = FAX_OBJECT_PAGE; - break; - - case FAX_OBJECT_PAGE: - Length = LineBuf.Len + (InBuf.Size - InBuf.Len); - if (Length < 2) { - Event = EVENT_NEEDDATA; - break; - } - if (LineBuf.Len == 0) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - if (LineBuf.Len == 1) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - PageHeaderLen = *(LineBuf.Data + 1); - ObjectSize = (PageHeaderLen == 0) ? 2 : sizeof(eicon_sff_pagehead); - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - Length = ObjectSize; - /* extract page dimensions */ - if (LineBuf.Len < Length) { - aLength = Length - LineBuf.Len; - memcpy(LineBuf.Next, InBuf.Next, aLength); - LineBuf.Next += aLength; - InBuf.Next += aLength; - LineBuf.Len += aLength; - InBuf.Len += aLength; - } - if (Length > 2) { - ob_page = (eicon_sff_pagehead *)LineBuf.Data; - switch(ob_page->linelength) { - case 2048: - chan->fax->r_width = 1; - break; - case 2432: - chan->fax->r_width = 2; - break; - case 1216: - chan->fax->r_width = 3; - break; - case 864: - chan->fax->r_width = 4; - break; - case 1728: - default: - chan->fax->r_width = 0; - } - switch(ob_page->pagelength) { - case 1143: - case 2287: - chan->fax->r_length = 0; - break; - case 1401: - case 2802: - chan->fax->r_length = 1; - break; - default: - chan->fax->r_length = 2; - } - eicon_log(ccard, 128, "rSFF-Head: linelength = %d\n", ob_page->linelength); - eicon_log(ccard, 128, "rSFF-Head: pagelength = %d\n", ob_page->pagelength); - } - LineBuf.Len -= Length; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); - - chan->fax2.PrevObject = FAX_OBJECT_PAGE; - chan->fax2.NextObject = FAX_OBJECT_LINE; - break; - - case FAX_OBJECT_LINE: - Length = LineBuf.Len + (InBuf.Size - InBuf.Len); - if (Length < 1) { - Event = EVENT_NEEDDATA; - break; - } - if (LineBuf.Len == 0) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - Recordtype = *LineBuf.Data; - if (Recordtype == 0) { - /* recordtype pixel row (2 byte length) */ - ObjHeadLen = 3; - if (Length < ObjHeadLen) { - Event = EVENT_NEEDDATA; - break; - } - while (LineBuf.Len < ObjHeadLen) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - ObjDataLen = *((__u16*) (LineBuf.Data + 1)); - ObjectSize = ObjHeadLen + ObjDataLen; - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - } else - if ((Recordtype >= 1) && (Recordtype <= 216)) { - /* recordtype pixel row (1 byte length) */ - ObjHeadLen = 1; - ObjDataLen = Recordtype; - ObjectSize = ObjHeadLen + ObjDataLen; - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - } else - if ((Recordtype >= 217) && (Recordtype <= 253)) { - /* recordtype empty lines */ - ObjHeadLen = 1; - ObjDataLen = 0; - ObjectSize = ObjHeadLen + ObjDataLen; - LineBuf.Len--; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + 1, LineBuf.Len); - break; - } else - if (Recordtype == 254) { - /* recordtype page header */ - chan->fax2.PrevObject = FAX_OBJECT_LINE; - chan->fax2.NextObject = FAX_OBJECT_PAGE; - break; - } else { - /* recordtype user information */ - ObjHeadLen = 2; - if (Length < ObjHeadLen) { - Event = EVENT_NEEDDATA; - break; - } - while (LineBuf.Len < ObjHeadLen) { - *LineBuf.Next++ = *InBuf.Next++; - LineBuf.Len++; - InBuf.Len++; - } - ObjDataLen = *(LineBuf.Data + 1); - ObjectSize = ObjHeadLen + ObjDataLen; - if (ObjDataLen == 0) { - /* illegal line coding */ - LineBuf.Len -= ObjHeadLen; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + ObjHeadLen, LineBuf.Len); - break; - } else { - /* user information */ - if (Length < ObjectSize) { - Event = EVENT_NEEDDATA; - break; - } - Length = ObjectSize; - if (LineBuf.Len < Length) { - Length -= LineBuf.Len; - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - InBuf.Len += Length; - InBuf.Next += Length; - } else { - LineBuf.Len -= Length; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - memmove(LineBuf.Data, LineBuf.Data + Length, LineBuf.Len); - } - } - break; - } - Length = ObjectSize; - if (LineBuf.Len > ObjHeadLen) { - fax_put_rcv(ccard, chan, LineBuf.Data + ObjHeadLen, - (LineBuf.Len - ObjHeadLen)); - } - Length -= LineBuf.Len; - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - if (Length > 0) { - fax_put_rcv(ccard, chan, InBuf.Next, Length); - InBuf.Len += Length; - InBuf.Next += Length; - } - fax_put_rcv(ccard, chan, (__u8 *)&Cl2Eol, sizeof(Cl2Eol)); - break; - } /* end of switch (chan->fax2.NextObject) */ - } /* end of while (Event==EVENT_NONE) */ - if (InBuf.Len < InBuf.Size) { - Length = InBuf.Size - InBuf.Len; - if ((LineBuf.Len + Length) > LineBuf.Size) { - eicon_log(ccard, 1, "idi_fax: Ch%d: %d bytes dropping, small buffer\n", chan->No, - Length); - } else { - memcpy(LineBuf.Next, InBuf.Next, Length); - LineBuf.Len += Length; - } - } - chan->fax2.LineLen = LineBuf.Len; - } else { /* CONN_OUT */ - /* On CONN_OUT we do not need incoming data, drop it */ - /* maybe later for polling */ - } - -# undef EVENT_NONE -# undef EVENT_NEEDDATA - - return; -} - -int -idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf) -{ - struct sk_buff *skb; - - skb = alloc_skb(OutBuf->Len, GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "idi_err: Ch%d: alloc_skb failed in fax_send_outbuf()\n", chan->No); - return(-1); - } - memcpy(skb_put(skb, OutBuf->Len), OutBuf->Data, OutBuf->Len); - - OutBuf->Len = 0; - OutBuf->Next = OutBuf->Data; - - return(idi_send_data(ccard, chan, 0, skb, 1)); -} - -int -idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb) -{ - isdn_ctrl cmd; - eicon_OBJBUFFER InBuf; - __u8 InData; - __u8 InMask; - eicon_OBJBUFFER OutBuf; - eicon_OBJBUFFER LineBuf; - __u32 LineData; - unsigned int LineDataLen; - __u8 Byte; - __u8 Event; - int ret = 1; - -# define EVENT_NONE 0 -# define EVENT_EOD 1 -# define EVENT_EOL 2 -# define EVENT_EOP 3 - - if ((!ccard) || (!chan)) - return -1; - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_fax: senddata with NULL fax struct, ERROR\n"); - return -1; - } - - if (chan->fax->direction == ISDN_TTY_FAX_CONN_IN) { - /* Simply ignore any data written in data mode when receiving a fax. */ - /* This is not completely correct because only XON's should come here. */ - dev_kfree_skb(skb); - return 1; - } - - if (chan->fax->phase != ISDN_FAX_PHASE_C) { - dev_kfree_skb(skb); - return 1; - } - - if (chan->queued + skb->len > 1200) - return 0; - - InBuf.Data = skb->data; - InBuf.Size = skb->len; - InBuf.Len = 0; - InBuf.Next = InBuf.Data; - InData = 0; - InMask = 0; - - LineBuf.Data = chan->fax2.abLine; - LineBuf.Size = sizeof(chan->fax2.abLine); - LineBuf.Len = chan->fax2.LineLen; - LineBuf.Next = LineBuf.Data + LineBuf.Len; - LineData = chan->fax2.LineData; - LineDataLen = chan->fax2.LineDataLen; - - OutBuf.Data = chan->fax2.abFrame; - OutBuf.Size = sizeof(chan->fax2.abFrame); - OutBuf.Len = 0; - OutBuf.Next = OutBuf.Data; - - Event = EVENT_NONE; - - chan->fax2.Eop = 0; - - for (;;) { - for (;;) { - if (InMask == 0) { - if (InBuf.Len >= InBuf.Size) { - Event = EVENT_EOD; - break; - } - if ((chan->fax2.Dle != _DLE_) && *InBuf.Next == _DLE_) { - chan->fax2.Dle = _DLE_; - InBuf.Next++; - InBuf.Len++; - if (InBuf.Len >= InBuf.Size) { - Event = EVENT_EOD; - break; - } - } - if (chan->fax2.Dle == _DLE_) { - chan->fax2.Dle = 0; - if (*InBuf.Next == _ETX_) { - Event = EVENT_EOP; - break; - } else - if (*InBuf.Next == _DLE_) { - /* do nothing */ - } else { - eicon_log(ccard, 1, - "idi_err: Ch%d: unknown DLE escape %02x found\n", - chan->No, *InBuf.Next); - InBuf.Next++; - InBuf.Len++; - if (InBuf.Len >= InBuf.Size) { - Event = EVENT_EOD; - break; - } - } - } - InBuf.Len++; - InData = *InBuf.Next++; - InMask = (chan->fax->bor) ? 0x80 : 0x01; - } - while (InMask) { - LineData >>= 1; - LineDataLen++; - if (InData & InMask) - LineData |= 0x80000000; - if (chan->fax->bor) - InMask >>= 1; - else - InMask <<= 1; - - if ((LineDataLen >= T4_EOL_BITSIZE) && - ((LineData & T4_EOL_MASK_DWORD) == T4_EOL_DWORD)) { - Event = EVENT_EOL; - if (LineDataLen > T4_EOL_BITSIZE) { - Byte = (__u8) - ((LineData & ~T4_EOL_MASK_DWORD) >> - (32 - LineDataLen)); - if (Byte == 0) { - if (! chan->fax2.NullByteExist) { - chan->fax2.NullBytesPos = LineBuf.Len; - chan->fax2.NullByteExist = 1; - } - } else { - chan->fax2.NullByteExist = 0; - } - if (LineBuf.Len < LineBuf.Size) { - *LineBuf.Next++ = Byte; - LineBuf.Len++; - } - } - LineDataLen = 0; - break; - } - if (LineDataLen >= T4_EOL_BITSIZE + 8) { - Byte = (__u8) - ((LineData & ~T4_EOL_MASK_DWORD) >> - (32 - T4_EOL_BITSIZE - 8)); - LineData &= T4_EOL_MASK_DWORD; - LineDataLen = T4_EOL_BITSIZE; - if (Byte == 0) { - if (! chan->fax2.NullByteExist) { - chan->fax2.NullBytesPos = LineBuf.Len; - chan->fax2.NullByteExist = 1; - } - } else { - chan->fax2.NullByteExist = 0; - } - if (LineBuf.Len < LineBuf.Size) { - *LineBuf.Next++ = Byte; - LineBuf.Len++; - } - } - } - if (Event != EVENT_NONE) - break; - } - - if ((Event != EVENT_EOL) && (Event != EVENT_EOP)) - break; - - if ((Event == EVENT_EOP) && (LineDataLen > 0)) { - LineData >>= 32 - LineDataLen; - LineDataLen = 0; - while (LineData != 0) { - Byte = (__u8) LineData; - LineData >>= 8; - if (Byte == 0) { - if (! chan->fax2.NullByteExist) { - chan->fax2.NullBytesPos = LineBuf.Len; - chan->fax2.NullByteExist = 1; - } - } else { - chan->fax2.NullByteExist = 0; - } - if (LineBuf.Len < LineBuf.Size) { - *LineBuf.Next++ = Byte; - LineBuf.Len++; - } - - } - } - if (chan->fax2.NullByteExist) { - if (chan->fax2.NullBytesPos == 0) { - LineBuf.Len = 0; - } else { - LineBuf.Len = chan->fax2.NullBytesPos + 1; - } - } - if (LineBuf.Len > 0) { - if (OutBuf.Len + LineBuf.Len + SFF_LEN_FLD_SIZE > OutBuf.Size) { - ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); - } - if (LineBuf.Len <= 216) { - *OutBuf.Next++ = (__u8) LineBuf.Len; - OutBuf.Len++; - } else { - *OutBuf.Next++ = 0; - *((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len; - OutBuf.Len += 3; - } - memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len); - OutBuf.Next += LineBuf.Len; - OutBuf.Len += LineBuf.Len; - } - LineBuf.Len = 0; - LineBuf.Next = LineBuf.Data; - chan->fax2.NullByteExist = 0; - if (Event == EVENT_EOP) - break; - - Event = EVENT_NONE; - } - - if (Event == EVENT_EOP) { - chan->fax2.Eop = 1; - chan->fax2.PageCount++; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_EOP; - ccard->interface.statcallb(&cmd); - } - if (OutBuf.Len > 0) { - ret = idi_fax_send_outbuf(ccard, chan, &OutBuf); - } - - chan->fax2.LineLen = LineBuf.Len; - chan->fax2.LineData = LineData; - chan->fax2.LineDataLen = LineDataLen; - -# undef EVENT_NONE -# undef EVENT_EOD -# undef EVENT_EOL -# undef EVENT_EOP - - if (ret >= 0) - dev_kfree_skb(skb); - if (ret == 0) - ret = 1; - return(ret); -} - -void -idi_fax_hangup(eicon_card *ccard, eicon_chan *chan) -{ - isdn_ctrl cmd; - - if (!chan->fax) { - eicon_log(ccard, 1, "idi_fax: hangup with NULL fax struct, ERROR\n"); - return; - } - if ((chan->fax->direction == ISDN_TTY_FAX_CONN_OUT) && - (chan->fax->code == 0)) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_PTS; - ccard->interface.statcallb(&cmd); - } - if ((chan->fax->code > 1) && (chan->fax->code < 120)) - chan->fax->code += 120; - chan->fax->r_code = ISDN_TTY_FAX_HNG; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); -} - -#endif /******** FAX ********/ - -int -idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int len) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - - if ((chan->fsm_state == EICON_STATE_NULL) || (chan->fsm_state == EICON_STATE_LISTEN)) { - eicon_log(card, 1, "idi_snd: Ch%d: send udata on state %d !\n", chan->No, chan->fsm_state); - return -ENODEV; - } - eicon_log(card, 8, "idi_snd: Ch%d: udata 0x%x: %d %d %d %d\n", chan->No, - UReq, buffer[0], buffer[1], buffer[2], buffer[3]); - - skb = alloc_skb(sizeof(eicon_REQ) + len + 1, GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_udata()\n", chan->No); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ)); - - reqbuf->Req = IDI_N_UDATA; - reqbuf->ReqCh = chan->e.IndCh; - reqbuf->ReqId = 1; - - reqbuf->XBuffer.length = len + 1; - reqbuf->XBuffer.P[0] = UReq; - memcpy(&reqbuf->XBuffer.P[1], buffer, len); - reqbuf->Reference = 1; /* Net Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_schedule_tx(card); - return (0); -} - -void -idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value) -{ - u_char buf[6]; - struct enable_dtmf_s *dtmf_buf = (struct enable_dtmf_s *)buf; - - if ((!ccard) || (!chan)) - return; - - memset(buf, 0, 6); - switch(cmd) { - case ISDN_AUDIO_SETDD: - if (value[0]) { - dtmf_buf->tone = (__u16) (value[1] * 5); - dtmf_buf->gap = (__u16) (value[1] * 5); - idi_send_udata(ccard, chan, - DSP_UDATA_REQUEST_ENABLE_DTMF_RECEIVER, - buf, 4); - } else { - idi_send_udata(ccard, chan, - DSP_UDATA_REQUEST_DISABLE_DTMF_RECEIVER, - buf, 0); - } - break; - } -} - -void -idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int len) -{ - isdn_ctrl cmd; - eicon_dsp_ind *p = (eicon_dsp_ind *) (&buffer[1]); - static char *connmsg[] = - {"", "V.21", "V.23", "V.22", "V.22bis", "V.32bis", "V.34", - "V.8", "Bell 212A", "Bell 103", "V.29 Leased", "V.33 Leased", "V.90", - "V.21 CH2", "V.27ter", "V.29", "V.33", "V.17"}; - static u_char dtmf_code[] = { - '1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D' - }; - - if ((!ccard) || (!chan)) - return; - - switch (buffer[0]) { - case DSP_UDATA_INDICATION_SYNC: - eicon_log(ccard, 16, "idi_ind: Ch%d: UDATA_SYNC time %d\n", chan->No, p->time); - break; - case DSP_UDATA_INDICATION_DCD_OFF: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_OFF time %d\n", chan->No, p->time); - break; - case DSP_UDATA_INDICATION_DCD_ON: - if ((chan->l2prot == ISDN_PROTO_L2_MODEM) && - (chan->fsm_state == EICON_STATE_WMCONN)) { - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]); - ccard->interface.statcallb(&cmd); - } - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DCD_ON time %d\n", chan->No, p->time); - eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - break; - case DSP_UDATA_INDICATION_CTS_OFF: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_OFF time %d\n", chan->No, p->time); - break; - case DSP_UDATA_INDICATION_CTS_ON: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_CTS_ON time %d\n", chan->No, p->time); - eicon_log(ccard, 8, "idi_ind: Ch%d: %d %d %d %d\n", chan->No, - p->norm, p->options, p->speed, p->delay); - break; - case DSP_UDATA_INDICATION_DISCONNECT: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DISCONNECT cause %d\n", chan->No, buffer[1]); - break; - case DSP_UDATA_INDICATION_DTMF_DIGITS_RECEIVED: - eicon_log(ccard, 8, "idi_ind: Ch%d: UDATA_DTMF_REC '%c'\n", chan->No, - dtmf_code[buffer[1]]); - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_AUDIO; - cmd.parm.num[0] = ISDN_AUDIO_DTMF; - cmd.parm.num[1] = dtmf_code[buffer[1]]; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - break; - default: - eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED UDATA Indication 0x%02x\n", chan->No, buffer[0]); - } -} - -void -eicon_parse_trace(eicon_card *ccard, unsigned char *buffer, int len) -{ - int i,j,n; - int buflen = len * 3 + 30; - char *p; - struct trace_s { - unsigned long time; - unsigned short size; - unsigned short code; - unsigned char data[1]; - } *q; - - if (!(p = kmalloc(buflen, GFP_ATOMIC))) { - eicon_log(ccard, 1, "idi_err: Ch??: could not allocate trace buffer\n"); - return; - } - memset(p, 0, buflen); - q = (struct trace_s *)buffer; - - if (DebugVar & 512) { - if ((q->code == 3) || (q->code == 4)) { - n = (short) *(q->data); - if (n) { - j = sprintf(p, "DTRC:"); - for (i = 0; i < n; i++) { - j += sprintf(p + j, "%02x ", q->data[i+2]); - } - j += sprintf(p + j, "\n"); - } - } - } else { - j = sprintf(p, "XLOG: %lx %04x %04x ", - q->time, q->size, q->code); - - for (i = 0; i < q->size; i++) { - j += sprintf(p + j, "%02x ", q->data[i]); - } - j += sprintf(p + j, "\n"); - } - if (strlen(p)) - eicon_putstatus(ccard, p); - kfree(p); -} - -void -idi_handle_ind(eicon_card *ccard, struct sk_buff *skb) -{ - int tmp; - char tnum[64]; - int dlev; - int free_buff; - ulong flags; - struct sk_buff *skb2; - eicon_IND *ind = (eicon_IND *)skb->data; - eicon_chan *chan; - idi_ind_message message; - isdn_ctrl cmd; - - if (!ccard) { - eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ind\n"); - dev_kfree_skb(skb); - return; - } - - if ((chan = ccard->IdTable[ind->IndId]) == NULL) { - eicon_log(ccard, 1, "idi_err: Ch??: null chan in handle_ind\n"); - dev_kfree_skb(skb); - return; - } - - if ((ind->Ind != 8) && (ind->Ind != 0xc)) - dlev = 144; - else - dlev = 128; - - eicon_log(ccard, dlev, "idi_hdl: Ch%d: Ind=%x Id=%x Ch=%x MInd=%x MLen=%x Len=%x\n", chan->No, - ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); - - free_buff = 1; - /* Signal Layer */ - if (chan->e.D3Id == ind->IndId) { - idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); - switch(ind->Ind) { - case HANGUP: - eicon_log(ccard, 8, "idi_ind: Ch%d: Hangup\n", chan->No); - while((skb2 = skb_dequeue(&chan->e.X))) { - dev_kfree_skb(skb2); - } - save_flags(flags); - cli(); - chan->queued = 0; - chan->waitq = 0; - chan->waitpq = 0; - restore_flags(flags); - if (message.e_cau[0] & 0x7f) { - cmd.driver = ccard->myid; - cmd.arg = chan->No; - sprintf(cmd.parm.num,"E%02x%02x", - chan->cause[0]&0x7f, message.e_cau[0]&0x7f); - cmd.command = ISDN_STAT_CAUSE; - ccard->interface.statcallb(&cmd); - } - chan->cause[0] = 0; -#ifdef CONFIG_ISDN_TTY_FAX - if (!chan->e.B2Id) - chan->fax = 0; -#endif - if (((chan->fsm_state == EICON_STATE_ACTIVE) || - (chan->fsm_state == EICON_STATE_WMCONN)) || - ((chan->l2prot == ISDN_PROTO_L2_FAX) && - (chan->fsm_state == EICON_STATE_OBWAIT))) { - chan->fsm_state = EICON_STATE_NULL; - } 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; - if (chan->statectrl & HAVE_CONN_REQ) { - eicon_log(ccard, 32, "idi_req: Ch%d: queueing delayed conn_req\n", chan->No); - chan->statectrl &= ~HAVE_CONN_REQ; - if ((chan->tskb1) && (chan->tskb2)) { - skb_queue_tail(&chan->e.X, chan->tskb1); - skb_queue_tail(&ccard->sndq, chan->tskb2); - eicon_schedule_tx(ccard); - } - chan->tskb1 = NULL; - chan->tskb2 = NULL; - } else { - chan->fsm_state = EICON_STATE_NULL; - cmd.driver = ccard->myid; - cmd.arg = chan->No; - cmd.command = ISDN_STAT_DHUP; - ccard->interface.statcallb(&cmd); - eicon_idi_listen_req(ccard, chan); - } - } - break; - case INDICATE_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Indicate_Ind\n", chan->No); - if (chan->fsm_state != EICON_STATE_LISTEN) { - eicon_log(ccard, 1, "idi_err: Ch%d: Incoming call on wrong state (%d).\n", - chan->No, chan->fsm_state); - idi_do_req(ccard, chan, HANGUP, 0); - break; - } - chan->fsm_state = EICON_STATE_ICALL; - idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2); - strcpy(chan->cpn, message.cpn + 1); - strcpy(chan->oad, message.oad); - strcpy(chan->dsa, message.dsa); - strcpy(chan->osa, message.osa); - chan->plan = message.plan; - chan->screen = message.screen; - try_stat_icall_again: - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_ICALL; - cmd.arg = chan->No; - cmd.parm.setup.si1 = chan->si1; - cmd.parm.setup.si2 = chan->si2; - strcpy(tnum, chan->cpn); - if (strlen(chan->dsa)) { - strcat(tnum, "."); - strcat(tnum, chan->dsa); - } - tnum[ISDN_MSNLEN - 1] = 0; - strcpy(cmd.parm.setup.eazmsn, tnum); - strcpy(tnum, chan->oad); - if (strlen(chan->osa)) { - strcat(tnum, "."); - strcat(tnum, chan->osa); - } - tnum[ISDN_MSNLEN - 1] = 0; - strcpy(cmd.parm.setup.phone, tnum); - cmd.parm.setup.plan = chan->plan; - cmd.parm.setup.screen = chan->screen; - tmp = ccard->interface.statcallb(&cmd); - switch(tmp) { - case 0: /* no user responding */ - idi_do_req(ccard, chan, HANGUP, 0); - chan->fsm_state = EICON_STATE_NULL; - break; - case 1: /* alert */ - eicon_log(ccard, 8, "idi_req: Ch%d: Call Alert\n", chan->No); - if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_ICALLW)) { - chan->fsm_state = EICON_STATE_ICALL; - idi_do_req(ccard, chan, CALL_ALERT, 0); - } - break; - case 2: /* reject */ - eicon_log(ccard, 8, "idi_req: Ch%d: Call Reject\n", chan->No); - idi_do_req(ccard, chan, REJECT, 0); - break; - case 3: /* incomplete number */ - eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No); - chan->fsm_state = EICON_STATE_ICALLW; - break; - } - break; - case INFO_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Info_Ind\n", chan->No); - if ((chan->fsm_state == EICON_STATE_ICALLW) && - (message.cpn[0])) { - strcat(chan->cpn, message.cpn + 1); - goto try_stat_icall_again; - } - break; - case CALL_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Ind\n", chan->No); - if ((chan->fsm_state == EICON_STATE_ICALL) || (chan->fsm_state == EICON_STATE_IWAIT)) { - chan->fsm_state = EICON_STATE_IBWAIT; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_DCONN; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - switch(chan->l2prot) { - case ISDN_PROTO_L2_FAX: -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->fax) - chan->fax->phase = ISDN_FAX_PHASE_A; -#endif - break; - case ISDN_PROTO_L2_MODEM: - /* do nothing, wait for connect */ - break; - case ISDN_PROTO_L2_TRANS: - idi_do_req(ccard, chan, IDI_N_CONNECT, 1); - break; - default: - /* On most incoming calls we use automatic connect */ - /* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */ - } - } else { - if (chan->fsm_state != EICON_STATE_ACTIVE) - idi_hangup(ccard, chan); - } - break; - case CALL_CON: - eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No); - if (chan->fsm_state == EICON_STATE_OCALL) { - chan->fsm_state = EICON_STATE_OBWAIT; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_DCONN; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - - /* check if old NetID has been removed */ - if (chan->e.B2Id) { - eicon_log(ccard, 1, "eicon: Ch%d: old net_id %x still exist, removing.\n", - chan->No, chan->e.B2Id); - idi_do_req(ccard, chan, REMOVE, 1); - } - - idi_do_req(ccard, chan, ASSIGN, 1); - idi_do_req(ccard, chan, IDI_N_CONNECT, 1); -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - if (chan->fax) - chan->fax->phase = ISDN_FAX_PHASE_A; - } -#endif - } else - idi_hangup(ccard, chan); - break; - case AOC_IND: - eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No); - break; - default: - eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind); - } - } - /* Network Layer */ - else if (chan->e.B2Id == ind->IndId) { - - if (chan->No == ccard->nchannels) { - /* Management Indication */ - if (ind->Ind == 0x04) { /* Trace_Ind */ - eicon_parse_trace(ccard, ind->RBuffer.P, ind->RBuffer.length); - } else { - idi_IndParse(ccard, chan, &message, ind->RBuffer.P, ind->RBuffer.length); - chan->fsm_state = 1; - } - } - else - switch(ind->Ind) { - case IDI_N_CONNECT_ACK: - eicon_log(ccard, 16, "idi_ind: Ch%d: N_Connect_Ack\n", chan->No); - if (chan->l2prot == ISDN_PROTO_L2_MODEM) { - chan->fsm_state = EICON_STATE_WMCONN; - break; - } - if (chan->l2prot == ISDN_PROTO_L2_FAX) { -#ifdef CONFIG_ISDN_TTY_FAX - chan->fsm_state = EICON_STATE_ACTIVE; - idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - if (chan->fax) { - if (chan->fax->phase == ISDN_FAX_PHASE_B) { - idi_fax_send_header(ccard, chan, 2); - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_DCS; - ccard->interface.statcallb(&cmd); - } - } - else { - eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n"); - } -#endif - break; - } - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, "64000"); - ccard->interface.statcallb(&cmd); - break; - case IDI_N_CONNECT: - eicon_log(ccard, 16,"idi_ind: Ch%d: N_Connect\n", chan->No); - chan->e.IndCh = ind->IndCh; - if (chan->e.B2Id) idi_do_req(ccard, chan, IDI_N_CONNECT_ACK, 1); - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - break; - } - if (chan->l2prot == ISDN_PROTO_L2_MODEM) { - chan->fsm_state = EICON_STATE_WMCONN; - break; - } - chan->fsm_state = EICON_STATE_ACTIVE; - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BCONN; - cmd.arg = chan->No; - strcpy(cmd.parm.num, "64000"); - ccard->interface.statcallb(&cmd); - break; - case IDI_N_DISC: - eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC\n", chan->No); - if (chan->e.B2Id) { - while((skb2 = skb_dequeue(&chan->e.X))) { - dev_kfree_skb(skb2); - } - idi_do_req(ccard, chan, IDI_N_DISC_ACK, 1); - idi_do_req(ccard, chan, REMOVE, 1); - } -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - idi_fax_hangup(ccard, chan); - } -#endif - chan->e.IndCh = 0; - save_flags(flags); - cli(); - chan->queued = 0; - chan->waitq = 0; - chan->waitpq = 0; - restore_flags(flags); - idi_do_req(ccard, chan, HANGUP, 0); - if (chan->fsm_state == EICON_STATE_ACTIVE) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BHUP; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - chan->fsm_state = EICON_STATE_NULL; - chan->statectrl |= WAITING_FOR_HANGUP; - } -#ifdef CONFIG_ISDN_TTY_FAX - chan->fax = 0; -#endif - break; - case IDI_N_DISC_ACK: - eicon_log(ccard, 16, "idi_ind: Ch%d: N_DISC_ACK\n", chan->No); -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - idi_parse_edata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - idi_fax_hangup(ccard, chan); - } -#endif - break; - case IDI_N_DATA_ACK: - eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No); - break; - case IDI_N_DATA: - skb_pull(skb, sizeof(eicon_IND) - 1); - eicon_log(ccard, 128, "idi_rcv: Ch%d: %d bytes\n", chan->No, skb->len); - if (chan->l2prot == ISDN_PROTO_L2_FAX) { -#ifdef CONFIG_ISDN_TTY_FAX - idi_faxdata_rcv(ccard, chan, skb); -#endif - } else { - ccard->interface.rcvcallb_skb(ccard->myid, chan->No, skb); - free_buff = 0; - } - break; - case IDI_N_UDATA: - idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - break; -#ifdef CONFIG_ISDN_TTY_FAX - case IDI_N_EDATA: - idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length); - break; -#endif - default: - eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED NetIndication 0x%02x\n", chan->No, ind->Ind); - } - } - else { - eicon_log(ccard, 1, "idi_ind: Ch%d: Ind is neither SIG nor NET !\n", chan->No); - } - if (free_buff) - dev_kfree_skb(skb); -} - -int -idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack) -{ - ulong flags; - isdn_ctrl cmd; - - if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) { - /* I dont know why this happens, should not ! */ - /* just ignoring this RC */ - eicon_log(ccard, 16, "idi_ack: Ch%d: RcId %d not equal to last %d\n", chan->No, - ack->RcId, (chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id); - return 1; - } - - /* Management Interface */ - if (chan->No == ccard->nchannels) { - /* Managementinterface: changing state */ - if (chan->e.Req != 0x02) - chan->fsm_state = 1; - } - - /* Remove an Id */ - if (chan->e.Req == REMOVE) { - if (ack->Reference != chan->e.ref) { - /* This should not happen anymore */ - eicon_log(ccard, 16, "idi_ack: Ch%d: Rc-Ref %d not equal to stored %d\n", chan->No, - ack->Reference, chan->e.ref); - } - save_flags(flags); - cli(); - ccard->IdTable[ack->RcId] = NULL; - eicon_log(ccard, 16, "idi_ack: Ch%d: Removed : Id=%x Ch=%d (%s)\n", chan->No, - ack->RcId, ack->RcCh, (chan->e.ReqCh)? "Net":"Sig"); - if (!chan->e.ReqCh) - chan->e.D3Id = 0; - else - chan->e.B2Id = 0; - restore_flags(flags); - return 1; - } - - /* Signal layer */ - if (!chan->e.ReqCh) { - eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, - ack->RcId, ack->RcCh, ack->Reference); - } else { - /* Network layer */ - switch(chan->e.Req & 0x0f) { - case IDI_N_CONNECT: - chan->e.IndCh = ack->RcCh; - eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, - ack->RcId, ack->RcCh, ack->Reference); - break; - case IDI_N_MDATA: - case IDI_N_DATA: - if ((chan->e.Req & 0x0f) == IDI_N_DATA) { - if (chan->queued) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_BSENT; - cmd.arg = chan->No; - cmd.parm.length = chan->waitpq; - ccard->interface.statcallb(&cmd); - } - save_flags(flags); - cli(); - chan->waitpq = 0; - restore_flags(flags); -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - if (((chan->queued - chan->waitq) < 1) && - (chan->fax2.Eop)) { - chan->fax2.Eop = 0; - if (chan->fax) { - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_FAXIND; - cmd.arg = chan->No; - chan->fax->r_code = ISDN_TTY_FAX_SENT; - ccard->interface.statcallb(&cmd); - } - else { - eicon_log(ccard, 1, "idi_ack: Sent with NULL fax struct, ERROR\n"); - } - } - } -#endif - } - save_flags(flags); - cli(); - chan->queued -= chan->waitq; - if (chan->queued < 0) chan->queued = 0; - restore_flags(flags); - break; - default: - eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No, - ack->RcId, ack->RcCh, ack->Reference); - } - } - return 1; -} - -void -idi_handle_ack(eicon_card *ccard, struct sk_buff *skb) -{ - int j; - ulong flags; - eicon_RC *ack = (eicon_RC *)skb->data; - eicon_chan *chan; - isdn_ctrl cmd; - int dCh = -1; - - if (!ccard) { - eicon_log(ccard, 1, "idi_err: Ch??: null card in handle_ack\n"); - dev_kfree_skb(skb); - return; - } - - save_flags(flags); - cli(); - if ((chan = ccard->IdTable[ack->RcId]) != NULL) - dCh = chan->No; - restore_flags(flags); - - switch (ack->Rc) { - case OK_FC: - case N_FLOW_CONTROL: - case ASSIGN_RC: - eicon_log(ccard, 1, "idi_ack: Ch%d: unhandled RC 0x%x\n", - dCh, ack->Rc); - break; - case READY_INT: - case TIMER_INT: - /* we do nothing here */ - break; - - case OK: - if (!chan) { - eicon_log(ccard, 1, "idi_ack: Ch%d: OK on chan without Id\n", dCh); - break; - } - if (!idi_handle_ack_ok(ccard, chan, ack)) - chan = NULL; - break; - - case ASSIGN_OK: - if (chan) { - eicon_log(ccard, 1, "idi_ack: Ch%d: ASSIGN-OK on chan already assigned (%x,%x)\n", - chan->No, chan->e.D3Id, chan->e.B2Id); - } - save_flags(flags); - cli(); - for(j = 0; j < ccard->nchannels + 1; j++) { - if ((ccard->bch[j].e.ref == ack->Reference) && - (ccard->bch[j].e.Req == ASSIGN)) { - if (!ccard->bch[j].e.ReqCh) - ccard->bch[j].e.D3Id = ack->RcId; - else - ccard->bch[j].e.B2Id = ack->RcId; - ccard->IdTable[ack->RcId] = &ccard->bch[j]; - chan = &ccard->bch[j]; - eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j, - ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig"); - break; - } - } - restore_flags(flags); - if (j > ccard->nchannels) { - eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n", - ack->Reference, ack->RcId); - } - break; - - case OUT_OF_RESOURCES: - case UNKNOWN_COMMAND: - case WRONG_COMMAND: - case WRONG_ID: - case WRONG_CH: - case UNKNOWN_IE: - case WRONG_IE: - default: - if (!chan) { - eicon_log(ccard, 1, "idi_ack: Ch%d: Not OK !! on chan without Id\n", dCh); - break; - } else - switch (chan->e.Req) { - case 12: /* Alert */ - eicon_log(ccard, 2, "eicon_err: Ch%d: Alert Not OK : Rc=%d Id=%x Ch=%d\n", - dCh, ack->Rc, ack->RcId, ack->RcCh); - break; - default: - if (dCh != ccard->nchannels) - eicon_log(ccard, 1, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n", - dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req); - } - if (dCh == ccard->nchannels) { /* Management */ - chan->fsm_state = 2; - eicon_log(ccard, 8, "eicon_err: Ch%d: Ack Not OK !!: Rc=%d Id=%x Ch=%d Req=%d\n", - dCh, ack->Rc, ack->RcId, ack->RcCh, chan->e.Req); - } else if (dCh >= 0) { - /* any other channel */ - /* card reports error: we hangup */ - idi_hangup(ccard, chan); - cmd.driver = ccard->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg = chan->No; - ccard->interface.statcallb(&cmd); - } - } - save_flags(flags); - cli(); - if (chan) { - chan->e.ref = 0; - chan->e.busy = 0; - } - restore_flags(flags); - dev_kfree_skb(skb); - eicon_schedule_tx(ccard); -} - -int -idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que) -{ - struct sk_buff *xmit_skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan_ptr *chan2; - int len, plen = 0, offset = 0; - unsigned long flags; - - if ((!card) || (!chan)) { - eicon_log(card, 1, "idi_err: Ch??: null card/chan in send_data\n"); - return -1; - } - - if (chan->fsm_state != EICON_STATE_ACTIVE) { - eicon_log(card, 1, "idi_snd: Ch%d: send bytes on state %d !\n", chan->No, chan->fsm_state); - return -ENODEV; - } - - len = skb->len; - if (len > EICON_MAX_QUEUE) /* too much for the shared memory */ - return -1; - if (!len) - return 0; - if (chan->queued + len > EICON_MAX_QUEUE) - return 0; - - eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len); - - save_flags(flags); - cli(); - while(offset < len) { - - plen = ((len - offset) > 270) ? 270 : len - offset; - - xmit_skb = alloc_skb(plen + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!xmit_skb) || (!skb2)) { - restore_flags(flags); - eicon_log(card, 1, "idi_err: Ch%d: alloc_skb failed in send_data()\n", chan->No); - if (xmit_skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ)); - if (((len - offset) > 270) && - (chan->l2prot != ISDN_PROTO_L2_MODEM) && - (chan->l2prot != ISDN_PROTO_L2_FAX) && - (chan->l2prot != ISDN_PROTO_L2_TRANS)) { - reqbuf->Req = IDI_N_MDATA; - } else { - reqbuf->Req = IDI_N_DATA; - /* if (ack) reqbuf->Req |= N_D_BIT; */ - } - reqbuf->ReqCh = chan->e.IndCh; - reqbuf->ReqId = 1; - memcpy(&reqbuf->XBuffer.P, skb->data + offset, plen); - reqbuf->XBuffer.length = plen; - reqbuf->Reference = 1; /* Net Entity */ - - skb_queue_tail(&chan->e.X, xmit_skb); - skb_queue_tail(&card->sndq, skb2); - - offset += plen; - } - if (que) - chan->queued += len; - restore_flags(flags); - eicon_schedule_tx(card); - dev_kfree_skb(skb); - return len; -} - - -int -eicon_idi_manage_assign(eicon_card *card) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan *chan; - eicon_chan_ptr *chan2; - - chan = &(card->bch[card->nchannels]); - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: alloc_skb failed in manage_assign()\n"); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - - reqbuf->XBuffer.P[0] = 0; - reqbuf->Req = ASSIGN; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 0xe0; - reqbuf->XBuffer.length = 1; - reqbuf->Reference = 2; /* Man Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_schedule_tx(card); - return(0); -} - - -int -eicon_idi_manage_remove(eicon_card *card) -{ - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan *chan; - eicon_chan_ptr *chan2; - - chan = &(card->bch[card->nchannels]); - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err: alloc_skb failed in manage_remove()\n"); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - - reqbuf->Req = REMOVE; - reqbuf->ReqCh = 0; - reqbuf->ReqId = 1; - reqbuf->XBuffer.length = 0; - reqbuf->Reference = 2; /* Man Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - eicon_schedule_tx(card); - return(0); -} - - -int -eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb) -{ - int l = 0; - int ret = 0; - int timeout; - int i; - struct sk_buff *skb; - struct sk_buff *skb2; - eicon_REQ *reqbuf; - eicon_chan *chan; - eicon_chan_ptr *chan2; - - chan = &(card->bch[card->nchannels]); - - if (!(chan->e.D3Id)) { - chan->e.D3Id = 1; - while((skb2 = skb_dequeue(&chan->e.X))) - dev_kfree_skb(skb2); - chan->e.busy = 0; - - if ((ret = eicon_idi_manage_assign(card))) { - chan->e.D3Id = 0; - return(ret); - } - - timeout = jiffies + 50; - while (timeout > jiffies) { - if (chan->e.B2Id) break; - SLEEP(10); - } - if (!chan->e.B2Id) { - chan->e.D3Id = 0; - return -EIO; - } - } - - chan->fsm_state = 0; - - if (!(manbuf = kmalloc(sizeof(eicon_manifbuf), GFP_KERNEL))) { - eicon_log(card, 1, "idi_err: alloc_manifbuf failed\n"); - return -ENOMEM; - } - if (copy_from_user(manbuf, mb, sizeof(eicon_manifbuf))) { - kfree(manbuf); - return -EFAULT; - } - - skb = alloc_skb(270 + sizeof(eicon_REQ), GFP_ATOMIC); - skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC); - - if ((!skb) || (!skb2)) { - eicon_log(card, 1, "idi_err_manif: alloc_skb failed in manage()\n"); - if (skb) - dev_kfree_skb(skb); - if (skb2) - dev_kfree_skb(skb2); - kfree(manbuf); - return -ENOMEM; - } - - chan2 = (eicon_chan_ptr *)skb_put(skb2, sizeof(eicon_chan_ptr)); - chan2->ptr = chan; - - reqbuf = (eicon_REQ *)skb_put(skb, 270 + sizeof(eicon_REQ)); - - reqbuf->XBuffer.P[l++] = ESC; - reqbuf->XBuffer.P[l++] = 6; - reqbuf->XBuffer.P[l++] = 0x80; - for (i = 0; i < manbuf->length[0]; i++) - reqbuf->XBuffer.P[l++] = manbuf->data[i]; - reqbuf->XBuffer.P[1] = manbuf->length[0] + 1; - - reqbuf->XBuffer.P[l++] = 0; - reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */ - reqbuf->ReqCh = 0; - reqbuf->ReqId = 1; - reqbuf->XBuffer.length = l; - reqbuf->Reference = 2; /* Man Entity */ - - skb_queue_tail(&chan->e.X, skb); - skb_queue_tail(&card->sndq, skb2); - - manbuf->count = 0; - manbuf->pos = 0; - - eicon_schedule_tx(card); - - timeout = jiffies + 50; - while (timeout > jiffies) { - if (chan->fsm_state) break; - SLEEP(10); - } - if ((!chan->fsm_state) || (chan->fsm_state == 2)) { - kfree(manbuf); - return -EIO; - } - if (copy_to_user(mb, manbuf, sizeof(eicon_manifbuf))) { - kfree(manbuf); - return -EFAULT; - } - - kfree(manbuf); - return(0); -} diff --git a/drivers/isdn/eicon/eicon_idi.h b/drivers/isdn/eicon/eicon_idi.h deleted file mode 100644 index bd0a75be..00000000 --- a/drivers/isdn/eicon/eicon_idi.h +++ /dev/null @@ -1,284 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for the Eicon active cards. - * IDI-Interface - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * 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. - * - * $Log$ - * Revision 1.8 1999/11/25 11:43:27 armin - * Fixed statectrl and connect message. - * X.75 fix and HDLC/transparent with autoconnect. - * Minor cleanup. - * - * Revision 1.7 1999/08/22 20:26:46 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.6 1999/07/25 15:12:04 armin - * fix of some debug logs. - * enabled ISA-cards option. - * - * Revision 1.5 1999/07/11 17:16:26 armin - * Bugfixes in queue handling. - * Added DSP-DTMF decoder functions. - * Reorganized ack_handler. - * - * Revision 1.4 1999/03/29 11:19:44 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.3 1999/03/02 12:37:45 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.2 1999/01/24 20:14:18 armin - * Changed and added debug stuff. - * Better data sending. (still problems with tty's flip buffer) - * - * Revision 1.1 1999/01/01 18:09:42 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - -#ifndef IDI_H -#define IDI_H - -#include - -#define ASSIGN 0x01 -#define REMOVE 0xff - -#define CALL_REQ 1 /* call request */ -#define CALL_CON 1 /* call confirmation */ -#define CALL_IND 2 /* incoming call connected */ -#define LISTEN_REQ 2 /* listen request */ -#define HANGUP 3 /* hangup request/indication */ -#define SUSPEND 4 /* call suspend request/confirm */ -#define RESUME 5 /* call resume request/confirm */ -#define SUSPEND_REJ 6 /* suspend rejected indication */ -#define USER_DATA 8 /* user data for user to user signaling */ -#define CONGESTION 9 /* network congestion indication */ -#define INDICATE_REQ 10 /* request to indicate an incoming call */ -#define INDICATE_IND 10 /* indicates that there is an incoming call */ -#define CALL_RES 11 /* accept an incoming call */ -#define CALL_ALERT 12 /* send ALERT for incoming call */ -#define INFO_REQ 13 /* INFO request */ -#define INFO_IND 13 /* INFO indication */ -#define REJECT 14 /* reject an incoming call */ -#define RESOURCES 15 /* reserve B-Channel hardware resources */ -#define TEL_CTRL 16 /* Telephone control request/indication */ -#define STATUS_REQ 17 /* Request D-State (returned in INFO_IND) */ -#define FAC_REG_REQ 18 /* connection idependent fac registration */ -#define FAC_REG_ACK 19 /* fac registration acknowledge */ -#define FAC_REG_REJ 20 /* fac registration reject */ -#define CALL_COMPLETE 21/* send a CALL_PROC for incoming call */ -#define AOC_IND 26/* Advice of Charge */ - -#define IDI_N_MDATA (0x01) -#define IDI_N_CONNECT (0x02) -#define IDI_N_CONNECT_ACK (0x03) -#define IDI_N_DISC (0x04) -#define IDI_N_DISC_ACK (0x05) -#define IDI_N_RESET (0x06) -#define IDI_N_RESET_ACK (0x07) -#define IDI_N_DATA (0x08) -#define IDI_N_EDATA (0x09) -#define IDI_N_UDATA (0x0a) -#define IDI_N_BDATA (0x0b) -#define IDI_N_DATA_ACK (0x0c) -#define IDI_N_EDATA_ACK (0x0d) - -#define N_Q_BIT 0x10 /* Q-bit for req/ind */ -#define N_M_BIT 0x20 /* M-bit for req/ind */ -#define N_D_BIT 0x40 /* D-bit for req/ind */ - - -#define SHIFT 0x90 /* codeset shift */ -#define MORE 0xa0 /* more data */ -#define CL 0xb0 /* congestion level */ - - /* codeset 0 */ - -#define BC 0x04 /* Bearer Capability */ -#define CAU 0x08 /* cause */ -#define CAD 0x0c /* Connected address */ -#define CAI 0x10 /* call identity */ -#define CHI 0x18 /* channel identification */ -#define LLI 0x19 /* logical link id */ -#define CHA 0x1a /* charge advice */ -#define FTY 0x1c -#define PI 0x1e /* Progress Indicator */ -#define NI 0x27 /* Notification Indicator */ -#define DT 0x29 /* ETSI date/time */ -#define KEY 0x2c /* keypad information element */ -#define DSP 0x28 /* display */ -#define OAD 0x6c /* origination address */ -#define OSA 0x6d /* origination sub-address */ -#define CPN 0x70 /* called party number */ -#define DSA 0x71 /* destination sub-address */ -#define RDN 0x74 /* redirecting number */ -#define LLC 0x7c /* low layer compatibility */ -#define HLC 0x7d /* high layer compatibility */ -#define UUI 0x7e /* user user information */ -#define ESC 0x7f /* escape extension */ - -#define DLC 0x20 /* data link layer configuration */ -#define NLC 0x21 /* network layer configuration */ - - /* codeset 6 */ - -#define SIN 0x01 /* service indicator */ -#define CIF 0x02 /* charging information */ -#define DATE 0x03 /* date */ -#define CPS 0x07 /* called party status */ - -/*------------------------------------------------------------------*/ -/* return code coding */ -/*------------------------------------------------------------------*/ - -#define UNKNOWN_COMMAND 0x01 /* unknown command */ -#define WRONG_COMMAND 0x02 /* wrong command */ -#define WRONG_ID 0x03 /* unknown task/entity id */ -#define WRONG_CH 0x04 /* wrong task/entity id */ -#define UNKNOWN_IE 0x05 /* unknown information el. */ -#define WRONG_IE 0x06 /* wrong information el. */ -#define OUT_OF_RESOURCES 0x07 /* card out of res. */ -#define N_FLOW_CONTROL 0x10 /* Flow-Control, retry */ -#define ASSIGN_RC 0xe0 /* ASSIGN acknowledgement */ -#define ASSIGN_OK 0xef /* ASSIGN OK */ -#define OK_FC 0xfc /* Flow-Control RC */ -#define READY_INT 0xfd /* Ready interrupt */ -#define TIMER_INT 0xfe /* timer interrupt */ -#define OK 0xff /* command accepted */ - -/*------------------------------------------------------------------*/ - -/* defines for statectrl */ -#define WAITING_FOR_HANGUP 0x01 -#define HAVE_CONN_REQ 0x02 - -typedef struct { - char cpn[32]; - char oad[32]; - char dsa[32]; - char osa[32]; - __u8 plan; - __u8 screen; - __u8 sin[4]; - __u8 chi[4]; - __u8 e_chi[4]; - __u8 bc[12]; - __u8 e_bc[12]; - __u8 llc[18]; - __u8 hlc[5]; - __u8 cau[4]; - __u8 e_cau[2]; - __u8 e_mt; - __u8 dt[6]; - char display[83]; - char keypad[35]; - char rdn[32]; -} idi_ind_message; - -typedef struct { - __u16 next __attribute__ ((packed)); - __u8 Req __attribute__ ((packed)); - __u8 ReqId __attribute__ ((packed)); - __u8 ReqCh __attribute__ ((packed)); - __u8 Reserved1 __attribute__ ((packed)); - __u16 Reference __attribute__ ((packed)); - __u8 Reserved[8] __attribute__ ((packed)); - eicon_PBUFFER XBuffer; -} eicon_REQ; - -typedef struct { - __u16 next __attribute__ ((packed)); - __u8 Rc __attribute__ ((packed)); - __u8 RcId __attribute__ ((packed)); - __u8 RcCh __attribute__ ((packed)); - __u8 Reserved1 __attribute__ ((packed)); - __u16 Reference __attribute__ ((packed)); - __u8 Reserved2[8] __attribute__ ((packed)); -} eicon_RC; - -typedef struct { - __u16 next __attribute__ ((packed)); - __u8 Ind __attribute__ ((packed)); - __u8 IndId __attribute__ ((packed)); - __u8 IndCh __attribute__ ((packed)); - __u8 MInd __attribute__ ((packed)); - __u16 MLength __attribute__ ((packed)); - __u16 Reference __attribute__ ((packed)); - __u8 RNR __attribute__ ((packed)); - __u8 Reserved __attribute__ ((packed)); - __u32 Ack __attribute__ ((packed)); - eicon_PBUFFER RBuffer; -} eicon_IND; - -typedef struct { - __u16 NextReq __attribute__ ((packed)); /* pointer to next Req Buffer */ - __u16 NextRc __attribute__ ((packed)); /* pointer to next Rc Buffer */ - __u16 NextInd __attribute__ ((packed)); /* pointer to next Ind Buffer */ - __u8 ReqInput __attribute__ ((packed)); /* number of Req Buffers sent */ - __u8 ReqOutput __attribute__ ((packed)); /* number of Req Buffers returned */ - __u8 ReqReserved __attribute__ ((packed));/*number of Req Buffers reserved */ - __u8 Int __attribute__ ((packed)); /* ISDN-P interrupt */ - __u8 XLock __attribute__ ((packed)); /* Lock field for arbitration */ - __u8 RcOutput __attribute__ ((packed)); /* number of Rc buffers received */ - __u8 IndOutput __attribute__ ((packed)); /* number of Ind buffers received */ - __u8 IMask __attribute__ ((packed)); /* Interrupt Mask Flag */ - __u8 Reserved1[2] __attribute__ ((packed)); /* reserved field, do not use */ - __u8 ReadyInt __attribute__ ((packed)); /* request field for ready int */ - __u8 Reserved2[12] __attribute__ ((packed)); /* reserved field, do not use */ - __u8 InterfaceType __attribute__ ((packed)); /* interface type 1=16K */ - __u16 Signature __attribute__ ((packed)); /* ISDN-P initialized ind */ - __u8 B[1]; /* buffer space for Req,Ind and Rc */ -} eicon_pr_ram; - -typedef struct { - __u8 *Data; - unsigned int Size; - unsigned int Len; - __u8 *Next; -} eicon_OBJBUFFER; - -extern int idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer); -extern int idi_hangup(eicon_card *card, eicon_chan *chan); -extern int idi_connect_res(eicon_card *card, eicon_chan *chan); -extern int eicon_idi_listen_req(eicon_card *card, eicon_chan *chan); -extern int idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone, - char *eazmsn, int si1, int si2); - -extern void idi_handle_ack(eicon_card *card, struct sk_buff *skb); -extern void idi_handle_ind(eicon_card *card, struct sk_buff *skb); -extern int eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb); -extern int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que); -extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value); -#ifdef CONFIG_ISDN_TTY_FAX -extern void idi_fax_cmd(eicon_card *card, eicon_chan *chan); -extern int idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb); -#endif - -#endif diff --git a/drivers/isdn/eicon/eicon_io.c b/drivers/isdn/eicon/eicon_io.c deleted file mode 100644 index d293aa81..00000000 --- a/drivers/isdn/eicon/eicon_io.c +++ /dev/null @@ -1,916 +0,0 @@ -/* $Id$ - * - * ISDN low-level module for Eicon active ISDN-Cards. - * Code for communicating with hardware. - * - * Copyright 1999,2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * Thanks to Eicon Technology GmbH & Co. oHG for - * documents, informations and hardware. - * - * 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. - * - * $Log$ - * Revision 1.9 1999/11/18 20:55:25 armin - * Ready_Int fix of ISA cards. - * - * Revision 1.8 1999/10/08 22:09:34 armin - * Some fixes of cards interface handling. - * Bugfix of NULL pointer occurence. - * Changed a few log outputs. - * - * Revision 1.7 1999/09/26 14:17:53 armin - * Improved debug and log via readstat() - * - * Revision 1.6 1999/09/21 20:35:43 armin - * added more error checking. - * - * Revision 1.5 1999/08/31 11:20:11 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.4 1999/08/22 20:26:47 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.3 1999/08/18 20:17:01 armin - * Added XLOG function for all cards. - * Bugfix of alloc_skb NULL pointer. - * - * Revision 1.2 1999/07/25 15:12:05 armin - * fix of some debug logs. - * enabled ISA-cards option. - * - * Revision 1.1 1999/03/29 11:19:45 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * - */ - - -#include -#include "eicon.h" - -void -eicon_io_rcv_dispatch(eicon_card *ccard) { - ulong flags; - struct sk_buff *skb, *skb2, *skb_new; - eicon_IND *ind, *ind2, *ind_new; - eicon_chan *chan; - - if (!ccard) { - eicon_log(ccard, 1, "eicon_err: NULL card in rcv_dispatch !\n"); - return; - } - - while((skb = skb_dequeue(&ccard->rcvq))) { - ind = (eicon_IND *)skb->data; - - save_flags(flags); - cli(); - if ((chan = ccard->IdTable[ind->IndId]) == NULL) { - if (DebugVar & 1) { - switch(ind->Ind) { - case IDI_N_DISC_ACK: - /* doesn't matter if this happens */ - break; - default: - eicon_log(ccard, 1, "idi: Indication for unknown channel Ind=%d Id=%x\n", ind->Ind, ind->IndId); - eicon_log(ccard, 1, "idi_hdl: Ch??: Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", - ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length); - } - } - restore_flags(flags); - dev_kfree_skb(skb); - continue; - } - restore_flags(flags); - - if (chan->e.complete) { /* check for rec-buffer chaining */ - if (ind->MLength == ind->RBuffer.length) { - chan->e.complete = 1; - idi_handle_ind(ccard, skb); - continue; - } - else { - chan->e.complete = 0; - ind->Ind = ind->MInd; - skb_queue_tail(&chan->e.R, skb); - continue; - } - } - else { - save_flags(flags); - cli(); - if (!(skb2 = skb_dequeue(&chan->e.R))) { - chan->e.complete = 1; - eicon_log(ccard, 1, "eicon: buffer incomplete, but 0 in queue\n"); - restore_flags(flags); - dev_kfree_skb(skb); - continue; - } - ind2 = (eicon_IND *)skb2->data; - skb_new = alloc_skb(((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length), - GFP_ATOMIC); - if (!skb_new) { - eicon_log(ccard, 1, "eicon_io: skb_alloc failed in rcv_dispatch()\n"); - restore_flags(flags); - dev_kfree_skb(skb); - dev_kfree_skb(skb2); - continue; - } - ind_new = (eicon_IND *)skb_put(skb_new, - ((sizeof(eicon_IND)-1)+ind->RBuffer.length+ind2->RBuffer.length)); - ind_new->Ind = ind2->Ind; - ind_new->IndId = ind2->IndId; - ind_new->IndCh = ind2->IndCh; - ind_new->MInd = ind2->MInd; - ind_new->MLength = ind2->MLength; - ind_new->RBuffer.length = ind2->RBuffer.length + ind->RBuffer.length; - memcpy(&ind_new->RBuffer.P, &ind2->RBuffer.P, ind2->RBuffer.length); - memcpy((&ind_new->RBuffer.P)+ind2->RBuffer.length, &ind->RBuffer.P, ind->RBuffer.length); - dev_kfree_skb(skb); - dev_kfree_skb(skb2); - if (ind->MLength == ind->RBuffer.length) { - chan->e.complete = 2; - restore_flags(flags); - idi_handle_ind(ccard, skb_new); - continue; - } - else { - chan->e.complete = 0; - skb_queue_tail(&chan->e.R, skb_new); - restore_flags(flags); - continue; - } - } - } -} - -void -eicon_io_ack_dispatch(eicon_card *ccard) { - struct sk_buff *skb; - - if (!ccard) { - eicon_log(ccard, 1, "eicon_err: NULL card in ack_dispatch!\n"); - return; - } - while((skb = skb_dequeue(&ccard->rackq))) { - idi_handle_ack(ccard, skb); - } -} - - -/* - * IO-Functions for different card-types - */ - -u8 ram_inb(eicon_card *card, void *adr) { - eicon_pci_card *pcard; - eicon_isa_card *icard; - u32 addr = (u32) adr; - - pcard = &card->hwif.pci; - icard = &card->hwif.isa; - - switch(card->type) { - case EICON_CTYPE_MAESTRA: - outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); - return(inb((u16)pcard->PCIreg + M_DATA)); - case EICON_CTYPE_MAESTRAP: - case EICON_CTYPE_S2M: - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - return(readb(addr)); - } - return(0); -} - -u16 ram_inw(eicon_card *card, void *adr) { - eicon_pci_card *pcard; - eicon_isa_card *icard; - u32 addr = (u32) adr; - - pcard = &card->hwif.pci; - icard = &card->hwif.isa; - - switch(card->type) { - case EICON_CTYPE_MAESTRA: - outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); - return(inw((u16)pcard->PCIreg + M_DATA)); - case EICON_CTYPE_MAESTRAP: - case EICON_CTYPE_S2M: - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - return(readw(addr)); - } - return(0); -} - -void ram_outb(eicon_card *card, void *adr, u8 data) { - eicon_pci_card *pcard; - eicon_isa_card *icard; - u32 addr = (u32) adr; - - pcard = &card->hwif.pci; - icard = &card->hwif.isa; - - switch(card->type) { - case EICON_CTYPE_MAESTRA: - outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); - outb((u8)data, (u16)pcard->PCIreg + M_DATA); - break; - case EICON_CTYPE_MAESTRAP: - case EICON_CTYPE_S2M: - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - writeb(data, addr); - break; - } -} - -void ram_outw(eicon_card *card, void *adr , u16 data) { - eicon_pci_card *pcard; - eicon_isa_card *icard; - u32 addr = (u32) adr; - - pcard = &card->hwif.pci; - icard = &card->hwif.isa; - - switch(card->type) { - case EICON_CTYPE_MAESTRA: - outw((u16)addr, (u16)pcard->PCIreg + M_ADDR); - outw((u16)data, (u16)pcard->PCIreg + M_DATA); - break; - case EICON_CTYPE_MAESTRAP: - case EICON_CTYPE_S2M: - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - writew(data, addr); - break; - } -} - -void ram_copyfromcard(eicon_card *card, void *adrto, void *adr, int len) { - int i; - switch(card->type) { - case EICON_CTYPE_MAESTRA: - for(i = 0; i < len; i++) { - writeb(ram_inb(card, adr + i), adrto + i); - } - break; - case EICON_CTYPE_MAESTRAP: - memcpy(adrto, adr, len); - break; - case EICON_CTYPE_S2M: - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - memcpy_fromio(adrto, adr, len); - break; - } -} - -void ram_copytocard(eicon_card *card, void *adrto, void *adr, int len) { - int i; - switch(card->type) { - case EICON_CTYPE_MAESTRA: - for(i = 0; i < len; i++) { - ram_outb(card, adrto + i, readb(adr + i)); - } - break; - case EICON_CTYPE_MAESTRAP: - memcpy(adrto, adr, len); - break; - case EICON_CTYPE_S2M: - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - memcpy_toio(adrto, adr, len); - break; - } -} - -/* - * XLOG - */ -int -eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq) -{ - int timeout, i; - int divas_shared_offset = 0; - int len = 0; - int stype = 0; - __u32 time = 0; - mi_pc_maint_t *pcm = &xlogreq->pcm; - eicon_pci_card *pci_card = &card->hwif.pci; - eicon_isa_card *isa_card = &card->hwif.isa; - eicon_pr_ram *prram = 0; - char *ram; - - switch(card->type) { - case EICON_CTYPE_MAESTRAP: - ram = (char *)pci_card->PCIram; - prram = (eicon_pr_ram *)ram; - divas_shared_offset = DIVAS_SHARED_OFFSET; - len = sizeof(mi_pc_maint_t); - break; - case EICON_CTYPE_MAESTRA: - prram = 0; - divas_shared_offset = 0; - len = sizeof(mi_pc_maint_t); - break; - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - case EICON_CTYPE_S2M: - prram = (eicon_pr_ram *)isa_card->shmem; - divas_shared_offset = 0xfb80; - len = sizeof(mi_pc_maint_t) - 78; - stype = 1; - break; - default: - return -ENODEV; - } - - memset(&(xlogreq->pcm), 0, sizeof(mi_pc_maint_t)); - - xlogreq->pcm.rc = 0; - xlogreq->pcm.req = 1; /* DO_LOG */ - - ram = ((char *)prram) + MIPS_MAINT_OFFS - divas_shared_offset; - - ram_outb(card, ram+1, pcm->rc); - ram_outb(card, ram+0, pcm->req); - - timeout = jiffies + 50; - while (timeout > jiffies) { - pcm->rc = ram_inb(card, ram+1); - pcm->req = ram_inb(card, ram+0); - if (!pcm->req) break; - SLEEP(10); - } - - if (pcm->req) { - return XLOG_ERR_TIMEOUT; - } - - if (pcm->rc != OK) { - return XLOG_ERR_DONE; - } - - ram_copyfromcard(card, pcm, ram, len); - - if (stype) { - for (i=0; i<8; i++) - ((__u8 *)pcm)[11-i] = ((__u8 *)pcm)[9-i]; - time = (__u32)pcm->data.w[2] * 3600 * 1000 + - (__u32)pcm->data.w[1] * 1000 + - (__u32)pcm->data.b[1] * 20 + - (__u32)pcm->data.b[0] ; - pcm->data.w[1] = (__u16) (time >> 16); - pcm->data.w[2] = (__u16) (time & 0x0000ffff); - pcm->data.w[0] = 2; - } - - return XLOG_OK; -} - -/* - * Transmit-Function - */ -void -eicon_io_transmit(eicon_card *ccard) { - eicon_pci_card *pci_card; - eicon_isa_card *isa_card; - struct sk_buff *skb; - struct sk_buff *skb2; - unsigned long flags; - char *ram, *reg, *cfg; - eicon_pr_ram *prram = 0; - eicon_isa_com *com = 0; - eicon_REQ *ReqOut = 0; - eicon_REQ *reqbuf = 0; - eicon_chan *chan; - eicon_chan_ptr *chan2; - int ReqCount; - int scom = 0; - int tmp = 0; - int quloop = 1; - int dlev = 0; - - pci_card = &ccard->hwif.pci; - isa_card = &ccard->hwif.isa; - - if (!ccard) { - eicon_log(ccard, 1, "eicon_transmit: NULL card!\n"); - return; - } - - switch(ccard->type) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - scom = 1; - com = (eicon_isa_com *)isa_card->shmem; - break; - case EICON_CTYPE_S2M: - scom = 0; - prram = (eicon_pr_ram *)isa_card->shmem; - break; -#endif - case EICON_CTYPE_MAESTRAP: - scom = 0; - ram = (char *)pci_card->PCIram; - reg = (char *)pci_card->PCIreg; - cfg = (char *)pci_card->PCIcfg; - prram = (eicon_pr_ram *)ram; - break; - case EICON_CTYPE_MAESTRA: - scom = 0; - ram = (char *)pci_card->PCIram; - reg = (char *)pci_card->PCIreg; - cfg = (char *)pci_card->PCIcfg; - prram = 0; - break; - default: - eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n"); - return; - } - - ReqCount = 0; - if (!(skb2 = skb_dequeue(&ccard->sndq))) - quloop = 0; - while(quloop) { - save_flags(flags); - cli(); - if (scom) { - if ((ram_inb(ccard, &com->Req)) || (ccard->ReadyInt)) { - if (!ccard->ReadyInt) { - tmp = ram_inb(ccard, &com->ReadyInt) + 1; - ram_outb(ccard, &com->ReadyInt, tmp); - ccard->ReadyInt++; - } - restore_flags(flags); - skb_queue_head(&ccard->sndq, skb2); - eicon_log(ccard, 32, "eicon: transmit: Card not ready\n"); - return; - } - } else { - if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) { - restore_flags(flags); - skb_queue_head(&ccard->sndq, skb2); - eicon_log(ccard, 32, "eicon: transmit: Card not ready\n"); - return; - } - } - restore_flags(flags); - chan2 = (eicon_chan_ptr *)skb2->data; - chan = chan2->ptr; - if (!chan->e.busy) { - if((skb = skb_dequeue(&chan->e.X))) { - save_flags(flags); - cli(); - reqbuf = (eicon_REQ *)skb->data; - if ((reqbuf->Reference) && (chan->e.B2Id == 0) && (reqbuf->ReqId & 0x1f)) { - eicon_log(ccard, 16, "eicon: transmit: error Id=0 on %d (Net)\n", chan->No); - } else { - if (scom) { - ram_outw(ccard, &com->XBuffer.length, reqbuf->XBuffer.length); - ram_copytocard(ccard, &com->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length); - ram_outb(ccard, &com->ReqCh, reqbuf->ReqCh); - - } else { - /* get address of next available request buffer */ - ReqOut = (eicon_REQ *)&prram->B[ram_inw(ccard, &prram->NextReq)]; - ram_outw(ccard, &ReqOut->XBuffer.length, reqbuf->XBuffer.length); - ram_copytocard(ccard, &ReqOut->XBuffer.P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length); - ram_outb(ccard, &ReqOut->ReqCh, reqbuf->ReqCh); - ram_outb(ccard, &ReqOut->Req, reqbuf->Req); - } - dlev = 160; - if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */ - - if (!reqbuf->Reference) { /* Signal Layer */ - if (scom) - ram_outb(ccard, &com->ReqId, chan->e.D3Id); - else - ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id); - - chan->e.ReqCh = 0; - } - else { /* Net Layer */ - if (scom) - ram_outb(ccard, &com->ReqId, chan->e.B2Id); - else - ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id); - - chan->e.ReqCh = 1; - if (((reqbuf->Req & 0x0f) == 0x08) || - ((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */ - chan->waitq = reqbuf->XBuffer.length; - chan->waitpq += reqbuf->XBuffer.length; - dlev = 128; - } - } - - } else { /* It is an ASSIGN */ - - if (scom) - ram_outb(ccard, &com->ReqId, reqbuf->ReqId); - else - ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId); - - if (!reqbuf->Reference) - chan->e.ReqCh = 0; - else - chan->e.ReqCh = 1; - } - if (scom) - chan->e.ref = ccard->ref_out++; - else - chan->e.ref = ram_inw(ccard, &ReqOut->Reference); - - chan->e.Req = reqbuf->Req; - ReqCount++; - if (scom) - ram_outb(ccard, &com->Req, reqbuf->Req); - else - ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next)); - - chan->e.busy = 1; - eicon_log(ccard, dlev, "eicon: Req=%d Id=%x Ch=%d Len=%d Ref=%d\n", - reqbuf->Req, - (scom) ? ram_inb(ccard, &com->ReqId) : - ram_inb(ccard, &ReqOut->ReqId), - reqbuf->ReqCh, reqbuf->XBuffer.length, - chan->e.ref); - } - restore_flags(flags); - dev_kfree_skb(skb); - } - dev_kfree_skb(skb2); - } - else { - skb_queue_tail(&ccard->sackq, skb2); - eicon_log(ccard, 128, "eicon: transmit: busy chan %d\n", chan->No); - } - - if (scom) - quloop = 0; - else - if (!(skb2 = skb_dequeue(&ccard->sndq))) - quloop = 0; - - } - if (!scom) - ram_outb(ccard, &prram->ReqInput, (__u8)(ram_inb(ccard, &prram->ReqInput) + ReqCount)); - - while((skb = skb_dequeue(&ccard->sackq))) { - skb_queue_tail(&ccard->sndq, skb); - } -} - - -/* - * IRQ handler - */ -void -eicon_irq(int irq, void *dev_id, struct pt_regs *regs) { - eicon_card *ccard = (eicon_card *)dev_id; - eicon_pci_card *pci_card; - eicon_isa_card *isa_card; - char *ram = 0; - char *reg = 0; - char *cfg = 0; - eicon_pr_ram *prram = 0; - eicon_isa_com *com = 0; - eicon_RC *RcIn; - eicon_IND *IndIn; - struct sk_buff *skb; - int Count = 0; - int Rc = 0; - int Ind = 0; - unsigned char *irqprobe = 0; - int scom = 0; - int tmp = 0; - int dlev = 0; - - - if (!ccard) { - eicon_log(ccard, 1, "eicon_irq: spurious interrupt %d\n", irq); - return; - } - - if (ccard->type == EICON_CTYPE_QUADRO) { - tmp = 4; - while(tmp) { - com = (eicon_isa_com *)ccard->hwif.isa.shmem; - if ((readb(ccard->hwif.isa.intack))) { /* quadro found */ - break; - } - ccard = ccard->qnext; - tmp--; - } - } - - pci_card = &ccard->hwif.pci; - isa_card = &ccard->hwif.isa; - - switch(ccard->type) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - scom = 1; - com = (eicon_isa_com *)isa_card->shmem; - irqprobe = &isa_card->irqprobe; - break; - case EICON_CTYPE_S2M: - scom = 0; - prram = (eicon_pr_ram *)isa_card->shmem; - irqprobe = &isa_card->irqprobe; - break; -#endif - case EICON_CTYPE_MAESTRAP: - scom = 0; - ram = (char *)pci_card->PCIram; - reg = (char *)pci_card->PCIreg; - cfg = (char *)pci_card->PCIcfg; - irqprobe = &pci_card->irqprobe; - prram = (eicon_pr_ram *)ram; - break; - case EICON_CTYPE_MAESTRA: - scom = 0; - ram = (char *)pci_card->PCIram; - reg = (char *)pci_card->PCIreg; - cfg = (char *)pci_card->PCIcfg; - irqprobe = &pci_card->irqprobe; - prram = 0; - break; - default: - eicon_log(ccard, 1, "eicon_irq: unsupported card-type!\n"); - return; - } - - if (*irqprobe) { - switch(ccard->type) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - if (readb(isa_card->intack)) { - writeb(0, &com->Rc); - writeb(0, isa_card->intack); - } - (*irqprobe)++; - break; - case EICON_CTYPE_S2M: - if (readb(isa_card->intack)) { - writeb(0, &prram->RcOutput); - writeb(0, isa_card->intack); - } - (*irqprobe)++; - break; -#endif - case EICON_CTYPE_MAESTRAP: - if (readb(&ram[0x3fe])) { - writeb(0, &prram->RcOutput); - writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]); - writew(0, &cfg[MP_IRQ_RESET + 2]); - writeb(0, &ram[0x3fe]); - } - *irqprobe = 0; - break; - case EICON_CTYPE_MAESTRA: - outb(0x08, pci_card->PCIreg + M_RESET); - *irqprobe = 0; - break; - } - return; - } - - switch(ccard->type) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - case EICON_CTYPE_S2M: - if (!(readb(isa_card->intack))) { /* card did not interrupt */ - eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); - return; - } - break; -#endif - case EICON_CTYPE_MAESTRAP: - if (!(readb(&ram[0x3fe]))) { /* card did not interrupt */ - eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); - return; - } - break; - case EICON_CTYPE_MAESTRA: - outw(0x3fe, pci_card->PCIreg + M_ADDR); - if (!(inb(pci_card->PCIreg + M_DATA))) { /* card did not interrupt */ - eicon_log(ccard, 1, "eicon: IRQ: card reports no interrupt!\n"); - return; - } - break; - } - - if (scom) { - - /* if a return code is available ... */ - if ((tmp = ram_inb(ccard, &com->Rc))) { - eicon_RC *ack; - if (tmp == READY_INT) { - eicon_log(ccard, 64, "eicon: IRQ Rc=READY_INT\n"); - if (ccard->ReadyInt) { - ccard->ReadyInt--; - ram_outb(ccard, &com->Rc, 0); - eicon_schedule_tx(ccard); - } - } else { - skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); - } else { - ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); - ack->Rc = tmp; - ack->RcId = ram_inb(ccard, &com->RcId); - ack->RcCh = ram_inb(ccard, &com->RcCh); - ack->Reference = ccard->ref_in++; - eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", - tmp,ack->RcId,ack->RcCh,ack->Reference); - skb_queue_tail(&ccard->rackq, skb); - eicon_schedule_ack(ccard); - } - ram_outb(ccard, &com->Req, 0); - ram_outb(ccard, &com->Rc, 0); - } - - } else { - - /* if an indication is available ... */ - if ((tmp = ram_inb(ccard, &com->Ind))) { - eicon_IND *ind; - int len = ram_inw(ccard, &com->RBuffer.length); - skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); - } else { - ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); - ind->Ind = tmp; - ind->IndId = ram_inb(ccard, &com->IndId); - ind->IndCh = ram_inb(ccard, &com->IndCh); - ind->MInd = ram_inb(ccard, &com->MInd); - ind->MLength = ram_inw(ccard, &com->MLength); - ind->RBuffer.length = len; - if ((tmp == 1) || (tmp == 8)) - dlev = 128; - else - dlev = 192; - eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", - tmp,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); - ram_copyfromcard(ccard, &ind->RBuffer.P, &com->RBuffer.P, len); - skb_queue_tail(&ccard->rcvq, skb); - eicon_schedule_rx(ccard); - } - ram_outb(ccard, &com->Ind, 0); - } - } - - } else { - - /* if return codes are available ... */ - if((Count = ram_inb(ccard, &prram->RcOutput))) { - eicon_RC *ack; - /* get the buffer address of the first return code */ - RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &prram->NextRc)]; - /* for all return codes do ... */ - while(Count--) { - - if((Rc=ram_inb(ccard, &RcIn->Rc))) { - skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); - } else { - ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC)); - ack->Rc = Rc; - ack->RcId = ram_inb(ccard, &RcIn->RcId); - ack->RcCh = ram_inb(ccard, &RcIn->RcCh); - ack->Reference = ram_inw(ccard, &RcIn->Reference); - eicon_log(ccard, 128, "eicon: IRQ Rc=%d Id=%x Ch=%d Ref=%d\n", - Rc,ack->RcId,ack->RcCh,ack->Reference); - skb_queue_tail(&ccard->rackq, skb); - eicon_schedule_ack(ccard); - } - ram_outb(ccard, &RcIn->Rc, 0); - } - /* get buffer address of next return code */ - RcIn = (eicon_RC *)&prram->B[ram_inw(ccard, &RcIn->next)]; - } - /* clear all return codes (no chaining!) */ - ram_outb(ccard, &prram->RcOutput, 0); - } - - /* if indications are available ... */ - if((Count = ram_inb(ccard, &prram->IndOutput))) { - eicon_IND *ind; - /* get the buffer address of the first indication */ - IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &prram->NextInd)]; - /* for all indications do ... */ - while(Count--) { - Ind = ram_inb(ccard, &IndIn->Ind); - if(Ind) { - int len = ram_inw(ccard, &IndIn->RBuffer.length); - skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC); - if (!skb) { - eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _irq()\n"); - } else { - ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1)); - ind->Ind = Ind; - ind->IndId = ram_inb(ccard, &IndIn->IndId); - ind->IndCh = ram_inb(ccard, &IndIn->IndCh); - ind->MInd = ram_inb(ccard, &IndIn->MInd); - ind->MLength = ram_inw(ccard, &IndIn->MLength); - ind->RBuffer.length = len; - if ((Ind == 1) || (Ind == 8)) - dlev = 128; - else - dlev = 192; - eicon_log(ccard, dlev, "eicon: IRQ Ind=%d Id=%x Ch=%d MInd=%d MLen=%d Len=%d\n", - Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,len); - ram_copyfromcard(ccard, &ind->RBuffer.P, &IndIn->RBuffer.P, len); - skb_queue_tail(&ccard->rcvq, skb); - eicon_schedule_rx(ccard); - } - ram_outb(ccard, &IndIn->Ind, 0); - } - /* get buffer address of next indication */ - IndIn = (eicon_IND *)&prram->B[ram_inw(ccard, &IndIn->next)]; - } - ram_outb(ccard, &prram->IndOutput, 0); - } - - } - - /* clear interrupt */ - switch(ccard->type) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_CTYPE_QUADRO: - writeb(0, isa_card->intack); - writeb(0, &com[0x401]); - break; - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_S2M: - writeb(0, isa_card->intack); - break; -#endif - case EICON_CTYPE_MAESTRAP: - writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]); - writew(0, &cfg[MP_IRQ_RESET + 2]); - writeb(0, &ram[0x3fe]); - break; - case EICON_CTYPE_MAESTRA: - outb(0x08, pci_card->PCIreg + M_RESET); - outw(0x3fe, pci_card->PCIreg + M_ADDR); - outb(0, pci_card->PCIreg + M_DATA); - break; - } - - return; -} - diff --git a/drivers/isdn/eicon/eicon_isa.c b/drivers/isdn/eicon/eicon_isa.c deleted file mode 100644 index c902f055..00000000 --- a/drivers/isdn/eicon/eicon_isa.c +++ /dev/null @@ -1,544 +0,0 @@ -/* $Id$ - * - * ISDN low-level module for Eicon active ISDN-Cards. - * Hardware-specific code for old ISA cards. - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * 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. - * - * $Log$ - * Revision 1.13 2000/01/23 21:21:23 armin - * Added new trace capability and some updates. - * DIVA Server BRI now supports data for ISDNLOG. - * - * Revision 1.12 1999/11/27 12:56:19 armin - * Forgot some iomem changes for last ioremap compat. - * - * Revision 1.11 1999/11/25 11:33:09 armin - * Microchannel fix from Erik Weber (exrz73@ibm.net). - * - * Revision 1.10 1999/11/18 21:14:30 armin - * New ISA memory mapped IO - * - * Revision 1.9 1999/09/08 20:17:31 armin - * Added microchannel patch from Erik Weber (exrz73@ibm.net). - * - * Revision 1.8 1999/09/06 07:29:35 fritz - * Changed my mail-address. - * - * Revision 1.7 1999/08/22 20:26:48 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.6 1999/07/25 15:12:06 armin - * fix of some debug logs. - * enabled ISA-cards option. - * - * Revision 1.5 1999/04/01 12:48:33 armin - * Changed some log outputs. - * - * Revision 1.4 1999/03/29 11:19:46 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.3 1999/03/02 12:37:45 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.2 1999/01/24 20:14:19 armin - * Changed and added debug stuff. - * Better data sending. (still problems with tty's flip buffer) - * - * Revision 1.1 1999/01/01 18:09:43 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - -#include -#include "eicon.h" -#include "eicon_isa.h" - -#define check_shmem check_region -#define release_shmem release_region -#define request_shmem request_region - -char *eicon_isa_revision = "$Revision$"; - -#undef EICON_MCA_DEBUG - -#ifdef CONFIG_ISDN_DRV_EICON_ISA - -/* Mask for detecting invalid IRQ parameter */ -static int eicon_isa_valid_irq[] = { - 0x1c1c, /* 2, 3, 4, 10, 11, 12 (S)*/ - 0x1c1c, /* 2, 3, 4, 10, 11, 12 (SX) */ - 0x1cbc, /* 2, 3, 4, 5, 7, 10, 11, 12 (SCOM) */ - 0x1cbc, /* 2, 3, 4, 5, 6, 10, 11, 12 (Quadro) */ - 0x1cbc /* 2, 3, 4, 5, 7, 10, 11, 12 (S2M) */ -}; - -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; -} - -static void -eicon_isa_release_irq(eicon_isa_card *card) { - if (!card->master) - return; - if (card->ivalid) - free_irq(card->irq, card); - card->ivalid = 0; -} - -void -eicon_isa_release(eicon_isa_card *card) { - eicon_isa_release_irq(card); - eicon_isa_release_shmem(card); -} - -void -eicon_isa_printpar(eicon_isa_card *card) { - switch (card->type) { - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - case EICON_CTYPE_S2M: - printk(KERN_INFO "Eicon %s at 0x%lx, irq %d.\n", - eicon_ctype_name[card->type], - card->physmem, - card->irq); - } -} - -int -eicon_isa_find_card(int Mem, int Irq, char * Id) -{ - int primary = 1; - unsigned long amem; - - if (!strlen(Id)) - return -1; - - if (Mem == -1) - return -1; - - /* Check for valid membase address */ - if ((Mem < 0x0c0000) || - (Mem > 0x0fc000) || - (Mem & 0xfff)) { - printk(KERN_WARNING "eicon_isa: illegal membase 0x%x for %s\n", - 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); - if (readw(amem + 0x402) != 0) primary = 0; - - printk(KERN_INFO "Eicon: Driver-ID: %s\n", Id); - 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; -} - -int -eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) { - int tmp; - int timeout; - eicon_isa_codebuf cbuf; - unsigned char *code; - eicon_isa_boot *boot; - - if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf))) - return -EFAULT; - - /* Allocate code-buffer and copy code from userspace */ - if (cbuf.bootstrap_len > 1024) { - printk(KERN_WARNING "eicon_isa_boot: Invalid startup-code size %ld\n", - cbuf.bootstrap_len); - return -EINVAL; - } - if (!(code = kmalloc(cbuf.bootstrap_len, GFP_KERNEL))) { - printk(KERN_WARNING "eicon_isa_boot: Couldn't allocate code buffer\n"); - return -ENOMEM; - } - if (copy_from_user(code, &cb->code, cbuf.bootstrap_len)) { - kfree(code); - return -EFAULT; - } - - if (card->type == EICON_CTYPE_ISAPRI) - card->ramsize = RAMSIZE_P; - 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); - kfree(code); - return -EBUSY; - } - 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 - card->mvalid = 1; - - switch(card->type) { - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - case EICON_CTYPE_QUADRO: - case EICON_CTYPE_ISABRI: - card->intack = (__u8 *)card->shmem + INTACK; - card->startcpu = (__u8 *)card->shmem + STARTCPU; - card->stopcpu = (__u8 *)card->shmem + STOPCPU; - break; - case EICON_CTYPE_S2M: - case EICON_CTYPE_ISAPRI: - card->intack = (__u8 *)card->shmem + INTACK_P; - card->startcpu = (__u8 *)card->shmem + STARTCPU_P; - card->stopcpu = (__u8 *)card->shmem + STOPCPU_P; - break; - default: - printk(KERN_WARNING "eicon_isa_boot: Invalid card type %d\n", card->type); - eicon_isa_release_shmem(card); - kfree(code); - return -EINVAL; - } - - /* clear any pending irq's */ - readb(card->intack); -#ifdef CONFIG_MCA - if (MCA_bus) { - if (card->type == EICON_CTYPE_SCOM) { - outb_p(0,card->io+1); - } - else { - printk(KERN_WARNING "eicon_isa_boot: Card type not supported yet.\n"); - eicon_isa_release_shmem(card); - return -EINVAL; - }; - -#ifdef EICON_MCA_DEBUG - printk(KERN_INFO "eicon_isa_boot: card->io = %x.\n", card->io); - printk(KERN_INFO "eicon_isa_boot: card->irq = %d.\n", (int)card->irq); -#endif - } -#else - /* set reset-line active */ - writeb(0, card->stopcpu); -#endif /* CONFIG_MCA */ - /* clear irq-requests */ - writeb(0, card->intack); - readb(card->intack); - - /* Copy code into card */ - memcpy_toio(&card->shmem->c, code, cbuf.bootstrap_len); - - /* Check for properly loaded code */ - if (!check_signature((unsigned long)&card->shmem->c, code, 1020)) { - printk(KERN_WARNING "eicon_isa_boot: Could not load startup-code\n"); - eicon_isa_release_shmem(card); - kfree(code); - return -EIO; - } - /* if 16k-ramsize, duplicate the reset-jump-code */ - if (card->ramsize == RAMSIZE_P) - memcpy_toio((__u8 *)card->shmem + 0x3ff0, &code[0x3f0], 12); - - kfree(code); - boot = &card->shmem->boot; - - /* Delay 0.2 sec. */ - SLEEP(20); - - /* Start CPU */ - writeb(cbuf.boot_opt, &boot->ctrl); -#ifdef CONFIG_MCA - if (MCA_bus) { - outb_p(0, card->io); - } -#else - writeb(0, card->startcpu); -#endif /* CONFIG_MCA */ - - /* Delay 0.2 sec. */ - SLEEP(20); - - timeout = jiffies + (HZ * 22); - while (timeout > jiffies) { - if (readb(&boot->ctrl) == 0) - break; - SLEEP(10); - } - if (readb(&boot->ctrl) != 0) { - printk(KERN_WARNING "eicon_isa_boot: CPU test failed.\n"); -#ifdef EICON_MCA_DEBUG - printk(KERN_INFO "eicon_isa_boot: &boot->ctrl = %d.\n", - readb(&boot->ctrl)); -#endif - eicon_isa_release_shmem(card); - return -EIO; - } - - /* Check for memory-test errors */ - if (readw(&boot->ebit)) { - printk(KERN_WARNING "eicon_isa_boot: memory test failed (bit 0x%04x at 0x%08x)\n", - readw(&boot->ebit), readl(&boot->eloc)); - eicon_isa_release_shmem(card); - return -EIO; - } - - /* Check card type and memory size */ - tmp = readb(&boot->card); - if ((tmp < 0) || (tmp > 4)) { - printk(KERN_WARNING "eicon_isa_boot: Type detect failed\n"); - eicon_isa_release_shmem(card); - return -EIO; - } - card->type = tmp; - ((eicon_card *)card->card)->type = tmp; - - tmp = readb(&boot->msize); - if (tmp != 8 && tmp != 16 && tmp != 24 && - tmp != 32 && tmp != 48 && tmp != 60) { - printk(KERN_WARNING "eicon_isa_boot: invalid memsize\n"); - eicon_isa_release_shmem(card); - return -EIO; - } - printk(KERN_INFO "%s: startup-code loaded\n", eicon_ctype_name[card->type]); - if ((card->type == EICON_CTYPE_QUADRO) && (card->master)) { - tmp = eicon_addcard(card->type, card->physmem, card->irq, - ((eicon_card *)card->card)->regname); - printk(KERN_INFO "Eicon: %d adapters added\n", tmp); - } - return 0; -} - -int -eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) { - eicon_isa_boot *boot; - int tmp; - int timeout; - int j; - eicon_isa_codebuf cbuf; - unsigned char *code; - unsigned char *p; - - if (copy_from_user(&cbuf, cb, sizeof(eicon_isa_codebuf))) - return -EFAULT; - - if (!(code = kmalloc(cbuf.firmware_len, GFP_KERNEL))) { - printk(KERN_WARNING "eicon_isa_load: Couldn't allocate code buffer\n"); - return -ENOMEM; - } - - if (copy_from_user(code, &cb->code, cbuf.firmware_len)) { - kfree(code); - return -EFAULT; - } - - boot = &card->shmem->boot; - - if ((!card->ivalid) && card->master) { - card->irqprobe = 1; - /* Check for valid IRQ */ - if ((card->irq < 0) || (card->irq > 15) || - (!((1 << card->irq) & eicon_isa_valid_irq[card->type & 0x0f]))) { - printk(KERN_WARNING "eicon_isa_load: illegal irq: %d\n", card->irq); - eicon_isa_release_shmem(card); - kfree(code); - return -EINVAL; - } - /* Register irq */ - if (!request_irq(card->irq, &eicon_irq, 0, "Eicon ISA ISDN", card)) - card->ivalid = 1; - else { - printk(KERN_WARNING "eicon_isa_load: irq %d already in use.\n", - card->irq); - eicon_isa_release_shmem(card); - kfree(code); - return -EBUSY; - } - } - - tmp = readb(&boot->msize); - if (tmp != 8 && tmp != 16 && tmp != 24 && - tmp != 32 && tmp != 48 && tmp != 60) { - printk(KERN_WARNING "eicon_isa_load: invalid memsize\n"); - eicon_isa_release_shmem(card); - return -EIO; - } - - eicon_isa_printpar(card); - - /* Download firmware */ - printk(KERN_INFO "%s %dkB, loading firmware ...\n", - eicon_ctype_name[card->type], - tmp * 16); - tmp = cbuf.firmware_len >> 8; - p = code; - while (tmp--) { - memcpy_toio(&boot->b, p, 256); - writeb(1, &boot->ctrl); - timeout = jiffies + 10; - while (timeout > jiffies) { - if (readb(&boot->ctrl) == 0) - break; - SLEEP(2); - } - if (readb(&boot->ctrl)) { - printk(KERN_WARNING "eicon_isa_load: download timeout at 0x%x\n", p-code); - eicon_isa_release(card); - kfree(code); - return -EIO; - } - p += 256; - } - kfree(code); - - /* Initialize firmware parameters */ - memcpy_toio(&card->shmem->c[8], &cbuf.tei, 14); - memcpy_toio(&card->shmem->c[32], &cbuf.oad, 96); - memcpy_toio(&card->shmem->c[128], &cbuf.oad, 96); - - /* Start firmware, wait for signature */ - writeb(2, &boot->ctrl); - timeout = jiffies + (5*HZ); - while (timeout > jiffies) { - if (readw(&boot->signature) == 0x4447) - break; - SLEEP(2); - } - if (readw(&boot->signature) != 0x4447) { - printk(KERN_WARNING "eicon_isa_load: firmware selftest failed %04x\n", - readw(&boot->signature)); - eicon_isa_release(card); - return -EIO; - } - - card->channels = readb(&card->shmem->c[0x3f6]); - - /* clear irq-requests, reset irq-count */ - readb(card->intack); - writeb(0, card->intack); - - if (card->master) { - card->irqprobe = 1; - /* Trigger an interrupt and check if it is delivered */ - tmp = readb(&card->shmem->com.ReadyInt); - tmp ++; - writeb(tmp, &card->shmem->com.ReadyInt); - timeout = jiffies + 20; - while (timeout > jiffies) { - if (card->irqprobe > 1) - break; - SLEEP(2); - } - if (card->irqprobe == 1) { - printk(KERN_WARNING "eicon_isa_load: IRQ # %d test failed\n", card->irq); - eicon_isa_release(card); - return -EIO; - } - } -#ifdef EICON_MCA_DEBUG - printk(KERN_INFO "eicon_isa_load: IRQ # %d test succeeded.\n", card->irq); -#endif - - writeb(card->irq, &card->shmem->com.Int); - - /* initializing some variables */ - ((eicon_card *)card->card)->ReadyInt = 0; - ((eicon_card *)card->card)->ref_in = 1; - ((eicon_card *)card->card)->ref_out = 1; - for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL; - for(j=0; j< (card->channels + 1); j++) { - ((eicon_card *)card->card)->bch[j].e.busy = 0; - ((eicon_card *)card->card)->bch[j].e.D3Id = 0; - ((eicon_card *)card->card)->bch[j].e.B2Id = 0; - ((eicon_card *)card->card)->bch[j].e.ref = 0; - ((eicon_card *)card->card)->bch[j].e.Req = 0; - ((eicon_card *)card->card)->bch[j].e.complete = 1; - ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL; - } - - printk(KERN_INFO "Eicon: Supported channels: %d\n", card->channels); - printk(KERN_INFO "%s successfully started\n", eicon_ctype_name[card->type]); - - /* Enable normal IRQ processing */ - card->irqprobe = 0; - return 0; -} - -#endif /* CONFIG_ISDN_DRV_EICON_ISA */ diff --git a/drivers/isdn/eicon/eicon_isa.h b/drivers/isdn/eicon/eicon_isa.h deleted file mode 100644 index 0c42ac7f..00000000 --- a/drivers/isdn/eicon/eicon_isa.h +++ /dev/null @@ -1,161 +0,0 @@ -/* $Id$ - * - * ISDN low-level module for Eicon active ISDN-Cards. - * - * Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * 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. - * - * $Log$ - * Revision 1.7 1999/11/18 21:14:30 armin - * New ISA memory mapped IO - * - * Revision 1.6 1999/11/15 19:37:04 keil - * need config.h - * - * Revision 1.5 1999/09/08 20:17:31 armin - * Added microchannel patch from Erik Weber. - * - * Revision 1.4 1999/09/06 07:29:35 fritz - * Changed my mail-address. - * - * Revision 1.3 1999/03/29 11:19:47 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.2 1999/03/02 12:37:46 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.1 1999/01/01 18:09:44 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - -#ifndef eicon_isa_h -#define eicon_isa_h - -#ifdef __KERNEL__ -#include - -/* Factory defaults for ISA-Cards */ -#define EICON_ISA_MEMBASE 0xd0000 -#define EICON_ISA_IRQ 3 -/* shmem offset for Quadro parts */ -#define EICON_ISA_QOFFSET 0x0800 - -typedef struct { - __u16 length __attribute__ ((packed)); /* length of data/parameter field */ - __u8 P[270]; /* data/parameter field */ -} eicon_scom_PBUFFER; - -/* General communication buffer */ -typedef struct { - __u8 Req; /* request register */ - __u8 ReqId; /* request task/entity identification */ - __u8 Rc; /* return code register */ - __u8 RcId; /* return code task/entity identification */ - __u8 Ind; /* Indication register */ - __u8 IndId; /* Indication task/entity identification */ - __u8 IMask; /* Interrupt Mask Flag */ - __u8 RNR; /* Receiver Not Ready (set by PC) */ - __u8 XLock; /* XBuffer locked Flag */ - __u8 Int; /* ISDN interrupt */ - __u8 ReqCh; /* Channel field for layer-3 Requests */ - __u8 RcCh; /* Channel field for layer-3 Returncodes */ - __u8 IndCh; /* Channel field for layer-3 Indications */ - __u8 MInd; /* more data indication field */ - __u16 MLength; /* more data total packet length */ - __u8 ReadyInt; /* request field for ready interrupt */ - __u8 Reserved[12]; /* reserved space */ - __u8 IfType; /* 1 = 16k-Interface */ - __u16 Signature __attribute__ ((packed)); /* ISDN adapter Signature */ - eicon_scom_PBUFFER XBuffer; /* Transmit Buffer */ - eicon_scom_PBUFFER RBuffer; /* Receive Buffer */ -} eicon_isa_com; - -/* struct for downloading firmware */ -typedef struct { - __u8 ctrl; - __u8 card; - __u8 msize; - __u8 fill0; - __u16 ebit __attribute__ ((packed)); - __u32 eloc __attribute__ ((packed)); - __u8 reserved[20]; - __u16 signature __attribute__ ((packed)); - __u8 fill[224]; - __u8 b[256]; -} eicon_isa_boot; - -/* Shared memory */ -typedef union { - unsigned char c[0x400]; - eicon_isa_com com; - eicon_isa_boot boot; -} eicon_isa_shmem; - -/* - * card's description - */ -typedef struct { - int ramsize; - int irq; /* IRQ */ - unsigned long physmem; /* physical memory address */ -#ifdef CONFIG_MCA - int io; /* IO-port for MCA brand */ -#endif /* CONFIG_MCA */ - void* card; - eicon_isa_shmem* shmem; /* Shared-memory area */ - unsigned char* intack; /* Int-Acknowledge */ - unsigned char* stopcpu; /* Writing here stops CPU */ - unsigned char* startcpu; /* Writing here starts CPU */ - unsigned char type; /* card type */ - int channels; /* No. of channels */ - unsigned char irqprobe; /* Flag: IRQ-probing */ - unsigned char mvalid; /* Flag: Memory is valid */ - unsigned char ivalid; /* Flag: IRQ is valid */ - unsigned char master; /* Flag: Card ist Quadro 1/4 */ - void* generic; /* Ptr to generic card struct */ -} eicon_isa_card; - -/* Offsets for special locations on standard cards */ -#define INTACK 0x03fe -#define STOPCPU 0x0400 -#define STARTCPU 0x0401 -#define RAMSIZE 0x0400 -/* Offsets for special location on PRI card */ -#define INTACK_P 0x3ffc -#define STOPCPU_P 0x3ffe -#define STARTCPU_P 0x3fff -#define RAMSIZE_P 0x4000 - - -extern int eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb); -extern int eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb); -extern void eicon_isa_release(eicon_isa_card *card); -extern void eicon_isa_printpar(eicon_isa_card *card); -extern void eicon_isa_transmit(eicon_isa_card *card); -extern int eicon_isa_find_card(int Mem, int Irq, char * Id); - -#endif /* __KERNEL__ */ - -#endif /* eicon_isa_h */ diff --git a/drivers/isdn/eicon/eicon_mod.c b/drivers/isdn/eicon/eicon_mod.c deleted file mode 100644 index 8e7529ae..00000000 --- a/drivers/isdn/eicon/eicon_mod.c +++ /dev/null @@ -1,1808 +0,0 @@ -/* $Id$ - * - * ISDN lowlevel-module for Eicon active cards. - * - * Copyright 1997 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * Thanks to Eicon Technology GmbH & Co. oHG for - * documents, informations and hardware. - * - * Deutsche Telekom AG for S2M support. - * - * Deutsche Mailbox Saar-Lor-Lux GmbH - * for sponsoring and testing fax - * capabilities with Diva Server cards. - * (dor@deutschemailbox.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. - * - * $Log$ - * Revision 1.24 2000/01/23 21:21:23 armin - * Added new trace capability and some updates. - * DIVA Server BRI now supports data for ISDNLOG. - * - * Revision 1.23 2000/01/20 19:55:34 keil - * Add FAX Class 1 support - * - * Revision 1.22 1999/11/27 12:56:19 armin - * Forgot some iomem changes for last ioremap compat. - * - * Revision 1.21 1999/11/25 11:35:10 armin - * Microchannel fix from Erik Weber (exrz73@ibm.net). - * Minor cleanup. - * - * Revision 1.20 1999/11/18 21:14:30 armin - * New ISA memory mapped IO - * - * Revision 1.19 1999/11/12 13:21:44 armin - * Bugfix of undefined reference with CONFIG_MCA - * - * Revision 1.18 1999/10/11 18:13:25 armin - * Added fax capabilities for Eicon Diva Server cards. - * - * Revision 1.17 1999/10/08 22:09:34 armin - * Some fixes of cards interface handling. - * Bugfix of NULL pointer occurence. - * Changed a few log outputs. - * - * Revision 1.16 1999/09/26 14:17:53 armin - * Improved debug and log via readstat() - * - * Revision 1.15 1999/09/08 20:17:31 armin - * Added microchannel patch from Erik Weber (exrz73@ibm.net). - * - * Revision 1.14 1999/09/06 07:29:35 fritz - * Changed my mail-address. - * - * Revision 1.13 1999/09/04 17:37:59 armin - * Removed not used define, did not work and caused error - * in 2.3.16 - * - * Revision 1.12 1999/08/31 11:20:14 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.11 1999/08/29 17:23:45 armin - * New setup compat. - * Bugfix if compile as not module. - * - * Revision 1.10 1999/08/28 21:32:53 armin - * Prepared for fax related functions. - * Now compilable without errors/warnings. - * - * Revision 1.9 1999/08/18 20:17:02 armin - * Added XLOG function for all cards. - * Bugfix of alloc_skb NULL pointer. - * - * Revision 1.8 1999/07/25 15:12:08 armin - * fix of some debug logs. - * enabled ISA-cards option. - * - * Revision 1.7 1999/07/11 17:16:27 armin - * Bugfixes in queue handling. - * Added DSP-DTMF decoder functions. - * Reorganized ack_handler. - * - * Revision 1.6 1999/06/09 19:31:26 armin - * Wrong PLX size for request_region() corrected. - * Added first MCA code from Erik Weber. - * - * Revision 1.5 1999/04/01 12:48:35 armin - * Changed some log outputs. - * - * Revision 1.4 1999/03/29 11:19:47 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.3 1999/03/02 12:37:47 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.2 1999/01/24 20:14:21 armin - * Changed and added debug stuff. - * Better data sending. (still problems with tty's flip buffer) - * - * Revision 1.1 1999/01/01 18:09:44 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - -#define DRIVERPATCH "" - -#include -#include -#include -#ifdef CONFIG_MCA -#include -#endif /* CONFIG_MCA */ - -#include "eicon.h" - -#define INCLUDE_INLINE_FUNCS - -static eicon_card *cards = (eicon_card *) NULL; /* glob. var , contains - start of card-list */ - -static char *eicon_revision = "$Revision$"; - -extern char *eicon_pci_revision; -extern char *eicon_isa_revision; -extern char *eicon_idi_revision; - -#ifdef MODULE -#define MOD_USE_COUNT (GET_USE_COUNT (&__this_module)) -#endif - -#define EICON_CTRL_VERSION 2 - -ulong DebugVar; - -/* Parameters to be set by insmod */ -#ifdef CONFIG_ISDN_DRV_EICON_ISA -static int membase = -1; -static int irq = -1; -#endif -static char *id = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - -MODULE_DESCRIPTION( "Driver for Eicon active ISDN cards"); -MODULE_AUTHOR( "Armin Schindler"); -MODULE_SUPPORTED_DEVICE( "ISDN subsystem"); -MODULE_PARM_DESC(id, "ID-String of first card"); -MODULE_PARM(id, "s"); -#ifdef CONFIG_ISDN_DRV_EICON_ISA -MODULE_PARM_DESC(membase, "Base address of first ISA card"); -MODULE_PARM_DESC(irq, "IRQ of first card"); -MODULE_PARM(membase, "i"); -MODULE_PARM(irq, "i"); -#endif - -char *eicon_ctype_name[] = { - "ISDN-S", - "ISDN-SX", - "ISDN-SCOM", - "ISDN-QUADRO", - "ISDN-S2M", - "DIVA Server BRI/PCI", - "DIVA Server 4BRI/PCI", - "DIVA Server 4BRI/PCI", - "DIVA Server PRI/PCI" -}; - -static int -getrel(char *p) -{ - int v = 0; - char *tmp = 0; - - if ((tmp = strchr(p, '.'))) - p = tmp + 1; - while (p[0] >= '0' && p[0] <= '9') { - v = ((v < 0) ? 0 : (v * 10)) + (int) (p[0] - '0'); - p++; - } - return v; - - -} - -static char * -eicon_getrev(const char *revision) -{ - char *rev; - char *p; - if ((p = strchr(revision, ':'))) { - rev = p + 2; - p = strchr(rev, '$'); - *--p = 0; - } else rev = "?.??"; - return rev; - -} - -static eicon_chan * -find_channel(eicon_card *card, int channel) -{ - if ((channel >= 0) && (channel < card->nchannels)) - return &(card->bch[channel]); - eicon_log(card, 1, "eicon: Invalid channel %d\n", channel); - return NULL; -} - -/* - * Free MSN list - */ -static void -eicon_clear_msn(eicon_card *card) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q; - unsigned long flags; - - save_flags(flags); - cli(); - card->msn_list = NULL; - restore_flags(flags); - while (p) { - q = p->next; - kfree(p); - p = q; - } -} - -/* - * Find an MSN entry in the list. - * If ia5 != 0, return IA5-encoded EAZ, else - * return a bitmask with corresponding bit set. - */ -static __u16 -eicon_find_msn(eicon_card *card, char *msn, int ia5) -{ - struct msn_entry *p = card->msn_list; - __u8 eaz = '0'; - - while (p) { - if (!strcmp(p->msn, msn)) { - eaz = p->eaz; - break; - } - p = p->next; - } - if (!ia5) - return (1 << (eaz - '0')); - else - return eaz; -} - -/* - * Find an EAZ entry in the list. - * return a string with corresponding msn. - */ -char * -eicon_find_eaz(eicon_card *card, char eaz) -{ - struct msn_entry *p = card->msn_list; - - while (p) { - if (p->eaz == eaz) - return(p->msn); - p = p->next; - } - return("\0"); -} - -#if 0 -/* - * Add or delete an MSN to the MSN list - * - * First character of msneaz is EAZ, rest is MSN. - * If length of eazmsn is 1, delete that entry. - */ -static int -eicon_set_msn(eicon_card *card, char *eazmsn) -{ - struct msn_entry *p = card->msn_list; - struct msn_entry *q = NULL; - unsigned long flags; - int i; - - if (!strlen(eazmsn)) - return 0; - if (strlen(eazmsn) > 16) - return -EINVAL; - for (i = 0; i < strlen(eazmsn); i++) - if (!isdigit(eazmsn[i])) - return -EINVAL; - if (strlen(eazmsn) == 1) { - /* Delete a single MSN */ - while (p) { - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - if (q) - q->next = p->next; - else - card->msn_list = p->next; - restore_flags(flags); - kfree(p); - eicon_log(card, 8, - "Mapping for EAZ %c deleted\n", - eazmsn[0]); - return 0; - } - q = p; - p = p->next; - } - return 0; - } - /* Add a single MSN */ - while (p) { - /* Found in list, replace MSN */ - if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); - strcpy(p->msn, &eazmsn[1]); - restore_flags(flags); - eicon_log(card, 8, - "Mapping for EAZ %c changed to %s\n", - eazmsn[0], - &eazmsn[1]); - return 0; - } - p = p->next; - } - /* Not found in list, add new entry */ - p = kmalloc(sizeof(msn_entry), GFP_KERNEL); - if (!p) - return -ENOMEM; - p->eaz = eazmsn[0]; - strcpy(p->msn, &eazmsn[1]); - p->next = card->msn_list; - save_flags(flags); - cli(); - card->msn_list = p; - restore_flags(flags); - eicon_log(card, 8, - "Mapping %c -> %s added\n", - eazmsn[0], - &eazmsn[1]); - return 0; -} -#endif - -static void -eicon_rcv_dispatch(struct eicon_card *card) -{ - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - case EICON_BUS_PCI: - eicon_io_rcv_dispatch(card); - break; - default: - eicon_log(card, 1, - "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); - } -} - -static void -eicon_ack_dispatch(struct eicon_card *card) -{ - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - case EICON_BUS_PCI: - eicon_io_ack_dispatch(card); - break; - default: - eicon_log(card, 1, - "eicon_ack_dispatch: Illegal bustype %d\n", card->bus); - } -} - -static void -eicon_transmit(struct eicon_card *card) -{ - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - case EICON_BUS_PCI: - eicon_io_transmit(card); - break; - default: - eicon_log(card, 1, - "eicon_transmit: Illegal bustype %d\n", card->bus); - } -} - -static int eicon_xlog(eicon_card *card, xlogreq_t *xlogreq) -{ - xlogreq_t *xlr; - int ret_val; - - if (!(xlr = kmalloc(sizeof(xlogreq_t), GFP_KERNEL))) { - eicon_log(card, 1, "idi_err: alloc_xlogreq_t failed\n"); - return -ENOMEM; - } - if (copy_from_user(xlr, xlogreq, sizeof(xlogreq_t))) { - kfree(xlr); - return -EFAULT; - } - - ret_val = eicon_get_xlog(card, xlr); - - if (copy_to_user(xlogreq, xlr, sizeof(xlogreq_t))) { - kfree(xlr); - return -EFAULT; - } - kfree(xlr); - - return ret_val; -} - -static int -eicon_command(eicon_card * card, isdn_ctrl * c) -{ - ulong a; - eicon_chan *chan; - eicon_cdef cdef; - isdn_ctrl cmd; - char tmp[17]; - int ret = 0; - unsigned long flags; - - eicon_log(card, 16, "eicon_cmd 0x%x with arg 0x%lx (0x%lx)\n", - c->command, c->arg, (ulong) *c->parm.num); - - switch (c->command) { - case ISDN_CMD_IOCTL: - memcpy(&a, c->parm.num, sizeof(ulong)); - switch (c->arg) { - case EICON_IOCTL_GETVER: - return(EICON_CTRL_VERSION); - case EICON_IOCTL_GETTYPE: - return(card->type); - case EICON_IOCTL_GETMMIO: - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - return (int)card->hwif.isa.shmem; -#if CONFIG_PCI - case EICON_BUS_PCI: - return card->hwif.pci.PCIram; -#endif - default: - eicon_log(card, 1, - "eicon: Illegal BUS type %d\n", - card->bus); - ret = -ENODEV; - } -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_IOCTL_SETMMIO: - if (card->flags & EICON_FLAGS_LOADED) - return -EBUSY; - switch (card->bus) { - case EICON_BUS_ISA: - if (eicon_isa_find_card(a, - card->hwif.isa.irq, - card->regname) < 0) - return -EFAULT; - card->hwif.isa.shmem = (eicon_isa_shmem *)a; - return 0; - case EICON_BUS_MCA: -#if CONFIG_MCA - if (eicon_mca_find_card( - 0, a, - card->hwif.isa.irq, - card->regname) < 0) - return -EFAULT; - card->hwif.isa.shmem = (eicon_isa_shmem *)a; - return 0; -#endif /* CONFIG_MCA */ - default: - eicon_log(card, 1, - "eicon: Illegal BUS type %d\n", - card->bus); - ret = -ENODEV; - } -#endif - case EICON_IOCTL_GETIRQ: - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - return card->hwif.isa.irq; -#if CONFIG_PCI - case EICON_BUS_PCI: - return card->hwif.pci.irq; -#endif - default: - eicon_log(card, 1, - "eicon: Illegal BUS type %d\n", - card->bus); - ret = -ENODEV; - } - case EICON_IOCTL_SETIRQ: - if (card->flags & EICON_FLAGS_LOADED) - return -EBUSY; - if ((a < 2) || (a > 15)) - return -EFAULT; - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - card->hwif.isa.irq = a; - return 0; - default: - eicon_log(card, 1, - "eicon: Illegal BUS type %d\n", - card->bus); - ret = -ENODEV; - } -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_IOCTL_LOADBOOT: - if (card->flags & EICON_FLAGS_RUNNING) - return -EBUSY; - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - ret = eicon_isa_bootload( - &(card->hwif.isa), - &(((eicon_codebuf *)a)->isa)); - break; - default: - eicon_log(card, 1, - "eicon: Illegal BUS type %d\n", - card->bus); - ret = -ENODEV; - } - return ret; -#endif -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_IOCTL_LOADISA: - if (card->flags & EICON_FLAGS_RUNNING) - return -EBUSY; - switch (card->bus) { - case EICON_BUS_ISA: - case EICON_BUS_MCA: - ret = eicon_isa_load( - &(card->hwif.isa), - &(((eicon_codebuf *)a)->isa)); - if (!ret) { - card->flags |= EICON_FLAGS_LOADED; - card->flags |= EICON_FLAGS_RUNNING; - if (card->hwif.isa.channels > 1) { - cmd.command = ISDN_STAT_ADDCH; - cmd.driver = card->myid; - cmd.arg = card->hwif.isa.channels - 1; - card->interface.statcallb(&cmd); - } - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - break; - default: - eicon_log(card, 1, - "eicon: Illegal BUS type %d\n", - card->bus); - ret = -ENODEV; - } - return ret; -#endif - case EICON_IOCTL_MANIF: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!card->Feature & PROTCAP_MANIF) - return -ENODEV; - ret = eicon_idi_manage( - card, - (eicon_manifbuf *)a); - return ret; - - case EICON_IOCTL_GETXLOG: - if (!card->flags & EICON_FLAGS_RUNNING) - return XLOG_ERR_CARD_STATE; - ret = eicon_xlog(card, (xlogreq_t *)a); - return ret; -#if CONFIG_PCI - case EICON_IOCTL_LOADPCI: - if (card->flags & EICON_FLAGS_RUNNING) - return -EBUSY; - if (card->bus == EICON_BUS_PCI) { - switch(card->type) { - case EICON_CTYPE_MAESTRA: - ret = eicon_pci_load_bri( - &(card->hwif.pci), - &(((eicon_codebuf *)a)->pci)); - break; - - case EICON_CTYPE_MAESTRAP: - ret = eicon_pci_load_pri( - &(card->hwif.pci), - &(((eicon_codebuf *)a)->pci)); - break; - } - if (!ret) { - card->flags |= EICON_FLAGS_LOADED; - card->flags |= EICON_FLAGS_RUNNING; - if (card->hwif.pci.channels > 1) { - cmd.command = ISDN_STAT_ADDCH; - cmd.driver = card->myid; - cmd.arg = card->hwif.pci.channels - 1; - card->interface.statcallb(&cmd); - } - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - return ret; - } else return -ENODEV; -#endif -#if 0 - case EICON_IOCTL_SETMSN: - if ((ret = copy_from_user(tmp, (char *)a, sizeof(tmp)))) - return -EFAULT; - if ((ret = eicon_set_msn(card, tmp))) - return ret; -#if 0 - if (card->flags & EICON_FLAGS_RUNNING) - return(eicon_capi_manufacturer_req_msn(card)); -#endif - return 0; -#endif - case EICON_IOCTL_ADDCARD: - if ((ret = copy_from_user(&cdef, (char *)a, sizeof(cdef)))) - return -EFAULT; - if (!(eicon_addcard(0, cdef.membase, cdef.irq, cdef.id))) - return -EIO; - return 0; - case EICON_IOCTL_DEBUGVAR: - DebugVar = a; - eicon_log(card, 1, "Eicon: Debug Value set to %ld\n", DebugVar); - return 0; -#ifdef MODULE - case EICON_IOCTL_FREEIT: - while (MOD_USE_COUNT > 0) MOD_DEC_USE_COUNT; - MOD_INC_USE_COUNT; - return 0; -#endif - default: - return -EINVAL; - } - break; - case ISDN_CMD_DIAL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - save_flags(flags); - cli(); - if ((chan->fsm_state != EICON_STATE_NULL) && (chan->fsm_state != EICON_STATE_LISTEN)) { - restore_flags(flags); - eicon_log(card, 1, "Dial on channel %d with state %d\n", - chan->No, chan->fsm_state); - return -EBUSY; - } - if (card->ptype == ISDN_PTYPE_EURO) - tmp[0] = eicon_find_msn(card, c->parm.setup.eazmsn, 1); - else - tmp[0] = c->parm.setup.eazmsn[0]; - chan->fsm_state = EICON_STATE_OCALL; - restore_flags(flags); - - ret = idi_connect_req(card, chan, c->parm.setup.phone, - c->parm.setup.eazmsn, - c->parm.setup.si1, - c->parm.setup.si2); - if (ret) { - cmd.driver = card->myid; - cmd.command = ISDN_STAT_DHUP; - cmd.arg &= 0x1f; - card->interface.statcallb(&cmd); - } - return ret; - case ISDN_CMD_ACCEPTD: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - if (chan->fsm_state == EICON_STATE_ICALL) { - idi_connect_res(card, chan); - } - return 0; - case ISDN_CMD_ACCEPTB: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - return 0; - case ISDN_CMD_HANGUP: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - idi_hangup(card, chan); - return 0; - case ISDN_CMD_SETEAZ: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - if (strlen(c->parm.num)) { - if (card->ptype == ISDN_PTYPE_EURO) { - chan->eazmask = eicon_find_msn(card, c->parm.num, 0); - } - if (card->ptype == ISDN_PTYPE_1TR6) { - int i; - chan->eazmask = 0; - for (i = 0; i < strlen(c->parm.num); i++) - if (isdigit(c->parm.num[i])) - chan->eazmask |= (1 << (c->parm.num[i] - '0')); - } - } else - chan->eazmask = 0x3ff; - eicon_idi_listen_req(card, chan); - return 0; - case ISDN_CMD_CLREAZ: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - chan->eazmask = 0; - eicon_idi_listen_req(card, chan); - return 0; - case ISDN_CMD_SETL2: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - chan->l2prot = (c->arg >> 8); - return 0; - case ISDN_CMD_GETL2: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - return chan->l2prot; - case ISDN_CMD_SETL3: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - chan->l3prot = (c->arg >> 8); -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l3prot == ISDN_PROTO_L3_FCLASS2) - chan->fax = c->parm.fax; -#endif - return 0; - case ISDN_CMD_GETL3: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - return chan->l3prot; - case ISDN_CMD_GETEAZ: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "eicon CMD_GETEAZ not implemented\n"); - return 0; - case ISDN_CMD_SETSIL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "eicon CMD_SETSIL not implemented\n"); - return 0; - case ISDN_CMD_GETSIL: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - eicon_log(card, 1, "eicon CMD_GETSIL not implemented\n"); - return 0; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - return 0; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - return 0; -#ifdef CONFIG_ISDN_TTY_FAX - case ISDN_CMD_FAXCMD: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - if (!chan->fax) - break; - idi_fax_cmd(card, chan); - return 0; -#endif - case ISDN_CMD_AUDIO: - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, c->arg & 0x1f))) - break; - idi_audio_cmd(card, chan, c->arg >> 8, c->parm.num); - return 0; - } - - return -EINVAL; -} - -/* - * Find card with given driverId - */ -static inline eicon_card * -eicon_findcard(int driverid) -{ - eicon_card *p = cards; - - while (p) { - if (p->myid == driverid) - return p; - p = p->next; - } - return (eicon_card *) 0; -} - -/* - * Wrapper functions for interface to linklevel - */ -static int -if_command(isdn_ctrl * c) -{ - eicon_card *card = eicon_findcard(c->driver); - - if (card) - return (eicon_command(card, c)); - printk(KERN_ERR - "eicon: if_command %d called with invalid driverId %d!\n", - c->command, c->driver); - return -ENODEV; -} - -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); -} - -static int -if_readstatus(u_char * buf, int len, int user, int id, int channel) -{ - int count = 0; - int cnt = 0; - ulong flags = 0; - u_char *p = buf; - struct sk_buff *skb; - - eicon_card *card = eicon_findcard(id); - - if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - - save_flags(flags); - cli(); - while((skb = skb_dequeue(&card->statq))) { - - if ((skb->len + count) > len) - cnt = len - count; - else - cnt = skb->len; - - if (user) - copy_to_user(p, skb->data, cnt); - else - memcpy(p, skb->data, cnt); - - count += cnt; - p += cnt; - - if (cnt == skb->len) { - dev_kfree_skb(skb); - if (card->statq_entries > 0) - card->statq_entries--; - } else { - skb_pull(skb, cnt); - skb_queue_head(&card->statq, skb); - restore_flags(flags); - return count; - } - } - card->statq_entries = 0; - restore_flags(flags); - return count; - } - printk(KERN_ERR - "eicon: if_readstatus called with invalid driverId!\n"); - return 0; -} - -static int -if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) -{ - eicon_card *card = eicon_findcard(id); - eicon_chan *chan; - int ret = 0; - int len; - - len = skb->len; - - if (card) { - if (!card->flags & EICON_FLAGS_RUNNING) - return -ENODEV; - if (!(chan = find_channel(card, channel))) - return -ENODEV; - - if (chan->fsm_state == EICON_STATE_ACTIVE) { -#ifdef CONFIG_ISDN_TTY_FAX - if (chan->l2prot == ISDN_PROTO_L2_FAX) { - if ((ret = idi_faxdata_send(card, chan, skb)) > 0) - ret = len; - } - else -#endif - ret = idi_send_data(card, chan, ack, skb, 1); - return (ret); - } else { - return -ENODEV; - } - } - printk(KERN_ERR - "eicon: if_sendbuf called with invalid driverId!\n"); - return -ENODEV; -} - -/* jiftime() copied from HiSax */ -static inline int jiftime(char *s, long mark) -{ - s += 8; - - *s-- = '\0'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = '.'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 6 + '0'; - mark /= 6; - *s-- = ':'; - *s-- = mark % 10 + '0'; - mark /= 10; - *s-- = mark % 10 + '0'; - return(8); -} - -void -eicon_putstatus(eicon_card * card, char * buf) -{ - ulong flags; - int count; - isdn_ctrl cmd; - u_char *p; - struct sk_buff *skb; - - if (!card) { - if (!(card = cards)) - return; - } - - save_flags(flags); - cli(); - count = strlen(buf); - skb = alloc_skb(count, GFP_ATOMIC); - if (!skb) { - restore_flags(flags); - printk(KERN_ERR "eicon: could not alloc skb in putstatus\n"); - return; - } - p = skb_put(skb, count); - memcpy(p, buf, count); - - skb_queue_tail(&card->statq, skb); - - if (card->statq_entries >= MAX_STATUS_BUFFER) { - if ((skb = skb_dequeue(&card->statq))) { - count -= skb->len; - dev_kfree_skb(skb); - } else - count = 0; - } else - card->statq_entries++; - - restore_flags(flags); - if (count) { - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = count; - card->interface.statcallb(&cmd); - } -} - -/* - * Debug and Log - */ -void -eicon_log(eicon_card * card, int level, const char *fmt, ...) -{ - va_list args; - char Line[160]; - u_char *p; - - - if ((DebugVar & level) || (DebugVar & 256)) { - va_start(args, fmt); - - if (DebugVar & level) { - if (DebugVar & 256) { - /* log-buffer */ - p = Line; - p += jiftime(p, jiffies); - *p++ = 32; - p += vsprintf(p, fmt, args); - *p = 0; - eicon_putstatus(card, Line); - } else { - /* printk, syslogd */ - vsprintf(Line, fmt, args); - printk(KERN_DEBUG "%s", Line); - } - } - - va_end(args); - } -} - - -/* - * Allocate a new card-struct, initialize it - * link it into cards-list. - */ -static void -eicon_alloccard(int Type, int membase, int irq, char *id) -{ - int i; - int j; - int qloop; -#ifdef CONFIG_ISDN_DRV_EICON_ISA - char qid[5]; -#endif - eicon_card *card; -#if CONFIG_PCI - eicon_pci_card *pcic; -#endif - - qloop = (Type == EICON_CTYPE_QUADRO)?2:0; - for (i = 0; i <= qloop; i++) { - if (!(card = (eicon_card *) kmalloc(sizeof(eicon_card), GFP_KERNEL))) { - eicon_log(card, 1, - "eicon: (%s) Could not allocate card-struct.\n", id); - return; - } - memset((char *) card, 0, sizeof(eicon_card)); - skb_queue_head_init(&card->sndq); - skb_queue_head_init(&card->rcvq); - skb_queue_head_init(&card->rackq); - skb_queue_head_init(&card->sackq); - skb_queue_head_init(&card->statq); - card->statq_entries = 0; - card->snd_tq.routine = (void *) (void *) eicon_transmit; - card->snd_tq.data = card; - card->rcv_tq.routine = (void *) (void *) eicon_rcv_dispatch; - card->rcv_tq.data = card; - card->ack_tq.routine = (void *) (void *) eicon_ack_dispatch; - card->ack_tq.data = card; - card->interface.maxbufsize = 4000; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = if_writecmd; - card->interface.readstat = if_readstatus; - card->interface.features = - ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L2_TRANS | - ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_P_UNKNOWN; - card->interface.hl_hdrlen = 20; - card->ptype = ISDN_PTYPE_UNKNOWN; - strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); - card->myid = -1; - card->type = Type; - switch (Type) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA -#if CONFIG_MCA /* only needed for MCA */ - case EICON_CTYPE_S: - case EICON_CTYPE_SX: - case EICON_CTYPE_SCOM: - if (MCA_bus) { - if (membase == -1) - membase = EICON_ISA_MEMBASE; - if (irq == -1) - irq = EICON_ISA_IRQ; - card->bus = EICON_BUS_MCA; - card->hwif.isa.card = (void *)card; - card->hwif.isa.shmem = (eicon_isa_shmem *)membase; - card->hwif.isa.physmem = (unsigned long)membase; - card->hwif.isa.master = 1; - - card->hwif.isa.irq = irq; - card->hwif.isa.type = Type; - card->nchannels = 2; - card->interface.channels = 1; - } else { - printk(KERN_WARNING - "eicon (%s): no MCA bus detected.\n", - card->interface.id); - kfree(card); - return; - } - break; -#endif /* CONFIG_MCA */ - case EICON_CTYPE_QUADRO: - if (membase == -1) - membase = EICON_ISA_MEMBASE; - if (irq == -1) - irq = EICON_ISA_IRQ; - card->bus = EICON_BUS_ISA; - card->hwif.isa.card = (void *)card; - card->hwif.isa.shmem = (eicon_isa_shmem *)(membase + (i+1) * EICON_ISA_QOFFSET); - card->hwif.isa.physmem = (unsigned long)(membase + (i+1) * EICON_ISA_QOFFSET); - card->hwif.isa.master = 0; - strcpy(card->interface.id, id); - if (id[strlen(id) - 1] == 'a') { - card->interface.id[strlen(id) - 1] = 'a' + i + 1; - } else { - sprintf(qid, "_%c",'2' + i); - strcat(card->interface.id, qid); - } - printk(KERN_INFO "Eicon: Quadro: Driver-Id %s added.\n", - card->interface.id); - if (i == 0) { - eicon_card *p = cards; - while(p) { - if ((p->hwif.isa.master) && (p->hwif.isa.irq == irq)) { - p->qnext = card; - break; - } - p = p->next; - } - if (!p) { - eicon_log(card, 1, "eicon_alloccard: Quadro Master not found.\n"); - kfree(card); - return; - } - } else { - cards->qnext = card; - } - card->hwif.isa.irq = irq; - card->hwif.isa.type = Type; - card->nchannels = 2; - card->interface.channels = 1; - break; -#endif -#if CONFIG_PCI - case EICON_CTYPE_MAESTRA: - (eicon_pci_card *)pcic = (eicon_pci_card *)membase; - card->bus = EICON_BUS_PCI; - card->interface.features |= - ISDN_FEATURE_L2_V11096 | - ISDN_FEATURE_L2_V11019 | - ISDN_FEATURE_L2_V11038 | - ISDN_FEATURE_L2_MODEM | - ISDN_FEATURE_L2_FAX | - ISDN_FEATURE_L3_TRANSDSP | - ISDN_FEATURE_L3_FCLASS2; - card->hwif.pci.card = (void *)card; - card->hwif.pci.PCIreg = pcic->PCIreg; - card->hwif.pci.PCIcfg = pcic->PCIcfg; - card->hwif.pci.master = 1; - card->hwif.pci.mvalid = pcic->mvalid; - card->hwif.pci.ivalid = 0; - card->hwif.pci.irq = irq; - card->hwif.pci.type = Type; - card->flags = 0; - card->nchannels = 2; - card->interface.channels = 1; - break; - - case EICON_CTYPE_MAESTRAP: - (eicon_pci_card *)pcic = (eicon_pci_card *)membase; - card->bus = EICON_BUS_PCI; - card->interface.features |= - ISDN_FEATURE_L2_V11096 | - ISDN_FEATURE_L2_V11019 | - ISDN_FEATURE_L2_V11038 | - ISDN_FEATURE_L2_MODEM | - ISDN_FEATURE_L2_FAX | - ISDN_FEATURE_L3_TRANSDSP | - ISDN_FEATURE_L3_FCLASS2; - card->hwif.pci.card = (void *)card; - card->hwif.pci.shmem = (eicon_pci_shmem *)pcic->shmem; - card->hwif.pci.PCIreg = pcic->PCIreg; - card->hwif.pci.PCIram = pcic->PCIram; - card->hwif.pci.PCIcfg = pcic->PCIcfg; - card->hwif.pci.master = 1; - card->hwif.pci.mvalid = pcic->mvalid; - card->hwif.pci.ivalid = 0; - card->hwif.pci.irq = irq; - card->hwif.pci.type = Type; - card->flags = 0; - card->nchannels = 30; - card->interface.channels = 1; - break; -#endif -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_CTYPE_ISABRI: - if (membase == -1) - membase = EICON_ISA_MEMBASE; - if (irq == -1) - irq = EICON_ISA_IRQ; - card->bus = EICON_BUS_ISA; - card->hwif.isa.card = (void *)card; - card->hwif.isa.shmem = (eicon_isa_shmem *)membase; - card->hwif.isa.physmem = (unsigned long)membase; - card->hwif.isa.master = 1; - card->hwif.isa.irq = irq; - card->hwif.isa.type = Type; - card->nchannels = 2; - card->interface.channels = 1; - break; - case EICON_CTYPE_ISAPRI: - if (membase == -1) - membase = EICON_ISA_MEMBASE; - if (irq == -1) - irq = EICON_ISA_IRQ; - card->bus = EICON_BUS_ISA; - card->hwif.isa.card = (void *)card; - card->hwif.isa.shmem = (eicon_isa_shmem *)membase; - card->hwif.isa.physmem = (unsigned long)membase; - card->hwif.isa.master = 1; - card->hwif.isa.irq = irq; - card->hwif.isa.type = Type; - card->nchannels = 30; - card->interface.channels = 1; - break; -#endif - default: - eicon_log(card, 1, "eicon_alloccard: Invalid type %d\n", Type); - kfree(card); - return; - } - if (!(card->bch = (eicon_chan *) kmalloc(sizeof(eicon_chan) * (card->nchannels + 1) - , GFP_KERNEL))) { - eicon_log(card, 1, - "eicon: (%s) Could not allocate bch-struct.\n", id); - kfree(card); - return; - } - for (j=0; j< (card->nchannels + 1); j++) { - memset((char *)&card->bch[j], 0, sizeof(eicon_chan)); - card->bch[j].statectrl = 0; - card->bch[j].l2prot = ISDN_PROTO_L2_X75I; - card->bch[j].l3prot = ISDN_PROTO_L3_TRANS; - card->bch[j].e.D3Id = 0; - card->bch[j].e.B2Id = 0; - card->bch[j].e.Req = 0; - card->bch[j].No = j; - card->bch[j].tskb1 = NULL; - card->bch[j].tskb2 = NULL; - skb_queue_head_init(&card->bch[j].e.X); - skb_queue_head_init(&card->bch[j].e.R); - } - card->next = cards; - cards = card; - } -} - -/* - * register card at linklevel - */ -static int -eicon_registercard(eicon_card * card) -{ - switch (card->bus) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_BUS_ISA: - /* TODO something to print */ - break; -#ifdef CONFIG_MCA - case EICON_BUS_MCA: - eicon_isa_printpar(&card->hwif.isa); - break; -#endif /* CONFIG_MCA */ -#endif - case EICON_BUS_PCI: -#if CONFIG_PCI - eicon_pci_printpar(&card->hwif.pci); - break; -#endif - default: - eicon_log(card, 1, - "eicon_registercard: Illegal BUS type %d\n", - card->bus); - return -1; - } - if (!register_isdn(&card->interface)) { - printk(KERN_WARNING - "eicon_registercard: Unable to register %s\n", - card->interface.id); - return -1; - } - card->myid = card->interface.channels; - sprintf(card->regname, "%s", card->interface.id); - return 0; -} - -#ifdef MODULE -static void -unregister_card(eicon_card * card) -{ - isdn_ctrl cmd; - - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - switch (card->bus) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_BUS_ISA: -#ifdef CONFIG_MCA - case EICON_BUS_MCA: -#endif /* CONFIG_MCA */ - eicon_isa_release(&card->hwif.isa); - break; -#endif - case EICON_BUS_PCI: -#if CONFIG_PCI - eicon_pci_release(&card->hwif.pci); - break; -#endif - default: - eicon_log(card, 1, - "eicon: Invalid BUS type %d\n", - card->bus); - break; - } -} -#endif /* MODULE */ - -static void -eicon_freecard(eicon_card *card) { - int i; - struct sk_buff *skb; - - for(i = 0; i < (card->nchannels + 1); i++) { - while((skb = skb_dequeue(&card->bch[i].e.X))) - dev_kfree_skb(skb); - while((skb = skb_dequeue(&card->bch[i].e.R))) - dev_kfree_skb(skb); - } - while((skb = skb_dequeue(&card->sndq))) - dev_kfree_skb(skb); - while((skb = skb_dequeue(&card->rcvq))) - dev_kfree_skb(skb); - while((skb = skb_dequeue(&card->rackq))) - dev_kfree_skb(skb); - while((skb = skb_dequeue(&card->sackq))) - dev_kfree_skb(skb); - while((skb = skb_dequeue(&card->statq))) - dev_kfree_skb(skb); - - eicon_clear_msn(card); - kfree(card->bch); - kfree(card); -} - -int -eicon_addcard(int Type, int membase, int irq, char *id) -{ - eicon_card *p; - eicon_card *q = NULL; - int registered; - int added = 0; - int failed = 0; - -#ifdef CONFIG_ISDN_DRV_EICON_ISA - if (!Type) /* ISA */ - if ((Type = eicon_isa_find_card(membase, irq, id)) < 0) - return 0; -#endif - eicon_alloccard(Type, membase, irq, id); - p = cards; - while (p) { - registered = 0; - if (!p->interface.statcallb) { - /* Not yet registered. - * Try to register and activate it. - */ - added++; - switch (p->bus) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA - case EICON_BUS_ISA: - case EICON_BUS_MCA: - if (eicon_registercard(p)) - break; - registered = 1; - break; -#endif - case EICON_BUS_PCI: -#if CONFIG_PCI - if (eicon_registercard(p)) - break; - registered = 1; - break; -#endif - default: - printk(KERN_ERR - "eicon: addcard: Invalid BUS type %d\n", - p->bus); - } - } else - /* Card already registered */ - registered = 1; - if (registered) { - /* Init OK, next card ... */ - q = p; - p = p->next; - } else { - /* registering failed, remove card from list, free memory */ - printk(KERN_ERR - "eicon: Initialization of %s failed\n", - p->interface.id); - if (q) { - q->next = p->next; - eicon_freecard(p); - p = q->next; - } else { - cards = p->next; - eicon_freecard(p); - p = cards; - } - failed++; - } - } - return (added - failed); -} - -#define DRIVERNAME "Eicon active ISDN driver" -#define DRIVERRELEASE "1" - -#ifdef MODULE -#define eicon_init init_module -#endif - -int -eicon_init(void) -{ - int card_count = 0; - int release = 0; - char tmprev[50]; - - DebugVar = 1; - - printk(KERN_INFO "%s Rev: ", DRIVERNAME); - strcpy(tmprev, eicon_revision); - printk("%s/", eicon_getrev(tmprev)); - release += getrel(tmprev); - strcpy(tmprev, eicon_pci_revision); -#if CONFIG_PCI - printk("%s/", eicon_getrev(tmprev)); -#else - printk("---/"); -#endif - release += getrel(tmprev); - strcpy(tmprev, eicon_isa_revision); -#ifdef CONFIG_ISDN_DRV_EICON_ISA - printk("%s/", eicon_getrev(tmprev)); -#else - printk("---/"); -#endif - release += getrel(tmprev); - strcpy(tmprev, eicon_idi_revision); - printk("%s\n", eicon_getrev(tmprev)); - release += getrel(tmprev); - sprintf(tmprev,"%d", release); - printk(KERN_INFO "%s Release: %s.%s%s\n", DRIVERNAME, - DRIVERRELEASE, tmprev, DRIVERPATCH); - -#ifdef CONFIG_ISDN_DRV_EICON_ISA -#ifdef CONFIG_MCA - /* Check if we have MCA-bus */ - if (!MCA_bus) - { - printk(KERN_INFO - "eicon: No MCA bus, ISDN-interfaces not probed.\n"); - } else { - eicon_log(NULL, 8, - "eicon_mca_find_card, irq=%d.\n", - irq); - if (!eicon_mca_find_card(0, membase, irq, id)) - card_count++; - }; -#else - card_count = eicon_addcard(0, membase, irq, id); -#endif /* CONFIG_MCA */ -#endif /* CONFIG_ISDN_DRV_EICON_ISA */ - -#if CONFIG_PCI - card_count += eicon_pci_find_card(id); -#endif - if (!cards) { -#ifdef MODULE -#ifndef CONFIG_PCI -#ifndef CONFIG_ISDN_DRV_EICON_ISA - printk(KERN_INFO "Eicon: Driver is neither ISA nor PCI compiled !\n"); -#else - printk(KERN_INFO "Eicon: No cards defined, driver not loaded !\n"); -#endif -#else - printk(KERN_INFO "Eicon: No PCI-cards found, driver not loaded !\n"); -#endif -#endif /* MODULE */ - return -ENODEV; - - } else - printk(KERN_INFO "Eicon: %d card%s added\n", card_count, - (card_count>1)?"s":""); - /* No symbols to export, hide all symbols */ - EXPORT_NO_SYMBOLS; - return 0; -} - -#ifdef MODULE -void -cleanup_module(void) -{ - eicon_card *card = cards; - eicon_card *last; - while (card) { -#ifdef CONFIG_ISDN_DRV_EICON_ISA -#ifdef CONFIG_MCA - if (MCA_bus) - { - mca_mark_as_unused (card->mca_slot); - mca_set_adapter_procfn(card->mca_slot, NULL, NULL); - }; -#endif /* CONFIG_MCA */ -#endif - unregister_card(card); - card = card->next; - } - card = cards; - while (card) { - last = card; - card = card->next; - eicon_freecard(last); - } - printk(KERN_INFO "%s unloaded\n", DRIVERNAME); -} - -#else /* no module */ - -#ifdef COMPAT_HAS_NEW_SETUP -static int __init -eicon_setup(char *line) -{ - int i, argc; - int ints[5]; - 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; -#ifdef CONFIG_ISDN_DRV_EICON_ISA - if (argc) { - membase = irq = -1; - if (argc) { - membase = ints[i]; - i++; - argc--; - } - if (argc) { - irq = ints[i]; - i++; - argc--; - } - if (strlen(str)) { - strcpy(id, str); - } else { - strcpy(id, "eicon"); - } - printk(KERN_INFO "Eicon ISDN active driver setup (id=%s membase=0x%x irq=%d)\n", - id, membase, irq); - } -#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 */ - -#ifdef CONFIG_ISDN_DRV_EICON_ISA -#ifdef CONFIG_MCA - -struct eicon_mca_adapters_struct { - char * name; - int adf_id; -}; -/* possible MCA-brands of eicon cards */ -struct eicon_mca_adapters_struct eicon_mca_adapters[] = { - { "ISDN-P/2 Adapter", 0x6abb }, - { "ISDN-[S|SX|SCOM]/2 Adapter", 0x6a93 }, - { "DIVA /MCA", 0x6336 }, - { NULL, 0 }, -}; - -int eicon_mca_find_card(int type, /* type-idx of eicon-card */ - int membase, - int irq, - char * id) /* name of eicon-isdn-dev */ -{ - int j, curr_slot = 0; - - eicon_log(NULL, 8, - "eicon_mca_find_card type: %d, membase: %#x, irq %d \n", - type, membase, irq); - /* find a no-driver-assigned eicon card */ - for (j=0; eicon_mca_adapters[j].adf_id != 0; j++) - { - for ( curr_slot=0; curr_slot<=MCA_MAX_SLOT_NR; curr_slot++) - { - curr_slot = mca_find_unused_adapter( - eicon_mca_adapters[j].adf_id, curr_slot); - if (curr_slot != MCA_NOTFOUND) - { - /* check if pre-set parameters match - these of the card, check cards memory */ - if (!(int) eicon_mca_probe(curr_slot, - j, - membase, - irq, - id)) - { - return 0; - /* means: adapter parms did match */ - }; - }; - break; - /* MCA_NOTFOUND-branch: no matching adapter of - THIS flavor found, next flavor */ - - }; - }; - /* all adapter flavors checked without match, finito with: */ - return ENODEV; -}; - - -/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - * stolen from 3c523.c/elmc_getinfo, ewe, 10.5.1999 - */ -int eicon_info(char * buf, int slot, void *d) -{ - int len = 0; - struct eicon_card *dev; - - dev = (struct eicon_card *) d; - - if (dev == NULL) - return len; - len += sprintf(buf+len, "eicon ISDN adapter, type %d.\n",dev->type); - len += sprintf(buf+len, "IRQ: %d\n", dev->hwif.isa.irq); - len += sprintf(buf+len, "MEMBASE: %#lx\n", (unsigned long)dev->hwif.isa.shmem); - - return len; -}; - -int eicon_mca_probe(int slot, /* slot-nr where the card was detected */ - int a_idx, /* idx-nr of probed card in eicon_mca_adapters */ - int membase, - int irq, - char * id) /* name of eicon-isdn-dev */ -{ - unsigned char adf_pos0; - int cards_irq, cards_membase, cards_io; - int type = EICON_CTYPE_S; - int irq_array[]={0,3,4,2}; - int irq_array1[]={3,4,0,0,2,10,11,12}; - - adf_pos0 = mca_read_stored_pos(slot,2); - eicon_log(NULL, 8, - "eicon_mca_probe irq=%d, membase=%d\n", - irq, - membase); - switch (a_idx) { - case 0: /* P/2-Adapter (== PRI/S2M ? ) */ - cards_membase= 0xC0000+((adf_pos0>>4)*0x4000); - if (membase == -1) { - membase = cards_membase; - } else { - if (membase != cards_membase) - return ENODEV; - }; - cards_irq=irq_array[((adf_pos0 & 0xC)>>2)]; - if (irq == -1) { - irq = cards_irq; - } else { - if (irq != cards_irq) - return ENODEV; - }; - cards_io= 0xC00 + ((adf_pos0>>4)*0x10); - type = EICON_CTYPE_ISAPRI; - break; - - case 1: /* [S|SX|SCOM]/2 */ - cards_membase= 0xC0000+((adf_pos0>>4)*0x2000); - if (membase == -1) { - membase = cards_membase; - } else { - if (membase != cards_membase) - return ENODEV; - }; - cards_irq=irq_array[((adf_pos0 & 0xC)>>2)]; - if (irq == -1) { - irq = cards_irq; - } else { - if (irq != cards_irq) - return ENODEV; - }; - - cards_io= 0xC00 + ((adf_pos0>>4)*0x10); - type = EICON_CTYPE_SCOM; - break; - - case 2: /* DIVA/MCA */ - cards_io = 0x200+ ((adf_pos0>>4)* 0x20); - cards_irq = irq_array1[(adf_pos0 & 0x7)]; - if (irq == -1) { - irq = cards_irq; - } else { - if (irq != cards_irq) - return ENODEV; - }; - type = 0; - break; - default: - return ENODEV; - }; - /* matching membase & irq */ - if ( 1 == eicon_addcard(type, membase, irq, id)) { - mca_set_adapter_name(slot, eicon_mca_adapters[a_idx].name); - mca_set_adapter_procfn(slot, (MCA_ProcFn) eicon_info, cards); - - mca_mark_as_used(slot); - cards->mca_slot = slot; - /* card->io noch setzen oder ?? */ - cards->mca_io = cards_io; - cards->hwif.isa.io = cards_io; - /* reset card */ - outb_p(0,cards_io+1); - - eicon_log(NULL, 8, "eicon_addcard: successful for slot # %d.\n", - cards->mca_slot+1); - return 0 ; /* eicon_addcard added a card */ - } else { - return ENODEV; - }; -}; -#endif /* CONFIG_MCA */ -#endif /* CONFIG_ISDN_DRV_EICON_ISA */ - diff --git a/drivers/isdn/eicon/eicon_pci.c b/drivers/isdn/eicon/eicon_pci.c deleted file mode 100644 index 4a5a6f47..00000000 --- a/drivers/isdn/eicon/eicon_pci.c +++ /dev/null @@ -1,969 +0,0 @@ -/* $Id$ - * - * ISDN low-level module for Eicon active ISDN-Cards. - * Hardware-specific code for PCI cards. - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * Thanks to Eicon Technology GmbH & Co. oHG for - * documents, informations and hardware. - * - * Deutsche Telekom AG for S2M support. - * - * 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. - * - * $Log$ - * Revision 1.10 1999/08/22 20:26:49 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.9 1999/08/11 21:01:11 keil - * new PCI codefix - * - * Revision 1.8 1999/08/10 16:02:20 calle - * struct pci_dev changed in 2.3.13. Made the necessary changes. - * - * Revision 1.7 1999/06/09 19:31:29 armin - * Wrong PLX size for request_region() corrected. - * Added first MCA code from Erik Weber. - * - * Revision 1.6 1999/04/01 12:48:37 armin - * Changed some log outputs. - * - * Revision 1.5 1999/03/29 11:19:49 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.4 1999/03/02 12:37:48 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.3 1999/01/24 20:14:24 armin - * Changed and added debug stuff. - * Better data sending. (still problems with tty's flip buffer) - * - * Revision 1.2 1999/01/10 18:46:06 armin - * Bug with wrong values in HLC fixed. - * Bytes to send are counted and limited now. - * - * Revision 1.1 1999/01/01 18:09:45 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - -#include -#include - -#include "eicon.h" -#include "eicon_pci.h" - - -char *eicon_pci_revision = "$Revision$"; - -#if CONFIG_PCI /* intire stuff is only for PCI */ - -#undef EICON_PCI_DEBUG - -int eicon_pci_find_card(char *ID) -{ - if (pci_present()) { - struct pci_dev *pdev = NULL; - int pci_nextindex=0, pci_cards=0, pci_akt=0; - int pci_type = PCI_MAESTRA; - int NoMorePCICards = FALSE; - char *ram, *reg, *cfg; - unsigned int pram=0, preg=0, pcfg=0; - char did[12]; - eicon_pci_card *aparms; - - if (!(aparms = (eicon_pci_card *) kmalloc(sizeof(eicon_pci_card), GFP_KERNEL))) { - printk(KERN_WARNING - "eicon_pci: Could not allocate card-struct.\n"); - return 0; - } - - for (pci_cards = 0; pci_cards < 0x0f; pci_cards++) - { - do { - if ((pdev = pci_find_device(PCI_VENDOR_EICON, - pci_type, - pdev))) - { - pci_nextindex++; - break; - } - else { - pci_nextindex = 0; - switch (pci_type) /* switch to next card type */ - { - case PCI_MAESTRA: - pci_type = PCI_MAESTRAQ; break; - case PCI_MAESTRAQ: - pci_type = PCI_MAESTRAQ_U; break; - case PCI_MAESTRAQ_U: - pci_type = PCI_MAESTRAP; break; - default: - case PCI_MAESTRAP: - NoMorePCICards = TRUE; - } - } - } - while (!NoMorePCICards); - if (NoMorePCICards) - { - if (pci_cards < 1) { - printk(KERN_INFO "Eicon: No supported PCI cards found.\n"); - kfree(aparms); - return 0; - } - else - { - printk(KERN_INFO "Eicon: %d PCI card%s registered.\n", - pci_cards, (pci_cards > 1) ? "s":""); - kfree(aparms); - return (pci_cards); - } - } - - pci_akt = 0; - switch(pci_type) - { - case PCI_MAESTRA: - printk(KERN_INFO "Eicon: DIVA Server BRI/PCI detected !\n"); - aparms->type = EICON_CTYPE_MAESTRA; - - aparms->irq = pdev->irq; - preg = get_pcibase(pdev, 2) & 0xfffffffc; - pcfg = get_pcibase(pdev, 1) & 0xffffff80; - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); - printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", preg); - printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", pcfg); -#endif - pci_akt = 1; - break; - - case PCI_MAESTRAQ: - case PCI_MAESTRAQ_U: - printk(KERN_ERR "Eicon: DIVA Server 4BRI/PCI detected but not supported !\n"); - pci_cards--; - pci_akt = 0; - break; - - case PCI_MAESTRAP: - printk(KERN_INFO "Eicon: DIVA Server PRI/PCI detected !\n"); - aparms->type = EICON_CTYPE_MAESTRAP; /*includes 9M,30M*/ - aparms->irq = pdev->irq; - pram = get_pcibase(pdev, 0) & 0xfffff000; - preg = get_pcibase(pdev, 2) & 0xfffff000; - pcfg = get_pcibase(pdev, 4) & 0xfffff000; - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: irq=%d\n", aparms->irq); - printk(KERN_DEBUG "eicon_pci: ram=0x%x\n", - (pram)); - printk(KERN_DEBUG "eicon_pci: reg=0x%x\n", - (preg)); - printk(KERN_DEBUG "eicon_pci: cfg=0x%x\n", - (pcfg)); -#endif - pci_akt = 1; - break; - default: - printk(KERN_ERR "eicon_pci: Unknown PCI card detected !\n"); - pci_cards--; - pci_akt = 0; - break; - } - - if (pci_akt) { - /* remapping memory */ - switch(pci_type) - { - case PCI_MAESTRA: - aparms->PCIreg = (unsigned int) preg; - aparms->PCIcfg = (unsigned int) pcfg; - if (check_region((aparms->PCIreg), 0x20)) { - printk(KERN_WARNING "eicon_pci: reg port already in use !\n"); - aparms->PCIreg = 0; - break; - } else { - request_region(aparms->PCIreg, 0x20, "eicon reg"); - } - if (check_region((aparms->PCIcfg), 0x80)) { - printk(KERN_WARNING "eicon_pci: cfg port already in use !\n"); - aparms->PCIcfg = 0; - release_region(aparms->PCIreg, 0x20); - break; - } else { - request_region(aparms->PCIcfg, 0x80, "eicon cfg"); - } - break; - case PCI_MAESTRAQ: - case PCI_MAESTRAQ_U: - case PCI_MAESTRAP: - aparms->shmem = (eicon_pci_shmem *) ioremap(pram, 0x10000); - ram = (u8 *) ((u32)aparms->shmem + MP_SHARED_RAM_OFFSET); - reg = ioremap(preg, 0x4000); - cfg = ioremap(pcfg, 0x1000); - aparms->PCIram = (unsigned int) ram; - aparms->PCIreg = (unsigned int) reg; - aparms->PCIcfg = (unsigned int) cfg; - break; - } - if ((!aparms->PCIreg) || (!aparms->PCIcfg)) { - printk(KERN_ERR "eicon_pci: Card could not be added !\n"); - pci_cards--; - } else { - aparms->mvalid = 1; - - sprintf(did, "%s%d", (strlen(ID) < 1) ? "eicon":ID, pci_cards); - - printk(KERN_INFO "%s: DriverID: '%s'\n",eicon_ctype_name[aparms->type] , did); - - if (!(eicon_addcard(aparms->type, (int) aparms, aparms->irq, did))) { - printk(KERN_ERR "eicon_pci: Card could not be added !\n"); - pci_cards--; - } - } - } - - } - } else - printk(KERN_ERR "eicon_pci: Kernel compiled with PCI but no PCI-bios found !\n"); - return 0; -} - -/* - * Checks protocol file id for "F#xxxx" string fragment to - * extract the features, supported by this protocol version. - * binary representation of the feature string value is returned - * in *value. The function returns 0 if feature string was not - * found or has a wrong format, else 1. - */ -static int GetProtFeatureValue(char *sw_id, int *value) -{ - __u8 i, offset; - - while (*sw_id) - { - if ((sw_id[0] == 'F') && (sw_id[1] == '#')) - { - sw_id = &sw_id[2]; - for (i=0, *value=0; i<4; i++, sw_id++) - { - if ((*sw_id >= '0') && (*sw_id <= '9')) - { - offset = '0'; - } - else if ((*sw_id >= 'A') && (*sw_id <= 'F')) - { - offset = 'A' + 10; - } - else if ((*sw_id >= 'a') && (*sw_id <= 'f')) - { - offset = 'a' + 10; - } - else - { - return 0; - } - *value |= (*sw_id - offset) << (4*(3-i)); - } - return 1; - } - else - { - sw_id++; - } - } - return 0; -} - - -void -eicon_pci_printpar(eicon_pci_card *card) { - switch (card->type) { - case EICON_CTYPE_MAESTRA: - printk(KERN_INFO "%s at 0x%x / 0x%x, irq %d\n", - eicon_ctype_name[card->type], - (unsigned int)card->PCIreg, - (unsigned int)card->PCIcfg, - card->irq); - break; - case EICON_CTYPE_MAESTRAQ: - case EICON_CTYPE_MAESTRAQ_U: - case EICON_CTYPE_MAESTRAP: - printk(KERN_INFO "%s at 0x%x, irq %d\n", - eicon_ctype_name[card->type], - (unsigned int)card->shmem, - card->irq); -#ifdef EICON_PCI_DEBUG - printk(KERN_INFO "eicon_pci: remapped ram= 0x%x\n",(unsigned int)card->PCIram); - printk(KERN_INFO "eicon_pci: remapped reg= 0x%x\n",(unsigned int)card->PCIreg); - printk(KERN_INFO "eicon_pci: remapped cfg= 0x%x\n",(unsigned int)card->PCIcfg); -#endif - break; - } -} - - -static void -eicon_pci_release_shmem(eicon_pci_card *card) { - if (!card->master) - return; - if (card->mvalid) { - switch (card->type) { - case EICON_CTYPE_MAESTRA: - /* reset board */ - outb(0, card->PCIcfg + 0x4c); /* disable interrupts from PLX */ - outb(0, card->PCIreg + M_RESET); - SLEEP(20); - outb(0, card->PCIreg + M_ADDRH); - outw(0, card->PCIreg + M_ADDR); - outw(0, card->PCIreg + M_DATA); - - release_region(card->PCIreg, 0x20); - release_region(card->PCIcfg, 0x80); - break; - case EICON_CTYPE_MAESTRAQ: - case EICON_CTYPE_MAESTRAQ_U: - case EICON_CTYPE_MAESTRAP: - /* reset board */ - writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET); - SLEEP(20); - writeb(0, card->PCIreg + MP_RESET); - SLEEP(20); - - iounmap((void *)card->shmem); - iounmap((void *)card->PCIreg); - iounmap((void *)card->PCIcfg); - break; - } - } - card->mvalid = 0; -} - -static void -eicon_pci_release_irq(eicon_pci_card *card) { - if (!card->master) - return; - if (card->ivalid) - free_irq(card->irq, card); - card->ivalid = 0; -} - -void -eicon_pci_release(eicon_pci_card *card) { - eicon_pci_release_irq(card); - eicon_pci_release_shmem(card); -} - -/* - * Upload buffer content to adapters shared memory - * on verify error, 1 is returned and a message is printed on screen - * else 0 is returned - * Can serve IO-Type and Memory type adapters - */ -int eicon_upload(t_dsp_download_space *p_para, - __u16 length, /* byte count */ - __u8 *buffer, - int verify) -{ - __u32 i, dwdata = 0, val = 0, timeout; - __u16 data; - eicon_pci_boot *boot = 0; - - switch (p_para->type) /* actions depend on type of union */ - { - case DL_PARA_IO_TYPE: - for (i=0; idat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH); - outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); - /* outw (((u16 *)code)[i >> 1], p_para->dat.io.ioDATA); */ - outw (*(u16 *)&buffer[i], p_para->dat.io.ioDATA); - } - if (verify) /* check written block */ - { - for (i=0; idat.io.r3addr + i) >> 16), p_para->dat.io.ioADDRH); - outw ((u16) (p_para->dat.io.r3addr + i), p_para->dat.io.ioADDR); - data = inw(p_para->dat.io.ioDATA); - if (data != *(u16 *)&buffer[i]) - { - p_para->dat.io.r3addr += i; - p_para->dat.io.BadData = data; - p_para->dat.io.GoodData = *(u16 *)&buffer[i]; - return 1; - } - } - } - break; - - case DL_PARA_MEM_TYPE: - boot = p_para->dat.mem.boot; - writel(p_para->dat.mem.r3addr, &boot->addr); - for (i=0; i> 2], &boot->data[i]); - } - if (verify) /* check written block */ - { - for (i=0; idata[i]); - if (((u32 *)buffer)[i >> 2] != dwdata) - { - p_para->dat.mem.r3addr += i; - p_para->dat.mem.BadData = dwdata; - p_para->dat.mem.GoodData = ((u32 *)buffer)[i >> 2]; - return 1; - } - } - } - writel(((length + 3) / 4), &boot->len); /* len in dwords */ - writel(2, &boot->cmd); - - timeout = jiffies + 20; - while (timeout > jiffies) { - val = readl(&boot->cmd); - if (!val) break; - SLEEP(2); - } - if (val) - { - p_para->dat.mem.timeout = 1; - return 1; - } - break; - } - return 0; -} - - -/* show header information of code file */ -static -int eicon_pci_print_hdr(unsigned char *code, int offset) -{ - unsigned char hdr[80]; - int i, fvalue = 0; - - i = 0; - while ((i < (sizeof(hdr) -1)) - && (code[offset + i] != '\0') - && (code[offset + i] != '\r') - && (code[offset + i] != '\n')) - { - hdr[i] = code[offset + i]; - i++; - } - hdr[i] = '\0'; - printk(KERN_DEBUG "Eicon: loading %s\n", hdr); - if (GetProtFeatureValue(hdr, &fvalue)) return(fvalue); - else return(0); -} - - -/* - * Configure a card, download code into BRI card, - * check if we get interrupts and return 0 on succes. - * Return -ERRNO on failure. - */ -int -eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb) { - int i,j; - int timeout; - unsigned int offset, offp=0, size, length; - int signature = 0; - int FeatureValue = 0; - eicon_pci_codebuf cbuf; - t_dsp_download_space dl_para; - t_dsp_download_desc dsp_download_table; - unsigned char *code; - unsigned int reg; - unsigned int cfg; - - if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf))) - return -EFAULT; - - reg = card->PCIreg; - cfg = card->PCIcfg; - - /* reset board */ - outb(0, reg + M_RESET); - SLEEP(10); - outb(0, reg + M_ADDRH); - outw(0, reg + M_ADDR); - outw(0, reg + M_DATA); - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: reset card\n"); -#endif - - /* clear shared memory */ - outb(0xff, reg + M_ADDRH); - outw(0, reg + M_ADDR); - for(i = 0; i < 0xffff; i++) outw(0, reg + M_DATA); - SLEEP(10); - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: clear shared memory\n"); -#endif - - /* download protocol and dsp file */ - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: downloading firmware...\n"); -#endif - - /* Allocate code-buffer */ - if (!(code = kmalloc(400, GFP_KERNEL))) { - printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n"); - return -ENOMEM; - } - - /* prepare protocol upload */ - dl_para.type = DL_PARA_IO_TYPE; - dl_para.dat.io.ioADDR = reg + M_ADDR; - dl_para.dat.io.ioADDRH = reg + M_ADDRH; - dl_para.dat.io.ioDATA = reg + M_DATA; - - for (j = 0; j <= cbuf.dsp_code_num; j++) - { - if (j == 0) size = cbuf.protocol_len; - else size = cbuf.dsp_code_len[j]; - - offset = 0; - - if (j == 0) dl_para.dat.io.r3addr = 0; - if (j == 1) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + - ((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc); - if (j == 2) dl_para.dat.io.r3addr = M_DSP_CODE_BASE; - if (j == 3) dl_para.dat.io.r3addr = M_DSP_CODE_BASE + sizeof(__u32); - - do /* download block of up to 400 bytes */ - { - length = ((size - offset) >= 400) ? 400 : (size - offset); - - if (copy_from_user(code, (&cb->code) + offp + offset, length)) { - kfree(code); - return -EFAULT; - } - - if ((offset == 0) && (j < 2)) { - FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); -#ifdef EICON_PCI_DEBUG - if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%04x.\n", FeatureValue); -#endif - if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) { - printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n"); - kfree(code); - return -EFAULT; - } - ((eicon_card *)card->card)->Feature = FeatureValue; - } - - if (eicon_upload(&dl_para, length, code, 1)) - { - printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr); - kfree(code); - return -EIO; - } - /* move onto next block */ - offset += length; - dl_para.dat.io.r3addr += length; - } while (offset < size); - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "Eicon: %d bytes loaded.\n", offset); -#endif - offp += size; - } - kfree(code); - - /* clear signature */ - outb(0xff, reg + M_ADDRH); - outw(0x1e, reg + M_ADDR); - outw(0, reg + M_DATA); - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n"); -#endif - /* copy configuration data into shared memory */ - outw(8, reg + M_ADDR); outb(cbuf.tei, reg + M_DATA); - outw(9, reg + M_ADDR); outb(cbuf.nt2, reg + M_DATA); - outw(10,reg + M_ADDR); outb(0, reg + M_DATA); - outw(11,reg + M_ADDR); outb(cbuf.WatchDog, reg + M_DATA); - outw(12,reg + M_ADDR); outb(cbuf.Permanent, reg + M_DATA); - outw(13,reg + M_ADDR); outb(0, reg + M_DATA); /* XInterface */ - outw(14,reg + M_ADDR); outb(cbuf.StableL2, reg + M_DATA); - outw(15,reg + M_ADDR); outb(cbuf.NoOrderCheck, reg + M_DATA); - outw(16,reg + M_ADDR); outb(0, reg + M_DATA); /* HandsetType */ - outw(17,reg + M_ADDR); outb(0, reg + M_DATA); /* SigFlags */ - outw(18,reg + M_ADDR); outb(cbuf.LowChannel, reg + M_DATA); - outw(19,reg + M_ADDR); outb(cbuf.ProtVersion, reg + M_DATA); - outw(20,reg + M_ADDR); outb(cbuf.Crc4, reg + M_DATA); - outw(21,reg + M_ADDR); outb((cbuf.Loopback) ? 2:0, reg + M_DATA); - - for (i=0;i<32;i++) - { - outw( 32+i, reg + M_ADDR); outb(cbuf.l[0].oad[i], reg + M_DATA); - outw( 64+i, reg + M_ADDR); outb(cbuf.l[0].osa[i], reg + M_DATA); - outw( 96+i, reg + M_ADDR); outb(cbuf.l[0].spid[i], reg + M_DATA); - outw(128+i, reg + M_ADDR); outb(cbuf.l[1].oad[i], reg + M_DATA); - outw(160+i, reg + M_ADDR); outb(cbuf.l[1].osa[i], reg + M_DATA); - outw(192+i, reg + M_ADDR); outb(cbuf.l[1].spid[i], reg + M_DATA); - } - -#ifdef EICON_PCI_DEBUG - printk(KERN_ERR "eicon_pci: starting CPU...\n"); -#endif - /* let the CPU run */ - outw(0x08, reg + M_RESET); - - timeout = jiffies + (5*HZ); - while (timeout > jiffies) { - outw(0x1e, reg + M_ADDR); - signature = inw(reg + M_DATA); - if (signature == DIVAS_SIGNATURE) break; - SLEEP(2); - } - if (signature != DIVAS_SIGNATURE) - { -#ifdef EICON_PCI_DEBUG - printk(KERN_ERR "eicon_pci: signature 0x%x expected 0x%x\n",signature,DIVAS_SIGNATURE); -#endif - printk(KERN_ERR "eicon_pci: Timeout, protocol code not running !\n"); - return -EIO; - } -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n"); -#endif - - /* get serial number and number of channels supported by card */ - outb(0xff, reg + M_ADDRH); - outw(0x3f6, reg + M_ADDR); - card->channels = inw(reg + M_DATA); - card->serial = (u32)inw(cfg + 0x22) << 16 | (u32)inw(cfg + 0x26); - printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels); - printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial); - - /* test interrupt */ - card->irqprobe = 1; - - if (!card->ivalid) { - if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card)) - { - printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq); - return -EIO; - } - } - card->ivalid = 1; - -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: testing interrupt\n"); -#endif - /* Trigger an interrupt and check if it is delivered */ - outb(0x41, cfg + 0x4c); /* enable PLX for interrupts */ - outb(0x89, reg + M_RESET); /* place int request */ - - timeout = jiffies + 20; - while (timeout > jiffies) { - if (card->irqprobe != 1) break; - SLEEP(5); - } - if (card->irqprobe == 1) { - free_irq(card->irq, card); - card->ivalid = 0; - printk(KERN_ERR "eicon_pci: Getting no interrupts !\n"); - return -EIO; - } - - /* initializing some variables */ - ((eicon_card *)card->card)->ReadyInt = 0; - for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL; - for(j=0; j< (card->channels + 1); j++) { - ((eicon_card *)card->card)->bch[j].e.busy = 0; - ((eicon_card *)card->card)->bch[j].e.D3Id = 0; - ((eicon_card *)card->card)->bch[j].e.B2Id = 0; - ((eicon_card *)card->card)->bch[j].e.ref = 0; - ((eicon_card *)card->card)->bch[j].e.Req = 0; - ((eicon_card *)card->card)->bch[j].e.complete = 1; - ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL; - } - - printk(KERN_INFO "Eicon: Card successfully started\n"); - - return 0; -} - - -/* - * Configure a card, download code into PRI card, - * check if we get interrupts and return 0 on succes. - * Return -ERRNO on failure. - */ -int -eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb) { - eicon_pci_boot *boot; - eicon_pr_ram *prram; - int i,j; - int timeout; - int FeatureValue = 0; - unsigned int offset, offp=0, size, length; - unsigned long int signature = 0; - t_dsp_download_space dl_para; - t_dsp_download_desc dsp_download_table; - eicon_pci_codebuf cbuf; - unsigned char *code; - unsigned char req_int; - char *ram, *reg, *cfg; - - if (copy_from_user(&cbuf, cb, sizeof(eicon_pci_codebuf))) - return -EFAULT; - - boot = &card->shmem->boot; - ram = (char *)card->PCIram; - reg = (char *)card->PCIreg; - cfg = (char *)card->PCIcfg; - prram = (eicon_pr_ram *)ram; - - /* reset board */ - writeb(_MP_RISC_RESET | _MP_LED1 | _MP_LED2, card->PCIreg + MP_RESET); - SLEEP(20); - writeb(0, card->PCIreg + MP_RESET); - SLEEP(20); - - /* set command count to 0 */ - writel(0, &boot->reserved); - - /* check if CPU increments the life word */ - i = readw(&boot->live); - SLEEP(20); - if (i == readw(&boot->live)) { - printk(KERN_ERR "eicon_pci: card is reset, but CPU not running !\n"); - return -EIO; - } -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: reset card OK (CPU running)\n"); -#endif - - /* download firmware : DSP and Protocol */ -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: downloading firmware...\n"); -#endif - - /* Allocate code-buffer */ - if (!(code = kmalloc(400, GFP_KERNEL))) { - printk(KERN_WARNING "eicon_pci_boot: Couldn't allocate code buffer\n"); - return -ENOMEM; - } - - /* prepare protocol upload */ - dl_para.type = DL_PARA_MEM_TYPE; - dl_para.dat.mem.boot = boot; - - for (j = 0; j <= cbuf.dsp_code_num; j++) - { - if (j==0) size = cbuf.protocol_len; - else size = cbuf.dsp_code_len[j]; - - if (j==1) writel(MP_DSP_ADDR, &boot->addr); /* DSP code entry point */ - - if (j == 0) dl_para.dat.io.r3addr = MP_PROTOCOL_ADDR; - if (j == 1) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + - ((sizeof(__u32) + (sizeof(dsp_download_table) * 35) + 3) &0xfffffffc); - if (j == 2) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE; - if (j == 3) dl_para.dat.io.r3addr = MP_DSP_CODE_BASE + sizeof(__u32); - - offset = 0; - do /* download block of up to 400 bytes */ - { - length = ((size - offset) >= 400) ? 400 : (size - offset); - - if (copy_from_user(code, (&cb->code) + offp + offset, length)) { - kfree(code); - return -EFAULT; - } - - if ((offset == 0) && (j < 2)) { - FeatureValue = eicon_pci_print_hdr(code, j ? 0x00 : 0x80); -#ifdef EICON_PCI_DEBUG - if (FeatureValue) printk(KERN_DEBUG "eicon_pci: Feature Value : 0x%x.\n", FeatureValue); -#endif - if ((j==0) && (!(FeatureValue & PROTCAP_TELINDUS))) { - printk(KERN_ERR "eicon_pci: Protocol Code cannot handle Telindus\n"); - kfree(code); - return -EFAULT; - } - ((eicon_card *)card->card)->Feature = FeatureValue; - } - - if (eicon_upload(&dl_para, length, code, 1)) - { - if (dl_para.dat.mem.timeout == 0) - printk(KERN_ERR "eicon_pci: code block check failed at 0x%x !\n",dl_para.dat.io.r3addr); - else - printk(KERN_ERR "eicon_pci: timeout, no ACK to load !\n"); - kfree(code); - return -EIO; - } - - /* move onto next block */ - offset += length; - dl_para.dat.mem.r3addr += length; - } while (offset < size); -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: %d bytes loaded.\n", offset); -#endif - offp += size; - } - kfree(code); - - /* initialize the adapter data structure */ -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: copy configuration data into shared memory...\n"); -#endif - /* clear out config space */ - for (i = 0; i < 256; i++) writeb(0, &ram[i]); - - /* copy configuration down to the card */ - writeb(cbuf.tei, &ram[8]); - writeb(cbuf.nt2, &ram[9]); - writeb(0, &ram[10]); - writeb(cbuf.WatchDog, &ram[11]); - writeb(cbuf.Permanent, &ram[12]); - writeb(cbuf.XInterface, &ram[13]); - writeb(cbuf.StableL2, &ram[14]); - writeb(cbuf.NoOrderCheck, &ram[15]); - writeb(cbuf.HandsetType, &ram[16]); - writeb(0, &ram[17]); - writeb(cbuf.LowChannel, &ram[18]); - writeb(cbuf.ProtVersion, &ram[19]); - writeb(cbuf.Crc4, &ram[20]); - for (i = 0; i < 32; i++) - { - writeb(cbuf.l[0].oad[i], &ram[32 + i]); - writeb(cbuf.l[0].osa[i], &ram[64 + i]); - writeb(cbuf.l[0].spid[i], &ram[96 + i]); - writeb(cbuf.l[1].oad[i], &ram[128 + i]); - writeb(cbuf.l[1].osa[i], &ram[160 + i]); - writeb(cbuf.l[1].spid[i], &ram[192 + i]); - } -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: configured card OK\n"); -#endif - - /* start adapter */ -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: tell card to start...\n"); -#endif - writel(MP_PROTOCOL_ADDR, &boot->addr); /* RISC code entry point */ - writel(3, &boot->cmd); /* DIVAS_START_CMD */ - - /* wait till card ACKs */ - timeout = jiffies + (5*HZ); - while (timeout > jiffies) { - signature = readl(&boot->signature); - if ((signature >> 16) == DIVAS_SIGNATURE) break; - SLEEP(2); - } - if ((signature >> 16) != DIVAS_SIGNATURE) - { -#ifdef EICON_PCI_DEBUG - printk(KERN_ERR "eicon_pci: signature 0x%lx expected 0x%x\n",(signature >> 16),DIVAS_SIGNATURE); -#endif - printk(KERN_ERR "eicon_pci: timeout, protocol code not running !\n"); - return -EIO; - } -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: Protocol code running, signature OK\n"); -#endif - - /* get serial number and number of channels supported by card */ - card->channels = readb(&ram[0x3f6]); - card->serial = readl(&ram[0x3f0]); - printk(KERN_INFO "Eicon: Supported channels : %d\n", card->channels); - printk(KERN_INFO "Eicon: Card serial no. = %lu\n", card->serial); - - /* test interrupt */ - readb(&ram[0x3fe]); - writeb(0, &ram[0x3fe]); /* reset any pending interrupt */ - readb(&ram[0x3fe]); - - writew(MP_IRQ_RESET_VAL, &cfg[MP_IRQ_RESET]); - writew(0, &cfg[MP_IRQ_RESET + 2]); - - card->irqprobe = 1; - - if (!card->ivalid) { - if (request_irq(card->irq, &eicon_irq, 0, "Eicon PCI ISDN", card->card)) - { - printk(KERN_ERR "eicon_pci: Couldn't request irq %d\n", card->irq); - return -EIO; - } - } - card->ivalid = 1; - - req_int = readb(&prram->ReadyInt); -#ifdef EICON_PCI_DEBUG - printk(KERN_DEBUG "eicon_pci: testing interrupt\n"); -#endif - req_int++; - /* Trigger an interrupt and check if it is delivered */ - writeb(req_int, &prram->ReadyInt); - - timeout = jiffies + 20; - while (timeout > jiffies) { - if (card->irqprobe != 1) break; - SLEEP(2); - } - if (card->irqprobe == 1) { - free_irq(card->irq, card); - card->ivalid = 0; - printk(KERN_ERR "eicon_pci: Getting no interrupts !\n"); - return -EIO; - } - - /* initializing some variables */ - ((eicon_card *)card->card)->ReadyInt = 0; - for(j=0; j<256; j++) ((eicon_card *)card->card)->IdTable[j] = NULL; - for(j=0; j< (card->channels + 1); j++) { - ((eicon_card *)card->card)->bch[j].e.busy = 0; - ((eicon_card *)card->card)->bch[j].e.D3Id = 0; - ((eicon_card *)card->card)->bch[j].e.B2Id = 0; - ((eicon_card *)card->card)->bch[j].e.ref = 0; - ((eicon_card *)card->card)->bch[j].e.Req = 0; - ((eicon_card *)card->card)->bch[j].e.complete = 1; - ((eicon_card *)card->card)->bch[j].fsm_state = EICON_STATE_NULL; - } - - printk(KERN_INFO "Eicon: Card successfully started\n"); - - return 0; -} - -#endif /* CONFIG_PCI */ - diff --git a/drivers/isdn/eicon/eicon_pci.h b/drivers/isdn/eicon/eicon_pci.h deleted file mode 100644 index 181ff734..00000000 --- a/drivers/isdn/eicon/eicon_pci.h +++ /dev/null @@ -1,188 +0,0 @@ -/* $Id$ - * - * ISDN low-level module for Eicon active ISDN-Cards (PCI part). - * - * Copyright 1998-2000 by Armin Schindler (mac@melware.de) - * Copyright 1999,2000 Cytronics & Melware (info@melware.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * 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. - * - * $Log$ - * Revision 1.3 1999/03/29 11:19:51 armin - * I/O stuff now in seperate file (eicon_io.c) - * Old ISA type cards (S,SX,SCOM,Quadro,S2M) implemented. - * - * Revision 1.2 1999/03/02 12:37:50 armin - * Added some important checks. - * Analog Modem with DSP. - * Channels will be added to Link-Level after loading firmware. - * - * Revision 1.1 1999/01/01 18:09:46 armin - * First checkin of new eicon driver. - * DIVA-Server BRI/PCI and PRI/PCI are supported. - * Old diehl code is obsolete. - * - * - */ - -#ifndef eicon_pci_h -#define eicon_pci_h - -#ifdef __KERNEL__ - - -#define PCI_VENDOR_EICON 0x1133 -#define PCI_DIVA_PRO20 0xe001 /* Not supported */ -#define PCI_DIVA20 0xe002 /* Not supported */ -#define PCI_DIVA_PRO20_U 0xe003 /* Not supported */ -#define PCI_DIVA20_U 0xe004 /* Not supported */ -#define PCI_MAESTRA 0xe010 -#define PCI_MAESTRAQ 0xe012 -#define PCI_MAESTRAQ_U 0xe013 -#define PCI_MAESTRAP 0xe014 - -#define DIVA_PRO20 1 -#define DIVA20 2 -#define DIVA_PRO20_U 3 -#define DIVA20_U 4 -#define MAESTRA 5 -#define MAESTRAQ 6 -#define MAESTRAQ_U 7 -#define MAESTRAP 8 - -#define TRUE 1 -#define FALSE 0 - -#define DIVAS_SIGNATURE 0x4447 - - -/* MAESTRA BRI PCI */ - -#define M_RESET 0x10 /* offset of reset register */ -#define M_DATA 0x00 /* offset of data register */ -#define M_ADDR 0x04 /* offset of address register */ -#define M_ADDRH 0x0c /* offset of high address register */ - -#define M_DSP_CODE_LEN 0xbf7d0000 -#define M_DSP_CODE 0xbf7d0004 /* max 128K DSP-Code */ -#define M_DSP_CODE_BASE 0xbf7a0000 -#define M_MAX_DSP_CODE_SIZE 0x00050000 /* max 320K DSP-Code (Telindus) */ - - - -/* MAESTRA PRI PCI */ - -#define MP_SHARED_RAM_OFFSET 0x1000 /* offset of shared RAM base in the DRAM memory bar */ - -#define MP_IRQ_RESET 0xc18 /* offset of interrupt status register in the CONFIG memory bar */ -#define MP_IRQ_RESET_VAL 0xfe /* value to clear an interrupt */ - -#define MP_PROTOCOL_ADDR 0xa0011000 /* load address of protocol code */ -#define MP_DSP_ADDR 0xa03c0000 /* load address of DSP code */ -#define MP_MAX_PROTOCOL_CODE_SIZE 0x000a0000 /* max 640K Protocol-Code */ -#define MP_DSP_CODE_BASE 0xa03a0000 -#define MP_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code */ - -#define MP_RESET 0x20 /* offset of RESET register in the DEVICES memory bar */ - -/* RESET register bits */ -#define _MP_S2M_RESET 0x10 /* active lo */ -#define _MP_LED2 0x08 /* 1 = on */ -#define _MP_LED1 0x04 /* 1 = on */ -#define _MP_DSP_RESET 0x02 /* active lo */ -#define _MP_RISC_RESET 0x81 /* active hi, bit 7 for compatibility with old boards */ - -/* boot interface structure */ -typedef struct { - __u32 cmd __attribute__ ((packed)); - __u32 addr __attribute__ ((packed)); - __u32 len __attribute__ ((packed)); - __u32 err __attribute__ ((packed)); - __u32 live __attribute__ ((packed)); - __u32 reserved[(0x1020>>2)-6] __attribute__ ((packed)); - __u32 signature __attribute__ ((packed)); - __u8 data[1]; /* real interface description */ -} eicon_pci_boot; - - -#define DL_PARA_IO_TYPE 0 -#define DL_PARA_MEM_TYPE 1 - -typedef struct tag_dsp_download_space -{ - __u16 type; /* see definitions above to differ union elements */ - union - { - struct - { - __u32 r3addr; - __u16 ioADDR; - __u16 ioADDRH; - __u16 ioDATA; - __u16 BadData; /* in case of verify error */ - __u16 GoodData; - } io; /* for io based adapters */ - struct - { - __u32 r3addr; - eicon_pci_boot *boot; - __u32 BadData; /* in case of verify error */ - __u32 GoodData; - __u16 timeout; - } mem; /* for memory based adapters */ - } dat; -} t_dsp_download_space; - - -/* Shared memory */ -typedef union { - eicon_pci_boot boot; -} eicon_pci_shmem; - -/* - * card's description - */ -typedef struct { - int ramsize; - int irq; /* IRQ */ - unsigned int PCIram; - unsigned int PCIreg; - unsigned int PCIcfg; - long int serial; /* Serial No. */ - int channels; /* No. of supported channels */ - void* card; - eicon_pci_shmem* shmem; /* Shared-memory area */ - unsigned char* intack; /* Int-Acknowledge */ - unsigned char* stopcpu; /* Writing here stops CPU */ - unsigned char* startcpu; /* Writing here starts CPU */ - unsigned char type; /* card type */ - unsigned char irqprobe; /* Flag: IRQ-probing */ - unsigned char mvalid; /* Flag: Memory is valid */ - unsigned char ivalid; /* Flag: IRQ is valid */ - unsigned char master; /* Flag: Card is Quadro 1/4 */ - void* generic; /* Ptr to generic card struct */ -} eicon_pci_card; - - - -extern int eicon_pci_load_pri(eicon_pci_card *card, eicon_pci_codebuf *cb); -extern int eicon_pci_load_bri(eicon_pci_card *card, eicon_pci_codebuf *cb); -extern void eicon_pci_release(eicon_pci_card *card); -extern void eicon_pci_printpar(eicon_pci_card *card); -extern int eicon_pci_find_card(char *ID); - -#endif /* __KERNEL__ */ - -#endif /* eicon_pci_h */ diff --git a/drivers/isdn/hysdn/Makefile b/drivers/isdn/hysdn/Makefile deleted file mode 100644 index 626a6dea..00000000 --- a/drivers/isdn/hysdn/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -SUB_DIRS := -MOD_SUB_DIRS := -ALL_SUB_DIRS := - -L_OBJS := -LX_OBJS := -M_OBJS := -MX_OBJS := -O_OBJS := -OX_OBJS := -L_TARGET := -O_TARGET := - -ifeq ($(CONFIG_PROC_FS),y) - ifeq ($(CONFIG_HYSDN),y) - M_OBJS += hysdn.o - O_TARGET += hysdn.o - O_OBJS += hysdn_procconf.o hysdn_proclog.o boardergo.o hysdn_boot.o hysdn_sched.o hysdn_net.o - OX_OBJS += hysdn_init.o - endif -endif - -include $(TOPDIR)/Rules.make - diff --git a/drivers/isdn/hysdn/boardergo.c b/drivers/isdn/hysdn/boardergo.c deleted file mode 100644 index 7dd8e878..00000000 --- a/drivers/isdn/hysdn/boardergo.c +++ /dev/null @@ -1,464 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, specific routines for ergo type boards. - * - * 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. - * - * $Log$ - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" -#include "boardergo.h" - -#define byteout(addr,val) outb(val,addr) -#define bytein(addr) inb(addr) - -/***************************************************/ -/* The cards interrupt handler. Called from system */ -/***************************************************/ -static void -ergo_interrupt(int intno, void *dev_id, struct pt_regs *regs) -{ - hysdn_card *card = dev_id; /* parameter from irq */ - tErgDpram *dpr; - ulong flags; - uchar volatile b; - - if (!card) - return; /* error -> spurious interrupt */ - if (!card->irq_enabled) - return; /* other device interrupting or irq switched off */ - - save_flags(flags); - cli(); /* no further irqs allowed */ - - if (!(bytein(card->iobase + PCI9050_INTR_REG) & PCI9050_INTR_REG_STAT1)) { - restore_flags(flags); /* restore old state */ - return; /* no interrupt requested by E1 */ - } - /* clear any pending ints on the board */ - dpr = card->dpram; - b = dpr->ToPcInt; /* clear for ergo */ - b |= dpr->ToPcIntMetro; /* same for metro */ - b |= dpr->ToHyInt; /* and for champ */ - - /* start kernel task immediately after leaving all interrupts */ - if (!card->hw_lock) { - queue_task(&card->irq_queue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - } - restore_flags(flags); -} /* ergo_interrupt */ - -/******************************************************************************/ -/* ergo_irq_bh is the function called by the immediate kernel task list after */ -/* being activated with queue_task and no interrupts active. This task is the */ -/* only one handling data transfer from or to the card after booting. The task */ -/* may be queued from everywhere (interrupts included). */ -/******************************************************************************/ -static void -ergo_irq_bh(hysdn_card * card) -{ - tErgDpram *dpr; - int again; - ulong flags; - - if (card->state != CARD_STATE_RUN) - return; /* invalid call */ - - dpr = card->dpram; /* point to DPRAM */ - - save_flags(flags); - cli(); - if (card->hw_lock) { - restore_flags(flags); /* hardware currently unavailable */ - 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) { - /* we are able to send a buffer */ - - if (hysdn_sched_tx(card, dpr->ToHyBuf, &dpr->ToHySize, &dpr->ToHyChannel, - ERG_TO_HY_BUF_SIZE)) { - dpr->ToHyFlag = 1; /* enable tx */ - again = 1; /* restart loop */ - } - } /* we are able to send a buffer */ - if (dpr->ToPcFlag) { - /* a message has arrived for us, handle it */ - - if (hysdn_sched_rx(card, dpr->ToPcBuf, dpr->ToPcSize, dpr->ToPcChannel)) { - dpr->ToPcFlag = 0; /* we worked the data */ - 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); -} /* ergo_irq_bh */ - - -/*********************************************************/ -/* stop the card (hardware reset) and disable interrupts */ -/*********************************************************/ -static void -ergo_stopcard(hysdn_card * card) -{ - ulong flags; - uchar val; - - hysdn_net_release(card); /* first release the net device if existing */ - save_flags(flags); - cli(); - 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); - card->irq_enabled = 0; - 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); -} /* ergo_stopcard */ - -/**************************************************************************/ -/* enable or disable the cards error log. The event is queued if possible */ -/**************************************************************************/ -static void -ergo_set_errlog_state(hysdn_card * card, int on) -{ - ulong flags; - - if (card->state != CARD_STATE_RUN) { - card->err_log_state = ERRLOG_STATE_OFF; /* must be off */ - return; - } - save_flags(flags); - cli(); - - if (((card->err_log_state == ERRLOG_STATE_OFF) && !on) || - ((card->err_log_state == ERRLOG_STATE_ON) && on)) { - restore_flags(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); - queue_task(&card->irq_queue, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} /* ergo_set_errlog_state */ - -/******************************************/ -/* test the cards RAM and return 0 if ok. */ -/******************************************/ -static const char TestText[36] = "This Message is filler, why read it"; - -static int -ergo_testram(hysdn_card * card) -{ - tErgDpram *dpr = card->dpram; - - memset(dpr->TrapTable, 0, sizeof(dpr->TrapTable)); /* clear all Traps */ - dpr->ToHyInt = 1; /* E1 INTR state forced */ - - memcpy(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText)); - if (memcmp(&dpr->ToHyBuf[ERG_TO_HY_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText))) - return (-1); - - memcpy(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText)); - if (memcmp(&dpr->ToPcBuf[ERG_TO_PC_BUF_SIZE - sizeof(TestText)], TestText, - sizeof(TestText))) - return (-1); - - return (0); -} /* ergo_testram */ - -/*****************************************************************************/ -/* this function is intended to write stage 1 boot image to the cards buffer */ -/* this is done in two steps. First the 1024 hi-words are written (offs=0), */ -/* then the 1024 lo-bytes are written. The remaining DPRAM is cleared, the */ -/* PCI-write-buffers flushed and the card is taken out of reset. */ -/* The function then waits for a reaction of the E1 processor or a timeout. */ -/* Negative return values are interpreted as errors. */ -/*****************************************************************************/ -static int -ergo_writebootimg(struct HYSDN_CARD *card, uchar * buf, ulong offs) -{ - uchar *dst; - tErgDpram *dpram; - int cnt = (BOOT_IMG_SIZE >> 2); /* number of words to move and swap (byte order!) */ - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write bootldr offs=0x%lx ", offs); - - dst = card->dpram; /* pointer to start of DPRAM */ - dst += (offs + ERG_DPRAM_FILL_SIZE); /* offset in the DPRAM */ - while (cnt--) { - *dst++ = *(buf + 1); /* high byte */ - *dst++ = *buf; /* low byte */ - dst += 2; /* point to next longword */ - buf += 2; /* buffer only filled with words */ - } - - /* if low words (offs = 2) have been written, clear the rest of the DPRAM, */ - /* flush the PCI-write-buffer and take the E1 out of reset */ - if (offs) { - memset(card->dpram, 0, ERG_DPRAM_FILL_SIZE); /* fill the DPRAM still not cleared */ - dpram = card->dpram; /* get pointer to dpram structure */ - dpram->ToHyNoDpramErrLog = 0xFF; /* write a dpram register */ - 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 */ - - if (((tDpramBootSpooler *) card->dpram)->Len != DPRAM_SPOOLER_DATA_SIZE) { - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write bootldr no answer"); - return (-ERR_BOOTIMG_FAIL); - } - } /* start_boot_img */ - return (0); /* successfull */ -} /* ergo_writebootimg */ - -/********************************************************************************/ -/* ergo_writebootseq writes the buffer containing len bytes to the E1 processor */ -/* using the boot spool mechanism. If everything works fine 0 is returned. In */ -/* case of errors a negative error value is returned. */ -/********************************************************************************/ -static int -ergo_writebootseq(struct HYSDN_CARD *card, uchar * buf, int len) -{ - tDpramBootSpooler *sp = (tDpramBootSpooler *) card->dpram; - uchar *dst; - uchar buflen; - int nr_write; - uchar tmp_rdptr; - uchar wr_mirror; - int i; - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write boot seq len=%d ", len); - - 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 */ - while (len) { - - /* first determine the number of bytes that may be buffered */ - do { - tmp_rdptr = sp->RdPtr; /* first read the pointer */ - i--; /* decrement timeout */ - } while (i && (tmp_rdptr != sp->RdPtr)); /* wait for stable pointer */ - - if (!i) { - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: write boot seq timeout"); - return (-ERR_BOOTSEQ_FAIL); /* value not stable -> timeout */ - } - if ((nr_write = tmp_rdptr - wr_mirror - 1) < 0) - nr_write += buflen; /* now we got number of free bytes - 1 in buffer */ - - if (!nr_write) - continue; /* no free bytes in buffer */ - - if (nr_write > len) - nr_write = len; /* limit if last few bytes */ - i = 0x1000; /* reset timeout value */ - - /* now we know how much bytes we may put in the puffer */ - len -= nr_write; /* we savely could adjust len before output */ - while (nr_write--) { - *(dst + wr_mirror) = *buf++; /* output one byte */ - if (++wr_mirror >= buflen) - wr_mirror = 0; - sp->WrPtr = wr_mirror; /* announce the next byte to E1 */ - } /* while (nr_write) */ - - } /* while (len) */ - - return (0); -} /* ergo_writebootseq */ - -/***********************************************************************************/ -/* ergo_waitpofready waits for a maximum of 10 seconds for the completition of the */ -/* boot process. If the process has been successfull 0 is returned otherwise a */ -/* negative error code is returned. */ -/***********************************************************************************/ -static int -ergo_waitpofready(struct HYSDN_CARD *card) -{ - tErgDpram *dpr = card->dpram; /* pointer to DPRAM structure */ - int timecnt = 10000 / 50; /* timeout is 10 secs max. */ - ulong flags; - int msg_size; - int i; - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: waiting for pof ready"); - - while (timecnt--) { - /* wait until timeout */ - - if (dpr->ToPcFlag) { - /* data has arrived */ - - if ((dpr->ToPcChannel != CHAN_SYSTEM) || - (dpr->ToPcSize < MIN_RDY_MSG_SIZE) || - (dpr->ToPcSize > MAX_RDY_MSG_SIZE) || - ((*(ulong *) dpr->ToPcBuf) != RDY_MAGIC)) - break; /* an error occured */ - - /* Check for additional data delivered during SysReady */ - msg_size = dpr->ToPcSize - RDY_MAGIC_SIZE; - if (msg_size > 0) - if (EvalSysrTokData(card, dpr->ToPcBuf + RDY_MAGIC_SIZE, msg_size)) - break; - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "ERGO: pof boot success"); - - save_flags(flags); - cli(); - - card->state = CARD_STATE_RUN; /* now card is running */ - /* enable the cards interrupt */ - byteout(card->iobase + PCI9050_INTR_REG, - bytein(card->iobase + PCI9050_INTR_REG) | - (PCI9050_INTR_REG_ENPCI | PCI9050_INTR_REG_EN1)); - card->irq_enabled = 1; /* we are ready to receive interrupts */ - - dpr->ToPcFlag = 0; /* reset data indicator */ - dpr->ToHyInt = 1; - dpr->ToPcInt = 1; /* interrupt to E1 for all cards */ - - restore_flags(flags); - if ((i = hysdn_net_create(card))) { - ergo_stopcard(card); - card->state = CARD_STATE_BOOTERR; - return (i); - } - return (0); /* success */ - } /* data has arrived */ - sti(); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout((50 * HZ) / 1000); /* Timeout 50ms */ - } /* wait until timeout */ - - if (card->debug_flags & LOG_POF_CARD) - hysdn_addlog(card, "ERGO: pof boot ready timeout"); - return (-ERR_POF_TIMEOUT); -} /* ergo_waitpofready */ - - - -/************************************************************************************/ -/* release the cards hardware. Before releasing do a interrupt disable and hardware */ -/* reset. Also unmap dpram. */ -/* Use only during module release. */ -/************************************************************************************/ -static void -ergo_releasehardware(hysdn_card * card) -{ - ergo_stopcard(card); /* first stop the card if not already done */ - free_irq(card->irq, card); /* release interrupt */ - release_region(card->iobase + PCI9050_INTR_REG, 1); /* release all io ports */ - release_region(card->iobase + PCI9050_USER_IO, 1); - vfree(card->dpram); - card->dpram = NULL; /* release shared mem */ -} /* ergo_releasehardware */ - - -/*********************************************************************************/ -/* acquire the needed hardware ports and map dpram. If an error occurs a nonzero */ -/* value is returned. */ -/* Use only during module init. */ -/*********************************************************************************/ -int -ergo_inithardware(hysdn_card * card) -{ - if (check_region(card->iobase + PCI9050_INTR_REG, 1) || - check_region(card->iobase + PCI9050_USER_IO, 1)) - return (-1); /* ports already in use */ - - card->memend = card->membase + ERG_DPRAM_PAGE_SIZE - 1; - if (!(card->dpram = ioremap(card->membase, ERG_DPRAM_PAGE_SIZE))) - return (-1); - - request_region(card->iobase + PCI9050_INTR_REG, 1, "HYSDN"); - request_region(card->iobase + PCI9050_USER_IO, 1, "HYSDN"); - ergo_stopcard(card); /* disable interrupts */ - if (request_irq(card->irq, ergo_interrupt, SA_SHIRQ, "HYSDN", card)) { - ergo_releasehardware(card); /* return the aquired hardware */ - return (-1); - } - /* success, now setup the function pointers */ - card->stopcard = ergo_stopcard; - card->releasehardware = ergo_releasehardware; - card->testram = ergo_testram; - card->writebootimg = ergo_writebootimg; - card->writebootseq = ergo_writebootseq; - card->waitpofready = ergo_waitpofready; - card->set_errlog_state = ergo_set_errlog_state; - card->irq_queue.next = 0; - card->irq_queue.sync = 0; - card->irq_queue.data = card; /* init task queue for interrupt */ - card->irq_queue.routine = (void *) (void *) ergo_irq_bh; - - return (0); -} /* ergo_inithardware */ diff --git a/drivers/isdn/hysdn/boardergo.h b/drivers/isdn/hysdn/boardergo.h deleted file mode 100644 index c27f37b7..00000000 --- a/drivers/isdn/hysdn/boardergo.h +++ /dev/null @@ -1,114 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, definitions for ergo type boards (buffers..). - * 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. - * - * $Log$ - * - */ - -#include - -/************************************************/ -/* defines for the dual port memory of the card */ -/************************************************/ -#define ERG_DPRAM_PAGE_SIZE 0x2000 /* DPRAM occupies a 8K page */ -#define BOOT_IMG_SIZE 4096 -#define ERG_DPRAM_FILL_SIZE (ERG_DPRAM_PAGE_SIZE - BOOT_IMG_SIZE) - -#define ERG_TO_HY_BUF_SIZE 0x0E00 /* 3072 bytes buffer size to card */ -#define ERG_TO_PC_BUF_SIZE 0x0E00 /* 3072 bytes to PC, too */ - -/* following DPRAM layout copied from OS2-driver boarderg.h */ -typedef struct ErgDpram_tag { -/*0000 */ uchar ToHyBuf[ERG_TO_HY_BUF_SIZE]; -/*0E00 */ uchar ToPcBuf[ERG_TO_PC_BUF_SIZE]; - - /*1C00 */ uchar bSoftUart[SIZE_RSV_SOFT_UART]; - /* size 0x1B0 */ - - /*1DB0 *//* tErrLogEntry */ uchar volatile ErrLogMsg[64]; - /* size 64 bytes */ - /*1DB0 ulong ulErrType; */ - /*1DB4 ulong ulErrSubtype; */ - /*1DB8 ulong ucTextSize; */ - /*1DB9 ulong ucText[ERRLOG_TEXT_SIZE]; *//* ASCIIZ of len ucTextSize-1 */ - /*1DF0 */ - -/*1DF0 */ word volatile ToHyChannel; -/*1DF2 */ word volatile ToHySize; - /*1DF4 */ uchar volatile ToHyFlag; - /* !=0: msg for Hy waiting */ - /*1DF5 */ uchar volatile ToPcFlag; - /* !=0: msg for PC waiting */ -/*1DF6 */ word volatile ToPcChannel; -/*1DF8 */ word volatile ToPcSize; - /*1DFA */ uchar bRes1DBA[0x1E00 - 0x1DFA]; - /* 6 bytes */ - -/*1E00 */ uchar bRestOfEntryTbl[0x1F00 - 0x1E00]; -/*1F00 */ ulong TrapTable[62]; - /*1FF8 */ uchar bRes1FF8[0x1FFB - 0x1FF8]; - /* low part of reset vetor */ -/*1FFB */ uchar ToPcIntMetro; - /* notes: - * - metro has 32-bit boot ram - accessing - * ToPcInt and ToHyInt would be the same; - * so we moved ToPcInt to 1FFB. - * Because on the PC side both vars are - * readonly (reseting on int from E1 to PC), - * we can read both vars on both cards - * without destroying anything. - * - 1FFB is the high byte of the reset vector, - * so E1 side should NOT change this byte - * when writing! - */ -/*1FFC */ uchar volatile ToHyNoDpramErrLog; - /* note: ToHyNoDpramErrLog is used to inform - * boot loader, not to use DPRAM based - * ErrLog; when DOS driver is rewritten - * this becomes obsolete - */ -/*1FFD */ uchar bRes1FFD; - /*1FFE */ uchar ToPcInt; - /* E1_intclear; on CHAMP2: E1_intset */ - /*1FFF */ uchar ToHyInt; - /* E1_intset; on CHAMP2: E1_intclear */ -} tErgDpram; - -/**********************************************/ -/* PCI9050 controller local register offsets: */ -/* copied from boarderg.c */ -/**********************************************/ -#define PCI9050_INTR_REG 0x4C /* Interrupt register */ -#define PCI9050_USER_IO 0x51 /* User I/O register */ - - /* bitmask for PCI9050_INTR_REG: */ -#define PCI9050_INTR_REG_EN1 0x01 /* 1= enable (def.), 0= disable */ -#define PCI9050_INTR_REG_POL1 0x02 /* 1= active high (def.), 0= active low */ -#define PCI9050_INTR_REG_STAT1 0x04 /* 1= intr. active, 0= intr. not active (def.) */ -#define PCI9050_INTR_REG_ENPCI 0x40 /* 1= PCI interrupts enable (def.) */ - - /* bitmask for PCI9050_USER_IO: */ -#define PCI9050_USER_IO_EN3 0x02 /* 1= disable , 0= enable (def.) */ -#define PCI9050_USER_IO_DIR3 0x04 /* 1= output (def.), 0= input */ -#define PCI9050_USER_IO_DAT3 0x08 /* 1= high (def.) , 0= low */ - -#define PCI9050_E1_RESET ( PCI9050_USER_IO_DIR3) /* 0x04 */ -#define PCI9050_E1_RUN (PCI9050_USER_IO_DAT3|PCI9050_USER_IO_DIR3) /* 0x0C */ diff --git a/drivers/isdn/hysdn/hysdn_boot.c b/drivers/isdn/hysdn/hysdn_boot.c deleted file mode 100644 index afddee18..00000000 --- a/drivers/isdn/hysdn/hysdn_boot.c +++ /dev/null @@ -1,417 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, specific routines for booting and pof handling. - * - * 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. - * - * $Log$ - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" -#include "hysdn_pof.h" - -/********************************/ -/* defines for pof read handler */ -/********************************/ -#define POF_READ_FILE_HEAD 0 -#define POF_READ_TAG_HEAD 1 -#define POF_READ_TAG_DATA 2 - -/************************************************************/ -/* definition of boot specific data area. This data is only */ -/* needed during boot and so allocated dynamically. */ -/************************************************************/ -struct boot_data { - word Cryptor; /* for use with Decrypt function */ - word Nrecs; /* records remaining in file */ - uchar pof_state; /* actual state of read handler */ - uchar is_crypted; /* card data is crypted */ - int BufSize; /* actual number of bytes bufferd */ - int last_error; /* last occured error */ - word pof_recid; /* actual pof recid */ - ulong pof_reclen; /* total length of pof record data */ - ulong pof_recoffset; /* actual offset inside pof record */ - union { - uchar BootBuf[BOOT_BUF_SIZE]; /* buffer as byte count */ - tPofRecHdr PofRecHdr; /* header for actual record/chunk */ - tPofFileHdr PofFileHdr; /* header from POF file */ - tPofTimeStamp PofTime; /* time information */ - } buf; -}; - -/*****************************************************/ -/* start decryption of sucessive POF file chuncks. */ -/* */ -/* to be called at start of POF file reading, */ -/* before starting any decryption on any POF record. */ -/*****************************************************/ -void -StartDecryption(struct boot_data *boot) -{ - boot->Cryptor = CRYPT_STARTTERM; -} /* StartDecryption */ - - -/***************************************************************/ -/* decrypt complete BootBuf */ -/* NOTE: decryption must be applied to all or none boot tags - */ -/* to HI and LO boot loader and (all) seq tags, because */ -/* global Cryptor is started for whole POF. */ -/***************************************************************/ -void -DecryptBuf(struct boot_data *boot, int cnt) -{ - uchar *bufp = boot->buf.BootBuf; - - while (cnt--) { - boot->Cryptor = (boot->Cryptor >> 1) ^ ((boot->Cryptor & 1U) ? CRYPT_FEEDTERM : 0); - *bufp++ ^= (uchar) boot->Cryptor; - } -} /* DecryptBuf */ - -/********************************************************************************/ -/* pof_handle_data executes the required actions dependant on the active record */ -/* id. If successfull 0 is returned, a negative value shows an error. */ -/********************************************************************************/ -static int -pof_handle_data(hysdn_card * card, int datlen) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - long l; - uchar *imgp; - int img_len; - - /* handle the different record types */ - switch (boot->pof_recid) { - - case TAG_TIMESTMP: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF created %s", boot->buf.PofTime.DateTimeText); - break; - - case TAG_CBOOTDTA: - DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ - case TAG_BOOTDTA: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", - (boot->pof_recid == TAG_CBOOTDTA) ? "CBOOTDATA" : "BOOTDTA", - datlen, boot->pof_recoffset); - - if (boot->pof_reclen != POF_BOOT_LOADER_TOTAL_SIZE) { - boot->last_error = EPOF_BAD_IMG_SIZE; /* invalid length */ - return (boot->last_error); - } - imgp = boot->buf.BootBuf; /* start of buffer */ - img_len = datlen; /* maximum length to transfer */ - - l = POF_BOOT_LOADER_OFF_IN_PAGE - - (boot->pof_recoffset & (POF_BOOT_LOADER_PAGE_SIZE - 1)); - if (l > 0) { - /* buffer needs to be truncated */ - imgp += l; /* advance pointer */ - img_len -= l; /* adjust len */ - } - /* at this point no special handling for data wrapping over buffer */ - /* is necessary, because the boot image always will be adjusted to */ - /* match a page boundary inside the buffer. */ - /* The buffer for the boot image on the card is filled in 2 cycles */ - /* first the 1024 hi-words are put in the buffer, then the low 1024 */ - /* word are handled in the same way with different offset. */ - - if (img_len > 0) { - /* data available for copy */ - if ((boot->last_error = - card->writebootimg(card, imgp, - (boot->pof_recoffset > POF_BOOT_LOADER_PAGE_SIZE) ? 2 : 0)) < 0) - return (boot->last_error); - } - break; /* end of case boot image hi/lo */ - - case TAG_CABSDATA: - DecryptBuf(boot, datlen); /* we need to encrypt the buffer */ - case TAG_ABSDATA: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got %s len=%d offs=0x%lx", - (boot->pof_recid == TAG_CABSDATA) ? "CABSDATA" : "ABSDATA", - datlen, boot->pof_recoffset); - - 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) - return (card->waitpofready(card)); /* data completely spooled, wait for ready */ - - break; /* end of case boot seq data */ - - default: - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF got data(id=0x%lx) len=%d offs=0x%lx", boot->pof_recid, - datlen, boot->pof_recoffset); - - break; /* simply skip record */ - } /* switch boot->pof_recid */ - - return (0); -} /* pof_handle_data */ - - -/******************************************************************************/ -/* pof_write_buffer is called when the buffer has been filled with the needed */ -/* number of data bytes. The number delivered is additionally supplied for */ -/* verification. The functions handles the data and returns the needed number */ -/* of bytes for the next action. If the returned value is 0 or less an error */ -/* occured and booting must be aborted. */ -/******************************************************************************/ -int -pof_write_buffer(hysdn_card * card, int datlen) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - - if (!boot) - return (-EFAULT); /* invalid call */ - if (boot->last_error < 0) - return (boot->last_error); /* repeated error */ - - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: got %d bytes ", datlen); - - switch (boot->pof_state) { - case POF_READ_FILE_HEAD: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: checking file header"); - - if (datlen != sizeof(tPofFileHdr)) { - boot->last_error = -EPOF_INTERNAL; - break; - } - if (boot->buf.PofFileHdr.Magic != TAGFILEMAGIC) { - boot->last_error = -EPOF_BAD_MAGIC; - break; - } - /* Setup the new state and vars */ - boot->Nrecs = (word) (boot->buf.PofFileHdr.N_PofRecs); /* limited to 65535 */ - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - break; - - case POF_READ_TAG_HEAD: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: checking tag header"); - - if (datlen != sizeof(tPofRecHdr)) { - boot->last_error = -EPOF_INTERNAL; - break; - } - boot->pof_recid = boot->buf.PofRecHdr.PofRecId; /* actual pof recid */ - boot->pof_reclen = boot->buf.PofRecHdr.PofRecDataLen; /* total length */ - boot->pof_recoffset = 0; /* no starting offset */ - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "POF: got record id=0x%lx length=%ld ", - boot->pof_recid, boot->pof_reclen); - - boot->pof_state = POF_READ_TAG_DATA; /* now start with tag data */ - if (boot->pof_reclen < BOOT_BUF_SIZE) - boot->last_error = boot->pof_reclen; /* limit size */ - else - boot->last_error = BOOT_BUF_SIZE; /* maximum */ - - if (!boot->last_error) { /* no data inside record */ - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - } - break; - - case POF_READ_TAG_DATA: - if (card->debug_flags & LOG_POF_WRITE) - hysdn_addlog(card, "POF write: getting tag data"); - - if (datlen != boot->last_error) { - boot->last_error = -EPOF_INTERNAL; - break; - } - if ((boot->last_error = pof_handle_data(card, datlen)) < 0) - return (boot->last_error); /* an error occured */ - - boot->pof_recoffset += datlen; - if (boot->pof_recoffset >= boot->pof_reclen) { - boot->pof_state = POF_READ_TAG_HEAD; /* now start with single tags */ - boot->last_error = sizeof(tPofRecHdr); /* new length */ - } else { - if (boot->pof_reclen - boot->pof_recoffset < BOOT_BUF_SIZE) - boot->last_error = boot->pof_reclen - boot->pof_recoffset; /* limit size */ - else - boot->last_error = BOOT_BUF_SIZE; /* maximum */ - } - break; - - default: - boot->last_error = -EPOF_INTERNAL; /* unknown state */ - break; - } /* switch (boot->pof_state) */ - - return (boot->last_error); -} /* pof_write_buffer */ - - -/*******************************************************************************/ -/* pof_write_open is called when an open for boot on the cardlog device occurs. */ -/* The function returns the needed number of bytes for the next operation. If */ -/* the returned number is less or equal 0 an error specified by this code */ -/* occurred. Additionally the pointer to the buffer data area is set on success */ -/*******************************************************************************/ -int -pof_write_open(hysdn_card * card, uchar ** bufp) -{ - struct boot_data *boot; /* pointer to boot specific data */ - - if (card->boot) { - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: already opened for boot"); - return (-ERR_ALREADY_BOOT); /* boot already active */ - } - /* error no mem available */ - if (!(boot = kmalloc(sizeof(struct boot_data), GFP_KERNEL))) { - if (card->debug_flags & LOG_MEM_ERR) - hysdn_addlog(card, "POF open: unable to allocate mem"); - return (-EFAULT); - } - card->boot = boot; - card->state = CARD_STATE_BOOTING; - memset(boot, 0, sizeof(struct boot_data)); - - card->stopcard(card); /* first stop the card */ - if (card->testram(card)) { - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: DPRAM test failure"); - boot->last_error = -ERR_BOARD_DPRAM; - card->state = CARD_STATE_BOOTERR; /* show boot error */ - return (boot->last_error); - } - boot->BufSize = 0; /* Buffer is empty */ - boot->pof_state = POF_READ_FILE_HEAD; /* read file header */ - StartDecryption(boot); /* if POF File should be encrypted */ - - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF open: success"); - - *bufp = boot->buf.BootBuf; /* point to buffer */ - return (sizeof(tPofFileHdr)); -} /* pof_write_open */ - -/********************************************************************************/ -/* pof_write_close is called when an close of boot on the cardlog device occurs. */ -/* The return value must be 0 if everything has happened as desired. */ -/********************************************************************************/ -int -pof_write_close(hysdn_card * card) -{ - struct boot_data *boot = card->boot; /* pointer to boot specific data */ - - if (!boot) - return (-EFAULT); /* invalid call */ - - card->boot = NULL; /* no boot active */ - kfree(boot); - - if (card->state == CARD_STATE_RUN) - card->set_errlog_state(card, 1); /* activate error log */ - - if (card->debug_flags & LOG_POF_OPEN) - hysdn_addlog(card, "POF close: success"); - - return (0); -} /* pof_write_close */ - -/*********************************************************************************/ -/* EvalSysrTokData checks additional records delivered with the Sysready Message */ -/* when POF has been booted. A return value of 0 is used if no error occured. */ -/*********************************************************************************/ -int -EvalSysrTokData(hysdn_card * card, uchar * cp, int len) -{ - u_char *p; - u_char crc; - - if (card->debug_flags & LOG_POF_RECORD) - hysdn_addlog(card, "SysReady Token data length %d", len); - - if (len < 2) { - hysdn_addlog(card, "SysReady Token Data to short"); - return (1); - } - for (p = cp, crc = 0; p < (cp + len - 2); p++) - if ((crc & 0x80)) - crc = (((u_char) (crc << 1)) + 1) + *p; - else - crc = ((u_char) (crc << 1)) + *p; - crc = ~crc; - if (crc != *(cp + len - 1)) { - hysdn_addlog(card, "SysReady Token Data invalid CRC"); - return (1); - } - len--; /* dont check CRC byte */ - while (len > 0) { - - if (*cp == SYSR_TOK_END) - return (0); /* End of Token stream */ - - if (len < (*(cp + 1) + 2)) { - hysdn_addlog(card, "token 0x%x invalid length %d", *cp, *(cp + 1)); - return (1); - } - switch (*cp) { - case SYSR_TOK_B_CHAN: /* 1 */ - if (*(cp + 1) != 1) - return (1); /* length invalid */ - card->bchans = *(cp + 2); - break; - - case SYSR_TOK_FAX_CHAN: /* 2 */ - if (*(cp + 1) != 1) - return (1); /* length invalid */ - card->faxchans = *(cp + 2); - break; - - case SYSR_TOK_MAC_ADDR: /* 3 */ - if (*(cp + 1) != 6) - return (1); /* length invalid */ - memcpy(card->mac_addr, cp + 2, 6); - break; - - default: - hysdn_addlog(card, "unknown token 0x%02x length %d", *cp, *(cp + 1)); - break; - } - len -= (*(cp + 1) + 2); /* adjust len */ - cp += (*(cp + 1) + 2); /* and pointer */ - } - - hysdn_addlog(card, "no end token found"); - return (1); -} /* EvalSysrTokData */ diff --git a/drivers/isdn/hysdn/hysdn_defs.h b/drivers/isdn/hysdn/hysdn_defs.h deleted file mode 100644 index fd9973f8..00000000 --- a/drivers/isdn/hysdn/hysdn_defs.h +++ /dev/null @@ -1,226 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, global definitions and exported vars and functions. - * 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. - * - * $Log$ - * - */ - -#include -#include -#include -#include -#include - -/****************************/ -/* storage type definitions */ -/****************************/ -#define uchar unsigned char -#define uint unsigned int -#define ulong unsigned long -#define word unsigned short - -#include "ince1pc.h" - -/************************************************/ -/* constants and bits for debugging/log outputs */ -/************************************************/ -#define LOG_MAX_LINELEN 120 -#define DEB_OUT_SYSLOG 0x80000000 /* output to syslog instead of proc fs */ -#define LOG_MEM_ERR 0x00000001 /* log memory errors like kmalloc failure */ -#define LOG_POF_OPEN 0x00000010 /* log pof open and close activities */ -#define LOG_POF_RECORD 0x00000020 /* log pof record parser */ -#define LOG_POF_WRITE 0x00000040 /* log detailed pof write operation */ -#define LOG_POF_CARD 0x00000080 /* log pof related card functions */ -#define LOG_CNF_LINE 0x00000100 /* all conf lines are put to procfs */ -#define LOG_CNF_DATA 0x00000200 /* non comment conf lines are shown with channel */ -#define LOG_CNF_MISC 0x00000400 /* additional conf line debug outputs */ -#define LOG_SCHED_ASYN 0x00001000 /* debug schedulers async tx routines */ -#define LOG_PROC_OPEN 0x00100000 /* open and close from procfs are logged */ -#define LOG_PROC_ALL 0x00200000 /* all actions from procfs are logged */ -#define LOG_NET_INIT 0x00010000 /* network init and deinit logging */ - -#define DEF_DEB_FLAGS 0x7fff000f /* everything is logged to procfs */ - -/**********************************/ -/* proc filesystem name constants */ -/**********************************/ -#define PROC_SUBDIR_NAME "hysdn" -#define PROC_CONF_BASENAME "cardconf" -#define PROC_LOG_BASENAME "cardlog" - -/************************/ -/* PCI constant defines */ -/************************/ -#define PCI_VENDOR_ID_HYPERCOPE 0x1365 -#define PCI_DEVICE_ID_PLX 0x9050 /* all DPRAM cards use the same id */ - -/*****************************/ -/* sub ids determining cards */ -/*****************************/ -#define PCI_SUB_ID_OLD_ERGO 0x0104 -#define PCI_SUB_ID_ERGO 0x0106 -#define PCI_SUB_ID_METRO 0x0107 -#define PCI_SUB_ID_CHAMP2 0x0108 -#define PCI_SUB_ID_PLEXUS 0x0109 - -/***********************************/ -/* PCI 32 bit parms for IO and MEM */ -/***********************************/ -#define PCI_REG_PLX_MEM_BASE 0 -#define PCI_REG_PLX_IO_BASE 1 -#define PCI_REG_MEMORY_BASE 3 - -/**************/ -/* card types */ -/**************/ -#define BD_NONE 0U -#define BD_PERFORMANCE 1U -#define BD_VALUE 2U -#define BD_PCCARD 3U -#define BD_ERGO 4U -#define BD_METRO 5U -#define BD_CHAMP2 6U -#define BD_PLEXUS 7U - -/******************************************************/ -/* defined states for cards shown by reading cardconf */ -/******************************************************/ -#define CARD_STATE_UNUSED 0 /* never been used or booted */ -#define CARD_STATE_BOOTING 1 /* booting is in progress */ -#define CARD_STATE_BOOTERR 2 /* a previous boot was aborted */ -#define CARD_STATE_RUN 3 /* card is active */ - -/*******************************/ -/* defines for error_log_state */ -/*******************************/ -#define ERRLOG_STATE_OFF 0 /* error log is switched off, nothing to do */ -#define ERRLOG_STATE_ON 1 /* error log is switched on, wait for data */ -#define ERRLOG_STATE_START 2 /* start error logging */ -#define ERRLOG_STATE_STOP 3 /* stop error logging */ - -/*******************************/ -/* data structure for one card */ -/*******************************/ -typedef struct HYSDN_CARD { - - /* general variables for the cards */ - int myid; /* own driver card id */ - uchar bus; /* pci bus the card is connected to */ - uchar devfn; /* slot+function bit encoded */ - word subsysid; /* PCI subsystem id */ - uchar brdtype; /* type of card */ - uint bchans; /* number of available B-channels */ - uint faxchans; /* number of available fax-channels */ - uchar mac_addr[6]; /* MAC Address read from card */ - uint irq; /* interrupt number */ - uint iobase; /* IO-port base address */ - ulong plxbase; /* PLX memory base */ - ulong membase; /* DPRAM memory base */ - ulong memend; /* DPRAM memory end */ - void *dpram; /* mapped dpram */ - int state; /* actual state of card -> CARD_STATE_** */ - struct HYSDN_CARD *next; /* pointer to next card */ - - /* data areas for the /proc file system */ - void *proclog; /* pointer to proclog filesystem specific data */ - void *procconf; /* pointer to procconf filesystem specific data */ - - /* debugging and logging */ - uchar err_log_state; /* actual error log state of the card */ - ulong debug_flags; /* tells what should be debugged and where */ - void (*set_errlog_state) (struct HYSDN_CARD *, int); - - /* interrupt handler + interrupt synchronisation */ - 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 */ - - /* boot process */ - void *boot; /* pointer to boot private data */ - int (*writebootimg) (struct HYSDN_CARD *, uchar *, ulong); - int (*writebootseq) (struct HYSDN_CARD *, uchar *, int); - int (*waitpofready) (struct HYSDN_CARD *); - int (*testram) (struct HYSDN_CARD *); - - /* scheduler for data transfer (only async parts) */ - uchar async_data[256]; /* async data to be sent (normally for config) */ - word volatile async_len; /* length of data to sent */ - word volatile async_channel; /* channel number for async transfer */ - int volatile async_busy; /* flag != 0 sending in progress */ - int volatile net_tx_busy; /* a network packet tx is in progress */ - - /* network interface */ - void *netif; /* pointer to network structure */ - - /* init and deinit stopcard for booting, too */ - void (*stopcard) (struct HYSDN_CARD *); - void (*releasehardware) (struct HYSDN_CARD *); -} hysdn_card; - - -/*****************/ -/* exported vars */ -/*****************/ -extern int cardmax; /* number of found cards */ -extern hysdn_card *card_root; /* pointer to first card */ - - - -/*************************/ -/* im/exported functions */ -/*************************/ -extern int printk(const char *fmt,...); -extern char *hysdn_getrev(const char *); - -/* hysdn_procconf.c */ -extern int hysdn_procconf_init(void); /* init proc config filesys */ -extern void hysdn_procconf_release(void); /* deinit proc config filesys */ - -/* hysdn_proclog.c */ -extern int hysdn_proclog_init(hysdn_card *); /* init proc log entry */ -extern void hysdn_proclog_release(hysdn_card *); /* deinit proc log entry */ -extern void put_log_buffer(hysdn_card *, char *); /* output log data */ -extern void hysdn_addlog(hysdn_card *, char *,...); /* output data to log */ -extern void hysdn_card_errlog(hysdn_card *, tErrLogEntry *, int); /* output card log */ - -/* boardergo.c */ -extern int ergo_inithardware(hysdn_card * card); /* get hardware -> module init */ - -/* hysdn_boot.c */ -extern int pof_write_close(hysdn_card *); /* close proc file after writing pof */ -extern int pof_write_open(hysdn_card *, uchar **); /* open proc file for writing pof */ -extern int pof_write_buffer(hysdn_card *, int); /* write boot data to card */ -extern int EvalSysrTokData(hysdn_card *, uchar *, int); /* Check Sysready Token Data */ - -/* hysdn_sched.c */ -extern int hysdn_sched_tx(hysdn_card *, uchar *, word volatile *, word volatile *, - word); -extern int hysdn_sched_rx(hysdn_card *, uchar *, word, word); -extern int hysdn_tx_cfgline(hysdn_card *, uchar *, word); /* send one cfg line */ - -/* hysdn_net.c */ -extern char *hysdn_net_revision; -extern int hysdn_net_create(hysdn_card *); /* create a new net device */ -extern int hysdn_net_release(hysdn_card *); /* delete the device */ -extern char *hysdn_net_getname(hysdn_card *); /* get name of net interface */ -extern void hysdn_tx_netack(hysdn_card *); /* acknowledge a packet tx */ -extern struct sk_buff *hysdn_tx_netget(hysdn_card *); /* get next network packet */ -extern void hysdn_rx_netpkt(hysdn_card *, uchar *, word); /* rxed packet from network */ diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c deleted file mode 100644 index b6907515..00000000 --- a/drivers/isdn/hysdn/hysdn_init.c +++ /dev/null @@ -1,239 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, init functions. - * 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. - * - * $Log$ - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -static char *hysdn_init_revision = "$Revision$"; -int cardmax; /* number of found cards */ -hysdn_card *card_root = NULL; /* pointer to first card */ - -/**********************************************/ -/* table assigning PCI-sub ids to board types */ -/* the last entry contains all 0 */ -/**********************************************/ -static struct { - word subid; /* PCI sub id */ - uchar cardtyp; /* card type assigned */ -} pci_subid_map[] = { - - { - PCI_SUB_ID_METRO, BD_METRO - }, - { - PCI_SUB_ID_CHAMP2, BD_CHAMP2 - }, - { - PCI_SUB_ID_ERGO, BD_ERGO - }, - { - PCI_SUB_ID_OLD_ERGO, BD_ERGO - }, - { - 0, 0 - } /* terminating entry */ -}; - -/*********************************************************************/ -/* search_cards searches for available cards in the pci config data. */ -/* If a card is found, the card structure is allocated and the cards */ -/* ressources are reserved. cardmax is incremented. */ -/*********************************************************************/ -static void -search_cards(void) -{ - struct pci_dev *akt_pcidev = NULL; - hysdn_card *card, *card_last; - uchar irq; - int i; - - card_root = NULL; - card_last = NULL; - while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_PLX, - akt_pcidev)) != NULL) { - - if (!(card = kmalloc(sizeof(hysdn_card), GFP_KERNEL))) { - printk(KERN_ERR "HYSDN: unable to alloc device mem \n"); - return; - } - memset(card, 0, sizeof(hysdn_card)); - card->myid = cardmax; /* set own id */ - card->bus = akt_pcidev->bus->number; - card->devfn = akt_pcidev->devfn; /* slot + function */ - pcibios_read_config_word(card->bus, card->devfn, PCI_SUBSYSTEM_ID, &card->subsysid); - pcibios_read_config_byte(card->bus, card->devfn, PCI_INTERRUPT_LINE, &irq); - card->irq = irq; - card->iobase = get_pcibase(akt_pcidev, PCI_REG_PLX_IO_BASE) & PCI_BASE_ADDRESS_IO_MASK; - card->plxbase = get_pcibase(akt_pcidev, PCI_REG_PLX_MEM_BASE); - card->membase = get_pcibase(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 */ - card->bchans = 2; /* and 2 b-channels */ - for (i = 0; pci_subid_map[i].subid; i++) - if (pci_subid_map[i].subid == card->subsysid) { - card->brdtype = pci_subid_map[i].cardtyp; - break; - } - if (card->brdtype != BD_NONE) { - if (ergo_inithardware(card)) { - printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase); - kfree(card); - continue; - } - } else { - printk(KERN_WARNING "HYSDN: unknown card id 0x%04x\n", card->subsysid); - kfree(card); /* release mem */ - continue; - } - cardmax++; - card->next = NULL; /*end of chain */ - if (card_last) - card_last->next = card; /* pointer to next card */ - else - card_root = card; - card_last = card; /* new chain end */ - } /* device found */ -} /* search_cards */ - -/************************************************************************************/ -/* free_resources frees the acquired PCI resources and returns the allocated memory */ -/************************************************************************************/ -static void -free_resources(void) -{ - hysdn_card *card; - - while (card_root) { - card = card_root; - if (card->releasehardware) - card->releasehardware(card); /* free all hardware resources */ - card_root = card_root->next; /* remove card from chain */ - kfree(card); /* return mem */ - - } /* while card_root */ -} /* free_resources */ - -/**************************************************************************/ -/* stop_cards disables (hardware resets) all cards and disables interrupt */ -/**************************************************************************/ -static void -stop_cards(void) -{ - hysdn_card *card; - - card = card_root; /* first in chain */ - while (card) { - if (card->stopcard) - card->stopcard(card); - card = card->next; /* remove card from chain */ - } /* while card */ -} /* stop_cards */ - - -/****************************************************************************/ -/* The module startup and shutdown code. Only compiled when used as module. */ -/* Using the driver as module is always advisable, because the booting */ -/* image becomes smaller and the driver code is only loaded when needed. */ -/* Additionally newer versions may be activated without rebooting. */ -/****************************************************************************/ -#ifdef CONFIG_MODULES - -/******************************************************/ -/* extract revision number from string for log output */ -/******************************************************/ -char * -hysdn_getrev(const char *revision) -{ - char *rev; - char *p; - - if ((p = strchr(revision, ':'))) { - rev = p + 2; - p = strchr(rev, '$'); - *--p = 0; - } else - rev = "???"; - return rev; -} - - -/****************************************************************************/ -/* init_module is called once when the module is loaded to do all necessary */ -/* things like autodetect... */ -/* If the return value of this function is 0 the init has been successfull */ -/* and the module is added to the list in /proc/modules, otherwise an error */ -/* is assumed and the module will not be kept in memory. */ -/****************************************************************************/ -int -init_module(void) -{ - char tmp[50]; - - strcpy(tmp, hysdn_init_revision); - printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp)); - strcpy(tmp, hysdn_net_revision); - printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp)); - if (!pci_present()) { - printk(KERN_ERR "HYSDN: no PCI bus present, module not loaded\n"); - return (-1); - } - search_cards(); - printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax); - - if (hysdn_procconf_init()) { - free_resources(); /* proc file_sys not created */ - return (-1); - } - return (0); /* no error */ -} /* init_module */ - - -/***********************************************************************/ -/* cleanup_module is called when the module is released by the kernel. */ -/* The routine is only called if init_module has been successfull and */ -/* the module counter has a value of 0. Otherwise this function will */ -/* not be called. This function must release all resources still allo- */ -/* cated as after the return from this function the module code will */ -/* be removed from memory. */ -/***********************************************************************/ -void -cleanup_module(void) -{ - - stop_cards(); - hysdn_procconf_release(); - free_resources(); - printk(KERN_NOTICE "HYSDN: module unloaded\n"); -} /* cleanup_module */ - -#endif /* CONFIG_MODULES */ diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c deleted file mode 100644 index d0c336ee..00000000 --- a/drivers/isdn/hysdn/hysdn_net.c +++ /dev/null @@ -1,462 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, net (ethernet type) handling routines. - * - * written by Werner Cornelius (werner@titro.de) for Hypercope GmbH - * - * Copyright 1999 by Werner Cornelius (werner@titro.de) - * - * This net module has been inspired by the skeleton driver from - * Donald Becker (becker@CESDIS.gsfc.nasa.gov) - * - * 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. - * - * $Log$ - * Revision 1.2 2000/02/13 17:32:19 werner - * - * Added support for new network layer of 2.3.43 and 44 kernels and tested driver. - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -/* store the actual version for log reporting */ -char *hysdn_net_revision = "$Revision$"; - -#define MAX_SKB_BUFFERS 20 /* number of buffers for keeping TX-data */ - -/****************************************************************************/ -/* structure containing the complete network data. The structure is aligned */ -/* in a way that both, the device and statistics are kept inside it. */ -/* for proper access, the device structure MUST be the first var/struct */ -/* inside the definition. */ -/****************************************************************************/ -struct net_local { - struct net_device netdev; /* the network device */ - struct net_device_stats stats; - /* 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 - * by this lock as well. - */ - spinlock_t lock; - struct sk_buff *skbs[MAX_SKB_BUFFERS]; /* pointers to tx-skbs */ - int in_idx, out_idx; /* indexes to buffer ring */ - int sk_count; /* number of buffers currently in ring */ - - int is_open; /* flag controlling module locking */ -#endif -}; /* net_local */ - - -/*****************************************************/ -/* Get the current statistics for this card. */ -/* This may be called with the card open or closed ! */ -/*****************************************************/ -static struct net_device_stats * -net_get_stats(struct net_device *dev) -{ - return (&((struct net_local *) dev)->stats); -} /* net_device_stats */ - -/*********************************************************************/ -/* Open/initialize the board. This is called (in the current kernel) */ -/* sometime after booting when the 'ifconfig' program is run. */ -/* This routine should set everything up anew at each open, even */ -/* registers that "should" only need to be set once at boot, so that */ -/* there is non-reboot way to recover if something goes wrong. */ -/*********************************************************************/ -static int -net_open(struct net_device *dev) -{ - struct in_device *in_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]) { - for (i = 0; i < ETH_ALEN - sizeof(ulong); i++) - dev->dev_addr[i] = 0xfc; - if ((in_dev = dev->ip_ptr) != NULL) { - struct in_ifaddr *ifa = in_dev->ifa_list; - if (ifa != NULL) - memcpy(dev->dev_addr + (ETH_ALEN - sizeof(ulong)), &ifa->ifa_local, sizeof(ulong)); - } - } else - memcpy(dev->dev_addr, card->mac_addr, ETH_ALEN); - - return (0); -} /* net_open */ - -#ifndef COMPAT_NO_SOFTNET -/*******************************************/ -/* flush the currently occupied tx-buffers */ -/* must only be called when device closed */ -/*******************************************/ -static void -flush_tx_buffers(struct net_local *nl) -{ - - while (nl->sk_count) { - dev_kfree_skb(nl->skbs[nl->out_idx++]); /* free skb */ - if (nl->out_idx >= MAX_SKB_BUFFERS) - nl->out_idx = 0; /* wrap around */ - nl->sk_count--; - } -} /* flush_tx_buffers */ -#endif - - -/*********************************************************************/ -/* close/decativate the device. The device is not removed, but only */ -/* deactivated. */ -/*********************************************************************/ -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) - MOD_DEC_USE_COUNT; /* adjust module counter */ - ((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 */ -/************************************/ -static int -net_send_packet(struct sk_buff *skb, struct net_device *dev) -{ - struct net_local *lp = (struct net_local *) dev; - - spin_lock_irq(&lp->lock); - - lp->skbs[lp->in_idx++] = skb; /* add to buffer list */ - if (lp->in_idx >= MAX_SKB_BUFFERS) - lp->in_idx = 0; /* wrap around */ - lp->sk_count++; /* adjust counter */ - dev->trans_start = jiffies; - - /* If we just used up the very last entry in the - * TX ring on this device, tell the queueing - * layer to send no more. - */ - if (lp->sk_count >= MAX_SKB_BUFFERS) - netif_stop_queue(dev); - - /* When the TX completion hw interrupt arrives, this - * is when the transmit statistics are updated. - */ - - spin_unlock_irq(&lp->lock); - - if (lp->sk_count <= 3) { - queue_task(&((hysdn_card *) dev->priv)->irq_queue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - } - return (0); /* success */ -} /* net_send_packet */ - -#endif - - -/***********************************************************************/ -/* acknowlegde a packet send. The network layer will be informed about */ -/* completion */ -/***********************************************************************/ -void -hysdn_tx_netack(hysdn_card * card) -{ - struct net_local *lp = card->netif; - - 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 */ - - lp->stats.tx_packets++; - lp->stats.tx_bytes += lp->skbs[lp->out_idx]->len; - - dev_kfree_skb(lp->skbs[lp->out_idx++]); /* free skb */ - if (lp->out_idx >= MAX_SKB_BUFFERS) - lp->out_idx = 0; /* wrap around */ - - if (lp->sk_count-- == MAX_SKB_BUFFERS) /* dec usage count */ - netif_start_queue((struct net_device *) lp); -#endif -} /* hysdn_tx_netack */ - -/*****************************************************/ -/* we got a packet from the network, go and queue it */ -/*****************************************************/ -void -hysdn_rx_netpkt(hysdn_card * card, uchar * buf, word len) -{ - struct net_local *lp = card->netif; - struct sk_buff *skb; - - if (!lp) - return; /* non existing device */ - - lp->stats.rx_bytes += len; - - skb = dev_alloc_skb(len); - if (skb == NULL) { - printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n", - lp->netdev.name); - lp->stats.rx_dropped++; - return; - } - skb->dev = &lp->netdev; - - /* copy the data */ - memcpy(skb_put(skb, len), buf, len); - - /* determine the used protocol */ - skb->protocol = eth_type_trans(skb, &lp->netdev); - - netif_rx(skb); - lp->stats.rx_packets++; /* adjust packet count */ - -} /* hysdn_rx_netpkt */ - -/*****************************************************/ -/* return the pointer to a network packet to be send */ -/*****************************************************/ -struct sk_buff * -hysdn_tx_netget(hysdn_card * card) -{ - struct net_local *lp = card->netif; - - 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 */ - - -/*******************************************/ -/* init function called by register device */ -/*******************************************/ -static int -net_init(struct net_device *dev) -{ - /* setup the function table */ - dev->open = net_open; - dev->stop = net_close; - dev->hard_start_xmit = net_send_packet; - dev->get_stats = net_get_stats; - - /* Fill in the fields of the device structure with ethernet values. */ - ether_setup(dev); - - return (0); /* success */ -} /* net_init */ - -/*****************************************************************************/ -/* hysdn_net_create creates a new net device for the given card. If a device */ -/* already exists, it will be deleted and created a new one. The return value */ -/* 0 announces success, else a negative error code will be returned. */ -/*****************************************************************************/ -int -hysdn_net_create(hysdn_card * card) -{ - struct net_device *dev; - int i; - - hysdn_net_release(card); /* release an existing net device */ - if ((dev = kmalloc(sizeof(struct net_local), GFP_KERNEL)) == NULL) { - printk(KERN_WARNING "HYSDN: unable to allocate mem\n"); - if (card->debug_flags & LOG_NET_INIT) - return (-ENOMEM); - } - 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 */ - dev->name = ((struct net_local *) dev)->dev_name; /* device name */ - if ((i = register_netdev(dev))) { - printk(KERN_WARNING "HYSDN: unable to create network device\n"); - kfree(dev); - return (i); - } - dev->priv = card; /* remember pointer to own data structure */ - card->netif = dev; /* setup the local pointer */ - - if (card->debug_flags & LOG_NET_INIT) - hysdn_addlog(card, "network device created"); - return (0); /* and return success */ -} /* hysdn_net_create */ - -/***************************************************************************/ -/* hysdn_net_release deletes the net device for the given card. The return */ -/* value 0 announces success, else a negative error code will be returned. */ -/***************************************************************************/ -int -hysdn_net_release(hysdn_card * card) -{ - struct net_device *dev = card->netif; - - if (!dev) - return (0); /* non existing */ - - 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 */ - if (card->debug_flags & LOG_NET_INIT) - hysdn_addlog(card, "network device deleted"); - - return (0); /* always successfull */ -} /* hysdn_net_release */ - -/*****************************************************************************/ -/* hysdn_net_getname returns a pointer to the name of the network interface. */ -/* if the interface is not existing, a "-" is returned. */ -/*****************************************************************************/ -char * -hysdn_net_getname(hysdn_card * card) -{ - struct net_device *dev = card->netif; - - if (!dev) - return ("-"); /* non existing */ - - return (dev->name); -} /* hysdn_net_getname */ diff --git a/drivers/isdn/hysdn/hysdn_pof.h b/drivers/isdn/hysdn/hysdn_pof.h deleted file mode 100644 index 983565bc..00000000 --- a/drivers/isdn/hysdn/hysdn_pof.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, definitions used for handling pof-files. - * 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. - * - * $Log$ - * - */ - -/************************/ -/* POF specific defines */ -/************************/ -#define BOOT_BUF_SIZE 0x1000 /* =4096, maybe moved to other h file */ -#define CRYPT_FEEDTERM 0x8142 -#define CRYPT_STARTTERM 0x81a5 - /* max. timeout time in seconds - * from end of booting to POF is ready - */ -#define POF_READY_TIME_OUT_SEC 10 - -/**********************************/ -/* defines for 1.stage boot image */ -/**********************************/ - -/* the POF file record containing the boot loader image - * has 2 pages a 16KB: - * 1. page contains the high 16-bit part of the 32-bit E1 words - * 2. page contains the low 16-bit part of the 32-bit E1 words - * - * In each 16KB page we assume the start of the boot loader code - * in the highest 2KB part (at offset 0x3800); - * the rest (0x0000..0x37FF) is assumed to contain 0 bytes. - */ - -#define POF_BOOT_LOADER_PAGE_SIZE 0x4000 /* =16384U */ -#define POF_BOOT_LOADER_TOTAL_SIZE (2U*POF_BOOT_LOADER_PAGE_SIZE) - -#define POF_BOOT_LOADER_CODE_SIZE 0x0800 /* =2KB =2048U */ - - /* offset in boot page, where loader code may start */ - /* =0x3800= 14336U */ -#define POF_BOOT_LOADER_OFF_IN_PAGE (POF_BOOT_LOADER_PAGE_SIZE-POF_BOOT_LOADER_CODE_SIZE) - - -/*--------------------------------------POF file record structs------------*/ -typedef struct PofFileHdr_tag { /* Pof file header */ -/*00 */ ulong Magic __attribute__((packed)); -/*04 */ ulong N_PofRecs __attribute__((packed)); -/*08 */ -} tPofFileHdr; - -typedef struct PofRecHdr_tag { /* Pof record header */ -/*00 */ word PofRecId __attribute__((packed)); -/*02 */ ulong PofRecDataLen __attribute__((packed)); -/*06 */ -} tPofRecHdr; - -typedef struct PofTimeStamp_tag { -/*00 */ ulong UnixTime __attribute__((packed)); - /*04 */ uchar DateTimeText[0x28] __attribute__((packed)); - /* =40 */ -/*2C */ -} tPofTimeStamp; - - /* tPofFileHdr.Magic value: */ -#define TAGFILEMAGIC 0x464F501AUL - /* tPofRecHdr.PofRecId values: */ -#define TAG_ABSDATA 0x1000 /* abs. data */ -#define TAG_BOOTDTA 0x1001 /* boot data */ -#define TAG_COMMENT 0x0020 -#define TAG_SYSCALL 0x0021 -#define TAG_FLOWCTRL 0x0022 -#define TAG_TIMESTMP 0x0010 /* date/time stamp of version */ -#define TAG_CABSDATA 0x1100 /* crypted abs. data */ -#define TAG_CBOOTDTA 0x1101 /* crypted boot data */ diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c deleted file mode 100644 index 6c44616f..00000000 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ /dev/null @@ -1,492 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, /proc/net filesystem dir and conf functions. - * 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. - * - * $Log$ - * Revision 1.2 2000/02/14 19:23:03 werner - * - * Changed handling of proc filesystem tables to a more portable version - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -static char *hysdn_procconf_revision = "$Revision$"; - -#define INFO_OUT_LEN 80 /* length of info line including lf */ - -/********************************************************/ -/* defines and data structure for conf write operations */ -/********************************************************/ -#define CONF_STATE_DETECT 0 /* waiting for detect */ -#define CONF_STATE_CONF 1 /* writing config data */ -#define CONF_STATE_POF 2 /* writing pof data */ -#define CONF_LINE_LEN 80 /* 80 chars max */ - -struct conf_writedata { - hysdn_card *card; /* card the device is connected to */ - int buf_size; /* actual number of bytes in the buffer */ - int needed_size; /* needed size when reading pof */ - int state; /* actual interface states from above constants */ - uchar conf_line[CONF_LINE_LEN]; /* buffered conf line */ - word channel; /* active channel number */ - uchar *pof_buffer; /* buffer when writing pof */ -}; - -/***********************************************************************/ -/* process_line parses one config line and transfers it to the card if */ -/* necessary. */ -/* if the return value is negative an error occured. */ -/***********************************************************************/ -static int -process_line(struct conf_writedata *cnf) -{ - uchar *cp = cnf->conf_line; - int i; - - if (cnf->card->debug_flags & LOG_CNF_LINE) - hysdn_addlog(cnf->card, "conf line: %s", cp); - - if (*cp == '-') { /* option */ - cp++; /* point to option char */ - - if (*cp++ != 'c') - return (0); /* option unknown or used */ - i = 0; /* start value for channel */ - while ((*cp <= '9') && (*cp >= '0')) - i = i * 10 + *cp++ - '0'; /* get decimal number */ - if (i > 65535) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "conf channel invalid %d", i); - return (-ERR_INV_CHAN); /* invalid channel */ - } - cnf->channel = i & 0xFFFF; /* set new channel number */ - return (0); /* success */ - } /* option */ - if (*cp == '*') { /* line to send */ - if (cnf->card->debug_flags & LOG_CNF_DATA) - hysdn_addlog(cnf->card, "conf chan=%d %s", cnf->channel, cp); - return (hysdn_tx_cfgline(cnf->card, cnf->conf_line + 1, - cnf->channel)); /* send the line without * */ - } /* line to send */ - return (0); -} /* process_line */ - -/*************************/ -/* dummy file operations */ -/*************************/ -static loff_t -hysdn_dummy_lseek(struct file *file, loff_t offset, int orig) -{ - return -ESPIPE; -} /* hysdn_dummy_lseek */ - -/***********************************/ -/* conf file operations and tables */ -/***********************************/ - -/****************************************************/ -/* write conf file -> boot or send cfg line to card */ -/****************************************************/ -static ssize_t -hysdn_conf_write(struct file *file, const char *buf, size_t count, loff_t * off) -{ - struct conf_writedata *cnf; - int i; - uchar ch, *cp; - - if (&file->f_pos != off) /* fs error check */ - return (-ESPIPE); - if (!count) - return (0); /* nothing to handle */ - - if (!(cnf = file->private_data)) - return (-EFAULT); /* should never happen */ - - if (cnf->state == CONF_STATE_DETECT) { /* auto detect cnf or pof data */ - if (copy_from_user(&ch, buf, 1)) /* get first char for detect */ - return (-EFAULT); - - if (ch == 0x1A) { - /* we detected a pof file */ - if ((cnf->needed_size = pof_write_open(cnf->card, &cnf->pof_buffer)) <= 0) - return (cnf->needed_size); /* an error occured -> exit */ - cnf->buf_size = 0; /* buffer is empty */ - cnf->state = CONF_STATE_POF; /* new state */ - } else { - /* conf data has been detected */ - cnf->buf_size = 0; /* buffer is empty */ - cnf->state = CONF_STATE_CONF; /* requested conf data write */ - if (cnf->card->state != CARD_STATE_RUN) - return (-ERR_NOT_BOOTED); - cnf->conf_line[CONF_LINE_LEN - 1] = 0; /* limit string length */ - cnf->channel = 4098; /* default channel for output */ - } - } /* state was auto detect */ - if (cnf->state == CONF_STATE_POF) { /* pof write active */ - i = cnf->needed_size - cnf->buf_size; /* bytes still missing for write */ - if (i <= 0) - return (-EINVAL); /* size error handling pof */ - - if (i < count) - count = i; /* limit requested number of bytes */ - if (copy_from_user(cnf->pof_buffer + cnf->buf_size, buf, count)) - return (-EFAULT); /* error while copying */ - cnf->buf_size += count; - - if (cnf->needed_size == cnf->buf_size) { - cnf->needed_size = pof_write_buffer(cnf->card, cnf->buf_size); /* write data */ - if (cnf->needed_size <= 0) { - cnf->card->state = CARD_STATE_BOOTERR; /* show boot error */ - return (cnf->needed_size); /* an error occured */ - } - cnf->buf_size = 0; /* buffer is empty again */ - } - } - /* pof write active */ - else { /* conf write active */ - - if (cnf->card->state != CARD_STATE_RUN) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf write denied -> not booted"); - return (-ERR_NOT_BOOTED); - } - i = (CONF_LINE_LEN - 1) - cnf->buf_size; /* bytes available in buffer */ - if (i > 0) { - /* copy remaining bytes into buffer */ - - if (count > i) - count = i; /* limit transfer */ - if (copy_from_user(cnf->conf_line + cnf->buf_size, buf, count)) - return (-EFAULT); /* error while copying */ - - i = count; /* number of chars in buffer */ - cp = cnf->conf_line + cnf->buf_size; - while (i) { - /* search for end of line */ - if ((*cp < ' ') && (*cp != 9)) - break; /* end of line found */ - cp++; - i--; - } /* search for end of line */ - - if (i) { - /* delimiter found */ - *cp++ = 0; /* string termination */ - count -= (i - 1); /* subtract remaining bytes from count */ - while ((i) && (*cp < ' ') && (*cp != 9)) { - i--; /* discard next char */ - count++; /* mark as read */ - cp++; /* next char */ - } - cnf->buf_size = 0; /* buffer is empty after transfer */ - if ((i = process_line(cnf)) < 0) /* handle the line */ - count = i; /* return the error */ - } - /* delimiter found */ - else { - cnf->buf_size += count; /* add chars to string */ - if (cnf->buf_size >= CONF_LINE_LEN - 1) { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf line too long %d chars pos %d", cnf->buf_size, count); - return (-ERR_CONF_LONG); - } - } /* not delimited */ - - } - /* copy remaining bytes into buffer */ - else { - if (cnf->card->debug_flags & LOG_CNF_MISC) - hysdn_addlog(cnf->card, "cnf line too long"); - return (-ERR_CONF_LONG); - } - } /* conf write active */ - - return (count); -} /* hysdn_conf_write */ - -/*******************************************/ -/* read conf file -> output card info data */ -/*******************************************/ -static ssize_t -hysdn_conf_read(struct file *file, char *buf, size_t count, loff_t * off) -{ - char *cp; - int i; - - if (off != &file->f_pos) /* fs error check */ - return -ESPIPE; - - 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 */ - -/******************/ -/* open conf file */ -/******************/ -static int -hysdn_conf_open(struct inode *ino, struct file *filep) -{ - hysdn_card *card; - struct proc_dir_entry *pd; - struct conf_writedata *cnf; - char *cp, *tmp; - - MOD_INC_USE_COUNT; /* lock module */ - - /* now search the addressed card */ - card = card_root; - while (card) { - pd = card->procconf; - if (pd->low_ino == (ino->i_ino & 0xFFFF)) - break; - card = card->next; /* search next entry */ - } - if (!card) { - MOD_DEC_USE_COUNT; /* unlock module */ - return (-ENODEV); /* device is unknown/invalid */ - } - if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) - hysdn_addlog(card, "config open for uid=%d gid=%d mode=0x%x", - filep->f_uid, filep->f_gid, filep->f_mode); - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write boot file or conf line */ - - if (!(cnf = kmalloc(sizeof(struct conf_writedata), GFP_KERNEL))) { - MOD_DEC_USE_COUNT; - return (-EFAULT); - } - cnf->card = card; - cnf->buf_size = 0; /* nothing buffered */ - cnf->state = CONF_STATE_DETECT; /* start auto detect */ - filep->private_data = cnf; - - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - /* read access -> output card info data */ - - if (!(tmp = (char *) kmalloc(INFO_OUT_LEN * 2 + 2, GFP_KERNEL))) { - MOD_DEC_USE_COUNT; - return (-EFAULT); /* out of memory */ - } - filep->private_data = tmp; /* start of string */ - - /* first output a headline */ - sprintf(tmp, "id bus slot type irq iobase dp-mem b-chans fax-chans state device"); - cp = tmp; /* start of string */ - while (*cp) - cp++; - while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) - *cp++ = ' '; - *cp++ = '\n'; - - /* and now the data */ - sprintf(cp, "%d %3d %4d %4d %3d 0x%04x 0x%08x %7d %9d %3d %s", - card->myid, - card->bus, - PCI_SLOT(card->devfn), - card->brdtype, - card->irq, - card->iobase, - card->membase, - card->bchans, - card->faxchans, - card->state, - hysdn_net_getname(card)); - while (*cp) - cp++; - while (((cp - tmp) % (INFO_OUT_LEN + 1)) != INFO_OUT_LEN) - *cp++ = ' '; - *cp++ = '\n'; - *cp = 0; /* end of string */ - } else { /* simultaneous read/write access forbidden ! */ - MOD_DEC_USE_COUNT; /* unlock module */ - return (-EPERM); /* no permission this time */ - } - return (0); -} /* hysdn_conf_open */ - -/***************************/ -/* close a config file. */ -/***************************/ -static int -hysdn_conf_close(struct inode *ino, struct file *filep) -{ - hysdn_card *card; - struct conf_writedata *cnf; - int retval = 0; - struct proc_dir_entry *pd; - - /* search the addressed card */ - card = card_root; - while (card) { - pd = card->procconf; - if (pd->low_ino == (ino->i_ino & 0xFFFF)) - break; - card = card->next; /* search next entry */ - } - if (!card) { - return (-ENODEV); /* device is unknown/invalid */ - } - if (card->debug_flags & (LOG_PROC_OPEN | LOG_PROC_ALL)) - hysdn_addlog(card, "config close for uid=%d gid=%d mode=0x%x", - filep->f_uid, filep->f_gid, filep->f_mode); - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write boot file or conf line */ - if (filep->private_data) { - cnf = filep->private_data; - - if (cnf->state == CONF_STATE_POF) - retval = pof_write_close(cnf->card); /* close the pof write */ - kfree(filep->private_data); /* free allocated memory for buffer */ - - } /* handle write private data */ - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - /* read access -> output card info data */ - - if (filep->private_data) - kfree(filep->private_data); /* release memory */ - } - MOD_DEC_USE_COUNT; /* reduce usage count */ - return (retval); -} /* hysdn_conf_close */ - -/******************************************************/ -/* table for conf filesystem functions defined above. */ -/******************************************************/ -static struct file_operations conf_fops = -{ - hysdn_dummy_lseek, - hysdn_conf_read, - hysdn_conf_write, - NULL, /* readdir */ - NULL, /* poll */ - NULL, /* ioctl */ - NULL, /* mmap */ - hysdn_conf_open, - NULL, /* flush */ - hysdn_conf_close, - NULL /* fsync */ -}; - -#ifdef COMPAT_NO_SOFTNET -static struct inode_operations conf_inode_operations; -#endif - -/*****************************/ -/* hysdn subdir in /proc/net */ -/*****************************/ -struct proc_dir_entry *hysdn_proc_entry = NULL; - -/*******************************************************************************/ -/* hysdn_procconf_init is called when the module is loaded and after the cards */ -/* have been detected. The needed proc dir and card config files are created. */ -/* The log init is called at last. */ -/*******************************************************************************/ -int -hysdn_procconf_init(void) -{ - hysdn_card *card; - uchar conf_name[20]; - - hysdn_proc_entry = create_proc_entry(PROC_SUBDIR_NAME, S_IFDIR | S_IRUGO | S_IXUGO, proc_net); - if (!hysdn_proc_entry) { - printk(KERN_ERR "HYSDN: unable to create hysdn subdir\n"); - return (-1); - } - card = card_root; /* point to first card */ - while (card) { - - sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); - 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; -#endif - hysdn_proclog_init(card); /* init the log file entry */ - } - card = card->next; /* next entry */ - } - - printk(KERN_NOTICE "HYSDN: procfs Rev. %s initialised\n", hysdn_getrev(hysdn_procconf_revision)); - return (0); -} /* hysdn_procconf_init */ - -/*************************************************************************************/ -/* hysdn_procconf_release is called when the module is unloaded and before the cards */ -/* resources are released. The module counter is assumed to be 0 ! */ -/*************************************************************************************/ -void -hysdn_procconf_release(void) -{ - hysdn_card *card; - uchar conf_name[20]; - - card = card_root; /* start with first card */ - while (card) { - - sprintf(conf_name, "%s%d", PROC_CONF_BASENAME, card->myid); - if (card->procconf) - remove_proc_entry(conf_name, hysdn_proc_entry); - - hysdn_proclog_release(card); /* init the log file entry */ - - card = card->next; /* point to next card */ - } - - remove_proc_entry(PROC_SUBDIR_NAME, proc_net); -} /* hysdn_procfs_release */ diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c deleted file mode 100644 index af445e6e..00000000 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ /dev/null @@ -1,495 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, /proc/net filesystem log functions. - * 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. - * - * $Log$ - * Revision 1.2 2000/02/14 19:23:03 werner - * - * Changed handling of proc filesystem tables to a more portable version - * - * Revision 1.1 2000/02/10 19:45:18 werner - * - * Initial release - * - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -static char *hysdn_proclog_revision = "$Revision$"; - -/* the proc subdir for the interface is defined in the procconf module */ -extern struct proc_dir_entry *hysdn_proc_entry; - -/*************************************************/ -/* structure keeping ascii log for device output */ -/*************************************************/ -struct log_data { - struct log_data *next; - ulong usage_cnt; /* number of files still to work */ - void *proc_ctrl; /* pointer to own control procdata structure */ - char log_start[2]; /* log string start (final len aligned by size) */ -}; - -/**********************************************/ -/* structure holding proc entrys for one card */ -/**********************************************/ -struct procdata { - struct proc_dir_entry *log; /* log entry */ - char log_name[15]; /* log filename */ - struct log_data *log_head, *log_tail; /* head and tail for queue */ - int if_used; /* open count for interface */ - int volatile del_lock; /* lock for delete operations */ - uchar logtmp[LOG_MAX_LINELEN]; -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t rd_queue; -#else - struct wait_queue *rd_queue; /* wait queue structure */ -#endif -}; - - -/**********************************************/ -/* log function for cards error log interface */ -/**********************************************/ -void -hysdn_card_errlog(hysdn_card * card, tErrLogEntry * logp, int maxsize) -{ - char buf[ERRLOG_TEXT_SIZE + 40]; - - sprintf(buf, "LOG 0x%08lX 0x%08lX : %s\n", logp->ulErrType, logp->ulErrSubtype, logp->ucText); - put_log_buffer(card, buf); /* output the string */ -} /* hysdn_card_errlog */ - -/***************************************************/ -/* Log function using format specifiers for output */ -/***************************************************/ -void -hysdn_addlog(hysdn_card * card, char *fmt,...) -{ - struct procdata *pd = card->proclog; - char *cp; - va_list args; - - if (!pd) - return; /* log structure non existent */ - - cp = pd->logtmp; - cp += sprintf(cp, "HYSDN: card %d ", card->myid); - - va_start(args, fmt); - cp += vsprintf(cp, fmt, args); - va_end(args); - *cp++ = '\n'; - *cp = 0; - - if (card->debug_flags & DEB_OUT_SYSLOG) - printk(KERN_INFO "%s", pd->logtmp); - else - put_log_buffer(card, pd->logtmp); - -} /* hysdn_addlog */ - -/********************************************/ -/* put an log buffer into the log queue. */ -/* This buffer will be kept until all files */ -/* opened for read got the contents. */ -/* Flushes buffers not longer in use. */ -/********************************************/ -void -put_log_buffer(hysdn_card * card, char *cp) -{ - struct log_data *ib; - struct procdata *pd = card->proclog; - int i, flags; - - if (!pd) - return; - if (!cp) - return; - if (!*cp) - return; - if (pd->if_used <= 0) - return; /* no open file for read */ - - if (!(ib = (struct log_data *) kmalloc(sizeof(struct log_data) + strlen(cp), GFP_ATOMIC))) - return; /* no memory */ - strcpy(ib->log_start, cp); /* set output string */ - ib->next = NULL; - ib->proc_ctrl = pd; /* point to own control structure */ - save_flags(flags); - cli(); - ib->usage_cnt = pd->if_used; - if (!pd->log_head) - pd->log_head = ib; /* new head */ - else - pd->log_tail->next = ib; /* follows existing messages */ - pd->log_tail = ib; /* new tail */ - i = pd->del_lock++; /* get lock state */ - restore_flags(flags); - - /* delete old entrys */ - if (!i) - while (pd->log_head->next) { - if ((pd->log_head->usage_cnt <= 0) && - (pd->log_head->next->usage_cnt <= 0)) { - ib = pd->log_head; - pd->log_head = pd->log_head->next; - kfree(ib); - } else - break; - } /* pd->log_head->next */ - pd->del_lock--; /* release lock level */ - wake_up_interruptible(&(pd->rd_queue)); /* announce new entry */ -} /* put_log_buffer */ - - -/*************************/ -/* dummy file operations */ -/*************************/ -static loff_t -hysdn_dummy_lseek(struct file *file, loff_t offset, int orig) -{ - return -ESPIPE; -} /* hysdn_dummy_lseek */ - -/******************************/ -/* file operations and tables */ -/******************************/ - -/****************************************/ -/* write log file -> set log level bits */ -/****************************************/ -static ssize_t -hysdn_log_write(struct file *file, const char *buf, size_t count, loff_t * off) -{ - ulong u = 0; - int found = 0; - uchar *cp, valbuf[128]; - long base = 10; - hysdn_card *card = (hysdn_card *) file->private_data; - - if (&file->f_pos != off) /* fs error check */ - return (-ESPIPE); - - if (count > (sizeof(valbuf) - 1)) - count = sizeof(valbuf) - 1; /* limit length */ - if (copy_from_user(valbuf, buf, count)) - return (-EFAULT); /* copy failed */ - - valbuf[count] = 0; /* terminating 0 */ - cp = valbuf; - if ((count > 2) && (valbuf[0] == '0') && (valbuf[1] == 'x')) { - cp += 2; /* pointer after hex modifier */ - base = 16; - } - /* scan the input for debug flags */ - while (*cp) { - if ((*cp >= '0') && (*cp <= '9')) { - found = 1; - u *= base; /* adjust to next digit */ - u += *cp++ - '0'; - continue; - } - if (base != 16) - break; /* end of number */ - - if ((*cp >= 'a') && (*cp <= 'f')) { - found = 1; - u *= base; /* adjust to next digit */ - u += *cp++ - 'a' + 10; - continue; - } - break; /* terminated */ - } - - if (found) { - card->debug_flags = u; /* remember debug flags */ - hysdn_addlog(card, "debug set to 0x%lx", card->debug_flags); - } - return (count); -} /* hysdn_log_write */ - -/******************/ -/* read log file */ -/******************/ -static ssize_t -hysdn_log_read(struct file *file, char *buf, size_t count, loff_t * off) -{ - struct log_data *inf; - int len; - word ino; - struct procdata *pd; - hysdn_card *card; - - if (!*((struct log_data **) file->private_data)) { - if (file->f_flags & O_NONBLOCK) - return (-EAGAIN); - - /* sorry, but we need to search the card */ - ino = file->f_dentry->d_inode->i_ino & 0xFFFF; /* low-ino */ - card = card_root; - while (card) { - pd = card->proclog; - if (pd->log->low_ino == ino) - break; - card = card->next; /* search next entry */ - } - if (card) - interruptible_sleep_on(&(pd->rd_queue)); - else - return (-EAGAIN); - - } - if (!(inf = *((struct log_data **) file->private_data))) - return (0); - - inf->usage_cnt--; /* new usage count */ - (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; - file->f_pos += len; - return (len); - } - return (0); -} /* hysdn_log_read */ - -/******************/ -/* open log file */ -/******************/ -static int -hysdn_log_open(struct inode *ino, struct file *filep) -{ - hysdn_card *card; - struct procdata *pd; - ulong flags; - - MOD_INC_USE_COUNT; /* lock module */ - card = card_root; - while (card) { - pd = card->proclog; - if (pd->log->low_ino == (ino->i_ino & 0xFFFF)) - break; - card = card->next; /* search next entry */ - } - if (!card) { - MOD_DEC_USE_COUNT; /* unlock module */ - return (-ENODEV); /* device is unknown/invalid */ - } - filep->private_data = card; /* remember our own card */ - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write log level only */ - } else if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) { - - /* read access -> log/debug read */ - save_flags(flags); - cli(); - pd->if_used++; - if (pd->log_head) - (struct log_data **) filep->private_data = &(pd->log_tail->next); - else - (struct log_data **) filep->private_data = &(pd->log_head); - restore_flags(flags); - } else { /* simultaneous read/write access forbidden ! */ - MOD_DEC_USE_COUNT; /* unlock module */ - return (-EPERM); /* no permission this time */ - } - return (0); -} /* hysdn_log_open */ - -/*******************************************************************************/ -/* close a cardlog file. If the file has been opened for exclusive write it is */ -/* assumed as pof data input and the pof loader is noticed about. */ -/* Otherwise file is handled as log output. In this case the interface usage */ -/* count is decremented and all buffers are noticed of closing. If this file */ -/* was the last one to be closed, all buffers are freed. */ -/*******************************************************************************/ -static int -hysdn_log_close(struct inode *ino, struct file *filep) -{ - struct log_data *inf; - struct procdata *pd; - hysdn_card *card; - int flags, retval = 0; - - - if ((filep->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) { - /* write only access -> write debug level written */ - retval = 0; /* success */ - } else { - /* read access -> log/debug read, mark one further file as closed */ - - pd = NULL; - save_flags(flags); - cli(); - inf = *((struct log_data **) filep->private_data); /* get first log entry */ - if (inf) - pd = (struct procdata *) inf->proc_ctrl; /* still entries there */ - else { - /* no info available -> search card */ - card = card_root; - while (card) { - pd = card->proclog; - if (pd->log->low_ino == (ino->i_ino & 0xFFFF)) - break; - card = card->next; /* search next entry */ - } - if (card) - pd = card->proclog; /* pointer to procfs log */ - } - if (pd) - pd->if_used--; /* decrement interface usage count by one */ - - while (inf) { - inf->usage_cnt--; /* decrement usage count for buffers */ - inf = inf->next; - } - restore_flags(flags); - - if (pd) - if (pd->if_used <= 0) /* delete buffers if last file closed */ - while (pd->log_head) { - inf = pd->log_head; - pd->log_head = pd->log_head->next; - kfree(inf); - } - } /* read access */ - - MOD_DEC_USE_COUNT; - return (retval); -} /* hysdn_log_close */ - -/*************************************************/ -/* select/poll routine to be able using select() */ -/*************************************************/ -static unsigned int -hysdn_log_poll(struct file *file, poll_table * wait) -{ - unsigned int mask = 0; - word ino; - hysdn_card *card; - struct procdata *pd; - - if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_WRITE) - return (mask); /* no polling for write supported */ - - /* we need to search the card */ - ino = file->f_dentry->d_inode->i_ino & 0xFFFF; /* low-ino */ - card = card_root; - while (card) { - pd = card->proclog; - if (pd->log->low_ino == ino) - break; - card = card->next; /* search next entry */ - } - if (!card) - return (mask); /* card not found */ - - poll_wait(file, &(pd->rd_queue), wait); - - if (*((struct log_data **) file->private_data)) - mask |= POLLIN | POLLRDNORM; - - return mask; -} /* hysdn_log_poll */ - -/**************************************************/ -/* table for log filesystem functions defined above. */ -/**************************************************/ -static struct file_operations log_fops = -{ - hysdn_dummy_lseek, - hysdn_log_read, - hysdn_log_write, - NULL, /* readdir */ - hysdn_log_poll, /* poll */ - NULL, - NULL, /* mmap */ - hysdn_log_open, - NULL, /* flush */ - hysdn_log_close, - NULL /* fsync */ -}; - -#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 */ -/* conf files. */ -/***********************************************************************************/ -int -hysdn_proclog_init(hysdn_card * card) -{ - struct procdata *pd; - - /* create a cardlog proc entry */ - - 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; -#endif - -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&(pd->rd_queue)); -#endif - - card->proclog = (void *) pd; /* remember procfs structure */ - } - return (0); -} /* hysdn_proclog_init */ - -/************************************************************************************/ -/* hysdn_proclog_release is called when the module is unloaded and before the cards */ -/* conf file is released */ -/* The module counter is assumed to be 0 ! */ -/************************************************************************************/ -void -hysdn_proclog_release(hysdn_card * card) -{ - struct procdata *pd; - - if ((pd = (struct procdata *) card->proclog) != NULL) { - if (pd->log) - remove_proc_entry(pd->log_name, hysdn_proc_entry); - kfree(pd); /* release memory */ - card->proclog = NULL; - } -} /* hysdn_proclog_release */ diff --git a/drivers/isdn/hysdn/hysdn_sched.c b/drivers/isdn/hysdn/hysdn_sched.c deleted file mode 100644 index e28379b4..00000000 --- a/drivers/isdn/hysdn/hysdn_sched.c +++ /dev/null @@ -1,199 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, scheduler routines for handling exchange card <-> pc. - * - * 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. - * - * $Log$ - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include - -#include "hysdn_defs.h" - -/*****************************************************************************/ -/* hysdn_sched_rx is called from the cards handler to announce new data is */ -/* available from the card. The routine has to handle the data and return */ -/* with a nonzero code if the data could be worked (or even thrown away), if */ -/* no room to buffer the data is available a zero return tells the card */ -/* to keep the data until later. */ -/*****************************************************************************/ -int -hysdn_sched_rx(hysdn_card * card, uchar * buf, word len, word chan) -{ - - switch (chan) { - case CHAN_NDIS_DATA: - hysdn_rx_netpkt(card, buf, len); /* give packet to network handler */ - break; - - case CHAN_ERRLOG: - hysdn_card_errlog(card, (tErrLogEntry *) buf, len); - if (card->err_log_state == ERRLOG_STATE_ON) - card->err_log_state = ERRLOG_STATE_START; /* start new fetch */ - break; - - default: - printk(KERN_INFO "irq message channel %d len %d unhandled \n", chan, len); - break; - - } /* switch rx channel */ - - return (1); /* always handled */ -} /* hysdn_sched_rx */ - -/*****************************************************************************/ -/* hysdn_sched_tx is called from the cards handler to announce that there is */ -/* room in the tx-buffer to the card and data may be sent if needed. */ -/* If the routine wants to send data it must fill buf, len and chan with the */ -/* appropriate data and return a nonzero value. With a zero return no new */ -/* data to send is assumed. maxlen specifies the buffer size available for */ -/* sending. */ -/*****************************************************************************/ -int -hysdn_sched_tx(hysdn_card * card, uchar * buf, word volatile *len, word volatile *chan, word maxlen) -{ - struct sk_buff *skb; - - if (card->net_tx_busy) { - card->net_tx_busy = 0; /* reset flag */ - hysdn_tx_netack(card); /* acknowledge packet send */ - } /* a network packet has completely been transferred */ - /* first of all async requests are handled */ - if (card->async_busy) { - if (card->async_len <= maxlen) { - memcpy(buf, card->async_data, card->async_len); - *len = card->async_len; - *chan = card->async_channel; - card->async_busy = 0; /* reset request */ - return (1); - } - card->async_busy = 0; /* in case of length error */ - } /* async request */ - if ((card->err_log_state == ERRLOG_STATE_START) && - (maxlen >= ERRLOG_CMD_REQ_SIZE)) { - strcpy(buf, ERRLOG_CMD_REQ); /* copy the command */ - *len = ERRLOG_CMD_REQ_SIZE; /* buffer length */ - *chan = CHAN_ERRLOG; /* and channel */ - card->err_log_state = ERRLOG_STATE_ON; /* new state is on */ - return (1); /* tell that data should be send */ - } /* error log start and able to send */ - if ((card->err_log_state == ERRLOG_STATE_STOP) && - (maxlen >= ERRLOG_CMD_STOP_SIZE)) { - strcpy(buf, ERRLOG_CMD_STOP); /* copy the command */ - *len = ERRLOG_CMD_STOP_SIZE; /* buffer length */ - *chan = CHAN_ERRLOG; /* and channel */ - card->err_log_state = ERRLOG_STATE_OFF; /* new state is off */ - return (1); /* tell that data should be send */ - } /* error log start and able to send */ - /* now handle network interface packets */ - if ((skb = hysdn_tx_netget(card)) != NULL) { - if (skb->len <= maxlen) { - memcpy(buf, skb->data, skb->len); /* copy the packet to the buffer */ - *len = skb->len; - *chan = CHAN_NDIS_DATA; - card->net_tx_busy = 1; /* we are busy sending network data */ - return (1); /* go and send the data */ - } else - hysdn_tx_netack(card); /* aknowledge packet -> throw away */ - } /* send a network packet if available */ - return (0); /* nothing to send */ -} /* hysdn_sched_tx */ - - -/*****************************************************************************/ -/* send one config line to the card and return 0 if successfull, otherwise a */ -/* negative error code. */ -/* The function works with timeouts perhaps not giving the greatest speed */ -/* sending the line, but this should be meaningless beacuse only some lines */ -/* are to be sent and this happens very seldom. */ -/*****************************************************************************/ -int -hysdn_tx_cfgline(hysdn_card * card, uchar * line, word chan) -{ - int cnt = 50; /* timeout intervalls */ - ulong flags; - - 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(); - while (card->async_busy) { - sti(); - - 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); - return (-ERR_ASYNC_TIME); /* timed out */ - } - cli(); - } /* wait for buffer to become free */ - - strcpy(card->async_data, line); - card->async_len = strlen(line) + 1; - card->async_channel = chan; - card->async_busy = 1; /* request transfer */ - - /* now queue the task */ - queue_task(&card->irq_queue, &tq_immediate); - mark_bh(IMMEDIATE_BH); - sti(); - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg data queued"); - - cnt++; /* short delay */ - cli(); - - while (card->async_busy) { - sti(); - - 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); - return (-ERR_ASYNC_TIME); /* timed out */ - } - cli(); - } /* wait for buffer to become free again */ - - restore_flags(flags); - - if (card->debug_flags & LOG_SCHED_ASYN) - hysdn_addlog(card, "async tx-cfg data send"); - - return (0); /* line send correctly */ -} /* hysdn_tx_cfgline */ diff --git a/drivers/isdn/hysdn/ince1pc.h b/drivers/isdn/hysdn/ince1pc.h deleted file mode 100644 index c22974d8..00000000 --- a/drivers/isdn/hysdn/ince1pc.h +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef __INCE1PC_H__ -#define __INCE1PC_H__ - -/**************************************************************************** - - FILE: ince1pc.h - - AUTHOR: M.Steinkopf - - PURPOSE: common definitions for both sides of the bus: - - conventions both spoolers must know - - channel numbers agreed upon - -*****************************************************************************/ - -/* basic scalar definitions have same meanning, - * but their declaration location depends on environment - */ - -/*--------------------------------------channel numbers---------------------*/ -#define CHAN_SYSTEM 0x0001 /* system channel (spooler to spooler) */ -#define CHAN_ERRLOG 0x0005 /* error logger */ -#define CHAN_CAPI 0x0064 /* CAPI interface */ -#define CHAN_NDIS_DATA 0x1001 /* NDIS data transfer */ - -/*--------------------------------------POF ready msg-----------------------*/ - /* NOTE: after booting POF sends system ready message to PC: */ -#define RDY_MAGIC 0x52535953UL /* 'SYSR' reversed */ -#define RDY_MAGIC_SIZE 4 /* size in bytes */ - -#define MAX_N_TOK_BYTES 255 - -#define MIN_RDY_MSG_SIZE RDY_MAGIC_SIZE -#define MAX_RDY_MSG_SIZE (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES) - -#define SYSR_TOK_END 0 -#define SYSR_TOK_B_CHAN 1 /* nr. of B-Channels; DataLen=1; def: 2 */ -#define SYSR_TOK_FAX_CHAN 2 /* nr. of FAX Channels; DataLen=1; def: 0 */ -#define SYSR_TOK_MAC_ADDR 3 /* MAC-Address; DataLen=6; def: auto */ -#define SYSR_TOK_ESC 255 /* undefined data size yet */ - /* default values, if not corrected by token: */ -#define SYSR_TOK_B_CHAN_DEF 2 /* assume 2 B-Channels */ -#define SYSR_TOK_FAX_CHAN_DEF 1 /* assume 1 FAX Channel */ - -/* syntax of new SYSR token stream: - * channel: CHAN_SYSTEM - * msgsize: MIN_RDY_MSG_SIZE <= x <= MAX_RDY_MSG_SIZE - * RDY_MAGIC_SIZE <= x <= (RDY_MAGIC_SIZE+MAX_N_TOK_BYTES) - * msg : 0 1 2 3 {4 5 6 ..} - * S Y S R MAX_N_TOK_BYTES bytes of TokenStream - * - * TokenStream := empty - * | {NonEndTokenChunk} EndToken RotlCRC - * NonEndTokenChunk:= NonEndTokenId DataLen [Data] - * NonEndTokenId := 0x01 .. 0xFE 1 BYTE - * DataLen := 0x00 .. 0xFF 1 BYTE - * Data := DataLen bytes - * EndToken := 0x00 - * RotlCRC := special 1 byte CRC over all NonEndTokenChunk bytes - * s. RotlCRC algorithm - * - * RotlCRC algorithm: - * ucSum= 0 1 uchar - * for all NonEndTokenChunk bytes: - * ROTL(ucSum,1) rotate left by 1 - * ucSum += Char; add current byte with swap around - * RotlCRC= ~ucSum; invert all bits for result - * - * note: - * - for 16-bit FIFO add padding 0 byte to achieve even token data bytes! - */ - -/*--------------------------------------error logger------------------------*/ - /* note: pof needs final 0 ! */ -#define ERRLOG_CMD_REQ "ERRLOG ON" -#define ERRLOG_CMD_REQ_SIZE 10 /* with final 0 byte ! */ -#define ERRLOG_CMD_STOP "ERRLOG OFF" -#define ERRLOG_CMD_STOP_SIZE 11 /* with final 0 byte ! */ - -#define ERRLOG_ENTRY_SIZE 64 /* sizeof(tErrLogEntry) */ - /* remaining text size = 55 */ -#define ERRLOG_TEXT_SIZE (ERRLOG_ENTRY_SIZE-2*4-1) - -typedef struct ErrLogEntry_tag { - -/*00 */ ulong ulErrType; - -/*04 */ ulong ulErrSubtype; - -/*08 */ uchar ucTextSize; - - /*09 */ uchar ucText[ERRLOG_TEXT_SIZE]; - /* ASCIIZ of len ucTextSize-1 */ - -/*40 */ -} tErrLogEntry; - - -#if defined(__TURBOC__) -#if sizeof(tErrLogEntry) != ERRLOG_ENTRY_SIZE -#error size of tErrLogEntry != ERRLOG_ENTRY_SIZE -#endif /* */ -#endif /* */ - -/*--------------------------------------DPRAM boot spooler------------------*/ - /* this is the struture used between pc and - * hyperstone to exchange boot data - */ -#define DPRAM_SPOOLER_DATA_SIZE 0x20 -typedef struct DpramBootSpooler_tag { - -/*00 */ uchar Len; - -/*01 */ volatile uchar RdPtr; - -/*02 */ uchar WrPtr; - -/*03 */ uchar Data[DPRAM_SPOOLER_DATA_SIZE]; - -/*23 */ -} tDpramBootSpooler; - - -#define DPRAM_SPOOLER_MIN_SIZE 5 /* Len+RdPtr+Wrptr+2*data */ -#define DPRAM_SPOOLER_DEF_SIZE 0x23 /* current default size */ - -/*--------------------------------------HYCARD/ERGO DPRAM SoftUart----------*/ - /* at DPRAM offset 0x1C00: */ -#define SIZE_RSV_SOFT_UART 0x1B0 /* 432 bytes reserved for SoftUart */ - - -#endif /* __INCE1PC_H__ */ diff --git a/drivers/isdn/icn/Makefile b/drivers/isdn/icn/Makefile deleted file mode 100644 index 17c533ee..00000000 --- a/drivers/isdn/icn/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -ifeq ($(CONFIG_ISDN_DRV_ICN),y) - O_TARGET := icn_obj.o - O_OBJS := icn.o -else - M_OBJS := icn.o -endif - -include $(TOPDIR)/Rules.make diff --git a/drivers/isdn/icn/icn.c b/drivers/isdn/icn/icn.c deleted file mode 100644 index 7b767199..00000000 --- a/drivers/isdn/icn/icn.c +++ /dev/null @@ -1,1962 +0,0 @@ -/* $Id$ - - * ISDN low-level module for the ICN active ISDN-Card. - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@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. - * - * $Log$ - * Revision 1.61 1999/09/03 14:06:58 fritz - * Fixed a memory leak. - * - * Revision 1.60 1999/08/31 11:20:32 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.59 1999/08/28 22:10:55 keil - * __setup function should be static - * - * Revision 1.58 1999/08/25 16:44:17 keil - * Support for new __setup function - * - * Revision 1.57 1999/07/06 16:15:30 detabc - * remove unused messages - * - * Revision 1.56 1999/04/12 13:15:07 fritz - * Fixed a cast. - * - * Revision 1.55 1999/04/12 12:34:02 fritz - * Changes from 2.0 tree. - * - * Revision 1.54 1999/01/05 18:29:39 he - * merged remaining schedule_timeout() changes from 2.1.127 - * - * Revision 1.53 1998/06/17 19:51:28 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.52 1998/05/20 19:29:58 tsbogend - * fixed bug introduced by changes for new BSENT callback - * - * Revision 1.51 1998/03/07 22:29:55 fritz - * Adapted Detlef's chenges for 2.1. - * - * Revision 1.49 1998/02/13 11:14:15 keil - * change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb() - * - * Revision 1.48 1997/10/10 15:56:14 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.47 1997/10/01 09:21:51 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.46 1997/08/21 22:38:33 fritz - * Fixed a typo. - * - * Revision 1.45 1997/06/21 10:42:06 fritz - * Added availability to select leased mode on only one channel. - * - * Revision 1.44 1997/03/30 16:51:26 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.43 1997/03/21 18:27:04 fritz - * Corrected parsing of incoming setup. - * - * Revision 1.42 1997/03/05 21:13:18 fritz - * Bugfix: sndcount was not reset on hangup. - * - * Revision 1.41 1997/02/24 23:34:29 fritz - * Bugfix in Layer1 error-recovery. - * - * Revision 1.40 1997/02/23 23:34:45 fritz - * Minor bugfixes in debugging code. - * - * Revision 1.39 1997/02/23 16:21:56 fritz - * Bugfix: Check for NULL pointer in icn_parse_status(). - * - * Revision 1.38 1997/02/11 18:29:31 fritz - * Bugfix in D64S initialization. - * - * Revision 1.37 1997/02/10 22:43:20 fritz - * Added plan and screen elements on ISDN_STAT_ICALL - * - * Revision 1.36 1997/02/10 21:31:20 fritz - * Changed setup-interface (incoming and outgoing). - * - * Revision 1.35 1997/02/10 10:10:28 fritz - * Changes for Kernel 2.1.X compatibility. - * Enhanced initialization, can recover from - * misconfiguration by other autoprobing drivers. - * - * Revision 1.34 1997/01/29 22:34:44 fritz - * Cleanup, Corrected D64S setup of 2nd channel. - * - * Revision 1.33 1996/12/05 20:31:48 tsbogend - * added handling of L2: DATA LINK LOST messages - * - * Revision 1.32 1996/11/14 23:49:18 fritz - * Bugfix: copy_to_user/copy_from_user mismatch in debugging-ioctl. - * - * Revision 1.31 1996/11/13 02:36:25 fritz - * Fixed a race condition in writecmd. - * Some optimizations and cleanup. - * - * Revision 1.30 1996/10/22 23:14:09 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.29 1996/08/29 20:34:54 fritz - * Bugfix in send queue management: - * sndcount was not updated correctly. - * Minor Bugfixes. - * - * Revision 1.28 1996/06/28 17:02:53 fritz - * replaced memcpy_fromfs_toio. - * - * Revision 1.27 1996/06/25 18:38:59 fritz - * Fixed function name in error message. - * - * Revision 1.26 1996/06/24 17:20:35 fritz - * Bugfixes in pollbchan_send(): - * - Using lock field of skbuff breaks networking. - * - Added channel locking - * - changed dequeuing scheme. - * Eliminated misc. compiler warnings. - * - * Revision 1.25 1996/06/11 22:53:35 tsbogend - * fixed problem with large array on stack - * made the driver working on Linux/alpha - * - * Revision 1.24 1996/06/06 13:58:33 fritz - * Changed code to be architecture independent - * - * Revision 1.23 1996/06/03 19:59:00 fritz - * Fixed typos. - * - * Revision 1.22 1996/05/17 15:46:41 fritz - * Removed own queue management. - * Changed queue management to use sk_buffs. - * - * Revision 1.21 1996/05/02 04:01:20 fritz - * Bugfix: - * - icn_addcard() evaluated wrong driverId. - * - * Revision 1.20 1996/05/02 00:40:27 fritz - * Major rewrite to support more than one card - * with a single module. - * Support for new firmware. - * - * Revision 1.19 1996/04/21 17:43:32 fritz - * Changes for Support of new Firmware BRV3.02 - * - * Revision 1.18 1996/04/20 16:50:26 fritz - * Fixed status-buffer overrun. - * Misc. typos - * - * Revision 1.17 1996/02/11 02:39:04 fritz - * Increased Buffer for status-messages. - * Removed conditionals for HDLC-firmware. - * - * Revision 1.16 1996/01/22 05:01:55 fritz - * Revert to GPL. - * - * Revision 1.15 1996/01/10 20:57:39 fritz - * Bugfix: Loading firmware twice caused the device stop working. - * - * Revision 1.14 1995/12/18 18:23:37 fritz - * Support for ICN-2B Cards. - * Change for supporting user-settable service-octet. - * - * Revision 1.13 1995/10/29 21:41:07 fritz - * Added support for DriverId's, added Jan's patches for Kernel versions. - * - * Revision 1.12 1995/04/29 13:07:35 fritz - * Added support for new Euro-ISDN-firmware - * - * Revision 1.11 1995/04/23 13:40:45 fritz - * Added support for SPV's. - * Changed Dial-Command to support MSN's on DSS1-Lines. - * - * Revision 1.10 1995/03/25 23:23:24 fritz - * Changed configurable Ports, to allow settings for DIP-Switch Cardversions. - * - * Revision 1.9 1995/03/25 23:17:30 fritz - * Fixed race-condition in pollbchan_send - * - * Revision 1.8 1995/03/15 12:49:44 fritz - * Added support for SPV's - * Split pollbchan_work for calling send-routine directly - * - * Revision 1.7 1995/02/20 03:48:03 fritz - * Added support of new request_region-function. - * Minor bugfixes. - * - * Revision 1.6 1995/01/31 15:48:45 fritz - * Added Cause-Messages to be signaled to upper layers. - * Added Revision-Info on load. - * - * Revision 1.5 1995/01/29 23:34:59 fritz - * Added stopdriver() and appropriate calls. - * Changed printk-statements to support loglevels. - * - * Revision 1.4 1995/01/09 07:40:46 fritz - * Added GPL-Notice - * - * Revision 1.3 1995/01/04 05:15:18 fritz - * Added undocumented "bootload-finished"-command in download-code - * to satisfy some brain-damaged icn card-versions. - * - * Revision 1.2 1995/01/02 02:14:45 fritz - * Misc Bugfixes - * - * Revision 1.1 1994/12/14 17:56:06 fritz - * Initial revision - * - */ - -#include "icn.h" - -/* - * Verbose bootcode- and protocol-downloading. - */ -#undef BOOT_DEBUG - -/* - * Verbose Shmem-Mapping. - */ -#undef MAP_DEBUG - -static char -*revision = "$Revision$"; - -static int icn_addcard(int, char *, char *); - -/* - * Free send-queue completely. - * Parameter: - * card = pointer to card struct - * channel = channel number - */ -static void -icn_free_queue(icn_card * card, int channel) -{ - struct sk_buff_head *queue = &card->spqueue[channel]; - struct sk_buff *skb; - unsigned long flags; - - while ((skb = skb_dequeue(queue))) - dev_kfree_skb(skb); - save_flags(flags); - cli(); - card->xlen[channel] = 0; - card->sndcount[channel] = 0; - if ((skb = card->xskb[channel])) { - card->xskb[channel] = NULL; - restore_flags(flags); - dev_kfree_skb(skb); - } else - restore_flags(flags); -} - -/* Put a value into a shift-register, highest bit first. - * Parameters: - * port = port for output (bit 0 is significant) - * val = value to be output - * firstbit = Bit-Number of highest bit - * bitcount = Number of bits to output - */ -static inline void -icn_shiftout(unsigned short port, - unsigned long val, - int firstbit, - int bitcount) -{ - - register u_char s; - register u_char c; - - for (s = firstbit, c = bitcount; c > 0; s--, c--) - OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port); -} - -/* - * disable a cards shared memory - */ -static inline void -icn_disable_ram(icn_card * card) -{ - OUTB_P(0, ICN_MAPRAM); -} - -/* - * enable a cards shared memory - */ -static inline void -icn_enable_ram(icn_card * card) -{ - OUTB_P(0xff, ICN_MAPRAM); -} - -/* - * Map a cards channel0 (Bank0/Bank8) or channel1 (Bank4/Bank12) - */ -static inline void -icn_map_channel(icn_card * card, int channel) -{ -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_map_channel %d %d\n", dev.channel, channel); -#endif - if ((channel == dev.channel) && (card == dev.mcard)) - return; - if (dev.mcard) - icn_disable_ram(dev.mcard); - icn_shiftout(ICN_BANK, chan2bank[channel], 3, 4); /* Select Bank */ - icn_enable_ram(card); - dev.mcard = card; - dev.channel = channel; -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_map_channel done\n"); -#endif -} - -/* - * Lock a cards channel. - * Return 0 if requested card/channel is unmapped (failure). - * Return 1 on success. - */ -static inline int -icn_lock_channel(icn_card * card, int channel) -{ - register int retval; - ulong flags; - -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_lock_channel %d\n", channel); -#endif - save_flags(flags); - cli(); - if ((dev.channel == channel) && (card == dev.mcard)) { - dev.chanlock++; - retval = 1; -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_lock_channel %d OK\n", channel); -#endif - } else { - retval = 0; -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev.channel); -#endif - } - restore_flags(flags); - return retval; -} - -/* - * Release current card/channel lock - */ -static inline void -icn_release_channel(void) -{ - ulong flags; - -#ifdef MAP_DEBUG - printk(KERN_DEBUG "icn_release_channel l=%d\n", dev.chanlock); -#endif - save_flags(flags); - cli(); - if (dev.chanlock > 0) - dev.chanlock--; - restore_flags(flags); -} - -/* - * Try to map and lock a cards channel. - * Return 1 on success, 0 on failure. - */ -static inline int -icn_trymaplock_channel(icn_card * card, int channel) -{ - ulong flags; - -#ifdef MAP_DEBUG - printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev.channel, - dev.chanlock); -#endif - save_flags(flags); - cli(); - if ((!dev.chanlock) || - ((dev.channel == channel) && (dev.mcard == card))) { - dev.chanlock++; - icn_map_channel(card, channel); - restore_flags(flags); -#ifdef MAP_DEBUG - printk(KERN_DEBUG "trymaplock %d OK\n", channel); -#endif - return 1; - } - restore_flags(flags); -#ifdef MAP_DEBUG - printk(KERN_DEBUG "trymaplock %d FAILED\n", channel); -#endif - return 0; -} - -/* - * Release current card/channel lock, - * then map same or other channel without locking. - */ -static inline void -icn_maprelease_channel(icn_card * card, int channel) -{ - ulong flags; - -#ifdef MAP_DEBUG - printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev.chanlock); -#endif - save_flags(flags); - cli(); - if (dev.chanlock > 0) - dev.chanlock--; - if (!dev.chanlock) - icn_map_channel(card, channel); - restore_flags(flags); -} - -/* Get Data from the B-Channel, assemble fragmented packets and put them - * into receive-queue. Wake up any B-Channel-reading processes. - * This routine is called via timer-callback from icn_pollbchan(). - */ - -static void -icn_pollbchan_receive(int channel, icn_card * card) -{ - int mch = channel + ((card->secondhalf) ? 2 : 0); - int eflag; - int cnt; - struct sk_buff *skb; - - if (icn_trymaplock_channel(card, mch)) { - while (rbavl) { - cnt = readb(&rbuf_l); - if ((card->rcvidx[channel] + cnt) > 4000) { - printk(KERN_WARNING - "icn: (%s) bogus packet on ch%d, dropping.\n", - CID, - channel + 1); - card->rcvidx[channel] = 0; - eflag = 0; - } else { - memcpy_fromio(&card->rcvbuf[channel][card->rcvidx[channel]], - &rbuf_d, cnt); - card->rcvidx[channel] += cnt; - eflag = readb(&rbuf_f); - } - rbnext; - icn_maprelease_channel(card, mch & 2); - if (!eflag) { - if ((cnt = card->rcvidx[channel])) { - if (!(skb = dev_alloc_skb(cnt))) { - printk(KERN_WARNING "icn: receive out of memory\n"); - break; - } - memcpy(skb_put(skb, cnt), card->rcvbuf[channel], cnt); - card->rcvidx[channel] = 0; - card->interface.rcvcallb_skb(card->myid, channel, skb); - } - } - if (!icn_trymaplock_channel(card, mch)) - break; - } - icn_maprelease_channel(card, mch & 2); - } -} - -/* Send data-packet to B-Channel, split it up into fragments of - * ICN_FRAGSIZE length. If last fragment is sent out, signal - * success to upper layers via statcallb with ISDN_STAT_BSENT argument. - * This routine is called via timer-callback from icn_pollbchan() or - * directly from icn_sendbuf(). - */ - -static void -icn_pollbchan_send(int channel, icn_card * card) -{ - int mch = channel + ((card->secondhalf) ? 2 : 0); - int cnt; - unsigned long flags; - struct sk_buff *skb; - isdn_ctrl cmd; - - if (!(card->sndcount[channel] || card->xskb[channel] || - skb_queue_len(&card->spqueue[channel]))) - return; - if (icn_trymaplock_channel(card, mch)) { - while (sbfree && - (card->sndcount[channel] || - skb_queue_len(&card->spqueue[channel]) || - card->xskb[channel])) { - save_flags(flags); - cli(); - if (card->xmit_lock[channel]) { - restore_flags(flags); - break; - } - card->xmit_lock[channel]++; - restore_flags(flags); - skb = card->xskb[channel]; - if (!skb) { - skb = skb_dequeue(&card->spqueue[channel]); - if (skb) { - /* Pop ACK-flag off skb. - * Store length to xlen. - */ - if (*(skb_pull(skb,1))) - card->xlen[channel] = skb->len; - else - card->xlen[channel] = 0; - } - } - if (!skb) - break; - if (skb->len > ICN_FRAGSIZE) { - writeb(0xff, &sbuf_f); - cnt = ICN_FRAGSIZE; - } else { - writeb(0x0, &sbuf_f); - cnt = skb->len; - } - writeb(cnt, &sbuf_l); - memcpy_toio(&sbuf_d, skb->data, cnt); - skb_pull(skb, cnt); - card->sndcount[channel] -= cnt; - sbnext; /* switch to next buffer */ - icn_maprelease_channel(card, mch & 2); - if (!skb->len) { - save_flags(flags); - cli(); - if (card->xskb[channel]) - card->xskb[channel] = NULL; - restore_flags(flags); - dev_kfree_skb(skb); - if (card->xlen[channel]) { - cmd.command = ISDN_STAT_BSENT; - cmd.driver = card->myid; - cmd.arg = channel; - cmd.parm.length = card->xlen[channel]; - card->interface.statcallb(&cmd); - } - } else { - save_flags(flags); - cli(); - card->xskb[channel] = skb; - restore_flags(flags); - } - card->xmit_lock[channel] = 0; - if (!icn_trymaplock_channel(card, mch)) - break; - } - icn_maprelease_channel(card, mch & 2); - } -} - -/* Send/Receive Data to/from the B-Channel. - * This routine is called via timer-callback. - * It schedules itself while any B-Channel is open. - */ - -static void -icn_pollbchan(unsigned long data) -{ - icn_card *card = (icn_card *) data; - unsigned long flags; - - if (card->flags & ICN_FLAGS_B1ACTIVE) { - icn_pollbchan_receive(0, card); - icn_pollbchan_send(0, card); - } - if (card->flags & ICN_FLAGS_B2ACTIVE) { - icn_pollbchan_receive(1, card); - icn_pollbchan_send(1, card); - } - if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) { - /* schedule b-channel polling again */ - save_flags(flags); - cli(); - del_timer(&card->rb_timer); - card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; - add_timer(&card->rb_timer); - card->flags |= ICN_FLAGS_RBTIMER; - restore_flags(flags); - } else - card->flags &= ~ICN_FLAGS_RBTIMER; -} - -typedef struct icn_stat { - char *statstr; - int command; - int action; -} icn_stat; -/* *INDENT-OFF* */ -static icn_stat icn_stat_table[] = -{ - {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */ - {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */ - /* - ** add d-channel connect and disconnect support to link-level - */ - {"DCON_", ISDN_STAT_DCONN, 10}, /* D-Channel connected */ - {"DDIS_", ISDN_STAT_DHUP, 11}, /* D-Channel disconnected */ - {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */ - {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */ - {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */ - {"CIF", ISDN_STAT_CINF, 5}, /* Charge-info, 1TR6-type */ - {"AOC", ISDN_STAT_CINF, 6}, /* Charge-info, DSS1-type */ - {"CAU", ISDN_STAT_CAUSE, 7}, /* Cause code */ - {"TEI OK", ISDN_STAT_RUN, 0}, /* Card connected to wallplug */ - {"NO D-CHAN", ISDN_STAT_NODCH, 0}, /* No D-channel available */ - {"E_L1: ACT FAIL", ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ - {"E_L2: DATA LIN", ISDN_STAT_BHUP, 8}, /* Layer-2 data link lost */ - {"E_L1: ACTIVATION FAILED", - ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ - {NULL, 0, -1} -}; -/* *INDENT-ON* */ - - -/* - * Check Statusqueue-Pointer from isdn-cards. - * If there are new status-replies from the interface, check - * them against B-Channel-connects/disconnects and set flags accordingly. - * Wake-Up any processes, who are reading the status-device. - * If there are B-Channels open, initiate a timer-callback to - * icn_pollbchan(). - * This routine is called periodically via timer. - */ - -static void -icn_parse_status(u_char * status, int channel, icn_card * card) -{ - icn_stat *s = icn_stat_table; - int action = -1; - unsigned long flags; - isdn_ctrl cmd; - - while (s->statstr) { - if (!strncmp(status, s->statstr, strlen(s->statstr))) { - cmd.command = s->command; - action = s->action; - break; - } - s++; - } - if (action == -1) - return; - cmd.driver = card->myid; - cmd.arg = channel; - switch (action) { - case 11: - save_flags(flags); - cli(); - icn_free_queue(card,channel); - card->rcvidx[channel] = 0; - - if (card->flags & - ((channel)?ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE)) { - - isdn_ctrl ncmd; - - card->flags &= ~((channel)? - ICN_FLAGS_B2ACTIVE:ICN_FLAGS_B1ACTIVE); - - memset(&ncmd, 0, sizeof(ncmd)); - - ncmd.driver = card->myid; - ncmd.arg = channel; - ncmd.command = ISDN_STAT_BHUP; - restore_flags(flags); - card->interface.statcallb(&cmd); - } else - restore_flags(flags); - - break; - case 1: - icn_free_queue(card,channel); - card->flags |= (channel) ? - ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE; - break; - case 2: - card->flags &= ~((channel) ? - ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE); - icn_free_queue(card, channel); - save_flags(flags); - cli(); - card->rcvidx[channel] = 0; - restore_flags(flags); - break; - case 3: - { - char *t = status + 6; - char *s = strpbrk(t, ","); - - *s++ = '\0'; - strncpy(cmd.parm.setup.phone, t, - sizeof(cmd.parm.setup.phone)); - s = strpbrk(t = s, ","); - *s++ = '\0'; - if (!strlen(t)) - cmd.parm.setup.si1 = 0; - else - cmd.parm.setup.si1 = - simple_strtoul(t, NULL, 10); - s = strpbrk(t = s, ","); - *s++ = '\0'; - if (!strlen(t)) - cmd.parm.setup.si2 = 0; - else - cmd.parm.setup.si2 = - simple_strtoul(t, NULL, 10); - strncpy(cmd.parm.setup.eazmsn, s, - sizeof(cmd.parm.setup.eazmsn)); - } - cmd.parm.setup.plan = 0; - cmd.parm.setup.screen = 0; - break; - case 4: - sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid); - sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1); - cmd.parm.setup.si1 = 7; - cmd.parm.setup.si2 = 0; - cmd.parm.setup.plan = 0; - cmd.parm.setup.screen = 0; - break; - case 5: - strncpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num) - 1); - break; - case 6: - sprintf(cmd.parm.num, "%d", - (int) simple_strtoul(status + 7, NULL, 16)); - break; - case 7: - status += 3; - if (strlen(status) == 4) - sprintf(cmd.parm.num, "%s%c%c", - status + 2, *status, *(status + 1)); - else - strncpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num) - 1); - break; - case 8: - card->flags &= ~ICN_FLAGS_B1ACTIVE; - icn_free_queue(card, 0); - save_flags(flags); - cli(); - card->rcvidx[0] = 0; - restore_flags(flags); - cmd.arg = 0; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_DHUP; - cmd.arg = 0; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_BHUP; - card->flags &= ~ICN_FLAGS_B2ACTIVE; - icn_free_queue(card, 1); - save_flags(flags); - cli(); - card->rcvidx[1] = 0; - restore_flags(flags); - cmd.arg = 1; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_DHUP; - cmd.arg = 1; - cmd.driver = card->myid; - break; - } - card->interface.statcallb(&cmd); - return; -} - -static void -icn_putmsg(icn_card * card, unsigned char c) -{ - ulong flags; - - save_flags(flags); - cli(); - *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; - if (card->msg_buf_write == card->msg_buf_read) { - if (++card->msg_buf_read > card->msg_buf_end) - card->msg_buf_read = card->msg_buf; - } - if (card->msg_buf_write > card->msg_buf_end) - card->msg_buf_write = card->msg_buf; - restore_flags(flags); -} - -static void -icn_polldchan(unsigned long data) -{ - icn_card *card = (icn_card *) data; - int mch = card->secondhalf ? 2 : 0; - int avail = 0; - int left; - u_char c; - int ch; - int flags; - int i; - u_char *p; - isdn_ctrl cmd; - - if (icn_trymaplock_channel(card, mch)) { - avail = msg_avail; - for (left = avail, i = readb(&msg_o); left > 0; i++, left--) { - c = readb(&dev.shmem->comm_buffers.iopc_buf[i & 0xff]); - icn_putmsg(card, c); - if (c == 0xff) { - card->imsg[card->iptr] = 0; - card->iptr = 0; - if (card->imsg[0] == '0' && card->imsg[1] >= '0' && - card->imsg[1] <= '2' && card->imsg[2] == ';') { - ch = (card->imsg[1] - '0') - 1; - p = &card->imsg[3]; - icn_parse_status(p, ch, card); - } else { - p = card->imsg; - if (!strncmp(p, "DRV1.", 5)) { - u_char vstr[10]; - u_char *q = vstr; - - printk(KERN_INFO "icn: (%s) %s\n", CID, p); - if (!strncmp(p + 7, "TC", 2)) { - card->ptype = ISDN_PTYPE_1TR6; - card->interface.features |= ISDN_FEATURE_P_1TR6; - printk(KERN_INFO - "icn: (%s) 1TR6-Protocol loaded and running\n", CID); - } - if (!strncmp(p + 7, "EC", 2)) { - card->ptype = ISDN_PTYPE_EURO; - card->interface.features |= ISDN_FEATURE_P_EURO; - printk(KERN_INFO - "icn: (%s) Euro-Protocol loaded and running\n", CID); - } - p = strstr(card->imsg, "BRV") + 3; - while (*p) { - if (*p >= '0' && *p <= '9') - *q++ = *p; - p++; - } - *q = '\0'; - strcat(vstr, "000"); - vstr[3] = '\0'; - card->fw_rev = (int) simple_strtoul(vstr, NULL, 10); - continue; - - } - } - } else { - card->imsg[card->iptr] = c; - if (card->iptr < 59) - card->iptr++; - } - } - writeb((readb(&msg_o) + avail) & 0xff, &msg_o); - icn_release_channel(); - } - if (avail) { - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = avail; - card->interface.statcallb(&cmd); - } - if (card->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) - if (!(card->flags & ICN_FLAGS_RBTIMER)) { - /* schedule b-channel polling */ - card->flags |= ICN_FLAGS_RBTIMER; - save_flags(flags); - cli(); - del_timer(&card->rb_timer); - card->rb_timer.function = icn_pollbchan; - card->rb_timer.data = (unsigned long) card; - card->rb_timer.expires = jiffies + ICN_TIMER_BCREAD; - add_timer(&card->rb_timer); - restore_flags(flags); - } - /* schedule again */ - save_flags(flags); - cli(); - del_timer(&card->st_timer); - card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - add_timer(&card->st_timer); - restore_flags(flags); -} - -/* Append a packet to the transmit buffer-queue. - * Parameters: - * channel = Number of B-channel - * skb = pointer to sk_buff - * card = pointer to card-struct - * Return: - * Number of bytes transferred, -E??? on error - */ - -static int -icn_sendbuf(int channel, int ack, struct sk_buff *skb, icn_card * card) -{ - int len = skb->len; - unsigned long flags; - struct sk_buff *nskb; - - if (len > 4000) { - printk(KERN_WARNING - "icn: Send packet too large\n"); - return -EINVAL; - } - if (len) { - if (!(card->flags & (channel) ? ICN_FLAGS_B2ACTIVE : ICN_FLAGS_B1ACTIVE)) - return 0; - if (card->sndcount[channel] > ICN_MAX_SQUEUE) - return 0; - save_flags(flags); - cli(); - nskb = skb_clone(skb, GFP_ATOMIC); - if (nskb) { - /* Push ACK flag as one - * byte in front of data. - */ - *(skb_push(nskb, 1)) = ack?1:0; - skb_queue_tail(&card->spqueue[channel], nskb); - dev_kfree_skb(skb); - } else - len = 0; - card->sndcount[channel] += len; - restore_flags(flags); - } - return len; -} - -/* - * Check card's status after starting the bootstrap loader. - * On entry, the card's shared memory has already to be mapped. - * Return: - * 0 on success (Boot loader ready) - * -EIO on failure (timeout) - */ -static int -icn_check_loader(int cardnumber) -{ - int timer = 0; - - while (1) { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Loader %d ?\n", cardnumber); -#endif - if (readb(&dev.shmem->data_control.scns) || - readb(&dev.shmem->data_control.scnr)) { - if (timer++ > 5) { - printk(KERN_WARNING - "icn: Boot-Loader %d timed out.\n", - cardnumber); - icn_release_channel(); - return -EIO; - } -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Loader %d TO?\n", cardnumber); -#endif - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(ICN_BOOT_TIMEOUT1); - } else { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Loader %d OK\n", cardnumber); -#endif - icn_release_channel(); - return 0; - } - } -} - -/* Load the boot-code into the interface-card's memory and start it. - * Always called from user-process. - * - * Parameters: - * buffer = pointer to packet - * Return: - * 0 if successfully loaded - */ - -#ifdef BOOT_DEBUG -#define SLEEP(sec) { \ -int slsec = sec; \ - printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \ - while (slsec) { \ - current->state = TASK_INTERRUPTIBLE; \ - schedule_timeout(HZ); \ - slsec--; \ - } \ -} -#else -#define SLEEP(sec) -#endif - -static int -icn_loadboot(u_char * buffer, icn_card * card) -{ - int ret; - ulong flags; - u_char *codebuf; - -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer); -#endif - if (!(codebuf = kmalloc(ICN_CODE_STAGE1, GFP_KERNEL))) { - printk(KERN_WARNING "icn: Could not allocate code buffer\n"); - return -ENOMEM; - } - if ((ret = copy_from_user(codebuf, buffer, ICN_CODE_STAGE1))) { - kfree(codebuf); - return ret; - } - save_flags(flags); - cli(); - if (!card->rvalid) { - if (check_region(card->port, ICN_PORTLEN)) { - printk(KERN_WARNING - "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, - card->port, - card->port + ICN_PORTLEN); - restore_flags(flags); - kfree(codebuf); - return -EBUSY; - } - request_region(card->port, ICN_PORTLEN, card->regname); - card->rvalid = 1; - if (card->doubleS0) - card->other->rvalid = 1; - } - if (!dev.mvalid) { - if (check_shmem((ulong) dev.shmem, 0x4000)) { - printk(KERN_WARNING - "icn: memory at 0x%08lx in use.\n", - (ulong) dev.shmem); - restore_flags(flags); - return -EBUSY; - } - request_shmem((ulong) dev.shmem, 0x4000, "icn"); - dev.mvalid = 1; - } - restore_flags(flags); - OUTB_P(0, ICN_RUN); /* Reset Controller */ - OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ - icn_shiftout(ICN_CFG, 0x0f, 3, 4); /* Windowsize= 16k */ - icn_shiftout(ICN_CFG, (unsigned long) dev.shmem, 23, 10); /* Set RAM-Addr. */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "shmem=%08lx\n", (ulong) dev.shmem); -#endif - SLEEP(1); -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Map Bank 0\n"); -#endif - save_flags(flags); - cli(); - icn_map_channel(card, 0); /* Select Bank 0 */ - icn_lock_channel(card, 0); /* Lock Bank 0 */ - restore_flags(flags); - SLEEP(1); - memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Bootloader transfered\n"); -#endif - if (card->doubleS0) { - SLEEP(1); -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Map Bank 8\n"); -#endif - save_flags(flags); - cli(); - icn_release_channel(); - icn_map_channel(card, 2); /* Select Bank 8 */ - icn_lock_channel(card, 2); /* Lock Bank 8 */ - restore_flags(flags); - SLEEP(1); - memcpy_toio(dev.shmem, codebuf, ICN_CODE_STAGE1); /* Copy code */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Bootloader transfered\n"); -#endif - } - kfree(codebuf); - SLEEP(1); - OUTB_P(0xff, ICN_RUN); /* Start Boot-Code */ - if ((ret = icn_check_loader(card->doubleS0 ? 2 : 1))) - return ret; - if (!card->doubleS0) - return 0; - /* reached only, if we have a Double-S0-Card */ -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Map Bank 0\n"); -#endif - save_flags(flags); - cli(); - icn_map_channel(card, 0); /* Select Bank 0 */ - icn_lock_channel(card, 0); /* Lock Bank 0 */ - restore_flags(flags); - SLEEP(1); - return (icn_check_loader(1)); -} - -static int -icn_loadproto(u_char * buffer, icn_card * card) -{ - register u_char *p = buffer; - u_char codebuf[256]; - uint left = ICN_CODE_STAGE2; - uint cnt; - int timer; - int ret; - unsigned long flags; - -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "icn_loadproto called\n"); -#endif - if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2))) - return ret; - timer = 0; - save_flags(flags); - cli(); - if (card->secondhalf) { - icn_map_channel(card, 2); - icn_lock_channel(card, 2); - } else { - icn_map_channel(card, 0); - icn_lock_channel(card, 0); - } - restore_flags(flags); - while (left) { - if (sbfree) { /* If there is a free buffer... */ - cnt = MIN(256, left); - if (copy_from_user(codebuf, p, cnt)) { - icn_maprelease_channel(card, 0); - return -EFAULT; - } - memcpy_toio(&sbuf_l, codebuf, cnt); /* copy data */ - sbnext; /* switch to next buffer */ - p += cnt; - left -= cnt; - timer = 0; - } else { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "boot 2 !sbfree\n"); -#endif - if (timer++ > 5) { - icn_maprelease_channel(card, 0); - return -EIO; - } - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(10); - } - } - writeb(0x20, &sbuf_n); - timer = 0; - while (1) { - if (readb(&cmd_o) || readb(&cmd_i)) { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto?\n"); -#endif - if (timer++ > 5) { - printk(KERN_WARNING - "icn: (%s) Protocol timed out.\n", - CID); -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto TO!\n"); -#endif - icn_maprelease_channel(card, 0); - return -EIO; - } -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto TO?\n"); -#endif - current->state = TASK_INTERRUPTIBLE; - schedule_timeout(ICN_BOOT_TIMEOUT1); - } else { - if ((card->secondhalf) || (!card->doubleS0)) { -#ifdef BOOT_DEBUG - printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n", - card->secondhalf); -#endif - save_flags(flags); - cli(); - init_timer(&card->st_timer); - card->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->st_timer.function = icn_polldchan; - card->st_timer.data = (unsigned long) card; - add_timer(&card->st_timer); - card->flags |= ICN_FLAGS_RUNNING; - if (card->doubleS0) { - init_timer(&card->other->st_timer); - card->other->st_timer.expires = jiffies + ICN_TIMER_DCREAD; - card->other->st_timer.function = icn_polldchan; - card->other->st_timer.data = (unsigned long) card->other; - add_timer(&card->other->st_timer); - card->other->flags |= ICN_FLAGS_RUNNING; - } - restore_flags(flags); - } - icn_maprelease_channel(card, 0); - return 0; - } - } -} - -/* Read the Status-replies from the Interface */ -static int -icn_readstatus(u_char * buf, int len, int user, icn_card * card) -{ - int count; - u_char *p; - - for (p = buf, count = 0; count < len; p++, count++) { - if (card->msg_buf_read == card->msg_buf_write) - return count; - if (user) - put_user(*card->msg_buf_read++, p); - else - *p = *card->msg_buf_read++; - if (card->msg_buf_read > card->msg_buf_end) - card->msg_buf_read = card->msg_buf; - } - return count; -} - -/* Put command-strings into the command-queue of the Interface */ -static int -icn_writecmd(const u_char * buf, int len, int user, icn_card * card) -{ - int mch = card->secondhalf ? 2 : 0; - int avail; - int pp; - int i; - int count; - int xcount; - int ocount; - int loop; - unsigned long flags; - int lastmap_channel; - struct icn_card *lastmap_card; - u_char *p; - isdn_ctrl cmd; - u_char msg[0x100]; - - ocount = 1; - xcount = loop = 0; - while (len) { - save_flags(flags); - cli(); - lastmap_card = dev.mcard; - lastmap_channel = dev.channel; - icn_map_channel(card, mch); - - avail = cmd_free; - count = MIN(avail, len); - if (user) - copy_from_user(msg, buf, count); - else - memcpy(msg, buf, count); - icn_putmsg(card, '>'); - for (p = msg, pp = readb(&cmd_i), i = count; i > 0; i--, p++, pp - ++) { - writeb((*p == '\n') ? 0xff : *p, - &dev.shmem->comm_buffers.pcio_buf[pp & 0xff]); - len--; - xcount++; - icn_putmsg(card, *p); - if ((*p == '\n') && (i > 1)) { - icn_putmsg(card, '>'); - ocount++; - } - ocount++; - } - writeb((readb(&cmd_i) + count) & 0xff, &cmd_i); - if (lastmap_card) - icn_map_channel(lastmap_card, lastmap_channel); - restore_flags(flags); - if (len) { - mdelay(1); - if (loop++ > 20) - break; - } else - break; - } - if (len && (!user)) - printk(KERN_WARNING "icn: writemsg incomplete!\n"); - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = ocount; - card->interface.statcallb(&cmd); - return xcount; -} - -/* - * Delete card's pending timers, send STOP to linklevel - */ -static void -icn_stopcard(icn_card * card) -{ - unsigned long flags; - isdn_ctrl cmd; - - save_flags(flags); - cli(); - if (card->flags & ICN_FLAGS_RUNNING) { - card->flags &= ~ICN_FLAGS_RUNNING; - del_timer(&card->st_timer); - del_timer(&card->rb_timer); - cmd.command = ISDN_STAT_STOP; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - if (card->doubleS0) - icn_stopcard(card->other); - } - restore_flags(flags); -} - -static void -icn_stopallcards(void) -{ - icn_card *p = cards; - - while (p) { - icn_stopcard(p); - p = p->next; - } -} - -/* - * Unmap all cards, because some of them may be mapped accidetly during - * autoprobing of some network drivers (SMC-driver?) - */ -static void -icn_disable_cards(void) -{ - icn_card *card = cards; - unsigned long flags; - - save_flags(flags); - cli(); - while (card) { - if (check_region(card->port, ICN_PORTLEN)) { - printk(KERN_WARNING - "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, - card->port, - card->port + ICN_PORTLEN); - cli(); - } else { - OUTB_P(0, ICN_RUN); /* Reset Controller */ - OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ - } - card = card->next; - } - restore_flags(flags); -} - -static int -icn_command(isdn_ctrl * c, icn_card * card) -{ - ulong a; - ulong flags; - int i; - char cbuf[60]; - isdn_ctrl cmd; - icn_cdef cdef; - - switch (c->command) { - case ISDN_CMD_IOCTL: - memcpy(&a, c->parm.num, sizeof(ulong)); - switch (c->arg) { - case ICN_IOCTL_SETMMIO: - if ((unsigned long) dev.shmem != (a & 0x0ffc000)) { - if (check_shmem((ulong) (a & 0x0ffc000), 0x4000)) { - printk(KERN_WARNING - "icn: memory at 0x%08lx in use.\n", - (ulong) (a & 0x0ffc000)); - return -EINVAL; - } - icn_stopallcards(); - save_flags(flags); - cli(); - if (dev.mvalid) - release_shmem((ulong) dev.shmem, 0x4000); - dev.mvalid = 0; - dev.shmem = (icn_shmem *) (a & 0x0ffc000); - restore_flags(flags); - printk(KERN_INFO - "icn: (%s) mmio set to 0x%08lx\n", - CID, - (unsigned long) dev.shmem); - } - break; - case ICN_IOCTL_GETMMIO: - return (long) dev.shmem; - case ICN_IOCTL_SETPORT: - if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330 - || a == 0x340 || a == 0x350 || a == 0x360 || - a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338 - || a == 0x348 || a == 0x358 || a == 0x368) { - if (card->port != (unsigned short) a) { - if (check_region((unsigned short) a, ICN_PORTLEN)) { - printk(KERN_WARNING - "icn: (%s) ports 0x%03x-0x%03x in use.\n", - CID, (int) a, (int) a + ICN_PORTLEN); - return -EINVAL; - } - icn_stopcard(card); - save_flags(flags); - cli(); - if (card->rvalid) - release_region(card->port, ICN_PORTLEN); - card->port = (unsigned short) a; - card->rvalid = 0; - if (card->doubleS0) { - card->other->port = (unsigned short) a; - card->other->rvalid = 0; - } - restore_flags(flags); - printk(KERN_INFO - "icn: (%s) port set to 0x%03x\n", - CID, card->port); - } - } else - return -EINVAL; - break; - case ICN_IOCTL_GETPORT: - return (int) card->port; - case ICN_IOCTL_GETDOUBLE: - return (int) card->doubleS0; - case ICN_IOCTL_DEBUGVAR: - if ((i = copy_to_user((char *) a, - (char *) &card, sizeof(ulong)))) - return i; - a += sizeof(ulong); - { - ulong l = (ulong) & dev; - if ((i = copy_to_user((char *) a, - (char *) &l, sizeof(ulong)))) - return i; - } - return 0; - case ICN_IOCTL_LOADBOOT: - if (dev.firstload) { - icn_disable_cards(); - dev.firstload = 0; - } - icn_stopcard(card); - return (icn_loadboot((u_char *) a, card)); - case ICN_IOCTL_LOADPROTO: - icn_stopcard(card); - if ((i = (icn_loadproto((u_char *) a, card)))) - return i; - if (card->doubleS0) - i = icn_loadproto((u_char *) (a + ICN_CODE_STAGE2), card->other); - return i; - break; - case ICN_IOCTL_ADDCARD: - if (!dev.firstload) - return -EBUSY; - if ((i = copy_from_user((char *) &cdef, (char *) a, sizeof(cdef)))) - return i; - return (icn_addcard(cdef.port, cdef.id1, cdef.id2)); - break; - case ICN_IOCTL_LEASEDCFG: - if (a) { - if (!card->leased) { - card->leased = 1; - while (card->ptype == ISDN_PTYPE_UNKNOWN) { - schedule_timeout(ICN_BOOT_TIMEOUT1); - } - schedule_timeout(ICN_BOOT_TIMEOUT1); - sprintf(cbuf, "00;FV2ON\n01;EAZ%c\n02;EAZ%c\n", - (a & 1)?'1':'C', (a & 2)?'2':'C'); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - printk(KERN_INFO - "icn: (%s) Leased-line mode enabled\n", - CID); - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - } else { - if (card->leased) { - card->leased = 0; - sprintf(cbuf, "00;FV2OFF\n"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - printk(KERN_INFO - "icn: (%s) Leased-line mode disabled\n", - CID); - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - } - return 0; - default: - return -EINVAL; - } - break; - case ISDN_CMD_DIAL: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if (card->leased) - break; - if ((c->arg & 255) < ICN_BCH) { - char *p; - char dial[50]; - char dcode[4]; - - a = c->arg; - p = c->parm.setup.phone; - if (*p == 's' || *p == 'S') { - /* Dial for SPV */ - p++; - strcpy(dcode, "SCA"); - } else - /* Normal Dial */ - strcpy(dcode, "CAL"); - strcpy(dial, p); - sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), - dcode, dial, c->parm.setup.si1, - c->parm.setup.si2, c->parm.setup.eazmsn); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_ACCEPTD: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->fw_rev >= 300) { - switch (card->l2_proto[a - 1]) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) a); - break; - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) a); - break; - } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - sprintf(cbuf, "%02d;DCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_ACCEPTB: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->fw_rev >= 300) - switch (card->l2_proto[a - 1]) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a); - break; - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a); - break; - } else - sprintf(cbuf, "%02d;BCON_R\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_HANGUP: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_SETEAZ: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if (card->leased) - break; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->ptype == ISDN_PTYPE_EURO) { - sprintf(cbuf, "%02d;MS%s%s\n", (int) a, - c->parm.num[0] ? "N" : "ALL", c->parm.num); - } else - sprintf(cbuf, "%02d;EAZ%s\n", (int) a, - c->parm.num[0] ? (char *)(c->parm.num) : "0123456789"); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_CLREAZ: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if (card->leased) - break; - if (c->arg < ICN_BCH) { - a = c->arg + 1; - if (card->ptype == ISDN_PTYPE_EURO) - sprintf(cbuf, "%02d;MSNC\n", (int) a); - else - sprintf(cbuf, "%02d;EAZC\n", (int) a); - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_SETL2: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ICN_BCH) { - a = c->arg; - switch (a >> 8) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1); - break; - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1); - break; - default: - return -EINVAL; - } - i = icn_writecmd(cbuf, strlen(cbuf), 0, card); - card->l2_proto[a & 255] = (a >> 8); - } - break; - case ISDN_CMD_GETL2: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ICN_BCH) - return card->l2_proto[c->arg & 255]; - else - return -ENODEV; - case ISDN_CMD_SETL3: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - return 0; - case ISDN_CMD_GETL3: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ICN_BCH) - return ISDN_PROTO_L3_TRANS; - else - return -ENODEV; - case ISDN_CMD_GETEAZ: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_SETSIL: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_GETSIL: - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - break; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - break; - default: - return -EINVAL; - } - return 0; -} - -/* - * Find card with given driverId - */ -static inline icn_card * -icn_findcard(int driverid) -{ - icn_card *p = cards; - - while (p) { - if (p->myid == driverid) - return p; - p = p->next; - } - return (icn_card *) 0; -} - -/* - * Wrapper functions for interface to linklevel - */ -static int -if_command(isdn_ctrl * c) -{ - icn_card *card = icn_findcard(c->driver); - - if (card) - return (icn_command(c, card)); - printk(KERN_ERR - "icn: if_command %d called with invalid driverId %d!\n", - c->command, c->driver); - return -ENODEV; -} - -static int -if_writecmd(const u_char * buf, int len, int user, int id, int channel) -{ - icn_card *card = icn_findcard(id); - - if (card) { - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - return (icn_writecmd(buf, len, user, card)); - } - printk(KERN_ERR - "icn: if_writecmd called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_readstatus(u_char * buf, int len, int user, int id, int channel) -{ - icn_card *card = icn_findcard(id); - - if (card) { - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - return (icn_readstatus(buf, len, user, card)); - } - printk(KERN_ERR - "icn: if_readstatus called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) -{ - icn_card *card = icn_findcard(id); - - if (card) { - if (!card->flags & ICN_FLAGS_RUNNING) - return -ENODEV; - return (icn_sendbuf(channel, ack, skb, card)); - } - printk(KERN_ERR - "icn: if_sendbuf called with invalid driverId!\n"); - return -ENODEV; -} - -/* - * Allocate a new card-struct, initialize it - * link it into cards-list and register it at linklevel. - */ -static icn_card * -icn_initcard(int port, char *id) -{ - icn_card *card; - int i; - - if (!(card = (icn_card *) kmalloc(sizeof(icn_card), GFP_KERNEL))) { - printk(KERN_WARNING - "icn: (%s) Could not allocate card-struct.\n", id); - return (icn_card *) 0; - } - memset((char *) card, 0, sizeof(icn_card)); - card->port = port; - card->interface.hl_hdrlen = 1; - card->interface.channels = ICN_BCH; - card->interface.maxbufsize = 4000; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = if_writecmd; - card->interface.readstat = if_readstatus; - card->interface.features = ISDN_FEATURE_L2_X75I | - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_P_UNKNOWN; - card->ptype = ISDN_PTYPE_UNKNOWN; - strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); - card->msg_buf_write = card->msg_buf; - card->msg_buf_read = card->msg_buf; - card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1]; - for (i = 0; i < ICN_BCH; i++) { - card->l2_proto[i] = ISDN_PROTO_L2_X75I; - skb_queue_head_init(&card->spqueue[i]); - } - card->next = cards; - cards = card; - if (!register_isdn(&card->interface)) { - cards = cards->next; - printk(KERN_WARNING - "icn: Unable to register %s\n", id); - kfree(card); - return (icn_card *) 0; - } - card->myid = card->interface.channels; - sprintf(card->regname, "icn-isdn (%s)", card->interface.id); - return card; -} - -static int -icn_addcard(int port, char *id1, char *id2) -{ - ulong flags; - icn_card *card; - icn_card *card2; - - save_flags(flags); - cli(); - if (!(card = icn_initcard(port, id1))) { - restore_flags(flags); - return -EIO; - } - if (!strlen(id2)) { - restore_flags(flags); - printk(KERN_INFO - "icn: (%s) ICN-2B, port 0x%x added\n", - card->interface.id, port); - return 0; - } - if (!(card2 = icn_initcard(port, id2))) { - restore_flags(flags); - printk(KERN_INFO - "icn: (%s) half ICN-4B, port 0x%x added\n", - card2->interface.id, port); - return 0; - } - card->doubleS0 = 1; - card->secondhalf = 0; - card->other = card2; - card2->doubleS0 = 1; - card2->secondhalf = 1; - card2->other = card; - restore_flags(flags); - printk(KERN_INFO - "icn: (%s and %s) ICN-4B, port 0x%x added\n", - card->interface.id, card2->interface.id, port); - return 0; -} - -#ifdef MODULE -#define icn_init init_module -#else -#ifdef COMPAT_HAS_NEW_SETUP -#include -static int __init -icn_setup(char *line) -{ - char *p, *str; - int ints[3]; - static char sid[20]; - 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) - membase = ints[2]; - if (strlen(str)) { - strcpy(sid, str); - icn_id = sid; - if ((p = strchr(sid, ','))) { - *p++ = 0; - strcpy(sid2, p); - icn_id2 = sid2; - } - } -#ifdef COMPAT_HAS_NEW_SETUP - return(1); -} -__setup("icn=", icn_setup); -#else -} -#endif -#endif /* MODULES */ - -int -icn_init(void) -{ - char *p; - char rev[10]; - - memset(&dev, 0, sizeof(icn_dev)); - dev.shmem = (icn_shmem *) ((unsigned long) membase & 0x0ffc000); - dev.channel = -1; - dev.mcard = NULL; - dev.firstload = 1; - - /* No symbols to export, hide all symbols */ - EXPORT_NO_SYMBOLS; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, " ??? "); - printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev, - (ulong) dev.shmem); - return (icn_addcard(portbase, icn_id, icn_id2)); -} - -#ifdef MODULE -void -cleanup_module(void) -{ - isdn_ctrl cmd; - icn_card *card = cards; - icn_card *last; - int i; - - icn_stopallcards(); - while (card) { - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - if (card->rvalid) { - OUTB_P(0, ICN_RUN); /* Reset Controller */ - OUTB_P(0, ICN_MAPRAM); /* Disable RAM */ - if (card->secondhalf || (!card->doubleS0)) { - release_region(card->port, ICN_PORTLEN); - card->rvalid = 0; - } - for (i = 0; i < ICN_BCH; i++) - icn_free_queue(card, i); - } - card = card->next; - } - card = cards; - while (card) { - last = card; - card = card->next; - kfree(last); - } - if (dev.mvalid) - release_shmem((ulong) dev.shmem, 0x4000); - printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n"); -} -#endif diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h deleted file mode 100644 index 541bed55..00000000 --- a/drivers/isdn/icn/icn.h +++ /dev/null @@ -1,400 +0,0 @@ -/* $Id$ - - * ISDN lowlevel-module for the ICN active ISDN-Card. - * - * Copyright 1994 by Fritz Elfert (fritz@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. - * - * $Log$ - * Revision 1.28 1997/10/10 15:56:18 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * - * Revision 1.27 1997/10/01 09:21:56 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.26 1997/02/14 12:23:16 fritz - * Added support for new insmod parameter handling. - * - * Revision 1.25 1997/02/10 10:10:31 fritz - * Changes for Kernel 2.1.X compatibility. - * Enhanced initialization, can recover from - * misconfiguration by other autoprobing drivers. - * - * Revision 1.24 1997/01/29 22:34:46 fritz - * Cleanup, Corrected D64S setup of 2nd channel. - * - * Revision 1.23 1996/12/17 18:47:55 tsbogend - * changed timeouts from absolute numbers to HZ based values - * - * Revision 1.22 1996/11/13 02:37:33 fritz - * Added delay include. - * - * Revision 1.21 1996/08/29 20:35:57 fritz - * Speed up B-Channel polling interval. - * - * Revision 1.20 1996/06/24 17:20:37 fritz - * Bugfixes in pollbchan_send(): - * - Using lock field of skbuff breaks networking. - * - Added channel locking - * - changed dequeuing scheme. - * Eliminated misc. compiler warnings. - * - * Revision 1.19 1996/06/06 13:58:35 fritz - * Changed code to be architecture independent - * - * Revision 1.18 1996/06/03 19:59:30 fritz - * Removed include of config.h - * - * Revision 1.17 1996/05/18 00:47:04 fritz - * Removed callback debug code. - * - * Revision 1.16 1996/05/17 15:46:43 fritz - * Removed own queue management. - * Changed queue management to use sk_buffs. - * - * Revision 1.15 1996/05/02 04:01:57 fritz - * Removed ICN_MAXCARDS - * - * Revision 1.14 1996/05/02 00:40:29 fritz - * Major rewrite to support more than one card - * with a single module. - * Support for new firmware. - * - * Revision 1.13 1996/04/20 16:51:41 fritz - * Increased status buffer. - * Misc. typos - * - * Revision 1.12 1996/01/22 05:01:22 fritz - * Revert to GPL. - * - * Revision 1.11 1995/12/18 18:25:00 fritz - * Support for ICN-2B Cards. - * Change for supporting user-settable service-octet. - * - * Revision 1.10 1995/10/29 21:43:10 fritz - * Added support for leased lines. - * - * Revision 1.9 1995/04/23 13:42:10 fritz - * Added some constants for distinguishing 1TR6 and DSS1 - * - * Revision 1.8 1995/03/25 23:18:55 fritz - * Changed ICN_PORTLEN to reflect correct number of ports. - * - * Revision 1.7 1995/03/15 12:52:06 fritz - * Some cleanup - * - * Revision 1.6 1995/02/20 03:49:22 fritz - * Fixed ICN_MAX_SQUEUE to correctly reflect outstanding bytes, not number - * of buffers. - * - * Revision 1.5 1995/01/29 23:36:50 fritz - * Minor cleanup. - * - * Revision 1.4 1995/01/09 07:41:20 fritz - * Added GPL-Notice - * - * Revision 1.3 1995/01/04 05:14:20 fritz - * removed include of linux/asm/string.h for compiling with Linux 1.1.76 - * - * Revision 1.2 1995/01/02 02:15:57 fritz - * Misc. Bugfixes - * - * Revision 1.1 1994/12/14 18:02:38 fritz - * Initial revision - * - */ - -#ifndef icn_h -#define icn_h - -#define ICN_IOCTL_SETMMIO 0 -#define ICN_IOCTL_GETMMIO 1 -#define ICN_IOCTL_SETPORT 2 -#define ICN_IOCTL_GETPORT 3 -#define ICN_IOCTL_LOADBOOT 4 -#define ICN_IOCTL_LOADPROTO 5 -#define ICN_IOCTL_LEASEDCFG 6 -#define ICN_IOCTL_GETDOUBLE 7 -#define ICN_IOCTL_DEBUGVAR 8 -#define ICN_IOCTL_ADDCARD 9 - -/* Struct for adding new cards */ -typedef struct icn_cdef { - int port; - char id1[10]; - char id2[10]; -} icn_cdef; - -#if defined(__KERNEL__) || defined(__DEBUGVAR__) - -#ifdef __KERNEL__ -/* Kernel includes */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif /* __KERNEL__ */ - -/* some useful macros for debugging */ -#ifdef ICN_DEBUG_PORT -#define OUTB_P(v,p) {printk(KERN_DEBUG "icn: outb_p(0x%02x,0x%03x)\n",v,p); outb_p(v,p);} -#else -#define OUTB_P outb -#endif - -/* Defaults for Port-Address and shared-memory */ -#define ICN_BASEADDR 0x320 -#define ICN_PORTLEN (0x04) -#define ICN_MEMADDR 0x0d0000 - -#define ICN_FLAGS_B1ACTIVE 1 /* B-Channel-1 is open */ -#define ICN_FLAGS_B2ACTIVE 2 /* B-Channel-2 is open */ -#define ICN_FLAGS_RUNNING 4 /* Cards driver activated */ -#define ICN_FLAGS_RBTIMER 8 /* cyclic scheduling of B-Channel-poll */ - -#define ICN_BOOT_TIMEOUT1 (HZ) /* Delay for Boot-download (jiffies) */ -#define ICN_CHANLOCK_DELAY (HZ/10) /* Delay for Channel-mapping (jiffies) */ - -#define ICN_TIMER_BCREAD (HZ/100) /* B-Channel poll-cycle */ -#define ICN_TIMER_DCREAD (HZ/2) /* D-Channel poll-cycle */ - -#define ICN_CODE_STAGE1 4096 /* Size of bootcode */ -#define ICN_CODE_STAGE2 65536 /* Size of protocol-code */ - -#define ICN_MAX_SQUEUE 8000 /* Max. outstanding send-data (2* hw-buf.) */ -#define ICN_FRAGSIZE (250) /* Max. size of send-fragments */ -#define ICN_BCH 2 /* Number of supported channels per card */ - -/* type-definitions for accessing the mmap-io-areas */ - -#define SHM_DCTL_OFFSET (0) /* Offset to data-controlstructures in shm */ -#define SHM_CCTL_OFFSET (0x1d2) /* Offset to comm-controlstructures in shm */ -#define SHM_CBUF_OFFSET (0x200) /* Offset to comm-buffers in shm */ -#define SHM_DBUF_OFFSET (0x2000) /* Offset to data-buffers in shm */ - -/* - * Layout of card's data buffers - */ -typedef struct { - unsigned char length; /* Bytecount of fragment (max 250) */ - unsigned char endflag; /* 0=last frag., 0xff=frag. continued */ - unsigned char data[ICN_FRAGSIZE]; /* The data */ - /* Fill to 256 bytes */ - char unused[0x100 - ICN_FRAGSIZE - 2]; -} frag_buf; - -/* - * Layout of card's shared memory - */ -typedef union { - struct { - unsigned char scns; /* Index to free SendFrag. */ - unsigned char scnr; /* Index to active SendFrag READONLY */ - unsigned char ecns; /* Index to free RcvFrag. READONLY */ - unsigned char ecnr; /* Index to valid RcvFrag */ - char unused[6]; - unsigned short fuell1; /* Internal Buf Bytecount */ - } data_control; - struct { - char unused[SHM_CCTL_OFFSET]; - unsigned char iopc_i; /* Read-Ptr Status-Queue READONLY */ - unsigned char iopc_o; /* Write-Ptr Status-Queue */ - unsigned char pcio_i; /* Write-Ptr Command-Queue */ - unsigned char pcio_o; /* Read-Ptr Command Queue READONLY */ - } comm_control; - struct { - char unused[SHM_CBUF_OFFSET]; - unsigned char pcio_buf[0x100]; /* Ring-Buffer Command-Queue */ - unsigned char iopc_buf[0x100]; /* Ring-Buffer Status-Queue */ - } comm_buffers; - struct { - char unused[SHM_DBUF_OFFSET]; - frag_buf receive_buf[0x10]; - frag_buf send_buf[0x10]; - } data_buffers; -} icn_shmem; - -/* - * Per card driver data - */ -typedef struct icn_card { - struct icn_card *next; /* Pointer to next device struct */ - struct icn_card *other; /* Pointer to other card for ICN4B */ - unsigned short port; /* Base-port-address */ - int myid; /* Driver-Nr. assigned by linklevel */ - int rvalid; /* IO-portregion has been requested */ - int leased; /* Flag: This Adapter is connected */ - /* to a leased line */ - unsigned short flags; /* Statusflags */ - int doubleS0; /* Flag: ICN4B */ - int secondhalf; /* Flag: Second half of a doubleS0 */ - int fw_rev; /* Firmware revision loaded */ - int ptype; /* Protocol type (1TR6 or Euro) */ - struct timer_list st_timer; /* Timer for Status-Polls */ - struct timer_list rb_timer; /* Timer for B-Channel-Polls */ - u_char rcvbuf[ICN_BCH][4096]; /* B-Channel-Receive-Buffers */ - int rcvidx[ICN_BCH]; /* Index for above buffers */ - int l2_proto[ICN_BCH]; /* Current layer-2-protocol */ - isdn_if interface; /* Interface to upper layer */ - int iptr; /* Index to imsg-buffer */ - char imsg[60]; /* Internal buf for status-parsing */ - char msg_buf[2048]; /* Buffer for status-messages */ - char *msg_buf_write; /* Writepointer for statusbuffer */ - char *msg_buf_read; /* Readpointer for statusbuffer */ - char *msg_buf_end; /* Pointer to end of statusbuffer */ - int sndcount[ICN_BCH]; /* Byte-counters for B-Ch.-send */ - int xlen[ICN_BCH]; /* Byte-counters/Flags for sent-ACK */ - struct sk_buff *xskb[ICN_BCH]; - /* Current transmitted skb */ - struct sk_buff_head - spqueue[ICN_BCH]; /* Sendqueue */ - char regname[35]; /* Name used for request_region */ - u_char xmit_lock[ICN_BCH]; /* Semaphore for pollbchan_send() */ -} icn_card; - -/* - * Main driver data - */ -typedef struct icn_dev { - icn_shmem *shmem; /* Pointer to memory-mapped-buffers */ - int mvalid; /* IO-shmem has been requested */ - int channel; /* Currently mapped channel */ - struct icn_card *mcard; /* Currently mapped card */ - int chanlock; /* Semaphore for channel-mapping */ - int firstload; /* Flag: firmware never loaded */ -} icn_dev; - -typedef icn_dev *icn_devptr; - -#ifdef __KERNEL__ - -static icn_card *cards = (icn_card *) 0; -static u_char chan2bank[] = -{0, 4, 8, 12}; /* for icn_map_channel() */ - -static icn_dev dev; - -/* With modutils >= 1.1.67 Integers can be changed while loading a - * module. For this reason define the Port-Base an Shmem-Base as - * integers. - */ -static int portbase = ICN_BASEADDR; -static int membase = ICN_MEMADDR; -static char *icn_id = "\0"; -static char *icn_id2 = "\0"; - -#ifdef MODULE -MODULE_AUTHOR("Fritz Elfert"); -MODULE_PARM(portbase, "i"); -MODULE_PARM_DESC(portbase, "Port adress of first card"); -MODULE_PARM(membase, "i"); -MODULE_PARM_DESC(membase, "Shared memory adress of all cards"); -MODULE_PARM(icn_id, "s"); -MODULE_PARM_DESC(icn_id, "ID-String of first card"); -MODULE_PARM(icn_id2, "s"); -MODULE_PARM_DESC(icn_id2, "ID-String of first card, second S0 (4B only)"); -#endif - -#endif /* __KERNEL__ */ - -/* Utility-Macros */ - -/* Macros for accessing ports */ -#define ICN_CFG (card->port) -#define ICN_MAPRAM (card->port+1) -#define ICN_RUN (card->port+2) -#define ICN_BANK (card->port+3) - -/* Return true, if there is a free transmit-buffer */ -#define sbfree (((readb(&dev.shmem->data_control.scns)+1) & 0xf) != \ - readb(&dev.shmem->data_control.scnr)) - -/* Switch to next transmit-buffer */ -#define sbnext (writeb((readb(&dev.shmem->data_control.scns)+1) & 0xf, \ - &dev.shmem->data_control.scns)) - -/* Shortcuts for transmit-buffer-access */ -#define sbuf_n dev.shmem->data_control.scns -#define sbuf_d dev.shmem->data_buffers.send_buf[readb(&sbuf_n)].data -#define sbuf_l dev.shmem->data_buffers.send_buf[readb(&sbuf_n)].length -#define sbuf_f dev.shmem->data_buffers.send_buf[readb(&sbuf_n)].endflag - -/* Return true, if there is receive-data is available */ -#define rbavl (readb(&dev.shmem->data_control.ecnr) != \ - readb(&dev.shmem->data_control.ecns)) - -/* Switch to next receive-buffer */ -#define rbnext (writeb((readb(&dev.shmem->data_control.ecnr)+1) & 0xf, \ - &dev.shmem->data_control.ecnr)) - -/* Shortcuts for receive-buffer-access */ -#define rbuf_n dev.shmem->data_control.ecnr -#define rbuf_d dev.shmem->data_buffers.receive_buf[readb(&rbuf_n)].data -#define rbuf_l dev.shmem->data_buffers.receive_buf[readb(&rbuf_n)].length -#define rbuf_f dev.shmem->data_buffers.receive_buf[readb(&rbuf_n)].endflag - -/* Shortcuts for command-buffer-access */ -#define cmd_o (dev.shmem->comm_control.pcio_o) -#define cmd_i (dev.shmem->comm_control.pcio_i) - -/* Return free space in command-buffer */ -#define cmd_free ((readb(&cmd_i)>=readb(&cmd_o))? \ - 0x100-readb(&cmd_i)+readb(&cmd_o): \ - readb(&cmd_o)-readb(&cmd_i)) - -/* Shortcuts for message-buffer-access */ -#define msg_o (dev.shmem->comm_control.iopc_o) -#define msg_i (dev.shmem->comm_control.iopc_i) - -/* Return length of Message, if avail. */ -#define msg_avail ((readb(&msg_o)>readb(&msg_i))? \ - 0x100-readb(&msg_o)+readb(&msg_i): \ - readb(&msg_i)-readb(&msg_o)) - -#define CID (card->interface.id) - -#define MIN(a,b) ((ab)?a:b) - -/* Hopefully, a separate resource-registration-scheme for shared-memory - * will be introduced into the kernel. Until then, we use the normal - * routines, designed for port-registration. - */ -#define check_shmem check_region -#define release_shmem release_region -#define request_shmem request_region - -#endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */ -#endif /* icn_h */ diff --git a/drivers/isdn/isdn_audio.c b/drivers/isdn/isdn_audio.c deleted file mode 100644 index 3e36e5bf..00000000 --- a/drivers/isdn/isdn_audio.c +++ /dev/null @@ -1,806 +0,0 @@ -/* $Id$ - - * 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) - * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.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. - * - * $Log$ - * Revision 1.16 1999/08/06 12:47:35 calle - * Using __GNUC__ == 2 && __GNUC_MINOR__ < 95 how to define - * ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT - * - * Revision 1.15 1999/08/06 12:02:52 calle - * egcs 2.95 complain about invalid asm statement: - * "fixed or forbidden register 2 (cx) was spilled for class CREG." - * Using ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT and not - * define it at the moment. - * - * Revision 1.14 1999/07/11 17:14:06 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.13 1999/04/12 12:33:09 fritz - * Changes from 2.0 tree. - * - * Revision 1.12 1998/07/26 18:48:43 armin - * Added silence detection in voice receive mode. - * - * Revision 1.11 1998/04/10 10:35:10 paul - * fixed (silly?) warnings from egcs on Alpha. - * - * Revision 1.10 1998/02/20 17:09:40 fritz - * Changes for recent kernels. - * - * Revision 1.9 1997/10/01 09:20:25 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.8 1997/03/02 14:29:16 fritz - * More ttyI related cleanup. - * - * Revision 1.7 1997/02/03 22:44:11 fritz - * Reformatted according CodingStyle - * - * Revision 1.6 1996/06/06 14:43:31 fritz - * Changed to support DTMF decoding on audio playback also. - * - * Revision 1.5 1996/06/05 02:24:08 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.4 1996/05/17 03:48:01 fritz - * Removed some test statements. - * Added revision string. - * - * Revision 1.3 1996/05/10 08:48:11 fritz - * Corrected adpcm bugs. - * - * Revision 1.2 1996/04/30 09:31:17 fritz - * General rewrite. - * - * Revision 1.1.1.1 1996/04/28 12:25:40 fritz - * Taken under CVS control - * - */ - -#define __NO_VERSION__ -#include -#include -#include "isdn_audio.h" -#include "isdn_common.h" - -char *isdn_audio_revision = "$Revision$"; - -/* - * Misc. lookup-tables. - */ - -/* ulaw -> signed 16-bit */ -static short isdn_audio_ulaw_to_s16[] = -{ - 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84, - 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84, - 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84, - 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84, - 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804, - 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004, - 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444, - 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844, - 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64, - 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64, - 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74, - 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74, - 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc, - 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c, - 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0, - 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000, - 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c, - 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c, - 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c, - 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c, - 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc, - 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc, - 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc, - 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc, - 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c, - 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c, - 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c, - 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c, - 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, - 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084, - 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, - 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000 -}; - -/* alaw -> signed 16-bit */ -static short isdn_audio_alaw_to_s16[] = -{ - 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4, - 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74, - 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4, - 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64, - 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4, - 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4, - 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4, - 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4, - 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64, - 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34, - 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844, - 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24, - 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64, - 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4, - 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964, - 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4, - 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24, - 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94, - 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924, - 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94, - 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24, - 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14, - 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24, - 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14, - 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4, - 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54, - 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4, - 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64, - 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4, - 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4, - 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4, - 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4 -}; - -/* alaw -> ulaw */ -static char isdn_audio_alaw_to_ulaw[] = -{ - 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49, - 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57, - 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41, - 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f, - 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d, - 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b, - 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45, - 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53, - 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47, - 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55, - 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f, - 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e, - 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b, - 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59, - 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43, - 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51, - 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a, - 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58, - 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42, - 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50, - 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e, - 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c, - 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46, - 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54, - 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48, - 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56, - 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40, - 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f, - 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c, - 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a, - 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44, - 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52 -}; - -/* ulaw -> alaw */ -static char isdn_audio_ulaw_to_alaw[] = -{ - 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35, - 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25, - 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d, - 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d, - 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31, - 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21, - 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9, - 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9, - 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47, - 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf, - 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f, - 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33, - 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23, - 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b, - 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b, - 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b, - 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34, - 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24, - 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c, - 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c, - 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30, - 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20, - 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8, - 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8, - 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46, - 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde, - 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e, - 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32, - 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22, - 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a, - 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a, - 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a -}; - -#define NCOEFF 16 /* number of frequencies to be analyzed */ -#define DTMF_TRESH 50000 /* above this is dtmf */ -#define SILENCE_TRESH 100 /* below this is silence */ -#define H2_TRESH 10000 /* 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] = -{ - 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] = -{ - {'1', '2', '3', 'A'}, - {'4', '5', '6', 'B'}, - {'7', '8', '9', 'C'}, - {'*', '0', '#', 'D'} -}; - - -/* - * egcs 2.95 complain about invalid asm statement: - * "fixed or forbidden register 2 (cx) was spilled for class CREG." - */ -#if ((CPU == 386) || (CPU == 486) || (CPU == 586)) && defined(__GNUC__) -#if __GNUC__ == 2 && __GNUC_MINOR__ < 95 -#define ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT -#endif -#endif - -#ifdef ISDN_AUDIO_OPTIMIZE_ON_X386_WITH_ASM_IF_GCC_ALLOW_IT -static inline void -isdn_audio_tlookup(const void *table, void *buff, unsigned long n) -{ - __asm__("cld\n" - "1:\tlodsb\n\t" - "xlatb\n\t" - "stosb\n\t" - "loop 1b\n\t" - : : "b"((long) table), "c"(n), "D"((long) buff), "S"((long) buff) - : "bx", "cx", "di", "si", "ax"); -} - -#else -static inline void -isdn_audio_tlookup(const char *table, char *buff, unsigned long n) -{ - while (n--) - *buff++ = table[*(unsigned char *)buff]; -} -#endif - -void -isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len) -{ - isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len); -} - -void -isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len) -{ - isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len); -} - -/* - * linear <-> adpcm conversion stuff - * Most parts from the mgetty-package. - * (C) by Gert Doering and Klaus Weidner - * Used by permission of Gert Doering - */ - - -#define ZEROTRAP /* turn on the trap as per the MIL-STD */ -#undef ZEROTRAP -#define BIAS 0x84 /* define the add-in bias for 16 bit samples */ -#define CLIP 32635 - -static unsigned char -isdn_audio_linear2ulaw(int sample) -{ - static int exp_lut[256] = - { - 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 - }; - int sign, - exponent, - mantissa; - unsigned char ulawbyte; - - /* Get the sample into sign-magnitude. */ - sign = (sample >> 8) & 0x80; /* set aside the sign */ - if (sign != 0) - sample = -sample; /* get magnitude */ - if (sample > CLIP) - sample = CLIP; /* clip the magnitude */ - - /* Convert from 16 bit linear to ulaw. */ - sample = sample + BIAS; - exponent = exp_lut[(sample >> 7) & 0xFF]; - mantissa = (sample >> (exponent + 3)) & 0x0F; - ulawbyte = ~(sign | (exponent << 4) | mantissa); -#ifdef ZEROTRAP - /* optional CCITT trap */ - if (ulawbyte == 0) - ulawbyte = 0x02; -#endif - return (ulawbyte); -} - - -static int Mx[3][8] = -{ - {0x3800, 0x5600, 0, 0, 0, 0, 0, 0}, - {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0}, - {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607}, -}; - -static int bitmask[9] = -{ - 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff -}; - -static int -isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len) -{ - while (s->nleft < s->nbits) { - int d = *((*in)++); - (*len)--; - s->word = (s->word << 8) | d; - s->nleft += 8; - } - s->nleft -= s->nbits; - return (s->word >> s->nleft) & bitmask[s->nbits]; -} - -static void -isdn_audio_put_bits(int data, int nbits, adpcm_state * s, - unsigned char **out, int *len) -{ - s->word = (s->word << nbits) | (data & bitmask[nbits]); - s->nleft += nbits; - while (s->nleft >= 8) { - int d = (s->word >> (s->nleft - 8)); - *(out[0]++) = d & 255; - (*len)++; - s->nleft -= 8; - } -} - -adpcm_state * -isdn_audio_adpcm_init(adpcm_state * s, int nbits) -{ - if (!s) - s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC); - if (s) { - s->a = 0; - s->d = 5; - s->word = 0; - s->nleft = 0; - s->nbits = nbits; - } - return s; -} - -dtmf_state * -isdn_audio_dtmf_init(dtmf_state * s) -{ - if (!s) - s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC); - if (s) { - s->idx = 0; - s->last = ' '; - } - return s; -} - -/* - * Decompression of adpcm data to a/u-law - * - */ - -int -isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in, - unsigned char *out, int len) -{ - int a = s->a; - int d = s->d; - int nbits = s->nbits; - int olen = 0; - - while (len) { - int e = isdn_audio_get_bits(s, &in, &len); - int sign; - - if (nbits == 4 && e == 0) - d = 4; - sign = (e >> (nbits - 1)) ? -1 : 1; - e &= bitmask[nbits - 1]; - a += sign * ((e << 1) + 1) * d >> 1; - if (d & 1) - a++; - if (fmt) - *out++ = isdn_audio_ulaw_to_alaw[ - isdn_audio_linear2ulaw(a << 2)]; - else - *out++ = isdn_audio_linear2ulaw(a << 2); - olen++; - d = (d * Mx[nbits - 2][e] + 0x2000) >> 14; - if (d < 5) - d = 5; - } - s->a = a; - s->d = d; - return olen; -} - -int -isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out) -{ - int olen = 0; - - if (s->nleft) - isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen); - return olen; -} - -int -isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in, - unsigned char *out, int len) -{ - int a = s->a; - int d = s->d; - int nbits = s->nbits; - int olen = 0; - - while (len--) { - int e = 0, - nmax = 1 << (nbits - 1); - int sign, - delta; - - if (fmt) - delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a; - else - delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a; - if (delta < 0) { - e = nmax; - delta = -delta; - } - while (--nmax && delta > d) { - delta -= d; - e++; - } - if (nbits == 4 && ((e & 0x0f) == 0)) - e = 8; - isdn_audio_put_bits(e, nbits, s, &out, &olen); - sign = (e >> (nbits - 1)) ? -1 : 1; - e &= bitmask[nbits - 1]; - - a += sign * ((e << 1) + 1) * d >> 1; - if (d & 1) - a++; - d = (d * Mx[nbits - 2][e] + 0x2000) >> 14; - if (d < 5) - d = 5; - } - s->a = a; - s->d = d; - return olen; -} - -/* - * Goertzel algorithm. - * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/ - * for more info. - * Result is stored into an sk_buff and queued up for later - * evaluation. - */ -static void -isdn_audio_goertzel(int *sample, modem_info * info) -{ - int sk, - sk1, - sk2; - int k, - n; - struct sk_buff *skb; - int *result; - - skb = dev_alloc_skb(sizeof(int) * NCOEFF); - if (!skb) { - printk(KERN_WARNING - "isdn_audio: Could not alloc DTMF result for ttyI%d\n", - info->line); - return; - } - result = (int *) skb_put(skb, sizeof(int) * NCOEFF); - for (k = 0; k < NCOEFF; k++) { - sk = sk1 = sk2 = 0; - for (n = 0; n < DTMF_NPOINTS; n++) { - sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2; - sk2 = sk1; - sk1 = sk; - } - result[k] = - ((sk * sk) >> AMP_BITS) - - ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) + - ((sk2 * sk2) >> AMP_BITS); - } - skb_queue_tail(&info->dtmf_queue, skb); - isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); -} - -void -isdn_audio_eval_dtmf(modem_info * info) -{ - struct sk_buff *skb; - int *result; - dtmf_state *s; - int silence; - int i; - int di; - int ch; - unsigned long flags; - int grp[2]; - char what; - char *p; - - while ((skb = skb_dequeue(&info->dtmf_queue))) { - result = (int *) skb->data; - s = info->dtmf_state; - grp[LOGRP] = grp[HIGRP] = -2; - silence = 0; - 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 == 8) - 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 != '.')) { - printk(KERN_DEBUG "dtmf: tt='%c'\n", what); - p = skb->data; - *p++ = 0x10; - *p = what; - skb_trim(skb, 2); - if (skb_headroom(skb) < sizeof(isdn_audio_skb)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return; - } - ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; - ISDN_AUDIO_SKB_LOCK(skb) = 0; - save_flags(flags); - cli(); - di = info->isdn_driver; - ch = info->isdn_channel; - __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); - dev->drv[di]->rcvcount[ch] += 2; - restore_flags(flags); - /* Schedule dequeuing */ - if ((dev->modempoll) && (info->rcvsched)) - isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); - wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); - } else - kfree_skb(skb); - s->last = what; - } -} - -/* - * Decode DTMF tones, queue result in separate sk_buf for - * later examination. - * Parameters: - * s = pointer to state-struct. - * buf = input audio data - * len = size of audio data. - * fmt = audio data format (0 = ulaw, 1 = alaw) - */ -void -isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt) -{ - dtmf_state *s = info->dtmf_state; - int i; - int c; - - while (len) { - c = MIN(len, (DTMF_NPOINTS - s->idx)); - if (c <= 0) - break; - for (i = 0; i < c; i++) { - if (fmt) - s->buf[s->idx++] = - isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS); - else - s->buf[s->idx++] = - isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS); - } - if (s->idx == DTMF_NPOINTS) { - isdn_audio_goertzel(s->buf, info); - s->idx = 0; - } - len -= c; - } -} - -silence_state * -isdn_audio_silence_init(silence_state * s) -{ - if (!s) - s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC); - if (s) { - s->idx = 0; - s->state = 0; - } - return s; -} - -void -isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt) -{ - silence_state *s = info->silence_state; - int i; - signed char c; - - if (!info->emu.vpar[1]) return; - - for (i = 0; i < len; i++) { - if (fmt) - c = isdn_audio_alaw_to_ulaw[*buf++]; - else - c = *buf++; - - if (c > 0) c -= 128; - c = abs(c); - - if (c > (info->emu.vpar[1] * 4)) { - s->idx = 0; - s->state = 1; - } else { - if (s->idx < 210000) s->idx++; - } - } -} - -void -isdn_audio_put_dle_code(modem_info * info, u_char code) -{ - struct sk_buff *skb; - unsigned long flags; - int di; - int ch; - char *p; - - skb = dev_alloc_skb(2); - if (!skb) { - printk(KERN_WARNING - "isdn_audio: Could not alloc skb for ttyI%d\n", - info->line); - return; - } - p = (char *) skb_put(skb, 2); - p[0] = 0x10; - p[1] = code; - if (skb_headroom(skb) < sizeof(isdn_audio_skb)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return; - } - ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; - ISDN_AUDIO_SKB_LOCK(skb) = 0; - save_flags(flags); - cli(); - di = info->isdn_driver; - ch = info->isdn_channel; - __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); - dev->drv[di]->rcvcount[ch] += 2; - restore_flags(flags); - /* Schedule dequeuing */ - if ((dev->modempoll) && (info->rcvsched)) - isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); - wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); -} - -void -isdn_audio_eval_silence(modem_info * info) -{ - silence_state *s = info->silence_state; - char what; - - what = ' '; - - if (s->idx > (info->emu.vpar[2] * 800)) { - s->idx = 0; - if (!s->state) { /* silence from beginning of rec */ - what = 's'; - } else { - what = 'q'; - } - } - if ((what == 's') || (what == 'q')) { - printk(KERN_DEBUG "ttyI%d: %s\n", info->line, - (what=='s') ? "silence":"quiet"); - isdn_audio_put_dle_code(info, what); - } -} diff --git a/drivers/isdn/isdn_audio.h b/drivers/isdn/isdn_audio.h deleted file mode 100644 index 4b640fc1..00000000 --- a/drivers/isdn/isdn_audio.h +++ /dev/null @@ -1,77 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, audio conversion and compression (linklevel). - * - * Copyright 1994-1999 by Fritz Elfert (fritz@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. - * - * $Log$ - * Revision 1.7 1999/04/12 12:33:11 fritz - * Changes from 2.0 tree. - * - * Revision 1.6 1998/07/26 18:48:44 armin - * Added silence detection in voice receive mode. - * - * Revision 1.5 1997/02/03 22:45:21 fritz - * Reformatted according CodingStyle - * - * Revision 1.4 1996/06/06 14:43:32 fritz - * Changed to support DTMF decoding on audio playback also. - * - * Revision 1.3 1996/06/05 02:24:09 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.2 1996/05/10 08:48:32 fritz - * Corrected adpcm bugs. - * - * Revision 1.1 1996/04/30 09:29:06 fritz - * Taken under CVS control. - * - */ - -#define DTMF_NPOINTS 205 /* Number of samples for DTMF recognition */ -typedef struct adpcm_state { - int a; - int d; - int word; - int nleft; - int nbits; -} adpcm_state; - -typedef struct dtmf_state { - char last; - int idx; - int buf[DTMF_NPOINTS]; -} dtmf_state; - -typedef struct silence_state { - int state; - unsigned int idx; -} silence_state; - -extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long); -extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long); -extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int); -extern int isdn_audio_adpcm2xlaw(adpcm_state *, int, unsigned char *, unsigned char *, int); -extern int isdn_audio_xlaw2adpcm(adpcm_state *, int, unsigned char *, unsigned char *, int); -extern int isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out); -extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int); -extern void isdn_audio_eval_dtmf(modem_info *); -dtmf_state *isdn_audio_dtmf_init(dtmf_state *); -extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int); -extern void isdn_audio_eval_silence(modem_info *); -silence_state *isdn_audio_silence_init(silence_state *); -extern void isdn_audio_put_dle_code(modem_info *, u_char); diff --git a/drivers/isdn/isdn_bsdcomp.c b/drivers/isdn/isdn_bsdcomp.c deleted file mode 100644 index 77431df8..00000000 --- a/drivers/isdn/isdn_bsdcomp.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * BSD compression module - * - * Patched version for ISDN syncPPP written 1997/1998 by Michael Hipp - * The whole module is now SKB based. - * - * Compile with: - * gcc -O2 -I/usr/src/linux/include -D__KERNEL__ -DMODULE -c isdn_bsdcomp.c - */ - -/* - * Original copyright notice: - * - * Copyright (c) 1985, 1986 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * James A. Woods, derived from original work by Spencer Thomas - * and Joseph Orost. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef MODULE -#error This file must be compiled as a module. -#endif - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* used in new tty drivers */ -#include /* used in new tty drivers */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -/* #include */ -#include -#include -#include -#include - -#include "isdn_ppp.h" - -#define BSD_VERSION(x) ((x) >> 5) -#define BSD_NBITS(x) ((x) & 0x1F) - -#define BSD_CURRENT_VERSION 1 - -#define DEBUG 1 - -/* - * A dictionary for doing BSD compress. - */ - -struct bsd_dict { - u32 fcode; - u16 codem1; /* output of hash table -1 */ - u16 cptr; /* map code to hash table entry */ -}; - -struct bsd_db { - int totlen; /* length of this structure */ - unsigned int hsize; /* size of the hash table */ - unsigned char hshift; /* used in hash function */ - unsigned char n_bits; /* current bits/code */ - unsigned char maxbits; /* maximum bits/code */ - unsigned char debug; /* non-zero if debug desired */ - unsigned char unit; /* ppp unit number */ - u16 seqno; /* sequence # of next packet */ - unsigned int mru; /* size of receive (decompress) bufr */ - unsigned int maxmaxcode; /* largest valid code */ - unsigned int max_ent; /* largest code in use */ - unsigned int in_count; /* uncompressed bytes, aged */ - unsigned int bytes_out; /* compressed bytes, aged */ - unsigned int ratio; /* recent compression ratio */ - unsigned int checkpoint; /* when to next check the ratio */ - unsigned int clear_count; /* times dictionary cleared */ - unsigned int incomp_count; /* incompressible packets */ - unsigned int incomp_bytes; /* incompressible bytes */ - unsigned int uncomp_count; /* uncompressed packets */ - unsigned int uncomp_bytes; /* uncompressed bytes */ - unsigned int comp_count; /* compressed packets */ - unsigned int comp_bytes; /* compressed bytes */ - unsigned short *lens; /* array of lengths of codes */ - struct bsd_dict *dict; /* dictionary */ - int xmit; -}; - -#define BSD_OVHD 2 /* BSD compress overhead/packet */ -#define MIN_BSD_BITS 9 -#define BSD_INIT_BITS MIN_BSD_BITS -#define MAX_BSD_BITS 15 - -/* - * the next two codes should not be changed lightly, as they must not - * lie within the contiguous general code space. - */ -#define CLEAR 256 /* table clear output code */ -#define FIRST 257 /* first free entry */ -#define LAST 255 - -#define MAXCODE(b) ((1 << (b)) - 1) -#define BADCODEM1 MAXCODE(MAX_BSD_BITS); - -#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \ - ^ (unsigned long)(prefix)) -#define BSD_KEY(prefix,suffix) ((((unsigned long)(suffix)) << 16) \ - + (unsigned long)(prefix)) - -#define CHECK_GAP 10000 /* Ratio check interval */ - -#define RATIO_SCALE_LOG 8 -#define RATIO_SCALE (1<>RATIO_SCALE_LOG) - -/* - * clear the dictionary - */ - -static void bsd_clear(struct bsd_db *db) -{ - db->clear_count++; - db->max_ent = FIRST-1; - db->n_bits = BSD_INIT_BITS; - db->bytes_out = 0; - db->in_count = 0; - db->incomp_count = 0; - db->ratio = 0; - db->checkpoint = CHECK_GAP; -} - -/* - * If the dictionary is full, then see if it is time to reset it. - * - * Compute the compression ratio using fixed-point arithmetic - * with 8 fractional bits. - * - * Since we have an infinite stream instead of a single file, - * watch only the local compression ratio. - * - * Since both peers must reset the dictionary at the same time even in - * the absence of CLEAR codes (while packets are incompressible), they - * must compute the same ratio. - */ -static int bsd_check (struct bsd_db *db) /* 1=output CLEAR */ -{ - unsigned int new_ratio; - - if (db->in_count >= db->checkpoint) - { - /* age the ratio by limiting the size of the counts */ - if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX) - { - db->in_count -= (db->in_count >> 2); - db->bytes_out -= (db->bytes_out >> 2); - } - - db->checkpoint = db->in_count + CHECK_GAP; - - if (db->max_ent >= db->maxmaxcode) - { - /* Reset the dictionary only if the ratio is worse, - * or if it looks as if it has been poisoned - * by incompressible data. - * - * This does not overflow, because - * db->in_count <= RATIO_MAX. - */ - - new_ratio = db->in_count << RATIO_SCALE_LOG; - if (db->bytes_out != 0) - { - new_ratio /= db->bytes_out; - } - - if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE) - { - bsd_clear (db); - return 1; - } - db->ratio = new_ratio; - } - } - return 0; -} - -/* - * Return statistics. - */ - -static void bsd_stats (void *state, struct compstat *stats) -{ - struct bsd_db *db = (struct bsd_db *) state; - - stats->unc_bytes = db->uncomp_bytes; - stats->unc_packets = db->uncomp_count; - stats->comp_bytes = db->comp_bytes; - stats->comp_packets = db->comp_count; - stats->inc_bytes = db->incomp_bytes; - stats->inc_packets = db->incomp_count; - stats->in_count = db->in_count; - stats->bytes_out = db->bytes_out; -} - -/* - * Reset state, as on a CCP ResetReq. - */ -static void bsd_reset (void *state,unsigned char code, unsigned char id, - unsigned char *data, unsigned len, - struct isdn_ppp_resetparams *rsparm) -{ - struct bsd_db *db = (struct bsd_db *) state; - - bsd_clear(db); - db->seqno = 0; - db->clear_count = 0; -} - -/* - * Release the compression structure - */ -static void bsd_free (void *state) -{ - struct bsd_db *db = (struct bsd_db *) state; - - if (db) { - /* - * Release the dictionary - */ - if (db->dict) { - vfree (db->dict); - db->dict = NULL; - } - - /* - * Release the string buffer - */ - if (db->lens) { - vfree (db->lens); - db->lens = NULL; - } - - /* - * Finally release the structure itself. - */ - kfree (db); - MOD_DEC_USE_COUNT; - } -} - - -/* - * Allocate space for a (de) compressor. - */ -static void *bsd_alloc (struct isdn_ppp_comp_data *data) -{ - int bits; - unsigned int hsize, hshift, maxmaxcode; - struct bsd_db *db; - int decomp; - - static unsigned int htab[][2] = { - { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , - { 9001 , 5 } , { 18013 , 6 } , { 35023 , 7 } , { 69001 , 8 } - }; - - if (data->optlen != 1 || data->num != CI_BSD_COMPRESS - || BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION) - return NULL; - - bits = BSD_NBITS(data->options[0]); - - if(bits < 9 || bits > 15) - return NULL; - - hsize = htab[bits-9][0]; - hshift = htab[bits-9][1]; - - /* - * Allocate the main control structure for this instance. - */ - maxmaxcode = MAXCODE(bits); - db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL); - if (!db) - return NULL; - - memset (db, 0, sizeof(struct bsd_db)); - - db->xmit = data->flags & IPPP_COMP_FLAG_XMIT; - decomp = db->xmit ? 0 : 1; - - /* - * 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)); - 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. - */ - if (!decomp) - db->lens = NULL; - else { - db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) * - sizeof (db->lens[0])); - if (!db->lens) { - bsd_free (db); /* calls MOD_DEC_USE_COUNT; */ - return (NULL); - } - } - - /* - * Initialize the data information for the compression code - */ - db->totlen = sizeof (struct bsd_db) + (sizeof (struct bsd_dict) * hsize); - db->hsize = hsize; - db->hshift = hshift; - db->maxmaxcode = maxmaxcode; - db->maxbits = bits; - - return (void *) db; -} - -/* - * Initialize the database. - */ -static int bsd_init (void *state, struct isdn_ppp_comp_data *data, int unit, int debug) -{ - struct bsd_db *db = state; - int indx; - int decomp; - - if(!state || !data) { - printk(KERN_ERR "isdn_bsd_init: [%d] ERR, state %lx data %lx\n",unit,(long)state,(long)data); - return 0; - } - - decomp = db->xmit ? 0 : 1; - - if (data->optlen != 1 || data->num != CI_BSD_COMPRESS - || (BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION) - || (BSD_NBITS(data->options[0]) != db->maxbits) - || (decomp && db->lens == NULL)) { - printk(KERN_ERR "isdn_bsd: %d %d %d %d %lx\n",data->optlen,data->num,data->options[0],decomp,(unsigned long)db->lens); - return 0; - } - - if (decomp) - for(indx=LAST;indx>=0;indx--) - db->lens[indx] = 1; - - indx = db->hsize; - while (indx-- != 0) { - db->dict[indx].codem1 = BADCODEM1; - db->dict[indx].cptr = 0; - } - - db->unit = unit; - db->mru = 0; - - db->debug = 1; - - bsd_reset(db,0,0,NULL,0,NULL); - - return 1; -} - -/* - * Obtain pointers to the various structures in the compression tables - */ - -#define dict_ptrx(p,idx) &(p->dict[idx]) -#define lens_ptrx(p,idx) &(p->lens[idx]) - -#ifdef DEBUG -static unsigned short *lens_ptr(struct bsd_db *db, int idx) -{ - if ((unsigned int) idx > (unsigned int) db->maxmaxcode) { - printk (KERN_DEBUG "<9>ppp: lens_ptr(%d) > max\n", idx); - idx = 0; - } - return lens_ptrx (db, idx); -} - -static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx) -{ - if ((unsigned int) idx >= (unsigned int) db->hsize) { - printk (KERN_DEBUG "<9>ppp: dict_ptr(%d) > max\n", idx); - idx = 0; - } - return dict_ptrx (db, idx); -} - -#else -#define lens_ptr(db,idx) lens_ptrx(db,idx) -#define dict_ptr(db,idx) dict_ptrx(db,idx) -#endif - -/* - * compress a packet - */ -static int bsd_compress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,int proto) -{ - struct bsd_db *db; - int hshift; - unsigned int max_ent; - unsigned int n_bits; - unsigned int bitno; - unsigned long accm; - int ent; - unsigned long fcode; - struct bsd_dict *dictp; - unsigned char c; - 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; \ - 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); \ - } -#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; - max_ent = db->max_ent; - n_bits = db->n_bits; - bitno = 32; - accm = 0; - mxcode = MAXCODE (n_bits); - - /* This is the PPP header information */ - if(skb_out && skb_tailroom(skb_out) >= 2) { - char *v = skb_put(skb_out,2); - /* we only push our own data on the header, - AC,PC and protos is pushed by caller */ - v[0] = db->seqno >> 8; - v[1] = db->seqno; - } - - ilen = ++isize; /* This is off by one, but that is what is in draft! */ - - while (--ilen > 0) { - c = *rptr++; - fcode = BSD_KEY (ent, c); - hval = BSD_HASH (ent, c, hshift); - dictp = dict_ptr (db, hval); - - /* Validate and then check the entry. */ - if (dictp->codem1 >= max_ent) - goto nomatch; - - if (dictp->fcode == fcode) { - ent = dictp->codem1 + 1; - continue; /* found (prefix,suffix) */ - } - - /* continue probing until a match or invalid entry */ - 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); - 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; - -nomatch: - OUTPUT(ent); /* output the prefix */ - - /* code -> hashtable */ - if (max_ent < db->maxmaxcode) { - struct bsd_dict *dictp2; - struct bsd_dict *dictp3; - int indx; - - /* expand code size if needed */ - if (max_ent >= mxcode) { - db->n_bits = ++n_bits; - mxcode = MAXCODE (n_bits); - } - - /* - * Invalidate old hash table entry using - * this code, and then take it over. - */ - dictp2 = dict_ptr (db, max_ent + 1); - indx = dictp2->cptr; - dictp3 = dict_ptr (db, indx); - - if (dictp3->codem1 == max_ent) - dictp3->codem1 = BADCODEM1; - - dictp2->cptr = hval; - dictp->codem1 = max_ent; - dictp->fcode = fcode; - db->max_ent = ++max_ent; - - if (db->lens) { - unsigned short *len1 = lens_ptr (db, max_ent); - unsigned short *len2 = lens_ptr (db, ent); - *len1 = *len2 + 1; - } - } - ent = c; - } - - OUTPUT(ent); /* output the last code */ - - if(skb_out) - db->bytes_out += skb_out->len; /* Do not count bytes from here */ - db->uncomp_bytes += isize; - db->in_count += isize; - ++db->uncomp_count; - ++db->seqno; - - if (bitno < 32) - ++db->bytes_out; /* must be set before calling bsd_check */ - - /* - * Generate the clear command if needed - */ - - if (bsd_check(db)) - OUTPUT (CLEAR); - - /* - * Pad dribble bits of last code with ones. - * Do not emit a completely useless byte of ones. - */ - if (bitno < 32 && skb_out && skb_tailroom(skb_out) > 0) - *(skb_put(skb_out,1)) = (unsigned char) ((accm | (0xff << (bitno-8))) >> 24); - - /* - * Increase code size if we would have without the packet - * boundary because the decompressor will do so. - */ - if (max_ent >= mxcode && max_ent < db->maxmaxcode) - db->n_bits++; - - /* If output length is too large then this is an incompressible frame. */ - if (!skb_out || (skb_out && skb_out->len >= skb_in->len) ) { - ++db->incomp_count; - db->incomp_bytes += isize; - return 0; - } - - /* Count the number of compressed frames */ - ++db->comp_count; - db->comp_bytes += skb_out->len; - return skb_out->len; - -#undef OUTPUT -} - -/* - * Update the "BSD Compress" dictionary on the receiver for - * incompressible data by pretending to compress the incoming data. - */ -static void bsd_incomp (void *state, struct sk_buff *skb_in,int proto) -{ - bsd_compress (state, skb_in, NULL, proto); -} - -/* - * Decompress "BSD Compress". - */ -static int bsd_decompress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out, - struct isdn_ppp_resetparams *rsparm) -{ - struct bsd_db *db; - unsigned int max_ent; - unsigned long accm; - unsigned int bitno; /* 1st valid bit in accm */ - unsigned int n_bits; - unsigned int tgtbitno; /* bitno when we have a code */ - struct bsd_dict *dictp; - int seq; - unsigned int incode; - unsigned int oldcode; - unsigned int finchar; - unsigned char *p,*ibuf; - 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; - accm = 0; - bitno = 32; /* 1st valid bit in accm */ - 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"); - return DECOMP_ERROR; - } - - /* - * Get the sequence number. - */ - if( (p = skb_pull(skb_in,2)) == NULL) { - return DECOMP_ERROR; - } - p-=2; - seq = (p[0] << 8) + p[1]; - ilen = skb_in->len; - ibuf = skb_in->data; - - /* - * Check the sequence number and give up if it differs from - * the value we're expecting. - */ - if (seq != db->seqno) { - if (db->debug) { - printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n", - db->unit, seq, db->seqno - 1); - } - return DECOMP_ERROR; - } - - ++db->seqno; - db->bytes_out += ilen; - - if(skb_tailroom(skb_out) > 0) - *(skb_put(skb_out,1)) = 0; - else - return DECOMP_ERR_NOMEM; - - oldcode = CLEAR; - - /* - * Keep the checkpoint correctly so that incompressible packets - * clear the dictionary at the proper times. - */ - - for (;;) { - if (ilen-- <= 0) { - db->in_count += (skb_out->len - 1); /* don't count the header */ - break; - } - - /* - * Accumulate bytes until we have a complete code. - * Then get the next code, relying on the 32-bit, - * unsigned accm to mask the result. - */ - - bitno -= 8; - accm |= *ibuf++ << bitno; - if (tgtbitno < bitno) - continue; - - incode = accm >> tgtbitno; - accm <<= n_bits; - bitno += n_bits; - - /* - * The dictionary must only be cleared at the end of a packet. - */ - - if (incode == CLEAR) { - if (ilen > 0) { - if (db->debug) - printk(KERN_DEBUG "bsd_decomp%d: bad CLEAR\n", db->unit); - return DECOMP_FATALERROR; /* probably a bug */ - } - bsd_clear(db); - break; - } - - if ((incode > max_ent + 2) || (incode > db->maxmaxcode) - || (incode > max_ent && oldcode == CLEAR)) { - if (db->debug) { - printk(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ", - db->unit, incode, oldcode); - printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n", - max_ent, skb_out->len, db->seqno); - } - return DECOMP_FATALERROR; /* probably a bug */ - } - - /* Special case for KwKwK string. */ - if (incode > max_ent) { - finchar = oldcode; - extra = 1; - } else { - finchar = incode; - extra = 0; - } - - codelen = *(lens_ptr (db, finchar)); - if( skb_tailroom(skb_out) < codelen + extra) { - if (db->debug) { - printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit); -#ifdef DEBUG - printk(KERN_DEBUG " len=%d, finchar=0x%x, codelen=%d,skblen=%d\n", - ilen, finchar, codelen, skb_out->len); -#endif - } - return DECOMP_FATALERROR; - } - - /* - * Decode this code and install it in the decompressed buffer. - */ - - 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); - -#ifdef DEBUG - if (--codelen <= 0 || dictp->codem1 != finchar-1) { - if (codelen <= 0) { - printk(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit); - printk(KERN_ERR "0x%x at 0x%x by 0x%x, max_ent=0x%x\n", incode, finchar, dictp2->cptr, max_ent); - } else { - if (dictp->codem1 != finchar-1) { - printk(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",db->unit, incode, finchar); - printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1); - } - } - return DECOMP_FATALERROR; - } -#endif - - { - u32 fcode = dictp->fcode; - *--p = (fcode >> 16) & 0xff; - finchar = fcode & 0xffff; - } - } - *--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) - printk(KERN_ERR "bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", db->unit, codelen, incode, max_ent); -#endif - - if (extra) /* the KwKwK case again */ - *(skb_put(skb_out,1)) = finchar; - - /* - * If not first code in a packet, and - * if not out of code space, then allocate a new code. - * - * Keep the hash table correct so it can be used - * with uncompressed packets. - */ - if (oldcode != CLEAR && max_ent < db->maxmaxcode) { - struct bsd_dict *dictp2, *dictp3; - u16 *lens1, *lens2; - unsigned long fcode; - int hval, disp, indx; - - fcode = BSD_KEY(oldcode,finchar); - hval = BSD_HASH(oldcode,finchar,db->hshift); - dictp = dict_ptr (db, hval); - - /* 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 - } - - /* - * Invalidate previous hash table entry - * assigned this code, and then take it over - */ - - dictp2 = dict_ptr (db, max_ent + 1); - indx = dictp2->cptr; - dictp3 = dict_ptr (db, indx); - - if (dictp3->codem1 == max_ent) - dictp3->codem1 = BADCODEM1; - - dictp2->cptr = hval; - dictp->codem1 = max_ent; - dictp->fcode = fcode; - db->max_ent = ++max_ent; - - /* Update the length of this string. */ - lens1 = lens_ptr (db, max_ent); - lens2 = lens_ptr (db, oldcode); - *lens1 = *lens2 + 1; - - /* Expand code size if needed. */ - if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) { - db->n_bits = ++n_bits; - tgtbitno = 32-n_bits; - } - } - oldcode = incode; - } - - ++db->comp_count; - ++db->uncomp_count; - db->comp_bytes += skb_in->len - BSD_OVHD; - db->uncomp_bytes += skb_out->len; - -#ifndef 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. - */ - - 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; -} - -/************************************************************* - * Table of addresses for the BSD compression module - *************************************************************/ - -static struct isdn_ppp_compressor ippp_bsd_compress = { - NULL,NULL, /* prev,next: overwritten by isdn_ppp */ - CI_BSD_COMPRESS, /* compress_proto */ - bsd_alloc, /* alloc */ - bsd_free, /* free */ - bsd_init, /* init */ - bsd_reset, /* reset */ - bsd_compress, /* compress */ - bsd_decompress, /* decompress */ - bsd_incomp, /* incomp */ - bsd_stats /* comp_stat */ -}; - -/************************************************************* - * Module support routines - *************************************************************/ - -int init_module(void) -{ - int answer = isdn_ppp_register_compressor (&ippp_bsd_compress); - if (answer == 0) - printk (KERN_INFO "PPP BSD Compression module registered\n"); - return answer; -} - -void cleanup_module(void) -{ - isdn_ppp_unregister_compressor (&ippp_bsd_compress); -} diff --git a/drivers/isdn/isdn_cards.c b/drivers/isdn/isdn_cards.c deleted file mode 100644 index 6cf2bcb4..00000000 --- a/drivers/isdn/isdn_cards.c +++ /dev/null @@ -1,98 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, initialization for non-modularized drivers. - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@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. - * - * $Log$ - * Revision 1.9 1999/04/12 12:33:11 fritz - * Changes from 2.0 tree. - * - * Revision 1.8 1999/03/29 11:13:23 armin - * Added eicon driver init. - * - * Revision 1.7 1998/02/20 17:24:28 fritz - * Added ACT2000 init. - * - * Revision 1.6 1997/04/23 18:56:03 fritz - * Old Teles driver removed, Changed doc and scripts accordingly. - * - * Revision 1.5 1997/03/30 17:10:36 calle - * added support for AVM-B1-PCI card. - * - * Revision 1.4 1997/03/04 21:59:44 calle - * Added AVM-B1-CAPI2.0 driver - * - * Revision 1.3 1997/02/03 23:31:14 fritz - * Reformatted according CodingStyle - * - * Revision 1.2 1996/10/13 19:52:17 keil - * HiSax support - * - * Revision 1.1 1996/04/20 16:04:36 fritz - * Initial revision - * - */ - -#include - -#ifdef CONFIG_ISDN_DRV_ICN -extern void icn_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_HISAX -extern void HiSax_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_PCBIT -extern void pcbit_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_EICON -extern void eicon_init(void); -#endif - -#ifdef CONFIG_ISDN_DRV_AVMB1 -extern void kcapi_init(void); -extern void capi_init(void); -extern void capidrv_init(void); -#endif - -void -isdn_cards_init(void) -{ -#if CONFIG_ISDN_DRV_ICN - icn_init(); -#endif -#ifdef CONFIG_ISDN_DRV_HISAX - HiSax_init(); -#endif -#if CONFIG_ISDN_DRV_PCBIT - pcbit_init(); -#endif -#ifdef CONFIG_ISDN_DRV_AVMB1 - kcapi_init(); - capi_init(); - capidrv_init(); -#endif -#if CONFIG_ISDN_DRV_ACT2000 - act2000_init(); -#endif -#if CONFIG_ISDN_DRV_EICON - eicon_init(); -#endif -} diff --git a/drivers/isdn/isdn_cards.h b/drivers/isdn/isdn_cards.h deleted file mode 100644 index 8871e4d5..00000000 --- a/drivers/isdn/isdn_cards.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, initialization for non-modularized drivers. - * - * Copyright 1994-1999 by Fritz Elfert (fritz@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. - * - * $Log$ - * Revision 1.2 1997/02/03 23:31:55 fritz - * Reformatted according CodingStyle - * - * Revision 1.1 1996/04/20 16:04:03 fritz - * Initial revision - * - */ - -extern void isdn_cards_init(void); diff --git a/drivers/isdn/isdn_common.c b/drivers/isdn/isdn_common.c deleted file mode 100644 index 0c34a8a2..00000000 --- a/drivers/isdn/isdn_common.c +++ /dev/null @@ -1,2938 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, common used functions (linklevel). - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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. - * - * $Log$ - * Revision 1.98 2000/02/16 14:56:27 paul - * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers - * - * Revision 1.97 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.96 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.95 2000/01/09 20:43:13 detabc - * exand logical bind-group's for both call's (in and out). - * add first part of kernel-config-help for abc-extension. - * - * Revision 1.94 1999/11/20 22:14:13 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.93 1999/11/04 13:11:36 keil - * Reinit of v110 structs - * - * Revision 1.92 1999/10/31 15:59:50 he - * more skb headroom checks - * - * Revision 1.91 1999/10/28 22:48:45 armin - * Bugfix: isdn_free_channel() now frees the channel, - * even when the usage of the ttyI has changed. - * - * Revision 1.90 1999/10/27 21:21:17 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.89 1999/10/16 14:46:47 keil - * replace kmalloc with vmalloc for the big dev struct - * - * Revision 1.88 1999/10/02 00:39:26 he - * Fixed a 2.3.x wait queue initialization (was causing panics) - * - * Revision 1.87 1999/09/12 16:19:39 detabc - * added abc features - * low cost routing for net-interfaces (only the HL side). - * need more implementation in the isdnlog-utility - * udp info support (first part). - * different EAZ on outgoing call's. - * more checks on D-Channel callbacks (double use of channels). - * tested and running with kernel 2.3.17 - * - * Revision 1.86 1999/07/31 12:59:42 armin - * Added tty fax capabilities. - * - * Revision 1.85 1999/07/29 16:58:35 armin - * Bugfix: DLE handling in isdn_readbchan() - * - * Revision 1.84 1999/07/25 16:21:10 keil - * fix number matching - * - * Revision 1.83 1999/07/13 21:02:05 werner - * Added limit possibilty of driver b_channel resources (ISDN_STAT_DISCH) - * - * Revision 1.82 1999/07/12 21:06:50 werner - * Fixed problem when loading more than one driver temporary - * - * Revision 1.81 1999/07/11 17:14:09 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.80 1999/07/07 10:14:00 detabc - * remove unused messages - * - * Revision 1.79 1999/07/05 23:51:30 werner - * Allow limiting of available HiSax B-chans per card. Controlled by hisaxctrl - * hisaxctrl id 10 - * - * Revision 1.78 1999/07/05 20:21:15 werner - * changes to use diversion sources for all kernel versions. - * removed static device, only proc filesystem used - * - * Revision 1.77 1999/07/01 08:29:50 keil - * compatibility to 2.3 kernel - * - * Revision 1.76 1999/06/29 16:16:44 calle - * Let ISDN_CMD_UNLOAD work with open isdn devices without crash again. - * Also right unlocking (ISDN_CMD_UNLOCK) is done now. - * isdnlog should check returncode of read(2) calls. - * - * Revision 1.75 1999/04/18 14:06:47 fritz - * Removed TIMRU stuff. - * - * Revision 1.74 1999/04/12 13:16:45 fritz - * Changes from 2.0 tree. - * - * Revision 1.73 1999/04/12 12:33:15 fritz - * Changes from 2.0 tree. - * - * Revision 1.72 1999/03/02 12:04:44 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.71 1999/01/28 09:10:43 armin - * Fixed bad while-loop in isdn_readbch(). - * - * Revision 1.70 1999/01/15 19:58:54 he - * removed compatibiltity macro - * - * Revision 1.69 1998/09/07 21:59:58 he - * flush method for 2.1.118 and above - * updated IIOCTLNETGPN - * - * Revision 1.68 1998/08/31 21:09:45 he - * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' - * peer phone number) - * - * Revision 1.67 1998/06/26 15:12:21 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.66 1998/06/17 19:50:41 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * - * Revision 1.62 1998/04/14 16:28:43 he - * Fixed user space access with interrupts off and remaining - * copy_{to,from}_user() -> -EFAULT return codes - * - * Revision 1.61 1998/03/22 18:50:46 hipp - * Added BSD Compression for syncPPP .. UNTESTED at the moment - * - * Revision 1.60 1998/03/19 13:18:18 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 1.59 1998/03/09 17:46:23 he - * merged in 2.1.89 changes - * - * Revision 1.58 1998/03/07 22:35:24 fritz - * Starting generic module support (Nothing usable yet). - * - * Revision 1.57 1998/03/07 18:21:01 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.56 1998/02/25 17:49:38 he - * Changed return codes caused be failing copy_{to,from}_user to -EFAULT - * - * Revision 1.55 1998/02/23 23:35:32 fritz - * Eliminated some compiler warnings. - * - * Revision 1.54 1998/02/22 19:44:19 fritz - * Bugfixes and improvements regarding V.110, V.110 now running. - * - * Revision 1.53 1998/02/20 17:18:05 fritz - * Changes for recent kernels. - * Added common stub for sending commands to lowlevel. - * Added V.110. - * - * Revision 1.52 1998/01/31 22:05:57 keil - * Lots of changes for X.25 support: - * Added generic support for connection-controlling encapsulation protocols - * Added support of BHUP status message - * Added support for additional p_encap X25IFACE - * Added support for kernels >= 2.1.72 - * - * Revision 1.51 1998/01/31 19:17:29 calle - * merged changes from and for 2.1.82 - * - * Revision 1.50 1997/12/12 06:12:11 calle - * moved EXPORT_SYMBOL(register_isdn) from isdn_syms.c to isdn_common.c - * - * Revision 1.49 1997/11/06 17:16:52 keil - * Sync to 2.1.62 changes - * - * Revision 1.48 1997/11/02 23:55:50 keil - * Andi Kleen's changes for 2.1.60 - * without it the isdninfo and isdnctrl devices won't work - * - * Revision 1.47 1997/10/09 21:28:46 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.46 1997/10/01 09:20:27 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.45 1997/08/21 23:11:41 fritz - * Added changes for kernels >= 2.1.45 - * - * Revision 1.44 1997/05/27 15:17:23 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.43 1997/03/31 14:09:43 fritz - * Fixed memory leak in isdn_close(). - * - * Revision 1.42 1997/03/30 16:51:08 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.41 1997/03/24 22:54:41 fritz - * Some small fixes in debug code. - * - * Revision 1.40 1997/03/08 08:13:51 fritz - * Bugfix: IIOCSETMAP (Set mapping) was broken. - * - * Revision 1.39 1997/03/07 01:32:54 fritz - * Added proper ifdef's for CONFIG_ISDN_AUDIO - * - * Revision 1.38 1997/03/05 21:15:02 fritz - * Fix: reduced stack usage of isdn_ioctl() and isdn_set_allcfg() - * - * Revision 1.37 1997/03/02 14:29:18 fritz - * More ttyI related cleanup. - * - * Revision 1.36 1997/02/28 02:32:40 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.35 1997/02/21 13:01:19 fritz - * Changes CAUSE message output in kernel log. - * - * Revision 1.34 1997/02/10 20:12:43 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.33 1997/02/10 10:05:42 fritz - * More changes for Kernel 2.1.X - * Symbol information moved to isdn_syms.c - * - * Revision 1.32 1997/02/03 22:55:26 fritz - * Reformatted according CodingStyle. - * Changed isdn_writebuf_stub static. - * Slow down tty-RING counter. - * skb->free stuff replaced by macro. - * Bugfix in audio-skb locking. - * Bugfix in HL-driver locking. - * - * Revision 1.31 1997/01/17 01:19:18 fritz - * Applied chargeint patch. - * - * Revision 1.30 1997/01/14 01:27:47 fritz - * Changed audio receive not to rely on skb->users and skb->lock. - * Added ATI2 and related variables. - * Started adding full-duplex audio capability. - * - * Revision 1.29 1997/01/12 23:33:03 fritz - * Made isdn_all_eaz foolproof. - * - * Revision 1.28 1996/11/13 02:33:19 fritz - * Fixed a race condition. - * - * Revision 1.27 1996/10/27 22:02:41 keil - * return codes for ISDN_STAT_ICALL - * - * Revision 1.26 1996/10/23 11:59:40 fritz - * More compatibility changes. - * - * Revision 1.25 1996/10/22 23:13:54 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.24 1996/10/11 14:02:03 fritz - * Bugfix: call to isdn_ppp_timer_timeout() never compiled, because of - * typo in #ifdef. - * - * Revision 1.23 1996/06/25 18:35:38 fritz - * Fixed bogus memory access in isdn_set_allcfg(). - * - * Revision 1.22 1996/06/24 17:37:37 fritz - * Bugfix: isdn_timer_ctrl() did restart timer, even if it - * was already running. - * lowlevel driver locking did use wrong parameters. - * - * Revision 1.21 1996/06/15 14:58:20 fritz - * Added version signatures for data structures used - * by userlevel programs. - * - * Revision 1.20 1996/06/12 16:01:49 fritz - * Bugfix: Remote B-channel hangup sometimes did not result - * in a NO CARRIER on tty. - * - * Revision 1.19 1996/06/11 14:52:04 hipp - * minor bugfix in isdn_writebuf_skb_stub() - * - * Revision 1.18 1996/06/06 14:51:51 fritz - * Changed to support DTMF decoding on audio playback also. - * - * Revision 1.17 1996/06/05 02:24:10 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.16 1996/06/03 20:09:05 fritz - * Bugfix: called wrong function pointer for locking in - * isdn_get_free_channel(). - * - * Revision 1.15 1996/05/31 01:10:54 fritz - * Bugfixes: - * Lowlevel modules did not get locked correctly. - * Did show wrong revision when initializing. - * Minor fixes in ioctl code. - * sk_buff did not get freed, if error in writebuf_stub. - * - * Revision 1.14 1996/05/18 01:36:55 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.13 1996/05/17 15:43:30 fritz - * Bugfix: decrement of rcvcount in readbchan() corrected. - * - * Revision 1.12 1996/05/17 03:55:43 fritz - * Changed DLE handling for audio receive. - * Some cleanup. - * Added display of isdn_audio_revision. - * - * Revision 1.11 1996/05/11 21:51:32 fritz - * Changed queue management to use sk_buffs. - * - * Revision 1.10 1996/05/10 08:49:16 fritz - * Checkin before major changes of tty-code. - * - * Revision 1.9 1996/05/07 09:19:41 fritz - * Adapted to changes in isdn_tty.c - * - * Revision 1.8 1996/05/06 11:34:51 hipp - * fixed a few bugs - * - * Revision 1.7 1996/05/02 03:55:17 fritz - * Bugfixes: - * - B-channel connect message for modem devices - * sometimes did not result in a CONNECT-message. - * - register_isdn did not check for driverId-conflicts. - * - * Revision 1.6 1996/04/30 20:57:21 fritz - * Commit test - * - * Revision 1.5 1996/04/20 16:19:07 fritz - * Changed slow timer handlers to increase accuracy. - * Added statistic information for usage by xisdnload. - * Fixed behaviour of isdnctrl-device on non-blocked io. - * Fixed all io to go through generic writebuf-function without - * bypassing. Same for incoming data. - * Fixed bug: Last channel had been unusable. - * Fixed kfree of tty xmit_buf on ppp initialization failure. - * - * Revision 1.4 1996/02/11 02:33:26 fritz - * Fixed bug in main timer-dispatcher. - * Bugfix: Lot of tty-callbacks got called regardless of the events already - * been handled by network-devices. - * Changed ioctl-names. - * - * Revision 1.3 1996/01/22 05:16:11 fritz - * Changed ioctl-names. - * Fixed bugs in isdn_open and isdn_close regarding PPP_MINOR. - * - * Revision 1.2 1996/01/21 16:52:40 fritz - * Support for sk_buffs added, changed header-stuffing. - * - * Revision 1.1 1996/01/09 04:12:52 fritz - * Initial revision - * - */ - -#include -#include -#include -#include -#include -#include -#include "isdn_common.h" -#include "isdn_tty.h" -#include "isdn_net.h" -#include "isdn_ppp.h" -#ifdef CONFIG_ISDN_AUDIO -#include "isdn_audio.h" -#endif -#ifdef CONFIG_ISDN_DIVERSION -#include -#endif CONFIG_ISDN_DIVERSION -#include "isdn_v110.h" -#include "isdn_cards.h" -#ifdef HAVE_DEVFS_FS -#include -#endif /* HAVE_DEVFS_FS */ - -/* Debugflags */ -#undef ISDN_DEBUG_STATCALLB - -isdn_dev *dev = (isdn_dev *) 0; - -static char *isdn_revision = "$Revision$"; - -extern char *isdn_net_revision; -extern char *isdn_tty_revision; -#ifdef CONFIG_ISDN_PPP -extern char *isdn_ppp_revision; -#else -static char *isdn_ppp_revision = ": none $"; -#endif -#ifdef CONFIG_ISDN_AUDIO -extern char *isdn_audio_revision; -#else -static char *isdn_audio_revision = ": none $"; -#endif -extern char *isdn_v110_revision; - -#ifdef CONFIG_ISDN_DIVERSION -isdn_divert_if *divert_if = NULL; /* interface to diversion module */ -#endif CONFIG_ISDN_DIVERSION - - -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 */ - -void -isdn_MOD_INC_USE_COUNT(void) -{ - int i; - - MOD_INC_USE_COUNT; - for (i = 0; i < dev->drivers; i++) { - isdn_ctrl cmd; - - cmd.driver = i; - cmd.arg = 0; - cmd.command = ISDN_CMD_LOCK; - isdn_command(&cmd); - dev->drv[i]->locks++; - } -} - -void -isdn_MOD_DEC_USE_COUNT(void) -{ - int i; - - MOD_DEC_USE_COUNT; - for (i = 0; i < dev->drivers; i++) - if (dev->drv[i]->locks > 0) { - isdn_ctrl cmd; - - cmd.driver = i; - cmd.arg = 0; - cmd.command = ISDN_CMD_UNLOCK; - isdn_command(&cmd); - dev->drv[i]->locks--; - } -} - -#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) -void -isdn_dumppkt(char *s, u_char * p, int len, int dumplen) -{ - int dumpc; - - printk(KERN_DEBUG "%s(%d) ", s, len); - for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++) - printk(" %02x", *p++); - printk("\n"); -} -#endif - -/* - * I picked the pattern-matching-functions from an old GNU-tar version (1.10) - * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz) - */ -static int -isdn_star(char *s, char *p) -{ - while (isdn_wildmat(s, p)) { - if (*++s == '\0') - return (2); - } - return (0); -} - -/* - * Shell-type Pattern-matching for incoming caller-Ids - * This function gets a string in s and checks, if it matches the pattern - * given in p. - * - * Return: - * 0 = match. - * 1 = no match. - * 2 = no match. Would eventually match, if s would be longer. - * - * Possible Patterns: - * - * '?' matches one character - * '*' matches zero or more characters - * [xyz] matches the set of characters in brackets. - * [^xyz] matches any single character not in the set of characters - */ - -int -isdn_wildmat(char *s, char *p) -{ - register int last; - register int matched; - register int reverse; - register int nostar = 1; - - if (!(*s) && !(*p)) - return(1); - for (; *p; s++, p++) - switch (*p) { - case '\\': - /* - * Literal match with following character, - * fall through. - */ - p++; - default: - if (*s != *p) - return (*s == '\0')?2:1; - continue; - case '?': - /* Match anything. */ - if (*s == '\0') - return (2); - continue; - case '*': - nostar = 0; - /* Trailing star matches everything. */ - return (*++p ? isdn_star(s, p) : 0); - case '[': - /* [^....] means inverse character class. */ - if ((reverse = (p[1] == '^'))) - p++; - for (last = 0, matched = 0; *++p && (*p != ']'); last = *p) - /* This next line requires a good C compiler. */ - if (*p == '-' ? *s <= *++p && *s >= last : *s == *p) - matched = 1; - if (matched == reverse) - return (1); - continue; - } - return (*s == '\0')?0:nostar; -} - -static void -isdn_free_queue(struct sk_buff_head *queue) -{ - struct sk_buff *skb; - unsigned long flags; - - save_flags(flags); - cli(); - if (skb_queue_len(queue)) - while ((skb = skb_dequeue(queue))) - dev_kfree_skb(skb); - restore_flags(flags); -} - -int -isdn_dc2minor(int di, int ch) -{ - int i; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (dev->chanmap[i] == ch && dev->drvmap[i] == di) - return i; - return -1; -} - -static int isdn_timer_cnt1 = 0; -static int isdn_timer_cnt2 = 0; -static int isdn_timer_cnt3 = 0; -static int isdn_timer_cnt4 = 0; - -static void -isdn_timer_funct(ulong dummy) -{ - int tf = dev->tflags; - if (tf & ISDN_TIMER_FAST) { - if (tf & ISDN_TIMER_MODEMREAD) - isdn_tty_readmodem(); - if (tf & ISDN_TIMER_MODEMPLUS) - isdn_tty_modem_escape(); - if (tf & ISDN_TIMER_MODEMXMIT) - isdn_tty_modem_xmit(); - } - if (tf & ISDN_TIMER_SLOW) { - if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) { - isdn_timer_cnt1 = 0; - if (tf & ISDN_TIMER_NETDIAL) - isdn_net_dial(); - } - if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) { - isdn_timer_cnt2 = 0; - if (tf & ISDN_TIMER_NETHANGUP) - isdn_net_autohup(); - if (++isdn_timer_cnt3 > ISDN_TIMER_RINGING) { - isdn_timer_cnt3 = 0; - if (tf & ISDN_TIMER_MODEMRING) - isdn_tty_modem_ring(); - } - if (++isdn_timer_cnt4 > ISDN_TIMER_KEEPINT) { - isdn_timer_cnt4 = 0; - if (tf & ISDN_TIMER_KEEPALIVE) - isdn_net_slarp_out(); - } - if (tf & ISDN_TIMER_CARRIER) - isdn_tty_carrier_timeout(); -#if (defined CONFIG_ISDN_PPP) && (defined CONFIG_ISDN_MPP) - if (tf & ISDN_TIMER_IPPP) - isdn_ppp_timer_timeout(); -#endif - } - } - if (tf) - { - int flags; - - save_flags(flags); - cli(); - del_timer(&dev->timer); - dev->timer.expires = jiffies + ISDN_TIMER_RES; - add_timer(&dev->timer); - restore_flags(flags); - } -} - -void -isdn_timer_ctrl(int tf, int onoff) -{ - int flags; - - save_flags(flags); - cli(); - if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) { - /* If the slow-timer wasn't activated until now */ - isdn_timer_cnt1 = 0; - isdn_timer_cnt2 = 0; - } - if (onoff) - dev->tflags |= tf; - else - dev->tflags &= ~tf; - if (dev->tflags) { - if (!del_timer(&dev->timer)) /* del_timer is 1, when active */ - dev->timer.expires = jiffies + ISDN_TIMER_RES; - add_timer(&dev->timer); - } - restore_flags(flags); -} - -/* - * Receive a packet from B-Channel. (Called from low-level-module) - */ -static void -isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb) -{ - int i; - - if ((i = isdn_dc2minor(di, channel)) == -1) { - dev_kfree_skb(skb); - return; - } - /* Update statistics */ - dev->ibytes[i] += skb->len; - - /* First, try to deliver data to network-device */ - if (isdn_net_rcv_skb(i, skb)) - return; - - /* V.110 handling - * makes sense for async streams only, so it is - * called after possible net-device delivery. - */ - if (dev->v110[i]) { - atomic_inc(&dev->v110use[i]); - skb = isdn_v110_decode(dev->v110[i], skb); - atomic_dec(&dev->v110use[i]); - if (!skb) - return; - } - - /* No network-device found, deliver to tty or raw-channel */ - if (skb->len) { - if (isdn_tty_rcv_skb(i, di, channel, skb)) - return; - wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]); - } else - dev_kfree_skb(skb); -} - -/* - * Intercept command from Linklevel to Lowlevel. - * If layer 2 protocol is V.110 and this is not supported by current - * lowlevel-driver, use driver's transparent mode and handle V.110 in - * linklevel instead. - */ -int -isdn_command(isdn_ctrl *cmd) -{ - if (cmd->driver == -1) { - printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command); - return(1); - } - if (cmd->command == ISDN_CMD_SETL2) { - int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255); - unsigned long l2prot = (cmd->arg >> 8) & 255; - unsigned long features = (dev->drv[cmd->driver]->interface->features - >> ISDN_FEATURE_L2_SHIFT) & - ISDN_FEATURE_L2_MASK; - unsigned long l2_feature = (1 << l2prot); - - switch (l2prot) { - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - /* If V.110 requested, but not supported by - * HL-driver, set emulator-flag and change - * Layer-2 to transparent - */ - if (!(features & l2_feature)) { - dev->v110emu[idx] = l2prot; - cmd->arg = (cmd->arg & 255) | - (ISDN_PROTO_L2_TRANS << 8); - } else - dev->v110emu[idx] = 0; - } - } - return dev->drv[cmd->driver]->interface->command(cmd); -} - -void -isdn_all_eaz(int di, int ch) -{ - isdn_ctrl cmd; - - if (di < 0) - return; - cmd.driver = di; - cmd.arg = ch; - cmd.command = ISDN_CMD_SETEAZ; - cmd.parm.num[0] = '\0'; - isdn_command(&cmd); -} - -/* - * Begin of a CAPI like LL<->HL interface, currently used only for - * supplementary service (CAPI 2.0 part III) - */ -#include "avmb1/capicmd.h" /* this should be moved in a common place */ - -int -isdn_capi_rec_hl_msg(capi_msg *cm) { - - int di; - int ch; - - di = (cm->adr.Controller & 0x7f) -1; - ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f); - switch(cm->Command) { - case CAPI_FACILITY: - /* in the moment only handled in tty */ - return(isdn_tty_capi_facility(cm)); - default: - return(-1); - } -} - -static int -isdn_status_callback(isdn_ctrl * c) -{ - int di; - ulong flags; - int i; - int r; - int retval = 0; - isdn_ctrl cmd; - - di = c->driver; - i = isdn_dc2minor(di, c->arg); - switch (c->command) { - case ISDN_STAT_BSENT: - if (i < 0) - return -1; - if (dev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - if (isdn_net_stat_callback(i, c)) - return 0; - if (isdn_v110_stat_callback(i, c)) - return 0; - if (isdn_tty_stat_callback(i, c)) - return 0; - wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]); - break; - case ISDN_STAT_STAVAIL: - save_flags(flags); - cli(); - dev->drv[di]->stavail += c->arg; - restore_flags(flags); - wake_up_interruptible(&dev->drv[di]->st_waitq); - break; - case ISDN_STAT_RUN: - dev->drv[di]->flags |= DRV_FLAG_RUNNING; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (dev->drvmap[i] == di) - isdn_all_eaz(di, dev->chanmap[i]); - set_global_features(); - break; - case ISDN_STAT_STOP: - dev->drv[di]->flags &= ~DRV_FLAG_RUNNING; - break; - case ISDN_STAT_ICALL: - if (i < 0) - return -1; -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num); -#endif - if (dev->global_flags & ISDN_GLOBAL_STOPPED) { - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_HANGUP; - isdn_command(&cmd); - return 0; - } - /* Try to find a network-interface which will accept incoming call */ - r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, c->parm.setup)); - switch (r) { - case 0: - /* No network-device replies. - * Try ttyI's. - * These return 0 on no match, 1 on match and - * 3 on eventually match, if CID is longer. - */ - if (c->command == ISDN_STAT_ICALL) - if ((retval = isdn_tty_find_icall(di, c->arg, c->parm.setup))) return(retval); -#ifdef CONFIG_ISDN_DIVERSION - if (divert_if) - if ((retval = divert_if->stat_callback(c))) - return(retval); /* processed */ -#endif CONFIG_ISDN_DIVERSION - if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) { - /* No tty responding */ - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_HANGUP; - isdn_command(&cmd); - retval = 2; - } - break; - case 1: - /* Schedule connection-setup */ - isdn_net_dial(); - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_ACCEPTD; - isdn_command(&cmd); - retval = 1; - break; - case 2: /* For calling back, first reject incoming call ... */ - case 3: /* Interface found, but down, reject call actively */ - retval = 2; - printk(KERN_INFO "isdn: Rejecting Call\n"); - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_HANGUP; - isdn_command(&cmd); - if (r == 3) - break; - /* Fall through */ - case 4: - /* ... then start callback. */ - isdn_net_dial(); - break; - case 5: - /* Number would eventually match, if longer */ - retval = 3; - break; - } -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "ICALL: ret=%d\n", retval); -#endif - return retval; - break; - case ISDN_STAT_CINF: - if (i < 0) - return -1; -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num); -#endif - if (dev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - if (strcmp(c->parm.num, "0")) - isdn_net_stat_callback(i, c); - isdn_tty_stat_callback(i, c); - break; - case ISDN_STAT_CAUSE: -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num); -#endif - printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n", - dev->drvid[di], c->arg, c->parm.num); - isdn_tty_stat_callback(i, c); -#ifdef CONFIG_ISDN_DIVERSION - if (divert_if) - divert_if->stat_callback(c); -#endif CONFIG_ISDN_DIVERSION - break; - case ISDN_STAT_DISPLAY: -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display); -#endif - isdn_tty_stat_callback(i, c); -#ifdef CONFIG_ISDN_DIVERSION - if (divert_if) - divert_if->stat_callback(c); -#endif CONFIG_ISDN_DIVERSION - break; - case ISDN_STAT_DCONN: - if (i < 0) - return -1; -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "DCONN: %ld\n", c->arg); -#endif - if (dev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - /* Find any net-device, waiting for D-channel setup */ - if (isdn_net_stat_callback(i, c)) - break; - isdn_v110_stat_callback(i, c); - /* Find any ttyI, waiting for D-channel setup */ - if (isdn_tty_stat_callback(i, c)) { - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_ACCEPTB; - isdn_command(&cmd); - break; - } - break; - case ISDN_STAT_DHUP: - if (i < 0) - return -1; -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "DHUP: %ld\n", c->arg); -#endif - if (dev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - dev->drv[di]->online &= ~(1 << (c->arg)); - isdn_info_update(); - /* Signal hangup to network-devices */ - if (isdn_net_stat_callback(i, c)) - break; - isdn_v110_stat_callback(i, c); - if (isdn_tty_stat_callback(i, c)) - break; -#ifdef CONFIG_ISDN_DIVERSION - if (divert_if) - divert_if->stat_callback(c); -#endif CONFIG_ISDN_DIVERSION - break; - break; - case ISDN_STAT_BCONN: - if (i < 0) - return -1; -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "BCONN: %ld\n", c->arg); -#endif - /* Signal B-channel-connect to network-devices */ - if (dev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - dev->drv[di]->online |= (1 << (c->arg)); - isdn_info_update(); - if (isdn_net_stat_callback(i, c)) - break; - isdn_v110_stat_callback(i, c); - if (isdn_tty_stat_callback(i, c)) - break; - break; - case ISDN_STAT_BHUP: - if (i < 0) - return -1; -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "BHUP: %ld\n", c->arg); -#endif - if (dev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - dev->drv[di]->online &= ~(1 << (c->arg)); - isdn_info_update(); -#ifdef CONFIG_ISDN_X25 - /* Signal hangup to network-devices */ - if (isdn_net_stat_callback(i, c)) - break; -#endif - isdn_v110_stat_callback(i, c); - if (isdn_tty_stat_callback(i, c)) - break; - break; - case ISDN_STAT_NODCH: - if (i < 0) - return -1; -#ifdef ISDN_DEBUG_STATCALLB - printk(KERN_DEBUG "NODCH: %ld\n", c->arg); -#endif - if (dev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - if (isdn_net_stat_callback(i, c)) - break; - if (isdn_tty_stat_callback(i, c)) - break; - break; - case ISDN_STAT_ADDCH: - if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) - return -1; - isdn_info_update(); - break; - case ISDN_STAT_DISCH: - save_flags(flags); - cli(); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if ((dev->drvmap[i] == di) && - (dev->chanmap[i] == c->arg)) { - if (c->parm.num[0]) - dev->usage[i] &= ~ISDN_USAGE_DISABLED; - else - if (USG_NONE(dev->usage[i])) { - dev->usage[i] |= ISDN_USAGE_DISABLED; - } - else - retval = -1; - break; - } - restore_flags(flags); - isdn_info_update(); - break; - case ISDN_STAT_UNLOAD: - while (dev->drv[di]->locks > 0) { - isdn_ctrl cmd; - cmd.driver = di; - cmd.arg = 0; - cmd.command = ISDN_CMD_UNLOCK; - isdn_command(&cmd); - dev->drv[di]->locks--; - } - save_flags(flags); - cli(); - isdn_tty_stat_callback(i, c); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (dev->drvmap[i] == di) { - 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; - kfree(dev->drv[di]->rcverr); - kfree(dev->drv[di]->rcvcount); - for (i = 0; i < dev->drv[di]->channels; i++) - isdn_free_queue(&dev->drv[di]->rpqueue[i]); - kfree(dev->drv[di]->rpqueue); - kfree(dev->drv[di]->rcv_waitq); -#ifndef COMPAT_HAS_NEW_WAITQ - kfree(dev->drv[di]->snd_waitq); -#endif - kfree(dev->drv[di]); - dev->drv[di] = NULL; - dev->drvid[di][0] = '\0'; - isdn_info_update(); - set_global_features(); - restore_flags(flags); - return 0; - case ISDN_STAT_L1ERR: - break; - case CAPI_PUT_MESSAGE: - return(isdn_capi_rec_hl_msg(&c->parm.cmsg)); -#ifdef CONFIG_ISDN_TTY_FAX - case ISDN_STAT_FAXIND: - isdn_tty_stat_callback(i, c); - break; -#endif -#ifdef CONFIG_ISDN_AUDIO - case ISDN_STAT_AUDIO: - isdn_tty_stat_callback(i, c); - break; -#endif -#ifdef CONFIG_ISDN_DIVERSION - case ISDN_STAT_PROT: - case ISDN_STAT_REDIR: - if (divert_if) - return(divert_if->stat_callback(c)); -#endif CONFIG_ISDN_DIVERSION - default: - return -1; - } - return 0; -} - -/* - * Get integer from char-pointer, set pointer to end of number - */ -int -isdn_getnum(char **p) -{ - int v = -1; - - while (*p[0] >= '0' && *p[0] <= '9') - v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0'); - return v; -} - -#define DLE 0x10 - -/* - * isdn_readbchan() tries to get data from the read-queue. - * It MUST be called with interrupts off. - * - * Be aware that this is not an atomic operation when sleep != 0, even though - * interrupts are turned off! Well, like that we are currently only called - * on behalf of a read system call on raw device files (which are documented - * to be dangerous and for for debugging purpose only). The inode semaphore - * takes care that this is not called for the same minor device number while - * we are sleeping, but access is not serialized against simultaneous read() - * from the corresponding ttyI device. Can other ugly events, like changes - * of the mapping (di,ch)<->minor, happen during the sleep? --he - */ -int -#ifdef COMPAT_HAS_NEW_WAITQ -isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep) -#else -isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep) -#endif -{ - int left; - int count; - int count_pull; - int count_put; - int dflag; - struct sk_buff *skb; - u_char *cp; - - if (!dev->drv[di]) - return 0; - if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) { - if (sleep) - interruptible_sleep_on(sleep); - else - return 0; - } - left = MIN(len, dev->drv[di]->rcvcount[channel]); - cp = buf; - count = 0; - while (left) { - if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel]))) - break; -#ifdef CONFIG_ISDN_AUDIO - if (ISDN_AUDIO_SKB_LOCK(skb)) - break; - ISDN_AUDIO_SKB_LOCK(skb) = 1; - if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) { - char *p = skb->data; - unsigned long DLEmask = (1 << channel); - - dflag = 0; - count_pull = count_put = 0; - while ((count_pull < skb->len) && (left > 0)) { - left--; - if (dev->drv[di]->DLEflag & DLEmask) { - *cp++ = DLE; - dev->drv[di]->DLEflag &= ~DLEmask; - } else { - *cp++ = *p; - if (*p == DLE) { - dev->drv[di]->DLEflag |= DLEmask; - (ISDN_AUDIO_SKB_DLECOUNT(skb))--; - } - p++; - count_pull++; - } - count_put++; - } - if (count_pull >= skb->len) - dflag = 1; - } else { -#endif - /* No DLE's in buff, so simply copy it */ - dflag = 1; - if ((count_pull = skb->len) > left) { - count_pull = left; - dflag = 0; - } - count_put = count_pull; - memcpy(cp, skb->data, count_put); - cp += count_put; - left -= count_put; -#ifdef CONFIG_ISDN_AUDIO - } -#endif - count += count_put; - if (fp) { - memset(fp, 0, count_put); - fp += count_put; - } - if (dflag) { - /* We got all the data in this buff. - * Now we can dequeue it. - */ - if (fp) - *(fp - 1) = 0xff; -#ifdef CONFIG_ISDN_AUDIO - ISDN_AUDIO_SKB_LOCK(skb) = 0; -#endif - skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]); - dev_kfree_skb(skb); - } else { - /* Not yet emptied this buff, so it - * must stay in the queue, for further calls - * but we pull off the data we got until now. - */ - skb_pull(skb, count_pull); -#ifdef CONFIG_ISDN_AUDIO - ISDN_AUDIO_SKB_LOCK(skb) = 0; -#endif - } - dev->drv[di]->rcvcount[channel] -= count_put; - } - return count; -} - -static __inline int -isdn_minor2drv(int minor) -{ - return (dev->drvmap[minor]); -} - -static __inline int -isdn_minor2chan(int minor) -{ - return (dev->chanmap[minor]); -} - -static char * -isdn_statstr(void) -{ - static char istatbuf[2048]; - char *p; - int i; - - sprintf(istatbuf, "idmap:\t"); - p = istatbuf + strlen(istatbuf); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]); - p = istatbuf + strlen(istatbuf); - } - sprintf(p, "\nchmap:\t"); - p = istatbuf + strlen(istatbuf); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%d ", dev->chanmap[i]); - p = istatbuf + strlen(istatbuf); - } - sprintf(p, "\ndrmap:\t"); - p = istatbuf + strlen(istatbuf); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%d ", dev->drvmap[i]); - p = istatbuf + strlen(istatbuf); - } - sprintf(p, "\nusage:\t"); - p = istatbuf + strlen(istatbuf); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%d ", dev->usage[i]); - p = istatbuf + strlen(istatbuf); - } - sprintf(p, "\nflags:\t"); - p = istatbuf + strlen(istatbuf); - for (i = 0; i < ISDN_MAX_DRIVERS; i++) { - if (dev->drv[i]) { - sprintf(p, "%ld ", dev->drv[i]->online); - p = istatbuf + strlen(istatbuf); - } else { - sprintf(p, "? "); - p = istatbuf + strlen(istatbuf); - } - } - sprintf(p, "\nphone:\t"); - p = istatbuf + strlen(istatbuf); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - sprintf(p, "%s ", dev->num[i]); - p = istatbuf + strlen(istatbuf); - } - sprintf(p, "\n"); - return istatbuf; -} - -/* Module interface-code */ - -void -isdn_info_update(void) -{ - infostruct *p = dev->infochain; - - while (p) { - *(p->private) = 1; - p = (infostruct *) p->next; - } - wake_up_interruptible(&(dev->info_waitq)); -} - -static ssize_t -isdn_read(struct file *file, char *buf, size_t count, loff_t * off) -{ - uint minor = MINOR(file->f_dentry->d_inode->i_rdev); - int len = 0; - ulong flags; - int drvidx; - int chidx; - char *p; - - if (off != &file->f_pos) - return -ESPIPE; - - if (minor == ISDN_MINOR_STATUS) { - if (!file->private_data) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - 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)) - return -EFAULT; - *off += len; - return len; - } - return 0; - } - if (!dev->drivers) - return -ENODEV; - if (minor < ISDN_MINOR_CTRL) { - drvidx = isdn_minor2drv(minor); - if (drvidx < 0) - return -ENODEV; - if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) - return -ENODEV; - chidx = isdn_minor2chan(minor); - if( ! (p = kmalloc(count,GFP_KERNEL)) ) return -ENOMEM; - save_flags(flags); - cli(); - len = isdn_readbchan(drvidx, chidx, p, 0, count, - &dev->drv[drvidx]->rcv_waitq[chidx]); - *off += len; - restore_flags(flags); - if( copy_to_user(buf,p,len) ) len = -EFAULT; - kfree(p); - return len; - } - if (minor <= ISDN_MINOR_CTRLMAX) { - drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - if (drvidx < 0) - return -ENODEV; - if (!dev->drv[drvidx]->stavail) { - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - 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) - len = dev->drv[drvidx]->interface-> - readstat(buf, MIN(count, dev->drv[drvidx]->stavail), - 1, drvidx, isdn_minor2chan(minor)); - else - len = 0; -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - } -#endif - save_flags(flags); - cli(); - if (len) - dev->drv[drvidx]->stavail -= len; - else - dev->drv[drvidx]->stavail = 0; - restore_flags(flags); - *off += len; - return len; - } -#ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - return (isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count)); -#endif - return -ENODEV; -} - -static loff_t -isdn_lseek(struct file *file, loff_t offset, int orig) -{ - return -ESPIPE; -} - -static ssize_t -isdn_write(struct file *file, const char *buf, size_t count, loff_t * off) -{ - uint minor = MINOR(file->f_dentry->d_inode->i_rdev); - int drvidx; - int chidx; - - if (off != &file->f_pos) - return -ESPIPE; - - if (minor == ISDN_MINOR_STATUS) - return -EPERM; - if (!dev->drivers) - return -ENODEV; - if (minor < ISDN_MINOR_CTRL) { - drvidx = isdn_minor2drv(minor); - if (drvidx < 0) - return -ENODEV; - if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) - return -ENODEV; - chidx = isdn_minor2chan(minor); - while (isdn_writebuf_stub(drvidx, chidx, buf, count, 1) != count) - interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]); - return count; - } - if (minor <= ISDN_MINOR_CTRLMAX) { - drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - if (drvidx < 0) - return -ENODEV; - /* - * We want to use the isdnctrl device to load the firmware - * - if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) - return -ENODEV; - */ - if (dev->drv[drvidx]->interface->writecmd) - return (dev->drv[drvidx]->interface-> - writecmd(buf, count, 1, drvidx, isdn_minor2chan(minor))); - else - return count; - } -#ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - return (isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count)); -#endif - return -ENODEV; -} - -static unsigned int -isdn_poll(struct file *file, poll_table * wait) -{ - unsigned int mask = 0; - unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev); - int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - - if (minor == ISDN_MINOR_STATUS) { - poll_wait(file, &(dev->info_waitq), wait); - /* mask = POLLOUT | POLLWRNORM; */ - if (file->private_data) { - mask |= POLLIN | POLLRDNORM; - } - return mask; - } - if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) { - if (drvidx < 0) { - /* driver deregistered while file open */ - return POLLHUP; - } - poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait); - mask = POLLOUT | POLLWRNORM; - if (dev->drv[drvidx]->stavail) { - mask |= POLLIN | POLLRDNORM; - } - return mask; - } -#ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - return (isdn_ppp_poll(file, wait)); -#endif - printk(KERN_ERR "isdn_common: isdn_poll 2 -> what the hell\n"); - return POLLERR; -} - - -static int -isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg) -{ - uint minor = MINOR(inode->i_rdev); - isdn_ctrl c; - int drvidx; - int chidx; - int ret; - int i; - char *p; - char *s; - union iocpar { - char name[10]; - char bname[22]; - isdn_ioctl_struct iocts; - isdn_net_ioctl_phone phone; - isdn_net_ioctl_cfg cfg; - } iocpar; - -#define name iocpar.name -#define bname iocpar.bname -#define iocts iocpar.iocts -#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 (!dev->drivers) - return -ENODEV; - if (minor < ISDN_MINOR_CTRL) { - drvidx = isdn_minor2drv(minor); - if (drvidx < 0) - return -ENODEV; - chidx = isdn_minor2chan(minor); - if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) - return -ENODEV; - return 0; - } - if (minor <= ISDN_MINOR_CTRLMAX) { -/* - * isdn net devices manage lots of configuration variables as linked lists. - * Those lists must only be manipulated from user space. Some of the ioctl's - * service routines access user space and are not atomic. Therefor, ioctl's - * manipulating the lists and ioctl's sleeping while accessing the lists - * are serialized by means of a semaphore. - */ - 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 - isdn_dw_abc_lcr_ioctl(arg); - return(0); -#else - printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n"); - return -ENODEV; -#endif -#ifdef CONFIG_NETDEVICES - case IIOCNETAIF: - /* Add a network-interface */ - if (arg) { - if (copy_from_user(name, (char *) arg, sizeof(name))) - return -EFAULT; - s = name; - } else { - s = NULL; - } - ret = down_interruptible(&dev->sem); - if( ret ) return ret; - if ((s = isdn_net_new(s, NULL))) { - if (copy_to_user((char *) arg, s, strlen(s) + 1)){ - ret = -EFAULT; - } else { - ret = 0; - } - } else - ret = -ENODEV; - up(&dev->sem); - return ret; - case IIOCNETASL: - /* Add a slave to a network-interface */ - if (arg) { - if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1)) - return -EFAULT; - } else - return -EINVAL; - ret = down_interruptible(&dev->sem); - if( ret ) return ret; - if ((s = isdn_net_newslave(bname))) { - if (copy_to_user((char *) arg, s, strlen(s) + 1)){ - ret = -EFAULT; - } else { - ret = 0; - } - } else - ret = -ENODEV; - up(&dev->sem); - return ret; - case IIOCNETDIF: - /* Delete a network-interface */ - if (arg) { - if (copy_from_user(name, (char *) arg, sizeof(name))) - return -EFAULT; - ret = down_interruptible(&dev->sem); - if( ret ) return ret; - ret = isdn_net_rm(name); - up(&dev->sem); - return ret; - } else - return -EINVAL; - case IIOCNETSCF: - /* Set configurable parameters of a network-interface */ - if (arg) { - if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) - return -EFAULT; - return isdn_net_setcfg(&cfg); - } else - return -EINVAL; - case IIOCNETGCF: - /* Get configurable parameters of a network-interface */ - if (arg) { - if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))) - return -EFAULT; - if (!(ret = isdn_net_getcfg(&cfg))) { - if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))) - return -EFAULT; - } - return ret; - } else - return -EINVAL; - case IIOCNETANM: - /* Add a phone-number to a network-interface */ - if (arg) { - if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) - return -EFAULT; - ret = down_interruptible(&dev->sem); - if( ret ) return ret; - ret = isdn_net_addphone(&phone); - up(&dev->sem); - return ret; - } else - return -EINVAL; - case IIOCNETGNM: - /* Get list of phone-numbers of a network-interface */ - if (arg) { - if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) - return -EFAULT; - ret = down_interruptible(&dev->sem); - if( ret ) return ret; - ret = isdn_net_getphones(&phone, (char *) arg); - up(&dev->sem); - return ret; - } else - return -EINVAL; - case IIOCNETDNM: - /* Delete a phone-number of a network-interface */ - if (arg) { - if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone))) - return -EFAULT; - ret = down_interruptible(&dev->sem); - if( ret ) return ret; - ret = isdn_net_delphone(&phone); - up(&dev->sem); - return ret; - } else - return -EINVAL; - case IIOCNETDIL: - /* Force dialing of a network-interface */ - if (arg) { - if (copy_from_user(name, (char *) arg, sizeof(name))) - return -EFAULT; - return isdn_net_force_dial(name); - } else - return -EINVAL; -#ifdef CONFIG_ISDN_PPP - case IIOCNETALN: - if (!arg) - return -EINVAL; - if (copy_from_user(name, (char *) arg, sizeof(name))) - return -EFAULT; - return isdn_ppp_dial_slave(name); - case IIOCNETDLN: - if (!arg) - return -EINVAL; - if (copy_from_user(name, (char *) arg, sizeof(name))) - return -EFAULT; - return isdn_ppp_hangup_slave(name); -#endif - case IIOCNETHUP: - /* Force hangup of a network-interface */ - if (!arg) - return -EINVAL; - if (copy_from_user(name, (char *) arg, sizeof(name))) - return -EFAULT; - return isdn_net_force_hangup(name); - break; -#endif /* CONFIG_NETDEVICES */ - case IIOCSETVER: - dev->net_verbose = arg; - printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose); - return 0; - case IIOCSETGST: - if (arg) - dev->global_flags |= ISDN_GLOBAL_STOPPED; - else - dev->global_flags &= ~ISDN_GLOBAL_STOPPED; - printk(KERN_INFO "isdn: Global Mode %s\n", - (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running"); - return 0; - case IIOCSETBRJ: - drvidx = -1; - if (arg) { - int i; - char *p; - if (copy_from_user((char *) &iocts, (char *) arg, - sizeof(isdn_ioctl_struct))) - return -EFAULT; - if (strlen(iocts.drvid)) { - if ((p = strchr(iocts.drvid, ','))) - *p = 0; - drvidx = -1; - for (i = 0; i < ISDN_MAX_DRIVERS; i++) - if (!(strcmp(dev->drvid[i], iocts.drvid))) { - drvidx = i; - break; - } - } - } - if (drvidx == -1) - return -ENODEV; - if (iocts.arg) - dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS; - else - dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS; - return 0; - case IIOCSIGPRF: - dev->profd = current; - return 0; - break; - case IIOCGETPRF: - /* Get all Modem-Profiles */ - if (arg) { - char *p = (char *) arg; - int i; - - if ((ret = verify_area(VERIFY_WRITE, (void *) arg, - (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) - * ISDN_MAX_CHANNELS))) - return ret; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (copy_to_user(p, dev->mdm.info[i].emu.profile, - ISDN_MODEM_NUMREG)) - return -EFAULT; - p += ISDN_MODEM_NUMREG; - if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN)) - return -EFAULT; - p += ISDN_MSNLEN; - if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN)) - return -EFAULT; - p += ISDN_LMSNLEN; - } - return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS; - } else - return -EINVAL; - break; - case IIOCSETPRF: - /* Set all Modem-Profiles */ - if (arg) { - char *p = (char *) arg; - int i; - - if ((ret = verify_area(VERIFY_READ, (void *) arg, - (ISDN_MODEM_NUMREG + ISDN_MSNLEN) - * ISDN_MAX_CHANNELS))) - return ret; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (copy_from_user(dev->mdm.info[i].emu.profile, p, - ISDN_MODEM_NUMREG)) - return -EFAULT; - p += ISDN_MODEM_NUMREG; - if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)) - return -EFAULT; - p += ISDN_MSNLEN; - } - return 0; - } else - return -EINVAL; - break; - case IIOCSETMAP: - case IIOCGETMAP: - /* Set/Get MSN->EAZ-Mapping for a driver */ - if (arg) { - - if (copy_from_user((char *) &iocts, - (char *) arg, - sizeof(isdn_ioctl_struct))) - return -EFAULT; - if (strlen(iocts.drvid)) { - drvidx = -1; - for (i = 0; i < ISDN_MAX_DRIVERS; i++) - if (!(strcmp(dev->drvid[i], iocts.drvid))) { - drvidx = i; - break; - } - } else - drvidx = 0; - if (drvidx == -1) - return -ENODEV; - if (cmd == IIOCSETMAP) { - int loop = 1; - - p = (char *) iocts.arg; - i = 0; - while (loop) { - int j = 0; - - while (1) { - if ((ret = verify_area(VERIFY_READ, p, 1))) - return ret; - get_user(bname[j], p++); - switch (bname[j]) { - case '\0': - loop = 0; - /* Fall through */ - case ',': - bname[j] = '\0'; - strcpy(dev->drv[drvidx]->msn2eaz[i], bname); - j = ISDN_MSNLEN; - break; - default: - j++; - } - if (j >= ISDN_MSNLEN) - break; - } - if (++i > 9) - break; - } - } else { - p = (char *) iocts.arg; - for (i = 0; i < 10; i++) { - sprintf(bname, "%s%s", - strlen(dev->drv[drvidx]->msn2eaz[i]) ? - dev->drv[drvidx]->msn2eaz[i] : "_", - (i < 9) ? "," : "\0"); - if (copy_to_user(p, bname, strlen(bname) + 1)) - return -EFAULT; - p += strlen(bname); - } - } - return 0; - } else - return -EINVAL; - case IIOCDBGVAR: - if (arg) { - if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))) - return -EFAULT; - return 0; - } else - return -EINVAL; - break; - default: - if ((cmd & IIOCDRVCTL) == IIOCDRVCTL) - cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK; - else - return -EINVAL; - if (arg) { - int i; - char *p; - if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))) - return -EFAULT; - if (strlen(iocts.drvid)) { - if ((p = strchr(iocts.drvid, ','))) - *p = 0; - drvidx = -1; - for (i = 0; i < ISDN_MAX_DRIVERS; i++) - if (!(strcmp(dev->drvid[i], iocts.drvid))) { - drvidx = i; - break; - } - } else - drvidx = 0; - if (drvidx == -1) - return -ENODEV; - if ((ret = verify_area(VERIFY_WRITE, (void *) arg, - sizeof(isdn_ioctl_struct)))) - return ret; - c.driver = drvidx; - c.command = ISDN_CMD_IOCTL; - c.arg = cmd; - memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong)); - ret = isdn_command(&c); - memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong)); - if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))) - return -EFAULT; - return ret; - } else - return -EINVAL; - } - } -#ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg)); -#endif - return -ENODEV; - -#undef name -#undef bname -#undef iocts -#undef phone -#undef cfg -} - -/* - * Open the device code. - * MOD_INC_USE_COUNT make sure that the driver memory is not freed - * while the device is in use. - */ -static int -isdn_open(struct inode *ino, struct file *filep) -{ - uint minor = MINOR(ino->i_rdev); - int drvidx; - int chidx; - - if (minor == ISDN_MINOR_STATUS) { - infostruct *p; - - if ((p = (infostruct *) kmalloc(sizeof(infostruct), GFP_KERNEL))) { - MOD_INC_USE_COUNT; - 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; - return 0; - } else - return -ENOMEM; - } - if (!dev->channels) - return -ENODEV; - if (minor < ISDN_MINOR_CTRL) { - drvidx = isdn_minor2drv(minor); - if (drvidx < 0) - return -ENODEV; - chidx = isdn_minor2chan(minor); - if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) - return -ENODEV; - if (!(dev->drv[drvidx]->online & (1 << chidx))) - return -ENODEV; - isdn_MOD_INC_USE_COUNT(); - return 0; - } - if (minor <= ISDN_MINOR_CTRLMAX) { - drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL); - if (drvidx < 0) - return -ENODEV; - isdn_MOD_INC_USE_COUNT(); -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - if(!drvidx) isdn_dw_abc_lcr_open(); -#endif - return 0; - } -#ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) { - int ret; - if (!(ret = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep))) - isdn_MOD_INC_USE_COUNT(); - return ret; - } -#endif - return -ENODEV; -} - -static int -isdn_close(struct inode *ino, struct file *filep) -{ - uint minor = MINOR(ino->i_rdev); - - if (minor == ISDN_MINOR_STATUS) { - infostruct *p = dev->infochain; - infostruct *q = NULL; - - MOD_DEC_USE_COUNT; - while (p) { - if (p->private == (char *) &(filep->private_data)) { - if (q) - q->next = p->next; - else - dev->infochain = (infostruct *) (p->next); - kfree(p); - return 0; - } - q = p; - p = (infostruct *) (p->next); - } - printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n"); - return 0; - } - isdn_MOD_DEC_USE_COUNT(); - if (minor < ISDN_MINOR_CTRL) - return 0; - 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 - return 0; - } -#ifdef CONFIG_ISDN_PPP - if (minor <= ISDN_MINOR_PPPMAX) - isdn_ppp_release(minor - ISDN_MINOR_PPP, filep); -#endif - return 0; -} - -static struct file_operations isdn_fops = -{ - isdn_lseek, - isdn_read, - isdn_write, - NULL, /* isdn_readdir */ - isdn_poll, /* isdn_poll */ - isdn_ioctl, /* isdn_ioctl */ - NULL, /* isdn_mmap */ - isdn_open, - NULL, /* flush */ - isdn_close, - NULL /* fsync */ -}; - -char * -isdn_map_eaz2msn(char *msn, int di) -{ - driver *this = dev->drv[di]; - int i; - - if (strlen(msn) == 1) { - i = msn[0] - '0'; - if ((i >= 0) && (i <= 9)) - if (strlen(this->msn2eaz[i])) - return (this->msn2eaz[i]); - } - return (msn); -} - -/* - * Find an unused ISDN-channel, whose feature-flags match the - * given L2- and L3-protocols. - */ -#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038)) - -int -isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev - ,int pre_chan, char *msn) -{ - int i; - ulong flags; - ulong features; - ulong vfeatures; - - save_flags(flags); - cli(); - features = ((1 << l2_proto) | (0x10000 << l3_proto)); - vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) & - ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038)); - /* If Layer-2 protocol is V.110, accept drivers with - * transparent feature even if these don't support V.110 - * because we can emulate this in linklevel. - */ - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - 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; - if (!strcmp(isdn_map_eaz2msn(msn, d), "-")) - continue; - if (dev->usage[i] & ISDN_USAGE_DISABLED) - continue; /* usage not allowed */ - if (dev->drv[d]->flags & DRV_FLAG_RUNNING) { - if (((dev->drv[d]->interface->features & features) == features) || - (((dev->drv[d]->interface->features & vfeatures) == vfeatures) && - (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) { - if ((pre_dev < 0) || (pre_chan < 0)) { - dev->usage[i] &= ISDN_USAGE_EXCLUSIVE; - dev->usage[i] |= usage; - isdn_info_update(); - 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(); - restore_flags(flags); - return i; - } - } - } - } - } - restore_flags(flags); - return -1; -} - -/* - * Set state of ISDN-channel to 'unused' - */ -void -isdn_free_channel(int di, int ch, int usage) -{ - int i; - ulong flags; - - save_flags(flags); - cli(); -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - isdn_dw_abc_free_lch_with_pch(di,ch); -#endif - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) && - (dev->drvmap[i] == di) && - (dev->chanmap[i] == ch)) { - dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE); - strcpy(dev->num[i], "???"); - dev->ibytes[i] = 0; - dev->obytes[i] = 0; -// 20.10.99 JIM, try to reinitialize v110 ! - dev->v110emu[i] = 0; - atomic_set(&(dev->v110use[i]), 0); - isdn_v110_close(dev->v110[i]); - dev->v110[i] = NULL; -// 20.10.99 JIM, try to reinitialize v110 ! - isdn_info_update(); - isdn_free_queue(&dev->drv[di]->rpqueue[ch]); - } - restore_flags(flags); -} - -/* - * Cancel Exclusive-Flag for ISDN-channel - */ -void -isdn_unexclusive_channel(int di, int ch) -{ - int i; - ulong flags; - - save_flags(flags); - cli(); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if ((dev->drvmap[i] == di) && - (dev->chanmap[i] == ch)) { - dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE; - isdn_info_update(); - restore_flags(flags); - return; - } - restore_flags(flags); -} - -/* - * writebuf replacement for SKB_ABLE drivers - */ -static int -isdn_writebuf_stub(int drvidx, int chan, const u_char * buf, int len, - int user) -{ - int ret; - int hl = dev->drv[drvidx]->interface->hl_hdrlen; - struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC); - - if (!skb) - return 0; - skb_reserve(skb, hl); - if (user) - copy_from_user(skb_put(skb, len), buf, len); - else - memcpy(skb_put(skb, len), buf, len); - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb); - if (ret <= 0) - dev_kfree_skb(skb); - if (ret > 0) - dev->obytes[isdn_dc2minor(drvidx, chan)] += ret; - return ret; -} - -/* - * Return: length of data on success, -ERRcode on failure. - */ -int -isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb) -{ - int ret; - struct sk_buff *nskb = NULL; - int v110_ret = skb->len; - int idx = isdn_dc2minor(drvidx, chan); - - if (dev->v110[idx]) { - atomic_inc(&dev->v110use[idx]); - nskb = isdn_v110_encode(dev->v110[idx], skb); - atomic_dec(&dev->v110use[idx]); - if (!nskb) - return 0; - v110_ret = *((int *)nskb->data); - skb_pull(nskb, sizeof(int)); - if (!nskb->len) { - dev_kfree_skb(nskb); - dev_kfree_skb(skb); - return v110_ret; - } - /* V.110 must always be acknowledged */ - ack = 1; - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb); - } else { - int hl = dev->drv[drvidx]->interface->hl_hdrlen; - - if( skb_headroom(skb) < hl ){ - /* - * This should only occur when new HL driver with - * increased hl_hdrlen was loaded after netdevice - * was created and connected to the new driver. - * - * The V.110 branch (re-allocates on its own) does - * not need this - */ - struct sk_buff * skb_tmp; - - skb_tmp = skb_realloc_headroom(skb, hl); - printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed"); - if (!skb_tmp) return -ENOMEM; /* 0 better? */ - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp); - if( ret > 0 ){ - dev_kfree_skb(skb); - } else { - dev_kfree_skb(skb_tmp); - } - } else { - ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb); - } - } - if (ret > 0) { - dev->obytes[idx] += ret; - if (dev->v110[idx]) { - atomic_inc(&dev->v110use[idx]); - dev->v110[idx]->skbuser++; - atomic_dec(&dev->v110use[idx]); - dev_kfree_skb(skb); - /* For V.110 return unencoded data length */ - ret = v110_ret; - if (ret == skb->len) - dev_kfree_skb(skb); - } - } else - if (dev->v110[idx]) - dev_kfree_skb(nskb); - return ret; -} - -int -register_isdn_module(isdn_module *m) { -#if 0 - isdn_module_list **pp = &dev->modules; - isdn_module *new = kmalloc(sizeof(isdn_module_list), GFP_KERNEL); - - if (!new) { - printk(KERN_WARNING "isdn: Out of memory in register_isdn_module\n"); - return -1; - } - while (*pp && (*pp)->orig != m) - pp = &(*pp)->next; - if (*pp != NULL) { - printk(KERN_WARNING "isdn: Module %s already registered\n", m->name); - return -1; - } - while (*pp && ((*pp)->module.priority < m->priority)) - pp = &(*pp)->next; - new->next = *pp; - new->orig = m; - new->module = *m; - - *pp = new; -#endif - return 0; -} - -int -unregister_isdn_module(isdn_module *m) { -#if 0 - isdn_module_list **pp = &dev->modules; - - while (*pp && *pp != m) - pp = &(*pp)->next; - if (*pp == NULL) { - printk(KERN_WARNING "isdn: Module %s not found\n", m->name); - return -1; - } -#endif - return 0; -} - -int -isdn_add_channels(driver *d, int drvidx, int n, int adding) -{ - int j, k, m; - ulong flags; - -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&d->st_waitq); -#endif - if (d->flags & DRV_FLAG_RUNNING) - return -1; - if (n < 1) return 0; - - m = (adding) ? d->channels + n : n; - - if (dev->channels + n > ISDN_MAX_CHANNELS) { - printk(KERN_WARNING "register_isdn: Max. %d channels supported\n", - ISDN_MAX_CHANNELS); - return -1; - } - - if ((adding) && (d->rcverr)) - kfree(d->rcverr); - if (!(d->rcverr = (int *) kmalloc(sizeof(int) * m, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n"); - return -1; - } - memset((char *) d->rcverr, 0, sizeof(int) * m); - - if ((adding) && (d->rcvcount)) - kfree(d->rcvcount); - 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; - } - memset((char *) d->rcvcount, 0, sizeof(int) * m); - - if ((adding) && (d->rpqueue)) { - for (j = 0; j < d->channels; j++) - isdn_free_queue(&d->rpqueue[j]); - kfree(d->rpqueue); - } - 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); - kfree(d->rcverr); - } - return -1; - } - for (j = 0; j < m; j++) { - skb_queue_head_init(&d->rpqueue[j]); - } - - if ((adding) && (d->rcv_waitq)) - kfree(d->rcv_waitq); -#ifdef COMPAT_HAS_NEW_WAITQ - d->rcv_waitq = (wait_queue_head_t *) - kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_KERNEL); - if (!d->rcv_waitq) { -#else - if (!(d->rcv_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { -#endif - printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n"); - if (!adding) { - kfree(d->rpqueue); - kfree(d->rcvcount); - kfree(d->rcverr); - } - return -1; - } -#ifdef COMPAT_HAS_NEW_WAITQ - d->snd_waitq = d->rcv_waitq + m; - for (j = 0; j < m; j++) { - init_waitqueue_head(&d->rcv_waitq[j]); - init_waitqueue_head(&d->snd_waitq[j]); - } -#else - memset((char *) d->rcv_waitq, 0, sizeof(struct wait_queue *) * m); - - if ((adding) && (d->snd_waitq)) - kfree(d->snd_waitq); - if (!(d->snd_waitq = (struct wait_queue **) - kmalloc(sizeof(struct wait_queue *) * m, GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc snd_waitq\n"); - if (!adding) { - kfree(d->rcv_waitq); - kfree(d->rpqueue); - kfree(d->rcvcount); - kfree(d->rcverr); - } - return -1; - } - memset((char *) d->snd_waitq, 0, sizeof(struct wait_queue *) * m); -#endif - - dev->channels += n; - save_flags(flags); - cli(); - for (j = d->channels; j < m; j++) - for (k = 0; k < ISDN_MAX_CHANNELS; k++) - 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); - d->channels = m; - return 0; -} - -/* - * Low-level-driver registration - */ - -static void -set_global_features(void) -{ - int drvidx; - - dev->global_features = 0; - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { - if (!dev->drv[drvidx]) - continue; - if (dev->drv[drvidx]->interface) - dev->global_features |= dev->drv[drvidx]->interface->features; - } -} - -#ifdef CONFIG_ISDN_DIVERSION -extern isdn_divert_if *divert_if; - -static char *map_drvname(int di) -{ - if ((di < 0) || (di >= ISDN_MAX_DRIVERS)) - return(NULL); - return(dev->drvid[di]); /* driver name */ -} /* map_drvname */ - -static int map_namedrv(char *id) -{ int i; - - for (i = 0; i < ISDN_MAX_DRIVERS; i++) - { if (!strcmp(dev->drvid[i],id)) - return(i); - } - return(-1); -} /* map_namedrv */ - -int DIVERT_REG_NAME(isdn_divert_if *i_div) -{ - if (i_div->if_magic != DIVERT_IF_MAGIC) - return(DIVERT_VER_ERR); - switch (i_div->cmd) - { - case DIVERT_CMD_REL: - if (divert_if != i_div) - return(DIVERT_REL_ERR); - divert_if = NULL; /* free interface */ - MOD_DEC_USE_COUNT; - return(DIVERT_NO_ERR); - - case DIVERT_CMD_REG: - if (divert_if) - return(DIVERT_REG_ERR); - i_div->ll_cmd = isdn_command; /* set command function */ - i_div->drv_to_name = map_drvname; - i_div->name_to_drv = map_namedrv; - MOD_INC_USE_COUNT; - divert_if = i_div; /* remember interface */ - return(DIVERT_NO_ERR); - - default: - return(DIVERT_CMD_ERR); - } -} /* DIVERT_REG_NAME */ - -EXPORT_SYMBOL(DIVERT_REG_NAME); - -#endif CONFIG_ISDN_DIVERSION - - -EXPORT_SYMBOL(register_isdn); -EXPORT_SYMBOL(register_isdn_module); -EXPORT_SYMBOL(unregister_isdn_module); -#ifdef CONFIG_ISDN_PPP -EXPORT_SYMBOL(isdn_ppp_register_compressor); -EXPORT_SYMBOL(isdn_ppp_unregister_compressor); -#endif - -int -register_isdn(isdn_if * i) -{ - driver *d; - int j; - ulong flags; - int drvidx; - - if (dev->drivers >= ISDN_MAX_DRIVERS) { - printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n", - ISDN_MAX_DRIVERS); - return 0; - } - if (!i->writebuf_skb) { - printk(KERN_WARNING "register_isdn: No write routine given.\n"); - return 0; - } - if (!(d = (driver *) kmalloc(sizeof(driver), GFP_KERNEL))) { - printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n"); - return 0; - } - memset((char *) d, 0, sizeof(driver)); - - d->maxbufsize = i->maxbufsize; - d->pktcount = 0; - d->stavail = 0; - d->flags = DRV_FLAG_LOADED; - d->online = 0; - d->interface = i; - d->channels = 0; - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) - if (!dev->drv[drvidx]) - break; - if (isdn_add_channels(d, drvidx, i->channels, 0)) { - kfree(d); - return 0; - } - i->channels = drvidx; - i->rcvcallb_skb = isdn_receive_skb_callback; - i->statcallb = isdn_status_callback; - if (!strlen(i->id)) - sprintf(i->id, "line%d", drvidx); - save_flags(flags); - cli(); - for (j = 0; j < drvidx; j++) - if (!strcmp(i->id, dev->drvid[j])) - sprintf(i->id, "line%d", drvidx); - dev->drv[drvidx] = d; - strcpy(dev->drvid[drvidx], i->id); - isdn_info_update(); - dev->drivers++; - set_global_features(); - restore_flags(flags); - return 1; -} - -/* - ***************************************************************************** - * And now the modules code. - ***************************************************************************** - */ - -extern int printk(const char *fmt,...); - -#ifdef MODULE -#define isdn_init init_module -#endif - -static char * -isdn_getrev(const char *revision) -{ - char *rev; - char *p; - - if ((p = strchr(revision, ':'))) { - rev = p + 2; - p = strchr(rev, '$'); - *--p = 0; - } else - rev = "???"; - return rev; -} - -#ifdef HAVE_DEVFS_FS -#ifdef CONFIG_DEVFS_FS - -static devfs_handle_t devfs_handle = NULL; - -static void isdn_register_devfs(int k) -{ - char buf[11]; - - sprintf (buf, "isdn%d", k); - dev->devfs_handle_isdnX[k] = - devfs_register (devfs_handle, buf, 0, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_B + k,0600 | S_IFCHR, 0, 0, - &isdn_fops, NULL); - sprintf (buf, "isdnctrl%d", k); - dev->devfs_handle_isdnctrlX[k] = - devfs_register (devfs_handle, buf, 0, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_CTRL + k, 0600 | S_IFCHR, - 0, 0, &isdn_fops, NULL); -} - -static void isdn_unregister_devfs(int k) -{ - devfs_unregister (dev->devfs_handle_isdnX[k]); - devfs_unregister (dev->devfs_handle_isdnctrlX[k]); -} - -static void isdn_init_devfs(void) -{ -# ifdef CONFIG_ISDN_PPP - int i; -# endif - - devfs_handle = devfs_mk_dir (NULL, "isdn", 4, NULL); -# ifdef CONFIG_ISDN_PPP - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - char buf[8]; - - sprintf (buf, "ippp%d", i); - dev->devfs_handle_ipppX[i] = - devfs_register (devfs_handle, buf, 0, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_PPP + i, - 0600 | S_IFCHR, 0, 0, &isdn_fops, NULL); - } -# endif - - dev->devfs_handle_isdninfo = - devfs_register (devfs_handle, "isdninfo", 0, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_STATUS, 0600 | S_IFCHR, - 0, 0, &isdn_fops, NULL); - dev->devfs_handle_isdnctrl = - devfs_register (devfs_handle, "isdnctrl", 0, DEVFS_FL_DEFAULT, - ISDN_MAJOR, ISDN_MINOR_CTRL, 0600 | S_IFCHR, 0, 0, - &isdn_fops, NULL); -} - -static void isdn_cleanup_devfs(void) -{ -# ifdef CONFIG_ISDN_PPP - int i; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - devfs_unregister (dev->devfs_handle_ipppX[i]); -# endif - devfs_unregister (dev->devfs_handle_isdninfo); - devfs_unregister (dev->devfs_handle_isdnctrl); - devfs_unregister (devfs_handle); -} - -#else /* CONFIG_DEVFS_FS */ -static void isdn_register_devfs(int dummy) -{ - return; -} - -static void isdn_unregister_devfs(int dummy) -{ - return; -} - -static void isdn_init_devfs(void) -{ - return; -} - -static void isdn_cleanup_devfs(void) -{ - return; -} - -#endif /* CONFIG_DEVFS_FS */ -#endif /* HAVE_DEVFS_FS */ - -/* - * Allocate and initialize all data, register modem-devices - */ -int -isdn_init(void) -{ - int i; - char tmprev[50]; - - if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) { - printk(KERN_WARNING "isdn: Could not allocate device-struct.\n"); - return -EIO; - } - memset((char *) dev, 0, sizeof(isdn_dev)); - init_timer(&dev->timer); - dev->timer.function = isdn_timer_funct; -#ifdef COMPAT_HAS_NEW_WAITQ - init_MUTEX(&dev->sem); - init_waitqueue_head(&dev->info_waitq); -#else - dev->sem = MUTEX; -#endif - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - dev->drvmap[i] = -1; - dev->chanmap[i] = -1; - dev->m_idx[i] = -1; - strcpy(dev->num[i], "???"); -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&dev->mdm.info[i].open_wait); - init_waitqueue_head(&dev->mdm.info[i].close_wait); -#endif - } - if (devfs_register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) { - printk(KERN_WARNING "isdn: Could not register control devices\n"); - 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) - tty_unregister_driver(&dev->mdm.cua_modem); - 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; - } -#ifdef CONFIG_ISDN_PPP - if (isdn_ppp_init() < 0) { - printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n"); - tty_unregister_driver(&dev->mdm.tty_modem); - 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; - } -#endif /* CONFIG_ISDN_PPP */ - - strcpy(tmprev, isdn_revision); - printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev)); - strcpy(tmprev, isdn_tty_revision); - printk("%s/", isdn_getrev(tmprev)); - strcpy(tmprev, isdn_net_revision); - printk("%s/", isdn_getrev(tmprev)); - strcpy(tmprev, isdn_ppp_revision); - printk("%s/", isdn_getrev(tmprev)); - strcpy(tmprev, isdn_audio_revision); - printk("%s/", isdn_getrev(tmprev)); - strcpy(tmprev, isdn_v110_revision); - printk("%s", isdn_getrev(tmprev)); - -#ifdef MODULE - printk(" loaded\n"); -#else - printk("\n"); - isdn_cards_init(); -#endif - isdn_info_update(); -#ifdef CONFIG_ISDN_WITH_ABC - isdn_dw_abc_init_func(); -#endif - return 0; -} - -#ifdef MODULE -/* - * Unload module - */ -void -cleanup_module(void) -{ - int flags; - int i; - -#ifdef CONFIG_ISDN_PPP - isdn_ppp_cleanup(); -#endif - save_flags(flags); - cli(); - if (isdn_net_rmall() < 0) { - printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n"); - restore_flags(flags); - return; - } - if (tty_unregister_driver(&dev->mdm.tty_modem)) { - printk(KERN_WARNING "isdn: ttyI-device busy, remove cancelled\n"); - restore_flags(flags); - return; - } - if (tty_unregister_driver(&dev->mdm.cua_modem)) { - printk(KERN_WARNING "isdn: cui-device busy, remove cancelled\n"); - restore_flags(flags); - return; - } - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - isdn_tty_cleanup_xmit(&dev->mdm.info[i]); - kfree(dev->mdm.info[i].xmit_buf - 4); -#ifdef CONFIG_ISDN_TTY_FAX - kfree(dev->mdm.info[i].fax); -#endif - } - if (devfs_unregister_chrdev(ISDN_MAJOR, "isdn") != 0) { - printk(KERN_WARNING "isdn: controldevice busy, remove cancelled\n"); - } else { -#ifdef HAVE_DEVFS_FS - isdn_cleanup_devfs(); -#endif /* HAVE_DEVFS_FS */ - del_timer(&dev->timer); - vfree(dev); - printk(KERN_NOTICE "ISDN-subsystem unloaded\n"); - } - restore_flags(flags); -#ifdef CONFIG_ISDN_WITH_ABC - isdn_dw_abc_release_func(); -#endif -} -#endif diff --git a/drivers/isdn/isdn_common.h b/drivers/isdn/isdn_common.h deleted file mode 100644 index 498f6c8f..00000000 --- a/drivers/isdn/isdn_common.h +++ /dev/null @@ -1,145 +0,0 @@ -/* $Id$ - - * header for Linux ISDN subsystem, common used functions and debugging-switches (linklevel). - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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. - * - * $Log$ - * Revision 1.17 1999/10/27 21:21:17 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.16 1999/07/01 08:29:54 keil - * compatibility to 2.3 kernel - * - * Revision 1.15 1999/04/18 14:06:50 fritz - * Removed TIMRU stuff. - * - * Revision 1.14 1999/04/12 12:33:18 fritz - * Changes from 2.0 tree. - * - * Revision 1.13 1999/03/02 12:04:47 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.12 1998/06/26 15:12:27 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.11 1998/04/14 16:28:47 he - * Fixed user space access with interrupts off and remaining - * copy_{to,from}_user() -> -EFAULT return codes - * - * Revision 1.10 1998/03/07 18:21:03 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.9 1998/02/20 17:19:01 fritz - * Added common stub for sending commands to lowlevel. - * - * Revision 1.8 1997/10/09 21:28:49 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.7 1997/10/01 09:20:30 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.6 1997/02/28 02:32:44 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.5 1997/02/10 10:05:45 fritz - * More changes for Kernel 2.1.X - * Symbol information moved to isdn_syms.c - * - * Revision 1.4 1997/02/03 22:56:50 fritz - * Removed isdn_writebuf_stub prototype. - * - * Revision 1.3 1996/05/19 00:13:05 fritz - * Removed debug flag. - * - * Revision 1.2 1996/04/20 16:20:40 fritz - * Misc. typos. - * - * Revision 1.1 1996/01/10 21:37:19 fritz - * Initial revision - * - */ - -#undef ISDN_DEBUG_MODEM_OPEN -#undef ISDN_DEBUG_MODEM_IOCTL -#undef ISDN_DEBUG_MODEM_WAITSENT -#undef ISDN_DEBUG_MODEM_HUP -#undef ISDN_DEBUG_MODEM_ICALL -#undef ISDN_DEBUG_MODEM_DUMP -#undef ISDN_DEBUG_MODEM_VOICE -#undef ISDN_DEBUG_AT -#undef ISDN_DEBUG_NET_DUMP -#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); -extern void isdn_free_channel(int di, int ch, int usage); -extern void isdn_all_eaz(int di, int ch); -extern int isdn_command(isdn_ctrl *); -extern int isdn_dc2minor(int di, int ch); -extern void isdn_info_update(void); -extern char *isdn_map_eaz2msn(char *msn, int di); -extern void isdn_timer_ctrl(int tf, int onoff); -extern void isdn_unexclusive_channel(int di, int ch); -extern int isdn_getnum(char **); -#ifdef COMPAT_HAS_NEW_WAITQ -extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *); -#else -extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**); -#endif -extern int isdn_get_free_channel(int, int, int, int, int, char *); -extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *); -extern int register_isdn(isdn_if * i); -extern int isdn_wildmat(char *, char *); -extern int isdn_add_channels(driver *, int, int, int); -#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP) -extern void isdn_dumppkt(char *, u_char *, int, int); -#endif diff --git a/drivers/isdn/isdn_concap.c b/drivers/isdn/isdn_concap.c deleted file mode 100644 index 0f05666a..00000000 --- a/drivers/isdn/isdn_concap.c +++ /dev/null @@ -1,114 +0,0 @@ -/* $Id$ - - * Stuff to support the concap_proto by isdn4linux. isdn4linux - specific - * stuff goes here. Stuff that depends only on the concap protocol goes to - * another -- protocol specific -- source file. - * - * $Log$ - * Revision 1.5 1998/10/30 18:44:48 he - * pass return value from isdn_net_dial_req for dialmode change - * - * Revision 1.4 1998/10/30 17:55:24 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.3 1998/05/26 22:39:22 he - * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) - * concap typo - * cleared dev.tbusy in isdn_net BCONN status callback - * - * Revision 1.2 1998/01/31 22:49:21 keil - * correct comments - * - * Revision 1.1 1998/01/31 22:27:57 keil - * New files from Henner Eisen for X.25 support - * - */ - - -#include -#include "isdn_x25iface.h" -#include "isdn_net.h" -#include -#include "isdn_concap.h" - - -/* The following set of device service operations are for encapsulation - protocols that require for reliable datalink semantics. That means: - - - before any data is to be submitted the connection must explicitly - be set up. - - after the successful set up of the connection is signalled the - connection is considered to be reliably up. - - Auto-dialing ist not compatible with this requirements. Thus, auto-dialing - is completely bypassed. - - It might be possible to implement a (non standardized) datalink protocol - that provides a reliable data link service while using some auto dialing - mechanism. Such a protocol would need an auxiliary channel (i.e. user-user- - signaling on the D-channel) while the B-channel is down. - */ - - -int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb) -{ - int tmp; - struct net_device *ndev = concap -> net_dev; - isdn_net_local *lp = (isdn_net_local *) ndev->priv; - - IX25DEBUG( "isdn_concap_dl_data_req: %s \n", concap->net_dev->name); - lp->huptimer = 0; - tmp=isdn_net_send_skb(ndev, lp, skb); - IX25DEBUG( "isdn_concap_dl_data_req: %s : isdn_net_send_skb returned %d\n", concap -> net_dev -> name, tmp); - return tmp; -} - - -int isdn_concap_dl_connect_req(struct concap_proto *concap) -{ - struct net_device *ndev = concap -> net_dev; - isdn_net_local *lp = (isdn_net_local *) ndev->priv; - int ret; - IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name); - - /* dial ... */ - ret = isdn_net_dial_req( lp ); - if ( ret ) IX25DEBUG("dialing failed\n"); - return ret; -} - -int isdn_concap_dl_disconn_req(struct concap_proto *concap) -{ - IX25DEBUG( "isdn_concap_dl_disconn_req: %s \n", concap -> net_dev -> name); - - isdn_net_hangup( concap -> net_dev ); - return 0; -} - -struct concap_device_ops isdn_concap_reliable_dl_dops = { - &isdn_concap_dl_data_req, - &isdn_concap_dl_connect_req, - &isdn_concap_dl_disconn_req -}; - -struct concap_device_ops isdn_concap_demand_dial_dops = { - NULL, /* set this first entry to something like &isdn_net_start_xmit, - but the entry part of the current isdn_net_start_xmit must be - separated first. */ - /* no connection control for demand dial semantics */ - NULL, - NULL, -}; - -/* The following should better go into a dedicated source file such that - this sourcefile does not need to include any protocol specific header - files. For now: - */ -struct concap_proto * isdn_concap_new( int encap ) -{ - switch ( encap ) { - case ISDN_NET_ENCAP_X25IFACE: - return isdn_x25iface_proto_new(); - } - return NULL; -} diff --git a/drivers/isdn/isdn_concap.h b/drivers/isdn/isdn_concap.h deleted file mode 100644 index 8349f462..00000000 --- a/drivers/isdn/isdn_concap.h +++ /dev/null @@ -1,7 +0,0 @@ -/* $Id$ - */ -extern struct concap_device_ops isdn_concap_reliable_dl_dops; -extern struct concap_device_ops isdn_concap_demand_dial_dops; -extern struct concap_proto * isdn_concap_new( int ); - - diff --git a/drivers/isdn/isdn_dwabc.c b/drivers/isdn/isdn_dwabc.c deleted file mode 100644 index 3d5a3cd5..00000000 --- a/drivers/isdn/isdn_dwabc.c +++ /dev/null @@ -1,2351 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, abc-extension releated funktions. - * - * Author: abc GmbH written by Detlef Wengorz - * - * Many thanks for testing, debugging and writing Doku to: - * Mario Schugowski - * - * 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. - * - * $Log$ - * - * Revision 1.16 2000/02/06 21:49:59 detabc - * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections. - * Include checksum-recompute of ip- and udp-header's. - * - * Revision 1.15 2000/02/05 22:11:33 detabc - * Add rewriting of socket's and frame's saddr adressfield for - * dynip-connections. Only for tcp/ipv4 and switchable per interface. - * Include checksum-recompute of ip- and tcp-header's. - * - * Revision 1.14 2000/01/25 22:37:14 detabc - * modify changes from Karsten ( MSN == - ) for bind-groups - * - * Revision 1.13 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.12 2000/01/09 20:43:14 detabc - * exand logical bind-group's for both call's (in and out). - * add first part of kernel-config-help for abc-extension. - * - * Revision 1.11 1999/12/05 16:06:08 detabc - * add resethandling for rawip-compression. - * at now all B2-Protocols are usable with rawip-compression - * - * Revision 1.10 1999/12/04 15:05:25 detabc - * bugfix abc-rawip-bsdcompress with channel-bundeling - * - * Revision 1.9 1999/11/30 11:29:06 detabc - * add a on the fly frame-counter and limit - * - * Revision 1.8 1999/11/28 14:49:07 detabc - * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the - * uncompressed size. - * - * Revision 1.7 1999/11/26 15:54:59 detabc - * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol. - * - * Revision 1.6 1999/11/20 22:14:13 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.5 1999/11/07 21:57:04 detabc - * added dwabc-udpinfo-dial support - * - * Revision 1.4 1999/10/27 21:21:17 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.3 1999/09/23 22:22:41 detabc - * added tcp-keepalive-detect with local response (ipv4 only) - * added host-only-interface support - * (source ipaddr == interface ipaddr) (ipv4 only) - * ok with kernel 2.3.18 and 2.2.12 - * - * Revision 1.2 1999/09/14 22:53:53 detabc - * - * Test LCR ioctl call/ change a wrong pointer++/ - * LCR LL->user_space(isdnlog)->ioctl->LL ok now - * - * Revision 1.1 1999/09/12 16:19:39 detabc - * added abc features - * least cost routing for net-interfaces (only the HL side). - * need more implementation in the isdnlog-utility - * udp info support (first part). - * different EAZ on outgoing call's. - * more checks on D-Channel callbacks (double use of channels). - * tested and running with kernel 2.3.17 - * - * - */ - -#include -#define __NO_VERSION__ - -#ifdef CONFIG_ISDN_WITH_ABC - -static char *dwabcrevison = "$Revision$"; - -#include -#include -#include "isdn_common.h" - -struct PSH { - u_long saddr; - u_long daddr; - u_char zp[2]; - u_short len; -}; - - -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE -#include -#include -#include -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR -#include -#endif -#endif - -#include -#include -#include - -volatile u_long dwsjiffies; - -#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 -static struct isdn_ppp_comp_data BSD_COMP_INIT_DATA; -#ifndef CI_BSD_COMPRESS -#define CI_BSD_COMPRESS 21 -#endif -#endif - -#define NBYTEORDER_30BYTES 0x1e00 -#define DWABC_TMRES (HZ) - -//#define KEEPALIVE_VERBOSE 1 -//#define DYNADDR_VERBOSE 1 - -#define VERBLEVEL (dev->net_verbose > 2) - -static struct timer_list dw_abc_timer; - -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT -static struct semaphore lcr_sema; -#define LCR_LOCK() down_interruptible(&lcr_sema); -#define LCR_ULOCK() up(&lcr_sema); - -typedef struct ISDN_DW_ABC_LCR { - - struct ISDN_DW_ABC_LCR *lcr_prev; - struct ISDN_DW_ABC_LCR *lcr_next; - char lcr_printbuf[64 + ISDN_MSNLEN + ISDN_MSNLEN]; - char *lcr_poin; - char *lcr_epoin; - -} ISDN_DW_ABC_LCR; - -static ISDN_DW_ABC_LCR *first_lcr = NULL; -static ISDN_DW_ABC_LCR *last_lcr = NULL; - -static int lcr_open_count = 0; -static volatile u_long lcr_call_counter = 0; -static long lcr_requests = 0; - -#endif - -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - -static short deadloop = 0; - -static struct semaphore ipv4keep_sema; -#define TKAL_LOCK down_interruptible(&ipv4keep_sema) -#define TKAL_ULOCK up(&ipv4keep_sema) - -struct TCPM { - u_short tcpm_srcport; - u_short tcpm_dstport; - u_short tcpm_window; - struct TCPM *tcpm_prev; - struct TCPM *tcpm_next; - u_long tcpm_srcadr; - u_long tcpm_dstadr; - u_long tcpm_seqnr; - u_long tcpm_acknr; - u_long tcpm_time; -}; - -static u_long next_police = 0; -static u_long last_police = 0; - -#define MAX_MMA 16 -static void *MMA[MAX_MMA]; -static struct TCPM *tcp_first = NULL; -static struct TCPM *tcp_last = NULL; -static struct TCPM *tcp_free = NULL; -#endif - -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - -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) -{ - - ISDN_DW_ABC_LCR *p; - - LCR_LOCK(); - - while((p = first_lcr) != NULL) { - - first_lcr = p->lcr_next; - kfree(p); - } - - last_lcr = NULL; - lcr_requests = 0; - LCR_ULOCK(); -} - -void isdn_dw_abc_lcr_open(void) { lcr_open_count++; } - -void isdn_dw_abc_lcr_close(void) -{ - lcr_open_count--; - - if(lcr_open_count < 1) { - - lcr_open_count = 0; - dw_lcr_clear_all(); - } -} - - -size_t isdn_dw_abc_lcr_readstat(char *buf,size_t count) -{ - size_t r = 0; - - if(buf != NULL && count > 0) { - - ISDN_DW_ABC_LCR *p; - - LCR_LOCK(); - - while(count > 0 && (p = first_lcr) != NULL) { - - if(p->lcr_poin < p->lcr_epoin) { - - size_t n = p->lcr_epoin - p->lcr_poin; - - if(n > count) - n = count; - - copy_to_user(buf,p->lcr_poin,n); - p->lcr_poin += n; - count -= n; - buf += n; - r += n; - } - - if(p->lcr_poin < p->lcr_epoin) - break; - - if((first_lcr = p->lcr_next) != NULL) - first_lcr->lcr_prev = NULL; - else - last_lcr = NULL; - - kfree(p); - lcr_requests--; - } - - LCR_ULOCK(); - } - - return(r); -} - -void isdn_dw_abc_lcr_clear(isdn_net_local *lp) -{ - - if(lp != NULL) { - - u_long flags; - - save_flags(flags); - cli(); - - if(lp->dw_abc_lcr_cmd != NULL) - kfree(lp->dw_abc_lcr_cmd); - - if(lp->dw_abc_lcr_io != NULL) - kfree(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; - - restore_flags(flags); - } -} - - -u_long isdn_dw_abc_lcr_call_number( isdn_net_local *lp,isdn_ctrl *call_cmd) -{ - u_long mid = 0; - - isdn_dw_abc_lcr_clear(lp); - - if(lcr_requests < 100 && lp != NULL && lcr_open_count > 0 && call_cmd != NULL) { - - u_long flags = 0; - ISDN_DW_ABC_LCR *lc = NULL; - int ab = 0; - - save_flags(flags); - cli(); - - if((lp->dw_abc_lcr_cmd = - ( isdn_ctrl *)kmalloc(sizeof(isdn_ctrl),GFP_ATOMIC)) == NULL) { - - restore_flags(flags); - printk(KERN_DEBUG "%s %d : LCR no memory\n",__FILE__,__LINE__); - return(0); - } - - memcpy(lp->dw_abc_lcr_cmd,call_cmd,sizeof(*call_cmd)); - - if(!(++lcr_call_counter)) - lcr_call_counter++; - - 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; - - restore_flags(flags); - - if((lc = (ISDN_DW_ABC_LCR *)kmalloc(sizeof(*lc),GFP_KERNEL)) == NULL) { - - printk(KERN_DEBUG "%s %d : LCR no memory\n",__FILE__,__LINE__); - return(0); - } - - 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; - - LCR_LOCK(); - - if((lc->lcr_prev = last_lcr) != NULL) - lc->lcr_prev->lcr_next = lc; - else - first_lcr = lc; - - lc->lcr_next = NULL; - last_lcr = lc; - lcr_requests++; - LCR_ULOCK(); - - if(ab > 0) { - - save_flags(flags); - cli(); - - if(dev->drv[0] != NULL ) { - - dev->drv[0]->stavail += ab; - wake_up_interruptible(&dev->drv[0]->st_waitq); - } - - restore_flags(flags); - } - } - - return(mid); -} - - -void 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; - u_long flags; - - 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); - - save_flags(flags); - cli(); - p = dev->netdev; - - for(;p ; p = p->next) { - - isdn_net_local *lp = p->local; - - if(lp->dw_abc_lcr_callid == i.lcr_ioctl_callid && - lp->dw_abc_lcr_cmd != NULL) { - - 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__); - - } else { - - 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; - } - } - } - } - - restore_flags(flags); -} - -#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; - - if(skb->len >= 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 *)(skb->data + (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) -{ - static int recu = 0; - - dw_abc_timer.expires = jiffies + DWABC_TMRES; - add_timer(&dw_abc_timer); - dwsjiffies++; - - if(test_and_set_bit(0,&recu)) - return; - - clear_bit(0,&recu); -} - - - -#if CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE || CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR - -static char *ipnr2buf(u_long ipadr) -{ - static char buf[8][16]; - static u_char bufp = 0; - char *p = buf[bufp = (bufp + 1) & 7]; - u_char *up = (u_char *) & ipadr; - - sprintf(p, "%d.%d.%d.%d", up[0], up[1], up[2], up[3]); - return (p); -} -#endif - -#if CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - -static __inline void free_tcpm(struct TCPM *fb) -{ - if (fb != NULL) { - - if (fb->tcpm_prev != NULL) - fb->tcpm_prev->tcpm_next = fb->tcpm_next; - else - tcp_first = fb->tcpm_next; - - if (fb->tcpm_next != NULL) - fb->tcpm_next->tcpm_prev = fb->tcpm_prev; - else - tcp_last = fb->tcpm_prev; - - fb->tcpm_next = tcp_free; - tcp_free = fb; - fb->tcpm_prev = NULL; - } -} - -static void ip4keepalive_get_memory(void) -{ - struct TCPM *nb; - struct TCPM *enb; - int anz = 1024 / sizeof(struct TCPM); - int shl; - - for (shl = 0; shl < MAX_MMA && MMA[shl] != NULL; shl++) ; - - if (shl >= MAX_MMA) - return; - - nb = (struct TCPM *) kmalloc(sizeof(struct TCPM) * anz, GFP_ATOMIC); - - if (nb == NULL) { - - printk(KERN_DEBUG "ip4keepalive no mem\n"); - return; - - } - - memset((void *) nb, 0, sizeof(struct TCPM) * anz); - enb = nb + anz; - MMA[shl] = (void *) nb; - - for (; nb < enb; nb++) { - - nb->tcpm_next = tcp_free; - tcp_free = nb; - } -} - -static __inline struct TCPM *get_free_tm(void) -{ - struct TCPM *nb; - - if ((nb = tcp_free) == NULL) { - - if(MMA[MAX_MMA - 1] == NULL) - ip4keepalive_get_memory(); - - if ((nb = tcp_free) == NULL) { - - if ((nb = tcp_last) == NULL) - return (NULL); - - free_tcpm(nb); - - if ((nb = tcp_free) == NULL) - return (NULL); - } - } - - tcp_free = nb->tcpm_next; - - if ((nb->tcpm_next = tcp_first) != NULL) - tcp_first->tcpm_prev = nb; - else - tcp_last = nb; - - nb->tcpm_prev = NULL; - tcp_first = nb; - return (nb); -} - - -static int isdn_tcpipv4_test(struct net_device *ndev, struct iphdr *ip, struct sk_buff *skb) -/****************************************************************************** - - return == 0 == no keepalive - == 1 == keepalive response transmited - -****************************************************************************/ - -{ - int ip_hd_len = ip->ihl << 2; - struct tcphdr *tcp = (struct tcphdr *) (((u_char *) ip) + ip_hd_len); - - int tcp_hdr_len = tcp->doff << 2; - int tcp_data_len = ntohs(ip->tot_len) - tcp_hdr_len - ip_hd_len; - - u_long tcp_seqnr; - struct TCPM *nb; - int retw = 0; - int shl = 0; - int secure = 10000; - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) - printk(KERN_DEBUG "isdn_keepalive %s-called ipver %d ipproto %d %s->%s len %d\n", - (ndev != NULL) ? "Tx" : "Rx", - ip->version, - ip->protocol, - ipnr2buf(ip->saddr), - ipnr2buf(ip->daddr), - ntohs(ip->tot_len)); -#endif - - if (next_police < jiffies || last_police > jiffies) { - - next_police = last_police = jiffies; - next_police += HZ * 60; - nb = tcp_first; - - for (shl=0;nb != NULL && shl < secure;shl++) { - - struct TCPM *b = nb; - - nb = nb->tcpm_next; - - if (b->tcpm_time > jiffies || ((jiffies - b->tcpm_time) > (HZ * 3600 * 12))) - free_tcpm(b); - } - - if(shl >= secure) { - - printk(KERN_WARNING "ip_isdn_tcp_keepalive: police deadloop\n"); - deadloop = 1; - } - } - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) { - - printk(KERN_DEBUG - "isdn_keepalive %hd->%hd %d %d %d/%d\n", - ntohs(tcp->source), - ntohs(tcp->dest), - ip_hd_len, - tcp->doff, - tcp_hdr_len, - tcp_data_len); - } -#endif - if (tcp_data_len < 0) { - - printk(KERN_DEBUG - "isdn_keepalive adaten < 0 %d %d %d/%d\n", - ip_hd_len, - tcp->doff, - tcp_hdr_len, - tcp_data_len); - - return (0); - } - - if(ndev == NULL) { - - for (nb = tcp_first,shl = 0; nb != NULL && shl < secure && - ((nb->tcpm_srcadr ^ ip->daddr) || - (nb->tcpm_dstadr ^ ip->saddr) || - (nb->tcpm_srcport ^ tcp->dest) || - (nb->tcpm_dstport ^ tcp->source)); nb = nb->tcpm_next,shl++) ; - - } else { - - for (nb = tcp_first,shl = 0; nb != NULL && shl < secure && - ((nb->tcpm_srcadr ^ ip->saddr) || - (nb->tcpm_dstadr ^ ip->daddr) || - (nb->tcpm_srcport ^ tcp->source) || - (nb->tcpm_dstport ^ tcp->dest)); nb = nb->tcpm_next,shl++) ; - } - - if(shl >= secure) { - - printk(KERN_WARNING "ip_isdn_tcp_keepalive: search deadloop\n"); - deadloop = 1; - } - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) { - - printk(KERN_DEBUG - "isdn_keepalive found tcp_merk 0x%08lX %d %d/%d\n", - (long) nb, - tcp->doff, - tcp_hdr_len, - tcp_data_len); - - printk(KERN_DEBUG - "isdn_keepalive syn %d ack %d fin %d rst %d psh %d urg %d\n", - tcp->syn, - tcp->ack, - tcp->fin, - tcp->rst, - tcp->psh, - tcp->urg); - } -#endif - if (nb == NULL) { - - if (!ndev || !tcp->ack || tcp->fin || tcp->rst || tcp->syn || tcp->urg) { - - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) - printk(KERN_DEBUG "isdn_keepalive flags ausgang\n"); -#endif - return (0); - } - - if ((nb = get_free_tm()) == NULL) { - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) - printk(KERN_DEBUG "isdn_keepalive get_free_tm == NULL\n"); -#endif - - return (0); - } - - nb->tcpm_srcadr = ip->saddr; - nb->tcpm_dstadr = ip->daddr; - nb->tcpm_srcport = tcp->source; - nb->tcpm_dstport = tcp->dest; - nb->tcpm_acknr = tcp->ack_seq; - nb->tcpm_window = tcp->window; - nb->tcpm_time = jiffies; - nb->tcpm_seqnr = ntohl(tcp->seq) + tcp_data_len; - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) { - - printk(KERN_DEBUG - "isdn_keepalive put new %s:%hu->%s:%hu ack %lu oseq %lu len %d nseq %lu\n", - ipnr2buf(ip->saddr), - ntohs(tcp->source), - ipnr2buf(ip->daddr), - ntohs(tcp->dest), - ntohl(tcp->ack_seq), - ntohl(tcp->seq), - tcp_data_len, - nb->tcpm_seqnr); - } -#endif - return (0); - } - - if(ndev == NULL) { - - /* - ** we receive a frame from the peer - ** in most case the local-side will respond with a frame - ** if the respons-frame is a keealive-response - ** then we cannot local answer (peer will drop the connection) - ** so we update only the time-step - */ - - nb->tcpm_time = jiffies; - return(0); - } - - if (!tcp->ack || tcp->fin || tcp->rst || tcp->urg) { - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) - printk(KERN_DEBUG - "isdn_keepalive received || flags != 0 || ack == 0\n"); -#endif - - free_tcpm(nb); - return (0); - } - - tcp_seqnr = ntohl(tcp->seq); - - if (!tcp->psh && - tcp_data_len < 2 && - nb->tcpm_acknr == tcp->ack_seq && - nb->tcpm_window == tcp->window ) { - - if (nb->tcpm_seqnr == tcp_seqnr || (nb->tcpm_seqnr - 1) == tcp_seqnr) { - - /* - * so, das ist schon ein fast ein sicherer - * keepalive-request. - * aber es koennte immer noch ein retransmit sein - */ - - if (nb->tcpm_time < jiffies && - (jiffies - nb->tcpm_time) >= ((u_long) 50 * HZ)) { - - struct sk_buff *nskb; - int need; - int hlen; - - /* - * ok jetzt eine antwort generieren - */ - - need = sizeof(struct iphdr) + sizeof(struct tcphdr); - - hlen = ndev->hard_header_len; - hlen = (hlen + 15) & ~15; - nskb = dev_alloc_skb(need + hlen); - - if (nskb != NULL) { - - struct tcphdr *ntcp; - struct iphdr *iph = (struct iphdr *) ((u_char *) skb->data); - - struct PSH *psh; - - skb_reserve(nskb, hlen); - iph = (struct iphdr *) skb_put(nskb, sizeof(*iph)); - ntcp = (struct tcphdr *) skb_put(nskb, sizeof(*ntcp)); - - if(dev->net_verbose > 0) - printk(KERN_DEBUG "isdn_keepalive send response %s->%s %d->%d\n", - ipnr2buf(ip->daddr), - ipnr2buf(ip->saddr), - ntohs(tcp->dest), - ntohs(tcp->source)); - - memset((void *) ntcp, 0, sizeof(*ntcp)); - psh = (struct PSH *) (((u_char *) ntcp) - sizeof(*psh)); - psh->saddr = ip->daddr; - psh->daddr = ip->saddr; - psh->zp[0] = 0; - psh->zp[1] = 6; - psh->len = htons(sizeof(*tcp)); - - ntcp->source = tcp->dest; - ntcp->dest = tcp->source; - ntcp->seq = tcp->ack_seq; - ntcp->ack_seq = htonl(tcp_seqnr + tcp_data_len); - ntcp->window = tcp->window; - ntcp->doff = sizeof(*tcp) >> 2; - ntcp->check = 0; - ntcp->urg_ptr = 0; - ntcp->ack = 1; - ntcp->check = ip_compute_csum((void *) psh, 32); - memset(iph, 0, sizeof(*iph)); - iph->version = 4; - iph->ihl = 5; - iph->tos = ip->tos; - iph->tot_len = htons(sizeof(*iph) + sizeof(*ntcp)); - iph->id = (u_short) (jiffies & 0xFFFF); - iph->frag_off = 0; - iph->ttl = IPDEFTTL; - iph->protocol = ip->protocol; - iph->daddr = ip->saddr; - iph->saddr = ip->daddr; - iph->check = ip_compute_csum((void *) iph, sizeof(*iph)); - nskb->dev = ndev; - nskb->mac.raw = nskb->data; - nskb->protocol = htons(ETH_P_IP); - nskb->pkt_type = PACKET_HOST; - netif_rx(nskb); - retw = 1; - - } else { - - printk(KERN_DEBUG - "isdn_keepalive no space for new skb\n"); - } - - } else { - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) { - - printk(KERN_DEBUG - "isdn_keepalive jiffies %lu %lu\n", - jiffies, nb->tcpm_time); - } -#endif - } - - } else { - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) { - - printk(KERN_DEBUG - "isdn_keepalive no keep nb->tcpm_seqnr %lu tcp->seqnr %lu dlen %d nb->ack %lu tcp->ack %lu nm->window %d tcp->window %d\n", - nb->tcpm_seqnr, - tcp_seqnr, - tcp_data_len, - ntohl(nb->tcpm_acknr), - ntohl(tcp->ack_seq), - ntohs(nb->tcpm_window), - ntohs(tcp->window)); - } -#endif - } - - } else { - -#ifdef KEEPALIVE_VERBOSE - if (VERBLEVEL) { - - printk(KERN_DEBUG - "isdn_keepalive datenlen %d ack==seq %d win==win %d\n", - tcp_data_len, - nb->tcpm_acknr == tcp->ack_seq, - nb->tcpm_window == tcp->window); - } -#endif - } - - nb->tcpm_seqnr = tcp_seqnr + tcp_data_len; - nb->tcpm_acknr = tcp->ack_seq; - nb->tcpm_window = tcp->window; - nb->tcpm_time = jiffies; - - if (nb->tcpm_prev != NULL) { - - nb->tcpm_prev->tcpm_next = nb->tcpm_next; - - if (nb->tcpm_next != NULL) - nb->tcpm_next->tcpm_prev = nb->tcpm_prev; - else - tcp_last = nb->tcpm_prev; - - if ((nb->tcpm_next = tcp_first) != NULL) - nb->tcpm_next->tcpm_prev = nb; - else - tcp_last = nb; - - tcp_first = nb; - nb->tcpm_prev = NULL; - } - - return (retw); -} - -static void isdn_tcp_keepalive_init(void) -{ - TKAL_LOCK; - tcp_first = NULL; - tcp_last = NULL; - tcp_free = NULL; - next_police = 0; - last_police = 0; - deadloop = 0; - memset(MMA,0,sizeof(MMA)); - TKAL_ULOCK; -} - -static void isdn_tcp_keepalive_done(void) -{ - int shl; - - TKAL_LOCK; - tcp_first = NULL; - tcp_last = NULL; - tcp_free = NULL; - next_police = 0; - last_police = 0; - for (shl = 0; shl < MAX_MMA && MMA[shl] != NULL; shl++) kfree(MMA[shl]); - memset(MMA,0,sizeof(MMA)); - TKAL_ULOCK; -} -#endif - -#if CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE || CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR -struct sk_buff *isdn_dw_abc_ip4_keepalive_test(struct net_device *ndev,struct sk_buff *skb) -{ - int rklen; - struct iphdr *ip; - isdn_net_local *lp = NULL; - - if(ndev == NULL) { -#ifndef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - return(skb); -#endif - } else lp = (isdn_net_local *)ndev->priv; - - if (skb == NULL) - return(skb); - - if(ntohs(skb->protocol) != ETH_P_IP) { - -#ifdef KEEPALIVE_VERBOSE - if(VERBLEVEL) - printk(KERN_WARNING "ip_isdn_keepalive: protocol != ETH_P_IP\n"); -#endif - return(skb); - } - - rklen = skb->len; - ip = (struct iphdr *)skb->data; - - if (skb->nh.raw > skb->data && skb->nh.raw < skb->tail) { - - rklen -= (char *)skb->nh.raw - (char *)skb->data; - ip = (struct iphdr *)skb->nh.raw; - } - - if (rklen < sizeof(struct iphdr)) { -#ifdef KEEPALIVE_VERBOSE - if(VERBLEVEL) - printk(KERN_WARNING "ip_isdn_keepalive: len %d < iphdr\n", - rklen); -#endif - return (skb); - } - - rklen -= sizeof(struct iphdr); - - if(ip->version != 4 ) { -#ifdef KEEPALIVE_VERBOSE - if(VERBLEVEL) - printk(KERN_WARNING - "ip_isdn_keepalive: ipversion %d != 4\n", - ip->version); -#endif - return(skb); - } - -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR - - if(ndev != NULL && ndev->ip_ptr != NULL && (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_DYNADDR)) { - - struct in_device *indev = (struct in_device *)ndev->ip_ptr; - struct in_ifaddr *ifaddr = NULL; - - if((ifaddr = indev->ifa_list) != NULL) { - - ulong ipaddr = ifaddr->ifa_local; - -#ifdef DYNADDR_VERBOSE - if(VERBLEVEL) - printk(KERN_DEBUG - "isdn_dynaddr: %s syncpp %d %s->%s %s\n", - lp->name, - lp->p_encap == ISDN_NET_ENCAP_SYNCPPP, - ipnr2buf(ip->saddr), - ipnr2buf(ip->daddr), - ipnr2buf(ipaddr)); -#endif - if((ip->saddr ^ ipaddr)) { -#if CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR || CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR - - struct sock *sk = skb->sk; - struct tcphdr *tcp; - struct udphdr *udp; - char *drpmsg = "isdn_dynaddr drop"; - char isudp = ip->protocol == IPPROTO_UDP; - struct sk_buff *newskb = NULL; - - if(isudp) { -#ifndef CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR - isdn_net_log_skb_dwabc(skb,lp,drpmsg); - return(NULL); -#else - if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_RWUDP_SOCKADDR) || - (rklen < sizeof(*udp))) { - - isdn_net_log_skb_dwabc(skb,lp,drpmsg); - return(NULL); - } -#endif - } else { -#ifndef CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR - isdn_net_log_skb_dwabc(skb,lp,drpmsg); - return(NULL); -#else - if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_RW_SOCKADDR) || - (rklen < sizeof(*tcp))) { - - isdn_net_log_skb_dwabc(skb,lp,drpmsg); - return(NULL); - } -#endif - } - - if( sk == NULL || - sk->prot == NULL || - sk->prot->unhash == NULL || - sk->prot->hash == NULL ) { - - isdn_net_log_skb_dwabc(skb,lp,drpmsg); - return(NULL); - } - - if(sk->saddr != ipaddr && sk->saddr != 0) { - - ulong flags; - - if(dev->net_verbose > 0) { - - printk(KERN_DEBUG - "%s rewriting %s-socket->saddr %s->%s:%hu->%s:%hu rcv_saddr %s\n", - lp->name, - (isudp) ? "UDP" : "TCP", - ipnr2buf(sk->saddr), - ipnr2buf(ipaddr), - sk->num, - ipnr2buf(sk->daddr), - ntohs(sk->dport), - ipnr2buf(sk->rcv_saddr)); - } - - save_flags(flags); - cli(); - sk->saddr = ipaddr; - sk->rcv_saddr = ipaddr; - sk->prot->unhash(sk); - sk->prot->hash(sk); - restore_flags(flags); - } - - if((newskb = skb_copy(skb,GFP_ATOMIC)) == NULL) { - - printk(KERN_DEBUG - "%s dynaddr-rewrite-frame skb_copy failed\n", - lp->name); - - } else { - - skb = newskb; - ip = (struct iphdr *)skb->data; - - if (skb->nh.raw > skb->data && skb->nh.raw < skb->tail) - ip = (struct iphdr *)skb->nh.raw; - - tcp = (struct tcphdr *) (((u_char *) ip) + (ip->ihl << 2)); - udp = (struct udphdr *)tcp; - - if(dev->net_verbose > 1) { - - printk(KERN_DEBUG - "%s rewriting %s-frame->saddr %s->%s:%hu->%s:%hu\n", - lp->name, - (isudp) ? "UDP" : "TCP", - ipnr2buf(ip->saddr), - ipnr2buf(ipaddr), - (isudp) ? ntohs(udp->source) : ntohs(tcp->source), - ipnr2buf(ip->daddr), - (isudp) ? ntohs(udp->source) : ntohs(tcp->dest)); - } - - { - struct PSH XXSTORE; - struct PSH *psh; - u_char p = ip->protocol; - ushort l = ntohs(ip->tot_len) - (ip->ihl << 2); - ulong da = ip->daddr; - - psh = (struct PSH *) (((u_char *) tcp) - sizeof(*psh)); - memcpy(&XXSTORE,psh,sizeof(*psh)); - memset(psh,0,sizeof(*psh)); - psh->daddr = da; - psh->saddr = ipaddr; - psh->zp[1] = p; - psh->len = htons(l); - - if(isudp) { - udp->check = 0; - udp->check = ip_compute_csum((void *) psh,l+sizeof(*psh)); - } else { - tcp->check = 0; - tcp->check = ip_compute_csum((void *) psh,l+sizeof(*psh)); - } - - memcpy(psh,&XXSTORE,sizeof(*psh)); - } - - ip->check = 0; - ip->saddr = ipaddr; - ip->check = ip_fast_csum((unsigned char *)ip,ip->ihl); - return(skb); - } -#else - isdn_net_log_skb_dwabc(skb,lp,"isdn_dynaddr drop"); - return(NULL); -#endif - } - } - } -#endif - -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - if(lp != NULL && (lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_TCP_KEEPALIVE)) - return(skb); - - if (rklen < sizeof(struct tcphdr)) { -#ifdef KEEPALIVE_VERBOSE - if(VERBLEVEL) - printk(KERN_WARNING "ip_isdn_keepalive: len %d < \n",skb->len); -#endif - return (skb); - } - - if(ip->protocol != IPPROTO_TCP) { -#ifdef KEEPALIVE_VERBOSE - if(VERBLEVEL) - printk(KERN_WARNING - "ip_isdn_keepalive: ip->proto %d != IPPROTO_TCP\n", - ip->protocol); -#endif - return(skb); - } - - if(deadloop) { - - if(deadloop < 10) { - printk(KERN_WARNING "ip_isdn_keepalive: sorry deadloop detected\n"); - deadloop++; - } - - return(skb); - } - - { - int retw = 0; - TKAL_LOCK; - retw = isdn_tcpipv4_test(ndev,ip,skb); - TKAL_ULOCK; - - return(retw ? NULL : skb); - } -#else - return(skb); -#endif -} -#endif - -void isdn_dw_abc_init_func(void) -{ - -#ifdef COMPAT_HAS_NEW_WAITQ -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - init_MUTEX(&lcr_sema); -#endif -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - init_MUTEX(&ipv4keep_sema); -#endif -#else -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - lcr_sema = MUTEX; -#endif -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - ipv4keep_sema = MUTEX; -#endif -#endif - -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - lcr_open_count = 0; -#endif - -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - isdn_tcp_keepalive_init(); -#endif - - init_timer(&dw_abc_timer); - dw_abc_timer.function = dw_abc_timer_func; - - printk( KERN_INFO - "abc-extension %s\n" - "written by\nDetlef Wengorz \n" - "Thanks for test's etc. to:\n" - "Mario Schugowski \n" - "For more details see http://i4l.mediatronix.de\n" - "Installed options:\n" -#ifdef CONFIG_ISDN_WITH_ABC_CALLB - "CONFIG_ISDN_WITH_ABC_CALLB\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK - "CONFIG_ISDN_WITH_ABC_UDP_CHECK\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP - "CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL - "CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ - "CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_LCR_SUPPORT - "CONFIG_ISDN_WITH_ABC_LCR_SUPPORT\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - "CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR - "CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR\n" -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR - "CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR\n" -#endif -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR - "CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR\n" -#endif -#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 -#ifdef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT - "CONFIG_ISDN_WITH_ABC_FRAME_LIMIT\n" -#endif - "loaded\n", - dwabcrevison); - - 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 -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - isdn_tcp_keepalive_done(); -#endif - printk( KERN_INFO - "abc-extension %s\n" - "written by\n" - "Detlef Wengorz \n" - "Thanks for test's etc. to:\n" - "Mario Schugowski \n" - "unloaded\n" - "For more details see http://i4l.mediatronix.de\n", - dwabcrevison); -} - - -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 'k': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_NO_TCP_KEEPALIVE; break; - 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 'D': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_DYNADDR; break; - case 'T': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_RW_SOCKADDR; break; - case 'U': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_RWUDP_SOCKADDR; break; - case 'B': lp->dw_abc_flags |= ISDN_DW_ABC_FLAG_BSD_COMPRESS; break; - - case '"': - case ' ': - case '\t': - case '\'': break; - - default: - printk(KERN_DEBUG"isdn_net: %s abc-switch <~%c> unknown\n",lp->name,*p); - break; - } - } - } - - 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); - - } -} - - -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND -void isdn_dw_abc_free_lch_with_pch(int di,int ch) -{ - if(di >= 0 && di < ISDN_MAX_DRIVERS && ch >= 0) { - - driver *d = dev->drv[di]; - - if(d != NULL) { - - u_char *p = d->dwabc_lchmap; - u_char *ep = d->dwabc_lchmap + ISDN_DW_ABC_MAX_CH_P_RIVER; - ch++; - - for(;p < ep;p++) { - - if(*p == ch) - *p = 0; - } - } - } -} - - - -static void dwabc_check_lchmap(void) -{ - if(dev->dwabc_lch_check > jiffies || (dev->dwabc_lch_check + HZ) < jiffies) { - int i; - dev->dwabc_lch_check = jiffies; - - for(i = 0; i < ISDN_MAX_CHANNELS; i++) { - - int di = dev->drvmap[i]; - driver *p; - - if(di < 0 || di >= ISDN_MAX_DRIVERS) - continue; - - if((p = dev->drv[di]) == NULL) - continue; - - if(p->dwabc_lch_use < jiffies && (p->dwabc_lch_use + HZ) < jiffies) - continue; - - if(USG_NONE(dev->usage[i])) - isdn_dw_abc_free_lch_with_pch(di,dev->chanmap[i]); - } - } -} - - -static int get_driverid(isdn_net_local *lp,char *name,char *ename,ulong *bits) -{ - int retw = -1; - - if(name != NULL && lp != NULL) { - - int i = 0; - char *p; - - for(;name < ename && *name && *name <= ' ' ; name++); - for(p = name;p < ename && *p && *p != ',';p++); - - for (i = 0; i < ISDN_MAX_DRIVERS; i++) { - - char *s = name; - char *d = dev->drvid[i]; - - for(;s < p && *s == *d && *s;s++,d++); - - if(!*d && s >= p) - break; - } - - if(i >= ISDN_MAX_DRIVERS) { - - printk(KERN_DEBUG "isdn_dwabc_bind %s interface %s not found\n", - lp->name,name); - - } else { - - retw = i; - - if(bits != NULL) { - - char buf[16]; - char *d = buf; - char *ed = buf + sizeof(buf) - 1; - - *bits = ~0L; - - for(;p < ename && *p == ',';p++); - - while(p < ename && *p && d < ed) - *(d++) = *(p++); - - *d = 0; - - if(*buf) - *bits = (ulong)simple_strtoul(buf,&d,0); - } - } - } - - return(retw); -} - - -int isdn_dwabc_check_icall_bind(isdn_net_local *lp,int di,int ch) -{ - int ret = 0; - short isset = 0; - - dwabc_check_lchmap(); - - if(di < 0 || di >= ISDN_MAX_DRIVERS) - return(0); - - if(lp != NULL && lp->pre_device < 0 && lp->pre_channel < 0 && - di >= 0 && di < ISDN_MAX_DRIVERS) { - - isdn_net_phone *h = lp->phone[0]; - int secure = 0; - short sd = 0; - - for(;h != NULL && secure < 1000;secure++,h = h->next) { - - char *p = h->num; - char *ep = p + ISDN_MSNLEN; - ulong bits = 0; - - for(;p < ep && *p && (*p <= ' ' || *p == '"' || *p == '\'');p++); - - if(p >= (ep-1) || *p != '>') - continue; - - if(*(++p) != '<') - continue; - - ret = -1; - p++; - sd = 0; - - if(p < ep && (*p == '<' || *p == '>')) { - - sd = (*p == '<'); - p++; - } - - if(get_driverid(lp,p,ep,&bits) == di) { - - driver *dri = dev->drv[di]; - - if(dri != NULL) { - - int shl = 0; - - if(sd) for(shl = dri->channels - 1; - ret != 0 && shl >= 0; shl--) { - - if(shl >= ISDN_DW_ABC_MAX_CH_P_RIVER) - continue; - - if(bits & (1L << shl)) { - - if(!dri->dwabc_lchmap[shl]) { - - dri->dwabc_lchmap[shl] = ch + 1; - dri->dwabc_lch_use = jiffies; - isset = 1; - ret = 0; - } - } - - } else for(shl = 0; - ret != 0 && shl < ISDN_DW_ABC_MAX_CH_P_RIVER && - shl < dri->channels ;shl++) { - - if(bits & (1L << shl)) { - - if(!dri->dwabc_lchmap[shl]) { - - dri->dwabc_lchmap[shl] = ch + 1; - dri->dwabc_lch_use = jiffies; - isset = 1; - ret = 0; - } - } - } - - if(!ret) - break; - } - } - } - - if(ret) { - - printk(KERN_DEBUG "isdn_dwabc_ibind: %s IN-CALL driver %d ch %d %s\n", - lp->name, - di, - ch, - "not allowed for this interface and channel"); - } - } - - if(!ret && !isset && ch >= 0) { - - driver *dri = dev->drv[di]; - - if(dri != NULL) { - - int shl; - - for(shl = 0; shl < ISDN_DW_ABC_MAX_CH_P_RIVER && shl < dri->channels;shl++) { - - if(!dri->dwabc_lchmap[shl]) { - - dri->dwabc_lchmap[shl] = ch + 1; - dri->dwabc_lch_use = jiffies; - break; - } - } - } - } - - return(ret); -} - -int dwabc_isdn_get_net_free_channel(isdn_net_local *lp) -{ - int retw = -1; - int isconf = 0; - - if(lp != NULL) { -#ifdef CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ - char *now_msn = (*lp->dw_out_msn) ? lp->dw_out_msn : lp->msn; -#else - char *now_msn = lp->msn; -#endif - - if(lp->pre_device < 0 && lp->pre_channel < 0) { - - isdn_net_phone *h = lp->phone[0]; - int secure = 0; - dwabc_check_lchmap(); - - for(;retw < 0 && h != NULL && secure < 1000;secure++,h = h->next) { - - char *p = h->num; - char *ep = p + ISDN_MSNLEN; - int di = 0; - int shl = 0; - ulong bits = 0; - short down = 0; - driver *dri = NULL; - - for(;p < ep && *p && (*p <= ' ' || *p == '"' || *p == '\'');p++); - - if(p >= (ep-1) || *p != '>') continue; - if(*(++p) != '>') continue; - - isconf = 1; - p++; - - if(p < ep && (*p == '<' || *p == '>')) { - - down = *p == '<'; - p++; - } - - if((di = get_driverid(lp,p,ep,&bits)) < 0 || di >= ISDN_MAX_DRIVERS) - continue; - - if((dri = dev->drv[di]) == NULL) - continue; - - if(down) for(shl = dri->channels -1 ; shl >= 0 && retw < 0; shl--) { - - if(shl >= ISDN_DW_ABC_MAX_CH_P_RIVER) - continue; - - if(bits & (1L << shl)) { - - if(dri->dwabc_lchmap[shl]) - continue; - - if(isdn_dc2minor(di,shl) < 0) - continue; - - if((retw = isdn_get_free_channel( - ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - di, - 9999, - now_msn - )) >= 0) { - - int c = dev->chanmap[retw]; - - if(c >= 0) { - - dri->dwabc_lchmap[shl] = c + 1; - dri->dwabc_lch_use = jiffies; - } - } - } - - } else for(shl = 0; shl < ISDN_DW_ABC_MAX_CH_P_RIVER && - retw < 0 && shl < dri->channels; shl++) { - - if(bits & (1L << shl)) { - - if(dri->dwabc_lchmap[shl]) - continue; - - if(isdn_dc2minor(di,shl) < 0) - break; - - if((retw = isdn_get_free_channel( - ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - di, - 9999, - now_msn)) >= 0) { - - int c = dev->chanmap[retw]; - - if(c >= 0) { - - dri->dwabc_lchmap[shl] = c + 1; - dri->dwabc_lch_use = jiffies; - } - } - } - } - } - } - - if(!isconf) { - - retw = isdn_get_free_channel( - ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel, - now_msn); - - if(retw >= 0) { - - int di = dev->drvmap[retw]; - int ch = dev->chanmap[retw]; - - if(di >= 0 && di < ISDN_MAX_DRIVERS && ch >= 0) { - - driver *dri = dev->drv[di]; - - if(dri != NULL) { - - int i; - - for(i = 0; i < dri->channels && i < ISDN_DW_ABC_MAX_CH_P_RIVER;i++) { - - if(!dri->dwabc_lchmap[i]) { - - dri->dwabc_lchmap[i] = ch + 1; - dri->dwabc_lch_use = jiffies; - break; - } - } - } - } - } - - } else if(retw < 0 && lp != NULL) { - - printk(KERN_INFO "%s: No free locical Channel found\n",lp->name); - } - - } else { - - printk(KERN_WARNING - "dwabc_isdn_get_net_free_channel called with *lp == NULL\n"); - } - - return(retw); -} -#endif - -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(lp->dw_abc_next_skb != NULL) - dev_kfree_skb(lp->dw_abc_next_skb); - - lp->dw_abc_next_skb = NULL; - lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_RSTREMOTE; - - 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; - lp->dw_abc_next_skb = 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; - atomic_set(&lp->dw_abc_pkt_onl,0); - - if(lp->dw_abc_next_skb) { - - dev_kfree_skb(lp->dw_abc_next_skb); - lp->dw_abc_next_skb = NULL; - } - } -} - - -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) { - - if(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_BSD_COMPRESS) { - - ulong flags = 0; - struct isdn_ppp_compressor *c = ipc_head; - - save_flags(flags); - cli(); - for(;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); - r = -1; - - } else { - - void *rx = NULL; - void *tx = NULL; - struct isdn_ppp_comp_data *cp = &BSD_COMP_INIT_DATA; - - 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); - r = -1; - - } else if(!(*c->init)(rx,cp,0,1)) { - - printk(KERN_INFO "%s: init of bsd rx-stream failed\n",lp->name); - (*c->free)(rx); - rx = NULL; - } - - if(rx != NULL) { - - 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); - r = -1; - - } else if(!(*c->init)(tx,cp,0,1)) { - - printk(KERN_INFO "%s: init of bsd tx-stream failed\n",lp->name); - (*c->free)(tx); - tx = NULL; - } - } - - if(tx != NULL) { - - lp->dw_abc_bsd_compressor = (void *)c; - lp->dw_abc_bsd_stat_rx = rx; - lp->dw_abc_bsd_stat_tx = tx; - r = 0; - - if(dev->net_verbose > 2) - printk(KERN_INFO "%s: bsd compress-memory and init ok\n",lp->name); - } - } - - restore_flags(flags); - } - - } 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 witk 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; - 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); - kfree_skb(skb); - lp->dw_abc_if_flags |= ISDN_DW_ABC_IFFLAG_RSTREMOTE; - 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; - lp->dw_abc_if_flags |= ISDN_DW_ABC_IFFLAG_RSTREMOTE; - - } 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); - lp->dw_abc_if_flags |= ISDN_DW_ABC_IFFLAG_RSTREMOTE; - } - - clear_bit(ISDN_DW_ABC_BITLOCK_RECEIVE,&lp->dw_abc_bitlocks); - r = nskb; - } - } - - return(r); -} - -#else -int dwabc_bsd_init(isdn_net_local *lp) { return(1); } -void dwabc_bsd_free(isdn_net_local *lp) { return; } -void dwabc_bsd_first_gen(isdn_net_local *lp) { return ; } - -struct sk_buff *dwabc_bsd_compress(isdn_net_local *lp,struct sk_buff *skb,struct net_device *ndev) -{ return(skb); } - -struct sk_buff *dwabc_bsd_rx_pkt(isdn_net_local *lp,struct sk_buff *skb,struct net_device *ndev) -{ return(skb); } -#endif -#endif diff --git a/drivers/isdn/isdn_net.c b/drivers/isdn/isdn_net.c deleted file mode 100644 index 4ea19656..00000000 --- a/drivers/isdn/isdn_net.c +++ /dev/null @@ -1,4175 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, network interfaces and related functions (linklevel). - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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. - * - * $Log$ - * Revision 1.111 2000/02/28 22:28:24 he - * moved tx_timeout warning messages in old (2.2.x) branch where it really only - * indicates problems. - * - * Revision 1.110 2000/02/26 01:00:53 keil - * changes from 2.3.47 - * - * Revision 1.109 2000/02/25 11:29:17 paul - * changed chargetime to ulong from int (after about 20 days the "chargetime of - * ipppX is now 1234" message displays a negative number on alpha). - * - * Revision 1.108 2000/02/15 12:54:01 kai - * set TX timeout back to 2 secs for 2.2.x, just to be safe - * - * Revision 1.107 2000/02/13 09:52:05 kai - * increased TX_TIMEOUT to 20sec - * - * Revision 1.106 2000/02/12 19:26:55 kai - * adopted to latest 2.3 softnet changes. - * - * tested with PPP and MPPP, it works here. - * can somebody check raw-ip? - * - * also changed std2kern, stddiff for bash-1 compatibility, - * hope this doesn't break anything. - * - * Revision 1.105 2000/02/12 11:43:26 he - * SOFTNET related changes, first try. Compatible with linux 2.2.x, but - * not tested for kernels with softnet (>= 2.3.43) yet. - * - * Revision 1.104 2000/02/06 21:49:59 detabc - * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections. - * Include checksum-recompute of ip- and udp-header's. - * - * Revision 1.103 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.102 2000/01/09 20:43:14 detabc - * exand logical bind-group's for both call's (in and out). - * add first part of kernel-config-help for abc-extension. - * - * Revision 1.101 1999/12/05 16:06:08 detabc - * add resethandling for rawip-compression. - * at now all B2-Protocols are usable with rawip-compression - * - * Revision 1.100 1999/12/04 15:05:25 detabc - * bugfix abc-rawip-bsdcompress with channel-bundeling - * - * Revision 1.99 1999/11/30 11:29:06 detabc - * add a on the fly frame-counter and limit - * - * Revision 1.98 1999/11/28 14:49:07 detabc - * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the - * uncompressed size. - * - * Revision 1.97 1999/11/26 15:54:59 detabc - * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol. - * - * Revision 1.96 1999/11/20 22:14:13 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.95 1999/10/27 21:21:17 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.94 1999/10/02 11:07:02 he - * Changed tbusy logic in indn_net.c - * - * Revision 1.93 1999/09/23 22:22:41 detabc - * added tcp-keepalive-detect with local response (ipv4 only) - * added host-only-interface support - * (source ipaddr == interface ipaddr) (ipv4 only) - * ok with kernel 2.3.18 and 2.2.12 - * - * Revision 1.92 1999/09/13 23:25:17 he - * serialized xmitting frames from isdn_ppp and BSENT statcallb - * - * Revision 1.91 1999/09/12 16:19:39 detabc - * added abc features - * low cost routing for net-interfaces (only the HL side). - * need more implementation in the isdnlog-utility - * udp info support (first part). - * different EAZ on outgoing call's. - * more checks on D-Channel callbacks (double use of channels). - * tested and running with kernel 2.3.17 - * - * Revision 1.90 1999/09/04 22:21:39 detabc - * - * Revision 1.89 1999/08/22 20:26:03 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.88 1999/07/07 10:13:31 detabc - * remove unused messages - * - * Revision 1.87 1999/07/06 07:53:53 calle - * calls to dev_alloc_skb waste 16 bytes of memory, if we calculate the - * right header space for the lowlevel driver. using alloc_skb instead. - * - * Revision 1.86 1999/06/09 10:12:05 paul - * thinko in previous patch - * - * Revision 1.85 1999/06/07 19:42:39 paul - * isdn_net_getpeer() fixed to return correct `outgoing' flag - * - * Revision 1.84 1999/04/18 14:06:55 fritz - * Removed TIMRU stuff. - * - * Revision 1.83 1999/04/12 12:33:23 fritz - * Changes from 2.0 tree. - * - * Revision 1.82 1999/01/17 00:55:58 he - * added mark_bh in BCONN statcallb and cleaned up some dead code - * - * Revision 1.81 1999/01/15 16:36:52 he - * replaced icmp_send() by dst_link_failure() - * - * Revision 1.80 1998/12/01 13:06:22 paul - * Also huptimeout with dialmode == manual - * - * Revision 1.79 1998/10/30 17:55:27 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.78 1998/10/26 18:20:46 he - * re-inserted p=p->next in isdn_net_find_icall() (fixes kernel lock up - * on incoming call not matching the first interface) - * - * Revision 1.77 1998/10/23 10:18:44 paul - * Implementation of "dialmode" (successor of "status") - * You also need current isdnctrl for this! - * - * Revision 1.76 1998/09/07 22:00:05 he - * flush method for 2.1.118 and above - * updated IIOCTLNETGPN - * - * Revision 1.75 1998/08/31 21:09:50 he - * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' - * peer phone number) - * - * Revision 1.74 1998/07/30 11:28:32 paul - * printk message only appeared when status is off and interface is rawIP, - * which is confusing for people who don't know about "isdnctrl status on". - * - * Revision 1.73 1998/06/26 22:01:37 keil - * tx_queue_len = 5 was too small - * - * Revision 1.72 1998/06/26 15:12:31 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.71 1998/06/18 22:43:08 fritz - * Bugfix: Setting ndev->do_ioctl had beed accidetly removed at cleanup. - * - * Revision 1.70 1998/06/17 19:50:49 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.69 1998/06/09 12:27:37 cal - * Changed default of local netdev flags: ISDN_NET_STOPPED is default now, - * so autodial is suppressed for that device until it is switched on using - * 'isdnctrl status dev-name on'. - * - * - * - * Revision 1.66 1998/05/26 22:39:24 he - * sync'ed with 2.1.102 where appropriate (CAPABILITY changes) - * concap typo - * cleared dev.tbusy in isdn_net BCONN status callback - * - * Revision 1.61 1998/04/16 19:19:42 keil - * Fix from vger (tx max qlength) - * - * Revision 1.60 1998/04/14 16:28:49 he - * Fixed user space access with interrupts off and remaining - * copy_{to,from}_user() -> -EFAULT return codes - * - * Revision 1.59 1998/03/07 22:37:33 fritz - * Bugfix: restore_flags missing. - * - * Revision 1.58 1998/03/07 18:21:05 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.57 1998/02/25 18:31:13 fritz - * Added debugging output in adjust_header. - * - * Revision 1.56 1998/02/25 17:49:42 he - * Changed return codes caused be failing copy_{to,from}_user to -EFAULT - * - * Revision 1.55 1998/02/23 19:38:22 fritz - * Corrected check for modified feature-flags. - * - * Revision 1.54 1998/02/20 17:15:07 fritz - * Changes for recent kernels. - * Ugly workaround for adjusting Ethernet frames with recent kernels. - * replaced direct calls to lowlevel-driver command by common hook. - * - * Revision 1.53 1998/01/31 22:05:54 keil - * Lots of changes for X.25 support: - * Added generic support for connection-controlling encapsulation protocols - * Added support of BHUP status message - * Added support for additional p_encap X25IFACE - * Added support for kernels >= 2.1.72 - * - * Revision 1.52 1998/01/31 19:29:51 calle - * Merged changes from and for 2.1.82, not tested only compiled ... - * - * Revision 1.51 1997/10/09 21:28:50 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.50 1997/10/01 09:20:32 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.49 1997/08/21 14:38:13 fritz - * Bugfix: Did not compile without SyncPPP. - * - * Revision 1.48 1997/06/22 11:57:15 fritz - * Added ability to adjust slave triggerlevel. - * - * Revision 1.47 1997/06/21 10:52:05 fritz - * Removed wrong SET_SKB_FREE in isdn_net_send_skb() - * - * Revision 1.46 1997/06/17 13:05:24 hipp - * Applied Eric's underflow-patches (slightly modified) - * - * Revision 1.45 1997/06/10 16:24:22 hipp - * hard_header changes for syncPPP (now behaves like RAWIP) - * - * Revision 1.44 1997/05/27 15:17:26 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.43 1997/03/30 16:51:13 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.42 1997/03/11 08:43:51 fritz - * Perform a hangup if number is deleted while dialing. - * - * Revision 1.41 1997/03/08 08:16:31 fritz - * Bugfix: Deleting a phone number during dial gave unpredictable results. - * - * Revision 1.40 1997/03/05 21:16:08 fritz - * Fix: did not compile with 2.1.27 - * - * Revision 1.39 1997/03/04 21:36:52 fritz - * Added sending ICMP messages when no connetion is possible. - * - * Revision 1.38 1997/02/23 23:41:14 fritz - * Bugfix: Slave interfaces have to be hung up before master. - * - * Revision 1.37 1997/02/11 18:32:51 fritz - * Bugfix in isdn_ppp_free_mpqueue(). - * - * Revision 1.36 1997/02/10 21:31:11 fritz - * Changed setup-interface (incoming and outgoing). - * - * Revision 1.35 1997/02/10 20:12:45 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.34 1997/02/03 23:15:07 fritz - * Reformatted according CodingStyle. - * replaced arp_find prototype by proper include. - * made dev_purge_queues static. - * Bugfix in bogocps calculation. - * removed isdn_net_receive_callback - was never used ;-) - * Misc. fixes for Kernel 2.1.X comaptibility. - * - * Revision 1.33 1997/01/17 01:19:25 fritz - * Applied chargeint patch. - * - * Revision 1.32 1997/01/14 01:29:31 fritz - * Bugfix: isdn_net_hangup() did not reset ISDN_NET_CONNECTED. - * - * Revision 1.31 1997/01/11 23:30:42 fritz - * Speed up dial statemachine. - * - * Revision 1.30 1996/11/25 17:20:50 hipp - * fixed pppbind bug in isdn_net_find_icall() - * - * Revision 1.29 1996/11/13 02:31:38 fritz - * Minor cleanup. - * - * Revision 1.28 1996/10/27 20:49:06 keil - * bugfix to compile without MPP - * - * Revision 1.27 1996/10/25 18:46:01 fritz - * Another bugfix in isdn_net_autohup() - * - * Revision 1.26 1996/10/23 23:05:36 fritz - * Bugfix: Divide by zero in isdn_net_autohup() - * - * Revision 1.25 1996/10/22 23:13:58 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.24 1996/10/11 13:57:40 fritz - * Bugfix: Error in BogoCPS calculation. - * - * Revision 1.23 1996/09/23 01:58:08 fritz - * Fix: With syncPPP encapsulation, discard LCP packets - * when calculating hangup timeout. - * - * Revision 1.22 1996/09/23 00:03:37 fritz - * Fix: did not compile without CONFIG_ISDN_PPP - * - * Revision 1.21 1996/09/07 12:44:50 hipp - * (hopefully) fixed callback problem with syncPPP - * syncPPP network devices now show PPP link encap - * - * Revision 1.20 1996/08/29 20:06:03 fritz - * Bugfix: Transmission timeout had been much to low. - * - * Revision 1.19 1996/08/12 16:24:32 hipp - * removed some (now) obsolete functions for syncPPP in rebuild_header etc. - * - * Revision 1.18 1996/07/03 13:48:51 hipp - * bugfix: Call dev_purge_queues() only for master device - * - * Revision 1.17 1996/06/25 18:37:37 fritz - * Fixed return count for empty return string in isdn_net_getphones(). - * - * Revision 1.16 1996/06/24 17:48:08 fritz - * Bugfixes: - * - Did not free channel on unbinding. - * - ioctl returned wrong callback settings. - * - * Revision 1.15 1996/06/16 17:42:54 tsbogend - * fixed problem with IP addresses on Linux/Alpha (long is 8 byte there) - * - * Revision 1.14 1996/06/11 14:54:08 hipp - * minor bugfix in isdn_net_send_skb - * changes in BSENT callback handler for syncPPP - * added lp->sav_skb stuff - * - * Revision 1.13 1996/06/06 14:25:44 fritz - * Changed loglevel of "incoming ... without OAD" message, since - * with audio support this is quite normal. - * - * Revision 1.12 1996/06/05 02:36:45 fritz - * Minor bugfixes by M. Hipp. - * - * Revision 1.11 1996/05/18 01:36:59 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.10 1996/05/17 03:49:01 fritz - * Some cleanup. - * - * Revision 1.9 1996/05/06 11:34:57 hipp - * fixed a few bugs - * - * Revision 1.8 1996/04/30 21:04:40 fritz - * Test commit - * - * Revision 1.7 1996/04/30 11:10:42 fritz - * Added Michael's ippp-bind patch. - * - * Revision 1.6 1996/04/30 09:34:35 fritz - * Removed compatibility-macros. - * - * Revision 1.5 1996/04/20 16:28:38 fritz - * Made more parameters of the dial statemachine user-configurable and - * added hangup after dial for more reliability using callback. - * Changed all io going through generic routines in isdn_common.c - * Added missing call to dev_free_skb on failed dialing. - * Added uihdlc encapsulation. - * Fixed isdn_net_setcfg not to destroy interface-flags anymore. - * Misc. typos. - * - * Revision 1.4 1996/02/19 15:23:38 fritz - * Bugfix: Sync-PPP packets got compressed twice, when resent due to - * send-queue-full reject. - * - * Revision 1.3 1996/02/11 02:22:28 fritz - * Changed status- receive-callbacks to use pointer-arrays for finding - * a corresponding interface instead of looping over all interfaces. - * Activate Auto-hangup-timer only when interface is online. - * Some bugfixes in the dialing-statemachine. - * Lot of bugfixes in sk_buff'ized encapsulation handling. - * For speedup connection-setup after dialing, remember sk_buf that triggered - * dialing. - * Fixed isdn_net_log_packet according to different encapsulations. - * Correct ARP-handling for ETHERNET-encapsulation. - * - * Revision 1.2 1996/01/22 05:05:12 fritz - * Changed returncode-logic for isdn_net_start_xmit() and its - * helper-functions. - * Changed handling of buildheader for RAWIP and ETHERNET-encapsulation. - * - * Revision 1.1 1996/01/09 04:12:34 fritz - * Initial revision - * - */ - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include -#include -#include "isdn_common.h" -#include "isdn_net.h" -#ifdef CONFIG_ISDN_PPP -#include "isdn_ppp.h" -#endif -#ifdef CONFIG_ISDN_X25 -#include -#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: - * - * Old method, roughly spoken, consisted of setting tbusy when entering - * isdn_net_start_xmit() and at several other locations and clearing - * it from isdn_net_start_xmit() thread when sending was successful. - * - * With 2.3.x multithreaded network core, to prevent problems, tbusy should - * only be set by the isdn_net_start_xmit() thread and only when a tx-busy - * condition is detected. Other threads (in particular isdn_net_stat_callb()) - * are only allowed to clear tbusy. - * - * -HE - */ - -/* - * About SOFTNET: - * Most of the changes were pretty obvious and basically done by HE already. - * - * One problem of the isdn net device code is that is uses struct net_device - * for masters and slaves. However, only master interface are registered to - * the network layer, and therefore, it only makes sense to call netif_* - * functions on them. - * - * The old code abused the slaves dev->start to remember the corresponding - * master's interface state (ifup'ed or not). This does not work with SOFTNET - * any more, because there's now dev->start anymore. - * Instead I chose to add isdn_net_started() which gives the state of the - * master in case of slaves. - * I'm still not sure if this is how it's supposed to be done this way - * because it uses netif_running(dev) which might be - * considered private to the network layer. However, it works for now. - * Alternative: set a flag in _open() and clear it in _close() - * - * I left some dead code around in #if 0 which I'm not absolutely sure about. - * If no problems turn up, it should be removed later - * - * --KG - */ - -/* - * Find out if the netdevice has been ifup-ed yet. - * For slaves, look at the corresponding master. - */ -static int __inline__ isdn_net_started(isdn_net_dev *n) -{ - isdn_net_local *lp = n->local; - struct net_device *dev; - - if (lp->master) - dev = lp->master; - else - dev = &n->dev; -#ifdef COMPAT_NO_SOFTNET - return dev->start; -#else - return netif_running(dev); -#endif -} - -/* - * wake up the network -> net_device queue. - * For slaves, wake the corresponding master interface. - */ -static void __inline__ isdn_net_lp_xon(isdn_net_local * lp) -{ - if (lp->master) - netif_wake_queue(lp->master); - else - netif_wake_queue(&lp->netdev->dev); -} - -/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just - * to be safe. - * For 2.3.x we push it up to 20 secs, because call establishment - * (in particular callback) may take such a long time, and we - * don't want confusing messages in the log. However, there is a slight - * possibility that this large timeout will break other things like MPPP, - * which might rely on the tx timeout. If so, we'll find out this way... - */ - -#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 int isdn_net_xmit(struct net_device *, isdn_net_local *, struct sk_buff *); - -char *isdn_net_revision = "$Revision$"; - - /* - * 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) -{ - 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) { - - u_short proto = ntohs(skb->protocol); - - printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n", - dev->name, - (reason != NULL) ? reason : "unknown", - (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : ""); - - dst_link_failure(skb); - } - else { /* dial not triggered by rawIP packet */ - printk(KERN_DEBUG "isdn_net: %s: %s\n", - dev->name, - (reason != NULL) ? reason : "reason unknown"); - } -} - -static void -isdn_net_reset(struct net_device *dev) -{ -#ifdef CONFIG_ISDN_X25 - struct concap_device_ops * dops = - ( (isdn_net_local *) dev->priv ) -> dops; - struct concap_proto * cprot = - ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; -#endif - ulong flags; - - /* not sure if the cli() is needed at all --KG */ - save_flags(flags); - cli(); /* Avoid glitch on writes to CMD regs */ -#ifdef CONFIG_ISDN_X25 - if( cprot && cprot -> pops && dops ) - cprot -> pops -> restart ( cprot, dev, dops ); -#endif - restore_flags(flags); -} - -/* Open/initialize the board. */ -static int -isdn_net_open(struct net_device *dev) -{ - int i; - struct net_device *p; - struct in_device *in_dev; - - /* moved here from isdn_net_reset, because only the master has an - interface associated which is supposed to be started. BTW: - we need to call netif_start_queue, not netif_wake_queue here */ - netif_start_queue(dev); - - isdn_net_reset(dev); - /* Fill in the MAC-level header (not needed, but for compatibility... */ - for (i = 0; i < ETH_ALEN - sizeof(u32); i++) - dev->dev_addr[i] = 0xfc; - if ((in_dev = dev->ip_ptr) != NULL) { - /* - * Any address will do - we take the first - */ - struct in_ifaddr *ifa = in_dev->ifa_list; - if (ifa != NULL) - memcpy(dev->dev_addr+2, &ifa->ifa_local, 4); - } - - /* If this interface has slaves, start them also */ - - if ((p = (((isdn_net_local *) dev->priv)->slave))) { - while (p) { - isdn_net_reset(p); - p = (((isdn_net_local *) p->priv)->slave); - } - } - isdn_MOD_INC_USE_COUNT(); - return 0; -} - -/* - * Assign an ISDN-channel to a net-interface - */ -static void -isdn_net_bind_channel(isdn_net_local * lp, int idx) -{ - ulong flags; - - save_flags(flags); - cli(); - lp->flags |= ISDN_NET_CONNECTED; - lp->isdn_device = dev->drvmap[idx]; - lp->isdn_channel = dev->chanmap[idx]; - dev->rx_netdev[idx] = lp->netdev; - dev->st_netdev[idx] = lp->netdev; - restore_flags(flags); -} - -/* - * unbind a net-interface (resets interface after an error) - */ -static void -isdn_net_unbind_channel(isdn_net_local * lp) -{ - ulong flags; - - 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 - if (lp->first_skb) { - dev_kfree_skb(lp->first_skb); - lp->first_skb = NULL; - } - if (lp->sav_skb) { - dev_kfree_skb(lp->sav_skb); - lp->sav_skb = NULL; - } - if (!lp->master) { /* reset only master device */ - /* Moral equivalent of dev_purge_queues(): - BEWARE! This chunk of code cannot be called from hardware - interrupt handler. I hope it is true. --ANK - */ - qdisc_reset(lp->netdev->dev.qdisc); - } - lp->dialstate = 0; - dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; - dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL; - isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET); - lp->flags &= ~ISDN_NET_CONNECTED; - lp->isdn_device = -1; - lp->isdn_channel = -1; - - restore_flags(flags); -} - -/* - * Perform auto-hangup and cps-calculation for net-interfaces. - * - * auto-hangup: - * Increment idle-counter (this counter is reset on any incoming or - * outgoing packet), if counter exceeds configured limit either do a - * hangup immediately or - if configured - wait until just before the next - * charge-info. - * - * cps-calculation (needed for dynamic channel-bundling): - * Since this function is called every second, simply reset the - * byte-counter of the interface after copying it to the cps-variable. - */ -unsigned long last_jiffies = -HZ; - -void -isdn_net_autohup() -{ - isdn_net_dev *p = dev->netdev; - int anymore; - - anymore = 0; - while (p) { - isdn_net_local *l = p->local; - if ((jiffies - last_jiffies) == 0) - l->cps = l->transcount; - else - l->cps = (l->transcount * HZ) / (jiffies - last_jiffies); - l->transcount = 0; - if (dev->net_verbose > 3) - printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps); - if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) { - anymore = 1; - l->huptimer++; -#ifdef CONFIG_ISDN_WITH_ABC - if( l->dw_abc_next_skb != NULL || - l->sav_skb != NULL || - l->first_skb != NULL || - (l->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_RSTREMOTE)) { - - isdn_net_send_skb(&p->dev,l,NULL); - } -#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 - */ - if ((l->onhtime) && - (l->huptimer > l->onhtime)) - { - if (l->hupflags & ISDN_MANCHARGE && - l->hupflags & ISDN_CHARGEHUP) { - while (jiffies - l->chargetime > l->chargeint) - l->chargetime += l->chargeint; - if (jiffies - l->chargetime >= l->chargeint - 2 * HZ) - if (l->outgoing || l->hupflags & ISDN_INHUP) - isdn_net_hangup(&p->dev); - } else if (l->outgoing) { - if (l->hupflags & ISDN_CHARGEHUP) { - if (l->hupflags & ISDN_WAITCHARGE) { - printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n", - l->name, l->hupflags); - isdn_net_hangup(&p->dev); - } else if (jiffies - l->chargetime > l->chargeint) { - printk(KERN_DEBUG - "isdn_net: %s: chtime = %lu, chint = %d\n", - l->name, l->chargetime, l->chargeint); - isdn_net_hangup(&p->dev); - } - } else - isdn_net_hangup(&p->dev); - } else if (l->hupflags & ISDN_INHUP) - isdn_net_hangup(&p->dev); - } - - if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) { - isdn_net_hangup(&p->dev); - break; - } - } - p = (isdn_net_dev *) p->next; - } - last_jiffies = jiffies; - isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore); -} - -/* - * Handle status-messages from ISDN-interfacecard. - * This function is called from within the main-status-dispatcher - * isdn_status_callback, which itself is called from the low-level driver. - * Return: 1 = Event handled, 0 = not for us or unknown Event. - */ -int -isdn_net_stat_callback(int idx, isdn_ctrl *c) -{ - isdn_net_dev *p = dev->st_netdev[idx]; - int cmd = c->command; - - if (p) { - isdn_net_local *lp = p->local; -#ifdef CONFIG_ISDN_X25 - struct concap_proto *cprot = lp -> netdev -> cprot; - struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; -#endif - switch (cmd) { - case ISDN_STAT_BSENT: - /* A packet has successfully been sent out */ - if ((lp->flags & ISDN_NET_CONNECTED) && - (!lp->dialstate)) { - lp->stats.tx_packets++; - lp->stats.tx_bytes += c->parm.length; -#ifdef CONFIG_ISDN_WITH_ABC -#ifdef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT - atomic_dec(&lp->dw_abc_pkt_onl); -#endif -#endif - /* some HL drivers deliver - ISDN_STAT_BSENT from hw interrupt. - Output routines in isdn_ppp are now - called with irq disabled such that - dequeueing the sav_skb while another - frame is sent will not occur. - */ - if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP && lp->sav_skb) { - struct net_device *mdev; - if (lp->master) - mdev = lp->master; - else - mdev = &lp->netdev->dev; - if (!isdn_net_send_skb(mdev, lp, lp->sav_skb)) { - lp->sav_skb = NULL; - } else { - return 1; - } - } - isdn_net_lp_xon(lp); - } - return 1; - case ISDN_STAT_DCONN: - /* D-Channel is up */ - switch (lp->dialstate) { - case 4: - case 7: - case 8: - lp->dialstate++; - return 1; - case 12: - lp->dialstate = 5; - return 1; - } - break; - case ISDN_STAT_DHUP: - /* Either D-Channel-hangup or error during dialout */ -#ifdef CONFIG_ISDN_X25 - /* If we are not connencted then dialing had - failed. If there are generic encap protocol - receiver routines signal the closure of - the link*/ - - if( !(lp->flags & ISDN_NET_CONNECTED) - && pops && pops -> disconn_ind ) - pops -> disconn_ind(cprot); -#endif /* CONFIG_ISDN_X25 */ - if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) { -#ifdef CONFIG_ISDN_PPP - isdn_ppp_free(lp); -#endif - isdn_all_eaz(lp->isdn_device, lp->isdn_channel); - printk(KERN_INFO "%s: remote hangup\n", lp->name); - 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: - /* B-Channel-hangup */ - /* try if there are generic encap protocol - receiver routines and signal the closure of - the link */ - if( pops && pops -> disconn_ind ){ - pops -> disconn_ind(cprot); - return 1; - } - break; -#endif /* CONFIG_ISDN_X25 */ - case ISDN_STAT_BCONN: - /* B-Channel is up */ - switch (lp->dialstate) { - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 12: - if (lp->dialstate <= 6) { - dev->usage[idx] |= ISDN_USAGE_OUTGOING; - isdn_info_update(); - } else - dev->rx_netdev[idx] = p; - lp->dialstate = 0; - isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1); - if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) - isdn_timer_ctrl(ISDN_TIMER_KEEPALIVE, 1); - 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. - */ - lp->chargetime = jiffies; - printk(KERN_DEBUG "isdn_net: chargetime of %s now %lu\n", - lp->name, lp->chargetime); - - /* reset dial-timeout */ - lp->dialstarted = 0; - lp->dialwait_timer = 0; - -#ifdef CONFIG_ISDN_PPP - if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) - isdn_ppp_wakeup_daemon(lp); -#endif -#ifdef CONFIG_ISDN_X25 - /* try if there are generic concap receiver routines */ - if( pops ) - if( pops->connect_ind) - pops->connect_ind(cprot); -#endif /* CONFIG_ISDN_X25 */ - /* Immediately send first skb to speed up arp */ - if (lp->first_skb) { - - if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb))) - lp->first_skb = NULL; - } - if(! lp->first_skb) isdn_net_lp_xon(lp); - return 1; - } - break; - case ISDN_STAT_NODCH: - /* No D-Channel avail. */ - if (lp->dialstate == 4) { - lp->dialstate--; - return 1; - } - break; - case ISDN_STAT_CINF: - /* Charge-info from TelCo. Calculate interval between - * charge-infos and set timestamp for last info for - * usage by isdn_net_autohup() - */ - lp->charge++; - if (lp->hupflags & ISDN_HAVECHARGE) { - lp->hupflags &= ~ISDN_WAITCHARGE; - lp->chargeint = jiffies - lp->chargetime - (2 * HZ); - } - if (lp->hupflags & ISDN_WAITCHARGE) - lp->hupflags |= ISDN_HAVECHARGE; - lp->chargetime = jiffies; - printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n", - lp->name, lp->chargetime); - return 1; - } - } - return 0; -} - -/* - * Check, if a number contains wildcard-characters, in which case it - * is for incoming purposes only. - */ -static int -isdn_net_checkwild(char *num) -{ - return ((strchr(num, '?')) || - (strchr(num, '*')) || - (strchr(num, '[')) || - (strchr(num, ']')) || - (strchr(num, '^'))); -} - -/* - * Perform dialout for net-interfaces and timeout-handling for - * D-Channel-up and B-Channel-up Messages. - * This function is initially called from within isdn_net_start_xmit() or - * or isdn_net_find_icall() after initializing the dialstate for an - * interface. If further calls are needed, the function schedules itself - * for a timer-callback via isdn_timer_function(). - * The dialstate is also affected by incoming status-messages from - * the ISDN-Channel which are handled in isdn_net_stat_callback() above. - */ -void -isdn_net_dial(void) -{ - isdn_net_dev *p = dev->netdev; - int anymore = 0; - int i; - int flags; - isdn_ctrl cmd; - - while (p) { - isdn_net_local *lp = p->local; - -#ifdef ISDN_DEBUG_NET_DIAL - if (lp->dialstate) - printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate); -#endif - switch (lp->dialstate) { - case 0: - /* Nothing to do for this interface */ - break; - case 1: - /* Initiate dialout. Set phone-number-pointer to first number - * of interface. - */ - 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)) { - - struct sk_buff *lfirst_skb = NULL; - int chi = 0; - short lsecure = 0; - - lfirst_skb = lp->first_skb; - lp->first_skb = NULL; - lsecure = lp->dw_abc_inuse_secure; - isdn_net_unbind_channel(lp); - lp->first_skb = lfirst_skb; - lp->dw_abc_inuse_secure = lsecure + 1; - - /* Grab a free ISDN-Channel */ - if ((lsecure >= ISDN_MAX_CHANNELS ) || (chi = -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - dwabc_isdn_get_net_free_channel(lp) -#else - 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 -#endif - ) < 0) { - - restore_flags(flags); - isdn_net_unreachable(&p->dev, lp->first_skb, - "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) { - printk(KERN_WARNING "%s: phone number deleted?\n", - lp->name); - isdn_net_hangup(&p->dev); - break; - } - anymore = 1; - - if(lp->dialtimeout > 0) - if(lp->dialstarted == 0 || jiffies > (lp->dialstarted + lp->dialtimeout + lp->dialwait)) { - lp->dialstarted = jiffies; - lp->dialwait_timer = 0; - } - - lp->dialstate++; - /* Fall through */ - case 2: - /* Prepare dialing. Clear EAZ, then set EAZ. */ - cmd.driver = lp->isdn_device; - 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( 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) { - - anymore = 1; - break; - } - - if(lp->dw_abc_lcr_io != NULL) { - - if(lp->dw_abc_lcr_io->lcr_ioctl_flags & - DWABC_LCR_FLG_DISABLE) { - - 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)); - goto dw_abc_lcr_next_click; - } -#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) - s = "dial suppressed: isdn system stopped"; - else - s = "dial suppressed: dialmode `off'"; - isdn_net_unreachable(&p->dev, lp->first_skb, s); - isdn_net_hangup(&p->dev); - break; - } - cmd.driver = lp->isdn_device; - cmd.command = ISDN_CMD_SETL2; - cmd.arg = lp->isdn_channel + (lp->l2_proto << 8); - isdn_command(&cmd); - cmd.driver = lp->isdn_device; - cmd.command = ISDN_CMD_SETL3; - cmd.arg = lp->isdn_channel + (lp->l3_proto << 8); - isdn_command(&cmd); - cmd.driver = lp->isdn_device; - cmd.arg = lp->isdn_channel; - save_flags(flags); - cli(); - if (!lp->dial) { - restore_flags(flags); - printk(KERN_WARNING "%s: phone number deleted?\n", - lp->name); - isdn_net_hangup(&p->dev); - break; - } - if (!strcmp(lp->dial->num, "LEASED")) { - restore_flags(flags); - lp->dialstate = 4; - printk(KERN_INFO "%s: Open leased line ...\n", lp->name); - } else { - if(lp->dialtimeout > 0) - if(jiffies > (lp->dialstarted + lp->dialtimeout)) { - restore_flags(flags); - lp->dialwait_timer = jiffies + lp->dialwait; - lp->dialstarted = 0; - isdn_net_unreachable(&p->dev, lp->first_skb, "dial: timed out"); - isdn_net_hangup(&p->dev); - break; - } - - sprintf(cmd.parm.setup.phone, "%s", lp->dial->num); - /* - * Switch to next number or back to start if at end of list. - */ - if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) { - lp->dial = lp->phone[1]; - lp->dialretry++; - - if (lp->dialretry > lp->dialmax) { - restore_flags(flags); - if (lp->dialtimeout == 0) { - lp->dialwait_timer = jiffies + lp->dialwait; - lp->dialstarted = 0; - isdn_net_unreachable(&p->dev, lp->first_skb, "dial: tried all numbers dialmax times"); - } - isdn_net_hangup(&p->dev); - break; - } - } - 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); - isdn_info_update(); - } -#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, - lp->isdn_channel); -#endif - isdn_command(&cmd); - } - lp->huptimer = 0; - lp->outgoing = 1; - if (lp->chargeint) { - lp->hupflags |= ISDN_HAVECHARGE; - lp->hupflags &= ~ISDN_WAITCHARGE; - } else { - lp->hupflags |= ISDN_WAITCHARGE; - lp->hupflags &= ~ISDN_HAVECHARGE; - } - anymore = 1; - 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. - * If timeout, switch back to state 3. - * Dialmax-handling moved to state 3. - */ - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) - lp->dialstate = 3; - anymore = 1; - break; - case 5: - /* Got D-Channel-Connect, send B-Channel-request */ - cmd.driver = lp->isdn_device; - cmd.arg = lp->isdn_channel; - cmd.command = ISDN_CMD_ACCEPTB; - anymore = 1; - lp->dtimer = 0; - lp->dialstate++; - isdn_command(&cmd); - break; - case 6: - /* Wait for B- or D-Channel-connect. If timeout, - * switch back to state 3. - */ -#ifdef ISDN_DEBUG_NET_DIAL - printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer); -#endif - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) - lp->dialstate = 3; - anymore = 1; - break; - case 7: - /* Got incoming Call, setup L2 and L3 protocols, - * then wait for D-Channel-connect - */ -#ifdef ISDN_DEBUG_NET_DIAL - printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer); -#endif - cmd.driver = lp->isdn_device; - cmd.command = ISDN_CMD_SETL2; - cmd.arg = lp->isdn_channel + (lp->l2_proto << 8); - isdn_command(&cmd); - cmd.driver = lp->isdn_device; - cmd.command = ISDN_CMD_SETL3; - cmd.arg = lp->isdn_channel + (lp->l3_proto << 8); - isdn_command(&cmd); - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15) - isdn_net_hangup(&p->dev); - else { - anymore = 1; - lp->dialstate++; - } - break; - case 9: - /* Got incoming D-Channel-Connect, send B-Channel-request */ - cmd.driver = lp->isdn_device; - cmd.arg = lp->isdn_channel; - cmd.command = ISDN_CMD_ACCEPTB; - isdn_command(&cmd); - anymore = 1; - lp->dtimer = 0; - lp->dialstate++; - break; - case 8: - case 10: - /* Wait for B- or D-channel-connect */ -#ifdef ISDN_DEBUG_NET_DIAL - printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer); -#endif - if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10) - isdn_net_hangup(&p->dev); - else - anymore = 1; - break; - case 11: - /* Callback Delay */ - if (lp->dtimer++ > lp->cbdelay) - lp->dialstate = 1; - anymore = 1; - break; - case 12: - /* Remote does callback. Hangup after cbdelay, then wait for incoming - * call (in state 4). - */ - if (lp->dtimer++ > lp->cbdelay) - { - printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name); - lp->dtimer = 0; - lp->dialstate = 4; - cmd.driver = lp->isdn_device; - cmd.command = ISDN_CMD_HANGUP; - cmd.arg = lp->isdn_channel; - isdn_command(&cmd); - isdn_all_eaz(lp->isdn_device, lp->isdn_channel); - } - anymore = 1; - break; - default: - printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n", - lp->dialstate, lp->name); - } - p = (isdn_net_dev *) p->next; - } - isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore); -} - -/* - * Perform hangup for a net-interface. - */ -void -isdn_net_hangup(struct net_device *d) -{ - isdn_net_local *lp = (isdn_net_local *) d->priv; - isdn_ctrl cmd; -#ifdef CONFIG_ISDN_X25 - struct concap_proto *cprot = lp -> netdev -> cprot; - struct concap_proto_ops *pops = cprot ? cprot -> pops : 0; -#endif - - if (lp->flags & ISDN_NET_CONNECTED) { - printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name); -#ifdef CONFIG_ISDN_PPP - isdn_ppp_free(lp); -#endif -#ifdef CONFIG_ISDN_X25 - /* try if there are generic encap protocol - receiver routines and signal the closure of - the link */ - if( pops && pops -> disconn_ind ) - pops -> disconn_ind(cprot); -#endif /* CONFIG_ISDN_X25 */ - - cmd.driver = lp->isdn_device; - cmd.command = ISDN_CMD_HANGUP; - cmd.arg = lp->isdn_channel; - 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); -} - -typedef struct { - unsigned short source; - 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); - int data_ofs; - ip_ports *ipp; - char addinfo[100]; - - addinfo[0] = '\0'; - /* This check stolen from 2.1.72 dev_queue_xmit_nit() */ - if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) { - /* fall back to old isdn_net_log_packet method() */ - char * buf = skb->data; - - printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name); - p = buf; - proto = ETH_P_IP; - switch (lp->p_encap) { - case ISDN_NET_ENCAP_IPTYP: - proto = ntohs(*(unsigned short *) &buf[0]); - p = &buf[2]; - break; - case ISDN_NET_ENCAP_ETHER: - proto = ntohs(*(unsigned short *) &buf[12]); - p = &buf[14]; - break; - case ISDN_NET_ENCAP_CISCOHDLC: - proto = ntohs(*(unsigned short *) &buf[2]); - p = &buf[4]; - break; -#ifdef CONFIG_ISDN_PPP - case ISDN_NET_ENCAP_SYNCPPP: - proto = ntohs(skb->protocol); - p = &buf[IPPP_MAX_HEADER]; - break; -#endif - } - } - data_ofs = ((p[0] & 15) * 4); - switch (proto) { - case ETH_P_IP: - switch (p[9]) { - case 1: - strcpy(addinfo, " ICMP"); - break; - case 2: - strcpy(addinfo, " IGMP"); - break; - case 4: - strcpy(addinfo, " IPIP"); - break; - case 6: - ipp = (ip_ports *) (&p[data_ofs]); - sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source), - ntohs(ipp->dest)); - break; - case 8: - strcpy(addinfo, " EGP"); - break; - case 12: - strcpy(addinfo, " PUP"); - break; - case 17: - ipp = (ip_ports *) (&p[data_ofs]); - sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source), - ntohs(ipp->dest)); - break; - case 22: - strcpy(addinfo, " IDP"); - 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], - addinfo); - 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; - } -} - -/* - * Generic routine to send out an skbuf. - * If lowlevel-device does not support support skbufs, use - * standard send-routine, else send directly. - * - * Return: 0 on success, !0 on failure. - */ -#ifdef CONFIG_ISDN_WITH_ABC -static int dwabc_helper_isdn_net_send_skb(struct net_device *,isdn_net_local *,struct sk_buff *); - -int isdn_net_send_skb(struct net_device *ndev, isdn_net_local * lp,struct sk_buff *skb) -{ - int r = 0; - - if(lp == NULL || ndev == NULL) { - - printk(KERN_WARNING "send_skb called with lp 0x%x ndev 0x%x\n", - (char *)lp - (char *)0,(char *)ndev - (char *)0); - - return(1); - } - - if(test_and_set_bit(ISDN_DW_ABC_BITLOCK_SEND,&lp->dw_abc_bitlocks)) { - - if(dev->net_verbose > 2) - printk(KERN_INFO "%s: send_skb called recursivly\n",lp->name); - - return(1); - } -once_more:; -#ifdef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT - if((r = atomic_read(&lp->dw_abc_pkt_onl) > 1)) { - netif_stop_queue(ndev); - clear_bit(ISDN_DW_ABC_BITLOCK_SEND,&lp->dw_abc_bitlocks); - return(1); - } -#endif - if(lp->dw_abc_next_skb != NULL) { - - if(skb == lp->dw_abc_next_skb) - skb = NULL; - - if(!dwabc_helper_isdn_net_send_skb(ndev,lp,lp->dw_abc_next_skb)) { - - lp->dw_abc_next_skb = NULL; - goto once_more; - } - - r = 1; - - } else if(lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_RSTREMOTE) { - - dwabc_bsd_first_gen(lp); - lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_RSTREMOTE; - goto once_more; - - } else if(lp->first_skb != NULL && skb != lp->first_skb) { - - lp->dw_abc_next_skb = lp->first_skb; - lp->first_skb = NULL; - goto once_more; - - } else if(lp->sav_skb != NULL && skb != lp->sav_skb) { - - lp->dw_abc_next_skb = lp->sav_skb; - lp->sav_skb = NULL; - goto once_more; - - } else 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) { - - nl = skb->len; - - if(l != nl && (r = isdn_dc2minor(lp->isdn_device,lp->isdn_channel)) >= 0) { - - dev->obytes[r] += l - nl; - lp->stats.tx_bytes += l - nl; - } - - if(dwabc_helper_isdn_net_send_skb(ndev,lp,skb)) { - - lp->dw_abc_next_skb = skb; - netif_stop_queue(ndev); - } - - r = 0; - } - - } else r = dwabc_helper_isdn_net_send_skb(ndev,lp,skb); - - if(lp->p_encap == ISDN_NET_ENCAP_RAWIP && !r) { - - lp->dw_abc_bsd_snd += l; - lp->dw_abc_bsd_bsd_snd += nl; - } - } - - if((lp->dw_abc_if_flags & ISDN_DW_ABC_IFFLAG_RSTREMOTE) && lp->dw_abc_next_skb == NULL) { - - dwabc_bsd_first_gen(lp); - lp->dw_abc_if_flags &= ~ISDN_DW_ABC_IFFLAG_RSTREMOTE; - goto once_more; - } - - clear_bit(ISDN_DW_ABC_BITLOCK_SEND,&lp->dw_abc_bitlocks); - return(r); -} - -static int dwabc_helper_isdn_net_send_skb -#else -int isdn_net_send_skb -#endif - (struct net_device *ndev, isdn_net_local * lp,struct sk_buff *skb) -{ - int ret; - int len = skb->len; /* save len */ - - ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb); - if (ret == len) { - lp->transcount += len; -#ifdef CONFIG_ISDN_WITH_ABC -#ifdef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT - atomic_inc(&lp->dw_abc_pkt_onl); -#endif -#endif - return 0; - } - if (ret < 0) { - dev_kfree_skb(skb); - lp->stats.tx_errors++; - return 0; - } - return 1; -} - -/* - * Helper function for isdn_net_start_xmit. - * When called, the connection is already established. - * Based on cps-calculation, check if device is overloaded. - * If so, and if a slave exists, trigger dialing for it. - * If any slave is online, deliver packets using a simple round robin - * scheme. - * - * Return: 0 on success, !0 on failure. - */ - -static int -isdn_net_xmit(struct net_device *ndev, isdn_net_local * lp, struct sk_buff *skb) -{ - int ret; - - /* For the other encaps the header has already been built */ -#ifdef CONFIG_ISDN_PPP - if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) { - return isdn_ppp_xmit(skb, ndev); - } -#endif - /* Reset hangup-timeout */ - lp->huptimer = 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 */ - ret = isdn_net_send_skb(ndev, lp, skb); - else { - isdn_net_local *slp = (isdn_net_local *) (lp->srobin->priv); - /* Master delivers via srobin and maintains srobin */ - if (lp->srobin == ndev) - ret = isdn_net_send_skb(ndev, lp, skb); - 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 */ - ret = isdn_net_send_skb(ndev, lp, skb); - if (lp->sqfull && ((jiffies - lp->sqfull_stamp) > (lp->slavedelay + (10 * HZ)))) - lp->sqfull = 0; - } - return ret; -} - -static void -isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev) -{ - isdn_net_local *lp = (isdn_net_local *) dev->priv; - if (!skb) - return; - if (lp->p_encap == ISDN_NET_ENCAP_ETHER) { - int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN; - if (pullsize > 0) { - printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize); - skb_pull(skb, pullsize); - } - } -} - - -#ifndef COMPAT_NO_SOFTNET -void isdn_net_tx_timeout(struct net_device * ndev) -{ - isdn_net_local *lp = (isdn_net_local *) ndev->priv; - - printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate); - if (!lp->dialstate){ - lp->stats.tx_errors++; - /* - * There is a certain probability that this currently - * works at all because if we always wake up the interface, - * then upper layer will try to send the next packet - * immediately. And then, the old clean_up logic in the - * driver will hopefully continue to work as it used to do. - * - * This is rather primitive right know, we better should - * clean internal queues here, in particular for multilink and - * ppp, and reset HL driver's channel, too. --HE - * - * actually, this may not matter at all, because ISDN hardware - * should not see transmitter hangs at all IMO - * changed KERN_DEBUG to KERN_WARNING to find out if this is - * ever called - */ - } - 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 -#if CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE || CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR - { - struct sk_buff *myskb = NULL; - - if((myskb = isdn_dw_abc_ip4_keepalive_test(ndev,skb)) == skb) - return(dwabc_isdn_net_start_xmit(skb,ndev)); - - if(dwabc_isdn_net_start_xmit(myskb,ndev)) { - - dev_kfree_skb(myskb); - return(1); - } - - dev_kfree_skb(skb); - return(0); - } -#else - return(dwabc_isdn_net_start_xmit(skb,ndev)); -#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). - For X.25 auto-dialing is completly bypassed because: - - It does not conform with the semantics of a reliable datalink - service as needed by X.25 PLP. - - I don't want that the interface starts dialing when the network layer - sends a message which requests to disconnect the lapb link (or if it - sends any other message not resulting in data transmission). - Instead, dialing will be initiated by the encapsulation protocol entity - when a dl_establish request is received from the upper layer. -*/ - if( cprot ) { - int ret = cprot -> pops -> encap_and_xmit ( cprot , skb); - if(ret) netif_stop_queue(ndev); - return ret; - } else -#endif - /* auto-dialing xmit function */ - { -#ifdef ISDN_DEBUG_NET_DUMP - u_char *buf; -#endif - isdn_net_adjust_hdr(skb, ndev); -#ifdef ISDN_DEBUG_NET_DUMP - buf = skb->data; - isdn_dumppkt("S:", buf, skb->len, 40); -#endif - if (!(lp->flags & ISDN_NET_CONNECTED)) { - int chi; - /* only do autodial if allowed by config */ - if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) { - isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'"); - dev_kfree_skb(skb); - return 0; - } - if (lp->phone[1]) { - ulong flags; - save_flags(flags); - cli(); - - 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) { - isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached"); - dev_kfree_skb(skb); - restore_flags(flags); - return 0; - } 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 = -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - dwabc_isdn_get_net_free_channel(lp) -#else - 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 -#endif - ) < 0) && - ((chi = -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - dwabc_isdn_get_net_free_channel(lp) -#else - 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 : lp->msn) -#else - lp->msn) -#endif -#endif - ) < 0)) { - restore_flags(flags); - isdn_net_unreachable(ndev, skb, - "No channel"); - dev_kfree_skb(skb); - return 0; - } - /* Log packet, which triggered dialing */ - if (dev->net_verbose) - isdn_net_log_skb(skb, lp); - 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) { - dev_kfree_skb(skb); - isdn_net_unbind_channel(lp); - restore_flags(flags); - return 0; /* STN (skb to nirvana) ;) */ - } - restore_flags(flags); - isdn_net_dial(); /* Initiate dialing */ - netif_stop_queue(ndev); - return 1; /* let upper layer requeue skb packet */ - } -#endif - /* remember first skb to speed up arp - * when using encap ETHER - */ - if (lp->first_skb) { - printk(KERN_WARNING "isdn_net_start_xmit: First skb already set!\n"); - dev_kfree_skb(lp->first_skb); - lp->first_skb = NULL; - } - lp->first_skb = skb; - /* Initiate dialing */ - restore_flags(flags); - isdn_net_dial(); - return 0; - } else { - isdn_net_unreachable(ndev, skb, - "No phone number"); - dev_kfree_skb(skb); - return 0; - } - } else { - /* Device is connected to an ISDN channel */ - ndev->trans_start = jiffies; - if (!lp->dialstate) { - /* ISDN connection is established, try sending */ - int ret; - if (lp->first_skb) { - if (isdn_net_xmit(ndev, lp, lp->first_skb)){ - netif_stop_queue(ndev); - return 1; -} - lp->first_skb = NULL; - } - ret = (isdn_net_xmit(ndev, lp, skb)); - if(ret) netif_stop_queue(ndev); - return ret; - } else - netif_stop_queue(ndev); - } - } - return 1; -} - -/* - * Shutdown a net-interface. - */ -static int -isdn_net_close(struct net_device *dev) -{ - struct net_device *p; -#ifdef CONFIG_ISDN_X25 - struct concap_proto * cprot = - ( (isdn_net_local *) dev->priv ) -> netdev -> cprot; - /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */ -#endif - -#ifdef CONFIG_ISDN_X25 - 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) { -#ifdef CONFIG_ISDN_X25 - cprot = ( (isdn_net_local *) p->priv ) - -> netdev -> cprot; - if( cprot && cprot -> pops ) - cprot -> pops -> close( cprot ); -#endif - isdn_net_hangup(p); - p = (((isdn_net_local *) p->priv)->slave); - } - } - isdn_net_hangup(dev); - isdn_MOD_DEC_USE_COUNT(); - return 0; -} - -/* - * Get statistics - */ -static struct enet_statistics * -isdn_net_get_stats(struct net_device *dev) -{ - isdn_net_local *lp = (isdn_net_local *) dev->priv; - return &lp->stats; -} - -/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN - * instead of dev->hard_header_len off. This is done because the - * lowlevel-driver has already pulled off its stuff when we get - * here and this routine only gets called with p_encap == ETHER. - * Determine the packet's protocol ID. The rule here is that we - * assume 802.3 if the type field is short enough to be a length. - * This is normal practice and works for any 'now in use' protocol. - */ - -static unsigned short -isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev) -{ - struct ethhdr *eth; - unsigned char *rawp; - - skb->mac.raw = skb->data; - skb_pull(skb, ETH_HLEN); - eth = skb->mac.ethernet; - - if (*eth->h_dest & 1) { - if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0) - skb->pkt_type = PACKET_BROADCAST; - else - skb->pkt_type = PACKET_MULTICAST; - } - /* - * This ALLMULTI check should be redundant by 1.4 - * so don't forget to remove it. - */ - - else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) { - if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN)) - skb->pkt_type = PACKET_OTHERHOST; - } - if (ntohs(eth->h_proto) >= 1536) - return eth->h_proto; - - rawp = skb->data; - - /* - * This is a magic hack to spot IPX packets. Older Novell breaks - * the protocol design and runs IPX over 802.3 without an 802.2 LLC - * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This - * won't work for fault tolerant netware but does for the rest. - */ - if (*(unsigned short *) rawp == 0xFFFF) - return htons(ETH_P_802_3); - /* - * Real 802.2 LLC - */ - return htons(ETH_P_802_2); -} - -static void -isdn_net_slarp_send(isdn_net_local *lp, int is_reply) -{ - unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; - struct sk_buff *skb = alloc_skb(hl + sizeof(cisco_hdr) + sizeof(cisco_slarp), GFP_ATOMIC); - unsigned long t = (jiffies / HZ * 1000000); - int len; - cisco_hdr *ch; - cisco_slarp *s; - - if (!skb) { - printk(KERN_WARNING - "%s: Could not allocate SLARP reply\n", lp->name); - return; - } - skb_reserve(skb, hl); - ch = (cisco_hdr *)skb_put(skb, sizeof(cisco_hdr)); - ch->addr = CISCO_ADDR_UNICAST; - ch->ctrl = 0; - ch->type = htons(CISCO_TYPE_SLARP); - s = (cisco_slarp *)skb_put(skb, sizeof(cisco_slarp)); - if (is_reply) { - s->code = htonl(CISCO_SLARP_REPLY); - memset(&s->slarp.reply.ifaddr, 0, sizeof(__u32)); - memset(&s->slarp.reply.netmask, 0, sizeof(__u32)); - } else { - lp->cisco_myseq++; - s->code = htonl(CISCO_SLARP_KEEPALIVE); - s->slarp.keepalive.my_seq = htonl(lp->cisco_myseq); - s->slarp.keepalive.your_seq = htonl(lp->cisco_yourseq); - } - s->rel = 0xffff; - s->t1 = t >> 16; - s->t0 = t & 0xffff; - len = skb->len; - if (isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 0, skb) != len) - dev_kfree_skb(skb); -} - -static void -isdn_net_slarp_in(isdn_net_local *lp, struct sk_buff *skb) -{ - cisco_slarp *s = (cisco_slarp *)skb->data; - - switch (ntohl(s->code)) { - case CISCO_SLARP_REQUEST: - isdn_net_slarp_send(lp, 1); - break; - case CISCO_SLARP_REPLY: - /* Ignore replies */ - break; - case CISCO_SLARP_KEEPALIVE: - lp->cisco_yourseq = s->slarp.keepalive.my_seq; - if (ntohl(s->slarp.keepalive.my_seq == lp->cisco_myseq)) { - if (lp->cisco_loop++ == 2) { - printk(KERN_WARNING "%s: Keepalive Loop\n", - lp->name); - lp->cisco_myseq ^= jiffies; - } - } else - lp->cisco_loop = 0; - break; - } - kfree_skb(skb); -} - -/* - * Called every 10 sec. via timer-interrupt if - * any network-interface has Cisco-Keepalive-Encapsulation - * and is online. - * Send Keepalive-Packet and re-schedule. - */ -void -isdn_net_slarp_out(void) -{ - isdn_net_dev *p = dev->netdev; - int anymore = 0; - - while (p) { - isdn_net_local *l = p->local; - if ((l->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) && - (l->flags & ISDN_NET_CONNECTED) && - (!l->dialstate) ) { - anymore = 1; - isdn_net_slarp_send(l, 0); - } - p = (isdn_net_dev *) p->next; - } - isdn_timer_ctrl(ISDN_TIMER_KEEPALIVE, anymore); -} - -/* - * Got a packet from ISDN-Channel. - */ -static void -isdn_net_receive(struct net_device *ndev, struct sk_buff *skb) -{ - 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; -#endif - cisco_hdr *ch; - - lp->transcount += skb->len; - - lp->stats.rx_packets++; - lp->stats.rx_bytes += skb->len; - if (lp->master) { - /* Bundling: If device is a slave-device, deliver to master, also - * handle master's statistics and hangup-timeout - */ - ndev = lp->master; - lp = (isdn_net_local *) ndev->priv; - lp->stats.rx_packets++; - lp->stats.rx_bytes += skb->len; - } - - skb->dev = ndev; - skb->pkt_type = PACKET_HOST; - skb->mac.raw = skb->data; -#ifdef ISDN_DEBUG_NET_DUMP - isdn_dumppkt("R:", skb->data, skb->len, 40); -#endif - switch (lp->p_encap) { - case ISDN_NET_ENCAP_ETHER: - /* Ethernet over ISDN */ -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif - olp->huptimer = 0; - lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif - skb->protocol = isdn_net_type_trans(skb, ndev); - break; - case ISDN_NET_ENCAP_UIHDLC: - /* HDLC with UI-frame (for ispa with -h1 option) */ -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif - olp->huptimer = 0; - lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif - skb_pull(skb, 2); - /* 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 -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif - olp->huptimer = 0; - lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif - 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: - ch = (cisco_hdr *)skb->data; - if ((ch->addr != CISCO_ADDR_UNICAST) && - (ch->addr != CISCO_ADDR_BROADCAST) ) { - printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n", - lp->name, ch->addr); - kfree_skb(skb); - return; - } - if (ch->ctrl != 0) { - printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n", - lp->name, ch->ctrl); - kfree_skb(skb); - return; - } - switch (ntohs(ch->type)) { - case CISCO_TYPE_INET: - skb_pull(skb, 4); - 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 CISCO_TYPE_SLARP: - skb_pull(skb, 4); - isdn_net_slarp_in(olp, skb); -#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR - lp->dw_abc_bchan_errcnt = 0; -#endif - return; - default: - printk(KERN_WARNING "%s: Unknown Cisco type 0x%04x\n", - lp->name, ch->type); - kfree_skb(skb); - return; - } - break; - case ISDN_NET_ENCAP_CISCOHDLC: - /* CISCO-HDLC IP with type field and fake I-frame-header */ - skb_pull(skb, 2); - /* Fall through */ - case ISDN_NET_ENCAP_IPTYP: - /* IP with type field */ -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif - olp->huptimer = 0; - lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif - skb->protocol = *(unsigned short *) &(skb->data[0]); - skb_pull(skb, 2); - if (*(unsigned short *) skb->data == 0xFFFF) - skb->protocol = htons(ETH_P_802_3); - break; -#ifdef CONFIG_ISDN_PPP - case ISDN_NET_ENCAP_SYNCPPP: - /* - * If encapsulation is syncppp, don't reset - * huptimer on LCP packets. - */ - if (proto != PPP_LCP) { -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - if(!(olp->dw_abc_flags & ISDN_DW_ABC_FLAG_RCV_NO_HUPTIMER)) { -#endif - olp->huptimer = 0; - lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER - } -#endif - } - isdn_ppp_receive(lp->netdev, olp, skb); - return; -#endif - default: -#ifdef CONFIG_ISDN_X25 - /* try if there are generic sync_device receiver routines */ - 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; -#endif - return; - }; -#endif /* CONFIG_ISDN_X25 */ - printk(KERN_WARNING "%s: unknown encapsulation, dropping\n", - lp->name); - kfree_skb(skb); - return; - } - -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_TCP_KEEPALIVE)) - (void)isdn_dw_abc_ip4_keepalive_test(NULL,skb); -#endif - netif_rx(skb); - return; -} - -/* - * A packet arrived via ISDN. Search interface-chain for a corresponding - * interface. If found, deliver packet to receiver-function and return 1, - * else return 0. - */ -int -isdn_net_rcv_skb(int idx, struct sk_buff *skb) -{ - isdn_net_dev *p = dev->rx_netdev[idx]; - - if (p) { - isdn_net_local *lp = p->local; - if ((lp->flags & ISDN_NET_CONNECTED) && - (!lp->dialstate)) { - isdn_net_receive(&p->dev, skb); - return 1; - } - } - return 0; -} - -static int -my_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - void *daddr, void *saddr, unsigned len) -{ - struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN); - - /* - * Set the protocol type. For a packet of type ETH_P_802_3 we - * put the length here instead. It is up to the 802.2 layer to - * carry protocol information. - */ - - if (type != ETH_P_802_3) - eth->h_proto = htons(type); - else - eth->h_proto = htons(len); - - /* - * Set the source hardware address. - */ - if (saddr) - memcpy(eth->h_source, saddr, dev->addr_len); - else - memcpy(eth->h_source, dev->dev_addr, dev->addr_len); - - /* - * Anyway, the loopback-device should never use this function... - */ - - if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { - memset(eth->h_dest, 0, dev->addr_len); - return ETH_HLEN /*(dev->hard_header_len)*/; - } - if (daddr) { - memcpy(eth->h_dest, daddr, dev->addr_len); - return ETH_HLEN /*dev->hard_header_len*/; - } - return -ETH_HLEN /*dev->hard_header_len*/; -} - -/* - * build an header - * depends on encaps that is being used. - */ - -static int -isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, - void *daddr, void *saddr, unsigned plen) -{ - isdn_net_local *lp = dev->priv; - ushort len = 0; - - switch (lp->p_encap) { - case ISDN_NET_ENCAP_ETHER: - len = my_eth_header(skb, dev, type, daddr, saddr, plen); - break; -#ifdef CONFIG_ISDN_PPP - case ISDN_NET_ENCAP_SYNCPPP: - /* stick on a fake header to keep fragmentation code happy. */ - len = IPPP_MAX_HEADER; - skb_push(skb,len); - break; -#endif - case ISDN_NET_ENCAP_RAWIP: - printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n"); - len = 0; - break; - case ISDN_NET_ENCAP_IPTYP: - /* ethernet type field */ - *((ushort *) skb_push(skb, 2)) = htons(type); - len = 2; - break; - case ISDN_NET_ENCAP_UIHDLC: - /* HDLC with UI-Frames (for ispa with -h1 option) */ - *((ushort *) skb_push(skb, 2)) = htons(0x0103); - len = 2; - break; - case ISDN_NET_ENCAP_CISCOHDLC: - skb_push(skb, 4); - skb->data[0] = 0x0f; - skb->data[1] = 0x00; - *((ushort *) & skb->data[2]) = htons(type); - len = 4; - break; -#ifdef CONFIG_ISDN_X25 - default: - /* try if there are generic concap protocol routines */ - if( lp-> netdev -> cprot ){ - printk(KERN_WARNING "isdn_net_header called with concap_proto!\n"); - len = 0; - break; - } - break; -#endif /* CONFIG_ISDN_X25 */ - } - return len; -} - -/* We don't need to send arp, because we have point-to-point connections. */ -static int -isdn_net_rebuild_header(struct sk_buff *skb) -{ - struct net_device *dev = skb->dev; - isdn_net_local *lp = dev->priv; - int ret = 0; - - if (lp->p_encap == ISDN_NET_ENCAP_ETHER) { - struct ethhdr *eth = (struct ethhdr *) skb->data; - - /* - * Only ARP/IP is currently supported - */ - - if (eth->h_proto != htons(ETH_P_IP)) { - printk(KERN_WARNING - "isdn_net: %s don't know how to resolve type %d addresses?\n", - dev->name, (int) eth->h_proto); - memcpy(eth->h_source, dev->dev_addr, dev->addr_len); - return 0; - } - /* - * Try to get ARP to resolve the header. - */ -#ifdef CONFIG_INET - ret = arp_find(eth->h_dest, skb); -#endif - } - return ret; -} - -/* - * Interface-setup. (just after registering a new interface) - */ -static int -isdn_net_init(struct net_device *ndev) -{ - ushort max_hlhdr_len = 0; - isdn_net_local *lp = (isdn_net_local *) ndev->priv; - int drvidx, - i; - - if (ndev == NULL) { - printk(KERN_WARNING "isdn_net_init: dev = NULL!\n"); - return -ENODEV; - } - if (ndev->priv == NULL) { - printk(KERN_WARNING "isdn_net_init: dev->priv = NULL!\n"); - return -ENODEV; - } - ether_setup(ndev); - lp->org_hhc = ndev->hard_header_cache; - lp->org_hcu = ndev->header_cache_update; - - /* Setup the generic properties */ - - ndev->hard_header = NULL; - ndev->hard_header_cache = NULL; - ndev->header_cache_update = NULL; - ndev->mtu = 1500; - ndev->flags = IFF_NOARP|IFF_POINTOPOINT; - ndev->type = ARPHRD_ETHER; - ndev->addr_len = ETH_ALEN; - - /* for clients with MPPP maybe higher values better */ - ndev->tx_queue_len = 30; - - for (i = 0; i < ETH_ALEN; i++) - ndev->broadcast[i] = 0xff; - - /* The ISDN-specific entries in the device structure. */ - ndev->open = &isdn_net_open; - ndev->hard_start_xmit = &isdn_net_start_xmit; - - /* - * up till binding we ask the protocol layer to reserve as much - * as we might need for HL layer - */ - - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) - if (dev->drv[drvidx]) - if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen) - max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen; - - ndev->hard_header_len = ETH_HLEN + max_hlhdr_len; - ndev->stop = &isdn_net_close; - ndev->get_stats = &isdn_net_get_stats; - ndev->rebuild_header = &isdn_net_rebuild_header; -#ifdef CONFIG_ISDN_PPP - ndev->do_ioctl = isdn_ppp_dev_ioctl; -#endif - return 0; -} - -static void -isdn_net_swapbind(int drvidx) -{ - isdn_net_dev *p; - -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx); -#endif - p = dev->netdev; - while (p) { - if (p->local->pre_device == drvidx) - switch (p->local->pre_channel) { - case 0: - p->local->pre_channel = 1; - break; - case 1: - p->local->pre_channel = 0; - break; - } - p = (isdn_net_dev *) p->next; - } -} - -static void -isdn_net_swap_usage(int i1, int i2) -{ - int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE; - int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE; - -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2); -#endif - dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE; - dev->usage[i1] |= u2; - dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE; - dev->usage[i2] |= u1; - isdn_info_update(); -} - -/* - * An incoming call-request has arrived. - * Search the interface-chain for an appropriate interface. - * If found, connect the interface to the ISDN-channel and initiate - * D- and B-Channel-setup. If secure-flag is set, accept only - * configured phone-numbers. If callback-flag is set, initiate - * callback-dialing. - * - * Return-Value: 0 = No appropriate interface for this call. - * 1 = Call accepted - * 2 = Reject call, wait cbdelay, then call back - * 3 = Reject call - * 4 = Wait cbdelay, then call back - * 5 = No appropriate interface for this call, - * would eventually match if CID was longer. - */ -int -isdn_net_find_icall(int di, int ch, int idx, setup_parm setup) -{ - char *eaz; - int si1; - int si2; - int ematch; - int wret; - int swapped; - int sidx = 0; - isdn_net_dev *p; - isdn_net_phone *n; - ulong flags; - char nr[32]; -#ifdef CONFIG_ISDN_WITH_ABC - if(dev->net_verbose > 2) - printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=0x%04X\n", di, ch, idx,dev->usage[idx]); -#endif - /* Search name in netdev-chain */ - save_flags(flags); - cli(); - if (!setup.phone[0]) { - nr[0] = '0'; - nr[1] = '\0'; - printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n"); - } else - strcpy(nr, setup.phone); - si1 = (int) setup.si1; - si2 = (int) setup.si2; - if (!setup.eazmsn[0]) { - printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n"); - eaz = "0"; - } else - 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 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, - dev->usage[idx]); -#endif - while (p) { - int matchret; - isdn_net_local *lp = p->local; - - /* If last check has triggered as binding-swap, revert it */ - switch (swapped) { - case 2: - isdn_net_swap_usage(idx, sidx); - /* fall through */ - case 1: - isdn_net_swapbind(di); - break; - } - swapped = 0; - if (!(matchret = isdn_wildmat(eaz, isdn_map_eaz2msn(lp->msn, di)))) - ematch = 1; - /* Remember if more numbers eventually can match */ - if (matchret > wret) - wret = matchret; -#ifdef ISDN_DEBUG_NET_ICALL - 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)) { - /* Here we got a problem: - * If using an ICN-Card, an incoming call is always signaled on - * on the first channel of the card, if both channels are - * down. However this channel may be bound exclusive. If the - * second channel is free, this call should be accepted. - * The solution is horribly but it runs, so what: - * We exchange the exclusive bindings of the two channels, the - * corresponding variables in the interface-structs. - */ - if (ch == 0) { - sidx = isdn_dc2minor(di, 1); -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: ch is 0\n"); -#endif - if (USG_NONE(dev->usage[sidx])) { - /* Second Channel is free, now see if it is bound - * exclusive too. */ - if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) { -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n"); -#endif - /* Yes, swap bindings only, if the original - * binding is bound to channel 1 of this driver */ - if ((lp->pre_device == di) && - (lp->pre_channel == 1)) { - isdn_net_swapbind(di); - swapped = 1; - } else { - /* ... else iterate next device */ - p = (isdn_net_dev *) p->next; - continue; - } - } else { -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n"); -#endif - /* No, swap always and swap excl-usage also */ - isdn_net_swap_usage(idx, sidx); - isdn_net_swapbind(di); - swapped = 2; - } - /* Now check for exclusive binding again */ -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: final check\n"); -#endif - if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) && - ((lp->pre_channel != ch) || - (lp->pre_device != di))) { -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: final check failed\n"); -#endif - p = (isdn_net_dev *) p->next; - continue; - } - } - } else { - /* We are already on the second channel, so nothing to do */ -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: already on 2nd channel\n"); -#endif - } - } - } -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: match2\n"); -#endif - n = lp->phone[0]; - if (lp->flags & ISDN_NET_SECURE) { - while (n) { - if (!isdn_wildmat(nr, n->num)) - break; - n = (isdn_net_phone *) n->next; - } - } - if (n || (!(lp->flags & ISDN_NET_SECURE))) { -#ifdef ISDN_DEBUG_NET_ICALL - printk(KERN_DEBUG "n_fi: match3\n"); -#endif - /* matching interface found */ - - /* - * Is the state STOPPED? - * If so, no dialin is allowed, - * so reject actively. - * */ - if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { - restore_flags(flags); - printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n", - lp->name); - return 3; - } - /* - * Is the interface up? - * If not, reject the call actively. - */ - if (!isdn_net_started(p)) { - restore_flags(flags); - printk(KERN_INFO "%s: incoming call, interface down -> rejected\n", - lp->name); - return 3; - } - /* Interface is up, now see if it's a slave. If so, see if - * it's master and parent slave is online. If not, reject the call. - */ - if (lp->master) { - isdn_net_local *mlp = (isdn_net_local *) lp->master->priv; - printk(KERN_DEBUG "ICALLslv: %s\n", lp->name); - printk(KERN_DEBUG "master=%s\n", mlp->name); - if (mlp->flags & ISDN_NET_CONNECTED) { - printk(KERN_DEBUG "master online\n"); - /* Master is online, find parent-slave (master if first slave) */ - while (mlp->slave) { - if ((isdn_net_local *) mlp->slave->priv == lp) - break; - mlp = (isdn_net_local *) mlp->slave->priv; - } - } else - printk(KERN_DEBUG "master offline\n"); - /* Found parent, if it's offline iterate next device */ - printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED); - if (!(mlp->flags & ISDN_NET_CONNECTED)) { - p = (isdn_net_dev *) p->next; - 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; - /* - * Is the state MANUAL? - * If so, no callback can be made, - * so reject actively. - * */ - if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) { - restore_flags(flags); - printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n", - lp->name); - return 3; - } - printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n", - lp->name, nr, eaz); - if (lp->phone[1]) { - /* Grab a free ISDN-Channel */ - if ((chi = -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - dwabc_isdn_get_net_free_channel(lp) -#else - isdn_get_free_channel( - ISDN_USAGE_NET, - lp->l2_proto, - lp->l3_proto, - lp->pre_device, - lp->pre_channel, - lp->msn) -#endif - ) < 0) { - - printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name); - restore_flags(flags); - return 0; - } - /* Setup dialstate. */ - lp->dtimer = 0; - lp->dialstate = 11; - /* Connect interface with channel */ - isdn_net_bind_channel(lp, chi); -#ifdef CONFIG_ISDN_PPP - if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) - if (isdn_ppp_bind(lp) < 0) { - isdn_net_unbind_channel(lp); - restore_flags(flags); - return 0; - } -#endif - /* Initiate dialing by returning 2 or 4 */ - restore_flags(flags); - return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4; - } else - printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name); - 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 -#ifdef CONFIG_ISDN_WITH_ABC -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - if(isdn_dwabc_check_icall_bind(lp,di,ch)) { - restore_flags(flags); - return 3; - } -#endif -#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 - device, so free this device */ - if ((lp->dialstate == 4) || (lp->dialstate == 12)) { -#ifdef CONFIG_ISDN_PPP - if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) - isdn_ppp_free(lp); -#endif - isdn_free_channel(lp->isdn_device, lp->isdn_channel, - ISDN_USAGE_NET); - } - dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; - dev->usage[idx] |= ISDN_USAGE_NET; - strcpy(dev->num[idx], nr); - isdn_info_update(); - dev->st_netdev[idx] = lp->netdev; - lp->isdn_device = di; - lp->isdn_channel = ch; - lp->ppp_slot = -1; - lp->flags |= ISDN_NET_CONNECTED; - lp->dialstate = 7; - lp->dtimer = 0; - lp->outgoing = 0; - lp->huptimer = 0; - lp->hupflags |= ISDN_WAITCHARGE; - lp->hupflags &= ~ISDN_HAVECHARGE; -#ifdef CONFIG_ISDN_PPP - if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) - if (isdn_ppp_bind(lp) < 0) { - isdn_net_unbind_channel(lp); - restore_flags(flags); - return 0; - } -#endif - restore_flags(flags); - return 1; - } - } - } - p = (isdn_net_dev *) p->next; - } - /* If none of configured EAZ/MSN matched and not verbose, be silent */ - if (!ematch || dev->net_verbose) - printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz); - restore_flags(flags); - return (wret == 2)?5:0; -} - -/* - * Search list of net-interfaces for an interface with given name. - */ -isdn_net_dev * -isdn_net_findif(char *name) -{ - isdn_net_dev *p = dev->netdev; - - while (p) { - if (!strcmp(p->local->name, name)) - return p; - p = (isdn_net_dev *) p->next; - } - return (isdn_net_dev *) NULL; -} - -/* - * Force a net-interface to dial out. - * This is called from the userlevel-routine below or - * from isdn_net_start_xmit(). - */ -int -isdn_net_force_dial_lp(isdn_net_local * lp) -{ - if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) { - int chi; - if (lp->phone[1]) { - ulong flags; - save_flags(flags); - cli(); - - /* Grab a free ISDN-Channel */ - if ((chi = -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - dwabc_isdn_get_net_free_channel(lp) -#else - 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 -#endif - ) < 0) { - printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name); - restore_flags(flags); - return -EAGAIN; - } - 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) - if (isdn_ppp_bind(lp) < 0) { - isdn_net_unbind_channel(lp); - restore_flags(flags); - return -EAGAIN; - } -#endif - /* Initiate dialing */ - restore_flags(flags); - isdn_net_dial(); - return 0; - } else - return -EINVAL; - } else - return -EBUSY; -} - -/* - * This is called from certain upper protocol layers (multilink ppp - * and x25iface encapsulation module) that want to initiate dialing - * themselves. - */ -int -isdn_net_dial_req(isdn_net_local * lp) -{ - /* is there a better error code? */ - if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY; - - return isdn_net_force_dial_lp(lp); -} - -/* - * Force a net-interface to dial out. - * This is always called from within userspace (ISDN_IOCTL_NET_DIAL). - */ -int -isdn_net_force_dial(char *name) -{ - isdn_net_dev *p = isdn_net_findif(name); - - if (!p) - return -ENODEV; - return (isdn_net_force_dial_lp(p->local)); -} - -/* - * Allocate a new network-interface and initialize its data structures. - */ -char * -isdn_net_new(char *name, struct net_device *master) -{ - isdn_net_dev *netdev; - - /* Avoid creating an existing interface */ - if (isdn_net_findif(name)) { - printk(KERN_WARNING "isdn_net: interface %s already exists\n", name); - return NULL; - } - if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) { - printk(KERN_WARNING "isdn_net: Could not allocate net-device\n"); - return NULL; - } - memset(netdev, 0, sizeof(isdn_net_dev)); - if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) { - printk(KERN_WARNING "isdn_net: Could not allocate device locals\n"); - return NULL; - } - memset(netdev->local, 0, sizeof(isdn_net_local)); - if (name == NULL) - strcpy(netdev->local->name, " "); - else - strcpy(netdev->local->name, name); - netdev->dev.name = netdev->local->name; - netdev->dev.priv = netdev->local; - netdev->dev.init = isdn_net_init; - netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP; - if (master) { - /* Device shall be a slave */ - struct net_device *p = (((isdn_net_local *) master->priv)->slave); - struct net_device *q = master; - - netdev->local->master = master; - /* Put device at end of slave-chain */ - while (p) { - q = p; - p = (((isdn_net_local *) p->priv)->slave); - } - ((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); - kfree(netdev); - return NULL; - } - } - netdev->local->magic = ISDN_NET_MAGIC; - -#ifdef CONFIG_ISDN_PPP - netdev->mp_last = NULL; /* mpqueue is empty */ - netdev->ib.next_num = 0; - netdev->ib.last = NULL; -#endif - netdev->queue = netdev->local; - netdev->local->last = netdev->local; - netdev->local->netdev = netdev; - netdev->local->next = netdev->local; - - netdev->local->isdn_device = -1; - netdev->local->isdn_channel = -1; - netdev->local->pre_device = -1; - netdev->local->pre_channel = -1; - netdev->local->exclusive = -1; - netdev->local->ppp_slot = -1; - netdev->local->pppbind = -1; - netdev->local->sav_skb = NULL; - netdev->local->first_skb = NULL; - netdev->local->l2_proto = ISDN_PROTO_L2_X75I; - netdev->local->l3_proto = ISDN_PROTO_L3_TRANS; - netdev->local->triggercps = 6000; - netdev->local->slavedelay = 10 * HZ; - netdev->local->srobin = &netdev->dev; - 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 */ - netdev->local->dialtimeout = -1; /* Infinite Dial-Timeout */ - netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */ - netdev->local->dialstarted = 0; /* Jiffies of last dial-start */ - netdev->local->dialwait_timer = 0; /* Jiffies of earliest next dial-start */ - - /* Put into to netdev-chain */ - netdev->next = (void *) dev->netdev; - dev->netdev = netdev; - return netdev->dev.name; -} - -char * -isdn_net_newslave(char *parm) -{ - char *p = strchr(parm, ','); - isdn_net_dev *n; - char newname[10]; - - if (p) { - /* Slave-Name MUST not be empty */ - if (!strlen(p + 1)) - return NULL; - strcpy(newname, p + 1); - *p = 0; - /* Master must already exist */ - if (!(n = isdn_net_findif(parm))) - return NULL; - /* Master must be a real interface, not a slave */ - if (n->local->master) - return NULL; - /* Master must not be started yet */ - if (isdn_net_started(n)) - return NULL; - return (isdn_net_new(newname, &(n->dev))); - } - return NULL; -} - -/* - * Set interface-parameters. - * Always set all parameters, so the user-level application is responsible - * for not overwriting existing setups. It has to get the current - * setup first, if only selected parameters are to be changed. - */ -int -isdn_net_setcfg(isdn_net_ioctl_cfg * cfg) -{ - isdn_net_dev *p = isdn_net_findif(cfg->name); - ulong features; - int i; - int drvidx; - int chidx; - char drvid[25]; -#ifdef CONFIG_ISDN_X25 - ulong flags; -#endif - if (p) { - isdn_net_local *lp = p->local; - - /* See if any registered driver supports the features we want */ - features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) | - ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT); - for (i = 0; i < ISDN_MAX_DRIVERS; i++) - if (dev->drv[i]) - if ((dev->drv[i]->interface->features & features) == features) - break; - if (i == ISDN_MAX_DRIVERS) { - printk(KERN_WARNING "isdn_net: No driver with selected features\n"); - return -ENODEV; - } - if (lp->p_encap != cfg->p_encap){ -#ifdef CONFIG_ISDN_X25 - struct concap_proto * cprot = p -> cprot; -#endif - if (isdn_net_started(p)) { - printk(KERN_WARNING "%s: cannot change encap when if is up\n", - lp->name); - return -EBUSY; - } -#ifdef CONFIG_ISDN_X25 - /* delete old encapsulation protocol if present ... */ - save_flags(flags); - cli(); /* avoid races with incoming events trying to - call cprot->pops methods */ - if( cprot && cprot -> pops ) - cprot -> pops -> proto_del ( cprot ); - p -> cprot = NULL; - lp -> dops = NULL; - restore_flags(flags); - /* ... , prepare for configuration of new one ... */ - switch ( cfg -> p_encap ){ - case ISDN_NET_ENCAP_X25IFACE: - lp -> dops = &isdn_concap_reliable_dl_dops; - } - /* ... and allocate new one ... */ - p -> cprot = isdn_concap_new( cfg -> p_encap ); - /* p -> cprot == NULL now if p_encap is not supported - by means of the concap_proto mechanism */ - /* the protocol is not configured yet; this will - happen later when isdn_net_reset() is called */ -#endif - } - switch ( cfg->p_encap ) { - case ISDN_NET_ENCAP_SYNCPPP: -#ifndef CONFIG_ISDN_PPP - printk(KERN_WARNING "%s: SyncPPP support not configured\n", - lp->name); - return -EINVAL; -#else - p->dev.type = ARPHRD_PPP; /* change ARP type */ - p->dev.addr_len = 0; -#endif - break; - case ISDN_NET_ENCAP_X25IFACE: -#ifndef CONFIG_ISDN_X25 - printk(KERN_WARNING "%s: isdn-x25 support not configured\n", - p->local->name); - return -EINVAL; -#else - p->dev.type = ARPHRD_X25; /* change ARP type */ - p->dev.addr_len = 0; -#endif - break; - default: - if( cfg->p_encap >= 0 && - cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP ) - break; - printk(KERN_WARNING - "%s: encapsulation protocol %d not supported\n", - p->local->name, cfg->p_encap); - return -EINVAL; - } - if (strlen(cfg->drvid)) { - /* A bind has been requested ... */ - char *c, - *e; - - drvidx = -1; - chidx = -1; - strcpy(drvid, cfg->drvid); - if ((c = strchr(drvid, ','))) { - /* The channel-number is appended to the driver-Id with a comma */ - chidx = (int) simple_strtoul(c + 1, &e, 10); - if (e == c) - chidx = -1; - *c = '\0'; - } - for (i = 0; i < ISDN_MAX_DRIVERS; i++) - /* Lookup driver-Id in array */ - if (!(strcmp(dev->drvid[i], drvid))) { - drvidx = i; - break; - } - if ((drvidx == -1) || (chidx == -1)) - /* Either driver-Id or channel-number invalid */ - return -ENODEV; - } else { - /* Parameters are valid, so get them */ - drvidx = lp->pre_device; - chidx = lp->pre_channel; - } - if (cfg->exclusive > 0) { - int flags; - - /* If binding is exclusive, try to grab the channel */ - save_flags(flags); - if ((i = isdn_get_free_channel(ISDN_USAGE_NET, - lp->l2_proto, lp->l3_proto, drvidx, - chidx, lp->msn)) < 0) { - /* Grab failed, because desired channel is in use */ - lp->exclusive = -1; - restore_flags(flags); - return -EBUSY; - } - /* All went ok, so update isdninfo */ - dev->usage[i] = ISDN_USAGE_EXCLUSIVE; - isdn_info_update(); - restore_flags(flags); - lp->exclusive = i; - } else { - /* Non-exclusive binding or unbind. */ - lp->exclusive = -1; - if ((lp->pre_device != -1) && (cfg->exclusive == -1)) { - isdn_unexclusive_channel(lp->pre_device, lp->pre_channel); - isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET); - drvidx = -1; - chidx = -1; - } - } - strcpy(lp->msn, cfg->eaz); - 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; - lp->cbdelay = cfg->cbdelay; - lp->dialmax = cfg->dialmax; - lp->triggercps = cfg->triggercps; - lp->slavedelay = cfg->slavedelay * HZ; - lp->pppbind = cfg->pppbind; - lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1; - lp->dialwait = cfg->dialwait * HZ; - if (cfg->secure) - lp->flags |= ISDN_NET_SECURE; - else - lp->flags &= ~ISDN_NET_SECURE; - if (cfg->cbhup) - lp->flags |= ISDN_NET_CBHUP; - else - lp->flags &= ~ISDN_NET_CBHUP; - switch (cfg->callback) { - case 0: - lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT); - break; - case 1: - lp->flags |= ISDN_NET_CALLBACK; - lp->flags &= ~ISDN_NET_CBOUT; - break; - case 2: - lp->flags |= ISDN_NET_CBOUT; - lp->flags &= ~ISDN_NET_CALLBACK; - break; - } - lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */ - if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) { - /* old isdnctrl version, where only 0 or 1 is given */ - printk(KERN_WARNING - "Old isdnctrl version detected! Please update.\n"); - lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */ - } - else { - lp->flags |= cfg->dialmode; /* turn on selected bits */ - } - if (cfg->chargehup) - lp->hupflags |= ISDN_CHARGEHUP; - else - lp->hupflags &= ~ISDN_CHARGEHUP; - if (cfg->ihup) - lp->hupflags |= ISDN_INHUP; - else - lp->hupflags &= ~ISDN_INHUP; - if (cfg->chargeint > 10) { - lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE; - lp->chargeint = cfg->chargeint * HZ; - } - if (cfg->p_encap != lp->p_encap) { - if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) { - p->dev.hard_header = NULL; - p->dev.hard_header_cache = NULL; - p->dev.header_cache_update = NULL; - p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; - } else { - p->dev.hard_header = isdn_net_header; - if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) { - p->dev.hard_header_cache = lp->org_hhc; - p->dev.header_cache_update = lp->org_hcu; - p->dev.flags = IFF_BROADCAST | IFF_MULTICAST; - } else { - p->dev.hard_header_cache = NULL; - p->dev.header_cache_update = NULL; - p->dev.flags = IFF_NOARP|IFF_POINTOPOINT; - } - } - } - lp->p_encap = cfg->p_encap; -#ifdef CONFIG_ISDN_WITH_ABC - isdn_dw_abc_reset_interface(lp,0); -#endif - return 0; - } - return -ENODEV; -} - -/* - * Perform get-interface-parameters.ioctl - */ -int -isdn_net_getcfg(isdn_net_ioctl_cfg * cfg) -{ - isdn_net_dev *p = isdn_net_findif(cfg->name); - - if (p) { - isdn_net_local *lp = p->local; - - strcpy(cfg->eaz, lp->msn); - cfg->exclusive = lp->exclusive; - if (lp->pre_device >= 0) { - sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device], - lp->pre_channel); - } else - cfg->drvid[0] = '\0'; - cfg->onhtime = lp->onhtime; - cfg->charge = lp->charge; - cfg->l2_proto = lp->l2_proto; - cfg->l3_proto = lp->l3_proto; - cfg->p_encap = lp->p_encap; - cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0; - cfg->callback = 0; - if (lp->flags & ISDN_NET_CALLBACK) - cfg->callback = 1; - if (lp->flags & ISDN_NET_CBOUT) - cfg->callback = 2; - cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0; - cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK; - cfg->chargehup = (lp->hupflags & 4) ? 1 : 0; - cfg->ihup = (lp->hupflags & 8) ? 1 : 0; - cfg->cbdelay = lp->cbdelay; - cfg->dialmax = lp->dialmax; - cfg->triggercps = lp->triggercps; - cfg->slavedelay = lp->slavedelay / HZ; - cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ? - (lp->chargeint / HZ) : 0; - cfg->pppbind = lp->pppbind; - cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1; - cfg->dialwait = lp->dialwait / HZ; - if (lp->slave) - strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name); - else - cfg->slave[0] = '\0'; - if (lp->master) - strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name); - else - cfg->master[0] = '\0'; - return 0; - } - return -ENODEV; -} - -/* - * Add a phone-number to an interface. - */ -int -isdn_net_addphone(isdn_net_ioctl_phone * phone) -{ - isdn_net_dev *p = isdn_net_findif(phone->name); - isdn_net_phone *n; - - if (isdn_net_checkwild(phone->phone) && (phone->outgoing & 1)) - return -EINVAL; - if (p) { - if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL))) - return -ENOMEM; - strcpy(n->num, phone->phone); - n->next = p->local->phone[phone->outgoing & 1]; - p->local->phone[phone->outgoing & 1] = n; -#ifdef CONFIG_ISDN_WITH_ABC - isdn_dwabc_test_phone(p->local); -#endif - return 0; - } - return -ENODEV; -} - -/* - * Copy a string of all phone-numbers of an interface to user space. - * This might sleep and must be called with the isdn semaphore down. - */ -int -isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones) -{ - isdn_net_dev *p = isdn_net_findif(phone->name); - int inout = phone->outgoing & 1; - int more = 0; - int count = 0; - isdn_net_phone *n; - - if (!p) - return -ENODEV; - inout &= 1; - for (n = p->local->phone[inout]; n; n = n->next) { - if (more) { - put_user(' ', phones++); - count++; - } - if (copy_to_user(phones, n->num, strlen(n->num) + 1)) { - return -EFAULT; - } - phones += strlen(n->num); - count += strlen(n->num); - more = 1; - } - put_user(0, phones); - count++; - return count; -} - -/* - * Copy a string containing the peer's phone number of a connected interface - * to user space. - */ -int -isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone *peer) -{ - isdn_net_dev *p = isdn_net_findif(phone->name); - int ch, dv, idx; - - if (!p) return -ENODEV; - /* - * Theoretical race: while this executes, the remote number might - * become invalid (hang up) or change (new connection), resulting - * in (partially) wrong number copied to user. This race - * currently ignored. - */ - ch = p->local->isdn_channel; - dv = p->local->isdn_device; - if(ch<0 && dv<0) return -ENOTCONN; - idx = isdn_dc2minor(dv, ch); - if (idx<0) return -ENODEV; - /* for pre-bound channels, we need this extra check */ - if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN; - strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN); - phone->outgoing=USG_OUTGOING(dev->usage[idx]); - if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT; - return 0; -} -/* - * Delete a phone-number from an interface. - */ -int -isdn_net_delphone(isdn_net_ioctl_phone * phone) -{ - isdn_net_dev *p = isdn_net_findif(phone->name); - int inout = phone->outgoing & 1; - isdn_net_phone *n; - isdn_net_phone *m; - int flags; - - if (p) { - save_flags(flags); - cli(); - n = p->local->phone[inout]; - m = NULL; - while (n) { - if (!strcmp(n->num, phone->phone)) { - if (p->local->dial == n) - p->local->dial = n->next; - if (m) - m->next = n->next; - 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; - } - m = n; - n = (isdn_net_phone *) n->next; - } - restore_flags(flags); - return -EINVAL; - } - return -ENODEV; -} - -/* - * Delete all phone-numbers of an interface. - */ -static int -isdn_net_rmallphone(isdn_net_dev * p) -{ - isdn_net_phone *n; - isdn_net_phone *m; - int flags; - int i; - - save_flags(flags); - cli(); - for (i = 0; i < 2; i++) { - n = p->local->phone[i]; - while (n) { - m = n->next; - kfree(n); - n = m; - } - 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; -} - -/* - * Force a hangup of a network-interface. - */ -int -isdn_net_force_hangup(char *name) -{ - isdn_net_dev *p = isdn_net_findif(name); - struct net_device *q; - - if (p) { - if (p->local->isdn_device < 0) - return 1; - q = p->local->slave; - /* If this interface has slaves, do a hangup for them also. */ - while (q) { - isdn_net_hangup(q); - q = (((isdn_net_local *) q->priv)->slave); - } - isdn_net_hangup(&p->dev); - return 0; - } - return -ENODEV; -} - -/* - * Helper-function for isdn_net_rm: Do the real work. - */ -static int -isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q) -{ - int flags; - - save_flags(flags); - cli(); -#if 0 - if (p->local->master) { - /* If it's a slave, it may be removed even if it is busy. However - * it has to be hung up first. - * - * Why? It can't be added when the master is up, why should it be - * possible to remove it? --KG - */ - isdn_net_hangup(&p->dev); -#ifdef COMPAT_NO_SOFTNET - p->dev.start = 0; -#endif - } -#endif - if (isdn_net_started(p)) { - restore_flags(flags); - return -EBUSY; - } -#ifdef CONFIG_ISDN_X25 - if( p -> cprot && p -> cprot -> pops ) - p -> cprot -> pops -> proto_del ( p -> cprot ); -#endif - /* Free all phone-entries */ - isdn_net_rmallphone(p); - /* If interface is bound exclusive, free channel-usage */ - if (p->local->exclusive != -1) - isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel); - if (p->local->master) { - /* It's a slave-device, so update master's slave-pointer if necessary */ - if (((isdn_net_local *) (p->local->master->priv))->slave == &p->dev) - ((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave; - } else { - /* Unregister only if it's a master-device */ - p->dev.hard_header_cache = p->local->org_hhc; - p->dev.header_cache_update = p->local->org_hcu; - unregister_netdev(&p->dev); - } - /* Unlink device from chain */ - if (q) - q->next = p->next; - else - dev->netdev = p->next; - if (p->local->slave) { - /* If this interface has a slave, remove it also */ - char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name; - isdn_net_dev *n = dev->netdev; - q = NULL; - while (n) { - if (!strcmp(n->local->name, slavename)) { - isdn_net_realrm(n, q); - break; - } - q = n; - n = (isdn_net_dev *) n->next; - } - } - /* 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); - - return 0; -} - -/* - * Remove a single network-interface. - */ -int -isdn_net_rm(char *name) -{ - isdn_net_dev *p; - isdn_net_dev *q; - - /* Search name in netdev-chain */ - p = dev->netdev; - q = NULL; - while (p) { - if (!strcmp(p->local->name, name)) - return (isdn_net_realrm(p, q)); - q = p; - p = (isdn_net_dev *) p->next; - } - /* If no more net-devices remain, disable auto-hangup timer */ - if (dev->netdev == NULL) - isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0); - return -ENODEV; -} - -/* - * Remove all network-interfaces - */ -int -isdn_net_rmall(void) -{ - int flags; - int ret; - - /* Walk through netdev-chain */ - save_flags(flags); - cli(); - while (dev->netdev) { - if (!dev->netdev->local->master) { - /* Remove master-devices only, slaves get removed with their master */ - if ((ret = isdn_net_realrm(dev->netdev, NULL))) { - restore_flags(flags); - return ret; - } - } - } - dev->netdev = NULL; - restore_flags(flags); - return 0; -} diff --git a/drivers/isdn/isdn_net.h b/drivers/isdn/isdn_net.h deleted file mode 100644 index bc6b66b8..00000000 --- a/drivers/isdn/isdn_net.h +++ /dev/null @@ -1,125 +0,0 @@ -/* $Id$ - - * header for Linux ISDN subsystem, network related functions (linklevel). - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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. - * - * $Log$ - * Revision 1.9 1999/04/12 12:33:27 fritz - * Changes from 2.0 tree. - * - * Revision 1.8 1998/10/30 17:55:33 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.7 1998/08/31 21:09:55 he - * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' - * peer phone number) - * - * Revision 1.6 1997/10/09 21:28:54 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.5 1997/02/10 20:12:47 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.4 1997/02/03 23:16:48 fritz - * Removed isdn_net_receive_callback prototype. - * - * Revision 1.3 1997/01/17 01:19:30 fritz - * Applied chargeint patch. - * - * Revision 1.2 1996/04/20 16:29:43 fritz - * Misc. typos - * - * Revision 1.1 1996/02/11 02:35:13 fritz - * Initial revision - * - */ - - /* Definitions for hupflags: */ -#define ISDN_WAITCHARGE 1 /* did not get a charge info yet */ -#define ISDN_HAVECHARGE 2 /* We know a charge info */ -#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */ -#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */ -#define ISDN_MANCHARGE 16 /* Charge Interval manually set */ - -/* - * Definitions for Cisco-HDLC header. - */ - -typedef struct cisco_hdr { - __u8 addr; /* unicast/broadcast */ - __u8 ctrl; /* Always 0 */ - __u16 type; /* IP-typefield */ -} cisco_hdr; - -typedef struct cisco_slarp { - __u32 code; /* SLREQ/SLREPLY/KEEPALIVE */ - union { - struct { - __u32 ifaddr; /* My interface address */ - __u32 netmask; /* My interface netmask */ - } reply; - struct { - __u32 my_seq; /* Packet sequence number */ - __u32 your_seq; - } keepalive; - } slarp; - __u16 rel; /* Always 0xffff */ - __u16 t1; /* Uptime in usec >> 16 */ - __u16 t0; /* Uptime in usec & 0xffff */ -} cisco_slarp; - -#define CISCO_ADDR_UNICAST 0x0f -#define CISCO_ADDR_BROADCAST 0x8f -#define CISCO_TYPE_INET 0x0800 -#define CISCO_TYPE_SLARP 0x8035 -#define CISCO_SLARP_REPLY 0 -#define CISCO_SLARP_REQUEST 1 -#define CISCO_SLARP_KEEPALIVE 2 - -extern char *isdn_net_new(char *, struct net_device *); -extern char *isdn_net_newslave(char *); -extern int isdn_net_rm(char *); -extern int isdn_net_rmall(void); -extern int isdn_net_stat_callback(int, isdn_ctrl *); -extern int isdn_net_setcfg(isdn_net_ioctl_cfg *); -extern int isdn_net_getcfg(isdn_net_ioctl_cfg *); -extern int isdn_net_addphone(isdn_net_ioctl_phone *); -extern int isdn_net_getphones(isdn_net_ioctl_phone *, char *); -extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone *); -extern int isdn_net_delphone(isdn_net_ioctl_phone *); -extern int isdn_net_find_icall(int, int, int, setup_parm); -extern void isdn_net_hangup(struct net_device *); -extern void isdn_net_dial(void); -extern void isdn_net_autohup(void); -extern int isdn_net_force_hangup(char *); -extern int isdn_net_force_dial(char *); -extern isdn_net_dev *isdn_net_findif(char *); -extern int isdn_net_send_skb(struct net_device *, isdn_net_local *, - struct sk_buff *); -extern int isdn_net_rcv_skb(int, struct sk_buff *); -extern void isdn_net_slarp_out(void); -extern int isdn_net_dial_req(isdn_net_local *); diff --git a/drivers/isdn/isdn_ppp.c b/drivers/isdn/isdn_ppp.c deleted file mode 100644 index 9228fa02..00000000 --- a/drivers/isdn/isdn_ppp.c +++ /dev/null @@ -1,3082 +0,0 @@ -/* $Id$ - * - * Linux ISDN subsystem, functions for synchronous PPP (linklevel). - * - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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. - * - * $Log$ - * Revision 1.61 1999/11/20 22:14:14 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.60 1999/11/04 20:29:55 he - * applied Andre Beck's reset_free fix - * - * Revision 1.59 1999/10/31 15:59:50 he - * more skb headroom checks - * - * Revision 1.58 1999/10/30 13:13:01 keil - * Henners isdn_ppp_skb_push:under fix - * - * Revision 1.57 1999/10/05 22:47:17 he - * Removed dead ISDN_SYNCPPP_READDRESS code (obsoleted by sysctl_ip_dynaddr - * and network address translation) - * - * Revision 1.56 1999/09/29 16:01:06 he - * replaced dev_alloc_skb() for downstream skbs by equivalent alloc_skb() - * - * Revision 1.55 1999/09/23 22:07:51 detabc - * - * make ipc_head common usable (for use compressor with raw-ip) - * add function before netif_rx(). needed for ipv4-tcp-keepalive-detect. - * ~ - * - * Revision 1.54 1999/09/13 23:25:17 he - * serialized xmitting frames from isdn_ppp and BSENT statcallb - * - * Revision 1.53 1999/08/31 11:18:14 paul - * various spelling corrections (new checksums may be needed, Karsten!) - * - * Revision 1.52 1999/08/22 20:26:07 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.51 1999/08/18 16:19:17 hipp - * applied MPPP-resize-headroom patch - * - * Revision 1.50 1999/08/16 07:11:41 hipp - * Additional VJ decomp-buffer-size increased from 40 to 128 - * - * Revision 1.49 1999/07/06 07:47:11 calle - * bugfix: dev_alloc_skb only reserve 16 bytes. We need to look at the - * hdrlen the driver want. So I changed dev_alloc_skb calls - * to alloc_skb and skb_reserve. - * - * Revision 1.48 1999/07/01 08:29:56 keil - * compatibility to 2.3 kernel - * - * Revision 1.47 1999/04/18 14:06:59 fritz - * Removed TIMRU stuff. - * - * Revision 1.46 1999/04/12 12:33:35 fritz - * Changes from 2.0 tree. - * - * Revision 1.45 1998/12/30 17:48:24 paul - * fixed syncPPP callback out - * - * Revision 1.44 1998/10/30 17:55:34 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.43 1998/10/29 17:23:54 hipp - * Minor MPPP fixes, verboser logging. - * - * Revision 1.42 1998/07/20 11:30:07 hipp - * Readded compression check - * - * Revision 1.41 1998/07/08 16:50:57 hipp - * Compression changes - * - * Revision 1.40 1998/04/06 19:07:27 hipp - * added check, whether compression is enabled. - * - * Revision 1.39 1998/03/25 22:46:53 hipp - * Some additional CCP changes. - * - * Revision 1.38 1998/03/24 16:33:06 hipp - * More CCP changes. BSD compression now "works" on a local loopback link. - * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h - * - * Revision 1.37 1998/03/22 18:50:49 hipp - * Added BSD Compression for syncPPP .. UNTESTED at the moment - * - * Revision 1.36 1998/03/09 17:46:30 he - * merged in 2.1.89 changes - * - * Revision 1.35 1998/03/07 18:21:11 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.34 1998/02/25 17:49:48 he - * Changed return codes caused be failing copy_{to,from}_user to -EFAULT - * - * Revision 1.33 1998/02/20 17:11:54 fritz - * Changes for recent kernels. - * - * Revision 1.32 1998/01/31 19:29:55 calle - * Merged changes from and for 2.1.82, not tested only compiled ... - * - * Revision 1.31 1997/10/09 21:29:01 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.30 1997/10/01 09:20:38 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.29 1997/08/21 23:11:44 fritz - * Added changes for kernels >= 2.1.45 - * - * Revision 1.28 1997/06/17 13:05:57 hipp - * Applied Eric's underflow-patches (slightly modified) - * more compression changes (but disabled at the moment) - * changed one copy_to_user() to run with enabled IRQs - * a few MP changes - * changed 'proto' handling in the isdn_ppp receive code - * - * Revision 1.27 1997/03/30 16:51:17 calle - * changed calls to copy_from_user/copy_to_user and removed verify_area - * were possible. - * - * Revision 1.26 1997/02/23 16:53:44 hipp - * minor cleanup - * some initial changes for future PPP compresion - * added AC,PC compression for outgoing frames - * - * Revision 1.25 1997/02/12 20:37:35 hipp - * New ioctl() PPPIOCGCALLINFO, minor cleanup - * - * Revision 1.24 1997/02/11 18:32:56 fritz - * Bugfix in isdn_ppp_free_mpqueue(). - * - * Revision 1.23 1997/02/10 11:12:19 fritz - * More changes for Kernel 2.1.X compatibility. - * - * Revision 1.22 1997/02/06 15:03:51 hipp - * changed GFP_KERNEL kmalloc to GFP_ATOMIC in isdn_ppp_fill_mpqueue() - * - * Revision 1.21 1997/02/03 23:29:38 fritz - * Reformatted according CodingStyle - * Bugfix: removed isdn_ppp_skb_destructor, used by upper layers. - * Misc changes for Kernel 2.1.X compatibility. - * - * Revision 1.20 1996/10/30 12:21:58 fritz - * Cosmetic fix: Compiler warning when compiling without MPP. - * - * Revision 1.19 1996/10/25 19:03:21 hipp - * changed/added some defines to (re)allow compilation without MP/VJ - * - * Revision 1.18 1996/10/22 23:14:00 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.17 1996/10/22 09:39:49 hipp - * a few MP changes and bugfixes - * - * Revision 1.16 1996/09/23 01:58:10 fritz - * Fix: With syncPPP encapsulation, discard LCP packets - * when calculating hangup timeout. - * - * Revision 1.15 1996/09/07 12:50:12 hipp - * bugfixes (unknown device after failed dial attempt, minor bugs) - * - * Revision 1.14 1996/08/12 16:26:47 hipp - * code cleanup - * changed connection management from minors to slots - * - * Revision 1.13 1996/07/01 19:47:24 hipp - * Fixed memory leak in VJ handling and more VJ changes - * - * Revision 1.12 1996/06/24 17:42:03 fritz - * Minor bugfixes. - * - * Revision 1.11 1996/06/16 17:46:05 tsbogend - * changed unsigned long to u32 to make Alpha people happy - * - * Revision 1.10 1996/06/11 14:50:29 hipp - * Lot of changes and bugfixes. - * New scheme to resend packets to busy LL devices. - * - * Revision 1.9 1996/05/18 01:37:01 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.8 1996/05/06 11:34:55 hipp - * fixed a few bugs - * - * Revision 1.7 1996/04/30 11:07:42 fritz - * Added Michael's ippp-bind patch. - * - * Revision 1.6 1996/04/30 09:33:09 fritz - * Removed compatibility-macros. - * - * Revision 1.5 1996/04/20 16:32:32 fritz - * Changed ippp_table to an array of pointers, allocating each part - * separately. - * - * Revision 1.4 1996/02/19 15:25:50 fritz - * Bugfix: Sync-PPP packets got compressed twice, when resent due to - * send-queue-full reject. - * - * Revision 1.3 1996/02/11 02:27:12 fritz - * Lot of Bugfixes my Michael. - * Moved calls to skb_push() into isdn_net_header() - * Fixed a possible race-condition in isdn_ppp_timer_timeout(). - * - * Revision 1.2 1996/01/22 05:08:06 fritz - * Merged in Michael's patches for MP. - * Minor changes in isdn_ppp_xmit. - * - * Revision 1.1 1996/01/09 04:11:29 fritz - * Initial revision - * - */ - -/* TODO: right tbusy handling when using MP */ - -#define CONFIG_ISDN_CCP 1 - -#include -#define __NO_VERSION__ -#include -#include -#include -#include -#include - -#include "isdn_common.h" -#include "isdn_ppp.h" -#include "isdn_net.h" - -#ifndef PPP_IPX -#define PPP_IPX 0x002b -#endif - -/* set this if you use dynamic addressing */ - -/* Prototypes */ -static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot); -static int isdn_ppp_closewait(int slot); -static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff *skb, int proto); -static int isdn_ppp_if_get_unit(char *namebuf); -static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *); -static struct sk_buff *isdn_ppp_decompress(struct sk_buff *, - struct ippp_struct *,struct ippp_struct *,int proto); -static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp, - struct sk_buff *skb,int proto); -static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, - struct ippp_struct *is,struct ippp_struct *master,int type); -static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, - struct sk_buff *skb); - -/* New CCP stuff */ -static void isdn_ppp_ccp_kickup(struct ippp_struct *is); -static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, - unsigned char code, unsigned char id, - unsigned char *data, int len); -static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is); -static void isdn_ppp_ccp_reset_free(struct ippp_struct *is); -static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, - unsigned char id); -static void isdn_ppp_ccp_timer_callback(unsigned long closure); -static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is, - unsigned char id); -static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is, - struct isdn_ppp_resetparams *rp); -static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is, - unsigned char id); - - - -#ifdef CONFIG_ISDN_MPP -static int isdn_ppp_bundle(struct ippp_struct *, int unit); -static void isdn_ppp_mask_queue(isdn_net_dev * dev, long mask); -static void isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min); -static void isdn_ppp_cleanup_sqqueue(isdn_net_dev * dev, isdn_net_local *, long min); -static void isdn_ppp_free_sqqueue(isdn_net_dev *); -static int isdn_ppp_fill_mpqueue(isdn_net_dev *, struct sk_buff **skb, - int BEbyte, long *sqno, int min_sqno); -static void isdn_ppp_free_mpqueue(isdn_net_dev *); -#endif - -char *isdn_ppp_revision = "$Revision$"; - -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) - */ -static void -isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot) -{ - int cnt, - j, - i; - char buf[80]; - - if (len < maxlen) - maxlen = len; - - for (i = 0, cnt = 0; cnt < maxlen; i++) { - for (j = 0; j < 16 && cnt < maxlen; j++, cnt++) - sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]); - printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf); - } -} - -/* - * unbind isdn_net_local <=> ippp-device - * note: it can happen, that we hangup/free the master before the slaves - * in this case we bind another lp to the master device - */ -int -isdn_ppp_free(isdn_net_local * lp) -{ -#ifdef CONFIG_ISDN_MPP - isdn_net_local *master_lp = lp; -#endif - unsigned long flags; - struct ippp_struct *is; - - if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) - return 0; - - is = ippp_table[lp->ppp_slot]; - - save_flags(flags); - cli(); -#ifdef CONFIG_ISDN_MPP - if (lp->master) - master_lp = (isdn_net_local *) lp->master->priv; - - lp->last->next = lp->next; - lp->next->last = lp->last; - if (master_lp->netdev->queue == lp) { - master_lp->netdev->queue = lp->next; - if (lp->next == lp) { /* last link in queue? */ - master_lp->netdev->ib.bundled = 0; - isdn_ppp_free_mpqueue(master_lp->netdev); - isdn_ppp_free_sqqueue(master_lp->netdev); - } - } - lp->next = lp->last = lp; /* (re)set own pointers */ -#endif - - if ((is->state & IPPP_CONNECT)) - isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */ - else if (is->state & IPPP_ASSIGNED) - is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */ - - if (is->debug & 0x1) - printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp); - - is->lp = NULL; /* link is down .. set lp to NULL */ - lp->ppp_slot = -1; /* is this OK ?? */ - restore_flags(flags); - - return 0; -} - -/* - * bind isdn_net_local <=> ippp-device - */ -int -isdn_ppp_bind(isdn_net_local * lp) -{ - int i; - int unit = 0; - long flags; - struct ippp_struct *is; - - if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) - return -1; - - save_flags(flags); - cli(); - - if (lp->pppbind < 0) { /* device bounded to ippp device ? */ - isdn_net_dev *net_dev = dev->netdev; - char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */ - memset(exclusive, 0, ISDN_MAX_CHANNELS); - while (net_dev) { /* step through net devices to find exclusive minors */ - isdn_net_local *lp = net_dev->local; - if (lp->pppbind >= 0) - exclusive[lp->pppbind] = 1; - net_dev = net_dev->next; - } - /* - * search a free device / slot - */ - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) { /* OPEN, but not connected! */ - break; - } - } - } else { - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (ippp_table[i]->minor == lp->pppbind && - (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN) - break; - } - } - - if (i >= ISDN_MAX_CHANNELS) { - restore_flags(flags); - printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n"); - return -1; - } - unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */ - if (unit < 0) { - printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name); - return -1; - } - lp->ppp_slot = i; - - /* reset some values */ - lp->netdev->ib.bundled = 0; - lp->netdev->ib.next_num = 0; - lp->netdev->ib.modify = 0; - lp->netdev->ib.last = NULL; - lp->netdev->ib.min = 0; - lp->netdev->ib.sq = NULL; - - is = ippp_table[i]; - is->lp = lp; - is->unit = unit; - is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */ - - restore_flags(flags); - - return lp->ppp_slot; -} - -/* - * kick the ipppd on the device - * (wakes up daemon after B-channel connect) - */ - -void -isdn_ppp_wakeup_daemon(isdn_net_local * lp) -{ - if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) - return; - - ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK; - -#ifndef COMPAT_HAS_NEW_WAITQ - if (ippp_table[lp->ppp_slot]->wq) -#endif - wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq); -} - -/* - * there was a hangup on the netdevice - * force wakeup of the ippp device - * go into 'device waits for release' state - */ -static int -isdn_ppp_closewait(int slot) -{ - struct ippp_struct *is; - - if (slot < 0 || slot >= ISDN_MAX_CHANNELS) - return 0; - is = ippp_table[slot]; - -#ifdef COMPAT_HAS_NEW_WAITQ - if (is->state) -#else - if (is->state && is->wq) -#endif - wake_up_interruptible(&is->wq); - - is->state = IPPP_CLOSEWAIT; - return 1; -} - -/* - * isdn_ppp_find_slot / isdn_ppp_free_slot - */ - -static int -isdn_ppp_get_slot(void) -{ - int i; - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (!ippp_table[i]->state) - return i; - } - return -1; -} - -/* - * isdn_ppp_open - */ - -int -isdn_ppp_open(int min, struct file *file) -{ - int slot; - struct ippp_struct *is; - - if (min < 0 || min > ISDN_MAX_CHANNELS) - return -ENODEV; - - slot = isdn_ppp_get_slot(); - if (slot < 0) { - return -EBUSY; - } - is = file->private_data = ippp_table[slot]; - -#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; - is->link_decompressor = is->decompressor = NULL; - is->link_comp_stat = is->comp_stat = NULL; - is->link_decomp_stat = is->decomp_stat = NULL; - is->compflags = 0; - - is->reset = isdn_ppp_ccp_reset_alloc(is); - - is->lp = NULL; - is->mp_seqno = 0; /* MP sequence number */ - is->pppcfg = 0; /* ppp configuration */ - is->mpppcfg = 0; /* mppp configuration */ - is->range = 0x1000000; /* MP: 24 bit range */ - is->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */ - is->unit = -1; /* set, when we have our interface */ - is->mru = 1524; /* MRU, default 1524 */ - is->maxcid = 16; /* VJ: maxcid */ - is->tk = current; -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&is->wq); -#else - is->wq = NULL; /* read() wait queue */ -#endif - is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ - is->last = is->rq; - is->minor = min; -#ifdef CONFIG_ISDN_PPP_VJ - /* - * VJ header compression init - */ - is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */ -#endif - - is->state = IPPP_OPEN; - - return 0; -} - -/* - * release ippp device - */ -void -isdn_ppp_release(int min, struct file *file) -{ - int i; - struct ippp_struct *is; - - if (min < 0 || min >= ISDN_MAX_CHANNELS) - return; - is = file->private_data; - - 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; - - is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */ - /* - * isdn_net_hangup() calls isdn_ppp_free() - * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1 - * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon() - */ - isdn_net_hangup(&p->dev); - } - for (i = 0; i < NUM_RCV_BUFFS; i++) { - if (is->rq[i].buf) { - kfree(is->rq[i].buf); - is->rq[i].buf = NULL; - } - } - is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */ - is->last = is->rq; - -#ifdef CONFIG_ISDN_PPP_VJ -/* TODO: if this was the previous master: link the slcomp to the new master */ - slhc_free(is->slcomp); - is->slcomp = NULL; -#endif - -/* 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) - is->link_compressor->free(is->link_comp_stat); - if(is->link_decomp_stat) - is->link_decompressor->free(is->link_decomp_stat); - if(is->decomp_stat) - is->decompressor->free(is->decomp_stat); - is->compressor = is->link_compressor = NULL; - is->decompressor = is->link_decompressor = NULL; - is->comp_stat = is->link_comp_stat = NULL; - is->decomp_stat = is->link_decomp_stat = NULL; - - /* Clean up if necessary */ - if(is->reset) - isdn_ppp_ccp_reset_free(is); - - /* this slot is ready for new connections */ - is->state = 0; -} - -/* - * get_arg .. ioctl helper - */ -static int -get_arg(void *b, void *val, int len) -{ - if (len <= 0) - len = sizeof(void *); - if (copy_from_user((void *) val, b, len)) - return -EFAULT; - return 0; -} - -/* - * set arg .. ioctl helper - */ -static int -set_arg(void *b, void *val,int len) -{ - if(len <= 0) - len = sizeof(void *); - if (copy_to_user(b, (void *) val, len)) - return -EFAULT; - return 0; -} - -/* - * ippp device ioctl - */ -int -isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg) -{ - unsigned long val; - int r,i,j; - struct ippp_struct *is; - isdn_net_local *lp; - struct isdn_ppp_comp_data data; - - is = (struct ippp_struct *) file->private_data; - lp = is->lp; - - if (is->debug & 0x1) - printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state); - - if (!(is->state & IPPP_OPEN)) - return -EINVAL; - - switch (cmd) { - case PPPIOCBUNDLE: -#ifdef CONFIG_ISDN_MPP - if (!(is->state & IPPP_CONNECT)) - return -EINVAL; - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; - printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n", - (int) min, (int) is->unit, (int) val); - return isdn_ppp_bundle(is, val); -#else - return -1; -#endif - break; - case PPPIOCGUNIT: /* get ppp/isdn unit number */ - if ((r = set_arg((void *) arg, &is->unit, sizeof(is->unit) ))) - return r; - break; - case PPPIOCGIFNAME: - if(!lp) - return -EINVAL; - if ((r = set_arg((void *) arg, lp->name, strlen(lp->name)))) - return r; - break; - case PPPIOCGMPFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, &is->mpppcfg, sizeof(is->mpppcfg) ))) - return r; - break; - case PPPIOCSMPFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; - is->mpppcfg = val; - break; - case PPPIOCGFLAGS: /* get configuration flags */ - if ((r = set_arg((void *) arg, &is->pppcfg,sizeof(is->pppcfg) ))) - return r; - break; - case PPPIOCSFLAGS: /* set configuration flags */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) { - return r; - } - if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) { - if (lp) { - /* OK .. we are ready to send buffers */ - netif_wake_queue(&lp->netdev->dev); - } - } - 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; - pidle.xmit_idle = pidle.recv_idle = lp->huptimer; - if ((r = set_arg((void *) arg, &pidle,sizeof(struct ppp_idle)))) - return r; - } - break; - case PPPIOCSMRU: /* set receive unit size for PPP */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; - is->mru = val; - break; - case PPPIOCSMPMRU: - break; - case PPPIOCSMPMTU: - break; - case PPPIOCSMAXCID: /* set the maximum compression slot id */ - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; - val++; - if (is->maxcid != val) { -#ifdef CONFIG_ISDN_PPP_VJ - struct slcompress *sltmp; -#endif - if (is->debug & 0x1) - printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val); - is->maxcid = val; -#ifdef CONFIG_ISDN_PPP_VJ - sltmp = slhc_init(16, val); - if (!sltmp) { - printk(KERN_ERR "ippp, can't realloc slhc struct\n"); - return -ENOMEM; - } - if (is->slcomp) - slhc_free(is->slcomp); - is->slcomp = sltmp; -#endif - } - break; - case PPPIOCGDEBUG: - if ((r = set_arg((void *) arg, &is->debug, sizeof(is->debug) ))) - return r; - break; - case PPPIOCSDEBUG: - if ((r = get_arg((void *) arg, &val, sizeof(val) ))) - return r; - is->debug = val; - break; - case PPPIOCGCOMPRESSORS: - { - unsigned long protos[8] = {0,}; - struct isdn_ppp_compressor *ipc = ipc_head; - while(ipc) { - j = ipc->num / (sizeof(long)*8); - i = ipc->num % (sizeof(long)*8); - if(j < 8) - protos[j] |= (0x1<next; - } - if ((r = set_arg((void *) arg,protos,8*sizeof(long) ))) - return r; - } - break; - case PPPIOCSCOMPRESSOR: - if ((r = get_arg((void *) arg, &data, sizeof(struct isdn_ppp_comp_data)))) - return r; - return isdn_ppp_set_compressor(is, &data); - case PPPIOCGCALLINFO: - { - struct pppcallinfo pci; - memset((char *) &pci,0,sizeof(struct pppcallinfo)); - if(lp) - { - strncpy(pci.local_num,lp->msn,63); - if(lp->dial) { - strncpy(pci.remote_num,lp->dial->num,63); - } - pci.charge_units = lp->charge; - if(lp->outgoing) - pci.calltype = CALLTYPE_OUTGOING; - else - pci.calltype = CALLTYPE_INCOMING; - if(lp->flags & ISDN_NET_CALLBACK) - pci.calltype |= CALLTYPE_CALLBACK; - } - return set_arg((void *)arg,&pci,sizeof(struct pppcallinfo)); - } - default: - break; - } - return 0; -} - -unsigned int -isdn_ppp_poll(struct file *file, poll_table * wait) -{ - unsigned int mask; - struct ippp_buf_queue *bf; - struct ippp_buf_queue *bl; - unsigned long flags; - struct ippp_struct *is; - - is = file->private_data; - - if (is->debug & 0x2) - printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n", - MINOR(file->f_dentry->d_inode->i_rdev)); - - /* just registers wait_queue hook. This doesn't really wait. */ - poll_wait(file, &is->wq, wait); - - if (!(is->state & IPPP_OPEN)) { - if(is->state == IPPP_CLOSEWAIT) - return POLLHUP; - printk(KERN_DEBUG "isdn_ppp: device not open\n"); - return POLLERR; - } - /* we're always ready to send .. */ - mask = POLLOUT | POLLWRNORM; - - save_flags(flags); - cli(); - bl = is->last; - bf = is->first; - /* - * if IPPP_NOBLOCK is set we return even if we have nothing to read - */ - if (bf->next != bl || (is->state & IPPP_NOBLOCK)) { - is->state &= ~IPPP_NOBLOCK; - mask |= POLLIN | POLLRDNORM; - } - restore_flags(flags); - return mask; -} - -/* - * fill up isdn_ppp_read() queue .. - */ - -static int -isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot) -{ - struct ippp_buf_queue *bf, - *bl; - unsigned long flags; - unsigned char *nbuf; - struct ippp_struct *is; - - if (slot < 0 || slot >= ISDN_MAX_CHANNELS) { - printk(KERN_WARNING "ippp: illegal slot.\n"); - return 0; - } - is = ippp_table[slot]; - - if (!(is->state & IPPP_CONNECT)) { - printk(KERN_DEBUG "ippp: device not activated.\n"); - return 0; - } - nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC); - if (!nbuf) { - printk(KERN_WARNING "ippp: Can't alloc buf\n"); - return 0; - } - nbuf[0] = PPP_ALLSTATIONS; - nbuf[1] = PPP_UI; - nbuf[2] = proto >> 8; - nbuf[3] = proto & 0xff; - memcpy(nbuf + 4, buf, len); - - save_flags(flags); - cli(); - - bf = is->first; - bl = is->last; - - if (bf == bl) { - printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n"); - bf = bf->next; - kfree(bf->buf); - is->first = bf; - } - bl->buf = (char *) nbuf; - bl->len = len + 4; - - is->last = bl->next; - restore_flags(flags); - -#ifndef COMPAT_HAS_NEW_WAITQ - if (is->wq) -#endif - wake_up_interruptible(&is->wq); - - return len; -} - -/* - * read() .. non-blocking: ipppd calls it only after select() - * reports, that there is data - */ - -int -isdn_ppp_read(int min, struct file *file, char *buf, int count) -{ - struct ippp_struct *is; - struct ippp_buf_queue *b; - int r; - unsigned long flags; - unsigned char *save_buf; - - is = file->private_data; - - if (!(is->state & IPPP_OPEN)) - return 0; - - if ((r = verify_area(VERIFY_WRITE, (void *) buf, count))) - return r; - - save_flags(flags); - cli(); - - b = is->first->next; - save_buf = b->buf; - if (!save_buf) { - restore_flags(flags); - return -EAGAIN; - } - if (b->len < count) - count = b->len; - b->buf = NULL; - is->first = b; - - restore_flags(flags); - - copy_to_user(buf, save_buf, count); - kfree(save_buf); - - return count; -} - -/* - * ipppd wanna write a packet to the card .. non-blocking - */ - -int -isdn_ppp_write(int min, struct file *file, const char *buf, int count) -{ - isdn_net_local *lp; - struct ippp_struct *is; - int proto; - unsigned char protobuf[4]; - - is = file->private_data; - - if (!(is->state & IPPP_CONNECT)) - return 0; - - lp = is->lp; - - /* -> push it directly to the lowlevel interface */ - - if (!lp) - printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n"); - else { - /* - * Don't reset huptimer for - * LCP packets. (Echo requests). - */ - if (copy_from_user(protobuf, buf, 4)) - return -EFAULT; - proto = PPP_PROTOCOL(protobuf); - if (proto != PPP_LCP) - lp->huptimer = 0; - - if (lp->isdn_device < 0 || lp->isdn_channel < 0) - return 0; - - if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) && - lp->dialstate == 0 && - (lp->flags & ISDN_NET_CONNECTED)) { - unsigned short hl; - unsigned long flags; - int cnt; - struct sk_buff *skb; - /* - * we need to reserve enought space in front of - * sk_buff. old call to dev_alloc_skb only reserved - * 16 bytes, now we are looking what the driver want - */ - hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; - skb = alloc_skb(hl+count, GFP_ATOMIC); - if (!skb) { - printk(KERN_WARNING "isdn_ppp_write: out of memory!\n"); - return count; - } - skb_reserve(skb, hl); - if (copy_from_user(skb_put(skb, count), buf, count)) - return -EFAULT; - if (is->debug & 0x40) { - printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len); - isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot); - } - - isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */ - - save_flags(flags); - cli(); - if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb)) != count) { - if (lp->sav_skb) { - dev_kfree_skb(lp->sav_skb); - printk(KERN_INFO "isdn_ppp_write: freeing sav_skb (%d,%d)!\n", cnt, count); - } else - printk(KERN_INFO "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n", cnt, count); - lp->sav_skb = skb; - } - restore_flags(flags); - } - } - return count; -} - -/* - * init memory, structures etc. - */ - -int -isdn_ppp_init(void) -{ - int i, - j; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if (!(ippp_table[i] = (struct ippp_struct *) - kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) { - printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n"); - for (j = 0; j < i; j++) - kfree(ippp_table[i]); - return -1; - } - memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct)); - ippp_table[i]->state = 0; - ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1; - ippp_table[i]->last = ippp_table[i]->rq; - - for (j = 0; j < NUM_RCV_BUFFS; j++) { - ippp_table[i]->rq[j].buf = NULL; - ippp_table[i]->rq[j].last = ippp_table[i]->rq + - (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS; - ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS; - } - } - return 0; -} - -void -isdn_ppp_cleanup(void) -{ - int i; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - kfree(ippp_table[i]); -} - -/* - * get the PPP protocol header and pull skb - */ -static int isdn_ppp_strip_proto(struct sk_buff *skb) -{ - int proto; - if (skb->data[0] & 0x1) { - proto = skb->data[0]; - skb_pull(skb, 1); /* protocol ID is only 8 bit */ - } else { - proto = ((int) skb->data[0] << 8) + skb->data[1]; - skb_pull(skb, 2); - } - return proto; -} - - -/* - * handler for incoming packets on a syncPPP interface - */ -void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb) -{ - struct ippp_struct *is; - int proto; - - is = ippp_table[lp->ppp_slot]; - - if (is->debug & 0x4) { - printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n", - (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len); - isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot); - } - if (net_dev->local->master) { - printk(KERN_WARNING "isdn_ppp_receive: net_dev != master\n"); - net_dev = ((isdn_net_local *) net_dev->local->master->priv)->netdev; - } - if (skb->data[0] == 0xff && skb->data[1] == 0x03) - skb_pull(skb, 2); - else if (is->pppcfg & SC_REJ_COMP_AC) { - dev_kfree_skb(skb); - return; /* discard it silently */ - } - - proto = isdn_ppp_strip_proto(skb); - -#ifdef CONFIG_ISDN_MPP - if (!(is->mpppcfg & SC_REJ_MP_PROT)) { - int sqno_end; - - if(is->compflags & SC_LINK_DECOMP_ON) { - if(proto == PPP_LINK_COMP) { - if(is->debug & 0x10) - printk(KERN_DEBUG "received single link compressed frame\n"); - skb = isdn_ppp_decompress(skb,is,NULL,proto); - if(!skb) - return; - proto = isdn_ppp_strip_proto(skb); - } - else - isdn_ppp_decompress(skb,is,NULL,proto); - } - - if (proto == PPP_MP) { - isdn_net_local *lpq; - long sqno, min_sqno, tseq; - - u_char BEbyte = skb->data[0]; - if (is->debug & 0x8) - printk(KERN_DEBUG "recv: %d/%04x/%d -> %02x %02x %02x %02x %02x %02x\n", lp->ppp_slot, proto, - (int) skb->len, (int) skb->data[0], (int) skb->data[1], (int) skb->data[2], - (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]); - if (!(is->mpppcfg & SC_IN_SHORT_SEQ)) { - sqno = ((int) skb->data[1] << 16) + ((int) skb->data[2] << 8) + (int) skb->data[3]; - skb_pull(skb, 4); - } else { - sqno = (((int) skb->data[0] & 0xf) << 8) + (int) skb->data[1]; - skb_pull(skb, 2); - } - - /* - * new sequence number lower than last number? (this is only allowed - * for overflow case) - */ - if ((tseq = is->last_link_seqno) >= sqno) { - int range = is->range; - if (tseq + 1024 < range + sqno) /* redundancy check .. not MP conform */ - printk(KERN_WARNING "isdn_ppp_receive, MP, detected overflow with sqno: %ld, last: %ld !!!\n", sqno, tseq); - else { - sqno += range; - is->last_link_seqno = sqno; - } - } else { - /* here, we should also add an redundancy check */ - is->last_link_seqno = sqno; - } - - /* - * step over all links to find lowest link number - */ - for (min_sqno = LONG_MAX, lpq = net_dev->queue;;) { - long lls = ippp_table[lpq->ppp_slot]->last_link_seqno; - if (lls >= 0 && lls < min_sqno) - min_sqno = lls; - lpq = lpq->next; - if (lpq == net_dev->queue) - break; - } - - /* - * for the case, that the last frame numbers of all - * links are overflowed: mask/reduce the sequenece number to - * 'normal' numbering. - */ - if (min_sqno >= ippp_table[lpq->ppp_slot]->range) { - int mask = ippp_table[lpq->ppp_slot]->range-1; /* range is power of two, so a mask will do the job */ - isdn_ppp_mask_queue(net_dev, mask); - net_dev->ib.next_num &= mask; - { - struct sqqueue *q = net_dev->ib.sq; - while (q) { - q->sqno_start &= mask; - q->sqno_end &= mask; - } - } - min_sqno &= mask; - for (lpq = net_dev->queue;;) { - if(ippp_table[lpq->ppp_slot]->last_link_seqno >= 0) - ippp_table[lpq->ppp_slot]->last_link_seqno &= mask; - lpq = lpq->next; - if (lpq == net_dev->queue) - break; - } - } - if ((BEbyte & (MP_BEGIN_FRAG | MP_END_FRAG)) != (MP_BEGIN_FRAG | MP_END_FRAG)) { - static int dmes = 0; - if( !dmes ) { - printk(KERN_DEBUG "ippp: trying ;) to fill mp_queue %d .. UNTESTED!!\n", lp->ppp_slot); - dmes = 1; - } - if ((sqno_end = isdn_ppp_fill_mpqueue(net_dev, &skb, BEbyte, &sqno, min_sqno)) < 0) { - net_dev->ib.modify = 1; /* block timeout-timer */ - isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno); - net_dev->ib.modify = 0; - return; /* no packet complete */ - } - } else - sqno_end = sqno; - - if (is->debug & 0x40) - printk(KERN_DEBUG "min_sqno: %ld sqno_end %d next: %ld\n", min_sqno, sqno_end, net_dev->ib.next_num); - - /* - * MP buffer management .. reorders incoming packets .. - * lotsa mem-copies and not heavily tested. - * - * first check whether there is more than one link in the bundle - * then check whether the number is in order - */ - net_dev->ib.modify = 1; /* block timeout-timer */ - if (net_dev->ib.bundled && net_dev->ib.next_num != sqno) { - /* - * packet is not 'in order' - */ - struct sqqueue *q; - - q = (struct sqqueue *) kmalloc(sizeof(struct sqqueue), GFP_ATOMIC); - if (!q) { - net_dev->ib.modify = 0; - printk(KERN_WARNING "ippp/MPPP: Bad! Can't alloc sq node!\n"); - dev_kfree_skb(skb); - return; /* discard */ - } - q->skb = skb; - q->sqno_end = sqno_end; - q->sqno_start = sqno; - q->timer = jiffies + (ISDN_TIMER_1SEC) * 5; /* timeout after 5 seconds */ - - if (!net_dev->ib.sq) { - net_dev->ib.sq = q; - q->next = NULL; - } else { - struct sqqueue *ql = net_dev->ib.sq; - if (ql->sqno_start > q->sqno_start) { - q->next = ql; - net_dev->ib.sq = q; - } else { - while (ql->next && ql->next->sqno_start < q->sqno_start) - ql = ql->next; - q->next = ql->next; - ql->next = q; - } - } - } else { - /* - * packet was 'in order' .. push it higher - */ - net_dev->ib.next_num = sqno_end + 1; - proto = isdn_ppp_strip_proto(skb); - isdn_ppp_push_higher(net_dev, lp, skb, proto); - } - isdn_ppp_cleanup_sqqueue(net_dev, lp, min_sqno); - net_dev->ib.modify = 0; - - } else - isdn_ppp_push_higher(net_dev, lp, skb, proto); - } else -#endif - isdn_ppp_push_higher(net_dev, lp, skb, proto); -} - -/* - * push frame to higher layers - * note: net_dev has to be master net_dev - */ -static void -isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto) -{ - struct net_device *dev = &net_dev->dev; - struct ippp_struct *is = ippp_table[lp->ppp_slot]; - - if (is->debug & 0x10) { - printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto); - isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot); - } - - if(proto == PPP_COMP) { - if(!lp->master) - skb = isdn_ppp_decompress(skb,is,is,proto); - else - skb = isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto); - - if(!skb) { - printk(KERN_DEBUG "ippp: compressed frame discarded!\n"); - return; - } - - proto = isdn_ppp_strip_proto(skb); - if (is->debug & 0x10) { - printk(KERN_DEBUG "RPostDecomp, skb %d %04x\n", (int) skb->len, proto); - isdn_ppp_frame_log("R-Decomp", skb->data, skb->len, 32,is->unit,lp->ppp_slot); - } - } - else if(is->compflags & SC_DECOMP_ON) { /* If decomp is ON */ - if(!lp->master) - isdn_ppp_decompress(skb,is,is,proto); - else - isdn_ppp_decompress(skb,is,ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot],proto); - } - - switch (proto) { - case PPP_IPX: /* untested */ - if (is->debug & 0x20) - printk(KERN_DEBUG "isdn_ppp: IPX\n"); - skb->dev = dev; - skb->mac.raw = skb->data; - skb->protocol = htons(ETH_P_IPX); - break; -#ifdef CONFIG_ISDN_PPP_VJ - case PPP_VJC_UNCOMP: - if (is->debug & 0x20) - printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n"); - 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"); - net_dev->local->stats.rx_dropped++; - dev_kfree_skb(skb); - return; - } -#endif - case PPP_IP: - if (is->debug & 0x20) - printk(KERN_DEBUG "isdn_ppp: IP\n"); - skb->dev = dev; - skb->mac.raw = skb->data; - skb->protocol = htons(ETH_P_IP); - break; - case PPP_VJC_COMP: - if (is->debug & 0x20) - printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n"); -#ifdef CONFIG_ISDN_PPP_VJ - { - struct sk_buff *skb_old = skb; - int pkt_len; - skb = dev_alloc_skb(skb_old->len + 128); - - if (!skb) { - printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); - net_dev->local->stats.rx_dropped++; - dev_kfree_skb(skb_old); - return; - } - skb->dev = dev; - skb_put(skb, skb_old->len + 128); - memcpy(skb->data, skb_old->data, skb_old->len); - skb->mac.raw = skb->data; - pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp, - skb->data, skb_old->len); - dev_kfree_skb(skb_old); - if (pkt_len < 0) { - dev_kfree_skb(skb); - lp->stats.rx_dropped++; - return; - } - skb_trim(skb, pkt_len); - skb->protocol = htons(ETH_P_IP); - } -#else - printk(KERN_INFO "isdn: Ooopsa .. VJ-Compression support not compiled into isdn driver.\n"); - lp->stats.rx_dropped++; - dev_kfree_skb(skb); - return; -#endif - break; - case PPP_CCP: - case PPP_LINK_CCP: - isdn_ppp_receive_ccp(net_dev,lp,skb,proto); - /* Dont pop up ResetReq/Ack stuff to the daemon any - longer - the job is done already */ - if(skb->data[0] == CCP_RESETREQ || - skb->data[0] == CCP_RESETACK) - break; - /* fall through */ - default: - isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */ - dev_kfree_skb(skb); - return; - } - - /* Reset hangup-timer */ - lp->huptimer = 0; -#ifdef CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE - if(!(lp->dw_abc_flags & ISDN_DW_ABC_FLAG_NO_TCP_KEEPALIVE)) - (void)isdn_dw_abc_ip4_keepalive_test(NULL,skb); -#ifdef CONFIG_ISDN_WITH_ABC_CONN_ERROR - lp->dw_abc_bchan_errcnt = 0; -#endif -#endif - netif_rx(skb); - /* net_dev->local->stats.rx_packets++; *//* done in isdn_net.c */ - - return; -} - -/* - * isdn_ppp_skb_push .. - * checks whether we have enough space at the beginning of the SKB - * and allocs a new SKB if necessary - */ -static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len) -{ - struct sk_buff *skb = *skb_p; - - if(skb_headroom(skb) < len) { - struct sk_buff *nskb = skb_realloc_headroom(skb, len); - - if (!nskb) { - printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n"); - dev_kfree_skb(skb); - return NULL; - } - printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len); - dev_kfree_skb(skb); - *skb_p = nskb; - return skb_push(nskb, len); - } - return skb_push(skb,len); -} - - -/* - * send ppp frame .. we expect a PIDCOMPressable proto -- - * (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP) - * - * VJ compression may change skb pointer!!! .. requeue with old - * skb isn't allowed!! - */ - -int -isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct net_device *mdev = ((isdn_net_local *) (netdev->priv))->master; /* get master (for redundancy) */ - isdn_net_local *lp,*mlp; - isdn_net_dev *nd; - unsigned int proto = PPP_IP; /* 0x21 */ - struct ippp_struct *ipt,*ipts; - unsigned long flags; - - if (mdev) - mlp = (isdn_net_local *) (mdev->priv); - else { - mdev = netdev; - mlp = (isdn_net_local *) (netdev->priv); - } - nd = mlp->netdev; /* get master lp */ - ipts = ippp_table[mlp->ppp_slot]; - - if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */ - if (ipts->debug & 0x1) - printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name); - return 1; - } - - switch (ntohs(skb->protocol)) { - case ETH_P_IP: - proto = PPP_IP; - break; - case ETH_P_IPX: - proto = PPP_IPX; /* untested */ - break; - default: - dev_kfree_skb(skb); - printk(KERN_ERR "isdn_ppp: skipped frame with unsupported protocoll: %#x.\n", skb->protocol); - return 0; - } - - lp = nd->queue; /* get lp on top of queue */ - - if (lp->sav_skb) { /* find a non-busy device */ - isdn_net_local *nlp = lp->next; - while (lp->sav_skb) { - if (lp == nlp) - return 1; - nlp = nd->queue = nd->queue->next; - } - lp = nlp; - } - ipt = ippp_table[lp->ppp_slot]; - lp->huptimer = 0; - - /* - * after this line .. requeueing in the device queue is no longer allowed!!! - */ - - /* Pull off the fake header we stuck on earlier to keep - * the fragemntation code happy. - */ - skb_pull(skb,IPPP_MAX_HEADER); - - if (ipt->debug & 0x4) - printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len); - if (ipts->debug & 0x40) - isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot); - -#ifdef CONFIG_ISDN_PPP_VJ - if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */ - struct sk_buff *new_skb; - unsigned short hl; - /* - * we need to reserve enought space in front of - * sk_buff. old call to dev_alloc_skb only reserved - * 16 bytes, now we are looking what the driver want. - */ - hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER; - /* - * Note: hl might still be insufficient because the method - * above does not account for a possibible MPPP slave channel - * which had larger HL header space requirements than the - * master. - */ - new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC); - if (new_skb) { - u_char *buf; - int pktlen; - - skb_reserve(new_skb, hl); - new_skb->dev = skb->dev; - skb_put(new_skb, skb->len); - buf = skb->data; - - pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data, - &buf, !(ipts->pppcfg & SC_NO_TCP_CCID)); - - if (buf != skb->data) { - if (new_skb->data != buf) - printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n"); - dev_kfree_skb(skb); - skb = new_skb; - } else { - dev_kfree_skb(new_skb); - } - - skb_trim(skb, pktlen); - if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) { /* cslip? style -> PPP */ - proto = PPP_VJC_COMP; - skb->data[0] ^= SL_TYPE_COMPRESSED_TCP; - } else { - if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP) - proto = PPP_VJC_UNCOMP; - skb->data[0] = (skb->data[0] & 0x0f) | 0x40; - } - } - } -#endif - - /* - * normal (single link) or bundle compression - */ - if(ipts->compflags & SC_COMP_ON) - skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0); - - if (ipt->debug & 0x24) - printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto); - -#ifdef CONFIG_ISDN_MPP - if (ipt->mpppcfg & SC_MP_PROT) { - /* we get mp_seqno from static isdn_net_local */ - long mp_seqno = ipts->mp_seqno; - ipts->mp_seqno++; - nd->queue = nd->queue->next; - if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) { - unsigned char *data = isdn_ppp_skb_push(&skb, 3); - if(!data) - return 0; - mp_seqno &= 0xfff; - data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf); /* (B)egin & (E)ndbit .. */ - data[1] = mp_seqno & 0xff; - data[2] = proto; /* PID compression */ - } else { - unsigned char *data = isdn_ppp_skb_push(&skb, 5); - if(!data) - return 0; - data[0] = MP_BEGIN_FRAG | MP_END_FRAG; /* (B)egin & (E)ndbit .. */ - data[1] = (mp_seqno >> 16) & 0xff; /* sequence number: 24bit */ - data[2] = (mp_seqno >> 8) & 0xff; - data[3] = (mp_seqno >> 0) & 0xff; - data[4] = proto; /* PID compression */ - } - proto = PPP_MP; /* MP Protocol, 0x003d */ - } -#endif - - /* - * 'link in bundle' compression ... - */ - if(ipt->compflags & SC_LINK_COMP_ON) - skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1); - - if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) { - unsigned char *data = isdn_ppp_skb_push(&skb,1); - if(!data) - return 0; - data[0] = proto & 0xff; - } - else { - unsigned char *data = isdn_ppp_skb_push(&skb,2); - if(!data) - return 0; - data[0] = (proto >> 8) & 0xff; - data[1] = proto & 0xff; - } - if(!(ipt->pppcfg & SC_COMP_AC)) { - unsigned char *data = isdn_ppp_skb_push(&skb,2); - if(!data) - return 0; - data[0] = 0xff; /* All Stations */ - data[1] = 0x03; /* Unnumbered information */ - } - - /* tx-stats are now updated via BSENT-callback */ - - if (ipts->debug & 0x40) { - printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len); - isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot); - } - save_flags(flags); - cli(); - if (isdn_net_send_skb(netdev, lp, skb)) { - if (lp->sav_skb) { /* should never happen as sav_skb are sent with disabled IRQs) */ - printk(KERN_ERR "%s: whoops .. there is another stored skb!\n", netdev->name); - dev_kfree_skb(skb); - } else - lp->sav_skb = skb; - } - restore_flags(flags); - return 0; -} - -#ifdef CONFIG_ISDN_MPP - -/* - * free SQ queue - * ------------- - * Note: We need two queues for MPPP. The SQ queue holds fully (re)assembled frames, - * that can't be delivered, because there is an outstanding earlier frame - */ -static void -isdn_ppp_free_sqqueue(isdn_net_dev * p) -{ - struct sqqueue *q = p->ib.sq; - - p->ib.sq = NULL; - while (q) { - struct sqqueue *qn = q->next; - if (q->skb) - dev_kfree_skb(q->skb); - kfree(q); - q = qn; - } - -} - -/* - * free MP queue - * ------------- - * Note: The MP queue holds all frame fragments of frames, that can't be - * reassembled, because there is at least one missing fragment. - */ -static void -isdn_ppp_free_mpqueue(isdn_net_dev * p) -{ - struct mpqueue *q = p->mp_last; - p->mp_last = NULL; - - while (q) { - struct mpqueue *ql = q->next; - dev_kfree_skb(q->skb); - kfree(q); - q = ql; - } -} - -static int -isdn_ppp_bundle(struct ippp_struct *is, int unit) -{ - char ifn[IFNAMSIZ + 1]; - long flags; - isdn_net_dev *p; - isdn_net_local *lp, - *nlp; - - sprintf(ifn, "ippp%d", unit); - p = isdn_net_findif(ifn); - if (!p) - return -1; - - isdn_timer_ctrl(ISDN_TIMER_IPPP, 1); /* enable timer for ippp/MP */ - - save_flags(flags); - cli(); - - nlp = is->lp; - - lp = p->queue; - p->ib.bundled = 1; - nlp->last = lp->last; - lp->last->next = nlp; - lp->last = nlp; - nlp->next = lp; - p->queue = nlp; - - ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit; -/* maybe also SC_CCP stuff */ - ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg & - (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP); - - ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg & - (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ); -#if 0 - if (ippp_table[nlp->ppp_slot]->mpppcfg != ippp_table[lp->ppp_slot]->mpppcfg) { - printk(KERN_WARNING "isdn_ppp_bundle: different MP options %04x and %04x\n", - ippp_table[nlp->ppp_slot]->mpppcfg, ippp_table[lp->ppp_slot]->mpppcfg); - } -#endif - - restore_flags(flags); - return 0; -} - -/* - * Mask sequence numbers in MP queue - */ -static void -isdn_ppp_mask_queue(isdn_net_dev * dev, long mask) -{ - struct mpqueue *q = dev->mp_last; - while (q) { - q->sqno &= mask; - q = q->next; - } -} - -/* - * put a fragment at the right place into the MP queue - * Also checks, whether this fragment completes a frame. In this case - * the fragments are copied together into one SKB - */ -static int -isdn_ppp_fill_mpqueue(isdn_net_dev * dev, struct sk_buff **skb, int BEbyte, long *sqnop, int min_sqno) -{ - struct mpqueue *qe, - *q1, - *q; - long cnt, - flags; - int pktlen, - sqno_end; - int sqno = *sqnop; - - q1 = (struct mpqueue *) kmalloc(sizeof(struct mpqueue), GFP_ATOMIC); - if (!q1) { - printk(KERN_WARNING "isdn_ppp_fill_mpqueue: Can't alloc struct memory.\n"); - save_flags(flags); - cli(); - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); - return -1; - } - q1->skb = *skb; - q1->sqno = sqno; - q1->BEbyte = BEbyte; - q1->time = jiffies; - - save_flags(flags); - cli(); - - if (!(q = dev->mp_last)) { - dev->mp_last = q1; - q1->next = NULL; - q1->last = NULL; - isdn_ppp_cleanup_mpqueue(dev, min_sqno); /* not necessary */ - restore_flags(flags); - return -1; /* -1 is not an error. Just says, that this fragment hasn't complete a full frame */ - } - for (;;) { /* the faster way would be to step from the queue-end to the start */ - if (sqno > q->sqno) { - if (q->next) { - q = q->next; - continue; - } - q->next = q1; - q1->next = NULL; - q1->last = q; - break; - } - if (sqno == q->sqno) - printk(KERN_WARNING "isdn_fill_mpqueue: illegal sqno received!!\n"); - q1->last = q->last; - q1->next = q; - if (q->last) { - q->last->next = q1; - } else - dev->mp_last = q1; - q->last = q1; - break; - } - -/* now we check whether we completed a packet with this fragment */ - pktlen = -q1->skb->len; - q = q1; - cnt = q1->sqno; - while (!(q->BEbyte & MP_END_FRAG)) { - cnt++; - if (!(q->next) || q->next->sqno != cnt) { - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); - return -1; - } - pktlen += q->skb->len; - q = q->next; - } - pktlen += q->skb->len; - qe = q; - - q = q1; - cnt = q1->sqno; - while (!(q->BEbyte & MP_BEGIN_FRAG)) { - cnt--; - if (!(q->last) || q->last->sqno != cnt) { - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); - return -1; - } - pktlen += q->skb->len; - q = q->last; - } - pktlen += q->skb->len; - - if (q->last) - q->last->next = qe->next; - else - dev->mp_last = qe->next; - - if (qe->next) - qe->next->last = q->last; - qe->next = NULL; - sqno_end = qe->sqno; - *sqnop = q->sqno; - - isdn_ppp_cleanup_mpqueue(dev, min_sqno); - restore_flags(flags); - - *skb = dev_alloc_skb(pktlen + 40); /* not needed: +40 for VJ compression .. */ - - if (!(*skb)) { - while (q) { - struct mpqueue *ql = q->next; - dev_kfree_skb(q->skb); - kfree(q); - q = ql; - } - return -2; - } - cnt = 0; - skb_put(*skb, pktlen); - while (q) { - struct mpqueue *ql = q->next; - memcpy((*skb)->data + cnt, q->skb->data, q->skb->len); - cnt += q->skb->len; - dev_kfree_skb(q->skb); - kfree(q); - q = ql; - } - - return sqno_end; -} - -/* - * check sq-queue, whether we have still buffered the next packet(s) - * or packets with a sqno less or equal to min_sqno - * net_dev: master netdevice , lp: 'real' local connection - */ -static void -isdn_ppp_cleanup_sqqueue(isdn_net_dev * net_dev, isdn_net_local * lp, long min_sqno) -{ - struct sqqueue *q; - - while ((q = net_dev->ib.sq) && (q->sqno_start == net_dev->ib.next_num || q->sqno_end <= min_sqno)) { - int proto; - if (q->sqno_start != net_dev->ib.next_num) { - printk(KERN_DEBUG "ippp: MP, stepping over missing frame: %ld\n", net_dev->ib.next_num); -#ifdef CONFIG_ISDN_PPP_VJ - slhc_toss(ippp_table[net_dev->local->ppp_slot]->slcomp); -#endif - } - proto = isdn_ppp_strip_proto(q->skb); - isdn_ppp_push_higher(net_dev, lp, q->skb, proto); - net_dev->ib.sq = q->next; - net_dev->ib.next_num = q->sqno_end + 1; - kfree(q); - } -} - -/* - * remove stale packets from list - */ -static void -isdn_ppp_cleanup_mpqueue(isdn_net_dev * dev, long min_sqno) -{ -#ifdef CONFIG_ISDN_PPP_VJ - int toss = 0; -#endif -/* z.z einfaches aussortieren gammeliger pakete. Fuer die Zukunft: - eventuell, solange vorne kein B-paket ist und sqno<=min_sqno: auch rauswerfen - wenn sqnomp_last; - while(q && (q->sqno < min_sqno) ) { - if ( (q->BEbyte & MP_END_FRAG) || - (q->next && (q->next->sqno <= min_sqno) && (q->next->BEbyte & MP_BEGIN_FRAG)) ) { - printk(KERN_DEBUG "ippp: freeing stale packet(s), min_sq: %ld!\n",min_sqno); - if ((dev->mp_last = q->next)) - q->next->last = NULL; - while (q) { - ql = q->last; - printk(KERN_DEBUG "ippp, freeing packet with sqno: %ld\n",q->sqno); - dev_kfree_skb(q->skb); - kfree(q); -#ifdef CONFIG_ISDN_PPP_VJ - toss = 1; -#endif - q = ql; - } - q = dev->mp_last; - } else - q = q->next; - } -#ifdef CONFIG_ISDN_PPP_VJ - /* did we free a stale frame ? */ - if (toss) - slhc_toss(ippp_table[dev->local->ppp_slot]->slcomp); -#endif -} -#endif - -/* - * a buffered packet timed-out? - */ -void -isdn_ppp_timer_timeout(void) -{ -#ifdef CONFIG_ISDN_MPP - isdn_net_dev *net_dev = dev->netdev; - struct sqqueue *q, - *ql = NULL, - *qn; - - while (net_dev) { - isdn_net_local *lp = net_dev->local; - if (net_dev->ib.modify || lp->master) { /* interface locked or slave? */ - net_dev = net_dev->next; - continue; - } - q = net_dev->ib.sq; - while (q) { - if (q->sqno_start == net_dev->ib.next_num || q->timer < jiffies) { - -#ifdef CONFIG_ISDN_PPP_VJ - /* did we step over a missing frame ? */ - if (q->sqno_start != net_dev->ib.next_num) - slhc_toss(ippp_table[lp->ppp_slot]->slcomp); -#endif - - ql = net_dev->ib.sq; - net_dev->ib.sq = q->next; - net_dev->ib.next_num = q->sqno_end + 1; - q->next = NULL; - for (; ql;) { - int proto = isdn_ppp_strip_proto(ql->skb); - isdn_ppp_push_higher(net_dev, lp, ql->skb, proto); - qn = ql->next; - kfree(ql); - ql = qn; - } - q = net_dev->ib.sq; - } else - q = q->next; - } - net_dev = net_dev->next; - } -#endif -} - -/* - * network device ioctl handlers - */ - -static int -isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev) -{ - struct ppp_stats *res, - t; - isdn_net_local *lp = (isdn_net_local *) dev->priv; - int err; - - res = (struct ppp_stats *) ifr->ifr_ifru.ifru_data; - err = verify_area(VERIFY_WRITE, res, sizeof(struct ppp_stats)); - - if (err) - return err; - - /* build a temporary stat struct and copy it to user space */ - - memset(&t, 0, sizeof(struct ppp_stats)); - if (dev->flags & IFF_UP) { - t.p.ppp_ipackets = lp->stats.rx_packets; - t.p.ppp_ierrors = lp->stats.rx_errors; - t.p.ppp_opackets = lp->stats.tx_packets; - t.p.ppp_oerrors = lp->stats.tx_errors; -#ifdef CONFIG_ISDN_PPP_VJ - if (slot >= 0 && ippp_table[slot]->slcomp) { - struct slcompress *slcomp = ippp_table[slot]->slcomp; - t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed; - t.vj.vjs_compressed = slcomp->sls_o_compressed; - t.vj.vjs_searches = slcomp->sls_o_searches; - t.vj.vjs_misses = slcomp->sls_o_misses; - t.vj.vjs_errorin = slcomp->sls_i_error; - t.vj.vjs_tossed = slcomp->sls_i_tossed; - t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed; - t.vj.vjs_compressedin = slcomp->sls_i_compressed; - } -#endif - } - if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT; - return 0; -} - -int -isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - int error=0; - char *r; - 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; - - switch (cmd) { - case SIOCGPPPVER: - r = (char *) ifr->ifr_ifru.ifru_data; - len = strlen(PPP_VERSION) + 1; - if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT; - break; - case SIOCGPPPSTATS: - error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev); - break; - default: - error = -EINVAL; - break; - } - return error; -} - -static int -isdn_ppp_if_get_unit(char *name) -{ - int len, - i, - unit = 0, - deci; - - len = strlen(name); - - if (strncmp("ippp", name, 4) || len > 8) - return -1; - - for (i = 0, deci = 1; i < len; i++, deci *= 10) { - char a = name[len - i - 1]; - if (a >= '0' && a <= '9') - unit += (a - '0') * deci; - else - break; - } - if (!i || len - i != 4) - unit = -1; - - return unit; -} - - -int -isdn_ppp_dial_slave(char *name) -{ -#ifdef CONFIG_ISDN_MPP - isdn_net_dev *ndev; - isdn_net_local *lp; - struct net_device *sdev; - - if (!(ndev = isdn_net_findif(name))) - return 1; - lp = ndev->local; - if (!(lp->flags & ISDN_NET_CONNECTED)) - return 5; - - sdev = lp->slave; - while (sdev) { - isdn_net_local *mlp = (isdn_net_local *) sdev->priv; - if (!(mlp->flags & ISDN_NET_CONNECTED)) - break; - sdev = mlp->slave; - } - if (!sdev) - return 2; - - isdn_net_dial_req((isdn_net_local *) sdev->priv); - return 0; -#else - return -1; -#endif -} - -int -isdn_ppp_hangup_slave(char *name) -{ -#ifdef CONFIG_ISDN_MPP - isdn_net_dev *ndev; - isdn_net_local *lp; - struct net_device *sdev; - - if (!(ndev = isdn_net_findif(name))) - return 1; - lp = ndev->local; - if (!(lp->flags & ISDN_NET_CONNECTED)) - return 5; - - sdev = lp->slave; - while (sdev) { - isdn_net_local *mlp = (isdn_net_local *) sdev->priv; - if ((mlp->flags & ISDN_NET_CONNECTED)) - break; - sdev = mlp->slave; - } - if (!sdev) - return 2; - - isdn_net_hangup(sdev); - return 0; -#else - return -1; -#endif -} - -/* - * PPP compression stuff - */ - - -/* Push an empty CCP Data Frame up to the daemon to wake it up and let it - generate a CCP Reset-Request or tear down CCP altogether */ - -static void isdn_ppp_ccp_kickup(struct ippp_struct *is) -{ - isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot); -} - -/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary, - but absolutely nontrivial. The most abstruse problem we are facing is - that the generation, reception and all the handling of timeouts and - resends including proper request id management should be entirely left - to the (de)compressor, but indeed is not covered by the current API to - the (de)compressor. The API is a prototype version from PPP where only - some (de)compressors have yet been implemented and all of them are - rather simple in their reset handling. Especially, their is only one - outstanding ResetAck at a time with all of them and ResetReq/-Acks do - not have parameters. For this very special case it was sufficient to - just return an error code from the decompressor and have a single - reset() entry to communicate all the necessary information between - the framework and the (de)compressor. Bad enough, LZS is different - (and any other compressor may be different, too). It has multiple - histories (eventually) and needs to Reset each of them independently - and thus uses multiple outstanding Acks and history numbers as an - additional parameter to Reqs/Acks. - All that makes it harder to port the reset state engine into the - kernel because it is not just the same simple one as in (i)pppd but - it must be able to pass additional parameters and have multiple out- - standing Acks. We are trying to achieve the impossible by handling - reset transactions independent by their id. The id MUST change when - the data portion changes, thus any (de)compressor who uses more than - one resettable state must provide and recognize individual ids for - each individual reset transaction. The framework itself does _only_ - differentiate them by id, because it has no other semantics like the - (de)compressor might. - This looks like a major redesign of the interface would be nice, - but I don't have an idea how to do it better. */ - -/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is - getting that lengthy because there is no simple "send-this-frame-out" - function above but every wrapper does a bit different. Hope I guess - correct in this hack... */ - -static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto, - unsigned char code, unsigned char id, - unsigned char *data, int len) -{ - struct sk_buff *skb; - unsigned char *p; - int count, hl; - unsigned long flags; - int cnt = 0; - isdn_net_local *lp = is->lp; - - /* Alloc large enough skb */ - hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen; - skb = alloc_skb(len + hl + 16,GFP_ATOMIC); - if(!skb) { - printk(KERN_WARNING - "ippp: CCP cannot send reset - out of memory\n"); - return; - } - skb_reserve(skb, hl); - - /* We may need to stuff an address and control field first */ - if(!(is->pppcfg & SC_COMP_AC)) { - p = skb_put(skb, 2); - *p++ = 0xff; - *p++ = 0x03; - } - - /* Stuff proto, code, id and length */ - p = skb_put(skb, 6); - *p++ = (proto >> 8); - *p++ = (proto & 0xff); - *p++ = code; - *p++ = id; - cnt = 4 + len; - *p++ = (cnt >> 8); - *p++ = (cnt & 0xff); - - /* Now stuff remaining bytes */ - if(len) { - p = skb_put(skb, len); - memcpy(p, data, len); - } - - /* skb is now ready for xmit */ - printk(KERN_DEBUG "Sending CCP Frame:\n"); - isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot); - - /* Just ripped from isdn_ppp_write. Dunno whether it makes sense, - especially dunno what the sav_skb stuff is good for. */ - - count = skb->len; - save_flags(flags); - cli(); - if ((cnt = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, - 1, skb)) != count) { - if (lp->sav_skb) { - dev_kfree_skb(lp->sav_skb); - printk(KERN_INFO - "isdn_ppp_write: freeing sav_skb (%d,%d)!\n", - cnt, count); - } else - printk(KERN_INFO - "isdn_ppp_write: Can't write PPP frame to LL (%d,%d)!\n", - cnt, count); - lp->sav_skb = skb; - } - restore_flags(flags); -} - -/* Allocate the reset state vector */ -static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is) -{ - struct ippp_ccp_reset *r; - r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL); - if(!r) { - printk(KERN_ERR "ippp_ccp: failed to allocate reset data" - " structure - no mem\n"); - return NULL; - } - memset(r, 0, sizeof(struct ippp_ccp_reset)); - printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r); - is->reset = r; - return r; -} - -/* Destroy the reset state vector. Kill all pending timers first. */ -static void isdn_ppp_ccp_reset_free(struct ippp_struct *is) -{ - unsigned int id; - - printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n", - is->reset); - for(id = 0; id < 256; id++) { - if(is->reset->rs[id]) { - isdn_ppp_ccp_reset_free_state(is, (unsigned char)id); - } - } - kfree(is->reset); - is->reset = NULL; -} - -/* Free a given state and clear everything up for later reallocation */ -static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is, - unsigned char id) -{ - struct ippp_ccp_reset_state *rs; - - if(is->reset->rs[id]) { - printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id); - rs = is->reset->rs[id]; - /* Make sure the kernel will not call back later */ - if(rs->ta) - del_timer(&rs->timer); - is->reset->rs[id] = NULL; - kfree(rs); - } else { - printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id); - } -} - -/* The timer callback function which is called when a ResetReq has timed out, - aka has never been answered by a ResetAck */ -static void isdn_ppp_ccp_timer_callback(unsigned long closure) -{ - struct ippp_ccp_reset_state *rs = - (struct ippp_ccp_reset_state *)closure; - - if(!rs) { - printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n"); - return; - } - if(rs->ta && rs->state == CCPResetSentReq) { - /* We are correct here */ - printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n", - rs->id); - if(!rs->expra) { - /* Hmm, there is no Ack really expected. We can clean - up the state now, it will be reallocated if the - decompressor insists on another reset */ - rs->ta = 0; - isdn_ppp_ccp_reset_free_state(rs->is, rs->id); - return; - } - /* Push it again */ - isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id, - rs->data, rs->dlen); - /* Restart timer */ - rs->timer.expires = jiffies + HZ*5; - add_timer(&rs->timer); - } else { - printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n", - rs->state); - } -} - -/* Allocate a new reset transaction state */ -static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is, - unsigned char id) -{ - struct ippp_ccp_reset_state *rs; - if(is->reset->rs[id]) { - printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n", - id); - return NULL; - } else { - rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL); - if(!rs) - return NULL; - memset(rs, 0, sizeof(struct ippp_ccp_reset_state)); - rs->state = CCPResetIdle; - rs->is = is; - rs->id = id; - rs->timer.data = (unsigned long)rs; - rs->timer.function = isdn_ppp_ccp_timer_callback; - is->reset->rs[id] = rs; - } - return rs; -} - - -/* A decompressor wants a reset with a set of parameters - do what is - necessary to fulfill it */ -static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is, - struct isdn_ppp_resetparams *rp) -{ - struct ippp_ccp_reset_state *rs; - - if(rp->valid) { - /* The decompressor defines parameters by itself */ - if(rp->rsend) { - /* And he wants us to send a request */ - if(!(rp->idval)) { - printk(KERN_ERR "ippp_ccp: decompressor must" - " specify reset id\n"); - return; - } - if(is->reset->rs[rp->id]) { - /* There is already a transaction in existence - for this id. May be still waiting for a - Ack or may be wrong. */ - rs = is->reset->rs[rp->id]; - if(rs->state == CCPResetSentReq && rs->ta) { - printk(KERN_DEBUG "ippp_ccp: reset" - " trans still in progress" - " for id %d\n", rp->id); - } else { - printk(KERN_WARNING "ippp_ccp: reset" - " trans in wrong state %d for" - " id %d\n", rs->state, rp->id); - } - } else { - /* Ok, this is a new transaction */ - printk(KERN_DEBUG "ippp_ccp: new trans for id" - " %d to be started\n", rp->id); - rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id); - if(!rs) { - printk(KERN_ERR "ippp_ccp: out of mem" - " allocing ccp trans\n"); - return; - } - rs->state = CCPResetSentReq; - rs->expra = rp->expra; - if(rp->dtval) { - rs->dlen = rp->dlen; - memcpy(rs->data, rp->data, rp->dlen); - } - /* HACK TODO - add link comp here */ - isdn_ppp_ccp_xmit_reset(is, PPP_CCP, - CCP_RESETREQ, rs->id, - rs->data, rs->dlen); - /* Start the timer */ - rs->timer.expires = jiffies + 5*HZ; - add_timer(&rs->timer); - rs->ta = 1; - } - } else { - printk(KERN_DEBUG "ippp_ccp: no reset sent\n"); - } - } else { - /* The reset params are invalid. The decompressor does not - care about them, so we just send the minimal requests - and increase ids only when an Ack is received for a - given id */ - if(is->reset->rs[is->reset->lastid]) { - /* There is already a transaction in existence - for this id. May be still waiting for a - Ack or may be wrong. */ - rs = is->reset->rs[is->reset->lastid]; - if(rs->state == CCPResetSentReq && rs->ta) { - printk(KERN_DEBUG "ippp_ccp: reset" - " trans still in progress" - " for id %d\n", rp->id); - } else { - printk(KERN_WARNING "ippp_ccp: reset" - " trans in wrong state %d for" - " id %d\n", rs->state, rp->id); - } - } else { - printk(KERN_DEBUG "ippp_ccp: new trans for id" - " %d to be started\n", is->reset->lastid); - rs = isdn_ppp_ccp_reset_alloc_state(is, - is->reset->lastid); - if(!rs) { - printk(KERN_ERR "ippp_ccp: out of mem" - " allocing ccp trans\n"); - return; - } - rs->state = CCPResetSentReq; - /* We always expect an Ack if the decompressor doesnt - know better */ - rs->expra = 1; - rs->dlen = 0; - /* HACK TODO - add link comp here */ - isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ, - rs->id, NULL, 0); - /* Start the timer */ - rs->timer.expires = jiffies + 5*HZ; - add_timer(&rs->timer); - rs->ta = 1; - } - } -} - -/* An Ack was received for this id. This means we stop the timer and clean - up the state prior to calling the decompressors reset routine. */ -static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is, - unsigned char id) -{ - struct ippp_ccp_reset_state *rs = is->reset->rs[id]; - - if(rs) { - if(rs->ta && rs->state == CCPResetSentReq) { - /* Great, we are correct */ - if(!rs->expra) - printk(KERN_DEBUG "ippp_ccp: ResetAck received" - " for id %d but not expected\n", id); - } else { - printk(KERN_INFO "ippp_ccp: ResetAck received out of" - "sync for id %d\n", id); - } - if(rs->ta) { - rs->ta = 0; - del_timer(&rs->timer); - } - isdn_ppp_ccp_reset_free_state(is, id); - } else { - printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id" - " %d\n", id); - } - /* Make sure the simple reset stuff uses a new id next time */ - is->reset->lastid++; -} - -static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master, - int proto) -{ -#ifndef CONFIG_ISDN_CCP - if(proto == PPP_COMP || proto == PPP_LINK_COMP) { - printk(KERN_ERR "isdn_ppp: Ouch! Compression not included!\n"); - dev_kfree_skb(skb); - return NULL; - } - return skb; -#else - void *stat = NULL; - struct isdn_ppp_compressor *ipc = NULL; - struct sk_buff *skb_out; - int len; - struct ippp_struct *ri; - struct isdn_ppp_resetparams rsparm; - unsigned char rsdata[IPPP_RESET_MAXDATABYTES]; - - if(!master) { - /* - * single link decompression - */ - if(!is->link_decompressor) { - printk(KERN_ERR "ippp: no link decompressor defined!\n"); - dev_kfree_skb(skb); - return NULL; - } - if(!is->link_decomp_stat) { - printk(KERN_DEBUG "ippp: no link decompressor data allocated\n"); - dev_kfree_skb(skb); - return NULL; - } - stat = is->link_decomp_stat; - ipc = is->link_decompressor; - ri = is; - } - else { - /* - * 'normal' or bundle-compression - */ - if(!master->decompressor) { - printk(KERN_ERR "ippp: no decompressor defined!\n"); - dev_kfree_skb(skb); - return NULL; - } - if(!master->decomp_stat) { - printk(KERN_DEBUG "ippp: no decompressor data allocated\n"); - dev_kfree_skb(skb); - return NULL; - } - stat = master->decomp_stat; - ipc = master->decompressor; - ri = master; - } - - /* - printk(KERN_DEBUG "ippp: Decompress valid!\n"); - */ - - if((master && proto == PPP_COMP) || (!master && proto == PPP_LINK_COMP) ) { - /* Set up reset params for the decompressor */ - memset(&rsparm, 0, sizeof(rsparm)); - rsparm.data = rsdata; - rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; - -/* !!!HACK,HACK,HACK!!! 2048 is only assumed */ - skb_out = dev_alloc_skb(2048); - len = ipc->decompress(stat,skb,skb_out, &rsparm); - dev_kfree_skb(skb); - if(len <= 0) { - /* Ok, some error */ - switch(len) { - case DECOMP_ERROR: - ri->pppcfg |= SC_DC_ERROR; - printk(KERN_INFO "ippp: decomp wants reset %s params\n", - rsparm.valid ? "with" : "without"); - - isdn_ppp_ccp_reset_trans(ri, &rsparm); - - break; - case DECOMP_FATALERROR: - ri->pppcfg |= SC_DC_FERROR; - /* Kick ipppd to recognize the error */ - isdn_ppp_ccp_kickup(ri); - break; - } - /* Did I see a leak here ? */ - dev_kfree_skb(skb_out); - return NULL; - } - return skb_out; - } - else { - /* - printk(KERN_DEBUG "isdn_ppp: [%d] Calling incomp with this frame!\n",is->unit); - */ - ipc->incomp(stat,skb,proto); - return skb; - } -#endif -} - -/* - * compress a frame - * type=0: normal/bundle compression - * =1: link compression - * returns original skb if we haven't compressed the frame - * and a new skb pointer if we've done it - */ -static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto, - struct ippp_struct *is,struct ippp_struct *master,int type) -{ - int ret; - int new_proto; - struct isdn_ppp_compressor *compressor; - void *stat; - struct sk_buff *skb_out; - -#ifdef CONFIG_ISDN_CCP - /* we do not compress control protocols */ - if(*proto < 0 || *proto > 0x3fff) { -#else - { -#endif - return skb_in; - } - - 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) { - compressor = is->compressor; - stat = is->comp_stat; - } - else { - compressor = master->compressor; - stat = master->comp_stat; - } - new_proto = PPP_COMP; - } - - if(!compressor) { - printk(KERN_ERR "isdn_ppp: No compressor set!\n"); - return skb_in; - } - if(!stat) { - printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n"); - return skb_in; - } - - /* Allow for at least 150 % expansion (for now) */ - skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 + - skb_headroom(skb_in), GFP_ATOMIC); - if(!skb_out) - return skb_in; - skb_reserve(skb_out, skb_headroom(skb_in)); - - ret = (compressor->compress)(stat,skb_in,skb_out,*proto); - if(!ret) { - dev_kfree_skb(skb_out); - return skb_in; - } - - dev_kfree_skb(skb_in); - *proto = new_proto; - return skb_out; -} - -/* - * we received a CCP frame .. - * not a clean solution, but we MUST handle a few cases in the kernel - */ -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 = 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\n"); - isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot); - - if(lp->master) - mis = ippp_table[((isdn_net_local *) (lp->master->priv))->ppp_slot]; - else - mis = is; - - switch(skb->data[0]) { - case CCP_CONFREQ: - case CCP_TERMREQ: - case CCP_TERMACK: - if(is->debug & 0x10) - printk(KERN_DEBUG "Disable (de)compression here!\n"); - if(proto == PPP_CCP) - mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); - else - is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON); - break; - case CCP_CONFACK: - /* if we RECEIVE an ackowledge we enable the decompressor */ - if(is->debug & 0x10) - printk(KERN_DEBUG "Enable decompression here!\n"); - if(proto == PPP_CCP) - mis->compflags |= SC_DECOMP_ON; - else - is->compflags |= SC_LINK_DECOMP_ON; - break; - - case CCP_RESETACK: - printk(KERN_DEBUG "Received ResetAck from peer\n"); - len = (skb->data[2] << 8) | skb->data[3]; - len -= 4; - - if(proto == PPP_CCP) { - /* If a reset Ack was outstanding for this id, then - clean up the state engine */ - isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]); - if(mis->decompressor && mis->decomp_stat) - mis->decompressor-> - reset(mis->decomp_stat, - skb->data[0], - skb->data[1], - len ? &skb->data[4] : NULL, - len, NULL); - /* TODO: This is not easy to decide here */ - mis->compflags &= ~SC_DECOMP_DISCARD; - mis->pppcfg &= ~SC_DC_ERROR; - } - else { - isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]); - if(is->link_decompressor && is->link_decomp_stat) - is->link_decompressor-> - reset(is->link_decomp_stat, - skb->data[0], - skb->data[1], - len ? &skb->data[4] : NULL, - len, NULL); - /* TODO: neither here */ - is->compflags &= ~SC_LINK_DECOMP_DISCARD; - is->pppcfg &= ~SC_DC_ERROR; - } - break; - - case CCP_RESETREQ: - printk(KERN_DEBUG "Received ResetReq from peer\n"); - /* Receiving a ResetReq means we must reset our compressor */ - /* Set up reset params for the reset entry */ - memset(&rsparm, 0, sizeof(rsparm)); - rsparm.data = rsdata; - rsparm.maxdlen = IPPP_RESET_MAXDATABYTES; - /* Isolate data length */ - len = (skb->data[2] << 8) | skb->data[3]; - len -= 4; - if(proto == PPP_CCP) { - if(mis->compressor && mis->comp_stat) - mis->compressor-> - reset(mis->comp_stat, - skb->data[0], - skb->data[1], - len ? &skb->data[4] : NULL, - len, &rsparm); - } - else { - if(is->link_compressor && is->link_comp_stat) - is->link_compressor-> - reset(is->link_comp_stat, - skb->data[0], - skb->data[1], - len ? &skb->data[4] : NULL, - len, &rsparm); - } - /* Ack the Req as specified by rsparm */ - if(rsparm.valid) { - /* Compressor reset handler decided how to answer */ - if(rsparm.rsend) { - /* We should send a Frame */ - isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK, - rsparm.idval ? rsparm.id - : skb->data[1], - rsparm.dtval ? - rsparm.data : NULL, - rsparm.dtval ? - rsparm.dlen : 0); - } else { - printk(KERN_DEBUG "ResetAck suppressed\n"); - } - } else { - /* We answer with a straight reflected Ack */ - isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK, - skb->data[1], - len ? &skb->data[4] : NULL, - len); - } - break; - } -} - - -/* - * Daemon sends a CCP frame ... - */ - -/* TODO: Clean this up with new Reset semantics */ - -static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb) -{ - struct ippp_struct *mis,*is = ippp_table[lp->ppp_slot]; - int proto; - unsigned char *data; - - if(!skb || skb->len < 3) - return; - - /* 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) { - data += 2; - if(skb->len < 5) - return; - } - - proto = ((int)data[0]<<8)+data[1]; - if(proto != PPP_CCP && proto != PPP_LINK_CCP) - return; - - 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) - 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]) { - case CCP_CONFREQ: - case CCP_TERMREQ: - case CCP_TERMACK: - if(is->debug & 0x10) - printk(KERN_DEBUG "Disable (de)compression here!\n"); - if(proto == PPP_CCP) - is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON); - else - is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON); - break; - case CCP_CONFACK: - /* if we SEND an ackowledge we can/must enable the compressor */ - if(is->debug & 0x10) - printk(KERN_DEBUG "Enable compression here!\n"); - if(proto == PPP_CCP) - is->compflags |= SC_COMP_ON; - else - is->compflags |= SC_LINK_COMP_ON; - break; - case CCP_RESETACK: - /* If we send a ACK we should reset our compressor */ - if(is->debug & 0x10) - printk(KERN_DEBUG "Reset decompression state here!\n"); - printk(KERN_DEBUG "ResetAck from daemon passed by\n"); - if(proto == PPP_CCP) { - /* link to master? */ - if(is->compressor && is->comp_stat) - is->compressor->reset(is->comp_stat, 0, 0, - NULL, 0, NULL); - is->compflags &= ~SC_COMP_DISCARD; - } - else { - if(is->link_compressor && is->link_comp_stat) - is->link_compressor->reset(is->link_comp_stat, - 0, 0, NULL, 0, NULL); - is->compflags &= ~SC_LINK_COMP_DISCARD; - } - break; - case CCP_RESETREQ: - /* Just let it pass by */ - printk(KERN_DEBUG "ResetReq from daemon passed by\n"); - break; - } -} - -int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc) -{ - ipc->next = ipc_head; - ipc->prev = NULL; - if(ipc_head) { - ipc_head->prev = ipc; - } - ipc_head = ipc; - return 0; -} - -int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc) -{ - if(ipc->prev) - ipc->prev->next = ipc->next; - else - ipc_head = ipc->next; - if(ipc->next) - ipc->next->prev = ipc->prev; - ipc->prev = ipc->next = NULL; - return 0; -} - -static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data) -{ - struct isdn_ppp_compressor *ipc = ipc_head; - int ret; - void *stat; - int num = data->num; - - if(is->debug & 0x10) - printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit, - (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num); - - /* If is has no valid reset state vector, we cannot allocate a - decompressor. The decompressor would cause reset transactions - sooner or later, and they need that vector. */ - - if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) { - printk(KERN_ERR "ippp_ccp: no reset data structure - can't" - " allow decompression.\n"); - return -ENOMEM; - } - - while(ipc) { - if(ipc->num == num) { - stat = ipc->alloc(data); - if(stat) { - ret = ipc->init(stat,data,is->unit,0); - if(!ret) { - printk(KERN_ERR "Can't init (de)compression!\n"); - ipc->free(stat); - stat = NULL; - break; - } - } - else { - printk(KERN_ERR "Can't alloc (de)compression!\n"); - break; - } - - if(data->flags & IPPP_COMP_FLAG_XMIT) { - if(data->flags & IPPP_COMP_FLAG_LINK) { - if(is->link_comp_stat) - is->link_compressor->free(is->link_comp_stat); - is->link_comp_stat = stat; - is->link_compressor = ipc; - } - else { - if(is->comp_stat) - is->compressor->free(is->comp_stat); - is->comp_stat = stat; - is->compressor = ipc; - } - } - else { - if(data->flags & IPPP_COMP_FLAG_LINK) { - if(is->link_decomp_stat) - is->link_decompressor->free(is->link_decomp_stat); - is->link_decomp_stat = stat; - is->link_decompressor = ipc; - } - else { - if(is->decomp_stat) - is->decompressor->free(is->decomp_stat); - is->decomp_stat = stat; - is->decompressor = ipc; - } - } - return 0; - } - ipc = ipc->next; - } - return -EINVAL; -} diff --git a/drivers/isdn/isdn_ppp.h b/drivers/isdn/isdn_ppp.h deleted file mode 100644 index 6a373854..00000000 --- a/drivers/isdn/isdn_ppp.h +++ /dev/null @@ -1,101 +0,0 @@ -/* $Id$ - - * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel). - * - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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. - * - * $Log$ - * Revision 1.13 1998/03/22 18:50:50 hipp - * Added BSD Compression for syncPPP .. UNTESTED at the moment - * - * Revision 1.12 1998/01/31 22:07:48 keil - * changes for newer kernels - * - * Revision 1.11 1997/10/01 09:20:44 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.10 1997/06/17 13:06:00 hipp - * Applied Eric's underflow-patches (slightly modified) - * more compression changes (but disabled at the moment) - * changed one copy_to_user() to run with enabled IRQs - * a few MP changes - * changed 'proto' handling in the isdn_ppp receive code - * - * Revision 1.9 1997/02/11 18:32:59 fritz - * Bugfix in isdn_ppp_free_mpqueue(). - * - * Revision 1.8 1997/02/10 10:11:33 fritz - * More changes for Kernel 2.1.X compatibility. - * - * Revision 1.7 1997/02/03 23:18:57 fritz - * Removed isdn_ppp_free_sqqueue prototype - * and ippp_table (both static in isdn_ppp.c). - * - * Revision 1.6 1996/09/23 01:58:11 fritz - * Fix: With syncPPP encapsulation, discard LCP packets - * when calculating hangup timeout. - * - * Revision 1.5 1996/09/07 12:51:34 hipp - * *** empty log message *** - * - * Revision 1.4 1996/05/06 11:34:56 hipp - * fixed a few bugs - * - * Revision 1.3 1996/04/30 09:33:10 fritz - * Removed compatibility-macros. - * - * Revision 1.2 1996/04/20 16:35:11 fritz - * Changed isdn_ppp_receive to use sk_buff as parameter. - * Added definition of isdn_ppp_dial_slave and ippp_table. - * - * Revision 1.1 1996/01/10 21:39:10 fritz - * Initial revision - * - */ - -#include /* for PPP_PROTOCOL */ -extern void isdn_ppp_timer_timeout(void); -extern int isdn_ppp_read(int, struct file *, char *, int); -extern int isdn_ppp_write(int, struct file *, const char *, int); -extern int isdn_ppp_open(int, struct file *); -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_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); -extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *); -extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long); -extern void isdn_ppp_release(int, struct file *); -extern int isdn_ppp_dial_slave(char *); -extern void isdn_ppp_wakeup_daemon(isdn_net_local *); - -extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc); -extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc); - -#define IPPP_OPEN 0x01 -#define IPPP_CONNECT 0x02 -#define IPPP_CLOSEWAIT 0x04 -#define IPPP_NOBLOCK 0x08 -#define IPPP_ASSIGNED 0x10 - -#define IPPP_MAX_HEADER 10 - - diff --git a/drivers/isdn/isdn_tty.c b/drivers/isdn/isdn_tty.c deleted file mode 100644 index e1a0bce7..00000000 --- a/drivers/isdn/isdn_tty.c +++ /dev/null @@ -1,4395 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel). - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg - * - * 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. - * - * $Log$ - * Revision 1.83 2000/02/16 14:59:33 paul - * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers; - * used defines for result codes; - * fixed RING ... RUNG problem (no empty lines in between). - * - * Revision 1.82 2000/01/23 18:45:37 keil - * Change EAZ mapping to forbit the use of cards (insert a "-" for the MSN) - * - * Revision 1.81 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.80 1999/11/07 13:34:30 armin - * Fixed AT command line editor - * - * Revision 1.79 1999/10/29 18:35:08 armin - * Check number len in isdn_get_msnstr() to avoid buffer overflow. - * - * Revision 1.78 1999/10/28 23:03:51 armin - * Bugfix: now freeing channel on modem_hup() even when - * usage on ttyI has changed and error-report for - * AT-commands on wrong channel-state. - * - * Revision 1.77 1999/10/26 21:13:14 armin - * using define for checking phone number len in isdn_tty_getdial() - * - * Revision 1.76 1999/10/11 22:16:26 keil - * Suspend/Resume is possible without explicit ID too - * - * Revision 1.75 1999/10/08 18:59:32 armin - * Bugfix of too small MSN buffer and checking phone number - * in isdn_tty_getdial() - * - * Revision 1.74 1999/09/04 06:20:04 keil - * Changes from kernel set_current_state() - * - * Revision 1.73 1999/08/28 21:56:27 keil - * misplaced #endif caused ttyI crash in 2.3.X - * - * Revision 1.72 1999/07/31 12:59:45 armin - * Added tty fax capabilities. - * - * Revision 1.71 1999/07/27 10:34:34 armin - * Fixed last change. Did not compile with AUDIO support off. - * - * Revision 1.70 1999/07/25 16:17:58 keil - * Fix Suspend/Resume - * - * Revision 1.69 1999/07/25 12:56:15 armin - * isdn_tty_at_cout() now queues the message if online and - * data is in queue or flip buffer is full. - * needed for fax connections. - * - * Revision 1.68 1999/07/11 17:51:51 armin - * Bugfix, "-" was missing for AT&L settings. - * - * Revision 1.67 1999/07/11 17:14:12 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.66 1999/07/07 10:13:46 detabc - * remove unused messages - * - * Revision 1.65 1999/07/04 21:01:59 werner - * Added support for keypad and display (ported from 2.0) - * - * Revision 1.64 1999/07/01 08:30:00 keil - * compatibility to 2.3 kernel - * - * Revision 1.63 1999/04/12 12:33:39 fritz - * Changes from 2.0 tree. - * - * Revision 1.62 1999/03/02 12:04:48 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.61 1999/01/27 22:53:11 he - * minor updates (spellings, jiffies wrap around in isdn_tty) - * - * Revision 1.60 1998/11/15 23:57:32 keil - * changes for 2.1.127 - * - * Revision 1.59 1998/08/20 13:50:15 keil - * More support for hybrid modem (not working yet) - * - * Revision 1.58 1998/07/26 18:48:45 armin - * Added silence detection in voice receive mode. - * - * Revision 1.57 1998/06/26 15:12:36 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.56 1998/06/18 23:31:51 fritz - * Replaced cli()/restore_flags() in isdn_tty_write() by locking. - * Removed direct-senddown feature in isdn_tty_write because it will - * never succeed with locking and is useless anyway. - * - * Revision 1.55 1998/06/17 19:50:55 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * - * - * Revision 1.52 1998/03/19 13:18:21 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * - * Revision 1.49 1998/03/08 00:01:59 fritz - * Bugfix: Lowlevel module usage and channel usage were not - * reset on NO DCHANNEL. - * - * Revision 1.48 1998/03/07 12:28:15 tsbogend - * fixed kernel unaligned traps on Linux/Alpha - * - * Revision 1.47 1998/02/22 19:44:14 fritz - * Bugfixes and improvements regarding V.110, V.110 now running. - * - * Revision 1.46 1998/02/20 17:23:08 fritz - * Changes for recent kernels. - * Merged in contributions by Thomas Pfeiffer (V.110 T.70+ Extended FAX stuff) - * Added symbolic constants for Modem-Registers. - * - * Revision 1.45 1998/01/31 22:07:49 keil - * changes for newer kernels - * - * Revision 1.44 1998/01/31 19:30:02 calle - * Merged changes from and for 2.1.82, not tested only compiled ... - * - * Revision 1.43 1997/10/09 21:29:04 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.42 1997/10/01 09:20:49 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.41 1997/05/27 15:17:31 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.40 1997/03/24 22:55:27 fritz - * Added debug code for status callbacks. - * - * Revision 1.39 1997/03/21 18:25:56 fritz - * Corrected CTS handling. - * - * Revision 1.38 1997/03/07 12:13:35 fritz - * Bugfix: Send audio in adpcm format was broken. - * Bugfix: CTS handling was wrong. - * - * Revision 1.37 1997/03/07 01:37:34 fritz - * Bugfix: Did not compile with CONFIG_ISDN_AUDIO disabled. - * Bugfix: isdn_tty_tint() did not handle lowlevel errors correctly. - * Bugfix: conversion was wrong when sending ulaw audio. - * Added proper ifdef's for CONFIG_ISDN_AUDIO - * - * Revision 1.36 1997/03/04 21:41:55 fritz - * Fix: Excessive stack usage of isdn_tty_senddown() - * and isdn_tty_end_vrx() could lead to problems. - * - * Revision 1.35 1997/03/02 19:05:52 fritz - * Bugfix: Avoid recursion. - * - * Revision 1.34 1997/03/02 14:29:22 fritz - * More ttyI related cleanup. - * - * Revision 1.33 1997/02/28 02:32:45 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.32 1997/02/23 15:43:03 fritz - * Small change in handling of incoming calls - * documented in newest version of ttyI.4 - * - * Revision 1.31 1997/02/21 13:05:57 fritz - * Bugfix: Remote hangup did not set location-info on ttyI's - * - * Revision 1.30 1997/02/18 09:41:05 fritz - * Added support for bitwise access to modem registers (ATSx.y=n, ATSx.y?). - * Beautified output of AT&V. - * - * Revision 1.29 1997/02/16 12:11:51 fritz - * Added S13,Bit4 option. - * - * Revision 1.28 1997/02/10 22:07:08 fritz - * Added 2 modem registers for numbering plan and screening info. - * - * Revision 1.27 1997/02/10 21:31:14 fritz - * Changed setup-interface (incoming and outgoing). - * - * Revision 1.26 1997/02/10 20:12:48 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.25 1997/02/03 23:04:30 fritz - * Reformatted according CodingStyle. - * skb->free stuff replaced by macro. - * Finished full-duplex audio. - * - * Revision 1.24 1997/01/14 01:32:42 fritz - * Changed audio receive not to rely on skb->users and skb->lock. - * Added ATI2 and related variables. - * Started adding full-duplex audio capability. - * - * Revision 1.23 1996/10/22 23:14:02 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.22 1996/10/19 18:56:43 fritz - * ATZ did not change the xmitbuf size. - * - * Revision 1.21 1996/06/24 17:40:28 fritz - * Bugfix: Did not compile without CONFIG_ISDN_AUDIO - * - * Revision 1.20 1996/06/15 14:59:39 fritz - * Fixed isdn_tty_tint() to handle partially sent - * sk_buffs. - * - * Revision 1.19 1996/06/12 15:53:56 fritz - * Bugfix: AT+VTX and AT+VRX could be executed without - * having a connection. - * Missing check for NULL tty in isdn_tty_flush_buffer(). - * - * Revision 1.18 1996/06/07 11:17:33 tsbogend - * added missing #ifdef CONFIG_ISDN_AUDIO to make compiling without - * audio support possible - * - * Revision 1.17 1996/06/06 14:55:47 fritz - * Changed to support DTMF decoding on audio playback also. - * Bugfix: Added check for invalid info->isdn_driver in - * isdn_tty_senddown(). - * Clear ncarrier flag on last close() of a tty. - * - * Revision 1.16 1996/06/05 02:24:12 fritz - * Added DTMF decoder for audio mode. - * - * Revision 1.15 1996/06/03 20:35:01 fritz - * Fixed typos. - * - * Revision 1.14 1996/06/03 20:12:19 fritz - * Fixed typos. - * Added call to write_wakeup via isdn_tty_flush_buffer() - * in isdn_tty_modem_hup(). - * - * Revision 1.13 1996/05/31 01:33:29 fritz - * Changed buffering due to bad performance with mgetty. - * Now sk_buff is delayed allocated in isdn_tty_senddown - * using xmit_buff like in standard serial driver. - * Fixed module locking. - * Added DLE-DC4 handling in voice mode. - * - * Revision 1.12 1996/05/19 01:34:40 fritz - * Bugfix: ATS returned error. - * Register 20 made readonly. - * - * Revision 1.11 1996/05/18 01:37:03 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.10 1996/05/17 03:51:49 fritz - * Changed DLE handling for audio receive. - * - * Revision 1.9 1996/05/11 21:52:07 fritz - * Changed queue management to use sk_buffs. - * - * Revision 1.8 1996/05/10 08:49:43 fritz - * Checkin before major changes of tty-code. - * - * Revision 1.7 1996/05/07 09:15:09 fritz - * Reorganized and general cleanup. - * Bugfixes: - * - Audio-transmit working now. - * - "NO CARRIER" now reported, when hanging up with DTR low. - * - Corrected CTS handling. - * - * Revision 1.6 1996/05/02 03:59:25 fritz - * Bugfixes: - * - On dialout, layer-2 setup had been incomplete - * when using new auto-layer2 feature. - * - On hangup, "NO CARRIER" message sometimes missing. - * - * Revision 1.5 1996/04/30 21:05:25 fritz - * Test commit - * - * Revision 1.4 1996/04/20 16:39:54 fritz - * Changed all io to go through generic routines in isdn_common.c - * Fixed a real ugly bug in modem-emulator: 'ATA' had been accepted - * even when a call has been cancelled from the remote machine. - * - * Revision 1.3 1996/02/11 02:12:32 fritz - * Bugfixes according to similar fixes in standard serial.c of kernel. - * - * Revision 1.2 1996/01/22 05:12:25 fritz - * replaced my_atoi by simple_strtoul - * - * Revision 1.1 1996/01/09 04:13:18 fritz - * Initial revision - * - */ -#undef ISDN_TTY_STAT_DEBUG - -#define __NO_VERSION__ -#include -#include -#include -#include "isdn_common.h" -#include "isdn_tty.h" -#ifdef CONFIG_ISDN_AUDIO -#include "isdn_audio.h" -#define VBUF 0x3e0 -#define VBUFX (VBUF/16) -#endif - -#define FIX_FILE_TRANSFER -#define DUMMY_HAYES_AT - -/* Prototypes */ - -static int isdn_tty_edit_at(const char *, int, modem_info *, int); -static void isdn_tty_check_esc(const u_char *, u_char, int, int *, int *, int); -static void isdn_tty_modem_reset_regs(modem_info *, int); -static void isdn_tty_cmd_ATA(modem_info *); -static void isdn_tty_flush_buffer(struct tty_struct *); -static void isdn_tty_modem_result(int, modem_info *); -#ifdef CONFIG_ISDN_AUDIO -static int isdn_tty_countDLE(unsigned char *, int); -#endif - -/* Leave this unchanged unless you know what you do! */ -#define MODEM_PARANOIA_CHECK -#define MODEM_DO_RESTART - -static char *isdn_ttyname_ttyI = "ttyI"; -static char *isdn_ttyname_cui = "cui"; -static int bit2si[8] = -{1, 5, 7, 7, 7, 7, 7, 7}; -static int si2bit[8] = -{4, 1, 4, 4, 4, 4, 4, 4}; - -char *isdn_tty_revision = "$Revision$"; - - -/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb() - * to stuff incoming data directly into a tty's flip-buffer. This - * is done to speed up tty-receiving if the receive-queue is empty. - * This routine MUST be called with interrupts off. - * Return: - * 1 = Success - * 0 = Failure, data has to be buffered and later processed by - * isdn_tty_readmodem(). - */ -static int -isdn_tty_try_read(modem_info * info, struct sk_buff *skb) -{ - int c; - int len; - struct tty_struct *tty; - - if (info->online) { - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - c = TTY_FLIPBUF_SIZE - tty->flip.count; - len = skb->len -#ifdef CONFIG_ISDN_AUDIO - + ISDN_AUDIO_SKB_DLECOUNT(skb) -#endif - ; - if (c >= len) { -#ifdef CONFIG_ISDN_AUDIO - if (ISDN_AUDIO_SKB_DLECOUNT(skb)) - while (skb->len--) { - if (*skb->data == DLE) - tty_insert_flip_char(tty, DLE, 0); - tty_insert_flip_char(tty, *skb->data++, 0); - } else { -#endif - memcpy(tty->flip.char_buf_ptr, - skb->data, len); - tty->flip.count += len; - tty->flip.char_buf_ptr += len; - memset(tty->flip.flag_buf_ptr, 0, len); - tty->flip.flag_buf_ptr += len; -#ifdef CONFIG_ISDN_AUDIO - } -#endif - if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP) - tty->flip.flag_buf_ptr[len - 1] = 0xff; - queue_task(&tty->flip.tqueue, &tq_timer); - kfree_skb(skb); - return 1; - } - } - } - } - return 0; -} - -/* isdn_tty_readmodem() is called periodically from within timer-interrupt. - * It tries getting received data from the receive queue an stuff it into - * the tty's flip-buffer. - */ -void -isdn_tty_readmodem(void) -{ - int resched = 0; - int midx; - int i; - int c; - int r; - ulong flags; - struct tty_struct *tty; - modem_info *info; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - if ((midx = dev->m_idx[i]) >= 0) { - info = &dev->mdm.info[midx]; - if (info->online) { - r = 0; -#ifdef CONFIG_ISDN_AUDIO - isdn_audio_eval_dtmf(info); - if ((info->vonline & 1) && (info->emu.vpar[1])) - isdn_audio_eval_silence(info); -#endif - if ((tty = info->tty)) { - if (info->mcr & UART_MCR_RTS) { - c = TTY_FLIPBUF_SIZE - tty->flip.count; - if (c > 0) { - save_flags(flags); - cli(); - r = isdn_readbchan(info->isdn_driver, info->isdn_channel, - tty->flip.char_buf_ptr, - tty->flip.flag_buf_ptr, c, 0); - /* CISCO AsyncPPP Hack */ - if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP)) - memset(tty->flip.flag_buf_ptr, 0, r); - tty->flip.count += r; - tty->flip.flag_buf_ptr += r; - tty->flip.char_buf_ptr += r; - if (r) - queue_task(&tty->flip.tqueue, &tq_timer); - restore_flags(flags); - } - } else - r = 1; - } else - r = 1; - if (r) { - info->rcvsched = 0; - resched = 1; - } else - info->rcvsched = 1; - } - } - } - if (!resched) - isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0); -} - -int -isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb) -{ - ulong flags; - int midx; -#ifdef CONFIG_ISDN_AUDIO - int ifmt; -#endif - modem_info *info; - - if ((midx = dev->m_idx[i]) < 0) { - /* if midx is invalid, packet is not for tty */ - return 0; - } - info = &dev->mdm.info[midx]; -#ifdef CONFIG_ISDN_AUDIO - ifmt = 1; - - if ((info->vonline) && (!info->emu.vpar[4])) - isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt); - if ((info->vonline & 1) && (info->emu.vpar[1])) - isdn_audio_calc_silence(info, skb->data, skb->len, ifmt); -#endif - if ((info->online < 2) -#ifdef CONFIG_ISDN_AUDIO - && (!(info->vonline & 1)) -#endif - ) { - /* If Modem not listening, drop data */ - kfree_skb(skb); - return 1; - } - if (info->emu.mdmreg[REG_T70] & BIT_T70) { - if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT) { - /* T.70 decoding: throw away the T.70 header (2 or 4 bytes) */ - if (skb->data[0] == 3) /* pure data packet -> 4 byte headers */ - skb_pull(skb, 4); - else - if (skb->data[0] == 1) /* keepalive packet -> 2 byte hdr */ - skb_pull(skb, 2); - } else - /* T.70 decoding: Simply throw away the T.70 header (4 bytes) */ - if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1))) - skb_pull(skb, 4); - } -#ifdef CONFIG_ISDN_AUDIO - if (skb_headroom(skb) < sizeof(isdn_audio_skb)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return 1; - } - ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; - ISDN_AUDIO_SKB_LOCK(skb) = 0; - if (info->vonline & 1) { - /* voice conversion/compression */ - switch (info->emu.vpar[3]) { - case 2: - case 3: - case 4: - /* adpcm - * Since compressed data takes less - * space, we can overwrite the buffer. - */ - skb_trim(skb, isdn_audio_xlaw2adpcm(info->adpcmr, - ifmt, - skb->data, - skb->data, - skb->len)); - break; - case 5: - /* a-law */ - if (!ifmt) - isdn_audio_ulaw2alaw(skb->data, skb->len); - break; - case 6: - /* u-law */ - if (ifmt) - isdn_audio_alaw2ulaw(skb->data, skb->len); - break; - } - ISDN_AUDIO_SKB_DLECOUNT(skb) = - isdn_tty_countDLE(skb->data, skb->len); - } -#ifdef CONFIG_ISDN_TTY_FAX - else { - if (info->faxonline & 2) { - isdn_tty_fax_bitorder(info, skb); - ISDN_AUDIO_SKB_DLECOUNT(skb) = - isdn_tty_countDLE(skb->data, skb->len); - } - } -#endif -#endif - /* Try to deliver directly via tty-flip-buf if queue is empty */ - save_flags(flags); - cli(); - if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) - if (isdn_tty_try_read(info, skb)) { - restore_flags(flags); - return 1; - } - /* Direct deliver failed or queue wasn't empty. - * Queue up for later dequeueing via timer-irq. - */ - __skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb); - dev->drv[di]->rcvcount[channel] += - (skb->len -#ifdef CONFIG_ISDN_AUDIO - + ISDN_AUDIO_SKB_DLECOUNT(skb) -#endif - ); - restore_flags(flags); - /* Schedule dequeuing */ - if ((dev->modempoll) && (info->rcvsched)) - isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); - return 1; -} - -void -isdn_tty_cleanup_xmit(modem_info * info) -{ - struct sk_buff *skb; - unsigned long flags; - - save_flags(flags); - cli(); - if (skb_queue_len(&info->xmit_queue)) - while ((skb = skb_dequeue(&info->xmit_queue))) - kfree_skb(skb); -#ifdef CONFIG_ISDN_AUDIO - if (skb_queue_len(&info->dtmf_queue)) - while ((skb = skb_dequeue(&info->dtmf_queue))) - kfree_skb(skb); -#endif - restore_flags(flags); -} - -static void -isdn_tty_tint(modem_info * info) -{ - struct sk_buff *skb = skb_dequeue(&info->xmit_queue); - int len, - slen; - - if (!skb) - return; - len = skb->len; - if ((slen = isdn_writebuf_skb_stub(info->isdn_driver, - info->isdn_channel, 1, skb)) == len) { - struct tty_struct *tty = info->tty; - info->send_outstanding++; - info->msr &= ~UART_MSR_CTS; - info->lsr &= ~UART_LSR_TEMT; - 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) { - /* Error: no channel, already shutdown, or wrong parameter */ - dev_kfree_skb(skb); - return; - } - skb_queue_head(&info->xmit_queue, skb); -} - -#ifdef CONFIG_ISDN_AUDIO -static int -isdn_tty_countDLE(unsigned char *buf, int len) -{ - int count = 0; - - while (len--) - if (*buf++ == DLE) - count++; - return count; -} - -/* This routine is called from within isdn_tty_write() to perform - * DLE-decoding when sending audio-data. - */ -static int -isdn_tty_handleDLEdown(modem_info * info, atemu * m, int len) -{ - unsigned char *p = &info->xmit_buf[info->xmit_count]; - int count = 0; - - while (len > 0) { - if (m->lastDLE) { - m->lastDLE = 0; - switch (*p) { - case DLE: - /* Escape code */ - if (len > 1) - memmove(p, p + 1, len - 1); - p--; - count++; - break; - case ETX: - /* End of data */ - info->vonline |= 4; - return count; - case DC4: - /* Abort RX */ - info->vonline &= ~1; -#ifdef ISDN_DEBUG_MODEM_VOICE - printk(KERN_DEBUG - "DLEdown: got DLE-DC4, send DLE-ETX on ttyI%d\n", - info->line); -#endif - isdn_tty_at_cout("\020\003", info); - if (!info->vonline) { -#ifdef ISDN_DEBUG_MODEM_VOICE - printk(KERN_DEBUG - "DLEdown: send VCON on ttyI%d\n", - info->line); -#endif - isdn_tty_at_cout("\r\nVCON\r\n", info); - } - /* Fall through */ - case 'q': - case 's': - /* Silence */ - if (len > 1) - memmove(p, p + 1, len - 1); - p--; - break; - } - } else { - if (*p == DLE) - m->lastDLE = 1; - else - count++; - } - p++; - len--; - } - if (len < 0) { - printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n"); - return 0; - } - return count; -} - -/* This routine is called from within isdn_tty_write() when receiving - * audio-data. It interrupts receiving, if an character other than - * ^S or ^Q is sent. - */ -static int -isdn_tty_end_vrx(const char *buf, int c, int from_user) -{ - char ch; - - while (c--) { - if (from_user) - get_user(ch, buf); - else - ch = *buf; - if ((ch != 0x11) && (ch != 0x13)) - return 1; - buf++; - } - return 0; -} - -static int voice_cf[7] = -{0, 0, 4, 3, 2, 0, 0}; - -#endif /* CONFIG_ISDN_AUDIO */ - -/* isdn_tty_senddown() is called either directly from within isdn_tty_write() - * or via timer-interrupt from within isdn_tty_modem_xmit(). It pulls - * outgoing data from the tty's xmit-buffer, handles voice-decompression or - * T.70 if necessary, and finally queues it up for sending via isdn_tty_tint. - */ -static void -isdn_tty_senddown(modem_info * info) -{ - int buflen; - int skb_res; -#ifdef CONFIG_ISDN_AUDIO - int audio_len; -#endif - struct sk_buff *skb; - -#ifdef CONFIG_ISDN_AUDIO - if (info->vonline & 4) { - info->vonline &= ~6; - if (!info->vonline) { -#ifdef ISDN_DEBUG_MODEM_VOICE - printk(KERN_DEBUG - "senddown: send VCON on ttyI%d\n", - info->line); -#endif - isdn_tty_at_cout("\r\nVCON\r\n", info); - } - } -#endif - if (!(buflen = info->xmit_count)) - return; - if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0) - info->msr &= ~UART_MSR_CTS; - info->lsr &= ~UART_LSR_TEMT; - /* info->xmit_count is modified here and in isdn_tty_write(). - * So we return here if isdn_tty_write() is in the - * critical section. - */ - atomic_inc(&info->xmit_lock); - if (!(atomic_dec_and_test(&info->xmit_lock))) - return; - if (info->isdn_driver < 0) { - info->xmit_count = 0; - return; - } - skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4; -#ifdef CONFIG_ISDN_AUDIO - if (info->vonline & 2) - audio_len = buflen * voice_cf[info->emu.vpar[3]]; - else - audio_len = 0; - skb = dev_alloc_skb(skb_res + buflen + audio_len); -#else - skb = dev_alloc_skb(skb_res + buflen); -#endif - if (!skb) { - printk(KERN_WARNING - "isdn_tty: Out of memory in ttyI%d senddown\n", - info->line); - return; - } - skb_reserve(skb, skb_res); - memcpy(skb_put(skb, buflen), info->xmit_buf, buflen); - info->xmit_count = 0; -#ifdef CONFIG_ISDN_AUDIO - if (info->vonline & 2) { - /* For now, ifmt is fixed to 1 (alaw), since this - * is used with ISDN everywhere in the world, except - * US, Canada and Japan. - * Later, when US-ISDN protocols are implemented, - * this setting will depend on the D-channel protocol. - */ - int ifmt = 1; - - /* voice conversion/decompression */ - switch (info->emu.vpar[3]) { - case 2: - case 3: - case 4: - /* adpcm, compatible to ZyXel 1496 modem - * with ROM revision 6.01 - */ - audio_len = isdn_audio_adpcm2xlaw(info->adpcms, - ifmt, - skb->data, - skb_put(skb, audio_len), - buflen); - skb_pull(skb, buflen); - skb_trim(skb, audio_len); - break; - case 5: - /* a-law */ - if (!ifmt) - isdn_audio_alaw2ulaw(skb->data, - buflen); - break; - case 6: - /* u-law */ - if (ifmt) - isdn_audio_ulaw2alaw(skb->data, - buflen); - break; - } - } -#endif /* CONFIG_ISDN_AUDIO */ - if (info->emu.mdmreg[REG_T70] & BIT_T70) { - /* Add T.70 simplified header */ - if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT) - memcpy(skb_push(skb, 2), "\1\0", 2); - else - memcpy(skb_push(skb, 4), "\1\0\1\0", 4); - } - skb_queue_tail(&info->xmit_queue, skb); -} - -/************************************************************ - * - * Modem-functions - * - * mostly "stolen" from original Linux-serial.c and friends. - * - ************************************************************/ - -/* The next routine is called once from within timer-interrupt - * triggered within isdn_tty_modem_ncarrier(). It calls - * isdn_tty_modem_result() to stuff a "NO CARRIER" Message - * into the tty's flip-buffer. - */ -static void -isdn_tty_modem_do_ncarrier(unsigned long data) -{ - modem_info *info = (modem_info *) data; - isdn_tty_modem_result(RESULT_NO_CARRIER, info); -} - -/* Next routine is called, whenever the DTR-signal is raised. - * It checks the ncarrier-flag, and triggers the above routine - * when necessary. The ncarrier-flag is set, whenever DTR goes - * low. - */ -static void -isdn_tty_modem_ncarrier(modem_info * info) -{ - if (info->ncarrier) { - info->nc_timer.expires = jiffies + HZ; - info->nc_timer.function = isdn_tty_modem_do_ncarrier; - info->nc_timer.data = (unsigned long) info; - add_timer(&info->nc_timer); - } -} - -/* - * return the usage calculated by si and layer 2 protocol - */ -int -isdn_calc_usage(int si, int l2) -{ - int usg = ISDN_USAGE_MODEM; - -#ifdef CONFIG_ISDN_AUDIO - if (si == 1) { - switch(l2) { - case ISDN_PROTO_L2_MODEM: - usg = ISDN_USAGE_MODEM; - break; -#ifdef CONFIG_ISDN_TTY_FAX - case ISDN_PROTO_L2_FAX: - usg = ISDN_USAGE_FAX; - break; -#endif - case ISDN_PROTO_L2_TRANS: - default: - usg = ISDN_USAGE_VOICE; - break; - } - } -#endif - return(usg); -} - -/* isdn_tty_dial() performs dialing of a tty an the necessary - * setup of the lower levels before that. - */ -static void -isdn_tty_dial(char *n, modem_info * info, atemu * m) -{ - int usg = ISDN_USAGE_MODEM; - int si = 7; - int l2 = m->mdmreg[REG_L2PROT]; - isdn_ctrl cmd; - ulong flags; - int i; - int j; - - for (j = 7; j >= 0; j--) - if (m->mdmreg[REG_SI1] & (1 << j)) { - si = bit2si[j]; - break; - } - usg = isdn_calc_usage(si, l2); -#ifdef CONFIG_ISDN_AUDIO - if ((si == 1) && - (l2 != ISDN_PROTO_L2_MODEM) -#ifdef CONFIG_ISDN_TTY_FAX - && (l2 != ISDN_PROTO_L2_FAX) -#endif - ) { - l2 = ISDN_PROTO_L2_TRANS; - usg = ISDN_USAGE_VOICE; - } -#endif - m->mdmreg[REG_SI1I] = si2bit[si]; - save_flags(flags); - cli(); - i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); - if (i < 0) { - restore_flags(flags); - isdn_tty_modem_result(RESULT_NO_DIALTONE, info); - } else { - info->isdn_driver = dev->drvmap[i]; - info->isdn_channel = dev->chanmap[i]; - info->drv_index = i; - dev->m_idx[i] = info->line; - dev->usage[i] |= ISDN_USAGE_OUTGOING; - info->last_dir = 1; - strcpy(info->last_num, n); - isdn_info_update(); - restore_flags(flags); - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.command = ISDN_CMD_CLREAZ; - isdn_command(&cmd); - strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETEAZ; - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL2; - info->last_l2 = l2; - cmd.arg = info->isdn_channel + (l2 << 8); - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL3; - cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); -#ifdef CONFIG_ISDN_TTY_FAX - if (l2 == ISDN_PROTO_L2_FAX) { - cmd.parm.fax = info->fax; - info->fax->direction = ISDN_TTY_FAX_CONN_OUT; - } -#endif - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - sprintf(cmd.parm.setup.phone, "%s", n); - sprintf(cmd.parm.setup.eazmsn, "%s", - isdn_map_eaz2msn(m->msn, info->isdn_driver)); - cmd.parm.setup.si1 = si; - cmd.parm.setup.si2 = m->mdmreg[REG_SI2]; - cmd.command = ISDN_CMD_DIAL; - info->dialing = 1; - info->emu.carrierwait = 0; - strcpy(dev->num[i], n); - isdn_info_update(); - isdn_command(&cmd); - isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); - } -} - -/* isdn_tty_hangup() disassociates a tty from the real - * ISDN-line (hangup). The usage-status is cleared - * and some cleanup is done also. - */ -void -isdn_tty_modem_hup(modem_info * info, int local) -{ - isdn_ctrl cmd; - - if (!info) - return; -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup ttyI%d\n", info->line); -#endif - info->rcvsched = 0; - isdn_tty_flush_buffer(info->tty); - if (info->online) { - info->last_lhup = local; - info->online = 0; - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - } -#ifdef CONFIG_ISDN_AUDIO - info->vonline = 0; -#ifdef CONFIG_ISDN_TTY_FAX - info->faxonline = 0; - info->fax->phase = ISDN_FAX_PHASE_IDLE; -#endif - info->emu.vpar[4] = 0; - info->emu.vpar[5] = 8; - if (info->dtmf_state) { - kfree(info->dtmf_state); - info->dtmf_state = NULL; - } - if (info->silence_state) { - kfree(info->silence_state); - info->silence_state = NULL; - } - if (info->adpcms) { - kfree(info->adpcms); - info->adpcms = NULL; - } - if (info->adpcmr) { - kfree(info->adpcmr); - info->adpcmr = NULL; - } -#endif - if ((info->msr & UART_MSR_RI) && - (info->emu.mdmreg[REG_RUNG] & BIT_RUNG)) - isdn_tty_modem_result(RESULT_RUNG, info); - info->msr &= ~(UART_MSR_DCD | UART_MSR_RI); - info->lsr |= UART_LSR_TEMT; - if (info->isdn_driver >= 0) { - if (local) { - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_HANGUP; - cmd.arg = info->isdn_channel; - isdn_command(&cmd); - } - isdn_all_eaz(info->isdn_driver, info->isdn_channel); - info->emu.mdmreg[REG_RINGCNT] = 0; - isdn_free_channel(info->isdn_driver, info->isdn_channel, 0); - } - info->isdn_driver = -1; - info->isdn_channel = -1; - if (info->drv_index >= 0) { - dev->m_idx[info->drv_index] = -1; - info->drv_index = -1; - } -} - -/* - * Begin of a CAPI like interface, currently used only for - * supplementary service (CAPI 2.0 part III) - */ -#include "avmb1/capicmd.h" /* this should be moved in a common place */ - -int -isdn_tty_capi_facility(capi_msg *cm) { - return(-1); /* dummy */ -} - -/* isdn_tty_suspend() tries to suspend the current tty connection - */ -static void -isdn_tty_suspend(char *id, modem_info * info, atemu * m) -{ - isdn_ctrl cmd; - - int l; - - if (!info) - return; - -#ifdef ISDN_DEBUG_MODEM_SERVICES - printk(KERN_DEBUG "Msusp ttyI%d\n", info->line); -#endif - l = strlen(id); - if ((info->isdn_driver >= 0)) { - cmd.parm.cmsg.Length = l+18; - cmd.parm.cmsg.Command = CAPI_FACILITY; - cmd.parm.cmsg.Subcommand = CAPI_REQ; - cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; - cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ - cmd.parm.cmsg.para[1] = 0; - cmd.parm.cmsg.para[2] = l + 3; - cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */ - cmd.parm.cmsg.para[4] = 0; - cmd.parm.cmsg.para[5] = l; - strncpy(&cmd.parm.cmsg.para[6], id, l); - cmd.command = CAPI_PUT_MESSAGE; - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - isdn_command(&cmd); - } -} - -/* isdn_tty_resume() tries to resume a suspended call - * setup of the lower levels before that. unfortunatly here is no - * checking for compatibility of used protocols implemented by Q931 - * It does the same things like isdn_tty_dial, the last command - * is different, may be we can merge it. - */ - -static void -isdn_tty_resume(char *id, modem_info * info, atemu * m) -{ - int usg = ISDN_USAGE_MODEM; - int si = 7; - int l2 = m->mdmreg[REG_L2PROT]; - isdn_ctrl cmd; - ulong flags; - int i; - int j; - int l; - - l = strlen(id); - for (j = 7; j >= 0; j--) - if (m->mdmreg[REG_SI1] & (1 << j)) { - si = bit2si[j]; - break; - } - usg = isdn_calc_usage(si, l2); -#ifdef CONFIG_ISDN_AUDIO - if ((si == 1) && - (l2 != ISDN_PROTO_L2_MODEM) -#ifdef CONFIG_ISDN_TTY_FAX - && (l2 != ISDN_PROTO_L2_FAX) -#endif - ) { - l2 = ISDN_PROTO_L2_TRANS; - usg = ISDN_USAGE_VOICE; - } -#endif - m->mdmreg[REG_SI1I] = si2bit[si]; - save_flags(flags); - cli(); - i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); - if (i < 0) { - restore_flags(flags); - isdn_tty_modem_result(RESULT_NO_DIALTONE, info); - } else { - info->isdn_driver = dev->drvmap[i]; - info->isdn_channel = dev->chanmap[i]; - info->drv_index = i; - dev->m_idx[i] = info->line; - dev->usage[i] |= ISDN_USAGE_OUTGOING; - info->last_dir = 1; -// strcpy(info->last_num, n); - isdn_info_update(); - restore_flags(flags); - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.command = ISDN_CMD_CLREAZ; - isdn_command(&cmd); - strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETEAZ; - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL2; - info->last_l2 = l2; - cmd.arg = info->isdn_channel + (l2 << 8); - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL3; - cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.parm.cmsg.Length = l+18; - cmd.parm.cmsg.Command = CAPI_FACILITY; - cmd.parm.cmsg.Subcommand = CAPI_REQ; - cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; - cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */ - cmd.parm.cmsg.para[1] = 0; - cmd.parm.cmsg.para[2] = l+3; - cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */ - cmd.parm.cmsg.para[4] = 0; - cmd.parm.cmsg.para[5] = l; - strncpy(&cmd.parm.cmsg.para[6], id, l); - cmd.command =CAPI_PUT_MESSAGE; - info->dialing = 1; -// strcpy(dev->num[i], n); - isdn_info_update(); - isdn_command(&cmd); - isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); - } -} - -/* isdn_tty_send_msg() sends a message to a HL driver - * This is used for hybrid modem cards to send AT commands to it - */ - -static void -isdn_tty_send_msg(modem_info * info, atemu * m, char *msg) -{ - int usg = ISDN_USAGE_MODEM; - int si = 7; - int l2 = m->mdmreg[REG_L2PROT]; - isdn_ctrl cmd; - ulong flags; - int i; - int j; - int l; - - l = strlen(msg); - if (!l) { - isdn_tty_modem_result(RESULT_ERROR, info); - return; - } - for (j = 7; j >= 0; j--) - if (m->mdmreg[REG_SI1] & (1 << j)) { - si = bit2si[j]; - break; - } - usg = isdn_calc_usage(si, l2); -#ifdef CONFIG_ISDN_AUDIO - if ((si == 1) && - (l2 != ISDN_PROTO_L2_MODEM) -#ifdef CONFIG_ISDN_TTY_FAX - && (l2 != ISDN_PROTO_L2_FAX) -#endif - ) { - l2 = ISDN_PROTO_L2_TRANS; - usg = ISDN_USAGE_VOICE; - } -#endif - m->mdmreg[REG_SI1I] = si2bit[si]; - save_flags(flags); - cli(); - i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn); - if (i < 0) { - restore_flags(flags); - isdn_tty_modem_result(RESULT_NO_DIALTONE, info); - } else { - info->isdn_driver = dev->drvmap[i]; - info->isdn_channel = dev->chanmap[i]; - info->drv_index = i; - dev->m_idx[i] = info->line; - dev->usage[i] |= ISDN_USAGE_OUTGOING; - info->last_dir = 1; - isdn_info_update(); - restore_flags(flags); - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.command = ISDN_CMD_CLREAZ; - isdn_command(&cmd); - strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver)); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETEAZ; - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL2; - info->last_l2 = l2; - cmd.arg = info->isdn_channel + (l2 << 8); - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL3; - cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.parm.cmsg.Length = l+14; - cmd.parm.cmsg.Command = CAPI_MANUFACTURER; - cmd.parm.cmsg.Subcommand = CAPI_REQ; - cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1; - cmd.parm.cmsg.para[0] = l+1; - strncpy(&cmd.parm.cmsg.para[1], msg, l); - cmd.parm.cmsg.para[l+1] = 0xd; - cmd.command =CAPI_PUT_MESSAGE; -/* info->dialing = 1; - strcpy(dev->num[i], n); - isdn_info_update(); -*/ - isdn_command(&cmd); - } -} - -static inline int -isdn_tty_paranoia_check(modem_info * info, kdev_t device, const char *routine) -{ -#ifdef MODEM_PARANOIA_CHECK - if (!info) { - printk(KERN_WARNING "isdn_tty: null info_struct for (%d, %d) in %s\n", - MAJOR(device), MINOR(device), routine); - return 1; - } - if (info->magic != ISDN_ASYNC_MAGIC) { - printk(KERN_WARNING "isdn_tty: bad magic for modem struct (%d, %d) in %s\n", - MAJOR(device), MINOR(device), routine); - return 1; - } -#endif - return 0; -} - -/* - * This routine is called to set the UART divisor registers to match - * the specified baud rate for a serial port. - */ -static void -isdn_tty_change_speed(modem_info * info) -{ - uint cflag, - cval, - fcr, - quot; - int i; - - if (!info->tty || !info->tty->termios) - return; - cflag = info->tty->termios->c_cflag; - - quot = i = cflag & CBAUD; - if (i & CBAUDEX) { - i &= ~CBAUDEX; - if (i < 1 || i > 2) - info->tty->termios->c_cflag &= ~CBAUDEX; - else - i += 15; - } - if (quot) { - info->mcr |= UART_MCR_DTR; - isdn_tty_modem_ncarrier(info); - } else { - info->mcr &= ~UART_MCR_DTR; - if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in changespeed\n"); -#endif - if (info->online) - info->ncarrier = 1; - isdn_tty_modem_reset_regs(info, 0); - isdn_tty_modem_hup(info, 1); - } - return; - } - /* byte size and parity */ - cval = cflag & (CSIZE | CSTOPB); - cval >>= 4; - if (cflag & PARENB) - cval |= UART_LCR_PARITY; - if (!(cflag & PARODD)) - cval |= UART_LCR_EPAR; - fcr = 0; - - /* CTS flow control flag and modem status interrupts */ - if (cflag & CRTSCTS) { - info->flags |= ISDN_ASYNC_CTS_FLOW; - } else - info->flags &= ~ISDN_ASYNC_CTS_FLOW; - if (cflag & CLOCAL) - info->flags &= ~ISDN_ASYNC_CHECK_CD; - else { - info->flags |= ISDN_ASYNC_CHECK_CD; - } -} - -static int -isdn_tty_startup(modem_info * info) -{ - ulong flags; - - if (info->flags & ISDN_ASYNC_INITIALIZED) - return 0; - save_flags(flags); - cli(); - isdn_MOD_INC_USE_COUNT(); -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line); -#endif - /* - * Now, initialize the UART - */ - info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2; - if (info->tty) - clear_bit(TTY_IO_ERROR, &info->tty->flags); - /* - * and set the speed of the serial port - */ - isdn_tty_change_speed(info); - - info->flags |= ISDN_ASYNC_INITIALIZED; - info->msr |= (UART_MSR_DSR | UART_MSR_CTS); - info->send_outstanding = 0; - restore_flags(flags); - return 0; -} - -/* - * This routine will shutdown a serial port; interrupts are disabled, and - * DTR is dropped if the hangup on close termio flag is on. - */ -static void -isdn_tty_shutdown(modem_info * info) -{ - ulong flags; - - if (!(info->flags & ISDN_ASYNC_INITIALIZED)) - return; -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line); -#endif - save_flags(flags); - cli(); /* Disable interrupts */ - isdn_MOD_DEC_USE_COUNT(); - info->msr &= ~UART_MSR_RI; - if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) { - info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS); - if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { - isdn_tty_modem_reset_regs(info, 0); -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n"); -#endif - isdn_tty_modem_hup(info, 1); - } - } - if (info->tty) - set_bit(TTY_IO_ERROR, &info->tty->flags); - - info->flags &= ~ISDN_ASYNC_INITIALIZED; - restore_flags(flags); -} - -/* isdn_tty_write() is the main send-routine. It is called from the upper - * levels within the kernel to perform sending data. Depending on the - * online-flag it either directs output to the at-command-interpreter or - * to the lower level. Additional tasks done here: - * - If online, check for escape-sequence (+++) - * - If sending audio-data, call isdn_tty_DLEdown() to parse DLE-codes. - * - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed. - * - If dialing, abort dial. - */ -static int -isdn_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int count) -{ - int c; - int total = 0; - modem_info *info = (modem_info *) tty->driver_data; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write")) - return 0; - if (!tty) - return 0; - if (from_user) - down(&info->write_sem); - /* See isdn_tty_senddown() */ - atomic_inc(&info->xmit_lock); - while (1) { - c = MIN(count, info->xmit_size - info->xmit_count); - if (info->isdn_driver >= 0) - c = MIN(c, dev->drv[info->isdn_driver]->maxbufsize); - if (c <= 0) - break; - if ((info->online > 1) -#ifdef CONFIG_ISDN_AUDIO - || (info->vonline & 3) -#endif - ) { - atemu *m = &info->emu; - -#ifdef CONFIG_ISDN_AUDIO - if (!info->vonline) -#endif - isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c, - &(m->pluscount), - &(m->lastplus), - from_user); - if (from_user) - copy_from_user(&(info->xmit_buf[info->xmit_count]), buf, c); - else - memcpy(&(info->xmit_buf[info->xmit_count]), buf, c); -#ifdef CONFIG_ISDN_AUDIO - if (info->vonline) { - int cc = isdn_tty_handleDLEdown(info, m, c); - if (info->vonline & 2) { - if (!cc) { - /* If DLE decoding results in zero-transmit, but - * c originally was non-zero, do a wakeup. - */ - 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; - } - info->xmit_count += cc; - } - if ((info->vonline & 3) == 1) { - /* Do NOT handle Ctrl-Q or Ctrl-S - * when in full-duplex audio mode. - */ - if (isdn_tty_end_vrx(buf, c, from_user)) { - info->vonline &= ~1; -#ifdef ISDN_DEBUG_MODEM_VOICE - printk(KERN_DEBUG - "got !^Q/^S, send DLE-ETX,VCON on ttyI%d\n", - info->line); -#endif - isdn_tty_at_cout("\020\003\r\nVCON\r\n", info); - } - } - } else -#ifdef ISDN_TTY_FCLASS1 - if (TTY_IS_FCLASS1(info)) { - int cc = isdn_tty_handleDLEdown(info, m, c); - - if (info->vonline & 4) { /* ETX seen */ - isdn_ctrl c; - - c.command = ISDN_CMD_FAXCMD; - c.driver = info->isdn_driver; - c.arg = info->isdn_channel; - c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL; - c.parm.aux.subcmd = ETX; - isdn_command(&c); - } - info->vonline = 0; - printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc,c); - info->xmit_count += cc; - } else -#endif -#endif - info->xmit_count += c; - } else { - info->msr |= UART_MSR_CTS; - info->lsr |= UART_LSR_TEMT; - if (info->dialing) { - info->dialing = 0; -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in isdn_tty_write\n"); -#endif - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - isdn_tty_modem_hup(info, 1); - } else - c = isdn_tty_edit_at(buf, c, info, from_user); - } - buf += c; - count -= c; - total += c; - } - if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) - isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); - atomic_dec(&info->xmit_lock); - if (from_user) - up(&info->write_sem); - return total; -} - -static int -isdn_tty_write_room(struct tty_struct *tty) -{ - modem_info *info = (modem_info *) tty->driver_data; - int ret; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_write_room")) - return 0; - if (!info->online) - return info->xmit_size; - ret = info->xmit_size - info->xmit_count; - return (ret < 0) ? 0 : ret; -} - -static int -isdn_tty_chars_in_buffer(struct tty_struct *tty) -{ - modem_info *info = (modem_info *) tty->driver_data; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_chars_in_buffer")) - return 0; - if (!info->online) - return 0; - return (info->xmit_count); -} - -static void -isdn_tty_flush_buffer(struct tty_struct *tty) -{ - modem_info *info; - unsigned long flags; - - save_flags(flags); - cli(); - if (!tty) { - restore_flags(flags); - return; - } - info = (modem_info *) tty->driver_data; - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_buffer")) { - restore_flags(flags); - return; - } - isdn_tty_cleanup_xmit(info); - info->xmit_count = 0; - restore_flags(flags); - 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 -isdn_tty_flush_chars(struct tty_struct *tty) -{ - modem_info *info = (modem_info *) tty->driver_data; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_flush_chars")) - return; - if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) - isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1); -} - -/* - * ------------------------------------------------------------ - * isdn_tty_throttle() - * - * This routine is called by the upper-layer tty layer to signal that - * incoming characters should be throttled. - * ------------------------------------------------------------ - */ -static void -isdn_tty_throttle(struct tty_struct *tty) -{ - modem_info *info = (modem_info *) tty->driver_data; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_throttle")) - return; - if (I_IXOFF(tty)) - info->x_char = STOP_CHAR(tty); - info->mcr &= ~UART_MCR_RTS; -} - -static void -isdn_tty_unthrottle(struct tty_struct *tty) -{ - modem_info *info = (modem_info *) tty->driver_data; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_unthrottle")) - return; - if (I_IXOFF(tty)) { - if (info->x_char) - info->x_char = 0; - else - info->x_char = START_CHAR(tty); - } - info->mcr |= UART_MCR_RTS; -} - -/* - * ------------------------------------------------------------ - * isdn_tty_ioctl() and friends - * ------------------------------------------------------------ - */ - -/* - * isdn_tty_get_lsr_info - get line status register info - * - * Purpose: Let user call ioctl() to get info when the UART physically - * is emptied. On bus types like RS485, the transmitter must - * release the bus after transmitting. This must be done when - * the transmit shift register is empty, not be done when the - * transmit holding register is empty. This functionality - * allows RS485 driver to be written in user space. - */ -static int -isdn_tty_get_lsr_info(modem_info * info, uint * value) -{ - u_char status; - uint result; - ulong flags; - - save_flags(flags); - cli(); - status = info->lsr; - restore_flags(flags); - result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0); - put_user(result, (uint *) value); - return 0; -} - - -static int -isdn_tty_get_modem_info(modem_info * info, uint * value) -{ - u_char control, - status; - uint result; - ulong flags; - - control = info->mcr; - save_flags(flags); - cli(); - status = info->msr; - restore_flags(flags); - result = ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) - | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) - | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) - | ((status & UART_MSR_RI) ? TIOCM_RNG : 0) - | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) - | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0); - put_user(result, (uint *) value); - return 0; -} - -static int -isdn_tty_set_modem_info(modem_info * info, uint cmd, uint * value) -{ - uint arg; - int pre_dtr; - - get_user(arg, (uint *) value); - switch (cmd) { - case TIOCMBIS: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIS\n", info->line); -#endif - if (arg & TIOCM_RTS) { - info->mcr |= UART_MCR_RTS; - } - if (arg & TIOCM_DTR) { - info->mcr |= UART_MCR_DTR; - isdn_tty_modem_ncarrier(info); - } - break; - case TIOCMBIC: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMBIC\n", info->line); -#endif - if (arg & TIOCM_RTS) { - info->mcr &= ~UART_MCR_RTS; - } - if (arg & TIOCM_DTR) { - info->mcr &= ~UART_MCR_DTR; - if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { - isdn_tty_modem_reset_regs(info, 0); -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in TIOCMBIC\n"); -#endif - if (info->online) - info->ncarrier = 1; - isdn_tty_modem_hup(info, 1); - } - } - break; - case TIOCMSET: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMSET\n", info->line); -#endif - pre_dtr = (info->mcr & UART_MCR_DTR); - info->mcr = ((info->mcr & ~(UART_MCR_RTS | UART_MCR_DTR)) - | ((arg & TIOCM_RTS) ? UART_MCR_RTS : 0) - | ((arg & TIOCM_DTR) ? UART_MCR_DTR : 0)); - if (pre_dtr |= (info->mcr & UART_MCR_DTR)) { - if (!(info->mcr & UART_MCR_DTR)) { - if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) { - isdn_tty_modem_reset_regs(info, 0); -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in TIOCMSET\n"); -#endif - if (info->online) - info->ncarrier = 1; - isdn_tty_modem_hup(info, 1); - } - } else - isdn_tty_modem_ncarrier(info); - } - break; - default: - return -EINVAL; - } - return 0; -} - -static int -isdn_tty_ioctl(struct tty_struct *tty, struct file *file, - uint cmd, ulong arg) -{ - modem_info *info = (modem_info *) tty->driver_data; - int error; - int retval; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_ioctl")) - return -ENODEV; - if (tty->flags & (1 << TTY_IO_ERROR)) - return -EIO; - switch (cmd) { - case TCSBRK: /* SVID version: non-zero arg --> no break */ -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TCSBRK\n", info->line); -#endif - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - return 0; - case TCSBRKP: /* support for POSIX tcsendbreak() */ -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TCSBRKP\n", info->line); -#endif - retval = tty_check_change(tty); - if (retval) - return retval; - tty_wait_until_sent(tty, 0); - return 0; - case TIOCGSOFTCAR: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line); -#endif - error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long)); - if (error) - return error; - put_user(C_CLOCAL(tty) ? 1 : 0, (ulong *) arg); - return 0; - case TIOCSSOFTCAR: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line); -#endif - error = verify_area(VERIFY_READ, (void *) arg, sizeof(long)); - if (error) - return error; - get_user(arg, (ulong *) arg); - tty->termios->c_cflag = - ((tty->termios->c_cflag & ~CLOCAL) | - (arg ? CLOCAL : 0)); - return 0; - case TIOCMGET: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line); -#endif - error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint)); - if (error) - return error; - return isdn_tty_get_modem_info(info, (uint *) arg); - case TIOCMBIS: - case TIOCMBIC: - case TIOCMSET: - error = verify_area(VERIFY_READ, (void *) arg, sizeof(uint)); - if (error) - return error; - return isdn_tty_set_modem_info(info, cmd, (uint *) arg); - case TIOCSERGETLSR: /* Get line status register */ -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line); -#endif - error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(uint)); - if (error) - return error; - else - return isdn_tty_get_lsr_info(info, (uint *) arg); - default: -#ifdef ISDN_DEBUG_MODEM_IOCTL - printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line); -#endif - return -ENOIOCTLCMD; - } - return 0; -} - -static void -isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios) -{ - modem_info *info = (modem_info *) tty->driver_data; - - if (!old_termios) - isdn_tty_change_speed(info); - else { - if (tty->termios->c_cflag == old_termios->c_cflag) - return; - isdn_tty_change_speed(info); - if ((old_termios->c_cflag & CRTSCTS) && - !(tty->termios->c_cflag & CRTSCTS)) { - tty->hw_stopped = 0; - } - } -} - -/* - * ------------------------------------------------------------ - * isdn_tty_open() and friends - * ------------------------------------------------------------ - */ -static int -isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info) -{ -#ifdef COMPAT_HAS_NEW_WAITQ - DECLARE_WAITQUEUE(wait, NULL); -#else - struct wait_queue wait = - {current, NULL}; -#endif - int do_clocal = 0; - unsigned long flags; - int retval; - - /* - * If the device is in the middle of being closed, then block - * until it's done, and then try again. - */ - if (tty_hung_up_p(filp) || - (info->flags & ISDN_ASYNC_CLOSING)) { - if (info->flags & ISDN_ASYNC_CLOSING) - interruptible_sleep_on(&info->close_wait); -#ifdef MODEM_DO_RESTART - if (info->flags & ISDN_ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; -#else - return -EAGAIN; -#endif - } - /* - * If this is a callout device, then just make sure the normal - * device isn't being used. - */ - if (tty->driver.subtype == ISDN_SERIAL_TYPE_CALLOUT) { - if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) - return -EBUSY; - if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && - (info->flags & ISDN_ASYNC_SESSION_LOCKOUT) && - (info->session != current->session)) - return -EBUSY; - if ((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && - (info->flags & ISDN_ASYNC_PGRP_LOCKOUT) && - (info->pgrp != current->pgrp)) - return -EBUSY; - info->flags |= ISDN_ASYNC_CALLOUT_ACTIVE; - return 0; - } - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - if ((filp->f_flags & O_NONBLOCK) || - (tty->flags & (1 << TTY_IO_ERROR))) { - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) - return -EBUSY; - info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; - return 0; - } - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) { - if (info->normal_termios.c_cflag & CLOCAL) - do_clocal = 1; - } else { - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - } - /* - * Block waiting for the carrier detect and the line to become - * free (i.e., not in use by the callout). While we are in - * this loop, info->count is dropped by one, so that - * isdn_tty_close() knows when to free things. We restore it upon - * exit, either normal or abnormal. - */ - retval = 0; - add_wait_queue(&info->open_wait, &wait); -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n", - info->line, info->count); -#endif - save_flags(flags); - cli(); - if (!(tty_hung_up_p(filp))) - info->count--; - restore_flags(flags); - info->blocked_open++; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(info->flags & ISDN_ASYNC_INITIALIZED)) { -#ifdef MODEM_DO_RESTART - if (info->flags & ISDN_ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; -#else - retval = -EAGAIN; -#endif - break; - } - if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) && - !(info->flags & ISDN_ASYNC_CLOSING) && - (do_clocal || (info->msr & UART_MSR_DCD))) { - break; - } - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n", - info->line, info->count); -#endif - schedule(); - } - current->state = TASK_RUNNING; - remove_wait_queue(&info->open_wait, &wait); - if (!tty_hung_up_p(filp)) - info->count++; - info->blocked_open--; -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n", - info->line, info->count); -#endif - if (retval) - return retval; - info->flags |= ISDN_ASYNC_NORMAL_ACTIVE; - return 0; -} - -/* - * This routine is called whenever a serial port is opened. It - * enables interrupts for a serial port, linking in its async structure into - * the IRQ chain. It also performs the serial-specific - * initialization for the tty structure. - */ -static int -isdn_tty_open(struct tty_struct *tty, struct file *filp) -{ - modem_info *info; - int retval, - line; - - line = MINOR(tty->device) - tty->driver.minor_start; - if (line < 0 || line > ISDN_MAX_CHANNELS) - return -ENODEV; - info = &dev->mdm.info[line]; - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_open")) - return -ENODEV; -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_open %s%d, count = %d\n", tty->driver.name, - info->line, info->count); -#endif - info->count++; - tty->driver_data = info; - info->tty = tty; - /* - * Start up serial port - */ - retval = isdn_tty_startup(info); - if (retval) { -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_open return after startup\n"); -#endif - return retval; - } - retval = isdn_tty_block_til_ready(tty, filp, info); - if (retval) { -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n"); -#endif - return retval; - } - if ((info->count == 1) && (info->flags & ISDN_ASYNC_SPLIT_TERMIOS)) { - if (tty->driver.subtype == ISDN_SERIAL_TYPE_NORMAL) - *tty->termios = info->normal_termios; - else - *tty->termios = info->callout_termios; - isdn_tty_change_speed(info); - } - info->session = current->session; - info->pgrp = current->pgrp; -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line); -#endif - dev->modempoll++; -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_open normal exit\n"); -#endif - return 0; -} - -static void -isdn_tty_close(struct tty_struct *tty, struct file *filp) -{ - modem_info *info = (modem_info *) tty->driver_data; - ulong flags; - ulong timeout; - - if (!info || isdn_tty_paranoia_check(info, tty->device, "isdn_tty_close")) - return; - save_flags(flags); - cli(); - if (tty_hung_up_p(filp)) { - restore_flags(flags); -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n"); -#endif - return; - } - if ((tty->count == 1) && (info->count != 1)) { - /* - * Uh, oh. tty->count is 1, which means that the tty - * structure will be freed. Info->count should always - * be one in these conditions. If it's greater than - * one, we've got real problems, since it means the - * serial port won't be shutdown. - */ - printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, " - "info->count is %d\n", info->count); - info->count = 1; - } - if (--info->count < 0) { - printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n", - info->line, info->count); - info->count = 0; - } - if (info->count) { - restore_flags(flags); -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n"); -#endif - return; - } - info->flags |= ISDN_ASYNC_CLOSING; - /* - * Save the termios structure, since this port may have - * separate termios for callout and dialin. - */ - if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) - info->normal_termios = *tty->termios; - if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) - info->callout_termios = *tty->termios; - - tty->closing = 1; - /* - * At this point we stop accepting input. To do this, we - * disable the receive line status interrupts, and tell the - * interrupt driver to stop checking the data ready bit in the - * line status register. - */ - if (info->flags & ISDN_ASYNC_INITIALIZED) { - tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */ - /* - * Before we drop DTR, make sure the UART transmitter - * has completely drained; this is especially - * important if there is a transmit FIFO! - */ - timeout = jiffies + HZ; - while (!(info->lsr & UART_LSR_TEMT)) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(20); - if (time_after(jiffies,timeout)) - break; - } - } - dev->modempoll--; - isdn_tty_shutdown(info); - if (tty->driver.flush_buffer) - tty->driver.flush_buffer(tty); - if (tty->ldisc.flush_buffer) - tty->ldisc.flush_buffer(tty); - info->tty = 0; - info->ncarrier = 0; - tty->closing = 0; - if (info->blocked_open) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(50); - wake_up_interruptible(&info->open_wait); - } - info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE | - ISDN_ASYNC_CLOSING); - wake_up_interruptible(&info->close_wait); - restore_flags(flags); -#ifdef ISDN_DEBUG_MODEM_OPEN - printk(KERN_DEBUG "isdn_tty_close normal exit\n"); -#endif -} - -/* - * isdn_tty_hangup() --- called by tty_hangup() when a hangup is signaled. - */ -static void -isdn_tty_hangup(struct tty_struct *tty) -{ - modem_info *info = (modem_info *) tty->driver_data; - - if (isdn_tty_paranoia_check(info, tty->device, "isdn_tty_hangup")) - return; - isdn_tty_shutdown(info); - info->count = 0; - info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE); - info->tty = 0; - wake_up_interruptible(&info->open_wait); -} - -/* This routine initializes all emulator-data. - */ -static void -isdn_tty_reset_profile(atemu * m) -{ - m->profile[0] = 0; - m->profile[1] = 0; - m->profile[2] = 43; - m->profile[3] = 13; - m->profile[4] = 10; - m->profile[5] = 8; - m->profile[6] = 3; - m->profile[7] = 60; - m->profile[8] = 2; - m->profile[9] = 6; - m->profile[10] = 7; - m->profile[11] = 70; - m->profile[12] = 0x45; - m->profile[13] = 4; - m->profile[14] = ISDN_PROTO_L2_X75I; - m->profile[15] = ISDN_PROTO_L3_TRANS; - m->profile[16] = ISDN_SERIAL_XMIT_SIZE / 16; - m->profile[17] = ISDN_MODEM_WINSIZE; - m->profile[18] = 4; - m->profile[19] = 0; - m->profile[20] = 0; - m->profile[23] = 0; - m->pmsn[0] = '\0'; - m->plmsn[0] = '\0'; -} - -#ifdef CONFIG_ISDN_AUDIO -static void -isdn_tty_modem_reset_vpar(atemu * m) -{ - m->vpar[0] = 2; /* Voice-device (2 = phone line) */ - m->vpar[1] = 0; /* Silence detection level (0 = none ) */ - m->vpar[2] = 70; /* Silence interval (7 sec. ) */ - m->vpar[3] = 2; /* Compression type (1 = ADPCM-2 ) */ - m->vpar[4] = 0; /* DTMF detection level (0 = softcode ) */ - m->vpar[5] = 8; /* DTMF interval (8 * 5 ms. ) */ -} -#endif - -#ifdef CONFIG_ISDN_TTY_FAX -static void -isdn_tty_modem_reset_faxpar(modem_info * info) -{ - T30_s *f = info->fax; - - f->code = 0; - f->phase = ISDN_FAX_PHASE_IDLE; - f->direction = 0; - f->resolution = 1; /* fine */ - f->rate = 5; /* 14400 bit/s */ - f->width = 0; - f->length = 0; - f->compression = 0; - f->ecm = 0; - f->binary = 0; - f->scantime = 0; - memset(&f->id[0], 32, FAXIDLEN - 1); - f->id[FAXIDLEN - 1] = 0; - f->badlin = 0; - f->badmul = 0; - f->bor = 0; - f->nbc = 0; - f->cq = 0; - f->cr = 0; - f->ctcrty = 0; - f->minsp = 0; - f->phcto = 30; - f->rel = 0; - memset(&f->pollid[0], 32, FAXIDLEN - 1); - f->pollid[FAXIDLEN - 1] = 0; -} -#endif - -static void -isdn_tty_modem_reset_regs(modem_info * info, int force) -{ - atemu *m = &info->emu; - if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) { - memcpy(m->mdmreg, m->profile, ISDN_MODEM_NUMREG); - memcpy(m->msn, m->pmsn, ISDN_MSNLEN); - memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN); - info->xmit_size = m->mdmreg[REG_PSIZE] * 16; - } -#ifdef CONFIG_ISDN_AUDIO - isdn_tty_modem_reset_vpar(m); -#endif -#ifdef CONFIG_ISDN_TTY_FAX - isdn_tty_modem_reset_faxpar(info); -#endif - m->mdmcmdl = 0; -} - -static void -modem_write_profile(atemu * m) -{ - memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG); - memcpy(m->pmsn, m->msn, ISDN_MSNLEN); - memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN); - if (dev->profd) - send_sig(SIGIO, dev->profd, 1); -} - -int -isdn_tty_modem_init(void) -{ - modem *m; - int i; - modem_info *info; - - m = &dev->mdm; - memset(&m->tty_modem, 0, sizeof(struct tty_driver)); - m->tty_modem.magic = TTY_DRIVER_MAGIC; - m->tty_modem.name = isdn_ttyname_ttyI; - m->tty_modem.major = ISDN_TTY_MAJOR; - m->tty_modem.minor_start = 0; - m->tty_modem.num = ISDN_MAX_CHANNELS; - m->tty_modem.type = TTY_DRIVER_TYPE_SERIAL; - m->tty_modem.subtype = ISDN_SERIAL_TYPE_NORMAL; - m->tty_modem.init_termios = tty_std_termios; - m->tty_modem.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - m->tty_modem.flags = TTY_DRIVER_REAL_RAW; - m->tty_modem.refcount = &m->refcount; - m->tty_modem.table = m->modem_table; - m->tty_modem.termios = m->modem_termios; - m->tty_modem.termios_locked = m->modem_termios_locked; - m->tty_modem.open = isdn_tty_open; - m->tty_modem.close = isdn_tty_close; - m->tty_modem.write = isdn_tty_write; - m->tty_modem.put_char = NULL; - m->tty_modem.flush_chars = isdn_tty_flush_chars; - m->tty_modem.write_room = isdn_tty_write_room; - m->tty_modem.chars_in_buffer = isdn_tty_chars_in_buffer; - m->tty_modem.flush_buffer = isdn_tty_flush_buffer; - m->tty_modem.ioctl = isdn_tty_ioctl; - m->tty_modem.throttle = isdn_tty_throttle; - m->tty_modem.unthrottle = isdn_tty_unthrottle; - m->tty_modem.set_termios = isdn_tty_set_termios; - m->tty_modem.stop = NULL; - m->tty_modem.start = NULL; - m->tty_modem.hangup = isdn_tty_hangup; - m->tty_modem.driver_name = "isdn_tty"; - /* - * The callout device is just like normal device except for - * major number and the subtype code. - */ - m->cua_modem = m->tty_modem; - m->cua_modem.name = isdn_ttyname_cui; - m->cua_modem.major = ISDN_TTYAUX_MAJOR; - m->tty_modem.minor_start = 0; - m->cua_modem.subtype = ISDN_SERIAL_TYPE_CALLOUT; - - if (tty_register_driver(&m->tty_modem)) { - printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n"); - return -1; - } - if (tty_register_driver(&m->cua_modem)) { - printk(KERN_WARNING "isdn_tty: Couldn't register modem-callout-device\n"); - return -2; - } - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - info = &m->info[i]; -#ifdef CONFIG_ISDN_TTY_FAX - if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) { - printk(KERN_ERR "Could not allocate fax t30-buffer\n"); - return -3; - } -#endif -#ifdef COMPAT_HAS_NEW_WAITQ - init_MUTEX(&info->write_sem); -#else - info->write_sem = MUTEX; -#endif - sprintf(info->last_cause, "0000"); - sprintf(info->last_num, "none"); - info->last_dir = 0; - info->last_lhup = 1; - info->last_l2 = -1; - info->last_si = 0; - isdn_tty_reset_profile(&info->emu); - isdn_tty_modem_reset_regs(info, 1); - info->magic = ISDN_ASYNC_MAGIC; - info->line = i; - info->tty = 0; - info->x_char = 0; - info->count = 0; - info->blocked_open = 0; - info->callout_termios = m->cua_modem.init_termios; - info->normal_termios = m->tty_modem.init_termios; -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&info->open_wait); - init_waitqueue_head(&info->close_wait); -#else - info->open_wait = 0; - info->close_wait = 0; -#endif - info->isdn_driver = -1; - info->isdn_channel = -1; - info->drv_index = -1; - info->xmit_size = ISDN_SERIAL_XMIT_SIZE; - skb_queue_head_init(&info->xmit_queue); -#ifdef CONFIG_ISDN_AUDIO - skb_queue_head_init(&info->dtmf_queue); -#endif - if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) { - printk(KERN_ERR "Could not allocate modem xmit-buffer\n"); - return -3; - } - /* Make room for T.70 header */ - info->xmit_buf += 4; - } - return 0; -} - - -/* - * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx) - * match the MSN against the MSNs (glob patterns) defined for tty_emulator, - * and return 0 for match, 1 for no match, 2 if MSN could match if longer. - */ - -static int -isdn_tty_match_icall(char *cid, atemu *emu, int di) -{ -#ifdef ISDN_DEBUG_MODEM_ICALL - printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n", - emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di), - emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]); -#endif - if (strlen(emu->lmsn)) { - char *p = emu->lmsn; - char *q; - int tmp; - int ret = 0; - - while (1) { - if ((q = strchr(p, ';'))) - *q = '\0'; - if ((tmp = isdn_wildmat(cid, isdn_map_eaz2msn(p, di))) > ret) - ret = tmp; -#ifdef ISDN_DEBUG_MODEM_ICALL - printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n", - p, isdn_map_eaz2msn(emu->msn, di), tmp); -#endif - if (q) { - *q = ';'; - p = q; - p++; - } - if (!tmp) - return 0; - if (!q) - break; - } - return ret; - } else { - int tmp; - tmp = isdn_wildmat(cid, isdn_map_eaz2msn(emu->msn, di)); -#ifdef ISDN_DEBUG_MODEM_ICALL - printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n", - isdn_map_eaz2msn(emu->msn, di), tmp); -#endif - return tmp; - } -} - -/* - * An incoming call-request has arrived. - * Search the tty-devices for an appropriate device and bind - * it to the ISDN-Channel. - * Return: - * - * 0 = No matching device found. - * 1 = A matching device found. - * 3 = No match found, but eventually would match, if - * CID is longer. - */ -int -isdn_tty_find_icall(int di, int ch, setup_parm setup) -{ - char *eaz; - int i; - int wret; - int idx; - int si1; - int si2; - char *nr; - ulong flags; - - if (!setup.phone[0]) { - nr = "0"; - printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n"); - } else - nr = setup.phone; - si1 = (int) setup.si1; - si2 = (int) setup.si2; - if (!setup.eazmsn[0]) { - printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n"); - eaz = "0"; - } else - eaz = setup.eazmsn; -#ifdef ISDN_DEBUG_MODEM_ICALL - printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2); -#endif - wret = 0; - save_flags(flags); - cli(); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - modem_info *info = &dev->mdm.info[i]; - - if (info->count == 0) - continue; - if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */ - (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */ - idx = isdn_dc2minor(di, ch); -#ifdef ISDN_DEBUG_MODEM_ICALL - printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret); - printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx, - info->flags, info->isdn_driver, info->isdn_channel, - dev->usage[idx]); -#endif - if ( -#ifndef FIX_FILE_TRANSFER - (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) && -#endif - (info->isdn_driver == -1) && - (info->isdn_channel == -1) && - (USG_NONE(dev->usage[idx]))) { - int matchret; - - if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret) - wret = matchret; - if (!matchret) { /* EAZ is matching */ - info->isdn_driver = di; - info->isdn_channel = ch; - info->drv_index = idx; - dev->m_idx[idx] = info->line; - dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE; - dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]); - strcpy(dev->num[idx], nr); - strcpy(info->emu.cpn, eaz); - info->emu.mdmreg[REG_SI1I] = si2bit[si1]; - info->emu.mdmreg[REG_PLAN] = setup.plan; - info->emu.mdmreg[REG_SCREEN] = setup.screen; - isdn_info_update(); - restore_flags(flags); - printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr, - info->line); - info->msr |= UART_MSR_RI; - isdn_tty_modem_result(RESULT_RING, info); - isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1); - return 1; - } - } - } - } - restore_flags(flags); - printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz, - ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored"); - return (wret == 2)?3:0; -} - -#define TTY_IS_ACTIVE(info) \ - (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE)) - -int -isdn_tty_stat_callback(int i, isdn_ctrl *c) -{ - int mi; - modem_info *info; - char *e; - - if (i < 0) - return 0; - if ((mi = dev->m_idx[i]) >= 0) { - info = &dev->mdm.info[mi]; - switch (c->command) { - case ISDN_STAT_CINF: - printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num); - info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10); - if (e == (char *)c->parm.num) - info->emu.charge = 0; - - break; - case ISDN_STAT_BSENT: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line); -#endif - if ((info->isdn_driver == c->driver) && - (info->isdn_channel == c->arg)) { - info->msr |= UART_MSR_CTS; - if (info->send_outstanding) - if (!(--info->send_outstanding)) - info->lsr |= UART_LSR_TEMT; - isdn_tty_tint(info); - return 1; - } - break; - case ISDN_STAT_CAUSE: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line); -#endif - /* Signal cause to tty-device */ - strncpy(info->last_cause, c->parm.num, 5); - return 1; - case ISDN_STAT_DISPLAY: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line); -#endif - /* Signal display to tty-device */ - if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) && - !(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) { - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout("DISPLAY: ", info); - isdn_tty_at_cout(c->parm.display, info); - isdn_tty_at_cout("\r\n", info); - } - return 1; - case ISDN_STAT_DCONN: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line); -#endif - if (TTY_IS_ACTIVE(info)) { - if (info->dialing == 1) { - info->dialing = 2; - return 1; - } - } - break; - case ISDN_STAT_DHUP: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line); -#endif - if (TTY_IS_ACTIVE(info)) { - if (info->dialing == 1) - isdn_tty_modem_result(RESULT_BUSY, info); - if (info->dialing > 1) - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - info->dialing = 0; -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n"); -#endif - isdn_tty_modem_hup(info, 0); - return 1; - } - break; - case ISDN_STAT_BCONN: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line); -#endif - /* Schedule CONNECT-Message to any tty - * waiting for it and - * set DCD-bit of its modem-status. - */ - if (TTY_IS_ACTIVE(info)) { - info->msr |= UART_MSR_DCD; - info->emu.charge = 0; - if (info->dialing & 0xf) - info->last_dir = 1; - else - info->last_dir = 0; - info->dialing = 0; - info->rcvsched = 1; - if (USG_MODEM(dev->usage[i])) { - if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) { - strcpy(info->emu.connmsg, c->parm.num); - isdn_tty_modem_result(RESULT_CONNECT, info); - } else - isdn_tty_modem_result(RESULT_CONNECT64000, info); - } - if (USG_VOICE(dev->usage[i])) - isdn_tty_modem_result(RESULT_VCON, info); - return 1; - } - break; - case ISDN_STAT_BHUP: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_BHUP ttyI%d\n", info->line); -#endif - if (TTY_IS_ACTIVE(info)) { -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n"); -#endif - isdn_tty_modem_hup(info, 0); - return 1; - } - break; - case ISDN_STAT_NODCH: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line); -#endif - if (TTY_IS_ACTIVE(info)) { - if (info->dialing) { - info->dialing = 0; - info->last_l2 = -1; - info->last_si = 0; - sprintf(info->last_cause, "0000"); - isdn_tty_modem_result(RESULT_NO_DIALTONE, info); - } - isdn_tty_modem_hup(info, 0); - return 1; - } - break; - case ISDN_STAT_UNLOAD: -#ifdef ISDN_TTY_STAT_DEBUG - printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line); -#endif - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - info = &dev->mdm.info[i]; - if (info->isdn_driver == c->driver) { - if (info->online) - isdn_tty_modem_hup(info, 1); - } - } - return 1; -#ifdef CONFIG_ISDN_TTY_FAX - case ISDN_STAT_FAXIND: - if (TTY_IS_ACTIVE(info)) { - isdn_tty_fax_command(info, c); - } - break; -#endif -#ifdef CONFIG_ISDN_AUDIO - case ISDN_STAT_AUDIO: - if (TTY_IS_ACTIVE(info)) { - switch(c->parm.num[0]) { - case ISDN_AUDIO_DTMF: - if (info->vonline) { - isdn_audio_put_dle_code(info, - c->parm.num[1]); - } - break; - } - } - break; -#endif - } - } - return 0; -} - -/********************************************************************* - Modem-Emulator-Routines - *********************************************************************/ - -#define cmdchar(c) ((c>=' ')&&(c<=0x7f)) - -/* - * Put a message from the AT-emulator into receive-buffer of tty, - * convert CR, LF, and BS to values in modem-registers 3, 4 and 5. - */ -void -isdn_tty_at_cout(char *msg, modem_info * info) -{ - struct tty_struct *tty; - atemu *m = &info->emu; - char *p; - char c; - ulong flags; - struct sk_buff *skb = 0; - char *sp = 0; - - if (!msg) { - printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n"); - return; - } - save_flags(flags); - cli(); - tty = info->tty; - if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) { - restore_flags(flags); - return; - } - - /* use queue instead of direct flip, if online and */ - /* data is in queue or flip buffer is full */ - if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) || - (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) { - skb = alloc_skb(strlen(msg) -#ifdef CONFIG_ISDN_AUDIO - + sizeof(isdn_audio_skb) -#endif - , GFP_ATOMIC); - if (!skb) { - restore_flags(flags); - return; - } -#ifdef CONFIG_ISDN_AUDIO - skb_reserve(skb, sizeof(isdn_audio_skb)); -#endif - sp = skb_put(skb, strlen(msg)); -#ifdef CONFIG_ISDN_AUDIO - ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; - ISDN_AUDIO_SKB_LOCK(skb) = 0; -#endif - } - - for (p = msg; *p; p++) { - switch (*p) { - case '\r': - c = m->mdmreg[REG_CR]; - break; - case '\n': - c = m->mdmreg[REG_LF]; - break; - case '\b': - c = m->mdmreg[REG_BS]; - break; - default: - c = *p; - } - if (skb) { - *sp++ = c; - } else { - if (tty->flip.count >= TTY_FLIPBUF_SIZE) - break; - tty_insert_flip_char(tty, c, 0); - } - } - if (skb) { - __skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb); - dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len; - restore_flags(flags); - /* Schedule dequeuing */ - if ((dev->modempoll) && (info->rcvsched)) - isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); - - } else { - restore_flags(flags); - queue_task(&tty->flip.tqueue, &tq_timer); - } -} - -/* - * Perform ATH Hangup - */ -static void -isdn_tty_on_hook(modem_info * info) -{ - if (info->isdn_channel >= 0) { -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n"); -#endif - isdn_tty_modem_hup(info, 1); - } -} - -static void -isdn_tty_off_hook(void) -{ - printk(KERN_DEBUG "isdn_tty_off_hook\n"); -} - -#define PLUSWAIT1 (HZ/2) /* 0.5 sec. */ -#define PLUSWAIT2 (HZ*3/2) /* 1.5 sec */ - -/* - * Check Buffer for Modem-escape-sequence, activate timer-callback to - * isdn_tty_modem_escape() if sequence found. - * - * Parameters: - * p pointer to databuffer - * plus escape-character - * count length of buffer - * pluscount count of valid escape-characters so far - * lastplus timestamp of last character - */ -static void -isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount, - int *lastplus, int from_user) -{ - char cbuf[3]; - - if (plus > 127) - return; - if (count > 3) { - p += count - 3; - count = 3; - *pluscount = 0; - } - if (from_user) { - copy_from_user(cbuf, p, count); - p = cbuf; - } - while (count > 0) { - if (*(p++) == plus) { - if ((*pluscount)++) { - /* Time since last '+' > 0.5 sec. ? */ - if ((jiffies - *lastplus) > PLUSWAIT1) - *pluscount = 1; - } else { - /* Time since last non-'+' < 1.5 sec. ? */ - if ((jiffies - *lastplus) < PLUSWAIT2) - *pluscount = 0; - } - if ((*pluscount == 3) && (count = 1)) - isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1); - if (*pluscount > 3) - *pluscount = 1; - } else - *pluscount = 0; - *lastplus = jiffies; - count--; - } -} - -/* - * Return result of AT-emulator to tty-receive-buffer, depending on - * modem-register 12, bit 0 and 1. - * For CONNECT-messages also switch to online-mode. - * For RING-message handle auto-ATA if register 0 != 0 - */ - -static void -isdn_tty_modem_result(int code, modem_info * info) -{ - atemu *m = &info->emu; - static char *msg[] = - {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR", - "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER", - "RINGING", "NO MSN/EAZ", "VCON", "RUNG"}; - ulong flags; - char s[ISDN_MSNLEN+10]; - - switch (code) { - case RESULT_RING: - m->mdmreg[REG_RINGCNT]++; - if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA]) - /* Automatically accept incoming call */ - isdn_tty_cmd_ATA(info); - break; - case RESULT_NO_CARRIER: -#ifdef ISDN_DEBUG_MODEM_HUP - printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n", - (info->flags & ISDN_ASYNC_CLOSING), - (!info->tty)); -#endif - save_flags(flags); - cli(); - m->mdmreg[REG_RINGCNT] = 0; - del_timer(&info->nc_timer); - info->ncarrier = 0; - if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { - restore_flags(flags); - return; - } - restore_flags(flags); -#ifdef CONFIG_ISDN_AUDIO - if (info->vonline & 1) { -#ifdef ISDN_DEBUG_MODEM_VOICE - printk(KERN_DEBUG "res3: send DLE-ETX on ttyI%d\n", - info->line); -#endif - /* voice-recording, add DLE-ETX */ - isdn_tty_at_cout("\020\003", info); - } - if (info->vonline & 2) { -#ifdef ISDN_DEBUG_MODEM_VOICE - printk(KERN_DEBUG "res3: send DLE-DC4 on ttyI%d\n", - info->line); -#endif - /* voice-playing, add DLE-DC4 */ - isdn_tty_at_cout("\020\024", info); - } -#endif - break; - case RESULT_CONNECT: - case RESULT_CONNECT64000: - sprintf(info->last_cause, "0000"); - if (!info->online) - info->online = 2; - break; - case RESULT_VCON: -#ifdef ISDN_DEBUG_MODEM_VOICE - printk(KERN_DEBUG "res3: send VCON on ttyI%d\n", - info->line); -#endif - sprintf(info->last_cause, "0000"); - if (!info->online) - info->online = 1; - break; - } /* switch(code) */ - - if (m->mdmreg[REG_RESP] & BIT_RESP) { - /* Show results */ - if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) { - /* Show numeric results only */ - sprintf(s, "\r\n%d\r\n", code); - isdn_tty_at_cout(s, info); - } else { - if (code == RESULT_RING) { - /* return if "show RUNG" and ringcounter>1 */ - if ((m->mdmreg[REG_RUNG] & BIT_RUNG) && - (m->mdmreg[REG_RINGCNT] > 1)) - return; - /* print CID, _before_ _every_ ring */ - if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) { - isdn_tty_at_cout("\r\nCALLER NUMBER: ", info); - isdn_tty_at_cout(dev->num[info->drv_index], info); - } - } - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout(msg[code], info); - switch (code) { - case RESULT_CONNECT: - switch (m->mdmreg[REG_L2PROT]) { - case ISDN_PROTO_L2_MODEM: - isdn_tty_at_cout(" ", info); - isdn_tty_at_cout(m->connmsg, info); - break; - } - break; - case RESULT_RING: - /* Append CPN, if enabled */ - if ((m->mdmreg[REG_CPN] & BIT_CPN)) { - sprintf(s, "/%s", m->cpn); - isdn_tty_at_cout(s, info); - } - /* Print CID only once, _after_ 1st RING */ - if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) && - (m->mdmreg[REG_RINGCNT] == 1)) { - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout("CALLER NUMBER: ", info); - isdn_tty_at_cout(dev->num[info->drv_index], info); - } - break; - case RESULT_NO_CARRIER: - case RESULT_NO_DIALTONE: - case RESULT_BUSY: - case RESULT_NO_ANSWER: - m->mdmreg[REG_RINGCNT] = 0; - /* Append Cause-Message if enabled */ - if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) { - sprintf(s, "/%s", info->last_cause); - isdn_tty_at_cout(s, info); - } - break; - case RESULT_CONNECT64000: - /* Append Protocol to CONNECT message */ - switch (m->mdmreg[REG_L2PROT]) { - case ISDN_PROTO_L2_X75I: - case ISDN_PROTO_L2_X75UI: - case ISDN_PROTO_L2_X75BUI: - isdn_tty_at_cout("/X.75", info); - break; - case ISDN_PROTO_L2_HDLC: - isdn_tty_at_cout("/HDLC", info); - break; - case ISDN_PROTO_L2_V11096: - isdn_tty_at_cout("/V110/9600", info); - break; - case ISDN_PROTO_L2_V11019: - isdn_tty_at_cout("/V110/19200", info); - break; - case ISDN_PROTO_L2_V11038: - isdn_tty_at_cout("/V110/38400", info); - break; - } - if (m->mdmreg[REG_T70] & BIT_T70) { - isdn_tty_at_cout("/T.70", info); - if (m->mdmreg[REG_T70] & BIT_T70_EXT) - isdn_tty_at_cout("+", info); - } - break; - } - isdn_tty_at_cout("\r\n", info); - } - } - if (code == RESULT_NO_CARRIER) { - save_flags(flags); - cli(); - if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) { - restore_flags(flags); - return; - } - 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)))) { - tty_hangup(info->tty); - } - restore_flags(flags); - } -} - - -/* - * Display a modem-register-value. - */ -static void -isdn_tty_show_profile(int ridx, modem_info * info) -{ - char v[6]; - - sprintf(v, "\r\n%d", info->emu.mdmreg[ridx]); - isdn_tty_at_cout(v, info); -} - -/* - * Get MSN-string from char-pointer, set pointer to end of number - */ -static void -isdn_tty_get_msnstr(char *n, char **p) -{ - int limit = ISDN_MSNLEN - 1; - - while (((*p[0] >= '0' && *p[0] <= '9') || - /* Why a comma ??? */ - (*p[0] == ',')) && - (limit--)) - *n++ = *p[0]++; - *n = '\0'; -} - -/* - * Get phone-number from modem-commandbuffer - */ -static void -isdn_tty_getdial(char *p, char *q,int cnt) -{ - int first = 1; - int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid - buffer overflow */ - - while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) { - if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) || - (*p == '*') || (*p == '#')) { - *q++ = *p; - limit--; - } - if(!limit) - break; - p++; - first = 0; - } - *q = 0; -} - -#define PARSE_ERROR { isdn_tty_modem_result(RESULT_ERROR, info); return; } -#define PARSE_ERROR1 { isdn_tty_modem_result(RESULT_ERROR, info); return 1; } - -static void -isdn_tty_report(modem_info * info) -{ - atemu *m = &info->emu; - char s[80]; - - isdn_tty_at_cout("\r\nStatistics of last connection:\r\n\r\n", info); - sprintf(s, " Remote Number: %s\r\n", info->last_num); - isdn_tty_at_cout(s, info); - sprintf(s, " Direction: %s\r\n", info->last_dir ? "outgoing" : "incoming"); - isdn_tty_at_cout(s, info); - isdn_tty_at_cout(" Layer-2 Protocol: ", info); - switch (info->last_l2) { - case ISDN_PROTO_L2_X75I: - isdn_tty_at_cout("X.75i", info); - break; - case ISDN_PROTO_L2_X75UI: - isdn_tty_at_cout("X.75ui", info); - break; - case ISDN_PROTO_L2_X75BUI: - isdn_tty_at_cout("X.75bui", info); - break; - case ISDN_PROTO_L2_HDLC: - isdn_tty_at_cout("HDLC", info); - break; - case ISDN_PROTO_L2_V11096: - isdn_tty_at_cout("V.110 9600 Baud", info); - break; - case ISDN_PROTO_L2_V11019: - isdn_tty_at_cout("V.110 19200 Baud", info); - break; - case ISDN_PROTO_L2_V11038: - isdn_tty_at_cout("V.110 38400 Baud", info); - break; - case ISDN_PROTO_L2_TRANS: - isdn_tty_at_cout("transparent", info); - break; - case ISDN_PROTO_L2_MODEM: - isdn_tty_at_cout("modem", info); - break; - case ISDN_PROTO_L2_FAX: - isdn_tty_at_cout("fax", info); - break; - default: - isdn_tty_at_cout("unknown", info); - break; - } - if (m->mdmreg[REG_T70] & BIT_T70) { - isdn_tty_at_cout("/T.70", info); - if (m->mdmreg[REG_T70] & BIT_T70_EXT) - isdn_tty_at_cout("+", info); - } - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout(" Service: ", info); - switch (info->last_si) { - case 1: - isdn_tty_at_cout("audio\r\n", info); - break; - case 5: - isdn_tty_at_cout("btx\r\n", info); - break; - case 7: - isdn_tty_at_cout("data\r\n", info); - break; - default: - sprintf(s, "%d\r\n", info->last_si); - isdn_tty_at_cout(s, info); - break; - } - sprintf(s, " Hangup location: %s\r\n", info->last_lhup ? "local" : "remote"); - isdn_tty_at_cout(s, info); - sprintf(s, " Last cause: %s\r\n", info->last_cause); - isdn_tty_at_cout(s, info); -} - -/* - * Parse AT&.. commands. - */ -static int -isdn_tty_cmd_ATand(char **p, modem_info * info) -{ - atemu *m = &info->emu; - int i; - char rb[100]; - -#define MAXRB (sizeof(rb) - 1) - - switch (*p[0]) { - case 'B': - /* &B - Set Buffersize */ - p[0]++; - i = isdn_getnum(p); - if ((i < 0) || (i > ISDN_SERIAL_XMIT_MAX)) - PARSE_ERROR1; -#ifdef CONFIG_ISDN_AUDIO - if ((m->mdmreg[REG_SI1] & 1) && (i > VBUF)) - PARSE_ERROR1; -#endif - m->mdmreg[REG_PSIZE] = i / 16; - info->xmit_size = m->mdmreg[REG_PSIZE] * 16; - switch (m->mdmreg[REG_L2PROT]) { - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - info->xmit_size /= 10; - } - break; - case 'C': - /* &C - DCD Status */ - p[0]++; - switch (isdn_getnum(p)) { - case 0: - m->mdmreg[REG_DCD] &= ~BIT_DCD; - break; - case 1: - m->mdmreg[REG_DCD] |= BIT_DCD; - break; - default: - PARSE_ERROR1 - } - break; - case 'D': - /* &D - Set DTR-Low-behavior */ - p[0]++; - switch (isdn_getnum(p)) { - case 0: - m->mdmreg[REG_DTRHUP] &= ~BIT_DTRHUP; - m->mdmreg[REG_DTRR] &= ~BIT_DTRR; - break; - case 2: - m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP; - m->mdmreg[REG_DTRR] &= ~BIT_DTRR; - break; - case 3: - m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP; - m->mdmreg[REG_DTRR] |= BIT_DTRR; - break; - default: - PARSE_ERROR1 - } - break; - case 'E': - /* &E -Set EAZ/MSN */ - p[0]++; - isdn_tty_get_msnstr(m->msn, p); - break; - case 'F': - /* &F -Set Factory-Defaults */ - p[0]++; - if (info->msr & UART_MSR_DCD) - PARSE_ERROR1; - isdn_tty_reset_profile(m); - isdn_tty_modem_reset_regs(info, 1); - break; -#ifdef DUMMY_HAYES_AT - case 'K': - /* only for be compilant with common scripts */ - /* &K Flowcontrol - no function */ - p[0]++; - isdn_getnum(p); - break; -#endif - case 'L': - /* &L -Set Numbers to listen on */ - p[0]++; - i = 0; - while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) && - (i < ISDN_LMSNLEN)) - m->lmsn[i++] = *p[0]++; - m->lmsn[i] = '\0'; - break; - case 'R': - /* &R - Set V.110 bitrate adaption */ - p[0]++; - i = isdn_getnum(p); - switch (i) { - case 0: - /* Switch off V.110, back to X.75 */ - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I; - m->mdmreg[REG_SI2] = 0; - info->xmit_size = m->mdmreg[REG_PSIZE] * 16; - break; - case 9600: - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11096; - m->mdmreg[REG_SI2] = 197; - info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10; - break; - case 19200: - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11019; - m->mdmreg[REG_SI2] = 199; - info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10; - break; - case 38400: - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11038; - m->mdmreg[REG_SI2] = 198; /* no existing standard for this */ - info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10; - break; - default: - PARSE_ERROR1; - } - /* Switch off T.70 */ - m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT); - /* Set Service 7 */ - m->mdmreg[REG_SI1] |= 4; - break; - case 'S': - /* &S - Set Windowsize */ - p[0]++; - i = isdn_getnum(p); - if ((i > 0) && (i < 9)) - m->mdmreg[REG_WSIZE] = i; - else - PARSE_ERROR1; - break; - case 'V': - /* &V - Show registers */ - p[0]++; - isdn_tty_at_cout("\r\n", info); - for (i = 0; i < ISDN_MODEM_NUMREG; i++) { - sprintf(rb, "S%02d=%03d%s", i, - m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n"); - isdn_tty_at_cout(rb, info); - } - sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n", - strlen(m->msn) ? m->msn : "None"); - isdn_tty_at_cout(rb, info); - if (strlen(m->lmsn)) { - isdn_tty_at_cout("\r\nListen: ", info); - isdn_tty_at_cout(m->lmsn, info); - isdn_tty_at_cout("\r\n", info); - } - break; - case 'W': - /* &W - Write Profile */ - p[0]++; - switch (*p[0]) { - case '0': - p[0]++; - modem_write_profile(m); - break; - default: - PARSE_ERROR1; - } - break; - case 'X': - /* &X - Switch to BTX-Mode and T.70 */ - p[0]++; - switch (isdn_getnum(p)) { - case 0: - m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT); - info->xmit_size = m->mdmreg[REG_PSIZE] * 16; - break; - case 1: - m->mdmreg[REG_T70] |= BIT_T70; - m->mdmreg[REG_T70] &= ~BIT_T70_EXT; - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I; - info->xmit_size = 112; - m->mdmreg[REG_SI1] = 4; - m->mdmreg[REG_SI2] = 0; - break; - case 2: - m->mdmreg[REG_T70] |= (BIT_T70 | BIT_T70_EXT); - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I; - info->xmit_size = 112; - m->mdmreg[REG_SI1] = 4; - m->mdmreg[REG_SI2] = 0; - break; - default: - PARSE_ERROR1; - } - break; - default: - PARSE_ERROR1; - } - return 0; -} - -static int -isdn_tty_check_ats(int mreg, int mval, modem_info * info, atemu * m) -{ - /* Some plausibility checks */ - switch (mreg) { - case REG_L2PROT: - if (mval > ISDN_PROTO_L2_MAX) - return 1; - break; - case REG_PSIZE: - if ((mval * 16) > ISDN_SERIAL_XMIT_MAX) - return 1; -#ifdef CONFIG_ISDN_AUDIO - if ((m->mdmreg[REG_SI1] & 1) && (mval > VBUFX)) - return 1; -#endif - info->xmit_size = mval * 16; - switch (m->mdmreg[REG_L2PROT]) { - case ISDN_PROTO_L2_V11096: - case ISDN_PROTO_L2_V11019: - case ISDN_PROTO_L2_V11038: - info->xmit_size /= 10; - } - break; - case REG_SI1I: - case REG_PLAN: - case REG_SCREEN: - /* readonly registers */ - return 1; - } - return 0; -} - -/* - * Perform ATS command - */ -static int -isdn_tty_cmd_ATS(char **p, modem_info * info) -{ - atemu *m = &info->emu; - int bitpos; - int mreg; - int mval; - int bval; - - mreg = isdn_getnum(p); - if (mreg < 0 || mreg >= ISDN_MODEM_NUMREG) - PARSE_ERROR1; - switch (*p[0]) { - case '=': - p[0]++; - mval = isdn_getnum(p); - if (mval < 0 || mval > 255) - PARSE_ERROR1; - if (isdn_tty_check_ats(mreg, mval, info, m)) - PARSE_ERROR1; - m->mdmreg[mreg] = mval; - break; - case '.': - /* Set/Clear a single bit */ - p[0]++; - bitpos = isdn_getnum(p); - if ((bitpos < 0) || (bitpos > 7)) - PARSE_ERROR1; - switch (*p[0]) { - case '=': - p[0]++; - bval = isdn_getnum(p); - if (bval < 0 || bval > 1) - PARSE_ERROR1; - if (bval) - mval = m->mdmreg[mreg] | (1 << bitpos); - else - mval = m->mdmreg[mreg] & ~(1 << bitpos); - if (isdn_tty_check_ats(mreg, mval, info, m)) - PARSE_ERROR1; - m->mdmreg[mreg] = mval; - break; - case '?': - p[0]++; - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout((m->mdmreg[mreg] & (1 << bitpos)) ? "1" : "0", - info); - break; - default: - PARSE_ERROR1; - } - break; - case '?': - p[0]++; - isdn_tty_show_profile(mreg, info); - break; - default: - PARSE_ERROR1; - break; - } - return 0; -} - -/* - * Perform ATA command - */ -static void -isdn_tty_cmd_ATA(modem_info * info) -{ - atemu *m = &info->emu; - isdn_ctrl cmd; - int l2; - - if (info->msr & UART_MSR_RI) { - /* Accept incoming call */ - info->last_dir = 0; - strcpy(info->last_num, dev->num[info->drv_index]); - m->mdmreg[REG_RINGCNT] = 0; - info->msr &= ~UART_MSR_RI; - l2 = m->mdmreg[REG_L2PROT]; -#ifdef CONFIG_ISDN_AUDIO - /* If more than one bit set in reg18, autoselect Layer2 */ - if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) { - if (m->mdmreg[REG_SI1I] == 1) { - if ((l2 != ISDN_PROTO_L2_MODEM) && (l2 != ISDN_PROTO_L2_FAX)) - l2 = ISDN_PROTO_L2_TRANS; - } else - l2 = ISDN_PROTO_L2_X75I; - } -#endif - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL2; - cmd.arg = info->isdn_channel + (l2 << 8); - info->last_l2 = l2; - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_SETL3; - cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8); -#ifdef CONFIG_ISDN_TTY_FAX - if (l2 == ISDN_PROTO_L2_FAX) { - cmd.parm.fax = info->fax; - info->fax->direction = ISDN_TTY_FAX_CONN_IN; - } -#endif - isdn_command(&cmd); - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.command = ISDN_CMD_ACCEPTD; - info->dialing = 16; - info->emu.carrierwait = 0; - isdn_command(&cmd); - isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1); - } else - isdn_tty_modem_result(RESULT_NO_ANSWER, info); -} - -#ifdef CONFIG_ISDN_AUDIO -/* - * Parse AT+F.. commands - */ -static int -isdn_tty_cmd_PLUSF(char **p, modem_info * info) -{ - atemu *m = &info->emu; - char rs[20]; - - if (!strncmp(p[0], "CLASS", 5)) { - p[0] += 5; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", - (m->mdmreg[REG_SI1] & 1) ? 8 : 0); -#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 '=': - p[0]++; - switch (*p[0]) { - case '0': - p[0]++; - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I; - m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS; - m->mdmreg[REG_SI1] = 4; - info->xmit_size = - m->mdmreg[REG_PSIZE] * 16; - break; -#ifdef CONFIG_ISDN_TTY_FAX -#ifdef ISDN_TTY_FCLASS1 - case '1': - p[0]++; - if (!(dev->global_features & - ISDN_FEATURE_L3_FCLASS1)) - PARSE_ERROR1; - m->mdmreg[REG_SI1] = 1; - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX; - m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS1; - info->xmit_size = - m->mdmreg[REG_PSIZE] * 16; - break; -#endif - case '2': - p[0]++; - if (!(dev->global_features & - ISDN_FEATURE_L3_FCLASS2)) - PARSE_ERROR1; - m->mdmreg[REG_SI1] = 1; - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX; - m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS2; - info->xmit_size = - m->mdmreg[REG_PSIZE] * 16; - break; -#endif - case '8': - p[0]++; - /* L2 will change on dialout with si=1 */ - m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I; - m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS; - m->mdmreg[REG_SI1] = 5; - info->xmit_size = VBUF; - break; - case '?': - 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,"); -#endif - strcat(rs, "8"); - isdn_tty_at_cout(rs, info); - break; - default: - PARSE_ERROR1; - } - break; - default: - PARSE_ERROR1; - } - return 0; - } -#ifdef CONFIG_ISDN_TTY_FAX - return (isdn_tty_cmd_PLUSF_FAX(p, info)); -#else - PARSE_ERROR1; -#endif -} - -/* - * Parse AT+V.. commands - */ -static int -isdn_tty_cmd_PLUSV(char **p, modem_info * info) -{ - atemu *m = &info->emu; - isdn_ctrl cmd; - static char *vcmd[] = - {"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL}; - int i; - int par1; - int par2; - char rs[20]; - - i = 0; - while (vcmd[i]) { - if (!strncmp(vcmd[i], p[0], 2)) { - p[0] += 2; - break; - } - i++; - } - switch (i) { - case 0: - /* AT+VNH - Auto hangup feature */ - switch (*p[0]) { - case '?': - p[0]++; - isdn_tty_at_cout("\r\n1", info); - break; - case '=': - p[0]++; - switch (*p[0]) { - case '1': - p[0]++; - break; - case '?': - p[0]++; - isdn_tty_at_cout("\r\n1", info); - break; - default: - PARSE_ERROR1; - } - break; - default: - PARSE_ERROR1; - } - break; - case 1: - /* AT+VIP - Reset all voice parameters */ - isdn_tty_modem_reset_vpar(m); - break; - case 2: - /* AT+VLS - Select device, accept incoming call */ - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", m->vpar[0]); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - switch (*p[0]) { - case '0': - p[0]++; - m->vpar[0] = 0; - break; - case '2': - p[0]++; - m->vpar[0] = 2; - break; - case '?': - p[0]++; - isdn_tty_at_cout("\r\n0,2", info); - break; - default: - PARSE_ERROR1; - } - break; - default: - PARSE_ERROR1; - } - break; - case 3: - /* AT+VRX - Start recording */ - if (!m->vpar[0]) - PARSE_ERROR1; - if (info->online != 1) { - isdn_tty_modem_result(RESULT_NO_ANSWER, info); - return 1; - } - info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state); - if (!info->dtmf_state) { - printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n"); - PARSE_ERROR1; - } - info->silence_state = isdn_audio_silence_init(info->silence_state); - if (!info->silence_state) { - printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n"); - PARSE_ERROR1; - } - if (m->vpar[3] < 5) { - info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]); - if (!info->adpcmr) { - printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n"); - PARSE_ERROR1; - } - } -#ifdef ISDN_DEBUG_AT - printk(KERN_DEBUG "AT: +VRX\n"); -#endif - info->vonline |= 1; - isdn_tty_modem_result(RESULT_CONNECT, info); - return 0; - break; - case 4: - /* AT+VSD - Silence detection */ - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n<%d>,<%d>", - m->vpar[1], - m->vpar[2]); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if ((*p[0]>='0') && (*p[0]<='9')) { - par1 = isdn_getnum(p); - if ((par1 < 0) || (par1 > 31)) - PARSE_ERROR1; - if (*p[0] != ',') - PARSE_ERROR1; - p[0]++; - par2 = isdn_getnum(p); - if ((par2 < 0) || (par2 > 255)) - PARSE_ERROR1; - m->vpar[1] = par1; - m->vpar[2] = par2; - break; - } else - if (*p[0] == '?') { - p[0]++; - isdn_tty_at_cout("\r\n<0-31>,<0-255>", - info); - break; - } else - PARSE_ERROR1; - break; - default: - PARSE_ERROR1; - } - break; - case 5: - /* AT+VSM - Select compression */ - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n<%d>,<%d><8000>", - m->vpar[3], - m->vpar[1]); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - switch (*p[0]) { - case '2': - case '3': - case '4': - case '5': - case '6': - par1 = isdn_getnum(p); - if ((par1 < 2) || (par1 > 6)) - PARSE_ERROR1; - m->vpar[3] = par1; - break; - case '?': - p[0]++; - isdn_tty_at_cout("\r\n2;ADPCM;2;0;(8000)\r\n", - info); - isdn_tty_at_cout("3;ADPCM;3;0;(8000)\r\n", - info); - isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n", - info); - isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n", - info); - isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n", - info); - break; - default: - PARSE_ERROR1; - } - break; - default: - PARSE_ERROR1; - } - break; - case 6: - /* AT+VTX - Start sending */ - if (!m->vpar[0]) - PARSE_ERROR1; - if (info->online != 1) { - isdn_tty_modem_result(RESULT_NO_ANSWER, info); - return 1; - } - info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state); - if (!info->dtmf_state) { - printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n"); - PARSE_ERROR1; - } - if (m->vpar[3] < 5) { - info->adpcms = isdn_audio_adpcm_init(info->adpcms, m->vpar[3]); - if (!info->adpcms) { - printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n"); - PARSE_ERROR1; - } - } -#ifdef ISDN_DEBUG_AT - printk(KERN_DEBUG "AT: +VTX\n"); -#endif - m->lastDLE = 0; - info->vonline |= 2; - isdn_tty_modem_result(RESULT_CONNECT, info); - return 0; - break; - case 7: - /* AT+VDD - DTMF detection */ - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n<%d>,<%d>", - m->vpar[4], - m->vpar[5]); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if ((*p[0]>='0') && (*p[0]<='9')) { - if (info->online != 1) - PARSE_ERROR1; - par1 = isdn_getnum(p); - if ((par1 < 0) || (par1 > 15)) - PARSE_ERROR1; - if (*p[0] != ',') - PARSE_ERROR1; - p[0]++; - par2 = isdn_getnum(p); - if ((par2 < 0) || (par2 > 255)) - PARSE_ERROR1; - m->vpar[4] = par1; - m->vpar[5] = par2; - cmd.driver = info->isdn_driver; - cmd.command = ISDN_CMD_AUDIO; - cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8); - cmd.parm.num[0] = par1; - cmd.parm.num[1] = par2; - isdn_command(&cmd); - break; - } else - if (*p[0] == '?') { - p[0]++; - isdn_tty_at_cout("\r\n<0-15>,<0-255>", - info); - break; - } else - PARSE_ERROR1; - break; - default: - PARSE_ERROR1; - } - break; - default: - PARSE_ERROR1; - } - return 0; -} -#endif /* CONFIG_ISDN_AUDIO */ - -/* - * Parse and perform an AT-command-line. - */ -static void -isdn_tty_parse_at(modem_info * info) -{ - atemu *m = &info->emu; - char *p; - char ds[40]; - -#ifdef ISDN_DEBUG_AT - printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd); -#endif - for (p = &m->mdmcmd[2]; *p;) { - switch (*p) { - case ' ': - p++; - break; - case 'A': - /* A - Accept incoming call */ - p++; - isdn_tty_cmd_ATA(info); - return; - break; - case 'D': - /* D - Dial */ - if (info->msr & UART_MSR_DCD) - PARSE_ERROR; - if (info->msr & UART_MSR_RI) { - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - return; - } - isdn_tty_getdial(++p, ds, sizeof ds); - p += strlen(p); - if (!strlen(m->msn)) - isdn_tty_modem_result(RESULT_NO_MSN_EAZ, info); - else if (strlen(ds)) - isdn_tty_dial(ds, info, m); - else - PARSE_ERROR; - return; - case 'E': - /* E - Turn Echo on/off */ - p++; - switch (isdn_getnum(&p)) { - case 0: - m->mdmreg[REG_ECHO] &= ~BIT_ECHO; - break; - case 1: - m->mdmreg[REG_ECHO] |= BIT_ECHO; - break; - default: - PARSE_ERROR; - } - break; - case 'H': - /* H - On/Off-hook */ - p++; - switch (*p) { - case '0': - p++; - isdn_tty_on_hook(info); - break; - case '1': - p++; - isdn_tty_off_hook(); - break; - default: - isdn_tty_on_hook(info); - break; - } - break; - case 'I': - /* I - Information */ - p++; - isdn_tty_at_cout("\r\nLinux ISDN", info); - switch (*p) { - case '0': - case '1': - p++; - break; - case '2': - p++; - isdn_tty_report(info); - break; - case '3': - p++; - sprintf(ds, "\r\n%d", info->emu.charge); - isdn_tty_at_cout(ds, info); - break; - default: - } - break; -#ifdef DUMMY_HAYES_AT - case 'L': - case 'M': - /* only for be compilant with common scripts */ - /* no function */ - p++; - isdn_getnum(&p); - break; -#endif - case 'O': - /* O - Go online */ - p++; - if (info->msr & UART_MSR_DCD) - /* if B-Channel is up */ - isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? RESULT_CONNECT:RESULT_CONNECT64000, info); - else - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - return; - case 'Q': - /* Q - Turn Emulator messages on/off */ - p++; - switch (isdn_getnum(&p)) { - case 0: - m->mdmreg[REG_RESP] |= BIT_RESP; - break; - case 1: - m->mdmreg[REG_RESP] &= ~BIT_RESP; - break; - default: - PARSE_ERROR; - } - break; - case 'S': - /* S - Set/Get Register */ - p++; - if (isdn_tty_cmd_ATS(&p, info)) - return; - break; - case 'V': - /* V - Numeric or ASCII Emulator-messages */ - p++; - switch (isdn_getnum(&p)) { - case 0: - m->mdmreg[REG_RESP] |= BIT_RESPNUM; - break; - case 1: - m->mdmreg[REG_RESP] &= ~BIT_RESPNUM; - break; - default: - PARSE_ERROR; - } - break; - case 'Z': - /* Z - Load Registers from Profile */ - p++; - if (info->msr & UART_MSR_DCD) { - info->online = 0; - isdn_tty_on_hook(info); - } - isdn_tty_modem_reset_regs(info, 1); - break; - case '+': - p++; - switch (*p) { -#ifdef CONFIG_ISDN_AUDIO - case 'F': - p++; - if (isdn_tty_cmd_PLUSF(&p, info)) - return; - break; - case 'V': - if ((!(m->mdmreg[REG_SI1] & 1)) || - (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM)) - PARSE_ERROR; - p++; - if (isdn_tty_cmd_PLUSV(&p, info)) - return; - break; -#endif /* CONFIG_ISDN_AUDIO */ - case 'S': /* SUSPEND */ - p++; - isdn_tty_get_msnstr(ds, &p); - isdn_tty_suspend(ds, info, m); - break; - case 'R': /* RESUME */ - p++; - isdn_tty_get_msnstr(ds, &p); - isdn_tty_resume(ds, info, m); - break; - case 'M': /* MESSAGE */ - p++; - isdn_tty_send_msg(info, m, p); - break; - default: - PARSE_ERROR; - } - break; - case '&': - p++; - if (isdn_tty_cmd_ATand(&p, info)) - return; - break; - default: - PARSE_ERROR; - } - } -#ifdef CONFIG_ISDN_AUDIO - if (!info->vonline) -#endif - isdn_tty_modem_result(RESULT_OK, info); -} - -/* Need own toupper() because standard-toupper is not available - * within modules. - */ -#define my_toupper(c) (((c>='a')&&(c<='z'))?(c&0xdf):c) - -/* - * Perform line-editing of AT-commands - * - * Parameters: - * p inputbuffer - * count length of buffer - * channel index to line (minor-device) - * user flag: buffer is in userspace - */ -static int -isdn_tty_edit_at(const char *p, int count, modem_info * info, int user) -{ - atemu *m = &info->emu; - int total = 0; - u_char c; - char eb[2]; - int cnt; - - for (cnt = count; cnt > 0; p++, cnt--) { - if (user) - get_user(c, p); - else - c = *p; - total++; - if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) { - /* Separator (CR or LF) */ - m->mdmcmd[m->mdmcmdl] = 0; - if (m->mdmreg[REG_ECHO] & BIT_ECHO) { - eb[0] = c; - eb[1] = 0; - isdn_tty_at_cout(eb, info); - } - if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2)))) - isdn_tty_parse_at(info); - m->mdmcmdl = 0; - continue; - } - if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) { - /* Backspace-Function */ - if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) { - if (m->mdmcmdl) - m->mdmcmdl--; - if (m->mdmreg[REG_ECHO] & BIT_ECHO) - isdn_tty_at_cout("\b", info); - } - continue; - } - if (cmdchar(c)) { - if (m->mdmreg[REG_ECHO] & BIT_ECHO) { - eb[0] = c; - eb[1] = 0; - isdn_tty_at_cout(eb, info); - } - if (m->mdmcmdl < 255) { - c = my_toupper(c); - switch (m->mdmcmdl) { - case 1: - if (c == 'T') { - m->mdmcmd[m->mdmcmdl] = c; - m->mdmcmd[++m->mdmcmdl] = 0; - break; - } else - m->mdmcmdl = 0; - /* Fall through, check for 'A' */ - case 0: - if (c == 'A') { - m->mdmcmd[m->mdmcmdl] = c; - m->mdmcmd[++m->mdmcmdl] = 0; - } - break; - default: - m->mdmcmd[m->mdmcmdl] = c; - m->mdmcmd[++m->mdmcmdl] = 0; - } - } - } - } - return total; -} - -/* - * Switch all modem-channels who are online and got a valid - * escape-sequence 1.5 seconds ago, to command-mode. - * This function is called every second via timer-interrupt from within - * timer-dispatcher isdn_timer_function() - */ -void -isdn_tty_modem_escape(void) -{ - int ton = 0; - int i; - int midx; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if (USG_MODEM(dev->usage[i])) - if ((midx = dev->m_idx[i]) >= 0) { - modem_info *info = &dev->mdm.info[midx]; - if (info->online) { - ton = 1; - if ((info->emu.pluscount == 3) && - ((jiffies - info->emu.lastplus) > PLUSWAIT2)) { - info->emu.pluscount = 0; - info->online = 0; - isdn_tty_modem_result(RESULT_OK, info); - } - } - } - isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton); -} - -/* - * Put a RING-message to all modem-channels who have the RI-bit set. - * This function is called every second via timer-interrupt from within - * timer-dispatcher isdn_timer_function() - */ -void -isdn_tty_modem_ring(void) -{ - int ton = 0; - int i; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - modem_info *info = &dev->mdm.info[i]; - if (info->msr & UART_MSR_RI) { - ton = 1; - isdn_tty_modem_result(RESULT_RING, info); - } - } - isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton); -} - -/* - * For all online tty's, try sending data to - * the lower levels. - */ -void -isdn_tty_modem_xmit(void) -{ - int ton = 1; - int i; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - modem_info *info = &dev->mdm.info[i]; - if (info->online) { - ton = 1; - isdn_tty_senddown(info); - isdn_tty_tint(info); - } - } - isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton); -} - -/* - * Check all channels if we have a 'no carrier' timeout. - * Timeout value is set by Register S7. - */ -void -isdn_tty_carrier_timeout(void) -{ - int ton = 0; - int i; - - for (i = 0; i < ISDN_MAX_CHANNELS; i++) { - modem_info *info = &dev->mdm.info[i]; - if (info->dialing) { - if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) { - info->dialing = 0; - isdn_tty_modem_result(RESULT_NO_CARRIER, info); - isdn_tty_modem_hup(info, 1); - } - else - ton = 1; - } - } - isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton); -} diff --git a/drivers/isdn/isdn_tty.h b/drivers/isdn/isdn_tty.h deleted file mode 100644 index adbf526d..00000000 --- a/drivers/isdn/isdn_tty.h +++ /dev/null @@ -1,207 +0,0 @@ -/* $Id$ - - * header for Linux ISDN subsystem, tty related functions (linklevel). - * - * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg - * - * 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. - * - * $Log$ - * Revision 1.18 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.17 1999/09/21 19:00:35 armin - * Extended FCON message with added CPN - * can now be activated with Bit 1 of Reg 23. - * - * Revision 1.16 1999/08/22 20:26:10 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.15 1999/07/31 12:59:48 armin - * Added tty fax capabilities. - * - * Revision 1.14 1999/07/11 17:14:15 armin - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * Moved "Add CPN to RING message" to new register S23, - * "Display message" is now correct on register S13 bit 7. - * New audio command AT+VDD implemented (deactivate DTMF decoder and - * activate possible existing hardware/DSP decoder). - * Moved some tty defines to .h file. - * Made whitespace possible in AT command line. - * Some AT-emulator output bugfixes. - * First Fax G3 implementations. - * - * Revision 1.13 1999/04/12 12:33:46 fritz - * Changes from 2.0 tree. - * - * Revision 1.12 1999/03/02 12:04:51 armin - * -added ISDN_STAT_ADDCH to increase supported channels after - * register_isdn(). - * -ttyI now goes on-hook on ATZ when B-Ch is connected. - * -added timer-function for register S7 (Wait for Carrier). - * -analog modem (ISDN_PROTO_L2_MODEM) implementations. - * -on L2_MODEM a string will be appended to the CONNECT-Message, - * which is provided by the HL-Driver in parm.num in ISDN_STAT_BCONN. - * -variable "dialing" used for ATA also, for interrupting call - * establishment and register S7. - * - * Revision 1.11 1998/03/19 13:18:27 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 1.10 1997/03/02 14:29:26 fritz - * More ttyI related cleanup. - * - * Revision 1.9 1997/02/28 02:32:49 fritz - * Cleanup: Moved some tty related stuff from isdn_common.c - * to isdn_tty.c - * Bugfix: Bisync protocol did not behave like documented. - * - * Revision 1.8 1997/02/10 20:12:50 fritz - * Changed interface for reporting incoming calls. - * - * Revision 1.7 1997/02/03 23:06:10 fritz - * Reformatted according CodingStyle - * - * Revision 1.6 1997/01/14 01:35:19 fritz - * Changed prototype of isdn_tty_modem_hup. - * - * Revision 1.5 1996/05/17 03:52:31 fritz - * Changed DLE handling for audio receive. - * - * Revision 1.4 1996/05/11 21:52:34 fritz - * Changed queue management to use sk_buffs. - * - * Revision 1.3 1996/05/07 09:16:34 fritz - * Changed isdn_try_read parameter. - * - * Revision 1.2 1996/04/30 21:05:27 fritz - * Test commit - * - * Revision 1.1 1996/01/10 21:39:22 fritz - * Initial revision - * - */ - -#include - -#define DLE 0x10 -#define ETX 0x03 -#define DC4 0x14 - - -/* - * Definition of some special Registers of AT-Emulator - */ -#define REG_RINGATA 0 -#define REG_RINGCNT 1 /* ring counter register */ -#define REG_ESC 2 -#define REG_CR 3 -#define REG_LF 4 -#define REG_BS 5 - -#define REG_WAITC 7 - -#define REG_RESP 12 /* show response messages register */ -#define BIT_RESP 1 /* show response messages bit */ -#define REG_RESPNUM 12 /* show numeric responses register */ -#define BIT_RESPNUM 2 /* show numeric responses bit */ -#define REG_ECHO 12 -#define BIT_ECHO 4 -#define REG_DCD 12 -#define BIT_DCD 8 -#define REG_CTS 12 -#define BIT_CTS 16 -#define REG_DTRR 12 -#define BIT_DTRR 32 -#define REG_DSR 12 -#define BIT_DSR 64 -#define REG_CPPP 12 -#define BIT_CPPP 128 - -#define REG_T70 13 -#define BIT_T70 2 -#define BIT_T70_EXT 32 -#define REG_DTRHUP 13 -#define BIT_DTRHUP 4 -#define REG_RESPXT 13 -#define BIT_RESPXT 8 -#define REG_CIDONCE 13 -#define BIT_CIDONCE 16 -#define REG_RUNG 13 /* show RUNG message register */ -#define BIT_RUNG 64 /* show RUNG message bit */ -#define REG_DISPLAY 13 -#define BIT_DISPLAY 128 - -#define REG_L2PROT 14 -#define REG_L3PROT 15 -#define REG_PSIZE 16 -#define REG_WSIZE 17 -#define REG_SI1 18 -#define REG_SI2 19 -#define REG_SI1I 20 -#define REG_PLAN 21 -#define REG_SCREEN 22 - -#define REG_CPN 23 -#define BIT_CPN 1 -#define BIT_CPNFCON 2 - -/* defines for result codes */ -#define RESULT_OK 0 -#define RESULT_CONNECT 1 -#define RESULT_RING 2 -#define RESULT_NO_CARRIER 3 -#define RESULT_ERROR 4 -#define RESULT_CONNECT64000 5 -#define RESULT_NO_DIALTONE 6 -#define RESULT_BUSY 7 -#define RESULT_NO_ANSWER 8 -#define RESULT_RINGING 9 -#define RESULT_NO_MSN_EAZ 10 -#define RESULT_VCON 11 -#define RESULT_RUNG 12 - -#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)) - -extern void isdn_tty_modem_escape(void); -extern void isdn_tty_modem_ring(void); -extern void isdn_tty_carrier_timeout(void); -extern void isdn_tty_modem_xmit(void); -extern int isdn_tty_modem_init(void); -extern void isdn_tty_readmodem(void); -extern int isdn_tty_find_icall(int, int, setup_parm); -extern void isdn_tty_cleanup_xmit(modem_info *); -extern int isdn_tty_stat_callback(int, isdn_ctrl *); -extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *); -extern int isdn_tty_capi_facility(capi_msg *cm); -extern void isdn_tty_at_cout(char *, modem_info *); -extern void isdn_tty_modem_hup(modem_info *, int); -#ifdef CONFIG_ISDN_TTY_FAX -extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *); -extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *); -extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *); -#endif diff --git a/drivers/isdn/isdn_ttyfax.c b/drivers/isdn/isdn_ttyfax.c deleted file mode 100644 index 48127333..00000000 --- a/drivers/isdn/isdn_ttyfax.c +++ /dev/null @@ -1,1291 +0,0 @@ -/* $Id$ - * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel). - * - * Copyright 1999 by Armin Schindler (mac@melware.de) - * Copyright 1999 by Ralf Spachmann (mel@melware.de) - * Copyright 1999 by Cytronics & Melware - * - * 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. - * - * $Log$ - * Revision 1.5 2000/01/20 19:55:33 keil - * Add FAX Class 1 support - * - * Revision 1.4 1999/09/21 19:00:35 armin - * Extended FCON message with added CPN - * can now be activated with Bit 1 of Reg 23. - * - * Revision 1.3 1999/08/22 20:26:12 calle - * backported changes from kernel 2.3.14: - * - several #include "config.h" gone, others come. - * - "struct device" changed to "struct net_device" in 2.3.14, added a - * define in isdn_compat.h for older kernel versions. - * - * Revision 1.2 1999/08/05 10:36:10 armin - * Bugfix: kernel oops on getting revision. - * - * Revision 1.1 1999/07/31 12:59:50 armin - * Added tty fax capabilities. - * - * - */ - -#undef ISDN_TTY_FAX_STAT_DEBUG -#undef ISDN_TTY_FAX_CMD_DEBUG - -#define __NO_VERSION__ -#include -#include -#include "isdn_common.h" -#include "isdn_tty.h" -#include "isdn_ttyfax.h" - - -static char *isdn_tty_fax_revision = "$Revision$"; - -#define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; } - -static char * -isdn_getrev(const char *revision) -{ - char *rev; - char *p; - - if ((p = strchr(revision, ':'))) { - rev = p + 2; - p = strchr(rev, '$'); - *--p = 0; - } else - rev = "???"; - return rev; -} - -/* - * Fax Class 2 Modem results - * - */ - -static void -isdn_tty_fax_modem_result(int code, modem_info * info) -{ - atemu *m = &info->emu; - T30_s *f = info->fax; - char rs[50]; - char rss[50]; - char *rp; - int i; - static char *msg[] = - {"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:", - "+FHNG:", "+FDCS:", "CONNECT", "+FTSI:", - "+FCFR", "+FPTS:", "+FET:"}; - - - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout(msg[code], info); - -#ifdef ISDN_TTY_FAX_CMD_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax send %s on ttyI%d\n", - msg[code], info->line); -#endif - switch (code) { - case 0: /* OK */ - break; - case 1: /* ERROR */ - break; - case 2: /* +FCON */ - /* Append CPN, if enabled */ - if ((m->mdmreg[REG_CPN] & BIT_CPNFCON) && - (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) { - sprintf(rs, "/%s", m->cpn); - isdn_tty_at_cout(rs, info); - } - info->online = 1; - f->fet = 0; - if (f->phase == ISDN_FAX_PHASE_A) - f->phase = ISDN_FAX_PHASE_B; - break; - case 3: /* +FCSI */ - case 8: /* +FTSI */ - sprintf(rs, "\"%s\"", f->r_id); - isdn_tty_at_cout(rs, info); - break; - case 4: /* +FDIS */ - rs[0] = 0; - rp = &f->r_resolution; - for (i = 0; i < 8; i++) { - sprintf(rss, "%c%s", rp[i] + 48, - (i < 7) ? "," : ""); - strcat(rs, rss); - } - isdn_tty_at_cout(rs, info); -#ifdef ISDN_TTY_FAX_CMD_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n", - rs, info->line); -#endif - break; - case 5: /* +FHNG */ - sprintf(rs, "%d", f->code); - isdn_tty_at_cout(rs, info); - info->faxonline = 0; - break; - case 6: /* +FDCS */ - rs[0] = 0; - rp = &f->r_resolution; - for (i = 0; i < 8; i++) { - sprintf(rss, "%c%s", rp[i] + 48, - (i < 7) ? "," : ""); - strcat(rs, rss); - } - isdn_tty_at_cout(rs, info); -#ifdef ISDN_TTY_FAX_CMD_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n", - rs, info->line); -#endif - break; - case 7: /* CONNECT */ - info->faxonline |= 2; - break; - case 9: /* FCFR */ - break; - case 10: /* FPTS */ - isdn_tty_at_cout("1", info); - break; - case 11: /* FET */ - sprintf(rs, "%d", f->fet); - isdn_tty_at_cout(rs, info); - break; - } - - isdn_tty_at_cout("\r\n", info); - - switch (code) { - case 7: /* CONNECT */ - info->online = 2; - if (info->faxonline & 1) { - sprintf(rs, "%c", XON); - isdn_tty_at_cout(rs, info); - } - break; - } -} - -#ifdef ISDN_TTY_FCLASS1 -int -isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c) -{ - static char *msg[] = - {"OK", "CONNECT", "NO CARRIER", "ERROR", "FCERROR"}; - -#ifdef ISDN_TTY_FAX_CMD_DEBUG - printk(KERN_DEBUG "isdn_tty: FCLASS1 cmd(%d)\n", c->parm.aux.cmd); -#endif - if (c->parm.aux.cmd < ISDN_FAX_CLASS1_QUERY) { - if (info->online) - info->online = 1; - isdn_tty_at_cout("\r\n", info); - isdn_tty_at_cout(msg[c->parm.aux.cmd], info); - isdn_tty_at_cout("\r\n", info); - } - switch (c->parm.aux.cmd) { - case ISDN_FAX_CLASS1_CONNECT: - info->online = 2; - break; - case ISDN_FAX_CLASS1_OK: - case ISDN_FAX_CLASS1_FCERROR: - case ISDN_FAX_CLASS1_ERROR: - case ISDN_FAX_CLASS1_NOCARR: - break; - case ISDN_FAX_CLASS1_QUERY: - isdn_tty_at_cout("\r\n", info); - if (!c->parm.aux.para[0]) { - isdn_tty_at_cout(msg[ISDN_FAX_CLASS1_ERROR], info); - isdn_tty_at_cout("\r\n", info); - } else { - isdn_tty_at_cout(c->parm.aux.para, info); - isdn_tty_at_cout("\r\nOK\r\n", info); - } - break; - } - return (0); -} -#endif - -int -isdn_tty_fax_command(modem_info * info, isdn_ctrl * c) -{ - 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", - f->r_code, info->line); -#endif - switch (f->r_code) { - case ISDN_TTY_FAX_FCON: - info->faxonline = 1; - isdn_tty_fax_modem_result(2, info); /* +FCON */ - return (0); - case ISDN_TTY_FAX_FCON_I: - info->faxonline = 16; - isdn_tty_fax_modem_result(2, info); /* +FCON */ - return (0); - case ISDN_TTY_FAX_RID: - if (info->faxonline & 1) - isdn_tty_fax_modem_result(3, info); /* +FCSI */ - if (info->faxonline & 16) - isdn_tty_fax_modem_result(8, info); /* +FTSI */ - return (0); - case ISDN_TTY_FAX_DIS: - isdn_tty_fax_modem_result(4, info); /* +FDIS */ - return (0); - case ISDN_TTY_FAX_HNG: - if (f->phase == ISDN_FAX_PHASE_C) { - if (f->direction == ISDN_TTY_FAX_CONN_IN) { - sprintf(rs, "%c%c", DLE, ETX); - isdn_tty_at_cout(rs, info); - } else { - sprintf(rs, "%c", 0x18); - isdn_tty_at_cout(rs, info); - } - info->faxonline &= ~2; /* leave data mode */ - info->online = 1; - } - f->phase = ISDN_FAX_PHASE_E; - isdn_tty_fax_modem_result(5, info); /* +FHNG */ - isdn_tty_fax_modem_result(0, info); /* OK */ - return (0); - case ISDN_TTY_FAX_DCS: - isdn_tty_fax_modem_result(6, info); /* +FDCS */ - isdn_tty_fax_modem_result(7, info); /* CONNECT */ - f->phase = ISDN_FAX_PHASE_C; - return (0); - case ISDN_TTY_FAX_TRAIN_OK: - isdn_tty_fax_modem_result(6, info); /* +FDCS */ - isdn_tty_fax_modem_result(0, info); /* OK */ - return (0); - case ISDN_TTY_FAX_SENT: - isdn_tty_fax_modem_result(0, info); /* OK */ - return (0); - case ISDN_TTY_FAX_CFR: - isdn_tty_fax_modem_result(9, info); /* +FCFR */ - return (0); - case ISDN_TTY_FAX_ET: - sprintf(rs, "%c%c", DLE, ETX); - isdn_tty_at_cout(rs, info); - isdn_tty_fax_modem_result(10, info); /* +FPTS */ - isdn_tty_fax_modem_result(11, info); /* +FET */ - isdn_tty_fax_modem_result(0, info); /* OK */ - info->faxonline &= ~2; /* leave data mode */ - info->online = 1; - f->phase = ISDN_FAX_PHASE_D; - return (0); - case ISDN_TTY_FAX_PTS: - isdn_tty_fax_modem_result(10, info); /* +FPTS */ - if (f->direction == ISDN_TTY_FAX_CONN_OUT) { - if (f->fet == 1) - f->phase = ISDN_FAX_PHASE_B; - if (f->fet == 0) - isdn_tty_fax_modem_result(0, info); /* OK */ - } - return (0); - case ISDN_TTY_FAX_EOP: - info->faxonline &= ~2; /* leave data mode */ - info->online = 1; - f->phase = ISDN_FAX_PHASE_D; - return (0); - - } - return (-1); -} - - -void -isdn_tty_fax_bitorder(modem_info * info, struct sk_buff *skb) -{ - __u8 LeftMask; - __u8 RightMask; - __u8 fBit; - __u8 Data; - int i; - - if (!info->fax->bor) { - for (i = 0; i < skb->len; i++) { - Data = skb->data[i]; - for ( - LeftMask = 0x80, RightMask = 0x01; - LeftMask > RightMask; - LeftMask >>= 1, RightMask <<= 1 - ) { - fBit = (Data & LeftMask); - if (Data & RightMask) - Data |= LeftMask; - else - Data &= ~LeftMask; - if (fBit) - Data |= RightMask; - else - Data &= ~RightMask; - - } - skb->data[i] = Data; - } - } -} - -#ifdef ISDN_TTY_FCLASS1 -/* - * Parse AT+F.. FAX class 1 commands - */ - -int -isdn_tty_cmd_FCLASS1(char **p, modem_info * info) -{ - static char *cmd[] = - {"AE", "TS", "RS", "TM", "RM", "TH", "RH"}; - isdn_ctrl c; - int par, i; - long flags; - - for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++) - if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2)) - break; - -#ifdef ISDN_TTY_FAX_CMD_DEBUG - printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 (%s,%d)\n", p[0], c.parm.aux.cmd); -#endif - if (c.parm.aux.cmd == 7) - PARSE_ERROR1; - - p[0] += 2; - switch (*p[0]) { - case '?': - p[0]++; - c.parm.aux.subcmd = AT_QUERY; - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - c.parm.aux.subcmd = AT_EQ_QUERY; - } else { - par = isdn_getnum(p); - if ((par < 0) || (par > 255)) - PARSE_ERROR1; - c.parm.aux.subcmd = AT_EQ_VALUE; - c.parm.aux.para[0] = par; - } - break; - case 0: - c.parm.aux.subcmd = AT_COMMAND; - break; - default: - PARSE_ERROR1; - } - c.command = ISDN_CMD_FAXCMD; -#ifdef ISDN_TTY_FAX_CMD_DEBUG - printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n", - c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]); -#endif - if (info->isdn_driver < 0) { - save_flags(flags); - cli(); - if ((c.parm.aux.subcmd == AT_EQ_VALUE) || - (c.parm.aux.subcmd == AT_COMMAND)) { - restore_flags(flags); - PARSE_ERROR1; - } - /* get a temporary connection to the first free fax driver */ - i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX, - ISDN_PROTO_L3_FCLASS1, -1, -1, "00"); - if (i < 0) { - restore_flags(flags); - PARSE_ERROR1; - } - info->isdn_driver = dev->drvmap[i]; - info->isdn_channel = dev->chanmap[i]; - info->drv_index = i; - dev->m_idx[i] = info->line; - c.driver = info->isdn_driver; - c.arg = info->isdn_channel; - isdn_command(&c); - isdn_free_channel(info->isdn_driver, info->isdn_channel, - ISDN_USAGE_FAX); - info->isdn_driver = -1; - info->isdn_channel = -1; - if (info->drv_index >= 0) { - dev->m_idx[info->drv_index] = -1; - info->drv_index = -1; - } - restore_flags(flags); - } else { - c.driver = info->isdn_driver; - c.arg = info->isdn_channel; - isdn_command(&c); - } - return 1; -} -#endif - -/* - * Parse AT+F.. FAX class 2 commands - */ - -int -isdn_tty_cmd_FCLASS2(char **p, modem_info * info) -{ - atemu *m = &info->emu; - T30_s *f = info->fax; - isdn_ctrl cmd; - int par; - char rs[50]; - char rss[50]; - int maxdccval[] = - {1, 5, 2, 2, 3, 2, 0, 7}; - - /* FAA still unchanged */ - if (!strncmp(p[0], "AA", 2)) { /* TODO */ - p[0] += 2; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", 0); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - par = isdn_getnum(p); - if ((par < 0) || (par > 255)) - PARSE_ERROR1; - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */ - if (!strncmp(p[0], "BADLIN", 6)) { - p[0] += 6; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->badlin); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n0-255"); - isdn_tty_at_cout(rs, info); - } else { - par = isdn_getnum(p); - if ((par < 0) || (par > 255)) - PARSE_ERROR1; - f->badlin = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */ - if (!strncmp(p[0], "BADMUL", 6)) { - p[0] += 6; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->badmul); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n0-255"); - isdn_tty_at_cout(rs, info); - } else { - par = isdn_getnum(p); - if ((par < 0) || (par > 255)) - PARSE_ERROR1; - f->badmul = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* BOR=n - Phase C bit order, 0=direct, 1=reverse */ - if (!strncmp(p[0], "BOR", 3)) { - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->bor); - 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->bor = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* NBC=n - No Best Capabilities */ - if (!strncmp(p[0], "NBC", 3)) { - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->nbc); - 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->nbc = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* BUF? - Readonly buffersize readout */ - if (!strncmp(p[0], "BUF?", 4)) { - p[0] += 4; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE])); -#endif - p[0]++; - sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE])); - isdn_tty_at_cout(rs, info); - return 0; - } - /* CIG=string - local fax station id string for polling rx */ - if (!strncmp(p[0], "CIG", 3)) { - int i, r; - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n\"%s\"", f->pollid); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n\"STRING\""); - isdn_tty_at_cout(rs, info); - } else { - if (*p[0] == '"') - p[0]++; - for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) { - f->pollid[i] = *p[0]++; - } - if (*p[0] == '"') - p[0]++; - for (r = i; r < FAXIDLEN; r++) { - f->pollid[r] = 32; - } - f->pollid[FAXIDLEN - 1] = 0; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */ - if (!strncmp(p[0], "CQ", 2)) { - p[0] += 2; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->cq); - 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->cq = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */ - if (!strncmp(p[0], "CR", 2)) { - p[0] += 2; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */ - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n0,1"); /* display online help */ - isdn_tty_at_cout(rs, info); - } else { - par = isdn_getnum(p); - if ((par < 0) || (par > 1)) - PARSE_ERROR1; - f->cr = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* CTCRTY=value - ECM retry count */ - if (!strncmp(p[0], "CTCRTY", 6)) { - p[0] += 6; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->ctcrty); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n0-255"); - isdn_tty_at_cout(rs, info); - } else { - par = isdn_getnum(p); - if ((par < 0) || (par > 255)) - PARSE_ERROR1; - f->ctcrty = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */ - if (!strncmp(p[0], "DCC", 3)) { - char *rp = &f->resolution; - int i; - - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - strcpy(rs, "\r\n"); - for (i = 0; i < 8; i++) { - sprintf(rss, "%c%s", rp[i] + 48, - (i < 7) ? "," : ""); - strcat(rs, rss); - } - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info); - p[0]++; - } else { - for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) { - if (*p[0] != ',') { - if ((*p[0] - 48) > maxdccval[i]) { - PARSE_ERROR1; - } - rp[i] = *p[0] - 48; - p[0]++; - if (*p[0] == ',') - p[0]++; - } else - p[0]++; - } -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n", - rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */ - if (!strncmp(p[0], "DIS", 3)) { - char *rp = &f->resolution; - int i; - - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - strcpy(rs, "\r\n"); - for (i = 0; i < 8; i++) { - sprintf(rss, "%c%s", rp[i] + 48, - (i < 7) ? "," : ""); - strcat(rs, rss); - } - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info); - p[0]++; - } else { - for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) { - if (*p[0] != ',') { - if ((*p[0] - 48) > maxdccval[i]) { - PARSE_ERROR1; - } - rp[i] = *p[0] - 48; - p[0]++; - if (*p[0] == ',') - p[0]++; - } else - p[0]++; - } -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n", - rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* DR - Receive Phase C data command, initiates document reception */ - if (!strncmp(p[0], "DR", 2)) { - p[0] += 2; - if ((info->faxonline & 16) && /* incoming connection */ - ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) { -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FDR\n"); -#endif - f->code = ISDN_TTY_FAX_DR; - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.command = ISDN_CMD_FAXCMD; - isdn_command(&cmd); - if (f->phase == ISDN_FAX_PHASE_B) { - f->phase = ISDN_FAX_PHASE_C; - } else if (f->phase == ISDN_FAX_PHASE_D) { - switch (f->fet) { - case 0: /* next page will be received */ - f->phase = ISDN_FAX_PHASE_C; - isdn_tty_fax_modem_result(7, info); /* CONNECT */ - break; - case 1: /* next doc will be received */ - f->phase = ISDN_FAX_PHASE_B; - break; - case 2: /* fax session is terminating */ - f->phase = ISDN_FAX_PHASE_E; - break; - default: - PARSE_ERROR1; - } - } - } else { - PARSE_ERROR1; - } - return 1; - } - /* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */ - if (!strncmp(p[0], "DT", 2)) { - int i, val[] = - {4, 0, 2, 3}; - char *rp = &f->resolution; - - p[0] += 2; - if (!info->faxonline & 1) /* not outgoing connection */ - PARSE_ERROR1; - - for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) { - if (*p[0] != ',') { - if ((*p[0] - 48) > maxdccval[val[i]]) { - PARSE_ERROR1; - } - rp[val[i]] = *p[0] - 48; - p[0]++; - if (*p[0] == ',') - p[0]++; - } else - p[0]++; - } -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n", - rp[4], rp[0], rp[2], rp[3]); -#endif - if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) { - f->code = ISDN_TTY_FAX_DT; - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.command = ISDN_CMD_FAXCMD; - isdn_command(&cmd); - if (f->phase == ISDN_FAX_PHASE_D) { - f->phase = ISDN_FAX_PHASE_C; - isdn_tty_fax_modem_result(7, info); /* CONNECT */ - } - } else { - PARSE_ERROR1; - } - return 1; - } - /* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */ - if (!strncmp(p[0], "ECM", 3)) { - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->ecm); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n0,2"); - isdn_tty_at_cout(rs, info); - } else { - par = isdn_getnum(p); - if ((par != 0) && (par != 2)) - PARSE_ERROR1; - f->ecm = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* ET=n - End of page or document */ - if (!strncmp(p[0], "ET=", 3)) { - p[0] += 3; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n0-2"); - isdn_tty_at_cout(rs, info); - } else { - if ((f->phase != ISDN_FAX_PHASE_D) || (!info->faxonline & 1)) - PARSE_ERROR1; - par = isdn_getnum(p); - if ((par < 0) || (par > 2)) - PARSE_ERROR1; - f->fet = par; - f->code = ISDN_TTY_FAX_ET; - cmd.driver = info->isdn_driver; - cmd.arg = info->isdn_channel; - cmd.command = ISDN_CMD_FAXCMD; - isdn_command(&cmd); -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par); -#endif - return 1; - } - return 0; - } - /* K - terminate */ - if (!strncmp(p[0], "K", 1)) { - p[0] += 1; - if ((f->phase == ISDN_FAX_PHASE_IDLE) || (f->phase == ISDN_FAX_PHASE_E)) - PARSE_ERROR1; - isdn_tty_modem_hup(info, 1); - return 1; - } - /* LID=string - local fax ID */ - if (!strncmp(p[0], "LID", 3)) { - int i, r; - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n\"%s\"", f->id); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n\"STRING\""); - isdn_tty_at_cout(rs, info); - } else { - if (*p[0] == '"') - p[0]++; - for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) { - f->id[i] = *p[0]++; - } - if (*p[0] == '"') - p[0]++; - for (r = i; r < FAXIDLEN; r++) { - f->id[r] = 32; - } - f->id[FAXIDLEN - 1] = 0; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id); -#endif - } - break; - default: - PARSE_ERROR1; - } - 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)) { - p[0] += 4; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: FMDL?\n"); -#endif - isdn_tty_at_cout("\r\nisdn4linux", info); - return 0; - } - /* MFR? - DCE Manufacturer */ - if (!strncmp(p[0], "MFR?", 4)) { - p[0] += 4; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: FMFR?\n"); -#endif - isdn_tty_at_cout("\r\nisdn4linux", info); - return 0; - } - /* MINSP=n - Minimum Speed for Phase C */ - if (!strncmp(p[0], "MINSP", 5)) { - p[0] += 5; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->minsp); - 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->minsp = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* PHCTO=value - DTE phase C timeout */ - if (!strncmp(p[0], "PHCTO", 5)) { - p[0] += 5; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->phcto); - isdn_tty_at_cout(rs, info); - break; - case '=': - p[0]++; - if (*p[0] == '?') { - p[0]++; - sprintf(rs, "\r\n0-255"); - isdn_tty_at_cout(rs, info); - } else { - par = isdn_getnum(p); - if ((par < 0) || (par > 255)) - PARSE_ERROR1; - f->phcto = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - 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)) { - p[0] += 3; - switch (*p[0]) { - case '?': - p[0]++; - sprintf(rs, "\r\n%d", f->rel); - 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->rel = par; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par); -#endif - } - break; - default: - PARSE_ERROR1; - } - return 0; - } - /* REV? - DCE Revision */ - if (!strncmp(p[0], "REV?", 4)) { - p[0] += 4; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: FREV?\n"); -#endif - strcpy(rss, isdn_tty_fax_revision); - sprintf(rs, "\r\nRev: %s", isdn_getrev(rss)); - 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 */ - p[0] += 4; -#ifdef ISDN_TTY_FAX_STAT_DEBUG - printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]); -#endif - switch (*p[0]) { - case '0': - p[0]++; - break; - default: - PARSE_ERROR1; - } - return 0; - } - printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]); - PARSE_ERROR1; -} - -int -isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info) -{ - if (TTY_IS_FCLASS2(info)) - return (isdn_tty_cmd_FCLASS2(p, info)); -#ifdef ISDN_TTY_FCLASS1 - else if (TTY_IS_FCLASS1(info)) - return (isdn_tty_cmd_FCLASS1(p, info)); -#endif - PARSE_ERROR1; -} diff --git a/drivers/isdn/isdn_ttyfax.h b/drivers/isdn/isdn_ttyfax.h deleted file mode 100644 index 30369635..00000000 --- a/drivers/isdn/isdn_ttyfax.h +++ /dev/null @@ -1,30 +0,0 @@ -/* $Id$ - * header for Linux ISDN subsystem, tty_fax related functions (linklevel). - * - * Copyright 1999 by Armin Schindler (mac@melware.de) - * Copyright 1999 by Ralf Spachmann (mel@melware.de) - * Copyright 1999 by Cytronics & Melware - * - * 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. - * - * $Log$ - * - */ - - -#define XON 0x11 -#define XOFF 0x13 -#define DC2 0x12 - diff --git a/drivers/isdn/isdn_v110.c b/drivers/isdn/isdn_v110.c deleted file mode 100644 index 752a721a..00000000 --- a/drivers/isdn/isdn_v110.c +++ /dev/null @@ -1,645 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, V.110 related functions (linklevel). - * - * Copyright by Thomas Pfeiffer (pfeiffer@pds.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. - * - * $Log$ - * Revision 1.2 1998/02/22 19:44:25 fritz - * Bugfixes and improvements regarding V.110, V.110 now running. - * - * Revision 1.1 1998/02/20 17:32:09 fritz - * First checkin (not yet completely functionable). - * - */ -#include -#include -#include -#include - -#include -#include "isdn_v110.h" - -#undef ISDN_V110_DEBUG - -char *isdn_v110_revision = "$Revision$"; - -#define V110_38400 255 -#define V110_19200 15 -#define V110_9600 3 - -/* Die folgenden Daten sind fertig kodierte Matrizen, jeweils - als online und offline matrix für 9600, 19200 und 38400 - */ -static unsigned char V110_OnMatrix_9600[] = -{0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, - 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, - 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd}; - -static unsigned char V110_OffMatrix_9600[] = -{0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -static unsigned char V110_OnMatrix_19200[] = -{0xf0, 0xf0, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, - 0xfd, 0xff, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7}; - -static unsigned char V110_OffMatrix_19200[] = -{0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - -static unsigned char V110_OnMatrix_38400[] = -{0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0xfd, 0x7f, 0x7f, 0x7f, 0x7f}; - -static unsigned char V110_OffMatrix_38400[] = -{0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff}; - - -/* FlipBits dreht die Reihenfolge von jeweils keylen bits in einem byte um. - Aus der Bitreihenfolge 76543210 werden bei keylen=4 die bits 45670123, - bei keylen=2 die bits 67452301. Dies ist notwendig, weil die reihenfolge - auf der isdn-leitung falsch herum ist. - */ - -static __inline unsigned char -FlipBits(unsigned char c, int keylen) -{ - unsigned char b = c; - unsigned char bit = 128; - int i; - int j; - int hunks = (8 / keylen); - - c = 0; - for (i = 0; i < hunks; i++) { - for (j = 0; j < keylen; j++) { - if (b & (bit >> j)) - c |= bit >> (keylen - j - 1); - } - bit >>= keylen; - } - return c; -} - - -/* isdn_v110_open allocates and initializes private V.110 data - * structures and returns a pointer to these. - */ -static isdn_v110_stream * -isdn_v110_open(unsigned char key, int hdrlen, int maxsize) -{ - int i; - isdn_v110_stream *v; - - if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_KERNEL)) == NULL) - return NULL; - memset(v, 0, sizeof(isdn_v110_stream)); - v->key = key; - v->nbits = 0; - for (i = 0; key & (1 << i); i++) - v->nbits++; - - v->nbytes = 8 / v->nbits; - v->decodelen = 0; - - switch (key) { - case V110_38400: - v->OnlineFrame = V110_OnMatrix_38400; - v->OfflineFrame = V110_OffMatrix_38400; - break; - case V110_19200: - v->OnlineFrame = V110_OnMatrix_19200; - v->OfflineFrame = V110_OffMatrix_19200; - break; - default: - v->OnlineFrame = V110_OnMatrix_9600; - v->OfflineFrame = V110_OffMatrix_9600; - break; - } - v->framelen = v->nbytes * 10; - v->SyncInit = 5; - v->introducer = 0; - v->dbit = 1; - v->b = 0; - v->skbres = hdrlen; - v->maxsize = maxsize - hdrlen; - if ((v->encodebuf = kmalloc(maxsize, GFP_KERNEL)) == NULL) { - kfree(v); - return NULL; - } - return v; -} - -/* isdn_v110_close frees private V.110 data structures */ -void -isdn_v110_close(isdn_v110_stream * v) -{ - if (v == NULL) - 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); -} - - -/* ValidHeaderBytes prüft, wieviele bytes in v->decodebuf gültig sind */ - -static int -ValidHeaderBytes(isdn_v110_stream * v) -{ - int i; - for (i = 0; (i < v->decodelen) && (i < v->nbytes); i++) - if ((v->decodebuf[i] & v->key) != 0) - break; - return i; -} - -/* SyncHeader schiebt den decodebuf pointer auf den nächsten gültigen header */ - -static void -SyncHeader(isdn_v110_stream * v) -{ - unsigned char *rbuf = v->decodebuf; - int len = v->decodelen; - - if (len == 0) - return; - for (rbuf++, len--; len > 0; len--, rbuf++) /* such den SyncHeader in buf ! */ - if ((*rbuf & v->key) == 0) /* erstes byte gefunden ? */ - break; /* jupp! */ - if (len) - memcpy(v->decodebuf, rbuf, len); - - v->decodelen = len; -#ifdef ISDN_V110_DEBUG - printk(KERN_DEBUG "isdn_v110: Header resync\n"); -#endif -} - -/* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where - len is the number of matrix-lines. len must be a multiple of 10, i.e. - only complete matices must be given. - From these, netto data is extracted and returned in buf. The return-value - is the bytecount of the decoded data. - */ -static int -DecodeMatrix(isdn_v110_stream * v, unsigned char *m, int len, unsigned char *buf) -{ - int line = 0; - int buflen = 0; - int mbit = 64; - int introducer = v->introducer; - int dbit = v->dbit; - unsigned char b = v->b; - - while (line < len) { /* sind schon alle matrizenzeilen abgearbeitet? */ - if ((line % 10) == 0) { /* die 0. zeile der matrix ist immer null ! */ - if (m[line] != 0x00) { /* nicht 0 ? dann fehler! */ -#ifdef ISDN_V110_DEBUG - printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad Header\n"); -#endif - -/* - dann einen return zu machen, ist auch irgendwie nicht das richtige! :-( - v->introducer = 0; v->dbit = 1; v->b = 0; - return buflen; anzahl schon erzeugter daten zurückgeben! - */ - } - line++; /* sonst die nächste matrixzeile nehmen */ - continue; - } else if ((line % 10) == 5) { /* in zeile 5 stehen nur e-bits ! */ - if ((m[line] & 0x70) != 0x30) { /* 011 muß am anfang stehen! */ -#ifdef ISDN_V110_DEBUG - printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad 5th line\n"); -#endif -/* dann einen return zu machen, ist auch irgendwie nicht das richtige! :-( - v->introducer = 0; v->dbit = 1; v->b = 0; - return buflen; - */ - } - line++; /* alles klar, nächste zeile */ - continue; - } else if (!introducer) { /* every byte starts with 10 (stopbit, startbit) */ - introducer = (m[line] & mbit) ? 0 : 1; /* aktuelles bit der matrix */ - next_byte: - if (mbit > 2) { /* war es das letzte bit dieser matrixzeile ? */ - mbit >>= 1; /* nein, nimm das nächste in dieser zeile */ - continue; - } /* sonst links in der nächsten zeile anfangen */ - mbit = 64; - line++; - continue; - } else { /* sonst müssen wir ein datenbit setzen */ - if (m[line] & mbit) /* war das bit in der matrix gesetzt ? */ - b |= dbit; /* ja, dann setz es auch im datenbyte */ - else - b &= dbit - 1; /* nein, lösch bit im datenbyte */ - if (dbit < 128) /* haben wir schon ein ganzes byte voll ? */ - dbit <<= 1; /* nein, auf zum nächsten datenbit */ - else { /* ein ganzes datenbyte ist voll */ - buf[buflen++] = b; /* byte in den output buffer kopieren */ - introducer = b = 0; /* Init der Introsequenz und des datenbytes */ - dbit = 1; /* als nächstes suchen wir das nullte bit */ - } - goto next_byte; /* suche das nächste bit in der matrix */ - } - } - v->introducer = introducer; - v->dbit = dbit; - v->b = b; - return buflen; /* return anzahl der bytes im output buffer */ -} - -/* DecodeStream erhält vom input stream V110 kodierte Daten, die zu den - V110 frames zusammengepackt werden müssen. Die Daten können an diese - Schnittstelle so übergeben werden, wie sie von der Leitung kommen, ohne - darauf achten zu müssen, das frames usw. eingehalten werden. - */ -struct sk_buff * -isdn_v110_decode(isdn_v110_stream * v, struct sk_buff *skb) -{ - int i; - int j; - int len; - unsigned char *v110_buf; - unsigned char *rbuf; - - if (!skb) { - printk(KERN_WARNING "isdn_v110_decode called with NULL skb!\n"); - return NULL; - } - rbuf = skb->data; - len = skb->len; - if (v == NULL) { - /* invalid handle, no chance to proceed */ - printk(KERN_WARNING "isdn_v110_decode called with NULL stream!\n"); - dev_kfree_skb(skb); - return NULL; - } - if (v->decodelen == 0) /* cache empty? */ - for (; len > 0; len--, rbuf++) /* scan for SyncHeader in buf */ - if ((*rbuf & v->key) == 0) - break; /* found first byte */ - if (len == 0) { - dev_kfree_skb(skb); - return NULL; - } - /* copy new data to decode-buffer */ - memcpy(&(v->decodebuf[v->decodelen]), rbuf, len); - v->decodelen += len; - ReSync: - if (v->decodelen < v->nbytes) { /* got a new header ? */ - dev_kfree_skb(skb); - return NULL; /* no, try later */ - } - if (ValidHeaderBytes(v) != v->nbytes) { /* ist es ein ungültiger header ? */ - SyncHeader(v); /* nein, such einen header */ - goto ReSync; - } - len = (v->decodelen - (v->decodelen % (10 * v->nbytes))) / v->nbytes; - if ((v110_buf = kmalloc(len, GFP_ATOMIC)) == NULL) { - printk(KERN_WARNING "isdn_v110_decode: Couldn't allocate v110_buf\n"); - dev_kfree_skb(skb); - return NULL; - } - for (i = 0; i < len; i++) { - v110_buf[i] = 0; - for (j = 0; j < v->nbytes; j++) - v110_buf[i] |= (v->decodebuf[(i * v->nbytes) + j] & v->key) << (8 - ((j + 1) * v->nbits)); - v110_buf[i] = FlipBits(v110_buf[i], v->nbits); - } - v->decodelen = (v->decodelen % (10 * v->nbytes)); - memcpy(v->decodebuf, &(v->decodebuf[len * v->nbytes]), v->decodelen); - - skb_trim(skb, DecodeMatrix(v, v110_buf, len, skb->data)); - kfree(v110_buf); - if (skb->len) - return skb; - else { - kfree_skb(skb); - return NULL; - } -} - -/* EncodeMatrix takes input data in buf, len is the bytecount. - Data is encoded into v110 frames in m. Return value is the number of - matrix-lines generated. - */ -static int -EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen) -{ - int line = 0; - int i = 0; - int mbit = 128; - int dbit = 1; - int introducer = 3; - int ibit[] = {0, 1, 1}; - - while ((i < len) && (line < mlen)) { /* solange noch input da ist */ - switch (line % 10) { /* in welcher matrixzeile sind wir ? */ - case 0: - m[line++] = 0x00; /* zeile 0 ist immer 0 */ - mbit = 128; /* und es geht mit dem 7. bit weiter */ - break; - case 5: - m[line++] = 0xbf; /* zeile 5 ist immer 10111111 */ - mbit = 128; /* und es geht mit dem 7. bit weiter */ - break; - } - if (line >= mlen) { - printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n"); - return line; - } - next_bit: - switch (mbit) { /* ganz linkes oder rechtes bit ? */ - case 1: - line++; /* ganz rechts ! dann in die nächste */ - if (line >= mlen) { - printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n"); - return line; - } - case 128: - m[line] = 128; /* ganz links byte auf 1000000 setzen */ - mbit = 64; /* aktuelles bit in der matrixzeile */ - continue; - } - if (introducer) { /* 110 sequenz setzen ? */ - introducer--; /* ein digit weniger setzen */ - m[line] |= ibit[introducer] ? mbit : 0; /* entsprechendes bit setzen */ - mbit >>= 1; /* bit der matrixzeile >> 1 */ - goto next_bit; /* und dort weiter machen */ - } /* else datenbits in die matrix packen! */ - m[line] |= (buf[i] & dbit) ? mbit : 0; /* datenbit in matrix setzen */ - if (dbit == 128) { /* war es das letzte datenbit ? */ - dbit = 1; /* dann mach beim nächsten weiter */ - i++; /* nächste datenbyte des input buffers */ - if (i < len) /* war es schon das letzte ? */ - introducer = 3; /* nein, schreib den introducer 110 */ - else { /* war das letzte datenbyte ! */ - m[line] |= (mbit - 1) & 0xfe; /* setz restliche bits der zeile auf 1 */ - break; - } - } else /* nicht das letzte datenbit */ - dbit <<= 1; /* dann gehe zum nächsten datenbit */ - mbit >>= 1; /* und setz bit der matrix weiter */ - goto next_bit; - - } - /* evtl. noch restliche zeilen in der matrix generieren... */ - if ((line) && ((line + 10) < mlen)) - switch (++line % 10) { - case 1: - m[line++] = 0xfe; - case 2: - m[line++] = 0xfe; - case 3: - m[line++] = 0xfe; - case 4: - m[line++] = 0xfe; - case 5: - m[line++] = 0xbf; - case 6: - m[line++] = 0xfe; - case 7: - m[line++] = 0xfe; - case 8: - m[line++] = 0xfe; - case 9: - m[line++] = 0xfe; - } - return line; /* soviele matrixzeilen sind es */ -} - -/* - * Build a sync frame. - */ -static struct sk_buff * -isdn_v110_sync(isdn_v110_stream *v) -{ - struct sk_buff *skb; - - if (v == NULL) { - /* invalid handle, no chance to proceed */ - printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n"); - return NULL; - } - if ((skb = dev_alloc_skb(v->framelen + v->skbres))) { - skb_reserve(skb, v->skbres); - memcpy(skb_put(skb, v->framelen), v->OfflineFrame, v->framelen); - } - return skb; -} - -/* - * Build an idle frame. - */ -static struct sk_buff * -isdn_v110_idle(isdn_v110_stream *v) -{ - struct sk_buff *skb; - - if (v == NULL) { - /* invalid handle, no chance to proceed */ - printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n"); - return NULL; - } - if ((skb = dev_alloc_skb(v->framelen + v->skbres))) { - skb_reserve(skb, v->skbres); - memcpy(skb_put(skb, v->framelen), v->OnlineFrame, v->framelen); - } - return skb; -} - -struct sk_buff * -isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb) -{ - int i; - int j; - int rlen; - int mlen; - int olen; - int size; - int sval1; - int sval2; - int nframes; - unsigned char *v110buf; - unsigned char *rbuf; - struct sk_buff *nskb; - - if (v == NULL) { - /* invalid handle, no chance to proceed */ - printk(KERN_WARNING "isdn_v110_encode called with NULL stream!\n"); - return NULL; - } - if (!skb) { - /* invalid skb, no chance to proceed */ - printk(KERN_WARNING "isdn_v110_encode called with NULL skb!\n"); - return NULL; - } - rlen = skb->len; - nframes = (rlen + 3) / 4; - v110buf = v->encodebuf; - if ((nframes * 40) > v->maxsize) { - size = v->maxsize; - rlen = v->maxsize / 40; - } else - size = nframes * 40; - if (!(nskb = dev_alloc_skb(size + v->skbres + sizeof(int)))) { - printk(KERN_WARNING "isdn_v110_encode: Couldn't alloc skb\n"); - return NULL; - } - skb_reserve(nskb, v->skbres + sizeof(int)); - if (skb->len == 0) { - memcpy(skb_put(nskb, v->framelen), v->OnlineFrame, v->framelen); - *((int *)skb_push(nskb, sizeof(int))) = 0; - return nskb; - } - mlen = EncodeMatrix(skb->data, rlen, v110buf, size); - /* jetzt noch jeweils 2 oder 4 bits auf den output stream verteilen! */ - rbuf = skb_put(nskb, size); - olen = 0; - sval1 = 8 - v->nbits; - sval2 = v->key << sval1; - for (i = 0; i < mlen; i++) { - v110buf[i] = FlipBits(v110buf[i], v->nbits); - for (j = 0; j < v->nbytes; j++) { - if (size--) - *rbuf++ = ~v->key | (((v110buf[i] << (j * v->nbits)) & sval2) >> sval1); - else { - printk(KERN_WARNING "isdn_v110_encode: buffers full!\n"); - goto buffer_full; - } - olen++; - } - } -buffer_full: - skb_trim(nskb, olen); - *((int *)skb_push(nskb, sizeof(int))) = rlen; - return nskb; -} - -int -isdn_v110_stat_callback(int idx, isdn_ctrl * c) -{ - isdn_v110_stream *v = NULL; - int i; - int ret; - - if (idx < 0) - return 0; - switch (c->command) { - case ISDN_STAT_BSENT: - /* Keep the send-queue of the driver filled - * with frames: - * If number of outstanding frames < 3, - * send down an Idle-Frame (or an Sync-Frame, if - * v->SyncInit != 0). - */ - if (!(v = dev->v110[idx])) - return 0; - atomic_inc(&dev->v110use[idx]); - if (v->skbidle > 0) { - v->skbidle--; - ret = 1; - } else { - if (v->skbuser > 0) - v->skbuser--; - ret = 0; - } - for (i = v->skbuser + v->skbidle; i < 2; i++) { - struct sk_buff *skb; - if (v->SyncInit > 0) - skb = isdn_v110_sync(v); - else - skb = isdn_v110_idle(v); - if (skb) { - if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) { - dev_kfree_skb(skb); - break; - } else { - if (v->SyncInit) - v->SyncInit--; - v->skbidle++; - } - } else - break; - } - atomic_dec(&dev->v110use[idx]); - return ret; - case ISDN_STAT_DHUP: - case ISDN_STAT_BHUP: - while (1) { - atomic_inc(&dev->v110use[idx]); - if (atomic_dec_and_test(&dev->v110use[idx])) { - isdn_v110_close(dev->v110[idx]); - dev->v110[idx] = NULL; - break; - } - sti(); - } - break; - case ISDN_STAT_BCONN: - if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) { - int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen; - int maxsize = dev->drv[c->driver]->interface->maxbufsize; - atomic_inc(&dev->v110use[idx]); - switch (dev->v110emu[idx]) { - case ISDN_PROTO_L2_V11096: - dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize); - break; - case ISDN_PROTO_L2_V11019: - dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize); - break; - case ISDN_PROTO_L2_V11038: - dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize); - break; - default: - } - if ((v = dev->v110[idx])) { - while (v->SyncInit) { - struct sk_buff *skb = isdn_v110_sync(v); - if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) { - dev_kfree_skb(skb); - /* Unable to send, try later */ - break; - } - v->SyncInit--; - v->skbidle++; - } - } else - printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx); - atomic_dec(&dev->v110use[idx]); - } - break; - default: - return 0; - } - return 0; -} diff --git a/drivers/isdn/isdn_v110.h b/drivers/isdn/isdn_v110.h deleted file mode 100644 index 5bb9d715..00000000 --- a/drivers/isdn/isdn_v110.h +++ /dev/null @@ -1,46 +0,0 @@ -/* $Id$ - - * Linux ISDN subsystem, V.110 related functions (linklevel). - * - * Copyright by Thomas Pfeiffer (pfeiffer@pds.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. - * - * $Log$ - * Revision 1.1 1998/02/20 17:32:11 fritz - * First checkin (not yet completely functionable). - * - */ -#ifndef _isdn_v110_h_ -#define _isdn_v110_h_ - -/* isdn_v110_encode erhält len Nettodaten in buf, kodiert diese und liefert - das Ergebnis wieder in buf. Wieviele Bytes kodiert wurden wird als - return zurück gegeben. Diese Daten können dann 1:1 auf die Leitung - gegeben werden. -*/ -extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *); - -/* isdn_v110_decode erhält vom input stream V110 kodierte Daten, die zu den - V110 frames zusammengepackt werden müssen. Die Daten können an diese - Schnittstelle so übergeben werden, wie sie von der Leitung kommen, ohne - darauf achten zu müssen, das frames usw. eingehalten werden. - */ -extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *); - -extern int isdn_v110_stat_callback(int, isdn_ctrl *); -extern void isdn_v110_close(isdn_v110_stream * v); - -#endif diff --git a/drivers/isdn/isdn_x25iface.c b/drivers/isdn/isdn_x25iface.c deleted file mode 100644 index fbbe45fe..00000000 --- a/drivers/isdn/isdn_x25iface.c +++ /dev/null @@ -1,356 +0,0 @@ -/* $Id$ - * stuff needed to support the Linux X.25 PLP code on top of devices that - * can provide a lab_b service using the concap_proto mechanism. - * This module supports a network interface wich provides lapb_sematics - * -- as defined in ../../Documentation/networking/x25-iface.txt -- to - * the upper layer and assumes that the lower layer provides a reliable - * data link service by means of the concap_device_ops callbacks. - * - * Only protocol specific stuff goes here. Device specific stuff - * goes to another -- device related -- concap_proto support source file. - * - * $Log$ - * Revision 1.6 1999/01/27 22:53:19 he - * minor updates (spellings, jiffies wrap around in isdn_tty) - * - * Revision 1.5 1998/10/30 17:55:39 he - * dialmode for x25iface and multulink ppp - * - * Revision 1.4 1998/06/17 19:51:00 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.3 1998/02/20 17:25:20 fritz - * Changes for recent kernels. - * - * Revision 1.2 1998/01/31 22:49:22 keil - * correct comments - * - * Revision 1.1 1998/01/31 22:27:58 keil - * New files from Henner Eisen for X.25 support - * - */ - -/* #include */ -#include -#include -#include -#include "isdn_x25iface.h" - -/* for debugging messages not to cause an oops when device pointer is NULL*/ -#define MY_DEVNAME(dev) ( (dev) ? (dev)->name : "DEVICE UNSPECIFIED" ) - - -typedef struct isdn_x25iface_proto_data { - int magic; - enum wan_states state; - /* Private stuff, not to be accessed via proto_data. We provide the - other storage for the concap_proto instance here as well, - enabling us to allocate both with just one kmalloc(): */ - struct concap_proto priv; -} ix25_pdata_t; - - - -/* is now in header file (extern): struct concap_proto * isdn_x25iface_proto_new(void); */ -void isdn_x25iface_proto_del( struct concap_proto * ); -int isdn_x25iface_proto_close( struct concap_proto * ); -int isdn_x25iface_proto_restart( struct concap_proto *, - struct net_device *, - struct concap_device_ops *); -int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * ); -int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * ); -int isdn_x25iface_connect_ind( struct concap_proto * ); -int isdn_x25iface_disconn_ind( struct concap_proto * ); - - -static struct concap_proto_ops ix25_pops = { - &isdn_x25iface_proto_new, - &isdn_x25iface_proto_del, - &isdn_x25iface_proto_restart, - &isdn_x25iface_proto_close, - &isdn_x25iface_xmit, - &isdn_x25iface_receive, - &isdn_x25iface_connect_ind, - &isdn_x25iface_disconn_ind -}; - -/* error message helper function */ -static void illegal_state_warn( unsigned state, unsigned char firstbyte) -{ - printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in" - "current state %d\n",firstbyte, state ); -} - -/* check protocol data field for consistency */ -static int pdata_is_bad( ix25_pdata_t * pda ){ - - if( pda && pda -> magic == ISDN_X25IFACE_MAGIC ) return 0; - printk( KERN_WARNING - "isdn_x25iface_xxx: illegal pointer to proto data\n" ); - return 1; -} - -/* create a new x25 interface protocol instance - */ -struct concap_proto * isdn_x25iface_proto_new() -{ - ix25_pdata_t * tmp = kmalloc(sizeof(ix25_pdata_t),GFP_KERNEL); - IX25DEBUG("isdn_x25iface_proto_new\n"); - if( tmp ){ - tmp -> magic = ISDN_X25IFACE_MAGIC; - tmp -> state = WAN_UNCONFIGURED; - /* private data space used to hold the concap_proto data. - Only to be accessed via the returned pointer */ - tmp -> priv.dops = NULL; - tmp -> priv.net_dev = NULL; - tmp -> priv.pops = &ix25_pops; - tmp -> priv.flags = 0; - tmp -> priv.proto_data = tmp; - return( &(tmp -> priv) ); - } - return NULL; -}; - -/* close the x25iface encapsulation protocol - */ -int isdn_x25iface_proto_close(struct concap_proto *cprot){ - - ix25_pdata_t *tmp; - int ret = 0; - ulong flags; - - if( ! cprot ){ - printk( KERN_ERR "isdn_x25iface_proto_close: " - "invalid concap_proto pointer\n" ); - return -1; - } - IX25DEBUG( "isdn_x25iface_proto_close %s \n", MY_DEVNAME(cprot -> net_dev) ); - save_flags(flags); - cli(); /* avoid races with incoming events calling pops methods while - cprot members are inconsistent */ - cprot -> dops = NULL; - cprot -> net_dev = NULL; - tmp = cprot -> proto_data; - if( pdata_is_bad( tmp ) ){ - ret = -1; - } else { - tmp -> state = WAN_UNCONFIGURED; - } - restore_flags(flags); - - return ret; -} - -/* Delete the x25iface encapsulation protocol instance - */ -void isdn_x25iface_proto_del(struct concap_proto *cprot){ - - ix25_pdata_t * tmp; - - IX25DEBUG( "isdn_x25iface_proto_del \n" ); - if( ! cprot ){ - printk( KERN_ERR "isdn_x25iface_proto_del: " - "concap_proto pointer is NULL\n" ); - return; - } - tmp = cprot -> proto_data; - if( tmp == NULL ){ - printk( KERN_ERR "isdn_x25iface_proto_del: inconsistent " - "proto_data pointer (maybe already deleted?)\n"); - return; - } - /* close if the protocol is still open */ - if( cprot -> dops ) isdn_x25iface_proto_close(cprot); - /* freeing the storage should be sufficient now. But some additional - settings might help to catch wild pointer bugs */ - tmp -> magic = 0; - cprot -> proto_data = NULL; - - kfree( tmp ); - return; -} - -/* (re-)initialize the data structures for x25iface encapsulation - */ -int isdn_x25iface_proto_restart(struct concap_proto *cprot, - struct net_device *ndev, - struct concap_device_ops *dops) -{ - ix25_pdata_t * pda = cprot -> proto_data ; - ulong flags; - - IX25DEBUG( "isdn_x25iface_proto_restart %s \n", MY_DEVNAME(ndev) ); - - if ( pdata_is_bad( pda ) ) return -1; - - if( !( dops && dops -> data_req && dops -> connect_req - && dops -> disconn_req ) ){ - printk( KERN_WARNING "isdn_x25iface_restart: required dops" - " missing\n" ); - isdn_x25iface_proto_close(cprot); - return -1; - } - save_flags(flags); - cli(); /* avoid races with incoming events calling pops methods while - cprot members are inconsistent */ - cprot -> net_dev = ndev; - cprot -> pops = &ix25_pops; - cprot -> dops = dops; - pda -> state = WAN_DISCONNECTED; - restore_flags(flags); - return 0; -} - -/* deliver a dl_data frame received from i4l HL driver to the network layer - */ -int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb) -{ - IX25DEBUG( "isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev) ); - if ( ( (ix25_pdata_t*) (cprot->proto_data) ) - -> state == WAN_CONNECTED ){ - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; - if( skb_push(skb, 1)){ - skb -> data[0]=0x00; - skb -> mac.raw = skb -> data; - netif_rx(skb); - return 0; - } - } - printk(KERN_WARNING "isdn_x25iface_receive %s: not connected, skb dropped\n", MY_DEVNAME(cprot->net_dev) ); - dev_kfree_skb(skb); - return -1; -} - -/* a connection set up is indicated by lower layer - */ -int isdn_x25iface_connect_ind(struct concap_proto *cprot) -{ - struct sk_buff * skb = dev_alloc_skb(1); - enum wan_states *state_p - = &( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state); - IX25DEBUG( "isdn_x25iface_connect_ind %s \n" - , MY_DEVNAME(cprot->net_dev) ); - if( *state_p == WAN_UNCONFIGURED ){ - printk(KERN_WARNING - "isdn_x25iface_connect_ind while unconfigured %s\n" - , MY_DEVNAME(cprot->net_dev) ); - return -1; - } - *state_p = WAN_CONNECTED; - if( skb ){ - *( skb_put(skb, 1) ) = 0x01; - skb -> mac.raw = skb -> data; - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; - netif_rx(skb); - return 0; - } else { - printk(KERN_WARNING "isdn_x25iface_connect_ind: " - " out of memory -- disconnecting\n"); - cprot -> dops -> disconn_req(cprot); - return -1; - } -} - -/* a disconnect is indicated by lower layer - */ -int isdn_x25iface_disconn_ind(struct concap_proto *cprot) -{ - struct sk_buff *skb; - enum wan_states *state_p - = &( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state); - IX25DEBUG( "isdn_x25iface_disconn_ind %s \n", MY_DEVNAME(cprot -> net_dev) ); - if( *state_p == WAN_UNCONFIGURED ){ - printk(KERN_WARNING - "isdn_x25iface_disconn_ind while unconfigured\n"); - return -1; - } - if(! cprot -> net_dev) return -1; - *state_p = WAN_DISCONNECTED; - skb = dev_alloc_skb(1); - if( skb ){ - *( skb_put(skb, 1) ) = 0x02; - skb -> mac.raw = skb -> data; - skb -> dev = cprot -> net_dev; - skb -> protocol = htons(ETH_P_X25); - skb -> pkt_type = PACKET_HOST; - netif_rx(skb); - return 0; - } else { - printk(KERN_WARNING "isdn_x25iface_disconn_ind:" - " out of memory\n"); - return -1; - } -} - -/* process a frame handed over to us from linux network layer. First byte - semantics as defined in ../../Documentation/networking/x25-iface.txt - */ -int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb) -{ - unsigned char firstbyte = skb->data[0]; - unsigned *state = - &( ( (ix25_pdata_t*) (cprot -> proto_data) ) -> state ); - int ret = 0; - IX25DEBUG( "isdn_x25iface_xmit: %s first=%x state=%d \n", MY_DEVNAME(cprot -> net_dev), firstbyte, *state ); - switch ( firstbyte ){ - case 0x00: /* dl_data request */ - if( *state == WAN_CONNECTED ){ - skb_pull(skb, 1); - cprot -> net_dev -> trans_start = jiffies; - ret = ( cprot -> dops -> data_req(cprot, skb) ); - /* prepare for future retransmissions */ - if( ret ) skb_push(skb,1); - return ret; - } - illegal_state_warn( *state, firstbyte ); - break; - case 0x01: /* dl_connect request */ - if( *state == WAN_DISCONNECTED ){ - *state = WAN_CONNECTING; - ret = cprot -> dops -> connect_req(cprot); - if(ret){ - /* reset state and notify upper layer about - * immidiatly failed attempts */ - isdn_x25iface_disconn_ind(cprot); - } - } else { - illegal_state_warn( *state, firstbyte ); - } - break; - case 0x02: /* dl_disconnect request */ - switch ( *state ){ - case WAN_DISCONNECTED: - /* Should not happen. However, give upper layer a - chance to recover from inconstistency but don't - trust the lower layer sending the disconn_confirm - when already disconnected */ - printk(KERN_WARNING "isdn_x25iface_xmit: disconnect " - " requested while disconnected\n" ); - isdn_x25iface_disconn_ind(cprot); - break; /* prevent infinite loops */ - case WAN_CONNECTING: - case WAN_CONNECTED: - *state = WAN_DISCONNECTED; - cprot -> dops -> disconn_req(cprot); - break; - default: - illegal_state_warn( *state, firstbyte ); - } - break; - case 0x03: /* changing lapb parameters requested */ - printk(KERN_WARNING "isdn_x25iface_xmit: setting of lapb" - " options not yet supported\n"); - break; - default: - printk(KERN_WARNING "isdn_x25iface_xmit: frame with illegal" - " first byte %x ignored:\n", firstbyte); - } - dev_kfree_skb(skb); - return 0; -} diff --git a/drivers/isdn/isdn_x25iface.h b/drivers/isdn/isdn_x25iface.h deleted file mode 100644 index a99dbfdc..00000000 --- a/drivers/isdn/isdn_x25iface.h +++ /dev/null @@ -1,32 +0,0 @@ -/* $Id$ - */ -#ifndef _LINUX_ISDN_X25IFACE_H -#define _LINUX_ISDN_X25IFACE_H - -#define ISDN_X25IFACE_MAGIC 0x1e75a2b9 -/* #define DEBUG_ISDN_X25 if you want isdn_x25 debugging messages */ -#ifdef DEBUG_ISDN_X25 -# define IX25DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args) -#else -# define IX25DEBUG(fmt,args...) -#endif - -#include -#include -#include -#include - -extern struct concap_proto_ops * isdn_x25iface_concap_proto_ops_pt; -extern struct concap_proto * isdn_x25iface_proto_new(void); - - - -#endif - - - - - - - - diff --git a/drivers/isdn/isdnloop/Makefile b/drivers/isdn/isdnloop/Makefile deleted file mode 100644 index 588d8076..00000000 --- a/drivers/isdn/isdnloop/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -L_OBJS := -M_OBJS := - -ifeq ($(CONFIG_ISDN_DRV_LOOP),y) - L_OBJS += isdnloop.o -else - M_OBJS += isdnloop.o -endif - -include $(TOPDIR)/Rules.make - diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c deleted file mode 100644 index c2d49194..00000000 --- a/drivers/isdn/isdnloop/isdnloop.c +++ /dev/null @@ -1,1632 +0,0 @@ -/* $Id$ - - * ISDN low-level module implementing a dummy loop driver. - * - * Copyright 1997 by Fritz Elfert (fritz@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. - * - * $Log$ - * Revision 1.8 1998/11/18 18:59:43 armin - * changes for 2.1.127 - * - * Revision 1.7 1998/10/30 18:58:03 he - * typecast to suppress a compiler warning - * - * Revision 1.6 1998/06/17 19:51:37 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.5 1998/04/14 20:59:32 he - * merged 2.1.94 changes - * - * Revision 1.4 1998/02/24 21:39:05 he - * L2_PROT_X25DTE / DCE - * additional state 17 and new internal signal messages "BCON_I" - * (for reliable connect confirmation primitive as needed by x.25 upper layer) - * Changes for new LL-HL interface - * - * Revision 1.3 1998/02/20 17:33:30 fritz - * Changes for recent kernels. - * - * Revision 1.2 1997/10/01 09:22:03 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.1 1997/03/24 23:02:04 fritz - * Added isdnloop driver. - * - */ - -#include -#include "isdnloop.h" - -static char -*revision = "$Revision$"; - -static int isdnloop_addcard(char *); - -/* - * Free queue completely. - * - * Parameter: - * card = pointer to card struct - * channel = channel number - */ -static void -isdnloop_free_queue(isdnloop_card * card, int channel) -{ - struct sk_buff_head *queue = &card->bqueue[channel]; - struct sk_buff *skb; - - while ((skb = skb_dequeue(queue))) - dev_kfree_skb(skb); - card->sndcount[channel] = 0; -} - -/* - * Send B-Channel data to another virtual card. - * This routine is called via timer-callback from isdnloop_pollbchan(). - * - * Parameter: - * card = pointer to card struct. - * ch = channel number (0-based) - */ -static void -isdnloop_bchan_send(isdnloop_card * card, int ch) -{ - isdnloop_card *rcard = card->rcard[ch]; - int rch = card->rch[ch], len, ack; - struct sk_buff *skb; - isdn_ctrl cmd; - - while (card->sndcount[ch]) { - if ((skb = skb_dequeue(&card->bqueue[ch]))) { - len = skb->len; - card->sndcount[ch] -= len; - ack = *(skb->head); /* used as scratch area */ - cmd.driver = card->myid; - cmd.arg = ch; - if (rcard){ - rcard->interface.rcvcallb_skb(rcard->myid, rch, skb); - } else { - printk(KERN_WARNING "isdnloop: no rcard, skb dropped\n"); - dev_kfree_skb(skb); - - cmd.command = ISDN_STAT_L1ERR; - cmd.parm.errcode = ISDN_STAT_L1ERR_SEND; - card->interface.statcallb(&cmd); - }; - cmd.command = ISDN_STAT_BSENT; - cmd.parm.length = len; - if ( ack ) card->interface.statcallb(&cmd); - } else - card->sndcount[ch] = 0; - } -} - -/* - * Send/Receive Data to/from the B-Channel. - * This routine is called via timer-callback. - * It schedules itself while any B-Channel is open. - * - * Parameter: - * data = pointer to card struct, set by kernel timer.data - */ -static void -isdnloop_pollbchan(unsigned long data) -{ - isdnloop_card *card = (isdnloop_card *) data; - unsigned long flags; - - if (card->flags & ISDNLOOP_FLAGS_B1ACTIVE) - isdnloop_bchan_send(card, 0); - if (card->flags & ISDNLOOP_FLAGS_B2ACTIVE) - isdnloop_bchan_send(card, 1); - if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) { - /* schedule b-channel polling again */ - save_flags(flags); - cli(); - card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; - add_timer(&card->rb_timer); - card->flags |= ISDNLOOP_FLAGS_RBTIMER; - restore_flags(flags); - } else - card->flags &= ~ISDNLOOP_FLAGS_RBTIMER; -} - -/* - * Parse ICN-type setup string and fill fields of setup-struct - * with parsed data. - * - * Parameter: - * setup = setup string, format: [caller-id],si1,si2,[called-id] - * cmd = pointer to struct to be filled. - */ -static void -isdnloop_parse_setup(char *setup, isdn_ctrl * cmd) -{ - char *t = setup; - char *s = strpbrk(t, ","); - - *s++ = '\0'; - strncpy(cmd->parm.setup.phone, t, sizeof(cmd->parm.setup.phone)); - s = strpbrk(t = s, ","); - *s++ = '\0'; - if (!strlen(t)) - cmd->parm.setup.si1 = 0; - else - cmd->parm.setup.si1 = simple_strtoul(t, NULL, 10); - s = strpbrk(t = s, ","); - *s++ = '\0'; - if (!strlen(t)) - cmd->parm.setup.si2 = 0; - else - cmd->parm.setup.si2 = - simple_strtoul(t, NULL, 10); - strncpy(cmd->parm.setup.eazmsn, s, sizeof(cmd->parm.setup.eazmsn)); - cmd->parm.setup.plan = 0; - cmd->parm.setup.screen = 0; -} - -typedef struct isdnloop_stat { - char *statstr; - int command; - int action; -} isdnloop_stat; -/* *INDENT-OFF* */ -static isdnloop_stat isdnloop_stat_table[] = -{ - {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */ - {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */ - {"DCON_", ISDN_STAT_DCONN, 0}, /* D-Channel connected */ - {"DDIS_", ISDN_STAT_DHUP, 0}, /* D-Channel disconnected */ - {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */ - {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */ - {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */ - {"CIF", ISDN_STAT_CINF, 5}, /* Charge-info, 1TR6-type */ - {"AOC", ISDN_STAT_CINF, 6}, /* Charge-info, DSS1-type */ - {"CAU", ISDN_STAT_CAUSE, 7}, /* Cause code */ - {"TEI OK", ISDN_STAT_RUN, 0}, /* Card connected to wallplug */ - {"NO D-CHAN", ISDN_STAT_NODCH, 0}, /* No D-channel available */ - {"E_L1: ACT FAIL", ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ - {"E_L2: DATA LIN", ISDN_STAT_BHUP, 8}, /* Layer-2 data link lost */ - {"E_L1: ACTIVATION FAILED", - ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */ - {NULL, 0, -1} -}; -/* *INDENT-ON* */ - - -/* - * Parse Status message-strings from virtual card. - * Depending on status, call statcallb for sending messages to upper - * levels. Also set/reset B-Channel active-flags. - * - * Parameter: - * status = status string to parse. - * channel = channel where message comes from. - * card = card where message comes from. - */ -static void -isdnloop_parse_status(u_char * status, int channel, isdnloop_card * card) -{ - isdnloop_stat *s = isdnloop_stat_table; - int action = -1; - isdn_ctrl cmd; - - while (s->statstr) { - if (!strncmp(status, s->statstr, strlen(s->statstr))) { - cmd.command = s->command; - action = s->action; - break; - } - s++; - } - if (action == -1) - return; - cmd.driver = card->myid; - cmd.arg = channel; - switch (action) { - case 1: - /* BCON_x */ - card->flags |= (channel) ? - ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE; - break; - case 2: - /* BDIS_x */ - card->flags &= ~((channel) ? - ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE); - isdnloop_free_queue(card, channel); - break; - case 3: - /* DCAL_I and DSCA_I */ - isdnloop_parse_setup(status + 6, &cmd); - break; - case 4: - /* FCALL */ - sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid); - sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1); - cmd.parm.setup.si1 = 7; - cmd.parm.setup.si2 = 0; - cmd.parm.setup.plan = 0; - cmd.parm.setup.screen = 0; - break; - case 5: - /* CIF */ - strncpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num) - 1); - break; - case 6: - /* AOC */ - sprintf(cmd.parm.num, "%d", - (int) simple_strtoul(status + 7, NULL, 16)); - break; - case 7: - /* CAU */ - status += 3; - if (strlen(status) == 4) - sprintf(cmd.parm.num, "%s%c%c", - status + 2, *status, *(status + 1)); - else - strncpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num) - 1); - break; - case 8: - /* Misc Errors on L1 and L2 */ - card->flags &= ~ISDNLOOP_FLAGS_B1ACTIVE; - isdnloop_free_queue(card, 0); - cmd.arg = 0; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_DHUP; - cmd.arg = 0; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_BHUP; - card->flags &= ~ISDNLOOP_FLAGS_B2ACTIVE; - isdnloop_free_queue(card, 1); - cmd.arg = 1; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - cmd.command = ISDN_STAT_DHUP; - cmd.arg = 1; - cmd.driver = card->myid; - break; - } - card->interface.statcallb(&cmd); -} - -/* - * Store a cwcharacter into ringbuffer for reading from /dev/isdnctrl - * - * Parameter: - * card = pointer to card struct. - * c = char to store. - */ -static void -isdnloop_putmsg(isdnloop_card * card, unsigned char c) -{ - ulong flags; - - save_flags(flags); - cli(); - *card->msg_buf_write++ = (c == 0xff) ? '\n' : c; - if (card->msg_buf_write == card->msg_buf_read) { - if (++card->msg_buf_read > card->msg_buf_end) - card->msg_buf_read = card->msg_buf; - } - if (card->msg_buf_write > card->msg_buf_end) - card->msg_buf_write = card->msg_buf; - restore_flags(flags); -} - -/* - * Poll a virtual cards message queue. - * If there are new status-replies from the card, copy them to - * ringbuffer for reading on /dev/isdnctrl and call - * isdnloop_parse_status() for processing them. Watch for special - * Firmware bootmessage and parse it, to get the D-Channel protocol. - * If there are B-Channels open, initiate a timer-callback to - * isdnloop_pollbchan(). - * This routine is called periodically via timer interrupt. - * - * Parameter: - * data = pointer to card struct - */ -static void -isdnloop_polldchan(unsigned long data) -{ - isdnloop_card *card = (isdnloop_card *) data; - struct sk_buff *skb; - int avail; - int left; - u_char c; - int ch; - int flags; - u_char *p; - isdn_ctrl cmd; - - if ((skb = skb_dequeue(&card->dqueue))) - avail = skb->len; - else - avail = 0; - for (left = avail; left > 0; left--) { - c = *skb->data; - skb_pull(skb, 1); - isdnloop_putmsg(card, c); - card->imsg[card->iptr] = c; - if (card->iptr < 59) - card->iptr++; - if (!skb->len) { - avail++; - isdnloop_putmsg(card, '\n'); - card->imsg[card->iptr] = 0; - card->iptr = 0; - if (card->imsg[0] == '0' && card->imsg[1] >= '0' && - card->imsg[1] <= '2' && card->imsg[2] == ';') { - ch = (card->imsg[1] - '0') - 1; - p = &card->imsg[3]; - isdnloop_parse_status(p, ch, card); - } else { - p = card->imsg; - if (!strncmp(p, "DRV1.", 5)) { - printk(KERN_INFO "isdnloop: (%s) %s\n", CID, p); - if (!strncmp(p + 7, "TC", 2)) { - card->ptype = ISDN_PTYPE_1TR6; - card->interface.features |= ISDN_FEATURE_P_1TR6; - printk(KERN_INFO - "isdnloop: (%s) 1TR6-Protocol loaded and running\n", CID); - } - if (!strncmp(p + 7, "EC", 2)) { - card->ptype = ISDN_PTYPE_EURO; - card->interface.features |= ISDN_FEATURE_P_EURO; - printk(KERN_INFO - "isdnloop: (%s) Euro-Protocol loaded and running\n", CID); - } - continue; - - } - } - } - } - if (avail) { - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = avail; - card->interface.statcallb(&cmd); - } - if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) - if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) { - /* schedule b-channel polling */ - card->flags |= ISDNLOOP_FLAGS_RBTIMER; - save_flags(flags); - cli(); - del_timer(&card->rb_timer); - card->rb_timer.function = isdnloop_pollbchan; - card->rb_timer.data = (unsigned long) card; - card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD; - add_timer(&card->rb_timer); - restore_flags(flags); - } - /* schedule again */ - save_flags(flags); - cli(); - card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; - add_timer(&card->st_timer); - restore_flags(flags); -} - -/* - * Append a packet to the transmit buffer-queue. - * - * Parameter: - * channel = Number of B-channel - * skb = packet to send. - * card = pointer to card-struct - * Return: - * Number of bytes transferred, -E??? on error - */ -static int -isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card * card) -{ - int len = skb->len; - unsigned long flags; - struct sk_buff *nskb; - - if (len > 4000) { - printk(KERN_WARNING - "isdnloop: Send packet too large\n"); - return -EINVAL; - } - if (len) { - if (!(card->flags & (channel) ? ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE)) - return 0; - if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE) - return 0; - save_flags(flags); - cli(); - nskb = skb_clone(skb, GFP_ATOMIC); - if (nskb) { - skb_queue_tail(&card->bqueue[channel], nskb); - dev_kfree_skb(skb); - } else - len = 0; - card->sndcount[channel] += len; - restore_flags(flags); - } - return len; -} - -/* - * Read the messages from the card's ringbuffer - * - * Parameter: - * buf = pointer to buffer. - * len = number of bytes to read. - * user = flag, 1: called from userlevel 0: called from kernel. - * card = pointer to card struct. - * Return: - * number of bytes actually transferred. - */ -static int -isdnloop_readstatus(u_char * buf, int len, int user, isdnloop_card * card) -{ - int count; - u_char *p; - - for (p = buf, count = 0; count < len; p++, count++) { - if (card->msg_buf_read == card->msg_buf_write) - return count; - if (user) - put_user(*card->msg_buf_read++, p); - else - *p = *card->msg_buf_read++; - if (card->msg_buf_read > card->msg_buf_end) - card->msg_buf_read = card->msg_buf; - } - return count; -} - -/* - * Simulate a card's response by appending it to the cards - * message queue. - * - * Parameter: - * card = pointer to card struct. - * s = pointer to message-string. - * ch = channel: 0 = generic messages, 1 and 2 = D-channel messages. - * Return: - * 0 on success, 1 on memory squeeze. - */ -static int -isdnloop_fake(isdnloop_card * card, char *s, int ch) -{ - struct sk_buff *skb; - int len = strlen(s) + ((ch >= 0) ? 3 : 0); - - if (!(skb = dev_alloc_skb(len))) { - printk(KERN_WARNING "isdnloop: Out of memory in isdnloop_fake\n"); - return 1; - } - if (ch >= 0) - sprintf(skb_put(skb, 3), "%02d;", ch); - memcpy(skb_put(skb, strlen(s)), s, strlen(s)); - skb_queue_tail(&card->dqueue, skb); - return 0; -} -/* *INDENT-OFF* */ -static isdnloop_stat isdnloop_cmd_table[] = -{ - {"BCON_R", 0, 1}, /* B-Channel connect */ - {"BCON_I", 0, 17}, /* B-Channel connect ind */ - {"BDIS_R", 0, 2}, /* B-Channel disconnect */ - {"DDIS_R", 0, 3}, /* D-Channel disconnect */ - {"DCON_R", 0, 16}, /* D-Channel connect */ - {"DSCA_R", 0, 4}, /* Dial 1TR6-SPV */ - {"DCAL_R", 0, 5}, /* Dial */ - {"EAZC", 0, 6}, /* Clear EAZ listener */ - {"EAZ", 0, 7}, /* Set EAZ listener */ - {"SEEAZ", 0, 8}, /* Get EAZ listener */ - {"MSN", 0, 9}, /* Set/Clear MSN listener */ - {"MSALL", 0, 10}, /* Set multi MSN listeners */ - {"SETSIL", 0, 11}, /* Set SI list */ - {"SEESIL", 0, 12}, /* Get SI list */ - {"SILC", 0, 13}, /* Clear SI list */ - {"LOCK", 0, -1}, /* LOCK channel */ - {"UNLOCK", 0, -1}, /* UNLOCK channel */ - {"FV2ON", 1, 14}, /* Leased mode on */ - {"FV2OFF", 1, 15}, /* Leased mode off */ - {NULL, 0, -1} -}; -/* *INDENT-ON* */ - - -/* - * Simulate an error-response from a card. - * - * Parameter: - * card = pointer to card struct. - */ -static void -isdnloop_fake_err(isdnloop_card * card) -{ - char buf[60]; - - sprintf(buf, "E%s", card->omsg); - isdnloop_fake(card, buf, -1); - isdnloop_fake(card, "NAK", -1); -} - -static u_char ctable_eu[] = -{0x00, 0x11, 0x01, 0x12}; -static u_char ctable_1t[] = -{0x00, 0x3b, 0x01, 0x3a}; - -/* - * Assemble a simplified cause message depending on the - * D-channel protocol used. - * - * Parameter: - * card = pointer to card struct. - * loc = location: 0 = local, 1 = remote. - * cau = cause: 1 = busy, 2 = nonexistent callerid, 3 = no user responding. - * Return: - * Pointer to buffer containing the assembled message. - */ -static char * -isdnloop_unicause(isdnloop_card * card, int loc, int cau) -{ - static char buf[6]; - - switch (card->ptype) { - case ISDN_PTYPE_EURO: - sprintf(buf, "E%02X%02X", (loc) ? 4 : 2, ctable_eu[cau]); - break; - case ISDN_PTYPE_1TR6: - sprintf(buf, "%02X44", ctable_1t[cau]); - break; - default: - return ("0000"); - } - return (buf); -} - -/* - * Release a virtual connection. Called from timer interrupt, when - * called party did not respond. - * - * Parameter: - * card = pointer to card struct. - * ch = channel (0-based) - */ -static void -isdnloop_atimeout(isdnloop_card * card, int ch) -{ - unsigned long flags; - char buf[60]; - - save_flags(flags); - cli(); - if (card->rcard) { - isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1); - card->rcard[ch]->rcard[card->rch[ch]] = NULL; - card->rcard[ch] = NULL; - } - isdnloop_fake(card, "DDIS_I", ch + 1); - /* No user responding */ - sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3)); - isdnloop_fake(card, buf, ch + 1); - restore_flags(flags); -} - -/* - * Wrapper for isdnloop_atimeout(). - */ -static void -isdnloop_atimeout0(unsigned long data) -{ - isdnloop_card *card = (isdnloop_card *) data; - isdnloop_atimeout(card, 0); -} - -/* - * Wrapper for isdnloop_atimeout(). - */ -static void -isdnloop_atimeout1(unsigned long data) -{ - isdnloop_card *card = (isdnloop_card *) data; - isdnloop_atimeout(card, 1); -} - -/* - * Install a watchdog for a user, not responding. - * - * Parameter: - * card = pointer to card struct. - * ch = channel to watch for. - */ -static void -isdnloop_start_ctimer(isdnloop_card * card, int ch) -{ - unsigned long flags; - - save_flags(flags); - cli(); - init_timer(&card->c_timer[ch]); - card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT; - if (ch) - card->c_timer[ch].function = isdnloop_atimeout1; - else - card->c_timer[ch].function = isdnloop_atimeout0; - card->c_timer[ch].data = (unsigned long) card; - add_timer(&card->c_timer[ch]); - restore_flags(flags); -} - -/* - * Kill a pending channel watchdog. - * - * Parameter: - * card = pointer to card struct. - * ch = channel (0-based). - */ -static void -isdnloop_kill_ctimer(isdnloop_card * card, int ch) -{ - unsigned long flags; - - save_flags(flags); - cli(); - del_timer(&card->c_timer[ch]); - restore_flags(flags); -} - -static u_char si2bit[] = -{0, 1, 0, 0, 0, 2, 0, 4, 0, 0}; -static u_char bit2si[] = -{1, 5, 7}; - -/* - * Try finding a listener for an outgoing call. - * - * Parameter: - * card = pointer to calling card. - * p = pointer to ICN-type setup-string. - * lch = channel of calling card. - * cmd = pointer to struct to be filled when parsing setup. - * Return: - * 0 = found match, alerting should happen. - * 1 = found matching number but it is busy. - * 2 = no matching listener. - * 3 = found matching number but SI does not match. - */ -static int -isdnloop_try_call(isdnloop_card * card, char *p, int lch, isdn_ctrl * cmd) -{ - isdnloop_card *cc = cards; - unsigned long flags; - int ch; - int num_match; - int i; - char *e; - char nbuf[32]; - - isdnloop_parse_setup(p, cmd); - while (cc) { - for (ch = 0; ch < 2; ch++) { - /* Exclude ourself */ - if ((cc == card) && (ch == lch)) - continue; - num_match = 0; - switch (cc->ptype) { - case ISDN_PTYPE_EURO: - for (i = 0; i < 3; i++) - if (!(strcmp(cc->s0num[i], cmd->parm.setup.phone))) - num_match = 1; - break; - case ISDN_PTYPE_1TR6: - e = cc->eazlist[ch]; - while (*e) { - sprintf(nbuf, "%s%c", cc->s0num[0], *e); - if (!(strcmp(nbuf, cmd->parm.setup.phone))) - num_match = 1; - e++; - } - } - if (num_match) { - save_flags(flags); - cli(); - /* channel idle? */ - if (!(cc->rcard[ch])) { - /* Check SI */ - if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) { - restore_flags(flags); - return 3; - } - /* ch is idle, si and number matches */ - cc->rcard[ch] = card; - cc->rch[ch] = lch; - card->rcard[lch] = cc; - card->rch[lch] = ch; - restore_flags(flags); - return 0; - } else { - restore_flags(flags); - /* num matches, but busy */ - if (ch == 1) - return 1; - } - } - } - cc = cc->next; - } - return 2; -} - -/* - * Depending on D-channel protocol and caller/called, modify - * phone number. - * - * Parameter: - * card = pointer to card struct. - * phone = pointer phone number. - * caller = flag: 1 = caller, 0 = called. - * Return: - * pointer to new phone number. - */ -static char * -isdnloop_vstphone(isdnloop_card * card, char *phone, int caller) -{ - int i; - static char nphone[30]; - - switch (card->ptype) { - case ISDN_PTYPE_EURO: - if (caller) { - for (i = 0; i < 2; i++) - if (!(strcmp(card->s0num[i], phone))) - return (phone); - return (card->s0num[0]); - } - return (phone); - break; - case ISDN_PTYPE_1TR6: - if (caller) { - sprintf(nphone, "%s%c", card->s0num[0], phone[0]); - return (nphone); - } else - return (&phone[strlen(phone) - 1]); - break; - } - return ("\0"); -} - -/* - * Parse an ICN-type command string sent to the 'card'. - * Perform misc. actions depending on the command. - * - * Parameter: - * card = pointer to card struct. - */ -static void -isdnloop_parse_cmd(isdnloop_card * card) -{ - char *p = card->omsg; - isdn_ctrl cmd; - char buf[60]; - isdnloop_stat *s = isdnloop_cmd_table; - int action = -1; - int i; - int ch; - - if ((card->omsg[0] != '0') && (card->omsg[2] != ';')) { - isdnloop_fake_err(card); - return; - } - ch = card->omsg[1] - '0'; - if ((ch < 0) || (ch > 2)) { - isdnloop_fake_err(card); - return; - } - p += 3; - while (s->statstr) { - if (!strncmp(p, s->statstr, strlen(s->statstr))) { - action = s->action; - if (s->command && (ch != 0)) { - isdnloop_fake_err(card); - return; - } - break; - } - s++; - } - if (action == -1) - return; - switch (action) { - case 1: - /* 0x;BCON_R */ - if (card->rcard[ch - 1]) { - isdnloop_fake(card->rcard[ch - 1], "BCON_I", - card->rch[ch - 1] + 1); - } - break; - case 17: - /* 0x;BCON_I */ - if (card->rcard[ch - 1]) { - isdnloop_fake(card->rcard[ch - 1], "BCON_C", - card->rch[ch - 1] + 1); - } - break; - case 2: - /* 0x;BDIS_R */ - isdnloop_fake(card, "BDIS_C", ch); - if (card->rcard[ch - 1]) { - isdnloop_fake(card->rcard[ch - 1], "BDIS_I", - card->rch[ch - 1] + 1); - } - break; - case 16: - /* 0x;DCON_R */ - isdnloop_kill_ctimer(card, ch - 1); - if (card->rcard[ch - 1]) { - isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]); - isdnloop_fake(card->rcard[ch - 1], "DCON_C", - card->rch[ch - 1] + 1); - isdnloop_fake(card, "DCON_C", ch); - } - break; - case 3: - /* 0x;DDIS_R */ - isdnloop_kill_ctimer(card, ch - 1); - if (card->rcard[ch - 1]) { - isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]); - isdnloop_fake(card->rcard[ch - 1], "DDIS_I", - card->rch[ch - 1] + 1); - card->rcard[ch - 1] = NULL; - } - isdnloop_fake(card, "DDIS_C", ch); - break; - case 4: - /* 0x;DSCA_Rdd,yy,zz,oo */ - if (card->ptype != ISDN_PTYPE_1TR6) { - isdnloop_fake_err(card); - return; - } - /* Fall through */ - case 5: - /* 0x;DCAL_Rdd,yy,zz,oo */ - p += 6; - switch (isdnloop_try_call(card, p, ch - 1, &cmd)) { - case 0: - /* Alerting */ - sprintf(buf, "D%s_I%s,%02d,%02d,%s", - (action == 4) ? "SCA" : "CAL", - isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1), - cmd.parm.setup.si1, - cmd.parm.setup.si2, - isdnloop_vstphone(card->rcard[ch], - cmd.parm.setup.phone, 0)); - isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1); - /* Fall through */ - case 3: - /* si1 does not match, don't alert but start timer */ - isdnloop_start_ctimer(card, ch - 1); - break; - case 1: - /* Remote busy */ - isdnloop_fake(card, "DDIS_I", ch); - sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 1)); - isdnloop_fake(card, buf, ch); - break; - case 2: - /* No such user */ - isdnloop_fake(card, "DDIS_I", ch); - sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 2)); - isdnloop_fake(card, buf, ch); - break; - } - break; - case 6: - /* 0x;EAZC */ - card->eazlist[ch - 1][0] = '\0'; - break; - case 7: - /* 0x;EAZ */ - p += 3; - strcpy(card->eazlist[ch - 1], p); - break; - case 8: - /* 0x;SEEAZ */ - sprintf(buf, "EAZ-LIST: %s", card->eazlist[ch - 1]); - isdnloop_fake(card, buf, ch + 1); - break; - case 9: - /* 0x;MSN */ - break; - case 10: - /* 0x;MSNALL */ - break; - case 11: - /* 0x;SETSIL */ - p += 6; - i = 0; - while (strchr("0157", *p)) { - if (i) - card->sil[ch - 1] |= si2bit[*p - '0']; - i = (*p++ == '0'); - } - if (*p) - isdnloop_fake_err(card); - break; - case 12: - /* 0x;SEESIL */ - sprintf(buf, "SIN-LIST: "); - p = buf + 10; - for (i = 0; i < 3; i++) - if (card->sil[ch - 1] & (1 << i)) - p += sprintf(p, "%02d", bit2si[i]); - isdnloop_fake(card, buf, ch + 1); - break; - case 13: - /* 0x;SILC */ - card->sil[ch - 1] = 0; - break; - case 14: - /* 00;FV2ON */ - break; - case 15: - /* 00;FV2OFF */ - break; - } -} - -/* - * Put command-strings into the of the 'card'. In reality, execute them - * right in place by calling isdnloop_parse_cmd(). Also copy every - * command to the read message ringbuffer, preceeding it with a '>'. - * These mesagges can be read at /dev/isdnctrl. - * - * Parameter: - * buf = pointer to command buffer. - * len = length of buffer data. - * user = flag: 1 = called form userlevel, 0 called from kernel. - * card = pointer to card struct. - * Return: - * number of bytes transfered (currently always equals len). - */ -static int -isdnloop_writecmd(const u_char * buf, int len, int user, isdnloop_card * card) -{ - int xcount = 0; - int ocount = 1; - isdn_ctrl cmd; - - while (len) { - int count = MIN(255, len); - u_char *p; - u_char msg[0x100]; - - if (user) - copy_from_user(msg, buf, count); - else - memcpy(msg, buf, count); - isdnloop_putmsg(card, '>'); - for (p = msg; count > 0; count--, p++) { - len--; - xcount++; - isdnloop_putmsg(card, *p); - card->omsg[card->optr] = *p; - if (*p == '\n') { - card->omsg[card->optr] = '\0'; - card->optr = 0; - isdnloop_parse_cmd(card); - if (len) { - isdnloop_putmsg(card, '>'); - ocount++; - } - } else { - if (card->optr < 59) - card->optr++; - } - ocount++; - } - } - cmd.command = ISDN_STAT_STAVAIL; - cmd.driver = card->myid; - cmd.arg = ocount; - card->interface.statcallb(&cmd); - return xcount; -} - -/* - * Delete card's pending timers, send STOP to linklevel - */ -static void -isdnloop_stopcard(isdnloop_card * card) -{ - unsigned long flags; - isdn_ctrl cmd; - - save_flags(flags); - cli(); - if (card->flags & ISDNLOOP_FLAGS_RUNNING) { - card->flags &= ~ISDNLOOP_FLAGS_RUNNING; - del_timer(&card->st_timer); - del_timer(&card->rb_timer); - del_timer(&card->c_timer[0]); - del_timer(&card->c_timer[1]); - cmd.command = ISDN_STAT_STOP; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - } - restore_flags(flags); -} - -/* - * Stop all cards before unload. - */ -static void -isdnloop_stopallcards(void) -{ - isdnloop_card *p = cards; - - while (p) { - isdnloop_stopcard(p); - p = p->next; - } -} - -/* - * Start a 'card'. Simulate card's boot message and set the phone - * number(s) of the virtual 'S0-Interface'. Install D-channel - * poll timer. - * - * Parameter: - * card = pointer to card struct. - * sdefp = pointer to struct holding ioctl parameters. - * Return: - * 0 on success, -E??? otherwise. - */ -static int -isdnloop_start(isdnloop_card * card, isdnloop_sdef * sdefp) -{ - unsigned long flags; - isdnloop_sdef sdef; - int i; - - if (card->flags & ISDNLOOP_FLAGS_RUNNING) - return -EBUSY; - copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)); - save_flags(flags); - cli(); - switch (sdef.ptype) { - case ISDN_PTYPE_EURO: - if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96", - -1)) { - restore_flags(flags); - return -ENOMEM; - } - card->sil[0] = card->sil[1] = 4; - if (isdnloop_fake(card, "TEI OK", 0)) { - restore_flags(flags); - return -ENOMEM; - } - for (i = 0; i < 3; i++) - strcpy(card->s0num[i], sdef.num[i]); - break; - case ISDN_PTYPE_1TR6: - if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", - -1)) { - restore_flags(flags); - return -ENOMEM; - } - card->sil[0] = card->sil[1] = 4; - if (isdnloop_fake(card, "TEI OK", 0)) { - restore_flags(flags); - return -ENOMEM; - } - strcpy(card->s0num[0], sdef.num[0]); - card->s0num[1][0] = '\0'; - card->s0num[2][0] = '\0'; - break; - default: - restore_flags(flags); - printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n", - sdef.ptype); - return -EINVAL; - } - init_timer(&card->st_timer); - card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD; - card->st_timer.function = isdnloop_polldchan; - card->st_timer.data = (unsigned long) card; - add_timer(&card->st_timer); - card->flags |= ISDNLOOP_FLAGS_RUNNING; - restore_flags(flags); - return 0; -} - -/* - * Main handler for commands sent by linklevel. - */ -static int -isdnloop_command(isdn_ctrl * c, isdnloop_card * card) -{ - ulong a; - int i; - char cbuf[60]; - isdn_ctrl cmd; - isdnloop_cdef cdef; - - switch (c->command) { - case ISDN_CMD_IOCTL: - memcpy(&a, c->parm.num, sizeof(ulong)); - switch (c->arg) { - case ISDNLOOP_IOCTL_DEBUGVAR: - return (ulong) card; - case ISDNLOOP_IOCTL_STARTUP: - if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(isdnloop_sdef)))) - return i; - return (isdnloop_start(card, (isdnloop_sdef *) a)); - break; - case ISDNLOOP_IOCTL_ADDCARD: - if ((i = verify_area(VERIFY_READ, (void *) a, sizeof(isdnloop_cdef)))) - return i; - copy_from_user((char *) &cdef, (char *) a, sizeof(cdef)); - return (isdnloop_addcard(cdef.id1)); - break; - case ISDNLOOP_IOCTL_LEASEDCFG: - if (a) { - if (!card->leased) { - card->leased = 1; - while (card->ptype == ISDN_PTYPE_UNKNOWN) { - schedule_timeout(10); - } - schedule_timeout(10); - sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n"); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - printk(KERN_INFO - "isdnloop: (%s) Leased-line mode enabled\n", - CID); - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - } else { - if (card->leased) { - card->leased = 0; - sprintf(cbuf, "00;FV2OFF\n"); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - printk(KERN_INFO - "isdnloop: (%s) Leased-line mode disabled\n", - CID); - cmd.command = ISDN_STAT_RUN; - cmd.driver = card->myid; - cmd.arg = 0; - card->interface.statcallb(&cmd); - } - } - return 0; - default: - return -EINVAL; - } - break; - case ISDN_CMD_DIAL: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if (card->leased) - break; - if ((c->arg & 255) < ISDNLOOP_BCH) { - char *p; - char dial[50]; - char dcode[4]; - - a = c->arg; - p = c->parm.setup.phone; - if (*p == 's' || *p == 'S') { - /* Dial for SPV */ - p++; - strcpy(dcode, "SCA"); - } else - /* Normal Dial */ - strcpy(dcode, "CAL"); - strcpy(dial, p); - sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), - dcode, dial, c->parm.setup.si1, - c->parm.setup.si2, c->parm.setup.eazmsn); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_ACCEPTD: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if (c->arg < ISDNLOOP_BCH) { - a = c->arg + 1; - cbuf[0] = 0; - switch (card->l2_proto[a - 1]) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) a); - break; -#ifdef CONFIG_ISDN_X25 - case ISDN_PROTO_L2_X25DTE: - sprintf(cbuf, "%02d;BX2T\n", (int) a); - break; - case ISDN_PROTO_L2_X25DCE: - sprintf(cbuf, "%02d;BX2C\n", (int) a); - break; -#endif - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) a); - break; - } - if (strlen(cbuf)) - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - sprintf(cbuf, "%02d;DCON_R\n", (int) a); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_ACCEPTB: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if (c->arg < ISDNLOOP_BCH) { - a = c->arg + 1; - switch (card->l2_proto[a - 1]) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a); - break; -#ifdef CONFIG_ISDN_X25 - case ISDN_PROTO_L2_X25DTE: - sprintf(cbuf, "%02d;BCON_R,BX2T\n", (int) a); - break; - case ISDN_PROTO_L2_X25DCE: - sprintf(cbuf, "%02d;BCON_R,BX2C\n", (int) a); - break; -#endif - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a); - break; - default: - sprintf(cbuf, "%02d;BCON_R\n", (int) a); - } - printk(KERN_DEBUG "isdnloop writecmd '%s'\n", cbuf); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - break; - case ISDN_CMD_HANGUP: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if (c->arg < ISDNLOOP_BCH) { - a = c->arg + 1; - sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_SETEAZ: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if (card->leased) - break; - if (c->arg < ISDNLOOP_BCH) { - a = c->arg + 1; - if (card->ptype == ISDN_PTYPE_EURO) { - sprintf(cbuf, "%02d;MS%s%s\n", (int) a, - c->parm.num[0] ? "N" : "ALL", c->parm.num); - } else - sprintf(cbuf, "%02d;EAZ%s\n", (int) a, - c->parm.num[0] ? c->parm.num : (u_char *) "0123456789"); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_CLREAZ: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if (card->leased) - break; - if (c->arg < ISDNLOOP_BCH) { - a = c->arg + 1; - if (card->ptype == ISDN_PTYPE_EURO) - sprintf(cbuf, "%02d;MSNC\n", (int) a); - else - sprintf(cbuf, "%02d;EAZC\n", (int) a); - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - } - break; - case ISDN_CMD_SETL2: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ISDNLOOP_BCH) { - a = c->arg; - switch (a >> 8) { - case ISDN_PROTO_L2_X75I: - sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1); - break; -#ifdef CONFIG_ISDN_X25 - case ISDN_PROTO_L2_X25DTE: - sprintf(cbuf, "%02d;BX2T\n", (int) (a & 255) + 1); - break; - case ISDN_PROTO_L2_X25DCE: - sprintf(cbuf, "%02d;BX2C\n", (int) (a & 255) + 1); - break; -#endif - case ISDN_PROTO_L2_HDLC: - sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1); - break; - default: - return -EINVAL; - } - i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card); - card->l2_proto[a & 255] = (a >> 8); - } - break; - case ISDN_CMD_GETL2: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ISDNLOOP_BCH) - return card->l2_proto[c->arg & 255]; - else - return -ENODEV; - case ISDN_CMD_SETL3: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - return 0; - case ISDN_CMD_GETL3: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - if ((c->arg & 255) < ISDNLOOP_BCH) - return ISDN_PROTO_L3_TRANS; - else - return -ENODEV; - case ISDN_CMD_GETEAZ: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_SETSIL: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_GETSIL: - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - break; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - break; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - break; - default: - return -EINVAL; - } - } - return 0; -} - -/* - * Find card with given driverId - */ -static inline isdnloop_card * -isdnloop_findcard(int driverid) -{ - isdnloop_card *p = cards; - - while (p) { - if (p->myid == driverid) - return p; - p = p->next; - } - return (isdnloop_card *) 0; -} - -/* - * Wrapper functions for interface to linklevel - */ -static int -if_command(isdn_ctrl * c) -{ - isdnloop_card *card = isdnloop_findcard(c->driver); - - if (card) - return (isdnloop_command(c, card)); - printk(KERN_ERR - "isdnloop: if_command called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_writecmd(const u_char * buf, int len, int user, int id, int channel) -{ - isdnloop_card *card = isdnloop_findcard(id); - - if (card) { - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - return (isdnloop_writecmd(buf, len, user, card)); - } - printk(KERN_ERR - "isdnloop: if_writecmd called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_readstatus(u_char * buf, int len, int user, int id, int channel) -{ - isdnloop_card *card = isdnloop_findcard(id); - - if (card) { - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - return (isdnloop_readstatus(buf, len, user, card)); - } - printk(KERN_ERR - "isdnloop: if_readstatus called with invalid driverId!\n"); - return -ENODEV; -} - -static int -if_sendbuf(int id, int channel, int ack, struct sk_buff *skb) -{ - isdnloop_card *card = isdnloop_findcard(id); - - if (card) { - if (!card->flags & ISDNLOOP_FLAGS_RUNNING) - return -ENODEV; - /* ack request stored in skb scratch area */ - *(skb->head) = ack; - return (isdnloop_sendbuf(channel, skb, card)); - } - printk(KERN_ERR - "isdnloop: if_sendbuf called with invalid driverId!\n"); - return -ENODEV; -} - -/* - * Allocate a new card-struct, initialize it - * link it into cards-list and register it at linklevel. - */ -static isdnloop_card * -isdnloop_initcard(char *id) -{ - isdnloop_card *card; - int i; - - if (!(card = (isdnloop_card *) kmalloc(sizeof(isdnloop_card), GFP_KERNEL))) { - printk(KERN_WARNING - "isdnloop: (%s) Could not allocate card-struct.\n", id); - return (isdnloop_card *) 0; - } - memset((char *) card, 0, sizeof(isdnloop_card)); - card->interface.channels = ISDNLOOP_BCH; - card->interface.hl_hdrlen = 1; /* scratch area for storing ack flag*/ - card->interface.maxbufsize = 4000; - card->interface.command = if_command; - card->interface.writebuf_skb = if_sendbuf; - card->interface.writecmd = if_writecmd; - card->interface.readstat = if_readstatus; - card->interface.features = ISDN_FEATURE_L2_X75I | -#ifdef CONFIG_ISDN_X25 - ISDN_FEATURE_L2_X25DTE | - ISDN_FEATURE_L2_X25DCE | -#endif - ISDN_FEATURE_L2_HDLC | - ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_P_UNKNOWN; - card->ptype = ISDN_PTYPE_UNKNOWN; - strncpy(card->interface.id, id, sizeof(card->interface.id) - 1); - card->msg_buf_write = card->msg_buf; - card->msg_buf_read = card->msg_buf; - card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1]; - for (i = 0; i < ISDNLOOP_BCH; i++) { - card->l2_proto[i] = ISDN_PROTO_L2_X75I; - skb_queue_head_init(&card->bqueue[i]); - } - skb_queue_head_init(&card->dqueue); - card->next = cards; - cards = card; - if (!register_isdn(&card->interface)) { - cards = cards->next; - printk(KERN_WARNING - "isdnloop: Unable to register %s\n", id); - kfree(card); - return (isdnloop_card *) 0; - } - card->myid = card->interface.channels; - return card; -} - -static int -isdnloop_addcard(char *id1) -{ - ulong flags; - isdnloop_card *card; - - save_flags(flags); - cli(); - if (!(card = isdnloop_initcard(id1))) { - restore_flags(flags); - return -EIO; - } - restore_flags(flags); - printk(KERN_INFO - "isdnloop: (%s) virtual card added\n", - card->interface.id); - return 0; -} - -#ifdef MODULE -#define isdnloop_init init_module -#else -void -isdnloop_setup(char *str, int *ints) -{ - static char sid[20]; - - if (strlen(str)) { - strcpy(sid, str); - isdnloop_id = sid; - } -} -#endif - -int -isdnloop_init(void) -{ - char *p; - char rev[10]; - - /* No symbols to export, hide all symbols */ - EXPORT_NO_SYMBOLS; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, " ??? "); - printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev); - return (isdnloop_addcard(isdnloop_id)); -} - -#ifdef MODULE -void -cleanup_module(void) -{ - isdn_ctrl cmd; - isdnloop_card *card = cards; - isdnloop_card *last; - int i; - - isdnloop_stopallcards(); - while (card) { - cmd.command = ISDN_STAT_UNLOAD; - cmd.driver = card->myid; - card->interface.statcallb(&cmd); - for (i = 0; i < ISDNLOOP_BCH; i++) - isdnloop_free_queue(card, i); - card = card->next; - } - card = cards; - while (card) { - struct sk_buff *skb; - - last = card; - while ((skb = skb_dequeue(&card->dqueue))) - dev_kfree_skb(skb); - card = card->next; - kfree(last); - } - printk(KERN_NOTICE "isdnloop-ISDN-driver unloaded\n"); -} -#endif diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h deleted file mode 100644 index 544a84a1..00000000 --- a/drivers/isdn/isdnloop/isdnloop.h +++ /dev/null @@ -1,147 +0,0 @@ -/* $Id$ - - * Loopback lowlevel module for testing of linklevel. - * - * Copyright 1997 by Fritz Elfert (fritz@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. - * - * $Log$ - * Revision 1.3 1998/04/14 20:59:35 he - * merged 2.1.94 changes - * - * Revision 1.2 1997/10/01 09:22:07 fritz - * Removed old compatibility stuff for 2.0.X kernels. - * From now on, this code is for 2.1.X ONLY! - * Old stuff is still in the separate branch. - * - * Revision 1.1 1997/03/24 23:02:05 fritz - * Added isdnloop driver. - * - */ - -#ifndef isdnloop_h -#define isdnloop_h - -#define ISDNLOOP_IOCTL_DEBUGVAR 0 -#define ISDNLOOP_IOCTL_ADDCARD 1 -#define ISDNLOOP_IOCTL_LEASEDCFG 2 -#define ISDNLOOP_IOCTL_STARTUP 3 - -/* Struct for adding new cards */ -typedef struct isdnloop_cdef { - char id1[10]; -} isdnloop_cdef; - -/* Struct for configuring cards */ -typedef struct isdnloop_sdef { - int ptype; - char num[3][20]; -} isdnloop_sdef; - -#if defined(__KERNEL__) || defined(__DEBUGVAR__) - -#ifdef __KERNEL__ -/* Kernel includes */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif /* __KERNEL__ */ - -#define ISDNLOOP_FLAGS_B1ACTIVE 1 /* B-Channel-1 is open */ -#define ISDNLOOP_FLAGS_B2ACTIVE 2 /* B-Channel-2 is open */ -#define ISDNLOOP_FLAGS_RUNNING 4 /* Cards driver activated */ -#define ISDNLOOP_FLAGS_RBTIMER 8 /* scheduling of B-Channel-poll */ -#define ISDNLOOP_TIMER_BCREAD 1 /* B-Channel poll-cycle */ -#define ISDNLOOP_TIMER_DCREAD (HZ/2) /* D-Channel poll-cycle */ -#define ISDNLOOP_TIMER_ALERTWAIT (10*HZ) /* Alert timeout */ -#define ISDNLOOP_MAX_SQUEUE 65536 /* Max. outstanding send-data */ -#define ISDNLOOP_BCH 2 /* channels per card */ - -/* - * Per card driver data - */ -typedef struct isdnloop_card { - struct isdnloop_card *next; /* Pointer to next device struct */ - struct isdnloop_card - *rcard[ISDNLOOP_BCH]; /* Pointer to 'remote' card */ - int rch[ISDNLOOP_BCH]; /* 'remote' channel */ - int myid; /* Driver-Nr. assigned by linklevel */ - int leased; /* Flag: This Adapter is connected */ - /* to a leased line */ - int sil[ISDNLOOP_BCH]; /* SI's to listen for */ - char eazlist[ISDNLOOP_BCH][11]; - /* EAZ's to listen for */ - char s0num[3][20]; /* 1TR6 base-number or MSN's */ - unsigned short flags; /* Statusflags */ - int ptype; /* Protocol type (1TR6 or Euro) */ - struct timer_list st_timer; /* Timer for Status-Polls */ - struct timer_list rb_timer; /* Timer for B-Channel-Polls */ - struct timer_list - c_timer[ISDNLOOP_BCH]; /* Timer for Alerting */ - int l2_proto[ISDNLOOP_BCH]; /* Current layer-2-protocol */ - isdn_if interface; /* Interface to upper layer */ - int iptr; /* Index to imsg-buffer */ - char imsg[60]; /* Internal buf for status-parsing */ - int optr; /* Index to omsg-buffer */ - char omsg[60]; /* Internal buf for cmd-parsing */ - char msg_buf[2048]; /* Buffer for status-messages */ - char *msg_buf_write; /* Writepointer for statusbuffer */ - char *msg_buf_read; /* Readpointer for statusbuffer */ - char *msg_buf_end; /* Pointer to end of statusbuffer */ - int sndcount[ISDNLOOP_BCH]; /* Byte-counters for B-Ch.-send */ - struct sk_buff_head - bqueue[ISDNLOOP_BCH]; /* B-Channel queues */ - struct sk_buff_head dqueue; /* D-Channel queue */ -} isdnloop_card; - -/* - * Main driver data - */ -#ifdef __KERNEL__ -static isdnloop_card *cards = (isdnloop_card *) 0; -static char *isdnloop_id = "\0"; - -#ifdef MODULE -MODULE_AUTHOR("Fritz Elfert"); -MODULE_PARM(isdnloop_id, "s"); -MODULE_PARM_DESC(isdnloop_id, "ID-String of first card"); -#endif - -#endif /* __KERNEL__ */ - -/* Utility-Macros */ - -#define CID (card->interface.id) -#define MIN(a,b) ((ab)?a:b) - -#endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */ -#endif /* isdnloop_h */ diff --git a/drivers/isdn/kdebug.h b/drivers/isdn/kdebug.h deleted file mode 100644 index cbaede2c..00000000 --- a/drivers/isdn/kdebug.h +++ /dev/null @@ -1,210 +0,0 @@ -/* $Id$ - - * Debugging utilities for Linux - * - * For debugging, include this file. If included more than once - * in a multi-module driver, exactly one include-statement should - * be preceeded by a #define KDBUG_DEF. - * - * What does this?: - * Main purpose is to realize a way of logging, even if interrupts - * are disabled. To work on virtual-screens with a screen-width other - * than 80, change the LINEWIDTH below.# - * - * For use with modules, you have to export screen_pos and fg_console - * from console.c and selection.h - * For recent kernels (e.g. 2.1.86) do this, by adding modifying - * kernel/ksyms.c: - * - * At end of other include-lines: - * Add an #include - * - * At section /* tty routines */ add the following lines: - * EXPORT_SYMBOL(fg_console) - * EXPORT_SYMBOL(screen_pos) - * - * Finally, rebuild the kernel. Now you can create modules using - * kdebug.h - * - * Functionality: - * - * -If you have defined CLI_DEBUG - * cli(), sti() and restore_flags() are redefined. Every time, cli() - * is called, the filename and linenumber of the caller is printed - * on the console, preceeded by a "!". Once interrupts are enabled - * again, - either with sti() or restore_flags() - the exclamation - * mark is replaced by a blank. - * - * -Wrapper-Macro for function calls. CTR(myfunc(a,b,c)) prints - * "Enter myfunc(...)", then executes the call, then prints - * "Leave myfunc(...)". Screenposition is 40,0. - * - * -Generic counter macros. DBGCNTDEF(n,x,y); Defines counter nr. n - * to be shown at screen-position x,y. DBGCNTINC(n); increments - * counter n. - * - * -An "i-am-alive" rotating bar. wheel(x,y) rotates a bar at - * position x,y. - * - * $Log$ - * Revision 1.3 1998/02/08 20:47:17 keil - * Changes for 2.1 (virtual address mapping; SMP stuff) - * New CLI_DEBUG define to enable cli/sti/restore_flags debugging - * - * Revision 1.2 1997/02/03 23:33:22 fritz - * Reformatted according CodingStyle - * - * Revision 1.1 1996/04/30 09:22:55 fritz - * Taken under CVS-control. - * - * - */ - -#ifndef _kdebug_h_ -#define _kdebug_h_ - -#include -#include - -#define LINEWIDTH 80 - -extern unsigned short *screen_pos(int, int, int); -extern int fg_console; - -#ifdef KDEBUG_DEF -unsigned short *scrpos; -int dbg_cnt_v[10]; -int dbg_cnt_x[10]; -int dbg_cnt_y[10]; -char clibuf[256] = "\0"; -#else -extern unsigned short *scrpos; -extern int dbg_cnt_v[10]; -extern int dbg_cnt_x[10]; -extern int dbg_cnt_y[10]; -extern char clibuf[256]; -#endif - -static __inline__ void -put_ch(const char c) -{ - writew(0x0700 + c, scrpos++); -} - -static __inline__ void -put_str(char *s) -{ - for (; *s; put_ch(*s++)); -} - -static __inline__ void -gotovid(int x, int y) -{ - scrpos = screen_pos(fg_console, (y * LINEWIDTH) + x, 1); -} - -static __inline__ void -gput_str(char *s, int x, int y) -{ - gotovid(x, y); - put_str(s); -} - -static __inline__ void -gput_ch(char c, int x, int y) -{ - gotovid(x, y); - put_ch(c); -} - -static __inline__ void -wheel(int x, int y) -{ - gotovid(x, y); - switch ((char) (readw(scrpos) & 0xff)) { - case '/': - writew(0x0700 + '-', scrpos); - break; - case '-': - writew(0x0700 + '\\', scrpos); - break; - case '\\': - writew(0x0700 + '|', scrpos); - break; - default: - writew(0x0700 + '/', scrpos); - } -} - -#ifdef CLI_DEBUG - -#ifndef __ASM_SYSTEM_H -#include -#endif - -#ifdef __SMP__ - -extern void __global_cli(void); -extern void __global_sti(void); -extern void __global_restore_flags(unsigned long); -#define x__cli() __global_cli() -#define x__sti() __global_sti() -#define x__restore_flags(x) __global_restore_flags(x) - -#else - -#define x__cli() __cli() -#define x__sti() __sti() -#define x__restore_flags(x) __restore_flags(x) - -#endif - -#undef cli -#define cli() { \ - x__cli(); \ - sprintf(clibuf,"!%-20s %04d !",__BASE_FILE__,__LINE__); \ - gput_str(clibuf,0,0); \ -} - -#undef restore_flags -#define restore_flags(x) { \ - if (x & 0x200) gput_ch(' ',0,0); \ - x__restore_flags(x); \ -} - -#undef sti -#define sti() { \ - gput_ch(' ',0,0); \ - x__sti(); \ -} -#endif /* CLI_DEBUG */ - -#define CTR(x) { \ - gput_str("Enter " #x " ", 40, 0); \ - x; \ - gput_str("Leave " #x " ", 40, 0); \ -} - -#define CTRXY(x, y, fn) { \ - gput_str("Enter " #fn " ", x, y); \ - fn; \ - gput_str("Leave " #fn " ", x, y); \ -} - -#define DBGCNTDEF(n,x,y) { \ - char tmp[10]; \ - dbg_cnt_v[n] = 0; \ - dbg_cnt_x[n] = x; \ - dbg_cnt_y[n] = y; \ - sprintf(tmp,"%02d",0); \ - gput_str(tmp,x,y); \ -} - -#define DBGCNTINC(i) { \ - char tmp[10]; \ - dbg_cnt_v[i]++; \ - sprintf(tmp,"%02d",dbg_cnt_v[i]); \ - gput_str(tmp,dbg_cnt_x[i],dbg_cnt_y[i]); \ -} - -#endif diff --git a/drivers/isdn/pcbit/Makefile b/drivers/isdn/pcbit/Makefile deleted file mode 100644 index 50a67269..00000000 --- a/drivers/isdn/pcbit/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -L_OBJS := -M_OBJS := -O_OBJS := module.o edss1.o drv.o layer2.o capi.o callbacks.o - -O_TARGET := -ifeq ($(CONFIG_ISDN_DRV_PCBIT),y) - O_TARGET += pcbit.o -else - ifeq ($(CONFIG_ISDN_DRV_PCBIT),m) - O_TARGET += pcbit.o - M_OBJS += pcbit.o - endif -endif - -include $(TOPDIR)/Rules.make diff --git a/drivers/isdn/pcbit/callbacks.c b/drivers/isdn/pcbit/callbacks.c deleted file mode 100644 index afa22b74..00000000 --- a/drivers/isdn/pcbit/callbacks.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * callbacks for the FSM - */ - -/* - * Fix: 19981230 - Carlos Morgado - * Port of Nelson Escravana's fix to CalledPN - * NULL pointer dereference in cb_in_1 (originally fixed in 2.0) - */ - - -#define __NO_VERSION__ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include - -#include "pcbit.h" -#include "layer2.h" -#include "edss1.h" -#include "callbacks.h" -#include "capi.h" - -ushort last_ref_num = 1; - -/* - * send_conn_req - * - */ - -void cb_out_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *cbdata) -{ - struct sk_buff *skb; - int len; - ushort refnum; - - -#ifdef DEBUG - printk(KERN_DEBUG "Called Party Number: %s\n", - cbdata->data.setup.CalledPN); -#endif - /* - * hdr - kmalloc in capi_conn_req - * - kfree when msg has been sent - */ - - if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb, - chan->proto)) < 0) - { - printk("capi_conn_req failed\n"); - return; - } - - - refnum = last_ref_num++ & 0x7fffU; - - chan->callref = 0; - chan->layer2link = 0; - chan->snum = 0; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_CONN_REQ, refnum, skb, len); -} - -/* - * rcv CONNECT - * will go into ACTIVE state - * send CONN_ACTIVE_RESP - * send Select protocol request - */ - -void cb_out_2(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - isdn_ctrl ictl; - struct sk_buff *skb; - int len; - ushort refnum; - - if ((len=capi_conn_active_resp(chan, &skb)) < 0) - { - printk("capi_conn_active_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_CONN_ACTV_RESP, refnum, skb, len); - - - ictl.command = ISDN_STAT_DCONN; - ictl.driver=dev->id; - ictl.arg=chan->id; - dev->dev_if->statcallb(&ictl); - - /* ACTIVE D-channel */ - - /* Select protocol */ - - if ((len=capi_select_proto_req(chan, &skb, 1 /*outgoing*/)) < 0) { - printk("capi_select_proto_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len); -} - - -/* - * Disconnect received (actually RELEASE COMPLETE) - * This means we were not able to establish connection with remote - * Inform the big boss above - */ -void cb_out_3(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - isdn_ctrl ictl; - - ictl.command = ISDN_STAT_DHUP; - ictl.driver=dev->id; - ictl.arg=chan->id; - dev->dev_if->statcallb(&ictl); -} - - -/* - * Incoming call received - * inform user - */ - -void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *cbdata) -{ - isdn_ctrl ictl; - unsigned short refnum; - struct sk_buff *skb; - int len; - - - ictl.command = ISDN_STAT_ICALL; - ictl.driver=dev->id; - ictl.arg=chan->id; - - /* - * ictl.num >= strlen() + strlen() + 5 - */ - - if (cbdata->data.setup.CallingPN == NULL) { - printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n"); - strcpy(ictl.parm.setup.phone, "0"); - } - else { - strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN); - } - if (cbdata->data.setup.CalledPN == NULL) { - printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n"); - strcpy(ictl.parm.setup.eazmsn, "0"); - } - else { - strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN); - } - ictl.parm.setup.si1 = 7; - ictl.parm.setup.si2 = 0; - ictl.parm.setup.plan = 0; - ictl.parm.setup.screen = 0; - -#ifdef DEBUG - printk(KERN_DEBUG "statstr: %s\n", ictl.num); -#endif - - dev->dev_if->statcallb(&ictl); - - - if ((len=capi_conn_resp(chan, &skb)) < 0) { - printk(KERN_DEBUG "capi_conn_resp failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_CONN_RESP, refnum, skb, len); -} - -/* - * user has replied - * open the channel - * send CONNECT message CONNECT_ACTIVE_REQ in CAPI - */ - -void cb_in_2(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - unsigned short refnum; - struct sk_buff *skb; - int len; - - if ((len = capi_conn_active_req(chan, &skb)) < 0) { - printk(KERN_DEBUG "capi_conn_active_req failed\n"); - return; - } - - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - printk(KERN_DEBUG "sending MSG_CONN_ACTV_REQ\n"); - pcbit_l2_write(dev, MSG_CONN_ACTV_REQ, refnum, skb, len); -} - -/* - * CONN_ACK arrived - * start b-proto selection - * - */ - -void cb_in_3(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - unsigned short refnum; - struct sk_buff *skb; - int len; - - if ((len = capi_select_proto_req(chan, &skb, 0 /*incoming*/)) < 0) - { - printk("capi_select_proto_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len); - -} - - -/* - * Received disconnect ind on active state - * send disconnect resp - * send msg to user - */ -void cb_disc_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - struct sk_buff *skb; - int len; - ushort refnum; - isdn_ctrl ictl; - - if ((len = capi_disc_resp(chan, &skb)) < 0) { - printk("capi_disc_resp failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_DISC_RESP, refnum, skb, len); - - ictl.command = ISDN_STAT_BHUP; - ictl.driver=dev->id; - ictl.arg=chan->id; - dev->dev_if->statcallb(&ictl); -} - - -/* - * User HANGUP on active/call proceeding state - * send disc.req - */ -void cb_disc_2(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - struct sk_buff *skb; - int len; - ushort refnum; - - if ((len = capi_disc_req(chan->callref, &skb, CAUSE_NORMAL)) < 0) - { - printk("capi_disc_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb, len); -} - -/* - * Disc confirm received send BHUP - * Problem: when the HL driver sends the disc req itself - * LL receives BHUP - */ -void cb_disc_3(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - isdn_ctrl ictl; - - ictl.command = ISDN_STAT_BHUP; - ictl.driver=dev->id; - ictl.arg=chan->id; - dev->dev_if->statcallb(&ictl); -} - -void cb_notdone(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ -} - -/* - * send activate b-chan protocol - */ -void cb_selp_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - struct sk_buff *skb; - int len; - ushort refnum; - - if ((len = capi_activate_transp_req(chan, &skb)) < 0) - { - printk("capi_conn_activate_transp_req failed\n"); - return; - } - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_ACT_TRANSP_REQ, refnum, skb, len); -} - -/* - * Inform User that the B-channel is available - */ -void cb_open(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data) -{ - isdn_ctrl ictl; - - ictl.command = ISDN_STAT_BCONN; - ictl.driver=dev->id; - ictl.arg=chan->id; - dev->dev_if->statcallb(&ictl); -} - - - diff --git a/drivers/isdn/pcbit/callbacks.h b/drivers/isdn/pcbit/callbacks.h deleted file mode 100644 index 62e296de..00000000 --- a/drivers/isdn/pcbit/callbacks.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * Callbacks prototypes for FSM - * - */ - -#ifndef CALLBACKS_H -#define CALLBACKS_H - - -extern void cb_out_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); - -extern void cb_out_2(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); - -extern void cb_out_3(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); - -extern void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); -extern void cb_in_2(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); -extern void cb_in_3(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); - -extern void cb_disc_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); -extern void cb_disc_2(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); -extern void cb_disc_3(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); - -extern void cb_notdone(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); - -extern void cb_selp_1(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); -extern void cb_open(struct pcbit_dev * dev, struct pcbit_chan* chan, - struct callb_data *data); - -#endif - - diff --git a/drivers/isdn/pcbit/capi.c b/drivers/isdn/pcbit/capi.c deleted file mode 100644 index ed681f37..00000000 --- a/drivers/isdn/pcbit/capi.c +++ /dev/null @@ -1,662 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * CAPI encoder/decoder for - * Portugal Telecom CAPI 2.0 - * - * Not compatible with the AVM Gmbh. CAPI 2.0 - */ - -/* - * Documentation: - * - "Common ISDN API - Perfil Português - Versão 2.1", - * Telecom Portugal, Fev 1992. - * - "Common ISDN API - Especificação de protocolos para - * acesso aos canais B", Inesc, Jan 1994. - */ - -/* - * TODO: better decoding of Information Elements - * for debug purposes mainly - * encode our number in CallerPN and ConnectedPN - */ - -#define __NO_VERSION__ - -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include - -#include - -#include "pcbit.h" -#include "edss1.h" -#include "capi.h" - - -/* - * Encoding of CAPI messages - * - */ - -int capi_conn_req(const char * calledPN, struct sk_buff **skb, int proto) -{ - ushort len; - - /* - * length - * AppInfoMask - 2 - * BC0 - 3 - * BC1 - 1 - * Chan - 2 - * Keypad - 1 - * CPN - 1 - * CPSA - 1 - * CalledPN - 2 + strlen - * CalledPSA - 1 - * rest... - 4 - * ---------------- - * Total 18 + strlen - */ - - len = 18 + strlen(calledPN); - - if (proto == ISDN_PROTO_L2_TRANS) - len++; - - if ((*skb = dev_alloc_skb(len)) == NULL) { - - printk(KERN_WARNING "capi_conn_req: alloc_skb failed\n"); - return -1; - } - - /* InfoElmMask */ - *((ushort*) skb_put(*skb, 2)) = AppInfoMask; - - if (proto == ISDN_PROTO_L2_TRANS) - { - /* Bearer Capability - Mandatory*/ - *(skb_put(*skb, 1)) = 3; /* BC0.Length */ - *(skb_put(*skb, 1)) = 0x80; /* Speech */ - *(skb_put(*skb, 1)) = 0x10; /* Circuit Mode */ - *(skb_put(*skb, 1)) = 0x23; /* A-law */ - } - else - { - /* Bearer Capability - Mandatory*/ - *(skb_put(*skb, 1)) = 2; /* BC0.Length */ - *(skb_put(*skb, 1)) = 0x88; /* Digital Information */ - *(skb_put(*skb, 1)) = 0x90; /* BC0.Octect4 */ - } - - /* Bearer Capability - Optional*/ - *(skb_put(*skb, 1)) = 0; /* BC1.Length = 0 */ - - *(skb_put(*skb, 1)) = 1; /* ChannelID.Length = 1 */ - *(skb_put(*skb, 1)) = 0x83; /* Basic Interface - Any Channel */ - - *(skb_put(*skb, 1)) = 0; /* Keypad.Length = 0 */ - - - *(skb_put(*skb, 1)) = 0; /* CallingPN.Length = 0 */ - *(skb_put(*skb, 1)) = 0; /* CallingPSA.Length = 0 */ - - /* Called Party Number */ - *(skb_put(*skb, 1)) = strlen(calledPN) + 1; - *(skb_put(*skb, 1)) = 0x81; - memcpy(skb_put(*skb, strlen(calledPN)), calledPN, strlen(calledPN)); - - /* '#' */ - - *(skb_put(*skb, 1)) = 0; /* CalledPSA.Length = 0 */ - - /* LLC.Length = 0; */ - /* HLC0.Length = 0; */ - /* HLC1.Length = 0; */ - /* UTUS.Length = 0; */ - memset(skb_put(*skb, 4), 0, 4); - - return len; -} - -int capi_conn_resp(struct pcbit_chan* chan, struct sk_buff **skb) -{ - - if ((*skb = dev_alloc_skb(5)) == NULL) { - - printk(KERN_WARNING "capi_conn_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2) ) = chan->callref; - *(skb_put(*skb, 1)) = 0x01; /* ACCEPT_CALL */ - *(skb_put(*skb, 1)) = 0; - *(skb_put(*skb, 1)) = 0; - - return 5; -} - -int capi_conn_active_req(struct pcbit_chan* chan, struct sk_buff **skb) -{ - /* - * 8 bytes - */ - - if ((*skb = dev_alloc_skb(8)) == NULL) { - - printk(KERN_WARNING "capi_conn_active_req: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2) ) = chan->callref; - -#ifdef DEBUG - printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref); -#endif - - *(skb_put(*skb, 1)) = 0; /* BC.Length = 0; */ - *(skb_put(*skb, 1)) = 0; /* ConnectedPN.Length = 0 */ - *(skb_put(*skb, 1)) = 0; /* PSA.Length */ - *(skb_put(*skb, 1)) = 0; /* LLC.Length = 0; */ - *(skb_put(*skb, 1)) = 0; /* HLC.Length = 0; */ - *(skb_put(*skb, 1)) = 0; /* UTUS.Length = 0; */ - - return 8; -} - -int capi_conn_active_resp(struct pcbit_chan* chan, struct sk_buff **skb) -{ - /* - * 2 bytes - */ - - if ((*skb = dev_alloc_skb(2)) == NULL) { - - printk(KERN_WARNING "capi_conn_active_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2) ) = chan->callref; - - return 2; -} - - -int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb, - int outgoing) -{ - - /* - * 18 bytes - */ - - if ((*skb = dev_alloc_skb(18)) == NULL) { - - printk(KERN_WARNING "capi_select_proto_req: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2) ) = chan->callref; - - /* Layer2 protocol */ - - switch (chan->proto) { - case ISDN_PROTO_L2_X75I: - *(skb_put(*skb, 1)) = 0x05; /* LAPB */ - break; - case ISDN_PROTO_L2_HDLC: - *(skb_put(*skb, 1)) = 0x02; - break; - case ISDN_PROTO_L2_TRANS: - /* - * Voice (a-law) - */ - *(skb_put(*skb, 1)) = 0x06; - break; - default: -#ifdef DEBUG - printk(KERN_DEBUG "Transparent\n"); -#endif - *(skb_put(*skb, 1)) = 0x03; - break; - } - - *(skb_put(*skb, 1)) = (outgoing ? 0x02 : 0x42); /* Don't ask */ - *(skb_put(*skb, 1)) = 0x00; - - *((ushort *) skb_put(*skb, 2)) = MRU; - - - *(skb_put(*skb, 1)) = 0x08; /* Modulo */ - *(skb_put(*skb, 1)) = 0x07; /* Max Window */ - - *(skb_put(*skb, 1)) = 0x01; /* No Layer3 Protocol */ - - /* - * 2 - layer3 MTU [10] - * - Modulo [12] - * - Window - * - layer1 proto [14] - * - bitrate - * - sub-channel [16] - * - layer1dataformat [17] - */ - - memset(skb_put(*skb, 8), 0, 8); - - return 18; -} - - -int capi_activate_transp_req(struct pcbit_chan *chan, struct sk_buff **skb) -{ - - if ((*skb = dev_alloc_skb(7)) == NULL) { - - printk(KERN_WARNING "capi_activate_transp_req: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2) ) = chan->callref; - - - *(skb_put(*skb, 1)) = chan->layer2link; /* Layer2 id */ - *(skb_put(*skb, 1)) = 0x00; /* Transmit by default */ - - *((ushort *) skb_put(*skb, 2)) = MRU; - - *(skb_put(*skb, 1)) = 0x01; /* Enables reception*/ - - return 7; -} - -int capi_tdata_req(struct pcbit_chan* chan, struct sk_buff *skb) -{ - ushort data_len; - - - /* - * callref - 2 - * layer2link - 1 - * wBlockLength - 2 - * data - 4 - * sernum - 1 - */ - - data_len = skb->len; - - skb_push(skb, 10); - - *((u16 *) (skb->data)) = chan->callref; - skb->data[2] = chan->layer2link; - *((u16 *) (skb->data + 3)) = data_len; - - chan->s_refnum = (chan->s_refnum + 1) % 8; - *((u32 *) (skb->data + 5)) = chan->s_refnum; - - skb->data[9] = 0; /* HDLC frame number */ - - return 10; -} - -int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff ** skb) - -{ - if ((*skb = dev_alloc_skb(4)) == NULL) { - - printk(KERN_WARNING "capi_tdata_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2) ) = chan->callref; - - *(skb_put(*skb, 1)) = chan->layer2link; - *(skb_put(*skb, 1)) = chan->r_refnum; - - return (*skb)->len; -} - -int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause) -{ - - if ((*skb = dev_alloc_skb(6)) == NULL) { - - printk(KERN_WARNING "capi_disc_req: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2) ) = callref; - - *(skb_put(*skb, 1)) = 2; /* Cause.Length = 2; */ - *(skb_put(*skb, 1)) = 0x80; - *(skb_put(*skb, 1)) = 0x80 | cause; - - /* - * Change it: we should send 'Sic transit gloria Mundi' here ;-) - */ - - *(skb_put(*skb, 1)) = 0; /* UTUS.Length = 0; */ - - return 6; -} - -int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb) -{ - if ((*skb = dev_alloc_skb(2)) == NULL) { - - printk(KERN_WARNING "capi_disc_resp: alloc_skb failed\n"); - return -1; - } - - *((ushort*) skb_put(*skb, 2)) = chan->callref; - - return 2; -} - - -/* - * Decoding of CAPI messages - * - */ - -int capi_decode_conn_ind(struct pcbit_chan * chan, - struct sk_buff *skb, - struct callb_data *info) -{ - int CIlen, len; - - /* Call Reference [CAPI] */ - chan->callref = *((ushort*) skb->data); - skb_pull(skb, 2); - -#ifdef DEBUG - printk(KERN_DEBUG "Call Reference: %04x\n", chan->callref); -#endif - - /* Channel Identification */ - - /* Expect - Len = 1 - Octect 3 = 0100 10CC - [ 7 Basic, 4 , 2-1 chan ] - */ - - CIlen = skb->data[0]; -#ifdef DEBUG - if (CIlen == 1) { - - if ( ((skb->data[1]) & 0xFC) == 0x48 ) - printk(KERN_DEBUG "decode_conn_ind: chan ok\n"); - printk(KERN_DEBUG "phyChan = %d\n", skb->data[1] & 0x03); - } - else - printk(KERN_DEBUG "conn_ind: CIlen = %d\n", CIlen); -#endif - skb_pull(skb, CIlen + 1); - - /* Calling Party Number */ - /* An "additional service" as far as Portugal Telecom is concerned */ - - len = skb->data[0]; - - if (len > 0) { - int count = 1; - -#ifdef DEBUG - printk(KERN_DEBUG "CPN: Octect 3 %02x\n", skb->data[1]); -#endif - if ((skb->data[1] & 0x80) == 0) - count = 2; - - if (!(info->data.setup.CallingPN = kmalloc(len - count + 1, GFP_ATOMIC))) - return -1; - - memcpy(info->data.setup.CallingPN, skb->data + count + 1, - len - count); - info->data.setup.CallingPN[len - count] = 0; - - } - else { - info->data.setup.CallingPN = NULL; - printk(KERN_DEBUG "NULL CallingPN\n"); - } - - skb_pull(skb, len + 1); - - /* Calling Party Subaddress */ - skb_pull(skb, skb->data[0] + 1); - - /* Called Party Number */ - - len = skb->data[0]; - - if (len > 0) { - int count = 1; - - if ((skb->data[1] & 0x80) == 0) - count = 2; - - if (!(info->data.setup.CalledPN = kmalloc(len - count + 1, GFP_ATOMIC))) - return -1; - - memcpy(info->data.setup.CalledPN, skb->data + count + 1, - len - count); - info->data.setup.CalledPN[len - count] = 0; - - } - else { - info->data.setup.CalledPN = NULL; - printk(KERN_DEBUG "NULL CalledPN\n"); - } - - skb_pull(skb, len + 1); - - /* Called Party Subaddress */ - skb_pull(skb, skb->data[0] + 1); - - /* LLC */ - skb_pull(skb, skb->data[0] + 1); - - /* HLC */ - skb_pull(skb, skb->data[0] + 1); - - /* U2U */ - skb_pull(skb, skb->data[0] + 1); - - return 0; -} - -/* - * returns errcode - */ - -int capi_decode_conn_conf(struct pcbit_chan * chan, struct sk_buff *skb, - int *complete) -{ - int errcode; - - chan->callref = *((ushort *) skb->data); /* Update CallReference */ - skb_pull(skb, 2); - - errcode = *((ushort *) skb->data); /* read errcode */ - skb_pull(skb, 2); - - *complete = *(skb->data); - skb_pull(skb, 1); - - /* FIX ME */ - /* This is actually a firmware bug */ - if (!*complete) - { - printk(KERN_DEBUG "complete=%02x\n", *complete); - *complete = 1; - } - - - /* Optional Bearer Capability */ - skb_pull(skb, *(skb->data) + 1); - - /* Channel Identification */ - skb_pull(skb, *(skb->data) + 1); - - /* High Layer Compatibility follows */ - skb_pull(skb, *(skb->data) + 1); - - return errcode; -} - -int capi_decode_conn_actv_ind(struct pcbit_chan * chan, struct sk_buff *skb) -{ - ushort len; -#ifdef DEBUG - char str[32]; -#endif - - /* Yet Another Bearer Capability */ - skb_pull(skb, *(skb->data) + 1); - - - /* Connected Party Number */ - len=*(skb->data); - -#ifdef DEBUG - if (len > 1 && len < 31) { - memcpy(str, skb->data + 2, len - 1); - str[len] = 0; - printk(KERN_DEBUG "Connected Party Number: %s\n", str); - } - else - printk(KERN_DEBUG "actv_ind CPN len = %d\n", len); -#endif - - skb_pull(skb, len + 1); - - /* Connected Subaddress */ - skb_pull(skb, *(skb->data) + 1); - - /* Low Layer Capability */ - skb_pull(skb, *(skb->data) + 1); - - /* High Layer Capability */ - skb_pull(skb, *(skb->data) + 1); - - return 0; -} - -int capi_decode_conn_actv_conf(struct pcbit_chan * chan, struct sk_buff *skb) -{ - ushort errcode; - - errcode = *((ushort*) skb->data); - skb_pull(skb, 2); - - /* Channel Identification - skb_pull(skb, skb->data[0] + 1); - */ - return errcode; -} - - -int capi_decode_sel_proto_conf(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort errcode; - - chan->layer2link = *(skb->data); - skb_pull(skb, 1); - - errcode = *((ushort*) skb->data); - skb_pull(skb, 2); - - return errcode; -} - -int capi_decode_actv_trans_conf(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort errcode; - - if (chan->layer2link != *(skb->data) ) - printk("capi_decode_actv_trans_conf: layer2link doesn't match\n"); - - skb_pull(skb, 1); - - errcode = *((ushort*) skb->data); - skb_pull(skb, 2); - - return errcode; -} - -int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort len; -#ifdef DEBUG - int i; -#endif - /* Cause */ - - len = *(skb->data); - skb_pull(skb, 1); - -#ifdef DEBUG - - for (i=0; idata + i)); -#endif - - skb_pull(skb, len); - - return 0; -} - -int capi_decode_disc_conf(struct pcbit_chan *chan, struct sk_buff *skb) -{ - ushort errcode; - - errcode = *((ushort*) skb->data); - skb_pull(skb, 2); - - return errcode; -} - -#ifdef DEBUG -int capi_decode_debug_188(u_char *hdr, ushort hdrlen) -{ - char str[64]; - int len; - - len = hdr[0]; - - if (len < 64 && len == hdrlen - 1) { - memcpy(str, hdr + 1, hdrlen - 1); - str[hdrlen - 1] = 0; - printk("%s\n", str); - } - else - printk("debug message incorrect\n"); - - return 0; -} -#endif - - - - - diff --git a/drivers/isdn/pcbit/capi.h b/drivers/isdn/pcbit/capi.h deleted file mode 100644 index 10bb6bf9..00000000 --- a/drivers/isdn/pcbit/capi.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * CAPI encode/decode prototypes and defines - */ - -#ifndef CAPI_H -#define CAPI_H - - -#define REQ_CAUSE 0x01 -#define REQ_DISPLAY 0x04 -#define REQ_USER_TO_USER 0x08 - -#define AppInfoMask REQ_CAUSE|REQ_DISPLAY|REQ_USER_TO_USER - -/* Connection Setup */ -extern int capi_conn_req(const char * calledPN, struct sk_buff **buf, - int proto); -extern int capi_decode_conn_conf(struct pcbit_chan * chan, struct sk_buff *skb, - int *complete); - -extern int capi_decode_conn_ind(struct pcbit_chan * chan, struct sk_buff *skb, - struct callb_data *info); -extern int capi_conn_resp(struct pcbit_chan* chan, struct sk_buff **skb); - -extern int capi_conn_active_req(struct pcbit_chan* chan, struct sk_buff **skb); -extern int capi_decode_conn_actv_conf(struct pcbit_chan * chan, - struct sk_buff *skb); - -extern int capi_decode_conn_actv_ind(struct pcbit_chan * chan, - struct sk_buff *skb); -extern int capi_conn_active_resp(struct pcbit_chan* chan, - struct sk_buff **skb); - -/* Data */ -extern int capi_select_proto_req(struct pcbit_chan *chan, struct sk_buff **skb, - int outgoing); -extern int capi_decode_sel_proto_conf(struct pcbit_chan *chan, - struct sk_buff *skb); - -extern int capi_activate_transp_req(struct pcbit_chan *chan, - struct sk_buff **skb); -extern int capi_decode_actv_trans_conf(struct pcbit_chan *chan, - struct sk_buff *skb); - -extern int capi_tdata_req(struct pcbit_chan* chan, struct sk_buff *skb); -extern int capi_tdata_resp(struct pcbit_chan *chan, struct sk_buff ** skb); - -/* Connection Termination */ -extern int capi_disc_req(ushort callref, struct sk_buff **skb, u_char cause); -extern int capi_decode_disc_conf(struct pcbit_chan *chan, struct sk_buff *skb); - -extern int capi_decode_disc_ind(struct pcbit_chan *chan, struct sk_buff *skb); -extern int capi_disc_resp(struct pcbit_chan *chan, struct sk_buff **skb); - -#ifdef DEBUG -extern int capi_decode_debug_188(u_char *hdr, ushort hdrlen); -#endif - -extern __inline__ -struct pcbit_chan * -capi_channel(struct pcbit_dev *dev, struct sk_buff *skb) -{ - ushort callref; - - callref = *((ushort*) skb->data); - skb_pull(skb, 2); - - if (dev->b1->callref == callref) - return dev->b1; - else if (dev->b2->callref == callref) - return dev->b2; - - return NULL; -} - -#endif - - - - - - diff --git a/drivers/isdn/pcbit/drv.c b/drivers/isdn/pcbit/drv.c deleted file mode 100644 index 8975a7e2..00000000 --- a/drivers/isdn/pcbit/drv.c +++ /dev/null @@ -1,1174 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * PCBIT-D interface with isdn4linux - */ - -/* - * Fixes: - * - * Nuno Grilo - * fixed msn_list NULL pointer dereference. - * - */ - -#define __NO_VERSION__ - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#ifdef COMPAT_HAS_ISA_IOREMAP -#include -#endif - -#include "pcbit.h" -#include "edss1.h" -#include "layer2.h" -#include "capi.h" - - -extern ushort last_ref_num; - -static int pcbit_ioctl(isdn_ctrl* ctl); - -static char* pcbit_devname[MAX_PCBIT_CARDS] = { - "pcbit0", - "pcbit1", - "pcbit2", - "pcbit3" -}; - -/* - * prototypes - */ - -int pcbit_command(isdn_ctrl* ctl); -int pcbit_stat(u_char* buf, int len, int user, int, int); -int pcbit_xmit(int driver, int chan, int ack, struct sk_buff *skb); -int pcbit_writecmd(const u_char*, int, int, int, int); - -static int set_protocol_running(struct pcbit_dev * dev); - -static void pcbit_clear_msn(struct pcbit_dev *dev); -static void pcbit_set_msn(struct pcbit_dev *dev, char *list); -static int pcbit_check_msn(struct pcbit_dev *dev, char *msn); - - -extern void pcbit_deliver(void * data); - -int pcbit_init_dev(int board, int mem_base, int irq) -{ - struct pcbit_dev *dev; - isdn_if *dev_if; - - if ((dev=kmalloc(sizeof(struct pcbit_dev), GFP_KERNEL)) == NULL) - { - printk("pcbit_init: couldn't malloc pcbit_dev struct\n"); - return -ENOMEM; - } - - dev_pcbit[board] = dev; - memset(dev, 0, sizeof(struct pcbit_dev)); -#ifdef COMPAT_HAS_NEW_WAITQ - init_waitqueue_head(&dev->set_running_wq); -#endif - - 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", - dev->ph_mem, dev->ph_mem + 4096); - kfree(dev); - dev_pcbit[board] = NULL; - return -EACCES; - } else { - 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 - { - printk("memory address invalid"); - kfree(dev); - dev_pcbit[board] = NULL; - return -EACCES; - } - - dev->b1 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); - if (!dev->b1) { - printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); - kfree(dev); -#ifdef COMPAT_HAS_ISA_IOREMAP - iounmap((unsigned char*)dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); -#endif - return -ENOMEM; - } - - dev->b2 = kmalloc(sizeof(struct pcbit_chan), GFP_KERNEL); - if (!dev->b2) { - printk("pcbit_init: couldn't malloc pcbit_chan struct\n"); - kfree(dev->b1); - kfree(dev); -#ifdef COMPAT_HAS_ISA_IOREMAP - iounmap((unsigned char*)dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); -#endif - return -ENOMEM; - } - - memset(dev->b1, 0, sizeof(struct pcbit_chan)); - memset(dev->b2, 0, sizeof(struct pcbit_chan)); - dev->b2->id = 1; - - - dev->qdelivery.next = NULL; - dev->qdelivery.sync = 0; - dev->qdelivery.routine = pcbit_deliver; - dev->qdelivery.data = dev; - - /* - * interrupts - */ - - if (request_irq(irq, &pcbit_irq_handler, 0, pcbit_devname[board], dev) != 0) - { - kfree(dev->b1); - kfree(dev->b2); - kfree(dev); -#ifdef COMPAT_HAS_ISA_IOREMAP - iounmap((unsigned char*)dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); -#endif - dev_pcbit[board] = NULL; - return -EIO; - } - - dev->irq = irq; - - /* next frame to be received */ - dev->rcv_seq = 0; - dev->send_seq = 0; - dev->unack_seq = 0; - - dev->hl_hdrlen = 10; - - dev_if = kmalloc(sizeof(isdn_if), GFP_KERNEL); - - if (!dev_if) { - free_irq(irq, dev); - kfree(dev->b1); - kfree(dev->b2); - kfree(dev); -#ifdef COMPAT_HAS_ISA_IOREMAP - iounmap((unsigned char*)dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); -#endif - dev_pcbit[board] = NULL; - return -EIO; - } - - dev->dev_if = dev_if; - - dev_if->channels = 2; - - - dev_if->features = (ISDN_FEATURE_P_EURO | ISDN_FEATURE_L3_TRANS | - ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L2_TRANS ); - - dev_if->writebuf_skb = pcbit_xmit; - dev_if->hl_hdrlen = 10; - - dev_if->maxbufsize = MAXBUFSIZE; - dev_if->command = pcbit_command; - - dev_if->writecmd = pcbit_writecmd; - dev_if->readstat = pcbit_stat; - - - strcpy(dev_if->id, pcbit_devname[board]); - - if (!register_isdn(dev_if)) { - free_irq(irq, dev); - kfree(dev->b1); - kfree(dev->b2); - kfree(dev); -#ifdef COMPAT_HAS_ISA_IOREMAP - iounmap((unsigned char*)dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); -#endif - dev_pcbit[board] = NULL; - return -EIO; - } - - dev->id = dev_if->channels; - - - dev->l2_state = L2_DOWN; - dev->free = 511; - - /* - * set_protocol_running(dev); - */ - - return 0; -} - -#ifdef MODULE -void pcbit_terminate(int board) -{ - struct pcbit_dev * dev; - - dev = dev_pcbit[board]; - - if (dev) { - /* unregister_isdn(dev->dev_if); */ - free_irq(dev->irq, dev); - pcbit_clear_msn(dev); - kfree(dev->dev_if); - if (dev->b1->fsm_timer.function) - del_timer(&dev->b1->fsm_timer); - if (dev->b2->fsm_timer.function) - del_timer(&dev->b2->fsm_timer); - kfree(dev->b1); - kfree(dev->b2); - kfree(dev); -#ifdef COMPAT_HAS_ISA_IOREMAP - iounmap((unsigned char*)dev->sh_mem); - release_mem_region(dev->ph_mem, 4096); -#endif - } -} -#endif - -int pcbit_command(isdn_ctrl* ctl) -{ - struct pcbit_dev *dev; - struct pcbit_chan *chan; - struct callb_data info; - - dev = finddev(ctl->driver); - - if (!dev) - { - printk("pcbit_command: unknown device\n"); - return -1; - } - - chan = (ctl->arg & 0x0F) ? dev->b2 : dev->b1; - - - switch(ctl->command) { - case ISDN_CMD_IOCTL: - return pcbit_ioctl(ctl); - break; - case ISDN_CMD_DIAL: - info.type = EV_USR_SETUP_REQ; - info.data.setup.CalledPN = (char *) &ctl->parm.setup.phone; - pcbit_fsm_event(dev, chan, EV_USR_SETUP_REQ, &info); - break; - case ISDN_CMD_ACCEPTD: - pcbit_fsm_event(dev, chan, EV_USR_SETUP_RESP, NULL); - break; - case ISDN_CMD_ACCEPTB: - printk("ISDN_CMD_ACCEPTB - not really needed\n"); - break; - case ISDN_CMD_HANGUP: - pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); - break; - case ISDN_CMD_SETL2: - chan->proto = (ctl->arg >> 8); - break; - case ISDN_CMD_GETL2: - return chan->proto; - break; - case ISDN_CMD_LOCK: - MOD_INC_USE_COUNT; - break; - case ISDN_CMD_UNLOCK: - MOD_DEC_USE_COUNT; - break; - case ISDN_CMD_CLREAZ: - pcbit_clear_msn(dev); - break; - case ISDN_CMD_SETEAZ: - pcbit_set_msn(dev, ctl->parm.num); - break; - case ISDN_CMD_SETL3: - if ((ctl->arg >> 8) != ISDN_PROTO_L3_TRANS) - printk(KERN_DEBUG "L3 protocol unknown\n"); - break; - case ISDN_CMD_GETL3: - return ISDN_PROTO_L3_TRANS; - break; - case ISDN_CMD_GETEAZ: - case ISDN_CMD_SETSIL: - case ISDN_CMD_GETSIL: - printk(KERN_DEBUG "pcbit_command: code %d not implemented yet\n", ctl->command); - break; - default: - printk(KERN_DEBUG "pcbit_command: unknown command\n"); - break; - }; - - return 0; -} - -/* - * Another Hack :-( - * on some conditions the board stops sending TDATA_CONFs - * let's see if we can turn around the problem - */ - -#ifdef BLOCK_TIMER -static void pcbit_block_timer(unsigned long data) -{ - struct pcbit_chan *chan; - struct pcbit_dev * dev; - isdn_ctrl ictl; - - chan = (struct pcbit_chan *) data; - - dev = chan2dev(chan); - - if (dev == NULL) { - printk(KERN_DEBUG "pcbit: chan2dev failed\n"); - return; - } - - del_timer(&chan->block_timer); - chan->block_timer.function = NULL; - -#ifdef DEBUG - printk(KERN_DEBUG "pcbit_block_timer\n"); -#endif - chan->queued = 0; - ictl.driver = dev->id; - ictl.command = ISDN_STAT_BSENT; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); -} -#endif - -int pcbit_xmit(int driver, int chnum, int ack, struct sk_buff *skb) -{ - ushort hdrlen; - int refnum, len; - struct pcbit_chan * chan; - struct pcbit_dev *dev; - - dev = finddev(driver); - if (dev == NULL) - { - printk("finddev returned NULL"); - return -1; - } - - chan = chnum ? dev->b2 : dev->b1; - - - if (chan->fsm_state != ST_ACTIVE) - return -1; - - if (chan->queued >= MAX_QUEUED ) - { -#ifdef DEBUG_QUEUE - printk(KERN_DEBUG - "pcbit: %d packets already in queue - write fails\n", - chan->queued); -#endif - /* - * packet stays on the head of the device queue - * since dev_start_xmit will fail - * see net/core/dev.c - */ -#ifdef BLOCK_TIMER - if (chan->block_timer.function == NULL) { - init_timer(&chan->block_timer); - chan->block_timer.function = &pcbit_block_timer; - chan->block_timer.data = (long) chan; - chan->block_timer.expires = jiffies + 1 * HZ; - add_timer(&chan->block_timer); - } -#endif - return 0; - } - - - chan->queued++; - - len = skb->len; - - hdrlen = capi_tdata_req(chan, skb); - - refnum = last_ref_num++ & 0x7fffU; - chan->s_refnum = refnum; - - pcbit_l2_write(dev, MSG_TDATA_REQ, refnum, skb, hdrlen); - - return len; -} - - -int pcbit_writecmd(const u_char* buf, int len, int user, int driver, int channel) -{ - struct pcbit_dev * dev; - int i, j; - const u_char * loadbuf; - u_char * ptr = NULL; - - int errstat; - - dev = finddev(driver); - - if (!dev) - { - printk("pcbit_writecmd: couldn't find device"); - return -ENODEV; - } - - switch(dev->l2_state) { - case L2_LWMODE: - /* check (size <= rdp_size); write buf into board */ - if (len > BANK4 + 1) - { - printk("pcbit_writecmd: invalid length %d\n", len); - return -EFAULT; - } - - if (user) - { - u_char cbuf[1024]; - - copy_from_user(cbuf, buf, len); - for (i=0; ish_mem + i); - } - else - memcpy_toio(dev->sh_mem, buf, len); - return len; - break; - case L2_FWMODE: - /* this is the hard part */ - /* dumb board */ - if (len < 0) - return -EINVAL; - - if (user) { - /* get it into kernel space */ - if ((ptr = kmalloc(len, GFP_KERNEL))==NULL) - return -ENOMEM; - copy_from_user(ptr, buf, len); - loadbuf = ptr; - } - else - loadbuf = buf; - - errstat = 0; - - for (i=0; i < len; i++) - { - for(j=0; j < LOAD_RETRY; j++) - if (!(readb(dev->sh_mem + dev->loadptr))) - break; - - if (j == LOAD_RETRY) - { - errstat = -ETIME; - printk("TIMEOUT i=%d\n", i); - break; - } - writeb(loadbuf[i], dev->sh_mem + dev->loadptr + 1); - writeb(0x01, dev->sh_mem + dev->loadptr); - - dev->loadptr += 2; - if (dev->loadptr > LOAD_ZONE_END) - dev->loadptr = LOAD_ZONE_START; - } - - if (user) - kfree(ptr); - - return errstat ? errstat : len; - - break; - default: - return -EBUSY; - } - return 0; -} - -/* - * demultiplexing of messages - * - */ - -void pcbit_l3_receive(struct pcbit_dev * dev, ulong msg, - struct sk_buff * skb, - ushort hdr_len, ushort refnum) -{ - struct pcbit_chan *chan; - struct sk_buff *skb2; - unsigned short len; - struct callb_data cbdata; - int complete, err; - isdn_ctrl ictl; -#ifdef DEBUG - struct msg_fmt * fmsg; -#endif - - switch(msg) { - - case MSG_TDATA_IND: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - chan->r_refnum = skb->data[7]; - skb_pull(skb, 8); - - dev->dev_if->rcvcallb_skb(dev->id, chan->id, skb); - - if (capi_tdata_resp(chan, &skb2) > 0) - pcbit_l2_write(dev, MSG_TDATA_RESP, refnum, - skb2, skb2->len); - return; - break; - case MSG_TDATA_CONF: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - -#ifdef DEBUG - if ( (*((ushort *) (skb->data + 2) )) != 0) { - printk(KERN_DEBUG "TDATA_CONF error\n"); - } -#endif -#ifdef BLOCK_TIMER - if (chan->queued == MAX_QUEUED) { - del_timer(&chan->block_timer); - chan->block_timer.function = NULL; - } - -#endif - chan->queued--; - - ictl.driver = dev->id; - ictl.command = ISDN_STAT_BSENT; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); - break; - - case MSG_CONN_IND: - /* - * channel: 1st not used will do - * if both are used we're in trouble - */ - - if (!dev->b1->fsm_state) - chan = dev->b1; - else if (!dev->b2->fsm_state) - chan = dev->b2; - else { - printk(KERN_INFO - "Incoming connection: no channels available"); - - if ((len = capi_disc_req(*(ushort*)(skb->data), &skb2, CAUSE_NOCHAN)) > 0) - pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb2, len); - break; - } - - cbdata.data.setup.CalledPN = NULL; - cbdata.data.setup.CallingPN = NULL; - - capi_decode_conn_ind(chan, skb, &cbdata); - cbdata.type = EV_NET_SETUP; - - pcbit_fsm_event(dev, chan, EV_NET_SETUP, NULL); - - if (pcbit_check_msn(dev, cbdata.data.setup.CallingPN)) - pcbit_fsm_event(dev, chan, EV_USR_PROCED_REQ, &cbdata); - else - pcbit_fsm_event(dev, chan, EV_USR_RELEASE_REQ, NULL); - - if (cbdata.data.setup.CalledPN) - kfree(cbdata.data.setup.CalledPN); - if (cbdata.data.setup.CallingPN) - kfree(cbdata.data.setup.CallingPN); - break; - - case MSG_CONN_CONF: - /* - * We should be able to find the channel by the message - * reference number. The current version of the firmware - * doesn't sent the ref number correctly. - */ -#ifdef DEBUG - printk(KERN_DEBUG "refnum=%04x b1=%04x b2=%04x\n", refnum, - 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) - chan = dev->b1; - else { - if (dev->b2->s_refnum == ST_CALL_INIT) - chan = dev->b2; - else { - chan = NULL; - printk(KERN_WARNING "Connection Confirm - no channel in Call Init state\n"); - 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); - } - else - if (complete) - pcbit_fsm_event(dev, chan, EV_NET_CALL_PROC, NULL); - else - pcbit_fsm_event(dev, chan, EV_NET_SETUP_ACK, NULL); - break; - case MSG_CONN_ACTV_IND: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (capi_decode_conn_actv_ind(chan, skb)) { - printk("error in capi_decode_conn_actv_ind\n"); - /* pcbit_fsm_event(dev, chan, EV_ERROR, NULL); */ - break; - } - chan->r_refnum = refnum; - pcbit_fsm_event(dev, chan, EV_NET_CONN, NULL); - break; - case MSG_CONN_ACTV_CONF: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (capi_decode_conn_actv_conf(chan, skb) == 0) - pcbit_fsm_event(dev, chan, EV_NET_CONN_ACK, NULL); - - else - printk(KERN_DEBUG "decode_conn_actv_conf failed\n"); - break; - - case MSG_SELP_CONF: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!(err = capi_decode_sel_proto_conf(chan, skb))) - pcbit_fsm_event(dev, chan, EV_NET_SELP_RESP, NULL); - else { - /* Error */ - printk("error %d - capi_decode_sel_proto_conf\n", err); - } - break; - case MSG_ACT_TRANSP_CONF: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!capi_decode_actv_trans_conf(chan, skb)) - pcbit_fsm_event(dev, chan, EV_NET_ACTV_RESP, NULL); - break; - - case MSG_DISC_IND: - - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!capi_decode_disc_ind(chan, skb)) - pcbit_fsm_event(dev, chan, EV_NET_DISC, NULL); - else - printk(KERN_WARNING "capi_decode_disc_ind - error\n"); - break; - case MSG_DISC_CONF: - if (!(chan = capi_channel(dev, skb))) { - printk(KERN_WARNING - "CAPI header: unknown channel id\n"); - break; - } - - if (!capi_decode_disc_ind(chan, skb)) - pcbit_fsm_event(dev, chan, EV_NET_RELEASE, NULL); - else - printk(KERN_WARNING "capi_decode_disc_conf - error\n"); - break; - case MSG_INFO_IND: -#ifdef DEBUG - printk(KERN_DEBUG "received Info Indication - discarded\n"); -#endif - break; -#ifdef DEBUG - case MSG_DEBUG_188: - capi_decode_debug_188(skb->data, skb->len); - break; - - default: - printk(KERN_DEBUG "pcbit_l3_receive: unknown message %08lx\n", - msg); - fmsg = (struct msg_fmt *) &msg; - printk(KERN_DEBUG "cmd=%02x sub=%02x\n", - fmsg->cmd, fmsg->scmd); - break; -#endif - } - - kfree_skb(skb); - -} - -/* - * Single statbuf - * should be a statbuf per device - */ - -static char statbuf[STATBUF_LEN]; -static int stat_st = 0; -static int stat_end = 0; - - -static __inline void -memcpy_to_COND(int flag, char *d, const char *s, int len) { - if (flag) - copy_to_user(d, s, len); - else - memcpy(d, s, len); -} - - -int pcbit_stat(u_char* buf, int len, int user, int driver, int channel) -{ - int stat_count; - stat_count = stat_end - stat_st; - - if (stat_count < 0) - stat_count = STATBUF_LEN - stat_st + stat_end; - - /* FIXME: should we sleep and wait for more cookies ? */ - if (len > stat_count) - len = stat_count; - - if (stat_st < stat_end) - { - memcpy_to_COND(user, buf, statbuf + stat_st, len); - stat_st += len; - } - else - { - if (len > STATBUF_LEN - stat_st) - { - memcpy_to_COND(user, buf, statbuf + stat_st, - STATBUF_LEN - stat_st); - memcpy_to_COND(user, buf, statbuf, - len - (STATBUF_LEN - stat_st)); - - stat_st = len - (STATBUF_LEN - stat_st); - } - else - { - memcpy_to_COND(user, buf, statbuf + stat_st, - len); - - stat_st += len; - - if (stat_st == STATBUF_LEN) - stat_st = 0; - } - } - - if (stat_st == stat_end) - stat_st = stat_end = 0; - - return len; -} - -static void pcbit_logstat(struct pcbit_dev *dev, char *str) -{ - int i; - isdn_ctrl ictl; - - for (i=stat_end; iid; - ictl.arg=strlen(str); - dev->dev_if->statcallb(&ictl); -} - -extern char * isdn_state_table[]; -extern char * strisdnevent(unsigned short); - - -void pcbit_state_change(struct pcbit_dev * dev, struct pcbit_chan * chan, - unsigned short i, unsigned short ev, unsigned short f) -{ - char buf[256]; - - sprintf(buf, "change on device: %d channel:%d\n%s -> %s -> %s\n", - dev->id, chan->id, - isdn_state_table[i], strisdnevent(ev), isdn_state_table[f] - ); - -#ifdef DEBUG - printk("%s", buf); -#endif - - pcbit_logstat(dev, buf); -} - -static void set_running_timeout(unsigned long ptr) -{ - struct pcbit_dev * dev; - -#ifdef DEBUG - printk(KERN_DEBUG "set_running_timeout\n"); -#endif - dev = (struct pcbit_dev *) ptr; - - wake_up_interruptible(&dev->set_running_wq); -} - -static int set_protocol_running(struct pcbit_dev * dev) -{ - isdn_ctrl ctl; - - init_timer(&dev->set_running_timer); - - dev->set_running_timer.function = &set_running_timeout; - dev->set_running_timer.data = (ulong) dev; - dev->set_running_timer.expires = jiffies + SET_RUN_TIMEOUT; - - /* kick it */ - - dev->l2_state = L2_STARTING; - - writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), - dev->sh_mem + BANK4); - - add_timer(&dev->set_running_timer); - - interruptible_sleep_on(&dev->set_running_wq); - - del_timer(&dev->set_running_timer); - - if (dev->l2_state == L2_RUNNING) - { - printk(KERN_DEBUG "pcbit: running\n"); - - dev->unack_seq = dev->send_seq; - - dev->writeptr = dev->sh_mem; - dev->readptr = dev->sh_mem + BANK2; - - /* tell the good news to the upper layer */ - ctl.driver = dev->id; - ctl.command = ISDN_STAT_RUN; - - dev->dev_if->statcallb(&ctl); - } - else - { - printk(KERN_DEBUG "pcbit: initialization failed\n"); - printk(KERN_DEBUG "pcbit: firmware not loaded\n"); - - dev->l2_state = L2_DOWN; - -#ifdef DEBUG - printk(KERN_DEBUG "Bank3 = %02x\n", - readb(dev->sh_mem + BANK3)); -#endif - *(dev->sh_mem + BANK4) = 0x40U; - - /* warn the upper layer */ - ctl.driver = dev->id; - ctl.command = ISDN_STAT_STOP; - - dev->dev_if->statcallb(&ctl); - - return -EL2HLT; /* Level 2 halted */ - } - - return 0; -} - -static int pcbit_ioctl(isdn_ctrl* ctl) -{ - struct pcbit_dev * dev; - struct pcbit_ioctl *cmd; - - dev = finddev(ctl->driver); - - if (!dev) - { - printk(KERN_DEBUG "pcbit_ioctl: unknown device\n"); - return -ENODEV; - } - - cmd = (struct pcbit_ioctl *) ctl->parm.num; - - switch(ctl->arg) { - case PCBIT_IOCTL_GETSTAT: - cmd->info.l2_status = dev->l2_state; - break; - - case PCBIT_IOCTL_STRLOAD: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - - dev->unack_seq = dev->send_seq = dev->rcv_seq = 0; - - dev->writeptr = dev->sh_mem; - dev->readptr = dev->sh_mem + BANK2; - - dev->l2_state = L2_LOADING; - break; - - case PCBIT_IOCTL_LWMODE: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - - dev->l2_state = L2_LWMODE; - break; - - case PCBIT_IOCTL_FWMODE: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - dev->loadptr = LOAD_ZONE_START; - dev->l2_state = L2_FWMODE; - - break; - case PCBIT_IOCTL_ENDLOAD: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - dev->l2_state = L2_DOWN; - break; - - case PCBIT_IOCTL_SETBYTE: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - - /* check addr */ - if (cmd->info.rdp_byte.addr > BANK4) - return -EFAULT; - - writeb(cmd->info.rdp_byte.value, dev->sh_mem + cmd->info.rdp_byte.addr); - break; - case PCBIT_IOCTL_GETBYTE: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - - /* check addr */ - - if (cmd->info.rdp_byte.addr > BANK4) - { - printk("getbyte: invalid addr %04x\n", cmd->info.rdp_byte.addr); - return -EFAULT; - } - - cmd->info.rdp_byte.value = readb(dev->sh_mem + cmd->info.rdp_byte.addr); - break; - case PCBIT_IOCTL_RUNNING: - if (dev->l2_state == L2_RUNNING) - return -EBUSY; - return set_protocol_running(dev); - break; - case PCBIT_IOCTL_WATCH188: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - pcbit_l2_write(dev, MSG_WATCH188, 0x0001, NULL, 0); - break; - case PCBIT_IOCTL_PING188: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - pcbit_l2_write(dev, MSG_PING188_REQ, 0x0001, NULL, 0); - break; - case PCBIT_IOCTL_APION: - if (dev->l2_state != L2_LOADING) - return -EINVAL; - pcbit_l2_write(dev, MSG_API_ON, 0x0001, NULL, 0); - break; - case PCBIT_IOCTL_STOP: - dev->l2_state = L2_DOWN; - writeb(0x40, dev->sh_mem + BANK4); - dev->rcv_seq = 0; - dev->send_seq = 0; - dev->unack_seq = 0; - break; - default: - printk("error: unknown ioctl\n"); - break; - }; - return 0; -} - -/* - * MSN list handling - * - * if null reject all calls - * if first entry has null MSN accept all calls - */ - -static void pcbit_clear_msn(struct pcbit_dev *dev) -{ - struct msn_entry *ptr, *back; - - for (ptr=dev->msn_list; ptr; ) - { - back = ptr->next; - kfree(ptr); - ptr = back; - } - - dev->msn_list = NULL; -} - -static void pcbit_set_msn(struct pcbit_dev *dev, char *list) -{ - struct msn_entry *ptr; - struct msn_entry *back = NULL; - char *cp, *sp; - int len; - - if (strlen(list) == 0) { - ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); - if (!ptr) { - printk(KERN_WARNING "kmalloc failed\n"); - return; - } - - ptr->msn = NULL; - - ptr->next = dev->msn_list; - dev->msn_list = ptr; - - return; - } - - if (dev->msn_list) - for (back=dev->msn_list; back->next; back=back->next); - - sp = list; - - do { - cp=strchr(sp, ','); - if (cp) - len = cp - sp; - else - len = strlen(sp); - - ptr = kmalloc(sizeof(struct msn_entry), GFP_ATOMIC); - - if (!ptr) { - printk(KERN_WARNING "kmalloc failed\n"); - return; - } - ptr->next = NULL; - - ptr->msn = kmalloc(len, GFP_ATOMIC); - if (!ptr->msn) { - printk(KERN_WARNING "kmalloc failed\n"); - return; - } - - memcpy(ptr->msn, sp, len - 1); - ptr->msn[len] = 0; - -#ifdef DEBUG - printk(KERN_DEBUG "msn: %s\n", ptr->msn); -#endif - if (dev->msn_list == NULL) - dev->msn_list = ptr; - else - back->next = ptr; - back = ptr; - sp += len; - } while(cp); -} - -/* - * check if we do signal or reject an incoming call - */ -static int pcbit_check_msn(struct pcbit_dev *dev, char *msn) -{ - struct msn_entry *ptr; - - for (ptr=dev->msn_list; ptr; ptr=ptr->next) { - - if (ptr->msn == NULL) - return 1; - - if (strcmp(ptr->msn, msn) == 0) - return 1; - } - - return 0; -} diff --git a/drivers/isdn/pcbit/edss1.c b/drivers/isdn/pcbit/edss1.c deleted file mode 100644 index 1b76b346..00000000 --- a/drivers/isdn/pcbit/edss1.c +++ /dev/null @@ -1,334 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * DSS.1 Finite State Machine - * base: ITU-T Rec Q.931 - */ - -/* - * TODO: complete the FSM - * move state/event descriptions to a user space logger - */ - -#define __NO_VERSION__ - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include "pcbit.h" -#include "edss1.h" -#include "layer2.h" -#include "callbacks.h" - - -extern void pcbit_state_change(struct pcbit_dev *, struct pcbit_chan *, - unsigned short i, unsigned short ev, - unsigned short f); - -extern struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS]; - -char * isdn_state_table[] = { - "Closed", - "Call initiated", - "Overlap sending", - "Outgoing call proceeding", - "NOT DEFINED", - "Call delivered", - "Call present", - "Call received", - "Connect request", - "Incoming call proceeding", - "Active", - "Disconnect request", - "Disconnect indication", - "NOT DEFINED", - "NOT DEFINED", - "Suspend request", - "NOT DEFINED", - "Resume request", - "NOT DEFINED", - "Release Request", - "NOT DEFINED", - "NOT DEFINED", - "NOT DEFINED", - "NOT DEFINED", - "NOT DEFINED", - "Overlap receiving", - "Select protocol on B-Channel", - "Activate B-channel protocol" -}; - -#ifdef DEBUG_ERRS -static -struct CauseValue { - byte nr; - char *descr; -} cvlist[]={ - {0x01,"Unallocated (unassigned) number"}, - {0x02,"No route to specified transit network"}, - {0x03,"No route to destination"}, - {0x04,"Send special information tone"}, - {0x05,"Misdialled trunk prefix"}, - {0x06,"Channel unacceptable"}, - {0x07,"Channel awarded and being delivered in an established channel"}, - {0x08,"Preemption"}, - {0x09,"Preemption - circuit reserved for reuse"}, - {0x10,"Normal call clearing"}, - {0x11,"User busy"}, - {0x12,"No user responding"}, - {0x13,"No answer from user (user alerted)"}, - {0x14,"Subscriber absent"}, - {0x15,"Call rejected"}, - {0x16,"Number changed"}, - {0x1a,"non-selected user clearing"}, - {0x1b,"Destination out of order"}, - {0x1c,"Invalid number format (address incomplete)"}, - {0x1d,"Facility rejected"}, - {0x1e,"Response to Status enquiry"}, - {0x1f,"Normal, unspecified"}, - {0x22,"No circuit/channel available"}, - {0x26,"Network out of order"}, - {0x27,"Permanent frame mode connection out-of-service"}, - {0x28,"Permanent frame mode connection operational"}, - {0x29,"Temporary failure"}, - {0x2a,"Switching equipment congestion"}, - {0x2b,"Access information discarded"}, - {0x2c,"Requested circuit/channel not available"}, - {0x2e,"Precedence call blocked"}, - {0x2f,"Resource unavailable, unspecified"}, - {0x31,"Quality of service unavailable"}, - {0x32,"Requested facility not subscribed"}, - {0x35,"Outgoing calls barred within CUG"}, - {0x37,"Incoming calls barred within CUG"}, - {0x39,"Bearer capability not authorized"}, - {0x3a,"Bearer capability not presently available"}, - {0x3e,"Inconsistency in designated outgoing access information and subscriber class"}, - {0x3f,"Service or option not available, unspecified"}, - {0x41,"Bearer capability not implemented"}, - {0x42,"Channel type not implemented"}, - {0x43,"Requested facility not implemented"}, - {0x44,"Only restricted digital information bearer capability is available"}, - {0x4f,"Service or option not implemented"}, - {0x51,"Invalid call reference value"}, - {0x52,"Identified channel does not exist"}, - {0x53,"A suspended call exists, but this call identity does not"}, - {0x54,"Call identity in use"}, - {0x55,"No call suspended"}, - {0x56,"Call having the requested call identity has been cleared"}, - {0x57,"User not member of CUG"}, - {0x58,"Incompatible destination"}, - {0x5a,"Non-existent CUG"}, - {0x5b,"Invalid transit network selection"}, - {0x5f,"Invalid message, unspecified"}, - {0x60,"Mandatory information element is missing"}, - {0x61,"Message type non-existent or not implemented"}, - {0x62,"Message not compatible with call state or message type non-existent or not implemented"}, - {0x63,"Information element/parameter non-existent or not implemented"}, - {0x64,"Invalid information element contents"}, - {0x65,"Message not compatible with call state"}, - {0x66,"Recovery on timer expiry"}, - {0x67,"Parameter non-existent or not implemented - passed on"}, - {0x6e,"Message with unrecognized parameter discarded"}, - {0x6f,"Protocol error, unspecified"}, - {0x7f,"Interworking, unspecified"} -}; - -#endif - -static struct isdn_event_desc { - unsigned short ev; - char * desc; -} isdn_event_table [] = { - {EV_USR_SETUP_REQ, "CC->L3: Setup Request"}, - {EV_USR_SETUP_RESP, "CC->L3: Setup Response"}, - {EV_USR_PROCED_REQ, "CC->L3: Proceeding Request"}, - {EV_USR_RELEASE_REQ, "CC->L3: Release Request"}, - - {EV_NET_SETUP, "NET->TE: setup "}, - {EV_NET_CALL_PROC, "NET->TE: call proceeding"}, - {EV_NET_SETUP_ACK, "NET->TE: setup acknowledge (more info needed)"}, - {EV_NET_CONN, "NET->TE: connect"}, - {EV_NET_CONN_ACK, "NET->TE: connect acknowledge"}, - {EV_NET_DISC, "NET->TE: disconnect indication"}, - {EV_NET_RELEASE, "NET->TE: release"}, - {EV_NET_RELEASE_COMP, "NET->TE: release complete"}, - {EV_NET_SELP_RESP, "Board: Select B-channel protocol ack"}, - {EV_NET_ACTV_RESP, "Board: Activate B-channel protocol ack"}, - {EV_TIMER, "Timeout"}, - {0, "NULL"} -}; - -char * strisdnevent(ushort ev) -{ - struct isdn_event_desc * entry; - - for (entry = isdn_event_table; entry->ev; entry++) - if (entry->ev == ev) - break; - - return entry->desc; -} - -/* - * Euro ISDN finite state machine - */ - -static struct fsm_timer_entry fsm_timers[] = { - {ST_CALL_PROC, 10}, - {ST_DISC_REQ, 2}, - {ST_ACTIVE_SELP, 5}, - {ST_ACTIVE_ACTV, 5}, - {ST_INCM_PROC, 10}, - {ST_CONN_REQ, 2}, - {0xff, 0} -}; - -static struct fsm_entry fsm_table[] = { -/* Connect Phase */ - /* Outgoing */ - {ST_NULL, ST_CALL_INIT, EV_USR_SETUP_REQ, cb_out_1}, - - {ST_CALL_INIT, ST_OVER_SEND, EV_NET_SETUP_ACK, cb_notdone}, - {ST_CALL_INIT, ST_CALL_PROC, EV_NET_CALL_PROC, NULL}, - {ST_CALL_INIT, ST_NULL, EV_NET_DISC, cb_out_2}, - - {ST_CALL_PROC, ST_ACTIVE_SELP, EV_NET_CONN, cb_out_2}, - {ST_CALL_PROC, ST_NULL, EV_NET_DISC, cb_disc_1}, - {ST_CALL_PROC, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - /* Incoming */ - {ST_NULL, ST_CALL_PRES, EV_NET_SETUP, NULL}, - - {ST_CALL_PRES, ST_INCM_PROC, EV_USR_PROCED_REQ, cb_in_1}, - {ST_CALL_PRES, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - {ST_INCM_PROC, ST_CONN_REQ, EV_USR_SETUP_RESP, cb_in_2}, - {ST_INCM_PROC, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - {ST_CONN_REQ, ST_ACTIVE_SELP, EV_NET_CONN_ACK, cb_in_3}, - - /* Active */ - {ST_ACTIVE, ST_NULL, EV_NET_DISC, cb_disc_1}, - {ST_ACTIVE, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - {ST_ACTIVE, ST_NULL, EV_NET_RELEASE, cb_disc_3}, - - /* Disconnect */ - - {ST_DISC_REQ, ST_NULL, EV_NET_DISC, cb_disc_1}, - {ST_DISC_REQ, ST_NULL, EV_NET_RELEASE, cb_disc_3}, - - /* protocol selection */ - {ST_ACTIVE_SELP, ST_ACTIVE_ACTV, EV_NET_SELP_RESP, cb_selp_1}, - {ST_ACTIVE_SELP, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - {ST_ACTIVE_ACTV, ST_ACTIVE, EV_NET_ACTV_RESP, cb_open}, - {ST_ACTIVE_ACTV, ST_DISC_REQ, EV_USR_RELEASE_REQ, cb_disc_2}, - - /* Timers */ - {ST_CALL_PROC, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_DISC_REQ, ST_NULL, EV_TIMER, cb_disc_3}, - {ST_ACTIVE_SELP, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_ACTIVE_ACTV, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_INCM_PROC, ST_DISC_REQ, EV_TIMER, cb_disc_2}, - {ST_CONN_REQ, ST_CONN_REQ, EV_TIMER, cb_in_2}, - - {0xff, 0, 0, NULL} -}; - - -static void pcbit_fsm_timer(unsigned long data) -{ - struct pcbit_dev *dev; - struct pcbit_chan *chan; - - chan = (struct pcbit_chan *) data; - - del_timer(&chan->fsm_timer); - chan->fsm_timer.function = NULL; - - dev = chan2dev(chan); - - if (dev == NULL) { - printk(KERN_WARNING "pcbit: timer for unknown device\n"); - return; - } - - pcbit_fsm_event(dev, chan, EV_TIMER, NULL); -} - - -void pcbit_fsm_event(struct pcbit_dev *dev, struct pcbit_chan *chan, - unsigned short event, struct callb_data *data) -{ - struct fsm_entry * action; - struct fsm_timer_entry *tentry; - unsigned long flags; - - save_flags(flags); - cli(); - - - for (action = fsm_table; action->init != 0xff; action++) - if (action->init == chan->fsm_state && action->event == event) - break; - - if (action->init == 0xff) { - - printk(KERN_DEBUG "fsm error: event %x on state %x\n", - event, chan->fsm_state); - restore_flags(flags); - return; - } - - if (chan->fsm_timer.function) { - del_timer(&chan->fsm_timer); - chan->fsm_timer.function = NULL; - } - - chan->fsm_state = action->final; - - pcbit_state_change(dev, chan, action->init, event, action->final); - - for (tentry = fsm_timers; tentry->init != 0xff; tentry++) - if (tentry->init == chan->fsm_state) - break; - - if (tentry->init != 0xff) { - init_timer(&chan->fsm_timer); - chan->fsm_timer.function = &pcbit_fsm_timer; - chan->fsm_timer.data = (ulong) chan; - chan->fsm_timer.expires = jiffies + tentry->timeout * HZ; - add_timer(&chan->fsm_timer); - } - - restore_flags(flags); - - if (action->callb) - action->callb(dev, chan, data); - -} - - - - diff --git a/drivers/isdn/pcbit/edss1.h b/drivers/isdn/pcbit/edss1.h deleted file mode 100644 index 1bf554dd..00000000 --- a/drivers/isdn/pcbit/edss1.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * DSS.1 module definitions - */ - -#ifndef EDSS1_H -#define EDSS1_H - -/* ISDN states */ - -#define ST_NULL 0 -#define ST_CALL_INIT 1 /* Call initiated */ -#define ST_OVER_SEND 2 /* Overlap sending - Requests More Info 4 call */ -#define ST_CALL_PROC 3 /* Call Proceeding */ -#define ST_CALL_DELV 4 -#define ST_CALL_PRES 6 /* Call Present - Received CONN.IND */ -#define ST_CALL_RECV 7 /* Alerting sent */ -#define ST_CONN_REQ 8 /* Answered - waiting 4 CONN.CONF */ -#define ST_INCM_PROC 9 -#define ST_ACTIVE 10 -#define ST_DISC_REQ 11 -#define ST_DISC_IND 12 -#define ST_SUSP_REQ 15 -#define ST_RESM_REQ 17 -#define ST_RELS_REQ 19 -#define ST_OVER_RECV 25 - -#define ST_ACTIVE_SELP 26 /* Select protocol on B-Channel */ -#define ST_ACTIVE_ACTV 27 /* Activate B-channel protocol */ - -#define MAX_STATE ST_ACTIVE_ACTV - -#define EV_NULL 0 -#define EV_USR_SETUP_REQ 1 -#define EV_USR_SETUP_RESP 2 -#define EV_USR_PROCED_REQ 3 -#define EV_USR_RELEASE_REQ 4 -#define EV_USR_REJECT_REQ 4 - -#define EV_NET_SETUP 16 -#define EV_NET_CALL_PROC 17 -#define EV_NET_SETUP_ACK 18 -#define EV_NET_CONN 19 -#define EV_NET_CONN_ACK 20 - -#define EV_NET_SELP_RESP 21 -#define EV_NET_ACTV_RESP 22 - -#define EV_NET_DISC 23 -#define EV_NET_RELEASE 24 -#define EV_NET_RELEASE_COMP 25 - -#define EV_TIMER 26 -#define EV_ERROR 32 - -/* - * Cause values - * only the ones we use - */ - -#define CAUSE_NORMAL 0x10U -#define CAUSE_NOCHAN 0x22U - -struct callb_data { - unsigned short type; - union { - struct ConnInfo { - char *CalledPN; - char *CallingPN; - } setup; - unsigned short cause; - } data; -}; - -struct fsm_entry { - unsigned short init; - unsigned short final; - unsigned short event; - void (*callb)(struct pcbit_dev *, struct pcbit_chan *, struct callb_data*); -}; - -struct fsm_timer_entry { - unsigned short init; - unsigned long timeout; /* in seconds */ -}; - - -extern void pcbit_fsm_event(struct pcbit_dev *, struct pcbit_chan *, - unsigned short event, struct callb_data *); -#endif - - - diff --git a/drivers/isdn/pcbit/layer2.c b/drivers/isdn/pcbit/layer2.c deleted file mode 100644 index bc1b079a..00000000 --- a/drivers/isdn/pcbit/layer2.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * PCBIT-D low-layer interface - */ - -/* - * Based on documentation provided by Inesc: - * - "Interface com bus do PC para o PCBIT e PCBIT-D", Inesc, Jan 93 - */ - -/* - * TODO: better handling of errors - * re-write/remove debug printks - */ - -#define __NO_VERSION__ - - -#ifdef MODULE -#define INCLUDE_INLINE_FUNCS -#endif - - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - - -#include "pcbit.h" -#include "layer2.h" -#include "edss1.h" - -#undef DEBUG_FRAG - - - -/* - * task queue struct - */ - - - -/* - * Layer 3 packet demultiplexer - * drv.c - */ - -extern void pcbit_l3_receive(struct pcbit_dev *dev, ulong msg, - struct sk_buff *skb, - ushort hdr_len, ushort refnum); - -/* - * Prototypes - */ - -void pcbit_deliver(void *data); -static void pcbit_transmit(struct pcbit_dev *dev); - -static void pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack); - -static void pcbit_l2_error(struct pcbit_dev *dev); -static void pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info); -static void pcbit_l2_err_recover(unsigned long data); - -static void pcbit_firmware_bug(struct pcbit_dev *dev); - -static __inline__ void -pcbit_sched_delivery(struct pcbit_dev *dev) -{ - queue_task(&dev->qdelivery, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - - -/* - * Called from layer3 - */ - -int -pcbit_l2_write(struct pcbit_dev *dev, ulong msg, ushort refnum, - struct sk_buff *skb, unsigned short hdr_len) -{ - struct frame_buf *frame, - *ptr; - unsigned long flags; - - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { - dev_kfree_skb(skb); - return -1; - } - if ((frame = (struct frame_buf *) kmalloc(sizeof(struct frame_buf), - GFP_ATOMIC)) == NULL) { - printk(KERN_WARNING "pcbit_2_write: kmalloc failed\n"); - dev_kfree_skb(skb); - return -1; - } - frame->msg = msg; - frame->refnum = refnum; - frame->copied = 0; - frame->hdr_len = hdr_len; - - if (skb) - frame->dt_len = skb->len - hdr_len; - else - frame->dt_len = 0; - - frame->skb = skb; - - frame->next = NULL; - - save_flags(flags); - cli(); - - if (dev->write_queue == NULL) { - dev->write_queue = frame; - restore_flags(flags); - pcbit_transmit(dev); - } else { - for (ptr = dev->write_queue; ptr->next; ptr = ptr->next); - ptr->next = frame; - - restore_flags(flags); - } - return 0; -} - -static __inline__ void -pcbit_tx_update(struct pcbit_dev *dev, ushort len) -{ - u_char info; - - dev->send_seq = (dev->send_seq + 1) % 8; - - dev->fsize[dev->send_seq] = len; - info = 0; - info |= dev->rcv_seq << 3; - info |= dev->send_seq; - - writeb(info, dev->sh_mem + BANK4); - -} - -/* - * called by interrupt service routine or by write_2 - */ - -static void -pcbit_transmit(struct pcbit_dev *dev) -{ - struct frame_buf *frame = NULL; - unsigned char unacked; - int flen; /* fragment frame length including all headers */ - int totlen; /* non-fragmented frame length */ - int free; - int count, - cp_len; - unsigned long flags; - unsigned short tt; - - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) - return; - - unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; - - save_flags(flags); - cli(); - - if (dev->free > 16 && dev->write_queue && unacked < 7) { - - if (!dev->w_busy) - dev->w_busy = 1; - else { - restore_flags(flags); - return; - } - - - frame = dev->write_queue; - free = dev->free; - - restore_flags(flags); - - if (frame->copied == 0) { - - /* Type 0 frame */ - - struct msg_fmt *msg; - - if (frame->skb) - totlen = FRAME_HDR_LEN + PREHDR_LEN + frame->skb->len; - else - totlen = FRAME_HDR_LEN + PREHDR_LEN; - - flen = MIN(totlen, free); - - msg = (struct msg_fmt *) &(frame->msg); - - /* - * Board level 2 header - */ - - pcbit_writew(dev, flen - FRAME_HDR_LEN); - - pcbit_writeb(dev, msg->cpu); - - pcbit_writeb(dev, msg->proc); - - /* TH */ - pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); - - /* TD */ - pcbit_writew(dev, frame->dt_len); - - - /* - * Board level 3 fixed-header - */ - - /* LEN = TH */ - pcbit_writew(dev, frame->hdr_len + PREHDR_LEN); - - /* XX */ - pcbit_writew(dev, 0); - - /* C + S */ - pcbit_writeb(dev, msg->cmd); - pcbit_writeb(dev, msg->scmd); - - /* NUM */ - pcbit_writew(dev, frame->refnum); - - count = FRAME_HDR_LEN + PREHDR_LEN; - } else { - /* Type 1 frame */ - - totlen = 2 + (frame->skb->len - frame->copied); - - flen = MIN(totlen, free); - - /* TT */ - tt = ((ushort) (flen - 2)) | 0x8000U; /* Type 1 */ - pcbit_writew(dev, tt); - - count = 2; - } - - if (frame->skb) { - cp_len = MIN(frame->skb->len - frame->copied, - flen - count); - - memcpy_topcbit(dev, frame->skb->data + frame->copied, - cp_len); - frame->copied += cp_len; - } - /* bookkeeping */ - dev->free -= flen; - pcbit_tx_update(dev, flen); - - save_flags(flags); - cli(); - - - if (frame->skb == NULL || frame->copied == frame->skb->len) { - - dev->write_queue = frame->next; - - if (frame->skb != NULL) { - /* free frame */ - dev_kfree_skb(frame->skb); - } - kfree(frame); - } - dev->w_busy = 0; - restore_flags(flags); - } else { - restore_flags(flags); -#ifdef DEBUG - printk(KERN_DEBUG "unacked %d free %d write_queue %s\n", - unacked, dev->free, dev->write_queue ? "not empty" : - "empty"); -#endif - } -} - - -/* - * deliver a queued frame to the upper layer - */ - -void -pcbit_deliver(void *data) -{ - struct frame_buf *frame; - unsigned long flags; - struct msg_fmt msg; - struct pcbit_dev *dev = (struct pcbit_dev *) data; - - save_flags(flags); - cli(); - - while ((frame = dev->read_queue)) { - dev->read_queue = frame->next; - restore_flags(flags); - - msg.cpu = 0; - msg.proc = 0; - msg.cmd = frame->skb->data[2]; - msg.scmd = frame->skb->data[3]; - - frame->refnum = *((ushort *) frame->skb->data + 4); - frame->msg = *((ulong *) & msg); - - skb_pull(frame->skb, 6); - - pcbit_l3_receive(dev, frame->msg, frame->skb, frame->hdr_len, - frame->refnum); - - kfree(frame); - - save_flags(flags); - cli(); - } - - restore_flags(flags); -} - -/* - * Reads BANK 2 & Reassembles - */ - -static void -pcbit_receive(struct pcbit_dev *dev) -{ - unsigned short tt; - u_char cpu, - proc; - struct frame_buf *frame = NULL; - unsigned long flags; - u_char type1; - - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) - return; - - tt = pcbit_readw(dev); - - if ((tt & 0x7fffU) > 511) { - printk(KERN_INFO "pcbit: invalid frame length -> TT=%04x\n", - tt); - pcbit_l2_error(dev); - return; - } - if (!(tt & 0x8000U)) { /* Type 0 */ - type1 = 0; - - 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); - - if (frame == NULL) { - printk(KERN_WARNING "kmalloc failed\n"); - return; - } - memset(frame, 0, sizeof(struct frame_buf)); - - cpu = pcbit_readb(dev); - proc = pcbit_readb(dev); - - - if (cpu != 0x06 && cpu != 0x02) { - printk(KERN_DEBUG "pcbit: invalid cpu value\n"); - kfree(frame); - pcbit_l2_error(dev); - return; - } - /* - * we discard cpu & proc on receiving - * but we read it to update the pointer - */ - - frame->hdr_len = pcbit_readw(dev); - frame->dt_len = pcbit_readw(dev); - - /* - * 0 sized packet - * I don't know if they are an error or not... - * But they are very frequent - * Not documented - */ - - if (frame->hdr_len == 0) { - kfree(frame); -#ifdef DEBUG - printk(KERN_DEBUG "0 sized frame\n"); -#endif - pcbit_firmware_bug(dev); - return; - } - /* sanity check the length values */ - if (frame->hdr_len > 1024 || frame->dt_len > 2048) { -#ifdef DEBUG - printk(KERN_DEBUG "length problem: "); - printk(KERN_DEBUG "TH=%04x TD=%04x\n", - frame->hdr_len, - frame->dt_len); -#endif - pcbit_l2_error(dev); - kfree(frame); - return; - } - /* minimum frame read */ - - frame->skb = dev_alloc_skb(frame->hdr_len + frame->dt_len + - ((frame->hdr_len + 15) & ~15)); - - if (!frame->skb) { - printk(KERN_DEBUG "pcbit_receive: out of memory\n"); - kfree(frame); - return; - } - /* 16 byte alignment for IP */ - if (frame->dt_len) - skb_reserve(frame->skb, (frame->hdr_len + 15) & ~15); - - } else { - /* Type 1 */ - type1 = 1; - tt &= 0x7fffU; - - 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; - - } - } - - memcpy_frompcbit(dev, skb_put(frame->skb, tt), tt); - - frame->copied += tt; - - if (frame->copied == frame->hdr_len + frame->dt_len) { - - save_flags(flags); - cli(); - - if (type1) { - dev->read_frame = NULL; - } - if (dev->read_queue) { - struct frame_buf *ptr; - for (ptr = dev->read_queue; ptr->next; ptr = ptr->next); - ptr->next = frame; - } else - dev->read_queue = frame; - - restore_flags(flags); - - } else { - save_flags(flags); - cli(); - dev->read_frame = frame; - restore_flags(flags); - } -} - -/* - * The board sends 0 sized frames - * They are TDATA_CONFs that get messed up somehow - * gotta send a fake acknowledgment to the upper layer somehow - */ - -static __inline__ void -pcbit_fake_conf(struct pcbit_dev *dev, struct pcbit_chan *chan) -{ - isdn_ctrl ictl; - - if (chan->queued) { - chan->queued--; - - ictl.driver = dev->id; - ictl.command = ISDN_STAT_BSENT; - ictl.arg = chan->id; - dev->dev_if->statcallb(&ictl); - } -} - -static void -pcbit_firmware_bug(struct pcbit_dev *dev) -{ - struct pcbit_chan *chan; - - chan = dev->b1; - - if (chan->fsm_state == ST_ACTIVE) { - pcbit_fake_conf(dev, chan); - } - chan = dev->b2; - - if (chan->fsm_state == ST_ACTIVE) { - pcbit_fake_conf(dev, chan); - } -} - -void -pcbit_irq_handler(int interrupt, void *devptr, struct pt_regs *regs) -{ - struct pcbit_dev *dev; - u_char info, - ack_seq, - read_seq; - - dev = (struct pcbit_dev *) devptr; - - if (!dev) { - printk(KERN_WARNING "pcbit_irq_handler: wrong device\n"); - return; - } - if (dev->interrupt) { - printk(KERN_DEBUG "pcbit: reentering interrupt hander\n"); - return; - } - dev->interrupt = 1; - - info = readb(dev->sh_mem + BANK3); - - if (dev->l2_state == L2_STARTING || dev->l2_state == L2_ERROR) { - pcbit_l2_active_conf(dev, info); - dev->interrupt = 0; - return; - } - if (info & 0x40U) { /* E bit set */ -#ifdef DEBUG - printk(KERN_DEBUG "pcbit_irq_handler: E bit on\n"); -#endif - pcbit_l2_error(dev); - dev->interrupt = 0; - return; - } - if (dev->l2_state != L2_RUNNING && dev->l2_state != L2_LOADING) { - dev->interrupt = 0; - return; - } - ack_seq = (info >> 3) & 0x07U; - read_seq = (info & 0x07U); - - dev->interrupt = 0; - - if (read_seq != dev->rcv_seq) { - while (read_seq != dev->rcv_seq) { - pcbit_receive(dev); - dev->rcv_seq = (dev->rcv_seq + 1) % 8; - } - pcbit_sched_delivery(dev); - } - if (ack_seq != dev->unack_seq) { - pcbit_recv_ack(dev, ack_seq); - } - info = dev->rcv_seq << 3; - info |= dev->send_seq; - - writeb(info, dev->sh_mem + BANK4); -} - - -static void -pcbit_l2_active_conf(struct pcbit_dev *dev, u_char info) -{ - u_char state; - - state = dev->l2_state; - -#ifdef DEBUG - printk(KERN_DEBUG "layer2_active_confirm\n"); -#endif - - - if (info & 0x80U) { - dev->rcv_seq = info & 0x07U; - dev->l2_state = L2_RUNNING; - } else - dev->l2_state = L2_DOWN; - - if (state == L2_STARTING) - wake_up_interruptible(&dev->set_running_wq); - - if (state == L2_ERROR && dev->l2_state == L2_RUNNING) { - pcbit_transmit(dev); - } -} - -static void -pcbit_l2_err_recover(unsigned long data) -{ - - struct pcbit_dev *dev; - struct frame_buf *frame; - - dev = (struct pcbit_dev *) data; - - del_timer(&dev->error_recover_timer); - if (dev->w_busy || dev->r_busy) { - init_timer(&dev->error_recover_timer); - dev->error_recover_timer.expires = jiffies + ERRTIME; - add_timer(&dev->error_recover_timer); - return; - } - dev->w_busy = dev->r_busy = 1; - - if (dev->read_frame) { - if (dev->read_frame->skb) - kfree_skb(dev->read_frame->skb); - kfree(dev->read_frame); - dev->read_frame = NULL; - } - if (dev->write_queue) { - frame = dev->write_queue; -#ifdef FREE_ON_ERROR - dev->write_queue = dev->write_queue->next; - - if (frame->skb) { - dev_kfree_skb(frame->skb); - } - kfree(frame); -#else - frame->copied = 0; -#endif - } - dev->rcv_seq = dev->send_seq = dev->unack_seq = 0; - dev->free = 511; - dev->l2_state = L2_ERROR; - - /* this is an hack... */ - pcbit_firmware_bug(dev); - - dev->writeptr = dev->sh_mem; - dev->readptr = dev->sh_mem + BANK2; - - writeb((0x80U | ((dev->rcv_seq & 0x07) << 3) | (dev->send_seq & 0x07)), - dev->sh_mem + BANK4); - dev->w_busy = dev->r_busy = 0; - -} - -static void -pcbit_l2_error(struct pcbit_dev *dev) -{ - if (dev->l2_state == L2_RUNNING) { - - printk(KERN_INFO "pcbit: layer 2 error\n"); - -#ifdef DEBUG - log_state(dev); -#endif - - dev->l2_state = L2_DOWN; - - init_timer(&dev->error_recover_timer); - dev->error_recover_timer.function = &pcbit_l2_err_recover; - dev->error_recover_timer.data = (ulong) dev; - dev->error_recover_timer.expires = jiffies + ERRTIME; - add_timer(&dev->error_recover_timer); - } -} - -/* - * Description: - * if board acks frames - * update dev->free - * call pcbit_transmit to write possible queued frames - */ - -static void -pcbit_recv_ack(struct pcbit_dev *dev, unsigned char ack) -{ - int i, - count; - int unacked; - - unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07; - - /* dev->unack_seq < ack <= dev->send_seq; */ - - if (unacked) { - - if (dev->send_seq > dev->unack_seq) { - if (ack <= dev->unack_seq || ack > dev->send_seq) { - printk(KERN_DEBUG - "layer 2 ack unacceptable - dev %d", - dev->id); - - pcbit_l2_error(dev); - } else if (ack > dev->send_seq && ack <= dev->unack_seq) { - printk(KERN_DEBUG - "layer 2 ack unacceptable - dev %d", - dev->id); - pcbit_l2_error(dev); - } - } - /* ack is acceptable */ - - - i = dev->unack_seq; - - do { - dev->unack_seq = i = (i + 1) % 8; - dev->free += dev->fsize[i]; - } while (i != ack); - - count = 0; - while (count < 7 && dev->write_queue) { - u8 lsend_seq = dev->send_seq; - - pcbit_transmit(dev); - - if (dev->send_seq == lsend_seq) - break; - count++; - } - } else - printk(KERN_DEBUG "recv_ack: unacked = 0\n"); -} diff --git a/drivers/isdn/pcbit/layer2.h b/drivers/isdn/pcbit/layer2.h deleted file mode 100644 index 2f56a584..00000000 --- a/drivers/isdn/pcbit/layer2.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * PCBIT-D low-layer interface definitions - */ - -#ifndef LAYER2_H -#define LAYER2_H - -#include - -#define BANK1 0x0000U /* PC -> Board */ -#define BANK2 0x01ffU /* Board -> PC */ -#define BANK3 0x03feU /* Att Board */ -#define BANK4 0x03ffU /* Att PC */ - -#define BANKLEN 0x01FFU - -#define LOAD_ZONE_START 0x03f8U -#define LOAD_ZONE_END 0x03fdU - -#define LOAD_RETRY 18000000 - - - -/* TAM - XX - C - S - NUM */ -#define PREHDR_LEN 8 -/* TT - M - I - TH - TD */ -#define FRAME_HDR_LEN 8 - -#define MSG_CONN_REQ 0x08000100 -#define MSG_CONN_CONF 0x00000101 -#define MSG_CONN_IND 0x00000102 -#define MSG_CONN_RESP 0x08000103 - -#define MSG_CONN_ACTV_REQ 0x08000300 -#define MSG_CONN_ACTV_CONF 0x00000301 -#define MSG_CONN_ACTV_IND 0x00000302 -#define MSG_CONN_ACTV_RESP 0x08000303 - -#define MSG_DISC_REQ 0x08000400 -#define MSG_DISC_CONF 0x00000401 -#define MSG_DISC_IND 0x00000402 -#define MSG_DISC_RESP 0x08000403 - -#define MSG_TDATA_REQ 0x0908E200 -#define MSG_TDATA_CONF 0x0000E201 -#define MSG_TDATA_IND 0x0000E202 -#define MSG_TDATA_RESP 0x0908E203 - -#define MSG_SELP_REQ 0x09004000 -#define MSG_SELP_CONF 0x00004001 - -#define MSG_ACT_TRANSP_REQ 0x0908E000 -#define MSG_ACT_TRANSP_CONF 0x0000E001 - -#define MSG_STPROT_REQ 0x09004100 -#define MSG_STPROT_CONF 0x00004101 - -#define MSG_PING188_REQ 0x09030500 -#define MSG_PING188_CONF 0x000005bc - -#define MSG_WATCH188 0x09030400 - -#define MSG_API_ON 0x08020102 -#define MSG_POOL_PCBIT 0x08020400 -#define MSG_POOL_PCBIT_CONF 0x00000401 - -#define MSG_INFO_IND 0x00002602 -#define MSG_INFO_RESP 0x08002603 - -#define MSG_DEBUG_188 0x0000ff00 - -/* - - long 4 3 2 1 - Intel 1 2 3 4 -*/ - -struct msg_fmt { -#ifdef __LITTLE_ENDIAN /* Little Endian */ - u_char scmd; - u_char cmd; - u_char proc; - u_char cpu; -#else -#error "Non-Intel CPU" - u_char cpu; - u_char proc; - u_char cmd; - u_char scmd; -#endif -}; - - -#define MAX_QUEUED 7 - -#define SCHED_READ 0x01 -#define SCHED_WRITE 0x02 - -#define SET_RUN_TIMEOUT 2*HZ /* 2 seconds */ - - -struct frame_buf { - ulong msg; - unsigned short refnum; - unsigned short dt_len; - unsigned short hdr_len; - struct sk_buff *skb; - unsigned short copied; - struct frame_buf * next; -}; - -#define MIN(a,b) ((awriteptr - dev->sh_mem)); - printk(KERN_DEBUG "readptr = %ld\n", - (ulong) (dev->readptr - (dev->sh_mem + BANK2))); - printk(KERN_DEBUG "{rcv_seq=%01x, send_seq=%01x, unack_seq=%01x}\n", - dev->rcv_seq, dev->send_seq, dev->unack_seq); -} -#endif - -static __inline__ struct pcbit_dev * chan2dev(struct pcbit_chan * chan) -{ - struct pcbit_dev * dev; - int i; - - - for (i=0; ib1 == chan || dev->b2 == chan) - return dev; - return NULL; - -} - -static __inline__ struct pcbit_dev * finddev(int id) -{ - struct pcbit_dev * dev; - int i; - - for (i=0; iid == id) - return dev; - return NULL; -} - - -/* - * Support routines for reading and writing in the board - */ - -static __inline__ void pcbit_writeb(struct pcbit_dev *dev, unsigned char dt) -{ - writeb(dt, dev->writeptr++); - if (dev->writeptr == dev->sh_mem + BANKLEN) - dev->writeptr = dev->sh_mem; -} - -static __inline__ void pcbit_writew(struct pcbit_dev *dev, unsigned short dt) -{ - int dist; - - dist = BANKLEN - (dev->writeptr - dev->sh_mem); - switch (dist) { - case 2: - writew(dt, dev->writeptr); - dev->writeptr = dev->sh_mem; - break; - case 1: - writeb((u_char) (dt & 0x00ffU), dev->writeptr); - dev->writeptr = dev->sh_mem; - writeb((u_char) (dt >> 8), dev->writeptr++); - break; - default: - writew(dt, dev->writeptr); - dev->writeptr += 2; - break; - }; -} - -static __inline__ void memcpy_topcbit(struct pcbit_dev * dev, u_char * data, - int len) -{ - int diff; - - diff = len - (BANKLEN - (dev->writeptr - dev->sh_mem) ); - - if (diff > 0) - { - memcpy_toio(dev->writeptr, data, len - diff); - memcpy_toio(dev->sh_mem, data + (len - diff), diff); - dev->writeptr = dev->sh_mem + diff; - } - else - { - memcpy_toio(dev->writeptr, data, len); - - dev->writeptr += len; - if (diff == 0) - dev->writeptr = dev->sh_mem; - } -} - -static __inline__ unsigned char pcbit_readb(struct pcbit_dev *dev) -{ - unsigned char val; - - val = readb(dev->readptr++); - if (dev->readptr == dev->sh_mem + BANK2 + BANKLEN) - dev->readptr = dev->sh_mem + BANK2; - - return val; -} - -static __inline__ unsigned short pcbit_readw(struct pcbit_dev *dev) -{ - int dist; - unsigned short val; - - dist = BANKLEN - ( dev->readptr - (dev->sh_mem + BANK2 ) ); - switch (dist) { - case 2: - val = readw(dev->readptr); - dev->readptr = dev->sh_mem + BANK2; - break; - case 1: - val = readb(dev->readptr); - dev->readptr = dev->sh_mem + BANK2; - val = (readb(dev->readptr++) << 8) | val; - break; - default: - val = readw(dev->readptr); - dev->readptr += 2; - break; - }; - return val; -} - -static __inline__ void memcpy_frompcbit(struct pcbit_dev * dev, u_char * data, int len) -{ - int diff; - - diff = len - (BANKLEN - (dev->readptr - (dev->sh_mem + BANK2) ) ); - if (diff > 0) - { - memcpy_fromio(data, dev->readptr, len - diff); - memcpy_fromio(data + (len - diff), dev->sh_mem + BANK2 , diff); - dev->readptr = dev->sh_mem + BANK2 + diff; - } - else - { - memcpy_fromio(data, dev->readptr, len); - dev->readptr += len; - if (diff == 0) - dev->readptr = dev->sh_mem + BANK2; - } -} - - -#endif - - - - - - - diff --git a/drivers/isdn/pcbit/module.c b/drivers/isdn/pcbit/module.c deleted file mode 100644 index 79955201..00000000 --- a/drivers/isdn/pcbit/module.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 1996 Universidade de Lisboa - * - * Written by Pedro Roque Marques (roque@di.fc.ul.pt) - * - * This software may be used and distributed according to the terms of - * the GNU Public License, incorporated herein by reference. - */ - -/* - * PCBIT-D module support - */ - -#include - -#include -#include -#include -#include -#include - -#include -#include "pcbit.h" - -static int mem[MAX_PCBIT_CARDS] = {0, }; -static int irq[MAX_PCBIT_CARDS] = {0, }; - -static int num_boards; -struct pcbit_dev * dev_pcbit[MAX_PCBIT_CARDS] = {0, 0, 0, 0}; - -int init_module(void); -void cleanup_module(void); - -extern void pcbit_terminate(int board); -extern int pcbit_init_dev(int board, int mem_base, int irq); - -#ifdef MODULE -MODULE_PARM(mem, "1-" __MODULE_STRING(MAX_PCBIT_CARDS) "i"); -MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_PCBIT_CARDS) "i"); -#define pcbit_init init_module -#endif - -int pcbit_init(void) -{ - int board; - - num_boards = 0; - - printk(KERN_INFO - "PCBIT-D device driver v 0.5 - " - "Copyright (C) 1996 Universidade de Lisboa\n"); - - if (mem[0] || irq[0]) - { - for (board=0; board < MAX_PCBIT_CARDS && mem[board] && irq[board]; board++) - { - if (!mem[board]) - mem[board] = 0xD0000; - if (!irq[board]) - irq[board] = 5; - - if (pcbit_init_dev(board, mem[board], irq[board]) == 0) - num_boards++; - - else - { - printk(KERN_WARNING - "pcbit_init failed for dev %d", - board + 1); - return -EIO; - } - } - } - - /* Hardcoded default settings detection */ - - if (!num_boards) - { - printk(KERN_INFO - "Trying to detect board using default settings\n"); - if (pcbit_init_dev(0, 0xD0000, 5) == 0) - num_boards++; - else - return -EIO; - } - - /* No symbols to export, hide all symbols */ - EXPORT_NO_SYMBOLS; - - return 0; -} - -#ifdef MODULE -void cleanup_module(void) -{ - int board; - - for (board = 0; board < num_boards; board++) - pcbit_terminate(board); - printk(KERN_INFO - "PCBIT-D module unloaded\n"); -} - -#else -#ifdef COMPAT_HAS_NEW_SETUP -#define MAX_PARA (MAX_PCBIT_CARDS * 2) -#include -static int __init pcbit_setup(char *line) -{ - int i, j, argc; - char *str; - 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; - - while (argc && (i= 0) && (x <= cinst)) - -/* - * Per channel status and configuration - */ -typedef struct { - int l2_proto; - int l3_proto; - char dn[50]; - unsigned long first_sendbuf; /* Offset of first send buffer */ - unsigned int num_sendbufs; /* Number of send buffers */ - unsigned int free_sendbufs; /* Number of free sendbufs */ - unsigned int next_sendbuf; /* Next sequential buffer */ - char eazlist[50]; /* Set with SETEAZ */ - char sillist[50]; /* Set with SETSIL */ - int eazclear; /* Don't accept calls if TRUE */ -} bchan; - -/* - * Everything you want to know about the adapter ... - */ -typedef struct { - int model; - int driverId; /* LL Id */ - char devicename[20]; /* The device name */ - isdn_if *card; /* ISDN4Linux structure */ - bchan *channel; /* status of the B channels */ - char nChannels; /* Number of channels */ - unsigned int interrupt; /* Interrupt number */ - int iobase; /* I/O Base address */ - int ioport[MAX_IO_REGS]; /* Index to I/O ports */ - int shmem_pgport; /* port for the exp mem page reg. */ - int shmem_magic; /* adapter magic number */ - unsigned int rambase; /* Shared RAM base address */ - unsigned int ramsize; /* Size of shared memory */ - RspMessage async_msg; /* Async response message */ - int want_async_messages; /* Snoop the Q ? */ - unsigned char seq_no; /* Next send seq. number */ - struct timer_list reset_timer; /* Check reset timer */ - struct timer_list stat_timer; /* Check startproc timer */ - unsigned char nphystat; /* Latest PhyStat info */ - unsigned char phystat; /* Last PhyStat info */ - HWConfig_pl hwconfig; /* Hardware config info */ - char load_ver[11]; /* CommManage Version string */ - char proc_ver[11]; /* CommEngine Version */ - int StartOnReset; /* Indicates startproc after reset */ - int EngineUp; /* Indicates CommEngine Up */ - int trace_mode; /* Indicate if tracing is on */ -} board; - -#endif /* CARD_H */ diff --git a/drivers/isdn/sc/command.c b/drivers/isdn/sc/command.c deleted file mode 100644 index 35b999fe..00000000 --- a/drivers/isdn/sc/command.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define __NO_VERSION__ -#include "includes.h" /* This must be first */ -#include "hardware.h" -#include "message.h" -#include "card.h" -#include "scioc.h" - -int dial(int card, unsigned long channel, setup_parm setup); -int hangup(int card, unsigned long channel); -int answer(int card, unsigned long channel); -int clreaz(int card, unsigned long channel); -int seteaz(int card, unsigned long channel, char *); -int geteaz(int card, unsigned long channel, char *); -int setsil(int card, unsigned long channel, char *); -int getsil(int card, unsigned long channel, char *); -int setl2(int card, unsigned long arg); -int getl2(int card, unsigned long arg); -int setl3(int card, unsigned long arg); -int getl3(int card, unsigned long arg); -int lock(void); -int unlock(void); -int acceptb(int card, unsigned long channel); - -extern int cinst; -extern board *adapter[]; - -extern int sc_ioctl(int, scs_ioctl *); -extern int setup_buffers(int, int, unsigned int); -extern int indicate_status(int, int,ulong,char*); -extern void check_reset(unsigned long); -extern int send_and_receive(int, unsigned int, unsigned char, unsigned char, - unsigned char, unsigned char, unsigned char, unsigned char *, - RspMessage *, int); -extern int sendmessage(int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int, unsigned int *); -extern inline void pullphone(char *, char *); - -#ifdef DEBUG -/* - * Translate command codes to strings - */ -static char *commands[] = { "ISDN_CMD_IOCTL", - "ISDN_CMD_DIAL", - "ISDN_CMD_ACCEPTB", - "ISDN_CMD_ACCEPTB", - "ISDN_CMD_HANGUP", - "ISDN_CMD_CLREAZ", - "ISDN_CMD_SETEAZ", - "ISDN_CMD_GETEAZ", - "ISDN_CMD_SETSIL", - "ISDN_CMD_GETSIL", - "ISDN_CMD_SETL2", - "ISDN_CMD_GETL2", - "ISDN_CMD_SETL3", - "ISDN_CMD_GETL3", - "ISDN_CMD_LOCK", - "ISDN_CMD_UNLOCK", - "ISDN_CMD_SUSPEND", - "ISDN_CMD_RESUME" }; - -/* - * Translates ISDN4Linux protocol codes to strings for debug messages - */ -static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" }; -static char *l2protos[] = { "ISDN_PROTO_L2_X75I", - "ISDN_PROTO_L2_X75UI", - "ISDN_PROTO_L2_X75BUI", - "ISDN_PROTO_L2_HDLC", - "ISDN_PROTO_L2_TRANS" }; -#endif - -int get_card_from_id(int driver) -{ - int i; - - for(i = 0 ; i < cinst ; i++) { - if(adapter[i]->driverId == driver) - return i; - } - return -NODEV; -} - -/* - * command - */ - -int command(isdn_ctrl *cmd) -{ - int card; - - card = get_card_from_id(cmd->driver); - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - pr_debug("%s: Received %s command from Link Layer\n", - adapter[card]->devicename, commands[cmd->command]); - - /* - * Dispatch the command - */ - switch(cmd->command) { - case ISDN_CMD_IOCTL: - { - unsigned long cmdptr; - scs_ioctl ioc; - int err; - - memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long)); - if((err = copy_from_user(&ioc, (scs_ioctl *) cmdptr, - sizeof(scs_ioctl)))) { - pr_debug("%s: Failed to verify user space 0x%x\n", - adapter[card]->devicename, cmdptr); - return err; - } - return sc_ioctl(card, &ioc); - } - case ISDN_CMD_DIAL: - return dial(card, cmd->arg, cmd->parm.setup); - case ISDN_CMD_HANGUP: - return hangup(card, cmd->arg); - case ISDN_CMD_ACCEPTD: - return answer(card, cmd->arg); - case ISDN_CMD_ACCEPTB: - return acceptb(card, cmd->arg); - case ISDN_CMD_CLREAZ: - return clreaz(card, cmd->arg); - case ISDN_CMD_SETEAZ: - return seteaz(card, cmd->arg, cmd->parm.num); - case ISDN_CMD_GETEAZ: - return geteaz(card, cmd->arg, cmd->parm.num); - case ISDN_CMD_SETSIL: - return setsil(card, cmd->arg, cmd->parm.num); - case ISDN_CMD_GETSIL: - return getsil(card, cmd->arg, cmd->parm.num); - case ISDN_CMD_SETL2: - return setl2(card, cmd->arg); - case ISDN_CMD_GETL2: - return getl2(card, cmd->arg); - case ISDN_CMD_SETL3: - return setl3(card, cmd->arg); - case ISDN_CMD_GETL3: - return getl3(card, cmd->arg); - case ISDN_CMD_LOCK: - return lock(); - case ISDN_CMD_UNLOCK: - return unlock(); - default: - return -EINVAL; - } - return 0; -} - -/* - * Confirm our ability to communicate with the board. This test assumes no - * other message activity is present - */ -int loopback(int card) -{ - - int status; - static char testmsg[] = "Test Message"; - RspMessage rspmsg; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - pr_debug("%s: Sending loopback message\n", adapter[card]->devicename); - - - /* - * Send the loopback message to confirm that memory transfer is - * operational - */ - status = send_and_receive(card, CMPID, cmReqType1, - cmReqClass0, - cmReqMsgLpbk, - 0, - (unsigned char) strlen(testmsg), - (unsigned char *)testmsg, - &rspmsg, SAR_TIMEOUT); - - - if (!status) { - pr_debug("%s: Loopback message successfully sent\n", - adapter[card]->devicename); - if(strcmp(rspmsg.msg_data.byte_array, testmsg)) { - pr_debug("%s: Loopback return != sent\n", - adapter[card]->devicename); - return -EIO; - } - return 0; - } - else { - pr_debug("%s: Send loopback message failed\n", - adapter[card]->devicename); - return -EIO; - } - -} - -/* - * start the onboard firmware - */ -int startproc(int card) -{ - int status; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - /* - * send start msg - */ - status = sendmessage(card, CMPID,cmReqType2, - cmReqClass0, - cmReqStartProc, - 0,0,0); - pr_debug("%s: Sent startProc\n", adapter[card]->devicename); - - return status; -} - - -int loadproc(int card, char *data) -{ - return -1; -} - - -/* - * Dials the number passed in - */ -int dial(int card, unsigned long channel, setup_parm setup) -{ - int status; - char Phone[48]; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - /*extract ISDN number to dial from eaz/msn string*/ - strcpy(Phone,setup.phone); - - /*send the connection message*/ - status = sendmessage(card, CEPID,ceReqTypePhy, - ceReqClass1, - ceReqPhyConnect, - (unsigned char) channel+1, - strlen(Phone), - (unsigned int *) Phone); - - pr_debug("%s: Dialing %s on channel %d\n", - adapter[card]->devicename, Phone, channel+1); - - return status; -} - -/* - * Answer an incoming call - */ -int answer(int card, unsigned long channel) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - if(setup_buffers(card, channel+1, BUFFER_SIZE)) { - hangup(card, channel+1); - return -ENOBUFS; - } - - indicate_status(card, ISDN_STAT_BCONN,channel,NULL); - pr_debug("%s: Answered incoming call on channel %s\n", - adapter[card]->devicename, channel+1); - return 0; -} - -/* - * Hangup up the call on specified channel - */ -int hangup(int card, unsigned long channel) -{ - int status; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - status = sendmessage(card, CEPID, ceReqTypePhy, - ceReqClass1, - ceReqPhyDisconnect, - (unsigned char) channel+1, - 0, - NULL); - pr_debug("%s: Sent HANGUP message to channel %d\n", - adapter[card]->devicename, channel+1); - return status; -} - -/* - * Set the layer 2 protocol (X.25, HDLC, Raw) - */ -int setl2(int card, unsigned long arg) -{ - int status =0; - int protocol,channel; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - protocol = arg >> 8; - channel = arg & 0xff; - adapter[card]->channel[channel].l2_proto = protocol; - pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n", - adapter[card]->devicename, channel+1,l2protos[adapter[card]->channel[channel].l2_proto],protocol); - - /* - * check that the adapter is also set to the correct protocol - */ - pr_debug("%s: Sending GetFrameFormat for channel %d\n", - adapter[card]->devicename, channel+1); - status = sendmessage(card, CEPID, ceReqTypeCall, - ceReqClass0, - ceReqCallGetFrameFormat, - (unsigned char)channel+1, - 1, - (unsigned int *) protocol); - if(status) - return status; - return 0; -} - -/* - * Get the layer 2 protocol - */ -int getl2(int card, unsigned long channel) { - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - pr_debug("%s: Level 2 protocol for channel %d reported as %s\n", - adapter[card]->devicename, channel+1, - l2protos[adapter[card]->channel[channel].l2_proto]); - - return adapter[card]->channel[channel].l2_proto; -} - -/* - * Set the layer 3 protocol - */ -int setl3(int card, unsigned long channel) -{ - int protocol = channel >> 8; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - adapter[card]->channel[channel].l3_proto = protocol; - pr_debug("%s: Level 3 protocol for channel %d set to %s\n", - adapter[card]->devicename, channel+1, l3protos[protocol]); - return 0; -} - -/* - * Get the layer 3 protocol - */ -int getl3(int card, unsigned long arg) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - pr_debug("%s: Level 3 protocol for channel %d reported as %s\n", - adapter[card]->devicename, arg+1, - l3protos[adapter[card]->channel[arg].l3_proto]); - return adapter[card]->channel[arg].l3_proto; -} - - -int acceptb(int card, unsigned long channel) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - if(setup_buffers(card, channel+1, BUFFER_SIZE)) - { - hangup(card, channel+1); - return -ENOBUFS; - } - - pr_debug("%s: B-Channel connection accepted on channel %d\n", - adapter[card]->devicename, channel+1); - indicate_status(card, ISDN_STAT_BCONN, channel, NULL); - return 0; -} - -int clreaz(int card, unsigned long arg) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(adapter[card]->channel[arg].eazlist, ""); - adapter[card]->channel[arg].eazclear = 1; - pr_debug("%s: EAZ List cleared for channel %d\n", - adapter[card]->devicename, arg+1); - return 0; -} - -int seteaz(int card, unsigned long arg, char *num) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(adapter[card]->channel[arg].eazlist, num); - adapter[card]->channel[arg].eazclear = 0; - pr_debug("%s: EAZ list for channel %d set to: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].eazlist); - return 0; -} - -int geteaz(int card, unsigned long arg, char *num) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(num, adapter[card]->channel[arg].eazlist); - pr_debug("%s: EAZ List for channel %d reported: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].eazlist); - return 0; -} - -int setsil(int card, unsigned long arg, char *num) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(adapter[card]->channel[arg].sillist, num); - pr_debug("%s: Service Indicators for channel %d set: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].sillist); - return 0; -} - -int getsil(int card, unsigned long arg, char *num) -{ - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - strcpy(num, adapter[card]->channel[arg].sillist); - pr_debug("%s: SIL for channel %d reported: %s\n", - adapter[card]->devicename, arg+1, - adapter[card]->channel[arg].sillist); - return 0; -} - - -int lock() -{ - MOD_INC_USE_COUNT; - return 0; -} - -int unlock() -{ - MOD_DEC_USE_COUNT; - return 0; -} - -int reset(int card) -{ - unsigned long flags; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - indicate_status(card, ISDN_STAT_STOP, 0, NULL); - - if(adapter[card]->EngineUp) { - del_timer(&adapter[card]->stat_timer); - } - - adapter[card]->EngineUp = 0; - - save_flags(flags); - cli(); - init_timer(&adapter[card]->reset_timer); - adapter[card]->reset_timer.function = check_reset; - adapter[card]->reset_timer.data = card; - adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME; - add_timer(&adapter[card]->reset_timer); - restore_flags(flags); - - outb(0x1,adapter[card]->ioport[SFT_RESET]); - - pr_debug("%s: Adapter Reset\n", adapter[card]->devicename); - return 0; -} - -void flushreadfifo (int card) -{ - while(inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) - inb(adapter[card]->ioport[FIFO_READ]); -} diff --git a/drivers/isdn/sc/debug.c b/drivers/isdn/sc/debug.c deleted file mode 100644 index d94921fe..00000000 --- a/drivers/isdn/sc/debug.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ -#include - -#define NULL 0x0 - -#define REQUEST_IRQ(a,b,c,d,e) request_irq(a,b,c,d,e) -#define FREE_IRQ(a,b) free_irq(a,b) - -inline char *strcpy(char *, const char *); - -int dbg_level = 0; -static char dbg_funcname[255]; - -void dbg_endfunc(void) -{ - if (dbg_level) { - printk("<-- Leaving function %s\n", dbg_funcname); - strcpy(dbg_funcname, ""); - } -} - -void dbg_func(char *func) -{ - strcpy(dbg_funcname, func); - if(dbg_level) - printk("--> Entering function %s\n", dbg_funcname); -} - -inline char *strcpy(char *dest, const char *src) -{ - char *i = dest; - char *j = (char *) src; - - while(*j) { - *i = *j; - i++; j++; - } - *(++i) = NULL; - return dest; -} - -inline void pullphone(char *dn, char *str) -{ - int i = 0; - - while(dn[i] != ',') - str[i] = dn[i++]; - str[i] = 0x0; -} diff --git a/drivers/isdn/sc/debug.h b/drivers/isdn/sc/debug.h deleted file mode 100644 index 033712d8..00000000 --- a/drivers/isdn/sc/debug.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define REQUEST_IRQ(a,b,c,d,e) request_irq(a,b,c,d,e) -#define FREE_IRQ(a,b) free_irq(a,b) diff --git a/drivers/isdn/sc/event.c b/drivers/isdn/sc/event.c deleted file mode 100644 index e0ecbe91..00000000 --- a/drivers/isdn/sc/event.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define __NO_VERSION__ -#include "includes.h" -#include "hardware.h" -#include "message.h" -#include "card.h" - -extern int cinst; -extern board *adapter[]; - -#ifdef DEBUG -static char *events[] = { "ISDN_STAT_STAVAIL", - "ISDN_STAT_ICALL", - "ISDN_STAT_RUN", - "ISDN_STAT_STOP", - "ISDN_STAT_DCONN", - "ISDN_STAT_BCONN", - "ISDN_STAT_DHUP", - "ISDN_STAT_BHUP", - "ISDN_STAT_CINF", - "ISDN_STAT_LOAD", - "ISDN_STAT_UNLOAD", - "ISDN_STAT_BSENT", - "ISDN_STAT_NODCH", - "ISDN_STAT_ADDCH", - "ISDN_STAT_CAUSE" }; -#endif - -int indicate_status(int card, int event,ulong Channel,char *Data) -{ - isdn_ctrl cmd; - - pr_debug("%s: Indicating event %s on Channel %d\n", - adapter[card]->devicename, events[event-256], Channel); - if (Data != NULL){ - pr_debug("%s: Event data: %s\n", adapter[card]->devicename, - Data); - switch (event) { - case ISDN_STAT_BSENT: - memcpy(&cmd.parm.length, Data, sizeof(cmd.parm.length)); - break; - case ISDN_STAT_ICALL: - memcpy(&cmd.parm.setup, Data, sizeof(cmd.parm.setup)); - break; - default: - strcpy(cmd.parm.num, Data); - } - } - - cmd.command = event; - cmd.driver = adapter[card]->driverId; - cmd.arg = Channel; - return adapter[card]->card->statcallb(&cmd); -} diff --git a/drivers/isdn/sc/hardware.h b/drivers/isdn/sc/hardware.h deleted file mode 100644 index b0f07ac3..00000000 --- a/drivers/isdn/sc/hardware.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Hardware specific macros, defines and structures - */ - -#ifndef HARDWARE_H -#define HARDWARE_H - -#include /* For HZ */ - -/* - * General hardware parameters common to all ISA adapters - */ - -#define MAX_CARDS 4 /* The maximum number of cards to - control or probe for. If you change - this, you must also change the number - of elements in io, irq, and ram to - match. Initialized in init.c */ -/* -extern unsigned int io[]; -extern unsigned char irq[]; -extern unsigned long ram[]; -*/ - -#define SIGNATURE 0x87654321 /* Board reset signature */ -#define SIG_OFFSET 0x1004 /* Where to find signature in shared RAM */ -#define TRACE_OFFSET 0x1008 /* Trace enable word offset in shared RAM */ -#define BUFFER_OFFSET 0x1800 /* Beginning of buffers */ - -/* I/O Port parameters */ -#define IOBASE_MIN 0x180 /* Lowest I/O port address */ -#define IOBASE_MAX 0x3C0 /* Highest I/O port address */ -#define IOBASE_OFFSET 0x20 /* Inter-board I/O port gap used during - probing */ -#define FIFORD_OFFSET 0x0 -#define FIFOWR_OFFSET 0x400 -#define FIFOSTAT_OFFSET 0x1000 -#define RESET_OFFSET 0x2800 -#define PG0_OFFSET 0x3000 /* Offset from I/O Base for Page 0 register */ -#define PG1_OFFSET 0x3400 /* Offset from I/O Base for Page 1 register */ -#define PG2_OFFSET 0x3800 /* Offset from I/O Base for Page 2 register */ -#define PG3_OFFSET 0x3C00 /* Offset from I/O Base for Page 3 register */ - -#define FIFO_READ 0 /* FIFO Read register */ -#define FIFO_WRITE 1 /* FIFO Write rgister */ -#define LO_ADDR_PTR 2 /* Extended RAM Low Addr Pointer */ -#define HI_ADDR_PTR 3 /* Extended RAM High Addr Pointer */ -#define NOT_USED_1 4 -#define FIFO_STATUS 5 /* FIFO Status Register */ -#define NOT_USED_2 6 -#define MEM_OFFSET 7 -#define SFT_RESET 10 /* Reset Register */ -#define EXP_BASE 11 /* Shared RAM Base address */ -#define EXP_PAGE0 12 /* Shared RAM Page0 register */ -#define EXP_PAGE1 13 /* Shared RAM Page1 register */ -#define EXP_PAGE2 14 /* Shared RAM Page2 register */ -#define EXP_PAGE3 15 /* Shared RAM Page3 register */ -#define IRQ_SELECT 16 /* IRQ selection register */ -#define MAX_IO_REGS 17 /* Total number of I/O ports */ - -/* FIFO register values */ -#define RF_HAS_DATA 0x01 /* fifo has data */ -#define RF_QUART_FULL 0x02 /* fifo quarter full */ -#define RF_HALF_FULL 0x04 /* fifo half full */ -#define RF_NOT_FULL 0x08 /* fifo not full */ -#define WF_HAS_DATA 0x10 /* fifo has data */ -#define WF_QUART_FULL 0x20 /* fifo quarter full */ -#define WF_HALF_FULL 0x40 /* fifo half full */ -#define WF_NOT_FULL 0x80 /* fifo not full */ - -/* Shared RAM parameters */ -#define SRAM_MIN 0xC0000 /* Lowest host shared RAM address */ -#define SRAM_MAX 0xEFFFF /* Highest host shared RAM address */ -#define SRAM_PAGESIZE 0x4000 /* Size of one RAM page (16K) */ - -/* Shared RAM buffer parameters */ -#define BUFFER_SIZE 0x800 /* The size of a buffer in bytes */ -#define BUFFER_BASE BUFFER_OFFSET /* Offset from start of shared RAM - where buffer start */ -#define BUFFERS_MAX 16 /* Maximum number of send/receive - buffers per channel */ -#define HDLC_PROTO 0x01 /* Frame Format for Layer 2 */ - -#define BRI_BOARD 0 -#define POTS_BOARD 1 -#define PRI_BOARD 2 - -/* - * Specific hardware parameters for the DataCommute/BRI - */ -#define BRI_CHANNELS 2 /* Number of B channels */ -#define BRI_BASEPG_VAL 0x98 -#define BRI_MAGIC 0x60000 /* Magic Number */ -#define BRI_MEMSIZE 0x10000 /* Ammount of RAM (64K) */ -#define BRI_PARTNO "72-029" -#define BRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS; -/* - * Specific hardware parameters for the DataCommute/PRI - */ -#define PRI_CHANNELS 23 /* Number of B channels */ -#define PRI_BASEPG_VAL 0x88 -#define PRI_MAGIC 0x20000 /* Magic Number */ -#define PRI_MEMSIZE 0x100000 /* Amount of RAM (1M) */ -#define PRI_PARTNO "72-030" -#define PRI_FEATURES ISDN_FEATURE_L2_HDLC | ISDN_FEATURE_L3_TRANS; - -/* - * Some handy macros - */ - -/* Return the number of jiffies in a given number of msecs */ -#define milliseconds(x) (x/(1000/HZ)) - -/* Determine if a channel number is valid for the adapter */ -#define IS_VALID_CHANNEL(y,x) ((x>0) && (x <= adapter[y]->channels)) - -#endif diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h deleted file mode 100644 index 951f06f2..00000000 --- a/drivers/isdn/sc/includes.h +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "debug.h" diff --git a/drivers/isdn/sc/init.c b/drivers/isdn/sc/init.c deleted file mode 100644 index 262fe17b..00000000 --- a/drivers/isdn/sc/init.c +++ /dev/null @@ -1,593 +0,0 @@ -#include "includes.h" -#include "hardware.h" -#include "card.h" - -board *adapter[MAX_CARDS]; -int cinst; - -static char devname[] = "scX"; -const char version[] = "2.0b1"; - -const char *boardname[] = { "DataCommute/BRI", "DataCommute/PRI", "TeleCommute/BRI" }; - -/* insmod set parameters */ -static unsigned int io[] = {0,0,0,0}; -static unsigned char irq[] = {0,0,0,0}; -static unsigned long ram[] = {0,0,0,0}; -static int do_reset = 0; - -static int sup_irq[] = { 11, 10, 9, 5, 12, 14, 7, 3, 4, 6 }; -#define MAX_IRQS 10 - -extern void interrupt_handler(int, void *, struct pt_regs *); -extern int sndpkt(int, int, int, struct sk_buff *); -extern int command(isdn_ctrl *); -extern int indicate_status(int, int, ulong, char*); -extern int reset(int); - -int identify_board(unsigned long, unsigned int); - -int irq_supported(int irq_x) -{ - int i; - for(i=0 ; i < MAX_IRQS ; i++) { - if(sup_irq[i] == irq_x) - return 1; - } - return 0; -} - -#ifdef MODULE -MODULE_PARM(io, "1-4i"); -MODULE_PARM(irq, "1-4i"); -MODULE_PARM(ram, "1-4i"); -MODULE_PARM(do_reset, "i"); -#define init_sc init_module -#else -/* -Initialization code for non-module version to be included - -void sc_setup(char *str, int *ints) -{ -} -*/ -#endif - -int init_sc(void) -{ - int b = -1; - int i, j; - int status = -ENODEV; - - unsigned long memsize = 0; - unsigned long features = 0; - isdn_if *interface; - unsigned char channels; - unsigned char pgport; - unsigned long magic; - int model; - int last_base = IOBASE_MIN; - int probe_exhasted = 0; - -#ifdef MODULE - pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s Loaded\n", version); -#else - pr_info("SpellCaster ISA ISDN Adapter Driver rev. %s\n", version); -#endif - pr_info("Copyright (C) 1996 SpellCaster Telecommunications Inc.\n"); - - while(b++ < MAX_CARDS - 1) { - pr_debug("Probing for adapter #%d\n", b); - /* - * Initialize reusable variables - */ - model = -1; - magic = 0; - channels = 0; - pgport = 0; - - /* - * See if we should probe for IO base - */ - pr_debug("I/O Base for board %d is 0x%x, %s probe\n", b, io[b], - io[b] == 0 ? "will" : "won't"); - if(io[b]) { - /* - * No, I/O Base has been provided - */ - for (i = 0 ; i < MAX_IO_REGS - 1 ; i++) { - if(check_region(io[b] + i * 0x400, 1)) { - pr_debug("check_region for 0x%x failed\n", io[b] + i * 0x400); - io[b] = 0; - break; - } - } - - /* - * Confirm the I/O Address with a test - */ - if(io[b] == 0) { - pr_debug("I/O Address 0x%x is in use.\n"); - continue; - } - - outb(0x18, io[b] + 0x400 * EXP_PAGE0); - if(inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) { - pr_debug("I/O Base 0x%x fails test\n"); - continue; - } - } - else { - /* - * Yes, probe for I/O Base - */ - if(probe_exhasted) { - pr_debug("All probe addresses exhasted, skipping\n"); - continue; - } - pr_debug("Probing for I/O...\n"); - for (i = last_base ; i <= IOBASE_MAX ; i += IOBASE_OFFSET) { - int found_io = 1; - if (i == IOBASE_MAX) { - probe_exhasted = 1; /* No more addresses to probe */ - pr_debug("End of Probes\n"); - } - last_base = i + IOBASE_OFFSET; - pr_debug(" checking 0x%x...", i); - for ( j = 0 ; j < MAX_IO_REGS - 1 ; j++) { - if(check_region(i + j * 0x400, 1)) { - pr_debug("Failed\n"); - found_io = 0; - break; - } - } - - if(found_io) { - io[b] = i; - outb(0x18, io[b] + 0x400 * EXP_PAGE0); - if(inb(io[b] + 0x400 * EXP_PAGE0) != 0x18) { - pr_debug("Failed by test\n"); - continue; - } - pr_debug("Passed\n"); - break; - } - } - if(probe_exhasted) { - continue; - } - } - - /* - * See if we should probe for shared RAM - */ - if(do_reset) { - pr_debug("Doing a SAFE probe reset\n"); - outb(0xFF, io[b] + RESET_OFFSET); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(milliseconds(10000)); - } - pr_debug("RAM Base for board %d is 0x%x, %s probe\n", b, ram[b], - ram[b] == 0 ? "will" : "won't"); - - if(ram[b]) { - /* - * No, the RAM base has been provided - * Just look for a signature and ID the - * board model - */ - if(!check_region(ram[b], SRAM_PAGESIZE)) { - pr_debug("check_region for RAM base 0x%x succeeded\n", ram[b]); - model = identify_board(ram[b], io[b]); - } - } - else { - /* - * Yes, probe for free RAM and look for - * a signature and id the board model - */ - for (i = SRAM_MIN ; i < SRAM_MAX ; i += SRAM_PAGESIZE) { - pr_debug("Checking RAM address 0x%x...\n", i); - if(!check_region(i, SRAM_PAGESIZE)) { - pr_debug(" check_region succeeded\n"); - model = identify_board(i, io[b]); - if (model >= 0) { - pr_debug(" Identified a %s\n", - boardname[model]); - ram[b] = i; - break; - } - pr_debug(" Unidentifed or inaccessible\n"); - continue; - } - pr_debug(" check_region failed\n"); - } - } - /* - * See if we found free RAM and the board model - */ - if(!ram[b] || model < 0) { - /* - * Nope, there was no place in RAM for the - * board, or it couldn't be identified - */ - pr_debug("Failed to find an adapter at 0x%x\n", ram[b]); - continue; - } - - /* - * Set the board's magic number, memory size and page register - */ - switch(model) { - case PRI_BOARD: - channels = 23; - magic = 0x20000; - memsize = 0x100000; - features = PRI_FEATURES; - break; - - case BRI_BOARD: - case POTS_BOARD: - channels = 2; - magic = 0x60000; - memsize = 0x10000; - features = BRI_FEATURES; - break; - } - switch(ram[b] >> 12 & 0x0F) { - case 0x0: - pr_debug("RAM Page register set to EXP_PAGE0\n"); - pgport = EXP_PAGE0; - break; - - case 0x4: - pr_debug("RAM Page register set to EXP_PAGE1\n"); - pgport = EXP_PAGE1; - break; - - case 0x8: - pr_debug("RAM Page register set to EXP_PAGE2\n"); - pgport = EXP_PAGE2; - break; - - case 0xC: - pr_debug("RAM Page register set to EXP_PAGE3\n"); - pgport = EXP_PAGE3; - break; - - default: - pr_debug("RAM base address doesn't fall on 16K boundary\n"); - continue; - } - - pr_debug("current IRQ: %d b: %d\n",irq[b],b); - /* - * See if we should probe for an irq - */ - if(irq[b]) { - /* - * No we were given one - * See that it is supported and free - */ - pr_debug("Trying for IRQ: %d\n",irq[b]); - if (irq_supported(irq[b])) { - if(REQUEST_IRQ(irq[b], interrupt_handler, - SA_PROBE, "sc_probe", NULL)) { - pr_debug("IRQ %d is already in use\n", - irq[b]); - continue; - } - FREE_IRQ(irq[b], NULL); - } - } - else { - /* - * Yes, we need to probe for an IRQ - */ - pr_debug("Probing for IRQ...\n"); - for (i = 0; i < MAX_IRQS ; i++) { - if(!REQUEST_IRQ(sup_irq[i], interrupt_handler, SA_PROBE, "sc_probe", NULL)) { - pr_debug("Probed for and found IRQ %d\n", sup_irq[i]); - FREE_IRQ(sup_irq[i], NULL); - irq[b] = sup_irq[i]; - break; - } - } - } - - /* - * Make sure we got an IRQ - */ - if(!irq[b]) { - /* - * No interrupt could be used - */ - pr_debug("Failed to aquire an IRQ line\n"); - continue; - } - - /* - * Horray! We found a board, Make sure we can register - * it with ISDN4Linux - */ - interface = kmalloc(sizeof(isdn_if), GFP_KERNEL); - if (interface == NULL) { - /* - * Oops, can't malloc isdn_if - */ - continue; - } - memset(interface, 0, sizeof(isdn_if)); - - interface->hl_hdrlen = 0; - interface->channels = channels; - interface->maxbufsize = BUFFER_SIZE; - interface->features = features; - interface->writebuf_skb = sndpkt; - interface->writecmd = NULL; - interface->command = command; - strcpy(interface->id, devname); - interface->id[2] = '0' + cinst; - - /* - * Allocate the board structure - */ - adapter[cinst] = kmalloc(sizeof(board), GFP_KERNEL); - if (adapter[cinst] == NULL) { - /* - * Oops, can't alloc memory for the board - */ - kfree(interface); - continue; - } - memset(adapter[cinst], 0, sizeof(board)); - - if(!register_isdn(interface)) { - /* - * Oops, couldn't register for some reason - */ - kfree(interface); - kfree(adapter[cinst]); - continue; - } - - adapter[cinst]->card = interface; - adapter[cinst]->driverId = interface->channels; - strcpy(adapter[cinst]->devicename, interface->id); - adapter[cinst]->nChannels = channels; - adapter[cinst]->ramsize = memsize; - adapter[cinst]->shmem_magic = magic; - adapter[cinst]->shmem_pgport = pgport; - adapter[cinst]->StartOnReset = 1; - - /* - * Allocate channels status structures - */ - adapter[cinst]->channel = kmalloc(sizeof(bchan) * channels, GFP_KERNEL); - if (adapter[cinst]->channel == NULL) { - /* - * Oops, can't alloc memory for the channels - */ - indicate_status(cinst, ISDN_STAT_UNLOAD, 0, NULL); /* Fix me */ - kfree(interface); - kfree(adapter[cinst]); - continue; - } - memset(adapter[cinst]->channel, 0, sizeof(bchan) * channels); - - /* - * Lock down the hardware resources - */ - adapter[cinst]->interrupt = irq[b]; - REQUEST_IRQ(adapter[cinst]->interrupt, interrupt_handler, SA_INTERRUPT, - interface->id, NULL); - adapter[cinst]->iobase = io[b]; - for(i = 0 ; i < MAX_IO_REGS - 1 ; i++) { - adapter[cinst]->ioport[i] = io[b] + i * 0x400; - request_region(adapter[cinst]->ioport[i], 1, interface->id); - pr_debug("Requesting I/O Port %#x\n", adapter[cinst]->ioport[i]); - } - adapter[cinst]->ioport[IRQ_SELECT] = io[b] + 0x2; - request_region(adapter[cinst]->ioport[IRQ_SELECT], 1, interface->id); - pr_debug("Requesting I/O Port %#x\n", adapter[cinst]->ioport[IRQ_SELECT]); - adapter[cinst]->rambase = ram[b]; - request_region(adapter[cinst]->rambase, SRAM_PAGESIZE, interface->id); - - pr_info(" %s (%d) - %s %d channels IRQ %d, I/O Base 0x%x, RAM Base 0x%lx\n", - adapter[cinst]->devicename, adapter[cinst]->driverId, - boardname[model], channels, irq[b], io[b], ram[b]); - - /* - * reset the adapter to put things in motion - */ - reset(cinst); - - cinst++; - status = 0; - } - if (status) - pr_info("Failed to find any adapters, driver unloaded\n"); - return status; -} - -#ifdef MODULE -void cleanup_module(void) -{ - int i, j; - - for(i = 0 ; i < cinst ; i++) { - pr_debug("Cleaning up after adapter %d\n", i); - /* - * kill the timers - */ - del_timer(&(adapter[i]->reset_timer)); - del_timer(&(adapter[i]->stat_timer)); - - /* - * Tell I4L we're toast - */ - indicate_status(i, ISDN_STAT_STOP, 0, NULL); - indicate_status(i, ISDN_STAT_UNLOAD, 0, NULL); - - /* - * Release shared RAM - */ - release_region(adapter[i]->rambase, SRAM_PAGESIZE); - - /* - * Release the IRQ - */ - FREE_IRQ(adapter[i]->interrupt, NULL); - - /* - * Reset for a clean start - */ - outb(0xFF, adapter[i]->ioport[SFT_RESET]); - - /* - * Release the I/O Port regions - */ - for(j = 0 ; j < MAX_IO_REGS - 1; j++) { - release_region(adapter[i]->ioport[j], 1); - pr_debug("Releasing I/O Port %#x\n", adapter[i]->ioport[j]); - } - release_region(adapter[i]->ioport[IRQ_SELECT], 1); - pr_debug("Releasing I/O Port %#x\n", adapter[i]->ioport[IRQ_SELECT]); - - /* - * Release any memory we alloced - */ - kfree(adapter[i]->channel); - kfree(adapter[i]->card); - kfree(adapter[i]); - } - pr_info("SpellCaster ISA ISDN Adapter Driver Unloaded.\n"); -} -#endif - -int identify_board(unsigned long rambase, unsigned int iobase) -{ - unsigned int pgport; - unsigned long sig; - DualPortMemory *dpm; - RspMessage rcvmsg; - ReqMessage sndmsg; - HWConfig_pl hwci; - int x; - - pr_debug("Attempting to identify adapter @ 0x%x io 0x%x\n", - rambase, iobase); - - /* - * Enable the base pointer - */ - outb(rambase >> 12, iobase + 0x2c00); - - switch(rambase >> 12 & 0x0F) { - case 0x0: - pgport = iobase + PG0_OFFSET; - pr_debug("Page Register offset is 0x%x\n", PG0_OFFSET); - break; - - case 0x4: - pgport = iobase + PG1_OFFSET; - pr_debug("Page Register offset is 0x%x\n", PG1_OFFSET); - break; - - case 0x8: - pgport = iobase + PG2_OFFSET; - pr_debug("Page Register offset is 0x%x\n", PG2_OFFSET); - break; - - case 0xC: - pgport = iobase + PG3_OFFSET; - pr_debug("Page Register offset is 0x%x\n", PG3_OFFSET); - break; - default: - pr_debug("Invalid rambase 0x%lx\n", rambase); - return -1; - } - - /* - * Try to identify a PRI card - */ - outb(PRI_BASEPG_VAL, pgport); - set_current_state(TASK_INTERRUPTIBLE); - 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; - - /* - * Try to identify a PRI card - */ - outb(BRI_BASEPG_VAL, pgport); - set_current_state(TASK_INTERRUPTIBLE); - 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; - - return -1; - - /* - * Try to spot a card - */ - sig = readl(rambase + SIG_OFFSET); - pr_debug("Looking for a signature, got 0x%x\n", sig); - if(sig != SIGNATURE) - return -1; - - dpm = (DualPortMemory *) rambase; - - memset(&sndmsg, 0, MSG_LEN); - sndmsg.msg_byte_cnt = 3; - sndmsg.type = cmReqType1; - sndmsg.class = cmReqClass0; - sndmsg.code = cmReqHWConfig; - memcpy_toio(&(dpm->req_queue[dpm->req_head++]), &sndmsg, MSG_LEN); - outb(0, iobase + 0x400); - pr_debug("Sent HWConfig message\n"); - /* - * Wait for the response - */ - x = 0; - while((inb(iobase + FIFOSTAT_OFFSET) & RF_HAS_DATA) && x < 100) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - x++; - } - if(x == 100) { - pr_debug("Timeout waiting for response\n"); - return -1; - } - - memcpy_fromio(&rcvmsg, &(dpm->rsp_queue[dpm->rsp_tail]), MSG_LEN); - pr_debug("Got HWConfig response, status = 0x%x\n", rcvmsg.rsp_status); - memcpy(&hwci, &(rcvmsg.msg_data.HWCresponse), sizeof(HWConfig_pl)); - pr_debug("Hardware Config: Interface: %s, RAM Size: %d, Serial: %s\n" - " Part: %s, Rev: %s\n", - hwci.st_u_sense ? "S/T" : "U", hwci.ram_size, - hwci.serial_no, hwci.part_no, hwci.rev_no); - - if(!strncmp(PRI_PARTNO, hwci.part_no, 6)) - return PRI_BOARD; - if(!strncmp(BRI_PARTNO, hwci.part_no, 6)) - return BRI_BOARD; - - return -1; -} diff --git a/drivers/isdn/sc/interrupt.c b/drivers/isdn/sc/interrupt.c deleted file mode 100644 index 933d3427..00000000 --- a/drivers/isdn/sc/interrupt.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define __NO_VERSION__ -#include "includes.h" -#include "hardware.h" -#include "message.h" -#include "card.h" - -extern int indicate_status(int, int, ulong, char *); -extern void check_phystat(unsigned long); -extern void dump_messages(int); -extern int receivemessage(int, RspMessage *); -extern int sendmessage(int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int, unsigned int *); -extern void rcvpkt(int, RspMessage *); - -extern int cinst; -extern board *adapter[]; - -int get_card_from_irq(int irq) -{ - int i; - - for(i = 0 ; i < cinst ; i++) { - if(adapter[i]->interrupt == irq) - return i; - } - return -1; -} - -/* - * - */ -void interrupt_handler(int interrupt, void * cardptr, struct pt_regs *regs ) { - - RspMessage rcvmsg; - int channel; - int card; - - card = get_card_from_irq(interrupt); - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return; - } - - pr_debug("%s: Entered Interrupt handler\n", adapter[card]->devicename); - - /* - * Pull all of the waiting messages off the response queue - */ - while (!receivemessage(card, &rcvmsg)) { - /* - * Push the message to the adapter structure for - * send_and_receive to snoop - */ - if(adapter[card]->want_async_messages) - memcpy(&(adapter[card]->async_msg), &rcvmsg, sizeof(RspMessage)); - - channel = (unsigned int) rcvmsg.phy_link_no; - - /* - * Trap Invalid request messages - */ - if(IS_CM_MESSAGE(rcvmsg, 0, 0, Invalid)) { - pr_debug("%s: Invalid request Message, rsp_status = %d\n", - adapter[card]->devicename, rcvmsg.rsp_status); - break; - } - - /* - * Check for a linkRead message - */ - if (IS_CE_MESSAGE(rcvmsg, Lnk, 1, Read)) - { - pr_debug("%s: Received packet 0x%x bytes long at 0x%x\n", - adapter[card]->devicename, - rcvmsg.msg_data.response.msg_len, - rcvmsg.msg_data.response.buff_offset); - rcvpkt(card, &rcvmsg); - continue; - - } - - /* - * Handle a write acknoledgement - */ - if(IS_CE_MESSAGE(rcvmsg, Lnk, 1, Write)) { - pr_debug("%s: Packet Send ACK on channel %d\n", adapter[card]->devicename, - rcvmsg.phy_link_no); - adapter[card]->channel[rcvmsg.phy_link_no-1].free_sendbufs++; - continue; - } - - /* - * Handle a connection message - */ - if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Connect)) - { - unsigned int callid; - setup_parm setup; - pr_debug("%s: Connect message: line %d: status %d: cause 0x%x\n", - adapter[card]->devicename, - rcvmsg.phy_link_no, - rcvmsg.rsp_status, - rcvmsg.msg_data.byte_array[2]); - - memcpy(&callid,rcvmsg.msg_data.byte_array,sizeof(int)); - if(callid>=0x8000 && callid<=0xFFFF) - { - pr_debug("%s: Got Dial-Out Rsp\n", adapter[card]->devicename); - indicate_status(card, ISDN_STAT_DCONN, - (unsigned long)rcvmsg.phy_link_no-1,NULL); - - } - else if(callid>=0x0000 && callid<=0x7FFF) - { - pr_debug("%s: Got Incomming Call\n", adapter[card]->devicename); - strcpy(setup.phone,&(rcvmsg.msg_data.byte_array[4])); - strcpy(setup.eazmsn,adapter[card]->channel[rcvmsg.phy_link_no-1].dn); - setup.si1 = 7; - setup.si2 = 0; - setup.plan = 0; - setup.screen = 0; - - indicate_status(card, ISDN_STAT_ICALL,(unsigned long)rcvmsg.phy_link_no-1,(char *)&setup); - indicate_status(card, ISDN_STAT_DCONN,(unsigned long)rcvmsg.phy_link_no-1,NULL); - } - continue; - } - - /* - * Handle a disconnection message - */ - if (IS_CE_MESSAGE(rcvmsg, Phy, 1, Disconnect)) - { - pr_debug("%s: disconnect message: line %d: status %d: cause 0x%x\n", - adapter[card]->devicename, - rcvmsg.phy_link_no, - rcvmsg.rsp_status, - rcvmsg.msg_data.byte_array[2]); - - indicate_status(card, ISDN_STAT_BHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL); - indicate_status(card, ISDN_STAT_DHUP,(unsigned long)rcvmsg.phy_link_no-1,NULL); - continue; - - } - - /* - * Handle a startProc engine up message - */ - if (IS_CM_MESSAGE(rcvmsg, 5, 0, MiscEngineUp)) { - pr_debug("%s: Received EngineUp message\n", adapter[card]->devicename); - adapter[card]->EngineUp = 1; - sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,1,0,NULL); - sendmessage(card, CEPID,ceReqTypeCall,ceReqClass0,ceReqCallGetMyNumber,2,0,NULL); - init_timer(&adapter[card]->stat_timer); - adapter[card]->stat_timer.function = check_phystat; - adapter[card]->stat_timer.data = card; - adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME; - add_timer(&adapter[card]->stat_timer); - continue; - } - - /* - * Start proc response - */ - if (IS_CM_MESSAGE(rcvmsg, 2, 0, StartProc)) { - pr_debug("%s: StartProc Response Status %d\n", adapter[card]->devicename, - rcvmsg.rsp_status); - continue; - } - - /* - * Handle a GetMyNumber Rsp - */ - if (IS_CE_MESSAGE(rcvmsg,Call,0,GetMyNumber)){ - strcpy(adapter[card]->channel[rcvmsg.phy_link_no-1].dn,rcvmsg.msg_data.byte_array); - continue; - } - - /* - * PhyStatus response - */ - if(IS_CE_MESSAGE(rcvmsg, Phy, 2, Status)) { - unsigned int b1stat, b2stat; - - /* - * Covert the message data to the adapter->phystat code - */ - b1stat = (unsigned int) rcvmsg.msg_data.byte_array[0]; - b2stat = (unsigned int) rcvmsg.msg_data.byte_array[1]; - - adapter[card]->nphystat = (b2stat >> 8) | b1stat; /* endian?? */ - pr_debug("%s: PhyStat is 0x%2x\n", adapter[card]->devicename, - adapter[card]->nphystat); - continue; - } - - - /* - * Handle a GetFramFormat - */ - if(IS_CE_MESSAGE(rcvmsg, Call, 0, GetFrameFormat)) { - if(rcvmsg.msg_data.byte_array[0] != HDLC_PROTO) { - unsigned int proto = HDLC_PROTO; - /* - * Set board format to HDLC if it wasn't already - */ - pr_debug("%s: current frame format: 0x%x, will change to HDLC\n", - adapter[card]->devicename, - rcvmsg.msg_data.byte_array[0]); - sendmessage(card, CEPID, ceReqTypeCall, - ceReqClass0, - ceReqCallSetFrameFormat, - (unsigned char) channel +1, - 1,&proto); - } - continue; - } - - /* - * Hmm... - */ - pr_debug("%s: Received unhandled message (%d,%d,%d) link %d\n", - adapter[card]->devicename, rcvmsg.type, rcvmsg.class, rcvmsg.code, - rcvmsg.phy_link_no); - - } /* while */ - - pr_debug("%s: Exiting Interrupt Handler\n", adapter[card]->devicename); -} diff --git a/drivers/isdn/sc/ioctl.c b/drivers/isdn/sc/ioctl.c deleted file mode 100644 index 24a8163b..00000000 --- a/drivers/isdn/sc/ioctl.c +++ /dev/null @@ -1,513 +0,0 @@ -#define __NO_VERSION__ -#include "includes.h" -#include "hardware.h" -#include "message.h" -#include "card.h" -#include "scioc.h" - -extern int indicate_status(int, int, unsigned long, char *); -extern int startproc(int); -extern int loadproc(int, char *record); -extern int reset(int); -extern int send_and_receive(int, unsigned int, unsigned char,unsigned char, - unsigned char,unsigned char, - unsigned char, unsigned char *, RspMessage *, int); - -extern board *adapter[]; - -#if 0 -static char *ChannelStates[] = { "Idle", "Ready", "Connecting", "Connected", "Disconnecting" }; -#endif - -int GetStatus(int card, boardInfo *); - -/* - * Process private IOCTL messages (typically from scctrl) - */ -int sc_ioctl(int card, scs_ioctl *data) -{ - switch(data->command) { - case SCIOCRESET: /* Perform a hard reset of the adapter */ - { - pr_debug("%s: SCIOCRESET: ioctl received\n", adapter[card]->devicename); - adapter[card]->StartOnReset = 0; - return (reset(card)); - } - - case SCIOCLOAD: - { - RspMessage rcvmsg; - char srec[SCIOC_SRECSIZE]; - int status, err; - - pr_debug("%s: SCIOLOAD: ioctl received\n", adapter[card]->devicename); - if(adapter[card]->EngineUp) { - pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n", - adapter[card]->devicename); - return -1; - } - - /* - * Get the SRec from user space - */ - if ((err = copy_from_user(srec, (char *) data->dataptr, sizeof(srec)))) - return err; - - status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc, - 0, sizeof(srec), srec, &rcvmsg, SAR_TIMEOUT); - if(status) { - pr_debug("%s: SCIOCLOAD: command failed, status = %d\n", - adapter[card]->devicename, status); - return -1; - } - else { - pr_debug("%s: SCIOCLOAD: command successful\n", adapter[card]->devicename); - return 0; - } - } - - case SCIOCSTART: - { - pr_debug("%s: SCIOSTART: ioctl received\n", adapter[card]->devicename); - if(adapter[card]->EngineUp) { - pr_debug("%s: SCIOCSTART: command failed, engine already running.\n", - adapter[card]->devicename); - return -1; - } - - adapter[card]->StartOnReset = 1; - startproc(card); - return 0; - } - - case SCIOCSETSWITCH: - { - RspMessage rcvmsg; - char switchtype; - int status, err; - - pr_debug("%s: SCIOSETSWITCH: ioctl received\n", adapter[card]->devicename); - - /* - * Get the switch type from user space - */ - if ((err = copy_from_user(&switchtype, (char *) data->dataptr, sizeof(char)))) - return err; - - pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n", adapter[card]->devicename, - switchtype); - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType, - 0, sizeof(char),&switchtype,&rcvmsg, SAR_TIMEOUT); - if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETSWITCH: command successful\n", adapter[card]->devicename); - return 0; - } - else { - pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n", - adapter[card]->devicename, status); - return status; - } - } - - case SCIOCGETSWITCH: - { - RspMessage rcvmsg; - char switchtype; - int status, err; - - pr_debug("%s: SCIOGETSWITCH: ioctl received\n", adapter[card]->devicename); - - /* - * Get the switch type from the board - */ - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, - ceReqCallGetSwitchType, 0, 0, 0, &rcvmsg, SAR_TIMEOUT); - if (!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCGETSWITCH: command successful\n", adapter[card]->devicename); - } - else { - pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n", - adapter[card]->devicename, status); - return status; - } - - switchtype = rcvmsg.msg_data.byte_array[0]; - - /* - * Package the switch type and send to user space - */ - if ((err = copy_to_user((char *) data->dataptr, &switchtype, sizeof(char)))) - return err; - - return 0; - } - - case SCIOCGETSPID: - { - RspMessage rcvmsg; - char spid[SCIOC_SPIDSIZE]; - int status, err; - - pr_debug("%s: SCIOGETSPID: ioctl received\n", adapter[card]->devicename); - - /* - * Get the spid from the board - */ - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID, - data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); - if (!status) { - pr_debug("%s: SCIOCGETSPID: command successful\n", adapter[card]->devicename); - } - else { - pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n", - adapter[card]->devicename, status); - return status; - } - strcpy(spid, rcvmsg.msg_data.byte_array); - - /* - * Package the switch type and send to user space - */ - if ((err = copy_to_user((char *) data->dataptr, spid, sizeof(spid)))) - return err; - - return 0; - } - - case SCIOCSETSPID: - { - RspMessage rcvmsg; - char spid[SCIOC_SPIDSIZE]; - int status, err; - - pr_debug("%s: DCBIOSETSPID: ioctl received\n", adapter[card]->devicename); - - /* - * Get the spid from user space - */ - if ((err = copy_from_user(spid, (char *) data->dataptr, sizeof(spid)))) - return err; - - pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n", - adapter[card]->devicename, data->channel, spid); - status = send_and_receive(card, CEPID, ceReqTypeCall, - ceReqClass0, ceReqCallSetSPID, data->channel, - strlen(spid), spid, &rcvmsg, SAR_TIMEOUT); - if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETSPID: command successful\n", - adapter[card]->devicename); - return 0; - } - else { - pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n", - adapter[card]->devicename, status); - return status; - } - } - - case SCIOCGETDN: - { - RspMessage rcvmsg; - char dn[SCIOC_DNSIZE]; - int status, err; - - pr_debug("%s: SCIOGETDN: ioctl received\n", adapter[card]->devicename); - - /* - * Get the dn from the board - */ - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, - data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); - if (!status) { - pr_debug("%s: SCIOCGETDN: command successful\n", adapter[card]->devicename); - } - else { - pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n", - adapter[card]->devicename, status); - return status; - } - - strcpy(dn, rcvmsg.msg_data.byte_array); - - /* - * Package the dn and send to user space - */ - if ((err = copy_to_user((char *) data->dataptr, dn, sizeof(dn)))) - return err; - - return 0; - } - - case SCIOCSETDN: - { - RspMessage rcvmsg; - char dn[SCIOC_DNSIZE]; - int status, err; - - pr_debug("%s: SCIOSETDN: ioctl received\n", adapter[card]->devicename); - - /* - * Get the spid from user space - */ - if ((err = copy_from_user(dn, (char *) data->dataptr, sizeof(dn)))) - return err; - - pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n", - adapter[card]->devicename, data->channel, dn); - status = send_and_receive(card, CEPID, ceReqTypeCall, - ceReqClass0, ceReqCallSetMyNumber, data->channel, - strlen(dn),dn,&rcvmsg, SAR_TIMEOUT); - if(!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCSETDN: command successful\n", - adapter[card]->devicename); - return 0; - } - else { - pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n", - adapter[card]->devicename, status); - return status; - } - } - - case SCIOCTRACE: - - pr_debug("%s: SCIOTRACE: ioctl received\n", adapter[card]->devicename); -/* adapter[card]->trace = !adapter[card]->trace; - pr_debug("%s: SCIOCTRACE: tracing turned %s\n", adapter[card]->devicename, - adapter[card]->trace ? "ON" : "OFF"); */ - break; - - case SCIOCSTAT: - { - boardInfo bi; - int err; - - pr_debug("%s: SCIOSTAT: ioctl received\n", adapter[card]->devicename); - GetStatus(card, &bi); - - if ((err = copy_to_user((boardInfo *) data->dataptr, &bi, sizeof(boardInfo)))) - return err; - - return 0; - } - - case SCIOCGETSPEED: - { - RspMessage rcvmsg; - char speed; - int status, err; - - pr_debug("%s: SCIOGETSPEED: ioctl received\n", adapter[card]->devicename); - - /* - * Get the speed from the board - */ - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, - ceReqCallGetCallType, data->channel, 0, 0, &rcvmsg, SAR_TIMEOUT); - if (!status && !rcvmsg.rsp_status) { - pr_debug("%s: SCIOCGETSPEED: command successful\n", - adapter[card]->devicename); - } - else { - pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n", - adapter[card]->devicename, status); - return status; - } - - speed = rcvmsg.msg_data.byte_array[0]; - - /* - * Package the switch type and send to user space - */ - if ((err = copy_to_user((char *) data->dataptr, &speed, sizeof(char)))) - return err; - - return 0; - } - - case SCIOCSETSPEED: - pr_debug("%s: SCIOCSETSPEED: ioctl received\n", adapter[card]->devicename); - break; - - case SCIOCLOOPTST: - pr_debug("%s: SCIOCLOOPTST: ioctl received\n", adapter[card]->devicename); - break; - - default: - return -1; - } - - return 0; -} - -int GetStatus(int card, boardInfo *bi) -{ - RspMessage rcvmsg; - int i, status; - - /* - * Fill in some of the basic info about the board - */ - bi->modelid = adapter[card]->model; - strcpy(bi->serial_no, adapter[card]->hwconfig.serial_no); - strcpy(bi->part_no, adapter[card]->hwconfig.part_no); - bi->iobase = adapter[card]->iobase; - bi->rambase = adapter[card]->rambase; - bi->irq = adapter[card]->interrupt; - bi->ramsize = adapter[card]->hwconfig.ram_size; - bi->interface = adapter[card]->hwconfig.st_u_sense; - strcpy(bi->load_ver, adapter[card]->load_ver); - strcpy(bi->proc_ver, adapter[card]->proc_ver); - - /* - * Get the current PhyStats and LnkStats - */ - status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2, - ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if(!status) { - if(adapter[card]->model < PRI_BOARD) { - bi->l1_status = rcvmsg.msg_data.byte_array[2]; - for(i = 0 ; i < BRI_CHANNELS ; i++) - bi->status.bristats[i].phy_stat = - rcvmsg.msg_data.byte_array[i]; - } - else { - bi->l1_status = rcvmsg.msg_data.byte_array[0]; - bi->l2_status = rcvmsg.msg_data.byte_array[1]; - for(i = 0 ; i < PRI_CHANNELS ; i++) - bi->status.pristats[i].phy_stat = - rcvmsg.msg_data.byte_array[i+2]; - } - } - - /* - * Get the call types for each channel - */ - for (i = 0 ; i < adapter[card]->nChannels ; i++) { - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, - ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if(!status) { - if (adapter[card]->model == PRI_BOARD) { - bi->status.pristats[i].call_type = - rcvmsg.msg_data.byte_array[0]; - } - else { - bi->status.bristats[i].call_type = - rcvmsg.msg_data.byte_array[0]; - } - } - } - - /* - * If PRI, get the call states and service states for each channel - */ - if (adapter[card]->model == PRI_BOARD) { - /* - * Get the call states - */ - status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2, - ceReqPhyChCallState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if(!status) { - for( i = 0 ; i < PRI_CHANNELS ; i++ ) - bi->status.pristats[i].call_state = - rcvmsg.msg_data.byte_array[i]; - } - - /* - * Get the service states - */ - status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2, - ceReqPhyChServState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if(!status) { - for( i = 0 ; i < PRI_CHANNELS ; i++ ) - bi->status.pristats[i].serv_state = - rcvmsg.msg_data.byte_array[i]; - } - - /* - * Get the link stats for the channels - */ - for (i = 1 ; i <= PRI_CHANNELS ; i++) { - status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0, - ceReqLnkGetStats, i, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if (!status) { - bi->status.pristats[i-1].link_stats.tx_good = - (unsigned long)rcvmsg.msg_data.byte_array[0]; - bi->status.pristats[i-1].link_stats.tx_bad = - (unsigned long)rcvmsg.msg_data.byte_array[4]; - bi->status.pristats[i-1].link_stats.rx_good = - (unsigned long)rcvmsg.msg_data.byte_array[8]; - bi->status.pristats[i-1].link_stats.rx_bad = - (unsigned long)rcvmsg.msg_data.byte_array[12]; - } - } - - /* - * Link stats for the D channel - */ - status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0, - ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if (!status) { - bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0]; - bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4]; - bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8]; - bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12]; - } - - return 0; - } - - /* - * If BRI or POTS, Get SPID, DN and call types for each channel - */ - - /* - * Get the link stats for the channels - */ - status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0, - ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if (!status) { - bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0]; - bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4]; - bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8]; - bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12]; - bi->status.bristats[0].link_stats.tx_good = - (unsigned long)rcvmsg.msg_data.byte_array[16]; - bi->status.bristats[0].link_stats.tx_bad = - (unsigned long)rcvmsg.msg_data.byte_array[20]; - bi->status.bristats[0].link_stats.rx_good = - (unsigned long)rcvmsg.msg_data.byte_array[24]; - bi->status.bristats[0].link_stats.rx_bad = - (unsigned long)rcvmsg.msg_data.byte_array[28]; - bi->status.bristats[1].link_stats.tx_good = - (unsigned long)rcvmsg.msg_data.byte_array[32]; - bi->status.bristats[1].link_stats.tx_bad = - (unsigned long)rcvmsg.msg_data.byte_array[36]; - bi->status.bristats[1].link_stats.rx_good = - (unsigned long)rcvmsg.msg_data.byte_array[40]; - bi->status.bristats[1].link_stats.rx_bad = - (unsigned long)rcvmsg.msg_data.byte_array[44]; - } - - /* - * Get the SPIDs - */ - for (i = 0 ; i < BRI_CHANNELS ; i++) { - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, - ceReqCallGetSPID, i+1, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if (!status) - strcpy(bi->status.bristats[i].spid, rcvmsg.msg_data.byte_array); - } - - /* - * Get the DNs - */ - for (i = 0 ; i < BRI_CHANNELS ; i++) { - status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, - ceReqCallGetMyNumber, i+1, 0, NULL, &rcvmsg, SAR_TIMEOUT); - if (!status) - strcpy(bi->status.bristats[i].dn, rcvmsg.msg_data.byte_array); - } - - return 0; -} diff --git a/drivers/isdn/sc/message.c b/drivers/isdn/sc/message.c deleted file mode 100644 index a552dbd9..00000000 --- a/drivers/isdn/sc/message.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * message.c - functions for sending and receiving control messages - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define __NO_VERSION__ -#include "includes.h" -#include "hardware.h" -#include "message.h" -#include "card.h" - -extern board *adapter[]; -extern unsigned int cinst; - -/* - * Obligitory function prototypes - */ -extern int indicate_status(int,ulong,char*); -extern int scm_command(isdn_ctrl *); -extern void *memcpy_fromshmem(int, void *, const void *, size_t); - -/* - * Dump message queue in shared memory to screen - */ -void dump_messages(int card) -{ - DualPortMemory dpm; - unsigned long flags; - - int i =0; - - if (!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - } - - save_flags(flags); - cli(); - outb(adapter[card]->ioport[adapter[card]->shmem_pgport], - (adapter[card]->shmem_magic >> 14) | 0x80); - memcpy_fromshmem(card, &dpm, 0, sizeof(dpm)); - restore_flags(flags); - - pr_debug("%s: Dumping Request Queue\n", adapter[card]->devicename); - for (i = 0; i < dpm.req_head; i++) { - pr_debug("%s: Message #%d: (%d,%d,%d), link: %d\n", - adapter[card]->devicename, i, - dpm.req_queue[i].type, - dpm.req_queue[i].class, - dpm.req_queue[i].code, - dpm.req_queue[i].phy_link_no); - } - - pr_debug("%s: Dumping Response Queue\n", adapter[card]->devicename); - for (i = 0; i < dpm.rsp_head; i++) { - pr_debug("%s: Message #%d: (%d,%d,%d), link: %d, status: %d\n", - adapter[card]->devicename, i, - dpm.rsp_queue[i].type, - dpm.rsp_queue[i].class, - dpm.rsp_queue[i].code, - dpm.rsp_queue[i].phy_link_no, - dpm.rsp_queue[i].rsp_status); - } - -} - -/* - * receive a message from the board - */ -int receivemessage(int card, RspMessage *rspmsg) -{ - DualPortMemory *dpm; - unsigned long flags; - - if (!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -EINVAL; - } - - pr_debug("%s: Entered receivemessage\n",adapter[card]->devicename); - - /* - * See if there are messages waiting - */ - if (inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) { - /* - * Map in the DPM to the base page and copy the message - */ - save_flags(flags); - cli(); - outb((adapter[card]->shmem_magic >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - dpm = (DualPortMemory *) adapter[card]->rambase; - memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]), - MSG_LEN); - dpm->rsp_tail = (dpm->rsp_tail+1) % MAX_MESSAGES; - inb(adapter[card]->ioport[FIFO_READ]); - restore_flags(flags); - - /* - * Tell the board that the message is received - */ - pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d " - "cnt:%d (type,class,code):(%d,%d,%d) " - "link:%d stat:0x%x\n", - adapter[card]->devicename, - rspmsg->sequence_no, - rspmsg->process_id, - rspmsg->time_stamp, - rspmsg->cmd_sequence_no, - rspmsg->msg_byte_cnt, - rspmsg->type, - rspmsg->class, - rspmsg->code, - rspmsg->phy_link_no, - rspmsg->rsp_status); - - return 0; - } - return -ENOMSG; -} - -/* - * send a message to the board - */ -int sendmessage(int card, - unsigned int procid, - unsigned int type, - unsigned int class, - unsigned int code, - unsigned int link, - unsigned int data_len, - unsigned int *data) -{ - DualPortMemory *dpm; - ReqMessage sndmsg; - unsigned long flags; - - if (!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -EINVAL; - } - - /* - * Make sure we only send CEPID messages when the engine is up - * and CMPID messages when it is down - */ - if(adapter[card]->EngineUp && procid == CMPID) { - pr_debug("%s: Attempt to send CM message with engine up\n", - adapter[card]->devicename); - return -ESRCH; - } - - if(!adapter[card]->EngineUp && procid == CEPID) { - pr_debug("%s: Attempt to send CE message with engine down\n", - adapter[card]->devicename); - return -ESRCH; - } - - memset(&sndmsg, 0, MSG_LEN); - sndmsg.msg_byte_cnt = 4; - sndmsg.type = type; - sndmsg.class = class; - sndmsg.code = code; - sndmsg.phy_link_no = link; - - if (data_len > 0) { - if (data_len > MSG_DATA_LEN) - data_len = MSG_DATA_LEN; - memcpy(&(sndmsg.msg_data), data, data_len); - sndmsg.msg_byte_cnt = data_len + 8; - } - - sndmsg.process_id = procid; - sndmsg.sequence_no = adapter[card]->seq_no++ % 256; - - /* - * wait for an empty slot in the queue - */ - while (!(inb(adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL)) - udelay(1); - - /* - * Disable interrupts and map in shared memory - */ - save_flags(flags); - cli(); - outb((adapter[card]->shmem_magic >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - dpm = (DualPortMemory *) adapter[card]->rambase; /* Fix me */ - memcpy_toio(&(dpm->req_queue[dpm->req_head]),&sndmsg,MSG_LEN); - dpm->req_head = (dpm->req_head+1) % MAX_MESSAGES; - outb(sndmsg.sequence_no, adapter[card]->ioport[FIFO_WRITE]); - restore_flags(flags); - - pr_debug("%s: Sent Message seq:%d pid:%d time:%d " - "cnt:%d (type,class,code):(%d,%d,%d) " - "link:%d\n ", - adapter[card]->devicename, - sndmsg.sequence_no, - sndmsg.process_id, - sndmsg.time_stamp, - sndmsg.msg_byte_cnt, - sndmsg.type, - sndmsg.class, - sndmsg.code, - sndmsg.phy_link_no); - - return 0; -} - -int send_and_receive(int card, - unsigned int procid, - unsigned char type, - unsigned char class, - unsigned char code, - unsigned char link, - unsigned char data_len, - unsigned char *data, - RspMessage *mesgdata, - int timeout) -{ - int retval; - int tries; - - if (!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return -EINVAL; - } - - adapter[card]->want_async_messages = 1; - retval = sendmessage(card, procid, type, class, code, link, - data_len, (unsigned int *) data); - - if (retval) { - pr_debug("%s: SendMessage failed in SAR\n", - adapter[card]->devicename); - adapter[card]->want_async_messages = 0; - return -EIO; - } - - tries = 0; - /* wait for the response */ - while (tries < timeout) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - - pr_debug("SAR waiting..\n"); - - /* - * See if we got our message back - */ - if ((adapter[card]->async_msg.type == type) && - (adapter[card]->async_msg.class == class) && - (adapter[card]->async_msg.code == code) && - (adapter[card]->async_msg.phy_link_no == link)) { - - /* - * Got it! - */ - pr_debug("%s: Got ASYNC message\n", - adapter[card]->devicename); - memcpy(mesgdata, &(adapter[card]->async_msg), - sizeof(RspMessage)); - adapter[card]->want_async_messages = 0; - return 0; - } - - tries++; - } - - pr_debug("%s: SAR message timeout\n", adapter[card]->devicename); - adapter[card]->want_async_messages = 0; - return -ETIME; -} diff --git a/drivers/isdn/sc/message.h b/drivers/isdn/sc/message.h deleted file mode 100644 index 13a121be..00000000 --- a/drivers/isdn/sc/message.h +++ /dev/null @@ -1,256 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * message.h - structures, macros and defines useful for sending - * messages to the adapter - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -/* - * Board message macros, defines and structures - */ - -#ifndef MESSAGE_H -#define MESSAGE_H - -#define MAX_MESSAGES 32 /* Maximum messages that can be - queued */ -#define MSG_DATA_LEN 48 /* Maximum size of message payload */ -#define MSG_LEN 64 /* Size of a message */ -#define CMPID 0 /* Loader message process ID */ -#define CEPID 64 /* Firmware message process ID */ - -/* - * Macro to determine if a message is a loader message - */ -#define IS_CM_MESSAGE(mesg, tx, cx, dx) \ - ((mesg.type == cmRspType##tx) \ - &&(mesg.class == cmRspClass##cx) \ - &&(mesg.code == cmRsp##dx)) - -/* - * Macro to determine if a message is a firmware message - */ -#define IS_CE_MESSAGE(mesg, tx, cx, dx) \ - ((mesg.type == ceRspType##tx) \ - &&(mesg.class == ceRspClass##cx) \ - &&(mesg.code == ceRsp##tx##dx)) - -/* - * Loader Request and Response Messages - */ - -/* message types */ -#define cmReqType1 1 -#define cmReqType2 2 -#define cmRspType0 0 -#define cmRspType1 1 -#define cmRspType2 2 -#define cmRspType5 5 - -/* message classes */ -#define cmReqClass0 0 -#define cmRspClass0 0 - -/* message codes */ -#define cmReqHWConfig 1 /* 1,0,1 */ -#define cmReqMsgLpbk 2 /* 1,0,2 */ -#define cmReqVersion 3 /* 1,0,3 */ -#define cmReqLoadProc 1 /* 2,0,1 */ -#define cmReqStartProc 2 /* 2,0,2 */ -#define cmReqReadMem 6 /* 2,0,6 */ -#define cmRspHWConfig cmReqHWConfig -#define cmRspMsgLpbk cmReqMsgLpbk -#define cmRspVersion cmReqVersion -#define cmRspLoadProc cmReqLoadProc -#define cmRspStartProc cmReqStartProc -#define cmRspReadMem cmReqReadMem -#define cmRspMiscEngineUp 1 /* 5,0,1 */ -#define cmRspInvalid 0 /* 0,0,0 */ - - -/* - * Firmware Request and Response Messages - */ - -/* message types */ -#define ceReqTypePhy 1 -#define ceReqTypeLnk 2 -#define ceReqTypeCall 3 -#define ceReqTypeStat 1 -#define ceRspTypeErr 0 -#define ceRspTypePhy ceReqTypePhy -#define ceRspTypeLnk ceReqTypeLnk -#define ceRspTypeCall ceReqTypeCall -#define ceRspTypeStat ceReqTypeStat - -/* message classes */ -#define ceReqClass0 0 -#define ceReqClass1 1 -#define ceReqClass2 2 -#define ceReqClass3 3 -#define ceRspClass0 ceReqClass0 -#define ceRspClass1 ceReqClass1 -#define ceRspClass2 ceReqClass2 -#define ceRspClass3 ceReqClass3 - -/* message codes (B) = BRI only, (P) = PRI only, (V) = POTS only */ -#define ceReqPhyProcInfo 1 /* 1,0,1 */ -#define ceReqPhyConnect 1 /* 1,1,1 */ -#define ceReqPhyDisconnect 2 /* 1,1,2 */ -#define ceReqPhySetParams 3 /* 1,1,3 (P) */ -#define ceReqPhyGetParams 4 /* 1,1,4 (P) */ -#define ceReqPhyStatus 1 /* 1,2,1 */ -#define ceReqPhyAcfaStatus 2 /* 1,2,2 (P) */ -#define ceReqPhyChCallState 3 /* 1,2,3 (P) */ -#define ceReqPhyChServState 4 /* 1,2,4 (P) */ -#define ceReqPhyRLoopBack 1 /* 1,3,1 */ -#define ceRspPhyProcInfo ceReqPhyProcInfo -#define ceRspPhyConnect ceReqPhyConnect -#define ceRspPhyDisconnect ceReqPhyDisconnect -#define ceRspPhySetParams ceReqPhySetParams -#define ceRspPhyGetParams ceReqPhyGetParams -#define ceRspPhyStatus ceReqPhyStatus -#define ceRspPhyAcfaStatus ceReqPhyAcfaStatus -#define ceRspPhyChCallState ceReqPhyChCallState -#define ceRspPhyChServState ceReqPhyChServState -#define ceRspPhyRLoopBack ceReqphyRLoopBack -#define ceReqLnkSetParam 1 /* 2,0,1 */ -#define ceReqLnkGetParam 2 /* 2,0,2 */ -#define ceReqLnkGetStats 3 /* 2,0,3 */ -#define ceReqLnkWrite 1 /* 2,1,1 */ -#define ceReqLnkRead 2 /* 2,1,2 */ -#define ceReqLnkFlush 3 /* 2,1,3 */ -#define ceReqLnkWrBufTrc 4 /* 2,1,4 */ -#define ceReqLnkRdBufTrc 5 /* 2,1,5 */ -#define ceRspLnkSetParam ceReqLnkSetParam -#define ceRspLnkGetParam ceReqLnkGetParam -#define ceRspLnkGetStats ceReqLnkGetStats -#define ceRspLnkWrite ceReqLnkWrite -#define ceRspLnkRead ceReqLnkRead -#define ceRspLnkFlush ceReqLnkFlush -#define ceRspLnkWrBufTrc ceReqLnkWrBufTrc -#define ceRspLnkRdBufTrc ceReqLnkRdBufTrc -#define ceReqCallSetSwitchType 1 /* 3,0,1 */ -#define ceReqCallGetSwitchType 2 /* 3,0,2 */ -#define ceReqCallSetFrameFormat 3 /* 3,0,3 */ -#define ceReqCallGetFrameFormat 4 /* 3,0,4 */ -#define ceReqCallSetCallType 5 /* 3,0,5 */ -#define ceReqCallGetCallType 6 /* 3,0,6 */ -#define ceReqCallSetSPID 7 /* 3,0,7 (!P) */ -#define ceReqCallGetSPID 8 /* 3,0,8 (!P) */ -#define ceReqCallSetMyNumber 9 /* 3,0,9 (!P) */ -#define ceReqCallGetMyNumber 10 /* 3,0,10 (!P) */ -#define ceRspCallSetSwitchType ceReqCallSetSwitchType -#define ceRspCallGetSwitchType ceReqCallSetSwitchType -#define ceRspCallSetFrameFormat ceReqCallSetFrameFormat -#define ceRspCallGetFrameFormat ceReqCallGetFrameFormat -#define ceRspCallSetCallType ceReqCallSetCallType -#define ceRspCallGetCallType ceReqCallGetCallType -#define ceRspCallSetSPID ceReqCallSetSPID -#define ceRspCallGetSPID ceReqCallGetSPID -#define ceRspCallSetMyNumber ceReqCallSetMyNumber -#define ceRspCallGetMyNumber ceReqCallGetMyNumber -#define ceRspStatAcfaStatus 2 -#define ceRspStat -#define ceRspErrError 0 /* 0,0,0 */ - -/* - * Call Types - */ -#define CALLTYPE_64K 0 -#define CALLTYPE_56K 1 -#define CALLTYPE_SPEECH 2 -#define CALLTYPE_31KHZ 3 - -/* - * Link Level data contains a pointer to and the length of - * a buffer in shared RAM. Used by LnkRead and LnkWrite message - * types. Part of RspMsgStruct and ReqMsgStruct. - */ -typedef struct { - unsigned long buff_offset; - unsigned short msg_len; -} LLData; - - -/* - * Message payload template for an HWConfig message - */ -typedef struct { - char st_u_sense; - char powr_sense; - char sply_sense; - unsigned char asic_id; - long ram_size; - char serial_no[13]; - char part_no[13]; - char rev_no[2]; -} HWConfig_pl; - -/* - * A Message - */ -struct message { - unsigned char sequence_no; - unsigned char process_id; - unsigned char time_stamp; - unsigned char cmd_sequence_no; /* Rsp messages only */ - unsigned char reserved1[3]; - unsigned char msg_byte_cnt; - unsigned char type; - unsigned char class; - unsigned char code; - unsigned char phy_link_no; - unsigned char rsp_status; /* Rsp messages only */ - unsigned char reseved2[3]; - union { - unsigned char byte_array[MSG_DATA_LEN]; - LLData response; - HWConfig_pl HWCresponse; - } msg_data; -}; - -typedef struct message ReqMessage; /* Request message */ -typedef struct message RspMessage; /* Response message */ - -/* - * The first 5010 bytes of shared memory contain the message queues, - * indexes and other data. This structure is its template - */ -typedef struct { - volatile ReqMessage req_queue[MAX_MESSAGES]; - volatile RspMessage rsp_queue[MAX_MESSAGES]; - volatile unsigned char req_head; - volatile unsigned char req_tail; - volatile unsigned char rsp_head; - volatile unsigned char rsp_tail; - volatile unsigned long signature; - volatile unsigned long trace_enable; - volatile unsigned char reserved[4]; -} DualPortMemory; - -#endif diff --git a/drivers/isdn/sc/packet.c b/drivers/isdn/sc/packet.c deleted file mode 100644 index 1e7e0565..00000000 --- a/drivers/isdn/sc/packet.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define __NO_VERSION__ -#include "includes.h" -#include "hardware.h" -#include "message.h" -#include "card.h" - -extern board *adapter[]; -extern unsigned int cinst; - -extern int get_card_from_id(int); -extern int indicate_status(int, int,ulong, char*); -extern void *memcpy_toshmem(int, void *, const void *, size_t); -extern void *memcpy_fromshmem(int, void *, const void *, size_t); -extern int sendmessage(int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int, unsigned int *); - -int sndpkt(int devId, int channel, struct sk_buff *data) -{ - LLData ReqLnkWrite; - int status; - int card; - unsigned long len; - - card = get_card_from_id(devId); - - if(!IS_VALID_CARD(card)) { - pr_debug("invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - pr_debug("%s: sndpkt: frst = 0x%x nxt = %d f = %d n = %d\n", - adapter[card]->devicename, - adapter[card]->channel[channel].first_sendbuf, - adapter[card]->channel[channel].next_sendbuf, - adapter[card]->channel[channel].free_sendbufs, - adapter[card]->channel[channel].num_sendbufs); - - if(!adapter[card]->channel[channel].free_sendbufs) { - pr_debug("%s: out of TX buffers\n", adapter[card]->devicename); - return -EINVAL; - } - - if(data->len > BUFFER_SIZE) { - pr_debug("%s: data overflows buffer size (data > buffer)\n", adapter[card]->devicename); - return -EINVAL; - } - - ReqLnkWrite.buff_offset = adapter[card]->channel[channel].next_sendbuf * - BUFFER_SIZE + adapter[card]->channel[channel].first_sendbuf; - ReqLnkWrite.msg_len = data->len; /* sk_buff size */ - pr_debug("%s: writing %d bytes to buffer offset 0x%x\n", adapter[card]->devicename, - ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset); - memcpy_toshmem(card, (char *)ReqLnkWrite.buff_offset, data->data, ReqLnkWrite.msg_len); - - /* - * sendmessage - */ - pr_debug("%s: sndpkt size=%d, buf_offset=0x%x buf_indx=%d\n", - adapter[card]->devicename, - ReqLnkWrite.msg_len, ReqLnkWrite.buff_offset, - adapter[card]->channel[channel].next_sendbuf); - - status = sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkWrite, - channel+1, sizeof(LLData), (unsigned int*)&ReqLnkWrite); - len = data->len; - if(status) { - pr_debug("%s: failed to send packet, status = %d\n", adapter[card]->devicename, status); - return -1; - } - else { - adapter[card]->channel[channel].free_sendbufs--; - adapter[card]->channel[channel].next_sendbuf = - ++adapter[card]->channel[channel].next_sendbuf == - adapter[card]->channel[channel].num_sendbufs ? 0 : - adapter[card]->channel[channel].next_sendbuf; - pr_debug("%s: packet sent successfully\n", adapter[card]->devicename); - dev_kfree_skb(data); - indicate_status(card,ISDN_STAT_BSENT,channel, (char *)&len); - } - return len; -} - -void rcvpkt(int card, RspMessage *rcvmsg) -{ - LLData newll; - struct sk_buff *skb; - - if(!IS_VALID_CARD(card)) { - pr_debug("invalid param: %d is not a valid card id\n", card); - return; - } - - switch(rcvmsg->rsp_status){ - case 0x01: - case 0x02: - case 0x70: - pr_debug("%s: error status code: 0x%x\n", adapter[card]->devicename, rcvmsg->rsp_status); - return; - case 0x00: - if (!(skb = dev_alloc_skb(rcvmsg->msg_data.response.msg_len))) { - printk(KERN_WARNING "%s: rcvpkt out of memory, dropping packet\n", - adapter[card]->devicename); - return; - } - skb_put(skb, rcvmsg->msg_data.response.msg_len); - pr_debug("%s: getting data from offset: 0x%x\n", - adapter[card]->devicename,rcvmsg->msg_data.response.buff_offset); - memcpy_fromshmem(card, - skb_put(skb, rcvmsg->msg_data.response.msg_len), - (char *)rcvmsg->msg_data.response.buff_offset, - rcvmsg->msg_data.response.msg_len); - adapter[card]->card->rcvcallb_skb(adapter[card]->driverId, - rcvmsg->phy_link_no-1, skb); - - case 0x03: - /* - * Recycle the buffer - */ - pr_debug("%s: buffer size : %d\n", adapter[card]->devicename, BUFFER_SIZE); -/* memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */ - newll.buff_offset = rcvmsg->msg_data.response.buff_offset; - newll.msg_len = BUFFER_SIZE; - pr_debug("%s: recycled buffer at offset 0x%x size %d\n", adapter[card]->devicename, - newll.buff_offset, newll.msg_len); - sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead, - rcvmsg->phy_link_no, sizeof(LLData), (unsigned int *)&newll); - } - -} - -int setup_buffers(int card, int c) -{ - unsigned int nBuffers, i, cBase; - unsigned int buffer_size; - LLData RcvBuffOffset; - - if(!IS_VALID_CARD(card)) { - pr_debug("invalid param: %d is not a valid card id\n", card); - return -ENODEV; - } - - /* - * Calculate the buffer offsets (send/recv/send/recv) - */ - pr_debug("%s: setting up channel buffer space in shared RAM\n", adapter[card]->devicename); - buffer_size = BUFFER_SIZE; - nBuffers = ((adapter[card]->ramsize - BUFFER_BASE) / buffer_size) / 2; - nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers; - pr_debug("%s: calculating buffer space: %d buffers, %d big\n", adapter[card]->devicename, - nBuffers, buffer_size); - if(nBuffers < 2) { - pr_debug("%s: not enough buffer space\n", adapter[card]->devicename); - return -1; - } - cBase = (nBuffers * buffer_size) * (c - 1); - pr_debug("%s: channel buffer offset from shared RAM: 0x%x\n", adapter[card]->devicename, cBase); - adapter[card]->channel[c-1].first_sendbuf = BUFFER_BASE + cBase; - adapter[card]->channel[c-1].num_sendbufs = nBuffers / 2; - adapter[card]->channel[c-1].free_sendbufs = nBuffers / 2; - adapter[card]->channel[c-1].next_sendbuf = 0; - pr_debug("%s: send buffer setup complete: first=0x%x n=%d f=%d, nxt=%d\n", - adapter[card]->devicename, - adapter[card]->channel[c-1].first_sendbuf, - adapter[card]->channel[c-1].num_sendbufs, - adapter[card]->channel[c-1].free_sendbufs, - adapter[card]->channel[c-1].next_sendbuf); - - /* - * Prep the receive buffers - */ - pr_debug("%s: adding %d RecvBuffers:\n", adapter[card]->devicename, nBuffers /2); - for (i = 0 ; i < nBuffers / 2; i++) { - RcvBuffOffset.buff_offset = - ((adapter[card]->channel[c-1].first_sendbuf + - (nBuffers / 2) * buffer_size) + (buffer_size * i)); - RcvBuffOffset.msg_len = buffer_size; - pr_debug("%s: adding RcvBuffer #%d offset=0x%x sz=%d bufsz:%d\n", - adapter[card]->devicename, - i + 1, RcvBuffOffset.buff_offset, - RcvBuffOffset.msg_len,buffer_size); - sendmessage(card, CEPID, ceReqTypeLnk, ceReqClass1, ceReqLnkRead, - c, sizeof(LLData), (unsigned int *)&RcvBuffOffset); - } - return 0; -} - -int print_skb(int card,char *skb_p, int len){ - int i,data; - pr_debug("%s: data at 0x%x len: 0x%x\n",adapter[card]->devicename, - skb_p,len); - for(i=1;i<=len;i++,skb_p++){ - data = (int) (0xff & (*skb_p)); - pr_debug("%s: data = 0x%x",adapter[card]->devicename,data); - if(!(i%4)) - pr_debug(" "); - if(!(i%32)) - pr_debug("\n"); - } - pr_debug("\n"); - return 0; -} - diff --git a/drivers/isdn/sc/scioc.h b/drivers/isdn/sc/scioc.h deleted file mode 100644 index 19db0b7c..00000000 --- a/drivers/isdn/sc/scioc.h +++ /dev/null @@ -1,101 +0,0 @@ - -/* - * IOCTL Command Codes - */ -#define SCIOCLOAD 0x01 /* Load a firmware record */ -#define SCIOCRESET 0x02 /* Perform hard reset */ -#define SCIOCDEBUG 0x03 /* Set debug level */ -#define SCIOCREV 0x04 /* Get driver revision(s) */ -#define SCIOCSTART 0x05 /* Start the firmware */ -#define SCIOCGETSWITCH 0x06 /* Get switch type */ -#define SCIOCSETSWITCH 0x07 /* Set switch type */ -#define SCIOCGETSPID 0x08 /* Get channel SPID */ -#define SCIOCSETSPID 0x09 /* Set channel SPID */ -#define SCIOCGETDN 0x0A /* Get channel DN */ -#define SCIOCSETDN 0x0B /* Set channel DN */ -#define SCIOCTRACE 0x0C /* Toggle trace mode */ -#define SCIOCSTAT 0x0D /* Get line status */ -#define SCIOCGETSPEED 0x0E /* Set channel speed */ -#define SCIOCSETSPEED 0x0F /* Set channel speed */ -#define SCIOCLOOPTST 0x10 /* Perform loopback test */ - -typedef struct { - int device; - int channel; - unsigned long command; - void *dataptr; -} scs_ioctl; - -/* Size of strings */ -#define SCIOC_SPIDSIZE 49 -#define SCIOC_DNSIZE SCIOC_SPIDSIZE -#define SCIOC_REVSIZE SCIOC_SPIDSIZE -#define SCIOC_SRECSIZE 49 - -typedef struct { - unsigned long tx_good; - unsigned long tx_bad; - unsigned long rx_good; - unsigned long rx_bad; -} ChLinkStats; - -typedef struct { - char spid[49]; - char dn[49]; - char call_type; - char phy_stat; - ChLinkStats link_stats; -} BRIStat; - -typedef BRIStat POTStat; - -typedef struct { - char call_type; - char call_state; - char serv_state; - char phy_stat; - ChLinkStats link_stats; -} PRIStat; - -typedef char PRIInfo; -typedef char BRIInfo; -typedef char POTInfo; - - -typedef struct { - char acfa_nos; - char acfa_ais; - char acfa_los; - char acfa_rra; - char acfa_slpp; - char acfa_slpn; - char acfa_fsrf; -} ACFAStat; - -typedef struct { - unsigned char modelid; - char serial_no[13]; - char part_no[13]; - char load_ver[11]; - char proc_ver[11]; - int iobase; - long rambase; - char irq; - long ramsize; - char interface; - char switch_type; - char l1_status; - char l2_status; - ChLinkStats dch_stats; - ACFAStat AcfaStats; - union { - PRIStat pristats[23]; - BRIStat bristats[2]; - POTStat potsstats[2]; - } status; - union { - PRIInfo priinfo; - BRIInfo briinfo; - POTInfo potsinfo; - } info; -} boardInfo; diff --git a/drivers/isdn/sc/shmem.c b/drivers/isdn/sc/shmem.c deleted file mode 100644 index 362e3bbe..00000000 --- a/drivers/isdn/sc/shmem.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * card.c - Card functions implementing ISDN4Linux functionality - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define __NO_VERSION__ -#include "includes.h" /* This must be first */ -#include "hardware.h" -#include "card.h" - -/* - * Main adapter array - */ -extern board *adapter[]; -extern int cinst; - -/* - * - */ -void *memcpy_toshmem(int card, void *dest, const void *src, size_t n) -{ - unsigned long flags; - void *ret; - unsigned char ch; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return NULL; - } - - if(n > SRAM_PAGESIZE) { - return NULL; - } - - /* - * determine the page to load from the address - */ - ch = (unsigned long) dest / SRAM_PAGESIZE; - pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch); - /* - * Block interrupts and load the page - */ - save_flags(flags); - cli(); - - outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); - ret = memcpy_toio(adapter[card]->rambase + - ((unsigned long) dest % 0x4000), src, n); - pr_debug("%s: copying %d bytes from %#x to %#x\n",adapter[card]->devicename, n, - (unsigned long) src, adapter[card]->rambase + ((unsigned long) dest %0x4000)); - restore_flags(flags); - - return ret; -} - -/* - * Reverse of above - */ -void *memcpy_fromshmem(int card, void *dest, const void *src, size_t n) -{ - unsigned long flags; - void *ret; - unsigned char ch; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return NULL; - } - - if(n > SRAM_PAGESIZE) { - return NULL; - } - - /* - * determine the page to load from the address - */ - ch = (unsigned long) src / SRAM_PAGESIZE; - pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch); - - - /* - * Block interrupts and load the page - */ - save_flags(flags); - cli(); - - outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); - ret = memcpy_fromio(dest,(void *)(adapter[card]->rambase + - ((unsigned long) src % 0x4000)), n); -/* pr_debug("%s: copying %d bytes from %#x to %#x\n", - adapter[card]->devicename, n, - adapter[card]->rambase + ((unsigned long) src %0x4000), (unsigned long) dest); */ - restore_flags(flags); - - return ret; -} - -void *memset_shmem(int card, void *dest, int c, size_t n) -{ - unsigned long flags; - unsigned char ch; - void *ret; - - if(!IS_VALID_CARD(card)) { - pr_debug("Invalid param: %d is not a valid card id\n", card); - return NULL; - } - - if(n > SRAM_PAGESIZE) { - return NULL; - } - - /* - * determine the page to load from the address - */ - ch = (unsigned long) dest / SRAM_PAGESIZE; - pr_debug("%s: loaded page %d\n",adapter[card]->devicename,ch); - - /* - * Block interrupts and load the page - */ - save_flags(flags); - cli(); - - outb(((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE) >> 14) | 0x80, - adapter[card]->ioport[adapter[card]->shmem_pgport]); - pr_debug("%s: set page to %#x\n",adapter[card]->devicename, - ((adapter[card]->shmem_magic + ch * SRAM_PAGESIZE)>>14)|0x80); - ret = memset_io(adapter[card]->rambase + - ((unsigned long) dest % 0x4000), c, n); - restore_flags(flags); - - return ret; -} diff --git a/drivers/isdn/sc/timer.c b/drivers/isdn/sc/timer.c deleted file mode 100644 index 7e6b8c07..00000000 --- a/drivers/isdn/sc/timer.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * $Id$ - * Copyright (C) 1996 SpellCaster Telecommunications Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * 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. - * - * For more information, please contact gpl-info@spellcast.com or write: - * - * SpellCaster Telecommunications Inc. - * 5621 Finch Avenue East, Unit #3 - * Scarborough, Ontario Canada - * M1B 2T9 - * +1 (416) 297-8565 - * +1 (416) 297-6433 Facsimile - */ - -#define __NO_VERSION__ -#include "includes.h" -#include "hardware.h" -#include "message.h" -#include "card.h" - -extern board *adapter[]; - -extern void flushreadfifo(int); -extern int startproc(int); -extern int indicate_status(int, int, unsigned long, char *); -extern int sendmessage(int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int, unsigned int *); - - -/* - * Write the proper values into the I/O ports following a reset - */ -void setup_ports(int card) -{ - - outb((adapter[card]->rambase >> 12), adapter[card]->ioport[EXP_BASE]); - - /* And the IRQ */ - outb((adapter[card]->interrupt | 0x80), - adapter[card]->ioport[IRQ_SELECT]); -} - -/* - * Timed function to check the status of a previous reset - * Must be very fast as this function runs in the context of - * an interrupt handler. - * - * Setup the ioports for the board that were cleared by the reset. - * Then, check to see if the signate has been set. Next, set the - * signature to a known value and issue a startproc if needed. - */ -void check_reset(unsigned long data) -{ - unsigned long flags; - unsigned long sig; - int card = (unsigned int) data; - - pr_debug("%s: check_timer timer called\n", adapter[card]->devicename); - - /* Setup the io ports */ - setup_ports(card); - - save_flags(flags); - cli(); - outb(adapter[card]->ioport[adapter[card]->shmem_pgport], - (adapter[card]->shmem_magic>>14) | 0x80); - sig = (unsigned long) *((unsigned long *)(adapter[card]->rambase + SIG_OFFSET)); - - /* check the signature */ - if(sig == SIGNATURE) { - flushreadfifo(card); - restore_flags(flags); - /* See if we need to do a startproc */ - if (adapter[card]->StartOnReset) - startproc(card); - } - else { - pr_debug("%s: No signature yet, waiting another %d jiffies.\n", - adapter[card]->devicename, CHECKRESET_TIME); - del_timer(&adapter[card]->reset_timer); - adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME; - add_timer(&adapter[card]->reset_timer); - } - restore_flags(flags); - -} - -/* - * Timed function to check the status of a previous reset - * Must be very fast as this function runs in the context of - * an interrupt handler. - * - * Send check adapter->phystat to see if the channels are up - * If they are, tell ISDN4Linux that the board is up. If not, - * tell IADN4Linux that it is up. Always reset the timer to - * fire again (endless loop). - */ -void check_phystat(unsigned long data) -{ - unsigned long flags; - int card = (unsigned int) data; - - pr_debug("%s: Checking status...\n", adapter[card]->devicename); - /* - * check the results of the last PhyStat and change only if - * has changed drastically - */ - if (adapter[card]->nphystat && !adapter[card]->phystat) { /* All is well */ - pr_debug("PhyStat transition to RUN\n"); - pr_info("%s: Switch contacted, transmitter enabled\n", - adapter[card]->devicename); - indicate_status(card, ISDN_STAT_RUN, 0, NULL); - } - else if (!adapter[card]->nphystat && adapter[card]->phystat) { /* All is not well */ - pr_debug("PhyStat transition to STOP\n"); - pr_info("%s: Switch connection lost, transmitter disabled\n", - adapter[card]->devicename); - - indicate_status(card, ISDN_STAT_STOP, 0, NULL); - } - - adapter[card]->phystat = adapter[card]->nphystat; - - /* Reinitialize the timer */ - save_flags(flags); - cli(); - del_timer(&adapter[card]->stat_timer); - adapter[card]->stat_timer.expires = jiffies + CHECKSTAT_TIME; - add_timer(&adapter[card]->stat_timer); - restore_flags(flags); - - /* Send a new cePhyStatus message */ - sendmessage(card, CEPID,ceReqTypePhy,ceReqClass2, - ceReqPhyStatus,0,0,NULL); -} - -/* - * When in trace mode, this callback is used to swap the working shared - * RAM page to the trace page(s) and process all received messages. It - * must be called often enough to get all of the messages out of RAM before - * it loops around. - * Trace messages are \n terminated strings. - * We output the messages in 64 byte chunks through readstat. Each chunk - * is scanned for a \n followed by a time stamp. If the timerstamp is older - * than the current time, scanning stops and the page and offset are recorded - * as the starting point the next time the trace timer is called. The final - * step is to restore the working page and reset the timer. - */ -void trace_timer(unsigned long data) -{ - unsigned long flags; - - /* - * Disable interrupts and swap the first page - */ - save_flags(flags); - cli(); -} diff --git a/include/linux/b1lli.h b/include/linux/b1lli.h deleted file mode 100644 index 96fdc46e..00000000 --- a/include/linux/b1lli.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * $Id$ - * - * ISDN lowlevel-module for AVM B1-card. - * - * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.7 1999/06/21 15:24:25 calle - * extend information in /proc. - * - * Revision 1.6 1999/04/15 19:49:36 calle - * fix fuer die B1-PCI. Jetzt geht z.B. auch IRQ 17 ... - * - * Revision 1.5 1998/10/25 14:50:28 fritz - * Backported from MIPS (Cobalt). - * - * Revision 1.4 1998/03/29 16:05:02 calle - * changes from 2.0 tree merged. - * - * Revision 1.1.2.9 1998/03/20 14:30:02 calle - * added cardnr to detect if you try to add same T1 to different io address. - * change number of nccis depending on number of channels. - * - * Revision 1.1.2.8 1998/03/04 17:32:33 calle - * Changes for T1. - * - * Revision 1.1.2.7 1998/02/27 15:38:29 calle - * T1 running with slow link. - * - * Revision 1.1.2.6 1998/02/24 17:57:36 calle - * changes for T1. - * - * Revision 1.3 1998/01/31 10:54:37 calle - * include changes for PCMCIA cards from 2.0 version - * - * Revision 1.2 1997/12/10 19:38:42 calle - * get changes from 2.0 tree - * - * Revision 1.1.2.2 1997/11/26 16:57:26 calle - * more changes for B1/M1/T1. - * - * Revision 1.1.2.1 1997/11/26 10:47:01 calle - * prepared for M1 (Mobile) and T1 (PMX) cards. - * prepared to set configuration after load to support other D-channel - * protocols, point-to-point and leased lines. - * - * Revision 1.1 1997/03/04 21:27:32 calle - * First version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - */ - -#ifndef _B1LLI_H_ -#define _B1LLI_H_ -/* - * struct for loading t4 file - */ -typedef struct avmb1_t4file { - int len; - unsigned char *data; -} avmb1_t4file; - -typedef struct avmb1_loaddef { - int contr; - avmb1_t4file t4file; -} avmb1_loaddef; - -typedef struct avmb1_loadandconfigdef { - int contr; - avmb1_t4file t4file; - avmb1_t4file t4config; -} avmb1_loadandconfigdef; - -typedef struct avmb1_resetdef { - int contr; -} avmb1_resetdef; - -typedef struct avmb1_getdef { - int contr; - int cardtype; - int cardstate; -} avmb1_getdef; - -/* - * struct for adding new cards - */ -typedef struct avmb1_carddef { - int port; - int irq; -} avmb1_carddef; - -#define AVM_CARDTYPE_B1 0 -#define AVM_CARDTYPE_T1 1 -#define AVM_CARDTYPE_M1 2 -#define AVM_CARDTYPE_M2 3 - -typedef struct avmb1_extcarddef { - int port; - int irq; - int cardtype; - int cardnr; /* for HEMA/T1 */ -} avmb1_extcarddef; - -#define AVMB1_LOAD 0 /* load image to card */ -#define AVMB1_ADDCARD 1 /* add a new card */ -#define AVMB1_RESETCARD 2 /* reset a card */ -#define AVMB1_LOAD_AND_CONFIG 3 /* load image and config to card */ -#define AVMB1_ADDCARD_WITH_TYPE 4 /* add a new card, with cardtype */ -#define AVMB1_GET_CARDINFO 5 /* get cardtype */ -#define AVMB1_REMOVECARD 6 /* remove a card (usefull for T1) */ - -#define AVMB1_REGISTERCARD_IS_OBSOLETE - -#endif /* _B1LLI_H_ */ diff --git a/include/linux/b1pcmcia.h b/include/linux/b1pcmcia.h deleted file mode 100644 index 595d51f4..00000000 --- a/include/linux/b1pcmcia.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * $Id$ - * - * Exported functions of module b1pcmcia to be called by - * avm_cs card services module. - * - * Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - */ - -#ifndef _B1PCMCIA_H_ -#define _B1PCMCIA_H_ - -int b1pcmcia_addcard_b1(unsigned int port, unsigned irq); -int b1pcmcia_addcard_m1(unsigned int port, unsigned irq); -int b1pcmcia_addcard_m2(unsigned int port, unsigned irq); -int b1pcmcia_delcard(unsigned int port, unsigned irq); - -#endif /* _B1PCMCIA_H_ */ diff --git a/include/linux/capi.h b/include/linux/capi.h deleted file mode 100644 index 8af03422..00000000 --- a/include/linux/capi.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * $Id$ - * - * CAPI 2.0 Interface for Linux - * - * Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.3 2000/03/08 17:06:34 calle - * - changes for devfs and 2.3.49 - * - capifs now configurable (no need with devfs) - * - New Middleware ioctl CAPI_NCCI_GETUNIT - * - Middleware again tested with 2.2.14 and 2.3.49 (with and without devfs) - * - * Revision 1.2 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.1 1997/03/04 21:27:33 calle - * First version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - * - */ - -#ifndef __LINUX_CAPI_H__ -#define __LINUX_CAPI_H__ - -#include -#include -#ifndef __KERNEL__ -#include -#endif - -/* - * CAPI_REGISTER - */ - -typedef struct capi_register_params { /* CAPI_REGISTER */ - __u32 level3cnt; /* No. of simulatneous user data connections */ - __u32 datablkcnt; /* No. of buffered data messages */ - __u32 datablklen; /* Size of buffered data messages */ -} capi_register_params; - -#define CAPI_REGISTER _IOW('C',0x01,struct capi_register_params) - -/* - * CAPI_GET_MANUFACTURER - */ - -#define CAPI_MANUFACTURER_LEN 64 - -#define CAPI_GET_MANUFACTURER _IOWR('C',0x06,CAPI_MANUFACTURER_LEN) - -/* - * CAPI_GET_VERSION - */ - -typedef struct capi_version { - __u32 majorversion; - __u32 minorversion; - __u32 majormanuversion; - __u32 minormanuversion; -} capi_version; - -#define CAPI_GET_VERSION _IOWR('C',0x07,struct capi_version) - -/* - * CAPI_GET_SERIAL - */ - -#define CAPI_SERIAL_LEN 8 -#define CAPI_GET_SERIAL _IOWR('C',0x08, CAPI_SERIAL_LEN) - -/* - * CAPI_GET_PROFILE - */ - -typedef struct capi_profile { - __u16 ncontroller; /* number of installed controller */ - __u16 nbchannel; /* number of B-Channels */ - __u32 goptions; /* global options */ - __u32 support1; /* B1 protocols support */ - __u32 support2; /* B2 protocols support */ - __u32 support3; /* B3 protocols support */ - __u32 reserved[6]; /* reserved */ - __u32 manu[5]; /* manufacturer specific information */ -} capi_profile; - -#define CAPI_GET_PROFILE _IOWR('C',0x09,struct capi_profile) - -typedef struct capi_manufacturer_cmd { - unsigned long cmd; - void *data; -} capi_manufacturer_cmd; - -/* - * CAPI_MANUFACTURER_CMD - */ - -#define CAPI_MANUFACTURER_CMD _IOWR('C',0x20, struct capi_manufacturer_cmd) - -/* - * CAPI_GET_ERRCODE - * capi errcode is set, * if read, write, or ioctl returns EIO, - * ioctl returns errcode directly, and in arg, if != 0 - */ - -#define CAPI_GET_ERRCODE _IOR('C',0x21, __u16) - -/* - * CAPI_INSTALLED - */ -#define CAPI_INSTALLED _IOR('C',0x22, __u16) - - -/* - * member contr is input for - * CAPI_GET_MANUFACTURER, CAPI_VERSION, CAPI_GET_SERIAL - * and CAPI_GET_PROFILE - */ -typedef union capi_ioctl_struct { - __u32 contr; - capi_register_params rparams; - __u8 manufacturer[CAPI_MANUFACTURER_LEN]; - capi_version version; - __u8 serial[CAPI_SERIAL_LEN]; - capi_profile profile; - capi_manufacturer_cmd cmd; - __u16 errcode; -} capi_ioctl_struct; - -/* - * Middleware extension - */ - -#define CAPIFLAG_HIGHJACKING 0x0001 - -#define CAPI_GET_FLAGS _IOR('C',0x23, unsigned) -#define CAPI_SET_FLAGS _IOR('C',0x24, unsigned) -#define CAPI_CLR_FLAGS _IOR('C',0x25, unsigned) - -#define CAPI_NCCI_OPENCOUNT _IOR('C',0x26, unsigned) - -#define CAPI_NCCI_GETUNIT _IOR('C',0x27, unsigned) - -#endif /* __LINUX_CAPI_H__ */ diff --git a/include/linux/concap.h b/include/linux/concap.h deleted file mode 100644 index 3f1d84eb..00000000 --- a/include/linux/concap.h +++ /dev/null @@ -1,110 +0,0 @@ -/* $Id$ -*/ -#ifndef _LINUX_CONCAP_H -#define _LINUX_CONCAP_H -#ifdef __KERNEL__ -#include -#include -#include - -/* Stuff to support encapsulation protocols genericly. The encapsulation - protocol is processed at the uppermost layer of the network interface. - - (c) 1997 by Henner Eisen - This software is subject to the GNU General Public License. - - Based on a ideas developed in a 'synchronous device' thread in the - linux-x25 mailing list contributed by Alan Cox, Thomasz Motylewski - and Jonathan Naylor. - - For more documetation on this refer to Documentation/isdn/README.concap - */ - -struct concap_proto_ops; -struct concap_device_ops; - -/* this manages all data needed by the encapsulation protocol - */ -struct concap_proto{ - struct net_device *net_dev; /* net device using our service */ - struct concap_device_ops *dops; /* callbacks provided by device */ - struct concap_proto_ops *pops; /* callbacks provided by us */ - int flags; - void *proto_data; /* protocol specific private data, to - be accessed via *pops methods only*/ - /* - : - whatever - : - */ -}; - -/* Operations to be supported by the net device. Called by the encapsulation - * protocol entity. No receive method is offered because the encapsulation - * protocol directly calls netif_rx(). - */ -struct concap_device_ops{ - - /* to request data is submitted by device*/ - int (*data_req)(struct concap_proto *, struct sk_buff *); - - /* Control methods must be set to NULL by devices which do not - support connection control.*/ - /* to request a connection is set up */ - int (*connect_req)(struct concap_proto *); - - /* to request a connection is released */ - int (*disconn_req)(struct concap_proto *); -}; - -/* Operations to be supported by the encapsulation protocol. Called by - * device driver. - */ -struct concap_proto_ops{ - - /* create a new encapsulation protocol instance of same type */ - struct concap_proto * (*proto_new) (void); - - /* delete encapsulation protocol instance and free all its resources. - cprot may no loger be referenced after calling this */ - void (*proto_del)(struct concap_proto *cprot); - - /* initialize the protocol's data. To be called at interface startup - or when the device driver resets the interface. All services of the - encapsulation protocol may be used after this*/ - int (*restart)(struct concap_proto *cprot, - struct net_device *ndev, - struct concap_device_ops *dops); - - /* inactivate an encapsulation protocol instance. The encapsulation - protocol may not call any *dops methods after this. */ - int (*close)(struct concap_proto *cprot); - - /* process a frame handed down to us by upper layer */ - int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb); - - /* to be called for each data entity received from lower layer*/ - int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb); - - /* to be called when a connection was set up/down. - Protocols that don't process these primitives might fill in - dummy methods here */ - int (*connect_ind)(struct concap_proto *cprot); - int (*disconn_ind)(struct concap_proto *cprot); - /* - Some network device support functions, like net_header(), rebuild_header(), - and others, that depend solely on the encapsulation protocol, might - be provided here, too. The net device would just fill them in its - corresponding fields when it is opened. - */ -}; - -/* dummy restart/close/connect/reset/disconn methods - */ -extern int concap_nop(struct concap_proto *cprot); - -/* dummy submit method - */ -extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb); -#endif -#endif diff --git a/include/linux/hysdn_if.h b/include/linux/hysdn_if.h deleted file mode 100644 index c5d2eef1..00000000 --- a/include/linux/hysdn_if.h +++ /dev/null @@ -1,45 +0,0 @@ -/* $Id$ - - * Linux driver for HYSDN cards, ioctl definitions shared by hynetmgr and driver. - * 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. - * - * $Log$ - * - */ - -/****************/ -/* error values */ -/****************/ -#define ERR_NONE 0 /* no error occured */ -#define ERR_ALREADY_BOOT 1000 /* we are already booting */ -#define EPOF_BAD_MAGIC 1001 /* bad magic in POF header */ -#define ERR_BOARD_DPRAM 1002 /* board DPRAM failed */ -#define EPOF_INTERNAL 1003 /* internal POF handler error */ -#define EPOF_BAD_IMG_SIZE 1004 /* POF boot image size invalid */ -#define ERR_BOOTIMG_FAIL 1005 /* 1. stage boot image did not start */ -#define ERR_BOOTSEQ_FAIL 1006 /* 2. stage boot seq handshake timeout */ -#define ERR_POF_TIMEOUT 1007 /* timeout waiting for card pof ready */ -#define ERR_NOT_BOOTED 1008 /* operation only allowed when booted */ -#define ERR_CONF_LONG 1009 /* conf line is to long */ -#define ERR_INV_CHAN 1010 /* invalid channel number */ -#define ERR_ASYNC_TIME 1011 /* timeout sending async data */ - - - - diff --git a/include/linux/isdn.h b/include/linux/isdn.h deleted file mode 100644 index e4d3bf65..00000000 --- a/include/linux/isdn.h +++ /dev/null @@ -1,1183 +0,0 @@ -/* $Id$ - * - * Main header for the Linux ISDN subsystem (linklevel). - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg - * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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. - * - * $Log$ - * Revision 1.94 2000/02/26 00:29:40 keil - * more softnet changes - * - * Revision 1.93 2000/02/25 11:29:17 paul - * changed chargetime to ulong from int (after about 20 days the "chargetime of - * ipppX is now 1234" message displays a negative number on alpha). - * - * Revision 1.92 2000/02/17 13:15:56 keil - * fix backward compatibility for 2.2 - * - * Revision 1.91 2000/02/16 14:56:27 paul - * translated ISDN_MODEM_ANZREG to ISDN_MODEM_NUMREG for english speakers - * - * Revision 1.90 2000/02/06 21:50:00 detabc - * add rewriting of socket's and frame's saddr for udp-ipv4 dynip-connections. - * Include checksum-recompute of ip- and udp-header's. - * - * Revision 1.89 2000/02/05 22:11:33 detabc - * Add rewriting of socket's and frame's saddr adressfield for - * dynip-connections. Only for tcp/ipv4 and switchable per interface. - * Include checksum-recompute of ip- and tcp-header's. - * - * Revision 1.88 2000/01/20 19:59:43 keil - * Add FAX Class 1 support - * - * Revision 1.87 2000/01/09 20:43:15 detabc - * exand logical bind-group's for both call's (in and out). - * add first part of kernel-config-help for abc-extension. - * - * Revision 1.86 1999/12/05 16:06:09 detabc - * add resethandling for rawip-compression. - * at now all B2-Protocols are usable with rawip-compression - * - * Revision 1.85 1999/11/30 11:29:06 detabc - * add a on the fly frame-counter and limit - * - * Revision 1.84 1999/11/28 14:49:08 detabc - * In case of rawip-compress adjust dev[x]->ibytes/obytes to reflect the - * uncompressed size. - * - * Revision 1.83 1999/11/26 15:54:59 detabc - * added compression (isdn_bsdcompress) for rawip interfaces with x75i B2-protocol. - * - * Revision 1.82 1999/11/20 22:14:14 detabc - * added channel dial-skip in case of external use - * (isdn phone or another isdn device) on the same NTBA. - * usefull with two or more card's connected the different NTBA's. - * global switchable in kernel-config and also per netinterface. - * - * add auto disable of netinterface's in case of: - * to many connection's in short time. - * config mistakes (wrong encapsulation, B2-protokoll or so on) on local - * or remote side. - * wrong password's or something else to a ISP (syncppp). - * - * possible encapsulations for this future are: - * ISDN_NET_ENCAP_SYNCPPP, ISDN_NET_ENCAP_UIHDLC, ISDN_NET_ENCAP_RAWIP, - * and ISDN_NET_ENCAP_CISCOHDLCK. - * - * Revision 1.81 1999/10/27 21:21:18 detabc - * Added support for building logically-bind-group's per interface. - * usefull for outgoing call's with more then one isdn-card. - * - * Switchable support to dont reset the hangup-timeout for - * receive frames. Most part's of the timru-rules for receiving frames - * are now obsolete. If the input- or forwarding-firewall deny - * the frame, the line will be not hold open. - * - * Revision 1.80 1999/10/26 21:09:29 armin - * New bufferlen for phonenumber only with kernel 2.3.x - * - * Revision 1.79 1999/10/16 17:52:38 keil - * Changing the MSN length need new data versions - * - * Revision 1.78 1999/10/08 18:59:33 armin - * Bugfix of too small MSN buffer and checking phone number - * in isdn_tty_getdial() - * - * Revision 1.77 1999/09/23 22:22:42 detabc - * added tcp-keepalive-detect with local response (ipv4 only) - * added host-only-interface support - * (source ipaddr == interface ipaddr) (ipv4 only) - * ok with kernel 2.3.18 and 2.2.12 - * - * Revision 1.76 1999/09/14 10:16:21 keil - * change ABC include - * - * Revision 1.75 1999/09/13 23:25:17 he - * serialized xmitting frames from isdn_ppp and BSENT statcallb - * - * Revision 1.74 1999/09/12 16:19:39 detabc - * added abc features - * low cost routing for net-interfaces (only the HL side). - * need more implementation in the isdnlog-utility - * udp info support (first part). - * different EAZ on outgoing call's. - * more checks on D-Channel callbacks (double use of channels). - * tested and running with kernel 2.3.17 - * - * Revision 1.73 1999/09/06 07:29:36 fritz - * Changed my mail-address. - * - * Revision 1.72 1999/09/04 22:20:19 detabc - * - * Revision 1.71 1999/08/23 15:54:22 keil - * more backported changes from kernel 2.3.14 - * - * Revision 1.70 1999/07/31 12:59:58 armin - * Added tty fax capabilities. - * - * Revision 1.69 1999/07/13 20:47:53 werner - * added channel bit ISDN_USAGE_DISABLED for limiting b-channel access. - * - * Revision 1.68 1999/07/11 17:07:37 armin - * Added tty modem register S23. - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * - * Revision 1.67 1999/07/07 10:17:24 detabc - * remove unused messages - * - * Revision 1.66 1999/07/01 08:35:37 keil - * compatibility to 2.3 - * - * Revision 1.65 1999/06/10 11:51:27 paul - * fixed comment for NET_DV - * - * Revision 1.64 1999/04/18 14:57:14 fritz - * Removed TIMRU stuff - * - * Revision 1.63 1999/04/18 14:07:18 fritz - * Removed TIMRU stuff. - * - * Revision 1.62 1999/04/12 13:16:54 fritz - * Changes from 2.0 tree. - * - * Revision 1.61 1999/03/02 11:43:21 armin - * Added variable to store connect-message of Modem. - * Added Timer-define for RegS7 (Wait for Carrier). - * - * Revision 1.60 1998/10/25 14:50:29 fritz - * Backported from MIPS (Cobalt). - * - * Revision 1.59 1998/10/23 10:18:55 paul - * Implementation of "dialmode" (successor of "status") - * You also need current isdnctrl for this! - * - * Revision 1.58 1998/10/23 10:10:06 fritz - * Test-Checkin - * - * Revision 1.57 1998/08/31 21:10:01 he - * new ioctl IIOCNETGPN for /dev/isdninfo (get network interface' - * peer phone number) - * - * Revision 1.56 1998/07/26 18:46:52 armin - * Added silence detection in voice receive mode. - * - * Revision 1.55 1998/06/26 15:13:17 fritz - * Added handling of STAT_ICALL with incomplete CPN. - * Added AT&L for ttyI emulator. - * Added more locking stuff in tty_write. - * - * Revision 1.54 1998/06/18 23:32:01 fritz - * Replaced cli()/restore_flags() in isdn_tty_write() by locking. - * Removed direct-senddown feature in isdn_tty_write because it will - * never succeed with locking and is useless anyway. - * - * Revision 1.53 1998/06/17 19:51:51 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.46 1998/04/14 16:28:59 he - * Fixed user space access with interrupts off and remaining - * copy_{to,from}_user() -> -EFAULT return codes - * - * Revision 1.45 1998/03/24 16:33:12 hipp - * More CCP changes. BSD compression now "works" on a local loopback link. - * Moved some isdn_ppp stuff from isdn.h to isdn_ppp.h - * - * Revision 1.44 1998/03/22 18:50:56 hipp - * Added BSD Compression for syncPPP .. UNTESTED at the moment - * - * Revision 1.43 1998/03/09 17:46:44 he - * merged in 2.1.89 changes - * - * - * Revision 1.40 1998/03/08 01:08:29 fritz - * Increased NET_DV because of TIMRU - * - * Revision 1.39 1998/03/07 22:42:49 fritz - * Starting generic module support (Nothing usable yet). - * - * Revision 1.38 1998/03/07 18:21:29 cal - * Dynamic Timeout-Rule-Handling vs. 971110 included - * - * Revision 1.37 1998/02/22 19:45:24 fritz - * Some changes regarding V.110 - * - * Revision 1.36 1998/02/20 17:35:55 fritz - * Added V.110 stuff. - * - * Revision 1.35 1998/01/31 22:14:14 keil - * changes for 2.1.82 - * - * Revision 1.34 1997/10/09 21:28:11 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.33 1997/08/21 14:44:22 fritz - * Moved triggercps to end of struct for backwards-compatibility. - * - * Revision 1.32 1997/08/21 09:49:46 fritz - * Increased NET_DV - * - * Revision 1.31 1997/06/22 11:57:07 fritz - * Added ability to adjust slave triggerlevel. - * - * Revision 1.30 1997/06/17 13:07:23 hipp - * compression changes , MP changes - * - * Revision 1.29 1997/05/27 15:18:02 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.28 1997/03/07 01:33:01 fritz - * Added proper ifdef's for CONFIG_ISDN_AUDIO - * - * Revision 1.27 1997/03/05 21:11:49 fritz - * Minor fixes. - * - * Revision 1.26 1997/02/28 02:37:53 fritz - * Added some comments. - * - * Revision 1.25 1997/02/23 16:54:23 hipp - * some initial changes for future PPP compresion - * - * Revision 1.24 1997/02/18 09:42:45 fritz - * Bugfix: Increased ISDN_MODEM_ANZREG. - * Increased TTY_DV. - * - * Revision 1.23 1997/02/10 22:07:13 fritz - * Added 2 modem registers for numbering plan and screening info. - * - * Revision 1.22 1997/02/03 23:42:08 fritz - * Added ISDN_TIMER_RINGING - * Misc. changes for Kernel 2.1.X compatibility - * - * Revision 1.21 1997/01/17 01:19:10 fritz - * Applied chargeint patch. - * - * Revision 1.20 1997/01/17 00:41:19 fritz - * Increased TTY_DV. - * - * Revision 1.19 1997/01/14 01:41:07 fritz - * Added ATI2 related variables. - * Added variables for audio support in skbuffs. - * - * Revision 1.18 1996/11/06 17:37:50 keil - * more changes for 2.1.X - * - * Revision 1.17 1996/09/07 12:53:57 hipp - * moved a few isdn_ppp.c specific defines to drives/isdn/isdn_ppp.h - * - * Revision 1.16 1996/08/12 16:20:56 hipp - * renamed ppp_minor to ppp_slot - * - * Revision 1.15 1996/06/15 14:56:57 fritz - * Added version signatures for data structures used - * by userlevel programs. - * - * Revision 1.14 1996/06/06 21:24:23 fritz - * Started adding support for suspend/resume. - * - * Revision 1.13 1996/06/05 02:18:20 fritz - * Added DTMF decoding stuff. - * - * Revision 1.12 1996/06/03 19:55:08 fritz - * Fixed typos. - * - * Revision 1.11 1996/05/31 01:37:47 fritz - * Minor changes, due to changes in isdn_tty.c - * - * Revision 1.10 1996/05/18 01:37:18 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.9 1996/05/17 03:58:20 fritz - * Added flags for DLE handling. - * - * Revision 1.8 1996/05/11 21:49:55 fritz - * Removed queue management variables. - * Changed queue management to use sk_buffs. - * - * Revision 1.7 1996/05/07 09:10:06 fritz - * Reorganized tty-related structs. - * - * Revision 1.6 1996/05/06 11:38:27 hipp - * minor change in ippp struct - * - * Revision 1.5 1996/04/30 11:03:16 fritz - * Added Michael's ippp-bind patch. - * - * Revision 1.4 1996/04/29 23:00:02 fritz - * Added variables for voice-support. - * - * Revision 1.3 1996/04/20 16:54:58 fritz - * Increased maximum number of channels. - * Added some flags for isdn_net to handle callback more reliable. - * Fixed delay-definitions to be more accurate. - * Misc. typos - * - * Revision 1.2 1996/02/11 02:10:02 fritz - * Changed IOCTL-names - * Added rx_netdev, st_netdev, first_skb, org_hcb, and org_hcu to - * Netdevice-local struct. - * - * Revision 1.1 1996/01/10 20:55:07 fritz - * Initial revision - * - */ - -#ifndef isdn_h -#define isdn_h - -#include -#include -#include - -#define ISDN_TTY_MAJOR 43 -#define ISDN_TTYAUX_MAJOR 44 -#define ISDN_MAJOR 45 - -/* The minor-devicenumbers for Channel 0 and 1 are used as arguments for - * physical Channel-Mapping, so they MUST NOT be changed without changing - * the correspondent code in isdn.c - */ - -#ifdef CONFIG_COBALT_MICRO_SERVER -/* Save memory */ -#define ISDN_MAX_DRIVERS 2 -#define ISDN_MAX_CHANNELS 8 -#else -#define ISDN_MAX_DRIVERS 32 -#define ISDN_MAX_CHANNELS 64 -#endif -#define ISDN_MINOR_B 0 -#define ISDN_MINOR_BMAX (ISDN_MAX_CHANNELS-1) -#define ISDN_MINOR_CTRL 64 -#define ISDN_MINOR_CTRLMAX (64 + (ISDN_MAX_CHANNELS-1)) -#define ISDN_MINOR_PPP 128 -#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_IPV4_TCP_KEEPALIVE -#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR -#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER -#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND -#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE -#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR -#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS -#undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT -#undef CONFIG_ISDN_WITH_ABC_IPV4_RW_SOCKADDR -#undef CONFIG_ISDN_WITH_ABC_IPV4_RWUDP_SOCKADDR -#else -#include - -#define ISDN_DW_ABC_FLAG_NO_TCP_KEEPALIVE 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_DYNADDR 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_RW_SOCKADDR 0x00000400L -#define ISDN_DW_ABC_FLAG_RWUDP_SOCKADDR 0x00000800L - -#define ISDN_DW_ABC_IFFLAG_NODCHAN 0x00000001L -#define ISDN_DW_ABC_IFFLAG_BSDAKTIV 0x00000002L -#define ISDN_DW_ABC_IFFLAG_RSTREMOTE 0x00000004L - -#define ISDN_DW_ABC_BITLOCK_SEND 0 -#define ISDN_DW_ABC_BITLOCK_RECEIVE 1 - -#define ISDN_DW_ABC_MAX_CH_P_RIVER (32) -#endif - - -/* New ioctl-codes */ -#define IIOCNETAIF _IO('I',1) -#define IIOCNETDIF _IO('I',2) -#define IIOCNETSCF _IO('I',3) -#define IIOCNETGCF _IO('I',4) -#define IIOCNETANM _IO('I',5) -#define IIOCNETDNM _IO('I',6) -#define IIOCNETGNM _IO('I',7) -#define IIOCGETSET _IO('I',8) /* no longer supported */ -#define IIOCSETSET _IO('I',9) /* no longer supported */ -#define IIOCSETVER _IO('I',10) -#define IIOCNETHUP _IO('I',11) -#define IIOCSETGST _IO('I',12) -#define IIOCSETBRJ _IO('I',13) -#define IIOCSIGPRF _IO('I',14) -#define IIOCGETPRF _IO('I',15) -#define IIOCSETPRF _IO('I',16) -#define IIOCGETMAP _IO('I',17) -#define IIOCSETMAP _IO('I',18) -#define IIOCNETASL _IO('I',19) -#define IIOCNETDIL _IO('I',20) -#define IIOCGETCPS _IO('I',21) -#define IIOCGETDVR _IO('I',22) -#define IIOCNETLCR _IO('I',23) /* dwabc ioctl for LCR from isdnlog */ -#define IIOCNETDWRSET _IO('I',24) /* dwabc ioctl to reset abc-values to default on a net-interface */ - -#define IIOCNETALN _IO('I',32) -#define IIOCNETDLN _IO('I',33) - -#define IIOCNETGPN _IO('I',34) - -#define IIOCDBGVAR _IO('I',127) - -#define IIOCDRVCTL _IO('I',128) - -/* Packet encapsulations for net-interfaces */ -#define ISDN_NET_ENCAP_ETHER 0 -#define ISDN_NET_ENCAP_RAWIP 1 -#define ISDN_NET_ENCAP_IPTYP 2 -#define ISDN_NET_ENCAP_CISCOHDLC 3 /* Without SLARP and keepalive */ -#define ISDN_NET_ENCAP_SYNCPPP 4 -#define ISDN_NET_ENCAP_UIHDLC 5 -#define ISDN_NET_ENCAP_CISCOHDLCK 6 /* With SLARP and keepalive */ -#define ISDN_NET_ENCAP_X25IFACE 7 /* Documentation/networking/x25-iface.txt*/ -#define ISDN_NET_ENCAP_MAX_ENCAP ISDN_NET_ENCAP_X25IFACE -/* Facility which currently uses an ISDN-channel */ -#define ISDN_USAGE_NONE 0 -#define ISDN_USAGE_RAW 1 -#define ISDN_USAGE_MODEM 2 -#define ISDN_USAGE_NET 3 -#define ISDN_USAGE_VOICE 4 -#define ISDN_USAGE_FAX 5 -#define ISDN_USAGE_MASK 7 /* Mask to get plain usage */ -#define ISDN_USAGE_DISABLED 32 /* This bit is set, if channel is disabled */ -#define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */ -#define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing */ - -#define ISDN_MODEM_NUMREG 24 /* Number of Modem-Registers */ -#define ISDN_LMSNLEN 255 /* Length of tty's Listen-MSN string */ -#define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */ - -#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 */ - -typedef struct { - char drvid[25]; - unsigned long arg; -} isdn_ioctl_struct; - -typedef struct { - unsigned long isdndev; - unsigned long atmodem[ISDN_MAX_CHANNELS]; - unsigned long info[ISDN_MAX_CHANNELS]; -} debugvar_addr; - -typedef struct { - char name[10]; - char phone[ISDN_MSNLEN]; - int outgoing; -} isdn_net_ioctl_phone; - -typedef struct { - char name[10]; /* Name of interface */ - char master[10]; /* Name of Master for Bundling */ - char slave[10]; /* Name of Slave for Bundling */ - char eaz[256]; /* EAZ/MSN */ - char drvid[25]; /* DriverId for Bindings */ - int onhtime; /* Hangup-Timeout */ - int charge; /* Charge-Units */ - int l2_proto; /* Layer-2 protocol */ - int l3_proto; /* Layer-3 protocol */ - int p_encap; /* Encapsulation */ - int exclusive; /* Channel, if bound exclusive */ - int dialmax; /* Dial Retry-Counter */ - int slavedelay; /* Delay until slave starts up */ - int cbdelay; /* Delay before Callback */ - int chargehup; /* Flag: Charge-Hangup */ - int ihup; /* Flag: Hangup-Timeout on incoming line */ - int secure; /* Flag: Secure */ - int callback; /* Flag: Callback */ - int cbhup; /* Flag: Reject Call before Callback */ - int pppbind; /* ippp device for bindings */ - int chargeint; /* Use fixed charge interval length */ - int triggercps; /* BogoCPS needed for triggering slave */ - int dialtimeout; /* Dial-Timeout */ - int dialwait; /* Time to wait after failed dial */ - int dialmode; /* Flag: off / on / auto */ -} isdn_net_ioctl_cfg; - -#define ISDN_NET_DIALMODE_MASK 0xC0 /* bits for status */ -#define ISDN_NET_DM_OFF 0x00 /* this interface is stopped */ -#define ISDN_NET_DM_MANUAL 0x40 /* this interface is on (manual) */ -#define ISDN_NET_DM_AUTO 0x80 /* this interface is autodial */ -#define ISDN_NET_DIALMODE(x) ((&(x))->flags & ISDN_NET_DIALMODE_MASK) - -#ifdef __KERNEL__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_ISDN_PPP - -#ifdef CONFIG_ISDN_PPP_VJ -# include -#endif - -#include -#include -#include - -#include -#endif - -#ifdef CONFIG_ISDN_X25 -# include -#endif - -#ifdef HAVE_DEVFS_FS -#ifdef CONFIG_DEVFS_FS -# include -#endif -#endif /* HAVE_DEVFS_FS */ - -#include - -#define ISDN_DRVIOCTL_MASK 0x7f /* Mask for Device-ioctl */ - -/* Until now unused */ -#define ISDN_SERVICE_VOICE 1 -#define ISDN_SERVICE_AB 1<<1 -#define ISDN_SERVICE_X21 1<<2 -#define ISDN_SERVICE_G4 1<<3 -#define ISDN_SERVICE_BTX 1<<4 -#define ISDN_SERVICE_DFUE 1<<5 -#define ISDN_SERVICE_X25 1<<6 -#define ISDN_SERVICE_TTX 1<<7 -#define ISDN_SERVICE_MIXED 1<<8 -#define ISDN_SERVICE_FW 1<<9 -#define ISDN_SERVICE_GTEL 1<<10 -#define ISDN_SERVICE_BTXN 1<<11 -#define ISDN_SERVICE_BTEL 1<<12 - -/* Macros checking plain usage */ -#define USG_NONE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NONE) -#define USG_RAW(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_RAW) -#define USG_MODEM(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) -#define USG_VOICE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE) -#define USG_NET(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NET) -#define USG_FAX(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_FAX) -#define USG_OUTGOING(x) ((x & ISDN_USAGE_OUTGOING)==ISDN_USAGE_OUTGOING) -#define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \ - ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE) ) - -/* Timer-delays and scheduling-flags */ -#define ISDN_TIMER_RES 3 /* Main Timer-Resolution */ -#define ISDN_TIMER_02SEC (HZ/(ISDN_TIMER_RES+1)/5) /* Slow-Timer1 .2 sec */ -#define ISDN_TIMER_1SEC (HZ/(ISDN_TIMER_RES+1)) /* Slow-Timer2 1 sec */ -#define ISDN_TIMER_RINGING 5 /* tty RINGs = ISDN_TIMER_1SEC * this factor */ -#define ISDN_TIMER_KEEPINT 10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */ -#define ISDN_TIMER_MODEMREAD 1 -#define ISDN_TIMER_MODEMPLUS 2 -#define ISDN_TIMER_MODEMRING 4 -#define ISDN_TIMER_MODEMXMIT 8 -#define ISDN_TIMER_NETDIAL 16 -#define ISDN_TIMER_NETHANGUP 32 -#define ISDN_TIMER_IPPP 64 -#define ISDN_TIMER_KEEPALIVE 128 /* Cisco-Keepalive */ -#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */ -#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \ - ISDN_TIMER_MODEMXMIT) -#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \ - ISDN_TIMER_NETDIAL | ISDN_TIMER_KEEPALIVE | \ - ISDN_TIMER_CARRIER) - -/* Timeout-Values for isdn_net_dial() */ -#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1))) -#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1))) -#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1))) - -/* GLOBAL_FLAGS */ -#define ISDN_GLOBAL_STOPPED 1 - -/*=================== Start of ip-over-ISDN stuff =========================*/ - -/* Feature- and status-flags for a net-interface */ -#define ISDN_NET_CONNECTED 0x01 /* Bound to ISDN-Channel */ -#define ISDN_NET_SECURE 0x02 /* Accept calls from phonelist only */ -#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 */ - -/* Phone-list-element */ -typedef struct { - void *next; - char num[ISDN_MSNLEN]; -} isdn_net_phone; - -/* - Principles when extending structures for generic encapsulation protocol - ("concap") support: - - Stuff which is hardware specific (here i4l-specific) goes in - the netdev -> local structure (here: isdn_net_local) - - Stuff which is encapsulation protocol specific goes in the structure - which holds the linux device structure (here: isdn_net_device) -*/ - -/* Local interface-data */ -typedef struct isdn_net_local_s { - ulong magic; - char name[10]; /* Name of device */ - struct enet_statistics stats; /* Ethernet Statistics */ - int isdn_device; /* Index to isdn-device */ - int isdn_channel; /* Index to isdn-channel */ - int ppp_slot; /* PPPD device slot number */ - int pre_device; /* Preselected isdn-device */ - int pre_channel; /* Preselected isdn-channel */ - int exclusive; /* If non-zero idx to reserved chan.*/ - int flags; /* Connection-flags */ - int dialretry; /* Counter for Dialout-retries */ - int dialmax; /* Max. Number of Dial-retries */ - int cbdelay; /* Delay before Callback starts */ - int dtimer; /* Timeout-counter for dialing */ - char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */ - u_char cbhup; /* Flag: Reject Call before Callback*/ - u_char dialstate; /* State for dialing */ - u_char p_encap; /* Packet encapsulation */ - /* 0 = Ethernet over ISDN */ - /* 1 = RAW-IP */ - /* 2 = IP with type field */ - u_char l2_proto; /* Layer-2-protocol */ - /* See ISDN_PROTO_L2..-constants in */ - /* isdnif.h */ - /* 0 = X75/LAPB with I-Frames */ - /* 1 = X75/LAPB with UI-Frames */ - /* 2 = X75/LAPB with BUI-Frames */ - /* 3 = HDLC */ - u_char l3_proto; /* Layer-3-protocol */ - /* See ISDN_PROTO_L3..-constants in */ - /* isdnif.h */ - /* 0 = Transparent */ - int huptimer; /* Timeout-counter for auto-hangup */ - int charge; /* Counter for charging units */ - ulong chargetime; /* Timer for Charging info */ - int hupflags; /* Flags for charge-unit-hangup: */ - /* bit0: chargeint is invalid */ - /* bit1: Getting charge-interval */ - /* bit2: Do charge-unit-hangup */ - /* bit3: Do hangup even on incoming */ - int outgoing; /* Flag: outgoing call */ - int onhtime; /* Time to keep link up */ - int chargeint; /* Interval between charge-infos */ - int onum; /* Flag: at least 1 outgoing number */ - int cps; /* current speed of this interface */ - int transcount; /* byte-counter for cps-calculation */ - int sqfull; /* Flag: netdev-queue overloaded */ - ulong sqfull_stamp; /* Start-Time of overload */ - ulong slavedelay; /* Dynamic bundling delaytime */ - int triggercps; /* BogoCPS needed for trigger slave */ - struct net_device *srobin; /* Ptr to Master device for slaves */ - isdn_net_phone *phone[2]; /* List of remote-phonenumbers */ - /* phone[0] = Incoming Numbers */ - /* phone[1] = Outgoing Numbers */ - isdn_net_phone *dial; /* Pointer to dialed number */ - struct net_device *master; /* Ptr to Master device for slaves */ - struct net_device *slave; /* Ptr to Slave device for masters */ - struct isdn_net_local_s *next; /* Ptr to next link in bundle */ - struct isdn_net_local_s *last; /* Ptr to last link in bundle */ - struct isdn_net_dev_s *netdev; /* Ptr to netdev */ - struct sk_buff *first_skb; /* Ptr to skb that triggers dialing */ - struct sk_buff *volatile sav_skb; /* Ptr to skb, rejected by LL-driver*/ - /* Ptr to orig. hard_header_cache */ - int (*org_hhc)( - struct neighbour *neigh, - struct hh_cache *hh); - /* Ptr to orig. header_cache_update */ - void (*org_hcu)(struct hh_cache *, - struct net_device *, - unsigned char *); - int pppbind; /* ippp device for bindings */ - int dialtimeout; /* How long shall we try on dialing? (jiffies) */ - int dialwait; /* How long shall we wait after failed attempt? (jiffies) */ - ulong dialstarted; /* jiffies of first dialing-attempt */ - ulong dialwait_timer; /* jiffies of earliest next dialing-attempt */ - int huptimeout; /* How long will the connection be up? (seconds) */ -#ifdef CONFIG_ISDN_X25 - struct concap_device_ops *dops; /* callbacks used by encapsulator */ -#endif - int cisco_loop; /* Loop counter for Cisco-SLARP */ - ulong cisco_myseq; /* Local keepalive seq. for Cisco */ - ulong cisco_yourseq; /* Remote keepalive seq. for Cisco */ -#ifdef CONFIG_ISDN_WITH_ABC - ulong dw_abc_flags; - ulong dw_abc_if_flags; - int dw_abc_inuse_secure; - volatile atomic_t dw_abc_pkt_onl; - ulong dw_abc_dialstart; - int dw_abc_old_onhtime; - struct sk_buff *dw_abc_next_skb; - 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 */ -typedef struct isdn_net_dev_s { - isdn_net_local *local; - isdn_net_local *queue; - void *next; /* Pointer to next isdn-interface */ - struct net_device dev; /* interface to upper levels */ -#ifdef CONFIG_ISDN_PPP - struct mpqueue *mp_last; - struct ippp_bundle ib; -#endif -#ifdef CONFIG_ISDN_X25 - struct concap_proto *cprot; /* connection oriented encapsulation protocol */ -#endif - -} isdn_net_dev; - -/*===================== End of ip-over-ISDN stuff ===========================*/ - -/*======================= Start of ISDN-tty stuff ===========================*/ - -#define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */ -#define ISDN_ASYNC_INITIALIZED 0x80000000 /* port was initialized */ -#define ISDN_ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device active */ -#define ISDN_ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device active */ -#define ISDN_ASYNC_CLOSING 0x08000000 /* Serial port is closing */ -#define ISDN_ASYNC_CTS_FLOW 0x04000000 /* Do CTS flow control */ -#define ISDN_ASYNC_CHECK_CD 0x02000000 /* i.e., CLOCAL */ -#define ISDN_ASYNC_HUP_NOTIFY 0x0001 /* Notify tty on hangups/closes */ -#define ISDN_ASYNC_SESSION_LOCKOUT 0x0100 /* Lock cua opens on session */ -#define ISDN_ASYNC_PGRP_LOCKOUT 0x0200 /* Lock cua opens on pgrp */ -#define ISDN_ASYNC_CALLOUT_NOHUP 0x0400 /* No hangup for cui */ -#define ISDN_ASYNC_SPLIT_TERMIOS 0x0008 /* Sep. termios for dialin/out */ -#define ISDN_SERIAL_XMIT_SIZE 1024 /* Default bufsize for write */ -#define ISDN_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */ -#define ISDN_SERIAL_TYPE_NORMAL 1 -#define ISDN_SERIAL_TYPE_CALLOUT 2 - -#ifdef CONFIG_ISDN_AUDIO -/* For using sk_buffs with audio we need some private variables - * within each sk_buff. For this purpose, we declare a struct here, - * and put it always at skb->head. A few macros help accessing the - * variables. Of course, we need to check skb_headroom prior to - * any access. - */ -typedef struct isdn_audio_skb { - unsigned short dle_count; - unsigned char lock; -} isdn_audio_skb; - -#define ISDN_AUDIO_SKB_DLECOUNT(skb) (((isdn_audio_skb*)skb->head)->dle_count) -#define ISDN_AUDIO_SKB_LOCK(skb) (((isdn_audio_skb*)skb->head)->lock) -#endif - -/* Private data of AT-command-interpreter */ -typedef struct atemu { - u_char profile[ISDN_MODEM_NUMREG]; /* Modem-Regs. Profile 0 */ - u_char mdmreg[ISDN_MODEM_NUMREG]; /* Modem-Registers */ - char pmsn[ISDN_MSNLEN]; /* EAZ/MSNs Profile 0 */ - char msn[ISDN_MSNLEN]; /* EAZ/MSN */ - char plmsn[ISDN_LMSNLEN]; /* Listening MSNs Profile 0 */ - char lmsn[ISDN_LMSNLEN]; /* Listening MSNs */ - char cpn[ISDN_MSNLEN]; /* CalledPartyNumber on incoming call */ - char connmsg[ISDN_CMSGLEN]; /* CONNECT-Msg from HL-Driver */ -#ifdef CONFIG_ISDN_AUDIO - u_char vpar[10]; /* Voice-parameters */ - int lastDLE; /* Flag for voice-coding: DLE seen */ -#endif - int mdmcmdl; /* Length of Modem-Commandbuffer */ - int pluscount; /* Counter for +++ sequence */ - int lastplus; /* Timestamp of last + */ - int carrierwait; /* Seconds of carrier waiting */ - char mdmcmd[255]; /* Modem-Commandbuffer */ - unsigned int charge; /* Charge units of current connection */ -} atemu; - -/* Private data (similar to async_struct in ) */ -typedef struct modem_info { - int magic; - int flags; /* defined in tty.h */ - int x_char; /* xon/xoff character */ - int mcr; /* Modem control register */ - int msr; /* Modem status register */ - int lsr; /* Line status register */ - int line; - int count; /* # of fd on device */ - int blocked_open; /* # of blocked opens */ - long session; /* Session of opening process */ - long pgrp; /* pgrp of opening process */ - int online; /* 1 = B-Channel is up, drop data */ - /* 2 = B-Channel is up, deliver d.*/ - int dialing; /* Dial in progress or ATA */ - int rcvsched; /* Receive needs schedule */ - int isdn_driver; /* Index to isdn-driver */ - int isdn_channel; /* Index to isdn-channel */ - int drv_index; /* Index to dev->usage */ - int ncarrier; /* Flag: schedule NO CARRIER */ - unsigned char last_cause[8]; /* Last cause message */ - unsigned char last_num[ISDN_MSNLEN]; - /* Last phone-number */ - unsigned char last_l2; /* Last layer-2 protocol */ - unsigned char last_si; /* Last service */ - unsigned char last_lhup; /* Last hangup local? */ - unsigned char last_dir; /* Last direction (in or out) */ - struct timer_list nc_timer; /* Timer for delayed NO CARRIER */ - int send_outstanding;/* # of outstanding send-requests */ - int xmit_size; /* max. # of chars in xmit_buf */ - int xmit_count; /* # of chars in xmit_buf */ - unsigned char *xmit_buf; /* transmit buffer */ - struct sk_buff_head xmit_queue; /* transmit queue */ - atomic_t xmit_lock; /* Semaphore for isdn_tty_write */ -#ifdef CONFIG_ISDN_AUDIO - int vonline; /* Voice-channel status */ - /* Bit 0 = recording */ - /* Bit 1 = playback */ - /* Bit 2 = playback, DLE-ETX seen */ - struct sk_buff_head dtmf_queue; /* queue for dtmf results */ - void *adpcms; /* state for adpcm decompression */ - void *adpcmr; /* state for adpcm compression */ - void *dtmf_state; /* state for dtmf decoder */ - void *silence_state; /* state for silence detection */ -#endif -#ifdef CONFIG_ISDN_TTY_FAX - struct T30_s *fax; /* T30 Fax Group 3 data/interface */ - int faxonline; /* Fax-channel status */ -#endif - struct tty_struct *tty; /* Pointer to corresponding tty */ - atemu emu; /* AT-emulator data */ - struct termios normal_termios; /* For saving termios structs */ - struct termios callout_termios; -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t open_wait, close_wait; -#else - struct wait_queue *open_wait; - struct wait_queue *close_wait; -#endif - struct semaphore write_sem; -} modem_info; - -#define ISDN_MODEM_WINSIZE 8 - -/* Description of one ISDN-tty */ -typedef struct { - int refcount; /* Number of opens */ - struct tty_driver tty_modem; /* tty-device */ - struct tty_driver cua_modem; /* cua-device */ - struct tty_struct *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */ - struct termios *modem_termios[ISDN_MAX_CHANNELS]; - struct termios *modem_termios_locked[ISDN_MAX_CHANNELS]; - modem_info info[ISDN_MAX_CHANNELS]; /* Private data */ -} modem; - -/*======================= End of ISDN-tty stuff ============================*/ - -/*======================== Start of V.110 stuff ============================*/ -#define V110_BUFSIZE 1024 - -typedef struct { - int nbytes; /* 1 Matrixbyte -> nbytes in stream */ - int nbits; /* Number of used bits in streambyte */ - unsigned char key; /* Bitmask in stream eg. 11 (nbits=2) */ - int decodelen; /* Amount of data in decodebuf */ - int SyncInit; /* Number of sync frames to send */ - unsigned char *OnlineFrame; /* Precalculated V110 idle frame */ - unsigned char *OfflineFrame; /* Precalculated V110 sync Frame */ - int framelen; /* Length of frames */ - int skbuser; /* Number of unacked userdata skbs */ - int skbidle; /* Number of unacked idle/sync skbs */ - int introducer; /* Local vars for decoder */ - int dbit; - unsigned char b; - int skbres; /* space to reserve in outgoing skb */ - int maxsize; /* maxbufsize of lowlevel driver */ - unsigned char *encodebuf; /* temporary buffer for encoding */ - unsigned char decodebuf[V110_BUFSIZE]; /* incomplete V110 matrices */ -} isdn_v110_stream; - -/*========================= End of V.110 stuff =============================*/ - -/*======================= Start of general stuff ===========================*/ - -typedef struct { - char *next; - char *private; -} infostruct; - -typedef struct isdn_module { - struct isdn_module *prev; - struct isdn_module *next; - char *name; - int (*get_free_channel)(int, int, int, int, int); - int (*free_channel)(int, int, int); - int (*status_callback)(isdn_ctrl *); - int (*command)(isdn_ctrl *); - int (*receive_callback)(int, int, struct sk_buff *); - int (*writebuf_skb)(int, int, int, struct sk_buff *); - int (*net_start_xmit)(struct sk_buff *, struct net_device *); - int (*net_receive)(struct net_device *, struct sk_buff *); - int (*net_open)(struct net_device *); - int (*net_close)(struct net_device *); - int priority; -} isdn_module; - -#define DRV_FLAG_RUNNING 1 -#define DRV_FLAG_REJBUS 2 -#define DRV_FLAG_LOADED 4 - -/* Description of hardware-level-driver */ -typedef struct { - ulong online; /* Channel-Online flags */ - ulong flags; /* Misc driver Flags */ - int locks; /* Number of locks for this driver */ - int channels; /* Number of channels */ -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t st_waitq; /* Wait-Queue for status-read's */ -#else - struct wait_queue *st_waitq; /* Wait-Queue for status-read's */ -#endif - int maxbufsize; /* Maximum Buffersize supported */ - unsigned long pktcount; /* Until now: unused */ - int stavail; /* Chars avail on Status-device */ - isdn_if *interface; /* Interface to driver */ - int *rcverr; /* Error-counters for B-Ch.-receive */ - int *rcvcount; /* Byte-counters for B-Ch.-receive */ -#ifdef CONFIG_ISDN_AUDIO - unsigned long DLEflag; /* Flags: Insert DLE at next read */ -#endif - struct sk_buff_head *rpqueue; /* Pointers to start of Rcv-Queue */ -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t *rcv_waitq; /* Wait-Queues for B-Channel-Reads */ - wait_queue_head_t *snd_waitq; /* Wait-Queue for B-Channel-Send's */ -#else - struct wait_queue **rcv_waitq; /* Wait-Queues for B-Channel-Reads */ - struct wait_queue **snd_waitq; /* Wait-Queue for B-Channel-Send's */ -#endif - char msn2eaz[10][ISDN_MSNLEN]; /* Mapping-Table MSN->EAZ */ -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - u_char dwabc_lchmap[ISDN_DW_ABC_MAX_CH_P_RIVER]; /* locically channelmap */ - u_long dwabc_lch_use; /* lasttime a locical chanelmap was set */ -#endif -} driver; - -/* Main driver-data */ -typedef struct isdn_devt { - unsigned short flags; /* Bitmapped Flags: */ - /* */ - int drivers; /* Current number of drivers */ - int channels; /* Current number of channels */ - int net_verbose; /* Verbose-Flag */ - int modempoll; /* Flag: tty-read active */ - int tflags; /* Timer-Flags: */ - /* see ISDN_TIMER_..defines */ - int global_flags; - infostruct *infochain; /* List of open info-devs. */ -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */ -#else - struct wait_queue *info_waitq; /* Wait-Queue for isdninfo */ -#endif - 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.... */ - driver *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */ - isdn_net_dev *netdev; /* Linked list of net-if's */ - char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */ - struct task_struct *profd; /* For iprofd */ - modem mdm; /* tty-driver-data */ - isdn_net_dev *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers */ - isdn_net_dev *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers */ - ulong ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes */ - ulong obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes */ - int v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */ - atomic_t v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */ - isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */ - struct semaphore sem; /* serialize list access*/ - isdn_module *modules; - unsigned long global_features; -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND - u_long dwabc_lch_check; /* lasttime a locical chanelmap checked */ -#endif -#ifdef HAVE_DEVFS_FS -#ifdef CONFIG_DEVFS_FS - devfs_handle_t devfs_handle_isdninfo; - devfs_handle_t devfs_handle_isdnctrl; - devfs_handle_t devfs_handle_isdnX[ISDN_MAX_CHANNELS]; - devfs_handle_t devfs_handle_isdnctrlX[ISDN_MAX_CHANNELS]; -#ifdef CONFIG_ISDN_PPP - 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 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 void isdn_dw_abc_lcr_ioctl(u_long); -extern void isdn_dw_abc_lcr_clear(isdn_net_local *); -extern void isdn_dw_abc_free_lch_with_pch(int,int); -#endif -#ifdef CONFIG_ISDN_WITH_ABC_UDP_CHECK -extern int dw_abc_udp_test(struct sk_buff *skb,struct net_device *ndev); -#endif -#if CONFIG_ISDN_WITH_ABC_IPV4_TCP_KEEPALIVE || CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR -struct sk_buff *isdn_dw_abc_ip4_keepalive_test(struct net_device *ndev,struct sk_buff *skb); -#endif -#ifdef CONFIG_ISDN_WITH_ABC_ICALL_BIND -extern int isdn_dwabc_check_icall_bind(isdn_net_local *,int,int); -extern int dwabc_isdn_get_net_free_channel(isdn_net_local *); -#endif -#endif - - -/* Utility-Macros */ -#define MIN(a,b) ((ab)?a:b) -#ifdef COMPAT_NO_SOFTNET -/* - * 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 */ -#endif /* __KERNEL__ */ -#endif /* isdn_h */ diff --git a/include/linux/isdn_compat.h b/include/linux/isdn_compat.h deleted file mode 100644 index 4eae693b..00000000 --- a/include/linux/isdn_compat.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifdef __KERNEL__ -/* Compatibility for various Linux kernel versions */ - -#ifndef _LINUX_ISDN_COMPAT_H -#define _LINUX_ISDN_COMPAT_H - -#ifndef LINUX_VERSION_CODE -#include -#endif - -#ifndef KERNEL_VERSION -#define KERNEL_VERSION(x,y,z) (((x)<<16)+((y)<<8)+(z)) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,0) -#include - -#define ioremap vremap -#define ioremap_nocache vremap -#define iounmap vfree - -static inline unsigned long copy_from_user(void *to, const void *from, unsigned long n) -{ - int i; - if ((i = verify_area(VERIFY_READ, from, n)) != 0) - return i; - memcpy_fromfs(to, from, n); - return 0; -} - -static inline unsigned long copy_to_user(void *to, const void *from, unsigned long n) -{ - int i; - if ((i = verify_area(VERIFY_WRITE, to, n)) != 0) - return i; - memcpy_tofs(to, from, n); - return 0; -} - -#define GET_USER(x, addr) ( x = get_user(addr) ) -#ifdef __alpha__ /* needed for 2.0.x with alpha-patches */ -#define RWTYPE long -#define LSTYPE long -#define RWARG unsigned long -#else -#define RWTYPE int -#define LSTYPE int -#define RWARG int -#endif -#define LSARG off_t -#else -#define COMPAT_NEED_UACCESS -#define GET_USER get_user -#define PUT_USER put_user -#define RWTYPE long -#define LSTYPE long long -#define RWARG unsigned long -#define LSARG long long -#endif /* LINUX_VERSION_CODE */ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,15) -#define SET_SKB_FREE(x) ( x->free = 1 ) -#define idev_kfree_skb(a,b) dev_kfree_skb(a,b) -#define idev_kfree_skb_irq(a,b) dev_kfree_skb(a,b) -#define idev_kfree_skb_any(a,b) dev_kfree_skb(a,b) -#else -#define SET_SKB_FREE(x) -#define idev_kfree_skb(a,b) dev_kfree_skb(a) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) -#define idev_kfree_skb_irq(a,b) dev_kfree_skb(a) -#define idev_kfree_skb_any(a,b) dev_kfree_skb(a) -#else -#define idev_kfree_skb_irq(a,b) dev_kfree_skb_irq(a) -#define idev_kfree_skb_any(a,b) dev_kfree_skb_any(a) -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,18) -#define COMPAT_HAS_NEW_SYMTAB -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,31) -#define CLOSETYPE void -#define CLOSEVAL -#else -#define CLOSETYPE int -#define CLOSEVAL (0) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,37) -#define test_and_clear_bit clear_bit -#define test_and_set_bit set_bit -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,45) -#define MINOR_PART(f) MINOR(f->f_inode->i_rdev) -#else -#define MINOR_PART(f) MINOR(f->f_dentry->d_inode->i_rdev) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,81) -#define kstat_irqs( PAR ) kstat.interrupts[PAR] -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,89) -#define poll_wait(f,wq,w) poll_wait((wq),(w)) -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,91) -#define COMPAT_HAS_NEW_PCI -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13) -#define get_pcibase(ps, nr) ps->base_address[nr] -#else -#define get_pcibase(ps, nr) ps->resource[nr].start -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,118) -#define FILEOP_HAS_FLUSH -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,127) -#define schedule_timeout(a) current->timeout = jiffies + (a); schedule (); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,0) -#define COMPAT_HAS_NEW_WAITQ -#define BIG_PHONE_NUMBERS -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,12) -#define COMPAT_HAS_NEW_SETUP -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,14) -#define net_device device -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,16) -#define set_current_state(sta) (current->state = sta) -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,22) -#define COMPAT_HAS_ISA_IOREMAP -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,43) -#define COMPAT_NO_SOFTNET -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,47) -#define netif_running(d) test_bit(LINK_STATE_START, &d->state) -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,45) -#define HAVE_DEVFS_FS -#else -#define devfs_register_chrdev(m,n,f) register_chrdev(m,n,f) -#define devfs_unregister_chrdev(m,n) unregister_chrdev(m,n) -#endif - -#endif /* __KERNEL__ */ -#endif /* _LINUX_ISDN_COMPAT_H */ diff --git a/include/linux/isdn_divertif.h b/include/linux/isdn_divertif.h deleted file mode 100644 index 66e5efec..00000000 --- a/include/linux/isdn_divertif.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * $Id$ - * - * Header for the diversion supplementary interface for i4l. - * - * Copyright 1998 by Werner Cornelius (werner@isdn4linux.de) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * 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. - * - * $Log$ - * Revision 1.2 1999/07/04 21:38:38 werner - * ported from kernel version 2.0 - * - * - */ - - -/***********************************************************/ -/* magic value is also used to control version information */ -/***********************************************************/ -#define DIVERT_IF_MAGIC 0x25873401 -#define DIVERT_CMD_REG 0x00 /* register command */ -#define DIVERT_CMD_REL 0x01 /* release command */ -#define DIVERT_NO_ERR 0x00 /* return value no error */ -#define DIVERT_CMD_ERR 0x01 /* invalid cmd */ -#define DIVERT_VER_ERR 0x02 /* magic/version invalid */ -#define DIVERT_REG_ERR 0x03 /* module already registered */ -#define DIVERT_REL_ERR 0x04 /* module not registered */ -#define DIVERT_REG_NAME isdn_register_divert - -/***************************************************************/ -/* structure exchanging data between isdn hl and divert module */ -/***************************************************************/ -typedef struct - { ulong if_magic; /* magic info and version */ - int cmd; /* command */ - int (*stat_callback)(isdn_ctrl *); /* supplied by divert module when calling */ - 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 */ - } isdn_divert_if; - -/*********************/ -/* function register */ -/*********************/ -extern int DIVERT_REG_NAME(isdn_divert_if *); diff --git a/include/linux/isdn_dwabc.h b/include/linux/isdn_dwabc.h deleted file mode 100644 index 472dd14d..00000000 --- a/include/linux/isdn_dwabc.h +++ /dev/null @@ -1,60 +0,0 @@ -/* $Id$ - * - * Header for the Linux ISDN abc-extension. - * - * Author: 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. - * - * 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. - * - * $Log$ - * Revision 1.2 1999/09/14 10:16:21 keil - * change ABC include - * - * Revision 1.1 1999/09/12 16:19:40 detabc - * added abc features - * low cost routing for net-interfaces (only the HL side). - * need more implementation in the isdnlog-utility - * udp info support (first part). - * different EAZ on outgoing call's. - * more checks on D-Channel callbacks (double use of channels). - * tested and running with kernel 2.3.17 - * - */ - -#ifndef ISDN_DWABC_H -#define ISDN_DWABC_H - -#ifdef __KERNEL__ -#include -#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 diff --git a/include/linux/isdn_lzscomp.h b/include/linux/isdn_lzscomp.h deleted file mode 100644 index 360e6055..00000000 --- a/include/linux/isdn_lzscomp.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * $Id$ - * - * Header for isdn_lzscomp.c - * Concentrated here to not mess up half a dozen kernel headers with code - * snippets - * - */ - -#define CI_LZS_COMPRESS 17 -#define CILEN_LZS_COMPRESS 5 - -#define LZS_CMODE_NONE 0 -#define LZS_CMODE_LCB 1 -#define LZS_CMODE_CRC 2 -#define LZS_CMODE_SEQNO 3 /* MUST be implemented (default) */ -#define LZS_CMODE_EXT 4 /* Seems to be what Win0.95 uses */ - -#define LZS_COMP_MAX_HISTS 1 /* Don't waste peers ressources */ -#define LZS_COMP_DEF_HISTS 1 /* Most likely to negotiate */ -#define LZS_DECOMP_MAX_HISTS 32 /* More is really nonsense */ -#define LZS_DECOMP_DEF_HISTS 8 /* If we get it, this may be optimal */ - -#define LZS_HIST_BYTE1(word) (word>>8) /* Just for better reading */ -#define LZS_HIST_BYTE2(word) (word&0xff) /* of this big endian stuff */ -#define LZS_HIST_WORD(b1,b2) ((b1<<8)|b2) /* (network byte order rulez) */ diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h deleted file mode 100644 index 9ca7dc7c..00000000 --- a/include/linux/isdn_ppp.h +++ /dev/null @@ -1,241 +0,0 @@ -/* -*- mode: c; c-basic-offset: 2 -*- */ - -#ifndef _LINUX_ISDN_PPP_H -#define _LINUX_ISDN_PPP_H - -#include -#include - -#define CALLTYPE_INCOMING 0x1 -#define CALLTYPE_OUTGOING 0x2 -#define CALLTYPE_CALLBACK 0x4 - -#define IPPP_VERSION "2.2.0" - -struct pppcallinfo -{ - int calltype; - unsigned char local_num[64]; - unsigned char remote_num[64]; - int charge_units; -}; - -#define PPPIOCGCALLINFO _IOWR('t',128,struct pppcallinfo) -#define PPPIOCBUNDLE _IOW('t',129,int) -#define PPPIOCGMPFLAGS _IOR('t',130,int) -#define PPPIOCSMPFLAGS _IOW('t',131,int) -#define PPPIOCSMPMTU _IOW('t',132,int) -#define PPPIOCSMPMRU _IOW('t',133,int) -#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long [8]) -#define PPPIOCSCOMPRESSOR _IOW('t',135,int) -#define PPPIOCGIFNAME _IOR('t',136, char [IFNAMSIZ] ) - -#define PPP_MP 0x003d -#define PPP_LINK_COMP 0x00fb -#define PPP_LINK_CCP 0x80fb - -#define SC_MP_PROT 0x00000200 -#define SC_REJ_MP_PROT 0x00000400 -#define SC_OUT_SHORT_SEQ 0x00000800 -#define SC_IN_SHORT_SEQ 0x00004000 - -#define SC_DECOMP_ON 0x01 -#define SC_COMP_ON 0x02 -#define SC_DECOMP_DISCARD 0x04 -#define SC_COMP_DISCARD 0x08 -#define SC_LINK_DECOMP_ON 0x10 -#define SC_LINK_COMP_ON 0x20 -#define SC_LINK_DECOMP_DISCARD 0x40 -#define SC_LINK_COMP_DISCARD 0x80 - -#define DECOMP_ERR_NOMEM (-10) - -#define MP_END_FRAG 0x40 -#define MP_BEGIN_FRAG 0x80 - -#define ISDN_PPP_COMP_MAX_OPTIONS 16 - -#define IPPP_COMP_FLAG_XMIT 0x1 -#define IPPP_COMP_FLAG_LINK 0x2 - -struct isdn_ppp_comp_data { - int num; - unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS]; - int optlen; - int flags; -}; - -#ifdef __KERNEL__ - -/* - * We need a way for the decompressor to influence the generation of CCP - * Reset-Requests in a variety of ways. The decompressor is already returning - * a lot of information (generated skb length, error conditions) so we use - * another parameter. This parameter is a pointer to a structure which is - * to be marked valid by the decompressor and only in this case is ever used. - * Furthermore, the only case where this data is used is when the decom- - * pressor returns DECOMP_ERROR. - * - * We use this same struct for the reset entry of the compressor to commu- - * nicate to its caller how to deal with sending of a Reset Ack. In this - * case, expra is not used, but other options still apply (supressing - * sending with rsend, appending arbitrary data, etc). - */ - -#define IPPP_RESET_MAXDATABYTES 32 - -struct isdn_ppp_resetparams { - unsigned char valid:1; /* rw Is this structure filled at all ? */ - unsigned char rsend:1; /* rw Should we send one at all ? */ - unsigned char idval:1; /* rw Is the id field valid ? */ - unsigned char dtval:1; /* rw Is the data field valid ? */ - unsigned char expra:1; /* rw Is an Ack expected for this Req ? */ - unsigned char id; /* wo Send CCP ResetReq with this id */ - unsigned short maxdlen; /* ro Max bytes to be stored in data field */ - unsigned short dlen; /* rw Bytes stored in data field */ - unsigned char *data; /* wo Data for ResetReq info field */ -}; - -/* - * this is an 'old friend' from ppp-comp.h under a new name - * check the original include for more information - */ -struct isdn_ppp_compressor { - struct isdn_ppp_compressor *next, *prev; - int num; /* CCP compression protocol number */ - - void *(*alloc) (struct isdn_ppp_comp_data *); - void (*free) (void *state); - int (*init) (void *state, struct isdn_ppp_comp_data *, - int unit,int debug); - - /* The reset entry needs to get more exact information about the - ResetReq or ResetAck it was called with. The parameters are - obvious. If reset is called without a Req or Ack frame which - could be handed into it, code MUST be set to 0. Using rsparm, - the reset entry can control if and how a ResetAck is returned. */ - - void (*reset) (void *state, unsigned char code, unsigned char id, - unsigned char *data, unsigned len, - struct isdn_ppp_resetparams *rsparm); - - int (*compress) (void *state, struct sk_buff *in, - struct sk_buff *skb_out, int proto); - - int (*decompress) (void *state,struct sk_buff *in, - struct sk_buff *skb_out, - struct isdn_ppp_resetparams *rsparm); - - void (*incomp) (void *state, struct sk_buff *in,int proto); - void (*stat) (void *state, struct compstat *stats); -}; - -extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *); -extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *); -extern int isdn_ppp_dial_slave(char *); -extern int isdn_ppp_hangup_slave(char *); - -struct ippp_bundle { - int mp_mrru; /* unused */ - struct mpqueue *last; /* currently defined in isdn_net_dev */ - int min; /* currently calculated 'on the fly' */ - long next_num; /* we wanna see this seq.-number next */ - struct sqqueue *sq; - int modify:1; /* set to 1 while modifying sqqueue */ - int bundled:1; /* bundle active ? */ -}; - -#define NUM_RCV_BUFFS 64 - -struct sqqueue { - struct sqqueue *next; - long sqno_start; - long sqno_end; - struct sk_buff *skb; - long timer; -}; - -struct mpqueue { - struct mpqueue *next; - struct mpqueue *last; - long sqno; - struct sk_buff *skb; - int BEbyte; - unsigned long time; -}; - -struct ippp_buf_queue { - struct ippp_buf_queue *next; - struct ippp_buf_queue *last; - char *buf; /* NULL here indicates end of queue */ - int len; -}; - -/* The data structure for one CCP reset transaction */ -enum ippp_ccp_reset_states { - CCPResetIdle, - CCPResetSentReq, - CCPResetRcvdReq, - CCPResetSentAck, - CCPResetRcvdAck -}; - -struct ippp_ccp_reset_state { - enum ippp_ccp_reset_states state; /* State of this transaction */ - struct ippp_struct *is; /* Backlink to device stuff */ - unsigned char id; /* Backlink id index */ - unsigned char ta:1; /* The timer is active (flag) */ - unsigned char expra:1; /* We expect a ResetAck at all */ - int dlen; /* Databytes stored in data */ - struct timer_list timer; /* For timeouts/retries */ - /* This is a hack but seems sufficient for the moment. We do not want - to have this be yet another allocation for some bytes, it is more - memory management overhead than the whole mess is worth. */ - unsigned char data[IPPP_RESET_MAXDATABYTES]; -}; - -/* The data structure keeping track of the currently outstanding CCP Reset - transactions. */ -struct ippp_ccp_reset { - struct ippp_ccp_reset_state *rs[256]; /* One per possible id */ - unsigned char lastid; /* Last id allocated by the engine */ -}; - -struct ippp_struct { - struct ippp_struct *next_link; - int state; - struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */ - struct ippp_buf_queue *first; /* pointer to (current) first packet */ - struct ippp_buf_queue *last; /* pointer to (current) last used packet in queue */ -#ifdef COMPAT_HAS_NEW_WAITQ - wait_queue_head_t wq; -#else - struct wait_queue *wq; -#endif - struct task_struct *tk; - unsigned int mpppcfg; - unsigned int pppcfg; - unsigned int mru; - unsigned int mpmru; - unsigned int mpmtu; - unsigned int maxcid; - struct isdn_net_local_s *lp; - int unit; - int minor; - long last_link_seqno; - long mp_seqno; - long range; -#ifdef CONFIG_ISDN_PPP_VJ - unsigned char *cbuf; - struct slcompress *slcomp; -#endif - unsigned long debug; - struct isdn_ppp_compressor *compressor,*decompressor; - struct isdn_ppp_compressor *link_compressor,*link_decompressor; - void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat; - struct ippp_ccp_reset *reset; /* Allocated on demand, may never be needed */ - unsigned long compflags; -}; - -#endif /* __KERNEL__ */ -#endif /* _LINUX_ISDN_PPP_H */ diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h deleted file mode 100644 index 5b66e8e3..00000000 --- a/include/linux/isdnif.h +++ /dev/null @@ -1,664 +0,0 @@ -/* $Id$ - * - * Linux ISDN subsystem - * - * Definition of the interface between the subsystem and its low-level drivers. - * - * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de) - * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg - * - * 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. - * - * $Log$ - * Revision 1.32 1999/10/11 22:03:00 keil - * COMPAT_NEED_UACCESS (no include in isdn_compat.h) - * - * Revision 1.31 1999/09/06 07:29:36 fritz - * Changed my mail-address. - * - * Revision 1.30 1999/08/23 15:54:29 keil - * more backported changes from kernel 2.3.14 - * - * Revision 1.29 1999/07/31 13:00:02 armin - * Added tty fax capabilities. - * - * Revision 1.28 1999/07/13 20:57:48 werner - * added callback ISDN_STAT_DISCH for limiting b-channel resources. - * - * Revision 1.27 1999/07/11 17:07:39 armin - * Added tty modem register S23. - * Added new layer 2 and 3 protocols for Fax and DSP functions. - * - * Revision 1.26 1999/07/01 08:35:44 keil - * compatibility to 2.3 - * - * Revision 1.25 1998/06/17 19:51:55 he - * merged with 2.1.10[34] (cosmetics and udelay() -> mdelay()) - * brute force fix to avoid Ugh's in isdn_tty_write() - * cleaned up some dead code - * - * Revision 1.24 1998/03/19 13:18:57 keil - * Start of a CAPI like interface for supplementary Service - * first service: SUSPEND - * - * Revision 1.23 1998/02/20 17:36:52 fritz - * Added L2-protocols for V.110, changed FEATURE-Flag-constants. - * - * Revision 1.22 1998/01/31 22:14:12 keil - * changes for 2.1.82 - * - * Revision 1.21 1997/10/09 21:28:13 fritz - * New HL<->LL interface: - * New BSENT callback with nr. of bytes included. - * Sending without ACK. - * New L1 error status (not yet in use). - * Cleaned up obsolete structures. - * Implemented Cisco-SLARP. - * Changed local net-interface data to be dynamically allocated. - * Removed old 2.0 compatibility stuff. - * - * Revision 1.20 1997/05/27 15:18:06 fritz - * Added changes for recent 2.1.x kernels: - * changed return type of isdn_close - * queue_task_* -> queue_task - * clear/set_bit -> test_and_... where apropriate. - * changed type of hard_header_cache parameter. - * - * Revision 1.19 1997/03/25 23:13:56 keil - * NI-1 US protocol - * - * Revision 1.18 1997/03/04 22:09:18 calle - * Change macros copy_from_user and copy_to_user in inline function. - * These are now correct replacements of the functions for 2.1.xx - * - * Revision 1.17 1997/02/10 21:12:53 fritz - * More setup-interface changes. - * - * Revision 1.16 1997/02/10 19:42:57 fritz - * New interface for reporting incoming calls. - * - * Revision 1.15 1997/02/09 00:18:42 keil - * leased line support - * - * Revision 1.14 1997/02/03 23:43:00 fritz - * Misc changes for Kernel 2.1.X compatibility. - * - * Revision 1.13 1996/11/13 02:39:59 fritz - * More compatibility changes. - * - * Revision 1.12 1996/11/06 17:38:48 keil - * more changes for 2.1.X - * - * Revision 1.11 1996/10/23 11:59:42 fritz - * More compatibility changes. - * - * Revision 1.10 1996/10/22 23:14:19 fritz - * Changes for compatibility to 2.0.X and 2.1.X kernels. - * - * Revision 1.9 1996/06/06 21:24:24 fritz - * Started adding support for suspend/resume. - * - * Revision 1.8 1996/05/18 01:45:37 fritz - * More spelling corrections. - * - * Revision 1.7 1996/05/18 01:37:19 fritz - * Added spelling corrections and some minor changes - * to stay in sync with kernel. - * - * Revision 1.6 1996/05/17 03:59:28 fritz - * Marked rcvcallb and writebuf obsolete. - * - * Revision 1.5 1996/05/01 11:43:54 fritz - * Removed STANDALONE - * - * Revision 1.4 1996/05/01 11:38:40 fritz - * Added ISDN_FEATURE_L2_TRANS - * - * Revision 1.3 1996/04/29 22:57:54 fritz - * Added driverId and channel parameters to - * writecmd() and readstat(). - * Added constant for voice-support. - * - * Revision 1.2 1996/04/20 17:02:40 fritz - * Changes to support skbuffs for Lowlevel-Drivers. - * Misc. typos - * - * Revision 1.1 1996/01/09 05:50:51 fritz - * Initial revision - * - */ - -#ifndef isdnif_h -#define isdnif_h - -#include -#include - -/* - * Values for general protocol-selection - */ -#define ISDN_PTYPE_UNKNOWN 0 /* Protocol undefined */ -#define ISDN_PTYPE_1TR6 1 /* german 1TR6-protocol */ -#define ISDN_PTYPE_EURO 2 /* EDSS1-protocol */ -#define ISDN_PTYPE_LEASED 3 /* for leased lines */ -#define ISDN_PTYPE_NI1 4 /* US NI-1 protocol */ -#define ISDN_PTYPE_MAX 7 /* Max. 8 Protocols */ - -/* - * Values for Layer-2-protocol-selection - */ -#define ISDN_PROTO_L2_X75I 0 /* X75/LAPB with I-Frames */ -#define ISDN_PROTO_L2_X75UI 1 /* X75/LAPB with UI-Frames */ -#define ISDN_PROTO_L2_X75BUI 2 /* X75/LAPB with UI-Frames */ -#define ISDN_PROTO_L2_HDLC 3 /* HDLC */ -#define ISDN_PROTO_L2_TRANS 4 /* Transparent (Voice) */ -#define ISDN_PROTO_L2_X25DTE 5 /* X25/LAPB DTE mode */ -#define ISDN_PROTO_L2_X25DCE 6 /* X25/LAPB DCE mode */ -#define ISDN_PROTO_L2_V11096 7 /* V.110 bitrate adaption 9600 Baud */ -#define ISDN_PROTO_L2_V11019 8 /* V.110 bitrate adaption 19200 Baud */ -#define ISDN_PROTO_L2_V11038 9 /* V.110 bitrate adaption 38400 Baud */ -#define ISDN_PROTO_L2_MODEM 10 /* Analog Modem on Board */ -#define ISDN_PROTO_L2_FAX 11 /* Fax Group 2/3 */ -#define ISDN_PROTO_L2_MAX 15 /* Max. 16 Protocols */ - -/* - * Values for Layer-3-protocol-selection - */ -#define ISDN_PROTO_L3_TRANS 0 /* Transparent */ -#define ISDN_PROTO_L3_TRANSDSP 1 /* Transparent with DSP */ -#define ISDN_PROTO_L3_FCLASS2 2 /* Fax Group 2/3 CLASS 2 */ -#define ISDN_PROTO_L3_FCLASS1 3 /* Fax Group 2/3 CLASS 1 */ -#define ISDN_PROTO_L3_MAX 7 /* Max. 8 Protocols */ - -#ifdef __KERNEL__ - -#include - -/***************************************************************************/ -/* Extensions made by Werner Cornelius (werner@ikt.de) */ -/* */ -/* The proceed command holds a incoming call in a state to leave processes */ -/* enough time to check whether ist should be accepted. */ -/* The PROT_IO Command extends the interface to make protocol dependant */ -/* features available (call diversion, call waiting...). */ -/* */ -/* The PROT_IO Command is executed with the desired driver id and the arg */ -/* parameter coded as follows: */ -/* The lower 8 bits of arg contain the desired protocol from ISDN_PTYPE */ -/* definitions. The upper 24 bits represent the protocol specific cmd/stat.*/ -/* Any additional data is protocol and command specific. */ -/* This mechanism also applies to the statcallb callback STAT_PROT. */ -/* */ -/* This suggested extension permits an easy expansion of protocol specific */ -/* handling. Extensions may be added at any time without changing the HL */ -/* driver code and not getting conflicts without certifications. */ -/* The well known CAPI 2.0 interface handles such extensions in a similar */ -/* way. Perhaps a protocol specific module may be added and separately */ -/* loaded and linked to the basic isdn module for handling. */ -/***************************************************************************/ - -/*****************/ -/* DSS1 commands */ -/*****************/ -#define DSS1_CMD_INVOKE ((0x00 << 8) | ISDN_PTYPE_EURO) /* invoke a supplementary service */ -#define DSS1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_EURO) /* abort a invoke cmd */ - -/*******************************/ -/* DSS1 Status callback values */ -/*******************************/ -#define DSS1_STAT_INVOKE_RES ((0x80 << 8) | ISDN_PTYPE_EURO) /* Result for invocation */ -#define DSS1_STAT_INVOKE_ERR ((0x81 << 8) | ISDN_PTYPE_EURO) /* Error Return for invocation */ -#define DSS1_STAT_INVOKE_BRD ((0x82 << 8) | ISDN_PTYPE_EURO) /* Deliver invoke broadcast info */ - - -/*********************************************************************/ -/* structures for DSS1 commands and callback */ -/* */ -/* An action is invoked by sending a DSS1_CMD_INVOKE. The ll_id, proc*/ -/* timeout, datalen and data fields must be set before calling. */ -/* */ -/* The return value is a positive hl_id value also delivered in the */ -/* hl_id field. A value of zero signals no more left hl_id capacitys.*/ -/* A negative return value signals errors in LL. So if the return */ -/* value is <= 0 no action in LL will be taken -> request ignored */ -/* */ -/* The timeout field must be filled with a positive value specifying */ -/* the amount of time the INVOKED process waits for a reaction from */ -/* the network. */ -/* If a response (either error or result) is received during this */ -/* intervall, a reporting callback is initiated and the process will */ -/* be deleted, the hl identifier will be freed. */ -/* If no response is received during the specified intervall, a error*/ -/* callback is initiated with timeout set to -1 and a datalen set */ -/* to 0. */ -/* If timeout is set to a value <= 0 during INVOCATION the process is*/ -/* immediately deleted after sending the data. No callback occurs ! */ -/* */ -/* A currently waiting process may be aborted with INVOKE_ABORT. No */ -/* callback will occur when a process has been aborted. */ -/* */ -/* Broadcast invoke frames from the network are reported via the */ -/* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */ -/* are supplied by the network and not by the HL. */ -/*********************************************************************/ -typedef struct - { ulong ll_id; /* ID supplied by LL when executing */ - /* a command and returned by HL for */ - /* INVOKE_RES and INVOKE_ERR */ - int hl_id; /* ID supplied by HL when called */ - /* for executing a cmd and delivered */ - /* for results and errors */ - /* must be supplied by LL when aborting*/ - int proc; /* invoke procedure used by CMD_INVOKE */ - /* returned by callback and broadcast */ - int timeout; /* timeout for INVOKE CMD in ms */ - /* -1 in stat callback when timed out */ - /* error value when error callback */ - int datalen; /* length of cmd or stat data */ - u_char *data;/* pointer to data delivered or send */ - } dss1_cmd_stat; - -/* - * Commands from linklevel to lowlevel - * - */ -#define ISDN_CMD_IOCTL 0 /* Perform ioctl */ -#define ISDN_CMD_DIAL 1 /* Dial out */ -#define ISDN_CMD_ACCEPTD 2 /* Accept an incoming call on D-Chan. */ -#define ISDN_CMD_ACCEPTB 3 /* Request B-Channel connect. */ -#define ISDN_CMD_HANGUP 4 /* Hangup */ -#define ISDN_CMD_CLREAZ 5 /* Clear EAZ(s) of channel */ -#define ISDN_CMD_SETEAZ 6 /* Set EAZ(s) of channel */ -#define ISDN_CMD_GETEAZ 7 /* Get EAZ(s) of channel */ -#define ISDN_CMD_SETSIL 8 /* Set Service-Indicator-List of channel */ -#define ISDN_CMD_GETSIL 9 /* Get Service-Indicator-List of channel */ -#define ISDN_CMD_SETL2 10 /* Set B-Chan. Layer2-Parameter */ -#define ISDN_CMD_GETL2 11 /* Get B-Chan. Layer2-Parameter */ -#define ISDN_CMD_SETL3 12 /* Set B-Chan. Layer3-Parameter */ -#define ISDN_CMD_GETL3 13 /* Get B-Chan. Layer3-Parameter */ -#define ISDN_CMD_LOCK 14 /* Signal usage by upper levels */ -#define ISDN_CMD_UNLOCK 15 /* Release usage-lock */ -#define ISDN_CMD_SUSPEND 16 /* Suspend connection */ -#define ISDN_CMD_RESUME 17 /* Resume connection */ -#define ISDN_CMD_PROCEED 18 /* Proceed with call establishment */ -#define ISDN_CMD_ALERT 19 /* Alert after Proceeding */ -#define ISDN_CMD_REDIR 20 /* Redir a incoming call */ -#define ISDN_CMD_PROT_IO 21 /* Protocol specific commands */ -#define CAPI_PUT_MESSAGE 22 /* CAPI message send down or up */ -#define ISDN_CMD_FAXCMD 23 /* FAX commands to HL-driver */ -#define ISDN_CMD_AUDIO 24 /* DSP, DTMF, ... settings */ - -/* - * Status-Values delivered from lowlevel to linklevel via - * statcallb(). - * - */ -#define ISDN_STAT_STAVAIL 256 /* Raw status-data available */ -#define ISDN_STAT_ICALL 257 /* Incoming call detected */ -#define ISDN_STAT_RUN 258 /* Signal protocol-code is running */ -#define ISDN_STAT_STOP 259 /* Signal halt of protocol-code */ -#define ISDN_STAT_DCONN 260 /* Signal D-Channel connect */ -#define ISDN_STAT_BCONN 261 /* Signal B-Channel connect */ -#define ISDN_STAT_DHUP 262 /* Signal D-Channel disconnect */ -#define ISDN_STAT_BHUP 263 /* Signal B-Channel disconnect */ -#define ISDN_STAT_CINF 264 /* Charge-Info */ -#define ISDN_STAT_LOAD 265 /* Signal new lowlevel-driver is loaded */ -#define ISDN_STAT_UNLOAD 266 /* Signal unload of lowlevel-driver */ -#define ISDN_STAT_BSENT 267 /* Signal packet sent */ -#define ISDN_STAT_NODCH 268 /* Signal no D-Channel */ -#define ISDN_STAT_ADDCH 269 /* Add more Channels */ -#define ISDN_STAT_CAUSE 270 /* Cause-Message */ -#define ISDN_STAT_ICALLW 271 /* Incoming call without B-chan waiting */ -#define ISDN_STAT_REDIR 272 /* Redir result */ -#define ISDN_STAT_PROT 273 /* protocol IO specific callback */ -#define ISDN_STAT_DISPLAY 274 /* deliver a received display message */ -#define ISDN_STAT_L1ERR 275 /* Signal Layer-1 Error */ -#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 */ - -/* - * Audio commands - */ -#define ISDN_AUDIO_SETDD 0 /* Set DTMF detection */ -#define ISDN_AUDIO_DTMF 1 /* Rx/Tx DTMF */ - -/* - * Values for errcode field - */ -#define ISDN_STAT_L1ERR_SEND 1 -#define ISDN_STAT_L1ERR_RECV 2 - -/* - * Values for feature-field of interface-struct. - */ -/* Layer 2 */ -#define ISDN_FEATURE_L2_X75I (0x0001 << ISDN_PROTO_L2_X75I) -#define ISDN_FEATURE_L2_X75UI (0x0001 << ISDN_PROTO_L2_X75UI) -#define ISDN_FEATURE_L2_X75BUI (0x0001 << ISDN_PROTO_L2_X75BUI) -#define ISDN_FEATURE_L2_HDLC (0x0001 << ISDN_PROTO_L2_HDLC) -#define ISDN_FEATURE_L2_TRANS (0x0001 << ISDN_PROTO_L2_TRANS) -#define ISDN_FEATURE_L2_X25DTE (0x0001 << ISDN_PROTO_L2_X25DTE) -#define ISDN_FEATURE_L2_X25DCE (0x0001 << ISDN_PROTO_L2_X25DCE) -#define ISDN_FEATURE_L2_V11096 (0x0001 << ISDN_PROTO_L2_V11096) -#define ISDN_FEATURE_L2_V11019 (0x0001 << ISDN_PROTO_L2_V11019) -#define ISDN_FEATURE_L2_V11038 (0x0001 << ISDN_PROTO_L2_V11038) -#define ISDN_FEATURE_L2_MODEM (0x0001 << ISDN_PROTO_L2_MODEM) -#define ISDN_FEATURE_L2_FAX (0x0001 << ISDN_PROTO_L2_FAX) - -#define ISDN_FEATURE_L2_MASK (0x0FFFF) /* Max. 16 protocols */ -#define ISDN_FEATURE_L2_SHIFT (0) - -/* Layer 3 */ -#define ISDN_FEATURE_L3_TRANS (0x10000 << ISDN_PROTO_L3_TRANS) -#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP) -#define ISDN_FEATURE_L3_FCLASS2 (0x10000 << ISDN_PROTO_L3_FCLASS2) -#define ISDN_FEATURE_L3_FCLASS1 (0x10000 << ISDN_PROTO_L3_FCLASS1) - -#define ISDN_FEATURE_L3_MASK (0x0FF0000) /* Max. 8 Protocols */ -#define ISDN_FEATURE_L3_SHIFT (16) - -/* Signaling */ -#define ISDN_FEATURE_P_UNKNOWN (0x1000000 << ISDN_PTYPE_UNKNOWN) -#define ISDN_FEATURE_P_1TR6 (0x1000000 << ISDN_PTYPE_1TR6) -#define ISDN_FEATURE_P_EURO (0x1000000 << ISDN_PTYPE_EURO) -#define ISDN_FEATURE_P_NI1 (0x1000000 << ISDN_PTYPE_NI1) - -#define ISDN_FEATURE_P_MASK (0x0FF000000) /* Max. 8 Protocols */ -#define ISDN_FEATURE_P_SHIFT (24) - -typedef struct setup_parm { - unsigned char phone[32]; /* Remote Phone-Number */ - unsigned char eazmsn[32]; /* Local EAZ or MSN */ - unsigned char si1; /* Service Indicator 1 */ - unsigned char si2; /* Service Indicator 2 */ - unsigned char plan; /* Numbering plan */ - unsigned char screen; /* Screening info */ -} setup_parm; - - -#ifdef CONFIG_ISDN_TTY_FAX -/* T.30 Fax G3 */ - -#define FAXIDLEN 21 - -typedef struct T30_s { - /* session parameters */ - __u8 resolution __attribute__ ((packed)); - __u8 rate __attribute__ ((packed)); - __u8 width __attribute__ ((packed)); - __u8 length __attribute__ ((packed)); - __u8 compression __attribute__ ((packed)); - __u8 ecm __attribute__ ((packed)); - __u8 binary __attribute__ ((packed)); - __u8 scantime __attribute__ ((packed)); - __u8 id[FAXIDLEN] __attribute__ ((packed)); - /* additional parameters */ - __u8 phase __attribute__ ((packed)); - __u8 direction __attribute__ ((packed)); - __u8 code __attribute__ ((packed)); - __u8 badlin __attribute__ ((packed)); - __u8 badmul __attribute__ ((packed)); - __u8 bor __attribute__ ((packed)); - __u8 fet __attribute__ ((packed)); - __u8 pollid[FAXIDLEN] __attribute__ ((packed)); - __u8 cq __attribute__ ((packed)); - __u8 cr __attribute__ ((packed)); - __u8 ctcrty __attribute__ ((packed)); - __u8 minsp __attribute__ ((packed)); - __u8 phcto __attribute__ ((packed)); - __u8 rel __attribute__ ((packed)); - __u8 nbc __attribute__ ((packed)); - /* remote station parameters */ - __u8 r_resolution __attribute__ ((packed)); - __u8 r_rate __attribute__ ((packed)); - __u8 r_width __attribute__ ((packed)); - __u8 r_length __attribute__ ((packed)); - __u8 r_compression __attribute__ ((packed)); - __u8 r_ecm __attribute__ ((packed)); - __u8 r_binary __attribute__ ((packed)); - __u8 r_scantime __attribute__ ((packed)); - __u8 r_id[FAXIDLEN] __attribute__ ((packed)); - __u8 r_code __attribute__ ((packed)); -} T30_s; - -#define ISDN_TTY_FAX_CONN_IN 0 -#define ISDN_TTY_FAX_CONN_OUT 1 - -#define ISDN_TTY_FAX_FCON 0 -#define ISDN_TTY_FAX_DIS 1 -#define ISDN_TTY_FAX_FTT 2 -#define ISDN_TTY_FAX_MCF 3 -#define ISDN_TTY_FAX_DCS 4 -#define ISDN_TTY_FAX_TRAIN_OK 5 -#define ISDN_TTY_FAX_EOP 6 -#define ISDN_TTY_FAX_EOM 7 -#define ISDN_TTY_FAX_MPS 8 -#define ISDN_TTY_FAX_DTC 9 -#define ISDN_TTY_FAX_RID 10 -#define ISDN_TTY_FAX_HNG 11 -#define ISDN_TTY_FAX_DT 12 -#define ISDN_TTY_FAX_FCON_I 13 -#define ISDN_TTY_FAX_DR 14 -#define ISDN_TTY_FAX_ET 15 -#define ISDN_TTY_FAX_CFR 16 -#define ISDN_TTY_FAX_PTS 17 -#define ISDN_TTY_FAX_SENT 18 - -#define ISDN_FAX_PHASE_IDLE 0 -#define ISDN_FAX_PHASE_A 1 -#define ISDN_FAX_PHASE_B 2 -#define ISDN_FAX_PHASE_C 3 -#define ISDN_FAX_PHASE_D 4 -#define ISDN_FAX_PHASE_E 5 - -#endif /* TTY_FAX */ - -#define ISDN_FAX_CLASS1_FAE 0 -#define ISDN_FAX_CLASS1_FTS 1 -#define ISDN_FAX_CLASS1_FRS 2 -#define ISDN_FAX_CLASS1_FTM 3 -#define ISDN_FAX_CLASS1_FRM 4 -#define ISDN_FAX_CLASS1_FTH 5 -#define ISDN_FAX_CLASS1_FRH 6 -#define ISDN_FAX_CLASS1_CTRL 7 - -#define ISDN_FAX_CLASS1_OK 0 -#define ISDN_FAX_CLASS1_CONNECT 1 -#define ISDN_FAX_CLASS1_NOCARR 2 -#define ISDN_FAX_CLASS1_ERROR 3 -#define ISDN_FAX_CLASS1_FCERROR 4 -#define ISDN_FAX_CLASS1_QUERY 5 - -typedef struct { - __u8 cmd; - __u8 subcmd; - __u8 para[50]; -} aux_s; - -#define AT_COMMAND 0 -#define AT_EQ_VALUE 1 -#define AT_QUERY 2 -#define AT_EQ_QUERY 3 - -/* CAPI structs */ - -/* this is compatible to the old union size */ -#define MAX_CAPI_PARA_LEN 50 - -typedef struct { - /* Header */ - __u16 Length; - __u16 ApplId; - __u8 Command; - __u8 Subcommand; - __u16 Messagenumber; - - /* Parameter */ - union { - __u32 Controller; - __u32 PLCI; - __u32 NCCI; - } adr; - __u8 para[MAX_CAPI_PARA_LEN]; -} capi_msg; - -/* - * Structure for exchanging above infos - * - */ -typedef struct { - int driver; /* Lowlevel-Driver-ID */ - int command; /* Command or Status (see above) */ - ulong arg; /* Additional Data */ - union { - ulong errcode; /* Type of error with STAT_L1ERR */ - int length; /* Amount of bytes sent with STAT_BSENT */ - u_char num[50]; /* Additional Data */ - setup_parm setup;/* For SETUP msg */ - capi_msg cmsg; /* For CAPI like messages */ - char display[85];/* display message data */ - dss1_cmd_stat dss1_io; /* DSS1 IO-parameter/result */ - aux_s aux; /* for modem commands/indications */ -#ifdef CONFIG_ISDN_TTY_FAX - T30_s *fax; /* Pointer to ttys fax struct */ -#endif - } parm; -} isdn_ctrl; - -/* - * The interface-struct itself (initialized at load-time of lowlevel-driver) - * - * See Documentation/isdn/INTERFACE for a description, how the communication - * between the ISDN subsystem and its drivers is done. - * - */ -typedef struct { - /* Number of channels supported by this driver - */ - int channels; - - /* - * Maximum Size of transmit/receive-buffer this driver supports. - */ - int maxbufsize; - - /* Feature-Flags for this driver. - * See defines ISDN_FEATURE_... for Values - */ - unsigned long features; - - /* - * Needed for calculating - * dev->hard_header_len = linklayer header + hl_hdrlen; - * Drivers, not supporting sk_buff's should set this to 0. - */ - unsigned short hl_hdrlen; - - /* - * Receive-Callback using sk_buff's - * Parameters: - * int Driver-ID - * int local channel-number (0 ...) - * struct sk_buff *skb received Data - */ - void (*rcvcallb_skb)(int, int, struct sk_buff *); - - /* Status-Callback - * Parameters: - * isdn_ctrl* - * driver = Driver ID. - * command = One of above ISDN_STAT_... constants. - * arg = depending on status-type. - * num = depending on status-type. - */ - int (*statcallb)(isdn_ctrl*); - - /* Send command - * Parameters: - * isdn_ctrl* - * driver = Driver ID. - * command = One of above ISDN_CMD_... constants. - * arg = depending on command. - * num = depending on command. - */ - int (*command)(isdn_ctrl*); - - /* - * Send data using sk_buff's - * Parameters: - * int driverId - * int local channel-number (0...) - * int Flag: Need ACK for this packet. - * struct sk_buff *skb Data to send - */ - int (*writebuf_skb) (int, int, int, struct sk_buff *); - - /* Send raw D-Channel-Commands - * Parameters: - * u_char pointer data - * int length of data - * int Flag: 0 = Call form Kernel-Space (use memcpy, - * no schedule allowed) - * 1 = Data is in User-Space (use memcpy_fromfs, - * may schedule) - * int driverId - * int local channel-number (0 ...) - */ - int (*writecmd)(const u_char*, int, int, int, int); - - /* Read raw Status replies - * u_char pointer data (volatile) - * int length of buffer - * int Flag: 0 = Call form Kernel-Space (use memcpy, - * no schedule allowed) - * 1 = Data is in User-Space (use memcpy_fromfs, - * may schedule) - * int driverId - * int local channel-number (0 ...) - */ - int (*readstat)(u_char*, int, int, int, int); - - char id[20]; -} isdn_if; - -/* - * Function which must be called by lowlevel-driver at loadtime with - * the following fields of above struct set: - * - * channels Number of channels that will be supported. - * hl_hdrlen Space to preserve in sk_buff's when sending. Drivers, not - * supporting sk_buff's should set this to 0. - * command Address of Command-Handler. - * features Bitwise coded Features of this driver. (use ISDN_FEATURE_...) - * writebuf_skb Address of Skbuff-Send-Handler. - * writecmd " " D-Channel " which accepts raw D-Ch-Commands. - * readstat " " D-Channel " which delivers raw Status-Data. - * - * The linklevel-driver fills the following fields: - * - * channels Driver-ID assigned to this driver. (Must be used on all - * subsequent callbacks. - * rcvcallb_skb Address of handler for received Skbuff's. - * statcallb " " " for status-changes. - * - */ -extern int register_isdn(isdn_if*); -#ifdef COMPAT_NEED_UACCESS -#include -#endif - -#endif /* __KERNEL__ */ -#endif /* isdnif_h */ diff --git a/include/linux/kernelcapi.h b/include/linux/kernelcapi.h deleted file mode 100644 index 583662dc..00000000 --- a/include/linux/kernelcapi.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * $Id$ - * - * Kernel CAPI 2.0 Interface for Linux - * - * (c) Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de) - * - * $Log$ - * Revision 1.6 2000/03/03 15:50:42 calle - * - kernel CAPI: - * - Changed parameter "param" in capi_signal from __u32 to void *. - * - rewrote notifier handling in kcapi.c - * - new notifier NCCI_UP and NCCI_DOWN - * - User CAPI: - * - /dev/capi20 is now a cloning device. - * - middleware extentions prepared. - * - capidrv.c - * - locking of list operations and module count updates. - * - * Revision 1.5 2000/01/28 16:45:40 calle - * new manufacturer command KCAPI_CMD_ADDCARD (generic addcard), - * will search named driver and call the add_card function if one exist. - * - * Revision 1.4 1999/09/10 17:24:19 calle - * Changes for proposed standard for CAPI2.0: - * - AK148 "Linux Exention" - * - * Revision 1.3 1999/07/01 15:26:56 calle - * complete new version (I love it): - * + new hardware independed "capi_driver" interface that will make it easy to: - * - support other controllers with CAPI-2.0 (i.e. USB Controller) - * - write a CAPI-2.0 for the passive cards - * - support serial link CAPI-2.0 boxes. - * + wrote "capi_driver" for all supported cards. - * + "capi_driver" (supported cards) now have to be configured with - * make menuconfig, in the past all supported cards where included - * at once. - * + new and better informations in /proc/capi/ - * + new ioctl to switch trace of capi messages per controller - * using "avmcapictrl trace [contr] on|off|...." - * + complete testcircle with all supported cards and also the - * PCMCIA cards (now patch for pcmcia-cs-3.0.13 needed) done. - * - * Revision 1.2 1999/06/21 15:24:26 calle - * extend information in /proc. - * - * Revision 1.1 1997/03/04 21:27:33 calle - * First version in isdn4linux - * - * Revision 2.2 1997/02/12 09:31:39 calle - * new version - * - * Revision 1.1 1997/01/31 10:32:20 calle - * Initial revision - * - * - */ -#ifndef __KERNELCAPI_H__ -#define __KERNELCAPI_H__ - -#define CAPI_MAXAPPL 20 /* - * maximum number of applications - */ -#define CAPI_MAXCONTR 10 /* - * maximum number of controller - */ -#define CAPI_MAXDATAWINDOW 8 - - -typedef struct kcapi_flagdef { - int contr; - int flag; -} kcapi_flagdef; - -typedef struct kcapi_carddef { - char driver[32]; - unsigned int port; - unsigned irq; - unsigned int membase; - int cardnr; -} kcapi_carddef; - -/* new ioctls >= 10 */ -#define KCAPI_CMD_TRACE 10 -#define KCAPI_CMD_ADDCARD 11 /* add card to named driver */ - -/* - * flag > 2 => trace also data - * flag & 1 => show trace - */ -#define KCAPI_TRACE_OFF 0 -#define KCAPI_TRACE_SHORT_NO_DATA 1 -#define KCAPI_TRACE_FULL_NO_DATA 2 -#define KCAPI_TRACE_SHORT 3 -#define KCAPI_TRACE_FULL 4 - - -#ifdef __KERNEL__ - -struct capi_interface { - __u16 (*capi_isinstalled) (void); - - __u16 (*capi_register) (capi_register_params * rparam, __u16 * applidp); - __u16 (*capi_release) (__u16 applid); - __u16 (*capi_put_message) (__u16 applid, struct sk_buff * msg); - __u16 (*capi_get_message) (__u16 applid, struct sk_buff ** msgp); - __u16 (*capi_set_signal) (__u16 applid, - void (*signal) (__u16 applid, void *param), - void *param); - __u16 (*capi_get_manufacturer) (__u32 contr, __u8 buf[CAPI_MANUFACTURER_LEN]); - __u16 (*capi_get_version) (__u32 contr, struct capi_version * verp); - __u16(*capi_get_serial) (__u32 contr, __u8 serial[CAPI_SERIAL_LEN]); - __u16(*capi_get_profile) (__u32 contr, struct capi_profile * profp); - - /* - * to init controllers, data is always in user memory - */ - int (*capi_manufacturer) (unsigned int cmd, void *data); - -}; - -struct capi_ncciinfo { - __u16 applid; - __u32 ncci; -}; - -#define KCI_CONTRUP 0 /* struct capi_profile */ -#define KCI_CONTRDOWN 1 /* NULL */ -#define KCI_NCCIUP 2 /* struct capi_ncciinfo */ -#define KCI_NCCIDOWN 3 /* struct capi_ncciinfo */ - -struct capi_interface_user { - char name[20]; - void (*callback) (unsigned int cmd, __u32 contr, void *data); - /* internal */ - struct capi_interface_user *next; -}; - -struct capi_interface *attach_capi_interface(struct capi_interface_user *); -int detach_capi_interface(struct capi_interface_user *); - - -#define CAPI_NOERROR 0x0000 - -#define CAPI_TOOMANYAPPLS 0x1001 -#define CAPI_LOGBLKSIZETOSMALL 0x1002 -#define CAPI_BUFFEXECEEDS64K 0x1003 -#define CAPI_MSGBUFSIZETOOSMALL 0x1004 -#define CAPI_ANZLOGCONNNOTSUPPORTED 0x1005 -#define CAPI_REGRESERVED 0x1006 -#define CAPI_REGBUSY 0x1007 -#define CAPI_REGOSRESOURCEERR 0x1008 -#define CAPI_REGNOTINSTALLED 0x1009 -#define CAPI_REGCTRLERNOTSUPPORTEXTEQUIP 0x100a -#define CAPI_REGCTRLERONLYSUPPORTEXTEQUIP 0x100b - -#define CAPI_ILLAPPNR 0x1101 -#define CAPI_ILLCMDORSUBCMDORMSGTOSMALL 0x1102 -#define CAPI_SENDQUEUEFULL 0x1103 -#define CAPI_RECEIVEQUEUEEMPTY 0x1104 -#define CAPI_RECEIVEOVERFLOW 0x1105 -#define CAPI_UNKNOWNNOTPAR 0x1106 -#define CAPI_MSGBUSY 0x1107 -#define CAPI_MSGOSRESOURCEERR 0x1108 -#define CAPI_MSGNOTINSTALLED 0x1109 -#define CAPI_MSGCTRLERNOTSUPPORTEXTEQUIP 0x110a -#define CAPI_MSGCTRLERONLYSUPPORTEXTEQUIP 0x110b - - -#endif /* __KERNEL__ */ - -#endif /* __KERNELCAPI_H__ */ diff --git a/preparser b/preparser deleted file mode 100755 index eb8568bc..00000000 Binary files a/preparser and /dev/null differ diff --git a/stackcheck b/stackcheck deleted file mode 100755 index 89a03f57..00000000 --- a/stackcheck +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh -if [ $# != 1 ] ; then - echo 'usage: stackcheck objectfile' - exit 1 -fi -objdump --disassemble -r $1 | awk ' -/>:/ { gsub("[<>:]","",$2); fname=$2 } -{print $0 "," fname} -' | \ -grep esp | \ -grep subl | grep -v ')' | cut '-d$' -f2- | \ -awk -F , '{print $1 " " $3}' | \ -while read LEN FNAME ; do - printf '%4d %s\n' $LEN $FNAME -done | \ -sort -n -u -r - diff --git a/std2kern b/std2kern deleted file mode 100755 index 9208ddb2..00000000 --- a/std2kern +++ /dev/null @@ -1,337 +0,0 @@ -#!/bin/sh - -KERNELDIR=/usr/src/linux -DOCP=docpd -PREPARSER="./preparser" -UNIQUE=false -VERBOSE=false -NOTEST=true - -docpd() { - if ! cmp -s $1 $2 ; then - if $NOTEST ; then - echo Copying $1 ... - mkdir -p `dirname $2` - cp $1 $2 - else - echo $1 was changed - fi - else - if $VERBOSE ; then - echo $2 is up to date, NOT converted - fi - fi -} - -docp() { - if [ $1 -nt $2 -o ! -f $2 ] ; then - if $NOTEST ; then - echo Copying $1 ... - mkdir -p `dirname $2` - cp $1 $2 - else - echo $1 was changed - fi - else - if $VERBOSE ; then - echo $2 is up to date, NOT converted - fi - fi -} - -docpuni() { - if $VERBOSE ; then - echo -n "Processing $1 ... " - fi - TMPNAME=/tmp/`basename $1`.$$ - $PREPARSER -c $CTRLNAME $1 $TMPNAME - RES=$? - if [ "$RES" -eq "0" ] ; then - if ! cmp -s $1 $2 ; then - if $NOTEST ; then - if $VERBOSE ; then - echo copying original - else - echo "Processing $1 ... copying original" - fi - mkdir -p `dirname $2` - cp $1 $2 - else - if $VERBOSE ; then - echo original was changed - else - echo "Processing $1 ... original was changed" - fi - fi - else - if $VERBOSE ; then - echo original file is up to date - fi - fi - rm $TMPNAME - return 0 - fi - if [ "$RES" -eq "2" ] ; then - if ! cmp -s $TMPNAME $2 ; then - if $NOTEST ; then - if $VERBOSE ; then - echo copying modified - else - echo "Processing $1 ... copying modified" - fi - mkdir -p `dirname $2` - cp $TMPNAME $2 - else - if $VERBOSE ; then - echo modified was changed - else - echo "Processing $1 ... modified was changed" - fi - fi - else - if $VERBOSE ; then - echo modified file is up to date - fi - fi - rm $TMPNAME - return 0 - fi - echo - echo "problem with $PREPARSER retcode $RES" - exit 1 -} - - -# -# Print usage and exit -# -usage() { - cat< -#define GET_USER get_user -#define PUT_USER put_user -#define RWTYPE long -#define LSTYPE long long -#define RWARG unsigned long -#define LSARG long long -#define COMPAT_NEED_UACCESS -#define SET_SKB_FREE(x) -#define idev_kfree_skb(a,b) dev_kfree_skb(a) -#define idev_kfree_skb_irq(a,b) dev_kfree_skb(a) -#define idev_kfree_skb_any(a,b) dev_kfree_skb(a) -#define COMPAT_HAS_NEW_SYMTAB -#define CLOSETYPE int -#define CLOSEVAL (0) -#define MINOR_PART(f) MINOR(f->f_dentry->d_inode->i_rdev) -#define COMPAT_HAS_NEW_PCI -#define get_pcibase(ps,nr) ps->base_address[nr] -#define FILEOP_HAS_FLUSH -#undef COMPAT_HAS_NEW_WAITQ -#undef COMPAT_HAS_NEW_SETUP -#undef BIG_PHONE_NUMBERS -#undef COMPAT_HAS_ISA_IOREMAP -#define net_device device -#define set_current_state(sta) current->state = sta - -#undef 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_IPV4_TCP_KEEPALIVE -#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR -#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER -#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND -#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE -#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR -#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS -#undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT -#undef ISDN_NEW_TBUSY -#delete #define ISDN_NEW_TBUSY -#define COMPAT_NO_SOFTNET -#undef HAVE_DEVFS_FS -#define devfs_register_chrdev(m,n,f) register_chrdev(m,n,f) -#define devfs_unregister_chrdev(m,n) unregister_chrdev(m,n) diff --git a/v2.2.ctrl b/v2.2.ctrl deleted file mode 100644 index f724811b..00000000 --- a/v2.2.ctrl +++ /dev/null @@ -1,46 +0,0 @@ -#delete #include -#define GET_USER get_user -#define PUT_USER put_user -#define RWTYPE long -#define LSTYPE long long -#define RWARG unsigned long -#define LSARG long long -#define COMPAT_NEED_UACCESS -#define SET_SKB_FREE(x) -#define idev_kfree_skb(a,b) dev_kfree_skb(a) -#define idev_kfree_skb_irq(a,b) dev_kfree_skb(a) -#define idev_kfree_skb_any(a,b) dev_kfree_skb(a) -#define COMPAT_HAS_NEW_SYMTAB -#define CLOSETYPE int -#define CLOSEVAL (0) -#define MINOR_PART(f) MINOR(f->f_dentry->d_inode->i_rdev) -#define COMPAT_HAS_NEW_PCI -#define get_pcibase(ps,nr) ps->base_address[nr] -#define FILEOP_HAS_FLUSH -#undef COMPAT_HAS_NEW_WAITQ -#undef COMPAT_HAS_NEW_SETUP -#undef BIG_PHONE_NUMBERS -#undef COMPAT_HAS_ISA_IOREMAP -#define net_device device -#define set_current_state(sta) current->state = sta -#undef COMPAT_HAS_pci_find_subsys -#define ISDN_TTY_FCLASS1 -#undef 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_IPV4_TCP_KEEPALIVE -#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR -#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER -#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND -#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE -#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR -#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS -#undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT -#define COMPAT_NO_SOFTNET -#undef HAVE_DEVFS_FS -#define devfs_register_chrdev(m,n,f) register_chrdev(m,n,f) -#define devfs_unregister_chrdev(m,n) unregister_chrdev(m,n) diff --git a/v2.3.ctrl b/v2.3.ctrl deleted file mode 100644 index 523bc6fb..00000000 --- a/v2.3.ctrl +++ /dev/null @@ -1,43 +0,0 @@ -#delete #include -#define GET_USER get_user -#define PUT_USER put_user -#define RWTYPE long -#define LSTYPE long long -#define RWARG unsigned long -#define LSARG long long -#define COMPAT_NEED_UACCESS -#define SET_SKB_FREE(x) -#define idev_kfree_skb(a,b) dev_kfree_skb(a) -#define idev_kfree_skb_irq(a,b) dev_kfree_skb_irq(a) -#define idev_kfree_skb_any(a,b) dev_kfree_skb_any(a) -#define COMPAT_HAS_NEW_SYMTAB -#define CLOSETYPE int -#define CLOSEVAL (0) -#define MINOR_PART(f) MINOR(f->f_dentry->d_inode->i_rdev) -#define COMPAT_HAS_NEW_PCI -#define get_pcibase(ps, nr) ps->resource[nr].start -#define FILEOP_HAS_FLUSH -#define COMPAT_HAS_NEW_WAITQ -#define COMPAT_HAS_NEW_SETUP -#define COMPAT_HAS_ISA_IOREMAP -#define COMPAT_HAS_pci_find_subsys -#define ISDN_TTY_FCLASS1 - -#undef 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_IPV4_TCP_KEEPALIVE -#undef CONFIG_ISDN_WITH_ABC_IPV4_DYNADDR -#undef CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER -#undef CONFIG_ISDN_WITH_ABC_ICALL_BIND -#undef CONFIG_ISDN_WITH_ABC_CH_EXTINUSE -#undef CONFIG_ISDN_WITH_ABC_CONN_ERROR -#undef CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS -#undef CONFIG_ISDN_WITH_ABC_FRAME_LIMIT -#define BIG_PHONE_NUMBERS -#undef COMPAT_NO_SOFTNET -#define HAVE_DEVFS_FS