Compare commits

..

103 Commits

Author SHA1 Message Date
Keith Morgan
75620dd9ef Remove struct devtype for unsupported drivers. 2018-10-05 19:42:50 +00:00
Keith Morgan
f47c9bd928 Changed readme to reflect driver support changes. 2018-10-04 19:03:00 +00:00
Keith Morgan
40f4f86ffa Revert "Remove support for xpp drivers."
add them back.
This reverts commit a36d266254.
2018-10-04 17:51:54 +00:00
Keith Morgan
29cb229cd3 Remove support for all but wcb41xp wcb43xp and wcb23xp. 2018-10-04 17:34:21 +00:00
Keith Morgan
a66e88e666 Remove support for wctdm800, wcaex800, wctdm410, wcaex410. 2018-10-03 17:02:56 +00:00
Keith Morgan
a36d266254 Remove support for xpp drivers. 2018-10-03 15:31:08 +00:00
Keith Morgan
3697450317 Remove support for driver wcte12xp. 2018-10-03 15:18:39 +00:00
Keith Morgan
3748456d22 Remove support for driver wcte11xp. 2018-10-03 15:01:04 +00:00
Keith Morgan
04e759f9c5 Remove support for driver wctdm. 2018-10-03 14:13:59 +00:00
Keith Morgan
dade6ac615 Remove support for wct1xxp driver. 2018-10-03 14:09:01 +00:00
Keith Morgan
14198aee85 Remove support for wcfxo driver. 2018-10-03 14:04:04 +00:00
Keith Morgan
60d058cc7a Remove support for tor2 driver. 2018-10-03 13:58:11 +00:00
Keith Morgan
bfdfc4728c Remove support for pciradio driver. 2018-10-03 13:50:39 +00:00
Keith Morgan
f95fff6588 Description: Remove a bodus "test" target
Author: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Bug: https://issues.asterisk.org/jira/browse/DAHLIN-364
2018-10-01 19:33:50 +00:00
Shaun Ruffell
6667f1c8d8 DAHDI in kernel 4.15: Switch to new timer_setup interface.
Upstream kernel 4.14, in commit (686fef928bba6b "timer: Prepare to change timer
callback argument type") [1], introduced the timer_setup interface to replace
the init_timer/setup_timer interfaces. The primary change is that the timer
callback functions now follow the standard kernel pattern where the structure
the callback sits in is passed to the callback instead of storing a pointer to
an unassociated data type.

The setup_timer functions were removed in upstream kernel v4.15, and therefore
this change is needed in order to compile DAHDI for kernels >= 4.15.

This change follows the same strategy that was done in the kernel to while the
existing users of setup_timer were migrated to the new interface.

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=686fef928bba6b
2018-09-03 10:27:18 -05:00
Shaun Ruffell
20328895a2 Disable -Wformat-truncation and prevent potential string overflows.
GCC 7.3.0 complained about the potential to overflow the fixed size span and
channel names and descriptions. It also flagged potential truncations of the
strings.

The sprintf calls are now changed to snprintf to prevent the potential
overflows, but the warning about truncations are now disabled globally.
2018-09-03 10:27:18 -05:00
Shaun Ruffell
7ecdf370bc voicebus: Initialize stack buffer.
Quiets the following (valid) warning from gcc 7.3.0:

drivers/dahdi/voicebus/GpakApi.c:1648:22: warning: ‘MsgBuffer[1]’ may be used
   uninitialized in this function [-Wmaybe-uninitialized]
         MsgBuffer[1] |= DTMF_UPDATE_MASK;
2018-09-03 10:26:43 -05:00
Shaun Ruffell
ea2d67414a xpp: fxs: Do not increment boolean.
This quiets the following warning from gcc 7.3.0:

  drivers/dahdi/xpp/card_fxs.c:1344:17: warning: increment of a boolean
  	expression [-Wbool-operation]
2018-09-03 10:26:29 -05:00
Shaun Ruffell
14d8754e34 Completely clear out conference buffers.
This fixes an error and quiets the following warning pointed out by gcc 7.3.0:

  warning: ‘memset’ used with length equal to number of elements without
    multiplication by element size [-Wmemset-elt-size] memset(chan->conflast, 0,
    DAHDI_MAX_CHUNKSIZE);

Previously only the first half of the conference buffers were cleared out.
2018-08-09 09:56:21 -05:00
Oron Peled
d3c9e43437 xpp: Support FXS module with 4 ports and no I/O
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2018-05-10 12:18:35 +03:00
Tzafrir Cohen
9a4d2fce48 xpp: init_card: eeprom_release_201 applies to any 20x
* The variable eeprom_release_201 was added in the initialization
  script of the FXS module to add a case where it is different from
  101 mains.
* However, it tests for "201" and it should apply for any 20x.
* Remove the variable from the init script of module type 6 (new FXS)
  as it was not used.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2018-02-20 19:07:50 +02:00
Tzafrir Cohen
26597a5cac Ignore quilt .pc directory, used in deb packaging
Debian packaging uses quilt to manage patches. Book-keeping for them is
done using quilt (either directly, or in a compatible format), and
tracked in the directory .pc .

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2018-01-11 15:23:55 +02:00
Jean-Denis Girard
d4e232a776 DAHDI in kernel 4.13: dev_attr to dev_groups
dev_attrs was removed from struct bus_type on kernel 4.13, need to
convert to dev_groups, see
http://lkml.iu.edu/hypermail/linux/kernel/1706.0/04578.html.

DAHLIN-356 #close

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2018-01-01 14:25:39 +02:00
Tzafrir Cohen
52f2c19769 xpp: mark init_card_6_30 as executable
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-09-17 08:25:31 +03:00
Dima Stoliarov
960472ed35 xpp: fxs: restore linefeed (for e.g. thermal alarm)
The si32260 chip may enter a state of thermal alarm to avoid
overheating. This disables the channel.

This commit allows automatic restoring of the channel after a certain
timeout (poll_chan_linefeed, by default 30 seconds).

Adds a per-channel counter ("overheats") in
/proc/xpp/XBUS-<n>/XPD-<m>0/fxs_info to count such events.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-09-13 15:37:24 +03:00
Dima Stoliarov
9c9029d0b6 xpp: fxs: reduce loop current to reduce heating 2017-09-13 15:33:31 +03:00
Tzafrir Cohen
39cd184c29 xpp: FPGA_1161.202.hex now alias for 201
We no longer need to maintain a separate firmware type 2.2: newer
versions of firmware types 2.1 will do.
2017-07-17 14:49:02 +03:00
Tzafrir Cohen
e2ee1eb30b xpp: card_pri: fix clocking initialization
Fix PCM synchronization between PRI module and the main board.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-06-26 19:01:34 +03:00
Tzafrir Cohen
d4ac65d0c1 xpp: fxo: update red alarms on span assignment
DAHDI gets notified of changes to battery status and hence to red alarm
on an FXO channel when the status changes. It thus needs to get notified
about it on "startup".

This startup was initially span registration. However following the
separation between device registration and span assignment, the
notification was sent after device registration, whereas it was ignored
if span was not assigned. It happened to work in most cases due to
delays.

This fix moves the startup notifications of battery status to the new
hook that is run on span assignment.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-06-26 17:58:33 +03:00
Tzafrir Cohen
7292c263ef xpp: add xpd method span_assigned
Add an phone device XPD method called 'span_assigned' that gets
called when the XPD's span is assigned.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-06-26 17:58:33 +03:00
Tzafrir Cohen
151853df0d xpp: bug fix in FPGA firmware: 11553
Update FPGA_1161.201.hex to rev. 11553 to fix
'category=2 errorbits=0x01' errors.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-06-26 17:58:33 +03:00
Dima Stoliarov
d9abf02894 xpp: init_card_6_3: parallel calibration
FXS module type 6: Further reduces time of the initialization by writing
to several ports' chips in parallel.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-06-26 17:58:33 +03:00
Dima Stoliarov
24648e6eb3 xpp: init_card_6_3: broadcasts for faster calibration
FXS module type 6: Use broadcast write for a much faster
calibration at init time.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-06-26 17:58:29 +03:00
Tzafrir Cohen
9c0002bf1f fail non-blocking I/O in case of span unassignment
In case a user has a file descriptor that is used for non-blocking I/O
and the span to which it belongs gets unassigned, its reads and writes
will still yield -EAGAIN.

This commit adds a test for such a case and returns the proper -ENODEV.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-06-26 17:49:13 +03:00
Shaun Ruffell
0159b0e7ce 'atomic_read()' -> refcount_read()'
The upstream 4.11 kernel, in commit (10383aea2f445bce9b2a2b308def08134b438c8e
"kref: Implement 'struct kref' using refcount_t"), changed refcount type on kref
objects. We now need to use refcount_read to read them.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2017-06-26 17:49:13 +03:00
Shaun Ruffell
ff88ccb1cd signal_pending() is now in linux/sched/signal.h include
Upstream kernel 4.11, in commit (bd0f9b356d00aa241ced36fb075a07041c28d3b8
"sched/headers: fix up header file dependency on <linux/sched/signal.h>"), now
requires users of signal_pending to include the new linux/sched/signal.h file.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2017-06-26 17:48:40 +03:00
Shaun Ruffell
7ab8780c25 GpakApi: Fix misleading indentation.
gcc-6.3.1 reports the following error when building the driver suite:

    drivers/dahdi/voicebus/GpakApi.c: In function 'gpakReadDSPMemoryMap':
    drivers/dahdi/voicebus/GpakApi.c:1560:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
         if (DspStatus != 0)
         ^~
    drivers/dahdi/voicebus/GpakApi.c:1563:2: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'if'
      for (i = 0; i < MemoryLength_Word16; i++)
      ^~~

So we'll now update the indentation level (which appears to be a side effect of
mixed tabs and spaces in this file).

NOTE: The GpakAPI files are checkpatch.pl unclean because I did not want to
increase the burden of merging in updates from the original provider, but it may
be time to go ahead and bring the file in compliance with the kernel coding
standards.

Internal-Issue-ID: DAHLIN-354
Reported-by: Sean Darcy
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2017-06-04 16:24:38 -05:00
Tzafrir Cohen
76ad75fc2a xpp: fxs: demote LED FXS6 messages to debug 2017-04-19 15:51:35 +03:00
Tzafrir Cohen
27b1ad108d xpp: fxs: remove verbose poll_inputs notice
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:35 +03:00
Dima Stoliarov
2dc030e61d xpp: bug fix in FPGA firmware: 11551
Update FPGA_1161.201.hex to rev. 11551 to fix the support of module type
6.
2017-04-19 15:51:34 +03:00
Tzafrir Cohen
5b9f520e78 xpp: re-add setting xpd->subunits
The number of subunits per XPD (which is not trivial in BRI) has been
accidentally left out in a previous commit.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:34 +03:00
Tzafrir Cohen
8e310fd264 xpp: output of parse_hexbyte() may be negative
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:34 +03:00
Tzafrir Cohen
6b119e60f5 xpp: remove useless sanity check of len field
The packet data length field may have other values in some cases (BRI D
channel).  It is also inherently limited to 3 bits.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:34 +03:00
Tzafrir Cohen
b8b884d205 xpp: correct size for BRI multibyte packets
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:34 +03:00
Tzafrir Cohen
95de230835 xpp: remove independent "Unknown" XPP_VERSION
The xpp drivers were originally developed seperately and thus had their
own version number. For quite some time they no longer have this version
number and report 'Revision: Unknown'.

Get rid of this mechanism.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:34 +03:00
Tzafrir Cohen
c05ad2200f xpp: fix chip/ports numbers sanity test
The test originally did not check any input from the hardware.
Fix it to check the actual (and proper) input from the hardware.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:34 +03:00
Tzafrir Cohen
55775ab0d2 xpp: FXS: RAM write support is fully implemented 2017-04-19 15:51:34 +03:00
Tzafrir Cohen
6456a027e5 xpp: init_card_6_30: Avoid using new perl features
Centos 5 has perl 5.8.8 . It does not support the '//' operator that was
added in perl 5.10. So sadly we have to avoid using it.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:51:32 +03:00
Tzafrir Cohen
92e4ce9b93 xpp: init_card_6_30: verify patches only on debug
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:50:55 +03:00
Tzafrir Cohen
fa57fed2df xpp: init_card_6_30: disable debug
* Don't enable debug by default.
* Demote some logging messages to debug.
* Remove a duplicate message about SLIC numbers.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-04-19 15:50:14 +03:00
Tzafrir Cohen
c21a98ebe5 xpp: FXS: Metering tone doesn't yet work on type 6
Generation of metering tone (a feture normally disabled at build time)
is not yet implemented on the new FXS type 6 module.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:49 +02:00
Oron Peled
d7e77a3e61 xpp: FXS type 6: ring and neon MWI support
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:48 +02:00
Dima Stoliarov
020735e3a7 xpp: FXS type 6: support digital outputs
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:48 +02:00
Dima Stoliarov
aaa1080a7c xpp: FXS type 6: support digital inputs
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:48 +02:00
Dima Stoliarov
7fcb793cd9 xpp: FXS type 6: hardware DTMF detection
Adapt the hardware DTMF detection for the SI32260 module.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:48 +02:00
Oron Peled
28a2cd068d xpp: FXS type 6: basic hookstate detection
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:48 +02:00
Oron Peled
a380b84545 xpp: FXS type 6: define registers
Add definitions of REG_TYPE6 for various SI32260 registers.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:48 +02:00
Dima Stoliarov
e47c096b73 xpp: FXS type 6: firmwares support
Firmware support for the type 6 FXS Astribank module.

FPGA_1161.201.hex rev. 11527
PIC_TYPE_6.hex rev. 11526
USB_FW.201.hex rev. 11502

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 15:42:46 +02:00
Dima Stoliarov
99ccfa35bb xpp: FXS type 6: init script (init_card_6_30)
Add init_card_6_30: an init script for new FXS based on Si32260 chip.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-21 14:09:11 +02:00
Dima Stoliarov
609114c0a9 xpp: FXS: support of I/O Expander.
Added do_expander field to SPI commands, in order to support an I/O
Expander on FXS.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-19 15:31:38 +02:00
Oron Peled
14d9a53162 xpp: support for RAM type register commands
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-16 16:55:35 +02:00
Oron Peled
2dd077cc53 xpp: FXS: rename all REG_* macros to REG_TYPE1_*
This is preparation for REG_TYPE6_* macros

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-16 16:55:29 +02:00
Dima Stoliarov
41279a8dcc xpp: added hwid attribute
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-16 16:11:50 +02:00
Oron Peled
d3a28c50cf xpp: a separate unit_descriptor
The new FXS chip supports two ports for each chip and hence we once
again need to look at hardware differently.

Struct unit_description includes information about all chips/port in a
specific module.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-16 13:46:15 +02:00
Oron Peled
17ac18d675 xpp: Remove unused "datalen" field from xframe
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-16 13:46:15 +02:00
Oron Peled
3d8d7995d7 xpp: XFRAME_NEW_REG_CMD
Prepare for different types of commands: replace XFRAME_NEW_CMD with
XFRAME_NEW_REG_CMD in some places.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-16 13:44:56 +02:00
Oron Peled
9dfc02a38c xpp: Check command type by length
Prepare for different types of commands: Don't assume a constant size.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-16 13:41:20 +02:00
Oron Peled
1c68f2ec73 xpp: refactor struct reg_cmd
Currently we only have REG (register) commands. Refactor it to allow
MEM (memory) commands.

* A common header
* Don't assume a constant size.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-15 12:01:39 +02:00
Oron Peled
d9aa82b025 xpp: rename xpd->type to xpd->xpd_type
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-03-14 20:37:45 +02:00
Oron Peled
a0434a8af5 xpp: remove unused #defines 2017-03-14 14:43:22 +02:00
Tzafrir Cohen
18de17084d wcfxo, wctdm: set spantype
* wctdm: set to SPANTYPE_ANALOG_MIXED. Maybe it could be improved if all
  slots have modules of the same type.
* wcfxo: type FXO.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2017-01-05 15:55:43 +02:00
Tzafrir Cohen
ffdfdfb66b xpp_usb: Fix potential corruption on clock rewind
The xpp modules use time differences for various statistics. In one case
xpp_usb creates a histogram of the time it took the system to send USB
packets (URBs). The time difference is used (after adjustments) as an
index to that array.

However if the clock happens to go back at that exact point in time, we
get to write to an arbitrary negative index in this array.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2016-03-16 18:20:44 +02:00
Wendell Thompson
4b242c3f84 Raised E1 pulse level for wcte43x targets 2016-02-15 15:45:51 -06:00
Tzafrir Cohen
8d1f17fc44 dahdi-modules: load and unloads the modules
A script that performs the module loading / unloading instead of the
init script.

Other functionality of the init script is performed by udev hooks. But
manual initiation of modules loading or unloading is still needed on
several occasions.

This script should help enable the removal of the init script from the
DAHDI package.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2015-11-05 18:11:57 +02:00
Oron Peled
404a67d089 xpp: improve handling of USB sluggishness
* Drop PCM during sluggish events:
  - Drop both rx/tx (was only tx)
  - Drop almost all pcm until sluggishness stops (used to drop only
    single pcm each time).
  - Renamed: "drop_next_pcm" -> "drop_pcm" (to match new semantics)
  - Still allow "keep alive" PCM so Astribank will not reset FXS high-voltage.
    The "sluggish_pcm_keepalive" parameter set the rate (1/50 by default)
  - Added rx/tx drop statistics counters
  - Removed "pcm_tx_drops" (replaced by new statistics counters)

* Also improved format of /proc/xpp/XBUS-*/xpp_usb:
  - Show cummulative number of sluggish events.
  - Clearly show range (in usec) of usb_tx_delay[]

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2015-11-02 10:49:42 +02:00
Russ Meyerriecks
fac77101fb wcb4xxp: Print serial number of gen 2 cards.
Now prints the serial number of the card to the kernel log for cards which
support this feature. This include the wcb23x and wcb43x series.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-10-27 09:54:43 -05:00
Russ Meyerriecks
80e0426dd6 wcb4xxp: Add support for wcb23x series
Adds support for Digium's new dual span wcb23x series cards. Also other minor
improvements for the new generation cards including the wcb23x and wcb43x

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-10-27 09:54:35 -05:00
Russ Meyerriecks
dd3c4ba015 wcb4xxp: Protect indirect register writes with sequence lock
A few of the indirect register writes to the A_ST_* indirect registers weren't
being protected by any kind of sequence lock. This could lead to potential race
conditions of two spans were configured simultaneously.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-10-23 16:25:59 -05:00
Russ Meyerriecks
92b645786d wcb4xxp: minor: Squelch initializing message on shutdown
The hw init function gets called on a module remove in order to reset the
hardware before shutdown. This was causing "Initializing zarlink echocan" to
print on shutdown which could be confusing.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-10-23 16:25:59 -05:00
Russ Meyerriecks
2cba62718f wcb4xxp: Remove "card sync source" logic
This logic was reading and printing the bri chips automatic selection of sync
source. We always use manual sync selection in the driver so this doesn't need
to exist.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-10-23 16:25:59 -05:00
Russ Meyerriecks
aa6a56863d octasic: Added slab.h include to fix ARM compile error
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-10-14 13:37:28 -05:00
Russ Meyerriecks
501222044c readme: Updated supported products section
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-10-14 13:30:28 -05:00
Shaun Ruffell
d5f13c5116 wctc4xxp: Clear packet error count when reloading firmware.
When the firmware is reloaded and reset, the packet error count is not.
This can create a condition where the firmware could report an error like
the following if a channel was closed without any new errors:

  wctc4xxp 0000:07:08.0: 18446744073709551597 errored receive packets

wcdte.packet_errors is also renamed to wcdte.reported_packet_errors to not
conflict with the packet_errors member of the descriptor lists.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-06-04 15:04:45 -05:00
Russ Meyerriecks
4df03284a8 wctc4xxp: Fix continuous "errored receive packets" with 2+ transcoders
In the case where two transcoders are loaded in a system and one transcoder
experiences an errored receive packet condition, the logic would ping pong the
error between the two cards, causing a runaway stream of errors in the kernel
log.

This fix moves the global error count var into the wcdte struct to allow for
per-card logic.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
2015-05-13 14:47:10 -05:00
Shaun Ruffell
8cd0823978 dahdi: Remove IRQF_DISABLED.
The IRQF_DISABLED flag was removed in 4.1 in commit
"genirq: Remove the deprecated 'IRQF_DISABLED' request_irq() flag entirely" [1].

By default all interrupt handlers are now run with interrupts disabled and
therefore should all be considered "fast interrupts". Any driver that was still
using the flag will now lock interrupts directly in the handler in case running
on an older kernel that is not disabling interrupts when running the handler.

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=d8bf368d0631d4bc2612d8bf2e4e8e74e620d0cc

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-05-13 14:45:01 -05:00
Shaun Ruffell
64a98af676 Remove DAHDI_IRQF_[SHARED|DISABLED] flags.
These flags are direct mappings to the IRQF_[SHARED|DISABLED] flags and no
longer need to be kept separate.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-05-13 14:45:01 -05:00
Shaun Ruffell
7ca082887a build_tools/make_version: Remove support for subversion working copies.
It has now been years since subversion has been used with this project. We can
go ahead and simplify the version script now.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-05-13 14:45:01 -05:00
Russ Meyerriecks
a008cc03b7 wcb4xxp: Add support for zarlink echocan
Introduces support for new series b43x cards which make use of the zarlink echo
canceller. Made as few changes to the b410 operation as possible, but the
critical region had some cleanups, so it may be a bit more performant.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-03-30 13:18:12 -05:00
John Sloan
ae5fa08abd wcxb: Fix "I/O error reported by firmware" followed by underruns
The cards affected include the TE131/3, TE235/435, A4B, and A8B.

Update all PCIe cards' firmware to increase the incoming and outgoing TDM FIFOs
to 16ms. The FIFOs will only be filled to a depth equal to the driver's latency
setting (ie. 3ms default). The total system latency is not effected. The
firmware and driver now also report the maximum DMA transaction time when in
DEBUG mode to aid in determining if the system is experiencing long PCIe
transactions (ie. TLP completion timeouts).

Decreased the maximum latency to from 20 to 12ms

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-03-30 13:18:12 -05:00
Tzafrir Cohen
6287954087 xpp: USB_FW*: fix incorrect chan num with 2FXS6FXO
New USB firmware that fix mis-reporting of the number of channels (or
rather: licenses) in the Astribank when a 2FXS6FXO module is used in
conjunction with another module.

USB_FW.hex: rev. 11452
USB_FW.201.hex: rev. 11453

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2015-03-30 16:02:48 +03:00
Tzafrir Cohen
b978e35636 README: use file time for reproducable build
https://bugs.debian.org/776622 asks to avoid using the build time in the
generated result to help make the build reproducable.

This fix uses the timestamp of README for generating the timestamp in
the footer of README.html.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2015-03-02 21:11:59 +02:00
Tzafrir Cohen
5c072d5bce xpp: module_refcount is back to int on 3.19
Commit d5db139ab3764640e0882a1746e7b9fdee33fd87 "module: make
module_refcount() a signed integer." included in 3.19 makes this
condition slightly more complex.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2015-03-02 21:11:57 +02:00
Shaun Ruffell
1559db9d1a dahdi: strnicmp() -> strncasecmp()
With commit (af3cd13501 "lib/string.c: remove strnicmp()") [1] dahdi can no
longer call strnicmp directly. strncasecmp was added into lib/string.c in kernel
version 2.6.22 so we'll map calls to strncasecmp to strnicmp for any kernel
before that.

This is necessary to compile against kernels >= 4.0.

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=af3cd13501

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2015-03-02 21:09:19 +02:00
Shaun Ruffell
1cc0ad510a dahdi: Fix "void value not ignored..." error when compiling against kernel 4.0.
With commit (d1f1052c52 "device: Change dev_<level> logging functions to return
void") [1] in kernel version 4.0, DAHDI would fail to compile with the following
error:

  .../drivers/dahdi/dahdi-base.c:7150:2: error: void value not ignored as it ought to be
    dahdi_dev_dbg(ASSIGN, span_device(span),
    ^

Now ignore the dev_printk return value.

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=d1f1052c5204524

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2015-03-02 21:07:21 +02:00
Shaun Ruffell
4d86a8f3f6 dahdi: struct file.f_dentry macro was removed in kernel 3.19
This is necessary to build against kernel version 3.19 since commit
(78d28e651f97866d608d9b41 "kill f_dentry macro") [1]

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=78d28e651

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-01-20 16:48:33 -06:00
Shaun Ruffell
e005030995 dahdi_dynamic: Release reference count on network device when destroying dynamic spans.
It was reported that for VLAN interfaces, failing to release this reference
count will prevent a system from rebooting properly, resulting in the need to
power cycle.

Reported-by: Assen Totin
Internal-Issue-ID: DAHLIN-343
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2015-01-20 16:47:55 -06:00
Tzafrir Cohen
ee691c23f4 xpp: firmware: a stray ^Z in FPGA_1161.201.hex 2014-11-17 18:00:51 +02:00
Tzafrir Cohen
9698657f7a xpp: firmware: 203 as alias to (newer) 201
Latest Astribank firmware (as of Rev. 11426 also supports some newer
hardware types, which will have the ID 203. Anyone installing this newer
version will now have 203 as an alias, but older versions will not have
it.
2014-11-17 17:55:47 +02:00
Tzafrir Cohen
79bf41ea8b xpp: FPGA_1161.201.hex: module types detection
New firmware that includes a better way to identify hardware modules
type that does not require multiplexers.

This is firmware file FPGA_1161.201.hex rev. 11426.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2014-11-05 20:08:47 +02:00
Shaun Ruffell
41b5353338 build_tools/dkms-helper: Use bash to process dkms-helper script.
Looks like there are some bashims in the script. Make this explicit in the
script until they can be taken out.

This fixes failures to run this script on Ubuntu when dash is the default shell.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-10-20 11:26:14 -05:00
Shaun Ruffell
378986841c dahdi: smp_mb_{before,after}_clear_bit -> smp_mb_{before,after}_atomic.
This is needed to compile against upstream Linux 3.18 since commit
"locking: Remove deprecated smp_mb__() barriers" [1].

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=2e39465abc4b7856a0ea6fcf4f

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-10-20 11:26:14 -05:00
Shaun Ruffell
b9a8000bbd dahdi: Fix failure to read / write on kernel 3.16+
Kernel version 3.16+, since upstream commit (7f7f25e82d54870d "replace checking
for ->read/->aio_read presence with check in ->f_mode" )[1], does not like it
when dahdi changes the set of allowed file operations on a file descriptor
outside of the context of an open() system call.

DAHDI changes the available file operations when a channel is opened by first
opening /dev/dahdi/channel and then calling the DAHDI_SPECIFY ioctl to bind it
to a particular DAHDI channel. Until DAHDI_SPECIFY is called there weren't any
read()/write() callbacks implemented and therefore after the initial open, the
kernel was setting not setting FMODE_CAN_{WRITE,READ} on the file descriptor
indicating that those operations were not allowed.

Now define empty shell functions on the general dahdi_fops so the vfs layer will
not mark a file descriptor as unwritteable or unreadable on open.

[1] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=7f7f25e82d54870df24d415a7007fbd327da027b

Internal-Issue-ID: DAHLIN-340
Reported-and-tested-by: Thomas B. Clark
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-09-17 16:29:16 -05:00
Michael Walton
eedb4bf944 dynamic: Prevent oops due to inverted compile flag
The logic on ENABLE_TASKELETS compiler flag was inverted causing an oops on
normal dahdi_cfg of a dynamic span.

Issue-id: https://issues.asterisk.org/jira/browse/DAHLIN-328

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
2014-08-15 14:58:47 -05:00
64 changed files with 19773 additions and 79698 deletions

2
.gitignore vendored
View File

@@ -1,6 +1,8 @@
# Files that are generated as part of the build process which we do not want git
# to track.
/.pc
*.[oa]
*.mod
*.mod.[oc]

View File

@@ -102,8 +102,6 @@ install-modconf:
/sbin/update-modules ; \
fi
install-xpp-firm:
$(MAKE) -C drivers/dahdi/xpp/firmwares install
install-firmware:
ifeq ($(HOTPLUG_FIRMWARE),yes)
@@ -190,8 +188,10 @@ dist-clean: clean
firmware-download:
@$(MAKE) -C drivers/dahdi/firmware all
ifneq (,$(wildcard test-script))
test:
./test-script $(DESTDIR)/lib/modules/$(KVERS) dahdi
endif
docs: $(GENERATED_DOCS)

235
README
View File

@@ -12,43 +12,46 @@ Supported Hardware
------------------
Digital Cards
~~~~~~~~~~~~~
- wcte43x:
* Digium TE435: PCI express quad-port T1/E1/J1
* Digium TE436: PCI quad-port T1/E1/J1
* Digium TE235: PCI express dual-port T1/E1/J1
* Digium TE236: PCI dual-port T1/E1/J1
- wcte13xp:
* Digium TE131: PCI express single-port T1/E1/J1
* Digium TE133: PCI express single-port T1/E1/J1 with echocan
* Digium TE132: PCI single-port T1/E1/J1
* Digium TE134: PCI single-port T1/E1/J1 with echocan
- wct4xxp:
* Digium TE205P/TE207P/TE210P/TE212P: PCI dual-port T1/E1/J1
* Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1
* Digium TE220: PCI-Express dual-port T1/E1/J1
* Digium TE420: PCI-Express quad-port T1/E1/J1
* Digium TE820: PCI-Express eight-port T1/E1/J1
- wcte12xp:
* Digium TE120P: PCI single-port T1/E1/J1
* Digium TE121: PCI-Express single-port T1/E1/J1
* Digium TE122: PCI single-port T1/E1/J1
- wcte11xp:
* Digium TE110P: PCI single-port T1/E1/J1
- wct1xxp:
* Digium T100P: PCI single-port T1
* Digium E100P: PCI single-port E1
- wcb4xxp:
* Digium B410: PCI quad-port BRI
- tor2: Tormenta quad-span T1/E1 card from the Zapata Telephony project
* Digium B233: PCI-Express dual-port BRI with echo can
* Digium B234: PCI dual-port dual-port BRI with echo can
* Digium B433: PCI-Express quad-port BRI with echo can
* Digium B434: PCI quad-port BRI with echo can
Analog Cards
~~~~~~~~~~~~
- wcaxx:
* Digium A8A: PCI up to 8 mixed FXS/FXO ports
* Digium A8B: PCI express up to 8 mixed FXS/FXO ports
* Digium A4A: PCI up to 4 mixed FXS/FXO ports
* Digium A4B: PCI express up to 4 mixed FXS/FXO ports
- wctdm24xxp:
* Digium TDM2400P/AEX2400: up to 24 analog ports
* Digium TDM800P/AEX800: up to 8 analog ports
* Digium TDM410P/AEX410: up to 4 analog ports
* Digium Hx8 Series: Up to 8 analog or BRI ports
- wctdm:
* Digium TDM400P: up to 4 analog ports
- xpp: Xorcom Astribank: a USB connected unit of up to 32 ports
(including the digital BRI and E1/T1 modules)
- wcfxo: X100P, similar and clones. A simple single-port FXO card
Other Drivers
~~~~~~~~~~~~~
- pciradio: Zapata Telephony PCI Quad Radio Interface
- wctc4xxp: Digium hardware transcoder cards (also need dahdi_transcode)
- dahdi_dynamic_eth: TDM over Ethernet (TDMoE) driver. Requires dahdi_dynamic
- dahdi_dynamic_loc: Mirror a local span. Requires dahdi_dynamic
@@ -181,204 +184,6 @@ you a clue of the versions installed:
find /lib/modules -name dahdi.ko
Installing the B410P drivers with mISDN
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DAHDI includes the wcb4xxp driver for the B410P, however, support for the
B410P was historically provided by mISDN. If you would like to use the mISDN
driver with the B410P, please comment out the wcb4xxp line in /etc/dahdi/modules.
This will prevent DAHDI from loading wcb4xxp which will conflict with the mISDN
driver.
To install the mISDN driver for the B410P, please see http://www.misdn.org for
more information, but the following sequence of steps is roughly equivalent to
'make b410p' from previous releases.
wget http://www.misdn.org/downloads/releases/mISDN-1_1_8.tar.gz
wget http://www.misdn.org/downloads/releases/mISDNuser-1_1_8.tar.gz
tar xfz mISDN-1_1_8.tar.gz
tar xfz mISDNuser-1_1_8.tar.gz
pushd mISDN-1_1_8
make install
popd
pushd mISDNuser-1_1_8
make install
popd
/usr/sbin/misdn-init config
You will then also want to make sure /etc/init.d/misdn-init is started
automatically with either 'chkconfig --add misdn-init' or 'update-rc.d
misdn-init defaults 15 30' depending on your distribution.
NOTE: At the time this was written, misdn-1.1.8 is not compatible the
2.6.25 kernel. Please use a kernel version 2.6.25 or earlier.
OSLEC
~~~~~
http://www.rowetel.com/ucasterisk/oslec.html[OSLEC] is an
Open Source Line Echo Canceller. It is currently in the staging subtree
of the mainline kernel and will hopefully be fully merged at around
version 2.6.29. The echo canceller module dahdi_echocan_oslec
provides a DAHDI echo canceller module that uses the code from OSLEC. As
OSLEC has not been accepted into mainline yet, its interface is not set
in stone and thus this driver may need to change. Thus it is not
built by default.
Luckily the structure of the dahdi-linux tree matches that of the kernel
tree. Hence you can basically copy drivers/staging/echo and place it
under driver/staging/echo . In fact, dahdi_echocan_oslec assumes that
this is where the oslec code lies. If it is elsewhere you'll need to fix
the #include line.
Thus for the moment, the simplest way to build OSLEC with dahdi is to
copy the directory `drivers/staging/echo` from a recent kernel tree (at
least 2.6.28-rc1) to the a subdirectory with the same name in the
dahdi-linux tree.
After doing that, you'll see the following when building (running
'make')
...
CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/dahdi_echocan_oslec.o
CC [M] /home/tzafrir/dahdi-linux/drivers/dahdi/../staging/echo/echo.o
...
As this is an experimental driver, problems building and using it should
be reported on the
https://lists.sourceforge.net/lists/listinfo/freetel-oslec[OSLEC mailing
list].
Alternatively you can also get the OSLEC code from the dahdi-linux-extra
GIT repository:
git clone git://gitorious.org/dahdi-extra/dahdi-linux-extra.git
cd dahdi-linux-extra
git archive extra-2.6 drivers/staging | (cd ..; tar xf -)
cd ..; rm -rf dahdi-linux-extra
Live Install
~~~~~~~~~~~~
In many cases you already have DAHDI installed on your system but would
like to try a different version. E.g. in order to check if the latest
version fixes a bug that your current system happens to have.
DAHDI-linux includes a script to automate the task of installing DAHDI
to a subtree and using it instead of the system copy. Module loading
through modprobe cannot be used. Thus the script pre-loads the required
modules with insmod (which requires some quesswork as for which modules
to load). It also sets PATH and other environment variables to make all
the commands do the right thing.
There is an extra mode of operation to copy all the required files to a
remote host and run things there, for those who don't like to test code
on thir build system.
Live Install: The Basics
^^^^^^^^^^^^^^^^^^^^^^^^
Basic operation is through running
./build_tools/live_dahdi
from the root directory of the dahdi-linux tree. Using DAHDI requires
dahdi-tools as well, and the script builds and installs dahdi-tools. By
default it assumes the tree of dahdi-tools is in the directory
'dahdi-tools' alongside the dahdi-linux tree. If you want to checkout
the trunks from SVN, use:
svn checkout http://svn.asterisk.org/svn/dahdi/linux/trunk dahdi-linux
svn checkout http://svn.asterisk.org/svn/dahdi/tools/trunk dahdi-tools
cd dahdi-linux
If the tools directory resides elsewhere, you'll need to edit
live/live.conf (see later on). The usage message of live_dahdi:
Usage: equivalent of:
live_dahdi configure ./configure
live_dahdi install make install
live_dahdi config make config
live_dahdi unload /etc/init.d/dahdi stop
live_dahdi load /etc/init.d/dahdi start
live_dahdi reload /etc/init.d/dahdi restart
live_dahdi xpp-firm (Reset and load xpp firmware)
live_dahdi rsync TARGET (copy filea to /tmp/live in host TARGET)
live_dahdi exec COMMAND (Run COMMAND in 'live' environment)
Normally you should run:
./build_tools/live_dahdi configure
./build_tools/live_dahdi install
./build_tools/live_dahdi config
to build and install everything. Up until now no real change was done.
This could actually be run by a non-root user. All files are installed
under the subdirectory live/ .
Reloading the modules (and restarting Asterisk) is done by:
./build_tools/live_dahdi reload
Note: this stops Asterisk, unloads the DAHDI modules, loads the DAHDI
modules from the live/ subdirectory, configures the system and re-starts
Asterisk. This *can* do damage to your system. Furthermore, the DAHDI
configuration is generated by dahdi_genconf. It can be influenced by
a genconf_parameters file. But it may or may not be what you want.
If you want to run a command in the environment of the live system, use
the command 'exec':
./build_tools/live_dahdi lsdahdi
./build_tools/live_dahdi dahdi_hardware -v
Note however:
./build_tools/live_dahdi dahdi_cfg -c live/etc/dahdi/system.conf
Live Install Remote
^^^^^^^^^^^^^^^^^^^
As mentioned above, live_dahdi can also copy all the live system files
to a remote system and run from there. This requires rsync installed on
both system and assumes you can connect to the remove system through
ssh.
tzafrir@hilbert $ ./build_tools/live_dahdi rsync root@david
root@david's password:
<f+++++++++ live_dahdi
cd+++++++++ live/
<f+++++++++ live/live.conf
cd+++++++++ live/dev/
cd+++++++++ live/dev/dahdi/
cd+++++++++ live/etc/
cd+++++++++ live/etc/asterisk/
cd+++++++++ live/etc/dahdi/
<f+++++++++ live/etc/dahdi/genconf_parameters
<f+++++++++ live/etc/dahdi/init.conf
...
As you can see, it copies the script itselfand the whole live/
subdirectory. The target directory is /tmp/live on the target directory
(changing it should probably be simple, but I never needed that).
Then, on the remove computer:
root@david:/tmp# ./live_dahdi reload
Configuring a Live Install
^^^^^^^^^^^^^^^^^^^^^^^^^^
The live_dahdi script reads a configuration file in 'live/live.conf' if
it exists. This file has the format of a shell script snippet:
var1=value # a '#' sign begins a comment
var2='value'
# comments and empty lines are ignored
var3="value"
The variables below can also be overriden from the environment:
var1='value' ./build_tools/live_dahdi
===== LINUX_DIR
The relative path to the dahdi-linux tree. The default is '.' and normally
there's no reason to override it.
@@ -1441,7 +1246,5 @@ http://issues.asterisk.org in the "DAHDI-linux" category.
Links
-----
- http://asterisk.org/[] - The Asterisk PBX
- http://voip-info.org/[]
- http://voip-info.org/wiki/view/DAHDI[]
- http://docs.tzafrir.org.il/dahdi-linux/README.html[Up-to-date HTML version
of this file]

View File

@@ -2,119 +2,18 @@
if [ -f ${1}/.version ]; then
cat ${1}/.version
elif [ -f ${1}/.svnrevision ]; then
echo SVN-`cat ${1}/.svnbranch`-r`cat ${1}/.svnrevision`
elif [ -d ${1}/.svn ]; then
PARTS=`LANG=C svn info ${1} | grep URL | awk '{print $2;}' | sed -e s:^.*/svn/${2}/:: | sed -e 's:/: :g'`
BRANCH=0
TEAM=0
REV=`svnversion -c ${1} | cut -d: -f2`
if [ "${PARTS}" = "trunk" ]
then
echo SVN-'trunk'-r${REV}
exit 0
fi
for PART in $PARTS
do
if [ ${BRANCH} != 0 ]
then
RESULT="${RESULT}-${PART}"
break
fi
if [ ${TEAM} != 0 ]
then
RESULT="${RESULT}-${PART}"
continue
fi
if [ "${PART}" = "branches" ]
then
BRANCH=1
RESULT="branch"
continue
fi
if [ "${PART}" = "tags" ]
then
BRANCH=1
RESULT="tag"
continue
fi
if [ "${PART}" = "team" ]
then
TEAM=1
continue
fi
done
echo SVN-${RESULT##-}-r${REV}
elif [ -d ${1}/.git ]; then
# If the first log commit messages indicates that this is checked into
# subversion, we'll just use the SVN- form of the revision.
MODIFIED=""
SVN_REV=`git log --pretty=full -1 | grep -F "git-svn-id:" | sed -e "s/.*\@\([^\s]*\)\s.*/\1/g"`
if [ -z "$SVN_REV" ]; then
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
if [ $? -ne 0 ]; then
if [ "`git ls-files -m | wc -l`" != "0" ]; then
MODIFIED="M"
fi
# Some older versions of git do not support all the above
# options.
VERSION=GIT-`git rev-parse --short --verify HEAD`${MODIFIED}
fi
echo ${VERSION}
else
PARTS=`LANG=C git log --pretty=full | grep -F "git-svn-id:" | head -1 | awk '{print $2;}' | sed -e s:^.*/svn/$2/:: | sed -e 's:/: :g' | sed -e 's/@.*$//g'`
BRANCH=0
TEAM=0
VERSION=`git describe --tags --dirty=M 2> /dev/null | sed -e "s/^v\([0-9]\)/\1/"`
if [ $? -ne 0 ]; then
MODIFIED=""
if [ "`git ls-files -m | wc -l`" != "0" ]; then
MODIFIED="M"
fi
if [ "${PARTS}" = "trunk" ]; then
echo SVN-'trunk'-r${SVN_REV}${MODIFIED}
exit 0
fi
for PART in $PARTS
do
if [ ${BRANCH} != 0 ]; then
RESULT="${RESULT}-${PART}"
break
fi
if [ ${TEAM} != 0 ]; then
RESULT="${RESULT}-${PART}"
continue
fi
if [ "${PART}" = "branches" ]; then
BRANCH=1
RESULT="branch"
continue
fi
if [ "${PART}" = "tags" ]; then
BRANCH=1
RESULT="tag"
continue
fi
if [ "${PART}" = "team" ]; then
TEAM=1
continue
fi
done
echo SVN-${RESULT##-}-r${SVN_REV}${MODIFIED}
# Some older versions of git do not support all the above
# options.
VERSION=GIT-`git rev-parse --short --verify HEAD`${MODIFIED}
fi
echo ${VERSION}
else
# Use the directory information in the absence of any other version
# information

72
dahdi-modules Executable file
View File

@@ -0,0 +1,72 @@
#!/bin/sh
MODULES="dahdi"
DAHDI_MODULES_FILE="/etc/dahdi/modules"
usage() {
cat <<EOF
$0: loads / unloads DAHDI kernel modules
Usage: $0 <load|unload>
* load: Loads all modules listed in /etc/dahdi/modules (one per line)
* unload: Unloads the DAHDI modules (all the modules that are dependencies
of $MODULES).
EOF
}
# recursively unload a module and its dependencies, if possible.
# where's modprobe -r when you need it?
# inputs: module to unload.
# returns: the result from
unload_module() {
module="$1"
line=`lsmod 2>/dev/null | grep "^$1 "`
if [ "$line" = '' ]; then return; fi # module was not loaded
set -- $line
# $1: the original module, $2: size, $3: refcount, $4: deps list
mods=`echo $4 | tr , ' '`
ec_modules=""
# xpp_usb keeps the xpds below busy if an xpp hardware is
# connected. Hence must be removed before them:
case "$module" in xpd_*) mods="xpp_usb $mods";; esac
for mod in $mods; do
case "$mod" in
dahdi_echocan_*)
ec_modules="$mod $ec_modules"
;;
*)
# run in a subshell, so it won't step over our vars:
(unload_module $mod)
;;
esac
done
# Now that all the other dependencies are unloaded, we can unload the
# dahdi_echocan modules. The drivers that register spans may keep
# references on the echocan modules before they are unloaded.
for mod in $ec_modules; do
(unload_module $mod)
done
rmmod $module
}
unload_modules() {
for module in "$@"; do
unload_module $module
done
}
load_modules() {
modules=`sed -e 's/#.*$//' $DAHDI_MODULES_FILE 2>/dev/null`
for line in $modules; do
modprobe $line
done
}
case "$1" in
load) load_modules "$@";;
unload) unload_modules $MODULES;;
*) usage;;
esac

View File

@@ -11,7 +11,6 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) += oct612x/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTC4XXP) += wctc4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM24XXP) += wctdm24xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE13XP) += wcte13xp.o
wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o
@@ -36,16 +35,10 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcaxx-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTDM) += wctdm.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_VOICEBUS) += voicebus/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP) += wcb4xxp/
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT1XXP) += wct1xxp.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE11XP) += wcte11xp.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCFXO) += wcfxo.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TOR2) += tor2.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_PCIRADIO) += pciradio.o
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP) += xpp/
@@ -66,7 +59,7 @@ obj-m += dahdi_echocan_oslec.o
obj-m += ../staging/echo/echo.o
endif
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src)
CFLAGS_MODULE += -I$(DAHDI_INCLUDE) -I$(src) -Wno-format-truncation
ifndef HOTPLUG_FIRMWARE
ifneq (,$(filter y m,$(CONFIG_FW_LOADER)))
@@ -158,15 +151,9 @@ ifeq ($(HPEC_PRESENT),yes)
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_HPEC) += dahdi_echocan_hpec.o
endif
$(obj)/pciradio.o: $(obj)/radfw.h
$(obj)/tor2.o: $(obj)/tor2fw.h
hostprogs-y := makefw
$(obj)/tor2fw.h: $(src)/tormenta2.rbt $(obj)/makefw
$(obj)/makefw $< tor2fw > $@
$(obj)/radfw.h: $(src)/pciradio.rbt $(obj)/makefw
$(obj)/makefw $< radfw > $@
clean-files := radfw.h tor2fw.h
clean-files := radfw.h

View File

@@ -69,18 +69,6 @@ config DAHDI_ECHOCAN_HPEC
If unsure, say Y.
config DAHDI_WCTDM
tristate "Digium Wildcard TDM400P Support"
depends on DAHDI && PCI
default DAHDI
---help---
This driver provides support for the Digium Wildcard TDM400P.
To compile this driver as a module, choose M here: the
module will be called wctdm.
If unsure, say Y.
config DAHDI_WCT4XXP
tristate "Digium Wildcard dual- and quad-T1/E1/J1 Support"
depends on DAHDI && PCI
@@ -158,23 +146,6 @@ config DAHDI_WCTDM24XXP
If unsure, say Y.
config DAHDI_WCTE12XP
tristate "Digium Wildcard VoiceBus digital card Support"
depends on DAHDI && DAHDI_VOICEBUS
default DAHDI
---help---
This driver provides support for the following Digium
Wildcard products:
* TE120P (PCI/PCI-X)
* TE121 (PCI/PCI-X)
* TE122 (PCI-E)
To compile this driver as a module, choose M here: the
module will be called wcte12xp.
If unsure, say Y.
config DAHDI_PCIRADIO
tristate "PCI Radio Support"
depends on DAHDI && PCI
@@ -251,44 +222,5 @@ config DAHDI_DYNAMIC_LOC
If unsure, say Y.
config DAHDI_TOR2
tristate "Tormenta2 quad-port T1/E1 Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called tor2.
If unsure, say Y.
config DAHDI_WCFXO
tristate "Digium Wildcard X100P Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called wcfxo.
If unsure, say Y.
config DAHDI_WCT1XXP
tristate "Digium Wildcard T100P Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called wct1xxp.
If unsure, say Y.
config DAHDI_WCTE11XP
tristate "Digium Wildcard TE110P Support"
depends on DAHDI && PCI
default DAHDI
---help---
To compile this driver as a module, choose M here: the
module will be called wcte11xp.
If unsure, say Y.
source "drivers/dahdi/xpp/Kconfig"

View File

@@ -66,6 +66,11 @@
/* Grab fasthdlc with tables */
#define FAST_HDLC_NEED_TABLES
#include <dahdi/kernel.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/signal.h>
#endif /* 4.11.0 */
#include "ecdis.h"
#include "dahdi.h"
@@ -2409,6 +2414,9 @@ static ssize_t dahdi_chan_read(struct file *file, char __user *usrbuf,
if (unlikely(count < 1))
return -EINVAL;
if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)))
return -ENODEV;
for (;;) {
spin_lock_irqsave(&chan->lock, flags);
if (chan->eventinidx != chan->eventoutidx) {
@@ -2526,6 +2534,9 @@ static ssize_t dahdi_chan_write(struct file *file, const char __user *usrbuf,
if (unlikely(count < 1))
return -EINVAL;
if (unlikely(!test_bit(DAHDI_FLAGBIT_REGISTERED, &chan->flags)))
return -ENODEV;
for (;;) {
spin_lock_irqsave(&chan->lock, flags);
if ((chan->curtone || chan->pdialcount) && !is_pseudo_chan(chan)) {
@@ -5698,9 +5709,9 @@ static int dahdi_ioctl_setconf(struct file *file, unsigned long data)
}
/* if changing confs, clear last added info */
if (conf.confno != chan->confna) {
memset(chan->conflast, 0, DAHDI_MAX_CHUNKSIZE);
memset(chan->conflast1, 0, DAHDI_MAX_CHUNKSIZE);
memset(chan->conflast2, 0, DAHDI_MAX_CHUNKSIZE);
memset(chan->conflast, 0, sizeof(chan->conflast));
memset(chan->conflast1, 0, sizeof(chan->conflast1));
memset(chan->conflast2, 0, sizeof(chan->conflast2));
}
oldconf = chan->confna; /* save old conference number */
chan->confna = conf.confno; /* set conference number */
@@ -10058,7 +10069,7 @@ static inline unsigned long msecs_processed(const struct core_timer *const ct)
return atomic_read(&ct->count) * DAHDI_MSECS_PER_CHUNK;
}
static void coretimer_func(unsigned long param)
static void coretimer_func(TIMER_DATA_TYPE unused)
{
unsigned long flags;
unsigned long ms_since_start;
@@ -10139,16 +10150,14 @@ static void coretimer_func(unsigned long param)
static void coretimer_init(void)
{
init_timer(&core_timer.timer);
core_timer.timer.function = coretimer_func;
timer_setup(&core_timer.timer, coretimer_func, 0);
ktime_get_ts(&core_timer.start_interval);
atomic_set(&core_timer.count, 0);
atomic_set(&core_timer.shutdown, 0);
core_timer.interval = max(msecs_to_jiffies(DAHDI_MSECS_PER_CHUNK), 1UL);
if (core_timer.interval < (HZ/250))
core_timer.interval = (HZ/250);
core_timer.timer.expires = jiffies + core_timer.interval;
add_timer(&core_timer.timer);
mod_timer(&core_timer.timer, jiffies + core_timer.interval);
}
static void coretimer_cleanup(void)
@@ -10444,7 +10453,7 @@ static const struct file_operations dahdi_chan_fops = {
#ifdef CONFIG_DAHDI_WATCHDOG
static struct timer_list watchdogtimer;
static void watchdog_check(unsigned long ignored)
static void watchdog_check(TIMER_DATA_TYPE ignored)
{
unsigned long flags;
static int wdcheck=0;
@@ -10485,10 +10494,7 @@ static void watchdog_check(unsigned long ignored)
static int __init watchdog_init(void)
{
init_timer(&watchdogtimer);
watchdogtimer.expires = 0;
watchdogtimer.data =0;
watchdogtimer.function = watchdog_check;
timer_setup(&watchdogtimer, watchdog_check, 0);
/* Run every couple of jiffy or so */
mod_timer(&watchdogtimer, jiffies + 2);
return 0;

View File

@@ -158,6 +158,7 @@ static BUS_ATTR_READER(ec_state_show, dev, buf)
return len;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
static struct device_attribute chan_dev_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(channo),
@@ -174,6 +175,39 @@ static struct device_attribute chan_dev_attrs[] = {
__ATTR_RO(in_use),
__ATTR_NULL,
};
#else
static DEVICE_ATTR_RO(name);
static DEVICE_ATTR_RO(channo);
static DEVICE_ATTR_RO(chanpos);
static DEVICE_ATTR_RO(sig);
static DEVICE_ATTR_RO(sigcap);
static DEVICE_ATTR_RO(alarms);
static DEVICE_ATTR_RO(ec_factory);
static DEVICE_ATTR_RO(ec_state);
static DEVICE_ATTR_RO(blocksize);
#ifdef OPTIMIZE_CHANMUTE
static DEVICE_ATTR_RO(chanmute);
#endif
static DEVICE_ATTR_RO(in_use);
static struct attribute *chan_dev_attrs[] = {
&dev_attr_name.attr,
&dev_attr_channo.attr,
&dev_attr_chanpos.attr,
&dev_attr_sig.attr,
&dev_attr_sigcap.attr,
&dev_attr_alarms.attr,
&dev_attr_ec_factory.attr,
&dev_attr_ec_state.attr,
&dev_attr_blocksize.attr,
#ifdef OPTIMIZE_CHANMUTE
&dev_attr_chanmute.attr,
#endif
&dev_attr_in_use.attr,
NULL,
};
ATTRIBUTE_GROUPS(chan_dev);
#endif
static void chan_release(struct device *dev)
{
@@ -196,7 +230,11 @@ static int chan_match(struct device *dev, struct device_driver *driver)
static struct bus_type chan_bus_type = {
.name = "dahdi_channels",
.match = chan_match,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
.dev_attrs = chan_dev_attrs,
#else
.dev_groups = chan_dev_groups,
#endif
};
static int chan_probe(struct device *dev)

View File

@@ -214,6 +214,7 @@ static BUS_ATTR_READER(linecompat_show, dev, buf)
return len;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
static struct device_attribute span_dev_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(desc),
@@ -230,6 +231,39 @@ static struct device_attribute span_dev_attrs[] = {
__ATTR_RO(linecompat),
__ATTR_NULL,
};
#else
static DEVICE_ATTR_RO(name);
static DEVICE_ATTR_RO(desc);
static DEVICE_ATTR_RO(spantype);
static DEVICE_ATTR_RO(local_spanno);
static DEVICE_ATTR_RO(alarms);
static DEVICE_ATTR_RO(lbo);
static DEVICE_ATTR_RO(syncsrc);
static DEVICE_ATTR_RO(is_digital);
static DEVICE_ATTR_RO(is_sync_master);
static DEVICE_ATTR_RO(basechan);
static DEVICE_ATTR_RO(channels);
static DEVICE_ATTR_RO(lineconfig);
static DEVICE_ATTR_RO(linecompat);
static struct attribute *span_dev_attrs[] = {
&dev_attr_name.attr,
&dev_attr_desc.attr,
&dev_attr_spantype.attr,
&dev_attr_local_spanno.attr,
&dev_attr_lbo.attr,
&dev_attr_alarms.attr,
&dev_attr_syncsrc.attr,
&dev_attr_is_digital.attr,
&dev_attr_is_sync_master.attr,
&dev_attr_basechan.attr,
&dev_attr_channels.attr,
&dev_attr_lineconfig.attr,
&dev_attr_linecompat.attr,
NULL,
};
ATTRIBUTE_GROUPS(span_dev);
#endif
static ssize_t master_span_show(struct device_driver *driver, char *buf)
{
@@ -270,7 +304,11 @@ static struct bus_type spans_bus_type = {
.name = "dahdi_spans",
.match = span_match,
.uevent = span_uevent,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
.dev_attrs = span_dev_attrs,
#else
.dev_groups = span_dev_groups,
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
.drv_attrs = dahdi_attrs,
#else
@@ -482,7 +520,7 @@ static int device_uevent(struct device *dev, struct kobj_uevent_env *kenv)
#endif
static ssize_t
dahdi_device_manufacturer_show(struct device *dev,
manufacturer_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -490,7 +528,7 @@ dahdi_device_manufacturer_show(struct device *dev,
}
static ssize_t
dahdi_device_type_show(struct device *dev,
type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -498,7 +536,7 @@ dahdi_device_type_show(struct device *dev,
}
static ssize_t
dahdi_device_span_count_show(struct device *dev,
span_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -512,7 +550,7 @@ dahdi_device_span_count_show(struct device *dev,
}
static ssize_t
dahdi_device_hardware_id_show(struct device *dev,
hardware_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -522,7 +560,7 @@ dahdi_device_hardware_id_show(struct device *dev,
}
static ssize_t
dahdi_device_location_show(struct device *dev,
location_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -532,7 +570,7 @@ dahdi_device_location_show(struct device *dev,
}
static ssize_t
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
auto_assign_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dahdi_device *ddev = to_ddev(dev);
@@ -541,7 +579,7 @@ dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
}
static ssize_t
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
assign_span_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
@@ -576,7 +614,7 @@ dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
}
static ssize_t
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
unassign_span_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
@@ -690,25 +728,56 @@ dahdi_registration_time_show(struct device *dev,
return count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
static struct device_attribute dahdi_device_attrs[] = {
__ATTR(manufacturer, S_IRUGO, dahdi_device_manufacturer_show, NULL),
__ATTR(type, S_IRUGO, dahdi_device_type_show, NULL),
__ATTR(span_count, S_IRUGO, dahdi_device_span_count_show, NULL),
__ATTR(hardware_id, S_IRUGO, dahdi_device_hardware_id_show, NULL),
__ATTR(location, S_IRUGO, dahdi_device_location_show, NULL),
__ATTR(auto_assign, S_IWUSR, NULL, dahdi_device_auto_assign),
__ATTR(assign_span, S_IWUSR, NULL, dahdi_device_assign_span),
__ATTR(unassign_span, S_IWUSR, NULL, dahdi_device_unassign_span),
__ATTR(manufacturer, S_IRUGO, manufacturer_show, NULL),
__ATTR(type, S_IRUGO, type_show, NULL),
__ATTR(span_count, S_IRUGO, span_count_show, NULL),
__ATTR(hardware_id, S_IRUGO, hardware_id_show, NULL),
__ATTR(location, S_IRUGO, location_show, NULL),
__ATTR(auto_assign, S_IWUSR, NULL, auto_assign_store),
__ATTR(assign_span, S_IWUSR, NULL, assign_span_store),
__ATTR(unassign_span, S_IWUSR, NULL, unassign_span_store),
__ATTR(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show,
dahdi_spantype_store),
__ATTR(registration_time, S_IRUGO, dahdi_registration_time_show, NULL),
__ATTR_NULL,
};
#else
static DEVICE_ATTR_RO(manufacturer);
static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RO(span_count);
static DEVICE_ATTR_RO(hardware_id);
static DEVICE_ATTR_RO(location);
static DEVICE_ATTR_WO(auto_assign);
static DEVICE_ATTR_WO(assign_span);
static DEVICE_ATTR_WO(unassign_span);
static DEVICE_ATTR_RW(dahdi_spantype);
static DEVICE_ATTR_RO(dahdi_registration_time);
static struct attribute *dahdi_device_attrs[] = {
&dev_attr_manufacturer.attr,
&dev_attr_type.attr,
&dev_attr_span_count.attr,
&dev_attr_hardware_id.attr,
&dev_attr_location.attr,
&dev_attr_auto_assign.attr,
&dev_attr_assign_span.attr,
&dev_attr_unassign_span.attr,
&dev_attr_dahdi_spantype.attr,
&dev_attr_dahdi_registration_time.attr,
NULL,
};
ATTRIBUTE_GROUPS(dahdi_device);
#endif
static struct bus_type dahdi_device_bus = {
.name = "dahdi_devices",
.uevent = device_uevent,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
.dev_attrs = dahdi_device_attrs,
#else
.dev_groups = dahdi_device_groups,
#endif
};
static void dahdi_sysfs_cleanup(void)

View File

@@ -157,7 +157,7 @@ static unsigned long timespec_diff_ms(struct timespec *t0, struct timespec *t1)
return ms;
}
static void dahdi_dummy_timer(unsigned long param)
static void dahdi_dummy_timer(struct timer_timer *unused)
{
unsigned long ms_since_start;
struct timespec now;
@@ -258,12 +258,10 @@ int init_module(void)
hrtimer_start(&zaptimer, ktime_set(0, DAHDI_TIME_NS), HRTIMER_MODE_REL);
printk(KERN_INFO "dahdi_dummy: High Resolution Timer started, good to go\n");
#else
init_timer(&timer);
timer.function = dahdi_dummy_timer;
timer_setup(&timer, dahdi_dummy_timer);
ztd->start_interval = current_kernel_time();
timer.expires = jiffies + JIFFIES_INTERVAL;
atomic_set(&shutdown, 0);
add_timer(&timer);
mod_timer(&timer, jiffies + JIFFIES_INTERVAL);
#endif
if (debug)

View File

@@ -467,7 +467,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
/* We shouldn't have more than the two references at this point. If
* we do, there are probably channels that are still opened. */
if (atomic_read(&d->kref.refcount) > 2) {
if (refcount_read(&d->kref.refcount) > 2) {
dynamic_put(d);
return -EBUSY;
}
@@ -638,8 +638,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CRC4 | DAHDI_CONFIG_NOTOPEN;
d->span.ops = &dynamic_ops;
for (x = 0; x < d->span.channels; x++) {
sprintf(d->chans[x]->name, "DYN/%s/%s/%d",
dds->driver, dds->addr, x+1);
snprintf(d->chans[x]->name, sizeof(d->chans[x]->name),
"DYN/%s/%s/%d", dds->driver, dds->addr, x+1);
d->chans[x]->sigcap = DAHDI_SIG_EM | DAHDI_SIG_CLEAR |
DAHDI_SIG_FXSLS | DAHDI_SIG_FXSKS |
DAHDI_SIG_FXSGS | DAHDI_SIG_FXOLS |
@@ -831,7 +831,7 @@ EXPORT_SYMBOL(dahdi_dynamic_unregister_driver);
static struct timer_list alarmcheck;
static void check_for_red_alarm(unsigned long ignored)
static void check_for_red_alarm(TIMER_DATA_TYPE unused)
{
int newalarm;
int alarmchanged = 0;
@@ -867,10 +867,7 @@ static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
static int dahdi_dynamic_init(void)
{
/* Start process to check for RED ALARM */
init_timer(&alarmcheck);
alarmcheck.expires = 0;
alarmcheck.data = 0;
alarmcheck.function = check_for_red_alarm;
timer_setup(&alarmcheck, check_for_red_alarm, 0);
/* Check once per second */
mod_timer(&alarmcheck, jiffies + 1 * HZ);
#ifdef ENABLE_TASKLETS

View File

@@ -681,16 +681,13 @@ static int ethmf_delay_dec(void)
* Timer callback function to allow all spans to be added, prior to any of
* them being used.
*/
static void timer_callback(unsigned long param)
static void timer_callback(TIMER_DATA_TYPE unused)
{
if (ethmf_delay_dec()) {
if (!atomic_read(&timer_deleted)) {
timer.expires = jiffies + HZ;
add_timer(&timer);
}
if (!atomic_read(&timer_deleted))
mod_timer(&timer, jiffies + HZ);
} else {
printk(KERN_INFO "All TDMoE multiframe span groups are active.\n");
del_timer(&timer);
}
}
@@ -764,11 +761,8 @@ static const struct file_operations ztdethmf_proc_fops = {
static int __init ztdethmf_init(void)
{
init_timer(&timer);
timer.expires = jiffies + HZ;
timer.function = &timer_callback;
if (!timer_pending(&timer))
add_timer(&timer);
timer_setup(&timer, timer_callback, 0);
mod_timer(&timer, jiffies + HZ);
dev_add_pack(&ztdethmf_ptype);
register_netdevice_notifier(&ztdethmf_nblock);

View File

@@ -148,7 +148,7 @@ static void sppp_lcp_open (struct sppp *sp);
static void sppp_ipcp_open (struct sppp *sp);
static int sppp_lcp_conf_parse_options (struct sppp *sp, struct lcp_header *h,
int len, u32 *magic);
static void sppp_cp_timeout (unsigned long arg);
static void sppp_cp_timeout (TIMER_DATA_TYPE timer);
static char *sppp_lcp_type_name (u8 type);
static char *sppp_ipcp_type_name (u8 type);
static void sppp_print_bytes (u8 *p, u16 len);
@@ -189,12 +189,9 @@ static void sppp_set_timeout(struct sppp *p,int s)
{
if (! (p->pp_flags & PP_TIMO))
{
init_timer(&p->pp_timer);
p->pp_timer.function=sppp_cp_timeout;
p->pp_timer.expires=jiffies+s*HZ;
p->pp_timer.data=(unsigned long)p;
p->pp_flags |= PP_TIMO;
add_timer(&p->pp_timer);
timer_setup(&p->pp_timer, sppp_cp_timeout, 0);
mod_timer(&p->pp_timer, jiffies + s*HZ);
}
}

View File

@@ -22,6 +22,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <dahdi/kernel.h>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,186 +0,0 @@
/*
* Tormenta 2 Quad-T1 PCI Driver
*
* Written by Mark Spencer <markster@linux-suppot.net>
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001-2008, Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef _TOR2_HW_H
#define _TOR2_HW_H
/*
* The Tormenta two consists of the following block architecture:
*
* [ Spartan ] --- [ DS 21Q352 ] -- Xfrms -- Span 1
* | | | | | | |
* Local Bus +----- Span 2
* | | | |
* [ PCI 9030 ] +----- Span 3
* | | | | | |
* PCI BUS +----- Span 4
*
* All communicatiosn to the framer (21Q352) are performed
* through the PCI 9030 part using memory mapped I/O.
*
* The Tormenta 2 requires a 2 2k wondows memory space
* which is mapped as follows:
*
* First (32 bit) space:
*
* 0x0000 -> 0x07FF: Memory map of Tx and Rx buffers. They are stored
* with increasing channel number, with each span in
* a byte of a 32-bit long word:
* Bits 31-24: Span 1
* Bits 23-16: Span 2
* Bits 16- 8: Span 3
* Bits 7- 0: Span 4
*
*
* Second (8 bit) space:
*
* 0x0000 -> 0x00FF: Registers for Transceiver 1
* 0x0100 -> 0x01FF: Registers for Transceiver 2
* 0x0200 -> 0x02FF: Registers for Transceiver 3
* 0x0300 -> 0x03FF: Registers for Transceiver 4
*
* 0x400 Write -> Firmware load location for Xilinx. This is the only valid
* register until the Xilinx is programmed to decode
* the remainder!
*
* 0x400 Write -> clkreg (sync source)
* 0=free run, 1=span 1, 2=span 2, 3=span 3, 4=span 4.
*
* 0x400 Read -> statreg
* bit 0 - Interrupt Enabled
* bit 1 - Interrupt Active
* bit 2 - Dallas Interrupt Active
*
* 0x401 Write -> ctlreg as follows:
* bit 0 - Interrupt Enable
* bit 1 - Drives "TEST1" signal ("Interrupt" outbit)
* bit 2 - Dallas Interrupt Enable (Allows DINT signal to drive INT)
* bit 3 - External Syncronization Enable (MASTER signal).
* bit 4 - Select E1 Divisor Mode (0 for T1, 1 for E1).
* bit 5 - Remote serial loopback (When set to 1, TSER is driven from RSER)
* bit 6 - Local serial loopback (When set to 1, Rx buffers are driven from Tx buffers)
* bit 7 - Interrupt Acknowledge (set to 1 to acknowledge interrupt)
*
* 0x402 Write -> LED register as follows:
* bit 0 - Span 1 Green
* bit 1 - Span 1 Red
* bit 2 - Span 2 Green
* bit 3 - Span 2 Red
* bit 4 - Span 3 Green
* bit 5 - Span 3 Red
* bit 6 - Span 4 Green
* bit 7 - Span 4 Red
* NOTE: turning on both red and green yields yellow.
*
* 0x403 Write -> TEST2, writing to bit 0 drives TEST2 pin.
*
* 0x404 Write -> ctlreg1 as follows:
* bit 0 - Non-REV.A Mode (Set this bit for Dallas chips later then Rev. A)
*/
#ifdef NEED_PCI_IDS
/*
* Provide routines for identifying a tormenta card
*/
#define PCI_VENDOR_ID_PLX 0x10b5
#ifdef __KERNEL__
static DEFINE_PCI_DEVICE_TABLE(tor2_pci_ids) =
#else
#define PCI_ANY_ID -1
static struct tor2_pci_id {
int vendor;
int device;
int subvendor;
int subdevice;
int class;
int classmask;
unsigned long driver_data;
} tor2_pci_ids[] =
#endif /* __KERNEL__ */
{
{ PCI_VENDOR_ID_PLX, 0x9030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX 9030" }, /* PLX 9030 Development board */
{ PCI_VENDOR_ID_PLX, 0x3001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"PLX Development Board" }, /* PLX 9030 Development board */
{ PCI_VENDOR_ID_PLX, 0xD00D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/PRI or E1/PRA" }, /* Tormenta 2 */
{ PCI_VENDOR_ID_PLX, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long)"Tormenta 2 Quad T1/E1 (non-Digium clone)" }, /* Tormenta 2 clone */
{ 0, }
};
#ifndef __KERNEL__
/* We provide a simple routine to match the given ID's */
static inline int tor2_pci_match(int vendorid, int deviceid, char **variant)
{
/* Returns 1 if this is a tormenta card or 0 if it isn't */
int x;
for (x = 0; x< sizeof(tor2_pci_ids) / sizeof(tor2_pci_ids[0]); x++)
if (((tor2_pci_ids[x].vendor == PCI_ANY_ID) ||
(tor2_pci_ids[x].vendor == vendorid)) &&
((tor2_pci_ids[x].device == PCI_ANY_ID) ||
(tor2_pci_ids[x].device == deviceid))) {
*variant = (char *)tor2_pci_ids[x].driver_data;
return 1;
}
if (variant)
*variant = NULL;
return 0;
}
#endif /* __KERNEL__ */
#endif /* NEED_PCI_IDS */
/*
* PLX PCI9030 PCI Configuration Registers
*
* This is not an all-inclusive list, just some interesting ones
* that we need and that are not standard.
*
*/
#define PLX_PCI_VPD_ADDR 0x4e /* Set address here */
#define PLX_PCI_VPD_DATA 0x50 /* Read/Write data here */
#define PLX_LOC_WP_BOUNDARY 0x4e /* Bits 6-0 here */
#define PLX_LOC_GPIOC 0x54 /* GPIO control register */
/* The 4 GPIO data bits we are interested in */
#define LOC_GPIOC_GPIO4 0x4000 /* GPIO4 data */
#define LOC_GPIOC_GPIO5 0x20000 /* GPIO5 data */
#define LOC_GPIOC_GPIO6 0x100000 /* GPIO6 data */
#define LOC_GPIOC_GPIO7 0x800000 /* GPIO7 data */
/* define the initialization of the GPIOC register */
#define LOC_GPIOC_INIT_VALUE 0x2036000 /* GPIO 4&5 in write and
both high and GPIO 8 in write low */
/* The defines by what they actually do */
#define GPIO_WRITE LOC_GPIOC_GPIO4
#define GPIO_PROGRAM LOC_GPIOC_GPIO5
#define GPIO_INIT LOC_GPIOC_GPIO6
#define GPIO_DONE LOC_GPIOC_GPIO7
#endif /* _TOR2_HW_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1560,7 +1560,7 @@ gpakReadDSPMemoryStat_t gpakReadDSPMemoryMap(
if (DspStatus != 0)
return (RmmFailure);
for (i = 0; i < MemoryLength_Word16; i++)
for (i = 0; i < MemoryLength_Word16; i++)
pDest[i] = (short int) MsgBuffer[2 + i];
@@ -1636,6 +1636,8 @@ gpakWriteSysParmsStatus_t gpakWriteSystemParms(
DSP_WORD MsgBuffer[MSG_BUFFER_SIZE]; /* message buffer */
DSP_WORD DspStatus; /* DSP's reply status */
memset(MsgBuffer, 0, sizeof(MsgBuffer));
/* Make sure the DSP Id is valid. */
if (DspId >= MAX_DSP_CORES)
return (WspInvalidDsp);

View File

@@ -1000,6 +1000,7 @@ __vb_rx_demand_poll(struct voicebus *vb)
__vb_setctl(vb, 0x0010, 0x00000000);
}
#ifndef CONFIG_VOICEBUS_TIMER
static void
__vb_enable_interrupts(struct voicebus *vb)
{
@@ -1008,6 +1009,7 @@ __vb_enable_interrupts(struct voicebus *vb)
else
__vb_setctl(vb, IER_CSR7, DEFAULT_NORMAL_INTERRUPTS);
}
#endif
static void
__vb_disable_interrupts(struct voicebus *vb)
@@ -1033,8 +1035,7 @@ static void start_packet_processing(struct voicebus *vb)
clear_bit(VOICEBUS_STOP, &vb->flags);
clear_bit(VOICEBUS_STOPPED, &vb->flags);
#if defined(CONFIG_VOICEBUS_TIMER)
vb->timer.expires = jiffies + HZ/1000;
add_timer(&vb->timer);
mod_timer(&vb->timer, jiffies + HZ/1000);
#else
/* Clear the interrupt status register. */
__vb_setctl(vb, SR_CSR5, 0xffffffff);
@@ -1746,18 +1747,17 @@ vb_isr(int irq, void *dev_id)
* the timer.
*/
static void
vb_timer(unsigned long data)
vb_timer(TIMER_DATA_TYPE timer)
{
unsigned long start = jiffies;
struct voicebus *vb = (struct voicebus *)data;
struct voicebus *vb = from_timer(vb, timer, timer);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
vb_isr(0, vb, 0);
#else
vb_isr(0, vb);
#endif
if (!test_bit(VOICEBUS_STOPPED, &vb->flags)) {
vb->timer.expires = start + HZ/1000;
add_timer(&vb->timer);
mod_timer(&vb->timer, start + HZ/1000);
}
}
#endif
@@ -1800,9 +1800,7 @@ __voicebus_init(struct voicebus *vb, const char *board_name,
INIT_LIST_HEAD(&vb->free_rx);
#if defined(CONFIG_VOICEBUS_TIMER)
init_timer(&vb->timer);
vb->timer.function = vb_timer;
vb->timer.data = (unsigned long)vb;
timer_setup(&vb->timer, vb_timer, 0);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)

View File

@@ -50,6 +50,10 @@
#include <dahdi/kernel.h>
#include <dahdi/wctdm_user.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/signal.h>
#endif /* 4.11.0 */
#include "proslic.h"
#include <dahdi/kernel.h>

File diff suppressed because it is too large Load Diff

View File

@@ -248,8 +248,8 @@
#define V_ROUT_TX_STIO2 (0x3 << 6) /* output data to STIO2 */
#define V_ROUT_RX_DIS (0x0 << 6) /* disabled, input data ignored */
#define V_ROUT_RX_LOOP (0x1 << 6) /* internally looped, input data ignored */
#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data comes from STIO1 */
#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data comes from STIO2 */
#define V_ROUT_RX_STIO2 (0x2 << 6) /* channel data from STIO2 */
#define V_ROUT_RX_STIO1 (0x3 << 6) /* channel data from STIO1 */
#define V_CH_SNUM_SHIFT (1)
#define V_CH_SNUM_MASK (31 << 1)
@@ -367,6 +367,16 @@
#define V_B2_RX_EN (1 << 1) /* 1=enable B2 RX */
#define V_ST_TRI (1 << 6) /* 1=tristate S/T output buffer */
/* User Flash Manager */
#define UFM_PROGRAM (1<<0)
#define UFM_ERASE (1<<1)
#define UFM_DRSHIFT (1<<2)
#define UFM_DRDIN (1<<3)
#define UFM_DRCLK (1<<4)
#define UFM_ARSHIFT (1<<5)
#define UFM_ARDIN (1<<6)
#define UFM_ARCLK (1<<7)
#define NUM_REGS 0xff
#define NUM_PCI 12
@@ -385,7 +395,8 @@
struct b4xxp_span {
struct b4xxp *parent;
int port; /* which S/T port this span belongs to */
int port; /* virtual port */
int phy_port; /* physical port */
unsigned char writechunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
unsigned char readchunk[WCB4XXP_CHANNELS_PER_SPAN * DAHDI_CHUNKSIZE];
@@ -426,7 +437,9 @@ enum cards_ids { /* Cards ==> Brand & Model */
BN4S0, /* Beronet BN4S0 */
BN8S0, /* BeroNet BN8S0 */
BSWYX_SX2, /* Swyx 4xS0 SX2 QuadBri */
QUADBRI_EVAL /* HFC-4S CCD Eval. Board */
QUADBRI_EVAL, /* HFC-4S CCD Eval. Board */
B430P, /* Digium B430P */
B230P /* Digium B230P */
};
/* This structure exists one per card */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/kmod.h>
#include <linux/sched.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
@@ -40,7 +41,12 @@
#include <stdbool.h>
#include "dahdi/kernel.h"
#include <dahdi/kernel.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/signal.h>
#endif /* 4.11.0 */
#include <linux/io.h>
@@ -3695,9 +3701,9 @@ wctc4xxp_send_commands(struct wcdte *wc, struct list_head *to_send)
}
static void
wctc4xxp_watchdog(unsigned long data)
wctc4xxp_watchdog(TIMER_DATA_TYPE timer)
{
struct wcdte *wc = (struct wcdte *)data;
struct wcdte *wc = from_timer(wc, timer, watchdog);
struct tcb *cmd, *temp;
LIST_HEAD(cmds_to_retry);
const int MAX_RETRIES = 5;
@@ -4084,13 +4090,7 @@ wctc4xxp_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
goto error_exit_swinit;
}
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
wc->watchdog.function = wctc4xxp_watchdog;
wc->watchdog.data = (unsigned long)wc;
init_timer(&wc->watchdog);
# else
setup_timer(&wc->watchdog, wctc4xxp_watchdog, (unsigned long)wc);
# endif
timer_setup(&wc->watchdog, wctc4xxp_watchdog, 0);
/* ------------------------------------------------------------------
* Load the firmware and start the DTE.

File diff suppressed because it is too large Load Diff

View File

@@ -44,6 +44,7 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
@@ -72,6 +73,10 @@ Tx Gain - W/Pre-Emphasis: -23.99 to 0.00 db
#include <dahdi/kernel.h>
#include <dahdi/wctdm_user.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/signal.h>
#endif /* 4.11.0 */
#include "proslic.h"
#include "wctdm24xxp.h"
@@ -6047,11 +6052,7 @@ static void __devexit wctdm_remove_one(struct pci_dev *pdev)
static DEFINE_PCI_DEVICE_TABLE(wctdm_pci_tbl) = {
{ 0xd161, 0x2400, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm2400 },
{ 0xd161, 0x0800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm800 },
{ 0xd161, 0x8002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex800 },
{ 0xd161, 0x8003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex2400 },
{ 0xd161, 0x8005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wctdm410 },
{ 0xd161, 0x8006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcaex410 },
{ 0xd161, 0x8007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wcha80000 },
{ 0xd161, 0x8008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (unsigned long) &wchb80000 },
{ 0 }

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +0,0 @@
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE12XP) += wcte12xp.o
EXTRA_CFLAGS += -I$(src)/.. -Wno-undef
wcte12xp-objs := base.o

File diff suppressed because it is too large Load Diff

View File

@@ -1,167 +0,0 @@
/*
* Digium, Inc. Wildcard TE12xP T1/E1 card Driver
*
* Written by Michael Spiceland <mspiceland@digium.com>
*
* Adapted from the wctdm24xxp and wcte11xp drivers originally
* written by Mark Spencer <markster@digium.com>
* Matthew Fredrickson <creslin@digium.com>
* William Meadows <wmeadows@digium.com>
*
* Copyright (C) 2007-2010, Digium, Inc.
*
* All rights reserved.
*
*/
/*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2 as published by the
* Free Software Foundation. See the LICENSE file included with
* this program for more details.
*/
#ifndef _WCTE12XP_H
#define _WCTE12XP_H
/* Comment to disable VPM support */
#define VPM_SUPPORT 1
#define WC_MAX_IFACES 8
#ifdef VPM_SUPPORT
#define MAX_TDM_CHAN 31
#endif
#define SDI_CLK (0x00010000)
#define SDI_DOUT (0x00020000)
#define SDI_DREAD (0x00040000)
#define SDI_DIN (0x00080000)
#define EFRAME_SIZE 108
#define ERING_SIZE 16 /* Maximum ring size */
#define EFRAME_GAP 20
#define SFRAME_SIZE ((EFRAME_SIZE * DAHDI_CHUNKSIZE) + (EFRAME_GAP * (DAHDI_CHUNKSIZE - 1)))
#define PCI_WINDOW_SIZE ((2 * 2 * 2 * SFRAME_SIZE) + (2 * ERING_SIZE * 4))
#define MAX_COMMANDS 16
#define NUM_EC 4
#define __CMD_PINS (1 << 18) /* CPLD pin read */
#define __CMD_LEDS (1 << 19) /* LED Operation */
#define __CMD_RD (1 << 20) /* Read Operation */
#define __CMD_WR (1 << 21) /* Write Operation */
#define __LED_ORANGE (1<<3)
#define __LED_GREEN (1<<2)
#define __LED_RED (1<<1)
#define SET_LED_ORANGE(a) (a | __LED_ORANGE)
#define SET_LED_RED(a) ((a | __LED_RED) & ~__LED_GREEN)
#define SET_LED_GREEN(a) ((a | __LED_GREEN) & ~__LED_RED)
#define UNSET_LED_ORANGE(a) (a & ~__LED_ORANGE)
#define UNSET_LED_REDGREEN(a) (a | __LED_RED | __LED_GREEN)
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
//TODO: make a separate macro
enum linemode {
T1 = 1,
E1,
J1,
};
struct command {
struct list_head node;
struct completion complete;
u8 data;
u8 ident;
u8 cs_slot;
u16 address;
u32 flags;
};
struct vpm150m;
struct t1 {
spinlock_t reglock;
unsigned char txident;
unsigned char rxident;
unsigned char statreg; /* bit 0 = vpmadt032 int */
struct {
unsigned int nmf:1;
unsigned int sendingyellow:1;
} flags;
unsigned char txsigs[16]; /* Copy of tx sig registers */
int alarmcount; /* How much red alarm we've seen */
int losalarmcount;
int aisalarmcount;
int yelalarmcount;
const char *variety;
char name[80];
unsigned long blinktimer;
int loopupcnt;
int loopdowncnt;
#define INITIALIZED 1
#define SHUTDOWN 2
#define READY 3
#define IOERROR 4
unsigned long bit_flags;
unsigned long alarmtimer;
unsigned char ledstate;
unsigned char vpm_check_count;
struct dahdi_device *ddev;
struct dahdi_span span; /* Span */
struct dahdi_chan *chans[32]; /* Channels */
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */
#ifdef CONFIG_VOICEBUS_ECREFERENCE
struct dahdi_fifo *ec_reference[32];
#else
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
#endif
unsigned long ctlreg;
struct voicebus vb;
atomic_t txints;
struct vpmadt032 *vpmadt032;
struct vpmoct *vpmoct;
unsigned long vpm_check;
struct work_struct vpm_check_work;
/* protected by t1.reglock */
struct list_head pending_cmds;
struct list_head active_cmds;
struct timer_list timer;
struct work_struct timer_work;
struct workqueue_struct *wq;
unsigned int not_ready; /* 0 when entire card is ready to go */
};
#define t1_info(t1, format, arg...) \
dev_info(&t1->vb.pdev->dev , format , ## arg)
#define t1_notice(t1, format, arg...) \
dev_notice(&t1->vb.pdev->dev , format , ## arg)
/* Maintenance Mode Registers */
#define LIM0 0x36
#define LIM0_LL (1<<1)
#define LIM1 0x37
#define LIM1_RL (1<<1)
#define LIM1_JATT (1<<2)
/* Clear Channel Registers */
#define CCB1 0x2f
#define CCB2 0x30
#define CCB3 0x31
#endif

View File

@@ -1805,7 +1805,8 @@ static int t13x_software_init(struct t13x *wc, enum linemode type)
t13x_serial_setup(wc);
set_bit(DAHDI_FLAGBIT_RBS, &wc->span.flags);
for (x = 0; x < wc->span.channels; x++) {
sprintf(wc->chans[x]->name, "%s/%d", wc->span.name, x + 1);
snprintf(wc->chans[x]->name, sizeof(wc->chans[x]->name),
"%s/%d", wc->span.name, x + 1);
t13x_chan_set_sigcap(&wc->span, x);
wc->chans[x]->pvt = wc;
wc->chans[x]->chanpos = x + 1;
@@ -2381,9 +2382,9 @@ static void te13x_handle_interrupt(struct wcxb *xb, u32 pending)
}
}
static void te13xp_timer(unsigned long data)
static void te13xp_timer(TIMER_DATA_TYPE timer)
{
struct t13x *wc = (struct t13x *)data;
struct t13x *wc = from_timer(wc, timer, timer);
if (unlikely(!test_bit(INITIALIZED, &wc->bit_flags)))
return;
@@ -2582,7 +2583,7 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
wc->ledstate = -1;
spin_lock_init(&wc->reglock);
mutex_init(&wc->lock);
setup_timer(&wc->timer, te13xp_timer, (unsigned long)wc);
timer_setup(&wc->timer, te13xp_timer, 0);
# if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&wc->timer_work, timer_work_func, wc);

View File

@@ -46,6 +46,10 @@
#include <stdbool.h>
#include <dahdi/kernel.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
#include <linux/sched/signal.h>
#endif /* 4.11.0 */
#include "wct4xxp/wct4xxp.h" /* For certain definitions */
#include "wcxb.h"
#include "wcxb_spi.h"
@@ -1709,7 +1713,7 @@ static void t43x_configure_e1(struct t43x *wc, int span_idx, int lineconfig)
__t43x_framer_set(wc, fidx, 0x21, 0x1c|cas);
/* Generate pulse mask for E1 */
__t43x_framer_set(wc, fidx, 0x26, 0x74); /* XPM0 */
__t43x_framer_set(wc, fidx, 0x26, 0xb5); /* XPM0 */
__t43x_framer_set(wc, fidx, 0x27, 0x02); /* XPM1 */
__t43x_framer_set(wc, fidx, 0x28, 0x00); /* XPM2 */
@@ -2532,7 +2536,8 @@ t43x_init_one_span(struct t43x *wc, struct t43x_span *ts, enum linemode type)
set_bit(DAHDI_FLAGBIT_RBS, &ts->span.flags);
for (x = 0; x < ts->span.channels; x++) {
sprintf(ts->chans[x]->name, "%s/%d", ts->span.name, x + 1);
snprintf(ts->chans[x]->name, sizeof(ts->chans[x]->name),
"%s/%d", ts->span.name, x + 1);
t43x_chan_set_sigcap(&ts->span, x);
ts->chans[x]->pvt = wc;
ts->chans[x]->chanpos = x + 1;
@@ -3199,9 +3204,9 @@ static void t43x_handle_interrupt(struct wcxb *xb, u32 pending)
wc->intr_span = 0;
}
static void t43x_timer(unsigned long data)
static void t43x_timer(TIMER_DATA_TYPE timer)
{
struct t43x *wc = (struct t43x *)data;
struct t43x *wc = from_timer(wc, timer, timer);
if (!is_initialized(wc))
return;
@@ -3427,7 +3432,7 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
goto fail_exit;
mutex_init(&wc->lock);
setup_timer(&wc->timer, t43x_timer, (unsigned long)wc);
timer_setup(&wc->timer, t43x_timer, 0);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
INIT_WORK(&wc->timer_work, timer_work_func, wc);

View File

@@ -36,20 +36,9 @@ EXTRA_CFLAGS += -DDEBUG_SYNC_PARPORT
obj-m += parport_debug.o
endif
# Handle versioning
XPP_VERSION_STR ?= $(shell if [ -r $(obj)/.version ]; then echo "\"`cat $(obj)/.version`\""; else echo '"Unknown"'; fi)
# Just in case it was left from an older version:
clean-files += xpp_version.h
$(obj)/card_fxs.o $(obj)/card_fxo.o $(obj)/card_bri.o $(obj)/card_pri.o $(obj)/xpp_usb.o $(obj)/xpp.o: $(obj)/xpp_version.h
$(obj)/xpp_version.h: FORCE
@echo ' VERSION $@'
$(Q)echo '#define XPP_VERSION $(XPP_VERSION_STR)' > $@.tmp
$(Q)if cmp -s $@.tmp $@ ; then echo; else \
mv $@.tmp $@ ; \
fi
$(Q)rm -f $@.tmp
# Validations:
# - Syntactic verification of perl scripts
# - Handle country table validation for init_card_2_*
@@ -69,7 +58,7 @@ FXO_MODES = $(src)/../fxo_modes.h
FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes
hostprogs-y := print_fxo_modes
always := $(xpp_verified) xpp_version.h
always := $(xpp_verified)
print_fxo_modes-objs := print_fxo_modes.o
HOSTCFLAGS_print_fxo_modes.o += -include $(FXO_MODES)

View File

@@ -162,7 +162,6 @@ static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
static int bri_startup(struct file *file, struct dahdi_span *span);
static int bri_shutdown(struct dahdi_span *span);
#define PROC_REGISTER_FNAME "slics"
#define PROC_BRI_INFO_FNAME "bri_info"
enum led_state {
@@ -468,8 +467,8 @@ static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
int ret = 0;
src = REG_XDATA(regcmd);
len = regcmd->bytes;
eoframe = regcmd->eoframe;
len = regcmd->h.bytes;
eoframe = regcmd->h.eoframe;
if (len <= 0)
return 0;
if (!SPAN_REGISTERED(xpd)) /* Nowhere to copy data */
@@ -565,12 +564,12 @@ static void fill_multibyte(xpd_t *xpd, xpacket_t *pack,
char *p;
XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
XPACKET_LEN(pack) = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
XPACKET_LEN(pack) = XFRAME_CMD_LEN(REG);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->bytes = len;
reg_cmd->is_multibyte = 1;
reg_cmd->portnum = xpd->addr.subunit;
reg_cmd->eoframe = eoframe;
reg_cmd->h.bytes = len;
reg_cmd->h.is_multibyte = 1;
reg_cmd->h.portnum = xpd->addr.subunit;
reg_cmd->h.eoframe = eoframe;
p = REG_XDATA(reg_cmd);
memcpy(p, buf, len);
if (debug)
@@ -611,7 +610,7 @@ static int tx_dchan(xpd_t *xpd)
return -ENOMEM;
}
for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
int packet_len = RPACKET_SIZE(GLOBAL, REGISTER_REQUEST);
int packet_len = XFRAME_CMD_LEN(REG);
char buf[MULTIBYTE_MAX_LEN];
int len = MULTIBYTE_MAX_LEN;
@@ -687,20 +686,29 @@ static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
}
static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels = min(3, CHANNELS_PERXPD);
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
if ((unit_descriptor->ports_per_chip < 1) ||
(unit_descriptor->ports_per_chip > 4)) {
XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
unit_descriptor->ports_per_chip);
return NULL;
}
if ((unit_descriptor->numchips) < 1 ||
(unit_descriptor->numchips > 2)) {
XBUS_ERR(xbus, "Bad numchips=%d\n",
unit_descriptor->numchips);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct BRI_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
@@ -977,7 +985,8 @@ static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
0, /* data_low */
0, /* do_datah */
0, /* data_high */
0 /* should_reply */
0, /* should_reply */
0 /* do_expander */
);
if (IS_NT(xpd) && nt_keepalive
@@ -1426,7 +1435,8 @@ static int write_state_register(xpd_t *xpd, __u8 value)
value, /* data_low */
0, /* do_datah */
0, /* data_high */
0 /* should_reply */
0, /* should_reply */
0 /* do_expander */
);
return ret;
}
@@ -1538,7 +1548,7 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
/* Map UNIT + PORTNUM to XPD */
orig_xpd = xpd;
addr.unit = orig_xpd->addr.unit;
addr.subunit = info->portnum;
addr.subunit = info->h.portnum;
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
if (!xpd) {
static int rate_limit;
@@ -1563,9 +1573,9 @@ static int BRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
XPD_DBG(REGS, xpd, "Got SU_RD_STA=%02X\n",
REG_FIELD(info, data_low));
}
if (info->is_multibyte) {
if (info->h.is_multibyte) {
XPD_DBG(REGS, xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
info->bytes, info->eoframe);
info->h.bytes, info->h.eoframe);
ret = rx_dchan(xpd, info);
if (ret < 0) {
priv->dchan_rx_drops++;
@@ -1745,9 +1755,9 @@ static int bri_xpd_probe(struct device *dev)
xpd = dev_to_xpd(dev);
/* Is it our device? */
if (xpd->type != XPD_TYPE_BRI) {
if (xpd->xpd_type != XPD_TYPE_BRI) {
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
xpd->type);
xpd->xpd_type);
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
@@ -1764,7 +1774,7 @@ static int bri_xpd_remove(struct device *dev)
}
static struct xpd_driver bri_driver = {
.type = XPD_TYPE_BRI,
.xpd_type = XPD_TYPE_BRI,
.driver = {
.name = "bri",
.owner = THIS_MODULE,
@@ -1778,7 +1788,6 @@ static int __init card_bri_startup(void)
if ((ret = xpd_driver_register(&bri_driver.driver)) < 0)
return ret;
INFO("revision %s\n", XPP_VERSION);
xproto_register(&PROTO_TABLE(BRI));
return 0;
}
@@ -1793,7 +1802,6 @@ static void __exit card_bri_cleanup(void)
MODULE_DESCRIPTION("XPP BRI Card Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
MODULE_ALIAS_XPD(XPD_TYPE_BRI);
module_init(card_bri_startup);

View File

@@ -54,20 +54,21 @@ static xproto_table_t PROTO_TABLE(ECHO);
/*---------------- ECHO: Methods -------------------------------------------*/
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels = 0;
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
if (unit_descriptor->ports_per_chip != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", unit_descriptor->ports_per_chip);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct ECHO_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct ECHO_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
xpd->type_name = "ECHO";
@@ -80,7 +81,7 @@ static int ECHO_card_init(xbus_t *xbus, xpd_t *xpd)
BUG_ON(!xpd);
XPD_DBG(GENERAL, xpd, "\n");
xpd->type = XPD_TYPE_ECHO;
xpd->xpd_type = XPD_TYPE_ECHO;
XPD_DBG(DEVICES, xpd, "%s\n", xpd->type_name);
ret = CALL_EC_METHOD(ec_update, xbus, xbus);
return ret;
@@ -112,7 +113,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
/* Map UNIT + PORTNUM to XPD */
orig_xpd = xpd;
addr.unit = orig_xpd->addr.unit;
addr.subunit = info->portnum;
addr.subunit = info->h.portnum;
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
if (!xpd) {
static int rate_limit;
@@ -307,9 +308,9 @@ static int echo_xpd_probe(struct device *dev)
ec_xpd = dev_to_xpd(dev);
/* Is it our device? */
if (ec_xpd->type != XPD_TYPE_ECHO) {
if (ec_xpd->xpd_type != XPD_TYPE_ECHO) {
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
ec_xpd->type);
ec_xpd->xpd_type);
return -EINVAL;
}
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
@@ -326,7 +327,7 @@ static int echo_xpd_remove(struct device *dev)
}
static struct xpd_driver echo_driver = {
.type = XPD_TYPE_ECHO,
.xpd_type = XPD_TYPE_ECHO,
.driver = {
.name = "echo",
.owner = THIS_MODULE,
@@ -341,7 +342,6 @@ static int __init card_echo_startup(void)
ret = xpd_driver_register(&echo_driver.driver);
if (ret < 0)
return ret;
INFO("revision %s\n", XPP_VERSION);
INFO("FEATURE: WITH Octasic echo canceller\n");
xproto_register(&PROTO_TABLE(ECHO));
return 0;
@@ -357,7 +357,6 @@ static void __exit card_echo_cleanup(void)
MODULE_DESCRIPTION("XPP ECHO Card Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
MODULE_ALIAS_XPD(XPD_TYPE_ECHO);
module_init(card_echo_startup);

View File

@@ -100,7 +100,7 @@ enum fxo_leds {
#define DAA_READ 0
#define DAA_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL) \
xpp_register_request((xbus), (xpd), (port), \
(writing), (reg), 0, 0, (dL), 0, 0, 0)
(writing), (reg), 0, 0, (dL), 0, 0, 0, 0)
/*---------------- FXO Protocol Commands ----------------------------------*/
@@ -115,7 +115,6 @@ static const struct file_operations proc_xpd_metering_ops;
static void dahdi_report_battery(xpd_t *xpd, lineno_t chan);
static void report_polarity_reversal(xpd_t *xpd, xportno_t portno, char *msg);
#define PROC_REGISTER_FNAME "slics"
#define PROC_FXO_INFO_FNAME "fxo_info"
#ifdef WITH_METERING
#define PROC_METERING_FNAME "metering_read"
@@ -488,11 +487,13 @@ static int fxo_proc_create(xbus_t *xbus, xpd_t *xpd)
}
static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels;
int subunit_ports;
if (to_phone) {
XBUS_NOTICE(xbus,
@@ -501,13 +502,14 @@ static xpd_t *FXO_card_new(xbus_t *xbus, int unit, int subunit,
unit, subunit);
return NULL;
}
if (subtype == 2)
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
if (unit_descriptor->subtype == 2)
channels = min(2, subunit_ports);
else
channels = min(8, subunit_ports);
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct FXO_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct FXO_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
PHONEDEV(xpd).direction = TO_PSTN;
@@ -618,7 +620,6 @@ static int FXO_card_dahdi_postregistration(xpd_t *xpd, bool on)
BUG_ON(!priv);
XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "ON" : "OFF");
for_each_line(xpd, i) {
dahdi_report_battery(xpd, i);
MARK_OFF(priv, i, LED_GREEN);
msleep(2);
MARK_OFF(priv, i, LED_RED);
@@ -627,6 +628,23 @@ static int FXO_card_dahdi_postregistration(xpd_t *xpd, bool on)
return 0;
}
static int FXO_span_assigned(xpd_t *xpd)
{
xbus_t *xbus;
struct FXO_priv_data *priv;
int i;
BUG_ON(!xpd);
xbus = xpd->xbus;
BUG_ON(!xbus);
priv = xpd->priv;
BUG_ON(!priv);
XPD_DBG(GENERAL, xpd, "\n");
for_each_line(xpd, i)
dahdi_report_battery(xpd, i);
return 0;
}
static int FXO_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
{
struct FXO_priv_data *priv;
@@ -1247,7 +1265,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
priv = xpd->priv;
BUG_ON(!priv);
portno = info->portnum;
portno = info->h.portnum;
switch (REG_FIELD(info, regnum)) {
case REG_INTERRUPT_SRC:
got_chip_interrupt(xpd, REG_FIELD(info, data_low), portno);
@@ -1265,7 +1283,7 @@ static int FXO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
#endif
}
LINE_DBG(REGS, xpd, portno, "%c reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
((info->bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
((info->h.bytes == 3) ? 'I' : 'D'), REG_FIELD(info, regnum),
REG_FIELD(info, data_low), REG_FIELD(info, data_high));
/* Update /proc info only if reply relate to the last slic read request */
if (REG_FIELD(&xpd->requested_reply, regnum) ==
@@ -1312,6 +1330,7 @@ static const struct phoneops fxo_phoneops = {
.card_ioctl = FXO_card_ioctl,
.card_open = FXO_card_open,
.card_state = FXO_card_state,
.span_assigned = FXO_span_assigned,
};
static xproto_table_t PROTO_TABLE(FXO) = {
@@ -1553,9 +1572,9 @@ static int fxo_xpd_probe(struct device *dev)
xpd = dev_to_xpd(dev);
/* Is it our device? */
if (xpd->type != XPD_TYPE_FXO) {
if (xpd->xpd_type != XPD_TYPE_FXO) {
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
xpd->type);
xpd->xpd_type);
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
@@ -1581,7 +1600,7 @@ static int fxo_xpd_remove(struct device *dev)
}
static struct xpd_driver fxo_driver = {
.type = XPD_TYPE_FXO,
.xpd_type = XPD_TYPE_FXO,
.driver = {
.name = "fxo",
.owner = THIS_MODULE,
@@ -1600,7 +1619,6 @@ static int __init card_fxo_startup(void)
}
if ((ret = xpd_driver_register(&fxo_driver.driver)) < 0)
return ret;
INFO("revision %s\n", XPP_VERSION);
#ifdef WITH_METERING
INFO("FEATURE: WITH METERING Detection\n");
#else
@@ -1619,7 +1637,6 @@ static void __exit card_fxo_cleanup(void)
MODULE_DESCRIPTION("XPP FXO Card Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
MODULE_ALIAS_XPD(XPD_TYPE_FXO);
module_init(card_fxo_startup);

View File

@@ -41,6 +41,7 @@ static DEF_PARM_BOOL(dtmf_detection, 1, 0644, "Do DTMF detection in hardware");
#ifdef POLL_DIGITAL_INPUTS
static DEF_PARM(uint, poll_digital_inputs, 1000, 0644, "Poll Digital Inputs");
#endif
static DEF_PARM(uint, poll_chan_linefeed, 30000, 0644, "Poll Channel Linefeed");
static DEF_PARM_BOOL(vmwi_ioctl, 1, 0644,
"Asterisk support VMWI notification via ioctl");
@@ -77,15 +78,21 @@ enum fxs_leds {
#define SLIC_READ 0
#define SLIC_DIRECT_REQUEST(xbus, xpd, port, writing, reg, dL) \
xpp_register_request((xbus), (xpd), (port), \
(writing), (reg), 0, 0, (dL), 0, 0, 0)
(writing), (reg), 0, 0, (dL), 0, 0, 0, 0)
#define SLIC_INDIRECT_REQUEST(xbus, xpd, port, writing, reg, dL, dH) \
xpp_register_request((xbus), (xpd), (port), \
(writing), 0x1E, 1, (reg), (dL), 1, (dH), 0)
(writing), 0x1E, 1, (reg), (dL), 1, (dH), 0, 0)
#define EXP_REQUEST(xbus, xpd, writing, reg, dL, dH) \
xpp_register_request((xbus), (xpd), 0, \
(writing), (reg), 1, 0, (dL), 1, (dH), 0, 1)
#define RAM_REQUEST(xbus, xpd, port, writing, addr, data) \
xpp_ram_request((xbus), (xpd), (port), \
(writing), (__u8)(addr), (__u8)((addr) >> 8), (__u8)(data), (__u8)((data) >> 8), (__u8)((data) >> 16), (__u8)((data) >> 24), 0)
#define VALID_PORT(port) \
(((port) >= 0 && (port) <= 7) || (port) == PORT_BROADCAST)
#define REG_DIGITAL_IOCTRL 0x06 /* LED and RELAY control */
#define REG_TYPE1_DIGITAL_IOCTRL 0x06 /* LED and RELAY control */
/* Values of SLIC linefeed control register (0x40) */
enum fxs_state {
@@ -99,22 +106,54 @@ enum fxs_state {
FXS_LINE_RING_OPEN = 0x07 /* RING open */
};
enum neon_state {
END_NEON = 0,
INIT_NEON = 1,
};
#define FXS_LINE_POL_ACTIVE \
((reversepolarity) ? FXS_LINE_REV_ACTIVE : FXS_LINE_ACTIVE)
#define FXS_LINE_POL_OHTRANS \
((reversepolarity) ? FXS_LINE_REV_OHTRANS : FXS_LINE_OHTRANS)
/* FXS type 1 registers */
#define REG_TYPE1_RINGCON 0x22 /* 34 - Ringing Oscillator Control */
/*
* DTMF detection
*/
#define REG_DTMF_DECODE 0x18 /* 24 - DTMF Decode Status */
#define REG_BATTERY 0x42 /* 66 - Battery Feed Control */
#define REG_BATTERY_BATSL BIT(1) /* Battery Feed Select */
#define REG_TYPE1_DTMF_DECODE 0x18 /* 24 - DTMF Decode Status */
#define REG_TYPE1_BATTERY 0x42 /* 66 - Battery Feed Control */
#define REG_TYPE1_BATTERY_BATSL BIT(1) /* Battery Feed Select */
/* 68 - Loop Closure/Ring Trip Detect Status */
#define REG_LOOPCLOSURE 0x44
#define REG_LOOPCLOSURE_ZERO 0xF8 /* Loop Closure zero bits. */
#define REG_LOOPCLOSURE_LCR BIT(0) /* Loop Closure Detect Indicator. */
#define REG_TYPE1_LOOPCLOSURE 0x44
#define REG_TYPE1_LOOPCLOSURE_ZERO 0xF8 /* Loop Closure zero bits. */
#define REG_TYPE1_LOOPCLOSURE_LCR BIT(0) /* Loop Closure Detect Indicator. */
/* FXS type 6 registers */
#define REG_TYPE6_RINGCON 0x26 /* 38 - Ringing Oscillator Control */
/* 34 - Loop Closure/Ring Trip Detect Status */
#define REG_TYPE6_LCRRTP 0x22
#define REG_TYPE6_LCRRTP_ZERO 0xF0 /* Loop Closure zero bits. */
#define REG_TYPE6_LCRRTP_LCR BIT(1) /* Loop Closure Detect Indicator. */
#define REG_TYPE6_TONEN 0x3E /* 62 - Hardware DTMF detection */
#define REG_TYPE6_TONEN_DTMF_DIS BIT(2) /* DTMF Disable */
#define REG_TYPE6_LINEFEED 0x1E /* 30 - Linefeed */
#define REG_TYPE6_TONDTMF 0x3C /* 60 - DTMF Decode Status */
#define REG_TYPE6_EXP_GPIOA 0x12 /* I/O Expander GPIOA */
#define REG_TYPE6_EXP_GPIOB 0x13 /* I/O Expander GPIOB */
#define REG_TYPE6_ENHANCE 0x2F /* 47 - Enhance */
#define REG_TYPE6_USERSTAT 0x42 /* 66 - Userstat */
#define REG_TYPE6_DIAG1 0x47 /* 71 - Diag1 */
#define RAM_TYPE6_SLOPE_VLIM 634
#define SLOPE_VLIM_DFLT 0x1E655196L
#define SLOPE_VLIM_MWI 0x8000000L
#define RAM_TYPE6_VBATH_EXPECT 767
#define VBATH_EXPECT_DFLT 0x2B10A20L
#define VBATH_EXPECT_MWI 0x6147AB2L
/*---------------- FXS Protocol Commands ----------------------------------*/
@@ -128,7 +167,6 @@ static const struct file_operations proc_xpd_metering_ops;
#endif
static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos);
#define PROC_REGISTER_FNAME "slics"
#define PROC_FXS_INFO_FNAME "fxs_info"
#ifdef WITH_METERING
#define PROC_METERING_FNAME "metering_gen"
@@ -148,14 +186,17 @@ struct FXS_priv_data {
xpp_line_t want_dtmf_mute; /* what dahdi want */
xpp_line_t prev_key_down; /* DTMF down sets the bit */
xpp_line_t neon_blinking;
xpp_line_t neonstate;
xpp_line_t vbat_h; /* High voltage */
struct timeval prev_key_time[CHANNELS_PERXPD];
int led_counter[NUM_LEDS][CHANNELS_PERXPD];
int overheat_reset_counter[CHANNELS_PERXPD];
int ohttimer[CHANNELS_PERXPD];
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
/* IDLE changing hook state */
enum fxs_state idletxhookstate[CHANNELS_PERXPD];
enum fxs_state lasttxhook[CHANNELS_PERXPD];
enum fxs_state polledhook[CHANNELS_PERXPD];
struct dahdi_vmwi_info vmwisetting[CHANNELS_PERXPD];
};
@@ -181,6 +222,9 @@ struct FXS_priv_data {
#define LED_BLINK_RING (1000/8) /* in ticks */
/*---------------- FXS: Static functions ----------------------------------*/
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
unsigned int msg_waiting);
static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
{
struct FXS_priv_data *priv;
@@ -189,6 +233,10 @@ static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
BUG_ON(!xbus);
BUG_ON(!xpd);
if (XPD_HW(xpd).type == 6) {
LINE_DBG(SIGNAL, xpd, chan, "is ignored in Si32260\n");
return 0;
}
priv = xpd->priv;
p = (unsigned long *)&priv->vbat_h;
if (on)
@@ -201,8 +249,8 @@ static int do_chan_power(xbus_t *xbus, xpd_t *xpd, lineno_t chan, bool on)
return 0;
}
LINE_DBG(SIGNAL, xpd, chan, "%s\n", (on) ? "up" : "down");
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_BATTERY,
(on) ? REG_BATTERY_BATSL : 0x00);
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE1_BATTERY,
(on) ? (int)REG_TYPE1_BATTERY_BATSL : 0x00);
}
static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan,
@@ -223,7 +271,20 @@ static int linefeed_control(xbus_t *xbus, xpd_t *xpd, lineno_t chan,
do_chan_power(xbus, xpd, chan, want_vbat_h);
LINE_DBG(SIGNAL, xpd, chan, "value=0x%02X\n", value);
priv->lasttxhook[chan] = value;
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
if (XPD_HW(xpd).type == 6) {
int ret;
/* Make sure NEON state is off for */
if (value == FXS_LINE_POL_OHTRANS && IS_SET(priv->neon_blinking, chan))
set_vm_led_mode(xpd->xbus, xpd, chan, 0);
ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_TYPE6_LINEFEED, value);
if (value == FXS_LINE_POL_ACTIVE && PHONEDEV(xpd).msg_waiting[chan])
set_vm_led_mode(xpd->xbus, xpd, chan, PHONEDEV(xpd).msg_waiting[chan]);
return ret;
} else {
return SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, 0x40, value);
}
return 0;
}
static void vmwi_search(xpd_t *xpd, lineno_t pos, bool on)
@@ -296,19 +357,75 @@ static int do_led(xpd_t *xpd, lineno_t chan, __u8 which, bool on)
else
BIT_CLR(priv->ledstate[which], chan);
}
LINE_DBG(LEDS, xpd, chan, "LED: which=%d -- %s\n", which,
LINE_DBG(LEDS, xpd, chan, "LED: (type=%d) which=%d -- %s\n", XPD_HW(xpd).type, which,
(on) ? "on" : "off");
value = BIT(2) | BIT(3);
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
if (on)
value |= led_register_vals[which];
ret =
SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE, REG_DIGITAL_IOCTRL,
value);
if (XPD_HW(xpd).type == 6) {
int mask = 1 << chan;
value = (on) << chan;
XPD_DBG(LEDS, xpd, "LED(%d): 0x%0X (mask: 0x%0X)\n", chan,
value, mask);
if (which == LED_GREEN) { /* other leds ignored */
ret = EXP_REQUEST(xbus, xpd, SLIC_WRITE,
REG_TYPE6_EXP_GPIOA, value, mask);
}
} else {
value = BIT(2) | BIT(3);
value |= ((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[which]);
if (on)
value |= led_register_vals[which];
ret = SLIC_DIRECT_REQUEST(xbus, xpd, chan, SLIC_WRITE,
REG_TYPE1_DIGITAL_IOCTRL, value);
}
return 0;
out:
return ret;
}
static inline void set_mwi_led(xpd_t *xpd, int pos, int on)
{
struct FXS_priv_data *priv;
BUG_ON(!xpd);
priv = xpd->priv;
if (XPD_HW(xpd).type != 6)
return;
if (on) {
if (! IS_SET(priv->neonstate, pos)) {
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x00);
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x04);
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x0F);
BIT_SET(priv->neonstate, pos);
}
} else {
if (IS_SET(priv->neonstate, pos)) {
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_DIAG1, 0x00);
BIT_CLR(priv->neonstate, pos);
}
}
}
static void blink_mwi(xpd_t *xpd)
{
struct FXS_priv_data *priv;
unsigned int timer_count;
int i;
BUG_ON(!xpd);
priv = xpd->priv;
timer_count = xpd->timer_count;
for_each_line(xpd, i) {
unsigned int msgs = PHONEDEV(xpd).msg_waiting[i];
/* LED duty cycle: 300ms on, 700ms off */
unsigned int in_range = (timer_count % 1000) >= 0 && (timer_count % 1000) <= 300;
if (!IS_OFFHOOK(xpd, i) && msgs && in_range &&
IS_SET(priv->neon_blinking,i) && priv->ohttimer[i] == 0)
set_mwi_led(xpd, i, 1);
else
set_mwi_led(xpd, i, 0);
}
}
static void handle_fxs_leds(xpd_t *xpd)
{
int i;
@@ -379,6 +496,10 @@ static int metering_gen(xpd_t *xpd, lineno_t chan, bool on)
{
__u8 value = (on) ? 0x94 : 0x00;
if (XPD_HW(xpd).type == 6) {
XBUS_NOTICE("Metering not supported with FXS type 6");
return 0;
}
LINE_DBG(SIGNAL, xpd, chan, "METERING Generate: %s\n",
(on) ? "ON" : "OFF");
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, chan, SLIC_WRITE, 0x23,
@@ -446,11 +567,13 @@ static int fxs_proc_create(xbus_t *xbus, xpd_t *xpd)
}
static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
int channels;
int subunit_ports;
int regular_channels;
struct FXS_priv_data *priv;
int i;
@@ -463,20 +586,21 @@ static xpd_t *FXS_card_new(xbus_t *xbus, int unit, int subunit,
unit, subunit);
return NULL;
}
if (subtype == 2)
subunit_ports = unit_descriptor->numchips * unit_descriptor->ports_per_chip;
if (unit_descriptor->subtype == 2)
regular_channels = min(6, subunit_ports);
else
regular_channels = min(8, subunit_ports);
channels = regular_channels;
/* Calculate digital inputs/outputs */
if (unit == 0 && subtype != 4) {
if (unit == 0 && unit_descriptor->subtype != 4 && unit_descriptor->numchips != 4) {
channels += 6; /* 2 DIGITAL OUTPUTS, 4 DIGITAL INPUTS */
d_inputs = LINES_DIGI_INP;
d_outputs = LINES_DIGI_OUT;
}
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct FXS_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct FXS_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
/* Initialize digital inputs/outputs */
@@ -510,20 +634,30 @@ err:
static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
{
struct FXS_priv_data *priv;
int ret = 0;
int i;
BUG_ON(!xpd);
priv = xpd->priv;
/*
* Setup ring timers
*/
/* Software controled ringing (for CID) */
/* Ringing Oscilator Control */
ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
0x22, 0x00);
if (XPD_HW(xpd).type == 6) {
ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
REG_TYPE6_RINGCON, 0x00);
} else {
ret = SLIC_DIRECT_REQUEST(xbus, xpd, PORT_BROADCAST, SLIC_WRITE,
REG_TYPE1_RINGCON, 0x00);
}
if (ret < 0)
goto err;
for_each_line(xpd, i) {
if (XPD_HW(xpd).type == 6)
/* An arbitrary value that is not FXS_LINE_OPEN */
priv->polledhook[i] = FXS_LINE_ACTIVE;
linefeed_control(xbus, xpd, i, FXS_LINE_POL_ACTIVE);
}
XPD_DBG(GENERAL, xpd, "done\n");
@@ -551,8 +685,13 @@ static int FXS_card_init(xbus_t *xbus, xpd_t *xpd)
(PHONEDEV(xpd).digital_outputs | PHONEDEV(xpd).
digital_inputs, i))
continue;
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_LOOPCLOSURE,
0);
if (XPD_HW(xpd).type == 6) {
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE6_LCRRTP,
0);
} else {
SLIC_DIRECT_REQUEST(xbus, xpd, i, SLIC_READ, REG_TYPE1_LOOPCLOSURE,
0);
}
}
return 0;
err:
@@ -702,6 +841,34 @@ static struct ring_reg_params ring_parameters[] = {
REG_ENTRY(1, 0x1D, 0x00, 0x46, 0x00, 0x36, 0x00, 0x36),
};
static void set_neon_state(xbus_t *xbus, xpd_t *xpd, int pos,
enum neon_state ns)
{
struct FXS_priv_data *priv;
LINE_DBG(SIGNAL, xpd, pos, "set NEON -> %d\n", ns);
priv = xpd->priv;
if (ns == INIT_NEON)
BIT_SET(priv->neon_blinking, pos);
else
BIT_CLR(priv->neon_blinking, pos);
if (XPD_HW(xpd).type == 6) {
switch (ns) {
case INIT_NEON:
RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_MWI << 3);
//RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_MWI << 3);
break;
default:
LINE_DBG(REGS, xpd, pos, "0x%04X: R 0x\n", RAM_TYPE6_SLOPE_VLIM);
set_mwi_led(xpd, pos, 0); /* Cannot have NEON LED during OHT (type == 6) */
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_USERSTAT, 0x00);
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, REG_TYPE6_ENHANCE, 0x10);
RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_VBATH_EXPECT, VBATH_EXPECT_DFLT << 3);
RAM_REQUEST(xbus, xpd, pos, SLIC_WRITE, RAM_TYPE6_SLOPE_VLIM, SLOPE_VLIM_DFLT << 3);
break;
}
}
}
static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos,
enum ring_types rtype)
{
@@ -710,6 +877,8 @@ static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos,
int ret = 0;
int i;
if (XPD_HW(xpd).type == 6)
return 0;
if (rtype < RING_TYPE_NEON || rtype > RING_TYPE_NORMAL)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
@@ -755,15 +924,16 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
if (VMWI_NEON(priv, pos) && msg_waiting) {
/* A write to register 0x40 will now turn on/off the VM led */
LINE_DBG(SIGNAL, xpd, pos, "NEON\n");
BIT_SET(priv->neon_blinking, pos);
set_neon_state(xbus, xpd, pos, INIT_NEON);
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NEON);
} else if (ring_trapez) {
LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n");
set_neon_state(xbus, xpd, pos, END_NEON);
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_TRAPEZ);
} else {
/* A write to register 0x40 will now turn on/off the ringer */
LINE_DBG(SIGNAL, xpd, pos, "RINGER\n");
BIT_CLR(priv->neon_blinking, pos);
set_neon_state(xbus, xpd, pos, END_NEON);
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NORMAL);
}
return (ret ? -EPROTO : 0);
@@ -782,31 +952,43 @@ static void start_stop_vm_led(xbus_t *xbus, xpd_t *xpd, lineno_t pos)
msgs = PHONEDEV(xpd).msg_waiting[pos];
LINE_DBG(SIGNAL, xpd, pos, "%s\n", (msgs) ? "ON" : "OFF");
set_vm_led_mode(xbus, xpd, pos, msgs);
do_chan_power(xbus, xpd, pos, msgs > 0);
linefeed_control(xbus, xpd, pos,
(msgs >
0) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
if (XPD_HW(xpd).type == 1) {
do_chan_power(xbus, xpd, pos, msgs > 0);
linefeed_control(xbus, xpd, pos,
(msgs > 0) ? FXS_LINE_RING : priv->idletxhookstate[pos]);
}
}
static int relay_out(xpd_t *xpd, int pos, bool on)
{
int value;
int ret = 0;
int value = 0;
int which = pos;
int relay_channels[] = { 0, 4 };
BUG_ON(!xpd);
/* map logical position to output port number (0/1) */
which -= (xpd->subtype == 2) ? 6 : 8;
which -= (XPD_HW(xpd).subtype == 2) ? 6 : 8;
LINE_DBG(SIGNAL, xpd, pos, "which=%d -- %s\n", which,
(on) ? "on" : "off");
which = which % ARRAY_SIZE(relay_channels);
value = BIT(2) | BIT(3);
value |=
((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
if (on)
value |= led_register_vals[OUTPUT_RELAY];
return SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels[which],
SLIC_WRITE, REG_DIGITAL_IOCTRL, value);
if (XPD_HW(xpd).type == 6) {
int relay_values_type6[] = { 0x01, 0x40 };
which = which % ARRAY_SIZE(relay_values_type6);
if (on)
value |= relay_values_type6[which];
ret = EXP_REQUEST(xpd->xbus, xpd, SLIC_WRITE,
REG_TYPE6_EXP_GPIOB, value, relay_values_type6[which]);
} else {
int relay_channels_type1[] = { 0, 4 };
which = which % ARRAY_SIZE(relay_channels_type1);
value = BIT(2) | BIT(3);
value |=
((BIT(5) | BIT(6) | BIT(7)) & ~led_register_mask[OUTPUT_RELAY]);
if (on)
value |= led_register_vals[OUTPUT_RELAY];
ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, relay_channels_type1[which],
SLIC_WRITE, REG_TYPE1_DIGITAL_IOCTRL, value);
}
return ret;
}
static int send_ring(xpd_t *xpd, lineno_t chan, bool on)
@@ -988,6 +1170,21 @@ static int set_vmwi(xpd_t *xpd, int pos, unsigned long arg)
return 0;
}
static int hardware_dtmf_control(xpd_t *xpd, int pos, bool on)
{
int ret = 0;
LINE_DBG(SIGNAL, xpd, pos, "%s: %s\n", __func__, (on) ? "on" : "off");
if (XPD_HW(xpd).type == 6) {
int value = (on) ? 0xE0 : REG_TYPE6_TONEN_DTMF_DIS;
ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE,
REG_TYPE6_TONEN, value);
} else {
ret = SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_WRITE, 0x17, on);
}
return ret;
}
/*
* Private ioctl()
* We don't need it now, since we detect vmwi via FSK patterns
@@ -1053,9 +1250,8 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
* Detection mode changed:
* Disable DTMF interrupts
*/
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x17, 0);
}
hardware_dtmf_control(xpd, pos, 0);
BIT_CLR(priv->want_dtmf_events, pos);
BIT_CLR(priv->want_dtmf_mute, pos);
__do_mute_dtmf(xpd, pos, 0);
@@ -1077,8 +1273,7 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
LINE_DBG(SIGNAL, xpd, pos,
"DAHDI_TONEDETECT: "
"Enable Hardware DTMF\n");
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x17, 1);
hardware_dtmf_control(xpd, pos, 1);
}
BIT_SET(priv->want_dtmf_events, pos);
} else {
@@ -1090,8 +1285,7 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
LINE_DBG(SIGNAL, xpd, pos,
"DAHDI_TONEDETECT: "
"Disable Hardware DTMF\n");
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x17, 0);
hardware_dtmf_control(xpd, pos, 0);
}
BIT_CLR(priv->want_dtmf_events, pos);
}
@@ -1147,11 +1341,13 @@ static int FXS_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
if (!vmwi_ioctl) {
static bool notified;
if (!notified++)
if (!notified) {
notified = true;
LINE_NOTICE(xpd, pos,
"Got DAHDI_VMWI notification "
"but vmwi_ioctl parameter is off. "
"Ignoring.\n");
}
return 0;
}
/* Digital inputs/outputs don't have VM leds */
@@ -1209,21 +1405,67 @@ static int FXS_card_close(xpd_t *xpd, lineno_t chan)
* +-----+-----+-----+-----+-----+-----+-----+-----+
*
*/
static int input_channels[] = { 6, 7, 2, 3 }; // Slic numbers of input relays
static int input_ports_type1[] = {
/* slic = input_port */
[0] = -1,
[1] = -1,
[2] = 2,
[3] = 3,
[4] = -1,
[5] = -1,
[6] = 0,
[7] = 1,
};
static void poll_inputs(xpd_t *xpd)
{
int i;
BUG_ON(xpd->xbus_idx != 0); // Only unit #0 has digital inputs
for (i = 0; i < ARRAY_SIZE(input_channels); i++) {
__u8 pos = input_channels[i];
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, pos, SLIC_READ, 0x06, 0);
if (XPD_HW(xpd).type == 6) {
EXP_REQUEST(xpd->xbus, xpd, SLIC_READ,
REG_TYPE6_EXP_GPIOB, 0, 0);
} else {
for (i = 0; i < ARRAY_SIZE(input_ports_type1); i++) {
int pos = input_ports_type1[i];
if (pos >= 0) {
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ, 0x06, 0);
}
}
}
}
#endif
static void poll_linefeed(xpd_t *xpd)
{
struct FXS_priv_data *priv;
int i;
if (XPD_HW(xpd).type != 6)
return;
if (xpd->xpd_state != XPD_STATE_READY)
return;
priv = xpd->priv;
BUG_ON(!priv);
BUG_ON(!xpd->xbus);
XPD_DBG(GENERAL, xpd, "periodic poll");
for_each_line(xpd, i) {
if (IS_SET(PHONEDEV(xpd).digital_outputs, i)
|| IS_SET(PHONEDEV(xpd).digital_inputs, i))
continue;
if (priv->polledhook[i] == FXS_LINE_OPEN &&
priv->lasttxhook[i] != FXS_LINE_OPEN) {
LINE_NOTICE(xpd, i, "Overheat detected, resetting.");
priv->overheat_reset_counter[i]++;
linefeed_control(xpd->xbus, xpd, i,
priv->lasttxhook[i]);
}
SLIC_DIRECT_REQUEST(xpd->xbus, xpd, i, SLIC_READ,
REG_TYPE6_LINEFEED, 0);
}
}
static void handle_linefeed(xpd_t *xpd)
{
struct FXS_priv_data *priv;
@@ -1369,8 +1611,12 @@ static int FXS_card_tick(xbus_t *xbus, xpd_t *xpd)
poll_inputs(xpd);
}
#endif
if ((xpd->timer_count % poll_chan_linefeed) == 0)
poll_linefeed(xpd);
handle_fxs_leds(xpd);
handle_linefeed(xpd);
if (XPD_HW(xpd).type == 6)
blink_mwi(xpd);
/*
* Hack alert (FIXME):
* Asterisk did FXS_card_open() and we wanted to report
@@ -1481,37 +1727,55 @@ HANDLER_DEF(FXS, SIG_CHANGED)
}
#ifdef POLL_DIGITAL_INPUTS
static inline void notify_digital_input(xpd_t *xpd, int input_port, int offhook)
{
int channo = PHONEDEV(xpd).channels - LINES_DIGI_INP + input_port;
/* Stop ringing. No leds for digital inputs. */
PHONEDEV(xpd).ringing[channo] = 0;
if (offhook && !IS_OFFHOOK(xpd, channo)) {
LINE_DBG(SIGNAL, xpd, channo, "OFFHOOK\n");
hookstate_changed(xpd, channo, 1);
} else if (!offhook && IS_OFFHOOK(xpd, channo)) {
LINE_DBG(SIGNAL, xpd, channo, "ONHOOK\n");
hookstate_changed(xpd, channo, 0);
}
}
static void process_digital_inputs(xpd_t *xpd, const reg_cmd_t *info)
{
int i;
bool offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
xpp_line_t lines = BIT(info->portnum);
bool offhook;
/* Sanity check */
if (!PHONEDEV(xpd).digital_inputs) {
XPD_NOTICE(xpd, "%s called without digital inputs. Ignored\n",
__func__);
return;
}
/* Map SLIC number into line number */
for (i = 0; i < ARRAY_SIZE(input_channels); i++) {
int channo = input_channels[i];
int newchanno;
if (XPD_HW(xpd).type == 6) {
static int input_values_type6[] = { 0x80, 0x20, 0x08, 0x02 }; /* I/O Expander values of input relays */
int i;
if (IS_SET(lines, channo)) {
newchanno = PHONEDEV(xpd).channels - LINES_DIGI_INP + i;
BIT_CLR(lines, channo);
BIT_SET(lines, newchanno);
/* Stop ringing. No leds for digital inputs. */
PHONEDEV(xpd).ringing[newchanno] = 0;
if (offhook && !IS_OFFHOOK(xpd, newchanno)) {
LINE_DBG(SIGNAL, xpd, newchanno, "OFFHOOK\n");
hookstate_changed(xpd, newchanno, 1);
} else if (!offhook && IS_OFFHOOK(xpd, newchanno)) {
LINE_DBG(SIGNAL, xpd, newchanno, "ONHOOK\n");
hookstate_changed(xpd, newchanno, 0);
}
/* Map I/O Expander GPIO into line number */
for (i = 0; i < ARRAY_SIZE(input_values_type6); i++) {
int chanmask = input_values_type6[i];
offhook = (REG_FIELD(info, data_low) & chanmask) == 0;
notify_digital_input(xpd, i, offhook);
}
} else {
int channo = info->h.portnum;
int input_port;
offhook = (REG_FIELD(info, data_low) & 0x1) == 0;
if (channo < 0 || channo >= ARRAY_SIZE(input_ports_type1)) {
XPD_ERR(xpd, "%s: got bad portnum=%d\n", __func__, channo);
return;
}
input_port = input_ports_type1[channo];
if (input_port < 0) {
XPD_ERR(xpd, "%s: portnum=%d is not input port\n", __func__, channo);
return;
}
notify_digital_input(xpd, input_port, offhook);
}
}
#endif
@@ -1580,42 +1844,87 @@ static int FXS_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
{
unsigned long flags;
struct FXS_priv_data *priv;
__u8 regnum;
bool indirect;
__u8 regnum = 0;
bool indirect = 0;
spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv;
BUG_ON(!priv);
indirect = (REG_FIELD(info, regnum) == 0x1E);
regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
(indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low),
REG_FIELD(info, data_high));
if (!indirect && regnum == REG_DTMF_DECODE) {
if (info->h.bytes == REG_CMD_SIZE(REG)) {
if ((XPD_HW(xpd).type == 1) && (REG_FIELD(info, regnum) == 0x1E))
indirect = 1;
regnum = (indirect) ? REG_FIELD(info, subreg) : REG_FIELD(info, regnum);
XPD_DBG(REGS, xpd, "%s reg_num=0x%X, dataL=0x%X dataH=0x%X\n",
(indirect) ? "I" : "D", regnum, REG_FIELD(info, data_low),
REG_FIELD(info, data_high));
}
if (info->h.bytes == REG_CMD_SIZE(RAM)) {
uint addr;
unsigned long val;
XPD_DBG(REGS, xpd, "port=%d, addr_low=0x%X, addr_high=0x%X, data_0=0x%X data_1=0x%X data_2=0x%X data_3=0x%X\n",
info->h.portnum,
REG_FIELD_RAM(info, addr_low),
REG_FIELD_RAM(info, addr_high),
REG_FIELD_RAM(info, data_0),
REG_FIELD_RAM(info, data_1),
REG_FIELD_RAM(info, data_2),
REG_FIELD_RAM(info, data_3));
addr = (REG_FIELD_RAM(info, addr_high) << 8) | REG_FIELD_RAM(info, addr_low);
val = (REG_FIELD_RAM(info, data_3) << 24) |
(REG_FIELD_RAM(info, data_2) << 16) |
(REG_FIELD_RAM(info, data_1) << 8) |
REG_FIELD_RAM(info, data_0);
} else if ((XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DTMF_DECODE) ||
(XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_TONDTMF)) {
__u8 val = REG_FIELD(info, data_low);
process_dtmf(xpd, info->portnum, val);
process_dtmf(xpd, info->h.portnum, val);
} else if ((XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LINEFEED)) {
__u8 val = REG_FIELD(info, data_low);
LINE_DBG(SIGNAL, xpd, info->h.portnum,
"REG_TYPE6_LINEFEED: dataL=0x%X \n", val);
priv->polledhook[info->h.portnum] = val;
}
#ifdef POLL_DIGITAL_INPUTS
/*
* Process digital inputs polling results
*/
else if (!indirect && regnum == REG_DIGITAL_IOCTRL)
else if ( (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_DIGITAL_IOCTRL) ||
(XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_EXP_GPIOB &&
REG_FIELD(info, do_expander)))
process_digital_inputs(xpd, info);
#endif
else if (!indirect && regnum == REG_LOOPCLOSURE) { /* OFFHOOK ? */
else if (XPD_HW(xpd).type == 1 && !indirect && regnum == REG_TYPE1_LOOPCLOSURE) { /* OFFHOOK ? */
__u8 val = REG_FIELD(info, data_low);
xpp_line_t mask = BIT(info->portnum);
xpp_line_t mask = BIT(info->h.portnum);
xpp_line_t offhook;
/*
* Validate reply. Non-existing/disabled ports
* will reply with 0xFF. Ignore these.
*/
if ((val & REG_LOOPCLOSURE_ZERO) == 0) {
offhook = (val & REG_LOOPCLOSURE_LCR) ? mask : 0;
LINE_DBG(SIGNAL, xpd, info->portnum,
"REG_LOOPCLOSURE: dataL=0x%X "
if ((val & REG_TYPE1_LOOPCLOSURE_ZERO) == 0) {
offhook = (val & REG_TYPE1_LOOPCLOSURE_LCR) ? mask : 0;
LINE_DBG(SIGNAL, xpd, info->h.portnum,
"REG_TYPE1_LOOPCLOSURE: dataL=0x%X "
"(offhook=0x%X mask=0x%X)\n",
val, offhook, mask);
process_hookstate(xpd, offhook, mask);
}
} else if (XPD_HW(xpd).type == 6 && !indirect && regnum == REG_TYPE6_LCRRTP) { /* OFFHOOK ? */
__u8 val = REG_FIELD(info, data_low);
xpp_line_t mask = BIT(info->h.portnum);
xpp_line_t offhook;
/*
* Validate reply. Non-existing/disabled ports
* will reply with 0xFF. Ignore these.
*/
if ((val & REG_TYPE6_LCRRTP_ZERO) == 0) {
offhook = (val & REG_TYPE6_LCRRTP_LCR) ? mask : 0;
LINE_DBG(SIGNAL, xpd, info->h.portnum,
"REG_TYPE6_LCRRTP: dataL=0x%X "
"(offhook=0x%X mask=0x%X)\n",
val, offhook, mask);
process_hookstate(xpd, offhook, mask);
@@ -1792,6 +2101,10 @@ static int proc_fxs_info_show(struct seq_file *sfile, void *not_used)
LED_COUNTER(priv, i, led));
}
}
seq_printf(sfile, "\n%-12s", "overheats:");
for_each_line(xpd, i) {
seq_printf(sfile, "%4d", priv->overheat_reset_counter[i]);
}
seq_printf(sfile, "\n");
spin_unlock_irqrestore(&xpd->lock, flags);
return 0;
@@ -1992,9 +2305,9 @@ static int fxs_xpd_probe(struct device *dev)
xpd = dev_to_xpd(dev);
/* Is it our device? */
if (xpd->type != XPD_TYPE_FXS) {
if (xpd->xpd_type != XPD_TYPE_FXS) {
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
xpd->type);
xpd->xpd_type);
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
@@ -2020,7 +2333,7 @@ static int fxs_xpd_remove(struct device *dev)
}
static struct xpd_driver fxs_driver = {
.type = XPD_TYPE_FXS,
.xpd_type = XPD_TYPE_FXS,
.driver = {
.name = "fxs",
.owner = THIS_MODULE,
@@ -2035,7 +2348,6 @@ static int __init card_fxs_startup(void)
if ((ret = xpd_driver_register(&fxs_driver.driver)) < 0)
return ret;
INFO("revision %s\n", XPP_VERSION);
#ifdef POLL_DIGITAL_INPUTS
INFO("FEATURE: with DIGITAL INPUTS support (polled every %d msec)\n",
poll_digital_inputs);
@@ -2061,7 +2373,6 @@ static void __exit card_fxs_cleanup(void)
MODULE_DESCRIPTION("XPP FXS Card Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
MODULE_ALIAS_XPD(XPD_TYPE_FXS);
module_init(card_fxs_startup);

View File

@@ -56,12 +56,12 @@ static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
* eoftx==1: Start sending us D-channel packets.
* eoftx==0: Stop sending us D-channel packets.
*/
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, unit);
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, unit);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
reg_cmd->bytes = 0;
reg_cmd->is_multibyte = 1;
reg_cmd->portnum = portno;
reg_cmd->eoframe = eoftx;
reg_cmd->h.bytes = 0;
reg_cmd->h.is_multibyte = 1;
reg_cmd->h.portnum = portno;
reg_cmd->h.eoframe = eoftx;
PORT_DBG(REGS, xbus, unit, portno, "Magic Packet (eoftx=%d)\n", eoftx);
if (debug & DBG_REGS)
dump_xframe(__func__, xbus, xframe, debug);
@@ -90,13 +90,14 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
int portno;
bool writing;
int op; /* [W]rite, [R]ead */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti, [R]AM */
bool do_subreg = 0;
int regnum;
int subreg;
int data_low;
bool do_datah;
int data_high;
bool do_expander = 0;
int ret = -EBADR;
num_args = 2; /* port + operation */
@@ -158,6 +159,12 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
num_args++; /* register */
//XPD_DBG(REGS, xpd, "DIRECT\n");
break;
case 'X':
do_subreg = 0;
do_expander = 1;
num_args++; /* register */
//XPD_DBG(REGS, xpd, "EXPANDER\n");
break;
case 'M':
case 'm':
if (op != 'W') {
@@ -169,6 +176,16 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
num_args--; /* No data low */
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
break;
case 'R':
switch (op) {
case 'W':
num_args += 5; /* add: addr_high, data_[0-3] */
break;
case 'R':
num_args += 2; /* add: addr_low, addr_high */
break;
}
break;
default:
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
goto out;
@@ -197,6 +214,32 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
addr_mode == 'm');
goto out;
}
if (addr_mode == 'R') {
__u8 input[6];
int i;
if (num_args - 2 > 6) {
XPD_ERR(xpd, "Too many args (%d) -- should be less than 6\n", num_args - 2);
goto out;
}
for (i = 0; i < num_args - 2; i++, argno++) {
int hexbyte= parse_hexbyte(argv[argno]);
if (hexbyte < 0) {
XPD_ERR(xpd, "Illegal input[%d] number '%s'\n", i, argv[argno]);
goto out;
}
input[i] = hexbyte;
}
ret = xpp_ram_request(xpd->xbus, xpd, portno, writing,
input[0],
input[1],
input[2],
input[3],
input[4],
input[5],
1);
goto out;
}
/* Normal (non-Magic) register commands */
do_datah = 0;
if (argno >= argc) {
@@ -264,17 +307,17 @@ static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
#if 0
XPD_DBG(REGS, xpd,
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
"dataL=%d do_datah=%d dataH=%d\n",
"dataL=%d do_datah=%d dataH=%d do_expander=%d\n",
portno, /* portno */
writing, /* writing */
regnum, do_subreg, /* use subreg */
subreg, /* subreg */
data_low, do_datah, /* use data_high */
data_high);
data_high, do_expander);
#endif
ret = xpp_register_request(xpd->xbus, xpd, portno,
writing, regnum, do_subreg, subreg,
data_low, do_datah, data_high, 1);
data_low, do_datah, data_high, 1, do_expander);
out:
return ret;
}
@@ -362,7 +405,7 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
__u8 data_low, bool do_datah, __u8 data_high,
bool should_reply)
bool should_reply, bool do_expander)
{
int ret = 0;
xframe_t *xframe;
@@ -373,23 +416,22 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
DBG(REGS, "NO XBUS\n");
return -EINVAL;
}
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
xpd->xbus_idx);
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, REG, xpd->xbus_idx);
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
data_low, data_high);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
/* do not count the 'bytes' field */
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
reg_cmd->is_multibyte = 0;
reg_cmd->h.bytes = REG_CMD_SIZE(REG);
reg_cmd->h.is_multibyte = 0;
if (portno == PORT_BROADCAST) {
reg_cmd->portnum = 0;
reg_cmd->h.portnum = 0;
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
} else {
reg_cmd->portnum = portno;
reg_cmd->h.portnum = portno;
REG_FIELD(reg_cmd, all_ports_broadcast) = 0;
}
reg_cmd->eoframe = 0;
reg_cmd->h.eoframe = 0;
REG_FIELD(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
REG_FIELD(reg_cmd, read_request) = (writing) ? 0 : 1;
REG_FIELD(reg_cmd, do_subreg) = do_subreg;
@@ -398,11 +440,12 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
REG_FIELD(reg_cmd, do_datah) = do_datah;
REG_FIELD(reg_cmd, data_low) = data_low;
REG_FIELD(reg_cmd, data_high) = data_high;
REG_FIELD(reg_cmd, do_expander) = do_expander;
if (should_reply)
xpd->requested_reply = *reg_cmd;
if (debug & DBG_REGS) {
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
reg_cmd->portnum, reg_cmd);
reg_cmd->h.portnum, reg_cmd);
dump_packet("REG_REQ", pack, 1);
}
if (!xframe->usec_towait) { /* default processing time of SPI */
@@ -416,6 +459,67 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
}
EXPORT_SYMBOL(xpp_register_request);
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing,
__u8 addr_low,
__u8 addr_high,
__u8 data_0,
__u8 data_1,
__u8 data_2,
__u8 data_3,
bool should_reply)
{
int ret = 0;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
if (!xbus) {
DBG(REGS, "NO XBUS\n");
return -EINVAL;
}
XFRAME_NEW_REG_CMD(xframe, pack, xbus, GLOBAL, RAM, xpd->xbus_idx);
LINE_DBG(REGS, xpd, portno, "%cR %02X %02X %02X %02X %02X %02X\n",
(writing) ? 'W' : 'R',
addr_low, addr_high,
data_0, data_1, data_2, data_3);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
/* do not count the 'bytes' field */
reg_cmd->h.bytes = REG_CMD_SIZE(RAM);
reg_cmd->h.is_multibyte = 0;
if (portno == PORT_BROADCAST) {
reg_cmd->h.portnum = 0;
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 1;
} else {
reg_cmd->h.portnum = portno;
REG_FIELD_RAM(reg_cmd, all_ports_broadcast) = 0;
}
reg_cmd->h.eoframe = 0;
REG_FIELD_RAM(reg_cmd, reserved) = 0; /* force reserved bits to 0 */
REG_FIELD_RAM(reg_cmd, read_request) = (writing) ? 0 : 1;
REG_FIELD_RAM(reg_cmd, do_datah) = 1;
REG_FIELD_RAM(reg_cmd, do_subreg) = 1;
REG_FIELD_RAM(reg_cmd, addr_low) = addr_low;
REG_FIELD_RAM(reg_cmd, addr_high) = addr_high;
REG_FIELD_RAM(reg_cmd, data_0) = data_0;
REG_FIELD_RAM(reg_cmd, data_1) = data_1;
REG_FIELD_RAM(reg_cmd, data_2) = data_2;
REG_FIELD_RAM(reg_cmd, data_3) = data_3;
if (should_reply)
xpd->requested_reply = *reg_cmd;
if (debug & DBG_REGS) {
dump_reg_cmd("REG_RAM", 1, xbus, xpd->addr.unit,
reg_cmd->h.portnum, reg_cmd);
dump_packet("REG_RAM", pack, 1);
}
if (!xframe->usec_towait) { /* default processing time of SPI */
xframe->usec_towait = 1000;
}
ret = send_cmd_frame(xbus, xframe);
return ret;
}
EXPORT_SYMBOL(xpp_ram_request);
/*
* The XPD parameter is totaly ignored by the driver and firmware as well.
*/
@@ -545,21 +649,14 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
}
card_desc->magic = CARD_DESC_MAGIC;
INIT_LIST_HEAD(&card_desc->card_list);
card_desc->type = this_unit->type;
card_desc->subtype = this_unit->subtype;
card_desc->xpd_addr = this_unit->addr;
card_desc->numchips = this_unit->numchips;
card_desc->ports_per_chip = this_unit->ports_per_chip;
card_desc->port_dir = this_unit->port_dir;
card_desc->ports =
card_desc->numchips * card_desc->ports_per_chip;
card_desc->unit_descriptor = *this_unit;
XBUS_INFO(xbus,
" CARD %d type=%d.%d ports=%d (%dx%d), "
" CARD %d type=%d.%d ports=(%dx%d), "
"port-dir=0x%02X\n",
card_desc->xpd_addr.unit, card_desc->type,
card_desc->subtype, card_desc->ports,
card_desc->numchips, card_desc->ports_per_chip,
card_desc->port_dir);
this_unit->addr.unit, this_unit->type,
this_unit->subtype,
this_unit->numchips, this_unit->ports_per_chip,
this_unit->port_dir);
spin_lock_irqsave(&worker->worker_lock, flags);
worker->num_units++;
XBUS_COUNTER(xbus, UNITS)++;
@@ -591,7 +688,7 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
return -EPROTO;
}
if (debug & DBG_REGS) {
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->h.portnum,
reg);
dump_packet("REG_REPLY", pack, 1);
}
@@ -706,6 +803,7 @@ int run_initialize_registers(xpd_t *xpd)
char xbuslabel[MAX_ENV_STR];
char init_card[MAX_PATH_STR];
__u8 direction_mask;
__u8 hw_type = XPD_HW(xpd).type;
int i;
char *argv[] = {
init_card,
@@ -752,8 +850,9 @@ int run_initialize_registers(xpd_t *xpd)
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
xbus->transport.model_string);
snprintf(typestr, MAX_ENV_STR, "HW_TYPE=%d", hw_type);
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->xpd_type);
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
direction_mask);
@@ -762,7 +861,7 @@ int run_initialize_registers(xpd_t *xpd)
xbus->connector);
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
if (snprintf
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, hw_type,
xbus->revision) > MAX_PATH_STR) {
XPD_NOTICE(xpd,
"Cannot initialize. pathname is longer "
@@ -779,7 +878,7 @@ int run_initialize_registers(xpd_t *xpd)
goto err;
}
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
init_card, xpd->type, xbus->revision);
init_card, xpd->xpd_type, xbus->revision);
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
/*
* Carefully report results

View File

@@ -74,9 +74,18 @@ DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
__u8 data_low, bool do_datah, __u8 data_high,
bool should_reply);
bool should_reply, bool do_expander);
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
bool eoftx, __u8 *buf, unsigned len);
int xpp_ram_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing,
__u8 addr_low,
__u8 addr_high,
__u8 data_0,
__u8 data_1,
__u8 data_2,
__u8 data_3,
bool should_reply);
extern xproto_table_t PROTO_TABLE(GLOBAL);
int run_initialize_registers(xpd_t *xpd);
int parse_chip_command(xpd_t *xpd, char *cmdline);

View File

@@ -85,8 +85,6 @@ static int pri_lineconfig(xpd_t *xpd, int lineconfig);
static void send_idlebits(xpd_t *xpd, bool saveold);
static int apply_pri_protocol(xpd_t *xpd);
#define PROC_REGISTER_FNAME "slics"
enum pri_protocol {
PRI_PROTO_0 = 0,
PRI_PROTO_E1 = 1,
@@ -390,7 +388,8 @@ static int query_subunit(xpd_t *xpd, __u8 regnum)
0, /* data_L */
0, /* do_datah */
0, /* data_H */
0 /* should_reply */
0, /* should_reply */
0 /* do_expander */
);
}
@@ -406,7 +405,8 @@ static int write_subunit(xpd_t *xpd, __u8 regnum, __u8 val)
val, /* data_L */
0, /* do_datah */
0, /* data_H */
0 /* should_reply */
0, /* should_reply */
0 /* do_expander */
);
}
@@ -421,7 +421,8 @@ static int pri_write_reg(xpd_t *xpd, int regnum, __u8 val)
val, /* data_L */
0, /* do_datah */
0, /* data_H */
0 /* should_reply */
0, /* should_reply */
0 /* do_expander */
);
}
@@ -707,7 +708,7 @@ static void set_clocking(xpd_t *xpd)
/* Now set it */
if (best_xpd
&& ((struct PRI_priv_data *)(best_xpd->priv))->clock_source == 0) {
__u8 reg_pc_init[] = { VAL_PC_GPI, VAL_PC_GPI, VAL_PC_GPI };
__u8 reg_pc_init[] = { VAL_PC_SYPR, VAL_PC_GPI, VAL_PC_GPI };
for (i = 0; i < ARRAY_SIZE(reg_pc_init); i++) {
__u8 reg_pc = reg_pc_init[i];
@@ -1255,21 +1256,29 @@ static int pri_chanconfig(struct file *file, struct dahdi_chan *chan,
}
static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone)
{
xpd_t *xpd = NULL;
struct PRI_priv_data *priv;
int channels = min(31, CHANNELS_PERXPD); /* worst case */
if (subunit_ports != 1) {
XBUS_ERR(xbus, "Bad subunit_ports=%d\n", subunit_ports);
if ((unit_descriptor->ports_per_chip < 1) ||
(unit_descriptor->ports_per_chip > 4)) {
XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
unit_descriptor->ports_per_chip);
return NULL;
}
if (unit_descriptor->numchips != 1) {
XBUS_ERR(xbus, "Bad numchips=%d\n",
unit_descriptor->numchips);
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct PRI_priv_data), proto_table, channels);
xpd_alloc(xbus, unit, subunit,
sizeof(struct PRI_priv_data), proto_table, unit_descriptor, channels);
if (!xpd)
return NULL;
priv = xpd->priv;
@@ -1289,7 +1298,7 @@ static int PRI_card_init(xbus_t *xbus, xpd_t *xpd)
BUG_ON(!xpd);
XPD_DBG(GENERAL, xpd, "\n");
xpd->type = XPD_TYPE_PRI;
xpd->xpd_type = XPD_TYPE_PRI;
priv = xpd->priv;
if (priv->pri_protocol == PRI_PROTO_0) {
/*
@@ -2255,7 +2264,7 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
/* Map UNIT + PORTNUM to XPD */
orig_xpd = xpd;
addr.unit = orig_xpd->addr.unit;
addr.subunit = info->portnum;
addr.subunit = info->h.portnum;
regnum = REG_FIELD(info, regnum);
data_low = REG_FIELD(info, data_low);
xpd = xpd_byaddr(xbus, addr.unit, addr.subunit);
@@ -2269,9 +2278,9 @@ static int PRI_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
spin_lock_irqsave(&xpd->lock, flags);
priv = xpd->priv;
BUG_ON(!priv);
if (info->is_multibyte) {
if (info->h.is_multibyte) {
XPD_NOTICE(xpd, "Got Multibyte: %d bytes, eoframe: %d\n",
info->bytes, info->eoframe);
info->h.bytes, info->h.eoframe);
goto end;
}
if (regnum == REG_FRS0 && !REG_FIELD(info, do_subreg))
@@ -2637,9 +2646,9 @@ static int pri_xpd_probe(struct device *dev)
xpd = dev_to_xpd(dev);
/* Is it our device? */
if (xpd->type != XPD_TYPE_PRI) {
if (xpd->xpd_type != XPD_TYPE_PRI) {
XPD_ERR(xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
xpd->type);
xpd->xpd_type);
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
@@ -2722,7 +2731,7 @@ static int pri_xpd_remove(struct device *dev)
}
static struct xpd_driver pri_driver = {
.type = XPD_TYPE_PRI,
.xpd_type = XPD_TYPE_PRI,
.driver = {
.name = "pri",
.owner = THIS_MODULE,
@@ -2736,7 +2745,6 @@ static int __init card_pri_startup(void)
if ((ret = xpd_driver_register(&pri_driver.driver)) < 0)
return ret;
INFO("revision %s\n", XPP_VERSION);
#ifdef DAHDI_AUDIO_NOTIFY
INFO("FEATURE: WITH DAHDI_AUDIO_NOTIFY\n");
#else
@@ -2756,7 +2764,6 @@ static void __exit card_pri_cleanup(void)
MODULE_DESCRIPTION("XPP PRI Card Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
MODULE_ALIAS_XPD(XPD_TYPE_PRI);
module_init(card_pri_startup);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
FPGA_1161.201.hex

View File

@@ -4,11 +4,12 @@
USB_FW = USB_FW.hex USB_FW.201.hex USB_RECOV.hex
FPGA_FW = FPGA_FXS.hex FPGA_1141.hex FPGA_1151.hex FPGA_1161.hex \
FPGA_1161.201.hex FPGA_1161.202.hex
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex \
PIC_TYPE_6.hex
OCT_FW = $(wildcard OCT6104E-256D.ima)
FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW)
PROTO_VER = 30
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5)
SCRIPTS_BASE = $(patsubst %,init_card_%_$(PROTO_VER),1 2 3 4 5 6)
SCRIPTS = $(SCRIPTS_BASE:%=../%)
TARGET = $(DESTDIR)/usr/share/dahdi

View File

@@ -0,0 +1,460 @@
#
# $Id: PIC_TYPE_6.hex 11526 2016-04-05 13:30:04Z dima $
#
:03000000A1CA5042
:03000100C41C41DB
:0300020069969963
:03000300D50D50C8
:030004000390392D
:0300050067967982
:03000600A05A05F8
:03000700C40C40E6
:030008006996995D
:03000900D50D50C2
:03000A0003903927
:03000B007797796B
:03000C00A0BA0B8C
:03000D0080080068
:03000E00F01F01DF
:03000F00022022AA
:03001000C05C05CC
:0300110002402486
:03001200C00C001F
:03001300021021B7
:030014003613613F
:03001500202202A4
:03001600E01E01E8
:03001700121121A2
:030018003223226E
:030019002E42E490
:03001A00A14A14E4
:03001B008008005A
:03001C00C0010B15
:03001D0019A038EF
:03001E00743C57D8
:03001F00A24D40AF
:03002000C01034D9
:030021001CCC42B2
:03002200E07D017D
:0300230002C021F7
:03002400C07C138A
:0300250018C024DC
:03002600643C0433
:03002700A4C0373B
:0300280020C201F2
:03002900743032FE
:03002A00AC3204F1
:03002B0021A031E0
:03002C0090E2025D
:03002D00C20030DE
:03002E00D40901F1
:03002F00121C00A0
:03003000C1E037F5
:03003100024C423C
:03003200C00021EA
:03003300022202A4
:03003400201FFF8B
:0300350003015074
:030036009016B968
:0300370020410263
:03003800030022A0
:03003900901C0414
:03003A002020374C
:03003B00030201BC
:03003C00901032EF
:03003D00C11204E9
:03003E0019003175
:03003F0064320226
:03004000A4503099
:03004100C22901D0
:03004200190C0096
:03004300743037DF
:03004400A48C0782
:03004500209D40BB
:0300460012503421
:03004700A4B8005A
:03004800209214EF
:03004900FFFE7047
:03004A0016530842
:03004B00AC3308CB
:03004C0021A308E5
:03004D0090E30835
:03004E00C20027C6
:03004F00D40800D2
:03005000121C007F
:03005100209039C3
:030052001450380F
:0300530064303FD7
:03005400AC3C07BA
:03005500C22D4079
:0300560002403431
:03005700C00C08D2
:030058000220384B
:0300590020121959
:03005A00030E078B
:03005B00901020E2
:03005C00204360DE
:03005D000303603A
:03005E009013609C
:03005F00202360FB
:03006000030C107E
:03006100901038C4
:03006200C02219A0
:03006300150E0770
:03006400643120E4
:03006500A69C183E
:03006600209038AF
:0300670013E21988
:03006800A6CE0F12
:03006900209022C2
:03006A00FFFC0098
:03006B0017E03863
:03006C0021E2008E
:03006D00035E0728
:03006E00C13CFF93
:03006F000240311B
:03007000C00C18A9
:03007100022A72EE
:0300720020103C1F
:0300730003003057
:03007400901E0FCC
:0300750020403CEC
:03007600030C0276
:03007700901039AD
:03007800202C0039
:0300790003003948
:03007A00901C0FC8
:03007B002100223F
:03007C00027C8083
:03007D00C3C024D9
:03007E00024C0829
:03007F00C00104B9
:0300800002203922
:03008100201C0040
:030082000300393F
:03008300901C00CE
:0300840020403ADF
:0300850003002B4A
:03008600901020B7
:03008700202C0327
:0300880003002C46
:03008900901C4088
:03008A0021003919
:03008B0003B7D9DF
:03008C00787A8BF4
:03008D00A91C406B
:03008E0020903986
:03008F0013F6D98C
:03009000A99A9496
:030091002096F9BD
:0300920015FBB4A7
:03009300643A8F3D
:03009400AC367314
:030095006BBA9CA7
:03009600AC39483A
:03009700209207AD
:030098001BF90E43
:03009900C50C2073
:03009A00039121AE
:03009B00799AC48B
:03009C00A9BC57A5
:03009D0020B0345C
:03009E00D00C4241
:03009F00038021BA
:0300A000219C019F
:0300A100E07121EA
:0300A200348C009B
:0300A30034802284
:0300A400348C0495
:0300A5003480376D
:0300A60003020151
:0300A70021A03263
:0300A8003482158A
:0300A9003480316F
:0300AA003482029B
:0300AB003480306E
:0300AC00D0590127
:0300AD00031C0031
:0300AE00C0003758
:0300AF000326D352
:0300B000033ADB35
:0300B100C70CFF7A
:0300B2000391981F
:0300B300C5015034
:0300B4000391179E
:0300B500C3C022A3
:0300B600030C42F6
:0300B700C0002165
:0300B800031C0422
:0300B90021B0373C
:0300BA000322011D
:0300BB00C0003250
:0300BC00033215F7
:0300BD00C7003148
:0300BE00039202A8
:0300BF00C5003049
:0300C000039901A0
:0300C100C40C006C
:0300C20003903771
:0300C300369ADB8F
:0300C400C01C80DD
:0300C5001FA6F380
:0300C60021C12134
:0300C70009A6B3D4
:0300C800743B077F
:0300C900A1C7D3F9
:0300CA0003AAD0B6
:0300CB00C02C4006
:0300CC00FFF12120
:0300CD0016BC005E
:0300CE00C020222D
:0300CF0023EAD24F
:0300D00074321770
:0300D10012B02248
:0300D20020B20158
:0300D30003803077
:0300D400C449011B
:0300D5000392157E
:0300D600C4003033
:0300D70003990189
:0300D800C0020261
:0300D900023030C2
:0300DA00A8D901A1
:0300DB00ADBC07B2
:0300DC00000D40D4
:0300DD00000034EC
:0300DE000002100D
:0300DF00000024FA
:0300E0000007D343
:0300E100000BAF62
:0300E200000C50BF
:0300E300000039E1
:0300E40000079979
:0300E500000AE42A
:0300E60000021203
:0300E700000030E6
:0300E800000214FF
:0300E900000031E3
:0300EA00000213FE
:0300EB00000032E0
:0300EC00000C08FD
:0300ED00000037D9
:0300EE00000218F5
:0300EF00000036D8
:0300F000000217F4
:0300F100000033D9
:0300F200000C00FF
:0300F300000037D3
:0300F400000C708D
:0300F500000039CF
:0300F600000C50AB
:0300F700000039CD
:0300F800000215EE
:0300F900000030D4
:0300FA00000C00F7
:0300FB00000031D1
:0300FC00000C00F5
:0300FD00000033CD
:0300FE00000204F9
:0300FF00000032CC
:03010000000C7080
:03010100000039C2
:03010200000C509E
:03010300000039C0
:03010400000C40AC
:03010500000039BE
:03010600000BAF3C
:03010700000C05E4
:03010800000024D0
:03010900000216DB
:03010A00000022D0
:03010B00000C07DE
:03010C000001628D
:03010D00000C08DB
:03010E00000122CB
:03010F0000036288
:03011000000703E2
:03011100000B0FD1
:03011200000CE0FE
:0301130000016286
:03011400000201E5
:03011500000030B7
:03011600000901DC
:03011700000204DF
:03011800000030B4
:03011900000901D9
:03011A00000202DE
:03011B00000030B1
:03011C00000901D6
:03011D000007D305
:03011E00000B4192
:03011F00000C0AC7
:03012000000024B8
:03012100000215C4
:03012200000022B8
:03012300000201D6
:03012400000030A8
:03012500000901CD
:03012600000204D0
:03012700000030A5
:03012800000901CA
:03012900000202CF
:03012A00000030A2
:03012B00000901C7
:03012C00000C0ABA
:03012D00000027A8
:03012E00000C4082
:03012F00000121AB
:03013000000C04BC
:03013100000024A7
:03013200000C00BE
:03013300000022A7
:03013400000201C5
:0301350000003097
:03013600000901BC
:03013700000204BF
:0301380000003094
:03013900000901B9
:03013A00000202BE
:03013B0000003091
:03013C00000901B6
:03013D000002E7D6
:03013E00000710A7
:03013F00000B4171
:03014000000B347D
:03014100000C08A7
:0301420000003783
:03014300000C09A4
:0301440000002494
:030145000002189D
:0301460000002294
:03014700000201B2
:0301480000003084
:03014900000901A9
:03014A00000204AC
:03014B0000003081
:03014C00000901A6
:03014D00000202AB
:03014E000000307E
:03014F00000901A3
:030150000002109A
:0301510000002784
:03015200000C0896
:0301530000002485
:030154000002178F
:0301550000002285
:03015600000C009A
:030157000000376E
:03015800000201A1
:0301590000003073
:03015A0000090198
:03015B000002049B
:03015C0000003070
:03015D0000090195
:03015E000002029A
:03015F000000306D
:0301600000090192
:030161000007D3C1
:03016200000B751A
:03016300000C503D
:030164000000395F
:03016500000799F7
:03016600000B6526
:0301670000021281
:0301680000003064
:030169000002147D
:03016A0000003161
:03016B000002137C
:03016C000000325E
:03016D0000020786
:03016E0000003658
:03016F000002107B
:0301700000003359
:03017100000C700F
:0301720000003951
:03017300000C502D
:030174000000394F
:03017500000C0774
:0301760000002462
:030177000002186B
:0301780000002262
:0301790000020180
:03017A0000003052
:03017B0000090177
:03017C000002047A
:03017D000000304F
:03017E0000090174
:03017F0000020279
:030180000000304C
:0301810000090171
:0301820000021068
:0301830000002752
:03018400000C0666
:0301850000002453
:030186000002175D
:0301870000002253
:0301880000020171
:0301890000003043
:03018A0000090168
:03018B000002046B
:03018C0000003040
:03018D0000090165
:03018E000002026A
:03018F000000303D
:0301900000090162
:030191000007D391
:03019200000BA2BD
:0301930000021552
:0301940000003038
:030195000002164F
:0301960000003135
:030197000002075C
:0301980000003331
:0301990000021051
:03019A0000003230
:03019B00000C70E5
:03019C0000003927
:03019D00000C5003
:03019E0000003925
:03019F00000C4011
:0301A00000003923
:0301A100000BAFA1
:0301A200000C0A44
:0301A30000002435
:0301A40000021541
:0301A50000002235
:0301A60000020153
:0301A70000003025
:0301A8000009014A
:0301A9000002044D
:0301AA0000003022
:0301AB0000090147
:0301AC000002024C
:0301AD000000301F
:0301AE0000090144
:0301AF00000C0041
:0301B00000003913
:0301B100000C003F
:0301B200000C003E
:0301B300000A8DB2
:0301B400000C0735
:0301B50000002F18
:0301B600000C0436
:0301B70000002223
:0301B800000C0038
:0301B90000091C1E
:0301BA00000C1026
:0301BB000000221F
:0301BC00000C082C
:0301BD0000091C1A
:0301BE00000C0032
:0301BF0000003A03
:0301C000000C012F
:0301C10000002912
:0301C200000C002E
:0301C30000002F0A
:0301C400000C200C
:0301C50000002314
:0301C600000A002C
:0301C700000BC763
:00000001FF

File diff suppressed because it is too large Load Diff

View File

@@ -94,7 +94,7 @@ if (-t STDERR) {
}
}
logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/201}) {
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/20.}) {
$eeprom_release_201 = 1;
}
$chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",

1170
drivers/dahdi/xpp/init_card_6_30 Executable file

File diff suppressed because it is too large Load Diff

View File

@@ -103,7 +103,6 @@ void __exit parallel_dbg_cleanup(void)
MODULE_DESCRIPTION("Use parallel port to debug drivers");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION("$Id:");
module_init(parallel_dbg_init);
module_exit(parallel_dbg_cleanup);

View File

@@ -244,7 +244,7 @@ int refcount_xbus(xbus_t *xbus)
{
struct kref *kref = &xbus->kref;
return atomic_read(&kref->refcount);
return refcount_read(&kref->refcount);
}
/*------------------------- Frame Handling ------------------------*/
@@ -687,10 +687,56 @@ int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd)
return 0;
}
static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
__u8 numchips, __u8 ports_per_chip, __u8 ports,
__u8 port_dir)
static xpd_type_t xpd_hw2xpd_type(const struct unit_descriptor *unit_descriptor)
{
xpd_type_t xpd_type;
switch (unit_descriptor->type) {
case 1:
case 6:
xpd_type = XPD_TYPE_FXS;
break;
case 2:
xpd_type = XPD_TYPE_FXO;
break;
case 3:
xpd_type = XPD_TYPE_BRI;
break;
case 4:
xpd_type = XPD_TYPE_PRI;
break;
case 5:
xpd_type = XPD_TYPE_ECHO;
break;
case 7:
xpd_type = XPD_TYPE_NOMODULE;
break;
default:
NOTICE("WARNING: xpd hw type is: %d\n", unit_descriptor->type);
xpd_type = XPD_TYPE_NOMODULE;
break;
}
return xpd_type;
}
int subunits_of_xpd(const struct unit_descriptor* unit_descriptor,
const xproto_table_t *proto_table) {
int ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips;
return
(ports + proto_table->ports_per_subunit - 1)
/ proto_table->ports_per_subunit;
}
static int new_card(xbus_t *xbus, const struct unit_descriptor *unit_descriptor)
{
int unit = unit_descriptor->addr.unit;
xpd_type_t xpd_type;
__u8 hw_type;
__u8 numchips;
__u8 ports_per_chip;
__u8 ports;
__u8 port_dir;
const xproto_table_t *proto_table;
int i;
int subunits;
@@ -698,12 +744,19 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
int remaining_ports;
const struct echoops *echoops;
proto_table = xproto_get(type);
/* Translate parameters from "unit_descriptor" */
hw_type = unit_descriptor->type;
numchips = unit_descriptor->numchips;
ports_per_chip = unit_descriptor->ports_per_chip;
port_dir = unit_descriptor->port_dir;
ports = unit_descriptor->ports_per_chip * unit_descriptor->numchips;
xpd_type = xpd_hw2xpd_type(unit_descriptor);
proto_table = xproto_get(xpd_type);
if (!proto_table) {
XBUS_NOTICE(xbus,
"CARD %d: missing protocol table for type %d. "
"CARD %d: missing protocol table for xpd_type %d. "
"Ignored.\n",
unit, type);
unit, xpd_type);
return -EINVAL;
}
echoops = proto_table->echoops;
@@ -711,26 +764,24 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
XBUS_INFO(xbus, "Detected ECHO Canceler (%d)\n", unit);
if (ECHOOPS(xbus)) {
XBUS_NOTICE(xbus,
"CARD %d: tryies to define echoops (type %d) "
"CARD %d: tryies to define echoops (xpd_type %d) "
"but we already have one. Ignored.\n",
unit, type);
unit, xpd_type);
return -EINVAL;
}
xbus->echo_state.echoops = echoops;
xbus->echo_state.xpd_idx = XPD_IDX(unit, 0);
}
remaining_ports = ports;
subunits =
(ports + proto_table->ports_per_subunit -
1) / proto_table->ports_per_subunit;
subunits = subunits_of_xpd(unit_descriptor, proto_table);
XBUS_DBG(DEVICES, xbus,
"CARD %d type=%d.%d ports=%d (%dx%d), "
"CARD %d xpd_type=%d/hw_type=%d ports=%d (%dx%d), "
"%d subunits, port-dir=0x%02X\n",
unit, type, subtype, ports, numchips, ports_per_chip, subunits,
unit, xpd_type, hw_type, ports, numchips, ports_per_chip, subunits,
port_dir);
if (type == XPD_TYPE_PRI || type == XPD_TYPE_BRI)
if (xpd_type == XPD_TYPE_PRI || xpd_type == XPD_TYPE_BRI)
xbus->quirks.has_digital_span = 1;
if (type == XPD_TYPE_FXO)
if (xpd_type == XPD_TYPE_FXO)
xbus->quirks.has_fxo = 1;
xbus->worker.num_units += subunits - 1;
for (i = 0; i < subunits; i++) {
@@ -754,11 +805,10 @@ static int new_card(xbus_t *xbus, int unit, __u8 type, __u8 subtype,
goto out;
}
XBUS_DBG(DEVICES, xbus,
"Creating XPD=%d%d type=%d.%d (%d ports)\n", unit, i,
type, subtype, subunit_ports);
"Creating XPD=%d%d xpd_type=%d.%d hw_type=%d (%d ports)\n", unit, i,
xpd_type, unit_descriptor->subtype, hw_type, subunit_ports);
ret =
create_xpd(xbus, proto_table, unit, i, type, subtype,
subunits, subunit_ports, port_dir);
create_xpd(xbus, proto_table, unit_descriptor, unit, i, xpd_type);
if (ret < 0) {
XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", unit,
i, ret);
@@ -1130,11 +1180,7 @@ void xbus_populate(void *data)
BUG_ON(card_desc->magic != CARD_DESC_MAGIC);
/* Release/Reacquire locks around blocking calls */
spin_unlock_irqrestore(&xbus->worker.worker_lock, flags);
ret =
new_card(xbus, card_desc->xpd_addr.unit, card_desc->type,
card_desc->subtype, card_desc->numchips,
card_desc->ports_per_chip, card_desc->ports,
card_desc->port_dir);
ret = new_card(xbus, &card_desc->unit_descriptor);
spin_lock_irqsave(&xbus->worker.worker_lock, flags);
KZFREE(card_desc);
if (ret)
@@ -1566,7 +1612,6 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
transport_init(xbus, ops, max_send_size, transport_device, priv);
spin_lock_init(&xbus->lock);
init_waitqueue_head(&xbus->command_queue_empty);
init_timer(&xbus->command_timer);
atomic_set(&xbus->pcm_rx_counter, 0);
xbus->min_tx_sync = INT_MAX;
xbus->min_rx_sync = INT_MAX;

View File

@@ -338,6 +338,8 @@ int waitfor_xpds(xbus_t *xbus, char *buf);
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
int subunits_of_xpd(const struct unit_descriptor* unit_descriptor,
const xproto_table_t *proto_table);
/* sysfs */
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
void xpd_device_unregister(xpd_t *xpd);

View File

@@ -353,9 +353,9 @@ static void xpp_set_syncer(xbus_t *xbus, bool on)
(syncer) ? syncer->busname : "NO-SYNC");
}
static void xbus_command_timer(unsigned long param)
static void xbus_command_timer(TIMER_DATA_TYPE timer)
{
xbus_t *xbus = (xbus_t *)param;
xbus_t *xbus = from_timer(xbus, timer, command_timer);
struct timeval now;
BUG_ON(!xbus);
@@ -371,10 +371,9 @@ void xbus_set_command_timer(xbus_t *xbus, bool on)
if (on) {
if (!timer_pending(&xbus->command_timer)) {
XBUS_DBG(SYNC, xbus, "add_timer\n");
xbus->command_timer.function = xbus_command_timer;
xbus->command_timer.data = (unsigned long)xbus;
xbus->command_timer.expires = jiffies + 1;
add_timer(&xbus->command_timer);
timer_setup(&xbus->command_timer,
xbus_command_timer, 0);
mod_timer(&xbus->command_timer, jiffies + 1);
}
} else if (timer_pending(&xbus->command_timer)) {
XBUS_DBG(SYNC, xbus, "del_timer\n");

View File

@@ -339,6 +339,7 @@ static DEVICE_ATTR_READER(dahdi_registration_show, dev, buf)
return len;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
static struct device_attribute xbus_dev_attrs[] = {
__ATTR_RO(connector),
__ATTR_RO(label),
@@ -358,6 +359,39 @@ static struct device_attribute xbus_dev_attrs[] = {
dahdi_registration_store),
__ATTR_NULL,
};
#else
static DEVICE_ATTR_RO(connector);
static DEVICE_ATTR_RO(label);
static DEVICE_ATTR_RO(status);
static DEVICE_ATTR_RO(timing);
static DEVICE_ATTR_RO(refcount_xbus);
static DEVICE_ATTR_RO(waitfor_xpds);
static DEVICE_ATTR_RO(driftinfo);
static DEVICE_ATTR_WO(cls);
static DEVICE_ATTR_RW(xbus_state);
#ifdef SAMPLE_TICKS
static DEVICE_ATTR_RO(samples);
#endif
static DEVICE_ATTR_RW(dahdi_registration);
static struct attribute *xbus_dev_attrs[] = {
&dev_attr_connector.attr,
&dev_attr_label.attr,
&dev_attr_status.attr,
&dev_attr_timing.attr,
&dev_attr_refcount_xbus.attr,
&dev_attr_waitfor_xpds.attr,
&dev_attr_driftinfo.attr,
&dev_attr_cls.attr,
&dev_attr_xbus_state.attr,
#ifdef SAMPLE_TICKS
&dev_attr_samples.attr,
#endif
&dev_attr_dahdi_registration.attr,
NULL,
};
ATTRIBUTE_GROUPS(xbus_dev);
#endif
static int astribank_match(struct device *dev, struct device_driver *driver)
{
@@ -457,7 +491,11 @@ static struct bus_type toplevel_bus_type = {
.name = "astribanks",
.match = astribank_match,
.uevent = astribank_uevent,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
.dev_attrs = xbus_dev_attrs,
#else
.dev_groups = xbus_dev_groups,
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
.drv_attrs = xpp_attrs,
#else
@@ -518,13 +556,25 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
REG_FIELD(regs, data_high));
} else
datah_str[0] = '\0';
if (REG_FIELD(regs, do_subreg)) {
if (regs->h.bytes == REG_CMD_SIZE(RAM)) {
len +=
sprintf(buf + len, "#CH\tOP\tAL\tAH\tD0\tD1\tD2\tD3\n");
len +=
sprintf(buf + len, "%2d\tRR\t%02X\t%02X\t%02X\t%02X\t%02X\t%02X\n",
regs->h.portnum,
REG_FIELD_RAM(regs, addr_low),
REG_FIELD_RAM(regs, addr_high),
REG_FIELD_RAM(regs, data_0),
REG_FIELD_RAM(regs, data_1),
REG_FIELD_RAM(regs, data_2),
REG_FIELD_RAM(regs, data_3));
} else if (REG_FIELD(regs, do_subreg)) {
len +=
sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
(do_datah) ? "\tDH" : "");
len +=
sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
regs->portnum, REG_FIELD(regs, regnum),
regs->h.portnum, REG_FIELD(regs, regnum),
REG_FIELD(regs, subreg), REG_FIELD(regs, data_low),
datah_str);
} else {
@@ -532,7 +582,7 @@ static DEVICE_ATTR_READER(chipregs_show, dev, buf)
sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
(do_datah) ? "\tDH" : "");
len +=
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->portnum,
sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n", regs->h.portnum,
REG_FIELD(regs, regnum), REG_FIELD(regs, data_low),
datah_str);
}
@@ -676,6 +726,19 @@ static DEVICE_ATTR_READER(type_show, dev, buf)
return len;
}
static DEVICE_ATTR_READER(hwid_show, dev, buf)
{
xpd_t *xpd;
int len = 0;
BUG_ON(!dev);
xpd = dev_to_xpd(dev);
if (!xpd)
return -ENODEV;
len += sprintf(buf, "%d.%d\n", XPD_HW(xpd).type, XPD_HW(xpd).subtype);
return len;
}
static DEVICE_ATTR_READER(offhook_show, dev, buf)
{
xpd_t *xpd;
@@ -731,34 +794,63 @@ static int xpd_match(struct device *dev, struct device_driver *driver)
xpd_driver = driver_to_xpd_driver(driver);
xpd = dev_to_xpd(dev);
if (xpd_driver->type != xpd->type) {
if (xpd_driver->xpd_type != xpd->xpd_type) {
XPD_DBG(DEVICES, xpd,
"SYSFS match fail: xpd->type = %d, "
"xpd_driver->type = %d\n",
xpd->type, xpd_driver->type);
"SYSFS match fail: xpd->xpd_type = %d, "
"xpd_driver->xpd_type = %d\n",
xpd->xpd_type, xpd_driver->xpd_type);
return 0;
}
XPD_DBG(DEVICES, xpd,
"SYSFS MATCH: type=%d dev->bus_id = %s, driver->name = %s\n",
xpd->type, dev_name(dev), driver->name);
"SYSFS MATCH: xpd_type=%d dev->bus_id = %s, driver->name = %s\n",
xpd->xpd_type, dev_name(dev), driver->name);
return 1;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
static struct device_attribute xpd_dev_attrs[] = {
__ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
__ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
__ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
__ATTR_RO(type),
__ATTR_RO(hwid),
__ATTR_RO(offhook),
__ATTR_RO(timing_priority),
__ATTR_RO(refcount_xpd),
__ATTR_NULL,
};
#else
static DEVICE_ATTR_RW(chipregs);
static DEVICE_ATTR_RW(blink);
static DEVICE_ATTR_RW(span);
static DEVICE_ATTR_RO(type);
static DEVICE_ATTR_RO(hwid);
static DEVICE_ATTR_RO(offhook);
static DEVICE_ATTR_RO(timing_priority);
static DEVICE_ATTR_RO(refcount_xpd);
static struct attribute *xpd_dev_attrs[] = {
&dev_attr_chipregs.attr,
&dev_attr_blink.attr,
&dev_attr_span.attr,
&dev_attr_type.attr,
&dev_attr_hwid.attr,
&dev_attr_offhook.attr,
&dev_attr_timing_priority.attr,
&dev_attr_refcount_xpd.attr,
NULL,
};
ATTRIBUTE_GROUPS(xpd_dev);
#endif
static struct bus_type xpd_type = {
.name = "xpds",
.match = xpd_match,
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
.dev_attrs = xpd_dev_attrs,
#else
.dev_groups = xpd_dev_groups,
#endif
};
int xpd_driver_register(struct device_driver *driver)
@@ -974,7 +1066,7 @@ void xbus_sysfs_remove(xbus_t *xbus)
return;
}
XBUS_DBG(DEVICES, xbus, "going to unregister: refcount=%d\n",
atomic_read(&astribank->kobj.kref.refcount));
refcount_read(&astribank->kobj.kref.refcount));
BUG_ON(dev_get_drvdata(astribank) != xbus);
device_unregister(astribank);
dev_set_drvdata(astribank, NULL);

View File

@@ -22,8 +22,6 @@
*
*/
#include "xpp_version.h"
#ifdef __KERNEL__
#include <linux/kernel.h>

View File

@@ -78,14 +78,7 @@
struct card_desc_struct {
struct list_head card_list;
u32 magic;
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
__u8 subtype;
struct xpd_addr xpd_addr;
__u8 numchips;
__u8 ports_per_chip;
__u8 ports;
__u8 port_dir;
struct xpd_addr ec_addr; /* echo canceler address */
struct unit_descriptor unit_descriptor;
};
typedef enum xpd_direction {
@@ -174,11 +167,12 @@ struct phonedev {
struct xpd {
char xpdname[XPD_NAMELEN];
struct phonedev phonedev;
struct unit_descriptor unit_descriptor;
#define XPD_HW(xpd) ((xpd)->unit_descriptor)
const struct xops *xops;
xpd_type_t type;
xpd_type_t xpd_type;
const char *type_name;
__u8 subtype;
int subunits; /* all siblings */
enum xpd_state xpd_state;
struct device xpd_dev;
@@ -217,7 +211,7 @@ struct xpd {
#define for_each_line(xpd, i) \
for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
#define IS_BRI(xpd) ((xpd)->xpd_type == XPD_TYPE_BRI)
#define TICK_TOLERANCE 500 /* usec */
#ifdef DEBUG_SYNC_PARPORT
@@ -237,7 +231,7 @@ static inline void *my_kzalloc(size_t size, gfp_t flags)
}
struct xpd_driver {
xpd_type_t type;
xpd_type_t xpd_type;
struct device_driver driver;
#define driver_to_xpd_driver(driver) \

View File

@@ -124,7 +124,7 @@ int refcount_xpd(xpd_t *xpd)
{
struct kref *kref = &xpd->kref;
return atomic_read(&kref->refcount);
return refcount_read(&kref->refcount);
}
xpd_t *get_xpd(const char *msg, xpd_t *xpd)
@@ -216,33 +216,43 @@ EXPORT_SYMBOL(xpd_free);
* Synchronous part of XPD detection.
* Called from new_card()
*/
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
int subunit, __u8 type, __u8 subtype, int subunits,
int subunit_ports, __u8 port_dir)
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int unit,
int subunit, __u8 type)
{
xpd_t *xpd = NULL;
bool to_phone;
BUG_ON(type == XPD_TYPE_NOMODULE);
to_phone = BIT(subunit) & port_dir;
to_phone = BIT(subunit) & unit_descriptor->port_dir;
BUG_ON(!xbus);
xpd = xpd_byaddr(xbus, unit, subunit);
if (xpd) {
XPD_NOTICE(xpd, "XPD at %d%d already exists\n", unit, subunit);
return 0;
}
if (subunit_ports <= 0 || subunit_ports > CHANNELS_PERXPD) {
INFO("%s: [%d.%d] type=%d subtype=%d numchips=%d ports_per_chip=%d ports_dir=%d\n",
__func__,
unit_descriptor->addr.unit,
unit_descriptor->addr.subunit,
unit_descriptor->type,
unit_descriptor->subtype,
unit_descriptor->numchips,
unit_descriptor->ports_per_chip,
unit_descriptor->port_dir);
if (unit_descriptor->ports_per_chip <= 0 || unit_descriptor->ports_per_chip > CHANNELS_PERXPD) {
XBUS_NOTICE(xbus, "Illegal number of ports %d for XPD %d%d\n",
subunit_ports, unit, subunit);
unit_descriptor->ports_per_chip, unit, subunit);
return 0;
}
xpd =
proto_table->xops->card_new(xbus, unit, subunit, proto_table,
subtype, subunits, subunit_ports,
unit_descriptor,
to_phone);
if (!xpd) {
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
unit, subunit, proto_table->type, subtype,
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d) failed. Ignored.\n",
unit, subunit, proto_table->type,
to_phone);
return -EINVAL;
}
@@ -279,7 +289,8 @@ static int xpd_read_proc_show(struct seq_file *sfile, void *data)
seq_printf(sfile, "Address: U=%d S=%d\n", xpd->addr.unit,
xpd->addr.subunit);
seq_printf(sfile, "Subunits: %d\n", xpd->subunits);
seq_printf(sfile, "Type: %d.%d\n\n", xpd->type, xpd->subtype);
seq_printf(sfile, "Type: %d.%d\n", xpd->xpd_type, XPD_HW(xpd).subtype);
seq_printf(sfile, "Hardware type: %d.%d\nn", XPD_HW(xpd).type, XPD_HW(xpd).subtype);
seq_printf(sfile, "pcm_len=%d\n\n", PHONEDEV(xpd).pcm_len);
seq_printf(sfile, "wanted_pcm_mask=0x%04X\n\n",
PHONEDEV(xpd).wanted_pcm_mask);
@@ -529,8 +540,10 @@ err:
*
*/
__must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
int subtype, int subunits, size_t privsize,
const xproto_table_t *proto_table, int channels)
size_t privsize,
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int channels)
{
xpd_t *xpd = NULL;
size_t alloc_size = sizeof(xpd_t) + privsize;
@@ -554,12 +567,12 @@ __must_check xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
xpd->priv = (__u8 *)xpd + sizeof(xpd_t);
spin_lock_init(&xpd->lock);
xpd->card_present = 0;
xpd->type = proto_table->type;
xpd->xpd_type = proto_table->type;
xpd->xproto = proto_table;
xpd->unit_descriptor = *unit_descriptor;
xpd->xops = proto_table->xops;
xpd->xpd_state = XPD_STATE_START;
xpd->subtype = subtype;
xpd->subunits = subunits;
xpd->subunits = subunits_of_xpd(unit_descriptor, proto_table);
kref_init(&xpd->kref);
/* For USB-1 disable some channels */
@@ -949,13 +962,13 @@ const char *xpp_echocan_name(const struct dahdi_chan *chan)
* quirks and limitations
*/
if (xbus->quirks.has_fxo) {
if (xbus->quirks.has_digital_span && xpd->type == XPD_TYPE_FXO) {
if (xbus->quirks.has_digital_span && xpd->xpd_type == XPD_TYPE_FXO) {
LINE_NOTICE(xpd, pos,
"quirk: give up HWEC on FXO: "
"AB has digital span\n");
return NULL;
} else if (xbus->sync_mode != SYNC_MODE_AB
&& xpd->type == XPD_TYPE_FXS) {
&& xpd->xpd_type == XPD_TYPE_FXS) {
LINE_NOTICE(xpd, pos,
"quirk: give up HWEC on FXS: "
"AB has FXO and is sync slave\n");
@@ -1007,6 +1020,8 @@ void xpp_span_assigned(struct dahdi_span *span)
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
dahdi_alarm_notify(&phonedev->span);
}
if (PHONE_METHOD(span_assigned, xpd))
CALL_PHONE_METHOD(span_assigned, xpd);
}
EXPORT_SYMBOL(xpp_span_assigned);
@@ -1183,8 +1198,7 @@ static int __init xpp_dahdi_init(void)
int ret = 0;
void *top = NULL;
INFO("revision %s MAX_XPDS=%d (%d*%d)\n", XPP_VERSION, MAX_XPDS,
MAX_UNIT, MAX_SUBUNIT);
INFO("MAX_XPDS=%d (%d*%d)\n", MAX_XPDS, MAX_UNIT, MAX_SUBUNIT);
#ifdef CONFIG_PROC_FS
xpp_proc_toplevel = proc_mkdir(PROC_DIR, NULL);
if (!xpp_proc_toplevel) {
@@ -1220,7 +1234,6 @@ static void __exit xpp_dahdi_cleanup(void)
MODULE_DESCRIPTION("XPP Dahdi Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
module_init(xpp_dahdi_init);
module_exit(xpp_dahdi_cleanup);

View File

@@ -30,11 +30,13 @@ int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
int xpd_dahdi_postregister(xpd_t *xpd);
void xpd_dahdi_preunregister(xpd_t *xpd);
void xpd_dahdi_postunregister(xpd_t *xpd);
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
int subunit, __u8 type, __u8 subtype, int subunits,
int subunit_ports, __u8 port_dir);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits,
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int unit,
int subunit, __u8 type);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit,
size_t privsize, const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
int channels);
void xpd_free(xpd_t *xpd);
void xpd_remove(xpd_t *xpd);

View File

@@ -49,7 +49,9 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
static DEF_PARM(int, usb1, 0, 0644, "Allow using USB 1.1 interfaces");
static DEF_PARM(uint, tx_sluggish, 2000, 0644, "A sluggish transmit (usec)");
static DEF_PARM(uint, drop_pcm_after, 6, 0644,
"Number of consecutive tx_sluggish to drop a PCM frame");
"Number of consecutive tx_sluggish to start dropping PCM");
static DEF_PARM(uint, sluggish_pcm_keepalive, 50, 0644,
"During sluggish -- Keep-alive PCM (1 every #)");
#include "dahdi_debug.h"
@@ -117,6 +119,8 @@ enum {
XUSB_N_TX_FRAMES,
XUSB_N_RX_ERRORS,
XUSB_N_TX_ERRORS,
XUSB_N_RX_DROPS,
XUSB_N_TX_DROPS,
XUSB_N_RCV_ZERO_LEN,
};
@@ -127,8 +131,14 @@ enum {
static struct xusb_counters {
char *name;
} xusb_counters[] = {
C_(RX_FRAMES), C_(TX_FRAMES), C_(RX_ERRORS), C_(TX_ERRORS),
C_(RCV_ZERO_LEN),};
C_(RX_FRAMES),
C_(TX_FRAMES),
C_(RX_ERRORS),
C_(TX_ERRORS),
C_(RX_DROPS),
C_(TX_DROPS),
C_(RCV_ZERO_LEN),
};
#undef C_
@@ -194,8 +204,7 @@ struct xusb {
unsigned int max_tx_delay;
uint usb_tx_delay[NUM_BUCKETS];
uint sluggish_debounce;
bool drop_next_pcm; /* due to sluggishness */
atomic_t pcm_tx_drops;
bool drop_pcm; /* due to sluggishness */
atomic_t usb_sluggish_count;
const char *manufacturer;
@@ -400,12 +409,23 @@ static int xframe_send_pcm(xbus_t *xbus, xframe_t *xframe)
BUG_ON(!xframe);
xusb = xusb_of(xbus);
BUG_ON(!xusb);
if (xusb->drop_next_pcm) {
FREE_SEND_XFRAME(xbus, xframe); /* return to pool */
xusb->drop_next_pcm = 0;
return -EIO;
if (xusb->drop_pcm) {
static int rate_limit;
if ((rate_limit++ % 1000) == 0)
XUSB_ERR(xusb, "Sluggish USB: drop tx-pcm (%d)\n",
rate_limit);
/* Let trickle of TX-PCM, so Astribank will not reset */
if (sluggish_pcm_keepalive &&
((rate_limit % sluggish_pcm_keepalive) != 0)) {
XUSB_COUNTER(xusb, TX_DROPS)++;
goto err;
}
}
return do_send_xframe(xbus, xframe);
err:
FREE_SEND_XFRAME(xbus, xframe); /* return to pool */
return -EIO;
}
/*
@@ -674,7 +694,6 @@ static int xusb_probe(struct usb_interface *interface,
sema_init(&xusb->sem, 1);
atomic_set(&xusb->pending_writes, 0);
atomic_set(&xusb->pending_reads, 0);
atomic_set(&xusb->pcm_tx_drops, 0);
atomic_set(&xusb->usb_sluggish_count, 0);
xusb->udev = udev;
xusb->interface = interface;
@@ -871,6 +890,8 @@ static void xpp_send_callback(USB_PASS_CB(urb))
do_gettimeofday(&now);
xusb->last_tx = xframe->tv_submitted;
usec = usec_diff(&now, &xframe->tv_submitted);
if (usec < 0)
usec = 0; /* System clock jumped */
if (usec > xusb->max_tx_delay)
xusb->max_tx_delay = usec;
i = usec / USEC_BUCKET;
@@ -878,7 +899,6 @@ static void xpp_send_callback(USB_PASS_CB(urb))
i = NUM_BUCKETS - 1;
xusb->usb_tx_delay[i]++;
if (unlikely(usec > tx_sluggish)) {
atomic_inc(&xusb->usb_sluggish_count);
if (xusb->sluggish_debounce++ > drop_pcm_after) {
static int rate_limit;
@@ -888,12 +908,14 @@ static void xpp_send_callback(USB_PASS_CB(urb))
"Sluggish USB. Dropping next PCM frame "
"(pending_writes=%d)\n",
writes);
atomic_inc(&xusb->pcm_tx_drops);
xusb->drop_next_pcm = 1;
atomic_inc(&xusb->usb_sluggish_count);
xusb->drop_pcm = 1;
xusb->sluggish_debounce = 0;
}
} else
} else {
xusb->sluggish_debounce = 0;
xusb->drop_pcm = 0;
}
/* sync/async unlink faults aren't errors */
if (urb->status
&& !(urb->status == -ENOENT || urb->status == -ECONNRESET)) {
@@ -956,6 +978,26 @@ static void xpp_receive_callback(USB_PASS_CB(urb))
// if (debug)
// dump_xframe("USB_FRAME_RECEIVE", xbus, xframe, debug);
XUSB_COUNTER(xusb, RX_FRAMES)++;
if (xusb->drop_pcm) {
/* some protocol analysis */
static int rate_limit;
xpacket_t *pack = (xpacket_t *)(xframe->packets);
bool is_pcm = XPACKET_IS_PCM(pack);
if (is_pcm) {
if ((rate_limit++ % 1000) == 0)
XUSB_ERR(xusb,
"Sluggish USB: drop rx-pcm (%d)\n",
rate_limit);
/* Let trickle of RX-PCM, so Astribank will not reset */
if (sluggish_pcm_keepalive &&
((rate_limit % sluggish_pcm_keepalive)
!= 0)) {
XUSB_COUNTER(xusb, RX_DROPS)++;
goto err;
}
}
}
/* Send UP */
xbus_receive_xframe(xbus, xframe);
end:
@@ -982,7 +1024,6 @@ static int __init xpp_usb_init(void)
int ret;
//xusb_t *xusb;
INFO("revision %s\n", XPP_VERSION);
xusb_cache =
kmem_cache_create("xusb_cache", sizeof(xframe_t) + XFRAME_DATASIZE,
#if (LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 22)) && defined(CONFIG_SLUB)
@@ -1061,17 +1102,16 @@ static int xusb_read_proc_show(struct seq_file *sfile, void *data)
stamp_last_pcm_read, accumulate_diff);
#endif
memcpy(usb_tx_delay, xusb->usb_tx_delay, sizeof(usb_tx_delay));
seq_printf(sfile, "usb_tx_delay[%d,%d,%d]: ", USEC_BUCKET,
BUCKET_START, NUM_BUCKETS);
seq_printf(sfile, "usb_tx_delay[%dus - %dus]: ",
USEC_BUCKET * BUCKET_START,
USEC_BUCKET * NUM_BUCKETS);
for (i = BUCKET_START; i < NUM_BUCKETS; i++) {
seq_printf(sfile, "%6d ", usb_tx_delay[i]);
if (i == mark_limit)
seq_printf(sfile, "| ");
}
seq_printf(sfile, "\nPCM_TX_DROPS: %5d (sluggish: %d)\n",
atomic_read(&xusb->pcm_tx_drops),
atomic_read(&xusb->usb_sluggish_count)
);
seq_printf(sfile, "\nSluggish events: %d\n",
atomic_read(&xusb->usb_sluggish_count));
seq_printf(sfile, "\nCOUNTERS:\n");
for (i = 0; i < XUSB_COUNTER_MAX; i++) {
seq_printf(sfile, "\t%-15s = %d\n", xusb_counters[i].name,
@@ -1103,7 +1143,6 @@ static const struct file_operations xusb_read_proc_ops = {
MODULE_DESCRIPTION("XPP USB Transport Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");
MODULE_LICENSE("GPL");
MODULE_VERSION(XPP_VERSION);
module_init(xpp_usb_init);
module_exit(xpp_usb_shutdown);

View File

@@ -191,20 +191,20 @@ static int packet_process(xbus_t *xbus, xpacket_t *pack)
}
goto out;
}
xtable = xproto_table(xpd->type);
xtable = xproto_table(xpd->xpd_type);
if (!xtable) {
if (printk_ratelimit())
XPD_ERR(xpd,
"%s: no protocol table (type=%d)\n",
__func__, xpd->type);
"%s: no protocol table (xpd_type=%d)\n",
__func__, xpd->xpd_type);
goto out;
}
xe = xproto_card_entry(xtable, op);
if (!xe) {
if (printk_ratelimit()) {
XPD_NOTICE(xpd,
"%s: bad command (type=%d,opcode=0x%x)\n",
__func__, xpd->type, op);
"%s: bad command (xpd_type=%d,opcode=0x%x)\n",
__func__, xpd->xpd_type, op);
dump_packet("packet_process -- bad command",
pack, 1);
}
@@ -381,17 +381,36 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
char data_buf[MAX_PROC_WRITE];
/* The size byte is not included */
if (regcmd->bytes > sizeof(*regcmd) - 1) {
if (regcmd->h.bytes > sizeof(*regcmd) - 1) {
PORT_NOTICE(xbus, unit, port,
"%s: %s: Too long: regcmd->bytes = %d\n", __func__,
msg, regcmd->bytes);
msg, regcmd->h.bytes);
return;
}
if (regcmd->is_multibyte) {
if (regcmd->h.bytes == REG_CMD_SIZE(RAM)) {
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum,
(REG_FIELD_RAM(regcmd, all_ports_broadcast)) ? "*" : "");
if (REG_FIELD_RAM(regcmd, read_request)) {
action = 'R';
} else {
action = 'W';
}
PORT_DBG(REGS, xbus, unit, port,
"%s: %s %cR %02X %02X %02X %02X %02X %02X\n",
msg, port_buf, action,
REG_FIELD_RAM(regcmd, addr_low),
REG_FIELD_RAM(regcmd, addr_high),
REG_FIELD_RAM(regcmd, data_0),
REG_FIELD_RAM(regcmd, data_1),
REG_FIELD_RAM(regcmd, data_2),
REG_FIELD_RAM(regcmd, data_3));
return;
}
if (regcmd->h.is_multibyte) {
char buf[MAX_PROC_WRITE + 1];
int i;
int n = 0;
size_t len = regcmd->bytes;
size_t len = regcmd->h.bytes;
const __u8 *p = REG_XDATA(regcmd);
buf[0] = '\0';
@@ -401,18 +420,18 @@ void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
PORT_DBG(REGS, xbus, unit, port,
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) "
"%s[0..%zd]: %s%s\n",
unit, port, regcmd->eoframe, msg, len - 1, buf,
unit, port, regcmd->h.eoframe, msg, len - 1, buf,
(n >= MAX_PROC_WRITE) ? "..." : "");
return;
}
/* The size byte is not included */
if (regcmd->bytes != sizeof(*regcmd) - 1) {
if (regcmd->h.bytes != REG_CMD_SIZE(REG)) {
PORT_NOTICE(xbus, unit, port,
"%s: %s: Wrong size: regcmd->bytes = %d\n",
__func__, msg, regcmd->bytes);
__func__, msg, regcmd->h.bytes);
return;
}
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->portnum,
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->h.portnum,
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
modifier = 'D';

View File

@@ -34,6 +34,8 @@
*/
#define XPP_PROTOCOL_VERSION 30
struct unit_descriptor;
struct xpd_addr {
uint8_t subunit:SUBUNIT_BITS;
uint8_t reserved:1;
@@ -127,7 +129,6 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
#define XENTRY(prototab, module, op) \
[ XPROTO_NAME(module, op) ] = { \
.handler = XPROTO_HANDLER(module, op), \
.datalen = RPACKET_SIZE(module, op), \
.name = #op, \
.table = &PROTO_TABLE(prototab) \
}
@@ -167,35 +168,84 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
typedef struct reg_cmd {
struct reg_cmd_header {
__u8 bytes:3; /* Length (for Multibyte) */
__u8 eoframe:1; /* For BRI -- end of frame */
__u8 portnum:3; /* For port specific registers */
__u8 is_multibyte:1;
} PACKED;
struct reg_cmd_REG {
__u8 reserved:3;
__u8 do_expander:1;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 regnum;
__u8 subreg;
__u8 data_low;
__u8 data_high;
} PACKED;
struct reg_cmd_RAM {
__u8 reserved:4;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 addr_low;
__u8 addr_high;
__u8 data_0;
__u8 data_1;
__u8 data_2;
__u8 data_3;
} PACKED;
typedef struct reg_cmd {
struct reg_cmd_header h;
union {
struct {
__u8 reserved:4;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 regnum;
__u8 subreg;
__u8 data_low;
__u8 data_high;
} PACKED r;
struct reg_cmd_REG r;
/* For Write-Multibyte commands in BRI */
struct {
__u8 xdata[MULTIBYTE_MAX_LEN];
} PACKED d;
struct reg_cmd_RAM m;
} PACKED alt;
} PACKED reg_cmd_t;
/* Shortcut access macros */
#define REG_CMD_SIZE(variant) (sizeof(struct reg_cmd_ ## variant))
#define REG_FIELD(regptr, member) ((regptr)->alt.r.member)
#define REG_XDATA(regptr) ((regptr)->alt.d.xdata)
#define REG_FIELD_RAM(regptr, member) ((regptr)->alt.m.member)
#ifdef __KERNEL__
#define XFRAME_CMD_LEN(variant) \
( \
sizeof(struct xpacket_header) + \
sizeof(struct reg_cmd_header) + \
sizeof(struct reg_cmd_ ## variant) \
)
#define XFRAME_NEW_REG_CMD(frm, p, xbus, card, variant, to) \
do { \
int pack_len = XFRAME_CMD_LEN(variant); \
\
if (!XBUS_FLAGS(xbus, CONNECTED)) \
return -ENODEV; \
(frm) = ALLOC_SEND_XFRAME(xbus); \
if (!(frm)) \
return -ENOMEM; \
(p) = xframe_next_packet(frm, pack_len); \
if (!(p)) \
return -ENOMEM; \
XPACKET_INIT(p, card, REGISTER_REQUEST, to, 0, 0); \
XPACKET_LEN(p) = pack_len; \
(frm)->usec_towait = 0; \
} while (0)
/*----------------- protocol tables ----------------------------------*/
typedef struct xproto_entry xproto_entry_t;
@@ -245,12 +295,14 @@ struct phoneops {
int (*card_open) (xpd_t *xpd, lineno_t pos);
int (*card_close) (xpd_t *xpd, lineno_t pos);
int (*card_state) (xpd_t *xpd, bool on);
int (*span_assigned) (xpd_t *xpd);
};
struct xops {
xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone);
const xproto_table_t *proto_table,
const struct unit_descriptor *unit_descriptor,
bool to_phone);
int (*card_init) (xbus_t *xbus, xpd_t *xpd);
int (*card_remove) (xbus_t *xbus, xpd_t *xpd);
int (*card_tick) (xbus_t *xbus, xpd_t *xpd);
@@ -259,7 +311,6 @@ struct xops {
struct xproto_entry {
xproto_handler_t handler;
int datalen;
const char *name;
xproto_table_t *table;
};

View File

@@ -1404,6 +1404,35 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
/*! Maximum audio mask */
#define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 15, 0)
#ifndef TIMER_DATA_TYPE
#define TIMER_DATA_TYPE unsigned long
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
/**
* timer_setup - Added in 4.13.0. We can make a direct translation to the
* setup_timer interface since DAHDI does not pass any flags to any of the
* timer_setup functions.
*
*/
static inline void
timer_setup(struct timer_list *timer,
void (*timer_callback)(TIMER_DATA_TYPE data),
unsigned long flags)
{
WARN_ON(flags != 0);
setup_timer(timer, timer_callback, (TIMER_DATA_TYPE)timer);
}
#define from_timer(var, callback_timer, timer_fieldname) \
container_of((struct timer_list *)(callback_timer), \
typeof(*var), timer_fieldname)
#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0)
#define refcount_read atomic_read
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0)
/* DAHDI only was using the xxx_clear_bit variants. */
@@ -1533,6 +1562,15 @@ static inline int strcasecmp(const char *s1, const char *s2)
#endif /* 2.6.31 */
#endif /* 3.10.0 */
#endif /* 3.16.0 */
#endif /* 4.11.0 */
#endif /* 4.13.0 */
#else /* >= 4.15.0 */
#ifndef TIMER_DATA_TYPE
#define TIMER_DATA_TYPE struct timer_list *
#endif
#endif /* 4.15.0 */
#ifndef DEFINE_SPINLOCK
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED