Compare commits

..

69 Commits

Author SHA1 Message Date
Shaun Ruffell
66edd67565 xpp: Fix compilation when CONFIG_DAHDI_WATCHDOG is defined.
Looks like a hold over from when dahdi_span_ops was first implemented in r8985
"dahdi: Move the callbacks in dahdi_span into its own structure" [1].

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=8985
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10658

Conflicts:

	drivers/dahdi/xpp/xpp_dahdi.h

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10659 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-11 20:19:24 +00:00
Mike Sinkovsky
897cbb01de dahdi: Fix compilation when CONFIG_DAHDI_WATCHDOG is defined.
From: Mike Sinkovsky <msink@trikom.ru>

Internal-Issue-ID: DAHLIN-288
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10655

Conflicts:

	drivers/dahdi/dahdi-base.c

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10656 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-11 17:45:35 +00:00
Tzafrir Cohen
f9e4bf52c2 FPGA_1161.201.hex rev 10545: fix reset of XR1000
Previous commit (r10650) included an incorrect version. Including full message
from that commit for the description.

rev. 10502 of the FPGA firmware for the new E-Main rev. 4 fixes a potential
issue when used on Xorcom XR1000 systems: an issue with the power supply may
cause the unit to reset.

Note that there is no issue with previous models, with a normal setup of an
Astribank, or other XRx000 systems.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10652

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10653 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-11 09:11:44 +00:00
Tzafrir Cohen
44a5add969 FPGA_1161.201.hex rev 10532: fix reset of XR1000
rev. 10502 of the FPGA firmware for the new E-Main rev. 4 fixes a potential
issue when used on Xorcom XR1000 systems: an issue with the power supply may
cause the unit to reset.

Note that there is no issue with previous models, with a normal setup of an
Astribank, or other XRx000 systems.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10649

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10650 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-10 21:51:49 +00:00
Shaun Ruffell
d18ec7f3b9 wcte12xp, wctdm24xxp, wct4xxp: Print warning about potential GPL violation w/HOTPLUG_FIRMWARE=no.
Print a warning message that it may be a GPL violation to redistribute these
binaries if the firmware for the VPMOCT032/64/128/256 is compiled in.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10646

Conflicts:

	drivers/dahdi/wct4xxp/Kbuild

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10647 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-05 20:34:44 +00:00
Shaun Ruffell
f69326bb66 wcb4xxp: Remove asm/system.h include.
Not needed anymore and will break compilation on Kernel versions >= 3.4 since
commit 0195c00244dc2e [1]

[1] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=commit;h=0195c00244dc2e

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10641

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10643 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-05 16:22:30 +00:00
Shaun Ruffell
c95385bb06 dahdi_dummy: Include timer.h instead of time.h
It appears that some kernel configurations do not include timer.h in any of
the include files that are included by dahdi_dummy. The timer_structs are
defined in timer.h and not time.h, so this change is correct even though I
never could find a configuation myself that actually failed to compile.

This has negligible impact since dahdi_dummy is not compiled by default.

Internal-Issue-ID: DAHLIN-185
Reported-by: Steve Murphy
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10640

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10642 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-05 16:22:26 +00:00
Shaun Ruffell
76468854ed dahdi: Fix compilation when CONFIG_DAHDI_ECHOCAN_PROCESS_TX is defined.
'ec_state' was renamed to 'dahdi_echocan_state' in r6529 [1] but support for
CONFIG_DAHDI_ECHOCAN_PROCESS_TX was first committed in r9442 [2]. So it
appears that I never compiled tested this exact commit when it went in for the
2.5.0 release.

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=6529
[2] http://svnview.digium.com/svn/dahdi?view=revision&revision=9442

Reported-by: Pavel Selivanov
Internal-Issue-ID: DAHLIN-279
Patches: ec.patch uploaded by Pavel Selivanov (License #5420)
[ edited the patch slightly for minor formatting ]
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10633

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10635 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-03 22:02:20 +00:00
Shaun Ruffell
2242c5394b wctdm24xxp, wcte12xp: Allow VPMOCT032 firmware to be compiled into driver.
Enables the driver to update firmware on systems that do not have the firmware
loader configured / enabled (Linux config option CONFIG_FW_LOADER). Compiling
the firmware into the driver increase the memory footprint by around ~440K.

Internal-Issue-ID: DAHDI-963
Reported-and-Tested-by: Guenther Kelleter
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10618

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10619 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-04-02 14:05:11 +00:00
Shaun Ruffell
62c5402a24 wctdm24xxp: Remove forward declaration of inline for GCC 3.4.4
GCC 3.4.4 does not allow forward declaration of inline functions.

Internal-Issue-ID: DAHLIN-286
Reported-by: Guenther Kelleter
Patches: wctdm24xxp-inline.patch uploaded by Guenther Kelleter (License #6372)
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10613

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10615 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-29 15:29:14 +00:00
Oron Peled
b222cfeb5d xpp: FXS: added a 'lower_ringing_noise' parameter
* Adds a new parameter, 'lower_ringing_noise', to module xpd_fxs.

* Makes the "power-down" behaviour that was added
  in upstream svn r10478, switchable in runtime.

* By default (false), makes the vbat_h behave like it did
  before the power-down change.
  - I.e: vbat_h is held throughout the ringing period (during
    both ring-up/ring-down)
  - So this patch revert part of r10478

* When switched to true, activate the "power-down" behaviour.
  - I.e: vbat_h follows the ring-up/ring-down.
  - This behaviour lowers the noise caused by group ringing of
    FXS channels in the same unit, but causes problems with CallerID.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10574

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10578 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 20:40:52 +00:00
Oron Peled
bd373e5075 xpp: FXS: atomic vbat_h power handling
* In do_chan_power() make vbat_h changes atomic.
* As a result we can ignore duplicate requests.
  This will allow cleaner logic in the next commit.
* Added proper debug messages.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10573

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10577 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-21 20:40:29 +00:00
Tzafrir Cohen
49d2e93245 xpp: firmwares: useless 0x1A at EOF
Remove a mostly harmless 0x1A (^Z) at the end of the file. If you
add a NL after it, it breaks the firmware loading.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10550

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10551 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-20 11:19:17 +00:00
Tzafrir Cohen
c573e5eaf5 xpp: firmwares to support E-Main 4
USB firmware (USB_FW.201.hex 10402) and FPGA firmware
(FPGA_1161.201.hex 10480) with support of the new E-Main 4 Astribank
mainboard.

(This was accidentally labeled as 'E-Main 3' in some previous commit
messages)

Also includes Makefile fixes from r10536.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10535

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10540 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-18 19:07:51 +00:00
Tzafrir Cohen
7559b61e54 xpp: USB_FW rev 10401: minor 6FXS/2FXO caps issue
Fixes an issues with the 6FXS/2FXO module: if an extra FXS or FXO module
is added to a system with such a module, an excessive number of port
licenses was accidentally required (as if the 6FXS/2FXO module required
8FXS/8FXO licenses).

Internal-Issue-ID: #1371
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10534

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10539 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-18 19:04:12 +00:00
Shaun Ruffell
f4cffb0c1a xpp: '%d' -> '%lu' when displaying module_refcount on kernel versions >= 3.3
Upstream commit bd77c047 "module: struct module_ref should contains long
fields" changed the return of module_refcount from int to unsigned long. This
change eliminates a warning from the string format specifier.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10485

Conflicts:

	drivers/dahdi/xpp/xproto.c

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10529 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-16 16:11:47 +00:00
Shaun Ruffell
42c0efb700 xpp: Use 'bool' type for boolean module parameters on kernel versions >= 2.6.31.
Eliminates warnings that are a result of upstream commit 72db395ffa
"module_param: check that bool parameters really are bool."

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10484

Conflicts:

	drivers/dahdi/xpp/xpd.h

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10528 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-16 16:11:43 +00:00
Shaun Ruffell
4afe8d0213 wctdm24xxp: Fix bug if hook state on FXS changes before channel configuration.
If the hook state on an FXS port changes before the channel is
configured with dahdi_cfg it is possible to erroneously force the line
feed register open without setting a timer to clear it.

The result would be a "dead" channel that cannot be cleared unless the
driver is reloaded and warning in the kernel log that "0 is an invalid
signaling state for an FXS module".

This change makes the OFF_HOOK to ON_HOOK change behave just as the
ON_HOOK to OFF_HOOK change has.

Internal-Issue-ID: DAHLIN-272
Reported-and-Tested-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10396

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10527 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-16 16:11:38 +00:00
Oron Peled
ae9d3a0bdc xpp: FXS: better power-down to lower noise
* Now every linefeed control command which is not RING'ing
  powers-down the SLIC. This reduce audible noise when
  several channels are ringing.

* Simplify code by removing redundant calls to do_chan_power()
  before linefeed_control()

* Manage vbat_h state so we skip do_chan_power() calls when
  there isn't a state change

* Export vbat_h state to /proc/.../fxs_info

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10478

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10488 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 17:33:16 +00:00
Oron Peled
d635b1ef61 xpp: reset Astribank SPI busses
* A driver reload should reset Astribank hardware
* This patch send an SPI reset after we get AB_DESCRIPTION reply from Astribank

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10474

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10487 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-03-15 17:32:43 +00:00
Tzafrir Cohen
6527164a02 USB_RECOV.hex: recovering from xpp hardware issues
USB_RECOV.hex, rev. 9760. It may be used to recover from certain
issues of the USB controller of the Astribank (when an Astribank
is not detected as such) by Support staff.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10455

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10456 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-02-07 22:17:34 +00:00
Tzafrir Cohen
2f55744b15 Astribank I firmwares rev. 7107
A slightly newer firmware (Xorcom rev. 7107) for older (non Astribank
II) Astribank modules. Was accidentally left uncommited. Includes minor
bug fixes.

No change for any relatively recent (Astribank II) Astribank.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10443

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10444 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-25 19:56:05 +00:00
Tzafrir Cohen
5ddb6535f7 Build OSLEC EC if in the tree
Build the OSLEC echo canceller (drivers/staging/echo and
dahdi_echocan_oslec) if the code of oslec is present in the tree.

Also closing another issue regarding documentation of building OSLEC,
as it is now even clearer than before.

Patch has been used in the Debian package for quite some time.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

(closes issue DAHLIN-110)
Reported by: biohumanoid (Pavel Selivanov)
Patches:
     oslec_auto.diff uploaded by tzafrir (license 5035)

(closes issue DAHLIN-261)

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10440

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10441 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-17 14:46:23 +00:00
Oron Peled
172ddb07b9 xpp: bugfix: fix bad refcount
Code path called in error condition contained an superflous put_xpd() call

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10408

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10420 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-11 12:03:56 +00:00
Tzafrir Cohen
94a00c0f00 Avoid building PCI devices if kernel has no PCI
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10398 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-03 22:55:29 +00:00
Oron Peled
47fbd9bcc3 xpp: BRI: batch D-Channel packets to fix frag.
* We need to split the BRI D-Channel (HDLC) frames to smaller packets,
  limitation of the FPGA.
* This changes batches BRI D-channel packets of the same HDLC frame to a
  single XPP frame.
* Avoids an accidental fragmantion in case we were delayed for a few ms-s.
* Also improves efficiency.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10394 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-03 14:44:37 +00:00
Oron Peled
1a9b8662ad xpp: BRI: split multibyte functionality
* The zero lenth case (Magic request) was split into
  send_magic_request() function. It was not possible
  to move it into card_bri.c, because it is called
  directly from the general interface we provide for
  register read/write via sysfs/proc.

* The normal case (send_multibyte_request) was moved from
  card_global.c into card_bri.c

* This sets the stage to enable bundling of multibyte
  packets into frames (like we do for PCM).

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10393 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-03 14:42:47 +00:00
Oron Peled
c3f65d39fa xpp: BRI: remove trivial BRISTUFF wrappers
Now that legacy BRISTUFF code is gone, some wrapper
functions became trivial. Removed these wrappers
and inlined their contents.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10392 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-03 14:42:21 +00:00
Oron Peled
c36b6cd738 xpp: BRI: remove legacy BRISTUFF code
Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10391 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2012-01-03 14:41:04 +00:00
Tzafrir Cohen
14f64038b0 xpp: Allow up to 128 Astribanks on a system
This is also a work around the bug fixed in the previous commit.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10386 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-21 18:38:13 +00:00
Oron Peled
a135f4e817 xpp: bad module_put() when too many Astribanks
module_put() that was added while developing the sysfs code. The real
module_get()/module_put() pair were already removed at the time of
developing code for this branch. It was only triggered when using a
system with more than 32 (MAX_BUSES) Astribanks.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-By: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10385 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-21 18:37:34 +00:00
Shaun Ruffell
1e8c9fb797 wctdm24xxp: Do not call voicebus_release() before wctdm_back_out_gracefully()
voicebus_release is already called as part of the wctdm_back_out_gracefully()
call. If an Hx8 card fails to initialize, this will eliminate warnings from
the kernel such as:

  WARNING: at kernel/irq/manage.c:904 __free_irq+0x94/0x173()
  Trying to free already-free IRQ 18

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10377

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10378 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-12 18:28:49 +00:00
Oron Peled
0893461985 xpp: BRI: fix timing priority calculation
Use similar caculation as in the PRI module:
* Save timing_priority from spanconfig and
  elect syncer when spanconfig is called.
* Create custom timing_priority() function that returns
  the value or error if span is disconnected.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: : Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10376 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-07 19:45:16 +00:00
Oron Peled
8edbfa881e xpp: FXS: mwi and search_fsk fixes
* We must not block PCM during from 'search_fsk_pattern' channels.
* We must vmwi_search() not only on FXS_LINE_POL_ACTIVE, but also during
  'neon_blinking' -- so we notice the message to turn it off.
* Also added 'search_fsk_pattern' and neon_blinking to /proc/.../fxs_info

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by: : Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10375 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-07 19:44:37 +00:00
Tzafrir Cohen
43412bc513 xpp: bugfix -- manage xpd refcount for EC module
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10374 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-07 19:42:20 +00:00
Shaun Ruffell
1cf2b86e75 dahdi: #include <linux/module.h> in dahdi/kernel.h and GpakCust.h
Commit de47725, first released in 3.2-rc1 removed module.h from some
kernel headers. Include it explicitly now.

Resolves compilation errors like:
error: implicit declaration of function 'try_module_get'
error: 'THIS_MODULE' undeclared (first use in this function)
error: implicit declaration of function 'module_put'

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10361

Conflicts:

	include/dahdi/kernel.h

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10363 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-02 20:06:03 +00:00
Shaun Ruffell
380ceed257 wctc4xxp: Replace 'ndo_set_multicast_list' with 'set_rx_mode'
The ndo_set_multicast_list callback was removed in b81693d9, which was
first released in Linux Kernel 3.2-rc1

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10360

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10362 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-12-02 20:05:58 +00:00
Oron Peled
3408c774ce xpp: pri: fix RS1 init in E1 CAS mode
Force some reserved bits to really be 1 in E1 mode (otherwise
terrorists will win).

(Closes issue DAHLIN-264)

Signed-off-by: Oron Peled <oron.peled@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10353 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-30 10:22:01 +00:00
Oron Peled
2de79e8905 xpp: fxs: demote SETPOLARITY message to DBG()
Signed-off-by: Oron Peled <oron.peled@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10352 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-30 10:21:20 +00:00
Tzafrir Cohen
99f1c099ec xpp: Adaptations for E-Main-3
* An xbus transport now have a "model_string" member
 * The xpp_usb driver fills this with "usb:<idVendor>/<idProduct>/<bcdDevice>"
 * It is passed via environment to the "init_card_<type>_<protocol>" scripts
 * The FXS script uses this to condition two registers according to
   the power supply model.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10351 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-30 10:20:38 +00:00
Tzafrir Cohen
136ab72d6c xpp: increase command queue length to 1500
A length of 1000 commands is not enough is some cases with CAS.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10342 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-16 12:17:29 +00:00
Tzafrir Cohen
e667e47418 xpp: USB_FW rev 10085: fix regression from r10324
Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10340 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-13 15:11:39 +00:00
Tzafrir Cohen
90c209f77b xpp: PIC_TYPE_1 rev 9841: followup to r10324
An extra fix that was accidentally not included in r10324. Minor bug fixes.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10338 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-13 13:35:12 +00:00
Oron Peled
2ecf474a07 xpp: silence some bad ioctl() reporting
Ignore some FXS-specific ioctl-s in xpd_pri.

Signed-off-by: Oron Peled <oron.peled@xorcom.com>
Acked-by Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10336 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-13 09:52:28 +00:00
Tzafrir Cohen
2fefa9dd60 xpp: USB firmware r9964: minor bugfixes
USB_FW rev 9964: includes a few stability bugfixes.

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10324 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-07 15:55:06 +00:00
Shaun Ruffell
d624adb358 dahdi: First span registered becomes master by default.
r10205 "dahdi: Check for master in DAHDI_STARTUP / resolves MeetMe
regression." did not handle the case for the wcb4xxp driver since it
would set DAHDI_FLAG_RUNNING as part of the probe. Therefore, the
DAHDI_STARTUP ioctl was never processed for it, creating a situation
where audio is missing on channels that are conferenced with channels on
the BRI spans.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10304

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10305 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-11-02 20:01:58 +00:00
Shaun Ruffell
40942e2a43 dahdi: Move WARN_ON_ONCE from wctc4xxp driver to include/dahdi/kernel.h
I only generally test on RHEL 4 when testing against kernels older
than 2.6.18. Apparently OpenSUSE 10.1 runs with 2.6.16 and doesn't
have WARN_ON_ONCE backported. I took the patch Richard Miller
originally attached to the issue and moved it to
include/dahdi/kernel.h so it would be available for all the board
drivers in the future.

Internal-Issue-ID: DAHLIN-260
Reported-by: Richard Miller
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10252

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10254 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-10-21 19:48:24 +00:00
Shaun Ruffell
78c92b52ed wcb4xxp: Do not show LASVEGAS2 as echocan name if vpmsupport is set to 0
This fixes an issue where "EC: LASVEGAS2" was displayed in /proc/dahdi/x
for a B410P span even though vpmsupport was disabled with the module
parameter.

Internal-Issue-ID: DAHLIN-247
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10251

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10253 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-10-21 19:48:20 +00:00
Shaun Ruffell
1bf7ebc42f wct4xxp: Fix condition where hardware echo canceler erroneously mutes DTMF.
Commit r9750 "wct4xxp: Reduce the memory footprint of the hardware
echocanceler.", as part of reducing the non-pageable memory required to
support the VPMOCT064 and VPMOCT128, disabled caching of some hardware
echocan registers. This resulted in more physical reads to the echo
canceler. These new read transactions exposed an existing issue where
sometimes reads could be turned into writes which put a channel into an
unintended state preventing Asterisk from detecting any DTMF.

This issue is resolved by ensuring that the write signal to the Octasic
part is explicitly cleared between when the address is presented on the
bus and when the read and chip select signals are asserted. The cost is
an increase in the average time to enable / disable echo cancellation by
about 5 us on one Intel Xeon X3220 test machine (~250ns increase per
read from the Octasic part and 20 reads to enable / disable a channel).

This commit resolves a behavioral regression first introduced in 2.5.0
and 2.4.1 which could take many calls before revealing itself. This
change only affects cards with a VPMOCT128 or VPMOCT064 installed.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Doug Bailey <dbailey@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10220

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10221 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-10-12 16:32:35 +00:00
Shaun Ruffell
7a275dc70b wctc4xxp: Allow G723 SID frames to pass to the hardware decoder.
The driver has, until now, dropped G723 SID frames even though the
firmware on the TC400/TCE400 can handle them. Now let them on
through.

Reported-and-Tested-by: Angel Carhuas <acarhuas@colinanet.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10218

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10219 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-09-30 19:23:22 +00:00
Shaun Ruffell
9fb13e2f6c wctdm24xxp: Set dahdi_span.devicetype string in one place.
Currently the devicetype string was set both when the device was first
allocated and updated when an echocanceler was detected. For simplicity,
combine both these steps into a single function.

This change also replaces an improper use of strncat with strlcat.

Additionally, on the 2.5 branch, this change actually makes r10206
"wctdm24xxp, wcte12xp: Advertise VPMOCT032 presence in
dahdi_span.devicetype",  work the way it was originally intended. That
change was only functioning properly previously on trunk.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10210

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10211 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-09-27 22:10:34 +00:00
Tzafrir Cohen
fcbde772c4 xpp: fxs: bugfix for 2fxs+6fxo cards
* Bug sympthoms: wrong FSK VMWI sent few seconds after
  offhook. That was caused because the driver kept
  polling the (physically unconnected) digital inputs.
  [note: a workaround for drivers without this patch
   is to zero the 'xpd_fxs.poll_digital_inputs' parameter.]

* Also, the digital_inputs/digital_output masks were
  calculate using a different condition.

* Now we determine number of channels, digital inputs and
  digital outputs in a single place and use this info
  later to calculate the correct masks.

* We poll only if there are digital_inputs

* We added a sanity check in process_digital_inputs, so
  we get a notice if it's called on an xpd without digital
  inputs (e.g: hypothetic firmware bug).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>
Acked-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10208 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-09-25 08:59:02 +00:00
Shaun Ruffell
2bc2ebd1de dahdi: Check for master in DAHDI_STARTUP / resolves MeetMe regression.
There were a couple of reports that MeetMe conferences were not
working in 2.5.0.1 and that downgrading to 2.4.1.2 resolved the
issue. This could occur if there were no analog spans in a system,
and all the digital spans were out of alarm before DAHDI_STARTUP
ioctl was called by dahdi_cfg. If the spans were *not* out of alarm,
they would be marked master when the span changes it's alarm state.

This would result in a condition where no spans were marked as the
"master" and so the core timer was handling conferencing. The core
timer runs by default at 4ms and most board drivers run at 1ms
intervals, but a channel currently only buffers up 2ms of data when
conferenced. Therefore, 2ms of audio from a board was continuously
dropped from the conference every 4ms by default.

This fixes a regression first introduced in 2.5.0 which was
specifically added in revision r9611 "dahdi: Do not locate new
master in interrupt context."

Internal-reference-ID: DAHDI-894
Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Tested-by: Dennis Martinez <dmartinez@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10205

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10207 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-09-23 20:23:47 +00:00
Shaun Ruffell
0f8559b045 wctdm24xxp, wcte12xp: Advertise VPMOCT032 presence in dahdi_span.devicetype.
A "(VPMADT032)" string is appended to the devicetype (as shown by
dahdi_scan) for the span if one is installed. Now append '(VPMOCT032)'
if one is installed as well.

Also, for the wcte12xp driver append the VPM name to the device type after
initially probing as opposed to only after the span is configured.

(Related to issue DAHDI-890)
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10203

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10206 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-09-23 20:23:43 +00:00
Shaun Ruffell
d6075a4c78 dahdi: Decrease the initial coretimer delay to 4ms from 1 second.
DAHDI currently waits a second before checking if a board driver is
calling dahdi_receive and switching to internal timing. Some versions of
Asterisk (I was looking at 1.4.42 when writing this) only wait 300ms for
a timer to expire when first starting and verifying that DAHDI is
properly configured. This can result in a

"ERROR[27673] asterisk.c: Asterisk has detected a problem with your DAHDI
configuration and will shutdown for your protection. You have options:"

message if asterisk is started soon after loading DAHDI.

This change sets the inital polling interval to the same as that used
during normal coretimer operation, 4ms. The interval will still be
slowed to 1 second if a board driver starts calling dahdi_receive().

DAHDI-892.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10200

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10201 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-09-13 18:38:19 +00:00
Tzafrir Cohen
c6e5ab448c xpp: firmware to detect the new 2+6 module
New firmwares to handle the new 2FXS/6FXO module.

FPGA_1161.hex, PIC_TYPE_1.hex, PIC_TYPE_2.hex of internal rev. 9732

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10180 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-09-05 10:29:53 +00:00
Doug Bailey
8ff6810740 wcte12xp, wctdm24xxp: Update VPMOCT032 firmware to 1.11.0.
Firmware version 1.11.0 resolves an issue where the driver fails to
detect certain VPMOCT032 modules after a cold boot.

Signed-off-by: Doug Bailey <dbailey@digium.com>
Acked-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10172

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10173 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-30 21:06:20 +00:00
Tzafrir Cohen
f3262ae381 xpp: FXS: new 2+6 module has no digital I/O ports
This module is recognized via subtype==4

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10157 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-28 09:45:15 +00:00
Shaun Ruffell
c3c891abdd wctdm24xxp: Set 'fastoffhook' counter to 8ms and turn off calibration delay.
r10006 "wctdm24xxp: Add 'fastpick' module parameter." copied the
fast-off hook module parameter from the wctdm.c driver, but the setting
in that driver does not match the data sheet. The previous commit did
not actually change any of the significant bits in that register. Also,
that commit changed the timer, but did not disable the callibration
delay which is necessary for Type-II callerid.

The fastpickup option in the wctdm24xxp driver should now match the
fastpickup option in the wctdm driver.

DAHDI-224.

Reported-By: Kinnith Wallace <kwallace@digium.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10148

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10150 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-19 22:53:51 +00:00
Shaun Ruffell
2fb5d7d6d7 wctdm: Set 'fastpickup' counter to 8ms
This fixes what looks like a typo in r1055 [1].

[1] http://svnview.digium.com/svn/dahdi?view=revision&revision=1055

Reported-by: Kinnith Wallace <kwallace@digium.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10147

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10149 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-19 22:53:47 +00:00
Shaun Ruffell
08ce93306d wctdm24xxp: Use our own free list for IRQ commands.
Really only *necessary* when SLAB debugging is enabled, but in that
case, can reduce the chance of latency bumps when first loading the
driver. Otherwise the constant slab poisoning / checking in interrupt
context from the kmalloc / kfrees is too much.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>
Acked-by: Russ Meyerriecks <rmeyerriecks@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10144

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10146 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-18 19:35:01 +00:00
Russ Meyerriecks
dac1d88399 wct4xxp: Bug in timing cable with different span density cards
The logic loops through the static cards[] array to determine timing,
    but the subloop was based off the current card's numspans member.
    This could cause a null dereference in the case where two cards of
    different span densities were connected via timing cables.

Reported-by: Doug Bailey <dbailey@digium.com>
Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10140

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10145 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-18 19:34:57 +00:00
Shaun Ruffell
5218e90962 wctc4xxp: Fix lock imbalance in wctc4xxp_watchdog.
r10082 "wctc4xxp: Cleanup in-flight commands when halting due to
hardware error." introduced a lock imblance on the error path where the
cmd_list_lock would be unlocked twice when the board is halted due to a
hardware error. Thanks sparse.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10138

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10139 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-15 21:55:49 +00:00
Shaun Ruffell
da2406db64 wcte12xp, wctdm24xxp: Force local interrupts off in the interrupt handler.
r10066 "wctdm24xxp, wcte12xp: Run the ISR with interrupts disabled."
requested that the interrupt handler be run in "fast" mode (disabled)
but this isn't necessarily guaranteed.

This patch makes the interrupt handler itself disable all the interrupts.
Linux commit 470c66239ef0336429b35345f3f615d47341e13b [1] contains a comment
about why this is necessary.

[1] http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=470c66239ef03364

(closes issue DAHLIN-248)
Reported-and-Tested-by: Vladimir Mikhelson <vlad@mikhelson.com>
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10118

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10119 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-12 16:06:28 +00:00
Shaun Ruffell
0b52fb24a0 dahdi: Define HAVE_NET_DEVICE_OPS on kernels > 2.6.29
HAVE_NET_DEVICE_OPS was defined in the mainline kernel in commit
47fd5b83 which was first released in 2.6.29. Any kernels after that will
have those fields defined.

Mainline commit e2270ea62ae4d7a removed the feature test macros, so
the easiest thing to do is define HAVE_NET_DEVICE_OPS ourselves on the
kernels since it was committed.

This change is needed to compile against the 3.1 kernel.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10109

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10117 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-11 19:56:22 +00:00
Wagner Gegler
2f880acd10 dahdi_dynamic: Call dahdi_receive in rx packet handler.
Currently dahdi_receive is called on all channels in the context of the
master dynamic span. If one span (not the master) receive two packets
before the master span received a packet, the older packet on the
dynamic span would end up lost because the "readchunk" for the
channels would be overwritten by the new packet. DAHLIN-245

Signed-off-by: Wagner Gegler <wagner@aligera.com.br> (License #6268)
Changed dahdi_ec_chunk to dahdi_ec_span.
Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10110

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10116 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-11 19:56:18 +00:00
Shaun Ruffell
950a3f2486 wctc4xxp, wcte12xp, wctdm24xxp: Remove check for HAVE_NETDEV_PRIV
DAHDI currently supports kernels >= 2.6.9. netdev_priv() has been in the
mainline kernel since versions 2.6.6 so it's available in all the
supported kernels. This change is needed to compile against the 3.1 kernel.

Signed-off-by: Shaun Ruffell <sruffell@digium.com>

Origin: http://svnview.digium.com/svn/dahdi?view=rev&rev=10096

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10115 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-11 19:56:14 +00:00
Tzafrir Cohen
2405c809e7 FPGA_1161 rev 9605: EC related bug fixes
Astribank II FPGA firmware rev 9605. Includes two bug fixes:

* Error in checking EC licenses when the license was for exactly 64 or 128
  channels.
* Proper handling of a slave FXO Astribank (in line with the quirks
  handling from r10019).

Signed-off-by: Tzafrir Cohen <tzafrir.cohen@xorcom.com>

git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10100 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-09 12:26:35 +00:00
Tzafrir Cohen
eb1c6cbeed A stable branch for DAHDI-linux 2.5
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.5@10098 a0bf4364-ded3-4de4-8d8a-66a801d63aff
2011-08-09 09:38:56 +00:00
89 changed files with 9062 additions and 12884 deletions

212
README
View File

@@ -17,7 +17,6 @@ Digital Cards
* Digium TE405P/TE407P/TE410P/TE412P: PCI quad-port T1/E1/J1
* Digium TE220: PCI-Express dual-port T1/E1/J1
* Digium TE420: PCI-Express quad-port T1/E1/J1
* Digium TE820: PCI-Express eight-port T1/E1/J1
- wcte12xp:
* Digium TE120P: PCI single-port T1/E1/J1
* Digium TE121: PCI-Express single-port T1/E1/J1
@@ -163,24 +162,6 @@ to the script:
./build_tools/make_static_devs -d tmp/newroot/dev/dahdi
DKMS
~~~~
DKMS, Dynamic Kernel Module Support, is a framework for building Linux
kernel modules. It is used, among others, by several distributions that
package the DAHDI kernel modules.
DKMS is designed to provide updates over drivers installed from original
kernel modules tree. Thus it installed modules into /lib/modules/updates
or /lib/modules/VERSION/updates . This is generally not an issue on
normal operation. However if you try to install DAHDI from source on
a system with DAHDI installed from DKMS this way (potentially of an
older version), be sure to remove the DKMS-installed modules from the
updates directory. If you're not sure, the following command will give
you a clue of the versions installed:
find /lib/modules -name dahdi.ko
Installing the B410P drivers with mISDN
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DAHDI includes the wcb4xxp driver for the B410P, however, support for the
@@ -248,15 +229,6 @@ be reported on the
https://lists.sourceforge.net/lists/listinfo/freetel-oslec[OSLEC mailing
list].
Alternatively you can also get the OSLEC code from the dahdi-linux-extra
GIT repository:
git clone git://gitorious.org/dahdi-extra/dahdi-linux-extra.git
cd dahdi-linux-extra
git archive extra-2.6 drivers/staging | (cd ..; tar xf -)
cd ..; rm -rf dahdi-linux-extra
Live Install
~~~~~~~~~~~~
In many cases you already have DAHDI installed on your system but would
@@ -494,9 +466,6 @@ max_pseudo_channels (dahdi)::
create. Pseudo channels are used when conferencing channels together.
The default is 512.
auto_assign_spans (dahdi)::
See <<_span_assignments,Span Assignments>> below.
To get a list of parameters supported by a module, use
modinfo module_name
@@ -566,7 +535,6 @@ timing device it will hang forever in the first cycle. Otherwise it will just
give you in each cycle the percent of how close it was. Also try running it
with the option -v for a verbose output.
Spans and Channels
~~~~~~~~~~~~~~~~~~
DAHDI provides telephony *channels* to the userspace applications.
@@ -586,81 +554,6 @@ There are up to 128 spans and 1024 channels. This is a hard-wired limit
number fits in a 16 bits number). Channel and span numbers start at 1.
Span Assignments
~~~~~~~~~~~~~~~~
A DAHDI device (e.g. a PCI card) is represented within the DAHDI drivers
as a 'DAHDI device'. Normally (with auto_assign_spans=1 in the module
dahdi, which is the default), when a device is discovered and loaded,
it registers with the DAHDI core and its spans automatically become
available. However if you have more than one device, you may be
interested to set explicit spans and channels numbers for them. To use
manual span assigment, set 'auto_assign_spans' to 0 . e.g. in a file
under /etc/modprobe.d/ include the following line:
options dahdi auto_assign_spans=0
You will then need to assign the spans manually at device startup. You
will need to assign a span number and channel numbers for each
available span on the system. On my test system I have one BRI PCI card
and one Astribank BRI+FXS:
# grep . /sys/bus/dahdi_devices/devices/*/spantype
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:1:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:2:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:3:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:4:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:5:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:6:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:7:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:8:BRI
/sys/bus/dahdi_devices/devices/astribanks:xbus-00/spantype:9:FXS
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:1:TE
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:2:TE
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:3:NT
/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/spantype:4:NT
All spans here, except the FXS one, are BRI spans with 3 channels per span.
In order to assign a span, we write three numbers separated by colns to
the file 'assign_span' in the SysFS node
local_num:span_num:base_chan_num
Thus:
echo 9:5:10 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
echo 2:8:40 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
echo 1:1:1 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
echo 4:6:20 >/sys/bus/dahdi_devices/devices/pci:0000:00:09.0/assign_span
echo 3:2:5 >/sys/bus/dahdi_devices/devices/astribanks:xbus-00/assign_span
As you can see, the order of span numbers or local span number is
insignificant. However the order of channel numbers must be the same as
that of span numbers.
Which indeed produced:
# head -n3 -q /proc/dahdi/*
Span 1: XBUS-00/XPD-00 "Xorcom XPD [usb:LAB-0003].1: BRI_NT"
1 XPP_BRI_NT/00/00/0
Span 2: XBUS-00/XPD-02 "Xorcom XPD [usb:LAB-0003].3: BRI_TE"
5 XPP_BRI_TE/00/02/0
Span 5: XBUS-00/XPD-10 "Xorcom XPD [usb:LAB-0003].9: FXS" (MASTER)
10 XPP_FXS/00/10/0
Span 6: B4/0/4 "B4XXP (PCI) Card 0 Span 4" RED
23 B4/0/4/1 YELLOW
Span 8: B4/0/2 "B4XXP (PCI) Card 0 Span 2" RED
40 B4/0/2/1 RED
Likewise spans can be unassigned by writing to the 'unassign-span'
"file".
Dynamic Spans
~~~~~~~~~~~~~
Dynamic spans are spans that are not represented by real hardware.
@@ -748,109 +641,6 @@ see an extra '(In use)':
2 XPP_FXS/0/0/1 FXOLS (In use)
SysFS Interface
~~~~~~~~~~~~~~~
DAHDI exposes several interfaces under the SysFS virtual file system.
SysFS represents kernel objects in nodes - directories. There properties
are often files. They may also contain other nodes or include symlinks
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.
Devices Bus
^^^^^^^^^^^
Each DAHDI device (a physical device, such as a PCI card) is represented
by a node under /sys/bus/dahdi_devices/devices named with the name of
its device.
Its attributes include:
===== /sys/bus/dahdi_devices/devices/DEVICE/assgin-span
Write-only attribute: this device's spans should now be assigned
("registered"). See section about <<_span_assignments>>.
===== /sys/bus/dahdi_devices/devices/DEVICE/auto-assign
Write-only attribute. Spans in the device auto-assign ("register" as in
the original interface). See section about <<_span_assignments>>.
===== /sys/bus/dahdi_devices/devices/DEVICE/hardware_id
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/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
it before span nodes are created.
===== /sys/bus/dahdi_devices/devices/DEVICE/spantype
Device type.
===== /sys/bus/dahdi_devices/devices/DEVICE/unassign-span
Write-only attribute: the span whose device-local number is written
should now be unassigned ("unregistered"). See section about
<<_span_assignments>>.
Spans Bus
^^^^^^^^^
Each DAHDI span is represented by a node under
/sys/bus/dahdi_spans/devices with the name 'span-N' (where N is the
number of the span). Spans of each device also reside under the node of
the device.
Useful attributes in the span node:
===== /sys/bus/dahdi_spans/devices/span-N/alarms
The alarms of the span. Currently this is a numeric representation.
This may change in the future.
===== /sys/bus/dahdi_spans/devices/span-N/basechan
The channel number of the first channel. The channel numbers of the
following channels are guaranteed to follow it.
===== /sys/bus/dahdi_spans/devices/span-N/channels
The number of the channels in the span.
===== /sys/bus/dahdi_spans/devices/span-N/desc
A free-form description of the span.
===== /sys/bus/dahdi_spans/devices/span-N/is_digital
1 if the span is digital, 0 if it isn't.
===== /sys/bus/dahdi_spans/devices/span-N/is_sync_master
1 if the span is the sync master, 0 if it isn't.
===== /sys/bus/dahdi_spans/devices/span-N/lbo
LBO setting for the channel.
===== /sys/bus/dahdi_spans/devices/span-N/lineconfig
The framing and coding of the span, for a digital span. Textual
represenation:
<B8ZS|AMI|HDB3>/<D4|ESF|CCS>[/CRC4]
===== /sys/bus/dahdi_spans/devices/span-N/local_spanno
The number of the span within the DAHDI device.
===== /sys/bus/dahdi_spans/devices/span-N/name
A concise name for this span.
===== /sys/bus/dahdi_spans/devices/span-N/spantype
A very short type string.
===== /sys/bus/dahdi_spans/devices/span-N/syncsrc
Current sync source.
User-space Interface
~~~~~~~~~~~~~~~~~~~~
User-space programs can only work with DAHDI channels. The basic
@@ -928,7 +718,7 @@ standard HDLC rate of 64k).
Low-Level Drivers
~~~~~~~~~~~~~~~~~
Low-level drivers create spans ('struct dahdi_span'). They register the
spans with the DAHDI core using 'dahdi_device_register()'.
spans with the DAHDI core using 'dahdi_register()'.
'struct dahdi_span' has a number of informative members that are updated
solely by the low-level driver:

View File

@@ -293,10 +293,6 @@ load)
# TODO: A local copy of Asterisk, configured with dahdi_gnconf.
# doable, but trickier.
run_asterisk
if [ "$LIVE_DAHDI_FREEPBXDB" = 'yes' ]; then
GENCONF_PARAMETERS=$DESTDIR/etc/dahdi/genconf_parameters \
dahdi_genconf freepbxdb
fi
;;
genconf)
genconf

View File

@@ -77,7 +77,7 @@ CFLAGS_dahdi_dynamic_ethmf.o := -DNEW_SKB_LINEARIZE
endif
endif
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-sysfs-chan.o dahdi-version.o
dahdi-objs := dahdi-base.o dahdi-sysfs.o dahdi-version.o
###############################################################################
# Find appropriate ARCH value for VPMADT032 and HPEC binary modules

6
drivers/dahdi/Makefile Normal file
View File

@@ -0,0 +1,6 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,215 +0,0 @@
/* dahdi-sysfs-chan.c
*
* Copyright (C) 2011-2012, Xorcom
* Copyright (C) 2011-2012, 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/version.h>
#define DAHDI_PRINK_MACROS_USE_debug
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <dahdi/kernel.h>
#include "dahdi.h"
#include "dahdi-sysfs.h"
/* shortcuts, for code readability */
#define MAKE_DAHDI_DEV(num, name) \
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
#define DEL_DAHDI_DEV(num) \
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
static struct class *dahdi_class;
int chan_sysfs_create(struct dahdi_chan *chan)
{
char chan_name[32];
void *dummy;
int res = 0;
if (chan->channo >= 250)
return 0;
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
return 0;
snprintf(chan_name, sizeof(chan_name), "dahdi!%d", chan->channo);
dummy = (void *)MAKE_DAHDI_DEV(chan->channo, chan_name);
if (IS_ERR(dummy)) {
res = PTR_ERR(dummy);
chan_err(chan, "Failed creating sysfs device: %d\n",
res);
return res;
}
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
return 0;
}
void chan_sysfs_remove(struct dahdi_chan *chan)
{
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
return;
DEL_DAHDI_DEV(chan->channo);
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
}
/*
* Used by dahdi_transcode.c
*/
int dahdi_register_chardev(struct dahdi_chardev *dev)
{
static const char *DAHDI_STRING = "dahdi!";
char *udevname;
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
GFP_KERNEL);
if (!udevname)
return -ENOMEM;
strcpy(udevname, DAHDI_STRING);
strcat(udevname, dev->name);
MAKE_DAHDI_DEV(dev->minor, udevname);
kfree(udevname);
return 0;
}
EXPORT_SYMBOL(dahdi_register_chardev);
/*
* Used by dahdi_transcode.c
*/
int dahdi_unregister_chardev(struct dahdi_chardev *dev)
{
DEL_DAHDI_DEV(dev->minor);
return 0;
}
EXPORT_SYMBOL(dahdi_unregister_chardev);
/*--------- Sysfs Device handling ----*/
/*
* Describe fixed device files and maintain their
* pointer so fixed_devfiles_remove() can always be called
* and work cleanly
*/
static struct {
int minor;
char *name;
void *dev; /* FIXME: wrong type because of old kernels */
} fixed_minors[] = {
{ DAHDI_CTL, "dahdi!ctl", },
{ DAHDI_TIMER, "dahdi!timer", },
{ DAHDI_CHANNEL, "dahdi!channel",},
{ DAHDI_PSEUDO, "dahdi!pseudo", },
};
/*
* Removes /dev/dahdi/{ctl,timer,channel,pseudo}
*
* It is safe to call it during initialization error handling,
* as it skips non existing objects.
*/
static void fixed_devfiles_remove(void)
{
int i;
if (!dahdi_class)
return;
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
void *d = fixed_minors[i].dev;
if (d && !IS_ERR(d))
dahdi_dbg(DEVICES, "Removing fixed device file %s\n",
fixed_minors[i].name);
DEL_DAHDI_DEV(fixed_minors[i].minor);
}
}
/*
* Creates /dev/dahdi/{ctl,timer,channel,pseudo}
*/
static int fixed_devfiles_create(void)
{
int i;
int res = 0;
if (!dahdi_class) {
dahdi_err("%s: dahdi_class is not initialized yet!\n",
__func__);
res = -ENODEV;
goto cleanup;
}
for (i = 0; i < ARRAY_SIZE(fixed_minors); i++) {
char *name = fixed_minors[i].name;
int minor = fixed_minors[i].minor;
void *dummy;
dahdi_dbg(DEVICES, "Making fixed device file %s\n", name);
dummy = (void *)MAKE_DAHDI_DEV(minor, name);
if (IS_ERR(dummy)) {
int res = PTR_ERR(dummy);
dahdi_err("%s: failed (%d: %s). Error: %d\n",
__func__, minor, name, res);
goto cleanup;
}
fixed_minors[i].dev = dummy;
}
return 0;
cleanup:
fixed_devfiles_remove();
return res;
}
/*
* Called during driver unload and while handling any error during
* driver load.
* Always clean any (and only) objects that were initialized (invariant)
*/
static void sysfs_channels_cleanup(void)
{
fixed_devfiles_remove();
if (dahdi_class) {
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
class_destroy(dahdi_class);
dahdi_class = NULL;
}
}
int __init dahdi_sysfs_chan_init(const struct file_operations *fops)
{
int res = 0;
dahdi_class = class_create(THIS_MODULE, "dahdi");
if (IS_ERR(dahdi_class)) {
res = PTR_ERR(dahdi_class);
dahdi_err("%s: class_create(dahi_chan) failed. Error: %d\n",
__func__, res);
goto cleanup;
}
res = fixed_devfiles_create();
if (res)
goto cleanup;
return 0;
cleanup:
sysfs_channels_cleanup();
return res;
}
void dahdi_sysfs_chan_exit(void)
{
sysfs_channels_cleanup();
}

View File

@@ -1,346 +1,123 @@
/* dahdi-sysfs.c
*
* Copyright (C) 2011-2012, Xorcom
* Copyright (C) 2011-2012, 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/version.h>
#define DAHDI_PRINK_MACROS_USE_debug
#include <dahdi/kernel.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/ctype.h>
#include "dahdi.h"
#include "dahdi-sysfs.h"
/* FIXME: Move to kernel.h */
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
static char *initdir = "/usr/share/dahdi";
module_param(initdir, charp, 0644);
static int span_match(struct device *dev, struct device_driver *driver)
{
return 1;
}
static inline struct dahdi_span *dev_to_span(struct device *dev)
{
return dev_get_drvdata(dev);
}
#define SPAN_VAR_BLOCK \
do { \
DAHDI_ADD_UEVENT_VAR("DAHDI_INIT_DIR=%s", initdir); \
DAHDI_ADD_UEVENT_VAR("SPAN_NUM=%d", span->spanno); \
DAHDI_ADD_UEVENT_VAR("SPAN_NAME=%s", span->name); \
} 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 span_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct dahdi_span *span;
int i = 0;
int len = 0;
if (!dev)
return -ENODEV;
span = dev_to_span(dev);
if (!span)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n",
dev_name(dev), span->name);
SPAN_VAR_BLOCK;
envp[i] = NULL;
return 0;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, NULL, "%s", name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_device_create(class, NULL, devt, device, name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_device_create(class, devt, device, name)
#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 span_uevent(struct device *dev, struct kobj_uevent_env *kenv)
{
struct dahdi_span *span;
if (!dev)
return -ENODEV;
span = dev_to_span(dev);
if (!span)
return -ENODEV;
dahdi_dbg(GENERAL, "SYFS dev_name=%s span=%s\n",
dev_name(dev), span->name);
SPAN_VAR_BLOCK;
return 0;
}
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_simple_device_add(class, devt, device, name)
#endif
#define span_attr(field, format_string) \
static BUS_ATTR_READER(field##_show, dev, buf) \
{ \
struct dahdi_span *span; \
\
span = dev_to_span(dev); \
return sprintf(buf, format_string, span->field); \
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#define CLASS_DEV_DESTROY(class, devt) \
device_destroy(class, devt)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
#define CLASS_DEV_DESTROY(class, devt) \
class_device_destroy(class, devt)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
#define CLASS_DEV_DESTROY(class, devt) \
class_simple_device_remove(devt)
#else
#define CLASS_DEV_DESTROY(class, devt) \
class_simple_device_remove(class, devt)
#endif
span_attr(name, "%s\n");
span_attr(desc, "%s\n");
span_attr(alarms, "0x%x\n");
span_attr(lbo, "%d\n");
span_attr(syncsrc, "%d\n");
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,13)
static struct class *dahdi_class = NULL;
#else
static struct class_simple *dahdi_class = NULL;
#define class_create class_simple_create
#define class_destroy class_simple_destroy
#endif
static BUS_ATTR_READER(spantype_show, dev, buf)
int dahdi_register_chardev(struct dahdi_chardev *dev)
{
struct dahdi_span *span;
static const char *DAHDI_STRING = "dahdi!";
char *udevname;
span = dev_to_span(dev);
return sprintf(buf, "%s\n", dahdi_spantype2str(span->spantype));
}
udevname = kzalloc(strlen(dev->name) + sizeof(DAHDI_STRING) + 1,
GFP_KERNEL);
if (!udevname)
return -ENOMEM;
static BUS_ATTR_READER(local_spanno_show, dev, buf)
{
struct dahdi_span *span;
span = dev_to_span(dev);
return sprintf(buf, "%d\n", local_spanno(span));
}
static BUS_ATTR_READER(is_digital_show, dev, buf)
{
struct dahdi_span *span;
span = dev_to_span(dev);
return sprintf(buf, "%d\n", dahdi_is_digital_span(span));
}
static BUS_ATTR_READER(is_sync_master_show, dev, buf)
{
struct dahdi_span *span;
span = dev_to_span(dev);
return sprintf(buf, "%d\n", dahdi_is_sync_master(span));
}
static BUS_ATTR_READER(basechan_show, dev, buf)
{
struct dahdi_span *span;
span = dev_to_span(dev);
if (!span->channels)
return -ENODEV;
return sprintf(buf, "%d\n", span->chans[0]->channo);
}
static BUS_ATTR_READER(channels_show, dev, buf)
{
struct dahdi_span *span;
span = dev_to_span(dev);
return sprintf(buf, "%d\n", span->channels);
}
static BUS_ATTR_READER(lineconfig_show, dev, buf)
{
struct dahdi_span *span;
int len = 0;
span = dev_to_span(dev);
len += lineconfig_str(span->lineconfig, buf, 20);
len += sprintf(buf + len, "\n");
return len;
}
static BUS_ATTR_READER(linecompat_show, dev, buf)
{
struct dahdi_span *span;
int bit;
int len = 0;
span = dev_to_span(dev);
for (bit = 4; bit <= 12; bit++) {
if (span->linecompat & (1 << bit)) {
const char *name = dahdi_lineconfig_bit_name(bit);
if (name)
len += sprintf(buf + len, "%s ", name);
}
}
/* chomp */
while (len > 0 && isspace(buf[len - 1]))
buf[--len] = '\0';
len += sprintf(buf + len, "\n");
return len;
}
static struct device_attribute span_dev_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(desc),
__ATTR_RO(spantype),
__ATTR_RO(local_spanno),
__ATTR_RO(alarms),
__ATTR_RO(lbo),
__ATTR_RO(syncsrc),
__ATTR_RO(is_digital),
__ATTR_RO(is_sync_master),
__ATTR_RO(basechan),
__ATTR_RO(channels),
__ATTR_RO(lineconfig),
__ATTR_RO(linecompat),
__ATTR_NULL,
};
static struct driver_attribute dahdi_attrs[] = {
__ATTR_NULL,
};
static struct bus_type spans_bus_type = {
.name = "dahdi_spans",
.match = span_match,
.uevent = span_uevent,
.dev_attrs = span_dev_attrs,
.drv_attrs = dahdi_attrs,
};
static int span_probe(struct device *dev)
{
struct dahdi_span *span;
span = dev_to_span(dev);
span_dbg(DEVICES, span, "\n");
strcpy(udevname, DAHDI_STRING);
strcat(udevname, dev->name);
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor), NULL, udevname);
kfree(udevname);
return 0;
}
EXPORT_SYMBOL(dahdi_register_chardev);
static int span_remove(struct device *dev)
int dahdi_unregister_chardev(struct dahdi_chardev *dev)
{
struct dahdi_span *span;
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, dev->minor));
span = dev_to_span(dev);
span_dbg(DEVICES, span, "\n");
return 0;
}
static struct device_driver dahdi_driver = {
.name = "generic_lowlevel",
.bus = &spans_bus_type,
.probe = span_probe,
.remove = span_remove,
.owner = THIS_MODULE
};
static void span_uevent_send(struct dahdi_span *span, enum kobject_action act)
{
struct kobject *kobj;
kobj = &span->span_device->kobj;
span_dbg(DEVICES, span, "SYFS dev_name=%s action=%d\n",
dev_name(span->span_device), act);
kobject_uevent(kobj, act);
}
static void span_release(struct device *dev)
{
dahdi_dbg(DEVICES, "%s: %s\n", __func__, dev_name(dev));
}
EXPORT_SYMBOL(dahdi_unregister_chardev);
void span_sysfs_remove(struct dahdi_span *span)
{
struct device *span_device;
int x;
for (x = 0; x < span->channels; x++) {
struct dahdi_chan *chan = span->chans[x];
if (!test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
continue;
span_dbg(DEVICES, span, "\n");
span_device = span->span_device;
if (!span_device)
return;
for (x = 0; x < span->channels; x++)
chan_sysfs_remove(span->chans[x]);
if (!dev_get_drvdata(span_device))
return;
/* Grab an extra reference to the device since we'll still want it
* after we've unregistered it */
get_device(span_device);
span_uevent_send(span, KOBJ_OFFLINE);
device_unregister(span->span_device);
dev_set_drvdata(span_device, NULL);
span_device->parent = NULL;
put_device(span_device);
memset(&span->span_device, 0, sizeof(span->span_device));
kfree(span->span_device);
span->span_device = NULL;
CLASS_DEV_DESTROY(dahdi_class,
MKDEV(DAHDI_MAJOR, chan->channo));
clear_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
}
}
int span_sysfs_create(struct dahdi_span *span)
{
struct device *span_device;
int res = 0;
int x;
if (span->span_device) {
WARN_ON(1);
return -EEXIST;
}
span->span_device = kzalloc(sizeof(*span->span_device), GFP_KERNEL);
if (!span->span_device)
return -ENOMEM;
span_device = span->span_device;
span_dbg(DEVICES, span, "\n");
span_device->bus = &spans_bus_type;
span_device->parent = &span->parent->dev;
dev_set_name(span_device, "span-%d", span->spanno);
dev_set_drvdata(span_device, span);
span_device->release = span_release;
res = device_register(span_device);
if (res) {
span_err(span, "%s: device_register 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]);
if (res)
struct dahdi_chan *chan = span->chans[x];
char chan_name[32];
void *dummy;
if (chan->channo >= 250)
continue;
if (test_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags))
continue;
snprintf(chan_name, sizeof(chan_name), "dahdi!%d",
chan->channo);
dummy = (void *)CLASS_DEV_CREATE(dahdi_class,
MKDEV(DAHDI_MAJOR, chan->channo),
NULL, chan_name);
if (IS_ERR(dummy)) {
res = PTR_ERR(dummy);
chan_err(chan, "Failed creating sysfs device: %d\n",
res);
goto cleanup;
}
set_bit(DAHDI_FLAGBIT_DEVFILE, &chan->flags);
}
return 0;
@@ -349,342 +126,105 @@ cleanup:
return res;
}
#define MAKE_DAHDI_DEV(num, name) \
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, num), NULL, name)
#define DEL_DAHDI_DEV(num) \
CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, num))
/* Only used to flag that the device exists: */
static struct {
unsigned int clean_dahdi_driver:1;
unsigned int clean_span_bus_type:1;
unsigned int clean_device_bus:1;
unsigned int clean_chardev:1;
} should_cleanup;
unsigned int ctl:1;
unsigned int timer:1;
unsigned int channel:1;
unsigned int pseudo:1;
} dummy_dev;
static inline struct dahdi_device *to_ddev(struct device *dev)
void dahdi_sysfs_exit(void)
{
return container_of(dev, struct dahdi_device, dev);
}
static ssize_t
dahdi_device_manufacturer_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n", ddev->manufacturer);
}
static ssize_t
dahdi_device_type_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n", ddev->devicetype);
}
static ssize_t
dahdi_device_span_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
unsigned int count = 0;
struct list_head *pos;
list_for_each(pos, &ddev->spans)
++count;
return sprintf(buf, "%d\n", count);
}
static ssize_t
dahdi_device_hardware_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
return sprintf(buf, "%s\n",
(ddev->hardware_id) ? ddev->hardware_id : "");
}
static ssize_t
dahdi_device_auto_assign(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dahdi_device *ddev = to_ddev(dev);
dahdi_assign_device_spans(ddev);
return count;
}
static ssize_t
dahdi_device_assign_span(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
struct dahdi_span *span;
unsigned int local_span_number;
unsigned int desired_spanno;
unsigned int desired_basechanno;
struct dahdi_device *const ddev = to_ddev(dev);
ret = sscanf(buf, "%u:%u:%u", &local_span_number, &desired_spanno,
&desired_basechanno);
if (ret != 3) {
dev_notice(dev, "bad input (should be <num>:<num>:<num>)\n");
return -EINVAL;
if (dummy_dev.pseudo) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/pseudo:\n");
DEL_DAHDI_DEV(DAHDI_PSEUDO);
dummy_dev.pseudo = 0;
}
if (desired_spanno && !desired_basechanno) {
dev_notice(dev, "Must set span number AND base chan number\n");
return -EINVAL;
if (dummy_dev.channel) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/channel:\n");
DEL_DAHDI_DEV(DAHDI_CHANNEL);
dummy_dev.channel = 0;
}
list_for_each_entry(span, &ddev->spans, device_node) {
if (local_span_number == local_spanno(span)) {
ret = dahdi_assign_span(span, desired_spanno,
desired_basechanno, 1);
return (ret) ? ret : count;
}
if (dummy_dev.timer) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/timer:\n");
DEL_DAHDI_DEV(DAHDI_TIMER);
dummy_dev.timer = 0;
}
dev_notice(dev, "no match for local span number %d\n",
local_span_number);
return -EINVAL;
}
static ssize_t
dahdi_device_unassign_span(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
int ret;
unsigned int local_span_number;
struct dahdi_span *span;
struct dahdi_device *const ddev = to_ddev(dev);
ret = sscanf(buf, "%u", &local_span_number);
if (ret != 1)
return -EINVAL;
ret = -ENODEV;
list_for_each_entry(span, &ddev->spans, device_node) {
if (local_span_number == local_spanno(span))
ret = dahdi_unassign_span(span);
if (dummy_dev.ctl) {
dahdi_dbg(DEVICES, "Removing /dev/dahdi/ctl:\n");
DEL_DAHDI_DEV(DAHDI_CTL);
dummy_dev.ctl = 0;
}
if (-ENODEV == ret) {
if (printk_ratelimit()) {
dev_info(dev, "'%d' is an invalid local span number.\n",
local_span_number);
}
return -EINVAL;
if (dahdi_class) {
dahdi_dbg(DEVICES, "Destroying DAHDI class:\n");
class_destroy(dahdi_class);
dahdi_class = NULL;
}
return (ret < 0) ? ret : count;
}
static ssize_t
dahdi_spantype_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct dahdi_device *ddev = to_ddev(dev);
int count = 0;
ssize_t total = 0;
struct dahdi_span *span;
/* TODO: Make sure this doesn't overflow the page. */
list_for_each_entry(span, &ddev->spans, device_node) {
count = sprintf(buf, "%d:%s\n",
local_spanno(span), dahdi_spantype2str(span->spantype));
buf += count;
total += count;
}
return total;
}
static ssize_t
dahdi_spantype_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dahdi_device *const ddev = to_ddev(dev);
int ret;
struct dahdi_span *span;
unsigned int local_span_number;
char spantype_name[80];
enum spantypes spantype;
ret = sscanf(buf, "%u:%70s", &local_span_number, spantype_name);
if (ret != 2) {
dev_err(&ddev->dev, "Wrong input format: '%s'\n", buf);
return -EINVAL;
}
spantype = dahdi_str2spantype(spantype_name);
if (spantype == SPANTYPE_INVALID) {
dev_err(&ddev->dev, "Invalid spantype: '%s'\n", buf);
return -EINVAL;
}
list_for_each_entry(span, &ddev->spans, device_node) {
if (local_spanno(span) == local_span_number)
break;
}
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags)) {
module_printk(KERN_WARNING, "Span %s is already assigned.\n",
span->name);
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 "
"setting type.\n", span->name);
return -EINVAL;
}
ret = span->ops->set_spantype(span, spantype);
return (ret < 0) ? ret : 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(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_NULL,
};
static struct bus_type dahdi_device_bus = {
.name = "dahdi_devices",
.dev_attrs = dahdi_device_attrs,
};
static void dahdi_sysfs_cleanup(void)
{
dahdi_dbg(DEVICES, "SYSFS\n");
if (should_cleanup.clean_dahdi_driver) {
dahdi_dbg(DEVICES, "Unregister driver\n");
driver_unregister(&dahdi_driver);
should_cleanup.clean_dahdi_driver = 0;
}
if (should_cleanup.clean_span_bus_type) {
dahdi_dbg(DEVICES, "Unregister span bus type\n");
bus_unregister(&spans_bus_type);
should_cleanup.clean_span_bus_type = 0;
}
dahdi_sysfs_chan_exit();
if (should_cleanup.clean_chardev) {
dahdi_dbg(DEVICES, "Unregister character device\n");
unregister_chrdev(DAHDI_MAJOR, "dahdi");
should_cleanup.clean_chardev = 0;
}
if (should_cleanup.clean_device_bus) {
dahdi_dbg(DEVICES, "Unregister DAHDI device bus\n");
bus_unregister(&dahdi_device_bus);
should_cleanup.clean_device_bus = 0;
}
}
static void dahdi_device_release(struct device *dev)
{
struct dahdi_device *ddev = container_of(dev, struct dahdi_device, dev);
kfree(ddev);
}
/**
* dahdi_sysfs_add_device - Add the dahdi_device into the sysfs hierarchy.
* @ddev: The device to add.
* @parent: The physical device that is implementing this device.
*
* By adding the dahdi_device to the sysfs hierarchy user space can control
* how spans are numbered.
*
*/
int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent)
{
int ret;
struct device *const dev = &ddev->dev;
const char *dn;
dev->parent = parent;
dev->bus = &dahdi_device_bus;
dn = dev_name(dev);
if (!dn || !*dn) {
/* Invent default name based on parent */
if (!parent)
return -EINVAL;
dev_set_name(dev, "%s:%s", parent->bus->name, dev_name(parent));
}
ret = device_add(dev);
return ret;
}
void dahdi_sysfs_init_device(struct dahdi_device *ddev)
{
device_initialize(&ddev->dev);
ddev->dev.release = dahdi_device_release;
}
void dahdi_sysfs_unregister_device(struct dahdi_device *ddev)
{
device_del(&ddev->dev);
unregister_chrdev(DAHDI_MAJOR, "dahdi");
}
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops)
{
int res = 0;
void *dev;
dahdi_dbg(DEVICES, "Registering DAHDI device bus\n");
res = bus_register(&dahdi_device_bus);
if (res)
return res;
should_cleanup.clean_device_bus = 1;
dahdi_dbg(DEVICES,
"Registering character device (major=%d)\n", DAHDI_MAJOR);
res = register_chrdev(DAHDI_MAJOR, "dahdi", dahdi_fops);
if (res) {
module_printk(KERN_ERR,
"Unable to register DAHDI character device "
"handler on %d\n", DAHDI_MAJOR);
module_printk(KERN_ERR, "Unable to register DAHDI character device handler on %d\n", DAHDI_MAJOR);
return res;
}
should_cleanup.clean_chardev = 1;
res = dahdi_sysfs_chan_init(dahdi_fops);
if (res)
goto cleanup;
res = bus_register(&spans_bus_type);
if (res) {
dahdi_err("%s: bus_register(%s) failed. Error number %d",
__func__, spans_bus_type.name, res);
goto cleanup;
}
should_cleanup.clean_span_bus_type = 1;
res = driver_register(&dahdi_driver);
if (res) {
dahdi_err("%s: driver_register(%s) failed. Error number %d",
__func__, dahdi_driver.name, res);
goto cleanup;
}
should_cleanup.clean_dahdi_driver = 1;
module_printk(KERN_INFO, "Telephony Interface Registered on major %d\n",
DAHDI_MAJOR);
module_printk(KERN_INFO, "Version: %s\n", dahdi_version);
dahdi_class = class_create(THIS_MODULE, "dahdi");
if (!dahdi_class) {
res = -EEXIST;
goto cleanup;
}
dahdi_dbg(DEVICES, "Creating /dev/dahdi/timer:\n");
dev = MAKE_DAHDI_DEV(DAHDI_TIMER, "dahdi!timer");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.timer = 1;
dahdi_dbg(DEVICES, "Creating /dev/dahdi/channel:\n");
dev = MAKE_DAHDI_DEV(DAHDI_CHANNEL, "dahdi!channel");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.channel = 1;
dahdi_dbg(DEVICES, "Creating /dev/dahdi/pseudo:\n");
dev = MAKE_DAHDI_DEV(DAHDI_PSEUDO, "dahdi!pseudo");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.pseudo = 1;
dahdi_dbg(DEVICES, "Creating /dev/dahdi/ctl:\n");
dev = MAKE_DAHDI_DEV(DAHDI_CTL, "dahdi!ctl");
if (IS_ERR(dev)) {
res = PTR_ERR(dev);
goto cleanup;
}
dummy_dev.ctl = 1;
return 0;
cleanup:
dahdi_sysfs_cleanup();
dahdi_sysfs_exit();
return res;
}
void dahdi_sysfs_exit(void)
{
dahdi_sysfs_cleanup();
}

View File

@@ -1,55 +0,0 @@
#ifndef DAHDI_SYSFS_H
#define DAHDI_SYSFS_H
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count)
#define BUS_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
char *buf)
#define BUS_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count)
#define DRIVER_ATTR_READER(name, drv, buf) \
ssize_t name(struct device_driver *drv, char * buf)
/* Device file creation macros */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, NULL, "%s", name)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#define CLASS_DEV_CREATE(class, devt, device, name) \
device_create(class, device, devt, name)
#else
#define CLASS_DEV_CREATE(class, devt, device, name) \
class_device_create(class, NULL, devt, device, name)
#endif
/* Device file destruction macros */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#define CLASS_DEV_DESTROY(class, devt) \
device_destroy(class, devt)
#else
#define CLASS_DEV_DESTROY(class, devt) \
class_device_destroy(class, devt)
#endif
/* Global */
int __init dahdi_sysfs_chan_init(const struct file_operations *fops);
void dahdi_sysfs_chan_exit(void);
/* Channel Handling */
int chan_sysfs_create(struct dahdi_chan *chan);
void chan_sysfs_remove(struct dahdi_chan *chan);
#endif /* DAHDI_SYSFS_H */

View File

@@ -6,7 +6,6 @@
*
* Written by Tzafrir Cohen <tzafrir.cohen@xorcom.com>
* Copyright (C) 2011, Xorcom
* Copyright (C) 2011, Digium, Inc
*
* All rights reserved.
*
@@ -35,28 +34,4 @@ void span_sysfs_remove(struct dahdi_span *span);
int __init dahdi_sysfs_init(const struct file_operations *dahdi_fops);
void dahdi_sysfs_exit(void);
void dahdi_sysfs_init_device(struct dahdi_device *ddev);
int dahdi_sysfs_add_device(struct dahdi_device *ddev, struct device *parent);
void dahdi_sysfs_unregister_device(struct dahdi_device *ddev);
int dahdi_assign_span(struct dahdi_span *span, unsigned int spanno,
unsigned int basechan, int prefmaster);
int dahdi_unassign_span(struct dahdi_span *span);
int dahdi_assign_device_spans(struct dahdi_device *ddev);
static inline int get_span(struct dahdi_span *span)
{
return try_module_get(span->ops->owner);
}
static inline void put_span(struct dahdi_span *span)
{
module_put(span->ops->owner);
}
static inline int local_spanno(struct dahdi_span *span)
{
return span->offset + 1;
}
#endif /* _DAHDI_H */

View File

@@ -10,7 +10,7 @@
* Converted to use HighResTimers on i386 by Jeffery Palmer <jeff@triggerinc.com>
*
* Copyright (C) 2002, Hermes Softlab
* Copyright (C) 2004-2012, Digium, Inc.
* Copyright (C) 2004-2009, Digium, Inc.
*
* All rights reserved.
*
@@ -75,7 +75,6 @@ static inline void hrtimer_set_expires(struct hrtimer *timer, ktime_t time)
#endif
struct dahdi_dummy {
struct dahdi_device *ddev;
struct dahdi_span span;
struct dahdi_chan _chan;
struct dahdi_chan *chan;
@@ -206,44 +205,37 @@ static const struct dahdi_span_ops dummy_ops = {
static int dahdi_dummy_initialize(struct dahdi_dummy *ztd)
{
int res = 0;
/* DAHDI stuff */
ztd->ddev = dahdi_create_device();
if (!ztd->ddev)
return -ENOMEM;
dev_set_name(&ztd->ddev->dev, "dahdi_dummy");
ztd->chan = &ztd->_chan;
sprintf(ztd->span.name, "DAHDI_DUMMY/1");
snprintf(ztd->span.desc, sizeof(ztd->span.desc) - 1, "%s (source: " CLOCK_SRC ") %d", ztd->span.name, 1);
sprintf(ztd->chan->name, "DAHDI_DUMMY/%d/%d", 1, 0);
ztd->ddev->devicetype = "DAHDI Dummy Timing";
strlcpy(ztd->span.devicetype, "DAHDI Dummy Timing",
sizeof(ztd->span.devicetype));
ztd->chan->chanpos = 1;
ztd->span.chans = &ztd->chan;
ztd->span.channels = 0; /* no channels on our span */
ztd->span.deflaw = DAHDI_LAW_MULAW;
ztd->chan->pvt = ztd;
ztd->span.ops = &dummy_ops;
list_add_tail(&ztd->span.device_node, &ztd->ddev->spans);
res = dahdi_register_device(ztd->ddev, NULL);
return res;
if (dahdi_register(&ztd->span, 0)) {
return -1;
}
return 0;
}
int init_module(void)
{
int res;
ztd = kzalloc(sizeof(*ztd), GFP_KERNEL);
if (ztd == NULL) {
printk(KERN_ERR "dahdi_dummy: Unable to allocate memory\n");
return -ENOMEM;
}
res = dahdi_dummy_initialize(ztd);
if (res) {
printk(KERN_ERR
"dahdi_dummy: Unable to intialize DAHDI driver (%d)\n",
res);
if (dahdi_dummy_initialize(ztd)) {
printk(KERN_ERR "dahdi_dummy: Unable to intialize DAHDI driver\n");
kfree(ztd);
return res;
return -ENODEV;
}
#if defined(USE_HIGHRESTIMER)
@@ -281,8 +273,7 @@ void cleanup_module(void)
atomic_set(&shutdown, 1);
del_timer_sync(&timer);
#endif
dahdi_unregister_device(ztd->ddev);
dahdi_free_device(ztd->ddev);
dahdi_unregister(&ztd->span);
kfree(ztd);
if (debug)
printk(KERN_DEBUG "dahdi_dummy: cleanup() finished\n");

View File

@@ -3,7 +3,7 @@
*
* Written by Mark Spencer <markster@digium.com>
*
* Copyright (C) 2001-2012, Digium, Inc.
* Copyright (C) 2001-2010, Digium, Inc.
*
* All rights reserved.
*
@@ -385,18 +385,32 @@ static void dahdi_dynamic_release(struct kref *kref)
WARN_ON(test_bit(DAHDI_FLAGBIT_REGISTERED, &d->span.flags));
if (d->pvt) {
if (d->driver && d->driver->destroy) {
__module_get(d->driver->owner);
d->driver->destroy(d);
module_put(d->driver->owner);
} else {
WARN_ON(1);
}
}
kfree(d->msgbuf);
for (x = 0; x < d->span.channels; x++)
kfree(d->chans[x]);
dahdi_free_device(d->ddev);
kfree(d);
}
static inline int dynamic_put(struct dahdi_dynamic *d)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
kref_put(&d->kref, dahdi_dynamic_release);
return 1;
#else
return kref_put(&d->kref, dahdi_dynamic_release);
#endif
}
static inline void dynamic_get(struct dahdi_dynamic *d)
@@ -455,25 +469,7 @@ static int _destroy_dynamic(struct dahdi_dynamic_span *dds)
return -EBUSY;
}
if (d->pvt) {
if (d->driver && d->driver->destroy) {
if (!try_module_get(d->driver->owner)) {
/* The driver for this device is in the
* process of unloading. Leave this dynamic on
* the list so it's cleaned up when the driver
* unregisters. */
dynamic_put(d);
return -ENXIO;
}
d->driver->destroy(d);
module_put(d->driver->owner);
} else {
WARN_ON(1);
}
d->pvt = NULL;
}
dahdi_unregister_device(d->ddev);
dahdi_unregister(&d->span);
spin_lock_irqsave(&dspan_lock, flags);
list_del_rcu(&d->list);
@@ -582,8 +578,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
d = kzalloc(sizeof(*d), GFP_KERNEL);
if (!d)
return -ENOMEM;
kref_init(&d->kref);
d->ddev = dahdi_create_device();
for (x = 0; x < dds->numchans; x++) {
d->chans[x] = kzalloc(sizeof(*d->chans[x]), GFP_KERNEL);
@@ -608,10 +604,9 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
strlcpy(d->dname, dds->driver, sizeof(d->dname));
strlcpy(d->addr, dds->addr, sizeof(d->addr));
d->timing = dds->timing;
snprintf(d->span.name, sizeof(d->span.name), "DYN/%s/%s",
dds->driver, dds->addr);
snprintf(d->span.desc, sizeof(d->span.desc),
"Dynamic '%s' span at '%s'", dds->driver, dds->addr);
sprintf(d->span.name, "DYN/%s/%s", dds->driver, dds->addr);
sprintf(d->span.desc, "Dynamic '%s' span at '%s'",
dds->driver, dds->addr);
d->span.deflaw = DAHDI_LAW_MULAW;
d->span.flags |= DAHDI_FLAG_RBS;
d->span.chans = d->chans;
@@ -662,12 +657,8 @@ static int _create_dynamic(struct dahdi_dynamic_span *dds)
return res;
}
d->ddev->devicetype = d->span.name;
d->ddev->hardware_id = d->span.name;
dev_set_name(&d->ddev->dev, "dynamic:%s:%d", dds->driver, dtd->id++);
list_add_tail(&d->span.device_node, &d->ddev->spans);
/* Whee! We're created. Now register the span */
if (dahdi_register_device(d->ddev, d->dev)) {
if (dahdi_register(&d->span, 0)) {
printk(KERN_NOTICE "Unable to register span '%s'\n",
d->span.name);
dynamic_put(d);
@@ -770,17 +761,19 @@ void dahdi_dynamic_unregister_driver(struct dahdi_dynamic_driver *dri)
list_for_each_entry_safe(d, n, &dspan_list, list) {
if (d->driver == dri) {
if (d->pvt) {
if (d->driver && d->driver->destroy)
if (d->driver && d->driver->destroy) {
__module_get(d->driver->owner);
d->driver->destroy(d);
else
module_put(d->driver->owner);
} else {
WARN_ON(1);
}
}
dahdi_unregister_device(d->ddev);
dahdi_unregister(&d->span);
spin_lock_irqsave(&dspan_lock, flags);
list_del_rcu(&d->list);
spin_unlock_irqrestore(&dspan_lock, flags);
synchronize_rcu();
d->driver = NULL;
dynamic_put(d);
}
}
@@ -824,13 +817,10 @@ static void check_for_red_alarm(unsigned long ignored)
mod_timer(&alarmcheck, jiffies + 1 * HZ);
}
static const struct dahdi_dynamic_ops dahdi_dynamic_ops = {
.owner = THIS_MODULE,
.ioctl = dahdi_dynamic_ioctl,
};
static int dahdi_dynamic_init(void)
{
dahdi_set_dynamic_ioctl(dahdi_dynamic_ioctl);
/* Start process to check for RED ALARM */
init_timer(&alarmcheck);
alarmcheck.expires = 0;
@@ -841,25 +831,19 @@ static int dahdi_dynamic_init(void)
#ifdef ENABLE_TASKLETS
tasklet_init(&dahdi_dynamic_tlet, dahdi_dynamic_tasklet, 0);
#endif
dahdi_set_dynamic_ops(&dahdi_dynamic_ops);
printk(KERN_INFO "DAHDI Dynamic Span support LOADED\n");
return 0;
}
static void dahdi_dynamic_cleanup(void)
{
dahdi_set_dynamic_ops(NULL);
#ifdef ENABLE_TASKLETS
if (taskletpending) {
tasklet_disable(&dahdi_dynamic_tlet);
tasklet_kill(&dahdi_dynamic_tlet);
}
#endif
del_timer_sync(&alarmcheck);
/* Must call again in case it was running before and rescheduled
* itself. */
dahdi_set_dynamic_ioctl(NULL);
del_timer(&alarmcheck);
printk(KERN_INFO "DAHDI Dynamic Span support unloaded\n");
}

View File

@@ -3,7 +3,7 @@
*
* Written by Mark Spencer <markster@digium.com>
*
* Copyright (C) 2001-2012, Digium, Inc.
* Copyright (C) 2001-2008, Digium, Inc.
*
* All rights reserved.
*
@@ -71,12 +71,14 @@ static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short sub
if (z)
span = z->span;
spin_unlock_irqrestore(&zlock, flags);
if (!span || !test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
return NULL;
return span;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
#else
static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
#endif
{
struct dahdi_span *span;
struct ztdeth_header *zh;
@@ -85,7 +87,11 @@ static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet
#else
zh = (struct ztdeth_header *)skb->nh.raw;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr);
#else
span = ztdeth_getspan(skb->mac.ethernet->h_source, zh->subaddr);
#endif
if (span) {
skb_pull(skb, sizeof(struct ztdeth_header));
#ifdef NEW_SKB_LINEARIZE
@@ -146,7 +152,7 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
spin_lock_irqsave(&zlock, flags);
z = dyn->pvt;
if (z && z->dev) {
if (z->dev) {
/* Copy fields to local variables to remove spinlock ASAP */
dev = z->dev;
memcpy(addr, z->addr, sizeof(z->addr));
@@ -185,44 +191,15 @@ static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
spin_unlock_irqrestore(&zlock, flags);
}
/**
* dahdi_dynamic_flush_work_fn - Flush all pending transactions.
*
* This function is run in a work queue since we can't guarantee interrupts
* will be enabled when we're called, and dev_queue_xmit() requires that
* interrupts be enabled.
*
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static void dahdi_dynamic_flush_work_fn(void *data)
#else
static void dahdi_dynamic_flush_work_fn(struct work_struct *work)
#endif
static int ztdeth_flush(void)
{
struct sk_buff *skb;
/* Handle all transmissions now */
while ((skb = skb_dequeue(&skbs))) {
dev_queue_xmit(skb);
}
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
dahdi_dynamic_flush_work_fn, NULL);
#else
static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
dahdi_dynamic_flush_work_fn);
#endif
/**
* ztdeth_flush - Flush all pending transactions.
*
* This function is called in interrupt context while processing the master
* span.
*/
static int ztdeth_flush(void)
{
schedule_work(&dahdi_dynamic_eth_flush_work);
return 0;
}
@@ -307,12 +284,11 @@ static void ztdeth_destroy(struct dahdi_dynamic *dyn)
prev = cur;
cur = cur->next;
}
spin_unlock_irqrestore(&zlock, flags);
if (cur == z) { /* Successfully removed */
dyn->pvt = NULL;
printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name);
kfree(z);
}
spin_unlock_irqrestore(&zlock, flags);
}
static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
@@ -435,27 +411,20 @@ static struct notifier_block ztdeth_nblock = {
static int __init ztdeth_init(void)
{
skb_queue_head_init(&skbs);
dev_add_pack(&ztdeth_ptype);
register_netdevice_notifier(&ztdeth_nblock);
dahdi_dynamic_register_driver(&ztd_eth);
skb_queue_head_init(&skbs);
return 0;
}
static void __exit ztdeth_exit(void)
{
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
flush_scheduled_work();
#else
cancel_work_sync(&dahdi_dynamic_eth_flush_work);
#endif
dahdi_dynamic_unregister_driver(&ztd_eth);
unregister_netdevice_notifier(&ztdeth_nblock);
dev_remove_pack(&ztdeth_ptype);
skb_queue_purge(&skbs);
unregister_netdevice_notifier(&ztdeth_nblock);
dahdi_dynamic_unregister_driver(&ztd_eth);
}
MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support");

View File

@@ -224,8 +224,13 @@ static inline int ethmf_trx_spans_ready(unsigned int addr_hash, struct ztdeth *(
/**
* Ethernet receiving side processing function.
*/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt, struct net_device *orig_dev)
#else
static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
struct packet_type *pt)
#endif
{
int num_spans = 0, span_index = 0;
unsigned char *data;
@@ -262,8 +267,13 @@ static int ztdethmf_rcv(struct sk_buff *skb, struct net_device *dev,
rcu_read_lock();
do {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
find_ethmf(eth_hdr(skb)->h_source,
htons(span_index), &z, &span);
#else
find_ethmf(skb->mac.ethernet->h_source,
htons(span_index), &z, &span);
#endif
if (unlikely(!z || !span)) {
/* The recv'd span does not belong to us */
/* ethmf_errors_inc(); */
@@ -386,6 +396,10 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
struct net_device *dev;
unsigned char addr[ETH_ALEN];
int spans_ready = 0, index = 0;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
static DEFINE_SPINLOCK(lock);
unsigned long flags;
#endif
if (atomic_read(&shutdown))
return;
@@ -397,12 +411,24 @@ static void ztdethmf_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
return;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 10)
if (!atomic_read(&z->ready)) {
spin_lock_irqsave(&lock, flags);
atomic_inc(&z->ready);
if (1 == atomic_read(&z->ready)) {
memcpy(z->msgbuf, msg, msglen);
z->msgbuf_len = msglen;
}
spin_unlock_irqrestore(&lock, flags);
}
#else
if (!atomic_read(&z->ready)) {
if (atomic_inc_return(&z->ready) == 1) {
memcpy(z->msgbuf, msg, msglen);
z->msgbuf_len = msglen;
}
}
#endif
spans_ready = ethmf_trx_spans_ready(z->addr_hash, &ready_spans);
if (spans_ready) {

View File

@@ -78,11 +78,10 @@ static LIST_HEAD(dynamic_local_list);
static void
dahdi_dynamic_local_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
{
struct dahdi_dynamic_local *d;
struct dahdi_dynamic_local *const d = dyn->pvt;
unsigned long flags;
spin_lock_irqsave(&local_lock, flags);
d = dyn->pvt;
if (d && d->peer && d->peer->span) {
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &d->peer->span->flags))
dahdi_dynamic_receive(d->peer->span, msg, msglen);
@@ -131,12 +130,11 @@ static int digit2int(char d)
static void dahdi_dynamic_local_destroy(struct dahdi_dynamic *dyn)
{
struct dahdi_dynamic_local *d;
struct dahdi_dynamic_local *d = dyn->pvt;
unsigned long flags;
struct dahdi_dynamic_local *cur;
spin_lock_irqsave(&local_lock, flags);
d = dyn->pvt;
list_for_each_entry(cur, &dynamic_local_list, node) {
if (cur->peer == d)
cur->peer = NULL;

View File

@@ -7,7 +7,7 @@
* This "echo can" will completely hose your audio.
* Don't use it unless you're absolutely sure you know what you're doing.
*
* Copyright (C) 2007-2012, Digium, Inc.
* Copyright (C) 2007-2008, Digium, Inc.
*
* All rights reserved.
*
@@ -38,6 +38,9 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);

View File

@@ -5,7 +5,7 @@
*
* Based upon mec2.h
*
* Copyright (C) 2002-2012, Digium, Inc.
* Copyright (C) 2002, Digium, Inc.
*
* Additional background on the techniques used in this code can be found in:
*
@@ -44,6 +44,9 @@
static int debug;
static int aggressive;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
/* Uncomment to provide summary statistics for overall echo can performance every 4000 samples */
/* #define MEC2_STATS 4000 */

View File

@@ -5,7 +5,7 @@
*
* Based upon kb1ec.h and mec2.h
*
* Copyright (C) 2002-2012, Digium, Inc.
* Copyright (C) 2002, Digium, Inc.
*
* Additional background on the techniques used in this code can be found in:
*
@@ -44,6 +44,9 @@
static int debug;
static int aggressive;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk("%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#define ABS(a) abs(a!=-32768?a:-32767)
#define RESTORE_COEFFS {\

View File

@@ -36,6 +36,8 @@
#include <dahdi/kernel.h>
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
static int echo_can_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p, struct dahdi_echocan_state **ec);
static void echo_can_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);

View File

@@ -48,6 +48,9 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#include "arith.h"
#ifndef NULL

View File

@@ -47,6 +47,9 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#include "fir.h"
#ifndef NULL

View File

@@ -24,16 +24,14 @@
OCT6114_064_VERSION:=1.05.01
OCT6114_128_VERSION:=1.05.01
OCT6114_256_VERSION:=1.05.01
TC400M_VERSION:=MR6.12
VPMADT032_VERSION:=1.25.0
HX8_VERSION:=2.06
VPMOCT032_VERSION:=1.12.0
WCT820_VERSION:=1.76
VPMOCT032_VERSION:=1.11.0
FIRMWARE_URL:=http://downloads.digium.com/pub/telephony/firmware/releases
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032 FIRMWARE-TE820
ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-TC400M FIRMWARE-HX8 FIRMWARE-VPMOCT032
# 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
@@ -44,18 +42,15 @@ ALL_FIRMWARE=FIRMWARE-OCT6114-064 FIRMWARE-OCT6114-128 FIRMWARE-OCT6114-256 FIRM
# Build a list of firmware package filenames we need
FIRMWARE:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064-$(OCT6114_064_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TC400M=dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-HX8=dahdi-fw-hx8-$(HX8_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032-$(VPMOCT032_VERSION).tar.gz)
FIRMWARE:=$(FIRMWARE:FIRMWARE-TE820=dahdi-fw-te820-$(WCT820_VERSION).tar.gz)
FWLOADERS:=dahdi-fwload-vpmadt032-$(VPMADT032_VERSION).tar.gz
# Build a list of object files if hotplug will not be used
OBJECT_FILES:=$(ALL_FIRMWARE:FIRMWARE-OCT6114-064=dahdi-fw-oct6114-064.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-128=dahdi-fw-oct6114-128.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-OCT6114-256=dahdi-fw-oct6114-256.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-TC400M=dahdi-fw-tc400m.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-HX8=dahdi-fw-hx8.o)
OBJECT_FILES:=$(OBJECT_FILES:FIRMWARE-VPMOCT032=dahdi-fw-vpmoct032.o)
@@ -129,17 +124,6 @@ ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-12
else
@echo "Firmware dahdi-fw-oct6114-128.bin is already installed with required version $(OCT6114_128_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-oct6114-256.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
@install -m 644 dahdi-fw-oct6114-256.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-oct6114-256-$(OCT6114_256_VERSION)
else
@echo "Firmware dahdi-fw-oct6114-256.bin is already installed with required version $(OCT6114_256_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-tc400m-$(TC400M_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-tc400m.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-tc400m.bin $(DESTDIR)/usr/lib/hotplug/firmware
@@ -173,17 +157,6 @@ ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-vpmoct032-
else
@echo "Firmware dahdi-fw-vpmoct032.bin is already installed with required version $(VPMOCT032_VERSION)"
endif
ifeq ($(shell if ( [ -f $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ) && ( [ -f $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION) ] ); then echo "no"; else echo "yes"; fi),yes)
@echo "Installing dahdi-fw-te820.bin to hotplug firmware directories"
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/usr/lib/hotplug/firmware
@rm -rf $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-*
@touch $(DESTDIR)/usr/lib/hotplug/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
@install -m 644 dahdi-fw-te820.bin $(DESTDIR)/lib/firmware
@rm -rf $(DESTDIR)/lib/firmware/.dahdi-fw-te820-*
@touch $(DESTDIR)/lib/firmware/.dahdi-fw-te820-$(WCT820_VERSION)
else
@echo "Firmware dahdi-fw-te820.bin is already installed with required version $(WCT820_VERSION)"
endif
# Uninstall any installed dahdi firmware images from hotplug firmware directories
hotplug-uninstall:
@@ -212,11 +185,6 @@ dahdi-fw-oct6114-128.o: dahdi-fw-oct6114-128-$(OCT6114_128_VERSION).tar.gz dahdi
@echo Making firmware object file for dahdi-fw-oct6114-128.bin
./make_firmware_object dahdi-fw-oct6114-128.bin $@
# Build object file of an oct6114 256 firmware image for linking
dahdi-fw-oct6114-256.o: dahdi-fw-oct6114-256-$(OCT6114_256_VERSION).tar.gz dahdi-fw-oct6114-256.bin make_firmware_object
@echo Making firmware object file for dahdi-fw-oct6114-256.bin
./make_firmware_object dahdi-fw-oct6114-256.bin $@
# Build object file of a TC400M firmware image for linking
dahdi-fw-tc400m.o: dahdi-fw-tc400m-$(TC400M_VERSION).tar.gz dahdi-fw-tc400m.bin make_firmware_object
@echo Making firmware object file for dahdi-fw-tc400m.bin

View File

@@ -1,7 +1,7 @@
/*
* DAHDI Telephony Interface to Digium High-Performance Echo Canceller
*
* Copyright (C) 2006-2012 Digium, Inc.
* Copyright (C) 2006-2008 Digium, Inc.
*
* All rights reserved.
*
@@ -31,6 +31,9 @@
static int debug;
#define module_printk(level, fmt, args...) printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define debug_printk(level, fmt, args...) if (debug >= level) printk(KERN_DEBUG "%s (%s): " fmt, THIS_MODULE->name, __FUNCTION__, ## args)
#include "hpec_user.h"
#include "hpec.h"
@@ -72,9 +75,18 @@ static int __attribute__((regparm(0), format(printf, 1, 2))) logger(const char *
int res;
va_list args;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
va_start(args, format);
res = vprintk(format, args);
va_end(args);
#else
char buf[256];
va_start(args, format);
res = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
printk(KERN_INFO "%s" buf);
#endif
return res;
}

View File

@@ -397,7 +397,7 @@ $Octasic_Revision: 171 $
/* Max defines.*/
#ifndef cOCT6100_MAX_ECHO_CHANNELS
#define cOCT6100_MAX_ECHO_CHANNELS 256
#define cOCT6100_MAX_ECHO_CHANNELS 128
#endif
#define cOCT6100_MAX_TSI_CNCTS 1530
#define cOCT6100_MAX_CALLER_ID_PLAYOUT_BUFFERS ( 3328 + 6 )

View File

@@ -146,7 +146,6 @@ struct encdec
struct pciradio {
struct pci_dev *dev;
struct dahdi_device *ddev;
struct dahdi_span span;
unsigned char ios;
int usecount;
@@ -1489,7 +1488,7 @@ static int pciradio_initialize(struct pciradio *rad)
rad->span.flags = DAHDI_FLAG_RBS;
rad->span.ops = &pciradio_span_ops;
if (dahdi_register_device(rad->ddev, &rad->dev->dev)) {
if (dahdi_register(&rad->span, 0)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
@@ -1778,7 +1777,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
release_region(rad->ioaddr, 0xff);
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)rad->writechunk, rad->writedma);
pci_set_drvdata(pdev, NULL);
dahdi_free_device(rad->ddev);
dahdi_unregister(&rad->span);
kfree(rad);
return -EIO;
@@ -1811,7 +1810,7 @@ static int __devinit pciradio_init_one(struct pci_dev *pdev, const struct pci_de
static void pciradio_release(struct pciradio *rad)
{
dahdi_unregister_device(rad->ddev);
dahdi_unregister(&rad->span);
if (rad->freeregion)
release_region(rad->ioaddr, 0xff);
kfree(rad);

View File

@@ -97,7 +97,6 @@ struct tor2 {
unsigned long xilinx8_region; /* 8 bit Region allocated to Xilinx */
unsigned long xilinx8_len; /* Length of 8 bit Xilinx region */
__iomem volatile unsigned char *mem8; /* Virtual representation of 8 bit Xilinx memory area */
struct dahdi_device *ddev;
struct tor2_span tspans[SPANS_PER_CARD]; /* Span data */
struct dahdi_chan **chans[SPANS_PER_CARD]; /* Pointers to card channels */
struct tor2_chan tchans[32 * SPANS_PER_CARD]; /* Channel user data */
@@ -286,16 +285,20 @@ static void init_spans(struct tor2 *tor)
snprintf(s->desc, sizeof(s->desc) - 1,
"Tormenta 2 (PCI) Quad %s Card %d Span %d",
(tor->cardtype == TYPE_T1) ? "T1" : "E1", tor->num, x + 1);
s->manufacturer = "Digium";
strlcpy(s->devicetype, tor->type, sizeof(s->devicetype));
snprintf(s->location, sizeof(s->location) - 1,
"PCI Bus %02d Slot %02d", tor->pci->bus->number, PCI_SLOT(tor->pci->devfn) + 1);
if (tor->cardtype == TYPE_T1) {
s->channels = 24;
s->deflaw = DAHDI_LAW_MULAW;
s->linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
s->spantype = SPANTYPE_DIGITAL_T1;
s->spantype = "T1";
} else {
s->channels = 31;
s->deflaw = DAHDI_LAW_ALAW;
s->linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
s->spantype = SPANTYPE_DIGITAL_E1;
s->spantype = "E1";
}
s->chans = tor->chans[x];
s->flags = DAHDI_FLAG_RBS;
@@ -319,31 +322,19 @@ static void init_spans(struct tor2 *tor)
static int __devinit tor2_launch(struct tor2 *tor)
{
int res;
struct dahdi_span *s;
int i;
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &tor->tspans[0].dahdi_span.flags))
return 0;
tor->ddev = dahdi_create_device();
tor->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
tor->pci->bus->number,
PCI_SLOT(tor->pci->devfn) + 1);
if (!tor->ddev->location)
return -ENOMEM;
printk(KERN_INFO "Tor2: Launching card: %d\n", tor->order);
for (i = 0; i < SPANS_PER_CARD; ++i) {
s = &tor->tspans[i].dahdi_span;
list_add_tail(&s->device_node, &tor->ddev->spans);
}
res = dahdi_register_device(tor->ddev, &tor->pci->dev);
if (res) {
dev_err(&tor->pci->dev, "Unable to register with DAHDI.\n");
return res;
if (dahdi_register(s, 0)) {
printk(KERN_ERR "Unable to register span %s\n", s->name);
goto error_exit;
}
}
writew(PLX_INTENA, &tor->plx[INTCSR]); /* enable PLX interrupt */
@@ -351,6 +342,14 @@ static int __devinit tor2_launch(struct tor2 *tor)
tasklet_init(&tor->tor2_tlet, tor2_tasklet, (unsigned long)tor);
#endif
return 0;
error_exit:
for (i = 0; i < SPANS_PER_CARD; ++i) {
s = &tor->tspans[i].dahdi_span;
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
dahdi_unregister(s);
}
return -1;
}
static void free_tor(struct tor2 *tor)
@@ -366,8 +365,6 @@ static void free_tor(struct tor2 *tor)
if (tor->chans[x])
kfree(tor->chans[x]);
}
kfree(tor->ddev->location);
dahdi_free_device(tor->ddev);
kfree(tor);
}
@@ -634,6 +631,7 @@ static struct pci_driver tor2_driver;
static void __devexit tor2_remove(struct pci_dev *pdev)
{
struct tor2 *tor;
int i;
tor = pci_get_drvdata(pdev);
if (!tor)
@@ -643,7 +641,11 @@ static void __devexit tor2_remove(struct pci_dev *pdev)
writeb(0, &tor->mem8[LEDREG]);
writew(0, &tor->plx[INTCSR]);
free_irq(tor->irq, tor);
dahdi_unregister_device(tor->ddev);
for (i = 0; i < SPANS_PER_CARD; ++i) {
struct dahdi_span *s = &tor->tspans[i].dahdi_span;
if (test_bit(DAHDI_FLAGBIT_REGISTERED, &s->flags))
dahdi_unregister(s);
}
release_mem_region(tor->plx_region, tor->plx_len);
release_mem_region(tor->xilinx32_region, tor->xilinx32_len);
release_mem_region(tor->xilinx8_region, tor->xilinx8_len);

View File

@@ -126,8 +126,8 @@ static int vpmadt032_getreg_full_return(struct vpmadt032 *vpm, int pagechange,
unsigned long ret;
BUG_ON(!cmd);
/* We'll wait for 2s */
ret = wait_for_completion_timeout(&cmd->complete, HZ*2);
/* We'll wait for 200ms */
ret = wait_for_completion_timeout(&cmd->complete, HZ/5);
if (unlikely(!ret)) {
spin_lock_irqsave(&vpm->list_lock, flags);
list_del(&cmd->node);

View File

@@ -0,0 +1,6 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

View File

@@ -2030,7 +2030,7 @@ static int __init voicebus_module_init(void)
* 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);
dahdi_register(NULL, 0);
spin_lock_init(&loader_list_lock);
return 0;
}

View File

@@ -57,15 +57,6 @@
* (and not tasklet). */
#define CONFIG_VOICEBUS_INTERRUPT
/*
* Enable the following definition in order to disable Active-State Power
* Management on the PCIe bridge for PCIe cards. This has been known to work
* around issues where the BIOS enables it on the cards even though the
* platform does not support it.
*
*/
#undef CONFIG_VOICEBUS_DISABLE_ASPM
/* Define this to use a FIFO for the software echocan reference.
* (experimental) */
#undef CONFIG_VOICEBUS_ECREFERENCE

View File

@@ -72,7 +72,7 @@ static int _vpmoct_read(struct vpmoct *vpm, u8 address,
list_del(&cmd->node);
spin_unlock_irqrestore(&vpm->list_lock, flags);
kfree(cmd);
dev_err(vpm->dev, "vpmoct_read_byte cmd timed out\n");
dev_err(vpm->dev, "vpmoct_read_byte cmd timed out :O(\n");
return 0;
}

View File

@@ -1,7 +1,7 @@
/*
* DAHDI Telephony Interface to VPMADT032 Firmware Loader
*
* Copyright (C) 2008-2012 Digium, Inc. All rights reserved.
* Copyright (C) 2008-2011 Digium, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -38,9 +38,18 @@ logger(const char *format, ...)
int res;
va_list args;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 9)
va_start(args, format);
res = vprintk(format, args);
va_end(args);
#else
char buf[256];
va_start(args, format);
res = vsnprintf(buf, sizeof(buf), format, args);
va_end(args);
printk(KERN_INFO "%s" buf);
#endif
return res;
}

View File

@@ -0,0 +1,7 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
else
endif

View File

@@ -2,7 +2,7 @@
* WCB410P Quad-BRI PCI Driver
* Written by Andrew Kohlsmith <akohlsmith@mixdown.ca>
*
* Copyright (C) 2009-2012 Digium, Inc.
* Copyright (C) 2009-2011 Digium, Inc.
* All rights reserved.
*
*/
@@ -90,7 +90,6 @@ static int milliwatt = 0;
static int pedanticpci = 0;
static int teignorered = 0;
static int alarmdebounce = 500;
static int persistentlayer1 = 1;
static int vpmsupport = 1;
static int timer_1_ms = 2000;
static int timer_3_ms = 30000;
@@ -140,7 +139,7 @@ static struct devtype hfc8s_BN = {"BeroNet BN8S0", .ports = 8, .card_type = BN8S
static struct devtype hfc4s_SW = {"Swyx 4xS0 SX2 QuadBri", .ports = 4, .card_type = BSWYX_SX2 };
static struct devtype hfc4s_EV = {"CCD HFC-4S Eval. Board", .ports = 4,
.card_type = QUADBRI_EVAL };
#define CARD_HAS_EC(card) ((card)->card_type == B410P)
static void echocan_free(struct dahdi_chan *chan, struct dahdi_echocan_state *ec);
@@ -1198,6 +1197,7 @@ static int b4xxp_find_sync(struct b4xxp *b4)
return src;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18))
static ssize_t b4_timing_master_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1225,6 +1225,13 @@ static void remove_sysfs_files(struct b4xxp *b4)
&dev_attr_timing_master);
}
#else
static inline void create_sysfs_files(struct b4xxp *b4) { return; }
static inline void remove_sysfs_files(struct b4xxp *b4) { return; }
#endif /* LINUX_KERNEL > 2.6.18 */
/*
* allocates memory and pretty-prints a given S/T state engine state to it.
* calling routine is responsible for freeing the pointer returned!
@@ -1295,9 +1302,6 @@ static void hfc_force_st_state(struct b4xxp *b4, int port, int state, int resume
hfc_handle_state(&b4->spans[port]);
}
static void hfc_stop_st(struct b4xxp_span *s);
static void hfc_start_st(struct b4xxp_span *s);
/* figures out what to do when an S/T port's timer expires. */
static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
{
@@ -1311,15 +1315,10 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
s->hfc_timer_on[t_no]);
}
/*
* There are four timers associated with every HFC S/T port:
* T1 is used by the NT state machine, and is the maximum time the NT side
* should wait for G3 (active) state.
* T2 is not actually used in the driver, it is handled by the HFC-4S
* internally.
* T3 is used by the TE state machine; it is the maximum time the TE side should
* wait for the INFO4 (activated) signal.
* T4 is a special timer used for debug purposes for monitoring of L1 state
* during activation attempt.
* there are three timers associated with every HFC S/T port.
* T1 is used by the NT state machine, and is the maximum time the NT side should wait for G3 (active) state.
* T2 is not actually used in the driver, it is handled by the HFC-4S internally.
* T3 is used by the TE state machine; it is the maximum time the TE side should wait for the INFO4 (activated) signal.
*/
/* First, disable the expired timer; hfc_force_st_state() may activate it again. */
@@ -1333,14 +1332,7 @@ static void hfc_timer_expire(struct b4xxp_span *s, int t_no)
hfc_force_st_state(b4, s->port, 1, 1);
break;
case HFC_T3: /* switch to F3 (deactivated), resume auto mode */
hfc_stop_st(s);
if (persistentlayer1)
hfc_start_st(s);
break;
case HFC_T4:
hfc_handle_state(s);
s->hfc_timers[HFC_T4] = b4->ticks + 1000;
s->hfc_timer_on[HFC_T4] = 1;
hfc_force_st_state(b4, s->port, 3, 1);
break;
default:
if (printk_ratelimit()) {
@@ -1363,9 +1355,9 @@ static void hfc_update_st_timers(struct b4xxp *b4)
for (i=0; i < b4->numspans; i++) {
s = &b4->spans[i];
for (j = HFC_T1; j < ARRAY_SIZE(s->hfc_timers); j++) {
/* we don't really do timer2, it is expired by the
* state change handler */
for (j=HFC_T1; j <= HFC_T3; j++) {
/* we don't really do timer2, it is expired by the state change handler */
if (j == HFC_T2)
continue;
@@ -1449,7 +1441,6 @@ static void hfc_handle_state(struct b4xxp_span *s)
break;
case 0x7: /* TE state F7: Activated */
s->hfc_timer_on[HFC_T3] = 0;
s->hfc_timer_on[HFC_T4] = 0;
s->newalarm = 0;
break;
}
@@ -1471,17 +1462,14 @@ static void hfc_handle_state(struct b4xxp_span *s)
/* If we're in F3 and receiving INFO0, start T3 and jump to F4 */
if (!nt && (sta == 3) && (state & V_INFO0)) {
if (persistentlayer1) {
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
s->hfc_timer_on[HFC_T3] = 1;
if (DBG_ST) {
dev_info(&b4->pdev->dev,
"port %d: receiving INFO0 in state 3, "
"setting T3 and jumping to F4\n",
s->port + 1);
}
hfc_start_st(s);
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
s->hfc_timer_on[HFC_T3] = 1;
if (DBG_ST) {
dev_info(&b4->pdev->dev,
"port %d: receiving INFO0 in state 3, "
"setting T3 and jumping to F4\n", s->port + 1);
}
hfc_force_st_state(b4, s->port, 4, 1);
}
/* read in R_BERT_STA to determine where our current sync source is */
@@ -1496,24 +1484,6 @@ static void hfc_handle_state(struct b4xxp_span *s)
}
}
static void hfc_stop_all_timers(struct b4xxp_span *s)
{
s->hfc_timer_on[HFC_T4] = 0;
s->hfc_timer_on[HFC_T3] = 0;
s->hfc_timer_on[HFC_T2] = 0;
s->hfc_timer_on[HFC_T1] = 0;
}
static void hfc_stop_st(struct b4xxp_span *s)
{
struct b4xxp *b4 = s->parent;
hfc_stop_all_timers(s);
b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA,
V_ST_ACT_DEACTIVATE);
}
/*
* resets an S/T interface to a given NT/TE mode
*/
@@ -1524,16 +1494,10 @@ static void hfc_reset_st(struct b4xxp_span *s)
b4 = s->parent;
hfc_stop_st(s);
/* force state G0/F0 (reset), then force state 1/2 (deactivated/sensing) */
b4xxp_setreg_ra(b4, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_LD_STA);
flush_pci(); /* make sure write hit hardware */
s->span.alarms = DAHDI_ALARM_RED;
s->newalarm = DAHDI_ALARM_RED;
dahdi_alarm_notify(&s->span);
udelay(10);
/* set up the clock control register. Must be done before we activate the interface. */
@@ -1564,13 +1528,9 @@ static void hfc_start_st(struct b4xxp_span *s)
/* start T1 if in NT mode, T3 if in TE mode */
if (s->te_mode) {
s->hfc_timers[HFC_T3] = b4->ticks + timer_3_ms;
s->hfc_timers[HFC_T3] = b4->ticks + 500; /* 500ms wait first time, timer_t3_ms afterward. */
s->hfc_timer_on[HFC_T3] = 1;
s->hfc_timer_on[HFC_T1] = 0;
s->hfc_timers[HFC_T4] = b4->ticks + 1000;
s->hfc_timer_on[HFC_T4] = 1;
if (DBG_ST) {
dev_info(&b4->pdev->dev,
"setting port %d t3 timer to %lu\n",
@@ -1588,6 +1548,17 @@ static void hfc_start_st(struct b4xxp_span *s)
}
}
#if 0 /* TODO: This function is not called anywhere */
static void hfc_stop_st(struct b4xxp_span *s)
{
b4xxp_setreg_ra(s->parent, R_ST_SEL, s->port, A_ST_WR_STA, V_ST_ACT_DEACTIVATE);
s->hfc_timer_on[HFC_T1] = 0;
s->hfc_timer_on[HFC_T2] = 0;
s->hfc_timer_on[HFC_T3] = 0;
}
#endif
/*
* read in the HFC GPIO to determine each port's mode (TE or NT).
* Then, reset and start the port.
@@ -1620,6 +1591,8 @@ static void hfc_init_all_st(struct b4xxp *b4)
dev_info(&b4->pdev->dev,
"Port %d: %s mode\n", i + 1, (nt ? "NT" : "TE"));
hfc_reset_st(s);
hfc_start_st(s);
}
}
@@ -1876,10 +1849,10 @@ static int hdlc_tx_frame(struct b4xxp_span *bspan)
char debugbuf[256];
unsigned long irq_flags;
/* if we're ignoring TE red alarms and we are in alarm, restart the
* S/T state machine */
if (bspan->te_mode && bspan->newalarm != 0)
hfc_start_st(bspan);
/* if we're ignoring TE red alarms and we are in alarm, restart the S/T state machine */
if (bspan->te_mode && teignorered && bspan->newalarm == DAHDI_ALARM_RED) {
hfc_force_st_state(b4, bspan->port, 3, 1);
}
fifo = bspan->fifos[2];
res = dahdi_hdlc_getbuf(bspan->sigchan, buf, &size);
@@ -2367,10 +2340,6 @@ static int b4xxp_spanconfig(struct file *file, struct dahdi_span *span,
if (lc->sync)
b4->spans[lc->sync - 1].sync = (span->offset + 1);
hfc_reset_st(bspan);
if (persistentlayer1)
hfc_start_st(bspan);
b4xxp_reset_span(bspan);
/* call startup() manually here, because DAHDI won't call the startup function unless it receives an IOCTL to do so, and dahdi_cfg doesn't. */
@@ -2505,9 +2474,8 @@ static void init_spans(struct b4xxp *b4)
bspan = &b4->spans[i];
bspan->parent = b4;
bspan->span.spantype = (bspan->te_mode)
? SPANTYPE_DIGITAL_BRI_TE
: SPANTYPE_DIGITAL_BRI_NT;
bspan->span.irq = b4->pdev->irq;
bspan->span.spantype = (bspan->te_mode) ? "TE" : "NT";
bspan->span.offset = i;
bspan->span.channels = WCB4XXP_CHANNELS_PER_SPAN;
bspan->span.flags = 0;
@@ -2525,6 +2493,11 @@ static void init_spans(struct b4xxp *b4)
sprintf(bspan->span.name, "B4/%d/%d", b4->cardno, i+1);
sprintf(bspan->span.desc, "B4XXP (PCI) Card %d Span %d", b4->cardno, i+1);
bspan->span.manufacturer = "Digium";
strlcpy(bspan->span.devicetype, b4->variety,
sizeof(bspan->span.devicetype));
sprintf(bspan->span.location, "PCI Bus %02d Slot %02d",
b4->pdev->bus->number, PCI_SLOT(b4->pdev->devfn) + 1);
bspan->span.ops = &b4xxp_span_ops;
/* HDLC stuff */
@@ -2956,27 +2929,14 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
hfc_init_all_st(b4);
/* initialize the DAHDI structures, and let DAHDI know it has some new hardware to play with */
b4->ddev = dahdi_create_device();
init_spans(b4);
for (x=0; x < b4->numspans; x++) {
struct dahdi_span *const s = &b4->spans[x].span;
list_add_tail(&s->device_node, &b4->ddev->spans);
}
b4->ddev->manufacturer = "Digium";
b4->ddev->devicetype = b4->variety;
b4->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
b4->pdev->bus->number,
PCI_SLOT(b4->pdev->devfn) + 1);
if (!b4->ddev->location) {
ret = -ENOMEM;
goto err_out_del_from_card_array;
}
if (dahdi_register_device(b4->ddev, &b4->pdev->dev)) {
dev_err(&b4->pdev->dev, "Unable to register device.\n");
goto err_out_unreg_spans;
if (dahdi_register(&b4->spans[x].span, 0)) {
dev_err(&b4->pdev->dev,
"Unable to register span %s\n",
b4->spans[x].span.name);
goto err_out_unreg_spans;
}
}
@@ -3012,7 +2972,10 @@ static int __devinit b4xx_probe(struct pci_dev *pdev, const struct pci_device_id
/* 'x' will have the failing span #. (0-3). We need to unregister everything before it. */
err_out_unreg_spans:
dahdi_unregister_device(b4->ddev);
while (x) {
dahdi_unregister(&b4->spans[x].span);
x--;
};
b4xxp_init_stage1(b4); /* full reset, re-init to "no-irq" state */
free_irq(pdev->irq, b4);
@@ -3033,8 +2996,6 @@ err_out_free_mem:
pci_set_drvdata(pdev, NULL);
pci_iounmap(pdev, b4->ioaddr);
pci_iounmap(pdev, b4->addr);
kfree(b4->ddev->location);
dahdi_free_device(b4->ddev);
kfree(b4);
err_out_release_regions:
@@ -3049,11 +3010,14 @@ err_out_disable_pdev:
static void __devexit b4xxp_remove(struct pci_dev *pdev)
{
struct b4xxp *b4 = pci_get_drvdata(pdev);
int i;
if (b4) {
b4->shutdown = 1;
dahdi_unregister_device(b4->ddev);
for (i=b4->numspans - 1; i >= 0; i--) {
dahdi_unregister(&b4->spans[i].span);
}
b4xxp_init_stage1(b4);
remove_sysfs_files(b4);
@@ -3068,8 +3032,6 @@ static void __devexit b4xxp_remove(struct pci_dev *pdev)
tasklet_kill(&b4->b4xxp_tlet);
kfree(b4->ddev->location);
dahdi_free_device(b4->ddev);
kfree(b4);
}
@@ -3151,7 +3113,6 @@ module_param(vpmsupport, int, S_IRUGO);
module_param(timer_1_ms, int, S_IRUGO | S_IWUSR);
module_param(timer_3_ms, int, S_IRUGO | S_IWUSR);
module_param(companding, charp, S_IRUGO);
module_param(persistentlayer1, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "bitmap: 1=general 2=dtmf 4=regops 8=fops 16=ec 32=st state 64=hdlc 128=alarm");
MODULE_PARM_DESC(spanfilter, "debug filter for spans. bitmap: 1=port 1, 2=port 2, 4=port 3, 8=port 4");

View File

@@ -376,7 +376,6 @@
#define HFC_T1 0
#define HFC_T2 1
#define HFC_T3 2
#define HFC_T4 3
#define MAX_SPANS_PER_CARD 8
@@ -397,8 +396,8 @@ struct b4xxp_span {
unsigned long alarmtimer;
int te_mode; /* 1=TE, 0=NT */
unsigned long hfc_timers[4]; /* T1, T2, T3, Fake T4 */
int hfc_timer_on[4]; /* 1=timer active */
unsigned long hfc_timers[WCB4XXP_CHANNELS_PER_SPAN]; /* T1, T2, T3 */
int hfc_timer_on[WCB4XXP_CHANNELS_PER_SPAN]; /* 1=timer active */
int fifos[WCB4XXP_CHANNELS_PER_SPAN]; /* B1, B2, D <--> host fifo numbers */
/* HDLC controller fields */
@@ -475,7 +474,6 @@ struct b4xxp {
/* Flags for our bottom half */
unsigned int shutdown; /* 1=bottom half doesn't process anything, just returns */
struct tasklet_struct b4xxp_tlet;
struct dahdi_device *ddev;
};
/* CPLD access bits */

View File

@@ -135,7 +135,6 @@ static int wecareregs[] =
struct wcfxo {
struct pci_dev *dev;
char *variety;
struct dahdi_device *ddev;
struct dahdi_span span;
struct dahdi_chan _chan;
struct dahdi_chan *chan;
@@ -648,24 +647,19 @@ static const struct dahdi_span_ops wcfxo_span_ops = {
static int wcfxo_initialize(struct wcfxo *wc)
{
wc->ddev = dahdi_create_device();
/* DAHDI stuff */
sprintf(wc->span.name, "WCFXO/%d", wc->pos);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
sprintf(wc->chan->name, "WCFXO/%d/%d", wc->pos, 0);
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
wc->dev->bus->number,
PCI_SLOT(wc->dev->devfn) + 1);
if (!wc->ddev->location)
return -ENOMEM;
wc->ddev->manufacturer = "Digium";
wc->ddev->devicetype = wc->variety;
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
wc->span.manufacturer = "Digium";
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
wc->chan->sigcap = DAHDI_SIG_FXSKS | DAHDI_SIG_FXSLS | DAHDI_SIG_SF;
wc->chan->chanpos = 1;
wc->span.chans = &wc->chan;
wc->span.channels = 1;
wc->span.irq = wc->dev->irq;
wc->span.flags = DAHDI_FLAG_RBS;
wc->span.deflaw = DAHDI_LAW_MULAW;
#ifdef ENABLE_TASKLETS
@@ -674,8 +668,7 @@ static int wcfxo_initialize(struct wcfxo *wc)
wc->chan->pvt = wc;
wc->span.ops = &wcfxo_span_ops;
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
if (dahdi_register(&wc->span, 0)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
@@ -983,7 +976,7 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
printk(KERN_NOTICE "Failed to initailize DAA, giving up...\n");
wcfxo_stop_dma(wc);
wcfxo_disable_interrupts(wc);
dahdi_unregister_device(wc->ddev);
dahdi_unregister(&wc->span);
free_irq(pdev->irq, wc);
/* Reset PCI chip and registers */
@@ -991,8 +984,6 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
if (wc->freeregion)
release_region(wc->ioaddr, 0xff);
kfree(wc->ddev->location);
dahdi_free_device(wc->ddev);
kfree(wc);
return -EIO;
}
@@ -1004,11 +995,9 @@ static int __devinit wcfxo_init_one(struct pci_dev *pdev, const struct pci_devic
static void wcfxo_release(struct wcfxo *wc)
{
dahdi_unregister_device(wc->ddev);
dahdi_unregister(&wc->span);
if (wc->freeregion)
release_region(wc->ioaddr, 0xff);
kfree(wc->ddev->location);
dahdi_free_device(wc->ddev);
kfree(wc);
printk(KERN_INFO "Freed a Wildcard\n");
}

View File

@@ -159,7 +159,6 @@ struct t1xxp {
unsigned char ec_chunk2[31][DAHDI_CHUNKSIZE];
unsigned char tempo[32];
struct dahdi_span span; /* Span */
struct dahdi_device *ddev;
struct dahdi_chan *chans[31]; /* Channels */
};
@@ -273,11 +272,10 @@ static void t1xxp_release(struct t1xxp *wc)
{
unsigned int x;
dahdi_unregister_device(wc->ddev);
dahdi_unregister(&wc->span);
for (x = 0; x < (wc->ise1 ? 31 : 24); x++) {
kfree(wc->chans[x]);
}
dahdi_free_device(wc->ddev);
kfree(wc);
printk(KERN_INFO "Freed a Wildcard\n");
}
@@ -772,32 +770,26 @@ static int t1xxp_software_init(struct t1xxp *wc)
}
if (x >= WC_MAX_CARDS)
return -1;
wc->ddev = dahdi_create_device();
wc->num = x;
sprintf(wc->span.name, "WCT1/%d", wc->num);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
wc->ddev->manufacturer = "Digium";
wc->ddev->devicetype = wc->variety;
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
wc->dev->bus->number,
PCI_SLOT(wc->dev->devfn) + 1);
if (!wc->ddev->location)
return -ENOMEM;
wc->span.manufacturer = "Digium";
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
wc->span.irq = wc->dev->irq;
wc->span.chans = wc->chans;
wc->span.flags = DAHDI_FLAG_RBS;
if (wc->ise1) {
wc->span.channels = 31;
wc->span.deflaw = DAHDI_LAW_ALAW;
wc->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
wc->span.spantype = SPANTYPE_DIGITAL_E1;
wc->span.spantype = "E1";
} else {
wc->span.channels = 24;
wc->span.deflaw = DAHDI_LAW_MULAW;
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
wc->span.spantype = SPANTYPE_DIGITAL_T1;
wc->span.spantype = "T1";
}
for (x=0;x<wc->span.channels;x++) {
sprintf(wc->chans[x]->name, "WCT1/%d/%d", wc->num, x + 1);
@@ -809,8 +801,7 @@ static int t1xxp_software_init(struct t1xxp *wc)
wc->chans[x]->chanpos = x + 1;
}
wc->span.ops = &t1xxp_span_ops;
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
if (dahdi_register(&wc->span, 0)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
@@ -917,10 +908,10 @@ static void t1xxp_receiveprep(struct t1xxp *wc, int ints)
if (((oldcan & 0xffff0000) >> 16) != CANARY) {
/* Check top part */
if (debug) printk(KERN_DEBUG "Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16);
wc->ddev->irqmisses++;
wc->span.irqmisses++;
} else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) {
if (debug) printk(KERN_DEBUG "Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff);
wc->ddev->irqmisses++;
wc->span.irqmisses++;
}
for (y=0;y<DAHDI_CHUNKSIZE;y++) {
for (x=0;x<wc->span.channels;x++) {

View File

@@ -17,7 +17,7 @@ endif
wct4xxp-objs := base.o vpm450m.o $(shell $(src)/../oct612x/octasic-helper objects ../oct612x)
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
wct4xxp-objs += $(FIRM_DIR)/dahdi-fw-oct6114-064.o $(FIRM_DIR)/dahdi-fw-oct6114-128.o
$(warning WARNING: You are compiling firmware into wct4xxp.ko which is not available under the terms of the GPL. It may be a violation of the GPL to distribute the resulting image since it combines both GPL and non-GPL work. You should consult a lawyer of your own before distributing such an image.)
endif
@@ -26,6 +26,3 @@ $(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-064.o: $(obj)/base.o
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-128.o: $(obj)/base.o
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-128.o
$(obj)/$(FIRM_DIR)/dahdi-fw-oct6114-256.o: $(obj)/base.o
$(MAKE) -C $(obj)/$(FIRM_DIR) dahdi-fw-oct6114-256.o

View File

@@ -0,0 +1,8 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
else
endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2005-2012 Digium, Inc.
* Copyright (C) 2005-2006 Digium, Inc.
*
* Mark Spencer <markster@digium.com>
*
@@ -28,6 +28,10 @@
#include "vpm450m.h"
#include "oct6100api/oct6100_api.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <linux/config.h>
#endif
/* API for Octasic access */
UINT32 Oct6100UserGetTime(tPOCT6100_GET_TIME f_pTime)
{
@@ -168,9 +172,9 @@ UINT32 Oct6100UserDriverReadBurstApi(tPOCT6100_READ_BURST_PARAMS f_pBurstParams)
struct vpm450m {
tPOCT6100_INSTANCE_API pApiInstance;
UINT32 aulEchoChanHndl[256];
int chanflags[256];
int ecmode[256];
UINT32 aulEchoChanHndl[128];
int chanflags[128];
int ecmode[128];
int numchans;
};
@@ -418,8 +422,6 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
tOCT6100_GET_INSTANCE_SIZE InstanceSize;
tOCT6100_CHANNEL_OPEN *ChannelOpen;
UINT32 ulResult;
const unsigned int mask = (8 == numspans) ? 0x7 : 0x3;
unsigned int sout_stream, rout_stream;
struct vpm450m *vpm450m;
int x,y,law;
@@ -465,22 +467,15 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
ChipOpen->ulMemoryType = cOCT6100_MEM_TYPE_DDR;
ChipOpen->ulMemoryChipSize = cOCT6100_MEMORY_CHIP_SIZE_32MB;
ChipOpen->ulNumMemoryChips = 1;
ChipOpen->ulMaxTdmStreams = 4;
ChipOpen->aulTdmStreamFreqs[0] = cOCT6100_TDM_STREAM_FREQ_8MHZ;
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
ChipOpen->ulMaxFlexibleConfParticipants = 0;
ChipOpen->ulMaxConfBridges = 0;
ChipOpen->ulMaxRemoteDebugSessions = 0;
ChipOpen->fEnableChannelRecording = FALSE;
ChipOpen->ulSoftToneEventsBufSize = 64;
if (vpm450m->numchans <= 128) {
ChipOpen->ulMaxTdmStreams = 4;
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_FALLING_EDGE;
} else {
ChipOpen->ulMaxTdmStreams = 32;
ChipOpen->fEnableFastH100Mode = TRUE;
ChipOpen->ulTdmSampling = cOCT6100_TDM_SAMPLE_AT_RISING_EDGE;
}
#if 0
ChipOpen->fEnableAcousticEcho = TRUE;
#endif
@@ -512,11 +507,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
kfree(ChannelOpen);
return NULL;
}
sout_stream = (8 == numspans) ? 29 : 2;
rout_stream = (8 == numspans) ? 24 : 3;
for (x = 0; x < ((8 == numspans) ? 256 : 128); x++) {
for (x = 0; x < ARRAY_SIZE(vpm450m->aulEchoChanHndl); x++) {
/* execute this loop always on 4 span cards but
* on 2 span cards only execute for the channels related to our spans */
if (( numspans > 2) || ((x & 0x03) <2)) {
@@ -524,7 +515,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
* therefore, the lower 2 bits tell us which span this
* timeslot/channel
*/
if (isalaw[x & mask])
if (isalaw[x & 0x03])
law = cOCT6100_PCM_A_LAW;
else
law = cOCT6100_PCM_U_LAW;
@@ -538,13 +529,11 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
ChannelOpen->TdmConfig.ulSinStream = 1;
ChannelOpen->TdmConfig.ulSinTimeslot = x;
ChannelOpen->TdmConfig.ulSoutPcmLaw = law;
ChannelOpen->TdmConfig.ulSoutStream = sout_stream;
ChannelOpen->TdmConfig.ulSoutStream = 2;
ChannelOpen->TdmConfig.ulSoutTimeslot = x;
#if 1
ChannelOpen->TdmConfig.ulRoutPcmLaw = law;
ChannelOpen->TdmConfig.ulRoutStream = rout_stream;
ChannelOpen->TdmConfig.ulRoutStream = 3;
ChannelOpen->TdmConfig.ulRoutTimeslot = x;
#endif
ChannelOpen->VqeConfig.fEnableNlp = TRUE;
ChannelOpen->VqeConfig.fRinDcOffsetRemoval = TRUE;
ChannelOpen->VqeConfig.fSinDcOffsetRemoval = TRUE;
@@ -554,7 +543,7 @@ struct vpm450m *init_vpm450m(void *wc, int *isalaw, int numspans, const struct f
ulResult = Oct6100ChannelOpen(vpm450m->pApiInstance, ChannelOpen);
if (ulResult != GENERIC_OK) {
printk(KERN_NOTICE "Failed to open channel %d %x!\n", x, ulResult);
printk(KERN_NOTICE "Failed to open channel %d!\n", x);
continue;
}
for (y = 0; y < ARRAY_SIZE(tones); y++) {

View File

@@ -54,12 +54,6 @@
#define FRMR_SIC3 0x40
#define FRMR_CMR1 0x44
#define FRMR_CMR2 0x45
/* OctalFALC Only */
#define FRMR_CMR4 0x41
#define FRMR_CMR5 0x42
#define FRMR_CMR6 0x43
#define FRMR_GPC2 0x8a
/* End Octal */
#define FRMR_GCR 0x46
#define FRMR_ISR0 0x68
#define FRMR_ISR0_RME 0x80
@@ -82,13 +76,6 @@
#define FRMR_CIS_GIS2 0x02
#define FRMR_CIS_GIS3 0x04
#define FRMR_CIS_GIS4 0x08
/* CIS - Octal falc bits */
#define FRMR_CIS_GIS5 0x10
#define FRMR_CIS_GIS6 0x20
#define FRMR_CIS_GIS7 0x40
#define FRMR_CIS_GIS8 0x80
#define FRMR_CMDR 0x02
#define FRMR_CMDR_SRES 0x01
#define FRMR_CMDR_XRES 0x10
@@ -126,11 +113,6 @@ struct t4_regs {
unsigned char regs[NUM_REGS];
};
struct t4_reg {
unsigned int reg;
unsigned int val;
};
#define T4_CHECK_VPM 0
#define T4_LOADING_FW 1
#define T4_STOP_DMA 2
@@ -138,7 +120,5 @@ struct t4_reg {
#define T4_CHANGE_LATENCY 4
#define T4_IGNORE_LATENCY 5
#define WCT4_GET_REGS _IOW(DAHDI_CODE, 60, struct t4_regs)
#define WCT4_GET_REG _IOW(DAHDI_CODE, 61, struct t4_reg)
#define WCT4_SET_REG _IOW(DAHDI_CODE, 62, struct t4_reg)
#define WCT4_GET_REGS _IOW (DAHDI_CODE, 60, struct t4_regs)

View File

@@ -0,0 +1,7 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
else
endif

View File

@@ -1,6 +1,6 @@
/* Wildcard TC400B Driver
*
* Copyright (C) 2006-2012, Digium, Inc.
* Copyright (C) 2006-2010, Digium, Inc.
*
* All rights reserved.
*
@@ -42,7 +42,11 @@
#include "dahdi/kernel.h"
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
#include <asm/io.h>
#else
#include <linux/io.h>
#endif
/* COMPILE TIME OPTIONS =================================================== */
@@ -69,6 +73,13 @@
dev_info(&(wc)->pdev->dev, _fmt, ## _args); \
} \
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
/* also added in RHEL kernels with the OpenInfiniband backport: */
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 9) || !defined(DEFINE_SPINLOCK)
typedef unsigned gfp_t; /* Added in 2.6.14 */
#endif
#endif
/* define CONFIG_WCTC4XXP_POLLING to operate in a pure polling mode. This is
* was placed in as a debugging tool for a particluar system that wasn't

View File

@@ -205,7 +205,6 @@ struct wctdm {
struct pci_dev *dev;
char *variety;
struct dahdi_span span;
struct dahdi_device *ddev;
unsigned char ios;
int usecount;
unsigned int intcount;
@@ -2363,26 +2362,13 @@ static int wctdm_initialize(struct wctdm *wc)
{
int x;
wc->ddev = dahdi_create_device();
if (!wc->ddev)
return -ENOMEM;
/* DAHDI stuff */
sprintf(wc->span.name, "WCTDM/%d", wc->pos);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Board %d", wc->variety, wc->pos + 1);
wc->ddev->location = kasprintf(GFP_KERNEL,
"PCI Bus %02d Slot %02d",
wc->dev->bus->number,
PCI_SLOT(wc->dev->devfn) + 1);
if (!wc->ddev->location) {
dahdi_free_device(wc->ddev);
wc->ddev = NULL;
return -ENOMEM;
}
wc->ddev->manufacturer = "Digium";
wc->ddev->devicetype = wc->variety;
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
wc->span.manufacturer = "Digium";
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
if (alawoverride) {
printk(KERN_INFO "ALAW override parameter detected. Device will be operating in ALAW\n");
wc->span.deflaw = DAHDI_LAW_ALAW;
@@ -2398,15 +2384,12 @@ static int wctdm_initialize(struct wctdm *wc)
}
wc->span.chans = wc->chans;
wc->span.channels = NUM_CARDS;
wc->span.irq = wc->dev->irq;
wc->span.flags = DAHDI_FLAG_RBS;
wc->span.ops = &wctdm_span_ops;
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
if (dahdi_register(&wc->span, 0)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
kfree(wc->ddev->location);
dahdi_free_device(wc->ddev);
wc->ddev = NULL;
return -1;
}
return 0;
@@ -2694,9 +2677,7 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
release_region(wc->ioaddr, 0xff);
pci_free_consistent(pdev, DAHDI_MAX_CHUNKSIZE * 2 * 2 * 2 * 4, (void *)wc->writechunk, wc->writedma);
pci_set_drvdata(pdev, NULL);
dahdi_unregister_device(wc->ddev);
kfree(wc->ddev->location);
dahdi_free_device(wc->ddev);
dahdi_unregister(&wc->span);
kfree(wc);
return -EIO;
@@ -2727,14 +2708,10 @@ static int __devinit wctdm_init_one(struct pci_dev *pdev, const struct pci_devic
static void wctdm_release(struct wctdm *wc)
{
dahdi_unregister_device(wc->ddev);
dahdi_unregister(&wc->span);
if (wc->freeregion)
release_region(wc->ioaddr, 0xff);
kfree(wc->ddev->location);
dahdi_free_device(wc->ddev);
kfree(wc);
printk(KERN_INFO "Freed a Wildcard\n");
}

View File

@@ -0,0 +1,6 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

File diff suppressed because it is too large Load Diff

View File

@@ -45,6 +45,7 @@
* \brief Default ringer debounce (in ms)
*/
#define DEFAULT_RING_DEBOUNCE 1024
#define POLARITY_DEBOUNCE 64 /* Polarity debounce (in ms) */
#define OHT_TIMER 6000 /* How long after RING to retain OHT */
@@ -84,6 +85,7 @@
#define NUM_CAL_REGS 12
#define ISR_COMMANDS 2
#define QRV_DEBOUNCETIME 20
#define VPM150M_HPI_CONTROL 0x00
@@ -105,30 +107,10 @@ struct calregs {
enum battery_state {
BATTERY_UNKNOWN = 0,
BATTERY_DEBOUNCING_PRESENT,
BATTERY_DEBOUNCING_PRESENT_ALARM,
BATTERY_PRESENT,
BATTERY_DEBOUNCING_LOST,
BATTERY_DEBOUNCING_LOST_ALARM,
BATTERY_LOST,
};
enum ring_detector_state {
RINGOFF = 0,
DEBOUNCING_RINGING_POSITIVE,
DEBOUNCING_RINGING_NEGATIVE,
RINGING,
DEBOUNCING_RINGOFF,
};
enum polarity_state {
UNKNOWN_POLARITY = 0,
POLARITY_DEBOUNCE_POSITIVE,
POLARITY_POSITIVE,
POLARITY_DEBOUNCE_NEGATIVE,
POLARITY_NEGATIVE,
};
struct wctdm_cmd {
struct list_head node;
struct completion *complete;
@@ -164,26 +146,29 @@ struct wctdm_chan {
};
struct fxo {
enum ring_detector_state ring_state:4;
enum battery_state battery_state:4;
enum polarity_state polarity_state:4;
u8 ring_polarity_change_count:4;
u8 hook_ring_shadow;
s8 line_voltage_status;
int wasringing;
int lastrdtx;
int lastrdtx_count;
int ringdebounce;
int offhook;
int battdebounce;
int battalarm;
enum battery_state battery;
int lastpol;
int polarity;
int polaritydebounce;
int neonmwi_state;
int neonmwi_last_voltage;
unsigned int neonmwi_debounce;
unsigned int neonmwi_offcounter;
unsigned long display_fxovoltage;
unsigned long ringdebounce_timer;
unsigned long battdebounce_timer;
unsigned long poldebounce_timer;
};
struct fxs {
u8 oht_active:1;
u8 off_hook:1;
int oldrxhook;
int debouncehook;
int lastrxhook;
int debounce;
int ohttimer;
int idletxhookstate; /* IDLE changing hook state */
/* lasttxhook reflects the last value written to the proslic's reg
* 64 (LINEFEED_CONTROL) in bits 0-2. Bit 4 indicates if the last
@@ -195,18 +180,13 @@ struct fxs {
* voicebus ISR.
*/
int lasttxhook;
u8 linefeed_control_shadow;
u8 hook_state_shadow;
int oppending_ms;
int palarms;
struct dahdi_vmwi_info vmwisetting;
int vmwi_active_messages;
int vmwi_linereverse;
int reversepolarity; /* polarity reversal */
struct calregs calregs;
unsigned long check_alarm;
unsigned long check_proslic;
unsigned long oppending_timeout;
unsigned long ohttimer;
};
struct qrv {
@@ -223,7 +203,6 @@ struct qrv {
int radmode;
signed short rxgain;
signed short txgain;
u8 isrshadow[3];
};
enum module_type {
@@ -236,7 +215,7 @@ enum module_type {
};
struct wctdm_module {
union modtypes {
union {
struct fxo fxo;
struct fxs fxs;
struct qrv qrv;
@@ -248,6 +227,7 @@ struct wctdm_module {
struct list_head active_cmds;
u8 offsets[3];
u8 subaddr;
u8 isrshadow[ISR_COMMANDS];
u8 card;
enum module_type type;
@@ -262,7 +242,7 @@ struct wctdm {
spinlock_t frame_list_lock;
struct list_head frame_list;
unsigned long framecount;
unsigned int intcount;
unsigned char txident;
unsigned char rxident;
@@ -297,7 +277,6 @@ struct wctdm {
int not_ready; /* 0 when the entire card is ready to go */
unsigned long checkflag; /* Internal state flags and task bits */
int companding;
struct dahdi_device *ddev;
};
static inline bool is_initialized(struct wctdm *wc)

View File

@@ -2150,9 +2150,7 @@ static int b400m_set_ntte(struct b400m_span *bspan, int te_mode, int term_on)
int all_modes = 0, all_terms = 0;
int i;
bspan->wspan->span.spantype = (te_mode > 0)
? SPANTYPE_DIGITAL_BRI_TE
: SPANTYPE_DIGITAL_BRI_NT;
bspan->wspan->span.spantype = (te_mode > 0) ? "TE" : "NT";
bspan->te_mode = te_mode;
bspan->term_on = term_on;

View File

@@ -174,7 +174,6 @@ struct t1 {
unsigned char ec_chunk1[32][DAHDI_CHUNKSIZE];
unsigned char ec_chunk2[32][DAHDI_CHUNKSIZE];
unsigned char tempo[33];
struct dahdi_device *ddev;
struct dahdi_span span; /* Span */
struct dahdi_chan *chans[32]; /* Channels */
};
@@ -341,12 +340,10 @@ static void t1xxp_release(struct t1 *wc)
{
unsigned int x;
dahdi_unregister_device(wc->ddev);
dahdi_unregister(&wc->span);
for (x = 0; x < (wc->spantype == TYPE_E1 ? 31 : 24); x++) {
kfree(wc->chans[x]);
}
kfree(wc->ddev->location);
dahdi_free_device(wc->ddev);
kfree(wc);
printk(KERN_INFO "Freed a Wildcard\n");
}
@@ -979,33 +976,27 @@ static int t1xxp_software_init(struct t1 *wc)
}
if (x >= WC_MAX_CARDS)
return -1;
wc->ddev = dahdi_create_device();
t4_serial_setup(wc);
wc->num = x;
sprintf(wc->span.name, "WCT1/%d", wc->num);
snprintf(wc->span.desc, sizeof(wc->span.desc) - 1, "%s Card %d", wc->variety, wc->num);
wc->ddev->manufacturer = "Digium";
wc->ddev->devicetype = wc->variety;
wc->ddev->location = kasprintf(GFP_KERNEL, "PCI Bus %02d Slot %02d",
wc->dev->bus->number,
PCI_SLOT(wc->dev->devfn) + 1);
if (!wc->ddev->location)
return -ENOMEM;
wc->span.manufacturer = "Digium";
strlcpy(wc->span.devicetype, wc->variety, sizeof(wc->span.devicetype));
snprintf(wc->span.location, sizeof(wc->span.location) - 1,
"PCI Bus %02d Slot %02d", wc->dev->bus->number, PCI_SLOT(wc->dev->devfn) + 1);
wc->span.irq = wc->dev->irq;
if (wc->spantype == TYPE_E1) {
if (unchannelized)
wc->span.channels = 32;
else
wc->span.channels = 31;
wc->span.deflaw = DAHDI_LAW_ALAW;
wc->span.spantype = SPANTYPE_DIGITAL_E1;
wc->span.spantype = "E1";
wc->span.linecompat = DAHDI_CONFIG_HDB3 | DAHDI_CONFIG_CCS | DAHDI_CONFIG_CRC4;
} else {
wc->span.channels = 24;
wc->span.deflaw = DAHDI_LAW_MULAW;
wc->span.spantype = SPANTYPE_DIGITAL_T1;
wc->span.spantype = "T1";
wc->span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_B8ZS | DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF;
}
wc->span.chans = wc->chans;
@@ -1020,8 +1011,7 @@ static int t1xxp_software_init(struct t1 *wc)
wc->chans[x]->chanpos = x + 1;
}
wc->span.ops = &t1xxp_span_ops;
list_add_tail(&wc->span.device_node, &wc->ddev->spans);
if (dahdi_register_device(wc->ddev, &wc->dev->dev)) {
if (dahdi_register(&wc->span, 0)) {
printk(KERN_NOTICE "Unable to register span with DAHDI\n");
return -1;
}
@@ -1128,10 +1118,10 @@ static void t1xxp_receiveprep(struct t1 *wc, int ints)
if (((oldcan & 0xffff0000) >> 16) != CANARY) {
/* Check top part */
if (debug) printk(KERN_DEBUG "Expecting top %04x, got %04x\n", CANARY, (oldcan & 0xffff0000) >> 16);
wc->ddev->irqmisses++;
wc->span.irqmisses++;
} else if ((oldcan & 0xffff) != ((wc->canary - 1) & 0xffff)) {
if (debug) printk(KERN_DEBUG "Expecting bottom %d, got %d\n", wc->canary - 1, oldcan & 0xffff);
wc->ddev->irqmisses++;
wc->span.irqmisses++;
}
for (y=0;y<DAHDI_CHUNKSIZE;y++) {
for (x=0;x<wc->span.channels;x++) {

View File

@@ -0,0 +1,6 @@
ifdef KBUILD_EXTMOD
# We only get here on kernels 2.6.0-2.6.9 .
# For newer kernels, Kbuild will be included directly by the kernel
# build system.
include $(src)/Kbuild
endif

File diff suppressed because it is too large Load Diff

View File

@@ -74,11 +74,8 @@
#define CMD_BYTE(slot, a, is_vpm) (slot*6)+(a*2)+is_vpm /* only even slots */
//TODO: make a separate macro
enum linemode {
T1 = 1,
E1,
J1,
};
#define TYPE_T1 1
#define TYPE_E1 2
struct command {
struct list_head node;
@@ -97,6 +94,7 @@ struct t1 {
unsigned char txident;
unsigned char rxident;
unsigned char statreg; /* bit 0 = vpmadt032 int */
int spantype;
struct {
unsigned int nmf:1;
unsigned int sendingyellow:1;
@@ -118,7 +116,6 @@ struct t1 {
unsigned long alarmtimer;
unsigned char ledstate;
unsigned char vpm_check_count;
struct dahdi_device *ddev;
struct dahdi_span span; /* Span */
struct dahdi_chan *chans[32]; /* Channels */
struct dahdi_echocan_state *ec[32]; /* Echocan state for channels */

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,7 @@
#include "xpd.h"
enum bri_opcodes {
XPROTO_NAME(BRI, SET_LED) = 0x33,
XPROTO_NAME(BRI, SET_LED) = 0x33,
};
#endif /* CARD_BRI_H */
#endif /* CARD_BRI_H */

View File

@@ -42,20 +42,25 @@ static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
static bool echo_packet_is_valid(xpacket_t *pack);
static void echo_packet_dump(const char *msg, xpacket_t *pack);
DEF_RPACKET_DATA(ECHO, SET, __u8 timeslots[ECHO_TIMESLOTS];);
DEF_RPACKET_DATA(ECHO, SET,
byte timeslots[ECHO_TIMESLOTS];
);
DEF_RPACKET_DATA(ECHO, SET_REPLY, __u8 status; __u8 reserved;);
DEF_RPACKET_DATA(ECHO, SET_REPLY,
byte status;
byte reserved;
);
struct ECHO_priv_data {
};
static xproto_table_t PROTO_TABLE(ECHO);
static xproto_table_t PROTO_TABLE(ECHO);
/*---------------- ECHO: Methods -------------------------------------------*/
static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone)
const xproto_table_t *proto_table, byte subtype,
int subunits, int subunit_ports, bool to_phone)
{
xpd_t *xpd = NULL;
int channels = 0;
@@ -65,9 +70,8 @@ static xpd_t *ECHO_card_new(xbus_t *xbus, int unit, int subunit,
return NULL;
}
XBUS_DBG(GENERAL, xbus, "\n");
xpd =
xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct ECHO_priv_data), proto_table, channels);
xpd = xpd_alloc(xbus, unit, subunit, subtype, subunits,
sizeof(struct ECHO_priv_data), proto_table, channels);
if (!xpd)
return NULL;
xpd->type_name = "ECHO";
@@ -118,17 +122,19 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
static int rate_limit;
if ((rate_limit++ % 1003) < 5)
notify_bad_xpd(__func__, xbus, addr, orig_xpd->xpdname);
notify_bad_xpd(__func__, xbus, addr,
orig_xpd->xpdname);
return -EPROTO;
}
spin_lock_irqsave(&xpd->lock, flags);
/* Update /proc info only if reply related to last reg read request */
if (REG_FIELD(&xpd->requested_reply, regnum) ==
REG_FIELD(info, regnum)
&& REG_FIELD(&xpd->requested_reply, do_subreg) ==
REG_FIELD(info, do_subreg)
&& REG_FIELD(&xpd->requested_reply, subreg) ==
REG_FIELD(info, subreg)) {
if (
REG_FIELD(&xpd->requested_reply, regnum) ==
REG_FIELD(info, regnum) &&
REG_FIELD(&xpd->requested_reply, do_subreg) ==
REG_FIELD(info, do_subreg) &&
REG_FIELD(&xpd->requested_reply, subreg) ==
REG_FIELD(info, subreg)) {
xpd->last_reply = *info;
}
spin_unlock_irqrestore(&xpd->lock, flags);
@@ -140,7 +146,7 @@ static int ECHO_card_register_reply(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *info)
static /* 0x39 */ HOSTCMD(ECHO, SET)
{
struct xbus_echo_state *es;
__u8 *ts;
byte *ts;
xframe_t *xframe;
xpacket_t *pack;
int ret;
@@ -166,7 +172,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
{
int ts_number;
int ts_mask;
__u8 *ts;
byte *ts;
ts = xpd->xbus->echo_state.timeslots;
/*
@@ -192,7 +198,7 @@ static int ECHO_ec_set(xpd_t *xpd, int pos, bool on)
ts[ts_number] &= ~ts_mask;
}
LINE_DBG(GENERAL, xpd, pos, "%s = %d -- ts_number=%d ts_mask=0x%X\n",
__func__, on, ts_number, ts_mask);
__func__, on, ts_number, ts_mask);
return 0;
}
@@ -201,7 +207,7 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
int ts_number;
int ts_mask;
int is_on;
__u8 *ts;
byte *ts;
ts = xpd->xbus->echo_state.timeslots;
ts_mask = (xpd->addr.unit == 0) ? 0x1 : 0x2; /* Which bit? */
@@ -214,14 +220,14 @@ static int ECHO_ec_get(xpd_t *xpd, int pos)
}
#if 0
LINE_DBG(GENERAL, xpd, pos, "ec_get=%d -- ts_number=%d ts_mask=0x%X\n",
is_on, ts_number, ts_mask);
is_on, ts_number, ts_mask);
#endif
return is_on;
}
static void ECHO_ec_dump(xbus_t *xbus)
{
__u8 *ts;
byte *ts;
int i;
ts = xbus->echo_state.timeslots;
@@ -230,11 +236,12 @@ static void ECHO_ec_dump(xbus_t *xbus)
"EC-DUMP[%03d]: "
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X "
"0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n",
i, ts[i + 0], ts[i + 1], ts[i + 2], ts[i + 3],
ts[i + 4], ts[i + 5], ts[i + 6], ts[i + 7], ts[i + 8],
ts[i + 9], ts[i + 10], ts[i + 11], ts[i + 12],
ts[i + 13], ts[i + 14], ts[i + 15]
);
i,
ts[i+0], ts[i+1], ts[i+2], ts[i+3], ts[i+4], ts[i+5],
ts[i+6], ts[i+7],
ts[i+8], ts[i+9], ts[i+10], ts[i+11], ts[i+12],
ts[i+13], ts[i+14], ts[i+15]
);
}
}
@@ -248,7 +255,7 @@ static int ECHO_ec_update(xbus_t *xbus)
/*---------------- ECHO: Astribank Reply Handlers --------------------------*/
HANDLER_DEF(ECHO, SET_REPLY)
{
__u8 status;
byte status;
BUG_ON(!xpd);
status = RPACKET_FIELD(pack, ECHO, SET_REPLY, status);
@@ -256,26 +263,26 @@ HANDLER_DEF(ECHO, SET_REPLY)
return 0;
}
static const struct xops echo_xops = {
.card_new = ECHO_card_new,
.card_init = ECHO_card_init,
.card_remove = ECHO_card_remove,
.card_tick = ECHO_card_tick,
.card_register_reply = ECHO_card_register_reply,
static const struct xops echo_xops = {
.card_new = ECHO_card_new,
.card_init = ECHO_card_init,
.card_remove = ECHO_card_remove,
.card_tick = ECHO_card_tick,
.card_register_reply = ECHO_card_register_reply,
};
static const struct echoops echoops = {
.ec_set = ECHO_ec_set,
.ec_get = ECHO_ec_get,
.ec_update = ECHO_ec_update,
.ec_dump = ECHO_ec_dump,
static const struct echoops echoops = {
.ec_set = ECHO_ec_set,
.ec_get = ECHO_ec_get,
.ec_update = ECHO_ec_update,
.ec_dump = ECHO_ec_dump,
};
static xproto_table_t PROTO_TABLE(ECHO) = {
.owner = THIS_MODULE,
.entries = {
/* Table Card Opcode */
XENTRY( ECHO, ECHO, SET_REPLY ),
/* Table Card Opcode */
XENTRY(ECHO, ECHO, SET_REPLY),
},
.name = "ECHO",
.ports_per_subunit = 1,
@@ -288,7 +295,7 @@ static xproto_table_t PROTO_TABLE(ECHO) = {
static bool echo_packet_is_valid(xpacket_t *pack)
{
const xproto_entry_t *xe = NULL;
const xproto_entry_t *xe = NULL;
// DBG(GENERAL, "\n");
xe = xproto_card_entry(&PROTO_TABLE(ECHO), XPACKET_OP(pack));
return xe != NULL;
@@ -302,14 +309,14 @@ static void echo_packet_dump(const char *msg, xpacket_t *pack)
/*------------------------- sysfs stuff --------------------------------*/
static int echo_xpd_probe(struct device *dev)
{
xpd_t *ec_xpd;
int ret = 0;
xpd_t *ec_xpd;
int ret = 0;
ec_xpd = dev_to_xpd(dev);
/* Is it our device? */
if (ec_xpd->type != XPD_TYPE_ECHO) {
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n", dev_name(dev),
ec_xpd->type);
XPD_ERR(ec_xpd, "drop suggestion for %s (%d)\n",
dev_name(dev), ec_xpd->type);
return -EINVAL;
}
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
@@ -318,20 +325,23 @@ static int echo_xpd_probe(struct device *dev)
static int echo_xpd_remove(struct device *dev)
{
xpd_t *ec_xpd;
xpd_t *ec_xpd;
ec_xpd = dev_to_xpd(dev);
XPD_DBG(DEVICES, ec_xpd, "SYSFS\n");
return 0;
}
static struct xpd_driver echo_driver = {
.type = XPD_TYPE_ECHO,
.driver = {
.name = "echo",
.owner = THIS_MODULE,
.probe = echo_xpd_probe,
.remove = echo_xpd_remove}
static struct xpd_driver echo_driver = {
.type = XPD_TYPE_ECHO,
.driver = {
.name = "echo",
#ifndef OLD_HOTPLUG_SUPPORT
.owner = THIS_MODULE,
#endif
.probe = echo_xpd_probe,
.remove = echo_xpd_remove
}
};
static int __init card_echo_startup(void)

View File

@@ -24,8 +24,8 @@
#include "xpd.h"
enum echo_opcodes {
XPROTO_NAME(ECHO, SET) = 0x39,
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
XPROTO_NAME(ECHO, SET) = 0x39,
XPROTO_NAME(ECHO, SET_REPLY) = 0x3A,
};
#endif /* CARD_ECHO_H */
#endif /* CARD_ECHO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -25,16 +25,18 @@
#include "xpd.h"
enum fxo_opcodes {
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06, /**/
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, SIG_CHANGED) = 0x06,
/**/
XPROTO_NAME(FXO, DAA_WRITE) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, XPD_STATE) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, CHAN_CID) = 0x0F, /* Write to DAA */
XPROTO_NAME(FXO, LED) = 0x0F, /* Write to DAA */
};
DEF_RPACKET_DATA(FXO, SIG_CHANGED,
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
#endif /* CARD_FXO_H */
#endif /* CARD_FXO_H */

File diff suppressed because it is too large Load Diff

View File

@@ -25,15 +25,18 @@
#include "xpd.h"
enum fxs_opcodes {
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
/**/ XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, SIG_CHANGED) = 0x06,
/**/
XPROTO_NAME(FXS, XPD_STATE) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, CHAN_POWER) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, CHAN_CID) = 0x0F, /* Write to SLIC */
XPROTO_NAME(FXS, LED) = 0x0F, /* Write to SLIC */
};
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
#endif /* CARD_FXS_H */
DEF_RPACKET_DATA(FXS, SIG_CHANGED,
xpp_line_t sig_status; /* channels: lsb=1, msb=8 */
xpp_line_t sig_toggles; /* channels: lsb=1, msb=8 */
);
#endif /* CARD_FXS_H */

View File

@@ -22,7 +22,6 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/kmod.h>
#include "xdefs.h"
#include "xpd.h"
#include "xpp_dahdi.h"
@@ -33,22 +32,21 @@
static const char rcsid[] = "$Id$";
DEF_PARM(charp, initdir, "/usr/share/dahdi", 0644,
"The directory of card initialization scripts");
DEF_PARM(charp,initdir, "/usr/share/dahdi", 0644, "The directory of card initialization scripts");
#define CHIP_REGISTERS "chipregs"
extern int debug;
extern int debug;
/*---------------- GLOBAL PROC handling -----------------------------------*/
static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
bool eoftx)
static int send_magic_request(xbus_t *xbus,
unsigned unit, xportno_t portno, bool eoftx)
{
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
int ret;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
int ret;
/*
* Zero length multibyte is legal and has special meaning for the
@@ -67,210 +65,203 @@ static int send_magic_request(xbus_t *xbus, unsigned unit, xportno_t portno,
dump_xframe(__func__, xbus, xframe, debug);
ret = send_cmd_frame(xbus, xframe);
if (ret < 0)
PORT_ERR(xbus, unit, portno, "%s: failed sending xframe\n",
__func__);
PORT_ERR(xbus, unit, portno,
"%s: failed sending xframe\n", __func__);
return ret;
}
static int parse_hexbyte(const char *buf)
{
char *endp;
unsigned val;
char *endp;
unsigned val;
val = simple_strtoul(buf, &endp, 16);
if (*endp != '\0' || val > 0xFF)
if(*endp != '\0' || val > 0xFF)
return -EBADR;
return (__u8)val;
return (byte)val;
}
static int execute_chip_command(xpd_t *xpd, const int argc, char *argv[])
{
int argno;
char num_args;
int portno;
bool writing;
int op; /* [W]rite, [R]ead */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
bool do_subreg = 0;
int regnum;
int subreg;
int data_low;
bool do_datah;
int data_high;
int ret = -EBADR;
int argno;
char num_args;
int portno;
bool writing;
int op; /* [W]rite, [R]ead */
int addr_mode; /* [D]irect, [I]ndirect, [Mm]ulti */
bool do_subreg = 0;
int regnum;
int subreg;
int data_low;
bool do_datah;
int data_high;
int ret = -EBADR;
num_args = 2; /* port + operation */
if (argc < num_args) {
num_args = 2; /* port + operation */
if(argc < num_args) {
XPD_ERR(xpd, "Not enough arguments (%d)\n", argc);
XPD_ERR(xpd,
"Any Command is composed of at least %d words "
"(got only %d)\n",
num_args, argc);
"Any Command is composed of at least %d words (got only %d)\n",
num_args, argc);
goto out;
}
/* Process the arguments */
argno = 0;
if (strcmp(argv[argno], "*") == 0) {
if(strcmp(argv[argno], "*") == 0) {
portno = PORT_BROADCAST;
//XPD_DBG(REGS, xpd, "Port broadcast\n");
} else {
portno = parse_hexbyte(argv[argno]);
if (portno < 0 || portno >= 8) {
if(portno < 0 || portno >= 8) {
XPD_ERR(xpd, "Illegal port number '%s'\n", argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Port is %d\n", portno);
}
argno++;
if (strlen(argv[argno]) != 2) {
if(strlen(argv[argno]) != 2) {
XPD_ERR(xpd, "Wrong operation codes '%s'\n", argv[argno]);
goto out;
}
op = argv[argno][0];
switch (op) {
case 'W':
writing = 1;
num_args++; /* data low */
//XPD_DBG(REGS, xpd, "WRITING\n");
break;
case 'R':
writing = 0;
//XPD_DBG(REGS, xpd, "READING\n");
break;
default:
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
goto out;
switch(op) {
case 'W':
writing = 1;
num_args++; /* data low */
//XPD_DBG(REGS, xpd, "WRITING\n");
break;
case 'R':
writing = 0;
//XPD_DBG(REGS, xpd, "READING\n");
break;
default:
XPD_ERR(xpd, "Unknown operation type '%c'\n", op);
goto out;
}
addr_mode = argv[argno][1];
switch (addr_mode) {
case 'I':
XPD_NOTICE(xpd,
"'I' is deprecated in register commands. "
"Use 'S' instead.\n");
/* fall through */
case 'S':
do_subreg = 1;
num_args += 2; /* register + subreg */
//XPD_DBG(REGS, xpd, "SUBREG\n");
break;
case 'D':
do_subreg = 0;
num_args++; /* register */
//XPD_DBG(REGS, xpd, "DIRECT\n");
break;
case 'M':
case 'm':
if (op != 'W') {
XPD_ERR(xpd,
"Can use Multibyte (%c) only with op 'W'\n",
addr_mode);
switch(addr_mode) {
case 'I':
XPD_NOTICE(xpd, "'I' is deprecated in register commands. Use 'S' instead.\n");
/* fall through */
case 'S':
do_subreg = 1;
num_args += 2; /* register + subreg */
//XPD_DBG(REGS, xpd, "SUBREG\n");
break;
case 'D':
do_subreg = 0;
num_args++; /* register */
//XPD_DBG(REGS, xpd, "DIRECT\n");
break;
case 'M':
case 'm':
if(op != 'W') {
XPD_ERR(xpd,
"Can use Multibyte (%c) only with op 'W'\n", addr_mode);
goto out;
}
num_args--; /* No data low */
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
break;
default:
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
goto out;
}
num_args--; /* No data low */
//XPD_DBG(REGS, xpd, "Multibyte (%c)\n", addr_mode);
break;
default:
XPD_ERR(xpd, "Unknown addressing type '%c'\n", addr_mode);
goto out;
}
if (argv[argno][2] != '\0') {
if(argv[argno][2] != '\0') {
XPD_ERR(xpd, "Bad operation field '%s'\n", argv[argno]);
goto out;
}
if (argc < num_args) {
if(argc < num_args) {
XPD_ERR(xpd,
"Command \"%s\" is composed of at least %d words "
"(got only %d)\n",
argv[argno], num_args, argc);
"Command \"%s\" is composed of at least %d words (got only %d)\n",
argv[argno], num_args, argc);
goto out;
}
argno++;
if (addr_mode == 'M' || addr_mode == 'm') {
if (argno < argc) {
if(addr_mode == 'M' || addr_mode == 'm') {
if(argno < argc) {
XPD_ERR(xpd,
"Magic-Multibyte(%c) with %d extra arguments\n",
addr_mode, argc - argno);
"Magic-Multibyte(%c) with %d extra arguments\n",
addr_mode, argc - argno);
goto out;
}
ret =
send_magic_request(xpd->xbus, xpd->addr.unit, portno,
addr_mode == 'm');
ret = send_magic_request(xpd->xbus, xpd->addr.unit, portno,
addr_mode == 'm');
goto out;
}
/* Normal (non-Magic) register commands */
do_datah = 0;
if (argno >= argc) {
if(argno >= argc) {
XPD_ERR(xpd, "Missing register number\n");
goto out;
}
regnum = parse_hexbyte(argv[argno]);
if (regnum < 0) {
if(regnum < 0) {
XPD_ERR(xpd, "Illegal register number '%s'\n", argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Register is %X\n", regnum);
argno++;
if (do_subreg) {
if (argno >= argc) {
if(do_subreg) {
if(argno >= argc) {
XPD_ERR(xpd, "Missing subregister number\n");
goto out;
}
subreg = parse_hexbyte(argv[argno]);
if (subreg < 0) {
XPD_ERR(xpd, "Illegal subregister number '%s'\n",
argv[argno]);
if(subreg < 0) {
XPD_ERR(xpd, "Illegal subregister number '%s'\n", argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Subreg is %X\n", subreg);
argno++;
} else
subreg = 0;
if (writing) {
if (argno >= argc) {
if(writing) {
if(argno >= argc) {
XPD_ERR(xpd, "Missing data low number\n");
goto out;
}
data_low = parse_hexbyte(argv[argno]);
if (data_low < 0) {
XPD_ERR(xpd, "Illegal data_low number '%s'\n",
argv[argno]);
if(data_low < 0) {
XPD_ERR(xpd, "Illegal data_low number '%s'\n", argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Data Low is %X\n", data_low);
argno++;
} else
data_low = 0;
if (argno < argc) {
if(argno < argc) {
do_datah = 1;
if (!argv[argno]) {
if(!argv[argno]) {
XPD_ERR(xpd, "Missing data high number\n");
goto out;
}
data_high = parse_hexbyte(argv[argno]);
if (data_high < 0) {
XPD_ERR(xpd, "Illegal data_high number '%s'\n",
argv[argno]);
if(data_high < 0) {
XPD_ERR(xpd, "Illegal data_high number '%s'\n", argv[argno]);
goto out;
}
//XPD_DBG(REGS, xpd, "Data High is %X\n", data_high);
argno++;
} else
data_high = 0;
if (argno < argc) {
XPD_ERR(xpd, "Command contains an extra %d argument\n",
argc - argno);
if(argno < argc) {
XPD_ERR(xpd,
"Command contains an extra %d argument\n",
argc - argno);
goto out;
}
#if 0
XPD_DBG(REGS, xpd,
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d "
"dataL=%d do_datah=%d dataH=%d\n",
portno, /* portno */
writing, /* writing */
regnum, do_subreg, /* use subreg */
subreg, /* subreg */
data_low, do_datah, /* use data_high */
data_high);
"portno=%d writing=%d regnum=%d do_subreg=%d subreg=%d dataL=%d do_datah=%d dataH=%d\n",
portno, /* portno */
writing, /* writing */
regnum,
do_subreg, /* use subreg */
subreg, /* subreg */
data_low,
do_datah, /* use data_high*/
data_high);
#endif
ret = xpp_register_request(xpd->xbus, xpd, portno,
writing, regnum, do_subreg, subreg,
@@ -279,38 +270,36 @@ out:
return ret;
}
#define MAX_ARGS 10
int parse_chip_command(xpd_t *xpd, char *cmdline)
{
xbus_t *xbus;
int ret = -EBADR;
__u8 buf[MAX_PROC_WRITE];
char *str;
char *p;
char *argv[MAX_ARGS + 1];
int argc;
int i;
xbus_t *xbus;
int ret = -EBADR;
byte buf[MAX_PROC_WRITE];
char *str;
char *p;
static const int MAX_ARGS = 10;
char *argv[MAX_ARGS + 1];
int argc;
int i;
BUG_ON(!xpd);
xbus = xpd->xbus;
if (!XBUS_FLAGS(xbus, CONNECTED)) {
if(!XBUS_FLAGS(xbus, CONNECTED)) {
XBUS_DBG(GENERAL, xbus, "Dropped packet. Disconnected.\n");
return -EBUSY;
}
strlcpy(buf, cmdline, MAX_PROC_WRITE); /* Save a copy */
if (buf[0] == '#' || buf[0] == ';')
if(buf[0] == '#' || buf[0] == ';')
XPD_DBG(REGS, xpd, "Note: '%s'\n", buf);
if ((p = strchr(buf, '#')) != NULL) /* Truncate comments */
if((p = strchr(buf, '#')) != NULL) /* Truncate comments */
*p = '\0';
if ((p = strchr(buf, ';')) != NULL) /* Truncate comments */
if((p = strchr(buf, ';')) != NULL) /* Truncate comments */
*p = '\0';
/* Trim leading whitespace */
for (p = buf; *p && (*p == ' ' || *p == '\t'); p++)
for(p = buf; *p && (*p == ' ' || *p == '\t'); p++) /* Trim leading whitespace */
;
str = p;
for (i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS;) {
if (*p != '\0') {
for(i = 0; (p = strsep(&str, " \t")) != NULL && i < MAX_ARGS; ) {
if(*p != '\0') {
argv[i] = p;
// XPD_DBG(REGS, xpd, "ARG %d = '%s'\n", i, p);
i++;
@@ -318,12 +307,11 @@ int parse_chip_command(xpd_t *xpd, char *cmdline)
}
argv[i] = NULL;
argc = i;
if (p) {
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n",
i, p);
if(p) {
XPD_ERR(xpd, "Too many words (%d) to process. Last was '%s'\n", i, p);
goto out;
}
if (argc)
if(argc)
ret = execute_chip_command(xpd, argc, argv);
else
ret = 0; /* empty command - no op */
@@ -340,11 +328,11 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
/* 0x07 */ HOSTCMD(GLOBAL, AB_REQUEST)
{
int ret = -ENODEV;
xframe_t *xframe;
xpacket_t *pack;
int ret = -ENODEV;
xframe_t *xframe;
xpacket_t *pack;
if (!xbus) {
if(!xbus) {
DBG(DEVICES, "NO XBUS\n");
return -EINVAL;
}
@@ -354,35 +342,33 @@ static void global_packet_dump(const char *msg, xpacket_t *pack);
RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, rev) = XPP_PROTOCOL_VERSION;
RPACKET_FIELD(pack, GLOBAL, AB_REQUEST, reserved) = 0;
XBUS_DBG(DEVICES, xbus, "Protocol Version %d\n", XPP_PROTOCOL_VERSION);
if (xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
if(xbus_setstate(xbus, XBUS_STATE_SENT_REQUEST))
ret = send_cmd_frame(xbus, xframe);
return ret;
}
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
__u8 data_low, bool do_datah, __u8 data_high,
bool should_reply)
bool writing, byte regnum, bool do_subreg, byte subreg,
byte data_low, bool do_datah, byte data_high, bool should_reply)
{
int ret = 0;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
int ret = 0;
xframe_t *xframe;
xpacket_t *pack;
reg_cmd_t *reg_cmd;
if (!xbus) {
if(!xbus) {
DBG(REGS, "NO XBUS\n");
return -EINVAL;
}
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST,
xpd->xbus_idx);
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx);
LINE_DBG(REGS, xpd, portno, "%c%c %02X %02X %02X %02X\n",
(writing) ? 'W' : 'R', (do_subreg) ? 'S' : 'D', regnum, subreg,
data_low, data_high);
(writing)?'W':'R',
(do_subreg)?'S':'D',
regnum, subreg, data_low, data_high);
reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
/* do not count the 'bytes' field */
reg_cmd->bytes = sizeof(*reg_cmd) - 1;
reg_cmd->bytes = sizeof(*reg_cmd) - 1; // do not count the 'bytes' field
reg_cmd->is_multibyte = 0;
if (portno == PORT_BROADCAST) {
if(portno == PORT_BROADCAST) {
reg_cmd->portnum = 0;
REG_FIELD(reg_cmd, all_ports_broadcast) = 1;
} else {
@@ -398,15 +384,14 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
REG_FIELD(reg_cmd, do_datah) = do_datah;
REG_FIELD(reg_cmd, data_low) = data_low;
REG_FIELD(reg_cmd, data_high) = data_high;
if (should_reply)
if(should_reply)
xpd->requested_reply = *reg_cmd;
if (debug & DBG_REGS) {
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit,
reg_cmd->portnum, reg_cmd);
if(debug & DBG_REGS) {
dump_reg_cmd("REG_REQ", 1, xbus, xpd->addr.unit, reg_cmd->portnum, reg_cmd);
dump_packet("REG_REQ", pack, 1);
}
if (!xframe->usec_towait) { /* default processing time of SPI */
if (subreg)
if(!xframe->usec_towait) { /* default processing time of SPI */
if(subreg)
xframe->usec_towait = 2000;
else
xframe->usec_towait = 1000;
@@ -414,19 +399,18 @@ int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
ret = send_cmd_frame(xbus, xframe);
return ret;
}
EXPORT_SYMBOL(xpp_register_request);
/*
* The XPD parameter is totaly ignored by the driver and firmware as well.
*/
/* 0x19 */ HOSTCMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift)
{
xframe_t *xframe;
xpacket_t *pack;
const char *mode_name;
xframe_t *xframe;
xpacket_t *pack;
const char *mode_name;
BUG_ON(!xbus);
if ((mode_name = sync_mode_name(mode)) == NULL) {
if((mode_name = sync_mode_name(mode)) == NULL) {
XBUS_ERR(xbus, "SYNC_SOURCE: bad sync_mode=0x%X\n", mode);
return -EINVAL;
}
@@ -443,8 +427,8 @@ EXPORT_SYMBOL(xpp_register_request);
*/
static int send_xbus_reset(xbus_t *xbus, uint8_t reset_mask)
{
xframe_t *xframe;
xpacket_t *pack;
xframe_t *xframe;
xpacket_t *pack;
BUG_ON(!xbus);
XFRAME_NEW_CMD(xframe, pack, xbus, GLOBAL, XBUS_RESET, 0);
@@ -477,14 +461,14 @@ HANDLER_DEF(GLOBAL, NULL_REPLY)
return 0;
}
HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
{ /* 0x08 */
struct xbus_workqueue *worker;
__u8 rev;
struct unit_descriptor *units;
int count_units;
int i;
int ret = 0;
HANDLER_DEF(GLOBAL, AB_DESCRIPTION) /* 0x08 */
{
struct xbus_workqueue *worker;
byte rev;
struct unit_descriptor *units;
int count_units;
int i;
int ret = 0;
if (!xbus) {
NOTICE("%s: xbus is gone!!!\n", __func__);
@@ -492,31 +476,31 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
}
rev = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, rev);
units = RPACKET_FIELD(pack, GLOBAL, AB_DESCRIPTION, unit_descriptor);
count_units = XPACKET_LEN(pack) - ((__u8 *)units - (__u8 *)pack);
count_units = XPACKET_LEN(pack) - ((byte *)units - (byte *)pack);
count_units /= sizeof(*units);
if (rev != XPP_PROTOCOL_VERSION) {
if(rev != XPP_PROTOCOL_VERSION) {
XBUS_NOTICE(xbus, "Bad protocol version %d (should be %d)\n",
rev, XPP_PROTOCOL_VERSION);
rev, XPP_PROTOCOL_VERSION);
ret = -EPROTO;
goto proto_err;
}
if (count_units > NUM_UNITS) {
if(count_units > NUM_UNITS) {
XBUS_NOTICE(xbus, "Too many units %d (should be %d)\n",
count_units, NUM_UNITS);
count_units, NUM_UNITS);
ret = -EPROTO;
goto proto_err;
}
if (count_units <= 0) {
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n", count_units);
if(count_units <= 0) {
XBUS_NOTICE(xbus, "Empty astribank? (%d units)\n",
count_units);
ret = -EPROTO;
goto proto_err;
}
if (!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
if(!xbus_setstate(xbus, XBUS_STATE_RECVD_DESC)) {
ret = -EPROTO;
goto proto_err;
}
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n",
count_units, rev);
XBUS_INFO(xbus, "DESCRIPTOR: %d cards, protocol revision %d\n", count_units, rev);
if (xbus_check_unique(xbus))
return -EBUSY;
xbus->revision = rev;
@@ -526,14 +510,12 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
ret = -ENODEV;
goto out;
}
for (i = 0; i < count_units; i++) {
struct unit_descriptor *this_unit = &units[i];
struct card_desc_struct *card_desc;
unsigned long flags;
for(i = 0; i < count_units; i++) {
struct unit_descriptor *this_unit = &units[i];
struct card_desc_struct *card_desc;
unsigned long flags;
if ((card_desc =
KZALLOC(sizeof(struct card_desc_struct),
GFP_ATOMIC)) == NULL) {
if((card_desc = KZALLOC(sizeof(struct card_desc_struct), GFP_ATOMIC)) == NULL) {
XBUS_ERR(xbus, "Card description allocation failed.\n");
ret = -ENOMEM;
goto out;
@@ -546,15 +528,16 @@ HANDLER_DEF(GLOBAL, AB_DESCRIPTION)
card_desc->numchips = this_unit->numchips;
card_desc->ports_per_chip = this_unit->ports_per_chip;
card_desc->port_dir = this_unit->port_dir;
card_desc->ports =
card_desc->numchips * card_desc->ports_per_chip;
XBUS_INFO(xbus,
" CARD %d type=%d.%d ports=%d (%dx%d), "
"port-dir=0x%02X\n",
card_desc->xpd_addr.unit, card_desc->type,
card_desc->subtype, card_desc->ports,
card_desc->numchips, card_desc->ports_per_chip,
card_desc->port_dir);
card_desc->ports = card_desc->numchips * card_desc->ports_per_chip;
XBUS_INFO(xbus, " CARD %d type=%d.%d ports=%d (%dx%d), port-dir=0x%02X\n",
card_desc->xpd_addr.unit,
card_desc->type,
card_desc->subtype,
card_desc->ports,
card_desc->numchips,
card_desc->ports_per_chip,
card_desc->port_dir
);
spin_lock_irqsave(&worker->worker_lock, flags);
worker->num_units++;
XBUS_COUNTER(xbus, UNITS)++;
@@ -575,23 +558,21 @@ out:
HANDLER_DEF(GLOBAL, REGISTER_REPLY)
{
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
reg_cmd_t *reg = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REPLY, regcmd);
if (!xpd) {
static int rate_limit;
if(!xpd) {
static int rate_limit;
if ((rate_limit++ % 1003) < 5)
notify_bad_xpd(__func__, xbus, XPACKET_ADDR(pack), "");
if((rate_limit++ % 1003) < 5)
notify_bad_xpd(__FUNCTION__, xbus, XPACKET_ADDR(pack), "");
return -EPROTO;
}
if (debug & DBG_REGS) {
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum,
reg);
if(debug & DBG_REGS) {
dump_reg_cmd("REG_REPLY", 0, xbus, xpd->addr.unit, reg->portnum, reg);
dump_packet("REG_REPLY", pack, 1);
}
if (!XMETHOD(card_register_reply, xpd)) {
XPD_ERR(xpd,
"REGISTER_REPLY: missing card_register_reply()\n");
if (! XMETHOD(card_register_reply, xpd)) {
XPD_ERR(xpd, "REGISTER_REPLY: without card_register_reply() method\n");
return -EINVAL;
}
return CALL_XMETHOD(card_register_reply, xpd, reg);
@@ -599,12 +580,12 @@ HANDLER_DEF(GLOBAL, REGISTER_REPLY)
HANDLER_DEF(GLOBAL, SYNC_REPLY)
{
__u8 mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
__u8 drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
const char *mode_name;
byte mode = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, sync_mode);
byte drift = RPACKET_FIELD(pack, GLOBAL, SYNC_REPLY, drift);
const char *mode_name;
BUG_ON(!xbus);
if ((mode_name = sync_mode_name(mode)) == NULL) {
if((mode_name = sync_mode_name(mode)) == NULL) {
XBUS_ERR(xbus, "SYNC_REPLY: bad sync_mode=0x%X\n", mode);
return -EINVAL;
}
@@ -618,26 +599,24 @@ HANDLER_DEF(GLOBAL, SYNC_REPLY)
HANDLER_DEF(GLOBAL, ERROR_CODE)
{
char tmp_name[TMP_NAME_LEN];
static long rate_limit;
__u8 category_code;
__u8 errorbits;
char tmp_name[TMP_NAME_LEN];
static long rate_limit;
byte category_code;
byte errorbits;
BUG_ON(!xbus);
if ((rate_limit++ % 5003) > 200)
if((rate_limit++ % 5003) > 200)
return 0;
category_code = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, category_code);
errorbits = RPACKET_FIELD(pack, GLOBAL, ERROR_CODE, errorbits);
if (!xpd) {
if(!xpd) {
snprintf(tmp_name, TMP_NAME_LEN, "%s(%1d%1d)", xbus->busname,
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
} else {
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname,
xpd->xpdname);
snprintf(tmp_name, TMP_NAME_LEN, "%s/%s", xbus->busname, xpd->xpdname);
}
NOTICE
("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
tmp_name, cmd->name, category_code, errorbits, rate_limit);
NOTICE("%s: FIRMWARE %s: category=%d errorbits=0x%02X (rate_limit=%ld)\n",
tmp_name, cmd->name, category_code, errorbits, rate_limit);
dump_packet("FIRMWARE: ", pack, 1);
/*
* FIXME: Should implement an error recovery plan
@@ -645,14 +624,15 @@ HANDLER_DEF(GLOBAL, ERROR_CODE)
return 0;
}
xproto_table_t PROTO_TABLE(GLOBAL) = {
.entries = {
/* Prototable Card Opcode */
XENTRY( GLOBAL, GLOBAL, NULL_REPLY ),
XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ),
XENTRY( GLOBAL, GLOBAL, NULL_REPLY ),
XENTRY( GLOBAL, GLOBAL, AB_DESCRIPTION ),
XENTRY( GLOBAL, GLOBAL, SYNC_REPLY ),
XENTRY( GLOBAL, GLOBAL, ERROR_CODE ),
XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ),
XENTRY( GLOBAL, GLOBAL, ERROR_CODE ),
XENTRY( GLOBAL, GLOBAL, REGISTER_REPLY ),
},
.name = "GLOBAL",
.packet_is_valid = global_packet_is_valid,
@@ -661,7 +641,7 @@ xproto_table_t PROTO_TABLE(GLOBAL) = {
static bool global_packet_is_valid(xpacket_t *pack)
{
const xproto_entry_t *xe;
const xproto_entry_t *xe;
//DBG(GENERAL, "\n");
xe = xproto_global_entry(XPACKET_OP(pack));
@@ -675,37 +655,28 @@ static void global_packet_dump(const char *msg, xpacket_t *pack)
#define MAX_PATH_STR 128
#ifndef UMH_WAIT_PROC
/*
* - UMH_WAIT_PROC was introduced as enum in 2.6.23
* with a value of 1
* - It was changed to a macro (and it's value was modified) in 3.3.0
*/
#define UMH_WAIT_PROC 1
#endif
int run_initialize_registers(xpd_t *xpd)
{
int ret;
xbus_t *xbus;
char busstr[MAX_ENV_STR];
char busnumstr[MAX_ENV_STR];
char modelstr[MAX_ENV_STR];
char unitstr[MAX_ENV_STR];
char subunitsstr[MAX_ENV_STR];
char typestr[MAX_ENV_STR];
char directionstr[MAX_ENV_STR];
char revstr[MAX_ENV_STR];
char connectorstr[MAX_ENV_STR];
char xbuslabel[MAX_ENV_STR];
char init_card[MAX_PATH_STR];
__u8 direction_mask;
int i;
char *argv[] = {
int ret;
xbus_t *xbus;
char busstr[MAX_ENV_STR];
char busnumstr[MAX_ENV_STR];
char modelstr[MAX_ENV_STR];
char unitstr[MAX_ENV_STR];
char subunitsstr[MAX_ENV_STR];
char typestr[MAX_ENV_STR];
char directionstr[MAX_ENV_STR];
char revstr[MAX_ENV_STR];
char connectorstr[MAX_ENV_STR];
char xbuslabel[MAX_ENV_STR];
char init_card[MAX_PATH_STR];
byte direction_mask;
int i;
char *argv[] = {
init_card,
NULL
};
char *envp[] = {
char *envp[] = {
busstr,
busnumstr,
modelstr,
@@ -721,82 +692,74 @@ int run_initialize_registers(xpd_t *xpd)
BUG_ON(!xpd);
xbus = xpd->xbus;
if (!initdir || !initdir[0]) {
if(!initdir || !initdir[0]) {
XPD_NOTICE(xpd, "Missing initdir parameter\n");
ret = -EINVAL;
goto err;
}
if (!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
if(!xpd_setstate(xpd, XPD_STATE_INIT_REGS)) {
ret = -EINVAL;
goto err;
}
direction_mask = 0;
for (i = 0; i < xpd->subunits; i++) {
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
for(i = 0; i < xpd->subunits; i++) {
xpd_t *su = xpd_byaddr(xbus, xpd->addr.unit, i);
if (!su) {
XPD_ERR(xpd, "Have %d subunits, but not subunit #%d\n",
if(!su) {
XPD_ERR(xpd,
"Have %d subunits, but not subunit #%d\n",
xpd->subunits, i);
continue;
}
direction_mask |=
(PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
direction_mask |= (PHONEDEV(su).direction == TO_PHONE) ? BIT(i) : 0;
}
snprintf(busstr, MAX_ENV_STR, "XBUS_NAME=%s", xbus->busname);
snprintf(busnumstr, MAX_ENV_STR, "XBUS_NUMBER=%d", xbus->num);
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s",
xbus->transport.model_string);
snprintf(modelstr, MAX_ENV_STR, "XBUS_MODEL_STRING=%s", xbus->transport.model_string);
snprintf(unitstr, MAX_ENV_STR, "UNIT_NUMBER=%d", xpd->addr.unit);
snprintf(typestr, MAX_ENV_STR, "UNIT_TYPE=%d", xpd->type);
snprintf(subunitsstr, MAX_ENV_STR, "UNIT_SUBUNITS=%d", xpd->subunits);
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d",
direction_mask);
snprintf(directionstr, MAX_ENV_STR, "UNIT_SUBUNITS_DIR=%d", direction_mask);
snprintf(revstr, MAX_ENV_STR, "XBUS_REVISION=%d", xbus->revision);
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s",
xbus->connector);
snprintf(connectorstr, MAX_ENV_STR, "XBUS_CONNECTOR=%s", xbus->connector);
snprintf(xbuslabel, MAX_ENV_STR, "XBUS_LABEL=%s", xbus->label);
if (snprintf
(init_card, MAX_PATH_STR, "%s/init_card_%d_%d", initdir, xpd->type,
xbus->revision) > MAX_PATH_STR) {
XPD_NOTICE(xpd,
"Cannot initialize. pathname is longer "
"than %d characters.\n",
MAX_PATH_STR);
if(snprintf(init_card, MAX_PATH_STR, "%s/init_card_%d_%d",
initdir, xpd->type, xbus->revision) > MAX_PATH_STR) {
XPD_NOTICE(xpd, "Cannot initialize. pathname is longer than %d characters.\n", MAX_PATH_STR);
ret = -E2BIG;
goto err;
}
if (!XBUS_IS(xbus, RECVD_DESC)) {
XBUS_ERR(xbus,
"Skipped register initialization. In state %s.\n",
xbus_statename(XBUS_STATE(xbus)));
if(!XBUS_IS(xbus, RECVD_DESC)) {
XBUS_ERR(xbus, "Skipped register initialization. In state %s.\n",
xbus_statename(XBUS_STATE(xbus)));
ret = -ENODEV;
goto err;
}
XPD_DBG(DEVICES, xpd, "running '%s' for type=%d revision=%d\n",
init_card, xpd->type, xbus->revision);
ret = call_usermodehelper(init_card, argv, envp, UMH_WAIT_PROC);
init_card, xpd->type, xbus->revision);
ret = call_usermodehelper(init_card, argv, envp, 1);
/*
* Carefully report results
*/
if (ret == 0)
if(ret == 0)
XPD_DBG(DEVICES, xpd, "'%s' finished OK\n", init_card);
else if (ret < 0) {
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card,
ret);
else if(ret < 0) {
XPD_ERR(xpd, "Failed running '%s' (errno %d)\n", init_card, ret);
} else {
__u8 exitval = ((unsigned)ret >> 8) & 0xFF;
__u8 sigval = ret & 0xFF;
byte exitval = ((unsigned)ret >> 8) & 0xFF;
byte sigval = ret & 0xFF;
if (!exitval) {
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card,
sigval);
if(!exitval) {
XPD_ERR(xpd, "'%s' killed by signal %d\n", init_card, sigval);
} else {
XPD_ERR(xpd, "'%s' aborted with exitval %d\n",
init_card, exitval);
XPD_ERR(xpd, "'%s' aborted with exitval %d\n", init_card, exitval);
}
ret = -EINVAL;
}
err:
return ret;
}
EXPORT_SYMBOL(sync_mode_name);
EXPORT_SYMBOL(run_initialize_registers);
EXPORT_SYMBOL(xpp_register_request);

View File

@@ -26,45 +26,75 @@
#include "xbus-pcm.h"
enum global_opcodes {
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
/**/ XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
/**/ XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
/**/ XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
XPROTO_NAME(GLOBAL, XBUS_RESET) = 0x23,
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
XPROTO_NAME(GLOBAL, AB_REQUEST) = 0x07,
XPROTO_NAME(GLOBAL, AB_DESCRIPTION) = 0x08,
XPROTO_NAME(GLOBAL, REGISTER_REQUEST) = 0x0F,
XPROTO_NAME(GLOBAL, REGISTER_REPLY) = 0x10,
/**/
XPROTO_NAME(GLOBAL, PCM_WRITE) = 0x11,
XPROTO_NAME(GLOBAL, PCM_READ) = 0x12,
/**/
XPROTO_NAME(GLOBAL, SYNC_SOURCE) = 0x19,
XPROTO_NAME(GLOBAL, SYNC_REPLY) = 0x1A,
/**/
XPROTO_NAME(GLOBAL, ERROR_CODE) = 0x22,
XPROTO_NAME(GLOBAL, XBUS_RESET) = 0x23,
XPROTO_NAME(GLOBAL, NULL_REPLY) = 0xFE,
};
struct unit_descriptor {
struct xpd_addr addr;
__u8 subtype:4;
__u8 type:4;
__u8 numchips;
__u8 ports_per_chip;
__u8 port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
__u8 reserved[2];
struct xpd_addr ec_addr;
struct xpd_addr addr;
byte subtype:4;
byte type:4;
byte numchips;
byte ports_per_chip;
byte port_dir; /* bitmask: 0 - PSTN, 1 - PHONE */
byte reserved[2];
struct xpd_addr ec_addr;
};
#define NUM_UNITS 6
DEF_RPACKET_DATA(GLOBAL, NULL_REPLY);
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST, __u8 rev; __u8 reserved;);
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION, __u8 rev; __u8 reserved[3];
struct unit_descriptor unit_descriptor[NUM_UNITS];);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST, reg_cmd_t reg_cmd;);
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
DEF_RPACKET_DATA(GLOBAL, PCM_READ, xpp_line_t lines; __u8 pcm[PCM_CHUNKSIZE];);
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE, __u8 sync_mode; __u8 drift;);
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY, __u8 sync_mode; __u8 drift;);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY, reg_cmd_t regcmd;);
DEF_RPACKET_DATA(GLOBAL, XBUS_RESET, __u8 mask;);
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
__u8 bad_packet[0];);
DEF_RPACKET_DATA(GLOBAL, AB_REQUEST,
byte rev;
byte reserved;
);
DEF_RPACKET_DATA(GLOBAL, AB_DESCRIPTION,
byte rev;
byte reserved[3];
struct unit_descriptor unit_descriptor[NUM_UNITS];
);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REQUEST,
reg_cmd_t reg_cmd;
);
DEF_RPACKET_DATA(GLOBAL, PCM_WRITE,
xpp_line_t lines;
byte pcm[PCM_CHUNKSIZE];
);
DEF_RPACKET_DATA(GLOBAL, PCM_READ,
xpp_line_t lines;
byte pcm[PCM_CHUNKSIZE];
);
DEF_RPACKET_DATA(GLOBAL, SYNC_SOURCE,
byte sync_mode;
byte drift;
);
DEF_RPACKET_DATA(GLOBAL, SYNC_REPLY,
byte sync_mode;
byte drift;
);
DEF_RPACKET_DATA(GLOBAL, REGISTER_REPLY,
reg_cmd_t regcmd;
);
DEF_RPACKET_DATA(GLOBAL, XBUS_RESET,
byte mask;
);
DEF_RPACKET_DATA(GLOBAL, ERROR_CODE,
byte category_code;
byte errorbits;
byte bad_packet[0];
);
/* 0x07 */ DECLARE_CMD(GLOBAL, AB_REQUEST);
/* 0x19 */ DECLARE_CMD(GLOBAL, SYNC_SOURCE, enum sync_mode mode, int drift);
@@ -72,14 +102,13 @@ DEF_RPACKET_DATA(GLOBAL, ERROR_CODE, __u8 category_code; __u8 errorbits;
/* 0x23 */ DECLARE_CMD(GLOBAL, RESET_SYNC_COUNTERS);
int xpp_register_request(xbus_t *xbus, xpd_t *xpd, xportno_t portno,
bool writing, __u8 regnum, bool do_subreg, __u8 subreg,
__u8 data_low, bool do_datah, __u8 data_high,
bool should_reply);
bool writing, byte regnum, bool do_subreg, byte subreg,
byte data_low, bool do_datah, byte data_high, bool should_reply);
int send_multibyte_request(xbus_t *xbus, unsigned unit, xportno_t portno,
bool eoftx, __u8 *buf, unsigned len);
bool eoftx, byte *buf, unsigned len);
extern xproto_table_t PROTO_TABLE(GLOBAL);
int run_initialize_registers(xpd_t *xpd);
int parse_chip_command(xpd_t *xpd, char *cmdline);
extern charp initdir;
#endif /* CARD_GLOBAL_H */
#endif /* CARD_GLOBAL_H */

File diff suppressed because it is too large Load Diff

View File

@@ -25,7 +25,8 @@
#include "xpd.h"
enum pri_opcodes {
XPROTO_NAME(PRI, SET_LED) = 0x33,
XPROTO_NAME(PRI, SET_LED) = 0x33,
};
#endif /* CARD_PRI_H */
#endif /* CARD_PRI_H */

View File

@@ -20,6 +20,11 @@
*
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
# warning "This module is tested only with 2.6 kernels"
#endif
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
@@ -30,48 +35,57 @@
static const char rcsid[] = "$Id$";
#define P_(x) [ x ] = { .value = x, .name = #x, }
static struct {
static struct {
int value;
char *name;
} poll_names[] = {
P_(POLLIN), P_(POLLPRI), P_(POLLOUT), P_(POLLERR), P_(POLLHUP),
P_(POLLNVAL), P_(POLLRDNORM), P_(POLLRDBAND), P_(POLLWRNORM),
P_(POLLWRBAND), P_(POLLMSG), P_(POLLREMOVE)
P_(POLLIN),
P_(POLLPRI),
P_(POLLOUT),
P_(POLLERR),
P_(POLLHUP),
P_(POLLNVAL),
P_(POLLRDNORM),
P_(POLLRDBAND),
P_(POLLWRNORM),
P_(POLLWRBAND),
P_(POLLMSG),
P_(POLLREMOVE)
};
#undef P_
void dump_poll(int debug, const char *msg, int poll)
{
int i;
int i;
for (i = 0; i < ARRAY_SIZE(poll_names); i++) {
if (poll & poll_names[i].value)
for(i = 0; i < ARRAY_SIZE(poll_names); i++) {
if(poll & poll_names[i].value)
DBG(GENERAL, "%s: %s\n", msg, poll_names[i].name);
}
}
EXPORT_SYMBOL(dump_poll);
void alarm2str(int alarm, char *buf, int buflen)
{
char *p = buf;
int left = buflen;
int i;
int n;
char *p = buf;
int left = buflen;
int i;
int n;
if (!alarm) {
if(!alarm) {
snprintf(buf, buflen, "NONE");
return;
}
memset(buf, 0, buflen);
for (i = 0; i < 8; i++) {
if (left && (alarm & BIT(i))) {
for(i = 0; i < 8; i++) {
if(left && (alarm & BIT(i))) {
n = snprintf(p, left, "%s,", alarmbit2str(i));
p += n;
left -= n;
}
}
if (p > buf) /* kill last comma */
if(p > buf) /* kill last comma */
*(p - 1) = '\0';
}
EXPORT_SYMBOL(dump_poll);
EXPORT_SYMBOL(alarm2str);

View File

@@ -26,76 +26,55 @@
/* Debugging Macros */
#define PRINTK(level, category, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: " fmt, \
#level, category, THIS_MODULE->name, ## __VA_ARGS__)
#define PRINTK(level, category, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, THIS_MODULE->name, ## __VA_ARGS__)
#define XBUS_PRINTK(level, category, xbus, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \
#define XBUS_PRINTK(level, category, xbus, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s: " fmt, #level, \
category, THIS_MODULE->name, (xbus)->busname, ## __VA_ARGS__)
#define XPD_PRINTK(level, category, xpd, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \
category, THIS_MODULE->name, \
(xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__)
#define XPD_PRINTK(level, category, xpd, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s: " fmt, #level, \
category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, ## __VA_ARGS__)
#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \
category, THIS_MODULE->name, \
(xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__)
#define LINE_PRINTK(level, category, xpd, pos, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s/%s/%d: " fmt, #level, \
category, THIS_MODULE->name, (xpd)->xbus->busname, (xpd)->xpdname, (pos), ## __VA_ARGS__)
#define PORT_PRINTK(level, category, xbus, unit, port, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s UNIT=%d PORT=%d: " fmt, #level, \
category, THIS_MODULE->name, \
(xbus)->busname, (unit), (port), ## __VA_ARGS__)
#define PORT_PRINTK(level, category, xbus, unit, port, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: %s UNIT=%d PORT=%d: " fmt, #level, \
category, THIS_MODULE->name, (xbus)->busname, (unit), (port), ## __VA_ARGS__)
#define DBG(bits, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && \
PRINTK(DEBUG, "-" #bits, "%s: " fmt, \
__func__, ## __VA_ARGS__)))
#define DBG(bits, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && PRINTK(DEBUG, "-" #bits, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define INFO(fmt, ...) PRINTK(INFO, "", fmt, ## __VA_ARGS__)
#define NOTICE(fmt, ...) PRINTK(NOTICE, "", fmt, ## __VA_ARGS__)
#define WARNING(fmt, ...) PRINTK(WARNING, "", fmt, ## __VA_ARGS__)
#define ERR(fmt, ...) PRINTK(ERR, "", fmt, ## __VA_ARGS__)
#define XBUS_DBG(bits, xbus, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, \
xbus, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define XBUS_INFO(xbus, fmt, ...) \
XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_NOTICE(xbus, fmt, ...) \
XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_ERR(xbus, fmt, ...) \
XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_DBG(bits, xbus, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XBUS_PRINTK(DEBUG, "-" #bits, xbus, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define XBUS_INFO(xbus, fmt, ...) XBUS_PRINTK(INFO, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_NOTICE(xbus, fmt, ...) XBUS_PRINTK(NOTICE, "", xbus, fmt, ## __VA_ARGS__)
#define XBUS_ERR(xbus, fmt, ...) XBUS_PRINTK(ERR, "", xbus, fmt, ## __VA_ARGS__)
#define XPD_DBG(bits, xpd, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, \
xpd, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define XPD_INFO(xpd, fmt, ...) \
XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_NOTICE(xpd, fmt, ...) \
XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_WARNING(xpd, fmt, ...) \
XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_ERR(xpd, fmt, ...) \
XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_DBG(bits, xpd, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && XPD_PRINTK(DEBUG, "-" #bits, xpd, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define XPD_INFO(xpd, fmt, ...) XPD_PRINTK(INFO, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_NOTICE(xpd, fmt, ...) XPD_PRINTK(NOTICE, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_WARNING(xpd, fmt, ...) XPD_PRINTK(WARNING, "", xpd, fmt, ## __VA_ARGS__)
#define XPD_ERR(xpd, fmt, ...) XPD_PRINTK(ERR, "", xpd, fmt, ## __VA_ARGS__)
#define LINE_DBG(bits, xpd, pos, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, \
xpd, pos, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define LINE_NOTICE(xpd, pos, fmt, ...) \
LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__)
#define LINE_ERR(xpd, pos, fmt, ...) \
LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__)
#define LINE_DBG(bits, xpd, pos, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && LINE_PRINTK(DEBUG, "-" #bits, xpd, pos, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define LINE_NOTICE(xpd, pos, fmt, ...) LINE_PRINTK(NOTICE, "", xpd, pos, fmt, ## __VA_ARGS__)
#define LINE_ERR(xpd, pos, fmt, ...) LINE_PRINTK(ERR, "", xpd, pos, fmt, ## __VA_ARGS__)
#define PORT_DBG(bits, xbus, unit, port, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && \
PORT_PRINTK(DEBUG, "-" #bits, \
xbus, unit, port, "%s: " fmt, __func__, ## __VA_ARGS__)))
#define PORT_NOTICE(xbus, unit, port, fmt, ...) \
PORT_PRINTK(NOTICE, "", xbus, unit, port, fmt, ## __VA_ARGS__)
#define PORT_ERR(xbus, unit, port, fmt, ...) \
PORT_PRINTK(ERR, "", xbus, unit, port, fmt, ## __VA_ARGS__)
#define PORT_DBG(bits, xbus, unit, port, fmt, ...) \
((void)((debug & (DBG_ ## bits)) && PORT_PRINTK(DEBUG, "-" #bits, \
xbus, unit, port, "%s: " fmt, __FUNCTION__, ## __VA_ARGS__)))
#define PORT_NOTICE(xbus, unit, port, fmt, ...) PORT_PRINTK(NOTICE, "", xbus, unit, port, fmt, ## __VA_ARGS__)
#define PORT_ERR(xbus, unit, port, fmt, ...) PORT_PRINTK(ERR, "", xbus, unit, port, fmt, ## __VA_ARGS__)
/*
* Bits for debug
@@ -115,98 +94,63 @@ void dump_poll(int debug, const char *msg, int poll);
static inline char *rxsig2str(enum dahdi_rxsig sig)
{
switch (sig) {
case DAHDI_RXSIG_ONHOOK:
return "ONHOOK";
case DAHDI_RXSIG_OFFHOOK:
return "OFFHOOK";
case DAHDI_RXSIG_START:
return "START";
case DAHDI_RXSIG_RING:
return "RING";
case DAHDI_RXSIG_INITIAL:
return "INITIAL";
switch(sig) {
case DAHDI_RXSIG_ONHOOK: return "ONHOOK";
case DAHDI_RXSIG_OFFHOOK: return "OFFHOOK";
case DAHDI_RXSIG_START: return "START";
case DAHDI_RXSIG_RING: return "RING";
case DAHDI_RXSIG_INITIAL: return "INITIAL";
}
return "Unknown rxsig";
}
static inline char *txsig2str(enum dahdi_txsig sig)
{
switch (sig) {
case DAHDI_TXSIG_ONHOOK:
return "TXSIG_ONHOOK";
case DAHDI_TXSIG_OFFHOOK:
return "TXSIG_OFFHOOK";
case DAHDI_TXSIG_START:
return "TXSIG_START";
case DAHDI_TXSIG_KEWL:
return "TXSIG_KEWL"; /* Drop battery if possible */
case DAHDI_TXSIG_TOTAL:
break;
switch(sig) {
case DAHDI_TXSIG_ONHOOK: return "TXSIG_ONHOOK";
case DAHDI_TXSIG_OFFHOOK: return "TXSIG_OFFHOOK";
case DAHDI_TXSIG_START: return "TXSIG_START";
case DAHDI_TXSIG_KEWL: return "TXSIG_KEWL"; /* Drop battery if possible */
case DAHDI_TXSIG_TOTAL: break;
}
return "Unknown txsig";
}
static inline char *event2str(int event)
{
switch (event) {
case DAHDI_EVENT_NONE:
return "NONE";
case DAHDI_EVENT_ONHOOK:
return "ONHOOK";
case DAHDI_EVENT_RINGOFFHOOK:
return "RINGOFFHOOK";
case DAHDI_EVENT_WINKFLASH:
return "WINKFLASH";
case DAHDI_EVENT_ALARM:
return "ALARM";
case DAHDI_EVENT_NOALARM:
return "NOALARM";
case DAHDI_EVENT_ABORT:
return "ABORT";
case DAHDI_EVENT_OVERRUN:
return "OVERRUN";
case DAHDI_EVENT_BADFCS:
return "BADFCS";
case DAHDI_EVENT_DIALCOMPLETE:
return "DIALCOMPLETE";
case DAHDI_EVENT_RINGERON:
return "RINGERON";
case DAHDI_EVENT_RINGEROFF:
return "RINGEROFF";
case DAHDI_EVENT_HOOKCOMPLETE:
return "HOOKCOMPLETE";
case DAHDI_EVENT_BITSCHANGED:
return "BITSCHANGED";
case DAHDI_EVENT_PULSE_START:
return "PULSE_START";
case DAHDI_EVENT_TIMER_EXPIRED:
return "TIMER_EXPIRED";
case DAHDI_EVENT_TIMER_PING:
return "TIMER_PING";
case DAHDI_EVENT_POLARITY:
return "POLARITY";
switch(event) {
case DAHDI_EVENT_NONE: return "NONE";
case DAHDI_EVENT_ONHOOK: return "ONHOOK";
case DAHDI_EVENT_RINGOFFHOOK: return "RINGOFFHOOK";
case DAHDI_EVENT_WINKFLASH: return "WINKFLASH";
case DAHDI_EVENT_ALARM: return "ALARM";
case DAHDI_EVENT_NOALARM: return "NOALARM";
case DAHDI_EVENT_ABORT: return "ABORT";
case DAHDI_EVENT_OVERRUN: return "OVERRUN";
case DAHDI_EVENT_BADFCS: return "BADFCS";
case DAHDI_EVENT_DIALCOMPLETE: return "DIALCOMPLETE";
case DAHDI_EVENT_RINGERON: return "RINGERON";
case DAHDI_EVENT_RINGEROFF: return "RINGEROFF";
case DAHDI_EVENT_HOOKCOMPLETE: return "HOOKCOMPLETE";
case DAHDI_EVENT_BITSCHANGED: return "BITSCHANGED";
case DAHDI_EVENT_PULSE_START: return "PULSE_START";
case DAHDI_EVENT_TIMER_EXPIRED: return "TIMER_EXPIRED";
case DAHDI_EVENT_TIMER_PING: return "TIMER_PING";
case DAHDI_EVENT_POLARITY: return "POLARITY";
}
return "Unknown event";
}
static inline char *hookstate2str(int hookstate)
{
switch (hookstate) {
case DAHDI_ONHOOK:
return "DAHDI_ONHOOK";
case DAHDI_START:
return "DAHDI_START";
case DAHDI_OFFHOOK:
return "DAHDI_OFFHOOK";
case DAHDI_WINK:
return "DAHDI_WINK";
case DAHDI_FLASH:
return "DAHDI_FLASH";
case DAHDI_RING:
return "DAHDI_RING";
case DAHDI_RINGOFF:
return "DAHDI_RINGOFF";
switch(hookstate) {
case DAHDI_ONHOOK: return "DAHDI_ONHOOK";
case DAHDI_START: return "DAHDI_START";
case DAHDI_OFFHOOK: return "DAHDI_OFFHOOK";
case DAHDI_WINK: return "DAHDI_WINK";
case DAHDI_FLASH: return "DAHDI_FLASH";
case DAHDI_RING: return "DAHDI_RING";
case DAHDI_RINGOFF: return "DAHDI_RINGOFF";
}
return "Unknown hookstate";
}
@@ -215,42 +159,25 @@ static inline char *hookstate2str(int hookstate)
static inline char *sig2str(int sig)
{
switch (sig) {
case DAHDI_SIG_FXSLS:
return "FXSLS";
case DAHDI_SIG_FXSKS:
return "FXSKS";
case DAHDI_SIG_FXSGS:
return "FXSGS";
case DAHDI_SIG_FXOLS:
return "FXOLS";
case DAHDI_SIG_FXOKS:
return "FXOKS";
case DAHDI_SIG_FXOGS:
return "FXOGS";
case DAHDI_SIG_EM:
return "E&M";
case DAHDI_SIG_EM_E1:
return "E&M-E1";
case DAHDI_SIG_CLEAR:
return "Clear";
case DAHDI_SIG_HDLCRAW:
return "HDLCRAW";
case DAHDI_SIG_HDLCFCS:
return "HDLCFCS";
case DAHDI_SIG_HDLCNET:
return "HDLCNET";
case DAHDI_SIG_SLAVE:
return "Slave";
case DAHDI_SIG_CAS:
return "CAS";
case DAHDI_SIG_DACS:
return "DACS";
case DAHDI_SIG_DACS_RBS:
return "DACS+RBS";
case DAHDI_SIG_SF:
return "SF (ToneOnly)";
case DAHDI_SIG_NONE:
break;
case DAHDI_SIG_FXSLS: return "FXSLS";
case DAHDI_SIG_FXSKS: return "FXSKS";
case DAHDI_SIG_FXSGS: return "FXSGS";
case DAHDI_SIG_FXOLS: return "FXOLS";
case DAHDI_SIG_FXOKS: return "FXOKS";
case DAHDI_SIG_FXOGS: return "FXOGS";
case DAHDI_SIG_EM: return "E&M";
case DAHDI_SIG_EM_E1: return "E&M-E1";
case DAHDI_SIG_CLEAR: return "Clear";
case DAHDI_SIG_HDLCRAW: return "HDLCRAW";
case DAHDI_SIG_HDLCFCS: return "HDLCFCS";
case DAHDI_SIG_HDLCNET: return "HDLCNET";
case DAHDI_SIG_SLAVE: return "Slave";
case DAHDI_SIG_CAS: return "CAS";
case DAHDI_SIG_DACS: return "DACS";
case DAHDI_SIG_DACS_RBS: return "DACS+RBS";
case DAHDI_SIG_SF: return "SF (ToneOnly)";
case DAHDI_SIG_NONE:
break;
}
return "Unconfigured";
}
@@ -258,25 +185,18 @@ static inline char *sig2str(int sig)
static inline char *alarmbit2str(int alarmbit)
{
/* from dahdi/kernel.h */
switch (1 << alarmbit) {
case DAHDI_ALARM_NONE:
return "NONE";
case DAHDI_ALARM_RECOVER:
return "RECOVER";
case DAHDI_ALARM_LOOPBACK:
return "LOOPBACK";
case DAHDI_ALARM_YELLOW:
return "YELLOW";
case DAHDI_ALARM_RED:
return "RED";
case DAHDI_ALARM_BLUE:
return "BLUE";
case DAHDI_ALARM_NOTOPEN:
return "NOTOPEN";
switch(1 << alarmbit) {
case DAHDI_ALARM_NONE: return "NONE";
case DAHDI_ALARM_RECOVER: return "RECOVER";
case DAHDI_ALARM_LOOPBACK: return "LOOPBACK";
case DAHDI_ALARM_YELLOW: return "YELLOW";
case DAHDI_ALARM_RED: return "RED";
case DAHDI_ALARM_BLUE: return "BLUE";
case DAHDI_ALARM_NOTOPEN: return "NOTOPEN";
}
return "UNKNOWN";
}
void alarm2str(int alarm, char *buf, int buflen);
#endif /* DAHDI_DEBUG_H */
#endif /* DAHDI_DEBUG_H */

View File

@@ -51,7 +51,7 @@ BEGIN { $init_dir = dirname($0); unshift(@INC, "$init_dir"); }
use XppConfig $init_dir;
my $unit_id;
my %opts;
my $eeprom_release_201 = 0;
my $vbat_48 = 0;
getopts('o:', \%opts);
@@ -94,7 +94,7 @@ if (-t STDERR) {
}
logit "XBUS_MODEL_STRING='$ENV{XBUS_MODEL_STRING}'";
if ($ENV{XBUS_MODEL_STRING} =~ m{.*/.*/201}) {
$eeprom_release_201 = 1;
$vbat_48 = 1;
}
$chipregs = sprintf "/sys/bus/xpds/devices/%02d:%1d:0/chipregs",
$ENV{XBUS_NUMBER}, $ENV{UNIT_NUMBER};
@@ -292,8 +292,8 @@ sub init_indirect_registers() {
}
sub init_early_direct_regs() {
my $lbv = ($eeprom_release_201) ? "20" : "10";
my $vcm = ($eeprom_release_201) ? "02" : "03";
my $lbv = ($vbat_48) ? "20" : "10";
my $vcm = ($vbat_48) ? "02" : "03";
return write_to_slic_file("#
* WD 08 00 # Audio Path Loopback Control

View File

@@ -7,9 +7,7 @@ static int mmap_match(struct device *dev, struct device_driver *driver)
{
return !strncmp(dev_name(dev), driver->name, strlen(driver->name));
}
static int mmap_uevent(struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
static int mmap_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
{
envp[0] = buffer;
envp[1] = NULL;
@@ -35,6 +33,8 @@ static struct device mmap_bus = {
.release = mmap_bus_release,
};
int register_mmap_device(struct mmap_device *dev)
{
dev->dev.bus = &mmap_bus_type;
@@ -43,12 +43,12 @@ int register_mmap_device(struct mmap_device *dev)
strncpy(dev->dev.bus_id, dev->name, BUS_ID_SIZE);
return device_register(&dev->dev);
}
EXPORT_SYMBOL(register_mmap_device);
void unregister_mmap_device(struct mmap_device *dev)
{
device_unregister(&dev->dev);
}
EXPORT_SYMBOL(register_mmap_device);
EXPORT_SYMBOL(unregister_mmap_device);
int register_mmap_driver(struct mmap_driver *driver)
@@ -56,12 +56,12 @@ int register_mmap_driver(struct mmap_driver *driver)
driver->driver.bus = &mmap_bus_type;
return driver_register(&driver->driver);
}
EXPORT_SYMBOL(register_mmap_driver);
void unregister_mmap_driver(struct mmap_driver *driver)
{
driver_unregister(&driver->driver);
}
EXPORT_SYMBOL(register_mmap_driver);
EXPORT_SYMBOL(unregister_mmap_driver);
int register_mmap_bus(void)
@@ -78,13 +78,13 @@ bus_reg:
bus_type_reg:
return ret;
}
EXPORT_SYMBOL(register_mmap_bus);
void unregister_mmap_bus(void)
{
device_unregister(&mmap_bus);
bus_unregister(&mmap_bus_type);
}
EXPORT_SYMBOL(register_mmap_bus);
EXPORT_SYMBOL(unregister_mmap_bus);
MODULE_AUTHOR("Alexander Landau <landau.alex@gmail.com>");

View File

@@ -19,13 +19,11 @@
#include "xframe_queue.h"
/* Check at compile time that sizeof(xframe_t) is a multiple of 4 */
typedef char
sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) ==
0) * 2 - 1];
typedef char sizeof_xframe_t_should_be_divisible_by_4[((sizeof(xframe_t) % 4) == 0) * 2 - 1];
#define ssync() __builtin_bfin_ssync()
//#define AB_IN_BUF PF5
//#define AB_IN_BUF PF5
/* firmware pins */
#define DATA PG8
#define NCONFIG PG9
@@ -35,13 +33,13 @@ typedef char
#ifdef DEBUG_VIA_GPIO
/*
* For debugging we can use the following two pins.
* For debugging we can use the following two pins.
* These two pins are not used *after initialization*
*/
#define DEBUG_GPIO1 CONF_DONE
#define DEBUG_GPIO2 NSTATUS
static int rx_intr_counter;
static int rx_intr_counter;
#endif
#define FPGA_RX_IRQ IRQ_PF7
@@ -51,15 +49,9 @@ static int rx_intr_counter;
#define END_OF_FRAME 0x0001
#define GET_LEN 0x0002
#define START_RD_BURST 0x0008
/* stand alone Astribank without USB (Asterisk BlackFin Mode) */
#define AS_BF_MODE 0x0010
/*
* all data between Astribank and USB routed
* thru BF(EchoCanceler BlackFin Mode)
*/
#define EC_BF_MODE 0x0020
/* Astribank worke with USB only (no BlackFin Mode) */
#define NO_BF_MODE 0x0040
#define AS_BF_MODE 0x0010 //stand alone Astribank without USB (Asterisk BlackFin Mode)
#define EC_BF_MODE 0x0020 //all data between Astribank and USB routed thru BF(EchoCanceler BlackFin Mode)
#define NO_BF_MODE 0x0040 //Astribank worke with USB only (no BlackFin Mode)
#define SET_XA_DIR 0x0080
#define GET_XPD_STS 0x0100
#define GET_CHECKSUM 0x0200
@@ -88,8 +80,9 @@ static void print_buffer(const char *msg, const char *buf, int len)
{
int i;
printk(KERN_ERR "%s", msg);
for (i = 0; i < len; i++)
for (i = 0; i < len; i++) {
printk("%02X ", (unsigned char)buf[i]);
}
printk("\n");
}
@@ -103,8 +96,7 @@ static void update_counter(struct counter *c, struct timeval *tv1)
c->intr_min = diff;
if (c->intr_max < diff)
c->intr_max = diff;
c->intr_avg =
(c->intr_avg * c->intr_count + diff) / (c->intr_count + 1);
c->intr_avg = (c->intr_avg*c->intr_count + diff) / (c->intr_count+1);
c->intr_count++;
}
@@ -113,7 +105,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
unsigned short rxcnt;
xbus_t *xbus;
xframe_t *xframe;
__u8 *buf;
byte *buf;
bool in_use = 0;
struct timeval tv1;
@@ -123,7 +115,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
xbus = xbus_num(global_xbus->num);
BUG_ON(!xbus);
if (!XBUS_GET(xbus)) {
if(!XBUS_GET(xbus)) {
if (printk_ratelimit())
XBUS_ERR(xbus, "Dropping packet. Is shutting down.\n");
goto out;
@@ -137,7 +129,7 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
NOTICE("Got %d bytes\n", rxcnt);
goto out;
}
if (rxcnt >= XFRAME_DATASIZE) {
if(rxcnt >= XFRAME_DATASIZE) {
if (printk_ratelimit())
ERR("Bad rxcnt=%d\n", rxcnt);
goto out;
@@ -161,22 +153,18 @@ static irqreturn_t xpp_mmap_rx_irq(int irq, void *dev_id)
outw(START_RD_BURST, FPGA_BASE_ADDR + 4);
insw((unsigned long)FPGA_BASE_ADDR, buf, rxcnt / 2);
#if 0
for (count = 0; count < rxcnt; count += 2) {
for (count = 0; count < rxcnt; count+=2) {
unsigned short v = inw(FPGA_BASE_ADDR);
buf[count] = v & 0xFF;
buf[count + 1] = v >> 8;
buf[count+1] = v >> 8;
}
#endif
if (rxcnt & 1)
buf[rxcnt - 1] = inw(FPGA_BASE_ADDR);
/*
* Sanity check: length of first packet in frame
* should be no more than the frame length
*/
if (((buf[0] | (buf[1] << 8)) & 0x3FF) > rxcnt) {
if (rxcnt & 1)
buf[rxcnt-1] = inw(FPGA_BASE_ADDR);
/* Sanity check: length of first packet in frame should be no more than the frame length */
if (((buf[0] | (buf[1]<<8)) & 0x3FF) > rxcnt) {
if (printk_ratelimit()) {
ERR("Packet len=%d, frame len=%d\n",
(buf[0] | (buf[1] << 8)) & 0x3FF, rxcnt);
ERR("Packet len=%d, frame len=%d\n", (buf[0] | (buf[1]<<8)) & 0x3FF, rxcnt);
print_buffer("16 bytes of packet: ", buf, 16);
}
goto free;
@@ -211,7 +199,7 @@ static void send_buffer(unsigned char *buf, unsigned long len)
print_buffer("Sent: ", buf, len);
outsw((unsigned long)FPGA_BASE_ADDR, buf, len / 2);
if (len & 1)
outw((unsigned short)buf[len - 1], FPGA_BASE_ADDR);
outw((unsigned short)buf[len-1], FPGA_BASE_ADDR);
outw(END_OF_FRAME, FPGA_BASE_ADDR + 4);
}
@@ -270,10 +258,7 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
if (pcm && pcm_in_pool_count >= 1) {
static int rate_limit;
if ((rate_limit++ % 1000) == 0)
XBUS_ERR(xbus,
"Dropped PCM xframe "
"(pcm_in_pool_count=%d).\n",
pcm_in_pool_count);
XBUS_ERR(xbus, "Dropped PCM xframe (pcm_in_pool_count=%d).\n", pcm_in_pool_count);
FREE_SEND_XFRAME(xbus, xframe);
pcm_dropped++;
} else {
@@ -281,9 +266,7 @@ static int xframe_send_common(xbus_t *xbus, xframe_t *xframe, bool pcm)
static int rate_limit;
spin_unlock_irqrestore(&tx_ready_lock, flags);
if ((rate_limit++ % 1000) == 0)
XBUS_ERR(xbus,
"Dropped xframe. "
"Cannot enqueue.\n");
XBUS_ERR(xbus, "Dropped xframe. Cannot enqueue.\n");
FREE_SEND_XFRAME(xbus, xframe);
return -E2BIG;
}
@@ -301,12 +284,10 @@ static xframe_t *alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
if (!xframe) {
static int rate_limit;
if ((rate_limit++ % 1000) < 5)
XBUS_ERR(xbus, "frame allocation failed (%d)\n",
rate_limit);
XBUS_ERR(xbus, "frame allocation failed (%d)\n", rate_limit);
return NULL;
}
xframe_init(xbus, xframe, ((__u8 *)xframe) + sizeof(xframe_t),
XFRAME_DATASIZE, xbus);
xframe_init(xbus, xframe, ((byte*)xframe) + sizeof(xframe_t), XFRAME_DATASIZE, xbus);
return xframe;
}
@@ -335,26 +316,28 @@ static struct xbus_ops xmmap_ops = {
static int fill_proc_queue(char *p, struct xframe_queue *q)
{
int len;
int len;
len = sprintf(p,
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d "
"worst_lag %02ld.%ld ms\n",
q->name, q->steady_state_count, q->count, q->max_count,
q->worst_count, q->overflows, q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
"%-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
q->name,
q->steady_state_count,
q->count,
q->max_count,
q->worst_count,
q->overflows,
q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
xframe_queue_clearstats(q);
return len;
}
static int fill_proc_counter(char *p, struct counter *c)
{
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min,
c->intr_max, c->intr_avg, c->intr_count);
return sprintf(p, "min=%ld\nmax=%ld\navg=%ld\ncount=%ld\n", c->intr_min, c->intr_max, c->intr_avg, c->intr_count);
}
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
len += fill_proc_queue(page + len, &txpool);
@@ -364,7 +347,7 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
len += fill_proc_counter(page + len, &rx_counter);
len += sprintf(page + len, "\ntx_counter:\n");
len += fill_proc_counter(page + len, &tx_counter);
if (len <= off + count) {
if (len <= off+count) {
*eof = 1;
tx_counter.intr_min = rx_counter.intr_min = INT_MAX;
tx_counter.intr_max = rx_counter.intr_max = 0;
@@ -380,15 +363,14 @@ static int xpp_mmap_proc_read(char *page, char **start, off_t off, int count,
return len;
}
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer,
unsigned long count, void *data)
static int xpp_mmap_proc_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
int i = 0;
char *txchunk, *p, *endp;
if (count >= XFRAME_DATASIZE * 3 + 10)
if (count >= XFRAME_DATASIZE*3+10)
return -EINVAL;
p = txchunk = kmalloc(count + 1, GFP_KERNEL);
p = txchunk = kmalloc(count+1, GFP_KERNEL);
if (copy_from_user(txchunk, buffer, count)) {
count = -EFAULT;
goto out;
@@ -397,15 +379,13 @@ static int xpp_mmap_proc_write(struct file *file, const char __user *buffer,
while (*p) {
unsigned long value;
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
p++;
if (*p == '\0')
break;
while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++;
if (*p == '\0') break;
value = simple_strtoul(p, &endp, 16);
if (endp == p || value > 0xFF) {
INFO("%s: Bad input\n", __func__);
count = -EINVAL;
goto out;
INFO("%s: Bad input\n", __FUNCTION__);
count = -EINVAL;
goto out;
}
p = endp;
txchunk[i++] = (char)value;
@@ -419,8 +399,8 @@ out:
static struct mmap_driver astribank_driver = {
.module = THIS_MODULE,
.driver = {
.name = "xpp_mmap",
},
.name = "xpp_mmap",
},
};
static struct mmap_device astribank_dev = {
@@ -428,52 +408,42 @@ static struct mmap_device astribank_dev = {
.driver = &astribank_driver,
};
static int __init xpp_mmap_load_fpga(u8 * data, size_t size)
static int __init xpp_mmap_load_fpga(u8 *data, size_t size)
{
size_t i;
/* set data, nconfig and dclk to port out */
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK);
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DATA | NCONFIG | DCLK); //set data, nconfig and dclk to port out
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DATA | NCONFIG | DCLK));
/* set conf_done and nstatus to port in */
bfin_write_PORTGIO_DIR(
bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS));
bfin_write_PORTGIO_INEN(
bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK));
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~(CONF_DONE | NSTATUS));//set conf_done and nstatus to port in
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DATA | NCONFIG | DCLK));
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() | CONF_DONE | NSTATUS);
/* reset fpga during configuration holds nCONFIG low */
bfin_write_PORTGIO_CLEAR(NCONFIG);
udelay(40); /* Tcfg ~40us delay */
/* transition nCONFIG to high - reset end. */
bfin_write_PORTGIO_SET(NCONFIG);
udelay(40); /* Tcf2ck ~40us delay */
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
udelay(40); //Tcfg ~40us delay
bfin_write_PORTGIO_SET(NCONFIG); //transition nCONFIG to high - reset end.
udelay(40); //Tcf2ck ~40us delay
if (!(bfin_read_PORTGIO() & NSTATUS))
return -EIO; /* report reset faill - Tcf2st1 pass */
return -EIO; //report reset faill - Tcf2st1 pass
#if 0
if (!(bfin_read_PORTGIO() & CONF_DONE))
return -EIO;
#endif
bfin_write_PORTGIO_CLEAR(DCLK);
for (i = 0; i < size; i++) { /* loop EP2OUT buffer data to FPGA */
for (i=0; i<size; i++) { // loop EP2OUT buffer data to FPGA
int j;
u8 __u8 = data[i];
/*
* Send the configuration data through the DATA0 pin
* one bit at a time.
*/
for (j = 0; j < 8; j++)
u8 byte = data[i];
for (j=0; j<8; j++) //send the configuration data through the DATA0 pin one bit at a time.
{
if (__u8 & 1)
if (byte & 1)
bfin_write_PORTGIO_SET(DATA);
else
bfin_write_PORTGIO_CLEAR(DATA);
__u8 >>= 1;
byte >>= 1;
bfin_write_PORTGIO_SET(DCLK);
bfin_write_PORTGIO_CLEAR(DCLK);
}
if (!(bfin_read_PORTGIO() & NSTATUS))
return -EIO; /* check the nSTATUS */
return -EIO; //check the nSTATUS
}
bfin_write_PORTGIO_CLEAR(DATA);
udelay(1);
@@ -485,29 +455,20 @@ static int __init xpp_mmap_load_fpga(u8 * data, size_t size)
* some pins that were used only during initialization
* to be used for debugging from now on.
*/
/* set to port out */
bfin_write_PORTGIO_DIR(
bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2);
bfin_write_PORTG_FER(bfin_read_PORTG_FER() &
~(DEBUG_GPIO1 | DEBUG_GPIO2));
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() &
~(DEBUG_GPIO1 | DEBUG_GPIO2));
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() | DEBUG_GPIO1 | DEBUG_GPIO2); //set to port out
bfin_write_PORTG_FER(bfin_read_PORTG_FER() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~(DEBUG_GPIO1 | DEBUG_GPIO2));
#endif
udelay(40); /* tCD2UM - CONF_DONE high to user mode */
udelay(40); //tCD2UM - CONF_DONE high to user mode
return 0;
}
static void __exit xpp_mmap_unload_fpga(void)
{
/* reset fpga during configuration holds nCONFIG low */
bfin_write_PORTGIO_CLEAR(NCONFIG);
udelay(40); /* Tcfg ~40us delay */
/* disable output pin */
bfin_write_PORTGIO_DIR(
bfin_read_PORTGIO_DIR() & ~(DATA | NCONFIG | DCLK));
/* disable input buffer */
bfin_write_PORTGIO_INEN(
bfin_read_PORTGIO_INEN() & ~(CONF_DONE | NSTATUS));
bfin_write_PORTGIO_CLEAR(NCONFIG); //reset fpga during configuration holds nCONFIG low
udelay(40); //Tcfg ~40us delay
bfin_write_PORTGIO_DIR(bfin_read_PORTGIO_DIR() & ~( DATA | NCONFIG | DCLK)); //disable output pin
bfin_write_PORTGIO_INEN(bfin_read_PORTGIO_INEN() & ~( CONF_DONE | NSTATUS));//disable input buffer
INFO("FPGA Firmware unloaded\n");
}
@@ -515,8 +476,7 @@ static int __init xpp_mmap_load_firmware(void)
{
const struct firmware *fw;
int ret;
if ((ret =
request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
if ((ret = request_firmware(&fw, "astribank.bin", &astribank_dev.dev)) < 0)
return ret;
xpp_mmap_load_fpga(fw->data, fw->size);
release_firmware(fw);
@@ -538,33 +498,29 @@ static int __init xpp_mmap_init(void)
ERR("xpp_mmap_load_firmware() failed, errno=%d\n", ret);
goto fail_fw;
}
if ((ret =
request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING,
"xpp_mmap_rx", NULL)) < 0) {
if ((ret = request_irq(FPGA_RX_IRQ, xpp_mmap_rx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_rx", NULL)) < 0) {
ERR("Unable to attach to RX interrupt %d\n", FPGA_RX_IRQ);
goto fail_irq_rx;
}
if ((ret =
request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING,
"xpp_mmap_tx", NULL)) < 0) {
if ((ret = request_irq(FPGA_TX_IRQ, xpp_mmap_tx_irq, IRQF_TRIGGER_RISING, "xpp_mmap_tx", NULL)) < 0) {
ERR("Unable to attach to TX interrupt %d\n", FPGA_TX_IRQ);
goto fail_irq_tx;
}
if (!request_region((resource_size_t) FPGA_BASE_ADDR, 8, "xpp_mmap")) {
if (!request_region((resource_size_t)FPGA_BASE_ADDR, 8, "xpp_mmap")) {
ERR("Unable to request memory region at %p\n", FPGA_BASE_ADDR);
goto fail_region;
}
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
outw(AS_BF_MODE, FPGA_BASE_ADDR + 4);
xframe_cache =
kmem_cache_create("xframe_cache",
sizeof(xframe_t) + XFRAME_DATASIZE, 0, 0,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 23)
NULL,
xframe_cache = kmem_cache_create("xframe_cache",
sizeof(xframe_t) + XFRAME_DATASIZE,
0, 0,
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
NULL,
#endif
NULL);
if (!xframe_cache) {
NULL);
if(!xframe_cache) {
ret = -ENOMEM;
goto fail_cache;
}
@@ -576,11 +532,9 @@ static int __init xpp_mmap_init(void)
}
strncpy(global_xbus->connector, "mmap", XBUS_DESCLEN);
strncpy(global_xbus->label, "mmap:0", LABEL_SIZE);
xframe_queue_init(&txpool, 10, 200, "mmap_txpool", global_xbus);
if (!
(proc_entry =
create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
if (!(proc_entry = create_proc_entry("xpp_mmap", 0, global_xbus->proc_xbus_dir))) {
ERR("create_proc_entry() failed\n");
ret = -EINVAL;
goto fail_proc;
@@ -598,7 +552,7 @@ fail_proc:
fail_xbus:
kmem_cache_destroy(xframe_cache);
fail_cache:
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
fail_region:
free_irq(FPGA_TX_IRQ, NULL);
fail_irq_tx:
@@ -625,7 +579,7 @@ static void __exit xpp_mmap_exit(void)
xbus_disconnect(xbus);
kmem_cache_destroy(xframe_cache);
release_region((resource_size_t) FPGA_BASE_ADDR, 8);
release_region((resource_size_t)FPGA_BASE_ADDR, 8);
free_irq(FPGA_RX_IRQ, NULL);
free_irq(FPGA_TX_IRQ, NULL);

View File

@@ -20,26 +20,31 @@
*
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
# warning "This module is tested only with 2.6 kernels"
#endif
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/parport.h>
#include "parport_debug.h"
static struct parport *debug_sync_parport;
static int parport_toggles[8]; /* 8 bit flip-flop */
static struct parport *debug_sync_parport = NULL;
static int parport_toggles[8]; /* 8 bit flip-flop */
void flip_parport_bit(unsigned char bitnum)
{
static unsigned char last_value;
static unsigned char last_value;
DEFINE_SPINLOCK(lock);
unsigned long flags;
unsigned char mask;
unsigned char value;
unsigned long flags;
unsigned char mask;
unsigned char value;
if (!debug_sync_parport) {
if (printk_ratelimit()) {
if(!debug_sync_parport) {
if(printk_ratelimit()) {
printk(KERN_NOTICE "%s: no debug parallel port\n",
THIS_MODULE->name);
THIS_MODULE->name);
}
return;
}
@@ -47,7 +52,7 @@ void flip_parport_bit(unsigned char bitnum)
mask = 1 << bitnum;
spin_lock_irqsave(&lock, flags);
value = last_value & ~mask;
if (parport_toggles[bitnum] % 2) /* square wave */
if(parport_toggles[bitnum] % 2) /* square wave */
value |= mask;
last_value = value;
parport_toggles[bitnum]++;
@@ -58,11 +63,10 @@ EXPORT_SYMBOL(flip_parport_bit);
static void parport_attach(struct parport *port)
{
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name,
port->name);
if (debug_sync_parport) {
printk(KERN_INFO "%s: Using %s for debugging\n", THIS_MODULE->name, port->name);
if(debug_sync_parport) {
printk(KERN_ERR "%s: Using %s, ignore new attachment %s\n",
THIS_MODULE->name, debug_sync_parport->name, port->name);
THIS_MODULE->name, debug_sync_parport->name, port->name);
return;
}
parport_get_port(port);
@@ -72,16 +76,16 @@ static void parport_attach(struct parport *port)
static void parport_detach(struct parport *port)
{
printk(KERN_INFO "%s: Releasing %s\n", THIS_MODULE->name, port->name);
if (debug_sync_parport != port) {
if(debug_sync_parport != port) {
printk(KERN_ERR "%s: Using %s, ignore new detachment %s\n",
THIS_MODULE->name, debug_sync_parport->name, port->name);
THIS_MODULE->name, debug_sync_parport->name, port->name);
return;
}
parport_put_port(debug_sync_parport);
debug_sync_parport = NULL;
}
static struct parport_driver debug_parport_driver = {
static struct parport_driver debug_parport_driver = {
.name = "parport_debug",
.attach = parport_attach,
.detach = parport_detach,
@@ -89,7 +93,7 @@ static struct parport_driver debug_parport_driver = {
int __init parallel_dbg_init(void)
{
int ret;
int ret;
ret = parport_register_driver(&debug_parport_driver);
return ret;

View File

@@ -28,4 +28,4 @@ void flip_parport_bit(unsigned char bitnum);
#define flip_parport_bit(bitnum)
#endif
#endif /* PARPORT_DEBUG_H */
#endif /* PARPORT_DEBUG_H */

View File

@@ -3,35 +3,30 @@
int main(int argc, char *argv[])
{
size_t i;
for (i = 0; i < (sizeof(fxo_modes) / sizeof(struct fxo_mode)); i++) {
if (fxo_modes[i].name == NULL)
break;
int reg16 = 0, reg26 = 0, reg30 = 0, reg31 = 0x20;
char ring_osc[BUFSIZ] = "", ring_x[BUFSIZ] = "";
for (i=0; i<(sizeof(fxo_modes)/sizeof(struct fxo_mode)); i++) {
if (fxo_modes[i].name == NULL) break;
int reg16=0, reg26=0, reg30=0, reg31=0x20;
char ring_osc[BUFSIZ]="", ring_x[BUFSIZ] = "";
reg16 |= (fxo_modes[i].ohs << 6);
reg16 |= (fxo_modes[i].rz << 1);
reg16 |= (fxo_modes[i].rt);
reg26 |= (fxo_modes[i].dcv << 6);
reg26 |= (fxo_modes[i].mini << 4);
reg26 |= (fxo_modes[i].ilim << 1);
reg30 = (fxo_modes[i].acim);
reg31 |= (fxo_modes[i].ohs2 << 3);
if (fxo_modes[i].ring_osc)
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X",
fxo_modes[i].ring_osc);
snprintf(ring_osc, BUFSIZ, "ring_osc=%04X", fxo_modes[i].ring_osc);
if (fxo_modes[i].ring_x)
snprintf(ring_x, BUFSIZ, "ring_x=%04X",
fxo_modes[i].ring_x);
printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\t"
"reg31=%02X\t%s\t%s\n",
fxo_modes[i].name, reg16, reg26, reg30, reg31,
ring_osc, ring_x);
snprintf(ring_x, BUFSIZ, "ring_x=%04X", fxo_modes[i].ring_x);
printf("%-15s\treg16=%02X\treg26=%02X\treg30=%02X\treg31=%02X\t%s\t%s\n",
fxo_modes[i].name, reg16, reg26, reg30, reg31, ring_osc, ring_x);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -39,10 +39,10 @@ struct xbus_workqueue;
#ifdef __KERNEL__
struct xbus_ops {
int (*xframe_send_pcm) (xbus_t *xbus, xframe_t *xframe);
int (*xframe_send_cmd) (xbus_t *xbus, xframe_t *xframe);
xframe_t *(*alloc_xframe) (xbus_t *xbus, gfp_t gfp_flags);
void (*free_xframe) (xbus_t *xbus, xframe_t *xframe);
int (*xframe_send_pcm)(xbus_t *xbus, xframe_t *xframe);
int (*xframe_send_cmd)(xbus_t *xbus, xframe_t *xframe);
xframe_t *(*alloc_xframe)(xbus_t *xbus, gfp_t gfp_flags);
void (*free_xframe)(xbus_t *xbus, xframe_t *xframe);
};
/*
@@ -67,11 +67,19 @@ enum {
/* yucky, make an instance so we can size it... */
static struct xbus_counters {
char *name;
char *name;
} xbus_counters[] = {
C_(UNITS), C_(TX_XFRAME_PCM), C_(RX_XFRAME_PCM), C_(TX_PACK_PCM),
C_(RX_PACK_PCM), C_(TX_BYTES), C_(RX_BYTES),
C_(TX_PCM_FRAG), C_(RX_CMD), C_(TX_CMD),};
C_(UNITS),
C_(TX_XFRAME_PCM),
C_(RX_XFRAME_PCM),
C_(TX_PACK_PCM),
C_(RX_PACK_PCM),
C_(TX_BYTES),
C_(RX_BYTES),
C_(TX_PCM_FRAG),
C_(RX_CMD),
C_(TX_CMD),
};
#undef C_
@@ -91,17 +99,17 @@ enum xbus_state {
const char *xbus_statename(enum xbus_state st);
struct xbus_transport {
struct xbus_ops *ops;
void *priv;
struct device *transport_device;
ushort max_send_size;
enum xbus_state xbus_state;
unsigned long transport_flags;
spinlock_t state_lock;
atomic_t transport_refcount;
wait_queue_head_t transport_unused;
spinlock_t lock;
char model_string[MAX_ENV_STR];
struct xbus_ops *ops;
void *priv;
struct device *transport_device;
ushort max_send_size;
enum xbus_state xbus_state;
unsigned long transport_flags;
spinlock_t state_lock;
atomic_t transport_refcount;
wait_queue_head_t transport_unused;
spinlock_t lock;
char model_string[MAX_ENV_STR];
};
#define MAX_SEND_SIZE(xbus) ((xbus)->transport.max_send_size)
@@ -110,8 +118,7 @@ struct xbus_transport {
#define TRANSPORT_EXIST(xbus) ((xbus)->transport.ops != NULL)
#define XBUS_FLAG_CONNECTED 0
#define XBUS_FLAGS(xbus, flg) \
test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags))
#define XBUS_FLAGS(xbus, flg) test_bit(XBUS_FLAG_ ## flg, &((xbus)->transport.transport_flags))
struct xbus_ops *transportops_get(xbus_t *xbus);
void transportops_put(xbus_t *xbus);
@@ -120,39 +127,35 @@ void transportops_put(xbus_t *xbus);
* Encapsulate all poll related data of a single xbus.
*/
struct xbus_workqueue {
struct workqueue_struct *wq;
struct work_struct xpds_init_work;
bool xpds_init_done;
struct list_head card_list;
int num_units;
int num_units_initialized;
wait_queue_head_t wait_for_xpd_initialization;
spinlock_t worker_lock;
struct semaphore running_initialization;
struct workqueue_struct *wq;
struct work_struct xpds_init_work;
bool xpds_init_done;
struct list_head card_list;
int num_units;
int num_units_initialized;
wait_queue_head_t wait_for_xpd_initialization;
spinlock_t worker_lock;
struct semaphore running_initialization;
};
/*
* Allocate/Free an xframe from pools of empty xframes.
* Calls to {get, put}_xframe are wrapped in
* Calls to {get,put}_xframe are wrapped in
* the macros bellow, so we take/return it
* to the correct pool.
*/
xframe_t *get_xframe(struct xframe_queue *q);
void put_xframe(struct xframe_queue *q, xframe_t *xframe);
#define ALLOC_SEND_XFRAME(xbus) \
get_xframe(&(xbus)->send_pool)
#define ALLOC_RECV_XFRAME(xbus) \
get_xframe(&(xbus)->receive_pool)
#define FREE_SEND_XFRAME(xbus, xframe) \
put_xframe(&(xbus)->send_pool, (xframe))
#define FREE_RECV_XFRAME(xbus, xframe) \
put_xframe(&(xbus)->receive_pool, (xframe))
#define ALLOC_SEND_XFRAME(xbus) get_xframe(&(xbus)->send_pool)
#define ALLOC_RECV_XFRAME(xbus) get_xframe(&(xbus)->receive_pool)
#define FREE_SEND_XFRAME(xbus, xframe) put_xframe(&(xbus)->send_pool, (xframe))
#define FREE_RECV_XFRAME(xbus, xframe) put_xframe(&(xbus)->receive_pool, (xframe))
xbus_t *xbus_num(uint num);
xbus_t *get_xbus(const char *msg, uint num);
void put_xbus(const char *msg, xbus_t *xbus);
int refcount_xbus(xbus_t *xbus);
xbus_t *xbus_num(uint num);
xbus_t *get_xbus(const char *msg, uint num);
void put_xbus(const char *msg, xbus_t *xbus);
int refcount_xbus(xbus_t *xbus);
/*
* Echo canceller related data
@@ -160,17 +163,17 @@ int refcount_xbus(xbus_t *xbus);
#define ECHO_TIMESLOTS 128
struct echoops {
int (*ec_set) (xpd_t *xpd, int pos, bool on);
int (*ec_get) (xpd_t *xpd, int pos);
int (*ec_update) (xbus_t *xbus);
void (*ec_dump) (xbus_t *xbus);
int (*ec_set)(xpd_t *xpd, int pos, bool on);
int (*ec_get)(xpd_t *xpd, int pos);
int (*ec_update)(xbus_t *xbus);
void (*ec_dump)(xbus_t *xbus);
};
struct xbus_echo_state {
const struct echoops *echoops;
__u8 timeslots[ECHO_TIMESLOTS];
int xpd_idx;
struct device_attribute *da[MAX_XPDS];
const struct echoops *echoops;
byte timeslots[ECHO_TIMESLOTS];
int xpd_idx;
struct device_attribute *da[MAX_XPDS];
};
#define ECHOOPS(xbus) ((xbus)->echo_state.echoops)
#define EC_METHOD(name, xbus) (ECHOOPS(xbus)->name)
@@ -180,128 +183,125 @@ struct xbus_echo_state {
* An xbus is a transport layer for Xorcom Protocol commands
*/
struct xbus {
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
char busname[XBUS_NAMELEN]; /* set by xbus_new() */
/* low-level bus drivers set these 2 fields */
char connector[XBUS_DESCLEN];
char label[LABEL_SIZE];
__u8 revision; /* Protocol revision */
struct xbus_transport transport;
struct dahdi_device *ddev;
char connector[XBUS_DESCLEN];
char label[LABEL_SIZE];
byte revision; /* Protocol revision */
struct xbus_transport transport;
int num;
struct xpd *xpds[MAX_XPDS];
struct xbus_echo_state echo_state;
int num;
struct xpd *xpds[MAX_XPDS];
struct xbus_echo_state echo_state;
int command_tick_counter;
int usec_nosend; /* Firmware flow control */
struct xframe_queue command_queue;
wait_queue_head_t command_queue_empty;
int command_tick_counter;
int usec_nosend; /* Firmware flow control */
struct xframe_queue command_queue;
wait_queue_head_t command_queue_empty;
struct xframe_queue send_pool; /* empty xframes for send */
struct xframe_queue receive_pool; /* empty xframes for receive */
struct xframe_queue send_pool; /* empty xframes for send */
struct xframe_queue receive_pool; /* empty xframes for receive */
/* tasklet processing */
struct xframe_queue receive_queue;
struct tasklet_struct receive_tasklet;
int cpu_rcv_intr[NR_CPUS];
int cpu_rcv_tasklet[NR_CPUS];
struct xframe_queue receive_queue;
struct tasklet_struct receive_tasklet;
int cpu_rcv_intr[NR_CPUS];
int cpu_rcv_tasklet[NR_CPUS];
struct quirks {
unsigned int has_fxo:1;
unsigned int has_digital_span:1;
} quirks;
bool self_ticking;
enum sync_mode sync_mode;
} quirks;
bool self_ticking;
enum sync_mode sync_mode;
/* Managed by low-level drivers: */
enum sync_mode sync_mode_default;
struct timer_list command_timer;
unsigned int xbus_frag_count;
struct xframe_queue pcm_tospan;
enum sync_mode sync_mode_default;
struct timer_list command_timer;
unsigned int xbus_frag_count;
struct xframe_queue pcm_tospan;
struct xpp_ticker ticker; /* for tick rate */
struct xpp_drift drift; /* for tick offset */
struct xpp_ticker ticker; /* for tick rate */
struct xpp_drift drift; /* for tick offset */
atomic_t pcm_rx_counter;
unsigned int global_counter;
atomic_t pcm_rx_counter;
unsigned int global_counter;
/* Device-Model */
struct device astribank;
struct device astribank;
#define dev_to_xbus(dev) container_of(dev, struct xbus, astribank)
struct kref kref;
struct kref kref;
#define kref_to_xbus(k) container_of(k, struct xbus, kref)
spinlock_t lock;
spinlock_t lock;
/* PCM metrics */
struct timeval last_tx_sync;
struct timeval last_rx_sync;
unsigned long max_tx_sync;
unsigned long min_tx_sync;
unsigned long max_rx_sync;
unsigned long min_rx_sync;
unsigned long max_rx_process; /* packet processing time (usec) */
struct timeval last_tx_sync;
struct timeval last_rx_sync;
unsigned long max_tx_sync;
unsigned long min_tx_sync;
unsigned long max_rx_sync;
unsigned long min_rx_sync;
unsigned long max_rx_process; /* packet processing time (usec) */
#ifdef SAMPLE_TICKS
#define SAMPLE_SIZE 1000
int sample_ticks[SAMPLE_SIZE];
bool sample_running;
int sample_pos;
int sample_ticks[SAMPLE_SIZE];
bool sample_running;
int sample_pos;
#endif
struct xbus_workqueue worker;
struct xbus_workqueue worker;
/*
* Sync adjustment
*/
int sync_adjustment;
int sync_adjustment_offset;
long pll_updated_at;
int sync_adjustment;
int sync_adjustment_offset;
long pll_updated_at;
atomic_t num_xpds;
atomic_t num_xpds;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_xbus_dir;
struct proc_dir_entry *proc_xbus_summary;
struct proc_dir_entry *proc_xbus_dir;
struct proc_dir_entry *proc_xbus_summary;
#ifdef PROTOCOL_DEBUG
struct proc_dir_entry *proc_xbus_command;
struct proc_dir_entry *proc_xbus_command;
#endif
#endif
/* statistics */
int counters[XBUS_COUNTER_MAX];
int counters[XBUS_COUNTER_MAX];
};
#endif
#define XFRAME_MAGIC 123456L
struct xframe {
unsigned long xframe_magic;
struct list_head frame_list;
atomic_t frame_len;
xbus_t *xbus;
struct timeval tv_created;
struct timeval tv_queued;
struct timeval tv_submitted;
struct timeval tv_received;
unsigned long xframe_magic;
struct list_head frame_list;
atomic_t frame_len;
xbus_t *xbus;
struct timeval tv_created;
struct timeval tv_queued;
struct timeval tv_submitted;
struct timeval tv_received;
/* filled by transport layer */
size_t frame_maxlen;
__u8 *packets; /* max XFRAME_DATASIZE */
__u8 *first_free;
int usec_towait; /* prevent overflowing AB */
void *priv;
size_t frame_maxlen;
byte *packets; /* max XFRAME_DATASIZE */
byte *first_free;
int usec_towait; /* prevent overflowing AB */
void *priv;
};
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize,
void *priv);
void xframe_init(xbus_t *xbus, xframe_t *xframe, void *buf, size_t maxsize, void *priv);
#define XFRAME_LEN(frame) atomic_read(&(frame)->frame_len)
int xbus_core_init(void); /* Initializer */
void xbus_core_shutdown(void); /* Terminator */
int xbus_core_init(void); /* Initializer */
void xbus_core_shutdown(void); /* Terminator */
/* Frame handling */
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe,
int debug);
void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int debug);
int send_cmd_frame(xbus_t *xbus, xframe_t *xframe);
/*
@@ -315,45 +315,54 @@ xpacket_t *xframe_next_packet(xframe_t *xframe, int len);
/*
* Map: unit+subunit <--> index in xbus->xpds[]
*/
#define XPD_IDX(unit, subunit) ((unit) * MAX_SUBUNIT + (subunit))
#define XPD_IDX(unit,subunit) ((unit) * MAX_SUBUNIT + (subunit))
#define XBUS_UNIT(idx) ((idx) / MAX_SUBUNIT)
#define XBUS_SUBUNIT(idx) ((idx) % MAX_SUBUNIT)
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
int xbus_check_unique(xbus_t *xbus);
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size,
struct device *transport_device, void *priv);
void xbus_free(xbus_t *xbus);
int xbus_connect(xbus_t *xbus);
int xbus_activate(xbus_t *xbus);
void xbus_deactivate(xbus_t *xbus);
void xbus_disconnect(xbus_t *xbus);
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
int xbus_process_worker(xbus_t *xbus);
int waitfor_xpds(xbus_t *xbus, char *buf);
xpd_t *xpd_of(const xbus_t *xbus, int xpd_num);
xpd_t *xpd_byaddr(const xbus_t *xbus, uint unit, uint subunit);
int xbus_check_unique(xbus_t *xbus);
bool xbus_setstate(xbus_t *xbus, enum xbus_state newstate);
bool xbus_setflags(xbus_t *xbus, int flagbit, bool on);
xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *transport_device, void *priv);
void xbus_free(xbus_t *xbus);
int xbus_connect(xbus_t *xbus);
int xbus_activate(xbus_t *xbus);
void xbus_deactivate(xbus_t *xbus);
void xbus_disconnect(xbus_t *xbus);
void xbus_receive_xframe(xbus_t *xbus, xframe_t *xframe);
int xbus_process_worker(xbus_t *xbus);
int waitfor_xpds(xbus_t *xbus, char *buf);
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
int xbus_xpd_bind(xbus_t *xbus, xpd_t *xpd, int unit, int subunit);
int xbus_xpd_unbind(xbus_t *xbus, xpd_t *xpd);
/* sysfs */
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
void xpd_device_unregister(xpd_t *xpd);
int echocancel_xpd(xpd_t *xpd, int on);
int xpd_device_register(xbus_t *xbus, xpd_t *xpd);
void xpd_device_unregister(xpd_t *xpd);
int echocancel_xpd(xpd_t *xpd, int on);
int xbus_is_registered(xbus_t *xbus);
int xbus_register_dahdi_device(xbus_t *xbus);
void xbus_unregister_dahdi_device(xbus_t *xbus);
int xpp_driver_init(void);
void xpp_driver_exit(void);
int xbus_sysfs_transport_create(xbus_t *xbus);
void xbus_sysfs_transport_remove(xbus_t *xbus);
int xbus_sysfs_create(xbus_t *xbus);
void xbus_sysfs_remove(xbus_t *xbus);
int xpp_driver_init(void);
void xpp_driver_exit(void);
int xbus_sysfs_transport_create(xbus_t *xbus);
void xbus_sysfs_transport_remove(xbus_t *xbus);
int xbus_sysfs_create(xbus_t *xbus);
void xbus_sysfs_remove(xbus_t *xbus);
#ifdef OLD_HOTPLUG_SUPPORT_269
/* Copy from new kernels lib/kobject_uevent.c */
enum kobject_action {
KOBJ_ADD,
KOBJ_REMOVE,
KOBJ_CHANGE,
KOBJ_MOUNT,
KOBJ_UMOUNT,
KOBJ_OFFLINE,
KOBJ_ONLINE,
};
#endif
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
void astribank_uevent_send(xbus_t *xbus, enum kobject_action act);
#endif /* XBUS_CORE_H */
#endif /* XBUS_CORE_H */

File diff suppressed because it is too large Load Diff

View File

@@ -33,10 +33,10 @@
#ifdef __KERNEL__
enum sync_mode {
SYNC_MODE_NONE = 0x00,
SYNC_MODE_AB = 0x01, /* Astribank sync */
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
SYNC_MODE_QUERY = 0x80,
SYNC_MODE_NONE = 0x00,
SYNC_MODE_AB = 0x01, /* Astribank sync */
SYNC_MODE_PLL = 0x03, /* Adjust XPD's PLL according to HOST */
SYNC_MODE_QUERY = 0x80,
};
/*
@@ -46,7 +46,7 @@ enum sync_mode {
* time representations.
*/
struct xpp_timestamp {
struct timeval tv;
struct timeval tv;
};
/*
@@ -58,12 +58,12 @@ struct xpp_timestamp {
* from other dahdi devices).
*/
struct xpp_ticker { /* for rate calculation */
int count;
int cycle;
struct xpp_timestamp first_sample;
struct xpp_timestamp last_sample;
int tick_period; /* usec/tick */
spinlock_t lock;
int count;
int cycle;
struct xpp_timestamp first_sample;
struct xpp_timestamp last_sample;
int tick_period; /* usec/tick */
spinlock_t lock;
};
/*
@@ -71,65 +71,66 @@ struct xpp_ticker { /* for rate calculation */
* xbus ticker to a reference ticker.
*/
struct xpp_drift {
int delta_tick; /* from ref_ticker */
int lost_ticks; /* occurances */
int lost_tick_count;
int sync_inaccuracy;
struct xpp_timestamp last_lost_tick;
long delta_sum;
int offset_prev;
int offset_range;
int offset_min;
int offset_max;
int min_speed;
int max_speed;
spinlock_t lock;
int delta_tick; /* from ref_ticker */
int lost_ticks; /* occurances */
int lost_tick_count;
int sync_inaccuracy;
struct xpp_timestamp last_lost_tick;
long delta_sum;
int offset_prev;
int offset_range;
int offset_min;
int offset_max;
int min_speed;
int max_speed;
spinlock_t lock;
};
void xpp_drift_init(xbus_t *xbus);
static inline long usec_diff(const struct timeval *tv1,
const struct timeval *tv2)
static inline long usec_diff(const struct timeval *tv1, const struct timeval *tv2)
{
long diff_sec;
long diff_usec;
long diff_sec;
long diff_usec;
diff_sec = tv1->tv_sec - tv2->tv_sec;
diff_usec = tv1->tv_usec - tv2->tv_usec;
return diff_sec * 1000000 + diff_usec;
}
int xbus_pcm_init(void *top);
void xbus_pcm_shutdown(void);
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
int generic_timing_priority(xpd_t *xpd);
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
void fill_beep(u_char *buf, int num, int duration);
const char *sync_mode_name(enum sync_mode mode);
void xbus_set_command_timer(xbus_t *xbus, bool on);
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
int xbus_command_queue_tick(xbus_t *xbus);
void xbus_reset_counters(xbus_t *xbus);
void elect_syncer(const char *msg);
int exec_sync_command(const char *buf, size_t count);
int fill_sync_string(char *buf, size_t count);
int xbus_pcm_init(void *top);
void xbus_pcm_shutdown(void);
int send_pcm_frame(xbus_t *xbus, xframe_t *xframe);
void pcm_recompute(xpd_t *xpd, xpp_line_t tmp_pcm_mask);
void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe);
void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len);
void generic_card_pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask);
void generic_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack);
void generic_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack);
int generic_timing_priority(xpd_t *xpd);
int generic_echocancel_timeslot(xpd_t *xpd, int pos);
int generic_echocancel_setmask(xpd_t *xpd, xpp_line_t ec_mask);
void fill_beep(u_char *buf, int num, int duration);
const char *sync_mode_name(enum sync_mode mode);
void xbus_set_command_timer(xbus_t *xbus, bool on);
void xbus_request_sync(xbus_t *xbus, enum sync_mode mode);
void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift);
int xbus_command_queue_tick(xbus_t *xbus);
void xbus_reset_counters(xbus_t *xbus);
void elect_syncer(const char *msg);
int exec_sync_command(const char *buf, size_t count);
int fill_sync_string(char *buf, size_t count);
#ifdef DAHDI_SYNC_TICK
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
void dahdi_sync_tick(struct dahdi_span *span, int is_master);
#endif
#ifdef DEBUG_PCMTX
extern int pcmtx;
extern int pcmtx_chan;
extern int pcmtx;
extern int pcmtx_chan;
#endif
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#endif /* XBUS_PCM_H */
#endif /* XBUS_PCM_H */

File diff suppressed because it is too large Load Diff

View File

@@ -34,21 +34,18 @@
/* This is to enable user-space programs to include this. */
#include <stdint.h>
typedef uint8_t __u8;
typedef uint8_t __u8;
typedef uint32_t __u32;
#include <stdio.h>
#define DBG(fmt, ...) printf("DBG: %s: " fmt, __func__, ## __VA_ARGS__)
#define DBG(fmt, ...) printf("DBG: %s: " fmt, __FUNCTION__, ## __VA_ARGS__)
#define INFO(fmt, ...) printf("INFO: " fmt, ## __VA_ARGS__)
#define NOTICE(fmt, ...) printf("NOTICE: " fmt, ## __VA_ARGS__)
#define ERR(fmt, ...) printf("ERR: " fmt, ## __VA_ARGS__)
#define __user
struct list_head {
struct list_head *next;
struct list_head *prev;
};
struct list_head { struct list_head *next; struct list_head *prev; };
#endif
@@ -56,15 +53,15 @@ struct list_head {
#define ALL_LINES ((lineno_t)-1)
#ifndef BIT /* added in 2.6.24 */
#ifndef BIT /* added in 2.6.24 */
#define BIT(i) (1UL << (i))
#endif
#define BIT_SET(x, i) ((x) |= BIT(i))
#define BIT_CLR(x, i) ((x) &= ~BIT(i))
#define IS_SET(x, i) (((x) & BIT(i)) != 0)
#define BIT_SET(x,i) ((x) |= BIT(i))
#define BIT_CLR(x,i) ((x) &= ~BIT(i))
#define IS_SET(x,i) (((x) & BIT(i)) != 0)
#define BITMASK(i) (((u64)1 << (i)) - 1)
#define MAX_PROC_WRITE 100 /* Longest write allowed to our /proc files */
#define MAX_PROC_WRITE 100 /* Largest buffer we allow writing our /proc files */
#define CHANNELS_PERXPD 32 /* Depends on xpp_line_t and protocol fields */
#define MAX_SPANNAME 20 /* From dahdi/kernel.h */
@@ -80,8 +77,7 @@ struct list_head {
#define UNIT_BITS 3 /* Bit for Astribank unit number */
#define SUBUNIT_BITS 3 /* Bit for Astribank subunit number */
/* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */
#define MAX_UNIT (1 << UNIT_BITS)
#define MAX_UNIT (1 << UNIT_BITS) /* 1 FXS + 3 FXS/FXO | 1 BRI + 3 FXS/FXO */
#define MAX_SUBUNIT (1 << SUBUNIT_BITS) /* 8 port BRI */
/*
@@ -99,70 +95,74 @@ struct list_head {
#define VALID_XPD_NUM(x) ((x) < MAX_XPDS && (x) >= 0)
#define CHAN_BITS 5 /* 0-31 for E1 */
#define CHAN_BITS 5 /* 0-31 for E1 */
typedef char *charp;
typedef char *charp;
typedef unsigned char byte;
#ifdef __KERNEL__
/* Kernel versions... */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#define KMEM_CACHE_T kmem_cache_t
#else
#else
#define KMEM_CACHE_T struct kmem_cache
#endif
#endif
#define KZALLOC(size, gfp) my_kzalloc(size, gfp)
#define KZFREE(p) \
do { \
memset((p), 0, sizeof(*(p))); \
kfree(p); \
} while (0);
#define KZFREE(p) do { \
memset((p), 0, sizeof(*(p))); \
kfree(p); \
} while(0);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
#define DEVICE_ATTR_READER(name, dev, buf) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
ssize_t name(struct device *dev, \
struct device_attribute *attr, \
const char *buf, size_t count)
/*
* Hotplug replaced with uevent in 2.6.16
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
#define OLD_HOTPLUG_SUPPORT // for older kernels
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
#define OLD_HOTPLUG_SUPPORT_269// for way older kernels
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
#define DEVICE_ATTR_READER(name,dev,buf) \
ssize_t name(struct device *dev, struct device_attribute *attr, char *buf)
#define DEVICE_ATTR_WRITER(name,dev,buf, count) \
ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
#else
#define DEVICE_ATTR_READER(name, dev, buf) \
#define DEVICE_ATTR_READER(name,dev,buf) \
ssize_t name(struct device *dev, char *buf)
#define DEVICE_ATTR_WRITER(name, dev, buf, count) \
#define DEVICE_ATTR_WRITER(name,dev,buf, count) \
ssize_t name(struct device *dev, const char *buf, size_t count)
#endif
#define DRIVER_ATTR_READER(name, drv, buf) \
#define DRIVER_ATTR_READER(name,drv,buf) \
ssize_t name(struct device_driver *drv, char * buf)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
#define SET_PROC_DIRENTRY_OWNER(p) \
do { \
(p)->owner = THIS_MODULE; \
} while (0);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30)
#define SET_PROC_DIRENTRY_OWNER(p) do { (p)->owner = THIS_MODULE; } while(0);
#else
#define SET_PROC_DIRENTRY_OWNER(p) do { } while (0);
#define SET_PROC_DIRENTRY_OWNER(p) do { } while(0);
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
/* Also don't define this for later RHEL >= 5.2 . hex_asc is from the
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
/* Also don't define this for later RHEL >= 5.2 . hex_asc is from the
* same linux-2.6-net-infrastructure-updates-to-mac80211-iwl4965.patch
* as is the bool typedef. */
#if LINUX_VERSION_CODE != KERNEL_VERSION(2, 6, 18) || !defined(hex_asc)
typedef int bool;
#if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,18) || ! defined(hex_asc)
typedef int bool;
#endif
#endif
#else
typedef int bool;
typedef int bool;
#endif
typedef struct xbus xbus_t;
typedef struct xpd xpd_t;
typedef struct xframe xframe_t;
typedef struct xpacket xpacket_t;
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
typedef __u8 lineno_t;
typedef __u8 xportno_t;
typedef struct xbus xbus_t;
typedef struct xpd xpd_t;
typedef struct xframe xframe_t;
typedef struct xpacket xpacket_t;
typedef __u32 xpp_line_t; /* at most 31 lines for E1 */
typedef byte lineno_t;
typedef byte xportno_t;
#define PORT_BROADCAST 255
#endif /* XDEFS_H */
#endif /* XDEFS_H */

View File

@@ -7,9 +7,7 @@ extern int debug;
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags);
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe);
void xframe_queue_init(struct xframe_queue *q,
unsigned int steady_state_count, unsigned int max_count,
const char *name, void *priv)
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count, unsigned int max_count, const char *name, void *priv)
{
memset(q, 0, sizeof(*q));
spin_lock_init(&q->lock);
@@ -19,60 +17,61 @@ void xframe_queue_init(struct xframe_queue *q,
q->name = name;
q->priv = priv;
}
EXPORT_SYMBOL(xframe_queue_init);
void xframe_queue_clearstats(struct xframe_queue *q)
{
q->worst_count = 0;
//q->overflows = 0; /* Never clear overflows */
//q->overflows = 0; /* Never clear overflows */
q->worst_lag_usec = 0L;
}
EXPORT_SYMBOL(xframe_queue_clearstats);
static void __xframe_dump_queue(struct xframe_queue *q)
{
xframe_t *xframe;
int i = 0;
char prefix[30];
struct timeval now;
xframe_t *xframe;
int i = 0;
char prefix[30];
struct timeval now;
do_gettimeofday(&now);
printk(KERN_DEBUG "%s: dump queue '%s' (first packet in each frame)\n",
THIS_MODULE->name, q->name);
THIS_MODULE->name,
q->name);
list_for_each_entry_reverse(xframe, &q->head, frame_list) {
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
long usec = usec_diff(&now, &xframe->tv_queued);
xpacket_t *pack = (xpacket_t *)&xframe->packets[0];
long usec = usec_diff(&now, &xframe->tv_queued);
snprintf(prefix, ARRAY_SIZE(prefix), " %3d> %5ld.%03ld msec",
i++, usec / 1000, usec % 1000);
i++, usec / 1000, usec % 1000);
dump_packet(prefix, pack, 1);
}
}
static bool __xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
{
int ret = 1;
static int overflow_cnt;
int ret = 1;
static int overflow_cnt = 0;
if (unlikely(q->disabled)) {
if(unlikely(q->disabled)) {
ret = 0;
goto out;
}
if (q->count >= q->max_count) {
if(q->count >= q->max_count) {
q->overflows++;
if ((overflow_cnt++ % 1000) < 5) {
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d "
"worst %3d, overflows %3d "
"worst_lag %02ld.%ld ms\n",
q->name, q->steady_state_count, q->count,
q->max_count, q->worst_count, q->overflows,
q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
NOTICE("Overflow of %-15s: counts %3d, %3d, %3d worst %3d, overflows %3d worst_lag %02ld.%ld ms\n",
q->name,
q->steady_state_count,
q->count,
q->max_count,
q->worst_count,
q->overflows,
q->worst_lag_usec / 1000,
q->worst_lag_usec % 1000);
__xframe_dump_queue(q);
}
ret = 0;
goto out;
}
if (++q->count > q->worst_count)
if(++q->count > q->worst_count)
q->worst_count = q->count;
list_add_tail(&xframe->frame_list, &q->head);
do_gettimeofday(&xframe->tv_queued);
@@ -82,36 +81,33 @@ out:
bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe)
{
unsigned long flags;
int ret;
unsigned long flags;
int ret;
spin_lock_irqsave(&q->lock, flags);
ret = __xframe_enqueue(q, xframe);
spin_unlock_irqrestore(&q->lock, flags);
return ret;
}
EXPORT_SYMBOL(xframe_enqueue);
static xframe_t *__xframe_dequeue(struct xframe_queue *q)
{
xframe_t *frm = NULL;
struct list_head *h;
struct timeval now;
unsigned long usec_lag;
xframe_t *frm = NULL;
struct list_head *h;
struct timeval now;
unsigned long usec_lag;
if (list_empty(&q->head))
if(list_empty(&q->head))
goto out;
h = q->head.next;
list_del_init(h);
--q->count;
frm = list_entry(h, xframe_t, frame_list);
do_gettimeofday(&now);
usec_lag =
(now.tv_sec - frm->tv_queued.tv_sec) * 1000 * 1000 + (now.tv_usec -
frm->
tv_queued.
tv_usec);
if (q->worst_lag_usec < usec_lag)
usec_lag =
(now.tv_sec - frm->tv_queued.tv_sec)*1000*1000 +
(now.tv_usec - frm->tv_queued.tv_usec);
if(q->worst_lag_usec < usec_lag)
q->worst_lag_usec = usec_lag;
out:
return frm;
@@ -119,68 +115,59 @@ out:
xframe_t *xframe_dequeue(struct xframe_queue *q)
{
unsigned long flags;
xframe_t *frm;
unsigned long flags;
xframe_t *frm;
spin_lock_irqsave(&q->lock, flags);
frm = __xframe_dequeue(q);
spin_unlock_irqrestore(&q->lock, flags);
return frm;
}
EXPORT_SYMBOL(xframe_dequeue);
void xframe_queue_disable(struct xframe_queue *q, bool disabled)
{
q->disabled = disabled;
}
EXPORT_SYMBOL(xframe_queue_disable);
void xframe_queue_clear(struct xframe_queue *q)
{
xframe_t *xframe;
xbus_t *xbus = q->priv;
int i = 0;
xframe_t *xframe;
xbus_t *xbus = q->priv;
int i = 0;
xframe_queue_disable(q, 1);
while ((xframe = xframe_dequeue(q)) != NULL) {
while((xframe = xframe_dequeue(q)) != NULL) {
transport_free_xframe(xbus, xframe);
i++;
}
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n",
q->name, i);
XBUS_DBG(DEVICES, xbus, "%s: finished queue clear (%d items)\n", q->name, i);
}
EXPORT_SYMBOL(xframe_queue_clear);
uint xframe_queue_count(struct xframe_queue *q)
{
return q->count;
}
EXPORT_SYMBOL(xframe_queue_count);
/*------------------------- Frame Alloc/Dealloc --------------------*/
static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
{
struct xbus_ops *ops;
xframe_t *xframe;
unsigned long flags;
struct xbus_ops *ops;
xframe_t *xframe;
unsigned long flags;
BUG_ON(!xbus);
ops = transportops_get(xbus);
if (unlikely(!ops)) {
if(unlikely(!ops)) {
XBUS_ERR(xbus, "Missing transport\n");
return NULL;
}
spin_lock_irqsave(&xbus->transport.lock, flags);
#if 0
XBUS_INFO(xbus, "%s (transport_refcount=%d)\n",
__func__, atomic_read(&xbus->transport.transport_refcount));
#endif
//XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
xframe = ops->alloc_xframe(xbus, gfp_flags);
if (!xframe) {
if(!xframe) {
static int rate_limit;
if ((rate_limit++ % 3001) == 0)
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus,
"Failed xframe allocation from transport (%d)\n",
rate_limit);
@@ -193,17 +180,14 @@ static xframe_t *transport_alloc_xframe(xbus_t *xbus, gfp_t gfp_flags)
static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
{
struct xbus_ops *ops;
unsigned long flags;
struct xbus_ops *ops;
unsigned long flags;
BUG_ON(!xbus);
ops = xbus->transport.ops;
BUG_ON(!ops);
spin_lock_irqsave(&xbus->transport.lock, flags);
#if 0
XBUS_INFO(xbus, "%s (transport_refcount=%d)\n",
__func__, atomic_read(&xbus->transport.transport_refcount));
#endif
//XBUS_INFO(xbus, "%s (transport_refcount=%d)\n", __FUNCTION__, atomic_read(&xbus->transport.transport_refcount));
ops->free_xframe(xbus, xframe);
transportops_put(xbus);
spin_unlock_irqrestore(&xbus->transport.lock, flags);
@@ -211,48 +195,45 @@ static void transport_free_xframe(xbus_t *xbus, xframe_t *xframe)
static bool xframe_queue_adjust(struct xframe_queue *q)
{
xbus_t *xbus;
xframe_t *xframe;
int delta;
unsigned long flags;
int ret = 0;
xbus_t *xbus;
xframe_t *xframe;
int delta;
unsigned long flags;
int ret = 0;
BUG_ON(!q);
xbus = q->priv;
BUG_ON(!xbus);
spin_lock_irqsave(&q->lock, flags);
delta = q->count - q->steady_state_count;
if (delta < -XFRAME_QUEUE_MARGIN) {
if(delta < -XFRAME_QUEUE_MARGIN) {
/* Increase pool by one frame */
//XBUS_INFO(xbus, "%s(%d): Allocate one\n", q->name, delta);
xframe = transport_alloc_xframe(xbus, GFP_ATOMIC);
if (!xframe) {
if(!xframe) {
static int rate_limit;
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed frame allocation\n",
q->name);
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed frame allocation\n", q->name);
goto out;
}
if (!__xframe_enqueue(q, xframe)) {
if(!__xframe_enqueue(q, xframe)) {
static int rate_limit;
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed enqueueing frame\n",
q->name);
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed enqueueing frame\n", q->name);
transport_free_xframe(xbus, xframe);
goto out;
}
} else if (delta > XFRAME_QUEUE_MARGIN) {
} else if(delta > XFRAME_QUEUE_MARGIN) {
/* Decrease pool by one frame */
//XBUS_INFO(xbus, "%s(%d): Free one\n", q->name, delta);
xframe = __xframe_dequeue(q);
if (!xframe) {
if(!xframe) {
static int rate_limit;
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed dequeueing frame\n",
q->name);
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s: failed dequeueing frame\n", q->name);
goto out;
}
transport_free_xframe(xbus, xframe);
@@ -265,20 +246,19 @@ out:
xframe_t *get_xframe(struct xframe_queue *q)
{
xframe_t *xframe;
xbus_t *xbus;
xframe_t *xframe;
xbus_t *xbus;
BUG_ON(!q);
xbus = (xbus_t *)q->priv;
BUG_ON(!xbus);
xframe_queue_adjust(q);
xframe = xframe_dequeue(q);
if (!xframe) {
if(!xframe) {
static int rate_limit;
if ((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name,
rate_limit);
if((rate_limit++ % 3001) == 0)
XBUS_ERR(xbus, "%s STILL EMPTY (%d)\n", q->name, rate_limit);
return NULL;
}
BUG_ON(xframe->xframe_magic != XFRAME_MAGIC);
@@ -293,25 +273,34 @@ xframe_t *get_xframe(struct xframe_queue *q)
*
* memset(xframe->packets, 0, xframe->frame_maxlen);
*/
//XBUS_INFO(xbus, "%s\n", __func__);
//XBUS_INFO(xbus, "%s\n", __FUNCTION__);
return xframe;
}
EXPORT_SYMBOL(get_xframe);
void put_xframe(struct xframe_queue *q, xframe_t *xframe)
{
xbus_t *xbus;
xbus_t *xbus;
BUG_ON(!q);
xbus = (xbus_t *)q->priv;
BUG_ON(!xbus);
//XBUS_INFO(xbus, "%s\n", __func__);
//XBUS_INFO(xbus, "%s\n", __FUNCTION__);
BUG_ON(!TRANSPORT_EXIST(xbus));
if (unlikely(!xframe_enqueue(q, xframe))) {
if(unlikely(!xframe_enqueue(q, xframe))) {
XBUS_ERR(xbus, "Failed returning xframe to %s\n", q->name);
transport_free_xframe(xbus, xframe);
return;
}
xframe_queue_adjust(q);
}
EXPORT_SYMBOL(xframe_queue_init);
EXPORT_SYMBOL(xframe_queue_clearstats);
EXPORT_SYMBOL(xframe_enqueue);
EXPORT_SYMBOL(xframe_dequeue);
EXPORT_SYMBOL(xframe_queue_disable);
EXPORT_SYMBOL(xframe_queue_clear);
EXPORT_SYMBOL(xframe_queue_count);
EXPORT_SYMBOL(get_xframe);
EXPORT_SYMBOL(put_xframe);

View File

@@ -8,22 +8,23 @@
#define XFRAME_QUEUE_MARGIN 10
struct xframe_queue {
struct list_head head;
bool disabled;
unsigned int count;
unsigned int max_count;
unsigned int steady_state_count;
spinlock_t lock;
const char *name;
void *priv;
struct list_head head;
bool disabled;
unsigned int count;
unsigned int max_count;
unsigned int steady_state_count;
spinlock_t lock;
const char *name;
void *priv;
/* statistics */
unsigned int worst_count;
unsigned int overflows;
unsigned long worst_lag_usec; /* since xframe creation */
unsigned int worst_count;
unsigned int overflows;
unsigned long worst_lag_usec; /* since xframe creation */
};
void xframe_queue_init(struct xframe_queue *q, unsigned int steady_state_count,
unsigned int max_count, const char *name, void *priv);
void xframe_queue_init(struct xframe_queue *q,
unsigned int steady_state_count, unsigned int max_count,
const char *name, void *priv);
__must_check bool xframe_enqueue(struct xframe_queue *q, xframe_t *xframe);
__must_check xframe_t *xframe_dequeue(struct xframe_queue *q);
void xframe_queue_clearstats(struct xframe_queue *q);
@@ -31,4 +32,4 @@ void xframe_queue_disable(struct xframe_queue *q, bool disabled);
void xframe_queue_clear(struct xframe_queue *q);
uint xframe_queue_count(struct xframe_queue *q);
#endif /* XFRAME_QUEUE_ */
#endif /* XFRAME_QUEUE_ */

View File

@@ -31,17 +31,23 @@
#include <linux/device.h>
#include <linux/version.h>
#include <asm/atomic.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include <linux/semaphore.h>
#else
#include <asm/semaphore.h>
#endif
#include <linux/moduleparam.h>
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#include <dahdi/kernel.h>
#ifdef __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,14)
/* also added in RHEL kernels with the OpenInfiniband backport: */
#if LINUX_VERSION_CODE != KERNEL_VERSION(2,6,9) || !defined(DEFINE_SPINLOCK)
typedef unsigned gfp_t; /* Added in 2.6.14 */
#endif
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
/*
@@ -49,9 +55,9 @@
* bool is now defined as a proper boolean type (gcc _Bool)
* but the command line parsing framework handles it as int.
*/
#define DEF_PARM_BOOL(name, init, perm, desc) \
int name = init; \
module_param(name, bool, perm); \
#define DEF_PARM_BOOL(name,init,perm,desc) \
int name = init; \
module_param(name, bool, perm); \
MODULE_PARM_DESC(name, desc " [default " #init "]")
#else
#define DEF_PARM_BOOL(name, init, perm, desc) \
@@ -60,31 +66,43 @@
MODULE_PARM_DESC(name, desc " [default " #init "]")
#endif
#define DEF_PARM(type, name, init, perm, desc) \
type name = init; \
module_param(name, type, perm); \
#define DEF_PARM(type,name,init,perm,desc) \
type name = init; \
module_param(name, type, perm); \
MODULE_PARM_DESC(name, desc " [default " #init "]")
#define DEF_ARRAY(type, name, count, init, desc) \
unsigned int name ## _num_values; \
type name[count] = {[0 ... ((count)-1)] = init}; \
module_param_array(name, type, &name ## _num_values, 0644); \
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10)
/*
* Old 2.6 kernels had module_param_array() macro that receive the counter
* by value.
*/
#define DEF_ARRAY(type,name,count,init,desc) \
unsigned int name ## _num_values; \
type name[count] = { [0 ... ((count)-1)] = (init) }; \
module_param_array(name, type, name ## _num_values, 0644); \
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
#endif // __KERNEL__
#else
#define DEF_ARRAY(type,name,count,init,desc) \
unsigned int name ## _num_values; \
type name[count] = {[0 ... ((count)-1)] = init}; \
module_param_array(name, type, &name ## _num_values, 0644); \
MODULE_PARM_DESC(name, desc " ( 1-" __MODULE_STRING(count) ")")
#endif
#endif // __KERNEL__
#define CARD_DESC_MAGIC 0xca9dde5c
struct card_desc_struct {
struct list_head card_list;
u32 magic;
__u8 type; /* LSB: 1 - to_phone, 0 - to_line */
__u8 subtype;
struct xpd_addr xpd_addr;
__u8 numchips;
__u8 ports_per_chip;
__u8 ports;
__u8 port_dir;
struct xpd_addr ec_addr; /* echo canceler address */
struct card_desc_struct {
struct list_head card_list;
u32 magic;
byte type; /* LSB: 1 - to_phone, 0 - to_line */
byte subtype;
struct xpd_addr xpd_addr;
byte numchips;
byte ports_per_chip;
byte ports;
byte port_dir;
struct xpd_addr ec_addr; /* echo canceler address */
};
typedef enum xpd_direction {
@@ -109,9 +127,12 @@ enum {
/* yucky, make an instance so we can size it... */
static struct xpd_counters {
char *name;
char *name;
} xpd_counters[] = {
C_(PCM_READ), C_(PCM_WRITE), C_(RECV_ERRORS),};
C_(PCM_READ),
C_(PCM_WRITE),
C_(RECV_ERRORS),
};
#undef C_
@@ -124,43 +145,43 @@ enum xpd_state {
XPD_STATE_NOHW,
};
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
const char *xpd_statename(enum xpd_state st);
bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate);
const char *xpd_statename(enum xpd_state st);
#define PHONEDEV(xpd) ((xpd)->phonedev)
#define IS_PHONEDEV(xpd) (PHONEDEV(xpd).phoneops)
struct phonedev {
const struct phoneops *phoneops; /* Card level operations */
struct dahdi_span span;
struct dahdi_chan *chans[32];
#define XPD_CHAN(xpd, chan) (PHONEDEV(xpd).chans[(chan)])
const struct phoneops *phoneops; /* Card level operations */
struct dahdi_span span;
struct dahdi_chan *chans[32];
#define XPD_CHAN(xpd,chan) (PHONEDEV(xpd).chans[(chan)])
struct dahdi_echocan_state *ec[32];
int channels;
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
xpp_line_t offhook_state; /* chip state: 0 - ONHOOK, 1 - OFHOOK */
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
int channels;
xpd_direction_t direction; /* TO_PHONE, TO_PSTN */
xpp_line_t no_pcm; /* Temporary: disable PCM (for USB-1) */
xpp_line_t offhook_state; /* Actual chip state: 0 - ONHOOK, 1 - OFHOOK */
xpp_line_t oht_pcm_pass; /* Transfer on-hook PCM */
/* Voice Mail Waiting Indication: */
unsigned int msg_waiting[CHANNELS_PERXPD];
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
xpp_line_t digital_signalling; /* BRI signalling channels */
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
unsigned int msg_waiting[CHANNELS_PERXPD];
xpp_line_t digital_outputs; /* 0 - no, 1 - yes */
xpp_line_t digital_inputs; /* 0 - no, 1 - yes */
xpp_line_t digital_signalling; /* BRI signalling channels */
uint timing_priority; /* from 'span' directives in chan_dahdi.conf */
/* Assure atomicity of changes to pcm_len and wanted_pcm_mask */
spinlock_t lock_recompute_pcm;
spinlock_t lock_recompute_pcm;
/* maintained by card drivers */
uint pcm_len; /* allocation length of PCM packet (dynamic) */
xpp_line_t wanted_pcm_mask;
xpp_line_t silence_pcm; /* inject silence during next tick */
xpp_line_t mute_dtmf;
uint pcm_len; /* allocation length of PCM packet (dynamic) */
xpp_line_t wanted_pcm_mask;
xpp_line_t silence_pcm; /* inject silence during next tick */
xpp_line_t mute_dtmf;
bool ringing[CHANNELS_PERXPD];
bool ringing[CHANNELS_PERXPD];
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
atomic_t open_counter; /* Number of open channels */
atomic_t dahdi_registered; /* Am I fully registered with dahdi */
atomic_t open_counter; /* Number of open channels */
/* Echo cancelation */
u_char ec_chunk1[CHANNELS_PERXPD][DAHDI_CHUNKSIZE];
@@ -172,52 +193,51 @@ struct phonedev {
*/
struct xpd {
char xpdname[XPD_NAMELEN];
struct phonedev phonedev;
struct phonedev phonedev;
const struct xops *xops;
xpd_type_t type;
const char *type_name;
__u8 subtype;
int subunits; /* all siblings */
enum xpd_state xpd_state;
struct device xpd_dev;
const struct xops *xops;
xpd_type_t type;
const char *type_name;
byte subtype;
int subunits; /* all siblings */
enum xpd_state xpd_state;
struct device xpd_dev;
#define dev_to_xpd(dev) container_of(dev, struct xpd, xpd_dev)
struct kref kref;
struct kref kref;
#define kref_to_xpd(k) container_of(k, struct xpd, kref)
xbus_t *xbus; /* The XBUS we are connected to */
struct device *echocancel;
xbus_t *xbus; /* The XBUS we are connected to */
struct device *echocancel;
spinlock_t lock;
spinlock_t lock;
int flags;
unsigned long blink_mode; /* bitmask of blinking ports */
int flags;
unsigned long blink_mode; /* bitmask of blinking ports */
#define DEFAULT_LED_PERIOD (1000/8) /* in tick */
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_xpd_dir;
struct proc_dir_entry *proc_xpd_summary;
struct proc_dir_entry *proc_xpd_dir;
struct proc_dir_entry *proc_xpd_summary;
#endif
int counters[XPD_COUNTER_MAX];
int counters[XPD_COUNTER_MAX];
const xproto_table_t *xproto; /* Card level protocol table */
void *priv; /* Card level private data */
bool card_present;
reg_cmd_t requested_reply;
reg_cmd_t last_reply;
const xproto_table_t *xproto; /* Card level protocol table */
void *priv; /* Card level private data */
bool card_present;
reg_cmd_t requested_reply;
reg_cmd_t last_reply;
unsigned long last_response; /* in jiffies */
unsigned xbus_idx; /* index in xbus->xpds[] */
struct xpd_addr addr;
unsigned long last_response; /* in jiffies */
unsigned xbus_idx; /* index in xbus->xpds[] */
struct xpd_addr addr;
struct list_head xpd_list;
unsigned int timer_count;
unsigned int timer_count;
};
#define for_each_line(xpd, i) \
for ((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
#define for_each_line(xpd,i) for((i) = 0; (i) < PHONEDEV(xpd).channels; (i)++)
#define IS_BRI(xpd) ((xpd)->type == XPD_TYPE_BRI)
#define TICK_TOLERANCE 500 /* usec */
#define TICK_TOLERANCE 500 /* usec */
#ifdef DEBUG_SYNC_PARPORT
void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
@@ -227,28 +247,27 @@ void xbus_flip_bit(xbus_t *xbus, unsigned int bitnum0, unsigned int bitnum1);
static inline void *my_kzalloc(size_t size, gfp_t flags)
{
void *p;
void *p;
p = kmalloc(size, flags);
if (p)
if(p)
memset(p, 0, size);
return p;
}
struct xpd_driver {
xpd_type_t type;
xpd_type_t type;
struct device_driver driver;
#define driver_to_xpd_driver(driver) \
container_of(driver, struct xpd_driver, driver)
struct device_driver driver;
#define driver_to_xpd_driver(driver) container_of(driver, struct xpd_driver, driver)
};
int xpd_driver_register(struct device_driver *driver);
void xpd_driver_unregister(struct device_driver *driver);
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
void put_xpd(const char *msg, xpd_t *xpd);
int refcount_xpd(xpd_t *xpd);
int xpd_driver_register(struct device_driver *driver);
void xpd_driver_unregister(struct device_driver *driver);
xpd_t *get_xpd(const char *msg, xpd_t *xpd);
void put_xpd(const char *msg, xpd_t *xpd);
int refcount_xpd(xpd_t *xpd);
#endif
#endif /* XPD_H */
#endif /* XPD_H */

File diff suppressed because it is too large Load Diff

View File

@@ -25,24 +25,21 @@
#include "xpd.h"
#include "xproto.h"
void xpd_set_spanname(xpd_t *xpd);
int xpd_dahdi_preregister(xpd_t *xpd, unsigned offset);
int xpd_dahdi_postregister(xpd_t *xpd);
void xpd_dahdi_preunregister(xpd_t *xpd);
void xpd_dahdi_postunregister(xpd_t *xpd);
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit,
int subunit, __u8 type, __u8 subtype, int subunits,
int subunit_ports, __u8 port_dir);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits,
size_t privsize, const xproto_table_t *proto_table,
int channels);
int dahdi_register_xpd(xpd_t *xpd);
int dahdi_unregister_xpd(xpd_t *xpd);
void xbus_request_removal(xbus_t *xbus);
int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table,
int unit, int subunit, byte type, byte subtype, int subunits, int subunit_ports, byte port_dir);
void xpd_post_init(xpd_t *xpd);
xpd_t *xpd_alloc(xbus_t *xbus, int unit, int subunit, int subtype, int subunits, size_t privsize, const xproto_table_t *proto_table, int channels);
void xpd_free(xpd_t *xpd);
void xpd_remove(xpd_t *xpd);
void update_xpd_status(xpd_t *xpd, int alarm_flag);
const char *xpp_echocan_name(const struct dahdi_chan *chan);
int xpp_echocan_create(struct dahdi_chan *chan, struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p,
struct dahdi_echocan_state **ec);
int xpp_echocan_create(struct dahdi_chan *chan,
struct dahdi_echocanparams *ecp,
struct dahdi_echocanparam *p,
struct dahdi_echocan_state **ec);
void hookstate_changed(xpd_t *xpd, int pos, bool good);
int xpp_open(struct dahdi_chan *chan);
int xpp_close(struct dahdi_chan *chan);
@@ -50,20 +47,19 @@ int xpp_ioctl(struct dahdi_chan *chan, unsigned int cmd, unsigned long arg);
int xpp_hooksig(struct dahdi_chan *chan, enum dahdi_txsig txsig);
int xpp_maint(struct dahdi_span *span, int cmd);
int xpp_watchdog(struct dahdi_span *span, int cause);
void xpp_span_assigned(struct dahdi_span *span);
void report_bad_ioctl(const char *msg, xpd_t *xpd, int pos, unsigned int cmd);
int total_registered_spans(void);
void oht_pcm(xpd_t *xpd, int pos, bool pass);
void mark_offhook(xpd_t *xpd, int pos, bool to_offhook);
#define IS_OFFHOOK(xpd, pos) IS_SET((xpd)->phonedev.offhook_state, (pos))
#define IS_OFFHOOK(xpd,pos) IS_SET((xpd)->phonedev.offhook_state, (pos))
void notify_rxsig(xpd_t *xpd, int pos, enum dahdi_rxsig rxsig);
#ifdef CONFIG_PROC_FS
#include <linux/proc_fs.h>
extern struct proc_dir_entry *xpp_proc_toplevel;
extern struct proc_dir_entry *xpp_proc_toplevel;
#endif
#define SPAN_REGISTERED(xpd) atomic_read(&PHONEDEV(xpd).dahdi_registered)
#endif /* XPP_DAHDI_H */
#endif /* XPP_DAHDI_H */

View File

@@ -43,10 +43,11 @@ show_debug() {
list=''
for n in $dbg_names
do
if [ $(( val & (1 << j) )) -ne 0 ]; then
if (( val & (1 << j) ))
then
list="$list $n"
fi
j=$((j+1))
let j++
done
if [ "$list" = "" ]; then
list=' NONE'
@@ -66,19 +67,19 @@ calc_debug() {
for n in $dbg_names
do
if [ "$wanted" = "$n" ]; then
: $(( val |= (1 << j) ))
(( val |= (1 << j) ))
found=1
elif [ "$wanted" = -"$n" ]; then
: $(( val &= ~(1 << j) ))
(( val &= ~(1 << j) ))
found=1
elif [ "$wanted" = "ANY" ]; then
: $(( val = ~0 ))
(( val = ~0 ))
found=1
elif [ "$wanted" = -"ANY" -o "$wanted" = "NONE" ]; then
val=0
(( val = 0 ))
found=1
fi
j=$((j+1))
let j++
done
if [ "$found" -eq 0 ]; then
echo >&2 "$0: Unknown debug flag '$wanted'"

File diff suppressed because it is too large Load Diff

View File

@@ -30,7 +30,7 @@
static const char rcsid[] = "$Id$";
extern int debug;
extern int debug;
static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
@@ -40,15 +40,12 @@ static const xproto_table_t *xprotocol_tables[XPD_TYPE_NOMODULE];
bool valid_xpd_addr(const struct xpd_addr *addr)
{
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0)
&& ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
return ((addr->subunit & ~BITMASK(SUBUNIT_BITS)) == 0) && ((addr->unit & ~BITMASK(UNIT_BITS)) == 0);
}
EXPORT_SYMBOL(valid_xpd_addr);
/*------ General Protocol Management ----------------------------*/
/*---------------- General Protocol Management ----------------------------*/
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
__u8 opcode)
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode)
{
const xproto_entry_t *xe;
@@ -56,9 +53,8 @@ const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
xe = &table->entries[opcode];
return (xe->handler != NULL) ? xe : NULL;
}
EXPORT_SYMBOL(xproto_card_entry);
const xproto_entry_t *xproto_global_entry(__u8 opcode)
const xproto_entry_t *xproto_global_entry(byte opcode)
{
const xproto_entry_t *xe;
@@ -66,16 +62,15 @@ const xproto_entry_t *xproto_global_entry(__u8 opcode)
//DBG(GENERAL, "opcode=0x%X xe=%p\n", opcode, xe);
return xe;
}
EXPORT_SYMBOL(xproto_global_entry);
xproto_handler_t xproto_global_handler(__u8 opcode)
xproto_handler_t xproto_global_handler(byte opcode)
{
return xproto_card_handler(&PROTO_TABLE(GLOBAL), opcode);
}
static const xproto_table_t *xproto_table(xpd_type_t cardtype)
{
if (cardtype >= XPD_TYPE_NOMODULE)
if(cardtype >= XPD_TYPE_NOMODULE)
return NULL;
return xprotocol_tables[cardtype];
}
@@ -90,28 +85,26 @@ const xproto_table_t *xproto_get(xpd_type_t cardtype)
{
const xproto_table_t *xtable;
if (cardtype >= XPD_TYPE_NOMODULE)
if(cardtype >= XPD_TYPE_NOMODULE)
return NULL;
xtable = xprotocol_tables[cardtype];
if (!xtable) { /* Try to load the relevant module */
if(!xtable) { /* Try to load the relevant module */
int ret = request_module(XPD_TYPE_PREFIX "%d", cardtype);
if (ret != 0) {
NOTICE("%s: Failed to load module for type=%d. "
"exit status=%d.\n",
__func__, cardtype, ret);
if(ret != 0) {
NOTICE("%s: Failed to load module for type=%d. exit status=%d.\n",
__FUNCTION__, cardtype, ret);
/* Drop through: we may be lucky... */
}
xtable = xprotocol_tables[cardtype];
}
if (xtable) {
if(xtable) {
BUG_ON(!xtable->owner);
#ifdef CONFIG_MODULE_UNLOAD
DBG(GENERAL, MODULE_REFCOUNT_FORMAT, xtable->name,
module_refcount(xtable->owner));
#endif
if (!try_module_get(xtable->owner)) {
ERR("%s: try_module_get for %s failed.\n", __func__,
xtable->name);
if(!try_module_get(xtable->owner)) {
ERR("%s: try_module_get for %s failed.\n", __FUNCTION__, xtable->name);
return NULL;
}
}
@@ -129,8 +122,7 @@ void xproto_put(const xproto_table_t *xtable)
module_put(xtable->owner);
}
xproto_handler_t xproto_card_handler(const xproto_table_t *table,
__u8 opcode)
xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode)
{
const xproto_entry_t *xe;
@@ -139,89 +131,78 @@ xproto_handler_t xproto_card_handler(const xproto_table_t *table,
return xe->handler;
}
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
const struct xpd_addr addr, const char *msg)
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg)
{
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n", funcname,
addr.unit, addr.subunit, msg);
XBUS_NOTICE(xbus, "%s: non-existing address (%1d%1d): %s\n",
funcname, addr.unit, addr.subunit, msg);
}
EXPORT_SYMBOL(notify_bad_xpd);
static int packet_process(xbus_t *xbus, xpacket_t *pack)
{
__u8 op;
const xproto_entry_t *xe;
xproto_handler_t handler;
xproto_table_t *table;
xpd_t *xpd;
int ret = -EPROTO;
byte op;
const xproto_entry_t *xe;
xproto_handler_t handler;
xproto_table_t *table;
xpd_t *xpd;
int ret = -EPROTO;
BUG_ON(!pack);
if (!valid_xpd_addr(&XPACKET_ADDR(pack))) {
if (printk_ratelimit()) {
if(!valid_xpd_addr(&XPACKET_ADDR(pack))) {
if(printk_ratelimit()) {
XBUS_NOTICE(xbus, "%s: from %d%d: bad address.\n",
__func__, XPACKET_ADDR_UNIT(pack),
XPACKET_ADDR_SUBUNIT(pack));
dump_packet("packet_process -- bad address", pack,
debug);
__FUNCTION__,
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
dump_packet("packet_process -- bad address", pack, debug);
}
goto out;
}
op = XPACKET_OP(pack);
xpd =
xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack),
XPACKET_ADDR_SUBUNIT(pack));
xpd = xpd_byaddr(xbus, XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack));
/* XPD may be NULL (e.g: during bus polling */
xe = xproto_global_entry(op);
/*-------- Validations -----------*/
if (!xe) {
if(!xe) {
const xproto_table_t *xtable;
if (!xpd) {
if (printk_ratelimit()) {
XBUS_NOTICE(xbus,
"%s: from %d%d opcode=0x%02X: "
"no such global command.\n",
__func__, XPACKET_ADDR_UNIT(pack),
XPACKET_ADDR_SUBUNIT(pack), op);
dump_packet
("packet_process -- no such global command",
pack, 1);
if(!xpd) {
if(printk_ratelimit()) {
XBUS_NOTICE(xbus, "%s: from %d%d opcode=0x%02X: no such global command.\n",
__FUNCTION__,
XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), op);
dump_packet("packet_process -- no such global command", pack, 1);
}
goto out;
}
xtable = xproto_table(xpd->type);
if (!xtable) {
if (printk_ratelimit())
XPD_ERR(xpd,
"%s: no protocol table (type=%d)\n",
__func__, xpd->type);
if(!xtable) {
if(printk_ratelimit())
XPD_ERR(xpd, "%s: no protocol table (type=%d)\n",
__FUNCTION__,
xpd->type);
goto out;
}
xe = xproto_card_entry(xtable, op);
if (!xe) {
if (printk_ratelimit()) {
XPD_NOTICE(xpd,
"%s: bad command (type=%d,opcode=0x%x)\n",
__func__, xpd->type, op);
dump_packet("packet_process -- bad command",
pack, 1);
if(!xe) {
if(printk_ratelimit()) {
XPD_NOTICE(xpd, "%s: bad command (type=%d,opcode=0x%x)\n",
__FUNCTION__,
xpd->type, op);
dump_packet("packet_process -- bad command", pack, 1);
}
goto out;
}
}
table = xe->table;
BUG_ON(!table);
if (!table->packet_is_valid(pack)) {
if (printk_ratelimit()) {
if(!table->packet_is_valid(pack)) {
if(printk_ratelimit()) {
ERR("xpp: %s: wrong size %d for opcode=0x%02X\n",
__func__, XPACKET_LEN(pack), op);
dump_packet("packet_process -- wrong size", pack,
debug);
__FUNCTION__, XPACKET_LEN(pack), op);
dump_packet("packet_process -- wrong size", pack, debug);
}
goto out;
}
ret = 0; /* All well */
ret = 0; /* All well */
handler = xe->handler;
BUG_ON(!handler);
XBUS_COUNTER(xbus, RX_BYTES) += XPACKET_LEN(pack);
@@ -232,13 +213,13 @@ out:
static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
{
__u8 *xframe_end;
xpacket_t *pack;
__u8 *p;
int len;
int ret;
byte *xframe_end;
xpacket_t *pack;
byte *p;
int len;
int ret;
if (debug & DBG_COMMANDS)
if(debug & DBG_COMMANDS)
dump_xframe("RX-CMD", xbus, xframe, DBG_ANY);
p = xframe->packets;
xframe_end = p + XFRAME_LEN(xframe);
@@ -246,34 +227,31 @@ static int xframe_receive_cmd(xbus_t *xbus, xframe_t *xframe)
pack = (xpacket_t *)p;
len = XPACKET_LEN(pack);
/* Sanity checks */
if (unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL, PCM_READ))) {
static int rate_limit;
if(unlikely(XPACKET_OP(pack) == XPROTO_NAME(GLOBAL,PCM_READ))) {
static int rate_limit;
if ((rate_limit++ % 1003) == 0) {
XBUS_DBG(GENERAL, xbus,
"A PCM packet within a Non-PCM xframe\n");
dump_xframe("In Non-PCM xframe",
xbus, xframe, debug);
if((rate_limit++ % 1003) == 0) {
XBUS_DBG(GENERAL, xbus, "A PCM packet within a Non-PCM xframe\n");
dump_xframe("In Non-PCM xframe", xbus, xframe, debug);
}
ret = -EPROTO;
goto out;
}
p += len;
if (p > xframe_end || len < RPACKET_HEADERSIZE) {
static int rate_limit;
if(p > xframe_end || len < RPACKET_HEADERSIZE) {
static int rate_limit;
if ((rate_limit++ % 1003) == 0) {
XBUS_NOTICE(xbus, "Invalid packet length %d\n",
len);
if((rate_limit++ % 1003) == 0) {
XBUS_NOTICE(xbus, "Invalid packet length %d\n", len);
dump_xframe("BAD LENGTH", xbus, xframe, debug);
}
ret = -EPROTO;
goto out;
}
ret = packet_process(xbus, pack);
if (unlikely(ret < 0))
if(unlikely(ret < 0))
break;
} while (p < xframe_end);
} while(p < xframe_end);
out:
FREE_RECV_XFRAME(xbus, xframe);
return ret;
@@ -281,22 +259,22 @@ out:
int xframe_receive(xbus_t *xbus, xframe_t *xframe)
{
int ret = 0;
struct timeval now;
struct timeval tv_received;
int usec;
int ret = 0;
struct timeval now;
struct timeval tv_received;
int usec;
if (XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
static int rate_limit;
if(XFRAME_LEN(xframe) < RPACKET_HEADERSIZE) {
static int rate_limit;
if ((rate_limit++ % 1003) == 0) {
if((rate_limit++ % 1003) == 0) {
XBUS_NOTICE(xbus, "short xframe\n");
dump_xframe("short xframe", xbus, xframe, debug);
}
FREE_RECV_XFRAME(xbus, xframe);
return -EPROTO;
}
if (!XBUS_FLAGS(xbus, CONNECTED)) {
if(!XBUS_FLAGS(xbus, CONNECTED)) {
XBUS_DBG(GENERAL, xbus, "Dropped xframe. Is shutting down.\n");
return -ENODEV;
}
@@ -304,8 +282,8 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
/*
* We want to check that xframes do not mix PCM and other commands
*/
if (XPACKET_IS_PCM((xpacket_t *)xframe->packets)) {
if (!XBUS_IS(xbus, READY))
if(XPACKET_IS_PCM((xpacket_t *)xframe->packets)) {
if(!XBUS_IS(xbus, READY))
FREE_RECV_XFRAME(xbus, xframe);
else
xframe_receive_pcm(xbus, xframe);
@@ -315,48 +293,47 @@ int xframe_receive(xbus_t *xbus, xframe_t *xframe)
}
/* Calculate total processing time */
do_gettimeofday(&now);
usec =
(now.tv_sec - tv_received.tv_sec) * 1000000 + now.tv_usec -
tv_received.tv_usec;
if (usec > xbus->max_rx_process)
usec = (now.tv_sec - tv_received.tv_sec) * 1000000 +
now.tv_usec - tv_received.tv_usec;
if(usec > xbus->max_rx_process)
xbus->max_rx_process = usec;
return ret;
}
EXPORT_SYMBOL(xframe_receive);
#define VERBOSE_DEBUG 1
#define ERR_REPORT_LIMIT 20
void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
{
__u8 op = XPACKET_OP(packet);
__u8 *addr = (__u8 *)&XPACKET_ADDR(packet);
byte op = XPACKET_OP(packet);
byte *addr = (byte *)&XPACKET_ADDR(packet);
if (!debug)
if(!debug)
return;
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d", msg,
XPACKET_ADDR_UNIT(packet), XPACKET_ADDR_SUBUNIT(packet),
(XPACKET_ADDR_SYNC(packet)) ? '+' : ' ', *addr, op,
XPACKET_LEN(packet));
printk(KERN_DEBUG "%s: XPD=%1X-%1X%c (0x%X) OP=0x%02X LEN=%d",
msg,
XPACKET_ADDR_UNIT(packet),
XPACKET_ADDR_SUBUNIT(packet),
(XPACKET_ADDR_SYNC(packet))?'+':' ',
*addr,
op,
XPACKET_LEN(packet));
#if VERBOSE_DEBUG
{
int i;
__u8 *p = (__u8 *)packet;
byte *p = (byte *)packet;
printk(" BYTES: ");
for (i = 0; i < XPACKET_LEN(packet); i++) {
static int limiter;
for(i = 0; i < XPACKET_LEN(packet); i++) {
static int limiter = 0;
if (i >= sizeof(xpacket_t)) {
if (limiter < ERR_REPORT_LIMIT) {
ERR("%s: length overflow "
"i=%d > sizeof(xpacket_t)=%lu\n",
__func__, i + 1,
(long)sizeof(xpacket_t));
} else if (limiter == ERR_REPORT_LIMIT) {
ERR("%s: error packet #%d... "
"squelsh reports.\n",
__func__, limiter);
if(i >= sizeof(xpacket_t)) {
if(limiter < ERR_REPORT_LIMIT) {
ERR("%s: length overflow i=%d > sizeof(xpacket_t)=%lu\n",
__FUNCTION__, i+1, (long)sizeof(xpacket_t));
} else if(limiter == ERR_REPORT_LIMIT) {
ERR("%s: error packet #%d... squelsh reports.\n",
__FUNCTION__, limiter);
}
limiter++;
break;
@@ -368,121 +345,112 @@ void dump_packet(const char *msg, const xpacket_t *packet, bool debug)
#endif
printk("\n");
}
EXPORT_SYMBOL(dump_packet);
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
__u8 unit, xportno_t port, const reg_cmd_t *regcmd)
byte unit, xportno_t port, const reg_cmd_t *regcmd)
{
char action;
char modifier;
char port_buf[MAX_PROC_WRITE];
char reg_buf[MAX_PROC_WRITE];
char data_buf[MAX_PROC_WRITE];
char action;
char modifier;
char port_buf[MAX_PROC_WRITE];
char reg_buf[MAX_PROC_WRITE];
char data_buf[MAX_PROC_WRITE];
/* The size byte is not included */
if (regcmd->bytes > sizeof(*regcmd) - 1) {
PORT_NOTICE(xbus, unit, port,
"%s: %s: Too long: regcmd->bytes = %d\n", __func__,
msg, regcmd->bytes);
if(regcmd->bytes > sizeof(*regcmd) - 1) { /* The size byte is not included */
PORT_NOTICE(xbus, unit, port, "%s: %s: Too long: regcmd->bytes = %d\n",
__FUNCTION__, msg, regcmd->bytes);
return;
}
if (regcmd->is_multibyte) {
char buf[MAX_PROC_WRITE + 1];
int i;
int n = 0;
size_t len = regcmd->bytes;
const __u8 *p = REG_XDATA(regcmd);
if(regcmd->is_multibyte) {
char buf[MAX_PROC_WRITE + 1];
int i;
int n = 0;
size_t len = regcmd->bytes;
const byte *p = REG_XDATA(regcmd);
buf[0] = '\0';
for (i = 0; i < len && n < MAX_PROC_WRITE; i++)
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ",
p[i]);
for(i = 0; i < len && n < MAX_PROC_WRITE; i++)
n += snprintf(&buf[n], MAX_PROC_WRITE - n, "%02X ", p[i]);
PORT_DBG(REGS, xbus, unit, port,
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) "
"%s[0..%zd]: %s%s\n",
unit, port, regcmd->eoframe, msg, len - 1, buf,
(n >= MAX_PROC_WRITE) ? "..." : "");
"UNIT-%d PORT-%d: Multibyte(eoframe=%d) %s[0..%zd]: %s%s\n",
unit, port, regcmd->eoframe,
msg, len-1, buf, (n >= MAX_PROC_WRITE)?"...":"");
return;
}
/* The size byte is not included */
if (regcmd->bytes != sizeof(*regcmd) - 1) {
PORT_NOTICE(xbus, unit, port,
"%s: %s: Wrong size: regcmd->bytes = %d\n",
__func__, msg, regcmd->bytes);
if(regcmd->bytes != sizeof(*regcmd) - 1) { /* The size byte is not included */
PORT_NOTICE(xbus, unit, port, "%s: %s: Wrong size: regcmd->bytes = %d\n",
__FUNCTION__, msg, regcmd->bytes);
return;
}
snprintf(port_buf, MAX_PROC_WRITE, "%d%s", regcmd->portnum,
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
snprintf(port_buf, MAX_PROC_WRITE, "%d%s",
regcmd->portnum,
(REG_FIELD(regcmd, all_ports_broadcast)) ? "*" : "");
action = (REG_FIELD(regcmd, read_request)) ? 'R' : 'W';
modifier = 'D';
if (REG_FIELD(regcmd, do_subreg)) {
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, regnum), REG_FIELD(regcmd, subreg));
if(REG_FIELD(regcmd, do_subreg)) {
snprintf(reg_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, regnum),
REG_FIELD(regcmd, subreg));
modifier = 'S';
} else {
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, regnum));
snprintf(reg_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, regnum));
}
if (REG_FIELD(regcmd, read_request)) {
if(REG_FIELD(regcmd, read_request)) {
data_buf[0] = '\0';
} else if (REG_FIELD(regcmd, do_datah)) {
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, data_low), REG_FIELD(regcmd,
data_high));
} else if(REG_FIELD(regcmd, do_datah)) {
snprintf(data_buf, MAX_PROC_WRITE, "%02X %02X",
REG_FIELD(regcmd, data_low),
REG_FIELD(regcmd, data_high));
modifier = 'I';
} else {
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, data_low));
snprintf(data_buf, MAX_PROC_WRITE, "%02X",
REG_FIELD(regcmd, data_low));
}
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n", msg, port_buf,
action, modifier, reg_buf, data_buf);
PORT_DBG(REGS, xbus, unit, port, "%s: %s %c%c %s %s\n",
msg, port_buf, action, modifier,
reg_buf, data_buf);
}
EXPORT_SYMBOL(dump_reg_cmd);
const char *xproto_name(xpd_type_t xpd_type)
{
const xproto_table_t *proto_table;
const xproto_table_t *proto_table;
BUG_ON(xpd_type >= XPD_TYPE_NOMODULE);
proto_table = xprotocol_tables[xpd_type];
if (!proto_table)
if(!proto_table)
return NULL;
return proto_table->name;
}
EXPORT_SYMBOL(xproto_name);
#define CHECK_XOP(xops, f) \
if (!(xops)->f) { \
ERR("%s: missing xmethod %s [%s (%d)]\n", \
__func__, #f, name, type); \
if(!(xops)->f) { \
ERR("%s: missing xmethod %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
return -EINVAL; \
}
#define CHECK_PHONEOP(phoneops, f) \
if (!(phoneops)->f) { \
ERR("%s: missing phone method %s [%s (%d)]\n", \
__func__, #f, name, type); \
if(!(phoneops)->f) { \
ERR("%s: missing phone method %s [%s (%d)]\n", __FUNCTION__, #f, name, type); \
return -EINVAL; \
}
int xproto_register(const xproto_table_t *proto_table)
{
int type;
const char *name;
const struct xops *xops;
const struct phoneops *phoneops;
int type;
const char *name;
const struct xops *xops;
const struct phoneops *phoneops;
BUG_ON(!proto_table);
type = proto_table->type;
name = proto_table->name;
if (type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %d\n", __func__, type);
if(type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %d\n", __FUNCTION__, type);
return -EINVAL;
}
DBG(GENERAL, "%s (%d)\n", name, type);
if (xprotocol_tables[type])
NOTICE("%s: overriding registration of %s (%d)\n", __func__,
name, type);
if(xprotocol_tables[type])
NOTICE("%s: overriding registration of %s (%d)\n", __FUNCTION__, name, type);
xops = proto_table->xops;
CHECK_XOP(xops, card_new);
CHECK_XOP(xops, card_init);
@@ -500,30 +468,38 @@ int xproto_register(const xproto_table_t *proto_table)
CHECK_PHONEOP(phoneops, card_dahdi_preregistration);
CHECK_PHONEOP(phoneops, card_dahdi_postregistration);
/* optional method -- call after testing: */
/*CHECK_PHONEOP(phoneops, card_ioctl); */
/*CHECK_PHONEOP(phoneops, card_ioctl);*/
}
xprotocol_tables[type] = proto_table;
return 0;
}
EXPORT_SYMBOL(xproto_register);
void xproto_unregister(const xproto_table_t *proto_table)
{
int type;
const char *name;
int type;
const char *name;
BUG_ON(!proto_table);
type = proto_table->type;
name = proto_table->name;
DBG(GENERAL, "%s (%d)\n", name, type);
if (type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %s (%d)\n", __func__, name, type);
if(type >= XPD_TYPE_NOMODULE) {
NOTICE("%s: Bad xproto type %s (%d)\n", __FUNCTION__, name, type);
return;
}
if (!xprotocol_tables[type])
NOTICE("%s: xproto type %s (%d) is already unregistered\n",
__func__, name, type);
if(!xprotocol_tables[type])
NOTICE("%s: xproto type %s (%d) is already unregistered\n", __FUNCTION__, name, type);
xprotocol_tables[type] = NULL;
}
EXPORT_SYMBOL(dump_packet);
EXPORT_SYMBOL(dump_reg_cmd);
EXPORT_SYMBOL(xframe_receive);
EXPORT_SYMBOL(notify_bad_xpd);
EXPORT_SYMBOL(valid_xpd_addr);
EXPORT_SYMBOL(xproto_global_entry);
EXPORT_SYMBOL(xproto_card_entry);
EXPORT_SYMBOL(xproto_name);
EXPORT_SYMBOL(xproto_register);
EXPORT_SYMBOL(xproto_unregister);

View File

@@ -35,25 +35,25 @@
#define XPP_PROTOCOL_VERSION 30
struct xpd_addr {
uint8_t subunit:SUBUNIT_BITS;
uint8_t reserved:1;
uint8_t unit:UNIT_BITS;
uint8_t sync_master:1;
uint8_t subunit:SUBUNIT_BITS;
uint8_t reserved:1;
uint8_t unit:UNIT_BITS;
uint8_t sync_master:1;
} PACKED;
#define MKADDR(p, u, s) do { \
(p)->unit = (u); \
(p)->subunit = (s); \
(p)->sync_master = 0; \
} while (0)
} while(0)
struct xpacket_header {
uint16_t packet_len:10;
uint16_t reserved:1;
uint16_t is_pcm:1;
uint16_t pcmslot:4;
uint8_t opcode;
struct xpd_addr addr;
uint16_t packet_len:10;
uint16_t reserved:1;
uint16_t is_pcm:1;
uint16_t pcmslot:4;
uint8_t opcode;
struct xpd_addr addr;
} PACKED;
#define XPACKET_OP(p) ((p)->head.opcode)
@@ -71,8 +71,8 @@ struct xpacket_header {
/*
* The LSB of the type number signifies:
* 0 - TO_PSTN
* 1 - TO_PHONE
* 0 - TO_PSTN
* 1 - TO_PHONE
*/
#define XPD_TYPE_FXS 1 // TO_PHONE
#define XPD_TYPE_FXO 2 // TO_PSTN
@@ -81,61 +81,60 @@ struct xpacket_header {
#define XPD_TYPE_ECHO 5 // Octasic echo canceller
#define XPD_TYPE_NOMODULE 7
typedef __u8 xpd_type_t;
typedef byte xpd_type_t;
#define XPD_TYPE_PREFIX "xpd-type-"
#define MODULE_ALIAS_XPD(type) \
#define MODULE_ALIAS_XPD(type) \
MODULE_ALIAS(XPD_TYPE_PREFIX __stringify(type))
#define PCM_CHUNKSIZE (CHANNELS_PERXPD * 8) /* samples of 8 bytes */
bool valid_xpd_addr(const struct xpd_addr *addr);
#define XPROTO_NAME(card, op) card ## _ ## op
#define XPROTO_HANDLER(card, op) XPROTO_NAME(card, op ## _handler)
#define XPROTO_CALLER(card, op) XPROTO_NAME(card, op ## _send)
#define XPROTO_NAME(card,op) card ## _ ## op
#define XPROTO_HANDLER(card,op) XPROTO_NAME(card,op ## _handler)
#define XPROTO_CALLER(card,op) XPROTO_NAME(card,op ## _send)
#define HANDLER_DEF(card, op) \
static int XPROTO_HANDLER(card, op) ( \
#define HANDLER_DEF(card,op) \
static int XPROTO_HANDLER(card,op) ( \
xbus_t *xbus, \
xpd_t *xpd, \
const xproto_entry_t *cmd, \
xpacket_t *pack)
#define CALL_PROTO(card, op, ...) XPROTO_CALLER(card, op)(__VA_ARGS__)
#define CALL_PROTO(card,op, ...) XPROTO_CALLER(card,op)( __VA_ARGS__ )
#define DECLARE_CMD(card, op, ...) \
int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__)
#define DECLARE_CMD(card,op, ...) \
int CALL_PROTO(card, op, xbus_t *xbus, xpd_t *xpd, ## __VA_ARGS__ )
#define HOSTCMD(card, op, ...) \
DECLARE_CMD(card, op, ## __VA_ARGS__)
#define HOSTCMD(card, op, ...) \
DECLARE_CMD(card, op, ## __VA_ARGS__ )
#define RPACKET_NAME(card, op) XPROTO_NAME(RPACKET_ ## card, op)
#define RPACKET_TYPE(card, op) struct RPACKET_NAME(card, op)
#define RPACKET_NAME(card,op) XPROTO_NAME(RPACKET_ ## card, op)
#define RPACKET_TYPE(card,op) struct RPACKET_NAME(card, op)
#define DEF_RPACKET_DATA(card, op, ...) \
RPACKET_TYPE(card, op) { \
#define DEF_RPACKET_DATA(card,op, ...) \
RPACKET_TYPE(card,op) { \
struct xpacket_header head; \
__VA_ARGS__ \
} PACKED
#define RPACKET_HEADERSIZE sizeof(struct xpacket_header)
#define RPACKET_FIELD(p, card, op, field) \
(((RPACKET_TYPE(card, op) *)(p))->field)
#define RPACKET_SIZE(card, op) sizeof(RPACKET_TYPE(card, op))
#define RPACKET_FIELD(p,card,op,field) (((RPACKET_TYPE(card,op) *)(p))->field)
#define RPACKET_SIZE(card,op) sizeof(RPACKET_TYPE(card,op))
#define XENTRY(prototab, module, op) \
[ XPROTO_NAME(module, op) ] = { \
.handler = XPROTO_HANDLER(module, op), \
.datalen = RPACKET_SIZE(module, op), \
#define XENTRY(prototab,module,op) \
[ XPROTO_NAME(module,op) ] = { \
.handler = XPROTO_HANDLER(module,op), \
.datalen = RPACKET_SIZE(module,op), \
.name = #op, \
.table = &PROTO_TABLE(prototab) \
}
#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \
#define XPACKET_INIT(p, card, op, to, pcm, pcmslot) \
do { \
XPACKET_OP(p) = XPROTO_NAME(card, op); \
XPACKET_LEN(p) = RPACKET_SIZE(card, op); \
XPACKET_OP(p) = XPROTO_NAME(card,op); \
XPACKET_LEN(p) = RPACKET_SIZE(card,op); \
XPACKET_IS_PCM(p) = (pcm); \
XPACKET_PCMSLOT(p) = (pcmslot); \
XPACKET_RESERVED(p) = 0; \
@@ -143,138 +142,138 @@ bool valid_xpd_addr(const struct xpd_addr *addr);
XPACKET_ADDR_SUBUNIT(p) = XBUS_SUBUNIT(to); \
XPACKET_ADDR_SYNC(p) = 0; \
XPACKET_ADDR_RESERVED(p) = 0; \
} while (0)
} while(0)
#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \
#define XFRAME_NEW_CMD(frm, p, xbus, card, op, to) \
do { \
int pack_len = RPACKET_SIZE(card, op); \
int pack_len = RPACKET_SIZE(card,op); \
\
if (!XBUS_FLAGS(xbus, CONNECTED)) \
if(!XBUS_FLAGS(xbus, CONNECTED)) \
return -ENODEV; \
(frm) = ALLOC_SEND_XFRAME(xbus); \
if (!(frm)) \
if(!(frm)) \
return -ENOMEM; \
(p) = xframe_next_packet(frm, pack_len); \
if (!(p)) \
if(!(p)) \
return -ENOMEM; \
XPACKET_INIT(p, card, op, to, 0, 0); \
(frm)->usec_towait = 0; \
} while (0)
} while(0)
#endif
/*----------------- register handling --------------------------------*/
/*--------------------------- register handling --------------------------------*/
#define MULTIBYTE_MAX_LEN 5 /* FPGA firmware limitation */
typedef struct reg_cmd {
__u8 bytes:3; /* Length (for Multibyte) */
__u8 eoframe:1; /* For BRI -- end of frame */
__u8 portnum:3; /* For port specific registers */
__u8 is_multibyte:1;
byte bytes:3; /* Length (for Multibyte) */
byte eoframe:1; /* For BRI -- end of frame */
byte portnum:3; /* For port specific registers */
byte is_multibyte:1;
union {
struct {
__u8 reserved:4;
__u8 do_datah:1;
__u8 do_subreg:1;
__u8 read_request:1;
__u8 all_ports_broadcast:1;
__u8 regnum;
__u8 subreg;
__u8 data_low;
__u8 data_high;
byte reserved:4;
byte do_datah:1;
byte do_subreg:1;
byte read_request:1;
byte all_ports_broadcast:1;
byte regnum;
byte subreg;
byte data_low;
byte data_high;
} PACKED r;
/* For Write-Multibyte commands in BRI */
struct {
__u8 xdata[MULTIBYTE_MAX_LEN];
byte xdata[MULTIBYTE_MAX_LEN];
} PACKED d;
} PACKED alt;
} PACKED reg_cmd_t;
/* Shortcut access macros */
#define REG_FIELD(regptr, member) ((regptr)->alt.r.member)
#define REG_FIELD(regptr,member) ((regptr)->alt.r.member)
#define REG_XDATA(regptr) ((regptr)->alt.d.xdata)
#ifdef __KERNEL__
/*----------------- protocol tables ----------------------------------*/
/*--------------------------- protocol tables ----------------------------------*/
typedef struct xproto_entry xproto_entry_t;
typedef struct xproto_table xproto_table_t;
typedef struct xproto_entry xproto_entry_t;
typedef struct xproto_table xproto_table_t;
typedef int (*xproto_handler_t) (xbus_t *xbus, xpd_t *xpd,
const xproto_entry_t *cmd, xpacket_t *pack);
typedef int (*xproto_handler_t)(
xbus_t *xbus,
xpd_t *xpd,
const xproto_entry_t *cmd,
xpacket_t *pack);
const xproto_table_t *xproto_get(xpd_type_t cardtype);
void xproto_put(const xproto_table_t *xtable);
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table,
__u8 opcode);
xproto_handler_t xproto_card_handler(const xproto_table_t *table,
__u8 opcode);
const xproto_entry_t *xproto_card_entry(const xproto_table_t *table, byte opcode);
xproto_handler_t xproto_card_handler(const xproto_table_t *table, byte opcode);
const xproto_entry_t *xproto_global_entry(__u8 opcode);
xproto_handler_t xproto_global_handler(__u8 opcode);
const xproto_entry_t *xproto_global_entry(byte opcode);
xproto_handler_t xproto_global_handler(byte opcode);
/*
* XMETHOD() resolve to method pointer (NULL for optional methods)
* CALL_XMETHOD() calls the method, passing mandatory arguments
*/
#define XMETHOD(name, xpd) ((xpd)->xops->name)
#define CALL_XMETHOD(name, xpd, ...) \
(XMETHOD(name, (xpd))((xpd)->xbus, (xpd), ## __VA_ARGS__))
#define CALL_XMETHOD(name, xpd, ...) \
(XMETHOD(name, (xpd))((xpd)->xbus, (xpd), ## __VA_ARGS__ ))
/*
* PHONE_METHOD() resolve to method pointer (NULL for optional methods)
* CALL_PHONE_METHOD() calls the method, passing mandatory arguments
*/
#define PHONE_METHOD(name, xpd) (PHONEDEV(xpd).phoneops->name)
#define CALL_PHONE_METHOD(name, xpd, ...) \
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__))
#define CALL_PHONE_METHOD(name, xpd, ...) \
(PHONE_METHOD(name, (xpd))((xpd), ## __VA_ARGS__ ))
struct phoneops {
void (*card_pcm_recompute) (xpd_t *xpd, xpp_line_t pcm_mask);
void (*card_pcm_fromspan) (xpd_t *xpd, xpacket_t *pack);
void (*card_pcm_tospan) (xpd_t *xpd, xpacket_t *pack);
int (*echocancel_timeslot) (xpd_t *xpd, int pos);
int (*echocancel_setmask) (xpd_t *xpd, xpp_line_t ec_mask);
int (*card_timing_priority) (xpd_t *xpd);
int (*card_dahdi_preregistration) (xpd_t *xpd, bool on);
int (*card_dahdi_postregistration) (xpd_t *xpd, bool on);
int (*card_hooksig) (xpd_t *xpd, int pos, enum dahdi_txsig txsig);
int (*card_ioctl) (xpd_t *xpd, int pos, unsigned int cmd,
unsigned long arg);
int (*card_open) (xpd_t *xpd, lineno_t pos);
int (*card_close) (xpd_t *xpd, lineno_t pos);
int (*card_state) (xpd_t *xpd, bool on);
void (*card_pcm_recompute)(xpd_t *xpd, xpp_line_t pcm_mask);
void (*card_pcm_fromspan)(xpd_t *xpd, xpacket_t *pack);
void (*card_pcm_tospan)(xpd_t *xpd, xpacket_t *pack);
int (*echocancel_timeslot)(xpd_t *xpd, int pos);
int (*echocancel_setmask)(xpd_t *xpd, xpp_line_t ec_mask);
int (*card_timing_priority)(xpd_t *xpd);
int (*card_dahdi_preregistration)(xpd_t *xpd, bool on);
int (*card_dahdi_postregistration)(xpd_t *xpd, bool on);
int (*card_hooksig)(xpd_t *xpd, int pos, enum dahdi_txsig txsig);
int (*card_ioctl)(xpd_t *xpd, int pos, unsigned int cmd, unsigned long arg);
int (*card_open)(xpd_t *xpd, lineno_t pos);
int (*card_close)(xpd_t *xpd, lineno_t pos);
int (*card_state)(xpd_t *xpd, bool on);
};
struct xops {
xpd_t *(*card_new) (xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, __u8 subtype,
int subunits, int subunit_ports, bool to_phone);
int (*card_init) (xbus_t *xbus, xpd_t *xpd);
int (*card_remove) (xbus_t *xbus, xpd_t *xpd);
int (*card_tick) (xbus_t *xbus, xpd_t *xpd);
int (*card_register_reply) (xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
xpd_t *(*card_new)(xbus_t *xbus, int unit, int subunit,
const xproto_table_t *proto_table, byte subtype,
int subunits, int subunit_ports, bool to_phone);
int (*card_init)(xbus_t *xbus, xpd_t *xpd);
int (*card_remove)(xbus_t *xbus, xpd_t *xpd);
int (*card_tick)(xbus_t *xbus, xpd_t *xpd);
int (*card_register_reply)(xbus_t *xbus, xpd_t *xpd, reg_cmd_t *reg);
};
struct xproto_entry {
xproto_handler_t handler;
int datalen;
const char *name;
xproto_table_t *table;
xproto_handler_t handler;
int datalen;
const char *name;
xproto_table_t *table;
};
struct xproto_table {
struct module *owner;
xproto_entry_t entries[256]; /* Indexed by opcode */
const struct xops *xops; /* Card level operations */
const struct phoneops *phoneops; /* DAHDI operations */
const struct echoops *echoops; /* Echo Canceller operations */
xpd_type_t type;
__u8 ports_per_subunit;
const char *name;
bool (*packet_is_valid) (xpacket_t *pack);
void (*packet_dump) (const char *msg, xpacket_t *pack);
struct module *owner;
xproto_entry_t entries[256]; /* Indexed by opcode */
const struct xops *xops; /* Card level operations */
const struct phoneops *phoneops; /* DAHDI operations */
const struct echoops *echoops; /* Echo Canceller operations */
xpd_type_t type;
byte ports_per_subunit;
const char *name;
bool (*packet_is_valid)(xpacket_t *pack);
void (*packet_dump)(const char *msg, xpacket_t *pack);
};
#include "card_global.h"
@@ -283,10 +282,11 @@ struct xproto_table {
#include "card_bri.h"
#include "card_pri.h"
#define MEMBER(card, op) RPACKET_TYPE(card, op) RPACKET_NAME(card, op)
#define MEMBER(card,op) RPACKET_TYPE(card,op) RPACKET_NAME(card,op)
struct xpacket {
struct xpacket_header head;
struct xpacket_header head;
union {
MEMBER(GLOBAL, NULL_REPLY);
MEMBER(GLOBAL, PCM_WRITE);
@@ -297,22 +297,20 @@ struct xpacket {
MEMBER(FXS, SIG_CHANGED);
MEMBER(FXO, SIG_CHANGED);
__u8 data[0];
byte data[0];
};
/* Last byte is chksum */
} PACKED;
void dump_packet(const char *msg, const xpacket_t *packet, bool debug);
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus,
__u8 unit, xportno_t port, const reg_cmd_t *regcmd);
void dump_reg_cmd(const char msg[], bool writing, xbus_t *xbus, byte unit, xportno_t port, const reg_cmd_t *regcmd);
int xframe_receive(xbus_t *xbus, xframe_t *xframe);
void notify_bad_xpd(const char *funcname, xbus_t *xbus,
const struct xpd_addr addr, const char *msg);
void notify_bad_xpd(const char *funcname, xbus_t *xbus, const struct xpd_addr addr, const char *msg);
int xproto_register(const xproto_table_t *proto_table);
void xproto_unregister(const xproto_table_t *proto_table);
const xproto_entry_t *xproto_global_entry(__u8 opcode);
const xproto_entry_t *xproto_global_entry(byte opcode);
const char *xproto_name(xpd_type_t xpd_type);
#endif /* __KERNEL__ */
#endif /* __KERNEL__ */
#endif /* XPROTO_H */
#endif /* XPROTO_H */

View File

@@ -21,6 +21,9 @@
#ifdef __KERNEL__
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <linux/config.h>
#endif
#endif
/* DAHDI compile time options */
@@ -73,8 +76,10 @@
/* You can still override them below */
#if defined(CONFIG_HDLC) || defined(CONFIG_HDLC_MODULE)
#define DAHDI_HDLC_TYPE_TRANS
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,3)
#define HDLC_MAINTAINERS_ARE_MORE_STUPID_THAN_I_THOUGHT
#endif
#endif
/*
* Uncomment CONFIG_DAHDI_NET to enable SyncPPP, CiscoHDLC, and Frame Relay

View File

@@ -6,7 +6,7 @@
* written by Jim Dixon <jim@lambdatel.com>.
*
* Copyright (C) 2001 Jim Dixon / Zapata Telephony.
* Copyright (C) 2001 - 2012 Digium, Inc.
* Copyright (C) 2001 - 2010 Digium, Inc.
*
* All rights reserved.
*
@@ -38,8 +38,11 @@
#include <dahdi/dahdi_config.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <linux/config.h>
#endif
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/module.h>
#include <linux/ioctl.h>
@@ -52,12 +55,14 @@
#include <linux/skbuff.h>
#include <linux/interrupt.h>
#endif
#include <linux/device.h>
#include <linux/sysfs.h>
#include <linux/poll.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
#define dahdi_pci_module pci_register_driver
#else
#define dahdi_pci_module pci_module_init
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id)
@@ -65,39 +70,37 @@
#define DAHDI_IRQ_HANDLER(a) static irqreturn_t a(int irq, void *dev_id, struct pt_regs *regs)
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 26)
#ifdef CONFIG_PCI
#include <linux/pci-aspm.h>
#endif
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
#define HAVE_NET_DEVICE_OPS
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18)
#define DAHDI_IRQ_SHARED IRQF_SHARED
#define DAHDI_IRQ_DISABLED IRQF_DISABLED
#define DAHDI_IRQ_SHARED_DISABLED IRQF_SHARED | IRQF_DISABLED
#else
#define DAHDI_IRQ_SHARED SA_SHIRQ
#define DAHDI_IRQ_DISABLED SA_INTERRUPT
#define DAHDI_IRQ_SHARED_DISABLED SA_SHIRQ | SA_INTERRUPT
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 26)
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,16)
#ifndef dev_notice
#define dev_notice(dev, format, arg...) \
dev_printk(KERN_NOTICE , dev , format , ## arg)
#endif
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
# ifdef RHEL_RELEASE_VERSION
# if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5, 6)
#define dev_name(dev) ((dev)->bus_id)
#define dev_set_name(dev, format, ...) \
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
# else
#define dev_set_name(dev, format, ...) \
do { \
kobject_set_name(&(dev)->kobj, format, ## __VA_ARGS__); \
snprintf((dev)->bus_id, BUS_ID_SIZE, \
kobject_name(&(dev)->kobj)); \
} while (0)
# endif
# else
#define dev_name(dev) ((dev)->bus_id)
#define dev_set_name(dev, format, ...) \
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__)
# endif
#define dev_set_name(dev, format, ...) \
snprintf((dev)->bus_id, BUS_ID_SIZE, format, ## __VA_ARGS__);
#endif
/*! Default chunk size for conferences and such -- static right now, might make
@@ -107,7 +110,7 @@
#define DAHDI_MIN_CHUNKSIZE DAHDI_CHUNKSIZE
#define DAHDI_DEFAULT_CHUNKSIZE DAHDI_CHUNKSIZE
#define DAHDI_MAX_CHUNKSIZE DAHDI_CHUNKSIZE
#define DAHDI_CB_SIZE (1 << 3)
#define DAHDI_CB_SIZE 2
/* DAHDI operates at 8Khz by default */
#define DAHDI_MS_TO_SAMPLES(ms) ((ms) * 8)
@@ -491,7 +494,10 @@ struct dahdi_chan {
int numbufs; /*!< How many buffers in channel */
int txbufpolicy; /*!< Buffer policy */
int rxbufpolicy; /*!< Buffer policy */
int txdisable; /*!< Disable transmitter */
int rxdisable; /*!< Disable receiver */
/* Tone zone stuff */
struct dahdi_zone *curzone; /*!< Zone for selecting tones */
@@ -536,6 +542,7 @@ struct dahdi_chan {
short getlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples */
unsigned char getraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */
short getlin_lastchunk[DAHDI_MAX_CHUNKSIZE]; /*!< Last transmitted samples from last chunk */
short putlin[DAHDI_MAX_CHUNKSIZE]; /*!< Last received samples */
unsigned char putraw[DAHDI_MAX_CHUNKSIZE]; /*!< Last received raw data */
short conflast[DAHDI_MAX_CHUNKSIZE]; /*!< Last conference sample -- base part of channel */
@@ -788,23 +795,6 @@ struct dahdi_count {
#define DAHDI_FLAG_TXUNDERRUN DAHDI_FLAG(TXUNDERRUN)
#define DAHDI_FLAG_RXOVERRUN DAHDI_FLAG(RXOVERRUN)
enum spantypes {
SPANTYPE_INVALID = 0,
SPANTYPE_ANALOG_FXS,
SPANTYPE_ANALOG_FXO,
SPANTYPE_ANALOG_MIXED,
SPANTYPE_DIGITAL_E1,
SPANTYPE_DIGITAL_T1,
SPANTYPE_DIGITAL_J1,
SPANTYPE_DIGITAL_BRI_NT,
SPANTYPE_DIGITAL_BRI_TE,
SPANTYPE_DIGITAL_BRI_SOFT,
};
const char *dahdi_spantype2str(enum spantypes st);
enum spantypes dahdi_str2spantype(const char *name);
const char *dahdi_lineconfig_bit_name(int lineconfig_bit);
ssize_t lineconfig_str(int lineconfig, char buf[], size_t size);
struct file;
struct dahdi_span_ops {
@@ -896,49 +886,21 @@ 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
* span has been assigned with the system. */
void (*assigned)(struct dahdi_span *span);
/*! Called when the spantype / linemode is changed before the span is
* assigned a number. */
int (*set_spantype)(struct dahdi_span *span, enum spantypes st);
};
/**
* dahdi_device - Represents a device that can contain one or more spans.
*
* @spans: List of child spans.
* @manufacturer: Device manufacturer.
* @location: The location of this device. This should not change if
* the device is replaced (e.g: in the same PCI slot)
* @hardware_id: The hardware_id of this device (NULL for devices without
* a hardware_id). This should not change if the device is
* relocated to a different location (e.g: different PCI slot)
* @devicetype: What type of device this is.
* @irqmisses: Count of "interrupt misses" for this device.
*
*/
struct dahdi_device {
struct list_head spans;
const char *manufacturer;
const char *location;
const char *hardware_id;
const char *devicetype;
struct device dev;
unsigned int irqmisses;
};
struct dahdi_span {
spinlock_t lock;
char name[40]; /*!< Span name */
char desc[80]; /*!< Span description */
enum spantypes spantype; /*!< span type */
const char *spantype; /*!< span type in text form */
const char *manufacturer; /*!< span's device manufacturer */
char devicetype[80]; /*!< span's device type */
char location[40]; /*!< span device's location in system */
int deflaw; /*!< Default law (DAHDI_MULAW or DAHDI_ALAW) */
int alarms; /*!< Pending alarms on span */
unsigned long flags;
u8 cannot_provide_timing:1;
int irq; /*!< IRQ for this span's hardware */
int lbo; /*!< Span Line-Buildout */
int lineconfig; /*!< Span line configuration */
int linecompat; /*!< Span line compatibility (0 for
@@ -952,6 +914,7 @@ struct dahdi_span {
int maintstat; /*!< Maintenance state */
int mainttimer; /*!< Maintenance timer */
int irqmisses; /*!< Interrupt misses */
int timingslips; /*!< Clock slips */
struct dahdi_chan **chans; /*!< Member channel structures */
@@ -971,11 +934,7 @@ struct dahdi_span {
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#endif
struct list_head spans_node;
struct dahdi_device *parent;
struct list_head device_node;
struct device *span_device;
struct list_head node;
};
struct dahdi_transcoder_channel {
@@ -992,8 +951,6 @@ struct dahdi_transcoder_channel {
u32 srcfmt;
};
int dahdi_is_sync_master(const struct dahdi_span *span);
static inline int
dahdi_tc_is_built(struct dahdi_transcoder_channel *dtc) {
return test_bit(DAHDI_TC_FLAG_CHAN_BUILT, &dtc->flags);
@@ -1075,7 +1032,6 @@ struct dahdi_dynamic {
long rxjif;
unsigned short txcnt;
unsigned short rxcnt;
struct dahdi_device *ddev;
struct dahdi_span span;
struct dahdi_chan *chans[256];
struct dahdi_dynamic_driver *driver;
@@ -1083,7 +1039,6 @@ struct dahdi_dynamic {
int timing;
int master;
unsigned char *msgbuf;
struct device *dev;
struct list_head list;
};
@@ -1109,9 +1064,6 @@ struct dahdi_dynamic_driver {
struct list_head list;
struct module *owner;
/*! Numberic id of next device created by this driver. */
unsigned int id;
};
/*! \brief Receive a dynamic span message */
@@ -1150,22 +1102,6 @@ static inline int dahdi_transmit(struct dahdi_span *span)
return ret;
}
static inline int dahdi_is_digital_span(const struct dahdi_span *s)
{
return (s->linecompat > 0);
}
static inline int dahdi_is_t1_span(const struct dahdi_span *s)
{
return (s->linecompat & (DAHDI_CONFIG_D4 | DAHDI_CONFIG_ESF |
DAHDI_CONFIG_B8ZS)) > 0;
}
static inline int dahdi_is_e1_span(const struct dahdi_span *s)
{
return dahdi_is_digital_span(s) && !dahdi_is_t1_span(s);
}
/*! Abort the buffer currently being receive with event "event" */
void dahdi_hdlc_abort(struct dahdi_chan *ss, int event);
@@ -1180,12 +1116,10 @@ void dahdi_hdlc_putbuf(struct dahdi_chan *ss, unsigned char *rxb, int bytes);
* and 1 if the currently transmitted message is now done */
int dahdi_hdlc_getbuf(struct dahdi_chan *ss, unsigned char *bufptr, unsigned int *size);
/*! Register a device. Returns 0 on success, -1 on failure. */
struct dahdi_device *dahdi_create_device(void);
int dahdi_register_device(struct dahdi_device *ddev, struct device *parent);
void dahdi_unregister_device(struct dahdi_device *ddev);
void dahdi_free_device(struct dahdi_device *ddev);
void dahdi_init_span(struct dahdi_span *span);
/*! Register a span. Returns 0 on success, -1 on failure. Pref-master is non-zero if
we should have preference in being the master device */
int dahdi_register(struct dahdi_span *span, int prefmaster);
/*! Allocate / free memory for a transcoder */
struct dahdi_transcoder *dahdi_transcoder_alloc(int numchans);
@@ -1200,6 +1134,9 @@ int dahdi_transcoder_unregister(struct dahdi_transcoder *tc);
/*! \brief Alert a transcoder */
int dahdi_transcoder_alert(struct dahdi_transcoder_channel *ztc);
/*! \brief Unregister a span */
int dahdi_unregister(struct dahdi_span *span);
/*! \brief Gives a name to an LBO */
const char *dahdi_lboname(int lbo);
@@ -1273,13 +1210,8 @@ extern u_char __dahdi_lin2mu[16384];
extern u_char __dahdi_lin2a[16384];
#endif
struct dahdi_dynamic_ops {
struct module *owner;
int (*ioctl)(unsigned int cmd, unsigned long data);
};
/*! \brief Used by dynamic DAHDI -- don't use directly */
void dahdi_set_dynamic_ops(const struct dahdi_dynamic_ops *ops);
void dahdi_set_dynamic_ioctl(int (*func)(unsigned int cmd, unsigned long data));
/*! \brief Used by DAHDI HPEC module -- don't use directly */
void dahdi_set_hpec_ioctl(int (*func)(unsigned int cmd, unsigned long data));
@@ -1398,16 +1330,6 @@ static inline short dahdi_txtone_nextsample(struct dahdi_chan *ss)
#define fatal_signal_pending(p) \
(signal_pending((p)) && sigismember(&(p)->pending.signal, SIGKILL))
#ifdef CONFIG_PCI
#ifndef PCIE_LINK_STATE_L0S
#define PCIE_LINK_STATE_L0S 1
#define PCIE_LINK_STATE_L1 2
#define PCIE_LINK_STATE_CLKPM 4
#endif
#define pci_disable_link_state dahdi_pci_disable_link_state
void dahdi_pci_disable_link_state(struct pci_dev *pdev, int state);
#endif /* CONFIG_PCI */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
#ifndef __packed
@@ -1435,16 +1357,59 @@ static inline int strcasecmp(const char *s1, const char *s2)
return c1 - c2;
}
#endif /* clamp_val */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)
static inline void list_replace(struct list_head *old, struct list_head *new)
{
new->next = old->next;
new->next->prev = new;
new->prev = old->prev;
new->prev->next = new;
}
#ifndef WARN_ON_ONCE
#define WARN_ON_ONCE(__condition) do { \
static int __once = 1; \
if (unlikely(__condition)) { \
if (__once) { \
__once = 0; \
WARN_ON(0); \
} \
} \
} while (0)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14)
#define kzalloc(a, b) kcalloc(1, a, b)
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
#define synchronize_rcu() synchronize_kernel()
#define kasprintf dahdi_kasprintf
char *dahdi_kasprintf(gfp_t gfp, const char *fmt, ...);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)
#if !defined(HAVE_WAIT_FOR_COMPLETION_TIMEOUT)
static inline unsigned long
wait_for_completion_interruptible_timeout(struct completion *x,
unsigned long timeout)
{
/* There is a race condition here. If x->done is reset to 0
* before the call to wait_for_completion after this thread wakes.
*/
timeout = wait_event_interruptible_timeout(x->wait, x->done, timeout);
if (timeout)
wait_for_completion(x);
return timeout;
}
#endif
typedef u32 __bitwise pm_message_t;
#endif /* 2.6.11 */
#endif /* 2.6.12 */
#endif /* 2.6.14 */
#endif /* 2.6.18 */
#endif /* 2.6.22 */
#endif /* 2.6.25 */
#endif /* 2.6.26 */
#endif /* 2.6.31 */
#ifndef CONFIG_TRACING
#define trace_printk printk
#endif
#ifndef DEFINE_SPINLOCK
#define DEFINE_SPINLOCK(x) spinlock_t x = SPIN_LOCK_UNLOCKED
#endif
@@ -1489,10 +1454,6 @@ struct mutex {
#define DAHDI_PSEUDO 255
/* prink-wrapper macros */
#define module_printk(level, fmt, args...) \
printk(level "%s: " fmt, THIS_MODULE->name, ## args)
#define DAHDI_PRINTK(level, category, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, \
THIS_MODULE->name, ## __VA_ARGS__)
@@ -1500,7 +1461,7 @@ struct mutex {
printk(KERN_ ## level "%s%s-%s: span-%d: " fmt, #level, \
category, THIS_MODULE->name, (span)->spanno, ## __VA_ARGS__)
#define chan_printk(level, category, chan, fmt, ...) \
printk(KERN_ ## level "%s%s-%s: chan-%d: " fmt, #level, \
printk(KERN_ ## level "%s%s-%s: %d: " fmt, #level, \
category, THIS_MODULE->name, (chan)->channo, ## __VA_ARGS__)
#define dahdi_err(fmt, ...) DAHDI_PRINTK(ERR, "", fmt, ## __VA_ARGS__)
#define span_info(span, fmt, ...) span_printk(INFO, "", span, fmt, \
@@ -1514,26 +1475,6 @@ struct mutex {
#define chan_err(chan, fmt, ...) chan_printk(ERR, "", chan, fmt, \
## __VA_ARGS__)
#ifndef pr_err
#define pr_err(fmt, ...) \
printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
#endif
#ifndef pr_warning
#define pr_warning(fmt, ...) \
printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
#endif
#ifndef pr_warn
#define pr_warn pr_warning
#endif
#ifndef pr_notice
#define pr_notice(fmt, ...) \
printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
#endif
#ifndef pr_info
#define pr_info(fmt, ...) \
printk(KERN_INFO pr_fmt(fmt), ##__VA_ARGS__)
#endif
/* The dbg_* ones use a magical variable 'debug' and the user should be
* aware of that.
*/
@@ -1545,7 +1486,6 @@ struct mutex {
* be of the form DAHDI_DBG_*
*/
#define DAHDI_DBG_GENERAL BIT(0)
#define DAHDI_DBG_ASSIGN BIT(1)
#define DAHDI_DBG_DEVICES BIT(7) /* instantiation/destruction etc. */
#define dahdi_dbg(bits, fmt, ...) \
((void)((debug & (DAHDI_DBG_ ## bits)) && DAHDI_PRINTK(DEBUG, \
@@ -1558,10 +1498,6 @@ struct mutex {
((void)((debug & (DAHDI_DBG_ ## bits)) && \
chan_printk(DEBUG, "-" #bits, chan, \
"%s: " fmt, __func__, ## __VA_ARGS__)))
#define dahdi_dev_dbg(bits, dev, fmt, ...) \
((void)((debug & (DAHDI_DBG_ ## bits)) && \
dev_printk(KERN_DEBUG, dev, \
"DBG-%s(%s): " fmt, #bits, __func__, ## __VA_ARGS__)))
#endif /* DAHDI_PRINK_MACROS_USE_debug */
#endif /* _DAHDI_KERNEL_H */