Compare commits

...

426 Commits
T6 ... master

Author SHA1 Message Date
Martin Bachem 3a24517201 obsolete interface for HFC-S USB driver, use hisax_if.h for loadable HiSax drivers instead 2005-04-08 19:23:46 +00:00
Martin Bachem 4feee5174d no HFC-S USB support for kernel 2.2 2005-04-08 19:16:23 +00:00
Martin Bachem 818d806b82 support for Sitecom DC-105 2005-04-08 14:05:53 +00:00
Martin Bachem 687a87f360 replaced outdated driver for kernels 2.4.20 and higher 2005-04-06 14:57:08 +00:00
Detlef Wengorz 215c508126 synchronize tx-frame with super_tx_queue (abc-stuff only). 2002-08-17 18:35:23 +00:00
Detlef Wengorz d6bcb93acf change alloc's/free's from vmalloc/vfree to kmalloc/kfree
to use bsdcomp in none user-context (abc-stuff only).
move MOD_INC_USE_COUNT before first bsd_free wich call MOD_DEC_USE_COUNT.
2002-08-17 18:28:38 +00:00
Karsten Keil 3fcfc40d2e change Christian Mock's address 2002-08-13 09:57:26 +00:00
Karsten Keil 572178b99a fix to allways clear BC_BUSY bit (problem with X.75) 2002-08-13 09:55:29 +00:00
Detlef Wengorz 3f1114644b remove high tx-que lengh for abc-extension
not longer need with cbq traffic control
2002-04-06 18:17:50 +00:00
Karsten Keil 68bcd010cf implement Ringing and Proceeding status display in ttyI 2002-02-09 21:19:11 +00:00
Karsten Keil f283a7e2c8 support for HST saphir III 2002-02-09 21:00:57 +00:00
Karsten Keil 5188e85a9d fix typo 2002-01-31 13:26:35 +00:00
Karsten Keil cab5bbc766 isapnp_driver is now part of <linux/isapnp.h> (since 2.4.15) 2002-01-08 17:22:14 +00:00
Karsten Keil 5bff970309 make compile 2002-01-08 17:21:33 +00:00
Karsten Keil 1703b79605 isapnp_driver is now part of <linux/isapnp.h> 2002-01-08 17:20:34 +00:00
Detlef Wengorz b6f56b49af remove not longer used code.
remove socket source-addr rewriting.
2001-12-01 23:18:21 +00:00
Detlef Wengorz 9b21ae7b60 remove tcp-keepalive response-code.
the right place for this is netfilter (maybe) not isdn.
2001-11-25 16:10:22 +00:00
Armin Schindler c052dac2f7 added Morten Helgesen's patch to fix "return -Exxx" 2001-11-20 09:48:25 +00:00
Kai Germaschewski 879c508ed1 merges from KERNEL_2_4 2001-11-07 22:35:49 +00:00
Kai Germaschewski 6e79abd50f IO region size for niccy set to 0x40 (Olaf Hering) 2001-10-20 22:05:00 +00:00
Detlef Wengorz 3a40e847c2 remove unused iptables stuff and cleanup source 2001-09-26 20:32:08 +00:00
Kai Germaschewski c24ac62372 first batch of merges from KERNEL_2_4 branch 2001-09-24 13:23:13 +00:00
Kai Germaschewski c259549bc1 add missing hisax_isapnp.[hc] 2001-09-24 11:50:56 +00:00
Karsten Keil c8ef9ea3f5 Wrong MIN replacement fixed (endless loop) 2001-09-23 12:00:05 +00:00
Kai Germaschewski 498f4da6ca small Config.in cleanup
make hisax_fcpcipnp compile w/o CONFIG_ISAPNP
2001-08-30 11:31:56 +00:00
Kai Germaschewski cdeb0a4c9f merges from KERNEL_2_4 branch 2001-08-30 10:54:25 +00:00
Kai Germaschewski a87ac24dee merged min/max changes from KERNEL_2_4 branch 2001-08-30 10:45:43 +00:00
Kai Germaschewski e80660afb5 added locking for new-style drivers. This is not hotplug-safe currently,
but at least no worse than before
2001-08-21 09:52:52 +00:00
Ulrich Albrecht 89a11781cb Changed IRQ-handling to use spinlocks instead of cli/sti 2001-08-16 09:42:20 +00:00
Kai Germaschewski 276d17903c update version of ST5481 driver
first version of new Fritz!PCI/PnP driver (also supports PCI v2)
2001-08-15 10:25:49 +00:00
Kai Germaschewski a7c9cd8c7f merges from KERNEL_2_4 2001-08-14 14:24:54 +00:00
Kai Germaschewski 132d6d83b7 merges from KERNEL_2_4 2001-08-14 13:59:27 +00:00
Karsten Keil 5ad604bf7f Should also complile without HFC USB (Thanks Bjoern A. Zeeb) 2001-07-30 21:53:19 +00:00
Kai Germaschewski 625e9d8760 also compare md5sums.asc 2001-07-27 11:44:09 +00:00
Kai Germaschewski 2b18963fc0 fix two kind-of-bugs found by Stanford checker (Rob Radez/me) 2001-07-27 11:15:15 +00:00
Kai Germaschewski 483673a6d3 cosmetics 2001-07-27 11:13:37 +00:00
Kai Germaschewski 5c71affd56 add missing files 2001-07-24 14:48:57 +00:00
Kai Germaschewski 3f57fd5432 should even compile now ;) 2001-07-22 10:53:35 +00:00
Kai Germaschewski b8115d4950 new version of st5481 usb support - mostly cleanup,seperating into different
files etc.
2001-07-22 10:44:25 +00:00
Kai Germaschewski fd1a3f457e merge from KERNEL_2_4 2001-07-19 21:22:29 +00:00
Kai Germaschewski 028b0f5570 merges from KERNEL_2_4 branch 2001-07-19 20:39:51 +00:00
Kai Germaschewski 4c5152e3ed fix for hdlc_decode 2001-07-19 20:39:19 +00:00
Karsten Keil e10f085bbb Fix wrong MPPP remove link order 2001-07-17 20:53:58 +00:00
Armin Schindler b41cb5d65a changes from kernel.org, removed pci id's, removed
double function.
2001-07-17 19:21:47 +00:00
Armin Schindler df75253118 changed some kernel compatibility stuff. 2001-07-17 18:09:40 +00:00
Detlef Wengorz 7b418c2b90 makes compiler happy 2001-07-13 10:44:12 +00:00
Kai Germaschewski df921e6651 more merges from KERNEL_2_4 branch 2001-07-13 09:34:30 +00:00
Kai Germaschewski de3b81cbce merges from KERNEL_2_4 branch 2001-07-13 09:27:00 +00:00
Werner Cornelius bf859c6ef7 Changes from certification of HFC-S PCI A and HFC-USB chips
Added certification info to READMEs and md5sums
2001-07-06 22:00:25 +00:00
Werner Cornelius ced29e47f1 Changes from certification tests. 2001-07-06 21:30:11 +00:00
Karsten Keil 042c4da0e9 Some whitespace cleanups 2001-07-05 20:10:59 +00:00
Karsten Keil 5c7df9c077 Support IPAC V1.2 too 2001-07-05 17:13:38 +00:00
Kai Germaschewski 6d2ddd8024 remaining skb_queue_purge issues 2001-06-17 08:28:31 +00:00
Kai Germaschewski f52026d482 fix remaining skb_queue_purge issues (hopefully) 2001-06-16 23:34:23 +00:00
Kai Germaschewski 271bd73c86 merge skb_queue_purge from KERNEL_2_4 2001-06-13 17:19:54 +00:00
Kai Germaschewski 257850e38e config/build cleanup 2001-06-13 14:53:40 +00:00
Kai Germaschewski 6c0e8c43ea merge ST5481_USB driver (Frode Isaksen) 2001-06-13 14:50:22 +00:00
Kai Germaschewski 4483226493 minor compilation fixes 2001-06-13 14:48:30 +00:00
Kai Germaschewski 2b5646effa hfc_usb build fixes 2001-06-13 14:02:38 +00:00
Kai Germaschewski bf736af8fe __init fix from KERNEL_2_4 2001-06-13 14:00:00 +00:00
Werner Cornelius 7201ec78cc changed structure and version 2001-06-12 20:32:47 +00:00
Werner Cornelius 5affe803e1 some fixes for 2.4 and large frames 2001-06-12 20:31:49 +00:00
Werner Cornelius d5d7b96910 update diversion features 2001-06-10 22:17:30 +00:00
Werner Cornelius 9917c4eab9 update diversion features, fix a diversion bug in common module 2001-06-10 22:15:30 +00:00
Werner Cornelius 8670d8c1b7 fix usb initialization diffs between 2.2 and 2.4 2001-06-10 15:58:03 +00:00
Werner Cornelius 6e243e06a1 corrected config bug 2001-06-09 11:09:24 +00:00
Werner Cornelius 794b57c5b0 added support for HFC-USB
added support for HFC-USB
2001-06-08 22:22:11 +00:00
Werner Cornelius c59d09a54c added support for HFC-USB 2001-06-08 22:21:40 +00:00
Werner Cornelius feebdafb63 added HFC-USB support 2001-06-08 22:19:16 +00:00
Werner Cornelius 0099cdbe13 add HFC-USB support 2001-06-08 21:56:11 +00:00
Kai Germaschewski 8bbee59c21 remove compat code 2001-06-08 08:40:19 +00:00
Kai Germaschewski da09cee971 merged new tpam driver 2001-06-08 08:17:30 +00:00
Kai Germaschewski c0fadb5f5e added compat defines for 2.2.20 2001-06-08 08:10:23 +00:00
Kai Germaschewski 7bc01fd25c fix from the Stanford CHECKER 2001-06-08 08:02:19 +00:00
Kai Germaschewski ab87def0bb merge with KERNEL_2_4/kernel tree 2001-05-26 15:21:18 +00:00
Kai Germaschewski b0f8f1dd42 assorted fixes, related to the Stanford checker project 2001-05-23 14:41:35 +00:00
Kai Germaschewski afe0d1ce83 clean up /dev/isdninfo 2001-05-22 20:50:08 +00:00
Kai Germaschewski 18962b1891 forgot one Log entry... 2001-05-17 20:47:31 +00:00
Kai Germaschewski 6e91e47e5c CVS Log gone for good... 2001-05-17 20:42:29 +00:00
Kai Germaschewski 3e9a5114aa cleanup the headers 2001-04-27 22:45:56 +00:00
Carsten Paeth 36c96b77ee Bugfix: card drivers and kernelcapi were using different constants
for number of maximum applications (CAPI_MAXAPPL and AVM_NAPPS).
   This result in strange behavior, when AVM_NAPPS is smaller than
   CAPI_MAXAPPL.
- Definition of AVM_NAPPS removed. CAPI_MAXAPPL will be used instead.
2001-04-23 15:50:27 +00:00
Carsten Paeth 4280a7f6f9 - Ignore reset notification if controllers are in detect state. 2001-04-19 13:00:54 +00:00
Carsten Paeth e92e025c06 Now the C2 is really running ... 2001-04-19 11:00:41 +00:00
Fritz Elfert 8e8810e7ab Fixes for 2.4 2001-04-19 00:43:18 +00:00
Carsten Paeth 53c6c6b193 support for AVM ISDN Controller C2 added. 2001-04-18 12:26:15 +00:00
Karsten Keil 988052c6a4 only _cs should depend on CONFIG_PCMCIA (since the standalone pcmcia
stuff is more stable as the kernel one)
2001-04-15 14:56:14 +00:00
Karsten Keil 304ed7995c cert 2001-04-15 14:53:18 +00:00
Karsten Keil b79c3467b7 reduce allocating addresses to the minimum to avoid problems with some
BIOS versions (Thanks to Ime Simts)
2001-04-15 14:52:54 +00:00
Ulrich Albrecht 334236da05 hycapi_enable and hynet_enable defined in header 2001-04-12 16:22:11 +00:00
Ulrich Albrecht 3711c9f8c4 Made network-usage configurable via hynet_enable module-parameter 2001-04-12 16:21:43 +00:00
Ulrich Albrecht 813394f454 Renamed capi_enable to hycapi_enable for consistency. Debug-Logmessages removed. 2001-04-12 16:19:56 +00:00
Ulrich Albrecht da280ff035 Network-Usage of several adapters configurable over hynet_enable module-parameter 2001-04-12 16:18:30 +00:00
Armin Schindler 1018a97dc8 updated analogue modem connect messages and
fixed out of range check.
2001-04-07 21:31:01 +00:00
Kai Germaschewski 400bce700c actually add the module ;) 2001-03-22 21:52:50 +00:00
Kai Germaschewski 4a982da022 add elsa_cs pcmcia support module
thanks to Klaus Lichtenwalder
2001-03-22 21:52:19 +00:00
Carsten Paeth d66c28295a - the revision strings in 2.4.3-pre4 get to long, changed handling
to support revision strings > 9 ...
2001-03-20 13:14:50 +00:00
Detlef Wengorz 91f3663b0e add missing ; at line 928 (now it compiles) 2001-03-20 08:10:38 +00:00
Detlef Wengorz d66fce0922 added missing dev-> before tflags (now it compiles) 2001-03-20 08:09:12 +00:00
Kai Germaschewski 554d2014f3 fix a bug in syncPPP CCP negotiation 2001-03-17 17:51:40 +00:00
Kai Germaschewski d2c067b2ba fix the isdn_common timer code
thanks to Henk-Jan Slotboom
2001-03-17 17:49:34 +00:00
Kai Germaschewski 391f2b7758 change < ISDN_MINOR_CTRL to <= ISDN_MINOR_BMAX
thanks to Julien Gaulmin <julien.gaulmin@fr.alcove.com>
2001-03-17 17:47:19 +00:00
Kai Germaschewski c977f66fab fixes for various bugs which came up on linux-kernel 2001-03-17 17:44:20 +00:00
Kai Germaschewski 5a21f01636 more small fixes... 2001-03-15 21:16:23 +00:00
Kai Germaschewski 03c561f5cc compatibility changes from KERNEL_2_4 2001-03-15 15:48:07 +00:00
Kai Germaschewski 331c629e51 spelling fixes from KERNEL_2_4
compilation warning fixes from KERNEL_2_4
sedlbauer PCMCIA support module
2001-03-15 09:03:42 +00:00
Kai Germaschewski 100bf42e08 merge Makefile changes from KERNEL_2_4 2001-03-13 16:53:23 +00:00
Ulrich Albrecht 217e453e65 Changed configuration line length (was too short) 2001-03-12 11:47:14 +00:00
Ulrich Albrecht fd5c5d22d1 Made controllers selectable for CAPI-use by "capi_enable" module parameter 2001-03-09 15:07:57 +00:00
Kai Germaschewski 2b25ca2dd0 improved CISCO HDLC support
by Bjoern A. Zeeb <i4l@zabbadoz.net>
2001-02-28 21:55:52 +00:00
Armin Schindler 87a7ba0fa2 removed obsolete remark 2001-02-19 10:01:50 +00:00
Armin Schindler 11baceac41 removed remark in header due to GPL violation. 2001-02-16 08:56:01 +00:00
Karsten Keil 686c8687c9 config.h and isdn_compat.h should be only included #ifdef __KERNEL__ 2001-02-08 12:54:37 +00:00
Armin Schindler 5573cae6a9 changes from 2.4.1-ac4 2001-02-07 10:44:11 +00:00
Armin Schindler 95ad8107ba fixed in_irq define. 2001-02-06 11:43:10 +00:00
Kai Germaschewski 24a4a2538b improved CISCO HDLC keepalive support.
Thanks to Bjoern A. Zeeb.
2001-02-02 21:08:47 +00:00
Carsten Paeth 21e841aafa - added compile info to revision output. 2001-01-29 13:13:44 +00:00
Carsten Paeth 3a95edaeec - insert ncci in list after registering to capifs, not before. 2001-01-25 14:58:56 +00:00
Kai Germaschewski 834d66319f more fixes 2001-01-24 23:47:37 +00:00
Kai Germaschewski 5327184e9d more compatibility fixes 2001-01-24 22:17:07 +00:00
Kai Germaschewski 841f2d9bf4 fix std2kern w/o -u 2001-01-24 21:40:06 +00:00
Kai Germaschewski 15696b18a0 fixes from 2.4 (same as in branch KERNEL_2_4, forget the changelog there :(
o fix typo in the pci MODULE_DEVICE_TABLE in hisax (Ingo Oeser/me)
o fix crash with dss1_divert compiled into the kernel
o fix PPP crash with compression (Andre Beck)
o fix V.110 crash

known bugs: most likely another MPPP crash remains, which I couldn't
reproduce yet.
2001-01-23 17:42:59 +00:00
Carsten Paeth 18a3ebaa1f - Didn't compile with 2.2.X (pci_resource_start not defined). 2001-01-22 10:26:03 +00:00
Armin Schindler 016469efaa fixes in interrupt handler 2001-01-20 20:20:30 +00:00
Detlef Wengorz 2f5d09601d patch works again with 2.4.x kernel's 2001-01-20 12:16:39 +00:00
Werner Cornelius 4662632e5b Changed leading number of 0 in output format 2001-01-09 19:19:21 +00:00
Karsten Keil 8774c83748 approve 2001-01-08 21:45:39 +00:00
Kai Germaschewski 553df5cb4e assorted fixes from post-2.4.0 2001-01-08 17:06:37 +00:00
Werner Cornelius a2d07d28b6 Fixed a queuing bug which changed the order of rames to be sent.
Thanks for a hint from Wolfram Joost.
2001-01-07 13:10:44 +00:00
Kai Germaschewski 84da742773 cosmetics 2000-12-18 22:14:59 +00:00
Kai Germaschewski 92fedf78ea added v2.2.19.ctrl 2000-12-17 21:28:39 +00:00
Kai Germaschewski 18d43861d0 sync with kernel. std2kern hopefully takes care of the Makefile
difference for the time being
2000-12-17 21:15:02 +00:00
Armin Schindler 6b5088dacc changed version number. 2000-12-17 13:05:24 +00:00
Armin Schindler 355e243418 merged changes (depreciated file check) from 2_4 branch. 2000-12-17 13:02:50 +00:00
Kai Germaschewski 57ac7b3275 fix pci_set_master compatibility
(not needed)
2000-12-13 16:25:15 +00:00
Kai Germaschewski 658b751b34 Fix my fix: Only use pci_set_master on devices doing busmaster DMA
(netjet, hfc_pci)
2000-12-13 13:57:56 +00:00
Kai Germaschewski f120a52b93 remove the obsolete (un)register_isdn_module 2000-12-12 23:33:06 +00:00
Kai Germaschewski 8f5a6cd114 add pci_set_master to (hopefully) all PCI busmaster drivers.
fixed compatibility for this.
2000-12-12 22:57:49 +00:00
Werner Cornelius 18f63bdba9 Changed E-Mail address, added additional info 2000-12-12 20:38:26 +00:00
Armin Schindler 5dafc5b63a removed include of isdn_cards.h 2000-12-12 20:38:25 +00:00
Kai Germaschewski cddc0e23e1 add the tq_scheduler -> schedule_task change from 2.4 2000-12-11 00:10:34 +00:00
Werner Cornelius 93d8811892 Added B-channel rx fifo overflow handling 2000-12-10 23:29:12 +00:00
Kai Germaschewski c853347a04 isdn_cards.[hc] should not be needed anymore now. 2000-12-10 23:04:14 +00:00
Kai Germaschewski 457078cc3f use new-style module_init/exit.
Armin, I'm not sure if I mistakenly broke something
in the eicon drivers. Could you please check that?
2000-12-10 23:02:32 +00:00
Kai Germaschewski 4322c46164 add pci_set_master
ioremap is handling unaligned regions since
at least 2.2.0
2000-12-10 22:51:05 +00:00
Kai Germaschewski 0b414d1641 fixes for 2.4.0t12-8 2000-12-10 22:26:47 +00:00
Kai Germaschewski ed8fcc4e6d introduce a config options for bsd compression
due to license changes compiling into the kernel is okay now
2000-12-07 20:57:07 +00:00
Kai Germaschewski df0bf3c658 setup dependency on CONFIG_PCI for the PCI drivers
in Config.in
2000-12-07 00:09:53 +00:00
Kai Germaschewski b5accabbd3 move compatibility stuff to isdn_compat.h 2000-12-07 00:03:55 +00:00
Kai Germaschewski 464a93efad fix compatiblity to 2.4 when using std2kern w/o -u 2000-12-07 00:00:04 +00:00
Kai Germaschewski 8c6c17493c patches from 2.4.0-test12-6
o remove unneeded includes
o flags needs to be long for set/test_..._bit
2000-12-06 16:58:01 +00:00
Kai Germaschewski cfeb228cc5 o call pci_enable_device() first of all, because this may change/assign
resources we use afterwards.
o #ifndef COMPAT_HAS_2_2_PCI is not necessary, because for 2.2
  pci_enable_device is defined to (0)
2000-12-05 19:15:44 +00:00
Werner Cornelius 8ad67f8f6b Added new PCI device from Abocom/Magitek 2000-12-04 22:34:58 +00:00
Kai Germaschewski 3baa300757 Change the Makefiles to new style.
There may be problems there that I missed, so this shouldn't go into
an offical kernel any time soon.
However, if I didn't commit it, we wouldn't find the bugs...
2000-12-02 19:47:30 +00:00
Kai Germaschewski ac3689287b comment out changing of MMIO regio.
according to Alan Cox it shouldn't be necessary and is invalid
2000-12-02 19:44:02 +00:00
Kai Germaschewski 4a6fbad3ec copies of v2.2.17.ctrl - if you need lower versions, just copy it yourself.
(just using v2.2.ctrl does't seem good to me, because that'll give trouble on
 2.2.19 and up...)
2000-11-30 08:29:42 +00:00
Kai Germaschewski 8216b0d1ff same thing for __devinitdata 2000-11-29 17:48:27 +00:00
Kai Germaschewski e372200e90 __initdata always needs to be initialized 2000-11-29 15:47:12 +00:00
Kai Germaschewski 5289ece6e7 nrcards is also referenced in callc.c, so shouldn't be static 2000-11-28 23:42:39 +00:00
Carsten Paeth 0807f87ce6 But the #ifndef PCI_DEVICE_ID_AVM* back, and let it compile again.
Please always check if 2.2.14-2.2.18 compile after a "std2kern -u"
before checkin ...
2000-11-28 14:26:46 +00:00
Kai Germaschewski 323a78023d merged MODULE_DEV_TABLE changes 2000-11-28 11:42:20 +00:00
Kai Germaschewski c3b6ae8436 *** empty log message *** 2000-11-28 11:28:39 +00:00
Kai Germaschewski 52afc6ea61 reversing the previous changes - wrong branch, sorry 2000-11-28 09:35:07 +00:00
Kai Germaschewski d404264552 This is current as of 2.4.0-test12-pre? 2000-11-28 09:34:02 +00:00
Kai Germaschewski 7dfb5916d0 compatibility cleanup - final part for the time being 2000-11-25 17:01:02 +00:00
Kai Germaschewski 05732ea78e compatibility fixes 2000-11-25 11:35:55 +00:00
Kai Germaschewski d68b25f279 use __init instead of deprecated __initfunc
use __devinit{,data} for hotplug drivers
static variables are initialized to 0 always (don't need to do so
explicitly)
2000-11-24 17:05:39 +00:00
Kai Germaschewski 75dd636457 now BUG() should work in <= 2.2.17, too 2000-11-23 23:57:35 +00:00
Kai Germaschewski c63391e1ab fixed module_init/exit stuff
Note: compiled-in kernel doesn't work pre 2.2.18 anymore.
2000-11-23 20:45:14 +00:00
Kai Germaschewski dfdcedb1af minor changes from kernel tree 2000-11-22 17:13:13 +00:00
Kai Germaschewski 69e4e1b52a more compatibility cleanup 2000-11-19 17:41:04 +00:00
Kai Germaschewski d37916e1ae make B1 work for kernels <= 2.2.17 again 2000-11-19 17:40:17 +00:00
Kai Germaschewski d64f7e03d3 remove unused ctrl files. For 2.2.x, x < 18 use v2.2.17.ctrl, else v2.2.18.ctrl 2000-11-19 17:06:26 +00:00
Kai Germaschewski 9f253b957c compatibility cleanup - part 8 2000-11-19 17:05:24 +00:00
Kai Germaschewski 31432e7bd7 compatibility cleanup - part 7 2000-11-19 17:05:07 +00:00
Kai Germaschewski 0c7ae2f941 compatibility cleanup - part 6 2000-11-19 17:04:35 +00:00
Kai Germaschewski 9957cbef2c compatibility cleanup - part 5 2000-11-19 17:03:56 +00:00
Kai Germaschewski 599511592d compatibility cleanup - part 4 2000-11-19 17:03:35 +00:00
Kai Germaschewski cb12a3862b compatibility cleanup - part 3 2000-11-19 17:02:49 +00:00
Kai Germaschewski a0f9eace40 compatibility cleanup - part 2 2000-11-19 17:01:54 +00:00
Kai Germaschewski ca7c105d3f compatiblity cleanup - part 1 2000-11-19 17:01:05 +00:00
Kai Germaschewski 1a4d53db2f change from 2.4 tree 2000-11-18 16:17:25 +00:00
Kai Germaschewski a942b3cb0e compilation fix 2000-11-18 16:16:59 +00:00
Kai Germaschewski 974cd58b9a compile fix if !CONFIG_PCI 2000-11-18 15:57:04 +00:00
Karsten Keil 87fc7fb493 NI1 update 2000-11-16 13:59:34 +00:00
Karsten Keil 5164c2014e cert NI1 changes 2000-11-16 13:53:16 +00:00
Karsten Keil de7ad8be4d NI1 update 2000-11-16 13:52:22 +00:00
Karsten Keil e0428a5d6b 09/10/00 spid_ok no longer used since layer 2 is permanent
19/09/00 state transition added for spid_ok - GE
15/09/00 set exclusive bit in Channel ID = GE
14/09/00 spid_ok flag added - GE
05/09/00 Channel ID added to setup_rsp - GE
05/09/00 64k voice u-law bug fixed - GE
2000-11-16 13:51:44 +00:00
Karsten Keil 5f3afeeb32 08/09/00 - SPID retry timer increased - Guy Ellis www.traverse.com.au 2000-11-16 13:50:43 +00:00
Karsten Keil 5817d0d2e1 12/10/00 - GE, release_l3_proc changed for NI-1
20/09/00 - GE, DREL_TIMER switch added for NI-1
2000-11-16 13:49:42 +00:00
Karsten Keil 1b792b177e TJ320 support added 13/07/00 Guy Ellis www.traverse.com.au 2000-11-16 13:45:59 +00:00
Karsten Keil bf71ea570a 06/10/00 56k support added - Guy Ellis 2000-11-16 13:44:22 +00:00
Carsten Paeth 134a3fcff2 Bugfix for v110. Connectparamters where setup for sync ... 2000-11-14 08:43:07 +00:00
Kai Germaschewski 8f9ff57a6d rm CVS $Log entries 2000-11-13 22:51:50 +00:00
Kai Germaschewski 6cb6a3e3f9 fix VJ compression 2000-11-13 20:03:50 +00:00
Kai Germaschewski 45daefbcc7 cleanup / rm CVS Log 2000-11-12 16:32:06 +00:00
Kai Germaschewski 464065fad2 use unlink before copy in std2kern, so it works better with
hardlinked trees
2000-11-12 16:15:47 +00:00
Kai Germaschewski 354adc90f6 fix isdnloop driver (works for me now) 2000-11-12 15:51:59 +00:00
Kai Germaschewski f979c1535c #define __exit when using <linux/isdn_compat.h> 2000-11-12 15:49:46 +00:00
Kai Germaschewski fa6653235e fixes from 2.4.0-test11-pre3 2000-11-12 15:29:37 +00:00
Kai Germaschewski 8c6a396304 avoid all of ABC netfilter when using stddiff -u 2000-11-02 22:48:30 +00:00
Detlef Wengorz fb22ff5ceb change double-link-list handling and locking to kernel-defaults.
(abc stuff only)
2000-11-01 17:54:01 +00:00
Detlef Wengorz 059c34cf0c remove from now on useless keepalive-call's 2000-11-01 17:42:08 +00:00
Kai Germaschewski a99a22cfac small fix 2000-11-01 15:40:15 +00:00
Carsten Paeth e89ba68f87 - use module_init/module_exit from linux/init.h.
- all static struct variables are initialized with "membername:" now.
- avm_cs.c, let it work with newer pcmcia-cs.
2000-11-01 14:05:02 +00:00
Carsten Paeth 974aabdb12 scripts to check capi stuff against a kernel. 2000-11-01 14:02:37 +00:00
Kai Germaschewski cc3077b26e fixes from 2.4 tree, CCP fix 2000-10-28 23:03:40 +00:00
Detlef Wengorz fc10f79d69 add new netfilter target ISDNDIAL (natfilter/Postrouting).
add a kernel-patch to insert isdn_skb_bits field in skbuff's.
stop using of skb->nfmark field.
2000-10-28 19:31:13 +00:00
Carsten Paeth e346262860 Workaround: pppd calls restoretty before reseting the ldisc and
ldisc "ppp_sync" didn't support this. So we call n_tty_ioctl
  in the driver ioctl function. (remember: driver ioctl function is
  only called if ldisc ioctl function did not handle the call)
2000-10-24 15:15:04 +00:00
Carsten Paeth 02d57b89c8 Too much includes. 2000-10-24 15:08:47 +00:00
Olaf Stoyke 19932ef38a Removing CAPI4Linux from I4L CVS. 2000-10-18 06:41:03 +00:00
Olaf Stoyke ddc1719fe9 Removing CAPI4Linux from I4L CVS. 2000-10-18 06:23:45 +00:00
Olaf Stoyke 3e10ab3581 Removing CAPI4Linux from I4L CVS. 2000-10-18 06:13:34 +00:00
Carsten Paeth c6835e540e Bugfix: second iput(inode) on umount, destroies a foreign inode. 2000-10-12 10:12:35 +00:00
Kai Germaschewski cce70b04bd changes from/for 2.2.18 2000-10-10 17:44:19 +00:00
Detlef Wengorz f5f22ceaae fix wrong abc prototype 2000-10-04 08:55:33 +00:00
Karsten Keil 4c3304e07b Fix NULL pointer error (thanks Luca Montecchia) 2000-10-02 17:33:43 +00:00
Paul Slootman 0d448fd90b fix for imon "incoming" while dialing _out_.
From James Courtier-Dutton <jcdutton@lucent.com>
2000-09-28 18:31:43 +00:00
Karsten Keil 7ed89938e8 add Ovislink ISDN sc100-p card 2000-09-19 14:43:55 +00:00
Kai Germaschewski 515f552555 fix some #ifdef to work better with std2kern -u 2000-09-12 19:43:47 +00:00
Armin Schindler d92cee6b06 fixed standalone version for compiled in kernel. 2000-09-12 15:37:24 +00:00
Detlef Wengorz ad87b5f637 add support for iptables version 1.1.1 and 1.1.2 (alpha-state)
for testing the user-space-tools (add-ons for iptables) are in
the i4l-utilitys/isdnctrl directory
2000-09-10 20:29:18 +00:00
Werner Cornelius 82cf44d24b Added HFC-SP PCMCIA support 2000-09-08 22:56:59 +00:00
Werner Cornelius 2bfd2e6d27 Added support for HFC-SP PCMCIA handling 2000-09-08 22:55:59 +00:00
Werner Cornelius 332f0a167f Added shared IRQ flag 2000-09-07 20:33:30 +00:00
Armin Schindler 5178acdda6 new checksum. 2000-09-04 18:15:03 +00:00
Armin Schindler fcb5c09a73 didd buffer should be zeroed before use. 2000-09-04 18:14:34 +00:00
Armin Schindler be6159b8b4 new checksum. 2000-09-02 11:18:01 +00:00
Armin Schindler 87a64c35b9 better checks of didd table buffer. 2000-09-02 11:16:47 +00:00
Armin Schindler 2b10490472 new checksum 2000-08-30 17:56:22 +00:00
Armin Schindler 06a0c7ce8d Changed internal IDI interface to be
compatible with existing software.
2000-08-30 17:54:15 +00:00
Carsten Paeth d469954416 - increased constants for maximum applications and controllers 2000-08-22 10:11:00 +00:00
Karsten Keil d6a3779566 Supports Class1 and Class2 comands 2000-08-20 16:48:41 +00:00
Karsten Keil fc9cf85ef8 Changes for 2.4 2000-08-20 16:46:09 +00:00
Karsten Keil 1abb46af72 changes for 2.4 2000-08-20 07:42:23 +00:00
Karsten Keil 5ba4067be9 changes from 2.4 2000-08-20 07:40:14 +00:00
Karsten Keil be992a3718 Change from 2.4 2000-08-20 07:35:46 +00:00
Karsten Keil 1586cc119e fix typos 2000-08-20 07:34:04 +00:00
Karsten Keil 8d0bcedb83 Add more PCI ids 2000-08-20 07:32:55 +00:00
Karsten Keil 7e40a07ed5 avoid none inlined memcpy 2000-08-20 07:31:30 +00:00
Karsten Keil e738bab3c4 changes for 2.4 2000-08-20 07:30:13 +00:00
Armin Schindler 9280a659cd fix typo. 2000-08-13 12:19:15 +00:00
Armin Schindler e485318794 new checksum for idi.c 2000-08-13 12:08:10 +00:00
Armin Schindler b89e76688e removed not needed code. 2000-08-13 12:05:46 +00:00
Armin Schindler 5affd1c32d packet queue also for async connections. 2000-08-12 18:00:47 +00:00
Armin Schindler 22e38fe1bf fixed problem of too small queue. 2000-08-12 15:06:11 +00:00
Kai Germaschewski fdbd010ff3 fine with 2.2 and 2.4 as far as I can see 2000-08-11 21:59:39 +00:00
Kai Germaschewski 755193f764 in sync with 2.4, compiles with 2.2 - 2.2 is untested yet 2000-08-10 22:52:46 +00:00
Olaf Stoyke 9b100d87ae CAPI4Linux. 2000-08-10 15:07:42 +00:00
Olaf Stoyke b0b55c3cf5 CAPI4Linux. 2000-08-10 14:55:20 +00:00
Olaf Stoyke 80886101d9 CAPI4Linux. 2000-08-10 14:46:25 +00:00
Carsten Paeth aeffee33b5 calls to pci_enable_device surounded by #ifndef COMPAT_HAS_2_2_PCI 2000-08-08 09:24:19 +00:00
Armin Schindler 13600f5366 fixed typo, backported from 2.4.0-test6-pre5 2000-08-06 09:22:51 +00:00
Armin Schindler 900701e406 Fixed esc-character check, backported from 2.4.0-test5 2000-08-05 09:58:26 +00:00
Carsten Paeth d9e55b323a copied wrong from file to file :-( 2000-08-04 15:36:31 +00:00
Carsten Paeth c16aca6071 - Fix unsigned/signed warning in the right way ... 2000-08-04 12:20:08 +00:00
Carsten Paeth 9b7acb5037 - Backported from 2.4.0-test5 2000-08-04 12:19:22 +00:00
Karsten Keil 97d29143ae Fix from Kai Hendrik Stuke against the "HFC FIFO channel BUSY" error 2000-07-26 20:46:47 +00:00
Ulrich Albrecht 8a5db16785 Fixed stupid re-registering bug resulting in system-freeze 2000-07-25 08:07:42 +00:00
Carsten Paeth fba9a03d51 - lock_kernel/unlock_kernel for _release functions. (from 2.4) 2000-07-24 13:42:50 +00:00
Carsten Paeth 9da5835515 - Bugfix: capiminor_del_all_ack completely wrong :-( 2000-07-24 08:49:09 +00:00
Carsten Paeth a6c70f5202 Include isdn_compat.h for people that don't use -p option of std2kern. 2000-07-20 10:23:13 +00:00
Carsten Paeth 7da95bec2d - Made procfs function cleaner and removed variable "begin". 2000-07-20 10:22:27 +00:00
Carsten Paeth 7f3246fe5b Bugfix: driver will not be unregistered, if not cards were detected.
this result in an oops in kcapi.c
2000-07-20 10:21:21 +00:00
Armin Schindler 094b5f4603 did not compile when not module. 2000-07-19 13:45:44 +00:00
Armin Schindler ab98e65b07 new checksum 2000-07-08 11:56:17 +00:00
Armin Schindler 0c0f3bafe4 Fixed va_arg char option.
New version 2.0.12
2000-07-08 11:53:57 +00:00
Karsten Keil f720acb42b Fix problems if NI1 is enabled 2000-07-04 10:24:32 +00:00
Carsten Paeth 94f9feac24 - call to devfs_register was wrong 2000-06-29 13:59:35 +00:00
Carsten Paeth a8fae58846 Bugfix: reinit txdma without interrupt will confuse some AMCC chips. 2000-06-29 13:59:06 +00:00
Karsten Keil d73a20a8da features should be or'ed 2000-06-26 15:13:41 +00:00
Karsten Keil c3ad1dd1cc new: NI1 / NETspider 2000-06-26 13:30:44 +00:00
Karsten Keil 843b1753b8 change NETjet U to NETspider U(Trademark issue)
HiSax is now version 3.5
2000-06-26 11:42:17 +00:00
Karsten Keil c8b8c616a5 remove log messages 2000-06-26 08:59:15 +00:00
Karsten Keil 6e297bb8e6 approve 2000-06-25 11:29:31 +00:00
Karsten Keil da97602862 fix ppc pci_enable stuff 2000-06-25 11:28:48 +00:00
Karsten Keil 393062192c fix problems on none intel 2000-06-25 11:27:56 +00:00
Karsten Keil 5347736a35 Fix double free of skb in v110 mode 2000-06-24 15:52:47 +00:00
Armin Schindler ad930e7ecb removed unnecessary include. 2000-06-21 11:28:42 +00:00
Karsten Keil 26dcbf70f4 approve 2000-06-21 09:58:23 +00:00
Karsten Keil f1375b15ea avoid none inlined memcpy with newer gcc versions 2000-06-21 09:54:30 +00:00
Karsten Keil 74e0a50e2f some support for NI1 decoding (thanks to Will Scales) 2000-06-21 09:52:03 +00:00
Karsten Keil c51f9fc84b fix TEI duplicate assign detection if we use one TEI per channel 2000-06-20 20:46:01 +00:00
Karsten Keil 5a92d32d89 void is not valid in this case, it will not compile under none i386 2000-06-20 18:01:55 +00:00
Karsten Keil 11fd40671f add colon as valid MSN char for NI1 SPID 2000-06-19 20:59:49 +00:00
Karsten Keil 0fc55a091b don't free skb in irq context 2000-06-19 16:51:53 +00:00
Karsten Keil 406eb472b2 don't touch anything if in testmode 2000-06-19 15:19:34 +00:00
Karsten Keil 2ba264c176 2.4 ac21 changes 2000-06-19 15:17:58 +00:00
Karsten Keil 1967246b7e Hangup slaves before master device goes down
Check encap synppp befor calling isdn_ppp_free
2000-06-19 15:15:59 +00:00
Karsten Keil aadbf2fd78 Fix from Petr Novak 2000-06-19 15:12:44 +00:00
Karsten Keil 8b2807c0c1 avoid use of freed structs
changes from 2.4.0-ac21
2000-06-19 15:11:25 +00:00
Carsten Paeth 398beb385c Added Modemsupport! 2000-06-19 13:13:55 +00:00
Karsten Keil b42db20c18 md5 are not valid if preparsed 2000-06-18 16:21:26 +00:00
Karsten Keil ffbb12023e approve 2000-06-18 16:18:44 +00:00
Karsten Keil 67115c4282 - 2.4 PCI changes
- Changes for Power PC with BIG ENDIAN
2000-06-18 16:15:56 +00:00
Karsten Keil 907df89fa6 Fix HYISDN CAPI selection 2000-06-18 16:13:18 +00:00
Karsten Keil 7b312bc61b more changes for 2.4 2000-06-18 16:09:54 +00:00
Karsten Keil fd1c87e173 2.4 PCI changes and some cosmetics 2000-06-18 16:08:18 +00:00
Karsten Keil fe43d8cb58 New 2.4 stuff 2000-06-18 16:06:23 +00:00
Armin Schindler e36f65fb3c Fixed V110 for incoming connections.
SI, BC, HLC and LLC decoding changed.
2000-06-17 14:30:24 +00:00
Karsten Keil 606d0ce2b3 approve 2000-06-16 13:21:57 +00:00
Karsten Keil 5fec73fd33 Support NI1 2000-06-16 13:19:38 +00:00
Karsten Keil 80d4c78303 Support NI1 and NetJet U interface cards 2000-06-16 13:17:15 +00:00
Karsten Keil b50a8d6c58 Support NI1 (US D-channel protocol) 2000-06-16 13:13:56 +00:00
Karsten Keil 1e8aae60f0 Support for SPID used by NI1 2000-06-16 13:12:21 +00:00
Karsten Keil b4139fe973 Support for Siemens PEB 2070 U interface circuit 2000-06-16 13:11:31 +00:00
Karsten Keil d9b4df592a Support for U interface cards
Support for NI1 D-channel protocol
2000-06-16 13:08:47 +00:00
Karsten Keil 2e37e520c3 Support for NetJet U interface cards 2000-06-16 13:06:08 +00:00
Karsten Keil f38f18f38c Make changes for handling SPID in MSN 2000-06-16 13:00:27 +00:00
Karsten Keil 8798cbd5af remove dle debug message in normal operation 2000-06-16 12:53:50 +00:00
Karsten Keil 4acd613f9e <DLE> escape also for receiving HDLC in FAX mode 2000-06-16 12:34:42 +00:00
Karsten Keil 954825b49b Better DTMF detection parameters 2000-06-14 08:47:07 +00:00
Karsten Keil 449fa25ed3 Reset ISAR statemachine after No More Data event in fax HDLC mode 2000-06-14 08:36:53 +00:00
Karsten Keil 9605b12e8f fix typo 2000-06-14 08:34:37 +00:00
Ulrich Albrecht a3447f58d2 Module will now unload more gracefully. 2000-06-13 09:15:07 +00:00
Ulrich Albrecht 09f8e15696 Removed obsolete struct for CAPI-application tracking. 2000-06-13 09:14:26 +00:00
Ulrich Albrecht 6684ed45e0 Changed internal application handling: Registration is now deferred
until a CAPI-message is actually sent to the controller (no good
wasting memory on the card if it's never used anyways).
Module will now unload more gracefully.
2000-06-13 09:13:06 +00:00
Karsten Keil 14da8b0ab1 more MPPP fixes 2000-06-12 16:46:34 +00:00
Armin Schindler 3835fcfa6c new md5sums for verification. 2000-06-12 12:51:44 +00:00
Armin Schindler 06bbbc0e32 fixed BRI card crash, new IRQ handler and
some minor fixes also.
2000-06-12 12:44:02 +00:00
Armin Schindler 3b3c83c05f Added Eicons 4BRI for fax support. 2000-06-12 12:40:37 +00:00
Kai Germaschewski 6c2f52aaed removal of $log, cleanup 2000-06-12 09:20:20 +00:00
Kai Germaschewski 0e0046a758 fix for devfs from kernel tree 2000-06-11 20:56:23 +00:00
Kai Germaschewski de0194bbc8 2.2 doesn't need kernel lock for read, write, poll 2000-06-11 20:05:53 +00:00
Kai Germaschewski 48cc1f988e 2.4 doesn't hold the kernel lock for read, write, poll
small cosmetic changes
2000-06-11 20:04:17 +00:00
Armin Schindler eae9986f04 corrected register S15 fax class 1 protocol value 2000-06-10 14:11:06 +00:00
Kai Germaschewski eeaba88443 minor cosmetics 2000-06-08 11:19:53 +00:00
Armin Schindler 444080450d corrected tei parameter option 2000-06-08 08:50:25 +00:00
Armin Schindler e681a3fc86 Fixed warning message with correct region size. 2000-06-07 19:58:17 +00:00
Detlef Wengorz 5aeb1161d6 fixed endif mistake for CONFIG_ISDN_WITH_ABC_CONN_ERROR 2000-06-05 07:46:19 +00:00
Detlef Wengorz 80e1f22d93 bugfix (skb_free) with droped frames 2000-06-01 12:29:00 +00:00
Karsten Keil 35e0fdcb77 make pci_enable_dev compatible to 2.2 kernel versions 2000-05-29 12:29:18 +00:00
Karsten Keil 160599cc64 approved 2000-05-23 20:47:17 +00:00
Karsten Keil 54fed61e91 generic PCMCIA interface 2000-05-23 20:46:19 +00:00
Karsten Keil 4ff4b97416 debug for wakeup callback 2000-05-23 20:45:05 +00:00
Karsten Keil 08a8e0bd1c support for the upcomming speedfax+ PCI 2000-05-23 18:59:13 +00:00
Karsten Keil 24a9866cf0 CLKDEL is different in NT and TE mode 2000-05-23 18:58:08 +00:00
Karsten Keil 7e23ea5bee fix an other NULL pointer and a missing spin_unlock_irqrestore 2000-05-23 18:56:51 +00:00
Ulrich Albrecht fc43e6389b Fixed stupid kfree on a skbuff 2000-05-23 13:09:23 +00:00
Ulrich Albrecht 8921d2c7d9 Reverted last change in dev->name assignment (broken netdevice.h in 2.3.99pre6?) 2000-05-23 06:48:54 +00:00
Ulrich Albrecht fa1875145b Parameter-checking for app-registration fixed 2000-05-22 10:31:22 +00:00
Armin Schindler 74ed9373c9 Fixed blocking open, patch from Herbert Nachtnebel. 2000-05-21 10:46:32 +00:00
Karsten Keil 7c6d5ae19a cleanup 2000-05-19 18:45:01 +00:00
Karsten Keil 18db97b00a approve 2000-05-19 18:42:02 +00:00
Karsten Keil 52f509f83b implement codeset shift procedure for IE checking 2000-05-19 18:40:57 +00:00
Karsten Keil 17b44ed7a1 some debug for upstream packets 2000-05-19 18:39:41 +00:00
Carsten Paeth f8231d1c15 added calls to pci_device_start(). 2000-05-19 15:43:22 +00:00
Karsten Keil 465c72a343 port the new MPPP bundle code from Semyon Ariel to the new flow control 2000-05-18 23:14:19 +00:00
Carsten Paeth b0e1f0019f Uaaahh. Bad memory leak fixed. 2000-05-18 16:35:43 +00:00
Ulrich Albrecht 77d30ae3c3 Updated to reflect CAPI 2.0 support 2000-05-17 11:59:14 +00:00
Ulrich Albrecht f1bb4ec7f3 Fixed a NULL-pointer kernel-oops assigning the device-name 2000-05-17 11:43:03 +00:00
Ulrich Albrecht 19995602cf CAPI 2.0 support added 2000-05-17 11:41:30 +00:00
Ulrich Albrecht 65b90b66ff Initial release 2000-05-17 11:34:30 +00:00
Ulrich Albrecht 50247a03fd Added HYSDN-Capi 2.0 support 2000-05-17 11:25:05 +00:00
Karsten Keil 4c8eeec66c Support all 4 BRI lines with one driver 2000-05-16 20:56:41 +00:00
Karsten Keil 0525ffa44d Include changes from official kernel 2000-05-16 20:54:05 +00:00
Karsten Keil d6da4a3374 Fix comments 2000-05-16 20:52:10 +00:00
Karsten Keil 3daf2bf3f6 Fix a well defined NULL pointer access in MPPP 2000-05-16 15:13:13 +00:00
Kai Germaschewski 3c40de9658 removal of Log lines 2000-05-11 22:29:22 +00:00
Armin Schindler b380e325dc removed log entries from code.
changed transmit queue handling.
fixed sometimes null pointer in fax struct.
2000-05-07 08:51:04 +00:00
Kai Germaschewski 7f5ba93f21 merged changes from kernel tree
fixed timer and net_device->name breakage
2000-05-06 00:52:40 +00:00
Karsten Keil 12bbd4eea8 approve changes 2000-04-27 10:34:07 +00:00
Karsten Keil 08a5b82b93 implement overlap receiving 2000-04-27 10:31:02 +00:00
Armin Schindler 9e2d2a82fa Re-added direct sending if bit 0 of reg 13 is set,
this time outside locking.
2000-04-24 20:38:17 +00:00
Kai Germaschewski 25fde20769 merge changes from main tree 2000-04-23 14:18:36 +00:00
Carsten Paeth ac727efe2d Revision in b1pciv4 driver was missing. 2000-04-21 13:01:33 +00:00
Carsten Paeth 22eb62c099 Bugfix: driver_proc_info was also wrong. 2000-04-21 13:00:56 +00:00
Carsten Paeth 177623b836 Bugfix: error in proc_ functions, begin-off => off-begin 2000-04-21 12:38:42 +00:00
Karsten Keil 4ca61103a2 aprove changes in l3/l2 2000-04-12 20:30:15 +00:00
Karsten Keil 37d344cc1d a I frame may be contain zero information bytes 2000-04-12 20:28:37 +00:00
Kai Germaschewski a4c02dd38d fix max iframe size
fix bug in multicasting DL_RELEASE_IND
2000-04-12 16:41:01 +00:00
Karsten Keil 71ce6b5be4 cleanup 2000-04-11 11:12:39 +00:00
Karsten Keil 60f0764d01 Bugfix: reset IRQ enable only valid for PCI version 2000-04-09 19:09:19 +00:00
Karsten Keil d58c8c0188 retry pump modulation settings if it fails 2000-04-09 19:02:44 +00:00
Armin Schindler cba7e6d378 spinlock changes and compiler warnings removed. 2000-04-09 15:43:56 +00:00
Carsten Paeth 0a5aa29b11 better error message if cabel not connected or T1 has no power. 2000-04-07 15:26:55 +00:00
Carsten Paeth 9cdecfcbcb remove warnings 2000-04-07 15:19:58 +00:00
Carsten Paeth fdc54378fe Bugfix: on my system 2.3.99-pre3 Dual PII 350, unload of module isdn.o
hangs if vfree is called with interrupt disabled. After moving
	restore_flags in front of vfree it doesn't hang.
2000-04-07 14:50:34 +00:00
Armin Schindler 8b747f9b1f Fixed ugly BSENT bug, which caused bad performance. 2000-04-06 20:05:44 +00:00
Carsten Paeth 5f8dd069ce Bugfix: crash in capidrv.c when reseting a capi controller.
- changed code order on remove of controller.
- using tq_schedule for notifier in kcapi.c.
- now using spin_lock_irqsave() and spin_unlock_irqrestore().
strange: sometimes even MP hang on unload of isdn.o ...
2000-04-06 15:01:25 +00:00
Detlef Wengorz fafbf7d96f add leased-line support to abc-stuff 2000-04-05 21:25:55 +00:00
Detlef Wengorz ebdaa8c5b5 change write_super handling for abc-stuff 2000-04-03 21:07:22 +00:00
Kai Germaschewski 89ec768bf8 fix "isdn BUG at isdn_net.c:1440!" 2000-04-03 19:14:36 +00:00
Carsten Paeth 714a4d6482 Makefile checked in with future things :-( 2000-04-03 16:39:25 +00:00
Carsten Paeth 64753ae814 made suppress_pollack static. 2000-04-03 16:38:05 +00:00
Carsten Paeth ecc76e2349 make Tim Waugh happy (module unload races in 2.3.99-pre3).
no real problem there, but now it is much cleaner ...
2000-04-03 13:29:25 +00:00
Armin Schindler aafb2b7e76 Modifications for new eicon driver. 2000-04-02 22:00:49 +00:00
Armin Schindler b1f8ecfea7 Added md5sum for filecheck. 2000-04-02 21:59:12 +00:00
Armin Schindler 390db3a46d Start of new driver V2. 2000-04-02 21:56:34 +00:00
Kai Germaschewski c86c3637cb merge changes from official kernel tree 2000-03-25 15:24:34 +00:00
Detlef Wengorz 50c3eea967 remove om the fly-limit from kernel-help-file 2000-03-25 12:51:08 +00:00
Kai Germaschewski 2cf873e4a2 We don't need a lock at all in 2.2 (BH's are single threaded) 2000-03-23 12:29:47 +00:00
Kai Germaschewski 1ea93bb122 fix backwards compatibility 2000-03-21 23:53:22 +00:00
Detlef Wengorz de9aef0045 modify abc-extension to work together with the new LL.
remove abc frame-counter (is obsolete now).
use the new lp->super_tx_queue for internal queueing (bsd-rawip-compress).
modify isdn_net_xmit() and isdn_net_write_super().
-- Kai, please have a look to this two function's. Thank's.
2000-03-20 22:37:47 +00:00
Kai Germaschewski 163a1f20d3 no known bugs left... 2000-03-19 15:27:53 +00:00
Kai Germaschewski 15e7682f1b changed keypad to use specified bearer, instead of always a-law 2000-03-19 15:26:35 +00:00
Carsten Paeth 126be487cf PPP over CAPI raw driver disabled for now, ppp_generic has been changed. 2000-03-19 12:31:36 +00:00
Kai Germaschewski 0ac93e1484 cosmetics / renaming 2000-03-18 16:20:26 +00:00
Kai Germaschewski 20b601d4f2 didn't even compile... now it does, and it works here 2000-03-17 19:23:18 +00:00
Kai Germaschewski 76aa55904e moved to frame_cnt based flow control
some races still need to be fixed
2000-03-17 18:20:47 +00:00
Kai Germaschewski 0ae6bc1923 cleanup 2000-03-17 17:01:00 +00:00
Kai Germaschewski 970c99e55b we keep track of outstanding packets (given to HL, but not confirmed yet)
now, but we don't use it for flow control yet.
2000-03-17 16:22:55 +00:00
Kai Germaschewski eb9393dd8d the current CVS tree now compiles in 2.3.99 without CONFIG_DEVFS_FS 2000-03-17 13:10:03 +00:00
Kai Germaschewski eb13d25d81 calling statcallb with ISDN_STAT_BSENT in hard-IRQ context is now
officially allowed. writebuf_skb() will never be called in hard-IRQ context
anymore.
2000-03-17 12:49:42 +00:00
Carsten Paeth 10f9c57517 send patchvalues now working. 2000-03-17 12:21:08 +00:00
Carsten Paeth 06fe2c8d3c ALL_SUB_DIRS were wrong. 2000-03-17 12:15:44 +00:00
Kai Germaschewski 748d718685 2.3.99 contains MPPP constants which cause a warning because we
redefine them in include/linux/isdn_ppp.h

So from now on we use the generic PPP constants, change is backwards
compatible, though
2000-03-17 10:43:56 +00:00
Kai Germaschewski 6af1d2d4fe fixed oops when dialing out without l3 protocol selected 2000-03-17 07:07:42 +00:00
Werner Cornelius 5ee13e2749 Fixed an additional location 2000-03-16 23:24:11 +00:00
Werner Cornelius d693b4790f Tried to fix second B-channel problem (still not tested) 2000-03-16 22:41:36 +00:00
Kai Germaschewski 93ae560439 Allow phone numbers starting with "*" as outgoing numbers for
networking interface. Some PBX's need this to allow dialing internal
numbers (mine, for example ;-)
2000-03-16 16:37:41 +00:00
Kai Germaschewski 76824fd61f some translation work
there shouldn't be any German comments lurking around anymore ;-)
2000-03-16 16:34:12 +00:00
Kai Germaschewski d4564c64a0 a little bugfix and cosmetic changes 2000-03-16 15:46:37 +00:00
Carsten Paeth 7e3431614d Bugfix in c4_remove: loop 5 times instead of 4 :-( 2000-03-16 15:21:03 +00:00
Carsten Paeth e103e143d0 Added avm_cs.c for 2.3.x PCMCIA support. 2000-03-13 17:50:55 +00:00
Carsten Paeth 3ea1695777 make it running with 2.3.51. 2000-03-13 17:49:52 +00:00
Carsten Paeth 1893040935 removed unused variable. 2000-03-13 17:48:13 +00:00
Carsten Paeth ba3d40acf1 - 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)
2000-03-08 17:06:34 +00:00
Carsten Paeth 31c5aa1fcb - Middleware extention now working with 2.3.49 (capifs).
- Fixed typos in debug section of capi.c
- Bugfix: Makefile corrected for b1pcmcia.c
2000-03-06 18:00:23 +00:00
Armin Schindler fc0a456c2b Added example for PtP configuration. 2000-03-06 16:38:43 +00:00
Armin Schindler c21c174ada Fixed incomplete number handling with BRI PtP connection. 2000-03-06 15:45:17 +00:00
Carsten Paeth 0402c2d424 - capifs: fileoperations now in inode (change for 2.3.49)
- Config.in: Middleware extention not a tristate, uups.
2000-03-06 09:17:07 +00:00
Armin Schindler 0c335333cc Fix of statemachine, B-connect before D-connect,
thanks to Helmut Adams <adams@ipcon.de>
Minor change in send-data packet handling.
2000-03-04 17:04:21 +00:00
Detlef Wengorz 00071128e4 copy frames before rewriting frame's saddr 2000-03-04 16:20:42 +00:00
Carsten Paeth 189065cec0 - 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.
2000-03-03 16:48:38 +00:00
Kai Germaschewski ae7e6db007 incorporated some cosmetic changes from the official kernel tree back
into CVS
2000-03-03 16:37:12 +00:00
Carsten Paeth 7fe092d9a5 - 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.
2000-03-03 15:50:42 +00:00
299 changed files with 40307 additions and 20537 deletions

View File

@ -1,6 +1,6 @@
--- Configure.help.orig Wed Dec 15 20:35:10 1999
+++ Configure.help Wed Dec 15 20:35:33 1999
@@ -11317,6 +11317,172 @@
--- /usr/src/linux/Documentation/Configure.help Sat Mar 25 09:22:49 2000
+++ Configure.help Sat Mar 25 09:29:13 2000
@@ -12738,6 +12738,160 @@
Please read the file Documentation/isdn/README.diversion.
@ -141,18 +141,6 @@
+ 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
+

View File

@ -31,7 +31,7 @@ README.act2000
README.eicon
- info on driver for Eicon active cards.
README.concap
- info on "CONCAP" ecapsulation protocol interface used for X.25.
- info on "CONCAP" encapsulation protocol interface used for X.25.
README.diversion
- info on module for isdn diversion services.
README.sc
@ -40,4 +40,4 @@ README.x25
_ info for running X.25 over ISDN.
README.hysdn
- info on driver for Hypercope active HYSDN cards

View File

@ -20,6 +20,23 @@ 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.
Additional ITU approval tests have been carried out for all generic cards
using Colognechip single chip solutions HFC-S PCI A for PCI cards as well
as HFC-S USB based USB ISDN ta adapters.
These tests included all layers 1-3 and as well all functional tests for
the layer 1. Because all hardware based on these chips are complete ISDN
solutions in one chip all cards and USB-TAs using these chips are to be
regarded as approved for those tests. Some additional electrical tests
of the layer 1 which are independant of the driver and related to a
special hardware used will be regarded as approved if at least one
solution has been tested including those electrical tests. So if cards
or tas have been completely approved for any other os, the approval
for those electrical tests is valid for linux, too.
Please send any questions regarding this drivers or approval abouts to
werner@isdn-development.de
Additional information and the type approval documents will be found
shortly on the Colognechip website www.colognechip.com
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
@ -50,6 +67,9 @@ drivers/isdn/hisax/l3_1tr6.c
drivers/isdn/hisax/cert.c
drivers/isdn/hisax/elsa.c
drivers/isdn/hisax/diva.c
drivers/isdn/hisax/hfc_pci.c
drivers/isdn/hisax/hfc_usbr.c
drivers/isdn/hisax/hfc_usb.c
Please send any changes, bugfixes and patches to me rather than implementing
them directly into the HiSax sources.

View File

@ -399,7 +399,7 @@ Description of the Interface between Linklevel and Hardwarelevel
protocol-Id is one of the constants ISDN_PROTO_L3...
parm.fax = Pointer to T30_s fax struct. (fax usage only)
ISDN_CMD_GETL2: (currently unused)
ISDN_CMD_GETL3: (currently unused)
With this command, the HL-driver is told to return the current
setting of the Layer-3-protocol.
@ -480,8 +480,8 @@ Description of the Interface between Linklevel and Hardwarelevel
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
arg = The lower 8 Bits define the addressed protocol as defined
in ISDN_PTYPE..., the upper bits are used to differentiate
the protocol specific CMD.
para = protocol and function specific. See isdnif.h for detail.
@ -734,7 +734,7 @@ Description of the Interface between Linklevel and Hardwarelevel
Parameter:
driver = driver-Id
command = ISDN_STAT_PROT
arg = The lower 8 Bits define the adressed protocol as defined
arg = The lower 8 Bits define the addressed protocol as defined
in ISDN_PTYPE..., the upper bits are used to differenciate
the protocol specific STAT.
@ -748,7 +748,7 @@ Description of the Interface between Linklevel and Hardwarelevel
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
The LL returns a nonzero code if the operation was not successful or the
selected channel is actually regarded as busy.
Parameter:
@ -781,3 +781,22 @@ Description of the Interface between Linklevel and Hardwarelevel
arg = channel-number, locally to the driver. (starting with 0)
parm = unused.
ISDN_STAT_ALERT:
With this call, the HL-driver signals the receive of an ALERTING message to the LL.
Parameter:
driver = driver-Id
command = ISDN_STAT_ALERT
arg = channel-number, locally to the driver. (starting with 0)
ISDN_STAT_PROCEED:
With this call, the HL-driver signals the receive of an CALL PROCEEDING message
to the LL.
Parameter:
driver = driver-Id
command = ISDN_STAT_PROCEED
arg = channel-number, locally to the driver. (starting with 0)

View File

@ -4,7 +4,7 @@ $Id$
Description of the fax-subinterface between linklevel and hardwarelevel of
isdn4linux.
The communication between linklevel (LL) and harwarelevel (HL) for fax
The communication between linklevel (LL) and hardwarelevel (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
@ -60,7 +60,7 @@ Structure T30_s:
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).
only necessary on call establishment (from IDLE to PHASE_A).
(one of the constants ISDN_FAX_PHASE_[IDLE,A,B,C,D,E])
- direction

View File

@ -146,7 +146,7 @@ README for the ISDN-subsystem
x = 38400: 198
Note on value in Reg 19:
There is _NO_ common convention for 38400 baud.
The value 198 is choosen arbitrarily. Users
The value 198 is chosen arbitrarily. Users
_MUST_ negotiate this value before establishing
a connection.
AT&Sx Set window-size (x = 1..8) (not yet implemented)
@ -242,7 +242,7 @@ README for the ISDN-subsystem
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)
3 = 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,
@ -276,6 +276,14 @@ README for the ISDN-subsystem
1 = Add CPN to RING message on
Bit 1: 0 = Add CPN to FCON message off
1 = Add CPN to FCON message on
Bit 2: 0 = Add CDN to RING/FCON message off
1 = Add CDN to RING/FCON message on
Bit 3: 0 = Do not signal RINGING
1 = Signal RINGING if ALERT was received
Bit 4: 0 = Do not signal PROCEEDING
1 = Signal PROCEEDING if CALL PROCEEDING
was received
Last but not least a (at the moment fairly primitive) device to request
the line-status (/dev/isdninfo) is made available.

View File

@ -53,7 +53,8 @@ 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
Traverse Technologie NETjet PCI S0 card and NETspider U card
Ovislink ISDN sc100-p card (NETjet driver)
Dr. Neuhaus Niccy PnP/PCI
Siemens I-Surf 1.0
Siemens I-Surf 2.0 (with IPAC, try type 12 asuscom)
@ -65,19 +66,15 @@ Gazel ISDN cards
HFC-PCI based cards
Winbond W6692 based cards
HFC-S+, HFC-SP/PCMCIA cards
HFC-USB ISDN TAs
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
You can combine any card, if there is no conflict between the resources
(io, mem, irq).
@ -134,7 +131,12 @@ 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).
"2" for EDSS1 (Euro ISDN), "3" for leased lines (no D-Channel) and "4"
for US NI1.
With US NI1 you have to include your SPID into the MSN setting in the form
<MSN>:<SPID> for example (your phonenumber is 1234 your SPID 5678):
AT&E1234:5678 on ttyI interfaces
isdnctrl eaz ippp0 1234:5678 on network devices
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.
@ -186,8 +188,9 @@ Card types:
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)
37 HFC 2BDS0 S+, SP irq,io
38 NETspider U PCI card none
39 HFC 2BDS0 SP/PCMCIA irq,io (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.
@ -291,7 +294,9 @@ type
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
37 HFC 2BDS0 S+,SP/PCMCIA ONLY WORKS AS A MODULE !
38 NETspider U PCI card none
Running the driver
------------------
@ -433,6 +438,7 @@ Special thanks to:
Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff
Ton van Rosmalen for Teles PCI
Petr Novak <petr.novak@i.cz> for Winbond W6692 support
Werner Cornelius <werner@isdn4linux.de> for HFC-PCI, HFC-S(+/P) and supplementary services support
and more people who are hunting bugs. (If I forgot somebody, please
send me a mail).
@ -532,7 +538,7 @@ to e.g. the Internet:
/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
# The incoming 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.
@ -551,7 +557,7 @@ a) Use state of the art isdn4k-utils
Here an example script:
#!/bin/sh
# Start/Stop ISDN lesaed line connection
# Start/Stop ISDN leased line connection
I4L_AS_MODULE=yes
I4L_REMOTE_IS_CISCO=no

View File

@ -7,7 +7,7 @@ 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
The ISA-Bus Version uses 8 IO-ports. The base port address has to be set
manually using the DIP switches.
Setting up the DIP switches for the IBM Active 2000 ISDN card:

View File

@ -175,7 +175,7 @@ a mail to majordomo@calle.in-berlin.de with
subscribe linux-avmb1
in the body.
German documentaion and several scripts can be found at
German documentation and several scripts can be found at
ftp://ftp.avm.de/cardware/b1/linux/
Bugs

View File

@ -68,7 +68,7 @@ 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
asynchronous 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.

View File

@ -6,7 +6,7 @@ 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.
GNU General 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
@ -57,7 +57,7 @@ Table of contents
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
The rules include primary and secondary service identifiers, 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.
@ -82,7 +82,7 @@ Table of contents
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
The dynamic diversion services 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

View File

@ -40,6 +40,7 @@ DIVA Server family
------------------
- DIVA Server BRI/PCI 2M
- DIVA Server PRI/PCI 2M (9M 23M 30M)
- DIVA Server 4BRI/PCI
supported functions of onboard DSPs:
- analog modem
- fax group 2/3 (Fax Class 2 commands)
@ -78,6 +79,10 @@ 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 -t1 -s1
Example for loading and starting a PRI card with E-DSS1 Protocol.
@ -95,6 +100,7 @@ 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
@ -109,3 +115,4 @@ Have fun !
Armin Schindler
mac@melware.de
http://www.melware.de

View File

@ -24,6 +24,9 @@ Supported ISDN-Cards
Eicon DIVA Server BRI/PCI
- full support with both B-channels.
Eicon DIVA Server 4BRI/PCI
- full support with all B-channels.
Eicon DIVA Server PRI/PCI
- full support on amount of B-channels
depending on DSPs on board.

View File

@ -35,7 +35,7 @@ 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 .
Comments and reports to werner@isdn4linux.de or werner@isdn-development.de

View File

@ -2,7 +2,11 @@ $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.
under the GNU General Public License.
The CAPI 2.0-support was added by Ulrich Albrecht (ualbrecht@hypercope.de)
for Hypercope GmbH Aachen, 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
@ -41,15 +45,19 @@ Table of contents
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
These cards provide two different interfaces to the kernel. Without the
optional CAPI 2.0 support, they register as ethernet card. IP-routing
to a ISDN-destination is performed on the card itself. 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.
With CAPI 2.0 support enabled, the card can also be used as a CAPI 2.0
compliant devices with either CAPI 2.0 applications
(check isdn4k-utils) or -using the capidrv module- as a regular
isdn4linux device. This is done via the same mechanism as with the
active AVM cards and in fact uses the same module.
2. Loading/Unloading the driver
@ -58,7 +66,14 @@ Table of contents
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.
unload.
If you are using the CAPI 2.0-interface, make sure to load/modprobe the
kernelcapi-module first.
If you plan to use the capidrv-link to isdn4linux, make sure to load
capidrv.o after all modules using this driver (i.e. after hysdn and
any avm-specific modules).
3. Entries in the /proc filesystem
@ -92,7 +107,7 @@ Table of contents
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 this card. Up to the first successful 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.
@ -128,12 +143,12 @@ Table of contents
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
appropriate 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
written to the cardlog file independent of the following options only used
to check and debug the driver itself:
For example:
@ -160,8 +175,11 @@ Table of contents
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)
the Hypercope support team (support@hypercope.de) and or the authors
Werner Cornelius (werner@isdn4linux or cornelius@titro.de) or
Ulrich Albrecht (ualbrecht@hypercope.de).

View File

@ -139,7 +139,7 @@ Loading the firmware into the card:
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
-> After downloading 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.

249
capi2kern Executable file
View File

@ -0,0 +1,249 @@
#!/bin/sh
KERNELDIR=/usr/src/Linux-Kernel/v2.2.18-pre9
KERNELDIR=/usr/src/Linux-Kernel/v2.2.17-pre5
KERNELDIR=/usr/src/Linux-Kernel/v2.2.15
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<<EOM
std2kern is used for updating your kernel-tree from within
this directory.
std2kern [-d] [-h] [-k DIR] [-v] [-u] [-c FILE] [files ...]
Options:
-h This Text.
-d Copy depends on modification date instead of file-compare.
-k DIR Kerneltree is in DIR instead of /usr/src/linux
-v More mesages about processing
-u Make a diff for a unique kernel-tree
(preprocessing with $PREPARSER)
-c FILE Use FILE as control file for $PREPARSER (only with -u)
-t Test, don't really copy files
Without any files given, within the whole tree, the "right"
files are copied. When any files are given in the commandline,
only those are copied.
EOM
exit
}
#
# Check, if argument is a linux kernel dir
#
checkkernel() {
if [ -f $1/Makefile ] ; then
if [ "`grep ^vmlinux: $1/Makefile | grep vmlinux`" != "" ] ; then
return 0
fi
fi
echo "The given argument does not look like a kernel dir"
exit 1
}
#
# Determine a control file name
#
calc_ctrl_file() {
eval `sed -n 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' $KERNELDIR/Makefile`
echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL"
if [ -z "$CTRLNAME" ] ; then
CTRLNAME=v$VERSION.$PATCHLEVEL.$SUBLEVEL.ctrl
if [ -f $CTRLNAME ] ; then
return 0
fi
CTRLNAME=v$VERSION.$PATCHLEVEL.ctrl
if [ -f $CTRLNAME ] ; then
return 0
fi
CTRLNAME=default.ctrl
fi
if [ -f $CTRLNAME ] ; then
return 0
fi
echo "No control file found"
exit 1
}
while getopts :dhk:uc:vt a ; do
case $a in
\?) case $OPTARG in
k) echo "-k requires Kernel directory parameter"
;;
*) echo "Unknown option: -$OPTARG"
echo "Try std2kern -h"
;;
esac
exit 1
;;
k) checkkernel $OPTARG
KERNELDIR=$OPTARG
;;
c) CTRLNAME=$OPTARG
;;
u) UNIQUE=true
;;
v) VERBOSE=true
;;
t) NOTEST=false
;;
d) DOCP=docp
;;
h) usage
;;
esac
done
shift `expr $OPTIND - 1`
if $UNIQUE ; then
DOCP=docpuni
calc_ctrl_file
fi
echo -n "Using $DOCP"
if $UNIQUE ; then
echo " with controlfile $CTRLNAME"
else
echo
fi
if [ $# != 0 ]; then
for i in $* ; do
$DOCP $i $KERNELDIR/$i
done
else
for i in drivers/isdn/avmb1/*.[ch] ; do
$DOCP $i $KERNELDIR/$i
done
for i in \
include/linux/kernelcapi.h \
include/linux/capi.h \
include/linux/b1lli.h \
include/linux/b1pcmcia.h \
; do
$DOCP $i $KERNELDIR/$i
done
for i in drivers/isdn/avmb1/Makefile; do
if [ -f $i.kernel ] ; then
if $UNIQUE ; then
docpd $i.kernel $KERNELDIR/$i
else
$DOCP $i.kernel $KERNELDIR/$i
fi
else
if $UNIQUE ; then
docpd $i $KERNELDIR/$i
else
$DOCP $i $KERNELDIR/$i
fi
fi
done
fi

170
capidiff Executable file
View File

@ -0,0 +1,170 @@
#!/bin/sh
KERNELDIR=/usr/src/linux
KERNFIRST=false
PREPARSER="./preparser"
DODIFF=dodiff
UNIQUE=false
dodiff() {
if $KERNFIRST ; then
diff -u -bB $EXTRAOPT $2 $1
else
diff -u -bB $EXTRAOPT $1 $2
fi
}
dodiffuni() {
echo -n "Processing $1 ... "
TMPNAME=/tmp/`basename $1`.$$
$PREPARSER -c $CTRLNAME $1 $TMPNAME
RES=$?
if [ "$RES" -eq "0" ] ; then
echo diff original
dodiff $1 $2
rm $TMPNAME
return 0
fi
if [ "$RES" -eq "2" ] ; then
echo diff modified
dodiff $TMPNAME $2
rm $TMPNAME
return 0
fi
echo "problem with $PREPARSER retcode $RES"
exit 1
}
#
# Print usage and exit
#
usage() {
cat<<EOM
stddiff is used for generating diffs of the cvs-tree
versus the kernel-tree.
stddiff [-r] [-h] [-k DIR] [-u] [-c FILE] [-w] [files ...]
Options:
-h This Text.
-r Reverse direction (kernel versus cvs).
-k DIR Kerneltree is in DIR instead of /usr/src/linux
-u Make a diff for a unique kernel-tree
(preprocessing with $PREPARSER)
-c FILE Use FILE as control file for $PREPARSER (only with -u)
-w Ignore white space when comparing lines
Without any files given, within the whole tree, the "right"
files are diffed. When any files are given in the commandline,
only those are diffed.
EOM
exit
}
#
# Check, if argument is a linux kernel dir
#
checkkernel() {
if [ -f $1/Makefile ] ; then
if [ "`grep ^vmlinux: $1/Makefile | grep vmlinux`" != "" ] ; then
return 0
fi
fi
echo "The given argument does not look like a kernel dir"
exit 1
}
#
# Determine a control file name
#
calc_ctrl_file() {
eval `sed -n 's/^\([A-Z]*\) = \([0-9]*\)$/\1=\2/p' $KERNELDIR/Makefile`
echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL"
if [ -z "$CTRLNAME" ] ; then
CTRLNAME=v$VERSION.$PATCHLEVEL.$SUBLEVEL.ctrl
if [ -f $CTRLNAME ] ; then
return 0
fi
CTRLNAME=v$VERSION.$PATCHLEVEL.ctrl
if [ -f $CTRLNAME ] ; then
return 0
fi
CTRLNAME=default.ctrl
fi
if [ -f $CTRLNAME ] ; then
return 0
fi
echo "No control file found"
exit 1
}
while getopts :rhk:uc:w a ; do
case $a in
\?) case $OPTARG in
k) echo "-k requires Kernel directory parameter"
;;
*) echo "Unknown option: -$OPTARG"
echo "Try stddiff -h"
;;
esac
exit 1
;;
k) checkkernel $OPTARG
KERNELDIR=$OPTARG
;;
c) CTRLNAME=$OPTARG
;;
u) UNIQUE=true
;;
r) KERNFIRST=true
;;
w) EXTRAOPT=-w
;;
h) usage
;;
esac
done
shift `expr $OPTIND - 1`
if $UNIQUE ; then
DODIFF=dodiffuni
calc_ctrl_file
fi
echo -n "Using $DODIFF $EXTRAOPT"
if $UNIQUE ; then
echo " with controlfile $CTRLNAME"
else
echo
fi
if [ $# != 0 ]; then
for i in $* ; do
$DODIFF $i $KERNELDIR/$i
done
else
for i in drivers/isdn/avmb1/*.[ch] ; do
$DODIFF $i $KERNELDIR/$i
done
for i in \
include/linux/kernelcapi.h \
include/linux/capi.h \
include/linux/b1lli.h \
include/linux/b1pcmcia.h \
; do
$DODIFF $i $KERNELDIR/$i
done
for i in drivers/isdn/avmb1/Makefile ; do
if [ -f $i.kernel ] ; then
dodiff $i.kernel $KERNELDIR/$i
else
dodiff $i $KERNELDIR/$i
fi
done
fi

View File

@ -1,56 +1,53 @@
#
# ISDN device configuration
#
# only included if CONFIG_ISDN != n
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
bool ' Use VJ-compression with synchronous PPP' CONFIG_ISDN_PPP_VJ
bool ' Support generic MP (RFC 1717)' CONFIG_ISDN_MPP
dep_tristate ' Support BSD compression' CONFIG_ISDN_PPP_BSDCOMP $CONFIG_ISDN
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
bool ' Support AT-Fax Class 1 and 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
mainmenu_option next_comment
comment 'ISDN abc-dw-extension'
bool 'Enable isdn-abc-dw-extension' CONFIG_ISDN_WITH_ABC
if [ "$CONFIG_ISDN_WITH_ABC" != "n" ]; then
bool ' Use D-Channel-Callback with Channel in use check' CONFIG_ISDN_WITH_ABC_CALLB
bool ' Enable Outgoing-EAZ-Support' CONFIG_ISDN_WITH_ABC_OUTGOING_EAZ
bool ' Enable LCR-Support (need isdnlog)' CONFIG_ISDN_WITH_ABC_LCR_SUPPORT
bool ' RX dont reset hanguptimeout' CONFIG_ISDN_WITH_ABC_RCV_NO_HUPTIMER
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
bool ' Enable UDP-Info-Support' CONFIG_ISDN_WITH_ABC_UDP_CHECK
if [ "$CONFIG_ISDN_WITH_ABC_UDP_CHECK" != "n" ]; then
bool ' Enable Hangup-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
bool ' Enable Dial-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
fi
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
bool ' Enable Hangup-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_HANGUP
bool ' Enable Dial-Support with UDP-INFO' CONFIG_ISDN_WITH_ABC_UDP_CHECK_DIAL
fi
fi
endmenu
bool ' Skip channel if used external (dial only)' CONFIG_ISDN_WITH_ABC_CH_EXTINUSE
bool ' Support interface-auto-disable if config-error' CONFIG_ISDN_WITH_ABC_CONN_ERROR
if [ "$CONFIG_ISDN_PPP" != "n" ]; then
bool ' Enable Compression with rawip and x75i' CONFIG_ISDN_WITH_ABC_RAWIPCOMPRESS
fi
fi
endmenu
mainmenu_option next_comment
comment 'ISDN feature submodules'
dep_tristate 'isdnloop support' CONFIG_ISDN_DRV_LOOP $CONFIG_ISDN
bool 'Support isdn diversion services' CONFIG_ISDN_DIVERSION
dep_tristate 'Support isdn diversion services' CONFIG_ISDN_DIVERSION $CONFIG_ISDN
endmenu
comment 'low-level hardware drivers'
@ -68,6 +65,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
bool ' Disable keypad protocol option' CONFIG_HISAX_NO_KEYPAD
fi
bool ' HiSax Support for german 1TR6' CONFIG_HISAX_1TR6
bool ' HiSax Support for US NI1' CONFIG_HISAX_NI1
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
@ -86,6 +84,7 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
bool ' USR Sportster internal TA' CONFIG_HISAX_SPORTSTER
bool ' MIC card' CONFIG_HISAX_MIC
bool ' NETjet card' CONFIG_HISAX_NETJET
bool ' NETspider U card' CONFIG_HISAX_NETJET_U
bool ' Niccy PnP/PCI card' CONFIG_HISAX_NICCY
bool ' Siemens I-Surf card' CONFIG_HISAX_ISURF
bool ' HST Saphir card' CONFIG_HISAX_HSTSAPHIR
@ -94,48 +93,93 @@ if [ "$CONFIG_ISDN_DRV_HISAX" != "n" ]; then
bool ' Gazel cards' CONFIG_HISAX_GAZEL
bool ' HFC PCI-Bus cards' CONFIG_HISAX_HFC_PCI
bool ' Winbond W6692 based cards' CONFIG_HISAX_W6692
bool ' HFC-S+, HFC-SP, HFC-PCMCIA cards' CONFIG_HISAX_HFC_SX
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
bool ' HiSax debugging' CONFIG_HISAX_DEBUG
dep_tristate 'Sedlbauer PCMCIA cards' CONFIG_HISAX_SEDLBAUER_CS $CONFIG_PCMCIA
dep_tristate 'ELSA PCMCIA MicroLink cards' CONFIG_HISAX_ELSA_CS $CONFIG_PCMCIA
dep_tristate 'ST5481 USB ISDN modem (EXPERIMENTAL)' CONFIG_HISAX_ST5481 $CONFIG_HISAX $CONFIG_USB $CONFIG_EXPERIMENTAL
dep_tristate 'Fritz!PCIv2 support (EXPERIMENTAL)' CONFIG_HISAX_FRITZ_PCIPNP $CONFIG_HISAX $CONFIG_EXPERIMENTAL
if [ "$CONFIG_HISAX_SEDLBAUER_CS" != "n" ]; then
define_bool CONFIG_HISAX_SEDLBAUER y
fi
if [ "$CONFIG_HISAX_ELSA_CS" != "n" ]; then
define_bool CONFIG_HISAX_ELSA y
fi
if [ "$CONFIG_HISAX_HFC_USB_CS" != "n" ]; then
define_bool CONFIG_HISAX_HFC_USB y
fi
fi
endmenu
### Active ISDN cards
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
dep_tristate 'ICN 2B and 4B support' CONFIG_ISDN_DRV_ICN $CONFIG_ISDN
dep_tristate 'PCBIT-D support' CONFIG_ISDN_DRV_PCBIT $CONFIG_ISDN
dep_tristate 'Spellcaster support' CONFIG_ISDN_DRV_SC $CONFIG_ISDN
dep_tristate 'IBM Active 2000 support' CONFIG_ISDN_DRV_ACT2000 $CONFIG_ISDN
bool 'Eicon active card support' CONFIG_ISDN_DRV_EICON
if [ "$CONFIG_ISDN_DRV_EICON" != "n" ]; then
bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
fi
dep_tristate 'AVM CAPI2.0 support' CONFIG_ISDN_DRV_AVMB1 $CONFIG_ISDN
if [ "$CONFIG_ISDN_DRV_AVMB1" != "n" ]; then
bool ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA
bool ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI
if [ "$CONFIG_ISDN_DRV_AVMB1_B1PCI" != "n" ]; then
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
bool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4
if [ "$CONFIG_ISDN_DRV_EICON_OLD" != "y" ]; then
dep_tristate ' Build Eicon driver type standalone' CONFIG_ISDN_DRV_EICON_DIVAS $CONFIG_ISDN $CONFIG_PCI
fi
if [ "$CONFIG_ISDN_DRV_EICON_DIVAS" != "y" ]; then
dep_tristate ' Legacy Eicon driver' CONFIG_ISDN_DRV_EICON_OLD $CONFIG_ISDN
if [ "$CONFIG_ISDN_DRV_EICON_OLD" != "n" ]; then
dep_bool ' Eicon PCI DIVA Server BRI/PRI/4BRI support' CONFIG_ISDN_DRV_EICON_PCI $CONFIG_PCI
bool ' Eicon S,SX,SCOM,Quadro,S2M support' CONFIG_ISDN_DRV_EICON_ISA
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
if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
dep_tristate 'Auvertech TurboPAM support' CONFIG_ISDN_DRV_TPAM $CONFIG_ISDN $CONFIG_PCI
fi
# CAPI subsystem
tristate 'CAPI2.0 support' CONFIG_ISDN_CAPI
if [ "$CONFIG_ISDN_CAPI" != "n" ]; then
bool ' Verbose reason code reporting (kernel size +=7K)' CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
dep_bool ' CAPI2.0 Middleware support (EXPERIMENTAL)' CONFIG_ISDN_CAPI_MIDDLEWARE $CONFIG_EXPERIMENTAL
dep_tristate ' CAPI2.0 /dev/capi support' CONFIG_ISDN_CAPI_CAPI20 $CONFIG_ISDN_CAPI
if [ "$CONFIG_ISDN_CAPI_MIDDLEWARE" = "y" ]; then
dep_mbool ' CAPI2.0 filesystem support' CONFIG_ISDN_CAPI_CAPIFS_BOOL $CONFIG_ISDN_CAPI_CAPI20
if [ "$CONFIG_ISDN_CAPI_CAPIFS_BOOL" = "y" ]; then
define_tristate CONFIG_ISDN_CAPI_CAPIFS $CONFIG_ISDN_CAPI_CAPI20
else
define_tristate CONFIG_ISDN_CAPI_CAPIFS n
fi
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
dep_tristate ' CAPI2.0 capidrv interface support' CONFIG_ISDN_CAPI_CAPIDRV $CONFIG_ISDN_CAPI $CONFIG_ISDN
fi
# CAPI drivers
if [ "$CONFIG_ISDN_CAPI" != "n" ]; then
dep_tristate ' AVM B1 ISA support' CONFIG_ISDN_DRV_AVMB1_B1ISA $CONFIG_ISDN_CAPI
dep_tristate ' AVM B1 PCI support' CONFIG_ISDN_DRV_AVMB1_B1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI
dep_mbool ' AVM B1 PCI V4 support' CONFIG_ISDN_DRV_AVMB1_B1PCIV4 $CONFIG_ISDN_DRV_AVMB1_B1PCI
dep_tristate ' AVM T1/T1-B ISA support' CONFIG_ISDN_DRV_AVMB1_T1ISA $CONFIG_ISDN_CAPI
dep_tristate ' AVM B1/M1/M2 PCMCIA support' CONFIG_ISDN_DRV_AVMB1_B1PCMCIA $CONFIG_ISDN_CAPI
dep_tristate ' AVM B1/M1/M2 PCMCIA cs module' CONFIG_ISDN_DRV_AVMB1_AVM_CS $CONFIG_ISDN_DRV_AVMB1_B1PCMCIA $CONFIG_PCMCIA
dep_tristate ' AVM T1/T1-B PCI support' CONFIG_ISDN_DRV_AVMB1_T1PCI $CONFIG_ISDN_CAPI $CONFIG_PCI
dep_tristate ' AVM C4/C2 support' CONFIG_ISDN_DRV_AVMB1_C4 $CONFIG_ISDN_CAPI $CONFIG_PCI
fi
# HYSDN
dep_tristate ' Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)' CONFIG_HYSDN m $CONFIG_PROC_FS
dep_mbool ' HYSDN CAPI 2.0 support' CONFIG_HYSDN_CAPI $CONFIG_HYSDN $CONFIG_ISDN_CAPI
endmenu

View File

@ -1,151 +1,57 @@
SUB_DIRS :=
MOD_SUB_DIRS :=
ALL_SUB_DIRS := icn pcbit hisax avmb1 act2000 eicon divert hysdn
# Makefile for the kernel ISDN subsystem and device drivers.
L_OBJS :=
LX_OBJS :=
M_OBJS :=
MX_OBJS :=
O_OBJS :=
OX_OBJS :=
L_TARGET :=
O_TARGET :=
# The target object and module list name.
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
O_TARGET := isdn.a
ifeq ($(CONFIG_ISDN_DIVERSION),y)
ifeq ($(CONFIG_MODULES),y)
MOD_SUB_DIRS += divert
endif
endif
# Objects that export symbols.
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
export-objs := isdn_common.o
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
# Multipart objects.
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
list-multi := isdn.o
isdn-objs := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o
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
# Optional parts of multipart objects.
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
isdn-objs-$(CONFIG_ISDN_PPP) += isdn_ppp.o
isdn-objs-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o
isdn-objs-$(CONFIG_ISDN_AUDIO) += isdn_audio.o
isdn-objs-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o
isdn-objs-$(CONFIG_ISDN_WITH_ABC) += isdn_dwabc.o
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
isdn-objs += $(isdn-objs-y)
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
# Ordering constraints: isdn.o first, rest doesn't matter
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
# Each configuration option enables a list of files.
ifeq ($(CONFIG_HYSDN),y)
MOD_SUB_DIRS += hysdn
endif
obj-$(CONFIG_ISDN) += isdn.o
obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
include $(TOPDIR)/Rules.make
# Object files in subdirectories
mod-subdirs := avmb1 eicon
subdir-$(CONFIG_ISDN_DIVERSION) += divert
subdir-$(CONFIG_ISDN_DRV_HISAX) += hisax
subdir-$(CONFIG_ISDN_DRV_ICN) += icn
subdir-$(CONFIG_ISDN_DRV_PCBIT) += pcbit
subdir-$(CONFIG_ISDN_DRV_SC) += sc
subdir-$(CONFIG_ISDN_CAPI) += avmb1
subdir-$(CONFIG_ISDN_DRV_LOOP) += isdnloop
subdir-$(CONFIG_ISDN_DRV_ACT2000) += act2000
subdir-$(CONFIG_ISDN_DRV_EICON) += eicon
subdir-$(CONFIG_HYSDN) += hysdn
subdir-$(CONFIG_ISDN_DRV_TPAM) += tpam
obj-y += $(addsuffix /vmlinux-obj.o, $(subdir-y))
# The global Rules.make.
include $(TOPDIR)/drivers/isdn/Rules.make
# Link rules for multi-part drivers.
isdn.o: $(isdn-objs)
$(LD) -r -o $@ $(isdn-objs)

32
drivers/isdn/Rules.make Normal file
View File

@ -0,0 +1,32 @@
# Extract lists of the multi-part drivers.
# The 'int-*' lists are the intermediate files used to build the multi's.
multi-y := $(filter $(list-multi), $(obj-y))
multi-m := $(filter $(list-multi), $(obj-m))
int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
# Files that are both resident and modular: remove from modular.
obj-m := $(filter-out $(obj-y), $(obj-m))
int-m := $(filter-out $(int-y), $(int-m))
# Take multi-part drivers out of obj-y and put components in.
obj-y := $(filter-out $(list-multi), $(obj-y)) $(int-y)
# Translate to Rules.make lists.
O_OBJS := $(sort $(filter-out $(export-objs), $(obj-y)))
OX_OBJS := $(sort $(filter $(export-objs), $(obj-y)))
M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
both-m := $(filter $(mod-subdirs), $(subdir-y))
SUB_DIRS := $(subdir-y)
MOD_SUB_DIRS := $(sort $(subdir-m) $(both-m))
ALL_SUB_DIRS := $(sort $(subdir-y) $(subdir-m) $(subdir-n) $(subdir-))
include $(TOPDIR)/Rules.make

View File

@ -1,15 +1,21 @@
L_OBJS :=
M_OBJS :=
O_OBJS := module.o capi.o act2000_isa.o
# Makefile for the act2000 ISDN device driver
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
# The target object and module list name.
include $(TOPDIR)/Rules.make
O_TARGET := vmlinux-obj.o
# Multipart objects.
list-multi := act2000.o
act2000-objs := module.o capi.o act2000_isa.o
# Each configuration option enables a list of files.
obj-$(CONFIG_ISDN_DRV_ACT2000) += act2000.o
include $(TOPDIR)/drivers/isdn/Rules.make
# Link rules for multi-part drivers.
act2000.o: $(act2000-objs)
$(LD) -r -o $@ $(act2000-objs)

View File

@ -2,57 +2,19 @@
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Author Fritz Elfert
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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 <linux/module.h>
#include <linux/version.h>
#endif
#define ACT2000_IOCTL_SETPORT 1
#define ACT2000_IOCTL_GETPORT 2
#define ACT2000_IOCTL_SETIRQ 3
@ -110,7 +72,7 @@ typedef struct act2000_fwid {
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/malloc.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/ioport.h>

View File

@ -2,56 +2,14 @@
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Author Fritz Elfert
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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__
@ -59,16 +17,7 @@
#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 act2000_card *irq2card_map[16];
static void
act2000_isa_delay(long t)
@ -115,13 +64,9 @@ 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;
}
@ -200,9 +145,6 @@ act2000_isa_enable_irq(act2000_card * card)
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;
@ -211,30 +153,13 @@ act2000_isa_config_irq(act2000_card * card, short irq)
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) {
if (!request_irq(irq, &act2000_isa_interrupt, 0, card->regname, NULL)) {
card->irq = irq;
irq2card_map[card->irq] = card;
card->flags |= ACT2000_FLAGS_IVALID;
printk(KERN_WARNING
"act2000: Could not request irq\n");
"act2000: Could not request irq %d\n",irq);
return -EBUSY;
} else {
act2000_isa_select_irq(card);
@ -490,7 +415,7 @@ act2000_isa_getid(act2000_card * card)
int
act2000_isa_download(act2000_card * card, act2000_ddef * cb)
{
int length;
unsigned int length;
int ret;
int l;
int c;
@ -503,9 +428,8 @@ act2000_isa_download(act2000_card * card, act2000_ddef * cb)
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));
if(copy_from_user(&cblock, (char *) cb, sizeof(cblock)))
return -EFAULT;
length = cblock.length;
p = cblock.buffer;
if ((ret = verify_area(VERIFY_READ, (void *) p, length)))

View File

@ -2,30 +2,14 @@
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000 (ISA-Version).
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Author Fritz Elfert
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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

View File

@ -1,50 +1,16 @@
/* $Id$
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
* CAPI encoder/decoder
* CAPI encoder/decoder
*
* Author Fritz Elfert
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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__
@ -153,7 +119,7 @@ actcapi_chkhdr(act2000_card * card, actcapi_msghdr *hdr)
m->hdr.cmd.cmd = c; \
m->hdr.cmd.subcmd = s; \
m->hdr.msgnum = actcapi_nextsmsg(card); \
} \
} else m = NULL;\
}
#define ACTCAPI_CHKSKB if (!skb) { \

View File

@ -2,39 +2,14 @@
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Author Fritz Elfert
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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
@ -60,7 +35,7 @@ typedef struct actcapi_msgdsc {
char *description;
} actcapi_msgdsc;
/* CAPI Adress */
/* CAPI Address */
typedef struct actcapi_addr {
__u8 len; /* Length of element */
__u8 tnp; /* Type/Numbering Plan */

View File

@ -2,63 +2,21 @@
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Author Fritz Elfert
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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"
#include <linux/module.h>
#include <linux/init.h>
static unsigned short act2000_isa_ports[] =
{
@ -72,15 +30,15 @@ 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 int act_irq = -1;
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_DESCRIPTION( "ISDN4Linux: Driver for IBM Active 2000 ISDN card");
MODULE_AUTHOR( "Fritz Elfert");
MODULE_SUPPORTED_DEVICE( "ISDN subsystem");
MODULE_LICENSE( "GPL");
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_irq, "IRQ of first card");
MODULE_PARM_DESC(act_id, "ID-String of first card");
MODULE_PARM(act_bus, "i");
MODULE_PARM(act_port, "i");
@ -276,9 +234,7 @@ act2000_poll(unsigned long data)
act2000_receive(card);
save_flags(flags);
cli();
del_timer(&card->ptimer);
card->ptimer.expires = jiffies + 3;
add_timer(&card->ptimer);
mod_timer(&card->ptimer, jiffies+3);
restore_flags(flags);
}
@ -562,37 +518,6 @@ act2000_readstatus(u_char * buf, int len, int user, act2000_card * card)
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
*/
@ -892,12 +817,7 @@ act2000_addcard(int bus, int port, int irq, char *id)
#define DRIVERNAME "IBM Active 2000 ISDN driver"
#ifdef MODULE
#define act2000_init init_module
#endif
int
act2000_init(void)
static int __init act2000_init(void)
{
printk(KERN_INFO "%s\n", DRIVERNAME);
if (!cards)
@ -909,9 +829,7 @@ act2000_init(void)
return 0;
}
#ifdef MODULE
void
cleanup_module(void)
static void __exit act2000_exit(void)
{
act2000_card *card = cards;
act2000_card *last;
@ -929,8 +847,8 @@ cleanup_module(void)
}
printk(KERN_INFO "%s unloaded\n", DRIVERNAME);
}
#else
#if 0
#ifndef MODULE
void
act2000_setup(char *str, int *ints)
{
@ -961,3 +879,7 @@ act2000_setup(char *str, int *ints)
}
}
#endif
#endif
module_init(act2000_init);
module_exit(act2000_exit);

View File

@ -1,130 +1,40 @@
#
# $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.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
#
#
# Makefile for the AVM ISDN device drivers and CAPI subsystem.
#
# 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)
# The target object and module list name.
ifeq ($(CONFIG_ISDN_DRV_AVMB1),y)
O_TARGET += avmb1.o
OX_OBJS += kcapi.o
O_OBJS += capi.o
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_DRV_AVMB1),m)
O_TARGET += kernelcapi.o
OX_OBJS += kcapi.o
M_OBJS += capi.o kernelcapi.o
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
O_TARGET := vmlinux-obj.o
# Objects that export symbols.
export-objs := kcapi.o capiutil.o b1dma.o b1pcmcia.o b1.o capifs.o
# Multipart objects.
list-multi := kernelcapi.o
kernelcapi-objs := kcapi.o
# Ordering constraints: kernelcapi.o first
# Each configuration option enables a list of files.
obj-$(CONFIG_ISDN_CAPI) += kernelcapi.o capiutil.o
obj-$(CONFIG_ISDN_CAPI_CAPI20) += capi.o
obj-$(CONFIG_ISDN_CAPI_CAPIDRV) += capidrv.o
obj-$(CONFIG_ISDN_CAPI_CAPIFS) += capifs.o
obj-$(CONFIG_ISDN_DRV_AVMB1_B1ISA) += b1isa.o b1.o
obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCI) += b1pci.o b1.o b1dma.o
obj-$(CONFIG_ISDN_DRV_AVMB1_B1PCMCIA) += b1pcmcia.o b1.o
obj-$(CONFIG_ISDN_DRV_AVMB1_AVM_CS) += avm_cs.o
obj-$(CONFIG_ISDN_DRV_AVMB1_T1ISA) += t1isa.o b1.o
obj-$(CONFIG_ISDN_DRV_AVMB1_T1PCI) += t1pci.o b1.o b1dma.o
obj-$(CONFIG_ISDN_DRV_AVMB1_C4) += c4.o b1.o
# The global Rules.make.
include $(TOPDIR)/drivers/isdn/Rules.make
# Link rules for multi-part drivers.
kernelcapi.o: $(kernelcapi-objs)
$(LD) -r -o $@ $(kernelcapi-objs)
include $(TOPDIR)/Rules.make

543
drivers/isdn/avmb1/avm_cs.c Normal file
View File

@ -0,0 +1,543 @@
/* $Id$
*
* A PCMCIA client driver for AVM B1/M1/M2
*
* Copyright 1999 by Carsten Paeth <calle@calle.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <linux/tty.h>
#include <linux/serial.h>
#include <linux/major.h>
#include <asm/io.h>
#include <asm/system.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/ds.h>
#include <pcmcia/cisreg.h>
#include <linux/skbuff.h>
#include <linux/capi.h>
#include <linux/b1lli.h>
#include <linux/b1pcmcia.h>
/*====================================================================*/
MODULE_DESCRIPTION("CAPI4Linux: PCMCIA client driver for AVM B1/M1/M2");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/*====================================================================*/
/* Parameters that can be set with 'insmod' */
/* This means pick from 15, 12, 11, 10, 9, 7, 5, 4, and 3 */
static int default_irq_list[10] = { 15, 12, 11, 10, 9, 7, 5, 4, 3, -1 };
static int irq_list[10] = { -1 };
MODULE_PARM(irq_list, "1-10i");
/*====================================================================*/
/*
The event() function is this driver's Card Services event handler.
It will be called by Card Services when an appropriate card status
event is received. The config() and release() entry points are
used to configure or release a socket, in response to card insertion
and ejection events. They are invoked from the skeleton event
handler.
*/
static void avmcs_config(dev_link_t *link);
static void avmcs_release(u_long arg);
static int avmcs_event(event_t event, int priority,
event_callback_args_t *args);
/*
The attach() and detach() entry points are used to create and destroy
"instances" of the driver, where each instance represents everything
needed to manage one actual PCMCIA card.
*/
static dev_link_t *avmcs_attach(void);
static void avmcs_detach(dev_link_t *);
/*
The dev_info variable is the "key" that is used to match up this
device driver with appropriate cards, through the card configuration
database.
*/
static dev_info_t dev_info = "avm_cs";
/*
A linked list of "instances" of the skeleton device. Each actual
PCMCIA card corresponds to one device instance, and is described
by one dev_link_t structure (defined in ds.h).
You may not want to use a linked list for this -- for example, the
memory card driver uses an array of dev_link_t pointers, where minor
device numbers are used to derive the corresponding array index.
*/
static dev_link_t *dev_list = NULL;
/*
A dev_link_t structure has fields for most things that are needed
to keep track of a socket, but there will usually be some device
specific information that also needs to be kept track of. The
'priv' pointer in a dev_link_t structure can be used to point to
a device-specific private data structure, like this.
A driver needs to provide a dev_node_t structure for each device
on a card. In some cases, there is only one device per card (for
example, ethernet cards, modems). In other cases, there may be
many actual or logical devices (SCSI adapters, memory cards with
multiple partitions). The dev_node_t structures need to be kept
in a linked list starting at the 'dev' field of a dev_link_t
structure. We allocate them in the card's private data structure,
because they generally can't be allocated dynamically.
*/
typedef struct local_info_t {
dev_node_t node;
} local_info_t;
/*====================================================================*/
static void cs_error(client_handle_t handle, int func, int ret)
{
error_info_t err = { func, ret };
CardServices(ReportError, handle, &err);
}
/*======================================================================
avmcs_attach() creates an "instance" of the driver, allocating
local data structures for one device. The device is registered
with Card Services.
The dev_link structure is initialized, but we don't actually
configure the card at this point -- we wait until we receive a
card insertion event.
======================================================================*/
static dev_link_t *avmcs_attach(void)
{
client_reg_t client_reg;
dev_link_t *link;
local_info_t *local;
int ret, i;
/* Initialize the dev_link_t structure */
link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
if (!link)
return NULL;
memset(link, 0, sizeof(struct dev_link_t));
link->release.function = &avmcs_release;
link->release.data = (u_long)link;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts2 = 0;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
if (irq_list[0] != -1) {
for (i = 0; i < 10 && irq_list[i] > 0; i++)
link->irq.IRQInfo2 |= 1 << irq_list[i];
} else {
for (i = 0; i < 10 && default_irq_list[i] > 0; i++)
link->irq.IRQInfo2 |= 1 << default_irq_list[i];
}
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
/* Allocate space for private device-specific data */
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
if (!local)
return NULL;
memset(local, 0, sizeof(local_info_t));
link->priv = local;
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.event_handler = &avmcs_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = CardServices(RegisterClient, &link->handle, &client_reg);
if (ret != 0) {
cs_error(link->handle, RegisterClient, ret);
avmcs_detach(link);
return NULL;
}
return link;
} /* avmcs_attach */
/*======================================================================
This deletes a driver "instance". The device is de-registered
with Card Services. If it has been released, all local data
structures are freed. Otherwise, the structures will be freed
when the device is released.
======================================================================*/
static void avmcs_detach(dev_link_t *link)
{
dev_link_t **linkp;
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
if (*linkp == link) break;
if (*linkp == NULL)
return;
/*
If the device is currently configured and active, we won't
actually delete it yet. Instead, it is marked so that when
the release() function is called, that will trigger a proper
detach().
*/
if (link->state & DEV_CONFIG) {
link->state |= DEV_STALE_LINK;
return;
}
/* Break the link with Card Services */
if (link->handle)
CardServices(DeregisterClient, link->handle);
/* Unlink device structure, free pieces */
*linkp = link->next;
if (link->priv) {
kfree(link->priv);
}
kfree(link);
} /* avmcs_detach */
/*======================================================================
avmcs_config() is scheduled to run after a CARD_INSERTION event
is received, to configure the PCMCIA socket, and to make the
ethernet device available to the system.
======================================================================*/
static int get_tuple(int fn, client_handle_t handle, tuple_t *tuple,
cisparse_t *parse)
{
int i;
i = CardServices(fn, handle, tuple);
if (i != CS_SUCCESS) return i;
i = CardServices(GetTupleData, handle, tuple);
if (i != CS_SUCCESS) return i;
return CardServices(ParseTuple, handle, tuple, parse);
}
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
static void avmcs_config(dev_link_t *link)
{
client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
local_info_t *dev;
int i;
u_char buf[64];
char devname[128];
int cardtype;
int (*addcard)(unsigned int port, unsigned irq);
handle = link->handle;
dev = link->priv;
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
i = CardServices(GetFirstTuple, handle, &tuple);
if (i != CS_SUCCESS) break;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
i = CardServices(GetTupleData, handle, &tuple);
if (i != CS_SUCCESS) break;
i = CardServices(ParseTuple, handle, &tuple, &parse);
if (i != CS_SUCCESS) break;
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
cs_error(link->handle, ParseTuple, i);
link->state &= ~DEV_CONFIG_PENDING;
return;
}
/* Configure card */
link->state |= DEV_CONFIG;
do {
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 254;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
strncpy(devname,parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
/*
* find IO port
*/
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
i = first_tuple(handle, &tuple, &parse);
while (i == CS_SUCCESS) {
if (cf->io.nwin > 0) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.NumPorts1 = cf->io.win[0].len;
link->io.NumPorts2 = 0;
printk(KERN_INFO "avm_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
link->io.BasePort1+link->io.NumPorts1-1);
i = CardServices(RequestIO, link->handle, &link->io);
if (i == CS_SUCCESS) goto found_port;
}
i = next_tuple(handle, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
cs_error(link->handle, RequestIO, i);
break;
}
/*
* allocate an interrupt line
*/
i = CardServices(RequestIRQ, link->handle, &link->irq);
if (i != CS_SUCCESS) {
cs_error(link->handle, RequestIRQ, i);
CardServices(ReleaseIO, link->handle, &link->io);
break;
}
/*
* configure the PCMCIA socket
*/
i = CardServices(RequestConfiguration, link->handle, &link->conf);
if (i != CS_SUCCESS) {
cs_error(link->handle, RequestConfiguration, i);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
break;
}
} while (0);
/* At this point, the dev_node_t structure(s) should be
initialized and arranged in a linked list at link->dev. */
if (devname[0]) {
char *s = strrchr(devname, ' ');
if (!s)
s = devname;
else s++;
strcpy(dev->node.dev_name, s);
if (strcmp("M1", s) == 0) {
cardtype = AVM_CARDTYPE_M1;
} else if (strcmp("M2", s) == 0) {
cardtype = AVM_CARDTYPE_M2;
} else {
cardtype = AVM_CARDTYPE_B1;
}
} else {
strcpy(dev->node.dev_name, "b1");
cardtype = AVM_CARDTYPE_B1;
}
dev->node.major = 64;
dev->node.minor = 0;
link->dev = &dev->node;
link->state &= ~DEV_CONFIG_PENDING;
/* If any step failed, release any partially configured state */
if (i != 0) {
avmcs_release((u_long)link);
return;
}
switch (cardtype) {
case AVM_CARDTYPE_M1: addcard = b1pcmcia_addcard_m1; break;
case AVM_CARDTYPE_M2: addcard = b1pcmcia_addcard_m2; break;
default:
case AVM_CARDTYPE_B1: addcard = b1pcmcia_addcard_b1; break;
}
if ((i = (*addcard)(link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
printk(KERN_ERR "avm_cs: failed to add AVM-%s-Controller at i/o %#x, irq %d\n",
dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
avmcs_release((u_long)link);
return;
}
dev->node.minor = i;
} /* avmcs_config */
/*======================================================================
After a card is removed, avmcs_release() will unregister the net
device, and release the PCMCIA configuration. If the device is
still open, this will be postponed until it is closed.
======================================================================*/
static void avmcs_release(u_long arg)
{
dev_link_t *link = (dev_link_t *)arg;
/*
If the device is currently in use, we won't release until it
is actually closed.
*/
if (link->open) {
link->state |= DEV_STALE_CONFIG;
return;
}
b1pcmcia_delcard(link->io.BasePort1, link->irq.AssignedIRQ);
/* Unlink the device chain */
link->dev = NULL;
/* Don't bother checking to see if these succeed or not */
CardServices(ReleaseConfiguration, link->handle);
CardServices(ReleaseIO, link->handle, &link->io);
CardServices(ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK)
avmcs_detach(link);
} /* avmcs_release */
/*======================================================================
The card status event handler. Mostly, this schedules other
stuff to run after an event is received. A CARD_REMOVAL event
also sets some flags to discourage the net drivers from trying
to talk to the card any more.
When a CARD_REMOVAL event is received, we immediately set a flag
to block future accesses to this device. All the functions that
actually access the device should check this flag to make sure
the card is still present.
======================================================================*/
static int avmcs_event(event_t event, int priority,
event_callback_args_t *args)
{
dev_link_t *link = args->client_data;
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
link->release.expires = jiffies + (HZ/20);
add_timer(&link->release);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
avmcs_config(link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG)
CardServices(ReleaseConfiguration, link->handle);
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG)
CardServices(RequestConfiguration, link->handle, &link->conf);
break;
}
return 0;
} /* avmcs_event */
/*====================================================================*/
static int __init avmcs_init(void)
{
servinfo_t serv;
CardServices(GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk(KERN_NOTICE "avm_cs: Card Services release "
"does not match!\n");
return -1;
}
register_pccard_driver(&dev_info, &avmcs_attach, &avmcs_detach);
return 0;
}
static void __exit avmcs_exit(void)
{
unregister_pccard_driver(&dev_info);
while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG)
avmcs_release((u_long)dev_list);
avmcs_detach(dev_list);
}
}
module_init(avmcs_init);
module_exit(avmcs_exit);

View File

@ -1,48 +1,9 @@
/*
* $Id$
/* $Id$
*
* Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.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.
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -51,7 +12,6 @@
#define AVMB1_PORTLEN 0x1f
#define AVM_MAXVERSION 8
#define AVM_NAPPS 30
#define AVM_NCCI_PER_CHANNEL 4
/*
@ -75,7 +35,8 @@ enum avmcardtype {
avm_m2,
avm_t1isa,
avm_t1pci,
avm_c4
avm_c4,
avm_c2
};
typedef struct avmcard_dmainfo {
@ -342,13 +303,13 @@ static inline unsigned int b1_rd_reg(unsigned int base,
static inline void b1_reset(unsigned int base)
{
b1outp(base, B1_RESET, 0);
udelay(55 * 2 * 1000); /* 2 TIC's */
mdelay(55 * 2); /* 2 TIC's */
b1outp(base, B1_RESET, 1);
udelay(55 * 2 * 1000); /* 2 TIC's */
mdelay(55 * 2); /* 2 TIC's */
b1outp(base, B1_RESET, 0);
udelay(55 * 2 * 1000); /* 2 TIC's */
mdelay(55 * 2); /* 2 TIC's */
}
static inline unsigned char b1_disable_irq(unsigned int base)

View File

@ -1,73 +1,11 @@
/*
* $Id$
/* $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.
* Copyright 1999 by Carsten Paeth <calle@calle.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -79,11 +17,12 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/isdn_compat.h>
#ifdef COMPAT_NEED_UACCESS
#include <asm/uaccess.h>
#endif
#include <linux/netdevice.h>
#include "capilli.h"
#include "avmcard.h"
#include "capicmd.h"
@ -93,7 +32,9 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
@ -334,7 +275,7 @@ int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
cli();
b1_setinterrupt(port, card->irq, card->cardtype);
b1_put_byte(port, SEND_INIT);
b1_put_word(port, AVM_NAPPS);
b1_put_word(port, CAPI_MAXAPPL);
b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
b1_put_word(port, ctrl->cnr - 1);
restore_flags(flags);
@ -418,7 +359,7 @@ void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
b1_put_slice(port, skb->data, len);
}
restore_flags(flags);
dev_kfree_skb(skb);
dev_kfree_skb_any(skb);
}
/* ------------------------------------------------------------- */
@ -591,25 +532,29 @@ void b1_handle_interrupt(avmcard * card)
ctrl->ready(ctrl);
break;
case RECEIVE_TASK_READY:
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
printk(KERN_INFO "%s: task %d \"%s\" ready.\n",
card->name, ApplId, card->msgbuf);
break;
case RECEIVE_DEBUGMSG:
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
break;
@ -645,6 +590,7 @@ int b1ctl_read_proc(char *page, char **start, off_t off,
case avm_t1isa: s = "T1 ISA (HEMA)"; break;
case avm_t1pci: s = "T1 PCI"; break;
case avm_c4: s = "C4"; break;
case avm_c2: s = "C2"; break;
default: s = "???"; break;
}
len += sprintf(page+len, "%-16s %s\n", "type", s);
@ -712,20 +658,16 @@ 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)
static int __init b1_init(void)
{
char *p;
char rev[10];
char rev[32];
if ((p = strchr(revision, ':'))) {
strncpy(rev, p + 1, sizeof(rev));
p = strchr(rev, '$');
*p = 0;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(rev, p + 2, sizeof(rev));
rev[sizeof(rev)-1] = 0;
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
@ -734,8 +676,9 @@ int b1_init(void)
return 0;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit b1_exit(void)
{
}
#endif
module_init(b1_init);
module_exit(b1_exit);

View File

@ -1,17 +1,11 @@
/*
* $Id$
/* $Id$
*
* Common module for AVM B1 cards that support dma with AMCC
*
* (c) Copyright 2000 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 2000 by Carsten Paeth <calle@calle.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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -24,23 +18,30 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/isdn_compat.h>
#ifdef COMPAT_NEED_UACCESS
#include <asm/uaccess.h>
#endif
#include <linux/netdevice.h>
#include "capilli.h"
#include "avmcard.h"
#include "capicmd.h"
#include "capiutil.h"
#if BITS_PER_LONG != 32
#error FIXME: driver requires 32-bit platform
#endif
static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: DMA support for active AVM cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
int suppress_pollack = 0;
static int suppress_pollack = 0;
MODULE_PARM(suppress_pollack, "0-1i");
/* ------------------------------------------------------------- */
@ -230,14 +231,14 @@ void b1dma_reset(avmcard *card)
restore_flags(flags);
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
udelay(10 * 1000);
mdelay(10);
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
udelay(10 * 1000);
mdelay(10);
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
if (card->cardtype == avm_t1pci)
udelay(42 * 1000);
mdelay(42);
else
udelay(10 * 1000);
mdelay(10);
}
/* ------------------------------------------------------------- */
@ -245,11 +246,11 @@ void b1dma_reset(avmcard *card)
int b1dma_detect(avmcard *card)
{
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
udelay(10 * 1000);
mdelay(10);
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0x0f000000); /* reset all */
udelay(10 * 1000);
mdelay(10);
b1dmaoutmeml(card->mbase+AMCC_MCSR, 0);
udelay(42 * 1000);
mdelay(42);
b1dmaoutmeml(card->mbase+AMCC_RXLEN, 0);
b1dmaoutmeml(card->mbase+AMCC_TXLEN, 0);
@ -427,7 +428,7 @@ static void b1dma_dispatch_tx(avmcard *card)
b1dmaoutmeml(card->mbase+AMCC_INTCSR, card->csr);
restore_flags(flags);
dev_kfree_skb(skb);
dev_kfree_skb_any(skb);
}
/* ------------------------------------------------------------- */
@ -551,22 +552,26 @@ static void b1dma_handle_rx(avmcard *card)
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
break;
@ -612,13 +617,6 @@ static void b1dma_handle_interrupt(avmcard *card)
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);
}
@ -694,7 +692,7 @@ static void b1dma_send_init(avmcard *card)
_put_byte(&p, 0);
_put_byte(&p, 0);
_put_byte(&p, SEND_INIT);
_put_word(&p, AVM_NAPPS);
_put_word(&p, CAPI_MAXAPPL);
_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
_put_word(&p, card->cardnr - 1);
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
@ -873,6 +871,7 @@ int b1dmactl_read_proc(char *page, char **start, off_t off,
case avm_t1isa: s = "T1 ISA (HEMA)"; break;
case avm_t1pci: s = "T1 PCI"; break;
case avm_c4: s = "C4"; break;
case avm_c2: s = "C2"; break;
default: s = "???"; break;
}
len += sprintf(page+len, "%-16s %s\n", "type", s);
@ -960,20 +959,16 @@ 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];
char rev[32];
if ((p = strchr(revision, ':'))) {
strncpy(rev, p + 1, sizeof(rev));
p = strchr(rev, '$');
*p = 0;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(rev, p + 2, sizeof(rev));
rev[sizeof(rev)-1] = 0;
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
@ -982,8 +977,9 @@ int b1dma_init(void)
return 0;
}
#ifdef MODULE
void cleanup_module(void)
void b1dma_exit(void)
{
}
#endif
module_init(b1dma_init);
module_exit(b1dma_exit);

View File

@ -1,53 +1,11 @@
/*
* $Id$
/* $Id$
*
* Module for AVM B1 ISA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -59,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/capi.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/isdn_compat.h>
#include "capicmd.h"
@ -70,7 +29,9 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
@ -237,37 +198,36 @@ static char *b1isa_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
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,
name: "b1isa",
revision: "0.0",
load_firmware: b1_load_firmware,
reset_ctr: b1_reset_ctr,
remove_ctr: b1isa_remove_ctr,
register_appl: b1_register_appl,
release_appl: b1_release_appl,
send_message: b1_send_message,
b1isa_procinfo,
b1ctl_read_proc,
0, /* use standard driver_read_proc */
procinfo: b1isa_procinfo,
ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
b1isa_add_card,
add_card: b1isa_add_card,
};
#ifdef MODULE
#define b1isa_init init_module
void cleanup_module(void);
#endif
int b1isa_init(void)
static int __init b1isa_init(void)
{
struct capi_driver *driver = &b1isa_driver;
char *p;
int retval = 0;
if ((p = strchr(revision, ':'))) {
strncpy(driver->revision, p + 1, sizeof(driver->revision));
p = strchr(driver->revision, '$');
*p = 0;
}
MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
@ -276,14 +236,16 @@ int b1isa_init(void)
if (!di) {
printk(KERN_ERR "%s: failed to attach capi_driver\n",
driver->name);
return -EIO;
retval = -EIO;
}
return 0;
MOD_DEC_USE_COUNT;
return retval;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit b1isa_exit(void)
{
detach_capi_driver(&b1isa_driver);
}
#endif
module_init(b1isa_init);
module_exit(b1isa_exit);

View File

@ -1,57 +1,11 @@
/*
* $Id$
/* $Id$
*
* Module for AVM B1 PCI-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -66,6 +20,7 @@
#include <linux/pci.h>
#include <linux/capi.h>
#include <asm/io.h>
#include <linux/init.h>
#include <linux/isdn_compat.h>
#include "capicmd.h"
#include "capiutil.h"
@ -76,17 +31,17 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
#ifndef PCI_VENDOR_ID_AVM
#define PCI_VENDOR_ID_AVM 0x1244
#ifndef COMPAT_HAS_2_2_PCI
static struct pci_device_id b1pci_pci_tbl[] __initdata = {
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, b1pci_pci_tbl);
#endif
#ifndef PCI_DEVICE_ID_AVM_B1
#define PCI_DEVICE_ID_AVM_B1 0x700
#endif
/* ------------------------------------------------------------- */
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 PCI card");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
@ -249,20 +204,20 @@ static int b1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
/* ------------------------------------------------------------- */
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,
name: "b1pci",
revision: "0.0",
load_firmware: b1_load_firmware,
reset_ctr: b1_reset_ctr,
remove_ctr: b1pci_remove_ctr,
register_appl: b1_register_appl,
release_appl: b1_release_appl,
send_message: b1_send_message,
b1pci_procinfo,
b1ctl_read_proc,
0, /* use standard driver_read_proc */
procinfo: b1pci_procinfo,
ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
0, /* no add_card function */
add_card: 0, /* no add_card function */
};
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
@ -281,7 +236,7 @@ static void b1pciv4_remove_ctr(struct capi_ctr *ctrl)
div4->detach_ctr(ctrl);
free_irq(card->irq, card);
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
kfree(card->ctrlinfo);
@ -312,15 +267,17 @@ static char *b1pciv4_procinfo(struct capi_ctr *ctrl)
static int b1pciv4_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));
@ -328,6 +285,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
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));
@ -336,6 +294,7 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
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));
@ -354,20 +313,18 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
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 {
card->mbase = ioremap_nocache(card->membase, 64);
if (!card->mbase) {
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;
}
@ -376,10 +333,11 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
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));
iounmap(card->mbase);
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
return -EIO;
}
b1dma_reset(card);
@ -391,23 +349,25 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
MOD_DEC_USE_COUNT;
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));
iounmap(card->mbase);
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;
@ -419,8 +379,6 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
driver->name, card->port, card->irq,
card->membase, card->revision);
MOD_INC_USE_COUNT;
return 0;
}
@ -428,29 +386,24 @@ static int b1pciv4_add_card(struct capi_driver *driver, struct capicardparams *p
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,
name: "b1pciv4",
revision: "0.0",
load_firmware: b1dma_load_firmware,
reset_ctr: b1dma_reset_ctr,
remove_ctr: b1pciv4_remove_ctr,
register_appl: b1dma_register_appl,
release_appl: b1dma_release_appl,
send_message: b1dma_send_message,
b1pciv4_procinfo,
b1dmactl_read_proc,
0, /* use standard driver_read_proc */
procinfo: b1pciv4_procinfo,
ctr_read_proc: b1dmactl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
0, /* no add_card function */
add_card: 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)
@ -459,13 +412,22 @@ static int add_card(struct pci_dev *dev)
struct capicardparams param;
int retval;
if (get_pcibase(dev, 2) & PCI_BASE_ADDRESS_IO_MASK) { /* B1 PCI V4 */
if (pci_enable_device(dev) < 0) {
printk(KERN_ERR "%s: failed to enable AVM-B1\n",
driver->name);
return -ENODEV;
}
param.irq = dev->irq;
if (pci_resource_start_io(dev, 2)) { /* B1 PCI V4 */
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
driver = &b1pciv4_driver;
pci_set_master(dev);
#endif
param.membase = get_pcibase(dev, 0) & PCI_BASE_ADDRESS_MEM_MASK;
param.port = get_pcibase(dev, 2) & PCI_BASE_ADDRESS_IO_MASK;
param.irq = dev->irq;
param.membase = pci_resource_start_mem(dev, 0);
param.port = pci_resource_start_io(dev, 2);
printk(KERN_INFO
"%s: PCI BIOS reports AVM-B1 V4 at i/o %#x, irq %d, mem %#x\n",
driver->name, param.port, param.irq, param.membase);
@ -481,8 +443,8 @@ static int add_card(struct pci_dev *dev)
}
} else {
param.membase = 0;
param.port = get_pcibase(dev, 1) & PCI_BASE_ADDRESS_IO_MASK;
param.irq = dev->irq;
param.port = pci_resource_start_io(dev, 1);
printk(KERN_INFO
"%s: PCI BIOS reports AVM-B1 at i/o %#x, irq %d\n",
driver->name, param.port, param.irq);
@ -496,7 +458,7 @@ static int add_card(struct pci_dev *dev)
return retval;
}
int b1pci_init(void)
static int __init b1pci_init(void)
{
struct capi_driver *driver = &b1pci_driver;
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
@ -504,76 +466,73 @@ int b1pci_init(void)
#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;
MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driverv4->revision, p + 2, sizeof(driverv4->revision));
driverv4->revision[sizeof(driverv4->revision)-1] = 0;
if ((p = strchr(driverv4->revision, '$')) != 0 && p > driverv4->revision)
*(p-1) = 0;
}
#endif
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;
MOD_DEC_USE_COUNT;
return -ENODEV;
}
#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;
MOD_DEC_USE_COUNT;
return -ENODEV;
}
#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 (add_card(dev) == 0)
ncards++;
}
if (ncards) {
printk(KERN_INFO "%s: %d B1-PCI card(s) detected\n",
driver->name, ncards);
MOD_DEC_USE_COUNT;
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;
detach_capi_driver(driver);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
detach_capi_driver(driverv4);
#endif
MOD_DEC_USE_COUNT;
return -ENODEV;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit b1pci_exit(void)
{
detach_capi_driver(&b1pci_driver);
#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4
detach_capi_driver(&b1pciv4_driver);
#endif
}
#endif
module_init(b1pci_init);
module_exit(b1pci_exit);

View File

@ -1,53 +1,11 @@
/*
* $Id$
/* $Id$
*
* Module for AVM B1/M1/M2 PCMCIA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.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: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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -58,10 +16,10 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <asm/io.h>
#include <linux/capi.h>
#include <linux/b1pcmcia.h>
#include <linux/isdn_compat.h>
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
@ -71,7 +29,9 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
@ -229,20 +189,20 @@ static char *b1pcmcia_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
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,
name: "b1pcmcia",
revision: "0.0",
load_firmware: b1_load_firmware,
reset_ctr: b1_reset_ctr,
remove_ctr: b1pcmcia_remove_ctr,
register_appl: b1_register_appl,
release_appl: b1_release_appl,
send_message: b1_send_message,
b1pcmcia_procinfo,
b1ctl_read_proc,
0, /* use standard driver_read_proc */
procinfo: b1pcmcia_procinfo,
ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
0,
add_card: 0,
};
/* ------------------------------------------------------------- */
@ -284,20 +244,19 @@ EXPORT_SYMBOL(b1pcmcia_delcard);
/* ------------------------------------------------------------- */
#ifdef MODULE
#define b1pcmcia_init init_module
void cleanup_module(void);
#endif
int b1pcmcia_init(void)
static int __init b1pcmcia_init(void)
{
struct capi_driver *driver = &b1pcmcia_driver;
char *p;
int retval = 0;
if ((p = strchr(revision, ':'))) {
strncpy(driver->revision, p + 1, sizeof(driver->revision));
p = strchr(driver->revision, '$');
*p = 0;
MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
@ -307,14 +266,16 @@ int b1pcmcia_init(void)
if (!di) {
printk(KERN_ERR "%s: failed to attach capi_driver\n",
driver->name);
return -EIO;
retval = -EIO;
}
return 0;
MOD_DEC_USE_COUNT;
return retval;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit b1pcmcia_exit(void)
{
detach_capi_driver(&b1pcmcia_driver);
}
#endif
module_init(b1pcmcia_init);
module_exit(b1pcmcia_exit);

View File

@ -1,21 +1,11 @@
/*
* $Id$
/* $Id$
*
* Module for AVM C4 card.
* Module for AVM C4 & C2 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.
* Copyright 1999 by Carsten Paeth <calle@calle.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -28,9 +18,13 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/isdn_compat.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/netdevice.h>
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
@ -43,28 +37,20 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
#ifndef PCI_VENDOR_ID_DEC
#define PCI_VENDOR_ID_DEC 0x1011
static int suppress_pollack;
#ifndef COMPAT_HAS_2_2_PCI
static struct pci_device_id c4_pci_tbl[] __initdata = {
{ PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4 },
{ PCI_VENDOR_ID_DEC,PCI_DEVICE_ID_DEC_21285, PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C2 },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, c4_pci_tbl);
#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 <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM C2/C4 cards");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
MODULE_PARM(suppress_pollack, "0-1i");
/* ------------------------------------------------------------- */
@ -366,7 +352,7 @@ static int c4_detect(avmcard *card)
return 8;
if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, 0)) return 9;
udelay(1000);
mdelay(1);
if (c4_peek(card, DC21285_DRAM_A0MR, &dummy)) return 10;
if (c4_peek(card, DC21285_DRAM_A1MR, &dummy)) return 11;
@ -378,7 +364,7 @@ static int c4_detect(avmcard *card)
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);
mdelay(1);
if (c4_poke(card, DC21285_ARMCSR_BASE+DRAM_TIMING, DRAM_TIMING_DEF))
return 18;
@ -493,7 +479,7 @@ static void c4_dispatch_tx(avmcard *card)
c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM);
restore_flags(flags);
dev_kfree_skb(skb);
dev_kfree_skb_any(skb);
}
/* ------------------------------------------------------------- */
@ -545,7 +531,7 @@ static void c4_handle_rx(avmcard *card)
MsgLen = _get_slice(&p, card->msgbuf);
DataB3Len = _get_slice(&p, card->databuf);
cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
if (cidx > 3) cidx = 0;
if (cidx >= card->nlogcontr) cidx = 0;
ctrl = card->ctrlinfo[cidx].capi_ctrl;
if (MsgLen < 30) { /* not CAPI 64Bit */
@ -568,7 +554,7 @@ static void c4_handle_rx(avmcard *card)
ApplId = (unsigned) _get_word(&p);
MsgLen = _get_slice(&p, card->msgbuf);
cidx = CAPIMSG_CONTROLLER(card->msgbuf)-card->cardnr;
if (cidx > 3) cidx = 0;
if (cidx >= card->nlogcontr) cidx = 0;
ctrl = card->ctrlinfo[cidx].capi_ctrl;
if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) {
@ -586,7 +572,7 @@ static void c4_handle_rx(avmcard *card)
NCCI = _get_word(&p);
WindowSize = _get_word(&p);
cidx = (NCCI&0x7f) - card->cardnr;
if (cidx > 3) cidx = 0;
if (cidx >= card->nlogcontr) cidx = 0;
ctrl = card->ctrlinfo[cidx].capi_ctrl;
ctrl->new_ncci(ctrl, ApplId, NCCI, WindowSize);
@ -600,13 +586,15 @@ static void c4_handle_rx(avmcard *card)
if (NCCI != 0xffffffff) {
cidx = (NCCI&0x7f) - card->cardnr;
if (cidx > 3) cidx = 0;
if (cidx >= card->nlogcontr) cidx = 0;
ctrl = card->ctrlinfo[cidx].capi_ctrl;
ctrl->free_ncci(ctrl, ApplId, NCCI);
if (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);
if (ctrl)
ctrl->appl_released(ctrl, ApplId);
}
}
break;
@ -619,20 +607,28 @@ static void c4_handle_rx(avmcard *card)
queue_pollack(card);
for (cidx=0; cidx < 4; cidx++) {
ctrl = card->ctrlinfo[cidx].capi_ctrl;
ctrl->resume_output(ctrl);
if (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);
if (ctrl)
ctrl->suspend_output(ctrl);
}
break;
case RECEIVE_INIT:
cidx = card->nlogcontr++;
cidx = card->nlogcontr;
if (cidx >= 4 || !card->ctrlinfo[cidx].capi_ctrl) {
printk(KERN_ERR "%s: card with %d controllers ??\n",
card->name, cidx+1);
break;
}
card->nlogcontr++;
cinfo = &card->ctrlinfo[cidx];
ctrl = cinfo->capi_ctrl;
cinfo->versionlen = _get_slice(&p, cinfo->versionbuf);
@ -647,22 +643,26 @@ static void c4_handle_rx(avmcard *card)
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
break;
@ -682,6 +682,8 @@ static void c4_handle_interrupt(avmcard *card)
if (status & DBELL_RESET_HOST) {
int i;
c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c);
if (card->nlogcontr == 0)
return;
printk(KERN_ERR "%s: unexpected reset\n", card->name);
for (i=0; i < 4; i++) {
avmctrl_info *cinfo = &card->ctrlinfo[i];
@ -689,6 +691,7 @@ static void c4_handle_interrupt(avmcard *card)
if (cinfo->capi_ctrl)
cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
}
card->nlogcontr = 0;
return;
}
@ -757,7 +760,7 @@ static void c4_send_init(avmcard *card)
_put_byte(&p, 0);
_put_byte(&p, 0);
_put_byte(&p, SEND_INIT);
_put_word(&p, AVM_NAPPS);
_put_word(&p, CAPI_MAXAPPL);
_put_word(&p, AVM_NCCI_PER_CHANNEL*30);
_put_word(&p, card->cardnr - 1);
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
@ -766,45 +769,78 @@ static void c4_send_init(avmcard *card)
c4_dispatch_tx(card);
}
static int c4_send_config(avmcard *card, capiloaddatapart * config)
static int queue_sendconfigword(avmcard *card, __u32 val)
{
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);
skb = alloc_skb(3+4, GFP_ATOMIC);
if (!skb) {
printk(KERN_CRIT "%s: no memory, can't send config.\n",
printk(KERN_CRIT "%s: no memory, send config\n",
card->name);
return -ENOMEM;
return -ENOMEM;
}
p = skb->data;
_put_byte(&p, 0);
_put_byte(&p, 0);
_put_byte(&p, SEND_CONFIG);
_put_word(&p, 1);
_put_word(&p, val);
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
skb_queue_tail(&card->dma->send_queue, skb);
c4_dispatch_tx(card);
return 0;
}
static int queue_sendconfig(avmcard *card, char cval[4])
{
struct sk_buff *skb;
void *p;
skb = alloc_skb(3+4, GFP_ATOMIC);
if (!skb) {
printk(KERN_CRIT "%s: no memory, 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, config->len); /* 12 */
_put_byte(&p, cval[0]);
_put_byte(&p, cval[1]);
_put_byte(&p, cval[2]);
_put_byte(&p, cval[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_send_config(avmcard *card, capiloaddatapart * config)
{
__u8 val[4];
unsigned char *dp;
int left, retval;
if ((retval = queue_sendconfigword(card, 1)) != 0)
return retval;
if ((retval = queue_sendconfigword(card, config->len)) != 0)
return retval;
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);
if (retval)
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]);
if ((retval = queue_sendconfig(card, val)) != 0)
return retval;
left -= sizeof(val);
dp += sizeof(val);
}
@ -812,25 +848,15 @@ static int c4_send_config(avmcard *card, capiloaddatapart * config)
memset(val, 0, sizeof(val));
if (config->user) {
retval = copy_from_user(&val, dp, left);
if (retval) {
dev_kfree_skb(skb);
if (retval)
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]);
if ((retval = queue_sendconfig(card, val)) != 0)
return retval;
}
skb_put(skb, (__u8 *)p - (__u8 *)skb->data);
skb_queue_tail(&card->dma->send_queue, skb);
c4_dispatch_tx(card);
return 0;
}
@ -855,7 +881,7 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
c4outmeml(card->mbase+MBOX_UP_LEN, 0);
c4outmeml(card->mbase+MBOX_DOWN_LEN, 0);
c4outmeml(card->mbase+DOORBELL, DBELL_INIT);
udelay(1000);
mdelay(1);
c4outmeml(card->mbase+DOORBELL,
DBELL_UP_HOST | DBELL_DOWN_HOST | DBELL_RESET_HOST);
@ -867,8 +893,15 @@ static int c4_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM);
restore_flags(flags);
if (data->configuration.len > 0 && data->configuration.data)
c4_send_config(card, &data->configuration);
if (data->configuration.len > 0 && data->configuration.data) {
retval = c4_send_config(card, &data->configuration);
if (retval) {
printk(KERN_ERR "%s: failed to set config!!\n",
card->name);
c4_reset(card);
return retval;
}
}
c4_send_init(card);
@ -890,6 +923,7 @@ void c4_reset_ctr(struct capi_ctr *ctrl)
if (cinfo->capi_ctrl)
cinfo->capi_ctrl->reseted(cinfo->capi_ctrl);
}
card->nlogcontr = 0;
}
static void c4_remove_ctr(struct capi_ctr *ctrl)
@ -900,14 +934,16 @@ static void c4_remove_ctr(struct capi_ctr *ctrl)
c4_reset(card);
for (i=0; i <= 4; i++) {
for (i=0; i < 4; i++) {
cinfo = &card->ctrlinfo[i];
if (cinfo->capi_ctrl)
if (cinfo->capi_ctrl) {
di->detach_ctr(cinfo->capi_ctrl);
cinfo->capi_ctrl = NULL;
}
}
free_irq(card->irq, card);
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
kfree(card->ctrlinfo);
@ -1040,6 +1076,7 @@ static int c4_read_proc(char *page, char **start, off_t off,
case avm_t1isa: s = "T1 ISA (HEMA)"; break;
case avm_t1pci: s = "T1 PCI"; break;
case avm_c4: s = "C4"; break;
case avm_c2: s = "C2"; break;
default: s = "???"; break;
}
len += sprintf(page+len, "%-16s %s\n", "type", s);
@ -1087,9 +1124,10 @@ static int c4_read_proc(char *page, char **start, off_t off,
/* ------------------------------------------------------------- */
static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
static int c4_add_card(struct capi_driver *driver,
struct capicardparams *p,
int nr)
{
unsigned long base, page_offset;
avmctrl_info *cinfo;
avmcard *card;
int retval;
@ -1116,7 +1154,6 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
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;
@ -1128,11 +1165,11 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
cinfo = &card->ctrlinfo[i];
cinfo->card = card;
}
sprintf(card->name, "c4-%x", p->port);
sprintf(card->name, "%s-%x", driver->name, p->port);
card->port = p->port;
card->irq = p->irq;
card->membase = p->membase;
card->cardtype = avm_c4;
card->cardtype = nr == 4 ? avm_c4 : avm_c2;
if (check_region(card->port, AVMB1_PORTLEN)) {
printk(KERN_WARNING
@ -1145,12 +1182,8 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
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 {
card->mbase = ioremap_nocache(card->membase, 128);
if (card->mbase == 0) {
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
kfree(card->ctrlinfo);
@ -1163,7 +1196,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
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));
iounmap(card->mbase);
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
@ -1178,7 +1211,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card->dma);
@ -1187,7 +1220,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
return -EBUSY;
}
for (i=0; i < 4; i++) {
for (i=0; i < nr ; i++) {
cinfo = &card->ctrlinfo[i];
cinfo->card = card;
cinfo->capi_ctrl = di->attach_ctr(driver, card->name, cinfo);
@ -1198,7 +1231,7 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
cinfo = &card->ctrlinfo[i];
di->detach_ctr(cinfo->capi_ctrl);
}
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
iounmap(card->mbase);
free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->dma);
@ -1214,131 +1247,160 @@ static int c4_add_card(struct capi_driver *driver, struct capicardparams *p)
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);
"%s: AVM C%d at i/o %#x, irq %d, mem %#lx\n",
driver->name, nr, 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,
static struct capi_driver c2_driver = {
name: "c2",
revision: "0.0",
load_firmware: c4_load_firmware,
reset_ctr: c4_reset_ctr,
remove_ctr: c4_remove_ctr,
register_appl: c4_register_appl,
release_appl: c4_release_appl,
send_message: c4_send_message,
c4_procinfo,
c4_read_proc,
0, /* use standard driver_read_proc */
procinfo: c4_procinfo,
ctr_read_proc: c4_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
0, /* no add_card function */
add_card: 0, /* no add_card function */
};
#ifdef MODULE
#define c4_init init_module
void cleanup_module(void);
#endif
static struct capi_driver c4_driver = {
name: "c4",
revision: "0.0",
load_firmware: c4_load_firmware,
reset_ctr: c4_reset_ctr,
remove_ctr: c4_remove_ctr,
register_appl: c4_register_appl,
release_appl: c4_release_appl,
send_message: c4_send_message,
#ifndef COMPAT_HAS_pci_find_subsys
#ifndef PCI_ANY_ID
#define PCI_ANY_ID (~0)
#endif
procinfo: c4_procinfo,
ctr_read_proc: c4_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
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
add_card: 0, /* no add_card function */
};
static int ncards = 0;
int c4_init(void)
static int c4_attach_driver (struct capi_driver * driver)
{
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;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 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;
MOD_DEC_USE_COUNT;
return -ENODEV;
}
return 0;
}
#ifdef CONFIG_PCI
if (!pci_present()) {
printk(KERN_ERR "%s: no PCI bus present\n", driver->name);
detach_capi_driver(driver);
return -EIO;
}
static int __init search_cards(struct capi_driver * driver,
int pci_id, int nr)
{
struct pci_dev * dev = NULL;
int retval = 0;
while ((dev = pci_find_subsys(
PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_C4, dev))) {
PCI_VENDOR_ID_AVM, pci_id, 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;
if (pci_enable_device(dev) < 0) {
printk(KERN_ERR "%s: failed to enable AVM-C%d\n",
driver->name, nr);
continue;
}
pci_set_master(dev);
param.port = pci_resource_start_io(dev, 1);
param.irq = dev->irq;
param.membase = pci_resource_start_mem(dev, 0);
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, &param);
"%s: PCI BIOS reports AVM-C%d at i/o %#x, irq %d, mem %#x\n",
driver->name, nr, param.port, param.irq, param.membase);
retval = c4_add_card(driver, &param, nr);
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;
"%s: no AVM-C%d at i/o %#x, irq %d detected, mem %#x\n",
driver->name, nr, param.port, param.irq, param.membase);
continue;
}
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
return retval;
}
#ifdef MODULE
void cleanup_module(void)
static int __init c4_init(void)
{
int retval;
MOD_INC_USE_COUNT;
retval = c4_attach_driver (&c4_driver);
if (retval) {
MOD_DEC_USE_COUNT;
return retval;
}
retval = c4_attach_driver (&c2_driver);
if (retval) {
MOD_DEC_USE_COUNT;
return retval;
}
retval = search_cards(&c4_driver, PCI_DEVICE_ID_AVM_C4, 4);
if (retval && ncards == 0) {
detach_capi_driver(&c2_driver);
detach_capi_driver(&c4_driver);
MOD_DEC_USE_COUNT;
return retval;
}
retval = search_cards(&c2_driver, PCI_DEVICE_ID_AVM_C2, 2);
if (retval && ncards == 0) {
detach_capi_driver(&c2_driver);
detach_capi_driver(&c4_driver);
MOD_DEC_USE_COUNT;
return retval;
}
if (ncards) {
printk(KERN_INFO "%s: %d C4/C2 card(s) detected\n",
c4_driver.name, ncards);
MOD_DEC_USE_COUNT;
return 0;
}
printk(KERN_ERR "%s: NO C4/C2 card detected\n", c4_driver.name);
detach_capi_driver(&c4_driver);
detach_capi_driver(&c2_driver);
MOD_DEC_USE_COUNT;
return -ENODEV;
}
static void __exit c4_exit(void)
{
detach_capi_driver(&c2_driver);
detach_capi_driver(&c4_driver);
}
#endif
module_init(c4_init);
module_exit(c4_exit);

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,21 @@
/*
* $Id$
/* $Id$
*
* CAPI 2.0 Interface for Linux
*
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1997 by Carsten Paeth <calle@calle.de>
*
* $Log$
* Revision 2.2 1997/02/12 09:31:39 calle
* new version
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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

View File

@ -1,45 +1,27 @@
/*
* $Id$
/* $Id$
*
* CAPI 2.0 Interface for Linux
*
* (c) Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1996 by Carsten Paeth <calle@calle.de>
*
* $Log$
* Revision 1.3 1999/07/01 08:22:58 keil
* compatibility macros now in <linux/isdn_compat.h>
*
* 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
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
struct capidev {
int is_open;
int is_registered;
__u16 applid;
struct sk_buff_head recv_queue;
#ifdef COMPAT_HAS_NEW_WAITQ
wait_queue_head_t recv_wait;
#else
struct wait_queue *recv_wait;
#endif
__u16 errcode;
/* Statistic */
unsigned long nopen;
unsigned long nrecvctlpkt;
unsigned long nrecvdatapkt;
unsigned long nsentctlpkt;
unsigned long nsentdatapkt;
};
struct capidev *next;
struct file *file;
__u16 applid;
__u16 errcode;
unsigned int minor;
#define CAPI_MAXMINOR CAPI_MAXAPPL
struct sk_buff_head recv_queue;
wait_queue_head_t recv_wait;
/* Statistic */
unsigned long nrecvctlpkt;
unsigned long nrecvdatapkt;
unsigned long nsentctlpkt;
unsigned long nsentdatapkt;
};

View File

@ -1,145 +1,11 @@
/*
* $Id$
/* $Id$
*
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
*
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1997 by Carsten Paeth <calle@calle.de>
*
* $Log$
* 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 <hel@admin.de>.
*
* 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 <linux/isdn_compat.h>
*
* 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
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -148,7 +14,7 @@
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
#include <linux/malloc.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/signal.h>
@ -162,17 +28,19 @@
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/ctype.h>
#include <linux/init.h>
#include <asm/segment.h>
#include <linux/isdn_compat.h>
#include "capiutil.h"
#include "capicmd.h"
#include "capidrv.h"
static char *revision = "$Revision$";
int debugmode = 0;
static int debugmode = 0;
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
MODULE_PARM(debugmode, "i");
/* -------- type definitions ----------------------------------------- */
@ -278,6 +146,7 @@ typedef struct capidrv_bchan capidrv_bchan;
/* -------- data definitions ----------------------------------------- */
static capidrv_data global;
static spinlock_t global_lock = SPIN_LOCK_UNLOCKED;
static struct capi_interface *capifuncs;
static void handle_dtrace_data(capidrv_contr *card,
@ -303,6 +172,8 @@ static inline __u32 b1prot(int l2, int l3)
return 2;
case ISDN_PROTO_L2_FAX:
return 4;
case ISDN_PROTO_L2_MODEM:
return 8;
}
}
@ -319,6 +190,7 @@ static inline __u32 b2prot(int l2, int l3)
case ISDN_PROTO_L2_V11096:
case ISDN_PROTO_L2_V11019:
case ISDN_PROTO_L2_V11038:
case ISDN_PROTO_L2_MODEM:
return 1;
case ISDN_PROTO_L2_FAX:
return 4;
@ -336,6 +208,7 @@ static inline __u32 b3prot(int l2, int l3)
case ISDN_PROTO_L2_V11096:
case ISDN_PROTO_L2_V11019:
case ISDN_PROTO_L2_V11038:
case ISDN_PROTO_L2_MODEM:
default:
return 0;
case ISDN_PROTO_L2_FAX:
@ -343,16 +216,16 @@ static inline __u32 b3prot(int l2, int l3)
}
}
static _cstruct b1config_sync_v110(__u16 rate)
static _cstruct b1config_async_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 */
buf[3] = 8; buf[4] = 0; /* 8 bits per character */
buf[5] = 0; buf[6] = 0; /* parity none */
buf[7] = 0; buf[8] = 0; /* 1 stop bit */
return buf;
}
@ -367,11 +240,11 @@ static _cstruct b1config(int l2, int l3)
default:
return 0;
case ISDN_PROTO_L2_V11096:
return b1config_sync_v110(9600);
return b1config_async_v110(9600);
case ISDN_PROTO_L2_V11019:
return b1config_sync_v110(19200);
return b1config_async_v110(19200);
case ISDN_PROTO_L2_V11038:
return b1config_sync_v110(38400);
return b1config_async_v110(38400);
}
}
@ -433,30 +306,32 @@ static inline __u8 cip2si2(__u16 cipval)
}
/* -------- controller managment ------------------------------------- */
/* -------- controller management ------------------------------------- */
static inline capidrv_contr *findcontrbydriverid(int driverid)
{
capidrv_contr *p = global.contr_list;
unsigned long flags;
capidrv_contr *p;
while (p) {
spin_lock_irqsave(&global_lock, flags);
for (p = global.contr_list; p; p = p->next)
if (p->myid == driverid)
return p;
p = p->next;
}
return (capidrv_contr *) 0;
break;
spin_unlock_irqrestore(&global_lock, flags);
return p;
}
static capidrv_contr *findcontrbynumber(__u32 contr)
{
unsigned long flags;
capidrv_contr *p = global.contr_list;
while (p) {
spin_lock_irqsave(&global_lock, flags);
for (p = global.contr_list; p; p = p->next)
if (p->contrnr == contr)
return p;
p = p->next;
}
return (capidrv_contr *) 0;
break;
spin_unlock_irqrestore(&global_lock, flags);
return p;
}
@ -1499,7 +1374,7 @@ static void handle_data(_cmsg * cmsg, struct sk_buff *skb)
static _cmsg s_cmsg;
static void capidrv_signal(__u16 applid, __u32 dummy)
static void capidrv_signal(__u16 applid, void *dummy)
{
struct sk_buff *skb = 0;
@ -1543,47 +1418,41 @@ static void capidrv_signal(__u16 applid, __u32 dummy)
static void handle_dtrace_data(capidrv_contr *card,
int send, int level2, __u8 *data, __u16 len)
{
long flags;
__u8 *p, *end;
isdn_ctrl cmd;
__u8 *p, *end;
isdn_ctrl cmd;
if (!len) {
printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
if (!len) {
printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
card->contrnr, len);
return;
}
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, ':');
}
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');
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);
cmd.command = ISDN_STAT_STAVAIL;
cmd.driver = card->myid;
cmd.arg = len*3+5;
card->interface.statcallb(&cmd);
}
/* ------------------------------------------------------------------- */
@ -1988,8 +1857,8 @@ static int if_command(isdn_ctrl * c)
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);
"capidrv: if_command %d called with invalid driverId %d!\n",
c->command, c->driver);
return -ENODEV;
}
@ -2006,8 +1875,8 @@ static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
__u16 datahandle;
if (!card) {
printk(KERN_ERR "capidrv-%d: if_sendbuf called with invalid driverId %d!\n",
card->contrnr, id);
printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
id);
return 0;
}
if (debugmode > 1)
@ -2078,8 +1947,8 @@ static int if_readstat(__u8 *buf, int len, int user, int id, int channel)
__u8 *p;
if (!card) {
printk(KERN_ERR "capidrv-%d: if_readstat called with invalid driverId %d!\n",
card->contrnr, id);
printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
id);
return -ENODEV;
}
@ -2147,6 +2016,7 @@ static void enable_dchannel_trace(capidrv_contr *card)
send_message(card, &cmdcmsg);
}
#if 0
static void disable_dchannel_trace(capidrv_contr *card)
{
__u8 manufacturer[CAPI_MANUFACTURER_LEN];
@ -2191,6 +2061,7 @@ static void disable_dchannel_trace(capidrv_contr *card)
(_cstruct)"\004\000\000\000\000");
send_message(card, &cmdcmsg);
}
#endif
static void send_listen(capidrv_contr *card)
{
@ -2218,14 +2089,18 @@ static void listentimerfunc(unsigned long x)
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));
@ -2238,6 +2113,7 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
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;
@ -2246,45 +2122,49 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
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.features = ISDN_FEATURE_L2_HDLC |
ISDN_FEATURE_L2_TRANS |
ISDN_FEATURE_L3_TRANS |
ISDN_FEATURE_P_UNKNOWN |
ISDN_FEATURE_L2_X75I |
ISDN_FEATURE_L2_X75UI |
ISDN_FEATURE_L2_X75BUI;
if (profp->support1 & (1<<2))
card->interface.features |= ISDN_FEATURE_L2_V11096 |
ISDN_FEATURE_L2_V11019 |
ISDN_FEATURE_L2_V11038;
if (profp->support1 & (1<<8))
card->interface.features |= ISDN_FEATURE_L2_MODEM;
card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
card->next = global.contr_list;
global.contr_list = card;
global.ncontr++;
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)) {
global.contr_list = global.contr_list->next;
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;
spin_lock_irqsave(&global_lock, flags);
card->next = global.contr_list;
global.contr_list = card;
global.ncontr++;
spin_unlock_irqrestore(&global_lock, flags);
memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
for (i = 0; i < card->nbchan; i++) {
card->bchans[i].contr = card;
}
cmd.driver = card->myid;
cmd.command = ISDN_STAT_RUN;
cmd.driver = card->myid;
card->interface.statcallb(&cmd);
card->cipmask = 0x1FFF03FF; /* any */
@ -2307,45 +2187,82 @@ static int capidrv_addcontr(__u16 contr, struct capi_profile *profp)
static int capidrv_delcontr(__u16 contr)
{
capidrv_contr **pp, *card;
unsigned long flags;
isdn_ctrl cmd;
int i;
for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
if ((*pp)->contrnr == contr)
spin_lock_irqsave(&global_lock, flags);
for (card = global.contr_list; card; card = card->next) {
if (card->contrnr == contr)
break;
}
if (!*pp) {
if (!card) {
spin_unlock_irqrestore(&global_lock, flags);
printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
return -1;
}
card = *pp;
spin_unlock_irqrestore(&global_lock, flags);
del_timer(&card->listentimer);
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);
while (card->nbchan) {
cmd.command = ISDN_STAT_DISCH;
cmd.driver = card->myid;
cmd.arg = card->nbchan-1;
cmd.parm.num[0] = 0;
if (debugmode)
printk(KERN_DEBUG "capidrv-%d: id=%d disable chan=%ld\n",
card->contrnr, card->myid, cmd.arg);
card->interface.statcallb(&cmd);
if (card->bchans[card->nbchan-1].nccip)
free_ncci(card, card->bchans[card->nbchan-1].nccip);
if (card->bchans[card->nbchan-1].plcip)
free_plci(card, card->bchans[card->nbchan-1].plcip);
if (card->plci_list)
printk(KERN_ERR "capidrv: bug in free_plci()\n");
card->nbchan--;
}
kfree(card->bchans);
card->bchans = 0;
if (debugmode)
printk(KERN_DEBUG "capidrv-%d: id=%d isdn unload\n",
card->contrnr, card->myid);
cmd.command = ISDN_STAT_UNLOAD;
cmd.driver = card->myid;
card->interface.statcallb(&cmd);
*pp = (*pp)->next;
global.ncontr--;
if (debugmode)
printk(KERN_DEBUG "capidrv-%d: id=%d remove contr from list\n",
card->contrnr, card->myid);
for (i = 0; i < card->nbchan; i++) {
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");
spin_lock_irqsave(&global_lock, flags);
for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
if (*pp == card) {
*pp = (*pp)->next;
card->next = 0;
global.ncontr--;
break;
}
}
kfree(card->bchans);
del_timer(&card->listentimer);
spin_unlock_irqrestore(&global_lock, flags);
printk(KERN_INFO "%s: now down.\n", card->name);
kfree(card);
MOD_DEC_USE_COUNT;
return 0;
}
@ -2398,7 +2315,7 @@ static struct procfsentries {
{ "capi/capidrv", 0 , proc_capidrv_read_proc },
};
static void proc_init(void)
static void __init proc_init(void)
{
int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
int i;
@ -2410,7 +2327,7 @@ static void proc_init(void)
}
}
static void proc_exit(void)
static void __exit proc_exit(void)
{
int nelem = sizeof(procfsentries)/sizeof(procfsentries[0]);
int i;
@ -2425,34 +2342,35 @@ static void proc_exit(void)
}
static struct capi_interface_user cuser = {
"capidrv",
lower_callback
name: "capidrv",
callback: lower_callback
};
#ifdef MODULE
#define capidrv_init init_module
#endif
int capidrv_init(void)
static int __init capidrv_init(void)
{
struct capi_register_params rparam;
capi_profile profile;
char rev[10];
char rev[32];
char *p;
__u32 ncontr, contr;
__u16 errcode;
MOD_INC_USE_COUNT;
capifuncs = attach_capi_interface(&cuser);
if (!capifuncs)
if (!capifuncs) {
MOD_DEC_USE_COUNT;
return -EIO;
}
if ((p = strchr(revision, ':'))) {
strcpy(rev, p + 1);
p = strchr(rev, '$');
*p = 0;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(rev, p + 2, sizeof(rev));
rev[sizeof(rev)-1] = 0;
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, " ??? ");
strcpy(rev, "1.0");
rparam.level3cnt = -2; /* number of bchannels twice */
rparam.datablkcnt = 16;
@ -2460,6 +2378,7 @@ int capidrv_init(void)
errcode = (*capifuncs->capi_register) (&rparam, &global.appid);
if (errcode) {
detach_capi_interface(&cuser);
MOD_DEC_USE_COUNT;
return -EIO;
}
@ -2467,6 +2386,7 @@ int capidrv_init(void)
if (errcode != CAPI_NOERROR) {
(void) (*capifuncs->capi_release) (global.appid);
detach_capi_interface(&cuser);
MOD_DEC_USE_COUNT;
return -EIO;
}
@ -2481,17 +2401,18 @@ int capidrv_init(void)
}
proc_init();
printk(KERN_NOTICE "capidrv: Rev %s: loaded\n", rev);
MOD_DEC_USE_COUNT;
return 0;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit capidrv_exit(void)
{
capidrv_contr *card, *next;
char rev[10];
char *p;
if ((p = strchr(revision, ':'))) {
if ((p = strchr(revision, ':')) != 0) {
strcpy(rev, p + 1);
p = strchr(rev, '$');
*p = 0;
@ -2499,17 +2420,14 @@ void cleanup_module(void)
strcpy(rev, " ??? ");
}
for (card = global.contr_list; card; card = next) {
next = card->next;
disable_dchannel_trace(card);
capidrv_delcontr(card->contrnr);
}
(void) (*capifuncs->capi_release) (global.appid);
detach_capi_interface(&cuser);
proc_exit();
printk(KERN_NOTICE "capidrv: Rev%s: unloaded\n", rev);
}
#endif
module_init(capidrv_init);
module_exit(capidrv_exit);

View File

@ -1,29 +1,14 @@
/*
* $Id$
/* $Id$
*
* ISDN4Linux Driver, using capi20 interface (kernelcapi)
*
* Copyright 1997 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1997 by Carsten Paeth <calle@calle.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
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef __CAPIDRV_H__
#define __CAPIDRV_H__

619
drivers/isdn/avmb1/capifs.c Normal file
View File

@ -0,0 +1,619 @@
/* $Id$
*
* Copyright 2000 by Carsten Paeth <calle@calle.de>
*
* Heavily based on devpts filesystem from H. Peter Anvin
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/tty.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/stat.h>
#include <linux/param.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/kdev_t.h>
#include <linux/kernel.h>
#include <linux/locks.h>
#include <linux/major.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include <linux/isdn_compat.h>
#include <asm/bitops.h>
#include <asm/uaccess.h>
MODULE_DESCRIPTION("CAPI4Linux: /dev/capi/ filesystem");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
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);
#ifdef COMPAT_VFS_2_4
static struct inode *capifs_new_inode(struct super_block *sb);
#endif
static struct file_operations capifs_root_operations = {
#ifdef COMPAT_VFS_2_4
read: generic_read_dir,
#endif
readdir: capifs_root_readdir,
};
struct inode_operations capifs_root_inode_operations = {
#ifndef COMPAT_VFS_2_4
default_file_ops: &capifs_root_operations, /* file operations */
#endif
lookup: capifs_root_lookup,
};
static struct dentry_operations capifs_dentry_operations = {
d_revalidate: capifs_revalidate,
};
/*
* /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:
#ifdef COMPAT_VFS_2_4
if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
#else
if (filldir(dirent, ".", 1, nr, inode->i_ino) < 0)
#endif
return 0;
filp->f_pos = ++nr;
/* fall through */
case 1:
#ifdef COMPAT_VFS_2_4
if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
#else
if (filldir(dirent, "..", 2, nr, inode->i_ino) < 0)
#endif
return 0;
filp->f_pos = ++nr;
/* fall through */
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);
#ifdef COMPAT_VFS_2_4
if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr, DT_UNKNOWN) < 0 )
#else
if ( filldir(dirent, numbuf, strlen(numbuf), nr, nr) < 0 )
#endif
return 0;
}
filp->f_pos = ++nr;
}
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 )
i_count_inc(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 (i_count_read(inode->i_count) != 1 )
printk("capifs_put_super: badness: entry %d count %d\n",
i, (unsigned)i_count_read(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);
#ifndef COMPAT_VFS_2_4
MOD_DEC_USE_COUNT;
#endif
}
#ifdef COMPAT_VFS_2_4
static int capifs_statfs(struct super_block *sb, struct statfs *buf);
#else
static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz);
static void capifs_write_inode(struct inode *inode) { };
static void capifs_read_inode(struct inode *inode);
#endif
static struct super_operations capifs_sops = {
#ifndef COMPAT_VFS_2_4
read_inode: capifs_read_inode,
write_inode: capifs_write_inode,
#endif
put_super: capifs_put_super,
statfs: capifs_statfs,
};
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;
#ifndef COMPAT_VFS_2_4
MOD_INC_USE_COUNT;
lock_super(s);
#endif
/* Super block already completed? */
if (s->s_root)
goto out;
sbi = (struct capifs_sb_info *) kmalloc(sizeof(struct capifs_sb_info), GFP_KERNEL);
if ( !sbi )
goto fail;
memset(sbi, 0, sizeof(struct capifs_sb_info));
sbi->magic = CAPIFS_SBI_MAGIC;
if ( capifs_parse_options(data,sbi) ) {
kfree(sbi);
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);
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;
/*
* Get the root inode and dentry, but defer checking for errors.
*/
#ifdef COMPAT_VFS_2_4
root_inode = capifs_new_inode(s);
if (root_inode) {
root_inode->i_ino = 1;
root_inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
root_inode->i_op = &capifs_root_inode_operations;
root_inode->i_fop = &capifs_root_operations;
root_inode->i_nlink = 2;
}
root = d_alloc_root(root_inode);
#else
root_inode = iget(s, 1); /* inode 1 == root directory */
root = d_alloc_root(root_inode, NULL);
#endif
/*
* Check whether somebody else completed the super block.
*/
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.
*/
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.
*/
s->s_root = root;
sbi->next = mounts;
if ( sbi->next )
SBI(sbi->next)->back = &(sbi->next);
sbi->back = &mounts;
mounts = s;
out: /* Success ... somebody else completed the super block for us. */
#ifndef COMPAT_VFS_2_4
unlock_super(s);
#endif
return s;
fail:
#ifndef COMPAT_VFS_2_4
unlock_super(s);
MOD_DEC_USE_COUNT;
#endif
return NULL;
}
#ifndef COMPAT_VFS_2_4
static int capifs_statfs(struct super_block *sb, struct statfs *buf, int bufsiz)
{
struct statfs tmp;
tmp.f_type = CAPIFS_SUPER_MAGIC;
tmp.f_bsize = 1024;
tmp.f_blocks = 0;
tmp.f_bfree = 0;
tmp.f_bavail = 0;
tmp.f_files = 0;
tmp.f_ffree = 0;
tmp.f_namelen = NAME_MAX;
return copy_to_user(buf, &tmp, bufsiz) ? -EFAULT : 0;
}
#else
static int capifs_statfs(struct super_block *sb, struct statfs *buf)
{
buf->f_type = CAPIFS_SUPER_MAGIC;
buf->f_bsize = 1024;
buf->f_blocks = 0;
buf->f_bfree = 0;
buf->f_bavail = 0;
buf->f_files = 0;
buf->f_ffree = 0;
buf->f_namelen = NAME_MAX;
return 0;
}
#endif
#ifdef COMPAT_VFS_2_4
static struct inode *capifs_new_inode(struct super_block *sb)
{
struct inode *inode = new_inode(sb);
if (inode) {
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;
}
return inode;
}
#else
static void capifs_read_inode(struct inode *inode)
{
ino_t ino = inode->i_ino;
struct capifs_sb_info *sbi = SBI(inode->i_sb);
inode->i_mode = 0;
inode->i_nlink = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0;
inode->i_blksize = 1024;
inode->i_uid = inode->i_gid = 0;
if ( ino == 1 ) {
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &capifs_root_inode_operations;
inode->i_nlink = 2;
return;
}
ino -= 2;
if ( ino >= sbi->max_ncci )
return; /* Bogus */
#ifdef COMPAT_VFS_2_4
init_special_inode(inode, S_IFCHR, 0);
#else
inode->i_mode = S_IFCHR;
inode->i_op = &chrdev_inode_operations;
#endif
return;
}
#endif
#ifndef COMPAT_VFS_2_4
static struct file_system_type capifs_fs_type = {
"capifs",
0,
capifs_read_super,
NULL
};
#else
static DECLARE_FSTYPE(capifs_fs_type, "capifs", capifs_read_super, 0);
#endif
void capifs_new_ncci(char type, unsigned int num, kdev_t device)
{
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;
}
}
#ifdef COMPAT_VFS_2_4
if ( ino >= sbi->max_ncci )
continue;
if ((np->inode = capifs_new_inode(sb)) != NULL) {
#else
if ((np->inode = iget(sb, ino+2)) != NULL) {
#endif
struct inode *inode = np->inode;
inode->i_uid = sbi->setuid ? sbi->uid : current->fsuid;
inode->i_gid = sbi->setgid ? sbi->gid : current->fsgid;
#ifdef COMPAT_VFS_2_4
inode->i_nlink = 1;
inode->i_ino = ino + 2;
init_special_inode(inode, sbi->mode|S_IFCHR, np->kdev);
#else
inode->i_mode = sbi->mode | S_IFCHR;
inode->i_rdev = np->kdev;
inode->i_nlink++;
#endif
}
}
}
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->inode = 0;
np->used = 0;
inode->i_nlink--;
iput(inode);
break;
}
}
}
}
static int __init capifs_init(void)
{
char rev[32];
char *p;
int err;
MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(rev, p + 2, sizeof(rev));
rev[sizeof(rev)-1] = 0;
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
err = register_filesystem(&capifs_fs_type);
if (err) {
MOD_DEC_USE_COUNT;
return err;
}
printk(KERN_NOTICE "capifs: Rev %s\n", rev);
MOD_DEC_USE_COUNT;
return 0;
}
static void __exit capifs_exit(void)
{
unregister_filesystem(&capifs_fs_type);
}
EXPORT_SYMBOL(capifs_new_ncci);
EXPORT_SYMBOL(capifs_free_ncci);
module_init(capifs_init);
module_exit(capifs_exit);

View File

@ -0,0 +1,11 @@
/* $Id$
*
* Copyright 2000 by Carsten Paeth <calle@calle.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
void capifs_new_ncci(char type, unsigned int num, kdev_t device);
void capifs_free_ncci(char type, unsigned int num);

View File

@ -1,11 +1,14 @@
/*
* $Id$
/* $Id$
*
* Kernel CAPI 2.0 Driver Interface for Linux
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef __CAPILLI_H__
#define __CAPILLI_H__

View File

@ -1,78 +1,31 @@
/*
* $Id$
/* $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)
* Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>
*
* $Log$
* 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 <linux/isdn_compat.h>
*
* 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
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/module.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/init.h>
#include <asm/segment.h>
#include <linux/config.h>
#include <linux/isdn_compat.h>
#include "capiutil.h"
MODULE_DESCRIPTION("CAPI4Linux: CAPI message conversion support");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/* from CAPI2.0 DDK AVM Berlin GmbH */
#ifndef CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON
@ -792,7 +745,7 @@ static char *pnames[] =
/*15 */ "Class",
/*16 */ "ConnectedNumber",
/*17 */ "ConnectedSubaddress",
/*18 */ "Data",
/*18 */ "Data32",
/*19 */ "DataHandle",
/*1a */ "DataLength",
/*1b */ "FacilityConfirmationParameter",
@ -890,13 +843,7 @@ static void protocol_message_2_pars(_cmsg * cmsg, int level)
cmsg->l += 2;
break;
case _CDWORD:
if (strcmp(NAME, "Data") == 0) {
bufprint("%-*s = ", slen, NAME);
printstructlen((__u8 *) * (__u32 *) (cmsg->m + cmsg->l),
*(__u16 *) (cmsg->m + cmsg->l + sizeof(__u32)));
bufprint("\n");
} else
bufprint("%-*s = 0x%lx\n", slen, NAME, *(__u32 *) (cmsg->m + cmsg->l));
bufprint("%-*s = 0x%lx\n", slen, NAME, *(__u32 *) (cmsg->m + cmsg->l));
cmsg->l += 4;
break;
case _CSTRUCT:
@ -971,7 +918,6 @@ char *capi_cmsg2str(_cmsg * cmsg)
return buf;
}
EXPORT_SYMBOL(capi_cmsg2message);
EXPORT_SYMBOL(capi_message2cmsg);
EXPORT_SYMBOL(capi_cmsg_header);
@ -980,15 +926,14 @@ EXPORT_SYMBOL(capi_cmsg2str);
EXPORT_SYMBOL(capi_message2str);
EXPORT_SYMBOL(capi_info2str);
#ifdef MODULE
int init_module(void)
{
return 0;
static int __init capiutil_init(void)
{
return 0;
}
void cleanup_module(void)
static void __exit capiutil_exit(void)
{
}
#endif
module_init(capiutil_init);
module_exit(capiutil_exit);

View File

@ -1,60 +1,61 @@
/*
* $Id$
*
/* $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.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
* From CAPI 2.0 Development Kit AVM 1995 (msg.c)
* Rewritten for Linux 1996 by Carsten Paeth <calle@calle.de>
*
* Revision 1.1 1997/03/04 21:50:35 calle
* Frirst version in isdn4linux
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* 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 <asm/types.h>
#define CAPIMSG_LEN(m) (m[0] | (m[1] << 8))
#define CAPIMSG_APPID(m) (m[2] | (m[3] << 8))
#define CAPIMSG_COMMAND(m) (m[4])
#define CAPIMSG_SUBCOMMAND(m) (m[5])
#define CAPIMSG_MSGID(m) (m[6] | (m[7] << 8))
#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) (m[8]|(m[9]<<8)|(m[10]<<16)|(m[11]<<24))
#define CAPIMSG_CONTROL(m) CAPIMSG_U32(m, 8)
#define CAPIMSG_NCCI(m) CAPIMSG_CONTROL(m)
#define CAPIMSG_DATA(m) (m[12]|(m[13]<<8)|(m[14]<<16)|(m[15]<<24))
#define CAPIMSG_DATALEN(m) (m[16] | (m[17]<<8))
#define CAPIMSG_DATALEN(m) CAPIMSG_U16(m,16) /* DATA_B3_REQ */
#define CAPIMSG_SETAPPID(m, applid) \
do { \
((__u8 *)m)[2] = (__u16)(applid) & 0xff; \
((__u8 *)m)[3] = ((__u16)(applid) >> 8) & 0xff; \
} while (0)
static inline void capimsg_setu8(void *m, int off, __u8 val)
{
((__u8 *)m)[off] = val;
}
#define CAPIMSG_SETLEN(m, len) \
do { \
((__u8 *)m)[0] = (__u16)(len) & 0xff; \
((__u8 *)m)[1] = ((__u16)(len) >> 8) & 0xff; \
} while (0)
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 -----*/

View File

@ -0,0 +1,544 @@
/*
* Copyright (C) 2000 AVM GmbH. All rights reserved.
*
* 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, and WITHOUT
* ANY LIABILITY FOR ANY DAMAGES arising out of or in connection
* with the use or performance of this software. See the
* GNU General Public License for further details.
*
*/
/*---------------------------------------------------------------------------*\
*
* Based on Carsten Paeth's PCMCIA client driver for AVM B1/M1/M2
*
\*---------------------------------------------------------------------------*/
#include <pcmcia/config.h>
#include <pcmcia/k_compat.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/timer.h>
#include <asm/io.h>
#include <asm/system.h>
#include <pcmcia/version.h>
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>
#include <linux/skbuff.h>
#include <linux/capi.h>
/*---------------------------------------------------------------------------*\
* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do
* not define PCMCIA_DEBUG at all, all the debug code will be left out. If
* you compile with PCMCIA_DEBUG=0, the debug code will be present but
* disabled -- but it can then be enabled for specific modules at load time
* with a 'pc_debug=#' option to insmod.
\*---------------------------------------------------------------------------*/
#ifdef PCMCIA_DEBUG
static int pc_debug = PCMCIA_DEBUG;
MODULE_PARM(pc_debug, "i");
#define DEBUG(n, args...) if (pc_debug>(n)) \
printk(KERN_DEBUG "fcpcmcia_cs: " args);
#else
#define DEBUG(n, args...)
#endif
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
/* Parameters that can be set with 'insmod' */
/* This means pick from 15, 12, 11, 10, 9, 7, 5, 4, and 3 */
static int default_irq_list[10] = { 15, 12, 11, 10, 9, 7, 5, 4, 3, -1 };
static int irq_list[10] = { -1 };
MODULE_PARM(irq_list, "1-10i");
/*---------------------------------------------------------------------------*\
* The event() function is this driver's Card Services event handler. It will
* be called by Card Services when an appropriate card status event is
* received. The config() and release() entry points are used to configure
* or release a socket, in response to card insertion and ejection events.
* They are invoked from the skeleton event handler.
\*---------------------------------------------------------------------------*/
static void fcpcmcia_config (dev_link_t * link);
static void fcpcmcia_release (u_long arg);
static int fcpcmcia_event (event_t event, int priority,
event_callback_args_t * args);
/*---------------------------------------------------------------------------*\
* The attach() and detach() entry points are used to create and destroy
* "instances" of the driver, where each instance represents everything
* needed to manage one actual PCMCIA card.
\*---------------------------------------------------------------------------*/
static dev_link_t * fcpcmcia_attach (void);
static void fcpcmcia_detach (dev_link_t *);
/*---------------------------------------------------------------------------*\
* The dev_info variable is the "key" that is used to match up this device
* driver with appropriate cards, through the card configuration database.
\*---------------------------------------------------------------------------*/
static dev_info_t dev_info = "fcpcmcia_cs";
/*---------------------------------------------------------------------------*\
* A linked list of "instances" of the skeleton device. Each actual PCMCIA
* card corresponds to one device instance, and is described by one dev_link_t
* structure (defined in ds.h).
*
* You may not want to use a linked list for this -- for example, the memory
* card driver uses an array of dev_link_t pointers, where minor device
* numbers are used to derive the corresponding array index.
\*---------------------------------------------------------------------------*/
static dev_link_t * dev_list = NULL;
/*---------------------------------------------------------------------------*\
* A dev_link_t structure has fields for most things that are needed to keep
* track of a socket, but there will usually be some device specific
* information that also needs to be kept track of. The 'priv' pointer in a
* dev_link_t structure can be used to point to a device-specific private data
* structure, like this.
*
* A driver needs to provide a dev_node_t structure for each device on a
* card. In some cases, there is only one device per card (for example,
* ethernet cards, modems). In other cases, there may be many actual or
* logical devices (SCSI adapters, memory cards with multiple partitions).
* The dev_node_t structures need to be kept in a linked list starting at the
* 'dev' field of a dev_link_t structure. We allocate them in the card's
* private data structure, because they generally can't be allocated
* dynamically.
\*---------------------------------------------------------------------------*/
typedef struct local_info_t {
dev_node_t node;
} local_info_t;
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
static void cs_error(client_handle_t handle, int func, int ret) {
error_info_t err = { func, ret };
CardServices (ReportError, handle, &err);
} /* cs_error */
/*---------------------------------------------------------------------------*\
* fcpcmcia_attach() creates an "instance" of the driver, allocating local
* data structures for one device. The device is registered with Card
* Services.
*
* The dev_link structure is initialized, but we don't actually configure the
* card at this point -- we wait until we receive a card insertion event.
\*---------------------------------------------------------------------------*/
static dev_link_t * fcpcmcia_attach(void) {
client_reg_t client_reg;
dev_link_t * link;
local_info_t * local;
int ret, i;
DEBUG (0, "fcpcmcia_attach()\n");
/* Initialize the dev_link_t structure */
link = kmalloc (sizeof (struct dev_link_t), GFP_KERNEL);
memset (link, 0, sizeof (struct dev_link_t));
link->release.function = &fcpcmcia_release;
link->release.data = (u_long) link;
/* The io structure describes IO port mapping */
link->io.NumPorts1 = 16;
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
link->io.NumPorts2 = 16;
link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
link->io.IOAddrLines = 5;
/* Interrupt setup */
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_FIRST_SHARED;
link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
if (irq_list[0] != -1) {
for (i = 0; i < 10 && irq_list[i] > 0; i++) {
link->irq.IRQInfo2 |= 1 << irq_list[i];
}
} else {
for (i = 0; i < 10 && default_irq_list[i] > 0; i++) {
link->irq.IRQInfo2 |= 1 << default_irq_list[i];
}
}
/* General socket configuration */
link->conf.Attributes = CONF_ENABLE_IRQ;
link->conf.Vcc = 50;
link->conf.IntType = INT_MEMORY_AND_IO;
link->conf.ConfigIndex = 1;
link->conf.Present = PRESENT_OPTION;
/* Allocate space for private device-specific data */
local = kmalloc (sizeof (local_info_t), GFP_KERNEL);
memset (local, 0, sizeof (local_info_t));
link->priv = local;
/* Register with Card Services */
link->next = dev_list;
dev_list = link;
client_reg.dev_info = &dev_info;
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
client_reg.EventMask =
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
client_reg.event_handler = &fcpcmcia_event;
client_reg.Version = 0x0210;
client_reg.event_callback_args.client_data = link;
ret = CardServices (RegisterClient, &link->handle, &client_reg);
if (ret != 0) {
cs_error (link->handle, RegisterClient, ret);
fcpcmcia_detach (link);
return NULL;
}
return link;
} /* fcpcmcia_attach */
/*---------------------------------------------------------------------------*\
* This deletes a driver "instance". The device is de-registered with Card
* Services. If it has been released, all local data structures are freed.
* Otherwise, the structures will be freed when the device is released.
\*---------------------------------------------------------------------------*/
static void fcpcmcia_detach (dev_link_t * link)
{
dev_link_t ** linkp;
DEBUG (0, "fcpcmcia_detach(0x%p)\n", link);
/* Locate device structure */
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
if (*linkp == link) break;
}
if (*linkp == NULL) {
return;
}
/*-----------------------------------------------------------------------*\
* If the device is currently configured and active, we won't actually
* delete it yet. Instead, it is marked so that when the release()
* function is called, that will trigger a proper detach().
\*-----------------------------------------------------------------------*/
if (link->state & DEV_CONFIG) {
#ifdef PCMCIA_DEBUG
printk (KERN_DEBUG "fcpcmcia_cs: detach postponed, '%s' "
"still locked\n", link->dev->dev_name);
#endif
link->state |= DEV_STALE_LINK;
return;
}
/* Break the link with Card Services */
if (link->handle) {
CardServices (DeregisterClient, link->handle);
}
/* Unlink device structure, free pieces */
*linkp = link->next;
if (link->priv) {
kfree_s (link->priv, sizeof(local_info_t));
}
kfree_s (link, sizeof(struct dev_link_t));
} /* fcpcmcia_detach */
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
static int get_tuple (int fn, client_handle_t handle, tuple_t * tuple,
cisparse_t *parse)
{
int i;
i = CardServices (fn, handle, tuple);
if (i != CS_SUCCESS) {
return i;
}
i = CardServices (GetTupleData, handle, tuple);
if (i != CS_SUCCESS) {
return i;
}
return CardServices (ParseTuple, handle, tuple, parse);
} /* get_tuple */
#define first_tuple(a, b, c) get_tuple(GetFirstTuple, a, b, c)
#define next_tuple(a, b, c) get_tuple(GetNextTuple, a, b, c)
/*---------------------------------------------------------------------------*\
* fcpcmcia_config() is scheduled to run after a CARD_INSERTION event is
* received, to configure the PCMCIA socket, and to make the ISDN controller
* available to the system.
\*---------------------------------------------------------------------------*/
static void fcpcmcia_config (dev_link_t * link) {
client_handle_t handle;
tuple_t tuple;
cisparse_t parse;
cistpl_cftable_entry_t * cf = &parse.cftable_entry;
local_info_t * dev;
int i;
u_char buf[64];
char devname[128];
int cardtype;
handle = link->handle;
dev = link->priv;
DEBUG (0, "fcpcmcia_config(0x%p)\n", link);
/*-----------------------------------------------------------------------*\
* Read the card's CONFIG tuple to find its configuration registers.
\*-----------------------------------------------------------------------*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
i = CardServices (GetFirstTuple, handle, &tuple);
if (i != CS_SUCCESS) {
break;
}
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
i = CardServices (GetTupleData, handle, &tuple);
if (i != CS_SUCCESS) {
break;
}
i = CardServices (ParseTuple, handle, &tuple, &parse);
if (i != CS_SUCCESS) {
break;
}
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
cs_error (link->handle, ParseTuple, i);
link->state &= ~DEV_CONFIG_PENDING;
return;
}
/* Configure card */
link->state |= DEV_CONFIG;
do {
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 254;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
if (!first_tuple (handle, &tuple, &parse) && (parse.version_1.ns > 1)) {
strncpy (devname, parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
/* find IO port */
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
i = first_tuple (handle, &tuple, &parse);
while (i == CS_SUCCESS) {
if (cf->io.nwin > 0) {
link->conf.ConfigIndex = cf->index;
link->io.BasePort1 = cf->io.win[0].base;
link->io.NumPorts1 = cf->io.win[0].len;
printk (KERN_INFO "fcpcmcia_cs: testing i/o %#x-%#x\n",
link->io.BasePort1,
link->io.BasePort1 + link->io.NumPorts1);
i = CardServices (RequestIO, link->handle, &link->io);
if (i == CS_SUCCESS) {
goto found_port;
}
}
i = next_tuple (handle, &tuple, &parse);
}
found_port:
if (i != CS_SUCCESS) {
cs_error (link->handle, RequestIO, i);
break;
}
/* allocate an interrupt line */
i = CardServices (RequestIRQ, link->handle, &link->irq);
if (i != CS_SUCCESS) {
cs_error (link->handle, RequestIRQ, i);
CardServices (ReleaseIO, link->handle, &link->io);
break;
}
/* configure the PCMCIA socket */
i = CardServices (RequestConfiguration, link->handle, &link->conf);
if (i != CS_SUCCESS) {
cs_error (link->handle, RequestConfiguration, i);
CardServices (ReleaseIO, link->handle, &link->io);
CardServices (ReleaseIRQ, link->handle, &link->irq);
break;
}
} while (0);
/*-----------------------------------------------------------------------*\
* At this point, the dev_node_t structure(s) should be initialized and
* arranged in a linked list at link->dev.
\*-----------------------------------------------------------------------*/
strcpy (dev->node.dev_name, "A1");
dev->node.major = 45; /* <<<< */
dev->node.minor = 0; /* <<<< */
link->dev = &dev->node;
link->state &= ~DEV_CONFIG_PENDING;
/* If any step failed, release any partially configured state */
if (i != 0) {
fcpcmcia_release ((u_long) link);
return;
}
if ((i = avm_a1pcmcia_addcard (link->io.BasePort1, link->irq.AssignedIRQ)) < 0) {
printk (KERN_ERR "fcpcmcia_cs: failed to add AVM-%s-Controller at"
" i/o %#x, irq %d\n",
dev->node.dev_name, link->io.BasePort1, link->irq.AssignedIRQ);
fcpcmcia_release ((u_long) link);
return;
}
dev->node.minor = i;
printk (KERN_DEBUG "fcpcmcia_cs device loaded\n");
} /* fcpcmcia_config */
/*---------------------------------------------------------------------------*\
* After a card is removed, fcpcmcia_release() will unregister the net device,
* and release the PCMCIA configuration. If the device is still open, this
* will be postponed until it is closed.
\*---------------------------------------------------------------------------*/
static void fcpcmcia_release (u_long arg) {
dev_link_t * link = (dev_link_t *) arg;
DEBUG (0, "fcpcmcia_release(0x%p)\n", link);
/*-----------------------------------------------------------------------*\
* If the device is currently in use, we won't release until it is
* actually closed.
\*-----------------------------------------------------------------------*/
if (link->open) {
DEBUG (1, "fcpcmcia_cs: release postponed, '%s' still open\n",
link->dev->dev_name);
link->state |= DEV_STALE_CONFIG;
return;
}
avm_a1pcmcia_delcard (link->io.BasePort1, link->irq.AssignedIRQ);
/* Unlink the device chain */
link->dev = NULL;
/* Don't bother checking to see if these succeed or not */
(void) CardServices (ReleaseConfiguration, link->handle);
(void) CardServices (ReleaseIO, link->handle, &link->io);
(void) CardServices (ReleaseIRQ, link->handle, &link->irq);
link->state &= ~DEV_CONFIG;
if (link->state & DEV_STALE_LINK)
fcpcmcia_detach (link);
} /* fcpcmcia_release */
/*---------------------------------------------------------------------------*\
* The card status event handler. Mostly, this schedules other stuff to run
* after an event is received. A CARD_REMOVAL event also sets some flags to
* discourage the net drivers from trying to talk to the card any more.
*
* When a CARD_REMOVAL event is received, we immediately set a flag to block
* future accesses to this device. All the functions that actually access
* the device should check this flag to make sure the card is still present.
\*---------------------------------------------------------------------------*/
static int fcpcmcia_event (event_t event, int priority,
event_callback_args_t * args)
{
dev_link_t * link = args->client_data;
DEBUG (1, "fcpcmcia_event(0x%06x)\n", event);
switch (event) {
case CS_EVENT_CARD_REMOVAL:
link->state &= ~DEV_PRESENT;
if (link->state & DEV_CONFIG) {
link->release.expires = RUN_AT (HZ/20);
add_timer (&link->release);
}
break;
case CS_EVENT_CARD_INSERTION:
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
fcpcmcia_config (link);
break;
case CS_EVENT_PM_SUSPEND:
link->state |= DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_RESET_PHYSICAL:
if (link->state & DEV_CONFIG) {
CardServices (ReleaseConfiguration, link->handle);
}
break;
case CS_EVENT_PM_RESUME:
link->state &= ~DEV_SUSPEND;
/* Fall through... */
case CS_EVENT_CARD_RESET:
if (link->state & DEV_CONFIG) {
CardServices (RequestConfiguration, link->handle, &link->conf);
}
break;
}
return 0;
} /* fcpcmcia_event */
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
int init_module (void) {
servinfo_t serv;
DEBUG (0, "%s\n", version);
CardServices (GetCardServicesInfo, &serv);
if (serv.Revision != CS_RELEASE_CODE) {
printk (KERN_NOTICE "fcpcmcia_cs: Card Services release "
"does not match!\n");
return -1;
}
register_pcmcia_driver (&dev_info, &fcpcmcia_attach, &fcpcmcia_detach);
return 0;
} /* init_module */
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/
void cleanup_module (void) {
DEBUG (0, "fcpcmcia_cs: unloading\n");
unregister_pcmcia_driver (&dev_info);
while (dev_list != NULL) {
if (dev_list->state & DEV_CONFIG) {
fcpcmcia_release ((u_long) dev_list);
}
fcpcmcia_detach (dev_list);
}
} /* cleanup_module */
/*---------------------------------------------------------------------------*\
\*---------------------------------------------------------------------------*/

View File

@ -1,65 +1,14 @@
/*
* $Id$
/* $Id$
*
* Kernel CAPI 2.0 Module
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.de>
*
* $Log$
* 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.
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define CONFIG_AVMB1_COMPAT
#include <linux/config.h>
@ -72,12 +21,12 @@
#include <linux/proc_fs.h>
#include <linux/skbuff.h>
#include <linux/tqueue.h>
#include <linux/isdn_compat.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/isdn_compat.h>
#ifdef COMPAT_NEED_UACCESS
#include <linux/locks.h>
#include <linux/init.h>
#include <asm/uaccess.h>
#endif
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
@ -96,10 +45,12 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
int showcapimsgs = 0;
static int showcapimsgs = 0;
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_PARM(showcapimsgs, "0-4i");
MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
MODULE_PARM(showcapimsgs, "i");
/* ------------------------------------------------------------- */
@ -124,8 +75,8 @@ struct capi_appl {
__u16 applid;
capi_register_params rparam;
int releasing;
__u32 param;
void (*signal) (__u16 applid, __u32 param);
void *param;
void (*signal) (__u16 applid, void *param);
struct sk_buff_head recv_queue;
int nncci;
struct capi_ncci *nccilist;
@ -136,6 +87,14 @@ struct capi_appl {
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};
@ -159,9 +118,9 @@ 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 long notify_up_set = 0;
static long notify_down_set = 0;
static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
static struct tq_struct tq_state_notify;
static struct tq_struct tq_recv_notify;
@ -225,7 +184,6 @@ static int proc_applications_read_proc(char *page, char **start, off_t off,
struct capi_appl *ap;
int i;
int len = 0;
off_t begin = 0;
for (i=0; i < CAPI_MAXAPPL; i++) {
ap = &applications[i];
@ -237,20 +195,21 @@ static int proc_applications_read_proc(char *page, char **start, off_t off,
ap->rparam.datablklen,
ap->nncci,
skb_queue_len(&ap->recv_queue));
if (len+begin > off+count)
goto endloop;
if (len+begin < off) {
begin += len;
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
endloop:
if (i >= CAPI_MAXAPPL)
*start = page+off;
if (len < count)
*eof = 1;
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*
@ -264,7 +223,6 @@ static int proc_ncci_read_proc(char *page, char **start, off_t off,
struct capi_ncci *np;
int i;
int len = 0;
off_t begin = 0;
for (i=0; i < CAPI_MAXAPPL; i++) {
ap = &applications[i];
@ -275,21 +233,22 @@ static int proc_ncci_read_proc(char *page, char **start, off_t off,
np->ncci,
np->winsize,
np->nmsg);
if (len+begin > off+count)
goto endloop;
if (len+begin < off) {
begin += len;
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
}
endloop:
if (i >= CAPI_MAXAPPL)
*start = page+off;
if (len < count)
*eof = 1;
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*
@ -301,27 +260,29 @@ static int proc_driver_read_proc(char *page, char **start, off_t off,
{
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;
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
endloop:
if (!driver)
spin_unlock(&drivers_lock);
*start = page+off;
if (len < count)
*eof = 1;
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*
@ -333,24 +294,26 @@ static int proc_users_read_proc(char *page, char **start, off_t off,
{
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;
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
endloop:
if (cp == 0)
spin_unlock(&capi_users_lock);
*start = page+off;
if (len < count)
*eof = 1;
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*
@ -363,7 +326,6 @@ static int proc_controller_read_proc(char *page, char **start, off_t off,
struct capi_ctr *cp;
int i;
int len = 0;
off_t begin = 0;
for (i=0; i < CAPI_MAXCONTR; i++) {
cp = &cards[i];
@ -374,20 +336,21 @@ static int proc_controller_read_proc(char *page, char **start, off_t off,
cp->name,
cp->driver->procinfo ? cp->driver->procinfo(cp) : ""
);
if (len+begin > off+count)
goto endloop;
if (len+begin < off) {
begin += len;
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
endloop:
if (i >= CAPI_MAXCONTR)
*start = page+off;
if (len < count)
*eof = 1;
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*
@ -400,7 +363,6 @@ static int proc_applstats_read_proc(char *page, char **start, off_t off,
struct capi_appl *ap;
int i;
int len = 0;
off_t begin = 0;
for (i=0; i < CAPI_MAXAPPL; i++) {
ap = &applications[i];
@ -411,20 +373,21 @@ static int proc_applstats_read_proc(char *page, char **start, off_t off,
ap->nrecvdatapkt,
ap->nsentctlpkt,
ap->nsentdatapkt);
if (len+begin > off+count)
goto endloop;
if (len+begin < off) {
begin += len;
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
endloop:
if (i >= CAPI_MAXAPPL)
*start = page+off;
if (len < count)
*eof = 1;
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
/*
@ -437,7 +400,6 @@ static int proc_contrstats_read_proc(char *page, char **start, off_t off,
struct capi_ctr *cp;
int i;
int len = 0;
off_t begin = 0;
for (i=0; i < CAPI_MAXCONTR; i++) {
cp = &cards[i];
@ -448,20 +410,21 @@ static int proc_contrstats_read_proc(char *page, char **start, off_t off,
cp->nrecvdatapkt,
cp->nsentctlpkt,
cp->nsentdatapkt);
if (len+begin > off+count)
goto endloop;
if (len+begin < off) {
begin += len;
if (len <= off) {
off -= len;
len = 0;
} else {
if (len-off > count)
goto endloop;
}
}
endloop:
if (i >= CAPI_MAXCONTR)
*start = page+off;
if (len < count)
*eof = 1;
if (off >= len+begin)
return 0;
*start = page + (begin-off);
return ((count < begin+len-off) ? count : begin+len-off);
if (len>count) len = count;
if (len<0) len = 0;
return len;
}
static struct procfsentries {
@ -509,6 +472,176 @@ static void proc_capi_exit(void)
}
}
/* -------- Notifier handling --------------------------------- */
static struct capi_notifier_list{
struct capi_notifier *head;
struct capi_notifier *tail;
} notifier_list;
static spinlock_t notifier_lock = SPIN_LOCK_UNLOCKED;
static inline void notify_enqueue(struct capi_notifier *np)
{
struct capi_notifier_list *q = &notifier_list;
unsigned long flags;
spin_lock_irqsave(&notifier_lock, flags);
if (q->tail) {
q->tail->next = np;
q->tail = np;
} else {
q->head = q->tail = np;
}
spin_unlock_irqrestore(&notifier_lock, flags);
}
static inline struct capi_notifier *notify_dequeue(void)
{
struct capi_notifier_list *q = &notifier_list;
struct capi_notifier *np = 0;
unsigned long flags;
spin_lock_irqsave(&notifier_lock, flags);
if (q->head) {
np = q->head;
if ((q->head = np->next) == 0)
q->tail = 0;
np->next = 0;
}
spin_unlock_irqrestore(&notifier_lock, flags);
return np;
}
static int notify_push(unsigned int cmd, __u32 controller,
__u16 applid, __u32 ncci)
{
struct capi_notifier *np;
MOD_INC_USE_COUNT;
np = (struct capi_notifier *)kmalloc(sizeof(struct capi_notifier), GFP_ATOMIC);
if (!np) {
MOD_DEC_USE_COUNT;
return -1;
}
memset(np, 0, sizeof(struct capi_notifier));
np->cmd = cmd;
np->controller = controller;
np->applid = applid;
np->ncci = ncci;
notify_enqueue(np);
/*
* The notifier will result in adding/deleteing
* of devices. Devices can only removed in
* user process, not in bh.
*/
#ifdef COMPAT_HAS_SCHEDULE_TASK
MOD_INC_USE_COUNT;
if (schedule_task(&tq_state_notify) == 0)
MOD_DEC_USE_COUNT;
#else
queue_task(&tq_state_notify, &tq_scheduler);
#endif
return 0;
}
/* -------- 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;
}
#ifdef COMPAT_HAS_SCHEDULE_TASK
MOD_DEC_USE_COUNT;
#endif
}
/* -------- NCCI Handling ------------------------------------- */
static inline void mq_init(struct capi_ncci * np)
@ -587,7 +720,7 @@ static void controllercb_appl_released(struct capi_ctr * card, __u16 appl)
}
}
/*
* ncci managment
* ncci management
*/
static void controllercb_new_ncci(struct capi_ctr * card,
@ -616,6 +749,7 @@ static void controllercb_new_ncci(struct capi_ctr * card,
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,
@ -633,6 +767,7 @@ static void controllercb_free_ncci(struct capi_ctr * card,
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;
}
}
@ -733,42 +868,6 @@ error:
kfree_skb(skb);
}
/* -------- Notifier ------------------------------------------ */
static void notify_up(__u32 contr)
{
struct capi_interface_user *p;
printk(KERN_NOTICE "kcapi: notify up contr %d\n", contr);
for (p = capi_users; p; p = p->next) {
if (!p->callback) continue;
(*p->callback) (KCI_CONTRUP, contr, &CARD(contr)->profile);
}
}
static void notify_down(__u32 contr)
{
struct capi_interface_user *p;
printk(KERN_NOTICE "kcapi: notify down contr %d\n", contr);
for (p = capi_users; p; p = p->next) {
if (!p->callback) continue;
(*p->callback) (KCI_CONTRDOWN, contr, 0);
}
}
static void notify_handler(void *dummy)
{
__u32 contr;
for (contr=1; VALID_CARD(contr); contr++)
if (test_and_clear_bit(contr, &notify_up_set))
notify_up(contr);
for (contr=1; VALID_CARD(contr); contr++)
if (test_and_clear_bit(contr, &notify_down_set))
notify_down(contr);
}
static void controllercb_ready(struct capi_ctr * card)
{
__u16 appl;
@ -781,11 +880,10 @@ static void controllercb_ready(struct capi_ctr * card)
card->driver->register_appl(card, appl, &APPL(appl)->rparam);
}
set_bit(CARDNR(card), &notify_up_set);
queue_task(&tq_state_notify, &tq_scheduler);
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)
@ -811,6 +909,7 @@ static void controllercb_reseted(struct capi_ctr * card)
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 {
@ -818,9 +917,10 @@ static void controllercb_reseted(struct capi_ctr * card)
}
}
}
set_bit(CARDNR(card), &notify_down_set);
queue_task(&tq_state_notify, &tq_scheduler);
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)
@ -936,7 +1036,7 @@ static int driver_read_proc(char *page, char **start, off_t off,
if (len < off)
return 0;
*eof = 1;
*start = page - off;
*start = page + off;
return ((count < len-off) ? count : len-off);
}
@ -951,9 +1051,12 @@ 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);
@ -973,6 +1076,7 @@ struct capi_driver_interface *attach_capi_driver(struct capi_driver *driver)
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;
@ -980,10 +1084,12 @@ void detach_capi_driver(struct capi_driver *driver)
} 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;
}
/* ------------------------------------------------------------- */
@ -1035,19 +1141,19 @@ static __u16 capi_register(capi_register_params * rparam, __u16 * applidp)
static __u16 capi_release(__u16 applid)
{
struct sk_buff *skb;
int i;
if (!VALID_APPLID(applid) || APPL(applid)->releasing)
return CAPI_ILLAPPNR;
while ((skb = skb_dequeue(&APPL(applid)->recv_queue)) != 0)
kfree_skb(skb);
APPL(applid)->releasing++;
skb_queue_purge(&APPL(applid)->recv_queue);
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);
@ -1127,8 +1233,8 @@ static __u16 capi_get_message(__u16 applid, struct sk_buff **msgp)
}
static __u16 capi_set_signal(__u16 applid,
void (*signal) (__u16 applid, __u32 param),
__u32 param)
void (*signal) (__u16 applid, void *param),
void *param)
{
if (!VALID_APPLID(applid))
return CAPI_ILLAPPNR;
@ -1193,10 +1299,12 @@ static __u16 capi_get_profile(__u32 contr, struct capi_profile *profp)
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)
return dp;
return 0;
break;
spin_unlock(&drivers_lock);
return dp;
}
#ifdef CONFIG_AVMB1_COMPAT
@ -1271,6 +1379,10 @@ static int old_capi_manufacturer(unsigned int cmd, void *data)
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);
@ -1489,16 +1601,20 @@ 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;
MOD_INC_USE_COUNT;
spin_unlock(&capi_users_lock);
printk(KERN_NOTICE "kcapi: %s attached\n", userp->name);
return &avmb1_interface;
@ -1508,15 +1624,18 @@ 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;
MOD_DEC_USE_COUNT;
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;
}
@ -1530,42 +1649,18 @@ 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)
static int __init kcapi_init(void)
{
char *p;
char rev[10];
char rev[32];
MOD_INC_USE_COUNT;
skb_queue_head_init(&recv_queue);
/* init_bh(CAPI_BH, do_capi_bh); */
tq_state_notify.routine = notify_handler;
tq_state_notify.data = 0;
@ -1575,41 +1670,24 @@ int kcapi_init(void)
proc_capi_init();
if ((p = strchr(revision, ':'))) {
strcpy(rev, p + 1);
p = strchr(rev, '$');
*p = 0;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(rev, p + 2, sizeof(rev));
rev[sizeof(rev)-1] = 0;
if ((p = strchr(rev, '$')) != 0 && p > rev)
*(p-1) = 0;
} else
strcpy(rev, "1.0");
#ifdef MODULE
printk(KERN_NOTICE "CAPI-driver Rev%s: loaded\n", rev);
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
printk(KERN_NOTICE "CAPI-driver Rev %s: started\n", rev);
#endif
MOD_DEC_USE_COUNT;
return 0;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit kcapi_exit(void)
{
char rev[10];
char *p;
@ -1622,8 +1700,9 @@ void cleanup_module(void)
strcpy(rev, "1.0");
}
schedule(); /* execute queued tasks .... */
proc_capi_exit();
printk(KERN_NOTICE "CAPI-driver Rev%s: unloaded\n", rev);
}
#endif
module_init(kcapi_init);
module_exit(kcapi_exit);

View File

@ -1,65 +1,11 @@
/*
* $Id$
/* $Id$
*
* Module for AVM T1 HEMA-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -71,8 +17,10 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/capi.h>
#include <asm/io.h>
#include <linux/kernelcapi.h>
#include <linux/init.h>
#include <linux/isdn_compat.h>
#include <asm/io.h>
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
@ -82,7 +30,9 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
@ -132,7 +82,7 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
cli();
/* board reset */
t1outp(base, T1_RESETBOARD, 0xf);
udelay(100 * 1000);
mdelay(100);
dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */
/* write config */
@ -144,18 +94,18 @@ static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr)
t1outp(base, ((base >> 4)) & 0x3, cregs[7]);
restore_flags(flags);
udelay(100 * 1000);
mdelay(100);
t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
udelay(10 * 1000);
mdelay(10);
t1outp(base, T1_FASTLINK+T1_RESETLINK, 1);
t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1);
udelay(100 * 1000);
mdelay(100);
t1outp(base, T1_FASTLINK+T1_RESETLINK, 0);
t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0);
udelay(10 * 1000);
mdelay(10);
t1outp(base, T1_FASTLINK+T1_ANALYSE, 0);
udelay(5 * 1000);
mdelay(5);
t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0);
if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */
@ -275,25 +225,30 @@ static void t1_handle_interrupt(avmcard * card)
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
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;
card->msgbuf[MsgLen] = 0;
while ( MsgLen > 0
&& ( card->msgbuf[MsgLen-1] == '\n'
|| card->msgbuf[MsgLen-1] == '\r')) {
card->msgbuf[MsgLen-1] = 0;
MsgLen--;
}
printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf);
break;
case 0xff:
printk(KERN_ERR "%s: card reseted ?\n", card->name);
return;
@ -367,7 +322,7 @@ static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data)
cli();
b1_setinterrupt(port, card->irq, card->cardtype);
b1_put_byte(port, SEND_INIT);
b1_put_word(port, AVM_NAPPS);
b1_put_word(port, CAPI_MAXAPPL);
b1_put_word(port, AVM_NCCI_PER_CHANNEL*30);
b1_put_word(port, ctrl->cnr - 1);
restore_flags(flags);
@ -570,36 +525,35 @@ static char *t1isa_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
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,
name: "t1isa",
revision: "0.0",
load_firmware: t1isa_load_firmware,
reset_ctr: t1isa_reset_ctr,
remove_ctr: t1isa_remove_ctr,
register_appl: b1_register_appl,
release_appl: b1_release_appl,
send_message: t1isa_send_message,
t1isa_procinfo,
b1ctl_read_proc,
0, /* use standard driver_read_proc */
procinfo: t1isa_procinfo,
ctr_read_proc: b1ctl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
t1isa_add_card,
add_card: t1isa_add_card,
};
#ifdef MODULE
#define t1isa_init init_module
void cleanup_module(void);
#endif
int t1isa_init(void)
static int __init t1isa_init(void)
{
struct capi_driver *driver = &t1isa_driver;
char *p;
int retval = 0;
if ((p = strchr(revision, ':'))) {
strncpy(driver->revision, p + 1, sizeof(driver->revision));
p = strchr(driver->revision, '$');
*p = 0;
MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 0;
}
printk(KERN_INFO "%s: revision %s\n", driver->name, driver->revision);
@ -609,14 +563,17 @@ int t1isa_init(void)
if (!di) {
printk(KERN_ERR "%s: failed to attach capi_driver\n",
driver->name);
return -EIO;
retval = -EIO;
}
return 0;
MOD_DEC_USE_COUNT;
return retval;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit t1isa_exit(void)
{
detach_capi_driver(&t1isa_driver);
}
#endif
module_init(t1isa_init);
module_exit(t1isa_exit);

View File

@ -1,29 +1,11 @@
/*
* $Id$
/* $Id$
*
* Module for AVM T1 PCI-card.
*
* (c) Copyright 1999 by Carsten Paeth (calle@calle.in-berlin.de)
* Copyright 1999 by Carsten Paeth <calle@calle.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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -36,9 +18,10 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/capi.h>
#include <asm/io.h>
#include <linux/isdn_compat.h>
#include <linux/capi.h>
#include <linux/init.h>
#include <asm/io.h>
#include "capicmd.h"
#include "capiutil.h"
#include "capilli.h"
@ -51,17 +34,17 @@ static char *revision = "$Revision$";
/* ------------------------------------------------------------- */
#ifndef PCI_VENDOR_ID_AVM
#define PCI_VENDOR_ID_AVM 0x1244
#ifndef COMPAT_HAS_2_2_PCI
static struct pci_device_id t1pci_pci_tbl[] __initdata = {
{ PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, t1pci_pci_tbl);
#endif
#ifndef PCI_DEVICE_ID_AVM_T1
#define PCI_DEVICE_ID_AVM_T1 0x1200
#endif
/* ------------------------------------------------------------- */
MODULE_AUTHOR("Carsten Paeth <calle@calle.in-berlin.de>");
MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 PCI card");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");
/* ------------------------------------------------------------- */
@ -78,7 +61,7 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
di->detach_ctr(ctrl);
free_irq(card->irq, card);
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
ctrl->driverdata = 0;
kfree(card->ctrlinfo);
@ -92,7 +75,6 @@ static void t1pci_remove_ctr(struct capi_ctr *ctrl)
static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
{
unsigned long base, page_offset;
avmcard *card;
avmctrl_info *cinfo;
int retval;
@ -143,12 +125,8 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
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 {
card->mbase = ioremap_nocache(card->membase, 64);
if (!card->mbase) {
printk(KERN_NOTICE "%s: can't remap memory at 0x%lx\n",
driver->name, card->membase);
kfree(card->ctrlinfo);
@ -161,9 +139,13 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
b1dma_reset(card);
if ((retval = t1pci_detect(card)) != 0) {
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
if (retval < 6)
printk(KERN_NOTICE "%s: NO card at 0x%x (%d)\n",
driver->name, card->port, retval);
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
else
printk(KERN_NOTICE "%s: card at 0x%x, but cabel not connected or T1 has no power (%d)\n",
driver->name, card->port, retval);
iounmap(card->mbase);
kfree(card->ctrlinfo);
kfree(card->dma);
kfree(card);
@ -178,7 +160,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
if (retval) {
printk(KERN_ERR "%s: unable to get IRQ %d.\n",
driver->name, card->irq);
iounmap((void *) (((unsigned long) card->mbase) & PAGE_MASK));
iounmap(card->mbase);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
kfree(card->dma);
@ -190,7 +172,7 @@ static int t1pci_add_card(struct capi_driver *driver, struct capicardparams *p)
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));
iounmap(card->mbase);
free_irq(card->irq, card);
release_region(card->port, AVMB1_PORTLEN);
kfree(card->ctrlinfo);
@ -231,65 +213,63 @@ static char *t1pci_procinfo(struct capi_ctr *ctrl)
/* ------------------------------------------------------------- */
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,
name: "t1pci",
revision: "0.0",
load_firmware: b1dma_load_firmware,
reset_ctr: b1dma_reset_ctr,
remove_ctr: t1pci_remove_ctr,
register_appl: b1dma_register_appl,
release_appl: b1dma_release_appl,
send_message: b1dma_send_message,
t1pci_procinfo,
b1dmactl_read_proc,
0, /* use standard driver_read_proc */
procinfo: t1pci_procinfo,
ctr_read_proc: b1dmactl_read_proc,
driver_read_proc: 0, /* use standard driver_read_proc */
0, /* no add_card function */
add_card: 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)
static int __init 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;
MOD_INC_USE_COUNT;
if ((p = strchr(revision, ':')) != 0 && p[1]) {
strncpy(driver->revision, p + 2, sizeof(driver->revision));
driver->revision[sizeof(driver->revision)-1] = 0;
if ((p = strchr(driver->revision, '$')) != 0 && p > driver->revision)
*(p-1) = 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);
MOD_DEC_USE_COUNT;
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;
if (pci_enable_device(dev) < 0) {
printk(KERN_ERR "%s: failed to enable AVM-T1-PCI\n",
driver->name);
continue;
}
pci_set_master(dev);
param.port = pci_resource_start_io(dev, 1);
param.irq = dev->irq;
param.membase = pci_resource_start_mem(dev, 0);
printk(KERN_INFO
"%s: PCI BIOS reports AVM-T1-PCI at i/o %#x, irq %d, mem %#x\n",
@ -299,29 +279,26 @@ int t1pci_init(void)
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;
continue;
}
ncards++;
}
if (ncards) {
printk(KERN_INFO "%s: %d T1-PCI card(s) detected\n",
driver->name, ncards);
MOD_DEC_USE_COUNT;
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
detach_capi_driver(&t1pci_driver);
MOD_DEC_USE_COUNT;
return -ENODEV;
}
#ifdef MODULE
void cleanup_module(void)
static void __exit t1pci_exit(void)
{
detach_capi_driver(&t1pci_driver);
}
#endif
module_init(t1pci_init);
module_exit(t1pci_exit);

View File

@ -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 <sys/types.h>
#include <sys/fcntl.h>
/* #include <sys/mman.h> */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/isdn.h>
#include <linux/isdnif.h>
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);
}

View File

@ -1,18 +1,26 @@
L_OBJS :=
LX_OBJS :=
M_OBJS :=
MX_OBJS :=
O_OBJS :=
OX_OBJS :=
L_TARGET :=
O_TARGET :=
#
# Makefile for the dss1_divert ISDN module
#
O_OBJS += isdn_divert.o divert_procfs.o
O_TARGET := dss1_divert.o
M_OBJS += dss1_divert.o
OX_OBJS += divert_init.o
# The target object and module list name.
include $(TOPDIR)/Rules.make
O_TARGET := vmlinux-obj.o
# Multipart objects.
list-multi := dss1_divert.o
dss1_divert-objs := isdn_divert.o divert_procfs.o divert_init.o
# Each configuration option enables a list of files.
obj-$(CONFIG_ISDN_DIVERSION) += dss1_divert.o
include $(TOPDIR)/drivers/isdn/Rules.make
# Link rules for multi-part drivers.
dss1_divert.o: $(dss1_divert-objs)
$(LD) -r -o $@ $(dss1_divert-objs)

View File

@ -1,40 +1,23 @@
/*
* $Id$
/* $Id divert_init.c,v 1.5.6.2 2001/01/24 22:18:17 kai Exp $
*
* 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
*
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include "isdn_divert.h"
MODULE_DESCRIPTION("ISDN4Linux: Call diversion support");
MODULE_AUTHOR("Werner Cornelius");
MODULE_LICENSE("GPL");
/********************/
/* needed externals */
/********************/
@ -56,7 +39,7 @@ isdn_divert_if divert_if =
/* Module interface code */
/* no cmd line parms */
/*************************/
int init_module(void)
static int __init divert_init(void)
{ int i;
if (divert_dev_init())
@ -73,13 +56,13 @@ int init_module(void)
#endif
printk(KERN_INFO "dss1_divert module successfully installed\n");
return(0);
} /* init_module */
}
/**********************/
/* Module deinit code */
/**********************/
void cleanup_module(void)
{ int flags;
static void __exit divert_exit(void)
{ unsigned long flags;
int i;
save_flags(flags);
@ -99,6 +82,8 @@ void cleanup_module(void)
deleterule(-1); /* delete all rules and free mem */
deleteprocs();
printk(KERN_INFO "dss1_divert module successfully removed \n");
} /* cleanup_module */
}
module_init(divert_init);
module_exit(divert_exit);

View File

@ -1,44 +1,11 @@
/*
* $Id$
/* $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
*
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -47,6 +14,9 @@
#include <linux/module.h>
#include <linux/version.h>
#include <linux/poll.h>
#ifndef COMPAT_USE_MODCOUNT_LOCK
#include <linux/smp_lock.h>
#endif
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
#else
@ -62,11 +32,7 @@
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 */
@ -75,7 +41,7 @@ void
put_info_buffer(char *cp)
{
struct divert_info *ib;
int flags;
unsigned long flags;
if (if_used <= 0)
return;
@ -170,9 +136,13 @@ isdn_divert_poll(struct file *file, poll_table * wait)
static int
isdn_divert_open(struct inode *ino, struct file *filep)
{
int flags;
unsigned long flags;
#ifdef COMPAT_USE_MODCOUNT_LOCK
MOD_INC_USE_COUNT;
#else
lock_kernel();
#endif
save_flags(flags);
cli();
if_used++;
@ -182,6 +152,9 @@ isdn_divert_open(struct inode *ino, struct file *filep)
(struct divert_info **) filep->private_data = &divert_info_head;
restore_flags(flags);
/* start_divert(); */
#ifndef COMPAT_USE_MODCOUNT_LOCK
unlock_kernel();
#endif
return (0);
} /* isdn_divert_open */
@ -192,8 +165,11 @@ static int
isdn_divert_close(struct inode *ino, struct file *filep)
{
struct divert_info *inf;
int flags;
unsigned long flags;
#ifndef COMPAT_USE_MODCOUNT_LOCK
lock_kernel();
#endif
save_flags(flags);
cli();
if_used--;
@ -209,7 +185,11 @@ isdn_divert_close(struct inode *ino, struct file *filep)
divert_info_head = divert_info_head->next;
kfree(inf);
}
#ifdef COMPAT_USE_MODCOUNT_LOCK
MOD_DEC_USE_COUNT;
#else
unlock_kernel();
#endif
return (0);
} /* isdn_divert_close */
@ -221,7 +201,8 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
uint cmd, ulong arg)
{
divert_ioctl dioctl;
int i, flags;
int i;
unsigned long flags;
divert_rule *rulep;
char *cp;
@ -299,27 +280,16 @@ isdn_divert_ioctl(struct inode *inode, struct file *file,
#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 */
llseek: no_llseek,
read: isdn_divert_read,
write: isdn_divert_write,
poll: isdn_divert_poll,
ioctl: isdn_divert_ioctl,
open: isdn_divert_open,
release: isdn_divert_close,
};
#ifdef COMPAT_NO_SOFTNET
struct inode_operations divert_file_inode_operations;
#endif
@ -338,9 +308,7 @@ 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);
@ -357,8 +325,10 @@ divert_dev_init(void)
isdn_divert_entry->ops = &divert_file_inode_operations;
#else
isdn_divert_entry->proc_fops = &isdn_fops;
#ifdef COMPAT_HAS_FILEOP_OWNER
isdn_divert_entry->owner = THIS_MODULE;
#endif
#endif /* COMPAT_NO_SOFTNET */
#endif /* CONFIG_PROC_FS */
return (0);

View File

@ -1,46 +1,14 @@
/*
* $Id$
/* $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
*
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/version.h>
#include <linux/proc_fs.h>
#include "isdn_divert.h"
@ -83,7 +51,7 @@ static unsigned char extern_wait_max = 4; /* maximum wait in s for external proc
/* timer callback function */
/***************************/
static void deflect_timer_expire(ulong arg)
{ int flags;
{ unsigned long flags;
struct call_struc *cs = (struct call_struc *) arg;
save_flags(flags);
@ -116,6 +84,9 @@ static void deflect_timer_expire(ulong arg)
restore_flags(flags);
break;
case NETWORK_DIAL:
divert_if.dial_net_name(cs->deflect_dest);
case DEFLECT_AUTODEL:
default:
save_flags(flags);
@ -141,7 +112,8 @@ static void deflect_timer_expire(ulong arg)
int cf_command(int drvid, int mode,
u_char proc, char *msn,
u_char service, char *fwd_nr, ulong *procid)
{ int retval,msnlen,flags;
{ unsigned long flags;
int retval,msnlen;
int fwd_len;
char *p,*ielenp,tmp[60];
struct call_struc *cs;
@ -203,7 +175,7 @@ int cf_command(int drvid, int mode,
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",
sprintf(cs->info,"%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
(!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
cs->ics.parm.dss1_io.ll_id,
(mode != 2) ? "" : "0 ",
@ -236,7 +208,7 @@ int cf_command(int drvid, int mode,
int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
{ struct call_struc *cs;
isdn_ctrl ic;
int flags;
unsigned long flags;
int i;
if ((cmd & 0x7F) > 2) return(-EINVAL); /* invalid command */
@ -306,8 +278,8 @@ int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
/* insert a new rule before idx */
/********************************/
int insertrule(int idx, divert_rule *newrule)
{ struct deflect_struc *ds,*ds1;
int flags;
{ struct deflect_struc *ds,*ds1=NULL;
unsigned long flags;
if (!(ds = (struct deflect_struc *) kmalloc(sizeof(struct deflect_struc),
GFP_KERNEL)))
@ -353,7 +325,7 @@ int insertrule(int idx, divert_rule *newrule)
/***********************************/
int deleterule(int idx)
{ struct deflect_struc *ds,*ds1;
int flags;
unsigned long flags;
if (idx < 0)
{ save_flags(flags);
@ -421,7 +393,7 @@ divert_rule *getruleptr(int idx)
/*************************************************/
int isdn_divert_icall(isdn_ctrl *ic)
{ int retval = 0;
int flags;
unsigned long flags;
struct call_struc *cs = NULL;
struct deflect_struc *dv;
char *p,*p1;
@ -483,6 +455,7 @@ int isdn_divert_icall(isdn_ctrl *ic)
case DEFLECT_PROCEED:
case DEFLECT_REPORT:
case DEFLECT_REJECT:
case NETWORK_DIAL:
if (dv->rule.action == DEFLECT_PROCEED)
if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
return(0); /* no external deflection needed */
@ -526,6 +499,11 @@ int isdn_divert_icall(isdn_ctrl *ic)
else
{ cs->deflect_dest[0] = '\0';
retval = 4; /* only proceed */
if (cs->akt_state == NETWORK_DIAL) {
strcpy(cs->deflect_dest,dv->rule.to_nr);
cs->timer.expires = jiffies + 10;
retval = 0;
}
}
sprintf(cs->info,"%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
cs->akt_state,
@ -573,7 +551,7 @@ int isdn_divert_icall(isdn_ctrl *ic)
void deleteprocs(void)
{ struct call_struc *cs, *cs1;
int flags;
unsigned long flags;
save_flags(flags);
cli();
@ -730,7 +708,8 @@ int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
/*********************************************/
int prot_stat_callback(isdn_ctrl *ic)
{ struct call_struc *cs, *cs1;
int i,flags;
int i;
unsigned long flags;
cs = divert_head; /* start of list */
cs1 = NULL;
@ -833,7 +812,8 @@ int prot_stat_callback(isdn_ctrl *ic)
/***************************/
int isdn_divert_stat_callback(isdn_ctrl *ic)
{ struct call_struc *cs, *cs1;
int flags, retval;
unsigned long flags;
int retval;
retval = -1;
cs = divert_head; /* start of list */

View File

@ -1,37 +1,14 @@
/*
* $Id$
/* $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
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/ioctl.h>
#include <linux/types.h>
@ -59,9 +36,10 @@
#define DEFLECT_PROCEED 2 /* deflect when externally triggered */
#define DEFLECT_ALERT 3 /* alert and deflect after delay */
#define DEFLECT_REJECT 4 /* reject immediately */
#define DIVERT_ACTIVATE 5 /* diversion activate */
#define DIVERT_DEACTIVATE 6 /* diversion deactivate */
#define DIVERT_REPORT 7 /* interrogation result */
#define NETWORK_DIAL 5 /* dial a network interface */
#define DIVERT_ACTIVATE 16 /* diversion activate */
#define DIVERT_DEACTIVATE 17 /* diversion deactivate */
#define DIVERT_REPORT 18 /* interrogation result */
#define DEFLECT_AUTODEL 255 /* only for internal use */
#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */
@ -83,6 +61,7 @@ typedef struct
2 = report call, send proceed, wait max waittime secs
3 = report call, alert and deflect after waittime
4 = report call, reject immediately
5 = dial net interface specified in to_nr
actions 1-2 only take place if interface is opened
*/
u_char waittime; /* maximum wait time for proceeding */

View File

@ -0,0 +1,140 @@
/*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/config.h>
#include <linux/init.h>
#include <linux/fs.h>
#undef N_DATA
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include "adapter.h"
#include "uxio.h"
#include <linux/isdn_compat.h>
MODULE_DESCRIPTION("ISDN4Linux: Driver for Eicon Diva Server cards");
MODULE_AUTHOR("Armin Schindler");
MODULE_LICENSE("GPL");
#ifdef MODULE
#include "idi.h"
void DIVA_DIDD_Write(DESCRIPTOR *, int);
EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Read);
EXPORT_SYMBOL_NOVERS(DIVA_DIDD_Write);
EXPORT_SYMBOL_NOVERS(DivasPrintf);
#endif
int DivasCardsDiscover(void);
static int __init
divas_init(void)
{
printk(KERN_DEBUG "DIVA Server Driver - initialising\n");
printk(KERN_DEBUG "DIVA Server Driver - Version 2.0.16\n");
#if !defined(CONFIG_PCI)
printk(KERN_WARNING "CONFIG_PCI is not defined!\n");
return -ENODEV;
#endif
if (pci_present())
{
if (DivasCardsDiscover() < 0)
{
printk(KERN_WARNING "Divas: Not loaded\n");
return -ENODEV;
}
}
else
{
printk(KERN_WARNING "Divas: No PCI bus present\n");
return -ENODEV;
}
return 0;
}
static void __exit
divas_exit(void)
{
card_t *pCard;
word wCardIndex;
extern int Divas_major;
printk(KERN_DEBUG "DIVA Server Driver - unloading\n");
pCard = DivasCards;
for (wCardIndex = 0; wCardIndex < MAX_CARDS; wCardIndex++)
{
if ((pCard->hw) && (pCard->hw->in_use))
{
(*pCard->card_reset)(pCard);
UxIsrRemove(pCard->hw, pCard);
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
if(pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
{
release_region(pCard->hw->io_base,0x20);
release_region(pCard->hw->reset_base,0x80);
}
// If this is a 4BRI ...
if (pCard->hw->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
{
// Skip over the next 3 virtual adapters
wCardIndex += 3;
// But free their handles
pCard++;
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
pCard++;
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
pCard++;
UxCardHandleFree(pCard->hw);
if(pCard->e_tbl != NULL)
{
kfree(pCard->e_tbl);
}
}
}
pCard++;
}
unregister_chrdev(Divas_major, "Divas");
}
module_init(divas_init);
module_exit(divas_exit);

View File

@ -1,13 +1,42 @@
L_OBJS :=
M_OBJS :=
O_OBJS := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o eicon_io.o
# Makefile for the eicon ISDN device driver
# The target object and module list name.
O_TARGET := vmlinux-obj.o
# Objects that export symbols.
export-objs := Divas_mod.o eicon_mod.o
# Multipart objects.
list-multi := eicon.o divas.o
eicon-objs := eicon_mod.o eicon_isa.o eicon_pci.o eicon_idi.o \
eicon_io.o
divas-objs := common.o idi.o bri.o pri.o log.o xlog.o kprintf.o fpga.o \
fourbri.o lincfg.o linchr.o linsys.o linio.o Divas_mod.o
# Optional parts of multipart objects.
eicon-objs-$(CONFIG_ISDN_DRV_EICON_PCI) += common.o idi.o bri.o pri.o log.o \
xlog.o kprintf.o fpga.o fourbri.o lincfg.o linchr.o \
linsys.o linio.o
eicon-objs += $(eicon-objs-y)
# Each configuration option enables a list of files.
obj-$(CONFIG_ISDN_DRV_EICON_OLD) += eicon.o
obj-$(CONFIG_ISDN_DRV_EICON_DIVAS) += divas.o
include $(TOPDIR)/drivers/isdn/Rules.make
# Link rules for multi-part drivers.
eicon.o: $(eicon-objs)
$(LD) -r -o $@ $(eicon-objs)
divas.o: $(divas-objs)
$(LD) -r -o $@ $(divas-objs)
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

View File

@ -0,0 +1,248 @@
/*
* Main internal include file for Diva Server driver
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.7
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(ADAPTER_H)
#define ADAPTER_H
#include "sys.h"
#include "idi.h"
#include "divas.h"
#undef ID_MASK
#include "pc.h"
#define XMOREC 0x1f
#define XMOREF 0x20
#define XBUSY 0x40
#define RMORE 0x80
/* structure for all information we have to keep on a per */
/* adapater basis */
typedef struct adapter_s ADAPTER;
struct adapter_s {
void * io;
byte IdTable[256];
byte ReadyInt;
byte (* ram_in)(ADAPTER * a, void * adr);
word (* ram_inw)(ADAPTER * a, void * adr);
void (* ram_in_buffer)(ADAPTER * a, void * adr, void * P, word length);
void (* ram_look_ahead)(ADAPTER * a, PBUFFER * RBuffer, ENTITY * e);
void (* ram_out)(ADAPTER * a, void * adr, byte data);
void (* ram_outw)(ADAPTER * a, void * adr, word data);
void (* ram_out_buffer)(ADAPTER * a, void * adr, void * P, word length);
void (* ram_inc)(ADAPTER * a, void * adr);
};
typedef struct card card_t;
typedef int card_load_fn_t(card_t *card, dia_load_t *load);
typedef int card_config_fn_t(card_t *card, dia_config_t *config);
typedef int card_start_fn_t(card_t *card, byte *channels);
typedef int card_reset_fn_t(card_t *card);
typedef int card_mem_get_fn_t(card_t *card, mem_block_t *mem_block);
#define MAX_PENTITIES 256 /* Number of entities primary adapter */
#define MAX_ENTITIES 16 /* Number of entities standard adapter */
typedef struct e_info_s E_INFO;
struct e_info_s
{
ENTITY *e; /* entity pointer */
byte next; /* chaining index */
word assign_ref; /* assign reference */
};
/* DIVA card info (details hidden from user) */
typedef struct ux_diva_card_s ux_diva_card_t;
/* card info */
struct card
{
ADAPTER a; /* per-adapter information */
dia_card_t cfg; /* card configuration */
int state; /* State of the adapter */
dword serial_no; /* serial number */
int test_int_pend; /* set for interrupt testing */
ux_diva_card_t *hw; /* O/S-specific handle */
card_reset_fn_t *card_reset; /* call this to reset card */
card_load_fn_t *card_load; /* call this to load card */
card_config_fn_t *card_config; /* call this to config card */
card_start_fn_t *card_start; /* call this to start card */
card_mem_get_fn_t *card_mem_get; /* call this to get card memory */
E_INFO *e_tbl; /* table of ENTITY pointers */
byte e_head; /* list of active ENTITIES */
byte e_tail; /* list of active ENTITIES */
int e_count; /* # of active ENTITIES */
int e_max; /* total # of ENTITIES */
byte assign; /* assign queue entry */
PBUFFER RBuffer; /* Copy of receive lookahead buffer */
int log_types; /* bit-mask of active logs */
word xlog_offset; /* offset to XLOG buffer on card */
void (*out)(ADAPTER *a);
byte (*dpc)(ADAPTER * a);
byte (*test_int)(ADAPTER * a);
void (*clear_int)(ADAPTER * a);
void (*reset_int)(card_t *c);
int is_live;
int (*card_isr)(card_t *card);
int int_pend; /* interrupt pending */
long interrupt_reentered;
long dpc_reentered;
int set_xlog_request;
} ;
/* card information */
#define MAX_CARDS 20 /* max number of cards on a system */
extern
card_t DivasCards[];
extern
int DivasCardNext;
extern
dia_config_t DivasCardConfigs[];
extern
byte DivasFlavourConfig[];
/*------------------------------------------------------------------*/
/* public functions of IDI common code */
/*------------------------------------------------------------------*/
void DivasOut(ADAPTER * a);
byte DivasDpc(ADAPTER * a);
byte DivasTestInt(ADAPTER * a);
void DivasClearInt(ADAPTER * a);
/*------------------------------------------------------------------*/
/* public functions of configuration platform-specific code */
/*------------------------------------------------------------------*/
int DivasConfigGet(dia_card_t *card);
/*------------------------------------------------------------------*/
/* public functions of LOG related code */
/*------------------------------------------------------------------*/
void DivasXlogReq(int card_num);
int DivasXlogRetrieve(card_t *card);
void DivasLog(dia_log_t *log);
void DivasLogIdi(card_t *card, ENTITY *e, int request);
/*------------------------------------------------------------------*/
/* public functions to initialise cards for each type supported */
/*------------------------------------------------------------------*/
int DivasPriInit(card_t *card, dia_card_t *cfg);
int DivasBriInit(card_t *card, dia_card_t *cfg);
int Divas4BriInit(card_t *card, dia_card_t *cfg);
void DivasBriPatch(card_t *card);
/*------------------------------------------------------------------*/
/* public functions of log common code */
/*------------------------------------------------------------------*/
extern char *DivasLogFifoRead(void);
extern void DivasLogFifoWrite(char *entry, int length);
extern int DivasLogFifoEmpty(void);
extern int DivasLogFifoFull(void);
extern void DivasLogAdd(void *buffer, int length);
/*------------------------------------------------------------------*/
/* public functions of misc. platform-specific code */
/*------------------------------------------------------------------*/
int DivasDpcSchedule(void);
void DivasDoDpc(void *);
void DivasDoRequestDpc(void *pData);
int DivasScheduleRequestDpc(void);
/* table of IDI request functions */
extern
IDI_CALL DivasIdiRequest[];
/*
* intialisation entry point
*/
int DivasInit(void);
/*
* Get information on the number and type of cards present
*/
extern
int DivasCardsDiscover(void);
/*
* initialise a new card
*/
int DivasCardNew(dia_card_t *card);
/*
* configure specified card
*/
int DivasCardConfig(dia_config_t *config);
/*
* load specified binary code onto card
*/
int DivasCardLoad(dia_load_t *load);
/*
* start specified card running
*/
int DivasCardStart(int card_id);
/*
* ISR for card
* Returns 0 if specified card was interrupting
*/
int DivasIsr(void *arg);
/*
* Get number of active cards
*/
int DivasGetNum(void);
/*
* Get list of active cards
*/
int DivasGetList(dia_card_list_t *card_list);
/* definitions common to several card types */
#define DIVAS_SHARED_OFFSET (0x1000)
#endif /* ADAPTER_H */

697
drivers/isdn/eicon/bri.c Normal file
View File

@ -0,0 +1,697 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.8
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "eicon.h"
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "adapter.h"
#include "uxio.h"
#define PCI_BADDR0 0x10
#define PCI_BADDR1 0x14
#define PCI_BADDR2 0x18
#define DIVAS_SIGNATURE 0x4447
/* offset to start of MAINT area (used by xlog) */
#define DIVAS_MAINT_OFFSET 0xff00 /* value for BRI card */
#define PROTCAP_TELINDUS 0x1
#define PROTCAP_V90D 0x8
word GetProtFeatureValue(char *sw_id);
byte io_in(ADAPTER *a, void *adr);
word io_inw(ADAPTER *a, void *adr);
void io_in_buffer(ADAPTER *a, void *adr, void *P, word length);
void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
void io_out(ADAPTER *a, void *adr, byte data);
void io_outw(ADAPTER *a, void *adr, word data);
void io_out_buffer(ADAPTER *a, void *adr, void *P, word length);
void io_inc(ADAPTER *a, void *adr);
static int diva_server_bri_test_int(card_t *card);
static int bri_ISR (card_t* card);
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
#define REG_DATA 0x00
#define REG_ADDRLO 0x04
#define REG_ADDRHI 0x0C
#define REG_IOCTRL 0x10
#define M_PCI_RESET 0x10
byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
int DivasBRIInitPCI(card_t *card, dia_card_t *cfg);
static
int diva_server_bri_reset(card_t *card)
{
byte *DivasIOBase;
word i;
dword dwWait;
UxCardLog(0);
DPRINTF(("divas: resetting BRI adapter"));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0);
for (i=0; i < 50000; i++)
;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x0000);
for (i=0; i<0x8000; i++)
{
UxCardPortIoOutW(card->hw, DivasIOBase, REG_DATA , 0);
}
for (dwWait=0; dwWait < 0x00FFFFFF; dwWait++)
;
UxCardMemDetach(card->hw, DivasIOBase);
return 0;
}
static
void diva_server_bri_reset_int(card_t *card)
{
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
static
int diva_server_bri_start(card_t *card, byte *channels)
{
byte *DivasIOBase, *PLXIOBase;
word wSig = 0;
word i;
dword dwSerialNum;
byte bPLX9060 = FALSE;
DPRINTF(("divas: starting Diva Server BRI card"));
card->is_live = FALSE;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA , 0);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x08);
/* wait for signature to indicate card has started */
for (i = 0; i < 300; i++)
{
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x1E);
wSig = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
if (wSig == DIVAS_SIGNATURE)
{
DPRINTF(("divas: card started after %d ms", i * 10));
break;
}
UxPause(10);
}
if (wSig != DIVAS_SIGNATURE)
{
DPRINTF(("divas: card failed to start (Sig=0x%x)", wSig));
UxCardMemDetach(card->hw, DivasIOBase);
return -1;
}
card->is_live = TRUE;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 0x3F6);
*channels = UxCardPortIoInW(card->hw, DivasIOBase, REG_DATA);
UxCardMemDetach(card->hw, DivasIOBase);
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) | UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
if (bPLX9060)
{
dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x1E) << 16) |
(UxCardPortIoInW(card->hw, PLXIOBase, 0x22));
DPRINTF(("divas: PLX9060 in use. Serial number 0x%04X", dwSerialNum));
}
else
{
dwSerialNum = (UxCardPortIoInW(card->hw, PLXIOBase, 0x22) << 16) |
(UxCardPortIoInW(card->hw, PLXIOBase, 0x26));
DPRINTF(("divas: PLX9050 in use. Serial number 0x%04X", dwSerialNum));
}
UxCardMemDetach(card->hw, PLXIOBase);
card->serial_no = dwSerialNum;
diva_server_bri_test_int(card);
return 0;
}
static
int diva_server_bri_load(card_t *card, dia_load_t *load)
{
byte *DivasIOBase;
dword r3000_base;
dword dwAddr, dwLength, i;
word wTest, aWord;
DPRINTF(("divas: loading Diva Server BRI card"));
switch (load->code_type)
{
case DIA_CPU_CODE:
DPRINTF(("divas: loading RISC %s", &load->code[0x80]));
card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
DPRINTF(("divas: features 0x%x", card->hw->features));
if (card->hw->features == 0xFFFF)
{
DPRINTF(("divas: invalid feature string failed load\n"));
return -1;
}
r3000_base = 0;
break;
case DIA_DSP_CODE:
DPRINTF(("divas: DSP code \"%s\"", load->code));
if ((card->hw->features) && (!(card->hw->features & PROTCAP_TELINDUS)))
{
DPRINTF(("divas: only Telindus style binaries supported"));
return -1;
}
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
DPRINTF(("divas: V.90 DSP binary"));
r3000_base = (0xBF790000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
}
else
{
DPRINTF(("divas: non-V.90 DSP binary"));
r3000_base = (0xBF7A0000 + (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC));
}
DPRINTF(("divas: loading at 0x%x", r3000_base));
break;
case DIA_TABLE_CODE:
DPRINTF(("divas: TABLE code"));
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
r3000_base = 0xBF790000 + sizeof(dword);
}
else
{
r3000_base = 0xBF7A0000 + sizeof(dword);
}
break;
case DIA_DLOAD_CNT:
DPRINTF(("divas: COUNT code"));
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
r3000_base = 0xBF790000;
}
else
{
r3000_base = 0xBF7A0000;
}
break;
default:
DPRINTF(("divas: unknown code type %d", load->code_type));
return -1;
break;
}
DPRINTF(("divas: Writing %d bytes to adapter, address 0x%x", load->length, r3000_base));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
DPRINTF(("divas: Attached to 0x%04X", DivasIOBase));
dwLength = load->length;
for (i=0; i < dwLength; i++)
{
dwAddr = r3000_base + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, load->code[i]);
}
DPRINTF(("divas: Verifying"));
for (i=0; i<dwLength; i++)
{
dwAddr = r3000_base + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, dwAddr >> 16);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, dwAddr);
wTest = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
aWord = load->code[i];
if (wTest != aWord)
{
DPRINTF(("divas: load verify failed on byte %d", i));
DPRINTF(("divas: RAM 0x%x File 0x%x",wTest,aWord));
UxCardMemDetach(card->hw, DivasIOBase);
return -1;
}
}
DPRINTF(("divas: Loaded and verified. Detaching from adapter"));
UxCardMemDetach(card->hw, DivasIOBase);
UxCardLog(0);
return 0;
}
static
int diva_server_bri_config(card_t *card, dia_config_t *config)
{
byte *DivasIOBase, i;
DPRINTF(("divas: configuring Diva Server BRI card"));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 8);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->tei);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 9);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->nt2);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 10);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->sig_flags);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 11);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->watchdog);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 12);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->permanent);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 13);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 14);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->stable_l2);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 15);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->no_order_check);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 16);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 17);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 18);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->low_channel);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 19);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->prot_version);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 20);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->crc4);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 21);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
DPRINTF(("divas: Signifying V.90"));
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 4);
}
else
{
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 22);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 0);
}
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 23);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, card->serial_no & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 24);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 8) & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 25);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, (card->serial_no >> 16) & 0xFF);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 26);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, 21);
for (i=0; i<32; i++)
{
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 32+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].oad[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 64+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].osa[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 96+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[0].spid[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 128+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].oad[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 160+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].osa[i]);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, 192+i);
UxCardPortIoOut(card->hw, DivasIOBase, REG_DATA, config->terminal[1].spid[i]);
}
UxCardMemDetach(card->hw, DivasIOBase);
return 0;
}
void DivasBriPatch(card_t *card)
{
dword PLXIOBase = 0;
dword DivasIOBase = 0;
PLXIOBase = card->cfg.reset_base;
DivasIOBase = card->cfg.io_base;
if(card->hw == NULL)
{
DPRINTF(("Divas: BRI PATCH (PLX chip) card->hw is null"));
return;
}
if (PLXIOBase == 0)
{
DPRINTF(("Divas: BRI (PLX chip) cannot be patched. The BRI adapter may"));
DPRINTF(("Divas: not function properly. If you do encounter problems,"));
DPRINTF(("Divas: ensure that your machine is using the latest BIOS."));
return;
}
DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
if (PLXIOBase & 0x80)
{
dword dwSize, dwSerialNum, dwCmd;
boolean_t bPLX9060;
word wSerHi, wSerLo;
DPRINTF(("Divas: Patch required"));
dwCmd = 0;
UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
PLXIOBase &= ~0x80;
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &PLXIOBase);
dwSize = 0xFFFFFFFF;
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &dwSize);
UxPciConfigRead(card->hw, 4, PCI_BADDR1, &dwSize);
dwSize = (~ (dwSize & ~7)) + 1;
DivasIOBase = PLXIOBase + dwSize;
card->cfg.reset_base = PLXIOBase;
card->cfg.io_base = DivasIOBase;
UxPciConfigWrite(card->hw, 4, PCI_BADDR1, &card->cfg.reset_base);
UxPciConfigWrite(card->hw, 4, PCI_BADDR2, &card->cfg.io_base);
dwCmd = 5;
UxPciConfigWrite(card->hw, 4, PCI_COMMAND, &dwCmd);
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) |
UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
if (bPLX9060)
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
dwSerialNum = (wSerHi << 16) | wSerLo;
UxCardLog(0);
}
else
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
dwSerialNum = (wSerHi << 16) | wSerLo;
UxCardLog(0);
}
}
else
{
word wSerHi, wSerLo;
boolean_t bPLX9060;
dword dwSerialNum;
DPRINTF(("divas: No patch required"));
bPLX9060 = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6C) |
UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x6E);
if (bPLX9060)
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x1E);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
dwSerialNum = (wSerHi << 16) | wSerLo;
}
else
{
wSerHi = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x22);
wSerLo = UxCardPortIoInW(card->hw, (void *) card->cfg.reset_base, 0x26);
dwSerialNum = (wSerHi << 16) | wSerLo;
}
}
DPRINTF(("Divas: After patching:"));
DPRINTF(("Divas: PLX I/O Base 0x%x", PLXIOBase));
DPRINTF(("Divas: Divas I/O Base 0x%x", DivasIOBase));
}
#define TEST_INT_DIVAS_BRI 0x12
static
int diva_server_bri_test_int(card_t *card)
{
boolean_t bPLX9060 = FALSE;
byte *PLXIOBase = NULL, *DivasIOBase = NULL;
DPRINTF(("divas: test interrupt for Diva Server BRI card"));
PLXIOBase = UxCardMemAttach(card->hw, PLX_IOBASE);
bPLX9060 = UxCardPortIoInW(card->hw, PLXIOBase, 0x6C) || UxCardPortIoInW(card->hw, PLXIOBase, 0x6E);
if (bPLX9060)
{ /* PLX9060 */
UxCardPortIoOut(card->hw, PLXIOBase, 0x69, 0x09);
}
else
{ /* PLX9050 */
UxCardPortIoOut(card->hw, PLXIOBase, 0x4C, 0x41);
}
card->test_int_pend = TEST_INT_DIVAS_BRI;
UxCardMemDetach(card->hw, PLXIOBase);
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardPortIoOut(card->hw, DivasIOBase, REG_IOCTRL, 0x89);
UxCardMemDetach(card->hw, DivasIOBase);
return 0;
}
static
int diva_server_bri_mem_get(card_t *card, mem_block_t *mem_block)
{
dword user_addr = mem_block->addr;
word length = 0;
dword addr;
word i;
byte *DivasIOBase;
DPRINTF(("divas: Retrieving memory from 0x%x", user_addr));
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
addr = user_addr;
for (i=0; i < (16 * 8); i++)
{
addr = user_addr + i;
UxCardPortIoOut(card->hw, DivasIOBase, REG_ADDRHI, addr >> 16);
UxCardPortIoOutW(card->hw, DivasIOBase, REG_ADDRLO, (word) addr);
mem_block->data[i] = UxCardPortIoIn(card->hw, DivasIOBase, REG_DATA);
length++;
}
UxCardMemDetach(card->hw, DivasIOBase);
return length;
}
int DivasBriInit(card_t *card, dia_card_t *cfg)
{
DPRINTF(("divas: initialise Diva Server BRI card"));
if (DivasBRIInitPCI(card, cfg) == -1)
{
return -1;
}
card->card_reset = diva_server_bri_reset;
card->card_start = diva_server_bri_start;
card->card_load = diva_server_bri_load;
card->card_config = diva_server_bri_config;
card->reset_int = diva_server_bri_reset_int;
card->card_mem_get = diva_server_bri_mem_get;
card->xlog_offset = DIVAS_MAINT_OFFSET;
card->out = DivasOut;
card->test_int = DivasTestInt;
card->dpc = DivasDpc;
card->clear_int = DivasClearInt;
card->card_isr = bri_ISR;
card->a.ram_out = io_out;
card->a.ram_outw = io_outw;
card->a.ram_out_buffer = io_out_buffer;
card->a.ram_inc = io_inc;
card->a.ram_in = io_in;
card->a.ram_inw = io_inw;
card->a.ram_in_buffer = io_in_buffer;
card->a.ram_look_ahead = io_look_ahead;
return 0;
}
word GetProtFeatureValue(char *sw_id)
{
word features = 0;
while ((*sw_id) && (sw_id[0] != '['))
sw_id++;
if (sw_id == NULL)
{
DPRINTF(("divas: no feature string present"));
features = -1;
}
else
{
byte i, shifter;
sw_id += 3;
for (i=0, shifter=12; i<4; i++, shifter-=4)
{
if ((sw_id[i] >= '0') && (sw_id[i] <= '9'))
{
features |= (sw_id[i] - '0') << shifter;
}
else if ((sw_id[i] >= 'a') && (sw_id[i] <= 'f'))
{
features |= (sw_id[i] - 'a' + 10) << shifter;
}
else if ((sw_id[i] >= 'A') && (sw_id[i] <= 'F'))
{
features |= (sw_id[i] - 'A' + 10) << shifter;
}
else
{
DPRINTF(("divas: invalid feature string"));
return -1;
}
}
}
return features;
}
int bri_ISR (card_t* card)
{
int served = 0;
byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01)
{
served = 1;
card->int_pend += 1;
DivasDpcSchedule(); /* ISR DPC */
UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
}
UxCardMemDetach(card->hw, DivasIOBase);
return (served != 0);
}

870
drivers/isdn/eicon/common.c Normal file
View File

@ -0,0 +1,870 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.15
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "eicon.h"
#include "sys.h"
#include "idi.h"
#include "constant.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "uxio.h"
#define DIVAS_LOAD_CMD 0x02
#define DIVAS_START_CMD 0x03
#define DIVAS_IRQ_RESET 0xC18
#define DIVAS_IRQ_RESET_VAL 0xFE
#define TEST_INT_DIVAS 0x11
#define TEST_INT_DIVAS_BRI 0x12
#define TEST_INT_DIVAS_Q 0x13
#define DIVAS_RESET 0x81
#define DIVAS_LED1 0x04
#define DIVAS_LED2 0x08
#define DIVAS_LED3 0x20
#define DIVAS_LED4 0x40
#define DIVAS_SIGNATURE 0x4447
#define MP_PROTOCOL_ADDR 0xA0011000
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
typedef struct {
dword cmd;
dword addr;
dword len;
dword err;
dword live;
dword reserved[(0x1020>>2)-6];
dword signature;
byte data[1];
} diva_server_boot_t;
int DivasCardNext;
card_t DivasCards[MAX_CARDS];
dia_config_t *DivasConfig(card_t *, dia_config_t *);
static
DESCRIPTOR DIDD_Table[32];
void DIVA_DIDD_Read( DESCRIPTOR *table, int tablelength )
{
memset(table, 0, tablelength);
if (tablelength > sizeof(DIDD_Table))
tablelength = sizeof(DIDD_Table);
if(tablelength % sizeof(DESCRIPTOR)) {
tablelength /= sizeof(DESCRIPTOR);
tablelength *= sizeof(DESCRIPTOR);
}
if (tablelength > 0)
memcpy((void *)table, (void *)DIDD_Table, tablelength);
return;
}
void DIVA_DIDD_Write(DESCRIPTOR *table, int tablelength)
{
if (tablelength > sizeof(DIDD_Table))
tablelength = sizeof(DIDD_Table);
memcpy((void *)DIDD_Table, (void *)table, tablelength);
return;
}
static
void init_idi_tab(void)
{
DESCRIPTOR d[32];
memset(d, 0, sizeof(d));
d[0].type = IDI_DIMAINT; /* identify the DIMAINT entry */
d[0].channels = 0; /* zero channels associated with dimaint*/
d[0].features = 0; /* no features associated with dimaint */
d[0].request = (IDI_CALL) DivasPrintf;
DIVA_DIDD_Write(d, sizeof(d));
return;
}
/*
* I/O routines for memory mapped cards
*/
byte mem_in(ADAPTER *a, void *adr)
{
card_t *card = a->io;
unsigned char *b, *m;
byte value;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemIn(card->hw, m);
UxCardMemDetach(card->hw, b);
return value;
}
word mem_inw(ADAPTER *a, void *adr)
{
card_t *card = a->io;
unsigned char *b, *m;
word value;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemInW(card->hw, m);
UxCardMemDetach(card->hw, b);
return value;
}
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemInBuffer(card->hw, m, P, length);
UxCardMemDetach(card->hw, b);
return;
}
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (dword) &RBuffer->length;
card->RBuffer.length = UxCardMemInW(card->hw, m);
m = b;
m += (dword) &RBuffer->P;
UxCardMemInBuffer(card->hw, m, card->RBuffer.P, card->RBuffer.length);
e->RBuffer = (DBUFFER *) &card->RBuffer;
UxCardMemDetach(card->hw, b);
return;
}
void mem_out(ADAPTER *a, void *adr, byte data)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOut(card->hw, m, data);
UxCardMemDetach(card->hw, b);
return;
}
void mem_outw(ADAPTER *a, void *adr, word data)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOutW(card->hw, m, data);
UxCardMemDetach(card->hw, b);
return;
}
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
UxCardMemOutBuffer(card->hw, m, P, length);
UxCardMemDetach(card->hw, b);
return;
}
void mem_inc(ADAPTER *a, void *adr)
{
word value;
card_t *card = a->io;
unsigned char *b, *m;
m = b = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
m += (unsigned int) adr;
value = UxCardMemInW(card->hw, m);
value++;
UxCardMemOutW(card->hw, m, value);
UxCardMemDetach(card->hw, b);
return;
}
/*
* I/O routines for I/O mapped cards
*/
byte io_in(ADAPTER *a, void *adr)
{
card_t *card = a->io;
byte value;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoIn(card->hw, DivasIOBase, adr);
UxCardMemDetach(card->hw, DivasIOBase);
return value;
}
word io_inw(ADAPTER *a, void *adr)
{
card_t *card = a->io;
word value;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoInW(card->hw, DivasIOBase, adr);
UxCardMemDetach(card->hw, DivasIOBase);
return value;
}
void io_in_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoInBuffer(card->hw, DivasIOBase, adr, P,length);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
card->RBuffer.length = UxCardIoInW(card->hw, DivasIOBase, (byte *) RBuffer);
UxCardIoInBuffer(card->hw, DivasIOBase, &RBuffer->P, card->RBuffer.P, card->RBuffer.length);
UxCardMemDetach(card->hw, DivasIOBase);
e->RBuffer = (DBUFFER *) &card->RBuffer;
return;
}
void io_out(ADAPTER *a, void *adr, byte data)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOut(card->hw, DivasIOBase, adr, data);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_outw(ADAPTER *a, void *adr, word data)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutW(card->hw, DivasIOBase, adr, data);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_out_buffer(ADAPTER *a, void *adr, void *P, word length)
{
card_t *card = a->io;
byte *DivasIOBase = NULL;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutBuffer(card->hw, DivasIOBase, adr, P, length);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
void io_inc(ADAPTER *a, void *adr)
{
word value;
card_t *card = a->io;
byte *DivasIOBase;
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
value = UxCardIoInW(card->hw, DivasIOBase, adr);
value++;
UxCardIoOutW(card->hw, DivasIOBase, adr, value);
UxCardMemDetach(card->hw, DivasIOBase);
return;
}
static
void test_int(card_t *card)
{
byte *shared, *DivasIOBase;
switch (card->test_int_pend)
{
case TEST_INT_DIVAS:
DPRINTF(("divas: test interrupt pending"));
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
if (UxCardMemIn(card->hw, &shared[0x3FE]))
{
UxCardMemOut(card->hw,
&(((struct pr_ram *)shared)->RcOutput), 0);
UxCardMemDetach(card->hw, shared);
(*card->reset_int)(card);
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
UxCardMemOut(card->hw, &shared[0x3FE], 0);
DPRINTF(("divas: test interrupt cleared"));
}
UxCardMemDetach(card->hw, shared);
card->test_int_pend = 0;
break;
case TEST_INT_DIVAS_BRI:
DPRINTF(("divas: BRI test interrupt pending"));
(*card->reset_int)(card);
DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
UxCardIoOutW(card->hw, DivasIOBase, (void *) 0x3FE, 0);
UxCardMemDetach(card->hw, DivasIOBase);
DPRINTF(("divas: test interrupt cleared"));
card->test_int_pend = 0;
break;
case TEST_INT_DIVAS_Q:
DPRINTF(("divas: 4BRI test interrupt pending"));
(*card->reset_int)(card);
card->test_int_pend = 0;
break;
default:
DPRINTF(("divas: unknown test interrupt pending"));
return;
}
return;
}
void card_isr (void *dev_id)
{
card_t *card = (card_t *) dev_id;
ADAPTER *a = &card->a;
int ipl;
if (card->test_int_pend)
{
ipl = UxCardLock(card->hw);
card->int_pend=0;
test_int(card);
UxCardUnlock(card->hw,ipl);
return;
}
if(card->card_isr)
{
(*(card->card_isr))(card);
}
else
{
ipl = UxCardLock(card->hw);
if ((card->test_int)(a))
{
(card->reset_int)(card);
}
UxCardUnlock(card->hw,ipl);
}
}
int DivasCardNew(dia_card_t *card_info)
{
card_t *card;
static boolean_t first_call = TRUE;
boolean_t NeedISRandReset = FALSE;
DPRINTF(("divas: new card "));
if (first_call)
{
first_call = FALSE;
init_idi_tab();
}
DivasConfigGet(card_info);
if (DivasCardNext == DIM(DivasCards))
{
KDPRINTF((KERN_WARNING "Divas: no space available for new card"));
return -1;
}
card = &DivasCards[DivasCardNext];
card->state = DIA_UNKNOWN;
card->cfg = *card_info;
card->a.io = card;
if (UxCardHandleGet(&card->hw, card_info))
{
KDPRINTF((KERN_WARNING "Divas: cannot get OS specific handle for card"));
return -1;
}
if (card_info->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
{
DivasBriPatch(card);
card_info->io_base = card->cfg.io_base;
}
switch (card_info->card_type)
{
case DIA_CARD_TYPE_DIVA_SERVER:
if (DivasPriInit(card, card_info))
{
return -1;
}
NeedISRandReset = TRUE;
break;
case DIA_CARD_TYPE_DIVA_SERVER_B:
if (DivasBriInit(card, card_info))
{
return -1;
}
NeedISRandReset = TRUE;
break;
case DIA_CARD_TYPE_DIVA_SERVER_Q:
if (Divas4BriInit(card, card_info))
{
return -1;
}
if (card_info->name[6] == '0')
{
NeedISRandReset = TRUE;
}
else // Need to set paramater for ISR anyway
{
card->hw->user_isr_arg = card;
card->hw->user_isr = card_isr;
}
break;
default:
KDPRINTF((KERN_WARNING "Divas: unsupported card type (%d)", card_info->card_type));
return -1;
}
if (NeedISRandReset)
{
if (UxIsrInstall(card->hw, card_isr, card))
{
KDPRINTF((KERN_WARNING "Divas: Install ISR failed (IRQ %d)", card->cfg.irq));
UxCardHandleFree(card->hw);
return -1;
}
if (card_info->card_type != DIA_CARD_TYPE_DIVA_SERVER_Q)
{
if ((*card->card_reset)(card))
{
KDPRINTF((KERN_WARNING "Divas: Adapter reset failed"));
return -1;
}
card->state = DIA_RESET;
}
NeedISRandReset = FALSE;
}
DivasCardNext++;
return 0;
}
void *get_card(int card_id)
{
int i;
for (i=0; i < DivasCardNext; i++)
{
if (DivasCards[i].cfg.card_id == card_id)
{
return(&DivasCards[i]);
}
}
DPRINTF(("divas: get_card() : no such card id (%d)", card_id));
return NULL;
}
int DivasCardConfig(dia_config_t *config)
{
card_t *card;
int status;
DPRINTF(("divas: configuring card"));
card = get_card(config->card_id);
if (!card)
{
return -1;
}
config = DivasConfig(card, config);
status = (*card->card_config)(card, config);
if (!status)
{
card->state = DIA_CONFIGURED;
}
return status;
}
int DivasCardLoad(dia_load_t *load)
{
card_t *card;
int status;
card = get_card(load->card_id);
if (!card)
{
return -1;
}
if (card->state == DIA_RUNNING)
{
(*card->card_reset)(card);
}
status = (*card->card_load)(card, load);
if (!status)
{
card->state = DIA_LOADED;
}
return status;
}
static int idi_register(card_t *card, byte channels)
{
DESCRIPTOR d[32];
int length, num_entities;
DPRINTF(("divas: registering card with IDI"));
num_entities = (channels > 2) ? MAX_PENTITIES : MAX_ENTITIES;
card->e_tbl = UxAlloc(sizeof(E_INFO) * num_entities);
if (!card->e_tbl)
{
KDPRINTF((KERN_WARNING "Divas: IDI register failed - no memory available"));
return -1;
}
memset(card->e_tbl, 0, sizeof(E_INFO) * num_entities);
card->e_max = num_entities;
DIVA_DIDD_Read(d, sizeof(d));
for(length=0; length < DIM(d); length++)
if (d[length].type == 0) break;
if (length >= DIM(d))
{
KDPRINTF((KERN_WARNING "Divas: IDI register failed - table full"));
return -1;
}
switch (card->cfg.card_type)
{
case DIA_CARD_TYPE_DIVA_SERVER:
d[length].type = IDI_ADAPTER_PR;
/* d[length].serial = card->serial_no; */
break;
case DIA_CARD_TYPE_DIVA_SERVER_B:
d[length].type = IDI_ADAPTER_MAESTRA;
/* d[length].serial = card->serial_no; */
break;
// 4BRI is treated as 4 BRI adapters
case DIA_CARD_TYPE_DIVA_SERVER_Q:
d[length].type = IDI_ADAPTER_MAESTRA;
/* d[length].serial = card->cfg.serial; */
}
d[length].features = 0;
d[length].features |= DI_FAX3|DI_MODEM|DI_POST|DI_V110|DI_V120;
if ( card->hw->features & PROTCAP_MANIF )
{
d[length].features |= DI_MANAGE ;
}
if ( card->hw->features & PROTCAP_V_42 )
{
d[length].features |= DI_V_42 ;
}
if ( card->hw->features & PROTCAP_EXTD_FAX )
{
d[length].features |= DI_EXTD_FAX ;
}
d[length].channels = channels;
d[length].request = DivasIdiRequest[card - DivasCards];
length++;
DIVA_DIDD_Write(d, sizeof(d));
return 0;
}
int DivasCardStart(int card_id)
{
card_t *card;
byte channels;
int status;
DPRINTF(("divas: starting card"));
card = get_card(card_id);
if (!card)
{
return -1;
}
status = (*card->card_start)(card, &channels);
if (status)
{
return status;
}
/* 4BRI == 4 x BRI so call idi_register 4 times each with 2 channels */
if (card->cfg.card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
{
int i;
card_t *FourBRISlave;
for (i=3; i >= 0; i--)
{
FourBRISlave = get_card(card_id - i); /* 0, 1, 2, 3 */
if (FourBRISlave)
{
idi_register(FourBRISlave, 2);
FourBRISlave->state = DIA_RUNNING;
}
}
card->serial_no = card->cfg.serial;
DPRINTF(("divas: card id %d (4BRI), serial no. 0x%x ready with %d channels",
card_id - 3, card->serial_no, (int) channels));
}
else
{
status = idi_register(card, channels);
if (!status)
{
card->state = DIA_RUNNING;
DPRINTF(("divas: card id %d, serial no. 0x%x ready with %d channels",
card_id, card->serial_no, (int) channels));
}
}
return status;
}
int DivasGetMem(mem_block_t *mem_block)
{
card_t *card;
word card_id = mem_block->card_id;
card = get_card(card_id);
if (!card)
{
return 0;
}
return (*card->card_mem_get)(card, mem_block);
}
/*
* Deleyed Procedure Call for handling interrupts from card
*/
void DivaDoCardDpc(card_t *card)
{
ADAPTER *a;
a = &card->a;
if(UxInterlockedIncrement(card->hw, &card->dpc_reentered) > 1)
{
return;
}
do{
if((*(card->test_int))(a))
{
(*(card->dpc))(a);
(*(card->clear_int))(a);
}
(*(card->out))(a);
}while(UxInterlockedDecrement(card->hw, &card->dpc_reentered));
}
void DivasDoDpc(void *pData)
{
card_t *card = DivasCards;
int i = DivasCardNext;
while(i--)
{
DivaDoCardDpc(card++);
}
}
void DivasDoRequestDpc(void *pData)
{
DivasDoDpc(pData);
}
/*
* DivasGetNum
* Returns the number of active adapters
*/
int DivasGetNum(void)
{
return(DivasCardNext);
}
/*
* DivasGetList
* Returns a list of active adapters
*/
int DivasGetList(dia_card_list_t *card_list)
{
int i;
memset(card_list, 0, sizeof(dia_card_list_t));
for(i = 0; i < DivasCardNext; i++)
{
card_list->card_type = DivasCards[i].cfg.card_type;
card_list->card_slot = DivasCards[i].cfg.slot;
card_list->state = DivasCards[i].state;
card_list++;
}
return 0;
}
/*
* control logging for specified card
*/
void DivasLog(dia_log_t *log)
{
card_t *card;
card = get_card(log->card_id);
if (!card)
{
return;
}
card->log_types = log->log_types;
return;
}

View File

@ -0,0 +1,161 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
/*------------------------------------------------------------------*/
/* Q.931 information elements maximum length */
/* excluding the identifier, including the length field */
/*------------------------------------------------------------------*/
#define MAX_LEN_BC 13
#define MAX_LEN_LLC 19 /* ctr3 */
#define MAX_LEN_HLC 6 /* ctr3 */
#define MAX_LEN_UUI 200 /* Hicom USBS req */
#define MAX_LEN_NUM 24
#define MAX_LEN_DSP 83 /* ctr3 */
#define MAX_LEN_NI 4
#define MAX_LEN_PI 5
#define MAX_LEN_SIN 3
#define MAX_LEN_CST 4
#define MAX_LEN_SIG 2
#define MAX_LEN_SPID 32
#define MAX_LEN_EID 3
#define MAX_LEN_CHI 35 /* ctr3 */
#define MAX_LEN_CAU 33
#define MAX_LEN_FTY 130
#define MAX_LEN_KEY 83 /* ctr3 */
#define MAX_LEN_RSI 4
#define MAX_LEN_CAI 11
#define MAX_NUM_SPID 4
#define MAX_LEN_USERID 9
#define MAX_LEN_APPLID 5
#define MAX_LEN_NTTCIF 15
/*------------------------------------------------------------------*/
/* decision return values */
/*------------------------------------------------------------------*/
#define YES 1
#define NO 0
/*-------------------------------------------------------------------*/
/* w element coding */
/*-------------------------------------------------------------------*/
#define NTTCIF 0x01
#define BC 0x04
#define CAU 0x08
#define CAD 0x0c
#define CAI 0x10
#define CST 0x14
#define CHI 0x18
#define LLI 0x19
#define CHA 0x1a
#define FTY 0x1c
#define PI 0x1e
#define NFAC 0x20
#define TC 0x24
#define ATT_EID 0x26
#define NI 0x27
#define DSP 0x28
#define DT 0x29
#define KEY 0x2c
#define KP 0x2c
#define UID 0x2d
#define SIG 0x34
#define FI 0x39
#define SPID 0x3a
#define EID 0x3b
#define DSPF 0x3c
#define ECAD 0x4c
#define OAD 0x6c
#define OSA 0x6d
#define DAD 0x70
#define CPN 0x70
#define DSA 0x71
#define RDX 0x73
#define RAD 0x74
#define RDN 0x74
#define RSI 0x79
#define SCR 0x7A /* internal unscreened CPN */
#define MIE 0x7a /* internal management info element */
#define LLC 0x7c
#define HLC 0x7d
#define UUI 0x7e
#define ESC 0x7f
#define SHIFT 0x90
#define MORE 0xa0
#define CL 0xb0
/* information elements used on the spid interface */
#define SPID_CMD 0xc0
#define SPID_LINK 0x10
#define SPID_DN 0x70
#define SPID_BC 0x04
#define SPID_SWITCH 0x11
/*------------------------------------------------------------------*/
/* global configuration parameters, defined in exec.c */
/* these parameters are configured with program loading */
/*------------------------------------------------------------------*/
#define PROT_1TR6 0
#define PROT_ETSI 1
#define PROT_FRANC 2
#define PROT_BELG 3
#define PROT_SWED 4
#define PROT_NI 5
#define PROT_5ESS 6
#define PROT_JAPAN 7
#define PROT_ATEL 8
#define PROT_US 9
#define PROT_ITALY 10
#define PROT_TWAN 11
#define PROT_AUSTRAL 12
#define INIT_PROT_1TR6 0x80|PROT_1TR6
#define INIT_PROT_ETSI 0x80|PROT_ETSI
#define INIT_PROT_FRANC 0x80|PROT_FRANC
#define INIT_PROT_BELG 0x80|PROT_BELG
#define INIT_PROT_SWED 0x80|PROT_SWED
#define INIT_PROT_NI 0x80|PROT_NI
#define INIT_PROT_5ESS 0x80|PROT_5ESS
#define INIT_PROT_JAPAN 0x80|PROT_JAPAN
#define INIT_PROT_ATEL 0x80|PROT_ATEL
#define INIT_PROT_ITALY 0x80|PROT_ITALY
#define INIT_PROT_TWAN 0x80|PROT_TWAN
#define INIT_PROT_AUSTRAL 0x80|PROT_AUSTRAL
/* -----------------------------------------------------------**
** The PROTOCOL_FEATURE_STRING in feature.h (included **
** in prstart.sx and astart.sx) 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 */

View File

@ -0,0 +1,38 @@
/*
* Include file for defining the kernel loggger messages
* These definitions are shared between the klog driver and the
* klogd daemon process
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(_KLOGMSG_H)
#define _KLOGMSG_H
/* define a type for a log entry */
#define KLOG_TEXT_MSG (0)
#define KLOG_XLOG_MSG (1)
#define KLOG_XTXT_MSG (2)
#define KLOG_IDI_REQ (4)
#define KLOG_IDI_CALLBACK (5)
#define KLOG_CAPI_MSG (6)
typedef struct
{
unsigned long time_stamp; /* in ms since last system boot */
int card; /* card number (-1 for all) */
unsigned int type; /* type of log message (0 is text) */
unsigned int length; /* message length (non-text messages only) */
unsigned short code; /* message code (non-text messages only) */
char buffer[110];/* text/data to log */
} klog_t;
void DivasLogAdd(void *buffer, int length);
#endif /* of _KLOGMSG_H */

215
drivers/isdn/eicon/divas.h Normal file
View File

@ -0,0 +1,215 @@
/*
* External Diva Server driver include file
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.5
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(DIVAS_H)
#define DIVAS_H
#include "sys.h"
/* IOCTL commands */
#define DIA_IOCTL_INIT (0)
#define DIA_IOCTL_LOAD (1)
#define DIA_IOCTL_CONFIG (2)
#define DIA_IOCTL_START (3)
#define DIA_IOCTL_GET_NUM (4)
#define DIA_IOCTL_GET_LIST (5)
#define DIA_IOCTL_LOG (6)
#define DIA_IOCTL_DETECT (7)
#define DIA_IOCTL_SPACE (8)
#define DIA_IOCTL_GET_MEM (9)
#define DIA_IOCTL_FLAVOUR (10)
#define DIA_IOCTL_XLOG_REQ (11)
/* Error codes */
#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)
/* Adapter states */
#define DIA_UNKNOWN (0)
#define DIA_RESET (1)
#define DIA_LOADED (2)
#define DIA_CONFIGURED (3)
#define DIA_RUNNING (4)
/* Stucture for getting card specific information from active cad driver */
typedef struct
{
int card_type;
int card_slot;
int state;
} dia_card_list_t;
/* use following to select which logging to have active */
#define DIVAS_LOG_DEBUG (1 << 0)
#define DIVAS_LOG_XLOG (1 << 1)
#define DIVAS_LOG_IDI (1 << 2)
#define DIVAS_LOG_CAPI (1 << 3)
/* stucture for DIA_IOCTL_LOG to get information from adapter */
typedef struct
{
int card_id;
int log_types; /* bit mask of log types: use DIVAS_LOG_XXX */
} dia_log_t;
/* list of cards supported by this driver */
#define DIA_CARD_TYPE_DIVA_SERVER (0) /* Diva Server PRI */
#define DIA_CARD_TYPE_DIVA_SERVER_B (1) /* Diva Server BRI */
#define DIA_CARD_TYPE_DIVA_SERVER_Q (2) /* Diva Server 4-BRI */
/* bus types */
#define DIA_BUS_TYPE_ISA (0)
#define DIA_BUS_TYPE_ISA_PNP (1)
#define DIA_BUS_TYPE_PCI (2)
#define DIA_BUS_TYPE_MCA (3)
/* types of memory used (index for memory array below) */
#define DIVAS_RAM_MEMORY 0
#define DIVAS_REG_MEMORY 1
#define DIVAS_CFG_MEMORY 2
#define DIVAS_SHARED_MEMORY 3
#define DIVAS_CTL_MEMORY 4
/*
* card config information
* passed as parameter to DIA_IOCTL_INIT ioctl to initialise new card
*/
typedef struct
{
int card_id; /* unique id assigned to this card */
int card_type; /* use DIA_CARD_TYPE_xxx above */
int bus_type; /* use DIA_BUS_TYPE_xxx above */
int bus_num; /* bus number (instance number of bus type) */
int func_num; /* adapter function number (PCI register) */
int slot; /* slot number in bus */
unsigned char irq; /* IRQ number */
int reset_base; /* Reset register for I/O mapped cards */
int io_base; /* I/O base for I/O mapped cards */
void *memory[5]; /* memory base addresses for memory mapped cards */
char name[9]; /* name of adapter */
int serial; /* serial number */
unsigned char int_priority; /* Interrupt priority */
} dia_card_t;
/*
* protocol configuration information
* passed as parameter to DIA_IOCTL_CONFIG ioctl to configure card
*/
typedef struct
{
int card_id; /* to identify particular card */
unsigned char tei;
unsigned char nt2;
unsigned char watchdog;
unsigned char permanent;
unsigned char x_interface;
unsigned char stable_l2;
unsigned char no_order_check;
unsigned char handset_type;
unsigned char sig_flags;
unsigned char low_channel;
unsigned char prot_version;
unsigned char crc4;
struct
{
unsigned char oad[32];
unsigned char osa[32];
unsigned char spid[32];
}terminal[2];
} dia_config_t;
/*
* code configuration
* passed as parameter to DIA_IOCTL_LOAD ioctl
* one of these ioctl per code file to load
*/
typedef struct
{
int card_id; /* card to load */
enum
{
DIA_CPU_CODE, /* CPU code */
DIA_DSP_CODE, /* DSP code */
DIA_CONT_CODE, /* continuation of code */
DIA_TABLE_CODE, /* code table */
DIA_DLOAD_CNT, /* number of downloads*/
DIA_FPGA_CODE
} code_type; /* code for CPU or DSP ? */
int length; /* length of code */
unsigned char *code; /* pointer (in user-space) to code */
} dia_load_t;
/*
* start configuration
* passed as parameter to DIA_IOCTL_START ioctl
*/
typedef struct
{
int card_id; /* card to start */
} dia_start_t;
/* used for retrieving memory from the card */
typedef struct {
word card_id;
dword addr;
byte data[16 * 8];
} mem_block_t;
/* DIVA Server specific addresses */
#define DIVAS_CPU_START_ADDR (0x0)
#define ORG_MAX_PROTOCOL_CODE_SIZE 0x000A0000
#define ORG_MAX_DSP_CODE_SIZE (0x000F0000 - ORG_MAX_PROTOCOL_CODE_SIZE)
#define ORG_DSP_CODE_BASE (0xBF7F0000 - ORG_MAX_DSP_CODE_SIZE)
#define DIVAS_DSP_START_ADDR (0xBF7A0000)
#define DIVAS_SHARED_OFFSET (0x1000)
#define MP_DSP_CODE_BASE 0xa03a0000
#define MQ_PROTCODE_OFFSET 0x100000
#define MQ_SM_OFFSET 0X0f0000
#define V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000
#define V90D_MAX_DSP_CODE_SIZE (0x000F0000 - V90D_MAX_PROTOCOL_CODE_SIZE)
#define V90D_DSP_CODE_BASE (0xBF7F0000 - V90D_MAX_DSP_CODE_SIZE)
#define MQ_ORG_MAX_PROTOCOL_CODE_SIZE 0x000a0000 /* max 640K Protocol-Code */
#define MQ_ORG_MAX_DSP_CODE_SIZE 0x00050000 /* max 320K DSP-Code */
#define MQ_ORG_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
- MQ_ORG_MAX_DSP_CODE_SIZE)
#define MQ_V90D_MAX_PROTOCOL_CODE_SIZE 0x00090000 /* max 576K Protocol-Code */
#define MQ_V90D_MAX_DSP_CODE_SIZE 0x00060000 /* max 384K DSP-Code if V.90D included */
#define MQ_MAX_DSP_DOWNLOAD_ADDR 0xa03f0000
#define MQ_V90D_DSP_CODE_BASE (MQ_MAX_DSP_DOWNLOAD_ADDR \
- MQ_V90D_MAX_DSP_CODE_SIZE)
#define ALIGNMENT_MASK_MAESTRA 0xfffffffc
#endif /* DIVAS_H */

View File

@ -0,0 +1,286 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef DSP_DEFS_H_
#define DSP_DEFS_H_
#ifndef DSPDIDS_H_
#include "dspdids.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------------------*/
#ifndef NULL
#define NULL 0
#endif
#ifndef TRUE
#define TRUE (0 == 0)
#endif
#ifndef FALSE
#define FALSE (0 != 0)
#endif
/*---------------------------------------------------------------------------*/
#define DSP_MEMORY_TYPE_EXTERNAL_DM 0
#define DSP_MEMORY_TYPE_EXTERNAL_PM 1
#define DSP_MEMORY_TYPE_INTERNAL_DM 2
#define DSP_MEMORY_TYPE_INTERNAL_PM 3
#define DSP_DOWNLOAD_FLAG_BOOTABLE 0x0001
#define DSP_DOWNLOAD_FLAG_2181 0x0002
#define DSP_DOWNLOAD_FLAG_TIMECRITICAL 0x0004
#define DSP_DOWNLOAD_FLAG_COMPAND 0x0008
#define DSP_MEMORY_BLOCK_COUNT 16
#define DSP_SEGMENT_PM_FLAG 0x0001
#define DSP_SEGMENT_SHARED_FLAG 0x0002
#define DSP_SEGMENT_EXTERNAL_DM DSP_MEMORY_TYPE_EXTERNAL_DM
#define DSP_SEGMENT_EXTERNAL_PM DSP_MEMORY_TYPE_EXTERNAL_PM
#define DSP_SEGMENT_INTERNAL_DM DSP_MEMORY_TYPE_INTERNAL_DM
#define DSP_SEGMENT_INTERNAL_PM DSP_MEMORY_TYPE_INTERNAL_PM
#define DSP_SEGMENT_FIRST_RELOCATABLE 4
#define DSP_DATA_BLOCK_PM_FLAG 0x0001
#define DSP_DATA_BLOCK_DWORD_FLAG 0x0002
#define DSP_DATA_BLOCK_RESOLVE_FLAG 0x0004
#define DSP_RELOC_NONE 0x00
#define DSP_RELOC_SEGMENT_MASK 0x3f
#define DSP_RELOC_TYPE_MASK 0xc0
#define DSP_RELOC_TYPE_0 0x00 /* relocation of address in DM word / high part of PM word */
#define DSP_RELOC_TYPE_1 0x40 /* relocation of address in low part of PM data word */
#define DSP_RELOC_TYPE_2 0x80 /* relocation of address in standard command */
#define DSP_RELOC_TYPE_3 0xc0 /* relocation of address in call/jump on flag in */
#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];
word format_version_bcd;
word header_size;
word combifile_description_size;
word directory_entries;
word directory_size;
word download_count;
word usage_mask_size;
} t_dsp_combifile_header;
typedef struct tag_dsp_combifile_directory_entry
{
word card_type_number;
word file_set_number;
} t_dsp_combifile_directory_entry;
typedef struct tag_dsp_file_header
{
char format_identification[DSP_FILE_FORMAT_IDENTIFICATION_SIZE];
word format_version_bcd;
word download_id;
word download_flags;
word required_processing_power;
word interface_channel_count;
word header_size;
word download_description_size;
word memory_block_table_size;
word memory_block_count;
word segment_table_size;
word segment_count;
word symbol_table_size;
word symbol_count;
word total_data_size_dm;
word data_block_count_dm;
word total_data_size_pm;
word data_block_count_pm;
} t_dsp_file_header;
typedef struct tag_dsp_memory_block_desc
{
word alias_memory_block;
word memory_type;
word address;
word size; /* DSP words */
} t_dsp_memory_block_desc;
typedef struct tag_dsp_segment_desc
{
word memory_block;
word attributes;
word base;
word size;
word alignment; /* ==0 -> no other legal start address than base */
} t_dsp_segment_desc;
typedef struct tag_dsp_symbol_desc
{
word symbol_id;
word segment;
word offset;
word size; /* DSP words */
} t_dsp_symbol_desc;
typedef struct tag_dsp_data_block_header
{
word attributes;
word segment;
word offset;
word size; /* DSP words */
} t_dsp_data_block_header;
typedef struct tag_dsp_download_desc /* be sure to keep native alignment for MAESTRA's */
{
word download_id;
word download_flags;
word required_processing_power;
word interface_channel_count;
word excess_header_size;
word memory_block_count;
word segment_count;
word symbol_count;
word data_block_count_dm;
word data_block_count_pm;
byte *p_excess_header_data;
char *p_download_description;
t_dsp_memory_block_desc *p_memory_block_table;
t_dsp_segment_desc *p_segment_table;
t_dsp_symbol_desc *p_symbol_table;
word *p_data_blocks_dm;
word *p_data_blocks_pm;
} t_dsp_download_desc;
#define DSP_DOWNLOAD_INDEX_KERNEL 0
#define DSP30TX_DOWNLOAD_INDEX_KERNEL 1
#define DSP30RX_DOWNLOAD_INDEX_KERNEL 2
#define DSP_MAX_DOWNLOAD_COUNT 35
#define DSP_DOWNLOAD_MAX_SEGMENTS 16
#define DSP_UDATA_REQUEST_RECONFIGURE 0
/*
parameters:
<word> reconfigure delay (in 8kHz samples)
<word> reconfigure code
<byte> 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
<byte> data 0
<byte> data 1
...
data indications if HDLC framer
<byte> data 0
<byte> data 1
...
<byte> CRC 0
<byte> CRC 1
<byte> preamble flags
*/
#define DSP_UDATA_INDICATION_SYNC 0
/*
returns:
<word> time of sync (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_OFF 1
/*
returns:
<word> time of DCD off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_ON 2
/*
returns:
<word> time of DCD on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s)
*/
#define DSP_UDATA_INDICATION_CTS_OFF 3
/*
returns:
<word> time of CTS off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_CTS_ON 4
/*
returns:
<word> time of CTS on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s)
*/
#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_TFAST 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
/*---------------------------------------------------------------------------*/
#ifdef __cplusplus
}
#endif
#endif
/*---------------------------------------------------------------------------*/

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef DSPDIDS_H_
#define DSPDIDS_H_
/*---------------------------------------------------------------------------*/
#define DSP_DID_INVALID 0
#define DSP_DID_DIVA 1
#define DSP_DID_DIVA_PRO 2
#define DSP_DID_DIVA_PRO_20 3
#define DSP_DID_DIVA_PRO_PCCARD 4
#define DSP_DID_DIVA_SERVER_BRI_1M 5
#define DSP_DID_DIVA_SERVER_BRI_2M 6
#define DSP_DID_DIVA_SERVER_PRI_2M_TX 7
#define DSP_DID_DIVA_SERVER_PRI_2M_RX 8
#define DSP_DID_DIVA_SERVER_PRI_30M 9
#define DSP_DID_TASK_HSCX 100
#define DSP_DID_TASK_HSCX_PRI_2M_TX 101
#define DSP_DID_TASK_HSCX_PRI_2M_RX 102
#define DSP_DID_TASK_V110KRNL 200
#define DSP_DID_OVERLAY_V1100 201
#define DSP_DID_OVERLAY_V1101 202
#define DSP_DID_OVERLAY_V1102 203
#define DSP_DID_OVERLAY_V1103 204
#define DSP_DID_OVERLAY_V1104 205
#define DSP_DID_OVERLAY_V1105 206
#define DSP_DID_OVERLAY_V1106 207
#define DSP_DID_OVERLAY_V1107 208
#define DSP_DID_OVERLAY_V1108 209
#define DSP_DID_OVERLAY_V1109 210
#define DSP_DID_TASK_V110_PRI_2M_TX 220
#define DSP_DID_TASK_V110_PRI_2M_RX 221
#define DSP_DID_TASK_MODEM 300
#define DSP_DID_TASK_FAX05 400
#define DSP_DID_TASK_VOICE 500
#define DSP_DID_TASK_TIKRNL81 600
#define DSP_DID_OVERLAY_DIAL 601
#define DSP_DID_OVERLAY_V22 602
#define DSP_DID_OVERLAY_V32 603
#define DSP_DID_OVERLAY_FSK 604
#define DSP_DID_OVERLAY_FAX 605
#define DSP_DID_OVERLAY_VXX 606
#define DSP_DID_OVERLAY_V8 607
#define DSP_DID_OVERLAY_INFO 608
#define DSP_DID_OVERLAY_V34 609
#define DSP_DID_OVERLAY_DFX 610
#define DSP_DID_PARTIAL_OVERLAY_DIAL 611
#define DSP_DID_PARTIAL_OVERLAY_FSK 612
#define DSP_DID_PARTIAL_OVERLAY_FAX 613
#define DSP_DID_TASK_TIKRNL05 700
/*---------------------------------------------------------------------------*/
#endif
/*---------------------------------------------------------------------------*/

View File

@ -2,103 +2,15 @@
*
* ISDN low-level module for Eicon active ISDN-Cards.
*
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1998 by Fritz Elfert (fritz@isdn4linux.de)
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef eicon_h
#define eicon_h
@ -120,6 +32,8 @@
#define EICON_IOCTL_TEST 98
#define EICON_IOCTL_DEBUGVAR 99
#define EICON_IOCTL_DIA_OFFSET 100
/* Bus types */
#define EICON_BUS_ISA 1
#define EICON_BUS_MCA 2
@ -181,39 +95,10 @@ typedef struct {
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 */
@ -224,6 +109,7 @@ typedef struct {
unsigned char data[700];
} eicon_manifbuf;
#define TRACE_OK (1)
#ifdef __KERNEL__
@ -241,7 +127,7 @@ typedef struct {
#include <asm/io.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/malloc.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/ioport.h>
@ -249,11 +135,11 @@ typedef struct {
#include <linux/wait.h>
#include <linux/delay.h>
#include <linux/ctype.h>
#include <linux/pci.h>
#include <linux/isdn.h>
#include <linux/isdnif.h>
#include <linux/isdn_compat.h>
typedef struct {
__u16 length __attribute__ ((packed)); /* length of data/parameter field */
@ -262,206 +148,34 @@ typedef struct {
#include "eicon_isa.h"
#include "idi.h"
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;
/* 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 */
@ -505,6 +219,7 @@ typedef struct {
unsigned short statectrl; /* State controling bits */
unsigned short eazmask; /* EAZ-Mask for this Channel */
int queued; /* User-Data Bytes in TX queue */
int pqueued; /* User-Data Packets 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 */
@ -515,7 +230,9 @@ typedef struct {
T30_s *fax; /* pointer to fax data in LL */
eicon_ch_fax_buf fax2; /* fax related struct */
#endif
entity e; /* Entity */
entity e; /* Native Entity */
ENTITY de; /* Divas D Entity */
ENTITY be; /* Divas B Entity */
char cpn[32]; /* remember cpn */
char oad[32]; /* remember oad */
char dsa[32]; /* remember dsa */
@ -539,8 +256,6 @@ typedef struct {
#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
@ -562,9 +277,6 @@ typedef struct {
#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;
@ -590,17 +302,12 @@ typedef struct {
__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 */
DESCRIPTOR *d; /* IDI Descriptor */
u_char ptype; /* Protocol type (1TR6 or Euro) */
u_char bus; /* Bustype (ISA, MCA, PCI) */
u_char type; /* Cardtype (EICON_CTYPE_...) */
@ -618,49 +325,23 @@ typedef struct eicon_card {
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;
DBUFFER *dbuf; /* Dbuffer for Diva Server */
BUFFERS *sbuf; /* Buffer for Diva Server */
char *sbufp; /* Data Buffer for Diva Server */
isdn_if interface; /* Interface to upper layer */
char regname[35]; /* Name used for request_region */
char regname[35]; /* Drivers card name */
#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;
@ -685,13 +366,11 @@ extern __inline__ void eicon_schedule_ack(eicon_card *card)
mark_bh(IMMEDIATE_BH);
}
extern char *eicon_find_eaz(eicon_card *, char);
extern int eicon_addcard(int, int, int, char *);
extern int eicon_addcard(int, int, int, char *, int);
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 *);
@ -702,6 +381,8 @@ extern ulong DebugVar;
extern void eicon_log(eicon_card * card, int level, const char *fmt, ...);
extern void eicon_putstatus(eicon_card * card, char * buf);
extern spinlock_t eicon_lock;
#endif /* __KERNEL__ */
#endif /* eicon_h */

View File

@ -1,90 +1,21 @@
/* $Id$
*
* ISDN lowlevel-module for Eicon active cards.
* DSP definitions
* 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef DSP_H
#define DSP_H
#define DSP_UDATA_REQUEST_RECONFIGURE 0
/*
parameters:
<word> reconfigure delay (in 8kHz samples)
<word> reconfigure code
<byte> reconfigure hdlc preamble flags
*/
#include "dsp_defs.h"
#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
<byte> data 0
<byte> data 1
...
data indications if HDLC framer
<byte> data 0
<byte> data 1
...
<byte> CRC 0
<byte> CRC 1
<byte> preamble flags
*/
#define DSP_UDATA_REQUEST_SWITCH_FRAMER 1
/*
@ -118,49 +49,6 @@ parameters:
- none -
*/
#define DSP_UDATA_INDICATION_SYNC 0
/*
returns:
<word> time of sync (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_OFF 1
/*
returns:
<word> time of DCD off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_DCD_ON 2
/*
returns:
<word> time of DCD on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s, max of tx and rx speed)
<word> roundtrip delay (ms)
<dword> connected speed tx (bit/s)
<dword> connected speed rx (bit/s)
*/
#define DSP_UDATA_INDICATION_CTS_OFF 3
/*
returns:
<word> time of CTS off (sampled from counter at 8kHz)
*/
#define DSP_UDATA_INDICATION_CTS_ON 4
/*
returns:
<word> time of CTS on (sampled from counter at 8kHz)
<byte> connected norm
<word> connected options
<dword> connected speed (bit/s, max of tx and rx speed)
<word> roundtrip delay (ms)
<dword> connected speed tx (bit/s)
<dword> connected speed rx (bit/s)
*/
typedef struct eicon_dsp_ind {
__u16 time __attribute__ ((packed));
__u8 norm __attribute__ ((packed));
@ -171,32 +59,11 @@ typedef struct eicon_dsp_ind {
__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:
@ -210,7 +77,6 @@ returns:
#define DSP_DISCONNECT_CAUSE_CLEARDOWN 0x04
#define DSP_DISCONNECT_CAUSE_TRAINING_TIMEOUT 0x05
#define DSP_UDATA_INDICATION_TX_CONFIRMATION 6
/*
returns:

View File

@ -1,7 +1,7 @@
/* $Id$
*
* ISDN lowlevel-module for Eicon active cards.
* IDI interface
* IDI interface
*
* Copyright 1998-2000 by Armin Schindler (mac@melware.de)
* Copyright 1999,2000 Cytronics & Melware (info@melware.de)
@ -11,136 +11,8 @@
* 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.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 <xfl23@dial.pipex.com>
*
* 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -149,6 +21,7 @@
#include "eicon.h"
#include "eicon_idi.h"
#include "eicon_dsp.h"
#include "uxio.h"
#undef EICON_FULL_SERVICE_OKTETT
@ -156,18 +29,6 @@ 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);
@ -197,7 +58,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
reqbuf->XBuffer.P[l++] = 0; /* end */
reqbuf->Req = ASSIGN;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 0;
reqbuf->ReqId = DSIG_ID;
reqbuf->XBuffer.length = l;
reqbuf->Reference = 0; /* Sig Entity */
}
@ -209,6 +70,9 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
reqbuf->XBuffer.P[l++] = LLC;
reqbuf->XBuffer.P[l++] = 2;
switch(chan->l2prot) {
case ISDN_PROTO_L2_V11096:
case ISDN_PROTO_L2_V11019:
case ISDN_PROTO_L2_V11038:
case ISDN_PROTO_L2_TRANS:
reqbuf->XBuffer.P[l++] = 2; /* transparent */
break;
@ -250,7 +114,7 @@ idi_assign_req(eicon_REQ *reqbuf, int signet, eicon_chan *chan)
reqbuf->XBuffer.P[l++] = 0; /* end */
reqbuf->Req = ASSIGN;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 0x20;
reqbuf->ReqId = NL_ID;
reqbuf->XBuffer.length = l;
reqbuf->Reference = 1; /* Net Entity */
}
@ -269,6 +133,21 @@ idi_put_req(eicon_REQ *reqbuf, int rq, int signet, int Ch)
return(0);
}
int
idi_put_suspend_req(eicon_REQ *reqbuf, eicon_chan *chan)
{
reqbuf->Req = SUSPEND;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 1;
reqbuf->XBuffer.P[0] = CAI;
reqbuf->XBuffer.P[1] = 1;
reqbuf->XBuffer.P[2] = chan->No;
reqbuf->XBuffer.P[3] = 0;
reqbuf->XBuffer.length = 4;
reqbuf->Reference = 0; /* Sig Entity */
return(0);
}
int
idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
{
@ -283,7 +162,7 @@ idi_call_res_req(eicon_REQ *reqbuf, eicon_chan *chan)
reqbuf->XBuffer.P[4] = 0;
reqbuf->XBuffer.P[5] = 0;
reqbuf->XBuffer.P[6] = 32;
reqbuf->XBuffer.P[7] = 3;
reqbuf->XBuffer.P[7] = 0;
switch(chan->l2prot) {
case ISDN_PROTO_L2_X75I:
case ISDN_PROTO_L2_X75UI:
@ -379,6 +258,12 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
case HANGUP:
idi_put_req(reqbuf, HANGUP, 0, 0);
break;
case SUSPEND:
idi_put_suspend_req(reqbuf, chan);
break;
case RESUME:
idi_put_req(reqbuf, RESUME, 0 ,0);
break;
case REJECT:
idi_put_req(reqbuf, REJECT, 0 ,0);
break;
@ -388,17 +273,20 @@ idi_do_req(eicon_card *card, eicon_chan *chan, int cmd, int layer)
case CALL_RES:
idi_call_res_req(reqbuf, chan);
break;
case IDI_N_CONNECT|0x700:
idi_put_req(reqbuf, IDI_N_CONNECT, 1, 0);
case CALL_HOLD:
idi_put_req(reqbuf, CALL_HOLD, 0, 0);
break;
case IDI_N_CONNECT_ACK|0x700:
idi_put_req(reqbuf, IDI_N_CONNECT_ACK, 1, 0);
case N_CONNECT|0x700:
idi_put_req(reqbuf, N_CONNECT, 1, 0);
break;
case IDI_N_DISC|0x700:
idi_put_req(reqbuf, IDI_N_DISC, 1, chan->e.IndCh);
case N_CONNECT_ACK|0x700:
idi_put_req(reqbuf, N_CONNECT_ACK, 1, 0);
break;
case IDI_N_DISC_ACK|0x700:
idi_put_req(reqbuf, IDI_N_DISC_ACK, 1, chan->e.IndCh);
case N_DISC|0x700:
idi_put_req(reqbuf, N_DISC, 1, chan->e.IndCh);
break;
case N_DISC_ACK|0x700:
idi_put_req(reqbuf, N_DISC_ACK, 1, chan->e.IndCh);
break;
default:
eicon_log(card, 1, "idi_req: Ch%d: Unknown request\n", chan->No);
@ -480,7 +368,7 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
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, N_DISC, 1);
}
if (chan->e.B2Id) idi_do_req(card, chan, REMOVE, 1);
if (chan->fsm_state != EICON_STATE_NULL) {
@ -495,6 +383,32 @@ idi_hangup(eicon_card *card, eicon_chan *chan)
return(0);
}
int
capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm)
{
if ((cm->para[0] != 3) || (cm->para[1] != 0))
return -1;
if (cm->para[2] < 3)
return -1;
if (cm->para[4] != 0)
return -1;
switch(cm->para[3]) {
case 4: /* Suspend */
eicon_log(card, 8, "idi_req: Ch%d: Call Suspend\n", chan->No);
if (cm->para[5]) {
idi_do_req(card, chan, SUSPEND, 0);
} else {
idi_do_req(card, chan, CALL_HOLD, 0);
}
break;
case 5: /* Resume */
eicon_log(card, 8, "idi_req: Ch%d: Call Resume\n", chan->No);
idi_do_req(card, chan, RESUME, 0);
break;
}
return 0;
}
int
idi_connect_res(eicon_card *card, eicon_chan *chan)
{
@ -600,7 +514,14 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
reqbuf->XBuffer.P[l++] = *sub++ & 0x7f;
}
if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
if (si2 > 2) {
reqbuf->XBuffer.P[l++] = SHIFT|6;
reqbuf->XBuffer.P[l++] = SIN;
reqbuf->XBuffer.P[l++] = 2;
reqbuf->XBuffer.P[l++] = si1;
reqbuf->XBuffer.P[l++] = si2;
}
else if ((tmp = idi_si2bc(si1, si2, bc, hlc)) > 0) {
reqbuf->XBuffer.P[l++] = BC;
reqbuf->XBuffer.P[l++] = tmp;
for(i=0; i<tmp;i++)
@ -620,7 +541,7 @@ idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
reqbuf->XBuffer.P[l++] = 0;
reqbuf->XBuffer.P[l++] = 0;
reqbuf->XBuffer.P[l++] = 32;
reqbuf->XBuffer.P[l++] = 3;
reqbuf->XBuffer.P[l++] = 0;
switch(chan->l2prot) {
case ISDN_PROTO_L2_X75I:
case ISDN_PROTO_L2_X75UI:
@ -847,7 +768,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
}
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],
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:
@ -857,7 +778,7 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
}
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,
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;
@ -1049,31 +970,55 @@ idi_IndParse(eicon_card *ccard, eicon_chan *chan, idi_ind_message *message, unsi
}
void
idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *si1, unsigned char *si2)
idi_bc2si(unsigned char *bc, unsigned char *hlc, unsigned char *sin, unsigned char *si1, unsigned char *si2)
{
si1[0] = 0;
si2[0] = 0;
if (memcmp(bc, BC_Speech, 3) == 0) { /* Speech */
si1[0] = 1;
si1[0] = 0;
si2[0] = 0;
switch (bc[0] & 0x7f) {
case 0x00: /* Speech */
si1[0] = 1;
#ifdef EICON_FULL_SERVICE_OKTETT
si2[0] = 1;
si1[0] = sin[0];
si2[0] = sin[1];
#endif
}
if (memcmp(bc, BC_31khz, 3) == 0) { /* 3.1kHz audio */
si1[0] = 1;
break;
case 0x10: /* 3.1 Khz 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;
si1[0] = sin[0];
si2[0] = sin[1];
#endif
break;
case 0x08: /* Unrestricted digital information */
si1[0] = 7;
si2[0] = sin[1];
break;
case 0x09: /* Restricted digital information */
si1[0] = 2;
break;
case 0x11:
/* Unrestr. digital information with
* tones/announcements ( or 7 kHz audio
*/
si1[0] = 3;
break;
case 0x18: /* Video */
si1[0] = 4;
break;
}
switch (bc[1] & 0x7f) {
case 0x40: /* packed mode */
si1[0] = 8;
break;
case 0x10: /* 64 kbit */
case 0x11: /* 2*64 kbit */
case 0x13: /* 384 kbit */
case 0x15: /* 1536 kbit */
case 0x17: /* 1920 kbit */
/* moderate = bc[1] & 0x7f; */
break;
}
#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 ***************************/
@ -1213,7 +1158,7 @@ idi_send_edata(eicon_card *card, eicon_chan *chan)
reqbuf = (eicon_REQ *)skb_put(skb, sizeof(eicon_t30_s) + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_EDATA;
reqbuf->Req = N_EDATA;
reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
@ -1347,7 +1292,7 @@ idi_fax_send_header(eicon_card *card, eicon_chan *chan, int header)
eicon_log(card, 128, "sSFF-Head: pagelength = %d\n", page->pagelength);
break;
}
idi_send_data(card, chan, 0, skb, 0);
idi_send_data(card, chan, 0, skb, 0, 0);
}
void
@ -1932,7 +1877,7 @@ idi_fax_send_outbuf(eicon_card *ccard, eicon_chan *chan, eicon_OBJBUFFER *OutBuf
OutBuf->Len = 0;
OutBuf->Next = OutBuf->Data;
return(idi_send_data(ccard, chan, 0, skb, 1));
return(idi_send_data(ccard, chan, 0, skb, 1, 0));
}
int
@ -1977,6 +1922,8 @@ idi_faxdata_send(eicon_card *ccard, eicon_chan *chan, struct sk_buff *skb)
if (chan->queued + skb->len > 1200)
return 0;
if (chan->pqueued > 1)
return 0;
InBuf.Data = skb->data;
InBuf.Size = skb->len;
@ -2202,6 +2149,7 @@ idi_fax_hangup(eicon_card *ccard, eicon_chan *chan)
}
if ((chan->fax->code > 1) && (chan->fax->code < 120))
chan->fax->code += 120;
eicon_log(ccard, 8, "idi_fax: Ch%d: Hangup (code=%d)\n", chan->No, chan->fax->code);
chan->fax->r_code = ISDN_TTY_FAX_HNG;
cmd.driver = ccard->myid;
cmd.command = ISDN_STAT_FAXIND;
@ -2243,7 +2191,7 @@ idi_send_udata(eicon_card *card, eicon_chan *chan, int UReq, u_char *buffer, int
reqbuf = (eicon_REQ *)skb_put(skb, 1 + len + sizeof(eicon_REQ));
reqbuf->Req = IDI_N_UDATA;
reqbuf->Req = N_UDATA;
reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
@ -2293,7 +2241,10 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int
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"};
"V.21 CH2", "V.27ter", "V.29", "V.33", "V.17", "V.32", "K56Flex",
"X2", "V.18", "V.18LH", "V.18HL", "V.21LH", "V.21HL",
"Bell 103LH", "Bell 103HL", "V.23", "V.23", "EDT 110",
"Baudot45", "Baudot47", "Baudot50", "DTMF" };
static u_char dtmf_code[] = {
'1','4','7','*','2','5','8','0','3','6','9','#','A','B','C','D'
};
@ -2315,7 +2266,11 @@ idi_parse_udata(eicon_card *ccard, eicon_chan *chan, unsigned char *buffer, int
cmd.driver = ccard->myid;
cmd.command = ISDN_STAT_BCONN;
cmd.arg = chan->No;
sprintf(cmd.parm.num, "%d/%s", p->speed, connmsg[p->norm]);
if (p->norm > 34) {
sprintf(cmd.parm.num, "%d/(%d)", p->speed, p->norm);
} else {
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);
@ -2437,12 +2392,12 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
while((skb2 = skb_dequeue(&chan->e.X))) {
dev_kfree_skb(skb2);
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
chan->queued = 0;
chan->pqueued = 0;
chan->waitq = 0;
chan->waitpq = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
if (message.e_cau[0] & 0x7f) {
cmd.driver = ccard->myid;
cmd.arg = chan->No;
@ -2452,10 +2407,6 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
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) &&
@ -2471,6 +2422,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
#endif
chan->statectrl &= ~WAITING_FOR_HANGUP;
chan->statectrl &= ~IN_HOLD;
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;
@ -2488,6 +2440,9 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
cmd.command = ISDN_STAT_DHUP;
ccard->interface.statcallb(&cmd);
eicon_idi_listen_req(ccard, chan);
#ifdef CONFIG_ISDN_TTY_FAX
chan->fax = 0;
#endif
}
}
break;
@ -2500,7 +2455,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
break;
}
chan->fsm_state = EICON_STATE_ICALL;
idi_bc2si(message.bc, message.hlc, &chan->si1, &chan->si2);
idi_bc2si(message.bc, message.hlc, message.sin, &chan->si1, &chan->si2);
strcpy(chan->cpn, message.cpn + 1);
strcpy(chan->oad, message.oad);
strcpy(chan->dsa, message.dsa);
@ -2548,15 +2503,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
break;
case 3: /* incomplete number */
eicon_log(ccard, 8, "idi_req: Ch%d: Incomplete Number\n", chan->No);
switch(ccard->type) {
case EICON_CTYPE_MAESTRAP:
case EICON_CTYPE_S2M:
/* TODO (other protocols) */
chan->fsm_state = EICON_STATE_ICALLW;
break;
default:
idi_do_req(ccard, chan, HANGUP, 0);
}
chan->fsm_state = EICON_STATE_ICALLW;
break;
}
break;
@ -2586,46 +2533,68 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
case ISDN_PROTO_L2_MODEM:
/* do nothing, wait for connect */
break;
case ISDN_PROTO_L2_V11096:
case ISDN_PROTO_L2_V11019:
case ISDN_PROTO_L2_V11038:
case ISDN_PROTO_L2_TRANS:
idi_do_req(ccard, chan, IDI_N_CONNECT, 1);
idi_do_req(ccard, chan, N_CONNECT, 1);
break;
default:
default:;
/* On most incoming calls we use automatic connect */
/* idi_do_req(ccard, chan, IDI_N_CONNECT, 1); */
/* idi_do_req(ccard, chan, N_CONNECT, 1); */
}
} else
idi_hangup(ccard, chan);
} else {
if (chan->fsm_state != EICON_STATE_ACTIVE)
idi_hangup(ccard, chan);
}
break;
case CALL_CON:
eicon_log(ccard, 8, "idi_ind: Ch%d: Call_Con\n", chan->No);
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)
if (chan->fax) {
chan->fax->phase = ISDN_FAX_PHASE_A;
} else {
eicon_log(ccard, 1, "idi_ind: Call_Con with NULL fax struct, ERROR\n");
idi_hangup(ccard, chan);
break;
}
}
#endif
chan->fsm_state = EICON_STATE_OBWAIT;
cmd.driver = ccard->myid;
cmd.command = ISDN_STAT_DCONN;
cmd.arg = chan->No;
ccard->interface.statcallb(&cmd);
idi_do_req(ccard, chan, ASSIGN, 1);
idi_do_req(ccard, chan, N_CONNECT, 1);
} else
idi_hangup(ccard, chan);
idi_hangup(ccard, chan);
break;
case AOC_IND:
eicon_log(ccard, 8, "idi_ind: Ch%d: Advice of Charge\n", chan->No);
break;
case CALL_HOLD_ACK:
chan->statectrl |= IN_HOLD;
eicon_log(ccard, 8, "idi_ind: Ch%d: Call Hold Ack\n", chan->No);
break;
case SUSPEND_REJ:
eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Rejected\n", chan->No);
break;
case SUSPEND:
eicon_log(ccard, 8, "idi_ind: Ch%d: Suspend Ack\n", chan->No);
break;
case RESUME:
eicon_log(ccard, 8, "idi_ind: Ch%d: Resume Ack\n", chan->No);
break;
default:
eicon_log(ccard, 8, "idi_ind: Ch%d: UNHANDLED SigIndication 0x%02x\n", chan->No, ind->Ind);
}
@ -2644,7 +2613,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
else
switch(ind->Ind) {
case IDI_N_CONNECT_ACK:
case 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;
@ -2665,7 +2634,7 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
}
else {
eicon_log(ccard, 1, "idi_ind: N_CONNECT_ACK with NULL fax struct, ERROR\n");
eicon_log(ccard, 1, "idi_ind: N_Connect_Ack with NULL fax struct, ERROR\n");
}
#endif
break;
@ -2677,10 +2646,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
strcpy(cmd.parm.num, "64000");
ccard->interface.statcallb(&cmd);
break;
case IDI_N_CONNECT:
case 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->e.B2Id) idi_do_req(ccard, chan, N_CONNECT_ACK, 1);
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
break;
}
@ -2695,43 +2664,47 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
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);
case 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, N_DISC_ACK, 1);
idi_do_req(ccard, chan, REMOVE, 1);
}
#ifdef CONFIG_ISDN_TTY_FAX
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
if ((chan->l2prot == ISDN_PROTO_L2_FAX) && (chan->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();
spin_lock_irqsave(&eicon_lock, flags);
chan->queued = 0;
chan->pqueued = 0;
chan->waitq = 0;
chan->waitpq = 0;
restore_flags(flags);
idi_do_req(ccard, chan, HANGUP, 0);
spin_unlock_irqrestore(&eicon_lock, flags);
if (!(chan->statectrl & IN_HOLD)) {
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;
if (!(chan->statectrl & IN_HOLD)) {
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);
case 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);
@ -2739,10 +2712,10 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
}
#endif
break;
case IDI_N_DATA_ACK:
eicon_log(ccard, 128, "idi_ind: Ch%d: N_DATA_ACK\n", chan->No);
case N_DATA_ACK:
eicon_log(ccard, 128, "idi_ind: Ch%d: N_Data_Ack\n", chan->No);
break;
case IDI_N_DATA:
case 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) {
@ -2754,11 +2727,11 @@ idi_handle_ind(eicon_card *ccard, struct sk_buff *skb)
free_buff = 0;
}
break;
case IDI_N_UDATA:
case N_UDATA:
idi_parse_udata(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
break;
#ifdef CONFIG_ISDN_TTY_FAX
case IDI_N_EDATA:
case N_EDATA:
idi_edata_action(ccard, chan, ind->RBuffer.P, ind->RBuffer.length);
break;
#endif
@ -2778,6 +2751,8 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
{
ulong flags;
isdn_ctrl cmd;
int tqueued = 0;
int twaitpq = 0;
if (ack->RcId != ((chan->e.ReqCh) ? chan->e.B2Id : chan->e.D3Id)) {
/* I dont know why this happens, should not ! */
@ -2801,16 +2776,15 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
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();
spin_lock_irqsave(&eicon_lock, flags);
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);
spin_unlock_irqrestore(&eicon_lock, flags);
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");
return 1;
}
@ -2821,25 +2795,21 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
} else {
/* Network layer */
switch(chan->e.Req & 0x0f) {
case IDI_N_CONNECT:
case 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();
case N_MDATA:
case N_DATA:
tqueued = chan->queued;
twaitpq = chan->waitpq;
if ((chan->e.Req & 0x0f) == N_DATA) {
spin_lock_irqsave(&eicon_lock, flags);
chan->waitpq = 0;
restore_flags(flags);
if(chan->pqueued)
chan->pqueued--;
spin_unlock_irqrestore(&eicon_lock, flags);
#ifdef CONFIG_ISDN_TTY_FAX
if (chan->l2prot == ISDN_PROTO_L2_FAX) {
if (((chan->queued - chan->waitq) < 1) &&
@ -2859,11 +2829,17 @@ idi_handle_ack_ok(eicon_card *ccard, eicon_chan *chan, eicon_RC *ack)
}
#endif
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
chan->queued -= chan->waitq;
if (chan->queued < 0) chan->queued = 0;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
if (((chan->e.Req & 0x0f) == N_DATA) && (tqueued)) {
cmd.driver = ccard->myid;
cmd.command = ISDN_STAT_BSENT;
cmd.arg = chan->No;
cmd.parm.length = twaitpq;
ccard->interface.statcallb(&cmd);
}
break;
default:
eicon_log(ccard, 16, "idi_ack: Ch%d: RC OK Id=%x Ch=%d (ref:%d)\n", chan->No,
@ -2889,11 +2865,10 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
return;
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if ((chan = ccard->IdTable[ack->RcId]) != NULL)
dCh = chan->No;
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
switch (ack->Rc) {
case OK_FC:
@ -2921,8 +2896,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
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();
spin_lock_irqsave(&eicon_lock, flags);
for(j = 0; j < ccard->nchannels + 1; j++) {
if ((ccard->bch[j].e.ref == ack->Reference) &&
(ccard->bch[j].e.Req == ASSIGN)) {
@ -2932,12 +2906,12 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
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);
}
spin_unlock_irqrestore(&eicon_lock, flags);
eicon_log(ccard, 16, "idi_ack: Ch%d: Id %x assigned (%s)\n", j,
ack->RcId, (ccard->bch[j].e.ReqCh)? "Net":"Sig");
if (j > ccard->nchannels) {
eicon_log(ccard, 24, "idi_ack: Ch??: ref %d not found for Id %d\n",
ack->Reference, ack->RcId);
@ -2948,6 +2922,7 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
case UNKNOWN_COMMAND:
case WRONG_COMMAND:
case WRONG_ID:
case ADAPTER_DEAD:
case WRONG_CH:
case UNKNOWN_IE:
case WRONG_IE:
@ -2980,19 +2955,18 @@ idi_handle_ack(eicon_card *ccard, struct sk_buff *skb)
ccard->interface.statcallb(&cmd);
}
}
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if (chan) {
chan->e.ref = 0;
chan->e.busy = 0;
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, 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)
idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk)
{
struct sk_buff *xmit_skb;
struct sk_buff *skb2;
@ -3016,13 +2990,14 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
return -1;
if (!len)
return 0;
if (chan->queued + len > EICON_MAX_QUEUE)
if ((chk) && (chan->pqueued > 1))
return 0;
eicon_log(card, 128, "idi_snd: Ch%d: %d bytes\n", chan->No, len);
eicon_log(card, 128, "idi_snd: Ch%d: %d bytes (Pqueue=%d)\n",
chan->No, len, chan->pqueued);
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
while(offset < len) {
plen = ((len - offset) > 270) ? 270 : len - offset;
@ -3031,7 +3006,7 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
skb2 = alloc_skb(sizeof(eicon_chan_ptr), GFP_ATOMIC);
if ((!xmit_skb) || (!skb2)) {
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, 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);
@ -3044,12 +3019,11 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
chan2->ptr = chan;
reqbuf = (eicon_REQ *)skb_put(xmit_skb, plen + sizeof(eicon_REQ));
if (((len - offset) > 270) &&
(chan->l2prot != ISDN_PROTO_L2_TRANS)) {
reqbuf->Req = IDI_N_MDATA;
if ((len - offset) > 270) {
reqbuf->Req = N_MDATA;
} else {
reqbuf->Req = IDI_N_DATA;
if (ack) reqbuf->Req |= N_D_BIT;
reqbuf->Req = N_DATA;
/* if (ack) reqbuf->Req |= N_D_BIT; */
}
reqbuf->ReqCh = chan->e.IndCh;
reqbuf->ReqId = 1;
@ -3062,9 +3036,11 @@ idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb,
offset += plen;
}
if (que)
if (que) {
chan->queued += len;
restore_flags(flags);
chan->pqueued++;
}
spin_unlock_irqrestore(&eicon_lock, flags);
eicon_schedule_tx(card);
dev_kfree_skb(skb);
return len;
@ -3102,7 +3078,7 @@ eicon_idi_manage_assign(eicon_card *card)
reqbuf->XBuffer.P[0] = 0;
reqbuf->Req = ASSIGN;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 0xe0;
reqbuf->ReqId = MAN_ID;
reqbuf->XBuffer.length = 1;
reqbuf->Reference = 2; /* Man Entity */
@ -3180,8 +3156,8 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
return(ret);
}
timeout = jiffies + 50;
while (timeout > jiffies) {
timeout = jiffies + HZ / 2;
while (time_before(jiffies, timeout)) {
if (chan->e.B2Id) break;
SLEEP(10);
}
@ -3228,7 +3204,7 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
reqbuf->XBuffer.P[1] = manbuf->length[0] + 1;
reqbuf->XBuffer.P[l++] = 0;
reqbuf->Req = (manbuf->count) ? manbuf->count : 0x02; /* Request */
reqbuf->Req = (manbuf->count) ? manbuf->count : MAN_READ;
reqbuf->ReqCh = 0;
reqbuf->ReqId = 1;
reqbuf->XBuffer.length = l;
@ -3242,8 +3218,8 @@ eicon_idi_manage(eicon_card *card, eicon_manifbuf *mb)
eicon_schedule_tx(card);
timeout = jiffies + 50;
while (timeout > jiffies) {
timeout = jiffies + HZ / 2;
while (time_before(jiffies, timeout)) {
if (chan->fsm_state) break;
SLEEP(10);
}

View File

@ -6,178 +6,32 @@
* 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef IDI_H
#define IDI_H
#ifndef E_IDI_H
#define E_IDI_H
#include <linux/config.h>
#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 */
#undef N_DATA
#undef ID_MASK
#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)
#include "pc.h"
#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 AOC_IND 26 /* Advice of Charge */
#define PI 0x1e /* Progress Indicator */
#define NI 0x27 /* Notification Indicator */
#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 */
/*------------------------------------------------------------------*/
#define CALL_HOLD 0x22
#define CALL_HOLD_ACK 0x24
/* defines for statectrl */
#define WAITING_FOR_HANGUP 0x01
#define HAVE_CONN_REQ 0x02
#define IN_HOLD 0x04
typedef struct {
char cpn[32];
@ -237,26 +91,6 @@ typedef struct {
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;
@ -274,8 +108,9 @@ extern int idi_connect_req(eicon_card *card, eicon_chan *chan, char *phone,
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 int idi_send_data(eicon_card *card, eicon_chan *chan, int ack, struct sk_buff *skb, int que, int chk);
extern void idi_audio_cmd(eicon_card *ccard, eicon_chan *chan, int cmd, u_char *value);
extern int capipmsg(eicon_card *card, eicon_chan *chan, capi_msg *cm);
#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);

View File

@ -6,65 +6,17 @@
* 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
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Thanks to Eicon Networks 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 <linux/config.h>
#include "eicon.h"
#include "uxio.h"
void
eicon_io_rcv_dispatch(eicon_card *ccard) {
@ -81,12 +33,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
while((skb = skb_dequeue(&ccard->rcvq))) {
ind = (eicon_IND *)skb->data;
save_flags(flags);
cli();
spin_lock_irqsave(&eicon_lock, flags);
if ((chan = ccard->IdTable[ind->IndId]) == NULL) {
spin_unlock_irqrestore(&eicon_lock, flags);
if (DebugVar & 1) {
switch(ind->Ind) {
case IDI_N_DISC_ACK:
case N_DISC_ACK:
/* doesn't matter if this happens */
break;
default:
@ -95,11 +47,10 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
ind->Ind,ind->IndId,ind->IndCh,ind->MInd,ind->MLength,ind->RBuffer.length);
}
}
restore_flags(flags);
dev_kfree_skb(skb);
continue;
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
if (chan->e.complete) { /* check for rec-buffer chaining */
if (ind->MLength == ind->RBuffer.length) {
@ -115,12 +66,9 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
}
}
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;
}
@ -129,7 +77,6 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
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;
@ -148,14 +95,12 @@ eicon_io_rcv_dispatch(eicon_card *ccard) {
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;
}
}
@ -177,242 +122,120 @@ eicon_io_ack_dispatch(eicon_card *ccard) {
/*
* IO-Functions for different card-types
* IO-Functions for ISA cards
*/
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);
return(readb(addr));
}
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);
return(readw(addr));
}
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;
}
writeb(data, addr);
}
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;
}
writew(data, addr);
}
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;
}
memcpy_fromio(adrto, adr, len);
}
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;
}
memcpy_toio(adrto, adr, len);
}
#ifdef CONFIG_ISDN_DRV_EICON_PCI
/*
* XLOG
* IDI-Callback function
*/
int
eicon_get_xlog(eicon_card *card, xlogreq_t *xlogreq)
void
eicon_idi_callback(ENTITY *de)
{
int timeout, i;
int divas_shared_offset = 0;
eicon_card *ccard = (eicon_card *)de->R;
struct sk_buff *skb;
eicon_RC *ack;
eicon_IND *ind;
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;
if (de->complete == 255) {
/* Return Code */
skb = alloc_skb(sizeof(eicon_RC), GFP_ATOMIC);
if (!skb) {
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
} else {
ack = (eicon_RC *)skb_put(skb, sizeof(eicon_RC));
ack->Rc = de->Rc;
if (de->Rc == ASSIGN_OK) {
ack->RcId = de->Id;
de->user[1] = de->Id;
} else {
ack->RcId = de->user[1];
}
ack->RcCh = de->RcCh;
ack->Reference = de->user[0];
skb_queue_tail(&ccard->rackq, skb);
eicon_schedule_ack(ccard);
eicon_log(ccard, 128, "idi_cbk: Ch%d: Rc=%x Id=%x RLen=%x compl=%x\n",
de->user[0], de->Rc, ack->RcId, de->RLength, de->complete);
}
} else {
/* Indication */
if (de->complete) {
len = de->RLength;
} else {
len = 270;
if (de->RLength <= 270)
eicon_log(ccard, 1, "eicon_cbk: ind not complete but <= 270\n");
}
skb = alloc_skb((sizeof(eicon_IND) + len - 1), GFP_ATOMIC);
if (!skb) {
eicon_log(ccard, 1, "eicon_io: skb_alloc failed in _idi_callback()\n");
} else {
ind = (eicon_IND *)skb_put(skb, (sizeof(eicon_IND) + len - 1));
ind->Ind = de->Ind;
ind->IndId = de->user[1];
ind->IndCh = de->IndCh;
ind->MInd = de->Ind;
ind->RBuffer.length = len;
ind->MLength = de->RLength;
memcpy(&ind->RBuffer.P, &de->RBuffer->P, len);
skb_queue_tail(&ccard->rcvq, skb);
eicon_schedule_rx(ccard);
eicon_log(ccard, 128, "idi_cbk: Ch%d: Ind=%x Id=%x RLen=%x compl=%x\n",
de->user[0], de->Ind, ind->IndId, de->RLength, de->complete);
}
}
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;
de->RNum = 0;
de->RNR = 0;
de->Rc = 0;
de->Ind = 0;
}
#endif /* CONFIG_ISDN_DRV_EICON_PCI */
/*
* 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;
@ -422,10 +245,11 @@ eicon_io_transmit(eicon_card *ccard) {
int ReqCount;
int scom = 0;
int tmp = 0;
int tmpid = 0;
int quloop = 1;
int dlev = 0;
ENTITY *ep = 0;
pci_card = &ccard->hwif.pci;
isa_card = &ccard->hwif.isa;
if (!ccard) {
@ -447,20 +271,17 @@ eicon_io_transmit(eicon_card *ccard) {
prram = (eicon_pr_ram *)isa_card->shmem;
break;
#endif
#ifdef CONFIG_ISDN_DRV_EICON_PCI
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;
scom = 2;
break;
case EICON_CTYPE_MAESTRAQ:
scom = 2;
break;
case EICON_CTYPE_MAESTRA:
scom = 0;
ram = (char *)pci_card->PCIram;
reg = (char *)pci_card->PCIreg;
cfg = (char *)pci_card->PCIcfg;
prram = 0;
scom = 2;
break;
#endif
default:
eicon_log(ccard, 1, "eicon_transmit: unsupported card-type!\n");
return;
@ -470,69 +291,91 @@ eicon_io_transmit(eicon_card *ccard) {
if (!(skb2 = skb_dequeue(&ccard->sndq)))
quloop = 0;
while(quloop) {
save_flags(flags);
cli();
if (scom) {
spin_lock_irqsave(&eicon_lock, flags);
switch (scom) {
case 1:
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);
spin_unlock_irqrestore(&eicon_lock, flags);
skb_queue_head(&ccard->sndq, skb2);
eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
return;
}
} else {
break;
case 0:
if (!(ram_inb(ccard, &prram->ReqOutput) - ram_inb(ccard, &prram->ReqInput))) {
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, flags);
skb_queue_head(&ccard->sndq, skb2);
eicon_log(ccard, 32, "eicon: transmit: Card not ready\n");
return;
}
break;
}
restore_flags(flags);
spin_unlock_irqrestore(&eicon_lock, 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) {
spin_lock_irqsave(&eicon_lock, flags);
switch (scom) {
case 1:
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 {
break;
case 0:
/* 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);
break;
}
dlev = 160;
if (reqbuf->ReqId & 0x1f) { /* if this is no ASSIGN */
if (!reqbuf->Reference) { /* Signal Layer */
if (scom)
switch (scom) {
case 1:
ram_outb(ccard, &com->ReqId, chan->e.D3Id);
else
break;
case 0:
ram_outb(ccard, &ReqOut->ReqId, chan->e.D3Id);
break;
case 2:
ep = &chan->de;
break;
}
tmpid = chan->e.D3Id;
chan->e.ReqCh = 0;
}
else { /* Net Layer */
if (scom)
switch(scom) {
case 1:
ram_outb(ccard, &com->ReqId, chan->e.B2Id);
else
break;
case 0:
ram_outb(ccard, &ReqOut->ReqId, chan->e.B2Id);
break;
case 2:
ep = &chan->be;
break;
}
tmpid = chan->e.B2Id;
chan->e.ReqCh = 1;
if (((reqbuf->Req & 0x0f) == 0x08) ||
((reqbuf->Req & 0x0f) == 0x01)) { /* Send Data */
@ -544,51 +387,106 @@ eicon_io_transmit(eicon_card *ccard) {
} else { /* It is an ASSIGN */
if (scom)
switch(scom) {
case 1:
ram_outb(ccard, &com->ReqId, reqbuf->ReqId);
else
break;
case 0:
ram_outb(ccard, &ReqOut->ReqId, reqbuf->ReqId);
break;
case 2:
if (!reqbuf->Reference)
ep = &chan->de;
else
ep = &chan->be;
ep->Id = reqbuf->ReqId;
break;
}
tmpid = reqbuf->ReqId;
if (!reqbuf->Reference)
chan->e.ReqCh = 0;
else
chan->e.ReqCh = 1;
}
if (scom)
switch(scom) {
case 1:
chan->e.ref = ccard->ref_out++;
else
break;
case 0:
chan->e.ref = ram_inw(ccard, &ReqOut->Reference);
break;
case 2:
chan->e.ref = chan->No;
break;
}
chan->e.Req = reqbuf->Req;
ReqCount++;
if (scom)
switch (scom) {
case 1:
ram_outb(ccard, &com->Req, reqbuf->Req);
else
break;
case 0:
ram_outw(ccard, &prram->NextReq, ram_inw(ccard, &ReqOut->next));
break;
case 2:
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if (!ep) break;
ep->callback = eicon_idi_callback;
ep->R = (BUFFERS *)ccard;
ep->user[0] = (word)chan->No;
ep->user[1] = (word)tmpid;
ep->XNum = 1;
ep->RNum = 0;
ep->RNR = 0;
ep->Rc = 0;
ep->Ind = 0;
ep->X->PLength = reqbuf->XBuffer.length;
memcpy(ep->X->P, &reqbuf->XBuffer.P, reqbuf->XBuffer.length);
ep->ReqCh = reqbuf->ReqCh;
ep->Req = reqbuf->Req;
#endif
break;
}
chan->e.busy = 1;
spin_unlock_irqrestore(&eicon_lock, flags);
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->Req, tmpid,
reqbuf->ReqCh, reqbuf->XBuffer.length,
chan->e.ref);
#ifdef CONFIG_ISDN_DRV_EICON_PCI
if (scom == 2) {
if (ep) {
ccard->d->request(ep);
if (ep->Rc)
eicon_idi_callback(ep);
}
}
#endif
}
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);
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)))
switch(scom) {
case 1:
quloop = 0;
break;
case 0:
case 2:
if (!(skb2 = skb_dequeue(&ccard->sndq)))
quloop = 0;
break;
}
}
if (!scom)
@ -599,18 +497,14 @@ eicon_io_transmit(eicon_card *ccard) {
}
}
#ifdef CONFIG_ISDN_DRV_EICON_ISA
/*
* 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;
@ -642,11 +536,9 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
}
}
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:
@ -660,23 +552,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
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;
@ -684,7 +559,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
if (*irqprobe) {
switch(ccard->type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_S:
case EICON_CTYPE_SX:
case EICON_CTYPE_SCOM:
@ -702,26 +576,11 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
}
(*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:
@ -732,20 +591,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
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) {
@ -887,7 +732,6 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
/* clear interrupt */
switch(ccard->type) {
#ifdef CONFIG_ISDN_DRV_EICON_ISA
case EICON_CTYPE_QUADRO:
writeb(0, isa_card->intack);
writeb(0, &com[0x401]);
@ -898,19 +742,8 @@ eicon_irq(int irq, void *dev_id, struct pt_regs *regs) {
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;
}
#endif

View File

@ -7,71 +7,8 @@
* 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -321,7 +258,7 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
boot = &card->shmem->boot;
/* Delay 0.2 sec. */
SLEEP(20);
SLEEP(HZ / 5);
/* Start CPU */
writeb(cbuf.boot_opt, &boot->ctrl);
@ -334,10 +271,10 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
#endif /* CONFIG_MCA */
/* Delay 0.2 sec. */
SLEEP(20);
SLEEP(HZ / 5);
timeout = jiffies + (HZ * 22);
while (timeout > jiffies) {
while (time_before(jiffies, timeout)) {
if (readb(&boot->ctrl) == 0)
break;
SLEEP(10);
@ -380,7 +317,7 @@ eicon_isa_bootload(eicon_isa_card *card, eicon_isa_codebuf *cb) {
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);
((eicon_card *)card->card)->regname, 0);
printk(KERN_INFO "Eicon: %d adapters added\n", tmp);
}
return 0;
@ -452,8 +389,8 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
while (tmp--) {
memcpy_toio(&boot->b, p, 256);
writeb(1, &boot->ctrl);
timeout = jiffies + 10;
while (timeout > jiffies) {
timeout = jiffies + HZ / 10;
while (time_before(jiffies, timeout)) {
if (readb(&boot->ctrl) == 0)
break;
SLEEP(2);
@ -476,7 +413,7 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
/* Start firmware, wait for signature */
writeb(2, &boot->ctrl);
timeout = jiffies + (5*HZ);
while (timeout > jiffies) {
while (time_before(jiffies, timeout)) {
if (readw(&boot->signature) == 0x4447)
break;
SLEEP(2);
@ -500,8 +437,8 @@ eicon_isa_load(eicon_isa_card *card, eicon_isa_codebuf *cb) {
tmp = readb(&card->shmem->com.ReadyInt);
tmp ++;
writeb(tmp, &card->shmem->com.ReadyInt);
timeout = jiffies + 20;
while (timeout > jiffies) {
timeout = jiffies + HZ / 5;
while (time_before(jiffies, timeout)) {
if (card->irqprobe > 1)
break;
SLEEP(2);

View File

@ -6,47 +6,8 @@
* 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -134,7 +95,6 @@ typedef struct {
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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -5,35 +5,8 @@
* 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.
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -42,147 +15,20 @@
#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 */

View File

@ -0,0 +1,560 @@
/*
* Diva Server 4BRI specific part of initialisation
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.7
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "constant.h"
#include "adapter.h"
#include "uxio.h"
#define TEST_INT_DIVAS_Q 0x13
#define DIVAS_MAINT_OFFSET 0xff00 /* value for 4BRI card */
#define MQ_BOARD_DSP_OFFSET 0x00a00000
#define MQ_DSP1_ADDR_OFFSET 0x00000008
#define MQ_DSP_JUNK_OFFSET 0x00000400
#define MQ_DSP1_DATA_OFFSET 0x00000000
#define MQ_BOARD_ISAC_DSP_RESET 0x00800028
#define MQ_BREG_RISC 0x1200 /* RISC Reset */
#define MQ_ISAC_DSP_RESET 0x0028 /* ISAC and DSP reset address offset */
#define MQ_RISC_COLD_RESET_MASK 0x0001 /* RISC Cold reset */
#define MQ_RISC_WARM_RESET_MASK 0x0002 /* RISC Warm reset */
#define MQ_IRQ_REQ_ON 0x1
#define MQ_IRQ_REQ_OFF 0x0
#define MQ_BREG_IRQ_TEST 0x0608
#define PLX9054_INTCSR 0x69
#define PLX9054_INT_ENA 0x09
#define DIVAS_IOBASE 0x01
#define M_PCI_RESET 0x10
byte mem_in(ADAPTER *a, void *adr);
word mem_inw(ADAPTER *a, void *adr);
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
void mem_out(ADAPTER *a, void *adr, byte data);
void mem_outw(ADAPTER *a, void *adr, word data);
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_inc(ADAPTER *a, void *adr);
int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg);
static int fourbri_ISR (card_t* card);
int FPGA_Download(word, dword, byte *, byte *, int);
extern byte FPGA_Bytes[];
extern void *get_card(int);
byte UxCardPortIoIn(ux_diva_card_t *card, byte *base, int offset);
void UxCardPortIoOut(ux_diva_card_t *card, byte *base, int offset, byte);
word GetProtFeatureValue(char *sw_id);
void memcp(byte *dst, byte *src, dword dwLen);
int memcm(byte *dst, byte *src, dword dwLen);
static int diva_server_4bri_reset(card_t *card)
{
byte *ctl;
DPRINTF(("divas: reset Diva Server 4BRI"));
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
/* stop RISC, DSP's and ISAC */
UxCardMemOut(card->hw, &ctl[MQ_BREG_RISC], 0);
UxCardMemOut(card->hw, &ctl[MQ_ISAC_DSP_RESET], 0);
UxCardMemDetach(card->hw, ctl);
return 0;
}
static int diva_server_4bri_config(card_t *card, dia_config_t *config)
{
byte *shared;
int i, j;
DPRINTF(("divas: configure Diva Server 4BRI"));
shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
for (i=0; i<256; i++)
{
UxCardMemOut(card->hw, &shared[i], 0);
}
UxCardMemOut(card->hw, &shared[ 8], config->tei);
UxCardMemOut(card->hw, &shared[ 9], config->nt2);
UxCardMemOut(card->hw, &shared[10], config->sig_flags);
UxCardMemOut(card->hw, &shared[11], config->watchdog);
UxCardMemOut(card->hw, &shared[12], config->permanent);
UxCardMemOut(card->hw, &shared[13], config->x_interface);
UxCardMemOut(card->hw, &shared[14], config->stable_l2);
UxCardMemOut(card->hw, &shared[15], config->no_order_check);
UxCardMemOut(card->hw, &shared[16], config->handset_type);
UxCardMemOut(card->hw, &shared[17], 0);
UxCardMemOut(card->hw, &shared[18], config->low_channel);
UxCardMemOut(card->hw, &shared[19], config->prot_version);
UxCardMemOut(card->hw, &shared[20], config->crc4);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
DPRINTF(("divas: Signifying V.90"));
UxCardMemOut(card->hw, &shared[22], 4);
}
else
{
UxCardMemOut(card->hw, &shared[22], 0);
}
for (i=0; i<2; i++)
{
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
}
}
UxCardMemDetach(card->hw, shared);
return 0;
}
static
void diva_server_4bri_reset_int(card_t *card)
{
byte *ctl;
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
UxCardMemDetach(card->hw, ctl);
return;
}
static int diva_server_4bri_test_int(card_t *card)
{
byte *ctl, i;
byte *reg;
DPRINTF(("divas: test interrupt for Diva Server 4BRI"));
/* We get the last (dummy) adapter in so we need to go back to the first */
card = get_card(card->cfg.card_id - 3);
/* Enable interrupts on PLX chip */
reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
UxCardPortIoOut(card->hw, reg, PLX9054_INTCSR, PLX9054_INT_ENA);
UxCardMemDetach(card->hw, reg);
/* Set the test interrupt flag */
card->test_int_pend = TEST_INT_DIVAS_Q;
/* Now to trigger the interrupt */
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_ON);
UxCardMemDetach(card->hw, ctl);
for (i = 0; i < 50; i++)
{
if (!card->test_int_pend)
{
break;
}
UxPause(10);
}
if (card->test_int_pend)
{
DPRINTF(("active: timeout waiting for card to interrupt"));
return (-1);
}
return 0;
}
static void print_hdr(unsigned char *code, int offset)
{
unsigned char hdr[80];
int i;
i = 0;
while ((i < (DIM(hdr) -1)) &&
(code[offset + i] != '\0') &&
(code[offset + i] != '\r') &&
(code[offset + i] != '\n'))
{
hdr[i] = code[offset + i];
i++;
}
hdr[i] = '\0';
DPRINTF(("divas: loading %s", hdr));
}
static int diva_server_4bri_load(card_t *card, dia_load_t *load)
{
byte *pRAM=NULL;
int download_offset=0;
card_t *FirstCard;
byte sw_id[80];
DPRINTF(("divas: loading Diva Server 4BRI[%d]", load->card_id));
switch(load->code_type)
{
case DIA_CPU_CODE:
DPRINTF(("divas: RISC code"));
print_hdr(load->code, 0x80);
card->hw->features = GetProtFeatureValue((char *)&load->code[0x80]);
download_offset = 0; // Protocol code written to offset 0
pRAM = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
break;
case DIA_DSP_CODE:
DPRINTF(("divas: DSP code"));
print_hdr(load->code, 0x0);
FirstCard = get_card(load->card_id - 3);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
download_offset = MQ_V90D_DSP_CODE_BASE;
}
else
{
download_offset = MQ_ORG_DSP_CODE_BASE;
}
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
download_offset += (((sizeof(dword) + (sizeof(t_dsp_download_desc)* DSP_MAX_DOWNLOAD_COUNT)) + 3) & 0xFFFFFFFC);
break;
case DIA_TABLE_CODE:
DPRINTF(("divas: TABLE code"));
FirstCard = get_card(load->card_id - 3);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
download_offset = MQ_V90D_DSP_CODE_BASE + sizeof(dword);
}
else
{
download_offset = MQ_ORG_DSP_CODE_BASE + sizeof(dword);
}
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
break;
case DIA_CONT_CODE:
DPRINTF(("divas: continuation code"));
break;
case DIA_DLOAD_CNT:
DPRINTF(("divas: COUNT code"));
FirstCard = get_card(load->card_id - 3);
if ((card->hw->features) && (card->hw->features & PROTCAP_V90D))
{
download_offset = MQ_V90D_DSP_CODE_BASE;
}
else
{
download_offset = MQ_ORG_DSP_CODE_BASE;
}
pRAM = UxCardMemAttach(FirstCard->hw, DIVAS_RAM_MEMORY);
break;
case DIA_FPGA_CODE:
DPRINTF(("divas: 4BRI FPGA download - %d bytes", load->length));
if (FPGA_Download(IDI_ADAPTER_MAESTRAQ,
card->hw->io_base,
sw_id,
load->code,
load->length
) == -1)
{
DPRINTF(("divas: FPGA download failed"));
return -1;
}
/* NOW reset the 4BRI */
diva_server_4bri_reset(card);
return 0; // No need for anything further loading
default:
DPRINTF(("divas: unknown code type"));
return -1;
}
memcp(pRAM + (download_offset & 0x3FFFFF), load->code, load->length);
{
int mism_off;
if ((mism_off = memcm(pRAM + (download_offset & 0x3FFFFF), load->code, load->length)))
{
DPRINTF(("divas: memory mismatch at offset %d", mism_off));
UxCardMemDetach(card->hw, pRAM);
return -1;
}
}
UxCardMemDetach(card->hw, pRAM);
return 0;
}
static int diva_server_4bri_start(card_t *card, byte *channels)
{
byte *ctl;
byte *shared, i;
int adapter_num;
DPRINTF(("divas: start Diva Server 4BRI"));
*channels = 0;
card->is_live = FALSE;
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_COLD_RESET_MASK);
UxPause(2);
UxCardMemOutW(card->hw, &ctl[MQ_BREG_RISC], MQ_RISC_WARM_RESET_MASK | MQ_RISC_COLD_RESET_MASK);
UxPause(10);
UxCardMemDetach(card->hw, ctl);
shared = (byte *) UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
for ( i = 0 ; i < 300 ; ++i )
{
UxPause (10) ;
if ( UxCardMemInW(card->hw, &shared[0x1E]) == 0x4447 )
{
DPRINTF(("divas: Protocol startup time %d.%02d seconds",
(i / 100), (i % 100) ));
break;
}
}
if (i==300)
{
DPRINTF(("divas: Timeout starting card"));
DPRINTF(("divas: Signature == 0x%04X", UxCardMemInW(card->hw, &shared[0x1E])));
UxCardMemDetach(card->hw, shared);
return -1;
}
UxCardMemDetach(card->hw, shared);
for (adapter_num=3; adapter_num >= 0; adapter_num--)
{
card_t *qbri_card;
qbri_card = get_card(card->cfg.card_id - adapter_num);
if (qbri_card)
{
qbri_card->is_live = TRUE;
shared = UxCardMemAttach(qbri_card->hw, DIVAS_SHARED_MEMORY);
*channels += UxCardMemIn(qbri_card->hw, &shared[0x3F6]);
UxCardMemDetach(qbri_card->hw, shared);
}
else
{
DPRINTF(("divas: Couldn't get card info %d", card->cfg.card_id));
}
}
diva_server_4bri_test_int(card);
return 0;
}
static
int diva_server_4bri_mem_get(card_t *card, mem_block_t *mem_block)
{
byte *a;
byte *card_addr;
word length = 0;
int i;
a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
card_addr = a;
card_addr += mem_block->addr;
for (i=0; i < sizeof(mem_block->data); i++)
{
mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
card_addr++;
length++;
}
UxCardMemDetach(card->hw, a);
return length;
}
/*
* Initialise 4BRI specific entry points
*/
int Divas4BriInit(card_t *card, dia_card_t *cfg)
{
// byte sw_id[80];
// extern int FPGA_Done;
DPRINTF(("divas: initialise Diva Server 4BRI"));
if (Divas4BRIInitPCI(card, cfg) == -1)
{
return -1;
}
/* Need to download the FPGA */
/* if (!FPGA_Done)
{
int retVal;
retVal=FPGA_Download(IDI_ADAPTER_MAESTRAQ,
cfg->io_base,
sw_id,
FPGA_Bytes
);
if(retVal==-1)
{
DPRINTF(("divas: FPGA Download Failed"));
return -1;
}
FPGA_Done = 1;
} */
card->card_reset = diva_server_4bri_reset;
card->card_load = diva_server_4bri_load;
card->card_config = diva_server_4bri_config;
card->card_start = diva_server_4bri_start;
card->reset_int = diva_server_4bri_reset_int;
card->card_mem_get = diva_server_4bri_mem_get;
card->xlog_offset = DIVAS_MAINT_OFFSET;
card->out = DivasOut;
card->test_int = DivasTestInt;
card->dpc = DivasDpc;
card->clear_int = DivasClearInt;
card->card_isr = fourbri_ISR;
card->a.ram_out = mem_out;
card->a.ram_outw = mem_outw;
card->a.ram_out_buffer = mem_out_buffer;
card->a.ram_inc = mem_inc;
card->a.ram_in = mem_in;
card->a.ram_inw = mem_inw;
card->a.ram_in_buffer = mem_in_buffer;
card->a.ram_look_ahead = mem_look_ahead;
return 0;
}
void memcp(byte *dst, byte *src, dword dwLen)
{
while (dwLen)
{
*dst = *src;
dst++; src++;
dwLen--;
}
}
int memcm(byte *dst, byte *src, dword dwLen)
{
int offset = 0;
while (offset < dwLen)
{
if(*dst != *src)
return (offset+1);
offset++;
src++;
dst++;
}
return 0;
}
/*int fourbri_ISR (card_t* card)
{
int served = 0;
byte *DivasIOBase = UxCardMemAttach(card->hw, DIVAS_IOBASE);
if (UxCardPortIoIn (card->hw, DivasIOBase, M_PCI_RESET) & 0x01)
{
served = 1;
card->int_pend += 1;
DivasDpcSchedule();
UxCardPortIoOut (card->hw, DivasIOBase, M_PCI_RESET, 0x08);
}
UxCardMemDetach(card->hw, DivasIOBase);
return (served != 0);
}*/
static int fourbri_ISR (card_t* card)
{
byte *ctl;
card->int_pend += 1;
DivasDpcSchedule(); /* ISR DPC */
ctl = UxCardMemAttach(card->hw, DIVAS_CTL_MEMORY);
UxCardMemOut(card->hw, &ctl[MQ_BREG_IRQ_TEST], MQ_IRQ_REQ_OFF);
UxCardMemDetach(card->hw, ctl);
return (1);
}

141
drivers/isdn/eicon/fpga.c Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "uxio.h"
#define FPGA_PORT 0x6E
#define FPGA_DLOAD_BUFLEN 256
#define NAME_OFFSET 0x10
#define NAME_MAXLEN 12
#define DATE_OFFSET 0x2c
#define DATE_MAXLEN 10
word UxCardPortIoInW(ux_diva_card_t *card, byte *base, int offset);
void UxCardPortIoOutW(ux_diva_card_t *card, byte *base, int offset, word);
void UxPause(long int);
/*-------------------------------------------------------------------------*/
/* Loads the FPGA configuration file onto the hardware. */
/* Function returns 0 on success, else an error number. */
/* On success, an identifier string is returned in the buffer */
/* */
/* A buffer of FPGA_BUFSIZE, a handle to the already opened bitstream */
/* file and a file read function has to be provided by the operating */
/* system part. */
/* ----------------------------------------------------------------------- */
int FPGA_Download( word cardtype,
dword RegBase,
byte *strbuf,
byte FPGA_SRC[],
int FPGA_LEN
)
{
word i, j, k;
word baseval, Mask_PROGRAM, Mask_DONE, Mask_CCLK, Mask_DIN;
dword addr;
byte *pFPGA;
//--- check for legal cardtype
switch (cardtype)
{
case IDI_ADAPTER_MAESTRAQ:
addr = RegBase ; // address where to access FPGA
Mask_PROGRAM = 0x0001; // FPGA pins at address
Mask_DONE = 0x0002;
Mask_CCLK = 0x0100;
Mask_DIN = 0x0400;
baseval = 0x000d; // PROGRAM hi, CCLK lo, DIN lo by default
break;
default:
DPRINTF(("divas: FPGA Download ,Illegal Card"));
return -1; // illegal card
}
//--- generate id string from file content
for (j=NAME_OFFSET, k=0; j<(NAME_OFFSET+NAME_MAXLEN); j++, k++) //name
{
if (!FPGA_SRC[j]) break;
strbuf[k] = FPGA_SRC[j];
}
strbuf[k++] = ' ';
for (j=DATE_OFFSET; j<(DATE_OFFSET+DATE_MAXLEN); j++, k++) // date
{
if (!FPGA_SRC[j]) break;
strbuf[k] = FPGA_SRC[j];
}
strbuf[k] = 0;
DPRINTF(("divas: FPGA Download - %s", strbuf));
//--- prepare download, Pulse PROGRAM pin down.
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval &~Mask_PROGRAM); // PROGRAM low pulse
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // release
UxPause(50); // wait until FPGA finised internal memory clear
//--- check done pin, must be low
if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE)
{
DPRINTF(("divas: FPGA_ERR_DONE_WRONG_LEVEL"));
return -1;
}
pFPGA = FPGA_SRC;
i = 0;
/* Move past the header */
while ((FPGA_SRC[i] != 0xFF) && (i < FPGA_LEN))
{
i++;
}
// We've hit the 0xFF so move on to the next byte
// i++;
DPRINTF(("divas: FPGA Code starts at offset %d", i));
//--- put data onto the FPGA
for (;i<FPGA_LEN; i++)
{
//--- put byte onto FPGA
for (j=0; j<8; j++)
{
if (FPGA_SRC[i] &(0x80>>j)) baseval |= Mask_DIN; // write a hi
else baseval &=~Mask_DIN; // write a lo
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval);
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK); // set CCLK hi
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // set CCLK lo
}
}
//--- add some additional startup clock cycles and check done pin
for (i=0; i<5; i++)
{
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval | Mask_CCLK); // set CCLK hi
UxCardPortIoOutW(NULL, (byte *) addr, FPGA_PORT, baseval); // set CCLK lo
}
UxPause(100);
if (UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT) &Mask_DONE)
{
DPRINTF(("divas: FPGA download successful"));
}
else
{
DPRINTF(("divas: FPGA download failed - 0x%x", UxCardPortIoInW(NULL, (byte *) addr, FPGA_PORT)));
return -1;
}
return 0;
}

854
drivers/isdn/eicon/idi.c Normal file
View File

@ -0,0 +1,854 @@
/*
* Core driver for Diva Server cards
* Implements the IDI interface
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.8
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "idi.h"
#include "adapter.h"
#include "pc.h"
#include "pr_pc.h"
#include "sys.h"
#include "uxio.h"
/* IDI request functions */
static void request(card_t *card, ENTITY *e);
static void req_0(ENTITY *e) { request(&DivasCards[ 0], e); }
static void req_1(ENTITY *e) { request(&DivasCards[ 1], e); }
static void req_2(ENTITY *e) { request(&DivasCards[ 2], e); }
static void req_3(ENTITY *e) { request(&DivasCards[ 3], e); }
static void req_4(ENTITY *e) { request(&DivasCards[ 4], e); }
static void req_5(ENTITY *e) { request(&DivasCards[ 5], e); }
static void req_6(ENTITY *e) { request(&DivasCards[ 6], e); }
static void req_7(ENTITY *e) { request(&DivasCards[ 7], e); }
static void req_8(ENTITY *e) { request(&DivasCards[ 8], e); }
static void req_9(ENTITY *e) { request(&DivasCards[ 9], e); }
static void req_10(ENTITY *e) { request(&DivasCards[10], e); }
static void req_11(ENTITY *e) { request(&DivasCards[11], e); }
static void req_12(ENTITY *e) { request(&DivasCards[12], e); }
static void req_13(ENTITY *e) { request(&DivasCards[13], e); }
static void req_14(ENTITY *e) { request(&DivasCards[14], e); }
static void req_15(ENTITY *e) { request(&DivasCards[15], e); }
IDI_CALL DivasIdiRequest[16] =
{
&req_0, &req_1, &req_2, &req_3,
&req_4, &req_5, &req_6, &req_7,
&req_8, &req_9, &req_10, &req_11,
&req_12, &req_13, &req_14, &req_15
};
#define PR_RAM ((struct pr_ram *)0)
#define RAM ((struct dual *)0)
/*------------------------------------------------------------------*/
/* local function prototypes */
/*------------------------------------------------------------------*/
static byte isdn_rc(ADAPTER *, byte, byte, byte, word);
static byte isdn_ind(ADAPTER *, byte, byte, byte, PBUFFER *, byte, word);
/*
* IDI related functions
*/
static
ENTITY *entity_ptr(ADAPTER *a, byte e_no)
{
card_t *card;
card = a->io;
return card->e_tbl[e_no].e;
}
static
void CALLBACK(ADAPTER *a, ENTITY *e)
{
card_t *card = a->io;
if (card->log_types & DIVAS_LOG_IDI)
{
DivasLogIdi(card, e, FALSE);
}
(*e->callback)(e);
}
static
void *PTR_P(ADAPTER *a, ENTITY *e, void *P)
{
return(P);
}
static
void *PTR_R(ADAPTER *a, ENTITY *e)
{
return((void*)e->R);
}
static
void *PTR_X(ADAPTER *a, ENTITY *e)
{
return((void*)e->X);
}
static
void free_entity(ADAPTER *a, byte e_no)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_tbl[e_no].e = NULL;
card->e_count--;
UxCardUnlock(card->hw, ipl);
return;
}
static
void assign_queue(ADAPTER * a, byte e_no, word ref)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_tbl[e_no].assign_ref = ref;
card->e_tbl[e_no].next = card->assign;
card->assign = e_no;
UxCardUnlock(card->hw, ipl);
return;
}
static
byte get_assign(ADAPTER *a, word ref)
{
card_t *card;
byte e_no;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
e_no = (byte)card->assign;
while (e_no)
{
if (card->e_tbl[e_no].assign_ref == ref)
{
break;
}
e_no = card->e_tbl[e_no].next;
}
UxCardUnlock(card->hw, ipl);
return e_no;
}
static
void req_queue(ADAPTER * a, byte e_no)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_tbl[e_no].next = 0;
if (card->e_head)
{
card->e_tbl[card->e_tail].next = e_no;
card->e_tail = e_no;
}
else
{
card->e_head = e_no;
card->e_tail = e_no;
}
UxCardUnlock(card->hw, ipl);
return;
}
static
byte look_req(ADAPTER * a)
{
card_t *card;
card = a->io;
return(card->e_head);
}
static
void next_req(ADAPTER * a)
{
card_t *card;
int ipl;
card = a->io;
ipl = UxCardLock(card->hw);
card->e_head = card->e_tbl[card->e_head].next;
if (!card->e_head)
{
card->e_tail = 0;
}
UxCardUnlock(card->hw, ipl);
return;
}
/*
* IDI request function for active cards
*/
static
void request(card_t *card, ENTITY *e)
{
word *special_req;
int i;
int ipl;
if (card->log_types & DIVAS_LOG_IDI)
{
DivasLogIdi(card, e, TRUE);
}
if (!e->Req)
{
special_req = (word *) e;
switch (*special_req)
{
case REQ_REMOVE:
return;
case REQ_NAME:
for (i=0; i < DIM(card->cfg.name); i++)
{
((struct get_name_s *) e)->name[i] = card->cfg.name[i];
}
return;
case REQ_SERIAL:
case REQ_XLOG:
DPRINTF(("IDI: attempted REQ_SERIAL or REQ_XLOG"));
return;
default:
return;
}
}
ipl = UxCardLock(card->hw);
if (!(e->Id & 0x1f))
{
DPRINTF(("IDI: ASSIGN req"));
for (i = 1; i < card->e_max; i++)
{
if (!card->e_tbl[i].e)
{
break;
}
}
if (i == card->e_max)
{
DPRINTF(("IDI: request all ids in use (IDI req ignored)"));
UxCardUnlock(card->hw, ipl);
e->Rc = OUT_OF_RESOURCES;
return;
}
card->e_tbl[i].e = e;
card->e_count++;
e->No = (byte) i;
e->More = 0;
e->RCurrent = 0xff;
}
else
{
i = e->No;
}
if (e->More & XBUSY)
{
DPRINTF(("IDI: request - entity is busy"));
UxCardUnlock(card->hw, ipl);
return;
}
e->More |= XBUSY;
e->More &= ~ XMOREF;
e->XCurrent = 0;
e->XOffset = 0;
card->e_tbl[i].next = 0;
if(card->e_head)
{
card->e_tbl[card->e_tail].next = i;
card->e_tail = i;
}
else
{
card->e_head = i;
card->e_tail = i;
}
UxCardUnlock(card->hw, ipl);
DivasScheduleRequestDpc();
return;
}
static byte pr_ready(ADAPTER * a)
{
byte ReadyCount;
ReadyCount = (byte)(a->ram_in(a, &PR_RAM->ReqOutput) -
a->ram_in(a, &PR_RAM->ReqInput));
if(!ReadyCount) {
if(!a->ReadyInt) {
a->ram_inc(a, &PR_RAM->ReadyInt);
a->ReadyInt++;
}
}
return ReadyCount;
}
/*------------------------------------------------------------------*/
/* output function */
/*------------------------------------------------------------------*/
void DivasOut(ADAPTER * a)
{
byte e_no;
ENTITY * this = NULL;
BUFFERS *X;
word length;
word i;
word clength;
REQ * ReqOut;
byte more;
byte ReadyCount;
byte ReqCount;
byte Id;
/* while a request is pending ... */
e_no = look_req(a);
if(!e_no)
{
return;
}
ReadyCount = pr_ready(a);
if(!ReadyCount)
{
DPRINTF(("IDI: card not ready for next request"));
return;
}
ReqCount = 0;
while(e_no && ReadyCount) {
next_req(a);
this = entity_ptr(a, e_no);
#ifdef USE_EXTENDED_DEBUGS
if ( !this )
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DBG_FTL(("!A%d ==> NULL entity ptr - try to ignore", (int)io->ANum))
e_no = look_req(a) ;
ReadyCount-- ;
continue ;
}
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DPRINTF(("IDI: >A%d Id=0x%x Req=0x%x", io->ANum, this->Id, this->Req))
}
#else
DPRINTF(("IDI: >REQ=%x,Id=%x,Ch=%x",this->Req,this->Id,this->ReqCh));
#endif
/* get address of next available request buffer */
ReqOut = (REQ *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextReq)];
/* now copy the data from the current data buffer into the */
/* adapters request buffer */
length = 0;
i = this->XCurrent;
X = PTR_X(a,this);
while(i<this->XNum && length<270) {
clength = (word)(270-length);
if (clength > X[i].PLength-this->XOffset)
clength = X[i].PLength-this->XOffset;
a->ram_out_buffer(a,
&ReqOut->XBuffer.P[length],
PTR_P(a,this,&X[i].P[this->XOffset]),
clength);
length +=clength;
this->XOffset +=clength;
if(this->XOffset==X[i].PLength) {
this->XCurrent = (byte)++i;
this->XOffset = 0;
}
}
a->ram_outw(a, &ReqOut->XBuffer.length, length);
a->ram_out(a, &ReqOut->ReqId, this->Id);
a->ram_out(a, &ReqOut->ReqCh, this->ReqCh);
/* if its a specific request (no ASSIGN) ... */
if(this->Id &0x1f) {
/* if buffers are left in the list of data buffers do */
/* do chaining (LL_MDATA, N_MDATA) */
this->More++;
if(i<this->XNum && this->MInd) {
a->ram_out(a, &ReqOut->Req, this->MInd);
more = TRUE;
}
else {
this->More |=XMOREF;
a->ram_out(a, &ReqOut->Req, this->Req);
more = FALSE;
}
/* if we did chaining, this entity is put back into the */
/* request queue */
if(more) {
req_queue(a,this->No);
}
}
/* else it's a ASSIGN */
else {
/* save the request code used for buffer chaining */
this->MInd = 0;
if (this->Id==BLLC_ID) this->MInd = LL_MDATA;
if (this->Id==NL_ID ||
this->Id==TASK_ID ||
this->Id==MAN_ID
) this->MInd = N_MDATA;
/* send the ASSIGN */
this->More |=XMOREF;
a->ram_out(a, &ReqOut->Req, this->Req);
/* save the reference of the ASSIGN */
assign_queue(a, this->No, a->ram_inw(a, &ReqOut->Reference));
}
a->ram_outw(a, &PR_RAM->NextReq, a->ram_inw(a, &ReqOut->next));
ReadyCount--;
ReqCount++;
e_no = look_req(a);
}
/* send the filled request buffers to the ISDN adapter */
a->ram_out(a, &PR_RAM->ReqInput,
(byte)(a->ram_in(a, &PR_RAM->ReqInput) + ReqCount));
/* if it is a 'unreturncoded' UREMOVE request, remove the */
/* Id from our table after sending the request */
if(this->Req==UREMOVE && this->Id) {
Id = this->Id;
e_no = a->IdTable[Id];
free_entity(a, e_no);
a->IdTable[Id] = 0;
this->Id = 0;
}
}
/*------------------------------------------------------------------*/
/* isdn interrupt handler */
/*------------------------------------------------------------------*/
byte DivasDpc(ADAPTER * a)
{
byte Count;
RC * RcIn;
IND * IndIn;
byte c;
byte RNRId;
byte Rc;
byte Ind;
/* if return codes are available ... */
if((Count = a->ram_in(a, &PR_RAM->RcOutput))) {
DPRINTF(("IDI: #Rc=%x",Count));
/* get the buffer address of the first return code */
RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextRc)];
/* for all return codes do ... */
while(Count--) {
if((Rc=a->ram_in(a, &RcIn->Rc))) {
/* call return code handler, if it is not our return code */
/* the handler returns 2 */
/* for all return codes we process, we clear the Rc field */
isdn_rc(a,
Rc,
a->ram_in(a, &RcIn->RcId),
a->ram_in(a, &RcIn->RcCh),
a->ram_inw(a, &RcIn->Reference));
a->ram_out(a, &RcIn->Rc, 0);
}
/* get buffer address of next return code */
RcIn = (RC *)&PR_RAM->B[a->ram_inw(a, &RcIn->next)];
}
/* clear all return codes (no chaining!) */
a->ram_out(a, &PR_RAM->RcOutput ,0);
/* call output function */
DivasOut(a);
}
/* clear RNR flag */
RNRId = 0;
/* if indications are available ... */
if((Count = a->ram_in(a, &PR_RAM->IndOutput))) {
DPRINTF(("IDI: #Ind=%x",Count));
/* get the buffer address of the first indication */
IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &PR_RAM->NextInd)];
/* for all indications do ... */
while(Count--) {
/* if the application marks an indication as RNR, all */
/* indications from the same Id delivered in this interrupt */
/* are marked RNR */
if(RNRId && RNRId==a->ram_in(a, &IndIn->IndId)) {
a->ram_out(a, &IndIn->Ind, 0);
a->ram_out(a, &IndIn->RNR, TRUE);
}
else {
Ind = a->ram_in(a, &IndIn->Ind);
if(Ind) {
RNRId = 0;
/* call indication handler, a return value of 2 means chain */
/* a return value of 1 means RNR */
/* for all indications we process, we clear the Ind field */
c = isdn_ind(a,
Ind,
a->ram_in(a, &IndIn->IndId),
a->ram_in(a, &IndIn->IndCh),
&IndIn->RBuffer,
a->ram_in(a, &IndIn->MInd),
a->ram_inw(a, &IndIn->MLength));
if(c==1) {
DPRINTF(("IDI: RNR"));
a->ram_out(a, &IndIn->Ind, 0);
RNRId = a->ram_in(a, &IndIn->IndId);
a->ram_out(a, &IndIn->RNR, TRUE);
}
}
}
/* get buffer address of next indication */
IndIn = (IND *)&PR_RAM->B[a->ram_inw(a, &IndIn->next)];
}
a->ram_out(a, &PR_RAM->IndOutput, 0);
}
return FALSE;
}
byte DivasTestInt(ADAPTER * a)
{
return a->ram_in(a,(void *)0x3fe);
}
void DivasClearInt(ADAPTER * a)
{
a->ram_out(a,(void *)0x3fe,0);
}
/*------------------------------------------------------------------*/
/* return code handler */
/*------------------------------------------------------------------*/
static
byte isdn_rc(ADAPTER * a,
byte Rc,
byte Id,
byte Ch,
word Ref)
{
ENTITY * this;
byte e_no;
#ifdef USE_EXTENDED_DEBUGS
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DPRINTF(("IDI: <A%d Id=0x%x Rc=0x%x", io->ANum, Id, Rc))
}
#else
DPRINTF(("IDI: <RC(Rc=%x,Id=%x,Ch=%x)",Rc,Id,Ch));
#endif
/* check for ready interrupt */
if(Rc==READY_INT) {
if(a->ReadyInt) {
a->ReadyInt--;
return 0;
}
return 2;
}
/* if we know this Id ... */
e_no = a->IdTable[Id];
if(e_no) {
this = entity_ptr(a,e_no);
this->RcCh = Ch;
/* if it is a return code to a REMOVE request, remove the */
/* Id from our table */
if(this->Req==REMOVE && Rc==OK) {
free_entity(a, e_no);
a->IdTable[Id] = 0;
this->Id = 0;
/**************************************************************/
if ((this->More & XMOREC) > 1) {
this->More &= ~XMOREC;
this->More |= 1;
DPRINTF(("isdn_rc, Id=%x, correct More on REMOVE", Id));
}
}
if (Rc==OK_FC) {
this->Rc = Rc;
this->More = (this->More & (~XBUSY | XMOREC)) | 1;
this->complete = 0xFF;
CALLBACK(a, this);
return 0;
}
if(this->More &XMOREC)
this->More--;
/* call the application callback function */
if(this->More &XMOREF && !(this->More &XMOREC)) {
this->Rc = Rc;
this->More &=~XBUSY;
this->complete=0xff;
CALLBACK(a, this);
}
return 0;
}
/* if it's an ASSIGN return code check if it's a return */
/* code to an ASSIGN request from us */
if((Rc &0xf0)==ASSIGN_RC) {
e_no = get_assign(a, Ref);
if(e_no) {
this = entity_ptr(a,e_no);
this->Id = Id;
/* call the application callback function */
this->Rc = Rc;
this->More &=~XBUSY;
this->complete=0xff;
CALLBACK(a, this);
if(Rc==ASSIGN_OK) {
a->IdTable[Id] = e_no;
}
else
{
free_entity(a, e_no);
a->IdTable[Id] = 0;
this->Id = 0;
}
return 1;
}
}
return 2;
}
/*------------------------------------------------------------------*/
/* indication handler */
/*------------------------------------------------------------------*/
static
byte isdn_ind(ADAPTER * a,
byte Ind,
byte Id,
byte Ch,
PBUFFER * RBuffer,
byte MInd,
word MLength)
{
ENTITY * this;
word clength;
word offset;
BUFFERS *R;
#ifdef USE_EXTENDED_DEBUGS
{
ISDN_ADAPTER *io = (ISDN_ADAPTER *)a->io ;
DPRINTF(("IDI: <A%d Id=0x%x Ind=0x%x", io->ANum, Id, Ind))
}
#else
DPRINTF(("IDI: <IND(Ind=%x,Id=%x,Ch=%x)",Ind,Id,Ch));
#endif
if(a->IdTable[Id]) {
this = entity_ptr(a,a->IdTable[Id]);
this->IndCh = Ch;
/* if the Receive More flag is not yet set, this is the */
/* first buffer of the packet */
if(this->RCurrent==0xff) {
/* check for receive buffer chaining */
if(Ind==this->MInd) {
this->complete = 0;
this->Ind = MInd;
}
else {
this->complete = 1;
this->Ind = Ind;
}
/* call the application callback function for the receive */
/* look ahead */
this->RLength = MLength;
a->ram_look_ahead(a, RBuffer, this);
this->RNum = 0;
CALLBACK(a, this);
/* map entity ptr, selector could be re-mapped by call to */
/* IDI from within callback */
this = entity_ptr(a,a->IdTable[Id]);
/* check for RNR */
if(this->RNR==1) {
this->RNR = 0;
return 1;
}
/* if no buffers are provided by the application, the */
/* application want to copy the data itself including */
/* N_MDATA/LL_MDATA chaining */
if(!this->RNR && !this->RNum) {
return 0;
}
/* if there is no RNR, set the More flag */
this->RCurrent = 0;
this->ROffset = 0;
}
if(this->RNR==2) {
if(Ind!=this->MInd) {
this->RCurrent = 0xff;
this->RNR = 0;
}
return 0;
}
/* if we have received buffers from the application, copy */
/* the data into these buffers */
offset = 0;
R = PTR_R(a,this);
do {
if(this->ROffset==R[this->RCurrent].PLength) {
this->ROffset = 0;
this->RCurrent++;
}
clength = a->ram_inw(a, &RBuffer->length)-offset;
if (clength > R[this->RCurrent].PLength-this->ROffset)
clength = R[this->RCurrent].PLength-this->ROffset;
if(R[this->RCurrent].P) {
a->ram_in_buffer(a,
&RBuffer->P[offset],
PTR_P(a,this,&R[this->RCurrent].P[this->ROffset]),
clength);
}
offset +=clength;
this->ROffset +=clength;
} while(offset<(a->ram_inw(a, &RBuffer->length)));
/* if it's the last buffer of the packet, call the */
/* application callback function for the receive complete */
/* call */
if(Ind!=this->MInd) {
R[this->RCurrent].PLength = this->ROffset;
if(this->ROffset) this->RCurrent++;
this->RNum = this->RCurrent;
this->RCurrent = 0xff;
this->Ind = Ind;
this->complete = 2;
CALLBACK(a, this);
}
return 0;
}
return 2;
}

129
drivers/isdn/eicon/idi.h Normal file
View File

@ -0,0 +1,129 @@
/*
* External IDI interface
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(IDI_H)
#define IDI_H
#include "sys.h"
/* typedefs for our data structures */
typedef struct get_name_s GET_NAME;
typedef struct entity_s ENTITY;
typedef struct buffers_s BUFFERS;
/* IDI request/callback function pointer */
typedef void (* IDI_CALL)(ENTITY *);
typedef struct {
word length; /* length of data/parameter field */
byte P[270]; /* data/parameter field */
} DBUFFER;
#define REQ_NAME 0x0100
#define BOARD_NAME_LENGTH 9
struct get_name_s {
word command; /* command = 0x0100 */
byte name[BOARD_NAME_LENGTH];
};
#define REQ_REMOVE 0x0000 /* pointer to word which is 0 */
#define REQ_SERIAL 0x0200
struct get_serial_s {
word command; /* command = 0x0200 */
dword serial; /* serial number */
};
#define REQ_POSTCALL 0x0300
struct postcall_s {
word command; /* command = 0x0300 */
word dummy; /* not used */
IDI_CALL callback; /* routine address to call back */
ENTITY *contxt; /* ptr to entity to use */
};
#define REQ_XLOG 0x0400 /* structure is card dependent/defined locally */
struct buffers_s {
word PLength;
byte *P;
};
struct entity_s {
byte Req; /* pending request */
byte Rc; /* return code received */
byte Ind; /* indication received */
byte ReqCh; /* channel of current Req */
byte RcCh; /* channel of current Rc */
byte IndCh; /* channel of current Ind */
byte Id; /* ID used by this entity */
byte GlobalId; /* reserved field */
byte XNum; /* number of X-buffers */
byte RNum; /* number of R-buffers */
BUFFERS *X; /* pointer to X-buffer list */
BUFFERS *R; /* pointer to R-buffer list */
word RLength; /* length of current R-data */
DBUFFER *RBuffer; /* buffer of current R-data */
byte RNR; /* receive not ready flag */
byte complete; /* receive complete status */
IDI_CALL callback;
word user[2];
/* fields used by the driver internally */
byte No; /* entity number */
byte reserved2; /* reserved field */
byte More; /* R/X More flags */
byte MInd; /* MDATA coding for this ID */
byte XCurrent; /* current transmit buffer */
byte RCurrent; /* current receive buffer */
word XOffset; /* offset in x-buffer */
word ROffset; /* offset in r-buffer */
};
typedef struct {
byte type;
byte channels;
word features;
/* dword serial; */
IDI_CALL request;
} DESCRIPTOR;
extern void DIVA_DIDD_Read(DESCRIPTOR *, int);
/* descriptor type field coding */
#define IDI_ADAPTER_S 1
#define IDI_ADAPTER_PR 2
#define IDI_ADAPTER_DIVA 3
#define IDI_ADAPTER_MAESTRA 4
#define IDI_ADAPTER_MAESTRAQ 5
#define IDI_ADAPTER_MAESTRAP 6
#define IDI_VADAPTER 0x40
#define IDI_DRIVER 0x80
#define IDI_DIMAINT 0xff
/* feature bit mask values */
#define DI_VOICE 0x0 /* obsolete define */
#define DI_FAX3 0x1
#define DI_MODEM 0x2
#define DI_POST 0x4
#define DI_V110 0x8
#define DI_V120 0x10
#define DI_POTS 0x20
#define DI_CODEC 0x40
#define DI_MANAGE 0x80
#define DI_V_42 0x0100
#define DI_EXTD_FAX 0x0200 /* Extended FAX (ECM, 2D, T.6, Polling) */
#endif /* IDI_H */

View File

@ -0,0 +1,514 @@
/*
* Source file for kernel interface to kernel log facility
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.3
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "eicon.h"
#include "sys.h"
#include <stdarg.h>
#include "divas.h"
#include "divalog.h"
#include "uxio.h"
/*
* Implementation of printf and sprintf for kernel
*/
#define MAX_BUFF (80) /* limit size of temporary buffers */
#define WRITE_CHAR(BUFFER, SIZE, C) \
if (--(SIZE) < 0) { (BUFFER)--; *(BUFFER) = '\0'; return; } *(BUFFER)++ = (C)
/*
* convert a number to decimal ASCII
*/
static
void do_decimal( char *temp,
int temp_len,
unsigned int value,
char *s)
{
int i;
temp[0] = '\0';
for (i = 1; i < temp_len; i++)
{
temp[i] = (char) ((value % 10) + (int) '0');
value /= 10;
}
for (i = (temp_len - 1); temp[i] == '0'; i--)
{
;
}
if (i == 0)
{
i++;
}
while (i >= 0)
{
*s++ = temp[i--];
}
return;
}
/*
* convert a number to octal ASCII
*/
static
void do_octal( char *temp,
unsigned int value,
char *s)
{
int i;
temp[0] = '\0';
for (i = 1; i <= 11; i++)
{
temp[i] = (char) ((value & 07) + (int) '0');
value >>= 3;
}
temp[11] &= '3';
for (i = 11; temp[i] == '0'; i--)
{
;
}
if (i == 0)
{
i++;
}
while (i >= 0)
{
*s++ = temp[i--];
}
return;
}
/*
* convert a number to hex ASCII
*/
static
void do_hex( char *temp,
unsigned int value,
char *s)
{
int i;
static
char *dec_to_hex = "0123456789abcdef";
temp[0] = '\0';
for (i = 1; i <= 8; i++)
{
temp[i] = dec_to_hex[value & 0x0f];
value >>= 4;
}
for (i = 8; temp[i] == '0'; i--)
{
;
}
if (i == 0)
{
i++;
}
while (i >= 0)
{
*s++ = temp[i--];
}
return;
}
/*
* convert a buffer to ASCII HEX
*/
static
void do_buffer( char *buffer,
int length,
char *s)
{
static
char hex_char [] = "0123456789abcdef";
char *b = buffer;
int hex_byte;
int nybble;
length = (length >= ((MAX_BUFF / 3) + 1)) ? (MAX_BUFF / 3) : length;
while (length)
{
hex_byte = (int) *b++;
nybble = (hex_byte >> 4) & 0xf;
*s++ = hex_char[nybble];
nybble = hex_byte & 0xf;
*s++ = hex_char[nybble];
*s++ = ' ';
length--;
}
*s = '\0';
return;
}
/*
* Body of sprintf function: behaves just like standard sprintf, except we
* have an extra argument (buffer size) which we use to ensure we don't
* overflow
*/
void Divas_vsprintf( char *buffer,
int size,
char *fmt,
va_list argptr)
{
char c; /* single character buffer */
int i; /* handy scratch counter */
int f; /* format character (after %) */
char *str; /* pointer into string */
char temp[20]; /* temp buffer used in printing numbers */
char string[MAX_BUFF]; /* output from number conversion */
int length; /* length of string "str" */
char fill; /* fill character ' ' or '0' */
boolean_t leftjust; /* TRUE if left justified, else right justified */
int fmax, fmin; /* field specifiers % MIN . MAX s */
int leading; /* number of leading/trailing fill characters */
char sign; /* set to '-' for negative decimals */
int number; /* numeric argument */
char *buff_ptr; /* pointer to user's buffer of hex data */
int buff_len; /* length of hex data */
/* make sure we have somthing to write into */
if ((!buffer) || (size <= 0))
{
return;
}
while (TRUE)
{
/* echo characters until end or '%' encountered */
while ((c = *fmt++) != '%')
{
if (!c)
{
*buffer = '\0';
return;
}
WRITE_CHAR(buffer, size, c);
}
/* echo %% as % */
if (*fmt == '%')
{
WRITE_CHAR(buffer, size, *fmt);
continue;
}
/* %- turns on left-justify */
if ((leftjust = (boolean_t) ((*fmt == '-') ? TRUE : FALSE)))
{
fmt++;
}
/* %0 turns on zero filling */
if (*fmt == '0')
{
fill = '0';
}
else
{
fill = ' ';
}
/* minium field width specifier for %d, u, x, c, s */
fmin = 0;
if (*fmt == '*')
{
fmin = va_arg(argptr, int);
fmt++;
}
else
{
while ('0' <= *fmt && *fmt <= '9')
{
fmin = (fmin * 10) + (*fmt++ - '0');
}
}
/* maximum string width specifier for %s */
fmax = 0;
if (*fmt == '.')
{
if (*(++fmt) == '*')
{
fmax = va_arg(argptr, int);
fmt++;
}
else
{
while ('0' <= *fmt && *fmt <= '9')
{
fmax = (fmax * 10) + (*fmt++ - '0');
}
}
}
/* skip over 'l' option (ints are assumed same size as longs) */
if (*fmt == 'l')
{
fmt++;
}
/* get the format chacater */
if (!(f = *fmt++))
{
WRITE_CHAR(buffer, size, '%');
*buffer = '\0';
return;
}
sign = '\0'; /* sign == '-' for negative decimal */
str = string;
switch (f)
{
case 'c' :
string[0] = (char) va_arg(argptr, int);
string[1] = '\0';
fmax = 0;
fill = ' ';
break;
case 's' :
str = va_arg(argptr, char *);
fill = ' ';
break;
case 'D' :
case 'd' :
number = va_arg(argptr, int);
if (number < 0)
{
sign = '-';
number = -number;
}
do_decimal(temp, DIM(temp), (unsigned int) number, str);
fmax = 0;
break;
case 'U' :
case 'u' :
number = va_arg(argptr, int);
do_decimal(temp, DIM(temp), (unsigned int) number, str);
fmax = 0;
break;
case 'O' :
case 'o' :
number = va_arg(argptr, int);
do_octal(temp, (unsigned int) number, str);
fmax = 0;
break;
case 'X' :
case 'x' :
number = va_arg(argptr, int);
do_hex(temp, (unsigned int) number, str);
fmax = 0;
break;
case 'H' :
case 'h' :
buff_ptr = va_arg(argptr, char *);
buff_len = va_arg(argptr, int);
do_buffer(buff_ptr, buff_len, str);
fmax = 0;
break;
default :
WRITE_CHAR(buffer, size, ((char) f));
break;
}
/* get the length of the string */
length = 0;
while (str[length])
{
length++;
}
/* make sure we have fmax and fmin values that are O.K. */
if (fmin > DIM(string) || fmin < 0)
{
fmin = 0;
}
if (fmax > DIM(string) || fmax < 0)
{
fmax = 0;
}
/* figure out how many leading characters thare are */
leading = 0;
if (fmax || fmin)
{
if (fmax)
{
if (length > fmax)
{
length = fmax;
}
}
if (fmin)
{
leading = fmin - length;
}
if (sign == '-')
{
leading--;
}
}
/* output sign now, if fill is numeric */
if (sign == '-' && fill == '0')
{
WRITE_CHAR(buffer, size, '-');
}
/* if right justified, output fill characters */
if (!leftjust)
{
for (i = 0; i < leading; i++)
{
WRITE_CHAR(buffer, size, fill);
}
}
/* output sign now, if fill is spaces */
if (sign == '-' && fill == ' ')
{
WRITE_CHAR(buffer, size, '-');
}
/* now the actual value */
for (i = 0; i < length; i++)
{
WRITE_CHAR(buffer, size, str[i]);
}
/* if left justified, fill out with the fill character */
if (leftjust)
{
for (i = 0; i < leading; i++)
{
WRITE_CHAR(buffer, size, fill);
}
}
}
}
/*
* sprintf for kernel
*
* call our vsprintf assuming user has a big buffer....
*/
void DivasSprintf(char *buffer, char *fmt, ...)
{
va_list argptr; /* pointer to additional args */
va_start(argptr, fmt);
Divas_vsprintf(buffer, 1024, fmt, argptr);
va_end(argptr);
return;
}
void DivasPrintf(char *fmt, ...)
{
klog_t log; /* log entry buffer */
va_list argptr; /* pointer to additional args */
va_start(argptr, fmt);
/* clear log entry */
memset((void *) &log, 0, sizeof(klog_t));
log.card = -1;
log.type = KLOG_TEXT_MSG;
/* time stamp the entry */
log.time_stamp = UxTimeGet();
/* call vsprintf to format the user's information */
Divas_vsprintf(log.buffer, DIM(log.buffer), fmt, argptr);
va_end(argptr);
/* send to the log streams driver and return */
DivasLogAdd(&log, sizeof(klog_t));
return;
}

390
drivers/isdn/eicon/lincfg.c Normal file
View File

@ -0,0 +1,390 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.9
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/fs.h>
#undef N_DATA /* Because we have our own definition */
#include <asm/segment.h>
#include <asm/io.h>
#include "sys.h"
#include "idi.h"
#include "constant.h"
#include "divas.h"
#undef ID_MASK
#include "pc.h"
#include "pr_pc.h"
#include "adapter.h"
#include "uxio.h"
#include <linux/pci.h>
#ifndef COMPAT_HAS_2_2_PCI
#include <linux/pci_ids.h>
#endif
#include <linux/kernel.h>
#include <linux/ioport.h>
struct file_operations Divas_fops;
int Divas_major;
extern int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
unsigned int command, unsigned long arg);
extern unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable);
extern ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset);
extern int do_open(struct inode *, struct file *);
extern int do_release(struct inode *, struct file *);
int FPGA_Done=0;
int DivasCardsDiscover(void)
{
word wNumCards = 0, wDeviceIndex = 0;
byte byBus, byFunc;
word wPCIConsultation, PCItmp;
dword j, i;
unsigned int PCIserial;
dia_card_t Card;
byte *b;
while (wDeviceIndex < 10)
{
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_MAESTRAQ,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwRAM, dwDivasIOBase, dwCFG, dwCTL;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server 4BRI Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2,(unsigned int *) &dwRAM);
dwRAM &= 0xFFC00000;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1,(unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFF00;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0,(unsigned int *) &dwCFG);
dwCFG &= 0xFFFFFF00;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_3,(unsigned int *) &dwCTL);
dwCTL &= 0xFFFFE000;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
/* Retrieve the serial number */
pcibios_write_config_word(byBus,byFunc,0x4E,0x00FC);
for (j=0, PCItmp=0; j<10000 && !PCItmp; j++)
{
pcibios_read_config_word(byBus,byFunc,0x4E, &PCItmp);
PCItmp &= 0x8000; // extract done flag
}
pcibios_read_config_dword(byBus,byFunc,0x50, &PCIserial);
Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x400000);
Card.memory[DIVAS_CTL_MEMORY] = ioremap(dwCTL, 0x2000);
Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x100);
Card.io_base=dwDivasIOBase;
Card.irq = byIRQ;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_Q;
Card.bus_type = DIA_BUS_TYPE_PCI;
FPGA_Done = 0;
/* Create four virtual card structures as we want to treat
the 4Bri card as 4 Bri cards*/
for(i=0;i<4;i++)
{
b=Card.memory[DIVAS_RAM_MEMORY];
b+=(MQ_PROTCODE_OFFSET) * (i==0?0:1);
DPRINTF(("divas: offset = 0x%x", i* MQ_PROTCODE_OFFSET));
Card.memory[DIVAS_RAM_MEMORY]=b;
b = Card.memory[DIVAS_RAM_MEMORY];
b += MQ_SM_OFFSET;
Card.memory[DIVAS_SHARED_MEMORY] = b;
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
/* Fill in Name */
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'Q';
Card.name[6] = '0' + i;
Card.name[7] = '\0';
Card.serial = PCIserial;
Card.card_id = wNumCards;
if (DivasCardNew(&Card) != 0)
{
// Force for loop to terminate
i = 4;
continue;
}
wNumCards++;
}//for
}
wDeviceIndex++;
}
wDeviceIndex = 0;
while (wDeviceIndex < 10)
{
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_MAESTRA,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwPLXIOBase, dwDivasIOBase;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server BRI (S/T) Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
dwPLXIOBase &= 0xFFFFFF80;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFFFC;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
Card.card_id = wNumCards;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
Card.bus_type = DIA_BUS_TYPE_PCI;
Card.irq = byIRQ;
Card.reset_base = dwPLXIOBase;
Card.io_base = dwDivasIOBase;
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'B';
Card.name[6] = '\0';
if (check_region(Card.io_base, 0x20))
{
printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
wDeviceIndex++;
continue;
}
if (check_region(Card.reset_base, 0x80))
{
printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
wDeviceIndex++;
continue;
}
if (DivasCardNew(&Card) != 0)
{
wDeviceIndex++;
continue;
}
wNumCards++;
}
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_MAESTRAQ_U,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwPLXIOBase, dwDivasIOBase;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server BRI (U) Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
dwPLXIOBase &= 0xFFFFFF80;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFFFC;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
Card.card_id = wNumCards;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER_B;
Card.bus_type = DIA_BUS_TYPE_PCI;
Card.irq = byIRQ;
Card.reset_base = dwPLXIOBase;
Card.io_base = dwDivasIOBase;
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'B';
Card.name[6] = '\0';
if (check_region(Card.io_base, 0x20))
{
printk(KERN_WARNING "Divas: DIVA I/O Base already in use 0x%x-0x%x\n", Card.io_base, Card.io_base + 0x1F);
wDeviceIndex++;
continue;
}
if (check_region(Card.reset_base, 0x80))
{
printk(KERN_WARNING "Divas: PLX I/O Base already in use 0x%x-0x%x\n", Card.reset_base, Card.reset_base + 0x7F);
wDeviceIndex++;
continue;
}
if (DivasCardNew(&Card) != 0)
{
wDeviceIndex++;
continue;
}
wNumCards++;
}
wDeviceIndex++;
}
wDeviceIndex = 0;
while (wDeviceIndex < 10)
{
wPCIConsultation = pcibios_find_device(PCI_VENDOR_ID_EICON,
PCI_DEVICE_ID_EICON_MAESTRAP,
wDeviceIndex,
&byBus, &byFunc);
if (wPCIConsultation == PCIBIOS_SUCCESSFUL)
{
dword dwRAM, dwREG, dwCFG;
byte byIRQ;
printk(KERN_DEBUG "Divas: DIVA Server PRI Found\n");
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_0, (unsigned int *) &dwRAM);
dwRAM &= 0xFFFFF000;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwREG);
dwREG &= 0xFFFFF000;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_4, (unsigned int *) &dwCFG);
dwCFG &= 0xFFFFF000;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
Card.memory[DIVAS_RAM_MEMORY] = ioremap(dwRAM, 0x10000);
Card.memory[DIVAS_REG_MEMORY] = ioremap(dwREG, 0x4000);
Card.memory[DIVAS_CFG_MEMORY] = ioremap(dwCFG, 0x1000);
Card.memory[DIVAS_SHARED_MEMORY] = Card.memory[DIVAS_RAM_MEMORY] + DIVAS_SHARED_OFFSET;
/* pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_1, (unsigned int *) &dwPLXIOBase);
dwPLXIOBase &= 0xFFFFFFFc;
pcibios_read_config_dword(byBus, byFunc, PCI_BASE_ADDRESS_2, (unsigned int *) &dwDivasIOBase);
dwDivasIOBase &= 0xFFFFFF80;
pcibios_read_config_byte(byBus, byFunc, PCI_INTERRUPT_LINE, &byIRQ);
*/
Card.card_id = wNumCards;
Card.card_type = DIA_CARD_TYPE_DIVA_SERVER;
Card.bus_type = DIA_BUS_TYPE_PCI;
Card.irq = byIRQ;
/* Card.reset_base = dwPLXIOBase;
Card.io_base = dwDivasIOBase;*/
Card.bus_num = byBus;
Card.func_num = byFunc;
Card.slot = -1;
Card.name[0] = 'D';
Card.name[1] = 'I';
Card.name[2] = 'V';
Card.name[3] = 'A';
Card.name[4] = 'S';
Card.name[5] = 'P';
Card.name[6] = '\0';
if (DivasCardNew(&Card) != 0)
{
wDeviceIndex++;
continue;
}
wNumCards++;
}
wDeviceIndex++;
}
printk(KERN_INFO "Divas: %d cards detected\n", wNumCards);
if(wNumCards == 0)
{
return -1;
}
Divas_fops.ioctl = do_ioctl;
Divas_fops.poll = do_poll;
Divas_fops.read = do_read;
Divas_fops.open = do_open;
Divas_fops.release = do_release;
Divas_major = register_chrdev(0, "Divas", &Divas_fops);
if (Divas_major < 0)
{
printk(KERN_WARNING "Divas: Unable to register character driver\n");
return -1;
}
return 0;
}
/* Error return -1 */
int DivasConfigGet(dia_card_t *card)
{
/* Retrieve Config from O/S? Not in Linux */
return 0;
}
dia_config_t *DivasConfig(card_t *card, dia_config_t *config)
{
/* If config retrieved from OS then copy the data into a dia_config_t structure here
and return the pointer here. If the config 'came from above' then just
return config;
*/
return config;
}

201
drivers/isdn/eicon/linchr.c Normal file
View File

@ -0,0 +1,201 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.12
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define __NO_VERSION__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/slab.h>
#undef N_DATA
#include "adapter.h"
#include "divas.h"
#include "divalog.h"
extern int DivasCardNext;
void UxPause(long ms);
int DivasGetMem(mem_block_t *);
#define DIA_IOCTL_UNLOCK 12
void UnlockDivas(void);
int do_ioctl(struct inode *pDivasInode, struct file *pDivasFile,
unsigned int command, unsigned long arg)
{
byte *pUserCards, card_i;
word wCardNum;
switch (command)
{
case DIA_IOCTL_CONFIG:
{
dia_config_t DivaConfig;
if (copy_from_user(&DivaConfig, (void *)arg, sizeof(dia_config_t)))
return -EFAULT;
DivasCardConfig(&DivaConfig);
return 0;
}
case DIA_IOCTL_DETECT:
pUserCards = (byte *) arg;
if (!verify_area(VERIFY_WRITE, pUserCards, 20))
{
if(__put_user(DivasCardNext, pUserCards++))
return -EFAULT;
for (card_i=1; card_i < 20; card_i++)
{
if(__put_user((byte) DivasCards[card_i - 1].cfg.card_type, pUserCards++))
return -EFAULT;
}
}
else return -EFAULT;
return 0;
case DIA_IOCTL_START:
{
dia_start_t DivaStart;
if (copy_from_user(&DivaStart, (void *)arg, sizeof(dia_start_t)))
return -EFAULT;
return DivasCardStart(DivaStart.card_id);
}
case DIA_IOCTL_FLAVOUR:
return 0;
case DIA_IOCTL_LOAD:
{
dia_load_t DivaLoad;
if(copy_from_user(&DivaLoad, (void *)arg, sizeof(dia_load_t)))
return -EFAULT;
if (!verify_area(VERIFY_READ, DivaLoad.code,DivaLoad.length))
{
if (DivasCardLoad(&DivaLoad))
{
printk(KERN_WARNING "Divas: Error loading DIVA Server adapter\n");
return -EINVAL;
}
return 0;
}
return -EFAULT;
}
case DIA_IOCTL_LOG:
{
dia_log_t DivaLog;
if (copy_from_user(&DivaLog, (void *) arg, sizeof(dia_log_t)))
return -EFAULT;
DivasLog(&DivaLog);
return 0;
}
case DIA_IOCTL_XLOG_REQ:
if(get_user(wCardNum, (word *) arg))
return -EFAULT;
DivasXlogReq(wCardNum);
return 0;
case DIA_IOCTL_GET_NUM:
if(put_user(DivasCardNext, (int *)arg))
return -EFAULT;
return 0;
case DIA_IOCTL_GET_LIST:
{
dia_card_list_t cards;
DPRINTF(("divas: DIA_IOCTL_GET_LIST"));
DivasGetList(&cards);
if(copy_to_user((void *)arg, &cards, sizeof(cards)))
return -EFAULT;
return 0;
}
case DIA_IOCTL_GET_MEM:
{
mem_block_t mem_block;
if (copy_from_user(&mem_block, (void *)arg, sizeof(mem_block_t)))
return -EFAULT;
DivasGetMem(&mem_block);
return 0;
}
case DIA_IOCTL_UNLOCK:
UnlockDivas();
return 0;
default:
return -EINVAL;
}
return -EINVAL;
}
unsigned int do_poll(struct file *pFile, struct poll_table_struct *pPollTable)
{
word wMask = 0;
if (!DivasLogFifoEmpty())
wMask |= POLLIN | POLLRDNORM;
return wMask;
}
ssize_t do_read(struct file *pFile, char *pUserBuffer, size_t BufferSize, loff_t *pOffset)
{
klog_t *pClientLogBuffer = (klog_t *) pUserBuffer;
klog_t *pHeadItem;
if (BufferSize < sizeof(klog_t))
{
printk(KERN_WARNING "Divas: Divalog buffer specifed a size that is too small (%d - %d required)\n",
BufferSize, sizeof(klog_t));
return -EIO;
}
pHeadItem = (klog_t *) DivasLogFifoRead();
if (pHeadItem)
{
memcpy(pClientLogBuffer, pHeadItem, sizeof(klog_t));
kfree(pHeadItem);
return sizeof(klog_t);
}
return 0;
}
static int private_usage_count;
int do_open(struct inode *pInode, struct file *pFile)
{
MOD_INC_USE_COUNT;
#ifdef MODULE
private_usage_count++;
#endif
return 0;
}
int do_release(struct inode *pInode, struct file *pFile)
{
MOD_DEC_USE_COUNT;
#ifdef MODULE
private_usage_count--;
#endif
return 0;
}
void UnlockDivas(void)
{
while (private_usage_count > 0)
{
private_usage_count--;
MOD_DEC_USE_COUNT;
}
}

734
drivers/isdn/eicon/linio.c Normal file
View File

@ -0,0 +1,734 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.16
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define N_DATA
#include <asm/io.h>
#include <asm/system.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/isdn_compat.h>
#undef N_DATA
#include "uxio.h"
static
int log_on=0;
int Divasdevflag = 0;
//spinlock_t diva_lock = SPIN_LOCK_UNLOCKED;
static
ux_diva_card_t card_pool[MAX_CARDS];
void UxPause(long int ms)
{
int timeout = jiffies + ((ms * HZ) / 1000);
while (time_before(jiffies, timeout));
}
int UxCardHandleGet(ux_diva_card_t **card, dia_card_t *cfg)
{
int i;
ux_diva_card_t *c;
if (cfg->bus_type != DIA_BUS_TYPE_PCI)
{
DPRINTF(("divas hw: type not PCI (%d)", cfg->bus_type));
return -1;
}
for (i = 0; (i < DIM(card_pool)) && (card_pool[i].in_use); i++)
{
;
}
if (i == DIM(card_pool))
{
DPRINTF(("divas hw: card_pool exhausted"));
return -1;
}
c = *card = &card_pool[i];
switch (cfg->bus_type)
{
case DIA_BUS_TYPE_PCI:
c->bus_num = cfg->bus_num;
c->func_num = cfg->func_num;
c->io_base = cfg->io_base;
c->reset_base = cfg->reset_base;
c->card_type = cfg->card_type;
c->mapped = NULL;
c->slot = cfg->slot;
c->irq = (int) cfg->irq;
c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
c->pCONTROL = cfg->memory[DIVAS_CTL_MEMORY];
/* c->bus_type = DIA_BUS_TYPE_PCI;
c->bus_num = cfg->bus_num & 0x3f;
c->slot = cfg->slot;
c->irq = (int) cfg->irq;
c->int_priority = (int) cfg->int_priority;
c->card_type = cfg->card_type;
c->io_base = cfg->io_base;
c->reset_base = cfg->reset_base;
c->pDRAM = cfg->memory[DIVAS_RAM_MEMORY];
c->pDEVICES = cfg->memory[DIVAS_REG_MEMORY];
c->pCONFIG = cfg->memory[DIVAS_CFG_MEMORY];
c->pSHARED = cfg->memory[DIVAS_SHARED_MEMORY];
DPRINTF(("divas hw: pDRAM is 0x%x", c->pDRAM));
DPRINTF(("divas hw: pSHARED is 0x%x", c->pSHARED));
DPRINTF(("divas hw: pCONFIG is 0x%x", c->pCONFIG));
c->cm_key = cm_getbrdkey("Divas", cfg->card_id);*/
break;
default:
break;
}
c->in_use = TRUE;
return 0;
}
void UxCardHandleFree(ux_diva_card_t *card)
{
card->in_use = FALSE;
}
#define PLX_IOBASE 0
#define DIVAS_IOBASE 1
void *UxCardMemAttach(ux_diva_card_t *card, int id)
{
if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER)
{
switch (id)
{
case DIVAS_SHARED_MEMORY:
card->mapped = card->pSHARED;
return card->pSHARED;
break;
case DIVAS_RAM_MEMORY:
card->mapped = card->pDRAM;
return card->pDRAM;
break;
case DIVAS_REG_MEMORY:
card->mapped = card->pDEVICES;
return card->pDEVICES;
break;
case DIVAS_CFG_MEMORY:
card->mapped = card->pCONFIG;
return card->pCONFIG;
break;
default:
ASSERT(FALSE);
card->mapped = NULL;
return (void *) 0;
}
}
else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_B)
{
switch (id)
{
case PLX_IOBASE:
return (void *) card->reset_base;
break;
case DIVAS_IOBASE:
return (void *) card->io_base;
break;
default:
ASSERT(FALSE);
return 0;
}
}
else if (card->card_type == DIA_CARD_TYPE_DIVA_SERVER_Q)
{
switch (id)
{
case DIVAS_SHARED_MEMORY:
card->mapped = card->pSHARED;
return card->pSHARED;
break;
case DIVAS_RAM_MEMORY:
card->mapped = card->pDRAM;
return card->pDRAM;
break;
case DIVAS_REG_MEMORY:
card->mapped = (void *) card->io_base;
return (void *) card->io_base;
break;
case DIVAS_CTL_MEMORY:
card->mapped = card->pCONTROL;
return card->pCONTROL;
break;
default:
// ASSERT(FALSE);
DPRINTF(("divas: Trying to attach to mem %d", id));
card->mapped = NULL;
return (void *) 0;
}
} else
DPRINTF(("divas: Tried to attach to unknown card"));
/* Unknown card type */
return NULL;
}
void UxCardMemDetach(ux_diva_card_t *card, void *address)
{
return; // Just a place holder. No un-mapping done.
}
void UxCardLog(int turn_on)
{
log_on = turn_on;
}
/*
* Control Register I/O Routines to be performed on Attached I/O ports
*/
void UxCardPortIoOut(ux_diva_card_t *card, void *AttachedBase, int offset, byte the_byte)
{
word base = (word) (dword) AttachedBase;
base += offset;
outb(the_byte, base);
}
void UxCardPortIoOutW(ux_diva_card_t *card, void *AttachedBase, int offset, word the_word)
{
word base = (word) (dword) AttachedBase;
base += offset;
outw(the_word, base);
}
void UxCardPortIoOutD(ux_diva_card_t *card, void *AttachedBase, int offset, dword the_dword)
{
word base = (word) (dword) AttachedBase;
base += offset;
outl(the_dword, base);
}
byte UxCardPortIoIn(ux_diva_card_t *card, void *AttachedBase, int offset)
{
word base = (word) (dword) AttachedBase;
base += offset;
return inb(base);
}
word UxCardPortIoInW(ux_diva_card_t *card, void *AttachedBase, int offset)
{
word base = (word) (dword) AttachedBase;
base += offset;
return inw(base);
}
/*
* Memory mapped card I/O functions
*/
byte UxCardMemIn(ux_diva_card_t *card, void *address)
{
byte b;
volatile byte* t = (byte*)address;
b = *t;
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: read 0x%02x from 0x%x (memory mapped)", b & 0xff, a));
}
return(b);
}
word UxCardMemInW(ux_diva_card_t *card, void *address)
{
word w;
volatile word* t = (word*)address;
w = *t;
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: read 0x%04x from 0x%x (memory mapped)", w & 0xffff, a));
}
return (w);
}
dword UxCardMemInD(ux_diva_card_t *card, void *address)
{
dword dw;
volatile dword* t = (dword*)address;
dw = *t;
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: read 0x%08x from 0x%x (memory mapped)", dw, a));
}
return (dw);
}
void UxCardMemInBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
{
volatile byte *pSource = address;
byte *pDest = buffer;
while (length--)
{
*pDest++ = *pSource++;
}
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
pDest = buffer;
DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (memory mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
a));
}
return;
}
void UxCardMemOut(ux_diva_card_t *card, void *address, byte data)
{
volatile byte* t = (byte*)address;
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: wrote 0x%02x to 0x%x (memory mapped)", data & 0xff, a));
}
*t = data;
return;
}
void UxCardMemOutW(ux_diva_card_t *card, void *address, word data)
{
volatile word* t = (word*)address;
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: wrote 0x%04x to 0x%x (memory mapped)", data & 0xffff, a));
}
*t = data;
return;
}
void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data)
{
volatile dword* t = (dword*)address;
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
DPRINTF(("divas hw: wrote 0x%08x to 0x%x (memory mapped)", data, a));
}
*t = data;
return;
}
void UxCardMemOutBuffer(ux_diva_card_t *card, void *address, void *buffer, int length)
{
byte *pSource = buffer;
byte *pDest = address;
while (length--)
{
*pDest++ = *pSource++;
}
if (log_on)
{
byte *a = address;
a -= (int) card->mapped;
pDest = buffer;
DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (memory mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
a));
}
return;
}
/*
* Memory mapped card I/O functions
*/
byte UxCardIoIn(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{
byte the_byte;
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
the_byte = inb(card->io_base);
if (log_on)
{
DPRINTF(("divas hw: read 0x%02x from 0x%x (I/O mapped)",
the_byte & 0xff, address));
}
return the_byte;
}
word UxCardIoInW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{
word the_word;
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
the_word = inw(card->io_base);
if (log_on)
{
DPRINTF(("divas hw: read 0x%04x from 0x%x (I/O mapped)",
the_word & 0xffff, address));
}
return the_word;
}
dword UxCardIoInD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address)
{
dword the_dword;
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
the_dword = inl(card->io_base);
if (log_on)
{
DPRINTF(("divas hw: read 0x%08x from 0x%x (I/O mapped)",
the_dword, address));
}
return the_dword;
}
void UxCardIoInBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
{
byte *pSource = address;
byte *pDest = buffer;
if ((word) (dword) address & 0x1)
{
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pSource, card->io_base + 4);
*pDest = (byte) inb(card->io_base);
pDest++;
pSource++;
length--;
if (!length)
{
return;
}
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pSource, card->io_base + 4);
insw(card->io_base, (word *)pDest,length%2 ? (length+1)>>1 : length>>1);
if (log_on)
{
pDest = buffer;
DPRINTF(("divas hw: read %02x %02x %02x %02x %02x %02x %02x %02x from 0x%x (I/O mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
address));
}
return;
}
/* Output */
void UxCardIoOut(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, byte data)
{
if (log_on)
{
DPRINTF(("divas hw: wrote 0x%02x to 0x%x (I/O mapped)",
data & 0xff, address));
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
outb((byte) data & 0xFF, card->io_base);
return;
}
void UxCardIoOutW(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, word data)
{
if (log_on)
{
DPRINTF(("divas hw: wrote 0x%04x to 0x%x (I/O mapped)",
data & 0xffff, address));
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
outw((word) data & 0xFFFF, card->io_base);
return;
}
void UxCardIoOutD(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, dword data)
{
if (log_on)
{
DPRINTF(("divas hw: wrote 0x%08x to 0x%x (I/O mapped)", data, address));
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) address, card->io_base + 4);
outl((dword) data & 0xFFFFFFFF, card->io_base);
return;
}
void UxCardIoOutBuffer(ux_diva_card_t *card, void *AttachedDivasIOBase, void *address, void *buffer, int length)
{
byte *pSource = buffer;
byte *pDest = address;
if ((word) (dword) address & 1)
{
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pDest, card->io_base + 4);
outb(*pSource, card->io_base);
pSource++;
pDest++;
length--;
if (!length)
{
return;
}
}
outb(0xFF, card->io_base + 0xC);
outw((word) (dword) pDest, card->io_base + 4);
outsw(card->io_base, (word *)pSource, length%2 ? (length+1)>>1 : length>>1);
if (log_on)
{
pDest = buffer;
DPRINTF(("divas hw: wrote %02x %02x %02x %02x %02x %02x %02x %02x to 0x%x (I/O mapped)",
pDest[0] & 0xff, pDest[1] & 0xff, pDest[2] & 0xff, pDest[3] & 0xff,
pDest[4] & 0xff, pDest[5] & 0xff, pDest[6] & 0xff, pDest[7] & 0xff,
address));
}
return;
}
void Divasintr(int arg, void *unused, struct pt_regs *unused_regs)
{
int i;
card_t *card = NULL;
ux_diva_card_t *ux_ref = NULL;
for (i = 0; i < DivasCardNext; i++)
{
if (arg == DivasCards[i].cfg.irq)
{
card = &DivasCards[i];
ux_ref = card->hw;
if ((ux_ref) && (card->is_live))
{
(*ux_ref->user_isr)(ux_ref->user_isr_arg);
}
else
{
DPRINTF(("divas: ISR couldn't locate card"));
}
}
}
return;
}
int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg)
{
int result;
card->user_isr = isr_fn;
card->user_isr_arg = isr_arg;
result = request_irq(card->irq, Divasintr, SA_INTERRUPT | SA_SHIRQ, "Divas", (void *) isr_arg);
return result;
}
void UxIsrRemove(ux_diva_card_t *card, void *dev_id)
{
free_irq(card->irq, card->user_isr_arg);
}
void UxPciConfigWrite(ux_diva_card_t *card, int size, int offset, void *value)
{
switch (size)
{
case sizeof(byte):
pcibios_write_config_byte(card->bus_num, card->func_num, offset, * (byte *) value);
break;
case sizeof(word):
pcibios_write_config_word(card->bus_num, card->func_num, offset, * (word *) value);
break;
case sizeof(dword):
pcibios_write_config_dword(card->bus_num, card->func_num, offset, * (dword *) value);
break;
default:
printk(KERN_WARNING "Divas: Invalid size in UxPciConfigWrite\n");
}
}
void UxPciConfigRead(ux_diva_card_t *card, int size, int offset, void *value)
{
switch (size)
{
case sizeof(byte):
pcibios_read_config_byte(card->bus_num, card->func_num, offset, (byte *) value);
break;
case sizeof(word):
pcibios_read_config_word(card->bus_num, card->func_num, offset, (word *) value);
break;
case sizeof(dword):
pcibios_read_config_dword(card->bus_num, card->func_num, offset, (unsigned int *) value);
break;
default:
printk(KERN_WARNING "Divas: Invalid size in UxPciConfigRead\n");
}
}
void *UxAlloc(unsigned int size)
{
void *m;
m = kmalloc(size, GFP_ATOMIC);
return m;
}
void UxFree(void *ptr)
{
kfree(ptr);
}
long UxCardLock(ux_diva_card_t *card)
{
unsigned long flags;
//spin_lock_irqsave(&diva_lock, flags);
save_flags(flags);
cli();
return flags;
}
void UxCardUnlock(ux_diva_card_t *card, long ipl)
{
//spin_unlock_irqrestore(&diva_lock, ipl);
restore_flags(ipl);
}
dword UxTimeGet(void)
{
return jiffies;
}
long UxInterlockedIncrement(ux_diva_card_t *card, long *dst)
{
register volatile long *p;
register long ret;
int ipl;
p =dst;
ipl = UxCardLock(card);
*p += 1;
ret = *p;
UxCardUnlock(card,ipl);
return(ret);
}
long UxInterlockedDecrement(ux_diva_card_t *card, long *dst)
{
register volatile long *p;
register long ret;
int ipl;
p =dst;
ipl = UxCardLock(card);
*p -= 1;
ret = *p;
UxCardUnlock(card,ipl);
return(ret);
}

141
drivers/isdn/eicon/linsys.c Normal file
View File

@ -0,0 +1,141 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.10
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include <linux/sched.h>
#undef N_DATA
#include <linux/tqueue.h>
#include <linux/smp.h>
struct pt_regs;
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include "sys.h"
#include "divas.h"
#include "adapter.h"
#include "divalog.h"
#include "uxio.h"
int Divas4BRIInitPCI(card_t *card, dia_card_t *cfg)
{
/* Use UxPciConfigWrite routines to initialise PCI config space */
/* wPCIcommand = 0x03;
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
wPCIcommand = 0x280;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
bPCIcommand = 0x30;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
*/
return 0;
}
int DivasPRIInitPCI(card_t *card, dia_card_t *cfg)
{
/* Use UxPciConfigWrite routines to initialise PCI config space */
/* wPCIcommand = 0x03;
cm_write_devconfig16(CMKey, PCI_COMMAND, &wPCIcommand);
wPCIcommand = 0x280;
cm_write_devconfig16(CMKey, PCI_STATUS, &wPCIcommand);
bPCIcommand = 0x30;
cm_write_devconfig8(CMKey, PCI_LATENCY, &bPCIcommand);*/
return 0;
}
int DivasBRIInitPCI(card_t *card, dia_card_t *cfg)
{
/* Need to set these platform dependent values after patching */
card->hw->reset_base = card->cfg.reset_base;
card->hw->io_base = card->cfg.io_base;
request_region(card->hw->reset_base,0x80,"Divas");
request_region(card->hw->io_base,0x20,"Divas");
/* Same as for PRI */
return DivasPRIInitPCI(card, cfg);
}
/* ######################### Stubs of routines that are not done yet ################## */
/*void DivasLogIdi(card_t *card, ENTITY *e, int request)
{
}
*/
int DivasDpcSchedule(void)
{
static struct tq_struct DivasTask;
DivasTask.routine = DivasDoDpc;
DivasTask.data = (void *) 0;
queue_task(&DivasTask, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return 0;
}
int DivasScheduleRequestDpc(void)
{
static struct tq_struct DivasTask;
DivasTask.routine = DivasDoRequestDpc;
DivasTask.data = (void *) 0;
queue_task(&DivasTask, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return 0;
}
void DivasLogAdd(void *buffer, int length)
{
static
boolean_t overflow = FALSE;
static
boolean_t busy = FALSE;
/* make sure we're not interrupting ourselves */
if (busy)
{
printk(KERN_DEBUG "Divas: Logging interrupting self !\n");
return;
}
busy = TRUE;
/* ignore call if daemon isn't running and we've reached limit */
if (DivasLogFifoFull())
{
if (!overflow)
{
printk(KERN_DEBUG "Divas: Trace buffer full\n");
overflow = TRUE;
}
busy = FALSE;
return;
}
DivasLogFifoWrite(buffer, length);
busy = FALSE;
return;
}
/* #################################################################################### */

160
drivers/isdn/eicon/log.c Normal file
View File

@ -0,0 +1,160 @@
/*
* Source file for diva log facility
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.5
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "adapter.h"
#include "divalog.h"
#include "uxio.h"
/*Counter to monitor number of messages */
static int m_count;
#define MAX_BUFFERED_MSGS (1000)
/* Our Linked List Structure to hold message */
typedef struct klog_link{
klog_t klog;
struct klog_link *next;
}KNODE;
/* First & Last structures in list*/
KNODE *head;
KNODE *tail;
/*
* retrieve message from FIFO buffer
* returns NULL if buffer empty
* otherwise returns pointer to entry
*/
char *DivasLogFifoRead(void)
{
KNODE *old_head;
if(head==NULL)
{
/* Buffer Empty - No Messages */
return NULL;
}
m_count--;
/* Keep track of message to be read & increment to next message*/
old_head = head;
head = head->next;
/*Return ptr to Msg */
return((char *)old_head);
}
/*
* write message into FIFO buffer
*/
void DivasLogFifoWrite(char *entry, int length)
{
KNODE *new_klog;
if(head == NULL)
{
/* No Entries in Log */
tail=NULL;
m_count=0;
new_klog=UxAlloc(sizeof(KNODE));
if(new_klog==NULL)
{
return;
}
m_count++;
memset(new_klog, 0, sizeof(KNODE));
/* Set head & tail to point to the new Msg Struct */
head=tail=new_klog;
tail->next=NULL;
}
else
{
new_klog=UxAlloc(sizeof(KNODE));
if(new_klog==NULL)
{
return;
}
m_count++;
memset(new_klog, 0, sizeof(KNODE));
/* Let last Msg Struct point to new Msg Struct & inc tail */
tail->next=new_klog;
tail=new_klog;
tail->next=NULL;
}
if (length > sizeof(klog_t))
{
length = sizeof(klog_t);
}
memcpy(&tail->klog, entry, length);
return;
}
/*
* DivaslogFifoEmpty:return TRUE if FIFO buffer is empty,otherwise FALSE
*/
int DivasLogFifoEmpty(void)
{
return (m_count == 0);
}
/*
*DivasLogFifoFull:return TRUE if FIFO buffer is full,otherwise FALSE
*/
int DivasLogFifoFull(void)
{
return (m_count == MAX_BUFFERED_MSGS);
}
/*
* generate an IDI log entry
*/
void DivasLogIdi(card_t *card, ENTITY *e, int request)
{
klog_t klog;
memset(&klog, 0, sizeof(klog));
klog.time_stamp = UxTimeGet();
klog.length = sizeof(ENTITY) > sizeof(klog.buffer) ?
sizeof(klog.buffer) : sizeof(ENTITY);
klog.card = (int) (card - DivasCards);
klog.type = request ? KLOG_IDI_REQ : KLOG_IDI_CALLBACK;
klog.code = 0;
memcpy(klog.buffer, e, klog.length);
/* send to the log driver and return */
DivasLogAdd(&klog, sizeof(klog));
return;
}

297
drivers/isdn/eicon/pc.h Normal file
View File

@ -0,0 +1,297 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef PC_H_INCLUDED
#define PC_H_INCLUDED
#define byte unsigned char
#define word unsigned short
#define dword unsigned long
/*------------------------------------------------------------------*/
/* buffer definition */
/*------------------------------------------------------------------*/
typedef struct {
word length; /* length of data/parameter field */
byte P[270]; /* data/parameter field */
} PBUFFER;
/*------------------------------------------------------------------*/
/* dual port ram structure */
/*------------------------------------------------------------------*/
struct dual
{
byte Req; /* request register */
byte ReqId; /* request task/entity identification */
byte Rc; /* return code register */
byte RcId; /* return code task/entity identification */
byte Ind; /* Indication register */
byte IndId; /* Indication task/entity identification */
byte IMask; /* Interrupt Mask Flag */
byte RNR; /* Receiver Not Ready (set by PC) */
byte XLock; /* XBuffer locked Flag */
byte Int; /* ISDN-S interrupt */
byte ReqCh; /* Channel field for layer-3 Requests */
byte RcCh; /* Channel field for layer-3 Returncodes */
byte IndCh; /* Channel field for layer-3 Indications */
byte MInd; /* more data indication field */
word MLength; /* more data total packet length */
byte ReadyInt; /* request field for ready interrupt */
byte SWReg; /* Software register for special purposes */
byte Reserved[11]; /* reserved space */
byte InterfaceType; /* interface type 1=16K interface */
word Signature; /* ISDN-S adapter Signature (GD) */
PBUFFER XBuffer; /* Transmit Buffer */
PBUFFER RBuffer; /* Receive Buffer */
};
/*------------------------------------------------------------------*/
/* SWReg Values (0 means no command) */
/*------------------------------------------------------------------*/
#define SWREG_DIE_WITH_LEDON 0x01
#define SWREG_HALT_CPU 0x02 /* Push CPU into a while(1) loop */
/*------------------------------------------------------------------*/
/* Id Fields Coding */
/*------------------------------------------------------------------*/
#define ID_MASK 0xe0 /* Mask for the ID field */
#define GL_ERR_ID 0x1f /* ID for error reporting on global requests*/
#define DSIG_ID 0x00 /* ID for D-channel signaling */
#define NL_ID 0x20 /* ID for network-layer access (B or D) */
#define BLLC_ID 0x60 /* ID for B-channel link level access */
#define TASK_ID 0x80 /* ID for dynamic user tasks */
#define TIMER_ID 0xa0 /* ID for timer task */
#define TEL_ID 0xc0 /* ID for telephone support */
#define MAN_ID 0xe0 /* ID for management */
/*------------------------------------------------------------------*/
/* ASSIGN and REMOVE requests are the same for all entities */
/*------------------------------------------------------------------*/
#define ASSIGN 0x01
#define UREMOVE 0xfe /* without returncode */
#define REMOVE 0xff
/*------------------------------------------------------------------*/
/* Timer Interrupt Task Interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TIM 0x01
#define REMOVE_TIM 0xff
/*------------------------------------------------------------------*/
/* dynamic user task interface */
/*------------------------------------------------------------------*/
#define ASSIGN_TSK 0x01
#define REMOVE_TSK 0xff
#define LOAD 0xf0
#define RELOCATE 0xf1
#define START 0xf2
#define LOAD2 0xf3
#define RELOCATE2 0xf4
/*------------------------------------------------------------------*/
/* dynamic user task messages */
/*------------------------------------------------------------------*/
#define TSK_B2 0x0000
#define TSK_WAKEUP 0x2000
#define TSK_TIMER 0x4000
#define TSK_TSK 0x6000
#define TSK_PC 0xe000
/*------------------------------------------------------------------*/
/* LL management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_LL 1 /* assign logical link */
#define REMOVE_LL 0xff /* remove logical link */
/*------------------------------------------------------------------*/
/* LL service primitives */
/*------------------------------------------------------------------*/
#define LL_UDATA 1 /* link unit data request/indication */
#define LL_ESTABLISH 2 /* link establish request/indication */
#define LL_RELEASE 3 /* link release request/indication */
#define LL_DATA 4 /* data request/indication */
#define LL_LOCAL 5 /* switch to local operation (COM only) */
#define LL_DATA_PEND 5 /* data pending indication (SDLC SHM only) */
#define LL_REMOTE 6 /* switch to remote operation (COM only) */
#define LL_TEST 8 /* link test request */
#define LL_MDATA 9 /* more data request/indication */
#define LL_BUDATA 10 /* broadcast unit data request/indication */
#define LL_XID 12 /* XID command request/indication */
#define LL_XID_R 13 /* XID response request/indication */
/*------------------------------------------------------------------*/
/* NL service primitives */
/*------------------------------------------------------------------*/
#define N_MDATA 1 /* more data to come REQ/IND */
#define N_CONNECT 2 /* OSI N-CONNECT REQ/IND */
#define N_CONNECT_ACK 3 /* OSI N-CONNECT CON/RES */
#define N_DISC 4 /* OSI N-DISC REQ/IND */
#define N_DISC_ACK 5 /* OSI N-DISC CON/RES */
#define N_RESET 6 /* OSI N-RESET REQ/IND */
#define N_RESET_ACK 7 /* OSI N-RESET CON/RES */
#define N_DATA 8 /* OSI N-DATA REQ/IND */
#define N_EDATA 9 /* OSI N-EXPEDITED DATA REQ/IND */
#define N_UDATA 10 /* OSI D-UNIT-DATA REQ/IND */
#define N_BDATA 11 /* BROADCAST-DATA REQ/IND */
#define N_DATA_ACK 12 /* data ack ind for D-bit procedure */
#define N_EDATA_ACK 13 /* data ack ind for INTERRUPT */
#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 */
/*------------------------------------------------------------------*/
/* Signaling management primitives */
/*------------------------------------------------------------------*/
#define ASSIGN_SIG 1 /* assign signaling task */
#define UREMOVE_SIG 0xfe /* remove signaling task without returncode */
#define REMOVE_SIG 0xff /* remove signaling task */
/*------------------------------------------------------------------*/
/* Signaling service primitives */
/*------------------------------------------------------------------*/
#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 FACILITY_REQ 22 /* send a Facility Message type */
#define FACILITY_IND 22 /* Facility Message type indication */
#define SIG_CTRL 29 /* Control for signalling hardware */
#define DSP_CTRL 30 /* Control for DSPs */
#define LAW_REQ 31 /* Law config request for (returns info_i) */
/*------------------------------------------------------------------*/
/* management service primitives */
/*------------------------------------------------------------------*/
#define MAN_READ 2
#define MAN_WRITE 3
#define MAN_EXECUTE 4
#define MAN_EVENT_ON 5
#define MAN_EVENT_OFF 6
#define MAN_LOCK 7
#define MAN_UNLOCK 8
#define MAN_INFO_IND 2
#define MAN_EVENT_IND 3
#define MAN_TRACE_IND 4
#define MAN_ESC 0x80
/*------------------------------------------------------------------*/
/* 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 /* ISDN-S card out of res. */
#define ADAPTER_DEAD 0x08 /* ISDN card CPU halted */
#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 */
/*------------------------------------------------------------------*/
/* information elements */
/*------------------------------------------------------------------*/
#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 DT 0x29 /* ETSI date/time */
#define KEY 0x2c /* keypad information element */
#define FTY 0x1c /* facility 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 RDX 0x73 /* redirected number extended */
#define RDN 0x74 /* redirected 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 */
/*------------------------------------------------------------------*/
/* TEL_CTRL contents */
/*------------------------------------------------------------------*/
#define RING_ON 0x01
#define RING_OFF 0x02
#define HANDS_FREE_ON 0x03
#define HANDS_FREE_OFF 0x04
#define ON_HOOK 0x80
#define OFF_HOOK 0x90
#endif

View File

@ -0,0 +1,148 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#ifndef PC_MAINT_H
#define PC_MAINT_H
#if !defined(MIPS_SCOM)
#define BUFFER_SZ 48
#define MAINT_OFFS 0x380
#else
#define BUFFER_SZ 128
#define MAINT_OFFS 0xff00
#endif
#define MIPS_BUFFER_SZ 128
#define MIPS_MAINT_OFFS 0xff00
#define DO_LOG 1
#define MEMR 2
#define MEMW 3
#define IOR 4
#define IOW 5
#define B1TEST 6
#define B2TEST 7
#define BTESTOFF 8
#define DSIG_STATS 9
#define B_CH_STATS 10
#define D_CH_STATS 11
#define BL1_STATS 12
#define BL1_STATS_C 13
#define GET_VERSION 14
#define OS_STATS 15
#define XLOG_SET_MASK 16
#define XLOG_GET_MASK 17
#define DSP_READ 20
#define DSP_WRITE 21
#define OK 0xff
#define MORE_EVENTS 0xfe
#define NO_EVENT 1
struct DSigStruc
{
byte Id;
byte uX;
byte listen;
byte active;
byte sin[3];
byte bc[6];
byte llc[6];
byte hlc[6];
byte oad[20];
};
struct BL1Struc {
dword cx_b1;
dword cx_b2;
dword cr_b1;
dword cr_b2;
dword px_b1;
dword px_b2;
dword pr_b1;
dword pr_b2;
word er_b1;
word er_b2;
};
struct L2Struc {
dword XTotal;
dword RTotal;
word XError;
word RError;
};
struct OSStruc {
word free_n;
};
typedef union
{
struct DSigStruc DSigStats;
struct BL1Struc BL1Stats;
struct L2Struc L2Stats;
struct OSStruc OSStats;
byte b[BUFFER_SZ];
word w[BUFFER_SZ>>1];
word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
dword d[BUFFER_SZ>>2];
} BUFFER;
typedef union
{
struct DSigStruc DSigStats;
struct BL1Struc BL1Stats;
struct L2Struc L2Stats;
struct OSStruc OSStats;
byte b[MIPS_BUFFER_SZ];
word w[MIPS_BUFFER_SZ>>1];
word l[BUFFER_SZ>>2]; /* word is wrong, do not use! Use 'd' instead. */
dword d[MIPS_BUFFER_SZ>>2];
} MIPS_BUFFER;
#if !defined(MIPS_SCOM)
struct pc_maint
{
byte req;
byte rc;
byte *mem; /*far*/
short length;
word port;
byte fill[6];
BUFFER data;
};
#else
struct pc_maint
{
byte req;
byte rc;
byte reserved[2]; /* R3000 alignment ... */
byte far *mem;
short length;
word port;
byte fill[4]; /* data at offset 16 */
BUFFER data;
};
#endif
struct mi_pc_maint
{
byte req;
byte rc;
byte reserved[2]; /* R3000 alignment ... */
byte *mem; /*far*/
short length;
word port;
byte fill[4]; /* data at offset 16 */
MIPS_BUFFER data;
};
#endif /* PC_MAINT_H */

View File

@ -0,0 +1,70 @@
/*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.0
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(PR_PC_H)
#define PR_PC_H
struct pr_ram {
word NextReq; /* pointer to next Req Buffer */
word NextRc; /* pointer to next Rc Buffer */
word NextInd; /* pointer to next Ind Buffer */
byte ReqInput; /* number of Req Buffers sent */
byte ReqOutput; /* number of Req Buffers returned */
byte ReqReserved; /* number of Req Buffers reserved */
byte Int; /* ISDN-P interrupt */
byte XLock; /* Lock field for arbitration */
byte RcOutput; /* number of Rc buffers received */
byte IndOutput; /* number of Ind buffers received */
byte IMask; /* Interrupt Mask Flag */
byte Reserved1[2]; /* reserved field, do not use */
byte ReadyInt; /* request field for ready interrupt */
byte Reserved2[12]; /* reserved field, do not use */
byte InterfaceType; /* interface type 1=16K interface */
word Signature; /* ISDN-P initialized indication */
byte B[1]; /* buffer space for Req,Ind and Rc */
};
typedef struct {
word next;
byte Req;
byte ReqId;
byte ReqCh;
byte Reserved1;
word Reference;
byte Reserved[8];
PBUFFER XBuffer;
} REQ;
typedef struct {
word next;
byte Rc;
byte RcId;
byte RcCh;
byte Reserved1;
word Reference;
byte Reserved2[8];
} RC;
typedef struct {
word next;
byte Ind;
byte IndId;
byte IndCh;
byte MInd;
word MLength;
word Reference;
byte RNR;
byte Reserved;
dword Ack;
PBUFFER RBuffer;
} IND;
#endif

517
drivers/isdn/eicon/pri.c Normal file
View File

@ -0,0 +1,517 @@
/*
* Diva Server PRI specific part of initialisation
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.5
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "divas.h"
#include "pc.h"
#include "pr_pc.h"
#include "dsp_defs.h"
#include "adapter.h"
#include "uxio.h"
#define DIVAS_LOAD_CMD 0x02
#define DIVAS_START_CMD 0x03
#define DIVAS_IRQ_RESET 0xC18
#define DIVAS_IRQ_RESET_VAL 0xFE
#define TEST_INT_DIVAS 0x11
#define TEST_INT_DIVAS_BRI 0x12
#define DIVAS_RESET 0x81
#define DIVAS_LED1 0x04
#define DIVAS_LED2 0x08
#define DIVAS_LED3 0x20
#define DIVAS_LED4 0x40
#define DIVAS_RESET_REG 0x20
#define DIVAS_SIGNATURE 0x4447
/* offset to start of MAINT area (used by xlog) */
#define DIVAS_MAINT_OFFSET 0xef00 /* value for PRI card */
#define MP_PROTOCOL_ADDR 0xA0011000
#define MP_DSP_CODE_BASE 0xa03a0000
typedef struct {
dword cmd;
dword addr;
dword len;
dword err;
dword live;
dword reserved[(0x1020>>2)-6];
dword signature;
byte data[1];
} diva_server_boot_t;
byte mem_in(ADAPTER *a, void *adr);
word mem_inw(ADAPTER *a, void *adr);
void mem_in_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_look_ahead(ADAPTER *a, PBUFFER *RBuffer, ENTITY *e);
void mem_out(ADAPTER *a, void *adr, byte data);
void mem_outw(ADAPTER *a, void *adr, word data);
void mem_out_buffer(ADAPTER *a, void *adr, void *P, word length);
void mem_inc(ADAPTER *a, void *adr);
int DivasPRIInitPCI(card_t *card, dia_card_t *cfg);
static int pri_ISR (card_t* card);
static int diva_server_reset(card_t *card)
{
byte *reg;
diva_server_boot_t *boot = NULL;
dword live = 0;
int i = 0;
dword dwWait;
DPRINTF(("divas: reset Diva Server PRI"));
reg = UxCardMemAttach(card->hw, DIVAS_REG_MEMORY);
UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], DIVAS_RESET |
DIVAS_LED1 | DIVAS_LED2 | DIVAS_LED3 | DIVAS_LED4);
for (dwWait = 0x000fffff; dwWait; dwWait--)
;
UxCardMemOut(card->hw, &reg[DIVAS_RESET_REG], 0x00);
for (dwWait = 0x000fffff; dwWait; dwWait--)
;
UxCardMemDetach(card->hw, reg);
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
UxCardMemOutD(card->hw, boot->reserved, 0);
live = UxCardMemInD(card->hw, &boot->live);
for (i=0; i<5; i++)
{
if (live != UxCardMemInD(card->hw, &boot->live))
{
break;
}
UxPause(10);
}
if (i == 5)
{
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: card is reset but CPU not running"));
return -1;
}
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: card reset after %d ms", i * 10));
return 0;
}
static int diva_server_config(card_t *card, dia_config_t *config)
{
byte *shared;
int i, j;
DPRINTF(("divas: configure Diva Server PRI"));
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
UxCardLog(0);
for (i=0; i<256; i++)
{
UxCardMemOut(card->hw, &shared[i], 0);
}
UxCardMemOut(card->hw, &shared[ 8], config->tei);
UxCardMemOut(card->hw, &shared[ 9], config->nt2);
UxCardMemOut(card->hw, &shared[10], config->sig_flags);
UxCardMemOut(card->hw, &shared[11], config->watchdog);
UxCardMemOut(card->hw, &shared[12], config->permanent);
UxCardMemOut(card->hw, &shared[13], config->x_interface);
UxCardMemOut(card->hw, &shared[14], config->stable_l2);
UxCardMemOut(card->hw, &shared[15], config->no_order_check);
UxCardMemOut(card->hw, &shared[16], config->handset_type);
UxCardMemOut(card->hw, &shared[17], 0);
UxCardMemOut(card->hw, &shared[18], config->low_channel);
UxCardMemOut(card->hw, &shared[19], config->prot_version);
UxCardMemOut(card->hw, &shared[20], config->crc4);
for (i=0; i<2; i++)
{
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[32+(i*96)+j],config->terminal[i].oad[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[64+(i*96)+j],config->terminal[i].osa[j]);
}
for (j=0; j<32; j++)
{
UxCardMemOut(card->hw, &shared[96+(i*96)+j],config->terminal[i].spid[j]);
}
}
UxCardMemDetach(card->hw, shared);
return 0;
}
static
void diva_server_reset_int(card_t *card)
{
byte *cfg;
cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET], DIVAS_IRQ_RESET_VAL);
UxCardMemOutW(card->hw, &cfg[DIVAS_IRQ_RESET + 2], 0);
UxCardMemDetach(card->hw, cfg);
return;
}
static int diva_server_test_int(card_t *card)
{
int i;
byte *shared;
byte req_int;
DPRINTF(("divas: test interrupt for Diva Server PRI"));
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
UxCardMemIn(card->hw, &shared[0x3FE]);
UxCardMemOut(card->hw, &shared[0x3FE], 0);
UxCardMemIn(card->hw, &shared[0x3FE]);
UxCardMemDetach(card->hw, shared);
diva_server_reset_int(card);
shared = UxCardMemAttach(card->hw, DIVAS_SHARED_MEMORY);
card->test_int_pend = TEST_INT_DIVAS;
req_int = UxCardMemIn(card->hw, &(((struct pr_ram *)shared)->ReadyInt));
req_int++;
UxCardMemOut(card->hw, &(((struct pr_ram *)shared)->ReadyInt), req_int);
UxCardMemDetach(card->hw, shared);
UxCardLog(0);
for (i = 0; i < 50; i++)
{
if (!card->test_int_pend)
{
break;
}
UxPause(10);
}
if (card->test_int_pend)
{
DPRINTF(("active: timeout waiting for card to interrupt"));
return (-1);
}
return 0;
}
static void print_hdr(unsigned char *code, int offset)
{
unsigned char hdr[80];
int i;
i = 0;
while ((i < (DIM(hdr) -1)) &&
(code[offset + i] != '\0') &&
(code[offset + i] != '\r') &&
(code[offset + i] != '\n'))
{
hdr[i] = code[offset + i];
i++;
}
hdr[i] = '\0';
DPRINTF(("divas: loading %s", hdr));
}
static int diva_server_load(card_t *card, dia_load_t *load)
{
diva_server_boot_t *boot;
int i, offset, length;
dword cmd = 0;
DPRINTF(("divas: loading Diva Server PRI"));
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
switch(load->code_type)
{
case DIA_CPU_CODE:
DPRINTF(("divas: RISC code"));
print_hdr(load->code, 0x80);
UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
break;
case DIA_DSP_CODE:
DPRINTF(("divas: DSP code"));
print_hdr(load->code, 0x0);
UxCardMemOutD(card->hw, &boot->addr,
(MP_DSP_CODE_BASE + (((sizeof(dword) +
(sizeof(t_dsp_download_desc) * DSP_MAX_DOWNLOAD_COUNT))
+ ~ALIGNMENT_MASK_MAESTRA) & ALIGNMENT_MASK_MAESTRA)));
break;
case DIA_TABLE_CODE:
DPRINTF(("divas: TABLE code"));
UxCardMemOutD(card->hw, &boot->addr,
(MP_DSP_CODE_BASE + sizeof(dword)));
break;
case DIA_CONT_CODE:
DPRINTF(("divas: continuation code"));
break;
case DIA_DLOAD_CNT:
DPRINTF(("divas: COUNT code"));
UxCardMemOutD(card->hw, &boot->addr, MP_DSP_CODE_BASE);
break;
default:
DPRINTF(("divas: unknown code type"));
UxCardMemDetach(card->hw, boot);
return -1;
}
UxCardLog(0);
offset = 0;
do
{
length = (load->length - offset >= 400) ? 400 : load->length - offset;
for (i=0; i<length; i++)
{
UxCardMemOut(card->hw, &boot->data[i], load->code[offset+i]);
}
for (i=0; i<length; i++)
{
if (load->code[offset + i] != UxCardMemIn(card->hw, &boot->data[i]))
{
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: card code block verify failed"));
return -1;
}
}
UxCardMemOutD(card->hw, &boot->len, (length + 3) / 4);
UxCardMemOutD(card->hw, &boot->cmd, DIVAS_LOAD_CMD);
for (i=0; i<50000; i++)
{
cmd = UxCardMemInD(card->hw, &boot->cmd);
if (!cmd)
{
break;
}
/*UxPause(1);*/
}
if (cmd)
{
DPRINTF(("divas: timeout waiting for card to ACK load (offset = %d)", offset));
UxCardMemDetach(card->hw, boot);
return -1;
}
offset += length;
} while (offset < load->length);
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: DIVA Server card loaded"));
return 0;
}
static int diva_server_start(card_t *card, byte *channels)
{
diva_server_boot_t *boot;
byte *ram;
int i;
dword signature = 0;
DPRINTF(("divas: start Diva Server PRI"));
card->is_live = FALSE;
boot = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
UxCardMemOutD(card->hw, &boot->addr, MP_PROTOCOL_ADDR);
UxCardMemOutD(card->hw, &boot->cmd, DIVAS_START_CMD);
UxCardLog(0);
for (i = 0; i < 300; i++)
{
signature = UxCardMemInD(card->hw, &boot->signature);
if ((signature >> 16) == DIVAS_SIGNATURE)
{
DPRINTF(("divas: started card after %d ms", i * 10));
break;
}
UxPause(10);
}
if ((signature >> 16) != DIVAS_SIGNATURE)
{
UxCardMemDetach(card->hw, boot);
DPRINTF(("divas: timeout waiting for card to run protocol code (sig = 0x%x)", signature));
return -1;
}
card->is_live = TRUE;
ram = (byte *) boot;
ram += DIVAS_SHARED_OFFSET;
*channels = UxCardMemIn(card->hw, &ram[0x3F6]);
card->serial_no = UxCardMemInD(card->hw, &ram[0x3F0]);
UxCardMemDetach(card->hw, boot);
if (diva_server_test_int(card))
{
DPRINTF(("divas: interrupt test failed"));
return -1;
}
DPRINTF(("divas: DIVA Server card started"));
return 0;
}
static
int diva_server_mem_get(card_t *card, mem_block_t *mem_block)
{
byte *a;
byte *card_addr;
word length = 0;
int i;
a = UxCardMemAttach(card->hw, DIVAS_RAM_MEMORY);
card_addr = a;
card_addr += mem_block->addr;
for (i=0; i < sizeof(mem_block->data); i++)
{
mem_block->data[i] = UxCardMemIn(card->hw, card_addr);
card_addr++;
length++;
}
UxCardMemDetach(card->hw, a);
return length;
}
/*
* Initialise PRI specific entry points
*/
int DivasPriInit(card_t *card, dia_card_t *cfg)
{
DPRINTF(("divas: initialise Diva Server PRI"));
if (DivasPRIInitPCI(card, cfg) == -1)
{
return -1;
}
card->card_reset = diva_server_reset;
card->card_load = diva_server_load;
card->card_config = diva_server_config;
card->card_start = diva_server_start;
card->reset_int = diva_server_reset_int;
card->card_mem_get = diva_server_mem_get;
card->xlog_offset = DIVAS_MAINT_OFFSET;
card->out = DivasOut;
card->test_int = DivasTestInt;
card->dpc = DivasDpc;
card->clear_int = DivasClearInt;
card->card_isr = pri_ISR;
card->a.ram_out = mem_out;
card->a.ram_outw = mem_outw;
card->a.ram_out_buffer = mem_out_buffer;
card->a.ram_inc = mem_inc;
card->a.ram_in = mem_in;
card->a.ram_inw = mem_inw;
card->a.ram_in_buffer = mem_in_buffer;
card->a.ram_look_ahead = mem_look_ahead;
return 0;
}
static int pri_ISR (card_t* card)
{
int served = 0;
byte* cfg = UxCardMemAttach(card->hw, DIVAS_CFG_MEMORY);
volatile unsigned long* isr = (unsigned long*)&cfg[DIVAS_IRQ_RESET];
register unsigned long val = *isr;
if (val & 0x80000000) /* our card had caused interrupt ??? */
{
served = 1;
card->int_pend += 1;
DivasDpcSchedule(); /* ISR DPC */
*isr = (unsigned long)~0x03E00000; /* Clear interrupt line */
}
UxCardMemDetach(card->hw, cfg);
return (served != 0);
}

95
drivers/isdn/eicon/sys.h Normal file
View File

@ -0,0 +1,95 @@
/*
* Environment provided by system and miscellaneous definitions
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(SYS_H)
#define SYS_H
/* abreviations for unsigned types */
typedef int boolean_t;
typedef unsigned char byte;
typedef unsigned long dword;
typedef unsigned short word;
/* abreviations for volatile types */
typedef volatile byte vbyte;
typedef volatile word vword;
typedef volatile dword vdword;
/* Booleans */
#if !defined(TRUE)
#define TRUE (1)
#define FALSE (0)
#endif
/* NULL pointer */
#if !defined(NULL)
#define NULL ((void *) 0)
#endif
/* Return the dimension of an array */
#if !defined(DIM)
#define DIM(array) (sizeof (array)/sizeof ((array)[0]))
#endif
/*
* Return the number of milliseconds since last boot
*/
extern dword UxTimeGet(void);
extern void DivasSprintf(char *buffer, char *format, ...);
extern void DivasPrintf(char *format, ...);
/* fatal errors, asserts and tracing */
void HwFatalErrorFrom(char *file, int line);
void HwFatalError(void);
/* void HwAssert(char *file, int line, char *condition); */
#include <linux/kernel.h>
#include <linux/string.h>
#define _PRINTK printk
#define _PRINTF DivasPrintf
void _PRINTF(char *format, ...);
#define PRINTF(arg_list) _PRINTF arg_list
#if defined DTRACE
# define DPRINTF(arg_list) _PRINTF arg_list
# define KDPRINTF(arg_list) _PRINTF arg_list ; _PRINTK arg_list ; _PRINTK("\n");
#else
# define DPRINTF(arg_list) (void)0
# define KDPRINTF(arg_list) _PRINTK arg_list ; _PRINTK("\n");
#endif
#if !defined(ASSERT)
#if defined DEBUG || defined DBG
# define HwFatalError() HwFatalErrorFrom(__FILE__, __LINE__)
# define ASSERT(cond) \
if (!(cond)) \
{ \
/* HwAssert(__FILE__, __LINE__, #cond);*/ \
}
#else
# define ASSERT(cond) ((void)0)
#endif
#endif /* !defined(ASSERT) */
#define TRACE (_PRINTF(__FILE__"@%d\n", __LINE__))
#endif /* SYS_H */

197
drivers/isdn/eicon/uxio.h Normal file
View File

@ -0,0 +1,197 @@
/*
* Interface to Unix specific code for performing card I/O
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.6
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#if !defined(UXIO_H)
#define UXIO_H
#include "sys.h"
#include "adapter.h"
struct pt_regs;
/* user callback, returns zero if interrupt was from this card */
typedef void isr_fn_t(void *);
struct ux_diva_card_s
{
word in_use;
int io_base;
int reset_base;
int card_type;
byte *mapped;
int bus_num;
int func_num;
int slot;
int irq;
byte *pDRAM;
byte *pDEVICES;
byte *pCONFIG;
byte *pSHARED;
byte *pCONTROL;
word features;
void *user_isr_arg;
isr_fn_t *user_isr;
};
/*
* Get a card handle to enable card to be accessed
*/
int UxCardHandleGet( ux_diva_card_t **card,
dia_card_t *cfg);
/*
* Free a card handle as no longer needed
*/
void UxCardHandleFree(ux_diva_card_t *card);
/*
* Lock and unlock access to a card
*/
long UxCardLock(ux_diva_card_t *card);
void UxCardUnlock(ux_diva_card_t *card, long ipl);
/*
* Set the mapping address for PCI cards
*/
int UxCardAddrMappingSet(ux_diva_card_t *card,
int id,
void *address,
int size);
/*
* Attach card to memory to enable it to be accessed
* Returns the mapped address
*/
void *UxCardMemAttach(ux_diva_card_t *card, int id);
/*
* map card out of memory after completion of access
*/
void UxCardMemDetach(ux_diva_card_t *card, void *address);
/*
* input functions for memory-mapped cards
*/
byte UxCardMemIn(ux_diva_card_t *card, void *address);
word UxCardMemInW(ux_diva_card_t *card, void *address);
dword UxCardMemInD(ux_diva_card_t *card, void *address);
void UxCardMemInBuffer( ux_diva_card_t *card,
void *address,
void *buffer,
int length);
/*
* output functions for memory-mapped cards
*/
void UxCardMemOut(ux_diva_card_t *card, void *address, byte data);
void UxCardMemOutW(ux_diva_card_t *card, void *address, word data);
void UxCardMemOutD(ux_diva_card_t *card, void *address, dword data);
void UxCardMemOutBuffer( ux_diva_card_t *card,
void *address,
void *buffer,
int length);
/*
* input functions for I/O-mapped cards
*/
byte UxCardIoIn(ux_diva_card_t *card, void *, void *address);
word UxCardIoInW(ux_diva_card_t *card, void *, void *address);
dword UxCardIoInD(ux_diva_card_t *card, void *, void *address);
void UxCardIoInBuffer( ux_diva_card_t *card,
void *, void *address,
void *buffer,
int length);
/*
* output functions for I/O-mapped cards
*/
void UxCardIoOut(ux_diva_card_t *card, void *, void *address, byte data);
void UxCardIoOutW(ux_diva_card_t *card, void *, void *address, word data);
void UxCardIoOutD(ux_diva_card_t *card, void *, void *address, dword data);
void UxCardIoOutBuffer( ux_diva_card_t *card,
void *, void *address,
void *buffer,
int length);
/*
* Get specified PCI config
*/
void UxPciConfigRead(ux_diva_card_t *card,
int size,
int offset,
void *value);
/*
* Set specified PCI config
*/
void UxPciConfigWrite(ux_diva_card_t *card,
int size,
int offset,
void *value);
/* allocate memory, returning NULL if none available */
void *UxAlloc(unsigned int size);
void UxFree(void *);
/*
* Pause for specified number of milli-seconds
*/
void UxPause(long ms);
/*
* Install an ISR for the specified card
*/
int UxIsrInstall(ux_diva_card_t *card, isr_fn_t *isr_fn, void *isr_arg);
/*
* Remove an ISR for the specified card
*/
void UxIsrRemove(ux_diva_card_t *card, void *);
/*
* DEBUG function to turn logging ON or OFF
*/
void UxCardLog(int turn_on);
long UxInterlockedIncrement(ux_diva_card_t *card, long *dst);
long UxInterlockedDecrement(ux_diva_card_t *card, long *dst);
#endif /* of UXIO_H */

164
drivers/isdn/eicon/xlog.c Normal file
View File

@ -0,0 +1,164 @@
/*
* Unix Eicon active card driver
* XLOG related functions
*
* Copyright (C) Eicon Technology Corporation, 2000.
*
* Eicon File Revision : 1.2
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#include "sys.h"
#include "idi.h"
#include "pc.h"
#include "pc_maint.h"
#include "divalog.h"
#include "adapter.h"
#include "uxio.h"
/*
* convert/copy XLOG info into a KLOG entry
*/
static
void xlog_to_klog(byte *b, int size, int card_num)
{
typedef struct
{
word code;
word time_hi;
word time_lo;
word xcode;
byte data[2];
} card_xlog_t;
card_xlog_t *x;
klog_t klog;
x = (card_xlog_t *) b;
memset(&klog, 0, sizeof(klog));
klog.time_stamp = (dword) x->time_hi;
klog.time_stamp = (klog.time_stamp << 16) | (dword) x->time_lo;
klog.length = size > sizeof(klog.buffer) ? sizeof(klog.buffer) : size;
klog.card = card_num;
if (x->code == 1)
{
klog.type = KLOG_XTXT_MSG;
klog.code = 0;
memcpy(klog.buffer, &x->xcode, klog.length);
}
else if (x->code == 2)
{
klog.type = KLOG_XLOG_MSG;
klog.code = x->xcode;
memcpy(klog.buffer, &x->data, klog.length);
}
else
{
char *c; int i;
klog.type = KLOG_TEXT_MSG;
klog.code = 0;
c = "divas: invalid xlog message code from card";
i = 0;
while (*c)
{
klog.buffer[i] = *c;
c++;
i++;
}
klog.buffer[i] = *c;
}
/* send to the log driver and return */
DivasLogAdd(&klog, sizeof(klog));
return;
}
/*
* send an XLOG request down to specified card
* if response available from previous request then read it
* if not then just send down new request, ready for next time
*/
void DivasXlogReq(int card_num)
{
card_t *card;
ADAPTER *a;
if ((card_num < 0) || (card_num > DivasCardNext))
{
DPRINTF(("xlog: invalid card number"));
return;
}
card = &DivasCards[card_num];
if (DivasXlogRetrieve(card))
{
return;
}
/* send down request for next time */
a = &card->a;
a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
return;
}
/*
* retrieve XLOG request from specified card
* returns non-zero if new request sent to card
*/
int DivasXlogRetrieve(card_t *card)
{
ADAPTER *a;
struct mi_pc_maint pcm;
a = &card->a;
/* get status of last request */
pcm.rc = a->ram_in(a, (word *)(card->xlog_offset + 1));
/* if nothing there from previous request, send down a new one */
if (pcm.rc == OK)
{
/* read in response */
a->ram_in_buffer(a, (word *) (dword) card->xlog_offset, &pcm, sizeof(pcm));
xlog_to_klog((byte *) &pcm.data, sizeof(pcm.data),
(int) (card - DivasCards));
}
/* if any response received from card, re-send request */
if (pcm.rc)
{
a->ram_out(a, (word *) (card->xlog_offset + 1), 0);
a->ram_out(a, (word *) (dword) (card->xlog_offset), DO_LOG);
return 1;
}
return 0;
}

View File

@ -1,217 +1,74 @@
L_OBJS :=
M_OBJS :=
LX_OBJS :=
MX_OBJS :=
O_OBJS :=
OX_OBJS :=
L_TARGET :=
O_TARGET :=
# Makefile for the hisax ISDN device driver
O_OBJS := isdnl1.o tei.o isdnl2.o isdnl3.o \
lmgr.o q931.o callc.o fsm.o cert.o
# The target object and module list name.
# EXTRA_CFLAGS += -S
O_TARGET := vmlinux-obj.o
ifeq ($(CONFIG_HISAX_EURO),y)
O_OBJS += l3dss1.o
endif
# Objects that export symbols.
ifeq ($(CONFIG_HISAX_NI1),y)
O_OBJS += l3ni1.o
endif
export-objs := config.o fsm.o hisax_isac.o
ifeq ($(CONFIG_HISAX_1TR6),y)
O_OBJS += l3_1tr6.o
endif
# Multipart objects.
ISAC_OBJ :=
HSCX_OBJ :=
ISAR_OBJ :=
HFC_OBJ :=
HFC_2BDS0 :=
JADE_OBJ :=
W6692_OBJ :=
list-multi := hisax.o hisax_st5481.o
hisax-objs := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \
lmgr.o q931.o callc.o fsm.o cert.o
hisax_st5481-objs := st5481_init.o st5481_usb.o st5481_d.o st5481_b.o \
st5481_hdlc.o
ifeq ($(CONFIG_HISAX_16_0),y)
O_OBJS += teles0.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
# Optional parts of multipart objects.
hisax-objs-$(CONFIG_HISAX_EURO) += l3dss1.o
hisax-objs-$(CONFIG_HISAX_NI1) += l3ni1.o
hisax-objs-$(CONFIG_HISAX_1TR6) += l3_1tr6.o
ifeq ($(CONFIG_HISAX_16_3),y)
O_OBJS += teles3.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
hisax-objs-$(CONFIG_HISAX_16_0) += teles0.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_16_3) += teles3.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_TELESPCI) += telespci.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_S0BOX) += s0box.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o
hisax-objs-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o
hisax-objs-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o isar.o
hisax-objs-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_NETJET) += nj_s.o netjet.o isac.o arcofi.o
hisax-objs-$(CONFIG_HISAX_NETJET_U) += nj_u.o netjet.o icc.o
hisax-objs-$(CONFIG_HISAX_HFCS) += hfcscard.o hfc_2bds0.o
hisax-objs-$(CONFIG_HISAX_HFC_PCI) += hfc_pci.o
hisax-objs-$(CONFIG_HISAX_HFC_SX) += hfc_sx.o
hisax-objs-$(CONFIG_HISAX_NICCY) += niccy.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o
hisax-objs-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o
hisax-objs-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o
hisax-objs-$(CONFIG_HISAX_W6692) += w6692.o
#hisax-objs-$(CONFIG_HISAX_TESTEMU) += testemu.o
ifeq ($(CONFIG_HISAX_TELESPCI),y)
O_OBJS += telespci.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
hisax-objs += $(sort $(hisax-objs-y))
ifeq ($(CONFIG_HISAX_S0BOX),y)
O_OBJS += s0box.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
# Each configuration option enables a list of files.
ifeq ($(CONFIG_HISAX_AVM_A1),y)
O_OBJS += avm_a1.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o
obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o
obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o
obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o
obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_fcpcipnp.o hisax_isac.o
ifeq ($(CONFIG_HISAX_AVM_A1_PCMCIA),y)
O_OBJS += avm_a1p.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_FRITZPCI),y)
O_OBJS += avm_pci.o
ISAC_OBJ := isac.o
endif
CERT := $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
CFLAGS_cert.o := -DCERTIFICATION=$(CERT)
include $(TOPDIR)/drivers/isdn/Rules.make
ifeq ($(CONFIG_HISAX_ELSA),y)
O_OBJS += elsa.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
# Link rules for multi-part drivers.
ifeq ($(CONFIG_HISAX_IX1MICROR2),y)
O_OBJS += ix1_micro.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_DIEHLDIVA),y)
O_OBJS += diva.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_ASUSCOM),y)
O_OBJS += asuscom.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_TELEINT),y)
O_OBJS += teleint.o
ISAC_OBJ := isac.o
HFC_OBJ := hfc_2bs0.o
endif
ifeq ($(CONFIG_HISAX_SEDLBAUER),y)
O_OBJS += sedlbauer.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
ISAR_OBJ := isar.o
endif
ifeq ($(CONFIG_HISAX_SPORTSTER),y)
O_OBJS += sportster.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_MIC),y)
O_OBJS += mic.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_NETJET),y)
O_OBJS += netjet.o
ISAC_OBJ := isac.o
endif
ifeq ($(CONFIG_HISAX_HFCS),y)
O_OBJS += hfcscard.o
HFC_2BDS0 := hfc_2bds0.o
endif
ifeq ($(CONFIG_HISAX_HFC_PCI),y)
HFC_2BDS0 += hfc_pci.o
endif
ifeq ($(CONFIG_HISAX_HFC_SX),y)
HFC_2BDS0 += hfc_sx.o
endif
ifeq ($(CONFIG_HISAX_NICCY),y)
O_OBJS += niccy.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_ISURF),y)
O_OBJS += isurf.o
ISAC_OBJ := isac.o
ISAR_OBJ := isar.o
endif
ifeq ($(CONFIG_HISAX_HSTSAPHIR),y)
O_OBJS += saphir.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_BKM_A4T),y)
O_OBJS += bkm_a4t.o
ISAC_OBJ := isac.o
JADE_OBJ := jade.o
endif
ifeq ($(CONFIG_HISAX_SCT_QUADRO),y)
O_OBJS += bkm_a8.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_GAZEL),y)
O_OBJS += gazel.o
ISAC_OBJ := isac.o
HSCX_OBJ := hscx.o
endif
ifeq ($(CONFIG_HISAX_W6692),y)
W6692_OBJ := w6692.o
endif
# ifeq ($(CONFIG_HISAX_TESTEMU),y)
# O_OBJS += testemu.o
# endif
ifeq ($(ISAC_OBJ), isac.o)
ISAC_OBJ += arcofi.o
endif
O_OBJS += $(ISAC_OBJ) $(HSCX_OBJ) $(ISAR_OBJ) $(JADE_OBJ)
O_OBJS += $(HFC_OBJ) $(HFC_2BDS0) $(W6692_OBJ)
OX_OBJS += config.o
O_TARGET :=
ifeq ($(CONFIG_ISDN_DRV_HISAX),y)
O_TARGET += hisax.o
else
ifeq ($(CONFIG_ISDN_DRV_HISAX),m)
O_TARGET += hisax.o
M_OBJS += hisax.o
endif
endif
include $(TOPDIR)/Rules.make
MD5FILES += isac.c isdnl1.c isdnl2.c isdnl3.c \
tei.c callc.c cert.c l3dss1.c l3_1tr6.c \
elsa.c diva.c
CERT = $(shell md5sum -c md5sums.asc >> /dev/null;echo $$?)
cert.o: $(MD5FILES) md5sums.asc
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -D CERTIFICATION=$(CERT) -c -o cert.o cert.c
hisax.o: $(hisax-objs)
$(LD) -r -o $@ $(hisax-objs)
hisax_st5481.o: $(hisax_st5481-objs)
$(LD) -r -o $@ $(hisax_st5481-objs)

View File

@ -2,19 +2,11 @@
*
* HiSax ISDN driver - chip specific routines for AMD 7930
*
* Author Brent Baccala (baccala@FreeSoft.org)
* Author Brent Baccala
* Copyright by Brent Baccala <baccala@FreeSoft.org>
*
*
*
* $Log$
* Revision 1.2 1998/02/12 23:07:10 keil
* change for 2.1.86 (removing FREE_READ/FREE_WRITE from [dev]_kfree_skb()
*
* Revision 1.1 1998/02/03 23:20:51 keil
* New files for SPARC isdn support
*
* Revision 1.1 1998/01/08 04:17:12 baccala
* ISDN comes to the Sparc. Key points:
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* - Existing ISDN HiSax driver provides all the smarts
* - it compiles, runs, talks to an isolated phone switch, connects
@ -26,6 +18,7 @@
*
* The code is unreliable enough to be consider alpha
*
* This file is (c) under GNU General Public License
*
* Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
* SparcStation 1+. The chip provides microphone and speaker interfaces
@ -373,12 +366,8 @@ Bchan_close(struct BCState *bcs)
amd7930_bclose(0, bcs->channel);
if (test_bit(BC_FLG_INIT, &bcs->Flag)) {
while ((skb = skb_dequeue(&bcs->rqueue))) {
dev_kfree_skb(skb);
}
while ((skb = skb_dequeue(&bcs->squeue))) {
dev_kfree_skb(skb);
}
skb_queue_purge(&bcs->rqueue);
skb_queue_purge(&bcs->squeue);
}
test_and_clear_bit(BC_FLG_INIT, &bcs->Flag);
}
@ -745,8 +734,8 @@ amd7930_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
__initfunc(int
setup_amd7930(struct IsdnCard *card))
int __init
setup_amd7930(struct IsdnCard *card)
{
struct IsdnCardState *cs = card->cs;
char tmp[64];

View File

@ -1,40 +1,12 @@
/* $Id$
* arcofi.c Ansteuerung ARCOFI 2165
*
* Author Karsten Keil (keil@isdn4linux.de)
* Ansteuerung ARCOFI 2165
*
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
*
*
* $Log$
* Revision 1.9 1999/12/19 13:09:41 keil
* changed TASK_INTERRUPTIBLE into TASK_UNINTERRUPTIBLE for
* signal proof delays
*
* Revision 1.8 1999/08/25 16:50:51 keil
* Fix bugs which cause 2.3.14 hangs (waitqueue init)
*
* Revision 1.7 1999/07/01 08:11:17 keil
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
*
* Revision 1.6 1998/09/30 22:21:56 keil
* cosmetics
*
* Revision 1.5 1998/09/27 12:52:57 keil
* cosmetics
*
* Revision 1.4 1998/08/20 13:50:24 keil
* More support for hybrid modem (not working yet)
*
* Revision 1.3 1998/05/25 12:57:38 keil
* HiSax golden code from certification, Don't use !!!
* No leased lines, no X75, but many changes.
*
* Revision 1.2 1998/04/15 16:47:16 keil
* new interface
*
* Revision 1.1 1997/10/29 18:51:20 keil
* New files
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
@ -158,8 +130,6 @@ init_arcofi(struct IsdnCardState *cs) {
cs->dc.isac.arcofitimer.function = (void *) arcofi_timer;
cs->dc.isac.arcofitimer.data = (long) cs;
init_timer(&cs->dc.isac.arcofitimer);
#ifdef COMPAT_HAS_NEW_WAITQ
init_waitqueue_head(&cs->dc.isac.arcofi_wait);
#endif
test_and_set_bit(HW_ARCOFI, &cs->HW_Flags);
}

View File

@ -1,24 +1,12 @@
/* $Id$
* arcofi.h Ansteuerung ARCOFI 2165
*
* Author Karsten Keil (keil@isdn4linux.de)
* Ansteuerung ARCOFI 2165
*
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
*
*
* $Log$
* Revision 1.4 1999/07/01 08:11:18 keil
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
*
* Revision 1.3 1998/05/25 12:57:39 keil
* HiSax golden code from certification, Don't use !!!
* No leased lines, no X75, but many changes.
*
* Revision 1.2 1998/04/15 16:47:17 keil
* new interface
*
* Revision 1.1 1997/10/29 18:51:20 keil
* New files
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/

View File

@ -1,39 +1,19 @@
/* $Id$
* asuscom.c low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
*
* Author Karsten Keil (keil@isdn4linux.de)
* low level stuff for ASUSCOM NETWORK INC. ISDNLink cards
*
* Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for informations
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* $Log$
* Revision 1.8 1999/09/04 06:20:05 keil
* Changes from kernel set_current_state()
*
* Revision 1.7 1999/07/12 21:04:53 keil
* fix race in IRQ handling
* added watchdog for lost IRQs
*
* Revision 1.6 1999/07/01 08:11:18 keil
* Common HiSax version for 2.0, 2.1, 2.2 and 2.3 kernel
*
* Revision 1.5 1998/11/15 23:54:19 keil
* changes from 2.0
*
* Revision 1.4 1998/06/18 23:18:20 keil
* Support for new IPAC card
*
* Revision 1.3 1998/04/15 16:46:53 keil
* new init code
*
* Revision 1.2 1998/02/02 13:27:06 keil
* New
*
* Thanks to ASUSCOM NETWORK INC. Taiwan and Dynalink NL for information
*
*/
#define __NO_VERSION__
#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "ipac.h"
@ -329,8 +309,8 @@ Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
__initfunc(int
setup_asuscom(struct IsdnCard *card))
int __init
setup_asuscom(struct IsdnCard *card)
{
int bytecnt;
struct IsdnCardState *cs = card->cs;
@ -363,7 +343,7 @@ setup_asuscom(struct IsdnCard *card))
cs->cardmsg = &Asus_card_msg;
val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE,
cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID);
if (val == 1) {
if ((val == 1) || (val == 2)) {
cs->subtyp = ASUS_IPAC;
cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE;
cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA;

View File

@ -1,65 +1,17 @@
/* $Id$
* avm_a1.c low level stuff for AVM A1 (Fritz) isdn cards
*
* Author Karsten Keil (keil@isdn4linux.de)
* low level stuff for AVM A1 (Fritz) isdn cards
*
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
*
* $Log$
* Revision 2.10 1998/11/15 23:54:21 keil
* changes from 2.0
*
* Revision 2.9 1998/08/13 23:36:12 keil
* HiSax 3.1 - don't work stable with current LinkLevel
*
* Revision 2.8 1998/04/15 16:44:27 keil
* new init code
*
* Revision 2.7 1998/02/02 13:29:37 keil
* fast io
*
* Revision 2.6 1998/01/13 23:09:46 keil
* really disable timer
*
* Revision 2.5 1998/01/02 06:50:29 calle
* Perodic timer of A1 now disabled, no need for linux driver.
*
* Revision 2.4 1997/11/08 21:35:42 keil
* new l1 init
*
* Revision 2.3 1997/11/06 17:13:32 keil
* New 2.1 init code
*
* Revision 2.2 1997/10/29 18:55:48 keil
* changes for 2.1.60 (irq2dev_map)
*
* Revision 2.1 1997/07/27 21:47:13 keil
* new interface structures
*
* Revision 2.0 1997/06/26 11:02:48 keil
* New Layer and card interface
*
* Revision 1.6 1997/04/13 19:54:07 keil
* Change in IRQ check delay for SMP
*
* Revision 1.5 1997/04/06 22:54:10 keil
* Using SKB's
*
* Revision 1.4 1997/01/27 15:50:21 keil
* SMP proof,cosmetics
*
* Revision 1.3 1997/01/21 22:14:20 keil
* cleanups
*
* Revision 1.2 1996/10/27 22:07:31 keil
* cosmetic changes
*
* Revision 1.1 1996/10/13 20:04:49 keil
* Initial revision
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
*/
#define __NO_VERSION__
#include <linux/init.h>
#include "hisax.h"
#include "isac.h"
#include "hscx.h"
@ -223,8 +175,8 @@ AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg)
return(0);
}
__initfunc(int
setup_avm_a1(struct IsdnCard *card))
int __init
setup_avm_a1(struct IsdnCard *card)
{
u_char val;
struct IsdnCardState *cs = card->cs;

Some files were not shown because too many files have changed in this diff Show More