Compare commits

...

82 Commits

Author SHA1 Message Date
Tzafrir Cohen
fdca6f36de sysfs: registration_time: use ktime_get_ts
A fix to 03b3ce1a10: use ktime_get_ts
instead of getnstimeofday to better handle system time changes.
(Shaun Ruffell)

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2014-01-28 20:39:21 +02:00
Tzafrir Cohen
02f6b4e7bd README: The sysfs class now includes no channels
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2014-01-28 20:24:40 +02:00
Tzafrir Cohen
701ed41adf README: the new registration_time device attribute
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2014-01-28 20:17:26 +02:00
Oron Peled
03b3ce1a10 sysfs: new device attribute: registration_time
Add a new sysfs attribute to dahdi_device: registration_time

* Records the time of the device's registration with DAHDI.
* Used by dahdi_auto_assign_compat to assign spans by device
  registration order when backward compatibility needed.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
2014-01-28 20:04:22 +02:00
Tzafrir Cohen
2c4373972b README: xpp.dahdi_autoreg is deprecated
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-28 19:27:05 +02:00
Oron Peled
2ecf700dd8 xpp: continue xpp.dahdi_autoreg deprecation
* Set it to 0 by default (as we use dahdi.auto_assign_spans now)
* Make it readonly (no runtime changes)
* Warn during startup if it was forced to 1

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-28 19:24:27 +02:00
Oron Peled
74e949c33a xpp: deprecate dahdi_autoreg
Instead, use the inverse of dahdi.auto_assign_spans value.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-28 19:24:15 +02:00
Russ Meyerriecks
3efa9d8cd1 wcte13xp: wcxb: Add delayed reset firmware feature
Allow certain older firmwares to delay the hard reset until a full power cycle.
This way we can "preload" newer firmware images, without requiring the user to
physically power off/on their machine.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>
2014-01-24 13:14:14 -06:00
Shaun Ruffell
4cd09feb54 wcte43x, wcte13xp, wcaxx: Bump irqmisses counter when there are DMA underruns.
This makes the behavior of IRQ misses for these drivers behave the same as the
wcte12xp, wctdm24xxp, and wct4xxp drivers.

Previously irqmisses would never increase. The presence of underruns would still
show up in dmesg as latency bumps.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 18:04:47 -06:00
Shaun Ruffell
1f024713ed wct4xxp: Trivial drop of unnecessary local variables.
These were left over from when the VPM callbacks depended on the different VPM
installed. On the wcte43x this is unnecessary.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 18:04:47 -06:00
Shaun Ruffell
0b499d9566 wcte43x: Trivial drop of unnecessary local variables.
These were left over from when the VPM callbacks depended on the different VPM
installed. On the wcte43x this is unnecessary.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 18:04:47 -06:00
Russ Meyerriecks
438b2a36b3 wcte13xp: wcaxx: wcte43x: Remove VPM_SUPPORT compile option.
This was a legacy compile time option that is no longer necessary with the new
series of cards.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-22 13:40:27 -06:00
Russ Meyerriecks
be94aa11bb Revert "dahdi: Change auto_assign_spans default from 1 to 0."
This reverts commit c49a56c954.

Delaying this feature until after v2.9 release.
2014-01-21 16:36:44 -06:00
Russ Meyerriecks
1add33efe7 wcte13xp: Add support for te131 and te132 products
These are similar to te133 and te134 but without integrated echo cancel.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-17 15:43:06 -06:00
Russ Meyerriecks
094e30483d wcte13xp: Update firmware to 0x780017
This firmware adds support for the te131 and te132 products.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-17 15:33:25 -06:00
Russ Meyerriecks
e4ea886ee0 wcte13xp: wcaxx: Fix broken devicetype attributes
struct dahdi_device.devicetype was set incorrectly in both drivers. This caused
the vpm module to not show up after the device name when reading this field
from a spanstat.

Reported-by: Charles Moye <cmoye@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-17 15:30:38 -06:00
Shaun Ruffell
860eb4ab48 dahdi: Do not access invalid memory if invalid local span number is passed to spantype attribute.
This fixes potential kernel panic due to accessing invalid memory if passing
invalid local span number to 'spantype' attribute via sysfs.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2014-01-14 16:03:18 -06:00
Shaun Ruffell
47dcc9377c wcte43x, wcte13xp: Use MSI interrupts if possible.
It was an oversight to prevent the wcte43x and wcte13xp drivers from using
Message Signaled interrupts during the switch to the wcxb library.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-08 12:21:10 -06:00
Shaun Ruffell
f10eb3f547 wcte13xp: Export max_latency module parameter.
wcte13xp now has a max_latency module parameter like the wcaxx and wcte43x
drivers.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-08 12:21:10 -06:00
Shaun Ruffell
99de304d84 wcaxx, wcte13xp, wcte43x: Honor max_latency module parameter.
The wcxb library did not do actually use the max_latency member to limit the
maximum latency of the DMA engine.

Now it does.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2014-01-08 12:21:10 -06:00
Shaun Ruffell
c49a56c954 dahdi: Change auto_assign_spans default from 1 to 0.
The infrastructure has been put in place in 2.8.0 for fully dynamic device and
span configuration. This will be the default mode in DAHDI-Linux 2.9.0.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Acked-by: Oron Peled <oron.peled@xorcom.com>
2014-01-06 13:24:28 -06:00
Shaun Ruffell
e6b16eace1 dahdi: Move clearing of DAHDI_ALARM_NOTOPEN to __dahdi_assign_span().
Previously this was in __dahdi_init_span(). The problem was that
__dahdi_init_span() was only called when a spans' line mode was being changed.
Therefore it was possible to unassign and resassign an analog span and leave it
stuck in the 'NOP' alarm state.

It also make the setting / clearing of DAHDI_ALARM_NOTOPEN symetrical about span
unassignment / assignment in addition to updating the alarm states on all the
channels on the span via the dahdi_alarm_notify() function.

This is a better version of commit 496f817773.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-26 17:04:29 -06:00
Shaun Ruffell
3933ffd350 wctdm24xxp: Reset module specific type information on probe.
This fixes an issue that affects TDM410 modules when there is not a module
installed in the first port, but there is an FXO module installed in the third
port.

When scaning for QRV modules in the first port, the 3rd port will have the
'hook' struct.qrv set to 0xff. When a QRV module is  not detected, that value
will be left, which then maps to an invalid state for both fxo.ring_state and
fxo.battery_state.

The result would be that FXO ports would fail to run the ring detector state
machine since it did not know what the current state was.

Now we'll just reset all the values in struct fxo or struct fxs to the expected
init state.

Internal-Issue-ID: DAHLIN-332
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-20 14:15:26 -06:00
Russ Meyerriecks
05bf6ac601 wcte13xp: Fix bug preventing recover timing from ever being set
A bug introduced in v2.8.0 prevented the recover timing configuration from
being set properly on the hardware. This caused the card to never go into
recovered timing mode.

Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-18 18:15:21 -06:00
Shaun Ruffell
d536c3e203 build_tools/dkms-helper: Helper script for DKMS integration.
DKMS (Dynamic Kernel Module Support) [1] provides a mechanism where kernel
modules can be automatically updated when a new kernel is booted.  This is a
simple helper script to automate the process of adding dahdi-linux to the local
DKMS system.

[1] http://linux.dell.com/dkms/

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-12-12 16:08:43 -06:00
Shaun Ruffell
2e7acd212e xpp: Replace drv_attrs with drv_groups on kernels > 3.12
drv_attrs was fully removed from the bus structure in upstream commit
e18945b159a1cdbc031f1d3b0b7e515a33bdcbf7 which was merged into 3.13.

This is necessary to compile against linux kernel version 3.13.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-12-06 15:42:46 -06:00
Shaun Ruffell
71c003ba49 dahdi: Fix previous CentOS 6.5 commit.
The previous commit from earlier today to fix the backport of PDE_DATA was
wrong in that it would not then process the other defines for older kernels if
it detected it was running on a redhat release.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-02 16:51:06 -06:00
Shaun Ruffell
3707ee713e Revert "wcaxx: Use startup/shutdown callbacks to protect access to channel registers."
This reverts commit 1cf7d9b08c.

It turns out this change was not necessary.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-02 16:23:58 -06:00
Shaun Ruffell
f5d3b35d7b dahdi: Replace drv_attr with drv_groups on kernels > 3.12.
drv_attrs was fully removed from the bus structure in upstream commit
e18945b159a1cdbc031f1d3b0b7e515a33bdcbf7 which was merged into 3.13.

This is necessary to compile dahdi against linux version 3.13.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-02 15:47:56 -06:00
Shaun Ruffell
6bcc70a421 wcte43x: Update firmware to version e0017.
This resolves issues where, when using internal timing, the first channel of
span 3 has occassional corrupted data in transmit stream.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-02 15:46:39 -06:00
Shaun Ruffell
d389f9f743 wcaxx: Add extra dummy read when checking for single fxs modules.
This extra read eliminates some problems with detecting certain S100M modules.
It is unclear at this time why it is necessary.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-02 15:46:39 -06:00
Shaun Ruffell
0faac26dde wcxb: Do not access cur_transfer/cur_msg outside of lock.
The spi master cur_transfer and cur_msg should only be changed under the
spin_lock for the master. The result is that if running user space tools, like
fxstest, that check registers on the modules, it's possible to have a message
that was not yet complete flagged as completed which would result in a bad read.

This does not affect "normal" operation of the wcaxx driver since interrupts are
not enabled during module detection, and during normal operation all access to
the resgisters is done in the context of the interrupt handler. This would only
be an issue if the interrupt handler was running and register accesses are tried
in user space context on an SMP system.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-02 15:46:39 -06:00
Oron Peled
d803fad133 Makefile: new 'make-dist' target
Creates a tar.gz:
* Identical results to the existing distributed tarballs
* Named "dahdi-linux-<version>.tar.gz"
* Only from committed files (uses git-archive)
* Adds a .version file

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-12-02 22:59:00 +02:00
Shaun Ruffell
acfec5dfbb wcxb: is_pcie -> pci_is_pcie()
is_pcie attribute was finally dropped from struct pci_dev in
upstream commit 115e3bc5e23e7ec3c85a2014bfa96c0ddd036083.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-01 22:44:09 -06:00
Shaun Ruffell
5ec9d756aa dahdi: CentOS 6.5 backported PDE_DATA definition.
This will fix the "error: redefinition of 'PDE_DATA'" error when compiling.

Internal-Issue-ID: DAHLIN-330
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-12-01 19:57:44 -06:00
Shaun Ruffell
4bfdd8bea5 dahdi: Remove "ddev" symlink before unregistering the span device.
This makes the order of operations for device removal symmetrical with those for
device addition. This change also eliminates the following warning when
unloading dahdi after dynamic spans have been created:

  ------------[ cut here ]------------
  WARNING: at /build/buildd/linux-3.2.0/fs/sysfs/inode.c:324 sysfs_hash_and_remove+0x92/0xa0()
  Hardware name: VirtualBox
  sysfs: can not remove 'ddev', no directory
  Modules linked in: dahdi_dynamic_loc(O-) dahdi_dynamic(O) dahdi(O) crc_ccitt
     hdlc_cisco hdlc vboxvideo(O) drm vboxsf(O) vesafb ppdev psmouse parport_pc
     serio_raw mac_hid vboxguest(O) nfsd nfs i2c_piix4 lockd fscache auth_rpcgss
     nfs_acl sunrpc ext2 lp parport e1000 [last unloaded: dahdi]
  Pid: 3533, comm: rmmod Tainted: G        W  O 3.2.0-56-generic-pae #86-Ubuntu
  Call Trace:
   [<c105ab42>] warn_slowpath_common+0x72/0xa0
   [<c11a7992>] ? sysfs_hash_and_remove+0x92/0xa0
   [<c11a7992>] ? sysfs_hash_and_remove+0x92/0xa0
   [<c105ac13>] warn_slowpath_fmt+0x33/0x40
   [<c11a7992>] sysfs_hash_and_remove+0x92/0xa0
   [<c1385427>] ? device_del+0x127/0x150
   [<c11a9bd0>] sysfs_remove_link+0x20/0x30
   [<d8a03fa3>] span_sysfs_remove+0xa3/0x170 [dahdi]
   [<c1036a88>] ? default_spin_lock_flags+0x8/0x10
   [<d89f7e5e>] _dahdi_unassign_span+0xae/0x210 [dahdi]
   [<c1053f6b>] ? __cond_resched+0x1b/0x30
   [<c15a9859>] ? _cond_resched+0x29/0x30
   [<d89f80a3>] dahdi_unregister_device+0xe3/0x190 [dahdi]
   [<d8936464>] dahdi_dynamic_unregister_driver+0x84/0x130 [dahdi_dynamic]
   [<d89284ed>] dahdi_dynamic_local_exit+0xd/0xb20 [dahdi_dynamic_loc]
   [<c1095995>] sys_delete_module+0x135/0x230
   [<c1110063>] ? pagetypeinfo_show.part.8+0x33/0x100
   [<c15b295f>] sysenter_do_call+0x12/0x28
  ---[ end trace b818e326720c8385 ]---

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-29 15:42:07 -06:00
Shaun Ruffell
c0d52a04cb wctdm24xxp: Remove assigned callback.
For the spans exported by the wctdm24xxp, the channels are not going to change
after they are already registered.

This eliminates a problem when analog spans are unassigned/reassigned and the
not_ready goes negative, thereby causing many warnings in the kernel.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-26 10:49:58 -06:00
Shaun Ruffell
1cf7d9b08c wcaxx: Use startup/shutdown callbacks to protect access to channel registers.
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-25 16:19:28 -06:00
Shaun Ruffell
3a0905b1ec dahdi_dynamic: Create a span type for dynamic spans.
Fixes the following warning when loading the driver:

  dahdi: Warning: Span DYN/eth/eth1/00:50:c2:97:92:1d/1 didn't specify a spantype. Please fix driver!

The spantype is intended to be used by the auto configuration tools
(dahdi_genconf, pinned spans, etc..) but dynamic spans, since they are created
directly by dahdi_cfg, never take part in the pre-registration auto
configuration, therefore the span type was never used.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-24 10:09:33 -06:00
Shaun Ruffell
4a75f58156 oct612x: Make dependent on dahdi.ko
This change will ensure that the oct612x module is unloaded automatically when
/etc/init.d/dahdi stop is run.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-24 10:09:33 -06:00
Tzafrir Cohen
2b20289cb7 Ignore some more firmware files
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-11-24 17:22:39 +02:00
Oron Peled
dd944f3362 sysfs: new driver attribute: master_span
* This changeset adds master_span as an attribute of the span's driver:
  /sys/bus/dahdi_spans/drivers/generic_lowlevel/master_span
* This is mainly used for debugging.
* Reading from it the master span number (or 0 if there is no master
  span).
* Writing a number to it, force specified span to be master
* Existing Alternatives:
  - grep "MASTER" from /proc/dahdi/*
  - cat /sys/bus/dahdi_spans/devices/span-*/is_sync_master

(Note: commit d8fe2af23d is also Acked-By
Tzafrir Cohen <tzafrir.cohen@xorcom.com>)

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 17:20:04 +02:00
Oron Peled
d8fe2af23d xpp: automatic dahdi_registration by default
* Now with pinned-spans, we can assure reliable ordering
2013-11-24 15:34:57 +02:00
Oron Peled
35e9924b3c Rename "pinned spans" to "assigned spans"
Rename as terminology has changed. No change in kernel interface.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 15:03:35 +02:00
Oron Peled
a9c85de700 .gitignore: *.ko.unsigned
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 14:55:49 +02:00
Oron Peled
7a822db82c dahdi: Rename span 'master' as 'master_span'
* No functional changes.
* Rename the span 'master' to 'master_span' to avoid ambiguity with the
  'master' channel.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 14:54:27 +02:00
Oron Peled
007ff90025 sysfs: create symlink "ddev" to device of span
Create a "ddev" symlink from span's sysfs node to the one of its dahdi
device.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 14:54:03 +02:00
Oron Peled
be25fdb6fa remove udev rules: moved to dahdi-tools
* Removed xpp.rules
* Removed generation of dahdi.rules

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 14:53:20 +02:00
Oron Peled
06daf6c270 live_dahdi: load "dahdi" with tools_rootdir=$DESTDIR
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 14:52:35 +02:00
Oron Peled
1672e07deb Also send DAHDI_TOOLS_ROOTDIR with device events
Send the new DAHDI_TOOLS_ROOTDIR and existing DAHDI_INIT_DIR with udev
device events as well.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 14:51:24 +02:00
Oron Peled
7b578b83b9 dahdi: add "tools_rootdir" module parameter
* Passed to udev as DAHDI_TOOLS_ROOTDIR environment variable
* Default is "/"
* Deprecates the parameter initdir:
  - Defaults to $DAHDI_TOOLS_ROOTDIR/usr/share/dahdi
  - If specified: taken relative to $DAHDI_TOOLS_ROOTDIR
  - Setting both parameters explicitly is prohibited.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>
2013-11-24 14:51:14 +02:00
Shaun Ruffell
1ab5723b85 wcte43x: Remove 'dcxo' debug attribute.
Removes another bit of debugging instrumentation that I let slip through.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-20 09:39:12 -06:00
Shaun Ruffell
cbad5a7ae1 wcte43x: Do not grab reglock in handle_transmit/handle_receive.
If the driver is loaded with vpmsupport=0, then it was possible to create a
deadlock situation since the call into __dahdi_ec_chunk might then try to grab
the channel lock while already holding the reglock.

The purpose of grabbing reglock in the DMA routines was to protect the channel
array, which can be changed when linemode is changing. So instead, we'll
completely mask off that interrupt line from all CPUs when potentially changing
the channel array.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-20 09:33:07 -06:00
Shaun RuffellL
b3c6320374 wcaxx: Remove some left over debugging trace statements.
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-17 02:36:29 -06:00
Shaun Ruffell
69a716af1a wcxb: Update the firmware meta block during flash update.
The meta block contains specific version and checksum information and allows the
test tools to validate the image in the flash.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-16 16:03:19 -06:00
Shaun Ruffell
eed2e4e00b wcaxx: Update A4B firmware to version 0b0017
Resolves some sporadic issues with invalid underruns.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-16 16:02:00 -06:00
Wendell Thompson
466acea7e0 wcte43x: Add driver for TE435/TE235 digital cards.
From: Wendell Thompson <wthompson@digium.com>

These new cards are based on a common architecture with the TE133/TE134 as well
as the new analog cards, A4A/A4B/A8A/A8B.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Russ Meyerriecks
3134b36d7e wcte13xp: Improve maintenance functions and error counters
From: Rus Meyerriecks <rmeyerriecks@digium.com>

* Removed work queue for maint interface as it is not needed in this driver
* Error counters are now accessible through the maint interface
* Consolidated and revised the big maint switch case
* Added loopup/loopdown code transmit logic to E1
* Now supports error/defect insersion

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Russ Meyerriecks
4707e19654 wcte13xp: Hold framer in reset to stop xmit on modprobe -r
From: Russ Meyerriecks <rmeyerriecks@digium.com>

The framer appears to continue transmitting a signal after modprobe -r. This
patch will leave the physical framer reset pin asserted to force the chip to
stop transmitting a signal when there is no driver attached.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Russ Meyerriecks
e42548f2c5 wcte13xp: Migrate to wcxb library
From: Russ Meyerriecks <rmeyerriecks@digium.com>

Removed all the custom logic and replaced with the common platform wcxb stuff.

There are also changes in here to standardize the function prefix in this
driver to t13x_.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Wendell Thompson
abe35059bc wcte13xp: Use interrupts for Falc alarms and signaling
From: Wendell Thompson <wthompson@digium.com>

Now uses framer interrupt vector polling (in the FPGA interrupt) for
alarm, loopcode, and signaling events eliminating continuous polling.
Now uses timer function for alarm and loopcode debouce, which only
executes during exception conditions.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
348f6ab030 wcaxx: New driver for A4A/A4B/A8A/A8B analog cards.
This is a driver for the new line of analog cards that shares a common interface
with the TE133/TE134 and the TE435.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
26efcf6902 wct4xxp, wcte13xp: Move the octasic DSP code into separate module.
The octasic library is relatively large and is currently separately linked into
both the wcte13xp and wct4xxp libraries. This change moves it out into a
separate loadable module.

The bigest change from the drivers perspectives is that they must provide a
table of callbacks instead of using statically linked Oct6100UserXxxxx functions
to allow the library to communicate with actual parts on the cards.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
a648cef0f6 wct4xxp: If linemode changed via sysfs, reset the complete part.
This works around some issues with older versions of the firmware not
working properly after the linemode is changed via sysfs. Basically the
intent is to simulate redoing a complete driver reload with a new
linemode.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
a5a52dbe94 wct4xxp: VPM companding switch print is now debug only.
This print happened when the linemode was changed via sysfs, but it didn't
really add much extra information that a user could act on.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
43ad3eeb65 wct4xxp: Fix bipolar error insertion test mode.
This change wouldn't affect most people since it's only used by the error
injection code.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
706dc43483 wct4xxp: Print warning in dmesg if span priority is not set correctly.
dahdi_genconf currently does not take into account the number of spans
configured for a particular board. Therefore if you have two dual span cards
installed in the system, it could be possible to have something like this in
/etc/dahdi/system.conf:

  spans=1,1,...
  spans=2,2,...
  spans=3,3,...
  spans=4,4,...

When what you really want is something like this:

  spans=1,1,...
  spans=2,2,...
  spans=3,1,...
  spans=4,2,...

Otherwise, spans 3 and 4 will be configured to not recover the clock from the
span which is most likely NOT what you want.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
92f1e46b8f dahdi: Backport try_wait_for_completion() and list_first_entry()
This allows drivers to use the newer interface but build against older
kernels.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
abb09a012d dahdi: Work around missing KBUILD_MODNAME
Some older versions of Kbuild will not pass KBUILD_MODNAME to a
compilation unit that is linked to multiple drivers. This change works
around this issue by globally modifing dev_dbg in this case.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:19 -06:00
Shaun Ruffell
7405dd6038 dahdi: Fix placement of '/' in output of /proc/dahdi/x
Fixes strings that look like:
  Span 1: TE2/0/1 "T2XXP (PCI) Card 0 Span 1" CCSHDB3//CRC4 RED

To look like:
  Span 1: TE2/0/1 "T2XXP (PCI) Card 0 Span 1" CCS/HDB3/CRC4 RED

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:18 -06:00
Shaun Ruffell
496f817773 dahdi: Clear DAHDI_ALARM_NOTOPEN when spans are re-initialized.
This eliminates the need for board drivers to always re-report their alarm
states when spans are unassigned and then reassigned.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:18 -06:00
Shaun Ruffell
4a6ecbbdeb dahdi_config: Remove unused NO_DCDC definition.
There are not any drivers in the tree that make reference to this definition
anymore, so it can be removed.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
2013-11-11 14:39:18 -06:00
Tzafrir Cohen
bd0366287e xpp: Fail loading if no module on first slot
The driver assumes that the first slot is not empty. If this is not the
case, synchronization will not work.

Fail loading if this assertion does not hold.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-11-10 16:39:36 +02:00
Tzafrir Cohen
f287c0af7f xpp: mark an AB as failed if it gives bad desc
If we fail at handling the device descriptor from the Astribank, mark it
as in state "failed".

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-11-10 16:39:36 +02:00
Tzafrir Cohen
7adc74512e xpp: USB_FW.202.hex: provide as a symlink
Provide USB_FW.202.hex as a (install-time) symlink to USB_FW.201.hex.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-11-07 17:08:45 +02:00
Tzafrir Cohen
b993d25c5a xpp: Firmware for Astribanks 2.02: Makefile
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-11-06 16:57:48 +02:00
Tzafrir Cohen
41ae90a8a3 xpp: Firmware for Astribanks 2.02
Astribank 2.02: a newer model: slight variation of 2.01 (both use E-Main
4). Uses the same USB firmware, has to use a different FPGA firmware as
newer devices cannot be made to work with older 2.01 firmware.

FPGA rev. 11307.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-10-21 16:51:30 +03:00
Oron Peled
d4c8eb47ac add a 'location' attribute to sysfs (dahdi_device):
* Our user-space previously used the implicit location from the sysfs
  device path of the "dahdi_device".
* However:
  - Sysfs paths are very limited in length.
  - Low-level driver need more control on the location field.
  - For example, it need to be persistant for span_assignments.
* We now export explicitly the 'location' field which is managed by
  low-level drivers.
* We will use this field as the location in span_assignments.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-10-01 23:42:21 +03:00
Oron Peled
2bd36a3307 xpp: ring/mwi settings: add to FXS init script
init_card_1_30 (FXS modules init script) can now use the new sysfs
interface to set ring settings.

Currently it only overwrite a single register

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-10-01 15:25:42 +03:00
Oron Peled
600dd03e30 xpp: FXS: ring/mwi settings: a sysfs interface
A new SysFS interface for FXS modules (XPDs):
* In /sys/bus/xpds/devices/<ll>:<m>:<n>/fxs_ring_registers
* Reading show current register values for NEON/TRAPEZ/NORMAL
* Modify the table via writing: "<column> <reg> <byte> [<byte>]"
* Example:
	echo "NEON 0x33 0x12" > \
		'/sys/bus/xpds/devices/00:0:0/fxs_ring_registers'

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-10-01 15:23:56 +03:00
Oron Peled
3d1d87e526 xpp: refactor FXS ring settings
xpp: refactor the FXS module ring settings into separate data structure:

* Update High VBAT initialization in init_card_1_30:
  - Take the value used in set_vm_led_mode() (0x34)
  - Now we don't need to set it over and over again in set_vm_led_mode()
* Create a unified ring_parameters[] array for all ring registers:
  - Columns for 3 ring types (NEON, TRAPEZ, NORMAL)
  - Used by new send_ring_parameters() function
* Now the set_vm_led_mode() simply calls send_ring_parameters()
* This cleanup would allow us to change ring parameters at runtime (by
  updating the values in these tables).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-10-01 15:22:32 +03:00
Oron Peled
745118acb9 xpp: Serialize dahdi registration
xpp: Serialize dahdi registration: Cause races under highly-parallel
workloads (with dahdi_autoreg=0).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
2013-09-29 19:13:26 +03:00
40 changed files with 32848 additions and 1831 deletions

9
.gitignore vendored
View File

@@ -5,6 +5,7 @@
*.mod
*.mod.[oc]
*.ko
*.ko.unsigned
*.cmd
*.order
*.tar.gz
@@ -38,4 +39,12 @@ drivers/dahdi/firmware/dahdi-fw-oct6114-256.bin
drivers/dahdi/firmware/dahdi-fw-tc400m.bin
drivers/dahdi/firmware/dahdi-fw-te820.bin
drivers/dahdi/firmware/dahdi-fw-vpmoct032.bin
drivers/dahdi/firmware/dahdi-fw-a4a.bin
drivers/dahdi/firmware/dahdi-fw-a4b.bin
drivers/dahdi/firmware/dahdi-fw-a8a.bin
drivers/dahdi/firmware/dahdi-fw-a8b.bin
drivers/dahdi/firmware/dahdi-fw-oct6114-032.bin
drivers/dahdi/firmware/dahdi-fw-te133.bin
drivers/dahdi/firmware/dahdi-fw-te134.bin
drivers/dahdi/firmware/dahdi-fw-te435.bin
drivers/dahdi/firmware/make_firmware_object

View File

@@ -47,8 +47,6 @@ ifeq (yes,$(HAS_KSRC))
HOTPLUG_FIRMWARE:=$(shell if grep -q '^CONFIG_FW_LOADER=[ym]' $(KCONFIG); then echo "yes"; else echo "no"; fi)
endif
UDEV_DIR:=/etc/udev/rules.d
MODULE_ALIASES:=wcfxs wctdm8xxp wct2xxp
INST_HEADERS:=kernel.h user.h fasthdlc.h wctdm_user.h dahdi_config.h
@@ -82,12 +80,12 @@ include/dahdi/version.h: FORCE
fi
@rm -f $@.tmp
prereq: include/dahdi/version.h firmware-loaders oct612x-lib
prereq: include/dahdi/version.h firmware-loaders
stackcheck: $(CHECKSTACK) modules
objdump -d drivers/dahdi/*.ko drivers/dahdi/*/*.ko | $(CHECKSTACK)
install: all install-modules install-devices install-include install-firmware install-xpp-firm
install: all install-modules install-include install-firmware install-xpp-firm
@echo "###################################################"
@echo "###"
@echo "### DAHDI installed successfully."
@@ -96,7 +94,7 @@ install: all install-modules install-devices install-include install-firmware in
@echo "###"
@echo "###################################################"
uninstall: uninstall-modules uninstall-devices uninstall-include uninstall-firmware
uninstall: uninstall-modules uninstall-include uninstall-firmware
install-modconf:
build_tools/genmodconf $(BUILDVER) "$(ROOT_PREFIX)" "$(filter-out dahdi dahdi_dummy xpp dahdi_transcode dahdi_dynamic,$(BUILD_MODULES)) $(MODULE_ALIASES)"
@@ -118,13 +116,6 @@ uninstall-firmware:
firmware-loaders:
$(MAKE) -C drivers/dahdi/firmware firmware-loaders
oct612x-lib:
ifeq (no,$(HAS_KSRC))
@echo "You do not appear to have the sources for the $(KVERS) kernel installed."
@exit 1
endif
$(MAKE) -C $(KSRC) M='$(PWD)/drivers/dahdi/oct612x'
install-include:
for hdr in $(INST_HEADERS); do \
install -D -m 644 include/dahdi/$$hdr $(DESTDIR)/usr/include/dahdi/$$hdr; \
@@ -137,14 +128,6 @@ uninstall-include:
done
-rmdir $(DESTDIR)/usr/include/dahdi
install-devices:
install -d $(DESTDIR)$(UDEV_DIR)
build_tools/genudevrules > $(DESTDIR)$(UDEV_DIR)/dahdi.rules
install -m 644 drivers/dahdi/xpp/xpp.rules $(DESTDIR)$(UDEV_DIR)/
uninstall-devices:
rm -f $(DESTDIR)$(UDEV_DIR)/dahdi.rules
install-modules: modules
ifndef DESTDIR
@if modinfo zaptel > /dev/null 2>&1; then \
@@ -186,6 +169,9 @@ update:
echo "Not under version control"; \
fi
dist:
@./build_tools/make_dist "dahdi-linux" "$(DAHDIVERSION)"
clean:
ifneq (no,$(HAS_KSRC))
$(KMAKE) clean
@@ -215,6 +201,6 @@ README.html: README
dahdi-api.html: drivers/dahdi/dahdi-base.c
build_tools/kernel-doc --kernel $(KSRC) $^ >$@
.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders
.PHONY: distclean dist-clean clean all install devices modules stackcheck install-udev update install-modules install-include uninstall-modules firmware-download install-xpp-firm firmware-loaders dist
FORCE:

43
README
View File

@@ -528,16 +528,26 @@ XPP (Astribank) module parameters
==== dahdi_autoreg
(xpp)
Register spans automatically (1) or not (0). Default: 0.
Setting it simplifies operations with a single Astribank and no other
DAHDI hardware. However if you have such systems, automatic
registration can cause the order of spans to be unpredictable.
The standard startup scripts use 'dahdi_registration on' instead of this.
Deprecated. See dahdi.<<_auto_assign_spans,auto_assign_spans>> above.
Originally had a somewhat similar (but xpp-specific and more limited)
role to auto_assign_spans. For backward compatibility this variable is
still kept, but its value is unused. Astribanks will auto-register
with dahdi if auto_assign_spans is not set.
==== tools_rootdir
(xpp)
Defaults to /. Passed (as the variable DAHDI_TOOLS_ROOTDIR) to generated
events (which can be used in udev hooks). Also serves as the base of
the variable DAHDI_INIT_DIR (by default: $DAHDI_TOOLS_DIR/usr/share/dahdi).
==== initdir
(xpp)
This is the directory containing the initialization scripts.
Deprecated. Setting both initdir and tools_rootdir will generate an error.
A directory under tools_rootdir containing the initialization scripts.
The default is /usr/share/dahdi .
Setting this value could be useful if that location is inconvenient for you.
@@ -887,11 +897,12 @@ to other nodes.
Class DAHDI
^^^^^^^^^^^
under /sys/class/dadhi there exists a node for each DAHDI device file
under /dev/dahdi. The name is 'dahdi!foo' for the file '/dev/dahdi/foo'
(udev translates exclamation marks to slashes). Those nodes are not, for
the most part, proper SysFS nodes, and don't include any interesting
properties.
Under /sys/class/dadhi there exists a node for the non-channel DAHDI
device file under /dev/dahdi. The name is 'dahdi!foo' for the file
'/dev/dahdi/foo' (udev translates exclamation marks to slashes). Those
nodes are not, for the most part, proper SysFS nodes, and don't include
any interesting properties. The files in this class `ctl`, `timer`,
`channel`, `pseudo` and (if exists) `transcode`.
Devices Bus
@@ -916,6 +927,10 @@ A unique hardware-level identifier (e.g. serial number), if available.
===== /sys/bus/dahdi_devices/devices/DEVICE/manufacturer
The name of the manufacturer. Freeform-string.
===== /sys/bus/dahdi_devices/devices/DEVICE/registration_time
The time at which the device registered with the DAHDI core. Example
value: "0005634136.941901429".
===== /sys/bus/dahdi_devices/devices/DEVICE/spantype
A line for each available span: <num>:<type>. This has to be provided
here as in the case of manual assignment, userspace may need to know
@@ -980,6 +995,12 @@ A very short type string.
===== /sys/bus/dahdi_spans/devices/span-N/syncsrc
Current sync source.
==== sys/bus/dahdi_spans/drivers/generic_lowlevel/master_span
All spans in the bus are handled by a single driver. The driver has one
non-standard attribute: master_span. printing it shows the current DAHDI
master span writing a number to it forces setting this span as the master
span.
Channels Bus
^^^^^^^^^^^^

123
build_tools/dkms-helper Executable file
View File

@@ -0,0 +1,123 @@
#!/bin/sh
set -e
DKMS=$(which dkms)
usage() {
echo "$(basename $0): Helper functions for DKMS (Dynamic Kernel Module Support)"
echo "Usage: $0 [add|remove|generate_conf]"
echo "Options:"
echo " remove -a : Remove all versions of DAHDI for all kernels."
echo ""
echo "Examples:"
echo ""
echo " build_tools/dkms-helper add"
echo " Installs the current version of DAHDI into the DKMS system."
echo ""
echo " build_tools/dkms-helper remove"
echo " Removes the current version of DAHDI from all kernels."
echo ""
echo " build_tools/dkms-helper generate_conf > dkms.conf"
echo " Create a dkms.conf based on the currently compiled kernel"
echo " modules. This is also done as part of add and is not"
echo " normally needed as a separate step."
echo ""
echo "NOTE: Because firmware files could be different between different"
echo "versions of DAHDI, and the firmware files are installed into the common"
echo "/lib/firmware directory, you should remove a given version of DAHDI from all"
echo "kernels before installing a new version of DAHDI to avoid potential"
echo "conflicts."
echo ""
}
generate_configuration() {
echo 'PACKAGE_NAME="dahdi-linux"'
echo "PACKAGE_VERSION=\"$(build_tools/make_version .)\""
echo 'MAKE="make KSRC=/lib/modules/${kernelver}/build"'
echo 'CLEAN="make clean"'
echo 'AUTOINSTALL="yes"'
let "module_number=0" || true
for file in $(find ./ -type f -name "*.ko"); do
MODULE_LOCATION=$(dirname $file | cut -d\/ -f 2-)
echo "BUILT_MODULE_NAME[$module_number]=\"$(basename $file .ko)\""
echo "BUILT_MODULE_LOCATION[$module_number]=\"$MODULE_LOCATION\""
echo "DEST_MODULE_LOCATION[$module_number]=\"/kernel/dahdi/$(echo $MODULE_LOCATION | cut -d\/ -f 3-)\""
let "module_number=${module_number}+1" || true
done
if [ $module_number -eq 0 ]; then
echo "WARNING: You should build the modules before generating a config." >&2
exit 1
fi
}
add() {
GIT=$(which git)
VERSION="$(build_tools/make_version .)"
if [ $(id -u) != "0" ]; then
echo "You must run $0 as root."
exit 1
fi
echo "Building for version ${VERSION}"
make > /dev/null
echo "Copying to /usr/src/dahdi-linux-${VERSION}"
if [ ! -d /usr/src/dahdi-linux-${VERSION} ]; then
if [ -d .git ]; then
${GIT} checkout-index -a --prefix=/usr/src/dahdi-linux-${VERSION}/
else
cp -f -r * /usr/src/dahdi-linux-${VERSION}/
fi
fi
make -C /usr/src/dahdi-linux-${VERSION} install-firmware firmware-loaders
build_tools/dkms-helper generate_conf > /usr/src/dahdi-linux-${VERSION}/dkms.conf
echo $VERSION > /usr/src/dahdi-linux-${VERSION}/.version
${DKMS} add -m dahdi-linux -v ${VERSION}
${DKMS} build -m dahdi-linux -v ${VERSION}
${DKMS} install --force -m dahdi-linux -v ${VERSION}
}
remove() {
if [ $(id -u) != "0" ]; then
echo "You must run $0 as root."
exit 1
fi
REMOVE_ALL=false
shift
while getopts "a" opt; do
case $opt in
a) REMOVE_ALL=true ;;
*) echo "Unknown option to remove" ; exit 1;;
esac
done
if [ $REMOVE_ALL == true ]; then
# Remove all installed dahdi versions for all kernels.
for version in $(${DKMS} status -m dahdi-linux | cut -d, -f 2 | sed -e "s/^\s\+//"); do
echo "Removing version ${version}"
${DKMS} remove -m dahdi-linux -v ${version} --all
rm -f -r /usr/src/dahdi-linux-${version}
done
else
# Just remove the version for the current tree.
GIT=$(which git)
VERSION="$(build_tools/make_version .)"
${DKMS} remove -m dahdi-linux -v ${VERSION} --all
if [ -e /usr/src/dahdi-linux-${VERSION}/dkms.conf ]; then
rm -f -r /usr/src/dahdi-linux-${VERSION}
else
echo "/usr/src/dahdi-linux-${VERSION} not a dkms dir?"
exit 1
fi
fi
}
# Run the command...
shift $(($OPTIND-1))
COMMAND=$1
case $COMMAND in
add) add $*; exit $? ;;
remove) remove $* ; exit $? ;;
generate_conf) generate_configuration; exit $? ;;
*) echo "unknown command $0" ; usage; exit 1;;
esac
exit 0

View File

@@ -1,40 +0,0 @@
#!/bin/sh
ver=`udevinfo -V | cut -f3 -d" "`
if [ -z "${ver}" ]; then
# Not found - try udevadm
ver=`udevadm info -V | cut -f3 -d" "`
if [ -z "${ver}" ]; then
# nobody has that old version, anyway.
ver=54
fi
fi
# udev versions prior to 055 use a single '=' for matching key values
# udev versions 055 and later support '==' for that purpose, and versions
# beyond 092 will probably make it mandatory
#
# very old versions of udev required naming rules and permissions rules to be
# in separate files, but it's not clear at what version number that changed
if [ ${ver} -gt 54 ]; then
match="=="
else
match="="
fi
cat <<EOF
# udev rules to generate the /dev/dahdi device files (if not yet provided
# by your distribution):
KERNEL${match}"dahdictl", NAME="dahdi/ctl"
KERNEL${match}"dahditranscode", NAME="dahdi/transcode"
KERNEL${match}"dahditimer", NAME="dahdi/timer"
KERNEL${match}"dahdichannel", NAME="dahdi/channel"
KERNEL${match}"dahdipseudo", NAME="dahdi/pseudo"
KERNEL${match}"dahdi[0-9]*", NAME="dahdi/%n"
# DAHDI devices with ownership/permissions for running as non-root
SUBSYSTEM${match}"dahdi", OWNER="asterisk", GROUP="asterisk", MODE="0660"
EOF

View File

@@ -61,7 +61,7 @@ export ASTRIBANK_HEXLOAD
# make sure Astribank initialization scripts are from our tree.
xpp_ARGS="$xpp_ARGS initdir=$FIRMWARE_DIR"
#dahdi_ARGS="$dahdi_ARGS initdir=$FIRMWARE_DIR"
dahdi_ARGS="$dahdi_ARGS tools_rootdir=$DESTDIR"
if [ "$DYNAMIC_LOC" = 'yes' ]; then
MODULES_LOAD="$MODULES_LOAD dahdi_dynamic dahdi_dynamic_loc"

26
build_tools/make_dist Executable file
View File

@@ -0,0 +1,26 @@
#! /bin/sh
if [ "$#" -ne 2 ]; then
echo >&2 "Usage: $0 <package> <version>"
exit 1
fi
package="$1"
version="$2"
tarball_prefix="$package-$version"
echo "I: Making dist tarball for $tarball_prefix"
tarball_name="$tarball_prefix.tar.gz"
tmp_work_dir=".tmp"
tmp_version_dir="$tmp_work_dir/$tarball_prefix"
if [ "$DESTDIR" != '' ]; then
destdir="$DESTDIR/"
fi
output="$destdir$tarball_name"
mkdir -p "$tmp_version_dir"
git archive --format tar HEAD | tar xf - -C "$tmp_version_dir"
echo "$version" > "$tmp_version_dir/.version"
tar czf "$output" -C "$tmp_work_dir" "$tarball_prefix"
rm -rf "$tmp_work_dir"
echo "I: tarball is ready: '$output'"

View File

@@ -7,18 +7,35 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_DYNAMIC_ETHMF) += dahdi_dynamic_ethmf.o
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_TRANSCODE) += dahdi_transcode.o
ifdef CONFIG_PCI
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 oct612x/lib.a
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
wcte13xp-objs := wcte13xp-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcte13xp-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcte13xp-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCTE43X) += wcte43x.o
wcte43x-objs := wcte43x-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcte43x-base.o += -I$(src)/oct612x -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
ifeq ($(HOTPLUG_FIRMWARE),yes)
CFLAGS_wcte43x-base.o += -DHOTPLUG_FIRMWARE
endif
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCAXX) += wcaxx.o
wcaxx-objs := wcaxx-base.o wcxb_spi.o wcxb.o wcxb_flash.o
CFLAGS_wcaxx-base.o += -I$(src)/oct612x/ -I$(src)/oct612x/include -I$(src)/oct612x/octdeviceapi -I$(src)/oct612x/octdeviceapi/oct6100api
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/

View File

@@ -50,6 +50,7 @@
#include <linux/list.h>
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/ktime.h>
#if defined(HAVE_UNLOCKED_IOCTL) && defined(CONFIG_BKL)
#include <linux/smp_lock.h>
@@ -173,7 +174,7 @@ static sumtype *conf_sums_next;
static sumtype *conf_sums;
static sumtype *conf_sums_prev;
static struct dahdi_span *master;
static struct dahdi_span *master_span;
struct file_operations *dahdi_transcode_fops = NULL;
@@ -611,7 +612,7 @@ void dahdi_unregister_echocan_factory(const struct dahdi_echocan_factory *ec)
/* Is this span our syncronization master? */
int dahdi_is_sync_master(const struct dahdi_span *span)
{
return span == master;
return span == master_span;
}
static inline void rotate_sums(void)
@@ -732,6 +733,8 @@ enum spantypes dahdi_str2spantype(const char *name)
return SPANTYPE_DIGITAL_BRI_TE;
else if (strcasecmp("BRI_SOFT", name) == 0)
return SPANTYPE_DIGITAL_BRI_SOFT;
else if (strcasecmp("DYNAMIC", name) == 0)
return SPANTYPE_DIGITAL_DYNAMIC;
else
return SPANTYPE_INVALID;
}
@@ -749,6 +752,7 @@ const char *dahdi_spantype2str(enum spantypes st)
case SPANTYPE_DIGITAL_BRI_NT: return "BRI_NT";
case SPANTYPE_DIGITAL_BRI_TE: return "BRI_TE";
case SPANTYPE_DIGITAL_BRI_SOFT: return "BRI_SOFT";
case SPANTYPE_DIGITAL_DYNAMIC: return "DYNAMIC";
default:
case SPANTYPE_INVALID: return "INVALID";
};
@@ -787,6 +791,7 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
int crc4_bit = 0;
int len = 0;
int bit;
bool written = false;
for (bit = 4; bit <= 12; bit++) {
int mask = (1 << bit);
@@ -798,8 +803,10 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
case DAHDI_CONFIG_AMI:
case DAHDI_CONFIG_HDB3:
framing_bit = bit;
len += snprintf(buf + len, size, "%s/",
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
if (!coding_bit) {
@@ -808,14 +815,18 @@ ssize_t lineconfig_str(int lineconfig, char buf[], size_t size)
case DAHDI_CONFIG_D4:
case DAHDI_CONFIG_CCS:
coding_bit = bit;
len += snprintf(buf + len, size, "%s",
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
if (!crc4_bit && mask == DAHDI_CONFIG_CRC4) {
crc4_bit = bit;
len += snprintf(buf + len, size, "/%s",
len += snprintf(buf + len, size, "%s%s",
(written) ? "/" : "",
dahdi_lineconfig_bit_name(bit));
written = true;
}
}
return len;
@@ -3833,6 +3844,31 @@ void dahdi_alarm_channel(struct dahdi_chan *chan, int alarms)
spin_unlock_irqrestore(&chan->lock, flags);
}
struct dahdi_span *get_master_span(void)
{
return master_span;
}
void set_master_span(int spanno)
{
struct dahdi_span *s;
unsigned long flags;
struct dahdi_span *old_master;
spin_lock_irqsave(&chan_lock, flags);
old_master = master_span;
list_for_each_entry(s, &span_list, spans_node) {
if (spanno == s->spanno) {
master_span = s;
break;
}
}
spin_unlock_irqrestore(&chan_lock, flags);
if ((debug & DEBUG_MAIN) && (old_master != master_span))
module_printk(KERN_NOTICE, "Master span is set to %d (%s)\n",
master_span->spanno, master_span->name);
}
static void __dahdi_find_master_span(void)
{
struct dahdi_span *s;
@@ -3840,7 +3876,7 @@ static void __dahdi_find_master_span(void)
struct dahdi_span *old_master;
spin_lock_irqsave(&chan_lock, flags);
old_master = master;
old_master = master_span;
list_for_each_entry(s, &span_list, spans_node) {
if (s->alarms && old_master)
continue;
@@ -3850,15 +3886,15 @@ static void __dahdi_find_master_span(void)
continue;
if (!can_provide_timing(s))
continue;
if (master == s)
if (master_span == s)
continue;
master = s;
master_span = s;
break;
}
spin_unlock_irqrestore(&chan_lock, flags);
if ((debug & DEBUG_MAIN) && (old_master != master))
if ((debug & DEBUG_MAIN) && (old_master != master_span))
module_printk(KERN_NOTICE, "Master changed to %s\n", s->name);
}
@@ -3899,7 +3935,7 @@ void dahdi_alarm_notify(struct dahdi_span *span)
dahdi_alarm_channel(span->chans[x], span->alarms);
/* If we're going into or out of alarm we should try to find a
* new master that may be a better fit. */
* new master_span that may be a better fit. */
dahdi_find_master_span();
/* Report more detailed alarms */
@@ -5129,7 +5165,7 @@ static int dahdi_ioctl_startup(struct file *file, unsigned long data)
}
/* Now that this span is running, it might be selected as the
* master span */
* master_span */
__dahdi_find_master_span();
}
put_span(s);
@@ -7194,7 +7230,7 @@ EXPORT_SYMBOL(dahdi_init_span);
* @spanno: The span number we would like assigned. If 0, the first
* available spanno/basechan will be used.
* @basechan: The base channel number we would like. Ignored if spanno is 0.
* @prefmaster: will the new span be preferred as a master?
* @prefmaster: will the new span be preferred as a master_span?
*
* Assigns a span for usage with DAHDI. All the channel numbers in it will
* have their numbering started at basechan.
@@ -7213,6 +7249,7 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
{
int res = 0;
unsigned int x;
unsigned long flags;
if (!span || !span->ops || !span->ops->owner)
return -EFAULT;
@@ -7224,6 +7261,16 @@ static int _dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
return -EINVAL;
}
/* DAHDI_ALARM_NOTOPEN can be set when a span is disabled, i.e. via
* sysfs, so when the span is being reassigned we should make sure it's
* cleared. This eliminates the need for board drivers to re-report
* their alarm states on span reassignment. */
spin_lock_irqsave(&span->lock, flags);
span->alarms &= ~DAHDI_ALARM_NOTOPEN;
dahdi_alarm_notify(span);
spin_unlock_irqrestore(&span->lock, flags);
if (span->ops->enable_hw_preechocan ||
span->ops->disable_hw_preechocan) {
if ((NULL == span->ops->enable_hw_preechocan) ||
@@ -7327,7 +7374,8 @@ int dahdi_assign_device_spans(struct dahdi_device *ddev)
return 0;
}
static int auto_assign_spans = 1;
int auto_assign_spans = 1;
EXPORT_SYMBOL(auto_assign_spans);
static const char *UNKNOWN = "";
/**
@@ -7357,6 +7405,7 @@ static int _dahdi_register_device(struct dahdi_device *ddev,
__dahdi_init_span(s);
}
ktime_get_ts(&ddev->registration_time);
ret = dahdi_sysfs_add_device(ddev, parent);
if (ret)
return ret;
@@ -7472,8 +7521,8 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
for (x=0;x<span->channels;x++)
dahdi_chan_unreg(span->chans[x]);
new_master = master; /* FIXME: locking */
if (master == span)
new_master = master_span; /* FIXME: locking */
if (master_span == span)
new_master = NULL;
spin_lock_irqsave(&chan_lock, flags);
@@ -7484,13 +7533,13 @@ static int _dahdi_unassign_span(struct dahdi_span *span)
break;
}
spin_unlock_irqrestore(&chan_lock, flags);
if (master != new_master) {
if (master_span != new_master) {
if (debug & DEBUG_MAIN) {
module_printk(KERN_NOTICE, "%s: Span ('%s') is new master\n", __FUNCTION__,
(new_master)? new_master->name: "no master");
}
}
master = new_master;
master_span = new_master;
return 0;
}

View File

@@ -32,8 +32,15 @@
#include "dahdi-sysfs.h"
static char *initdir = "/usr/share/dahdi";
module_param(initdir, charp, 0644);
static char *initdir;
module_param(initdir, charp, 0444);
MODULE_PARM_DESC(initdir,
"deprecated, should use <tools_rootdir>/usr/share/dahdi");
static char *tools_rootdir;
module_param(tools_rootdir, charp, 0444);
MODULE_PARM_DESC(tools_rootdir,
"root directory of all tools paths (default /)");
static int span_match(struct device *dev, struct device_driver *driver)
{
@@ -47,7 +54,9 @@ static inline struct dahdi_span *dev_to_span(struct device *dev)
#define SPAN_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
initdir); \
DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \
DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \
} while (0)
@@ -222,16 +231,51 @@ static struct device_attribute span_dev_attrs[] = {
__ATTR_NULL,
};
static ssize_t master_span_show(struct device_driver *driver, char *buf)
{
struct dahdi_span *s = get_master_span();
return snprintf(buf, PAGE_SIZE, "%d\n", (s) ? s->spanno : 0);
}
static ssize_t master_span_store(struct device_driver *driver, const char *buf,
size_t count)
{
int spanno;
if (sscanf(buf, "%d", &spanno) != 1) {
module_printk(KERN_ERR, "non-numeric input '%s'\n", buf);
return -EINVAL;
}
set_master_span(spanno);
return count;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static struct driver_attribute dahdi_attrs[] = {
__ATTR(master_span, S_IRUGO | S_IWUSR, master_span_show,
master_span_store),
__ATTR_NULL,
};
#else
static DRIVER_ATTR_RW(master_span);
static struct attribute *dahdi_attrs[] = {
&driver_attr_master_span.attr,
NULL,
};
ATTRIBUTE_GROUPS(dahdi);
#endif
static struct bus_type spans_bus_type = {
.name = "dahdi_spans",
.match = span_match,
.uevent = span_uevent,
.dev_attrs = span_dev_attrs,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
.drv_attrs = dahdi_attrs,
#else
.drv_groups = dahdi_groups,
#endif
};
static int span_probe(struct device *dev)
@@ -296,6 +340,7 @@ void span_sysfs_remove(struct dahdi_span *span)
get_device(span_device);
span_uevent_send(span, KOBJ_OFFLINE);
sysfs_remove_link(&span_device->kobj, "ddev");
device_unregister(span->span_device);
dev_set_drvdata(span_device, NULL);
span_device->parent = NULL;
@@ -336,6 +381,15 @@ int span_sysfs_create(struct dahdi_span *span)
span->span_device = NULL;
goto cleanup;
}
res = sysfs_create_link(&span_device->kobj, &span_device->parent->kobj,
"ddev");
if (res) {
span_err(span, "%s: sysfs_create_link failed: %d\n", __func__,
res);
kfree(span->span_device);
span->span_device = NULL;
goto cleanup;
}
for (x = 0; x < span->channels; x++) {
res = chan_sysfs_create(span->chans[x]);
@@ -362,6 +416,71 @@ static inline struct dahdi_device *to_ddev(struct device *dev)
return container_of(dev, struct dahdi_device, dev);
}
#define DEVICE_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_TOOLS_ROOTDIR=%s", tools_rootdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s/%s", tools_rootdir, \
initdir); \
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_HWID=%s", \
ddev->hardware_id); \
DAHDI_ADD_UEVENT_VAR("DAHDI_DEVICE_LOCATION=%s", \
ddev->location); \
} while (0)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(envp, num_envp, &i, \
buffer, buffer_size, &len, \
fmt, val); \
if (err) \
return err; \
} while (0)
static int device_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct dahdi_device *ddev;
int i = 0;
int len = 0;
if (!dev)
return -ENODEV;
ddev = to_ddev(dev);
if (!ddev)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s\n", dev_name(dev));
DEVICE_VAR_BLOCK;
envp[i] = NULL;
return 0;
}
#else
#define DAHDI_ADD_UEVENT_VAR(fmt, val...) \
do { \
int err = add_uevent_var(kenv, fmt, val); \
if (err) \
return err; \
} while (0)
static int device_uevent(struct device *dev, struct kobj_uevent_env *kenv)
{
struct dahdi_device *ddev;
if (!dev)
return -ENODEV;
ddev = to_ddev(dev);
if (!ddev)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s\n", dev_name(dev));
DEVICE_VAR_BLOCK;
return 0;
}
#endif
static ssize_t
dahdi_device_manufacturer_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -402,6 +521,16 @@ dahdi_device_hardware_id_show(struct device *dev,
(ddev->hardware_id) ? ddev->hardware_id : "");
}
static ssize_t
dahdi_device_location_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n",
(ddev->location) ? ddev->location : "");
}
static ssize_t
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@@ -500,7 +629,8 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
{
struct dahdi_device *const ddev = to_ddev(dev);
int ret;
struct dahdi_span *span;
struct dahdi_span *span = NULL;
struct dahdi_span *cur;
unsigned int local_span_number;
char spantype_name[80];
enum spantypes spantype;
@@ -516,9 +646,18 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
list_for_each_entry(span, &ddev->spans, device_node) {
if (local_spanno(span) == local_span_number)
list_for_each_entry(cur, &ddev->spans, device_node) {
if (local_spanno(cur) == local_span_number) {
span = cur;
break;
}
}
if (!span || (local_spanno(span) != local_span_number)) {
module_printk(KERN_WARNING,
"%d is not a valid local span number "
"for this device.\n", local_span_number);
return -EINVAL;
}
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
@@ -527,12 +666,6 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return -EINVAL;
}
if (local_spanno(span) != local_span_number) {
module_printk(KERN_WARNING,
"%d is not a valid local span number "
"for this device.\n", local_span_number);
return -EINVAL;
}
if (!span->ops->set_spantype) {
module_printk(KERN_WARNING, "Span %s does not support "
@@ -544,21 +677,37 @@ dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
return (ret < 0) ? ret : count;
}
static ssize_t
dahdi_registration_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
int count = 0;
count += sprintf(buf, "%010ld.%09ld\n",
ddev->registration_time.tv_sec,
ddev->registration_time.tv_nsec);
return count;
}
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(spantype, S_IWUSR | S_IRUGO, dahdi_spantype_show,
dahdi_spantype_store),
__ATTR(registration_time, S_IRUGO, dahdi_registration_time_show, NULL),
__ATTR_NULL,
};
static struct bus_type dahdi_device_bus = {
.name = "dahdi_devices",
.uevent = device_uevent,
.dev_attrs = dahdi_device_attrs,
};
@@ -639,6 +788,19 @@ int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
int res = 0;
dahdi_dbg(DEVICES, "Registering DAHDI device bus\n");
/* Handle dahdi-tools paths (for udev environment) */
if (tools_rootdir && initdir) {
dahdi_err("Cannot use tools-rootdir and initdir parameters simultaneously\n");
return -EINVAL;
}
if (initdir)
pr_notice("dahdi: initdir is depracated -- prefer using \"tools_rootdir\" parameter\n");
else
initdir = "/usr/share/dahdi";
if (!tools_rootdir)
tools_rootdir = "";
res = bus_register(&dahdi_device_bus);
if (res)
return res;

View File

@@ -630,6 +630,10 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
d->span.deflaw = DAHDI_LAW_MULAW;
d->span.flags |= DAHDI_FLAG_RBS;
d->span.chans = d->chans;
d->span.spantype = SPANTYPE_DIGITAL_DYNAMIC;
d->span.linecompat = DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF |
DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_CCS |
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",

View File

@@ -3,7 +3,7 @@
#
# Makefile for firmware downloading/installation
#
# Copyright (C) 2007-2010, Digium, Inc.
# Copyright (C) 2007-2013, Digium, Inc.
#
# Joshua Colp <jcolp@digium.com>
#
@@ -31,12 +31,19 @@ VPMADT032_VERSION:=1.25.0
HX8_VERSION:=2.06
VPMOCT032_VERSION:=1.12.0
WCT820_VERSION:=1.76
TE133_VERSION:=6f0017
TE134_VERSION:=6f0017
TE133_VERSION:=780017
TE134_VERSION:=780017
TE435_VERSION:=e0017
A8A_VERSION:=1d0017
A8B_VERSION:=1d0017
A4A_VERSION:=a0017
A4B_VERSION:=b0017
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
ALL_FIRMWARE=FIRMWARE-OCT6114-032 FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256
ALL_FIRMWARE+=FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820 FIRMWARE-TE133 FIRMWARE-TE134
ALL_FIRMWARE+=FIRMWARE-A8A FIRMWARE-A8B FIRMWARE-A4A FIRMWARE-A4B FIRMWARE-TE435
# Firmware files should use the naming convention: dahdi-fw-<base name>-<sub name>-<version> or dahdi-fw-<base name>-<version>
# First example: dahdi-fw-oct6114-064-1.05.01
@@ -55,6 +62,11 @@ FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE133=dahdi-fw-te133-$(TE133_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE134=dahdi-fw-te134-$(TE134_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE435=dahdi-fw-te435-$(TE435_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8A=dahdi-fw-a8b-$(A8B_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A8B=dahdi-fw-a8a-$(A8A_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4A=dahdi-fw-a4b-$(A4B_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-A4B=dahdi-fw-a4a-$(A4A_VERSION).tar.gz)
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
@@ -225,6 +237,61 @@ ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te134-$(TE
else
@echo "Firmware dahdi-fw-te134.bin is already installed with required version $(TE134_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-$(TE435_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te435-$(TE435_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te435.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te435.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te435-$(TE435_VERSION)
@install -m 644 dahdi-fw-te435.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te435-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te435-$(TE435_VERSION)
else
@echo "Firmware dahdi-fw-te435.bin is already installed with required version $(TE435_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-$(A8A_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-$(A8A_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a8a.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a8a.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8a-$(A8A_VERSION)
@install -m 644 dahdi-fw-a8a.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a8a-$(A8A_VERSION)
else
@echo "Firmware dahdi-fw-a8a.bin is already installed with required version $(A8A_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-$(A8B_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-$(A8B_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a8b.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a8b.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a8b-$(A8B_VERSION)
@install -m 644 dahdi-fw-a8b.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a8b-$(A8B_VERSION)
else
@echo "Firmware dahdi-fw-a8b.bin is already installed with required version $(A8B_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-$(A4A_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-$(A4A_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a4a.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a4a.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4a-$(A4A_VERSION)
@install -m 644 dahdi-fw-a4a.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a4a-$(A4A_VERSION)
else
@echo "Firmware dahdi-fw-a4a.bin is already installed with required version $(A4A_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-$(A4B_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-$(A4B_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-a4b.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-a4b.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-a4b-$(A4B_VERSION)
@install -m 645 dahdi-fw-a4b.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-a4b-$(A4B_VERSION)
else
@echo "Firmware dahdi-fw-a4b.bin is already installed with required version $(A4B_VERSION)"
endif
# Uninstall any installed dahdi firmware images from hotplug firmware directories
hotplug-uninstall:

View File

@@ -0,0 +1,32 @@
#
# Produces the oct612x library
#
octapi_files = octdeviceapi/oct6100api/oct6100_api/oct6100_adpcm_chan.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_channel.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_chip_open.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_chip_stats.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_conf_bridge.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_debug.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_events.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_interrupts.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_memory.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_miscellaneous.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_mixer.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_phasing_tsst.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_playout_buf.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_remote_debug.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tlv.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tone_detection.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tsi_cnct.o \
octdeviceapi/oct6100api/oct6100_api/oct6100_tsst.o \
apilib/bt/octapi_bt0.o \
apilib/largmath/octapi_largmath.o \
apilib/llman/octapi_llman.o \
oct612x-user.o
# TODO: ccflags was added in 2.6.24 in commit f77bf01425b11947eeb3b5b54. This
# should be changed to a conditional compilation based on the Kernel Version.
# ccflags-y := -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
EXTRA_CFLAGS = -I$(src)/.. -Wno-undef -I$(src)/include -I$(src)/octdeviceapi -I$(src)/octdeviceapi/oct6100api
obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_OCT612X) := oct612x.o
oct612x-objs := $(octapi_files)

View File

@@ -0,0 +1,200 @@
/*
* Octasic OCT6100 Interface
*
* Copyright (C) 2013 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <dahdi/kernel.h>
#include "oct612x.h"
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
{
/* Why couldn't they just take a timeval like everyone else? */
struct timeval tv;
unsigned long long total_usecs;
unsigned int mask = ~0;
do_gettimeofday(&tv);
total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
(((unsigned long long)(tv.tv_usec)));
f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern,
UINT32 f_ulLength)
{
memset(f_pAddress, f_ulPattern, f_ulLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource,
UINT32 f_ulLength)
{
memcpy(f_pDestination, f_pSource, f_ulLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserCreateSerializeObject(
tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
{
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDestroySerializeObject(
tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
{
#ifdef OCTASIC_DEBUG
pr_debug("I should never be called! (destroy serialize object)\n");
#endif
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserSeizeSerializeObject(
tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserReleaseSerializeObject(
tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
{
struct oct612x_context *context = f_pWriteParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write(context, f_pWriteParams->ulWriteAddress,
f_pWriteParams->usWriteData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
{
struct oct612x_context *context = f_pSmearParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write_smear) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write_smear(context, f_pSmearParams->ulWriteAddress,
f_pSmearParams->usWriteData,
f_pSmearParams->ulWriteLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteBurstApi(
tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
{
struct oct612x_context *context = f_pBurstParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->write_burst) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->write_burst(context, f_pBurstParams->ulWriteAddress,
f_pBurstParams->pusWriteData,
f_pBurstParams->ulWriteLength);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
{
struct oct612x_context *context = f_pReadParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->read) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->read(context, f_pReadParams->ulReadAddress,
f_pReadParams->pusReadData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
{
struct oct612x_context *context = f_pBurstParams->pProcessContext;
#ifdef OCTASIC_DEBUG
if (!context || !context->ops || !context->ops->read_burst) {
pr_debug("Invalid call to %s\n", __func__);
return cOCT6100_ERR_BASE;
}
#endif
context->ops->read_burst(context, f_pBurstParams->ulReadAddress,
f_pBurstParams->pusReadData,
f_pBurstParams->ulReadLength);
return cOCT6100_ERR_OK;
}
EXPORT_SYMBOL(Oct6100ChipOpen);
EXPORT_SYMBOL(Oct6100ChipClose);
EXPORT_SYMBOL(Oct6100ChipCloseDef);
EXPORT_SYMBOL(Oct6100GetInstanceSize);
EXPORT_SYMBOL(Oct6100GetInstanceSizeDef);
EXPORT_SYMBOL(Oct6100ChipOpenDef);
EXPORT_SYMBOL(Oct6100ChannelModify);
EXPORT_SYMBOL(Oct6100ToneDetectionEnableDef);
EXPORT_SYMBOL(Oct6100InterruptServiceRoutine);
EXPORT_SYMBOL(Oct6100InterruptServiceRoutineDef);
EXPORT_SYMBOL(Oct6100ApiGetCapacityPins);
EXPORT_SYMBOL(Oct6100ToneDetectionEnable);
EXPORT_SYMBOL(Oct6100EventGetToneDef);
EXPORT_SYMBOL(Oct6100EventGetTone);
EXPORT_SYMBOL(Oct6100ApiGetCapacityPinsDef);
EXPORT_SYMBOL(Oct6100ChannelOpen);
EXPORT_SYMBOL(Oct6100ChannelOpenDef);
EXPORT_SYMBOL(Oct6100ChannelModifyDef);
static int __init oct612x_module_init(void)
{
/* This registration with dahdi.ko will fail since the span is not
* defined, but it will make sure that this module is a dependency of
* dahdi.ko, so that when it is being unloded, this module will be
* unloaded as well. */
dahdi_register_device(NULL, NULL);
return 0;
}
module_init(oct612x_module_init);
static void __exit oct612x_module_cleanup(void)
{
/* Nothing to do */;
}
module_exit(oct612x_module_cleanup);
MODULE_AUTHOR("Digium Incorporated <support@digium.com>");
MODULE_DESCRIPTION("Octasic OCT6100 Hardware Echocan Library");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,49 @@
/*
* Octasic OCT6100 Interface
*
* Copyright (C) 2013 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 __OCT612X_H__
#define __OCT612X_H__
#include <oct6100api/oct6100_api.h>
struct oct612x_context;
/**
* struct oct612x_ops - Callbacks used by oct612x library to talk to part.
*
*/
struct oct612x_ops {
int (*write)(struct oct612x_context *context, u32 address, u16 value);
int (*read)(struct oct612x_context *context, u32 address, u16 *value);
int (*write_smear)(struct oct612x_context *context, u32 address,
u16 value, size_t count);
int (*write_burst)(struct oct612x_context *context, u32 address,
const u16 *value, size_t count);
int (*read_burst)(struct oct612x_context *context, u32 address,
u16 *value, size_t count);
};
struct oct612x_context {
const struct oct612x_ops *ops;
struct device *dev;
};
#endif /* __OCT612X_H__ */

4544
drivers/dahdi/wcaxx-base.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCT4XXP) += wct4xxp.o
FIRM_DIR := ../firmware
EXTRA_CFLAGS += -I$(src)/.. $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef
EXTRA_CFLAGS += -I$(src)/.. -I$(src)/../oct612x/ $(shell $(src)/../oct612x/octasic-helper cflags $(src)/../oct612x) -Wno-undef
# The OCT612X source files are from a vendor drop and we do not want to edit
# them to make this warning go away. Therefore, turn off the
@@ -14,7 +14,7 @@ ifeq ($(HOTPLUG_FIRMWARE),yes)
EXTRA_CFLAGS+=-DHOTPLUG_FIRMWARE
endif
wct4xxp-objs := base.o vpm450m.o ../oct612x/lib.a
wct4xxp-objs := base.o vpm450m.o
ifneq ($(HOTPLUG_FIRMWARE),yes)
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o $(FIRM_DIR)/dahdi-fw-oct6114-256.o

View File

@@ -183,7 +183,7 @@ static inline int t4_queue_work(struct workqueue_struct *wq, struct work_struct
"CONFIG_NOEXTENDED_RESET."
#endif
static int debug=0;
int debug = 0;
static int timingcable = 0;
static int t1e1override = -1; /* deprecated */
static char *default_linemode = "auto";
@@ -299,6 +299,7 @@ struct t4_span {
unsigned long alarmcheck_time;
int spanflags;
int syncpos;
#ifdef SUPPORT_GEN1
int e1check; /* E1 check */
#endif
@@ -345,6 +346,7 @@ struct t4 {
int irq; /* IRQ used by device */
int order; /* Order */
const struct devtype *devtype;
unsigned int reset_required:1; /* If reset needed in serial_setup */
unsigned int falc31:1; /* are we falc v3.1 (atomic not necessary) */
unsigned int t1e1:8; /* T1 / E1 select pins */
int ledreg; /* LED Register */
@@ -505,7 +507,7 @@ static void t4_check_sigbits(struct t4 *wc, int span);
#define FMR5_EIBR (1 << 6) /* Internal Bit Robbing Access */
#define DEC_T 0x60 /* Diable Error Counter */
#define IERR_T 0x1B /* Single Bit Defect Insertion Register */
#define IBV 0 /* Bipolar violation */
#define IBV (1 << 0) /* Bipolar violation */
#define IPE (1 << 1) /* PRBS defect */
#define ICASE (1 << 2) /* CAS defect */
#define ICRCE (1 << 3) /* CRC defect */
@@ -1119,16 +1121,11 @@ static int t4_echocan_create(struct dahdi_chan *chan,
struct t4 *wc = chan->pvt;
struct t4_span *tspan = container_of(chan->span, struct t4_span, span);
int channel;
const struct dahdi_echocan_ops *ops;
const struct dahdi_echocan_features *features;
const bool alaw = (chan->span->deflaw == 2);
if (!vpmsupport || !wc->vpm)
return -ENODEV;
ops = &vpm_ec_ops;
features = &vpm_ec_features;
if (ecp->param_count > 0) {
dev_warn(&wc->dev->dev, "%s echo canceller does not support "
"parameters; failing request\n",
@@ -1137,8 +1134,8 @@ static int t4_echocan_create(struct dahdi_chan *chan,
}
*ec = tspan->ec[chan->chanpos - 1];
(*ec)->ops = ops;
(*ec)->features = *features;
(*ec)->ops = &vpm_ec_ops;
(*ec)->features = vpm_ec_features;
channel = has_e1_span(wc) ? chan->chanpos : chan->chanpos + 4;
@@ -1712,8 +1709,11 @@ _t4_spanconfig(struct file *file, struct dahdi_span *span,
if (lc->sync < 0)
lc->sync = 0;
if (lc->sync > wc->numspans)
if (lc->sync > wc->numspans) {
dev_warn(&wc->dev->dev, "WARNING: Cannot set priority on span %d to %d. Please set to a number between 1 and %d\n",
span->spanno, lc->sync, wc->numspans);
lc->sync = 0;
}
/* remove this span number from the current sync sources, if there */
for(i = 0; i < wc->numspans; i++) {
@@ -1890,6 +1890,33 @@ static void setup_chunks(struct t4 *wc, int which)
}
}
static int __t4_hardware_init_1(struct t4 *wc, unsigned int cardflags,
bool first_time);
static int __t4_hardware_init_2(struct t4 *wc, bool first_time);
static int t4_hardware_stop(struct t4 *wc);
static void t4_framer_reset(struct t4 *wc)
{
const bool first_time = false;
bool have_vpm = wc->vpm != NULL;
if (have_vpm) {
release_vpm450m(wc->vpm);
wc->vpm = NULL;
}
t4_hardware_stop(wc);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
__t4_hardware_init_1(wc, wc->devtype->flags, first_time);
__t4_hardware_init_2(wc, first_time);
if (have_vpm) {
t4_vpm_init(wc);
wc->dmactrl |= (wc->vpm) ? T4_VPM_PRESENT : 0;
t4_pci_out(wc, WC_DMACTRL, wc->dmactrl);
}
setup_chunks(wc, 0);
wc->lastindex = 0;
}
/**
* t4_serial_setup - Setup serial parameters and system interface.
* @wc: The card to configure.
@@ -1899,6 +1926,7 @@ static void t4_serial_setup(struct t4 *wc)
{
unsigned long flags;
unsigned int unit;
bool reset_required = false;
if (debug) {
dev_info(&wc->dev->dev,
@@ -1906,6 +1934,14 @@ static void t4_serial_setup(struct t4 *wc)
wc->numspans);
}
spin_lock_irqsave(&wc->reglock, flags);
reset_required = wc->reset_required > 0;
wc->reset_required = 0;
spin_unlock_irqrestore(&wc->reglock, flags);
if (reset_required)
t4_framer_reset(wc);
spin_lock_irqsave(&wc->reglock, flags);
/* GPC1: Multiplex mode enabled, FSC is output, active low, RCLK from
* channel 0 */
@@ -2056,6 +2092,7 @@ static void t4_span_assigned(struct dahdi_span *span)
struct t4 *wc = tspan->owner;
struct dahdi_span *pos;
unsigned int unassigned_spans = 0;
unsigned long flags;
/* We use this to make sure all the spans are assigned before
* running the serial setup. */
@@ -2064,8 +2101,14 @@ static void t4_span_assigned(struct dahdi_span *span)
++unassigned_spans;
}
if (0 == unassigned_spans)
if (0 == unassigned_spans) {
t4_serial_setup(wc);
set_bit(T4_CHECK_TIMING, &wc->checkflag);
spin_lock_irqsave(&wc->reglock, flags);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
spin_unlock_irqrestore(&wc->reglock, flags);
}
}
static void free_wc(struct t4 *wc)
@@ -2227,6 +2270,7 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
enum linemode mode;
const char *old_name;
static DEFINE_MUTEX(linemode_lock);
unsigned long flags;
dev_dbg(&wc->dev->dev, "Setting '%s' to '%s'\n", span->name,
dahdi_spantype2str(linemode));
@@ -2234,6 +2278,10 @@ static int t4_set_linemode(struct dahdi_span *span, enum spantypes linemode)
if (span->spantype == linemode)
return 0;
spin_lock_irqsave(&wc->reglock, flags);
wc->reset_required = 1;
spin_unlock_irqrestore(&wc->reglock, flags);
/* Do not allow the t1e1 member to be changed by multiple threads. */
mutex_lock(&linemode_lock);
old_name = dahdi_spantype2str(span->spantype);
@@ -2830,6 +2878,10 @@ static void __t4_configure_e1(struct t4 *wc, int unit, int lineconfig)
__t4_framer_out(wc, unit, 0x17, 0x04 | imr3extra); /* IMR3: AIS */
__t4_framer_out(wc, unit, 0x18, 0x3f); /* IMR4: We care about slips on transmit */
__t4_framer_out(wc, unit, 0x2f, 0x00);
__t4_framer_out(wc, unit, 0x30, 0x00);
__t4_framer_out(wc, unit, 0x31, 0x00);
dev_info(&wc->dev->dev, "TE%dXXP: Span %d configured for %s/%s%s\n",
wc->numspans, unit + 1, framing, line, crc4);
}
@@ -4306,7 +4358,7 @@ static void t4_vpm_init(struct t4 *wc)
laws[x] = 1;
}
vpm_capacity = get_vpm450m_capacity(wc);
vpm_capacity = get_vpm450m_capacity(&wc->dev->dev);
if (vpm_capacity != wc->numspans * 32) {
dev_info(&wc->dev->dev, "Disabling VPMOCT%03d. TE%dXXP"\
" requires a VPMOCT%03d", vpm_capacity,
@@ -4378,7 +4430,8 @@ static void t4_vpm_init(struct t4 *wc)
return;
}
if (!(wc->vpm = init_vpm450m(wc, laws, wc->numspans, firmware))) {
wc->vpm = init_vpm450m(&wc->dev->dev, laws, wc->numspans, firmware);
if (!wc->vpm) {
dev_notice(&wc->dev->dev, "VPM450: Failed to initialize\n");
if (firmware != &embedded_firmware)
release_firmware(firmware);
@@ -4865,17 +4918,18 @@ cleanup:
return res;
}
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
static int
__t4_hardware_init_1(struct t4 *wc, unsigned int cardflags, bool first_time)
{
unsigned int version;
int res;
version = t4_pci_in(wc, WC_VERSION);
if (is_octal(wc)) {
if (is_octal(wc) && first_time) {
dev_info(&wc->dev->dev, "Firmware Version: %01x.%02x\n",
(version & 0xf00) >> 8,
version & 0xff);
} else {
} else if (first_time) {
dev_info(&wc->dev->dev, "Firmware Version: %08x\n", version);
}
if (debug) {
@@ -4923,30 +4977,33 @@ static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
t4_pci_out(wc, WC_INTR, 0x00000000);
/* Read T1/E1 status */
if (!strcasecmp("auto", default_linemode)) {
if (-1 == t1e1override) {
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) & 0x0f00) >> 8);
wc->t1e1 &= 0xf;
if (is_octal(wc)) {
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
0x0f00) >> 4;
if (first_time) {
if (!strcasecmp("auto", default_linemode)) {
if (-1 == t1e1override) {
wc->t1e1 = (((t4_pci_in(wc, WC_LEDS)) &
0x0f00) >> 8);
wc->t1e1 &= 0xf;
if (is_octal(wc)) {
wc->t1e1 |= ((t4_pci_in(wc, WC_LEDS2)) &
0x0f00) >> 4;
}
} else {
dev_warn(&wc->dev->dev,
"'t1e1override' is deprecated. Please use 'default_linemode'.\n");
wc->t1e1 = t1e1override & 0xf;
}
} else if (!strcasecmp("t1", default_linemode)) {
wc->t1e1 = 0;
} else if (!strcasecmp("e1", default_linemode)) {
wc->t1e1 = 0xff;
} else if (!strcasecmp("j1", default_linemode)) {
wc->t1e1 = 0;
j1mode = 1;
} else {
dev_warn(&wc->dev->dev, "'t1e1override' is deprecated. "
"Please use 'default_linemode'.\n");
wc->t1e1 = t1e1override & 0xf;
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
default_linemode);
wc->t1e1 = 0;
}
} else if (!strcasecmp("t1", default_linemode)) {
wc->t1e1 = 0;
} else if (!strcasecmp("e1", default_linemode)) {
wc->t1e1 = 0xff;
} else if (!strcasecmp("j1", default_linemode)) {
wc->t1e1 = 0;
j1mode = 1;
} else {
dev_err(&wc->dev->dev, "'%s' is an unknown linemode.\n",
default_linemode);
wc->t1e1 = 0;
}
wc->order = ((t4_pci_in(wc, WC_LEDS)) & 0xf0000000) >> 28;
@@ -4975,7 +5032,12 @@ static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
return 0;
}
static int t4_hardware_init_2(struct t4 *wc)
static int t4_hardware_init_1(struct t4 *wc, unsigned int cardflags)
{
return __t4_hardware_init_1(wc, cardflags, true);
}
static int __t4_hardware_init_2(struct t4 *wc, bool first_time)
{
int x;
unsigned int regval;
@@ -5007,13 +5069,14 @@ static int t4_hardware_init_2(struct t4 *wc)
if (!is_octal(wc)) {
regval = t4_framer_in(wc, 0, 0x4a);
if (regval == 0x05) {
if (first_time && regval == 0x05) {
dev_info(&wc->dev->dev, "FALC Framer Version: 2.1 or "
"earlier\n");
} else if (regval == 0x20) {
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
if (first_time)
dev_info(&wc->dev->dev, "FALC Framer Version: 3.1\n");
wc->falc31 = 1;
} else {
} else if (first_time) {
dev_info(&wc->dev->dev, "FALC Framer Version: Unknown "
"(VSTR = 0x%02x)\n", regval);
}
@@ -5033,14 +5096,24 @@ static int t4_hardware_init_2(struct t4 *wc)
t4_pci_in(wc, x));
}
}
wc->gpio = 0x00000000;
t4_pci_out(wc, WC_GPIO, wc->gpio);
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
t4_gpio_setdir(wc, (0xff), (0xff));
return 0;
}
static int t4_hardware_init_2(struct t4 *wc)
{
return __t4_hardware_init_2(wc, true);
}
static int __devinit t4_launch(struct t4 *wc)
{
int x;
int res;
unsigned long flags;
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &wc->tspans[0]->span.flags))
return 0;
@@ -5072,17 +5145,14 @@ static int __devinit t4_launch(struct t4 *wc)
&wc->ddev->spans);
}
tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
res = dahdi_register_device(wc->ddev, &wc->dev->dev);
if (res) {
dev_err(&wc->dev->dev, "Failed to register with DAHDI.\n");
return res;
}
set_bit(T4_CHECK_TIMING, &wc->checkflag);
spin_lock_irqsave(&wc->reglock, flags);
__t4_set_sclk_src(wc, WC_SELF, 0, 0);
spin_unlock_irqrestore(&wc->reglock, flags);
tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc);
return 0;
}
@@ -5296,10 +5366,6 @@ t4_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
dev_info(&wc->dev->dev,
"Found a Wildcard: %s\n", wc->devtype->desc);
}
wc->gpio = 0x00000000;
t4_pci_out(wc, WC_GPIO, wc->gpio);
t4_gpio_setdir(wc, (1 << 17), (1 << 17));
t4_gpio_setdir(wc, (0xff), (0xff));
#ifdef VPM_SUPPORT
if (!wc->vpm) {

View File

@@ -31,99 +31,62 @@
#include <stdbool.h>
#include "vpm450m.h"
#include "oct6100api/oct6100_api.h"
#include <oct612x.h>
/* API for Octasic access */
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
static int wct4xxp_oct612x_write(struct oct612x_context *context,
u32 address, u16 value)
{
/* Why couldn't they just take a timeval like everyone else? */
struct timeval tv;
unsigned long long total_usecs;
unsigned int mask = ~0;
do_gettimeofday(&tv);
total_usecs = (((unsigned long long)(tv.tv_sec)) * 1000000) +
(((unsigned long long)(tv.tv_usec)));
f_pTime->aulWallTimeUs[0] = (total_usecs & mask);
f_pTime->aulWallTimeUs[1] = (total_usecs >> 32);
return cOCT6100_ERR_OK;
struct t4 *wc = dev_get_drvdata(context->dev);
oct_set_reg(wc, address, value);
return 0;
}
UINT32 Oct6100UserMemSet(PVOID f_pAddress, UINT32 f_ulPattern, UINT32 f_ulLength)
static int wct4xxp_oct612x_read(struct oct612x_context *context, u32 address,
u16 *value)
{
memset(f_pAddress, f_ulPattern, f_ulLength);
return cOCT6100_ERR_OK;
struct t4 *wc = dev_get_drvdata(context->dev);
*value = (u16)oct_get_reg(wc, address);
return 0;
}
UINT32 Oct6100UserMemCopy(PVOID f_pDestination, const void *f_pSource, UINT32 f_ulLength)
static int wct4xxp_oct612x_write_smear(struct oct612x_context *context,
u32 address, u16 value, size_t count)
{
memcpy(f_pDestination, f_pSource, f_ulLength);
return cOCT6100_ERR_OK;
struct t4 *wc = dev_get_drvdata(context->dev);
int i;
for (i = 0; i < count; ++i)
oct_set_reg(wc, address + (i << 1), value);
return 0;
}
UINT32 Oct6100UserCreateSerializeObject(tPOCT6100_CREATE_SERIALIZE_OBJECT f_pCreate)
static int wct4xxp_oct612x_write_burst(struct oct612x_context *context,
u32 address, const u16 *buffer,
size_t count)
{
return cOCT6100_ERR_OK;
struct t4 *wc = dev_get_drvdata(context->dev);
int i;
for (i = 0; i < count; ++i)
oct_set_reg(wc, address + (i << 1), buffer[i]);
return 0;
}
UINT32 Oct6100UserDestroySerializeObject(tPOCT6100_DESTROY_SERIALIZE_OBJECT f_pDestroy)
static int wct4xxp_oct612x_read_burst(struct oct612x_context *context,
u32 address, u16 *buffer, size_t count)
{
#ifdef OCTASIC_DEBUG
printk(KERN_DEBUG "I should never be called! (destroy serialize object)\n");
#endif
return cOCT6100_ERR_OK;
struct t4 *wc = dev_get_drvdata(context->dev);
int i;
for (i = 0; i < count; ++i)
buffer[i] = oct_get_reg(wc, address + (i << 1));
return 0;
}
UINT32 Oct6100UserSeizeSerializeObject(tPOCT6100_SEIZE_SERIALIZE_OBJECT f_pSeize)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserReleaseSerializeObject(tPOCT6100_RELEASE_SERIALIZE_OBJECT f_pRelease)
{
/* Not needed */
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteApi(tPOCT6100_WRITE_PARAMS f_pWriteParams)
{
oct_set_reg(f_pWriteParams->pProcessContext, f_pWriteParams->ulWriteAddress, f_pWriteParams->usWriteData);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteSmearApi(tPOCT6100_WRITE_SMEAR_PARAMS f_pSmearParams)
{
unsigned int x;
for (x=0;x<f_pSmearParams->ulWriteLength;x++) {
oct_set_reg(f_pSmearParams->pProcessContext, f_pSmearParams->ulWriteAddress + (x << 1), f_pSmearParams->usWriteData);
}
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverWriteBurstApi(tPOCT6100_WRITE_BURST_PARAMS f_pBurstParams)
{
unsigned int x;
for (x=0;x<f_pBurstParams->ulWriteLength;x++) {
oct_set_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulWriteAddress + (x << 1), f_pBurstParams->pusWriteData[x]);
}
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadApi(tPOCT6100_READ_PARAMS f_pReadParams)
{
*(f_pReadParams->pusReadData) = oct_get_reg(f_pReadParams->pProcessContext, f_pReadParams->ulReadAddress);
return cOCT6100_ERR_OK;
}
UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
{
unsigned int x;
for (x=0;x<f_pBurstParams->ulReadLength;x++) {
f_pBurstParams->pusReadData[x] = oct_get_reg(f_pBurstParams->pProcessContext, f_pBurstParams->ulReadAddress + (x << 1));
}
return cOCT6100_ERR_OK;
}
static const struct oct612x_ops wct4xxp_oct612x_ops = {
.write = wct4xxp_oct612x_write,
.read = wct4xxp_oct612x_read,
.write_smear = wct4xxp_oct612x_write_smear,
.write_burst = wct4xxp_oct612x_write_burst,
.read_burst = wct4xxp_oct612x_read_burst,
};
#define SOUT_G168_1100GB_ON 0x40000004
#define SOUT_DTMF_1 0x40000011
@@ -173,6 +136,7 @@ UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
struct vpm450m {
tPOCT6100_INSTANCE_API pApiInstance;
struct oct612x_context context;
UINT32 aulEchoChanHndl[256];
int chanflags[256];
int ecmode[256];
@@ -256,8 +220,10 @@ void vpm450m_set_alaw_companding(struct vpm450m *vpm450m, int channel,
pr_notice("Failed to apply echo can changes on channel %d %d %08x!\n",
vpm450m->aulEchoChanHndl[channel], channel, ulResult);
} else {
pr_info("Changed companding on channel %d to %s.\n", channel,
(alaw) ? "alaw" : "ulaw");
if (debug) {
pr_info("Changed companding on channel %d to %s.\n",
channel, (alaw) ? "alaw" : "ulaw");
}
if (alaw)
vpm450m->chanflags[channel] |= FLAG_ALAW;
else
@@ -451,14 +417,18 @@ int vpm450m_getdtmf(struct vpm450m *vpm450m, int *channel, int *tone, int *start
return 0;
}
unsigned int get_vpm450m_capacity(void *wc)
unsigned int get_vpm450m_capacity(struct device *device)
{
struct oct612x_context context;
UINT32 ulResult;
tOCT6100_API_GET_CAPACITY_PINS CapacityPins;
context.dev = device;
context.ops = &wct4xxp_oct612x_ops;
Oct6100ApiGetCapacityPinsDef(&CapacityPins);
CapacityPins.pProcessContext = wc;
CapacityPins.pProcessContext = &context;
CapacityPins.ulMemoryType = cOCT6100_MEM_TYPE_DDR;
CapacityPins.fEnableMemClkOut = TRUE;
CapacityPins.ulMemClkFreq = cOCT6100_MCLK_FREQ_133_MHZ;
@@ -472,7 +442,8 @@ unsigned int get_vpm450m_capacity(void *wc)
return CapacityPins.ulCapacityValue;
}
struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware)
struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
int numspans, const struct firmware *firmware)
{
tOCT6100_CHIP_OPEN *ChipOpen;
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
@@ -487,6 +458,8 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
return NULL;
memset(vpm450m, 0, sizeof(struct vpm450m));
vpm450m->context.dev = device;
vpm450m->context.ops = &wct4xxp_oct612x_ops;
if (!(ChipOpen = kmalloc(sizeof(tOCT6100_CHIP_OPEN), GFP_KERNEL))) {
kfree(vpm450m);
@@ -515,7 +488,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
ChipOpen->ulUpclkFreq = cOCT6100_UPCLK_FREQ_33_33_MHZ;
Oct6100GetInstanceSizeDef(&InstanceSize);
ChipOpen->pProcessContext = wc;
ChipOpen->pProcessContext = &vpm450m->context;
ChipOpen->pbyImageFile = firmware->data;
ChipOpen->ulImageSize = firmware->size;

View File

@@ -25,6 +25,7 @@
#include <linux/firmware.h>
struct t4;
struct vpm450m;
/* From driver */
@@ -32,8 +33,9 @@ unsigned int oct_get_reg(void *data, unsigned int reg);
void oct_set_reg(void *data, unsigned int reg, unsigned int val);
/* From vpm450m */
struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct firmware *firmware);
unsigned int get_vpm450m_capacity(void *wc);
struct vpm450m *init_vpm450m(struct device *device, int *isalaw,
int numspans, const struct firmware *firmware);
unsigned int get_vpm450m_capacity(struct device *device);
void vpm450m_setec(struct vpm450m *instance, int channel, int eclen);
void vpm450m_setdtmf(struct vpm450m *instance, int channel, int dtmfdetect, int dtmfmute);
int vpm450m_checkirq(struct vpm450m *vpm450m);
@@ -42,4 +44,6 @@ void release_vpm450m(struct vpm450m *instance);
void vpm450m_set_alaw_companding(struct vpm450m *vpm450m,
int channel, bool alaw);
extern int debug;
#endif

View File

@@ -3100,6 +3100,8 @@ wctdm_init_voicedaa(struct wctdm *wc, struct wctdm_module *mod,
spin_unlock_irqrestore(&wc->reglock, flags);
msleep(20);
memset(&mod->mod.fxo, 0, sizeof(mod->mod.fxo));
if (!sane && wctdm_voicedaa_insane(wc, mod))
return -2;
@@ -3244,8 +3246,7 @@ wctdm_init_proslic(struct wctdm *wc, struct wctdm_module *const mod,
return -2;
/* Initialize VMWI settings */
memset(&(fxs->vmwisetting), 0, sizeof(fxs->vmwisetting));
fxs->vmwi_linereverse = 0;
memset(fxs, 0, sizeof(*fxs));
/* By default, don't send on hook */
if (!reversepolarity != !fxs->reversepolarity)
@@ -4384,32 +4385,6 @@ wctdm_chanconfig(struct file *file, struct dahdi_chan *chan, int sigtype)
return wctdm_wait_for_ready(wc);
}
/*
* wctdm24xxp_assigned - Called when span is assigned.
* @span: The span that is now assigned.
*
* This function is called by the core of DAHDI after the span number and
* channel numbers have been assigned.
*
*/
static void wctdm24xxp_assigned(struct dahdi_span *span)
{
struct dahdi_span *s;
struct dahdi_device *ddev = span->parent;
struct wctdm *wc = NULL;
list_for_each_entry(s, &ddev->spans, device_node) {
wc = (container_of(s, struct wctdm_span, span))->wc;
if (!test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
return;
}
if (wc) {
WARN_ON(0 == wc->not_ready);
--wc->not_ready;
}
}
static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.owner = THIS_MODULE,
.hooksig = wctdm_hooksig,
@@ -4419,7 +4394,6 @@ static const struct dahdi_span_ops wctdm24xxp_analog_span_ops = {
.watchdog = wctdm_watchdog,
.chanconfig = wctdm_chanconfig,
.dacs = wctdm_dacs,
.assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -4438,7 +4412,6 @@ static const struct dahdi_span_ops wctdm24xxp_digital_span_ops = {
.spanconfig = b400m_spanconfig,
.chanconfig = b400m_chanconfig,
.dacs = wctdm_dacs,
.assigned = wctdm24xxp_assigned,
#ifdef VPM_SUPPORT
.enable_hw_preechocan = wctdm_enable_hw_preechocan,
.disable_hw_preechocan = wctdm_disable_hw_preechocan,
@@ -5951,6 +5924,9 @@ __wctdm_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return -1;
}
WARN_ON(wc->not_ready <= 0);
--wc->not_ready;
dev_info(&wc->vb.pdev->dev,
"Found a %s: %s (%d BRI spans, %d analog %s)\n",
(is_hx8(wc)) ? "Hybrid card" : "Wildcard TDM",

File diff suppressed because it is too large Load Diff

3575
drivers/dahdi/wcte43x-base.c Normal file

File diff suppressed because it is too large Load Diff

1009
drivers/dahdi/wcxb.c Normal file

File diff suppressed because it is too large Load Diff

192
drivers/dahdi/wcxb.h Normal file
View File

@@ -0,0 +1,192 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 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 __WCXB_H__
#define __WCXB_H__
#define WCXB_DEFAULT_LATENCY 3U
#define WCXB_DEFAULT_MAXLATENCY 20U
#define WCXB_DMA_CHAN_SIZE 128
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
/* The is_pcie member was backported but I'm not sure in which version. */
# ifndef RHEL_RELEASE_VERSION
#define WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
# endif
#else
#endif
struct wcxb;
struct wcxb_operations {
void (*handle_receive)(struct wcxb *xb, void *frame);
void (*handle_transmit)(struct wcxb *xb, void *frame);
void (*handle_error)(struct wcxb *xb);
void (*handle_interrupt)(struct wcxb *xb, u32 pending);
};
struct wcxb_meta_desc;
struct wcxb_hw_desc;
struct wcxb {
struct pci_dev *pdev;
spinlock_t lock;
const struct wcxb_operations *ops;
unsigned int *debug;
unsigned int max_latency;
unsigned int latency;
struct {
u32 have_msi:1;
u32 latency_locked:1;
u32 drive_timing_cable:1;
#ifdef WCXB_PCI_DEV_DOES_NOT_HAVE_IS_PCIE
u32 is_pcie:1;
#endif
} flags;
void __iomem *membase;
struct wcxb_meta_desc *meta_dring;
struct wcxb_hw_desc *hw_dring;
unsigned int dma_head;
unsigned int dma_tail;
dma_addr_t hw_dring_phys;
struct dma_pool *pool;
unsigned long framecount;
};
extern int wcxb_init(struct wcxb *xb, const char *board_name, u32 int_mode);
extern void wcxb_release(struct wcxb *xb);
extern int wcxb_start(struct wcxb *xb);
extern void wcxb_stop(struct wcxb *xb);
extern int wcxb_wait_for_stop(struct wcxb *xb, unsigned long timeout_ms);
extern bool wcxb_is_stopped(struct wcxb *xb);
enum wcxb_clock_sources {
WCXB_CLOCK_SELF, /* Use the internal oscillator for timing. */
WCXB_CLOCK_RECOVER, /* Recover the clock from a framer. */
#ifdef RPC_RCLK
WCXB_CLOCK_RECOVER_ALT, /* Recover the clock from a framer. */
#endif
WCXB_CLOCK_SLAVE /* Recover clock from any timing header. */
};
extern enum wcxb_clock_sources wcxb_get_clksrc(struct wcxb *xb);
extern void wcxb_set_clksrc(struct wcxb *xb, enum wcxb_clock_sources clksrc);
static inline void wcxb_enable_timing_header_driver(struct wcxb *xb)
{
xb->flags.drive_timing_cable = 1;
}
static inline bool wcxb_is_timing_header_driver_enabled(struct wcxb *xb)
{
return 1 == xb->flags.drive_timing_cable;
}
static inline void wcxb_disable_timing_header_driver(struct wcxb *xb)
{
xb->flags.drive_timing_cable = 0;
}
enum wcxb_reset_option {
WCXB_RESET_NOW,
WCXB_RESET_LATER
};
extern u32 wcxb_get_firmware_version(struct wcxb *xb);
extern int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
const char *firmware_filename,
bool force_firmware,
enum wcxb_reset_option reset);
extern void wcxb_stop_dma(struct wcxb *xb);
extern void wcxb_disable_interrupts(struct wcxb *xb);
static inline void wcxb_gpio_set(struct wcxb *xb, u32 bits)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be(reg | bits, xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void wcxb_gpio_clear(struct wcxb *xb, u32 bits)
{
u32 reg;
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
reg = ioread32be(xb->membase);
iowrite32be(reg & (~bits), xb->membase);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_set_maxlatency(struct wcxb *xb, unsigned int max_latency)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->max_latency = clamp(max_latency,
xb->latency,
WCXB_DEFAULT_MAXLATENCY);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_set_minlatency(struct wcxb *xb, unsigned int min_latency)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->latency = clamp(min_latency, WCXB_DEFAULT_LATENCY,
WCXB_DEFAULT_MAXLATENCY);
spin_unlock_irqrestore(&xb->lock, flags);
}
static inline void
wcxb_lock_latency(struct wcxb *xb)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->flags.latency_locked = 1;
spin_unlock_irqrestore(&xb->lock, flags);
return;
}
static inline void
wcxb_unlock_latency(struct wcxb *xb)
{
unsigned long flags;
spin_lock_irqsave(&xb->lock, flags);
xb->flags.latency_locked = 0;
spin_unlock_irqrestore(&xb->lock, flags);
return;
}
/* Interface for the echocan block */
extern void wcxb_enable_echocan(struct wcxb *xb);
extern void wcxb_disable_echocan(struct wcxb *xb);
extern void wcxb_reset_echocan(struct wcxb *xb);
extern void wcxb_enable_echocan_dram(struct wcxb *xb);
extern bool wcxb_is_echocan_present(struct wcxb *xb);
extern u16 wcxb_get_echocan_reg(struct wcxb *xb, u32 address);
extern void wcxb_set_echocan_reg(struct wcxb *xb, u32 address, u16 val);
#endif

170
drivers/dahdi/wcxb_flash.c Normal file
View File

@@ -0,0 +1,170 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 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.
*/
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/sched.h>
#include "wcxb_spi.h"
#include "wcxb_flash.h"
#define FLASH_PAGE_PROGRAM 0x02
#define FLASH_READ 0x03
#define FLASH_READ_STATUS 0x05
#define FLASH_WRITE_ENABLE 0x06
#define FLASH_SECTOR_ERASE 0xd8
static int wcxb_flash_read_status_register(struct wcxb_spi_device *spi,
u8 *status)
{
u8 command[] = {
FLASH_READ_STATUS,
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_serial = {
.rx_buf = status,
.len = 1,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_serial, &m);
return wcxb_spi_sync(spi, &m);
}
int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address,
void *data, size_t len)
{
u8 command[] = {
FLASH_READ,
(address & 0xff0000) >> 16,
(address & 0xff00) >> 8,
(address & 0xff)
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_serial = {
.rx_buf = data,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_serial, &m);
return wcxb_spi_sync(spi, &m);
}
static int wcxb_flash_wait_until_not_busy(struct wcxb_spi_device *spi)
{
int res;
u8 status;
unsigned long stop = jiffies + 5*HZ;
do {
res = wcxb_flash_read_status_register(spi, &status);
} while (!res && (status & 0x1) && time_before(jiffies, stop));
if (!res)
return res;
if (time_after_eq(jiffies, stop))
return -EIO;
return 0;
}
static int wcxb_flash_write_enable(struct wcxb_spi_device *spi)
{
u8 command = FLASH_WRITE_ENABLE;
return wcxb_spi_write(spi, &command, 1);
}
int wcxb_flash_sector_erase(struct wcxb_spi_device *spi,
unsigned int address)
{
int res;
u8 command[] = {FLASH_SECTOR_ERASE, (address >> 16)&0xff, 0x00, 0x00};
/* Sector must be on 64KB boundary. */
if (address & 0xffff)
return -EINVAL;
/* Start the erase. */
res = wcxb_flash_write_enable(spi);
if (res)
return res;
res = wcxb_spi_write(spi, &command, sizeof(command));
if (res)
return res;
return wcxb_flash_wait_until_not_busy(spi);
}
int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address,
const void *data, size_t len)
{
int res;
const size_t FLASH_PAGE_SIZE = 256;
u8 command[] = {
FLASH_PAGE_PROGRAM,
(address & 0xff0000) >> 16,
(address & 0xff00) >> 8,
0x00,
};
struct wcxb_spi_transfer t_cmd = {
.tx_buf = command,
.len = sizeof(command),
};
struct wcxb_spi_transfer t_data = {
.tx_buf = data,
.len = len,
};
struct wcxb_spi_message m;
/* We need to write on page size boundaries */
WARN_ON(address & 0xff);
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t_cmd, &m);
wcxb_spi_message_add_tail(&t_data, &m);
while (len) {
res = wcxb_flash_write_enable(spi);
if (res)
return res;
command[1] = (address >> 16) & 0xff;
command[2] = (address >> 8) & 0xff;
t_data.tx_buf = data;
t_data.len = min(len, FLASH_PAGE_SIZE);
res = wcxb_spi_sync(spi, &m);
WARN_ON(res);
if (res)
return res;
res = wcxb_flash_wait_until_not_busy(spi);
WARN_ON(res);
if (res)
return res;
len -= t_data.len;
address += t_data.len;
data += t_data.len;
}
return 0;
}

View File

@@ -0,0 +1,34 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 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 __WCXB_FLASH_H__
#define __WCXB_FLASH_H__
extern int wcxb_flash_read(struct wcxb_spi_device *spi, unsigned int address,
void *data, size_t len);
extern int wcxb_flash_sector_erase(struct wcxb_spi_device *spi, unsigned int
address);
extern int wcxb_flash_write(struct wcxb_spi_device *spi, unsigned int address,
const void *data, size_t len);
#endif

386
drivers/dahdi/wcxb_spi.c Normal file
View File

@@ -0,0 +1,386 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 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.
*/
#define DEBUG
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/device.h>
#include <linux/completion.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <dahdi/kernel.h>
#include "wcxb_spi.h"
#define BBIT(n) (1UL << (31UL - (n)))
#define SPISRR 0x40
#define SPISRR_RESET 0x0000000a /* Resets Device */
#define SPICR 0x60
#define SPICR_LSB_FIRST BBIT(22) /* LSB First. 0=MSB first transfer */
#define SPICR_MASTER_INHIBIT BBIT(23) /* Master Transaction Inhibit */
#define SPICR_SLAVE_SELECT BBIT(24) /* Manual Slave Select Assert Enable */
#define SPICR_RX_FIFO_RESET BBIT(25) /* Receive FIFO Reset */
#define SPICR_TX_FIFO_RESET BBIT(26) /* Transmit FIFO Reset */
#define SPICR_CPHA BBIT(27) /* Clock Phase */
#define SPICR_CPOL BBIT(28) /* Clock Polarity 0=Active High */
#define SPICR_MASTER BBIT(29) /* Master Enable */
#define SPICR_SPE BBIT(30) /* SPI System Enable */
#define SPICR_LOOP BBIT(31) /* Local Loopback Mode */
#define SPICR_START_TRANSFER (SPICR_CPHA | SPICR_CPOL | \
SPICR_MASTER | SPICR_SPE)
#define SPICR_READY_TRANSFER (SPICR_MASTER_INHIBIT | SPICR_START_TRANSFER)
#define SPISR 0x64 /* SPI Status Register */
#define SPISR_SLAVE_MODE_SEL BBIT(26) /* Slave Mode Select Flag */
#define SPISR_MODF BBIT(27) /* Mode-Fault Error Flag */
#define SPISR_TX_FULL BBIT(28) /* Transmit FIFO Full */
#define SPISR_TX_EMPTY BBIT(29) /* Transmit FIFO Empty */
#define SPISR_RX_FULL BBIT(30) /* Receive FIFO Full */
#define SPISR_RX_EMPTY BBIT(31) /* Receive FIFO Empty */
#define SPIDTR 0x68 /* SPI Data Transmit Register */
#define SPIDRR 0x6c /* SPI Data Receive Register */
#define SPISSR 0x70 /* SPI Slave Select Register */
#undef SUCCESS
#define SUCCESS 0
struct wcxb_spi_master {
struct device *parent;
struct list_head message_queue;
spinlock_t lock;
void __iomem *base;
struct wcxb_spi_message *cur_msg;
struct wcxb_spi_transfer *cur_transfer;
u16 bytes_left;
u16 bytes_in_fifo;
const u8 *cur_tx_byte;
u8 *cur_rx_byte;
u16 auto_cs:1;
};
static inline void _wcxb_assert_chip_select(struct wcxb_spi_master *master,
unsigned int cs)
{
const int cs_mask = ~(1UL << cs);
iowrite32be(cs_mask, master->base + SPISSR);
ioread32be(master->base + SPISSR);
}
static inline void _wcxb_clear_chip_select(struct wcxb_spi_master *master)
{
iowrite32be(~(0), master->base + SPISSR);
ioread32(master->base + SPISSR);
}
static inline void wcxb_spi_reset_controller(struct wcxb_spi_master *master)
{
u32 spicr = SPICR_READY_TRANSFER;
spicr |= (master->auto_cs) ? 0 : SPICR_SLAVE_SELECT;
iowrite32be(SPISRR_RESET, master->base + SPISRR);
iowrite32be(spicr, master->base + SPICR);
iowrite32be(0xffffffff, master->base + SPISSR);
}
struct wcxb_spi_master *wcxb_spi_master_create(struct device *parent,
void __iomem *membase,
bool auto_cs)
{
struct wcxb_spi_master *master = NULL;
master = kzalloc(sizeof(struct wcxb_spi_master), GFP_KERNEL);
if (!master)
goto error_exit;
spin_lock_init(&master->lock);
INIT_LIST_HEAD(&master->message_queue);
master->base = membase;
master->parent = parent;
master->auto_cs = (auto_cs) ? 1 : 0;
wcxb_spi_reset_controller(master);
return master;
error_exit:
kfree(master);
return NULL;
}
void wcxb_spi_master_destroy(struct wcxb_spi_master *master)
{
struct wcxb_spi_message *m;
if (!master)
return;
while (!list_empty(&master->message_queue)) {
m = list_first_entry(&master->message_queue,
struct wcxb_spi_message, node);
list_del(&m->node);
if (m->complete)
m->complete(m->arg);
}
kfree(master);
return;
}
static inline bool is_txfifo_empty(const struct wcxb_spi_master *master)
{
return ((ioread32(master->base + SPISR) &
cpu_to_be32(SPISR_TX_EMPTY)) > 0);
}
static const u8 DUMMY_TX = 0xff;
static u8 DUMMY_RX;
static void _wcxb_spi_transfer_to_fifo(struct wcxb_spi_master *master)
{
const unsigned int FIFO_SIZE = 16;
u32 spicr;
while (master->bytes_left && master->bytes_in_fifo < FIFO_SIZE) {
iowrite32be(*master->cur_tx_byte, master->base + SPIDTR);
master->bytes_in_fifo++;
master->bytes_left--;
if (&DUMMY_TX != master->cur_tx_byte)
master->cur_tx_byte++;
}
spicr = (master->auto_cs) ? SPICR_START_TRANSFER :
SPICR_START_TRANSFER | SPICR_SLAVE_SELECT;
iowrite32be(spicr, master->base + SPICR);
}
static void _wcxb_spi_transfer_from_fifo(struct wcxb_spi_master *master)
{
u32 spicr;
while (master->bytes_in_fifo) {
*master->cur_rx_byte = ioread32be(master->base + SPIDRR);
if (&DUMMY_RX != master->cur_rx_byte)
master->cur_rx_byte++;
--master->bytes_in_fifo;
}
spicr = SPICR_START_TRANSFER;
spicr |= (master->auto_cs) ? 0 : SPICR_SLAVE_SELECT;
iowrite32be(spicr | SPICR_MASTER_INHIBIT, master->base + SPICR);
}
static void _wcxb_spi_start_transfer(struct wcxb_spi_master *master,
struct wcxb_spi_transfer *t)
{
#ifdef DEBUG
if (!t || !master || (!t->tx_buf && !t->rx_buf) ||
master->cur_transfer) {
WARN_ON(1);
return;
}
#endif
master->cur_transfer = t;
master->bytes_left = t->len;
master->cur_tx_byte = (t->tx_buf) ?: &DUMMY_TX;
master->cur_rx_byte = (t->rx_buf) ?: &DUMMY_RX;
_wcxb_spi_transfer_to_fifo(master);
}
/**
* _wcxb_spi_start_message - Start a new message transferring.
*
* Must be called with master->lock held.
*
*/
static int _wcxb_spi_start_message(struct wcxb_spi_master *master,
struct wcxb_spi_message *message)
{
struct wcxb_spi_transfer *t;
if (master->cur_msg) {
/* There is already a message in progress. Queue for later. */
list_add_tail(&message->node, &master->message_queue);
return 0;
}
if (!message->spi) {
dev_dbg(master->parent,
"Queueing message without SPI device specified?\n");
return -EINVAL;
};
master->cur_msg = message;
_wcxb_assert_chip_select(master, message->spi->chip_select);
t = list_first_entry(&message->transfers,
struct wcxb_spi_transfer, node);
_wcxb_spi_start_transfer(master, t);
return 0;
}
/**
* wcxb_spi_complete_message - Complete the current message.
*
* Called after all transfers in current message have been completed. This will
* complete the current message and start the next queued message if there are
* any.
*
* Must be called with the master->lock held.
*
*/
static void _wcxb_spi_complete_cur_msg(struct wcxb_spi_master *master)
{
struct wcxb_spi_message *message;
if (!master->cur_msg)
return;
message = master->cur_msg;
message->status = SUCCESS;
_wcxb_clear_chip_select(master);
master->cur_msg = NULL;
if (!list_empty(&master->message_queue)) {
message = list_first_entry(&master->message_queue,
struct wcxb_spi_message, node);
list_del(&message->node);
_wcxb_spi_start_message(master, message);
}
return;
}
static inline bool
_wcxb_spi_is_last_transfer(const struct wcxb_spi_transfer *t,
const struct wcxb_spi_message *message)
{
return t->node.next == &message->transfers;
}
static inline struct wcxb_spi_transfer *
_wcxb_spi_next_transfer(struct wcxb_spi_transfer *t)
{
return list_entry(t->node.next, struct wcxb_spi_transfer, node);
}
/**
* wcxb_spi_handle_interrupt - Drives the transfers forward.
*
* Doesn't necessarily need to be called in the context of a real interrupt, but
* should be called with interrupts disabled on the local CPU.
*
*/
void wcxb_spi_handle_interrupt(struct wcxb_spi_master *master)
{
struct wcxb_spi_message *msg;
struct wcxb_spi_transfer *t;
void (*complete)(void *arg) = NULL;
unsigned long flags;
/* Check if we're not in the middle of a transfer, or not finished with
* a part of one. */
spin_lock_irqsave(&master->lock, flags);
t = master->cur_transfer;
msg = master->cur_msg;
if (!msg || !is_txfifo_empty(master))
goto done;
#ifdef DEBUG
if (!t) {
dev_dbg(master->parent,
"No current transfer in %s\n", __func__);
goto done;
}
#endif
/* First read any data out of the receive FIFO into the current
* transfer. */
_wcxb_spi_transfer_from_fifo(master);
if (master->bytes_left) {
/* The current transfer isn't finished. */
_wcxb_spi_transfer_to_fifo(master);
goto done;
}
/* The current transfer is finished. Check for another transfer in this
* message or complete it and look for another message to start. */
master->cur_transfer = NULL;
if (_wcxb_spi_is_last_transfer(t, msg)) {
complete = msg->complete;
_wcxb_spi_complete_cur_msg(master);
} else {
t = _wcxb_spi_next_transfer(t);
_wcxb_spi_start_transfer(master, t);
}
done:
spin_unlock_irqrestore(&master->lock, flags);
/* Do not call the complete call back under the bus lock. */
if (complete)
complete(msg->arg);
return;
}
int wcxb_spi_async(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message)
{
int res;
unsigned long flags;
WARN_ON(!spi || !message || !spi->master);
if (list_empty(&message->transfers)) {
/* No transfers in this message? */
if (message->complete)
message->complete(message->arg);
message->status = -EINVAL;
return 0;
}
message->status = -EINPROGRESS;
message->spi = spi;
spin_lock_irqsave(&spi->master->lock, flags);
res = _wcxb_spi_start_message(spi->master, message);
spin_unlock_irqrestore(&spi->master->lock, flags);
return res;
}
static void wcxb_spi_complete_message(void *arg)
{
complete((struct completion *)arg);
}
int wcxb_spi_sync(struct wcxb_spi_device *spi, struct wcxb_spi_message *message)
{
DECLARE_COMPLETION_ONSTACK(done);
WARN_ON(!spi || !spi->master);
message->complete = wcxb_spi_complete_message;
message->arg = &done;
wcxb_spi_async(spi, message);
/* TODO: There has got to be a better way to do this. */
while (!try_wait_for_completion(&done)) {
wcxb_spi_handle_interrupt(spi->master);
cpu_relax();
}
return message->status;
}

116
drivers/dahdi/wcxb_spi.h Normal file
View File

@@ -0,0 +1,116 @@
/*
* wcxb SPI library
*
* Copyright (C) 2013 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 __WCXB_SPI_H
#define __WCXB_SPI_H
#include <linux/spi/spi.h>
#include <stdbool.h>
struct wcxb_spi_transfer {
const void *tx_buf;
void *rx_buf;
u32 len:16;
u16 delay_usecs;
struct list_head node;
};
struct wcxb_spi_message {
struct list_head transfers;
struct list_head node;
struct wcxb_spi_device *spi;
void (*complete)(void *arg);
void *arg;
int status;
};
struct wcxb_spi_master;
struct wcxb_spi_device {
struct wcxb_spi_master *master;
u16 chip_select;
};
extern struct wcxb_spi_master *wcxb_spi_master_create(struct device *parent,
void __iomem *base, bool auto_cs);
extern void wcxb_spi_master_destroy(struct wcxb_spi_master *master);
extern int wcxb_spi_sync(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message);
extern int wcxb_spi_async(struct wcxb_spi_device *spi,
struct wcxb_spi_message *message);
extern void wcxb_spi_handle_interrupt(struct wcxb_spi_master *master);
static inline struct wcxb_spi_device *
wcxb_spi_device_create(struct wcxb_spi_master *master, u16 chip_select)
{
struct wcxb_spi_device *spi = kzalloc(sizeof(*spi), GFP_KERNEL);
if (!spi)
return NULL;
spi->master = master;
spi->chip_select = chip_select;
return spi;
}
static inline void wcxb_spi_device_destroy(struct wcxb_spi_device *spi)
{
kfree(spi);
}
static inline void wcxb_spi_message_init(struct wcxb_spi_message *m)
{
memset(m, 0, sizeof(*m));
INIT_LIST_HEAD(&m->transfers);
}
static inline void wcxb_spi_message_add_tail(struct wcxb_spi_transfer *t,
struct wcxb_spi_message *m)
{
list_add_tail(&t->node, &m->transfers);
}
static inline int
wcxb_spi_write(struct wcxb_spi_device *spi, const void *buffer, size_t len)
{
struct wcxb_spi_transfer t = {
.tx_buf = buffer,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t, &m);
return wcxb_spi_sync(spi, &m);
}
static inline int
wcxb_spi_read(struct wcxb_spi_device *spi, void *buffer, size_t len)
{
struct wcxb_spi_transfer t = {
.rx_buf = buffer,
.len = len,
};
struct wcxb_spi_message m;
wcxb_spi_message_init(&m);
wcxb_spi_message_add_tail(&t, &m);
return wcxb_spi_sync(spi, &m);
}
#endif

View File

@@ -654,6 +654,95 @@ static void __do_mute_dtmf(xpd_t *xpd, int pos, bool muteit)
CALL_PHONE_METHOD(card_pcm_recompute, xpd, priv->search_fsk_pattern);
}
struct ring_reg_param {
int is_indirect;
int regno;
uint8_t h_val;
uint8_t l_val;
};
enum ring_types {
RING_TYPE_NEON = 0,
RING_TYPE_TRAPEZ,
RING_TYPE_NORMAL,
};
struct byte_pair {
uint8_t h_val;
uint8_t l_val;
};
struct ring_reg_params {
const int is_indirect;
const int regno;
struct byte_pair values[1 + RING_TYPE_NORMAL - RING_TYPE_NEON];
};
#define REG_ENTRY(di, reg, vh1, vl1, vh2, vl2, vh3, vl3) \
{ (di), (reg), .values = { \
[RING_TYPE_NEON] = { .h_val = (vh1), .l_val = (vl1) }, \
[RING_TYPE_TRAPEZ] = { .h_val = (vh2), .l_val = (vl2) }, \
[RING_TYPE_NORMAL] = { .h_val = (vh3), .l_val = (vl3) }, \
}, \
}
static struct ring_reg_params ring_parameters[] = {
/* INDIR REG NEON TRAPEZ NORMAL */
REG_ENTRY(1, 0x16, 0xE8, 0x03, 0xC8, 0x00, 0x00, 0x00),
REG_ENTRY(1, 0x15, 0xEF, 0x7B, 0xAB, 0x5E, 0x77, 0x01),
REG_ENTRY(1, 0x14, 0x9F, 0x00, 0x8C, 0x01, 0xFD, 0x7E),
REG_ENTRY(0, 0x22, 0x00, 0x19, 0x00, 0x01, 0x00, 0x00),
REG_ENTRY(0, 0x30, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(0, 0x31, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(0, 0x32, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(0, 0x33, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00),
REG_ENTRY(1, 0x1D, 0x00, 0x46, 0x00, 0x36, 0x00, 0x36),
};
static int send_ring_parameters(xbus_t *xbus, xpd_t *xpd, int pos,
enum ring_types rtype)
{
const struct ring_reg_params *p;
const struct byte_pair *v;
int ret = 0;
int i;
if (rtype < RING_TYPE_NEON || rtype > RING_TYPE_NORMAL)
return -EINVAL;
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
p = &ring_parameters[i];
v = &(p->values[rtype]);
if (p->is_indirect) {
LINE_DBG(REGS, xpd, pos,
"[%d] 0x%02X: I 0x%02X 0x%02X\n",
i, p->regno, v->h_val, v->l_val);
ret = SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
p->regno, v->h_val, v->l_val);
if (ret < 0) {
LINE_ERR(xpd, pos,
"Failed: 0x%02X: I 0x%02X, 0x%02X\n",
p->regno, v->h_val, v->l_val);
break;
}
} else {
LINE_DBG(REGS, xpd, pos, "[%d] 0x%02X: D 0x%02X\n",
i, p->regno, v->l_val);
ret = SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
p->regno, v->l_val);
if (ret < 0) {
LINE_ERR(xpd, pos,
"Failed: 0x%02X: D 0x%02X\n",
p->regno, v->l_val);
break;
}
}
}
return ret;
}
static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
unsigned int msg_waiting)
{
@@ -667,81 +756,15 @@ static int set_vm_led_mode(xbus_t *xbus, xpd_t *xpd, int pos,
/* 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);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16,
0xE8, 0x03);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15,
0xEF, 0x7B);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14,
0x9F, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x19);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0xE0);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x01);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0xF0);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x05);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D,
0x00, 0x46);
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NEON);
} else if (ring_trapez) {
LINE_DBG(SIGNAL, xpd, pos, "RINGER: Trapez ring\n");
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x16,
0xC8, 0x00);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x15,
0xAB, 0x5E);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x14,
0x8C, 0x01);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x22, 0x01);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x4A, 0x34);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x30, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x31, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x32, 0x00);
ret +=
SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x33, 0x00);
ret +=
SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE, 0x1D,
0x00, 0x36);
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);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x16, 0x00, 0x00);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x15, 0x77, 0x01);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x14, 0xFD, 0x7E);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x22, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x30, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x31, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x32, 0x00);
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x33, 0x00);
/* High Vbat~ -82V[Dc] */
ret += SLIC_DIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x4A, 0x34);
ret += SLIC_INDIRECT_REQUEST(xbus, xpd, pos, SLIC_WRITE,
0x1D, 0x00, 0x36);
ret = send_ring_parameters(xbus, xpd, pos, RING_TYPE_NORMAL);
}
return (ret ? -EPROTO : 0);
}
@@ -1838,9 +1861,134 @@ static const struct file_operations proc_xpd_metering_ops = {
#endif
#endif
static DEVICE_ATTR_READER(fxs_ring_registers_show, dev, buf)
{
xpd_t *xpd;
struct FXS_priv_data *priv;
unsigned long flags;
const struct ring_reg_params *p;
const struct byte_pair *v;
enum ring_types rtype;
int len = 0;
int i;
BUG_ON(!dev);
xpd = dev_to_xpd(dev);
if (!xpd)
return -ENODEV;
priv = xpd->priv;
BUG_ON(!priv);
spin_lock_irqsave(&xpd->lock, flags);
len += sprintf(buf + len, "# Reg#: D/I\tNEON \tTRAPEZ \tNORMAL \n");
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
p = &ring_parameters[i];
len += sprintf(buf + len, "[%d] 0x%02X: %c",
i, p->regno, (p->is_indirect) ? 'I' : 'D');
for (rtype = RING_TYPE_NEON; rtype <= RING_TYPE_NORMAL; rtype++) {
v = &(p->values[rtype]);
if (p->is_indirect)
len += sprintf(buf + len, "\t0x%02X 0x%02X",
v->h_val, v->l_val);
else
len += sprintf(buf + len, "\t0x%02X ----",
v->l_val);
}
len += sprintf(buf + len, "\n");
}
spin_unlock_irqrestore(&xpd->lock, flags);
return len;
}
static DEVICE_ATTR_WRITER(fxs_ring_registers_store, dev, buf, count)
{
xpd_t *xpd;
struct FXS_priv_data *priv;
unsigned long flags;
char rtype_name[MAX_PROC_WRITE];
enum ring_types rtype;
struct ring_reg_params *params;
struct byte_pair *v;
int regno;
int h_val;
int l_val;
int ret;
int i;
BUG_ON(!dev);
xpd = dev_to_xpd(dev);
if (!xpd)
return -ENODEV;
priv = xpd->priv;
BUG_ON(!priv);
ret = sscanf(buf, "%10s %X %X %X\n",
rtype_name, &regno, &h_val, &l_val);
if (ret < 3 || ret > 4) {
XPD_ERR(xpd, "Bad input: '%s'\n", buf);
XPD_ERR(xpd, "# Correct input\n");
XPD_ERR(xpd, "{NEON|TRAPEZ|NORMAL} <regno> <byte> [<byte>]\n");
goto invalid_input;
}
if (strcasecmp("NEON", rtype_name) == 0)
rtype = RING_TYPE_NEON;
else if (strcasecmp("TRAPEZ", rtype_name) == 0)
rtype = RING_TYPE_TRAPEZ;
else if (strcasecmp("NORMAL", rtype_name) == 0)
rtype = RING_TYPE_NORMAL;
else {
XPD_ERR(xpd, "Unknown ring type '%s' (NEON/TRAPEZ/NORMAL)\n",
rtype_name);
goto invalid_input;
}
params = NULL;
for (i = 0; i < ARRAY_SIZE(ring_parameters); i++) {
if (ring_parameters[i].regno == regno) {
params = &ring_parameters[i];
break;
}
}
if (!params) {
XPD_ERR(xpd, "Bad register 0x%X\n", regno);
goto invalid_input;
}
if (params->is_indirect) {
if (ret != 4) {
XPD_ERR(xpd,
"Missing low-byte (0x%X is indirect register)\n",
regno);
goto invalid_input;
}
XPD_INFO(xpd, "%s Indirect 0x%X <=== 0x%X 0x%X\n",
rtype_name, regno, h_val, l_val);
} else {
if (ret != 3) {
XPD_ERR(xpd,
"Should give exactly one value (0x%X is direct register)\n",
regno);
goto invalid_input;
}
l_val = h_val;
h_val = 0;
XPD_INFO(xpd, "%s Direct 0x%X <=== 0x%X\n",
rtype_name, regno, h_val);
}
spin_lock_irqsave(&xpd->lock, flags);
v = &(params->values[rtype]);
v->h_val = h_val;
v->l_val = l_val;
spin_unlock_irqrestore(&xpd->lock, flags);
return count;
invalid_input:
return -EINVAL;
}
static DEVICE_ATTR(fxs_ring_registers, S_IRUGO | S_IWUSR,
fxs_ring_registers_show,
fxs_ring_registers_store);
static int fxs_xpd_probe(struct device *dev)
{
xpd_t *xpd;
int ret;
xpd = dev_to_xpd(dev);
/* Is it our device? */
@@ -1850,7 +1998,15 @@ static int fxs_xpd_probe(struct device *dev)
return -EINVAL;
}
XPD_DBG(DEVICES, xpd, "SYSFS\n");
ret = device_create_file(dev, &dev_attr_fxs_ring_registers);
if (ret) {
XPD_ERR(xpd, "%s: device_create_file(fxs_ring_registers) failed: %d\n",
__func__, ret);
goto fail_fxs_ring_registers;
}
return 0;
fail_fxs_ring_registers:
return ret;
}
static int fxs_xpd_remove(struct device *dev)
@@ -1859,6 +2015,7 @@ static int fxs_xpd_remove(struct device *dev)
xpd = dev_to_xpd(dev);
XPD_DBG(DEVICES, xpd, "SYSFS\n");
device_remove_file(dev, &dev_attr_fxs_ring_registers);
return 0;
}

View File

@@ -511,6 +511,11 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
ret = -EPROTO;
goto proto_err;
}
if (units[0].addr.unit != 0 || units[0].addr.subunit != 0) {
XBUS_NOTICE(xbus, "No first module. Astribank unusable.\n");
ret = -EPROTO;
goto proto_err;
}
if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
ret = -EPROTO;
goto proto_err;
@@ -568,6 +573,7 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
}
goto out;
proto_err:
xbus_setstate(xbus, XBUS_STATE_FAIL);
dump_packet("AB_DESCRIPTION", pack, DBG_ANY);
out:
return ret;

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
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.201.hex FPGA_1161.202.hex
PIC_FW = PIC_TYPE_1.hex PIC_TYPE_2.hex PIC_TYPE_3.hex PIC_TYPE_4.hex
OCT_FW = $(wildcard OCT6104E-256D.ima)
FIRMWARES = $(USB_FW) $(FPGA_FW) $(PIC_FW) $(OCT_FW)
@@ -20,4 +20,7 @@ install:
mkdir -p $(TARGET)
install $(SCRIPTS) $(TARGET)/
install -m 644 ../XppConfig.pm $(FIRMWARES) $(TARGET)/
if [ ! -r $(TARGET)/USB_FW.202.hex ]; then \
ln -s USB_FW.201.hex $(TARGET)/USB_FW.202.hex;\
fi

View File

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

View File

@@ -59,6 +59,7 @@ my %settings;
$settings{debug} = 0;
$settings{fxs_skip_calib} = 0;
my $chipregs;
my $ring_registers;
sub logit {
print STDERR "$unit_id: @_\n";
@@ -104,6 +105,10 @@ if (-t STDERR) {
logit "OLD DRIVER: does not use /sys chipregs. Falling back to /proc"
if -f $chipregs;
}
$ring_registers = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/fxs_ring_registers",
$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
logit "OLD DRIVER: missing '$ring_registers' -- fallback to hard-coded defaults"
unless -f $ring_registers;
}
sub set_output() {
@@ -147,6 +152,16 @@ sub write_to_slic_file($) {
}
sub write_to_ring_register($) {
my $write_str = shift;
open(SLICS,">$ring_registers") or
die("Failed writing to ring_registers file $ring_registers");
print SLICS $write_str;
close(SLICS) or die "Failed writing '$write_str' to '$ring_registers': $!";
main::mysleep(0.001);
}
sub read_reg($$$) {
my $read_slic = shift;
my $read_reg = shift;
@@ -298,7 +313,7 @@ sub init_early_direct_regs() {
return write_to_slic_file("#
* WD 08 00 # Audio Path Loopback Control
* WD 6C 01
* WD 4A 3F # High Battery Voltage
* WD 4A 34 # High Battery Voltage
* WD 4B $lbv # Low Battery Voltage
* WD 49 $vcm # Common Mode Voltage (VCM)
* WD 40 00 # Line Feed Control
@@ -442,6 +457,10 @@ sub check_slics() {
return @slics;
}
sub overwrite_ring_registers() {
write_to_ring_register("NEON 0x33 0x12");
}
package main;
main::debug "Starting '$0'";
@@ -470,6 +489,7 @@ while(<DATA>) {
print "$_\n";
}
close REG;
FXS::overwrite_ring_registers();
main::debug "Ending '$0'";
close STDERR;

View File

@@ -24,6 +24,7 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#ifdef PROTOCOL_DEBUG
@@ -59,8 +60,8 @@ static DEF_PARM(uint, command_queue_length, 1500, 0444,
static DEF_PARM(uint, poll_timeout, 1000, 0644,
"Timeout (in jiffies) waiting for units to reply");
static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets");
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0644,
"Register devices automatically (1) or not (0)");
static DEF_PARM_BOOL(dahdi_autoreg, 0, 0444,
"Register devices automatically (1) or not (0). UNUSED.");
#ifdef CONFIG_PROC_FS
static const struct file_operations xbus_read_proc_ops;
@@ -937,6 +938,8 @@ static void xbus_free_ddev(xbus_t *xbus)
xbus->ddev = NULL;
}
static DEFINE_MUTEX(dahdi_registration_mutex);
int xbus_register_dahdi_device(xbus_t *xbus)
{
int i;
@@ -944,6 +947,11 @@ int xbus_register_dahdi_device(xbus_t *xbus)
int ret;
XBUS_DBG(DEVICES, xbus, "Entering %s\n", __func__);
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
if (ret < 0) {
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
goto err;
}
if (xbus_is_registered(xbus)) {
XBUS_ERR(xbus, "Already registered to DAHDI\n");
WARN_ON(1);
@@ -1008,17 +1016,26 @@ int xbus_register_dahdi_device(xbus_t *xbus)
xpd_dahdi_postregister(xpd);
}
}
return 0;
ret = 0;
out:
mutex_unlock(&dahdi_registration_mutex);
return ret;
err:
xbus_free_ddev(xbus);
return ret;
goto out;
}
void xbus_unregister_dahdi_device(xbus_t *xbus)
{
int i;
int ret;
XBUS_NOTICE(xbus, "%s\n", __func__);
ret = mutex_lock_interruptible(&dahdi_registration_mutex);
if (ret < 0) {
XBUS_ERR(xbus, "dahdi_registration_mutex already taken\n");
return;
}
for (i = 0; i < MAX_XPDS; i++) {
xpd_t *xpd = xpd_of(xbus, i);
xpd_dahdi_preunregister(xpd);
@@ -1033,6 +1050,7 @@ void xbus_unregister_dahdi_device(xbus_t *xbus)
xpd_t *xpd = xpd_of(xbus, i);
xpd_dahdi_postunregister(xpd);
}
mutex_unlock(&dahdi_registration_mutex);
}
/*
@@ -1100,7 +1118,7 @@ void xbus_populate(void *data)
*/
xbus_request_sync(xbus, SYNC_MODE_PLL);
elect_syncer("xbus_populate(end)"); /* FIXME: try to do it later */
if (dahdi_autoreg)
if (!auto_assign_spans)
xbus_register_dahdi_device(xbus);
out:
XBUS_DBG(DEVICES, xbus, "Leaving\n");
@@ -1959,6 +1977,10 @@ int __init xbus_core_init(void)
{
int ret = 0;
if (dahdi_autoreg == 1) {
NOTICE("WARNING: The dahdi_autoreg parameter is deprecated " \
"-- just set dahdi.auto_assign_spans=0\n");
}
initialize_xbuses_array();
#ifdef PROTOCOL_DEBUG
INFO("FEATURE: with PROTOCOL_DEBUG\n");

View File

@@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#ifdef PROTOCOL_DEBUG
#include <linux/ctype.h>
@@ -54,10 +55,19 @@ static ssize_t sync_store(struct device_driver *driver, const char *buf,
return exec_sync_command(buf, count);
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
static struct driver_attribute xpp_attrs[] = {
__ATTR(sync, S_IRUGO | S_IWUSR, sync_show, sync_store),
__ATTR_NULL,
};
#else
static DRIVER_ATTR_RW(sync);
static struct attribute *xpp_attrs[] = {
&driver_attr_sync.attr,
NULL,
};
ATTRIBUTE_GROUPS(xpp);
#endif
/*--------- Sysfs Bus handling ----*/
static DEVICE_ATTR_READER(xbus_state_show, dev, buf)
@@ -409,7 +419,11 @@ static struct bus_type toplevel_bus_type = {
.match = astribank_match,
.uevent = astribank_uevent,
.dev_attrs = xbus_dev_attrs,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)
.drv_attrs = xpp_attrs,
#else
.drv_groups = xpp_groups,
#endif
};
static int astribank_probe(struct device *dev)
@@ -582,6 +596,8 @@ static DEVICE_ATTR_READER(span_show, dev, buf)
return len;
}
static DEFINE_MUTEX(span_store_mutex);
/*
* For backward compatibility with old dahdi-tools
* Remove after dahdi_registration is upgraded
@@ -601,8 +617,13 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
return -EINVAL;
if (!XBUS_IS(xpd->xbus, READY))
return -ENODEV;
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use pinned-spans)\n",
XPD_DBG(DEVICES, xpd, "%s -- deprecated (should use assigned-spans)\n",
(dahdi_reg) ? "register" : "unregister");
ret = mutex_lock_interruptible(&span_store_mutex);
if (ret < 0) {
XBUS_ERR(xpd->xbus, "span_store_mutex already taken\n");
return ret;
}
if (xbus_is_registered(xpd->xbus)) {
if (dahdi_reg) {
XPD_DBG(DEVICES, xpd,
@@ -620,6 +641,7 @@ static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
xbus_register_dahdi_device(xpd->xbus);
}
}
mutex_unlock(&span_store_mutex);
return count;
}

View File

@@ -1,11 +0,0 @@
# Load firmware into the Xorcom Astribank device:
SUBSYSTEM=="usb", ACTION=="add", \
ENV{PRODUCT}=="e4e4/11[3456][013]/*", ENV{DEVTYPE}!="usb_interface", \
RUN+="/usr/share/dahdi/xpp_fxloader udev $env{PRODUCT}"
# Hotplug hook for Astribank up/down
# If you need this functionality, copy the astribank_hook.sample
# to $XPP_INIT_DIR/astribank_hook
#
# By default XPP_INIT_DIR="/usr/share/dahdi"
KERNEL=="xbus*", RUN+="%E{XPP_INIT_DIR}/astribank_hook udev $kernel $sysfs{status} $sysfs{connector}"

View File

@@ -40,11 +40,10 @@
/* #define SHORT_FLASH_TIME */
/*
* Uncomment to disable calibration and/or DC/DC converter tests
* Uncomment to disable calibration tests
* (not generally recommended)
*/
/* #define NO_CALIBRATION */
/* #define NO_DCDC */
/*
* Boost ring voltage (Higher ring voltage, takes more power)

View File

@@ -811,6 +811,7 @@ enum spantypes {
SPANTYPE_DIGITAL_BRI_NT,
SPANTYPE_DIGITAL_BRI_TE,
SPANTYPE_DIGITAL_BRI_SOFT,
SPANTYPE_DIGITAL_DYNAMIC,
};
const char *dahdi_spantype2str(enum spantypes st);
enum spantypes dahdi_str2spantype(const char *name);
@@ -909,7 +910,7 @@ struct dahdi_span_ops {
/*! Opt: Provide the name of the echo canceller on a channel */
const char *(*echocan_name)(const struct dahdi_chan *chan);
/*! When using "pinned_spans", this function is called back when this
/*! When using "assigned spans", this function is called back when this
* span has been assigned with the system. */
void (*assigned)(struct dahdi_span *span);
@@ -940,6 +941,7 @@ struct dahdi_device {
const char *devicetype;
struct device dev;
unsigned int irqmisses;
struct timespec registration_time;
};
struct dahdi_span {
@@ -1003,6 +1005,8 @@ struct dahdi_transcoder_channel {
};
int dahdi_is_sync_master(const struct dahdi_span *span);
struct dahdi_span *get_master_span(void);
void set_master_span(int spanno);
static inline int
dahdi_tc_is_built(struct dahdi_transcoder_channel *dtc) {
@@ -1276,6 +1280,7 @@ static inline void dahdi_ec_span(struct dahdi_span *span)
}
extern struct file_operations *dahdi_transcode_fops;
extern int auto_assign_spans;
/* Don't use these directly -- they're not guaranteed to
be there. */
@@ -1402,6 +1407,8 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
#define DAHDI_FORMAT_AUDIO_MASK ((1 << 16) - 1)
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
#ifdef RHEL_RELEASE_VERSION
#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(6, 5)
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
static inline void *PDE_DATA(const struct inode *inode)
@@ -1409,8 +1416,37 @@ static inline void *PDE_DATA(const struct inode *inode)
return PDE(inode)->data;
}
#endif
#endif
#else
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
static inline void *PDE_DATA(const struct inode *inode)
{
return PDE(inode)->data;
}
#endif
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
#define KERN_CONT ""
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 27)
# ifndef RHEL_RELEASE_VERSION
/* I'm not sure which 5.x release this was backported into. */
static inline int try_wait_for_completion(struct completion *x)
{
unsigned long flags;
int ret = 1;
spin_lock_irqsave(&x->wait.lock, flags);
if (!x->done)
ret = 0;
else
x->done--;
spin_unlock_irqrestore(&x->wait.lock, flags);
return ret;
}
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
@@ -1450,8 +1486,11 @@ void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
#ifndef __packed
#define __packed __attribute__((packed))
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
#ifndef __packed
#define __packed __attribute__((packed))
#endif
#include <linux/ctype.h>
@@ -1479,6 +1518,7 @@ static inline int strcasecmp(const char *s1, const char *s2)
#endif /* 2.6.22 */
#endif /* 2.6.25 */
#endif /* 2.6.26 */
#endif /* 2.6.27 */
#endif /* 2.6.31 */
#endif /* 3.10.0 */
@@ -1571,6 +1611,17 @@ struct mutex {
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
#endif
/* If KBUILD_MODNAME is not defined in a compilation unit, then the dev_dbg
* macro will not work properly. */
#ifndef KBUILD_MODNAME
#undef dev_dbg
#ifdef DEBUG
#define dev_dbg dev_info
#else
#define dev_dbg(...) do { } while (0)
#endif
#endif
/* The dbg_* ones use a magical variable 'debug' and the user should be
* aware of that.
*/