[dahdi-commits] dahdi/linux.git branch "master" updated.

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Mon Nov 5 02:36:56 CST 2018


branch "master" has been updated
       via  75620dd9ef6ac746745a1ecab4ef925a5b9e2988 (commit)
       via  f47c9bd9285d4c9d15f47a4cfbd2a00a5a1eaa13 (commit)
       via  40f4f86ffae6775c4f0f82005e0450c99da39601 (commit)
       via  29cb229cd3f1d252872b7f1924b6e3be941f7ad3 (commit)
       via  a66e88e666229092a96d54e5873d4b3ae79b1ce3 (commit)
       via  a36d2662546e56c5be44e610bd5fd9deed57a9bb (commit)
       via  3697450317a7bd60bfa7031aad250085928d5c47 (commit)
       via  3748456d22122cf807b47d5cf6e2ff23183f440d (commit)
       via  04e759f9c5a6f76ed88bc6ba6446fb0c23c1ff55 (commit)
       via  dade6ac6154b58c4f5b6f178cc09de397359000b (commit)
       via  14198aee8532bbafed2ad1297177f8e0e0f13f50 (commit)
       via  60d058cc7a064b6e07889f76dd9514059c303e0f (commit)
       via  bfdfc4728c033381656b59bf83aa37187b5dfca8 (commit)
       via  f95fff65883893defc79ae5c25ab04bf29afe80a (commit)
       via  6667f1c8d8fadc29ef95dce4f8b025f38d3d3084 (commit)
       via  20328895a28831024baf7fcd9e7bce57ef7cf263 (commit)
       via  7ecdf370bc137dab124eab134781ca23aa2ab5b4 (commit)
       via  ea2d67414a2a543a113eebdbbb541ce648b90b74 (commit)
       via  14d8754e342dbd05ee775ef31488e9a8ae797d4c (commit)
      from  d3c9e434373f6eac20ee4ff827286d5e97960a9a (commit)

Summary of changes:
 Makefile                            |    4 +-
 README                              |  220 +-
 drivers/dahdi/Kbuild                |   17 +-
 drivers/dahdi/Kconfig               |   68 -
 drivers/dahdi/dahdi-base.c          |   21 +-
 drivers/dahdi/dahdi_dummy.c         |    8 +-
 drivers/dahdi/dahdi_dynamic.c       |   11 +-
 drivers/dahdi/dahdi_dynamic_ethmf.c |   16 +-
 drivers/dahdi/datamods/syncppp.c    |    9 +-
 drivers/dahdi/pciradio.c            | 1891 ----
 drivers/dahdi/pciradio.rbt          |10531 ---------------------
 drivers/dahdi/tor2-hw.h             |  186 -
 drivers/dahdi/tor2.c                | 1537 ---
 drivers/dahdi/tormenta2.rbt         |17482 -----------------------------------
 drivers/dahdi/voicebus/GpakApi.c    |    2 +
 drivers/dahdi/voicebus/voicebus.c   |   16 +-
 drivers/dahdi/wcb4xxp/base.c        |   30 -
 drivers/dahdi/wcfxo.c               | 1105 ---
 drivers/dahdi/wct1xxp.c             | 1454 ---
 drivers/dahdi/wctc4xxp/base.c       |   12 +-
 drivers/dahdi/wctdm.c               | 2894 ------
 drivers/dahdi/wctdm24xxp/base.c     |    4 -
 drivers/dahdi/wcte11xp.c            | 1657 ----
 drivers/dahdi/wcte12xp/Kbuild       |    5 -
 drivers/dahdi/wcte12xp/base.c       | 3223 -------
 drivers/dahdi/wcte12xp/wcte12xp.h   |  167 -
 drivers/dahdi/wcte13xp-base.c       |    9 +-
 drivers/dahdi/wcte43x-base.c        |    9 +-
 drivers/dahdi/xpp/card_fxs.c        |    4 +-
 drivers/dahdi/xpp/xbus-core.c       |    1 -
 drivers/dahdi/xpp/xbus-pcm.c        |   11 +-
 include/dahdi/kernel.h              |   35 +
 32 files changed, 96 insertions(+), 42543 deletions(-)
 delete mode 100644 drivers/dahdi/pciradio.c
 delete mode 100644 drivers/dahdi/pciradio.rbt
 delete mode 100644 drivers/dahdi/tor2-hw.h
 delete mode 100644 drivers/dahdi/tor2.c
 delete mode 100644 drivers/dahdi/tormenta2.rbt
 delete mode 100644 drivers/dahdi/wcfxo.c
 delete mode 100644 drivers/dahdi/wct1xxp.c
 delete mode 100644 drivers/dahdi/wctdm.c
 delete mode 100644 drivers/dahdi/wcte11xp.c
 delete mode 100644 drivers/dahdi/wcte12xp/Kbuild
 delete mode 100644 drivers/dahdi/wcte12xp/base.c
 delete mode 100644 drivers/dahdi/wcte12xp/wcte12xp.h


- Log -----------------------------------------------------------------
commit 75620dd9ef6ac746745a1ecab4ef925a5b9e2988
Author: Keith Morgan <kmorgan at digium.com>
Date:   Fri Oct 5 19:42:50 2018 +0000

    Remove struct devtype for unsupported drivers.

diff --git a/drivers/dahdi/wcb4xxp/base.c b/drivers/dahdi/wcb4xxp/base.c
index 159abbc..5fe6fb2 100644
--- a/drivers/dahdi/wcb4xxp/base.c
+++ b/drivers/dahdi/wcb4xxp/base.c
@@ -135,18 +135,6 @@ static struct devtype wcb43xp = {"Wildcard B430P", .ports = 4,
 					.card_type = B430P};
 static struct devtype wcb23xp = {"Wildcard B230P", .ports = 2,
 					.card_type = B230P};
-static struct devtype hfc2s =	 {"HFC-2S Junghanns.NET duoBRI PCI", .ports = 2, .card_type = DUOBRI };
-static struct devtype hfc4s =	 {"HFC-4S Junghanns.NET quadBRI PCI", .ports = 4, .card_type = QUADBRI };
-static struct devtype hfc8s =	 {"HFC-8S Junghanns.NET octoBRI PCI", .ports = 8, .card_type = OCTOBRI };
-static struct devtype hfc2s_OV = {"OpenVox B200P", .ports = 2, .card_type = B200P_OV };
-static struct devtype hfc4s_OV = {"OpenVox B400P", .ports = 4, .card_type = B400P_OV };
-static struct devtype hfc8s_OV = {"OpenVox B800P", .ports = 8, .card_type = B800P_OV };
-static struct devtype hfc2s_BN = {"BeroNet BN2S0", .ports = 2, .card_type = BN2S0 };
-static struct devtype hfc4s_BN = {"BeroNet BN4S0", .ports = 4, .card_type = BN4S0 };
-static struct devtype hfc8s_BN = {"BeroNet BN8S0", .ports = 8, .card_type = BN8S0 };
-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 IS_B430P(card) ((card)->card_type == B430P)
 #define IS_B230P(card) ((card)->card_type == B230P)

commit f47c9bd9285d4c9d15f47a4cfbd2a00a5a1eaa13
Author: Keith Morgan <kmorgan at digium.com>
Date:   Thu Oct 4 19:03:00 2018 +0000

    Changed readme to reflect driver support changes.

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

commit 40f4f86ffae6775c4f0f82005e0450c99da39601
Author: Keith Morgan <kmorgan at digium.com>
Date:   Thu Oct 4 17:51:54 2018 +0000

    Revert "Remove support for xpp drivers."
    add them back.
    This reverts commit a36d2662546e56c5be44e610bd5fd9deed57a9bb.

diff --git a/drivers/dahdi/Kbuild b/drivers/dahdi/Kbuild
index 6d9b91c..855e5bf 100644
--- a/drivers/dahdi/Kbuild
+++ b/drivers/dahdi/Kbuild
@@ -41,6 +41,7 @@ obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_WCB4XXP)		+= wcb4xxp/
 
 endif
 
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP)		+= xpp/
 
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_JPAH)	+= dahdi_echocan_jpah.o
 obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_ECHOCAN_STEVE)	+= dahdi_echocan_sec.o
diff --git a/drivers/dahdi/Kconfig b/drivers/dahdi/Kconfig
index 2e9a6db..5b94bf1 100644
--- a/drivers/dahdi/Kconfig
+++ b/drivers/dahdi/Kconfig
@@ -223,3 +223,4 @@ config DAHDI_DYNAMIC_LOC
 	  If unsure, say Y.
 
 
+source "drivers/dahdi/xpp/Kconfig"
diff --git a/drivers/dahdi/xpp/Changelog_xpp b/drivers/dahdi/xpp/Changelog_xpp
new file mode 100644
index 0000000..5408651
--- /dev/null
+++ b/drivers/dahdi/xpp/Changelog_xpp
@@ -0,0 +1,31 @@
+Sun Mar  1 2009 Oron Peled <oron at actcom.co.il> - xpp.r6795
+  * Fix cases where the command_queue overflowed during initialization.
+    - Also add a 'command_queue_length' parameter to xpp.ko
+  * More migrations to sysfs:
+    - Add a 'transport' attribute to our astribank devices which
+      points to the usb device we use. E.g:
+       /sys/bus/astribanks/devices/xbus-00/transport is symlinked to
+       ../../../../../../devices/pci0000:00/0000:00:10.4/usb5/5-4
+    - Move /proc/xpp/XBUS-??/XPD-??/span to
+      /sys/bus/xpds/devices/??:?:?/span
+    - Migrate from /proc/xpp/sync to:
+      /sys/bus/astribanks/drivers/xppdrv/sync
+    - New 'offhook' attribute in:
+      /sys/bus/xpds/devices/??:?:?/offhook
+  * PRI: change the "timing" priority to match the convention used by
+         other PRI cards -- I.e: lower numbers (not 0) have higher
+	 priority.
+  * FXO: 
+    - Power denial: create two module parameters instead of hard-coded
+      constants (power_denial_safezone, power_denial_minlen).
+      For sites that get non-standard power-denial signals from central
+      office on offhook.
+    - Don't hangup on power-denial, just notify Dahdi and wait for
+    - Fix caller-id detection for the case central office sends it before
+      first ring without any indication before.
+      Asterisk's desicion.
+  * USB_FW.hex:
+    - Fixes cases where firmware loading would fail.
+
+Thu, Aug 14 2008 Oron Peled <oron at actcom.co.il> - xpp.r6056
+  * First DAHDI-linux release.
diff --git a/drivers/dahdi/xpp/Kbuild b/drivers/dahdi/xpp/Kbuild
new file mode 100644
index 0000000..2965af0
--- /dev/null
+++ b/drivers/dahdi/xpp/Kbuild
@@ -0,0 +1,81 @@
+EXTRA_CFLAGS	=	$(XPP_LOCAL_CFLAGS)	\
+			-DDEBUG			\
+			-DPOLL_DIGITAL_INPUTS	\
+			-DDEBUG_PCMTX		\
+			-DPROTOCOL_DEBUG	\
+			-g
+			#
+
+WITH_BRISTUFF	:= $(shell grep -c '^[[:space:]]*\#[[:space:]]*define[[:space:]]\+CONFIG_DAHDI_BRI_DCHANS\>' $(src)/../../../include/dahdi/dahdi_config.h)
+
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPP)		+= xpp.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_FXS)		+= xpd_fxs.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_FXO)		+= xpd_fxo.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_PRI)		+= xpd_pri.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_BRI)		+= xpd_bri.o
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_DAHDI_XPD_ECHO)		+= xpd_echo.o
+
+# Build only supported modules
+ifneq	(,$(filter y m,$(CONFIG_USB)))
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_XPP_USB)			+= xpp_usb.o
+endif
+ifneq	(,$(filter y m,$(CONFIG_BF537)))
+obj-$(DAHDI_BUILD_ALL)$(CONFIG_XPP_MMAP)		+= xpp_mmap.o
+endif
+
+xpp-objs		+= xbus-core.o xbus-sysfs.o xbus-pcm.o xframe_queue.o xpp_dahdi.o xproto.o card_global.o dahdi_debug.o
+xpd_fxs-objs		+= card_fxs.o
+xpd_fxo-objs		+= card_fxo.o
+xpd_bri-objs		+= card_bri.o
+xpd_pri-objs		+= card_pri.o
+xpd_echo-objs		+= card_echo.o
+xpp_mmap-objs		+= mmapbus.o mmapdrv.o
+
+ifeq	(y,$(PARPORT_DEBUG))
+EXTRA_CFLAGS	+= -DDEBUG_SYNC_PARPORT
+obj-m		+= parport_debug.o
+endif
+
+# Just in case it was left from an older version:
+clean-files	+= xpp_version.h
+
+# Validations:
+#  - Syntactic verification of perl scripts
+#  - Handle country table validation for init_card_2_*
+
+XPP_PROTOCOL_VERSION	:= $(shell grep XPP_PROTOCOL_VERSION $(src)/xproto.h | sed -e 's/^.*XPP_PROTOCOL_VERSION[ \t]*//')
+
+xpp_verifications		= \
+				init_card_1_$(XPP_PROTOCOL_VERSION)	\
+				init_card_2_$(XPP_PROTOCOL_VERSION)	\
+				init_card_3_$(XPP_PROTOCOL_VERSION)	\
+				init_card_4_$(XPP_PROTOCOL_VERSION)	\
+				init_fxo_modes
+
+xpp_verified			= $(foreach file, $(xpp_verifications), $(file).verified)
+
+FXO_MODES  = $(src)/../fxo_modes.h
+FXO_VERIFY = $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) -v $(obj)/init_fxo_modes
+
+hostprogs-y			:= print_fxo_modes
+always				:= $(xpp_verified)
+print_fxo_modes-objs		:= print_fxo_modes.o
+HOSTCFLAGS_print_fxo_modes.o	+= -include $(FXO_MODES)
+
+clean-files			+= print_fxo_modes init_fxo_modes $(xpp_verified)
+
+$(obj)/init_fxo_modes: $(obj)/print_fxo_modes
+	@echo '  GEN     $@'
+	$(Q)$(obj)/print_fxo_modes >$@ || (rm -f $@; exit 1)
+
+$(obj)/init_fxo_modes.verified: $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION) $(obj)/init_fxo_modes
+	@echo '  CHECK   $(obj)/init_card_2_$(XPP_PROTOCOL_VERSION)'
+	$(Q)$(FXO_VERIFY) || (rm -f $@; exit 1)
+	$(Q)touch $@
+
+$(obj)/init_card_%_$(XPP_PROTOCOL_VERSION).verified: $(src)/init_card_%_$(XPP_PROTOCOL_VERSION)
+	@echo '  VERIFY  $<'
+	$(Q)perl -c $< 2> $@ || (cat $@; rm -f $@; exit 1)
+
+.PHONY: FORCE
+FORCE:
diff --git a/drivers/dahdi/xpp/Kconfig b/drivers/dahdi/xpp/Kconfig
new file mode 100644
index 0000000..aebd29c
--- /dev/null
+++ b/drivers/dahdi/xpp/Kconfig
@@ -0,0 +1,82 @@
+#
+# XPP configuration
+#
+
+menuconfig DAHDI_XPP
+	tristate "Xorcom Astribank Support"
+	depends on DAHDI
+	default DAHDI
+	---help---
+	  Infrastructure support for Xorcom Astribank products.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called xpp.
+
+	  If unsure, say Y.
+
+config DAHDI_XPP_USB
+       tristate "Astribank USB transport"
+       depends on DAHDI_XPP && USB
+       default DAHDI_XPP
+	---help---
+	  To compile this driver as a module, choose M here: the
+	  module will be called xpp_usb.
+
+	  If unsure, say Y.
+
+config DAHDI_XPP_MMAP
+       tristate "Astribank Blackfin transport"
+       depends on DAHDI_XPP && BF537
+       default DAHDI_XPP
+	---help---
+	  To compile this driver as a module, choose M here: the
+	  module will be called xpp_mmap.
+	  
+	  This module can be compiled only on Blackfin architecture
+	  (with uClinux).
+
+	  If unsure, say N.
+
+config DAHDI_XPD_FXS
+	tristate "FXS port Support"
+	depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
+	default DAHDI_XPP
+	---help---
+	  To compile this driver as a module, choose M here: the
+	  module will be called xpd_fxs.
+
+	  If unsure, say Y.
+
+config DAHDI_XPD_FXO
+	tristate "FXO port Support"
+	depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
+	default DAHDI_XPP
+	---help---
+	  To compile this driver as a module, choose M here: the
+	  module will be called xpd_fxo.
+
+	  If unsure, say Y.
+
+config DAHDI_XPD_BRI
+	tristate "BRI port Support"
+	depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
+	default DAHDI_XPP
+	---help---
+	  To compile this driver as a module, choose M here: the
+	  module will be called xpd_pri.
+
+	  Note: this driver will be automatically excluded
+	        from compilation if dahdi driver does not
+		contain the "bristuff" patch.
+
+	  If unsure, say Y.
+
+config DAHDI_XPD_PRI
+	tristate "PRI port Support"
+	depends on DAHDI_XPP && (DAHDI_XPP_USB || DAHDI_XPP_MMAP)
+	default DAHDI_XPP
+	---help---
+	  To compile this driver as a module, choose M here: the
+	  module will be called xpd_pri.
+
+	  If unsure, say Y.
diff --git a/drivers/dahdi/xpp/Makefile b/drivers/dahdi/xpp/Makefile
new file mode 100644
index 0000000..00fc5ee
--- /dev/null
+++ b/drivers/dahdi/xpp/Makefile
@@ -0,0 +1,7 @@
+# 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
+
+ctags:
+	ctags *.[ch]
diff --git a/drivers/dahdi/xpp/XppConfig.pm b/drivers/dahdi/xpp/XppConfig.pm
new file mode 100644
index 0000000..f00811f
--- /dev/null
+++ b/drivers/dahdi/xpp/XppConfig.pm
@@ -0,0 +1,38 @@
+package XppConfig;
+#
+# Written by Oron Peled <oron at actcom.co.il>
+# Copyright (C) 2008, Xorcom
+# This program is free software; you can redistribute and/or
+# modify it under the same terms as Perl itself.
+#
+# $Id$
+#
+use strict;
+
+my $conf_file = "/etc/dahdi/xpp.conf";
+
+sub import {
+	my $pack = shift || die "Import without package?";
+	my $init_dir = shift || die "$pack::import -- missing init_dir parameter";
+	my $local_conf = "$init_dir/xpp.conf";
+	$conf_file = $local_conf if -r $local_conf;
+}
+
+sub read_config($) {
+	my $opts = shift || die;
+
+	open(F, $conf_file) || return ();
+	while(<F>) {
+		chomp;
+		s/#.*//;	# strip comments
+		next unless /\S/;
+		s/\s*$//;	# Trim trailing whitespace
+		my ($key, $value) = split(/\s+/, $_, 2);
+		$opts->{$key} = $value;
+	}
+	close F;
+	$opts->{'xppconf'} = $conf_file;
+	return %{$opts};
+}
+
+1;
diff --git a/drivers/dahdi/xpp/card_bri.c b/drivers/dahdi/xpp/card_bri.c
new file mode 100644
index 0000000..12efecf
--- /dev/null
+++ b/drivers/dahdi/xpp/card_bri.c
@@ -0,0 +1,1808 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2006, Xorcom
+ *
+ * Parts derived from Cologne demo driver for the chip.
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <linux/seq_file.h>
+#include "xpd.h"
+#include "xproto.h"
+#include "xpp_dahdi.h"
+#include "card_bri.h"
+#include "dahdi_debug.h"
+#include "xbus-core.h"
+
+static const char rcsid[] = "$Id$";
+
+#ifndef	DAHDI_SIG_HARDHDLC
+#error Cannot build BRI without HARDHDLC supprt
+#endif
+
+/* must be before dahdi_debug.h */
+static DEF_PARM(int, debug, 0, 0644, "Print DBG statements");
+static DEF_PARM(uint, poll_interval, 500, 0644,
+		"Poll channel state interval in milliseconds (0 - disable)");
+static DEF_PARM_BOOL(nt_keepalive, 1, 0644,
+		     "Force BRI_NT to keep trying connection");
+
+enum xhfc_states {
+	ST_RESET = 0,		/* G/F0 */
+	/* TE */
+	ST_TE_SENSING = 2,	/* F2   */
+	ST_TE_DEACTIVATED = 3,	/* F3   */
+	ST_TE_SIGWAIT = 4,	/* F4   */
+	ST_TE_IDENT = 5,	/* F5   */
+	ST_TE_SYNCED = 6,	/* F6   */
+	ST_TE_ACTIVATED = 7,	/* F7   */
+	ST_TE_LOST_FRAMING = 8,	/* F8   */
+	/* NT */
+	ST_NT_DEACTIVATED = 1,	/* G1   */
+	ST_NT_ACTIVATING = 2,	/* G2   */
+	ST_NT_ACTIVATED = 3,	/* G3   */
+	ST_NT_DEACTIVTING = 4,	/* G4   */
+};
+
+#ifdef CONFIG_PROC_FS
+static const char *xhfc_state_name(bool is_nt, enum xhfc_states state)
+{
+	const char *p;
+
+#define	_E(x)	[ST_ ## x] = #x
+	static const char *te_names[] = {
+		_E(RESET),
+		_E(TE_SENSING),
+		_E(TE_DEACTIVATED),
+		_E(TE_SIGWAIT),
+		_E(TE_IDENT),
+		_E(TE_SYNCED),
+		_E(TE_ACTIVATED),
+		_E(TE_LOST_FRAMING),
+	};
+	static const char *nt_names[] = {
+		_E(RESET),
+		_E(NT_DEACTIVATED),
+		_E(NT_ACTIVATING),
+		_E(NT_ACTIVATED),
+		_E(NT_DEACTIVTING),
+	};
+#undef	_E
+	if (is_nt) {
+		if (state > ST_NT_DEACTIVTING)
+			p = "NT ???";
+		else
+			p = nt_names[state];
+	} else {
+		if (state > ST_TE_LOST_FRAMING)
+			p = "TE ???";
+		else
+			p = te_names[state];
+	}
+	return p;
+}
+#endif
+
+/* xhfc Layer1 physical commands */
+#define HFC_L1_ACTIVATE_TE		0x01
+#define HFC_L1_FORCE_DEACTIVATE_TE	0x02
+#define HFC_L1_ACTIVATE_NT		0x03
+#define HFC_L1_DEACTIVATE_NT		0x04
+
+#define HFC_L1_ACTIVATING	1
+#define HFC_L1_ACTIVATED	2
+#define	HFC_TIMER_T1		2500
+#define	HFC_TIMER_T3		8000	/* 8s activation timer T3 */
+#define	HFC_TIMER_OFF		-1	/* timer disabled */
+
+#define	A_SU_WR_STA		0x30	/* ST/Up state machine register */
+#define		V_SU_LD_STA	0x10
+#define	V_SU_ACT	0x60	/* start activation/deactivation        */
+#define	STA_DEACTIVATE	0x40	/* start deactivation in A_SU_WR_STA */
+#define	STA_ACTIVATE	0x60	/* start activation   in A_SU_WR_STA */
+#define	V_SU_SET_G2_G3	0x80
+
+#define	A_SU_RD_STA		0x30
+typedef union {
+	struct {
+		__u8 v_su_sta:4;
+		__u8 v_su_fr_sync:1;
+		__u8 v_su_t2_exp:1;
+		__u8 v_su_info0:1;
+		__u8 v_g2_g3:1;
+	} bits;
+	__u8 reg;
+} su_rd_sta_t;
+
+#define	REG30_LOST	3	/* in polls */
+#define	DCHAN_LOST	15000	/* in ticks */
+
+#define	BRI_DCHAN_SIGCAP	DAHDI_SIG_HARDHDLC
+#define	BRI_BCHAN_SIGCAP	(DAHDI_SIG_CLEAR | DAHDI_SIG_DACS)
+
+#define	IS_NT(xpd)		(PHONEDEV(xpd).direction == TO_PHONE)
+#define	BRI_PORT(xpd)		((xpd)->addr.subunit)
+
+/* shift in PCM highway */
+#define	SUBUNIT_PCM_SHIFT	4
+#define	PCM_SHIFT(mask, sunit)	((mask) << (SUBUNIT_PCM_SHIFT * (sunit)))
+
+/*---------------- BRI Protocol Commands ----------------------------------*/
+
+static int write_state_register(xpd_t *xpd, __u8 value);
+static bool bri_packet_is_valid(xpacket_t *pack);
+static void bri_packet_dump(const char *msg, xpacket_t *pack);
+#ifdef	CONFIG_PROC_FS
+static const struct file_operations proc_bri_info_ops;
+#endif
+static int bri_spanconfig(struct file *file, struct dahdi_span *span,
+			  struct dahdi_lineconfig *lc);
+static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
+			  int sigtype);
+static int bri_startup(struct file *file, struct dahdi_span *span);
+static int bri_shutdown(struct dahdi_span *span);
+
+#define	PROC_BRI_INFO_FNAME	"bri_info"
+
+enum led_state {
+	BRI_LED_OFF = 0x0,
+	BRI_LED_ON = 0x1,
+	/*
+	 * We blink by software from driver, so that
+	 * if the driver malfunction that blink would stop.
+	 */
+	// BRI_LED_BLINK_SLOW   = 0x2,  /* 1/2 a second blink cycle */
+	// BRI_LED_BLINK_FAST   = 0x3   /* 1/4 a second blink cycle */
+};
+
+enum bri_led_names {
+	GREEN_LED = 0,
+	RED_LED = 1
+};
+
+#define	NUM_LEDS	2
+#define	LED_TICKS	100
+
+struct bri_leds {
+	__u8 state:2;
+	__u8 led_sel:1;		/* 0 - GREEN, 1 - RED */
+	__u8 reserved:5;
+};
+
+#ifndef MAX_DFRAME_LEN_L1
+#define MAX_DFRAME_LEN_L1 300
+#endif
+
+#define	DCHAN_BUFSIZE	MAX_DFRAME_LEN_L1
+
+struct BRI_priv_data {
+	struct proc_dir_entry *bri_info;
+	su_rd_sta_t state_register;
+	bool initialized;
+	bool dchan_is_open;
+	int t1;			/* timer 1 for NT deactivation */
+	int t3;			/* timer 3 for TE activation */
+	ulong l1_flags;
+	bool reg30_good;
+	uint reg30_ticks;
+	bool layer1_up;
+
+	/*
+	 * D-Chan: buffers + extra state info.
+	 */
+	atomic_t hdlc_pending;
+	bool txframe_begin;
+
+	uint tick_counter;
+	uint poll_counter;
+	uint dchan_tx_counter;
+	uint dchan_rx_counter;
+	uint dchan_rx_drops;
+	bool dchan_alive;
+	uint dchan_alive_ticks;
+	uint dchan_notx_ticks;
+	uint dchan_norx_ticks;
+	enum led_state ledstate[NUM_LEDS];
+};
+
+static xproto_table_t PROTO_TABLE(BRI);
+
+DEF_RPACKET_DATA(BRI, SET_LED,	/* Set one of the LED's */
+		 struct bri_leds bri_leds;);
+
+static /* 0x33 */ DECLARE_CMD(BRI, SET_LED, enum bri_led_names which_led,
+			      enum led_state to_led_state);
+
+#define	DO_LED(xpd, which, tostate) \
+		CALL_PROTO(BRI, SET_LED, (xpd)->xbus, (xpd), (which), (tostate))
+
+#define DEBUG_BUF_SIZE (100)
+static void dump_hex_buf(xpd_t *xpd, char *msg, __u8 *buf, size_t len)
+{
+	char debug_buf[DEBUG_BUF_SIZE + 1];
+	int i;
+	int n = 0;
+
+	debug_buf[0] = '\0';
+	for (i = 0; i < len && n < DEBUG_BUF_SIZE; i++)
+		n += snprintf(&debug_buf[n], DEBUG_BUF_SIZE - n, "%02X ",
+			      buf[i]);
+	XPD_NOTICE(xpd, "%s[0..%zd]: %s%s\n", msg, len - 1, debug_buf,
+		   (n >= DEBUG_BUF_SIZE) ? "..." : "");
+}
+
+static void dump_dchan_packet(xpd_t *xpd, bool transmit, __u8 *buf, int len)
+{
+	struct BRI_priv_data *priv;
+	char msgbuf[MAX_PROC_WRITE];
+	char ftype = '?';
+	char *direction;
+	int frame_begin;
+
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (transmit) {
+		direction = "TX";
+		frame_begin = priv->txframe_begin;
+	} else {
+		direction = "RX";
+		frame_begin = 1;
+	}
+	if (frame_begin) {	/* Packet start */
+		if (!IS_SET(buf[0], 7))
+			ftype = 'I';	/* Information */
+		else if (IS_SET(buf[0], 7) && !IS_SET(buf[0], 6))
+			ftype = 'S';	/* Supervisory */
+		else if (IS_SET(buf[0], 7) && IS_SET(buf[0], 6))
+			ftype = 'U';	/* Unnumbered */
+		else
+			XPD_NOTICE(xpd, "Unknown frame type 0x%X\n", buf[0]);
+
+		snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s = (%c) ", direction,
+			 ftype);
+	} else {
+		snprintf(msgbuf, MAX_PROC_WRITE, "D-Chan %s =     ", direction);
+	}
+	dump_hex_buf(xpd, msgbuf, buf, len);
+}
+
+static void set_bri_timer(xpd_t *xpd, const char *name, int *bri_timer,
+			  int value)
+{
+	if (value == HFC_TIMER_OFF)
+		XPD_DBG(SIGNAL, xpd, "Timer %s DISABLE\n", name);
+	else
+		XPD_DBG(SIGNAL, xpd, "Timer %s: set to %d\n", name, value);
+	*bri_timer = value;
+}
+
+static void dchan_state(xpd_t *xpd, bool up)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (priv->dchan_alive == up)
+		return;
+	if (up) {
+		XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel RUNNING\n");
+		priv->dchan_alive = 1;
+	} else {
+		XPD_DBG(SIGNAL, xpd, "STATE CHANGE: D-Channel STOPPED\n");
+		priv->dchan_rx_counter = priv->dchan_tx_counter =
+		    priv->dchan_rx_drops = 0;
+		priv->dchan_alive = 0;
+		priv->dchan_alive_ticks = 0;
+	}
+}
+
+static void layer1_state(xpd_t *xpd, bool up)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (priv->layer1_up == up)
+		return;
+	priv->layer1_up = up;
+	XPD_DBG(SIGNAL, xpd, "STATE CHANGE: Layer1 %s\n", (up) ? "UP" : "DOWN");
+	if (!up)
+		dchan_state(xpd, 0);
+}
+
+static void te_activation(xpd_t *xpd, bool on)
+{
+	struct BRI_priv_data *priv;
+	__u8 curr_state;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	curr_state = priv->state_register.bits.v_su_sta;
+	XPD_DBG(SIGNAL, xpd, "%s\n", (on) ? "ON" : "OFF");
+	if (on) {
+		if (curr_state == ST_TE_DEACTIVATED) {
+			XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_TE\n");
+			set_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
+			write_state_register(xpd, STA_ACTIVATE);
+			set_bri_timer(xpd, "T3", &priv->t3, HFC_TIMER_T3);
+		} else {
+			XPD_DBG(SIGNAL, xpd,
+				"HFC_L1_ACTIVATE_TE (state %d, ignored)\n",
+				curr_state);
+		}
+	} else {		/* happen only because of T3 expiry */
+		switch (curr_state) {
+		case ST_TE_DEACTIVATED:	/* F3   */
+		case ST_TE_SYNCED:	/* F6   */
+		case ST_TE_ACTIVATED:	/* F7   */
+			XPD_DBG(SIGNAL, xpd,
+				"HFC_L1_FORCE_DEACTIVATE_TE "
+				"(state %d, ignored)\n",
+				curr_state);
+			break;
+		case ST_TE_SIGWAIT:	/* F4   */
+		case ST_TE_IDENT:	/* F5   */
+		case ST_TE_LOST_FRAMING:	/* F8   */
+			XPD_DBG(SIGNAL, xpd, "HFC_L1_FORCE_DEACTIVATE_TE\n");
+			write_state_register(xpd, STA_DEACTIVATE);
+			break;
+		default:
+			XPD_NOTICE(xpd, "Bad TE state: %d\n", curr_state);
+			break;
+		}
+	}
+}
+
+static void nt_activation(xpd_t *xpd, bool on)
+{
+	struct BRI_priv_data *priv;
+	__u8 curr_state;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	curr_state = priv->state_register.bits.v_su_sta;
+	XPD_DBG(SIGNAL, xpd, "%s\n", (on) ? "ON" : "OFF");
+	if (on) {
+		switch (curr_state) {
+		case ST_RESET:	/* F/G 0 */
+		case ST_NT_DEACTIVATED:	/* G1 */
+		case ST_NT_DEACTIVTING:	/* G4 */
+			XPD_DBG(SIGNAL, xpd, "HFC_L1_ACTIVATE_NT\n");
+			set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_T1);
+			set_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
+			write_state_register(xpd, STA_ACTIVATE);
+			break;
+		case ST_NT_ACTIVATING:	/* G2 */
+		case ST_NT_ACTIVATED:	/* G3 */
+			XPD_DBG(SIGNAL, xpd,
+				"HFC_L1_ACTIVATE_NT (in state %d, ignored)\n",
+				curr_state);
+			break;
+		}
+	} else {
+		switch (curr_state) {
+		case ST_RESET:	/* F/G 0 */
+		case ST_NT_DEACTIVATED:	/* G1 */
+		case ST_NT_DEACTIVTING:	/* G4 */
+			XPD_DBG(SIGNAL, xpd,
+				"HFC_L1_DEACTIVATE_NT (in state %d, ignored)\n",
+				curr_state);
+			break;
+		case ST_NT_ACTIVATING:	/* G2 */
+		case ST_NT_ACTIVATED:	/* G3 */
+			XPD_DBG(SIGNAL, xpd, "HFC_L1_DEACTIVATE_NT\n");
+			write_state_register(xpd, STA_DEACTIVATE);
+			break;
+		default:
+			XPD_NOTICE(xpd, "Bad NT state: %d\n", curr_state);
+			break;
+		}
+	}
+}
+
+/*
+ * D-Chan receive
+ */
+static int bri_check_stat(xpd_t *xpd, struct dahdi_chan *dchan, __u8 *buf,
+			  int len)
+{
+	struct BRI_priv_data *priv;
+	__u8 status;
+
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (len <= 0) {
+		XPD_NOTICE(xpd, "D-Chan RX DROP: short frame (len=%d)\n", len);
+		dahdi_hdlc_abort(dchan, DAHDI_EVENT_ABORT);
+		return -EPROTO;
+	}
+	status = buf[len - 1];
+	if (status) {
+		int event = DAHDI_EVENT_ABORT;
+
+		if (status == 0xFF) {
+			XPD_NOTICE(xpd, "D-Chan RX DROP: ABORT: %d\n", status);
+		} else {
+			XPD_NOTICE(xpd, "D-Chan RX DROP: BADFCS: %d\n", status);
+			event = DAHDI_EVENT_BADFCS;
+		}
+		dump_hex_buf(xpd, "D-Chan RX:    current packet", buf, len);
+		dahdi_hdlc_abort(dchan, event);
+		return -EPROTO;
+	}
+	return 0;
+}
+
+static int rx_dchan(xpd_t *xpd, reg_cmd_t *regcmd)
+{
+	struct BRI_priv_data *priv;
+	__u8 *src;
+	struct dahdi_chan *dchan;
+	uint len;
+	bool eoframe;
+	int ret = 0;
+
+	src = REG_XDATA(regcmd);
+	len = regcmd->h.bytes;
+	eoframe = regcmd->h.eoframe;
+	if (len <= 0)
+		return 0;
+	if (!SPAN_REGISTERED(xpd))	/* Nowhere to copy data */
+		return 0;
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	dchan = XPD_CHAN(xpd, 2);
+	if (!IS_OFFHOOK(xpd, 2)) {	/* D-chan is used? */
+		static int rate_limit;
+
+		if ((rate_limit++ % 1000) == 0)
+			XPD_DBG(SIGNAL, xpd, "D-Chan unused\n");
+		goto out;
+	}
+	XPD_DBG(GENERAL, xpd, "D-Chan RX: eoframe=%d len=%d\n", eoframe, len);
+	dahdi_hdlc_putbuf(dchan, src, (eoframe) ? len - 1 : len);
+	if (!eoframe)
+		goto out;
+	if ((ret = bri_check_stat(xpd, dchan, src, len)) < 0)
+		goto out;
+	/*
+	 * Tell Dahdi that we received len-1 bytes.
+	 * They include the data and a 2-byte checksum.
+	 * The last byte (that we don't pass on) is 0 if the
+	 * checksum is correct. If it were wrong, we would drop the
+	 * packet in the "if (src[len-1])" above.
+	 */
+	dahdi_hdlc_finish(dchan);
+	priv->dchan_rx_counter++;
+	priv->dchan_norx_ticks = 0;
+out:
+	return ret;
+}
+
+/*
+ * D-Chan transmit
+ */
+/*
+ * DAHDI calls this when it has data it wants to send to
+ * the HDLC controller
+ */
+static void bri_hdlc_hard_xmit(struct dahdi_chan *chan)
+{
+	xpd_t *xpd = chan->pvt;
+	struct dahdi_chan *dchan;
+	struct BRI_priv_data *priv;
+
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	dchan = XPD_CHAN(xpd, 2);
+	if (dchan == chan)
+		atomic_inc(&priv->hdlc_pending);
+}
+
+static int send_dchan_frame(xpd_t *xpd, xframe_t *xframe, bool is_eof)
+{
+	struct BRI_priv_data *priv;
+	int ret;
+
+	XPD_DBG(COMMANDS, xpd, "eoframe=%d\n", is_eof);
+	priv = xpd->priv;
+	if (!test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
+	    && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
+		XPD_DBG(SIGNAL, xpd,
+			"Want to transmit: Kick D-Channel transmiter\n");
+		if (!IS_NT(xpd))
+			te_activation(xpd, 1);
+		else
+			nt_activation(xpd, 1);
+	}
+	dump_xframe("send_dchan_frame", xpd->xbus, xframe, debug);
+	ret = send_cmd_frame(xpd->xbus, xframe);
+	if (ret < 0)
+		XPD_ERR(xpd, "%s: failed sending xframe\n", __func__);
+	if (is_eof) {
+		atomic_dec(&priv->hdlc_pending);
+		priv->dchan_tx_counter++;
+		priv->txframe_begin = 1;
+	} else
+		priv->txframe_begin = 0;
+	priv->dchan_notx_ticks = 0;
+	return ret;
+}
+
+/*
+ * Fill a single multibyte REGISTER_REQUEST
+ */
+static void fill_multibyte(xpd_t *xpd, xpacket_t *pack,
+	bool eoframe, char *buf, int len)
+{
+	reg_cmd_t *reg_cmd;
+	char *p;
+
+	XPACKET_INIT(pack, GLOBAL, REGISTER_REQUEST, xpd->xbus_idx, 0, 0);
+	XPACKET_LEN(pack) = XFRAME_CMD_LEN(REG);
+	reg_cmd = &RPACKET_FIELD(pack, GLOBAL, REGISTER_REQUEST, reg_cmd);
+	reg_cmd->h.bytes = len;
+	reg_cmd->h.is_multibyte = 1;
+	reg_cmd->h.portnum = xpd->addr.subunit;
+	reg_cmd->h.eoframe = eoframe;
+	p = REG_XDATA(reg_cmd);
+	memcpy(p, buf, len);
+	if (debug)
+		dump_dchan_packet(xpd, 1, p, len);
+}
+
+/*
+ * Transmit available D-Channel frames
+ *
+ * - FPGA firmware expect to get this as a sequence of REGISTER_REQUEST
+ *   multibyte commands.
+ * - The payload of each command is limited to MULTIBYTE_MAX_LEN bytes.
+ * - We batch several REGISTER_REQUEST packets into a single xframe.
+ * - The xframe is terminated when we get a bri "end of frame"
+ *   or when the xframe is full (should not happen).
+ */
+static int tx_dchan(xpd_t *xpd)
+{
+	struct BRI_priv_data *priv;
+	xframe_t *xframe;
+	xpacket_t *pack;
+	int packet_count;
+	int eoframe;
+	int ret;
+
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (atomic_read(&priv->hdlc_pending) == 0)
+		return 0;
+	if (!SPAN_REGISTERED(xpd)
+	    || !(PHONEDEV(xpd).span.flags & DAHDI_FLAG_RUNNING))
+		return 0;
+	/* Allocate frame */
+	xframe = ALLOC_SEND_XFRAME(xpd->xbus);
+	if (!xframe) {
+		XPD_NOTICE(xpd, "%s: failed to allocate new xframe\n",
+			   __func__);
+		return -ENOMEM;
+	}
+	for (packet_count = 0, eoframe = 0; !eoframe; packet_count++) {
+		int packet_len = XFRAME_CMD_LEN(REG);
+		char buf[MULTIBYTE_MAX_LEN];
+		int len = MULTIBYTE_MAX_LEN;
+
+		/* Reserve packet */
+		pack = xframe_next_packet(xframe, packet_len);
+		if (!pack) {
+			BUG_ON(!packet_count);
+			/*
+			 * A split. Send what we currently have.
+			 */
+			XPD_NOTICE(xpd, "%s: xframe is full (%d packets)\n",
+				   __func__, packet_count);
+			break;
+		}
+		/* Get data from DAHDI */
+		eoframe = dahdi_hdlc_getbuf(XPD_CHAN(xpd, 2), buf, &len);
+		if (len <= 0) {
+			/*
+			 * Already checked priv->hdlc_pending,
+			 * should never get here.
+			 */
+			if (printk_ratelimit())
+				XPD_ERR(xpd,
+					"%s: hdlc_pending, but nothing "
+					"to transmit?\n", __func__);
+			FREE_SEND_XFRAME(xpd->xbus, xframe);
+			return -EINVAL;
+		}
+		BUG_ON(len > MULTIBYTE_MAX_LEN);
+		fill_multibyte(xpd, pack, eoframe != 0, buf, len);
+	}
+	return send_dchan_frame(xpd, xframe, eoframe != 0);
+	return ret;
+}
+
+/*---------------- BRI: Methods -------------------------------------------*/
+
+static void bri_proc_remove(xbus_t *xbus, xpd_t *xpd)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	XPD_DBG(PROC, xpd, "\n");
+#ifdef	CONFIG_PROC_FS
+	if (priv->bri_info) {
+		XPD_DBG(PROC, xpd, "Removing '%s'\n", PROC_BRI_INFO_FNAME);
+		remove_proc_entry(PROC_BRI_INFO_FNAME, xpd->proc_xpd_dir);
+	}
+#endif
+}
+
+static int bri_proc_create(xbus_t *xbus, xpd_t *xpd)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	XPD_DBG(PROC, xpd, "\n");
+#ifdef	CONFIG_PROC_FS
+	XPD_DBG(PROC, xpd, "Creating '%s'\n", PROC_BRI_INFO_FNAME);
+	priv->bri_info = proc_create_data(PROC_BRI_INFO_FNAME, 0444,
+				 xpd->proc_xpd_dir, &proc_bri_info_ops, xpd);
+	if (!priv->bri_info) {
+		XPD_ERR(xpd, "Failed to create proc file '%s'\n",
+			PROC_BRI_INFO_FNAME);
+		bri_proc_remove(xbus, xpd);
+		return -EINVAL;
+	}
+	SET_PROC_DIRENTRY_OWNER(priv->bri_info);
+#endif
+	return 0;
+}
+
+static xpd_t *BRI_card_new(xbus_t *xbus, int unit, int subunit,
+			   const xproto_table_t *proto_table,
+			   const struct unit_descriptor *unit_descriptor,
+			   bool to_phone)
+{
+	xpd_t *xpd = NULL;
+	int channels = min(3, CHANNELS_PERXPD);
+
+	if ((unit_descriptor->ports_per_chip < 1) ||
+			(unit_descriptor->ports_per_chip > 4)) {
+		XBUS_ERR(xbus, "Bad ports_per_chip=%d\n",
+				unit_descriptor->ports_per_chip);
+		return NULL;
+	}
+	if ((unit_descriptor->numchips) < 1 ||
+			(unit_descriptor->numchips > 2)) {
+		XBUS_ERR(xbus, "Bad numchips=%d\n",
+				unit_descriptor->numchips);
+		return NULL;
+	}
+	XBUS_DBG(GENERAL, xbus, "\n");
+	xpd =
+	    xpd_alloc(xbus, unit, subunit,
+		      sizeof(struct BRI_priv_data), proto_table, unit_descriptor, channels);
+	if (!xpd)
+		return NULL;
+	PHONEDEV(xpd).direction = (to_phone) ? TO_PHONE : TO_PSTN;
+	xpd->type_name = (to_phone) ? "BRI_NT" : "BRI_TE";
+	xbus->sync_mode_default = SYNC_MODE_AB;
+	if (bri_proc_create(xbus, xpd) < 0)
+		goto err;
+	return xpd;
+err:
+	xpd_free(xpd);
+	return NULL;
+}
+
+static int BRI_card_init(xbus_t *xbus, xpd_t *xpd)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	XPD_DBG(GENERAL, xpd, "\n");
+	priv = xpd->priv;
+	DO_LED(xpd, GREEN_LED, BRI_LED_OFF);
+	DO_LED(xpd, RED_LED, BRI_LED_OFF);
+	set_bri_timer(xpd, "T1", &priv->t1, HFC_TIMER_OFF);
+	write_state_register(xpd, 0);	/* Enable L1 state machine */
+	priv->initialized = 1;
+	return 0;
+}
+
+static int BRI_card_remove(xbus_t *xbus, xpd_t *xpd)
+{
+	BUG_ON(!xpd);
+	XPD_DBG(GENERAL, xpd, "\n");
+	bri_proc_remove(xbus, xpd);
+	return 0;
+}
+
+#ifdef	DAHDI_AUDIO_NOTIFY
+static int bri_audio_notify(struct dahdi_chan *chan, int on)
+{
+	xpd_t *xpd = chan->pvt;
+	int pos = chan->chanpos - 1;
+
+	BUG_ON(!xpd);
+	LINE_DBG(SIGNAL, xpd, pos, "BRI-AUDIO: %s\n", (on) ? "on" : "off");
+	mark_offhook(xpd, pos, on);
+	return 0;
+}
+#endif
+
+static const struct dahdi_span_ops BRI_span_ops = {
+	.owner = THIS_MODULE,
+	.spanconfig = bri_spanconfig,
+	.chanconfig = bri_chanconfig,
+	.startup = bri_startup,
+	.shutdown = bri_shutdown,
+	.hdlc_hard_xmit = bri_hdlc_hard_xmit,
+	.open = xpp_open,
+	.close = xpp_close,
+	.hooksig = xpp_hooksig,	/* Only with RBS bits */
+	.ioctl = xpp_ioctl,
+	.maint = xpp_maint,
+	.echocan_create = xpp_echocan_create,
+	.echocan_name = xpp_echocan_name,
+	.assigned = xpp_span_assigned,
+#ifdef	DAHDI_SYNC_TICK
+	.sync_tick = dahdi_sync_tick,
+#endif
+#ifdef	CONFIG_DAHDI_WATCHDOG
+	.watchdog = xpp_watchdog,
+#endif
+
+#ifdef	DAHDI_AUDIO_NOTIFY
+	.audio_notify = bri_audio_notify,
+#endif
+};
+
+static int BRI_card_dahdi_preregistration(xpd_t *xpd, bool on)
+{
+	xbus_t *xbus;
+	struct BRI_priv_data *priv;
+	int i;
+
+	BUG_ON(!xpd);
+	xbus = xpd->xbus;
+	priv = xpd->priv;
+	BUG_ON(!xbus);
+	XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
+	if (!on) {
+		/* Nothing to do yet */
+		return 0;
+	}
+	PHONEDEV(xpd).span.spantype =
+		(PHONEDEV(xpd).direction == TO_PHONE)
+			? SPANTYPE_DIGITAL_BRI_NT
+			: SPANTYPE_DIGITAL_BRI_TE;
+	PHONEDEV(xpd).span.linecompat = DAHDI_CONFIG_AMI | DAHDI_CONFIG_CCS;
+	PHONEDEV(xpd).span.deflaw = DAHDI_LAW_ALAW;
+	BIT_SET(PHONEDEV(xpd).digital_signalling, 2);	/* D-Channel */
+	for_each_line(xpd, i) {
+		struct dahdi_chan *cur_chan = XPD_CHAN(xpd, i);
+
+		XPD_DBG(GENERAL, xpd, "setting BRI channel %d\n", i);
+		snprintf(cur_chan->name, MAX_CHANNAME, "XPP_%s/%02d/%1d%1d/%d",
+			 xpd->type_name, xbus->num, xpd->addr.unit,
+			 xpd->addr.subunit, i);
+		cur_chan->chanpos = i + 1;
+		cur_chan->pvt = xpd;
+		if (i == 2) {	/* D-CHAN */
+			cur_chan->sigcap = BRI_DCHAN_SIGCAP;
+			clear_bit(DAHDI_FLAGBIT_HDLC, &cur_chan->flags);
+			priv->txframe_begin = 1;
+			atomic_set(&priv->hdlc_pending, 0);
+		} else {
+			cur_chan->sigcap = BRI_BCHAN_SIGCAP;
+		}
+	}
+	CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
+	PHONEDEV(xpd).span.ops = &BRI_span_ops;
+	return 0;
+}
+
+static int BRI_card_dahdi_postregistration(xpd_t *xpd, bool on)
+{
+	xbus_t *xbus;
+
+	BUG_ON(!xpd);
+	xbus = xpd->xbus;
+	BUG_ON(!xbus);
+	XPD_DBG(GENERAL, xpd, "%s\n", (on) ? "on" : "off");
+	return (0);
+}
+
+static int BRI_card_hooksig(xpd_t *xpd, int pos, enum dahdi_txsig txsig)
+{
+	LINE_DBG(SIGNAL, xpd, pos, "%s\n", txsig2str(txsig));
+	return 0;
+}
+
+/*
+ * LED managment is done by the driver now:
+ *   - Turn constant ON RED/GREEN led to indicate NT/TE port
+ *   - Very fast "Double Blink" to indicate Layer1 alive (without D-Channel)
+ *   - Constant blink (1/2 sec cycle) to indicate D-Channel alive.
+ */
+static void handle_leds(xbus_t *xbus, xpd_t *xpd)
+{
+	struct BRI_priv_data *priv;
+	unsigned int timer_count;
+	int which_led;
+	int other_led;
+	int mod;
+
+	BUG_ON(!xpd);
+	if (IS_NT(xpd)) {
+		which_led = RED_LED;
+		other_led = GREEN_LED;
+	} else {
+		which_led = GREEN_LED;
+		other_led = RED_LED;
+	}
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	timer_count = xpd->timer_count;
+	if (xpd->blink_mode) {
+		if ((timer_count % DEFAULT_LED_PERIOD) == 0) {
+			// led state is toggled
+			if (priv->ledstate[which_led] == BRI_LED_OFF) {
+				DO_LED(xpd, which_led, BRI_LED_ON);
+				DO_LED(xpd, other_led, BRI_LED_ON);
+			} else {
+				DO_LED(xpd, which_led, BRI_LED_OFF);
+				DO_LED(xpd, other_led, BRI_LED_OFF);
+			}
+		}
+		return;
+	}
+	if (priv->ledstate[other_led] != BRI_LED_OFF)
+		DO_LED(xpd, other_led, BRI_LED_OFF);
+	if (priv->dchan_alive) {
+		mod = timer_count % 1000;
+		switch (mod) {
+		case 0:
+			DO_LED(xpd, which_led, BRI_LED_ON);
+			break;
+		case 500:
+			DO_LED(xpd, which_led, BRI_LED_OFF);
+			break;
+		}
+	} else if (priv->layer1_up) {
+		mod = timer_count % 1000;
+		switch (mod) {
+		case 0:
+		case 100:
+			DO_LED(xpd, which_led, BRI_LED_ON);
+			break;
+		case 50:
+		case 150:
+			DO_LED(xpd, which_led, BRI_LED_OFF);
+			break;
+		}
+	} else {
+		if (priv->ledstate[which_led] != BRI_LED_ON)
+			DO_LED(xpd, which_led, BRI_LED_ON);
+	}
+}
+
+static void handle_bri_timers(xpd_t *xpd)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (IS_NT(xpd)) {
+		if (priv->t1 > HFC_TIMER_OFF) {
+			if (--priv->t1 == 0) {
+				set_bri_timer(xpd, "T1", &priv->t1,
+					      HFC_TIMER_OFF);
+				if (!nt_keepalive) {
+					/* G2 */
+					if (priv->state_register.bits.v_su_sta == ST_NT_ACTIVATING) {
+						XPD_DBG(SIGNAL, xpd,
+							"T1 Expired. "
+							"Deactivate NT\n");
+						clear_bit(HFC_L1_ACTIVATING,
+							  &priv->l1_flags);
+						/* Deactivate NT */
+						nt_activation(xpd, 0);
+					} else
+						XPD_DBG(SIGNAL, xpd,
+							"T1 Expired. "
+							"(state %d, ignored)\n",
+							priv->state_register.
+							bits.v_su_sta);
+				}
+			}
+		}
+	} else {
+		if (priv->t3 > HFC_TIMER_OFF) {
+			/* timer expired ? */
+			if (--priv->t3 == 0) {
+				XPD_DBG(SIGNAL, xpd,
+					"T3 expired. Deactivate TE\n");
+				set_bri_timer(xpd, "T3", &priv->t3,
+					      HFC_TIMER_OFF);
+				clear_bit(HFC_L1_ACTIVATING, &priv->l1_flags);
+				te_activation(xpd, 0);	/* Deactivate TE */
+			}
+		}
+	}
+}
+
+/* Poll the register ST/Up-State-machine Register, to see if the cable
+ * if a cable is connected to the port.
+ */
+static int BRI_card_tick(xbus_t *xbus, xpd_t *xpd)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (!priv->initialized || !xbus->self_ticking)
+		return 0;
+	if (poll_interval != 0 && (priv->tick_counter % poll_interval) == 0) {
+		// XPD_DBG(GENERAL, xpd, "%d\n", priv->tick_counter);
+		priv->poll_counter++;
+		xpp_register_request(xbus, xpd,
+			BRI_PORT(xpd),	/* portno       */
+			0,		/* writing      */
+			A_SU_RD_STA,	/* regnum       */
+			0,		/* do_subreg    */
+			0,		/* subreg       */
+			0,		/* data_low     */
+			0,		/* do_datah     */
+			0,		/* data_high    */
+			0,		/* should_reply */
+			0		/* do_expander  */
+		    );
+
+		if (IS_NT(xpd) && nt_keepalive
+		    && !test_bit(HFC_L1_ACTIVATED, &priv->l1_flags)
+		    && !test_bit(HFC_L1_ACTIVATING, &priv->l1_flags)) {
+			XPD_DBG(SIGNAL, xpd, "Kick NT D-Channel\n");
+			nt_activation(xpd, 1);
+		}
+	}
+	/* Detect D-Channel disconnect heuristic */
+	priv->dchan_notx_ticks++;
+	priv->dchan_norx_ticks++;
+	priv->dchan_alive_ticks++;
+	if (priv->dchan_alive
+	    && (priv->dchan_notx_ticks > DCHAN_LOST
+		|| priv->dchan_norx_ticks > DCHAN_LOST)) {
+		/*
+		 * No tx_dchan() or rx_dchan() for many ticks
+		 * This D-Channel is probabelly dead.
+		 */
+		dchan_state(xpd, 0);
+	} else if (priv->dchan_rx_counter > 1 && priv->dchan_tx_counter > 1) {
+		if (!priv->dchan_alive)
+			dchan_state(xpd, 1);
+	}
+	/* Detect Layer1 disconnect */
+	if (priv->reg30_good && priv->reg30_ticks > poll_interval * REG30_LOST) {
+		/* No reply for 1/2 a second */
+		XPD_ERR(xpd, "Lost state tracking for %d ticks\n",
+			priv->reg30_ticks);
+		priv->reg30_good = 0;
+		layer1_state(xpd, 0);
+	}
+	handle_leds(xbus, xpd);
+	handle_bri_timers(xpd);
+	tx_dchan(xpd);
+	priv->tick_counter++;
+	priv->reg30_ticks++;
+	return 0;
+}
+
+static int BRI_card_ioctl(xpd_t *xpd, int pos, unsigned int cmd,
+			  unsigned long arg)
+{
+	BUG_ON(!xpd);
+	if (!XBUS_IS(xpd->xbus, READY))
+		return -ENODEV;
+	switch (cmd) {
+	case DAHDI_TONEDETECT:
+		/*
+		 * Asterisk call all span types with this (FXS specific)
+		 * call. Silently ignore it.
+		 */
+		LINE_DBG(SIGNAL, xpd, pos, "BRI: Starting a call\n");
+		return -ENOTTY;
+	default:
+		report_bad_ioctl(THIS_MODULE->name, xpd, pos, cmd);
+		return -ENOTTY;
+	}
+	return 0;
+}
+
+static int BRI_card_open(xpd_t *xpd, lineno_t pos)
+{
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	if (pos == 2) {
+		priv->dchan_is_open = 1;
+		LINE_DBG(SIGNAL, xpd, pos, "OFFHOOK the whole span\n");
+		BIT_SET(PHONEDEV(xpd).offhook_state, 0);
+		BIT_SET(PHONEDEV(xpd).offhook_state, 1);
+		BIT_SET(PHONEDEV(xpd).offhook_state, 2);
+		CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
+	}
+	return 0;
+}
+
+static int BRI_card_close(xpd_t *xpd, lineno_t pos)
+{
+	struct BRI_priv_data *priv;
+
+	priv = xpd->priv;
+	/* Clear D-Channel pending data */
+	if (pos == 2) {
+		LINE_DBG(SIGNAL, xpd, pos, "ONHOOK the whole span\n");
+		BIT_CLR(PHONEDEV(xpd).offhook_state, 0);
+		BIT_CLR(PHONEDEV(xpd).offhook_state, 1);
+		BIT_CLR(PHONEDEV(xpd).offhook_state, 2);
+		CALL_PHONE_METHOD(card_pcm_recompute, xpd, 0);
+		priv->dchan_is_open = 0;
+	} else if (!priv->dchan_is_open)
+		mark_offhook(xpd, pos, 0);	/* e.g: patgen/pattest */
+	return 0;
+}
+
+/*
+ * Called only for 'span' keyword in /etc/dahdi/system.conf
+ */
+static int bri_spanconfig(struct file *file, struct dahdi_span *span,
+			  struct dahdi_lineconfig *lc)
+{
+	struct phonedev *phonedev = container_of(span, struct phonedev, span);
+	xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
+	const char *framingstr = "";
+	const char *codingstr = "";
+	const char *crcstr = "";
+
+	/* framing first */
+	if (lc->lineconfig & DAHDI_CONFIG_B8ZS)
+		framingstr = "B8ZS";
+	else if (lc->lineconfig & DAHDI_CONFIG_AMI)
+		framingstr = "AMI";
+	else if (lc->lineconfig & DAHDI_CONFIG_HDB3)
+		framingstr = "HDB3";
+	/* then coding */
+	if (lc->lineconfig & DAHDI_CONFIG_ESF)
+		codingstr = "ESF";
+	else if (lc->lineconfig & DAHDI_CONFIG_D4)
+		codingstr = "D4";
+	else if (lc->lineconfig & DAHDI_CONFIG_CCS)
+		codingstr = "CCS";
+	/* E1's can enable CRC checking */
+	if (lc->lineconfig & DAHDI_CONFIG_CRC4)
+		crcstr = "CRC4";
+	XPD_DBG(GENERAL, xpd,
+		"[%s]: span=%d (%s) lbo=%d lineconfig=%s/%s/%s (0x%X) sync=%d\n",
+		IS_NT(xpd) ? "NT" : "TE", lc->span, lc->name, lc->lbo,
+		framingstr, codingstr, crcstr, lc->lineconfig, lc->sync);
+	PHONEDEV(xpd).timing_priority = lc->sync;
+	elect_syncer("BRI-spanconfig");
+	/*
+	 * FIXME: validate
+	 */
+	span->lineconfig = lc->lineconfig;
+	return 0;
+}
+
+/*
+ * Set signalling type (if appropriate)
+ * Called from dahdi with spinlock held on chan. Must not call back
+ * dahdi functions.
+ */
+static int bri_chanconfig(struct file *file, struct dahdi_chan *chan,
+			  int sigtype)
+{
+	DBG(GENERAL, "channel %d (%s) -> %s\n", chan->channo, chan->name,
+	    sig2str(sigtype));
+	// FIXME: sanity checks:
+	// - should be supported (within the sigcap)
+	// - should not replace fxs <->fxo ??? (covered by previous?)
+	return 0;
+}
+
+/*
+ * Called only for 'span' keyword in /etc/dahdi/system.conf
+ */
+static int bri_startup(struct file *file, struct dahdi_span *span)
+{
+	struct phonedev *phonedev = container_of(span, struct phonedev, span);
+	xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
+	struct BRI_priv_data *priv;
+	struct dahdi_chan *dchan;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (!XBUS_IS(xpd->xbus, READY)) {
+		XPD_DBG(GENERAL, xpd,
+			"Startup called by dahdi. No Hardware. Ignored\n");
+		return -ENODEV;
+	}
+	XPD_DBG(GENERAL, xpd, "STARTUP\n");
+	// Turn on all channels
+	CALL_PHONE_METHOD(card_state, xpd, 1);
+	if (SPAN_REGISTERED(xpd)) {
+		dchan = XPD_CHAN(xpd, 2);
+		span->flags |= DAHDI_FLAG_RUNNING;
+		/*
+		 * Dahdi (wrongly) assume that D-Channel need HDLC decoding
+		 * and during dahdi registration override our flags.
+		 *
+		 * Don't Get Mad, Get Even:  Now we override dahdi :-)
+		 */
+		clear_bit(DAHDI_FLAGBIT_HDLC, &dchan->flags);
+	}
+	return 0;
+}
+
+/*
+ * Called only for 'span' keyword in /etc/dahdi/system.conf
+ */
+static int bri_shutdown(struct dahdi_span *span)
+{
+	struct phonedev *phonedev = container_of(span, struct phonedev, span);
+	xpd_t *xpd = container_of(phonedev, struct xpd, phonedev);
+	struct BRI_priv_data *priv;
+
+	BUG_ON(!xpd);
+	priv = xpd->priv;
+	BUG_ON(!priv);
+	if (!XBUS_IS(xpd->xbus, READY)) {
+		XPD_DBG(GENERAL, xpd,
+			"Shutdown called by dahdi. No Hardware. Ignored\n");
+		return -ENODEV;
+	}
+	XPD_DBG(GENERAL, xpd, "SHUTDOWN\n");
+	// Turn off all channels
+	CALL_PHONE_METHOD(card_state, xpd, 0);
+	return 0;
+}
+
+static void BRI_card_pcm_recompute(xpd_t *xpd, xpp_line_t dont_care)
+{
+	int i;
+	int line_count;
+	xpp_line_t pcm_mask;
+	uint pcm_len;
+	xpd_t *main_xpd;
+	unsigned long flags;
+
+	BUG_ON(!xpd);
+	main_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, 0);
+	if (!main_xpd) {
+		XPD_DBG(DEVICES, xpd,
+			"Unit 0 is already gone. Ignore request\n");
+		return;
+	}
+	/*
+	 * We calculate all subunits, so use the main lock
+	 * as a mutex for the whole operation.
+	 */
+	spin_lock_irqsave(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
+	line_count = 0;
+	pcm_mask = 0;
+	for (i = 0; i < MAX_SUBUNIT; i++) {
+		xpd_t *sub_xpd = xpd_byaddr(xpd->xbus, main_xpd->addr.unit, i);
+
+		if (sub_xpd) {
+			xpp_line_t lines =
+			    PHONEDEV(sub_xpd).
+			    offhook_state & ~(PHONEDEV(sub_xpd).
+					      digital_signalling);
+
+			if (lines) {
+				pcm_mask |= PCM_SHIFT(lines, i);
+				line_count += 2;
+			}
+			/* subunits have fake pcm_len and wanted_pcm_mask */
+			if (i > 0)
+				update_wanted_pcm_mask(sub_xpd, lines, 0);
+		}
+	}
+	/*
+	 * FIXME: Workaround a bug in sync code of the Astribank.
+	 *        Send dummy PCM for sync.
+	 */
+	if (main_xpd->addr.unit == 0 && line_count == 0) {
+		pcm_mask = BIT(0);
+		line_count = 1;
+	}
+	/*
+	 * The main unit account for all subunits (pcm_len and wanted_pcm_mask).
+	 */
+	pcm_len = (line_count)
+	    ? RPACKET_HEADERSIZE + sizeof(xpp_line_t) +
+	    line_count * DAHDI_CHUNKSIZE : 0L;
+	update_wanted_pcm_mask(main_xpd, pcm_mask, pcm_len);
+	spin_unlock_irqrestore(&PHONEDEV(main_xpd).lock_recompute_pcm, flags);
+}
+
+static void BRI_card_pcm_fromspan(xpd_t *xpd, xpacket_t *pack)
+{
+	__u8 *pcm;
+	unsigned long flags;
+	int i;
+	int subunit;
+	xpp_line_t pcm_mask = 0;
+	xpp_line_t wanted_lines;
+
+	BUG_ON(!xpd);
+	BUG_ON(!pack);
+	pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
+	for (subunit = 0; subunit < MAX_SUBUNIT; subunit++) {
+		xpd_t *tmp_xpd;
+
+		tmp_xpd = xpd_byaddr(xpd->xbus, xpd->addr.unit, subunit);
+		if (!tmp_xpd || !tmp_xpd->card_present)
+			continue;
+		spin_lock_irqsave(&tmp_xpd->lock, flags);
+		wanted_lines = PHONEDEV(tmp_xpd).wanted_pcm_mask;
+		for_each_line(tmp_xpd, i) {
+			struct dahdi_chan *chan = XPD_CHAN(tmp_xpd, i);
+
+			if (IS_SET(wanted_lines, i)) {
+				if (SPAN_REGISTERED(tmp_xpd)) {
+#ifdef	DEBUG_PCMTX
+					int channo = chan->channo;
+
+					if (pcmtx >= 0 && pcmtx_chan == channo)
+						memset((u_char *)pcm, pcmtx,
+						       DAHDI_CHUNKSIZE);
+					else
+#endif
+						memcpy((u_char *)pcm,
+						       chan->writechunk,
+						       DAHDI_CHUNKSIZE);
+				} else
+					memset((u_char *)pcm, 0x7F,
+					       DAHDI_CHUNKSIZE);
+				pcm += DAHDI_CHUNKSIZE;
+			}
+		}
+		pcm_mask |= PCM_SHIFT(wanted_lines, subunit);
+		XPD_COUNTER(tmp_xpd, PCM_WRITE)++;
+		spin_unlock_irqrestore(&tmp_xpd->lock, flags);
+	}
+	RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = pcm_mask;
+}
+
+static void BRI_card_pcm_tospan(xpd_t *xpd, xpacket_t *pack)
+{
+	__u8 *pcm;
+	xpp_line_t pcm_mask;
+	unsigned long flags;
+	int subunit;
+	int i;
+
+	/*
+	 * Subunit 0 handle all other subunits
+	 */
+	if (xpd->addr.subunit != 0)
+		return;
+	if (!SPAN_REGISTERED(xpd))
+		return;
+	pcm = RPACKET_FIELD(pack, GLOBAL, PCM_READ, pcm);
+	pcm_mask = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines);
+	for (subunit = 0; subunit < MAX_SUBUNIT;
+	     subunit++, pcm_mask >>= SUBUNIT_PCM_SHIFT) {
... 145082 lines suppressed ...


-- 
dahdi/linux.git



More information about the dahdi-commits mailing list