Compare commits

..

142 Commits

Author SHA1 Message Date
Andreas Eversberg 13b0b86b8c corrected wrong generation of alaw tables. thanx Alex.
Modified Files:
  Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/dsp_audio.c
2006-04-12 11:50:51 +00:00
Martin Bachem 8403b5d665 Add new PCI IDs for HFC-S PCI based ISDN TA 'Primux II S0' and 'Primux II S0' from Gerdes AG 2006-03-02 14:39:35 +00:00
Karsten Keil 2b27730824 - fix wrong fifo usage (fix for bug 0000042) 2006-03-01 17:26:01 +00:00
Martin Bachem 86c4c32518 schedule_timeout OK cause running in non atomic context 2006-03-01 17:13:59 +00:00
Martin Bachem 76194ba679 no need to spinlock hardware chip access because chip registers are written/read
sequentially by control-urbs which cannot interfer with each other.
2006-03-01 16:58:46 +00:00
Karsten Keil a081dd41b5 - add SENDING_COMPLETE and CALLED_PN INFO_IND (fix mantis bug 0000040) 2006-03-01 15:15:39 +00:00
Karsten Keil 646c6aaec2 - Do not send INFO_IND before CONNECT_IND (mantis bug 40) 2006-02-28 21:20:45 +00:00
Chrisian Richter a8c8fb9d64 added the possibility to disable CRC-4 Multiframe mode, use double frame mode instead. Some PBX use double frame Mode instead of CRC-4. It is bit 23 in the protocol parameter for hfcmulti. Also extended the misdn-init script to handle this new parameter 2006-02-22 18:00:34 +00:00
Martin Bachem 6541634bdf - using fifo wrirte/read 32 bit access
- optimized forced TE deactivation
2006-02-22 12:26:14 +00:00
Martin Bachem 226ac84366 fixed several missing line breaks 2006-02-22 12:21:49 +00:00
Martin Bachem 93c491eec5 using index defines IDX_* to select multi registers in indexing bitmaps 2006-02-22 12:08:38 +00:00
Chrisian Richter 40c277506a added more cards to the configuration 2006-02-21 11:05:57 +00:00
Chrisian Richter 03e4ea51db added winbond card to misdn-init script 2006-02-21 11:01:59 +00:00
Martin Bachem 95c37c4208 added support for severel Processor interface modes 2006-02-15 11:48:12 +00:00
Chrisian Richter 9dd14368ee added preload module check, for hotplug distros 2006-02-10 21:43:41 +00:00
Chrisian Richter 824a3f4a5f * added support of displaying the used Echo Cancellor
* braces don't hurt, but satisfy the compiler
2006-02-10 19:30:09 +00:00
Chrisian Richter a00448dea6 don't have dsp debugging enabled by default 2006-02-10 18:54:36 +00:00
Martin Bachem 78322daa7d take care of __le16 variables to satisfy BigEndian systems 2006-02-10 16:45:25 +00:00
Chrisian Richter a8cac1057a added the new mg2 echocancellor, which should be G168 compliant and made it default 2006-02-10 13:48:55 +00:00
Chrisian Richter 98e8418132 reverted Makefile also 2006-02-06 23:20:32 +00:00
Chrisian Richter 5e8b1b43f3 sorry, avm_fritz.c committed accidently, reverted it now 2006-02-06 23:17:51 +00:00
Chrisian Richter 9ac71a30b3 print the not running and pending timer warning only when debug timer is enabled, they do not harm anything, but people are afraid they are errors 2006-02-06 23:12:41 +00:00
Chrisian Richter eb8acfed40 added more debugging info in rport queue overflow case 2006-01-24 15:36:14 +00:00
Martin Bachem 44fc461e01 - new register header file
- correct chip ID's
2006-01-10 16:39:24 +00:00
Chrisian Richter 60999c882e Added new Echo cancellor kbec1 from zaptel. Also upgraded to zaptels non-type structure for easy updateing of the echo can.
You can now choose between the original Mark2 echo cancellor and the kb1 echo cancellor which is now the standard for zaptel.

It will also be easy to add new echo cancellors, in the feature we can make the echo cancellor technique chooseable by make menuconfig.
2006-01-10 11:03:35 +00:00
Andreas Eversberg fd576a94f5 Work on the LOOP device. Still untested...
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/Makefile
	mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6
	mISDN/drivers/isdn/hardware/mISDN/loop.c
	mISDN/drivers/isdn/hardware/mISDN/loop.h
	mISDN/include/linux/mISDNif.h
2006-01-03 21:48:19 +00:00
Andreas Eversberg 7be8b664cc Minor changes on cmx.
Crash fix on loading multiple hfc_multi devices.

Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/dsp_cmx.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_core.c
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.h
2005-12-29 16:24:35 +00:00
Karsten Keil f604d153eb - -I without parameter is no good idea, it did eat -DMODULE 2005-12-27 18:43:18 +00:00
Andreas Eversberg c3669c66a0 Fixed accidently change of Kconfig
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/Kconfig.v2.6
2005-12-25 18:35:21 +00:00
Andreas Eversberg 6cb9fd45ae Fixed accidently change of Makefile !!!
Modified Files:
  Tag: mqueue
 	mISDN/drivers/isdn/hardware/mISDN/Makefile
 	mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6
2005-12-25 18:32:45 +00:00
Andreas Eversberg abf892687b Forthcomming support for Layer 1 over IP virtual interface.
NOTE: NOT COMPLETE AT ALL. (Just to keep my CVS in sync.)
Added Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/l1oip.c
	mISDN/drivers/isdn/hardware/mISDN/socket.c
	mISDN/drivers/isdn/hardware/mISDN/socket.h
2005-12-25 18:08:36 +00:00
Andreas Eversberg c3bed6b64f Added support for loop device. NOTE: THIS IS NOT COMPLETE!!! (just to keep my CVS in sync)
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/Kconfig.v2.6
	mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6
Added Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/loop.c
	mISDN/drivers/isdn/hardware/mISDN/loop.h
2005-12-25 18:01:10 +00:00
Chrisian Richter 62762480db some fixes in the makefiles for standalone make 2005-12-24 15:09:22 +00:00
Karsten Keil 66a95b62db add missing vmalloc include 2005-12-22 23:22:49 +00:00
Karsten Keil 0bee77c02b - fix wrong pointer reference 2005-12-22 23:22:21 +00:00
Chrisian Richter e769d4a829 added Davids Woodhouse Patch to prevent Kernel Oops in hfcpci 2005-12-21 10:09:43 +00:00
Martin Bachem ae2adf6c7f slightly modified debug output, slightly code beautifications 2005-12-21 08:50:54 +00:00
Martin Bachem 2e887b0c04 improved layer1 state handling 2005-12-20 15:26:52 +00:00
Chrisian Richter e7facfbafe added option to delete non-mqueue headers, and optimized the clean target to remove every temporary generated files 2005-12-20 12:24:19 +00:00
Martin Bachem 26f3a2b940 *** empty log message *** 2005-12-19 16:38:54 +00:00
Martin Bachem 9d40b9fb64 - improved activation/deactivation timers (t3/t4) 2005-12-19 16:38:27 +00:00
Martin Bachem 69301b97d7 - tunnel (CC_RELEASE_CR | INDICATION) to application to have a connection realease with cause 0x3301
(Protocol error layer 1 (broken line or B-channel removed by signalling protocol))
2005-12-19 16:37:07 +00:00
Martin Bachem b59714d7cd - tunnel (CC_RELEASE_CR | INDICATION) to application to a fully connection realease with cause 0x3301
(Protocol error layer 1 (broken line or B-channel removed by signalling protocol))
2005-12-19 16:33:30 +00:00
Chrisian Richter 330b1c3b02 repaired Makefile to compile standalone on Suse Systems 2005-12-19 13:53:31 +00:00
Chrisian Richter 2a3309d053 repaired the upgrade test 2005-12-19 13:32:47 +00:00
Chrisian Richter 8828921356 added check for old mISDNif.h 2005-12-16 13:42:43 +00:00
Chrisian Richter 2dbbd53ef6 added fpu_begin/end for dsp_cancel because we used the fpu without asking before 2005-12-16 12:05:09 +00:00
Chrisian Richter ce26b92218 * fixed minor debugging issue in dsp_cancel.c (too much output over serial
line creates Kernel Oops..)
* driver/isdn/hardware/mISDN/Makefile is now the 2.6 one (i don't know if mISDN
  works with 2.4 anymore ..)
* added misdn-init and README.misdn-init:
make install will install misdn-init in /etc/init.d/
This will load all the necessary drivers and pass useful options to them. It
is very easy to configure the Modes for a port now, just by editing:
/etc/misdn-init.conf now.

There are 6 Modes at the moment:
te_ptp,te_ptmp,te_capi_ptp,te_capi_ptmp,nt_ptp,nt_ptmp

Also the possible extra options like timing and hw-dtmf detection are now
easily settable without calculating the protocol/layermask anymore.

When its later possible to use the sysfs interface to set/change the port
parameters, this script can easily be adapted.
2005-12-16 12:02:20 +00:00
Chrisian Richter c1b1125207 hfcusb compiles again so readded to Makefile 2005-12-16 11:26:16 +00:00
Martin Bachem 12c9aac89a correct NT Timer value 2005-12-16 11:10:51 +00:00
Martin Bachem 23fb3808e3 no FLG_ACTIVE in layer0 TE mode 2005-12-16 11:05:19 +00:00
Martin Bachem 14463646ba - common HW layer channel model for B and D channel
- minor code optimizations
2005-12-15 13:49:37 +00:00
srichter 054549f836 Disable #error for big endian machines, as it should work now 2005-12-11 23:05:00 +00:00
Karsten Keil 32dd9af3eb common channel_t for w6692
handle SHORTSTATUS for isac
2005-12-11 18:27:08 +00:00
srichter ab7fd00493 Forward port patch from #4 to mqueue branch 2005-12-11 17:26:34 +00:00
Chrisian Richter 591674cb3b according to ETSI the T310 should be stopped by a received PROGRESS 2005-12-10 10:34:42 +00:00
Andreas Eversberg bbe04955ef forthcomming new layer ids
Modified Files:
 Tag: mqueue
	mISDN/include/linux/mISDNif.h
2005-12-09 22:44:28 +00:00
Martin Bachem 5ccc714c19 - common HW layer channel model for B and D channel 2005-12-09 16:20:38 +00:00
Chrisian Richter 86d23dc746 hfcs_usb.c doesn't compile anymore, so not compiling it defaulty 2005-12-09 11:37:37 +00:00
Karsten Keil 60ba3b689f minor cleanups and fixes 2005-12-08 23:18:48 +00:00
Karsten Keil 66319c89ef display kernel version 2005-12-08 18:52:00 +00:00
Karsten Keil 0913082112 - common HW layer channel model for B and D channel
* reduce duplicated code
  * not finished and tested for all drivers
2005-12-08 18:32:53 +00:00
Martin Bachem e1b97ac317 - send transparent audio data asap to upper layer to reduce latency 2005-12-08 16:36:37 +00:00
Martin Bachem aad4a831a4 - implemented MGR_SHORTSTATUS messages for NT mode
- send transparent audio data asap to upper layer to reduce latency
2005-12-08 16:35:06 +00:00
Martin Bachem e4442d1014 - directly linked to layer2 (omitting layer1.c)
- implement MGR_SHORTSTATUS messages
2005-12-08 15:54:18 +00:00
Chrisian Richter 9e4f839496 added INSTALL_PREFIX for headers 2005-12-05 09:28:54 +00:00
Andreas Eversberg 0e241668db Complete rework of DSP audio bridging (CMX).
- faster (much faster)
- capable of handling jitter
- capable of handling misordered frames
- new clocking mechanism
- compiles and sucessfully tested

Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/dsp.h
	mISDN/drivers/isdn/hardware/mISDN/dsp_cmx.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_core.c
2005-12-04 16:13:30 +00:00
Chrisian Richter 4da89691bc it makes sense to copy the includes with make install 2005-12-04 14:53:44 +00:00
Chrisian Richter ba58127def use local Include dir rather then copying mISDNif.h and isdn_compat.h to the local kernel includes, we need to modify mISDNuser for that 2005-12-04 12:52:14 +00:00
Chrisian Richter c3e596c162 changed KERNELDIR to real current installed sources path 2005-12-02 15:45:05 +00:00
Chrisian Richter 39c27195e1 added Makefile to compile and install the modules standalone 2005-12-02 15:44:18 +00:00
Karsten Keil 526c241c06 remove unused bch->st 2005-11-25 13:32:27 +00:00
Andreas Eversberg e906ebf312 Added some missing L1_RELEASED short messages (state >=7 -> <7)
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/layer2.c
2005-11-23 17:14:38 +00:00
Andreas Eversberg 94762d412a Fixed locking problems. CMX not tested with software bridging.
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/dsp_cmx.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_core.c
2005-11-23 17:05:41 +00:00
Andreas Eversberg 052818c38c Removed double locking bug.
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/dsp_core.c
2005-11-23 10:38:51 +00:00
Chrisian Richter 3a185417f1 fixed bug #27 nasty Kernel Oops with freeze when using mISDN_dsp with SMP, needed to remove the spin_lock/spin_unlock functions in the receive and transmit part (dsp_from_up and dsp_from_down) just like in l3_udss1. Seems to work for me after a few tests 2005-11-18 16:01:03 +00:00
Chrisian Richter 01d5d96214 if c_skb == NULL we get a Kernel Oops when freeing it. This removes some nasty kernel oopses, and makes it possible to unload hfcmulti again. 2005-11-17 18:05:24 +00:00
Karsten Keil c2ba762cc6 - for mqueue we don't need locks in datapath anymore 2005-11-17 12:25:17 +00:00
Karsten Keil 1939d96c3e - implement MGR_SHORTSTATUS for L1 TE
- fix some issues with MGR_SHORTSTATUS
- broadcast enhancements
  * if a layer returns a error for a broadcast the skb is still OK and so we
    do not need a new copy
  * all layer which do not handle a broadcast should return
    -EOPNOTSUPP
  * a layer which handle a broadcast, but do not consume the skb should
    return -EAGAIN and of course not free the skb (no example yet)
2005-11-17 09:40:39 +00:00
Chrisian Richter d298512a5a Possible Kernel Oops fixed: when Echo Cancel Disable Tone detected, send by a modem for example, we had a segfault here. 2005-11-16 18:49:38 +00:00
Martin Bachem b567a02093 - fixed unterminated device list 2005-11-15 10:09:32 +00:00
Martin Bachem 0fb681d79b avoid reading fifo fill state more than needed 2005-11-11 12:57:16 +00:00
Martin Bachem 04974882dc make sure chip register register access is atomic 2005-11-10 14:14:34 +00:00
Karsten Keil 0d53a2acb4 - 64bit cleanup 2005-11-10 00:44:30 +00:00
Martin Bachem c4a730317a added support for Cologne Chip AG's XHFC Evaluation card 2005-11-09 18:09:38 +00:00
Martin Bachem 1b126dbf2c decrease NT T1 counter 2005-11-09 17:53:35 +00:00
Martin Bachem ec80024786 fixed using wrong locks 2005-11-09 17:23:10 +00:00
Karsten Keil 08c5463d36 - fix some GCC4 complaints
* not longer allowed to overwrite external variables with static in the
    same scope - remove unnecessary card_cnt declare
  * inline bodies must be here before called
2005-11-09 17:12:57 +00:00
Karsten Keil f5a08ff371 - add remaining sysfs device links
- remove locks for request/free IRQ calls, make shure the HW irqs are
  disabled here
2005-11-09 16:54:53 +00:00
Martin Bachem a6debe87e6 added support for Cologne Chip AG's 'HFC-S mini' Evaluation card 2005-11-09 15:57:12 +00:00
Karsten Keil 98043b2034 - some cleanup to reduce indent level 2005-11-07 21:57:53 +00:00
Karsten Keil 9f59a14b76 - implement broadcast STATUS messages (Peter Sprenger) 2005-11-07 14:56:53 +00:00
Karsten Keil b645e6ca3d - compatibility code update
* should be OK for 2.6.8 - 2.6.14 now
2005-11-07 14:55:30 +00:00
Karsten Keil 653d44dc82 - replace old locking code (now it follows standard kernel way) 2005-11-07 14:53:57 +00:00
Karsten Keil 8698d511b8 - fix compiler warning; declaration inside code are not allowed in C90 2005-10-30 14:11:27 +00:00
Andreas Eversberg 143679e28d Made DSP running.
Also added echo cancelation (not tested yet).

Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/Kconfig.v2.6
	mISDN/drivers/isdn/hardware/mISDN/Makefile.v2.6
	mISDN/drivers/isdn/hardware/mISDN/dsp.h
	mISDN/drivers/isdn/hardware/mISDN/dsp_audio.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_blowfish.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_cmx.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_core.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_dtmf.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_tones.c
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
	mISDN/include/linux/mISDNif.h
Added Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/dsp_arith.h
	mISDN/drivers/isdn/hardware/mISDN/dsp_biquad.h
	mISDN/drivers/isdn/hardware/mISDN/dsp_cancel.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_ecdis.h
	mISDN/drivers/isdn/hardware/mISDN/dsp_mec2.h
	mISDN/drivers/isdn/hardware/mISDN/dsp_mec2_const.h
2005-10-30 12:35:34 +00:00
Karsten Keil ff3e27b2bc trim CONFIRM skbs 2005-10-27 19:27:22 +00:00
Karsten Keil 9f4e63a6c0 - move remaining HW drivers to mISDN
- fix possible race ->next_skb usage
- helper for sending bchannel DATA INDICATION and CONFIRM
2005-10-27 19:23:39 +00:00
Karsten Keil e872a653bd test 2005-10-25 23:19:33 +00:00
Karsten Keil ac4c62c371 test 2005-10-25 23:17:49 +00:00
Karsten Keil 36957da2e9 cleanups 2005-10-25 22:37:30 +00:00
Karsten Keil bf14432f45 cleanups 2005-10-25 22:30:26 +00:00
Karsten Keil 2605f160d3 cleanups 2005-10-25 22:12:42 +00:00
Karsten Keil 69bba1de9b cleanups 2005-10-25 15:52:41 +00:00
Karsten Keil eb973639fb cleanups 2005-10-25 15:36:07 +00:00
Andreas Eversberg f85380c49c Seems to work but still some problems:
- locking inside interrupt disabled due to deadlock
- still problems with pbx4linux, but already got a dial tone for a short period

Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.h
2005-10-23 16:08:17 +00:00
Karsten Keil aa7d9e187f forgot this file in last checkin 2005-10-21 08:58:55 +00:00
Karsten Keil bd1c13ae2b add restart of thread if killed by accident 2005-10-20 22:54:43 +00:00
Karsten Keil a3b6908c6f fix for gcc4 2005-10-20 22:50:43 +00:00
Karsten Keil a45ecad811 test 2005-10-20 15:08:38 +00:00
Karsten Keil 4ca4a72946 test 2005-10-20 15:06:00 +00:00
Karsten Keil 0a386d3456 test 2005-10-20 15:02:38 +00:00
Karsten Keil 45c35318ca fix cvs update reject 2005-10-20 14:56:09 +00:00
Karsten Keil 375e643a39 - add sysfs support to discover and configure mISDN stacks
it adds following class devices:
	/sys/class/mISDN-objects
	/sys/class/mISDN-instances
	/sys/class/mISDN-stacks
    even it's not finished yet, you already can reconfigure a stack
    For full support all MISDN HW have to support the Linux driver model
    (e.g register the driver for hotplug).
2005-10-20 14:23:07 +00:00
Andreas Eversberg b914ab29eb latest source from my side, no change to hfc_multi
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/dsp.h
	mISDN/drivers/isdn/hardware/mISDN/dsp_cmx.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_core.c
	mISDN/drivers/isdn/hardware/mISDN/dsp_tones.c
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
2005-10-18 21:51:36 +00:00
Karsten Keil 82d37c7fc3 free with NULL pointer is now allowed 2005-10-17 00:22:28 +00:00
Karsten Keil 0cc92c0d61 cleanup not needed NULL checks before kfree, thanks to Jesper Juhl for the
hints
2005-10-15 12:31:05 +00:00
Andreas Eversberg f285da122c Now unloads clean.
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
2005-10-13 19:11:50 +00:00
Andreas Eversberg 7c4f82a743 fix for unloading hfcmulti
Modified Files:
 Tag: mqueue
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
2005-10-13 18:50:36 +00:00
Andreas Eversberg 276b42c675 Fixes of loading and unloading drivers. Added eval board support.
Modified Files:
Tag: mqueue
 	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.c
	mISDN/drivers/isdn/hardware/mISDN/hfc_multi.h
2005-10-11 21:11:47 +00:00
psprenger ece4ff91c7 default now PLX_PCI_BRIDGE undefined 2005-10-10 00:02:50 +00:00
psprenger 68cb061bec more cleanup code
re-merged chnages for dtmf handling
2005-10-10 00:02:20 +00:00
psprenger 102f12b346 support for PLX PCI Bridge and address offsets 2005-10-06 12:02:08 +00:00
psprenger 1ea587a505 enhanced support for PLX PCI Bridge
encapsulated fifo read/write routines
16 Bit support
PCI hotplug support - experimental - not testet in all configuration
2005-10-06 11:58:02 +00:00
Karsten Keil 63f37c3939 - bugfix for 0000016
- fix sysfs/udev API for 2.6.13, should be backward compatible
2005-09-05 13:30:10 +00:00
psprenger eac2a36d7c /*
* hfc_multi.c  low level driver for hfc-4s/hfc-8s/hfc-e1 based cards
 *
 * Author     Andreas Eversberg (jolly@jolly.de)
 *
 * inspired by existing hfc-pci driver:
 * Copyright 1999  by Werner Cornelius (werner@isdn-development.de)
 * Copyright 2001  by Karsten Keil (keil@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.
 *
 *
 * Thanx to Cologne Chip AG for this great controller!
 */

 // warning Experimental version!! This version supports the new mqueue mechanisnm
 // changings by Peter Sprenger (sprengermoving-bytes.de)

/* module parameters:
 * type:
	Value 1	= HFC-E1 (1 port) 0x01
	Value 4	= HFC-4S (4 ports) 0x04
	Value 8	= HFC-8S (8 ports) 0x08
	Bit 8	= uLaw (instead of aLaw)
	Bit 9	= Enable DTMF detection on all B-channels
	Bit 10	= spare
	Bit 11	= Set PCM bus into slave mode.
	Bit 12	= Ignore missing frame clock on PCM bus.
	Bit 13	= Use direct RX clock for PCM sync rather than PLL. (E1 only)
	Bit 14	= Use external ram (128K)
	Bit 15	= Use external ram (512K)
	Bit 16	= Use 64 timeslots instead of 32
	Bit 17	= Use 128 timeslots instead of anything else

 * protocol:
	NOTE: Must be given for all ports, not for the number of cards.
	HFC-4S/HFC-8S/HFC-E1 bits:
 	Bit 0-3 = protocol
	Bit 4	= NT-Mode
	Bit 5	= PTP (instead of multipoint)

	HFC-4S/HFC-8S only bits:
	Bit 16	= Use master clock for this S/T interface (ony once per chip).
	Bit 17	= transmitter line setup (non capacitive mode) DONT CARE!
	Bit 18	= Disable E-channel. (No E-channel processing)
	Bit 19	= Register E-channel as D-stack (TE-mode only)

	HFC-E1 only bits:
	Bit 16	= interface: 0=copper, 1=optical
	Bit 17	= reserved (later for 32 B-channels transparent mode)
	Bit 18	= Report LOS
	Bit 19	= Report AIS
	Bit 20	= Report SLIP
	Bit 21-22 = elastic jitter buffer (1-3), Use 0 for default.
(all other bits are reserved and shall be 0)

 * layermask:
	NOTE: Must be given for all ports, not for the number of cards.
	mask of layers to be used for D-channel stack

 * debug:
	NOTE: only one debug value must be given for all cards
	enable debugging (see hfc_multi.h for debug options)

 * poll:
	NOTE: only one poll value must be given for all cards
	Give the number of samples for each fifo process.
	By default 128 is used. Decrease to reduce delay, increase to
	reduce cpu load. If unsure, don't mess with it!
	Valid is 8, 16, 32, 64, 128, 256.

 * pcm:
	NOTE: only one pcm value must be given for all cards
	Give the id of the PCM bus. All PCM busses with the same ID
	are expected to be connected and have equal slots.
	Only one chip of the PCM bus must be master, the others slave.
	-1 means no support of PCM bus.
 */

/* debug using register map (never use this, it will flood your system log) */
//#define HFC_REGISTER_MAP

#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>

#include "dchannel.h"
#include "bchannel.h"
#include "layer1.h"
#include "dsp.h"
#include "helper.h"
#include "debug.h"
#include <linux/isdn_compat.h>

#define SPIN_DEBUG
#define LOCK_STATISTIC
#include "hw_lock.h"
#include "hfc_multi.h"

static void ph_state_change(dchannel_t *dch);

extern const char *CardType[];

static const char *hfcmulti_revision = "$Revision: 1.23.2.2 $";

static int HFC_cnt;

static mISDNobject_t	HFCM_obj;

static char HFCName[] = "HFC_multi";

/* table entry in the PCI devices list */
typedef struct {
	int vendor_id;
	int vendor_sub;
	int device_id;
	int device_sub;
	char *vendor_name;
	char *card_name;
	int type;
	int clock2;
	int leds;
} PCI_ENTRY;

static int poll_timer = 6;	/* default = 128 samples = 16ms */
/* number of POLL_TIMER interrupts for G2 timeout (min 120ms) */
static int nt_t1_count[] = { 480, 240, 120, 60, 30, 15, 8, 4 };
#define CLKDEL_TE	0x0f	/* CLKDEL in TE mode */
#define CLKDEL_NT	0x0c	/* CLKDEL in NT mode (0x60 MUST not be included!) */
static u_char silence =	0xff;	/* silence by LAW */

/* enable 32 bit fifo access (PC usage) */
#define FIFO_32BIT_ACCESS

#define VENDOR_CCD "Cologne Chip AG"

static const PCI_ENTRY id_list[] =
{
	{0x1397, 0x1397, 0x08B4, 0x08B4, VENDOR_CCD,
	 "HFC-4S Eval", 4, 0, 0},
	{0x1397, 0x1397, 0x16B8, 0x16B8, VENDOR_CCD,
	 "HFC-8S Eval", 8, 0, 0},
	{0x1397, 0x1397, 0x30B1, 0x30B1, VENDOR_CCD,
	 "HFC-E1 Eval", 1, 0, 0},
	{0x1397, 0x1397, 0x08B4, 0xB520, VENDOR_CCD,
	 "HFC-4S IOB4ST", 4, 1, 2},
	{0x1397, 0x1397, 0x08B4, 0xB620, VENDOR_CCD,
	 "HFC-4S", 4, 1, 2},
	{0x1397, 0x1397, 0x08B4, 0xB560, VENDOR_CCD,
	 "HFC-4S Beronet Card", 4, 1, 2},
	{0x1397, 0x1397, 0x16B8, 0xB521, VENDOR_CCD,
	 "HFC-8S IOB4ST Recording", 8, 1, 0},
	{0x1397, 0x1397, 0x16B8, 0xB522, VENDOR_CCD,
	 "HFC-8S IOB8ST", 8, 1, 0},
	{0x1397, 0x1397, 0x16B8, 0xB622, VENDOR_CCD,
	 "HFC-8S", 8, 1, 0},
	{0x1397, 0x1397, 0x16B8, 0xB562, VENDOR_CCD,
	 "HFC-8S Beronet Card", 8, 1, 0},
	{0x1397, 0x1397, 0x30B1, 0xB523, VENDOR_CCD,
	 "HFC-E1 IOB1E1", 1, 0, 1}, /* E1 only supports single clock */
	{0x1397, 0x1397, 0x30B1, 0xC523, VENDOR_CCD,
	 "HFC-E1", 1, 0, 1}, /* E1 only supports single clock */
	{0x1397, 0x1397, 0x30B1, 0xB563, VENDOR_CCD,
	 "HFC-E1 Beronet Card", 1, 0, 1}, /* E1 only supports single clock */
	{0, 0, 0, 0, NULL, NULL, 0, 0, 0},
};


/****************/
/* module stuff */
/****************/

/* NOTE: MAX_PORTS must be 8*MAX_CARDS */
#define MAX_CARDS	16
#define MAX_PORTS	128
#define MODULE_CARDS_T	"1-16i"
#define MODULE_PORTS_T	"1-128i" /* 16 cards can have 128 ports */
static u_int type[MAX_CARDS];
static int pcm[MAX_PORTS];
static u_int protocol[MAX_PORTS];
static int layermask[MAX_PORTS];
static int debug;
static int poll;

#ifdef MODULE
MODULE_AUTHOR("Andreas Eversberg");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
MODULE_PARM(debug, "1i");
MODULE_PARM(poll, "1i");
MODULE_PARM(type, MODULE_CARDS_T);
MODULE_PARM(pcm, MODULE_CARDS_T);
MODULE_PARM(protocol, MODULE_PORTS_T);
MODULE_PARM(layermask, MODULE_PORTS_T);
#endif


/*************************/
/* lock and unlock stuff */
/*************************/

static int
lock_dev(void *data, int nowait)
{
	register mISDN_HWlock_t *lock = &((hfc_multi_t *)data)->lock;
	if (debug & DEBUG_HFCMULTI_LOCK)
		printk(KERN_DEBUG "%s\n", __FUNCTION__);
	return(lock_HW(lock, nowait));
}
static void
unlock_dev(void *data)
{
	register mISDN_HWlock_t *lock = &((hfc_multi_t *)data)->lock;
	if (debug & DEBUG_HFCMULTI_LOCK)
		printk(KERN_DEBUG "%s\n", __FUNCTION__);
	unlock_HW(lock);
}

/******************************************/
/* free hardware resources used by driver */
/******************************************/

static void
release_io_hfcmulti(hfc_multi_t *hc)
{
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);

	/* irq off */
	HFC_outb(hc, R_IRQ_CTRL, 0);

	/* soft reset */
	hc->hw.r_cirm |= V_SRES;
	HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
	udelay(10);
	hc->hw.r_cirm &= ~V_SRES;
	HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
	udelay(10); /* instead of 'wait' that may cause locking */

	/* disable memory mapped ports / io ports */
	pci_write_config_word(hc->pci_dev, PCI_COMMAND, 0);
#ifdef CONFIG_HFCMULTI_PCIMEM
	if (hc->pci_membase)
		iounmap((void *)hc->pci_membase);
#else
	if (hc->pci_iobase)
		release_region(hc->pci_iobase, 8);
#endif

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
}

/****************************************************************************/
/* function called to reset the HFC chip. A complete software reset of chip */
/* and fifos is done. All configuration of the chip is done.                */
/****************************************************************************/

static int
init_chip(hfc_multi_t *hc)
{
	u_long val, val2 = 0, rev;
	int cnt = 0;
	int i;
	u_char r_conf_en;

	/* reset all registers */
	memset(&hc->hw, 0, sizeof(hfcmulti_hw_t));

	/* revision check */
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);
	val = HFC_inb(hc, R_CHIP_ID);
	rev = HFC_inb(hc, R_CHIP_RV);
	printk(KERN_INFO "HFC_multi: resetting HFC with chip ID=0x%lx revision=%ld%s\n", val>>4, rev, (rev==0)?" (old FIFO handling)":"");
	if (rev == 0) {
		test_and_set_bit(HFC_CHIP_REVISION0, &hc->chip);
		printk(KERN_WARNING "HFC_multi: NOTE: Your chip is revision 0, ask Cologne Chip for update. Newer chips have a better FIFO handling. Old chips still work but may have slightly lower HDLC transmit performance.\n");
	}
	if (rev > 1) {
		printk(KERN_WARNING "HFC_multi: WARNING: This driver doesn't consider chip revision = %ld. The chip / bridge may not work.\n", rev);
	}

	/* set s-ram size */
	hc->Flen = 0x10;
	hc->Zmin = 0x80;
	hc->Zlen = 384;
	hc->DTMFbase = 0x1000;
	if (test_bit(HFC_CHIP_EXRAM_128, &hc->chip)) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: changing to 128K extenal RAM\n", __FUNCTION__);
		hc->hw.r_ctrl |= V_EXT_RAM;
		hc->hw.r_ram_sz = 1;
		hc->Flen = 0x20;
		hc->Zmin = 0xc0;
		hc->Zlen = 1856;
		hc->DTMFbase = 0x2000;
	}
	if (test_bit(HFC_CHIP_EXRAM_512, &hc->chip)) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: changing to 512K extenal RAM\n", __FUNCTION__);
		hc->hw.r_ctrl |= V_EXT_RAM;
		hc->hw.r_ram_sz = 2;
		hc->Flen = 0x20;
		hc->Zmin = 0xc0;
		hc->Zlen = 8000;
		hc->DTMFbase = 0x2000;
	}

	/* we only want the real Z2 read-pointer for revision > 0 */
	if (!test_bit(HFC_CHIP_REVISION0, &hc->chip))
		hc->hw.r_ram_sz |= V_FZ_MD;

	/* soft reset */
	HFC_outb(hc, R_CTRL, hc->hw.r_ctrl);
	HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);
	HFC_outb(hc, R_FIFO_MD, 0);
	hc->hw.r_cirm = V_SRES | V_HFCRES | V_PCMRES | V_STRES | V_RLD_EPR;
	HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
	udelay(10);
	hc->hw.r_cirm = 0;
	HFC_outb(hc, R_CIRM, hc->hw.r_cirm);
	udelay(10);
	HFC_outb(hc, R_RAM_SZ, hc->hw.r_ram_sz);

	/* set pcm mode & reset */
	if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: setting PCM into slave mode\n", __FUNCTION__);
	} else {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: setting PCM into master mode\n", __FUNCTION__);
		hc->hw.r_pcm_md0 |= V_PCM_MD;
	}
	i = 0;
	HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x90);
	if (hc->slots == 32)
		HFC_outb(hc, R_PCM_MD1, 0x00);
	if (hc->slots == 64)
		HFC_outb(hc, R_PCM_MD1, 0x10);
	if (hc->slots == 128)
		HFC_outb(hc, R_PCM_MD1, 0x20);
	HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0xa0);
	HFC_outb(hc, R_PCM_MD2, 0x00);
	HFC_outb(hc, R_PCM_MD0, hc->hw.r_pcm_md0 | 0x00);
	while (i < 256) {
		HFC_outb_(hc, R_SLOT, i);
		HFC_outb_(hc, A_SL_CFG, 0);
		HFC_outb_(hc, A_CONF, 0);
		hc->slot_owner[i] = -1;
		i++;
	}

	/* set clock speed */
	if (test_bit(HFC_CHIP_CLOCK2, &hc->chip)) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: setting double clock\n", __FUNCTION__);
		HFC_outb(hc, R_BRG_PCM_CFG, V_PCM_CLK);
	}

	/* check if R_F0_CNT counts */
	val = HFC_inb(hc, R_F0_CNTL);
	val += HFC_inb(hc, R_F0_CNTH) << 8;
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "HFC_multi F0_CNT %ld after status ok\n", val);
	unlock_dev(hc);
	set_current_state(TASK_UNINTERRUPTIBLE);
	while (cnt < 50) { /* max 50 ms */
		schedule_timeout((HZ*10)/1000); /* Timeout 10ms */
		cnt+=10;
		val2 = HFC_inb(hc, R_F0_CNTL);
		val2 += HFC_inb(hc, R_F0_CNTH) << 8;
		if (val2 >= val+4) /* wait 4 pulses */
			break;
	}
	lock_dev(hc, 0);
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "HFC_multi F0_CNT %ld after %dms\n", val2, cnt);
	if (val2 < val+4) {
		printk(KERN_ERR "HFC_multi ERROR 125us pulse not counting.\n");
		if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
			printk(KERN_ERR "HFC_multi This happens in PCM slave mode without connected master.\n");
		}
		if (!test_bit(HFC_CHIP_CLOCK_IGNORE, &hc->chip))
			return(-EIO);
	}

	/* set up timer */
	HFC_outb(hc, R_TI_WD, poll_timer);
	hc->hw.r_irqmsk_misc |= V_TI_IRQMSK;

	/* set E1 state machine IRQ */
	if (hc->type == 1)
		hc->hw.r_irqmsk_misc |= V_STA_IRQMSK;

	/* set DTMF detection */
	if (test_bit(HFC_CHIP_DTMF, &hc->chip)) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: enabling DTMF detection for all B-channel\n", __FUNCTION__);
		hc->hw.r_dtmf = V_DTMF_EN | V_DTMF_STOP;
		if (test_bit(HFC_CHIP_ULAW, &hc->chip))
			hc->hw.r_dtmf |= V_ULAW_SEL;
		HFC_outb(hc, R_DTMF_N, 102-1);
		hc->hw.r_irqmsk_misc |= V_DTMF_IRQMSK;
	}

	/* conference engine */
	if (test_bit(HFC_CHIP_ULAW, &hc->chip))
		r_conf_en = V_CONF_EN | V_ULAW;
	else
		r_conf_en = V_CONF_EN;
	HFC_outb(hc, R_CONF_EN, r_conf_en);

	/* setting leds */
	switch(hc->leds) {
		case 1: /* HFC-E1 OEM */
		HFC_outb(hc, R_GPIO_SEL, 0x30);
		HFC_outb(hc, R_GPIO_EN1, 0x0f);
		HFC_outb(hc, R_GPIO_OUT1, 0x00);
		break;

		case 2: /* HFC-4S OEM */
		HFC_outb(hc, R_GPIO_SEL, 0xf0);
		HFC_outb(hc, R_GPIO_EN1, 0xff);
		HFC_outb(hc, R_GPIO_OUT1, 0x00);
		break;
	}

	/* set master clock */
	if (hc->masterclk >= 0) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: setting ST master clock to port %d (0..%d)\n", __FUNCTION__, hc->masterclk, hc->type-1);
		hc->hw.r_st_sync = hc->masterclk | V_AUTO_SYNC;
		HFC_outb(hc, R_ST_SYNC, hc->hw.r_st_sync);
	}

	/* setting misc irq */
	HFC_outb(hc, R_IRQMSK_MISC, hc->hw.r_irqmsk_misc);

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
	return(0);
}


/***************/
/* output leds */
/***************/
static void
hfcmulti_leds(hfc_multi_t *hc)
{
	int i, state, active;
	dchannel_t *dch;
	int led[4];

	hc->ledcount += poll;
	if (hc->ledcount > 4096)
		hc->ledcount -= 4096;

	switch(hc->leds) {
		case 1: /* HFC-E1 OEM */
		/* 2 red blinking: LOS
		   1 red: AIS
		   left green: PH_ACTIVATE
		   right green flashing: FIFO activity
		*/
		i = HFC_inb(hc, R_GPI_IN0) & 0xf0;
		if (!(i & 0x40)) { /* LOS */
			if (hc->e1_switch != i) {
				hc->e1_switch = i;
				hc->hw.r_tx0 &= ~V_OUT_EN;
				HFC_outb(hc, R_TX0, hc->hw.r_tx0);
			}
			if (hc->ledcount & 512)
				led[0] = led[1] = 1;
			else
				led[0] = led[1] = 0;
			led[2] = led[3] = 0;
		} else
		if (!(i & 0x80)) { /* AIS */
			if (hc->e1_switch != i) {
				hc->e1_switch = i;
				hc->hw.r_tx0 |= V_OUT_EN;
				hc->hw.r_tx1 |= V_AIS_OUT;
				HFC_outb(hc, R_TX0, hc->hw.r_tx0);
				HFC_outb(hc, R_TX1, hc->hw.r_tx1);
			}
			if (hc->ledcount & 512)
				led[2] = led[3] = 1;
			else
				led[2] = led[3] = 0;
			led[0] = led[1] = 0;
		} else {
			if (hc->e1_switch != i) {
				/* reset LOS/AIS */
				hc->e1_switch = i;
				hc->hw.r_tx0 |= V_OUT_EN;
				hc->hw.r_tx1 &= ~V_AIS_OUT;
				HFC_outb(hc, R_TX0, hc->hw.r_tx0);
				HFC_outb(hc, R_TX1, hc->hw.r_tx1);
			}
			if (HFC_inb_(hc, R_RX_STA0) & V_SIG_LOS) {
				if (hc->ledcount>>11)
					led[0] = led[1] = 1; /* both red blinking */
				else
					led[0] = led[1] = 0;
			} else
			if (HFC_inb_(hc, R_RX_STA0) & V_AIS) {
				led[0] = led[1] = 1; /* both red */
			} else {
				led[0] = led[1] = 0; /* no red */
			}
			state = 0;
			active = 1;
			if ((dch = hc->chan[16].dch)) {
				state = dch->ph_state;
			}
			if (state == active) {
				led[2] = 1; /* left green */
				if (hc->activity[0]) {
					led[3] = 1; /* right green */
					hc->activity[0] = 0;
				} else
					led[3] = 0; /* no right green */

			} else
				led[2] = led[3] = 0; /* no green */
		}
		HFC_outb(hc, R_GPIO_OUT1,
			(led[0] | (led[1]<<2) | (led[2]<<1) | (led[3]<<3))^0xf); /* leds are inverted */

		break;

		case 2: /* HFC-4S OEM */
		/* red blinking = PH_DEACTIVATE
		   red steady = PH_ACTIVATE
		   green flashing = fifo activity
		*/
		i = 0;
		while(i < 4) {
			state = 0;
			active = -1;
			if ((dch = hc->chan[(i<<2)|2].dch)) {
				state = dch->ph_state;
				active = test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7;
			}
			if (state) {
				if (state==active) {
					if (hc->activity[i]) {
						led[i] = 1; /* led green */
						hc->activity[i] = 0;
					} else
						led[i] = 2; /* led red */
				} else if (hc->ledcount>>11)
					led[i] = 2; /* led red */
				else
					led[i] = 0; /* led off */
			} else
				led[i] = 0; /* led off */
			i++;
		}
//printk("leds %d %d %d %d\n", led[0], led[1], led[2], led[3]);
		HFC_outb(hc, R_GPIO_EN1,
			((led[0]>0)<<0) | ((led[1]>0)<<1) |
			((led[2]>0)<<2) | ((led[3]>0)<<3));
		HFC_outb(hc, R_GPIO_OUT1,
			((led[0]&1)<<0) | ((led[1]&1)<<1) |
			((led[2]&1)<<2) | ((led[3]&1)<<3));
		break;
	}
}
/**************************/
/* read dtmf coefficients */
/**************************/

/*
static void
hfcmulti_dtmf(hfc_multi_t *hc)
{
	signed long coeff[16];
	unsigned long mantissa;
	int co, ch;
	bchannel_t *bch = NULL;
	unsigned char exponent;
	int dtmf = 0;
	int addr;
	unsigned short w_float;
	struct sk_buff *skb;

	if (debug & DEBUG_HFCMULTI_DTMF)
		printk(KERN_DEBUG "%s: dtmf detection irq\n", __FUNCTION__);
	ch = 0;
	while(ch < 32) {
		// only process enabled B-channels
		if (!(bch = hc->chan[ch].bch)) {
			ch++;
			continue;
		}
		if (!hc->created[hc->chan[ch].port]) {
			ch++;
			continue;
		}
		if (bch->protocol != ISDN_PID_L1_B_64TRANS) {
			ch++;
			continue;
		}
		if (debug & DEBUG_HFCMULTI_DTMF)
			printk(KERN_DEBUG "%s: dtmf channel %d:", __FUNCTION__, ch);
		dtmf = 1;
		co = 0;
		while(co < 8) {
			// read W(n-1) coefficient
			addr = hc->DTMFbase + ((co<<7) | (ch<<2));
			HFC_outb_(hc, R_RAM_ADDR0, addr);
			HFC_outb_(hc, R_RAM_ADDR1, addr>>8);
			HFC_outb_(hc, R_RAM_ADDR2, (addr>>16) | V_ADDR_INC);
			w_float = HFC_inb_(hc, R_RAM_DATA);
#ifdef CONFIG_HFCMULTI_PCIMEM
			w_float |= (HFC_inb_(hc, R_RAM_DATA) << 8);
#else
			w_float |= (HFC_getb(hc) << 8);
#endif
			if (debug & DEBUG_HFCMULTI_DTMF)
				printk(" %04x", w_float);

			// decode float (see chip doc)
			mantissa = w_float & 0x0fff;
			if (w_float & 0x8000)
				mantissa |= 0xfffff000;
			exponent = (w_float>>12) & 0x7;
			if (exponent) {
				mantissa ^= 0x1000;
				mantissa <<= (exponent-1);
			}

			// store coefficient
			coeff[co<<1] = mantissa;

			// read W(n) coefficient
acnt			w_float = HFC_inb_(hc, R_RAM_DATA);
#ifdef CONFIG_HFCMULTI_PCIMEM
			w_float |= (HFC_inb_(hc, R_RAM_DATA) << 8);
#else
			w_float |= (HFC_getb(hc) << 8);
#endif
			if (debug & DEBUG_HFCMULTI_DTMF)
				printk(" %04x", w_float);

			// decode float (see chip doc)
			mantissa = w_float & 0x0fff;
			if (w_float & 0x8000)
				mantissa |= 0xfffff000;
			exponent = (w_float>>12) & 0x7;
			if (exponent) {
				mantissa ^= 0x1000;
				mantissa <<= (exponent-1);
			}

			// store coefficient
			coeff[(co<<1)|1] = mantissa;
			co++;
		}
		if (debug & DEBUG_HFCMULTI_DTMF)
			printk("\n");
		skb = create_link_skb(PH_CONTROL | INDICATION, HW_HFC_COEFF, sizeof(coeff), coeff, 0);
		if (!skb) {
			printk(KERN_WARNING "%s: No memory for skb\n", __FUNCTION__);
			ch++;
			continue;
		}
		skb_queue_tail(&hc->chan[ch].dtmfque, skb);
		bch_sched_event(bch, B_DTMFREADY);
		ch++;
	}

	// restart DTMF processing
	hc->dtmf = dtmf;
	if (dtmf)
		HFC_outb_(hc, R_DTMF, hc->hw.r_dtmf | V_RST_DTMF);
}
*/


/*********************************/
/* fill fifo as much as possible */
/*********************************/

static void
hfcmulti_tx(hfc_multi_t *hc, int ch, dchannel_t *dch, bchannel_t *bch)
{
	int i, ii, temp;
	int Zspace, z1, z2;
	int Fspace, f1, f2;
	unsigned char *d, *dd, *buf = NULL;
	int *len = NULL, *idx = NULL; /* = NULL, to make GCC happy */
	int txpending, slot_tx;
	int hdlc = 0;

	/* get skb, fifo & mode */
	if (dch) {
		buf = dch->tx_buf;
		len = &dch->tx_len;
		idx = &dch->tx_idx;
		hdlc = 1;
	}
	if (bch) {
		buf = bch->tx_buf;
		len = &bch->tx_len;
		idx = &bch->tx_idx;
		if (bch->protocol == ISDN_PID_L1_B_64HDLC)
			hdlc = 1;
	}
	txpending = hc->chan[ch].txpending;
	slot_tx = hc->chan[ch].slot_tx;
	if ((!(*len)) && txpending!=1)
		return; /* no data */

//printk("debug: data: len = %d, txpending = %d!!!!\n", *len, txpending);
	/* lets see how much data we will have left in buffer */
	HFC_outb_(hc, R_FIFO, ch<<1);
	HFC_wait_(hc);
	if (txpending == 2) {
		/* reset fifo */
		HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait_(hc);
		HFC_outb(hc, A_SUBCH_CFG, 0);
		txpending = 1;
	}
next_frame:
	if (hdlc) {
		f1 = HFC_inb_(hc, A_F1);
		f2 = HFC_inb_(hc, A_F2);
		while (f2 != (temp=HFC_inb_(hc, A_F2))) {
			if (debug & DEBUG_HFCMULTI_FIFO)
				printk(KERN_DEBUG "%s: reread f2 because %d!=%d\n", __FUNCTION__, temp, f2);
			f2 = temp; /* repeat until F2 is equal */
		}
		Fspace = f2-f1-1;
		if (Fspace < 0)
			Fspace += hc->Flen;
		/* Old FIFO handling doesn't give us the current Z2 read
		 * pointer, so we cannot send the next frame before the fifo
		 * is empty. It makes no difference except for a slightly
		 * lower performance.
		 */
		if (test_bit(HFC_CHIP_REVISION0, &hc->chip)) {
			if (f1 != f2)
				Fspace = 0;
			else
				Fspace = 1;
		}
		/* one frame only for ST D-channels, to allow resending */
		if (hc->type!=1 && dch) {
			if (f1 != f2)
				Fspace = 0;
		}
		/* F-counter full condition */
		if (Fspace == 0)
			return;
	}
	z1 = HFC_inw_(hc, A_Z1) - hc->Zmin;
	z2 = HFC_inw_(hc, A_Z2) - hc->Zmin;
	while(z2 != (temp=(HFC_inw_(hc, A_Z2) - hc->Zmin))) {
		if (debug & DEBUG_HFCMULTI_FIFO)
			printk(KERN_DEBUG "%s: reread z2 because %d!=%d\n", __FUNCTION__, temp, z2);
		z2 = temp; /* repeat unti Z2 is equal */
	}
	Zspace = z2-z1-1;
	if (Zspace < 0)
		Zspace += hc->Zlen;
	/* buffer too full, there must be at least one more byte for 0-volume */
	if (Zspace < 4) /* just to be safe */
		return;

	/* if no data */
	if (!(*len)) {
		if (z1 == z2) { /* empty */
			/* if done with FIFO audio data during PCM connection */
			if (!hdlc && txpending && slot_tx>=0) {
				if (debug & DEBUG_HFCMULTI_MODE)
					printk(KERN_DEBUG "%s: reconnecting PCM due to no more FIFO data: channel %d slot_tx %d\n", __FUNCTION__, ch, slot_tx);

				/* connect slot */
				HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
				HFC_outb_(hc, R_FIFO, ch<<1 | 1);
				HFC_wait_(hc);
				HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
				HFC_outb_(hc, R_FIFO, ch<<1);
				HFC_wait_(hc);
			}
			txpending = hc->chan[ch].txpending = 0;
		}
		return; /* no data */
	}

	/* if audio data */
	if (!hdlc && !txpending && slot_tx>=0) {
		if (debug & DEBUG_HFCMULTI_MODE)
			printk(KERN_DEBUG "%s: disconnecting PCM due to FIFO data: channel %d slot_tx %d\n", __FUNCTION__, ch, slot_tx);
		/* disconnect slot */
		HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
		HFC_outb_(hc, R_FIFO, ch<<1 | 1);
		HFC_wait_(hc);
		HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
		HFC_outb_(hc, R_FIFO, ch<<1);
		HFC_wait_(hc);
	}
	txpending = hc->chan[ch].txpending = 1;

	/* show activity */
	hc->activity[hc->chan[ch].port] = 1;

	/* fill fifo to what we have left */
	i = *idx;
	ii = *len;
	d = buf + i;
	if (ii-i > Zspace)
		ii = Zspace+i;
	if (debug & DEBUG_HFCMULTI_FIFO) {
		printk(KERN_DEBUG "%s: fifo(%d) has %d bytes space left (z1=%04x, z2=%04x) sending %d of %d bytes %s\n",
			__FUNCTION__, ch, Zspace, z1, z2, ii-i, (*len)-i, hdlc?"HDLC":"TRANS");
	}
#ifdef FIFO_32BIT_ACCESS
#ifndef CONFIG_HFCMULTI_PCIMEM
	HFC_set(hc, A_FIFO_DATA0);
#endif
	dd = d + ((ii-i)&0xfffc);
	i += (ii-i) & 0xfffc;
	while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
		HFC_outl_(hc, A_FIFO_DATA0, *((unsigned long *)d));
#else
		HFC_putl(hc, *((unsigned long *)d));
#endif
//		if (debug & DEBUG_HFCMULTI_FIFO)
//			printk("%02x %02x %02x %02x ", d[0], d[1], d[2], d[3]);
		d+=4;
	}
#endif
	dd = d + (ii-i);
	while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
		HFC_outb_(hc, A_FIFO_DATA0, *d);
#else
		HFC_putb(hc, *d);
#endif
//		if (debug & DEBUG_HFCMULTI_FIFO)
//			printk("%02x ", d[0]);
		d++;
	}
//	if (debug & DEBUG_HFCMULTI_FIFO)
//		printk("\n");
	*idx = ii;

	/* if not all data has been written */
	if (ii != *len) {
		/* NOTE: fifo is started by the calling function */
		return;
	}

	/* if all data has been written */
	if (hdlc) {
		/* increment f-counter */
		HFC_outb_(hc, R_INC_RES_FIFO, V_INC_F);
		HFC_wait_(hc);
	}
	if (dch) {
		// check for next frame
		/*if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
			if (dch->next_skb) {
				dch->tx_idx = 0;
				dch->tx_len = dch->next_skb->len;
				memcpy(dch->tx_buf, dch->next_skb->data, dch->tx_len);
				dchannel_sched_event(dch, D_XMTBUFREADY);
				goto next_frame;
			} else
				printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (dch ch=%d)\n", __FUNCTION__, ch);
		} */

		// check for next frame
		if (test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags)) {
			struct sk_buff	*skb = dch->next_skb;
			mISDN_head_t	*hh;
			if (skb) {
				dch->next_skb = NULL;
				hh = mISDN_HEAD_P(skb);
				dch->tx_idx = 0;
				dch->tx_len = skb->len;
				memcpy(dch->tx_buf, skb->data, dch->tx_len);
				skb_trim(skb, 0);
				if (mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_CNF, hh->dinfo, skb)) dev_kfree_skb(skb);
				goto next_frame;
			} else
				printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (dch ch=%d)\n", __FUNCTION__, ch);
		}

		test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
		dch->tx_idx = dch->tx_len = 0;
	}
	if (bch) {
		// check for next frame      TODO changed
		/* if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
			if (bch->next_skb) {
				bch->tx_idx = 0;
				bch->tx_len = bch->next_skb->len;
				memcpy(bch->tx_buf, bch->next_skb->data, bch->tx_len);
				bch_sched_event(bch, B_XMTBUFREADY);
				goto next_frame;
			} else
				printk(KERN_WARNING "%s: tx irq TX_NEXT without skb (bch ch=%d)\n", __FUNCTION__, ch);
		} */
		// check for next frame
		if (test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag)) {
			struct sk_buff	*skb = bch->next_skb;
			mISDN_head_t	*hh;
			u_int		pr;
			if (skb) {
				bch->next_skb = NULL;
				hh = mISDN_HEAD_P(skb);
				bch->tx_idx = 0;
				bch->tx_len = skb->len;
				memcpy(bch->tx_buf, skb->data, bch->tx_len);
				skb_trim(skb, 0);
				if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
					pr = DL_DATA | CONFIRM;
				else
					pr = PH_DATA | CONFIRM;
				if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, hh->dinfo, skb))) {
					int_error();
					dev_kfree_skb(skb);
				}
				goto next_frame;
			} else
				printk(KERN_WARNING "hfcB tx irq TX_NEXT without skb\n");
		}

		test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
		bch->tx_idx = bch->tx_len = 0;
	}
	/* now we have no more data, so in case of transparent,
	 * we set the last byte in fifo to 'silence' in case we will get
	 * no more data at all. this prevents sending an undefined value.
	 */
	if (!hdlc)
		HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
}


/**************/
/* empty fifo */
/**************/

static void
hfcmulti_rx(hfc_multi_t *hc, int ch, dchannel_t *dch, bchannel_t *bch)
{
	int ii, temp;
	int Zsize, z1, z2 = 0; /* = 0, to make GCC happy */
	int f1 = 0, f2 = 0; /* = 0, to make GCC happy */
	unsigned char *d, *dd, *buf = NULL;
	int *idx = NULL, max = 0; /* = 0, to make GCC happy */
	int hdlc = 0;
	struct sk_buff *skb;
	u_int 	pr;

	/* get skb, fifo & mode */
	if (dch) {
		buf = hc->chan[ch].rx_buf;
		idx = &hc->chan[ch].rx_idx;
		max = MAX_DFRAME_LEN_L1;
		hdlc = 1;
	}
	if (bch) {
		buf = bch->rx_buf;
		idx = &bch->rx_idx;
		max = MAX_DATA_MEM;
		if (bch->protocol == ISDN_PID_L1_B_64HDLC)
			hdlc = 1;
	}

	/* lets see how much data we received */
	HFC_outb_(hc, R_FIFO, (ch<<1)|1);
	HFC_wait_(hc);
next_frame:
#if 0
	/* set Z2(F1) */
	HFC_outb_(hc, R_RAM_SZ, hc->hw.r_ram_sz & ~V_FZ_MD);
#endif
	if (hdlc) {
		f1 = HFC_inb_(hc, A_F1);
		while (f1 != (temp=HFC_inb_(hc, A_F1))) {
			if (debug & DEBUG_HFCMULTI_FIFO)
				printk(KERN_DEBUG "%s: reread f1 because %d!=%d\n", __FUNCTION__, temp, f1);
			f1 = temp; /* repeat until F1 is equal */
		}
		f2 = HFC_inb_(hc, A_F2);
	}
	z1 = HFC_inw_(hc, A_Z1) - hc->Zmin;
	while(z1 != (temp=(HFC_inw_(hc, A_Z1) - hc->Zmin))) {
		if (debug & DEBUG_HFCMULTI_FIFO)
			printk(KERN_DEBUG "%s: reread z2 because %d!=%d\n", __FUNCTION__, temp, z2);
		z1 = temp; /* repeat unti Z1 is equal */
	}
	z2 = HFC_inw_(hc, A_Z2) - hc->Zmin;
	Zsize = z1-z2;
	if (hdlc && f1!=f2) /* complete hdlc frame */
		Zsize++;
	if (Zsize < 0)
		Zsize += hc->Zlen;
	/* if buffer is empty */
	if (Zsize <= 0)
		return;

	/* show activity */
	hc->activity[hc->chan[ch].port] = 1;

	/* empty fifo with what we have */
	if (hdlc) {
		if (debug & DEBUG_HFCMULTI_FIFO)
			printk(KERN_DEBUG "%s: fifo(%d) reading %d bytes (z1=%04x, z2=%04x) HDLC %s (f1=%d, f2=%d) got=%d\n",
				__FUNCTION__, ch, Zsize, z1, z2, (f1==f2)?"fragment":"COMPLETE", f1, f2, Zsize+*idx);
		/* HDLC */
		ii = Zsize;
		if ((ii + *idx) > max) {
			if (debug & DEBUG_HFCMULTI_FIFO)
				printk(KERN_DEBUG "%s: hdlc-frame too large.\n", __FUNCTION__);
			*idx = 0;
			HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
			HFC_wait_(hc);
			return;
		}
		d = buf + *idx;
#ifdef FIFO_32BIT_ACCESS
#ifndef CONFIG_HFCMULTI_PCIMEM
		HFC_set(hc, A_FIFO_DATA0);
#endif
		dd = d + (ii&0xfffc);
		while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
			*((unsigned long *)d) = HFC_inl_(hc, A_FIFO_DATA0);
#else
			*((unsigned long *)d) = HFC_getl(hc);
#endif
			d+=4;
		}
		dd = d + (ii&0x0003);
#else
		dd = d + ii;
#endif
		while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
			*d++ = HFC_inb_(hc, A_FIFO_DATA0);
#else
			*d++ = HFC_getb(hc);
#endif
		}
		*idx += ii;
		if (f1 != f2) {
			/* increment Z2,F2-counter */
			HFC_outb_(hc, R_INC_RES_FIFO, V_INC_F);
			HFC_wait_(hc);
			/* check size */
			if (*idx < 4) {
				if (debug & DEBUG_HFCMULTI_FIFO)
					printk(KERN_DEBUG "%s: Frame below minimum size\n", __FUNCTION__);
				return;
			}
			/* there is at least one complete frame, check crc */
			if (buf[(*idx)-1]) {
				if (debug & DEBUG_HFCMULTI_CRC)
					printk(KERN_DEBUG "%s: CRC-error\n", __FUNCTION__);
				return;
			}
			/* only send dchannel if in active state */
			if (dch && hc->type==1 && hc->chan[ch].e1_state!=1)
				return;
			if (!(skb = alloc_stack_skb((*idx)-3, (bch)?bch->up_headerlen:dch->up_headerlen))) {
				printk(KERN_DEBUG "%s: No mem for skb\n", __FUNCTION__);
				return;
			}
			memcpy(skb_put(skb, (*idx)-3), buf, (*idx)-3);
			if (debug & DEBUG_HFCMULTI_FIFO) {
				temp = 0;
				while(temp < (*idx)-3)
					printk("%02x ", skb->data[temp++]);
				printk("\n");
			}
			if (dch) {
				if (debug & DEBUG_HFCMULTI_FIFO)
					printk(KERN_DEBUG "%s: sending D-channel frame to user space.\n", __FUNCTION__);
				// schedule D-channel event   TODO: changed
				//skb_queue_tail(&dch->rqueue, skb);
				//dchannel_sched_event(dch, D_RCVBUFREADY);
				mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb);
			}
			if (bch) {
				// schedule B-channel event TODO: changed
				//skb_queue_tail(&bch->rqueue, skb);
				//bch_sched_event(bch, B_RCVBUFREADY);
				if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
					pr = DL_DATA | INDICATION;
				else
					pr = PH_DATA | INDICATION;
				if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {   // TODO: ask Karsten for unlikely
					int_error();
					dev_kfree_skb(skb);
				}
			}
			*idx = 0;
			goto next_frame;
		}
		/* there is an incomplete frame */
	} else {
		/* transparent */
		ii = Zsize;
		if (ii > MAX_DATA_MEM)
			ii = MAX_DATA_MEM;
		if (!(skb = alloc_stack_skb(ii, bch->up_headerlen))) {
			printk(KERN_DEBUG "%s: No mem for skb\n", __FUNCTION__);
			HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
			HFC_wait_(hc);
			return;
		}
		if (debug & DEBUG_HFCMULTI_FIFO)
			printk(KERN_DEBUG "%s: fifo(%d) reading %d bytes (z1=%04x, z2=%04x) TRANS\n",
				__FUNCTION__, ch, ii, z1, z2);
		d = skb_put(skb, ii);
#ifdef FIFO_32BIT_ACCESS
#ifndef CONFIG_HFCMULTI_PCIMEM
		HFC_set(hc, A_FIFO_DATA0);
#endif
		dd = d + (ii&0xfffc);
		while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
			*((unsigned long *)d) = HFC_inl_(hc, A_FIFO_DATA0);
#else
			*((unsigned long *)d) = HFC_getl(hc);
#endif
			d+=4;
		}
#endif
		dd = d + (ii&0x0003);
		while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
			*d++ = HFC_inb_(hc, A_FIFO_DATA0);
#else
			*d++ = HFC_getb(hc);
#endif
		}
		if (dch) {
			// schedule D-channel event
			//skb_queue_tail(&dch->rqueue, skb);
			//dchannel_sched_event(dch, D_RCVBUFREADY);
			mISDN_queueup_newhead(&dch->inst, 0, PH_DATA_IND, MISDN_ID_ANY, skb);
		}
		if (bch) {
			// schedule B-channel event
			//skb_queue_tail(&bch->rqueue, skb);
			//bch_sched_event(bch, B_RCVBUFREADY);
			if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
				pr = DL_DATA | INDICATION;
			else
				pr = PH_DATA | INDICATION;
			if (unlikely(mISDN_queueup_newhead(&bch->inst, 0, pr, MISDN_ID_ANY, skb))) {   // TODO_ ask Karsten for unlikely
				int_error();
				dev_kfree_skb(skb);
			}
		}
	}
}


/*********************/
/* Interrupt handler */
/*********************/

static irqreturn_t
hfcmulti_interrupt(int intno, void *dev_id, struct pt_regs *regs)
{
	hfc_multi_t *hc = dev_id;
	bchannel_t *bch;
	dchannel_t *dch;
	u_long flags;
	u_char r_irq_statech, status, r_irq_misc, r_irq_oview, r_irq_fifo_bl;
	int ch;
	int i, j;
	int temp;

	spin_lock_irqsave(&hc->lock.lock, flags);
#ifdef SPIN_DEBUG
	hc->lock.spin_adr = (void *)0x3001;
#endif

	if (!hc) {
		printk(KERN_WARNING "HFC-multi: Spurious interrupt!\n");
		irq_notforus:
#ifdef SPIN_DEBUG
		hc->lock.spin_adr = NULL;
#endif
		spin_unlock_irqrestore(&hc->lock.lock, flags);
		return(IRQ_NONE);
	}

	status = HFC_inb_(hc, R_STATUS);
	r_irq_statech = HFC_inb_(hc, R_IRQ_STATECH);
	if (!r_irq_statech && !(status & (V_DTMF_STA | V_LOST_STA | V_EXT_IRQSTA | V_MISC_IRQSTA | V_FR_IRQSTA))) {
		/* irq is not for us */
		goto irq_notforus;
	}
	hc->irqcnt++;
	if (test_and_set_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
		printk(KERN_ERR "%s: STATE_FLAG_BUSY allready activ, should never happen state:%lx\n",
			__FUNCTION__, hc->lock.state);
#ifdef SPIN_DEBUG
		printk(KERN_ERR "%s: previous lock:%p\n",
			__FUNCTION__, hc->lock.busy_adr);
#endif
#ifdef LOCK_STATISTIC
		hc->lock.irq_fail++;
#endif
	} else {
#ifdef LOCK_STATISTIC
		hc->lock.irq_ok++;
#endif
#ifdef SPIN_DEBUG
		hc->lock.busy_adr = hfcmulti_interrupt;
#endif
	}

	test_and_set_bit(STATE_FLAG_INIRQ, &hc->lock.state);
#ifdef SPIN_DEBUG
        hc->lock.spin_adr= NULL;
#endif
	spin_unlock_irqrestore(&hc->lock.lock, flags);

	if (r_irq_statech) {
		if (hc->type != 1) {
			/* state machine */
			ch = 0;
			while(ch < 32) {
				if ((dch = hc->chan[ch].dch)) {
					if (r_irq_statech & 1) {
						HFC_outb_(hc, R_ST_SEL, hc->chan[ch].port);
						dch->ph_state = HFC_inb(hc, A_ST_RD_STATE) & 0x0f;
						if (dch->ph_state == (test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)?3:7)) {
							HFC_outb_(hc, R_FIFO, (ch<<1)|1);
							HFC_wait_(hc);
							HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
							HFC_wait_(hc);
						}

						//dchannel_sched_event(dch, D_L1STATECHANGE);
						ph_state_change(dch);
						if (debug & DEBUG_HFCMULTI_STATE)
							printk(KERN_DEBUG "%s: S/T newstate %x port %d\n", __FUNCTION__, dch->ph_state, hc->chan[ch].port);
					}
					r_irq_statech >>= 1;
				}
				ch++;
			}
		}
	}
	if (status & V_EXT_IRQSTA) {
		/* external IRQ */
	}
	if (status & V_LOST_STA) {
		/* LOST IRQ */
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_LOST); /* clear irq! */
	}
	if (status & V_MISC_IRQSTA) {
		/* misc IRQ */
		r_irq_misc = HFC_inb_(hc, R_IRQ_MISC);
		if (r_irq_misc & V_STA_IRQ) {
			if (hc->type == 1) {
				/* state machine */
				dch = hc->chan[16].dch;
				dch->ph_state = HFC_inb_(hc, R_E1_RD_STA) & 0x7;
				//dchannel_sched_event(dch, D_L1STATECHANGE);
				ph_state_change(dch);
				if (debug & DEBUG_HFCMULTI_STATE)
					printk(KERN_DEBUG "%s: E1 newstate %x\n", __FUNCTION__, dch->ph_state);
			}
		}
		if (r_irq_misc & V_TI_IRQ) {
			/* -> timer IRQ */
			ch = 0;
			while(ch < 32) {
				if ((dch = hc->chan[ch].dch))
				if (hc->created[hc->chan[ch].port]) {
					hfcmulti_tx(hc, ch, dch, NULL);
					/* fifo is started when switching to rx-fifo */
					hfcmulti_rx(hc, ch, dch, NULL);
					if (hc->chan[ch].nt_timer > -1) {
						if (!(--hc->chan[ch].nt_timer)) {
							//dchannel_sched_event(dch, D_L1STATECHANGE);
							ph_state_change(dch);
							if (debug & DEBUG_HFCMULTI_STATE)
								printk(KERN_DEBUG "%s: nt_timer at state %x\n", __FUNCTION__, dch->ph_state);
						}
					}
				}
				if ((bch = hc->chan[ch].bch))
				if (hc->created[hc->chan[ch].port]) {
					if (bch->protocol != ISDN_PID_NONE) {
						hfcmulti_tx(hc, ch, NULL, bch);
						/* fifo is started when switching to rx-fifo */
						hfcmulti_rx(hc, ch, NULL, bch);
					}
				}
				ch++;
			}
			if (hc->type == 1)
			if (hc->created[0]) {
				if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[16].cfg)) {
					if (debug & DEBUG_HFCMULTI_SYNC)
						printk(KERN_DEBUG "%s: (id=%d) E1 got LOS\n", __FUNCTION__, hc->id);
					/* LOS */
					temp = HFC_inb_(hc, R_RX_STA0) & V_SIG_LOS;
					//if (!temp && hc->chan[16].los) dchannel_sched_event(dch, D_LOS);  TODO
					//if (temp && !hc->chan[16].los) dchannel_sched_event(dch, D_LOS_OFF);
					hc->chan[16].los = temp;
				}
				if (test_bit(HFC_CFG_REPORT_AIS, &hc->chan[16].cfg)) {
					if (debug & DEBUG_HFCMULTI_SYNC)
						printk(KERN_DEBUG "%s: (id=%d) E1 got AIS\n", __FUNCTION__, hc->id);
					/* AIS */
					temp = HFC_inb_(hc, R_RX_STA0) & V_AIS;
					//if (!temp && hc->chan[16].ais) dchannel_sched_event(dch, D_AIS);  TODO
					//if (!temp && hc->chan[16].ais) dchannel_sched_event(dch, D_AIS_OFF);
					hc->chan[16].ais = temp;
				}
				if (test_bit(HFC_CFG_REPORT_SLIP, &hc->chan[16].cfg)) {
					if (debug & DEBUG_HFCMULTI_SYNC)
						printk(KERN_DEBUG "%s: (id=%d) E1 got SLIP (RX)\n", __FUNCTION__, hc->id);
					/* SLIP */
					temp = HFC_inb_(hc, R_SLIP) & V_FOSLIP_RX;
					//if (!temp && hc->chan[16].slip_rx) dchannel_sched_event(dch, D_SLIP_RX);  TODO
					hc->chan[16].slip_rx = temp;
					temp = HFC_inb_(hc, R_SLIP) & V_FOSLIP_TX;
					//if (!temp && hc->chan[16].slip_tx) dchannel_sched_event(dch, D_SLIP_TX);   TODO
					hc->chan[16].slip_tx = temp;
				}
				temp = HFC_inb_(hc, R_JATT_DIR);
				switch(hc->chan[16].sync) {
					case 0:
					if ((temp&0x60) == 0x60) {
						if (debug & DEBUG_HFCMULTI_SYNC)
							printk(KERN_DEBUG "%s: (id=%d) E1 now in clock sync\n", __FUNCTION__, hc->id);
						HFC_outb(hc, R_RX_OFF, hc->chan[16].jitter | V_RX_INIT);
						HFC_outb(hc, R_TX_OFF, hc->chan[16].jitter | V_RX_INIT);
						hc->chan[16].sync = 1;
						goto check_framesync;
					}
					break;

					case 1:
					if ((temp&0x60) != 0x60) {
						if (debug & DEBUG_HFCMULTI_SYNC)
							printk(KERN_DEBUG "%s: (id=%d) E1 lost clock sync\n", __FUNCTION__, hc->id);
						hc->chan[16].sync = 0;
						break;
					}
					check_framesync:
					temp = HFC_inb_(hc, R_RX_STA0);
					if (temp == 0x27) {
						if (debug & DEBUG_HFCMULTI_SYNC)
							printk(KERN_DEBUG "%s: (id=%d) E1 now in frame sync\n", __FUNCTION__, hc->id);
						hc->chan[16].sync = 2;
					}
					break;

					case 2:
					if ((temp&0x60) != 0x60) {
						if (debug & DEBUG_HFCMULTI_SYNC)
							printk(KERN_DEBUG "%s: (id=%d) E1 lost clock & frame sync\n", __FUNCTION__, hc->id);
						hc->chan[16].sync = 0;
						break;
					}
					temp = HFC_inb_(hc, R_RX_STA0);
					if (temp != 0x27) {
						if (debug & DEBUG_HFCMULTI_SYNC)
							printk(KERN_DEBUG "%s: (id=%d) E1 lost frame sync\n", __FUNCTION__, hc->id);
						hc->chan[16].sync = 1;
					}
					break;
				}
			}
			if (hc->leds)
				hfcmulti_leds(hc);
		}

		//if (r_irq_misc & V_DTMF_IRQ) {   TODO: Re-enable DTMF recognition
		//	/* -> DTMF IRQ */
		//	hfcmulti_dtmf(hc);
		//}
	}
	if (status & V_FR_IRQSTA) {
		/* FIFO IRQ */
		r_irq_oview = HFC_inb_(hc, R_IRQ_OVIEW);
		i = 0;
		while(i < 8) {
			if (r_irq_oview & (1 << i)) {
				r_irq_fifo_bl = HFC_inb_(hc, R_IRQ_FIFO_BL0 + i);
				j = 0;
				while(j < 8) {
					ch = (i<<2) + (j>>1);
					if (r_irq_fifo_bl & (1 << j)) {
						if ((dch = hc->chan[ch].dch))
						if (hc->created[hc->chan[ch].port]) {
							hfcmulti_tx(hc, ch, dch, NULL);
							/* start fifo */
							HFC_outb_(hc, R_FIFO, 0);
							HFC_wait_(hc);
						}
						if ((bch = hc->chan[ch].bch))
						if (hc->created[hc->chan[ch].port]) {
							if (bch->protocol != ISDN_PID_NONE) {
								hfcmulti_tx(hc, ch, NULL, bch);
								/* start fifo */
								HFC_outb_(hc, R_FIFO, 0);
								HFC_wait_(hc);
							}
						}
					}
					j++;
					if (r_irq_fifo_bl & (1 << j)) {
						if ((dch = hc->chan[ch].dch))
						if (hc->created[hc->chan[ch].port]) {
							hfcmulti_rx(hc, ch, dch, NULL);
						}
						if ((bch = hc->chan[ch].bch))
						if (hc->created[hc->chan[ch].port]) {
							if (bch->protocol != ISDN_PID_NONE) {
								hfcmulti_rx(hc, ch, NULL, bch);
							}
						}
					}
					j++;
				}
			}
			i++;
		}
	}

	spin_lock_irqsave(&hc->lock.lock, flags);
#ifdef SPIN_DEBUG
	hc->lock.spin_adr = (void *)0x3002;
#endif
	if (!test_and_clear_bit(STATE_FLAG_INIRQ, &hc->lock.state)) {
	}
	if (!test_and_clear_bit(STATE_FLAG_BUSY, &hc->lock.state)) {
		printk(KERN_ERR "%s: STATE_FLAG_BUSY not locked state(%lx)\n",
			__FUNCTION__, hc->lock.state);
	}
#ifdef SPIN_DEBUG
	hc->lock.busy_adr = NULL;
	hc->lock.spin_adr = NULL;
#endif
	spin_unlock_irqrestore(&hc->lock.lock, flags);
	return IRQ_HANDLED;
}


/********************************************************************/
/* timer callback for D-chan busy resolution. Currently no function */
/********************************************************************/

static void
hfcmulti_dbusy_timer(hfc_multi_t *hc)
{
}


/***************************************************************/
/* activate/deactivate hardware for selected channels and mode */
/***************************************************************/

/* configure B-channel with the given protocol
 * ch eqals to the HFC-channel (0-31)
 * ch is the number of channel (0-4,4-7,8-11,12-15,16-19,20-23,24-27,28-31 for S/T, 1-31 for E1)
 * the hdlc interrupts will be set/unset
 *
 */
static int
mode_hfcmulti(hfc_multi_t *hc, int ch, int protocol, int slot_tx, int bank_tx, int slot_rx, int bank_rx)
{
	int flow_tx = 0, flow_rx = 0, routing = 0;
	int oslot_tx = hc->chan[ch].slot_tx;
	int oslot_rx = hc->chan[ch].slot_rx;
	int conf = hc->chan[ch].conf;

	if (debug & DEBUG_HFCMULTI_MODE)
		printk(KERN_DEBUG "%s: channel %d protocol %x slot %d bank %d (TX) slot %d bank %d (RX)\n", __FUNCTION__, ch, protocol, slot_tx, bank_tx, slot_rx, bank_rx);

	if (oslot_tx>=0 && slot_tx!=oslot_tx) {
		/* remove from slot */
		if (debug & DEBUG_HFCMULTI_MODE)
			printk(KERN_DEBUG "%s: remove from slot %d (TX)\n", __FUNCTION__, oslot_tx);
		if (hc->slot_owner[oslot_tx<<1] == ch) {
			HFC_outb(hc, R_SLOT, oslot_tx<<1);
			HFC_outb(hc, A_SL_CFG, 0);
			HFC_outb(hc, A_CONF, 0);
			hc->slot_owner[oslot_tx<<1] = -1;
		} else {
			if (debug & DEBUG_HFCMULTI_MODE)
				printk(KERN_DEBUG "%s: we are not owner of this slot anymore, channel %d is.\n", __FUNCTION__, hc->slot_owner[oslot_tx<<1]);
		}
	}

	if (oslot_rx>=0 && slot_rx!=oslot_rx) {
		/* remove from slot */
		if (debug & DEBUG_HFCMULTI_MODE)
			printk(KERN_DEBUG "%s: remove from slot %d (RX)\n", __FUNCTION__, oslot_rx);
		if (hc->slot_owner[(oslot_rx<<1)|1] == ch) {
			HFC_outb(hc, R_SLOT, (oslot_rx<<1) | V_SL_DIR);
			HFC_outb(hc, A_SL_CFG, 0);
			hc->slot_owner[(oslot_rx<<1)|1] = -1;
		} else {
			if (debug & DEBUG_HFCMULTI_MODE)
				printk(KERN_DEBUG "%s: we are not owner of this slot anymore, channel %d is.\n", __FUNCTION__, hc->slot_owner[(oslot_rx<<1)|1]);
		}
	}

	if (slot_tx < 0) {
		flow_tx = 0x80; /* FIFO->ST */
		/* disable pcm slot */
		hc->chan[ch].slot_tx = -1;
		hc->chan[ch].bank_tx = 0;
	} else {
		/* set pcm slot */
		if (hc->chan[ch].txpending)
			flow_tx = 0x80; /* FIFO->ST */
		else
			flow_tx = 0xc0; /* PCM->ST */
		/* put on slot */
		routing = bank_tx?0xc0:0x80;
		if (conf>=0 || bank_tx>1)
			routing = 0x40; /* loop */
		if (debug & DEBUG_HFCMULTI_MODE)
			printk(KERN_DEBUG "%s: put to slot %d bank %d flow %02x routing %02x conf %d (TX)\n", __FUNCTION__, slot_tx, bank_tx, flow_tx, routing, conf);
		HFC_outb(hc, R_SLOT, slot_tx<<1);
		HFC_outb(hc, A_SL_CFG, (ch<<1) | routing);
		HFC_outb(hc, A_CONF, (conf<0)?0:(conf|V_CONF_SL));
		hc->slot_owner[slot_tx<<1] = ch;
		hc->chan[ch].slot_tx = slot_tx;
		hc->chan[ch].bank_tx = bank_tx;
	}
	if (slot_rx < 0) {
		/* disable pcm slot */
		flow_rx = 0x80; /* ST->FIFO */
		hc->chan[ch].slot_rx = -1;
		hc->chan[ch].bank_rx = 0;
	} else {
		/* set pcm slot */
		if (hc->chan[ch].txpending)
			flow_rx = 0x80; /* ST->FIFO */
		else
			flow_rx = 0xc0; /* ST->(FIFO,PCM) */
		/* put on slot */
		routing = bank_rx?0x80:0xc0; /* reversed */
		if (conf>=0 || bank_rx>1)
			routing = 0x40; /* loop */
		if (debug & DEBUG_HFCMULTI_MODE)
			printk(KERN_DEBUG "%s: put to slot %d bank %d flow %02x routing %02x conf %d (RX)\n", __FUNCTION__, slot_rx, bank_rx, flow_rx, routing, conf);
		HFC_outb(hc, R_SLOT, (slot_rx<<1) | V_SL_DIR);
		HFC_outb(hc, A_SL_CFG, (ch<<1) | V_CH_DIR | routing);
		hc->slot_owner[(slot_rx<<1)|1] = ch;
		hc->chan[ch].slot_rx = slot_rx;
		hc->chan[ch].bank_rx = bank_rx;
	}

	switch (protocol) {
		case (ISDN_PID_NONE):
		/* disable TX fifo */
		HFC_outb(hc, R_FIFO, ch<<1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_IFF);
		HFC_outb(hc, A_SUBCH_CFG, 0);
		HFC_outb(hc, A_IRQ_MSK, 0);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		/* disable RX fifo */
		HFC_outb(hc, R_FIFO, (ch<<1)|1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00);
		HFC_outb(hc, A_SUBCH_CFG, 0);
		HFC_outb(hc, A_IRQ_MSK, 0);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		if (hc->type == 1) {
		} else if ((ch&0x3)<2) {
			hc->hw.a_st_ctrl0[hc->chan[ch].port] &= ((ch&0x3)==0)?~V_B1_EN:~V_B2_EN;
			HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
			HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[hc->chan[ch].port]);
		}
		break;

		case (ISDN_PID_L1_B_64TRANS): /* B-channel */
		/* enable TX fifo */
		HFC_outb(hc, R_FIFO, ch<<1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_tx | 0x00 | V_HDLC_TRP | V_IFF);
		HFC_outb(hc, A_SUBCH_CFG, 0);
		HFC_outb(hc, A_IRQ_MSK, 0);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence); /* tx silence */
		/* enable RX fifo */
		HFC_outb(hc, R_FIFO, (ch<<1)|1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_rx | 0x00 | V_HDLC_TRP);
		HFC_outb(hc, A_SUBCH_CFG, 0);
		HFC_outb(hc, A_IRQ_MSK, 0);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		if (hc->type != 1) {
			hc->hw.a_st_ctrl0[hc->chan[ch].port] |= ((ch&0x3)==0)?V_B1_EN:V_B2_EN;
			HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
			HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[hc->chan[ch].port]);
		}
		break;

		case (ISDN_PID_L1_B_64HDLC): /* B-channel */
		case (ISDN_PID_L1_TE_E1): /* D-channel E1 */
		case (ISDN_PID_L1_NT_E1):
		/* enable TX fifo */
		HFC_outb(hc, R_FIFO, ch<<1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04);
		HFC_outb(hc, A_SUBCH_CFG, 0);
		HFC_outb(hc, A_IRQ_MSK, V_IRQ);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		/* enable RX fifo */
		HFC_outb(hc, R_FIFO, (ch<<1)|1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04);
		HFC_outb(hc, A_SUBCH_CFG, 0);
		HFC_outb(hc, A_IRQ_MSK, V_IRQ);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		if (hc->type == 1) {
		} else {
			hc->hw.a_st_ctrl0[hc->chan[ch].port] |= ((ch&0x3)==0)?V_B1_EN:V_B2_EN;
			HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
			HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[hc->chan[ch].port]);
		}
		break;

		case (ISDN_PID_L1_TE_S0): /* D-channel S0 */
		case (ISDN_PID_L1_NT_S0):
		/* enable TX fifo */
		HFC_outb(hc, R_FIFO, ch<<1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_tx | 0x04 | V_IFF);
		HFC_outb(hc, A_SUBCH_CFG, 2);
		HFC_outb(hc, A_IRQ_MSK, V_IRQ);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		/* enable RX fifo */
		HFC_outb(hc, R_FIFO, (ch<<1)|1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, flow_rx | 0x04);
		HFC_outb(hc, A_SUBCH_CFG, 2);
		HFC_outb(hc, A_IRQ_MSK, V_IRQ);
		HFC_outb(hc, R_INC_RES_FIFO, V_RES_F);
		HFC_wait(hc);
		break;

		default:
		printk(KERN_DEBUG "%s: protocol not known %x\n", __FUNCTION__, protocol);
		hc->chan[ch].protocol = ISDN_PID_NONE;
		return(-ENOPROTOOPT);
	}
	hc->chan[ch].protocol = protocol;
	return(0);
}


/**************************/
/* connect/disconnect PCM */
/**************************/

static void
hfcmulti_pcm(hfc_multi_t *hc, int ch, int slot_tx, int bank_tx, int slot_rx, int bank_rx)
{
	if (slot_rx<0 || slot_rx<0 || bank_tx<0 || bank_rx<0) {
		/* disable PCM */
		mode_hfcmulti(hc, ch, hc->chan[ch].protocol, -1, 0, -1, 0);
		return;
	}

	/* enable pcm */
	mode_hfcmulti(hc, ch, hc->chan[ch].protocol, slot_tx, bank_tx, slot_rx, bank_rx);
}


/**************************/
/* set/disable conference */
/**************************/

static void
hfcmulti_conf(hfc_multi_t *hc, int ch, int num)
{
	if (num>=0 && num<=7)
		hc->chan[ch].conf = num;
	else
		hc->chan[ch].conf = -1;
	mode_hfcmulti(hc, ch, hc->chan[ch].protocol, hc->chan[ch].slot_tx, hc->chan[ch].bank_tx, hc->chan[ch].slot_rx, hc->chan[ch].bank_rx);
}


/***************************/
/* set/disable sample loop */
/***************************/
// NOTE: this function is experimental and therefore disabled
static void
hfcmulti_splloop(hfc_multi_t *hc, int ch, u_char *data, int len)
{
	u_char *d, *dd;
	bchannel_t *bch = hc->chan[ch].bch;

	/* flush pending TX data */
	if (bch->next_skb) {
		test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
		dev_kfree_skb(bch->next_skb);
		bch->next_skb = NULL;
	}
	bch->tx_idx = bch->tx_len = bch->rx_idx = 0;

	/* prevent overflow */
	if (len > hc->Zlen-1)
		len = hc->Zlen-1;

	/* select fifo */
	HFC_outb_(hc, R_FIFO, ch<<1);
	HFC_wait_(hc);

	/* reset fifo */
	HFC_outb(hc, A_SUBCH_CFG, 0);
	udelay(500);
	HFC_outb_(hc, R_INC_RES_FIFO, V_RES_F);
	HFC_wait_(hc);
	udelay(500);

	/* if off */
	if (len <= 0) {
		HFC_outb_(hc, A_FIFO_DATA0_NOINC, silence);
		if (hc->chan[ch].slot_tx>=0) {
			if (debug & DEBUG_HFCMULTI_MODE)
				printk(KERN_DEBUG "%s: connecting PCM due to no more TONE: channel %d slot_tx %d\n", __FUNCTION__, ch, hc->chan[ch].slot_tx);
			/* connect slot */
			HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
			HFC_outb(hc, R_FIFO, ch<<1 | 1);
			HFC_wait(hc);
			HFC_outb(hc, A_CON_HDLC, 0xc0 | 0x00 | V_HDLC_TRP | V_IFF);
		}
		hc->chan[ch].txpending = 0;
		return;
	}

	/* loop fifo */

	/* set mode */
	hc->chan[ch].txpending = 2;

//printk("len=%d %02x %02x %02x\n", len, data[0], data[1], data[2]);
	/* write loop data */
	d = data;
#ifdef FIFO_32BIT_ACCESS
#ifndef CONFIG_HFCMULTI_PCIMEM
	HFC_set(hc, A_FIFO_DATA0);
#endif
	dd = d + (len & 0xfffc);
	while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
		HFC_outl_(hc, A_FIFO_DATA0, *((unsigned long *)d));
#else
		HFC_putl(hc, *((unsigned long *)d));
#endif
		d+=4;

	}
	dd = d + (len & 0x0003);
#else
	dd = d + len;
#endif
	while(d != dd) {
#ifdef CONFIG_HFCMULTI_PCIMEM
		HFC_outb_(hc, A_FIFO_DATA0, *d);
#else
		HFC_putb(hc, *d);
#endif
		d++;
	}

	udelay(500);
	HFC_outb(hc, A_SUBCH_CFG, V_LOOP_FIFO);
	udelay(500);

	/* disconnect slot */
	if (hc->chan[ch].slot_tx>=0) {
		if (debug & DEBUG_HFCMULTI_MODE)
			printk(KERN_DEBUG "%s: disconnecting PCM due to TONE: channel %d slot_tx %d\n", __FUNCTION__, ch, hc->chan[ch].slot_tx);
		HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
		HFC_outb(hc, R_FIFO, ch<<1 | 1);
		HFC_wait(hc);
		HFC_outb(hc, A_CON_HDLC, 0x80 | 0x00 | V_HDLC_TRP | V_IFF);
		HFC_outb(hc, R_FIFO, ch<<1);
		HFC_wait(hc);
	} else {
		/* change fifo */
		HFC_outb(hc, R_FIFO, ch<<1);
		HFC_wait(hc);
	}

//udelay(300);
}

/*************************************/
/* Layer 1 D-channel hardware access */
/*************************************/

/* message transfer from layer 1 to hardware.
 */
static int hfcmulti_l1hw(mISDNinstance_t *inst, struct sk_buff *skb)
{
	dchannel_t	*dch = container_of(inst, dchannel_t, inst);
	int		slot_tx, slot_rx, bank_tx, bank_rx;
	hfc_multi_t	*hc;
	int		ret = -EINVAL;
	mISDN_head_t	*hh;

	hh = mISDN_HEAD_P(skb);
	hc = dch->inst.privat;
	ret = 0;
	if (hh->prim == PH_DATA_REQ) {
		/* check oversize */
		if (skb->len == 0) {
			printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
			return(-EINVAL);
		}
		if (skb->len > MAX_DFRAME_LEN_L1) {
			printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
			return(-EINVAL);
		}
		/* check for pending next_skb */
		if (dch->next_skb) {
			printk(KERN_WARNING "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n", __FUNCTION__, skb->len, dch->next_skb->len);
			return(-EBUSY);
		}
		/* if we have currently a pending tx skb */
		dch->inst.lock(hc, 0);
		if (test_and_set_bit(FLG_TX_BUSY, &dch->DFlags)) {
			test_and_set_bit(FLG_TX_NEXT, &dch->DFlags);
			dch->next_skb = skb;
			dch->inst.unlock(hc);
			return(0);
		}
		/* write to fifo */
		dch->tx_len = skb->len;
		memcpy(dch->tx_buf, skb->data, dch->tx_len);
//		if (debug & DEBUG_HFCMULTI_FIFO) {
//			printk(KERN_DEBUG "%s:from user space:\n", __FUNCTION__);
//			i = 0;
//			while(i < dch->tx_len)
//				printk(" %02x", dch->tx_buf[i++]);
//			printk("\n");
//		}
		dch->tx_idx = 0;
		hfcmulti_tx(hc, dch->channel, dch, NULL);
		/* start fifo */
		HFC_outb(hc, R_FIFO, 0);
		HFC_wait(hc);
		dch->inst.unlock(hc);
		skb_trim(skb, 0);
		// return(if_newhead(&dch->inst.up, PH_DATA_CNF,hh->dinfo, skb)); TODO changed
		return(mISDN_queueup_newhead(inst, 0, PH_DATA_CNF,hh->dinfo, skb));
	} else
	if (hh->prim == (PH_SIGNAL | REQUEST)) {
		dch->inst.lock(hc, 0);
		switch (hh->dinfo) {
#if 0
			case INFO3_P8:
			case INFO3_P10:
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: INFO3_P%d\n", __FUNCTION__, (hh->dinfo==INFO3_P8)?8:10);
			if (test_bit(HFC_CHIP_MASTER, &hc->chip))
				hc->hw.mst_m |= HFCPCI_MASTER;
			Write_hfc(hc, HFCPCI_MST_MODE, hc->hw.mst_m);
			break;
#endif
			default:
			printk(KERN_DEBUG "%s: unknown PH_SIGNAL info %x\n", __FUNCTION__, hh->dinfo);
			ret = -EINVAL;
		}
		dch->inst.unlock(hc);
	} else
	if (hh->prim == (PH_CONTROL | REQUEST)) {
		dch->inst.lock(hc, 0);
		switch (hh->dinfo) {
			case HW_RESET:
			/* start activation */
			if (hc->type == 1) {
				HFC_outb(hc, R_E1_WR_STA, V_E1_LD_STA | 0);
				udelay(6); /* wait at least 5,21us */
				HFC_outb(hc, R_E1_WR_STA, 0);
			} else {
				HFC_outb(hc, R_ST_SEL, hc->chan[dch->channel].port);
				HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 3); /* G1 */
				udelay(6); /* wait at least 5,21us */
				HFC_outb(hc, A_ST_WR_STATE, 3);
				HFC_outb(hc, A_ST_WR_STATE, 3 | (V_ST_ACT*3)); /* activate */
			}
			dch->inst.unlock(hc);
			skb_trim(skb, 0);
			return(mISDN_queueup_newhead(inst, 0, PH_CONTROL | INDICATION,HW_POWERUP, skb));
			break;

			case HW_DEACTIVATE:
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_DEACTIVATE\n", __FUNCTION__);
			goto hw_deactivate; /* after lock */

			/* connect interface to pcm timeslot (0..N) */
			case HW_PCM_CONN:
			if (skb->len < 4*sizeof(u_long)) {
				printk(KERN_WARNING "%s: HW_PCM_CONN lacks parameters\n", __FUNCTION__);
				break;
			}
			slot_tx = ((int *)skb->data)[0];
			bank_tx = ((int *)skb->data)[1];
			slot_rx = ((int *)skb->data)[2];
			bank_rx = ((int *)skb->data)[3];
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX)\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
			if (slot_tx<=hc->slots && bank_tx<=2 && slot_rx<=hc->slots && bank_rx<=2)
				hfcmulti_pcm(hc, dch->channel, slot_tx, bank_tx, slot_rx, bank_rx);
			else
				printk(KERN_WARNING "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX) out of range\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
			break;

			/* release interface from pcm timeslot */
			case HW_PCM_DISC:
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_PCM_DISC\n", __FUNCTION__);
			hfcmulti_pcm(hc, dch->channel, -1, -1, -1, -1);
			break;

			default:
			printk(KERN_DEBUG "%s: unknown PH_CONTROL info %x\n", __FUNCTION__, hh->dinfo);
			ret = -EINVAL;
		}
		dch->inst.unlock(hc);
	} else
	if (hh->prim == (PH_ACTIVATE | REQUEST)) {
		if (test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)) {
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: PH_ACTIVATE port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
			dch->inst.lock(hc, 0);
			/* start activation */
			if (hc->type == 1) {
				//dchannel_sched_event(dch, D_L1STATECHANGE);
				ph_state_change(dch);
				if (debug & DEBUG_HFCMULTI_STATE)
					printk(KERN_DEBUG "%s: E1 report state %x \n", __FUNCTION__, dch->ph_state);
			} else {
				HFC_outb(hc, R_ST_SEL, hc->chan[dch->channel].port);
				HFC_outb(hc, A_ST_WR_STATE, V_ST_LD_STA | 1); /* G1 */
				udelay(6); /* wait at least 5,21us */
				HFC_outb(hc, A_ST_WR_STATE, 1);
				HFC_outb(hc, A_ST_WR_STATE, 1 | (V_ST_ACT*3)); /* activate */
				dch->ph_state = 1;
			}
			dch->inst.unlock(hc);
		} else {
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: PH_ACTIVATE no NT-mode port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
			ret = -EINVAL;
		}
	} else
	if (hh->prim == (PH_DEACTIVATE | REQUEST)) {
		if (test_bit(HFC_CFG_NTMODE, &hc->chan[dch->channel].cfg)) {
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: PH_DEACTIVATE port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
			dch->inst.lock(hc, 0);
			hw_deactivate: /* after lock */
			dch->ph_state = 0;
			/* start deactivation */
			if (hc->type == 1) {
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: PH_DEACTIVATE no BRI\n", __FUNCTION__);
			} else {
				HFC_outb(hc, R_ST_SEL, hc->chan[dch->channel].port);
				HFC_outb(hc, A_ST_WR_STATE, V_ST_ACT*2); /* deactivate */
			}
			// discard_queue(&dch->rqueue); TODO changed
			if (dch->next_skb) {
				dev_kfree_skb(dch->next_skb);
				dch->next_skb = NULL;
			}
			dch->tx_idx = dch->tx_len = hc->chan[dch->channel].rx_idx = 0;
			test_and_clear_bit(FLG_TX_NEXT, &dch->DFlags);
			test_and_clear_bit(FLG_TX_BUSY, &dch->DFlags);
			if (test_and_clear_bit(FLG_DBUSY_TIMER, &dch->DFlags))
				del_timer(&dch->dbusytimer);
			//if (test_and_clear_bit(FLG_L1_DBUSY, &dch->DFlags)) dchannel_sched_event(dch, D_CLEARBUSY);  TODO why???
			dch->inst.unlock(hc);
		} else {
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: PH_DEACTIVATE no NT-mode port %d (0..%d)\n", __FUNCTION__, hc->chan[dch->channel].port, hc->type-1);
			ret = -EINVAL;
		}
	} else {
		if (debug & DEBUG_HFCMULTI_MSG)
			printk(KERN_DEBUG "%s: unknown prim %x\n", __FUNCTION__, hh->prim);
		ret = -EINVAL;
	}
	if (!ret) {
//		printk("1\n");
		dev_kfree_skb(skb);
//		printk("2\n");
	}
	return(ret);
}


/******************************/
/* Layer2 -> Layer 1 Transfer */
/******************************/

/* messages from layer 2 to layer 1 are processed here.
 */
static int
hfcmulti_l2l1(mISDNinstance_t *inst, struct sk_buff *skb)
{
	u_long		num;
	int		slot_tx, slot_rx, bank_tx, bank_rx;
	bchannel_t	*bch = container_of(inst, bchannel_t, inst);
	int		ret = -EINVAL;
	mISDN_head_t	*hh;
	hfc_multi_t	*hc;
	struct		dsp_features *features;

	hh = mISDN_HEAD_P(skb);
	hc = bch->inst.privat;

	if ((hh->prim == PH_DATA_REQ)
	 || (hh->prim == (DL_DATA | REQUEST))) {
		if (skb->len == 0) {
			printk(KERN_WARNING "%s: skb too small\n", __FUNCTION__);
			return(-EINVAL);
		}
		if (skb->len > MAX_DATA_MEM) {
			printk(KERN_WARNING "%s: skb too large\n", __FUNCTION__);
			return(-EINVAL);
		}
		/* check for pending next_skb */
		if (bch->next_skb) {
			printk(KERN_WARNING "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n", __FUNCTION__, skb->len, bch->next_skb->len);
			return(-EBUSY);
		}
		/* if we have currently a pending tx skb */
		bch->inst.lock(hc, 0);
		if (test_and_set_bit(BC_FLG_TX_BUSY, &bch->Flag)) {
			test_and_set_bit(BC_FLG_TX_NEXT, &bch->Flag);
			bch->next_skb = skb;
			bch->inst.unlock(hc);
			return(0);
		}
		/* write to fifo */
		bch->tx_len = skb->len;
		memcpy(bch->tx_buf, skb->data, bch->tx_len);
		bch->tx_idx = 0;
		hfcmulti_tx(hc, bch->channel, NULL, bch);
		/* start fifo */
		HFC_outb_(hc, R_FIFO, 0);
		HFC_wait_(hc);
		bch->inst.unlock(hc);
#ifdef FIXME   // TODO changed
		if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
			&& bch->dev)
			hif = &bch->dev->rport.pif;
		else
			hif = &bch->inst.up;
#endif
		skb_trim(skb, 0);
		// return(if_newhead(hif, hh->prim | CONFIRM, hh->dinfo, skb)); TOO changed
		return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, hh->dinfo, skb));
	} else
	if ((hh->prim == (PH_ACTIVATE | REQUEST))
	 || (hh->prim == (DL_ESTABLISH  | REQUEST))) {
		/* activate B-channel if not already activated */
		if (debug & DEBUG_HFCMULTI_MSG)
			printk(KERN_DEBUG "%s: PH_ACTIVATE ch %d (0..32)\n", __FUNCTION__, bch->channel);
		if (test_and_set_bit(BC_FLG_ACTIV, &bch->Flag))
			ret = 0;
		else {
			bch->inst.lock(hc, 0);
			ret = mode_hfcmulti(hc, bch->channel, bch->inst.pid.protocol[1], hc->chan[bch->channel].slot_tx, hc->chan[bch->channel].bank_tx, hc->chan[bch->channel].slot_rx, hc->chan[bch->channel].bank_rx);
			if (!ret) {
				bch->protocol = bch->inst.pid.protocol[1];
				// if (bch->protocol) bch_sched_event(bch, B_XMTBUFREADY); TODO discard????
				if (bch->protocol==ISDN_PID_L1_B_64TRANS && !hc->dtmf) {
					/* start decoder */
					hc->dtmf = 1;
					if (debug & DEBUG_HFCMULTI_DTMF)
						printk(KERN_DEBUG "%s: start dtmf decoder\n", __FUNCTION__);
					HFC_outb(hc, R_DTMF, hc->hw.r_dtmf | V_RST_DTMF);
				}
			}
			bch->inst.unlock(hc);
		}
#ifdef FIXME  // TODO changed
		if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
			if (bch->dev)
				if_link(&bch->dev->rport.pif, hh->prim | CONFIRM, 0, 0, NULL, 0);
#endif
		skb_trim(skb, 0);
		// return(if_newhead(&bch->inst.up, hh->prim | CONFIRM, ret, skb));  TODO changed
		return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, ret, skb));
	} else
	if ((hh->prim == (PH_DEACTIVATE | REQUEST))
	 || (hh->prim == (DL_RELEASE | REQUEST))
	 // || (hh->prim == (MGR_DISCONNECT | REQUEST))) { TODO changed
	 || ((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) {
		if (debug & DEBUG_HFCMULTI_MSG)
			printk(KERN_DEBUG "%s: PH_DEACTIVATE ch %d (0..32)\n", __FUNCTION__, bch->channel);
		/* deactivate B-channel if not already deactivated */
		bch->inst.lock(hc, 0);
		if (bch->next_skb) {
			test_and_clear_bit(BC_FLG_TX_NEXT, &bch->Flag);
			dev_kfree_skb(bch->next_skb);
			bch->next_skb = NULL;
		}
		bch->tx_idx = bch->tx_len = bch->rx_idx = 0;
		test_and_clear_bit(BC_FLG_TX_BUSY, &bch->Flag);
		hc->chan[bch->channel].slot_tx = -1;
		hc->chan[bch->channel].slot_rx = -1;
		hc->chan[bch->channel].conf = -1;
		mode_hfcmulti(hc, bch->channel, ISDN_PID_NONE, hc->chan[bch->channel].slot_tx, hc->chan[bch->channel].bank_tx, hc->chan[bch->channel].slot_rx, hc->chan[bch->channel].bank_rx);
		bch->protocol = ISDN_PID_NONE;
		test_and_clear_bit(BC_FLG_ACTIV, &bch->Flag);
		bch->inst.unlock(hc);
		skb_trim(skb, 0);
//printk("5\n");
		// if (hh->prim != (MGR_DISCONNECT | REQUEST)) { TODO
		if (hh->prim != (PH_CONTROL | REQUEST)) {
#ifdef FIXME  // TODO changed
			if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
				if (bch->dev)
					if_link(&bch->dev->rport.pif, hh->prim | CONFIRM, 0, 0, NULL, 0);
#endif
			// if (!if_newhead(&bch->inst.up, hh->prim | CONFIRM, 0, skb)) return(0); TODO changed
			return(mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, ret, skb));
//printk("6\n");
		}
//printk("7\n");
		ret = 0;
	} else
	if (hh->prim == (PH_CONTROL | REQUEST)) {
		bch->inst.lock(hc, 0);
		switch (hh->dinfo) {
			/* fill features structure */
			case HW_FEATURES:
			if (skb->len != sizeof(void *)) {
				printk(KERN_WARNING "%s: HW_FEATURES lacks parameters\n", __FUNCTION__);
				break;
			}
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_FEATURE request\n", __FUNCTION__);
			features = *((struct dsp_features **)skb->data);
			features->hfc_id = hc->id;
			if (test_bit(HFC_CHIP_DTMF, &hc->chip))
				features->hfc_dtmf = 1;
			features->hfc_loops = 0;
			features->pcm_id = hc->pcm;
			features->pcm_slots = hc->slots;
			features->pcm_banks = 2;
			ret = 0;
			break;

			/* connect interface to pcm timeslot (0..N) */
			case HW_PCM_CONN:
			if (skb->len < 4*sizeof(u_long)) {
				printk(KERN_WARNING "%s: HW_PCM_CONN lacks parameters\n", __FUNCTION__);
				break;
			}
			slot_tx = ((int *)skb->data)[0];
			bank_tx = ((int *)skb->data)[1];
			slot_rx = ((int *)skb->data)[2];
			bank_rx = ((int *)skb->data)[3];
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX)\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
			if (slot_tx<=hc->slots && bank_tx<=2 && slot_rx<=hc->slots && bank_rx<=2)
				hfcmulti_pcm(hc, bch->channel, slot_tx, bank_tx, slot_rx, bank_rx);
			else
				printk(KERN_WARNING "%s: HW_PCM_CONN slot %d bank %d (TX) slot %d bank %d (RX) out of range\n", __FUNCTION__, slot_tx, bank_tx, slot_rx, bank_rx);
			ret = 0;
			break;

			/* release interface from pcm timeslot */
			case HW_PCM_DISC:
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_PCM_DISC\n", __FUNCTION__);
			hfcmulti_pcm(hc, bch->channel, -1, -1, -1, -1);
			ret = 0;
			break;

			/* join conference (0..7) */
			case HW_CONF_JOIN:
			if (skb->len < sizeof(u_long)) {
				printk(KERN_WARNING "%s: HW_CONF_JOIN lacks parameters\n", __FUNCTION__);
				break;
			}
			num = ((u_long *)skb->data)[0];
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_CONF_JOIN conf %ld\n", __FUNCTION__, num);
			if (num <= 7) {
				hfcmulti_conf(hc, bch->channel, num);
				ret = 0;
			} else
				printk(KERN_WARNING "%s: HW_CONF_JOIN conf %ld out of range\n", __FUNCTION__, num);
			break;

			/* split conference */
			case HW_CONF_SPLIT:
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_CONF_SPLIT\n", __FUNCTION__);
			hfcmulti_conf(hc, bch->channel, -1);
			ret = 0;
			break;

			/* set sample loop */
			case HW_SPL_LOOP_ON:
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_SPL_LOOP_ON (len = %d)\n", __FUNCTION__, skb->len);
			hfcmulti_splloop(hc, bch->channel, skb->data, skb->len);
			ret = 0;
			break;

			/* set silence */
			case HW_SPL_LOOP_OFF:
			if (debug & DEBUG_HFCMULTI_MSG)
				printk(KERN_DEBUG "%s: HW_SPL_LOOP_OFF\n", __FUNCTION__);
			hfcmulti_splloop(hc, bch->channel, NULL, 0);
			ret = 0;
			break;

			default:
			printk(KERN_DEBUG "%s: unknown PH_CONTROL info %x\n", __FUNCTION__, hh->dinfo);
			ret = -EINVAL;
		}
		bch->inst.unlock(hc);
	} else {
		printk(KERN_WARNING "%s: unknown prim(%x)\n", __FUNCTION__, hh->prim);
		ret = -EINVAL;
	}
	if (!ret) {
//		printk("3\n");
		dev_kfree_skb(skb);
//		printk("4\n");
	}
	return(ret);
}


/***************************/
/* handle D-channel events */
/***************************/

/* handle state change event
 */
static void ph_state_change(dchannel_t *dch)
{
	hfc_multi_t *hc = dch->inst.privat;
	u_int prim = PH_SIGNAL | INDICATION;
	u_int para = 0;
	// mISDNif_t *upif = &dch->inst.up; TODO
	//mISDN_head_t *hh;
	int ch;
	//struct sk_buff *skb;

	if (!dch) {
		printk(KERN_WARNING "%s: ERROR given dch is NULL\n", __FUNCTION__);
		return;
	}
	ch = dch->channel;

	// Loss Of Signal    TODO handle for E1
	/*
	if (test_and_clear_bit(D_LOS, &dch->event)) {
		if (debug & DEBUG_HFCMULTI_STATE)
			printk(KERN_DEBUG "%s: LOS detected\n", __FUNCTION__);
		skb = create_link_skb(PH_CONTROL | INDICATION, HW_LOS, 0, NULL, 0);
		if (skb) {
			hh = mISDN_HEAD_P(skb);
			if (if_newhead(upif, hh->prim, hh->dinfo, skb))
				dev_kfree_skb(skb);
		}
	}
	// Loss Of Signal OFF
	if (test_and_clear_bit(D_LOS_OFF, &dch->event)) {
		if (debug & DEBUG_HFCMULTI_STATE)
			printk(KERN_DEBUG "%s: LOS gone\n", __FUNCTION__);
		skb = create_link_skb(PH_CONTROL | INDICATION, HW_LOS_OFF, 0, NULL, 0);
		if (skb) {
			hh = mISDN_HEAD_P(skb);
			if (if_newhead(upif, hh->prim, hh->dinfo, skb))
				dev_kfree_skb(skb);
		}
	}
	// Alarm Indication Signal
	if (test_and_clear_bit(D_AIS, &dch->event)) {
		if (debug & DEBUG_HFCMULTI_STATE)
			printk(KERN_DEBUG "%s: AIS detected\n", __FUNCTION__);
		skb = create_link_skb(PH_CONTROL | INDICATION, HW_AIS, 0, NULL, 0);
		if (skb) {
			hh = mISDN_HEAD_P(skb);
			if (if_newhead(upif, hh->prim, hh->dinfo, skb))
				dev_kfree_skb(skb);
		}
	}
	// Alarm Indication Signal OFF
	if (test_and_clear_bit(D_AIS_OFF, &dch->event)) {
		if (debug & DEBUG_HFCMULTI_STATE)
			printk(KERN_DEBUG "%s: AIS gone\n", __FUNCTION__);
		skb = create_link_skb(PH_CONTROL | INDICATION, HW_AIS_OFF, 0, NULL, 0);
		if (skb) {
			hh = mISDN_HEAD_P(skb);
			if (if_newhead(upif, hh->prim, hh->dinfo, skb))
				dev_kfree_skb(skb);
		}
	}
	// SLIP detected
	if (test_and_clear_bit(D_SLIP_TX, &dch->event)) {
		if (debug & DEBUG_HFCMULTI_STATE)
			printk(KERN_DEBUG "%s: bit SLIP detected TX\n", __FUNCTION__);
		skb = create_link_skb(PH_CONTROL | INDICATION, HW_SLIP_TX, 0, NULL, 0);
		if (skb) {
			hh = mISDN_HEAD_P(skb);
			if (if_newhead(upif, hh->prim, hh->dinfo, skb))
				dev_kfree_skb(skb);
		}
	}
	if (test_and_clear_bit(D_SLIP_RX, &dch->event)) {
		if (debug & DEBUG_HFCMULTI_STATE)
			printk(KERN_DEBUG "%s: bit SLIP detected RX\n", __FUNCTION__);
		skb = create_link_skb(PH_CONTROL | INDICATION, HW_SLIP_RX, 0, NULL, 0);
		if (skb) {
			hh = mISDN_HEAD_P(skb);
			if (if_newhead(upif, hh->prim, hh->dinfo, skb))
				dev_kfree_skb(skb);
		}
	} */

	if (hc->type == 1) {
		if (!test_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg)) {
			if (debug & DEBUG_HFCMULTI_STATE)
				printk(KERN_DEBUG "%s: E1 TE newstate %x\n", __FUNCTION__, dch->ph_state);
		} else {
			if (debug & DEBUG_HFCMULTI_STATE)
				printk(KERN_DEBUG "%s: E1 NT newstate %x\n", __FUNCTION__, dch->ph_state);
		}
		switch (dch->ph_state) {
			case (1):
			prim = PH_ACTIVATE | INDICATION;
			para = 0;
			break;

			default:
			if (hc->chan[ch].e1_state != 1)
				return;
			prim = PH_DEACTIVATE | INDICATION;
			para = 0;
		}
		hc->chan[ch].e1_state = dch->ph_state;
	} else {
		if (!test_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg)) {
			if (debug & DEBUG_HFCMULTI_STATE)
				printk(KERN_DEBUG "%s: S/T TE newstate %x\n", __FUNCTION__, dch->ph_state);
			switch (dch->ph_state) {
				case (0):
				prim = PH_CONTROL | INDICATION;
				para = HW_RESET;
				break;

				case (3):
				prim = PH_CONTROL | INDICATION;
				para = HW_DEACTIVATE;
				break;

				case (5):
				case (8):
				para = ANYSIGNAL;
				break;

				case (6):
				para = INFO2;
				break;

				case (7):
				para = INFO4_P8;
				break;

				default:
				return;
			}
		} else {
			if (debug & DEBUG_HFCMULTI_STATE)
				printk(KERN_DEBUG "%s: S/T NT newstate %x\n", __FUNCTION__, dch->ph_state);
			dch->inst.lock(hc, 0);
			switch (dch->ph_state) {
				case (2):
				if (hc->chan[ch].nt_timer == 0) {
					hc->chan[ch].nt_timer = -1;
					HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
					HFC_outb(hc, A_ST_WR_STATE, 4 | V_ST_LD_STA); /* G4 */
					udelay(6); /* wait at least 5,21us */
					HFC_outb(hc, A_ST_WR_STATE, 4);
					dch->ph_state = 4;
				} else {
					/* one extra count for the next event */
					hc->chan[ch].nt_timer = nt_t1_count[poll_timer] + 1;
					HFC_outb(hc, R_ST_SEL, hc->chan[ch].port);
					HFC_outb(hc, A_ST_WR_STATE, 2 | V_SET_G2_G3); /* allow G2 -> G3 transition */
				}
				dch->inst.unlock(hc);
				return;
				//upif = NULL;  TODO
				//break;

				case (1):
				prim = PH_DEACTIVATE | INDICATION;
				para = 0;
				hc->chan[ch].nt_timer = -1;
				break;

				case (4):
				hc->chan[ch].nt_timer = -1;
				dch->inst.unlock(hc);
				return;
				//upif = NULL;
				// break; TODO

				case (3):
				prim = PH_ACTIVATE | INDICATION;
				para = 0;
				hc->chan[ch].nt_timer = -1;
				break;

				default:
				break;
			}
			dch->inst.unlock(hc);
		}
	}
	/* transmit new state to upper layer if available */
	//if (hc->created[hc->chan[ch].port]) {
	//	while(upif) {
	//		if_link(upif, prim, para, 0, NULL, 0);
	//		upif = upif->clone;
	//	}
	//}

	mISDN_queue_data(&dch->inst, FLG_MSG_UP, prim, para, 0, NULL, 0);    // TODO
}

/***************************/
/* handle B-channel events */
/***************************/

/* handle DTMF event  TODO: handle DTMF later
 */
/*static void
hfcmulti_bch_bh(bchannel_t *bch)
{
	hfc_multi_t	*hc = bch->inst.data;
	struct sk_buff  *skb;
        mISDN_head_t    *hh;
        mISDNif_t       *hif = 0; // make gcc happy
	u_long		*coeff;

	if (!bch) {
		printk(KERN_WARNING "%s: ERROR given bch is NULL\n", __FUNCTION__);
		return;
	}

	// DTMF event   TODO: handle DTMF later
	if (test_and_clear_bit(B_DTMFREADY, &bch->event)) {
		while ((skb = skb_dequeue(&hc->chan[bch->channel].dtmfque))) {
			if (debug & DEBUG_HFCMULTI_DTMF) {
				coeff = (u_long *)skb->data;
				printk("%s: DTMF ready %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx len=%d\n", __FUNCTION__,
				coeff[0], coeff[1], coeff[2], coeff[3], coeff[4], coeff[5], coeff[6], coeff[7], skb->len);
			}
			hh = mISDN_HEAD_P(skb);
			if ((bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV) && bch->dev)
				hif = &bch->dev->rport.pif;
			else
				hif = &bch->inst.up;
			if (if_newhead(hif, hh->prim, hh->dinfo, skb))
				dev_kfree_skb(skb);
		}
	}

} */


/*************************************/
/* called for card mode init message */
/*************************************/

static void
hfcmulti_initmode(hfc_multi_t *hc)
{
	int nt_mode;
	unsigned char r_sci_msk, a_st_wr_state, r_e1_wr_sta;
	int i, port;
	dchannel_t *dch;

	if (debug & DEBUG_HFCMULTI_INIT)
		printk("%s: entered\n", __FUNCTION__);

	lock_dev(hc, 0);

	if (hc->type == 1) {
		nt_mode = test_bit(HFC_CFG_NTMODE, &hc->chan[16].cfg);
		hc->chan[16].slot_tx = -1;
		hc->chan[16].slot_rx = -1;
		hc->chan[16].conf = -1;
		mode_hfcmulti(hc, 16, nt_mode?ISDN_PID_L1_NT_E1:ISDN_PID_L1_TE_E1, -1, 0, -1, 0);
		// hc->chan[16].dch->hw_bh = hfcmulti_dch_bh;   TODO
		hc->chan[16].dch->dbusytimer.function = (void *) hfcmulti_dbusy_timer;
		hc->chan[16].dch->dbusytimer.data = (long) &hc->chan[16].dch;
		init_timer(&hc->chan[16].dch->dbusytimer);

		i = 0;
		while (i < 30) {
			hc->chan[i+1+(i>=15)].slot_tx = -1;
			hc->chan[i+1+(i>=15)].slot_rx = -1;
			hc->chan[i+1+(i>=15)].conf = -1;
			//hc->chan[i+1+(i>=15)].bch->hw_bh = hfcmulti_bch_bh;
			mode_hfcmulti(hc, i+1+(i>=15), ISDN_PID_NONE, -1, 0, -1, 0);
			hc->chan[i+1+(i>=15)].bch->protocol = ISDN_PID_NONE;
			i++;
		}
	} else {
		i = 0;
		while (i < hc->type) {
			nt_mode = test_bit(HFC_CFG_NTMODE, &hc->chan[(i<<2)+2].cfg);
			hc->chan[(i<<2)+2].slot_tx = -1;
			hc->chan[(i<<2)+2].slot_rx = -1;
			hc->chan[(i<<2)+2].conf = -1;
			mode_hfcmulti(hc, (i<<2)+2, nt_mode?ISDN_PID_L1_NT_S0:ISDN_PID_L1_TE_S0, -1, 0, -1, 0);
			// hc->chan[(i<<2)+2].dch->hw_bh = hfcmulti_dch_bh;  TODO
			hc->chan[(i<<2)+2].dch->dbusytimer.function = (void *) hfcmulti_dbusy_timer;
			hc->chan[(i<<2)+2].dch->dbusytimer.data = (long) &hc->chan[(i<<2)+2].dch;
			init_timer(&hc->chan[(i<<2)+2].dch->dbusytimer);

			//hc->chan[i<<2].bch->hw_bh = hfcmulti_bch_bh;
			hc->chan[i<<2].slot_tx = -1;
			hc->chan[i<<2].slot_rx = -1;
			hc->chan[i<<2].conf = -1;
			mode_hfcmulti(hc, i<<2, ISDN_PID_NONE, -1, 0, -1, 0);
			hc->chan[i<<2].bch->protocol = ISDN_PID_NONE;
			//hc->chan[(i<<2)+1].bch->hw_bh = hfcmulti_bch_bh;
			hc->chan[(i<<2)+1].slot_tx = -1;
			hc->chan[(i<<2)+1].slot_rx = -1;
			hc->chan[(i<<2)+1].conf = -1;
			mode_hfcmulti(hc, (i<<2)+1, ISDN_PID_NONE, -1, 0, -1, 0);
			hc->chan[(i<<2)+1].bch->protocol = ISDN_PID_NONE;
			i++;
		}
	}

	/* set up interface */
	if (hc->type != 1) {
		/* ST */
		r_sci_msk = 0;
		i = 0;
		while(i < 32) {
			if (!(dch = hc->chan[i].dch)) {
				i++;
				continue;
			}
			port = hc->chan[i].port;
			/* select interface */
			HFC_outb(hc, R_ST_SEL, port);
			if (test_bit(HFC_CFG_NTMODE, &hc->chan[i].cfg)) {
				if (debug & DEBUG_HFCMULTI_INIT)
					printk(KERN_DEBUG "%s: ST port %d is NT-mode\n", __FUNCTION__, port);
				/* clock delay */
				HFC_outb(hc, A_ST_CLK_DLY, CLKDEL_NT | 0x60);
				a_st_wr_state = 1; /* G1 */
				hc->hw.a_st_ctrl0[port] = V_ST_MD;
			} else {
				if (debug & DEBUG_HFCMULTI_INIT)
					printk(KERN_DEBUG "%s: ST port %d is TE-mode\n", __FUNCTION__, port);
				/* clock delay */
				HFC_outb(hc, A_ST_CLK_DLY, CLKDEL_TE);
				a_st_wr_state = 2; /* F2 */
				hc->hw.a_st_ctrl0[port] = 0;
			}
			if (!test_bit(HFC_CFG_NONCAP_TX, &hc->chan[i].cfg)) {
				hc->hw.a_st_ctrl0[port] |= V_TX_LI;
			}
			/* line setup */
			HFC_outb(hc, A_ST_CTRL0,  hc->hw.a_st_ctrl0[port]);
			/* disable E-channel */
			if (test_bit(HFC_CFG_NTMODE, &hc->chan[i].cfg)
			 || test_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[i].cfg))
				HFC_outb(hc, A_ST_CTRL1, V_E_IGNO);
			/* enable B-channel receive */
			HFC_outb(hc, A_ST_CTRL2,  V_B1_RX_EN | V_B2_RX_EN);
			/* state machine setup */
			HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state | V_ST_LD_STA);
			udelay(6); /* wait at least 5,21us */
			HFC_outb(hc, A_ST_WR_STATE, a_st_wr_state);
			r_sci_msk |= 1 << port;
			i++;
		}
		/* state machine interrupts */
		HFC_outb(hc, R_SCI_MSK, r_sci_msk);
	} else {
		/* E1 */
		if (test_bit(HFC_CFG_REPORT_LOS, &hc->chan[16].cfg)) {
			HFC_outb(hc, R_LOS0, 255); /* 2 ms */
			HFC_outb(hc, R_LOS1, 255); /* 512 ms */
		}
		if (test_bit(HFC_CFG_OPTICAL, &hc->chan[16].cfg)) {
			HFC_outb(hc, R_RX0, 0);
			hc->hw.r_tx0 = 0 | V_OUT_EN;
		} else {
			HFC_outb(hc, R_RX0, 1);
			hc->hw.r_tx0 = 1 | V_OUT_EN;
		}
		hc->hw.r_tx1 = V_ATX | V_NTRI;
		HFC_outb(hc, R_TX0, hc->hw.r_tx0);
		HFC_outb(hc, R_TX1, hc->hw.r_tx1);
		HFC_outb(hc, R_TX_FR0, 0x00);
		HFC_outb(hc, R_TX_FR1, 0xf8);
		HFC_outb(hc, R_TX_FR2, V_TX_MF | V_TX_E | V_NEG_E);
		HFC_outb(hc, R_RX_FR0, V_AUTO_RESYNC | V_AUTO_RECO | 0);
		HFC_outb(hc, R_RX_FR1, V_RX_MF | V_RX_MF_SYNC);
		if (test_bit(HFC_CHIP_PCM_SLAVE, &hc->chip)) {
			/* SLAVE (clock master) */
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: E1 port is clock master\n", __FUNCTION__);
//			HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS | V_PCM_SYNC);
			HFC_outb(hc, R_SYNC_CTRL, V_EXT_CLK_SYNC | V_PCM_SYNC);
		} else {
			/* MASTER (clock slave) */
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: E1 port is clock slave\n", __FUNCTION__);
			HFC_outb(hc, R_SYNC_CTRL, V_SYNC_OFFS);
		}
		if (test_bit(HFC_CFG_NTMODE, &hc->chan[(i<<2)+2].cfg)) {
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: E1 port is NT-mode\n", __FUNCTION__);
			r_e1_wr_sta = 0; /* G0 */
		}else {
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: E1 port is TE-mode\n", __FUNCTION__);
			r_e1_wr_sta = 0; /* F0 */
		}
		HFC_outb(hc, R_JATT_ATT, 0x9c); /* undoc register */
		if (test_bit(HFC_CHIP_RX_SYNC, &hc->chip)) {
			HFC_outb(hc, R_SYNC_OUT, V_SYNC_E1_RX | V_IPATS0 | V_IPATS1 | V_IPATS2);
		} else {
			HFC_outb(hc, R_SYNC_OUT, V_IPATS0 | V_IPATS1 | V_IPATS2);
		}
		HFC_outb(hc, R_PWM_MD, V_PWM0_MD);
		HFC_outb(hc, R_PWM0, 0x50);
		HFC_outb(hc, R_PWM1, 0xff);
		/* state machine setup */
		HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta | V_E1_LD_STA);
		udelay(6); /* wait at least 5,21us */
		HFC_outb(hc, R_E1_WR_STA, r_e1_wr_sta);

	}

	/* set interrupts & global interrupt */
	hc->hw.r_irq_ctrl = V_FIFO_IRQ | V_GLOB_IRQ_EN;

	unlock_dev(hc);

	if (debug & DEBUG_HFCMULTI_INIT)
		printk("%s: done\n", __FUNCTION__);
}


/***********************/
/* initialize the card */
/***********************/

/* start timer irq, wait some time and check if we have interrupts.
 * if not, reset chip and try again.
 */
static int
init_card(hfc_multi_t *hc)
{
	int cnt = 1; /* as long as there is no trouble */
	int err = -EIO;

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);

	lock_dev(hc, 0);
	if (request_irq(hc->pci_dev->irq, hfcmulti_interrupt, SA_SHIRQ, "HFC-multi", hc)) {
		printk(KERN_WARNING "mISDN: Could not get interrupt %d.\n", hc->pci_dev->irq);
		unlock_dev(hc);
		return(-EIO);
	}
	hc->irq = hc->pci_dev->irq;

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: IRQ %d count %d\n", __FUNCTION__, hc->irq, hc->irqcnt);
	while (cnt) {
		if ((err = init_chip(hc)))
			goto error;
		/* Finally enable IRQ output
		 * this is only allowed, if an IRQ routine is allready
		 * established for this HFC, so don't do that earlier
		 */
		unlock_dev(hc);
		HFC_outb(hc, R_IRQ_CTRL, V_GLOB_IRQ_EN);
		set_current_state(TASK_UNINTERRUPTIBLE);
		schedule_timeout((100*HZ)/1000); /* Timeout 100ms */
		/* turn IRQ off until chip is completely initialized */
		HFC_outb(hc, R_IRQ_CTRL, 0);
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: IRQ %d count %d\n", __FUNCTION__, hc->irq, hc->irqcnt);
		if (hc->irqcnt) {
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: done\n", __FUNCTION__);
			return(0);
		}
		lock_dev(hc, 0);
		printk(KERN_WARNING "HFC PCI: IRQ(%d) getting no interrupts during init (try %d)\n", hc->irq, cnt);
		cnt--;
		err = -EIO;
	}

	error:
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_WARNING "%s: free irq %d\n", __FUNCTION__, hc->irq);
	free_irq(hc->irq, hc);
	hc->irq = 0;
	unlock_dev(hc);

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: done (err=%d)\n", __FUNCTION__, err);
	return(err);
}


/*********************************************************/
/* select free channel and return OK(0), -EBUSY, -EINVAL */
/*********************************************************/

static int
SelFreeBChannel(hfc_multi_t *hc, int ch, channel_info_t *ci)
{
	bchannel_t		*bch;
	hfc_multi_t		*hfc;
	mISDNstack_t		*bst;
	struct list_head	*head;
	int			cnr;
	int			port = hc->chan[ch].port;

	if (port < 0 || port>=hc->type) {
		printk(KERN_WARNING "%s: port(%d) out of range", __FUNCTION__, port);
		return(-EINVAL);
	}

	if (!ci)
		return(-EINVAL);
	ci->st.p = NULL;
	cnr=0;
	bst = hc->chan[ch].dch->inst.st;
	if (list_empty(&bst->childlist)) {
		if ((bst->id & FLG_CLONE_STACK) &&
			(bst->childlist.prev != &bst->childlist)) {
			head = bst->childlist.prev;
		} else {
			printk(KERN_ERR "%s: invalid empty childlist (no clone) stid(%x) childlist(%p<-%p->%p)\n",
				__FUNCTION__, bst->id, bst->childlist.prev, &bst->childlist, bst->childlist.next);
			return(-EINVAL);
		}
	} else
		head = &bst->childlist;
	list_for_each_entry(bst, head, list) {
		if (cnr == ((hc->type==1)?30:2)) /* 30 or 2 B-channels */ {
			printk(KERN_WARNING "%s: fatal error: more b-stacks than ports", __FUNCTION__);
			return(-EINVAL);
		}
		if(!bst->mgr) {
			int_errtxt("no mgr st(%p)", bst);
			return(-EINVAL);
		}
		hfc = bst->mgr->privat;
		if (!hfc) {
			int_errtxt("no mgr->data st(%p)", bst);
			return(-EINVAL);
		}
		if (hc->type==1)
			bch = hc->chan[cnr + 1 + (cnr>=15)].bch;
		else
			bch = hc->chan[(port<<2) + cnr].bch;
		if (!(ci->channel & (~CHANNEL_NUMBER))) {
			/* only number is set */
			if ((ci->channel & 0x3) == (cnr + 1)) {
				if (bch->protocol != ISDN_PID_NONE)
					return(-EBUSY);
				ci->st.p = bst;
				return(0);
			}
		}
		if ((ci->channel & (~CHANNEL_NUMBER)) == 0x00a18300) {
			if (bch->protocol == ISDN_PID_NONE) {
				ci->st.p = bst;
				return(0);
			}
		}
		cnr++;
	}
	return(-EBUSY);
}


/*********************************/
/* find pci device and set it up */
/*********************************/

static int
setup_pci(hfc_multi_t *hc)
{
	int i;
	struct pci_dev *tmp_dev = NULL;
	hfc_multi_t *hc_tmp, *next;

	/* go into 0-state (we might already be due to zero-filled-object */
	i = 0;
	while(i < 32) {
		if (hc->chan[i].dch)
			hc->chan[i].dch->ph_state = 0;
		i++;
	}

	/* loop all card ids */
	i = 0;
	while (id_list[i].vendor_id) {
		/* only the given type is searched */
		if (id_list[i].type != hc->type) {
			i++;
			continue;
		}
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "setup_pci(): investigating card entry %d (looking for type %d)\n", i, hc->type);
		inuse:
		tmp_dev = pci_find_subsys(id_list[i].vendor_id, id_list[i].device_id, id_list[i].vendor_sub, id_list[i].device_sub, tmp_dev);
		if (tmp_dev) {
			/* skip if already in use */
			list_for_each_entry_safe(hc_tmp, next, &HFCM_obj.ilist, list) {
				if (hc_tmp->pci_dev == tmp_dev) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_INFO "setup_pci(): found a pci card: '%s' card name: '%s', but already in use, so we skip.\n", id_list[i].vendor_name, id_list[i].card_name);
					goto inuse;
				}
			}
			break;
		}
		i++;
	}
	if (!tmp_dev) {
		printk(KERN_WARNING "HFC-multi: No PCI card found\n");
		return (-ENODEV);
	}

	/* found a card */
	printk(KERN_INFO "HFC-multi: card manufacturer: '%s' card name: '%s' clock: %s\n", id_list[i].vendor_name, id_list[i].card_name, (id_list[i].clock2)?"double":"normal");
	hc->pci_dev = tmp_dev;
	if (id_list[i].clock2)
		test_and_set_bit(HFC_CHIP_CLOCK2, &hc->chip);
	if (hc->pci_dev->irq <= 0) {
		printk(KERN_WARNING "HFC-multi: No IRQ for PCI card found.\n");
		return (-EIO);
	}
	if (pci_enable_device(hc->pci_dev)) {
		printk(KERN_WARNING "HFC-multi: Error enabling PCI card.\n");
		return (-EIO);
	}
	hc->leds = id_list[i].leds;
#ifdef CONFIG_HFCMULTI_PCIMEM
	hc->pci_membase = (char *) get_pcibase(hc->pci_dev, 1);
	if (!hc->pci_membase) {
		printk(KERN_WARNING "HFC-multi: No IO-Memory for PCI card found\n");
		return (-EIO);
	}

	if (!(hc->pci_membase = ioremap((ulong) hc->pci_membase, 256))) {
		printk(KERN_WARNING "HFC-multi: failed to remap io address space. (internal error)\n");
		hc->pci_membase = NULL;
		return (-EIO);
	}
	printk(KERN_INFO "%s: defined at MEMBASE %#x IRQ %d HZ %d leds-type %d\n", hc->name, (u_int) hc->pci_membase, hc->pci_dev->irq, HZ, hc->leds);
	pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_MEMIO);
#else
	hc->pci_iobase = (u_int) get_pcibase(hc->pci_dev, 0);
	if (!hc->pci_iobase) {
		printk(KERN_WARNING "HFC-multi: No IO for PCI card found\n");
		return (-EIO);
	}
	if (!request_region(hc->pci_iobase, 8, "hfcmulti")) {
		printk(KERN_WARNING "HFC-multi: failed to rquest address space at 0x%04x (internal error)\n", hc->pci_iobase);
		hc->pci_iobase = 0;
		return (-EIO);
	}

	printk(KERN_INFO "%s: defined at IOBASE %#x IRQ %d HZ %d leds-type %d\n", hc->name, (u_int) hc->pci_iobase, hc->pci_dev->irq, HZ, hc->leds);
	pci_write_config_word(hc->pci_dev, PCI_COMMAND, PCI_ENA_REGIO);
#endif

	/* At this point the needed PCI config is done */
	/* fifos are still not enabled */
        lock_dev(hc, 0);
#ifdef SPIN_DEBUG
	printk(KERN_ERR "spin_lock_adr=%p now(%p)\n", &hc->lock.spin_adr, hc->lock.spin_adr);
	printk(KERN_ERR "busy_lock_adr=%p now(%p)\n", &hc->lock.busy_adr, hc->lock.busy_adr);
#endif
	unlock_dev(hc);
	return (0);
}


/*******************************************
 * remove port or complete card from stack *
 *******************************************/

static void
release_port(hfc_multi_t *hc, int port)
{
	int i = 0;
	int all = 1, any = 0;

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: entered\n", __FUNCTION__);

#ifdef LOCK_STATISTIC
        printk(KERN_INFO "try_ok(%d) try_wait(%d) try_mult(%d) try_inirq(%d)\n",                hc->lock.try_ok, hc->lock.try_wait, hc->lock.try_mult, hc->lock.try_inirq);
        printk(KERN_INFO "irq_ok(%d) irq_fail(%d)\n",
                hc->lock.irq_ok, hc->lock.irq_fail);
#endif

	if (port >= hc->type) {
		printk(KERN_WARNING "%s: ERROR port out of range (%d).\n", __FUNCTION__, port);
		return;
	}

//	if (debug & DEBUG_HFCMULTI_INIT)
//		printk(KERN_DEBUG "%s: before lock_dev\n", __FUNCTION__);
	lock_dev(hc, 0);
//	if (debug & DEBUG_HFCMULTI_INIT)
//		printk(KERN_DEBUG "%s: after lock_dev\n", __FUNCTION__);

	if (port > -1) {
		i = 0;
		while(i < hc->type) {
			if (hc->created[i] && i!=port)
				all = 0;
			if (hc->created[i])
				any = 1;
			i++;
		}
		if (!any) {
			printk(KERN_WARNING "%s: ERROR card has no used stacks anymore.\n", __FUNCTION__);
			unlock_dev(hc);
			return;
		}
	}
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: releasing port=%d all=%d any=%d\n", __FUNCTION__, port, all, any);

	if (port>-1 && !hc->created[port]) {
		printk(KERN_WARNING "%s: ERROR given stack is not used by card (port=%d).\n", __FUNCTION__, port);
		unlock_dev(hc);
		return;
	}

	if (all) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_WARNING "%s: card has no more used stacks, so we release hardware.\n", __FUNCTION__);
		if (hc->irq) {
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_WARNING "%s: free irq %d\n", __FUNCTION__, hc->irq);
			free_irq(hc->irq, hc);
			hc->irq = 0;
		}
	}

	/* disable D-channels & B-channels */
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: disable all channels (d and b)\n", __FUNCTION__);
	if (hc->type == 1) {
		hc->chan[16].slot_tx = -1;
		hc->chan[16].slot_rx = -1;
		hc->chan[16].conf = -1;
		mode_hfcmulti(hc, 16, ISDN_PID_NONE, -1, 0, -1, 0);//d
		i = 0;
		while(i < 30) {
			hc->chan[i+1+(i>=15)].slot_tx = -1;
			hc->chan[i+1+(i>=15)].slot_rx = -1;
			hc->chan[i+1+(i>=15)].conf = -1;
			mode_hfcmulti(hc, i+1+(i>=15), ISDN_PID_NONE, -1, 0, -1, 0); //b
			i++;
		}
	} else {
		i = 0;
		while(i < hc->type) {
			if (all || port==i)
			if (hc->created[i]) {
				hc->chan[(i<<2)+2].slot_tx = -1;
				hc->chan[(i<<2)+2].slot_rx = -1;
				hc->chan[(i<<2)+2].conf = -1;
				mode_hfcmulti(hc, (i<<2)+2, ISDN_PID_NONE, -1, 0, -1, 0); //d
				hc->chan[i<<2].slot_tx = -1;
				hc->chan[i<<2].slot_rx = -1;
				hc->chan[i<<2].conf = -1;
				mode_hfcmulti(hc, i<<2, ISDN_PID_NONE, -1, 0, -1, 0); //b1
				hc->chan[(i<<2)+1].slot_tx = -1;
				hc->chan[(i<<2)+1].slot_rx = -1;
				hc->chan[(i<<2)+1].conf = -1;
				mode_hfcmulti(hc, (i<<2)+1, ISDN_PID_NONE, -1, 0, -1, 0); //b2
			}
			i++;
		}
	}

	i = 0;
	while(i < 32) {
		if (hc->chan[i].dch)
		if (hc->created[hc->chan[i].port])
		if (hc->chan[i].dch->dbusytimer.function != NULL && (all || port==i)) {
			del_timer(&hc->chan[i].dch->dbusytimer);
			hc->chan[i].dch->dbusytimer.function = NULL;
		}
		i++;
	}

	/* free channels */
	i = 0;
	while(i < 32) {
		if (hc->created[hc->chan[i].port])
		if (hc->chan[i].port==port || all) {
			if (hc->chan[i].dch) {
				if (debug & DEBUG_HFCMULTI_INIT)
					printk(KERN_DEBUG "%s: free port %d D-channel %d (1..32)\n", __FUNCTION__, hc->chan[i].port, i);
				mISDN_free_dch(hc->chan[i].dch);
				// HFCM_obj.ctrl(hc->chan[i].dch->inst.up.peer, MGR_DISCONNECT | REQUEST, &hc->chan[i].dch->inst.up); TODO
				HFCM_obj.ctrl(&hc->chan[i].dch->inst, MGR_UNREGLAYER | REQUEST, NULL);
				kfree(hc->chan[i].dch);
				hc->chan[i].dch = NULL;
			}
			if (hc->chan[i].rx_buf) {
				kfree(hc->chan[i].rx_buf);
				hc->chan[i].rx_buf = NULL;
			}
			if (hc->chan[i].bch) {
				if (debug & DEBUG_HFCMULTI_INIT)
					printk(KERN_DEBUG "%s: free port %d B-channel %d (1..32)\n", __FUNCTION__, hc->chan[i].port, i);
				discard_queue(&hc->chan[i].dtmfque);
				mISDN_free_bch(hc->chan[i].bch);
				kfree(hc->chan[i].bch);
				hc->chan[i].bch = NULL;
			}
		}
		i++;
	}
	i = 0;
	while(i < 8) {
		if (i==port || all)
			hc->created[i] = 0;
		i++;
	}

	/* dimm leds */
	if (hc->leds)
		hfcmulti_leds(hc);

	/* release IO & remove card */
	if (all) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: do release_io_hfcmulti\n", __FUNCTION__);
		release_io_hfcmulti(hc);

		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: removing object from listbase\n", __FUNCTION__);
		list_del(&hc->list);
		unlock_dev(hc);
		kfree(hc);
	} else
		unlock_dev(hc);
}

static int
HFC_manager(void *data, u_int prim, void *arg)
{
	hfc_multi_t *hc;
	mISDNinstance_t *inst = data;
	struct sk_buff *skb;
	dchannel_t *dch = NULL;
	bchannel_t *bch = NULL;
	int ch = -1;
	int i;

	if (!data) {
		MGR_HASPROTOCOL_HANDLER(prim,arg,&HFCM_obj)
		printk(KERN_ERR "%s: no data prim %x arg %p\n", __FUNCTION__, prim, arg);
		return(-EINVAL);
	}

	/* find channel and card */
	list_for_each_entry(hc, &HFCM_obj.ilist, list) {
		i = 0;
		while(i < 32) {
//printk(KERN_DEBUG "comparing (D-channel) card=%08x inst=%08x with inst=%08x\n", hc, &hc->dch[i].inst, inst);
			if (hc->chan[i].dch)
			if (&hc->chan[i].dch->inst == inst) {
				ch = i;
				dch = hc->chan[i].dch;
				break;
			}
			if (hc->chan[i].bch)
			if (&hc->chan[i].bch->inst == inst) {
				ch = i;
				bch = hc->chan[i].bch;
				break;
			}
			i++;
		}
		if (ch >= 0)
			break;
	}
	if (ch < 0) {
		printk(KERN_ERR "%s: no card/channel found  data %p prim %x arg %p\n", __FUNCTION__, data, prim, arg);
		return(-EINVAL);
	}
	if (debug & DEBUG_HFCMULTI_MGR)
		printk(KERN_DEBUG "%s: channel %d (0..31)  data %p prim %x arg %p\n", __FUNCTION__, ch, data, prim, arg);

	switch(prim) {
		case MGR_REGLAYER | CONFIRM:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_REGLAYER\n", __FUNCTION__);
		if (dch)
			dch_set_para(dch, &inst->st->para);
		if (bch)
			bch_set_para(bch, &inst->st->para);
		break;

		case MGR_UNREGLAYER | REQUEST:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_UNREGLAYER\n", __FUNCTION__);
		if (dch) {
			// inst->down.fdata = dch;  TODO
			if ((skb = create_link_skb(PH_CONTROL | REQUEST, HW_DEACTIVATE, 0, NULL, 0))) {
				//if (hfcmulti_l1hw(&inst->down, skb)) dev_kfree_skb(skb); TODO
				if (hfcmulti_l1hw(inst, skb)) dev_kfree_skb(skb);
			}
		} else
		if (bch) {
			// inst->down.fdata = bch;
			if ((skb = create_link_skb(PH_CONTROL | REQUEST, 0, 0, NULL, 0))) {
				//if (hfcmulti_l2l1(&inst->down, skb)) dev_kfree_skb(skb);
				if (hfcmulti_l2l1(inst, skb)) dev_kfree_skb(skb);
			}
		}
		// HFCM_obj.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up); TODO
		HFCM_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
		break;

		case MGR_CLRSTPARA | INDICATION:
		arg = NULL;
		// fall through
		case MGR_ADDSTPARA | INDICATION:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_***STPARA\n", __FUNCTION__);
		if (dch)
			dch_set_para(dch, arg);
		if (bch)
			bch_set_para(bch, arg);
		break;

		case MGR_RELEASE | INDICATION:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_RELEASE = remove port from mISDN\n", __FUNCTION__);
		if (dch) {
			release_port(hc, hc->chan[ch].port);
			HFCM_obj.refcnt--;
		}
		if (bch)
			HFCM_obj.refcnt--;
		break;
#ifdef FIXME
		case MGR_CONNECT | REQUEST:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_CONNECT\n", __FUNCTION__);
		return(mISDN_ConnectIF(inst, arg));
		//break;

		case MGR_SETIF | REQUEST:
		case MGR_SETIF | INDICATION:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_SETIF\n", __FUNCTION__);
		if (dch)
			return(mISDN_SetIF(inst, arg, prim, hfcmulti_l1hw, NULL, dch));
		if (bch)
			return(mISDN_SetIF(inst, arg, prim, hfcmulti_l2l1, NULL, bch));
		//break;

		case MGR_DISCONNECT | REQUEST:
		case MGR_DISCONNECT | INDICATION:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_DISCONNECT\n", __FUNCTION__);
		return(mISDN_DisConnectIF(inst, arg));
		//break;
#endif
		case MGR_SELCHANNEL | REQUEST:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_SELCHANNEL\n", __FUNCTION__);
		if (!dch) {
			printk(KERN_WARNING "%s(MGR_SELCHANNEL|REQUEST): selchannel not dinst\n", __FUNCTION__);
			return(-EINVAL);
		}
		return(SelFreeBChannel(hc, ch, arg));
		//break;

		case MGR_SETSTACK | INDICATION:
		if (debug & DEBUG_HFCMULTI_MGR)
			printk(KERN_DEBUG "%s: MGR_SETSTACK\n", __FUNCTION__);
		if (bch && inst->pid.global==2) {
			//inst->down.fdata = bch;
			if ((skb = create_link_skb(PH_ACTIVATE | REQUEST, 0, 0, NULL, 0))) {
				// if (hfcmulti_l2l1(&inst->down, skb)) dev_kfree_skb(skb); TODO
				if (hfcmulti_l2l1(inst, skb)) dev_kfree_skb(skb);
			}
			if (inst->pid.protocol[2] == ISDN_PID_L2_B_TRANS)
			//	 if_link(&inst->up, DL_ESTABLISH | INDICATION, 0, 0, NULL, 0);  TODO
			// else if_link(&inst->up, PH_ACTIVATE | INDICATION, 0, 0, NULL, 0);
			mISDN_queue_data(inst, FLG_MSG_UP, DL_ESTABLISH | INDICATION, 0, 0, NULL, 0);
		else mISDN_queue_data(inst, FLG_MSG_UP, PH_ACTIVATE | INDICATION, 0, 0, NULL, 0);
		}
		break;

		PRIM_NOT_HANDLED(MGR_CTRLREADY | INDICATION);
		PRIM_NOT_HANDLED(MGR_GLOBALOPT | REQUEST);
		default:
		printk(KERN_WARNING "%s: prim %x not handled\n", __FUNCTION__, prim);
		return(-EINVAL);
	}
	return(0);
}


static int __init
HFCmulti_init(void)
{
	int err, err2, i;
	hfc_multi_t *hc,*next;
	mISDN_pid_t pid, pids[MAX_CARDS];
	mISDNstack_t *dst = NULL; /* make gcc happy */
	int port_cnt;
	int bchperport, pt;
	int ch, ch2;
	dchannel_t *dch;
	bchannel_t *bch;
	char tmp[64];

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: init entered\n", __FUNCTION__);

#ifdef __BIG_ENDIAN
#error "not running on big endian machines now"
#endif
	strcpy(tmp, hfcmulti_revision);
	printk(KERN_INFO "mISDN: HFC-multi driver Rev. %s\n", mISDN_getrev(tmp));

	switch(poll) {
		case 8:
		poll_timer = 2;
		break;
		case 16:
		poll_timer = 3;
		break;
		case 32:
		poll_timer = 4;
		break;
		case 64:
		poll_timer = 5;
		break;
		case 128: case 0:
		poll_timer = 6;
		poll = 128;
		break;
		case 256:
		poll_timer = 7;
		break;
		default:
		printk(KERN_ERR "%s: Wrong poll value (%d).\n", __FUNCTION__, poll);
		err = -EINVAL;
		return(err);

	}

	memset(&HFCM_obj, 0, sizeof(HFCM_obj));
#ifdef MODULE
	HFCM_obj.owner = THIS_MODULE;
#endif
	INIT_LIST_HEAD(&HFCM_obj.ilist);
	HFCM_obj.name = HFCName;
	HFCM_obj.own_ctrl = HFC_manager;
	HFCM_obj.DPROTO.protocol[0] = ISDN_PID_L0_TE_S0 | ISDN_PID_L0_NT_S0
				| ISDN_PID_L0_TE_E1 | ISDN_PID_L0_NT_E1;
	HFCM_obj.DPROTO.protocol[1] = ISDN_PID_L1_NT_S0
				| ISDN_PID_L1_TE_E1 | ISDN_PID_L1_NT_E1;
	HFCM_obj.BPROTO.protocol[1] = ISDN_PID_L1_B_64TRANS | ISDN_PID_L1_B_64HDLC;
	HFCM_obj.BPROTO.protocol[2] = ISDN_PID_L2_B_TRANS | ISDN_PID_L2_B_RAWDEV;

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: registering HFCM_obj\n", __FUNCTION__);
	if ((err = mISDN_register(&HFCM_obj))) {
		printk(KERN_ERR "Can't register HFC-Multi cards error(%d)\n", err);
		return(err);
	}
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: new mISDN object (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);

	/* Note: ALL ports are one "card" object */

	port_cnt = HFC_cnt = 0;
	while (HFC_cnt < MAX_CARDS  &&  type[HFC_cnt] > 0) {
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: Registering chip type %d (0x%x)\n", __FUNCTION__, type[HFC_cnt] & 0xff, type[HFC_cnt]);

		/* check card type */
		switch (type[HFC_cnt] & 0xff) {
			case 1:
			bchperport = 30;
			break;

			case 4:
			bchperport = 2;
			break;

			case 8:
			bchperport = 2;
			break;

			default:
			printk(KERN_ERR "Card type(%d) not supported.\n", type[HFC_cnt] & 0xff);
			err = -EINVAL;
			goto free_object;
		}


		/* allocate card+fifo structure */
		if (!(hc = kmalloc(sizeof(hfc_multi_t), GFP_ATOMIC))) {
			printk(KERN_ERR "No kmem for HFC-Multi card\n");
			err = -ENOMEM;
			goto free_object;
		}
		memset(hc, 0, sizeof(hfc_multi_t));
		hc->id = HFC_cnt + 1;
		hc->pcm = pcm[HFC_cnt];

		/* set chip specific features */
		hc->masterclk = -1;
		hc->type = type[HFC_cnt] & 0xff;
		if (type[HFC_cnt] & 0x100) {
			test_and_set_bit(HFC_CHIP_ULAW, &hc->chip);
			silence = 0xff; /* ulaw silence */
		} else
			silence = 0x2a; /* alaw silence */
		if (type[HFC_cnt] & 0x200)
			test_and_set_bit(HFC_CHIP_DTMF, &hc->chip);
//		if ((type[HFC_cnt]&0x400) && hc->type==4)
//			test_and_set_bit(HFC_CHIP_LEDS, &hc->chip);
		if (type[HFC_cnt] & 0x800)
			test_and_set_bit(HFC_CHIP_PCM_SLAVE, &hc->chip);
		if (type[HFC_cnt] & 0x1000)
			test_and_set_bit(HFC_CHIP_CLOCK_IGNORE, &hc->chip);
		if (type[HFC_cnt] & 0x2000)
			test_and_set_bit(HFC_CHIP_RX_SYNC, &hc->chip);
		if (type[HFC_cnt] & 0x4000)
			test_and_set_bit(HFC_CHIP_EXRAM_128, &hc->chip);
		if (type[HFC_cnt] & 0x8000)
			test_and_set_bit(HFC_CHIP_EXRAM_512, &hc->chip);
		hc->slots = 32;
		if (type[HFC_cnt] & 0x10000)
			hc->slots = 64;
		if (type[HFC_cnt] & 0x20000)
			hc->slots = 128;
		if (hc->type == 1)
			sprintf(hc->name, "HFC-E1#%d", HFC_cnt+1);
		else
			sprintf(hc->name, "HFC-%dS#%d", hc->type, HFC_cnt+1);

		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);
		list_add_tail(&hc->list, &HFCM_obj.ilist);
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: (after APPEND_TO_LIST)\n", __FUNCTION__);

		lock_HW_init(&hc->lock);

		pt = 0;
		while (pt < hc->type) {
			if (protocol[port_cnt] == 0) {
				printk(KERN_ERR "Not enough 'protocol' values given.\n");
				err = -EINVAL;
				goto free_channels;
			}
			if (hc->type == 1)
				ch = 16;
			else
				ch = (pt<<2)+2;
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: Registering D-channel, card(%d) ch(%d) port(%d) protocol(%x)\n", __FUNCTION__, HFC_cnt+1, ch, pt+1, protocol[port_cnt]);
			hc->chan[ch].port = pt;
			hc->chan[ch].nt_timer = -1;
			dch = kmalloc(sizeof(dchannel_t), GFP_ATOMIC);
			if (!dch) {
				err = -ENOMEM;
				goto free_channels;
			}
			memset(dch, 0, sizeof(dchannel_t));
			dch->channel = ch;
			//dch->debug = debug;
			dch->inst.obj = &HFCM_obj;
			dch->inst.lock = lock_dev;
			dch->inst.unlock = unlock_dev;
			mISDN_init_instance(&dch->inst, &HFCM_obj, hc, hfcmulti_l1hw);
			dch->inst.pid.layermask = ISDN_LAYER(0);
			sprintf(dch->inst.name, "HFCm%d/%d", HFC_cnt+1, pt+1);
			if (!(hc->chan[ch].rx_buf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
				err = -ENOMEM;
				goto free_channels;
			}
			if (mISDN_init_dch(dch)) {
				err = -ENOMEM;
				goto free_channels;
			}
			hc->chan[ch].dch = dch;

			i=0;
			while(i < bchperport) {
				if (hc->type == 1)
					ch2 = i + 1 + (i>=15);
				else
					ch2 = (pt<<2)+i;
				if (debug & DEBUG_HFCMULTI_INIT)
					printk(KERN_DEBUG "%s: Registering B-channel, card(%d) ch(%d) port(%d) channel(%d)\n", __FUNCTION__, HFC_cnt+1, ch2, pt+1, i);
				hc->chan[ch2].port = pt;
				bch = kmalloc(sizeof(bchannel_t), GFP_ATOMIC);
				if (!bch) {
					err = -ENOMEM;
					goto free_channels;
				}
				memset(bch, 0, sizeof(bchannel_t));
				bch->channel = ch2;
				mISDN_init_instance(&bch->inst, &HFCM_obj, hc, hfcmulti_l2l1);
				bch->inst.pid.layermask = ISDN_LAYER(0);
				bch->inst.lock = lock_dev;
				bch->inst.unlock = unlock_dev;
				//bch->debug = debug;
				sprintf(bch->inst.name, "%s B%d",
					dch->inst.name, i+1);
				if (mISDN_init_bch(bch)) {
					kfree(bch);
					err = -ENOMEM;
					goto free_channels;
				}
				skb_queue_head_init(&hc->chan[ch2].dtmfque);
				hc->chan[ch2].bch = bch;
#ifdef FIXME  // TODO
				if (bch->dev) {
					bch->dev->wport.pif.func = hfcmulti_l2l1;
					bch->dev->wport.pif.fdata = bch;
				}
#endif
				i++;
			}

			/* set D-channel */
			mISDN_set_dchannel_pid(&pid, protocol[port_cnt], layermask[port_cnt]);

			/* set PRI */
			if (hc->type == 1) {
				if (layermask[port_cnt] & ISDN_LAYER(2)) {
					pid.protocol[2] |= ISDN_PID_L2_DF_PTP;
				}
				if (layermask[port_cnt] & ISDN_LAYER(3)) {
					pid.protocol[3] |= ISDN_PID_L3_DF_PTP;
					pid.protocol[3] |= ISDN_PID_L3_DF_EXTCID;
					pid.protocol[3] |= ISDN_PID_L3_DF_CRLEN2;
				}
			}

			/* set protocol type */
			if (protocol[port_cnt] & 0x10) {
				/* NT-mode */
				dch->inst.pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_NT_E1:ISDN_PID_L0_NT_S0;
				dch->inst.pid.protocol[1] = (hc->type==1)?ISDN_PID_L1_NT_E1:ISDN_PID_L1_NT_S0;
				pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_NT_E1:ISDN_PID_L0_NT_S0;
				pid.protocol[1] = (hc->type==1)?ISDN_PID_L1_NT_E1:ISDN_PID_L1_NT_S0;
				dch->inst.pid.layermask |= ISDN_LAYER(1);
				pid.layermask |= ISDN_LAYER(1);
				if (layermask[port_cnt] & ISDN_LAYER(2))
					pid.protocol[2] = ISDN_PID_L2_LAPD_NET;
				test_and_set_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg);
			} else {
				/* TE-mode */
				dch->inst.pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_TE_E1:ISDN_PID_L0_TE_S0;
				pid.protocol[0] = (hc->type==1)?ISDN_PID_L0_TE_E1:ISDN_PID_L0_TE_S0;
				if (hc->type == 1) {
					/* own E1 for E1 */
					dch->inst.pid.protocol[1] = ISDN_PID_L1_TE_E1;
					pid.protocol[1] = ISDN_PID_L1_TE_E1;
					dch->inst.pid.layermask |= ISDN_LAYER(1);
					pid.layermask |= ISDN_LAYER(1);
				}
			}


			if (hc->type != 1) {
				/* S/T */
				/* set master clock */
				if (protocol[port_cnt] & 0x10000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL set master clock: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					if (test_bit(HFC_CFG_NTMODE, &hc->chan[ch].cfg)) {
						printk(KERN_ERR "Error: Master clock for port(%d) of card(%d) is only possible with TE-mode\n", pt+1, HFC_cnt+1);
						err = -EINVAL;
						goto free_channels;
					}
					if (hc->masterclk >= 0) {
						printk(KERN_ERR "Error: Master clock for port(%d) of card(%d) already defined for port(%d)\n", pt+1, HFC_cnt+1, hc->masterclk+1);
						err = -EINVAL;
						goto free_channels;
					}
					hc->masterclk = pt;
				}

				/* set transmitter line to non capacitive */
				if (protocol[port_cnt] & 0x20000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL set non capacitive transmitter: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					test_and_set_bit(HFC_CFG_NONCAP_TX, &hc->chan[ch].cfg);
				}

				/* disable E-channel */
				if (protocol[port_cnt] & 0x40000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL disable E-channel: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					test_and_set_bit(HFC_CFG_DIS_ECHANNEL, &hc->chan[ch].cfg);
				}
				/* register E-channel */
				if (protocol[port_cnt] & 0x80000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL register E-channel: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					test_and_set_bit(HFC_CFG_REG_ECHANNEL, &hc->chan[ch].cfg);
				}
			} else {
				/* E1 */
				/* set optical line type */
				if (protocol[port_cnt] & 0x10000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL set optical interfacs: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					test_and_set_bit(HFC_CFG_OPTICAL, &hc->chan[ch].cfg);
				}

				/* set LOS report */
				if (protocol[port_cnt] & 0x40000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL set LOS report: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					test_and_set_bit(HFC_CFG_REPORT_LOS, &hc->chan[ch].cfg);
				}

				/* set AIS report */
				if (protocol[port_cnt] & 0x80000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL set AIS report: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					test_and_set_bit(HFC_CFG_REPORT_AIS, &hc->chan[ch].cfg);
				}

				/* set SLIP report */
				if (protocol[port_cnt] & 0x100000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL set SLIP report: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt);
					test_and_set_bit(HFC_CFG_REPORT_SLIP, &hc->chan[ch].cfg);
				}

				/* set elastic jitter buffer */
				if (protocol[port_cnt] & 0x600000) {
					if (debug & DEBUG_HFCMULTI_INIT)
						printk(KERN_DEBUG "%s: PROTOCOL set elastic buffer to %d: card(%d) port(%d)\n", __FUNCTION__, hc->chan[ch].jitter, HFC_cnt+1, pt);
					hc->chan[ch].jitter = (protocol[port_cnt]>>21) & 0x3;
				} else
					hc->chan[ch].jitter = 2; /* default */
			}

			memcpy(&pids[pt], &pid, sizeof(pid));

			pt++;
			port_cnt++;
		}

		/* run card setup */
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: Setting up card(%d)\n", __FUNCTION__, HFC_cnt+1);
		if ((err = setup_pci(hc))) {
			goto free_channels;
		}
		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: Initializing card(%d)\n", __FUNCTION__, HFC_cnt+1);
		if ((err = init_card(hc))) {
			if (debug & DEBUG_HFCMULTI_INIT) {
				printk(KERN_DEBUG "%s: do release_io_hfcmulti\n", __FUNCTION__);
				release_io_hfcmulti(hc);
			}
			goto free_channels;
		}

		if (debug & DEBUG_HFCMULTI_INIT)
			printk(KERN_DEBUG "%s: Init modes card(%d)\n", __FUNCTION__, HFC_cnt+1);
		hfcmulti_initmode(hc);

		/* add stacks */
		pt = 0;
		while(pt < hc->type) {
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: Adding d-stack: card(%d) port(%d)\n", __FUNCTION__, HFC_cnt+1, pt+1);
			if (hc->type == 1)
				dch = hc->chan[16].dch;
			else
				dch = hc->chan[(pt<<2)+2].dch;
			if ((err = HFCM_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &dch->inst))) {
				printk(KERN_ERR  "MGR_ADDSTACK REQUEST dch err(%d)\n", err);
				free_release:
				release_port(hc, -1); /* all ports */
				goto free_object;
			}
			/* indicate that this stack is created */
			hc->created[pt] = 1;

			dst = dch->inst.st;

			i = 0;
			while(i < bchperport) {
				if (debug & DEBUG_HFCMULTI_INIT)
					printk(KERN_DEBUG "%s: Adding b-stack: card(%d) port(%d) B-channel(%d)\n", __FUNCTION__, HFC_cnt+1, pt+1, i+1);
				if (hc->type == 1)
					bch = hc->chan[i + 1 + (i>=15)].bch;
				else
					bch = hc->chan[(pt<<2) + i].bch;
				if ((err = HFCM_obj.ctrl(dst, MGR_NEWSTACK | REQUEST, &bch->inst))) {
					printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
					free_delstack:
					HFCM_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
					goto free_release;
				}
				bch->st = bch->inst.st;
				i++;
			}
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: (before MGR_SETSTACK REQUEST) layermask=0x%x\n", __FUNCTION__, pids[pt].layermask);

			if ((err = HFCM_obj.ctrl(dst, MGR_SETSTACK | REQUEST, &pids[pt]))) {
				printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
				goto free_delstack;
			}
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: (after MGR_SETSTACK REQUEST)\n", __FUNCTION__);

			/* delay some time */
			set_current_state(TASK_UNINTERRUPTIBLE);
			schedule_timeout((100*HZ)/1000); /* Timeout 100ms */

			/* tell stack, that we are ready */
			HFCM_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);

			pt++;
		}

		/* now turning on irq */
		HFC_outb(hc, R_IRQ_CTRL, hc->hw.r_irq_ctrl);

		HFC_cnt++;
	}

	if (HFC_cnt == 0) {
		printk(KERN_INFO "hfc_multi: No cards defined, read the documentation.\n");
		err = -EINVAL;
		goto free_object;
	}

	printk(KERN_INFO "hfc_multi driver: %d cards with total of %d ports installed.\n", HFC_cnt, port_cnt);
	return(0);

	/* DONE */

	/* if an error ocurred */
	free_channels:
	i = 0;
	while(i < 32) {
		if (hc->chan[i].dch) {
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: free D-channel %d (1..32)\n", __FUNCTION__, i);
			mISDN_free_dch(hc->chan[i].dch);
			kfree(hc->chan[i].dch);
			hc->chan[i].dch = NULL;
		}
		if (hc->chan[i].rx_buf) {
			kfree(hc->chan[i].rx_buf);
			hc->chan[i].rx_buf = NULL;
		}
		if (hc->chan[i].bch) {
			if (debug & DEBUG_HFCMULTI_INIT)
				printk(KERN_DEBUG "%s: free B-channel %d (1..32)\n", __FUNCTION__, i);
			discard_queue(&hc->chan[i].dtmfque);
			mISDN_free_bch(hc->chan[i].bch);
			kfree(hc->chan[i].bch);
			hc->chan[i].bch = NULL;
		}
		i++;
	}
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: before REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
	list_del(&hc->list);
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: after REMOVE_FROM_LIST (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
	kfree(hc);

	free_object:
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: brefore mISDN_unregister (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
	if ((err2 = mISDN_unregister(&HFCM_obj))) {
		printk(KERN_ERR "Can't unregister HFC-Multi cards error(%d)\n", err);
	}
	list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
		printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
		release_port(hc, -1); /* all ports */
	}
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: after mISDN_unregister (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: exitting with error %d\n", __FUNCTION__, err);
	return(err);
}


#ifdef MODULE
static void __exit
HFCmulti_cleanup(void)
{
	hfc_multi_t *hc,*next;
	int err;

	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: entered (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
	if ((err = mISDN_unregister(&HFCM_obj))) {
		printk(KERN_ERR "Can't unregister HFC-Multi cards error(%d)\n", err);
	}
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: now checking ilist (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);

	list_for_each_entry_safe(hc, next, &HFCM_obj.ilist, list) {
		printk(KERN_ERR "HFC PCI card struct not empty refs %d\n", HFCM_obj.refcnt);
		release_port(hc, -1); /* all ports */
	}
	if (debug & DEBUG_HFCMULTI_INIT)
		printk(KERN_DEBUG "%s: done (refcnt = %d)\n", __FUNCTION__, HFCM_obj.refcnt);
	return;
}
module_init(HFCmulti_init);
module_exit(HFCmulti_cleanup);
#endif
2005-07-06 01:18:05 +00:00
Karsten Keil 73cce70fa6 - L1 statemachine need HW_POWERUP to start properly 2005-07-04 13:21:28 +00:00
Karsten Keil 26200fa375 - add HOLD/RETRIEVE support (L3 and CAPI)
- add CDallDefection support
2005-07-04 09:09:54 +00:00
Karsten Keil a1420e85b2 - Support for codesets != 0 in Q.931 messages
- Support for repeated infoelements
- Handling of Reject component in Supplementary Services
2005-06-28 07:25:31 +00:00
Karsten Keil 542f8588c4 Second bugfix for bug 7, encoded component length was wrong
add some useful debug
2005-06-26 11:24:02 +00:00
Karsten Keil 2fb2b854ef Fix bug #0000007 Capidivert doesnt work with mISDN an Fritz! PCI
- DUMMY CR messages from up was not handled in l3_udss1
- some better debug and cleanup
- FACILITY RESPONSE is a currently a no op, handle it early without queueing
  to abvoid possible races with ReleaseApplication
2005-06-24 15:28:54 +00:00
Karsten Keil 822b8d28ee - implement basic udev support, now /dev/mISDN should be created on the fly 2005-06-23 16:25:51 +00:00
Karsten Keil 08ac4af99a - change sleep* -> wait* functions
- add some more statistic printout for the threads
- clear_stack is now done in stack thread context, maybe I will move more
  control functions this way
2005-06-22 13:51:17 +00:00
Karsten Keil d46b857d67 move capi layer to use the message queues for CAPI messages
now we can remove the locks in ncci code
2005-06-21 14:57:04 +00:00
psprenger 3f71c60ef2 new mqueue support - first tests were ok 2005-06-15 15:11:24 +00:00
Karsten Keil 865dfe93b2 add support for cloned stacks
messages queues can be temporary stopped now
some cleanups
2005-05-30 16:42:28 +00:00
Karsten Keil 9aa4b41d68 - fix HFC PCI driver
- some cleanups
2005-05-18 14:19:34 +00:00
Karsten Keil 3f5a6d398f get kernel/user interface working for some cases, still missing clone
stacks and rawdevices
2005-05-13 10:41:48 +00:00
Karsten Keil b901a8dfcd FLG_MSG_TARGET for direct target addressing 2005-05-12 10:24:08 +00:00
Karsten Keil fbd7e82890 first working version
STILL TODO:
  - capi update to queue first
  - more cards (only hfc_pci and sedlfax ported now)
  - Kernel/Userinterface still not fully changed
2005-05-12 07:59:06 +00:00
Karsten Keil 7ce8e6cc8c next step for mqueue !!! DO NOT USE !!! 2005-05-10 14:18:13 +00:00
Karsten Keil 4cbd60f063 first step move to message queue driven desgin (DO NOT USE THIS VERSION) 2005-05-07 21:04:11 +00:00
88 changed files with 1899 additions and 7776 deletions

View File

@ -1,8 +0,0 @@
mISDN-1-1-2:
- added a workaround that fixes a kernel panic when bridging is done after already a few
voice frames where transceived on both legs (like when you transfer a call from SIP 2 ISDN)
- jollys mail has changed
- minor tweaks to misdn-init and to the Kernel-Patch script
- fix in CMX: sending is required even during PCM bridge, because sending data overrides bridging temporarily (for sending info tones during bridge)
- enabled CMX audio processing for RX data in all cases, because it is essential
- now it is save to free skb during interrupt, if memdebug is on

View File

@ -1,25 +1,14 @@
BASEDIR=$(shell pwd)
MAJOR=1
MINOR=1
SUBMINOR=2
INSTALL_PREFIX := /
export INSTALL_PREFIX
#PATH to linux source/headers
#LINUX=/usr/src/linux
ifndef KVERS
KVERS:=$(shell uname -r)
endif
MODS=/lib/modules/$(KVERS)
MODS=/lib/modules/$(shell uname -r)
LINUX=$(MODS)/build
LINUX_SOURCE=$(MODS)/source
UPDATE_MODULES=$(shell which update-modules)
MODULES_UPDATE=$(shell which modules-update)
DEPMOD=$(shell which depmod)
MISDNDIR=$(BASEDIR)
@ -29,8 +18,7 @@ MISDN_SRC=$(MISDNDIR)/drivers/isdn/hardware/mISDN
# USER CONFIGS END
########################################
CONFIGS+=CONFIG_MISDN_DRV=m
CONFIGS+=CONFIG_MISDN_DSP=m
CONFIGS+=CONFIG_MISDN_DRV=m CONFIG_MISDN_DSP=m
CONFIGS+=CONFIG_MISDN_HFCMULTI=m
CONFIGS+=CONFIG_MISDN_HFCPCI=m
CONFIGS+=CONFIG_MISDN_HFCUSB=m
@ -39,44 +27,30 @@ CONFIGS+=CONFIG_MISDN_HFCMINI=m
CONFIGS+=CONFIG_MISDN_W6692=m
CONFIGS+=CONFIG_MISDN_SPEEDFAX=m
CONFIGS+=CONFIG_MISDN_AVM_FRITZ=m
CONFIGS+=CONFIG_MISDN_NETJET=m
#CONFIGS+=CONFIG_MISDN_NETDEV=y
MISDNVERSION=$(shell cat VERSION)
MINCLUDES+=-I$(MISDNDIR)/include
all: VERSION test_old_misdn
all: test_old_misdn
@echo
@echo "Makeing mISDN"
@echo "============="
@echo
cp $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile.v2.6 $(MISDNDIR)/drivers/isdn/hardware/mISDN/Makefile
export MINCLUDES=$(MISDNDIR)/include ; export MISDNVERSION=$(MISDNVERSION); make -C $(LINUX) SUBDIRS=$(MISDN_SRC) modules $(CONFIGS)
install: all modules-install misdn-init
$(DEPMOD)
$(UPDATE_MODULES)
$(MODULES_UPDATE)
make -C config install
export MINCLUDES=$(MISDNDIR)/include ; make -C $(LINUX) SUBDIRS=$(MISDN_SRC) modules $(CONFIGS)
modules-install:
cd $(LINUX) ; make INSTALL_MOD_PATH=$(INSTALL_PREFIX) SUBDIRS=$(MISDN_SRC) modules_install
mkdir -p $(INSTALL_PREFIX)/usr/include/linux/
install: all
cd $(LINUX) ; make SUBDIRS=$(MISDN_SRC) modules_install
cp $(MISDNDIR)/include/linux/*.h $(INSTALL_PREFIX)/usr/include/linux/
install -m755 misdn-init /etc/init.d/
depmod
misdn-init:
mkdir -p $(INSTALL_PREFIX)/usr/sbin/
install -m755 misdn-init $(INSTALL_PREFIX)/usr/sbin/
if [ -d $(INSTALL_PREFIX)/etc/init.d ]; then \
if [ -e $(INSTALL_PREFIX)/etc/init.d/misdn-init ]; then rm -rf $(INSTALL_PREFIX)/etc/init.d/misdn-init; fi; \
ln -s $(INSTALL_PREFIX)/usr/sbin/misdn-init $(INSTALL_PREFIX)/etc/init.d/misdn-init; \
fi
mkdir -p $(INSTALL_PREFIX)/etc/modprobe.d
cp mISDN.modprobe.d $(INSTALL_PREFIX)/etc/modprobe.d/mISDN
mkdir -p $(INSTALL_PREFIX)/etc/modules.d
cp mISDN.modprobe.d $(INSTALL_PREFIX)/etc/modules.d/mISDN
test_old_misdn:
@if echo -ne "#include <linux/mISDNif.h>" | gcc -C -E - 2>/dev/null 1>/dev/null ; then \
if ! echo -ne "#include <linux/mISDNif.h>\n#if MISDN_MAJOR_VERSION < 4\n#error old mISDNif.h\n#endif\n" | gcc -C -E - 2>/dev/null 1>/dev/null ; then \
if ! echo -ne "#include <linux/mISDNif.h>\n#ifndef FLG_MSG_DOWN\n#error old mISDNif.h\n#endif\n" | gcc -C -E - 2>/dev/null 1>/dev/null ; then \
echo -ne "\n!!You should remove the following files:\n\n$(LINUX)/include/linux/mISDNif.h\n$(LINUX)/include/linux/isdn_compat.h\n/usr/include/linux/mISDNif.h\n/usr/include/linux/isdn_compat.h\n\nIn order to upgrade to the mqueue branch\n\n"; \
echo -ne "I can do that for you, just type: make force\n\n" ; \
exit 1; \
@ -84,8 +58,7 @@ test_old_misdn:
fi
.PHONY: modules-install install all clean misdn-init VERSION
.PHONY: install all clean
force:
rm -f $(LINUX)/include/linux/mISDNif.h
@ -102,26 +75,3 @@ clean:
find . -iname "*.mod.c" -exec rm -rf {} \;
find . -iname "*.mod" -exec rm -rf {} \;
VERSION:
if cvs status Makefile | grep "Sticky Tag" | grep none > /dev/null ; then \
echo $(MAJOR)_$(MINOR)_$(SUBMINOR)-$$(date +"20%y_%m_%d" | sed -e "s/\//_/g") > VERSION ; \
else \
echo $(MAJOR)_$(MINOR)_$(SUBMINOR) > VERSION ; \
fi
snapshot: clean
DIR=mISDN-$$(date +"20%y_%m_%d") ; \
echo $(MAJOR)_$(MINOR)_$(SUBMINOR)-$$(date +"20%y_%m_%d" | sed -e "s/\//_/g") > VERSION ; \
mkdir -p /tmp/$$DIR ; \
cp -a * /tmp/$$DIR ; \
cd /tmp/; \
tar czf $$DIR.tar.gz $$DIR
release: clean
DIR=mISDN-$(MAJOR)_$(MINOR)_$(SUBMINOR) ; \
echo $(MAJOR)_$(MINOR)_$(SUBMINOR) > VERSION ; \
mkdir -p /tmp/$$DIR ; \
cp -a * /tmp/$$DIR ; \
cd /tmp/; \
tar czf $$DIR.tar.gz $$DIR

View File

@ -7,7 +7,7 @@ for your card and port settings, then it loads the driver modules properly.
The misdn-init.conf can also be autogenerated by the misdn-init script.
---------------------------------------------------------------------------
Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
Usage: /etc/init.d/misdn-init start|stop|restart|config|scan|help
--start scan /etc/misdn-init.conf and load the mISDN drivers
--stop unload the mISDN drivers
@ -25,11 +25,11 @@ Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
1) Get and install misdn-init:
$ wget http://www.beronet.com/downloads/chan_misdn/stable/chan_misdn.tar.gz
$ tar zxf chan_misdn.tar.gz
$ (as root) cp chan_misdn/misdn-init /usr/sbin/misdn-init
$ (as root) cp chan_misdn/misdn-init /etc/init.d/misdn-init
2) Let misdn-init scan your PCI bus for mISDN compatible hardware and write
the results into /etc/misdn-init.conf:
$ (as root) /usr/sbin/misdn-init config
$ (as root) /etc/init.d/misdn-init config
3) (optional) Edit /etc/misdn-init.conf and set everything the way you want it.
This file is heavily commented, hence it should be self-explaining.
@ -44,7 +44,7 @@ Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
$ (as root) update-rc.d misdn-init start 60 2 3 4 5 . stop 60 0 1 6 .
5) Run the following to start mISDN:
$ (as root) /usr/sbin/misdn-init start
$ (as root) /etc/init.d/misdn-init start

View File

@ -1,11 +0,0 @@
all:
@echo "Please run 'make install'."
install:
install -D -m755 mISDN $(INSTALL_PREFIX)/usr/sbin/mISDN
for file in $(shell echo *.xsl); do install -D -m644 $${file} $(INSTALL_PREFIX)/usr/lib/mISDN/$${file}; done
if [ -d $(INSTALL_PREFIX)/etc/init.d ]; then \
if [ -e $(INSTALL_PREFIX)/etc/init.d/mISDN ]; then rm -rf $(INSTALL_PREFIX)/etc/init.d/mISDN; fi; \
ln -s $(INSTALL_PREFIX)/usr/sbin/mISDN $(INSTALL_PREFIX)/etc/init.d/mISDN; \
fi

View File

@ -1,65 +0,0 @@
'mISDN': init-script to auto-configure and load the mISDN kernel drivers
===========================================================================
This script makes it easy to configure and activate mISDN compatible
adapter cards. It scans an eyecandy config file named mISDN.conf
for your card and port settings, then it loads the driver modules properly.
The misdn-init.conf can also be autogenerated by the mISDN script.
---------------------------------------------------------------------------
Requirements:
The 'mISDN' script requires you to install the tool 'xsltproc'. To install
xsltproc on debian, just type:
$ apt-get install xsltproc (as root)
On other distros the package name might be libxmtools or likewise.
---------------------------------------------------------------------------
Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
--start scan /etc/misdn-init.conf and load the mISDN drivers
--stop unload the mISDN drivers
--restart see stop, then start
--config scan your PCI bus for mISDN compatible hardware and generate
a /etc/mISDN.conf
--scan scan your PCI bus for mISDN compatible hardware and print
the results to the console
--help print the usage info
---------------------------------------------------------------------------
* Here is a quick overview on how to use mISDN:
1) Get and install mISDN:
$ wget http://www.misdn.org/downloads/mISDN.tar.gz
$ tar xzf mISDN.tar.gz
$ cd mISDN*
$ make install
2) Let mISDN scan your PCI bus for mISDN compatible hardware and write
the results into /etc/mISDN.conf:
$ (as root) mISDN config
3) (optional) Edit /etc/mISDN.conf and set everything the way you want it.
This file is heavily commented, hence it should be self-explaining.
4) (optional, but recommended) Add 'mISDN' to your run level.
This is distribution dependend. Here an example for a debian system:
ATTENTION: If you have services in your runlevels that depend
on mISDN, make sure that 'mISDN' starts before, and
stops after them (this is done by changing the values
that are set to 60 in this example, more info: read the
manpage for update-rc.d).
$ (as root) update-rc.d mISDN start 60 2 3 4 5 . stop 60 0 1 6 .
5) Run the following to start mISDN:
$ (as root) mISDN start
---------------------------------------------------------------------------
* Report Bugs:
If you experience any bugs or have a feature request, please visit:
www.isdn4linux.de/mantis

View File

@ -1,434 +0,0 @@
#!/bin/bash
#----------------------------------------------
#
# CONFIGURATION:
#
MISDN_CONF="/etc/mISDN.conf"
MISDN_CONF_XSL="/usr/lib/mISDN/mISDN.conf.xsl"
#
#----------------------------------------------
SELF="${0}"
USAGE="Usage: ${SELF} start|stop|restart|config|scan|help"
function die {
echo "[!!] ${1}"
exit 1
}
function check_cmd
{
if ! which "${1}" > /dev/null; then
if [ "${2}" = "opt" ]; then
return
fi
if [ "$(id -u)" != "0" ]; then
die "$1 not in path, please install and/or be root."
else
die "$1 not in path, please install."
fi
exit 1
else
local var=$(echo ${1} | tr a-z A-Z)
eval "$var=`which ${1}`"
fi
}
function check_misdn_conf
{
if [ ! -f ${MISDN_CONF} ]; then
die "${MISDN_CONF} not found. Please run: ${SELF} config"
fi
}
check_cmd sed
check_cmd cut
check_cmd cp
check_cmd wc
check_cmd grep
check_cmd xsltproc
check_cmd modprobe
check_cmd sleep
check_cmd lspci
check_cmd lsusb opt
check_cmd mknod
check_cmd chown
check_cmd chmod
declare -a START_COMMANDS
declare -a STOP_COMMANDS
declare -a HFCMULTI_card
declare -a HFCMULTI_type
declare -a HFCMULTI_protocol
declare -a HFCMULTI_layermask
HFCMULTI_options=''
MISDNDSP_options=''
AVMFRITZ_protocol=''
AVMFRITZ_layermask=''
HFCPCI_protocol=''
HFCPCI_layermask=''
DEVNODE_user='root'
DEVNODE_group='root'
DEVNODE_mode='0644'
declare -a SCAN_card
declare -a SCAN_opts
declare -a SCAN_num_ports
declare -a SCAN_port_opts
function parse_config
{
local CONFIG=$(${XSLTPROC} ${MISDN_CONF_XSL} ${MISDN_CONF})
local t p l line i tmpcmd curr tmpstr
local IFS=$'\n'
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install capi"
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_core debug=0"
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_l1 debug=0"
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_l2 debug=0"
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install l3udss1 debug=0"
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_capi"
for line in ${CONFIG}; do
case "${line}" in
DEVNODE:mISDN*)
tmpstr=$(echo ${line} | ${SED} -n 's/.*user:\([^ ]*\).*/\1/p')
if [ ! -z "${tmpstr}" ]; then
DEVNODE_user="${tmpstr}"
fi
tmpstr=$(echo ${line} | ${SED} -n 's/.*group:\([^ ]*\).*/\1/p')
if [ ! -z "${tmpstr}" ]; then
DEVNODE_group="${tmpstr}"
fi
tmpstr=$(echo ${line} | ${SED} -n 's/.*mode:\([^ ]*\).*/\1/p')
if [ ! -z "${tmpstr}" ]; then
DEVNODE_mode="${tmpstr}"
fi
;;
MODULE:hfcmulti*)
HFCMULTI_options=${line:16}
;;
MODULE:mISDN_dsp*)
MISDNDSP_options=${line:17}
;;
CARD:BN*)
curr='hfcmulti'
i=${#HFCMULTI_type[@]}
let "t = $(echo ${line} | ${SED} -n 's/.*type:\([^,]*\).*/\1/p')"
HFCMULTI_type[${i}]=$(printf "0x%x" ${t})
# this is for the BN2E1 card that needs two type numbers
t=$(echo ${line} | ${SED} -n 's/.*type:[^,]*,\([^ ]*\).*/\1/p')
if [ ! -z "${t}" ]; then
let "t = ${t}"
HFCMULTI_type[${i}]="${HFCMULTI_type[${i}]},$(printf "0x%x" ${t})"
fi
HFCMULTI_card[${i}]=$(echo ${line:5} | ${CUT} -d" " -f1)
;;
CARD:hfcpci*)
curr='hfcpci'
;;
CARD:avmfritz*)
curr='avmfritz'
;;
PORT*)
case "${curr}" in
hfcmulti)
let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
HFCMULTI_protocol[${i}]="${HFCMULTI_protocol[${i}]:+"${HFCMULTI_protocol[${i}]},"}$(printf "0x%x" ${p})"
let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
HFCMULTI_layermask[${i}]="${HFCMULTI_layermask[${i}]:+"${HFCMULTI_layermask[${i}]},"}$(printf "0x%x" ${l})"
;;
hfcpci)
let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
HFCPCI_protocol="${HFCPCI_protocol:+"${HFCPCI_protocol},"}$(printf "0x%x" ${p})"
let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
HFCPCI_layermask="${HFCPCI_layermask:+"${HFCPCI_layermask},"}$(printf "0x%x" ${l})"
;;
avmfritz)
let "p = $(echo ${line} | ${SED} -n 's/.*protocol:\([^ ]*\).*/\1/p')"
AVMFRITZ_protocol="${AVMFRITZ_protocol:+"${AVMFRITZ_protocol},"}$(printf "0x%x" ${p})"
let "l = $(echo ${line} | ${SED} -n 's/.*layermask:\([^ ]*\).*/\1/p')"
AVMFRITZ_layermask="${AVMFRITZ_layermask:+"${AVMFRITZ_layermask},"}$(printf "0x%x" ${l})"
;;
esac
;;
esac
done
if [ ! -z "${HFCMULTI_protocol[0]}" ]; then
tmpcmd="${MODPROBE} --ignore-install hfcmulti type=${HFCMULTI_type[0]}"
i=1
while [ ! -z "${HFCMULTI_type[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_type[${i}]}"
let "i = ${i} + 1"
done
tmpcmd="${tmpcmd} protocol=${HFCMULTI_protocol[0]}"
i=1
while [ ! -z "${HFCMULTI_protocol[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_protocol[${i}]}"
let "i = ${i} + 1"
done
tmpcmd="${tmpcmd} layermask=${HFCMULTI_layermask[0]}"
i=1
while [ ! -z "${HFCMULTI_layermask[${i}]}" ]; do
tmpcmd="${tmpcmd},${HFCMULTI_layermask[${i}]}"
let "i = ${i} + 1"
done
START_COMMANDS[${#START_COMMANDS[@]}]="${tmpcmd} ${HFCMULTI_options}"
fi
if [ ! -z "${HFCPCI_protocol}" ]; then
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install hfcpci protocol=${HFCPCI_protocol} layermask=${HFCPCI_layermask}"
fi
if [ ! -z "${AVMFRITZ_protocol}" ]; then
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install avmfritz protocol=${AVMFRITZ_protocol} layermask=${AVMFRITZ_layermask}"
fi
START_COMMANDS[${#START_COMMANDS[@]}]="${MODPROBE} --ignore-install mISDN_dsp ${MISDNDSP_options}"
}
function run_start_commands
{
local i=0
echo "-- Loading mISDN modules --"
while [ ! -z "${START_COMMANDS[${i}]}" ]; do
echo ">> ${START_COMMANDS[${i}]}"
eval "${START_COMMANDS[${i}]}"
let "i = ${i} + 1"
done
}
function run_stop_commands
{
local mod i=0
for mod in $(lsmod | ${SED} -ne '/Module/!{s/\([^ ]*\).*/\1/;p}'); do
case "${mod}" in
mISDN_capi | mISDN_dsp | l3udss1 | mISDN_l2 | mISDN_l1 | mISDN_isac | hfcmulti | avmfritz)
STOP_COMMANDS[0]="${STOP_COMMANDS[0]:-"${MODPROBE} -r --ignore-remove"} ${mod}"
;;
mISDN_core)
STOP_COMMANDS[1]="${MODPROBE} -r --ignore-remove mISDN_core"
;;
esac
done
echo "-- Unloading mISDN modules --"
while [ ! -z "${STOP_COMMANDS[${i}]}" ]; do
echo ">> ${STOP_COMMANDS[${i}]}"
eval "${STOP_COMMANDS[${i}]}"
let "i = ${i} + 1"
done
}
function scan_devices
{
local skipnext=0 IFS=$'\n'
local NL="
"
function addcard {
SCAN_card[${#SCAN_card[@]}]="${1}"
SCAN_opts[${#SCAN_opts[@]}]="${2}"
SCAN_num_ports[${#SCAN_num_ports[@]}]="${3}"
SCAN_port_opts[${#SCAN_port_opts[@]}]="${4}"
}
for line in $(${LSPCI} -n -d 0xd161:b410); do
addcard "BN4S0" "" 4 'mode="te" link="ptmp"'
done
for line in $(${LSPCI} -n | ${SED} -n 's/^\(0000:\|\)\([0-9a-f]\{2\}:[0-9a-f]\{2\}.[0-9a-f]\{1\}\)\( Class \| \)[0-9a-f]\{4\}: 1397:\([0-9a-f]\{4\}\).*$/\4 \2/p'); do
if [ ${skipnext} -eq 1 ]; then
skipnext=0
continue
fi
case "${line}" in
30b1*)
case "${line:5}" in
00*)
addcard "BN1E1" "" 1 'mode="nt" link="ptp"'
;;
*)
if [ $(${LSPCI} -n -s "${line:5:3}" | ${WC} -l) -eq 2 ]; then
addcard "BN2E1" "" 2 'mode="nt" link="ptp"'
skipnext=1
else
addcard "BN1E1" "" 1 'mode="nt" link="ptp"'
fi
;;
esac
;;
16b8*)
addcard "BN8S0" "" 8 'mode="te" link="ptmp"'
;;
08b4*)
if ${LSPCI} -n -v -s "${line:5}" | ${GREP} "Subsystem" | ${GREP} "1397:b567" > /dev/null ; then
addcard "BN1S0" "" 1 'mode="te" link="ptmp"'
elif ${LSPCI} -n -v -s "${line:5}" | ${GREP} "Subsystem" | ${GREP} "1397:b566\|1397:b569" > /dev/null ; then
addcard "BN2S0" "" 2 'mode="te" link="ptmp"'
else
addcard "BN4S0" "" 4 'mode="te" link="ptmp"'
fi
;;
esac
done
for line in $(${LSPCI} -n | ${GREP} "1397:\(2bd\(0\|6\|7\|8\|9\|a\|b\|c\)\|b100\)\|1043:0675\|0871:ffa\(1\|2\)\|1051:0100\|15b0:2bd0\|114f:007\(0\|1\|2\|3\)\|13d1:2bd1\|182d:3069"); do
addcard "hfcpci" "" 1 'mode="te" link="ptmp"'
done
for line in $(${LSPCI} -n | ${GREP} "1244:\(0a00\|0e00\)"); do
addcard "avmfritz" "" 1 'mode="te" link="ptmp"'
done
for line in $(${LSPCI} -n -d 1050:6692); do
addcard "w6692pci" "" 1 'mode="te" link="ptmp"'
done
if [ -e ${LSUSB} ]; then
for line in $(${LSUSB} | ${GREP} "0959:2bd0\|0675:1688\|07b0:0007\|0742:200\(7\|8\|9\|A\)\|08e3:0301\|07fa:084\(7\|8\)\|07ba:0006"); do
addcard "hfcsusb" "" 1 'mode="te" link="ptmp"'
done
fi
}
function write_mISDN_conf
{
local NL="
"
local TAB=" "
local HEADER="<?xml version=\"1.0\"?>
<!--
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Card Type: BN2S0, BN4S0, BN8S0
Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
crystalclock=(yes|no), watchdog=(yes|no)
Port Attributes: mode=(te|nt), link=(ptp|ptmp), master-clock=(yes|no),
capi=(yes|no)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Card Type: BN2E1
Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no),
ignore_pcm_frameclock=(yes|no), rxclock=(yes|no),
crystalclock=(yes|no), watchdog=(yes|no)
Port Attributes: mode=(te|nt), link=(ptp|ptmp), optical=(yes|no), los=(yes|no),
ais=(yes|no), slip=(yes|no), nocrc4=(yes|no), capi=(yes|no)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Card Type: hfcmulti, avmfritz, w6692pci
Port Attributes: mode=(te|nt), link=(ptp|ptmp), capi=(yes|no)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Module: hfcmulti
Options: poll=<number>, pcm=<number>, debug=<number>, timer=(yes|no)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Module: mISDN_dsp
Options: debug=<number>, options=<number>, poll=<number>,
dtmfthreshold=<number>
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-->
<mISDNconf>
${TAB}<module poll=\"128\" debug=\"0\" timer=\"no\">hfcmulti</module>
${TAB}<module debug=\"0\" options=\"0\">mISDN_dsp</module>
${TAB}<devnode user=\"root\" group=\"root\" mode=\"644\">mISDN</devnode>"
local FOOTER="</mISDNconf>"
local i=0 j=0 MAIN=""
echo "Writing ${MISDN_CONF} for ${#SCAN_card[@]} mISDN compatible device(s):"
while [ ! -z "${SCAN_card[${i}]}" ]; do
echo ">> ${SCAN_card[${i}]}"
MAIN="${MAIN}${NL}${TAB}<card type=\"${SCAN_card[${i}]}\"${SCAN_opts[${i}]:+" ${SCAN_opts[${i}]}"}>"
j=1
while [ ${j} -le ${SCAN_num_ports[${i}]} ]; do
MAIN="${MAIN}${NL}${TAB}${TAB}<port${SCAN_port_opts[${i}]:+" ${SCAN_port_opts[${i}]}"}>${j}</port>"
let "j = ${j} + 1"
done
MAIN="${MAIN}${NL}${TAB}</card>"
let "i = ${i} + 1"
done
if [ -f ${MISDN_CONF} ]; then
echo "${MISDN_CONF} already present, saving a backup: ${MISDN_CONF}.bak"
${CP} "${MISDN_CONF}" "${MISDN_CONF}.bak" || die "Could not backup your existing ${MISDN_CONF}!"
fi
echo "${HEADER}${MAIN}${NL}${FOOTER}" > ${MISDN_CONF}
}
function print_scan_results
{
local i=0
echo "${#SCAN_card[@]} mISDN compatible device(s) found:"
while [ ! -z "${SCAN_card[${i}]}" ]; do
echo ">> ${SCAN_card[${i}]}"
let "i = ${i} + 1"
done
}
function mk_misdn_dev
{
if [ ! -e /dev/mISDN ]; then
echo "creating device node: /dev/mISDN"
${MKNOD} /dev/mISDN c 46 0
fi
${CHOWN} ${DEVNODE_user}:${DEVNODE_group} /dev/mISDN
${CHMOD} ${DEVNODE_mode} /dev/mISDN
}
#
# MAIN
#
case "${1}" in
start|--start)
check_misdn_conf
parse_config
run_start_commands
mk_misdn_dev
;;
stop|--stop)
run_stop_commands
;;
restart|--restart)
check_misdn_conf
parse_config
run_stop_commands
${SLEEP} 2
run_start_commands
mk_misdn_dev
;;
config|--config)
scan_devices
write_mISDN_conf
;;
scan|--scan)
scan_devices
print_scan_results
;;
help|--help)
echo "${USAGE}"
exit 0
;;
*)
echo "${USAGE}"
exit 2
;;
esac

View File

@ -1,13 +0,0 @@
<?xml version="1.0"?>
<mISDNconf>
<card type="BN8S0">
<port mode="nt" link="ptmp">1</port>
<port mode="nt" link="ptmp">2</port>
<port mode="te" link="ptmp">3</port>
<port mode="te" link="ptmp">4</port>
<port mode="nt" link="ptmp">5</port>
<port mode="nt" link="ptmp">6</port>
<port mode="te" link="ptmp">7</port>
<port mode="te" link="ptmp">8</port>
</card>
</mISDNconf>

View File

@ -1,230 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<!--
Card Type: BN2S0, BN4S0, BN8S0
Ports: 2, 4, 8
Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no), ignore_pcm_frameclock=(yes|no),
rxclock=(yes|no), crystalclock=(yes|no), watchdog=(yes|no)
Port Attributes: mode=(te|nt), link=(ptp|ptmp), master-clock=(yes|no), capi=(yes|no)
-->
<xsl:template name="type-options">
<xsl:param name="force-pcm-slave">no</xsl:param>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@ulaw" />
<xsl:with-param name="val-true">(2**8)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@dtmf" />
<xsl:with-param name="val-true">(2**9)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:choose>
<xsl:when test="$force-pcm-slave='yes'">
<xsl:text>(2**11)</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@pcm_slave" />
<xsl:with-param name="val-true">(2**11)</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@ignore_pcm_frameclock" />
<xsl:with-param name="val-true">(2**12)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@rxclock" />
<xsl:with-param name="val-true">(2**13)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@crystalclock" />
<xsl:with-param name="val-true">(2**18)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@watchdog" />
<xsl:with-param name="val-true">(2**19)</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="BN2S0card">
<xsl:param name="type">4</xsl:param>
<xsl:value-of select="concat(' type:',$type,'+')" />
<xsl:call-template name="type-options" />
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="BN2S0port">
<xsl:text> layermask:</xsl:text>
<xsl:choose>
<xsl:when test="@mode='nt'">
<xsl:text>3</xsl:text>
</xsl:when>
<xsl:when test="@capi='yes'">
<xsl:text>0</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>15</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text> protocol:</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@mode" />
<xsl:with-param name="match-true">te</xsl:with-param>
<xsl:with-param name="match-false">nt</xsl:with-param>
<xsl:with-param name="val-true">34</xsl:with-param>
<xsl:with-param name="val-false">18</xsl:with-param>
<xsl:with-param name="val-default">34</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:if test="@mode!='nt'">
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@link" />
<xsl:with-param name="match-true">ptp</xsl:with-param>
<xsl:with-param name="match-false">ptmp</xsl:with-param>
<xsl:with-param name="val-true">0</xsl:with-param>
<xsl:with-param name="val-false">(-32)</xsl:with-param>
<xsl:with-param name="val-default">(-32)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
</xsl:if>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@master-clock" />
<xsl:with-param name="val-true">(2**16)</xsl:with-param>
</xsl:call-template>
<xsl:text> capi:</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@capi" />
<xsl:with-param name="val-true">yes</xsl:with-param>
<xsl:with-param name="val-false">no</xsl:with-param>
<xsl:with-param name="val-default">no</xsl:with-param>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="BN4S0card">
<xsl:call-template name="BN2S0card">
<xsl:with-param name="type">4</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="BN4S0port">
<xsl:call-template name="BN2S0port" />
</xsl:template>
<xsl:template name="BN8S0card">
<xsl:call-template name="BN2S0card">
<xsl:with-param name="type">8</xsl:with-param>
</xsl:call-template>
</xsl:template>
<xsl:template name="BN8S0port">
<xsl:call-template name="BN2S0port" />
</xsl:template>
<!--
Card Type: BN2E1
Ports: 2
Card Attributes: ulaw=(yes|no), dtmf=(yes|no), pcm_slave=(yes|no), ignore_pcm_frameclock=(yes|no),
rxclock=(yes|no), crystalclock=(yes|no), watchdog=(yes|no)
Port Attributes: mode=(te|nt), link=(ptp|ptmp), optical=(yes|no), los=(yes|no), ais=(yes|no),
slip=(yes|no), nocrc4=(yes|no), capi=(yes|no)
-->
<xsl:template name="BN2E1card">
<xsl:text> type:1+</xsl:text>
<xsl:call-template name="type-options" />
<xsl:text>,1+</xsl:text>
<xsl:call-template name="type-options">
<xsl:with-param name="force-pcm-slave">yes</xsl:with-param>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="BN2E1port">
<xsl:text> layermask:</xsl:text>
<xsl:choose>
<xsl:when test="@mode='nt'">
<xsl:text>3</xsl:text>
</xsl:when>
<xsl:when test="@capi='yes'">
<xsl:text>0</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>15</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text> protocol:</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@mode" />
<xsl:with-param name="match-true">te</xsl:with-param>
<xsl:with-param name="match-false">nt</xsl:with-param>
<xsl:with-param name="val-true">34</xsl:with-param>
<xsl:with-param name="val-false">18</xsl:with-param>
<xsl:with-param name="val-default">34</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:if test="@mode!='nt'">
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@link" />
<xsl:with-param name="match-true">ptp</xsl:with-param>
<xsl:with-param name="match-false">ptmp</xsl:with-param>
<xsl:with-param name="val-true">0</xsl:with-param>
<xsl:with-param name="val-false">(-32)</xsl:with-param>
<xsl:with-param name="val-default">(-32)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
</xsl:if>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@optical" />
<xsl:with-param name="val-true">(2**16)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@los" />
<xsl:with-param name="val-true">(2**18)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@ais" />
<xsl:with-param name="val-true">(2**19)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@slip" />
<xsl:with-param name="val-true">(2**21)</xsl:with-param>
</xsl:call-template>
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@nocrc4" />
<xsl:with-param name="val-true">(2**23)</xsl:with-param>
</xsl:call-template>
<xsl:text> capi:</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@capi" />
<xsl:with-param name="val-true">yes</xsl:with-param>
<xsl:with-param name="val-false">no</xsl:with-param>
<xsl:with-param name="val-default">no</xsl:with-param>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<!--
Module: hfcmulti
Options: poll=<number>, pcm=<number>, debug=<number>, timer=(yes|no)
-->
<xsl:template name="HFCMULTImodule">
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> poll=</xsl:with-param>
<xsl:with-param name="val" select="@poll" />
<xsl:with-param name="val-default">128</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> pcm=</xsl:with-param>
<xsl:with-param name="val" select="@pcm" />
</xsl:call-template>
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> debug=</xsl:with-param>
<xsl:with-param name="val" select="@debug" />
<xsl:with-param name="val-default">0</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="if-set-match">
<xsl:with-param name="prefix"> timer=</xsl:with-param>
<xsl:with-param name="val" select="@timer" />
<xsl:with-param name="val-default">0</xsl:with-param>
<xsl:with-param name="val-true">1</xsl:with-param>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,64 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template name="if-set">
<xsl:param name="prefix"></xsl:param>
<xsl:param name="val"></xsl:param>
<xsl:param name="val-default"></xsl:param>
<xsl:choose>
<xsl:when test="$val!=''">
<xsl:value-of select="concat($prefix,$val)" />
</xsl:when>
<xsl:otherwise>
<xsl:if test="$val-default!=''">
<xsl:value-of select="concat($prefix,$val-default)" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="if-set-match">
<xsl:param name="prefix"></xsl:param>
<xsl:param name="val"></xsl:param>
<xsl:param name="val-default"></xsl:param>
<xsl:param name="val-true">0</xsl:param>
<xsl:param name="val-false">0</xsl:param>
<xsl:param name="match-true">yes</xsl:param>
<xsl:param name="match-false">no</xsl:param>
<xsl:choose>
<xsl:when test="$val=$match-true">
<xsl:value-of select="concat($prefix,$val-true)" />
</xsl:when>
<xsl:when test="$val=$match-false">
<xsl:value-of select="concat($prefix,$val-false)" />
</xsl:when>
<xsl:otherwise>
<xsl:if test="$val-default!=''">
<xsl:value-of select="concat($prefix,$val-default)" />
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="if-match">
<xsl:param name="val">no</xsl:param>
<xsl:param name="val-default">0</xsl:param>
<xsl:param name="val-true">0</xsl:param>
<xsl:param name="val-false">0</xsl:param>
<xsl:param name="match-true">yes</xsl:param>
<xsl:param name="match-false">no</xsl:param>
<xsl:choose>
<xsl:when test="$val=$match-true">
<xsl:value-of select="$val-true" />
</xsl:when>
<xsl:when test="$val=$match-false">
<xsl:value-of select="$val-false" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$val-default" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<!--
Module: mISDN_dsp
Options: debug=<number>, options=<number>, poll=<number>, dtmfthreshold=<number>
-->
<xsl:template name="MISDNDSPmodule">
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> debug=</xsl:with-param>
<xsl:with-param name="val" select="@debug" />
<xsl:with-param name="val-default">0</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> options=</xsl:with-param>
<xsl:with-param name="val" select="@options" />
<xsl:with-param name="val-default">0</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> poll=</xsl:with-param>
<xsl:with-param name="val" select="@poll" />
</xsl:call-template>
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> dtmfthreshold=</xsl:with-param>
<xsl:with-param name="val" select="@dtmfthreshold" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<!--
Card Type: hfcmulti, avmfritz, w6692pci
Ports: 1
Port Attributes: mode=(te|nt), link=(ptp|ptmp), capi=(yes|no)
-->
<xsl:template name="singlepcicard">
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template name="singlepciport">
<xsl:text> layermask:</xsl:text>
<xsl:choose>
<xsl:when test="@mode='nt'">
<xsl:text>3</xsl:text>
</xsl:when>
<xsl:when test="@capi='yes'">
<xsl:text>0</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>15</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:text> protocol:</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@mode" />
<xsl:with-param name="match-true">te</xsl:with-param>
<xsl:with-param name="match-false">nt</xsl:with-param>
<xsl:with-param name="val-true">34</xsl:with-param>
<xsl:with-param name="val-false">18</xsl:with-param>
<xsl:with-param name="val-default">34</xsl:with-param>
</xsl:call-template>
<xsl:if test="@mode!='nt'">
<xsl:text>+</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@link" />
<xsl:with-param name="match-true">ptp</xsl:with-param>
<xsl:with-param name="match-false">ptmp</xsl:with-param>
<xsl:with-param name="val-true">0</xsl:with-param>
<xsl:with-param name="val-false">(-32)</xsl:with-param>
<xsl:with-param name="val-default">(-32)</xsl:with-param>
</xsl:call-template>
</xsl:if>
<xsl:text> capi:</xsl:text>
<xsl:call-template name="if-match">
<xsl:with-param name="val" select="@capi" />
<xsl:with-param name="val-true">yes</xsl:with-param>
<xsl:with-param name="val-false">no</xsl:with-param>
<xsl:with-param name="val-default">no</xsl:with-param>
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,131 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:include href='mISDN.conf.inc.xsl' />
<xsl:include href='mISDN.conf.mISDN_dsp.xsl' />
<xsl:include href='mISDN.conf.hfcmulti.xsl' />
<xsl:include href='mISDN.conf.bnx.xsl' />
<xsl:include href='mISDN.conf.singlepci.xsl' />
<!--
Main mISDNconf Template
-->
<xsl:template match="mISDNconf">
<!-- module -->
<xsl:for-each select="module">
<xsl:choose>
<xsl:when test=".='hfcmulti'">
<xsl:value-of select="concat('MODULE:',.)" />
<xsl:call-template name="HFCMULTImodule" />
</xsl:when>
<xsl:when test=".='mISDN_dsp'">
<xsl:value-of select="concat('MODULE:',.)" />
<xsl:call-template name="MISDNDSPmodule" />
</xsl:when>
</xsl:choose>
</xsl:for-each>
<!-- devnode -->
<xsl:for-each select="devnode">
<xsl:choose>
<xsl:when test=".='mISDN'">
<xsl:value-of select="concat('DEVNODE:',.)" />
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> user:</xsl:with-param>
<xsl:with-param name="val" select="@user" />
<xsl:with-param name="val-default">root</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> group:</xsl:with-param>
<xsl:with-param name="val" select="@group" />
<xsl:with-param name="val-default">root</xsl:with-param>
</xsl:call-template>
<xsl:call-template name="if-set">
<xsl:with-param name="prefix"> mode:</xsl:with-param>
<xsl:with-param name="val" select="@mode" />
<xsl:with-param name="val-default">644</xsl:with-param>
</xsl:call-template>
</xsl:when>
</xsl:choose>
<xsl:text>
</xsl:text>
</xsl:for-each>
<!-- card, port -->
<xsl:for-each select="card">
<xsl:choose>
<xsl:when test="@type='BN2S0'">
<xsl:value-of select="concat('CARD:',@type)" />
<xsl:call-template name="BN2S0card" />
<xsl:for-each select="port">
<xsl:sort data-type="number" />
<xsl:text>PORT:</xsl:text>
<xsl:value-of select="." />
<xsl:call-template name="BN2S0port" />
</xsl:for-each>
</xsl:when>
<xsl:when test="@type='BN4S0'">
<xsl:value-of select="concat('CARD:',@type)" />
<xsl:call-template name="BN4S0card" />
<xsl:for-each select="port">
<xsl:sort data-type="number" />
<xsl:text>PORT:</xsl:text>
<xsl:value-of select="." />
<xsl:call-template name="BN4S0port" />
</xsl:for-each>
</xsl:when>
<xsl:when test="@type='BN8S0'">
<xsl:value-of select="concat('CARD:',@type)" />
<xsl:call-template name="BN8S0card" />
<xsl:for-each select="port">
<xsl:sort data-type="number" />
<xsl:text>PORT:</xsl:text>
<xsl:value-of select="." />
<xsl:call-template name="BN8S0port" />
</xsl:for-each>
</xsl:when>
<xsl:when test="@type='BN2E1'">
<xsl:value-of select="concat('CARD:',@type)" />
<xsl:call-template name="BN2E1card" />
<xsl:for-each select="port">
<xsl:sort data-type="number" />
<xsl:text>PORT:</xsl:text>
<xsl:value-of select="." />
<xsl:call-template name="BN2E1port" />
</xsl:for-each>
</xsl:when>
<xsl:when test="@type='hfcpci' or @type='avmfritz' or @type='w6692pci'">
<xsl:value-of select="concat('CARD:',@type)" />
<xsl:call-template name="singlepcicard" />
<xsl:for-each select="port">
<xsl:sort data-type="number" />
<xsl:text>PORT:</xsl:text>
<xsl:value-of select="." />
<xsl:call-template name="singlepciport" />
</xsl:for-each>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

View File

@ -28,12 +28,6 @@ config MISDN_AVM_FRITZ
help
Enable support for AVM Fritz!Card PCI and PnP.
config MISDN_NETJET
bool "Support for NETJet cards"
depends on PCI
help
Enable support for Traverse Technologies' NETJet PCI cards.
config MISDN_HFCPCI
bool "Support for HFC PCI cards"
depends on PCI
@ -106,7 +100,7 @@ config MISDN_DSP
echo cancelation, tone generation, and Blowfish encryption and
decryption.
It may use hardware features if available.
E.g. it is required for PBX4Linux. Go to http://isdn.eversberg.eu
E.g. it is required for PBX4Linux. Go to http://isdn.jolly.de
and get more informations about this module and it's usage.
If unsure, say 'N'.
@ -118,7 +112,7 @@ config MISDN_LOOP
bchannel data from user space. Applications can directly
access bchannels, so applications can be integrated into DSP
audio processing.
E.g. it is required for PBX4Linux. Go to http://isdn.eversberg.eu
E.g. it is required for PBX4Linux. Go to http://isdn.jolly.de
and get more informations about this module and it's usage.
If unsure, say 'N'.

View File

@ -1,21 +1,15 @@
# Makefile for the modular ISDN driver
#
EXTRA_CFLAGS += -ggdb
# EXTRA_CFLAGS += -S -g
#
ifdef MINCLUDES
CFLAGS += -I$(MINCLUDES) -g
CFLAGS += -I$(MINCLUDES)
endif
ifdef CONFIG_MISDN_MEMDEBUG
EXTRA_CFLAGS += -DMISDN_MEMDEBUG
endif
ifdef CONFIG_MISDN_NETDEV
EXTRA_CFLAGS += -DCONFIG_MISDN_NETDEV
endif
CFLAGS += -DMISDNVERSION=\"$(MISDNVERSION)\"
obj-$(CONFIG_MISDN_DRV) += mISDN_core.o
obj-$(CONFIG_MISDN_DRV) += mISDN_isac.o
obj-$(CONFIG_MISDN_DRV) += mISDN_l1.o
@ -29,10 +23,6 @@ ifdef CONFIG_MISDN_AVM_FRITZ
obj-$(CONFIG_MISDN_DRV) += avmfritz.o
endif
ifdef CONFIG_MISDN_NETJET
obj-$(CONFIG_MISDN_DRV) += netjetpci.o
endif
ifdef CONFIG_MISDN_HFCPCI
obj-$(CONFIG_MISDN_DRV) += hfcpci.o
endif
@ -78,7 +68,6 @@ endif
sedlfax-objs := sedl_fax.o isar.o
avmfritz-objs := avm_fritz.o
netjetpci-objs := netjet.o
hfcpci-objs := hfc_pci.o
hfcsusb-objs := hfcs_usb.o
hfcsmini-objs := hfcs_mini.o
@ -88,12 +77,7 @@ xhfc-objs := xhfc_su.o xhfc_pci2pi.o
mISDN_isac-objs := isac.o arcofi.o
mISDN_core-objs := core.o stack.o udevice.o helper.o debug.o fsm.o \
channel.o l3helper.o \
sysfs_obj.o sysfs_inst.o sysfs_st.o
ifdef CONFIG_MISDN_NETDEV
mISDN_core-objs += netdev.o
endif
sysfs_obj.o sysfs_inst.o sysfs_st.o
ifdef CONFIG_MISDN_MEMDEBUG
mISDN_core-objs += memdbg.o
endif

View File

@ -1,21 +1,15 @@
# Makefile for the modular ISDN driver
#
EXTRA_CFLAGS += -ggdb
# EXTRA_CFLAGS += -S -g
#
ifdef MINCLUDES
CFLAGS += -I$(MINCLUDES) -g
CFLAGS += -I$(MINCLUDES)
endif
ifdef CONFIG_MISDN_MEMDEBUG
EXTRA_CFLAGS += -DMISDN_MEMDEBUG
endif
ifdef CONFIG_MISDN_NETDEV
EXTRA_CFLAGS += -DCONFIG_MISDN_NETDEV
endif
CFLAGS += -DMISDNVERSION=\"$(MISDNVERSION)\"
obj-$(CONFIG_MISDN_DRV) += mISDN_core.o
obj-$(CONFIG_MISDN_DRV) += mISDN_isac.o
obj-$(CONFIG_MISDN_DRV) += mISDN_l1.o
@ -29,10 +23,6 @@ ifdef CONFIG_MISDN_AVM_FRITZ
obj-$(CONFIG_MISDN_DRV) += avmfritz.o
endif
ifdef CONFIG_MISDN_NETJET
obj-$(CONFIG_MISDN_DRV) += netjetpci.o
endif
ifdef CONFIG_MISDN_HFCPCI
obj-$(CONFIG_MISDN_DRV) += hfcpci.o
endif
@ -78,7 +68,6 @@ endif
sedlfax-objs := sedl_fax.o isar.o
avmfritz-objs := avm_fritz.o
netjetpci-objs := netjet.o
hfcpci-objs := hfc_pci.o
hfcsusb-objs := hfcs_usb.o
hfcsmini-objs := hfcs_mini.o
@ -88,12 +77,7 @@ xhfc-objs := xhfc_su.o xhfc_pci2pi.o
mISDN_isac-objs := isac.o arcofi.o
mISDN_core-objs := core.o stack.o udevice.o helper.o debug.o fsm.o \
channel.o l3helper.o \
sysfs_obj.o sysfs_inst.o sysfs_st.o
ifdef CONFIG_MISDN_NETDEV
mISDN_core-objs += netdev.o
endif
sysfs_obj.o sysfs_inst.o sysfs_st.o
ifdef CONFIG_MISDN_MEMDEBUG
mISDN_core-objs += memdbg.o
endif

View File

@ -149,13 +149,13 @@ __u16 AppPlciCheckBprotocol(AppPlci_t *aplci, _cmsg *cmsg)
struct capi_ctr *ctrl = aplci->contr->ctrl;
u_long sprot;
sprot = le32_to_cpu(ctrl->profile.support1);
sprot = ctrl->profile.support1;
if (!test_bit(cmsg->B1protocol, &sprot))
return CapiB1ProtocolNotSupported;
sprot = le32_to_cpu(ctrl->profile.support2);
sprot = ctrl->profile.support2;
if (!test_bit(cmsg->B2protocol, &sprot))
return CapiB2ProtocolNotSupported;
sprot = le32_to_cpu(ctrl->profile.support3);
sprot = ctrl->profile.support3;
if (!test_bit(cmsg->B3protocol, &sprot))
return CapiB3ProtocolNotSupported;
aplci->Bprotocol.B1 = cmsg->B1protocol;
@ -516,7 +516,7 @@ plci_alert_req(struct FsmInst *fi, int event, void *arg)
if (test_and_set_bit(PLCI_STATE_ALERTING, &plci->state)) {
Info = 0x0003; // other app is already alerting
} else {
struct sk_buff *skb = mISDN_alloc_l3msg(260, MT_ALERTING);
struct sk_buff *skb = mISDN_alloc_l3msg(10, MT_ALERTING);
if (!skb) {
int_error();
goto answer;
@ -577,14 +577,12 @@ plci_connect_resp(struct FsmInst *fi, int event, void *arg)
// plciDetachAppPlci(plci, aplci);
if (plci->nAppl == 1) {
int prim;
if (test_bit(PLCI_STATE_ALERTING, &plci->state)) {
if (test_bit(PLCI_STATE_ALERTING, &plci->state))
prim = CC_DISCONNECT | REQUEST;
skb = mISDN_alloc_l3msg(10, MT_DISCONNECT);
} else {
else
// if we already answered, we can't just ignore but must clear actively
prim = CC_RELEASE_COMPLETE | REQUEST;
skb = mISDN_alloc_l3msg(10, MT_RELEASE_COMPLETE);
}
skb = mISDN_alloc_l3msg(10, MT_DISCONNECT);
if (!skb) {
plciL4L3(plci, prim, NULL);
} else {
@ -1567,7 +1565,7 @@ AppPlciLinkUp(AppPlci_t *aplci)
if (aplci->channel == -1) {/* no valid channel set */
int_error();
return -EINVAL;
return(-EINVAL);
}
memset(&pid, 0, sizeof(mISDN_pid_t));
pid.layermask = ISDN_LAYER(1) | ISDN_LAYER(2) | ISDN_LAYER(3) |
@ -1578,59 +1576,47 @@ AppPlciLinkUp(AppPlci_t *aplci)
pid.global = 2; // DCE, answer
if (aplci->Bprotocol.B1 > 23) {
int_errtxt("wrong B1 prot %x", aplci->Bprotocol.B1);
return 0x3001;
return(0x3001);
}
pid.protocol[1] = (1 << aplci->Bprotocol.B1) |
ISDN_PID_LAYER(1) | ISDN_PID_BCHANNEL_BIT;
retval = mISDN_add_pid_parameter(&pid, 1, &aplci->Bprotocol.B1cfg[0]);
if (retval) {/* ressource error */
kfree(pid.pbuf);
return 0x1008;
if (aplci->Bprotocol.B1cfg[0]) {
pid.param[1] = &aplci->Bprotocol.B1cfg[0];
pid.maxplen += aplci->Bprotocol.B1cfg[0];
}
if (aplci->Bprotocol.B2 > 23) {
int_errtxt("wrong B2 prot %x", aplci->Bprotocol.B2);
kfree(pid.pbuf);
return 0x3002;
return(0x3002);
}
pid.protocol[2] = (1 << aplci->Bprotocol.B2) |
ISDN_PID_LAYER(2) | ISDN_PID_BCHANNEL_BIT;
retval = mISDN_add_pid_parameter(&pid, 2, &aplci->Bprotocol.B2cfg[0]);
if (retval) {/* ressource error */
kfree(pid.pbuf);
return 0x1008;
if (aplci->Bprotocol.B2cfg[0]) {
pid.param[2] = &aplci->Bprotocol.B2cfg[0];
pid.maxplen += aplci->Bprotocol.B2cfg[0];
}
/* handle DTMF TODO */
if ((pid.protocol[2] == ISDN_PID_L2_B_TRANS) &&
(pid.protocol[1] == ISDN_PID_L1_B_64TRANS))
pid.protocol[2] = ISDN_PID_L2_B_TRANSDTMF;
if (aplci->Bprotocol.B3 > 23) {
int_errtxt("wrong B3 prot %x", aplci->Bprotocol.B3);
kfree(pid.pbuf);
return 0x3003;
return(0x3003);
}
pid.protocol[3] = (1 << aplci->Bprotocol.B3) |
ISDN_PID_LAYER(3) | ISDN_PID_BCHANNEL_BIT;
retval = mISDN_add_pid_parameter(&pid, 3, &aplci->Bprotocol.B3cfg[0]);
if (retval) {/* ressource error */
kfree(pid.pbuf);
return 0x1008;
if (aplci->Bprotocol.B3cfg[0]) {
pid.param[3] = &aplci->Bprotocol.B3cfg[0];
pid.maxplen += aplci->Bprotocol.B3cfg[0];
}
capidebug(CAPI_DBG_PLCI, "AppPlciLinkUp B1(%x) B2(%x) B3(%x) global(%d) ch(%x)",
pid.protocol[1], pid.protocol[2], pid.protocol[3], pid.global,
pid.protocol[1], pid.protocol[2], pid.protocol[3], pid.global,
aplci->channel);
capidebug(CAPI_DBG_PLCI, "AppPlciLinkUp B1cfg(%d) B2cfg(%d) B3cfg(%d) maxplen(%d)",
aplci->Bprotocol.B1cfg[0], aplci->Bprotocol.B2cfg[0],
aplci->Bprotocol.B3cfg[0], pid.maxplen);
capidebug(CAPI_DBG_PLCI, "AppPlciLinkUp ch(%d) aplci->contr->linklist(%p)",
aplci->channel & 3, aplci->contr->linklist);
pid.protocol[4] = ISDN_PID_L4_B_CAPI20;
aplci->link = ControllerSelChannel(aplci->contr, aplci->channel);
if (!aplci->link) {
int_error();
kfree(pid.pbuf);
return(-EBUSY);
}
capidebug(CAPI_DBG_NCCI, "AppPlciLinkUp aplci->link(%p)", aplci->link);
@ -1648,7 +1634,8 @@ AppPlciLinkUp(AppPlci_t *aplci)
aplci->link->inst.function = PL_l3l4;
else
aplci->link->inst.function = PL_l3l4mux;
retval = mISDN_ctrl(aplci->link->st, MGR_ADDLAYER | REQUEST, &aplci->link->inst);
retval = aplci->link->inst.obj->ctrl(aplci->link->st,
MGR_ADDLAYER | REQUEST, &aplci->link->inst);
if (retval) {
printk(KERN_WARNING "%s MGR_ADDLAYER | REQUEST ret(%d)\n",
__FUNCTION__, retval);
@ -1658,13 +1645,14 @@ AppPlciLinkUp(AppPlci_t *aplci)
stpara.up_headerlen = CAPI_B3_DATA_IND_HEADER_SIZE;
stpara.down_headerlen = 0;
retval = mISDN_ctrl(aplci->link->st, MGR_ADDSTPARA | REQUEST, &stpara);
retval = aplci->link->inst.obj->ctrl(aplci->link->st,
MGR_ADDSTPARA | REQUEST, &stpara);
if (retval) {
printk(KERN_WARNING "%s MGR_SETSTACK | REQUEST ret(%d)\n",
__FUNCTION__, retval);
}
retval = mISDN_ctrl(aplci->link->st, MGR_SETSTACK | REQUEST, &pid);
kfree(pid.pbuf);
retval = aplci->link->inst.obj->ctrl(aplci->link->st,
MGR_SETSTACK | REQUEST, &pid);
if (retval) {
printk(KERN_WARNING "%s MGR_SETSTACK | REQUEST ret(%d)\n",
__FUNCTION__, retval);
@ -1683,7 +1671,8 @@ ReleaseLink(AppPlci_t *aplci)
if (ncci->ncci_m.state != ST_NCCI_N_0)
ncciL4L3(ncci, DL_RELEASE | REQUEST, 0, 0, NULL, NULL);
#endif
retval = mISDN_ctrl(aplci->link->inst.st, MGR_CLEARSTACK | REQUEST, NULL);
retval = aplci->link->inst.obj->ctrl(aplci->link->inst.st,
MGR_CLEARSTACK | REQUEST, NULL);
if (retval)
int_error();
aplci->link = NULL;
@ -2188,7 +2177,7 @@ AppPlciClearOtherApps(AppPlci_t *aplci)
_cmsg *cm;
struct list_head *item, *next;
if (!aplci->plci)
if (aplci->plci)
return;
if (aplci->plci->nAppl <= 1)
return;

View File

@ -192,7 +192,7 @@ ParseRejectComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
int
ParseUnknownComponent(struct asn1_parm *pc, u_char *p, u_char *end, int dummy)
{
//int invokeId;
int invokeId;
INIT;
pc->comp = tag;

View File

@ -8,6 +8,7 @@
* This file is (c) under GNU PUBLIC LICENSE
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#ifdef NEW_ISAPNP
@ -16,7 +17,6 @@
#include <linux/isapnp.h>
#endif
#include <linux/delay.h>
#include "core.h"
#include "channel.h"
#include "isac.h"
#include "layer1.h"
@ -103,17 +103,17 @@ enum {
struct hdlc_stat_reg {
#ifdef __BIG_ENDIAN
u_char fill;
u_char mode;
u_char xml;
u_char cmd;
u_char fill __attribute__((packed));
u_char mode __attribute__((packed));
u_char xml __attribute__((packed));
u_char cmd __attribute__((packed));
#else
u_char cmd;
u_char xml;
u_char mode;
u_char fill;
u_char cmd __attribute__((packed));
u_char xml __attribute__((packed));
u_char mode __attribute__((packed));
u_char fill __attribute__((packed));
#endif
} __attribute__((packed));
};
typedef struct hdlc_hw {
union {
@ -804,8 +804,7 @@ hdlc_down(mISDNinstance_t *inst, struct sk_buff *skb)
spin_unlock_irqrestore(inst->hwlock, flags);
skb_trim(skb, 0);
if (hh->prim != (PH_CONTROL | REQUEST))
if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb))
return(0);
ret = mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb);
} else {
printk(KERN_WARNING "hdlc_down unknown prim(%x)\n", hh->prim);
ret = -EINVAL;
@ -933,6 +932,7 @@ static int init_card(fritzpnppci *fc)
}
#define MAX_CARDS 4
#define MODULE_PARM_T "1-4i"
static int fritz_cnt;
static u_int protocol[MAX_CARDS];
static int layermask[MAX_CARDS];
@ -945,25 +945,9 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#define MODULE_PARM_T "1-4i"
MODULE_PARM(protocol, MODULE_PARM_T);
MODULE_PARM(layermask, MODULE_PARM_T);
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#ifdef OLD_MODULE_PARAM_ARRAY
static int num_protocol=0,num_layermask=0;
module_param_array(protocol, uint, num_protocol, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, num_layermask, S_IRUGO | S_IWUSR);
#else
module_param_array(protocol, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, NULL, S_IRUGO | S_IWUSR);
#endif
#endif
#endif
int
@ -1052,7 +1036,7 @@ release_card(fritzpnppci *card)
mISDN_freechannel(&card->bch[0]);
mISDN_freechannel(&card->dch);
spin_unlock_irqrestore(&card->lock, flags);
mISDN_ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
fritz.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
spin_lock_irqsave(&fritz.lock, flags);
list_del(&card->list);
spin_unlock_irqrestore(&fritz.lock, flags);
@ -1126,7 +1110,7 @@ fritz_manager(void *data, u_int prim, void *arg) {
}
} else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
fritz.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
arg = NULL;
@ -1222,31 +1206,31 @@ static int __devinit setup_instance(fritzpnppci *card)
return(err);
}
fritz_cnt++;
err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
err = fritz.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
if (err) {
release_card(card);
return(err);
}
for (i=0; i<2; i++) {
err = mISDN_ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
err = fritz.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
if (err) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
}
err = mISDN_ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
err = fritz.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
if (err) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
err = init_card(card);
if (err) {
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
mISDN_ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
fritz.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
printk(KERN_INFO "fritz %d cards installed\n", fritz_cnt);
return(0);
}
@ -1331,7 +1315,7 @@ static void __devexit fritz_remove_pci(struct pci_dev *pdev)
fritzpnppci *card = pci_get_drvdata(pdev);
if (card)
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
else
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
}
@ -1346,7 +1330,7 @@ static void __devexit fritz_remove_pnp(struct pci_dev *pdev)
fritzpnppci *card = pnp_get_drvdata(pdev);
if (card)
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
fritz.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
else
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
}
@ -1440,9 +1424,6 @@ static int __init Fritz_init(void)
}
#endif
#endif
mISDN_module_register(THIS_MODULE);
return 0;
#if !defined(CONFIG_HOTPLUG) || defined(MODULE)
@ -1466,8 +1447,6 @@ static void __exit Fritz_cleanup(void)
fritzpnppci *card, *next;
int err;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&fritz))) {
printk(KERN_ERR "Can't unregister Fritz PCI error(%d)\n", err);
}

View File

@ -3,7 +3,6 @@
*/
#include <linux/module.h>
#include "core.h"
#include "m_capi.h"
#include "helper.h"
#include "debug.h"
@ -20,11 +19,7 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#endif
#endif
static char deb_buf[256];
@ -381,7 +376,7 @@ capi20_manager(void *data, u_int prim, void *arg) {
case MGR_UNREGLAYER | REQUEST:
if (plink) {
plink->inst.function = NULL;
mISDN_ctrl(&plink->inst, MGR_UNREGLAYER | REQUEST, NULL);
capi_obj.ctrl(&plink->inst, MGR_UNREGLAYER | REQUEST, NULL);
}
break;
case MGR_CTRLREADY | INDICATION:
@ -424,8 +419,7 @@ int Capi20Init(void)
free_AppPlci();
free_ncci();
free_Application();
} else
mISDN_module_register(THIS_MODULE);
}
return(err);
}
@ -435,8 +429,6 @@ static void Capi20cleanup(void)
int err;
Controller_t *contr, *next;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&capi_obj))) {
printk(KERN_ERR "Can't unregister CAPI20 error(%d)\n", err);
}

View File

@ -17,9 +17,6 @@
#ifdef MISDN_MEMDEBUG
#include "memdbg.h"
#endif
#ifdef CONFIG_MISDN_NETDEV
#include "core.h"
#endif
#define MAX_DFRAME_LEN_L1 300
#define MAX_MON_FRAME 32
@ -104,14 +101,10 @@ queue_ch_frame(channel_t *ch, u_int pr, int dinfo, struct sk_buff *skb)
int err;
pr |= test_bit(FLG_L2DATA, &ch->Flags) ? DL_DATA : PH_DATA;
if (!skb) {
if (!skb)
err = mISDN_queue_data(&ch->inst, FLG_MSG_UP, pr, dinfo, 0, NULL, ch->up_headerlen);
} else {
#ifdef CONFIG_MISDN_NETDEV
misdn_log_frame(ch->inst.st, skb->data, skb->len, FLG_MSG_UP);
#endif
else
err = mISDN_queueup_newhead(&ch->inst, 0, pr, dinfo, skb);
}
if (unlikely(err)) {
int_errtxt("err=%d", err);
if (skb)
@ -135,26 +128,18 @@ channel_senddata(channel_t *ch, int di, struct sk_buff *skb)
}
/* check for pending next_skb */
if (ch->next_skb) {
#ifdef DEBUG_NEXT_SKB_EXISTS
printk(KERN_WARNING "%s: next_skb exist ERROR (skb->len=%d next_skb->len=%d)\n",
__FUNCTION__, skb->len, ch->next_skb->len);
#endif
return(-EBUSY);
}
if (test_and_set_bit(FLG_TX_BUSY, &ch->Flags)) {
test_and_set_bit(FLG_TX_NEXT, &ch->Flags);
#ifdef CONFIG_MISDN_NETDEV
misdn_log_frame(ch->inst.st, skb->data, skb->len, FLG_MSG_DOWN);
#endif
ch->next_skb = skb;
return(0);
} else {
/* write to fifo */
ch->tx_skb = skb;
ch->tx_idx = 0;
#ifdef CONFIG_MISDN_NETDEV
misdn_log_frame(ch->inst.st, skb->data, skb->len, FLG_MSG_DOWN);
#endif
queue_ch_frame(ch, CONFIRM, di, NULL);
return(skb->len);
}

View File

@ -60,10 +60,12 @@ ControllerDestr(Controller_t *contr)
contr->ctrl = NULL;
#ifdef FIXME
if (inst->up.peer) {
mISDN_ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
inst->up.peer->obj->ctrl(inst->up.peer,
MGR_DISCONNECT | REQUEST, &inst->up);
}
if (inst->down.peer) {
mISDN_ctrl(inst->down.peer, MGR_DISCONNECT | REQUEST, &inst->down);
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
#endif
list_for_each_safe(item, next, &contr->linklist) {
@ -72,8 +74,8 @@ ControllerDestr(Controller_t *contr)
kfree(plink);
}
if (contr->entity != MISDN_ENTITY_NONE)
mISDN_ctrl(inst, MGR_DELENTITY | REQUEST, (void *)((u_long)contr->entity));
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST, (void *)((u_long)contr->entity));
inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
list_del(&contr->list);
spin_unlock_irqrestore(&contr->list_lock, flags);
kfree(contr);
@ -95,12 +97,12 @@ ControllerRun(Controller_t *contr)
contr->ctrl->version.majormanuversion = 1;
contr->ctrl->version.minormanuversion = 0;
memset(&contr->ctrl->profile, 0, sizeof(struct capi_profile));
contr->ctrl->profile.ncontroller = cpu_to_le16(1);
contr->ctrl->profile.nbchannel = cpu_to_le16(contr->nr_bc);
contr->ctrl->profile.ncontroller = 1;
contr->ctrl->profile.nbchannel = contr->nr_bc;
contrDebug(contr, CAPI_DBG_INFO, "%s: %s version(%s)",
__FUNCTION__, contr->ctrl->manu, contr->ctrl->serial);
// FIXME
ret = mISDN_ctrl(contr->inst.st, MGR_GLOBALOPT | REQUEST, &contr->ctrl->profile.goptions);
ret = contr->inst.obj->ctrl(contr->inst.st, MGR_GLOBALOPT | REQUEST, &contr->ctrl->profile.goptions);
if (ret) {
/* Fallback on error, minimum set */
contr->ctrl->profile.goptions = GLOBALOPT_INTERNAL_CTRL;
@ -121,7 +123,7 @@ ControllerRun(Controller_t *contr)
ret = -EINVAL;
} else {
plink = list_entry(contr->linklist.next, PLInst_t, list);
ret = mISDN_ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
ret = plink->inst.obj->ctrl(plink->st, MGR_EVALSTACK | REQUEST, &pidmask);
}
if (ret) {
/* Fallback on error, minimum set */
@ -137,11 +139,7 @@ ControllerRun(Controller_t *contr)
}
contrDebug(contr, CAPI_DBG_INFO, "%s: GLOBAL(%08X) B1(%08X) B2(%08X) B3(%08X)",
__FUNCTION__, contr->ctrl->profile.goptions, contr->ctrl->profile.support1,
contr->ctrl->profile.support2, contr->ctrl->profile.support3);
cpu_to_le32s(&contr->ctrl->profile.goptions);
cpu_to_le32s(&contr->ctrl->profile.support1);
cpu_to_le32s(&contr->ctrl->profile.support2);
cpu_to_le32s(&contr->ctrl->profile.support3);
contr->ctrl->profile.support2, contr->ctrl->profile.support2);
#ifdef OLDCAPI_DRIVER_INTERFACE
contr->ctrl->ready(contr->ctrl);
#else
@ -347,7 +345,7 @@ LoadFirmware(struct capi_ctr *ctrl, capiloaddata *data)
}
} else
firm.data = data;
mISDN_ctrl(contr->inst.st, MGR_LOADFIRM | REQUEST, &firm);
contr->inst.obj->ctrl(contr->inst.st, MGR_LOADFIRM | REQUEST, &firm);
if (data->firmware.user)
vfree(firm.data);
return(0);
@ -693,7 +691,7 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
list_add_tail(&contr->list, &ocapi->ilist);
spin_unlock_irqrestore(&ocapi->lock, flags);
contr->entity = MISDN_ENTITY_NONE;
retval = mISDN_ctrl(&contr->inst, MGR_NEWENTITY | REQUEST, NULL);
retval = ocapi->ctrl(&contr->inst, MGR_NEWENTITY | REQUEST, NULL);
if (retval) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%d)\n",
__FUNCTION__, retval);
@ -727,7 +725,7 @@ ControllerConstr(Controller_t **contr_p, mISDNstack_t *st, mISDN_pid_t *pid, mIS
contr->addr, contr->ctrl->cnr, st->id);
contr->addr = contr->ctrl->cnr;
plciInit(contr);
mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &contr->inst);
ocapi->ctrl(st, MGR_REGLAYER | INDICATION, &contr->inst);
// contr->inst.up.stat = IF_DOWN;
*contr_p = contr;
} else {
@ -750,7 +748,7 @@ ControllerSelChannel(Controller_t *contr, u_int channel)
}
ci.channel = channel;
ci.st.p = NULL;
ret = mISDN_ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST, &ci);
ret = contr->inst.obj->ctrl(contr->inst.st, MGR_SELCHANNEL | REQUEST, &ci);
if (ret) {
int_errtxt("MGR_SELCHANNEL ret(%d)", ret);
return(NULL);

View File

@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include "core.h"
@ -19,18 +20,10 @@
#endif
static char *mISDN_core_revision = "$Revision$";
static char *mISDN_core_version = MISDNVERSION ;
LIST_HEAD(mISDN_objectlist);
static rwlock_t mISDN_objects_lock = RW_LOCK_UNLOCKED;
LIST_HEAD(mISDN_modulelist);
static rwlock_t mISDN_modules_lock = RW_LOCK_UNLOCKED;
struct modulelist {
struct list_head list;
struct module *module;
};
int core_debug;
static u_char entityarray[MISDN_MAX_ENTITY/8];
@ -44,11 +37,7 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#else
module_param (debug, uint, S_IRUGO | S_IWUSR);
#endif
MODULE_PARM_DESC (debug, "mISDN core debug mask");
#endif
@ -96,7 +85,7 @@ mISDNd(void *data)
#ifdef CONFIG_SMP
unlock_kernel();
#endif
printk(KERN_DEBUG "mISDNd: kernel daemon started (current:%p)\n", current);
printk(KERN_DEBUG "mISDNd: kernel daemon started\n");
test_and_set_bit(mISDN_TFLAGS_STARTED, &hkt->Flags);
@ -154,7 +143,7 @@ mISDNd(void *data)
printk(KERN_DEBUG "mISDNd: test event done\n");
}
printk(KERN_DEBUG "mISDNd: daemon exit now (current:%p)\n", current);
printk(KERN_DEBUG "mISDNd: daemon exit now\n");
test_and_clear_bit(mISDN_TFLAGS_STARTED, &hkt->Flags);
test_and_clear_bit(mISDN_TFLAGS_ACTIV, &hkt->Flags);
discard_queue(&hkt->workq);
@ -422,6 +411,8 @@ mgr_queue(void *data, u_int prim, struct sk_buff *skb)
#endif
static int central_manager(void *, u_int, void *);
static int
set_stack_req(mISDNstack_t *st, mISDN_pid_t *pid)
{
@ -443,7 +434,7 @@ set_stack_req(mISDNstack_t *st, mISDN_pid_t *pid)
err = copy_pid(npid, pid, pbuf);
if (err) // FIXME error handling
int_errtxt("copy_pid error %d", err);
hhe->func.ctrl = mISDN_ctrl;
hhe->func.ctrl = central_manager;
skb_queue_tail(&mISDN_thread.workq, skb);
wake_up_interruptible(&mISDN_thread.waitq);
return(0);
@ -521,8 +512,7 @@ new_entity(mISDNinstance_t *inst)
return(ret);
}
int
mISDN_ctrl(void *data, u_int prim, void *arg) {
static int central_manager(void *data, u_int prim, void *arg) {
mISDNstack_t *st = data;
switch(prim) {
@ -566,9 +556,6 @@ mISDN_ctrl(void *data, u_int prim, void *arg) {
return(preregister_layer(st, arg));
case MGR_SETSTACK | REQUEST:
/* can sleep in case of module reload */
#ifdef CONFIG_MISDN_NETDEV
misdn_netdev_addstack(st);
#endif
return(set_stack_req(st, arg));
case MGR_SETSTACK_NW | REQUEST:
return(set_stack(st, arg));
@ -612,62 +599,6 @@ mISDN_ctrl(void *data, u_int prim, void *arg) {
return(-EINVAL);
}
void
mISDN_module_register(struct module *module)
{
struct modulelist *ml = kmalloc(sizeof(struct modulelist), GFP_KERNEL);
if (!ml) {
printk(KERN_DEBUG "mISDN_register_module: kmalloc failed!\n");
return;
}
ml->module = module;
write_lock(&mISDN_modules_lock);
list_add(&ml->list, &mISDN_modulelist);
write_unlock(&mISDN_modules_lock);
printk(KERN_DEBUG "mISDN_register_module(%p)\n", module);
}
void
mISDN_module_unregister(struct module *module)
{
struct modulelist *ml, *mi;
write_lock(&mISDN_modules_lock);
list_for_each_entry_safe(ml, mi, &mISDN_modulelist, list)
if (ml->module == module) {
list_del(&ml->list);
kfree(ml);
write_unlock(&mISDN_modules_lock);
printk(KERN_DEBUG "mISDN_unregister_module(%p)\n", module);
return;
}
write_unlock(&mISDN_modules_lock);
}
void
mISDN_inc_usage(void)
{
struct modulelist *ml;
read_lock(&mISDN_modules_lock);
list_for_each_entry(ml, &mISDN_modulelist, list)
try_module_get(ml->module);
read_unlock(&mISDN_modules_lock);
}
void
mISDN_dec_usage(void)
{
struct modulelist *ml;
read_lock(&mISDN_modules_lock);
list_for_each_entry(ml, &mISDN_modulelist, list)
module_put(ml->module);
read_unlock(&mISDN_modules_lock);
}
int mISDN_register(mISDNobject_t *obj) {
u_long flags;
int retval;
@ -678,6 +609,7 @@ int mISDN_register(mISDNobject_t *obj) {
obj->id = obj_id++;
list_add_tail(&obj->list, &mISDN_objectlist);
write_unlock_irqrestore(&mISDN_objects_lock, flags);
obj->ctrl = central_manager;
// register_prop
if (debug)
printk(KERN_DEBUG "mISDN_register %s id %x\n", obj->name,
@ -709,7 +641,6 @@ int mISDN_unregister(mISDNobject_t *obj) {
write_lock_irqsave(&mISDN_objects_lock, flags);
list_del(&obj->list);
write_unlock_irqrestore(&mISDN_objects_lock, flags);
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "mISDN_unregister: mISDN_objectlist(%p<-%p->%p)\n",
mISDN_objectlist.prev, &mISDN_objectlist, mISDN_objectlist.next);
@ -723,7 +654,7 @@ mISDNInit(void)
DECLARE_MUTEX_LOCKED(sem);
int err;
printk(KERN_INFO "Modular ISDN Stack core version (%s) revision (%s)\n", mISDN_core_version, mISDN_core_revision);
printk(KERN_INFO "Modular ISDN Stack core %s\n", mISDN_core_revision);
core_debug = debug;
#ifdef MISDN_MEMDEBUG
err = __mid_init();
@ -738,10 +669,6 @@ mISDNInit(void)
if (err)
goto dev_fail;
#ifdef CONFIG_MISDN_NETDEV
misdn_netdev_init();
#endif
init_waitqueue_head(&mISDN_thread.waitq);
skb_queue_head_init(&mISDN_thread.workq);
mISDN_thread.notify = &sem;
@ -780,12 +707,6 @@ void mISDN_cleanup(void) {
#ifdef MISDN_MEMDEBUG
__mid_cleanup();
#endif
#ifdef CONFIG_MISDN_NETDEV
misdn_netdev_exit();
#endif
mISDN_sysfs_cleanup();
printk(KERN_DEBUG "mISDNcore unloaded\n");
}
@ -793,13 +714,5 @@ void mISDN_cleanup(void) {
module_init(mISDNInit);
module_exit(mISDN_cleanup);
EXPORT_SYMBOL(mISDN_module_register);
EXPORT_SYMBOL(mISDN_module_unregister);
EXPORT_SYMBOL(mISDN_inc_usage);
EXPORT_SYMBOL(mISDN_dec_usage);
EXPORT_SYMBOL(mISDN_ctrl);
EXPORT_SYMBOL(mISDN_register);
EXPORT_SYMBOL(mISDN_unregister);
#ifdef CONFIG_MISDN_NETDEV
EXPORT_SYMBOL(misdn_log_frame);
#endif

View File

@ -28,17 +28,16 @@
#define DEBUG_DEV_TIMER 0x0400
#define DEBUG_RDATA 0x1000
#define DEBUG_WDATA 0x2000
#define DEBUG_SYSFS 0x4000
#define DEBUG_THREADS 0x8000
/* from udevice.c */
extern int init_mISDNdev(int);
extern int free_mISDNdev(void);
extern mISDNdevice_t *get_free_rawdevice(void);
extern int free_device(mISDNdevice_t *dev);
/* from stack.c */
extern void get_stack_info(struct sk_buff *);
extern int get_stack_cnt(void);
extern void check_stacklist(void);
@ -85,23 +84,3 @@ extern mISDNobject_t *get_object(int);
extern mISDNinstance_t *get_instance4id(u_int);
extern int mISDN_alloc_entity(int *);
extern int mISDN_delete_entity(int);
extern void mISDN_module_register(struct module *);
extern void mISDN_module_unregister(struct module *);
extern void mISDN_inc_usage(void);
extern void mISDN_dec_usage(void);
#ifdef CONFIG_MISDN_NETDEV
/* from netdev_main.c */
void misdn_log_frame(mISDNstack_t *, /* Stack for which to log */
unsigned char *, /* frame to log */
int, /* frame len */
int ); /* direction (0=rx,1=tx) */
int misdn_netdev_addstack(mISDNstack_t *); /* create new netdevice by
stack */
int misdn_netdev_init(void); /* initialize netdevices */
void misdn_netdev_exit(void); /* exit netdeivces */
#endif

View File

@ -47,7 +47,7 @@ mISDN_debugprint(mISDNinstance_t *inst, char *fmt, ...)
va_start(log.args, fmt);
log.head = inst->name;
log.fmt = fmt;
mISDN_ctrl(inst, MGR_DEBUGDATA | REQUEST, &log);
inst->obj->ctrl(inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}

View File

@ -2,7 +2,7 @@
*
* Audio support data for ISDN4Linux.
*
* Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu)
* Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
@ -29,7 +29,6 @@
#define FEAT_STATE_INIT 1
#define FEAT_STATE_WAIT 2
#define FEAT_STATE_RECEIVED 3
#include <linux/timer.h>
@ -45,20 +44,10 @@
* out the other.
*/
//#define AGGRESSIVE_SUPPRESSOR
//#include "dsp_mec2.h"
//#include "dsp_kb1ec.h"
#include "dsp_mg2ec.h"
/*
* uncomment this one to cancel echo more aggressive
*/
//#define AGGRESSIVE_SUPPRESSOR
extern int dsp_options;
extern int dsp_debug;
extern int dsp_poll;
@ -137,7 +126,6 @@ extern mISDNobject_t dsp_obj;
#define ECHOCAN_BUFLEN 4*128
typedef struct _dtmf_t {
int treshold; /* above this is dtmf (square of) */
int software; /* dtmf uses software decoding */
int hardware; /* dtmf uses hardware decoding */
int size; /* number of bytes in buffer */
@ -178,7 +166,6 @@ struct dsp_features {
int hfc_id; /* unique id to identify the chip (or -1) */
int hfc_dtmf; /* set if HFCmulti card supports dtmf */
int hfc_loops; /* set if card supports tone loops */
int hfc_echocanhw; /* set if card supports echocancelation*/
int pcm_id; /* unique id to identify the pcm bus (or -1) */
int pcm_slots; /* number of slots on the pcm bus */
int pcm_banks; /* number of IO banks of pcm bus */
@ -194,7 +181,6 @@ typedef struct _dsp {
int tx_mix;
tone_t tone;
dtmf_t dtmf;
int queue_dtmf; /* flags enabled dtmf, prior feature reply */
int tx_volume, rx_volume;
/* conference stuff */
@ -202,9 +188,6 @@ typedef struct _dsp {
conference_t *conf;
conf_member_t *member;
/* while we're waiting for the hw */
u32 queue_conf_id; /* stores conf id prior feature reply */
/* buffer stuff */
int rx_W; /* current write pos for data without timestamp */
int rx_R; /* current read pos for transmit clock */
@ -217,8 +200,6 @@ typedef struct _dsp {
/* hardware stuff */
struct dsp_features features; /* features */
struct timer_list feature_tl;
spinlock_t feature_lock;
int feature_state;
int pcm_slot_rx; /* current PCM slot (or -1) */
int pcm_bank_rx;
@ -240,9 +221,7 @@ typedef struct _dsp {
int bf_sync;
/* echo cancellation stuff */
int queue_cancel[3]; /* stores cancel values prior feature reply */
int cancel_enable;
int cancel_hardware; /*we are using hw echo canc*/
struct echo_can_state * ec; /**< == NULL: echo cancellation disabled;
!= NULL: echo cancellation enabled */

View File

@ -2,7 +2,7 @@
*
* Audio support data for mISDN_dsp.
*
* Copyright 2002/2003 by Andreas Eversberg (jolly@eversberg.eu)
* Copyright 2002/2003 by Andreas Eversberg (jolly@jolly.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.

View File

@ -2,7 +2,7 @@
*
* Blowfish encryption/decryption for mISDN_dsp.
*
* Copyright Andreas Eversberg (jolly@eversberg.eu)
* Copyright Andreas Eversberg (jolly@jolly.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.

View File

@ -13,12 +13,7 @@
#include "helper.h"
#include "debug.h"
#include "dsp.h"
#ifdef ARCH_I386
#include <asm/i387.h>
#else
#define kernel_fpu_begin()
#define kernel_fpu_end()
#endif
/*
@ -27,27 +22,6 @@
*
*
*/
/*
* send HW message to hfc card
*/
static void
dsp_cancel_hw_message(dsp_t *dsp, u32 message, u32 param)
{
struct sk_buff *nskb;
nskb = create_link_skb(PH_CONTROL | REQUEST, message, sizeof(param), &param, 0);
if (!nskb) {
printk(KERN_ERR "%s: No mem for skb.\n", __FUNCTION__);
return;
}
/* unlocking is not required, because we don't expect a response */
if (mISDN_queue_down(&dsp->inst, 0, nskb))
dev_kfree_skb(nskb);
}
void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size);
int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int train);
void bchdev_echocancel_deactivate(dsp_t* dev);
@ -110,47 +84,28 @@ dsp_cancel_init(dsp_t *dsp, int deftaps, int training, int delay)
{
if (!dsp) return -1;
if (dsp->feature_state != FEAT_STATE_RECEIVED) {
dsp->queue_cancel[0]=deftaps;
dsp->queue_cancel[1]=training;
dsp->queue_cancel[2]=delay;
return 0;
}
//printk("DSP_CANCEL_INIT called\n");
printk("DSP_CANCEL_INIT called\n");
if (delay < 0)
{
//printk(KERN_NOTICE "Disabling EC\n");
printk("Disabling EC\n");
dsp->cancel_enable = 0;
dsp->txbuflen=0;
if (dsp->features.hfc_echocanhw) {
//printk(KERN_NOTICE "Disabling Hardware EC\n");
dsp_cancel_hw_message(dsp, HW_ECHOCAN_OFF, deftaps);
} else {
bchdev_echocancel_deactivate(dsp);
}
bchdev_echocancel_deactivate(dsp);
return(0);
}
if (dsp->features.hfc_echocanhw) {
//printk(KERN_NOTICE "Using Hardware EC taps [%d]\n",deftaps);
dsp_cancel_hw_message(dsp, HW_ECHOCAN_ON, deftaps);
return 0;
}
dsp->txbuflen=0;
dsp->rxbuflen=0;
bchdev_echocancel_activate(dsp,deftaps, training);
//printk("Enabling EC\n");
printk("Enabling EC\n");
dsp->cancel_enable = 1;
return(0);
}
@ -202,13 +157,11 @@ char* bchdev_echocancel_statestr(uint16_t state)
/** Changes state of echo cancellation to given state */
void bchdev_echocancel_setstate(dsp_t* dev, uint16_t state)
{
#if 0
char* statestr = bchdev_echocancel_statestr(state);
printk("bchdev: echo cancel state %d (%s)\n", state & 0xff, statestr);
if (state == ECHO_STATE_ACTIVE)
printk("bchdev: %d taps trained\n", dev->echolastupdate);
#endif
dev->echostate = state;
}
@ -262,14 +215,14 @@ int bchdev_echocancel_activate(dsp_t* dev, int deftaps, int training)
}
if (!dev->ecdis_rd) dev->ecdis_rd = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_ATOMIC);
if (!dev->ecdis_rd) dev->ecdis_rd = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL);
if (!dev->ecdis_rd) {
kfree(dev->ec); dev->ec = NULL;
return -ENOMEM;
}
echo_can_disable_detector_init(dev->ecdis_rd);
if (!dev->ecdis_wr) dev->ecdis_wr = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_ATOMIC);
if (!dev->ecdis_wr) dev->ecdis_wr = kmalloc(sizeof(echo_can_disable_detector_state_t), GFP_KERNEL);
if (!dev->ecdis_wr) {
kfree(dev->ec); dev->ec = NULL;
kfree(dev->ecdis_rd); dev->ecdis_rd = NULL;
@ -302,48 +255,62 @@ void bchdev_echocancel_deactivate(dsp_t* dev)
}
/** Processes one TX- and one RX-packet with echocancellation */
void bchdev_echocancel_chunk(dsp_t* ss, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size)
void bchdev_echocancel_chunk(dsp_t* dev, uint8_t *rxchunk, uint8_t *txchunk, uint16_t size)
{
int16_t rxlin, txlin;
uint16_t x;
uint16_t pos;
/* Perform echo cancellation on a chunk if requested */
if (ss->ec) {
if (ss->echostate & __ECHO_STATE_MUTE) {
/* Special stuff for training the echo can */
for (x=0;x<size;x++) {
rxlin = dsp_audio_law_to_s32[rxchunk[x]];
txlin = dsp_audio_law_to_s32[txchunk[x]];
if (ss->echostate == ECHO_STATE_PRETRAINING) {
if (--ss->echotimer <= 0) {
ss->echotimer = 0;
ss->echostate = ECHO_STATE_STARTTRAINING;
}
}
if ((ss->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
ss->echolastupdate = 0;
ss->echostate = ECHO_STATE_TRAINING;
}
if (ss->echostate == ECHO_STATE_TRAINING) {
if (echo_can_traintap(ss->ec, ss->echolastupdate++, rxlin)) {
#if 0
printk("Finished training (%d taps trained)!\n", ss->echolastupdate);
#endif
ss->echostate = ECHO_STATE_ACTIVE;
}
}
rxlin = 0;
rxchunk[x] = dsp_audio_s16_to_law[(int)rxlin];
}
} else {
for (x=0;x<size;x++) {
rxlin = dsp_audio_law_to_s32[rxchunk[x]&0xff];
txlin = dsp_audio_law_to_s32[txchunk[x]&0xff];
rxlin = echo_can_update(ss->ec, txlin, rxlin);
rxchunk[x] = dsp_audio_s16_to_law[rxlin &0xffff];
}
if (dev->ec) {
if (dev->echostate & __ECHO_STATE_MUTE) {
if (dev->echostate == ECHO_STATE_STARTTRAINING) {
// Transmit impulse now
txchunk[0] = dsp_audio_s16_to_law[16384 & 0xffff];
memset(txchunk+1, 0, size-1);
bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING); //AWAITINGECHO);
} else {
// train the echo cancellation
for (pos = 0; pos < size; pos++) {
rxlin = dsp_audio_law_to_s32[rxchunk[pos]];
txlin = dsp_audio_law_to_s32[txchunk[pos]];
if (dev->echostate == ECHO_STATE_PRETRAINING) {
if (dev->echotimer <= 0) {
dev->echotimer = 0;
bchdev_echocancel_setstate(dev, ECHO_STATE_STARTTRAINING);
} else {
dev->echotimer--;
}
}
if ((dev->echostate == ECHO_STATE_AWAITINGECHO) && (txlin > 8000)) {
dev->echolastupdate = 0;
bchdev_echocancel_setstate(dev, ECHO_STATE_TRAINING);
}
if (dev->echostate == ECHO_STATE_TRAINING) {
if (echo_can_traintap(dev->ec, dev->echolastupdate++, rxlin)) {
bchdev_echocancel_setstate(dev, ECHO_STATE_ACTIVE);
}
}
rxchunk[pos] = dsp_silence;
txchunk[pos] = dsp_silence;
}
}
} else {
for (pos = 0; pos < size; pos++) {
rxlin = dsp_audio_law_to_s32[rxchunk[pos]];
txlin = dsp_audio_law_to_s32[txchunk[pos]];
if (echo_can_disable_detector_update(dev->ecdis_rd, rxlin) ||
echo_can_disable_detector_update(dev->ecdis_wr, txlin)) {
bchdev_echocancel_deactivate(dev);
printk("EC: Disable tone detected\n");
return ;
} else {
rxlin = echo_can_update(dev->ec, txlin, rxlin);
rxchunk[pos] = dsp_audio_s16_to_law[rxlin & 0xffff];
}
}
}
}
}

View File

@ -2,7 +2,7 @@
*
* Audio crossconnecting/conferrencing (hardware level).
*
* Copyright 2002 by Andreas Eversberg (jolly@eversberg.eu)
* Copyright 2002 by Andreas Eversberg (jolly@jolly.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
@ -472,7 +472,6 @@ dsp_cmx_hardware(conference_t *conf, dsp_t *dsp)
if (dsp_debug & DEBUG_DSP_CMX)
printk(KERN_DEBUG "%s dsp %s cannot form a conf, because tx_mix is turned on\n", __FUNCTION__, member->dsp->inst.name);
conf_software:
// printk(KERN_NOTICE "****** SOFTWARE CONFERENCE\n");
list_for_each_entry(member, &conf->mlist, list) {
dsp = member->dsp;
/* remove HFC conference if enabled */
@ -864,14 +863,6 @@ dsp_cmx_conf(dsp_t *dsp, u32 conf_id)
if (dsp->conf_id == conf_id)
return(0);
spin_lock(&dsp->feature_lock);
if (dsp->feature_state != FEAT_STATE_RECEIVED) {
dsp->queue_conf_id=conf_id;
spin_unlock(&dsp->feature_lock);
return 0;
}
spin_unlock(&dsp->feature_lock);
/* first remove us from current conf */
if (dsp->conf_id) {
if (dsp_debug & DEBUG_DSP_CMX)
@ -995,7 +986,7 @@ dsp_cmx_receive(dsp_t *dsp, struct sk_buff *skb)
/* show where to write */
#ifdef CMX_DEBUG
printk( KERN_DEBUG "cmx_receive(dsp=%lx): rx_R(dsp)=%05x rx_W(dsp)=%05x len=%d %s\n", (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->inst.name);
printk(KERN_DEBUG "cmx_receive(dsp=%lx): rx_R(dsp) rx_W(dsp)=%05x len=%d %s\n", (u_long)dsp, dsp->rx_R, dsp->rx_W, len, dsp->inst.name);
#endif
/* write data into rx_buffer */
@ -1035,21 +1026,6 @@ dsp_cmx_send_member(dsp_t *dsp, int len, s32 *c, int members)
return;
if (!dsp->b_active) /* if not active */
return;
// NOTE: The following is not good, because we MUST send transmit data or
// software tones during pcm brige. (The condition above expresses this
// exactly. The card driver MUST disable bridging if data is in TX-
// fifo, to allow temporarily transmit tones until fifo is empty again.
#if 0
/* If we have 2 members and we are connected to pcm_slot, it looks
like we're bridged on the pcm, so why should we send anything ?
*/
if ( members==2 && (dsp->features.pcm_id>=0) &&
(dsp->pcm_slot_tx>=0) && (dsp->pcm_slot_rx>=0) ) {
return;
}
#endif
#ifdef CMX_DEBUG
printk(KERN_DEBUG "SEND members=%d dsp=%s, conf=%p, rx_R=%05x rx_W=%05x\n", members, dsp->inst.name, conf, dsp->rx_R, dsp->rx_W);
#endif

View File

@ -1,6 +1,6 @@
/* $Id$
*
* Author Andreas Eversberg (jolly@eversberg.eu)
* Author Andreas Eversberg (jolly@jolly.de)
* Based on source code structure by
* Karsten Keil (keil@isdn4linux.de)
*
@ -172,9 +172,9 @@ There are three things that need to transmit data to card:
const char *dsp_revision = "$Revision$";
#include <linux/delay.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/vmalloc.h>
#include "core.h"
#include "layer1.h"
#include "helper.h"
#include "debug.h"
@ -190,21 +190,11 @@ int dsp_options;
static int poll = 0;
int dsp_poll, dsp_tics;
int dtmfthreshold=100L;
#ifdef MODULE
MODULE_AUTHOR("Andreas Eversberg");
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
MODULE_PARM(options, "1i");
MODULE_PARM(poll, "1i");
MODULE_PARM(dtmfthreshold, "1i");
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
module_param(options, uint, S_IRUGO | S_IWUSR);
module_param(poll, uint, S_IRUGO | S_IWUSR);
module_param(dtmfthreshold, uint, S_IRUGO | S_IWUSR);
#endif
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
@ -234,35 +224,19 @@ dsp_control_req(dsp_t *dsp, mISDN_head_t *hh, struct sk_buff *skb)
case DTMF_TONE_START: /* turn on DTMF */
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: start dtmf\n", __FUNCTION__);
#if 0
if (len == sizeof(int)) {
printk(KERN_NOTICE "changing DTMF Threshold to %d\n",*((int*)data));
dsp->dtmf.treshold=(*(int*)data)*10000;
}
#endif
dsp_dtmf_goertzel_init(dsp);
dsp->dtmf.software = 0;
dsp->dtmf.hardware = 0;
/* checking for hardware capability */
spin_lock(&dsp->feature_lock);
if (dsp->feature_state != FEAT_STATE_RECEIVED) {
dsp->queue_dtmf=1;
spin_unlock(&dsp->feature_lock);
break;
}
spin_unlock(&dsp->feature_lock);
if (dsp->features.hfc_dtmf) {
dsp->dtmf.hardware = 1;
dsp->dtmf.software = 0;
} else {
dsp->dtmf.hardware = 0;
dsp->dtmf.software = 1;
}
break;
case DTMF_TONE_STOP: /* turn off DTMF */
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: stop dtmf\n", __FUNCTION__);
dsp->queue_dtmf=0;
dsp->dtmf.hardware = 0;
dsp->dtmf.software = 0;
break;
@ -466,7 +440,7 @@ dsp_from_up(mISDNinstance_t *inst, struct sk_buff *skb)
if (!dsp->tone.tone)
dsp_cmx_transmit(dsp, skb);
spin_unlock_irqrestore(&dsp_obj.lock, flags);
dev_kfree_skb(skb);
break;
case PH_CONTROL | REQUEST:
@ -566,7 +540,6 @@ dsp_from_down(mISDNinstance_t *inst, struct sk_buff *skb)
/* change volume if requested */
if (dsp->rx_volume)
dsp_change_volume(skb, dsp->rx_volume);
/* we need to process receive data if software */
spin_lock_irqsave(&dsp_obj.lock, flags);
if (dsp->pcm_slot_tx<0 && dsp->pcm_slot_rx<0) {
@ -574,7 +547,6 @@ dsp_from_down(mISDNinstance_t *inst, struct sk_buff *skb)
dsp_cmx_receive(dsp, skb);
}
spin_unlock_irqrestore(&dsp_obj.lock, flags);
if (dsp->rx_disabled) {
/* if receive is not allowed */
dev_kfree_skb(skb);
@ -612,17 +584,6 @@ dsp_from_down(mISDNinstance_t *inst, struct sk_buff *skb)
dev_kfree_skb(skb);
break;
case VOL_CHANGE_TX: /* change volume */
if (skb->len != sizeof(int)) {
ret = -EINVAL;
break;
}
dsp->tx_volume = *((int *)skb->data);
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: change tx volume to %d\n", __FUNCTION__, dsp->tx_volume);
printk(KERN_DEBUG "%s: change tx volume to %d\n", __FUNCTION__, dsp->tx_volume);
dsp_cmx_hardware(dsp->conf, dsp);
break;
default:
if (dsp_debug & DEBUG_DSP_CORE)
printk(KERN_DEBUG "%s: ctrl ind %x unhandled %s\n", __FUNCTION__, hh->dinfo, dsp->inst.name);
@ -723,7 +684,7 @@ release_dsp(dsp_t *dsp)
printk(KERN_DEBUG "%s: remove & destroy object %s\n", __FUNCTION__, dsp->inst.name);
list_del(&dsp->list);
spin_unlock_irqrestore(&dsp_obj.lock, flags);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
dsp_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
vfree(dsp);
if (dsp_debug & DEBUG_DSP_MGR)
@ -740,7 +701,6 @@ dsp_feat(void *arg)
dsp_t *dsp = arg;
struct sk_buff *nskb;
void *feat;
switch (dsp->feature_state) {
case FEAT_STATE_INIT:
@ -754,58 +714,23 @@ dsp_feat(void *arg)
}
if (dsp_debug & DEBUG_DSP_MGR)
printk(KERN_DEBUG "%s: features will be quered now for instance %s\n", __FUNCTION__, dsp->inst.name);
spin_lock(&dsp->feature_lock);
dsp->feature_state = FEAT_STATE_WAIT;
spin_unlock(&dsp->feature_lock);
init_timer(&dsp->feature_tl);
dsp->feature_tl.expires = jiffies + (HZ / 100);
add_timer(&dsp->feature_tl);
break;
case FEAT_STATE_WAIT:
if (dsp_debug & DEBUG_DSP_MGR)
printk(KERN_DEBUG "%s: features of %s are: hfc_id=%d hfc_dtmf=%d hfc_loops=%d hfc_echocanhw:%d pcm_id=%d pcm_slots=%d pcm_banks=%d\n",
printk(KERN_DEBUG "%s: features of %s are: hfc_id=%d hfc_dtmf=%d hfc_loops=%d pcm_id=%d pcm_slots=%d pcm_banks=%d\n",
__FUNCTION__, dsp->inst.name,
dsp->features.hfc_id,
dsp->features.hfc_dtmf,
dsp->features.hfc_loops,
dsp->features.hfc_echocanhw,
dsp->features.pcm_id,
dsp->features.pcm_slots,
dsp->features.pcm_banks);
spin_lock(&dsp->feature_lock);
dsp->feature_state = FEAT_STATE_RECEIVED;
spin_unlock(&dsp->feature_lock);
if (dsp->queue_conf_id) {
/* work on queued conf id*/
dsp_cmx_conf(dsp, dsp->queue_conf_id );
if (dsp_debug & DEBUG_DSP_CMX)
dsp_cmx_debug(dsp);
}
if (dsp->queue_dtmf) {
/* work on queued dtmf */
if (dsp->features.hfc_dtmf) {
dsp->dtmf.software = 0;
dsp->dtmf.hardware = 1;
} else {
dsp->dtmf.hardware = 0;
dsp->dtmf.software = 1;
}
}
if (dsp->queue_cancel[2]) {
dsp_cancel_init(dsp,
dsp->queue_cancel[0],
dsp->queue_cancel[1],
dsp->queue_cancel[2]
);
}
break;
}
}
@ -855,28 +780,17 @@ new_dsp(mISDNstack_t *st, mISDN_pid_t *pid)
/* set dsp feture timer */
ndsp->feature_tl.function = (void *)dsp_feat;
ndsp->feature_tl.data = (long) ndsp;
if (dtmfthreshold < 20 || dtmfthreshold> 500) {
dtmfthreshold=200;
}
ndsp->dtmf.treshold=dtmfthreshold*10000;
spin_lock_init(&ndsp->feature_lock);
ndsp->feature_state = FEAT_STATE_INIT;
init_timer(&ndsp->feature_tl);
if (!(dsp_options & DSP_OPT_NOHARDWARE)) {
ndsp->feature_state = FEAT_STATE_INIT;
ndsp->feature_tl.expires = jiffies + (HZ / 100);
add_timer(&ndsp->feature_tl);
} else {
// we don't need features, because we disabled them, so we must
// set the state to *_RECEIVED
ndsp->feature_state = FEAT_STATE_RECEIVED;
}
spin_lock_irqsave(&dsp_obj.lock, flags);
/* append and register */
list_add_tail(&ndsp->list, &dsp_obj.ilist);
spin_unlock_irqrestore(&dsp_obj.lock, flags);
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &ndsp->inst);
err = dsp_obj.ctrl(st, MGR_REGLAYER | INDICATION, &ndsp->inst);
if (err) {
printk(KERN_ERR "%s: failed to register layer %s\n", __FUNCTION__, ndsp->inst.name);
spin_lock_irqsave(&dsp_obj.lock, flags);
@ -964,7 +878,7 @@ static int dsp_init(void)
dsp_debug = debug;
/* display revision */
printk(KERN_INFO "mISDN_dsp: Audio DSP Rev. %s (debug=0x%x) EchoCancellor %s dtmfthreshold(%d)\n", mISDN_getrev(dsp_revision), debug, EC_TYPE, dtmfthreshold);
printk(KERN_INFO "mISDN_dsp: Audio DSP Rev. %s (debug=0x%x) EchoCancellor %s\n", mISDN_getrev(dsp_revision), debug, EC_TYPE);
/* set packet size */
if (poll == 0) {
@ -1027,8 +941,6 @@ static int dsp_init(void)
dsp_spl_jiffies = dsp_spl_tl.expires;
add_timer(&dsp_spl_tl);
mISDN_module_register(THIS_MODULE);
return(0);
}
@ -1041,8 +953,6 @@ static void dsp_cleanup(void)
dsp_t *dspl, *nd;
int err;
mISDN_module_unregister(THIS_MODULE);
if (timer_pending(&dsp_spl_tl))
del_timer(&dsp_spl_tl);

View File

@ -2,7 +2,7 @@
*
* DTMF decoder.
*
* Copyright by Andreas Eversberg (jolly@eversberg.eu)
* Copyright by Andreas Eversberg (jolly@jolly.de)
* based on different decoders such as ISDN4Linux
*
* This software may be used and distributed according to the terms
@ -16,6 +16,7 @@
#include "dsp.h"
#define NCOEFF 8 /* number of frequencies to be analyzed */
#define DTMF_TRESH 200000L /* above this is dtmf (square of)*/
/* For DTMF recognition:
* 2 * cos(2 * PI * k / N) precalculated for all k
@ -159,7 +160,7 @@ again:
for (i = 0; i < NCOEFF; i++) {
if (result[i] < 0)
result[i] = 0;
if (result[i] > dsp->dtmf.treshold) {
if (result[i] > DTMF_TRESH) {
if (result[i] > tresh)
tresh = result[i];
}

View File

@ -31,7 +31,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/slab.h>
#define MALLOC(a) kmalloc((a), GFP_ATOMIC)
#define MALLOC(a) kmalloc((a), GFP_KERNEL)
#define FREE(a) kfree(a)
#else
#include <stdlib.h>

View File

@ -17,7 +17,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/slab.h>
#define MALLOC(a) kmalloc((a), GFP_ATOMIC)
#define MALLOC(a) kmalloc((a), GFP_KERNEL)
#define FREE(a) kfree(a)
#else
#include <stdlib.h>

View File

@ -32,7 +32,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
#include <linux/slab.h>
#define MALLOC(a) kmalloc((a), GFP_ATOMIC)
#define MALLOC(a) kmalloc((a), GFP_KERNEL)
#define FREE(a) kfree(a)
#else
#include <stdlib.h>
@ -61,17 +61,12 @@
/* Uncomment to generate per-sample statistics - this will severely degrade system performance and audio quality */
/* #define MEC2_STATS_DETAILED */
/* Uncomment to generate per-call DC bias offset messages */
/* #define MEC2_DCBIAS_MESSAGE */
/* Get optimized routines for math */
#include "dsp_arith.h"
/* Bring in definitions for the various constants and thresholds */
#include "dsp_mg2ec_const.h"
#define DC_NORMALIZE
#ifndef NULL
#define NULL 0
#endif
@ -160,12 +155,9 @@ struct echo_can_state {
int avg_Lu_i_toolow;
int avg_Lu_i_ok;
#endif
short lastsig;
int lastcount;
short lastsig[256];
int lastpos;
int backup;
#ifdef DC_NORMALIZE
int dc_estimate;
#endif
};
@ -268,20 +260,9 @@ static inline void init_cc(struct echo_can_state *ec, int N, int maxy, int maxu)
static inline void echo_can_free(struct echo_can_state *ec)
{
#if defined(DC_NORMALIZE) && defined(MEC2_DCBIAS_MESSAGE)
printk("EC: DC bias calculated: %d V\n", ec->dc_estimate >> 15);
#endif
FREE(ec);
}
#ifdef DC_NORMALIZE
static short inline dc_removal(int *dc_estimate, short samp)
{
*dc_estimate += ((((int)samp << 15) - *dc_estimate) >> 9);
return samp - (*dc_estimate >> 15);
}
#endif
static inline short echo_can_update(struct echo_can_state *ec, short iref, short isig)
{
@ -296,10 +277,6 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
int Py_i;
/* ... */
int two_beta_i;
#ifdef DC_NORMALIZE
isig = dc_removal(&ec->dc_estimate, isig);
#endif
/* flow A on pg. 428 */
/* eq. (16): high-pass filter the input to generate the next value;
@ -329,18 +306,18 @@ static inline short echo_can_update(struct echo_can_state *ec, short iref, short
ec->N_d);
rs >>= 15;
if (ec->lastsig == isig) {
ec->lastcount++;
} else {
ec->lastcount = 0;
ec->lastsig = isig;
ec->lastsig[ec->lastpos++] = isig;
if (ec->lastpos >= 256)
ec->lastpos = 0;
for (k=0; k < 256; k++) {
if (isig != ec->lastsig[k])
break;
}
if (isig == 0) {
u = 0;
} else if (ec->lastcount > 255) {
/* We have seen the same input-signal more than 255 times,
* we should pass it through uncancelled, as we are likely on hold */
} else if (k == 256) {
u = isig;
} else {
if (rs < -32768) {

View File

@ -2,7 +2,7 @@
*
* Audio support data for ISDN4Linux.
*
* Copyright Andreas Eversberg (jolly@eversberg.eu)
* Copyright Andreas Eversberg (jolly@jolly.de)
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.

View File

@ -16,9 +16,7 @@
/* for layer 1 certification T309 < layer1 T3 (e.g. 4000) */
/* This makes some tests easier and quicker */
#define T309 40000
/* T310 can be between 30-120 Seconds. We use 120 Seconds so the user can hear
the inband messages */
#define T310 120000
#define T310 30000
#define T313 4000
#define T318 4000
#define T319 4000
@ -109,7 +107,6 @@
#define IE_CALLED_PN 0x70
#define IE_CALLED_SUB 0x71
#define IE_REDIR_NR 0x74
#define IE_REDIR_DN 0x76
#define IE_TRANS_SEL 0x78
#define IE_RESTART_IND 0x79
#define IE_LLC 0x7c
@ -120,7 +117,6 @@
#define IE_MORE_DATA 0xa0
#define IE_COMPLETE 0xa1
#define IE_CONGESTION 0xb0
#define IE_COMPR_REQ 0x01
#define IE_REPEAT 0xd0
#define IE_MANDATORY 0x0100

View File

@ -15,8 +15,8 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include "core.h"
#include "layer1.h"
#include "helper.h"
#include "debug.h"
@ -496,7 +496,7 @@ release_dtmf(dtmf_t *dtmf) {
spin_lock_irqsave(&dtmf_obj.lock, flags);
list_del(&dtmf->list);
spin_unlock_irqrestore(&dtmf_obj.lock, flags);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
dtmf_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
kfree(dtmf);
}
@ -524,7 +524,7 @@ new_dtmf(mISDNstack_t *st, mISDN_pid_t *pid) {
spin_lock_irqsave(&dtmf_obj.lock, flags);
list_add_tail(&n_dtmf->list, &dtmf_obj.ilist);
spin_unlock_irqrestore(&dtmf_obj.lock, flags);
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &n_dtmf->inst);
err = dtmf_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_dtmf->inst);
if (err) {
list_del(&n_dtmf->list);
kfree(n_dtmf);
@ -559,11 +559,7 @@ static char MName[] = "DTMF";
#ifdef MODULE
MODULE_AUTHOR("Karsten Keil");
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#else
module_param (debug, uint, S_IRUGO | S_IWUSR);
#endif
MODULE_PARM_DESC (debug, "dtmf debug mask");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
@ -641,8 +637,7 @@ static int dtmf_init(void)
INIT_LIST_HEAD(&dtmf_obj.ilist);
if ((err = mISDN_register(&dtmf_obj))) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
} else
mISDN_module_register(THIS_MODULE);
}
return(err);
}
@ -651,8 +646,6 @@ static void dtmf_cleanup(void)
int err;
dtmf_t *dtmf, *nd;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&dtmf_obj))) {
printk(KERN_ERR "Can't unregister DTMF error(%d)\n", err);
}

View File

@ -11,6 +11,7 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include "layer1.h"
#include "m_capi.h"
@ -1919,8 +1920,8 @@ static char MName[] = "FAXL3";
#ifdef MODULE
MODULE_AUTHOR("Karsten Keil");
module_param(debug, uint, S_IRUGO | S_IWUSR);
module_param(ttt, uint, S_IRUGO | S_IWUSR);
MODULE_PARM(debug, "1i");
MODULE_PARM(ttt, "1i");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
@ -1935,7 +1936,7 @@ l3m_debug(struct FsmInst *fi, char *fmt, ...)
va_start(log.args, fmt);
log.fmt = fmt;
log.head = fl3->inst.name;
mISDN_ctrl(&fl3->inst, MGR_DEBUGDATA | REQUEST, &log);
fl3->inst.obj->ctrl(&fl3->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}
@ -1944,10 +1945,12 @@ release_faxl3(faxl3_t *faxl3) {
mISDNinstance_t *inst = &faxl3->inst;
if (inst->up.peer) {
mISDN_ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
inst->up.peer->obj->ctrl(inst->up.peer,
MGR_DISCONNECT | REQUEST, &inst->up);
}
if (inst->down.peer) {
mISDN_ctrl(inst->down.peer, MGR_DISCONNECT | REQUEST, &inst->down);
inst->down.peer->obj->ctrl(inst->down.peer,
MGR_DISCONNECT | REQUEST, &inst->down);
}
list_del(&faxl3->list);
discard_queue(&faxl3->downq);
@ -1958,8 +1961,8 @@ release_faxl3(faxl3_t *faxl3) {
mISDN_FsmDelTimer(&faxl3->timer1, 99);
mISDN_FsmDelTimer(&faxl3->modtimer, 99);
if (faxl3->entity != MISDN_ENTITY_NONE)
mISDN_ctrl(inst, MGR_DELENTITY | REQUEST, (void *)faxl3->entity);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
faxl3_obj.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)faxl3->entity);
faxl3_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
kfree(faxl3);
}
@ -2046,12 +2049,12 @@ new_faxl3(mISDNstack_t *st, mISDN_pid_t *pid) {
list_add_tail(&n_faxl3->list, &faxl3_obj.ilist);
n_faxl3->entity = MISDN_ENTITY_NONE;
err = mISDN_ctrl(&n_faxl3->inst, MGR_NEWENTITY | REQUEST, NULL);
err = faxl3_obj.ctrl(&n_faxl3->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%d)\n",
__FUNCTION__, err);
}
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &n_faxl3->inst);
err = faxl3_obj.ctrl(st, MGR_REGLAYER | INDICATION, &n_faxl3->inst);
if (err) {
list_del(&n_faxl3->list);
kfree(n_faxl3);

View File

@ -127,10 +127,8 @@ mISDN_FsmAddTimer(struct FsmTimer *ft,
#endif
if (timer_pending(&ft->tl)) {
if (ft->fi->debug) {
printk(KERN_WARNING "mISDN_FsmAddTimer: timer already active!\n");
ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer already active!");
}
printk(KERN_WARNING "mISDN_FsmAddTimer: timer already active!\n");
ft->fi->printdebug(ft->fi, "mISDN_FsmAddTimer already active!");
return -1;
}
init_timer(&ft->tl);

View File

@ -41,63 +41,26 @@ mISDN_set_dchannel_pid(mISDN_pid_t *pid, int protocol, int layermask)
pid->protocol[4] = ISDN_PID_L4_CAPI20;
}
int
mISDN_add_pid_parameter(mISDN_pid_t *pid, int layer, u_char *para)
{
u16 l;
if (para == NULL || *para == 0) {
pid->param[layer] = 0;
return 0;
}
l = 1 + *para; /* including length itself */
if (!pid->pbuf) {
pid->maxplen = l + 1; /* pbuf[0] is never used */
if (l < 63)
pid->maxplen = 64;
pid->pbuf = kzalloc(pid->maxplen, GFP_ATOMIC);
pid->pidx = 1;
if (!pid->pbuf) {
pid->maxplen = 0;
return -ENOMEM;
}
} else if ((pid->pidx + l) > pid->maxplen) {
u_char *tbuf;
tbuf = kmalloc(pid->pidx + l, GFP_ATOMIC);
if (!tbuf)
return -ENOMEM;
memcpy(tbuf, pid->pbuf, pid->pidx);
kfree(pid->pbuf);
pid->pbuf = tbuf;
pid->maxplen = pid->pidx + l;
}
pid->param[layer] = pid->pidx;
memcpy(&pid->pbuf[pid->pidx], para, l);
pid->pidx += l;
return 0;
}
int
mISDN_bprotocol2pid(void *bp, mISDN_pid_t *pid)
{
u8 *p = bp;
u16 *w = bp;
int i, ret;
__u8 *p = bp;
__u16 *w = bp;
int i;
p += 6;
for (i=1; i<=3; i++) {
if (*w > 23) {
int_errtxt("L%d pid %x\n",i,*w);
return -EINVAL;
return(-EINVAL);
}
pid->protocol[i] = (1 <<*w) | ISDN_PID_LAYER(i) |
ISDN_PID_BCHANNEL_BIT;
ret = mISDN_add_pid_parameter(pid, i, p);
if (ret)
return ret;
if (*p)
pid->param[i] = p;
else
pid->param[i] = NULL;
w++;
p += *p;
p++;
@ -105,10 +68,10 @@ mISDN_bprotocol2pid(void *bp, mISDN_pid_t *pid)
pid->global = 0;
if (*p == 2) { // len of 1 word
p++;
w = (u16 *)p;
w = (__u16 *)p;
pid->global = *w;
}
return 0;
return(0);
}
int
@ -154,9 +117,6 @@ mISDN_SetHandledPID(mISDNobject_t *obj, mISDN_pid_t *pid)
#endif
memcpy(&sav, pid, sizeof(mISDN_pid_t));
memset(pid, 0, sizeof(mISDN_pid_t));
pid->pbuf = sav.pbuf;
pid->maxplen = sav.maxplen;
pid->pidx = sav.pidx;
pid->global = sav.global;
if (!sav.layermask) {
printk(KERN_WARNING "%s: no layermask in pid\n", __FUNCTION__);
@ -196,7 +156,7 @@ mISDN_RemoveUsedPID(mISDN_pid_t *pid, mISDN_pid_t *used)
if (!(ISDN_LAYER(layer) & used->layermask))
continue;
pid->protocol[layer] = ISDN_PID_NONE;
pid->param[layer] = 0;
pid->param[layer] = NULL;
pid->layermask &= ~(ISDN_LAYER(layer));
}
}
@ -389,6 +349,10 @@ mISDN_init_instance(mISDNinstance_t *inst, mISDNobject_t *obj, void *data, if_fu
int_error();
return;
}
if (!obj->ctrl) {
int_error();
return;
}
INIT_LIST_HEAD(&inst->list);
inst->obj = obj;
inst->privat = data;
@ -408,5 +372,4 @@ EXPORT_SYMBOL(mISDN_init_instance);
// EXPORT_SYMBOL(mISDN_SetIF);
// EXPORT_SYMBOL(mISDN_ConnectIF);
// EXPORT_SYMBOL(mISDN_DisConnectIF);
EXPORT_SYMBOL(mISDN_add_pid_parameter);
EXPORT_SYMBOL(mISDN_bprotocol2pid);

View File

@ -280,7 +280,6 @@ extern void mISDN_AddIE(struct sk_buff *, u_char, u_char *);
extern ie_info_t *mISDN_get_last_repeated_ie(Q931_info_t *, ie_info_t *);
extern int mISDN_get_free_ext_ie(Q931_info_t *);
extern void mISDN_LogL3Msg(struct sk_buff *);
extern int mISDN_add_pid_parameter(mISDN_pid_t *, int, u_char *);
/* manager default handler helper macros */

File diff suppressed because it is too large Load Diff

View File

@ -97,19 +97,16 @@ typedef struct hfcmulti_hw hfcmulti_hw_t;
#define HFC_CHIP_ULAW 7 /* ULAW mode */
#define HFC_CHIP_CLOCK2 8 /* double clock mode */
#define HFC_CHIP_CRYSTAL_CLOCK 9 /* autarc clocking mode */
#define HFC_CHIP_WATCHDOG 10 /* wether we should send signals
to the watchdog */
#define HFC_CHIP_DIGICARD 11 /* wether we have a b410p with echocan in
hw */
struct hfc_multi {
struct list_head list;
#warning
void *davor, *danach;
char name[32];
int idx; /* chip index for module parameters */
int id; /* chip number starting with 1 */
int pcm; /* id of pcm bus */
int type;
int ports;
u_int irq; /* irq used by card */
u_int irqcnt;
@ -136,10 +133,6 @@ struct hfc_multi {
u_int slots; /* number of PCM slots */
u_int leds; /* type of leds */
u_int ledcount; /* used to animate leds */
int opticalsupport; /* has the e1 board an optical Interface*/
u_long wdcount; /* every 500 ms we need to send the watchdog a signal */
u_char wdbyte; /* watchdog toggle byte*/
u_int activity[8]; /* if there is any action on this port (will be cleared after showing led-states) */
spinlock_t lock; /* the lock */
@ -1239,37 +1232,31 @@ static void _HFC_wait(hfc_multi_t *a, char *function, int line)
#endif
/* usage: HFC_outX(card,register,value); */
static inline void HFC_outb(hfc_multi_t *a, unsigned short b, u_char c)
static inline void HFC_outb(hfc_multi_t *a, u_char b, u_char c)
{
outw(b,(a->pci_iobase)+4);
outb(b,(a->pci_iobase)+4);
outb(c,a->pci_iobase);
}
static inline void HFC_outl(hfc_multi_t *a, unsigned short b, u_long c)
static inline void HFC_outl(hfc_multi_t *a, u_char b, u_long c)
{
outw(b,(a->pci_iobase)+4);
outb(b,(a->pci_iobase)+4);
outl(c,a->pci_iobase);
}
static inline void HFC_outw(hfc_multi_t *a, unsigned short b, u_long c)
{
outw(b,(a->pci_iobase)+4);
outw(c,a->pci_iobase);
}
/* usage: value=HFC_inX(card,register); */
static inline u_char HFC_inb(hfc_multi_t *a, unsigned short b)
static inline u_char HFC_inb(hfc_multi_t *a, u_char b)
{
outw(b,(a->pci_iobase)+4);
outb(b,(a->pci_iobase)+4);
return (inb((volatile u_int)a->pci_iobase));
}
static inline u_short HFC_inw(hfc_multi_t *a, unsigned short b)
static inline u_short HFC_inw(hfc_multi_t *a, u_char b)
{
outw(b,(a->pci_iobase)+4);
outb(b,(a->pci_iobase)+4);
return (inw((volatile u_int)a->pci_iobase));
}
static inline u_long HFC_inl(hfc_multi_t *a, unsigned short b)
static inline u_long HFC_inl(hfc_multi_t *a, u_char b)
{
outw(b,(a->pci_iobase)+4);
outb(b,(a->pci_iobase)+4);
return (inl((volatile u_int)a->pci_iobase));
}

View File

@ -25,11 +25,11 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include "core.h"
#include "channel.h"
#include "hfc_pci.h"
#include "layer1.h"
@ -1800,6 +1800,7 @@ SelFreeBChannel(hfc_pci_t *hc, channel_info_t *ci)
}
#define MAX_CARDS 8
#define MODULE_PARM_T "1-8i"
static int HFC_cnt;
static uint protocol[MAX_CARDS];
static uint layermask[MAX_CARDS];
@ -1812,12 +1813,6 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#define MODULE_PARM_T "1-4i"
MODULE_PARM(protocol, MODULE_PARM_T);
MODULE_PARM(layermask, MODULE_PARM_T);
#else
module_param (debug, uint, 0);
MODULE_PARM_DESC (debug, "hfcpci debug mask");
#ifdef OLD_MODULE_PARAM_ARRAY
@ -1859,7 +1854,6 @@ module_param_array(layermask, uint, NULL, 0);
#endif
MODULE_PARM_DESC(layermask, "hfcpci layer mask");
#endif
#endif
static char HFCName[] = "HFC_PCI";
@ -1919,7 +1913,7 @@ setup_hfcpci(hfc_pci_t *hc)
return 1;
}
hc->hw.fifos = buffer;
pci_write_config_dword(hc->hw.dev, 0x80, hc->hw.dmahandle);
pci_write_config_dword(hc->hw.dev, 0x80, (u_int) cpu_to_le32((unsigned int)virt_to_bus(hc->hw.fifos)));
hc->hw.pci_io = ioremap((ulong) hc->hw.pci_io, 256);
printk(KERN_INFO
"HFC-PCI: defined at mem %#lx fifo %#lx(%#lx) IRQ %d HZ %d\n",
@ -1957,7 +1951,7 @@ release_card(hfc_pci_t *hc) {
mISDN_freechannel(&hc->bch[0]);
mISDN_freechannel(&hc->dch);
spin_unlock_irqrestore(&hc->lock, flags);
mISDN_ctrl(&hc->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
HFC_obj.ctrl(&hc->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
spin_lock_irqsave(&HFC_obj.lock, flags);
list_del(&hc->list);
spin_unlock_irqrestore(&HFC_obj.lock, flags);
@ -2014,7 +2008,7 @@ HFC_manager(void *data, u_int prim, void *arg) {
if (hfcpci_l2l1(inst, skb))
dev_kfree_skb(skb);
}
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
HFC_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
arg = NULL;
@ -2220,7 +2214,7 @@ static int __init HFC_init(void)
if (prev) {
dst = prev->dch.inst.st;
} else {
if ((err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST,
if ((err = HFC_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST,
&card->dch.inst))) {
printk(KERN_ERR "MGR_ADDSTACK REQUEST dch err(%d)\n", err);
release_card(card);
@ -2232,12 +2226,14 @@ static int __init HFC_init(void)
}
dst = card->dch.inst.st;
}
mISDN_ctrl(dst, MGR_STOPSTACK | REQUEST, NULL);
HFC_obj.ctrl(dst, MGR_STOPSTACK | REQUEST, NULL);
for (i = 0; i < 2; i++) {
card->bch[i].inst.class_dev.dev = &card->hw.dev->dev;
if ((err = mISDN_ctrl(dst, MGR_NEWSTACK | REQUEST, &card->bch[i].inst))) {
if ((err = HFC_obj.ctrl(dst,
MGR_NEWSTACK | REQUEST, &card->bch[i].inst))) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
HFC_obj.ctrl(card->dch.inst.st,
MGR_DELSTACK | REQUEST, NULL);
if (!HFC_cnt)
mISDN_unregister(&HFC_obj);
else
@ -2246,10 +2242,11 @@ static int __init HFC_init(void)
}
}
if (protocol[HFC_cnt] != 0x100) { /* next not second HFC */
if ((err = mISDN_ctrl(dst, MGR_SETSTACK | REQUEST, &pid))) {
if ((err = HFC_obj.ctrl(dst, MGR_SETSTACK | REQUEST,
&pid))) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n",
err);
mISDN_ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
HFC_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
if (!HFC_cnt)
mISDN_unregister(&HFC_obj);
else
@ -2258,17 +2255,16 @@ static int __init HFC_init(void)
}
}
if ((err = init_card(card))) {
mISDN_ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
HFC_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
if (!HFC_cnt)
mISDN_unregister(&HFC_obj);
else
err = 0;
return(err);
}
mISDN_ctrl(dst, MGR_STARTSTACK | REQUEST, NULL);
mISDN_ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
HFC_obj.ctrl(dst, MGR_STARTSTACK | REQUEST, NULL);
HFC_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
}
mISDN_module_register(THIS_MODULE);
printk(KERN_INFO "HFC %d cards installed\n", HFC_cnt);
return(0);
}
@ -2279,8 +2275,6 @@ static void __exit HFC_cleanup(void)
hfc_pci_t *card, *next;
int err;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&HFC_obj))) {
printk(KERN_ERR "Can't unregister HFC PCI error(%d)\n", err);
}

View File

@ -49,10 +49,10 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <asm/timex.h>
#include "core.h"
#include "layer1.h"
#include "debug.h"
#include "hfcs_mini.h"
@ -69,31 +69,18 @@ static int card_cnt;
static u_int protocol[MAX_CARDS];
static int layermask[MAX_CARDS];
#ifdef MODULE
MODULE_LICENSE("GPL");
#define MODULE_PARM_T "1-8i"
MODULE_PARM(debug, "1i");
MODULE_PARM(protocol, MODULE_PARM_T);
MODULE_PARM(layermask, MODULE_PARM_T);
#endif
static mISDNobject_t hw_mISDNObj;
static int debug = 0;
#ifdef MODULE
MODULE_LICENSE("GPL");
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#define MODULE_PARM_T "1-4i"
MODULE_PARM(protocol, MODULE_PARM_T);
MODULE_PARM(layermask, MODULE_PARM_T);
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#ifdef OLD_MODULE_PARAM_ARRAY
static int num_protocol=0, num_layermask=0;
module_param_array(protocol, uint, num_protocol, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, num_layermask, S_IRUGO | S_IWUSR);
#else
module_param_array(protocol, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, NULL, S_IRUGO | S_IWUSR);
#endif
#endif
#endif
#if HFCBRIDGE == BRIDGE_HFCPCI
static inline void
@ -597,7 +584,7 @@ hfcsmini_manager(void *data, u_int prim, void *arg)
dev_kfree_skb(skb);
} else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
hw_mISDNObj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
arg = NULL;
@ -1037,7 +1024,7 @@ release_channels(hfcsmini_hw * hw)
printk(KERN_DEBUG "%s %s: free channel %d\n",
hw->card_name, __FUNCTION__, i);
mISDN_freechannel(&hw->chan[i]);
mISDN_ctrl(&hw->chan[i].inst, MGR_UNREGLAYER | REQUEST, NULL);
hw_mISDNObj.ctrl(&hw->chan[i].inst, MGR_UNREGLAYER | REQUEST, NULL);
}
i++;
}
@ -1291,7 +1278,7 @@ init_mISDN_channels(hfcsmini_hw * hw)
hw->card_name, __FUNCTION__);
/* register stack */
err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &hw->chan[ch].inst);
err = hw_mISDNObj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &hw->chan[ch].inst);
if (err) {
printk(KERN_ERR "%s %s: MGR_NEWSTACK | REQUEST err(%d)\n",
hw->card_name, __FUNCTION__, err);
@ -1300,7 +1287,7 @@ init_mISDN_channels(hfcsmini_hw * hw)
hw->chan[ch].state = 0;
for (b = 0; b < 2; b++) {
err = mISDN_ctrl(hw->chan[ch].inst.st, MGR_NEWSTACK | REQUEST, &hw->chan[b].inst);
err = hw_mISDNObj.ctrl(hw->chan[ch].inst.st, MGR_NEWSTACK | REQUEST, &hw->chan[b].inst);
if (err) {
printk(KERN_ERR
"%s %s: MGR_ADDSTACK bchan error %d\n",
@ -1309,13 +1296,14 @@ init_mISDN_channels(hfcsmini_hw * hw)
}
}
err = mISDN_ctrl(hw->chan[ch].inst.st, MGR_SETSTACK | REQUEST, &pid);
err = hw_mISDNObj.ctrl(hw->chan[ch].inst.st, MGR_SETSTACK | REQUEST, &pid);
if (err) {
printk(KERN_ERR
"%s %s: MGR_SETSTACK REQUEST dch err(%d)\n",
hw->card_name, __FUNCTION__, err);
mISDN_ctrl(hw->chan[ch].inst.st, MGR_DELSTACK | REQUEST, NULL);
hw_mISDNObj.ctrl(hw->chan[ch].inst.st,
MGR_DELSTACK | REQUEST, NULL);
goto free_stack;
}
@ -1328,11 +1316,12 @@ init_mISDN_channels(hfcsmini_hw * hw)
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout((100 * HZ) / 1000); /* Timeout 100ms */
mISDN_ctrl(hw->chan[ch].inst.st, MGR_CTRLREADY | INDICATION, NULL);
hw_mISDNObj.ctrl(hw->chan[ch].inst.st, MGR_CTRLREADY | INDICATION,
NULL);
return (0);
free_stack:
mISDN_ctrl(hw->chan[ch].inst.st, MGR_DELSTACK | REQUEST, NULL);
hw_mISDNObj.ctrl(hw->chan[ch].inst.st, MGR_DELSTACK | REQUEST, NULL);
free_channels:
spin_lock_irqsave(&hw_mISDNObj.lock, flags);
release_channels(hw);
@ -1847,7 +1836,6 @@ hfcsmini_init(void)
#endif
#endif
mISDN_module_register(THIS_MODULE);
printk(KERN_INFO "HFC-S mini: %d cards installed\n", card_cnt);
return 0;
@ -1861,8 +1849,6 @@ hfcsmini_cleanup(void)
{
int err;
mISDN_module_unregister(THIS_MODULE);
#if HFCBRIDGE == BRIDGE_HFCPCI
pci_unregister_driver(&hfcsmini_driver);
#endif

View File

@ -21,14 +21,17 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* TODO
* - hotplug disconnect the USB TA does not unregister mISDN Controller
* /proc/capi/controller is still "ready"...
* --> use rmmod before disconnecting the TA
* - E channel features
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/usb.h>
#include "core.h"
#include "channel.h"
#include "layer1.h"
#include "debug.h"
@ -39,38 +42,21 @@
const char *hfcsusb_rev = "$Revision$";
#define MAX_CARDS 8
#define MODULE_PARM_T "1-8i"
static int hfcsusb_cnt;
static u_int protocol[MAX_CARDS] = {2,2,2,2,2,2,2,2};
static int layermask[MAX_CARDS];
static mISDNobject_t hw_mISDNObj;
static int debug = 0;
static int poll = 128;
static int debug = 0x1FFFF; // 0;
#ifdef MODULE
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
MODULE_PARM(poll, "1i");
#define MODULE_PARM_T "1-4i"
MODULE_PARM(protocol, MODULE_PARM_T);
MODULE_PARM(layermask, MODULE_PARM_T);
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
module_param(poll, uint, S_IRUGO | S_IWUSR);
#ifdef OLD_MODULE_PARAM_ARRAY
static int num_protocol=0, num_layermask=0;
module_param_array(protocol, uint, num_protocol, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, num_layermask, S_IRUGO | S_IWUSR);
#else
module_param_array(protocol, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, NULL, S_IRUGO | S_IWUSR);
#endif
#endif
#endif
@ -127,8 +113,6 @@ typedef struct _hfcsusb_t {
struct usb_ctrlrequest ctrl_read; /* same for read request */
int ctrl_paksize; /* control pipe packet size */
int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */
spinlock_t ctrl_lock; /* queueing ctrl urbs needs to be locked */
spinlock_t lock;
volatile __u8 threshold_mask; /* threshold in fifo flow control */
__u8 old_led_state, led_state;
@ -211,8 +195,6 @@ static struct usb_device_id hfcsusb_idtab[] = {
{ }
};
MODULE_DEVICE_TABLE(usb, hfcsusb_idtab);
/* some function prototypes */
static int hfcsusb_l2l1(mISDNinstance_t *inst, struct sk_buff *skb);
static int setup_bchannel(channel_t * bch, int protocol);
@ -250,8 +232,7 @@ static int
queued_Write_hfc(hfcsusb_t * card, __u8 reg, __u8 val)
{
ctrl_buft *buf;
spin_lock(&card->ctrl_lock);
if (card->ctrl_cnt >= HFC_CTRL_BUFSIZE)
return (1); /* no space left */
buf = &card->ctrl_buff[card->ctrl_in_idx]; /* pointer to new index */
@ -261,8 +242,6 @@ queued_Write_hfc(hfcsusb_t * card, __u8 reg, __u8 val)
card->ctrl_in_idx = 0; /* pointer wrap */
if (++card->ctrl_cnt == 1)
ctrl_start_transfer(card);
spin_unlock(&card->ctrl_lock);
return (0);
}
@ -443,7 +422,7 @@ S0_new_state(channel_t * dch)
test_and_set_bit(FLG_ACTIVE, &dch->Flags);
card->nt_timer = 0;
card->portmode &= ~NT_ACTIVATION_TIMER;
prim = PH_ACTIVATE | CONFIRM;
prim = PH_ACTIVATE | INDICATION;
para = 0;
handle_led(card, LED_S0_ON);
break;
@ -534,11 +513,6 @@ setup_bchannel(channel_t * bch, int protocol)
}
if (protocol >= ISDN_PID_NONE) {
/*
printk ("HFCS-USB: %s: HFCUSB_FIFO(0x%x) HFCUSB_CON_HDLC(0x%x)\n",
__FUNCTION__, (bch->channel)?2:0, conhdlc);
*/
/* set FIFO to transmit register */
queued_Write_hfc(card, HFCUSB_FIFO,
(bch->channel)?2:0);
@ -547,11 +521,6 @@ setup_bchannel(channel_t * bch, int protocol)
/* reset fifo */
queued_Write_hfc(card, HFCUSB_INC_RES_F, 2);
/*
printk ("HFCS-USB: %s: HFCUSB_FIFO(0x%x) HFCUSB_CON_HDLC(0x%x)\n",
__FUNCTION__, (bch->channel)?2:0, conhdlc);
*/
/* set FIFO to receive register */
queued_Write_hfc(card, HFCUSB_FIFO,
((bch->channel)?3:1));
@ -572,11 +541,6 @@ setup_bchannel(channel_t * bch, int protocol)
sctrl |= ((card->chan[B2].channel)?2:1);
sctrl_r |= ((card->chan[B2].channel)?2:1);
}
/*
printk ("HFCS-USB: %s: HFCUSB_SCTRL(0x%x) HFCUSB_SCTRL_R(0x%x)\n",
__FUNCTION__, sctrl, sctrl_r);
*/
queued_Write_hfc(card, HFCUSB_SCTRL, sctrl);
queued_Write_hfc(card, HFCUSB_SCTRL_R, sctrl_r);
@ -611,14 +575,10 @@ hfcsusb_ph_command(hfcsusb_t * card, u_char command)
break;
case HFC_L1_ACTIVATE_NT:
if (card->chan[D].state == 3) {
mISDN_queue_data(&card->chan[D].inst, FLG_MSG_UP, PH_ACTIVATE | INDICATION, 0, 0, NULL, 0);
} else {
queued_Write_hfc(card, HFCUSB_STATES,
HFCUSB_ACTIVATE
| HFCUSB_DO_ACTION
| HFCUSB_NT_G2_G3);
}
queued_Write_hfc(card, HFCUSB_STATES,
HFCUSB_ACTIVATE
| HFCUSB_DO_ACTION
| HFCUSB_NT_G2_G3);
break;
case HFC_L1_DEACTIVATE_NT:
@ -644,7 +604,7 @@ handle_dmsg(channel_t *dch, struct sk_buff *skb)
if (hh->dinfo == HW_RESET) {
if (dch->state != 0)
hfcsusb_ph_command(hw, HFC_L1_ACTIVATE_TE);
skb_trim(skb, 0);
skb_trim(skb, 0);
return(mISDN_queueup_newhead(&dch->inst, 0, PH_CONTROL | INDICATION,HW_POWERUP, skb));
} else if (hh->dinfo == HW_DEACTIVATE) {
if (dch->next_skb) {
@ -734,18 +694,14 @@ handle_bmsg(channel_t *bch, struct sk_buff *skb)
{
int ret = 0;
mISDN_head_t *hh = mISDN_HEAD_P(skb);
hfcsusb_t *hw = bch->hw;
u_long flags;
if ((hh->prim == (PH_ACTIVATE | REQUEST)) ||
(hh->prim == (DL_ESTABLISH | REQUEST))) {
spin_lock_irqsave(&hw->lock, flags);
if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) {
ret = setup_bchannel(bch, bch->inst.pid.protocol[1]);
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_TRANS)
test_and_set_bit(FLG_L2DATA, &bch->Flags);
}
spin_unlock_irqrestore(&hw->lock, flags);
#ifdef FIXME
if (bch->inst.pid.protocol[2] == ISDN_PID_L2_B_RAWDEV)
if (bch->dev)
@ -758,7 +714,6 @@ handle_bmsg(channel_t *bch, struct sk_buff *skb)
(hh->prim == (DL_RELEASE | REQUEST)) ||
((hh->prim == (PH_CONTROL | REQUEST) && (hh->dinfo == HW_DEACTIVATE)))) {
spin_lock_irqsave(&hw->lock, flags);
if (test_and_clear_bit(FLG_TX_NEXT, &bch->Flags)) {
dev_kfree_skb(bch->next_skb);
bch->next_skb = NULL;
@ -776,7 +731,6 @@ handle_bmsg(channel_t *bch, struct sk_buff *skb)
test_and_clear_bit(FLG_TX_BUSY, &bch->Flags);
setup_bchannel(bch, ISDN_PID_NONE);
test_and_clear_bit(FLG_ACTIVE, &bch->Flags);
spin_unlock_irqrestore(&hw->lock, flags);
skb_trim(skb, 0);
if (hh->prim != (PH_CONTROL | REQUEST)) {
#ifdef FIXME
@ -809,42 +763,13 @@ hfcsusb_l2l1(mISDNinstance_t *inst, struct sk_buff *skb)
channel_t *chan = container_of(inst, channel_t, inst);
int ret = 0;
mISDN_head_t *hh = mISDN_HEAD_P(skb);
u_long flags;
int i;
if ((hh->prim == PH_DATA_REQ) || (hh->prim == DL_DATA_REQ)) {
spin_lock_irqsave(inst->hwlock, flags);
ret = channel_senddata(chan, hh->dinfo, skb);
if (ret > 0) {
if (!(chan)) {
printk (KERN_INFO "HFC-S USB: CRITICAL ERROR! chan is NULL pointer!\n");
spin_unlock_irqrestore(inst->hwlock, flags);
return(-EINVAL);
}
if (!(chan->tx_skb)) {
printk (KERN_INFO "HFC-S USB: CRITICAL ERROR! channel_senddata returned %d without chan->tx_skb\n", ret);
spin_unlock_irqrestore(inst->hwlock, flags);
return(-EINVAL);
}
/* channel data debug: */
if ((chan->debug) && (debug & DEBUG_HFC_FIFO)) {
mISDN_debugprint(&chan->inst,
"new TX channel(%i) len(%i): ",
chan->channel, chan->tx_skb->len);
i = 0;
printk(" ");
while (i < chan->tx_skb->len)
printk("%02x ", chan->tx_skb->data[i++]);
printk("\n");
}
/* data gets transmitted later in USB ISO OUT traffic */
ret = 0;
}
spin_unlock_irqrestore(inst->hwlock, flags);
return(ret);
}
if (test_bit(FLG_DCHANNEL, &chan->Flags)) {
@ -920,7 +845,7 @@ hfcsusb_manager(void *data, u_int prim, void *arg)
dev_kfree_skb(skb);
} else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
hw_mISDNObj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
arg = NULL;
@ -982,42 +907,19 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, unsigned int len, int finish)
channel_t *ch = &card->chan[fifo->ch_idx];
struct sk_buff *skb; /* data buffer for upper layer */
int fifon;
int i;
if (!len)
return;
fifon = fifo->fifonum;
if (!ch->rx_skb) {
printk(KERN_INFO "alloc new skb for fifon(%d), len(%d+%d)\n", fifon, ch->maxlen + 3, ch->up_headerlen);
ch->rx_skb = alloc_stack_skb(ch->maxlen + 3, ch->up_headerlen);
if (!ch->rx_skb) {
printk(KERN_DEBUG "%s: No mem for rx_skb\n", __FUNCTION__);
return;
}
skb_trim(ch->rx_skb, 0);
}
if (fifon == HFCUSB_D_RX) {
/* D-Channel SKK range check */
if ((ch->rx_skb->len + len) >= MAX_DFRAME_LEN_L1) {
printk(KERN_DEBUG "%s: sbk mem exceeded for fifo(%d) HFCUSB_D_RX\n",
__FUNCTION__, fifon);
skb_trim(ch->rx_skb, 0);
return;
}
} else {
/* B-Channel SKB range check */
if ((ch->rx_skb->len + len) >= (MAX_BCH_SIZE + 3)) {
printk(KERN_DEBUG "%s: sbk mem exceeded for fifo(%d) HFCUSB_B_RX\n",
__FUNCTION__, fifon);
skb_trim(ch->rx_skb, 0);
return;
}
}
// printk ("skb_put: len(%d) new_len(%d)", ch->rx_skb->len, len);
memcpy(skb_put(ch->rx_skb, len), data, len);
if (test_bit(FLG_HDLC, &ch->Flags)) {
@ -1026,17 +928,6 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, unsigned int len, int finish)
if ((ch->rx_skb->len > 3) &&
(!(ch->rx_skb->data[ch->rx_skb->len - 1]))) {
if ((ch->debug) && (debug & DEBUG_HFC_FIFO)) {
mISDN_debugprint(&ch->inst,
"fifon(%i) new RX len(%i): ",
fifon, ch->rx_skb->len);
i = 0;
printk(" ");
while (i < ch->rx_skb->len)
printk("%02x ", ch->rx_skb->data[i++]);
printk("\n");
}
/* remove CRC & status */
skb_trim(ch->rx_skb, ch->rx_skb->len - 3);
@ -1055,23 +946,13 @@ collect_rx_frame(usb_fifo * fifo, __u8 * data, unsigned int len, int finish)
ch->rx_skb = NULL;
}
queue_ch_frame(ch, INDICATION, MISDN_ID_ANY, skb);
} else {
printk ("HFC-S USB: CRC or minlen ERROR fifon(%i) RX len(%i): ",
fifon, ch->rx_skb->len);
if (ch->debug) {
i = 0;
printk(" ");
while (i < ch->rx_skb->len)
printk("%02x ", ch->rx_skb->data[i++]);
printk("\n");
}
skb_trim(ch->rx_skb, 0);
printk ("HFC-S USB: CRC or minlen ERROR\n");
}
}
} else {
if (finish || ch->rx_skb->len >= poll) {
printk(KERN_DEBUG "%s: queueing transp data fifon(%i) (%i)\n", __FUNCTION__, fifon, ch->rx_skb->len);
if (ch->rx_skb->len >= TRANSP_PACKET_SIZE) {
/* deliver transparent data to layer2 */
queue_ch_frame(ch, INDICATION, MISDN_ID_ANY, ch->rx_skb);
ch->rx_skb = NULL;
@ -1125,9 +1006,7 @@ rx_iso_complete(struct urb *urb, struct pt_regs *regs)
if (fifo->active && !status) {
num_isoc_packets = iso_packets[fifon];
maxlen = fifo->usb_packet_maxlen;
for (k = 0; k < num_isoc_packets; ++k) {
len = urb->iso_frame_desc[k].actual_length;
offset = urb->iso_frame_desc[k].offset;
buf = context_iso_urb->buffer + offset;
@ -1138,17 +1017,6 @@ rx_iso_complete(struct urb *urb, struct pt_regs *regs)
"HFC-S USB: ISO packet failure - status:%x",
iso_status);
/*
USB data log for every ISO in:
if (fifon == 1) {
printk ("(%d/%d) len(%d) ", k, num_isoc_packets-1, len);
for (i=0; i<len; i++) {
printk ("%x ", buf[i]);
}
printk ("\n");
}
*/
if (fifo->last_urblen != maxlen) {
/* the threshold mask is in the 2nd status byte */
card->threshold_mask = buf[1];
@ -1182,7 +1050,7 @@ rx_iso_complete(struct urb *urb, struct pt_regs *regs)
errcode = usb_submit_urb(urb, GFP_ATOMIC);
if (errcode < 0) {
printk(KERN_INFO
"HFC-S USB: error submitting ISO URB: %d\n",
"HFC-S USB: error submitting ISO URB: %d \n",
errcode);
}
} else {
@ -1214,7 +1082,7 @@ rx_int_complete(struct urb *urb, struct pt_regs *regs)
fifon = fifo->fifonum;
if ((!fifo->active) || (urb->status)) {
printk(KERN_INFO
"HFC-S USB: RX-Fifo %i is going down (%i)\n", fifon,
"HFC-S USB: RX-Fifo %i is going down (%i)", fifon,
urb->status);
fifo->urb->interval = 0; /* cancel automatic rescheduling */
@ -1223,18 +1091,7 @@ rx_int_complete(struct urb *urb, struct pt_regs *regs)
len = urb->actual_length;
buf = fifo->buffer;
maxlen = fifo->usb_packet_maxlen;
/*
USB data log for every INT in:
if (fifon == 1) {
printk ("fifon %d len %d: ", fifon, len);
for (i=0; i<len; i++) {
printk ("%x ", buf[i]);
}
printk ("\n");
}
*/
if (fifo->last_urblen != fifo->usb_packet_maxlen) {
/* the threshold mask is in the 2nd status byte */
card->threshold_mask = buf[1];
@ -1269,7 +1126,6 @@ rx_int_complete(struct urb *urb, struct pt_regs *regs)
int
next_tx_frame(hfcsusb_t * hw, __u8 channel)
{
int i;
channel_t *ch = &hw->chan[channel];
if (ch->tx_skb)
@ -1281,19 +1137,6 @@ next_tx_frame(hfcsusb_t * hw, __u8 channel)
ch->next_skb = NULL;
test_and_clear_bit(FLG_TX_NEXT, &ch->Flags);
ch->tx_idx = 0;
/* channel data debug: */
if ((ch->debug) && (debug & DEBUG_HFC_FIFO)) {
mISDN_debugprint(&ch->inst,
"new TX channel(%i) len(%i): ",
ch->channel, ch->tx_skb->len);
i = 0;
printk(" ");
while (i < ch->tx_skb->len)
printk("%02x ", ch->tx_skb->data[i++]);
printk(" (TX_NEXT)\n");
}
queue_ch_frame(ch, CONFIRM, hh->dinfo, NULL);
return (1);
} else {
@ -1322,7 +1165,6 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
int k, tx_offset, num_isoc_packets, sink, remain, current_len,
errcode;
int frame_complete, fifon, status;
int i;
__u8 threshbit;
__u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 };
@ -1350,16 +1192,14 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
sizeof(context_iso_urb->buffer));
frame_complete = 0;
/* Generate next Iso Packets */
for (k = 0; k < num_isoc_packets; ++k) {
if (ch->tx_skb) {
if (ch->tx_skb) {
remain = ch->tx_skb->len - ch->tx_idx;
} else {
remain = 0;
}
if (remain > 0) {
if (remain>0) {
/* we lower data margin every msec */
fifo->bit_line -= sink;
current_len = (0 - fifo->bit_line) / 8;
@ -1391,19 +1231,6 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
/* define packet delimeters within the URB buffer */
urb->iso_frame_desc[k].offset = tx_offset;
urb->iso_frame_desc[k].length = current_len + 1;
// USB data log for every ISO out
if (fifon == HFCUSB_D_TX) {
printk ("D ISO TX (%d/%d) offset(%d) len(%d) ", k, num_isoc_packets-1,
urb->iso_frame_desc[k].offset,
urb->iso_frame_desc[k].length);
for (i=urb->iso_frame_desc[k].offset; i<(urb->iso_frame_desc[k].offset + urb->iso_frame_desc[k].length); i++) {
printk ("%x ", context_iso_urb->buffer[i]);
}
printk (" skb->len(%i) tx-idx(%d)\n", ch->tx_skb->len, ch->tx_idx);
}
tx_offset += (current_len + 1);
} else {
@ -1417,10 +1244,8 @@ tx_iso_complete(struct urb *urb, struct pt_regs *regs)
}
}
if (frame_complete) {
if (frame_complete)
next_tx_frame(card, fifo->ch_idx);
frame_complete = 0;
}
}
errcode = usb_submit_urb(urb, GFP_ATOMIC);
@ -1615,32 +1440,22 @@ setup_hfcsusb(hfcsusb_t * card)
fifo[i].max_size =
(i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
fifo[i].last_urblen = 0;
/* set 2 bit for D- & E-channel */
write_usb(card, HFCUSB_HDLC_PAR,
((i <= HFCUSB_B2_RX) ? 0 : 2));
/* enable all fifos */
if (i == HFCUSB_D_TX) {
// enable Interframe Fill for DChannel TX in TE Mode
write_usb(card, HFCUSB_CON_HDLC, (card->portmode & PORT_MODE_NT) ? 0x08 : 0x09);
// write_usb(card, HFCUSB_CON_HDLC, 0x08);
} else {
write_usb(card, HFCUSB_CON_HDLC, 0x08);
}
/* rx hdlc, enable IFF for D-channel */
write_usb(card, HFCUSB_CON_HDLC,
((i == HFCUSB_D_TX) ? 0x09 : 0x08));
write_usb(card, HFCUSB_INC_RES_F, 2); /* reset the fifo */
}
if (card->portmode & PORT_MODE_NT) {
write_usb(card, HFCUSB_SCTRL, 0x44); /* disable B transmitters + capacitive mode, enable NT mode */
write_usb(card, HFCUSB_SCTRL_E, 0x09);
write_usb(card, HFCUSB_CLKDEL, CLKDEL_NT); /* clock delay value */
write_usb(card, HFCUSB_STATES, 1 | 0x10); /* set deactivated mode */
write_usb(card, HFCUSB_STATES, 1); /* enable state machine */
} else {
write_usb(card, HFCUSB_SCTRL, 0x40); /* disable B transmitters + capacitive mode, enable TE mode */
write_usb(card, HFCUSB_SCTRL_E, 0x00);
write_usb(card, HFCUSB_CLKDEL, CLKDEL_TE); /* clock delay value */
write_usb(card, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
write_usb(card, HFCUSB_STATES, 3); /* enable state machine */
@ -1732,7 +1547,7 @@ release_card(hfcsusb_t * card)
mISDN_freechannel(&card->chan[B1]);
mISDN_freechannel(&card->chan[B2]);
mISDN_freechannel(&card->chan[D]);
mISDN_ctrl(&card->chan[D].inst, MGR_UNREGLAYER | REQUEST, NULL);
hw_mISDNObj.ctrl(&card->chan[D].inst, MGR_UNREGLAYER | REQUEST, NULL);
spin_lock_irqsave(&hw_mISDNObj.lock, flags);
list_del(&card->list);
@ -1783,9 +1598,6 @@ setup_instance(hfcsusb_t * card)
spin_unlock_irqrestore(&hw_mISDNObj.lock, flags);
card->chan[D].debug = debug;
spin_lock_init(&card->ctrl_lock);
spin_lock_init(&card->lock);
/* link card->fifos[] to card->chan[] */
card->fifos[HFCUSB_D_RX].ch_idx = D;
card->fifos[HFCUSB_D_TX].ch_idx = D;
@ -1798,7 +1610,7 @@ setup_instance(hfcsusb_t * card)
card->chan[D].channel = D;
card->chan[D].state = 0;
card->chan[D].inst.hwlock = &card->lock;
card->chan[D].inst.hwlock = NULL;
card->chan[D].inst.pid.layermask = ISDN_LAYER(0);
card->chan[D].inst.pid.protocol[0] = ISDN_PID_L0_TE_S0;
card->chan[D].inst.class_dev.dev = &card->dev->dev;
@ -1813,7 +1625,7 @@ setup_instance(hfcsusb_t * card)
card->chan[i].channel = i;
mISDN_init_instance(&card->chan[i].inst, &hw_mISDNObj, card, hfcsusb_l2l1);
card->chan[i].inst.pid.layermask = ISDN_LAYER(0);
card->chan[i].inst.hwlock = &card->lock;
card->chan[i].inst.hwlock = NULL;
card->chan[i].inst.class_dev.dev = &card->dev->dev;
card->chan[i].debug = debug;
sprintf(card->chan[i].inst.name, "%s B%d",
@ -1867,31 +1679,31 @@ setup_instance(hfcsusb_t * card)
return (err);
}
hfcsusb_cnt++;
err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->chan[D].inst);
err = hw_mISDNObj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->chan[D].inst);
if (err) {
release_card(card);
return (err);
}
for (i = B1; i <= B2; i++) {
err = mISDN_ctrl(card->chan[D].inst.st,
err = hw_mISDNObj.ctrl(card->chan[D].inst.st,
MGR_NEWSTACK | REQUEST, &card->chan[i].inst);
if (err) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
mISDN_ctrl(card->chan[D].inst.st, MGR_DELSTACK | REQUEST, NULL);
hw_mISDNObj.ctrl(card->chan[D].inst.st, MGR_DELSTACK | REQUEST, NULL);
return (err);
}
setup_bchannel(&card->chan[i], -1);
}
if (debug)
printk(KERN_DEBUG "%s lm %x\n", __FUNCTION__, pid.layermask);
err = mISDN_ctrl(card->chan[D].inst.st, MGR_SETSTACK | REQUEST, &pid);
err = hw_mISDNObj.ctrl(card->chan[D].inst.st, MGR_SETSTACK | REQUEST, &pid);
if (err) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
mISDN_ctrl(card->chan[D].inst.st, MGR_DELSTACK | REQUEST, NULL);
hw_mISDNObj.ctrl(card->chan[D].inst.st, MGR_DELSTACK | REQUEST, NULL);
return (err);
}
mISDN_ctrl(card->chan[D].inst.st, MGR_CTRLREADY | INDICATION, NULL);
hw_mISDNObj.ctrl(card->chan[D].inst.st, MGR_CTRLREADY | INDICATION, NULL);
usb_set_intfdata(card->intf, card);
return (0);
}
@ -2112,7 +1924,7 @@ hfcsusb_disconnect(struct usb_interface *intf)
if (debug & 0x10000)
printk(KERN_DEBUG "%s\n", __FUNCTION__);
card->disc_flag = 1;
mISDN_ctrl(card->chan[D].inst.st, MGR_DELSTACK | REQUEST, NULL);
hw_mISDNObj.ctrl(card->chan[D].inst.st, MGR_DELSTACK | REQUEST, NULL);
// release_card(card);
usb_set_intfdata(intf, NULL);
} /* hfcsusb_disconnect */
@ -2122,6 +1934,7 @@ hfcsusb_disconnect(struct usb_interface *intf)
/* our driver information structure */
/************************************/
static struct usb_driver hfcsusb_drv = {
.owner = THIS_MODULE,
.name = DRIVER_NAME,
.id_table = hfcsusb_idtab,
.probe = hfcsusb_probe,
@ -2134,7 +1947,6 @@ hfcsusb_init(void)
{
int err;
// debug = 0xFFFF;
printk(KERN_INFO "hfcsusb driver Rev. %s (debug=%i)\n",
mISDN_getrev(hfcsusb_rev), debug);
@ -2163,9 +1975,6 @@ hfcsusb_init(void)
"hfcsusb: Unable to register hfcsusb module at usb stack\n");
goto out;
}
mISDN_module_register(THIS_MODULE);
return 0;
out:
@ -2179,8 +1988,6 @@ hfcsusb_cleanup(void)
int err;
hfcsusb_t *card, *next;
mISDN_module_unregister(THIS_MODULE);
if (debug & 0x10000)
printk(KERN_DEBUG "%s\n", __FUNCTION__);

View File

@ -10,15 +10,7 @@
#define DRIVER_AUTHOR "Martin Bachem / Peter Sprenger"
#define DRIVER_DESC "HFC-S USB based HiSAX ISDN driver"
/* DEBUG flags, use combined value for module parameter debug=x */
#define DEBUG_HFC_INIT 0x0001
#define DEBUG_HFC_MODE 0x0002
#define DEBUG_HFC_S0_STATES 0x0004
#define DEBUG_HFC_IRQ 0x0008
#define DEBUG_HFC_FIFO_ERR 0x0010
#define DEBUG_HFC_DTRACE 0x2000
#define DEBUG_HFC_BTRACE 0x4000 /* very(!) heavy messageslog load */
#define DEBUG_HFC_FIFO 0x8000 /* very(!) heavy messageslog load */
#define VERBOSE_USB_DEBUG
/***********/
@ -106,6 +98,7 @@
#define ISOC_PACKETS_D 8
#define ISOC_PACKETS_B 8
#define ISO_BUFFER_SIZE 128
#define TRANSP_PACKET_SIZE 0
/* defines how much ISO packets are handled in one URB */
static int iso_packets[8] =

View File

@ -10,6 +10,7 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/isdnif.h>
#include <linux/delay.h>
@ -156,7 +157,7 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
module_param(debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM(debug, "1i");
#endif
static void
@ -216,7 +217,7 @@ init_channel(i4l_capi_t *ic, int nr)
ch->inst.pid.layermask = ISDN_LAYER(0);
ch->inst.up.owner = &ch->inst;
ch->inst.down.owner = &ch->inst;
mISDN_ctrl(NULL, MGR_DISCONNECT | REQUEST, &ch->inst.down);
I4Lcapi.ctrl(NULL, MGR_DISCONNECT | REQUEST, &ch->inst.down);
sprintf(ch->inst.name, "%s B%d", ic->inst.name, nr+1);
}
@ -1127,10 +1128,10 @@ static int
i4l_stat_run(i4l_capi_t *ic) {
int err;
err = mISDN_ctrl(ic->inst.st, MGR_SETSTACK | REQUEST, &ic->pid);
err = I4Lcapi.ctrl(ic->inst.st, MGR_SETSTACK | REQUEST, &ic->pid);
if (err) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
mISDN_ctrl(ic->inst.st, MGR_DELSTACK | REQUEST, NULL);
I4Lcapi.ctrl(ic->inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
return(0);
@ -1289,7 +1290,7 @@ I4Lcapi_status_callback(isdn_ctrl *c)
ret = 0;
break;
case ISDN_STAT_UNLOAD:
ret = mISDN_ctrl(drv->inst.st, MGR_DELSTACK | REQUEST, NULL);
ret = I4Lcapi.ctrl(drv->inst.st, MGR_DELSTACK | REQUEST, NULL);
MOD_DEC_USE_COUNT;
break;
case CAPI_PUT_MESSAGE:
@ -1354,8 +1355,8 @@ I4Lcapi_manager(void *data, u_int prim, void *arg) {
case MGR_REGLAYER | CONFIRM:
break;
case MGR_UNREGLAYER | REQUEST:
mISDN_ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
I4Lcapi.ctrl(inst->up.peer, MGR_DISCONNECT | REQUEST, &inst->up);
I4Lcapi.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_RELEASE | INDICATION:
if (nr_ch == -1) {
@ -1445,17 +1446,17 @@ I4Lcapi_register(isdn_if *iif)
for (i=0; i < drvmap[drvidx]->nr_ch; i++) {
init_channel(drvmap[drvidx], i);
}
err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &drvmap[drvidx]->inst);
err = I4Lcapi.ctrl(NULL, MGR_NEWSTACK | REQUEST, &drvmap[drvidx]->inst);
if (err) {
release_card(drvidx);
return(err);
}
ch = drvmap[drvidx]->ch;
for (i=0; i < drvmap[drvidx]->nr_ch; i++) {
err = mISDN_ctrl(drvmap[drvidx]->inst.st, MGR_NEWSTACK | REQUEST, &ch->inst);
err = I4Lcapi.ctrl(drvmap[drvidx]->inst.st, MGR_NEWSTACK | REQUEST, &ch->inst);
if (err) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
mISDN_ctrl(drvmap[drvidx]->inst.st, MGR_DELSTACK | REQUEST, NULL);
I4Lcapi.ctrl(drvmap[drvidx]->inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
ch++;

View File

@ -8,7 +8,6 @@
*/
#include <linux/module.h>
#include "core.h"
#include "channel.h"
#include "isac.h"
#include "arcofi.h"
@ -824,13 +823,11 @@ mISDN_clear_isac(channel_t *dch)
static int isac_mod_init(void)
{
printk(KERN_INFO "ISAC module %s\n", isac_revision);
mISDN_module_register(THIS_MODULE);
return(0);
}
static void isac_mod_cleanup(void)
{
mISDN_module_unregister(THIS_MODULE);
printk(KERN_INFO "ISAC module unloaded\n");
}
module_init(isac_mod_init);

View File

@ -1656,8 +1656,7 @@ isar_down(mISDNinstance_t *inst, struct sk_buff *skb)
spin_unlock_irqrestore(inst->hwlock, flags);
skb_trim(skb, 0);
if (hh->prim != (PH_CONTROL | REQUEST))
if (!mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb))
return(0);
ret = mISDN_queueup_newhead(inst, 0, hh->prim | CONFIRM, 0, skb);
} else if (hh->prim == (PH_CONTROL | REQUEST)) {
int *val;
int len;

View File

@ -4,7 +4,7 @@
*
* NOTE: It is not compatible with TDMoIP nor "ISDN over IP".
*
* Author Andreas Eversberg (jolly@eversberg.eu)
* Author Andreas Eversberg (jolly@jolly.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
@ -207,6 +207,7 @@ announced.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
@ -237,6 +238,7 @@ static char l1oipName[] = "Layer1oIP";
/****************/
#define MAX_CARDS 16
#define MODULE_CARDS_T "1-16i"
static u_int type[MAX_CARDS];
static u_int codec[MAX_CARDS];
static u_int protocol[MAX_CARDS];
@ -248,11 +250,11 @@ MODULE_AUTHOR("Andreas Eversberg");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(codec, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(protocol, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, NULL, S_IRUGO | S_IWUSR);
module_param(debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM(type, MODULE_CARDS_T);
MODULE_PARM(codec, MODULE_CARDS_T);
MODULE_PARM(protocol, MODULE_CARDS_T);
MODULE_PARM(layermask, MODULE_CARDS_T);
MODULE_PARM(debug, "1i");
#endif
@ -704,7 +706,7 @@ l1oip_manager(void *data, u_int prim, void *arg)
if (hfcmulti_l2l1(inst, skb)) dev_kfree_skb(skb);
}
}
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
HFCM_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
@ -798,7 +800,7 @@ release_card(hfc_multi_t *hc)
if (debug & DEBUG_L1OIP_INIT)
printk(KERN_DEBUG "%s: free port %d D-channel %d (1..32)\n", __FUNCTION__, hc->chan[i].port, i);
mISDN_free_dch(hc->chan[i].dch);
mISDN_ctrl(&hc->chan[i].dch->inst, MGR_UNREGLAYER | REQUEST, NULL);
HFCM_obj.ctrl(&hc->chan[i].dch->inst, MGR_UNREGLAYER | REQUEST, NULL);
kfree(hc->chan[i].dch);
hc->chan[i].dch = NULL;
}
@ -1105,7 +1107,7 @@ l1oip_init(void)
/* add stacks */
if (debug & DEBUG_L1OIP_INIT)
printk(KERN_DEBUG "%s: Adding d-stack: card(%d)\n", __FUNCTION__, l1oip_cnt+1);
if ((ret_err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &dch->inst))) {
if ((ret_err = l1oip_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &dch->inst))) {
printk(KERN_ERR "MGR_ADDSTACK REQUEST dch err(%d)\n", ret_err);
free_release:
release_network(hc);
@ -1117,10 +1119,10 @@ l1oip_init(void)
bch = hc->bch;
if (debug & DEBUG_L1OIP_INIT)
printk(KERN_DEBUG "%s: Adding b-stack: card(%d) B-channel(%d)\n", __FUNCTION__, l1oip_cnt+1, bch->channel);
if ((ret_err = mISDN_ctrl(dst, MGR_NEWSTACK | REQUEST, &bch->inst))) {
if ((ret_err = l1oip_obj.ctrl(dst, MGR_NEWSTACK | REQUEST, &bch->inst))) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", ret_err);
free_delstack:
mISDN_ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
l1oip_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
goto free_release;
}
bch->st = bch->inst.st;
@ -1129,7 +1131,7 @@ l1oip_init(void)
if (debug & DEBUG_L1OIP_INIT)
printk(KERN_DEBUG "%s: (before MGR_SETSTACK REQUEST) layermask=0x%x\n", __FUNCTION__, pids[pt].layermask);
if ((ret_err = mISDN_ctrl(dst, MGR_SETSTACK | REQUEST, &pids[pt]))) {
if ((ret_err = l1oip_obj.ctrl(dst, MGR_SETSTACK | REQUEST, &pids[pt]))) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", ret_err);
goto free_delstack;
}
@ -1141,7 +1143,7 @@ l1oip_init(void)
schedule_timeout((100*HZ)/1000); /* Timeout 100ms */
/* tell stack, that we are ready */
mISDN_ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
l1oip_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
HFC_cnt++;
goto next_card;

View File

@ -15,7 +15,6 @@
#include <linux/module.h>
#include "core.h"
#include "layer3.h"
#include "helper.h"
#include "debug.h"
@ -27,10 +26,6 @@ static mISDNobject_t u_dss1;
const char *dss1_revision = "$Revision$";
static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
static int dss1man(l3_process_t *, u_int, void *);
static int
@ -81,8 +76,6 @@ parseQ931(struct sk_buff *skb) {
codeset = maincodeset = 0;
ie = &qi->bearer_capability;
while (pos < len) {
if ((p[pos] & 0xf0) == 0x90) {
codeset = p[pos] & 0x07;
if (!(p[pos] & 0x08))
@ -98,14 +91,10 @@ parseQ931(struct sk_buff *skb) {
if (p[pos] & 0x80) { /* single octett IE */
if (p[pos] == IE_MORE_DATA)
qi->more_data.off = pos;
else if (p[pos] == IE_COMPLETE) {
else if (p[pos] == IE_COMPLETE)
qi->sending_complete.off = pos;
}
else if ((p[pos] & 0xf0) == IE_CONGESTION)
qi->congestion_level.off = pos;
else {
printk("parseQ931: Unknown Single Oct IE [%x]\n",p[pos]);
}
cnt++;
pos++;
} else {
@ -139,15 +128,6 @@ parseQ931(struct sk_buff *skb) {
qi->ext[eidx].v.val = t;
eidx = -1;
}
} else {
int i;
for (i=0; comp_required[i] > 0; i++) {
if ( p[pos] == comp_required[i] && l==1 ) {
qi->comprehension_required.off = pos;
}
}
if (!qi->comprehension_required.off)
printk(" ie not handled ie [%x] l [%x]\n", p[pos],l);
}
pos += l + 2;
cnt++;
@ -205,7 +185,7 @@ calc_msg_len(Q931_info_t *qi)
if (qi->congestion_level.off)
cnt++;
ie = &qi->bearer_capability;
while (ie <= &qi->comprehension_required) {
while (ie <= &qi->fill1) {
if (ie->off)
cnt += buf[ie->off + 1] + 2;
ie++;
@ -245,7 +225,7 @@ compose_msg(struct sk_buff *skb, Q931_info_t *qi)
*p = buf[qi->congestion_level.off];
}
ie = &qi->bearer_capability;
for (i=0; i<33; i++) {
for (i=0; i<32; i++) {
if (ie[i].off) {
l = buf[ie[i].off + 1] +1;
p = skb_put(skb, l + 1);
@ -414,10 +394,10 @@ l3dss1_msg_without_setup(l3_process_t *pc, u_char cause)
}
static int ie_ALERTING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_REDIR_DN,
IE_HLC, IE_USER_USER, -1};
IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_SIGNAL, IE_HLC,
IE_USER_USER, -1};
static int ie_CALL_PROCEEDING[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_REDIR_DN, IE_HLC, -1};
IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_HLC, -1};
static int ie_CONNECT[] = {IE_BEARER, IE_CHANNEL_ID | IE_MANDATORY_1,
IE_FACILITY, IE_PROGRESS, IE_DISPLAY, IE_DATE, IE_SIGNAL,
IE_CONNECT_PN, IE_CONNECT_SUB, IE_LLC, IE_HLC, IE_USER_USER, -1};
@ -464,7 +444,7 @@ static int ie_RETRIEVE_REJECT[] = {IE_CAUSE | IE_MANDATORY, IE_DISPLAY, -1};
* IE_MANDATORY, -1};
*/
static int ie_FACILITY[] = {IE_FACILITY | IE_MANDATORY, IE_DISPLAY, -1};
static int comp_required[] = {1,2,3,5,6,7,9,10,11,14,15,-1};
static int l3_valid_states[] = {0,1,2,3,4,6,7,8,9,10,11,12,15,17,19,25,-1};
struct ie_len {
@ -501,7 +481,6 @@ struct ie_len max_ie_len[] = {
{IE_CALLED_PN, 24},
{IE_CALLED_SUB, 23},
{IE_REDIR_NR, 255},
{IE_REDIR_DN, 255},
{IE_TRANS_SEL, 255},
{IE_RESTART_IND, 3},
{IE_LLC, 18},
@ -552,8 +531,7 @@ check_infoelements(l3_process_t *pc, struct sk_buff *skb, int *checklist)
p += L3_EXTRA_SIZE;
iep = &qi->bearer_capability;
oldpos = -1;
for (i=0; i<33; i++) {
for (i=0; i<32; i++) {
if (iep[i].off) {
ie = mISDN_l3_pos2ie(i);
if ((newpos = ie_in_set(pc, ie, cl))) {
@ -562,11 +540,8 @@ check_infoelements(l3_process_t *pc, struct sk_buff *skb, int *checklist)
err_seq++;
else
oldpos = newpos;
} else {
printk(KERN_NOTICE "ie_in_set returned <0 [%d] ie:[%x]\n",newpos,ie);
}
} else {
if (debug) printk(KERN_NOTICE "Found ie in set which we do not support ie [%x]\n",ie);
if (ie_in_set(pc, ie, comp_required))
err_compr++;
else
@ -577,13 +552,6 @@ check_infoelements(l3_process_t *pc, struct sk_buff *skb, int *checklist)
err_len++;
}
}
if (qi->comprehension_required.off) {
if ( ! (p[qi->comprehension_required.off +2] &0xf) ) {
err_compr++;
}
}
if (err_compr | err_ureg | err_len | err_seq) {
if (pc->l3->debug & L3_DEB_CHECK)
l3_debug(pc->l3, "check IE MT(%x) %d/%d/%d/%d",
@ -683,7 +651,6 @@ l3dss1_get_channel_id(l3_process_t *pc, struct sk_buff *skb) {
if (test_bit(FLG_EXTCID, &pc->l3->Flag)) {
if (*p != 1) {
pc->bc = 1;
pc->real_bc=p[3];
return (0);
}
}
@ -699,7 +666,6 @@ l3dss1_get_channel_id(l3_process_t *pc, struct sk_buff *skb) {
return (-3);
}
pc->bc = *p & 3;
pc->real_bc=pc->bc;
} else
return(-1);
return(0);
@ -785,17 +751,11 @@ l3dss1_disconnect_req(l3_process_t *pc, u_char pr, void *arg)
*p++ = 2;
*p++ = 0x80 | CAUSE_LOC_USER;
*p++ = 0x80 | CAUSE_NORMALUNSPECIFIED;
pc->cause=CAUSE_NORMALUNSPECIFIED;
} else {
p=skb->data;
p += L3_EXTRA_SIZE + qi->cause.off;
pc->cause = (*(p+3) & 0x7f);
}
SendMsg(pc, arg, 11);
} else {
newl3state(pc, 11);
l3dss1_message_cause(pc, MT_DISCONNECT, CAUSE_NORMALUNSPECIFIED);
pc->cause=CAUSE_NORMALUNSPECIFIED;
}
L3AddTimer(&pc->timer, T305, CC_T305);
}
@ -939,14 +899,6 @@ l3dss1_facility_req(l3_process_t *pc, u_char pr, void *arg)
}
}
static void
l3dss1_restart_req(l3_process_t *pc, u_char pr, void *arg)
{
if (arg) {
SendMsg(pc, arg, -1);
}
}
static void
l3dss1_release_cmpl(l3_process_t *pc, u_char pr, void *arg)
{
@ -1092,8 +1044,6 @@ l3dss1_disconnect(l3_process_t *pc, u_char pr, void *arg)
else
cause = CAUSE_INVALID_CONTENTS;
}
else if (pc->state == 7) /* Call Received*/
cause = pc->err;
ret = check_infoelements(pc, skb, ie_DISCONNECT);
if (ERR_IE_COMPREHENSION == ret)
cause = CAUSE_MANDATORY_IE_MISS;
@ -1469,29 +1419,22 @@ l3dss1_release_ind(l3_process_t *pc, u_char pr, void *arg)
int err, callState = -1;
Q931_info_t *qi = (Q931_info_t *)skb->data;
if (pc->state == 19) {
/* ETS 300-102 5.3.5 */
if (qi->call_state.off) {
p = skb->data;
p += L3_EXTRA_SIZE + qi->call_state.off;
p++;
if (1 == *p++)
callState = *p;
}
if (callState == 0) {
/* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
* set down layer 3 without sending any message
*/
newl3state(pc, 0);
err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
release_l3_process(pc);
} else {
if (qi->call_state.off) {
p = skb->data;
p += L3_EXTRA_SIZE + qi->call_state.off;
p++;
if (1 == *p++)
callState = *p;
}
if (callState == 0) {
/* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1
* set down layer 3 without sending any message
*/
newl3state(pc, 0);
err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
release_l3_process(pc);
} else {
err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
}
err = mISDN_l3up(pc, CC_RELEASE | INDICATION, skb);
}
if (err)
dev_kfree_skb(skb);
@ -1707,11 +1650,10 @@ l3dss1_resume_rej(l3_process_t *pc, u_char pr, void *arg)
static void
l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
{
u_char *p=NULL, *cp=NULL, ri, ch = 0, chan = 0, chan_len=0;
u_char *p, ri, ch = 0, chan = 0;
struct sk_buff *skb = arg;
Q931_info_t *qi = (Q931_info_t *)skb->data;
l3_process_t *up, *n;
int i=0;
// newl3state(pc, 2);
L3DelTimer(&pc->timer);
@ -1728,57 +1670,26 @@ l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
if (qi->channel_id.off) {
p = skb->data;
p += L3_EXTRA_SIZE + qi->channel_id.off;
cp=p;
p++;
chan_len=p[0];
if (chan_len==1) {
chan = p[1] & 0x3;
ch = p[1];
} else {
chan = p[3];
ch = p[1];
}
chan = p[1] & 3;
ch = p[1];
if (pc->l3->debug)
l3_debug(pc->l3, "Restart for channel %d", chan);
}
list_for_each_entry_safe(up, n, &pc->l3->plist, list) {
if ((ri & 7) == 7)
dss1man(up, CC_RESTART | REQUEST, NULL);
else if (up->real_bc == chan) {
else if (up->bc == chan)
mISDN_l3up(up, CC_RESTART | REQUEST, NULL);
l3_debug(up->l3, "Resetting channel\n");
release_l3_process(up);
}
}
dev_kfree_skb(skb);
switch(chan_len) {
case 0:
skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, 3);
p = skb_put(skb, 3);
break;
case 1:
skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, 6);
p = skb_put(skb, 6);
if (chan) {
*p++ = IE_CHANNEL_ID;
*p++ = 1;
*p++ = ch | 0x80;
}
break;
case 3:
skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, 8);
p = skb_put(skb, 8);
/*copy channel ie*/
for (i=0; i<5; i++)
*p++ = *cp++;
break;
skb = MsgStart(pc, MT_RESTART_ACKNOWLEDGE, chan ? 6 : 3);
p = skb_put(skb, chan ? 6 : 3);
if (chan) {
*p++ = IE_CHANNEL_ID;
*p++ = 1;
*p++ = ch | 0x80;
}
*p++ = IE_RESTART_IND;
*p++ = 1;
*p++ = ri;
@ -1786,13 +1697,6 @@ l3dss1_global_restart(l3_process_t *pc, u_char pr, void *arg)
kfree_skb(skb);
}
static void
l3dss1_restart_ack(l3_process_t *pc, u_char pr, void *arg)
{
printk(KERN_NOTICE "Restart Acknowledge\n");
}
static void
l3dss1_dummy(l3_process_t *pc, u_char pr, void *arg)
{
@ -2235,21 +2139,13 @@ l3dss1_t304(l3_process_t *pc, u_char pr, void *arg)
static void
l3dss1_t305(l3_process_t *pc, u_char pr, void *arg)
{
int cause;
L3DelTimer(&pc->timer);
if (pc->cause != NO_CAUSE) {
printk(KERN_NOTICE "Using buffered cause %x\n",pc->cause);
#if 0
if (pc->cause != NO_CAUSE)
cause = pc->cause;
}
else {
cause=CAUSE_NORMAL_CLEARING;
}
#endif
newl3state(pc, 19);
l3dss1_message_cause(pc, MT_RELEASE, cause);
l3dss1_message_cause(pc, MT_RELEASE, CAUSE_NORMALUNSPECIFIED);
L3AddTimer(&pc->timer, T308, CC_T308_1);
}
@ -2385,7 +2281,7 @@ static struct stateentry downstatelist[] =
{SBIT(1) | SBIT(2) | SBIT(3) | SBIT(4) | SBIT(6) | SBIT(7) |
SBIT(8) | SBIT(9) | SBIT(10) | SBIT(25),
CC_DISCONNECT | REQUEST, l3dss1_disconnect_req},
{SBIT(6) | SBIT(11) | SBIT(12),
{SBIT(11) | SBIT(12),
CC_RELEASE | REQUEST, l3dss1_release_req},
{ALL_STATES,
CC_RESTART | REQUEST, l3dss1_restart},
@ -2507,8 +2403,9 @@ static struct stateentry globalmes_list[] =
MT_STATUS, l3dss1_status},
{SBIT(0),
MT_RESTART, l3dss1_global_restart},
{SBIT(1),
/* {SBIT(1),
MT_RESTART_ACKNOWLEDGE, l3dss1_restart_ack},
*/
};
#define GLOBALM_LEN \
(sizeof(globalmes_list) / sizeof(struct stateentry))
@ -2648,17 +2545,12 @@ dss1_fromdown(layer3_t *l3, struct sk_buff *skb, mISDN_head_t *hh)
if (l3->debug & L3_DEB_STATE)
l3_debug(l3, "dss1up cr %d", qi->cr);
if (qi->crlen == 0) { /* Dummy Callref */
switch(qi->type) {
case MT_FACILITY:
l3dss1_facility(l3->dummy, hh->prim, skb);
if (qi->type == MT_FACILITY) {
l3dss1_facility(l3->dummy, hh->prim, skb);
return(0);
default:
if (l3->debug & L3_DEB_WARN)
l3_debug(l3, "dss1up dummy Callref (no facility msg or ie)");
break;
}
} else if (l3->debug & L3_DEB_WARN)
l3_debug(l3, "dss1up dummy Callref (no facility msg or ie)");
dev_kfree_skb(skb);
return(0);
} else if ((qi->cr & 0x7fff) == 0) { /* Global CallRef */
if (l3->debug & L3_DEB_STATE)
@ -2733,9 +2625,6 @@ dss1_fromdown(layer3_t *l3, struct sk_buff *skb, mISDN_head_t *hh)
* if setup has not been made and a message type
* (except MT_SETUP and RELEASE_COMPLETE) is received,
* we must send MT_RELEASE_COMPLETE cause 81 */
printk("We got Message with Invalid Callref\n");
if ((proc = new_l3_process(l3, qi->cr, N303, MISDN_ID_ANY))) {
l3dss1_msg_without_setup(proc,
CAUSE_INVALID_CALLREF);
@ -2804,7 +2693,6 @@ dss1_fromup(layer3_t *l3, struct sk_buff *skb, mISDN_head_t *hh)
}
if ((l3->debug & L3_DEB_MSG) && skb->len)
mISDN_LogL3Msg(skb);
if (!proc && hh->dinfo == MISDN_ID_DUMMY) {
if (hh->prim == (CC_FACILITY | REQUEST)) {
l3dss1_facility_req(l3->dummy, hh->prim, skb->len ? skb : NULL);
@ -2812,28 +2700,9 @@ dss1_fromup(layer3_t *l3, struct sk_buff *skb, mISDN_head_t *hh)
}
return(ret);
}
if (!proc && hh->dinfo == MISDN_ID_GLOBAL) {
if (hh->prim == (CC_RESTART | REQUEST)) {
printk(KERN_NOTICE "Global Restart Req\n");
l3dss1_restart_req(l3->dummy, hh->prim, skb->len ? skb : NULL);
ret = 0;
}
return(ret);
}
if (!proc && (hh->prim == (CC_RELEASE_COMPLETE | REQUEST)) ) {
/* crich: */
if (l3->debug) l3_debug(l3, "mISDN dss1 sending RELEASE_COMPLETE without proc pr=%04x dinof(%x)", hh->prim, hh->dinfo);
SendMsg(l3->dummy, skb, -1);
return 0;
}
if (!proc) {
if(debug)
printk(KERN_ERR "mISDN dss1 fromup without proc pr=%04x dinfo(%x)\n",
hh->prim, hh->dinfo);
printk(KERN_ERR "mISDN dss1 fromup without proc pr=%04x dinfo(%x)\n",
hh->prim, hh->dinfo);
return(-EINVAL);
}
for (i = 0; i < DOWNSLLEN; i++)
@ -2845,11 +2714,11 @@ dss1_fromup(layer3_t *l3, struct sk_buff *skb, mISDN_head_t *hh)
l3_debug(l3, "dss1down state %d prim %#x unhandled",
proc->state, hh->prim);
}
dev_kfree_skb(skb);
dev_kfree_skb(skb);
} else {
if (l3->debug & L3_DEB_STATE) {
l3_debug(l3, "dss1down state %d prim %#x para len %d",
proc->state, hh->prim, skb->len);
proc->state, hh->prim, skb->len);
}
if (skb->len)
downstatelist[i].rout(proc, hh->prim, skb);
@ -2932,8 +2801,7 @@ release_udss1(layer3_t *l3)
mISDNinstance_t *inst = &l3->inst;
u_long flags;
if (debug)
printk(KERN_DEBUG "release_udss1 refcnt %d l3(%p) inst(%p)\n",
printk(KERN_DEBUG "release_udss1 refcnt %d l3(%p) inst(%p)\n",
u_dss1.refcnt, l3, inst);
release_l3(l3);
#ifdef FIXME
@ -2949,9 +2817,9 @@ release_udss1(layer3_t *l3)
spin_lock_irqsave(&u_dss1.lock, flags);
list_del(&l3->list);
spin_unlock_irqrestore(&u_dss1.lock, flags);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
u_dss1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
if (l3->entity != MISDN_ENTITY_NONE)
mISDN_ctrl(inst, MGR_DELENTITY | REQUEST, (void *)((u_long)l3->entity));
u_dss1.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)((u_long)l3->entity));
kfree(l3);
}
@ -3024,12 +2892,12 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
spin_lock_irqsave(&u_dss1.lock, flags);
list_add_tail(&nl3->list, &u_dss1.ilist);
spin_unlock_irqrestore(&u_dss1.lock, flags);
err = mISDN_ctrl(&nl3->inst, MGR_NEWENTITY | REQUEST, NULL);
err = u_dss1.ctrl(&nl3->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%d)\n",
__FUNCTION__, err);
}
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &nl3->inst);
err = u_dss1.ctrl(st, MGR_REGLAYER | INDICATION, &nl3->inst);
if (err) {
release_l3(nl3);
list_del(&nl3->list);
@ -3042,7 +2910,7 @@ new_udss1(mISDNstack_t *st, mISDN_pid_t *pid)
stp.maxdatalen = 0;
stp.up_headerlen = L3_EXTRA_SIZE;
stp.down_headerlen = 0;
mISDN_ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
u_dss1.ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
}
return(err);
}
@ -3054,11 +2922,7 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#endif
#endif
static int
@ -3141,8 +3005,7 @@ int UDSS1Init(void)
if ((err = mISDN_register(&u_dss1))) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
mISDNl3Free();
} else
mISDN_module_register(THIS_MODULE);
}
return(err);
}
@ -3152,8 +3015,6 @@ void UDSS1_cleanup(void)
int err;
layer3_t *l3, *next;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&u_dss1))) {
printk(KERN_ERR "Can't unregister User DSS1 error(%d)\n", err);
}

View File

@ -22,15 +22,14 @@ static signed char _mISDN_l3_ie2pos[128] = {
13,-1,14,15,16,17,18,19,-1,-1,-1,-1,20,21,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,23,-1,-1,
24,25,-1,-1,26,-1,27,-1,28,29,-1,-1,30,31,32,-1
24,25,-1,-1,26,-1,-1,-1,27,28,-1,-1,29,30,31,-1
};
static unsigned char _mISDN_l3_pos2ie[33] = {
static unsigned char _mISDN_l3_pos2ie[32] = {
0x04, 0x08, 0x10, 0x14, 0x18, 0x1c, 0x1e, 0x20,
0x27, 0x28, 0x29, 0x2c, 0x34, 0x40, 0x42, 0x43,
0x44, 0x45, 0x46, 0x47, 0x4c, 0x4d, 0x6c, 0x6d,
0x70, 0x71, 0x74, 0x76, 0x78, 0x79, 0x7c, 0x7d,
0x7e
0x70, 0x71, 0x74, 0x78, 0x79, 0x7c, 0x7d, 0x7e
};
signed int
@ -225,7 +224,7 @@ void mISDN_LogL3Msg(struct sk_buff *skb)
ps += L3_EXTRA_SIZE;
printk(KERN_DEBUG "L3Msg type(%02x) qi(%p) ies(%p) ps(%p)\n",
qi->type, qi, ies, ps);
for (i=0;i<33;i++) {
for (i=0;i<32;i++) {
if (ies[i].off) {
p = ps + ies[i].off;
t = tmp;

View File

@ -1,345 +0,0 @@
/*
* vISDN LAPD/q.921 protocol implementation
*
* Copyright (C) 2004-2006 Daniele Orlandi
*
* Authors: Daniele "Vihai" Orlandi <daniele@orlandi.com>
*
* This program is free software and may be modified and distributed
* under the terms and conditions of the GNU General Public License.
*
*/
#ifndef _LAPD_H
#define _LAPD_H
#include <linux/types.h>
#ifdef __KERNEL__
#include <linux/socket.h>
#else
#include <sys/socket.h>
#endif
#ifndef ARPHRD_LAPD
#define ARPHRD_LAPD 8445
#endif
#ifndef ETH_P_LAPD
#define ETH_P_LAPD 0x0030 /* LAPD pseudo type */
#endif
#ifndef AF_LAPD
#define AF_LAPD 30
#endif
#ifndef PF_LAPD
#define PF_LAPD AF_LAPD
#endif
#ifndef SOL_LAPD
#define SOL_LAPD 300
#endif
#define LAPD_SAPI_Q931 0x00
#define LAPD_SAPI_X25 0x0f
#define LAPD_SAPI_MGMT 0x10
#define LAPD_BROADCAST_TEI 127
#define LAPD_DYNAMIC_TEI 255
#define LAPD_DEV_IOC_ACTIVATE _IOR(0xd0, 0x00, unsigned int)
#define LAPD_DEV_IOC_DEACTIVATE _IOR(0xd0, 0x01, unsigned int)
enum
{
LAPD_INTF_TYPE = 0,
LAPD_INTF_MODE = 1,
LAPD_INTF_ROLE = 2,
LAPD_TEI = 3,
LAPD_SAPI = 4,
LAPD_TEI_MGMT_STATUS = 5,
LAPD_TEI_MGMT_T201 = 6,
LAPD_TEI_MGMT_N202 = 7,
LAPD_TEI_MGMT_T202 = 8,
LAPD_DLC_STATE = 9,
LAPD_T200 = 10,
LAPD_N200 = 11,
LAPD_T203 = 12,
LAPD_N201 = 13,
LAPD_K = 14,
};
enum lapd_intf_type
{
LAPD_INTF_TYPE_BRA = 0,
LAPD_INTF_TYPE_PRA = 1,
};
enum lapd_intf_mode
{
LAPD_INTF_MODE_POINT_TO_POINT = 0,
LAPD_INTF_MODE_MULTIPOINT = 1
};
enum lapd_intf_role
{
LAPD_INTF_ROLE_TE = 0,
LAPD_INTF_ROLE_NT = 1
};
struct sockaddr_lapd
{
sa_family_t sal_family;
__u8 sal_tei;
};
enum lapd_primitive_type
{
LAPD_PH_DATA_REQUEST = 1,
LAPD_PH_DATA_INDICATION,
LAPD_PH_ACTIVATE_INDICATION,
LAPD_PH_DEACTIVATE_INDICATION,
LAPD_PH_ACTIVATE_REQUEST,
LAPD_MPH_ERROR_INDICATION,
LAPD_MPH_ACTIVATE_INDICATION,
LAPD_MPH_DEACTIVATE_INDICATION,
LAPD_MPH_DEACTIVATE_REQUEST,
LAPD_MPH_INFORMATION_INDICATION,
};
enum lapd_mph_information_indication
{
LAPD_MPH_II_CONNECTED,
LAPD_MPH_II_DISCONNECTED,
};
struct lapd_prim_hdr
{
__u8 primitive_type;
__u8 reserved[3];
};
struct lapd_ctrl_hdr
{
__u8 param;
};
#ifdef __KERNEL__
#include <asm/atomic.h>
#include <linux/types.h>
#include <linux/netdevice.h>
#include <linux/version.h>
#include <net/sock.h>
#define lapd_MODULE_NAME "lapd"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#define LAPD_HASHBITS 8
#define LAPD_HASHSIZE ((1 << LAPD_HASHBITS) - 1)
#define LAPD_SK_STATE_NULL TCP_LAST_ACK
#define LAPD_SK_STATE_LISTEN TCP_LISTEN
#define LAPD_SK_STATE_NORMAL_DLC TCP_ESTABLISHED
#define LAPD_SK_STATE_NORMAL_DLC_CLOSING TCP_CLOSING
#define LAPD_SK_STATE_BROADCAST_DLC TCP_SYN_SENT
#define LAPD_SK_STATE_MGMT TCP_SYN_RECV
#define LAPD_SK_STATE_CLOSE TCP_CLOSE
#ifdef DEBUG_CODE
#define lapd_debug(format, arg...) \
printk(KERN_DEBUG \
"lapd: " \
format, \
## arg)
#define lapd_debug_ls(ls, format, arg...) \
SOCK_DEBUG(&ls->sk, \
"lapd: " \
"%s " \
format, \
(ls)->dev ? (ls)->dev->dev->name : "", \
## arg)
#else
#define lapd_debug(ls, format, arg...) do { } while (0)
#define lapd_debug_ls(ls, format, arg...) do { } while (0)
#define lapd_debug_dev(ls, format, arg...) do { } while (0)
#endif
#define lapd_msg(lvl, format, arg...) \
printk(lvl "lapd: " \
format, \
## arg)
#define lapd_msg_ls(ls, lvl, format, arg...) \
printk(lvl "lapd: " \
"%s: " \
format, \
(ls)->dev ? (ls)->dev->dev->name : "", \
## arg)
extern struct hlist_head lapd_hash[LAPD_HASHSIZE];
extern rwlock_t lapd_hash_lock;
// Do not changes these values, user mode binary compatibility needs them
enum lapd_datalink_state
{
LAPD_DLS_NULL = 0,
LAPD_DLS_1_TEI_UNASSIGNED = 1,
LAPD_DLS_2_AWAITING_TEI = 2,
LAPD_DLS_3_ESTABLISH_AWAITING_TEI = 3,
LAPD_DLS_4_TEI_ASSIGNED = 4,
LAPD_DLS_5_AWAITING_ESTABLISH = 5,
LAPD_DLS_6_AWAITING_RELEASE = 6,
LAPD_DLS_7_LINK_CONNECTION_ESTABLISHED = 7,
LAPD_DLS_8_TIMER_RECOVERY = 8,
LAPD_DLS_LISTENING = 0xFF,
};
enum lapd_mdl_error_indications
{
LAPD_MDL_ERROR_INDICATION_A = (1 << 0),
LAPD_MDL_ERROR_INDICATION_B = (1 << 1),
LAPD_MDL_ERROR_INDICATION_C = (1 << 2),
LAPD_MDL_ERROR_INDICATION_D = (1 << 3),
LAPD_MDL_ERROR_INDICATION_E = (1 << 4),
LAPD_MDL_ERROR_INDICATION_F = (1 << 5),
LAPD_MDL_ERROR_INDICATION_G = (1 << 6),
LAPD_MDL_ERROR_INDICATION_H = (1 << 7),
LAPD_MDL_ERROR_INDICATION_I = (1 << 8),
LAPD_MDL_ERROR_INDICATION_J = (1 << 9),
LAPD_MDL_ERROR_INDICATION_K = (1 << 10),
LAPD_MDL_ERROR_INDICATION_L = (1 << 11),
LAPD_MDL_ERROR_INDICATION_M = (1 << 12),
LAPD_MDL_ERROR_INDICATION_N = (1 << 13),
LAPD_MDL_ERROR_INDICATION_O = (1 << 14),
};
enum lapd_format_errors
{
LAPD_FE_LENGTH,
LAPD_FE_N201,
LAPD_FE_UNDEFINED_COMMAND,
LAPD_FE_I_FIELD_NOT_PERMITTED,
};
struct lapd_sap
{
atomic_t refcnt;
// SAP parameters
int k;
int N200;
int N201;
int T200;
int T203;
};
//#include "device.h"
struct lapd_new_dlc
{
struct hlist_node node;
struct lapd_sock *lapd_sock;
};
static inline struct lapd_sap *lapd_sap_alloc(void)
{
return kmalloc(sizeof(struct lapd_sap), GFP_ATOMIC);
}
static inline void lapd_sap_hold(
struct lapd_sap *entity)
{
atomic_inc(&entity->refcnt);
}
static inline void lapd_sap_put(
struct lapd_sap *entity)
{
if (atomic_dec_and_test(&entity->refcnt))
kfree(entity);
}
struct lapd_sock
{
struct sock sk;
struct lapd_device *dev;
struct sk_buff_head u_queue;
int retrans_cnt;
struct timer_list timer_T200;
struct timer_list timer_T203;
u8 v_s;
u8 v_r;
u8 v_a;
enum lapd_datalink_state state;
int peer_receiver_busy;
int own_receiver_busy;
int reject_exception;
int acknowledge_pending;
int layer_3_initiated;
// ------------------
struct lapd_sap *sap;
struct lapd_utme *usr_tme;
int tei;
int sapi;
struct hlist_head new_dlcs;
};
#define to_lapd_sock(obj) container_of(obj, struct lapd_sock, sk)
enum lapd_dl_primitive_type
{
LAPD_DL_RELEASE_INDICATION,
LAPD_DL_RELEASE_CONFIRM,
LAPD_DL_ESTABLISH_INDICATION,
LAPD_DL_ESTABLISH_CONFIRM,
};
struct lapd_dl_primitive
{
enum lapd_dl_primitive_type type;
int param;
};
struct lapd_sock *lapd_new_sock(
struct lapd_sock *parent_lapd_sock,
u8 tei, int sapi);
void lapd_mdl_error_indication(
struct lapd_sock *lapd_sock,
unsigned long indication);
void lapd_dl_primitive(
struct lapd_sock *lapd_sock,
enum lapd_dl_primitive_type type,
int param);
int lapd_dl_unit_data_indication(
struct lapd_sock *lapd_sock,
struct sk_buff *skb);
void lapd_dl_data_indication(
struct lapd_sock *lapd_sock,
struct sk_buff *skb);
#endif
#endif

View File

@ -10,8 +10,8 @@
static char *l1_revision = "$Revision$";
#include <linux/config.h>
#include <linux/module.h>
#include "core.h"
#include "layer1.h"
#include "helper.h"
#include "debug.h"
@ -160,7 +160,7 @@ l1m_debug(struct FsmInst *fi, char *fmt, ...)
va_start(log.args, fmt);
log.fmt = fmt;
log.head = l1->inst.name;
mISDN_ctrl(&l1->inst, MGR_DEBUGDATA | REQUEST, &log);
l1->inst.obj->ctrl(&l1->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}
@ -659,7 +659,7 @@ release_l1(layer1_t *l1) {
spin_lock_irqsave(&isdnl1.lock, flags);
list_del(&l1->list);
spin_unlock_irqrestore(&isdnl1.lock, flags);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
isdnl1.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
kfree(l1);
}
@ -704,7 +704,7 @@ new_l1(mISDNstack_t *st, mISDN_pid_t *pid) {
spin_lock_irqsave(&isdnl1.lock, flags);
list_add_tail(&nl1->list, &isdnl1.ilist);
spin_unlock_irqrestore(&isdnl1.lock, flags);
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &nl1->inst);
err = isdnl1.ctrl(st, MGR_REGLAYER | INDICATION, &nl1->inst);
if (err) {
mISDN_FsmDelTimer(&nl1->timer, 0);
list_del(&nl1->list);
@ -737,11 +737,7 @@ static char MName[] = "ISDNL1";
#ifdef MODULE
MODULE_AUTHOR("Karsten Keil");
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#endif
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
@ -769,8 +765,7 @@ l1_manager(void *data, u_int prim, void *arg) {
}
spin_unlock_irqrestore(&isdnl1.lock, flags);
if (err && (prim != (MGR_NEWLAYER | REQUEST))) {
if (debug)
printk(KERN_WARNING "l1_manager connect no instance\n");
printk(KERN_WARNING "l1_manager connect no instance\n");
return(err);
}
@ -801,7 +796,6 @@ l1_manager(void *data, u_int prim, void *arg) {
break;
PRIM_NOT_HANDLED(MGR_CTRLREADY|INDICATION);
PRIM_NOT_HANDLED(MGR_ADDSTPARA|INDICATION);
PRIM_NOT_HANDLED(MGR_SETSTACK|INDICATION);
default:
printk(KERN_WARNING "l1_manager prim %x not handled\n", prim);
err = -EINVAL;
@ -852,8 +846,7 @@ int Isdnl1Init(void)
#ifdef OBSOLETE
mISDN_FsmFree(&l1fsm_b);
#endif
} else
mISDN_module_register(THIS_MODULE);
}
return(err);
}
@ -863,8 +856,6 @@ void cleanup_module(void)
int err;
layer1_t *l1, *nl1;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&isdnl1))) {
printk(KERN_ERR "Can't unregister ISDN layer 1 error(%d)\n", err);
}

View File

@ -6,7 +6,6 @@
*
*/
#include <linux/module.h>
#include "core.h"
#include "layer2.h"
#include "helper.h"
#include "debug.h"
@ -243,7 +242,7 @@ static int
l2mgr(layer2_t *l2, u_int prim, void *arg) {
long c = (long)arg;
printk(KERN_WARNING "l2mgr: addr:%x prim %x %c\n", l2->inst.id, prim, (char)c);
printk(KERN_WARNING "l2mgr: prim %x %c\n", prim, (char)c);
if (test_bit(FLG_LAPD, &l2->flag) &&
!test_bit(FLG_FIXED_TEI, &l2->flag)) {
struct sk_buff *skb;
@ -1182,9 +1181,8 @@ l2_st7_got_super(struct FsmInst *fi, int event, void *arg)
mISDN_FsmDelTimer(&l2->t203, 9);
restart_t200(l2, 12);
}
if (skb_queue_len(&l2->i_queue) && (typ == RR)) {
if (skb_queue_len(&l2->i_queue) && (typ == RR))
mISDN_FsmEvent(fi, EV_L2_ACK_PULL, NULL);
}
} else
nrerrorrecovery(fi);
}
@ -1833,7 +1831,7 @@ ph_data_indication(layer2_t *l2, mISDN_head_t *hh, struct sk_buff *skb) {
psapi = *datap++;
ptei = *datap++;
if ((psapi & 1) || !(ptei & 1)) {
printk(KERN_WARNING "l2 D-channel addr:%x frame wrong EA0/EA1\n", l2->inst.id);
printk(KERN_WARNING "l2 D-channel frame wrong EA0/EA1\n");
return(ret);
}
psapi >>= 2;
@ -1946,7 +1944,7 @@ l2from_down(layer2_t *l2, struct sk_buff *askb, mISDN_head_t *hh)
case (PH_ACTIVATE | CONFIRM):
case (PH_ACTIVATE | INDICATION):
test_and_set_bit(FLG_L1_ACTIV, &l2->flag);
if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
if (test_and_clear_bit(FLG_ESTAB_PEND, &l2->flag))
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_DL_ESTABLISH_REQ, cskb);
break;
case (PH_DEACTIVATE | INDICATION):
@ -2116,11 +2114,6 @@ tei_l2(layer2_t *l2, struct sk_buff *skb)
case (MDL_ERROR | RESPONSE):
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, skb);
break;
case (MDL_ERROR | REQUEST):
/* ETS 300-125 5.3.2.1 Test: TC13010*/
printk(KERN_NOTICE "MDL_ERROR|REQ (tei_l2)\n");
ret = mISDN_FsmEvent(&l2->l2m, EV_L2_MDL_ERROR, skb);
break;
case (MDL_FINDTEI | REQUEST):
ret = l2down_skb(l2, skb);
break;
@ -2137,7 +2130,7 @@ l2m_debug(struct FsmInst *fi, char *fmt, ...)
va_start(log.args, fmt);
log.fmt = fmt;
log.head = l2->inst.name;
mISDN_ctrl(&l2->inst, MGR_DEBUGDATA | REQUEST, &log);
l2->inst.obj->ctrl(&l2->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}
@ -2181,9 +2174,9 @@ release_l2(layer2_t *l2)
spin_lock_irqsave(&isdnl2.lock, flags);
list_del(&l2->list);
spin_unlock_irqrestore(&isdnl2.lock, flags);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
isdnl2.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
if (l2->entity != MISDN_ENTITY_NONE)
mISDN_ctrl(inst, MGR_DELENTITY | REQUEST, (void *)((u_long)l2->entity));
isdnl2.ctrl(inst, MGR_DELENTITY | REQUEST, (void *)((u_long)l2->entity));
kfree(l2);
}
@ -2242,19 +2235,8 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid) {
test_and_set_bit(FLG_FIXED_TEI, &nl2->flag);
nl2->tei = 0;
}
nl2->maxlen = MAX_DFRAME_LEN;
if (pid->protocol[3] & ISDN_PID_L3_DF_CRLEN2) {
if (debug)
printk("layer2: Windowsize 7\n");
nl2->window = 7;
} else {
if (debug)
printk("layer2: Windowsize 1\n");
nl2->window = 1;
}
nl2->window = 1;
nl2->T200 = 1000;
nl2->N200 = 3;
nl2->T203 = 10000;
@ -2275,8 +2257,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid) {
nl2->addr.B = 1;
if (nl2->inst.pid.global == 1)
test_and_set_bit(FLG_ORIG, &nl2->flag);
if (pid->param[2] && pid->pbuf) {
p = pid->pbuf + pid->param[2];
if ((p=pid->param[2])) {
if (*p>=4) {
p++;
nl2->addr.A = *p++;
@ -2317,12 +2298,12 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid) {
spin_lock_irqsave(&isdnl2.lock, flags);
list_add_tail(&nl2->list, &isdnl2.ilist);
spin_unlock_irqrestore(&isdnl2.lock, flags);
err = mISDN_ctrl(&nl2->inst, MGR_NEWENTITY | REQUEST, NULL);
err = isdnl2.ctrl(&nl2->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%d)\n",
__FUNCTION__, err);
}
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &nl2->inst);
err = isdnl2.ctrl(st, MGR_REGLAYER | INDICATION, &nl2->inst);
if (err) {
mISDN_FsmDelTimer(&nl2->t200, 0);
mISDN_FsmDelTimer(&nl2->t203, 0);
@ -2337,7 +2318,7 @@ new_l2(mISDNstack_t *st, mISDN_pid_t *pid) {
stp.maxdatalen = 0;
stp.up_headerlen = 0;
stp.down_headerlen = l2headersize(nl2, 0);
mISDN_ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
isdnl2.ctrl(st, MGR_ADDSTPARA | REQUEST, &stp);
}
return(err);
}
@ -2427,11 +2408,7 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#endif
#endif
static int
@ -2530,8 +2507,7 @@ int Isdnl2_Init(void)
if ((err = mISDN_register(&isdnl2))) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
mISDN_FsmFree(&l2fsm);
} else
mISDN_module_register(THIS_MODULE);
}
return(err);
}
@ -2540,8 +2516,6 @@ void Isdnl2_cleanup(void)
int err;
layer2_t *l2, *nl2;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&isdnl2))) {
printk(KERN_ERR "Can't unregister ISDN layer 2 error(%d)\n", err);
}

View File

@ -12,7 +12,6 @@
*/
#include "layer3.h"
#include "helper.h"
#include "dss1.h"
const char *l3_revision = "$Revision$";
@ -70,7 +69,7 @@ l3m_debug(struct FsmInst *fi, char *fmt, ...)
va_start(log.args, fmt);
log.fmt = fmt;
log.head = l3->inst.name;
mISDN_ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}
@ -82,7 +81,7 @@ l3_debug(layer3_t *l3, char *fmt, ...)
va_start(log.args, fmt);
log.fmt = fmt;
log.head = l3->inst.name;
mISDN_ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}
@ -310,9 +309,6 @@ l3_process_t
return (NULL);
}
memset(p, 0, sizeof(l3_process_t));
p->cause=NO_CAUSE;
p->l3 = l3;
p->id = id;
p->callref = cr;

View File

@ -42,11 +42,9 @@ typedef struct _l3_process {
int state;
L3Timer_t timer;
int n303;
int cause;
struct sk_buff *t303skb;
u_int id;
int bc;
int real_bc;
int err;
int aux_state;
L3Timer_t aux_timer;

View File

@ -1,7 +1,7 @@
/*
* loop.c loop driver for looped bchannel pairs
*
* Author Andreas Eversberg (jolly@eversberg.eu)
* Author Andreas Eversberg (jolly@jolly.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
@ -25,6 +25,7 @@
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
@ -56,8 +57,8 @@ MODULE_AUTHOR("Andreas Eversberg");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
module_param(interfaces, uint, S_IRUGO | S_IWUSR);
module_param(debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM(interfaces, "1i");
MODULE_PARM(debug, "1i");
#endif
@ -258,7 +259,7 @@ found:
if (loop_l2l1(inst, skb)) dev_kfree_skb(skb);
}
}
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
loop_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
@ -434,7 +435,7 @@ static int __devinit loop_new(void)
/* add stacks */
if (debug & DEBUG_LOOP_INIT)
printk(KERN_DEBUG "%s: Adding d-stack: card(%d)\n", __FUNCTION__, loop_cnt+1);
if ((ret_err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &dch->inst))) {
if ((ret_err = loop_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &dch->inst))) {
printk(KERN_ERR "MGR_ADDSTACK REQUEST dch err(%d)\n", ret_err);
free_release:
loop_delete(hc); /* hc is free */
@ -448,10 +449,10 @@ static int __devinit loop_new(void)
if (debug & DEBUG_LOOP_INIT)
printk(KERN_DEBUG "%s: Adding b-stack: card(%d) B-channel(%d)\n", __FUNCTION__, loop_cnt+1, ch+1);
bch = hc->bch[ch];
if ((ret_err = mISDN_ctrl(dst, MGR_NEWSTACK | REQUEST, &bch->inst))) {
if ((ret_err = loop_obj.ctrl(dst, MGR_NEWSTACK | REQUEST, &bch->inst))) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", ret_err);
free_delstack:
mISDN_ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
loop_obj.ctrl(dst, MGR_DELSTACK | REQUEST, NULL);
goto free_release;
}
ch++;
@ -459,7 +460,7 @@ static int __devinit loop_new(void)
if (debug & DEBUG_LOOP_INIT)
printk(KERN_DEBUG "%s: (before MGR_SETSTACK REQUEST) layermask=0x%x\n", __FUNCTION__, pid.layermask);
if ((ret_err = mISDN_ctrl(dst, MGR_SETSTACK | REQUEST, &pid))) {
if ((ret_err = loop_obj.ctrl(dst, MGR_SETSTACK | REQUEST, &pid))) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", ret_err);
goto free_delstack;
}
@ -471,7 +472,7 @@ static int __devinit loop_new(void)
schedule_timeout((100*HZ)/1000); /* Timeout 100ms */
/* tell stack, that we are ready */
mISDN_ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
loop_obj.ctrl(dst, MGR_CTRLREADY | INDICATION, NULL);
loop_cnt++;
return(0);

View File

@ -178,24 +178,6 @@ __mid_dev_alloc_skb(unsigned int size, char *fn, int line)
return(skb);
}
void
__mid_kfree_skb(struct sk_buff *skb)
{
if (skb->destructor)
skb->destructor(skb);
skb->destructor = NULL;
kfree_skb(skb);
}
void
__mid_dev_kfree_skb(struct sk_buff *skb)
{
if (skb->destructor)
skb->destructor(skb);
skb->destructor = NULL;
dev_kfree_skb(skb);
}
struct sk_buff
*__mid_skb_clone(struct sk_buff *skb, int gfp_mask, char *fn, int line)
{
@ -299,8 +281,6 @@ EXPORT_SYMBOL(__mid_vmalloc);
EXPORT_SYMBOL(__mid_vfree);
EXPORT_SYMBOL(__mid_alloc_skb);
EXPORT_SYMBOL(__mid_dev_alloc_skb);
EXPORT_SYMBOL(__mid_kfree_skb);
EXPORT_SYMBOL(__mid_dev_kfree_skb);
EXPORT_SYMBOL(__mid_skb_clone);
EXPORT_SYMBOL(__mid_skb_copy);
EXPORT_SYMBOL(__mid_skb_realloc_headroom);

View File

@ -11,8 +11,6 @@
#undef vfree
#undef alloc_skb
#undef dev_alloc_skb
#undef kfree_skb
#undef dev_kfree_skb
#undef skb_clone
#undef skb_copy
#undef skb_realloc_headroom
@ -23,8 +21,6 @@
#define vfree(p) __mid_vfree(p)
#define alloc_skb(a, b) __mid_alloc_skb(a, b, __FILE__, __LINE__)
#define dev_alloc_skb(a) __mid_dev_alloc_skb(a, __FILE__, __LINE__)
#define kfree_skb(a) __mid_kfree_skb(a)
#define dev_kfree_skb(a) __mid_dev_kfree_skb(a)
#define skb_clone(a, b) __mid_skb_clone(a, b, __FILE__, __LINE__)
#define skb_copy(a, b) __mid_skb_copy(a, b, __FILE__, __LINE__)
#define skb_realloc_headroom(a, b) __mid_skb_realloc_headroom(a, b, __FILE__, __LINE__)
@ -37,8 +33,6 @@ extern void __mid_cleanup(void);
extern int __mid_init(void);
extern struct sk_buff *__mid_alloc_skb(unsigned int,int, char *, int);
extern struct sk_buff *__mid_dev_alloc_skb(unsigned int,char *, int);
extern void __mid_kfree_skb(struct sk_buff *);
extern void __mid_dev_kfree_skb(struct sk_buff *);
extern struct sk_buff *__mid_skb_clone(struct sk_buff *, int, char *, int);
extern struct sk_buff *__mid_skb_copy(struct sk_buff *, int, char *, int);
extern struct sk_buff *__mid_skb_realloc_headroom(struct sk_buff *, unsigned int, char *, int);

View File

@ -380,14 +380,14 @@ ncci_manufacturer_req(struct FsmInst *fi, int event, void *arg)
_cmsg *cmsg = arg;
int err, op;
struct _manu_conf_para {
u8 len;
u16 Info;
u16 vol;
u8 len __attribute__((packed));
u16 Info __attribute__((packed));
u16 vol __attribute__((packed));
} mcp = {2, CAPI_NOERROR,0};
struct _manu_req_para {
u8 len;
u16 vol;
} __attribute__((packed)) *mrp;
u8 len __attribute__((packed));
u16 vol __attribute__((packed));
} *mrp;
if (!ncci->appl)
return;
@ -931,23 +931,23 @@ ncciDataInd(Ncci_t *ncci, int pr, struct sk_buff *skb)
ncci->recv_skb_handles[i] = nskb;
skb_push(nskb, CAPI_B3_DATA_IND_HEADER_SIZE);
CAPIMSG_SETLEN(nskb->data, CAPI_B3_DATA_IND_HEADER_SIZE);
CAPIMSG_SETAPPID(nskb->data, ncci->appl->ApplId);
CAPIMSG_SETCOMMAND(nskb->data, CAPI_DATA_B3);
CAPIMSG_SETSUBCOMMAND(nskb->data, CAPI_IND);
CAPIMSG_SETMSGID(nskb->data, ncci->appl->MsgId++);
CAPIMSG_SETCONTROL(nskb->data, ncci->addr);
*((__u16*) nskb->data) = CAPI_B3_DATA_IND_HEADER_SIZE;
*((__u16*)(nskb->data+2)) = ncci->appl->ApplId;
*((__u8*) (nskb->data+4)) = CAPI_DATA_B3;
*((__u8*) (nskb->data+5)) = CAPI_IND;
*((__u16*)(nskb->data+6)) = ncci->appl->MsgId++;
*((__u32*)(nskb->data+8)) = ncci->addr;
if (sizeof(nskb) == 4) {
capimsg_setu32(nskb->data, 12, (__u32)(((u_long)nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE) & 0xffffffff));
*((__u64*)(nskb->data+22)) = cpu_to_le64(0);
*((__u32*)(nskb->data+12)) = (__u32)(((u_long)nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE) & 0xffffffff);
*((__u64*)(nskb->data+22)) = 0;
} else {
capimsg_setu32(nskb->data, 12, 0);
*((__u64*)(nskb->data+22)) = cpu_to_le64((__u64)nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE);
*((__u32*)(nskb->data+12)) = 0;
*((__u64*)(nskb->data+22)) = (u_long)(nskb->data + CAPI_B3_DATA_IND_HEADER_SIZE);
}
CAPIMSG_SETDATALEN(nskb->data, nskb->len - CAPI_B3_DATA_IND_HEADER_SIZE);
capimsg_setu16(nskb->data, 18, i);
*((__u16*)(nskb->data+16)) = nskb->len - CAPI_B3_DATA_IND_HEADER_SIZE;
*((__u16*)(nskb->data+18)) = i;
// FIXME FLAGS
capimsg_setu16(nskb->data, 20, 0);
*((__u16*)(nskb->data+20)) = 0;
#ifdef OLDCAPI_DRIVER_INTERFACE
ncci->contr->ctrl->handle_capimsg(ncci->contr->ctrl, ncci->appl->ApplId, nskb);
#else

View File

@ -1,316 +0,0 @@
/*
* gateway between mISDN and Linux's netdev subsystem
*
* Copyright (C) 2005-2006 Christian Richter
*
* Authors: Christian Richter
*
* Thanks to Daniele Orlandi from the vISDN Developer Team
*
* This program is free software and may be modified and distributed
* under the terms and conditions of the GNU General Public License.
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/netdevice.h>
#include <linux/device.h>
#include <linux/delay.h>
#include <linux/list.h>
#include <linux/crc32.h>
#include <linux/mISDNif.h>
#include "core.h"
#include "lapd.h"
wait_queue_head_t waitq;
struct sk_buff_head finishq;
struct mISDN_netdev {
struct sk_buff_head workq;
struct list_head list;
struct net_device *netdev;
struct net_device_stats stats;
mISDNstack_t *st;
int nt;
int addr;
};
LIST_HEAD(mISDN_netdev_list);
static int misdn_chan_frame_xmit(
struct net_device *netdev,
struct sk_buff *skb, int rx)
{
struct mISDN_netdev *ndev=netdev->priv;
struct lapd_prim_hdr *prim_hdr;
netdev->last_rx = jiffies;
skb->protocol = htons(ETH_P_LAPD);
skb->dev = netdev;
skb->ip_summed = CHECKSUM_UNNECESSARY;
skb->pkt_type = PACKET_HOST;
skb_push(skb, sizeof(struct lapd_prim_hdr));
prim_hdr = (struct lapd_prim_hdr *)skb->data;
prim_hdr->primitive_type = LAPD_PH_DATA_INDICATION;
if (rx)
ndev->stats.rx_packets++;
else
ndev->stats.rx_packets++;
return netif_rx(skb);
}
static struct net_device_stats *misdn_netdev_get_stats(
struct net_device *netdev)
{
struct mISDN_netdev *ndev=netdev->priv;
return &ndev->stats;
}
static void misdn_netdev_set_multicast_list(
struct net_device *netdev)
{
}
static int misdn_netdev_do_ioctl(
struct net_device *netdev,
struct ifreq *ifr, int cmd)
{
return -EOPNOTSUPP;
}
static int misdn_netdev_change_mtu(
struct net_device *netdev,
int new_mtu)
{
return 0;
}
static int lapd_mac_addr(struct net_device *dev, void *addr)
{
return 0;
}
static void setup_lapd(struct net_device *netdev)
{
netdev->change_mtu = NULL;
netdev->hard_header = NULL;
netdev->rebuild_header = NULL;
netdev->set_mac_address = lapd_mac_addr;
netdev->hard_header_cache = NULL;
netdev->header_cache_update= NULL;
//netdev->hard_header_parse = lapd_hard_header_parse;
netdev->hard_header_parse = NULL;
netdev->type = ARPHRD_LAPD;
netdev->hard_header_len = 0;
netdev->addr_len = 1;
netdev->tx_queue_len = 10;
memset(netdev->broadcast, 0, sizeof(netdev->broadcast));
netdev->flags = 0;
}
static int misdn_netdev_open(struct net_device *netdev)
{
return 0;
}
static int misdn_netdev_stop(struct net_device *netdev)
{
return 0;
}
static int mISDN_netdevd(void *data)
{
struct sk_buff *skb;
struct mISDN_netdev *ndev;
for(;;) {
wait_event_interruptible(waitq, 1);
if ((skb=skb_dequeue(&finishq))) {
kfree_skb(skb);
return 0;
}
list_for_each_entry(ndev, &mISDN_netdev_list, list) {
while ((skb=skb_dequeue(&ndev->workq))) {
misdn_chan_frame_xmit(ndev->netdev, skb, 1);
}
}
}
return 0;
}
static int misdn_netdev_frame_xmit(
struct sk_buff *skb,
struct net_device *netdev)
{
return 0;
}
/*************************/
/** Interface Functions **/
/*************************/
void misdn_log_frame(mISDNstack_t* st, unsigned char *data, int len, int direction)
{
struct sk_buff *skb;
struct mISDN_netdev *ndev;
int i;
skb = alloc_skb(sizeof(struct lapd_prim_hdr)+len, GFP_KERNEL);
if (!skb) {
printk ("%s: no mem for skb\n", __FUNCTION__);
return;
}
skb_reserve(skb, sizeof(struct lapd_prim_hdr));
skb_reserve(skb, 4);
memcpy(skb_put(skb, len), data, len);
list_for_each_entry(ndev, &mISDN_netdev_list, list) {
if (ndev->st==st) break;
}
// use syslog as long as kernel oops when using netdev
printk ("%s: st(%x): %s ", __FUNCTION__, st->id, (direction==FLG_MSG_UP)?"-->":"<--");
for (i=0; i<len; i++)
printk("0x%02x ", data[i]);
printk ("\n");
kfree_skb(skb);
/*
if (ndev)
misdn_chan_frame_xmit(ndev->netdev, skb , 1);
else
printk(KERN_WARNING "No mISDN_netdev for stack:%x\n",st->id);
*/
}
int misdn_netdev_addstack(mISDNstack_t *st)
{
struct net_device *netdev;
struct mISDN_netdev *ndev;
int err;
char name[8];
sprintf(name, "mISDN%02x",
((((st->id >> 8) & 0xFF) +
((st->id >> 12) & 0xFF))
& 0xFF));
printk(KERN_NOTICE "allocating netdev(%s) for stack(%x)\n", name, st->id);
netdev = alloc_netdev(0, name, setup_lapd);
if(!netdev) {
printk(KERN_ERR "net_device alloc failed, abort.\n");
return -ENOMEM;
}
ndev = kmalloc(sizeof(struct mISDN_netdev), GFP_KERNEL);
if(!ndev) {
printk(KERN_ERR "mISDN_netdevice alloc failed, abort.\n");
return -ENOMEM;
}
memset(&ndev->stats,0,sizeof(ndev->stats));
skb_queue_head_init(&ndev->workq);
ndev->netdev=netdev;
netdev->priv = ndev;
netdev->open = misdn_netdev_open;
netdev->stop = misdn_netdev_stop;
netdev->hard_start_xmit = misdn_netdev_frame_xmit;
netdev->get_stats = misdn_netdev_get_stats;
netdev->set_multicast_list = misdn_netdev_set_multicast_list;
netdev->do_ioctl = misdn_netdev_do_ioctl;
netdev->change_mtu = misdn_netdev_change_mtu;
netdev->features = NETIF_F_NO_CSUM;
switch (st->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK) {
case ISDN_PID_L0_TE_S0:
case ISDN_PID_L0_TE_E1:
printk(KERN_NOTICE " --> TE Mode\n");
memset(netdev->dev_addr, 0, sizeof(netdev->dev_addr));
break;
case ISDN_PID_L0_NT_S0:
case ISDN_PID_L0_NT_E1:
printk(KERN_NOTICE " --> NT Mode\n");
memset(netdev->dev_addr, 1, sizeof(netdev->dev_addr));
break;
}
SET_MODULE_OWNER(netdev);
netdev->irq = 0;
netdev->base_addr = 0;
list_add(&ndev->list, &mISDN_netdev_list);
err = register_netdev(netdev);
if (err < 0) {
printk(KERN_ERR "Cannot register net device %s, aborting.\n",
netdev->name);
}
return 0;
}
int misdn_netdev_init(void)
{
int err=0;
init_waitqueue_head(&waitq);
skb_queue_head_init(&finishq);
kernel_thread(mISDN_netdevd, NULL, 0);
return err;
}
void misdn_netdev_exit(void)
{
struct sk_buff *skb=alloc_skb(8,GFP_KERNEL);
struct mISDN_netdev *ndev;
skb_queue_tail(&finishq,skb);
list_for_each_entry(ndev, &mISDN_netdev_list, list) {
unregister_netdev(ndev->netdev);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +0,0 @@
/*
*
* NETjet common header file
*
* Author Karsten Keil
* Copyright by Karsten Keil <keil@isdn4linux.de>
* by Matt Henderson and Daniel Potts,
* Traverse Technologies P/L www.traverse.com.au
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Ported to mISDN from HiSax by Daniel Potts
*
*/
#define NETJET_CTRL 0x00
#define NETJET_DMACTRL 0x01
#define NETJET_AUXCTRL 0x02
#define NETJET_AUXDATA 0x03
#define NETJET_IRQMASK0 0x04
#define NETJET_IRQMASK1 0x05
#define NETJET_IRQSTAT0 0x06
#define NETJET_IRQSTAT1 0x07
#define NETJET_DMA_READ_START 0x08
#define NETJET_DMA_READ_IRQ 0x0c
#define NETJET_DMA_READ_END 0x10
#define NETJET_DMA_READ_ADR 0x14
#define NETJET_DMA_WRITE_START 0x18
#define NETJET_DMA_WRITE_IRQ 0x1c
#define NETJET_DMA_WRITE_END 0x20
#define NETJET_DMA_WRITE_ADR 0x24
#define NETJET_PULSE_CNT 0x28
#define NETJET_ISAC_OFF 0xc0
#define NETJET_ISACIRQ 0x10
#define NETJET_IRQM0_READ_MASK 0x0c
#define NETJET_IRQM0_READ_1 0x04
#define NETJET_IRQM0_READ_2 0x08
#define NETJET_IRQM0_WRITE_MASK 0x03
#define NETJET_IRQM0_WRITE_1 0x01
#define NETJET_IRQM0_WRITE_2 0x02
#define NETJET_HA_OFFSET 2
#define NETJET_HA_BITS 4
#define NETJET_HA_MASK 0xf // mask from offset
#define NETJET_DMA_TXSIZE 512 // dma buf size in 32-bit words
#define NETJET_DMA_RXSIZE 128 // dma buf size in 32-bit words
#define HDLC_ZERO_SEARCH 0
#define HDLC_FLAG_SEARCH 1
#define HDLC_FLAG_FOUND 2
#define HDLC_FRAME_FOUND 3
#define HDLC_NULL 4
#define HDLC_PART 5
#define HDLC_FULL 6
#define HDLC_FLAG_VALUE 0x7e
#define FLG_NOFRAME 26
#define FLG_HALF 27
#define FLG_EMPTY 28

View File

@ -26,6 +26,7 @@
* the firmware onto the card.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
@ -35,7 +36,6 @@
#else
#include <linux/isapnp.h>
#endif
#include "core.h"
#include "channel.h"
#include "isac.h"
#include "isar.h"
@ -391,9 +391,12 @@ static int init_card(sedl_fax *sf)
#define MAX_CARDS 4
#define MODULE_PARM_T "1-4i"
static int sedl_cnt;
static mISDNobject_t speedfax;
static uint debug;
static uint protocol_num;
static uint layermask_num;
static uint protocol[MAX_CARDS];
static uint layermask[MAX_CARDS];
@ -402,16 +405,8 @@ MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#define MODULE_PARM_T "1-4i"
MODULE_PARM(protocol, MODULE_PARM_T);
MODULE_PARM(layermask, MODULE_PARM_T);
#else
module_param (debug, uint, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC (debug, "sedlfax debug mask");
static uint protocol_num;
static uint layermask_num;
#ifdef OLD_MODULE_PARAM_ARRAY
module_param_array(protocol, uint, protocol_num, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, layermask_num, S_IRUGO | S_IWUSR);
@ -422,7 +417,7 @@ module_param_array(layermask, uint, &layermask_num, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC (protocol, "sedlfax protcol (DSS1 := 2)");
MODULE_PARM_DESC(layermask, "sedlfax layer mask");
#endif
#endif
static char SpeedfaxName[] = "Speedfax";
int
@ -506,7 +501,7 @@ release_card(sedl_fax *card) {
mISDN_freechannel(&card->bch[0]);
mISDN_freechannel(&card->dch);
spin_unlock_irqrestore(&card->lock, flags);
mISDN_ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
speedfax.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
spin_lock_irqsave(&speedfax.lock, flags);
list_del(&card->list);
spin_unlock_irqrestore(&speedfax.lock, flags);
@ -582,7 +577,7 @@ speedfax_manager(void *data, u_int prim, void *arg) {
}
} else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
speedfax.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
arg = NULL;
@ -624,7 +619,7 @@ speedfax_manager(void *data, u_int prim, void *arg) {
return(isar_load_firmware(&card->bch[0], firm->data, firm->len));
}
case MGR_LOADFIRM | CONFIRM:
mISDN_ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
break;
case MGR_SETSTACK | INDICATION:
if ((channel!=2) && (inst->pid.global == 2)) {
@ -709,32 +704,32 @@ static int __devinit setup_instance(sedl_fax *card)
return(err);
}
sedl_cnt++;
err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
err = speedfax.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
if (err) {
release_card(card);
return(err);
}
mISDN_ctrl(card->dch.inst.st, MGR_STOPSTACK | REQUEST, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_STOPSTACK | REQUEST, NULL);
for (i=0; i<2; i++) {
err = mISDN_ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
err = speedfax.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
if (err) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
}
err = mISDN_ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
err = speedfax.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
if (err) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
err = init_card(card);
if (err) {
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
mISDN_ctrl(card->dch.inst.st, MGR_STARTSTACK | REQUEST, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_STARTSTACK | REQUEST, NULL);
printk(KERN_INFO "SpeedFax %d cards installed\n", sedl_cnt);
return(0);
}
@ -819,7 +814,7 @@ static void __devexit sedl_remove_pci(struct pci_dev *pdev)
sedl_fax *card = pci_get_drvdata(pdev);
if (card)
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
else
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
}
@ -834,7 +829,7 @@ static void __devexit sedl_remove_pnp(struct pci_dev *pdev)
sedl_fax *card = pnp_get_drvdata(pdev);
if (card)
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
speedfax.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
else
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
}
@ -929,9 +924,6 @@ static int __init Speedfax_init(void)
}
#endif
#endif
mISDN_module_register(THIS_MODULE);
return 0;
#ifdef OLD_PCI_REGISTER_DRIVER
@ -955,8 +947,6 @@ static void __exit Speedfax_cleanup(void)
int err;
sedl_fax *card, *next;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&speedfax))) {
printk(KERN_ERR "Can't unregister Speedfax PCI error(%d)\n", err);
}

View File

@ -2,7 +2,7 @@
* socket handling, transfer, receive-process for Voice over IP
*
* Author Andreas Eversberg (jolly@eversberg.eu)
* Author Andreas Eversberg (jolly@jolly.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
@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/config.h>
#include <linux/in.h>
#include <net/sock.h>

View File

@ -2,7 +2,7 @@
* socket handling, transfer, receive-process for Voice over IP
*
* Author Andreas Eversberg (jolly@eversberg.eu)
* Author Andreas Eversberg (jolly@jolly.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

View File

@ -478,9 +478,7 @@ mISDNStackd(void *data)
#ifdef CONFIG_SMP
unlock_kernel();
#endif
if ( core_debug & DEBUG_THREADS)
printk(KERN_DEBUG "mISDNStackd started for id(%08x)\n", st->id);
printk(KERN_DEBUG "mISDNStackd started for id(%08x)\n", st->id);
for (;;) {
struct sk_buff *skb, *c_skb;
mISDN_head_t *hh;
@ -622,8 +620,8 @@ mISDNStackd(void *data)
st->id, st->msg_cnt, st->clone_cnt, st->sleep_cnt, st->stopped_cnt);
printk(KERN_DEBUG "mISDNStackd daemon for id(%08x) utime(%ld) stime(%ld)\n", st->id, st->thread->utime, st->thread->stime);
printk(KERN_DEBUG "mISDNStackd daemon for id(%08x) nvcsw(%ld) nivcsw(%ld)\n", st->id, st->thread->nvcsw, st->thread->nivcsw);
printk(KERN_DEBUG "mISDNStackd daemon for id(%08x) killed now\n", st->id);
#endif
printk(KERN_DEBUG "mISDNStackd daemon for id(%08x) killed now\n", st->id);
test_and_set_bit(mISDN_STACK_KILLED, &st->status);
test_and_clear_bit(mISDN_STACK_RUNNING, &st->status);
test_and_clear_bit(mISDN_STACK_ACTIVE, &st->status);
@ -1005,7 +1003,7 @@ register_layer(mISDNstack_t *st, mISDNinstance_t *inst)
if (!list_empty(&inst->list)) {
if (core_debug & DEBUG_CORE_FUNC)
printk(KERN_DEBUG "%s: register preregistered instance st(%p/%p)\n",
printk(KERN_DEBUG "%s: register preregistered instance st(%p/%p)",
__FUNCTION__, st, inst->st);
list_del_init(&inst->list);
}
@ -1100,6 +1098,8 @@ unregister_instance(mISDNinstance_t *inst) {
int
copy_pid(mISDN_pid_t *dpid, mISDN_pid_t *spid, u_char *pbuf)
{
u_int i, off;
memcpy(dpid, spid, sizeof(mISDN_pid_t));
if (spid->pbuf && spid->maxplen) {
if (!pbuf) {
@ -1108,6 +1108,39 @@ copy_pid(mISDN_pid_t *dpid, mISDN_pid_t *spid, u_char *pbuf)
}
dpid->pbuf = pbuf;
memcpy(dpid->pbuf, spid->pbuf, spid->maxplen);
for (i = 0; i <= MAX_LAYER_NR; i++) {
if (spid->param[i]) {
off = (u_int)(spid->param[i] - spid->pbuf);
dpid->param[i] = dpid->pbuf + off;
}
}
} else if (spid->maxplen) {
off = 0;
for (i = 0; i <= MAX_LAYER_NR; i++)
if (spid->param[i])
off += *spid->param[i];
if (off == 0) {
int_error(); /* we ignore this */
dpid->maxplen = 0;
return(0);
}
if (off > spid->maxplen) {
int_errtxt("overflow");
dpid->maxplen = 0;
return(-EINVAL);
}
if (!pbuf) {
int_error();
return(-ENOMEM);
}
for (i = 0; i <= MAX_LAYER_NR; i++) {
if (spid->param[i]) {
dpid->param[i] = pbuf;
off = *dpid->param[i] +1;
memcpy(pbuf, dpid->param[i], off);
pbuf += off;
}
}
}
return(0);
}
@ -1124,7 +1157,7 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
int_error();
return(-EINVAL);
}
if (!st->mgr || !st->mgr->obj) {
if (!st->mgr || !st->mgr->obj || !st->mgr->obj->ctrl) {
int_error();
return(-EINVAL);
}
@ -1140,7 +1173,7 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
} else {
mISDN_RemoveUsedPID(pid, &st->mgr->pid);
}
err = mISDN_ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
err = st->mgr->obj->ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
if (err) {
int_error();
return(err);
@ -1149,7 +1182,7 @@ set_stack(mISDNstack_t *st, mISDN_pid_t *pid)
inst = get_next_instance(st, pid);
if (!inst) {
int_error();
mISDN_ctrl(st, MGR_CLEARSTACK| REQUEST, (void *)1);
st->mgr->obj->ctrl(st, MGR_CLEARSTACK| REQUEST, (void *)1);
return(-ENOPROTOOPT);
}
mISDN_RemoveUsedPID(pid, &inst->pid);
@ -1239,7 +1272,7 @@ test_stack_protocol(mISDNstack_t *st, u_int l1prot, u_int l2prot, u_int l3prot)
memset(&st->pid, 0, sizeof(mISDN_pid_t));
return(0);
}
ret = mISDN_ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
ret = st->mgr->obj->ctrl(st, MGR_REGLAYER | REQUEST, st->mgr);
if (ret) {
clear_stack(st, 1);
return(ret);
@ -1298,7 +1331,7 @@ evaluate_stack_pids(mISDNstack_t *st, mISDN_pid_t *pid)
int_error();
return(-EINVAL);
}
if (!st->mgr || !st->mgr->obj) {
if (!st->mgr || !st->mgr->obj || !st->mgr->obj->ctrl) {
int_error();
return(-EINVAL);
}

View File

@ -40,21 +40,16 @@ static ssize_t show_inst_regcnt(struct class_device *class_dev, char *buf)
}
static CLASS_DEVICE_ATTR(regcnt, S_IRUGO, show_inst_regcnt, NULL);
#ifdef SYSFS_SUPPORT
MISDN_PROTO(mISDNinstance, pid, S_IRUGO);
#endif
static void release_mISDN_inst(struct class_device *dev)
{
#ifdef SYSFS_SUPPORT
mISDNinstance_t *inst = to_mISDNinstance(dev);
if (inst->obj)
sysfs_remove_link(&dev->kobj, "obj");
sysfs_remove_group(&inst->class_dev.kobj, &pid_group);
#endif
if (core_debug & DEBUG_SYSFS)
printk(KERN_INFO "release instance class dev %s\n", dev->class_id);
printk(KERN_INFO "release instance class dev %s\n", dev->class_id);
}
static struct class inst_dev_class = {
@ -68,22 +63,17 @@ static struct class inst_dev_class = {
int
mISDN_register_sysfs_inst(mISDNinstance_t *inst) {
int err;
#ifdef SYSFS_SUPPORT
char name[8];
#endif
inst->class_dev.class = &inst_dev_class;
snprintf(inst->class_dev.class_id, BUS_ID_SIZE, "inst-%08x", inst->id);
err = class_device_register(&inst->class_dev);
if (err)
return(err);
class_device_create_file(&inst->class_dev, &class_device_attr_id);
class_device_create_file(&inst->class_dev, &class_device_attr_name);
class_device_create_file(&inst->class_dev, &class_device_attr_extentions);
class_device_create_file(&inst->class_dev, &class_device_attr_regcnt);
#ifdef SYSFS_SUPPORT
err = sysfs_create_group(&inst->class_dev.kobj, &pid_group);
if (err)
goto out_unreg;
@ -97,14 +87,11 @@ mISDN_register_sysfs_inst(mISDNinstance_t *inst) {
sysfs_create_link(&inst->st->class_dev.kobj, &inst->class_dev.kobj, "mgr");
}
}
#endif
return(err);
#ifdef SYSFS_SUPPORT
out_unreg:
class_device_unregister(&inst->class_dev);
return(err);
#endif
}
void
@ -112,16 +99,13 @@ mISDN_unregister_sysfs_inst(mISDNinstance_t *inst)
{
char name[8];
if (inst && inst->id) {
if (inst->id) {
if (inst->st) {
sprintf(name,"layer.%d", inst->id & LAYER_ID_MASK);
#ifdef SYSFS_SUPPORT
sysfs_remove_link(&inst->st->class_dev.kobj, name);
sysfs_remove_link(&inst->class_dev.kobj, "stack");
if (inst->st->mgr == inst)
sysfs_remove_link(&inst->st->class_dev.kobj, "mgr");
#endif
}
class_device_unregister(&inst->class_dev);
}

View File

@ -51,19 +51,14 @@ ssize_t mISDN_show_pid_parameter(mISDN_pid_t *pid, char *buf)
char *p = buf, *t;
uint i, l;
for (i=0; i <= MAX_LAYER_NR; i++) {
if (pid->param[i]) {
if (pid->pbuf) {
t = pid->param[i] + pid->pbuf;
l = *t++;
p += sprintf(p,"0x%02x,", l);
while(l--)
p += sprintf(p,"0x%02x,", *t++);
} else {
p += sprintf(p,"0x00,");
}
} else {
t = pid->param[i];
l = *t++;
p += sprintf(p,"0x%02x,", l);
while(l--)
p += sprintf(p,"0x%02x,", *t++);
}else {
p += sprintf(p,"0x00,");
}
}
@ -72,19 +67,14 @@ ssize_t mISDN_show_pid_parameter(mISDN_pid_t *pid, char *buf)
return (p -buf);
}
#ifdef SYSFS_SUPPORT
MISDN_PROTO(mISDNobject, BPROTO, S_IRUGO);
MISDN_PROTO(mISDNobject, DPROTO, S_IRUGO);
#endif
static void release_mISDN_obj(struct class_device *dev)
{
#ifdef SYSFS_SUPPORT
mISDNobject_t *obj = to_mISDNobject(dev);
if ( core_debug & DEBUG_SYSFS)
printk(KERN_INFO "release object class dev %s\n", dev->class_id);
printk(KERN_INFO "release object class dev %s\n", dev->class_id);
if (obj->owner)
#ifdef MODULE_MKOBJ_POINTER
if (obj->owner->mkobj)
@ -92,8 +82,6 @@ static void release_mISDN_obj(struct class_device *dev)
sysfs_remove_link(&dev->kobj, "module");
sysfs_remove_group(&obj->class_dev.kobj, &BPROTO_group);
sysfs_remove_group(&obj->class_dev.kobj, &DPROTO_group);
#endif
}
static struct class obj_dev_class = {
@ -113,11 +101,9 @@ mISDN_register_sysfs_obj(mISDNobject_t *obj) {
err = class_device_register(&obj->class_dev);
if (err)
goto out;
class_device_create_file(&obj->class_dev, &class_device_attr_id);
class_device_create_file(&obj->class_dev, &class_device_attr_name);
class_device_create_file(&obj->class_dev, &class_device_attr_refcnt);
#ifdef SYSFS_SUPPORT
err = sysfs_create_group(&obj->class_dev.kobj, &BPROTO_group);
if (err)
goto out_unreg;
@ -130,16 +116,10 @@ mISDN_register_sysfs_obj(mISDNobject_t *obj) {
sysfs_create_link(&obj->class_dev.kobj, &obj->owner->mkobj->kobj, "module");
#else
sysfs_create_link(&obj->class_dev.kobj, &obj->owner->mkobj.kobj, "module");
#endif
#endif
return(err);
#ifdef SYSFS_SUPPORT
out_unreg:
class_device_unregister(&obj->class_dev);
#endif
out:
return(err);
}

View File

@ -99,7 +99,7 @@ static ssize_t store_st_parameter(struct class_device *class_dev, const char *bu
{
mISDNstack_t *st = to_mISDNstack(class_dev);
ulong tmp;
char *p = (char *)buf;
char *d, *p = (char *)buf;
u_int i, j, l;
memset(&st->new_pid.param, 0, (MAX_LAYER_NR + 1)*sizeof(st->new_pid.param[0]));
@ -131,11 +131,12 @@ static ssize_t store_st_parameter(struct class_device *class_dev, const char *bu
st->new_pid.maxplen = 0;
return(count);
}
st->new_pid.pbuf = kzalloc(l + 1, GFP_ATOMIC);
st->new_pid.pbuf = kmalloc(l, GFP_ATOMIC);
if (!st->new_pid.pbuf)
return(-ENOMEM);
st->new_pid.maxplen = l + 1;
st->new_pid.pidx = 1;
st->new_pid.maxplen = l;
d = st->new_pid.pbuf;
memset(d, 0, l);
p = (char *)buf;
for (i=0; i<=MAX_LAYER_NR; i++) {
if (!*p)
@ -145,13 +146,13 @@ static ssize_t store_st_parameter(struct class_device *class_dev, const char *bu
p++;
if (tmp) {
j = tmp;
st->new_pid.param[i] = st->new_pid.pidx;
st->new_pid.pbuf[st->new_pid.pidx++] = tmp & 0xff;
st->new_pid.param[i] = d;
*d++ = tmp & 0xff;
while(j--) {
if (!*p)
break;
tmp = simple_strtol(p, &p, 0);
st->new_pid.pbuf[st->new_pid.pidx++] = tmp & 0xff;
*d++ = tmp & 0xff;
if (*p)
p++;
else
@ -162,9 +163,7 @@ static ssize_t store_st_parameter(struct class_device *class_dev, const char *bu
return(count);
}
#ifdef SYSFS_SUPPORT
MISDN_PROTO(mISDNstack, pid, S_IRUGO);
#endif
MISDN_PROTO(mISDNstack, new_pid, S_IRUGO);
static ssize_t show_st_qlen(struct class_device *class_dev, char *buf)
@ -176,27 +175,22 @@ static CLASS_DEVICE_ATTR(qlen, S_IRUGO, show_st_qlen, NULL);
static void release_mISDN_stack(struct class_device *dev)
{
#ifdef SYSFS_SUPPORT
mISDNstack_t *st = to_mISDNstack(dev);
char name[12];
sysfs_remove_group(&st->class_dev.kobj, &pid_group);
sysfs_remove_group(&st->class_dev.kobj, &new_pid_group);
if (core_debug & DEBUG_SYSFS)
printk(KERN_INFO "release stack class dev %s\n", dev->class_id);
printk(KERN_INFO "release stack class dev %s\n", dev->class_id);
if (st->parent) {
sysfs_remove_link(&dev->kobj, "parent");
snprintf(name, 12, "child%d", (CHILD_ID_MASK & st->id) >> 16);
sysfs_remove_link(&st->parent->class_dev.kobj, name);
}
if (st->master) {
sysfs_remove_link(&dev->kobj, "master");
snprintf(name, 12, "clone%d", (CLONE_ID_MASK & st->id) >> 16);
sysfs_remove_link(&st->master->class_dev.kobj, name);
}
#endif
}
static struct class stack_dev_class = {
@ -211,9 +205,7 @@ int
mISDN_register_sysfs_stack(mISDNstack_t *st)
{
int err;
#ifdef SYSFS_SUPPORT
char name[12];
#endif
st->class_dev.class = &stack_dev_class;
if (st->id & FLG_CHILD_STACK)
@ -227,29 +219,21 @@ mISDN_register_sysfs_stack(mISDNstack_t *st)
err = class_device_register(&st->class_dev);
if (err)
return(err);
#ifdef SYSFS_SUPPORT
err = sysfs_create_group(&st->class_dev.kobj, &pid_group);
if (err)
goto out_unreg;
#endif
mISDNstack_attr_protocol_new_pid.attr.mode |= S_IWUSR;
mISDNstack_attr_protocol_new_pid.store = store_st_protocol;
mISDNstack_attr_parameter_new_pid.attr.mode |= S_IWUSR;
mISDNstack_attr_parameter_new_pid.store = store_st_parameter;
mISDNstack_attr_layermask_new_pid.attr.mode |= S_IWUSR;
mISDNstack_attr_layermask_new_pid.store = store_st_layermask;
#ifdef SYSFS_SUPPORT
err = sysfs_create_group(&st->class_dev.kobj, &new_pid_group);
if (err)
goto out_unreg;
#endif
class_device_create_file(&st->class_dev, &class_device_attr_id);
class_device_create_file(&st->class_dev, &class_device_attr_qlen);
class_device_create_file(&st->class_dev, &class_device_attr_status);
#ifdef SYSFS_SUPPORT
if (st->parent) {
sysfs_create_link(&st->class_dev.kobj, &st->parent->class_dev.kobj, "parent");
snprintf(name, 12, "child%d", (CHILD_ID_MASK & st->id) >> 16);
@ -260,14 +244,11 @@ mISDN_register_sysfs_stack(mISDNstack_t *st)
snprintf(name, 12, "clone%d", (CLONE_ID_MASK & st->id) >> 16);
sysfs_create_link(&st->master->class_dev.kobj, &st->class_dev.kobj, name);
}
#endif
return(err);
#ifdef SYSFS_SUPPORT
out_unreg:
class_device_unregister(&st->class_dev);
return(err);
#endif
}
void

View File

@ -444,7 +444,7 @@ tei_debug(struct FsmInst *fi, char *fmt, ...)
sprintf(head,"tei %s", tm->l2->inst.name);
log.fmt = fmt;
log.head = head;
mISDN_ctrl(&tm->l2->inst, MGR_DEBUGDATA | REQUEST, &log);
tm->l2->inst.obj->ctrl(&tm->l2->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}

View File

@ -8,10 +8,9 @@
#include <linux/stddef.h>
#include <linux/poll.h>
#include <linux/vmalloc.h>
#include <linux/config.h>
#include <linux/timer.h>
#ifdef CONFIG_DEVFS_FS
#include <linux/devfs_fs_kernel.h>
#endif
#include "core.h"
#define MAX_HEADER_LEN 4
@ -308,14 +307,14 @@ new_devstack(mISDNdevice_t *dev, stack_info_t *si)
return(-EINVAL);
}
}
err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &inst);
err = udev_obj.ctrl(NULL, MGR_NEWSTACK | REQUEST, &inst);
if (err) {
int_error();
return(err);
}
if (!(nds = kmalloc(sizeof(devicestack_t), GFP_ATOMIC))) {
printk(KERN_ERR "kmalloc devicestack failed\n");
mISDN_ctrl(inst.st, MGR_DELSTACK | REQUEST, NULL);
udev_obj.ctrl(inst.st, MGR_DELSTACK | REQUEST, NULL);
return(-ENOMEM);
}
memset(nds, 0, sizeof(devicestack_t));
@ -346,7 +345,7 @@ sel_channel(u_int addr, u_int channel)
return(NULL);
ci.channel = channel;
ci.st.p = NULL;
if (mISDN_ctrl(st, MGR_SELCHANNEL | REQUEST, &ci))
if (udev_obj.ctrl(st, MGR_SELCHANNEL | REQUEST, &ci))
return(NULL);
return(ci.st.p);
}
@ -510,7 +509,7 @@ create_layer(mISDNdevice_t *dev, struct sk_buff *skb)
test_and_set_bit(FLG_MGR_OWNSTACK, &nl->Flags);
}
if (st)
mISDN_ctrl(st, MGR_ADDLAYER | REQUEST, &nl->inst);
nl->inst.obj->ctrl(st, MGR_ADDLAYER | REQUEST, &nl->inst);
} else {
nl->slave = inst;
nl->inst.extentions |= EXT_INST_UNUSED;
@ -543,7 +542,7 @@ del_stack(devicestack_t *ds)
if (ds->st) {
if (ds->extentions & EXT_STACK_CLONE)
INIT_LIST_HEAD(&ds->st->childlist);
mISDN_ctrl(ds->st, MGR_DELSTACK | REQUEST, NULL);
udev_obj.ctrl(ds->st, MGR_DELSTACK | REQUEST, NULL);
}
list_del(&ds->list);
kfree(ds);
@ -582,12 +581,12 @@ del_layer(devicelayer_t *dl)
if (device_debug & DEBUG_MGR_FUNC)
printk(KERN_DEBUG "del_layer: CLEARSTACK id(%x)\n",
inst->st->id);
mISDN_ctrl(inst->st, MGR_CLEARSTACK | REQUEST, NULL);
udev_obj.ctrl(inst->st, MGR_CLEARSTACK | REQUEST, NULL);
}
dl->id = 0;
list_del(&dl->list);
if (!(inst->extentions & EXT_INST_UNUSED)) {
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
udev_obj.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
}
if (test_and_clear_bit(FLG_MGR_OWNSTACK, &dl->Flags)) {
if (dl->inst.st) {
@ -647,7 +646,7 @@ remove_if(devicelayer_t *dl, int stat) {
printk(KERN_WARNING "%s: stat not UP/DOWN\n", __FUNCTION__);
return(-EINVAL);
}
err = mISDN_ctrl(hif->peer, MGR_DISCONNECT | REQUEST, hif);
err = udev_obj.ctrl(hif->peer, MGR_DISCONNECT | REQUEST, hif);
if (phif) {
memcpy(phif, shif, sizeof(mISDNif_t));
memset(shif, 0, sizeof(mISDNif_t));
@ -1198,7 +1197,7 @@ mISDN_wdata_if(mISDNdevice_t *dev, struct sk_buff *skb)
hp->dinfo = 0;
if ((st = get_stack4id(hp->addr))) {
stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 0);
hp->len = mISDN_ctrl(st, hp->prim, skb->data);
hp->len = udev_obj.ctrl(st, hp->prim, skb->data);
} else
hp->len = -ENODEV;
hp->prim = MGR_SETSTACK | CONFIRM;
@ -1217,7 +1216,7 @@ mISDN_wdata_if(mISDNdevice_t *dev, struct sk_buff *skb)
hp->dinfo = 0;
if ((st = get_stack4id(hp->addr))) {
stack_inst_flg(dev, st, FLG_MGR_SETSTACK, 1);
hp->len = mISDN_ctrl(st, hp->prim, NULL);
hp->len = udev_obj.ctrl(st, hp->prim, NULL);
} else
hp->len = -ENODEV;
hp->prim = MGR_CLEARSTACK | CONFIRM;
@ -1279,9 +1278,8 @@ mISDN_wdata_if(mISDNdevice_t *dev, struct sk_buff *skb)
if (!(dl = get_devlayer(dev, lay)))
return(error_answer(dev, skb, -ENODEV));
hp->prim = MGR_REGLAYER | CONFIRM;
hp->len = mISDN_ctrl(st, MGR_REGLAYER | REQUEST, &dl->inst);
if (core_debug & DEBUG_MGR_FUNC)
printk(KERN_DEBUG "MGR_REGLAYER | REQUEST: ret(%d)\n", hp->len);
hp->len = udev_obj.ctrl(st, MGR_REGLAYER | REQUEST, &dl->inst);
printk(KERN_DEBUG "MGR_REGLAYER | REQUEST: ret(%d)\n", hp->len);
break;
case (MGR_UNREGLAYER | REQUEST):
lay = hp->dinfo;
@ -1291,7 +1289,7 @@ mISDN_wdata_if(mISDNdevice_t *dev, struct sk_buff *skb)
if (!(dl = get_devlayer(dev, lay)))
return(error_answer(dev, skb, -ENODEV));
hp->prim = MGR_UNREGLAYER | CONFIRM;
hp->len = mISDN_ctrl(st, MGR_UNREGLAYER | REQUEST, &dl->inst);
hp->len = udev_obj.ctrl(st, MGR_UNREGLAYER | REQUEST, &dl->inst);
break;
case (MGR_DELLAYER | REQUEST):
hp->prim = MGR_DELLAYER | CONFIRM;
@ -1409,9 +1407,8 @@ mISDN_wdata_if(mISDNdevice_t *dev, struct sk_buff *skb)
err = error_answer(dev, skb, err);
}
} else {
if (device_debug)
printk(KERN_WARNING "mISDN: prim %x addr %x not implemented\n",
hp->prim, hp->addr);
printk(KERN_WARNING "mISDN: prim %x addr %x not implemented\n",
hp->prim, hp->addr);
err = error_answer(dev, skb, -EINVAL);
}
return(err);
@ -1508,7 +1505,7 @@ free_device(mISDNdevice_t *dev)
list_del(&dev->list);
write_unlock_irqrestore(&mISDN_device_lock, flags);
if (!list_empty(&dev->entitylist)) {
if (device_debug ) printk(KERN_WARNING "MISDN %s: entitylist not empty\n", __FUNCTION__);
printk(KERN_WARNING "MISDN %s: entitylist not empty\n", __FUNCTION__);
list_for_each_safe(item, ni, &dev->entitylist) {
struct entity_item *ei = list_entry(item, struct entity_item, head);
list_del(item);
@ -1555,9 +1552,6 @@ mISDN_open(struct inode *ino, struct file *filep)
filep->private_data = dev;
if (device_debug & DEBUG_DEV_OP)
printk(KERN_DEBUG "mISDN_open out: %p %p\n", filep, filep->private_data);
mISDN_inc_usage();
return(0);
}
@ -1587,12 +1581,10 @@ mISDN_close(struct inode *ino, struct file *filep)
filep->private_data = NULL;
if (!dev->minor)
free_device(dev);
mISDN_dec_usage();
return 0;
}
}
read_unlock(&mISDN_device_lock);
mISDN_dec_usage();
printk(KERN_WARNING "mISDN: No private data while closing device\n");
return 0;
}
@ -1922,8 +1914,7 @@ udev_manager(void *data, u_int prim, void *arg) {
break;
}
if (err) {
if (device_debug)
printk(KERN_WARNING "dev_manager prim %x without device layer\n", prim);
printk(KERN_WARNING "dev_manager prim %x without device layer\n", prim);
goto out;
}
switch(prim) {
@ -1955,7 +1946,7 @@ udev_manager(void *data, u_int prim, void *arg) {
err = 0;
break;
default:
if (device_debug) printk(KERN_WARNING "dev_manager prim %x not handled\n", prim);
printk(KERN_WARNING "dev_manager prim %x not handled\n", prim);
err = -EINVAL;
break;
}
@ -1991,11 +1982,9 @@ int init_mISDNdev (int debug) {
if (err) {
printk(KERN_ERR "Can't register %s error(%d)\n", MName, err);
unregister_chrdev(mISDN_MAJOR, "mISDN");
return(err);
} else
#ifdef CONFIG_DEVFS_FS
devfs_mk_cdev(MKDEV(mISDN_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR, "mISDN");
#endif
return(err);
}
@ -2016,8 +2005,6 @@ int free_mISDNdev(void) {
if ((err = unregister_chrdev(mISDN_MAJOR, "mISDN"))) {
printk(KERN_WARNING "mISDN: devices busy on remove\n");
}
#ifdef CONFIG_DEVFS_FS
devfs_remove("mISDN");
#endif
return(err);
}

View File

@ -21,11 +21,11 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include "core.h"
#include "channel.h"
#include "layer1.h"
#include "helper.h"
@ -40,30 +40,6 @@ const char *w6692_rev = "$Revision$";
#define DBUSY_TIMER_VALUE 80
enum {
W6692_ASUS,
W6692_WINBOND,
W6692_USR
};
/* private data in the PCI devices list */
typedef struct _w6692_map{
u_int subtype;
char *name;
} w6692_map_t;
static w6692_map_t w6692_map[] =
{
{W6692_ASUS, "Dynalink/AsusCom IS64PH"},
{W6692_WINBOND, "Winbond W6692"},
{W6692_USR, "USR W6692"}
};
#ifndef PCI_VENDOR_ID_USR2
#define PCI_VENDOR_ID_USR2 0x16ec
#define PCI_DEVICE_ID_USR2_6692 0x3409
#endif
typedef struct _w6692_bc {
struct timer_list timer;
u_char b_mode;
@ -72,7 +48,6 @@ typedef struct _w6692_bc {
typedef struct _w6692pci {
struct list_head list;
struct pci_dev *pdev;
u_int subtype;
u_int irq;
u_int irqcnt;
u_int addr;
@ -143,7 +118,7 @@ W6692Version(w6692pci *card, char *s)
static void
w6692_led_handler(w6692pci *card, int on)
{
if (!card->led || card->subtype == W6692_USR)
if (!card->led)
return;
if (on) {
card->xdata &= 0xfb; /* LED ON */
@ -951,31 +926,20 @@ void initW6692(w6692pci *card)
WriteW6692B(card, 0, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
WriteW6692B(card, 1, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_XRST);
/* enable peripheral */
if (card->subtype == W6692_USR) {
/* seems that USR implemented some power control features
* Pin 79 is connected to the oscilator circuit so we
* have to handle it here
*/
card->pctl = 0x80;
card->xdata = 0;
card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 | W_PCTL_OE1 | W_PCTL_OE0;
if (card->pots) {
card->xaddr = 0x00; /* all sw off */
card->xdata = 0x06; /* LED OFF / POWER UP / ALAW */
WriteW6692(card, W_PCTL, card->pctl);
WriteW6692(card, W_XADDR, card->xaddr);
WriteW6692(card, W_XDATA, card->xdata);
} else {
card->pctl = W_PCTL_OE5 | W_PCTL_OE4 | W_PCTL_OE2 | W_PCTL_OE1 | W_PCTL_OE0;
if (card->pots) {
card->xaddr = 0x00; /* all sw off */
card->xdata |= 0x06; /* POWER UP/ LED OFF / ALAW */
WriteW6692(card, W_PCTL, card->pctl);
WriteW6692(card, W_XADDR, card->xaddr);
WriteW6692(card, W_XDATA, card->xdata);
val = ReadW6692(card, W_XADDR);
if (card->dch.debug & L1_DEB_ISAC)
mISDN_debugprint(&card->dch.inst, "W_XADDR: %02x", val);
if (card->led & W_LED1_ON)
w6692_led_handler(card, 1);
else
w6692_led_handler(card, 0);
}
val = ReadW6692(card, W_XADDR);
if (card->dch.debug & L1_DEB_ISAC)
mISDN_debugprint(&card->dch.inst, "W_XADDR: %02x", val);
if (card->led & W_LED1_ON)
w6692_led_handler(card, 1);
else
w6692_led_handler(card, 0);
}
}
@ -1028,6 +992,7 @@ static int init_card(w6692pci *card)
}
#define MAX_CARDS 4
#define MODULE_PARM_T "1-4i"
static int w6692_cnt;
static u_int protocol[MAX_CARDS];
static int layermask[MAX_CARDS];
@ -1037,33 +1002,16 @@ static int debug;
static int pots[MAX_CARDS];
static int led[MAX_CARDS];
#ifdef MODULE
MODULE_AUTHOR("Karsten Keil");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#define MODULE_PARM_T "1-4i"
MODULE_PARM(led, MODULE_PARM_T);
MODULE_PARM(pots, MODULE_PARM_T);
MODULE_PARM(protocol, MODULE_PARM_T);
MODULE_PARM(layermask, MODULE_PARM_T);
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#ifdef OLD_MODULE_PARAM_ARRAY
static int num_led=0, num_pots=0, num_protocol=0, num_layermask=0;
module_param_array(led, uint, num_led, S_IRUGO | S_IWUSR);
module_param_array(pots, uint, num_pots, S_IRUGO | S_IWUSR);
module_param_array(protocol, uint, num_protocol, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, num_layermask, S_IRUGO | S_IWUSR);
#else
module_param_array(led, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(pots, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(protocol, uint, NULL, S_IRUGO | S_IWUSR);
module_param_array(layermask, uint, NULL, S_IRUGO | S_IWUSR);
#endif
#endif
#endif
/******************************/
@ -1297,7 +1245,7 @@ release_card(w6692pci *card)
spin_lock_irqsave(&card->lock, flags);
mode_w6692(&card->bch[0], 0, ISDN_PID_NONE);
mode_w6692(&card->bch[1], 1, ISDN_PID_NONE);
if (card->led || card->subtype == W6692_USR) {
if (card->led) {
card->xdata |= 0x04; /* LED OFF */
WriteW6692(card, W_XDATA, card->xdata);
}
@ -1306,7 +1254,7 @@ release_card(w6692pci *card)
mISDN_freechannel(&card->bch[0]);
mISDN_freechannel(&card->dch);
spin_unlock_irqrestore(&card->lock, flags);
mISDN_ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
w6692.ctrl(&card->dch.inst, MGR_UNREGLAYER | REQUEST, NULL);
spin_lock_irqsave(&w6692.lock, flags);
list_del(&card->list);
spin_unlock_irqrestore(&w6692.lock, flags);
@ -1368,7 +1316,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
dev_kfree_skb(skb);
} else
printk(KERN_WARNING "no SKB in %s MGR_UNREGLAYER | REQUEST\n", __FUNCTION__);
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
w6692.ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
break;
case MGR_CLRSTPARA | INDICATION:
arg = NULL;
@ -1422,7 +1370,7 @@ w6692_manager(void *data, u_int prim, void *arg) {
return(0);
}
static int setup_instance(w6692pci *card)
static int __devinit setup_instance(w6692pci *card)
{
int i, err;
mISDN_pid_t pid;
@ -1468,31 +1416,31 @@ static int setup_instance(w6692pci *card)
card->pots = pots[w6692_cnt];
card->led = led[w6692_cnt];
w6692_cnt++;
err = mISDN_ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
err = w6692.ctrl(NULL, MGR_NEWSTACK | REQUEST, &card->dch.inst);
if (err) {
release_card(card);
return(err);
}
for (i=0; i<2; i++) {
err = mISDN_ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
err = w6692.ctrl(card->dch.inst.st, MGR_NEWSTACK | REQUEST, &card->bch[i].inst);
if (err) {
printk(KERN_ERR "MGR_ADDSTACK bchan error %d\n", err);
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
}
err = mISDN_ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
err = w6692.ctrl(card->dch.inst.st, MGR_SETSTACK | REQUEST, &pid);
if (err) {
printk(KERN_ERR "MGR_SETSTACK REQUEST dch err(%d)\n", err);
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
err = init_card(card);
if (err) {
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
return(err);
}
mISDN_ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
w6692.ctrl(card->dch.inst.st, MGR_CTRLREADY | INDICATION, NULL);
printk(KERN_INFO "w6692 %d cards installed\n", w6692_cnt);
return(0);
}
@ -1501,7 +1449,6 @@ static int __devinit w6692_probe(struct pci_dev *pdev, const struct pci_device_i
{
int err = -ENOMEM;
w6692pci *card;
w6692_map_t *m = (w6692_map_t *)ent->driver_data;
if (!(card = kmalloc(sizeof(w6692pci), GFP_ATOMIC))) {
printk(KERN_ERR "No kmem for w6692 card\n");
@ -1509,7 +1456,6 @@ static int __devinit w6692_probe(struct pci_dev *pdev, const struct pci_device_i
}
memset(card, 0, sizeof(w6692pci));
card->pdev = pdev;
card->subtype = m->subtype;
err = pci_enable_device(pdev);
if (err) {
kfree(card);
@ -1517,7 +1463,7 @@ static int __devinit w6692_probe(struct pci_dev *pdev, const struct pci_device_i
}
printk(KERN_INFO "mISDN_w6692: found adapter %s at %s\n",
m->name, pci_name(pdev));
(char *) ent->driver_data, pci_name(pdev));
card->addr = pci_resource_start(pdev, 1);
card->irq = pdev->irq;
@ -1531,18 +1477,31 @@ static void __devexit w6692_remove_pci(struct pci_dev *pdev)
w6692pci *card = pci_get_drvdata(pdev);
if (card)
mISDN_ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
w6692.ctrl(card->dch.inst.st, MGR_DELSTACK | REQUEST, NULL);
else
printk(KERN_WARNING "%s: drvdata allready removed\n", __FUNCTION__);
}
static struct pci_device_id w6692_ids[] = {
/* table entry in the PCI devices list */
typedef struct {
int vendor_id;
int device_id;
char *vendor_name;
char *card_name;
} PCI_ENTRY;
static const PCI_ENTRY id_list[] =
{
{PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, "Dynalink/AsusCom", "IS64PH"},
{PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, "Winbond", "W6692"},
{0, 0, NULL, NULL}
};
static struct pci_device_id w6692_ids[] __devinitdata = {
{ PCI_VENDOR_ID_DYNALINK, PCI_DEVICE_ID_DYNALINK_IS64PH, PCI_ANY_ID, PCI_ANY_ID,
0, 0, (unsigned long) &w6692_map[0] },
{ PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, PCI_VENDOR_ID_USR2, PCI_DEVICE_ID_USR2_6692,
0, 0, (unsigned long) &w6692_map[2] },
0, 0, (unsigned long) "Dynalink/AsusCom IS64PH" },
{ PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_6692, PCI_ANY_ID, PCI_ANY_ID,
0, 0, (unsigned long) &w6692_map[1] },
0, 0, (unsigned long) "Winbond W6692" },
{ }
};
MODULE_DEVICE_TABLE(pci, w6692_ids);
@ -1589,9 +1548,6 @@ static int __init w6692_init(void)
goto out;
}
#endif
mISDN_module_register(THIS_MODULE);
return 0;
out:
@ -1604,8 +1560,6 @@ static void __exit w6692_cleanup(void)
int err;
w6692pci *card, *next;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&w6692))) {
printk(KERN_ERR "Can't unregister Winbond W6692 PCI error(%d)\n", err);
}

View File

@ -12,8 +12,8 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include "core.h"
#include "x25_l3.h"
#include "helper.h"
#include "debug.h"
@ -1256,11 +1256,7 @@ static char MName[] = "X25_DTE";
#ifdef MODULE
MODULE_AUTHOR("Karsten Keil");
#ifdef OLD_MODULE_PARAM
MODULE_PARM(debug, "1i");
#else
module_param(debug, uint, S_IRUGO | S_IWUSR);
#endif
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
#endif
@ -1369,7 +1365,6 @@ x25_dte_init(void)
dte_dfsm.strEvent = X25strDEvent;
dte_dfsm.strState = X25strDState;
mISDN_FsmNew(&dte_dfsm, DFnList, D_FN_COUNT);
mISDN_module_register(THIS_MODULE);
}
return(err);
}
@ -1380,8 +1375,6 @@ x25_dte_cleanup(void)
x25_l3_t *l3, *nl3;
int err;
mISDN_module_unregister(THIS_MODULE);
if ((err = mISDN_unregister(&x25dte_obj))) {
printk(KERN_ERR "Can't unregister l3x25 error(%d)\n", err);
}

View File

@ -12,6 +12,7 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include "x25_l3.h"
#include "helper.h"
@ -124,7 +125,7 @@ l3m_debug(struct FsmInst *fi, char *fmt, ...)
va_start(log.args, fmt);
log.fmt = fmt;
log.head = l3->inst.name;
mISDN_ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
l3->inst.obj->ctrl(&l3->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}
@ -228,7 +229,7 @@ l3c_debug(struct FsmInst *fi, char *fmt, ...)
va_start(log.args, fmt);
log.fmt = fmt;
log.head = l3c->l3->inst.name;
mISDN_ctrl(&l3c->l3->inst, MGR_DEBUGDATA | REQUEST, &log);
l3c->l3->inst.obj->ctrl(&l3c->l3->inst, MGR_DEBUGDATA | REQUEST, &log);
va_end(log.args);
}
@ -574,9 +575,9 @@ X25_release_l3(x25_l3_t *l3) {
mISDN_FsmDelTimer(&l3->TR, 3);
if (inst->obj) {
if (l3->entity != MISDN_ENTITY_NONE)
mISDN_ctrl(inst, MGR_DELENTITY | REQUEST,
inst->obj->ctrl(inst, MGR_DELENTITY | REQUEST,
(void *)((u_long)l3->entity));
mISDN_ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
inst->obj->ctrl(inst, MGR_UNREGLAYER | REQUEST, NULL);
}
kfree(l3);
}
@ -678,8 +679,8 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
}
n_l3->debug = debug;
n_l3->B3cfg = (x25_B3_cfg_t)DEFAULT_X25_B3_CFG;
if (pid->param[3] && pid->pbuf) {
u_char *p = pid->pbuf + pid->param[3];
if (pid->param[3]) {
u_char *p = pid->param[3];
memcpy(&n_l3->B3cfg, &p[1], p[0]);
}
if (n_l3->B3cfg.modulo == 128)
@ -703,12 +704,12 @@ new_x25_l3(x25_l3_t **l3_p, mISDNstack_t *st, mISDN_pid_t *pid, mISDNobject_t *o
spin_lock_irqsave(&obj->lock, flags);
list_add_tail(&n_l3->list, &obj->ilist);
spin_unlock_irqrestore(&obj->lock, flags);
err = mISDN_ctrl(&n_l3->inst, MGR_NEWENTITY | REQUEST, NULL);
err = obj->ctrl(&n_l3->inst, MGR_NEWENTITY | REQUEST, NULL);
if (err) {
printk(KERN_WARNING "mISDN %s: MGR_NEWENTITY REQUEST failed err(%d)\n",
__FUNCTION__, err);
}
err = mISDN_ctrl(st, MGR_REGLAYER | INDICATION, &n_l3->inst);
err = obj->ctrl(st, MGR_REGLAYER | INDICATION, &n_l3->inst);
if (err) {
list_del(&n_l3->list);
kfree(n_l3);

View File

@ -32,12 +32,12 @@ struct _x25_B3_cfg {
#define DEFAULT_X25_B3_CFG {0, 0, 1, 1, 0, 0, 8, 2}
struct _x25_ncpi {
__u8 len;
__u8 Flags;
__u8 Group;
__u8 Channel;
__u8 Contens[4]; /* Note this can be less/more bytes in use */
} __attribute__((packed));
__u8 len __attribute__((packed));
__u8 Flags __attribute__((packed));
__u8 Group __attribute__((packed));
__u8 Channel __attribute__((packed));
__u8 Contens[4] __attribute__((packed)); /* Note this can be less/more bytes in use */
};
struct _x25_ConfQueue {
__u32 PktId;

View File

@ -21,6 +21,7 @@
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/delay.h>
#include "xhfc_su.h"
@ -59,8 +60,6 @@ static PCI2PI_cfg PCI2PI_config = {
.eep_recover = 4,
};
/* base addr to address several XHFCs on one PCI2PI bridge */
__u32 PCI2PI_XHFC_OFFSETS[PCI2PI_MAX_XHFC] = {0, 0x400};
/***********************************/
@ -68,18 +67,18 @@ __u32 PCI2PI_XHFC_OFFSETS[PCI2PI_MAX_XHFC] = {0, 0x400};
/* return 0 on success. */
/***********************************/
int
init_pci_bridge(xhfc_pi * pi)
init_pci_bridge(xhfc_hw * hw)
{
int err = -ENODEV;
printk(KERN_INFO "%s %s: using PCI2PI Bridge at 0x%p\n",
pi->name, __FUNCTION__, pi->hw_membase);
hw->card_name, __FUNCTION__, hw->hw_membase);
/* test if Bridge regsiter accessable */
WritePCI2PI_u32(pi, PCI2PI_DEL_CS, 0x0);
if (ReadPCI2PI_u32(pi, PCI2PI_DEL_CS) == 0x00) {
WritePCI2PI_u32(pi, PCI2PI_DEL_CS, 0xFFFFFFFF);
if (ReadPCI2PI_u32(pi, PCI2PI_DEL_CS) == 0xF) {
WritePCI2PI_u32(hw, PCI2PI_DEL_CS, 0x0);
if (ReadPCI2PI_u32(hw, PCI2PI_DEL_CS) == 0x00) {
WritePCI2PI_u32(hw, PCI2PI_DEL_CS, 0xFFFFFFFF);
if (ReadPCI2PI_u32(hw, PCI2PI_DEL_CS) == 0xF) {
err = 0;
}
}
@ -87,48 +86,48 @@ init_pci_bridge(xhfc_pi * pi)
return (err);
/* enable hardware reset XHFC */
WritePCI2PI_u32(pi, PCI2PI_GPIO_OUT, GPIO_OUT_VAL);
WritePCI2PI_u32(hw, PCI2PI_GPIO_OUT, GPIO_OUT_VAL);
WritePCI2PI_u32(pi, PCI2PI_PI_MODE, PCI2PI_config.pi_mode);
WritePCI2PI_u32(pi, PCI2PI_DEL_CS, PCI2PI_config.del_cs);
WritePCI2PI_u32(pi, PCI2PI_DEL_RD, PCI2PI_config.del_rd);
WritePCI2PI_u32(pi, PCI2PI_DEL_WR, PCI2PI_config.del_wr);
WritePCI2PI_u32(pi, PCI2PI_DEL_ALE, PCI2PI_config.del_ale);
WritePCI2PI_u32(pi, PCI2PI_DEL_ADR, PCI2PI_config.del_adr);
WritePCI2PI_u32(pi, PCI2PI_DEL_DOUT, PCI2PI_config.del_dout);
WritePCI2PI_u32(pi, PCI2PI_DEFAULT_ADR, PCI2PI_config.default_adr);
WritePCI2PI_u32(pi, PCI2PI_DEFAULT_DOUT,
WritePCI2PI_u32(hw, PCI2PI_PI_MODE, PCI2PI_config.pi_mode);
WritePCI2PI_u32(hw, PCI2PI_DEL_CS, PCI2PI_config.del_cs);
WritePCI2PI_u32(hw, PCI2PI_DEL_RD, PCI2PI_config.del_rd);
WritePCI2PI_u32(hw, PCI2PI_DEL_WR, PCI2PI_config.del_wr);
WritePCI2PI_u32(hw, PCI2PI_DEL_ALE, PCI2PI_config.del_ale);
WritePCI2PI_u32(hw, PCI2PI_DEL_ADR, PCI2PI_config.del_adr);
WritePCI2PI_u32(hw, PCI2PI_DEL_DOUT, PCI2PI_config.del_dout);
WritePCI2PI_u32(hw, PCI2PI_DEFAULT_ADR, PCI2PI_config.default_adr);
WritePCI2PI_u32(hw, PCI2PI_DEFAULT_DOUT,
PCI2PI_config.default_dout);
WritePCI2PI_u32(pi, PCI2PI_CYCLE_SHD, 0x80 * PCI2PI_config.setup
WritePCI2PI_u32(hw, PCI2PI_CYCLE_SHD, 0x80 * PCI2PI_config.setup
+ 0x40 * PCI2PI_config.hold + PCI2PI_config.cycle);
WritePCI2PI_u32(pi, PCI2PI_ALE_ADR_WHSF,
WritePCI2PI_u32(hw, PCI2PI_ALE_ADR_WHSF,
PCI2PI_config.ale_adr_first +
PCI2PI_config.ale_adr_setup * 2 +
PCI2PI_config.ale_adr_hold * 4 +
PCI2PI_config.ale_adr_wait * 8);
WritePCI2PI_u32(pi, PCI2PI_CYCLE_PAUSE,
WritePCI2PI_u32(hw, PCI2PI_CYCLE_PAUSE,
0x10 * PCI2PI_config.pause_seq +
PCI2PI_config.pause_end);
WritePCI2PI_u32(pi, PCI2PI_STATUS_INT_ENABLE,
WritePCI2PI_u32(hw, PCI2PI_STATUS_INT_ENABLE,
PCI2PI_config.status_int_enable);
WritePCI2PI_u32(pi, PCI2PI_PI_INT_POL,
WritePCI2PI_u32(hw, PCI2PI_PI_INT_POL,
2 * PCI2PI_config.pi_wait_enable +
PCI2PI_config.pi_int_pol);
WritePCI2PI_u32(pi, PCI2PI_SPI_CFG0, PCI2PI_config.spi_cfg0);
WritePCI2PI_u32(pi, PCI2PI_SPI_CFG1, PCI2PI_config.spi_cfg1);
WritePCI2PI_u32(pi, PCI2PI_SPI_CFG2, PCI2PI_config.spi_cfg2);
WritePCI2PI_u32(pi, PCI2PI_SPI_CFG3, PCI2PI_config.spi_cfg3);
WritePCI2PI_u32(pi, PCI2PI_EEP_RECOVER, PCI2PI_config.eep_recover);
ReadPCI2PI_u32(pi, PCI2PI_STATUS);
WritePCI2PI_u32(hw, PCI2PI_SPI_CFG0, PCI2PI_config.spi_cfg0);
WritePCI2PI_u32(hw, PCI2PI_SPI_CFG1, PCI2PI_config.spi_cfg1);
WritePCI2PI_u32(hw, PCI2PI_SPI_CFG2, PCI2PI_config.spi_cfg2);
WritePCI2PI_u32(hw, PCI2PI_SPI_CFG3, PCI2PI_config.spi_cfg3);
WritePCI2PI_u32(hw, PCI2PI_EEP_RECOVER, PCI2PI_config.eep_recover);
ReadPCI2PI_u32(hw, PCI2PI_STATUS);
/* release hardware reset XHFC */
WritePCI2PI_u32(pi, PCI2PI_GPIO_OUT, GPIO_OUT_VAL | PCI2PI_GPIO7_NRST);
WritePCI2PI_u32(hw, PCI2PI_GPIO_OUT, GPIO_OUT_VAL | PCI2PI_GPIO7_NRST);
udelay(10);
return (err);

View File

@ -60,10 +60,6 @@
#define XHFC_2S4U_BOND PCI2PI_GPIO1_BOND1
#define XHFC_4SU_BOND PCI2PI_GPIO1_BOND1 | PCI2PI_GPIO0_BOND0
/* membase offset to address XHFC controllers */
#define PCI2PI_MAX_XHFC 2
extern __u32 PCI2PI_XHFC_OFFSETS[PCI2PI_MAX_XHFC];
/*******************************************************/
/*******************************************************/
@ -275,39 +271,39 @@ read and write functions to access registers of the PCI bridge
*/
static inline __u8
ReadPCI2PI_u8(xhfc_pi * pi, __u16 reg_addr)
ReadPCI2PI_u8(xhfc_hw * hw, __u16 reg_addr)
{
return (*(volatile __u8 *) (pi->membase + reg_addr));
return (*(volatile __u8 *) (hw->membase + reg_addr));
}
static inline __u16
ReadPCI2PI_u16(xhfc_pi * pi, __u16 reg_addr)
ReadPCI2PI_u16(xhfc_hw * hw, __u16 reg_addr)
{
return (*(volatile __u16 *) (pi->membase + reg_addr));
return (*(volatile __u16 *) (hw->membase + reg_addr));
}
static inline __u32
ReadPCI2PI_u32(xhfc_pi * pi, __u16 reg_addr)
ReadPCI2PI_u32(xhfc_hw * hw, __u16 reg_addr)
{
return (*(volatile __u32 *) (pi->membase + reg_addr));
return (*(volatile __u32 *) (hw->membase + reg_addr));
}
static inline void
WritePCI2PI_u8(xhfc_pi * pi, __u16 reg_addr, __u8 value)
WritePCI2PI_u8(xhfc_hw * hw, __u16 reg_addr, __u8 value)
{
*((volatile __u8 *) (pi->membase + reg_addr)) = value;
*((volatile __u8 *) (hw->membase + reg_addr)) = value;
}
static inline void
WritePCI2PI_u16(xhfc_pi * pi, __u16 reg_addr, __u16 value)
WritePCI2PI_u16(xhfc_hw * hw, __u16 reg_addr, __u16 value)
{
*((volatile __u16 *) (pi->membase + reg_addr)) = value;
*((volatile __u16 *) (hw->membase + reg_addr)) = value;
}
static inline void
WritePCI2PI_u32(xhfc_pi * pi, __u16 reg_addr, __u32 value)
WritePCI2PI_u32(xhfc_hw * hw, __u16 reg_addr, __u32 value)
{
*((volatile __u32 *) (pi->membase + reg_addr)) = value;
*((volatile __u32 *) (hw->membase + reg_addr)) = value;
}
@ -343,9 +339,9 @@ these modes is not interrupted by its own interrupt handler.
functions for multiplexed access
*/
static inline __u8
read_xhfc(xhfc_t * xhfc, __u8 reg_addr)
read_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
return (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2)));
return (*(volatile __u8 *) (hw->membase + (reg_addr << 2)));
}
@ -355,22 +351,22 @@ e.g. A_FIFO_DATA
this function is only defined for software compatibility here
*/
static inline __u32
read32_xhfc(xhfc_t * xhfc, __u8 reg_addr)
read32_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
__u32 value;
value = (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2)));
value |= (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) << 8;
value |= (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) << 16;
value |= (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) << 24;
value = (*(volatile __u8 *) (hw->membase + (reg_addr << 2)));
value |= (*(volatile __u8 *) (hw->membase + (reg_addr << 2))) << 8;
value |= (*(volatile __u8 *) (hw->membase + (reg_addr << 2))) << 16;
value |= (*(volatile __u8 *) (hw->membase + (reg_addr << 2))) << 24;
return (value);
}
static inline void
write_xhfc(xhfc_t * xhfc, __u8 reg_addr, __u8 value)
write_xhfc(xhfc_hw * hw, __u8 reg_addr, __u8 value)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) = value;
*((volatile __u8 *) (hw->membase + (reg_addr << 2))) = value;
}
/*
@ -379,12 +375,12 @@ e.g. A_FIFO_DATA
this function is only defined for software compatibility here
*/
static inline void
write32_xhfc(xhfc_t * xhfc, __u8 reg_addr, __u32 value)
write32_xhfc(xhfc_hw * hw, __u8 reg_addr, __u32 value)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) = value & 0xff;
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) = (value >>8) & 0xff;
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) = (value >>16) & 0xff;
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2))) = (value >>24) & 0xff;
*((volatile __u8 *) (hw->membase + (reg_addr << 2))) = value & 0xff;
*((volatile __u8 *) (hw->membase + (reg_addr << 2))) = (value >>8) & 0xff;
*((volatile __u8 *) (hw->membase + (reg_addr << 2))) = (value >>16) & 0xff;
*((volatile __u8 *) (hw->membase + (reg_addr << 2))) = (value >>24) & 0xff;
}
@ -393,10 +389,10 @@ this allows to read ram based registers
that normally requires long read access times
*/
static inline __u8
sread_xhfc(xhfc_t * xhfc, __u8 reg_addr)
sread_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
(*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (reg_addr << 2)));
return (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + (R_INT_DATA << 2)));
(*(volatile __u8 *) (hw->membase + (reg_addr << 2)));
return (*(volatile __u8 *) (hw->membase + (R_INT_DATA << 2)));
}
/* this function reads the currently selected regsiter from XHFC and is only
@ -404,7 +400,7 @@ required for non multiplexed access modes. For multiplexed access modes this
function is only defined for for software compatibility. */
static inline __u8
read_xhfcregptr(xhfc_t * xhfc)
read_xhfcregptr(xhfc_hw * hw)
{
return 0;
}
@ -414,7 +410,7 @@ required for non multiplexed access modes. For multiplexed access modes this
function is only defined for for software compatibility. */
static inline void
write_xhfcregptr(xhfc_t * xhfc, __u8 reg_addr)
write_xhfcregptr(xhfc_hw * hw, __u8 reg_addr)
{
}
@ -436,10 +432,10 @@ port is accessed with PCI address A2=0
*/
static inline __u8
read_xhfc(xhfc_t * xhfc, __u8 reg_addr)
read_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4)) = reg_addr;
return (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx]));
*((volatile __u8 *) (hw->membase + 4)) = reg_addr;
return (*(volatile __u8 *) (hw->membase));
}
@ -451,17 +447,17 @@ PCI bridge generates for 8 bit data read cycles at the local bus interface.
*/
static inline __u32
read32_xhfc(xhfc_t * xhfc, __u8 reg_addr)
read32_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4)) = reg_addr;
return (*(volatile __u32 *) xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx]);
*((volatile __u8 *) (hw->membase + 4)) = reg_addr;
return (*(volatile __u32 *) hw->membase);
}
static inline void
write_xhfc(xhfc_t * xhfc, __u8 reg_addr, __u8 value)
write_xhfc(xhfc_hw * hw, __u8 reg_addr, __u8 value)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4)) = reg_addr;
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx])) = value;
*((volatile __u8 *) (hw->membase + 4)) = reg_addr;
*((volatile __u8 *) (hw->membase)) = value;
}
/*
@ -472,10 +468,10 @@ local bus interface.
*/
static inline void
write32_xhfc(xhfc_t * xhfc, __u8 reg_addr, __u32 value)
write32_xhfc(xhfc_hw * hw, __u8 reg_addr, __u32 value)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4)) = reg_addr;
*((volatile __u32 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx])) = value;
*((volatile __u8 *) (hw->membase + 4)) = reg_addr;
*((volatile __u32 *) (hw->membase)) = value;
}
@ -486,13 +482,13 @@ registers that normally requires long read access times
*/
static inline __u8
sread_xhfc(xhfc_t * xhfc, __u8 reg_addr)
sread_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4)) = reg_addr;
(*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] ));
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4)) = R_INT_DATA;
return (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx]));
*((volatile __u8 *) (hw->membase + 4)) = reg_addr;
(*(volatile __u8 *) (hw->membase));
*((volatile __u8 *) (hw->membase + 4)) = R_INT_DATA;
return (*(volatile __u8 *) (hw->membase));
}
/*
@ -501,17 +497,17 @@ this function reads the currently selected regsiter from XHFC
*/
static inline __u8
read_xhfcregptr(xhfc_t * xhfc)
read_xhfcregptr(xhfc_hw * hw)
{
return (*(volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4));
return (*(volatile __u8 *) (hw->membase + 4));
}
/* this function writes the XHFC register address pointer */
static inline void
write_xhfcregptr(xhfc_t * xhfc, __u8 reg_addr)
write_xhfcregptr(xhfc_hw * hw, __u8 reg_addr)
{
*((volatile __u8 *) (xhfc->pi->membase + PCI2PI_XHFC_OFFSETS[xhfc->chipidx] + 4)) = reg_addr;
*((volatile __u8 *) (hw->membase + 4)) = reg_addr;
}
@ -539,12 +535,12 @@ functions for SPI access
static inline __u8
read_xhfc(xhfc_t * xhfc, __u8 reg_addr)
read_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 32 clock SPI master transfer
WritePCI2PI_u32(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR | xhfc->chipidx) << 24) | (reg_addr << 16) | ((SPI_DATA | SPI_RD) << 8));
WritePCI2PI_u32(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR) << 24) | (reg_addr << 16) | ((SPI_DATA | SPI_RD) << 8));
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// read data from the SPI data receive register and return one byte
@ -559,33 +555,33 @@ read four bytes from the same register address by using a SPI multiple read acce
*/
static inline __u32
read32_xhfc(xhfc_t * xhfc, __u8 reg_addr)
read32_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 16 clock SPI master transfer
WritePCI2PI_u16(xhfc->pi, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR | xhfc->chipidx) << 8) | reg_addr);
WritePCI2PI_u16(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR) << 8) | reg_addr);
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 8 clock SPI master transfer
WritePCI2PI_u8(xhfc->pi, PCI2PI_SPI_MO_DATA, (SPI_DATA | SPI_RD | SPI_MULTI));
WritePCI2PI_u8(hw, PCI2PI_SPI_MO_DATA, (SPI_DATA | SPI_RD | SPI_MULTI));
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 32 clock SPI master transfer
// output data is arbitrary
WritePCI2PI_u32(xhfc->pi, PCI2PI_SPI_MO_DATA, 0);
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
WritePCI2PI_u32(hw, PCI2PI_SPI_MO_DATA, 0);
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// read data from the SPI data receive register and return four bytes
return (__u32) be32_to_cpu(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_MI_DATA));
return (__u32) be32_to_cpu(ReadPCI2PI_u32(hw, PCI2PI_SPI_MI_DATA));
}
static inline void
write_xhfc(xhfc_t * xhfc, __u8 reg_addr, __u8 value)
write_xhfc(xhfc_hw * hw, __u8 reg_addr, __u8 value)
{
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 32 clock SPI master transfer
WritePCI2PI_u32(xhfc->pi, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR | xhfc->chipidx) << 24) | (reg_addr << 16) | ((SPI_DATA | SPI_WR) << 8) | value);
WritePCI2PI_u32(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR) << 24) | (reg_addr << 16) | ((SPI_DATA | SPI_WR) << 8) | value);
}
/*
@ -595,20 +591,20 @@ multiple write access
*/
static inline void
write32_xhfc(xhfc_t * xhfc, __u8 reg_addr, __u32 value)
write32_xhfc(xhfc_hw * hw, __u8 reg_addr, __u32 value)
{
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 16 clock SPI master transfer
WritePCI2PI_u16(xhfc->pi, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR | xhfc->chipidx) << 8) | reg_addr);
WritePCI2PI_u16(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR) << 8) | reg_addr);
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 8 clock SPI master transfer
WritePCI2PI_u8(xhfc->pi, PCI2PI_SPI_MO_DATA, (SPI_DATA | SPI_WR | SPI_MULTI));
WritePCI2PI_u8(hw, PCI2PI_SPI_MO_DATA, (SPI_DATA | SPI_WR | SPI_MULTI));
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 32 clock SPI master transfer
WritePCI2PI_u32(xhfc->pi, PCI2PI_SPI_MO_DATA, cpu_to_be32(value));
WritePCI2PI_u32(hw, PCI2PI_SPI_MO_DATA, cpu_to_be32(value));
}
@ -619,24 +615,24 @@ registers that normally requires long read access times
*/
static inline __u8
sread_xhfc(xhfc_t * xhfc, __u8 reg_addr)
sread_xhfc(xhfc_hw * hw, __u8 reg_addr)
{
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 32 clock SPI master transfer
WritePCI2PI_u32(xhfc->pi, PCI2PI_SPI_MO_DATA ,((SPI_ADDR | SPI_WR | xhfc->chipidx) << 24) | (reg_addr << 16) | ((SPI_DATA | SPI_RD) << 8));
WritePCI2PI_u32(hw, PCI2PI_SPI_MO_DATA ,((SPI_ADDR | SPI_WR) << 24) | (reg_addr << 16) | ((SPI_DATA | SPI_RD) << 8));
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 32 clock SPI master transfer to read R_INT_DATA register
WritePCI2PI_u32(xhfc->pi, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR | xhfc->chipidx) << 24) | (R_INT_DATA << 16) | ((SPI_DATA | SPI_RD) << 8));
WritePCI2PI_u32(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR) << 24) | (R_INT_DATA << 16) | ((SPI_DATA | SPI_RD) << 8));
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// read data from the SPI data receive register and return one byte
return (__u8) (ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_MI_DATA) & 0xFF);
return (__u8) (ReadPCI2PI_u32(hw, PCI2PI_SPI_MI_DATA) & 0xFF);
}
/*
@ -645,27 +641,27 @@ this function reads the currently selected regsiter from XHFC
*/
static inline __u8
read_xhfcregptr(xhfc_t * xhfc)
read_xhfcregptr(xhfc_hw * hw)
{
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 16 clock SPI master transfer
WritePCI2PI_u16(xhfc->pi, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_RD | xhfc->chipidx) << 8));
WritePCI2PI_u16(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_RD) << 8));
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// read data from the SPI data receive register and return one byte
return (__u8) (ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_MI_DATA) & 0xFF);
return (__u8) (ReadPCI2PI_u32(hw, PCI2PI_SPI_MI_DATA) & 0xFF);
}
/* this function writes the XHFC register address pointer */
static inline void
write_xhfcregptr(xhfc_t * xhfc, __u8 reg_addr)
write_xhfcregptr(xhfc_hw * hw, __u8 reg_addr)
{
// wait until SPI master is idle
while (!(ReadPCI2PI_u32(xhfc->pi, PCI2PI_SPI_STATUS) & 1));
while (!(ReadPCI2PI_u32(hw, PCI2PI_SPI_STATUS) & 1));
// initiate a 16 clock SPI master transfer
WritePCI2PI_u16(xhfc->pi, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR | xhfc->chipidx) << 8) | reg_addr);
WritePCI2PI_u16(hw, PCI2PI_SPI_MO_DATA, ((SPI_ADDR | SPI_WR) << 8) | reg_addr);
}
#endif /* PI_MODE == PI_SPI */
@ -673,6 +669,6 @@ write_xhfcregptr(xhfc_t * xhfc, __u8 reg_addr)
/* Function Prototypes */
int init_pci_bridge(xhfc_pi * pi);
int init_pci_bridge(xhfc_hw * hw);
#endif /* _XHFC_PCI2PI_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -42,13 +42,14 @@
#ifndef CHIP_ID_2SU
#define CHIP_ID_2SU 0x61
#endif
/* define bridge for chip register access */
#define BRIDGE_UNKWOWN 0
#define BRIDGE_PCI2PI 1 /* used at Cologne Chip AG's Evaluation Card */
#define BRIDGE BRIDGE_PCI2PI
#define MAX_PORT 4
#define CHAN_PER_PORT 4 /* D, B1, B2, PCM */
#define MAX_CHAN MAX_PORT * CHAN_PER_PORT
@ -60,13 +61,9 @@
#define PORT_MODE_S0 0x0004
#define PORT_MODE_UP 0x0008
#define PORT_MODE_EXCH_POL 0x0010
#define PORT_MODE_LOOP_B1 0x0020
#define PORT_MODE_LOOP_B2 0x0040
#define PORT_MODE_LOOP_D 0x0080
#define PORT_MODE_LOOP 0x0020
#define NT_TIMER 0x8000
#define PORT_MODE_LOOPS 0xE0 /* mask port mode Loop B1/B2/D */
/* NT / TE defines */
#define NT_T1_COUNT 25 /* number of 4ms interrupts for G2 timeout */
@ -79,14 +76,12 @@
#define XHFC_TIMER_T4 500 /* 500ms deactivation timer T4 */
/* xhfc Layer1 physical commands */
#define HFC_L1_ACTIVATE_TE 0x00
#define HFC_L1_FORCE_DEACTIVATE_TE 0x01
#define HFC_L1_ACTIVATE_NT 0x02
#define HFC_L1_DEACTIVATE_NT 0x03
#define HFC_L1_TESTLOOP_B1 0x04
#define HFC_L1_TESTLOOP_B2 0x05
#define HFC_L1_TESTLOOP_D 0x06
#define HFC_L1_ACTIVATE_TE 0x01
#define HFC_L1_FORCE_DEACTIVATE_TE 0x02
#define HFC_L1_ACTIVATE_NT 0x03
#define HFC_L1_DEACTIVATE_NT 0x04
#define HFC_L1_TESTLOOP_B1 0x05
#define HFC_L1_TESTLOOP_B2 0x06
/* xhfc Layer1 Flags (stored in xhfc_port_t->l1_flags) */
#define HFC_L1_ACTIVATING 1
@ -114,20 +109,15 @@
/* private driver_data */
typedef struct {
__u8 num_xhfcs;
char *device_name;
} pi_params;
int chip_id;
char *device_name;
} xhfc_param;
struct _xhfc_t;
struct _xhfc_pi;
/* port struct for each S/U port */
typedef struct {
int idx;
struct _xhfc_t * xhfc;
char name[20]; /* XHFC_PI0_0_0 = ProcessorInterface no. 0, Chip no. 0, port no 0 */
__u8 dpid; /* DChannel Protocoll ID */
__u16 mode; /* NT/TE + ST/U */
int nt_timer;
@ -151,28 +141,41 @@ typedef struct {
} xhfc_chan_t;
struct _xhfx_hw;
/**********************/
/* hardware structure */
/**********************/
typedef struct _xhfc_t {
char name[15]; /* XHFC_PI0_0 = ProcessorInterface no. 0, Chip no. 0 */
__u8 chipnum; /* global chip number */
__u8 chipidx; /* index in pi->xhfcs[NUM_XHFCS] */
struct _xhfc_pi * pi; /* backpointer to xhfc_pi */
__u8 param_idx; /* used to access module param arrays */
typedef struct _xhfx_hw {
struct list_head list;
spinlock_t lock;
struct tasklet_struct tasklet; /* interrupt bottom half */
__u8 testirq;
int cardnum;
__u8 param_idx; /* used to access module param arrays */
int ifnum;
__u8 testirq;
int irq;
int iobase;
int nt_mode;
u_char *membase;
u_char *hw_membase;
#if BRIDGE == BRIDGE_PCI2PI
struct pci_dev *pdev;
#endif
xhfc_param driver_data;
char card_name[60];
int chip_id;
int num_ports; /* number of S and U interfaces */
int max_fifo; /* always 4 fifos per port */
__u8 max_z; /* fifo depth -1 */
xhfc_port_t * port; /* one for each Line intercace */
xhfc_chan_t * chan; /* one each D/B/PCM channel */
xhfc_port_t port[MAX_PORT]; /* one for each Line intercace */
xhfc_chan_t chan[MAX_CHAN]; /* one each D/B/PCM channel */
__u32 irq_cnt; /* count irqs */
__u32 f0_cnt; /* last F0 counter value */
@ -193,26 +196,16 @@ typedef struct _xhfc_t {
__u32 fifo_irq; /* fifo bl irq */
__u32 fifo_irqmsk; /* fifo bl irq */
} xhfc_t;
/**********************/
/* hardware structure */
/**********************/
typedef struct _xhfc_pi {
#if BRIDGE == BRIDGE_PCI2PI
struct pci_dev *pdev;
int irq;
int iobase;
u_char *membase;
u_char *hw_membase;
int cardnum;
char name[10]; /* 'XHFC_PI0' = ProcessorInterface no. 0 */
pi_params driver_data;
#endif
xhfc_t * xhfc;
} xhfc_pi;
} xhfc_hw;
/* function prototypes */
int setup_channel(xhfc_hw * hw, __u8 channel, int protocol);
void xhfc_write_fifo(xhfc_hw * hw, __u8 channel);
void xhfc_read_fifo(xhfc_hw * hw, __u8 channel);
void print_fc(xhfc_hw * hw, __u8 fifo);
void setup_fifo(xhfc_hw * hw, __u8 fifo, __u8 conhdlc, __u8 subcfg,
__u8 fifoctrl, __u8 enable);
void setup_su(xhfc_hw * hw, __u8 pt, __u8 bc, __u8 enable);
#endif /* _XHFC_SU_H_ */

View File

@ -91,15 +91,6 @@ typedef struct wait_queue *wait_queue_head_t;
#undef OLD_PCI_REGISTER_DRIVER
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8)
#define __ATTR(_name,_mode,_show,_store) { \
.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE }, \
.show = _show, \
.store = _store, \
}
#define LOCAL_FCSTAB
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11)
#define MODULE_MKOBJ_POINTER
#endif
@ -109,24 +100,9 @@ typedef struct wait_queue *wait_queue_head_t;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
#define OLD_MODULE_PARAM
/* udev sysfs stuff */
#define CLASS_WITHOUT_OWNER
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
#define kzalloc kmalloc
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
#define kzalloc(s,f) kcalloc(1,s,f)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
#include <linux/config.h>
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
#include <linux/config.h>
#endif
#endif /* __KERNEL__ */
#endif /* _LINUX_ISDN_COMPAT_H */

View File

@ -19,7 +19,7 @@
* - changed if any interface is extended but backwards compatible
*
*/
#define MISDN_MAJOR_VERSION 5
#define MISDN_MAJOR_VERSION 3
#define MISDN_MINOR_VERSION 0
#define MISDN_VERSION ((MISDN_MAJOR_VERSION<<16) | MISDN_MINOR_VERSION)
@ -27,7 +27,7 @@
#define MISDN_DATE "$Date$"
/* collect some statistics about the message queues */
//#define MISDN_MSG_STATS
#define MISDN_MSG_STATS
/* primitives for information exchange
* generell format
@ -158,8 +158,6 @@
#define HW_RECEIVE_ON 0x0585
#define HW_SPL_LOOP_ON 0x0586
#define HW_SPL_LOOP_OFF 0x0587
#define HW_ECHOCAN_ON 0x0588
#define HW_ECHOCAN_OFF 0x0589
#define HW_TESTLOOP 0xFF00
#define HW_FIRM_START 0xFF10
#define HW_FIRM_DATA 0xFF11
@ -581,11 +579,11 @@
#define STATUS_INFO_L2 2
typedef struct _mISDN_head {
u_int addr;
u_int prim;
int dinfo;
int len;
} __attribute__((packed)) mISDN_head_t;
u_int addr __attribute__((packed));
u_int prim __attribute__((packed));
int dinfo __attribute__((packed));
int len __attribute__((packed));
} mISDN_head_t;
#define mISDN_HEADER_LEN sizeof(mISDN_head_t)
@ -608,13 +606,10 @@ typedef struct _moditem {
typedef struct _mISDN_pid {
int protocol[MAX_LAYER_NR +1];
u_char *param[MAX_LAYER_NR +1];
__u16 global;
int layermask;
int maxplen;
/* 0 is defined as no prameter, all other values are offsets into pbuf
* so pbuf[0] is always unused */
u16 param[MAX_LAYER_NR +1];
u16 global;
u16 pidx;
u_char *pbuf;
} mISDN_pid_t;
@ -698,48 +693,47 @@ typedef struct _ie_info_ext {
} __attribute__((packed)) ie_info_ext_t;
typedef struct _Q931_info {
u_char type;
u_char crlen;
u16 cr;
ie_info_t bearer_capability;
ie_info_t cause;
ie_info_t call_id;
ie_info_t call_state;
ie_info_t channel_id;
ie_info_t facility;
ie_info_t progress;
ie_info_t net_fac;
ie_info_t notify;
ie_info_t display;
ie_info_t date;
ie_info_t keypad;
ie_info_t signal;
ie_info_t info_rate;
ie_info_t end2end_transit;
ie_info_t transit_delay_sel;
ie_info_t pktl_bin_para;
ie_info_t pktl_window;
ie_info_t pkt_size;
ie_info_t closed_userg;
ie_info_t connected_nr;
ie_info_t connected_sub;
ie_info_t calling_nr;
ie_info_t calling_sub;
ie_info_t called_nr;
ie_info_t called_sub;
ie_info_t redirect_nr;
ie_info_t redirect_dn;
ie_info_t transit_net_sel;
ie_info_t restart_ind;
ie_info_t llc;
ie_info_t hlc;
ie_info_t useruser;
ie_info_t more_data;
ie_info_t sending_complete;
ie_info_t congestion_level;
ie_info_t comprehension_required;
ie_info_ext_t ext[8];
} __attribute__((packed)) Q931_info_t;
u_char type __attribute__((packed));
u_char crlen __attribute__((packed));
u16 cr __attribute__((packed));
ie_info_t bearer_capability __attribute__((packed));
ie_info_t cause __attribute__((packed));
ie_info_t call_id __attribute__((packed));
ie_info_t call_state __attribute__((packed));
ie_info_t channel_id __attribute__((packed));
ie_info_t facility __attribute__((packed));
ie_info_t progress __attribute__((packed));
ie_info_t net_fac __attribute__((packed));
ie_info_t notify __attribute__((packed));
ie_info_t display __attribute__((packed));
ie_info_t date __attribute__((packed));
ie_info_t keypad __attribute__((packed));
ie_info_t signal __attribute__((packed));
ie_info_t info_rate __attribute__((packed));
ie_info_t end2end_transit __attribute__((packed));
ie_info_t transit_delay_sel __attribute__((packed));
ie_info_t pktl_bin_para __attribute__((packed));
ie_info_t pktl_window __attribute__((packed));
ie_info_t pkt_size __attribute__((packed));
ie_info_t closed_userg __attribute__((packed));
ie_info_t connected_nr __attribute__((packed));
ie_info_t connected_sub __attribute__((packed));
ie_info_t calling_nr __attribute__((packed));
ie_info_t calling_sub __attribute__((packed));
ie_info_t called_nr __attribute__((packed));
ie_info_t called_sub __attribute__((packed));
ie_info_t redirect_nr __attribute__((packed));
ie_info_t transit_net_sel __attribute__((packed));
ie_info_t restart_ind __attribute__((packed));
ie_info_t llc __attribute__((packed));
ie_info_t hlc __attribute__((packed));
ie_info_t useruser __attribute__((packed));
ie_info_t more_data __attribute__((packed));
ie_info_t sending_complete __attribute__((packed));
ie_info_t congestion_level __attribute__((packed));
ie_info_t fill1 __attribute__((packed));
ie_info_ext_t ext[8] __attribute__((packed));
} Q931_info_t;
#define L3_EXTRA_SIZE sizeof(Q931_info_t)
@ -761,16 +755,16 @@ typedef int (if_func_t)(mISDNinstance_t *, struct sk_buff *);
#define mISDN_HEAD_DINFO(s) ((mISDN_head_t *)&s->cb[0])->dinfo
typedef struct _mISDN_headext {
u_int addr;
u_int prim;
int dinfo;
u_int addr __attribute__((packed));
u_int prim __attribute__((packed));
int dinfo __attribute__((packed));
void *data[3];
union {
ctrl_func_t *ctrl;
if_func_t *iff;
void *func;
} func;
} __attribute__((packed)) mISDN_headext_t;
} mISDN_headext_t;
#define mISDN_HEADEXT_P(s) ((mISDN_headext_t *)&s->cb[0])
@ -783,6 +777,7 @@ struct _mISDNobject {
mISDN_pid_t DPROTO;
mISDN_pid_t BPROTO;
ctrl_func_t *own_ctrl;
ctrl_func_t *ctrl;
struct list_head ilist;
spinlock_t lock;
struct module *owner;
@ -898,7 +893,6 @@ extern int mISDN_queue_message(mISDNinstance_t *, u_int, struct sk_buff *);
extern int mISDN_register(mISDNobject_t *obj);
extern int mISDN_unregister(mISDNobject_t *obj);
extern int mISDN_ctrl(void *, u_int, void *);
#endif /* __KERNEL__ */
#endif /* mISDNIF_H */

View File

@ -1,25 +0,0 @@
install hfcmulti /usr/sbin/misdn-init start hfcmulti
remove hfcmulti /usr/sbin/misdn-init stop
install hfcpci /usr/sbin/misdn-init start hfcpci
remove hfcpci /usr/sbin/misdn-init stop
install hfcsusb /usr/sbin/misdn-init start hfcsusb
remove hfcsusb /usr/sbin/misdn-init stop
install hfcsmini /usr/sbin/misdn-init start hfcsmini
remove hfcsmini /usr/sbin/misdn-init stop
install xhfc /usr/sbin/misdn-init start xhfc
remove xhfc /usr/sbin/misdn-init stop
install avmfritz /usr/sbin/misdn-init start avmfritz
remove avmfritz /usr/sbin/misdn-init stop
install w6692pci /usr/sbin/misdn-init start w6692pci
remove w6692pci /usr/sbin/misdn-init stop
install sedlfax /usr/sbin/misdn-init start sedlfax
remove sedlfax /usr/sbin/misdn-init stop

View File

@ -15,12 +15,9 @@
#
# USAGE:
#
# /usr/sbin/misdn-init start|stop|restart|config|scan|help
# /etc/init.d/misdn-init start|stop|restart|config|scan|help
#
# chkconfig: 2345 35 60
# description: mISDN Kernel Modules
#
# CONFIGURATION:
#
@ -30,225 +27,63 @@ misdn_init_conf="/etc/misdn-init.conf"
#
################################################################################
#
# change this to modify the user/group settings of /dev/mISDN
#
USER=asterisk
GROUP=asterisk
MODPROBE=modprobe
RMMOD=rmmod
INSMOD=insmod
LSPCI=lspci
MKNOD=mknod
# HFC 8/4 (S0) Options
master_clock=17
master_clock=16
# HFC-E1 Options
optical=17
los=19
ais=20
slip=21
optical=16
los=18
ais=19
slip=20
nocrc4=24
# Card Settings
ulaw=9
dtmf=10
pcm_slave=12
ignore_pcm_frameclock=13
rxclock=14
crystalclock=19
watchdog=20
ulaw=8
dtmf=9
pcm_slave=11
#dsp defaults
dsp_options=0
function remove_preloaded_modules {
tmp=$(lsmod)
cards="hfcmulti hfcpci avmfritz w6692 hfcusb"
poll_option=
dsp_poll_option=
dtmfthreshold_option=
function check_cmd {
if ! which "${1}" > /dev/null; then
if [ "$(id -u)" != "0" ]; then
echo "[!!] FATAL: $1 not in path, please install and/or be root."
else
echo "[!!] FATAL: $1 not in path, please install."
fi
if [ "${2}" != "notfatal" ] ; then
exit 1
fi
else
var=$(echo ${1} | tr a-z A-Z)
eval "$var=`which ${1}`"
fi
}
check_cmd modprobe
check_cmd rmmod
check_cmd insmod
check_cmd lspci
check_cmd lsusb notfatal
check_cmd mknod
check_cmd bc
check_cmd cut
check_cmd wc
check_cmd seq
check_cmd sed
function check_asterisk {
if ps ax | grep -v grep | grep asterisk > /dev/null ; then asterisk -rx "stop now" ; fi
}
function create_card_db
{
cardline=""
cardcount=1
skipnext=0
IFS=$'\n'
NL="
"
function addcard {
cardline="${cardline}${cardcount},${1}${NL}"
let "cardcount = ${cardcount} + 1"
}
function addport {
let "portcount = ${portcount} + ${1}"
}
for line in $(${LSPCI} -n -d 0xd161:b410); do
addcard "4,0x4"
done
for line in $(${LSPCI} -n | ${SED} -n 's/^\(0000:\|\)\([0-9a-f]\{2\}:[0-9a-f]\{2\}.[0-9a-f]\{1\}\)\( Class \| \)[0-9a-f]\{4\}: 1397:\([0-9a-f]\{4\}\).*$/\4 \2/p'); do
if [ ${skipnext} -eq 1 ]; then
skipnext=0
continue
fi
case "${line}" in
30b1*)
case "${line:5}" in
00*)
addcard "1,0x1"
;;
*)
if [ $(${LSPCI} -n -s ${line:5:3} | ${WC} -l) -eq 2 ]; then
addcard "2,2E1"
skipnext=1
else
addcard "1,0x1"
fi
;;
esac
;;
16b8*)
addcard "8,0x8"
;;
08b4*)
if ${LSPCI} -n -v -s "${line:5}" | grep "Subsystem" | grep "1397:b567" > /dev/null ; then
addcard "1,0x4"
elif ${LSPCI} -n -v -s "${line:5}" | grep "Subsystem" | grep "1397:b566\|1397:b569" > /dev/null ; then
addcard "2,0x4"
else
addcard "4,0x4"
fi
;;
esac
done
for line in $(${LSPCI} -n | grep "1397:\(2bd\(0\|6\|7\|8\|9\|a\|b\|c\)\|b100\)\|1043:0675\|0871:ffa\(1\|2\)\|1051:0100\|15b0:2bd0\|114f:007\(0\|1\|2\|3\)\|13d1:2bd1\|182d:3069"); do
addcard "1,hfcpci"
done
for line in $(${LSPCI} -n | grep "1244:\(0a00\|0e00\)"); do
addcard "1,avmfritz"
done
for line in $(${LSPCI} -n -d 1050:6692); do
addcard "1,w6692pci"
done
if [ -e ${LSUSB} ]; then
for line in $(${LSUSB} | grep "0959:2bd0\|0675:1688\|07b0:0007\|0742:200\(7\|8\|9\|A\)\|08e3:0301\|07fa:084\(7\|8\)\|07ba:0006"); do
addcard "1,hfcsusb"
done
fi
echo "${cardline}"
}
function expand
{
local IFS=$','
for tok in $1; do
if [ "$(echo $tok | ${SED} -ne 's/\([0-9]*\)-\([0-9]*\)/\1 \2/p')" != "" ]; then
${SEQ} $(echo $tok | ${SED} -ne 's/\([0-9]*\)-[0-9]*/\1/p') $(echo $tok | ${SED} -ne 's/[0-9]*-\([0-9]*\)/\1/p')
else
echo $tok
fi
for i in $cards ; do
echo $tmp | grep $i >/dev/null && (echo "$i already loaded, removing it"; modprobe -r $i)
done
}
function load_card_modules {
carddb=$(create_card_db)
function find_carddb_line {
i=1
for l in ${carddb} ; do
if [ $i -eq $1 ] ; then
echo $l
return
fi
let "i=$i+1"
done
}
if [ ! -z "$1" ] ; then
echo "Loading only $1"
fi
IFS=$'\n'
skipnr=0
for line in $(${SED} -n -e '/^[^#]/p' ${misdn_init_conf});
for line in $(sed -n -e '/^[^#]/p' ${misdn_init_conf});
do
var=$(echo "${line}" | ${CUT} -d "=" -f1)
val=$(echo "${line}" | ${CUT} -d "=" -f2)
var=`echo "${line}" | sed -e "s/^\(.*\)=.*/\1/"`
val=`echo "${line}" | sed -e "s/^.*=\(.*\)/\1/"`
case "${var}" in
card)
#echo "processing line: $val"
nr=$(echo "${val}" | ${CUT} -d "," -f1)
mod=$(echo "${val}" | ${CUT} -d "," -f2)
opns=$(echo "${val}" | ${CUT} -d "," -f3-)
#getting portcount from carddb
ports=$(find_carddb_line $nr | ${CUT} -d "," -f2)
let "nr = ${nr} + ${skipnr}"
#echo "nr $nr ports $ports mod $mod opns: $opns"
nr=`echo "${val}" | sed -e "s/^\([0-9]*\),.*/\1/"`
mod=`echo "${val}" | sed -e "s/^[^,]*,\([^,]*\).*/\1/"`
if [ ${#val} -gt $(echo "obase=10;${#nr}+${#mod}+1" | bc) ]; then
opns=`echo "${val}" | sed -e "s/^[^,]*,[^,]*,\(.*\)/\1/"`
else
opns=""
fi
case "${mod}" in
2E1)
hfcmulti[${nr}]=1
hfcmulti[$((${nr} + 1))]=1
let "hfcports = ${hfcports} + ${ports}"
IFS=$','
for li in ${opns}; do
hfcmulti[${nr}]=$(echo "obase=10;2^(${!li}-1)+${hfcmulti[${nr}]}" | ${BC})
if [ "${li}" != "pcm_slave" ]; then
hfcmulti[$((${nr} + 1))]=$(echo "obase=10;2^(${!li}-1)+${hfcmulti[$((${nr}+1))]}" | ${BC})
fi
done
IFS=$'\n'
hfcmulti[$((${nr} + 1))]=$(echo "obase=10;2^(${pcm_slave}-1)+${hfcmulti[$((${nr}+1))]}" | ${BC})
let "skipnr = ${skipnr} + 1"
;;
0x*)
hfcmulti[${nr}]=$(echo ${mod} | ${SED} -e "s/^0x\([0-9]*\)/\1/")
let "hfcports = ${hfcports} + ${ports}"
hfcmulti[${nr}]=$(echo ${mod} | sed -e "s/^0x\([0-9]*\)/\1/")
let "hfcports = ${hfcports} + ${hfcmulti[${nr}]}"
IFS=$','
for li in ${opns}; do
hfcmulti[${nr}]=$(echo "obase=10;2^(${!li}-1)+${hfcmulti[${nr}]}" | ${BC})
hfcmulti[${nr}]=$(echo "obase=10;2^(${!li}-1)+${hfcmulti[${nr}]}" | bc)
done
IFS=$'\n'
;;
@ -258,43 +93,52 @@ function load_card_modules {
esac
;;
te_ptp)
for li in $(expand "${val}"); do
IFS=$','
for li in ${val}; do
layermask[${li}]="0xf"
protocol[${li}]=34 # 0x22 == 34
done
IFS=$'\n'
;;
te_ptmp)
for li in $(expand "${val}"); do
IFS=$','
for li in ${val}; do
layermask[${li}]="0xf"
protocol[${li}]=2 # 0x2 == 2
done
IFS=$'\n'
;;
nt_*)
for li in $(expand "${val}"); do
IFS=$','
for li in ${val}; do
layermask[${li}]="0x3"
protocol[${li}]=18 # 0x12 == 18
done
IFS=$'\n'
;;
te_capi_ptp)
for li in $(expand "${val}"); do
IFS=$','
for li in ${val}; do
layermask[${li}]="0x0"
protocol[${li}]=34 # 0x22 == 34
done
IFS=$'\n'
export addcapi=1
addcapi=1
;;
te_capi_ptmp)
for li in $(expand "${val}"); do
IFS=$','
for li in ${val}; do
layermask[${li}]="0x0"
protocol[${li}]=2 # 0x2 == 2
done
export addcapi=1
IFS=$'\n'
addcapi=1
;;
option)
port=`echo "${val}" | ${SED} -e "s/^\([0-9]*\),.*/\1/"`
opt=`echo "${val}" | ${SED} -e "s/^[0-9]*,\(.*\)/\1/"`
port=`echo "${val}" | sed -e "s/^\([0-9]*\),.*/\1/"`
opt=`echo "${val}" | sed -e "s/^[0-9]*,\(.*\)/\1/"`
if [ -z ${protocol[${port}]} ]; then
protocol[${port}]="0"
@ -302,32 +146,19 @@ function load_card_modules {
IFS=$','
for li in ${opt}; do
protocol[${port}]=$(echo "obase=10;2^(${!li}-1)+${protocol[${port}]}" | ${BC})
protocol[${port}]=$(echo "obase=10;2^(${!li}-1)+${protocol[${port}]}" | bc)
done
IFS=$'\n'
;;
poll)
poll=${val}
poll_option=poll=${val}
;;
dsp_poll)
dsp_poll_option=poll=${val}
;;
pcm)
pcm=${val}
;;
dsp_options)
export dsp_options=${val}
;;
dtmfthreshold)
export dtmfthreshold_option="dtmfthreshold=${val}"
;;
debug)
debug=${val}
;;
timer)
timer=${val}
;;
*)
echo "unknown variable: ${var}"
;;
@ -350,13 +181,13 @@ function load_card_modules {
hfcmulti_layer="layermask="
while [ ! -z ${hfcmulti[${card_index}]} ];
do
hfcmulti_type="${hfcmulti_type}$(echo "obase=16;\"0x\";${hfcmulti[${card_index}]}" | ${BC} ),"
hfcmulti_type="${hfcmulti_type}$(echo "obase=16;\"0x\";${hfcmulti[${card_index}]}" | bc ),"
let "card_index = ${card_index} + 1"
done
while [ ${hfcports} -gt 0 ];
do
if [ ! -z ${protocol[${port_index}]} ]; then
hfcmulti_prot="${hfcmulti_prot}$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | ${BC}),"
hfcmulti_prot="${hfcmulti_prot}$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | bc),"
else
hfcmulti_prot="${hfcmulti_prot}0x2,"
fi
@ -368,10 +199,10 @@ function load_card_modules {
let "port_index = ${port_index} + 1"
let "hfcports = ${hfcports} - 1"
done
hfcmulti_type="$(echo ${hfcmulti_type} | ${SED} -e 's/^\(.*\),$/\1/')"
hfcmulti_prot="$(echo ${hfcmulti_prot} | ${SED} -e 's/^\(.*\),$/\1/')"
hfcmulti_layer="$(echo ${hfcmulti_layer} | ${SED} -e 's/^\(.*\),$/\1/')"
hfcmulti_cmd="${MODPROBE} --ignore-install hfcmulti ${hfcmulti_type} ${hfcmulti_prot} ${hfcmulti_layer}"
hfcmulti_type="$(echo ${hfcmulti_type} | sed -e 's/^\(.*\),$/\1/')"
hfcmulti_prot="$(echo ${hfcmulti_prot} | sed -e 's/^\(.*\),$/\1/')"
hfcmulti_layer="$(echo ${hfcmulti_layer} | sed -e 's/^\(.*\),$/\1/')"
hfcmulti_cmd="modprobe hfcmulti ${hfcmulti_type} ${hfcmulti_prot} ${hfcmulti_layer}"
if [ ! -z ${poll} ]; then
hfcmulti_cmd="${hfcmulti_cmd} poll=${poll}"
fi
@ -382,25 +213,13 @@ function load_card_modules {
hfcmulti_cmd="${hfcmulti_cmd} debug=${debug}"
fi
if [ ! -z ${timer} ]; then
hfcmulti_cmd="${hfcmulti_cmd} timer=${timer}"
fi
if [ -z "$1" ] ; then
echo ${hfcmulti_cmd}
eval ${hfcmulti_cmd}
else
if [ "$1" = "hfcmulti" ] ; then
echo ${hfcmulti_cmd}
eval ${hfcmulti_cmd}
fi
fi
echo ${hfcmulti_cmd}
eval ${hfcmulti_cmd}
else
# MODPROBE COMMAND FOR _NON_ hfcmulti CARD
other_mod="${other_card[${card_index}]}"
other_cmd="${MODPROBE} --ignore-install ${other_mod}"
other_cmd="modprobe ${other_card[${card_index}]}"
if [ ! -z ${protocol[${port_index}]} ]; then
other_prot="protocol=$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | ${BC}),"
other_prot="protocol=$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | bc),"
else
other_prot="protocol=0x2,"
fi
@ -409,8 +228,6 @@ function load_card_modules {
else
other_layer="layermask=0xf,"
fi
other_extra=""
modinfo $other_mod | egrep -q 'parm: *poll' && other_extra="$other_extra ${poll_option}"
let "prev = ${card_index}"
let "card_index = ${card_index} + 1"
@ -418,7 +235,7 @@ function load_card_modules {
while [ "${other_card[${card_index}]}" == "${other_card[${prev}]}" ];
do
if [ ! -z ${protocol[${port_index}]} ]; then
other_prot="${other_prot}$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | ${BC}),"
other_prot="${other_prot}$(echo "obase=16;\"0x\";${protocol[${port_index}]}" | bc),"
else
other_prot="${other_prot}0x2,"
fi
@ -432,21 +249,11 @@ function load_card_modules {
let "port_index = ${port_index} + 1"
done
other_prot="$(echo ${other_prot} | ${SED} -e 's/^\(.*\),$/\1/')"
other_layer="$(echo ${other_layer} | ${SED} -e 's/^\(.*\),$/\1/')"
other_cmd="${other_cmd} ${other_prot} ${other_layer} ${other_extra}"
if [ -z "$1" ] ; then
echo "${other_cmd}"
eval ${other_cmd}
else
if [ "$1" = "${other_card[${prev}]}" ] ; then
echo ${other_cmd}
eval ${other_cmd}
fi
fi
other_prot="$(echo ${other_prot} | sed -e 's/^\(.*\),$/\1/')"
other_layer="$(echo ${other_layer} | sed -e 's/^\(.*\),$/\1/')"
other_cmd="${other_cmd} ${other_prot} ${other_layer}"
echo "${other_cmd}"
eval ${other_cmd}
fi
done
}
@ -455,19 +262,16 @@ function unload_card_modules {
IFS=$'\n'
for line in $(${SED} -ne '/^[^#]/p' ${misdn_init_conf});
for line in $(sed -ne '/^[^#]/p' ${misdn_init_conf});
do
var=$(echo "${line}" | ${CUT} -d "=" -f 1)
val=$(echo "${line}" | ${CUT} -d "=" -f 2)
var=`echo "${line}" | sed -e "s/^\(.*\)=.*/\1/"`
val=`echo "${line}" | sed -e "s/^.*=\(.*\)/\1/"`
case "${var}" in
card)
nr=$(echo "${val}" | ${CUT} -d "," -f 1)
mod=$(echo "${val}" | ${CUT} -d "," -f 2)
nr=`echo "${val}" | sed -e "s/^\([0-9]*\),.*/\1/"`
mod=`echo "${val}" | sed -e "s/^[^,]*,\([^,]*\).*/\1/"`
case "${mod}" in
2E1)
modulelist[${nr}]=hfcmulti
;;
0x*)
modulelist[${nr}]=hfcmulti
;;
@ -503,29 +307,56 @@ function unload_card_modules {
}
function create_misdn_init_conf {
cardline=""
cardcount=1
portcount=0
cardconf=""
IFS=$'\n'
NL="
"
carddb=$(create_card_db)
for line in $carddb ; do
tmp="card=$(echo $line | ${CUT} -d, -f1,3)"
let "portcount = ${portcount} + $(echo $line | ${CUT} -d, -f2)"
cardline="${cardline}${tmp}${NL}"
done
function die {
echo "[!!] ${1}"
exit 1
}
function addcard {
cardline="${cardline}card=${cardcount},${1}${NL}"
let "cardcount = ${cardcount} + 1"
}
function addport {
let "portcount = ${portcount} + ${1}"
}
portcount=0
for line in $(${LSPCI} -n -d 1397:30b1); do
addcard "0x1"
addport 1
done
for line in $(${LSPCI} -n -d 1397:08b4); do
addcard "0x4"
addport 4
done
for line in $(${LSPCI} -n -d 1397:16b8); do
addcard "0x8"
addport 8
done
for line in $(${LSPCI} -n | grep "1397:\(2bd\(0\|6\|7\|8\|9\|a\|b\|c\)\|b100\)\|1043:0675\|0871:ffa\(1\|2\)\|1051:0100\|15b0:2bd0\|114f:007\(0\|1\|2\|3\)\|13d1:2bd1\|182d:3069"); do
addcard "hfcpci"
addport 1
done
for line in $(${LSPCI} -n -d 1244:0xa00); do
addcard "avmfritz"
addport 1
done
for line in $(${LSPCI} -n -d 1050:6692); do
addcard "w6692pci"
addport 1
done
if [ "${1}" == "scan" ]; then
echo "[OK] found the following devices:"
echo "${cardline}[ii] run \"/usr/sbin/misdn-init config\" to store this information to ${misdn_init_conf}"
echo "${cardline}[ii] run \"/etc/init.d/misdn-init config\" to store this information to ${misdn_init_conf}"
else
index=1
@ -534,12 +365,12 @@ function create_misdn_init_conf {
portline="${portline}${index},"
let "index = ${index} + 1"
done
portline="$(echo ${portline} | ${SED} -e 's/^\(.*\),$/\1/')"
portline="$(echo ${portline} | sed -e 's/^\(.*\),$/\1/')"
misdn_cfg_pt1="#
# Configuration file for your misdn hardware
#
# Usage: /usr/sbin/misdn-init start|stop|restart|config|scan|help
# Usage: /etc/init.d/misdn-init start|stop|restart|config|scan|help
#
#
@ -552,24 +383,7 @@ function create_misdn_init_conf {
# or the name of your card driver module.
# <option> ulaw - uLaw (instead of aLaw)
# dtmf - enable DTMF detection on all B-channels
#
# pcm_slave - set PCM bus into slave mode
# If you have a set of cards, all wired via PCM. Set
# all cards into pcm_slave mode and leave one out.
# The left card will automatically be Master.
#
# ignore_pcm_frameclock - this can be set in conjunction with
# pcm_slave. If this card has a
# PCI Bus Position before the Position
# of the Master, then this port cannot
# yet receive a frameclock, so it must
# ignore the pcm frameclock.
#
# rxclock - use clocking for pcm from ST Port
# crystalclock - use clocking for pcm from PLL (genrated on board)
# watchdog - This dual E1 Board has a Watchdog for
# transparent mode
#
#"
misdn_cfg_pt2="#
# Port settings
@ -598,11 +412,6 @@ function create_misdn_init_conf {
# nocrc4 - turn off crc4 mode use double frame instead
# (only HFC-E1)
#
# The master_clock option is essential for retrieving and transmitting
# faxes to avoid failures during transmission. It tells the driver to
# synchronize the Card with the given Port which should be a TE Port and
# connected to the PSTN in general.
#
#option=1,master_clock
#option=2,ais,nocrc4
#option=3,optical,los,ais,slip
@ -619,50 +428,19 @@ function create_misdn_init_conf {
# reduce cpu load. If unsure, don't mess with it!!!
# Valid is 32, 64, 128, 256.
#
# dsp_poll=<number>
# This is the poll option which is used by mISDN_dsp, this might
# differ from the one given by poll= for the hfc based cards, since
# they can only use multiples of 32, the dsp_poll is dependant on
# the kernel timer setting which can be found in the CPU section
# in the kernel config. Defaults are there either 100Hz, 250Hz
# or 1000Hz. If your setting is either 1000 or 250 it is compatible
# with the poll option for the hfc chips, if you have 100 it is
# different and you need here a multiple of 80.
# The default is to have no dsp_poll option, then the dsp itself
# finds out which option is the best to use by itself
#
# pcm=<number>
#
# Give the id of the PCM bus. All PCM busses with the same ID
# are expected to be connected and have equal slots.
# Only one chip of the PCM bus must be master, the others slave.
# -1 means no support of PCM bus.
#
# debug=<number>
#
# Enable debugging (see hfc_multi.h for debug options).
#
# dsp_options=<number>
#
# set this to 2 and you'll have software bridging instead of
# hardware bridging.
#
#
# dtmfthreshold=<milliseconds>
#
# Here you can tune the sensitivity of the dtmf tone recognizer.
#
# timer=<1|0>
#
# set this to 1 if you want hfcmulti to register at ztdummy (zaptel)
# and provide a 1khz timing source for it. This makes it possible
# to have an accurate timing source for asterisk through zaptel from
# hfcmulti to make applications like Meetme and faxing between wctdm
# and hfcmulti work properly.
#
poll=128
dsp_poll=128
dsp_options=0
dtmfthreshold=100
#pcm=1
debug=0"
if [ -f ${misdn_init_conf} ]; then
@ -672,7 +450,7 @@ debug=0"
echo "${misdn_cfg_pt1}${NL}${cardline}${NL}${misdn_cfg_pt2}${NL}${portline}${NL}${NL}${misdn_cfg_pt3}" > ${misdn_init_conf} || die "could not write to /etc/misdn-init.conf!"
#echo "${misdn_cfg_pt1}${NL}${cardline}${NL}${misdn_cfg_pt2}${NL}${portline}${NL}${NL}${misdn_cfg_pt3}" > testconf || die "could not write to /etc/misdn-init.conf!"
echo "[OK] ${misdn_init_conf} created. It's now safe to run \"/usr/sbin/misdn-init start\""
echo "[OK] ${misdn_init_conf} created. It's now safe to run \"/etc/init.d/misdn-init start\""
if [ ${portcount} -gt 1 ]; then
echo "[ii] make your ports (1-${portcount}) available in asterisk by editing \"/etc/asterisk/misdn.conf\""
elif [ ${portcount} -eq 1 ]; then
@ -683,14 +461,9 @@ debug=0"
function check_cfg_file {
if [ ! -f ${misdn_init_conf} ]; then
if [ ! -z "$1" ] ; then
/usr/sbin/misdn-init config
else
echo "[!!] failed to load: ${misdn_init_conf}"
echo "run \"/usr/sbin/misdn-init config\" to scan your devices and generate a basic config file."
exit 1
fi
echo "[!!] failed to load: ${misdn_init_conf}"
echo "run \"/etc/init.d/misdn-init config\" to scan your devices and generate a basic config file."
exit 1
fi
}
@ -698,26 +471,24 @@ function check_cfg_file {
case "$1" in
start|--start)
check_cfg_file $2
${MODPROBE} capi
${MODPROBE} mISDN_core debug=0
${MODPROBE} mISDN_l1 debug=0
${MODPROBE} mISDN_l2 debug=0
${MODPROBE} l3udss1 debug=0
${MODPROBE} mISDN_capi
remove_preloaded_modules
check_cfg_file
$MODPROBE mISDN_core debug=0
$MODPROBE mISDN_l1 debug=0
$MODPROBE mISDN_l2 debug=0
$MODPROBE l3udss1 debug=0
$MODPROBE mISDN_dsp debug=0x0 options=0x0
$MODPROBE mISDN_capi
load_card_modules $2
echo "${MODPROBE} mISDN_dsp debug=0x0 options=$dsp_options $dsp_poll_option $dtmfthreshold_option"
${MODPROBE} mISDN_dsp debug=0x0 options=$dsp_options $dsp_poll_option $dtmfthreshold_option
load_card_modules
sleep 1
if [ ! -e /dev/mISDN ]; then
$MKNOD /dev/mISDN c 46 0
if grep asterisk /etc/passwd > /dev/null; then
chown $USER:$GROUP /dev/mISDN
fi
echo "[i] creating device node: /dev/mISDN"
fi
;;
@ -726,22 +497,16 @@ case "$1" in
check_cfg_file
check_asterisk
unload_card_modules
for mod in $(lsmod | ${SED} -ne '/Module/!{s/\([^ ]*\).*/\1/;p}');
for mod in $(lsmod | sed -ne '/Module/!{s/\([^ ]*\).*/\1/;p}');
do
case "${mod}" in
mISDN_capi | mISDN_dsp | l3udss1 | mISDN_l2 | mISDN_l1 | mISDN_isac )
mISDN_capi | mISDN_dsp | l3udss1 | mISDN_l2 | mISDN_l1 | mISDN_isac | mISDN_core)
eval "${RMMOD} ${mod}"
;;
esac
done
unload_card_modules
${RMMOD} mISDN_core
;;
restart|--restart)
@ -777,4 +542,3 @@ case "$1" in
esac

View File

@ -128,7 +128,6 @@ usage() {
-r reverse directions of diff
-c FILE Use FILE as control file for $PREPARSER (only with -u)
-t Test, don't really copy files
-p PREFIX use PREFIX to install mISDNif.h in the system in the path $PREFIX/usr/include/linux
Without any files given, within the whole tree, the "right"
files are copied. When any files are given in the commandline,
@ -191,7 +190,7 @@ calc_version_file() {
return 1
}
while getopts :p:dhk:uc:vtidr a ; do
while getopts :dhk:uc:vtidr a ; do
case $a in
\?) case $OPTARG in
k) echo "-k requires Kernel directory parameter"
@ -219,8 +218,6 @@ while getopts :p:dhk:uc:vtidr a ; do
;;
r) DIFFREV=true;
;;
p) PREFIX=$OPTARG;
;;
h) usage
;;
esac
@ -231,7 +228,6 @@ echo
echo "BE AWARE!!"
echo
echo "You are just attempting to overwrite your Kernel mISDN Sources"
echo "and to install mISDNif.h in your /usr/include/linux directory"
echo "you probably prefer to use make install."
echo
echo "KERNELDIR=$KERNELDIR"
@ -245,11 +241,6 @@ if [ ! $i == "yes" ] ; then
exit 1
fi
#copy mISDNif.h to allow userspace apps to compile againt mISDN
echo "Installing mISDNif.h in $PREFIX/usr/include/linux/mISDNif.h"
mkdir -p $PREFIX/usr/include/linux/
cp include/linux/mISDNif.h $PREFIX/usr/include/linux/
if [ -z "$VERSION" -o -z "$PATCHLEVEL" ] ; then
if ! [ -f $KERNELDIR/Makefile ] ; then
echo "VERSION/PATCHLEVEL not set and no Makefile to read from"